/* Minification failed. Returning unminified contents.
(1791,142-149): run-time error JS1019: Can't have 'break' outside of loop: break n
(1790,451-458): run-time error JS1019: Can't have 'break' outside of loop: break n
 */
/*! jQuery v3.3.1 | (c) JS Foundation and other contributors | jquery.org/license */
!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){"use strict";var n=[],r=e.document,i=Object.getPrototypeOf,o=n.slice,a=n.concat,s=n.push,u=n.indexOf,l={},c=l.toString,f=l.hasOwnProperty,p=f.toString,d=p.call(Object),h={},g=function e(t){return"function"==typeof t&&"number"!=typeof t.nodeType},y=function e(t){return null!=t&&t===t.window},v={type:!0,src:!0,noModule:!0};function m(e,t,n){var i,o=(t=t||r).createElement("script");if(o.text=e,n)for(i in v)n[i]&&(o[i]=n[i]);t.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[c.call(e)]||"object":typeof e}var b="3.3.1",w=function(e,t){return new w.fn.init(e,t)},T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;w.fn=w.prototype={jquery:"3.3.1",constructor:w,length:0,toArray:function(){return o.call(this)},get:function(e){return null==e?o.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=w.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return w.each(this,e)},map:function(e){return this.pushStack(w.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(o.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:s,sort:n.sort,splice:n.splice},w.extend=w.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||g(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)n=a[t],a!==(r=e[t])&&(l&&r&&(w.isPlainObject(r)||(i=Array.isArray(r)))?(i?(i=!1,o=n&&Array.isArray(n)?n:[]):o=n&&w.isPlainObject(n)?n:{},a[t]=w.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},w.extend({expando:"jQuery"+("3.3.1"+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==c.call(e))&&(!(t=i(e))||"function"==typeof(n=f.call(t,"constructor")&&t.constructor)&&p.call(n)===d)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e){m(e)},each:function(e,t){var n,r=0;if(C(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},trim:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(C(Object(e))?w.merge(n,"string"==typeof e?[e]:e):s.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:u.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r,i=[],o=0,a=e.length,s=!n;o<a;o++)(r=!t(e[o],o))!==s&&i.push(e[o]);return i},map:function(e,t,n){var r,i,o=0,s=[];if(C(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&s.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&s.push(i);return a.apply([],s)},guid:1,support:h}),"function"==typeof Symbol&&(w.fn[Symbol.iterator]=n[Symbol.iterator]),w.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function C(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!g(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e)}var E=function(e){var t,n,r,i,o,a,s,u,l,c,f,p,d,h,g,y,v,m,x,b="sizzle"+1*new Date,w=e.document,T=0,C=0,E=ae(),k=ae(),S=ae(),D=function(e,t){return e===t&&(f=!0),0},N={}.hasOwnProperty,A=[],j=A.pop,q=A.push,L=A.push,H=A.slice,O=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},P="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",I="\\["+M+"*("+R+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+R+"))|)"+M+"*\\]",W=":("+R+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+I+")*)|.*)\\)|)",$=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),F=new RegExp("^"+M+"*,"+M+"*"),_=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),z=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),X=new RegExp(W),U=new RegExp("^"+R+"$"),V={ID:new RegExp("^#("+R+")"),CLASS:new RegExp("^\\.("+R+")"),TAG:new RegExp("^("+R+"|[*])"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+W),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+P+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},G=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Q=/^[^{]+\{\s*\[native \w/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,K=/[+~]/,Z=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ee=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},te=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ne=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},re=function(){p()},ie=me(function(e){return!0===e.disabled&&("form"in e||"label"in e)},{dir:"parentNode",next:"legend"});try{L.apply(A=H.call(w.childNodes),w.childNodes),A[w.childNodes.length].nodeType}catch(e){L={apply:A.length?function(e,t){q.apply(e,H.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function oe(e,t,r,i){var o,s,l,c,f,h,v,m=t&&t.ownerDocument,T=t?t.nodeType:9;if(r=r||[],"string"!=typeof e||!e||1!==T&&9!==T&&11!==T)return r;if(!i&&((t?t.ownerDocument||t:w)!==d&&p(t),t=t||d,g)){if(11!==T&&(f=J.exec(e)))if(o=f[1]){if(9===T){if(!(l=t.getElementById(o)))return r;if(l.id===o)return r.push(l),r}else if(m&&(l=m.getElementById(o))&&x(t,l)&&l.id===o)return r.push(l),r}else{if(f[2])return L.apply(r,t.getElementsByTagName(e)),r;if((o=f[3])&&n.getElementsByClassName&&t.getElementsByClassName)return L.apply(r,t.getElementsByClassName(o)),r}if(n.qsa&&!S[e+" "]&&(!y||!y.test(e))){if(1!==T)m=t,v=e;else if("object"!==t.nodeName.toLowerCase()){(c=t.getAttribute("id"))?c=c.replace(te,ne):t.setAttribute("id",c=b),s=(h=a(e)).length;while(s--)h[s]="#"+c+" "+ve(h[s]);v=h.join(","),m=K.test(e)&&ge(t.parentNode)||t}if(v)try{return L.apply(r,m.querySelectorAll(v)),r}catch(e){}finally{c===b&&t.removeAttribute("id")}}}return u(e.replace(B,"$1"),t,r,i)}function ae(){var e=[];function t(n,i){return e.push(n+" ")>r.cacheLength&&delete t[e.shift()],t[n+" "]=i}return t}function se(e){return e[b]=!0,e}function ue(e){var t=d.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function le(e,t){var n=e.split("|"),i=n.length;while(i--)r.attrHandle[n[i]]=t}function ce(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function fe(e){return function(t){return"input"===t.nodeName.toLowerCase()&&t.type===e}}function pe(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function de(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&ie(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function he(e){return se(function(t){return t=+t,se(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function ge(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}n=oe.support={},o=oe.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},p=oe.setDocument=function(e){var t,i,a=e?e.ownerDocument||e:w;return a!==d&&9===a.nodeType&&a.documentElement?(d=a,h=d.documentElement,g=!o(d),w!==d&&(i=d.defaultView)&&i.top!==i&&(i.addEventListener?i.addEventListener("unload",re,!1):i.attachEvent&&i.attachEvent("onunload",re)),n.attributes=ue(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ue(function(e){return e.appendChild(d.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=Q.test(d.getElementsByClassName),n.getById=ue(function(e){return h.appendChild(e).id=b,!d.getElementsByName||!d.getElementsByName(b).length}),n.getById?(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){return e.getAttribute("id")===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n=t.getElementById(e);return n?[n]:[]}}):(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),r.find.TAG=n.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):n.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=n.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&g)return t.getElementsByClassName(e)},v=[],y=[],(n.qsa=Q.test(d.querySelectorAll))&&(ue(function(e){h.appendChild(e).innerHTML="<a id='"+b+"'></a><select id='"+b+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+P+")"),e.querySelectorAll("[id~="+b+"-]").length||y.push("~="),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+b+"+*").length||y.push(".#.+[+~]")}),ue(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=d.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),h.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(n.matchesSelector=Q.test(m=h.matches||h.webkitMatchesSelector||h.mozMatchesSelector||h.oMatchesSelector||h.msMatchesSelector))&&ue(function(e){n.disconnectedMatch=m.call(e,"*"),m.call(e,"[s!='']:x"),v.push("!=",W)}),y=y.length&&new RegExp(y.join("|")),v=v.length&&new RegExp(v.join("|")),t=Q.test(h.compareDocumentPosition),x=t||Q.test(h.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return f=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r||(1&(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!n.sortDetached&&t.compareDocumentPosition(e)===r?e===d||e.ownerDocument===w&&x(w,e)?-1:t===d||t.ownerDocument===w&&x(w,t)?1:c?O(c,e)-O(c,t):0:4&r?-1:1)}:function(e,t){if(e===t)return f=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===d?-1:t===d?1:i?-1:o?1:c?O(c,e)-O(c,t):0;if(i===o)return ce(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?ce(a[r],s[r]):a[r]===w?-1:s[r]===w?1:0},d):d},oe.matches=function(e,t){return oe(e,null,null,t)},oe.matchesSelector=function(e,t){if((e.ownerDocument||e)!==d&&p(e),t=t.replace(z,"='$1']"),n.matchesSelector&&g&&!S[t+" "]&&(!v||!v.test(t))&&(!y||!y.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){}return oe(t,d,null,[e]).length>0},oe.contains=function(e,t){return(e.ownerDocument||e)!==d&&p(e),x(e,t)},oe.attr=function(e,t){(e.ownerDocument||e)!==d&&p(e);var i=r.attrHandle[t.toLowerCase()],o=i&&N.call(r.attrHandle,t.toLowerCase())?i(e,t,!g):void 0;return void 0!==o?o:n.attributes||!g?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null},oe.escape=function(e){return(e+"").replace(te,ne)},oe.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},oe.uniqueSort=function(e){var t,r=[],i=0,o=0;if(f=!n.detectDuplicates,c=!n.sortStable&&e.slice(0),e.sort(D),f){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return c=null,e},i=oe.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=i(e)}else if(3===o||4===o)return e.nodeValue}else while(t=e[r++])n+=i(t);return n},(r=oe.selectors={cacheLength:50,createPseudo:se,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(Z,ee),e[3]=(e[3]||e[4]||e[5]||"").replace(Z,ee),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||oe.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&oe.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return V.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=a(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(Z,ee).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=E[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&E(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=oe.attr(r,e);return null==i?"!="===t:!t||(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i.replace($," ")+" ").indexOf(n)>-1:"|="===t&&(i===n||i.slice(0,n.length+1)===n+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,d,h,g=o!==a?"nextSibling":"previousSibling",y=t.parentNode,v=s&&t.nodeName.toLowerCase(),m=!u&&!s,x=!1;if(y){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===v:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?y.firstChild:y.lastChild],a&&m){x=(d=(l=(c=(f=(p=y)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1])&&l[2],p=d&&y.childNodes[d];while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if(1===p.nodeType&&++x&&p===t){c[e]=[T,d,x];break}}else if(m&&(x=d=(l=(c=(f=(p=t)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1]),!1===x)while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===v:1===p.nodeType)&&++x&&(m&&((c=(f=p[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]=[T,x]),p===t))break;return(x-=i)===r||x%r==0&&x/r>=0}}},PSEUDO:function(e,t){var n,i=r.pseudos[e]||r.setFilters[e.toLowerCase()]||oe.error("unsupported pseudo: "+e);return i[b]?i(t):i.length>1?(n=[e,e,"",t],r.setFilters.hasOwnProperty(e.toLowerCase())?se(function(e,n){var r,o=i(e,t),a=o.length;while(a--)e[r=O(e,o[a])]=!(n[r]=o[a])}):function(e){return i(e,0,n)}):i}},pseudos:{not:se(function(e){var t=[],n=[],r=s(e.replace(B,"$1"));return r[b]?se(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),t[0]=null,!n.pop()}}),has:se(function(e){return function(t){return oe(e,t).length>0}}),contains:se(function(e){return e=e.replace(Z,ee),function(t){return(t.textContent||t.innerText||i(t)).indexOf(e)>-1}}),lang:se(function(e){return U.test(e||"")||oe.error("unsupported lang: "+e),e=e.replace(Z,ee).toLowerCase(),function(t){var n;do{if(n=g?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(n=n.toLowerCase())===e||0===n.indexOf(e+"-")}while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===h},focus:function(e){return e===d.activeElement&&(!d.hasFocus||d.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:de(!1),disabled:de(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!r.pseudos.empty(e)},header:function(e){return Y.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:he(function(){return[0]}),last:he(function(e,t){return[t-1]}),eq:he(function(e,t,n){return[n<0?n+t:n]}),even:he(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:he(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:he(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:he(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=r.pseudos.eq;for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})r.pseudos[t]=fe(t);for(t in{submit:!0,reset:!0})r.pseudos[t]=pe(t);function ye(){}ye.prototype=r.filters=r.pseudos,r.setFilters=new ye,a=oe.tokenize=function(e,t){var n,i,o,a,s,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=r.preFilter;while(s){n&&!(i=F.exec(s))||(i&&(s=s.slice(i[0].length)||s),u.push(o=[])),n=!1,(i=_.exec(s))&&(n=i.shift(),o.push({value:n,type:i[0].replace(B," ")}),s=s.slice(n.length));for(a in r.filter)!(i=V[a].exec(s))||l[a]&&!(i=l[a](i))||(n=i.shift(),o.push({value:n,type:a,matches:i}),s=s.slice(n.length));if(!n)break}return t?s.length:s?oe.error(e):k(e,u).slice(0)};function ve(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function me(e,t,n){var r=t.dir,i=t.next,o=i||r,a=n&&"parentNode"===o,s=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||a)return e(t,n,i);return!1}:function(t,n,u){var l,c,f,p=[T,s];if(u){while(t=t[r])if((1===t.nodeType||a)&&e(t,n,u))return!0}else while(t=t[r])if(1===t.nodeType||a)if(f=t[b]||(t[b]={}),c=f[t.uniqueID]||(f[t.uniqueID]={}),i&&i===t.nodeName.toLowerCase())t=t[r]||t;else{if((l=c[o])&&l[0]===T&&l[1]===s)return p[2]=l[2];if(c[o]=p,p[2]=e(t,n,u))return!0}return!1}}function xe(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function be(e,t,n){for(var r=0,i=t.length;r<i;r++)oe(e,t[r],n);return n}function we(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Te(e,t,n,r,i,o){return r&&!r[b]&&(r=Te(r)),i&&!i[b]&&(i=Te(i,o)),se(function(o,a,s,u){var l,c,f,p=[],d=[],h=a.length,g=o||be(t||"*",s.nodeType?[s]:s,[]),y=!e||!o&&t?g:we(g,p,e,s,u),v=n?i||(o?e:h||r)?[]:a:y;if(n&&n(y,v,s,u),r){l=we(v,d),r(l,[],s,u),c=l.length;while(c--)(f=l[c])&&(v[d[c]]=!(y[d[c]]=f))}if(o){if(i||e){if(i){l=[],c=v.length;while(c--)(f=v[c])&&l.push(y[c]=f);i(null,v=[],l,u)}c=v.length;while(c--)(f=v[c])&&(l=i?O(o,f):p[c])>-1&&(o[l]=!(a[l]=f))}}else v=we(v===a?v.splice(h,v.length):v),i?i(null,a,v,u):L.apply(a,v)})}function Ce(e){for(var t,n,i,o=e.length,a=r.relative[e[0].type],s=a||r.relative[" "],u=a?1:0,c=me(function(e){return e===t},s,!0),f=me(function(e){return O(t,e)>-1},s,!0),p=[function(e,n,r){var i=!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):f(e,n,r));return t=null,i}];u<o;u++)if(n=r.relative[e[u].type])p=[me(xe(p),n)];else{if((n=r.filter[e[u].type].apply(null,e[u].matches))[b]){for(i=++u;i<o;i++)if(r.relative[e[i].type])break;return Te(u>1&&xe(p),u>1&&ve(e.slice(0,u-1).concat({value:" "===e[u-2].type?"*":""})).replace(B,"$1"),n,u<i&&Ce(e.slice(u,i)),i<o&&Ce(e=e.slice(i)),i<o&&ve(e))}p.push(n)}return xe(p)}function Ee(e,t){var n=t.length>0,i=e.length>0,o=function(o,a,s,u,c){var f,h,y,v=0,m="0",x=o&&[],b=[],w=l,C=o||i&&r.find.TAG("*",c),E=T+=null==w?1:Math.random()||.1,k=C.length;for(c&&(l=a===d||a||c);m!==k&&null!=(f=C[m]);m++){if(i&&f){h=0,a||f.ownerDocument===d||(p(f),s=!g);while(y=e[h++])if(y(f,a||d,s)){u.push(f);break}c&&(T=E)}n&&((f=!y&&f)&&v--,o&&x.push(f))}if(v+=m,n&&m!==v){h=0;while(y=t[h++])y(x,b,a,s);if(o){if(v>0)while(m--)x[m]||b[m]||(b[m]=j.call(u));b=we(b)}L.apply(u,b),c&&!o&&b.length>0&&v+t.length>1&&oe.uniqueSort(u)}return c&&(T=E,l=w),x};return n?se(o):o}return s=oe.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=a(e)),n=t.length;while(n--)(o=Ce(t[n]))[b]?r.push(o):i.push(o);(o=S(e,Ee(i,r))).selector=e}return o},u=oe.select=function(e,t,n,i){var o,u,l,c,f,p="function"==typeof e&&e,d=!i&&a(e=p.selector||e);if(n=n||[],1===d.length){if((u=d[0]=d[0].slice(0)).length>2&&"ID"===(l=u[0]).type&&9===t.nodeType&&g&&r.relative[u[1].type]){if(!(t=(r.find.ID(l.matches[0].replace(Z,ee),t)||[])[0]))return n;p&&(t=t.parentNode),e=e.slice(u.shift().value.length)}o=V.needsContext.test(e)?0:u.length;while(o--){if(l=u[o],r.relative[c=l.type])break;if((f=r.find[c])&&(i=f(l.matches[0].replace(Z,ee),K.test(u[0].type)&&ge(t.parentNode)||t))){if(u.splice(o,1),!(e=i.length&&ve(u)))return L.apply(n,i),n;break}}}return(p||s(e,d))(i,t,!g,n,!t||K.test(e)&&ge(t.parentNode)||t),n},n.sortStable=b.split("").sort(D).join("")===b,n.detectDuplicates=!!f,p(),n.sortDetached=ue(function(e){return 1&e.compareDocumentPosition(d.createElement("fieldset"))}),ue(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||le("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ue(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||le("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ue(function(e){return null==e.getAttribute("disabled")})||le(P,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),oe}(e);w.find=E,w.expr=E.selectors,w.expr[":"]=w.expr.pseudos,w.uniqueSort=w.unique=E.uniqueSort,w.text=E.getText,w.isXMLDoc=E.isXML,w.contains=E.contains,w.escapeSelector=E.escape;var k=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&w(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},D=w.expr.match.needsContext;function N(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var A=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,t,n){return g(t)?w.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?w.grep(e,function(e){return e===t!==n}):"string"!=typeof t?w.grep(e,function(e){return u.call(t,e)>-1!==n}):w.filter(t,e,n)}w.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?w.find.matchesSelector(r,e)?[r]:[]:w.find.matches(e,w.grep(t,function(e){return 1===e.nodeType}))},w.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(w(e).filter(function(){for(t=0;t<r;t++)if(w.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)w.find(e,i[t],n);return r>1?w.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&D.test(e)?w(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(w.fn.init=function(e,t,n){var i,o;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(i="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:L.exec(e))||!i[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(i[1]){if(t=t instanceof w?t[0]:t,w.merge(this,w.parseHTML(i[1],t&&t.nodeType?t.ownerDocument||t:r,!0)),A.test(i[1])&&w.isPlainObject(t))for(i in t)g(this[i])?this[i](t[i]):this.attr(i,t[i]);return this}return(o=r.getElementById(i[2]))&&(this[0]=o,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):g(e)?void 0!==n.ready?n.ready(e):e(w):w.makeArray(e,this)}).prototype=w.fn,q=w(r);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};w.fn.extend({has:function(e){var t=w(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(w.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&w(e);if(!D.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?a.index(n)>-1:1===n.nodeType&&w.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?w.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?u.call(w(e),this[0]):u.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(w.uniqueSort(w.merge(this.get(),w(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}w.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return k(e,"parentNode")},parentsUntil:function(e,t,n){return k(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return k(e,"nextSibling")},prevAll:function(e){return k(e,"previousSibling")},nextUntil:function(e,t,n){return k(e,"nextSibling",n)},prevUntil:function(e,t,n){return k(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return N(e,"iframe")?e.contentDocument:(N(e,"template")&&(e=e.content||e),w.merge([],e.childNodes))}},function(e,t){w.fn[e]=function(n,r){var i=w.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=w.filter(r,i)),this.length>1&&(O[e]||w.uniqueSort(i),H.test(e)&&i.reverse()),this.pushStack(i)}});var M=/[^\x20\t\r\n\f]+/g;function R(e){var t={};return w.each(e.match(M)||[],function(e,n){t[n]=!0}),t}w.Callbacks=function(e){e="string"==typeof e?R(e):w.extend({},e);var t,n,r,i,o=[],a=[],s=-1,u=function(){for(i=i||e.once,r=t=!0;a.length;s=-1){n=a.shift();while(++s<o.length)!1===o[s].apply(n[0],n[1])&&e.stopOnFalse&&(s=o.length,n=!1)}e.memory||(n=!1),t=!1,i&&(o=n?[]:"")},l={add:function(){return o&&(n&&!t&&(s=o.length-1,a.push(n)),function t(n){w.each(n,function(n,r){g(r)?e.unique&&l.has(r)||o.push(r):r&&r.length&&"string"!==x(r)&&t(r)})}(arguments),n&&!t&&u()),this},remove:function(){return w.each(arguments,function(e,t){var n;while((n=w.inArray(t,o,n))>-1)o.splice(n,1),n<=s&&s--}),this},has:function(e){return e?w.inArray(e,o)>-1:o.length>0},empty:function(){return o&&(o=[]),this},disable:function(){return i=a=[],o=n="",this},disabled:function(){return!o},lock:function(){return i=a=[],n||t||(o=n=""),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=[e,(n=n||[]).slice?n.slice():n],a.push(n),t||u()),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!r}};return l};function I(e){return e}function W(e){throw e}function $(e,t,n,r){var i;try{e&&g(i=e.promise)?i.call(e).done(t).fail(n):e&&g(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}w.extend({Deferred:function(t){var n=[["notify","progress",w.Callbacks("memory"),w.Callbacks("memory"),2],["resolve","done",w.Callbacks("once memory"),w.Callbacks("once memory"),0,"resolved"],["reject","fail",w.Callbacks("once memory"),w.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},"catch":function(e){return i.then(null,e)},pipe:function(){var e=arguments;return w.Deferred(function(t){w.each(n,function(n,r){var i=g(e[r[4]])&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&g(e.promise)?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(t,r,i){var o=0;function a(t,n,r,i){return function(){var s=this,u=arguments,l=function(){var e,l;if(!(t<o)){if((e=r.apply(s,u))===n.promise())throw new TypeError("Thenable self-resolution");l=e&&("object"==typeof e||"function"==typeof e)&&e.then,g(l)?i?l.call(e,a(o,n,I,i),a(o,n,W,i)):(o++,l.call(e,a(o,n,I,i),a(o,n,W,i),a(o,n,I,n.notifyWith))):(r!==I&&(s=void 0,u=[e]),(i||n.resolveWith)(s,u))}},c=i?l:function(){try{l()}catch(e){w.Deferred.exceptionHook&&w.Deferred.exceptionHook(e,c.stackTrace),t+1>=o&&(r!==W&&(s=void 0,u=[e]),n.rejectWith(s,u))}};t?c():(w.Deferred.getStackHook&&(c.stackTrace=w.Deferred.getStackHook()),e.setTimeout(c))}}return w.Deferred(function(e){n[0][3].add(a(0,e,g(i)?i:I,e.notifyWith)),n[1][3].add(a(0,e,g(t)?t:I)),n[2][3].add(a(0,e,g(r)?r:W))}).promise()},promise:function(e){return null!=e?w.extend(e,i):i}},o={};return w.each(n,function(e,t){var a=t[2],s=t[5];i[t[1]]=a.add,s&&a.add(function(){r=s},n[3-e][2].disable,n[3-e][3].disable,n[0][2].lock,n[0][3].lock),a.add(t[3].fire),o[t[0]]=function(){return o[t[0]+"With"](this===o?void 0:this,arguments),this},o[t[0]+"With"]=a.fireWith}),i.promise(o),t&&t.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),i=o.call(arguments),a=w.Deferred(),s=function(e){return function(n){r[e]=this,i[e]=arguments.length>1?o.call(arguments):n,--t||a.resolveWith(r,i)}};if(t<=1&&($(e,a.done(s(n)).resolve,a.reject,!t),"pending"===a.state()||g(i[n]&&i[n].then)))return a.then();while(n--)$(i[n],s(n),a.reject);return a.promise()}});var B=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;w.Deferred.exceptionHook=function(t,n){e.console&&e.console.warn&&t&&B.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,n)},w.readyException=function(t){e.setTimeout(function(){throw t})};var F=w.Deferred();w.fn.ready=function(e){return F.then(e)["catch"](function(e){w.readyException(e)}),this},w.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--w.readyWait:w.isReady)||(w.isReady=!0,!0!==e&&--w.readyWait>0||F.resolveWith(r,[w]))}}),w.ready.then=F.then;function _(){r.removeEventListener("DOMContentLoaded",_),e.removeEventListener("load",_),w.ready()}"complete"===r.readyState||"loading"!==r.readyState&&!r.documentElement.doScroll?e.setTimeout(w.ready):(r.addEventListener("DOMContentLoaded",_),e.addEventListener("load",_));var z=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===x(n)){i=!0;for(s in n)z(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,g(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(w(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},X=/^-ms-/,U=/-([a-z])/g;function V(e,t){return t.toUpperCase()}function G(e){return e.replace(X,"ms-").replace(U,V)}var Y=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function Q(){this.expando=w.expando+Q.uid++}Q.uid=1,Q.prototype={cache:function(e){var t=e[this.expando];return t||(t={},Y(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[G(t)]=n;else for(r in t)i[G(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][G(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(G):(t=G(t))in r?[t]:t.match(M)||[]).length;while(n--)delete r[t[n]]}(void 0===t||w.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!w.isEmptyObject(t)}};var J=new Q,K=new Q,Z=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,ee=/[A-Z]/g;function te(e){return"true"===e||"false"!==e&&("null"===e?null:e===+e+""?+e:Z.test(e)?JSON.parse(e):e)}function ne(e,t,n){var r;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(ee,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n=te(n)}catch(e){}K.set(e,t,n)}else n=void 0;return n}w.extend({hasData:function(e){return K.hasData(e)||J.hasData(e)},data:function(e,t,n){return K.access(e,t,n)},removeData:function(e,t){K.remove(e,t)},_data:function(e,t,n){return J.access(e,t,n)},_removeData:function(e,t){J.remove(e,t)}}),w.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=K.get(o),1===o.nodeType&&!J.get(o,"hasDataAttrs"))){n=a.length;while(n--)a[n]&&0===(r=a[n].name).indexOf("data-")&&(r=G(r.slice(5)),ne(o,r,i[r]));J.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof e?this.each(function(){K.set(this,e)}):z(this,function(t){var n;if(o&&void 0===t){if(void 0!==(n=K.get(o,e)))return n;if(void 0!==(n=ne(o,e)))return n}else this.each(function(){K.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){K.remove(this,e)})}}),w.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=J.get(e,t),n&&(!r||Array.isArray(n)?r=J.access(e,t,w.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=w.queue(e,t),r=n.length,i=n.shift(),o=w._queueHooks(e,t),a=function(){w.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return J.get(e,n)||J.access(e,n,{empty:w.Callbacks("once memory").add(function(){J.remove(e,[t+"queue",n])})})}}),w.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length<n?w.queue(this[0],e):void 0===t?this:this.each(function(){var n=w.queue(this,e,t);w._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&w.dequeue(this,e)})},dequeue:function(e){return this.each(function(){w.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=w.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=J.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var re=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ie=new RegExp("^(?:([+-])=|)("+re+")([a-z%]*)$","i"),oe=["Top","Right","Bottom","Left"],ae=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&w.contains(e.ownerDocument,e)&&"none"===w.css(e,"display")},se=function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i};function ue(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return w.css(e,t,"")},u=s(),l=n&&n[3]||(w.cssNumber[t]?"":"px"),c=(w.cssNumber[t]||"px"!==l&&+u)&&ie.exec(w.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)w.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,w.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var le={};function ce(e){var t,n=e.ownerDocument,r=e.nodeName,i=le[r];return i||(t=n.body.appendChild(n.createElement(r)),i=w.css(t,"display"),t.parentNode.removeChild(t),"none"===i&&(i="block"),le[r]=i,i)}function fe(e,t){for(var n,r,i=[],o=0,a=e.length;o<a;o++)(r=e[o]).style&&(n=r.style.display,t?("none"===n&&(i[o]=J.get(r,"display")||null,i[o]||(r.style.display="")),""===r.style.display&&ae(r)&&(i[o]=ce(r))):"none"!==n&&(i[o]="none",J.set(r,"display",n)));for(o=0;o<a;o++)null!=i[o]&&(e[o].style.display=i[o]);return e}w.fn.extend({show:function(){return fe(this,!0)},hide:function(){return fe(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){ae(this)?w(this).show():w(this).hide()})}});var pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]+)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&N(e,t)?w.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n<r;n++)J.set(e[n],"globalEval",!t||J.get(t[n],"globalEval"))}var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===x(o))w.merge(p,o.nodeType?[o]:o);else if(me.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+w.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;w.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&w.inArray(o,r)>-1)i&&i.push(o);else if(l=w.contains(o.ownerDocument,o),a=ye(f.appendChild(o),"script"),l&&ve(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}!function(){var e=r.createDocumentFragment().appendChild(r.createElement("div")),t=r.createElement("input");t.setAttribute("type","radio"),t.setAttribute("checked","checked"),t.setAttribute("name","t"),e.appendChild(t),h.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,e.innerHTML="<textarea>x</textarea>",h.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue}();var be=r.documentElement,we=/^key/,Te=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ce=/^([^.]*)(?:\.(.+)|)/;function Ee(){return!0}function ke(){return!1}function Se(){try{return r.activeElement}catch(e){}}function De(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)De(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=ke;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return w().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=w.guid++)),e.each(function(){w.event.add(this,t,i,r,n)})}w.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.get(e);if(y){n.handler&&(n=(o=n).handler,i=o.selector),i&&w.find.matchesSelector(be,i),n.guid||(n.guid=w.guid++),(u=y.events)||(u=y.events={}),(a=y.handle)||(a=y.handle=function(t){return"undefined"!=typeof w&&w.event.triggered!==t.type?w.event.dispatch.apply(e,arguments):void 0}),l=(t=(t||"").match(M)||[""]).length;while(l--)d=g=(s=Ce.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=w.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=w.event.special[d]||{},c=w.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&w.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(e,r,h,a)||e.addEventListener&&e.addEventListener(d,a)),f.add&&(f.add.call(e,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),w.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.hasData(e)&&J.get(e);if(y&&(u=y.events)){l=(t=(t||"").match(M)||[""]).length;while(l--)if(s=Ce.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){f=w.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,y.handle)||w.removeEvent(e,d,y.handle),delete u[d])}else for(d in u)w.event.remove(e,d+t[l],n,r,!0);w.isEmptyObject(u)&&J.remove(e,"handle events")}},dispatch:function(e){var t=w.event.fix(e),n,r,i,o,a,s,u=new Array(arguments.length),l=(J.get(this,"events")||{})[t.type]||[],c=w.event.special[t.type]||{};for(u[0]=t,n=1;n<arguments.length;n++)u[n]=arguments[n];if(t.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,t)){s=w.event.handlers.call(this,t,l),n=0;while((o=s[n++])&&!t.isPropagationStopped()){t.currentTarget=o.elem,r=0;while((a=o.handlers[r++])&&!t.isImmediatePropagationStopped())t.rnamespace&&!t.rnamespace.test(a.namespace)||(t.handleObj=a,t.data=a.data,void 0!==(i=((w.event.special[a.origType]||{}).handle||a.handler).apply(o.elem,u))&&!1===(t.result=i)&&(t.preventDefault(),t.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,t),t.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&e.button>=1))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?w(i,this).index(l)>-1:w.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(e,t){Object.defineProperty(w.Event.prototype,e,{enumerable:!0,configurable:!0,get:g(t)?function(){if(this.originalEvent)return t(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[e]},set:function(t){Object.defineProperty(this,e,{enumerable:!0,configurable:!0,writable:!0,value:t})}})},fix:function(e){return e[w.expando]?e:new w.Event(e)},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==Se()&&this.focus)return this.focus(),!1},delegateType:"focusin"},blur:{trigger:function(){if(this===Se()&&this.blur)return this.blur(),!1},delegateType:"focusout"},click:{trigger:function(){if("checkbox"===this.type&&this.click&&N(this,"input"))return this.click(),!1},_default:function(e){return N(e.target,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},w.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},w.Event=function(e,t){if(!(this instanceof w.Event))return new w.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?Ee:ke,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&w.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[w.expando]=!0},w.Event.prototype={constructor:w.Event,isDefaultPrevented:ke,isPropagationStopped:ke,isImmediatePropagationStopped:ke,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=Ee,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=Ee,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=Ee,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},w.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&we.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&Te.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},w.event.addProp),w.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,t){w.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return i&&(i===r||w.contains(r,i))||(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),w.fn.extend({on:function(e,t,n,r){return De(this,e,t,n,r)},one:function(e,t,n,r){return De(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,w(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=ke),this.each(function(){w.event.remove(this,e,n,t)})}});var Ne=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,Ae=/<script|<style|<link/i,je=/checked\s*(?:[^=]|=\s*.checked.)/i,qe=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Le(e,t){return N(e,"table")&&N(11!==t.nodeType?t:t.firstChild,"tr")?w(e).children("tbody")[0]||e:e}function He(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Oe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Pe(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(J.hasData(e)&&(o=J.access(e),a=J.set(t,o),l=o.events)){delete a.handle,a.events={};for(i in l)for(n=0,r=l[i].length;n<r;n++)w.event.add(t,i,l[i][n])}K.hasData(e)&&(s=K.access(e),u=w.extend({},s),K.set(t,u))}}function Me(e,t){var n=t.nodeName.toLowerCase();"input"===n&&pe.test(e.type)?t.checked=e.checked:"input"!==n&&"textarea"!==n||(t.defaultValue=e.defaultValue)}function Re(e,t,n,r){t=a.apply([],t);var i,o,s,u,l,c,f=0,p=e.length,d=p-1,y=t[0],v=g(y);if(v||p>1&&"string"==typeof y&&!h.checkClone&&je.test(y))return e.each(function(i){var o=e.eq(i);v&&(t[0]=y.call(this,i,o.html())),Re(o,t,n,r)});if(p&&(i=xe(t,e[0].ownerDocument,!1,e,r),o=i.firstChild,1===i.childNodes.length&&(i=o),o||r)){for(u=(s=w.map(ye(i,"script"),He)).length;f<p;f++)l=i,f!==d&&(l=w.clone(l,!0,!0),u&&w.merge(s,ye(l,"script"))),n.call(e[f],l,f);if(u)for(c=s[s.length-1].ownerDocument,w.map(s,Oe),f=0;f<u;f++)l=s[f],he.test(l.type||"")&&!J.access(l,"globalEval")&&w.contains(c,l)&&(l.src&&"module"!==(l.type||"").toLowerCase()?w._evalUrl&&w._evalUrl(l.src):m(l.textContent.replace(qe,""),c,l))}return e}function Ie(e,t,n){for(var r,i=t?w.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||w.cleanData(ye(r)),r.parentNode&&(n&&w.contains(r.ownerDocument,r)&&ve(ye(r,"script")),r.parentNode.removeChild(r));return e}w.extend({htmlPrefilter:function(e){return e.replace(Ne,"<$1></$2>")},clone:function(e,t,n){var r,i,o,a,s=e.cloneNode(!0),u=w.contains(e.ownerDocument,e);if(!(h.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||w.isXMLDoc(e)))for(a=ye(s),r=0,i=(o=ye(e)).length;r<i;r++)Me(o[r],a[r]);if(t)if(n)for(o=o||ye(e),a=a||ye(s),r=0,i=o.length;r<i;r++)Pe(o[r],a[r]);else Pe(e,s);return(a=ye(s,"script")).length>0&&ve(a,!u&&ye(e,"script")),s},cleanData:function(e){for(var t,n,r,i=w.event.special,o=0;void 0!==(n=e[o]);o++)if(Y(n)){if(t=n[J.expando]){if(t.events)for(r in t.events)i[r]?w.event.remove(n,r):w.removeEvent(n,r,t.handle);n[J.expando]=void 0}n[K.expando]&&(n[K.expando]=void 0)}}}),w.fn.extend({detach:function(e){return Ie(this,e,!0)},remove:function(e){return Ie(this,e)},text:function(e){return z(this,function(e){return void 0===e?w.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Re(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Le(this,e).appendChild(e)})},prepend:function(){return Re(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Le(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(w.cleanData(ye(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return w.clone(this,e,t)})},html:function(e){return z(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Ae.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=w.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(w.cleanData(ye(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=[];return Re(this,arguments,function(t){var n=this.parentNode;w.inArray(this,e)<0&&(w.cleanData(ye(this)),n&&n.replaceChild(t,this))},e)}}),w.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){w.fn[e]=function(e){for(var n,r=[],i=w(e),o=i.length-1,a=0;a<=o;a++)n=a===o?this:this.clone(!0),w(i[a])[t](n),s.apply(r,n.get());return this.pushStack(r)}});var We=new RegExp("^("+re+")(?!px)[a-z%]+$","i"),$e=function(t){var n=t.ownerDocument.defaultView;return n&&n.opener||(n=e),n.getComputedStyle(t)},Be=new RegExp(oe.join("|"),"i");!function(){function t(){if(c){l.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",c.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",be.appendChild(l).appendChild(c);var t=e.getComputedStyle(c);i="1%"!==t.top,u=12===n(t.marginLeft),c.style.right="60%",s=36===n(t.right),o=36===n(t.width),c.style.position="absolute",a=36===c.offsetWidth||"absolute",be.removeChild(l),c=null}}function n(e){return Math.round(parseFloat(e))}var i,o,a,s,u,l=r.createElement("div"),c=r.createElement("div");c.style&&(c.style.backgroundClip="content-box",c.cloneNode(!0).style.backgroundClip="",h.clearCloneStyle="content-box"===c.style.backgroundClip,w.extend(h,{boxSizingReliable:function(){return t(),o},pixelBoxStyles:function(){return t(),s},pixelPosition:function(){return t(),i},reliableMarginLeft:function(){return t(),u},scrollboxSize:function(){return t(),a}}))}();function Fe(e,t,n){var r,i,o,a,s=e.style;return(n=n||$e(e))&&(""!==(a=n.getPropertyValue(t)||n[t])||w.contains(e.ownerDocument,e)||(a=w.style(e,t)),!h.pixelBoxStyles()&&We.test(a)&&Be.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+"":a}function _e(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}var ze=/^(none|table(?!-c[ea]).+)/,Xe=/^--/,Ue={position:"absolute",visibility:"hidden",display:"block"},Ve={letterSpacing:"0",fontWeight:"400"},Ge=["Webkit","Moz","ms"],Ye=r.createElement("div").style;function Qe(e){if(e in Ye)return e;var t=e[0].toUpperCase()+e.slice(1),n=Ge.length;while(n--)if((e=Ge[n]+t)in Ye)return e}function Je(e){var t=w.cssProps[e];return t||(t=w.cssProps[e]=Qe(e)||e),t}function Ke(e,t,n){var r=ie.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function Ze(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=w.css(e,n+oe[a],!0,i)),r?("content"===n&&(u-=w.css(e,"padding"+oe[a],!0,i)),"margin"!==n&&(u-=w.css(e,"border"+oe[a]+"Width",!0,i))):(u+=w.css(e,"padding"+oe[a],!0,i),"padding"!==n?u+=w.css(e,"border"+oe[a]+"Width",!0,i):s+=w.css(e,"border"+oe[a]+"Width",!0,i));return!r&&o>=0&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))),u}function et(e,t,n){var r=$e(e),i=Fe(e,t,r),o="border-box"===w.css(e,"boxSizing",!1,r),a=o;if(We.test(i)){if(!n)return i;i="auto"}return a=a&&(h.boxSizingReliable()||i===e.style[t]),("auto"===i||!parseFloat(i)&&"inline"===w.css(e,"display",!1,r))&&(i=e["offset"+t[0].toUpperCase()+t.slice(1)],a=!0),(i=parseFloat(i)||0)+Ze(e,t,n||(o?"border":"content"),a,r,i)+"px"}w.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Fe(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=G(t),u=Xe.test(t),l=e.style;if(u||(t=Je(s)),a=w.cssHooks[t]||w.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"==(o=typeof n)&&(i=ie.exec(n))&&i[1]&&(n=ue(e,t,i),o="number"),null!=n&&n===n&&("number"===o&&(n+=i&&i[3]||(w.cssNumber[s]?"":"px")),h.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=G(t);return Xe.test(t)||(t=Je(s)),(a=w.cssHooks[t]||w.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Fe(e,t,r)),"normal"===i&&t in Ve&&(i=Ve[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),w.each(["height","width"],function(e,t){w.cssHooks[t]={get:function(e,n,r){if(n)return!ze.test(w.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?et(e,t,r):se(e,Ue,function(){return et(e,t,r)})},set:function(e,n,r){var i,o=$e(e),a="border-box"===w.css(e,"boxSizing",!1,o),s=r&&Ze(e,t,r,a,o);return a&&h.scrollboxSize()===o.position&&(s-=Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-parseFloat(o[t])-Ze(e,t,"border",!1,o)-.5)),s&&(i=ie.exec(n))&&"px"!==(i[3]||"px")&&(e.style[t]=n,n=w.css(e,t)),Ke(e,n,s)}}}),w.cssHooks.marginLeft=_e(h.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Fe(e,"marginLeft"))||e.getBoundingClientRect().left-se(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),w.each({margin:"",padding:"",border:"Width"},function(e,t){w.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+oe[r]+t]=o[r]||o[r-2]||o[0];return i}},"margin"!==e&&(w.cssHooks[e+t].set=Ke)}),w.fn.extend({css:function(e,t){return z(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=$e(e),i=t.length;a<i;a++)o[t[a]]=w.css(e,t[a],!1,r);return o}return void 0!==n?w.style(e,t,n):w.css(e,t)},e,t,arguments.length>1)}});function tt(e,t,n,r,i){return new tt.prototype.init(e,t,n,r,i)}w.Tween=tt,tt.prototype={constructor:tt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||w.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(w.cssNumber[n]?"":"px")},cur:function(){var e=tt.propHooks[this.prop];return e&&e.get?e.get(this):tt.propHooks._default.get(this)},run:function(e){var t,n=tt.propHooks[this.prop];return this.options.duration?this.pos=t=w.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):tt.propHooks._default.set(this),this}},tt.prototype.init.prototype=tt.prototype,tt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=w.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){w.fx.step[e.prop]?w.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[w.cssProps[e.prop]]&&!w.cssHooks[e.prop]?e.elem[e.prop]=e.now:w.style(e.elem,e.prop,e.now+e.unit)}}},tt.propHooks.scrollTop=tt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},w.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},w.fx=tt.prototype.init,w.fx.step={};var nt,rt,it=/^(?:toggle|show|hide)$/,ot=/queueHooks$/;function at(){rt&&(!1===r.hidden&&e.requestAnimationFrame?e.requestAnimationFrame(at):e.setTimeout(at,w.fx.interval),w.fx.tick())}function st(){return e.setTimeout(function(){nt=void 0}),nt=Date.now()}function ut(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=oe[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function lt(e,t,n){for(var r,i=(pt.tweeners[t]||[]).concat(pt.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function ct(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&ae(e),y=J.get(e,"fxshow");n.queue||(null==(a=w._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,w.queue(e,"fx").length||a.empty.fire()})}));for(r in t)if(i=t[r],it.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!y||void 0===y[r])continue;g=!0}d[r]=y&&y[r]||w.style(e,r)}if((u=!w.isEmptyObject(t))||!w.isEmptyObject(d)){f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=y&&y.display)&&(l=J.get(e,"display")),"none"===(c=w.css(e,"display"))&&(l?c=l:(fe([e],!0),l=e.style.display||l,c=w.css(e,"display"),fe([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===w.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1;for(r in d)u||(y?"hidden"in y&&(g=y.hidden):y=J.access(e,"fxshow",{display:l}),o&&(y.hidden=!g),g&&fe([e],!0),p.done(function(){g||fe([e]),J.remove(e,"fxshow");for(r in d)w.style(e,r,d[r])})),u=lt(g?y[r]:0,r,p),r in y||(y[r]=u.start,g&&(u.end=u.start,u.start=0))}}function ft(e,t){var n,r,i,o,a;for(n in e)if(r=G(n),i=t[r],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=w.cssHooks[r])&&"expand"in a){o=a.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}function pt(e,t,n){var r,i,o=0,a=pt.prefilters.length,s=w.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;for(var t=nt||st(),n=Math.max(0,l.startTime+l.duration-t),r=1-(n/l.duration||0),o=0,a=l.tweens.length;o<a;o++)l.tweens[o].run(r);return s.notifyWith(e,[l,r,n]),r<1&&a?n:(a||s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:w.extend({},t),opts:w.extend(!0,{specialEasing:{},easing:w.easing._default},n),originalProperties:t,originalOptions:n,startTime:nt||st(),duration:n.duration,tweens:[],createTween:function(t,n){var r=w.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;n<r;n++)l.tweens[n].run(1);return t?(s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l,t])):s.rejectWith(e,[l,t]),this}}),c=l.props;for(ft(c,l.opts.specialEasing);o<a;o++)if(r=pt.prefilters[o].call(l,e,c,l.opts))return g(r.stop)&&(w._queueHooks(l.elem,l.opts.queue).stop=r.stop.bind(r)),r;return w.map(c,lt,l),g(l.opts.start)&&l.opts.start.call(e,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),w.fx.timer(w.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l}w.Animation=w.extend(pt,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return ue(n.elem,e,ie.exec(t),n),n}]},tweener:function(e,t){g(e)?(t=e,e=["*"]):e=e.match(M);for(var n,r=0,i=e.length;r<i;r++)n=e[r],pt.tweeners[n]=pt.tweeners[n]||[],pt.tweeners[n].unshift(t)},prefilters:[ct],prefilter:function(e,t){t?pt.prefilters.unshift(e):pt.prefilters.push(e)}}),w.speed=function(e,t,n){var r=e&&"object"==typeof e?w.extend({},e):{complete:n||!n&&t||g(e)&&e,duration:e,easing:n&&t||t&&!g(t)&&t};return w.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in w.fx.speeds?r.duration=w.fx.speeds[r.duration]:r.duration=w.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){g(r.old)&&r.old.call(this),r.queue&&w.dequeue(this,r.queue)},r},w.fn.extend({fadeTo:function(e,t,n,r){return this.filter(ae).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=w.isEmptyObject(e),o=w.speed(t,n,r),a=function(){var t=pt(this,w.extend({},e),o);(i||J.get(this,"finish"))&&t.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(e,t,n){var r=function(e){var t=e.stop;delete e.stop,t(n)};return"string"!=typeof e&&(n=t,t=e,e=void 0),t&&!1!==e&&this.queue(e||"fx",[]),this.each(function(){var t=!0,i=null!=e&&e+"queueHooks",o=w.timers,a=J.get(this);if(i)a[i]&&a[i].stop&&r(a[i]);else for(i in a)a[i]&&a[i].stop&&ot.test(i)&&r(a[i]);for(i=o.length;i--;)o[i].elem!==this||null!=e&&o[i].queue!==e||(o[i].anim.stop(n),t=!1,o.splice(i,1));!t&&n||w.dequeue(this,e)})},finish:function(e){return!1!==e&&(e=e||"fx"),this.each(function(){var t,n=J.get(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=w.timers,a=r?r.length:0;for(n.finish=!0,w.queue(this,e,[]),i&&i.stop&&i.stop.call(this,!0),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;t<a;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}}),w.each(["toggle","show","hide"],function(e,t){var n=w.fn[t];w.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ut(t,!0),e,r,i)}}),w.each({slideDown:ut("show"),slideUp:ut("hide"),slideToggle:ut("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){w.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),w.timers=[],w.fx.tick=function(){var e,t=0,n=w.timers;for(nt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||w.fx.stop(),nt=void 0},w.fx.timer=function(e){w.timers.push(e),w.fx.start()},w.fx.interval=13,w.fx.start=function(){rt||(rt=!0,at())},w.fx.stop=function(){rt=null},w.fx.speeds={slow:600,fast:200,_default:400},w.fn.delay=function(t,n){return t=w.fx?w.fx.speeds[t]||t:t,n=n||"fx",this.queue(n,function(n,r){var i=e.setTimeout(n,t);r.stop=function(){e.clearTimeout(i)}})},function(){var e=r.createElement("input"),t=r.createElement("select").appendChild(r.createElement("option"));e.type="checkbox",h.checkOn=""!==e.value,h.optSelected=t.selected,(e=r.createElement("input")).value="t",e.type="radio",h.radioValue="t"===e.value}();var dt,ht=w.expr.attrHandle;w.fn.extend({attr:function(e,t){return z(this,w.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){w.removeAttr(this,e)})}}),w.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?w.prop(e,t,n):(1===o&&w.isXMLDoc(e)||(i=w.attrHooks[t.toLowerCase()]||(w.expr.match.bool.test(t)?dt:void 0)),void 0!==n?null===n?void w.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=w.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!h.radioValue&&"radio"===t&&N(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(M);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),dt={set:function(e,t,n){return!1===t?w.removeAttr(e,n):e.setAttribute(n,n),n}},w.each(w.expr.match.bool.source.match(/\w+/g),function(e,t){var n=ht[t]||w.find.attr;ht[t]=function(e,t,r){var i,o,a=t.toLowerCase();return r||(o=ht[a],ht[a]=i,i=null!=n(e,t,r)?a:null,ht[a]=o),i}});var gt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;w.fn.extend({prop:function(e,t){return z(this,w.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[w.propFix[e]||e]})}}),w.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&w.isXMLDoc(e)||(t=w.propFix[t]||t,i=w.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=w.find.attr(e,"tabindex");return t?parseInt(t,10):gt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),h.optSelected||(w.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),w.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){w.propFix[this.toLowerCase()]=this});function vt(e){return(e.match(M)||[]).join(" ")}function mt(e){return e.getAttribute&&e.getAttribute("class")||""}function xt(e){return Array.isArray(e)?e:"string"==typeof e?e.match(M)||[]:[]}w.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).addClass(e.call(this,t,mt(this)))});if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).removeClass(e.call(this,t,mt(this)))});if(!arguments.length)return this.attr("class","");if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])while(r.indexOf(" "+o+" ")>-1)r=r.replace(" "+o+" "," ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(e,t){var n=typeof e,r="string"===n||Array.isArray(e);return"boolean"==typeof t&&r?t?this.addClass(e):this.removeClass(e):g(e)?this.each(function(n){w(this).toggleClass(e.call(this,n,mt(this),t),t)}):this.each(function(){var t,i,o,a;if(r){i=0,o=w(this),a=xt(e);while(t=a[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else void 0!==e&&"boolean"!==n||((t=mt(this))&&J.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||!1===e?"":J.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&(" "+vt(mt(n))+" ").indexOf(t)>-1)return!0;return!1}});var bt=/\r/g;w.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=g(e),this.each(function(n){var i;1===this.nodeType&&(null==(i=r?e.call(this,n,w(this).val()):e)?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=w.map(i,function(e){return null==e?"":e+""})),(t=w.valHooks[this.type]||w.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return(t=w.valHooks[i.type]||w.valHooks[i.nodeName.toLowerCase()])&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:"string"==typeof(n=i.value)?n.replace(bt,""):null==n?"":n}}}),w.extend({valHooks:{option:{get:function(e){var t=w.find.attr(e,"value");return null!=t?t:vt(w.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!N(n.parentNode,"optgroup"))){if(t=w(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=w.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=w.inArray(w.valHooks.option.get(r),o)>-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),w.each(["radio","checkbox"],function(){w.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=w.inArray(w(e).val(),t)>-1}},h.checkOn||(w.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),h.focusin="onfocusin"in e;var wt=/^(?:focusinfocus|focusoutblur)$/,Tt=function(e){e.stopPropagation()};w.extend(w.event,{trigger:function(t,n,i,o){var a,s,u,l,c,p,d,h,v=[i||r],m=f.call(t,"type")?t.type:t,x=f.call(t,"namespace")?t.namespace.split("."):[];if(s=h=u=i=i||r,3!==i.nodeType&&8!==i.nodeType&&!wt.test(m+w.event.triggered)&&(m.indexOf(".")>-1&&(m=(x=m.split(".")).shift(),x.sort()),c=m.indexOf(":")<0&&"on"+m,t=t[w.expando]?t:new w.Event(m,"object"==typeof t&&t),t.isTrigger=o?2:3,t.namespace=x.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+x.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=i),n=null==n?[t]:w.makeArray(n,[t]),d=w.event.special[m]||{},o||!d.trigger||!1!==d.trigger.apply(i,n))){if(!o&&!d.noBubble&&!y(i)){for(l=d.delegateType||m,wt.test(l+m)||(s=s.parentNode);s;s=s.parentNode)v.push(s),u=s;u===(i.ownerDocument||r)&&v.push(u.defaultView||u.parentWindow||e)}a=0;while((s=v[a++])&&!t.isPropagationStopped())h=s,t.type=a>1?l:d.bindType||m,(p=(J.get(s,"events")||{})[t.type]&&J.get(s,"handle"))&&p.apply(s,n),(p=c&&s[c])&&p.apply&&Y(s)&&(t.result=p.apply(s,n),!1===t.result&&t.preventDefault());return t.type=m,o||t.isDefaultPrevented()||d._default&&!1!==d._default.apply(v.pop(),n)||!Y(i)||c&&g(i[m])&&!y(i)&&((u=i[c])&&(i[c]=null),w.event.triggered=m,t.isPropagationStopped()&&h.addEventListener(m,Tt),i[m](),t.isPropagationStopped()&&h.removeEventListener(m,Tt),w.event.triggered=void 0,u&&(i[c]=u)),t.result}},simulate:function(e,t,n){var r=w.extend(new w.Event,n,{type:e,isSimulated:!0});w.event.trigger(r,null,t)}}),w.fn.extend({trigger:function(e,t){return this.each(function(){w.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return w.event.trigger(e,t,n,!0)}}),h.focusin||w.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){w.event.simulate(t,e.target,w.event.fix(e))};w.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=J.access(r,t);i||r.addEventListener(e,n,!0),J.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=J.access(r,t)-1;i?J.access(r,t,i):(r.removeEventListener(e,n,!0),J.remove(r,t))}}});var Ct=e.location,Et=Date.now(),kt=/\?/;w.parseXML=function(t){var n;if(!t||"string"!=typeof t)return null;try{n=(new e.DOMParser).parseFromString(t,"text/xml")}catch(e){n=void 0}return n&&!n.getElementsByTagName("parsererror").length||w.error("Invalid XML: "+t),n};var St=/\[\]$/,Dt=/\r?\n/g,Nt=/^(?:submit|button|image|reset|file)$/i,At=/^(?:input|select|textarea|keygen)/i;function jt(e,t,n,r){var i;if(Array.isArray(t))w.each(t,function(t,i){n||St.test(e)?r(e,i):jt(e+"["+("object"==typeof i&&null!=i?t:"")+"]",i,n,r)});else if(n||"object"!==x(t))r(e,t);else for(i in t)jt(e+"["+i+"]",t[i],n,r)}w.param=function(e,t){var n,r=[],i=function(e,t){var n=g(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(Array.isArray(e)||e.jquery&&!w.isPlainObject(e))w.each(e,function(){i(this.name,this.value)});else for(n in e)jt(n,e[n],t,i);return r.join("&")},w.fn.extend({serialize:function(){return w.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=w.prop(this,"elements");return e?w.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!w(this).is(":disabled")&&At.test(this.nodeName)&&!Nt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=w(this).val();return null==n?null:Array.isArray(n)?w.map(n,function(e){return{name:t.name,value:e.replace(Dt,"\r\n")}}):{name:t.name,value:n.replace(Dt,"\r\n")}}).get()}});var qt=/%20/g,Lt=/#.*$/,Ht=/([?&])_=[^&]*/,Ot=/^(.*?):[ \t]*([^\r\n]*)$/gm,Pt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Mt=/^(?:GET|HEAD)$/,Rt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Bt=r.createElement("a");Bt.href=Ct.href;function Ft(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(M)||[];if(g(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function _t(e,t,n,r){var i={},o=e===Wt;function a(s){var u;return i[s]=!0,w.each(e[s]||[],function(e,s){var l=s(t,n,r);return"string"!=typeof l||o||i[l]?o?!(u=l):void 0:(t.dataTypes.unshift(l),a(l),!1)}),u}return a(t.dataTypes[0])||!i["*"]&&a("*")}function zt(e,t){var n,r,i=w.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&w.extend(!0,e,r),e}function Xt(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}function Ut(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}w.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ct.href,type:"GET",isLocal:Pt.test(Ct.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":w.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,w.ajaxSettings),t):zt(w.ajaxSettings,e)},ajaxPrefilter:Ft(It),ajaxTransport:Ft(Wt),ajax:function(t,n){"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,p,d,h=w.ajaxSetup({},n),g=h.context||h,y=h.context&&(g.nodeType||g.jquery)?w(g):w.event,v=w.Deferred(),m=w.Callbacks("once memory"),x=h.statusCode||{},b={},T={},C="canceled",E={readyState:0,getResponseHeader:function(e){var t;if(c){if(!s){s={};while(t=Ot.exec(a))s[t[1].toLowerCase()]=t[2]}t=s[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return c?a:null},setRequestHeader:function(e,t){return null==c&&(e=T[e.toLowerCase()]=T[e.toLowerCase()]||e,b[e]=t),this},overrideMimeType:function(e){return null==c&&(h.mimeType=e),this},statusCode:function(e){var t;if(e)if(c)E.always(e[E.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||C;return i&&i.abort(t),k(0,t),this}};if(v.promise(E),h.url=((t||h.url||Ct.href)+"").replace(Rt,Ct.protocol+"//"),h.type=n.method||n.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(M)||[""],null==h.crossDomain){l=r.createElement("a");try{l.href=h.url,l.href=l.href,h.crossDomain=Bt.protocol+"//"+Bt.host!=l.protocol+"//"+l.host}catch(e){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=w.param(h.data,h.traditional)),_t(It,h,n,E),c)return E;(f=w.event&&h.global)&&0==w.active++&&w.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!Mt.test(h.type),o=h.url.replace(Lt,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(qt,"+")):(d=h.url.slice(o.length),h.data&&(h.processData||"string"==typeof h.data)&&(o+=(kt.test(o)?"&":"?")+h.data,delete h.data),!1===h.cache&&(o=o.replace(Ht,"$1"),d=(kt.test(o)?"&":"?")+"_="+Et+++d),h.url=o+d),h.ifModified&&(w.lastModified[o]&&E.setRequestHeader("If-Modified-Since",w.lastModified[o]),w.etag[o]&&E.setRequestHeader("If-None-Match",w.etag[o])),(h.data&&h.hasContent&&!1!==h.contentType||n.contentType)&&E.setRequestHeader("Content-Type",h.contentType),E.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", "+$t+"; q=0.01":""):h.accepts["*"]);for(p in h.headers)E.setRequestHeader(p,h.headers[p]);if(h.beforeSend&&(!1===h.beforeSend.call(g,E,h)||c))return E.abort();if(C="abort",m.add(h.complete),E.done(h.success),E.fail(h.error),i=_t(Wt,h,n,E)){if(E.readyState=1,f&&y.trigger("ajaxSend",[E,h]),c)return E;h.async&&h.timeout>0&&(u=e.setTimeout(function(){E.abort("timeout")},h.timeout));try{c=!1,i.send(b,k)}catch(e){if(c)throw e;k(-1,e)}}else k(-1,"No Transport");function k(t,n,r,s){var l,p,d,b,T,C=n;c||(c=!0,u&&e.clearTimeout(u),i=void 0,a=s||"",E.readyState=t>0?4:0,l=t>=200&&t<300||304===t,r&&(b=Xt(h,E,r)),b=Ut(h,b,E,l),l?(h.ifModified&&((T=E.getResponseHeader("Last-Modified"))&&(w.lastModified[o]=T),(T=E.getResponseHeader("etag"))&&(w.etag[o]=T)),204===t||"HEAD"===h.type?C="nocontent":304===t?C="notmodified":(C=b.state,p=b.data,l=!(d=b.error))):(d=C,!t&&C||(C="error",t<0&&(t=0))),E.status=t,E.statusText=(n||C)+"",l?v.resolveWith(g,[p,C,E]):v.rejectWith(g,[E,C,d]),E.statusCode(x),x=void 0,f&&y.trigger(l?"ajaxSuccess":"ajaxError",[E,h,l?p:d]),m.fireWith(g,[E,C]),f&&(y.trigger("ajaxComplete",[E,h]),--w.active||w.event.trigger("ajaxStop")))}return E},getJSON:function(e,t,n){return w.get(e,t,n,"json")},getScript:function(e,t){return w.get(e,void 0,t,"script")}}),w.each(["get","post"],function(e,t){w[t]=function(e,n,r,i){return g(n)&&(i=i||r,r=n,n=void 0),w.ajax(w.extend({url:e,type:t,dataType:i,data:n,success:r},w.isPlainObject(e)&&e))}}),w._evalUrl=function(e){return w.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},w.fn.extend({wrapAll:function(e){var t;return this[0]&&(g(e)&&(e=e.call(this[0])),t=w(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return g(e)?this.each(function(t){w(this).wrapInner(e.call(this,t))}):this.each(function(){var t=w(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=g(e);return this.each(function(n){w(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){w(this).replaceWith(this.childNodes)}),this}}),w.expr.pseudos.hidden=function(e){return!w.expr.pseudos.visible(e)},w.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},w.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var Vt={0:200,1223:204},Gt=w.ajaxSettings.xhr();h.cors=!!Gt&&"withCredentials"in Gt,h.ajax=Gt=!!Gt,w.ajaxTransport(function(t){var n,r;if(h.cors||Gt&&!t.crossDomain)return{send:function(i,o){var a,s=t.xhr();if(s.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(a in t.xhrFields)s[a]=t.xhrFields[a];t.mimeType&&s.overrideMimeType&&s.overrideMimeType(t.mimeType),t.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");for(a in i)s.setRequestHeader(a,i[a]);n=function(e){return function(){n&&(n=r=s.onload=s.onerror=s.onabort=s.ontimeout=s.onreadystatechange=null,"abort"===e?s.abort():"error"===e?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o(Vt[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=n(),r=s.onerror=s.ontimeout=n("error"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&e.setTimeout(function(){n&&r()})},n=n("abort");try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}},abort:function(){n&&n()}}}),w.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),w.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return w.globalEval(e),e}}}),w.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),w.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(i,o){t=w("<script>").prop({charset:e.scriptCharset,src:e.url}).on("load error",n=function(e){t.remove(),n=null,e&&o("error"===e.type?404:200,e.type)}),r.head.appendChild(t[0])},abort:function(){n&&n()}}}});var Yt=[],Qt=/(=)\?(?=&|$)|\?\?/;w.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Yt.pop()||w.expando+"_"+Et++;return this[e]=!0,e}}),w.ajaxPrefilter("json jsonp",function(t,n,r){var i,o,a,s=!1!==t.jsonp&&(Qt.test(t.url)?"url":"string"==typeof t.data&&0===(t.contentType||"").indexOf("application/x-www-form-urlencoded")&&Qt.test(t.data)&&"data");if(s||"jsonp"===t.dataTypes[0])return i=t.jsonpCallback=g(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(Qt,"$1"+i):!1!==t.jsonp&&(t.url+=(kt.test(t.url)?"&":"?")+t.jsonp+"="+i),t.converters["script json"]=function(){return a||w.error(i+" was not called"),a[0]},t.dataTypes[0]="json",o=e[i],e[i]=function(){a=arguments},r.always(function(){void 0===o?w(e).removeProp(i):e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,Yt.push(i)),a&&g(o)&&o(a[0]),a=o=void 0}),"script"}),h.createHTMLDocument=function(){var e=r.implementation.createHTMLDocument("").body;return e.innerHTML="<form></form><form></form>",2===e.childNodes.length}(),w.parseHTML=function(e,t,n){if("string"!=typeof e)return[];"boolean"==typeof t&&(n=t,t=!1);var i,o,a;return t||(h.createHTMLDocument?((i=(t=r.implementation.createHTMLDocument("")).createElement("base")).href=r.location.href,t.head.appendChild(i)):t=r),o=A.exec(e),a=!n&&[],o?[t.createElement(o[1])]:(o=xe([e],t,a),a&&a.length&&w(a).remove(),w.merge([],o.childNodes))},w.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return s>-1&&(r=vt(e.slice(s)),e=e.slice(0,s)),g(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),a.length>0&&w.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?w("<div>").append(w.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},w.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){w.fn[t]=function(e){return this.on(t,e)}}),w.expr.pseudos.animated=function(e){return w.grep(w.timers,function(t){return e===t.elem}).length},w.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l,c=w.css(e,"position"),f=w(e),p={};"static"===c&&(e.style.position="relative"),s=f.offset(),o=w.css(e,"top"),u=w.css(e,"left"),(l=("absolute"===c||"fixed"===c)&&(o+u).indexOf("auto")>-1)?(a=(r=f.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),g(t)&&(t=t.call(e,n,w.extend({},s))),null!=t.top&&(p.top=t.top-s.top+a),null!=t.left&&(p.left=t.left-s.left+i),"using"in t?t.using.call(e,p):f.css(p)}},w.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){w.offset.setOffset(this,e,t)});var t,n,r=this[0];if(r)return r.getClientRects().length?(t=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:t.top+n.pageYOffset,left:t.left+n.pageXOffset}):{top:0,left:0}},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===w.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===w.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=w(e).offset()).top+=w.css(e,"borderTopWidth",!0),i.left+=w.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-w.css(r,"marginTop",!0),left:t.left-i.left-w.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===w.css(e,"position"))e=e.offsetParent;return e||be})}}),w.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,t){var n="pageYOffset"===t;w.fn[e]=function(r){return z(this,function(e,r,i){var o;if(y(e)?o=e:9===e.nodeType&&(o=e.defaultView),void 0===i)return o?o[t]:e[r];o?o.scrollTo(n?o.pageXOffset:i,n?i:o.pageYOffset):e[r]=i},e,r,arguments.length)}}),w.each(["top","left"],function(e,t){w.cssHooks[t]=_e(h.pixelPosition,function(e,n){if(n)return n=Fe(e,t),We.test(n)?w(e).position()[t]+"px":n})}),w.each({Height:"height",Width:"width"},function(e,t){w.each({padding:"inner"+e,content:t,"":"outer"+e},function(n,r){w.fn[r]=function(i,o){var a=arguments.length&&(n||"boolean"!=typeof i),s=n||(!0===i||!0===o?"margin":"border");return z(this,function(t,n,i){var o;return y(t)?0===r.indexOf("outer")?t["inner"+e]:t.document.documentElement["client"+e]:9===t.nodeType?(o=t.documentElement,Math.max(t.body["scroll"+e],o["scroll"+e],t.body["offset"+e],o["offset"+e],o["client"+e])):void 0===i?w.css(t,n,s):w.style(t,n,i,s)},t,a?i:void 0,a)}})}),w.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,t){w.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),w.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),w.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),w.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),g(e))return r=o.call(arguments,2),i=function(){return e.apply(t||this,r.concat(o.call(arguments)))},i.guid=e.guid=e.guid||w.guid++,i},w.holdReady=function(e){e?w.readyWait++:w.ready(!0)},w.isArray=Array.isArray,w.parseJSON=JSON.parse,w.nodeName=N,w.isFunction=g,w.isWindow=y,w.camelCase=G,w.type=x,w.now=Date.now,w.isNumeric=function(e){var t=w.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},"function"==typeof define&&define.amd&&define("jquery",[],function(){return w});var Jt=e.jQuery,Kt=e.$;return w.noConflict=function(t){return e.$===w&&(e.$=Kt),t&&e.jQuery===w&&(e.jQuery=Jt),w},t||(e.jQuery=e.$=w),w});
;
/*!
 * Knockout JavaScript library v3.4.2
 * (c) The Knockout.js team - http://knockoutjs.com/
 * License: MIT (http://www.opensource.org/licenses/mit-license.php)
 */

(function() {(function(n){var x=this||(0,eval)("this"),t=x.document,M=x.navigator,u=x.jQuery,H=x.JSON;(function(n){"function"===typeof define&&define.amd?define(["exports","require"],n):"object"===typeof exports&&"object"===typeof module?n(module.exports||exports):n(x.ko={})})(function(N,O){function J(a,c){return null===a||typeof a in R?a===c:!1}function S(b,c){var d;return function(){d||(d=a.a.setTimeout(function(){d=n;b()},c))}}function T(b,c){var d;return function(){clearTimeout(d);d=a.a.setTimeout(b,c)}}function U(a,
c){c&&c!==E?"beforeChange"===c?this.Ob(a):this.Ja(a,c):this.Pb(a)}function V(a,c){null!==c&&c.k&&c.k()}function W(a,c){var d=this.Mc,e=d[s];e.T||(this.ob&&this.Oa[c]?(d.Sb(c,a,this.Oa[c]),this.Oa[c]=null,--this.ob):e.s[c]||d.Sb(c,a,e.t?{$:a}:d.yc(a)),a.Ha&&a.Hc())}function K(b,c,d,e){a.d[b]={init:function(b,g,h,l,m){var k,r;a.m(function(){var q=g(),p=a.a.c(q),p=!d!==!p,A=!r;if(A||c||p!==k)A&&a.xa.Ca()&&(r=a.a.wa(a.f.childNodes(b),!0)),p?(A||a.f.fa(b,a.a.wa(r)),a.hb(e?e(m,q):m,b)):a.f.za(b),k=p},null,
{i:b});return{controlsDescendantBindings:!0}}};a.h.va[b]=!1;a.f.aa[b]=!0}var a="undefined"!==typeof N?N:{};a.b=function(b,c){for(var d=b.split("."),e=a,f=0;f<d.length-1;f++)e=e[d[f]];e[d[d.length-1]]=c};a.H=function(a,c,d){a[c]=d};a.version="3.4.2";a.b("version",a.version);a.options={deferUpdates:!1,useOnlyNativeEvents:!1};a.a=function(){function b(a,b){for(var c in a)a.hasOwnProperty(c)&&b(c,a[c])}function c(a,b){if(b)for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}function d(a,b){a.__proto__=
b;return a}function e(b,c,d,e){var m=b[c].match(r)||[];a.a.r(d.match(r),function(b){a.a.ra(m,b,e)});b[c]=m.join(" ")}var f={__proto__:[]}instanceof Array,g="function"===typeof Symbol,h={},l={};h[M&&/Firefox\/2/i.test(M.userAgent)?"KeyboardEvent":"UIEvents"]=["keyup","keydown","keypress"];h.MouseEvents="click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave".split(" ");b(h,function(a,b){if(b.length)for(var c=0,d=b.length;c<d;c++)l[b[c]]=a});var m={propertychange:!0},k=
t&&function(){for(var a=3,b=t.createElement("div"),c=b.getElementsByTagName("i");b.innerHTML="\x3c!--[if gt IE "+ ++a+"]><i></i><![endif]--\x3e",c[0];);return 4<a?a:n}(),r=/\S+/g;return{gc:["authenticity_token",/^__RequestVerificationToken(_.*)?$/],r:function(a,b){for(var c=0,d=a.length;c<d;c++)b(a[c],c)},o:function(a,b){if("function"==typeof Array.prototype.indexOf)return Array.prototype.indexOf.call(a,b);for(var c=0,d=a.length;c<d;c++)if(a[c]===b)return c;return-1},Vb:function(a,b,c){for(var d=
0,e=a.length;d<e;d++)if(b.call(c,a[d],d))return a[d];return null},Na:function(b,c){var d=a.a.o(b,c);0<d?b.splice(d,1):0===d&&b.shift()},Wb:function(b){b=b||[];for(var c=[],d=0,e=b.length;d<e;d++)0>a.a.o(c,b[d])&&c.push(b[d]);return c},ib:function(a,b){a=a||[];for(var c=[],d=0,e=a.length;d<e;d++)c.push(b(a[d],d));return c},Ma:function(a,b){a=a||[];for(var c=[],d=0,e=a.length;d<e;d++)b(a[d],d)&&c.push(a[d]);return c},ta:function(a,b){if(b instanceof Array)a.push.apply(a,b);else for(var c=0,d=b.length;c<
d;c++)a.push(b[c]);return a},ra:function(b,c,d){var e=a.a.o(a.a.Bb(b),c);0>e?d&&b.push(c):d||b.splice(e,1)},la:f,extend:c,$a:d,ab:f?d:c,D:b,Ea:function(a,b){if(!a)return a;var c={},d;for(d in a)a.hasOwnProperty(d)&&(c[d]=b(a[d],d,a));return c},rb:function(b){for(;b.firstChild;)a.removeNode(b.firstChild)},nc:function(b){b=a.a.W(b);for(var c=(b[0]&&b[0].ownerDocument||t).createElement("div"),d=0,e=b.length;d<e;d++)c.appendChild(a.ba(b[d]));return c},wa:function(b,c){for(var d=0,e=b.length,m=[];d<e;d++){var k=
b[d].cloneNode(!0);m.push(c?a.ba(k):k)}return m},fa:function(b,c){a.a.rb(b);if(c)for(var d=0,e=c.length;d<e;d++)b.appendChild(c[d])},uc:function(b,c){var d=b.nodeType?[b]:b;if(0<d.length){for(var e=d[0],m=e.parentNode,k=0,f=c.length;k<f;k++)m.insertBefore(c[k],e);k=0;for(f=d.length;k<f;k++)a.removeNode(d[k])}},Ba:function(a,b){if(a.length){for(b=8===b.nodeType&&b.parentNode||b;a.length&&a[0].parentNode!==b;)a.splice(0,1);for(;1<a.length&&a[a.length-1].parentNode!==b;)a.length--;if(1<a.length){var c=
a[0],d=a[a.length-1];for(a.length=0;c!==d;)a.push(c),c=c.nextSibling;a.push(d)}}return a},wc:function(a,b){7>k?a.setAttribute("selected",b):a.selected=b},cb:function(a){return null===a||a===n?"":a.trim?a.trim():a.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g,"")},sd:function(a,b){a=a||"";return b.length>a.length?!1:a.substring(0,b.length)===b},Rc:function(a,b){if(a===b)return!0;if(11===a.nodeType)return!1;if(b.contains)return b.contains(3===a.nodeType?a.parentNode:a);if(b.compareDocumentPosition)return 16==
(b.compareDocumentPosition(a)&16);for(;a&&a!=b;)a=a.parentNode;return!!a},qb:function(b){return a.a.Rc(b,b.ownerDocument.documentElement)},Tb:function(b){return!!a.a.Vb(b,a.a.qb)},A:function(a){return a&&a.tagName&&a.tagName.toLowerCase()},Zb:function(b){return a.onError?function(){try{return b.apply(this,arguments)}catch(c){throw a.onError&&a.onError(c),c;}}:b},setTimeout:function(b,c){return setTimeout(a.a.Zb(b),c)},dc:function(b){setTimeout(function(){a.onError&&a.onError(b);throw b;},0)},q:function(b,
c,d){var e=a.a.Zb(d);d=k&&m[c];if(a.options.useOnlyNativeEvents||d||!u)if(d||"function"!=typeof b.addEventListener)if("undefined"!=typeof b.attachEvent){var f=function(a){e.call(b,a)},l="on"+c;b.attachEvent(l,f);a.a.G.qa(b,function(){b.detachEvent(l,f)})}else throw Error("Browser doesn't support addEventListener or attachEvent");else b.addEventListener(c,e,!1);else u(b).bind(c,e)},Fa:function(b,c){if(!b||!b.nodeType)throw Error("element must be a DOM node when calling triggerEvent");var d;"input"===
a.a.A(b)&&b.type&&"click"==c.toLowerCase()?(d=b.type,d="checkbox"==d||"radio"==d):d=!1;if(a.options.useOnlyNativeEvents||!u||d)if("function"==typeof t.createEvent)if("function"==typeof b.dispatchEvent)d=t.createEvent(l[c]||"HTMLEvents"),d.initEvent(c,!0,!0,x,0,0,0,0,0,!1,!1,!1,!1,0,b),b.dispatchEvent(d);else throw Error("The supplied element doesn't support dispatchEvent");else if(d&&b.click)b.click();else if("undefined"!=typeof b.fireEvent)b.fireEvent("on"+c);else throw Error("Browser doesn't support triggering events");
else u(b).trigger(c)},c:function(b){return a.I(b)?b():b},Bb:function(b){return a.I(b)?b.p():b},fb:function(b,c,d){var k;c&&("object"===typeof b.classList?(k=b.classList[d?"add":"remove"],a.a.r(c.match(r),function(a){k.call(b.classList,a)})):"string"===typeof b.className.baseVal?e(b.className,"baseVal",c,d):e(b,"className",c,d))},bb:function(b,c){var d=a.a.c(c);if(null===d||d===n)d="";var e=a.f.firstChild(b);!e||3!=e.nodeType||a.f.nextSibling(e)?a.f.fa(b,[b.ownerDocument.createTextNode(d)]):e.data=
d;a.a.Wc(b)},vc:function(a,b){a.name=b;if(7>=k)try{a.mergeAttributes(t.createElement("<input name='"+a.name+"'/>"),!1)}catch(c){}},Wc:function(a){9<=k&&(a=1==a.nodeType?a:a.parentNode,a.style&&(a.style.zoom=a.style.zoom))},Sc:function(a){if(k){var b=a.style.width;a.style.width=0;a.style.width=b}},nd:function(b,c){b=a.a.c(b);c=a.a.c(c);for(var d=[],e=b;e<=c;e++)d.push(e);return d},W:function(a){for(var b=[],c=0,d=a.length;c<d;c++)b.push(a[c]);return b},bc:function(a){return g?Symbol(a):a},xd:6===k,
yd:7===k,C:k,ic:function(b,c){for(var d=a.a.W(b.getElementsByTagName("input")).concat(a.a.W(b.getElementsByTagName("textarea"))),e="string"==typeof c?function(a){return a.name===c}:function(a){return c.test(a.name)},k=[],m=d.length-1;0<=m;m--)e(d[m])&&k.push(d[m]);return k},kd:function(b){return"string"==typeof b&&(b=a.a.cb(b))?H&&H.parse?H.parse(b):(new Function("return "+b))():null},Gb:function(b,c,d){if(!H||!H.stringify)throw Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js");
return H.stringify(a.a.c(b),c,d)},ld:function(c,d,e){e=e||{};var k=e.params||{},m=e.includeFields||this.gc,f=c;if("object"==typeof c&&"form"===a.a.A(c))for(var f=c.action,l=m.length-1;0<=l;l--)for(var g=a.a.ic(c,m[l]),h=g.length-1;0<=h;h--)k[g[h].name]=g[h].value;d=a.a.c(d);var r=t.createElement("form");r.style.display="none";r.action=f;r.method="post";for(var n in d)c=t.createElement("input"),c.type="hidden",c.name=n,c.value=a.a.Gb(a.a.c(d[n])),r.appendChild(c);b(k,function(a,b){var c=t.createElement("input");
c.type="hidden";c.name=a;c.value=b;r.appendChild(c)});t.body.appendChild(r);e.submitter?e.submitter(r):r.submit();setTimeout(function(){r.parentNode.removeChild(r)},0)}}}();a.b("utils",a.a);a.b("utils.arrayForEach",a.a.r);a.b("utils.arrayFirst",a.a.Vb);a.b("utils.arrayFilter",a.a.Ma);a.b("utils.arrayGetDistinctValues",a.a.Wb);a.b("utils.arrayIndexOf",a.a.o);a.b("utils.arrayMap",a.a.ib);a.b("utils.arrayPushAll",a.a.ta);a.b("utils.arrayRemoveItem",a.a.Na);a.b("utils.extend",a.a.extend);a.b("utils.fieldsIncludedWithJsonPost",
a.a.gc);a.b("utils.getFormFields",a.a.ic);a.b("utils.peekObservable",a.a.Bb);a.b("utils.postJson",a.a.ld);a.b("utils.parseJson",a.a.kd);a.b("utils.registerEventHandler",a.a.q);a.b("utils.stringifyJson",a.a.Gb);a.b("utils.range",a.a.nd);a.b("utils.toggleDomNodeCssClass",a.a.fb);a.b("utils.triggerEvent",a.a.Fa);a.b("utils.unwrapObservable",a.a.c);a.b("utils.objectForEach",a.a.D);a.b("utils.addOrRemoveItem",a.a.ra);a.b("utils.setTextContent",a.a.bb);a.b("unwrap",a.a.c);Function.prototype.bind||(Function.prototype.bind=
function(a){var c=this;if(1===arguments.length)return function(){return c.apply(a,arguments)};var d=Array.prototype.slice.call(arguments,1);return function(){var e=d.slice(0);e.push.apply(e,arguments);return c.apply(a,e)}});a.a.e=new function(){function a(b,g){var h=b[d];if(!h||"null"===h||!e[h]){if(!g)return n;h=b[d]="ko"+c++;e[h]={}}return e[h]}var c=0,d="__ko__"+(new Date).getTime(),e={};return{get:function(c,d){var e=a(c,!1);return e===n?n:e[d]},set:function(c,d,e){if(e!==n||a(c,!1)!==n)a(c,!0)[d]=
e},clear:function(a){var b=a[d];return b?(delete e[b],a[d]=null,!0):!1},J:function(){return c++ +d}}};a.b("utils.domData",a.a.e);a.b("utils.domData.clear",a.a.e.clear);a.a.G=new function(){function b(b,c){var e=a.a.e.get(b,d);e===n&&c&&(e=[],a.a.e.set(b,d,e));return e}function c(d){var e=b(d,!1);if(e)for(var e=e.slice(0),l=0;l<e.length;l++)e[l](d);a.a.e.clear(d);a.a.G.cleanExternalData(d);if(f[d.nodeType])for(e=d.firstChild;d=e;)e=d.nextSibling,8===d.nodeType&&c(d)}var d=a.a.e.J(),e={1:!0,8:!0,9:!0},
f={1:!0,9:!0};return{qa:function(a,c){if("function"!=typeof c)throw Error("Callback must be a function");b(a,!0).push(c)},tc:function(c,e){var f=b(c,!1);f&&(a.a.Na(f,e),0==f.length&&a.a.e.set(c,d,n))},ba:function(b){if(e[b.nodeType]&&(c(b),f[b.nodeType])){var d=[];a.a.ta(d,b.getElementsByTagName("*"));for(var l=0,m=d.length;l<m;l++)c(d[l])}return b},removeNode:function(b){a.ba(b);b.parentNode&&b.parentNode.removeChild(b)},cleanExternalData:function(a){u&&"function"==typeof u.cleanData&&u.cleanData([a])}}};
a.ba=a.a.G.ba;a.removeNode=a.a.G.removeNode;a.b("cleanNode",a.ba);a.b("removeNode",a.removeNode);a.b("utils.domNodeDisposal",a.a.G);a.b("utils.domNodeDisposal.addDisposeCallback",a.a.G.qa);a.b("utils.domNodeDisposal.removeDisposeCallback",a.a.G.tc);(function(){var b=[0,"",""],c=[1,"<table>","</table>"],d=[3,"<table><tbody><tr>","</tr></tbody></table>"],e=[1,"<select multiple='multiple'>","</select>"],f={thead:c,tbody:c,tfoot:c,tr:[2,"<table><tbody>","</tbody></table>"],td:d,th:d,option:e,optgroup:e},
g=8>=a.a.C;a.a.na=function(c,d){var e;if(u)if(u.parseHTML)e=u.parseHTML(c,d)||[];else{if((e=u.clean([c],d))&&e[0]){for(var k=e[0];k.parentNode&&11!==k.parentNode.nodeType;)k=k.parentNode;k.parentNode&&k.parentNode.removeChild(k)}}else{(e=d)||(e=t);var k=e.parentWindow||e.defaultView||x,r=a.a.cb(c).toLowerCase(),q=e.createElement("div"),p;p=(r=r.match(/^<([a-z]+)[ >]/))&&f[r[1]]||b;r=p[0];p="ignored<div>"+p[1]+c+p[2]+"</div>";"function"==typeof k.innerShiv?q.appendChild(k.innerShiv(p)):(g&&e.appendChild(q),
q.innerHTML=p,g&&q.parentNode.removeChild(q));for(;r--;)q=q.lastChild;e=a.a.W(q.lastChild.childNodes)}return e};a.a.Eb=function(b,c){a.a.rb(b);c=a.a.c(c);if(null!==c&&c!==n)if("string"!=typeof c&&(c=c.toString()),u)u(b).html(c);else for(var d=a.a.na(c,b.ownerDocument),e=0;e<d.length;e++)b.appendChild(d[e])}})();a.b("utils.parseHtmlFragment",a.a.na);a.b("utils.setHtml",a.a.Eb);a.N=function(){function b(c,e){if(c)if(8==c.nodeType){var f=a.N.pc(c.nodeValue);null!=f&&e.push({Qc:c,hd:f})}else if(1==c.nodeType)for(var f=
0,g=c.childNodes,h=g.length;f<h;f++)b(g[f],e)}var c={};return{yb:function(a){if("function"!=typeof a)throw Error("You can only pass a function to ko.memoization.memoize()");var b=(4294967296*(1+Math.random())|0).toString(16).substring(1)+(4294967296*(1+Math.random())|0).toString(16).substring(1);c[b]=a;return"\x3c!--[ko_memo:"+b+"]--\x3e"},Bc:function(a,b){var f=c[a];if(f===n)throw Error("Couldn't find any memo with ID "+a+". Perhaps it's already been unmemoized.");try{return f.apply(null,b||[]),
!0}finally{delete c[a]}},Cc:function(c,e){var f=[];b(c,f);for(var g=0,h=f.length;g<h;g++){var l=f[g].Qc,m=[l];e&&a.a.ta(m,e);a.N.Bc(f[g].hd,m);l.nodeValue="";l.parentNode&&l.parentNode.removeChild(l)}},pc:function(a){return(a=a.match(/^\[ko_memo\:(.*?)\]$/))?a[1]:null}}}();a.b("memoization",a.N);a.b("memoization.memoize",a.N.yb);a.b("memoization.unmemoize",a.N.Bc);a.b("memoization.parseMemoText",a.N.pc);a.b("memoization.unmemoizeDomNodeAndDescendants",a.N.Cc);a.Z=function(){function b(){if(e)for(var b=
e,c=0,m;g<e;)if(m=d[g++]){if(g>b){if(5E3<=++c){g=e;a.a.dc(Error("'Too much recursion' after processing "+c+" task groups."));break}b=e}try{m()}catch(k){a.a.dc(k)}}}function c(){b();g=e=d.length=0}var d=[],e=0,f=1,g=0;return{scheduler:x.MutationObserver?function(a){var b=t.createElement("div");(new MutationObserver(a)).observe(b,{attributes:!0});return function(){b.classList.toggle("foo")}}(c):t&&"onreadystatechange"in t.createElement("script")?function(a){var b=t.createElement("script");b.onreadystatechange=
function(){b.onreadystatechange=null;t.documentElement.removeChild(b);b=null;a()};t.documentElement.appendChild(b)}:function(a){setTimeout(a,0)},Za:function(b){e||a.Z.scheduler(c);d[e++]=b;return f++},cancel:function(a){a-=f-e;a>=g&&a<e&&(d[a]=null)},resetForTesting:function(){var a=e-g;g=e=d.length=0;return a},rd:b}}();a.b("tasks",a.Z);a.b("tasks.schedule",a.Z.Za);a.b("tasks.runEarly",a.Z.rd);a.Aa={throttle:function(b,c){b.throttleEvaluation=c;var d=null;return a.B({read:b,write:function(e){clearTimeout(d);
d=a.a.setTimeout(function(){b(e)},c)}})},rateLimit:function(a,c){var d,e,f;"number"==typeof c?d=c:(d=c.timeout,e=c.method);a.gb=!1;f="notifyWhenChangesStop"==e?T:S;a.Wa(function(a){return f(a,d)})},deferred:function(b,c){if(!0!==c)throw Error("The 'deferred' extender only accepts the value 'true', because it is not supported to turn deferral off once enabled.");b.gb||(b.gb=!0,b.Wa(function(c){var e,f=!1;return function(){if(!f){a.Z.cancel(e);e=a.Z.Za(c);try{f=!0,b.notifySubscribers(n,"dirty")}finally{f=
!1}}}}))},notify:function(a,c){a.equalityComparer="always"==c?null:J}};var R={undefined:1,"boolean":1,number:1,string:1};a.b("extenders",a.Aa);a.zc=function(b,c,d){this.$=b;this.jb=c;this.Pc=d;this.T=!1;a.H(this,"dispose",this.k)};a.zc.prototype.k=function(){this.T=!0;this.Pc()};a.K=function(){a.a.ab(this,D);D.ub(this)};var E="change",D={ub:function(a){a.F={change:[]};a.Qb=1},Y:function(b,c,d){var e=this;d=d||E;var f=new a.zc(e,c?b.bind(c):b,function(){a.a.Na(e.F[d],f);e.Ka&&e.Ka(d)});e.ua&&e.ua(d);
e.F[d]||(e.F[d]=[]);e.F[d].push(f);return f},notifySubscribers:function(b,c){c=c||E;c===E&&this.Kb();if(this.Ra(c)){var d=c===E&&this.Fc||this.F[c].slice(0);try{a.l.Xb();for(var e=0,f;f=d[e];++e)f.T||f.jb(b)}finally{a.l.end()}}},Pa:function(){return this.Qb},Zc:function(a){return this.Pa()!==a},Kb:function(){++this.Qb},Wa:function(b){var c=this,d=a.I(c),e,f,g,h;c.Ja||(c.Ja=c.notifySubscribers,c.notifySubscribers=U);var l=b(function(){c.Ha=!1;d&&h===c&&(h=c.Mb?c.Mb():c());var a=f||c.Ua(g,h);f=e=!1;
a&&c.Ja(g=h)});c.Pb=function(a){c.Fc=c.F[E].slice(0);c.Ha=e=!0;h=a;l()};c.Ob=function(a){e||(g=a,c.Ja(a,"beforeChange"))};c.Hc=function(){c.Ua(g,c.p(!0))&&(f=!0)}},Ra:function(a){return this.F[a]&&this.F[a].length},Xc:function(b){if(b)return this.F[b]&&this.F[b].length||0;var c=0;a.a.D(this.F,function(a,b){"dirty"!==a&&(c+=b.length)});return c},Ua:function(a,c){return!this.equalityComparer||!this.equalityComparer(a,c)},extend:function(b){var c=this;b&&a.a.D(b,function(b,e){var f=a.Aa[b];"function"==
typeof f&&(c=f(c,e)||c)});return c}};a.H(D,"subscribe",D.Y);a.H(D,"extend",D.extend);a.H(D,"getSubscriptionsCount",D.Xc);a.a.la&&a.a.$a(D,Function.prototype);a.K.fn=D;a.lc=function(a){return null!=a&&"function"==typeof a.Y&&"function"==typeof a.notifySubscribers};a.b("subscribable",a.K);a.b("isSubscribable",a.lc);a.xa=a.l=function(){function b(a){d.push(e);e=a}function c(){e=d.pop()}var d=[],e,f=0;return{Xb:b,end:c,sc:function(b){if(e){if(!a.lc(b))throw Error("Only subscribable things can act as dependencies");
e.jb.call(e.Lc,b,b.Gc||(b.Gc=++f))}},w:function(a,d,e){try{return b(),a.apply(d,e||[])}finally{c()}},Ca:function(){if(e)return e.m.Ca()},Va:function(){if(e)return e.Va}}}();a.b("computedContext",a.xa);a.b("computedContext.getDependenciesCount",a.xa.Ca);a.b("computedContext.isInitial",a.xa.Va);a.b("ignoreDependencies",a.wd=a.l.w);var F=a.a.bc("_latestValue");a.O=function(b){function c(){if(0<arguments.length)return c.Ua(c[F],arguments[0])&&(c.ia(),c[F]=arguments[0],c.ha()),this;a.l.sc(c);return c[F]}
c[F]=b;a.a.la||a.a.extend(c,a.K.fn);a.K.fn.ub(c);a.a.ab(c,B);a.options.deferUpdates&&a.Aa.deferred(c,!0);return c};var B={equalityComparer:J,p:function(){return this[F]},ha:function(){this.notifySubscribers(this[F])},ia:function(){this.notifySubscribers(this[F],"beforeChange")}};a.a.la&&a.a.$a(B,a.K.fn);var I=a.O.md="__ko_proto__";B[I]=a.O;a.Qa=function(b,c){return null===b||b===n||b[I]===n?!1:b[I]===c?!0:a.Qa(b[I],c)};a.I=function(b){return a.Qa(b,a.O)};a.Da=function(b){return"function"==typeof b&&
b[I]===a.O||"function"==typeof b&&b[I]===a.B&&b.$c?!0:!1};a.b("observable",a.O);a.b("isObservable",a.I);a.b("isWriteableObservable",a.Da);a.b("isWritableObservable",a.Da);a.b("observable.fn",B);a.H(B,"peek",B.p);a.H(B,"valueHasMutated",B.ha);a.H(B,"valueWillMutate",B.ia);a.ma=function(b){b=b||[];if("object"!=typeof b||!("length"in b))throw Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");b=a.O(b);a.a.ab(b,a.ma.fn);return b.extend({trackArrayChanges:!0})};
a.ma.fn={remove:function(b){for(var c=this.p(),d=[],e="function"!=typeof b||a.I(b)?function(a){return a===b}:b,f=0;f<c.length;f++){var g=c[f];e(g)&&(0===d.length&&this.ia(),d.push(g),c.splice(f,1),f--)}d.length&&this.ha();return d},removeAll:function(b){if(b===n){var c=this.p(),d=c.slice(0);this.ia();c.splice(0,c.length);this.ha();return d}return b?this.remove(function(c){return 0<=a.a.o(b,c)}):[]},destroy:function(b){var c=this.p(),d="function"!=typeof b||a.I(b)?function(a){return a===b}:b;this.ia();
for(var e=c.length-1;0<=e;e--)d(c[e])&&(c[e]._destroy=!0);this.ha()},destroyAll:function(b){return b===n?this.destroy(function(){return!0}):b?this.destroy(function(c){return 0<=a.a.o(b,c)}):[]},indexOf:function(b){var c=this();return a.a.o(c,b)},replace:function(a,c){var d=this.indexOf(a);0<=d&&(this.ia(),this.p()[d]=c,this.ha())}};a.a.la&&a.a.$a(a.ma.fn,a.O.fn);a.a.r("pop push reverse shift sort splice unshift".split(" "),function(b){a.ma.fn[b]=function(){var a=this.p();this.ia();this.Yb(a,b,arguments);
var d=a[b].apply(a,arguments);this.ha();return d===a?this:d}});a.a.r(["slice"],function(b){a.ma.fn[b]=function(){var a=this();return a[b].apply(a,arguments)}});a.b("observableArray",a.ma);a.Aa.trackArrayChanges=function(b,c){function d(){if(!e){e=!0;l=b.notifySubscribers;b.notifySubscribers=function(a,b){b&&b!==E||++h;return l.apply(this,arguments)};var c=[].concat(b.p()||[]);f=null;g=b.Y(function(d){d=[].concat(d||[]);if(b.Ra("arrayChange")){var e;if(!f||1<h)f=a.a.lb(c,d,b.kb);e=f}c=d;f=null;h=0;
e&&e.length&&b.notifySubscribers(e,"arrayChange")})}}b.kb={};c&&"object"==typeof c&&a.a.extend(b.kb,c);b.kb.sparse=!0;if(!b.Yb){var e=!1,f=null,g,h=0,l,m=b.ua,k=b.Ka;b.ua=function(a){m&&m.call(b,a);"arrayChange"===a&&d()};b.Ka=function(a){k&&k.call(b,a);"arrayChange"!==a||b.Ra("arrayChange")||(l&&(b.notifySubscribers=l,l=n),g.k(),e=!1)};b.Yb=function(b,c,d){function k(a,b,c){return m[m.length]={status:a,value:b,index:c}}if(e&&!h){var m=[],l=b.length,g=d.length,G=0;switch(c){case "push":G=l;case "unshift":for(c=
0;c<g;c++)k("added",d[c],G+c);break;case "pop":G=l-1;case "shift":l&&k("deleted",b[G],G);break;case "splice":c=Math.min(Math.max(0,0>d[0]?l+d[0]:d[0]),l);for(var l=1===g?l:Math.min(c+(d[1]||0),l),g=c+g-2,G=Math.max(l,g),n=[],s=[],w=2;c<G;++c,++w)c<l&&s.push(k("deleted",b[c],c)),c<g&&n.push(k("added",d[w],c));a.a.hc(s,n);break;default:return}f=m}}}};var s=a.a.bc("_state");a.m=a.B=function(b,c,d){function e(){if(0<arguments.length){if("function"===typeof f)f.apply(g.sb,arguments);else throw Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");
return this}a.l.sc(e);(g.V||g.t&&e.Sa())&&e.U();return g.M}"object"===typeof b?d=b:(d=d||{},b&&(d.read=b));if("function"!=typeof d.read)throw Error("Pass a function that returns the value of the ko.computed");var f=d.write,g={M:n,da:!0,V:!0,Ta:!1,Hb:!1,T:!1,Ya:!1,t:!1,od:d.read,sb:c||d.owner,i:d.disposeWhenNodeIsRemoved||d.i||null,ya:d.disposeWhen||d.ya,pb:null,s:{},L:0,fc:null};e[s]=g;e.$c="function"===typeof f;a.a.la||a.a.extend(e,a.K.fn);a.K.fn.ub(e);a.a.ab(e,z);d.pure?(g.Ya=!0,g.t=!0,a.a.extend(e,
Y)):d.deferEvaluation&&a.a.extend(e,Z);a.options.deferUpdates&&a.Aa.deferred(e,!0);g.i&&(g.Hb=!0,g.i.nodeType||(g.i=null));g.t||d.deferEvaluation||e.U();g.i&&e.ca()&&a.a.G.qa(g.i,g.pb=function(){e.k()});return e};var z={equalityComparer:J,Ca:function(){return this[s].L},Sb:function(a,c,d){if(this[s].Ya&&c===this)throw Error("A 'pure' computed must not be called recursively");this[s].s[a]=d;d.Ia=this[s].L++;d.pa=c.Pa()},Sa:function(){var a,c,d=this[s].s;for(a in d)if(d.hasOwnProperty(a)&&(c=d[a],this.oa&&
c.$.Ha||c.$.Zc(c.pa)))return!0},gd:function(){this.oa&&!this[s].Ta&&this.oa(!1)},ca:function(){var a=this[s];return a.V||0<a.L},qd:function(){this.Ha?this[s].V&&(this[s].da=!0):this.ec()},yc:function(a){if(a.gb&&!this[s].i){var c=a.Y(this.gd,this,"dirty"),d=a.Y(this.qd,this);return{$:a,k:function(){c.k();d.k()}}}return a.Y(this.ec,this)},ec:function(){var b=this,c=b.throttleEvaluation;c&&0<=c?(clearTimeout(this[s].fc),this[s].fc=a.a.setTimeout(function(){b.U(!0)},c)):b.oa?b.oa(!0):b.U(!0)},U:function(b){var c=
this[s],d=c.ya,e=!1;if(!c.Ta&&!c.T){if(c.i&&!a.a.qb(c.i)||d&&d()){if(!c.Hb){this.k();return}}else c.Hb=!1;c.Ta=!0;try{e=this.Vc(b)}finally{c.Ta=!1}c.L||this.k();return e}},Vc:function(b){var c=this[s],d=!1,e=c.Ya?n:!c.L,f={Mc:this,Oa:c.s,ob:c.L};a.l.Xb({Lc:f,jb:W,m:this,Va:e});c.s={};c.L=0;f=this.Uc(c,f);this.Ua(c.M,f)&&(c.t||this.notifySubscribers(c.M,"beforeChange"),c.M=f,c.t?this.Kb():b&&this.notifySubscribers(c.M),d=!0);e&&this.notifySubscribers(c.M,"awake");return d},Uc:function(b,c){try{var d=
b.od;return b.sb?d.call(b.sb):d()}finally{a.l.end(),c.ob&&!b.t&&a.a.D(c.Oa,V),b.da=b.V=!1}},p:function(a){var c=this[s];(c.V&&(a||!c.L)||c.t&&this.Sa())&&this.U();return c.M},Wa:function(b){a.K.fn.Wa.call(this,b);this.Mb=function(){this[s].da?this.U():this[s].V=!1;return this[s].M};this.oa=function(a){this.Ob(this[s].M);this[s].V=!0;a&&(this[s].da=!0);this.Pb(this)}},k:function(){var b=this[s];!b.t&&b.s&&a.a.D(b.s,function(a,b){b.k&&b.k()});b.i&&b.pb&&a.a.G.tc(b.i,b.pb);b.s=null;b.L=0;b.T=!0;b.da=
!1;b.V=!1;b.t=!1;b.i=null}},Y={ua:function(b){var c=this,d=c[s];if(!d.T&&d.t&&"change"==b){d.t=!1;if(d.da||c.Sa())d.s=null,d.L=0,c.U()&&c.Kb();else{var e=[];a.a.D(d.s,function(a,b){e[b.Ia]=a});a.a.r(e,function(a,b){var e=d.s[a],l=c.yc(e.$);l.Ia=b;l.pa=e.pa;d.s[a]=l})}d.T||c.notifySubscribers(d.M,"awake")}},Ka:function(b){var c=this[s];c.T||"change"!=b||this.Ra("change")||(a.a.D(c.s,function(a,b){b.k&&(c.s[a]={$:b.$,Ia:b.Ia,pa:b.pa},b.k())}),c.t=!0,this.notifySubscribers(n,"asleep"))},Pa:function(){var b=
this[s];b.t&&(b.da||this.Sa())&&this.U();return a.K.fn.Pa.call(this)}},Z={ua:function(a){"change"!=a&&"beforeChange"!=a||this.p()}};a.a.la&&a.a.$a(z,a.K.fn);var P=a.O.md;a.m[P]=a.O;z[P]=a.m;a.bd=function(b){return a.Qa(b,a.m)};a.cd=function(b){return a.Qa(b,a.m)&&b[s]&&b[s].Ya};a.b("computed",a.m);a.b("dependentObservable",a.m);a.b("isComputed",a.bd);a.b("isPureComputed",a.cd);a.b("computed.fn",z);a.H(z,"peek",z.p);a.H(z,"dispose",z.k);a.H(z,"isActive",z.ca);a.H(z,"getDependenciesCount",z.Ca);a.rc=
function(b,c){if("function"===typeof b)return a.m(b,c,{pure:!0});b=a.a.extend({},b);b.pure=!0;return a.m(b,c)};a.b("pureComputed",a.rc);(function(){function b(a,f,g){g=g||new d;a=f(a);if("object"!=typeof a||null===a||a===n||a instanceof RegExp||a instanceof Date||a instanceof String||a instanceof Number||a instanceof Boolean)return a;var h=a instanceof Array?[]:{};g.save(a,h);c(a,function(c){var d=f(a[c]);switch(typeof d){case "boolean":case "number":case "string":case "function":h[c]=d;break;case "object":case "undefined":var k=
g.get(d);h[c]=k!==n?k:b(d,f,g)}});return h}function c(a,b){if(a instanceof Array){for(var c=0;c<a.length;c++)b(c);"function"==typeof a.toJSON&&b("toJSON")}else for(c in a)b(c)}function d(){this.keys=[];this.Lb=[]}a.Ac=function(c){if(0==arguments.length)throw Error("When calling ko.toJS, pass the object you want to convert.");return b(c,function(b){for(var c=0;a.I(b)&&10>c;c++)b=b();return b})};a.toJSON=function(b,c,d){b=a.Ac(b);return a.a.Gb(b,c,d)};d.prototype={save:function(b,c){var d=a.a.o(this.keys,
b);0<=d?this.Lb[d]=c:(this.keys.push(b),this.Lb.push(c))},get:function(b){b=a.a.o(this.keys,b);return 0<=b?this.Lb[b]:n}}})();a.b("toJS",a.Ac);a.b("toJSON",a.toJSON);(function(){a.j={u:function(b){switch(a.a.A(b)){case "option":return!0===b.__ko__hasDomDataOptionValue__?a.a.e.get(b,a.d.options.zb):7>=a.a.C?b.getAttributeNode("value")&&b.getAttributeNode("value").specified?b.value:b.text:b.value;case "select":return 0<=b.selectedIndex?a.j.u(b.options[b.selectedIndex]):n;default:return b.value}},ja:function(b,
c,d){switch(a.a.A(b)){case "option":switch(typeof c){case "string":a.a.e.set(b,a.d.options.zb,n);"__ko__hasDomDataOptionValue__"in b&&delete b.__ko__hasDomDataOptionValue__;b.value=c;break;default:a.a.e.set(b,a.d.options.zb,c),b.__ko__hasDomDataOptionValue__=!0,b.value="number"===typeof c?c:""}break;case "select":if(""===c||null===c)c=n;for(var e=-1,f=0,g=b.options.length,h;f<g;++f)if(h=a.j.u(b.options[f]),h==c||""==h&&c===n){e=f;break}if(d||0<=e||c===n&&1<b.size)b.selectedIndex=e;break;default:if(null===
c||c===n)c="";b.value=c}}}})();a.b("selectExtensions",a.j);a.b("selectExtensions.readValue",a.j.u);a.b("selectExtensions.writeValue",a.j.ja);a.h=function(){function b(b){b=a.a.cb(b);123===b.charCodeAt(0)&&(b=b.slice(1,-1));var c=[],d=b.match(e),r,h=[],p=0;if(d){d.push(",");for(var A=0,y;y=d[A];++A){var v=y.charCodeAt(0);if(44===v){if(0>=p){c.push(r&&h.length?{key:r,value:h.join("")}:{unknown:r||h.join("")});r=p=0;h=[];continue}}else if(58===v){if(!p&&!r&&1===h.length){r=h.pop();continue}}else 47===
v&&A&&1<y.length?(v=d[A-1].match(f))&&!g[v[0]]&&(b=b.substr(b.indexOf(y)+1),d=b.match(e),d.push(","),A=-1,y="/"):40===v||123===v||91===v?++p:41===v||125===v||93===v?--p:r||h.length||34!==v&&39!==v||(y=y.slice(1,-1));h.push(y)}}return c}var c=["true","false","null","undefined"],d=/^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i,e=RegExp("\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*'|/(?:[^/\\\\]|\\\\.)*/w*|[^\\s:,/][^,\"'{}()/:[\\]]*[^\\s,\"'{}()/:[\\]]|[^\\s]","g"),f=/[\])"'A-Za-z0-9_$]+$/,
g={"in":1,"return":1,"typeof":1},h={};return{va:[],ga:h,Ab:b,Xa:function(e,m){function k(b,e){var m;if(!A){var l=a.getBindingHandler(b);if(l&&l.preprocess&&!(e=l.preprocess(e,b,k)))return;if(l=h[b])m=e,0<=a.a.o(c,m)?m=!1:(l=m.match(d),m=null===l?!1:l[1]?"Object("+l[1]+")"+l[2]:m),l=m;l&&g.push("'"+b+"':function(_z){"+m+"=_z}")}p&&(e="function(){return "+e+" }");f.push("'"+b+"':"+e)}m=m||{};var f=[],g=[],p=m.valueAccessors,A=m.bindingParams,y="string"===typeof e?b(e):e;a.a.r(y,function(a){k(a.key||
a.unknown,a.value)});g.length&&k("_ko_property_writers","{"+g.join(",")+" }");return f.join(",")},fd:function(a,b){for(var c=0;c<a.length;c++)if(a[c].key==b)return!0;return!1},Ga:function(b,c,d,e,f){if(b&&a.I(b))!a.Da(b)||f&&b.p()===e||b(e);else if((b=c.get("_ko_property_writers"))&&b[d])b[d](e)}}}();a.b("expressionRewriting",a.h);a.b("expressionRewriting.bindingRewriteValidators",a.h.va);a.b("expressionRewriting.parseObjectLiteral",a.h.Ab);a.b("expressionRewriting.preProcessBindings",a.h.Xa);a.b("expressionRewriting._twoWayBindings",
a.h.ga);a.b("jsonExpressionRewriting",a.h);a.b("jsonExpressionRewriting.insertPropertyAccessorsIntoJson",a.h.Xa);(function(){function b(a){return 8==a.nodeType&&g.test(f?a.text:a.nodeValue)}function c(a){return 8==a.nodeType&&h.test(f?a.text:a.nodeValue)}function d(a,d){for(var e=a,f=1,l=[];e=e.nextSibling;){if(c(e)&&(f--,0===f))return l;l.push(e);b(e)&&f++}if(!d)throw Error("Cannot find closing comment tag to match: "+a.nodeValue);return null}function e(a,b){var c=d(a,b);return c?0<c.length?c[c.length-
1].nextSibling:a.nextSibling:null}var f=t&&"\x3c!--test--\x3e"===t.createComment("test").text,g=f?/^\x3c!--\s*ko(?:\s+([\s\S]+))?\s*--\x3e$/:/^\s*ko(?:\s+([\s\S]+))?\s*$/,h=f?/^\x3c!--\s*\/ko\s*--\x3e$/:/^\s*\/ko\s*$/,l={ul:!0,ol:!0};a.f={aa:{},childNodes:function(a){return b(a)?d(a):a.childNodes},za:function(c){if(b(c)){c=a.f.childNodes(c);for(var d=0,e=c.length;d<e;d++)a.removeNode(c[d])}else a.a.rb(c)},fa:function(c,d){if(b(c)){a.f.za(c);for(var e=c.nextSibling,f=0,l=d.length;f<l;f++)e.parentNode.insertBefore(d[f],
e)}else a.a.fa(c,d)},qc:function(a,c){b(a)?a.parentNode.insertBefore(c,a.nextSibling):a.firstChild?a.insertBefore(c,a.firstChild):a.appendChild(c)},kc:function(c,d,e){e?b(c)?c.parentNode.insertBefore(d,e.nextSibling):e.nextSibling?c.insertBefore(d,e.nextSibling):c.appendChild(d):a.f.qc(c,d)},firstChild:function(a){return b(a)?!a.nextSibling||c(a.nextSibling)?null:a.nextSibling:a.firstChild},nextSibling:function(a){b(a)&&(a=e(a));return a.nextSibling&&c(a.nextSibling)?null:a.nextSibling},Yc:b,vd:function(a){return(a=
(f?a.text:a.nodeValue).match(g))?a[1]:null},oc:function(d){if(l[a.a.A(d)]){var k=d.firstChild;if(k){do if(1===k.nodeType){var f;f=k.firstChild;var g=null;if(f){do if(g)g.push(f);else if(b(f)){var h=e(f,!0);h?f=h:g=[f]}else c(f)&&(g=[f]);while(f=f.nextSibling)}if(f=g)for(g=k.nextSibling,h=0;h<f.length;h++)g?d.insertBefore(f[h],g):d.appendChild(f[h])}while(k=k.nextSibling)}}}}})();a.b("virtualElements",a.f);a.b("virtualElements.allowedBindings",a.f.aa);a.b("virtualElements.emptyNode",a.f.za);a.b("virtualElements.insertAfter",
a.f.kc);a.b("virtualElements.prepend",a.f.qc);a.b("virtualElements.setDomNodeChildren",a.f.fa);(function(){a.S=function(){this.Kc={}};a.a.extend(a.S.prototype,{nodeHasBindings:function(b){switch(b.nodeType){case 1:return null!=b.getAttribute("data-bind")||a.g.getComponentNameForNode(b);case 8:return a.f.Yc(b);default:return!1}},getBindings:function(b,c){var d=this.getBindingsString(b,c),d=d?this.parseBindingsString(d,c,b):null;return a.g.Rb(d,b,c,!1)},getBindingAccessors:function(b,c){var d=this.getBindingsString(b,
c),d=d?this.parseBindingsString(d,c,b,{valueAccessors:!0}):null;return a.g.Rb(d,b,c,!0)},getBindingsString:function(b){switch(b.nodeType){case 1:return b.getAttribute("data-bind");case 8:return a.f.vd(b);default:return null}},parseBindingsString:function(b,c,d,e){try{var f=this.Kc,g=b+(e&&e.valueAccessors||""),h;if(!(h=f[g])){var l,m="with($context){with($data||{}){return{"+a.h.Xa(b,e)+"}}}";l=new Function("$context","$element",m);h=f[g]=l}return h(c,d)}catch(k){throw k.message="Unable to parse bindings.\nBindings value: "+
b+"\nMessage: "+k.message,k;}}});a.S.instance=new a.S})();a.b("bindingProvider",a.S);(function(){function b(a){return function(){return a}}function c(a){return a()}function d(b){return a.a.Ea(a.l.w(b),function(a,c){return function(){return b()[c]}})}function e(c,e,k){return"function"===typeof c?d(c.bind(null,e,k)):a.a.Ea(c,b)}function f(a,b){return d(this.getBindings.bind(this,a,b))}function g(b,c,d){var e,k=a.f.firstChild(c),f=a.S.instance,m=f.preprocessNode;if(m){for(;e=k;)k=a.f.nextSibling(e),
m.call(f,e);k=a.f.firstChild(c)}for(;e=k;)k=a.f.nextSibling(e),h(b,e,d)}function h(b,c,d){var e=!0,k=1===c.nodeType;k&&a.f.oc(c);if(k&&d||a.S.instance.nodeHasBindings(c))e=m(c,null,b,d).shouldBindDescendants;e&&!r[a.a.A(c)]&&g(b,c,!k)}function l(b){var c=[],d={},e=[];a.a.D(b,function X(k){if(!d[k]){var f=a.getBindingHandler(k);f&&(f.after&&(e.push(k),a.a.r(f.after,function(c){if(b[c]){if(-1!==a.a.o(e,c))throw Error("Cannot combine the following bindings, because they have a cyclic dependency: "+e.join(", "));
X(c)}}),e.length--),c.push({key:k,jc:f}));d[k]=!0}});return c}function m(b,d,e,k){var m=a.a.e.get(b,q);if(!d){if(m)throw Error("You cannot apply bindings multiple times to the same element.");a.a.e.set(b,q,!0)}!m&&k&&a.xc(b,e);var g;if(d&&"function"!==typeof d)g=d;else{var h=a.S.instance,r=h.getBindingAccessors||f,p=a.B(function(){(g=d?d(e,b):r.call(h,b,e))&&e.Q&&e.Q();return g},null,{i:b});g&&p.ca()||(p=null)}var s;if(g){var t=p?function(a){return function(){return c(p()[a])}}:function(a){return g[a]},
u=function(){return a.a.Ea(p?p():g,c)};u.get=function(a){return g[a]&&c(t(a))};u.has=function(a){return a in g};k=l(g);a.a.r(k,function(c){var d=c.jc.init,k=c.jc.update,f=c.key;if(8===b.nodeType&&!a.f.aa[f])throw Error("The binding '"+f+"' cannot be used with virtual elements");try{"function"==typeof d&&a.l.w(function(){var a=d(b,t(f),u,e.$data,e);if(a&&a.controlsDescendantBindings){if(s!==n)throw Error("Multiple bindings ("+s+" and "+f+") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.");
s=f}}),"function"==typeof k&&a.B(function(){k(b,t(f),u,e.$data,e)},null,{i:b})}catch(m){throw m.message='Unable to process binding "'+f+": "+g[f]+'"\nMessage: '+m.message,m;}})}return{shouldBindDescendants:s===n}}function k(b){return b&&b instanceof a.R?b:new a.R(b)}a.d={};var r={script:!0,textarea:!0,template:!0};a.getBindingHandler=function(b){return a.d[b]};a.R=function(b,c,d,e,k){function f(){var k=g?b():b,m=a.a.c(k);c?(c.Q&&c.Q(),a.a.extend(l,c),l.Q=r):(l.$parents=[],l.$root=m,l.ko=a);l.$rawData=
k;l.$data=m;d&&(l[d]=m);e&&e(l,c,m);return l.$data}function m(){return h&&!a.a.Tb(h)}var l=this,g="function"==typeof b&&!a.I(b),h,r;k&&k.exportDependencies?f():(r=a.B(f,null,{ya:m,i:!0}),r.ca()&&(l.Q=r,r.equalityComparer=null,h=[],r.Dc=function(b){h.push(b);a.a.G.qa(b,function(b){a.a.Na(h,b);h.length||(r.k(),l.Q=r=n)})}))};a.R.prototype.createChildContext=function(b,c,d,e){return new a.R(b,this,c,function(a,b){a.$parentContext=b;a.$parent=b.$data;a.$parents=(b.$parents||[]).slice(0);a.$parents.unshift(a.$parent);
d&&d(a)},e)};a.R.prototype.extend=function(b){return new a.R(this.Q||this.$data,this,null,function(c,d){c.$rawData=d.$rawData;a.a.extend(c,"function"==typeof b?b():b)})};a.R.prototype.ac=function(a,b){return this.createChildContext(a,b,null,{exportDependencies:!0})};var q=a.a.e.J(),p=a.a.e.J();a.xc=function(b,c){if(2==arguments.length)a.a.e.set(b,p,c),c.Q&&c.Q.Dc(b);else return a.a.e.get(b,p)};a.La=function(b,c,d){1===b.nodeType&&a.f.oc(b);return m(b,c,k(d),!0)};a.Ic=function(b,c,d){d=k(d);return a.La(b,
e(c,d,b),d)};a.hb=function(a,b){1!==b.nodeType&&8!==b.nodeType||g(k(a),b,!0)};a.Ub=function(a,b){!u&&x.jQuery&&(u=x.jQuery);if(b&&1!==b.nodeType&&8!==b.nodeType)throw Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");b=b||x.document.body;h(k(a),b,!0)};a.nb=function(b){switch(b.nodeType){case 1:case 8:var c=a.xc(b);if(c)return c;if(b.parentNode)return a.nb(b.parentNode)}return n};a.Oc=function(b){return(b=a.nb(b))?b.$data:n};a.b("bindingHandlers",
a.d);a.b("applyBindings",a.Ub);a.b("applyBindingsToDescendants",a.hb);a.b("applyBindingAccessorsToNode",a.La);a.b("applyBindingsToNode",a.Ic);a.b("contextFor",a.nb);a.b("dataFor",a.Oc)})();(function(b){function c(c,e){var m=f.hasOwnProperty(c)?f[c]:b,k;m?m.Y(e):(m=f[c]=new a.K,m.Y(e),d(c,function(b,d){var e=!(!d||!d.synchronous);g[c]={definition:b,dd:e};delete f[c];k||e?m.notifySubscribers(b):a.Z.Za(function(){m.notifySubscribers(b)})}),k=!0)}function d(a,b){e("getConfig",[a],function(c){c?e("loadComponent",
[a,c],function(a){b(a,c)}):b(null,null)})}function e(c,d,f,k){k||(k=a.g.loaders.slice(0));var g=k.shift();if(g){var q=g[c];if(q){var p=!1;if(q.apply(g,d.concat(function(a){p?f(null):null!==a?f(a):e(c,d,f,k)}))!==b&&(p=!0,!g.suppressLoaderExceptions))throw Error("Component loaders must supply values by invoking the callback, not by returning values synchronously.");}else e(c,d,f,k)}else f(null)}var f={},g={};a.g={get:function(d,e){var f=g.hasOwnProperty(d)?g[d]:b;f?f.dd?a.l.w(function(){e(f.definition)}):
a.Z.Za(function(){e(f.definition)}):c(d,e)},$b:function(a){delete g[a]},Nb:e};a.g.loaders=[];a.b("components",a.g);a.b("components.get",a.g.get);a.b("components.clearCachedDefinition",a.g.$b)})();(function(){function b(b,c,d,e){function g(){0===--y&&e(h)}var h={},y=2,v=d.template;d=d.viewModel;v?f(c,v,function(c){a.g.Nb("loadTemplate",[b,c],function(a){h.template=a;g()})}):g();d?f(c,d,function(c){a.g.Nb("loadViewModel",[b,c],function(a){h[l]=a;g()})}):g()}function c(a,b,d){if("function"===typeof b)d(function(a){return new b(a)});
else if("function"===typeof b[l])d(b[l]);else if("instance"in b){var e=b.instance;d(function(){return e})}else"viewModel"in b?c(a,b.viewModel,d):a("Unknown viewModel value: "+b)}function d(b){switch(a.a.A(b)){case "script":return a.a.na(b.text);case "textarea":return a.a.na(b.value);case "template":if(e(b.content))return a.a.wa(b.content.childNodes)}return a.a.wa(b.childNodes)}function e(a){return x.DocumentFragment?a instanceof DocumentFragment:a&&11===a.nodeType}function f(a,b,c){"string"===typeof b.require?
O||x.require?(O||x.require)([b.require],c):a("Uses require, but no AMD loader is present"):c(b)}function g(a){return function(b){throw Error("Component '"+a+"': "+b);}}var h={};a.g.register=function(b,c){if(!c)throw Error("Invalid configuration for "+b);if(a.g.wb(b))throw Error("Component "+b+" is already registered");h[b]=c};a.g.wb=function(a){return h.hasOwnProperty(a)};a.g.ud=function(b){delete h[b];a.g.$b(b)};a.g.cc={getConfig:function(a,b){b(h.hasOwnProperty(a)?h[a]:null)},loadComponent:function(a,
c,d){var e=g(a);f(e,c,function(c){b(a,e,c,d)})},loadTemplate:function(b,c,f){b=g(b);if("string"===typeof c)f(a.a.na(c));else if(c instanceof Array)f(c);else if(e(c))f(a.a.W(c.childNodes));else if(c.element)if(c=c.element,x.HTMLElement?c instanceof HTMLElement:c&&c.tagName&&1===c.nodeType)f(d(c));else if("string"===typeof c){var l=t.getElementById(c);l?f(d(l)):b("Cannot find element with ID "+c)}else b("Unknown element type: "+c);else b("Unknown template value: "+c)},loadViewModel:function(a,b,d){c(g(a),
b,d)}};var l="createViewModel";a.b("components.register",a.g.register);a.b("components.isRegistered",a.g.wb);a.b("components.unregister",a.g.ud);a.b("components.defaultLoader",a.g.cc);a.g.loaders.push(a.g.cc);a.g.Ec=h})();(function(){function b(b,e){var f=b.getAttribute("params");if(f){var f=c.parseBindingsString(f,e,b,{valueAccessors:!0,bindingParams:!0}),f=a.a.Ea(f,function(c){return a.m(c,null,{i:b})}),g=a.a.Ea(f,function(c){var e=c.p();return c.ca()?a.m({read:function(){return a.a.c(c())},write:a.Da(e)&&
function(a){c()(a)},i:b}):e});g.hasOwnProperty("$raw")||(g.$raw=f);return g}return{$raw:{}}}a.g.getComponentNameForNode=function(b){var c=a.a.A(b);if(a.g.wb(c)&&(-1!=c.indexOf("-")||"[object HTMLUnknownElement]"==""+b||8>=a.a.C&&b.tagName===c))return c};a.g.Rb=function(c,e,f,g){if(1===e.nodeType){var h=a.g.getComponentNameForNode(e);if(h){c=c||{};if(c.component)throw Error('Cannot use the "component" binding on a custom element matching a component');var l={name:h,params:b(e,f)};c.component=g?function(){return l}:
l}}return c};var c=new a.S;9>a.a.C&&(a.g.register=function(a){return function(b){t.createElement(b);return a.apply(this,arguments)}}(a.g.register),t.createDocumentFragment=function(b){return function(){var c=b(),f=a.g.Ec,g;for(g in f)f.hasOwnProperty(g)&&c.createElement(g);return c}}(t.createDocumentFragment))})();(function(b){function c(b,c,d){c=c.template;if(!c)throw Error("Component '"+b+"' has no template");b=a.a.wa(c);a.f.fa(d,b)}function d(a,b,c,d){var e=a.createViewModel;return e?e.call(a,
d,{element:b,templateNodes:c}):d}var e=0;a.d.component={init:function(f,g,h,l,m){function k(){var a=r&&r.dispose;"function"===typeof a&&a.call(r);q=r=null}var r,q,p=a.a.W(a.f.childNodes(f));a.a.G.qa(f,k);a.m(function(){var l=a.a.c(g()),h,v;"string"===typeof l?h=l:(h=a.a.c(l.name),v=a.a.c(l.params));if(!h)throw Error("No component name specified");var n=q=++e;a.g.get(h,function(e){if(q===n){k();if(!e)throw Error("Unknown component '"+h+"'");c(h,e,f);var l=d(e,f,p,v);e=m.createChildContext(l,b,function(a){a.$component=
l;a.$componentTemplateNodes=p});r=l;a.hb(e,f)}})},null,{i:f});return{controlsDescendantBindings:!0}}};a.f.aa.component=!0})();var Q={"class":"className","for":"htmlFor"};a.d.attr={update:function(b,c){var d=a.a.c(c())||{};a.a.D(d,function(c,d){d=a.a.c(d);var g=!1===d||null===d||d===n;g&&b.removeAttribute(c);8>=a.a.C&&c in Q?(c=Q[c],g?b.removeAttribute(c):b[c]=d):g||b.setAttribute(c,d.toString());"name"===c&&a.a.vc(b,g?"":d.toString())})}};(function(){a.d.checked={after:["value","attr"],init:function(b,
c,d){function e(){var e=b.checked,f=p?g():e;if(!a.xa.Va()&&(!l||e)){var h=a.l.w(c);if(k){var m=r?h.p():h;q!==f?(e&&(a.a.ra(m,f,!0),a.a.ra(m,q,!1)),q=f):a.a.ra(m,f,e);r&&a.Da(h)&&h(m)}else a.h.Ga(h,d,"checked",f,!0)}}function f(){var d=a.a.c(c());b.checked=k?0<=a.a.o(d,g()):h?d:g()===d}var g=a.rc(function(){return d.has("checkedValue")?a.a.c(d.get("checkedValue")):d.has("value")?a.a.c(d.get("value")):b.value}),h="checkbox"==b.type,l="radio"==b.type;if(h||l){var m=c(),k=h&&a.a.c(m)instanceof Array,
r=!(k&&m.push&&m.splice),q=k?g():n,p=l||k;l&&!b.name&&a.d.uniqueName.init(b,function(){return!0});a.m(e,null,{i:b});a.a.q(b,"click",e);a.m(f,null,{i:b});m=n}}};a.h.ga.checked=!0;a.d.checkedValue={update:function(b,c){b.value=a.a.c(c())}}})();a.d.css={update:function(b,c){var d=a.a.c(c());null!==d&&"object"==typeof d?a.a.D(d,function(c,d){d=a.a.c(d);a.a.fb(b,c,d)}):(d=a.a.cb(String(d||"")),a.a.fb(b,b.__ko__cssValue,!1),b.__ko__cssValue=d,a.a.fb(b,d,!0))}};a.d.enable={update:function(b,c){var d=a.a.c(c());
d&&b.disabled?b.removeAttribute("disabled"):d||b.disabled||(b.disabled=!0)}};a.d.disable={update:function(b,c){a.d.enable.update(b,function(){return!a.a.c(c())})}};a.d.event={init:function(b,c,d,e,f){var g=c()||{};a.a.D(g,function(g){"string"==typeof g&&a.a.q(b,g,function(b){var m,k=c()[g];if(k){try{var r=a.a.W(arguments);e=f.$data;r.unshift(e);m=k.apply(e,r)}finally{!0!==m&&(b.preventDefault?b.preventDefault():b.returnValue=!1)}!1===d.get(g+"Bubble")&&(b.cancelBubble=!0,b.stopPropagation&&b.stopPropagation())}})})}};
a.d.foreach={mc:function(b){return function(){var c=b(),d=a.a.Bb(c);if(!d||"number"==typeof d.length)return{foreach:c,templateEngine:a.X.vb};a.a.c(c);return{foreach:d.data,as:d.as,includeDestroyed:d.includeDestroyed,afterAdd:d.afterAdd,beforeRemove:d.beforeRemove,afterRender:d.afterRender,beforeMove:d.beforeMove,afterMove:d.afterMove,templateEngine:a.X.vb}}},init:function(b,c){return a.d.template.init(b,a.d.foreach.mc(c))},update:function(b,c,d,e,f){return a.d.template.update(b,a.d.foreach.mc(c),
d,e,f)}};a.h.va.foreach=!1;a.f.aa.foreach=!0;a.d.hasfocus={init:function(b,c,d){function e(e){b.__ko_hasfocusUpdating=!0;var f=b.ownerDocument;if("activeElement"in f){var g;try{g=f.activeElement}catch(k){g=f.body}e=g===b}f=c();a.h.Ga(f,d,"hasfocus",e,!0);b.__ko_hasfocusLastValue=e;b.__ko_hasfocusUpdating=!1}var f=e.bind(null,!0),g=e.bind(null,!1);a.a.q(b,"focus",f);a.a.q(b,"focusin",f);a.a.q(b,"blur",g);a.a.q(b,"focusout",g)},update:function(b,c){var d=!!a.a.c(c());b.__ko_hasfocusUpdating||b.__ko_hasfocusLastValue===
d||(d?b.focus():b.blur(),!d&&b.__ko_hasfocusLastValue&&b.ownerDocument.body.focus(),a.l.w(a.a.Fa,null,[b,d?"focusin":"focusout"]))}};a.h.ga.hasfocus=!0;a.d.hasFocus=a.d.hasfocus;a.h.ga.hasFocus=!0;a.d.html={init:function(){return{controlsDescendantBindings:!0}},update:function(b,c){a.a.Eb(b,c())}};K("if");K("ifnot",!1,!0);K("with",!0,!1,function(a,c){return a.ac(c)});var L={};a.d.options={init:function(b){if("select"!==a.a.A(b))throw Error("options binding applies only to SELECT elements");for(;0<
b.length;)b.remove(0);return{controlsDescendantBindings:!0}},update:function(b,c,d){function e(){return a.a.Ma(b.options,function(a){return a.selected})}function f(a,b,c){var d=typeof b;return"function"==d?b(a):"string"==d?a[b]:c}function g(c,e){if(A&&k)a.j.ja(b,a.a.c(d.get("value")),!0);else if(p.length){var f=0<=a.a.o(p,a.j.u(e[0]));a.a.wc(e[0],f);A&&!f&&a.l.w(a.a.Fa,null,[b,"change"])}}var h=b.multiple,l=0!=b.length&&h?b.scrollTop:null,m=a.a.c(c()),k=d.get("valueAllowUnset")&&d.has("value"),r=
d.get("optionsIncludeDestroyed");c={};var q,p=[];k||(h?p=a.a.ib(e(),a.j.u):0<=b.selectedIndex&&p.push(a.j.u(b.options[b.selectedIndex])));m&&("undefined"==typeof m.length&&(m=[m]),q=a.a.Ma(m,function(b){return r||b===n||null===b||!a.a.c(b._destroy)}),d.has("optionsCaption")&&(m=a.a.c(d.get("optionsCaption")),null!==m&&m!==n&&q.unshift(L)));var A=!1;c.beforeRemove=function(a){b.removeChild(a)};m=g;d.has("optionsAfterRender")&&"function"==typeof d.get("optionsAfterRender")&&(m=function(b,c){g(0,c);
a.l.w(d.get("optionsAfterRender"),null,[c[0],b!==L?b:n])});a.a.Db(b,q,function(c,e,g){g.length&&(p=!k&&g[0].selected?[a.j.u(g[0])]:[],A=!0);e=b.ownerDocument.createElement("option");c===L?(a.a.bb(e,d.get("optionsCaption")),a.j.ja(e,n)):(g=f(c,d.get("optionsValue"),c),a.j.ja(e,a.a.c(g)),c=f(c,d.get("optionsText"),g),a.a.bb(e,c));return[e]},c,m);a.l.w(function(){k?a.j.ja(b,a.a.c(d.get("value")),!0):(h?p.length&&e().length<p.length:p.length&&0<=b.selectedIndex?a.j.u(b.options[b.selectedIndex])!==p[0]:
p.length||0<=b.selectedIndex)&&a.a.Fa(b,"change")});a.a.Sc(b);l&&20<Math.abs(l-b.scrollTop)&&(b.scrollTop=l)}};a.d.options.zb=a.a.e.J();a.d.selectedOptions={after:["options","foreach"],init:function(b,c,d){a.a.q(b,"change",function(){var e=c(),f=[];a.a.r(b.getElementsByTagName("option"),function(b){b.selected&&f.push(a.j.u(b))});a.h.Ga(e,d,"selectedOptions",f)})},update:function(b,c){if("select"!=a.a.A(b))throw Error("values binding applies only to SELECT elements");var d=a.a.c(c()),e=b.scrollTop;
d&&"number"==typeof d.length&&a.a.r(b.getElementsByTagName("option"),function(b){var c=0<=a.a.o(d,a.j.u(b));b.selected!=c&&a.a.wc(b,c)});b.scrollTop=e}};a.h.ga.selectedOptions=!0;a.d.style={update:function(b,c){var d=a.a.c(c()||{});a.a.D(d,function(c,d){d=a.a.c(d);if(null===d||d===n||!1===d)d="";b.style[c]=d})}};a.d.submit={init:function(b,c,d,e,f){if("function"!=typeof c())throw Error("The value for a submit binding must be a function");a.a.q(b,"submit",function(a){var d,e=c();try{d=e.call(f.$data,
b)}finally{!0!==d&&(a.preventDefault?a.preventDefault():a.returnValue=!1)}})}};a.d.text={init:function(){return{controlsDescendantBindings:!0}},update:function(b,c){a.a.bb(b,c())}};a.f.aa.text=!0;(function(){if(x&&x.navigator)var b=function(a){if(a)return parseFloat(a[1])},c=x.opera&&x.opera.version&&parseInt(x.opera.version()),d=x.navigator.userAgent,e=b(d.match(/^(?:(?!chrome).)*version\/([^ ]*) safari/i)),f=b(d.match(/Firefox\/([^ ]*)/));if(10>a.a.C)var g=a.a.e.J(),h=a.a.e.J(),l=function(b){var c=
this.activeElement;(c=c&&a.a.e.get(c,h))&&c(b)},m=function(b,c){var d=b.ownerDocument;a.a.e.get(d,g)||(a.a.e.set(d,g,!0),a.a.q(d,"selectionchange",l));a.a.e.set(b,h,c)};a.d.textInput={init:function(b,d,g){function l(c,d){a.a.q(b,c,d)}function h(){var c=a.a.c(d());if(null===c||c===n)c="";u!==n&&c===u?a.a.setTimeout(h,4):b.value!==c&&(s=c,b.value=c)}function y(){t||(u=b.value,t=a.a.setTimeout(v,4))}function v(){clearTimeout(t);u=t=n;var c=b.value;s!==c&&(s=c,a.h.Ga(d(),g,"textInput",c))}var s=b.value,
t,u,x=9==a.a.C?y:v;10>a.a.C?(l("propertychange",function(a){"value"===a.propertyName&&x(a)}),8==a.a.C&&(l("keyup",v),l("keydown",v)),8<=a.a.C&&(m(b,x),l("dragend",y))):(l("input",v),5>e&&"textarea"===a.a.A(b)?(l("keydown",y),l("paste",y),l("cut",y)):11>c?l("keydown",y):4>f&&(l("DOMAutoComplete",v),l("dragdrop",v),l("drop",v)));l("change",v);a.m(h,null,{i:b})}};a.h.ga.textInput=!0;a.d.textinput={preprocess:function(a,b,c){c("textInput",a)}}})();a.d.uniqueName={init:function(b,c){if(c()){var d="ko_unique_"+
++a.d.uniqueName.Nc;a.a.vc(b,d)}}};a.d.uniqueName.Nc=0;a.d.value={after:["options","foreach"],init:function(b,c,d){if("input"!=b.tagName.toLowerCase()||"checkbox"!=b.type&&"radio"!=b.type){var e=["change"],f=d.get("valueUpdate"),g=!1,h=null;f&&("string"==typeof f&&(f=[f]),a.a.ta(e,f),e=a.a.Wb(e));var l=function(){h=null;g=!1;var e=c(),f=a.j.u(b);a.h.Ga(e,d,"value",f)};!a.a.C||"input"!=b.tagName.toLowerCase()||"text"!=b.type||"off"==b.autocomplete||b.form&&"off"==b.form.autocomplete||-1!=a.a.o(e,"propertychange")||
(a.a.q(b,"propertychange",function(){g=!0}),a.a.q(b,"focus",function(){g=!1}),a.a.q(b,"blur",function(){g&&l()}));a.a.r(e,function(c){var d=l;a.a.sd(c,"after")&&(d=function(){h=a.j.u(b);a.a.setTimeout(l,0)},c=c.substring(5));a.a.q(b,c,d)});var m=function(){var e=a.a.c(c()),f=a.j.u(b);if(null!==h&&e===h)a.a.setTimeout(m,0);else if(e!==f)if("select"===a.a.A(b)){var g=d.get("valueAllowUnset"),f=function(){a.j.ja(b,e,g)};f();g||e===a.j.u(b)?a.a.setTimeout(f,0):a.l.w(a.a.Fa,null,[b,"change"])}else a.j.ja(b,
e)};a.m(m,null,{i:b})}else a.La(b,{checkedValue:c})},update:function(){}};a.h.ga.value=!0;a.d.visible={update:function(b,c){var d=a.a.c(c()),e="none"!=b.style.display;d&&!e?b.style.display="":!d&&e&&(b.style.display="none")}};(function(b){a.d[b]={init:function(c,d,e,f,g){return a.d.event.init.call(this,c,function(){var a={};a[b]=d();return a},e,f,g)}}})("click");a.P=function(){};a.P.prototype.renderTemplateSource=function(){throw Error("Override renderTemplateSource");};a.P.prototype.createJavaScriptEvaluatorBlock=
function(){throw Error("Override createJavaScriptEvaluatorBlock");};a.P.prototype.makeTemplateSource=function(b,c){if("string"==typeof b){c=c||t;var d=c.getElementById(b);if(!d)throw Error("Cannot find template with ID "+b);return new a.v.n(d)}if(1==b.nodeType||8==b.nodeType)return new a.v.sa(b);throw Error("Unknown template type: "+b);};a.P.prototype.renderTemplate=function(a,c,d,e){a=this.makeTemplateSource(a,e);return this.renderTemplateSource(a,c,d,e)};a.P.prototype.isTemplateRewritten=function(a,
c){return!1===this.allowTemplateRewriting?!0:this.makeTemplateSource(a,c).data("isRewritten")};a.P.prototype.rewriteTemplate=function(a,c,d){a=this.makeTemplateSource(a,d);c=c(a.text());a.text(c);a.data("isRewritten",!0)};a.b("templateEngine",a.P);a.Ib=function(){function b(b,c,d,h){b=a.h.Ab(b);for(var l=a.h.va,m=0;m<b.length;m++){var k=b[m].key;if(l.hasOwnProperty(k)){var r=l[k];if("function"===typeof r){if(k=r(b[m].value))throw Error(k);}else if(!r)throw Error("This template engine does not support the '"+
k+"' binding within its templates");}}d="ko.__tr_ambtns(function($context,$element){return(function(){return{ "+a.h.Xa(b,{valueAccessors:!0})+" } })()},'"+d.toLowerCase()+"')";return h.createJavaScriptEvaluatorBlock(d)+c}var c=/(<([a-z]+\d*)(?:\s+(?!data-bind\s*=\s*)[a-z0-9\-]+(?:=(?:\"[^\"]*\"|\'[^\']*\'|[^>]*))?)*\s+)data-bind\s*=\s*(["'])([\s\S]*?)\3/gi,d=/\x3c!--\s*ko\b\s*([\s\S]*?)\s*--\x3e/g;return{Tc:function(b,c,d){c.isTemplateRewritten(b,d)||c.rewriteTemplate(b,function(b){return a.Ib.jd(b,
c)},d)},jd:function(a,f){return a.replace(c,function(a,c,d,e,k){return b(k,c,d,f)}).replace(d,function(a,c){return b(c,"\x3c!-- ko --\x3e","#comment",f)})},Jc:function(b,c){return a.N.yb(function(d,h){var l=d.nextSibling;l&&l.nodeName.toLowerCase()===c&&a.La(l,b,h)})}}}();a.b("__tr_ambtns",a.Ib.Jc);(function(){a.v={};a.v.n=function(b){if(this.n=b){var c=a.a.A(b);this.eb="script"===c?1:"textarea"===c?2:"template"==c&&b.content&&11===b.content.nodeType?3:4}};a.v.n.prototype.text=function(){var b=1===
this.eb?"text":2===this.eb?"value":"innerHTML";if(0==arguments.length)return this.n[b];var c=arguments[0];"innerHTML"===b?a.a.Eb(this.n,c):this.n[b]=c};var b=a.a.e.J()+"_";a.v.n.prototype.data=function(c){if(1===arguments.length)return a.a.e.get(this.n,b+c);a.a.e.set(this.n,b+c,arguments[1])};var c=a.a.e.J();a.v.n.prototype.nodes=function(){var b=this.n;if(0==arguments.length)return(a.a.e.get(b,c)||{}).mb||(3===this.eb?b.content:4===this.eb?b:n);a.a.e.set(b,c,{mb:arguments[0]})};a.v.sa=function(a){this.n=
a};a.v.sa.prototype=new a.v.n;a.v.sa.prototype.text=function(){if(0==arguments.length){var b=a.a.e.get(this.n,c)||{};b.Jb===n&&b.mb&&(b.Jb=b.mb.innerHTML);return b.Jb}a.a.e.set(this.n,c,{Jb:arguments[0]})};a.b("templateSources",a.v);a.b("templateSources.domElement",a.v.n);a.b("templateSources.anonymousTemplate",a.v.sa)})();(function(){function b(b,c,d){var e;for(c=a.f.nextSibling(c);b&&(e=b)!==c;)b=a.f.nextSibling(e),d(e,b)}function c(c,d){if(c.length){var e=c[0],f=c[c.length-1],g=e.parentNode,h=
a.S.instance,n=h.preprocessNode;if(n){b(e,f,function(a,b){var c=a.previousSibling,d=n.call(h,a);d&&(a===e&&(e=d[0]||b),a===f&&(f=d[d.length-1]||c))});c.length=0;if(!e)return;e===f?c.push(e):(c.push(e,f),a.a.Ba(c,g))}b(e,f,function(b){1!==b.nodeType&&8!==b.nodeType||a.Ub(d,b)});b(e,f,function(b){1!==b.nodeType&&8!==b.nodeType||a.N.Cc(b,[d])});a.a.Ba(c,g)}}function d(a){return a.nodeType?a:0<a.length?a[0]:null}function e(b,e,f,h,q){q=q||{};var p=(b&&d(b)||f||{}).ownerDocument,n=q.templateEngine||g;
a.Ib.Tc(f,n,p);f=n.renderTemplate(f,h,q,p);if("number"!=typeof f.length||0<f.length&&"number"!=typeof f[0].nodeType)throw Error("Template engine must return an array of DOM nodes");p=!1;switch(e){case "replaceChildren":a.f.fa(b,f);p=!0;break;case "replaceNode":a.a.uc(b,f);p=!0;break;case "ignoreTargetNode":break;default:throw Error("Unknown renderMode: "+e);}p&&(c(f,h),q.afterRender&&a.l.w(q.afterRender,null,[f,h.$data]));return f}function f(b,c,d){return a.I(b)?b():"function"===typeof b?b(c,d):b}
var g;a.Fb=function(b){if(b!=n&&!(b instanceof a.P))throw Error("templateEngine must inherit from ko.templateEngine");g=b};a.Cb=function(b,c,k,h,q){k=k||{};if((k.templateEngine||g)==n)throw Error("Set a template engine before calling renderTemplate");q=q||"replaceChildren";if(h){var p=d(h);return a.B(function(){var g=c&&c instanceof a.R?c:new a.R(c,null,null,null,{exportDependencies:!0}),n=f(b,g.$data,g),g=e(h,q,n,g,k);"replaceNode"==q&&(h=g,p=d(h))},null,{ya:function(){return!p||!a.a.qb(p)},i:p&&
"replaceNode"==q?p.parentNode:p})}return a.N.yb(function(d){a.Cb(b,c,k,d,"replaceNode")})};a.pd=function(b,d,g,h,q){function p(a,b){c(b,t);g.afterRender&&g.afterRender(b,a);t=null}function s(a,c){t=q.createChildContext(a,g.as,function(a){a.$index=c});var d=f(b,a,t);return e(null,"ignoreTargetNode",d,t,g)}var t;return a.B(function(){var b=a.a.c(d)||[];"undefined"==typeof b.length&&(b=[b]);b=a.a.Ma(b,function(b){return g.includeDestroyed||b===n||null===b||!a.a.c(b._destroy)});a.l.w(a.a.Db,null,[h,b,
s,g,p])},null,{i:h})};var h=a.a.e.J();a.d.template={init:function(b,c){var d=a.a.c(c());if("string"==typeof d||d.name)a.f.za(b);else{if("nodes"in d){if(d=d.nodes||[],a.I(d))throw Error('The "nodes" option must be a plain, non-observable array.');}else d=a.f.childNodes(b);d=a.a.nc(d);(new a.v.sa(b)).nodes(d)}return{controlsDescendantBindings:!0}},update:function(b,c,d,e,f){var g=c();c=a.a.c(g);d=!0;e=null;"string"==typeof c?c={}:(g=c.name,"if"in c&&(d=a.a.c(c["if"])),d&&"ifnot"in c&&(d=!a.a.c(c.ifnot)));
"foreach"in c?e=a.pd(g||b,d&&c.foreach||[],c,b,f):d?(f="data"in c?f.ac(c.data,c.as):f,e=a.Cb(g||b,f,c,b)):a.f.za(b);f=e;(c=a.a.e.get(b,h))&&"function"==typeof c.k&&c.k();a.a.e.set(b,h,f&&f.ca()?f:n)}};a.h.va.template=function(b){b=a.h.Ab(b);return 1==b.length&&b[0].unknown||a.h.fd(b,"name")?null:"This template engine does not support anonymous templates nested within its templates"};a.f.aa.template=!0})();a.b("setTemplateEngine",a.Fb);a.b("renderTemplate",a.Cb);a.a.hc=function(a,c,d){if(a.length&&
c.length){var e,f,g,h,l;for(e=f=0;(!d||e<d)&&(h=a[f]);++f){for(g=0;l=c[g];++g)if(h.value===l.value){h.moved=l.index;l.moved=h.index;c.splice(g,1);e=g=0;break}e+=g}}};a.a.lb=function(){function b(b,d,e,f,g){var h=Math.min,l=Math.max,m=[],k,n=b.length,q,p=d.length,s=p-n||1,t=n+p+1,v,u,x;for(k=0;k<=n;k++)for(u=v,m.push(v=[]),x=h(p,k+s),q=l(0,k-1);q<=x;q++)v[q]=q?k?b[k-1]===d[q-1]?u[q-1]:h(u[q]||t,v[q-1]||t)+1:q+1:k+1;h=[];l=[];s=[];k=n;for(q=p;k||q;)p=m[k][q]-1,q&&p===m[k][q-1]?l.push(h[h.length]={status:e,
value:d[--q],index:q}):k&&p===m[k-1][q]?s.push(h[h.length]={status:f,value:b[--k],index:k}):(--q,--k,g.sparse||h.push({status:"retained",value:d[q]}));a.a.hc(s,l,!g.dontLimitMoves&&10*n);return h.reverse()}return function(a,d,e){e="boolean"===typeof e?{dontLimitMoves:e}:e||{};a=a||[];d=d||[];return a.length<d.length?b(a,d,"added","deleted",e):b(d,a,"deleted","added",e)}}();a.b("utils.compareArrays",a.a.lb);(function(){function b(b,c,d,h,l){var m=[],k=a.B(function(){var k=c(d,l,a.a.Ba(m,b))||[];0<
m.length&&(a.a.uc(m,k),h&&a.l.w(h,null,[d,k,l]));m.length=0;a.a.ta(m,k)},null,{i:b,ya:function(){return!a.a.Tb(m)}});return{ea:m,B:k.ca()?k:n}}var c=a.a.e.J(),d=a.a.e.J();a.a.Db=function(e,f,g,h,l){function m(b,c){w=q[c];u!==c&&(D[b]=w);w.tb(u++);a.a.Ba(w.ea,e);t.push(w);z.push(w)}function k(b,c){if(b)for(var d=0,e=c.length;d<e;d++)c[d]&&a.a.r(c[d].ea,function(a){b(a,d,c[d].ka)})}f=f||[];h=h||{};var r=a.a.e.get(e,c)===n,q=a.a.e.get(e,c)||[],p=a.a.ib(q,function(a){return a.ka}),s=a.a.lb(p,f,h.dontLimitMoves),
t=[],v=0,u=0,x=[],z=[];f=[];for(var D=[],p=[],w,C=0,B,E;B=s[C];C++)switch(E=B.moved,B.status){case "deleted":E===n&&(w=q[v],w.B&&(w.B.k(),w.B=n),a.a.Ba(w.ea,e).length&&(h.beforeRemove&&(t.push(w),z.push(w),w.ka===d?w=null:f[C]=w),w&&x.push.apply(x,w.ea)));v++;break;case "retained":m(C,v++);break;case "added":E!==n?m(C,E):(w={ka:B.value,tb:a.O(u++)},t.push(w),z.push(w),r||(p[C]=w))}a.a.e.set(e,c,t);k(h.beforeMove,D);a.a.r(x,h.beforeRemove?a.ba:a.removeNode);for(var C=0,r=a.f.firstChild(e),F;w=z[C];C++){w.ea||
a.a.extend(w,b(e,g,w.ka,l,w.tb));for(v=0;s=w.ea[v];r=s.nextSibling,F=s,v++)s!==r&&a.f.kc(e,s,F);!w.ad&&l&&(l(w.ka,w.ea,w.tb),w.ad=!0)}k(h.beforeRemove,f);for(C=0;C<f.length;++C)f[C]&&(f[C].ka=d);k(h.afterMove,D);k(h.afterAdd,p)}})();a.b("utils.setDomNodeChildrenFromArrayMapping",a.a.Db);a.X=function(){this.allowTemplateRewriting=!1};a.X.prototype=new a.P;a.X.prototype.renderTemplateSource=function(b,c,d,e){if(c=(9>a.a.C?0:b.nodes)?b.nodes():null)return a.a.W(c.cloneNode(!0).childNodes);b=b.text();
return a.a.na(b,e)};a.X.vb=new a.X;a.Fb(a.X.vb);a.b("nativeTemplateEngine",a.X);(function(){a.xb=function(){var a=this.ed=function(){if(!u||!u.tmpl)return 0;try{if(0<=u.tmpl.tag.tmpl.open.toString().indexOf("__"))return 2}catch(a){}return 1}();this.renderTemplateSource=function(b,e,f,g){g=g||t;f=f||{};if(2>a)throw Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");var h=b.data("precompiled");h||(h=b.text()||"",h=u.template(null,"{{ko_with $item.koBindingContext}}"+
h+"{{/ko_with}}"),b.data("precompiled",h));b=[e.$data];e=u.extend({koBindingContext:e},f.templateOptions);e=u.tmpl(h,b,e);e.appendTo(g.createElement("div"));u.fragments={};return e};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+a+" })()) }}"};this.addTemplate=function(a,b){t.write("<script type='text/html' id='"+a+"'>"+b+"\x3c/script>")};0<a&&(u.tmpl.tag.ko_code={open:"__.push($1 || '');"},u.tmpl.tag.ko_with={open:"with($1) {",close:"} "})};a.xb.prototype=
new a.P;var b=new a.xb;0<b.ed&&a.Fb(b);a.b("jqueryTmplTemplateEngine",a.xb)})()})})();})();
;
/*!
 * Bootstrap v3.3.7 (http://getbootstrap.com)
 * Copyright 2011-2016 Twitter, Inc.
 * Licensed under the MIT license
 */
if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&j<i.length-1&&j++,~j||(j=0),i.eq(j).trigger("focus")}}}};var h=a.fn.dropdown;a.fn.dropdown=d,a.fn.dropdown.Constructor=g,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=h,this},a(document).on("click.bs.dropdown.data-api",c).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",f,g.prototype.toggle).on("keydown.bs.dropdown.data-api",f,g.prototype.keydown).on("keydown.bs.dropdown.data-api",".dropdown-menu",g.prototype.keydown)}(jQuery),+function(a){"use strict";function b(b,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},c.DEFAULTS,e.data(),"object"==typeof b&&b);f||e.data("bs.modal",f=new c(this,g)),"string"==typeof b?f[b](d):g.show&&f.show(d)})}var c=function(b,c){this.options=c,this.$body=a(document.body),this.$element=a(b),this.$dialog=this.$element.find(".modal-dialog"),this.$backdrop=null,this.isShown=null,this.originalBodyPad=null,this.scrollbarWidth=0,this.ignoreBackdropClick=!1,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=300,c.BACKDROP_TRANSITION_DURATION=150,c.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},c.prototype.toggle=function(a){return this.isShown?this.hide():this.show(a)},c.prototype.show=function(b){var d=this,e=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(e),this.isShown||e.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.setScrollbar(),this.$body.addClass("modal-open"),this.escape(),this.resize(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.$dialog.on("mousedown.dismiss.bs.modal",function(){d.$element.one("mouseup.dismiss.bs.modal",function(b){a(b.target).is(d.$element)&&(d.ignoreBackdropClick=!0)})}),this.backdrop(function(){var e=a.support.transition&&d.$element.hasClass("fade");d.$element.parent().length||d.$element.appendTo(d.$body),d.$element.show().scrollTop(0),d.adjustDialog(),e&&d.$element[0].offsetWidth,d.$element.addClass("in"),d.enforceFocus();var f=a.Event("shown.bs.modal",{relatedTarget:b});e?d.$dialog.one("bsTransitionEnd",function(){d.$element.trigger("focus").trigger(f)}).emulateTransitionEnd(c.TRANSITION_DURATION):d.$element.trigger("focus").trigger(f)}))},c.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),this.resize(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal"),this.$dialog.off("mousedown.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",a.proxy(this.hideModal,this)).emulateTransitionEnd(c.TRANSITION_DURATION):this.hideModal())},c.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){document===a.target||this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.trigger("focus")},this))},c.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keydown.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keydown.dismiss.bs.modal")},c.prototype.resize=function(){this.isShown?a(window).on("resize.bs.modal",a.proxy(this.handleUpdate,this)):a(window).off("resize.bs.modal")},c.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.$body.removeClass("modal-open"),a.resetAdjustments(),a.resetScrollbar(),a.$element.trigger("hidden.bs.modal")})},c.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},c.prototype.backdrop=function(b){var d=this,e=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var f=a.support.transition&&e;if(this.$backdrop=a(document.createElement("div")).addClass("modal-backdrop "+e).appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){return this.ignoreBackdropClick?void(this.ignoreBackdropClick=!1):void(a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus():this.hide()))},this)),f&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;f?this.$backdrop.one("bsTransitionEnd",b).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):b()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var g=function(){d.removeBackdrop(),b&&b()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",g).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):g()}else b&&b()},c.prototype.handleUpdate=function(){this.adjustDialog()},c.prototype.adjustDialog=function(){var a=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth<a,this.scrollbarWidth=this.measureScrollbar()},c.prototype.setScrollbar=function(){var a=parseInt(this.$body.css("padding-right")||0,10);this.originalBodyPad=document.body.style.paddingRight||"",this.bodyIsOverflowing&&this.$body.css("padding-right",a+this.scrollbarWidth)},c.prototype.resetScrollbar=function(){this.$body.css("padding-right",this.originalBodyPad)},c.prototype.measureScrollbar=function(){var a=document.createElement("div");a.className="modal-scrollbar-measure",this.$body.append(a);var b=a.offsetWidth-a.clientWidth;return this.$body[0].removeChild(a),b};var d=a.fn.modal;a.fn.modal=b,a.fn.modal.Constructor=c,a.fn.modal.noConflict=function(){return a.fn.modal=d,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(c){var d=a(this),e=d.attr("href"),f=a(d.attr("data-target")||e&&e.replace(/.*(?=#[^\s]+$)/,"")),g=f.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(e)&&e},f.data(),d.data());d.is("a")&&c.preventDefault(),f.one("show.bs.modal",function(a){a.isDefaultPrevented()||f.one("hidden.bs.modal",function(){d.is(":visible")&&d.trigger("focus")})}),b.call(f,g,this)})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.tooltip",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init("tooltip",a,b)};c.VERSION="3.3.7",c.TRANSITION_DURATION=150,c.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-m<o.top?"bottom":"right"==h&&k.right+l>o.width?"left":"left"==h&&k.left-l<o.left?"right":h,f.removeClass(n).addClass(h)}var p=this.getCalculatedOffset(h,k,l,m);this.applyPlacement(p,h);var q=function(){var a=e.hoverState;e.$element.trigger("shown.bs."+e.type),e.hoverState=null,"out"==a&&e.leave(e)};a.support.transition&&this.$tip.hasClass("fade")?f.one("bsTransitionEnd",q).emulateTransitionEnd(c.TRANSITION_DURATION):q()}},c.prototype.applyPlacement=function(b,c){var d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),b.top+=g,b.left+=h,a.offset.setOffset(d[0],a.extend({using:function(a){d.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),d.addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;"top"==c&&j!=f&&(b.top=b.top+f-j);var k=this.getViewportAdjustedDelta(c,b,i,j);k.left?b.left+=k.left:b.top+=k.top;var l=/top|bottom/.test(c),m=l?2*k.left-e+i:2*k.top-f+j,n=l?"offsetWidth":"offsetHeight";d.offset(b),this.replaceArrow(m,d[0][n],l)},c.prototype.replaceArrow=function(a,b,c){this.arrow().css(c?"left":"top",50*(1-a/b)+"%").css(c?"top":"left","")},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},c.prototype.hide=function(b){function d(){"in"!=e.hoverState&&f.detach(),e.$element&&e.$element.removeAttr("aria-describedby").trigger("hidden.bs."+e.type),b&&b()}var e=this,f=a(this.$tip),g=a.Event("hide.bs."+this.type);if(this.$element.trigger(g),!g.isDefaultPrevented())return f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",d).emulateTransitionEnd(c.TRANSITION_DURATION):d(),this.hoverState=null,this},c.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},c.prototype.hasContent=function(){return this.getTitle()},c.prototype.getPosition=function(b){b=b||this.$element;var c=b[0],d="BODY"==c.tagName,e=c.getBoundingClientRect();null==e.width&&(e=a.extend({},e,{width:e.right-e.left,height:e.bottom-e.top}));var f=window.SVGElement&&c instanceof window.SVGElement,g=d?{top:0,left:0}:f?null:b.offset(),h={scroll:d?document.documentElement.scrollTop||document.body.scrollTop:b.scrollTop()},i=d?{width:a(window).width(),height:a(window).height()}:null;return a.extend({},e,h,i,g)},c.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},c.prototype.getViewportAdjustedDelta=function(a,b,c,d){var e={top:0,left:0};if(!this.$viewport)return e;var f=this.options.viewport&&this.options.viewport.padding||0,g=this.getPosition(this.$viewport);if(/right|left/.test(a)){var h=b.top-f-g.scroll,i=b.top+f-g.scroll+d;h<g.top?e.top=g.top-h:i>g.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;j<g.left?e.left=g.left-j:k>g.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b<e[0])return this.activeTarget=null,this.clear();for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(void 0===e[a+1]||b<e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){
this.activeTarget=b,this.clear();var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")},b.prototype.clear=function(){a(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on("load.bs.scrollspy.data-api",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new c(this)),"string"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION="3.3.7",c.TRANSITION_DURATION=150,c.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a"),f=a.Event("hide.bs.tab",{relatedTarget:b[0]}),g=a.Event("show.bs.tab",{relatedTarget:e[0]});if(e.trigger(f),b.trigger(g),!g.isDefaultPrevented()&&!f.isDefaultPrevented()){var h=a(d);this.activate(b.closest("li"),c),this.activate(h,h.parent(),function(){e.trigger({type:"hidden.bs.tab",relatedTarget:b[0]}),b.trigger({type:"shown.bs.tab",relatedTarget:e[0]})})}}},c.prototype.activate=function(b,d,e){function f(){g.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e<c&&"top";if("bottom"==this.affixed)return null!=c?!(e+this.unpin<=f.top)&&"bottom":!(e+g<=a-d)&&"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&e<=c?"top":null!=d&&i+j>=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery);;
/**
 * Bootstrap Multiselect (https://github.com/davidstutz/bootstrap-multiselect)
 * 
 * Apache License, Version 2.0:
 * Copyright (c) 2012 - 2015 David Stutz
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a
 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 * 
 * BSD 3-Clause License:
 * Copyright (c) 2012 - 2015 David Stutz
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *    - Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *    - Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation
 *      and/or other materials provided with the distribution.
 *    - Neither the name of David Stutz nor the names of its contributors may be
 *      used to endorse or promote products derived from this software without
 *      specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
!function ($) {
    "use strict";// jshint ;_;

    if (typeof ko !== 'undefined' && ko.bindingHandlers && !ko.bindingHandlers.multiselect) {
        ko.bindingHandlers.multiselect = {
            after: ['options', 'value', 'selectedOptions'],

            init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
                var $element = $(element);
                var config = ko.toJS(valueAccessor());

                $element.multiselect(config);

                if (allBindings.has('options')) {
                    var options = allBindings.get('options');
                    if (ko.isObservable(options)) {
                        ko.computed({
                            read: function() {
                                options();
                                setTimeout(function() {
                                    var ms = $element.data('multiselect');
                                    if (ms)
                                        ms.updateOriginalOptions();//Not sure how beneficial this is.
                                    $element.multiselect('rebuild');
                                }, 1);
                            },
                            disposeWhenNodeIsRemoved: element
                        });
                    }
                }

                //value and selectedOptions are two-way, so these will be triggered even by our own actions.
                //It needs some way to tell if they are triggered because of us or because of outside change.
                //It doesn't loop but it's a waste of processing.
                if (allBindings.has('value')) {
                    var value = allBindings.get('value');
                    if (ko.isObservable(value)) {
                        ko.computed({
                            read: function() {
                                value();
                                setTimeout(function() {
                                    $element.multiselect('refresh');
                                }, 1);
                            },
                            disposeWhenNodeIsRemoved: element
                        }).extend({ rateLimit: 100, notifyWhenChangesStop: true });
                    }
                }

                //Switched from arrayChange subscription to general subscription using 'refresh'.
                //Not sure performance is any better using 'select' and 'deselect'.
                if (allBindings.has('selectedOptions')) {
                    var selectedOptions = allBindings.get('selectedOptions');
                    if (ko.isObservable(selectedOptions)) {
                        ko.computed({
                            read: function() {
                                selectedOptions();
                                setTimeout(function() {
                                    $element.multiselect('refresh');
                                }, 1);
                            },
                            disposeWhenNodeIsRemoved: element
                        }).extend({ rateLimit: 100, notifyWhenChangesStop: true });
                    }
                }

                ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
                    $element.multiselect('destroy');
                });
            },

            update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
                var $element = $(element);
                var config = ko.toJS(valueAccessor());

                $element.multiselect('setOptions', config);
                $element.multiselect('rebuild');
            }
        };
    }

    function forEach(array, callback) {
        for (var index = 0; index < array.length; ++index) {
            callback(array[index], index);
        }
    }

    /**
     * Constructor to create a new multiselect using the given select.
     *
     * @param {jQuery} select
     * @param {Object} options
     * @returns {Multiselect}
     */
    function Multiselect(select, options) {

        this.$select = $(select);
        
        // Placeholder via data attributes
        if (this.$select.attr("data-placeholder")) {
            options.nonSelectedText = this.$select.data("placeholder");
        }
        
        this.options = this.mergeOptions($.extend({}, options, this.$select.data()));

        // Initialization.
        // We have to clone to create a new reference.
        this.originalOptions = this.$select.clone()[0].options;
        this.query = '';
        this.searchTimeout = null;
        this.lastToggledInput = null

        this.options.multiple = this.$select.attr('multiple') === "multiple";
        this.options.onChange = $.proxy(this.options.onChange, this);
        this.options.onDropdownShow = $.proxy(this.options.onDropdownShow, this);
        this.options.onDropdownHide = $.proxy(this.options.onDropdownHide, this);
        this.options.onDropdownShown = $.proxy(this.options.onDropdownShown, this);
        this.options.onDropdownHidden = $.proxy(this.options.onDropdownHidden, this);
        
        // Build select all if enabled.
        this.buildContainer();
        this.buildButton();
        this.buildDropdown();
        this.buildSelectAll();
        this.buildDropdownOptions();
        this.buildFilter();

        this.updateButtonText();
        this.updateSelectAll();

        if (this.options.disableIfEmpty && $('option', this.$select).length <= 0) {
            this.disable();
        }
        
        this.$select.hide().after(this.$container);
    };

    Multiselect.prototype = {

        defaults: {
            /**
             * Default text function will either print 'None selected' in case no
             * option is selected or a list of the selected options up to a length
             * of 3 selected options.
             * 
             * @param {jQuery} options
             * @param {jQuery} select
             * @returns {String}
             */
            buttonText: function(options, select) {
                if (options.length === 0) {
                    return this.nonSelectedText;
                }
                else if (this.allSelectedText 
                            && options.length === $('option', $(select)).length 
                            && $('option', $(select)).length !== 1 
                            && this.multiple) {

                    if (this.selectAllNumber) {
                        return this.allSelectedText + ' (' + options.length + ')';
                    }
                    else {
                        return this.allSelectedText;
                    }
                }
                else if (options.length > this.numberDisplayed) {
                    return options.length + ' ' + this.nSelectedText;
                }
                else {
                    var selected = '';
                    var delimiter = this.delimiterText;
                    
                    options.each(function() {
                        var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).text();
                        selected += label + delimiter;
                    });
                    
                    return selected.substr(0, selected.length - 2);
                }
            },
            /**
             * Updates the title of the button similar to the buttonText function.
             * 
             * @param {jQuery} options
             * @param {jQuery} select
             * @returns {@exp;selected@call;substr}
             */
            buttonTitle: function(options, select) {
                if (options.length === 0) {
                    return this.nonSelectedText;
                }
                else {
                    var selected = '';
                    var delimiter = this.delimiterText;
                    
                    options.each(function () {
                        var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).text();
                        selected += label + delimiter;
                    });
                    return selected.substr(0, selected.length - 2);
                }
            },
            /**
             * Create a label.
             *
             * @param {jQuery} element
             * @returns {String}
             */
            optionLabel: function(element){
                return $(element).attr('label') || $(element).text();
            },
            /**
             * Triggered on change of the multiselect.
             * 
             * Not triggered when selecting/deselecting options manually.
             * 
             * @param {jQuery} option
             * @param {Boolean} checked
             */
            onChange : function(option, checked) {

            },
            /**
             * Triggered when the dropdown is shown.
             *
             * @param {jQuery} event
             */
            onDropdownShow: function(event) {

            },
            /**
             * Triggered when the dropdown is hidden.
             *
             * @param {jQuery} event
             */
            onDropdownHide: function(event) {

            },
            /**
             * Triggered after the dropdown is shown.
             * 
             * @param {jQuery} event
             */
            onDropdownShown: function(event) {
                
            },
            /**
             * Triggered after the dropdown is hidden.
             * 
             * @param {jQuery} event
             */
            onDropdownHidden: function(event) {
                
            },
            /**
             * Triggered on select all.
             */
            onSelectAll: function() {
                
            },
            enableHTML: false,
            buttonClass: 'btn btn-default',
            inheritClass: false,
            buttonWidth: 'auto',
            buttonContainer: '<div class="btn-group" />',
            dropRight: false,
            selectedClass: 'active',
            // Maximum height of the dropdown menu.
            // If maximum height is exceeded a scrollbar will be displayed.
            maxHeight: false,
            checkboxName: false,
            includeSelectAllOption: false,
            includeSelectAllIfMoreThan: 0,
            selectAllText: ' Select all',
            selectAllValue: 'multiselect-all',
            selectAllName: false,
            selectAllNumber: true,
            enableFiltering: false,
            enableCaseInsensitiveFiltering: false,
            enableClickableOptGroups: false,
            filterPlaceholder: 'Search',
            // possible options: 'text', 'value', 'both'
            filterBehavior: 'text',
            includeFilterClearBtn: true,
            preventInputChangeEvent: false,
            nonSelectedText: 'None selected',
            nSelectedText: 'selected',
            allSelectedText: 'All selected',
            numberDisplayed: 3,
            disableIfEmpty: false,
            delimiterText: ', ',
            templates: {
                button: '<button type="button" class="multiselect dropdown-toggle" data-toggle="dropdown"><span class="multiselect-selected-text"></span> <b class="caret"></b></button>',
                ul: '<ul class="multiselect-container dropdown-menu"></ul>',
                filter: '<li class="multiselect-item filter"><div class="input-group"><span class="input-group-addon"><i class="glyphicon glyphicon-search"></i></span><input class="form-control multiselect-search" type="text"></div></li>',
                filterClearBtn: '<span class="input-group-btn"><button class="btn btn-default multiselect-clear-filter" type="button"><i class="glyphicon glyphicon-remove-circle"></i></button></span>',
                li: '<li><a tabindex="0"><label></label></a></li>',
                divider: '<li class="multiselect-item divider"></li>',
                liGroup: '<li class="multiselect-item multiselect-group"><label></label></li>'
            }
        },

        constructor: Multiselect,

        /**
         * Builds the container of the multiselect.
         */
        buildContainer: function() {
            this.$container = $(this.options.buttonContainer);
            this.$container.on('show.bs.dropdown', this.options.onDropdownShow);
            this.$container.on('hide.bs.dropdown', this.options.onDropdownHide);
            this.$container.on('shown.bs.dropdown', this.options.onDropdownShown);
            this.$container.on('hidden.bs.dropdown', this.options.onDropdownHidden);
        },

        /**
         * Builds the button of the multiselect.
         */
        buildButton: function() {
            this.$button = $(this.options.templates.button).addClass(this.options.buttonClass);
            if (this.$select.attr('class') && this.options.inheritClass) {
                this.$button.addClass(this.$select.attr('class'));
            }
            // Adopt active state.
            if (this.$select.prop('disabled')) {
                this.disable();
            }
            else {
                this.enable();
            }

            // Manually add button width if set.
            if (this.options.buttonWidth && this.options.buttonWidth !== 'auto') {
                this.$button.css({
                    'width' : this.options.buttonWidth,
                    'overflow' : 'hidden',
                    'text-overflow' : 'ellipsis'
                });
                this.$container.css({
                    'width': this.options.buttonWidth
                });
            }

            // Keep the tab index from the select.
            var tabindex = this.$select.attr('tabindex');
            if (tabindex) {
                this.$button.attr('tabindex', tabindex);
            }

            this.$container.prepend(this.$button);
        },

        /**
         * Builds the ul representing the dropdown menu.
         */
        buildDropdown: function() {

            // Build ul.
            this.$ul = $(this.options.templates.ul);

            if (this.options.dropRight) {
                this.$ul.addClass('pull-right');
            }

            // Set max height of dropdown menu to activate auto scrollbar.
            if (this.options.maxHeight) {
                // TODO: Add a class for this option to move the css declarations.
                this.$ul.css({
                    'max-height': this.options.maxHeight + 'px',
                    'overflow-y': 'auto',
                    'overflow-x': 'hidden'
                });
            }

            this.$container.append(this.$ul);
        },

        /**
         * Build the dropdown options and binds all nessecary events.
         * 
         * Uses createDivider and createOptionValue to create the necessary options.
         */
        buildDropdownOptions: function() {

            this.$select.children().each($.proxy(function(index, element) {

                var $element = $(element);
                // Support optgroups and options without a group simultaneously.
                var tag = $element.prop('tagName')
                    .toLowerCase();
            
                if ($element.prop('value') === this.options.selectAllValue) {
                    return;
                }

                if (tag === 'optgroup') {
                    this.createOptgroup(element);
                }
                else if (tag === 'option') {

                    if ($element.data('role') === 'divider') {
                        this.createDivider();
                    }
                    else {
                        this.createOptionValue(element);
                    }

                }

                // Other illegal tags will be ignored.
            }, this));

            // Bind the change event on the dropdown elements.
            $('li input', this.$ul).on('change', $.proxy(function(event) {
                var $target = $(event.target);

                var checked = $target.prop('checked') || false;
                var isSelectAllOption = $target.val() === this.options.selectAllValue;

                // Apply or unapply the configured selected class.
                if (this.options.selectedClass) {
                    if (checked) {
                        $target.closest('li')
                            .addClass(this.options.selectedClass);
                    }
                    else {
                        $target.closest('li')
                            .removeClass(this.options.selectedClass);
                    }
                }

                // Get the corresponding option.
                var value = $target.val();
                var $option = this.getOptionByValue(value);

                var $optionsNotThis = $('option', this.$select).not($option);
                var $checkboxesNotThis = $('input', this.$container).not($target);

                if (isSelectAllOption) {
                    if (checked) {
                        this.selectAll();
                    }
                    else {
                        this.deselectAll();
                    }
                }

                if(!isSelectAllOption){
                    if (checked) {
                        $option.prop('selected', true);

                        if (this.options.multiple) {
                            // Simply select additional option.
                            $option.prop('selected', true);
                        }
                        else {
                            // Unselect all other options and corresponding checkboxes.
                            if (this.options.selectedClass) {
                                $($checkboxesNotThis).closest('li').removeClass(this.options.selectedClass);
                            }

                            $($checkboxesNotThis).prop('checked', false);
                            $optionsNotThis.prop('selected', false);

                            // It's a single selection, so close.
                            this.$button.click();
                        }

                        if (this.options.selectedClass === "active") {
                            $optionsNotThis.closest("a").css("outline", "");
                        }
                    }
                    else {
                        // Unselect option.
                        $option.prop('selected', false);
                    }
                }

                this.$select.change();

                this.updateButtonText();
                this.updateSelectAll();

                this.options.onChange($option, checked);

                if(this.options.preventInputChangeEvent) {
                    return false;
                }
            }, this));

            $('li a', this.$ul).on('mousedown', function(e) {
                if (e.shiftKey) {
                    // Prevent selecting text by Shift+click
                    return false;
                }
            });
        
            $('li a', this.$ul).on('touchstart click', $.proxy(function(event) {
                event.stopPropagation();

                var $target = $(event.target);
                
                if (event.shiftKey && this.options.multiple) {
                    if($target.is("label")){ // Handles checkbox selection manually (see https://github.com/davidstutz/bootstrap-multiselect/issues/431)
                        event.preventDefault();
                        $target = $target.find("input");
                        $target.prop("checked", !$target.prop("checked"));
                    }
                    var checked = $target.prop('checked') || false;

                    if (this.lastToggledInput !== null && this.lastToggledInput !== $target) { // Make sure we actually have a range
                        var from = $target.closest("li").index();
                        var to = this.lastToggledInput.closest("li").index();
                        
                        if (from > to) { // Swap the indices
                            var tmp = to;
                            to = from;
                            from = tmp;
                        }
                        
                        // Make sure we grab all elements since slice excludes the last index
                        ++to;
                        
                        // Change the checkboxes and underlying options
                        var range = this.$ul.find("li").slice(from, to).find("input");
                        
                        range.prop('checked', checked);
                        
                        if (this.options.selectedClass) {
                            range.closest('li')
                                .toggleClass(this.options.selectedClass, checked);
                        }
                        
                        for (var i = 0, j = range.length; i < j; i++) {
                            var $checkbox = $(range[i]);

                            var $option = this.getOptionByValue($checkbox.val());

                            $option.prop('selected', checked);
                        }                   
                    }
                    
                    // Trigger the select "change" event
                    $target.trigger("change");
                }
                
                // Remembers last clicked option
                if($target.is("input") && !$target.closest("li").is(".multiselect-item")){
                    this.lastToggledInput = $target;
                }

                $target.blur();
            }, this));

            // Keyboard support.
            this.$container.off('keydown.multiselect').on('keydown.multiselect', $.proxy(function(event) {
                if ($('input[type="text"]', this.$container).is(':focus')) {
                    return;
                }

                if (event.keyCode === 9 && this.$container.hasClass('open')) {
                    this.$button.click();
                }
                else {
                    var $items = $(this.$container).find("li:not(.divider):not(.disabled) a").filter(":visible");

                    if (!$items.length) {
                        return;
                    }

                    var index = $items.index($items.filter(':focus'));

                    // Navigation up.
                    if (event.keyCode === 38 && index > 0) {
                        index--;
                    }
                    // Navigate down.
                    else if (event.keyCode === 40 && index < $items.length - 1) {
                        index++;
                    }
                    else if (!~index) {
                        index = 0;
                    }

                    var $current = $items.eq(index);
                    $current.focus();

                    if (event.keyCode === 32 || event.keyCode === 13) {
                        var $checkbox = $current.find('input');

                        $checkbox.prop("checked", !$checkbox.prop("checked"));
                        $checkbox.change();
                    }

                    event.stopPropagation();
                    event.preventDefault();
                }
            }, this));

            if(this.options.enableClickableOptGroups && this.options.multiple) {
                $('li.multiselect-group', this.$ul).on('click', $.proxy(function(event) {
                    event.stopPropagation();

                    var group = $(event.target).parent();

                    // Search all option in optgroup
                    var $options = group.nextUntil('li.multiselect-group');
                    var $visibleOptions = $options.filter(":visible:not(.disabled)");

                    // check or uncheck items
                    var allChecked = true;
                    var optionInputs = $visibleOptions.find('input');
                    optionInputs.each(function() {
                        allChecked = allChecked && $(this).prop('checked');
                    });

                    optionInputs.prop('checked', !allChecked).trigger('change');
               }, this));
            }
        },

        /**
         * Create an option using the given select option.
         *
         * @param {jQuery} element
         */
        createOptionValue: function(element) {
            var $element = $(element);
            if ($element.is(':selected')) {
                $element.prop('selected', true);
            }

            // Support the label attribute on options.
            var label = this.options.optionLabel(element);
            var value = $element.val();
            var inputType = this.options.multiple ? "checkbox" : "radio";

            var $li = $(this.options.templates.li);
            var $label = $('label', $li);
            $label.addClass(inputType);

            if (this.options.enableHTML) {
                $label.html(" " + label);
            }
            else {
                $label.text(" " + label);
            }
        
            var $checkbox = $('<input/>').attr('type', inputType);

            if (this.options.checkboxName) {
                $checkbox.attr('name', this.options.checkboxName);
            }
            $label.prepend($checkbox);

            var selected = $element.prop('selected') || false;
            $checkbox.val(value);

            if (value === this.options.selectAllValue) {
                $li.addClass("multiselect-item multiselect-all");
                $checkbox.parent().parent()
                    .addClass('multiselect-all');
            }

            $label.attr('title', $element.attr('title'));

            this.$ul.append($li);

            if ($element.is(':disabled')) {
                $checkbox.attr('disabled', 'disabled')
                    .prop('disabled', true)
                    .closest('a')
                    .attr("tabindex", "-1")
                    .closest('li')
                    .addClass('disabled');
            }

            $checkbox.prop('checked', selected);

            if (selected && this.options.selectedClass) {
                $checkbox.closest('li')
                    .addClass(this.options.selectedClass);
            }
        },

        /**
         * Creates a divider using the given select option.
         *
         * @param {jQuery} element
         */
        createDivider: function(element) {
            var $divider = $(this.options.templates.divider);
            this.$ul.append($divider);
        },

        /**
         * Creates an optgroup.
         *
         * @param {jQuery} group
         */
        createOptgroup: function(group) {
            var groupName = $(group).prop('label');

            // Add a header for the group.
            var $li = $(this.options.templates.liGroup);
            
            if (this.options.enableHTML) {
                $('label', $li).html(groupName);
            }
            else {
                $('label', $li).text(groupName);
            }
            
            if (this.options.enableClickableOptGroups) {
                $li.addClass('multiselect-group-clickable');
            }

            this.$ul.append($li);

            if ($(group).is(':disabled')) {
                $li.addClass('disabled');
            }

            // Add the options of the group.
            $('option', group).each($.proxy(function(index, element) {
                this.createOptionValue(element);
            }, this));
        },

        /**
         * Build the selct all.
         * 
         * Checks if a select all has already been created.
         */
        buildSelectAll: function() {
            if (typeof this.options.selectAllValue === 'number') {
                this.options.selectAllValue = this.options.selectAllValue.toString();
            }
            
            var alreadyHasSelectAll = this.hasSelectAll();

            if (!alreadyHasSelectAll && this.options.includeSelectAllOption && this.options.multiple
                    && $('option', this.$select).length > this.options.includeSelectAllIfMoreThan) {

                // Check whether to add a divider after the select all.
                if (this.options.includeSelectAllDivider) {
                    this.$ul.prepend($(this.options.templates.divider));
                }

                var $li = $(this.options.templates.li);
                $('label', $li).addClass("checkbox");
                
                if (this.options.enableHTML) {
                    $('label', $li).html(" " + this.options.selectAllText);
                }
                else {
                    $('label', $li).text(" " + this.options.selectAllText);
                }
                
                if (this.options.selectAllName) {
                    $('label', $li).prepend('<input type="checkbox" name="' + this.options.selectAllName + '" />');
                }
                else {
                    $('label', $li).prepend('<input type="checkbox" />');
                }
                
                var $checkbox = $('input', $li);
                $checkbox.val(this.options.selectAllValue);

                $li.addClass("multiselect-item multiselect-all");
                $checkbox.parent().parent()
                    .addClass('multiselect-all');

                this.$ul.prepend($li);

                $checkbox.prop('checked', false);
            }
        },

        /**
         * Builds the filter.
         */
        buildFilter: function() {

            // Build filter if filtering OR case insensitive filtering is enabled and the number of options exceeds (or equals) enableFilterLength.
            if (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering) {
                var enableFilterLength = Math.max(this.options.enableFiltering, this.options.enableCaseInsensitiveFiltering);

                if (this.$select.find('option').length >= enableFilterLength) {

                    this.$filter = $(this.options.templates.filter);
                    $('input', this.$filter).attr('placeholder', this.options.filterPlaceholder);
                    
                    // Adds optional filter clear button
                    if(this.options.includeFilterClearBtn){
                        var clearBtn = $(this.options.templates.filterClearBtn);
                        clearBtn.on('click', $.proxy(function(event){
                            clearTimeout(this.searchTimeout);
                            this.$filter.find('.multiselect-search').val('');
                            $('li', this.$ul).show().removeClass("filter-hidden");
                            this.updateSelectAll();
                        }, this));
                        this.$filter.find('.input-group').append(clearBtn);
                    }
                    
                    this.$ul.prepend(this.$filter);

                    this.$filter.val(this.query).on('click', function(event) {
                        event.stopPropagation();
                    }).on('input keydown', $.proxy(function(event) {
                        // Cancel enter key default behaviour
                        if (event.which === 13) {
                          event.preventDefault();
                        }
                        
                        // This is useful to catch "keydown" events after the browser has updated the control.
                        clearTimeout(this.searchTimeout);

                        this.searchTimeout = this.asyncFunction($.proxy(function() {

                            if (this.query !== event.target.value) {
                                this.query = event.target.value;

                                var currentGroup, currentGroupVisible;
                                $.each($('li', this.$ul), $.proxy(function(index, element) {
                                    var value = $('input', element).length > 0 ? $('input', element).val() : "";
                                    var text = $('label', element).text();

                                    var filterCandidate = '';
                                    if ((this.options.filterBehavior === 'text')) {
                                        filterCandidate = text;
                                    }
                                    else if ((this.options.filterBehavior === 'value')) {
                                        filterCandidate = value;
                                    }
                                    else if (this.options.filterBehavior === 'both') {
                                        filterCandidate = text + '\n' + value;
                                    }

                                    if (value !== this.options.selectAllValue && text) {
                                        // By default lets assume that element is not
                                        // interesting for this search.
                                        var showElement = false;

                                        if (this.options.enableCaseInsensitiveFiltering && filterCandidate.toLowerCase().indexOf(this.query.toLowerCase()) > -1) {
                                            showElement = true;
                                        }
                                        else if (filterCandidate.indexOf(this.query) > -1) {
                                            showElement = true;
                                        }

                                        // Toggle current element (group or group item) according to showElement boolean.
                                        $(element).toggle(showElement).toggleClass('filter-hidden', !showElement);
                                        
                                        // Differentiate groups and group items.
                                        if ($(element).hasClass('multiselect-group')) {
                                            // Remember group status.
                                            currentGroup = element;
                                            currentGroupVisible = showElement;
                                        }
                                        else {
                                            // Show group name when at least one of its items is visible.
                                            if (showElement) {
                                                $(currentGroup).show().removeClass('filter-hidden');
                                            }
                                            
                                            // Show all group items when group name satisfies filter.
                                            if (!showElement && currentGroupVisible) {
                                                $(element).show().removeClass('filter-hidden');
                                            }
                                        }
                                    }
                                }, this));
                            }

                            this.updateSelectAll();
                        }, this), 300, this);
                    }, this));
                }
            }
        },

        /**
         * Unbinds the whole plugin.
         */
        destroy: function() {
            this.$container.remove();
            this.$select.show();
            this.$select.data('multiselect', null);
        },

        /**
         * Refreshs the multiselect based on the selected options of the select.
         */
        refresh: function() {
            $('option', this.$select).each($.proxy(function(index, element) {
                var $input = $('li input', this.$ul).filter(function() {
                    return $(this).val() === $(element).val();
                });

                if ($(element).is(':selected')) {
                    $input.prop('checked', true);

                    if (this.options.selectedClass) {
                        $input.closest('li')
                            .addClass(this.options.selectedClass);
                    }
                }
                else {
                    $input.prop('checked', false);

                    if (this.options.selectedClass) {
                        $input.closest('li')
                            .removeClass(this.options.selectedClass);
                    }
                }

                if ($(element).is(":disabled")) {
                    $input.attr('disabled', 'disabled')
                        .prop('disabled', true)
                        .closest('li')
                        .addClass('disabled');
                }
                else {
                    $input.prop('disabled', false)
                        .closest('li')
                        .removeClass('disabled');
                }
            }, this));

            this.updateButtonText();
            this.updateSelectAll();
        },

        /**
         * Select all options of the given values.
         * 
         * If triggerOnChange is set to true, the on change event is triggered if
         * and only if one value is passed.
         * 
         * @param {Array} selectValues
         * @param {Boolean} triggerOnChange
         */
        select: function(selectValues, triggerOnChange) {
            if(!$.isArray(selectValues)) {
                selectValues = [selectValues];
            }

            for (var i = 0; i < selectValues.length; i++) {
                var value = selectValues[i];

                if (value === null || value === undefined) {
                    continue;
                }

                var $option = this.getOptionByValue(value);
                var $checkbox = this.getInputByValue(value);

                if($option === undefined || $checkbox === undefined) {
                    continue;
                }
                
                if (!this.options.multiple) {
                    this.deselectAll(false);
                }
                
                if (this.options.selectedClass) {
                    $checkbox.closest('li')
                        .addClass(this.options.selectedClass);
                }

                $checkbox.prop('checked', true);
                $option.prop('selected', true);
                
                if (triggerOnChange) {
                    this.options.onChange($option, true);
                }
            }

            this.updateButtonText();
            this.updateSelectAll();
        },

        /**
         * Clears all selected items.
         */
        clearSelection: function () {
            this.deselectAll(false);
            this.updateButtonText();
            this.updateSelectAll();
        },

        /**
         * Deselects all options of the given values.
         * 
         * If triggerOnChange is set to true, the on change event is triggered, if
         * and only if one value is passed.
         * 
         * @param {Array} deselectValues
         * @param {Boolean} triggerOnChange
         */
        deselect: function(deselectValues, triggerOnChange) {
            if(!$.isArray(deselectValues)) {
                deselectValues = [deselectValues];
            }

            for (var i = 0; i < deselectValues.length; i++) {
                var value = deselectValues[i];

                if (value === null || value === undefined) {
                    continue;
                }

                var $option = this.getOptionByValue(value);
                var $checkbox = this.getInputByValue(value);

                if($option === undefined || $checkbox === undefined) {
                    continue;
                }

                if (this.options.selectedClass) {
                    $checkbox.closest('li')
                        .removeClass(this.options.selectedClass);
                }

                $checkbox.prop('checked', false);
                $option.prop('selected', false);
                
                if (triggerOnChange) {
                    this.options.onChange($option, false);
                }
            }

            this.updateButtonText();
            this.updateSelectAll();
        },
        
        /**
         * Selects all enabled & visible options.
         *
         * If justVisible is true or not specified, only visible options are selected.
         *
         * @param {Boolean} justVisible
         * @param {Boolean} triggerOnSelectAll
         */
        selectAll: function (justVisible, triggerOnSelectAll) {
            var justVisible = typeof justVisible === 'undefined' ? true : justVisible;
            var allCheckboxes = $("li input[type='checkbox']:enabled", this.$ul);
            var visibleCheckboxes = allCheckboxes.filter(":visible");
            var allCheckboxesCount = allCheckboxes.length;
            var visibleCheckboxesCount = visibleCheckboxes.length;
            
            if(justVisible) {
                visibleCheckboxes.prop('checked', true);
                $("li:not(.divider):not(.disabled)", this.$ul).filter(":visible").addClass(this.options.selectedClass);
            }
            else {
                allCheckboxes.prop('checked', true);
                $("li:not(.divider):not(.disabled)", this.$ul).addClass(this.options.selectedClass);
            }
                
            if (allCheckboxesCount === visibleCheckboxesCount || justVisible === false) {
                $("option:enabled", this.$select).prop('selected', true);
            }
            else {
                var values = visibleCheckboxes.map(function() {
                    return $(this).val();
                }).get();
                
                $("option:enabled", this.$select).filter(function(index) {
                    return $.inArray($(this).val(), values) !== -1;
                }).prop('selected', true);
            }
            
            if (triggerOnSelectAll) {
                this.options.onSelectAll();
            }
        },

        /**
         * Deselects all options.
         * 
         * If justVisible is true or not specified, only visible options are deselected.
         * 
         * @param {Boolean} justVisible
         */
        deselectAll: function (justVisible) {
            var justVisible = typeof justVisible === 'undefined' ? true : justVisible;
            
            if(justVisible) {              
                var visibleCheckboxes = $("li input[type='checkbox']:not(:disabled)", this.$ul).filter(":visible");
                visibleCheckboxes.prop('checked', false);
                
                var values = visibleCheckboxes.map(function() {
                    return $(this).val();
                }).get();
                
                $("option:enabled", this.$select).filter(function(index) {
                    return $.inArray($(this).val(), values) !== -1;
                }).prop('selected', false);
                
                if (this.options.selectedClass) {
                    $("li:not(.divider):not(.disabled)", this.$ul).filter(":visible").removeClass(this.options.selectedClass);
                }
            }
            else {
                $("li input[type='checkbox']:enabled", this.$ul).prop('checked', false);
                $("option:enabled", this.$select).prop('selected', false);
                
                if (this.options.selectedClass) {
                    $("li:not(.divider):not(.disabled)", this.$ul).removeClass(this.options.selectedClass);
                }
            }
        },

        /**
         * Rebuild the plugin.
         * 
         * Rebuilds the dropdown, the filter and the select all option.
         */
        rebuild: function() {
            this.$ul.html('');

            // Important to distinguish between radios and checkboxes.
            this.options.multiple = this.$select.attr('multiple') === "multiple";

            this.buildSelectAll();
            this.buildDropdownOptions();
            this.buildFilter();

            this.updateButtonText();
            this.updateSelectAll();
            
            if (this.options.disableIfEmpty && $('option', this.$select).length <= 0) {
                this.disable();
            }
            else {
                this.enable();
            }
            
            if (this.options.dropRight) {
                this.$ul.addClass('pull-right');
            }
        },

        /**
         * The provided data will be used to build the dropdown.
         */
        dataprovider: function(dataprovider) {
            
            var groupCounter = 0;
            var $select = this.$select.empty();
            
            $.each(dataprovider, function (index, option) {
                var $tag;
                
                if ($.isArray(option.children)) { // create optiongroup tag
                    groupCounter++;
                    
                    $tag = $('<optgroup/>').attr({
                        label: option.label || 'Group ' + groupCounter,
                        disabled: !!option.disabled
                    });
                    
                    forEach(option.children, function(subOption) { // add children option tags
                        $tag.append($('<option/>').attr({
                            value: subOption.value,
                            label: subOption.label || subOption.value,
                            title: subOption.title,
                            selected: !!subOption.selected,
                            disabled: !!subOption.disabled
                        }));
                    });
                }
                else {
                    $tag = $('<option/>').attr({
                        value: option.value,
                        label: option.label || option.value,
                        title: option.title,
                        selected: !!option.selected,
                        disabled: !!option.disabled
                    });
                }
                
                $select.append($tag);
            });
            
            this.rebuild();
        },

        /**
         * Enable the multiselect.
         */
        enable: function() {
            this.$select.prop('disabled', false);
            this.$button.prop('disabled', false)
                .removeClass('disabled');
        },

        /**
         * Disable the multiselect.
         */
        disable: function() {
            this.$select.prop('disabled', true);
            this.$button.prop('disabled', true)
                .addClass('disabled');
        },

        /**
         * Set the options.
         *
         * @param {Array} options
         */
        setOptions: function(options) {
            this.options = this.mergeOptions(options);
        },

        /**
         * Merges the given options with the default options.
         *
         * @param {Array} options
         * @returns {Array}
         */
        mergeOptions: function(options) {
            return $.extend(true, {}, this.defaults, this.options, options);
        },

        /**
         * Checks whether a select all checkbox is present.
         *
         * @returns {Boolean}
         */
        hasSelectAll: function() {
            return $('li.multiselect-all', this.$ul).length > 0;
        },

        /**
         * Updates the select all checkbox based on the currently displayed and selected checkboxes.
         */
        updateSelectAll: function() {
            if (this.hasSelectAll()) {
                var allBoxes = $("li:not(.multiselect-item):not(.filter-hidden) input:enabled", this.$ul);
                var allBoxesLength = allBoxes.length;
                var checkedBoxesLength = allBoxes.filter(":checked").length;
                var selectAllLi  = $("li.multiselect-all", this.$ul);
                var selectAllInput = selectAllLi.find("input");
                
                if (checkedBoxesLength > 0 && checkedBoxesLength === allBoxesLength) {
                    selectAllInput.prop("checked", true);
                    selectAllLi.addClass(this.options.selectedClass);
                    this.options.onSelectAll();
                }
                else {
                    selectAllInput.prop("checked", false);
                    selectAllLi.removeClass(this.options.selectedClass);
                }
            }
        },

        /**
         * Update the button text and its title based on the currently selected options.
         */
        updateButtonText: function() {
            var options = this.getSelected();
            
            // First update the displayed button text.
            if (this.options.enableHTML) {
                $('.multiselect .multiselect-selected-text', this.$container).html(this.options.buttonText(options, this.$select));
            }
            else {
                $('.multiselect .multiselect-selected-text', this.$container).text(this.options.buttonText(options, this.$select));
            }
            
            // Now update the title attribute of the button.
            $('.multiselect', this.$container).attr('title', this.options.buttonTitle(options, this.$select));
        },

        /**
         * Get all selected options.
         *
         * @returns {jQUery}
         */
        getSelected: function() {
            return $('option', this.$select).filter(":selected");
        },

        /**
         * Gets a select option by its value.
         *
         * @param {String} value
         * @returns {jQuery}
         */
        getOptionByValue: function (value) {

            var options = $('option', this.$select);
            var valueToCompare = value.toString();

            for (var i = 0; i < options.length; i = i + 1) {
                var option = options[i];
                if (option.value === valueToCompare) {
                    return $(option);
                }
            }
        },

        /**
         * Get the input (radio/checkbox) by its value.
         *
         * @param {String} value
         * @returns {jQuery}
         */
        getInputByValue: function (value) {

            var checkboxes = $('li input', this.$ul);
            var valueToCompare = value.toString();

            for (var i = 0; i < checkboxes.length; i = i + 1) {
                var checkbox = checkboxes[i];
                if (checkbox.value === valueToCompare) {
                    return $(checkbox);
                }
            }
        },

        /**
         * Used for knockout integration.
         */
        updateOriginalOptions: function() {
            this.originalOptions = this.$select.clone()[0].options;
        },

        asyncFunction: function(callback, timeout, self) {
            var args = Array.prototype.slice.call(arguments, 3);
            return setTimeout(function() {
                callback.apply(self || window, args);
            }, timeout);
        },

        setAllSelectedText: function(allSelectedText) {
            this.options.allSelectedText = allSelectedText;
            this.updateButtonText();
        }
    };

    $.fn.multiselect = function(option, parameter, extraOptions) {
        return this.each(function() {
            var data = $(this).data('multiselect');
            var options = typeof option === 'object' && option;

            // Initialize the multiselect.
            if (!data) {
                data = new Multiselect(this, options);
                $(this).data('multiselect', data);
            }

            // Call multiselect method.
            if (typeof option === 'string') {
                data[option](parameter, extraOptions);
                
                if (option === 'destroy') {
                    $(this).data('multiselect', false);
                }
            }
        });
    };

    $.fn.multiselect.Constructor = Multiselect;

    $(function() {
        $("select[data-role=multiselect]").multiselect();
    });

}(window.jQuery);
;
/*!
   SpryMedia Ltd.

 This source file is free software, available under the following license:
   MIT license - http://datatables.net/license

 This source file is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.

 For details please refer to: http://www.datatables.net
 DataTables 1.12.1
 ©2008-2022 SpryMedia Ltd - datatables.net/license
*/
var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.findInternal=function(l,y,A){l instanceof String&&(l=String(l));for(var q=l.length,E=0;E<q;E++){var P=l[E];if(y.call(A,P,E,l))return{i:E,v:P}}return{i:-1,v:void 0}};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.SIMPLE_FROUND_POLYFILL=!1;$jscomp.ISOLATE_POLYFILLS=!1;
$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(l,y,A){if(l==Array.prototype||l==Object.prototype)return l;l[y]=A.value;return l};$jscomp.getGlobal=function(l){l=["object"==typeof globalThis&&globalThis,l,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var y=0;y<l.length;++y){var A=l[y];if(A&&A.Math==Math)return A}throw Error("Cannot find global object");};$jscomp.global=$jscomp.getGlobal(this);
$jscomp.IS_SYMBOL_NATIVE="function"===typeof Symbol&&"symbol"===typeof Symbol("x");$jscomp.TRUST_ES6_POLYFILLS=!$jscomp.ISOLATE_POLYFILLS||$jscomp.IS_SYMBOL_NATIVE;$jscomp.polyfills={};$jscomp.propertyToPolyfillSymbol={};$jscomp.POLYFILL_PREFIX="$jscp$";var $jscomp$lookupPolyfilledValue=function(l,y){var A=$jscomp.propertyToPolyfillSymbol[y];if(null==A)return l[y];A=l[A];return void 0!==A?A:l[y]};
$jscomp.polyfill=function(l,y,A,q){y&&($jscomp.ISOLATE_POLYFILLS?$jscomp.polyfillIsolated(l,y,A,q):$jscomp.polyfillUnisolated(l,y,A,q))};$jscomp.polyfillUnisolated=function(l,y,A,q){A=$jscomp.global;l=l.split(".");for(q=0;q<l.length-1;q++){var E=l[q];if(!(E in A))return;A=A[E]}l=l[l.length-1];q=A[l];y=y(q);y!=q&&null!=y&&$jscomp.defineProperty(A,l,{configurable:!0,writable:!0,value:y})};
$jscomp.polyfillIsolated=function(l,y,A,q){var E=l.split(".");l=1===E.length;q=E[0];q=!l&&q in $jscomp.polyfills?$jscomp.polyfills:$jscomp.global;for(var P=0;P<E.length-1;P++){var la=E[P];if(!(la in q))return;q=q[la]}E=E[E.length-1];A=$jscomp.IS_SYMBOL_NATIVE&&"es6"===A?q[E]:null;y=y(A);null!=y&&(l?$jscomp.defineProperty($jscomp.polyfills,E,{configurable:!0,writable:!0,value:y}):y!==A&&($jscomp.propertyToPolyfillSymbol[E]=$jscomp.IS_SYMBOL_NATIVE?$jscomp.global.Symbol(E):$jscomp.POLYFILL_PREFIX+E,
E=$jscomp.propertyToPolyfillSymbol[E],$jscomp.defineProperty(q,E,{configurable:!0,writable:!0,value:y})))};$jscomp.polyfill("Array.prototype.find",function(l){return l?l:function(y,A){return $jscomp.findInternal(this,y,A).v}},"es6","es3");
(function(l){"function"===typeof define&&define.amd?define(["jquery"],function(y){return l(y,window,document)}):"object"===typeof exports?module.exports=function(y,A){y||(y=window);A||(A="undefined"!==typeof window?require("jquery"):require("jquery")(y));return l(A,y,y.document)}:window.DataTable=l(jQuery,window,document)})(function(l,y,A,q){function E(a){var b,c,d={};l.each(a,function(e,h){(b=e.match(/^([^A-Z]+?)([A-Z])/))&&-1!=="a aa ai ao as b fn i m o s ".indexOf(b[1]+" ")&&(c=e.replace(b[0],
b[2].toLowerCase()),d[c]=e,"o"===b[1]&&E(a[e]))});a._hungarianMap=d}function P(a,b,c){a._hungarianMap||E(a);var d;l.each(b,function(e,h){d=a._hungarianMap[e];d===q||!c&&b[d]!==q||("o"===d.charAt(0)?(b[d]||(b[d]={}),l.extend(!0,b[d],b[e]),P(a[d],b[d],c)):b[d]=b[e])})}function la(a){var b=u.defaults.oLanguage,c=b.sDecimal;c&&bb(c);if(a){var d=a.sZeroRecords;!a.sEmptyTable&&d&&"No data available in table"===b.sEmptyTable&&Y(a,a,"sZeroRecords","sEmptyTable");!a.sLoadingRecords&&d&&"Loading..."===b.sLoadingRecords&&
Y(a,a,"sZeroRecords","sLoadingRecords");a.sInfoThousands&&(a.sThousands=a.sInfoThousands);(a=a.sDecimal)&&c!==a&&bb(a)}}function Db(a){S(a,"ordering","bSort");S(a,"orderMulti","bSortMulti");S(a,"orderClasses","bSortClasses");S(a,"orderCellsTop","bSortCellsTop");S(a,"order","aaSorting");S(a,"orderFixed","aaSortingFixed");S(a,"paging","bPaginate");S(a,"pagingType","sPaginationType");S(a,"pageLength","iDisplayLength");S(a,"searching","bFilter");"boolean"===typeof a.sScrollX&&(a.sScrollX=a.sScrollX?"100%":
"");"boolean"===typeof a.scrollX&&(a.scrollX=a.scrollX?"100%":"");if(a=a.aoSearchCols)for(var b=0,c=a.length;b<c;b++)a[b]&&P(u.models.oSearch,a[b])}function Eb(a){S(a,"orderable","bSortable");S(a,"orderData","aDataSort");S(a,"orderSequence","asSorting");S(a,"orderDataType","sortDataType");var b=a.aDataSort;"number"!==typeof b||Array.isArray(b)||(a.aDataSort=[b])}function Fb(a){if(!u.__browser){var b={};u.__browser=b;var c=l("<div/>").css({position:"fixed",top:0,left:-1*l(y).scrollLeft(),height:1,
width:1,overflow:"hidden"}).append(l("<div/>").css({position:"absolute",top:1,left:1,width:100,overflow:"scroll"}).append(l("<div/>").css({width:"100%",height:10}))).appendTo("body"),d=c.children(),e=d.children();b.barWidth=d[0].offsetWidth-d[0].clientWidth;b.bScrollOversize=100===e[0].offsetWidth&&100!==d[0].clientWidth;b.bScrollbarLeft=1!==Math.round(e.offset().left);b.bBounding=c[0].getBoundingClientRect().width?!0:!1;c.remove()}l.extend(a.oBrowser,u.__browser);a.oScroll.iBarWidth=u.__browser.barWidth}
function Gb(a,b,c,d,e,h){var f=!1;if(c!==q){var g=c;f=!0}for(;d!==e;)a.hasOwnProperty(d)&&(g=f?b(g,a[d],d,a):a[d],f=!0,d+=h);return g}function cb(a,b){var c=u.defaults.column,d=a.aoColumns.length;c=l.extend({},u.models.oColumn,c,{nTh:b?b:A.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.mData:d,idx:d});a.aoColumns.push(c);c=a.aoPreSearchCols;c[d]=l.extend({},u.models.oSearch,c[d]);Ia(a,d,l(b).data())}function Ia(a,b,c){b=a.aoColumns[b];
var d=a.oClasses,e=l(b.nTh);if(!b.sWidthOrig){b.sWidthOrig=e.attr("width")||null;var h=(e.attr("style")||"").match(/width:\s*(\d+[pxem%]+)/);h&&(b.sWidthOrig=h[1])}c!==q&&null!==c&&(Eb(c),P(u.defaults.column,c,!0),c.mDataProp===q||c.mData||(c.mData=c.mDataProp),c.sType&&(b._sManualType=c.sType),c.className&&!c.sClass&&(c.sClass=c.className),c.sClass&&e.addClass(c.sClass),h=b.sClass,l.extend(b,c),Y(b,c,"sWidth","sWidthOrig"),h!==b.sClass&&(b.sClass=h+" "+b.sClass),c.iDataSort!==q&&(b.aDataSort=[c.iDataSort]),
Y(b,c,"aDataSort"));var f=b.mData,g=ma(f),k=b.mRender?ma(b.mRender):null;c=function(m){return"string"===typeof m&&-1!==m.indexOf("@")};b._bAttrSrc=l.isPlainObject(f)&&(c(f.sort)||c(f.type)||c(f.filter));b._setter=null;b.fnGetData=function(m,n,p){var t=g(m,n,q,p);return k&&n?k(t,n,m,p):t};b.fnSetData=function(m,n,p){return ha(f)(m,n,p)};"number"!==typeof f&&(a._rowReadObject=!0);a.oFeatures.bSort||(b.bSortable=!1,e.addClass(d.sSortableNone));a=-1!==l.inArray("asc",b.asSorting);c=-1!==l.inArray("desc",
b.asSorting);b.bSortable&&(a||c)?a&&!c?(b.sSortingClass=d.sSortableAsc,b.sSortingClassJUI=d.sSortJUIAscAllowed):!a&&c?(b.sSortingClass=d.sSortableDesc,b.sSortingClassJUI=d.sSortJUIDescAllowed):(b.sSortingClass=d.sSortable,b.sSortingClassJUI=d.sSortJUI):(b.sSortingClass=d.sSortableNone,b.sSortingClassJUI="")}function sa(a){if(!1!==a.oFeatures.bAutoWidth){var b=a.aoColumns;db(a);for(var c=0,d=b.length;c<d;c++)b[c].nTh.style.width=b[c].sWidth}b=a.oScroll;""===b.sY&&""===b.sX||Ja(a);F(a,null,"column-sizing",
[a])}function ta(a,b){a=Ka(a,"bVisible");return"number"===typeof a[b]?a[b]:null}function ua(a,b){a=Ka(a,"bVisible");b=l.inArray(b,a);return-1!==b?b:null}function na(a){var b=0;l.each(a.aoColumns,function(c,d){d.bVisible&&"none"!==l(d.nTh).css("display")&&b++});return b}function Ka(a,b){var c=[];l.map(a.aoColumns,function(d,e){d[b]&&c.push(e)});return c}function eb(a){var b=a.aoColumns,c=a.aoData,d=u.ext.type.detect,e,h,f;var g=0;for(e=b.length;g<e;g++){var k=b[g];var m=[];if(!k.sType&&k._sManualType)k.sType=
k._sManualType;else if(!k.sType){var n=0;for(h=d.length;n<h;n++){var p=0;for(f=c.length;p<f;p++){m[p]===q&&(m[p]=T(a,p,g,"type"));var t=d[n](m[p],a);if(!t&&n!==d.length-1)break;if("html"===t&&!aa(m[p]))break}if(t){k.sType=t;break}}k.sType||(k.sType="string")}}}function Hb(a,b,c,d){var e,h,f,g=a.aoColumns;if(b)for(e=b.length-1;0<=e;e--){var k=b[e];var m=k.target!==q?k.target:k.targets!==q?k.targets:k.aTargets;Array.isArray(m)||(m=[m]);var n=0;for(h=m.length;n<h;n++)if("number"===typeof m[n]&&0<=m[n]){for(;g.length<=
m[n];)cb(a);d(m[n],k)}else if("number"===typeof m[n]&&0>m[n])d(g.length+m[n],k);else if("string"===typeof m[n]){var p=0;for(f=g.length;p<f;p++)("_all"==m[n]||l(g[p].nTh).hasClass(m[n]))&&d(p,k)}}if(c)for(e=0,a=c.length;e<a;e++)d(e,c[e])}function ia(a,b,c,d){var e=a.aoData.length,h=l.extend(!0,{},u.models.oRow,{src:c?"dom":"data",idx:e});h._aData=b;a.aoData.push(h);for(var f=a.aoColumns,g=0,k=f.length;g<k;g++)f[g].sType=null;a.aiDisplayMaster.push(e);b=a.rowIdFn(b);b!==q&&(a.aIds[b]=h);!c&&a.oFeatures.bDeferRender||
fb(a,e,c,d);return e}function La(a,b){var c;b instanceof l||(b=l(b));return b.map(function(d,e){c=gb(a,e);return ia(a,c.data,e,c.cells)})}function T(a,b,c,d){"search"===d?d="filter":"order"===d&&(d="sort");var e=a.iDraw,h=a.aoColumns[c],f=a.aoData[b]._aData,g=h.sDefaultContent,k=h.fnGetData(f,d,{settings:a,row:b,col:c});if(k===q)return a.iDrawError!=e&&null===g&&(ea(a,0,"Requested unknown parameter "+("function"==typeof h.mData?"{function}":"'"+h.mData+"'")+" for row "+b+", column "+c,4),a.iDrawError=
e),g;if((k===f||null===k)&&null!==g&&d!==q)k=g;else if("function"===typeof k)return k.call(f);if(null===k&&"display"===d)return"";"filter"===d&&(a=u.ext.type.search,a[h.sType]&&(k=a[h.sType](k)));return k}function Ib(a,b,c,d){a.aoColumns[c].fnSetData(a.aoData[b]._aData,d,{settings:a,row:b,col:c})}function hb(a){return l.map(a.match(/(\\.|[^\.])+/g)||[""],function(b){return b.replace(/\\\./g,".")})}function ib(a){return U(a.aoData,"_aData")}function Ma(a){a.aoData.length=0;a.aiDisplayMaster.length=
0;a.aiDisplay.length=0;a.aIds={}}function Na(a,b,c){for(var d=-1,e=0,h=a.length;e<h;e++)a[e]==b?d=e:a[e]>b&&a[e]--; -1!=d&&c===q&&a.splice(d,1)}function va(a,b,c,d){var e=a.aoData[b],h,f=function(k,m){for(;k.childNodes.length;)k.removeChild(k.firstChild);k.innerHTML=T(a,b,m,"display")};if("dom"!==c&&(c&&"auto"!==c||"dom"!==e.src)){var g=e.anCells;if(g)if(d!==q)f(g[d],d);else for(c=0,h=g.length;c<h;c++)f(g[c],c)}else e._aData=gb(a,e,d,d===q?q:e._aData).data;e._aSortData=null;e._aFilterData=null;f=
a.aoColumns;if(d!==q)f[d].sType=null;else{c=0;for(h=f.length;c<h;c++)f[c].sType=null;jb(a,e)}}function gb(a,b,c,d){var e=[],h=b.firstChild,f,g=0,k,m=a.aoColumns,n=a._rowReadObject;d=d!==q?d:n?{}:[];var p=function(x,w){if("string"===typeof x){var r=x.indexOf("@");-1!==r&&(r=x.substring(r+1),ha(x)(d,w.getAttribute(r)))}},t=function(x){if(c===q||c===g)f=m[g],k=x.innerHTML.trim(),f&&f._bAttrSrc?(ha(f.mData._)(d,k),p(f.mData.sort,x),p(f.mData.type,x),p(f.mData.filter,x)):n?(f._setter||(f._setter=ha(f.mData)),
f._setter(d,k)):d[g]=k;g++};if(h)for(;h;){var v=h.nodeName.toUpperCase();if("TD"==v||"TH"==v)t(h),e.push(h);h=h.nextSibling}else for(e=b.anCells,h=0,v=e.length;h<v;h++)t(e[h]);(b=b.firstChild?b:b.nTr)&&(b=b.getAttribute("id"))&&ha(a.rowId)(d,b);return{data:d,cells:e}}function fb(a,b,c,d){var e=a.aoData[b],h=e._aData,f=[],g,k;if(null===e.nTr){var m=c||A.createElement("tr");e.nTr=m;e.anCells=f;m._DT_RowIndex=b;jb(a,e);var n=0;for(g=a.aoColumns.length;n<g;n++){var p=a.aoColumns[n];e=(k=c?!1:!0)?A.createElement(p.sCellType):
d[n];e._DT_CellIndex={row:b,column:n};f.push(e);if(k||!(!p.mRender&&p.mData===n||l.isPlainObject(p.mData)&&p.mData._===n+".display"))e.innerHTML=T(a,b,n,"display");p.sClass&&(e.className+=" "+p.sClass);p.bVisible&&!c?m.appendChild(e):!p.bVisible&&c&&e.parentNode.removeChild(e);p.fnCreatedCell&&p.fnCreatedCell.call(a.oInstance,e,T(a,b,n),h,b,n)}F(a,"aoRowCreatedCallback",null,[m,h,b,f])}}function jb(a,b){var c=b.nTr,d=b._aData;if(c){if(a=a.rowIdFn(d))c.id=a;d.DT_RowClass&&(a=d.DT_RowClass.split(" "),
b.__rowc=b.__rowc?Oa(b.__rowc.concat(a)):a,l(c).removeClass(b.__rowc.join(" ")).addClass(d.DT_RowClass));d.DT_RowAttr&&l(c).attr(d.DT_RowAttr);d.DT_RowData&&l(c).data(d.DT_RowData)}}function Jb(a){var b,c,d=a.nTHead,e=a.nTFoot,h=0===l("th, td",d).length,f=a.oClasses,g=a.aoColumns;h&&(c=l("<tr/>").appendTo(d));var k=0;for(b=g.length;k<b;k++){var m=g[k];var n=l(m.nTh).addClass(m.sClass);h&&n.appendTo(c);a.oFeatures.bSort&&(n.addClass(m.sSortingClass),!1!==m.bSortable&&(n.attr("tabindex",a.iTabIndex).attr("aria-controls",
a.sTableId),kb(a,m.nTh,k)));m.sTitle!=n[0].innerHTML&&n.html(m.sTitle);lb(a,"header")(a,n,m,f)}h&&wa(a.aoHeader,d);l(d).children("tr").children("th, td").addClass(f.sHeaderTH);l(e).children("tr").children("th, td").addClass(f.sFooterTH);if(null!==e)for(a=a.aoFooter[0],k=0,b=a.length;k<b;k++)m=g[k],m.nTf=a[k].cell,m.sClass&&l(m.nTf).addClass(m.sClass)}function xa(a,b,c){var d,e,h=[],f=[],g=a.aoColumns.length;if(b){c===q&&(c=!1);var k=0;for(d=b.length;k<d;k++){h[k]=b[k].slice();h[k].nTr=b[k].nTr;for(e=
g-1;0<=e;e--)a.aoColumns[e].bVisible||c||h[k].splice(e,1);f.push([])}k=0;for(d=h.length;k<d;k++){if(a=h[k].nTr)for(;e=a.firstChild;)a.removeChild(e);e=0;for(b=h[k].length;e<b;e++){var m=g=1;if(f[k][e]===q){a.appendChild(h[k][e].cell);for(f[k][e]=1;h[k+g]!==q&&h[k][e].cell==h[k+g][e].cell;)f[k+g][e]=1,g++;for(;h[k][e+m]!==q&&h[k][e].cell==h[k][e+m].cell;){for(c=0;c<g;c++)f[k+c][e+m]=1;m++}l(h[k][e].cell).attr("rowspan",g).attr("colspan",m)}}}}}function ja(a,b){var c="ssp"==Q(a),d=a.iInitDisplayStart;
d!==q&&-1!==d&&(a._iDisplayStart=c?d:d>=a.fnRecordsDisplay()?0:d,a.iInitDisplayStart=-1);c=F(a,"aoPreDrawCallback","preDraw",[a]);if(-1!==l.inArray(!1,c))V(a,!1);else{c=[];var e=0;d=a.asStripeClasses;var h=d.length,f=a.oLanguage,g="ssp"==Q(a),k=a.aiDisplay,m=a._iDisplayStart,n=a.fnDisplayEnd();a.bDrawing=!0;if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++,V(a,!1);else if(!g)a.iDraw++;else if(!a.bDestroying&&!b){Kb(a);return}if(0!==k.length)for(b=g?a.aoData.length:n,f=g?0:m;f<b;f++){g=k[f];var p=a.aoData[g];
null===p.nTr&&fb(a,g);var t=p.nTr;if(0!==h){var v=d[e%h];p._sRowStripe!=v&&(l(t).removeClass(p._sRowStripe).addClass(v),p._sRowStripe=v)}F(a,"aoRowCallback",null,[t,p._aData,e,f,g]);c.push(t);e++}else e=f.sZeroRecords,1==a.iDraw&&"ajax"==Q(a)?e=f.sLoadingRecords:f.sEmptyTable&&0===a.fnRecordsTotal()&&(e=f.sEmptyTable),c[0]=l("<tr/>",{"class":h?d[0]:""}).append(l("<td />",{valign:"top",colSpan:na(a),"class":a.oClasses.sRowEmpty}).html(e))[0];F(a,"aoHeaderCallback","header",[l(a.nTHead).children("tr")[0],
ib(a),m,n,k]);F(a,"aoFooterCallback","footer",[l(a.nTFoot).children("tr")[0],ib(a),m,n,k]);d=l(a.nTBody);d.children().detach();d.append(l(c));F(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing=!1}}function ka(a,b){var c=a.oFeatures,d=c.bFilter;c.bSort&&Lb(a);d?ya(a,a.oPreviousSearch):a.aiDisplay=a.aiDisplayMaster.slice();!0!==b&&(a._iDisplayStart=0);a._drawHold=b;ja(a);a._drawHold=!1}function Mb(a){var b=a.oClasses,c=l(a.nTable);c=l("<div/>").insertBefore(c);var d=a.oFeatures,
e=l("<div/>",{id:a.sTableId+"_wrapper","class":b.sWrapper+(a.nTFoot?"":" "+b.sNoFooter)});a.nHolding=c[0];a.nTableWrapper=e[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var h=a.sDom.split(""),f,g,k,m,n,p,t=0;t<h.length;t++){f=null;g=h[t];if("<"==g){k=l("<div/>")[0];m=h[t+1];if("'"==m||'"'==m){n="";for(p=2;h[t+p]!=m;)n+=h[t+p],p++;"H"==n?n=b.sJUIHeader:"F"==n&&(n=b.sJUIFooter);-1!=n.indexOf(".")?(m=n.split("."),k.id=m[0].substr(1,m[0].length-1),k.className=m[1]):"#"==n.charAt(0)?k.id=n.substr(1,
n.length-1):k.className=n;t+=p}e.append(k);e=l(k)}else if(">"==g)e=e.parent();else if("l"==g&&d.bPaginate&&d.bLengthChange)f=Nb(a);else if("f"==g&&d.bFilter)f=Ob(a);else if("r"==g&&d.bProcessing)f=Pb(a);else if("t"==g)f=Qb(a);else if("i"==g&&d.bInfo)f=Rb(a);else if("p"==g&&d.bPaginate)f=Sb(a);else if(0!==u.ext.feature.length)for(k=u.ext.feature,p=0,m=k.length;p<m;p++)if(g==k[p].cFeature){f=k[p].fnInit(a);break}f&&(k=a.aanFeatures,k[g]||(k[g]=[]),k[g].push(f),e.append(f))}c.replaceWith(e);a.nHolding=
null}function wa(a,b){b=l(b).children("tr");var c,d,e;a.splice(0,a.length);var h=0;for(e=b.length;h<e;h++)a.push([]);h=0;for(e=b.length;h<e;h++){var f=b[h];for(c=f.firstChild;c;){if("TD"==c.nodeName.toUpperCase()||"TH"==c.nodeName.toUpperCase()){var g=1*c.getAttribute("colspan");var k=1*c.getAttribute("rowspan");g=g&&0!==g&&1!==g?g:1;k=k&&0!==k&&1!==k?k:1;var m=0;for(d=a[h];d[m];)m++;var n=m;var p=1===g?!0:!1;for(d=0;d<g;d++)for(m=0;m<k;m++)a[h+m][n+d]={cell:c,unique:p},a[h+m].nTr=f}c=c.nextSibling}}}
function Pa(a,b,c){var d=[];c||(c=a.aoHeader,b&&(c=[],wa(c,b)));b=0;for(var e=c.length;b<e;b++)for(var h=0,f=c[b].length;h<f;h++)!c[b][h].unique||d[h]&&a.bSortCellsTop||(d[h]=c[b][h].cell);return d}function Qa(a,b,c){F(a,"aoServerParams","serverParams",[b]);if(b&&Array.isArray(b)){var d={},e=/(.*?)\[\]$/;l.each(b,function(n,p){(n=p.name.match(e))?(n=n[0],d[n]||(d[n]=[]),d[n].push(p.value)):d[p.name]=p.value});b=d}var h=a.ajax,f=a.oInstance,g=function(n){var p=a.jqXHR?a.jqXHR.status:null;if(null===
n||"number"===typeof p&&204==p)n={},za(a,n,[]);(p=n.error||n.sError)&&ea(a,0,p);a.json=n;F(a,null,"xhr",[a,n,a.jqXHR]);c(n)};if(l.isPlainObject(h)&&h.data){var k=h.data;var m="function"===typeof k?k(b,a):k;b="function"===typeof k&&m?m:l.extend(!0,b,m);delete h.data}m={data:b,success:g,dataType:"json",cache:!1,type:a.sServerMethod,error:function(n,p,t){t=F(a,null,"xhr",[a,null,a.jqXHR]);-1===l.inArray(!0,t)&&("parsererror"==p?ea(a,0,"Invalid JSON response",1):4===n.readyState&&ea(a,0,"Ajax error",
7));V(a,!1)}};a.oAjaxData=b;F(a,null,"preXhr",[a,b]);a.fnServerData?a.fnServerData.call(f,a.sAjaxSource,l.map(b,function(n,p){return{name:p,value:n}}),g,a):a.sAjaxSource||"string"===typeof h?a.jqXHR=l.ajax(l.extend(m,{url:h||a.sAjaxSource})):"function"===typeof h?a.jqXHR=h.call(f,b,g,a):(a.jqXHR=l.ajax(l.extend(m,h)),h.data=k)}function Kb(a){a.iDraw++;V(a,!0);Qa(a,Tb(a),function(b){Ub(a,b)})}function Tb(a){var b=a.aoColumns,c=b.length,d=a.oFeatures,e=a.oPreviousSearch,h=a.aoPreSearchCols,f=[],g=oa(a);
var k=a._iDisplayStart;var m=!1!==d.bPaginate?a._iDisplayLength:-1;var n=function(x,w){f.push({name:x,value:w})};n("sEcho",a.iDraw);n("iColumns",c);n("sColumns",U(b,"sName").join(","));n("iDisplayStart",k);n("iDisplayLength",m);var p={draw:a.iDraw,columns:[],order:[],start:k,length:m,search:{value:e.sSearch,regex:e.bRegex}};for(k=0;k<c;k++){var t=b[k];var v=h[k];m="function"==typeof t.mData?"function":t.mData;p.columns.push({data:m,name:t.sName,searchable:t.bSearchable,orderable:t.bSortable,search:{value:v.sSearch,
regex:v.bRegex}});n("mDataProp_"+k,m);d.bFilter&&(n("sSearch_"+k,v.sSearch),n("bRegex_"+k,v.bRegex),n("bSearchable_"+k,t.bSearchable));d.bSort&&n("bSortable_"+k,t.bSortable)}d.bFilter&&(n("sSearch",e.sSearch),n("bRegex",e.bRegex));d.bSort&&(l.each(g,function(x,w){p.order.push({column:w.col,dir:w.dir});n("iSortCol_"+x,w.col);n("sSortDir_"+x,w.dir)}),n("iSortingCols",g.length));b=u.ext.legacy.ajax;return null===b?a.sAjaxSource?f:p:b?f:p}function Ub(a,b){var c=function(f,g){return b[f]!==q?b[f]:b[g]},
d=za(a,b),e=c("sEcho","draw"),h=c("iTotalRecords","recordsTotal");c=c("iTotalDisplayRecords","recordsFiltered");if(e!==q){if(1*e<a.iDraw)return;a.iDraw=1*e}d||(d=[]);Ma(a);a._iRecordsTotal=parseInt(h,10);a._iRecordsDisplay=parseInt(c,10);e=0;for(h=d.length;e<h;e++)ia(a,d[e]);a.aiDisplay=a.aiDisplayMaster.slice();ja(a,!0);a._bInitComplete||Ra(a,b);V(a,!1)}function za(a,b,c){a=l.isPlainObject(a.ajax)&&a.ajax.dataSrc!==q?a.ajax.dataSrc:a.sAjaxDataProp;if(!c)return"data"===a?b.aaData||b[a]:""!==a?ma(a)(b):
b;ha(a)(b,c)}function Ob(a){var b=a.oClasses,c=a.sTableId,d=a.oLanguage,e=a.oPreviousSearch,h=a.aanFeatures,f='<input type="search" class="'+b.sFilterInput+'"/>',g=d.sSearch;g=g.match(/_INPUT_/)?g.replace("_INPUT_",f):g+f;b=l("<div/>",{id:h.f?null:c+"_filter","class":b.sFilter}).append(l("<label/>").append(g));var k=function(n){var p=this.value?this.value:"";e.return&&"Enter"!==n.key||p==e.sSearch||(ya(a,{sSearch:p,bRegex:e.bRegex,bSmart:e.bSmart,bCaseInsensitive:e.bCaseInsensitive,"return":e.return}),
a._iDisplayStart=0,ja(a))};h=null!==a.searchDelay?a.searchDelay:"ssp"===Q(a)?400:0;var m=l("input",b).val(e.sSearch).attr("placeholder",d.sSearchPlaceholder).on("keyup.DT search.DT input.DT paste.DT cut.DT",h?mb(k,h):k).on("mouseup",function(n){setTimeout(function(){k.call(m[0],n)},10)}).on("keypress.DT",function(n){if(13==n.keyCode)return!1}).attr("aria-controls",c);l(a.nTable).on("search.dt.DT",function(n,p){if(a===p)try{m[0]!==A.activeElement&&m.val(e.sSearch)}catch(t){}});return b[0]}function ya(a,
b,c){var d=a.oPreviousSearch,e=a.aoPreSearchCols,h=function(g){d.sSearch=g.sSearch;d.bRegex=g.bRegex;d.bSmart=g.bSmart;d.bCaseInsensitive=g.bCaseInsensitive;d.return=g.return},f=function(g){return g.bEscapeRegex!==q?!g.bEscapeRegex:g.bRegex};eb(a);if("ssp"!=Q(a)){Vb(a,b.sSearch,c,f(b),b.bSmart,b.bCaseInsensitive,b.return);h(b);for(b=0;b<e.length;b++)Wb(a,e[b].sSearch,b,f(e[b]),e[b].bSmart,e[b].bCaseInsensitive);Xb(a)}else h(b);a.bFiltered=!0;F(a,null,"search",[a])}function Xb(a){for(var b=u.ext.search,
c=a.aiDisplay,d,e,h=0,f=b.length;h<f;h++){for(var g=[],k=0,m=c.length;k<m;k++)e=c[k],d=a.aoData[e],b[h](a,d._aFilterData,e,d._aData,k)&&g.push(e);c.length=0;l.merge(c,g)}}function Wb(a,b,c,d,e,h){if(""!==b){var f=[],g=a.aiDisplay;d=nb(b,d,e,h);for(e=0;e<g.length;e++)b=a.aoData[g[e]]._aFilterData[c],d.test(b)&&f.push(g[e]);a.aiDisplay=f}}function Vb(a,b,c,d,e,h){e=nb(b,d,e,h);var f=a.oPreviousSearch.sSearch,g=a.aiDisplayMaster;h=[];0!==u.ext.search.length&&(c=!0);var k=Yb(a);if(0>=b.length)a.aiDisplay=
g.slice();else{if(k||c||d||f.length>b.length||0!==b.indexOf(f)||a.bSorted)a.aiDisplay=g.slice();b=a.aiDisplay;for(c=0;c<b.length;c++)e.test(a.aoData[b[c]]._sFilterRow)&&h.push(b[c]);a.aiDisplay=h}}function nb(a,b,c,d){a=b?a:ob(a);c&&(a="^(?=.*?"+l.map(a.match(/"[^"]+"|[^ ]+/g)||[""],function(e){if('"'===e.charAt(0)){var h=e.match(/^"(.*)"$/);e=h?h[1]:e}return e.replace('"',"")}).join(")(?=.*?")+").*$");return new RegExp(a,d?"i":"")}function Yb(a){var b=a.aoColumns,c,d;var e=!1;var h=0;for(c=a.aoData.length;h<
c;h++){var f=a.aoData[h];if(!f._aFilterData){var g=[];e=0;for(d=b.length;e<d;e++){var k=b[e];k.bSearchable?(k=T(a,h,e,"filter"),null===k&&(k=""),"string"!==typeof k&&k.toString&&(k=k.toString())):k="";k.indexOf&&-1!==k.indexOf("&")&&(Sa.innerHTML=k,k=Bc?Sa.textContent:Sa.innerText);k.replace&&(k=k.replace(/[\r\n\u2028]/g,""));g.push(k)}f._aFilterData=g;f._sFilterRow=g.join("  ");e=!0}}return e}function Zb(a){return{search:a.sSearch,smart:a.bSmart,regex:a.bRegex,caseInsensitive:a.bCaseInsensitive}}
function $b(a){return{sSearch:a.search,bSmart:a.smart,bRegex:a.regex,bCaseInsensitive:a.caseInsensitive}}function Rb(a){var b=a.sTableId,c=a.aanFeatures.i,d=l("<div/>",{"class":a.oClasses.sInfo,id:c?null:b+"_info"});c||(a.aoDrawCallback.push({fn:ac,sName:"information"}),d.attr("role","status").attr("aria-live","polite"),l(a.nTable).attr("aria-describedby",b+"_info"));return d[0]}function ac(a){var b=a.aanFeatures.i;if(0!==b.length){var c=a.oLanguage,d=a._iDisplayStart+1,e=a.fnDisplayEnd(),h=a.fnRecordsTotal(),
f=a.fnRecordsDisplay(),g=f?c.sInfo:c.sInfoEmpty;f!==h&&(g+=" "+c.sInfoFiltered);g+=c.sInfoPostFix;g=bc(a,g);c=c.fnInfoCallback;null!==c&&(g=c.call(a.oInstance,a,d,e,h,f,g));l(b).html(g)}}function bc(a,b){var c=a.fnFormatNumber,d=a._iDisplayStart+1,e=a._iDisplayLength,h=a.fnRecordsDisplay(),f=-1===e;return b.replace(/_START_/g,c.call(a,d)).replace(/_END_/g,c.call(a,a.fnDisplayEnd())).replace(/_MAX_/g,c.call(a,a.fnRecordsTotal())).replace(/_TOTAL_/g,c.call(a,h)).replace(/_PAGE_/g,c.call(a,f?1:Math.ceil(d/
e))).replace(/_PAGES_/g,c.call(a,f?1:Math.ceil(h/e)))}function Aa(a){var b=a.iInitDisplayStart,c=a.aoColumns;var d=a.oFeatures;var e=a.bDeferLoading;if(a.bInitialised){Mb(a);Jb(a);xa(a,a.aoHeader);xa(a,a.aoFooter);V(a,!0);d.bAutoWidth&&db(a);var h=0;for(d=c.length;h<d;h++){var f=c[h];f.sWidth&&(f.nTh.style.width=K(f.sWidth))}F(a,null,"preInit",[a]);ka(a);c=Q(a);if("ssp"!=c||e)"ajax"==c?Qa(a,[],function(g){var k=za(a,g);for(h=0;h<k.length;h++)ia(a,k[h]);a.iInitDisplayStart=b;ka(a);V(a,!1);Ra(a,g)},
a):(V(a,!1),Ra(a))}else setTimeout(function(){Aa(a)},200)}function Ra(a,b){a._bInitComplete=!0;(b||a.oInit.aaData)&&sa(a);F(a,null,"plugin-init",[a,b]);F(a,"aoInitComplete","init",[a,b])}function pb(a,b){b=parseInt(b,10);a._iDisplayLength=b;qb(a);F(a,null,"length",[a,b])}function Nb(a){var b=a.oClasses,c=a.sTableId,d=a.aLengthMenu,e=Array.isArray(d[0]),h=e?d[0]:d;d=e?d[1]:d;e=l("<select/>",{name:c+"_length","aria-controls":c,"class":b.sLengthSelect});for(var f=0,g=h.length;f<g;f++)e[0][f]=new Option("number"===
typeof d[f]?a.fnFormatNumber(d[f]):d[f],h[f]);var k=l("<div><label/></div>").addClass(b.sLength);a.aanFeatures.l||(k[0].id=c+"_length");k.children().append(a.oLanguage.sLengthMenu.replace("_MENU_",e[0].outerHTML));l("select",k).val(a._iDisplayLength).on("change.DT",function(m){pb(a,l(this).val());ja(a)});l(a.nTable).on("length.dt.DT",function(m,n,p){a===n&&l("select",k).val(p)});return k[0]}function Sb(a){var b=a.sPaginationType,c=u.ext.pager[b],d="function"===typeof c,e=function(f){ja(f)};b=l("<div/>").addClass(a.oClasses.sPaging+
b)[0];var h=a.aanFeatures;d||c.fnInit(a,b,e);h.p||(b.id=a.sTableId+"_paginate",a.aoDrawCallback.push({fn:function(f){if(d){var g=f._iDisplayStart,k=f._iDisplayLength,m=f.fnRecordsDisplay(),n=-1===k;g=n?0:Math.ceil(g/k);k=n?1:Math.ceil(m/k);m=c(g,k);var p;n=0;for(p=h.p.length;n<p;n++)lb(f,"pageButton")(f,h.p[n],n,m,g,k)}else c.fnUpdate(f,e)},sName:"pagination"}));return b}function Ta(a,b,c){var d=a._iDisplayStart,e=a._iDisplayLength,h=a.fnRecordsDisplay();0===h||-1===e?d=0:"number"===typeof b?(d=b*
e,d>h&&(d=0)):"first"==b?d=0:"previous"==b?(d=0<=e?d-e:0,0>d&&(d=0)):"next"==b?d+e<h&&(d+=e):"last"==b?d=Math.floor((h-1)/e)*e:ea(a,0,"Unknown paging action: "+b,5);b=a._iDisplayStart!==d;a._iDisplayStart=d;b&&(F(a,null,"page",[a]),c&&ja(a));return b}function Pb(a){return l("<div/>",{id:a.aanFeatures.r?null:a.sTableId+"_processing","class":a.oClasses.sProcessing}).html(a.oLanguage.sProcessing).append("<div><div></div><div></div><div></div><div></div></div>").insertBefore(a.nTable)[0]}function V(a,
b){a.oFeatures.bProcessing&&l(a.aanFeatures.r).css("display",b?"block":"none");F(a,null,"processing",[a,b])}function Qb(a){var b=l(a.nTable),c=a.oScroll;if(""===c.sX&&""===c.sY)return a.nTable;var d=c.sX,e=c.sY,h=a.oClasses,f=b.children("caption"),g=f.length?f[0]._captionSide:null,k=l(b[0].cloneNode(!1)),m=l(b[0].cloneNode(!1)),n=b.children("tfoot");n.length||(n=null);k=l("<div/>",{"class":h.sScrollWrapper}).append(l("<div/>",{"class":h.sScrollHead}).css({overflow:"hidden",position:"relative",border:0,
width:d?d?K(d):null:"100%"}).append(l("<div/>",{"class":h.sScrollHeadInner}).css({"box-sizing":"content-box",width:c.sXInner||"100%"}).append(k.removeAttr("id").css("margin-left",0).append("top"===g?f:null).append(b.children("thead"))))).append(l("<div/>",{"class":h.sScrollBody}).css({position:"relative",overflow:"auto",width:d?K(d):null}).append(b));n&&k.append(l("<div/>",{"class":h.sScrollFoot}).css({overflow:"hidden",border:0,width:d?d?K(d):null:"100%"}).append(l("<div/>",{"class":h.sScrollFootInner}).append(m.removeAttr("id").css("margin-left",
0).append("bottom"===g?f:null).append(b.children("tfoot")))));b=k.children();var p=b[0];h=b[1];var t=n?b[2]:null;if(d)l(h).on("scroll.DT",function(v){v=this.scrollLeft;p.scrollLeft=v;n&&(t.scrollLeft=v)});l(h).css("max-height",e);c.bCollapse||l(h).css("height",e);a.nScrollHead=p;a.nScrollBody=h;a.nScrollFoot=t;a.aoDrawCallback.push({fn:Ja,sName:"scrolling"});return k[0]}function Ja(a){var b=a.oScroll,c=b.sX,d=b.sXInner,e=b.sY;b=b.iBarWidth;var h=l(a.nScrollHead),f=h[0].style,g=h.children("div"),k=
g[0].style,m=g.children("table");g=a.nScrollBody;var n=l(g),p=g.style,t=l(a.nScrollFoot).children("div"),v=t.children("table"),x=l(a.nTHead),w=l(a.nTable),r=w[0],C=r.style,G=a.nTFoot?l(a.nTFoot):null,ba=a.oBrowser,L=ba.bScrollOversize;U(a.aoColumns,"nTh");var O=[],I=[],H=[],fa=[],Z,Ba=function(D){D=D.style;D.paddingTop="0";D.paddingBottom="0";D.borderTopWidth="0";D.borderBottomWidth="0";D.height=0};var X=g.scrollHeight>g.clientHeight;if(a.scrollBarVis!==X&&a.scrollBarVis!==q)a.scrollBarVis=X,sa(a);
else{a.scrollBarVis=X;w.children("thead, tfoot").remove();if(G){X=G.clone().prependTo(w);var ca=G.find("tr");var Ca=X.find("tr");X.find("[id]").removeAttr("id")}var Ua=x.clone().prependTo(w);x=x.find("tr");X=Ua.find("tr");Ua.find("th, td").removeAttr("tabindex");Ua.find("[id]").removeAttr("id");c||(p.width="100%",h[0].style.width="100%");l.each(Pa(a,Ua),function(D,W){Z=ta(a,D);W.style.width=a.aoColumns[Z].sWidth});G&&da(function(D){D.style.width=""},Ca);h=w.outerWidth();""===c?(C.width="100%",L&&
(w.find("tbody").height()>g.offsetHeight||"scroll"==n.css("overflow-y"))&&(C.width=K(w.outerWidth()-b)),h=w.outerWidth()):""!==d&&(C.width=K(d),h=w.outerWidth());da(Ba,X);da(function(D){var W=y.getComputedStyle?y.getComputedStyle(D).width:K(l(D).width());H.push(D.innerHTML);O.push(W)},X);da(function(D,W){D.style.width=O[W]},x);l(X).css("height",0);G&&(da(Ba,Ca),da(function(D){fa.push(D.innerHTML);I.push(K(l(D).css("width")))},Ca),da(function(D,W){D.style.width=I[W]},ca),l(Ca).height(0));da(function(D,
W){D.innerHTML='<div class="dataTables_sizing">'+H[W]+"</div>";D.childNodes[0].style.height="0";D.childNodes[0].style.overflow="hidden";D.style.width=O[W]},X);G&&da(function(D,W){D.innerHTML='<div class="dataTables_sizing">'+fa[W]+"</div>";D.childNodes[0].style.height="0";D.childNodes[0].style.overflow="hidden";D.style.width=I[W]},Ca);Math.round(w.outerWidth())<Math.round(h)?(ca=g.scrollHeight>g.offsetHeight||"scroll"==n.css("overflow-y")?h+b:h,L&&(g.scrollHeight>g.offsetHeight||"scroll"==n.css("overflow-y"))&&
(C.width=K(ca-b)),""!==c&&""===d||ea(a,1,"Possible column misalignment",6)):ca="100%";p.width=K(ca);f.width=K(ca);G&&(a.nScrollFoot.style.width=K(ca));!e&&L&&(p.height=K(r.offsetHeight+b));c=w.outerWidth();m[0].style.width=K(c);k.width=K(c);d=w.height()>g.clientHeight||"scroll"==n.css("overflow-y");e="padding"+(ba.bScrollbarLeft?"Left":"Right");k[e]=d?b+"px":"0px";G&&(v[0].style.width=K(c),t[0].style.width=K(c),t[0].style[e]=d?b+"px":"0px");w.children("colgroup").insertBefore(w.children("thead"));
n.trigger("scroll");!a.bSorted&&!a.bFiltered||a._drawHold||(g.scrollTop=0)}}function da(a,b,c){for(var d=0,e=0,h=b.length,f,g;e<h;){f=b[e].firstChild;for(g=c?c[e].firstChild:null;f;)1===f.nodeType&&(c?a(f,g,d):a(f,d),d++),f=f.nextSibling,g=c?g.nextSibling:null;e++}}function db(a){var b=a.nTable,c=a.aoColumns,d=a.oScroll,e=d.sY,h=d.sX,f=d.sXInner,g=c.length,k=Ka(a,"bVisible"),m=l("th",a.nTHead),n=b.getAttribute("width"),p=b.parentNode,t=!1,v,x=a.oBrowser;d=x.bScrollOversize;(v=b.style.width)&&-1!==
v.indexOf("%")&&(n=v);for(v=0;v<k.length;v++){var w=c[k[v]];null!==w.sWidth&&(w.sWidth=cc(w.sWidthOrig,p),t=!0)}if(d||!t&&!h&&!e&&g==na(a)&&g==m.length)for(v=0;v<g;v++)k=ta(a,v),null!==k&&(c[k].sWidth=K(m.eq(v).width()));else{g=l(b).clone().css("visibility","hidden").removeAttr("id");g.find("tbody tr").remove();var r=l("<tr/>").appendTo(g.find("tbody"));g.find("thead, tfoot").remove();g.append(l(a.nTHead).clone()).append(l(a.nTFoot).clone());g.find("tfoot th, tfoot td").css("width","");m=Pa(a,g.find("thead")[0]);
for(v=0;v<k.length;v++)w=c[k[v]],m[v].style.width=null!==w.sWidthOrig&&""!==w.sWidthOrig?K(w.sWidthOrig):"",w.sWidthOrig&&h&&l(m[v]).append(l("<div/>").css({width:w.sWidthOrig,margin:0,padding:0,border:0,height:1}));if(a.aoData.length)for(v=0;v<k.length;v++)t=k[v],w=c[t],l(dc(a,t)).clone(!1).append(w.sContentPadding).appendTo(r);l("[name]",g).removeAttr("name");w=l("<div/>").css(h||e?{position:"absolute",top:0,left:0,height:1,right:0,overflow:"hidden"}:{}).append(g).appendTo(p);h&&f?g.width(f):h?
(g.css("width","auto"),g.removeAttr("width"),g.width()<p.clientWidth&&n&&g.width(p.clientWidth)):e?g.width(p.clientWidth):n&&g.width(n);for(v=e=0;v<k.length;v++)p=l(m[v]),f=p.outerWidth()-p.width(),p=x.bBounding?Math.ceil(m[v].getBoundingClientRect().width):p.outerWidth(),e+=p,c[k[v]].sWidth=K(p-f);b.style.width=K(e);w.remove()}n&&(b.style.width=K(n));!n&&!h||a._reszEvt||(b=function(){l(y).on("resize.DT-"+a.sInstance,mb(function(){sa(a)}))},d?setTimeout(b,1E3):b(),a._reszEvt=!0)}function cc(a,b){if(!a)return 0;
a=l("<div/>").css("width",K(a)).appendTo(b||A.body);b=a[0].offsetWidth;a.remove();return b}function dc(a,b){var c=ec(a,b);if(0>c)return null;var d=a.aoData[c];return d.nTr?d.anCells[b]:l("<td/>").html(T(a,c,b,"display"))[0]}function ec(a,b){for(var c,d=-1,e=-1,h=0,f=a.aoData.length;h<f;h++)c=T(a,h,b,"display")+"",c=c.replace(Cc,""),c=c.replace(/&nbsp;/g," "),c.length>d&&(d=c.length,e=h);return e}function K(a){return null===a?"0px":"number"==typeof a?0>a?"0px":a+"px":a.match(/\d$/)?a+"px":a}function oa(a){var b=
[],c=a.aoColumns;var d=a.aaSortingFixed;var e=l.isPlainObject(d);var h=[];var f=function(n){n.length&&!Array.isArray(n[0])?h.push(n):l.merge(h,n)};Array.isArray(d)&&f(d);e&&d.pre&&f(d.pre);f(a.aaSorting);e&&d.post&&f(d.post);for(a=0;a<h.length;a++){var g=h[a][0];f=c[g].aDataSort;d=0;for(e=f.length;d<e;d++){var k=f[d];var m=c[k].sType||"string";h[a]._idx===q&&(h[a]._idx=l.inArray(h[a][1],c[k].asSorting));b.push({src:g,col:k,dir:h[a][1],index:h[a]._idx,type:m,formatter:u.ext.type.order[m+"-pre"]})}}return b}
function Lb(a){var b,c=[],d=u.ext.type.order,e=a.aoData,h=0,f=a.aiDisplayMaster;eb(a);var g=oa(a);var k=0;for(b=g.length;k<b;k++){var m=g[k];m.formatter&&h++;fc(a,m.col)}if("ssp"!=Q(a)&&0!==g.length){k=0;for(b=f.length;k<b;k++)c[f[k]]=k;h===g.length?f.sort(function(n,p){var t,v=g.length,x=e[n]._aSortData,w=e[p]._aSortData;for(t=0;t<v;t++){var r=g[t];var C=x[r.col];var G=w[r.col];C=C<G?-1:C>G?1:0;if(0!==C)return"asc"===r.dir?C:-C}C=c[n];G=c[p];return C<G?-1:C>G?1:0}):f.sort(function(n,p){var t,v=g.length,
x=e[n]._aSortData,w=e[p]._aSortData;for(t=0;t<v;t++){var r=g[t];var C=x[r.col];var G=w[r.col];r=d[r.type+"-"+r.dir]||d["string-"+r.dir];C=r(C,G);if(0!==C)return C}C=c[n];G=c[p];return C<G?-1:C>G?1:0})}a.bSorted=!0}function gc(a){var b=a.aoColumns,c=oa(a);a=a.oLanguage.oAria;for(var d=0,e=b.length;d<e;d++){var h=b[d];var f=h.asSorting;var g=h.ariaTitle||h.sTitle.replace(/<.*?>/g,"");var k=h.nTh;k.removeAttribute("aria-sort");h.bSortable&&(0<c.length&&c[0].col==d?(k.setAttribute("aria-sort","asc"==
c[0].dir?"ascending":"descending"),h=f[c[0].index+1]||f[0]):h=f[0],g+="asc"===h?a.sSortAscending:a.sSortDescending);k.setAttribute("aria-label",g)}}function rb(a,b,c,d){var e=a.aaSorting,h=a.aoColumns[b].asSorting,f=function(g,k){var m=g._idx;m===q&&(m=l.inArray(g[1],h));return m+1<h.length?m+1:k?null:0};"number"===typeof e[0]&&(e=a.aaSorting=[e]);c&&a.oFeatures.bSortMulti?(c=l.inArray(b,U(e,"0")),-1!==c?(b=f(e[c],!0),null===b&&1===e.length&&(b=0),null===b?e.splice(c,1):(e[c][1]=h[b],e[c]._idx=b)):
(e.push([b,h[0],0]),e[e.length-1]._idx=0)):e.length&&e[0][0]==b?(b=f(e[0]),e.length=1,e[0][1]=h[b],e[0]._idx=b):(e.length=0,e.push([b,h[0]]),e[0]._idx=0);ka(a);"function"==typeof d&&d(a)}function kb(a,b,c,d){var e=a.aoColumns[c];sb(b,{},function(h){!1!==e.bSortable&&(a.oFeatures.bProcessing?(V(a,!0),setTimeout(function(){rb(a,c,h.shiftKey,d);"ssp"!==Q(a)&&V(a,!1)},0)):rb(a,c,h.shiftKey,d))})}function Va(a){var b=a.aLastSort,c=a.oClasses.sSortColumn,d=oa(a),e=a.oFeatures,h;if(e.bSort&&e.bSortClasses){e=
0;for(h=b.length;e<h;e++){var f=b[e].src;l(U(a.aoData,"anCells",f)).removeClass(c+(2>e?e+1:3))}e=0;for(h=d.length;e<h;e++)f=d[e].src,l(U(a.aoData,"anCells",f)).addClass(c+(2>e?e+1:3))}a.aLastSort=d}function fc(a,b){var c=a.aoColumns[b],d=u.ext.order[c.sSortDataType],e;d&&(e=d.call(a.oInstance,a,b,ua(a,b)));for(var h,f=u.ext.type.order[c.sType+"-pre"],g=0,k=a.aoData.length;g<k;g++)if(c=a.aoData[g],c._aSortData||(c._aSortData=[]),!c._aSortData[b]||d)h=d?e[g]:T(a,g,b,"sort"),c._aSortData[b]=f?f(h):h}
function Da(a){if(!a._bLoadingState){var b={time:+new Date,start:a._iDisplayStart,length:a._iDisplayLength,order:l.extend(!0,[],a.aaSorting),search:Zb(a.oPreviousSearch),columns:l.map(a.aoColumns,function(c,d){return{visible:c.bVisible,search:Zb(a.aoPreSearchCols[d])}})};a.oSavedState=b;F(a,"aoStateSaveParams","stateSaveParams",[a,b]);a.oFeatures.bStateSave&&!a.bDestroying&&a.fnStateSaveCallback.call(a.oInstance,a,b)}}function hc(a,b,c){if(a.oFeatures.bStateSave)return b=a.fnStateLoadCallback.call(a.oInstance,
a,function(d){tb(a,d,c)}),b!==q&&tb(a,b,c),!0;c()}function tb(a,b,c){var d,e=a.aoColumns;a._bLoadingState=!0;var h=a._bInitComplete?new u.Api(a):null;if(b&&b.time){var f=F(a,"aoStateLoadParams","stateLoadParams",[a,b]);if(-1!==l.inArray(!1,f))a._bLoadingState=!1;else if(f=a.iStateDuration,0<f&&b.time<+new Date-1E3*f)a._bLoadingState=!1;else if(b.columns&&e.length!==b.columns.length)a._bLoadingState=!1;else{a.oLoadedState=l.extend(!0,{},b);b.length!==q&&(h?h.page.len(b.length):a._iDisplayLength=b.length);
b.start!==q&&(null===h?(a._iDisplayStart=b.start,a.iInitDisplayStart=b.start):Ta(a,b.start/a._iDisplayLength));b.order!==q&&(a.aaSorting=[],l.each(b.order,function(k,m){a.aaSorting.push(m[0]>=e.length?[0,m[1]]:m)}));b.search!==q&&l.extend(a.oPreviousSearch,$b(b.search));if(b.columns){f=0;for(d=b.columns.length;f<d;f++){var g=b.columns[f];g.visible!==q&&(h?h.column(f).visible(g.visible,!1):e[f].bVisible=g.visible);g.search!==q&&l.extend(a.aoPreSearchCols[f],$b(g.search))}h&&h.columns.adjust()}a._bLoadingState=
!1;F(a,"aoStateLoaded","stateLoaded",[a,b])}}else a._bLoadingState=!1;c()}function Wa(a){var b=u.settings;a=l.inArray(a,U(b,"nTable"));return-1!==a?b[a]:null}function ea(a,b,c,d){c="DataTables warning: "+(a?"table id="+a.sTableId+" - ":"")+c;d&&(c+=". For more information about this error, please see http://datatables.net/tn/"+d);if(b)y.console&&console.log&&console.log(c);else if(b=u.ext,b=b.sErrMode||b.errMode,a&&F(a,null,"error",[a,d,c]),"alert"==b)alert(c);else{if("throw"==b)throw Error(c);"function"==
typeof b&&b(a,d,c)}}function Y(a,b,c,d){Array.isArray(c)?l.each(c,function(e,h){Array.isArray(h)?Y(a,b,h[0],h[1]):Y(a,b,h)}):(d===q&&(d=c),b[c]!==q&&(a[d]=b[c]))}function ub(a,b,c){var d;for(d in b)if(b.hasOwnProperty(d)){var e=b[d];l.isPlainObject(e)?(l.isPlainObject(a[d])||(a[d]={}),l.extend(!0,a[d],e)):c&&"data"!==d&&"aaData"!==d&&Array.isArray(e)?a[d]=e.slice():a[d]=e}return a}function sb(a,b,c){l(a).on("click.DT",b,function(d){l(a).trigger("blur");c(d)}).on("keypress.DT",b,function(d){13===d.which&&
(d.preventDefault(),c(d))}).on("selectstart.DT",function(){return!1})}function R(a,b,c,d){c&&a[b].push({fn:c,sName:d})}function F(a,b,c,d){var e=[];b&&(e=l.map(a[b].slice().reverse(),function(h,f){return h.fn.apply(a.oInstance,d)}));null!==c&&(b=l.Event(c+".dt"),l(a.nTable).trigger(b,d),e.push(b.result));return e}function qb(a){var b=a._iDisplayStart,c=a.fnDisplayEnd(),d=a._iDisplayLength;b>=c&&(b=c-d);b-=b%d;if(-1===d||0>b)b=0;a._iDisplayStart=b}function lb(a,b){a=a.renderer;var c=u.ext.renderer[b];
return l.isPlainObject(a)&&a[b]?c[a[b]]||c._:"string"===typeof a?c[a]||c._:c._}function Q(a){return a.oFeatures.bServerSide?"ssp":a.ajax||a.sAjaxSource?"ajax":"dom"}function Ea(a,b){var c=ic.numbers_length,d=Math.floor(c/2);b<=c?a=pa(0,b):a<=d?(a=pa(0,c-2),a.push("ellipsis"),a.push(b-1)):(a>=b-1-d?a=pa(b-(c-2),b):(a=pa(a-d+2,a+d-1),a.push("ellipsis"),a.push(b-1)),a.splice(0,0,"ellipsis"),a.splice(0,0,0));a.DT_el="span";return a}function bb(a){l.each({num:function(b){return Xa(b,a)},"num-fmt":function(b){return Xa(b,
a,vb)},"html-num":function(b){return Xa(b,a,Ya)},"html-num-fmt":function(b){return Xa(b,a,Ya,vb)}},function(b,c){M.type.order[b+a+"-pre"]=c;b.match(/^html\-/)&&(M.type.search[b+a]=M.type.search.html)})}function jc(a,b,c,d,e){return y.moment?a[b](e):y.luxon?a[c](e):d?a[d](e):a}function Za(a,b,c){if(y.moment){var d=y.moment.utc(a,b,c,!0);if(!d.isValid())return null}else if(y.luxon){d=b?y.luxon.DateTime.fromFormat(a,b):y.luxon.DateTime.fromISO(a);if(!d.isValid)return null;d.setLocale(c)}else b?(kc||
alert("DataTables warning: Formatted date without Moment.js or Luxon - https://datatables.net/tn/17"),kc=!0):d=new Date(a);return d}function wb(a){return function(b,c,d,e){0===arguments.length?(d="en",b=c=null):1===arguments.length?(d="en",c=b,b=null):2===arguments.length&&(d=c,c=b,b=null);var h="datetime-"+c;u.ext.type.order[h]||(u.ext.type.detect.unshift(function(f){return f===h?h:!1}),u.ext.type.order[h+"-asc"]=function(f,g){f=f.valueOf();g=g.valueOf();return f===g?0:f<g?-1:1},u.ext.type.order[h+
"-desc"]=function(f,g){f=f.valueOf();g=g.valueOf();return f===g?0:f>g?-1:1});return function(f,g){if(null===f||f===q)"--now"===e?(f=new Date,f=new Date(Date.UTC(f.getFullYear(),f.getMonth(),f.getDate(),f.getHours(),f.getMinutes(),f.getSeconds()))):f="";if("type"===g)return h;if(""===f)return"sort"!==g?"":Za("0000-01-01 00:00:00",null,d);if(null!==c&&b===c&&"sort"!==g&&"type"!==g&&!(f instanceof Date))return f;var k=Za(f,b,d);if(null===k)return f;if("sort"===g)return k;f=null===c?jc(k,"toDate","toJSDate",
"")[a]():jc(k,"format","toFormat","toISOString",c);return"display"===g?$a(f):f}}}function lc(a){return function(){var b=[Wa(this[u.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return u.ext.internal[a].apply(this,b)}}var u=function(a,b){if(this instanceof u)return l(a).DataTable(b);b=a;this.$=function(f,g){return this.api(!0).$(f,g)};this._=function(f,g){return this.api(!0).rows(f,g).data()};this.api=function(f){return f?new B(Wa(this[M.iApiIndex])):new B(this)};this.fnAddData=function(f,
g){var k=this.api(!0);f=Array.isArray(f)&&(Array.isArray(f[0])||l.isPlainObject(f[0]))?k.rows.add(f):k.row.add(f);(g===q||g)&&k.draw();return f.flatten().toArray()};this.fnAdjustColumnSizing=function(f){var g=this.api(!0).columns.adjust(),k=g.settings()[0],m=k.oScroll;f===q||f?g.draw(!1):(""!==m.sX||""!==m.sY)&&Ja(k)};this.fnClearTable=function(f){var g=this.api(!0).clear();(f===q||f)&&g.draw()};this.fnClose=function(f){this.api(!0).row(f).child.hide()};this.fnDeleteRow=function(f,g,k){var m=this.api(!0);
f=m.rows(f);var n=f.settings()[0],p=n.aoData[f[0][0]];f.remove();g&&g.call(this,n,p);(k===q||k)&&m.draw();return p};this.fnDestroy=function(f){this.api(!0).destroy(f)};this.fnDraw=function(f){this.api(!0).draw(f)};this.fnFilter=function(f,g,k,m,n,p){n=this.api(!0);null===g||g===q?n.search(f,k,m,p):n.column(g).search(f,k,m,p);n.draw()};this.fnGetData=function(f,g){var k=this.api(!0);if(f!==q){var m=f.nodeName?f.nodeName.toLowerCase():"";return g!==q||"td"==m||"th"==m?k.cell(f,g).data():k.row(f).data()||
null}return k.data().toArray()};this.fnGetNodes=function(f){var g=this.api(!0);return f!==q?g.row(f).node():g.rows().nodes().flatten().toArray()};this.fnGetPosition=function(f){var g=this.api(!0),k=f.nodeName.toUpperCase();return"TR"==k?g.row(f).index():"TD"==k||"TH"==k?(f=g.cell(f).index(),[f.row,f.columnVisible,f.column]):null};this.fnIsOpen=function(f){return this.api(!0).row(f).child.isShown()};this.fnOpen=function(f,g,k){return this.api(!0).row(f).child(g,k).show().child()[0]};this.fnPageChange=
function(f,g){f=this.api(!0).page(f);(g===q||g)&&f.draw(!1)};this.fnSetColumnVis=function(f,g,k){f=this.api(!0).column(f).visible(g);(k===q||k)&&f.columns.adjust().draw()};this.fnSettings=function(){return Wa(this[M.iApiIndex])};this.fnSort=function(f){this.api(!0).order(f).draw()};this.fnSortListener=function(f,g,k){this.api(!0).order.listener(f,g,k)};this.fnUpdate=function(f,g,k,m,n){var p=this.api(!0);k===q||null===k?p.row(g).data(f):p.cell(g,k).data(f);(n===q||n)&&p.columns.adjust();(m===q||m)&&
p.draw();return 0};this.fnVersionCheck=M.fnVersionCheck;var c=this,d=b===q,e=this.length;d&&(b={});this.oApi=this.internal=M.internal;for(var h in u.ext.internal)h&&(this[h]=lc(h));this.each(function(){var f={},g=1<e?ub(f,b,!0):b,k=0,m;f=this.getAttribute("id");var n=!1,p=u.defaults,t=l(this);if("table"!=this.nodeName.toLowerCase())ea(null,0,"Non-table node initialisation ("+this.nodeName+")",2);else{Db(p);Eb(p.column);P(p,p,!0);P(p.column,p.column,!0);P(p,l.extend(g,t.data()),!0);var v=u.settings;
k=0;for(m=v.length;k<m;k++){var x=v[k];if(x.nTable==this||x.nTHead&&x.nTHead.parentNode==this||x.nTFoot&&x.nTFoot.parentNode==this){var w=g.bRetrieve!==q?g.bRetrieve:p.bRetrieve;if(d||w)return x.oInstance;if(g.bDestroy!==q?g.bDestroy:p.bDestroy){x.oInstance.fnDestroy();break}else{ea(x,0,"Cannot reinitialise DataTable",3);return}}if(x.sTableId==this.id){v.splice(k,1);break}}if(null===f||""===f)this.id=f="DataTables_Table_"+u.ext._unique++;var r=l.extend(!0,{},u.models.oSettings,{sDestroyWidth:t[0].style.width,
sInstance:f,sTableId:f});r.nTable=this;r.oApi=c.internal;r.oInit=g;v.push(r);r.oInstance=1===c.length?c:t.dataTable();Db(g);la(g.oLanguage);g.aLengthMenu&&!g.iDisplayLength&&(g.iDisplayLength=Array.isArray(g.aLengthMenu[0])?g.aLengthMenu[0][0]:g.aLengthMenu[0]);g=ub(l.extend(!0,{},p),g);Y(r.oFeatures,g,"bPaginate bLengthChange bFilter bSort bSortMulti bInfo bProcessing bAutoWidth bSortClasses bServerSide bDeferRender".split(" "));Y(r,g,["asStripeClasses","ajax","fnServerData","fnFormatNumber","sServerMethod",
"aaSorting","aaSortingFixed","aLengthMenu","sPaginationType","sAjaxSource","sAjaxDataProp","iStateDuration","sDom","bSortCellsTop","iTabIndex","fnStateLoadCallback","fnStateSaveCallback","renderer","searchDelay","rowId",["iCookieDuration","iStateDuration"],["oSearch","oPreviousSearch"],["aoSearchCols","aoPreSearchCols"],["iDisplayLength","_iDisplayLength"]]);Y(r.oScroll,g,[["sScrollX","sX"],["sScrollXInner","sXInner"],["sScrollY","sY"],["bScrollCollapse","bCollapse"]]);Y(r.oLanguage,g,"fnInfoCallback");
R(r,"aoDrawCallback",g.fnDrawCallback,"user");R(r,"aoServerParams",g.fnServerParams,"user");R(r,"aoStateSaveParams",g.fnStateSaveParams,"user");R(r,"aoStateLoadParams",g.fnStateLoadParams,"user");R(r,"aoStateLoaded",g.fnStateLoaded,"user");R(r,"aoRowCallback",g.fnRowCallback,"user");R(r,"aoRowCreatedCallback",g.fnCreatedRow,"user");R(r,"aoHeaderCallback",g.fnHeaderCallback,"user");R(r,"aoFooterCallback",g.fnFooterCallback,"user");R(r,"aoInitComplete",g.fnInitComplete,"user");R(r,"aoPreDrawCallback",
g.fnPreDrawCallback,"user");r.rowIdFn=ma(g.rowId);Fb(r);var C=r.oClasses;l.extend(C,u.ext.classes,g.oClasses);t.addClass(C.sTable);r.iInitDisplayStart===q&&(r.iInitDisplayStart=g.iDisplayStart,r._iDisplayStart=g.iDisplayStart);null!==g.iDeferLoading&&(r.bDeferLoading=!0,f=Array.isArray(g.iDeferLoading),r._iRecordsDisplay=f?g.iDeferLoading[0]:g.iDeferLoading,r._iRecordsTotal=f?g.iDeferLoading[1]:g.iDeferLoading);var G=r.oLanguage;l.extend(!0,G,g.oLanguage);G.sUrl?(l.ajax({dataType:"json",url:G.sUrl,
success:function(I){P(p.oLanguage,I);la(I);l.extend(!0,G,I,r.oInit.oLanguage);F(r,null,"i18n",[r]);Aa(r)},error:function(){Aa(r)}}),n=!0):F(r,null,"i18n",[r]);null===g.asStripeClasses&&(r.asStripeClasses=[C.sStripeOdd,C.sStripeEven]);f=r.asStripeClasses;var ba=t.children("tbody").find("tr").eq(0);-1!==l.inArray(!0,l.map(f,function(I,H){return ba.hasClass(I)}))&&(l("tbody tr",this).removeClass(f.join(" ")),r.asDestroyStripes=f.slice());f=[];v=this.getElementsByTagName("thead");0!==v.length&&(wa(r.aoHeader,
v[0]),f=Pa(r));if(null===g.aoColumns)for(v=[],k=0,m=f.length;k<m;k++)v.push(null);else v=g.aoColumns;k=0;for(m=v.length;k<m;k++)cb(r,f?f[k]:null);Hb(r,g.aoColumnDefs,v,function(I,H){Ia(r,I,H)});if(ba.length){var L=function(I,H){return null!==I.getAttribute("data-"+H)?H:null};l(ba[0]).children("th, td").each(function(I,H){var fa=r.aoColumns[I];if(fa.mData===I){var Z=L(H,"sort")||L(H,"order");H=L(H,"filter")||L(H,"search");if(null!==Z||null!==H)fa.mData={_:I+".display",sort:null!==Z?I+".@data-"+Z:q,
type:null!==Z?I+".@data-"+Z:q,filter:null!==H?I+".@data-"+H:q},Ia(r,I)}})}var O=r.oFeatures;f=function(){if(g.aaSorting===q){var I=r.aaSorting;k=0;for(m=I.length;k<m;k++)I[k][1]=r.aoColumns[k].asSorting[0]}Va(r);O.bSort&&R(r,"aoDrawCallback",function(){if(r.bSorted){var Z=oa(r),Ba={};l.each(Z,function(X,ca){Ba[ca.src]=ca.dir});F(r,null,"order",[r,Z,Ba]);gc(r)}});R(r,"aoDrawCallback",function(){(r.bSorted||"ssp"===Q(r)||O.bDeferRender)&&Va(r)},"sc");I=t.children("caption").each(function(){this._captionSide=
l(this).css("caption-side")});var H=t.children("thead");0===H.length&&(H=l("<thead/>").appendTo(t));r.nTHead=H[0];var fa=t.children("tbody");0===fa.length&&(fa=l("<tbody/>").insertAfter(H));r.nTBody=fa[0];H=t.children("tfoot");0===H.length&&0<I.length&&(""!==r.oScroll.sX||""!==r.oScroll.sY)&&(H=l("<tfoot/>").appendTo(t));0===H.length||0===H.children().length?t.addClass(C.sNoFooter):0<H.length&&(r.nTFoot=H[0],wa(r.aoFooter,r.nTFoot));if(g.aaData)for(k=0;k<g.aaData.length;k++)ia(r,g.aaData[k]);else(r.bDeferLoading||
"dom"==Q(r))&&La(r,l(r.nTBody).children("tr"));r.aiDisplay=r.aiDisplayMaster.slice();r.bInitialised=!0;!1===n&&Aa(r)};R(r,"aoDrawCallback",Da,"state_save");g.bStateSave?(O.bStateSave=!0,hc(r,g,f)):f()}});c=null;return this},M,z,J,xb={},mc=/[\r\n\u2028]/g,Ya=/<.*?>/g,Dc=/^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/,Ec=/(\/|\.|\*|\+|\?|\||\(|\)|\[|\]|\{|\}|\\|\$|\^|\-)/g,vb=/['\u00A0,$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi,aa=function(a){return a&&!0!==a&&"-"!==
a?!1:!0},nc=function(a){var b=parseInt(a,10);return!isNaN(b)&&isFinite(a)?b:null},oc=function(a,b){xb[b]||(xb[b]=new RegExp(ob(b),"g"));return"string"===typeof a&&"."!==b?a.replace(/\./g,"").replace(xb[b],"."):a},yb=function(a,b,c){var d="string"===typeof a;if(aa(a))return!0;b&&d&&(a=oc(a,b));c&&d&&(a=a.replace(vb,""));return!isNaN(parseFloat(a))&&isFinite(a)},pc=function(a,b,c){return aa(a)?!0:aa(a)||"string"===typeof a?yb(a.replace(Ya,""),b,c)?!0:null:null},U=function(a,b,c){var d=[],e=0,h=a.length;
if(c!==q)for(;e<h;e++)a[e]&&a[e][b]&&d.push(a[e][b][c]);else for(;e<h;e++)a[e]&&d.push(a[e][b]);return d},Fa=function(a,b,c,d){var e=[],h=0,f=b.length;if(d!==q)for(;h<f;h++)a[b[h]][c]&&e.push(a[b[h]][c][d]);else for(;h<f;h++)e.push(a[b[h]][c]);return e},pa=function(a,b){var c=[];if(b===q){b=0;var d=a}else d=b,b=a;for(a=b;a<d;a++)c.push(a);return c},qc=function(a){for(var b=[],c=0,d=a.length;c<d;c++)a[c]&&b.push(a[c]);return b},Oa=function(a){a:{if(!(2>a.length)){var b=a.slice().sort();for(var c=b[0],
d=1,e=b.length;d<e;d++){if(b[d]===c){b=!1;break a}c=b[d]}}b=!0}if(b)return a.slice();b=[];e=a.length;var h,f=0;d=0;a:for(;d<e;d++){c=a[d];for(h=0;h<f;h++)if(b[h]===c)continue a;b.push(c);f++}return b},rc=function(a,b){if(Array.isArray(b))for(var c=0;c<b.length;c++)rc(a,b[c]);else a.push(b);return a},sc=function(a,b){b===q&&(b=0);return-1!==this.indexOf(a,b)};Array.isArray||(Array.isArray=function(a){return"[object Array]"===Object.prototype.toString.call(a)});Array.prototype.includes||(Array.prototype.includes=
sc);String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")});String.prototype.includes||(String.prototype.includes=sc);u.util={throttle:function(a,b){var c=b!==q?b:200,d,e;return function(){var h=this,f=+new Date,g=arguments;d&&f<d+c?(clearTimeout(e),e=setTimeout(function(){d=q;a.apply(h,g)},c)):(d=f,a.apply(h,g))}},escapeRegex:function(a){return a.replace(Ec,"\\$1")},set:function(a){if(l.isPlainObject(a))return u.util.set(a._);if(null===
a)return function(){};if("function"===typeof a)return function(c,d,e){a(c,"set",d,e)};if("string"!==typeof a||-1===a.indexOf(".")&&-1===a.indexOf("[")&&-1===a.indexOf("("))return function(c,d){c[a]=d};var b=function(c,d,e){e=hb(e);var h=e[e.length-1];for(var f,g,k=0,m=e.length-1;k<m;k++){if("__proto__"===e[k]||"constructor"===e[k])throw Error("Cannot set prototype values");f=e[k].match(Ga);g=e[k].match(qa);if(f){e[k]=e[k].replace(Ga,"");c[e[k]]=[];h=e.slice();h.splice(0,k+1);f=h.join(".");if(Array.isArray(d))for(g=
0,m=d.length;g<m;g++)h={},b(h,d[g],f),c[e[k]].push(h);else c[e[k]]=d;return}g&&(e[k]=e[k].replace(qa,""),c=c[e[k]](d));if(null===c[e[k]]||c[e[k]]===q)c[e[k]]={};c=c[e[k]]}if(h.match(qa))c[h.replace(qa,"")](d);else c[h.replace(Ga,"")]=d};return function(c,d){return b(c,d,a)}},get:function(a){if(l.isPlainObject(a)){var b={};l.each(a,function(d,e){e&&(b[d]=u.util.get(e))});return function(d,e,h,f){var g=b[e]||b._;return g!==q?g(d,e,h,f):d}}if(null===a)return function(d){return d};if("function"===typeof a)return function(d,
e,h,f){return a(d,e,h,f)};if("string"!==typeof a||-1===a.indexOf(".")&&-1===a.indexOf("[")&&-1===a.indexOf("("))return function(d,e){return d[a]};var c=function(d,e,h){if(""!==h){var f=hb(h);for(var g=0,k=f.length;g<k;g++){h=f[g].match(Ga);var m=f[g].match(qa);if(h){f[g]=f[g].replace(Ga,"");""!==f[g]&&(d=d[f[g]]);m=[];f.splice(0,g+1);f=f.join(".");if(Array.isArray(d))for(g=0,k=d.length;g<k;g++)m.push(c(d[g],e,f));d=h[0].substring(1,h[0].length-1);d=""===d?m:m.join(d);break}else if(m){f[g]=f[g].replace(qa,
"");d=d[f[g]]();continue}if(null===d||d[f[g]]===q)return q;d=d[f[g]]}}return d};return function(d,e){return c(d,e,a)}}};var S=function(a,b,c){a[b]!==q&&(a[c]=a[b])},Ga=/\[.*?\]$/,qa=/\(\)$/,ma=u.util.get,ha=u.util.set,ob=u.util.escapeRegex,Sa=l("<div>")[0],Bc=Sa.textContent!==q,Cc=/<.*?>/g,mb=u.util.throttle,tc=[],N=Array.prototype,Fc=function(a){var b,c=u.settings,d=l.map(c,function(h,f){return h.nTable});if(a){if(a.nTable&&a.oApi)return[a];if(a.nodeName&&"table"===a.nodeName.toLowerCase()){var e=
l.inArray(a,d);return-1!==e?[c[e]]:null}if(a&&"function"===typeof a.settings)return a.settings().toArray();"string"===typeof a?b=l(a):a instanceof l&&(b=a)}else return[];if(b)return b.map(function(h){e=l.inArray(this,d);return-1!==e?c[e]:null}).toArray()};var B=function(a,b){if(!(this instanceof B))return new B(a,b);var c=[],d=function(f){(f=Fc(f))&&c.push.apply(c,f)};if(Array.isArray(a))for(var e=0,h=a.length;e<h;e++)d(a[e]);else d(a);this.context=Oa(c);b&&l.merge(this,b);this.selector={rows:null,
cols:null,opts:null};B.extend(this,this,tc)};u.Api=B;l.extend(B.prototype,{any:function(){return 0!==this.count()},concat:N.concat,context:[],count:function(){return this.flatten().length},each:function(a){for(var b=0,c=this.length;b<c;b++)a.call(this,this[b],b,this);return this},eq:function(a){var b=this.context;return b.length>a?new B(b[a],this[a]):null},filter:function(a){var b=[];if(N.filter)b=N.filter.call(this,a,this);else for(var c=0,d=this.length;c<d;c++)a.call(this,this[c],c,this)&&b.push(this[c]);
return new B(this.context,b)},flatten:function(){var a=[];return new B(this.context,a.concat.apply(a,this.toArray()))},join:N.join,indexOf:N.indexOf||function(a,b){b=b||0;for(var c=this.length;b<c;b++)if(this[b]===a)return b;return-1},iterator:function(a,b,c,d){var e=[],h,f,g=this.context,k,m=this.selector;"string"===typeof a&&(d=c,c=b,b=a,a=!1);var n=0;for(h=g.length;n<h;n++){var p=new B(g[n]);if("table"===b){var t=c.call(p,g[n],n);t!==q&&e.push(t)}else if("columns"===b||"rows"===b)t=c.call(p,g[n],
this[n],n),t!==q&&e.push(t);else if("column"===b||"column-rows"===b||"row"===b||"cell"===b){var v=this[n];"column-rows"===b&&(k=ab(g[n],m.opts));var x=0;for(f=v.length;x<f;x++)t=v[x],t="cell"===b?c.call(p,g[n],t.row,t.column,n,x):c.call(p,g[n],t,n,x,k),t!==q&&e.push(t)}}return e.length||d?(a=new B(g,a?e.concat.apply([],e):e),b=a.selector,b.rows=m.rows,b.cols=m.cols,b.opts=m.opts,a):this},lastIndexOf:N.lastIndexOf||function(a,b){return this.indexOf.apply(this.toArray.reverse(),arguments)},length:0,
map:function(a){var b=[];if(N.map)b=N.map.call(this,a,this);else for(var c=0,d=this.length;c<d;c++)b.push(a.call(this,this[c],c));return new B(this.context,b)},pluck:function(a){var b=u.util.get(a);return this.map(function(c){return b(c)})},pop:N.pop,push:N.push,reduce:N.reduce||function(a,b){return Gb(this,a,b,0,this.length,1)},reduceRight:N.reduceRight||function(a,b){return Gb(this,a,b,this.length-1,-1,-1)},reverse:N.reverse,selector:null,shift:N.shift,slice:function(){return new B(this.context,
this)},sort:N.sort,splice:N.splice,toArray:function(){return N.slice.call(this)},to$:function(){return l(this)},toJQuery:function(){return l(this)},unique:function(){return new B(this.context,Oa(this))},unshift:N.unshift});B.extend=function(a,b,c){if(c.length&&b&&(b instanceof B||b.__dt_wrapper)){var d,e=function(g,k,m){return function(){var n=k.apply(g,arguments);B.extend(n,n,m.methodExt);return n}};var h=0;for(d=c.length;h<d;h++){var f=c[h];b[f.name]="function"===f.type?e(a,f.val,f):"object"===
f.type?{}:f.val;b[f.name].__dt_wrapper=!0;B.extend(a,b[f.name],f.propExt)}}};B.register=z=function(a,b){if(Array.isArray(a))for(var c=0,d=a.length;c<d;c++)B.register(a[c],b);else{d=a.split(".");var e=tc,h;a=0;for(c=d.length;a<c;a++){var f=(h=-1!==d[a].indexOf("()"))?d[a].replace("()",""):d[a];a:{var g=0;for(var k=e.length;g<k;g++)if(e[g].name===f){g=e[g];break a}g=null}g||(g={name:f,val:{},methodExt:[],propExt:[],type:"object"},e.push(g));a===c-1?(g.val=b,g.type="function"===typeof b?"function":l.isPlainObject(b)?
"object":"other"):e=h?g.methodExt:g.propExt}}};B.registerPlural=J=function(a,b,c){B.register(a,c);B.register(b,function(){var d=c.apply(this,arguments);return d===this?this:d instanceof B?d.length?Array.isArray(d[0])?new B(d.context,d[0]):d[0]:q:d})};var uc=function(a,b){if(Array.isArray(a))return l.map(a,function(d){return uc(d,b)});if("number"===typeof a)return[b[a]];var c=l.map(b,function(d,e){return d.nTable});return l(c).filter(a).map(function(d){d=l.inArray(this,c);return b[d]}).toArray()};
z("tables()",function(a){return a!==q&&null!==a?new B(uc(a,this.context)):this});z("table()",function(a){a=this.tables(a);var b=a.context;return b.length?new B(b[0]):a});J("tables().nodes()","table().node()",function(){return this.iterator("table",function(a){return a.nTable},1)});J("tables().body()","table().body()",function(){return this.iterator("table",function(a){return a.nTBody},1)});J("tables().header()","table().header()",function(){return this.iterator("table",function(a){return a.nTHead},
1)});J("tables().footer()","table().footer()",function(){return this.iterator("table",function(a){return a.nTFoot},1)});J("tables().containers()","table().container()",function(){return this.iterator("table",function(a){return a.nTableWrapper},1)});z("draw()",function(a){return this.iterator("table",function(b){"page"===a?ja(b):("string"===typeof a&&(a="full-hold"===a?!1:!0),ka(b,!1===a))})});z("page()",function(a){return a===q?this.page.info().page:this.iterator("table",function(b){Ta(b,a)})});z("page.info()",
function(a){if(0===this.context.length)return q;a=this.context[0];var b=a._iDisplayStart,c=a.oFeatures.bPaginate?a._iDisplayLength:-1,d=a.fnRecordsDisplay(),e=-1===c;return{page:e?0:Math.floor(b/c),pages:e?1:Math.ceil(d/c),start:b,end:a.fnDisplayEnd(),length:c,recordsTotal:a.fnRecordsTotal(),recordsDisplay:d,serverSide:"ssp"===Q(a)}});z("page.len()",function(a){return a===q?0!==this.context.length?this.context[0]._iDisplayLength:q:this.iterator("table",function(b){pb(b,a)})});var vc=function(a,b,
c){if(c){var d=new B(a);d.one("draw",function(){c(d.ajax.json())})}if("ssp"==Q(a))ka(a,b);else{V(a,!0);var e=a.jqXHR;e&&4!==e.readyState&&e.abort();Qa(a,[],function(h){Ma(a);h=za(a,h);for(var f=0,g=h.length;f<g;f++)ia(a,h[f]);ka(a,b);V(a,!1)})}};z("ajax.json()",function(){var a=this.context;if(0<a.length)return a[0].json});z("ajax.params()",function(){var a=this.context;if(0<a.length)return a[0].oAjaxData});z("ajax.reload()",function(a,b){return this.iterator("table",function(c){vc(c,!1===b,a)})});
z("ajax.url()",function(a){var b=this.context;if(a===q){if(0===b.length)return q;b=b[0];return b.ajax?l.isPlainObject(b.ajax)?b.ajax.url:b.ajax:b.sAjaxSource}return this.iterator("table",function(c){l.isPlainObject(c.ajax)?c.ajax.url=a:c.ajax=a})});z("ajax.url().load()",function(a,b){return this.iterator("table",function(c){vc(c,!1===b,a)})});var zb=function(a,b,c,d,e){var h=[],f,g,k;var m=typeof b;b&&"string"!==m&&"function"!==m&&b.length!==q||(b=[b]);m=0;for(g=b.length;m<g;m++){var n=b[m]&&b[m].split&&
!b[m].match(/[\[\(:]/)?b[m].split(","):[b[m]];var p=0;for(k=n.length;p<k;p++)(f=c("string"===typeof n[p]?n[p].trim():n[p]))&&f.length&&(h=h.concat(f))}a=M.selector[a];if(a.length)for(m=0,g=a.length;m<g;m++)h=a[m](d,e,h);return Oa(h)},Ab=function(a){a||(a={});a.filter&&a.search===q&&(a.search=a.filter);return l.extend({search:"none",order:"current",page:"all"},a)},Bb=function(a){for(var b=0,c=a.length;b<c;b++)if(0<a[b].length)return a[0]=a[b],a[0].length=1,a.length=1,a.context=[a.context[b]],a;a.length=
0;return a},ab=function(a,b){var c=[],d=a.aiDisplay;var e=a.aiDisplayMaster;var h=b.search;var f=b.order;b=b.page;if("ssp"==Q(a))return"removed"===h?[]:pa(0,e.length);if("current"==b)for(f=a._iDisplayStart,a=a.fnDisplayEnd();f<a;f++)c.push(d[f]);else if("current"==f||"applied"==f)if("none"==h)c=e.slice();else if("applied"==h)c=d.slice();else{if("removed"==h){var g={};f=0;for(a=d.length;f<a;f++)g[d[f]]=null;c=l.map(e,function(k){return g.hasOwnProperty(k)?null:k})}}else if("index"==f||"original"==
f)for(f=0,a=a.aoData.length;f<a;f++)"none"==h?c.push(f):(e=l.inArray(f,d),(-1===e&&"removed"==h||0<=e&&"applied"==h)&&c.push(f));return c},Gc=function(a,b,c){var d;return zb("row",b,function(e){var h=nc(e),f=a.aoData;if(null!==h&&!c)return[h];d||(d=ab(a,c));if(null!==h&&-1!==l.inArray(h,d))return[h];if(null===e||e===q||""===e)return d;if("function"===typeof e)return l.map(d,function(k){var m=f[k];return e(k,m._aData,m.nTr)?k:null});if(e.nodeName){h=e._DT_RowIndex;var g=e._DT_CellIndex;if(h!==q)return f[h]&&
f[h].nTr===e?[h]:[];if(g)return f[g.row]&&f[g.row].nTr===e.parentNode?[g.row]:[];h=l(e).closest("*[data-dt-row]");return h.length?[h.data("dt-row")]:[]}if("string"===typeof e&&"#"===e.charAt(0)&&(h=a.aIds[e.replace(/^#/,"")],h!==q))return[h.idx];h=qc(Fa(a.aoData,d,"nTr"));return l(h).filter(e).map(function(){return this._DT_RowIndex}).toArray()},a,c)};z("rows()",function(a,b){a===q?a="":l.isPlainObject(a)&&(b=a,a="");b=Ab(b);var c=this.iterator("table",function(d){return Gc(d,a,b)},1);c.selector.rows=
a;c.selector.opts=b;return c});z("rows().nodes()",function(){return this.iterator("row",function(a,b){return a.aoData[b].nTr||q},1)});z("rows().data()",function(){return this.iterator(!0,"rows",function(a,b){return Fa(a.aoData,b,"_aData")},1)});J("rows().cache()","row().cache()",function(a){return this.iterator("row",function(b,c){b=b.aoData[c];return"search"===a?b._aFilterData:b._aSortData},1)});J("rows().invalidate()","row().invalidate()",function(a){return this.iterator("row",function(b,c){va(b,
c,a)})});J("rows().indexes()","row().index()",function(){return this.iterator("row",function(a,b){return b},1)});J("rows().ids()","row().id()",function(a){for(var b=[],c=this.context,d=0,e=c.length;d<e;d++)for(var h=0,f=this[d].length;h<f;h++){var g=c[d].rowIdFn(c[d].aoData[this[d][h]]._aData);b.push((!0===a?"#":"")+g)}return new B(c,b)});J("rows().remove()","row().remove()",function(){var a=this;this.iterator("row",function(b,c,d){var e=b.aoData,h=e[c],f,g;e.splice(c,1);var k=0;for(f=e.length;k<
f;k++){var m=e[k];var n=m.anCells;null!==m.nTr&&(m.nTr._DT_RowIndex=k);if(null!==n)for(m=0,g=n.length;m<g;m++)n[m]._DT_CellIndex.row=k}Na(b.aiDisplayMaster,c);Na(b.aiDisplay,c);Na(a[d],c,!1);0<b._iRecordsDisplay&&b._iRecordsDisplay--;qb(b);c=b.rowIdFn(h._aData);c!==q&&delete b.aIds[c]});this.iterator("table",function(b){for(var c=0,d=b.aoData.length;c<d;c++)b.aoData[c].idx=c});return this});z("rows.add()",function(a){var b=this.iterator("table",function(d){var e,h=[];var f=0;for(e=a.length;f<e;f++){var g=
a[f];g.nodeName&&"TR"===g.nodeName.toUpperCase()?h.push(La(d,g)[0]):h.push(ia(d,g))}return h},1),c=this.rows(-1);c.pop();l.merge(c,b);return c});z("row()",function(a,b){return Bb(this.rows(a,b))});z("row().data()",function(a){var b=this.context;if(a===q)return b.length&&this.length?b[0].aoData[this[0]]._aData:q;var c=b[0].aoData[this[0]];c._aData=a;Array.isArray(a)&&c.nTr&&c.nTr.id&&ha(b[0].rowId)(a,c.nTr.id);va(b[0],this[0],"data");return this});z("row().node()",function(){var a=this.context;return a.length&&
this.length?a[0].aoData[this[0]].nTr||null:null});z("row.add()",function(a){a instanceof l&&a.length&&(a=a[0]);var b=this.iterator("table",function(c){return a.nodeName&&"TR"===a.nodeName.toUpperCase()?La(c,a)[0]:ia(c,a)});return this.row(b[0])});l(A).on("plugin-init.dt",function(a,b){a=new B(b);a.on("stateSaveParams",function(d,e,h){d=e.rowIdFn;e=e.aoData;for(var f=[],g=0;g<e.length;g++)e[g]._detailsShow&&f.push("#"+d(e[g]._aData));h.childRows=f});var c=a.state.loaded();c&&c.childRows&&a.rows(l.map(c.childRows,
function(d){return d.replace(/:/g,"\\:")})).every(function(){F(b,null,"requestChild",[this])})});var Hc=function(a,b,c,d){var e=[],h=function(f,g){if(Array.isArray(f)||f instanceof l)for(var k=0,m=f.length;k<m;k++)h(f[k],g);else f.nodeName&&"tr"===f.nodeName.toLowerCase()?e.push(f):(k=l("<tr><td></td></tr>").addClass(g),l("td",k).addClass(g).html(f)[0].colSpan=na(a),e.push(k[0]))};h(c,d);b._details&&b._details.detach();b._details=l(e);b._detailsShow&&b._details.insertAfter(b.nTr)},wc=u.util.throttle(function(a){Da(a[0])},
500),Cb=function(a,b){var c=a.context;c.length&&(a=c[0].aoData[b!==q?b:a[0]])&&a._details&&(a._details.remove(),a._detailsShow=q,a._details=q,l(a.nTr).removeClass("dt-hasChild"),wc(c))},xc=function(a,b){var c=a.context;if(c.length&&a.length){var d=c[0].aoData[a[0]];d._details&&((d._detailsShow=b)?(d._details.insertAfter(d.nTr),l(d.nTr).addClass("dt-hasChild")):(d._details.detach(),l(d.nTr).removeClass("dt-hasChild")),F(c[0],null,"childRow",[b,a.row(a[0])]),Ic(c[0]),wc(c))}},Ic=function(a){var b=new B(a),
c=a.aoData;b.off("draw.dt.DT_details column-sizing.dt.DT_details destroy.dt.DT_details");0<U(c,"_details").length&&(b.on("draw.dt.DT_details",function(d,e){a===e&&b.rows({page:"current"}).eq(0).each(function(h){h=c[h];h._detailsShow&&h._details.insertAfter(h.nTr)})}),b.on("column-sizing.dt.DT_details",function(d,e,h,f){if(a===e)for(e=na(e),h=0,f=c.length;h<f;h++)d=c[h],d._details&&d._details.children("td[colspan]").attr("colspan",e)}),b.on("destroy.dt.DT_details",function(d,e){if(a===e)for(d=0,e=
c.length;d<e;d++)c[d]._details&&Cb(b,d)}))};z("row().child()",function(a,b){var c=this.context;if(a===q)return c.length&&this.length?c[0].aoData[this[0]]._details:q;!0===a?this.child.show():!1===a?Cb(this):c.length&&this.length&&Hc(c[0],c[0].aoData[this[0]],a,b);return this});z(["row().child.show()","row().child().show()"],function(a){xc(this,!0);return this});z(["row().child.hide()","row().child().hide()"],function(){xc(this,!1);return this});z(["row().child.remove()","row().child().remove()"],function(){Cb(this);
return this});z("row().child.isShown()",function(){var a=this.context;return a.length&&this.length?a[0].aoData[this[0]]._detailsShow||!1:!1});var Jc=/^([^:]+):(name|visIdx|visible)$/,yc=function(a,b,c,d,e){c=[];d=0;for(var h=e.length;d<h;d++)c.push(T(a,e[d],b));return c},Kc=function(a,b,c){var d=a.aoColumns,e=U(d,"sName"),h=U(d,"nTh");return zb("column",b,function(f){var g=nc(f);if(""===f)return pa(d.length);if(null!==g)return[0<=g?g:d.length+g];if("function"===typeof f){var k=ab(a,c);return l.map(d,
function(p,t){return f(t,yc(a,t,0,0,k),h[t])?t:null})}var m="string"===typeof f?f.match(Jc):"";if(m)switch(m[2]){case "visIdx":case "visible":g=parseInt(m[1],10);if(0>g){var n=l.map(d,function(p,t){return p.bVisible?t:null});return[n[n.length+g]]}return[ta(a,g)];case "name":return l.map(e,function(p,t){return p===m[1]?t:null});default:return[]}if(f.nodeName&&f._DT_CellIndex)return[f._DT_CellIndex.column];g=l(h).filter(f).map(function(){return l.inArray(this,h)}).toArray();if(g.length||!f.nodeName)return g;
g=l(f).closest("*[data-dt-column]");return g.length?[g.data("dt-column")]:[]},a,c)};z("columns()",function(a,b){a===q?a="":l.isPlainObject(a)&&(b=a,a="");b=Ab(b);var c=this.iterator("table",function(d){return Kc(d,a,b)},1);c.selector.cols=a;c.selector.opts=b;return c});J("columns().header()","column().header()",function(a,b){return this.iterator("column",function(c,d){return c.aoColumns[d].nTh},1)});J("columns().footer()","column().footer()",function(a,b){return this.iterator("column",function(c,
d){return c.aoColumns[d].nTf},1)});J("columns().data()","column().data()",function(){return this.iterator("column-rows",yc,1)});J("columns().dataSrc()","column().dataSrc()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].mData},1)});J("columns().cache()","column().cache()",function(a){return this.iterator("column-rows",function(b,c,d,e,h){return Fa(b.aoData,h,"search"===a?"_aFilterData":"_aSortData",c)},1)});J("columns().nodes()","column().nodes()",function(){return this.iterator("column-rows",
function(a,b,c,d,e){return Fa(a.aoData,e,"anCells",b)},1)});J("columns().visible()","column().visible()",function(a,b){var c=this,d=this.iterator("column",function(e,h){if(a===q)return e.aoColumns[h].bVisible;var f=e.aoColumns,g=f[h],k=e.aoData,m;if(a!==q&&g.bVisible!==a){if(a){var n=l.inArray(!0,U(f,"bVisible"),h+1);f=0;for(m=k.length;f<m;f++){var p=k[f].nTr;e=k[f].anCells;p&&p.insertBefore(e[h],e[n]||null)}}else l(U(e.aoData,"anCells",h)).detach();g.bVisible=a}});a!==q&&this.iterator("table",function(e){xa(e,
e.aoHeader);xa(e,e.aoFooter);e.aiDisplay.length||l(e.nTBody).find("td[colspan]").attr("colspan",na(e));Da(e);c.iterator("column",function(h,f){F(h,null,"column-visibility",[h,f,a,b])});(b===q||b)&&c.columns.adjust()});return d});J("columns().indexes()","column().index()",function(a){return this.iterator("column",function(b,c){return"visible"===a?ua(b,c):c},1)});z("columns.adjust()",function(){return this.iterator("table",function(a){sa(a)},1)});z("column.index()",function(a,b){if(0!==this.context.length){var c=
this.context[0];if("fromVisible"===a||"toData"===a)return ta(c,b);if("fromData"===a||"toVisible"===a)return ua(c,b)}});z("column()",function(a,b){return Bb(this.columns(a,b))});var Lc=function(a,b,c){var d=a.aoData,e=ab(a,c),h=qc(Fa(d,e,"anCells")),f=l(rc([],h)),g,k=a.aoColumns.length,m,n,p,t,v,x;return zb("cell",b,function(w){var r="function"===typeof w;if(null===w||w===q||r){m=[];n=0;for(p=e.length;n<p;n++)for(g=e[n],t=0;t<k;t++)v={row:g,column:t},r?(x=d[g],w(v,T(a,g,t),x.anCells?x.anCells[t]:null)&&
m.push(v)):m.push(v);return m}if(l.isPlainObject(w))return w.column!==q&&w.row!==q&&-1!==l.inArray(w.row,e)?[w]:[];r=f.filter(w).map(function(C,G){return{row:G._DT_CellIndex.row,column:G._DT_CellIndex.column}}).toArray();if(r.length||!w.nodeName)return r;x=l(w).closest("*[data-dt-row]");return x.length?[{row:x.data("dt-row"),column:x.data("dt-column")}]:[]},a,c)};z("cells()",function(a,b,c){l.isPlainObject(a)&&(a.row===q?(c=a,a=null):(c=b,b=null));l.isPlainObject(b)&&(c=b,b=null);if(null===b||b===
q)return this.iterator("table",function(n){return Lc(n,a,Ab(c))});var d=c?{page:c.page,order:c.order,search:c.search}:{},e=this.columns(b,d),h=this.rows(a,d),f,g,k,m;d=this.iterator("table",function(n,p){n=[];f=0;for(g=h[p].length;f<g;f++)for(k=0,m=e[p].length;k<m;k++)n.push({row:h[p][f],column:e[p][k]});return n},1);d=c&&c.selected?this.cells(d,c):d;l.extend(d.selector,{cols:b,rows:a,opts:c});return d});J("cells().nodes()","cell().node()",function(){return this.iterator("cell",function(a,b,c){return(a=
a.aoData[b])&&a.anCells?a.anCells[c]:q},1)});z("cells().data()",function(){return this.iterator("cell",function(a,b,c){return T(a,b,c)},1)});J("cells().cache()","cell().cache()",function(a){a="search"===a?"_aFilterData":"_aSortData";return this.iterator("cell",function(b,c,d){return b.aoData[c][a][d]},1)});J("cells().render()","cell().render()",function(a){return this.iterator("cell",function(b,c,d){return T(b,c,d,a)},1)});J("cells().indexes()","cell().index()",function(){return this.iterator("cell",
function(a,b,c){return{row:b,column:c,columnVisible:ua(a,c)}},1)});J("cells().invalidate()","cell().invalidate()",function(a){return this.iterator("cell",function(b,c,d){va(b,c,a,d)})});z("cell()",function(a,b,c){return Bb(this.cells(a,b,c))});z("cell().data()",function(a){var b=this.context,c=this[0];if(a===q)return b.length&&c.length?T(b[0],c[0].row,c[0].column):q;Ib(b[0],c[0].row,c[0].column,a);va(b[0],c[0].row,"data",c[0].column);return this});z("order()",function(a,b){var c=this.context;if(a===
q)return 0!==c.length?c[0].aaSorting:q;"number"===typeof a?a=[[a,b]]:a.length&&!Array.isArray(a[0])&&(a=Array.prototype.slice.call(arguments));return this.iterator("table",function(d){d.aaSorting=a.slice()})});z("order.listener()",function(a,b,c){return this.iterator("table",function(d){kb(d,a,b,c)})});z("order.fixed()",function(a){if(!a){var b=this.context;b=b.length?b[0].aaSortingFixed:q;return Array.isArray(b)?{pre:b}:b}return this.iterator("table",function(c){c.aaSortingFixed=l.extend(!0,{},a)})});
z(["columns().order()","column().order()"],function(a){var b=this;return this.iterator("table",function(c,d){var e=[];l.each(b[d],function(h,f){e.push([f,a])});c.aaSorting=e})});z("search()",function(a,b,c,d){var e=this.context;return a===q?0!==e.length?e[0].oPreviousSearch.sSearch:q:this.iterator("table",function(h){h.oFeatures.bFilter&&ya(h,l.extend({},h.oPreviousSearch,{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),1)})});J("columns().search()","column().search()",
function(a,b,c,d){return this.iterator("column",function(e,h){var f=e.aoPreSearchCols;if(a===q)return f[h].sSearch;e.oFeatures.bFilter&&(l.extend(f[h],{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),ya(e,e.oPreviousSearch,1))})});z("state()",function(){return this.context.length?this.context[0].oSavedState:null});z("state.clear()",function(){return this.iterator("table",function(a){a.fnStateSaveCallback.call(a.oInstance,a,{})})});z("state.loaded()",function(){return this.context.length?
this.context[0].oLoadedState:null});z("state.save()",function(){return this.iterator("table",function(a){Da(a)})});u.versionCheck=u.fnVersionCheck=function(a){var b=u.version.split(".");a=a.split(".");for(var c,d,e=0,h=a.length;e<h;e++)if(c=parseInt(b[e],10)||0,d=parseInt(a[e],10)||0,c!==d)return c>d;return!0};u.isDataTable=u.fnIsDataTable=function(a){var b=l(a).get(0),c=!1;if(a instanceof u.Api)return!0;l.each(u.settings,function(d,e){d=e.nScrollHead?l("table",e.nScrollHead)[0]:null;var h=e.nScrollFoot?
l("table",e.nScrollFoot)[0]:null;if(e.nTable===b||d===b||h===b)c=!0});return c};u.tables=u.fnTables=function(a){var b=!1;l.isPlainObject(a)&&(b=a.api,a=a.visible);var c=l.map(u.settings,function(d){if(!a||a&&l(d.nTable).is(":visible"))return d.nTable});return b?new B(c):c};u.camelToHungarian=P;z("$()",function(a,b){b=this.rows(b).nodes();b=l(b);return l([].concat(b.filter(a).toArray(),b.find(a).toArray()))});l.each(["on","one","off"],function(a,b){z(b+"()",function(){var c=Array.prototype.slice.call(arguments);
c[0]=l.map(c[0].split(/\s/),function(e){return e.match(/\.dt\b/)?e:e+".dt"}).join(" ");var d=l(this.tables().nodes());d[b].apply(d,c);return this})});z("clear()",function(){return this.iterator("table",function(a){Ma(a)})});z("settings()",function(){return new B(this.context,this.context)});z("init()",function(){var a=this.context;return a.length?a[0].oInit:null});z("data()",function(){return this.iterator("table",function(a){return U(a.aoData,"_aData")}).flatten()});z("destroy()",function(a){a=a||
!1;return this.iterator("table",function(b){var c=b.oClasses,d=b.nTable,e=b.nTBody,h=b.nTHead,f=b.nTFoot,g=l(d);e=l(e);var k=l(b.nTableWrapper),m=l.map(b.aoData,function(p){return p.nTr}),n;b.bDestroying=!0;F(b,"aoDestroyCallback","destroy",[b]);a||(new B(b)).columns().visible(!0);k.off(".DT").find(":not(tbody *)").off(".DT");l(y).off(".DT-"+b.sInstance);d!=h.parentNode&&(g.children("thead").detach(),g.append(h));f&&d!=f.parentNode&&(g.children("tfoot").detach(),g.append(f));b.aaSorting=[];b.aaSortingFixed=
[];Va(b);l(m).removeClass(b.asStripeClasses.join(" "));l("th, td",h).removeClass(c.sSortable+" "+c.sSortableAsc+" "+c.sSortableDesc+" "+c.sSortableNone);e.children().detach();e.append(m);h=b.nTableWrapper.parentNode;f=a?"remove":"detach";g[f]();k[f]();!a&&h&&(h.insertBefore(d,b.nTableReinsertBefore),g.css("width",b.sDestroyWidth).removeClass(c.sTable),(n=b.asDestroyStripes.length)&&e.children().each(function(p){l(this).addClass(b.asDestroyStripes[p%n])}));c=l.inArray(b,u.settings);-1!==c&&u.settings.splice(c,
1)})});l.each(["column","row","cell"],function(a,b){z(b+"s().every()",function(c){var d=this.selector.opts,e=this;return this.iterator(b,function(h,f,g,k,m){c.call(e[b](f,"cell"===b?g:d,"cell"===b?d:q),f,g,k,m)})})});z("i18n()",function(a,b,c){var d=this.context[0];a=ma(a)(d.oLanguage);a===q&&(a=b);c!==q&&l.isPlainObject(a)&&(a=a[c]!==q?a[c]:a._);return a.replace("%d",c)});u.version="1.12.1";u.settings=[];u.models={};u.models.oSearch={bCaseInsensitive:!0,sSearch:"",bRegex:!1,bSmart:!0,"return":!1};
u.models.oRow={nTr:null,anCells:null,_aData:[],_aSortData:null,_aFilterData:null,_sFilterRow:null,_sRowStripe:"",src:null,idx:-1};u.models.oColumn={idx:null,aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bVisible:null,_sManualType:null,_bAttrSrc:!1,fnCreatedCell:null,fnGetData:null,fnSetData:null,mData:null,mRender:null,nTh:null,nTf:null,sClass:null,sContentPadding:null,sDefaultContent:null,sName:null,sSortDataType:"std",sSortingClass:null,sSortingClassJUI:null,sTitle:null,sType:null,
sWidth:null,sWidthOrig:null};u.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:[],ajax:null,aLengthMenu:[10,25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bLengthChange:!0,bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollCollapse:!1,bServerSide:!1,bSort:!0,bSortMulti:!0,bSortCellsTop:!1,bSortClasses:!0,bStateSave:!1,fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,fnFormatNumber:function(a){return a.toString().replace(/\B(?=(\d{3})+(?!\d))/g,
this.oLanguage.sThousands)},fnHeaderCallback:null,fnInfoCallback:null,fnInitComplete:null,fnPreDrawCallback:null,fnRowCallback:null,fnServerData:null,fnServerParams:null,fnStateLoadCallback:function(a){try{return JSON.parse((-1===a.iStateDuration?sessionStorage:localStorage).getItem("DataTables_"+a.sInstance+"_"+location.pathname))}catch(b){return{}}},fnStateLoadParams:null,fnStateLoaded:null,fnStateSaveCallback:function(a,b){try{(-1===a.iStateDuration?sessionStorage:localStorage).setItem("DataTables_"+
a.sInstance+"_"+location.pathname,JSON.stringify(b))}catch(c){}},fnStateSaveParams:null,iStateDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iTabIndex:0,oClasses:{},oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"},oPaginate:{sFirst:"First",sLast:"Last",sNext:"Next",sPrevious:"Previous"},sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",
sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sDecimal:"",sThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"",sSearch:"Search:",sSearchPlaceholder:"",sUrl:"",sZeroRecords:"No matching records found"},oSearch:l.extend({},u.models.oSearch),sAjaxDataProp:"data",sAjaxSource:null,sDom:"lfrtip",searchDelay:null,sPaginationType:"simple_numbers",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET",renderer:null,rowId:"DT_RowId"};E(u.defaults);
u.defaults.column={aDataSort:null,iDataSort:-1,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bVisible:!0,fnCreatedCell:null,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};E(u.defaults.column);u.models.oSettings={oFeatures:{bAutoWidth:null,bDeferRender:null,bFilter:null,bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,bSort:null,bSortMulti:null,bSortClasses:null,
bStateSave:null},oScroll:{bCollapse:null,iBarWidth:0,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1,bScrollbarLeft:!1,bBounding:!1,barWidth:0},ajax:null,aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aIds:{},aoColumns:[],aoHeader:[],aoFooter:[],oPreviousSearch:{},aoPreSearchCols:[],aaSorting:null,aaSortingFixed:[],asStripeClasses:null,asDestroyStripes:[],sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[],aoFooterCallback:[],aoDrawCallback:[],
aoRowCreatedCallback:[],aoPreDrawCallback:[],aoInitComplete:[],aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null,nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,searchDelay:null,sPaginationType:"two_button",iStateDuration:0,aoStateSave:[],aoStateLoad:[],oSavedState:null,oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null,jqXHR:null,json:q,oAjaxData:q,fnServerData:null,aoServerParams:[],sServerMethod:null,
fnFormatNumber:null,aLengthMenu:null,iDraw:0,bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iRecordsTotal:0,_iRecordsDisplay:0,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null,oInit:null,aoDestroyCallback:[],fnRecordsTotal:function(){return"ssp"==Q(this)?1*this._iRecordsTotal:this.aiDisplayMaster.length},fnRecordsDisplay:function(){return"ssp"==Q(this)?1*this._iRecordsDisplay:this.aiDisplay.length},fnDisplayEnd:function(){var a=this._iDisplayLength,b=this._iDisplayStart,c=b+
a,d=this.aiDisplay.length,e=this.oFeatures,h=e.bPaginate;return e.bServerSide?!1===h||-1===a?b+d:Math.min(b+a,this._iRecordsDisplay):!h||c>d||-1===a?d:c},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null,nScrollFoot:null,aLastSort:[],oPlugins:{},rowIdFn:null,rowId:null};u.ext=M={buttons:{},classes:{},builder:"-source-",errMode:"alert",feature:[],search:[],selector:{cell:[],column:[],row:[]},internal:{},legacy:{ajax:null},pager:{},renderer:{pageButton:{},header:{}},order:{},type:{detect:[],
search:{},order:{}},_unique:0,fnVersionCheck:u.fnVersionCheck,iApiIndex:0,oJUIClasses:{},sVersion:u.version};l.extend(M,{afnFiltering:M.search,aTypes:M.type.detect,ofnSearch:M.type.search,oSort:M.type.order,afnSortData:M.order,aoFeatures:M.feature,oApi:M.internal,oStdClasses:M.classes,oPagination:M.pager});l.extend(u.ext.classes,{sTable:"dataTable",sNoFooter:"no-footer",sPageButton:"paginate_button",sPageButtonActive:"current",sPageButtonDisabled:"disabled",sStripeOdd:"odd",sStripeEven:"even",sRowEmpty:"dataTables_empty",
sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_desc_disabled",sSortableDesc:"sorting_asc_disabled",sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sFilterInput:"",sLengthSelect:"",sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",sScrollHeadInner:"dataTables_scrollHeadInner",
sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sHeaderTH:"",sFooterTH:"",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"",sJUIHeader:"",sJUIFooter:""});var ic=u.ext.pager;l.extend(ic,{simple:function(a,b){return["previous","next"]},full:function(a,b){return["first","previous","next","last"]},numbers:function(a,b){return[Ea(a,b)]},simple_numbers:function(a,b){return["previous",
Ea(a,b),"next"]},full_numbers:function(a,b){return["first","previous",Ea(a,b),"next","last"]},first_last_numbers:function(a,b){return["first",Ea(a,b),"last"]},_numbers:Ea,numbers_length:7});l.extend(!0,u.ext.renderer,{pageButton:{_:function(a,b,c,d,e,h){var f=a.oClasses,g=a.oLanguage.oPaginate,k=a.oLanguage.oAria.paginate||{},m,n,p=0,t=function(x,w){var r,C=f.sPageButtonDisabled,G=function(I){Ta(a,I.data.action,!0)};var ba=0;for(r=w.length;ba<r;ba++){var L=w[ba];if(Array.isArray(L)){var O=l("<"+(L.DT_el||
"div")+"/>").appendTo(x);t(O,L)}else{m=null;n=L;O=a.iTabIndex;switch(L){case "ellipsis":x.append('<span class="ellipsis">&#x2026;</span>');break;case "first":m=g.sFirst;0===e&&(O=-1,n+=" "+C);break;case "previous":m=g.sPrevious;0===e&&(O=-1,n+=" "+C);break;case "next":m=g.sNext;if(0===h||e===h-1)O=-1,n+=" "+C;break;case "last":m=g.sLast;if(0===h||e===h-1)O=-1,n+=" "+C;break;default:m=a.fnFormatNumber(L+1),n=e===L?f.sPageButtonActive:""}null!==m&&(O=l("<a>",{"class":f.sPageButton+" "+n,"aria-controls":a.sTableId,
"aria-label":k[L],"data-dt-idx":p,tabindex:O,id:0===c&&"string"===typeof L?a.sTableId+"_"+L:null}).html(m).appendTo(x),sb(O,{action:L},G),p++)}}};try{var v=l(b).find(A.activeElement).data("dt-idx")}catch(x){}t(l(b).empty(),d);v!==q&&l(b).find("[data-dt-idx="+v+"]").trigger("focus")}}});l.extend(u.ext.type.detect,[function(a,b){b=b.oLanguage.sDecimal;return yb(a,b)?"num"+b:null},function(a,b){if(a&&!(a instanceof Date)&&!Dc.test(a))return null;b=Date.parse(a);return null!==b&&!isNaN(b)||aa(a)?"date":
null},function(a,b){b=b.oLanguage.sDecimal;return yb(a,b,!0)?"num-fmt"+b:null},function(a,b){b=b.oLanguage.sDecimal;return pc(a,b)?"html-num"+b:null},function(a,b){b=b.oLanguage.sDecimal;return pc(a,b,!0)?"html-num-fmt"+b:null},function(a,b){return aa(a)||"string"===typeof a&&-1!==a.indexOf("<")?"html":null}]);l.extend(u.ext.type.search,{html:function(a){return aa(a)?a:"string"===typeof a?a.replace(mc," ").replace(Ya,""):""},string:function(a){return aa(a)?a:"string"===typeof a?a.replace(mc," "):
a}});var Xa=function(a,b,c,d){if(0!==a&&(!a||"-"===a))return-Infinity;b&&(a=oc(a,b));a.replace&&(c&&(a=a.replace(c,"")),d&&(a=a.replace(d,"")));return 1*a};l.extend(M.type.order,{"date-pre":function(a){a=Date.parse(a);return isNaN(a)?-Infinity:a},"html-pre":function(a){return aa(a)?"":a.replace?a.replace(/<.*?>/g,"").toLowerCase():a+""},"string-pre":function(a){return aa(a)?"":"string"===typeof a?a.toLowerCase():a.toString?a.toString():""},"string-asc":function(a,b){return a<b?-1:a>b?1:0},"string-desc":function(a,
b){return a<b?1:a>b?-1:0}});bb("");l.extend(!0,u.ext.renderer,{header:{_:function(a,b,c,d){l(a.nTable).on("order.dt.DT",function(e,h,f,g){a===h&&(e=c.idx,b.removeClass(d.sSortAsc+" "+d.sSortDesc).addClass("asc"==g[e]?d.sSortAsc:"desc"==g[e]?d.sSortDesc:c.sSortingClass))})},jqueryui:function(a,b,c,d){l("<div/>").addClass(d.sSortJUIWrapper).append(b.contents()).append(l("<span/>").addClass(d.sSortIcon+" "+c.sSortingClassJUI)).appendTo(b);l(a.nTable).on("order.dt.DT",function(e,h,f,g){a===h&&(e=c.idx,
b.removeClass(d.sSortAsc+" "+d.sSortDesc).addClass("asc"==g[e]?d.sSortAsc:"desc"==g[e]?d.sSortDesc:c.sSortingClass),b.find("span."+d.sSortIcon).removeClass(d.sSortJUIAsc+" "+d.sSortJUIDesc+" "+d.sSortJUI+" "+d.sSortJUIAscAllowed+" "+d.sSortJUIDescAllowed).addClass("asc"==g[e]?d.sSortJUIAsc:"desc"==g[e]?d.sSortJUIDesc:c.sSortingClassJUI))})}}});var $a=function(a){Array.isArray(a)&&(a=a.join(","));return"string"===typeof a?a.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,
"&quot;"):a},kc=!1,zc=",",Ac=".";if(Intl)try{for(var Ha=(new Intl.NumberFormat).formatToParts(100000.1),ra=0;ra<Ha.length;ra++)"group"===Ha[ra].type?zc=Ha[ra].value:"decimal"===Ha[ra].type&&(Ac=Ha[ra].value)}catch(a){}u.datetime=function(a,b){var c="datetime-detect-"+a;b||(b="en");u.ext.type.order[c]||(u.ext.type.detect.unshift(function(d){var e=Za(d,a,b);return""===d||e?c:!1}),u.ext.type.order[c+"-pre"]=function(d){return Za(d,a,b)||0})};u.render={date:wb("toLocaleDateString"),datetime:wb("toLocaleString"),
time:wb("toLocaleTimeString"),number:function(a,b,c,d,e){if(null===a||a===q)a=zc;if(null===b||b===q)b=Ac;return{display:function(h){if("number"!==typeof h&&"string"!==typeof h||""===h||null===h)return h;var f=0>h?"-":"",g=parseFloat(h);if(isNaN(g))return $a(h);g=g.toFixed(c);h=Math.abs(g);g=parseInt(h,10);h=c?b+(h-g).toFixed(c).substring(2):"";0===g&&0===parseFloat(h)&&(f="");return f+(d||"")+g.toString().replace(/\B(?=(\d{3})+(?!\d))/g,a)+h+(e||"")}}},text:function(){return{display:$a,filter:$a}}};
l.extend(u.ext.internal,{_fnExternApiFunc:lc,_fnBuildAjax:Qa,_fnAjaxUpdate:Kb,_fnAjaxParameters:Tb,_fnAjaxUpdateDraw:Ub,_fnAjaxDataSrc:za,_fnAddColumn:cb,_fnColumnOptions:Ia,_fnAdjustColumnSizing:sa,_fnVisibleToColumnIndex:ta,_fnColumnIndexToVisible:ua,_fnVisbleColumns:na,_fnGetColumns:Ka,_fnColumnTypes:eb,_fnApplyColumnDefs:Hb,_fnHungarianMap:E,_fnCamelToHungarian:P,_fnLanguageCompat:la,_fnBrowserDetect:Fb,_fnAddData:ia,_fnAddTr:La,_fnNodeToDataIndex:function(a,b){return b._DT_RowIndex!==q?b._DT_RowIndex:
null},_fnNodeToColumnIndex:function(a,b,c){return l.inArray(c,a.aoData[b].anCells)},_fnGetCellData:T,_fnSetCellData:Ib,_fnSplitObjNotation:hb,_fnGetObjectDataFn:ma,_fnSetObjectDataFn:ha,_fnGetDataMaster:ib,_fnClearTable:Ma,_fnDeleteIndex:Na,_fnInvalidate:va,_fnGetRowElements:gb,_fnCreateTr:fb,_fnBuildHead:Jb,_fnDrawHead:xa,_fnDraw:ja,_fnReDraw:ka,_fnAddOptionsHtml:Mb,_fnDetectHeader:wa,_fnGetUniqueThs:Pa,_fnFeatureHtmlFilter:Ob,_fnFilterComplete:ya,_fnFilterCustom:Xb,_fnFilterColumn:Wb,_fnFilter:Vb,
_fnFilterCreateSearch:nb,_fnEscapeRegex:ob,_fnFilterData:Yb,_fnFeatureHtmlInfo:Rb,_fnUpdateInfo:ac,_fnInfoMacros:bc,_fnInitialise:Aa,_fnInitComplete:Ra,_fnLengthChange:pb,_fnFeatureHtmlLength:Nb,_fnFeatureHtmlPaginate:Sb,_fnPageChange:Ta,_fnFeatureHtmlProcessing:Pb,_fnProcessingDisplay:V,_fnFeatureHtmlTable:Qb,_fnScrollDraw:Ja,_fnApplyToChildren:da,_fnCalculateColumnWidths:db,_fnThrottle:mb,_fnConvertToWidth:cc,_fnGetWidestNode:dc,_fnGetMaxLenString:ec,_fnStringToCss:K,_fnSortFlatten:oa,_fnSort:Lb,
_fnSortAria:gc,_fnSortListener:rb,_fnSortAttachListener:kb,_fnSortingClasses:Va,_fnSortData:fc,_fnSaveState:Da,_fnLoadState:hc,_fnImplementState:tb,_fnSettingsFromNode:Wa,_fnLog:ea,_fnMap:Y,_fnBindAction:sb,_fnCallbackReg:R,_fnCallbackFire:F,_fnLengthOverflow:qb,_fnRenderer:lb,_fnDataSource:Q,_fnRowAttributes:jb,_fnExtend:ub,_fnCalculateEnd:function(){}});l.fn.dataTable=u;u.$=l;l.fn.dataTableSettings=u.settings;l.fn.dataTableExt=u.ext;l.fn.DataTable=function(a){return l(this).dataTable(a).api()};
l.each(u,function(a,b){l.fn.DataTable[a]=b});return u});
;
/*!
 DataTables Bootstrap 3 integration
 ©2011-2015 SpryMedia Ltd - datatables.net/license
*/
var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.findInternal=function(a,b,c){a instanceof String&&(a=String(a));for(var e=a.length,d=0;d<e;d++){var f=a[d];if(b.call(c,f,d,a))return{i:d,v:f}}return{i:-1,v:void 0}};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.SIMPLE_FROUND_POLYFILL=!1;$jscomp.ISOLATE_POLYFILLS=!1;
$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){if(a==Array.prototype||a==Object.prototype)return a;a[b]=c.value;return a};$jscomp.getGlobal=function(a){a=["object"==typeof globalThis&&globalThis,a,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var b=0;b<a.length;++b){var c=a[b];if(c&&c.Math==Math)return c}throw Error("Cannot find global object");};$jscomp.global=$jscomp.getGlobal(this);
$jscomp.IS_SYMBOL_NATIVE="function"===typeof Symbol&&"symbol"===typeof Symbol("x");$jscomp.TRUST_ES6_POLYFILLS=!$jscomp.ISOLATE_POLYFILLS||$jscomp.IS_SYMBOL_NATIVE;$jscomp.polyfills={};$jscomp.propertyToPolyfillSymbol={};$jscomp.POLYFILL_PREFIX="$jscp$";var $jscomp$lookupPolyfilledValue=function(a,b){var c=$jscomp.propertyToPolyfillSymbol[b];if(null==c)return a[b];c=a[c];return void 0!==c?c:a[b]};
$jscomp.polyfill=function(a,b,c,e){b&&($jscomp.ISOLATE_POLYFILLS?$jscomp.polyfillIsolated(a,b,c,e):$jscomp.polyfillUnisolated(a,b,c,e))};$jscomp.polyfillUnisolated=function(a,b,c,e){c=$jscomp.global;a=a.split(".");for(e=0;e<a.length-1;e++){var d=a[e];if(!(d in c))return;c=c[d]}a=a[a.length-1];e=c[a];b=b(e);b!=e&&null!=b&&$jscomp.defineProperty(c,a,{configurable:!0,writable:!0,value:b})};
$jscomp.polyfillIsolated=function(a,b,c,e){var d=a.split(".");a=1===d.length;e=d[0];e=!a&&e in $jscomp.polyfills?$jscomp.polyfills:$jscomp.global;for(var f=0;f<d.length-1;f++){var l=d[f];if(!(l in e))return;e=e[l]}d=d[d.length-1];c=$jscomp.IS_SYMBOL_NATIVE&&"es6"===c?e[d]:null;b=b(c);null!=b&&(a?$jscomp.defineProperty($jscomp.polyfills,d,{configurable:!0,writable:!0,value:b}):b!==c&&($jscomp.propertyToPolyfillSymbol[d]=$jscomp.IS_SYMBOL_NATIVE?$jscomp.global.Symbol(d):$jscomp.POLYFILL_PREFIX+d,d=
$jscomp.propertyToPolyfillSymbol[d],$jscomp.defineProperty(e,d,{configurable:!0,writable:!0,value:b})))};$jscomp.polyfill("Array.prototype.find",function(a){return a?a:function(b,c){return $jscomp.findInternal(this,b,c).v}},"es6","es3");
(function(a){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(b){return a(b,window,document)}):"object"===typeof exports?module.exports=function(b,c){b||(b=window);c&&c.fn.dataTable||(c=require("datatables.net")(b,c).$);return a(c,b,b.document)}:a(jQuery,window,document)})(function(a,b,c,e){var d=a.fn.dataTable;a.extend(!0,d.defaults,{dom:"<'row'<'col-sm-6'l><'col-sm-6'f>><'row'<'col-sm-12'tr>><'row'<'col-sm-5'i><'col-sm-7'p>>",renderer:"bootstrap"});a.extend(d.ext.classes,
{sWrapper:"dataTables_wrapper form-inline dt-bootstrap",sFilterInput:"form-control input-sm",sLengthSelect:"form-control input-sm",sProcessing:"dataTables_processing panel panel-default"});d.ext.renderer.pageButton.bootstrap=function(f,l,A,B,m,t){var u=new d.Api(f),C=f.oClasses,n=f.oLanguage.oPaginate,D=f.oLanguage.oAria.paginate||{},h,k,v=0,y=function(q,w){var x,E=function(p){p.preventDefault();a(p.currentTarget).hasClass("disabled")||u.page()==p.data.action||u.page(p.data.action).draw("page")};
var r=0;for(x=w.length;r<x;r++){var g=w[r];if(Array.isArray(g))y(q,g);else{k=h="";switch(g){case "ellipsis":h="&#x2026;";k="disabled";break;case "first":h=n.sFirst;k=g+(0<m?"":" disabled");break;case "previous":h=n.sPrevious;k=g+(0<m?"":" disabled");break;case "next":h=n.sNext;k=g+(m<t-1?"":" disabled");break;case "last":h=n.sLast;k=g+(m<t-1?"":" disabled");break;default:h=g+1,k=m===g?"active":""}if(h){var F=a("<li>",{"class":C.sPageButton+" "+k,id:0===A&&"string"===typeof g?f.sTableId+"_"+g:null}).append(a("<a>",
{href:"#","aria-controls":f.sTableId,"aria-label":D[g],"data-dt-idx":v,tabindex:f.iTabIndex}).html(h)).appendTo(q);f.oApi._fnBindAction(F,{action:g},E);v++}}}};try{var z=a(l).find(c.activeElement).data("dt-idx")}catch(q){}y(a(l).empty().html('<ul class="pagination"/>').children("ul"),B);z!==e&&a(l).find("[data-dt-idx="+z+"]").trigger("focus")};return d});
;
/**
 * @license
 * Lodash lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE
 */
;(function(){function n(n,t,r){switch(r.length){case 0:return n.call(t);case 1:return n.call(t,r[0]);case 2:return n.call(t,r[0],r[1]);case 3:return n.call(t,r[0],r[1],r[2])}return n.apply(t,r)}function t(n,t,r,e){for(var u=-1,i=null==n?0:n.length;++u<i;){var o=n[u];t(e,o,r(o),n)}return e}function r(n,t){for(var r=-1,e=null==n?0:n.length;++r<e&&false!==t(n[r],r,n););return n}function e(n,t){for(var r=null==n?0:n.length;r--&&false!==t(n[r],r,n););return n}function u(n,t){for(var r=-1,e=null==n?0:n.length;++r<e;)if(!t(n[r],r,n))return false;
return true}function i(n,t){for(var r=-1,e=null==n?0:n.length,u=0,i=[];++r<e;){var o=n[r];t(o,r,n)&&(i[u++]=o)}return i}function o(n,t){return!(null==n||!n.length)&&-1<v(n,t,0)}function f(n,t,r){for(var e=-1,u=null==n?0:n.length;++e<u;)if(r(t,n[e]))return true;return false}function c(n,t){for(var r=-1,e=null==n?0:n.length,u=Array(e);++r<e;)u[r]=t(n[r],r,n);return u}function a(n,t){for(var r=-1,e=t.length,u=n.length;++r<e;)n[u+r]=t[r];return n}function l(n,t,r,e){var u=-1,i=null==n?0:n.length;for(e&&i&&(r=n[++u]);++u<i;)r=t(r,n[u],u,n);
return r}function s(n,t,r,e){var u=null==n?0:n.length;for(e&&u&&(r=n[--u]);u--;)r=t(r,n[u],u,n);return r}function h(n,t){for(var r=-1,e=null==n?0:n.length;++r<e;)if(t(n[r],r,n))return true;return false}function p(n,t,r){var e;return r(n,function(n,r,u){if(t(n,r,u))return e=r,false}),e}function _(n,t,r,e){var u=n.length;for(r+=e?1:-1;e?r--:++r<u;)if(t(n[r],r,n))return r;return-1}function v(n,t,r){if(t===t)n:{--r;for(var e=n.length;++r<e;)if(n[r]===t){n=r;break n}n=-1}else n=_(n,d,r);return n}function g(n,t,r,e){
--r;for(var u=n.length;++r<u;)if(e(n[r],t))return r;return-1}function d(n){return n!==n}function y(n,t){var r=null==n?0:n.length;return r?m(n,t)/r:F}function b(n){return function(t){return null==t?T:t[n]}}function x(n){return function(t){return null==n?T:n[t]}}function j(n,t,r,e,u){return u(n,function(n,u,i){r=e?(e=false,n):t(r,n,u,i)}),r}function w(n,t){var r=n.length;for(n.sort(t);r--;)n[r]=n[r].c;return n}function m(n,t){for(var r,e=-1,u=n.length;++e<u;){var i=t(n[e]);i!==T&&(r=r===T?i:r+i)}return r;
}function A(n,t){for(var r=-1,e=Array(n);++r<n;)e[r]=t(r);return e}function E(n,t){return c(t,function(t){return[t,n[t]]})}function k(n){return function(t){return n(t)}}function S(n,t){return c(t,function(t){return n[t]})}function O(n,t){return n.has(t)}function I(n,t){for(var r=-1,e=n.length;++r<e&&-1<v(t,n[r],0););return r}function R(n,t){for(var r=n.length;r--&&-1<v(t,n[r],0););return r}function z(n){return"\\"+Un[n]}function W(n){var t=-1,r=Array(n.size);return n.forEach(function(n,e){r[++t]=[e,n];
}),r}function B(n,t){return function(r){return n(t(r))}}function L(n,t){for(var r=-1,e=n.length,u=0,i=[];++r<e;){var o=n[r];o!==t&&"__lodash_placeholder__"!==o||(n[r]="__lodash_placeholder__",i[u++]=r)}return i}function U(n){var t=-1,r=Array(n.size);return n.forEach(function(n){r[++t]=n}),r}function C(n){var t=-1,r=Array(n.size);return n.forEach(function(n){r[++t]=[n,n]}),r}function D(n){if(Rn.test(n)){for(var t=On.lastIndex=0;On.test(n);)++t;n=t}else n=Qn(n);return n}function M(n){return Rn.test(n)?n.match(On)||[]:n.split("");
}var T,$=1/0,F=NaN,N=[["ary",128],["bind",1],["bindKey",2],["curry",8],["curryRight",16],["flip",512],["partial",32],["partialRight",64],["rearg",256]],P=/\b__p\+='';/g,Z=/\b(__p\+=)''\+/g,q=/(__e\(.*?\)|\b__t\))\+'';/g,V=/&(?:amp|lt|gt|quot|#39);/g,K=/[&<>"']/g,G=RegExp(V.source),H=RegExp(K.source),J=/<%-([\s\S]+?)%>/g,Y=/<%([\s\S]+?)%>/g,Q=/<%=([\s\S]+?)%>/g,X=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,nn=/^\w*$/,tn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,rn=/[\\^$.*+?()[\]{}|]/g,en=RegExp(rn.source),un=/^\s+|\s+$/g,on=/^\s+/,fn=/\s+$/,cn=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,an=/\{\n\/\* \[wrapped with (.+)\] \*/,ln=/,? & /,sn=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,hn=/\\(\\)?/g,pn=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,_n=/\w*$/,vn=/^[-+]0x[0-9a-f]+$/i,gn=/^0b[01]+$/i,dn=/^\[object .+?Constructor\]$/,yn=/^0o[0-7]+$/i,bn=/^(?:0|[1-9]\d*)$/,xn=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,jn=/($^)/,wn=/['\n\r\u2028\u2029\\]/g,mn="[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?(?:\\u200d(?:[^\\ud800-\\udfff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?)*",An="(?:[\\u2700-\\u27bf]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])"+mn,En="(?:[^\\ud800-\\udfff][\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]?|[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\ud800-\\udfff])",kn=RegExp("['\u2019]","g"),Sn=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]","g"),On=RegExp("\\ud83c[\\udffb-\\udfff](?=\\ud83c[\\udffb-\\udfff])|"+En+mn,"g"),In=RegExp(["[A-Z\\xc0-\\xd6\\xd8-\\xde]?[a-z\\xdf-\\xf6\\xf8-\\xff]+(?:['\u2019](?:d|ll|m|re|s|t|ve))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde]|$)|(?:[A-Z\\xc0-\\xd6\\xd8-\\xde]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde](?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])|$)|[A-Z\\xc0-\\xd6\\xd8-\\xde]?(?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:d|ll|m|re|s|t|ve))?|[A-Z\\xc0-\\xd6\\xd8-\\xde]+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?|\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])|\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])|\\d+",An].join("|"),"g"),Rn=RegExp("[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff\\ufe0e\\ufe0f]"),zn=/[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Wn="Array Buffer DataView Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Map Math Object Promise RegExp Set String Symbol TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap _ clearTimeout isFinite parseInt setTimeout".split(" "),Bn={};
Bn["[object Float32Array]"]=Bn["[object Float64Array]"]=Bn["[object Int8Array]"]=Bn["[object Int16Array]"]=Bn["[object Int32Array]"]=Bn["[object Uint8Array]"]=Bn["[object Uint8ClampedArray]"]=Bn["[object Uint16Array]"]=Bn["[object Uint32Array]"]=true,Bn["[object Arguments]"]=Bn["[object Array]"]=Bn["[object ArrayBuffer]"]=Bn["[object Boolean]"]=Bn["[object DataView]"]=Bn["[object Date]"]=Bn["[object Error]"]=Bn["[object Function]"]=Bn["[object Map]"]=Bn["[object Number]"]=Bn["[object Object]"]=Bn["[object RegExp]"]=Bn["[object Set]"]=Bn["[object String]"]=Bn["[object WeakMap]"]=false;
var Ln={};Ln["[object Arguments]"]=Ln["[object Array]"]=Ln["[object ArrayBuffer]"]=Ln["[object DataView]"]=Ln["[object Boolean]"]=Ln["[object Date]"]=Ln["[object Float32Array]"]=Ln["[object Float64Array]"]=Ln["[object Int8Array]"]=Ln["[object Int16Array]"]=Ln["[object Int32Array]"]=Ln["[object Map]"]=Ln["[object Number]"]=Ln["[object Object]"]=Ln["[object RegExp]"]=Ln["[object Set]"]=Ln["[object String]"]=Ln["[object Symbol]"]=Ln["[object Uint8Array]"]=Ln["[object Uint8ClampedArray]"]=Ln["[object Uint16Array]"]=Ln["[object Uint32Array]"]=true,
Ln["[object Error]"]=Ln["[object Function]"]=Ln["[object WeakMap]"]=false;var Un={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Cn=parseFloat,Dn=parseInt,Mn=typeof global=="object"&&global&&global.Object===Object&&global,Tn=typeof self=="object"&&self&&self.Object===Object&&self,$n=Mn||Tn||Function("return this")(),Fn=typeof exports=="object"&&exports&&!exports.nodeType&&exports,Nn=Fn&&typeof module=="object"&&module&&!module.nodeType&&module,Pn=Nn&&Nn.exports===Fn,Zn=Pn&&Mn.process,qn=function(){
try{var n=Nn&&Nn.f&&Nn.f("util").types;return n?n:Zn&&Zn.binding&&Zn.binding("util")}catch(n){}}(),Vn=qn&&qn.isArrayBuffer,Kn=qn&&qn.isDate,Gn=qn&&qn.isMap,Hn=qn&&qn.isRegExp,Jn=qn&&qn.isSet,Yn=qn&&qn.isTypedArray,Qn=b("length"),Xn=x({"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I",
"\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\u0100":"A","\u0102":"A","\u0104":"A","\u0101":"a","\u0103":"a","\u0105":"a","\u0106":"C",
"\u0108":"C","\u010a":"C","\u010c":"C","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\u010e":"D","\u0110":"D","\u010f":"d","\u0111":"d","\u0112":"E","\u0114":"E","\u0116":"E","\u0118":"E","\u011a":"E","\u0113":"e","\u0115":"e","\u0117":"e","\u0119":"e","\u011b":"e","\u011c":"G","\u011e":"G","\u0120":"G","\u0122":"G","\u011d":"g","\u011f":"g","\u0121":"g","\u0123":"g","\u0124":"H","\u0126":"H","\u0125":"h","\u0127":"h","\u0128":"I","\u012a":"I","\u012c":"I","\u012e":"I","\u0130":"I","\u0129":"i",
"\u012b":"i","\u012d":"i","\u012f":"i","\u0131":"i","\u0134":"J","\u0135":"j","\u0136":"K","\u0137":"k","\u0138":"k","\u0139":"L","\u013b":"L","\u013d":"L","\u013f":"L","\u0141":"L","\u013a":"l","\u013c":"l","\u013e":"l","\u0140":"l","\u0142":"l","\u0143":"N","\u0145":"N","\u0147":"N","\u014a":"N","\u0144":"n","\u0146":"n","\u0148":"n","\u014b":"n","\u014c":"O","\u014e":"O","\u0150":"O","\u014d":"o","\u014f":"o","\u0151":"o","\u0154":"R","\u0156":"R","\u0158":"R","\u0155":"r","\u0157":"r","\u0159":"r",
"\u015a":"S","\u015c":"S","\u015e":"S","\u0160":"S","\u015b":"s","\u015d":"s","\u015f":"s","\u0161":"s","\u0162":"T","\u0164":"T","\u0166":"T","\u0163":"t","\u0165":"t","\u0167":"t","\u0168":"U","\u016a":"U","\u016c":"U","\u016e":"U","\u0170":"U","\u0172":"U","\u0169":"u","\u016b":"u","\u016d":"u","\u016f":"u","\u0171":"u","\u0173":"u","\u0174":"W","\u0175":"w","\u0176":"Y","\u0177":"y","\u0178":"Y","\u0179":"Z","\u017b":"Z","\u017d":"Z","\u017a":"z","\u017c":"z","\u017e":"z","\u0132":"IJ","\u0133":"ij",
"\u0152":"Oe","\u0153":"oe","\u0149":"'n","\u017f":"s"}),nt=x({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}),tt=x({"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&#39;":"'"}),rt=function x(mn){function An(n){if(du(n)&&!of(n)&&!(n instanceof Un)){if(n instanceof On)return n;if(ii.call(n,"__wrapped__"))return $e(n)}return new On(n)}function En(){}function On(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=T}function Un(n){this.__wrapped__=n,
this.__actions__=[],this.__dir__=1,this.__filtered__=false,this.__iteratees__=[],this.__takeCount__=4294967295,this.__views__=[]}function Mn(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function Tn(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function Fn(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function Nn(n){var t=-1,r=null==n?0:n.length;for(this.__data__=new Fn;++t<r;)this.add(n[t]);
}function Zn(n){this.size=(this.__data__=new Tn(n)).size}function qn(n,t){var r,e=of(n),u=!e&&uf(n),i=!e&&!u&&cf(n),o=!e&&!u&&!i&&pf(n),u=(e=e||u||i||o)?A(n.length,Xu):[],f=u.length;for(r in n)!t&&!ii.call(n,r)||e&&("length"==r||i&&("offset"==r||"parent"==r)||o&&("buffer"==r||"byteLength"==r||"byteOffset"==r)||Se(r,f))||u.push(r);return u}function Qn(n){var t=n.length;return t?n[ir(0,t-1)]:T}function et(n,t){return Ce(Ur(n),pt(t,0,n.length))}function ut(n){return Ce(Ur(n))}function it(n,t,r){(r===T||au(n[t],r))&&(r!==T||t in n)||st(n,t,r);
}function ot(n,t,r){var e=n[t];ii.call(n,t)&&au(e,r)&&(r!==T||t in n)||st(n,t,r)}function ft(n,t){for(var r=n.length;r--;)if(au(n[r][0],t))return r;return-1}function ct(n,t,r,e){return eo(n,function(n,u,i){t(e,n,r(n),i)}),e}function at(n,t){return n&&Cr(t,zu(t),n)}function lt(n,t){return n&&Cr(t,Wu(t),n)}function st(n,t,r){"__proto__"==t&&mi?mi(n,t,{configurable:true,enumerable:true,value:r,writable:true}):n[t]=r}function ht(n,t){for(var r=-1,e=t.length,u=Vu(e),i=null==n;++r<e;)u[r]=i?T:Iu(n,t[r]);return u;
}function pt(n,t,r){return n===n&&(r!==T&&(n=n<=r?n:r),t!==T&&(n=n>=t?n:t)),n}function _t(n,t,e,u,i,o){var f,c=1&t,a=2&t,l=4&t;if(e&&(f=i?e(n,u,i,o):e(n)),f!==T)return f;if(!gu(n))return n;if(u=of(n)){if(f=me(n),!c)return Ur(n,f)}else{var s=_o(n),h="[object Function]"==s||"[object GeneratorFunction]"==s;if(cf(n))return Ir(n,c);if("[object Object]"==s||"[object Arguments]"==s||h&&!i){if(f=a||h?{}:Ae(n),!c)return a?Mr(n,lt(f,n)):Dr(n,at(f,n))}else{if(!Ln[s])return i?n:{};f=Ee(n,s,c)}}if(o||(o=new Zn),
i=o.get(n))return i;if(o.set(n,f),hf(n))return n.forEach(function(r){f.add(_t(r,t,e,r,n,o))}),f;if(lf(n))return n.forEach(function(r,u){f.set(u,_t(r,t,e,u,n,o))}),f;var a=l?a?ve:_e:a?Wu:zu,p=u?T:a(n);return r(p||n,function(r,u){p&&(u=r,r=n[u]),ot(f,u,_t(r,t,e,u,n,o))}),f}function vt(n){var t=zu(n);return function(r){return gt(r,n,t)}}function gt(n,t,r){var e=r.length;if(null==n)return!e;for(n=Yu(n);e--;){var u=r[e],i=t[u],o=n[u];if(o===T&&!(u in n)||!i(o))return false}return true}function dt(n,t,r){if(typeof n!="function")throw new ni("Expected a function");
return yo(function(){n.apply(T,r)},t)}function yt(n,t,r,e){var u=-1,i=o,a=true,l=n.length,s=[],h=t.length;if(!l)return s;r&&(t=c(t,k(r))),e?(i=f,a=false):200<=t.length&&(i=O,a=false,t=new Nn(t));n:for(;++u<l;){var p=n[u],_=null==r?p:r(p),p=e||0!==p?p:0;if(a&&_===_){for(var v=h;v--;)if(t[v]===_)continue n;s.push(p)}else i(t,_,e)||s.push(p)}return s}function bt(n,t){var r=true;return eo(n,function(n,e,u){return r=!!t(n,e,u)}),r}function xt(n,t,r){for(var e=-1,u=n.length;++e<u;){var i=n[e],o=t(i);if(null!=o&&(f===T?o===o&&!ju(o):r(o,f)))var f=o,c=i;
}return c}function jt(n,t){var r=[];return eo(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function wt(n,t,r,e,u){var i=-1,o=n.length;for(r||(r=ke),u||(u=[]);++i<o;){var f=n[i];0<t&&r(f)?1<t?wt(f,t-1,r,e,u):a(u,f):e||(u[u.length]=f)}return u}function mt(n,t){return n&&io(n,t,zu)}function At(n,t){return n&&oo(n,t,zu)}function Et(n,t){return i(t,function(t){return pu(n[t])})}function kt(n,t){t=Sr(t,n);for(var r=0,e=t.length;null!=n&&r<e;)n=n[De(t[r++])];return r&&r==e?n:T}function St(n,t,r){return t=t(n),
of(n)?t:a(t,r(n))}function Ot(n){if(null==n)n=n===T?"[object Undefined]":"[object Null]";else if(wi&&wi in Yu(n)){var t=ii.call(n,wi),r=n[wi];try{n[wi]=T;var e=true}catch(n){}var u=ci.call(n);e&&(t?n[wi]=r:delete n[wi]),n=u}else n=ci.call(n);return n}function It(n,t){return n>t}function Rt(n,t){return null!=n&&ii.call(n,t)}function zt(n,t){return null!=n&&t in Yu(n)}function Wt(n,t,r){for(var e=r?f:o,u=n[0].length,i=n.length,a=i,l=Vu(i),s=1/0,h=[];a--;){var p=n[a];a&&t&&(p=c(p,k(t))),s=Ui(p.length,s),
l[a]=!r&&(t||120<=u&&120<=p.length)?new Nn(a&&p):T}var p=n[0],_=-1,v=l[0];n:for(;++_<u&&h.length<s;){var g=p[_],d=t?t(g):g,g=r||0!==g?g:0;if(v?!O(v,d):!e(h,d,r)){for(a=i;--a;){var y=l[a];if(y?!O(y,d):!e(n[a],d,r))continue n}v&&v.push(d),h.push(g)}}return h}function Bt(n,t,r){var e={};return mt(n,function(n,u,i){t(e,r(n),u,i)}),e}function Lt(t,r,e){return r=Sr(r,t),t=2>r.length?t:kt(t,hr(r,0,-1)),r=null==t?t:t[De(qe(r))],null==r?T:n(r,t,e)}function Ut(n){return du(n)&&"[object Arguments]"==Ot(n)}function Ct(n){
return du(n)&&"[object ArrayBuffer]"==Ot(n)}function Dt(n){return du(n)&&"[object Date]"==Ot(n)}function Mt(n,t,r,e,u){if(n===t)t=true;else if(null==n||null==t||!du(n)&&!du(t))t=n!==n&&t!==t;else n:{var i=of(n),o=of(t),f=i?"[object Array]":_o(n),c=o?"[object Array]":_o(t),f="[object Arguments]"==f?"[object Object]":f,c="[object Arguments]"==c?"[object Object]":c,a="[object Object]"==f,o="[object Object]"==c;if((c=f==c)&&cf(n)){if(!cf(t)){t=false;break n}i=true,a=false}if(c&&!a)u||(u=new Zn),t=i||pf(n)?se(n,t,r,e,Mt,u):he(n,t,f,r,e,Mt,u);else{
if(!(1&r)&&(i=a&&ii.call(n,"__wrapped__"),f=o&&ii.call(t,"__wrapped__"),i||f)){n=i?n.value():n,t=f?t.value():t,u||(u=new Zn),t=Mt(n,t,r,e,u);break n}if(c)t:if(u||(u=new Zn),i=1&r,f=_e(n),o=f.length,c=_e(t).length,o==c||i){for(a=o;a--;){var l=f[a];if(!(i?l in t:ii.call(t,l))){t=false;break t}}if((c=u.get(n))&&u.get(t))t=c==t;else{c=true,u.set(n,t),u.set(t,n);for(var s=i;++a<o;){var l=f[a],h=n[l],p=t[l];if(e)var _=i?e(p,h,l,t,n,u):e(h,p,l,n,t,u);if(_===T?h!==p&&!Mt(h,p,r,e,u):!_){c=false;break}s||(s="constructor"==l);
}c&&!s&&(r=n.constructor,e=t.constructor,r!=e&&"constructor"in n&&"constructor"in t&&!(typeof r=="function"&&r instanceof r&&typeof e=="function"&&e instanceof e)&&(c=false)),u.delete(n),u.delete(t),t=c}}else t=false;else t=false}}return t}function Tt(n){return du(n)&&"[object Map]"==_o(n)}function $t(n,t,r,e){var u=r.length,i=u,o=!e;if(null==n)return!i;for(n=Yu(n);u--;){var f=r[u];if(o&&f[2]?f[1]!==n[f[0]]:!(f[0]in n))return false}for(;++u<i;){var f=r[u],c=f[0],a=n[c],l=f[1];if(o&&f[2]){if(a===T&&!(c in n))return false;
}else{if(f=new Zn,e)var s=e(a,l,c,n,t,f);if(s===T?!Mt(l,a,3,e,f):!s)return false}}return true}function Ft(n){return!(!gu(n)||fi&&fi in n)&&(pu(n)?si:dn).test(Me(n))}function Nt(n){return du(n)&&"[object RegExp]"==Ot(n)}function Pt(n){return du(n)&&"[object Set]"==_o(n)}function Zt(n){return du(n)&&vu(n.length)&&!!Bn[Ot(n)]}function qt(n){return typeof n=="function"?n:null==n?Tu:typeof n=="object"?of(n)?Jt(n[0],n[1]):Ht(n):Pu(n)}function Vt(n){if(!ze(n))return Bi(n);var t,r=[];for(t in Yu(n))ii.call(n,t)&&"constructor"!=t&&r.push(t);
return r}function Kt(n,t){return n<t}function Gt(n,t){var r=-1,e=lu(n)?Vu(n.length):[];return eo(n,function(n,u,i){e[++r]=t(n,u,i)}),e}function Ht(n){var t=xe(n);return 1==t.length&&t[0][2]?We(t[0][0],t[0][1]):function(r){return r===n||$t(r,n,t)}}function Jt(n,t){return Ie(n)&&t===t&&!gu(t)?We(De(n),t):function(r){var e=Iu(r,n);return e===T&&e===t?Ru(r,n):Mt(t,e,3)}}function Yt(n,t,r,e,u){n!==t&&io(t,function(i,o){if(gu(i)){u||(u=new Zn);var f=u,c="__proto__"==o?T:n[o],a="__proto__"==o?T:t[o],l=f.get(a);
if(l)it(n,o,l);else{var l=e?e(c,a,o+"",n,t,f):T,s=l===T;if(s){var h=of(a),p=!h&&cf(a),_=!h&&!p&&pf(a),l=a;h||p||_?of(c)?l=c:su(c)?l=Ur(c):p?(s=false,l=Ir(a,true)):_?(s=false,l=zr(a,true)):l=[]:bu(a)||uf(a)?(l=c,uf(c)?l=Su(c):(!gu(c)||r&&pu(c))&&(l=Ae(a))):s=false}s&&(f.set(a,l),Yt(l,a,r,e,f),f.delete(a)),it(n,o,l)}}else f=e?e("__proto__"==o?T:n[o],i,o+"",n,t,u):T,f===T&&(f=i),it(n,o,f)},Wu)}function Qt(n,t){var r=n.length;if(r)return t+=0>t?r:0,Se(t,r)?n[t]:T}function Xt(n,t,r){var e=-1;return t=c(t.length?t:[Tu],k(ye())),
n=Gt(n,function(n){return{a:c(t,function(t){return t(n)}),b:++e,c:n}}),w(n,function(n,t){var e;n:{e=-1;for(var u=n.a,i=t.a,o=u.length,f=r.length;++e<o;){var c=Wr(u[e],i[e]);if(c){e=e>=f?c:c*("desc"==r[e]?-1:1);break n}}e=n.b-t.b}return e})}function nr(n,t){return tr(n,t,function(t,r){return Ru(n,r)})}function tr(n,t,r){for(var e=-1,u=t.length,i={};++e<u;){var o=t[e],f=kt(n,o);r(f,o)&&lr(i,Sr(o,n),f)}return i}function rr(n){return function(t){return kt(t,n)}}function er(n,t,r,e){var u=e?g:v,i=-1,o=t.length,f=n;
for(n===t&&(t=Ur(t)),r&&(f=c(n,k(r)));++i<o;)for(var a=0,l=t[i],l=r?r(l):l;-1<(a=u(f,l,a,e));)f!==n&&bi.call(f,a,1),bi.call(n,a,1);return n}function ur(n,t){for(var r=n?t.length:0,e=r-1;r--;){var u=t[r];if(r==e||u!==i){var i=u;Se(u)?bi.call(n,u,1):xr(n,u)}}}function ir(n,t){return n+Oi(Mi()*(t-n+1))}function or(n,t){var r="";if(!n||1>t||9007199254740991<t)return r;do t%2&&(r+=n),(t=Oi(t/2))&&(n+=n);while(t);return r}function fr(n,t){return bo(Be(n,t,Tu),n+"")}function cr(n){return Qn(Lu(n))}function ar(n,t){
var r=Lu(n);return Ce(r,pt(t,0,r.length))}function lr(n,t,r,e){if(!gu(n))return n;t=Sr(t,n);for(var u=-1,i=t.length,o=i-1,f=n;null!=f&&++u<i;){var c=De(t[u]),a=r;if(u!=o){var l=f[c],a=e?e(l,c,f):T;a===T&&(a=gu(l)?l:Se(t[u+1])?[]:{})}ot(f,c,a),f=f[c]}return n}function sr(n){return Ce(Lu(n))}function hr(n,t,r){var e=-1,u=n.length;for(0>t&&(t=-t>u?0:u+t),r=r>u?u:r,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Vu(u);++e<u;)r[e]=n[e+t];return r}function pr(n,t){var r;return eo(n,function(n,e,u){return r=t(n,e,u),
!r}),!!r}function _r(n,t,r){var e=0,u=null==n?e:n.length;if(typeof t=="number"&&t===t&&2147483647>=u){for(;e<u;){var i=e+u>>>1,o=n[i];null!==o&&!ju(o)&&(r?o<=t:o<t)?e=i+1:u=i}return u}return vr(n,t,Tu,r)}function vr(n,t,r,e){t=r(t);for(var u=0,i=null==n?0:n.length,o=t!==t,f=null===t,c=ju(t),a=t===T;u<i;){var l=Oi((u+i)/2),s=r(n[l]),h=s!==T,p=null===s,_=s===s,v=ju(s);(o?e||_:a?_&&(e||h):f?_&&h&&(e||!p):c?_&&h&&!p&&(e||!v):p||v?0:e?s<=t:s<t)?u=l+1:i=l}return Ui(i,4294967294)}function gr(n,t){for(var r=-1,e=n.length,u=0,i=[];++r<e;){
var o=n[r],f=t?t(o):o;if(!r||!au(f,c)){var c=f;i[u++]=0===o?0:o}}return i}function dr(n){return typeof n=="number"?n:ju(n)?F:+n}function yr(n){if(typeof n=="string")return n;if(of(n))return c(n,yr)+"";if(ju(n))return to?to.call(n):"";var t=n+"";return"0"==t&&1/n==-$?"-0":t}function br(n,t,r){var e=-1,u=o,i=n.length,c=true,a=[],l=a;if(r)c=false,u=f;else if(200<=i){if(u=t?null:lo(n))return U(u);c=false,u=O,l=new Nn}else l=t?[]:a;n:for(;++e<i;){var s=n[e],h=t?t(s):s,s=r||0!==s?s:0;if(c&&h===h){for(var p=l.length;p--;)if(l[p]===h)continue n;
t&&l.push(h),a.push(s)}else u(l,h,r)||(l!==a&&l.push(h),a.push(s))}return a}function xr(n,t){return t=Sr(t,n),n=2>t.length?n:kt(n,hr(t,0,-1)),null==n||delete n[De(qe(t))]}function jr(n,t,r,e){for(var u=n.length,i=e?u:-1;(e?i--:++i<u)&&t(n[i],i,n););return r?hr(n,e?0:i,e?i+1:u):hr(n,e?i+1:0,e?u:i)}function wr(n,t){var r=n;return r instanceof Un&&(r=r.value()),l(t,function(n,t){return t.func.apply(t.thisArg,a([n],t.args))},r)}function mr(n,t,r){var e=n.length;if(2>e)return e?br(n[0]):[];for(var u=-1,i=Vu(e);++u<e;)for(var o=n[u],f=-1;++f<e;)f!=u&&(i[u]=yt(i[u]||o,n[f],t,r));
return br(wt(i,1),t,r)}function Ar(n,t,r){for(var e=-1,u=n.length,i=t.length,o={};++e<u;)r(o,n[e],e<i?t[e]:T);return o}function Er(n){return su(n)?n:[]}function kr(n){return typeof n=="function"?n:Tu}function Sr(n,t){return of(n)?n:Ie(n,t)?[n]:xo(Ou(n))}function Or(n,t,r){var e=n.length;return r=r===T?e:r,!t&&r>=e?n:hr(n,t,r)}function Ir(n,t){if(t)return n.slice();var r=n.length,r=vi?vi(r):new n.constructor(r);return n.copy(r),r}function Rr(n){var t=new n.constructor(n.byteLength);return new _i(t).set(new _i(n)),
t}function zr(n,t){return new n.constructor(t?Rr(n.buffer):n.buffer,n.byteOffset,n.length)}function Wr(n,t){if(n!==t){var r=n!==T,e=null===n,u=n===n,i=ju(n),o=t!==T,f=null===t,c=t===t,a=ju(t);if(!f&&!a&&!i&&n>t||i&&o&&c&&!f&&!a||e&&o&&c||!r&&c||!u)return 1;if(!e&&!i&&!a&&n<t||a&&r&&u&&!e&&!i||f&&r&&u||!o&&u||!c)return-1}return 0}function Br(n,t,r,e){var u=-1,i=n.length,o=r.length,f=-1,c=t.length,a=Li(i-o,0),l=Vu(c+a);for(e=!e;++f<c;)l[f]=t[f];for(;++u<o;)(e||u<i)&&(l[r[u]]=n[u]);for(;a--;)l[f++]=n[u++];
return l}function Lr(n,t,r,e){var u=-1,i=n.length,o=-1,f=r.length,c=-1,a=t.length,l=Li(i-f,0),s=Vu(l+a);for(e=!e;++u<l;)s[u]=n[u];for(l=u;++c<a;)s[l+c]=t[c];for(;++o<f;)(e||u<i)&&(s[l+r[o]]=n[u++]);return s}function Ur(n,t){var r=-1,e=n.length;for(t||(t=Vu(e));++r<e;)t[r]=n[r];return t}function Cr(n,t,r,e){var u=!r;r||(r={});for(var i=-1,o=t.length;++i<o;){var f=t[i],c=e?e(r[f],n[f],f,r,n):T;c===T&&(c=n[f]),u?st(r,f,c):ot(r,f,c)}return r}function Dr(n,t){return Cr(n,ho(n),t)}function Mr(n,t){return Cr(n,po(n),t);
}function Tr(n,r){return function(e,u){var i=of(e)?t:ct,o=r?r():{};return i(e,n,ye(u,2),o)}}function $r(n){return fr(function(t,r){var e=-1,u=r.length,i=1<u?r[u-1]:T,o=2<u?r[2]:T,i=3<n.length&&typeof i=="function"?(u--,i):T;for(o&&Oe(r[0],r[1],o)&&(i=3>u?T:i,u=1),t=Yu(t);++e<u;)(o=r[e])&&n(t,o,e,i);return t})}function Fr(n,t){return function(r,e){if(null==r)return r;if(!lu(r))return n(r,e);for(var u=r.length,i=t?u:-1,o=Yu(r);(t?i--:++i<u)&&false!==e(o[i],i,o););return r}}function Nr(n){return function(t,r,e){
var u=-1,i=Yu(t);e=e(t);for(var o=e.length;o--;){var f=e[n?o:++u];if(false===r(i[f],f,i))break}return t}}function Pr(n,t,r){function e(){return(this&&this!==$n&&this instanceof e?i:n).apply(u?r:this,arguments)}var u=1&t,i=Vr(n);return e}function Zr(n){return function(t){t=Ou(t);var r=Rn.test(t)?M(t):T,e=r?r[0]:t.charAt(0);return t=r?Or(r,1).join(""):t.slice(1),e[n]()+t}}function qr(n){return function(t){return l(Du(Cu(t).replace(kn,"")),n,"")}}function Vr(n){return function(){var t=arguments;switch(t.length){
case 0:return new n;case 1:return new n(t[0]);case 2:return new n(t[0],t[1]);case 3:return new n(t[0],t[1],t[2]);case 4:return new n(t[0],t[1],t[2],t[3]);case 5:return new n(t[0],t[1],t[2],t[3],t[4]);case 6:return new n(t[0],t[1],t[2],t[3],t[4],t[5]);case 7:return new n(t[0],t[1],t[2],t[3],t[4],t[5],t[6])}var r=ro(n.prototype),t=n.apply(r,t);return gu(t)?t:r}}function Kr(t,r,e){function u(){for(var o=arguments.length,f=Vu(o),c=o,a=de(u);c--;)f[c]=arguments[c];return c=3>o&&f[0]!==a&&f[o-1]!==a?[]:L(f,a),
o-=c.length,o<e?ue(t,r,Jr,u.placeholder,T,f,c,T,T,e-o):n(this&&this!==$n&&this instanceof u?i:t,this,f)}var i=Vr(t);return u}function Gr(n){return function(t,r,e){var u=Yu(t);if(!lu(t)){var i=ye(r,3);t=zu(t),r=function(n){return i(u[n],n,u)}}return r=n(t,r,e),-1<r?u[i?t[r]:r]:T}}function Hr(n){return pe(function(t){var r=t.length,e=r,u=On.prototype.thru;for(n&&t.reverse();e--;){var i=t[e];if(typeof i!="function")throw new ni("Expected a function");if(u&&!o&&"wrapper"==ge(i))var o=new On([],true)}for(e=o?e:r;++e<r;)var i=t[e],u=ge(i),f="wrapper"==u?so(i):T,o=f&&Re(f[0])&&424==f[1]&&!f[4].length&&1==f[9]?o[ge(f[0])].apply(o,f[3]):1==i.length&&Re(i)?o[u]():o.thru(i);
return function(){var n=arguments,e=n[0];if(o&&1==n.length&&of(e))return o.plant(e).value();for(var u=0,n=r?t[u].apply(this,n):e;++u<r;)n=t[u].call(this,n);return n}})}function Jr(n,t,r,e,u,i,o,f,c,a){function l(){for(var d=arguments.length,y=Vu(d),b=d;b--;)y[b]=arguments[b];if(_){var x,j=de(l),b=y.length;for(x=0;b--;)y[b]===j&&++x}if(e&&(y=Br(y,e,u,_)),i&&(y=Lr(y,i,o,_)),d-=x,_&&d<a)return j=L(y,j),ue(n,t,Jr,l.placeholder,r,y,j,f,c,a-d);if(j=h?r:this,b=p?j[n]:n,d=y.length,f){x=y.length;for(var w=Ui(f.length,x),m=Ur(y);w--;){
var A=f[w];y[w]=Se(A,x)?m[A]:T}}else v&&1<d&&y.reverse();return s&&c<d&&(y.length=c),this&&this!==$n&&this instanceof l&&(b=g||Vr(b)),b.apply(j,y)}var s=128&t,h=1&t,p=2&t,_=24&t,v=512&t,g=p?T:Vr(n);return l}function Yr(n,t){return function(r,e){return Bt(r,n,t(e))}}function Qr(n,t){return function(r,e){var u;if(r===T&&e===T)return t;if(r!==T&&(u=r),e!==T){if(u===T)return e;typeof r=="string"||typeof e=="string"?(r=yr(r),e=yr(e)):(r=dr(r),e=dr(e)),u=n(r,e)}return u}}function Xr(t){return pe(function(r){
return r=c(r,k(ye())),fr(function(e){var u=this;return t(r,function(t){return n(t,u,e)})})})}function ne(n,t){t=t===T?" ":yr(t);var r=t.length;return 2>r?r?or(t,n):t:(r=or(t,Si(n/D(t))),Rn.test(t)?Or(M(r),0,n).join(""):r.slice(0,n))}function te(t,r,e,u){function i(){for(var r=-1,c=arguments.length,a=-1,l=u.length,s=Vu(l+c),h=this&&this!==$n&&this instanceof i?f:t;++a<l;)s[a]=u[a];for(;c--;)s[a++]=arguments[++r];return n(h,o?e:this,s)}var o=1&r,f=Vr(t);return i}function re(n){return function(t,r,e){
e&&typeof e!="number"&&Oe(t,r,e)&&(r=e=T),t=mu(t),r===T?(r=t,t=0):r=mu(r),e=e===T?t<r?1:-1:mu(e);var u=-1;r=Li(Si((r-t)/(e||1)),0);for(var i=Vu(r);r--;)i[n?r:++u]=t,t+=e;return i}}function ee(n){return function(t,r){return typeof t=="string"&&typeof r=="string"||(t=ku(t),r=ku(r)),n(t,r)}}function ue(n,t,r,e,u,i,o,f,c,a){var l=8&t,s=l?o:T;o=l?T:o;var h=l?i:T;return i=l?T:i,t=(t|(l?32:64))&~(l?64:32),4&t||(t&=-4),u=[n,t,u,h,s,i,o,f,c,a],r=r.apply(T,u),Re(n)&&go(r,u),r.placeholder=e,Le(r,n,t)}function ie(n){
var t=Ju[n];return function(n,r){if(n=ku(n),r=null==r?0:Ui(Au(r),292)){var e=(Ou(n)+"e").split("e"),e=t(e[0]+"e"+(+e[1]+r)),e=(Ou(e)+"e").split("e");return+(e[0]+"e"+(+e[1]-r))}return t(n)}}function oe(n){return function(t){var r=_o(t);return"[object Map]"==r?W(t):"[object Set]"==r?C(t):E(t,n(t))}}function fe(n,t,r,e,u,i,o,f){var c=2&t;if(!c&&typeof n!="function")throw new ni("Expected a function");var a=e?e.length:0;if(a||(t&=-97,e=u=T),o=o===T?o:Li(Au(o),0),f=f===T?f:Au(f),a-=u?u.length:0,64&t){
var l=e,s=u;e=u=T}var h=c?T:so(n);return i=[n,t,r,e,u,l,s,i,o,f],h&&(r=i[1],n=h[1],t=r|n,e=128==n&&8==r||128==n&&256==r&&i[7].length<=h[8]||384==n&&h[7].length<=h[8]&&8==r,131>t||e)&&(1&n&&(i[2]=h[2],t|=1&r?0:4),(r=h[3])&&(e=i[3],i[3]=e?Br(e,r,h[4]):r,i[4]=e?L(i[3],"__lodash_placeholder__"):h[4]),(r=h[5])&&(e=i[5],i[5]=e?Lr(e,r,h[6]):r,i[6]=e?L(i[5],"__lodash_placeholder__"):h[6]),(r=h[7])&&(i[7]=r),128&n&&(i[8]=null==i[8]?h[8]:Ui(i[8],h[8])),null==i[9]&&(i[9]=h[9]),i[0]=h[0],i[1]=t),n=i[0],t=i[1],
r=i[2],e=i[3],u=i[4],f=i[9]=i[9]===T?c?0:n.length:Li(i[9]-a,0),!f&&24&t&&(t&=-25),Le((h?fo:go)(t&&1!=t?8==t||16==t?Kr(n,t,f):32!=t&&33!=t||u.length?Jr.apply(T,i):te(n,t,r,e):Pr(n,t,r),i),n,t)}function ce(n,t,r,e){return n===T||au(n,ri[r])&&!ii.call(e,r)?t:n}function ae(n,t,r,e,u,i){return gu(n)&&gu(t)&&(i.set(t,n),Yt(n,t,T,ae,i),i.delete(t)),n}function le(n){return bu(n)?T:n}function se(n,t,r,e,u,i){var o=1&r,f=n.length,c=t.length;if(f!=c&&!(o&&c>f))return false;if((c=i.get(n))&&i.get(t))return c==t;var c=-1,a=true,l=2&r?new Nn:T;
for(i.set(n,t),i.set(t,n);++c<f;){var s=n[c],p=t[c];if(e)var _=o?e(p,s,c,t,n,i):e(s,p,c,n,t,i);if(_!==T){if(_)continue;a=false;break}if(l){if(!h(t,function(n,t){if(!O(l,t)&&(s===n||u(s,n,r,e,i)))return l.push(t)})){a=false;break}}else if(s!==p&&!u(s,p,r,e,i)){a=false;break}}return i.delete(n),i.delete(t),a}function he(n,t,r,e,u,i,o){switch(r){case"[object DataView]":if(n.byteLength!=t.byteLength||n.byteOffset!=t.byteOffset)break;n=n.buffer,t=t.buffer;case"[object ArrayBuffer]":if(n.byteLength!=t.byteLength||!i(new _i(n),new _i(t)))break;
return true;case"[object Boolean]":case"[object Date]":case"[object Number]":return au(+n,+t);case"[object Error]":return n.name==t.name&&n.message==t.message;case"[object RegExp]":case"[object String]":return n==t+"";case"[object Map]":var f=W;case"[object Set]":if(f||(f=U),n.size!=t.size&&!(1&e))break;return(r=o.get(n))?r==t:(e|=2,o.set(n,t),t=se(f(n),f(t),e,u,i,o),o.delete(n),t);case"[object Symbol]":if(no)return no.call(n)==no.call(t)}return false}function pe(n){return bo(Be(n,T,Pe),n+"")}function _e(n){
return St(n,zu,ho)}function ve(n){return St(n,Wu,po)}function ge(n){for(var t=n.name+"",r=Ki[t],e=ii.call(Ki,t)?r.length:0;e--;){var u=r[e],i=u.func;if(null==i||i==n)return u.name}return t}function de(n){return(ii.call(An,"placeholder")?An:n).placeholder}function ye(){var n=An.iteratee||$u,n=n===$u?qt:n;return arguments.length?n(arguments[0],arguments[1]):n}function be(n,t){var r=n.__data__,e=typeof t;return("string"==e||"number"==e||"symbol"==e||"boolean"==e?"__proto__"!==t:null===t)?r[typeof t=="string"?"string":"hash"]:r.map;
}function xe(n){for(var t=zu(n),r=t.length;r--;){var e=t[r],u=n[e];t[r]=[e,u,u===u&&!gu(u)]}return t}function je(n,t){var r=null==n?T:n[t];return Ft(r)?r:T}function we(n,t,r){t=Sr(t,n);for(var e=-1,u=t.length,i=false;++e<u;){var o=De(t[e]);if(!(i=null!=n&&r(n,o)))break;n=n[o]}return i||++e!=u?i:(u=null==n?0:n.length,!!u&&vu(u)&&Se(o,u)&&(of(n)||uf(n)))}function me(n){var t=n.length,r=new n.constructor(t);return t&&"string"==typeof n[0]&&ii.call(n,"index")&&(r.index=n.index,r.input=n.input),r}function Ae(n){
return typeof n.constructor!="function"||ze(n)?{}:ro(gi(n))}function Ee(n,t,r){var e=n.constructor;switch(t){case"[object ArrayBuffer]":return Rr(n);case"[object Boolean]":case"[object Date]":return new e(+n);case"[object DataView]":return t=r?Rr(n.buffer):n.buffer,new n.constructor(t,n.byteOffset,n.byteLength);case"[object Float32Array]":case"[object Float64Array]":case"[object Int8Array]":case"[object Int16Array]":case"[object Int32Array]":case"[object Uint8Array]":case"[object Uint8ClampedArray]":
case"[object Uint16Array]":case"[object Uint32Array]":return zr(n,r);case"[object Map]":return new e;case"[object Number]":case"[object String]":return new e(n);case"[object RegExp]":return t=new n.constructor(n.source,_n.exec(n)),t.lastIndex=n.lastIndex,t;case"[object Set]":return new e;case"[object Symbol]":return no?Yu(no.call(n)):{}}}function ke(n){return of(n)||uf(n)||!!(xi&&n&&n[xi])}function Se(n,t){var r=typeof n;return t=null==t?9007199254740991:t,!!t&&("number"==r||"symbol"!=r&&bn.test(n))&&-1<n&&0==n%1&&n<t;
}function Oe(n,t,r){if(!gu(r))return false;var e=typeof t;return!!("number"==e?lu(r)&&Se(t,r.length):"string"==e&&t in r)&&au(r[t],n)}function Ie(n,t){if(of(n))return false;var r=typeof n;return!("number"!=r&&"symbol"!=r&&"boolean"!=r&&null!=n&&!ju(n))||(nn.test(n)||!X.test(n)||null!=t&&n in Yu(t))}function Re(n){var t=ge(n),r=An[t];return typeof r=="function"&&t in Un.prototype&&(n===r||(t=so(r),!!t&&n===t[0]))}function ze(n){var t=n&&n.constructor;return n===(typeof t=="function"&&t.prototype||ri)}function We(n,t){
return function(r){return null!=r&&(r[n]===t&&(t!==T||n in Yu(r)))}}function Be(t,r,e){return r=Li(r===T?t.length-1:r,0),function(){for(var u=arguments,i=-1,o=Li(u.length-r,0),f=Vu(o);++i<o;)f[i]=u[r+i];for(i=-1,o=Vu(r+1);++i<r;)o[i]=u[i];return o[r]=e(f),n(t,this,o)}}function Le(n,t,r){var e=t+"";t=bo;var u,i=Te;return u=(u=e.match(an))?u[1].split(ln):[],r=i(u,r),(i=r.length)&&(u=i-1,r[u]=(1<i?"& ":"")+r[u],r=r.join(2<i?", ":" "),e=e.replace(cn,"{\n/* [wrapped with "+r+"] */\n")),t(n,e)}function Ue(n){
var t=0,r=0;return function(){var e=Ci(),u=16-(e-r);if(r=e,0<u){if(800<=++t)return arguments[0]}else t=0;return n.apply(T,arguments)}}function Ce(n,t){var r=-1,e=n.length,u=e-1;for(t=t===T?e:t;++r<t;){var e=ir(r,u),i=n[e];n[e]=n[r],n[r]=i}return n.length=t,n}function De(n){if(typeof n=="string"||ju(n))return n;var t=n+"";return"0"==t&&1/n==-$?"-0":t}function Me(n){if(null!=n){try{return ui.call(n)}catch(n){}return n+""}return""}function Te(n,t){return r(N,function(r){var e="_."+r[0];t&r[1]&&!o(n,e)&&n.push(e);
}),n.sort()}function $e(n){if(n instanceof Un)return n.clone();var t=new On(n.__wrapped__,n.__chain__);return t.__actions__=Ur(n.__actions__),t.__index__=n.__index__,t.__values__=n.__values__,t}function Fe(n,t,r){var e=null==n?0:n.length;return e?(r=null==r?0:Au(r),0>r&&(r=Li(e+r,0)),_(n,ye(t,3),r)):-1}function Ne(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e-1;return r!==T&&(u=Au(r),u=0>r?Li(e+u,0):Ui(u,e-1)),_(n,ye(t,3),u,true)}function Pe(n){return(null==n?0:n.length)?wt(n,1):[]}function Ze(n){
return n&&n.length?n[0]:T}function qe(n){var t=null==n?0:n.length;return t?n[t-1]:T}function Ve(n,t){return n&&n.length&&t&&t.length?er(n,t):n}function Ke(n){return null==n?n:Ti.call(n)}function Ge(n){if(!n||!n.length)return[];var t=0;return n=i(n,function(n){if(su(n))return t=Li(n.length,t),true}),A(t,function(t){return c(n,b(t))})}function He(t,r){if(!t||!t.length)return[];var e=Ge(t);return null==r?e:c(e,function(t){return n(r,T,t)})}function Je(n){return n=An(n),n.__chain__=true,n}function Ye(n,t){
return t(n)}function Qe(){return this}function Xe(n,t){return(of(n)?r:eo)(n,ye(t,3))}function nu(n,t){return(of(n)?e:uo)(n,ye(t,3))}function tu(n,t){return(of(n)?c:Gt)(n,ye(t,3))}function ru(n,t,r){return t=r?T:t,t=n&&null==t?n.length:t,fe(n,128,T,T,T,T,t)}function eu(n,t){var r;if(typeof t!="function")throw new ni("Expected a function");return n=Au(n),function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=T),r}}function uu(n,t,r){return t=r?T:t,n=fe(n,8,T,T,T,T,T,t),n.placeholder=uu.placeholder,
n}function iu(n,t,r){return t=r?T:t,n=fe(n,16,T,T,T,T,T,t),n.placeholder=iu.placeholder,n}function ou(n,t,r){function e(t){var r=c,e=a;return c=a=T,_=t,s=n.apply(e,r)}function u(n){var r=n-p;return n-=_,p===T||r>=t||0>r||g&&n>=l}function i(){var n=Ko();if(u(n))return o(n);var r,e=yo;r=n-_,n=t-(n-p),r=g?Ui(n,l-r):n,h=e(i,r)}function o(n){return h=T,d&&c?e(n):(c=a=T,s)}function f(){var n=Ko(),r=u(n);if(c=arguments,a=this,p=n,r){if(h===T)return _=n=p,h=yo(i,t),v?e(n):s;if(g)return h=yo(i,t),e(p)}return h===T&&(h=yo(i,t)),
s}var c,a,l,s,h,p,_=0,v=false,g=false,d=true;if(typeof n!="function")throw new ni("Expected a function");return t=ku(t)||0,gu(r)&&(v=!!r.leading,l=(g="maxWait"in r)?Li(ku(r.maxWait)||0,t):l,d="trailing"in r?!!r.trailing:d),f.cancel=function(){h!==T&&ao(h),_=0,c=p=a=h=T},f.flush=function(){return h===T?s:o(Ko())},f}function fu(n,t){function r(){var e=arguments,u=t?t.apply(this,e):e[0],i=r.cache;return i.has(u)?i.get(u):(e=n.apply(this,e),r.cache=i.set(u,e)||i,e)}if(typeof n!="function"||null!=t&&typeof t!="function")throw new ni("Expected a function");
return r.cache=new(fu.Cache||Fn),r}function cu(n){if(typeof n!="function")throw new ni("Expected a function");return function(){var t=arguments;switch(t.length){case 0:return!n.call(this);case 1:return!n.call(this,t[0]);case 2:return!n.call(this,t[0],t[1]);case 3:return!n.call(this,t[0],t[1],t[2])}return!n.apply(this,t)}}function au(n,t){return n===t||n!==n&&t!==t}function lu(n){return null!=n&&vu(n.length)&&!pu(n)}function su(n){return du(n)&&lu(n)}function hu(n){if(!du(n))return false;var t=Ot(n);return"[object Error]"==t||"[object DOMException]"==t||typeof n.message=="string"&&typeof n.name=="string"&&!bu(n);
}function pu(n){return!!gu(n)&&(n=Ot(n),"[object Function]"==n||"[object GeneratorFunction]"==n||"[object AsyncFunction]"==n||"[object Proxy]"==n)}function _u(n){return typeof n=="number"&&n==Au(n)}function vu(n){return typeof n=="number"&&-1<n&&0==n%1&&9007199254740991>=n}function gu(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function du(n){return null!=n&&typeof n=="object"}function yu(n){return typeof n=="number"||du(n)&&"[object Number]"==Ot(n)}function bu(n){return!(!du(n)||"[object Object]"!=Ot(n))&&(n=gi(n),
null===n||(n=ii.call(n,"constructor")&&n.constructor,typeof n=="function"&&n instanceof n&&ui.call(n)==ai))}function xu(n){return typeof n=="string"||!of(n)&&du(n)&&"[object String]"==Ot(n)}function ju(n){return typeof n=="symbol"||du(n)&&"[object Symbol]"==Ot(n)}function wu(n){if(!n)return[];if(lu(n))return xu(n)?M(n):Ur(n);if(ji&&n[ji]){n=n[ji]();for(var t,r=[];!(t=n.next()).done;)r.push(t.value);return r}return t=_o(n),("[object Map]"==t?W:"[object Set]"==t?U:Lu)(n)}function mu(n){return n?(n=ku(n),
n===$||n===-$?1.7976931348623157e308*(0>n?-1:1):n===n?n:0):0===n?n:0}function Au(n){n=mu(n);var t=n%1;return n===n?t?n-t:n:0}function Eu(n){return n?pt(Au(n),0,4294967295):0}function ku(n){if(typeof n=="number")return n;if(ju(n))return F;if(gu(n)&&(n=typeof n.valueOf=="function"?n.valueOf():n,n=gu(n)?n+"":n),typeof n!="string")return 0===n?n:+n;n=n.replace(un,"");var t=gn.test(n);return t||yn.test(n)?Dn(n.slice(2),t?2:8):vn.test(n)?F:+n}function Su(n){return Cr(n,Wu(n))}function Ou(n){return null==n?"":yr(n);
}function Iu(n,t,r){return n=null==n?T:kt(n,t),n===T?r:n}function Ru(n,t){return null!=n&&we(n,t,zt)}function zu(n){return lu(n)?qn(n):Vt(n)}function Wu(n){if(lu(n))n=qn(n,true);else if(gu(n)){var t,r=ze(n),e=[];for(t in n)("constructor"!=t||!r&&ii.call(n,t))&&e.push(t);n=e}else{if(t=[],null!=n)for(r in Yu(n))t.push(r);n=t}return n}function Bu(n,t){if(null==n)return{};var r=c(ve(n),function(n){return[n]});return t=ye(t),tr(n,r,function(n,r){return t(n,r[0])})}function Lu(n){return null==n?[]:S(n,zu(n));
}function Uu(n){return Tf(Ou(n).toLowerCase())}function Cu(n){return(n=Ou(n))&&n.replace(xn,Xn).replace(Sn,"")}function Du(n,t,r){return n=Ou(n),t=r?T:t,t===T?zn.test(n)?n.match(In)||[]:n.match(sn)||[]:n.match(t)||[]}function Mu(n){return function(){return n}}function Tu(n){return n}function $u(n){return qt(typeof n=="function"?n:_t(n,1))}function Fu(n,t,e){var u=zu(t),i=Et(t,u);null!=e||gu(t)&&(i.length||!u.length)||(e=t,t=n,n=this,i=Et(t,zu(t)));var o=!(gu(e)&&"chain"in e&&!e.chain),f=pu(n);return r(i,function(r){
var e=t[r];n[r]=e,f&&(n.prototype[r]=function(){var t=this.__chain__;if(o||t){var r=n(this.__wrapped__);return(r.__actions__=Ur(this.__actions__)).push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,a([this.value()],arguments))})}),n}function Nu(){}function Pu(n){return Ie(n)?b(De(n)):rr(n)}function Zu(){return[]}function qu(){return false}mn=null==mn?$n:rt.defaults($n.Object(),mn,rt.pick($n,Wn));var Vu=mn.Array,Ku=mn.Date,Gu=mn.Error,Hu=mn.Function,Ju=mn.Math,Yu=mn.Object,Qu=mn.RegExp,Xu=mn.String,ni=mn.TypeError,ti=Vu.prototype,ri=Yu.prototype,ei=mn["__core-js_shared__"],ui=Hu.prototype.toString,ii=ri.hasOwnProperty,oi=0,fi=function(){
var n=/[^.]+$/.exec(ei&&ei.keys&&ei.keys.IE_PROTO||"");return n?"Symbol(src)_1."+n:""}(),ci=ri.toString,ai=ui.call(Yu),li=$n._,si=Qu("^"+ui.call(ii).replace(rn,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),hi=Pn?mn.Buffer:T,pi=mn.Symbol,_i=mn.Uint8Array,vi=hi?hi.g:T,gi=B(Yu.getPrototypeOf,Yu),di=Yu.create,yi=ri.propertyIsEnumerable,bi=ti.splice,xi=pi?pi.isConcatSpreadable:T,ji=pi?pi.iterator:T,wi=pi?pi.toStringTag:T,mi=function(){try{var n=je(Yu,"defineProperty");
return n({},"",{}),n}catch(n){}}(),Ai=mn.clearTimeout!==$n.clearTimeout&&mn.clearTimeout,Ei=Ku&&Ku.now!==$n.Date.now&&Ku.now,ki=mn.setTimeout!==$n.setTimeout&&mn.setTimeout,Si=Ju.ceil,Oi=Ju.floor,Ii=Yu.getOwnPropertySymbols,Ri=hi?hi.isBuffer:T,zi=mn.isFinite,Wi=ti.join,Bi=B(Yu.keys,Yu),Li=Ju.max,Ui=Ju.min,Ci=Ku.now,Di=mn.parseInt,Mi=Ju.random,Ti=ti.reverse,$i=je(mn,"DataView"),Fi=je(mn,"Map"),Ni=je(mn,"Promise"),Pi=je(mn,"Set"),Zi=je(mn,"WeakMap"),qi=je(Yu,"create"),Vi=Zi&&new Zi,Ki={},Gi=Me($i),Hi=Me(Fi),Ji=Me(Ni),Yi=Me(Pi),Qi=Me(Zi),Xi=pi?pi.prototype:T,no=Xi?Xi.valueOf:T,to=Xi?Xi.toString:T,ro=function(){
function n(){}return function(t){return gu(t)?di?di(t):(n.prototype=t,t=new n,n.prototype=T,t):{}}}();An.templateSettings={escape:J,evaluate:Y,interpolate:Q,variable:"",imports:{_:An}},An.prototype=En.prototype,An.prototype.constructor=An,On.prototype=ro(En.prototype),On.prototype.constructor=On,Un.prototype=ro(En.prototype),Un.prototype.constructor=Un,Mn.prototype.clear=function(){this.__data__=qi?qi(null):{},this.size=0},Mn.prototype.delete=function(n){return n=this.has(n)&&delete this.__data__[n],
this.size-=n?1:0,n},Mn.prototype.get=function(n){var t=this.__data__;return qi?(n=t[n],"__lodash_hash_undefined__"===n?T:n):ii.call(t,n)?t[n]:T},Mn.prototype.has=function(n){var t=this.__data__;return qi?t[n]!==T:ii.call(t,n)},Mn.prototype.set=function(n,t){var r=this.__data__;return this.size+=this.has(n)?0:1,r[n]=qi&&t===T?"__lodash_hash_undefined__":t,this},Tn.prototype.clear=function(){this.__data__=[],this.size=0},Tn.prototype.delete=function(n){var t=this.__data__;return n=ft(t,n),!(0>n)&&(n==t.length-1?t.pop():bi.call(t,n,1),
--this.size,true)},Tn.prototype.get=function(n){var t=this.__data__;return n=ft(t,n),0>n?T:t[n][1]},Tn.prototype.has=function(n){return-1<ft(this.__data__,n)},Tn.prototype.set=function(n,t){var r=this.__data__,e=ft(r,n);return 0>e?(++this.size,r.push([n,t])):r[e][1]=t,this},Fn.prototype.clear=function(){this.size=0,this.__data__={hash:new Mn,map:new(Fi||Tn),string:new Mn}},Fn.prototype.delete=function(n){return n=be(this,n).delete(n),this.size-=n?1:0,n},Fn.prototype.get=function(n){return be(this,n).get(n);
},Fn.prototype.has=function(n){return be(this,n).has(n)},Fn.prototype.set=function(n,t){var r=be(this,n),e=r.size;return r.set(n,t),this.size+=r.size==e?0:1,this},Nn.prototype.add=Nn.prototype.push=function(n){return this.__data__.set(n,"__lodash_hash_undefined__"),this},Nn.prototype.has=function(n){return this.__data__.has(n)},Zn.prototype.clear=function(){this.__data__=new Tn,this.size=0},Zn.prototype.delete=function(n){var t=this.__data__;return n=t.delete(n),this.size=t.size,n},Zn.prototype.get=function(n){
return this.__data__.get(n)},Zn.prototype.has=function(n){return this.__data__.has(n)},Zn.prototype.set=function(n,t){var r=this.__data__;if(r instanceof Tn){var e=r.__data__;if(!Fi||199>e.length)return e.push([n,t]),this.size=++r.size,this;r=this.__data__=new Fn(e)}return r.set(n,t),this.size=r.size,this};var eo=Fr(mt),uo=Fr(At,true),io=Nr(),oo=Nr(true),fo=Vi?function(n,t){return Vi.set(n,t),n}:Tu,co=mi?function(n,t){return mi(n,"toString",{configurable:true,enumerable:false,value:Mu(t),writable:true})}:Tu,ao=Ai||function(n){
return $n.clearTimeout(n)},lo=Pi&&1/U(new Pi([,-0]))[1]==$?function(n){return new Pi(n)}:Nu,so=Vi?function(n){return Vi.get(n)}:Nu,ho=Ii?function(n){return null==n?[]:(n=Yu(n),i(Ii(n),function(t){return yi.call(n,t)}))}:Zu,po=Ii?function(n){for(var t=[];n;)a(t,ho(n)),n=gi(n);return t}:Zu,_o=Ot;($i&&"[object DataView]"!=_o(new $i(new ArrayBuffer(1)))||Fi&&"[object Map]"!=_o(new Fi)||Ni&&"[object Promise]"!=_o(Ni.resolve())||Pi&&"[object Set]"!=_o(new Pi)||Zi&&"[object WeakMap]"!=_o(new Zi))&&(_o=function(n){
var t=Ot(n);if(n=(n="[object Object]"==t?n.constructor:T)?Me(n):"")switch(n){case Gi:return"[object DataView]";case Hi:return"[object Map]";case Ji:return"[object Promise]";case Yi:return"[object Set]";case Qi:return"[object WeakMap]"}return t});var vo=ei?pu:qu,go=Ue(fo),yo=ki||function(n,t){return $n.setTimeout(n,t)},bo=Ue(co),xo=function(n){n=fu(n,function(n){return 500===t.size&&t.clear(),n});var t=n.cache;return n}(function(n){var t=[];return 46===n.charCodeAt(0)&&t.push(""),n.replace(tn,function(n,r,e,u){
t.push(e?u.replace(hn,"$1"):r||n)}),t}),jo=fr(function(n,t){return su(n)?yt(n,wt(t,1,su,true)):[]}),wo=fr(function(n,t){var r=qe(t);return su(r)&&(r=T),su(n)?yt(n,wt(t,1,su,true),ye(r,2)):[]}),mo=fr(function(n,t){var r=qe(t);return su(r)&&(r=T),su(n)?yt(n,wt(t,1,su,true),T,r):[]}),Ao=fr(function(n){var t=c(n,Er);return t.length&&t[0]===n[0]?Wt(t):[]}),Eo=fr(function(n){var t=qe(n),r=c(n,Er);return t===qe(r)?t=T:r.pop(),r.length&&r[0]===n[0]?Wt(r,ye(t,2)):[]}),ko=fr(function(n){var t=qe(n),r=c(n,Er);return(t=typeof t=="function"?t:T)&&r.pop(),
r.length&&r[0]===n[0]?Wt(r,T,t):[]}),So=fr(Ve),Oo=pe(function(n,t){var r=null==n?0:n.length,e=ht(n,t);return ur(n,c(t,function(n){return Se(n,r)?+n:n}).sort(Wr)),e}),Io=fr(function(n){return br(wt(n,1,su,true))}),Ro=fr(function(n){var t=qe(n);return su(t)&&(t=T),br(wt(n,1,su,true),ye(t,2))}),zo=fr(function(n){var t=qe(n),t=typeof t=="function"?t:T;return br(wt(n,1,su,true),T,t)}),Wo=fr(function(n,t){return su(n)?yt(n,t):[]}),Bo=fr(function(n){return mr(i(n,su))}),Lo=fr(function(n){var t=qe(n);return su(t)&&(t=T),
mr(i(n,su),ye(t,2))}),Uo=fr(function(n){var t=qe(n),t=typeof t=="function"?t:T;return mr(i(n,su),T,t)}),Co=fr(Ge),Do=fr(function(n){var t=n.length,t=1<t?n[t-1]:T,t=typeof t=="function"?(n.pop(),t):T;return He(n,t)}),Mo=pe(function(n){function t(t){return ht(t,n)}var r=n.length,e=r?n[0]:0,u=this.__wrapped__;return!(1<r||this.__actions__.length)&&u instanceof Un&&Se(e)?(u=u.slice(e,+e+(r?1:0)),u.__actions__.push({func:Ye,args:[t],thisArg:T}),new On(u,this.__chain__).thru(function(n){return r&&!n.length&&n.push(T),
n})):this.thru(t)}),To=Tr(function(n,t,r){ii.call(n,r)?++n[r]:st(n,r,1)}),$o=Gr(Fe),Fo=Gr(Ne),No=Tr(function(n,t,r){ii.call(n,r)?n[r].push(t):st(n,r,[t])}),Po=fr(function(t,r,e){var u=-1,i=typeof r=="function",o=lu(t)?Vu(t.length):[];return eo(t,function(t){o[++u]=i?n(r,t,e):Lt(t,r,e)}),o}),Zo=Tr(function(n,t,r){st(n,r,t)}),qo=Tr(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]}),Vo=fr(function(n,t){if(null==n)return[];var r=t.length;return 1<r&&Oe(n,t[0],t[1])?t=[]:2<r&&Oe(t[0],t[1],t[2])&&(t=[t[0]]),
Xt(n,wt(t,1),[])}),Ko=Ei||function(){return $n.Date.now()},Go=fr(function(n,t,r){var e=1;if(r.length)var u=L(r,de(Go)),e=32|e;return fe(n,e,t,r,u)}),Ho=fr(function(n,t,r){var e=3;if(r.length)var u=L(r,de(Ho)),e=32|e;return fe(t,e,n,r,u)}),Jo=fr(function(n,t){return dt(n,1,t)}),Yo=fr(function(n,t,r){return dt(n,ku(t)||0,r)});fu.Cache=Fn;var Qo=fr(function(t,r){r=1==r.length&&of(r[0])?c(r[0],k(ye())):c(wt(r,1),k(ye()));var e=r.length;return fr(function(u){for(var i=-1,o=Ui(u.length,e);++i<o;)u[i]=r[i].call(this,u[i]);
return n(t,this,u)})}),Xo=fr(function(n,t){return fe(n,32,T,t,L(t,de(Xo)))}),nf=fr(function(n,t){return fe(n,64,T,t,L(t,de(nf)))}),tf=pe(function(n,t){return fe(n,256,T,T,T,t)}),rf=ee(It),ef=ee(function(n,t){return n>=t}),uf=Ut(function(){return arguments}())?Ut:function(n){return du(n)&&ii.call(n,"callee")&&!yi.call(n,"callee")},of=Vu.isArray,ff=Vn?k(Vn):Ct,cf=Ri||qu,af=Kn?k(Kn):Dt,lf=Gn?k(Gn):Tt,sf=Hn?k(Hn):Nt,hf=Jn?k(Jn):Pt,pf=Yn?k(Yn):Zt,_f=ee(Kt),vf=ee(function(n,t){return n<=t}),gf=$r(function(n,t){
if(ze(t)||lu(t))Cr(t,zu(t),n);else for(var r in t)ii.call(t,r)&&ot(n,r,t[r])}),df=$r(function(n,t){Cr(t,Wu(t),n)}),yf=$r(function(n,t,r,e){Cr(t,Wu(t),n,e)}),bf=$r(function(n,t,r,e){Cr(t,zu(t),n,e)}),xf=pe(ht),jf=fr(function(n,t){n=Yu(n);var r=-1,e=t.length,u=2<e?t[2]:T;for(u&&Oe(t[0],t[1],u)&&(e=1);++r<e;)for(var u=t[r],i=Wu(u),o=-1,f=i.length;++o<f;){var c=i[o],a=n[c];(a===T||au(a,ri[c])&&!ii.call(n,c))&&(n[c]=u[c])}return n}),wf=fr(function(t){return t.push(T,ae),n(Sf,T,t)}),mf=Yr(function(n,t,r){
null!=t&&typeof t.toString!="function"&&(t=ci.call(t)),n[t]=r},Mu(Tu)),Af=Yr(function(n,t,r){null!=t&&typeof t.toString!="function"&&(t=ci.call(t)),ii.call(n,t)?n[t].push(r):n[t]=[r]},ye),Ef=fr(Lt),kf=$r(function(n,t,r){Yt(n,t,r)}),Sf=$r(function(n,t,r,e){Yt(n,t,r,e)}),Of=pe(function(n,t){var r={};if(null==n)return r;var e=false;t=c(t,function(t){return t=Sr(t,n),e||(e=1<t.length),t}),Cr(n,ve(n),r),e&&(r=_t(r,7,le));for(var u=t.length;u--;)xr(r,t[u]);return r}),If=pe(function(n,t){return null==n?{}:nr(n,t);
}),Rf=oe(zu),zf=oe(Wu),Wf=qr(function(n,t,r){return t=t.toLowerCase(),n+(r?Uu(t):t)}),Bf=qr(function(n,t,r){return n+(r?"-":"")+t.toLowerCase()}),Lf=qr(function(n,t,r){return n+(r?" ":"")+t.toLowerCase()}),Uf=Zr("toLowerCase"),Cf=qr(function(n,t,r){return n+(r?"_":"")+t.toLowerCase()}),Df=qr(function(n,t,r){return n+(r?" ":"")+Tf(t)}),Mf=qr(function(n,t,r){return n+(r?" ":"")+t.toUpperCase()}),Tf=Zr("toUpperCase"),$f=fr(function(t,r){try{return n(t,T,r)}catch(n){return hu(n)?n:new Gu(n)}}),Ff=pe(function(n,t){
return r(t,function(t){t=De(t),st(n,t,Go(n[t],n))}),n}),Nf=Hr(),Pf=Hr(true),Zf=fr(function(n,t){return function(r){return Lt(r,n,t)}}),qf=fr(function(n,t){return function(r){return Lt(n,r,t)}}),Vf=Xr(c),Kf=Xr(u),Gf=Xr(h),Hf=re(),Jf=re(true),Yf=Qr(function(n,t){return n+t},0),Qf=ie("ceil"),Xf=Qr(function(n,t){return n/t},1),nc=ie("floor"),tc=Qr(function(n,t){return n*t},1),rc=ie("round"),ec=Qr(function(n,t){return n-t},0);return An.after=function(n,t){if(typeof t!="function")throw new ni("Expected a function");
return n=Au(n),function(){if(1>--n)return t.apply(this,arguments)}},An.ary=ru,An.assign=gf,An.assignIn=df,An.assignInWith=yf,An.assignWith=bf,An.at=xf,An.before=eu,An.bind=Go,An.bindAll=Ff,An.bindKey=Ho,An.castArray=function(){if(!arguments.length)return[];var n=arguments[0];return of(n)?n:[n]},An.chain=Je,An.chunk=function(n,t,r){if(t=(r?Oe(n,t,r):t===T)?1:Li(Au(t),0),r=null==n?0:n.length,!r||1>t)return[];for(var e=0,u=0,i=Vu(Si(r/t));e<r;)i[u++]=hr(n,e,e+=t);return i},An.compact=function(n){for(var t=-1,r=null==n?0:n.length,e=0,u=[];++t<r;){
var i=n[t];i&&(u[e++]=i)}return u},An.concat=function(){var n=arguments.length;if(!n)return[];for(var t=Vu(n-1),r=arguments[0];n--;)t[n-1]=arguments[n];return a(of(r)?Ur(r):[r],wt(t,1))},An.cond=function(t){var r=null==t?0:t.length,e=ye();return t=r?c(t,function(n){if("function"!=typeof n[1])throw new ni("Expected a function");return[e(n[0]),n[1]]}):[],fr(function(e){for(var u=-1;++u<r;){var i=t[u];if(n(i[0],this,e))return n(i[1],this,e)}})},An.conforms=function(n){return vt(_t(n,1))},An.constant=Mu,
An.countBy=To,An.create=function(n,t){var r=ro(n);return null==t?r:at(r,t)},An.curry=uu,An.curryRight=iu,An.debounce=ou,An.defaults=jf,An.defaultsDeep=wf,An.defer=Jo,An.delay=Yo,An.difference=jo,An.differenceBy=wo,An.differenceWith=mo,An.drop=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:Au(t),hr(n,0>t?0:t,e)):[]},An.dropRight=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:Au(t),t=e-t,hr(n,0,0>t?0:t)):[]},An.dropRightWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),true,true):[];
},An.dropWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),true):[]},An.fill=function(n,t,r,e){var u=null==n?0:n.length;if(!u)return[];for(r&&typeof r!="number"&&Oe(n,t,r)&&(r=0,e=u),u=n.length,r=Au(r),0>r&&(r=-r>u?0:u+r),e=e===T||e>u?u:Au(e),0>e&&(e+=u),e=r>e?0:Eu(e);r<e;)n[r++]=t;return n},An.filter=function(n,t){return(of(n)?i:jt)(n,ye(t,3))},An.flatMap=function(n,t){return wt(tu(n,t),1)},An.flatMapDeep=function(n,t){return wt(tu(n,t),$)},An.flatMapDepth=function(n,t,r){return r=r===T?1:Au(r),
wt(tu(n,t),r)},An.flatten=Pe,An.flattenDeep=function(n){return(null==n?0:n.length)?wt(n,$):[]},An.flattenDepth=function(n,t){return null!=n&&n.length?(t=t===T?1:Au(t),wt(n,t)):[]},An.flip=function(n){return fe(n,512)},An.flow=Nf,An.flowRight=Pf,An.fromPairs=function(n){for(var t=-1,r=null==n?0:n.length,e={};++t<r;){var u=n[t];e[u[0]]=u[1]}return e},An.functions=function(n){return null==n?[]:Et(n,zu(n))},An.functionsIn=function(n){return null==n?[]:Et(n,Wu(n))},An.groupBy=No,An.initial=function(n){
return(null==n?0:n.length)?hr(n,0,-1):[]},An.intersection=Ao,An.intersectionBy=Eo,An.intersectionWith=ko,An.invert=mf,An.invertBy=Af,An.invokeMap=Po,An.iteratee=$u,An.keyBy=Zo,An.keys=zu,An.keysIn=Wu,An.map=tu,An.mapKeys=function(n,t){var r={};return t=ye(t,3),mt(n,function(n,e,u){st(r,t(n,e,u),n)}),r},An.mapValues=function(n,t){var r={};return t=ye(t,3),mt(n,function(n,e,u){st(r,e,t(n,e,u))}),r},An.matches=function(n){return Ht(_t(n,1))},An.matchesProperty=function(n,t){return Jt(n,_t(t,1))},An.memoize=fu,
An.merge=kf,An.mergeWith=Sf,An.method=Zf,An.methodOf=qf,An.mixin=Fu,An.negate=cu,An.nthArg=function(n){return n=Au(n),fr(function(t){return Qt(t,n)})},An.omit=Of,An.omitBy=function(n,t){return Bu(n,cu(ye(t)))},An.once=function(n){return eu(2,n)},An.orderBy=function(n,t,r,e){return null==n?[]:(of(t)||(t=null==t?[]:[t]),r=e?T:r,of(r)||(r=null==r?[]:[r]),Xt(n,t,r))},An.over=Vf,An.overArgs=Qo,An.overEvery=Kf,An.overSome=Gf,An.partial=Xo,An.partialRight=nf,An.partition=qo,An.pick=If,An.pickBy=Bu,An.property=Pu,
An.propertyOf=function(n){return function(t){return null==n?T:kt(n,t)}},An.pull=So,An.pullAll=Ve,An.pullAllBy=function(n,t,r){return n&&n.length&&t&&t.length?er(n,t,ye(r,2)):n},An.pullAllWith=function(n,t,r){return n&&n.length&&t&&t.length?er(n,t,T,r):n},An.pullAt=Oo,An.range=Hf,An.rangeRight=Jf,An.rearg=tf,An.reject=function(n,t){return(of(n)?i:jt)(n,cu(ye(t,3)))},An.remove=function(n,t){var r=[];if(!n||!n.length)return r;var e=-1,u=[],i=n.length;for(t=ye(t,3);++e<i;){var o=n[e];t(o,e,n)&&(r.push(o),
u.push(e))}return ur(n,u),r},An.rest=function(n,t){if(typeof n!="function")throw new ni("Expected a function");return t=t===T?t:Au(t),fr(n,t)},An.reverse=Ke,An.sampleSize=function(n,t,r){return t=(r?Oe(n,t,r):t===T)?1:Au(t),(of(n)?et:ar)(n,t)},An.set=function(n,t,r){return null==n?n:lr(n,t,r)},An.setWith=function(n,t,r,e){return e=typeof e=="function"?e:T,null==n?n:lr(n,t,r,e)},An.shuffle=function(n){return(of(n)?ut:sr)(n)},An.slice=function(n,t,r){var e=null==n?0:n.length;return e?(r&&typeof r!="number"&&Oe(n,t,r)?(t=0,
r=e):(t=null==t?0:Au(t),r=r===T?e:Au(r)),hr(n,t,r)):[]},An.sortBy=Vo,An.sortedUniq=function(n){return n&&n.length?gr(n):[]},An.sortedUniqBy=function(n,t){return n&&n.length?gr(n,ye(t,2)):[]},An.split=function(n,t,r){return r&&typeof r!="number"&&Oe(n,t,r)&&(t=r=T),r=r===T?4294967295:r>>>0,r?(n=Ou(n))&&(typeof t=="string"||null!=t&&!sf(t))&&(t=yr(t),!t&&Rn.test(n))?Or(M(n),0,r):n.split(t,r):[]},An.spread=function(t,r){if(typeof t!="function")throw new ni("Expected a function");return r=null==r?0:Li(Au(r),0),
fr(function(e){var u=e[r];return e=Or(e,0,r),u&&a(e,u),n(t,this,e)})},An.tail=function(n){var t=null==n?0:n.length;return t?hr(n,1,t):[]},An.take=function(n,t,r){return n&&n.length?(t=r||t===T?1:Au(t),hr(n,0,0>t?0:t)):[]},An.takeRight=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:Au(t),t=e-t,hr(n,0>t?0:t,e)):[]},An.takeRightWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),false,true):[]},An.takeWhile=function(n,t){return n&&n.length?jr(n,ye(t,3)):[]},An.tap=function(n,t){return t(n),
n},An.throttle=function(n,t,r){var e=true,u=true;if(typeof n!="function")throw new ni("Expected a function");return gu(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),ou(n,t,{leading:e,maxWait:t,trailing:u})},An.thru=Ye,An.toArray=wu,An.toPairs=Rf,An.toPairsIn=zf,An.toPath=function(n){return of(n)?c(n,De):ju(n)?[n]:Ur(xo(Ou(n)))},An.toPlainObject=Su,An.transform=function(n,t,e){var u=of(n),i=u||cf(n)||pf(n);if(t=ye(t,4),null==e){var o=n&&n.constructor;e=i?u?new o:[]:gu(n)&&pu(o)?ro(gi(n)):{};
}return(i?r:mt)(n,function(n,r,u){return t(e,n,r,u)}),e},An.unary=function(n){return ru(n,1)},An.union=Io,An.unionBy=Ro,An.unionWith=zo,An.uniq=function(n){return n&&n.length?br(n):[]},An.uniqBy=function(n,t){return n&&n.length?br(n,ye(t,2)):[]},An.uniqWith=function(n,t){return t=typeof t=="function"?t:T,n&&n.length?br(n,T,t):[]},An.unset=function(n,t){return null==n||xr(n,t)},An.unzip=Ge,An.unzipWith=He,An.update=function(n,t,r){return null==n?n:lr(n,t,kr(r)(kt(n,t)),void 0)},An.updateWith=function(n,t,r,e){
return e=typeof e=="function"?e:T,null!=n&&(n=lr(n,t,kr(r)(kt(n,t)),e)),n},An.values=Lu,An.valuesIn=function(n){return null==n?[]:S(n,Wu(n))},An.without=Wo,An.words=Du,An.wrap=function(n,t){return Xo(kr(t),n)},An.xor=Bo,An.xorBy=Lo,An.xorWith=Uo,An.zip=Co,An.zipObject=function(n,t){return Ar(n||[],t||[],ot)},An.zipObjectDeep=function(n,t){return Ar(n||[],t||[],lr)},An.zipWith=Do,An.entries=Rf,An.entriesIn=zf,An.extend=df,An.extendWith=yf,Fu(An,An),An.add=Yf,An.attempt=$f,An.camelCase=Wf,An.capitalize=Uu,
An.ceil=Qf,An.clamp=function(n,t,r){return r===T&&(r=t,t=T),r!==T&&(r=ku(r),r=r===r?r:0),t!==T&&(t=ku(t),t=t===t?t:0),pt(ku(n),t,r)},An.clone=function(n){return _t(n,4)},An.cloneDeep=function(n){return _t(n,5)},An.cloneDeepWith=function(n,t){return t=typeof t=="function"?t:T,_t(n,5,t)},An.cloneWith=function(n,t){return t=typeof t=="function"?t:T,_t(n,4,t)},An.conformsTo=function(n,t){return null==t||gt(n,t,zu(t))},An.deburr=Cu,An.defaultTo=function(n,t){return null==n||n!==n?t:n},An.divide=Xf,An.endsWith=function(n,t,r){
n=Ou(n),t=yr(t);var e=n.length,e=r=r===T?e:pt(Au(r),0,e);return r-=t.length,0<=r&&n.slice(r,e)==t},An.eq=au,An.escape=function(n){return(n=Ou(n))&&H.test(n)?n.replace(K,nt):n},An.escapeRegExp=function(n){return(n=Ou(n))&&en.test(n)?n.replace(rn,"\\$&"):n},An.every=function(n,t,r){var e=of(n)?u:bt;return r&&Oe(n,t,r)&&(t=T),e(n,ye(t,3))},An.find=$o,An.findIndex=Fe,An.findKey=function(n,t){return p(n,ye(t,3),mt)},An.findLast=Fo,An.findLastIndex=Ne,An.findLastKey=function(n,t){return p(n,ye(t,3),At);
},An.floor=nc,An.forEach=Xe,An.forEachRight=nu,An.forIn=function(n,t){return null==n?n:io(n,ye(t,3),Wu)},An.forInRight=function(n,t){return null==n?n:oo(n,ye(t,3),Wu)},An.forOwn=function(n,t){return n&&mt(n,ye(t,3))},An.forOwnRight=function(n,t){return n&&At(n,ye(t,3))},An.get=Iu,An.gt=rf,An.gte=ef,An.has=function(n,t){return null!=n&&we(n,t,Rt)},An.hasIn=Ru,An.head=Ze,An.identity=Tu,An.includes=function(n,t,r,e){return n=lu(n)?n:Lu(n),r=r&&!e?Au(r):0,e=n.length,0>r&&(r=Li(e+r,0)),xu(n)?r<=e&&-1<n.indexOf(t,r):!!e&&-1<v(n,t,r);
},An.indexOf=function(n,t,r){var e=null==n?0:n.length;return e?(r=null==r?0:Au(r),0>r&&(r=Li(e+r,0)),v(n,t,r)):-1},An.inRange=function(n,t,r){return t=mu(t),r===T?(r=t,t=0):r=mu(r),n=ku(n),n>=Ui(t,r)&&n<Li(t,r)},An.invoke=Ef,An.isArguments=uf,An.isArray=of,An.isArrayBuffer=ff,An.isArrayLike=lu,An.isArrayLikeObject=su,An.isBoolean=function(n){return true===n||false===n||du(n)&&"[object Boolean]"==Ot(n)},An.isBuffer=cf,An.isDate=af,An.isElement=function(n){return du(n)&&1===n.nodeType&&!bu(n)},An.isEmpty=function(n){
if(null==n)return true;if(lu(n)&&(of(n)||typeof n=="string"||typeof n.splice=="function"||cf(n)||pf(n)||uf(n)))return!n.length;var t=_o(n);if("[object Map]"==t||"[object Set]"==t)return!n.size;if(ze(n))return!Vt(n).length;for(var r in n)if(ii.call(n,r))return false;return true},An.isEqual=function(n,t){return Mt(n,t)},An.isEqualWith=function(n,t,r){var e=(r=typeof r=="function"?r:T)?r(n,t):T;return e===T?Mt(n,t,T,r):!!e},An.isError=hu,An.isFinite=function(n){return typeof n=="number"&&zi(n)},An.isFunction=pu,
An.isInteger=_u,An.isLength=vu,An.isMap=lf,An.isMatch=function(n,t){return n===t||$t(n,t,xe(t))},An.isMatchWith=function(n,t,r){return r=typeof r=="function"?r:T,$t(n,t,xe(t),r)},An.isNaN=function(n){return yu(n)&&n!=+n},An.isNative=function(n){if(vo(n))throw new Gu("Unsupported core-js use. Try https://npms.io/search?q=ponyfill.");return Ft(n)},An.isNil=function(n){return null==n},An.isNull=function(n){return null===n},An.isNumber=yu,An.isObject=gu,An.isObjectLike=du,An.isPlainObject=bu,An.isRegExp=sf,
An.isSafeInteger=function(n){return _u(n)&&-9007199254740991<=n&&9007199254740991>=n},An.isSet=hf,An.isString=xu,An.isSymbol=ju,An.isTypedArray=pf,An.isUndefined=function(n){return n===T},An.isWeakMap=function(n){return du(n)&&"[object WeakMap]"==_o(n)},An.isWeakSet=function(n){return du(n)&&"[object WeakSet]"==Ot(n)},An.join=function(n,t){return null==n?"":Wi.call(n,t)},An.kebabCase=Bf,An.last=qe,An.lastIndexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e;if(r!==T&&(u=Au(r),u=0>u?Li(e+u,0):Ui(u,e-1)),
t===t){for(r=u+1;r--&&n[r]!==t;);n=r}else n=_(n,d,u,true);return n},An.lowerCase=Lf,An.lowerFirst=Uf,An.lt=_f,An.lte=vf,An.max=function(n){return n&&n.length?xt(n,Tu,It):T},An.maxBy=function(n,t){return n&&n.length?xt(n,ye(t,2),It):T},An.mean=function(n){return y(n,Tu)},An.meanBy=function(n,t){return y(n,ye(t,2))},An.min=function(n){return n&&n.length?xt(n,Tu,Kt):T},An.minBy=function(n,t){return n&&n.length?xt(n,ye(t,2),Kt):T},An.stubArray=Zu,An.stubFalse=qu,An.stubObject=function(){return{}},An.stubString=function(){
return""},An.stubTrue=function(){return true},An.multiply=tc,An.nth=function(n,t){return n&&n.length?Qt(n,Au(t)):T},An.noConflict=function(){return $n._===this&&($n._=li),this},An.noop=Nu,An.now=Ko,An.pad=function(n,t,r){n=Ou(n);var e=(t=Au(t))?D(n):0;return!t||e>=t?n:(t=(t-e)/2,ne(Oi(t),r)+n+ne(Si(t),r))},An.padEnd=function(n,t,r){n=Ou(n);var e=(t=Au(t))?D(n):0;return t&&e<t?n+ne(t-e,r):n},An.padStart=function(n,t,r){n=Ou(n);var e=(t=Au(t))?D(n):0;return t&&e<t?ne(t-e,r)+n:n},An.parseInt=function(n,t,r){
return r||null==t?t=0:t&&(t=+t),Di(Ou(n).replace(on,""),t||0)},An.random=function(n,t,r){if(r&&typeof r!="boolean"&&Oe(n,t,r)&&(t=r=T),r===T&&(typeof t=="boolean"?(r=t,t=T):typeof n=="boolean"&&(r=n,n=T)),n===T&&t===T?(n=0,t=1):(n=mu(n),t===T?(t=n,n=0):t=mu(t)),n>t){var e=n;n=t,t=e}return r||n%1||t%1?(r=Mi(),Ui(n+r*(t-n+Cn("1e-"+((r+"").length-1))),t)):ir(n,t)},An.reduce=function(n,t,r){var e=of(n)?l:j,u=3>arguments.length;return e(n,ye(t,4),r,u,eo)},An.reduceRight=function(n,t,r){var e=of(n)?s:j,u=3>arguments.length;
return e(n,ye(t,4),r,u,uo)},An.repeat=function(n,t,r){return t=(r?Oe(n,t,r):t===T)?1:Au(t),or(Ou(n),t)},An.replace=function(){var n=arguments,t=Ou(n[0]);return 3>n.length?t:t.replace(n[1],n[2])},An.result=function(n,t,r){t=Sr(t,n);var e=-1,u=t.length;for(u||(u=1,n=T);++e<u;){var i=null==n?T:n[De(t[e])];i===T&&(e=u,i=r),n=pu(i)?i.call(n):i}return n},An.round=rc,An.runInContext=x,An.sample=function(n){return(of(n)?Qn:cr)(n)},An.size=function(n){if(null==n)return 0;if(lu(n))return xu(n)?D(n):n.length;
var t=_o(n);return"[object Map]"==t||"[object Set]"==t?n.size:Vt(n).length},An.snakeCase=Cf,An.some=function(n,t,r){var e=of(n)?h:pr;return r&&Oe(n,t,r)&&(t=T),e(n,ye(t,3))},An.sortedIndex=function(n,t){return _r(n,t)},An.sortedIndexBy=function(n,t,r){return vr(n,t,ye(r,2))},An.sortedIndexOf=function(n,t){var r=null==n?0:n.length;if(r){var e=_r(n,t);if(e<r&&au(n[e],t))return e}return-1},An.sortedLastIndex=function(n,t){return _r(n,t,true)},An.sortedLastIndexBy=function(n,t,r){return vr(n,t,ye(r,2),true);
},An.sortedLastIndexOf=function(n,t){if(null==n?0:n.length){var r=_r(n,t,true)-1;if(au(n[r],t))return r}return-1},An.startCase=Df,An.startsWith=function(n,t,r){return n=Ou(n),r=null==r?0:pt(Au(r),0,n.length),t=yr(t),n.slice(r,r+t.length)==t},An.subtract=ec,An.sum=function(n){return n&&n.length?m(n,Tu):0},An.sumBy=function(n,t){return n&&n.length?m(n,ye(t,2)):0},An.template=function(n,t,r){var e=An.templateSettings;r&&Oe(n,t,r)&&(t=T),n=Ou(n),t=yf({},t,e,ce),r=yf({},t.imports,e.imports,ce);var u,i,o=zu(r),f=S(r,o),c=0;
r=t.interpolate||jn;var a="__p+='";r=Qu((t.escape||jn).source+"|"+r.source+"|"+(r===Q?pn:jn).source+"|"+(t.evaluate||jn).source+"|$","g");var l="sourceURL"in t?"//# sourceURL="+t.sourceURL+"\n":"";if(n.replace(r,function(t,r,e,o,f,l){return e||(e=o),a+=n.slice(c,l).replace(wn,z),r&&(u=true,a+="'+__e("+r+")+'"),f&&(i=true,a+="';"+f+";\n__p+='"),e&&(a+="'+((__t=("+e+"))==null?'':__t)+'"),c=l+t.length,t}),a+="';",(t=t.variable)||(a="with(obj){"+a+"}"),a=(i?a.replace(P,""):a).replace(Z,"$1").replace(q,"$1;"),
a="function("+(t||"obj")+"){"+(t?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(i?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+a+"return __p}",t=$f(function(){return Hu(o,l+"return "+a).apply(T,f)}),t.source=a,hu(t))throw t;return t},An.times=function(n,t){if(n=Au(n),1>n||9007199254740991<n)return[];var r=4294967295,e=Ui(n,4294967295);for(t=ye(t),n-=4294967295,e=A(e,t);++r<n;)t(r);return e},An.toFinite=mu,An.toInteger=Au,An.toLength=Eu,An.toLower=function(n){
return Ou(n).toLowerCase()},An.toNumber=ku,An.toSafeInteger=function(n){return n?pt(Au(n),-9007199254740991,9007199254740991):0===n?n:0},An.toString=Ou,An.toUpper=function(n){return Ou(n).toUpperCase()},An.trim=function(n,t,r){return(n=Ou(n))&&(r||t===T)?n.replace(un,""):n&&(t=yr(t))?(n=M(n),r=M(t),t=I(n,r),r=R(n,r)+1,Or(n,t,r).join("")):n},An.trimEnd=function(n,t,r){return(n=Ou(n))&&(r||t===T)?n.replace(fn,""):n&&(t=yr(t))?(n=M(n),t=R(n,M(t))+1,Or(n,0,t).join("")):n},An.trimStart=function(n,t,r){
return(n=Ou(n))&&(r||t===T)?n.replace(on,""):n&&(t=yr(t))?(n=M(n),t=I(n,M(t)),Or(n,t).join("")):n},An.truncate=function(n,t){var r=30,e="...";if(gu(t))var u="separator"in t?t.separator:u,r="length"in t?Au(t.length):r,e="omission"in t?yr(t.omission):e;n=Ou(n);var i=n.length;if(Rn.test(n))var o=M(n),i=o.length;if(r>=i)return n;if(i=r-D(e),1>i)return e;if(r=o?Or(o,0,i).join(""):n.slice(0,i),u===T)return r+e;if(o&&(i+=r.length-i),sf(u)){if(n.slice(i).search(u)){var f=r;for(u.global||(u=Qu(u.source,Ou(_n.exec(u))+"g")),
u.lastIndex=0;o=u.exec(f);)var c=o.index;r=r.slice(0,c===T?i:c)}}else n.indexOf(yr(u),i)!=i&&(u=r.lastIndexOf(u),-1<u&&(r=r.slice(0,u)));return r+e},An.unescape=function(n){return(n=Ou(n))&&G.test(n)?n.replace(V,tt):n},An.uniqueId=function(n){var t=++oi;return Ou(n)+t},An.upperCase=Mf,An.upperFirst=Tf,An.each=Xe,An.eachRight=nu,An.first=Ze,Fu(An,function(){var n={};return mt(An,function(t,r){ii.call(An.prototype,r)||(n[r]=t)}),n}(),{chain:false}),An.VERSION="4.17.10",r("bind bindKey curry curryRight partial partialRight".split(" "),function(n){
An[n].placeholder=An}),r(["drop","take"],function(n,t){Un.prototype[n]=function(r){r=r===T?1:Li(Au(r),0);var e=this.__filtered__&&!t?new Un(this):this.clone();return e.__filtered__?e.__takeCount__=Ui(r,e.__takeCount__):e.__views__.push({size:Ui(r,4294967295),type:n+(0>e.__dir__?"Right":"")}),e},Un.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}}),r(["filter","map","takeWhile"],function(n,t){var r=t+1,e=1==r||3==r;Un.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({
iteratee:ye(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}}),r(["head","last"],function(n,t){var r="take"+(t?"Right":"");Un.prototype[n]=function(){return this[r](1).value()[0]}}),r(["initial","tail"],function(n,t){var r="drop"+(t?"":"Right");Un.prototype[n]=function(){return this.__filtered__?new Un(this):this[r](1)}}),Un.prototype.compact=function(){return this.filter(Tu)},Un.prototype.find=function(n){return this.filter(n).head()},Un.prototype.findLast=function(n){return this.reverse().find(n);
},Un.prototype.invokeMap=fr(function(n,t){return typeof n=="function"?new Un(this):this.map(function(r){return Lt(r,n,t)})}),Un.prototype.reject=function(n){return this.filter(cu(ye(n)))},Un.prototype.slice=function(n,t){n=Au(n);var r=this;return r.__filtered__&&(0<n||0>t)?new Un(r):(0>n?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==T&&(t=Au(t),r=0>t?r.dropRight(-t):r.take(t-n)),r)},Un.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},Un.prototype.toArray=function(){return this.take(4294967295);
},mt(Un.prototype,function(n,t){var r=/^(?:filter|find|map|reject)|While$/.test(t),e=/^(?:head|last)$/.test(t),u=An[e?"take"+("last"==t?"Right":""):t],i=e||/^find/.test(t);u&&(An.prototype[t]=function(){function t(n){return n=u.apply(An,a([n],f)),e&&h?n[0]:n}var o=this.__wrapped__,f=e?[1]:arguments,c=o instanceof Un,l=f[0],s=c||of(o);s&&r&&typeof l=="function"&&1!=l.length&&(c=s=false);var h=this.__chain__,p=!!this.__actions__.length,l=i&&!h,c=c&&!p;return!i&&s?(o=c?o:new Un(this),o=n.apply(o,f),o.__actions__.push({
func:Ye,args:[t],thisArg:T}),new On(o,h)):l&&c?n.apply(this,f):(o=this.thru(t),l?e?o.value()[0]:o.value():o)})}),r("pop push shift sort splice unshift".split(" "),function(n){var t=ti[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|shift)$/.test(n);An.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(of(u)?u:[],n)}return this[r](function(r){return t.apply(of(r)?r:[],n)})}}),mt(Un.prototype,function(n,t){var r=An[t];if(r){var e=r.name+"";
(Ki[e]||(Ki[e]=[])).push({name:t,func:r})}}),Ki[Jr(T,2).name]=[{name:"wrapper",func:T}],Un.prototype.clone=function(){var n=new Un(this.__wrapped__);return n.__actions__=Ur(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=Ur(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=Ur(this.__views__),n},Un.prototype.reverse=function(){if(this.__filtered__){var n=new Un(this);n.__dir__=-1,n.__filtered__=true}else n=this.clone(),n.__dir__*=-1;return n;
},Un.prototype.value=function(){var n,t=this.__wrapped__.value(),r=this.__dir__,e=of(t),u=0>r,i=e?t.length:0;n=i;for(var o=this.__views__,f=0,c=-1,a=o.length;++c<a;){var l=o[c],s=l.size;switch(l.type){case"drop":f+=s;break;case"dropRight":n-=s;break;case"take":n=Ui(n,f+s);break;case"takeRight":f=Li(f,n-s)}}if(n={start:f,end:n},o=n.start,f=n.end,n=f-o,o=u?f:o-1,f=this.__iteratees__,c=f.length,a=0,l=Ui(n,this.__takeCount__),!e||!u&&i==n&&l==n)return wr(t,this.__actions__);e=[];n:for(;n--&&a<l;){for(o+=r,
u=-1,i=t[o];++u<c;){var h=f[u],s=h.type,h=(0,h.iteratee)(i);if(2==s)i=h;else if(!h){if(1==s)continue n;break n}}e[a++]=i}return e},An.prototype.at=Mo,An.prototype.chain=function(){return Je(this)},An.prototype.commit=function(){return new On(this.value(),this.__chain__)},An.prototype.next=function(){this.__values__===T&&(this.__values__=wu(this.value()));var n=this.__index__>=this.__values__.length;return{done:n,value:n?T:this.__values__[this.__index__++]}},An.prototype.plant=function(n){for(var t,r=this;r instanceof En;){
var e=$e(r);e.__index__=0,e.__values__=T,t?u.__wrapped__=e:t=e;var u=e,r=r.__wrapped__}return u.__wrapped__=n,t},An.prototype.reverse=function(){var n=this.__wrapped__;return n instanceof Un?(this.__actions__.length&&(n=new Un(this)),n=n.reverse(),n.__actions__.push({func:Ye,args:[Ke],thisArg:T}),new On(n,this.__chain__)):this.thru(Ke)},An.prototype.toJSON=An.prototype.valueOf=An.prototype.value=function(){return wr(this.__wrapped__,this.__actions__)},An.prototype.first=An.prototype.head,ji&&(An.prototype[ji]=Qe),
An}();typeof define=="function"&&typeof define.amd=="object"&&define.amd?($n._=rt, define(function(){return rt})):Nn?((Nn.exports=rt)._=rt,Fn._=rt):$n._=rt}).call(this);
;
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.moment=t()}(this,function(){"use strict";var e,i;function c(){return e.apply(null,arguments)}function o(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function u(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function l(e){return void 0===e}function d(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function h(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function f(e,t){var n,s=[];for(n=0;n<e.length;++n)s.push(t(e[n],n));return s}function m(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function _(e,t){for(var n in t)m(t,n)&&(e[n]=t[n]);return m(t,"toString")&&(e.toString=t.toString),m(t,"valueOf")&&(e.valueOf=t.valueOf),e}function y(e,t,n,s){return Ot(e,t,n,s,!0).utc()}function g(e){return null==e._pf&&(e._pf={empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null,rfc2822:!1,weekdayMismatch:!1}),e._pf}function p(e){if(null==e._isValid){var t=g(e),n=i.call(t.parsedDateParts,function(e){return null!=e}),s=!isNaN(e._d.getTime())&&t.overflow<0&&!t.empty&&!t.invalidMonth&&!t.invalidWeekday&&!t.weekdayMismatch&&!t.nullInput&&!t.invalidFormat&&!t.userInvalidated&&(!t.meridiem||t.meridiem&&n);if(e._strict&&(s=s&&0===t.charsLeftOver&&0===t.unusedTokens.length&&void 0===t.bigHour),null!=Object.isFrozen&&Object.isFrozen(e))return s;e._isValid=s}return e._isValid}function v(e){var t=y(NaN);return null!=e?_(g(t),e):g(t).userInvalidated=!0,t}i=Array.prototype.some?Array.prototype.some:function(e){for(var t=Object(this),n=t.length>>>0,s=0;s<n;s++)if(s in t&&e.call(this,t[s],s,t))return!0;return!1};var r=c.momentProperties=[];function w(e,t){var n,s,i;if(l(t._isAMomentObject)||(e._isAMomentObject=t._isAMomentObject),l(t._i)||(e._i=t._i),l(t._f)||(e._f=t._f),l(t._l)||(e._l=t._l),l(t._strict)||(e._strict=t._strict),l(t._tzm)||(e._tzm=t._tzm),l(t._isUTC)||(e._isUTC=t._isUTC),l(t._offset)||(e._offset=t._offset),l(t._pf)||(e._pf=g(t)),l(t._locale)||(e._locale=t._locale),0<r.length)for(n=0;n<r.length;n++)l(i=t[s=r[n]])||(e[s]=i);return e}var t=!1;function M(e){w(this,e),this._d=new Date(null!=e._d?e._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===t&&(t=!0,c.updateOffset(this),t=!1)}function S(e){return e instanceof M||null!=e&&null!=e._isAMomentObject}function D(e){return e<0?Math.ceil(e)||0:Math.floor(e)}function k(e){var t=+e,n=0;return 0!==t&&isFinite(t)&&(n=D(t)),n}function a(e,t,n){var s,i=Math.min(e.length,t.length),r=Math.abs(e.length-t.length),a=0;for(s=0;s<i;s++)(n&&e[s]!==t[s]||!n&&k(e[s])!==k(t[s]))&&a++;return a+r}function Y(e){!1===c.suppressDeprecationWarnings&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+e)}function n(i,r){var a=!0;return _(function(){if(null!=c.deprecationHandler&&c.deprecationHandler(null,i),a){for(var e,t=[],n=0;n<arguments.length;n++){if(e="","object"==typeof arguments[n]){for(var s in e+="\n["+n+"] ",arguments[0])e+=s+": "+arguments[0][s]+", ";e=e.slice(0,-2)}else e=arguments[n];t.push(e)}Y(i+"\nArguments: "+Array.prototype.slice.call(t).join("")+"\n"+(new Error).stack),a=!1}return r.apply(this,arguments)},r)}var s,O={};function T(e,t){null!=c.deprecationHandler&&c.deprecationHandler(e,t),O[e]||(Y(t),O[e]=!0)}function x(e){return e instanceof Function||"[object Function]"===Object.prototype.toString.call(e)}function b(e,t){var n,s=_({},e);for(n in t)m(t,n)&&(u(e[n])&&u(t[n])?(s[n]={},_(s[n],e[n]),_(s[n],t[n])):null!=t[n]?s[n]=t[n]:delete s[n]);for(n in e)m(e,n)&&!m(t,n)&&u(e[n])&&(s[n]=_({},s[n]));return s}function P(e){null!=e&&this.set(e)}c.suppressDeprecationWarnings=!1,c.deprecationHandler=null,s=Object.keys?Object.keys:function(e){var t,n=[];for(t in e)m(e,t)&&n.push(t);return n};var W={};function H(e,t){var n=e.toLowerCase();W[n]=W[n+"s"]=W[t]=e}function R(e){return"string"==typeof e?W[e]||W[e.toLowerCase()]:void 0}function C(e){var t,n,s={};for(n in e)m(e,n)&&(t=R(n))&&(s[t]=e[n]);return s}var F={};function L(e,t){F[e]=t}function U(e,t,n){var s=""+Math.abs(e),i=t-s.length;return(0<=e?n?"+":"":"-")+Math.pow(10,Math.max(0,i)).toString().substr(1)+s}var N=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,G=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,V={},E={};function I(e,t,n,s){var i=s;"string"==typeof s&&(i=function(){return this[s]()}),e&&(E[e]=i),t&&(E[t[0]]=function(){return U(i.apply(this,arguments),t[1],t[2])}),n&&(E[n]=function(){return this.localeData().ordinal(i.apply(this,arguments),e)})}function A(e,t){return e.isValid()?(t=j(t,e.localeData()),V[t]=V[t]||function(s){var e,i,t,r=s.match(N);for(e=0,i=r.length;e<i;e++)E[r[e]]?r[e]=E[r[e]]:r[e]=(t=r[e]).match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"");return function(e){var t,n="";for(t=0;t<i;t++)n+=x(r[t])?r[t].call(e,s):r[t];return n}}(t),V[t](e)):e.localeData().invalidDate()}function j(e,t){var n=5;function s(e){return t.longDateFormat(e)||e}for(G.lastIndex=0;0<=n&&G.test(e);)e=e.replace(G,s),G.lastIndex=0,n-=1;return e}var Z=/\d/,z=/\d\d/,$=/\d{3}/,q=/\d{4}/,J=/[+-]?\d{6}/,B=/\d\d?/,Q=/\d\d\d\d?/,X=/\d\d\d\d\d\d?/,K=/\d{1,3}/,ee=/\d{1,4}/,te=/[+-]?\d{1,6}/,ne=/\d+/,se=/[+-]?\d+/,ie=/Z|[+-]\d\d:?\d\d/gi,re=/Z|[+-]\d\d(?::?\d\d)?/gi,ae=/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,oe={};function ue(e,n,s){oe[e]=x(n)?n:function(e,t){return e&&s?s:n}}function le(e,t){return m(oe,e)?oe[e](t._strict,t._locale):new RegExp(de(e.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(e,t,n,s,i){return t||n||s||i})))}function de(e){return e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}var he={};function ce(e,n){var t,s=n;for("string"==typeof e&&(e=[e]),d(n)&&(s=function(e,t){t[n]=k(e)}),t=0;t<e.length;t++)he[e[t]]=s}function fe(e,i){ce(e,function(e,t,n,s){n._w=n._w||{},i(e,n._w,n,s)})}var me=0,_e=1,ye=2,ge=3,pe=4,ve=5,we=6,Me=7,Se=8;function De(e){return ke(e)?366:365}function ke(e){return e%4==0&&e%100!=0||e%400==0}I("Y",0,0,function(){var e=this.year();return e<=9999?""+e:"+"+e}),I(0,["YY",2],0,function(){return this.year()%100}),I(0,["YYYY",4],0,"year"),I(0,["YYYYY",5],0,"year"),I(0,["YYYYYY",6,!0],0,"year"),H("year","y"),L("year",1),ue("Y",se),ue("YY",B,z),ue("YYYY",ee,q),ue("YYYYY",te,J),ue("YYYYYY",te,J),ce(["YYYYY","YYYYYY"],me),ce("YYYY",function(e,t){t[me]=2===e.length?c.parseTwoDigitYear(e):k(e)}),ce("YY",function(e,t){t[me]=c.parseTwoDigitYear(e)}),ce("Y",function(e,t){t[me]=parseInt(e,10)}),c.parseTwoDigitYear=function(e){return k(e)+(68<k(e)?1900:2e3)};var Ye,Oe=Te("FullYear",!0);function Te(t,n){return function(e){return null!=e?(be(this,t,e),c.updateOffset(this,n),this):xe(this,t)}}function xe(e,t){return e.isValid()?e._d["get"+(e._isUTC?"UTC":"")+t]():NaN}function be(e,t,n){e.isValid()&&!isNaN(n)&&("FullYear"===t&&ke(e.year())&&1===e.month()&&29===e.date()?e._d["set"+(e._isUTC?"UTC":"")+t](n,e.month(),Pe(n,e.month())):e._d["set"+(e._isUTC?"UTC":"")+t](n))}function Pe(e,t){if(isNaN(e)||isNaN(t))return NaN;var n,s=(t%(n=12)+n)%n;return e+=(t-s)/12,1===s?ke(e)?29:28:31-s%7%2}Ye=Array.prototype.indexOf?Array.prototype.indexOf:function(e){var t;for(t=0;t<this.length;++t)if(this[t]===e)return t;return-1},I("M",["MM",2],"Mo",function(){return this.month()+1}),I("MMM",0,0,function(e){return this.localeData().monthsShort(this,e)}),I("MMMM",0,0,function(e){return this.localeData().months(this,e)}),H("month","M"),L("month",8),ue("M",B),ue("MM",B,z),ue("MMM",function(e,t){return t.monthsShortRegex(e)}),ue("MMMM",function(e,t){return t.monthsRegex(e)}),ce(["M","MM"],function(e,t){t[_e]=k(e)-1}),ce(["MMM","MMMM"],function(e,t,n,s){var i=n._locale.monthsParse(e,s,n._strict);null!=i?t[_e]=i:g(n).invalidMonth=e});var We=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,He="January_February_March_April_May_June_July_August_September_October_November_December".split("_");var Re="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_");function Ce(e,t){var n;if(!e.isValid())return e;if("string"==typeof t)if(/^\d+$/.test(t))t=k(t);else if(!d(t=e.localeData().monthsParse(t)))return e;return n=Math.min(e.date(),Pe(e.year(),t)),e._d["set"+(e._isUTC?"UTC":"")+"Month"](t,n),e}function Fe(e){return null!=e?(Ce(this,e),c.updateOffset(this,!0),this):xe(this,"Month")}var Le=ae;var Ue=ae;function Ne(){function e(e,t){return t.length-e.length}var t,n,s=[],i=[],r=[];for(t=0;t<12;t++)n=y([2e3,t]),s.push(this.monthsShort(n,"")),i.push(this.months(n,"")),r.push(this.months(n,"")),r.push(this.monthsShort(n,""));for(s.sort(e),i.sort(e),r.sort(e),t=0;t<12;t++)s[t]=de(s[t]),i[t]=de(i[t]);for(t=0;t<24;t++)r[t]=de(r[t]);this._monthsRegex=new RegExp("^("+r.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+s.join("|")+")","i")}function Ge(e){var t=new Date(Date.UTC.apply(null,arguments));return e<100&&0<=e&&isFinite(t.getUTCFullYear())&&t.setUTCFullYear(e),t}function Ve(e,t,n){var s=7+t-n;return-((7+Ge(e,0,s).getUTCDay()-t)%7)+s-1}function Ee(e,t,n,s,i){var r,a,o=1+7*(t-1)+(7+n-s)%7+Ve(e,s,i);return o<=0?a=De(r=e-1)+o:o>De(e)?(r=e+1,a=o-De(e)):(r=e,a=o),{year:r,dayOfYear:a}}function Ie(e,t,n){var s,i,r=Ve(e.year(),t,n),a=Math.floor((e.dayOfYear()-r-1)/7)+1;return a<1?s=a+Ae(i=e.year()-1,t,n):a>Ae(e.year(),t,n)?(s=a-Ae(e.year(),t,n),i=e.year()+1):(i=e.year(),s=a),{week:s,year:i}}function Ae(e,t,n){var s=Ve(e,t,n),i=Ve(e+1,t,n);return(De(e)-s+i)/7}I("w",["ww",2],"wo","week"),I("W",["WW",2],"Wo","isoWeek"),H("week","w"),H("isoWeek","W"),L("week",5),L("isoWeek",5),ue("w",B),ue("ww",B,z),ue("W",B),ue("WW",B,z),fe(["w","ww","W","WW"],function(e,t,n,s){t[s.substr(0,1)]=k(e)});I("d",0,"do","day"),I("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),I("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),I("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),I("e",0,0,"weekday"),I("E",0,0,"isoWeekday"),H("day","d"),H("weekday","e"),H("isoWeekday","E"),L("day",11),L("weekday",11),L("isoWeekday",11),ue("d",B),ue("e",B),ue("E",B),ue("dd",function(e,t){return t.weekdaysMinRegex(e)}),ue("ddd",function(e,t){return t.weekdaysShortRegex(e)}),ue("dddd",function(e,t){return t.weekdaysRegex(e)}),fe(["dd","ddd","dddd"],function(e,t,n,s){var i=n._locale.weekdaysParse(e,s,n._strict);null!=i?t.d=i:g(n).invalidWeekday=e}),fe(["d","e","E"],function(e,t,n,s){t[s]=k(e)});var je="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_");var Ze="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_");var ze="Su_Mo_Tu_We_Th_Fr_Sa".split("_");var $e=ae;var qe=ae;var Je=ae;function Be(){function e(e,t){return t.length-e.length}var t,n,s,i,r,a=[],o=[],u=[],l=[];for(t=0;t<7;t++)n=y([2e3,1]).day(t),s=this.weekdaysMin(n,""),i=this.weekdaysShort(n,""),r=this.weekdays(n,""),a.push(s),o.push(i),u.push(r),l.push(s),l.push(i),l.push(r);for(a.sort(e),o.sort(e),u.sort(e),l.sort(e),t=0;t<7;t++)o[t]=de(o[t]),u[t]=de(u[t]),l[t]=de(l[t]);this._weekdaysRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+a.join("|")+")","i")}function Qe(){return this.hours()%12||12}function Xe(e,t){I(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}function Ke(e,t){return t._meridiemParse}I("H",["HH",2],0,"hour"),I("h",["hh",2],0,Qe),I("k",["kk",2],0,function(){return this.hours()||24}),I("hmm",0,0,function(){return""+Qe.apply(this)+U(this.minutes(),2)}),I("hmmss",0,0,function(){return""+Qe.apply(this)+U(this.minutes(),2)+U(this.seconds(),2)}),I("Hmm",0,0,function(){return""+this.hours()+U(this.minutes(),2)}),I("Hmmss",0,0,function(){return""+this.hours()+U(this.minutes(),2)+U(this.seconds(),2)}),Xe("a",!0),Xe("A",!1),H("hour","h"),L("hour",13),ue("a",Ke),ue("A",Ke),ue("H",B),ue("h",B),ue("k",B),ue("HH",B,z),ue("hh",B,z),ue("kk",B,z),ue("hmm",Q),ue("hmmss",X),ue("Hmm",Q),ue("Hmmss",X),ce(["H","HH"],ge),ce(["k","kk"],function(e,t,n){var s=k(e);t[ge]=24===s?0:s}),ce(["a","A"],function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e}),ce(["h","hh"],function(e,t,n){t[ge]=k(e),g(n).bigHour=!0}),ce("hmm",function(e,t,n){var s=e.length-2;t[ge]=k(e.substr(0,s)),t[pe]=k(e.substr(s)),g(n).bigHour=!0}),ce("hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=k(e.substr(0,s)),t[pe]=k(e.substr(s,2)),t[ve]=k(e.substr(i)),g(n).bigHour=!0}),ce("Hmm",function(e,t,n){var s=e.length-2;t[ge]=k(e.substr(0,s)),t[pe]=k(e.substr(s))}),ce("Hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=k(e.substr(0,s)),t[pe]=k(e.substr(s,2)),t[ve]=k(e.substr(i))});var et,tt=Te("Hours",!0),nt={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:He,monthsShort:Re,week:{dow:0,doy:6},weekdays:je,weekdaysMin:ze,weekdaysShort:Ze,meridiemParse:/[ap]\.?m?\.?/i},st={},it={};function rt(e){return e?e.toLowerCase().replace("_","-"):e}function at(e){var t=null;if(!st[e]&&"undefined"!=typeof module&&module&&module.exports)try{t=et._abbr,require("./locale/"+e),ot(t)}catch(e){}return st[e]}function ot(e,t){var n;return e&&((n=l(t)?lt(e):ut(e,t))?et=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),et._abbr}function ut(e,t){if(null!==t){var n,s=nt;if(t.abbr=e,null!=st[e])T("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=st[e]._config;else if(null!=t.parentLocale)if(null!=st[t.parentLocale])s=st[t.parentLocale]._config;else{if(null==(n=at(t.parentLocale)))return it[t.parentLocale]||(it[t.parentLocale]=[]),it[t.parentLocale].push({name:e,config:t}),null;s=n._config}return st[e]=new P(b(s,t)),it[e]&&it[e].forEach(function(e){ut(e.name,e.config)}),ot(e),st[e]}return delete st[e],null}function lt(e){var t;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return et;if(!o(e)){if(t=at(e))return t;e=[e]}return function(e){for(var t,n,s,i,r=0;r<e.length;){for(t=(i=rt(e[r]).split("-")).length,n=(n=rt(e[r+1]))?n.split("-"):null;0<t;){if(s=at(i.slice(0,t).join("-")))return s;if(n&&n.length>=t&&a(i,n,!0)>=t-1)break;t--}r++}return et}(e)}function dt(e){var t,n=e._a;return n&&-2===g(e).overflow&&(t=n[_e]<0||11<n[_e]?_e:n[ye]<1||n[ye]>Pe(n[me],n[_e])?ye:n[ge]<0||24<n[ge]||24===n[ge]&&(0!==n[pe]||0!==n[ve]||0!==n[we])?ge:n[pe]<0||59<n[pe]?pe:n[ve]<0||59<n[ve]?ve:n[we]<0||999<n[we]?we:-1,g(e)._overflowDayOfYear&&(t<me||ye<t)&&(t=ye),g(e)._overflowWeeks&&-1===t&&(t=Me),g(e)._overflowWeekday&&-1===t&&(t=Se),g(e).overflow=t),e}function ht(e,t,n){return null!=e?e:null!=t?t:n}function ct(e){var t,n,s,i,r,a=[];if(!e._d){var o,u;for(o=e,u=new Date(c.now()),s=o._useUTC?[u.getUTCFullYear(),u.getUTCMonth(),u.getUTCDate()]:[u.getFullYear(),u.getMonth(),u.getDate()],e._w&&null==e._a[ye]&&null==e._a[_e]&&function(e){var t,n,s,i,r,a,o,u;if(null!=(t=e._w).GG||null!=t.W||null!=t.E)r=1,a=4,n=ht(t.GG,e._a[me],Ie(Tt(),1,4).year),s=ht(t.W,1),((i=ht(t.E,1))<1||7<i)&&(u=!0);else{r=e._locale._week.dow,a=e._locale._week.doy;var l=Ie(Tt(),r,a);n=ht(t.gg,e._a[me],l.year),s=ht(t.w,l.week),null!=t.d?((i=t.d)<0||6<i)&&(u=!0):null!=t.e?(i=t.e+r,(t.e<0||6<t.e)&&(u=!0)):i=r}s<1||s>Ae(n,r,a)?g(e)._overflowWeeks=!0:null!=u?g(e)._overflowWeekday=!0:(o=Ee(n,s,i,r,a),e._a[me]=o.year,e._dayOfYear=o.dayOfYear)}(e),null!=e._dayOfYear&&(r=ht(e._a[me],s[me]),(e._dayOfYear>De(r)||0===e._dayOfYear)&&(g(e)._overflowDayOfYear=!0),n=Ge(r,0,e._dayOfYear),e._a[_e]=n.getUTCMonth(),e._a[ye]=n.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=a[t]=s[t];for(;t<7;t++)e._a[t]=a[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[ge]&&0===e._a[pe]&&0===e._a[ve]&&0===e._a[we]&&(e._nextDay=!0,e._a[ge]=0),e._d=(e._useUTC?Ge:function(e,t,n,s,i,r,a){var o=new Date(e,t,n,s,i,r,a);return e<100&&0<=e&&isFinite(o.getFullYear())&&o.setFullYear(e),o}).apply(null,a),i=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[ge]=24),e._w&&void 0!==e._w.d&&e._w.d!==i&&(g(e).weekdayMismatch=!0)}}var ft=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,mt=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,_t=/Z|[+-]\d\d(?::?\d\d)?/,yt=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],gt=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],pt=/^\/?Date\((\-?\d+)/i;function vt(e){var t,n,s,i,r,a,o=e._i,u=ft.exec(o)||mt.exec(o);if(u){for(g(e).iso=!0,t=0,n=yt.length;t<n;t++)if(yt[t][1].exec(u[1])){i=yt[t][0],s=!1!==yt[t][2];break}if(null==i)return void(e._isValid=!1);if(u[3]){for(t=0,n=gt.length;t<n;t++)if(gt[t][1].exec(u[3])){r=(u[2]||" ")+gt[t][0];break}if(null==r)return void(e._isValid=!1)}if(!s&&null!=r)return void(e._isValid=!1);if(u[4]){if(!_t.exec(u[4]))return void(e._isValid=!1);a="Z"}e._f=i+(r||"")+(a||""),kt(e)}else e._isValid=!1}var wt=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;function Mt(e,t,n,s,i,r){var a=[function(e){var t=parseInt(e,10);{if(t<=49)return 2e3+t;if(t<=999)return 1900+t}return t}(e),Re.indexOf(t),parseInt(n,10),parseInt(s,10),parseInt(i,10)];return r&&a.push(parseInt(r,10)),a}var St={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function Dt(e){var t,n,s,i=wt.exec(e._i.replace(/\([^)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").replace(/^\s\s*/,"").replace(/\s\s*$/,""));if(i){var r=Mt(i[4],i[3],i[2],i[5],i[6],i[7]);if(t=i[1],n=r,s=e,t&&Ze.indexOf(t)!==new Date(n[0],n[1],n[2]).getDay()&&(g(s).weekdayMismatch=!0,!(s._isValid=!1)))return;e._a=r,e._tzm=function(e,t,n){if(e)return St[e];if(t)return 0;var s=parseInt(n,10),i=s%100;return(s-i)/100*60+i}(i[8],i[9],i[10]),e._d=Ge.apply(null,e._a),e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),g(e).rfc2822=!0}else e._isValid=!1}function kt(e){if(e._f!==c.ISO_8601)if(e._f!==c.RFC_2822){e._a=[],g(e).empty=!0;var t,n,s,i,r,a,o,u,l=""+e._i,d=l.length,h=0;for(s=j(e._f,e._locale).match(N)||[],t=0;t<s.length;t++)i=s[t],(n=(l.match(le(i,e))||[])[0])&&(0<(r=l.substr(0,l.indexOf(n))).length&&g(e).unusedInput.push(r),l=l.slice(l.indexOf(n)+n.length),h+=n.length),E[i]?(n?g(e).empty=!1:g(e).unusedTokens.push(i),a=i,u=e,null!=(o=n)&&m(he,a)&&he[a](o,u._a,u,a)):e._strict&&!n&&g(e).unusedTokens.push(i);g(e).charsLeftOver=d-h,0<l.length&&g(e).unusedInput.push(l),e._a[ge]<=12&&!0===g(e).bigHour&&0<e._a[ge]&&(g(e).bigHour=void 0),g(e).parsedDateParts=e._a.slice(0),g(e).meridiem=e._meridiem,e._a[ge]=function(e,t,n){var s;if(null==n)return t;return null!=e.meridiemHour?e.meridiemHour(t,n):(null!=e.isPM&&((s=e.isPM(n))&&t<12&&(t+=12),s||12!==t||(t=0)),t)}(e._locale,e._a[ge],e._meridiem),ct(e),dt(e)}else Dt(e);else vt(e)}function Yt(e){var t,n,s,i,r=e._i,a=e._f;return e._locale=e._locale||lt(e._l),null===r||void 0===a&&""===r?v({nullInput:!0}):("string"==typeof r&&(e._i=r=e._locale.preparse(r)),S(r)?new M(dt(r)):(h(r)?e._d=r:o(a)?function(e){var t,n,s,i,r;if(0===e._f.length)return g(e).invalidFormat=!0,e._d=new Date(NaN);for(i=0;i<e._f.length;i++)r=0,t=w({},e),null!=e._useUTC&&(t._useUTC=e._useUTC),t._f=e._f[i],kt(t),p(t)&&(r+=g(t).charsLeftOver,r+=10*g(t).unusedTokens.length,g(t).score=r,(null==s||r<s)&&(s=r,n=t));_(e,n||t)}(e):a?kt(e):l(n=(t=e)._i)?t._d=new Date(c.now()):h(n)?t._d=new Date(n.valueOf()):"string"==typeof n?(s=t,null===(i=pt.exec(s._i))?(vt(s),!1===s._isValid&&(delete s._isValid,Dt(s),!1===s._isValid&&(delete s._isValid,c.createFromInputFallback(s)))):s._d=new Date(+i[1])):o(n)?(t._a=f(n.slice(0),function(e){return parseInt(e,10)}),ct(t)):u(n)?function(e){if(!e._d){var t=C(e._i);e._a=f([t.year,t.month,t.day||t.date,t.hour,t.minute,t.second,t.millisecond],function(e){return e&&parseInt(e,10)}),ct(e)}}(t):d(n)?t._d=new Date(n):c.createFromInputFallback(t),p(e)||(e._d=null),e))}function Ot(e,t,n,s,i){var r,a={};return!0!==n&&!1!==n||(s=n,n=void 0),(u(e)&&function(e){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(e).length;var t;for(t in e)if(e.hasOwnProperty(t))return!1;return!0}(e)||o(e)&&0===e.length)&&(e=void 0),a._isAMomentObject=!0,a._useUTC=a._isUTC=i,a._l=n,a._i=e,a._f=t,a._strict=s,(r=new M(dt(Yt(a))))._nextDay&&(r.add(1,"d"),r._nextDay=void 0),r}function Tt(e,t,n,s){return Ot(e,t,n,s,!1)}c.createFromInputFallback=n("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(e){e._d=new Date(e._i+(e._useUTC?" UTC":""))}),c.ISO_8601=function(){},c.RFC_2822=function(){};var xt=n("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=Tt.apply(null,arguments);return this.isValid()&&e.isValid()?e<this?this:e:v()}),bt=n("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=Tt.apply(null,arguments);return this.isValid()&&e.isValid()?this<e?this:e:v()});function Pt(e,t){var n,s;if(1===t.length&&o(t[0])&&(t=t[0]),!t.length)return Tt();for(n=t[0],s=1;s<t.length;++s)t[s].isValid()&&!t[s][e](n)||(n=t[s]);return n}var Wt=["year","quarter","month","week","day","hour","minute","second","millisecond"];function Ht(e){var t=C(e),n=t.year||0,s=t.quarter||0,i=t.month||0,r=t.week||0,a=t.day||0,o=t.hour||0,u=t.minute||0,l=t.second||0,d=t.millisecond||0;this._isValid=function(e){for(var t in e)if(-1===Ye.call(Wt,t)||null!=e[t]&&isNaN(e[t]))return!1;for(var n=!1,s=0;s<Wt.length;++s)if(e[Wt[s]]){if(n)return!1;parseFloat(e[Wt[s]])!==k(e[Wt[s]])&&(n=!0)}return!0}(t),this._milliseconds=+d+1e3*l+6e4*u+1e3*o*60*60,this._days=+a+7*r,this._months=+i+3*s+12*n,this._data={},this._locale=lt(),this._bubble()}function Rt(e){return e instanceof Ht}function Ct(e){return e<0?-1*Math.round(-1*e):Math.round(e)}function Ft(e,n){I(e,0,0,function(){var e=this.utcOffset(),t="+";return e<0&&(e=-e,t="-"),t+U(~~(e/60),2)+n+U(~~e%60,2)})}Ft("Z",":"),Ft("ZZ",""),ue("Z",re),ue("ZZ",re),ce(["Z","ZZ"],function(e,t,n){n._useUTC=!0,n._tzm=Ut(re,e)});var Lt=/([\+\-]|\d\d)/gi;function Ut(e,t){var n=(t||"").match(e);if(null===n)return null;var s=((n[n.length-1]||[])+"").match(Lt)||["-",0,0],i=60*s[1]+k(s[2]);return 0===i?0:"+"===s[0]?i:-i}function Nt(e,t){var n,s;return t._isUTC?(n=t.clone(),s=(S(e)||h(e)?e.valueOf():Tt(e).valueOf())-n.valueOf(),n._d.setTime(n._d.valueOf()+s),c.updateOffset(n,!1),n):Tt(e).local()}function Gt(e){return 15*-Math.round(e._d.getTimezoneOffset()/15)}function Vt(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}c.updateOffset=function(){};var Et=/^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,It=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function At(e,t){var n,s,i,r=e,a=null;return Rt(e)?r={ms:e._milliseconds,d:e._days,M:e._months}:d(e)?(r={},t?r[t]=e:r.milliseconds=e):(a=Et.exec(e))?(n="-"===a[1]?-1:1,r={y:0,d:k(a[ye])*n,h:k(a[ge])*n,m:k(a[pe])*n,s:k(a[ve])*n,ms:k(Ct(1e3*a[we]))*n}):(a=It.exec(e))?(n="-"===a[1]?-1:(a[1],1),r={y:jt(a[2],n),M:jt(a[3],n),w:jt(a[4],n),d:jt(a[5],n),h:jt(a[6],n),m:jt(a[7],n),s:jt(a[8],n)}):null==r?r={}:"object"==typeof r&&("from"in r||"to"in r)&&(i=function(e,t){var n;if(!e.isValid()||!t.isValid())return{milliseconds:0,months:0};t=Nt(t,e),e.isBefore(t)?n=Zt(e,t):((n=Zt(t,e)).milliseconds=-n.milliseconds,n.months=-n.months);return n}(Tt(r.from),Tt(r.to)),(r={}).ms=i.milliseconds,r.M=i.months),s=new Ht(r),Rt(e)&&m(e,"_locale")&&(s._locale=e._locale),s}function jt(e,t){var n=e&&parseFloat(e.replace(",","."));return(isNaN(n)?0:n)*t}function Zt(e,t){var n={milliseconds:0,months:0};return n.months=t.month()-e.month()+12*(t.year()-e.year()),e.clone().add(n.months,"M").isAfter(t)&&--n.months,n.milliseconds=+t-+e.clone().add(n.months,"M"),n}function zt(s,i){return function(e,t){var n;return null===t||isNaN(+t)||(T(i,"moment()."+i+"(period, number) is deprecated. Please use moment()."+i+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),n=e,e=t,t=n),$t(this,At(e="string"==typeof e?+e:e,t),s),this}}function $t(e,t,n,s){var i=t._milliseconds,r=Ct(t._days),a=Ct(t._months);e.isValid()&&(s=null==s||s,a&&Ce(e,xe(e,"Month")+a*n),r&&be(e,"Date",xe(e,"Date")+r*n),i&&e._d.setTime(e._d.valueOf()+i*n),s&&c.updateOffset(e,r||a))}At.fn=Ht.prototype,At.invalid=function(){return At(NaN)};var qt=zt(1,"add"),Jt=zt(-1,"subtract");function Bt(e,t){var n=12*(t.year()-e.year())+(t.month()-e.month()),s=e.clone().add(n,"months");return-(n+(t-s<0?(t-s)/(s-e.clone().add(n-1,"months")):(t-s)/(e.clone().add(n+1,"months")-s)))||0}function Qt(e){var t;return void 0===e?this._locale._abbr:(null!=(t=lt(e))&&(this._locale=t),this)}c.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",c.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Xt=n("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(e){return void 0===e?this.localeData():this.locale(e)});function Kt(){return this._locale}function en(e,t){I(0,[e,e.length],0,t)}function tn(e,t,n,s,i){var r;return null==e?Ie(this,s,i).year:((r=Ae(e,s,i))<t&&(t=r),function(e,t,n,s,i){var r=Ee(e,t,n,s,i),a=Ge(r.year,0,r.dayOfYear);return this.year(a.getUTCFullYear()),this.month(a.getUTCMonth()),this.date(a.getUTCDate()),this}.call(this,e,t,n,s,i))}I(0,["gg",2],0,function(){return this.weekYear()%100}),I(0,["GG",2],0,function(){return this.isoWeekYear()%100}),en("gggg","weekYear"),en("ggggg","weekYear"),en("GGGG","isoWeekYear"),en("GGGGG","isoWeekYear"),H("weekYear","gg"),H("isoWeekYear","GG"),L("weekYear",1),L("isoWeekYear",1),ue("G",se),ue("g",se),ue("GG",B,z),ue("gg",B,z),ue("GGGG",ee,q),ue("gggg",ee,q),ue("GGGGG",te,J),ue("ggggg",te,J),fe(["gggg","ggggg","GGGG","GGGGG"],function(e,t,n,s){t[s.substr(0,2)]=k(e)}),fe(["gg","GG"],function(e,t,n,s){t[s]=c.parseTwoDigitYear(e)}),I("Q",0,"Qo","quarter"),H("quarter","Q"),L("quarter",7),ue("Q",Z),ce("Q",function(e,t){t[_e]=3*(k(e)-1)}),I("D",["DD",2],"Do","date"),H("date","D"),L("date",9),ue("D",B),ue("DD",B,z),ue("Do",function(e,t){return e?t._dayOfMonthOrdinalParse||t._ordinalParse:t._dayOfMonthOrdinalParseLenient}),ce(["D","DD"],ye),ce("Do",function(e,t){t[ye]=k(e.match(B)[0])});var nn=Te("Date",!0);I("DDD",["DDDD",3],"DDDo","dayOfYear"),H("dayOfYear","DDD"),L("dayOfYear",4),ue("DDD",K),ue("DDDD",$),ce(["DDD","DDDD"],function(e,t,n){n._dayOfYear=k(e)}),I("m",["mm",2],0,"minute"),H("minute","m"),L("minute",14),ue("m",B),ue("mm",B,z),ce(["m","mm"],pe);var sn=Te("Minutes",!1);I("s",["ss",2],0,"second"),H("second","s"),L("second",15),ue("s",B),ue("ss",B,z),ce(["s","ss"],ve);var rn,an=Te("Seconds",!1);for(I("S",0,0,function(){return~~(this.millisecond()/100)}),I(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),I(0,["SSS",3],0,"millisecond"),I(0,["SSSS",4],0,function(){return 10*this.millisecond()}),I(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),I(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),I(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),I(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),I(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),H("millisecond","ms"),L("millisecond",16),ue("S",K,Z),ue("SS",K,z),ue("SSS",K,$),rn="SSSS";rn.length<=9;rn+="S")ue(rn,ne);function on(e,t){t[we]=k(1e3*("0."+e))}for(rn="S";rn.length<=9;rn+="S")ce(rn,on);var un=Te("Milliseconds",!1);I("z",0,0,"zoneAbbr"),I("zz",0,0,"zoneName");var ln=M.prototype;function dn(e){return e}ln.add=qt,ln.calendar=function(e,t){var n=e||Tt(),s=Nt(n,this).startOf("day"),i=c.calendarFormat(this,s)||"sameElse",r=t&&(x(t[i])?t[i].call(this,n):t[i]);return this.format(r||this.localeData().calendar(i,this,Tt(n)))},ln.clone=function(){return new M(this)},ln.diff=function(e,t,n){var s,i,r;if(!this.isValid())return NaN;if(!(s=Nt(e,this)).isValid())return NaN;switch(i=6e4*(s.utcOffset()-this.utcOffset()),t=R(t)){case"year":r=Bt(this,s)/12;break;case"month":r=Bt(this,s);break;case"quarter":r=Bt(this,s)/3;break;case"second":r=(this-s)/1e3;break;case"minute":r=(this-s)/6e4;break;case"hour":r=(this-s)/36e5;break;case"day":r=(this-s-i)/864e5;break;case"week":r=(this-s-i)/6048e5;break;default:r=this-s}return n?r:D(r)},ln.endOf=function(e){return void 0===(e=R(e))||"millisecond"===e?this:("date"===e&&(e="day"),this.startOf(e).add(1,"isoWeek"===e?"week":e).subtract(1,"ms"))},ln.format=function(e){e||(e=this.isUtc()?c.defaultFormatUtc:c.defaultFormat);var t=A(this,e);return this.localeData().postformat(t)},ln.from=function(e,t){return this.isValid()&&(S(e)&&e.isValid()||Tt(e).isValid())?At({to:this,from:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},ln.fromNow=function(e){return this.from(Tt(),e)},ln.to=function(e,t){return this.isValid()&&(S(e)&&e.isValid()||Tt(e).isValid())?At({from:this,to:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},ln.toNow=function(e){return this.to(Tt(),e)},ln.get=function(e){return x(this[e=R(e)])?this[e]():this},ln.invalidAt=function(){return g(this).overflow},ln.isAfter=function(e,t){var n=S(e)?e:Tt(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=R(l(t)?"millisecond":t))?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(t).valueOf())},ln.isBefore=function(e,t){var n=S(e)?e:Tt(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=R(l(t)?"millisecond":t))?this.valueOf()<n.valueOf():this.clone().endOf(t).valueOf()<n.valueOf())},ln.isBetween=function(e,t,n,s){return("("===(s=s||"()")[0]?this.isAfter(e,n):!this.isBefore(e,n))&&(")"===s[1]?this.isBefore(t,n):!this.isAfter(t,n))},ln.isSame=function(e,t){var n,s=S(e)?e:Tt(e);return!(!this.isValid()||!s.isValid())&&("millisecond"===(t=R(t||"millisecond"))?this.valueOf()===s.valueOf():(n=s.valueOf(),this.clone().startOf(t).valueOf()<=n&&n<=this.clone().endOf(t).valueOf()))},ln.isSameOrAfter=function(e,t){return this.isSame(e,t)||this.isAfter(e,t)},ln.isSameOrBefore=function(e,t){return this.isSame(e,t)||this.isBefore(e,t)},ln.isValid=function(){return p(this)},ln.lang=Xt,ln.locale=Qt,ln.localeData=Kt,ln.max=bt,ln.min=xt,ln.parsingFlags=function(){return _({},g(this))},ln.set=function(e,t){if("object"==typeof e)for(var n=function(e){var t=[];for(var n in e)t.push({unit:n,priority:F[n]});return t.sort(function(e,t){return e.priority-t.priority}),t}(e=C(e)),s=0;s<n.length;s++)this[n[s].unit](e[n[s].unit]);else if(x(this[e=R(e)]))return this[e](t);return this},ln.startOf=function(e){switch(e=R(e)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":case"date":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===e&&this.weekday(0),"isoWeek"===e&&this.isoWeekday(1),"quarter"===e&&this.month(3*Math.floor(this.month()/3)),this},ln.subtract=Jt,ln.toArray=function(){var e=this;return[e.year(),e.month(),e.date(),e.hour(),e.minute(),e.second(),e.millisecond()]},ln.toObject=function(){var e=this;return{years:e.year(),months:e.month(),date:e.date(),hours:e.hours(),minutes:e.minutes(),seconds:e.seconds(),milliseconds:e.milliseconds()}},ln.toDate=function(){return new Date(this.valueOf())},ln.toISOString=function(e){if(!this.isValid())return null;var t=!0!==e,n=t?this.clone().utc():this;return n.year()<0||9999<n.year()?A(n,t?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):x(Date.prototype.toISOString)?t?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",A(n,"Z")):A(n,t?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")},ln.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var e="moment",t="";this.isLocal()||(e=0===this.utcOffset()?"moment.utc":"moment.parseZone",t="Z");var n="["+e+'("]',s=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",i=t+'[")]';return this.format(n+s+"-MM-DD[T]HH:mm:ss.SSS"+i)},ln.toJSON=function(){return this.isValid()?this.toISOString():null},ln.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},ln.unix=function(){return Math.floor(this.valueOf()/1e3)},ln.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},ln.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},ln.year=Oe,ln.isLeapYear=function(){return ke(this.year())},ln.weekYear=function(e){return tn.call(this,e,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},ln.isoWeekYear=function(e){return tn.call(this,e,this.isoWeek(),this.isoWeekday(),1,4)},ln.quarter=ln.quarters=function(e){return null==e?Math.ceil((this.month()+1)/3):this.month(3*(e-1)+this.month()%3)},ln.month=Fe,ln.daysInMonth=function(){return Pe(this.year(),this.month())},ln.week=ln.weeks=function(e){var t=this.localeData().week(this);return null==e?t:this.add(7*(e-t),"d")},ln.isoWeek=ln.isoWeeks=function(e){var t=Ie(this,1,4).week;return null==e?t:this.add(7*(e-t),"d")},ln.weeksInYear=function(){var e=this.localeData()._week;return Ae(this.year(),e.dow,e.doy)},ln.isoWeeksInYear=function(){return Ae(this.year(),1,4)},ln.date=nn,ln.day=ln.days=function(e){if(!this.isValid())return null!=e?this:NaN;var t,n,s=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=e?(t=e,n=this.localeData(),e="string"!=typeof t?t:isNaN(t)?"number"==typeof(t=n.weekdaysParse(t))?t:null:parseInt(t,10),this.add(e-s,"d")):s},ln.weekday=function(e){if(!this.isValid())return null!=e?this:NaN;var t=(this.day()+7-this.localeData()._week.dow)%7;return null==e?t:this.add(e-t,"d")},ln.isoWeekday=function(e){if(!this.isValid())return null!=e?this:NaN;if(null!=e){var t=(n=e,s=this.localeData(),"string"==typeof n?s.weekdaysParse(n)%7||7:isNaN(n)?null:n);return this.day(this.day()%7?t:t-7)}return this.day()||7;var n,s},ln.dayOfYear=function(e){var t=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==e?t:this.add(e-t,"d")},ln.hour=ln.hours=tt,ln.minute=ln.minutes=sn,ln.second=ln.seconds=an,ln.millisecond=ln.milliseconds=un,ln.utcOffset=function(e,t,n){var s,i=this._offset||0;if(!this.isValid())return null!=e?this:NaN;if(null!=e){if("string"==typeof e){if(null===(e=Ut(re,e)))return this}else Math.abs(e)<16&&!n&&(e*=60);return!this._isUTC&&t&&(s=Gt(this)),this._offset=e,this._isUTC=!0,null!=s&&this.add(s,"m"),i!==e&&(!t||this._changeInProgress?$t(this,At(e-i,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,c.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?i:Gt(this)},ln.utc=function(e){return this.utcOffset(0,e)},ln.local=function(e){return this._isUTC&&(this.utcOffset(0,e),this._isUTC=!1,e&&this.subtract(Gt(this),"m")),this},ln.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var e=Ut(ie,this._i);null!=e?this.utcOffset(e):this.utcOffset(0,!0)}return this},ln.hasAlignedHourOffset=function(e){return!!this.isValid()&&(e=e?Tt(e).utcOffset():0,(this.utcOffset()-e)%60==0)},ln.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},ln.isLocal=function(){return!!this.isValid()&&!this._isUTC},ln.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},ln.isUtc=Vt,ln.isUTC=Vt,ln.zoneAbbr=function(){return this._isUTC?"UTC":""},ln.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},ln.dates=n("dates accessor is deprecated. Use date instead.",nn),ln.months=n("months accessor is deprecated. Use month instead",Fe),ln.years=n("years accessor is deprecated. Use year instead",Oe),ln.zone=n("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,t){return null!=e?("string"!=typeof e&&(e=-e),this.utcOffset(e,t),this):-this.utcOffset()}),ln.isDSTShifted=n("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!l(this._isDSTShifted))return this._isDSTShifted;var e={};if(w(e,this),(e=Yt(e))._a){var t=e._isUTC?y(e._a):Tt(e._a);this._isDSTShifted=this.isValid()&&0<a(e._a,t.toArray())}else this._isDSTShifted=!1;return this._isDSTShifted});var hn=P.prototype;function cn(e,t,n,s){var i=lt(),r=y().set(s,t);return i[n](r,e)}function fn(e,t,n){if(d(e)&&(t=e,e=void 0),e=e||"",null!=t)return cn(e,t,n,"month");var s,i=[];for(s=0;s<12;s++)i[s]=cn(e,s,n,"month");return i}function mn(e,t,n,s){"boolean"==typeof e?d(t)&&(n=t,t=void 0):(t=e,e=!1,d(n=t)&&(n=t,t=void 0)),t=t||"";var i,r=lt(),a=e?r._week.dow:0;if(null!=n)return cn(t,(n+a)%7,s,"day");var o=[];for(i=0;i<7;i++)o[i]=cn(t,(i+a)%7,s,"day");return o}hn.calendar=function(e,t,n){var s=this._calendar[e]||this._calendar.sameElse;return x(s)?s.call(t,n):s},hn.longDateFormat=function(e){var t=this._longDateFormat[e],n=this._longDateFormat[e.toUpperCase()];return t||!n?t:(this._longDateFormat[e]=n.replace(/MMMM|MM|DD|dddd/g,function(e){return e.slice(1)}),this._longDateFormat[e])},hn.invalidDate=function(){return this._invalidDate},hn.ordinal=function(e){return this._ordinal.replace("%d",e)},hn.preparse=dn,hn.postformat=dn,hn.relativeTime=function(e,t,n,s){var i=this._relativeTime[n];return x(i)?i(e,t,n,s):i.replace(/%d/i,e)},hn.pastFuture=function(e,t){var n=this._relativeTime[0<e?"future":"past"];return x(n)?n(t):n.replace(/%s/i,t)},hn.set=function(e){var t,n;for(n in e)x(t=e[n])?this[n]=t:this["_"+n]=t;this._config=e,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},hn.months=function(e,t){return e?o(this._months)?this._months[e.month()]:this._months[(this._months.isFormat||We).test(t)?"format":"standalone"][e.month()]:o(this._months)?this._months:this._months.standalone},hn.monthsShort=function(e,t){return e?o(this._monthsShort)?this._monthsShort[e.month()]:this._monthsShort[We.test(t)?"format":"standalone"][e.month()]:o(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},hn.monthsParse=function(e,t,n){var s,i,r;if(this._monthsParseExact)return function(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],s=0;s<12;++s)r=y([2e3,s]),this._shortMonthsParse[s]=this.monthsShort(r,"").toLocaleLowerCase(),this._longMonthsParse[s]=this.months(r,"").toLocaleLowerCase();return n?"MMM"===t?-1!==(i=Ye.call(this._shortMonthsParse,a))?i:null:-1!==(i=Ye.call(this._longMonthsParse,a))?i:null:"MMM"===t?-1!==(i=Ye.call(this._shortMonthsParse,a))?i:-1!==(i=Ye.call(this._longMonthsParse,a))?i:null:-1!==(i=Ye.call(this._longMonthsParse,a))?i:-1!==(i=Ye.call(this._shortMonthsParse,a))?i:null}.call(this,e,t,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),s=0;s<12;s++){if(i=y([2e3,s]),n&&!this._longMonthsParse[s]&&(this._longMonthsParse[s]=new RegExp("^"+this.months(i,"").replace(".","")+"$","i"),this._shortMonthsParse[s]=new RegExp("^"+this.monthsShort(i,"").replace(".","")+"$","i")),n||this._monthsParse[s]||(r="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[s]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===t&&this._longMonthsParse[s].test(e))return s;if(n&&"MMM"===t&&this._shortMonthsParse[s].test(e))return s;if(!n&&this._monthsParse[s].test(e))return s}},hn.monthsRegex=function(e){return this._monthsParseExact?(m(this,"_monthsRegex")||Ne.call(this),e?this._monthsStrictRegex:this._monthsRegex):(m(this,"_monthsRegex")||(this._monthsRegex=Ue),this._monthsStrictRegex&&e?this._monthsStrictRegex:this._monthsRegex)},hn.monthsShortRegex=function(e){return this._monthsParseExact?(m(this,"_monthsRegex")||Ne.call(this),e?this._monthsShortStrictRegex:this._monthsShortRegex):(m(this,"_monthsShortRegex")||(this._monthsShortRegex=Le),this._monthsShortStrictRegex&&e?this._monthsShortStrictRegex:this._monthsShortRegex)},hn.week=function(e){return Ie(e,this._week.dow,this._week.doy).week},hn.firstDayOfYear=function(){return this._week.doy},hn.firstDayOfWeek=function(){return this._week.dow},hn.weekdays=function(e,t){return e?o(this._weekdays)?this._weekdays[e.day()]:this._weekdays[this._weekdays.isFormat.test(t)?"format":"standalone"][e.day()]:o(this._weekdays)?this._weekdays:this._weekdays.standalone},hn.weekdaysMin=function(e){return e?this._weekdaysMin[e.day()]:this._weekdaysMin},hn.weekdaysShort=function(e){return e?this._weekdaysShort[e.day()]:this._weekdaysShort},hn.weekdaysParse=function(e,t,n){var s,i,r;if(this._weekdaysParseExact)return function(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],s=0;s<7;++s)r=y([2e3,1]).day(s),this._minWeekdaysParse[s]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[s]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[s]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===t?-1!==(i=Ye.call(this._weekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:null:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:"dddd"===t?-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:null}.call(this,e,t,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),s=0;s<7;s++){if(i=y([2e3,1]).day(s),n&&!this._fullWeekdaysParse[s]&&(this._fullWeekdaysParse[s]=new RegExp("^"+this.weekdays(i,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[s]=new RegExp("^"+this.weekdaysShort(i,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[s]=new RegExp("^"+this.weekdaysMin(i,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[s]||(r="^"+this.weekdays(i,"")+"|^"+this.weekdaysShort(i,"")+"|^"+this.weekdaysMin(i,""),this._weekdaysParse[s]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===t&&this._fullWeekdaysParse[s].test(e))return s;if(n&&"ddd"===t&&this._shortWeekdaysParse[s].test(e))return s;if(n&&"dd"===t&&this._minWeekdaysParse[s].test(e))return s;if(!n&&this._weekdaysParse[s].test(e))return s}},hn.weekdaysRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Be.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(m(this,"_weekdaysRegex")||(this._weekdaysRegex=$e),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)},hn.weekdaysShortRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Be.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(m(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=qe),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},hn.weekdaysMinRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Be.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(m(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Je),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},hn.isPM=function(e){return"p"===(e+"").toLowerCase().charAt(0)},hn.meridiem=function(e,t,n){return 11<e?n?"pm":"PM":n?"am":"AM"},ot("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var t=e%10;return e+(1===k(e%100/10)?"th":1===t?"st":2===t?"nd":3===t?"rd":"th")}}),c.lang=n("moment.lang is deprecated. Use moment.locale instead.",ot),c.langData=n("moment.langData is deprecated. Use moment.localeData instead.",lt);var _n=Math.abs;function yn(e,t,n,s){var i=At(t,n);return e._milliseconds+=s*i._milliseconds,e._days+=s*i._days,e._months+=s*i._months,e._bubble()}function gn(e){return e<0?Math.floor(e):Math.ceil(e)}function pn(e){return 4800*e/146097}function vn(e){return 146097*e/4800}function wn(e){return function(){return this.as(e)}}var Mn=wn("ms"),Sn=wn("s"),Dn=wn("m"),kn=wn("h"),Yn=wn("d"),On=wn("w"),Tn=wn("M"),xn=wn("y");function bn(e){return function(){return this.isValid()?this._data[e]:NaN}}var Pn=bn("milliseconds"),Wn=bn("seconds"),Hn=bn("minutes"),Rn=bn("hours"),Cn=bn("days"),Fn=bn("months"),Ln=bn("years");var Un=Math.round,Nn={ss:44,s:45,m:45,h:22,d:26,M:11};var Gn=Math.abs;function Vn(e){return(0<e)-(e<0)||+e}function En(){if(!this.isValid())return this.localeData().invalidDate();var e,t,n=Gn(this._milliseconds)/1e3,s=Gn(this._days),i=Gn(this._months);t=D((e=D(n/60))/60),n%=60,e%=60;var r=D(i/12),a=i%=12,o=s,u=t,l=e,d=n?n.toFixed(3).replace(/\.?0+$/,""):"",h=this.asSeconds();if(!h)return"P0D";var c=h<0?"-":"",f=Vn(this._months)!==Vn(h)?"-":"",m=Vn(this._days)!==Vn(h)?"-":"",_=Vn(this._milliseconds)!==Vn(h)?"-":"";return c+"P"+(r?f+r+"Y":"")+(a?f+a+"M":"")+(o?m+o+"D":"")+(u||l||d?"T":"")+(u?_+u+"H":"")+(l?_+l+"M":"")+(d?_+d+"S":"")}var In=Ht.prototype;return In.isValid=function(){return this._isValid},In.abs=function(){var e=this._data;return this._milliseconds=_n(this._milliseconds),this._days=_n(this._days),this._months=_n(this._months),e.milliseconds=_n(e.milliseconds),e.seconds=_n(e.seconds),e.minutes=_n(e.minutes),e.hours=_n(e.hours),e.months=_n(e.months),e.years=_n(e.years),this},In.add=function(e,t){return yn(this,e,t,1)},In.subtract=function(e,t){return yn(this,e,t,-1)},In.as=function(e){if(!this.isValid())return NaN;var t,n,s=this._milliseconds;if("month"===(e=R(e))||"year"===e)return t=this._days+s/864e5,n=this._months+pn(t),"month"===e?n:n/12;switch(t=this._days+Math.round(vn(this._months)),e){case"week":return t/7+s/6048e5;case"day":return t+s/864e5;case"hour":return 24*t+s/36e5;case"minute":return 1440*t+s/6e4;case"second":return 86400*t+s/1e3;case"millisecond":return Math.floor(864e5*t)+s;default:throw new Error("Unknown unit "+e)}},In.asMilliseconds=Mn,In.asSeconds=Sn,In.asMinutes=Dn,In.asHours=kn,In.asDays=Yn,In.asWeeks=On,In.asMonths=Tn,In.asYears=xn,In.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*k(this._months/12):NaN},In._bubble=function(){var e,t,n,s,i,r=this._milliseconds,a=this._days,o=this._months,u=this._data;return 0<=r&&0<=a&&0<=o||r<=0&&a<=0&&o<=0||(r+=864e5*gn(vn(o)+a),o=a=0),u.milliseconds=r%1e3,e=D(r/1e3),u.seconds=e%60,t=D(e/60),u.minutes=t%60,n=D(t/60),u.hours=n%24,o+=i=D(pn(a+=D(n/24))),a-=gn(vn(i)),s=D(o/12),o%=12,u.days=a,u.months=o,u.years=s,this},In.clone=function(){return At(this)},In.get=function(e){return e=R(e),this.isValid()?this[e+"s"]():NaN},In.milliseconds=Pn,In.seconds=Wn,In.minutes=Hn,In.hours=Rn,In.days=Cn,In.weeks=function(){return D(this.days()/7)},In.months=Fn,In.years=Ln,In.humanize=function(e){if(!this.isValid())return this.localeData().invalidDate();var t,n,s,i,r,a,o,u,l,d,h,c=this.localeData(),f=(n=!e,s=c,i=At(t=this).abs(),r=Un(i.as("s")),a=Un(i.as("m")),o=Un(i.as("h")),u=Un(i.as("d")),l=Un(i.as("M")),d=Un(i.as("y")),(h=r<=Nn.ss&&["s",r]||r<Nn.s&&["ss",r]||a<=1&&["m"]||a<Nn.m&&["mm",a]||o<=1&&["h"]||o<Nn.h&&["hh",o]||u<=1&&["d"]||u<Nn.d&&["dd",u]||l<=1&&["M"]||l<Nn.M&&["MM",l]||d<=1&&["y"]||["yy",d])[2]=n,h[3]=0<+t,h[4]=s,function(e,t,n,s,i){return i.relativeTime(t||1,!!n,e,s)}.apply(null,h));return e&&(f=c.pastFuture(+this,f)),c.postformat(f)},In.toISOString=En,In.toString=En,In.toJSON=En,In.locale=Qt,In.localeData=Kt,In.toIsoString=n("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",En),In.lang=Xt,I("X",0,0,"unix"),I("x",0,0,"valueOf"),ue("x",se),ue("X",/[+-]?\d+(\.\d{1,3})?/),ce("X",function(e,t,n){n._d=new Date(1e3*parseFloat(e,10))}),ce("x",function(e,t,n){n._d=new Date(k(e))}),c.version="2.22.2",e=Tt,c.fn=ln,c.min=function(){return Pt("isBefore",[].slice.call(arguments,0))},c.max=function(){return Pt("isAfter",[].slice.call(arguments,0))},c.now=function(){return Date.now?Date.now():+new Date},c.utc=y,c.unix=function(e){return Tt(1e3*e)},c.months=function(e,t){return fn(e,t,"months")},c.isDate=h,c.locale=ot,c.invalid=v,c.duration=At,c.isMoment=S,c.weekdays=function(e,t,n){return mn(e,t,n,"weekdays")},c.parseZone=function(){return Tt.apply(null,arguments).parseZone()},c.localeData=lt,c.isDuration=Rt,c.monthsShort=function(e,t){return fn(e,t,"monthsShort")},c.weekdaysMin=function(e,t,n){return mn(e,t,n,"weekdaysMin")},c.defineLocale=ut,c.updateLocale=function(e,t){if(null!=t){var n,s,i=nt;null!=(s=at(e))&&(i=s._config),(n=new P(t=b(i,t))).parentLocale=st[e],st[e]=n,ot(e)}else null!=st[e]&&(null!=st[e].parentLocale?st[e]=st[e].parentLocale:null!=st[e]&&delete st[e]);return st[e]},c.locales=function(){return s(st)},c.weekdaysShort=function(e,t,n){return mn(e,t,n,"weekdaysShort")},c.normalizeUnits=R,c.relativeTimeRounding=function(e){return void 0===e?Un:"function"==typeof e&&(Un=e,!0)},c.relativeTimeThreshold=function(e,t){return void 0!==Nn[e]&&(void 0===t?Nn[e]:(Nn[e]=t,"s"===e&&(Nn.ss=t-1),!0))},c.calendarFormat=function(e,t){var n=e.diff(t,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},c.prototype=ln,c.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"YYYY-[W]WW",MONTH:"YYYY-MM"},c});;
/*!
 * URI.js - Mutating URLs
 *
 * Version: 1.19.1
 *
 * Author: Rodney Rehm
 * Web: http://medialize.github.io/URI.js/
 *
 * Licensed under
 *   MIT License http://www.opensource.org/licenses/mit-license
 *
 */
(function (root, factory) {
  'use strict';
  // https://github.com/umdjs/umd/blob/master/returnExports.js
  if (typeof module === 'object' && module.exports) {
    // Node
    module.exports = factory(require('./punycode'), require('./IPv6'), require('./SecondLevelDomains'));
  } else if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define(['./punycode', './IPv6', './SecondLevelDomains'], factory);
  } else {
    // Browser globals (root is window)
    root.URI = factory(root.punycode, root.IPv6, root.SecondLevelDomains, root);
  }
}(this, function (punycode, IPv6, SLD, root) {
  'use strict';
  /*global location, escape, unescape */
  // FIXME: v2.0.0 renamce non-camelCase properties to uppercase
  /*jshint camelcase: false */

  // save current URI variable, if any
  var _URI = root && root.URI;

  function URI(url, base) {
    var _urlSupplied = arguments.length >= 1;
    var _baseSupplied = arguments.length >= 2;

    // Allow instantiation without the 'new' keyword
    if (!(this instanceof URI)) {
      if (_urlSupplied) {
        if (_baseSupplied) {
          return new URI(url, base);
        }

        return new URI(url);
      }

      return new URI();
    }

    if (url === undefined) {
      if (_urlSupplied) {
        throw new TypeError('undefined is not a valid argument for URI');
      }

      if (typeof location !== 'undefined') {
        url = location.href + '';
      } else {
        url = '';
      }
    }

    if (url === null) {
      if (_urlSupplied) {
        throw new TypeError('null is not a valid argument for URI');
      }
    }

    this.href(url);

    // resolve to base according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#constructor
    if (base !== undefined) {
      return this.absoluteTo(base);
    }

    return this;
  }

  function isInteger(value) {
    return /^[0-9]+$/.test(value);
  }

  URI.version = '1.19.1';

  var p = URI.prototype;
  var hasOwn = Object.prototype.hasOwnProperty;

  function escapeRegEx(string) {
    // https://github.com/medialize/URI.js/commit/85ac21783c11f8ccab06106dba9735a31a86924d#commitcomment-821963
    return string.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
  }

  function getType(value) {
    // IE8 doesn't return [Object Undefined] but [Object Object] for undefined value
    if (value === undefined) {
      return 'Undefined';
    }

    return String(Object.prototype.toString.call(value)).slice(8, -1);
  }

  function isArray(obj) {
    return getType(obj) === 'Array';
  }

  function filterArrayValues(data, value) {
    var lookup = {};
    var i, length;

    if (getType(value) === 'RegExp') {
      lookup = null;
    } else if (isArray(value)) {
      for (i = 0, length = value.length; i < length; i++) {
        lookup[value[i]] = true;
      }
    } else {
      lookup[value] = true;
    }

    for (i = 0, length = data.length; i < length; i++) {
      /*jshint laxbreak: true */
      var _match = lookup && lookup[data[i]] !== undefined
        || !lookup && value.test(data[i]);
      /*jshint laxbreak: false */
      if (_match) {
        data.splice(i, 1);
        length--;
        i--;
      }
    }

    return data;
  }

  function arrayContains(list, value) {
    var i, length;

    // value may be string, number, array, regexp
    if (isArray(value)) {
      // Note: this can be optimized to O(n) (instead of current O(m * n))
      for (i = 0, length = value.length; i < length; i++) {
        if (!arrayContains(list, value[i])) {
          return false;
        }
      }

      return true;
    }

    var _type = getType(value);
    for (i = 0, length = list.length; i < length; i++) {
      if (_type === 'RegExp') {
        if (typeof list[i] === 'string' && list[i].match(value)) {
          return true;
        }
      } else if (list[i] === value) {
        return true;
      }
    }

    return false;
  }

  function arraysEqual(one, two) {
    if (!isArray(one) || !isArray(two)) {
      return false;
    }

    // arrays can't be equal if they have different amount of content
    if (one.length !== two.length) {
      return false;
    }

    one.sort();
    two.sort();

    for (var i = 0, l = one.length; i < l; i++) {
      if (one[i] !== two[i]) {
        return false;
      }
    }

    return true;
  }

  function trimSlashes(text) {
    var trim_expression = /^\/+|\/+$/g;
    return text.replace(trim_expression, '');
  }

  URI._parts = function() {
    return {
      protocol: null,
      username: null,
      password: null,
      hostname: null,
      urn: null,
      port: null,
      path: null,
      query: null,
      fragment: null,
      // state
      preventInvalidHostname: URI.preventInvalidHostname,
      duplicateQueryParameters: URI.duplicateQueryParameters,
      escapeQuerySpace: URI.escapeQuerySpace
    };
  };
  // state: throw on invalid hostname
  // see https://github.com/medialize/URI.js/pull/345
  // and https://github.com/medialize/URI.js/issues/354
  URI.preventInvalidHostname = false;
  // state: allow duplicate query parameters (a=1&a=1)
  URI.duplicateQueryParameters = false;
  // state: replaces + with %20 (space in query strings)
  URI.escapeQuerySpace = true;
  // static properties
  URI.protocol_expression = /^[a-z][a-z0-9.+-]*$/i;
  URI.idn_expression = /[^a-z0-9\._-]/i;
  URI.punycode_expression = /(xn--)/i;
  // well, 333.444.555.666 matches, but it sure ain't no IPv4 - do we care?
  URI.ip4_expression = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
  // credits to Rich Brown
  // source: http://forums.intermapper.com/viewtopic.php?p=1096#1096
  // specification: http://www.ietf.org/rfc/rfc4291.txt
  URI.ip6_expression = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/;
  // expression used is "gruber revised" (@gruber v2) determined to be the
  // best solution in a regex-golf we did a couple of ages ago at
  // * http://mathiasbynens.be/demo/url-regex
  // * http://rodneyrehm.de/t/url-regex.html
  URI.find_uri_expression = /\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/ig;
  URI.findUri = {
    // valid "scheme://" or "www."
    start: /\b(?:([a-z][a-z0-9.+-]*:\/\/)|www\.)/gi,
    // everything up to the next whitespace
    end: /[\s\r\n]|$/,
    // trim trailing punctuation captured by end RegExp
    trim: /[`!()\[\]{};:'".,<>?«»“”„‘’]+$/,
    // balanced parens inclusion (), [], {}, <>
    parens: /(\([^\)]*\)|\[[^\]]*\]|\{[^}]*\}|<[^>]*>)/g,
  };
  // http://www.iana.org/assignments/uri-schemes.html
  // http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Well-known_ports
  URI.defaultPorts = {
    http: '80',
    https: '443',
    ftp: '21',
    gopher: '70',
    ws: '80',
    wss: '443'
  };
  // list of protocols which always require a hostname
  URI.hostProtocols = [
    'http',
    'https'
  ];

  // allowed hostname characters according to RFC 3986
  // ALPHA DIGIT "-" "." "_" "~" "!" "$" "&" "'" "(" ")" "*" "+" "," ";" "=" %encoded
  // I've never seen a (non-IDN) hostname other than: ALPHA DIGIT . - _
  URI.invalid_hostname_characters = /[^a-zA-Z0-9\.\-:_]/;
  // map DOM Elements to their URI attribute
  URI.domAttributes = {
    'a': 'href',
    'blockquote': 'cite',
    'link': 'href',
    'base': 'href',
    'script': 'src',
    'form': 'action',
    'img': 'src',
    'area': 'href',
    'iframe': 'src',
    'embed': 'src',
    'source': 'src',
    'track': 'src',
    'input': 'src', // but only if type="image"
    'audio': 'src',
    'video': 'src'
  };
  URI.getDomAttribute = function(node) {
    if (!node || !node.nodeName) {
      return undefined;
    }

    var nodeName = node.nodeName.toLowerCase();
    // <input> should only expose src for type="image"
    if (nodeName === 'input' && node.type !== 'image') {
      return undefined;
    }

    return URI.domAttributes[nodeName];
  };

  function escapeForDumbFirefox36(value) {
    // https://github.com/medialize/URI.js/issues/91
    return escape(value);
  }

  // encoding / decoding according to RFC3986
  function strictEncodeURIComponent(string) {
    // see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/encodeURIComponent
    return encodeURIComponent(string)
      .replace(/[!'()*]/g, escapeForDumbFirefox36)
      .replace(/\*/g, '%2A');
  }
  URI.encode = strictEncodeURIComponent;
  URI.decode = decodeURIComponent;
  URI.iso8859 = function() {
    URI.encode = escape;
    URI.decode = unescape;
  };
  URI.unicode = function() {
    URI.encode = strictEncodeURIComponent;
    URI.decode = decodeURIComponent;
  };
  URI.characters = {
    pathname: {
      encode: {
        // RFC3986 2.1: For consistency, URI producers and normalizers should
        // use uppercase hexadecimal digits for all percent-encodings.
        expression: /%(24|26|2B|2C|3B|3D|3A|40)/ig,
        map: {
          // -._~!'()*
          '%24': '$',
          '%26': '&',
          '%2B': '+',
          '%2C': ',',
          '%3B': ';',
          '%3D': '=',
          '%3A': ':',
          '%40': '@'
        }
      },
      decode: {
        expression: /[\/\?#]/g,
        map: {
          '/': '%2F',
          '?': '%3F',
          '#': '%23'
        }
      }
    },
    reserved: {
      encode: {
        // RFC3986 2.1: For consistency, URI producers and normalizers should
        // use uppercase hexadecimal digits for all percent-encodings.
        expression: /%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/ig,
        map: {
          // gen-delims
          '%3A': ':',
          '%2F': '/',
          '%3F': '?',
          '%23': '#',
          '%5B': '[',
          '%5D': ']',
          '%40': '@',
          // sub-delims
          '%21': '!',
          '%24': '$',
          '%26': '&',
          '%27': '\'',
          '%28': '(',
          '%29': ')',
          '%2A': '*',
          '%2B': '+',
          '%2C': ',',
          '%3B': ';',
          '%3D': '='
        }
      }
    },
    urnpath: {
      // The characters under `encode` are the characters called out by RFC 2141 as being acceptable
      // for usage in a URN. RFC2141 also calls out "-", ".", and "_" as acceptable characters, but
      // these aren't encoded by encodeURIComponent, so we don't have to call them out here. Also
      // note that the colon character is not featured in the encoding map; this is because URI.js
      // gives the colons in URNs semantic meaning as the delimiters of path segements, and so it
      // should not appear unencoded in a segment itself.
      // See also the note above about RFC3986 and capitalalized hex digits.
      encode: {
        expression: /%(21|24|27|28|29|2A|2B|2C|3B|3D|40)/ig,
        map: {
          '%21': '!',
          '%24': '$',
          '%27': '\'',
          '%28': '(',
          '%29': ')',
          '%2A': '*',
          '%2B': '+',
          '%2C': ',',
          '%3B': ';',
          '%3D': '=',
          '%40': '@'
        }
      },
      // These characters are the characters called out by RFC2141 as "reserved" characters that
      // should never appear in a URN, plus the colon character (see note above).
      decode: {
        expression: /[\/\?#:]/g,
        map: {
          '/': '%2F',
          '?': '%3F',
          '#': '%23',
          ':': '%3A'
        }
      }
    }
  };
  URI.encodeQuery = function(string, escapeQuerySpace) {
    var escaped = URI.encode(string + '');
    if (escapeQuerySpace === undefined) {
      escapeQuerySpace = URI.escapeQuerySpace;
    }

    return escapeQuerySpace ? escaped.replace(/%20/g, '+') : escaped;
  };
  URI.decodeQuery = function(string, escapeQuerySpace) {
    string += '';
    if (escapeQuerySpace === undefined) {
      escapeQuerySpace = URI.escapeQuerySpace;
    }

    try {
      return URI.decode(escapeQuerySpace ? string.replace(/\+/g, '%20') : string);
    } catch(e) {
      // we're not going to mess with weird encodings,
      // give up and return the undecoded original string
      // see https://github.com/medialize/URI.js/issues/87
      // see https://github.com/medialize/URI.js/issues/92
      return string;
    }
  };
  // generate encode/decode path functions
  var _parts = {'encode':'encode', 'decode':'decode'};
  var _part;
  var generateAccessor = function(_group, _part) {
    return function(string) {
      try {
        return URI[_part](string + '').replace(URI.characters[_group][_part].expression, function(c) {
          return URI.characters[_group][_part].map[c];
        });
      } catch (e) {
        // we're not going to mess with weird encodings,
        // give up and return the undecoded original string
        // see https://github.com/medialize/URI.js/issues/87
        // see https://github.com/medialize/URI.js/issues/92
        return string;
      }
    };
  };

  for (_part in _parts) {
    URI[_part + 'PathSegment'] = generateAccessor('pathname', _parts[_part]);
    URI[_part + 'UrnPathSegment'] = generateAccessor('urnpath', _parts[_part]);
  }

  var generateSegmentedPathFunction = function(_sep, _codingFuncName, _innerCodingFuncName) {
    return function(string) {
      // Why pass in names of functions, rather than the function objects themselves? The
      // definitions of some functions (but in particular, URI.decode) will occasionally change due
      // to URI.js having ISO8859 and Unicode modes. Passing in the name and getting it will ensure
      // that the functions we use here are "fresh".
      var actualCodingFunc;
      if (!_innerCodingFuncName) {
        actualCodingFunc = URI[_codingFuncName];
      } else {
        actualCodingFunc = function(string) {
          return URI[_codingFuncName](URI[_innerCodingFuncName](string));
        };
      }

      var segments = (string + '').split(_sep);

      for (var i = 0, length = segments.length; i < length; i++) {
        segments[i] = actualCodingFunc(segments[i]);
      }

      return segments.join(_sep);
    };
  };

  // This takes place outside the above loop because we don't want, e.g., encodeUrnPath functions.
  URI.decodePath = generateSegmentedPathFunction('/', 'decodePathSegment');
  URI.decodeUrnPath = generateSegmentedPathFunction(':', 'decodeUrnPathSegment');
  URI.recodePath = generateSegmentedPathFunction('/', 'encodePathSegment', 'decode');
  URI.recodeUrnPath = generateSegmentedPathFunction(':', 'encodeUrnPathSegment', 'decode');

  URI.encodeReserved = generateAccessor('reserved', 'encode');

  URI.parse = function(string, parts) {
    var pos;
    if (!parts) {
      parts = {
        preventInvalidHostname: URI.preventInvalidHostname
      };
    }
    // [protocol"://"[username[":"password]"@"]hostname[":"port]"/"?][path]["?"querystring]["#"fragment]

    // extract fragment
    pos = string.indexOf('#');
    if (pos > -1) {
      // escaping?
      parts.fragment = string.substring(pos + 1) || null;
      string = string.substring(0, pos);
    }

    // extract query
    pos = string.indexOf('?');
    if (pos > -1) {
      // escaping?
      parts.query = string.substring(pos + 1) || null;
      string = string.substring(0, pos);
    }

    // extract protocol
    if (string.substring(0, 2) === '//') {
      // relative-scheme
      parts.protocol = null;
      string = string.substring(2);
      // extract "user:pass@host:port"
      string = URI.parseAuthority(string, parts);
    } else {
      pos = string.indexOf(':');
      if (pos > -1) {
        parts.protocol = string.substring(0, pos) || null;
        if (parts.protocol && !parts.protocol.match(URI.protocol_expression)) {
          // : may be within the path
          parts.protocol = undefined;
        } else if (string.substring(pos + 1, pos + 3) === '//') {
          string = string.substring(pos + 3);

          // extract "user:pass@host:port"
          string = URI.parseAuthority(string, parts);
        } else {
          string = string.substring(pos + 1);
          parts.urn = true;
        }
      }
    }

    // what's left must be the path
    parts.path = string;

    // and we're done
    return parts;
  };
  URI.parseHost = function(string, parts) {
    if (!string) {
      string = '';
    }

    // Copy chrome, IE, opera backslash-handling behavior.
    // Back slashes before the query string get converted to forward slashes
    // See: https://github.com/joyent/node/blob/386fd24f49b0e9d1a8a076592a404168faeecc34/lib/url.js#L115-L124
    // See: https://code.google.com/p/chromium/issues/detail?id=25916
    // https://github.com/medialize/URI.js/pull/233
    string = string.replace(/\\/g, '/');

    // extract host:port
    var pos = string.indexOf('/');
    var bracketPos;
    var t;

    if (pos === -1) {
      pos = string.length;
    }

    if (string.charAt(0) === '[') {
      // IPv6 host - http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-04#section-6
      // I claim most client software breaks on IPv6 anyways. To simplify things, URI only accepts
      // IPv6+port in the format [2001:db8::1]:80 (for the time being)
      bracketPos = string.indexOf(']');
      parts.hostname = string.substring(1, bracketPos) || null;
      parts.port = string.substring(bracketPos + 2, pos) || null;
      if (parts.port === '/') {
        parts.port = null;
      }
    } else {
      var firstColon = string.indexOf(':');
      var firstSlash = string.indexOf('/');
      var nextColon = string.indexOf(':', firstColon + 1);
      if (nextColon !== -1 && (firstSlash === -1 || nextColon < firstSlash)) {
        // IPv6 host contains multiple colons - but no port
        // this notation is actually not allowed by RFC 3986, but we're a liberal parser
        parts.hostname = string.substring(0, pos) || null;
        parts.port = null;
      } else {
        t = string.substring(0, pos).split(':');
        parts.hostname = t[0] || null;
        parts.port = t[1] || null;
      }
    }

    if (parts.hostname && string.substring(pos).charAt(0) !== '/') {
      pos++;
      string = '/' + string;
    }

    if (parts.preventInvalidHostname) {
      URI.ensureValidHostname(parts.hostname, parts.protocol);
    }

    if (parts.port) {
      URI.ensureValidPort(parts.port);
    }

    return string.substring(pos) || '/';
  };
  URI.parseAuthority = function(string, parts) {
    string = URI.parseUserinfo(string, parts);
    return URI.parseHost(string, parts);
  };
  URI.parseUserinfo = function(string, parts) {
    // extract username:password
    var firstSlash = string.indexOf('/');
    var pos = string.lastIndexOf('@', firstSlash > -1 ? firstSlash : string.length - 1);
    var t;

    // authority@ must come before /path
    if (pos > -1 && (firstSlash === -1 || pos < firstSlash)) {
      t = string.substring(0, pos).split(':');
      parts.username = t[0] ? URI.decode(t[0]) : null;
      t.shift();
      parts.password = t[0] ? URI.decode(t.join(':')) : null;
      string = string.substring(pos + 1);
    } else {
      parts.username = null;
      parts.password = null;
    }

    return string;
  };
  URI.parseQuery = function(string, escapeQuerySpace) {
    if (!string) {
      return {};
    }

    // throw out the funky business - "?"[name"="value"&"]+
    string = string.replace(/&+/g, '&').replace(/^\?*&*|&+$/g, '');

    if (!string) {
      return {};
    }

    var items = {};
    var splits = string.split('&');
    var length = splits.length;
    var v, name, value;

    for (var i = 0; i < length; i++) {
      v = splits[i].split('=');
      name = URI.decodeQuery(v.shift(), escapeQuerySpace);
      // no "=" is null according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#collect-url-parameters
      value = v.length ? URI.decodeQuery(v.join('='), escapeQuerySpace) : null;

      if (hasOwn.call(items, name)) {
        if (typeof items[name] === 'string' || items[name] === null) {
          items[name] = [items[name]];
        }

        items[name].push(value);
      } else {
        items[name] = value;
      }
    }

    return items;
  };

  URI.build = function(parts) {
    var t = '';

    if (parts.protocol) {
      t += parts.protocol + ':';
    }

    if (!parts.urn && (t || parts.hostname)) {
      t += '//';
    }

    t += (URI.buildAuthority(parts) || '');

    if (typeof parts.path === 'string') {
      if (parts.path.charAt(0) !== '/' && typeof parts.hostname === 'string') {
        t += '/';
      }

      t += parts.path;
    }

    if (typeof parts.query === 'string' && parts.query) {
      t += '?' + parts.query;
    }

    if (typeof parts.fragment === 'string' && parts.fragment) {
      t += '#' + parts.fragment;
    }
    return t;
  };
  URI.buildHost = function(parts) {
    var t = '';

    if (!parts.hostname) {
      return '';
    } else if (URI.ip6_expression.test(parts.hostname)) {
      t += '[' + parts.hostname + ']';
    } else {
      t += parts.hostname;
    }

    if (parts.port) {
      t += ':' + parts.port;
    }

    return t;
  };
  URI.buildAuthority = function(parts) {
    return URI.buildUserinfo(parts) + URI.buildHost(parts);
  };
  URI.buildUserinfo = function(parts) {
    var t = '';

    if (parts.username) {
      t += URI.encode(parts.username);
    }

    if (parts.password) {
      t += ':' + URI.encode(parts.password);
    }

    if (t) {
      t += '@';
    }

    return t;
  };
  URI.buildQuery = function(data, duplicateQueryParameters, escapeQuerySpace) {
    // according to http://tools.ietf.org/html/rfc3986 or http://labs.apache.org/webarch/uri/rfc/rfc3986.html
    // being »-._~!$&'()*+,;=:@/?« %HEX and alnum are allowed
    // the RFC explicitly states ?/foo being a valid use case, no mention of parameter syntax!
    // URI.js treats the query string as being application/x-www-form-urlencoded
    // see http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type

    var t = '';
    var unique, key, i, length;
    for (key in data) {
      if (hasOwn.call(data, key) && key) {
        if (isArray(data[key])) {
          unique = {};
          for (i = 0, length = data[key].length; i < length; i++) {
            if (data[key][i] !== undefined && unique[data[key][i] + ''] === undefined) {
              t += '&' + URI.buildQueryParameter(key, data[key][i], escapeQuerySpace);
              if (duplicateQueryParameters !== true) {
                unique[data[key][i] + ''] = true;
              }
            }
          }
        } else if (data[key] !== undefined) {
          t += '&' + URI.buildQueryParameter(key, data[key], escapeQuerySpace);
        }
      }
    }

    return t.substring(1);
  };
  URI.buildQueryParameter = function(name, value, escapeQuerySpace) {
    // http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type -- application/x-www-form-urlencoded
    // don't append "=" for null values, according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#url-parameter-serialization
    return URI.encodeQuery(name, escapeQuerySpace) + (value !== null ? '=' + URI.encodeQuery(value, escapeQuerySpace) : '');
  };

  URI.addQuery = function(data, name, value) {
    if (typeof name === 'object') {
      for (var key in name) {
        if (hasOwn.call(name, key)) {
          URI.addQuery(data, key, name[key]);
        }
      }
    } else if (typeof name === 'string') {
      if (data[name] === undefined) {
        data[name] = value;
        return;
      } else if (typeof data[name] === 'string') {
        data[name] = [data[name]];
      }

      if (!isArray(value)) {
        value = [value];
      }

      data[name] = (data[name] || []).concat(value);
    } else {
      throw new TypeError('URI.addQuery() accepts an object, string as the name parameter');
    }
  };

  URI.setQuery = function(data, name, value) {
    if (typeof name === 'object') {
      for (var key in name) {
        if (hasOwn.call(name, key)) {
          URI.setQuery(data, key, name[key]);
        }
      }
    } else if (typeof name === 'string') {
      data[name] = value === undefined ? null : value;
    } else {
      throw new TypeError('URI.setQuery() accepts an object, string as the name parameter');
    }
  };

  URI.removeQuery = function(data, name, value) {
    var i, length, key;

    if (isArray(name)) {
      for (i = 0, length = name.length; i < length; i++) {
        data[name[i]] = undefined;
      }
    } else if (getType(name) === 'RegExp') {
      for (key in data) {
        if (name.test(key)) {
          data[key] = undefined;
        }
      }
    } else if (typeof name === 'object') {
      for (key in name) {
        if (hasOwn.call(name, key)) {
          URI.removeQuery(data, key, name[key]);
        }
      }
    } else if (typeof name === 'string') {
      if (value !== undefined) {
        if (getType(value) === 'RegExp') {
          if (!isArray(data[name]) && value.test(data[name])) {
            data[name] = undefined;
          } else {
            data[name] = filterArrayValues(data[name], value);
          }
        } else if (data[name] === String(value) && (!isArray(value) || value.length === 1)) {
          data[name] = undefined;
        } else if (isArray(data[name])) {
          data[name] = filterArrayValues(data[name], value);
        }
      } else {
        data[name] = undefined;
      }
    } else {
      throw new TypeError('URI.removeQuery() accepts an object, string, RegExp as the first parameter');
    }
  };
  URI.hasQuery = function(data, name, value, withinArray) {
    switch (getType(name)) {
      case 'String':
        // Nothing to do here
        break;

      case 'RegExp':
        for (var key in data) {
          if (hasOwn.call(data, key)) {
            if (name.test(key) && (value === undefined || URI.hasQuery(data, key, value))) {
              return true;
            }
          }
        }

        return false;

      case 'Object':
        for (var _key in name) {
          if (hasOwn.call(name, _key)) {
            if (!URI.hasQuery(data, _key, name[_key])) {
              return false;
            }
          }
        }

        return true;

      default:
        throw new TypeError('URI.hasQuery() accepts a string, regular expression or object as the name parameter');
    }

    switch (getType(value)) {
      case 'Undefined':
        // true if exists (but may be empty)
        return name in data; // data[name] !== undefined;

      case 'Boolean':
        // true if exists and non-empty
        var _booly = Boolean(isArray(data[name]) ? data[name].length : data[name]);
        return value === _booly;

      case 'Function':
        // allow complex comparison
        return !!value(data[name], name, data);

      case 'Array':
        if (!isArray(data[name])) {
          return false;
        }

        var op = withinArray ? arrayContains : arraysEqual;
        return op(data[name], value);

      case 'RegExp':
        if (!isArray(data[name])) {
          return Boolean(data[name] && data[name].match(value));
        }

        if (!withinArray) {
          return false;
        }

        return arrayContains(data[name], value);

      case 'Number':
        value = String(value);
        /* falls through */
      case 'String':
        if (!isArray(data[name])) {
          return data[name] === value;
        }

        if (!withinArray) {
          return false;
        }

        return arrayContains(data[name], value);

      default:
        throw new TypeError('URI.hasQuery() accepts undefined, boolean, string, number, RegExp, Function as the value parameter');
    }
  };


  URI.joinPaths = function() {
    var input = [];
    var segments = [];
    var nonEmptySegments = 0;

    for (var i = 0; i < arguments.length; i++) {
      var url = new URI(arguments[i]);
      input.push(url);
      var _segments = url.segment();
      for (var s = 0; s < _segments.length; s++) {
        if (typeof _segments[s] === 'string') {
          segments.push(_segments[s]);
        }

        if (_segments[s]) {
          nonEmptySegments++;
        }
      }
    }

    if (!segments.length || !nonEmptySegments) {
      return new URI('');
    }

    var uri = new URI('').segment(segments);

    if (input[0].path() === '' || input[0].path().slice(0, 1) === '/') {
      uri.path('/' + uri.path());
    }

    return uri.normalize();
  };

  URI.commonPath = function(one, two) {
    var length = Math.min(one.length, two.length);
    var pos;

    // find first non-matching character
    for (pos = 0; pos < length; pos++) {
      if (one.charAt(pos) !== two.charAt(pos)) {
        pos--;
        break;
      }
    }

    if (pos < 1) {
      return one.charAt(0) === two.charAt(0) && one.charAt(0) === '/' ? '/' : '';
    }

    // revert to last /
    if (one.charAt(pos) !== '/' || two.charAt(pos) !== '/') {
      pos = one.substring(0, pos).lastIndexOf('/');
    }

    return one.substring(0, pos + 1);
  };

  URI.withinString = function(string, callback, options) {
    options || (options = {});
    var _start = options.start || URI.findUri.start;
    var _end = options.end || URI.findUri.end;
    var _trim = options.trim || URI.findUri.trim;
    var _parens = options.parens || URI.findUri.parens;
    var _attributeOpen = /[a-z0-9-]=["']?$/i;

    _start.lastIndex = 0;
    while (true) {
      var match = _start.exec(string);
      if (!match) {
        break;
      }

      var start = match.index;
      if (options.ignoreHtml) {
        // attribut(e=["']?$)
        var attributeOpen = string.slice(Math.max(start - 3, 0), start);
        if (attributeOpen && _attributeOpen.test(attributeOpen)) {
          continue;
        }
      }

      var end = start + string.slice(start).search(_end);
      var slice = string.slice(start, end);
      // make sure we include well balanced parens
      var parensEnd = -1;
      while (true) {
        var parensMatch = _parens.exec(slice);
        if (!parensMatch) {
          break;
        }

        var parensMatchEnd = parensMatch.index + parensMatch[0].length;
        parensEnd = Math.max(parensEnd, parensMatchEnd);
      }

      if (parensEnd > -1) {
        slice = slice.slice(0, parensEnd) + slice.slice(parensEnd).replace(_trim, '');
      } else {
        slice = slice.replace(_trim, '');
      }

      if (slice.length <= match[0].length) {
        // the extract only contains the starting marker of a URI,
        // e.g. "www" or "http://"
        continue;
      }

      if (options.ignore && options.ignore.test(slice)) {
        continue;
      }

      end = start + slice.length;
      var result = callback(slice, start, end, string);
      if (result === undefined) {
        _start.lastIndex = end;
        continue;
      }

      result = String(result);
      string = string.slice(0, start) + result + string.slice(end);
      _start.lastIndex = start + result.length;
    }

    _start.lastIndex = 0;
    return string;
  };

  URI.ensureValidHostname = function(v, protocol) {
    // Theoretically URIs allow percent-encoding in Hostnames (according to RFC 3986)
    // they are not part of DNS and therefore ignored by URI.js

    var hasHostname = !!v; // not null and not an empty string
    var hasProtocol = !!protocol;
    var rejectEmptyHostname = false;

    if (hasProtocol) {
      rejectEmptyHostname = arrayContains(URI.hostProtocols, protocol);
    }

    if (rejectEmptyHostname && !hasHostname) {
      throw new TypeError('Hostname cannot be empty, if protocol is ' + protocol);
    } else if (v && v.match(URI.invalid_hostname_characters)) {
      // test punycode
      if (!punycode) {
        throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-:_] and Punycode.js is not available');
      }
      if (punycode.toASCII(v).match(URI.invalid_hostname_characters)) {
        throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-:_]');
      }
    }
  };

  URI.ensureValidPort = function (v) {
    if (!v) {
      return;
    }

    var port = Number(v);
    if (isInteger(port) && (port > 0) && (port < 65536)) {
      return;
    }

    throw new TypeError('Port "' + v + '" is not a valid port');
  };

  // noConflict
  URI.noConflict = function(removeAll) {
    if (removeAll) {
      var unconflicted = {
        URI: this.noConflict()
      };

      if (root.URITemplate && typeof root.URITemplate.noConflict === 'function') {
        unconflicted.URITemplate = root.URITemplate.noConflict();
      }

      if (root.IPv6 && typeof root.IPv6.noConflict === 'function') {
        unconflicted.IPv6 = root.IPv6.noConflict();
      }

      if (root.SecondLevelDomains && typeof root.SecondLevelDomains.noConflict === 'function') {
        unconflicted.SecondLevelDomains = root.SecondLevelDomains.noConflict();
      }

      return unconflicted;
    } else if (root.URI === this) {
      root.URI = _URI;
    }

    return this;
  };

  p.build = function(deferBuild) {
    if (deferBuild === true) {
      this._deferred_build = true;
    } else if (deferBuild === undefined || this._deferred_build) {
      this._string = URI.build(this._parts);
      this._deferred_build = false;
    }

    return this;
  };

  p.clone = function() {
    return new URI(this);
  };

  p.valueOf = p.toString = function() {
    return this.build(false)._string;
  };


  function generateSimpleAccessor(_part){
    return function(v, build) {
      if (v === undefined) {
        return this._parts[_part] || '';
      } else {
        this._parts[_part] = v || null;
        this.build(!build);
        return this;
      }
    };
  }

  function generatePrefixAccessor(_part, _key){
    return function(v, build) {
      if (v === undefined) {
        return this._parts[_part] || '';
      } else {
        if (v !== null) {
          v = v + '';
          if (v.charAt(0) === _key) {
            v = v.substring(1);
          }
        }

        this._parts[_part] = v;
        this.build(!build);
        return this;
      }
    };
  }

  p.protocol = generateSimpleAccessor('protocol');
  p.username = generateSimpleAccessor('username');
  p.password = generateSimpleAccessor('password');
  p.hostname = generateSimpleAccessor('hostname');
  p.port = generateSimpleAccessor('port');
  p.query = generatePrefixAccessor('query', '?');
  p.fragment = generatePrefixAccessor('fragment', '#');

  p.search = function(v, build) {
    var t = this.query(v, build);
    return typeof t === 'string' && t.length ? ('?' + t) : t;
  };
  p.hash = function(v, build) {
    var t = this.fragment(v, build);
    return typeof t === 'string' && t.length ? ('#' + t) : t;
  };

  p.pathname = function(v, build) {
    if (v === undefined || v === true) {
      var res = this._parts.path || (this._parts.hostname ? '/' : '');
      return v ? (this._parts.urn ? URI.decodeUrnPath : URI.decodePath)(res) : res;
    } else {
      if (this._parts.urn) {
        this._parts.path = v ? URI.recodeUrnPath(v) : '';
      } else {
        this._parts.path = v ? URI.recodePath(v) : '/';
      }
      this.build(!build);
      return this;
    }
  };
  p.path = p.pathname;
  p.href = function(href, build) {
    var key;

    if (href === undefined) {
      return this.toString();
    }

    this._string = '';
    this._parts = URI._parts();

    var _URI = href instanceof URI;
    var _object = typeof href === 'object' && (href.hostname || href.path || href.pathname);
    if (href.nodeName) {
      var attribute = URI.getDomAttribute(href);
      href = href[attribute] || '';
      _object = false;
    }

    // window.location is reported to be an object, but it's not the sort
    // of object we're looking for:
    // * location.protocol ends with a colon
    // * location.query != object.search
    // * location.hash != object.fragment
    // simply serializing the unknown object should do the trick
    // (for location, not for everything...)
    if (!_URI && _object && href.pathname !== undefined) {
      href = href.toString();
    }

    if (typeof href === 'string' || href instanceof String) {
      this._parts = URI.parse(String(href), this._parts);
    } else if (_URI || _object) {
      var src = _URI ? href._parts : href;
      for (key in src) {
        if (key === 'query') { continue; }
        if (hasOwn.call(this._parts, key)) {
          this._parts[key] = src[key];
        }
      }
      if (src.query) {
        this.query(src.query, false);
      }
    } else {
      throw new TypeError('invalid input');
    }

    this.build(!build);
    return this;
  };

  // identification accessors
  p.is = function(what) {
    var ip = false;
    var ip4 = false;
    var ip6 = false;
    var name = false;
    var sld = false;
    var idn = false;
    var punycode = false;
    var relative = !this._parts.urn;

    if (this._parts.hostname) {
      relative = false;
      ip4 = URI.ip4_expression.test(this._parts.hostname);
      ip6 = URI.ip6_expression.test(this._parts.hostname);
      ip = ip4 || ip6;
      name = !ip;
      sld = name && SLD && SLD.has(this._parts.hostname);
      idn = name && URI.idn_expression.test(this._parts.hostname);
      punycode = name && URI.punycode_expression.test(this._parts.hostname);
    }

    switch (what.toLowerCase()) {
      case 'relative':
        return relative;

      case 'absolute':
        return !relative;

      // hostname identification
      case 'domain':
      case 'name':
        return name;

      case 'sld':
        return sld;

      case 'ip':
        return ip;

      case 'ip4':
      case 'ipv4':
      case 'inet4':
        return ip4;

      case 'ip6':
      case 'ipv6':
      case 'inet6':
        return ip6;

      case 'idn':
        return idn;

      case 'url':
        return !this._parts.urn;

      case 'urn':
        return !!this._parts.urn;

      case 'punycode':
        return punycode;
    }

    return null;
  };

  // component specific input validation
  var _protocol = p.protocol;
  var _port = p.port;
  var _hostname = p.hostname;

  p.protocol = function(v, build) {
    if (v) {
      // accept trailing ://
      v = v.replace(/:(\/\/)?$/, '');

      if (!v.match(URI.protocol_expression)) {
        throw new TypeError('Protocol "' + v + '" contains characters other than [A-Z0-9.+-] or doesn\'t start with [A-Z]');
      }
    }

    return _protocol.call(this, v, build);
  };
  p.scheme = p.protocol;
  p.port = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this;
    }

    if (v !== undefined) {
      if (v === 0) {
        v = null;
      }

      if (v) {
        v += '';
        if (v.charAt(0) === ':') {
          v = v.substring(1);
        }

        URI.ensureValidPort(v);
      }
    }
    return _port.call(this, v, build);
  };
  p.hostname = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this;
    }

    if (v !== undefined) {
      var x = { preventInvalidHostname: this._parts.preventInvalidHostname };
      var res = URI.parseHost(v, x);
      if (res !== '/') {
        throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]');
      }

      v = x.hostname;
      if (this._parts.preventInvalidHostname) {
        URI.ensureValidHostname(v, this._parts.protocol);
      }
    }

    return _hostname.call(this, v, build);
  };

  // compound accessors
  p.origin = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this;
    }

    if (v === undefined) {
      var protocol = this.protocol();
      var authority = this.authority();
      if (!authority) {
        return '';
      }

      return (protocol ? protocol + '://' : '') + this.authority();
    } else {
      var origin = URI(v);
      this
        .protocol(origin.protocol())
        .authority(origin.authority())
        .build(!build);
      return this;
    }
  };
  p.host = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this;
    }

    if (v === undefined) {
      return this._parts.hostname ? URI.buildHost(this._parts) : '';
    } else {
      var res = URI.parseHost(v, this._parts);
      if (res !== '/') {
        throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]');
      }

      this.build(!build);
      return this;
    }
  };
  p.authority = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this;
    }

    if (v === undefined) {
      return this._parts.hostname ? URI.buildAuthority(this._parts) : '';
    } else {
      var res = URI.parseAuthority(v, this._parts);
      if (res !== '/') {
        throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]');
      }

      this.build(!build);
      return this;
    }
  };
  p.userinfo = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this;
    }

    if (v === undefined) {
      var t = URI.buildUserinfo(this._parts);
      return t ? t.substring(0, t.length -1) : t;
    } else {
      if (v[v.length-1] !== '@') {
        v += '@';
      }

      URI.parseUserinfo(v, this._parts);
      this.build(!build);
      return this;
    }
  };
  p.resource = function(v, build) {
    var parts;

    if (v === undefined) {
      return this.path() + this.search() + this.hash();
    }

    parts = URI.parse(v);
    this._parts.path = parts.path;
    this._parts.query = parts.query;
    this._parts.fragment = parts.fragment;
    this.build(!build);
    return this;
  };

  // fraction accessors
  p.subdomain = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this;
    }

    // convenience, return "www" from "www.example.org"
    if (v === undefined) {
      if (!this._parts.hostname || this.is('IP')) {
        return '';
      }

      // grab domain and add another segment
      var end = this._parts.hostname.length - this.domain().length - 1;
      return this._parts.hostname.substring(0, end) || '';
    } else {
      var e = this._parts.hostname.length - this.domain().length;
      var sub = this._parts.hostname.substring(0, e);
      var replace = new RegExp('^' + escapeRegEx(sub));

      if (v && v.charAt(v.length - 1) !== '.') {
        v += '.';
      }

      if (v.indexOf(':') !== -1) {
        throw new TypeError('Domains cannot contain colons');
      }

      if (v) {
        URI.ensureValidHostname(v, this._parts.protocol);
      }

      this._parts.hostname = this._parts.hostname.replace(replace, v);
      this.build(!build);
      return this;
    }
  };
  p.domain = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this;
    }

    if (typeof v === 'boolean') {
      build = v;
      v = undefined;
    }

    // convenience, return "example.org" from "www.example.org"
    if (v === undefined) {
      if (!this._parts.hostname || this.is('IP')) {
        return '';
      }

      // if hostname consists of 1 or 2 segments, it must be the domain
      var t = this._parts.hostname.match(/\./g);
      if (t && t.length < 2) {
        return this._parts.hostname;
      }

      // grab tld and add another segment
      var end = this._parts.hostname.length - this.tld(build).length - 1;
      end = this._parts.hostname.lastIndexOf('.', end -1) + 1;
      return this._parts.hostname.substring(end) || '';
    } else {
      if (!v) {
        throw new TypeError('cannot set domain empty');
      }

      if (v.indexOf(':') !== -1) {
        throw new TypeError('Domains cannot contain colons');
      }

      URI.ensureValidHostname(v, this._parts.protocol);

      if (!this._parts.hostname || this.is('IP')) {
        this._parts.hostname = v;
      } else {
        var replace = new RegExp(escapeRegEx(this.domain()) + '$');
        this._parts.hostname = this._parts.hostname.replace(replace, v);
      }

      this.build(!build);
      return this;
    }
  };
  p.tld = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this;
    }

    if (typeof v === 'boolean') {
      build = v;
      v = undefined;
    }

    // return "org" from "www.example.org"
    if (v === undefined) {
      if (!this._parts.hostname || this.is('IP')) {
        return '';
      }

      var pos = this._parts.hostname.lastIndexOf('.');
      var tld = this._parts.hostname.substring(pos + 1);

      if (build !== true && SLD && SLD.list[tld.toLowerCase()]) {
        return SLD.get(this._parts.hostname) || tld;
      }

      return tld;
    } else {
      var replace;

      if (!v) {
        throw new TypeError('cannot set TLD empty');
      } else if (v.match(/[^a-zA-Z0-9-]/)) {
        if (SLD && SLD.is(v)) {
          replace = new RegExp(escapeRegEx(this.tld()) + '$');
          this._parts.hostname = this._parts.hostname.replace(replace, v);
        } else {
          throw new TypeError('TLD "' + v + '" contains characters other than [A-Z0-9]');
        }
      } else if (!this._parts.hostname || this.is('IP')) {
        throw new ReferenceError('cannot set TLD on non-domain host');
      } else {
        replace = new RegExp(escapeRegEx(this.tld()) + '$');
        this._parts.hostname = this._parts.hostname.replace(replace, v);
      }

      this.build(!build);
      return this;
    }
  };
  p.directory = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this;
    }

    if (v === undefined || v === true) {
      if (!this._parts.path && !this._parts.hostname) {
        return '';
      }

      if (this._parts.path === '/') {
        return '/';
      }

      var end = this._parts.path.length - this.filename().length - 1;
      var res = this._parts.path.substring(0, end) || (this._parts.hostname ? '/' : '');

      return v ? URI.decodePath(res) : res;

    } else {
      var e = this._parts.path.length - this.filename().length;
      var directory = this._parts.path.substring(0, e);
      var replace = new RegExp('^' + escapeRegEx(directory));

      // fully qualifier directories begin with a slash
      if (!this.is('relative')) {
        if (!v) {
          v = '/';
        }

        if (v.charAt(0) !== '/') {
          v = '/' + v;
        }
      }

      // directories always end with a slash
      if (v && v.charAt(v.length - 1) !== '/') {
        v += '/';
      }

      v = URI.recodePath(v);
      this._parts.path = this._parts.path.replace(replace, v);
      this.build(!build);
      return this;
    }
  };
  p.filename = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this;
    }

    if (typeof v !== 'string') {
      if (!this._parts.path || this._parts.path === '/') {
        return '';
      }

      var pos = this._parts.path.lastIndexOf('/');
      var res = this._parts.path.substring(pos+1);

      return v ? URI.decodePathSegment(res) : res;
    } else {
      var mutatedDirectory = false;

      if (v.charAt(0) === '/') {
        v = v.substring(1);
      }

      if (v.match(/\.?\//)) {
        mutatedDirectory = true;
      }

      var replace = new RegExp(escapeRegEx(this.filename()) + '$');
      v = URI.recodePath(v);
      this._parts.path = this._parts.path.replace(replace, v);

      if (mutatedDirectory) {
        this.normalizePath(build);
      } else {
        this.build(!build);
      }

      return this;
    }
  };
  p.suffix = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this;
    }

    if (v === undefined || v === true) {
      if (!this._parts.path || this._parts.path === '/') {
        return '';
      }

      var filename = this.filename();
      var pos = filename.lastIndexOf('.');
      var s, res;

      if (pos === -1) {
        return '';
      }

      // suffix may only contain alnum characters (yup, I made this up.)
      s = filename.substring(pos+1);
      res = (/^[a-z0-9%]+$/i).test(s) ? s : '';
      return v ? URI.decodePathSegment(res) : res;
    } else {
      if (v.charAt(0) === '.') {
        v = v.substring(1);
      }

      var suffix = this.suffix();
      var replace;

      if (!suffix) {
        if (!v) {
          return this;
        }

        this._parts.path += '.' + URI.recodePath(v);
      } else if (!v) {
        replace = new RegExp(escapeRegEx('.' + suffix) + '$');
      } else {
        replace = new RegExp(escapeRegEx(suffix) + '$');
      }

      if (replace) {
        v = URI.recodePath(v);
        this._parts.path = this._parts.path.replace(replace, v);
      }

      this.build(!build);
      return this;
    }
  };
  p.segment = function(segment, v, build) {
    var separator = this._parts.urn ? ':' : '/';
    var path = this.path();
    var absolute = path.substring(0, 1) === '/';
    var segments = path.split(separator);

    if (segment !== undefined && typeof segment !== 'number') {
      build = v;
      v = segment;
      segment = undefined;
    }

    if (segment !== undefined && typeof segment !== 'number') {
      throw new Error('Bad segment "' + segment + '", must be 0-based integer');
    }

    if (absolute) {
      segments.shift();
    }

    if (segment < 0) {
      // allow negative indexes to address from the end
      segment = Math.max(segments.length + segment, 0);
    }

    if (v === undefined) {
      /*jshint laxbreak: true */
      return segment === undefined
        ? segments
        : segments[segment];
      /*jshint laxbreak: false */
    } else if (segment === null || segments[segment] === undefined) {
      if (isArray(v)) {
        segments = [];
        // collapse empty elements within array
        for (var i=0, l=v.length; i < l; i++) {
          if (!v[i].length && (!segments.length || !segments[segments.length -1].length)) {
            continue;
          }

          if (segments.length && !segments[segments.length -1].length) {
            segments.pop();
          }

          segments.push(trimSlashes(v[i]));
        }
      } else if (v || typeof v === 'string') {
        v = trimSlashes(v);
        if (segments[segments.length -1] === '') {
          // empty trailing elements have to be overwritten
          // to prevent results such as /foo//bar
          segments[segments.length -1] = v;
        } else {
          segments.push(v);
        }
      }
    } else {
      if (v) {
        segments[segment] = trimSlashes(v);
      } else {
        segments.splice(segment, 1);
      }
    }

    if (absolute) {
      segments.unshift('');
    }

    return this.path(segments.join(separator), build);
  };
  p.segmentCoded = function(segment, v, build) {
    var segments, i, l;

    if (typeof segment !== 'number') {
      build = v;
      v = segment;
      segment = undefined;
    }

    if (v === undefined) {
      segments = this.segment(segment, v, build);
      if (!isArray(segments)) {
        segments = segments !== undefined ? URI.decode(segments) : undefined;
      } else {
        for (i = 0, l = segments.length; i < l; i++) {
          segments[i] = URI.decode(segments[i]);
        }
      }

      return segments;
    }

    if (!isArray(v)) {
      v = (typeof v === 'string' || v instanceof String) ? URI.encode(v) : v;
    } else {
      for (i = 0, l = v.length; i < l; i++) {
        v[i] = URI.encode(v[i]);
      }
    }

    return this.segment(segment, v, build);
  };

  // mutating query string
  var q = p.query;
  p.query = function(v, build) {
    if (v === true) {
      return URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);
    } else if (typeof v === 'function') {
      var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);
      var result = v.call(this, data);
      this._parts.query = URI.buildQuery(result || data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);
      this.build(!build);
      return this;
    } else if (v !== undefined && typeof v !== 'string') {
      this._parts.query = URI.buildQuery(v, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);
      this.build(!build);
      return this;
    } else {
      return q.call(this, v, build);
    }
  };
  p.setQuery = function(name, value, build) {
    var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);

    if (typeof name === 'string' || name instanceof String) {
      data[name] = value !== undefined ? value : null;
    } else if (typeof name === 'object') {
      for (var key in name) {
        if (hasOwn.call(name, key)) {
          data[key] = name[key];
        }
      }
    } else {
      throw new TypeError('URI.addQuery() accepts an object, string as the name parameter');
    }

    this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);
    if (typeof name !== 'string') {
      build = value;
    }

    this.build(!build);
    return this;
  };
  p.addQuery = function(name, value, build) {
    var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);
    URI.addQuery(data, name, value === undefined ? null : value);
    this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);
    if (typeof name !== 'string') {
      build = value;
    }

    this.build(!build);
    return this;
  };
  p.removeQuery = function(name, value, build) {
    var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);
    URI.removeQuery(data, name, value);
    this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);
    if (typeof name !== 'string') {
      build = value;
    }

    this.build(!build);
    return this;
  };
  p.hasQuery = function(name, value, withinArray) {
    var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);
    return URI.hasQuery(data, name, value, withinArray);
  };
  p.setSearch = p.setQuery;
  p.addSearch = p.addQuery;
  p.removeSearch = p.removeQuery;
  p.hasSearch = p.hasQuery;

  // sanitizing URLs
  p.normalize = function() {
    if (this._parts.urn) {
      return this
        .normalizeProtocol(false)
        .normalizePath(false)
        .normalizeQuery(false)
        .normalizeFragment(false)
        .build();
    }

    return this
      .normalizeProtocol(false)
      .normalizeHostname(false)
      .normalizePort(false)
      .normalizePath(false)
      .normalizeQuery(false)
      .normalizeFragment(false)
      .build();
  };
  p.normalizeProtocol = function(build) {
    if (typeof this._parts.protocol === 'string') {
      this._parts.protocol = this._parts.protocol.toLowerCase();
      this.build(!build);
    }

    return this;
  };
  p.normalizeHostname = function(build) {
    if (this._parts.hostname) {
      if (this.is('IDN') && punycode) {
        this._parts.hostname = punycode.toASCII(this._parts.hostname);
      } else if (this.is('IPv6') && IPv6) {
        this._parts.hostname = IPv6.best(this._parts.hostname);
      }

      this._parts.hostname = this._parts.hostname.toLowerCase();
      this.build(!build);
    }

    return this;
  };
  p.normalizePort = function(build) {
    // remove port of it's the protocol's default
    if (typeof this._parts.protocol === 'string' && this._parts.port === URI.defaultPorts[this._parts.protocol]) {
      this._parts.port = null;
      this.build(!build);
    }

    return this;
  };
  p.normalizePath = function(build) {
    var _path = this._parts.path;
    if (!_path) {
      return this;
    }

    if (this._parts.urn) {
      this._parts.path = URI.recodeUrnPath(this._parts.path);
      this.build(!build);
      return this;
    }

    if (this._parts.path === '/') {
      return this;
    }

    _path = URI.recodePath(_path);

    var _was_relative;
    var _leadingParents = '';
    var _parent, _pos;

    // handle relative paths
    if (_path.charAt(0) !== '/') {
      _was_relative = true;
      _path = '/' + _path;
    }

    // handle relative files (as opposed to directories)
    if (_path.slice(-3) === '/..' || _path.slice(-2) === '/.') {
      _path += '/';
    }

    // resolve simples
    _path = _path
      .replace(/(\/(\.\/)+)|(\/\.$)/g, '/')
      .replace(/\/{2,}/g, '/');

    // remember leading parents
    if (_was_relative) {
      _leadingParents = _path.substring(1).match(/^(\.\.\/)+/) || '';
      if (_leadingParents) {
        _leadingParents = _leadingParents[0];
      }
    }

    // resolve parents
    while (true) {
      _parent = _path.search(/\/\.\.(\/|$)/);
      if (_parent === -1) {
        // no more ../ to resolve
        break;
      } else if (_parent === 0) {
        // top level cannot be relative, skip it
        _path = _path.substring(3);
        continue;
      }

      _pos = _path.substring(0, _parent).lastIndexOf('/');
      if (_pos === -1) {
        _pos = _parent;
      }
      _path = _path.substring(0, _pos) + _path.substring(_parent + 3);
    }

    // revert to relative
    if (_was_relative && this.is('relative')) {
      _path = _leadingParents + _path.substring(1);
    }

    this._parts.path = _path;
    this.build(!build);
    return this;
  };
  p.normalizePathname = p.normalizePath;
  p.normalizeQuery = function(build) {
    if (typeof this._parts.query === 'string') {
      if (!this._parts.query.length) {
        this._parts.query = null;
      } else {
        this.query(URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace));
      }

      this.build(!build);
    }

    return this;
  };
  p.normalizeFragment = function(build) {
    if (!this._parts.fragment) {
      this._parts.fragment = null;
      this.build(!build);
    }

    return this;
  };
  p.normalizeSearch = p.normalizeQuery;
  p.normalizeHash = p.normalizeFragment;

  p.iso8859 = function() {
    // expect unicode input, iso8859 output
    var e = URI.encode;
    var d = URI.decode;

    URI.encode = escape;
    URI.decode = decodeURIComponent;
    try {
      this.normalize();
    } finally {
      URI.encode = e;
      URI.decode = d;
    }
    return this;
  };

  p.unicode = function() {
    // expect iso8859 input, unicode output
    var e = URI.encode;
    var d = URI.decode;

    URI.encode = strictEncodeURIComponent;
    URI.decode = unescape;
    try {
      this.normalize();
    } finally {
      URI.encode = e;
      URI.decode = d;
    }
    return this;
  };

  p.readable = function() {
    var uri = this.clone();
    // removing username, password, because they shouldn't be displayed according to RFC 3986
    uri.username('').password('').normalize();
    var t = '';
    if (uri._parts.protocol) {
      t += uri._parts.protocol + '://';
    }

    if (uri._parts.hostname) {
      if (uri.is('punycode') && punycode) {
        t += punycode.toUnicode(uri._parts.hostname);
        if (uri._parts.port) {
          t += ':' + uri._parts.port;
        }
      } else {
        t += uri.host();
      }
    }

    if (uri._parts.hostname && uri._parts.path && uri._parts.path.charAt(0) !== '/') {
      t += '/';
    }

    t += uri.path(true);
    if (uri._parts.query) {
      var q = '';
      for (var i = 0, qp = uri._parts.query.split('&'), l = qp.length; i < l; i++) {
        var kv = (qp[i] || '').split('=');
        q += '&' + URI.decodeQuery(kv[0], this._parts.escapeQuerySpace)
          .replace(/&/g, '%26');

        if (kv[1] !== undefined) {
          q += '=' + URI.decodeQuery(kv[1], this._parts.escapeQuerySpace)
            .replace(/&/g, '%26');
        }
      }
      t += '?' + q.substring(1);
    }

    t += URI.decodeQuery(uri.hash(), true);
    return t;
  };

  // resolving relative and absolute URLs
  p.absoluteTo = function(base) {
    var resolved = this.clone();
    var properties = ['protocol', 'username', 'password', 'hostname', 'port'];
    var basedir, i, p;

    if (this._parts.urn) {
      throw new Error('URNs do not have any generally defined hierarchical components');
    }

    if (!(base instanceof URI)) {
      base = new URI(base);
    }

    if (resolved._parts.protocol) {
      // Directly returns even if this._parts.hostname is empty.
      return resolved;
    } else {
      resolved._parts.protocol = base._parts.protocol;
    }

    if (this._parts.hostname) {
      return resolved;
    }

    for (i = 0; (p = properties[i]); i++) {
      resolved._parts[p] = base._parts[p];
    }

    if (!resolved._parts.path) {
      resolved._parts.path = base._parts.path;
      if (!resolved._parts.query) {
        resolved._parts.query = base._parts.query;
      }
    } else {
      if (resolved._parts.path.substring(-2) === '..') {
        resolved._parts.path += '/';
      }

      if (resolved.path().charAt(0) !== '/') {
        basedir = base.directory();
        basedir = basedir ? basedir : base.path().indexOf('/') === 0 ? '/' : '';
        resolved._parts.path = (basedir ? (basedir + '/') : '') + resolved._parts.path;
        resolved.normalizePath();
      }
    }

    resolved.build();
    return resolved;
  };
  p.relativeTo = function(base) {
    var relative = this.clone().normalize();
    var relativeParts, baseParts, common, relativePath, basePath;

    if (relative._parts.urn) {
      throw new Error('URNs do not have any generally defined hierarchical components');
    }

    base = new URI(base).normalize();
    relativeParts = relative._parts;
    baseParts = base._parts;
    relativePath = relative.path();
    basePath = base.path();

    if (relativePath.charAt(0) !== '/') {
      throw new Error('URI is already relative');
    }

    if (basePath.charAt(0) !== '/') {
      throw new Error('Cannot calculate a URI relative to another relative URI');
    }

    if (relativeParts.protocol === baseParts.protocol) {
      relativeParts.protocol = null;
    }

    if (relativeParts.username !== baseParts.username || relativeParts.password !== baseParts.password) {
      return relative.build();
    }

    if (relativeParts.protocol !== null || relativeParts.username !== null || relativeParts.password !== null) {
      return relative.build();
    }

    if (relativeParts.hostname === baseParts.hostname && relativeParts.port === baseParts.port) {
      relativeParts.hostname = null;
      relativeParts.port = null;
    } else {
      return relative.build();
    }

    if (relativePath === basePath) {
      relativeParts.path = '';
      return relative.build();
    }

    // determine common sub path
    common = URI.commonPath(relativePath, basePath);

    // If the paths have nothing in common, return a relative URL with the absolute path.
    if (!common) {
      return relative.build();
    }

    var parents = baseParts.path
      .substring(common.length)
      .replace(/[^\/]*$/, '')
      .replace(/.*?\//g, '../');

    relativeParts.path = (parents + relativeParts.path.substring(common.length)) || './';

    return relative.build();
  };

  // comparing URIs
  p.equals = function(uri) {
    var one = this.clone();
    var two = new URI(uri);
    var one_map = {};
    var two_map = {};
    var checked = {};
    var one_query, two_query, key;

    one.normalize();
    two.normalize();

    // exact match
    if (one.toString() === two.toString()) {
      return true;
    }

    // extract query string
    one_query = one.query();
    two_query = two.query();
    one.query('');
    two.query('');

    // definitely not equal if not even non-query parts match
    if (one.toString() !== two.toString()) {
      return false;
    }

    // query parameters have the same length, even if they're permuted
    if (one_query.length !== two_query.length) {
      return false;
    }

    one_map = URI.parseQuery(one_query, this._parts.escapeQuerySpace);
    two_map = URI.parseQuery(two_query, this._parts.escapeQuerySpace);

    for (key in one_map) {
      if (hasOwn.call(one_map, key)) {
        if (!isArray(one_map[key])) {
          if (one_map[key] !== two_map[key]) {
            return false;
          }
        } else if (!arraysEqual(one_map[key], two_map[key])) {
          return false;
        }

        checked[key] = true;
      }
    }

    for (key in two_map) {
      if (hasOwn.call(two_map, key)) {
        if (!checked[key]) {
          // two contains a parameter not present in one
          return false;
        }
      }
    }

    return true;
  };

  // state
  p.preventInvalidHostname = function(v) {
    this._parts.preventInvalidHostname = !!v;
    return this;
  };

  p.duplicateQueryParameters = function(v) {
    this._parts.duplicateQueryParameters = !!v;
    return this;
  };

  p.escapeQuerySpace = function(v) {
    this._parts.escapeQuerySpace = !!v;
    return this;
  };

  return URI;
}));
;
/*! Magnific Popup - v1.1.0 - 2016-02-20
* http://dimsemenov.com/plugins/magnific-popup/
* Copyright (c) 2016 Dmitry Semenov; */
;(function (factory) { 
if (typeof define === 'function' && define.amd) { 
 // AMD. Register as an anonymous module. 
 define(['jquery'], factory); 
 } else if (typeof exports === 'object') { 
 // Node/CommonJS 
 factory(require('jquery')); 
 } else { 
 // Browser globals 
 factory(window.jQuery || window.Zepto); 
 } 
 }(function($) { 

/*>>core*/
/**
 * 
 * Magnific Popup Core JS file
 * 
 */


/**
 * Private static constants
 */
var CLOSE_EVENT = 'Close',
	BEFORE_CLOSE_EVENT = 'BeforeClose',
	AFTER_CLOSE_EVENT = 'AfterClose',
	BEFORE_APPEND_EVENT = 'BeforeAppend',
	MARKUP_PARSE_EVENT = 'MarkupParse',
	OPEN_EVENT = 'Open',
	CHANGE_EVENT = 'Change',
	NS = 'mfp',
	EVENT_NS = '.' + NS,
	READY_CLASS = 'mfp-ready',
	REMOVING_CLASS = 'mfp-removing',
	PREVENT_CLOSE_CLASS = 'mfp-prevent-close';


/**
 * Private vars 
 */
/*jshint -W079 */
var mfp, // As we have only one instance of MagnificPopup object, we define it locally to not to use 'this'
	MagnificPopup = function(){},
	_isJQ = !!(window.jQuery),
	_prevStatus,
	_window = $(window),
	_document,
	_prevContentType,
	_wrapClasses,
	_currPopupType;


/**
 * Private functions
 */
var _mfpOn = function(name, f) {
		mfp.ev.on(NS + name + EVENT_NS, f);
	},
	_getEl = function(className, appendTo, html, raw) {
		var el = document.createElement('div');
		el.className = 'mfp-'+className;
		if(html) {
			el.innerHTML = html;
		}
		if(!raw) {
			el = $(el);
			if(appendTo) {
				el.appendTo(appendTo);
			}
		} else if(appendTo) {
			appendTo.appendChild(el);
		}
		return el;
	},
	_mfpTrigger = function(e, data) {
		mfp.ev.triggerHandler(NS + e, data);

		if(mfp.st.callbacks) {
			// converts "mfpEventName" to "eventName" callback and triggers it if it's present
			e = e.charAt(0).toLowerCase() + e.slice(1);
			if(mfp.st.callbacks[e]) {
				mfp.st.callbacks[e].apply(mfp, $.isArray(data) ? data : [data]);
			}
		}
	},
	_getCloseBtn = function(type) {
		if(type !== _currPopupType || !mfp.currTemplate.closeBtn) {
			mfp.currTemplate.closeBtn = $( mfp.st.closeMarkup.replace('%title%', mfp.st.tClose ) );
			_currPopupType = type;
		}
		return mfp.currTemplate.closeBtn;
	},
	// Initialize Magnific Popup only when called at least once
	_checkInstance = function() {
		if(!$.magnificPopup.instance) {
			/*jshint -W020 */
			mfp = new MagnificPopup();
			mfp.init();
			$.magnificPopup.instance = mfp;
		}
	},
	// CSS transition detection, http://stackoverflow.com/questions/7264899/detect-css-transitions-using-javascript-and-without-modernizr
	supportsTransitions = function() {
		var s = document.createElement('p').style, // 's' for style. better to create an element if body yet to exist
			v = ['ms','O','Moz','Webkit']; // 'v' for vendor

		if( s['transition'] !== undefined ) {
			return true; 
		}
			
		while( v.length ) {
			if( v.pop() + 'Transition' in s ) {
				return true;
			}
		}
				
		return false;
	};



/**
 * Public functions
 */
MagnificPopup.prototype = {

	constructor: MagnificPopup,

	/**
	 * Initializes Magnific Popup plugin. 
	 * This function is triggered only once when $.fn.magnificPopup or $.magnificPopup is executed
	 */
	init: function() {
		var appVersion = navigator.appVersion;
		mfp.isLowIE = mfp.isIE8 = document.all && !document.addEventListener;
		mfp.isAndroid = (/android/gi).test(appVersion);
		mfp.isIOS = (/iphone|ipad|ipod/gi).test(appVersion);
		mfp.supportsTransition = supportsTransitions();

		// We disable fixed positioned lightbox on devices that don't handle it nicely.
		// If you know a better way of detecting this - let me know.
		mfp.probablyMobile = (mfp.isAndroid || mfp.isIOS || /(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent) );
		_document = $(document);

		mfp.popupsCache = {};
	},

	/**
	 * Opens popup
	 * @param  data [description]
	 */
	open: function(data) {

		var i;

		if(data.isObj === false) { 
			// convert jQuery collection to array to avoid conflicts later
			mfp.items = data.items.toArray();

			mfp.index = 0;
			var items = data.items,
				item;
			for(i = 0; i < items.length; i++) {
				item = items[i];
				if(item.parsed) {
					item = item.el[0];
				}
				if(item === data.el[0]) {
					mfp.index = i;
					break;
				}
			}
		} else {
			mfp.items = $.isArray(data.items) ? data.items : [data.items];
			mfp.index = data.index || 0;
		}

		// if popup is already opened - we just update the content
		if(mfp.isOpen) {
			mfp.updateItemHTML();
			return;
		}
		
		mfp.types = []; 
		_wrapClasses = '';
		if(data.mainEl && data.mainEl.length) {
			mfp.ev = data.mainEl.eq(0);
		} else {
			mfp.ev = _document;
		}

		if(data.key) {
			if(!mfp.popupsCache[data.key]) {
				mfp.popupsCache[data.key] = {};
			}
			mfp.currTemplate = mfp.popupsCache[data.key];
		} else {
			mfp.currTemplate = {};
		}



		mfp.st = $.extend(true, {}, $.magnificPopup.defaults, data ); 
		mfp.fixedContentPos = mfp.st.fixedContentPos === 'auto' ? !mfp.probablyMobile : mfp.st.fixedContentPos;

		if(mfp.st.modal) {
			mfp.st.closeOnContentClick = false;
			mfp.st.closeOnBgClick = false;
			mfp.st.showCloseBtn = false;
			mfp.st.enableEscapeKey = false;
		}
		

		// Building markup
		// main containers are created only once
		if(!mfp.bgOverlay) {

			// Dark overlay
			mfp.bgOverlay = _getEl('bg').on('click'+EVENT_NS, function() {
				mfp.close();
			});

			mfp.wrap = _getEl('wrap').attr('tabindex', -1).on('click'+EVENT_NS, function(e) {
				if(mfp._checkIfClose(e.target)) {
					mfp.close();
				}
			});

			mfp.container = _getEl('container', mfp.wrap);
		}

		mfp.contentContainer = _getEl('content');
		if(mfp.st.preloader) {
			mfp.preloader = _getEl('preloader', mfp.container, mfp.st.tLoading);
		}


		// Initializing modules
		var modules = $.magnificPopup.modules;
		for(i = 0; i < modules.length; i++) {
			var n = modules[i];
			n = n.charAt(0).toUpperCase() + n.slice(1);
			mfp['init'+n].call(mfp);
		}
		_mfpTrigger('BeforeOpen');


		if(mfp.st.showCloseBtn) {
			// Close button
			if(!mfp.st.closeBtnInside) {
				mfp.wrap.append( _getCloseBtn() );
			} else {
				_mfpOn(MARKUP_PARSE_EVENT, function(e, template, values, item) {
					values.close_replaceWith = _getCloseBtn(item.type);
				});
				_wrapClasses += ' mfp-close-btn-in';
			}
		}

		if(mfp.st.alignTop) {
			_wrapClasses += ' mfp-align-top';
		}

	

		if(mfp.fixedContentPos) {
			mfp.wrap.css({
				overflow: mfp.st.overflowY,
				overflowX: 'hidden',
				overflowY: mfp.st.overflowY
			});
		} else {
			mfp.wrap.css({ 
				top: _window.scrollTop(),
				position: 'absolute'
			});
		}
		if( mfp.st.fixedBgPos === false || (mfp.st.fixedBgPos === 'auto' && !mfp.fixedContentPos) ) {
			mfp.bgOverlay.css({
				height: _document.height(),
				position: 'absolute'
			});
		}

		

		if(mfp.st.enableEscapeKey) {
			// Close on ESC key
			_document.on('keyup' + EVENT_NS, function(e) {
				if(e.keyCode === 27) {
					mfp.close();
				}
			});
		}

		_window.on('resize' + EVENT_NS, function() {
			mfp.updateSize();
		});


		if(!mfp.st.closeOnContentClick) {
			_wrapClasses += ' mfp-auto-cursor';
		}
		
		if(_wrapClasses)
			mfp.wrap.addClass(_wrapClasses);


		// this triggers recalculation of layout, so we get it once to not to trigger twice
		var windowHeight = mfp.wH = _window.height();

		
		var windowStyles = {};

		if( mfp.fixedContentPos ) {
            if(mfp._hasScrollBar(windowHeight)){
                var s = mfp._getScrollbarSize();
                if(s) {
                    windowStyles.marginRight = s;
                }
            }
        }

		if(mfp.fixedContentPos) {
			if(!mfp.isIE7) {
				windowStyles.overflow = 'hidden';
			} else {
				// ie7 double-scroll bug
				$('body, html').css('overflow', 'hidden');
			}
		}

		
		
		var classesToadd = mfp.st.mainClass;
		if(mfp.isIE7) {
			classesToadd += ' mfp-ie7';
		}
		if(classesToadd) {
			mfp._addClassToMFP( classesToadd );
		}

		// add content
		mfp.updateItemHTML();

		_mfpTrigger('BuildControls');

		// remove scrollbar, add margin e.t.c
		$('html').css(windowStyles);
		
		// add everything to DOM
		mfp.bgOverlay.add(mfp.wrap).prependTo( mfp.st.prependTo || $(document.body) );

		// Save last focused element
		mfp._lastFocusedEl = document.activeElement;
		
		// Wait for next cycle to allow CSS transition
		setTimeout(function() {
			
			if(mfp.content) {
				mfp._addClassToMFP(READY_CLASS);
				mfp._setFocus();
			} else {
				// if content is not defined (not loaded e.t.c) we add class only for BG
				mfp.bgOverlay.addClass(READY_CLASS);
			}
			
			// Trap the focus in popup
			_document.on('focusin' + EVENT_NS, mfp._onFocusIn);

		}, 16);

		mfp.isOpen = true;
		mfp.updateSize(windowHeight);
		_mfpTrigger(OPEN_EVENT);

		return data;
	},

	/**
	 * Closes the popup
	 */
	close: function() {
		if(!mfp.isOpen) return;
		_mfpTrigger(BEFORE_CLOSE_EVENT);

		mfp.isOpen = false;
		// for CSS3 animation
		if(mfp.st.removalDelay && !mfp.isLowIE && mfp.supportsTransition )  {
			mfp._addClassToMFP(REMOVING_CLASS);
			setTimeout(function() {
				mfp._close();
			}, mfp.st.removalDelay);
		} else {
			mfp._close();
		}
	},

	/**
	 * Helper for close() function
	 */
	_close: function() {
		_mfpTrigger(CLOSE_EVENT);

		var classesToRemove = REMOVING_CLASS + ' ' + READY_CLASS + ' ';

		mfp.bgOverlay.detach();
		mfp.wrap.detach();
		mfp.container.empty();

		if(mfp.st.mainClass) {
			classesToRemove += mfp.st.mainClass + ' ';
		}

		mfp._removeClassFromMFP(classesToRemove);

		if(mfp.fixedContentPos) {
			var windowStyles = {marginRight: ''};
			if(mfp.isIE7) {
				$('body, html').css('overflow', '');
			} else {
				windowStyles.overflow = '';
			}
			$('html').css(windowStyles);
		}
		
		_document.off('keyup' + EVENT_NS + ' focusin' + EVENT_NS);
		mfp.ev.off(EVENT_NS);

		// clean up DOM elements that aren't removed
		mfp.wrap.attr('class', 'mfp-wrap').removeAttr('style');
		mfp.bgOverlay.attr('class', 'mfp-bg');
		mfp.container.attr('class', 'mfp-container');

		// remove close button from target element
		if(mfp.st.showCloseBtn &&
		(!mfp.st.closeBtnInside || mfp.currTemplate[mfp.currItem.type] === true)) {
			if(mfp.currTemplate.closeBtn)
				mfp.currTemplate.closeBtn.detach();
		}


		if(mfp.st.autoFocusLast && mfp._lastFocusedEl) {
			$(mfp._lastFocusedEl).focus(); // put tab focus back
		}
		mfp.currItem = null;	
		mfp.content = null;
		mfp.currTemplate = null;
		mfp.prevHeight = 0;

		_mfpTrigger(AFTER_CLOSE_EVENT);
	},
	
	updateSize: function(winHeight) {

		if(mfp.isIOS) {
			// fixes iOS nav bars https://github.com/dimsemenov/Magnific-Popup/issues/2
			var zoomLevel = document.documentElement.clientWidth / window.innerWidth;
			var height = window.innerHeight * zoomLevel;
			mfp.wrap.css('height', height);
			mfp.wH = height;
		} else {
			mfp.wH = winHeight || _window.height();
		}
		// Fixes #84: popup incorrectly positioned with position:relative on body
		if(!mfp.fixedContentPos) {
			mfp.wrap.css('height', mfp.wH);
		}

		_mfpTrigger('Resize');

	},

	/**
	 * Set content of popup based on current index
	 */
	updateItemHTML: function() {
		var item = mfp.items[mfp.index];

		// Detach and perform modifications
		mfp.contentContainer.detach();

		if(mfp.content)
			mfp.content.detach();

		if(!item.parsed) {
			item = mfp.parseEl( mfp.index );
		}

		var type = item.type;

		_mfpTrigger('BeforeChange', [mfp.currItem ? mfp.currItem.type : '', type]);
		// BeforeChange event works like so:
		// _mfpOn('BeforeChange', function(e, prevType, newType) { });

		mfp.currItem = item;

		if(!mfp.currTemplate[type]) {
			var markup = mfp.st[type] ? mfp.st[type].markup : false;

			// allows to modify markup
			_mfpTrigger('FirstMarkupParse', markup);

			if(markup) {
				mfp.currTemplate[type] = $(markup);
			} else {
				// if there is no markup found we just define that template is parsed
				mfp.currTemplate[type] = true;
			}
		}

		if(_prevContentType && _prevContentType !== item.type) {
			mfp.container.removeClass('mfp-'+_prevContentType+'-holder');
		}

		var newContent = mfp['get' + type.charAt(0).toUpperCase() + type.slice(1)](item, mfp.currTemplate[type]);
		mfp.appendContent(newContent, type);

		item.preloaded = true;

		_mfpTrigger(CHANGE_EVENT, item);
		_prevContentType = item.type;

		// Append container back after its content changed
		mfp.container.prepend(mfp.contentContainer);

		_mfpTrigger('AfterChange');
	},


	/**
	 * Set HTML content of popup
	 */
	appendContent: function(newContent, type) {
		mfp.content = newContent;

		if(newContent) {
			if(mfp.st.showCloseBtn && mfp.st.closeBtnInside &&
				mfp.currTemplate[type] === true) {
				// if there is no markup, we just append close button element inside
				if(!mfp.content.find('.mfp-close').length) {
					mfp.content.append(_getCloseBtn());
				}
			} else {
				mfp.content = newContent;
			}
		} else {
			mfp.content = '';
		}

		_mfpTrigger(BEFORE_APPEND_EVENT);
		mfp.container.addClass('mfp-'+type+'-holder');

		mfp.contentContainer.append(mfp.content);
	},


	/**
	 * Creates Magnific Popup data object based on given data
	 * @param  {int} index Index of item to parse
	 */
	parseEl: function(index) {
		var item = mfp.items[index],
			type;

		if(item.tagName) {
			item = { el: $(item) };
		} else {
			type = item.type;
			item = { data: item, src: item.src };
		}

		if(item.el) {
			var types = mfp.types;

			// check for 'mfp-TYPE' class
			for(var i = 0; i < types.length; i++) {
				if( item.el.hasClass('mfp-'+types[i]) ) {
					type = types[i];
					break;
				}
			}

			item.src = item.el.attr('data-mfp-src');
			if(!item.src) {
				item.src = item.el.attr('href');
			}
		}

		item.type = type || mfp.st.type || 'inline';
		item.index = index;
		item.parsed = true;
		mfp.items[index] = item;
		_mfpTrigger('ElementParse', item);

		return mfp.items[index];
	},


	/**
	 * Initializes single popup or a group of popups
	 */
	addGroup: function(el, options) {
		var eHandler = function(e) {
			e.mfpEl = this;
			mfp._openClick(e, el, options);
		};

		if(!options) {
			options = {};
		}

		var eName = 'click.magnificPopup';
		options.mainEl = el;

		if(options.items) {
			options.isObj = true;
			el.off(eName).on(eName, eHandler);
		} else {
			options.isObj = false;
			if(options.delegate) {
				el.off(eName).on(eName, options.delegate , eHandler);
			} else {
				options.items = el;
				el.off(eName).on(eName, eHandler);
			}
		}
	},
	_openClick: function(e, el, options) {
		var midClick = options.midClick !== undefined ? options.midClick : $.magnificPopup.defaults.midClick;


		if(!midClick && ( e.which === 2 || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey ) ) {
			return;
		}

		var disableOn = options.disableOn !== undefined ? options.disableOn : $.magnificPopup.defaults.disableOn;

		if(disableOn) {
			if($.isFunction(disableOn)) {
				if( !disableOn.call(mfp) ) {
					return true;
				}
			} else { // else it's number
				if( _window.width() < disableOn ) {
					return true;
				}
			}
		}

		if(e.type) {
			e.preventDefault();

			// This will prevent popup from closing if element is inside and popup is already opened
			if(mfp.isOpen) {
				e.stopPropagation();
			}
		}

		options.el = $(e.mfpEl);
		if(options.delegate) {
			options.items = el.find(options.delegate);
		}
		mfp.open(options);
	},


	/**
	 * Updates text on preloader
	 */
	updateStatus: function(status, text) {

		if(mfp.preloader) {
			if(_prevStatus !== status) {
				mfp.container.removeClass('mfp-s-'+_prevStatus);
			}

			if(!text && status === 'loading') {
				text = mfp.st.tLoading;
			}

			var data = {
				status: status,
				text: text
			};
			// allows to modify status
			_mfpTrigger('UpdateStatus', data);

			status = data.status;
			text = data.text;

			mfp.preloader.html(text);

			mfp.preloader.find('a').on('click', function(e) {
				e.stopImmediatePropagation();
			});

			mfp.container.addClass('mfp-s-'+status);
			_prevStatus = status;
		}
	},


	/*
		"Private" helpers that aren't private at all
	 */
	// Check to close popup or not
	// "target" is an element that was clicked
	_checkIfClose: function(target) {

		if($(target).hasClass(PREVENT_CLOSE_CLASS)) {
			return;
		}

		var closeOnContent = mfp.st.closeOnContentClick;
		var closeOnBg = mfp.st.closeOnBgClick;

		if(closeOnContent && closeOnBg) {
			return true;
		} else {

			// We close the popup if click is on close button or on preloader. Or if there is no content.
			if(!mfp.content || $(target).hasClass('mfp-close') || (mfp.preloader && target === mfp.preloader[0]) ) {
				return true;
			}

			// if click is outside the content
			if(  (target !== mfp.content[0] && !$.contains(mfp.content[0], target))  ) {
				if(closeOnBg) {
					// last check, if the clicked element is in DOM, (in case it's removed onclick)
					if( $.contains(document, target) ) {
						return true;
					}
				}
			} else if(closeOnContent) {
				return true;
			}

		}
		return false;
	},
	_addClassToMFP: function(cName) {
		mfp.bgOverlay.addClass(cName);
		mfp.wrap.addClass(cName);
	},
	_removeClassFromMFP: function(cName) {
		this.bgOverlay.removeClass(cName);
		mfp.wrap.removeClass(cName);
	},
	_hasScrollBar: function(winHeight) {
		return (  (mfp.isIE7 ? _document.height() : document.body.scrollHeight) > (winHeight || _window.height()) );
	},
	_setFocus: function() {
		(mfp.st.focus ? mfp.content.find(mfp.st.focus).eq(0) : mfp.wrap).focus();
	},
	_onFocusIn: function(e) {
		if( e.target !== mfp.wrap[0] && !$.contains(mfp.wrap[0], e.target) ) {
			mfp._setFocus();
			return false;
		}
	},
	_parseMarkup: function(template, values, item) {
		var arr;
		if(item.data) {
			values = $.extend(item.data, values);
		}
		_mfpTrigger(MARKUP_PARSE_EVENT, [template, values, item] );

		$.each(values, function(key, value) {
			if(value === undefined || value === false) {
				return true;
			}
			arr = key.split('_');
			if(arr.length > 1) {
				var el = template.find(EVENT_NS + '-'+arr[0]);

				if(el.length > 0) {
					var attr = arr[1];
					if(attr === 'replaceWith') {
						if(el[0] !== value[0]) {
							el.replaceWith(value);
						}
					} else if(attr === 'img') {
						if(el.is('img')) {
							el.attr('src', value);
						} else {
							el.replaceWith( $('<img>').attr('src', value).attr('class', el.attr('class')) );
						}
					} else {
						el.attr(arr[1], value);
					}
				}

			} else {
				template.find(EVENT_NS + '-'+key).html(value);
			}
		});
	},

	_getScrollbarSize: function() {
		// thx David
		if(mfp.scrollbarSize === undefined) {
			var scrollDiv = document.createElement("div");
			scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;';
			document.body.appendChild(scrollDiv);
			mfp.scrollbarSize = scrollDiv.offsetWidth - scrollDiv.clientWidth;
			document.body.removeChild(scrollDiv);
		}
		return mfp.scrollbarSize;
	}

}; /* MagnificPopup core prototype end */




/**
 * Public static functions
 */
$.magnificPopup = {
	instance: null,
	proto: MagnificPopup.prototype,
	modules: [],

	open: function(options, index) {
		_checkInstance();

		if(!options) {
			options = {};
		} else {
			options = $.extend(true, {}, options);
		}

		options.isObj = true;
		options.index = index || 0;
		return this.instance.open(options);
	},

	close: function() {
		return $.magnificPopup.instance && $.magnificPopup.instance.close();
	},

	registerModule: function(name, module) {
		if(module.options) {
			$.magnificPopup.defaults[name] = module.options;
		}
		$.extend(this.proto, module.proto);
		this.modules.push(name);
	},

	defaults: {

		// Info about options is in docs:
		// http://dimsemenov.com/plugins/magnific-popup/documentation.html#options

		disableOn: 0,

		key: null,

		midClick: false,

		mainClass: '',

		preloader: true,

		focus: '', // CSS selector of input to focus after popup is opened

		closeOnContentClick: false,

		closeOnBgClick: true,

		closeBtnInside: true,

		showCloseBtn: true,

		enableEscapeKey: true,

		modal: false,

		alignTop: false,

		removalDelay: 0,

		prependTo: null,

		fixedContentPos: 'auto',

		fixedBgPos: 'auto',

		overflowY: 'auto',

		closeMarkup: '<button title="%title%" type="button" class="mfp-close">&#215;</button>',

		tClose: 'Close (Esc)',

		tLoading: 'Loading...',

		autoFocusLast: true

	}
};



$.fn.magnificPopup = function(options) {
	_checkInstance();

	var jqEl = $(this);

	// We call some API method of first param is a string
	if (typeof options === "string" ) {

		if(options === 'open') {
			var items,
				itemOpts = _isJQ ? jqEl.data('magnificPopup') : jqEl[0].magnificPopup,
				index = parseInt(arguments[1], 10) || 0;

			if(itemOpts.items) {
				items = itemOpts.items[index];
			} else {
				items = jqEl;
				if(itemOpts.delegate) {
					items = items.find(itemOpts.delegate);
				}
				items = items.eq( index );
			}
			mfp._openClick({mfpEl:items}, jqEl, itemOpts);
		} else {
			if(mfp.isOpen)
				mfp[options].apply(mfp, Array.prototype.slice.call(arguments, 1));
		}

	} else {
		// clone options obj
		options = $.extend(true, {}, options);

		/*
		 * As Zepto doesn't support .data() method for objects
		 * and it works only in normal browsers
		 * we assign "options" object directly to the DOM element. FTW!
		 */
		if(_isJQ) {
			jqEl.data('magnificPopup', options);
		} else {
			jqEl[0].magnificPopup = options;
		}

		mfp.addGroup(jqEl, options);

	}
	return jqEl;
};

/*>>core*/

/*>>inline*/

var INLINE_NS = 'inline',
	_hiddenClass,
	_inlinePlaceholder,
	_lastInlineElement,
	_putInlineElementsBack = function() {
		if(_lastInlineElement) {
			_inlinePlaceholder.after( _lastInlineElement.addClass(_hiddenClass) ).detach();
			_lastInlineElement = null;
		}
	};

$.magnificPopup.registerModule(INLINE_NS, {
	options: {
		hiddenClass: 'hide', // will be appended with `mfp-` prefix
		markup: '',
		tNotFound: 'Content not found'
	},
	proto: {

		initInline: function() {
			mfp.types.push(INLINE_NS);

			_mfpOn(CLOSE_EVENT+'.'+INLINE_NS, function() {
				_putInlineElementsBack();
			});
		},

		getInline: function(item, template) {

			_putInlineElementsBack();

			if(item.src) {
				var inlineSt = mfp.st.inline,
					el = $(item.src);

				if(el.length) {

					// If target element has parent - we replace it with placeholder and put it back after popup is closed
					var parent = el[0].parentNode;
					if(parent && parent.tagName) {
						if(!_inlinePlaceholder) {
							_hiddenClass = inlineSt.hiddenClass;
							_inlinePlaceholder = _getEl(_hiddenClass);
							_hiddenClass = 'mfp-'+_hiddenClass;
						}
						// replace target inline element with placeholder
						_lastInlineElement = el.after(_inlinePlaceholder).detach().removeClass(_hiddenClass);
					}

					mfp.updateStatus('ready');
				} else {
					mfp.updateStatus('error', inlineSt.tNotFound);
					el = $('<div>');
				}

				item.inlineElement = el;
				return el;
			}

			mfp.updateStatus('ready');
			mfp._parseMarkup(template, {}, item);
			return template;
		}
	}
});

/*>>inline*/

/*>>ajax*/
var AJAX_NS = 'ajax',
	_ajaxCur,
	_removeAjaxCursor = function() {
		if(_ajaxCur) {
			$(document.body).removeClass(_ajaxCur);
		}
	},
	_destroyAjaxRequest = function() {
		_removeAjaxCursor();
		if(mfp.req) {
			mfp.req.abort();
		}
	};

$.magnificPopup.registerModule(AJAX_NS, {

	options: {
		settings: null,
		cursor: 'mfp-ajax-cur',
		tError: '<a href="%url%">The content</a> could not be loaded.'
	},

	proto: {
		initAjax: function() {
			mfp.types.push(AJAX_NS);
			_ajaxCur = mfp.st.ajax.cursor;

			_mfpOn(CLOSE_EVENT+'.'+AJAX_NS, _destroyAjaxRequest);
			_mfpOn('BeforeChange.' + AJAX_NS, _destroyAjaxRequest);
		},
		getAjax: function(item) {

			if(_ajaxCur) {
				$(document.body).addClass(_ajaxCur);
			}

			mfp.updateStatus('loading');

			var opts = $.extend({
				url: item.src,
				success: function(data, textStatus, jqXHR) {
					var temp = {
						data:data,
						xhr:jqXHR
					};

					_mfpTrigger('ParseAjax', temp);

					mfp.appendContent( $(temp.data), AJAX_NS );

					item.finished = true;

					_removeAjaxCursor();

					mfp._setFocus();

					setTimeout(function() {
						mfp.wrap.addClass(READY_CLASS);
					}, 16);

					mfp.updateStatus('ready');

					_mfpTrigger('AjaxContentAdded');
				},
				error: function() {
					_removeAjaxCursor();
					item.finished = item.loadError = true;
					mfp.updateStatus('error', mfp.st.ajax.tError.replace('%url%', item.src));
				}
			}, mfp.st.ajax.settings);

			mfp.req = $.ajax(opts);

			return '';
		}
	}
});

/*>>ajax*/

/*>>image*/
var _imgInterval,
	_getTitle = function(item) {
		if(item.data && item.data.title !== undefined)
			return item.data.title;

		var src = mfp.st.image.titleSrc;

		if(src) {
			if($.isFunction(src)) {
				return src.call(mfp, item);
			} else if(item.el) {
				return item.el.attr(src) || '';
			}
		}
		return '';
	};

$.magnificPopup.registerModule('image', {

	options: {
		markup: '<div class="mfp-figure">'+
					'<div class="mfp-close"></div>'+
					'<figure>'+
						'<div class="mfp-img"></div>'+
						'<figcaption>'+
							'<div class="mfp-bottom-bar">'+
								'<div class="mfp-title"></div>'+
								'<div class="mfp-counter"></div>'+
							'</div>'+
						'</figcaption>'+
					'</figure>'+
				'</div>',
		cursor: 'mfp-zoom-out-cur',
		titleSrc: 'title',
		verticalFit: true,
		tError: '<a href="%url%">The image</a> could not be loaded.'
	},

	proto: {
		initImage: function() {
			var imgSt = mfp.st.image,
				ns = '.image';

			mfp.types.push('image');

			_mfpOn(OPEN_EVENT+ns, function() {
				if(mfp.currItem.type === 'image' && imgSt.cursor) {
					$(document.body).addClass(imgSt.cursor);
				}
			});

			_mfpOn(CLOSE_EVENT+ns, function() {
				if(imgSt.cursor) {
					$(document.body).removeClass(imgSt.cursor);
				}
				_window.off('resize' + EVENT_NS);
			});

			_mfpOn('Resize'+ns, mfp.resizeImage);
			if(mfp.isLowIE) {
				_mfpOn('AfterChange', mfp.resizeImage);
			}
		},
		resizeImage: function() {
			var item = mfp.currItem;
			if(!item || !item.img) return;

			if(mfp.st.image.verticalFit) {
				var decr = 0;
				// fix box-sizing in ie7/8
				if(mfp.isLowIE) {
					decr = parseInt(item.img.css('padding-top'), 10) + parseInt(item.img.css('padding-bottom'),10);
				}
				item.img.css('max-height', mfp.wH-decr);
			}
		},
		_onImageHasSize: function(item) {
			if(item.img) {

				item.hasSize = true;

				if(_imgInterval) {
					clearInterval(_imgInterval);
				}

				item.isCheckingImgSize = false;

				_mfpTrigger('ImageHasSize', item);

				if(item.imgHidden) {
					if(mfp.content)
						mfp.content.removeClass('mfp-loading');

					item.imgHidden = false;
				}

			}
		},

		/**
		 * Function that loops until the image has size to display elements that rely on it asap
		 */
		findImageSize: function(item) {

			var counter = 0,
				img = item.img[0],
				mfpSetInterval = function(delay) {

					if(_imgInterval) {
						clearInterval(_imgInterval);
					}
					// decelerating interval that checks for size of an image
					_imgInterval = setInterval(function() {
						if(img.naturalWidth > 0) {
							mfp._onImageHasSize(item);
							return;
						}

						if(counter > 200) {
							clearInterval(_imgInterval);
						}

						counter++;
						if(counter === 3) {
							mfpSetInterval(10);
						} else if(counter === 40) {
							mfpSetInterval(50);
						} else if(counter === 100) {
							mfpSetInterval(500);
						}
					}, delay);
				};

			mfpSetInterval(1);
		},

		getImage: function(item, template) {

			var guard = 0,

				// image load complete handler
				onLoadComplete = function() {
					if(item) {
						if (item.img[0].complete) {
							item.img.off('.mfploader');

							if(item === mfp.currItem){
								mfp._onImageHasSize(item);

								mfp.updateStatus('ready');
							}

							item.hasSize = true;
							item.loaded = true;

							_mfpTrigger('ImageLoadComplete');

						}
						else {
							// if image complete check fails 200 times (20 sec), we assume that there was an error.
							guard++;
							if(guard < 200) {
								setTimeout(onLoadComplete,100);
							} else {
								onLoadError();
							}
						}
					}
				},

				// image error handler
				onLoadError = function() {
					if(item) {
						item.img.off('.mfploader');
						if(item === mfp.currItem){
							mfp._onImageHasSize(item);
							mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) );
						}

						item.hasSize = true;
						item.loaded = true;
						item.loadError = true;
					}
				},
				imgSt = mfp.st.image;


			var el = template.find('.mfp-img');
			if(el.length) {
				var img = document.createElement('img');
				img.className = 'mfp-img';
				if(item.el && item.el.find('img').length) {
					img.alt = item.el.find('img').attr('alt');
				}
				item.img = $(img).on('load.mfploader', onLoadComplete).on('error.mfploader', onLoadError);
				img.src = item.src;

				// without clone() "error" event is not firing when IMG is replaced by new IMG
				// TODO: find a way to avoid such cloning
				if(el.is('img')) {
					item.img = item.img.clone();
				}

				img = item.img[0];
				if(img.naturalWidth > 0) {
					item.hasSize = true;
				} else if(!img.width) {
					item.hasSize = false;
				}
			}

			mfp._parseMarkup(template, {
				title: _getTitle(item),
				img_replaceWith: item.img
			}, item);

			mfp.resizeImage();

			if(item.hasSize) {
				if(_imgInterval) clearInterval(_imgInterval);

				if(item.loadError) {
					template.addClass('mfp-loading');
					mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) );
				} else {
					template.removeClass('mfp-loading');
					mfp.updateStatus('ready');
				}
				return template;
			}

			mfp.updateStatus('loading');
			item.loading = true;

			if(!item.hasSize) {
				item.imgHidden = true;
				template.addClass('mfp-loading');
				mfp.findImageSize(item);
			}

			return template;
		}
	}
});

/*>>image*/

/*>>zoom*/
var hasMozTransform,
	getHasMozTransform = function() {
		if(hasMozTransform === undefined) {
			hasMozTransform = document.createElement('p').style.MozTransform !== undefined;
		}
		return hasMozTransform;
	};

$.magnificPopup.registerModule('zoom', {

	options: {
		enabled: false,
		easing: 'ease-in-out',
		duration: 300,
		opener: function(element) {
			return element.is('img') ? element : element.find('img');
		}
	},

	proto: {

		initZoom: function() {
			var zoomSt = mfp.st.zoom,
				ns = '.zoom',
				image;

			if(!zoomSt.enabled || !mfp.supportsTransition) {
				return;
			}

			var duration = zoomSt.duration,
				getElToAnimate = function(image) {
					var newImg = image.clone().removeAttr('style').removeAttr('class').addClass('mfp-animated-image'),
						transition = 'all '+(zoomSt.duration/1000)+'s ' + zoomSt.easing,
						cssObj = {
							position: 'fixed',
							zIndex: 9999,
							left: 0,
							top: 0,
							'-webkit-backface-visibility': 'hidden'
						},
						t = 'transition';

					cssObj['-webkit-'+t] = cssObj['-moz-'+t] = cssObj['-o-'+t] = cssObj[t] = transition;

					newImg.css(cssObj);
					return newImg;
				},
				showMainContent = function() {
					mfp.content.css('visibility', 'visible');
				},
				openTimeout,
				animatedImg;

			_mfpOn('BuildControls'+ns, function() {
				if(mfp._allowZoom()) {

					clearTimeout(openTimeout);
					mfp.content.css('visibility', 'hidden');

					// Basically, all code below does is clones existing image, puts in on top of the current one and animated it

					image = mfp._getItemToZoom();

					if(!image) {
						showMainContent();
						return;
					}

					animatedImg = getElToAnimate(image);

					animatedImg.css( mfp._getOffset() );

					mfp.wrap.append(animatedImg);

					openTimeout = setTimeout(function() {
						animatedImg.css( mfp._getOffset( true ) );
						openTimeout = setTimeout(function() {

							showMainContent();

							setTimeout(function() {
								animatedImg.remove();
								image = animatedImg = null;
								_mfpTrigger('ZoomAnimationEnded');
							}, 16); // avoid blink when switching images

						}, duration); // this timeout equals animation duration

					}, 16); // by adding this timeout we avoid short glitch at the beginning of animation


					// Lots of timeouts...
				}
			});
			_mfpOn(BEFORE_CLOSE_EVENT+ns, function() {
				if(mfp._allowZoom()) {

					clearTimeout(openTimeout);

					mfp.st.removalDelay = duration;

					if(!image) {
						image = mfp._getItemToZoom();
						if(!image) {
							return;
						}
						animatedImg = getElToAnimate(image);
					}

					animatedImg.css( mfp._getOffset(true) );
					mfp.wrap.append(animatedImg);
					mfp.content.css('visibility', 'hidden');

					setTimeout(function() {
						animatedImg.css( mfp._getOffset() );
					}, 16);
				}

			});

			_mfpOn(CLOSE_EVENT+ns, function() {
				if(mfp._allowZoom()) {
					showMainContent();
					if(animatedImg) {
						animatedImg.remove();
					}
					image = null;
				}
			});
		},

		_allowZoom: function() {
			return mfp.currItem.type === 'image';
		},

		_getItemToZoom: function() {
			if(mfp.currItem.hasSize) {
				return mfp.currItem.img;
			} else {
				return false;
			}
		},

		// Get element postion relative to viewport
		_getOffset: function(isLarge) {
			var el;
			if(isLarge) {
				el = mfp.currItem.img;
			} else {
				el = mfp.st.zoom.opener(mfp.currItem.el || mfp.currItem);
			}

			var offset = el.offset();
			var paddingTop = parseInt(el.css('padding-top'),10);
			var paddingBottom = parseInt(el.css('padding-bottom'),10);
			offset.top -= ( $(window).scrollTop() - paddingTop );


			/*

			Animating left + top + width/height looks glitchy in Firefox, but perfect in Chrome. And vice-versa.

			 */
			var obj = {
				width: el.width(),
				// fix Zepto height+padding issue
				height: (_isJQ ? el.innerHeight() : el[0].offsetHeight) - paddingBottom - paddingTop
			};

			// I hate to do this, but there is no another option
			if( getHasMozTransform() ) {
				obj['-moz-transform'] = obj['transform'] = 'translate(' + offset.left + 'px,' + offset.top + 'px)';
			} else {
				obj.left = offset.left;
				obj.top = offset.top;
			}
			return obj;
		}

	}
});



/*>>zoom*/

/*>>iframe*/

var IFRAME_NS = 'iframe',
	_emptyPage = '//about:blank',

	_fixIframeBugs = function(isShowing) {
		if(mfp.currTemplate[IFRAME_NS]) {
			var el = mfp.currTemplate[IFRAME_NS].find('iframe');
			if(el.length) {
				// reset src after the popup is closed to avoid "video keeps playing after popup is closed" bug
				if(!isShowing) {
					el[0].src = _emptyPage;
				}

				// IE8 black screen bug fix
				if(mfp.isIE8) {
					el.css('display', isShowing ? 'block' : 'none');
				}
			}
		}
	};

$.magnificPopup.registerModule(IFRAME_NS, {

	options: {
		markup: '<div class="mfp-iframe-scaler">'+
					'<div class="mfp-close"></div>'+
					'<iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe>'+
				'</div>',

		srcAction: 'iframe_src',

		// we don't care and support only one default type of URL by default
		patterns: {
			youtube: {
				index: 'youtube.com',
				id: 'v=',
				src: '//www.youtube.com/embed/%id%?autoplay=1'
			},
			vimeo: {
				index: 'vimeo.com/',
				id: '/',
				src: '//player.vimeo.com/video/%id%?autoplay=1'
			},
			gmaps: {
				index: '//maps.google.',
				src: '%id%&output=embed'
			}
		}
	},

	proto: {
		initIframe: function() {
			mfp.types.push(IFRAME_NS);

			_mfpOn('BeforeChange', function(e, prevType, newType) {
				if(prevType !== newType) {
					if(prevType === IFRAME_NS) {
						_fixIframeBugs(); // iframe if removed
					} else if(newType === IFRAME_NS) {
						_fixIframeBugs(true); // iframe is showing
					}
				}// else {
					// iframe source is switched, don't do anything
				//}
			});

			_mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() {
				_fixIframeBugs();
			});
		},

		getIframe: function(item, template) {
			var embedSrc = item.src;
			var iframeSt = mfp.st.iframe;

			$.each(iframeSt.patterns, function() {
				if(embedSrc.indexOf( this.index ) > -1) {
					if(this.id) {
						if(typeof this.id === 'string') {
							embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length);
						} else {
							embedSrc = this.id.call( this, embedSrc );
						}
					}
					embedSrc = this.src.replace('%id%', embedSrc );
					return false; // break;
				}
			});

			var dataObj = {};
			if(iframeSt.srcAction) {
				dataObj[iframeSt.srcAction] = embedSrc;
			}
			mfp._parseMarkup(template, dataObj, item);

			mfp.updateStatus('ready');

			return template;
		}
	}
});



/*>>iframe*/

/*>>gallery*/
/**
 * Get looped index depending on number of slides
 */
var _getLoopedId = function(index) {
		var numSlides = mfp.items.length;
		if(index > numSlides - 1) {
			return index - numSlides;
		} else  if(index < 0) {
			return numSlides + index;
		}
		return index;
	},
	_replaceCurrTotal = function(text, curr, total) {
		return text.replace(/%curr%/gi, curr + 1).replace(/%total%/gi, total);
	};

$.magnificPopup.registerModule('gallery', {

	options: {
		enabled: false,
		arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',
		preload: [0,2],
		navigateByImgClick: true,
		arrows: true,

		tPrev: 'Previous (Left arrow key)',
		tNext: 'Next (Right arrow key)',
		tCounter: '%curr% of %total%'
	},

	proto: {
		initGallery: function() {

			var gSt = mfp.st.gallery,
				ns = '.mfp-gallery';

			mfp.direction = true; // true - next, false - prev

			if(!gSt || !gSt.enabled ) return false;

			_wrapClasses += ' mfp-gallery';

			_mfpOn(OPEN_EVENT+ns, function() {

				if(gSt.navigateByImgClick) {
					mfp.wrap.on('click'+ns, '.mfp-img', function() {
						if(mfp.items.length > 1) {
							mfp.next();
							return false;
						}
					});
				}

				_document.on('keydown'+ns, function(e) {
					if (e.keyCode === 37) {
						mfp.prev();
					} else if (e.keyCode === 39) {
						mfp.next();
					}
				});
			});

			_mfpOn('UpdateStatus'+ns, function(e, data) {
				if(data.text) {
					data.text = _replaceCurrTotal(data.text, mfp.currItem.index, mfp.items.length);
				}
			});

			_mfpOn(MARKUP_PARSE_EVENT+ns, function(e, element, values, item) {
				var l = mfp.items.length;
				values.counter = l > 1 ? _replaceCurrTotal(gSt.tCounter, item.index, l) : '';
			});

			_mfpOn('BuildControls' + ns, function() {
				if(mfp.items.length > 1 && gSt.arrows && !mfp.arrowLeft) {
					var markup = gSt.arrowMarkup,
						arrowLeft = mfp.arrowLeft = $( markup.replace(/%title%/gi, gSt.tPrev).replace(/%dir%/gi, 'left') ).addClass(PREVENT_CLOSE_CLASS),
						arrowRight = mfp.arrowRight = $( markup.replace(/%title%/gi, gSt.tNext).replace(/%dir%/gi, 'right') ).addClass(PREVENT_CLOSE_CLASS);

					arrowLeft.click(function() {
						mfp.prev();
					});
					arrowRight.click(function() {
						mfp.next();
					});

					mfp.container.append(arrowLeft.add(arrowRight));
				}
			});

			_mfpOn(CHANGE_EVENT+ns, function() {
				if(mfp._preloadTimeout) clearTimeout(mfp._preloadTimeout);

				mfp._preloadTimeout = setTimeout(function() {
					mfp.preloadNearbyImages();
					mfp._preloadTimeout = null;
				}, 16);
			});


			_mfpOn(CLOSE_EVENT+ns, function() {
				_document.off(ns);
				mfp.wrap.off('click'+ns);
				mfp.arrowRight = mfp.arrowLeft = null;
			});

		},
		next: function() {
			mfp.direction = true;
			mfp.index = _getLoopedId(mfp.index + 1);
			mfp.updateItemHTML();
		},
		prev: function() {
			mfp.direction = false;
			mfp.index = _getLoopedId(mfp.index - 1);
			mfp.updateItemHTML();
		},
		goTo: function(newIndex) {
			mfp.direction = (newIndex >= mfp.index);
			mfp.index = newIndex;
			mfp.updateItemHTML();
		},
		preloadNearbyImages: function() {
			var p = mfp.st.gallery.preload,
				preloadBefore = Math.min(p[0], mfp.items.length),
				preloadAfter = Math.min(p[1], mfp.items.length),
				i;

			for(i = 1; i <= (mfp.direction ? preloadAfter : preloadBefore); i++) {
				mfp._preloadItem(mfp.index+i);
			}
			for(i = 1; i <= (mfp.direction ? preloadBefore : preloadAfter); i++) {
				mfp._preloadItem(mfp.index-i);
			}
		},
		_preloadItem: function(index) {
			index = _getLoopedId(index);

			if(mfp.items[index].preloaded) {
				return;
			}

			var item = mfp.items[index];
			if(!item.parsed) {
				item = mfp.parseEl( index );
			}

			_mfpTrigger('LazyLoad', item);

			if(item.type === 'image') {
				item.img = $('<img class="mfp-img" />').on('load.mfploader', function() {
					item.hasSize = true;
				}).on('error.mfploader', function() {
					item.hasSize = true;
					item.loadError = true;
					_mfpTrigger('LazyLoadError', item);
				}).attr('src', item.src);
			}


			item.preloaded = true;
		}
	}
});

/*>>gallery*/

/*>>retina*/

var RETINA_NS = 'retina';

$.magnificPopup.registerModule(RETINA_NS, {
	options: {
		replaceSrc: function(item) {
			return item.src.replace(/\.\w+$/, function(m) { return '@2x' + m; });
		},
		ratio: 1 // Function or number.  Set to 1 to disable.
	},
	proto: {
		initRetina: function() {
			if(window.devicePixelRatio > 1) {

				var st = mfp.st.retina,
					ratio = st.ratio;

				ratio = !isNaN(ratio) ? ratio : ratio();

				if(ratio > 1) {
					_mfpOn('ImageHasSize' + '.' + RETINA_NS, function(e, item) {
						item.img.css({
							'max-width': item.img[0].naturalWidth / ratio,
							'width': '100%'
						});
					});
					_mfpOn('ElementParse' + '.' + RETINA_NS, function(e, item) {
						item.src = st.replaceSrc(item, ratio);
					});
				}
			}

		}
	}
});

/*>>retina*/
 _checkInstance(); }));;
/*!
 * accounting.js v0.4.1
 * Copyright 2014 Open Exchange Rates
 *
 * Freely distributable under the MIT license.
 * Portions of accounting.js are inspired or borrowed from underscore.js
 *
 * Full details and documentation:
 * http://openexchangerates.github.io/accounting.js/
 */

(function(root, undefined) {

	/* --- Setup --- */

	// Create the local library object, to be exported or referenced globally later
	var lib = {};

	// Current version
	lib.version = '0.4.1';


	/* --- Exposed settings --- */

	// The library's settings configuration object. Contains default parameters for
	// currency and number formatting
	lib.settings = {
		currency: {
			symbol : "$",		// default currency symbol is '$'
			format : "%s%v",	// controls output: %s = symbol, %v = value (can be object, see docs)
			decimal : ".",		// decimal point separator
			thousand : ",",		// thousands separator
			precision : 2,		// decimal places
			grouping : 3		// digit grouping (not implemented yet)
		},
		number: {
			precision : 0,		// default precision on numbers is 0
			grouping : 3,		// digit grouping (not implemented yet)
			thousand : ",",
			decimal : "."
		}
	};


	/* --- Internal Helper Methods --- */

	// Store reference to possibly-available ECMAScript 5 methods for later
	var nativeMap = Array.prototype.map,
		nativeIsArray = Array.isArray,
		toString = Object.prototype.toString;

	/**
	 * Tests whether supplied parameter is a string
	 * from underscore.js
	 */
	function isString(obj) {
		return !!(obj === '' || (obj && obj.charCodeAt && obj.substr));
	}

	/**
	 * Tests whether supplied parameter is a string
	 * from underscore.js, delegates to ECMA5's native Array.isArray
	 */
	function isArray(obj) {
		return nativeIsArray ? nativeIsArray(obj) : toString.call(obj) === '[object Array]';
	}

	/**
	 * Tests whether supplied parameter is a true object
	 */
	function isObject(obj) {
		return obj && toString.call(obj) === '[object Object]';
	}

	/**
	 * Extends an object with a defaults object, similar to underscore's _.defaults
	 *
	 * Used for abstracting parameter handling from API methods
	 */
	function defaults(object, defs) {
		var key;
		object = object || {};
		defs = defs || {};
		// Iterate over object non-prototype properties:
		for (key in defs) {
			if (defs.hasOwnProperty(key)) {
				// Replace values with defaults only if undefined (allow empty/zero values):
				if (object[key] == null) object[key] = defs[key];
			}
		}
		return object;
	}

	/**
	 * Implementation of `Array.map()` for iteration loops
	 *
	 * Returns a new Array as a result of calling `iterator` on each array value.
	 * Defers to native Array.map if available
	 */
	function map(obj, iterator, context) {
		var results = [], i, j;

		if (!obj) return results;

		// Use native .map method if it exists:
		if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);

		// Fallback for native .map:
		for (i = 0, j = obj.length; i < j; i++ ) {
			results[i] = iterator.call(context, obj[i], i, obj);
		}
		return results;
	}

	/**
	 * Check and normalise the value of precision (must be positive integer)
	 */
	function checkPrecision(val, base) {
		val = Math.round(Math.abs(val));
		return isNaN(val)? base : val;
	}


	/**
	 * Parses a format string or object and returns format obj for use in rendering
	 *
	 * `format` is either a string with the default (positive) format, or object
	 * containing `pos` (required), `neg` and `zero` values (or a function returning
	 * either a string or object)
	 *
	 * Either string or format.pos must contain "%v" (value) to be valid
	 */
	function checkCurrencyFormat(format) {
		var defaults = lib.settings.currency.format;

		// Allow function as format parameter (should return string or object):
		if ( typeof format === "function" ) format = format();

		// Format can be a string, in which case `value` ("%v") must be present:
		if ( isString( format ) && format.match("%v") ) {

			// Create and return positive, negative and zero formats:
			return {
				pos : format,
				neg : format.replace("-", "").replace("%v", "-%v"),
				zero : format
			};

		// If no format, or object is missing valid positive value, use defaults:
		} else if ( !format || !format.pos || !format.pos.match("%v") ) {

			// If defaults is a string, casts it to an object for faster checking next time:
			return ( !isString( defaults ) ) ? defaults : lib.settings.currency.format = {
				pos : defaults,
				neg : defaults.replace("%v", "-%v"),
				zero : defaults
			};

		}
		// Otherwise, assume format was fine:
		return format;
	}


	/* --- API Methods --- */

	/**
	 * Takes a string/array of strings, removes all formatting/cruft and returns the raw float value
	 * Alias: `accounting.parse(string)`
	 *
	 * Decimal must be included in the regular expression to match floats (defaults to
	 * accounting.settings.number.decimal), so if the number uses a non-standard decimal 
	 * separator, provide it as the second argument.
	 *
	 * Also matches bracketed negatives (eg. "$ (1.99)" => -1.99)
	 *
	 * Doesn't throw any errors (`NaN`s become 0) but this may change in future
	 */
	var unformat = lib.unformat = lib.parse = function(value, decimal) {
		// Recursively unformat arrays:
		if (isArray(value)) {
			return map(value, function(val) {
				return unformat(val, decimal);
			});
		}

		// Fails silently (need decent errors):
		value = value || 0;

		// Return the value as-is if it's already a number:
		if (typeof value === "number") return value;

		// Default decimal point comes from settings, but could be set to eg. "," in opts:
		decimal = decimal || lib.settings.number.decimal;

		 // Build regex to strip out everything except digits, decimal point and minus sign:
		var regex = new RegExp("[^0-9-" + decimal + "]", ["g"]),
			unformatted = parseFloat(
				("" + value)
				.replace(/\((.*)\)/, "-$1") // replace bracketed values with negatives
				.replace(regex, '')         // strip out any cruft
				.replace(decimal, '.')      // make sure decimal point is standard
			);

		// This will fail silently which may cause trouble, let's wait and see:
		return !isNaN(unformatted) ? unformatted : 0;
	};


	/**
	 * Implementation of toFixed() that treats floats more like decimals
	 *
	 * Fixes binary rounding issues (eg. (0.615).toFixed(2) === "0.61") that present
	 * problems for accounting- and finance-related software.
	 */
	var toFixed = lib.toFixed = function(value, precision) {
		precision = checkPrecision(precision, lib.settings.number.precision);
		var power = Math.pow(10, precision);

		// Multiply up by precision, round accurately, then divide and use native toFixed():
		return (Math.round(lib.unformat(value) * power) / power).toFixed(precision);
	};


	/**
	 * Format a number, with comma-separated thousands and custom precision/decimal places
	 * Alias: `accounting.format()`
	 *
	 * Localise by overriding the precision and thousand / decimal separators
	 * 2nd parameter `precision` can be an object matching `settings.number`
	 */
	var formatNumber = lib.formatNumber = lib.format = function(number, precision, thousand, decimal) {
		// Resursively format arrays:
		if (isArray(number)) {
			return map(number, function(val) {
				return formatNumber(val, precision, thousand, decimal);
			});
		}

		// Clean up number:
		number = unformat(number);

		// Build options object from second param (if object) or all params, extending defaults:
		var opts = defaults(
				(isObject(precision) ? precision : {
					precision : precision,
					thousand : thousand,
					decimal : decimal
				}),
				lib.settings.number
			),

			// Clean up precision
			usePrecision = checkPrecision(opts.precision),

			// Do some calc:
			negative = number < 0 ? "-" : "",
			base = parseInt(toFixed(Math.abs(number || 0), usePrecision), 10) + "",
			mod = base.length > 3 ? base.length % 3 : 0;

		// Format the number:
		return negative + (mod ? base.substr(0, mod) + opts.thousand : "") + base.substr(mod).replace(/(\d{3})(?=\d)/g, "$1" + opts.thousand) + (usePrecision ? opts.decimal + toFixed(Math.abs(number), usePrecision).split('.')[1] : "");
	};


	/**
	 * Format a number into currency
	 *
	 * Usage: accounting.formatMoney(number, symbol, precision, thousandsSep, decimalSep, format)
	 * defaults: (0, "$", 2, ",", ".", "%s%v")
	 *
	 * Localise by overriding the symbol, precision, thousand / decimal separators and format
	 * Second param can be an object matching `settings.currency` which is the easiest way.
	 *
	 * To do: tidy up the parameters
	 */
	var formatMoney = lib.formatMoney = function(number, symbol, precision, thousand, decimal, format) {
		// Resursively format arrays:
		if (isArray(number)) {
			return map(number, function(val){
				return formatMoney(val, symbol, precision, thousand, decimal, format);
			});
		}

		// Clean up number:
		number = unformat(number);

		// Build options object from second param (if object) or all params, extending defaults:
		var opts = defaults(
				(isObject(symbol) ? symbol : {
					symbol : symbol,
					precision : precision,
					thousand : thousand,
					decimal : decimal,
					format : format
				}),
				lib.settings.currency
			),

			// Check format (returns object with pos, neg and zero):
			formats = checkCurrencyFormat(opts.format),

			// Choose which format to use for this value:
			useFormat = number > 0 ? formats.pos : number < 0 ? formats.neg : formats.zero;

		// Return with currency symbol added:
		return useFormat.replace('%s', opts.symbol).replace('%v', formatNumber(Math.abs(number), checkPrecision(opts.precision), opts.thousand, opts.decimal));
	};


	/**
	 * Format a list of numbers into an accounting column, padding with whitespace
	 * to line up currency symbols, thousand separators and decimals places
	 *
	 * List should be an array of numbers
	 * Second parameter can be an object containing keys that match the params
	 *
	 * Returns array of accouting-formatted number strings of same length
	 *
	 * NB: `white-space:pre` CSS rule is required on the list container to prevent
	 * browsers from collapsing the whitespace in the output strings.
	 */
	lib.formatColumn = function(list, symbol, precision, thousand, decimal, format) {
		if (!list) return [];

		// Build options object from second param (if object) or all params, extending defaults:
		var opts = defaults(
				(isObject(symbol) ? symbol : {
					symbol : symbol,
					precision : precision,
					thousand : thousand,
					decimal : decimal,
					format : format
				}),
				lib.settings.currency
			),

			// Check format (returns object with pos, neg and zero), only need pos for now:
			formats = checkCurrencyFormat(opts.format),

			// Whether to pad at start of string or after currency symbol:
			padAfterSymbol = formats.pos.indexOf("%s") < formats.pos.indexOf("%v") ? true : false,

			// Store value for the length of the longest string in the column:
			maxLength = 0,

			// Format the list according to options, store the length of the longest string:
			formatted = map(list, function(val, i) {
				if (isArray(val)) {
					// Recursively format columns if list is a multi-dimensional array:
					return lib.formatColumn(val, opts);
				} else {
					// Clean up the value
					val = unformat(val);

					// Choose which format to use for this value (pos, neg or zero):
					var useFormat = val > 0 ? formats.pos : val < 0 ? formats.neg : formats.zero,

						// Format this value, push into formatted list and save the length:
						fVal = useFormat.replace('%s', opts.symbol).replace('%v', formatNumber(Math.abs(val), checkPrecision(opts.precision), opts.thousand, opts.decimal));

					if (fVal.length > maxLength) maxLength = fVal.length;
					return fVal;
				}
			});

		// Pad each number in the list and send back the column of numbers:
		return map(formatted, function(val, i) {
			// Only if this is a string (not a nested array, which would have already been padded):
			if (isString(val) && val.length < maxLength) {
				// Depending on symbol position, pad after symbol or at index 0:
				return padAfterSymbol ? val.replace(opts.symbol, opts.symbol+(new Array(maxLength - val.length + 1).join(" "))) : (new Array(maxLength - val.length + 1).join(" ")) + val;
			}
			return val;
		});
	};


	/* --- Module Definition --- */

	// Export accounting for CommonJS. If being loaded as an AMD module, define it as such.
	// Otherwise, just add `accounting` to the global object
	if (typeof exports !== 'undefined') {
		if (typeof module !== 'undefined' && module.exports) {
			exports = module.exports = lib;
		}
		exports.accounting = lib;
	} else if (typeof define === 'function' && define.amd) {
		// Return the library as an AMD module:
		define([], function() {
			return lib;
		});
	} else {
		// Use accounting.noConflict to restore `accounting` back to its original value.
		// Returns a reference to the library's `accounting` object;
		// e.g. `var numbers = accounting.noConflict();`
		lib.noConflict = (function(oldAccounting) {
			return function() {
				// Reset the value of the root's `accounting` variable:
				root.accounting = oldAccounting;
				// Delete the noConflict method:
				lib.noConflict = undefined;
				// Return reference to the library to re-assign it:
				return lib;
			};
		})(root.accounting);

		// Declare `fx` on the root (global/window) object:
		root['accounting'] = lib;
	}

	// Root will be `window` in browser or `global` on the server:
}(this));
;
(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory();
	else if(typeof define === 'function' && define.amd)
		define([], factory);
	else if(typeof exports === 'object')
		exports["AutoNumeric"] = factory();
	else
		root["AutoNumeric"] = factory();
})(window, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/
/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId]) {
/******/ 			return installedModules[moduleId].exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			i: moduleId,
/******/ 			l: false,
/******/ 			exports: {}
/******/ 		};
/******/
/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ 		// Flag the module as loaded
/******/ 		module.l = true;
/******/
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/
/******/
/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;
/******/
/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;
/******/
/******/ 	// define getter function for harmony exports
/******/ 	__webpack_require__.d = function(exports, name, getter) {
/******/ 		if(!__webpack_require__.o(exports, name)) {
/******/ 			Object.defineProperty(exports, name, {
/******/ 				configurable: false,
/******/ 				enumerable: true,
/******/ 				get: getter
/******/ 			});
/******/ 		}
/******/ 	};
/******/
/******/ 	// define __esModule on exports
/******/ 	__webpack_require__.r = function(exports) {
/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
/******/ 	};
/******/
/******/ 	// getDefaultExport function for compatibility with non-harmony modules
/******/ 	__webpack_require__.n = function(module) {
/******/ 		var getter = module && module.__esModule ?
/******/ 			function getDefault() { return module['default']; } :
/******/ 			function getModuleExports() { return module; };
/******/ 		__webpack_require__.d(getter, 'a', getter);
/******/ 		return getter;
/******/ 	};
/******/
/******/ 	// Object.prototype.hasOwnProperty.call
/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";
/******/
/******/
/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(__webpack_require__.s = "./src/main.js");
/******/ })
/************************************************************************/
/******/ ({

/***/ "./src/AutoNumeric.js":
/*!****************************!*\
  !*** ./src/AutoNumeric.js ***!
  \****************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

"use strict";
eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n    value: true\n});\n\nvar _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\"); } }; }();\n\nvar _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *               AutoNumeric.js\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @version      4.4.0\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @date         2018-08-04 UTC 07:44\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @authors      Bob Knothe, Alexandre Bonneau\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @contributors Sokolov Yura and others, cf. AUTHORS\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @copyright    2009 Robert J. Knothe\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @since        2009-08-09\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @summary      autoNumeric is a standalone Javascript library\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *               that provides live *as-you-type* formatting for\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *               international numbers and currencies.\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @link         http://autonumeric.org\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *               Note : Some functions are borrowed from big.js\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @see          https://github.com/MikeMcl/big.js/\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * Please report any bugs to https://github.com/autoNumeric/autoNumeric\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @license      Released under the MIT License\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @link         http://www.opensource.org/licenses/mit-license.php\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * Permission is hereby granted, free of charge, to any person\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * obtaining a copy of this software and associated documentation\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * files (the \"Software\"), to deal in the Software without\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * restriction, including without limitation the rights to use,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * copy, modify, merge, publish, distribute, sub license, and/or sell\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * copies of the Software, and to permit persons to whom the\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * Software is furnished to do so, subject to the following\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * conditions:\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * The above copyright notice and this permission notice shall be\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * included in all copies or substantial portions of the Software.\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * OTHER DEALINGS IN THE SOFTWARE.\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      */\n\n//TODO Prevent having to enter relative path in the js files (ie. using `./AutoNumericHelper` instead of just `AutoNumericHelper`) (cf. http://moduscreate.com/es6-es2015-import-no-relative-path-webpack/)\n\n\nvar _AutoNumericHelper = __webpack_require__(/*! ./AutoNumericHelper */ \"./src/AutoNumericHelper.js\");\n\nvar _AutoNumericHelper2 = _interopRequireDefault(_AutoNumericHelper);\n\nvar _AutoNumericEnum = __webpack_require__(/*! ./AutoNumericEnum */ \"./src/AutoNumericEnum.js\");\n\nvar _AutoNumericEnum2 = _interopRequireDefault(_AutoNumericEnum);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _toConsumableArray(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); } }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n/**\n * Class declaration for the AutoNumeric object.\n *\n * An AutoNumeric element is an object wrapper that keeps a reference to the DOM element it manages (usually an <input> one), and provides autoNumeric-specific variables and functions.\n */\nvar AutoNumeric = function () {\n    /**\n     * Initialize the AutoNumeric object onto the given DOM element, and attach the settings and related event listeners to it.\n     * The options passed as a parameter is an object that contains the settings (ie. {digitGroupSeparator: \".\", decimalCharacter: \",\", currencySymbol: '€ '})\n     *\n     * @example\n     * anElement = new AutoNumeric(domElement); // With the default options\n     * anElement = new AutoNumeric(domElement, { options }); // With one option object\n     * anElement = new AutoNumeric(domElement, 'euroPos'); // With a named pre-defined string\n     * anElement = new AutoNumeric(domElement, [{ options1 }, 'euroPos', { options2 }]); // With multiple option objects (the latest option overwriting the previous ones)\n     * anElement = new AutoNumeric(domElement, null, { options }); // With one option object, and a failed initial value\n     * anElement = new AutoNumeric(domElement).french(); // With one pre-defined language object\n     * anElement = new AutoNumeric(domElement).french({ options });// With one pre-defined language object and additional options that will override the defaults\n     *\n     * // ...or init and set the value in one call :\n     * anElement = new AutoNumeric(domElement, 12345.789); // With the default options, and an initial value\n     * anElement = new AutoNumeric(domElement, 12345.789, { options });\n     * anElement = new AutoNumeric(domElement, '12345.789', { options });\n     * anElement = new AutoNumeric(domElement, 12345.789, 'euroPos');\n     * anElement = new AutoNumeric(domElement, 12345.789, [{ options1 }, 'euroPos', { options2 }]);\n     * anElement = new AutoNumeric(domElement, 12345.789).french({ options });\n     * anElement = new AutoNumeric(domElement, 12345.789, { options }).french({ options }); // Not really helpful, but possible\n     *\n     * // The AutoNumeric constructor class can also accept a string as a css selector. Under the hood this use `QuerySelector` and limit itself to only the first element it finds.\n     * anElement = new AutoNumeric('.myCssClass > input');\n     * anElement = new AutoNumeric('.myCssClass > input', { options });\n     * anElement = new AutoNumeric('.myCssClass > input', 'euroPos');\n     * anElement = new AutoNumeric('.myCssClass > input', [{ options1 }, 'euroPos', { options2 }]);\n     * anElement = new AutoNumeric('.myCssClass > input', 12345.789);\n     * anElement = new AutoNumeric('.myCssClass > input', 12345.789, { options });\n     * anElement = new AutoNumeric('.myCssClass > input', 12345.789, 'euroPos');\n     * anElement = new AutoNumeric('.myCssClass > input', 12345.789, [{ options1 }, 'euroPos', { options2 }]);\n     * anElement = new AutoNumeric('.myCssClass > input', null, { options }); // With a failed initial value\n     * anElement = new AutoNumeric('.myCssClass > input', 12345.789).french({ options });\n     *\n     * @param {object|Array|number|string} arg1\n     * @param {object|Array|number|string|null} arg2\n     * @param {object|Array|number|string|null} arg3\n     * @throws\n     */\n    function AutoNumeric() {\n        var arg1 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n        var _this = this;\n\n        var arg2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n        var arg3 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\n        _classCallCheck(this, AutoNumeric);\n\n        // --------------------------------------------------------\n        // -------------- Initialization\n        // Initialize the arguments\n        var _AutoNumeric$_setArgu = AutoNumeric._setArgumentsValues(arg1, arg2, arg3),\n            domElement = _AutoNumeric$_setArgu.domElement,\n            initialValue = _AutoNumeric$_setArgu.initialValue,\n            userOptions = _AutoNumeric$_setArgu.userOptions;\n\n        // Initialize the element\n\n\n        this.domElement = domElement;\n\n        // Generate the settings\n        this.defaultRawValue = ''; // The default raw value to set when initializing an AutoNumeric object\n        this._setSettings(userOptions, false);\n        //TODO If `styleRules` is not null, add by default a class 'autoNumeric' that adds transition to color, background-color, border-color properties\n        // Check if the DOM element is supported\n        this._checkElement();\n\n        // Store the additional attributes inside the AutoNumeric object\n        // Note: This variable is needed and not a duplicate of `initialValueOnKeydown` nor `valueOnFocus` since it serves a different purpose and has a different lifecycle\n        this.savedCancellableValue = null;\n\n        // Initialize the undo/redo variables\n        this.historyTable = []; // Keep track of *all* valid states of the element value\n        this.historyTableIndex = -1; // Pointer to the current undo/redo state. This will be set to '0' during initialization since it first adds itself.\n        this.onGoingRedo = false; // Variable that keeps track if a 'redo' is ongoing (in order to prevent an 'undo' to be launch when releasing the shift key before the ctrl key after a 'redo' shortcut)\n\n        // Initialize the parent form element, if any\n        this.parentForm = this._getParentForm();\n\n        // Set the initial value if it exists and if the `formatOnPageLoad` option will allow it\n        if (!this.runOnce && this.settings.formatOnPageLoad) {\n            // Format the element value if needed\n            this._formatDefaultValueOnPageLoad(initialValue);\n        } else {\n            // Otherwise set the `rawValue` and the element value, but do not format the latter yet\n            var valueToSet = void 0;\n            if (_AutoNumericHelper2.default.isNull(initialValue)) {\n                switch (this.settings.emptyInputBehavior) {\n                    case AutoNumeric.options.emptyInputBehavior.min:\n                        valueToSet = this.settings.minimumValue;\n                        break;\n                    case AutoNumeric.options.emptyInputBehavior.max:\n                        valueToSet = this.settings.maximumValue;\n                        break;\n                    case AutoNumeric.options.emptyInputBehavior.zero:\n                        valueToSet = '0';\n                        break;\n                    // In order to stay consistent when `formatOnPageLoad` is set to `true`, it's still impossible to set the `null` value as the initial value\n                    case AutoNumeric.options.emptyInputBehavior.focus:\n                    case AutoNumeric.options.emptyInputBehavior.press:\n                    case AutoNumeric.options.emptyInputBehavior.always:\n                    case AutoNumeric.options.emptyInputBehavior.null:\n                        valueToSet = '';\n                        break;\n                    // When `emptyInputBehavior` is a number or a string representing a number\n                    default:\n                        valueToSet = this.settings.emptyInputBehavior;\n                }\n            } else {\n                valueToSet = initialValue;\n            }\n\n            this._setElementAndRawValue(valueToSet);\n        }\n\n        this.runOnce = true;\n\n        // Add the events listeners only on input or editable elements\n        this.hasEventListeners = false;\n        if (this.isInputElement || this.isContentEditable) {\n            if (!this.settings.noEventListeners) {\n                //XXX Here we make sure the global list is created after creating the event listeners, to only create the event listeners on `document` once\n                this._createEventListeners();\n            }\n\n            this._setWritePermissions();\n        }\n\n        // Save the initial values (html attribute + element.value) for the pristine test\n        this._saveInitialValues(initialValue);\n\n        // Setup the data for the persistent storage solution (ie. sessionStorage or cookies)\n        this.sessionStorageAvailable = this.constructor._storageTest();\n        this.storageNamePrefix = 'AUTO_'; // The prefix for the raw value storage name variable can be modified here\n        this._setPersistentStorageName();\n\n        // --------------------------------------------------------\n        // -------------- Tracking\n        // Keep track if the element is currently focused\n        this.isFocused = false;\n        // Keep track if a mouse wheel event is currently ongoing\n        this.isWheelEvent = false;\n        // Keep track if a drop event is currently ongoing\n        this.isDropEvent = false;\n        // Keep track if the user is currently editing the element\n        this.isEditing = false;\n        // Keep track of the rawValue (needed to define if a change event must be sent on blur or enter key)\n        this.rawValueOnFocus = void 0;\n        // Watch any external changes to the element value/textContent/nodeValue and `set()` the new value so that it gets formatted/saved in the history\n        this.internalModification = false; // This is temporarily set to `true` only when the AutoNumeric object does update the element value\n        this.attributeToWatch = this._getAttributeToWatch();\n        this.getterSetter = Object.getOwnPropertyDescriptor(this.domElement.__proto__, this.attributeToWatch);\n        this._addWatcher();\n\n        if (this.settings.createLocalList) {\n            // Keep track of every AutoNumeric elements that this object initialized\n            this._createLocalList();\n        }\n\n        // Keep track of all AutoNumeric elements in the current web page\n        this.constructor._addToGlobalList(this);\n\n        // --------------------------------------------------------\n        // -------------- Methods\n        // Create the global functions\n        this.global = {\n            /**\n             * Set the same given element value for each elements in the local AutoNumeric element list, and format those elements immediately\n             *\n             * @param {number|string} newValue The value must be a number or a numeric string\n             * @param {object} options A settings object that will override the current settings. Note: the update is done only if the `newValue` is defined.\n             */\n            set: function set(newValue) {\n                var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n                _this.autoNumericLocalList.forEach(function (aNObject) {\n                    aNObject.set(newValue, options);\n                });\n            },\n\n            /**\n             * Set the value given value directly as the DOM element value, without formatting it beforehand.\n             * This sets the same unformatted value for each elements in the local AutoNumeric element list.\n             *\n             * @param {number|string} value\n             * @param {object} options\n             */\n            setUnformatted: function setUnformatted(value) {\n                var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n                _this.autoNumericLocalList.forEach(function (aNObject) {\n                    aNObject.setUnformatted(value, options);\n                });\n            },\n\n            /**\n             * This is an alias of the `getNumericString()` function, and should not be used anymore.\n             *\n             * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n             * @returns {Array<string>}\n             * @deprecated\n             */\n            get: function get() {\n                var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n                var result = [];\n                _this.autoNumericLocalList.forEach(function (aNObject) {\n                    result.push(aNObject.get());\n                });\n                _this._executeCallback(result, callback);\n\n                return result;\n            },\n\n            /**\n             * Return an array of the unformatted values (as a string) of each AutoNumeric element of the local AutoNumeric element list\n             *\n             * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n             * @returns {Array<string>}\n             */\n            getNumericString: function getNumericString() {\n                var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n                var result = [];\n                _this.autoNumericLocalList.forEach(function (aNObject) {\n                    result.push(aNObject.getNumericString());\n                });\n                _this._executeCallback(result, callback);\n\n                return result;\n            },\n\n            /**\n             * Return an array of the current formatted values (as a string) of each AutoNumeric element of the local AutoNumeric element list\n             *\n             * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n             * @returns {Array<string>}\n             */\n            getFormatted: function getFormatted() {\n                var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n                var result = [];\n                _this.autoNumericLocalList.forEach(function (aNObject) {\n                    result.push(aNObject.getFormatted());\n                });\n                _this._executeCallback(result, callback);\n\n                return result;\n            },\n\n            /**\n             * Return an array of the element unformatted values (as a real Javascript number), for each element of the local AutoNumeric element list\n             *\n             * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n             * @returns {Array<number>}\n             */\n            getNumber: function getNumber() {\n                var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n                var result = [];\n                _this.autoNumericLocalList.forEach(function (aNObject) {\n                    result.push(aNObject.getNumber());\n                });\n                _this._executeCallback(result, callback);\n\n                return result;\n            },\n\n            /**\n             * Returns the unformatted values (following the `outputFormat` setting) of each element of the local AutoNumeric element list into an array\n             *\n             * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n             * @returns {Array<string>}\n             */\n            getLocalized: function getLocalized() {\n                var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n                var result = [];\n                _this.autoNumericLocalList.forEach(function (aNObject) {\n                    result.push(aNObject.getLocalized());\n                });\n                _this._executeCallback(result, callback);\n\n                return result;\n            },\n\n            /**\n             * Force each element of the local AutoNumeric element list to reformat its value\n             */\n            reformat: function reformat() {\n                _this.autoNumericLocalList.forEach(function (aNObject) {\n                    aNObject.reformat();\n                });\n            },\n\n            /**\n             * Remove the formatting and keep only the raw unformatted value (as a numericString) in each elements of the local AutoNumeric element list\n             */\n            unformat: function unformat() {\n                _this.autoNumericLocalList.forEach(function (aNObject) {\n                    aNObject.unformat();\n                });\n            },\n\n            /**\n             * Remove the formatting and keep only the localized unformatted value in the element, with the option to override the default outputFormat if needed\n             *\n             * @param {null|string} forcedOutputFormat If set to something different than `null`, then this is used as an overriding outputFormat option\n             */\n            unformatLocalized: function unformatLocalized() {\n                var forcedOutputFormat = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n                _this.autoNumericLocalList.forEach(function (aNObject) {\n                    aNObject.unformatLocalized(forcedOutputFormat);\n                });\n            },\n\n            /**\n             * Updates the AutoNumeric settings, and immediately format the elements accordingly, for each elements of the local AutoNumeric element list\n             *\n             * @param {object} newOptions This can be either one or more option objects\n             */\n            update: function update() {\n                for (var _len = arguments.length, newOptions = Array(_len), _key = 0; _key < _len; _key++) {\n                    newOptions[_key] = arguments[_key];\n                }\n\n                _this.autoNumericLocalList.forEach(function (aNObject) {\n                    aNObject.update.apply(aNObject, newOptions);\n                });\n            },\n\n            /**\n             * Return `true` if *all* the autoNumeric-managed elements are pristine, if their raw value hasn't changed.\n             * By default, this returns `true` if the raw unformatted value is still the same even if the formatted one has changed (due to a configuration update for instance).\n             *\n             * @param {boolean} checkOnlyRawValue If set to `true`, the pristine value is done on the raw unformatted value, not the formatted one. If set to `false`, this also checks that the formatted value hasn't changed.\n             * @returns {boolean}\n             */\n            isPristine: function isPristine() {\n                var checkOnlyRawValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;\n\n                var isPristine = true;\n                _this.autoNumericLocalList.forEach(function (aNObject) {\n                    if (isPristine && !aNObject.isPristine(checkOnlyRawValue)) {\n                        isPristine = false;\n                    }\n                });\n\n                return isPristine;\n            },\n\n            /**\n             * Execute the `clear()` method on each AutoNumeric object in the local AutoNumeric element list\n             *\n             * @param {boolean} forceClearAll\n             */\n            clear: function clear() {\n                var forceClearAll = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n\n                _this.autoNumericLocalList.forEach(function (aNObject) {\n                    aNObject.clear(forceClearAll);\n                });\n            },\n\n            /**\n             * Execute the `remove()` method on each AutoNumeric object in the local AutoNumeric element list\n             */\n            remove: function remove() {\n                _this.autoNumericLocalList.forEach(function (aNObject) {\n                    aNObject.remove();\n                });\n            },\n\n            /**\n             * Execute the `wipe()` method on each AutoNumeric object in the local AutoNumeric element list\n             */\n            wipe: function wipe() {\n                _this.autoNumericLocalList.forEach(function (aNObject) {\n                    aNObject.wipe();\n                });\n            },\n\n            /**\n             * Execute the `nuke()` method on each AutoNumeric object in the local AutoNumeric element list\n             */\n            nuke: function nuke() {\n                _this.autoNumericLocalList.forEach(function (aNObject) {\n                    aNObject.nuke();\n                });\n            },\n\n            /**\n             * Return `true` if the given AutoNumeric object (or DOM element) is in the local AutoNumeric element list\n             *\n             * @param {HTMLElement|HTMLInputElement|AutoNumeric} domElementOrAutoNumericObject\n             * @returns {*}\n             */\n            has: function has(domElementOrAutoNumericObject) {\n                var result = void 0;\n                if (domElementOrAutoNumericObject instanceof AutoNumeric) {\n                    result = _this.autoNumericLocalList.has(domElementOrAutoNumericObject.node());\n                } else {\n                    result = _this.autoNumericLocalList.has(domElementOrAutoNumericObject);\n                }\n\n                return result;\n            },\n\n            /**\n             * Add an existing AutoNumeric object (or DOM element) to the local AutoNumeric element list, using the DOM element as the key.\n             * This manages the case where `addObject` is used on an AutoNumeric object that already has multiple elements in its local list.\n             *\n             * @param {HTMLElement|HTMLInputElement|AutoNumeric} domElementOrAutoNumericObject\n             */\n            addObject: function addObject(domElementOrAutoNumericObject) {\n                // Start with the same data, whatever the user passed as arguments\n                var domElement = void 0;\n                var otherAutoNumericObject = void 0;\n                if (domElementOrAutoNumericObject instanceof AutoNumeric) {\n                    domElement = domElementOrAutoNumericObject.node();\n                    otherAutoNumericObject = domElementOrAutoNumericObject;\n                } else {\n                    domElement = domElementOrAutoNumericObject;\n                    otherAutoNumericObject = AutoNumeric.getAutoNumericElement(domElement);\n                }\n\n                // Check if the current autoNumeric object has a local list\n                if (!_this._hasLocalList()) {\n                    _this._createLocalList();\n                }\n\n                // Check if the other autoNumeric object has a local list...\n                var otherANLocalList = otherAutoNumericObject._getLocalList();\n                if (otherANLocalList.size === 0) {\n                    // Special case if the other AutoNumeric object has an empty local list, then populate itself to it\n                    otherAutoNumericObject._createLocalList();\n                    otherANLocalList = otherAutoNumericObject._getLocalList(); // Update the other local list\n                }\n\n                var mergedLocalLists = void 0;\n                if (otherANLocalList instanceof Map) {\n                    // ...If it does, merge the local lists together\n                    mergedLocalLists = _AutoNumericHelper2.default.mergeMaps(_this._getLocalList(), otherANLocalList);\n                } else {\n                    // ...If not, just set the current local list onto the other AutoNumeric object\n                    // We need to specify the AutoNumeric object, otherwise the `_addToLocalList` function would not correctly add the AutoNumeric object since we would not have a reference to it, but a reference to the current AutoNumeric object on which is called this method.\n                    _this._addToLocalList(domElement, otherAutoNumericObject);\n                    mergedLocalLists = _this._getLocalList();\n                }\n\n                // Update the resulting list, on all the objects of that local list (so that we can indifferently use `init()` on any object belonging to that list)\n                mergedLocalLists.forEach(function (aNObject) {\n                    aNObject._setLocalList(mergedLocalLists);\n                });\n            },\n\n            /**\n             * Remove the given AutoNumeric object (or DOM element) from the local AutoNumeric element list, using the DOM element as the key.\n             * If this function attempts to remove the current AutoNumeric object from the local list, a warning is shown, but the deletion is still done.\n             *\n             * Special cases :\n             * - If the current object removes itself, then it's removed from the shared local list, then a new empty local list is used/created\n             * - If another object remove this object, then a local list with only this object is used/created\n             *\n             * @param {HTMLElement|HTMLInputElement|AutoNumeric} domElementOrAutoNumericObject\n             * @param {boolean} keepCurrentANObject If set to `false`, then the function will also remove the current AutoNumeric object if asked, otherwise it will ignore it and print a warning message\n             */\n            removeObject: function removeObject(domElementOrAutoNumericObject) {\n                var keepCurrentANObject = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n\n                // Start with the same data, whatever the user passed as arguments\n                var domElement = void 0;\n                var otherAutoNumericObject = void 0;\n                if (domElementOrAutoNumericObject instanceof AutoNumeric) {\n                    domElement = domElementOrAutoNumericObject.node();\n                    otherAutoNumericObject = domElementOrAutoNumericObject;\n                } else {\n                    domElement = domElementOrAutoNumericObject;\n                    otherAutoNumericObject = AutoNumeric.getAutoNumericElement(domElement);\n                }\n\n                // Remove the other object from the local list\n                var initialCompleteLocalList = _this.autoNumericLocalList;\n                _this.autoNumericLocalList.delete(domElement);\n\n                // Update the local list for all objects in it\n                initialCompleteLocalList.forEach(function (aNObject) {\n                    aNObject._setLocalList(_this.autoNumericLocalList);\n                });\n\n                if (!keepCurrentANObject && domElement === _this.node()) {\n                    // This object is removed by itself\n                    // Empty the object local list\n                    otherAutoNumericObject._setLocalList(new Map());\n                } else {\n                    // This object is removed by another object\n                    // Set the local list for the removed object, with only this object in it\n                    otherAutoNumericObject._createLocalList();\n                }\n            },\n\n            /**\n             * Remove all elements from the shared list, effectively emptying it.\n             * This is the equivalent of calling `detach()` on each of its elements.\n             *\n             * @param {boolean} keepEachANObjectInItsOwnList If set to `true`, then instead of completely emptying the local list of each AutoNumeric objects, each one of those keeps itself in its own local list\n             */\n            empty: function empty() {\n                var keepEachANObjectInItsOwnList = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n\n                var initialCompleteLocalList = _this.autoNumericLocalList;\n\n                // Update the local list for all objects in it\n                initialCompleteLocalList.forEach(function (aNObject) {\n                    if (keepEachANObjectInItsOwnList) {\n                        aNObject._createLocalList();\n                    } else {\n                        aNObject._setLocalList(new Map());\n                    }\n                });\n            },\n\n            /**\n             * Return an array containing all the AutoNumeric DOM elements that have been initialized by each other\n             *\n             * @returns {Array<HTMLElement>}\n             */\n            elements: function elements() {\n                var result = [];\n                _this.autoNumericLocalList.forEach(function (aNObject) {\n                    result.push(aNObject.node());\n                });\n\n                return result;\n            },\n\n            /**\n             * Return the `Map` object directly\n             * @returns {Map}\n             */\n            getList: function getList() {\n                return _this.autoNumericLocalList;\n            },\n\n            /**\n             * Return the number of element in the local AutoNumeric element list\n             * @returns {number}\n             */\n            size: function size() {\n                return _this.autoNumericLocalList.size;\n            }\n        };\n\n        // Create the functions that will allow to change each setting one by one\n        /**\n         * For each options, we define if we need to reformat the element content (does changing the options should change the way its value is displayed?).\n         * If yes, then we use the `update()` for force a reformat, otherwise, we just update the `settings` object.\n         */\n        this.options = {\n            /**\n             * Reset any options set previously, by overwriting them with the default settings\n             *\n             * @returns {AutoNumeric}\n             */\n            reset: function reset() {\n                //TODO Add a `settings` parameter so that the user can reset to a specific set of settings. This is different than update since it drops any non-default settings before using those new settings.\n                _this.settings = { rawValue: _this.defaultRawValue }; // Here we pass the default rawValue in order to prevent showing a warning that we try to set an `undefined` value\n                _this.update(AutoNumeric.defaultSettings);\n\n                return _this;\n            },\n            allowDecimalPadding: function allowDecimalPadding(_allowDecimalPadding) {\n                _this.update({ allowDecimalPadding: _allowDecimalPadding });\n\n                return _this;\n            },\n            alwaysAllowDecimalCharacter: function alwaysAllowDecimalCharacter(_alwaysAllowDecimalCharacter) {\n                //FIXME Test this\n                _this.update({ alwaysAllowDecimalCharacter: _alwaysAllowDecimalCharacter });\n\n                return _this;\n            },\n            caretPositionOnFocus: function caretPositionOnFocus(_caretPositionOnFocus) {\n                //FIXME test this\n                _this.settings.caretPositionOnFocus = _caretPositionOnFocus;\n\n                return _this;\n            },\n            createLocalList: function createLocalList(_createLocalList2) {\n                _this.settings.createLocalList = _createLocalList2;\n\n                // Delete the local list when this is set to `false`, create it if this is set to `true` and there is not pre-existing list\n                if (_this.settings.createLocalList) {\n                    if (!_this._hasLocalList()) {\n                        _this._createLocalList();\n                    }\n                } else {\n                    _this._deleteLocalList();\n                }\n\n                return _this;\n            },\n            currencySymbol: function currencySymbol(_currencySymbol) {\n                _this.update({ currencySymbol: _currencySymbol });\n\n                return _this;\n            },\n            currencySymbolPlacement: function currencySymbolPlacement(_currencySymbolPlacement) {\n                _this.update({ currencySymbolPlacement: _currencySymbolPlacement });\n\n                return _this;\n            },\n            decimalCharacter: function decimalCharacter(_decimalCharacter) {\n                _this.update({ decimalCharacter: _decimalCharacter });\n\n                return _this;\n            },\n            decimalCharacterAlternative: function decimalCharacterAlternative(_decimalCharacterAlternative) {\n                _this.settings.decimalCharacterAlternative = _decimalCharacterAlternative;\n\n                return _this;\n            },\n            /**\n             * Update the decimal places globally, which means this override any previously set number of decimal shown on focus, on blur, or in the raw value.\n             *\n             * @param {int} decimalPlaces\n             * @returns {AutoNumeric}\n             */\n            decimalPlaces: function decimalPlaces(_decimalPlaces) {\n                _AutoNumericHelper2.default.warning('Using `options.decimalPlaces()` instead of calling the specific `options.decimalPlacesRawValue()`, `options.decimalPlacesShownOnFocus()` and `options.decimalPlacesShownOnBlur()` methods will reset those options.\\nPlease call the specific methods if you do not want to reset those.', _this.settings.showWarnings);\n                _this.update({ decimalPlaces: _decimalPlaces });\n\n                return _this;\n            },\n            decimalPlacesRawValue: function decimalPlacesRawValue(_decimalPlacesRawValue) {\n                //FIXME test this\n                _this.update({ decimalPlacesRawValue: _decimalPlacesRawValue });\n\n                return _this;\n            },\n            decimalPlacesShownOnBlur: function decimalPlacesShownOnBlur(_decimalPlacesShownOnBlur) {\n                _this.update({ decimalPlacesShownOnBlur: _decimalPlacesShownOnBlur });\n\n                return _this;\n            },\n            decimalPlacesShownOnFocus: function decimalPlacesShownOnFocus(_decimalPlacesShownOnFocus) {\n                _this.update({ decimalPlacesShownOnFocus: _decimalPlacesShownOnFocus });\n\n                return _this;\n            },\n            defaultValueOverride: function defaultValueOverride(_defaultValueOverride) {\n                _this.update({ defaultValueOverride: _defaultValueOverride });\n\n                return _this;\n            },\n            digitalGroupSpacing: function digitalGroupSpacing(_digitalGroupSpacing) {\n                _this.update({ digitalGroupSpacing: _digitalGroupSpacing });\n\n                return _this;\n            },\n            digitGroupSeparator: function digitGroupSeparator(_digitGroupSeparator) {\n                _this.update({ digitGroupSeparator: _digitGroupSeparator });\n\n                return _this;\n            },\n            divisorWhenUnfocused: function divisorWhenUnfocused(_divisorWhenUnfocused) {\n                _this.update({ divisorWhenUnfocused: _divisorWhenUnfocused });\n\n                return _this;\n            },\n            emptyInputBehavior: function emptyInputBehavior(_emptyInputBehavior) {\n                if (_this.rawValue === null && _emptyInputBehavior !== AutoNumeric.options.emptyInputBehavior.null) {\n                    // Special case : if the current `rawValue` is `null` and the `emptyInputBehavior` is changed to something else than `'null'`, then it makes that `rawValue` invalid.\n                    // Here we can either prevent the option update and throw an error, or still accept the option update and update the value from `null` to `''`.\n                    // We cannot keep `rawValue` to `null` since if `emptyInputBehavior` is not set to `null`, lots of function assume `rawValue` is a string.\n                    _AutoNumericHelper2.default.warning('You are trying to modify the `emptyInputBehavior` option to something different than `\\'null\\'` (' + _emptyInputBehavior + '), but the element raw value is currently set to `null`. This would result in an invalid `rawValue`. In order to fix that, the element value has been changed to the empty string `\\'\\'`.', _this.settings.showWarnings);\n                    _this.rawValue = '';\n                }\n\n                _this.update({ emptyInputBehavior: _emptyInputBehavior });\n\n                return _this;\n            },\n            eventBubbles: function eventBubbles(_eventBubbles) {\n                _this.settings.eventBubbles = _eventBubbles;\n\n                return _this;\n            },\n            eventIsCancelable: function eventIsCancelable(_eventIsCancelable) {\n                _this.settings.eventIsCancelable = _eventIsCancelable;\n\n                return _this;\n            },\n            failOnUnknownOption: function failOnUnknownOption(_failOnUnknownOption) {\n                _this.settings.failOnUnknownOption = _failOnUnknownOption; //FIXME test this\n\n                return _this;\n            },\n            formatOnPageLoad: function formatOnPageLoad(_formatOnPageLoad) {\n                _this.settings.formatOnPageLoad = _formatOnPageLoad; //FIXME test this\n\n                return _this;\n            },\n            historySize: function historySize(_historySize) {\n                _this.settings.historySize = _historySize;\n\n                return _this;\n            },\n            isCancellable: function isCancellable(_isCancellable) {\n                _this.settings.isCancellable = _isCancellable; //FIXME test this\n\n                return _this;\n            },\n            leadingZero: function leadingZero(_leadingZero) {\n                _this.update({ leadingZero: _leadingZero });\n\n                return _this;\n            },\n            maximumValue: function maximumValue(_maximumValue) {\n                _this.update({ maximumValue: _maximumValue });\n\n                return _this;\n            },\n            minimumValue: function minimumValue(_minimumValue) {\n                _this.update({ minimumValue: _minimumValue });\n\n                return _this;\n            },\n            modifyValueOnWheel: function modifyValueOnWheel(_modifyValueOnWheel) {\n                _this.settings.modifyValueOnWheel = _modifyValueOnWheel; //FIXME test this\n\n                return _this;\n            },\n            negativeBracketsTypeOnBlur: function negativeBracketsTypeOnBlur(_negativeBracketsTypeOnBlur) {\n                _this.update({ negativeBracketsTypeOnBlur: _negativeBracketsTypeOnBlur });\n\n                return _this;\n            },\n            negativePositiveSignPlacement: function negativePositiveSignPlacement(_negativePositiveSignPlacement) {\n                _this.update({ negativePositiveSignPlacement: _negativePositiveSignPlacement });\n\n                return _this;\n            },\n            negativeSignCharacter: function negativeSignCharacter(_negativeSignCharacter) {\n                _this.update({ negativeSignCharacter: _negativeSignCharacter });\n\n                return _this;\n            },\n            noEventListeners: function noEventListeners(_noEventListeners) {\n                //FIXME test this\n                if (_noEventListeners === AutoNumeric.options.noEventListeners.noEvents && _this.settings.noEventListeners === AutoNumeric.options.noEventListeners.addEvents) {\n                    // Remove the events once\n                    _this._removeEventListeners();\n                }\n\n                _this.update({ noEventListeners: _noEventListeners });\n\n                return _this;\n            },\n            onInvalidPaste: function onInvalidPaste(_onInvalidPaste) {\n                _this.settings.onInvalidPaste = _onInvalidPaste; //FIXME test this\n\n                return _this;\n            },\n            outputFormat: function outputFormat(_outputFormat) {\n                _this.settings.outputFormat = _outputFormat;\n\n                return _this;\n            },\n            overrideMinMaxLimits: function overrideMinMaxLimits(_overrideMinMaxLimits) {\n                _this.update({ overrideMinMaxLimits: _overrideMinMaxLimits });\n\n                return _this;\n            },\n            positiveSignCharacter: function positiveSignCharacter(_positiveSignCharacter) {\n                _this.update({ positiveSignCharacter: _positiveSignCharacter });\n\n                return _this;\n            },\n            rawValueDivisor: function rawValueDivisor(_rawValueDivisor) {\n                _this.update({ rawValueDivisor: _rawValueDivisor });\n\n                return _this;\n            },\n            readOnly: function readOnly(_readOnly) {\n                // When changing the readOnly attribute, the raw and formatted values do not change, so no need to call the costly 'update()` method\n                _this.settings.readOnly = _readOnly;\n                _this._setWritePermissions();\n\n                return _this;\n            },\n            roundingMethod: function roundingMethod(_roundingMethod) {\n                _this.update({ roundingMethod: _roundingMethod });\n\n                return _this;\n            },\n            saveValueToSessionStorage: function saveValueToSessionStorage(_saveValueToSessionStorage) {\n                _this.update({ saveValueToSessionStorage: _saveValueToSessionStorage });\n\n                return _this;\n            },\n            symbolWhenUnfocused: function symbolWhenUnfocused(_symbolWhenUnfocused) {\n                _this.update({ symbolWhenUnfocused: _symbolWhenUnfocused });\n\n                return _this;\n            },\n            selectNumberOnly: function selectNumberOnly(_selectNumberOnly) {\n                _this.settings.selectNumberOnly = _selectNumberOnly; //FIXME test this\n\n                return _this;\n            },\n            selectOnFocus: function selectOnFocus(_selectOnFocus) {\n                _this.settings.selectOnFocus = _selectOnFocus; //FIXME test this\n\n                return _this;\n            },\n            serializeSpaces: function serializeSpaces(_serializeSpaces) {\n                _this.settings.serializeSpaces = _serializeSpaces; //FIXME test this\n\n                return _this;\n            },\n            showOnlyNumbersOnFocus: function showOnlyNumbersOnFocus(_showOnlyNumbersOnFocus) {\n                _this.update({ showOnlyNumbersOnFocus: _showOnlyNumbersOnFocus });\n\n                return _this;\n            },\n            showPositiveSign: function showPositiveSign(_showPositiveSign) {\n                _this.update({ showPositiveSign: _showPositiveSign });\n\n                return _this;\n            },\n            showWarnings: function showWarnings(_showWarnings) {\n                _this.settings.showWarnings = _showWarnings; //FIXME test this\n\n                return _this;\n            },\n            styleRules: function styleRules(_styleRules) {\n                _this.update({ styleRules: _styleRules });\n\n                return _this;\n            },\n            suffixText: function suffixText(_suffixText) {\n                _this.update({ suffixText: _suffixText });\n\n                return _this;\n            },\n            unformatOnHover: function unformatOnHover(_unformatOnHover) {\n                _this.settings.unformatOnHover = _unformatOnHover; //FIXME test this\n\n                return _this;\n            },\n            unformatOnSubmit: function unformatOnSubmit(_unformatOnSubmit2) {\n                _this.settings.unformatOnSubmit = _unformatOnSubmit2; //FIXME test this\n\n                return _this;\n            },\n            valuesToStrings: function valuesToStrings(_valuesToStrings) {\n                _this.update({ valuesToStrings: _valuesToStrings });\n\n                return _this;\n            },\n            watchExternalChanges: function watchExternalChanges(_watchExternalChanges) {\n                //FIXME test this\n                _this.update({ watchExternalChanges: _watchExternalChanges });\n\n                return _this;\n            },\n            wheelOn: function wheelOn(_wheelOn) {\n                _this.settings.wheelOn = _wheelOn; //FIXME test this\n\n                return _this;\n            },\n            wheelStep: function wheelStep(_wheelStep) {\n                _this.settings.wheelStep = _wheelStep; //FIXME test this\n\n                return _this;\n            }\n        };\n\n        // Once the autoNumeric element has been initialized, broadcast that message with additional info.\n        // Note: When using `AutoNumeric.multiple()`, one event is sent *per* element initialized\n        this._triggerEvent(AutoNumeric.events.initialized, this.domElement, {\n            newValue: _AutoNumericHelper2.default.getElementValue(this.domElement),\n            newRawValue: this.rawValue,\n            error: null,\n            aNElement: this\n        });\n    }\n\n    /**\n     * Return the autoNumeric version number (for debugging purpose)\n     *\n     * @returns {string}\n     */\n\n\n    _createClass(AutoNumeric, [{\n        key: '_saveInitialValues',\n\n\n        /**\n         * Save the initial element values for later use in the pristine test.\n         * Those values are :\n         * - the html attribute (ie. <input value='42'>), and\n         * - the script `value` (ie. `let domElement.value`)\n         *\n         * @param {null|number|string} initialValue\n         * @private\n         */\n        value: function _saveInitialValues(initialValue) {\n            // Keep the very first initial values (in the html attribute and set by the script). This is needed to check if the element is pristine.\n            // Save the html attribute 'value'\n            this.initialValueHtmlAttribute = _AutoNumericHelper2.default.scientificToDecimal(this.domElement.getAttribute('value'));\n            if (_AutoNumericHelper2.default.isNull(this.initialValueHtmlAttribute)) {\n                // Set the default empty value attribute instead of `null`, since if the initial value is null, the empty string is used\n                this.initialValueHtmlAttribute = '';\n            }\n\n            // Save the 'script' value\n            this.initialValue = initialValue;\n            if (_AutoNumericHelper2.default.isNull(this.initialValue)) {\n                // Same as above\n                this.initialValue = '';\n            }\n        }\n\n        /**\n         * Generate all the event listeners for the given DOM element\n         * @private\n         */\n\n    }, {\n        key: '_createEventListeners',\n        value: function _createEventListeners() {\n            var _this2 = this;\n\n            // Create references to the event handler functions, so we can then cleanly removes those listeners if needed\n            // That would not be possible if we used closures directly in the event handler declarations\n            this._onFocusInFunc = function (e) {\n                _this2._onFocusIn(e);\n            };\n            this._onFocusInAndMouseEnterFunc = function (e) {\n                _this2._onFocusInAndMouseEnter(e);\n            };\n            this._onFocusFunc = function () {\n                _this2._onFocus();\n            };\n            this._onKeydownFunc = function (e) {\n                _this2._onKeydown(e);\n            };\n            this._onKeypressFunc = function (e) {\n                _this2._onKeypress(e);\n            };\n            this._onKeyupFunc = function (e) {\n                _this2._onKeyup(e);\n            };\n            this._onFocusOutAndMouseLeaveFunc = function (e) {\n                _this2._onFocusOutAndMouseLeave(e);\n            };\n            this._onPasteFunc = function (e) {\n                _this2._onPaste(e);\n            };\n            this._onWheelFunc = function (e) {\n                _this2._onWheel(e);\n            };\n            this._onDropFunc = function (e) {\n                _this2._onDrop(e);\n            };\n            this._onKeydownGlobalFunc = function (e) {\n                _this2._onKeydownGlobal(e);\n            };\n            this._onKeyupGlobalFunc = function (e) {\n                _this2._onKeyupGlobal(e);\n            };\n\n            // Add the event listeners\n            this.domElement.addEventListener('focusin', this._onFocusInFunc, false);\n            this.domElement.addEventListener('focus', this._onFocusInAndMouseEnterFunc, false);\n            this.domElement.addEventListener('focus', this._onFocusFunc, false);\n            this.domElement.addEventListener('mouseenter', this._onFocusInAndMouseEnterFunc, false);\n            this.domElement.addEventListener('keydown', this._onKeydownFunc, false);\n            this.domElement.addEventListener('keypress', this._onKeypressFunc, false);\n            this.domElement.addEventListener('keyup', this._onKeyupFunc, false);\n            this.domElement.addEventListener('blur', this._onFocusOutAndMouseLeaveFunc, false);\n            this.domElement.addEventListener('mouseleave', this._onFocusOutAndMouseLeaveFunc, false);\n            this.domElement.addEventListener('paste', this._onPasteFunc, false);\n            this.domElement.addEventListener('wheel', this._onWheelFunc, false);\n            this.domElement.addEventListener('drop', this._onDropFunc, false);\n            this._setupFormListener();\n\n            // Keep track if the event listeners have been initialized on this object\n            this.hasEventListeners = true;\n\n            // Create one global event listener for the keyup event on the document object, which will be shared by all the autoNumeric elements\n            if (!AutoNumeric._doesGlobalListExists()) {\n                document.addEventListener('keydown', this._onKeydownGlobalFunc, false);\n                document.addEventListener('keyup', this._onKeyupGlobalFunc, false);\n            }\n        }\n\n        /**\n         * Remove all the autoNumeric-related event listeners for the given DOM element\n         * @private\n         */\n\n    }, {\n        key: '_removeEventListeners',\n        value: function _removeEventListeners() {\n            this.domElement.removeEventListener('focusin', this._onFocusInFunc, false);\n            this.domElement.removeEventListener('focus', this._onFocusInAndMouseEnterFunc, false);\n            this.domElement.removeEventListener('focus', this._onFocusFunc, false);\n            this.domElement.removeEventListener('mouseenter', this._onFocusInAndMouseEnterFunc, false);\n            this.domElement.removeEventListener('blur', this._onFocusOutAndMouseLeaveFunc, false);\n            this.domElement.removeEventListener('mouseleave', this._onFocusOutAndMouseLeaveFunc, false);\n            this.domElement.removeEventListener('keydown', this._onKeydownFunc, false);\n            this.domElement.removeEventListener('keypress', this._onKeypressFunc, false);\n            this.domElement.removeEventListener('keyup', this._onKeyupFunc, false);\n            this.domElement.removeEventListener('paste', this._onPasteFunc, false);\n            this.domElement.removeEventListener('wheel', this._onWheelFunc, false);\n            this.domElement.removeEventListener('drop', this._onDropFunc, false);\n            this._removeFormListener();\n\n            // Keep track if the event listeners have been initialized on this object\n            this.hasEventListeners = false;\n\n            document.removeEventListener('keydown', this._onKeydownGlobalFunc, false);\n            document.removeEventListener('keyup', this._onKeyupGlobalFunc, false);\n        }\n\n        /**\n         * Toggle the event listeners according to the `noEventListeners` option, if those were not activated/deactivated before\n         * @private\n         */\n\n    }, {\n        key: '_updateEventListeners',\n        value: function _updateEventListeners() {\n            if (!this.settings.noEventListeners && !this.hasEventListeners) {\n                // Special case where an update is done on an element that did not activate its event listeners in the first place\n                // ie. when an element is first created with `contenteditable=\"false\"`, then an update is done with `anElement.french()`\n                this._createEventListeners();\n            }\n\n            if (this.settings.noEventListeners && this.hasEventListeners) {\n                this._removeEventListeners();\n            }\n        }\n\n        /**\n         * Mark the parent <form> so that other AutoNumeric object will not add more listeners.\n         * Add a counter so that when removing the AutoNumeric object, we only remove the submit listener if that count is equal to 0.\n         * Also keep a reference to the 'submit' event handler function to be able to remove that handler later if the `_removeFormListener()` function is called from another AutoNumeric object.\n         *\n         * @private\n         */\n\n    }, {\n        key: '_setupFormListener',\n        value: function _setupFormListener() {\n            var _this3 = this;\n\n            if (!_AutoNumericHelper2.default.isNull(this.parentForm)) {\n                // Setup the handler function\n                this._onFormSubmitFunc = function () {\n                    _this3._onFormSubmit();\n                };\n                this._onFormResetFunc = function () {\n                    _this3._onFormReset();\n                };\n\n                // Check if the parent form already has the AutoNumeric mark\n                if (this._hasParentFormCounter()) {\n                    this._incrementParentFormCounter();\n                } else {\n                    // If not, add the counter\n                    this._initializeFormCounterToOne();\n                    // And add the submit and reset event listeners\n                    this.parentForm.addEventListener('submit', this._onFormSubmitFunc, false);\n                    this.parentForm.addEventListener('reset', this._onFormResetFunc, false);\n                    // Also keep a reference to the handler function so that we can remove it later\n                    this._storeFormHandlerFunction();\n                }\n            }\n        }\n\n        /**\n         * Remove the form 'submit' event listener, as well as the `dataset` info (`anCount` and `anFormHandler`) from the parent form, only when there are only one AutoNumeric child element left in that <form>.\n         * Otherwise decrement the `anCount`.\n         *\n         * @private\n         */\n\n    }, {\n        key: '_removeFormListener',\n        value: function _removeFormListener() {\n            if (!_AutoNumericHelper2.default.isNull(this.parentForm)) {\n                // Check the parent form counter value\n                var anCount = this._getParentFormCounter();\n\n                if (anCount === 1) {\n                    // If it's 1, remove the listeners\n                    this.parentForm.removeEventListener('submit', this._getFormHandlerFunction().submitFn, false);\n                    this.parentForm.removeEventListener('reset', this._getFormHandlerFunction().resetFn, false);\n                    // Also remove the dataset info\n                    this._removeFormDataSetInfo();\n                } else if (anCount > 1) {\n                    // Otherwise if it's >1 decrement the counter\n                    this._decrementParentFormCounter();\n                } else {\n                    // If it's <1, throw an error\n                    _AutoNumericHelper2.default.throwError('The AutoNumeric object count on the form is incoherent.');\n                }\n            }\n        }\n\n        /**\n         * Return `true` if the parent form has the form counter attribute\n         *\n         * @returns {boolean}\n         * @private\n         */\n\n    }, {\n        key: '_hasParentFormCounter',\n        value: function _hasParentFormCounter() {\n            return 'anCount' in this.parentForm.dataset;\n        }\n\n        /**\n         * Return the count of AutoNumeric form children\n         *\n         * @returns {number}\n         * @private\n         */\n\n    }, {\n        key: '_getParentFormCounter',\n        value: function _getParentFormCounter() {\n            return Number(this.parentForm.dataset.anCount);\n        }\n\n        /**\n         * Set the count of AutoNumeric form children to 1 for the given form element, or if none are passed, the current `this.parentForm` one.\n         *\n         * @param {HTMLFormElement|null} formElement\n         * @private\n         */\n\n    }, {\n        key: '_initializeFormCounterToOne',\n        value: function _initializeFormCounterToOne() {\n            var formElement = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            this._getFormElement(formElement).dataset.anCount = 1;\n        }\n\n        /**\n         * Increment the AutoNumeric form children count for the given form element, or if none are passed, the current `this.parentForm` one.\n         *\n         * @param {HTMLFormElement|null} formElement\n         * @private\n         */\n\n    }, {\n        key: '_incrementParentFormCounter',\n        value: function _incrementParentFormCounter() {\n            var formElement = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            this._getFormElement(formElement).dataset.anCount++;\n        }\n\n        /**\n         * Decrement the AutoNumeric form children count for the current `this.parentForm` form element.\n         *\n         * @private\n         */\n\n    }, {\n        key: '_decrementParentFormCounter',\n        value: function _decrementParentFormCounter() {\n            this.parentForm.dataset.anCount--;\n        }\n\n        /**\n         * Return `true` if the global form handler list exists on the `window` object.\n         *\n         * @returns {boolean}\n         * @private\n         */\n\n    }, {\n        key: '_hasFormHandlerFunction',\n\n\n        /**\n         * Return `true` if the given form element, or if none are passed, the current `this.parentForm` one has a form handler name.\n         *\n         * @param {HTMLFormElement|null} formElement\n         * @returns {boolean}\n         * @private\n         */\n        value: function _hasFormHandlerFunction() {\n            var formElement = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            return 'anFormHandler' in this._getFormElement(formElement).dataset;\n        }\n\n        /**\n         * Return the given form element, or defaults to `this.parentForm` if no argument is passed.\n         *\n         * @param {HTMLFormElement|null} formElement\n         * @returns {*}\n         * @private\n         */\n\n    }, {\n        key: '_getFormElement',\n        value: function _getFormElement() {\n            var formElement = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            var formElementToUse = void 0;\n            if (!_AutoNumericHelper2.default.isNull(formElement)) {\n                formElementToUse = formElement;\n            } else {\n                formElementToUse = this.parentForm;\n            }\n\n            return formElementToUse;\n        }\n\n        /**\n         * Generate a form handler unique name and store it in the global form handler list.\n         * This also save that name in the dataset of the given form element.\n         *\n         * @param {HTMLFormElement|null} formElement\n         * @private\n         */\n\n    }, {\n        key: '_storeFormHandlerFunction',\n        value: function _storeFormHandlerFunction() {\n            var formElement = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            // Create the weakMap if it does not exist\n            if (!this.constructor._doesFormHandlerListExists()) {\n                this.constructor._createFormHandlerList();\n            }\n\n            // Generate a unique name and save it in the form dataset\n            var formHandlerName = _AutoNumericHelper2.default.randomString();\n            this._getFormElement(formElement).dataset.anFormHandler = formHandlerName;\n\n            // Add the form handler name and handle function reference to the WeakMap\n            window.aNFormHandlerMap.set(formHandlerName, { submitFn: this._onFormSubmitFunc, resetFn: this._onFormResetFunc });\n        }\n\n        /**\n         * Return the form handler key name from the parent form element, for the global form handler list.\n         *\n         * @returns {string|*}\n         * @private\n         */\n\n    }, {\n        key: '_getFormHandlerKey',\n        value: function _getFormHandlerKey() {\n            if (!this._hasFormHandlerFunction()) {\n                _AutoNumericHelper2.default.throwError('Unable to retrieve the form handler name');\n            }\n\n            var formHandlerName = this.parentForm.dataset.anFormHandler;\n            if (formHandlerName === '') {\n                _AutoNumericHelper2.default.throwError('The form handler name is invalid');\n            }\n\n            return formHandlerName;\n        }\n\n        /**\n         * Return the 'submit' event handler function used for the parent form.\n         *\n         * @returns {function}\n         * @private\n         */\n\n    }, {\n        key: '_getFormHandlerFunction',\n        value: function _getFormHandlerFunction() {\n            var formHandlerName = this._getFormHandlerKey();\n\n            return window.aNFormHandlerMap.get(formHandlerName);\n        }\n\n        /**\n         * Remove the dataset attributes `data-an-count` and `data-an-form-handler` from the parent form element.\n         *\n         * @private\n         */\n\n    }, {\n        key: '_removeFormDataSetInfo',\n        value: function _removeFormDataSetInfo() {\n            // Just in case, set the counter to 0\n            this._decrementParentFormCounter();\n            // Remove the form handler function from the FormHandlerFunction Map\n            window.aNFormHandlerMap.delete(this._getFormHandlerKey());\n            // Lastly, remove the dataset attributes\n            this.parentForm.removeAttribute('data-an-count');\n            this.parentForm.removeAttribute('data-an-form-handler');\n        }\n\n        /**\n         * Set the DOM element write permissions according to the current settings, by setting the `readonly` or `contenteditable` attributes depending of its tag type.\n         *\n         * @private\n         */\n\n    }, {\n        key: '_setWritePermissions',\n        value: function _setWritePermissions() {\n            if (this.settings.readOnly) {\n                this._setReadOnly();\n            } else {\n                this._setReadWrite();\n            }\n        }\n\n        /**\n         * Set the element to be read-only.\n         * If the DOM element tag is not an `input`, then it `contenteditable` attribute is set to `false`.\n         *\n         * @private\n         */\n\n    }, {\n        key: '_setReadOnly',\n        value: function _setReadOnly() {\n            if (this.isInputElement) {\n                this.domElement.readOnly = true;\n            } else {\n                this.domElement.setAttribute('contenteditable', false);\n            }\n        }\n\n        /**\n         * Set the element to be read-write.\n         *\n         * @private\n         */\n\n    }, {\n        key: '_setReadWrite',\n        value: function _setReadWrite() {\n            if (this.isInputElement) {\n                this.domElement.readOnly = false;\n            } else {\n                this.domElement.setAttribute('contenteditable', true);\n            }\n        }\n\n        /**\n         * Add a watcher so that any external change to the AutoNumeric-managed element would be detected.\n         * As soon as such change is detected, AutoNumeric then tries to `set()` the value so that it gets formatted and stored in the history.\n         * //XXX For now, this only works when watching the `value` attribute, not the `textContent` one\n         * @private\n         */\n\n    }, {\n        key: '_addWatcher',\n        value: function _addWatcher() {\n            var _this4 = this;\n\n            // `getterSetter` can be undefined when a non-input element is used\n            if (!_AutoNumericHelper2.default.isUndefined(this.getterSetter)) {\n                var _getterSetter = this.getterSetter,\n                    setter = _getterSetter.set,\n                    getter = _getterSetter.get;\n\n                Object.defineProperty(this.domElement, this.attributeToWatch, {\n                    configurable: true, // This is needed in some rare cases\n                    get: function get() {\n                        return getter.call(_this4.domElement);\n                    },\n                    set: function set(val) {\n                        setter.call(_this4.domElement, val);\n                        // Only `set()` the value if the modification comes from an external source\n                        if (_this4.settings.watchExternalChanges && !_this4.internalModification) {\n                            _this4.set(val);\n                        }\n                    }\n                });\n            }\n\n            //FIXME The code above fails for the `textContent` attribute since `this.getterSetter` is undefined when using `getOwnPropertyDescriptor()`\n            /* //XXX The code below *almost* work for the textContent, but breaks some unit tests\n            this.valueWatched = this.domElement[this.attributeToWatch];\n            Object.defineProperty(this.domElement, this.attributeToWatch, {\n                configurable: true, // This is needed in some rare cases\n                get         : () => this.valueWatched,\n                set         : val => {\n                    this.valueWatched = val;\n                    // Only `set()` the value if the modification comes from an external source\n                    if (this.settings.watchExternalChanges && !this.internalModification) {\n                        this.set(val);\n                    }\n                },\n            });\n            */\n        }\n\n        /**\n         * Remove the watcher on the AutoNumeric-managed element\n         * Note: This needs to be called when the AutoNumeric element is 'removed', otherwise the getter/setter stays on the DOM element and that can lead to problem if the user initialize another AutoNumeric object on it.\n         * @private\n         */\n\n    }, {\n        key: '_removeWatcher',\n        value: function _removeWatcher() {\n            var _this5 = this;\n\n            // `getterSetter` can be undefined when a non-input element is used\n            if (!_AutoNumericHelper2.default.isUndefined(this.getterSetter)) {\n                var _getterSetter2 = this.getterSetter,\n                    setter = _getterSetter2.set,\n                    getter = _getterSetter2.get;\n\n                Object.defineProperty(this.domElement, this.attributeToWatch, {\n                    configurable: true, // This is needed in some rare cases\n                    get: function get() {\n                        return getter.call(_this5.domElement);\n                    },\n                    set: function set(val) {\n                        setter.call(_this5.domElement, val);\n                    }\n                });\n            }\n\n            //FIXME The code above fails for the `textContent` attribute since `this.getterSetter` is undefined when using `getOwnPropertyDescriptor()`\n            /* //XXX The code below *almost* work for the textContent, but breaks some unit tests\n            this.valueWatched = this.domElement[this.attributeToWatch];\n            Object.defineProperty(this.domElement, this.attributeToWatch, {\n                configurable: true, // This is needed in some rare cases\n                get         : () => this.valueWatched,\n                set         : val => {\n                    this.valueWatched = val;\n                },\n            });\n            */\n        }\n\n        /**\n         * Return the name of the object attribute that store the current formatted data in the DOM element.\n         *\n         * @returns {string}\n         * @private\n         */\n\n    }, {\n        key: '_getAttributeToWatch',\n        value: function _getAttributeToWatch() {\n            var attributeToWatch = void 0;\n            if (this.isInputElement) {\n                attributeToWatch = 'value';\n            } else {\n                var nodeType = this.domElement.nodeType;\n                if (nodeType === Node.ELEMENT_NODE || nodeType === Node.DOCUMENT_NODE || nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\n                    attributeToWatch = 'textContent';\n                } else if (nodeType === Node.TEXT_NODE) {\n                    attributeToWatch = 'nodeValue';\n                }\n            }\n\n            return attributeToWatch;\n        }\n\n        /**\n         * Save the current raw value into the history table, along with the selection information.\n         *\n         * If the user has done some undos and tries to enter:\n         * - a new and different number than the 'next' state, this drops the rest of the history table\n         * - the very same number that result in the same rawValue than the 'next' state, we only move the history table pointer to the next state\n         *\n         * @private\n         */\n\n    }, {\n        key: '_historyTableAdd',\n        value: function _historyTableAdd() {\n            //TODO Add a `this.settings.saveSelectionsIntoHistory` option to prevent saving the selections (in order to gain performance)\n            var isEmptyHistoryTable = this.historyTable.length === 0;\n            // Only add a new value if it's different than the previous one (to prevent infinitely adding values on mouseover for instance)\n            if (isEmptyHistoryTable || this.rawValue !== this._historyTableCurrentValueUsed()) {\n                // Trim the history table if the user changed the value of an intermediary state\n                var addNewHistoryState = true;\n                if (!isEmptyHistoryTable) {\n                    // If some undo has been done and the user type the exact same data than the next entry after the current history pointer, do no drop the rest of the 'redo' list, and just advance the historyTableIndex\n                    var nextHistoryStateIndex = this.historyTableIndex + 1;\n                    if (nextHistoryStateIndex < this.historyTable.length && this.rawValue === this.historyTable[nextHistoryStateIndex].value) {\n                        // If the character input result in the same state than the next one, do not remove the next history states nor add a new one\n                        addNewHistoryState = false;\n                    } else {\n                        // First remove anything that is after the current index\n                        _AutoNumericHelper2.default.arrayTrim(this.historyTable, this.historyTableIndex + 1);\n                    }\n                }\n\n                // Update the history pointer\n                this.historyTableIndex++;\n\n                // Add the new history state, if needed\n                if (addNewHistoryState) {\n                    // Save the selection info\n                    var selection = _AutoNumericHelper2.default.getElementSelection(this.domElement);\n                    this.selectionStart = selection.start;\n                    this.selectionEnd = selection.end;\n\n                    // Then add the new raw value\n                    this.historyTable.push({\n                        // Save the rawValue and selection start/end\n                        value: this.rawValue,\n                        // The selection for this element is temporary, and will be updated when the next history state will be recorded.\n                        // That way, we are always sure we save the last caret or selection positions just before the value is changed. Otherwise we would only save those positions when the value is first changed, and would not take into account that the user could move the caret around afterward.\n                        // For instance, this is needed if the user change the element value, and immediately undo it ; if he then does a redo, he'll see the value and the right selection\n                        // To sum up; The selection position are not always +1 character, since it could also be '2' if a group separator is added when entering one character. That's why the current history state caret/selection position is updated on each `keyup` event.\n                        start: this.selectionStart + 1, // Here we add one since the user added one character too\n                        end: this.selectionEnd + 1\n                    });\n\n                    // Update the selection in the previous entry, in order to keep track of the updated caret/selection positions\n                    if (this.historyTable.length > 1) {\n                        this.historyTable[this.historyTableIndex - 1].start = this.selectionStart;\n                        this.historyTable[this.historyTableIndex - 1].end = this.selectionEnd;\n                    }\n                }\n\n                // Limit the history table size according to the `historySize` option\n                if (this.historyTable.length > this.settings.historySize) {\n                    this._historyTableForget();\n                }\n            }\n        }\n\n        /**\n         * Debug function for the history table\n         * @private\n         */\n        /*\n        _debugHistoryTable() {\n            let i = 0;\n            let mark;\n            this.historyTable.forEach(history => {\n                if (this.historyTableIndex === i) {\n                    mark = '> ';\n                } else {\n                    mark = '';\n                }\n                console.log(`${mark}${i++}: ${history.value} ${history.start}|${history.end} [onGoingRedo: ${this.onGoingRedo}]`); //DEBUG\n            });\n        }\n        */\n\n        /**\n         * 'Undo' or 'Redo' the last/next user entry in the history table.\n         * This does not modify the history table, only the pointer to the current state.\n         *\n         * @param {boolean} undo If set to `true`, then this function does an 'Undo', otherwise it does a 'Redo'\n         * @private\n         */\n\n    }, {\n        key: '_historyTableUndoOrRedo',\n        value: function _historyTableUndoOrRedo() {\n            var undo = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;\n\n            var check = void 0;\n            if (undo) {\n                // Only 'undo' if there are some info to undo\n                check = this.historyTableIndex > 0;\n                if (check) {\n                    this.historyTableIndex--;\n                }\n            } else {\n                // Only 'redo' if there are some info to redo at the end of the history table\n                check = this.historyTableIndex + 1 < this.historyTable.length;\n                if (check) {\n                    this.historyTableIndex++;\n                }\n            }\n\n            if (check) {\n                // Set the value back\n                var undoInfo = this.historyTable[this.historyTableIndex];\n                this.set(undoInfo.value, null, false); // next or previous raw value\n\n                // Set the selection back\n                _AutoNumericHelper2.default.setElementSelection(this.domElement, undoInfo.start, undoInfo.end);\n            }\n        }\n\n        /**\n         * 'Undo' the last user entry by going back one entry in the history table.\n         * This keeps the following entries in order to allow for a 'redo'.\n         * This does not modify the history table, only the pointer to the current state.\n         * @private\n         */\n\n    }, {\n        key: '_historyTableUndo',\n        value: function _historyTableUndo() {\n            this._historyTableUndoOrRedo(true);\n        }\n\n        /**\n         * 'Redo' the next user entry in the history table.\n         * This does not modify the history table, only the pointer to the current state.\n         * @private\n         */\n\n    }, {\n        key: '_historyTableRedo',\n        value: function _historyTableRedo() {\n            this._historyTableUndoOrRedo(false);\n        }\n\n        /**\n         * Reset the history table to its initial state, and select the value.\n         * @private\n         */\n        /*\n        resetHistoryTable() { //FIXME Test this\n            this.set(this.rawValue, null, false);\n            this.select();\n            const selection = AutoNumericHelper.getElementSelection(this.domElement);\n            this.historyTableIndex = 0;\n            this.historyTable = [{\n                // Save the rawValue and selection start/end\n                value: this.rawValue,\n                start: selection.start,\n                end  : selection.end,\n            }];\n        }\n        */\n\n        /**\n         * Make the history table forget its first N elements, shifting its indexes in the process.\n         * `N` being given as the `numberOfEntriesToForget` parameter.\n         *\n         * @param {Number} numberOfEntriesToForget\n         * @returns {object|Array<object>} The discarded objects, in an Array.\n         * @private\n         */\n\n    }, {\n        key: '_historyTableForget',\n        value: function _historyTableForget() {\n            var numberOfEntriesToForget = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;\n\n            var shiftedAway = [];\n            for (var i = 0; i < numberOfEntriesToForget; i++) {\n                shiftedAway.push(this.historyTable.shift());\n                // Update the history table index accordingly\n                this.historyTableIndex--;\n                if (this.historyTableIndex < 0) {\n                    // In case this function is called more times than there is states in the history table\n                    this.historyTableIndex = 0;\n                }\n            }\n\n            if (shiftedAway.length === 1) {\n                return shiftedAway[0];\n            }\n\n            return shiftedAway;\n        }\n\n        /**\n         * Return the currently used value from the history table.\n         *\n         * @returns {string|number}\n         * @private\n         */\n\n    }, {\n        key: '_historyTableCurrentValueUsed',\n        value: function _historyTableCurrentValueUsed() {\n            var indexToUse = this.historyTableIndex;\n            if (indexToUse < 0) {\n                indexToUse = 0;\n            }\n\n            var result = void 0;\n            if (_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(this.historyTable[indexToUse])) {\n                result = '';\n            } else {\n                result = this.historyTable[indexToUse].value;\n            }\n\n            return result;\n        }\n\n        /**\n         * Parse the `styleRules` option and run the test for each given rules, either pre-defined ones like `positive`, `negative` and `ranges`, or user defined callbacks within the `userDefined` attribute.\n         * @private\n         */\n\n    }, {\n        key: '_parseStyleRules',\n        value: function _parseStyleRules() {\n            var _this6 = this;\n\n            if (_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(this.settings.styleRules) || this.rawValue === '') {\n                return;\n            }\n\n            // 'positive' attribute\n            if (!_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(this.settings.styleRules.positive)) {\n                if (this.rawValue >= 0) {\n                    this._addCSSClass(this.settings.styleRules.positive);\n                } else {\n                    this._removeCSSClass(this.settings.styleRules.positive);\n                }\n            }\n\n            // 'negative' attribute\n            if (!_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(this.settings.styleRules.negative)) {\n                if (this.rawValue < 0) {\n                    this._addCSSClass(this.settings.styleRules.negative);\n                } else {\n                    this._removeCSSClass(this.settings.styleRules.negative);\n                }\n            }\n\n            // 'ranges' attribute\n            if (!_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(this.settings.styleRules.ranges) && this.settings.styleRules.ranges.length !== 0) {\n                this.settings.styleRules.ranges.forEach(function (range) {\n                    if (_this6.rawValue >= range.min && _this6.rawValue < range.max) {\n                        _this6._addCSSClass(range.class);\n                    } else {\n                        _this6._removeCSSClass(range.class);\n                    }\n                });\n            }\n\n            // 'userDefined' attribute\n            //TODO Also pass the old raw value as a parameter, and not only the new raw value\n            if (!_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(this.settings.styleRules.userDefined) && this.settings.styleRules.userDefined.length !== 0) {\n                this.settings.styleRules.userDefined.forEach(function (userObject) {\n                    if (_AutoNumericHelper2.default.isFunction(userObject.callback)) {\n                        // Test for the type of the `classes` attribute, which changes the function behavior\n                        if (_AutoNumericHelper2.default.isString(userObject.classes)) {\n                            // If 'classes' is a string, set it if `true`, remove it if `false`\n                            if (userObject.callback(_this6.rawValue)) {\n                                _this6._addCSSClass(userObject.classes);\n                            } else {\n                                _this6._removeCSSClass(userObject.classes);\n                            }\n                        } else if (_AutoNumericHelper2.default.isArray(userObject.classes)) {\n                            if (userObject.classes.length === 2) {\n                                // If 'classes' is an array with only 2 elements, set the first class if `true`, the second if `false`\n                                if (userObject.callback(_this6.rawValue)) {\n                                    _this6._addCSSClass(userObject.classes[0]);\n                                    _this6._removeCSSClass(userObject.classes[1]);\n                                } else {\n                                    _this6._removeCSSClass(userObject.classes[0]);\n                                    _this6._addCSSClass(userObject.classes[1]);\n                                }\n                            } else if (userObject.classes.length > 2) {\n                                // The callback returns an array of indexes to use on the `classes` array\n                                var callbackResult = userObject.callback(_this6.rawValue);\n                                if (_AutoNumericHelper2.default.isArray(callbackResult)) {\n                                    // If multiple indexes are returned\n                                    userObject.classes.forEach(function (userClass, index) {\n                                        if (_AutoNumericHelper2.default.isInArray(index, callbackResult)) {\n                                            _this6._addCSSClass(userClass);\n                                        } else {\n                                            _this6._removeCSSClass(userClass);\n                                        }\n                                    });\n                                } else if (_AutoNumericHelper2.default.isInt(callbackResult)) {\n                                    // If only one index is returned\n                                    userObject.classes.forEach(function (userClass, index) {\n                                        if (index === callbackResult) {\n                                            _this6._addCSSClass(userClass);\n                                        } else {\n                                            _this6._removeCSSClass(userClass);\n                                        }\n                                    });\n                                } else if (_AutoNumericHelper2.default.isNull(callbackResult)) {\n                                    // Remove all the classes\n                                    userObject.classes.forEach(function (userClass) {\n                                        _this6._removeCSSClass(userClass);\n                                    });\n                                } else {\n                                    _AutoNumericHelper2.default.throwError('The callback result is not an array nor a valid array index, ' + (typeof callbackResult === 'undefined' ? 'undefined' : _typeof(callbackResult)) + ' given.');\n                                }\n                            } else {\n                                _AutoNumericHelper2.default.throwError('The classes attribute is not valid for the `styleRules` option.');\n                            }\n                        } else if (_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(userObject.classes)) {\n                            // If 'classes' is `undefined` or `null`, then the callback is called with the AutoNumeric object passed as a parameter\n                            userObject.callback(_this6);\n                        } else {\n                            _AutoNumericHelper2.default.throwError('The callback/classes structure is not valid for the `styleRules` option.');\n                        }\n                    } else {\n                        _AutoNumericHelper2.default.warning('The given `styleRules` callback is not a function, ' + (typeof callback === 'undefined' ? 'undefined' : _typeof(callback)) + ' given.', _this6.settings.showWarnings);\n                    }\n                });\n            }\n        }\n\n        /**\n         * Add the given CSS class to the DOM element.\n         *\n         * @param {string} cssClassName\n         * @private\n         */\n\n    }, {\n        key: '_addCSSClass',\n        value: function _addCSSClass(cssClassName) {\n            this.domElement.classList.add(cssClassName);\n        }\n\n        /**\n         * Remove the given CSS class from the DOM element.\n         *\n         * @param {string} cssClassName\n         * @private\n         */\n\n    }, {\n        key: '_removeCSSClass',\n        value: function _removeCSSClass(cssClassName) {\n            this.domElement.classList.remove(cssClassName);\n        }\n\n        // This are the public function available on each autoNumeric-managed element\n\n        /**\n         * Method that updates the AutoNumeric settings, and immediately format the element accordingly.\n         * The options passed as parameter(s) is either one or many objects that each contains some settings, ie. :\n         * {\n         *     digitGroupSeparator: \".\",\n         *     decimalCharacter: \",\",\n         *     currencySymbol: '€ ',\n         * }\n         * If multiple options are passed, the latter overwrite the previous ones.\n         *\n         * Note: If the new settings are not validated, or the call to `set()` fails, then the previous valid settings are reverted back to.\n         *\n         * @example anElement.update({ options }) // Updates the settings\n         * @example anElement.update({ options1 }, { options2 }) // Updates the settings with multiple option objects\n         * @example anElement.update([{ options1 }, { options2 }]) // Updates the settings with multiple option objects in a single array\n         *\n         * @param {object|string|array} newOptions\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'update',\n        value: function update() {\n            var _this7 = this;\n\n            for (var _len2 = arguments.length, newOptions = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n                newOptions[_key2] = arguments[_key2];\n            }\n\n            if (Array.isArray(newOptions) && Array.isArray(newOptions[0])) {\n                // Allows to pass a single array of options\n                newOptions = newOptions[0];\n            }\n\n            // Keep a copy of the original settings before changing them, in case they do not validate correctly, so we can switch back to them\n            var originalSettings = _AutoNumericHelper2.default.cloneObject(this.settings); //TODO Check that the `styleRules` option is correctly cloned (due to depth cloning limitation)\n\n            // Store the current unformatted input value\n            var numericString = this.rawValue;\n\n            // Generate a single option object with the settings from the latter overwriting those from the former\n            var optionsToUse = {};\n            if (_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(newOptions) || newOptions.length === 0) {\n                optionsToUse = null;\n            } else if (newOptions.length >= 1) {\n                newOptions.forEach(function (optionObject) {\n                    if (_this7.constructor._isPreDefinedOptionValid(optionObject)) {\n                        // The option object is a predefined option name (ie. 'euro')\n                        optionObject = _this7.constructor._getOptionObject(optionObject);\n                    }\n\n                    _extends(optionsToUse, optionObject);\n                });\n            }\n\n            // Update the settings\n            try {\n                this._setSettings(optionsToUse, true);\n                this._setWritePermissions(); // Update the read/write permissions\n                this._updateEventListeners();\n\n                // Reformat the input value with the new settings\n                // Note: we always `set`, even when `numericString` is the empty string '', since `emptyInputBehavior` (set to `always` or `zero`) can change how the empty input is formatted\n                this.set(numericString);\n            } catch (error) {\n                // If the settings validation fails, then we switch back to the previous valid settings\n                this._setSettings(originalSettings, true); // `_setSettings()` is used here instead of directly doing `this.settings = originalSettings;` since lots of side variables are calculated from the settings, and we need to get those back to their previous state. Note: `_setSettings()` is called in the 'update' mode in order to correctly set back the `originalDecimalPlacesRawValue` value.\n                _AutoNumericHelper2.default.throwError('Unable to update the settings, those are invalid: [' + error + ']');\n\n                return this;\n            }\n\n            return this;\n        }\n\n        /**\n         * Return the options object containing all the current autoNumeric settings in effect.\n         * You can then directly access each option by using its name : `anElement.getSettings().optionNameAutoCompleted`.\n         *\n         * @example\n         * anElement.getSettings()\n         * anElement.getSettings().decimalCharacter // Return the decimalCharacter setting as a string - any valid option name can be used\n         *\n         * @returns {object}\n         */\n\n    }, {\n        key: 'getSettings',\n        value: function getSettings() {\n            return this.settings;\n        }\n\n        /**\n         * Set the given element value, and format it immediately.\n         * Additionally, this `set()` method can accept options that will be merged into the current AutoNumeric element, taking precedence over any previous settings.\n         *\n         * @example anElement.set('12345.67') // Formats the value\n         * @example anElement.set(12345.67) // Formats the value\n         * @example anElement.set(12345.67, { decimalCharacter : ',' }) // Update the settings and formats the value in one go\n         * @example anElement.northAmerican().set('$12,345.67') // Set an already formatted value (this does not _exactly_ respect the currency symbol/negative placements, but only remove all non-numbers characters, according to the ones given in the settings)\n         * @example anElement.set(null) // Set the rawValue and element value to `null`\n         *\n         * @param {number|string|null} newValue The value must be a Number, a numeric string or `null` (if `emptyInputBehavior` is set to `'null'`)\n         * @param {object} options A settings object that will override the current settings. Note: the update is done only if the `newValue` is defined.\n         * @param {boolean} saveChangeToHistory If set to `true`, then the change is recorded in the history table\n         * @returns {AutoNumeric}\n         * @throws\n         */\n\n    }, {\n        key: 'set',\n        value: function set(newValue) {\n            var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n            var saveChangeToHistory = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;\n\n            //TODO Add the `saveSettings` options. If `true`, then when `options` is passed, then it overwrite the current `this.settings`. If `false` the `options` are only used once and `this.settings` is not modified\n            if (_AutoNumericHelper2.default.isUndefined(newValue)) {\n                _AutoNumericHelper2.default.warning('You are trying to set an \\'undefined\\' value ; an error could have occurred.', this.settings.showWarnings);\n                return this;\n            }\n\n            // The options update is done only if the `newValue` is not `undefined`\n            if (!_AutoNumericHelper2.default.isNull(options)) {\n                this._setSettings(options, true); // We do not call `update` here since this would call `set` too\n            }\n\n            if (newValue === null && this.settings.emptyInputBehavior !== AutoNumeric.options.emptyInputBehavior.null) {\n                _AutoNumericHelper2.default.warning('You are trying to set the `null` value while the `emptyInputBehavior` option is set to ' + this.settings.emptyInputBehavior + '. If you want to be able to set the `null` value, you need to change the \\'emptyInputBehavior\\' option to `\\'null\\'`.', this.settings.showWarnings);\n                return this;\n            }\n\n            var value = void 0;\n            if (newValue === null) {\n                //TODO Merge this into a global `if (newValue === null) {` test, with the test above\n                // Here this.settings.emptyInputBehavior === AutoNumeric.options.emptyInputBehavior.null\n                this._setElementAndRawValue(null, null, saveChangeToHistory);\n                this._saveValueToPersistentStorage();\n\n                return this;\n            }\n\n            value = this.constructor._toNumericValue(newValue, this.settings);\n            if (isNaN(Number(value))) {\n                //TODO Do not modify the element value if the newValue results in `NaN`. Make sure the settings, if modified, are revert back too.\n                _AutoNumericHelper2.default.warning('The value you are trying to set results in `NaN`. The element value is set to the empty string instead.', this.settings.showWarnings);\n                this.setValue('', saveChangeToHistory);\n\n                return this;\n            }\n\n            if (value === '') {\n                switch (this.settings.emptyInputBehavior) {\n                    case AutoNumeric.options.emptyInputBehavior.zero:\n                        value = 0;\n                        break;\n                    case AutoNumeric.options.emptyInputBehavior.min:\n                        value = this.settings.minimumValue;\n                        break;\n                    case AutoNumeric.options.emptyInputBehavior.max:\n                        value = this.settings.maximumValue;\n                        break;\n                    default:\n                        if (_AutoNumericHelper2.default.isNumber(this.settings.emptyInputBehavior)) {\n                            value = Number(this.settings.emptyInputBehavior);\n                        }\n                }\n            }\n\n            if (value !== '') {\n                var _constructor$_checkIf = this.constructor._checkIfInRangeWithOverrideOption(value, this.settings),\n                    _constructor$_checkIf2 = _slicedToArray(_constructor$_checkIf, 2),\n                    minTest = _constructor$_checkIf2[0],\n                    maxTest = _constructor$_checkIf2[1];\n\n                // Modify the formatted value if the rawValue is found in the `valuesToStrings` option\n\n\n                if (minTest && maxTest && this.settings.valuesToStrings && this._checkValuesToStrings(value)) {\n                    // Set the raw value normally, and the formatted value with the corresponding string\n                    this._setElementAndRawValue(this.settings.valuesToStrings[value], value, saveChangeToHistory);\n                    this._saveValueToPersistentStorage();\n\n                    return this;\n                }\n\n                // This test is needed by the `showPositiveSign` option\n                var isZero = _AutoNumericHelper2.default.isZeroOrHasNoValue(value);\n                if (isZero) {\n                    value = '0';\n                }\n\n                if (minTest && maxTest) {\n                    var forcedRawValue = this.constructor._roundRawValue(value, this.settings);\n                    forcedRawValue = this._trimLeadingAndTrailingZeros(forcedRawValue.replace(this.settings.decimalCharacter, '.')); // Move the `setRawValue` call after the `setElementValue` one\n                    value = this._getRawValueToFormat(value); // Multiply the raw value to obtain the formatted value\n\n                    // Round the given value according to the object state (focused/unfocused)\n                    if (this.isFocused) {\n                        value = this.constructor._roundFormattedValueShownOnFocus(value, this.settings);\n                    } else {\n                        if (this.settings.divisorWhenUnfocused) {\n                            value = value / this.settings.divisorWhenUnfocused;\n                            value = value.toString();\n                        }\n\n                        value = this.constructor._roundFormattedValueShownOnBlur(value, this.settings);\n                    }\n\n                    value = this.constructor._modifyNegativeSignAndDecimalCharacterForFormattedValue(value, this.settings);\n                    value = this.constructor._addGroupSeparators(value, this.settings, this.isFocused, this.rawValue, forcedRawValue);\n                    if (!this.isFocused && this.settings.symbolWhenUnfocused) {\n                        value = '' + value + this.settings.symbolWhenUnfocused;\n                    }\n\n                    if (this.settings.decimalPlacesShownOnFocus || this.settings.divisorWhenUnfocused) {\n                        this._saveValueToPersistentStorage();\n                    }\n\n                    this._setElementAndRawValue(value, forcedRawValue, saveChangeToHistory);\n\n                    return this;\n                } else {\n                    if (!minTest) {\n                        this._triggerEvent(AutoNumeric.events.minRangeExceeded, this.domElement);\n                    }\n\n                    if (!maxTest) {\n                        this._triggerEvent(AutoNumeric.events.maxRangeExceeded, this.domElement);\n                    }\n\n                    _AutoNumericHelper2.default.throwError('The value [' + value + '] being set falls outside of the minimumValue [' + this.settings.minimumValue + '] and maximumValue [' + this.settings.maximumValue + '] range set for this element');\n\n                    this._removeValueFromPersistentStorage();\n                    this.setValue('', saveChangeToHistory); //TODO Shouldn't we just drop that faulty newValue and keep the previous one? This is behind a `throwError()` call anyway..\n\n                    return this;\n                }\n            } else {\n                // Here, `value` equal the empty string `''`\n                var result = void 0;\n                if (this.settings.emptyInputBehavior === AutoNumeric.options.emptyInputBehavior.always) {\n                    // Keep the currency symbol as per emptyInputBehavior\n                    result = this.settings.currencySymbol;\n                } else {\n                    result = '';\n                }\n\n                this._setElementAndRawValue(result, '', saveChangeToHistory);\n\n                return this;\n            }\n        }\n\n        /**\n         * Set the given value directly as the DOM element value, without formatting it beforehand.\n         * You can also set the value and update the setting in one go (the value will again not be formatted immediately).\n         *\n         * @param {number|string} value\n         * @param {object} options\n         * @returns {AutoNumeric}\n         * @throws\n         */\n\n    }, {\n        key: 'setUnformatted',\n        value: function setUnformatted(value) {\n            var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n            //TODO Should we use `AutoNumeric.unformat()` here and set the unformatted result in case `value` is formatted?\n            if (value === null || _AutoNumericHelper2.default.isUndefined(value)) {\n                return this;\n            }\n\n            // The options update is done only if the `value` is not null\n            if (!_AutoNumericHelper2.default.isNull(options)) {\n                this._setSettings(options, true); // We do not call `update` here since this would call `set` too\n            }\n\n            var strippedValue = this.constructor._removeBrackets(value, this.settings);\n            var normalizedValue = this.constructor._stripAllNonNumberCharacters(strippedValue, this.settings, true, this.isFocused);\n            if (!_AutoNumericHelper2.default.isNumber(normalizedValue)) {\n                _AutoNumericHelper2.default.throwError('The value is not a valid one, it\\'s not a numeric string nor a recognized currency.');\n            }\n\n            var _constructor$_checkIf3 = this.constructor._checkIfInRangeWithOverrideOption(normalizedValue, this.settings),\n                _constructor$_checkIf4 = _slicedToArray(_constructor$_checkIf3, 2),\n                minTest = _constructor$_checkIf4[0],\n                maxTest = _constructor$_checkIf4[1];\n\n            if (minTest && maxTest) {\n                // If the `normalizedValue` is in the range\n                this.setValue(value);\n            } else {\n                _AutoNumericHelper2.default.throwError('The value is out of the range limits [' + this.settings.minimumValue + ', ' + this.settings.maximumValue + '].');\n            }\n\n            return this;\n        }\n\n        /**\n         * Set the given value directly as the DOM element value, without formatting it beforehand, and without checking its validity.\n         * This also updates the `rawValue` with the given `newValue`, without checking it too ; if it's not formatted like a number recognized by Javascript, this *will* likely make other AutoNumeric methods fail.\n         *\n         * @param {string|number|null} newValue The new value to set on the element\n         * @param {boolean} saveChangeToHistory If set to `true`, then the change is recorded in the history array, otherwise it is not\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'setValue',\n        value: function setValue(newValue) {\n            var saveChangeToHistory = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n\n            this._setElementAndRawValue(newValue, saveChangeToHistory);\n\n            return this;\n        }\n\n        /**\n         * Save the raw value inside the AutoNumeric object.\n         *\n         * @param {number|string|null} rawValue The numeric value as understood by Javascript like a `Number`\n         * @param {boolean} saveChangeToHistory If set to `true`, then the change is recorded in the history array, otherwise it is not\n         * @private\n         */\n\n    }, {\n        key: '_setRawValue',\n        value: function _setRawValue(rawValue) {\n            var saveChangeToHistory = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n\n            // Only set the raw value if the given value is different than the current one\n            if (this.rawValue !== rawValue) {\n                //TODO Manage the case where one value is a string while the other is a number?\n                var oldRawValue = this.rawValue;\n                // Update the raw value\n                this.rawValue = rawValue; // By default, if the `rawValue` is changed programmatically\n\n                if (!_AutoNumericHelper2.default.isNull(this.settings.rawValueDivisor) && this.settings.rawValueDivisor !== 0 && // Only divide if the `rawValueDivisor` option is set\n                rawValue !== '' && rawValue !== null && // Do not modify the `rawValue` if it's an empty string or null\n                this._isUserManuallyEditingTheValue()) {\n                    // If the user is manually changing the element value\n                    this.rawValue /= this.settings.rawValueDivisor;\n                }\n\n                // Broadcast the `rawValueModified` event since the `rawValue` has been modified\n                this._triggerEvent(AutoNumeric.events.rawValueModified, this.domElement, {\n                    oldRawValue: oldRawValue,\n                    newRawValue: this.rawValue,\n                    isPristine: this.isPristine(true),\n                    error: null,\n                    aNElement: this\n                });\n\n                // Change the element style or use the relevant callbacks\n                this._parseStyleRules();\n\n                if (saveChangeToHistory) {\n                    // Save in the history the last known raw value and formatted result selection\n                    this._historyTableAdd();\n                }\n            }\n        }\n\n        /**\n         * Set the given value on the DOM element, without affecting the `rawValue`.\n         * This send an 'autoNumeric:formatted' event if the new value is different than the old one.\n         *\n         * @param {number|string} newElementValue\n         * @param {boolean} sendFormattedEvent If set to `true`, then the `AutoNumeric.events.formatted` event is sent if the value has changed\n         * @returns {AutoNumeric}\n         * @private\n         */\n\n    }, {\n        key: '_setElementValue',\n        value: function _setElementValue(newElementValue) {\n            var sendFormattedEvent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n\n            //TODO Use an internal attribute to track the current value of the element `formattedValue` (like its counterpart `rawValue`). This would allow us to avoid calling `getElementValue` many times\n            var oldElementValue = _AutoNumericHelper2.default.getElementValue(this.domElement);\n\n            // Only update the value if it's different from the current one\n            if (newElementValue !== oldElementValue) {\n                this.internalModification = true;\n                _AutoNumericHelper2.default.setElementValue(this.domElement, newElementValue);\n                this.internalModification = false;\n\n                if (sendFormattedEvent) {\n                    this._triggerEvent(AutoNumeric.events.formatted, this.domElement, {\n                        oldValue: oldElementValue,\n                        newValue: newElementValue,\n                        oldRawValue: this.rawValue,\n                        newRawValue: this.rawValue,\n                        isPristine: this.isPristine(false),\n                        error: null,\n                        aNElement: this\n                    });\n                }\n            }\n\n            return this;\n        }\n\n        /**\n         * Set the given value on the DOM element, and the raw value on `this.rawValue`, if both are given.\n         * If only one value is given, then both the DOM element value and the raw value are set with that value.\n         * The third argument `saveChangeToHistory` defines if the change should be recorded in the history array.\n         * Note: if the second argument `rawValue` is a boolean, we consider that is really is the `saveChangeToHistory` argument.\n         *\n         * @param {number|string|null} newElementValue\n         * @param {number|string|null|boolean} rawValue\n         * @param {boolean} saveChangeToHistory\n         * @returns {AutoNumeric}\n         * @private\n         */\n\n    }, {\n        key: '_setElementAndRawValue',\n        value: function _setElementAndRawValue(newElementValue) {\n            var rawValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n            var saveChangeToHistory = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;\n\n            if (_AutoNumericHelper2.default.isNull(rawValue)) {\n                rawValue = newElementValue;\n            } else if (_AutoNumericHelper2.default.isBoolean(rawValue)) {\n                saveChangeToHistory = rawValue;\n                rawValue = newElementValue;\n            }\n\n            //XXX The order here is important ; the value should first be set on the element, then and only then we should update the raw value\n            // In the `set()` function, we make sure to call `_setRawValue` *after* `setElementValue` so that if `_setRawValue` calls a callback that modify the `rawValue`, then the new value is set correctly (after `setElementValue` briefly set its value first)\n            this._setElementValue(newElementValue);\n            this._setRawValue(rawValue, saveChangeToHistory);\n\n            return this;\n        }\n\n        /**\n         * Return the multiplied raw value with the `rawValueDivisor`.\n         * This is used to display different values between the raw and formatted values.\n         *\n         * @param {number|string|null} rawValue The numeric value as understood by Javascript like a `Number`\n         * @returns {number|string|null}\n         * @private\n         */\n\n    }, {\n        key: '_getRawValueToFormat',\n        value: function _getRawValueToFormat(rawValue) {\n            var rawValueForTheElementValue = void 0;\n            if (!_AutoNumericHelper2.default.isNull(this.settings.rawValueDivisor) && this.settings.rawValueDivisor !== 0 && // Only multiply if the `rawValueDivisor` option is set\n            rawValue !== '' && rawValue !== null) {\n                // Do not modify the `rawValue` if it's an empty string or null\n                // !this._isUserManuallyEditingTheValue()) { // If the user is NOT manually changing the element value, but that is done programmatically\n                rawValueForTheElementValue = rawValue * this.settings.rawValueDivisor;\n            } else {\n                rawValueForTheElementValue = rawValue;\n            }\n\n            return rawValueForTheElementValue;\n        }\n\n        /**\n         * Check if the given value has a corresponding key in the `valuesToStrings` option object.\n         *\n         * @param {number|string} value\n         * @returns {boolean} Returns `true` if such a key is found.\n         * @private\n         */\n\n    }, {\n        key: '_checkValuesToStrings',\n        value: function _checkValuesToStrings(value) {\n            return this.constructor._checkValuesToStringsArray(value, this.valuesToStringsKeys);\n        }\n\n        /**\n         * Check if the given value has a corresponding key in the `stringsArray` array.\n         *\n         * @param {number|string} key\n         * @param {array} stringsArray Array where the `key` is checked against its keys\n         * @returns {boolean} Returns `true` if such a key is found.\n         * @private\n         */\n\n    }, {\n        key: '_isUserManuallyEditingTheValue',\n\n\n        /**\n         * Return `true` if the user is currently modifying the element value manually.\n         *\n         * @returns {boolean}\n         * @private\n         */\n        value: function _isUserManuallyEditingTheValue() {\n            // return (this.isFocused && this.isEditing) || this.isWheelEvent || this.isDropEvent;\n            return this.isFocused && this.isEditing || this.isDropEvent;\n        }\n\n        /**\n         * Execute the given callback function using the given result as its first parameter, and the AutoNumeric object as its second.\n         *\n         * @param {number|string|Array|null} result\n         * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n         * @private\n         */\n\n    }, {\n        key: '_executeCallback',\n        value: function _executeCallback(result, callback) {\n            if (!_AutoNumericHelper2.default.isNull(callback) && _AutoNumericHelper2.default.isFunction(callback)) {\n                callback(result, this);\n            }\n        }\n\n        /**\n         * Trigger the given event on the given element with the given detail.\n         * This takes into account the `eventBubbles` and `eventIsCancelable` options.\n         *\n         * @param {string} eventName\n         * @param {HTMLElement|HTMLDocument|EventTarget} element\n         * @param {object} detail\n         * @private\n         */\n\n    }, {\n        key: '_triggerEvent',\n        value: function _triggerEvent(eventName) {\n            var element = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document;\n            var detail = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\n            _AutoNumericHelper2.default.triggerEvent(eventName, element, detail, this.settings.eventBubbles, this.settings.eventIsCancelable);\n        }\n\n        /**\n         * Alias of the `getNumericString()` function.\n         * Developers should use one of the more explicit function names to get what they want :\n         * - a numeric string : `getNumericString()`\n         * - a formatted string : `getFormatted()`\n         * - a number : `getNumber()`, or\n         * - a localized numeric string : `getLocalized()`\n         *\n         * @usage anElement.get();\n         *\n         * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n         *\n         * @deprecated\n         * @returns {string|null}\n         */\n\n    }, {\n        key: 'get',\n        value: function get() {\n            var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            return this.getNumericString(callback);\n        }\n\n        /**\n         * Return the unformatted value as a string.\n         * This can also return `null` if `rawValue` is null.\n         *\n         * @usage anElement.getNumericString();\n         *\n         * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n         *\n         * @returns {string|null}\n         */\n\n    }, {\n        key: 'getNumericString',\n        value: function getNumericString() {\n            var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            var result = void 0;\n            if (_AutoNumericHelper2.default.isNull(this.rawValue)) {\n                result = null;\n            } else {\n                // Always return a numeric string\n                // The following statement gets rid of the trailing zeros in the decimal places since the current method does not pad decimals\n                result = _AutoNumericHelper2.default.trimPaddedZerosFromDecimalPlaces(this.rawValue);\n            }\n\n            this._executeCallback(result, callback);\n\n            return result;\n        }\n\n        /**\n         * Return the current formatted value of the AutoNumeric element as a string\n         *\n         * @usage anElement.getFormatted()\n         *\n         * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n         *\n         * @returns {string}\n         */\n\n    }, {\n        key: 'getFormatted',\n        value: function getFormatted() {\n            var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            if (!('value' in this.domElement || 'textContent' in this.domElement)) {\n                // Make sure `.value` or `.textContent' exists before trying to access those properties\n                _AutoNumericHelper2.default.throwError('Unable to get the formatted string from the element.');\n            }\n\n            var result = _AutoNumericHelper2.default.getElementValue(this.domElement);\n            this._executeCallback(result, callback);\n\n            return result;\n        }\n\n        /**\n         * Return the element unformatted value as a real Javascript number.\n         * Warning: This can lead to precision problems with big numbers that should be stored as strings.\n         *\n         * @usage anElement.getNumber()\n         *\n         * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n         *\n         * @returns {number|null}\n         */\n\n    }, {\n        key: 'getNumber',\n        value: function getNumber() {\n            var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            var result = void 0;\n            if (this.rawValue === null) {\n                result = null;\n            } else {\n                result = this.constructor._toLocale(this.getNumericString(), 'number', this.settings);\n            }\n\n            this._executeCallback(result, callback);\n\n            return result;\n        }\n\n        /**\n         * Returns the unformatted value, but following the `outputFormat` setting, which means the output can either be :\n         * - a string (that could or could not represent a number (ie. \"12345,67-\")), or\n         * - a plain number (if the setting 'number' is used).\n         *\n         * By default the returned values are an ISO numeric string \"1234.56\" or \"-1234.56\" where the decimal character is a period.\n         * Check the \"outputFormat\" option definition for more details.\n         *\n         * @usage anElement.getLocalized();\n         *\n         * @param {null|string|function} forcedOutputFormat If set to something different than `null`, then this is used as an overriding outputFormat option\n         * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n         *\n         * @returns {*}\n         */\n\n    }, {\n        key: 'getLocalized',\n        value: function getLocalized() {\n            var forcedOutputFormat = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n            var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n            // First, check if only a callback has been passed, and if so, sanitize the parameters\n            if (_AutoNumericHelper2.default.isFunction(forcedOutputFormat) && _AutoNumericHelper2.default.isNull(callback)) {\n                callback = forcedOutputFormat;\n                forcedOutputFormat = null;\n            }\n\n            // Then get the localized value\n            var value = void 0;\n            if (_AutoNumericHelper2.default.isEmptyString(this.rawValue)) {\n                value = '';\n            } else {\n                // Here I use `this.rawValue` instead of `this.getNumericString()` since the current input value could be unformatted with a localization (ie. '1234567,89-').\n                // I also convert the rawValue to a number, then back to a string in order to drop the decimal part if the rawValue is an integer.\n                value = '' + Number(this.rawValue);\n            }\n\n            if (value !== '' && Number(value) === 0 && this.settings.leadingZero !== AutoNumeric.options.leadingZero.keep) {\n                value = '0';\n            }\n\n            var outputFormatToUse = void 0;\n            if (_AutoNumericHelper2.default.isNull(forcedOutputFormat)) {\n                outputFormatToUse = this.settings.outputFormat;\n            } else {\n                outputFormatToUse = forcedOutputFormat;\n            }\n\n            var result = this.constructor._toLocale(value, outputFormatToUse, this.settings);\n            this._executeCallback(result, callback);\n\n            return result;\n        }\n\n        /**\n         * Force the element to reformat its value again (just in case the formatting has been lost).\n         * This can be used right after a form submission for instance (after a previous call to `unformat`).\n         *\n         * @example anElement.reformat()\n         *\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'reformat',\n        value: function reformat() {\n            // `this.rawValue` is used instead of `this.domElement.value` because when the content is `unformatLocalized`, it can become a string that cannot be converted to a number easily\n            this.set(this.rawValue);\n\n            return this;\n        }\n\n        /**\n         * Remove the formatting and keep only the raw unformatted value in the element (as a numericString)\n         * Note: this is loosely based on the previous 'unSet()' function\n         *\n         * By default, values are returned as ISO numeric strings (ie. \"1234.56\" or \"-1234.56\"), where the decimal character is a period.\n         * @example anElement.unformat()\n         *\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'unformat',\n        value: function unformat() {\n            this._setElementValue(this.getNumericString());\n\n            return this;\n        }\n\n        /**\n         * Remove the formatting and keep only the localized unformatted value in the element, with the option to override the default outputFormat if needed\n         *\n         * Locale formats are supported \"1234.56-\" or \"1234,56\" or \"-1234,56 or \"1234,56-\", or even plain numbers.\n         * Take a look at the `outputFormat` option definition in the default settings for more details.\n         *\n         * @param {null|string} forcedOutputFormat If set to something different than `null`, then this is used as an overriding outputFormat option\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'unformatLocalized',\n        value: function unformatLocalized() {\n            var forcedOutputFormat = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            this._setElementValue(this.getLocalized(forcedOutputFormat));\n\n            return this;\n        }\n\n        /**\n         * Return `true` if the current value is the same as when the element got initialized.\n         * Note: By default, this returns `true` if the raw unformatted value is still the same even if the formatted one has changed (due to a configuration update for instance).\n         * In order to test if the formatted value is the same (which means neither the raw value nor the settings have been changed), then you must pass `false` as its argument.\n         *\n         * @param {boolean} checkOnlyRawValue If set to `true`, the pristine value is done on the raw unformatted value, not the formatted one.  If set to `false`, this also checks that the formatted value hasn't changed.\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isPristine',\n        value: function isPristine() {\n            var checkOnlyRawValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;\n\n            var result = void 0;\n            if (checkOnlyRawValue) {\n                result = this.initialValue === this.getNumericString();\n            } else {\n                result = this.initialValueHtmlAttribute === this.getFormatted();\n            }\n\n            return result;\n        }\n\n        /**\n         * Select the formatted element content, based on the `selectNumberOnly` option\n         *\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'select',\n        value: function select() {\n            if (this.settings.selectNumberOnly) {\n                this.selectNumber();\n            } else {\n                this._defaultSelectAll();\n            }\n\n            return this;\n        }\n\n        /**\n         * Select the whole element content (including the currency symbol).\n         * @private\n         */\n\n    }, {\n        key: '_defaultSelectAll',\n        value: function _defaultSelectAll() {\n            _AutoNumericHelper2.default.setElementSelection(this.domElement, 0, _AutoNumericHelper2.default.getElementValue(this.domElement).length);\n        }\n\n        /**\n         * Select only the numbers in the formatted element content, leaving out the currency symbol, whatever the value of the `selectNumberOnly` option\n         *\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'selectNumber',\n        value: function selectNumber() {\n            //TODO Make sure the selection is ok when showPositiveSign is set to `true` (select the negative sign, but not the positive one)\n            var unformattedValue = _AutoNumericHelper2.default.getElementValue(this.domElement);\n            var valueLen = unformattedValue.length;\n            var currencySymbolSize = this.settings.currencySymbol.length;\n            var currencySymbolPlacement = this.settings.currencySymbolPlacement;\n            var negLen = !_AutoNumericHelper2.default.isNegative(unformattedValue, this.settings.negativeSignCharacter) ? 0 : 1;\n            var suffixTextLen = this.settings.suffixText.length;\n\n            var start = void 0;\n            if (currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) {\n                start = 0;\n            } else if (this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.left && negLen === 1 && currencySymbolSize > 0) {\n                start = currencySymbolSize + 1;\n            } else {\n                start = currencySymbolSize;\n            }\n\n            var end = void 0;\n            if (currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix) {\n                end = valueLen - suffixTextLen;\n            } else {\n                switch (this.settings.negativePositiveSignPlacement) {\n                    case AutoNumeric.options.negativePositiveSignPlacement.left:\n                        end = valueLen - (suffixTextLen + currencySymbolSize);\n                        break;\n                    case AutoNumeric.options.negativePositiveSignPlacement.right:\n                        if (currencySymbolSize > 0) {\n                            end = valueLen - (currencySymbolSize + negLen + suffixTextLen);\n                        } else {\n                            end = valueLen - (currencySymbolSize + suffixTextLen);\n                        }\n                        break;\n                    default:\n                        end = valueLen - (currencySymbolSize + suffixTextLen);\n                }\n            }\n\n            _AutoNumericHelper2.default.setElementSelection(this.domElement, start, end);\n\n            return this;\n        }\n\n        /**\n         * Select only the integer part in the formatted element content, whatever the value of `selectNumberOnly`\n         *\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'selectInteger',\n        value: function selectInteger() {\n            var start = 0;\n            var isPositive = this.rawValue >= 0;\n\n            // Negative or positive sign, if any\n            if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix || this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix && (this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.prefix || this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.none)) {\n                if (this.settings.showPositiveSign && isPositive || // This only exclude the positive sign from being selected\n                !isPositive && this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix && this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.left) {\n                    // And this exclude the negative sign from being selected in this special case : '-€ 1.234,57suffixText'\n                    start = start + 1;\n                }\n            }\n\n            // Currency symbol\n            if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix) {\n                start = start + this.settings.currencySymbol.length;\n            }\n\n            // Calculate the selection end position\n            var elementValue = _AutoNumericHelper2.default.getElementValue(this.domElement);\n            var end = elementValue.indexOf(this.settings.decimalCharacter);\n            if (end === -1) {\n                // No decimal character found\n                if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) {\n                    end = elementValue.length - this.settings.currencySymbol.length;\n                } else {\n                    end = elementValue.length;\n                }\n\n                // Trailing negative sign\n                if (!isPositive && (this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.suffix || this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix)) {\n                    end = end - 1;\n                }\n\n                // Avoid selecting the suffix test\n                end = end - this.settings.suffixText.length;\n            }\n\n            _AutoNumericHelper2.default.setElementSelection(this.domElement, start, end);\n\n            return this;\n        }\n\n        /**\n         * Select only the decimal part in the formatted element content, whatever the value of `selectNumberOnly`\n         * Multiple cases are possible :\n         * +1.234,57suffixText\n         *\n         * € +1.234,57suffixText\n         * +€ 1.234,57suffixText\n         * € 1.234,57+suffixText\n         *\n         * 1.234,57+ €suffixText\n         * 1.234,57 €+suffixText\n         * +1.234,57 €suffixText\n         *\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'selectDecimal',\n        value: function selectDecimal() {\n            var start = _AutoNumericHelper2.default.getElementValue(this.domElement).indexOf(this.settings.decimalCharacter);\n            var end = void 0;\n\n            if (start === -1) {\n                // The decimal character has not been found, we deselect all\n                start = 0;\n                end = 0;\n            } else {\n                // A decimal character has been found\n                start = start + 1; // We add 1 to exclude the decimal character from the selection\n\n                var decimalCount = void 0;\n                if (this.isFocused) {\n                    decimalCount = this.settings.decimalPlacesShownOnFocus;\n                } else {\n                    decimalCount = this.settings.decimalPlacesShownOnBlur;\n                }\n\n                end = start + Number(decimalCount);\n            }\n\n            _AutoNumericHelper2.default.setElementSelection(this.domElement, start, end);\n\n            return this;\n        }\n\n        /**\n         * Return the DOM element reference of the autoNumeric-managed element\n         *\n         * @returns {HTMLElement|HTMLInputElement}\n         */\n\n    }, {\n        key: 'node',\n        value: function node() {\n            return this.domElement;\n        }\n\n        /**\n         * Return the DOM element reference of the parent node of the autoNumeric-managed element\n         *\n         * @returns {HTMLElement|HTMLInputElement|Node}\n         */\n\n    }, {\n        key: 'parent',\n        value: function parent() {\n            return this.domElement.parentNode;\n        }\n\n        /**\n         * Detach the current AutoNumeric element from the shared local 'init' list.\n         * This means any changes made on that local shared list will not be transmitted to that element anymore.\n         * Note : The user can provide another AutoNumeric element, and detach this one instead of the current one.\n         *\n         * @param {AutoNumeric} otherAnElement\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'detach',\n        value: function detach() {\n            var otherAnElement = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n            //FIXME test this\n            var domElementToDetach = void 0;\n            if (!_AutoNumericHelper2.default.isNull(otherAnElement)) {\n                domElementToDetach = otherAnElement.node();\n            } else {\n                domElementToDetach = this.domElement;\n            }\n\n            this._removeFromLocalList(domElementToDetach); //FIXME What happens if the selected dom element does not exist in the list?\n\n            return this;\n        }\n\n        /**\n         * Attach the given AutoNumeric element to the shared local 'init' list.\n         * When doing that, by default the DOM content is left untouched.\n         * The user can force a reformat with the new shared list options by passing a second argument to `true`.\n         *\n         * @param {AutoNumeric} otherAnElement\n         * @param {boolean} reFormat\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'attach',\n        value: function attach(otherAnElement) {\n            var reFormat = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n            //FIXME test this\n            this._addToLocalList(otherAnElement.node()); //FIXME Should we make sure the element is not already in the list?\n            if (reFormat) {\n                otherAnElement.update(this.settings);\n            }\n\n            return this;\n        }\n\n        /**\n         * Format and return the given value, or set the formatted value into the given DOM element if one is passed as an argument.\n         * By default, this use the current element settings.\n         * The user can override any option of its choosing by passing an option object.\n         *\n         * @param {number|HTMLElement|HTMLInputElement} valueOrElement\n         * @param {null|object} optionOverride\n         * @returns {string|null}\n         */\n\n    }, {\n        key: 'formatOther',\n        value: function formatOther(valueOrElement) {\n            var optionOverride = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n            //FIXME test this\n            return this._formatOrUnformatOther(true, valueOrElement, optionOverride);\n        }\n\n        /**\n         * Unformat and return the raw numeric string corresponding to the given value, or directly set the unformatted value into the given DOM element if one is passed as an argument.\n         * By default, this use the current element settings.\n         * The user can override any option of its choosing by passing an option object.\n          * @param {string|HTMLElement|HTMLInputElement} stringOrElement\n         * @param {null|object} optionOverride\n         * @returns {string|null}\n         */\n\n    }, {\n        key: 'unformatOther',\n        value: function unformatOther(stringOrElement) {\n            var optionOverride = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n            //FIXME test this\n            return this._formatOrUnformatOther(false, stringOrElement, optionOverride);\n        }\n\n        /**\n         * Method that either format or unformat the value of another element.\n         *\n         * - Format and return the given value, or set the formatted value into the given DOM element if one is passed as an argument.\n         * - Unformat and return the raw numeric string corresponding to the given value, or directly set the unformatted value into the given DOM element if one is passed as an argument.\n         *\n         * By default, this use the current element settings.\n         * The user can override any option of its choosing by passing an option object.\n         *\n         * @param {boolean} isFormatting If set to `true`, then the method formats, otherwise if set to `false`, it unformats\n         * @param {number|string|HTMLElement|HTMLInputElement} valueOrStringOrElement\n         * @param {null|object} optionOverride\n         * @returns {string|null}\n         * @private\n         */\n\n    }, {\n        key: '_formatOrUnformatOther',\n        value: function _formatOrUnformatOther(isFormatting, valueOrStringOrElement) {\n            var optionOverride = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n            //FIXME test this\n            // If the user wants to override the current element settings temporarily\n            var settingsToUse = void 0;\n            if (!_AutoNumericHelper2.default.isNull(optionOverride)) {\n                settingsToUse = this._cloneAndMergeSettings(optionOverride);\n            } else {\n                settingsToUse = this.settings;\n            }\n\n            // Then the unformatting is done...\n            var result = void 0;\n            if (_AutoNumericHelper2.default.isElement(valueOrStringOrElement)) {\n                // ...either directly on the DOM element value\n                var elementValue = _AutoNumericHelper2.default.getElementValue(valueOrStringOrElement);\n                if (isFormatting) {\n                    result = AutoNumeric.format(elementValue, settingsToUse);\n                } else {\n                    result = AutoNumeric.unformat(elementValue, settingsToUse);\n                }\n\n                _AutoNumericHelper2.default.setElementValue(valueOrStringOrElement, result); //TODO Use `unformatAndSet` and `formatAndSet`instead\n\n                return null;\n            }\n\n            // ...or on the given value\n            if (isFormatting) {\n                result = AutoNumeric.format(valueOrStringOrElement, settingsToUse);\n            } else {\n                result = AutoNumeric.unformat(valueOrStringOrElement, settingsToUse);\n            }\n\n            return result;\n        }\n\n        /**\n         * Use the current AutoNumeric element settings to initialize the DOM element(s) given as a parameter.\n         * Doing so will *link* the AutoNumeric elements together since they will share the same local AutoNumeric element list.\n         * (cf. prototype pattern : https://en.wikipedia.org/wiki/Prototype_pattern)\n         *\n         * You can `init` either a single DOM element (in that case an AutoNumeric object will be returned), or an array of DOM elements or a string that will be used as a CSS selector. In the latter cases, an array of AutoNumeric objects will then be returned (or an empty array if nothing gets selected by the CSS selector).\n         *\n         * Use case : Once you have an AutoNumeric element already setup correctly with the right options, you can use it as many times you want to initialize as many other DOM elements as needed.\n         * Note : this works only on elements that can be managed by autoNumeric.\n         *\n         * @param {HTMLElement|HTMLInputElement|Array<HTMLElement|HTMLInputElement>|string} domElementOrArrayOrString\n         * @param {boolean} attached If set to `false`, then the newly generated AutoNumeric element will not share the same local element list\n         * @returns {AutoNumeric|[AutoNumeric]}\n         */\n\n    }, {\n        key: 'init',\n        value: function init(domElementOrArrayOrString) {\n            var _this8 = this;\n\n            var attached = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n\n            var returnASingleAutoNumericObject = false; // By default, this function returns an array of AutoNumeric objects\n            var domElementsArray = [];\n            if (_AutoNumericHelper2.default.isString(domElementOrArrayOrString)) {\n                domElementsArray = [].concat(_toConsumableArray(document.querySelectorAll(domElementOrArrayOrString))); // Convert a NodeList to an Array\n            } else if (_AutoNumericHelper2.default.isElement(domElementOrArrayOrString)) {\n                domElementsArray.push(domElementOrArrayOrString);\n                returnASingleAutoNumericObject = true; // Special case when only one DOM element is passed as a parameter\n            } else if (_AutoNumericHelper2.default.isArray(domElementOrArrayOrString)) {\n                domElementsArray = domElementOrArrayOrString;\n            } else {\n                _AutoNumericHelper2.default.throwError('The given parameters to the \\'init\\' function are invalid.');\n            }\n\n            if (domElementsArray.length === 0) {\n                _AutoNumericHelper2.default.warning('No valid DOM elements were given hence no AutoNumeric object were instantiated.', true);\n\n                return [];\n            }\n\n            var currentLocalList = this._getLocalList();\n            var autoNumericObjectsArray = [];\n\n            // Instantiate (and link depending on `attached`) each AutoNumeric objects\n            domElementsArray.forEach(function (domElement) {\n                // Initialize the new AutoNumeric element\n                var originalCreateLocalListSetting = _this8.settings.createLocalList;\n                if (attached) {\n                    // Temporary variable to know if we should create the local list during the initialization (since we'll remove it afterwards)\n                    _this8.settings.createLocalList = false;\n                }\n\n                var newAutoNumericElement = new AutoNumeric(domElement, _AutoNumericHelper2.default.getElementValue(domElement), _this8.settings);\n\n                // Set the common shared local list if needed\n                // If the user wants to create a detached new AutoNumeric element, then skip the following step that bind the two elements together by default\n                if (attached) {\n                    // 1) Set the local list reference to point to the initializer's one\n                    newAutoNumericElement._setLocalList(currentLocalList);\n\n                    // 2) Add the new element to that existing list\n                    _this8._addToLocalList(domElement, newAutoNumericElement); // Here we use the *new* AutoNumeric object reference to add to the local list, since we'll need the reference to `this` in the methods to points to that new AutoNumeric object.\n                    _this8.settings.createLocalList = originalCreateLocalListSetting;\n                }\n\n                autoNumericObjectsArray.push(newAutoNumericElement);\n            });\n\n            if (returnASingleAutoNumericObject) {\n                // If a single DOM element was used as the parameter, then we return an AutoNumeric object directly\n                return autoNumericObjectsArray[0];\n            }\n\n            // ...otherwise we return an Array of AutoNumeric objects\n            return autoNumericObjectsArray;\n        }\n\n        /**\n         * Reset the element value either to the empty string '', or the currency sign, depending on the `emptyInputBehavior` option value.\n         * If you set the `forceClearAll` argument to `true`, then the `emptyInputBehavior` option is overridden and the whole input is clear, including any currency sign.\n         *\n         * @param {boolean} forceClearAll\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'clear',\n        value: function clear() {\n            var forceClearAll = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n\n            if (forceClearAll) {\n                var temporaryForcedOptions = {\n                    emptyInputBehavior: AutoNumeric.options.emptyInputBehavior.focus\n                };\n                this.set('', temporaryForcedOptions);\n            } else {\n                this.set('');\n            }\n\n            return this;\n        }\n\n        /**\n         * Remove the autoNumeric data and event listeners from the element, but keep the element content intact.\n         * This also clears the value from sessionStorage (or cookie, depending on browser supports).\n         * Note: this does not remove the formatting.\n         *\n         * @example anElement.remove()\n         */\n\n    }, {\n        key: 'remove',\n        value: function remove() {\n            this._removeValueFromPersistentStorage();\n            this._removeEventListeners();\n            this._removeWatcher();\n\n            // Also remove the element from the local AutoNumeric list\n            this._removeFromLocalList(this.domElement);\n            // Also remove the element from the global AutoNumeric list\n            this.constructor._removeFromGlobalList(this);\n        }\n\n        /**\n         * Remove the autoNumeric data and event listeners from the element, and reset its value to the empty string ''.\n         * This also clears the value from sessionStorage (or cookie, depending on browser supports).\n         *\n         * @example anElement.wipe()\n         */\n\n    }, {\n        key: 'wipe',\n        value: function wipe() {\n            this._setElementValue('', false); // Do not send the 'AutoNumeric.events.formatted' event when wiping an AutoNumeric object\n            this.remove();\n        }\n\n        /**\n         * Remove the autoNumeric data and event listeners from the element, and delete the DOM element altogether\n         */\n\n    }, {\n        key: 'nuke',\n        value: function nuke() {\n            this.remove();\n            // Remove the element from the DOM\n            this.domElement.parentNode.removeChild(this.domElement);\n        }\n\n        // Special functions that really work on the parent <form> element, instead of the <input> element itself\n\n        /**\n         * Return a reference to the parent <form> element if it exists, otherwise return `null`.\n         * If the parent form element as already been found, this directly return a reference to it.\n         * However, you can force AutoNumeric to search again for its reference by passing `true` as a parameter to this method.\n         * This method updates the `this.parentForm` attribute.\n         *\n         * In either case, whenever a new parent form is set for the current AutoNumeric element, we make sure to update the anCount and anFormHandler attributes on both the old form and the new one (for instance in case the user moved the input elements with `appendChild()` since AutoNumeric cannot not detect that).\n         *\n         * @param {boolean} forceSearch If set to `true`, the parent form is searched again, even if `this.parentForm` is already set.\n         *\n         * @returns {HTMLFormElement|null}\n         */\n\n    }, {\n        key: 'form',\n        value: function form() {\n            var forceSearch = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n\n            if (forceSearch || _AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(this.parentForm)) {\n                var newParentForm = this._getParentForm();\n                if (!_AutoNumericHelper2.default.isNull(newParentForm) && newParentForm !== this.parentForm) {\n                    // If the current parent form exists and is different from the previous parent form\n\n                    // Search for all the AutoNumeric elements in the old parent form\n                    var oldANChildren = this._getFormAutoNumericChildren(this.parentForm);\n                    // Update the anCount with the correct number of AutoNumeric elements\n                    this.parentForm.dataset.anCount = oldANChildren.length;\n\n                    // Check if the new parent form already has a anFormHandler name\n                    if (this._hasFormHandlerFunction(newParentForm)) {\n                        this._incrementParentFormCounter(newParentForm); // Increment its counter\n                    } else {\n                        // Create one and set the anCount to 1\n                        this._storeFormHandlerFunction(newParentForm);\n                        this._initializeFormCounterToOne(newParentForm);\n                    }\n                }\n\n                this.parentForm = newParentForm;\n            }\n\n            return this.parentForm;\n        }\n\n        /**\n         * Return an array of the AutoNumeric-managed elements for the given form element is passed, otherwise for the current `this.parentForm` element.\n         *\n         * @param {HTMLFormElement|null} formElement\n         *\n         * @returns {Array.<HTMLInputElement>}\n         * @private\n         */\n\n    }, {\n        key: '_getFormAutoNumericChildren',\n        value: function _getFormAutoNumericChildren(formElement) {\n            var _this9 = this;\n\n            // Search for all the child AutoNumeric elements in that parent form\n            //TODO This only search for <input> elements, not contenteditable non-input tag ones, for now. Add a parameter to allow this function to search on every tags.\n            var inputList = [].concat(_toConsumableArray(formElement.querySelectorAll('input')));\n\n            return inputList.filter(function (input) {\n                return _this9.constructor.isManagedByAutoNumeric(input);\n            });\n        }\n\n        /**\n         * Return a reference to the parent <form> element if it exists, otherwise return `null`.\n         *\n         * @returns {HTMLFormElement|null}\n         * @private\n         */\n\n    }, {\n        key: '_getParentForm',\n        value: function _getParentForm() {\n            if (this.domElement.tagName.toLowerCase() === 'body') {\n                return null;\n            }\n\n            var node = this.domElement;\n            var tagName = void 0;\n            do {\n                node = node.parentNode;\n                if (_AutoNumericHelper2.default.isNull(node)) {\n                    // Special case when using templates with frameworks like Vue.js, where the input element can be 'detached' when initializing the DOM structure\n                    return null;\n                }\n\n                if (node.tagName) {\n                    tagName = node.tagName.toLowerCase();\n                } else {\n                    tagName = '';\n                }\n\n                if (tagName === 'body') {\n                    // Get out of the loop if we get up to the `<body>` element\n                    break;\n                }\n            } while (tagName !== 'form');\n\n            if (tagName === 'form') {\n                return node;\n            } else {\n                return null;\n            }\n        }\n\n        /**\n         * Return a string in standard URL-encoded notation with the form input values being unformatted.\n         * This string can be used as a query for instance.\n         *\n         * @returns {string}\n         */\n\n    }, {\n        key: 'formNumericString',\n        value: function formNumericString() {\n            return this.constructor._serializeNumericString(this.form(), this.settings.serializeSpaces);\n        }\n\n        /**\n         * Return a string in standard URL-encoded notation with the form input values being formatted.\n         *\n         * @returns {string}\n         */\n\n    }, {\n        key: 'formFormatted',\n        value: function formFormatted() {\n            return this.constructor._serializeFormatted(this.form(), this.settings.serializeSpaces);\n        }\n\n        /**\n         * Return a string in standard URL-encoded notation with the form input values, with localized values.\n         * The default output format can be overridden by passing the option as a parameter.\n         *\n         * @param {null|string} forcedOutputFormat If set to something different than `null`, then this is used as an overriding outputFormat option\n         * @returns {string}\n         */\n\n    }, {\n        key: 'formLocalized',\n        value: function formLocalized() {\n            var forcedOutputFormat = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            var outputFormatToUse = void 0;\n            if (_AutoNumericHelper2.default.isNull(forcedOutputFormat)) {\n                outputFormatToUse = this.settings.outputFormat;\n            } else {\n                outputFormatToUse = forcedOutputFormat;\n            }\n\n            return this.constructor._serializeLocalized(this.form(), this.settings.serializeSpaces, outputFormatToUse);\n        }\n\n        /**\n         * Return an array containing an object for each form <input> element.\n         * Those objects are of the following structure `{ name: foo, value: '42' }`, where the `name` is the DOM element name, and the `value` is an unformatted numeric string.\n         *\n         * @returns {Array}\n         */\n\n    }, {\n        key: 'formArrayNumericString',\n        value: function formArrayNumericString() {\n            return this.constructor._serializeNumericStringArray(this.form(), this.settings.serializeSpaces);\n        }\n\n        /**\n         * Return an array containing an object for each form <input> element.\n         * Those objects are of the following structure `{ name: foo, value: '42' }`, where the `name` is the DOM element name, and the `value` is the formatted string.\n         *\n         * @returns {Array}\n         */\n\n    }, {\n        key: 'formArrayFormatted',\n        value: function formArrayFormatted() {\n            return this.constructor._serializeFormattedArray(this.form(), this.settings.serializeSpaces);\n        }\n\n        /**\n         * Return an array containing an object for each form <input> element.\n         * Those objects are of the following structure `{ name: foo, value: '42' }`, where the `name` is the DOM element name, and the `value` is the localized numeric string.\n         *\n         * @param {null|string} forcedOutputFormat If set to something different than `null`, then this is used as an overriding outputFormat option\n         * @returns {Array}\n         */\n\n    }, {\n        key: 'formArrayLocalized',\n        value: function formArrayLocalized() {\n            var forcedOutputFormat = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            var outputFormatToUse = void 0;\n            if (_AutoNumericHelper2.default.isNull(forcedOutputFormat)) {\n                outputFormatToUse = this.settings.outputFormat;\n            } else {\n                outputFormatToUse = forcedOutputFormat;\n            }\n\n            return this.constructor._serializeLocalizedArray(this.form(), this.settings.serializeSpaces, outputFormatToUse);\n        }\n\n        /**\n         * Return a JSON string containing an object representing the form input values.\n         * This is based on the result of the `formArrayNumericString()` function.\n         *\n         * @returns {string}\n         */\n\n    }, {\n        key: 'formJsonNumericString',\n        value: function formJsonNumericString() {\n            return JSON.stringify(this.formArrayNumericString());\n        }\n\n        /**\n         * Return a JSON string containing an object representing the form input values.\n         * This is based on the result of the `formArrayFormatted()` function.\n         *\n         * @returns {string}\n         */\n\n    }, {\n        key: 'formJsonFormatted',\n        value: function formJsonFormatted() {\n            return JSON.stringify(this.formArrayFormatted());\n        }\n\n        /**\n         * Return a JSON string containing an object representing the form input values.\n         * This is based on the result of the `formArrayLocalized()` function.\n         *\n         * @param {null|string} forcedOutputFormat If set to something different than `null`, then this is used as an overriding outputFormat option\n         * @returns {string}\n         */\n\n    }, {\n        key: 'formJsonLocalized',\n        value: function formJsonLocalized() {\n            var forcedOutputFormat = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            return JSON.stringify(this.formArrayLocalized(forcedOutputFormat));\n        }\n\n        /**\n         * Unformat all the autoNumeric-managed elements that are a child of the parent <form> element of this DOM element, to numeric strings\n         *\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'formUnformat',\n        value: function formUnformat() {\n            //FIXME test this\n            var inputs = this.constructor._getChildANInputElement(this.form());\n            inputs.forEach(function (input) {\n                AutoNumeric.getAutoNumericElement(input).unformat();\n            });\n\n            return this;\n        }\n\n        /**\n         * Unformat all the autoNumeric-managed elements that are a child of the parent <form> element of this DOM element, to localized strings\n         *\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'formUnformatLocalized',\n        value: function formUnformatLocalized() {\n            //FIXME test this\n            var inputs = this.constructor._getChildANInputElement(this.form());\n            inputs.forEach(function (input) {\n                AutoNumeric.getAutoNumericElement(input).unformatLocalized();\n            });\n\n            return this;\n        }\n\n        /**\n         * Reformat all the autoNumeric-managed elements that are a child of the parent <form> element of this DOM element\n         *\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'formReformat',\n        value: function formReformat() {\n            //FIXME test this\n            var inputs = this.constructor._getChildANInputElement(this.form());\n            inputs.forEach(function (input) {\n                AutoNumeric.getAutoNumericElement(input).reformat();\n            });\n\n            return this;\n        }\n\n        /**\n         * Convert the input values to numeric strings, submit the form, then reformat those back.\n         * The function can either take a callback, or not. If it doesn't, the default `form.submit()` function will be called.\n         * Otherwise, it runs `callback(value)` with `value` being equal to the result of `formNumericString()`.\n         *\n         * @param {function|null} callback\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'formSubmitNumericString',\n        value: function formSubmitNumericString() {\n            var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n            //FIXME test this\n            if (_AutoNumericHelper2.default.isNull(callback)) {\n                this.formUnformat();\n                this.form().submit();\n                this.formReformat();\n            } else if (_AutoNumericHelper2.default.isFunction(callback)) {\n                callback(this.formNumericString());\n            } else {\n                _AutoNumericHelper2.default.throwError('The given callback is not a function.');\n            }\n\n            return this;\n        }\n\n        /**\n         * Submit the form with the current formatted values.\n         * The function can either take a callback, or not. If it doesn't, the default `form.submit()` function will be called.\n         * Otherwise, it runs `callback(value)` with `value` being equal to the result of `formFormatted()`.\n         *\n         * @param {function|null} callback\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'formSubmitFormatted',\n        value: function formSubmitFormatted() {\n            var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n            //FIXME test this\n            if (_AutoNumericHelper2.default.isNull(callback)) {\n                this.form().submit();\n            } else if (_AutoNumericHelper2.default.isFunction(callback)) {\n                callback(this.formFormatted());\n            } else {\n                _AutoNumericHelper2.default.throwError('The given callback is not a function.');\n            }\n\n            return this;\n        }\n\n        /**\n         * Convert the input values to localized strings, submit the form, then reformat those back.\n         * The function can either take a callback, or not. If it doesn't, the default `form.submit()` function will be called.\n         * Otherwise, it runs `callback(value)` with `value` being equal to the result of `formLocalized()`.\n         *\n         * @param {null|string} forcedOutputFormat If set to something different than `null`, then this is used as an overriding outputFormat option\n         * @param {function|null} callback\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'formSubmitLocalized',\n        value: function formSubmitLocalized() {\n            var forcedOutputFormat = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n            var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n            //FIXME test this\n            if (_AutoNumericHelper2.default.isNull(callback)) {\n                this.formUnformatLocalized();\n                this.form().submit();\n                this.formReformat();\n            } else if (_AutoNumericHelper2.default.isFunction(callback)) {\n                callback(this.formLocalized(forcedOutputFormat));\n            } else {\n                _AutoNumericHelper2.default.throwError('The given callback is not a function.');\n            }\n\n            return this;\n        }\n\n        /**\n         * Generate an array of numeric strings from the `<input>` elements, and pass it to the given callback.\n         * Under the hood, the array is generated via a call to `formArrayNumericString()`.\n         *\n         * @param {function} callback\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'formSubmitArrayNumericString',\n        value: function formSubmitArrayNumericString(callback) {\n            //FIXME test this\n            if (_AutoNumericHelper2.default.isFunction(callback)) {\n                callback(this.formArrayNumericString());\n            } else {\n                _AutoNumericHelper2.default.throwError('The given callback is not a function.');\n            }\n\n            return this;\n        }\n\n        /**\n         * Generate an array of the current formatted values from the `<input>` elements, and pass it to the given callback.\n         * Under the hood, the array is generated via a call to `formArrayFormatted()`.\n         *\n         * @param {function} callback\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'formSubmitArrayFormatted',\n        value: function formSubmitArrayFormatted(callback) {\n            //FIXME test this\n            if (_AutoNumericHelper2.default.isFunction(callback)) {\n                callback(this.formArrayFormatted());\n            } else {\n                _AutoNumericHelper2.default.throwError('The given callback is not a function.');\n            }\n\n            return this;\n        }\n\n        /**\n         * Generate an array of localized strings from the `<input>` elements, and pass it to the given callback.\n         * Under the hood, the array is generated via a call to `formArrayLocalized()`.\n         *\n         * @param {function} callback\n         * @param {null|string} forcedOutputFormat If set to something different than `null`, then this is used as an overriding outputFormat option\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'formSubmitArrayLocalized',\n        value: function formSubmitArrayLocalized(callback) {\n            var forcedOutputFormat = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n            //FIXME test this\n            if (_AutoNumericHelper2.default.isFunction(callback)) {\n                callback(this.formArrayLocalized(forcedOutputFormat));\n            } else {\n                _AutoNumericHelper2.default.throwError('The given callback is not a function.');\n            }\n\n            return this;\n        }\n\n        /**\n         * Generate a JSON string with the numeric strings values from the `<input>` elements, and pass it to the given callback.\n         * Under the hood, the array is generated via a call to `formJsonNumericString()`.\n         *\n         * @param {function} callback\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'formSubmitJsonNumericString',\n        value: function formSubmitJsonNumericString(callback) {\n            //FIXME test this\n            if (_AutoNumericHelper2.default.isFunction(callback)) {\n                callback(this.formJsonNumericString());\n            } else {\n                _AutoNumericHelper2.default.throwError('The given callback is not a function.');\n            }\n\n            return this;\n        }\n\n        /**\n         * Generate a JSON string with the current formatted values from the `<input>` elements, and pass it to the given callback.\n         * Under the hood, the array is generated via a call to `formJsonFormatted()`.\n         *\n         * @param {function} callback\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'formSubmitJsonFormatted',\n        value: function formSubmitJsonFormatted(callback) {\n            //FIXME test this\n            if (_AutoNumericHelper2.default.isFunction(callback)) {\n                callback(this.formJsonFormatted());\n            } else {\n                _AutoNumericHelper2.default.throwError('The given callback is not a function.');\n            }\n\n            return this;\n        }\n\n        /**\n         * Generate a JSON string with the localized strings values from the `<input>` elements, and pass it to the given callback.\n         * Under the hood, the array is generated via a call to `formJsonLocalized()`.\n         *\n         * @param {function} callback\n         * @param {null|string} forcedOutputFormat If set to something different than `null`, then this is used as an overriding outputFormat option\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'formSubmitJsonLocalized',\n        value: function formSubmitJsonLocalized(callback) {\n            var forcedOutputFormat = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n            //FIXME test this\n            if (_AutoNumericHelper2.default.isFunction(callback)) {\n                callback(this.formJsonLocalized(forcedOutputFormat));\n            } else {\n                _AutoNumericHelper2.default.throwError('The given callback is not a function.');\n            }\n\n            return this;\n        }\n\n        /**\n         * Unformat the given AutoNumeric element, and update the `hoveredWithAlt` variable.\n         *\n         * @param {AutoNumeric} anElement\n         * @private\n         */\n\n    }, {\n        key: '_createLocalList',\n\n\n        /**\n         * Create a `Map` that will stores all the autoNumeric elements that are initialized from this current element.\n         * @private\n         */\n        value: function _createLocalList() {\n            this.autoNumericLocalList = new Map();\n            this._addToLocalList(this.domElement);\n        }\n\n        /**\n         * In some rare cases, you could want to delete the local list generated during the element initialization (in order to use another one instead for instance).\n         * @private\n         */\n\n    }, {\n        key: '_deleteLocalList',\n        value: function _deleteLocalList() {\n            delete this.autoNumericLocalList;\n        }\n\n        /**\n         * Set the local list with the given Map object.\n         *\n         * @param {Map} localList\n         * @private\n         */\n\n    }, {\n        key: '_setLocalList',\n        value: function _setLocalList(localList) {\n            this.autoNumericLocalList = localList;\n        }\n\n        /**\n         * Return the local list Map object.\n         *\n         * @returns {*|Map}\n         * @private\n         */\n\n    }, {\n        key: '_getLocalList',\n        value: function _getLocalList() {\n            return this.autoNumericLocalList;\n        }\n\n        /**\n         * Return `true` if the AutoNumeric object has a local list defined already and has at least one element in it (itself usually).\n         *\n         * @returns {boolean}\n         * @private\n         */\n\n    }, {\n        key: '_hasLocalList',\n        value: function _hasLocalList() {\n            return this.autoNumericLocalList instanceof Map && this.autoNumericLocalList.size !== 0;\n        }\n\n        /**\n         * Add the given object to the local autoNumeric element list.\n         * Note: in order to keep a coherent list, we only add DOM elements in it, not the autoNumeric object.\n         *\n         * @param {HTMLElement|HTMLInputElement} domElement\n         * @param {AutoNumeric} autoNumericObject A reference to the AutoNumeric object that manage the given DOM element\n         * @throws\n         * @private\n         */\n\n    }, {\n        key: '_addToLocalList',\n        value: function _addToLocalList(domElement) {\n            var autoNumericObject = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n            if (_AutoNumericHelper2.default.isNull(autoNumericObject)) {\n                autoNumericObject = this;\n            }\n\n            if (!_AutoNumericHelper2.default.isUndefined(this.autoNumericLocalList)) {\n                this.autoNumericLocalList.set(domElement, autoNumericObject); // Use the DOM element as key, and the AutoNumeric object as the value\n            } else {\n                _AutoNumericHelper2.default.throwError('The local list provided does not exists when trying to add an element. [' + this.autoNumericLocalList + '] given.');\n            }\n        }\n\n        /**\n         * Remove the given object from the local autoNumeric element list.\n         *\n         * @param {HTMLElement|HTMLInputElement} domElement\n         * @private\n         */\n\n    }, {\n        key: '_removeFromLocalList',\n        value: function _removeFromLocalList(domElement) {\n            if (!_AutoNumericHelper2.default.isUndefined(this.autoNumericLocalList)) {\n                this.autoNumericLocalList.delete(domElement);\n            } else if (this.settings.createLocalList) {\n                _AutoNumericHelper2.default.throwError('The local list provided does not exists when trying to remove an element. [' + this.autoNumericLocalList + '] given.');\n            }\n        }\n\n        /**\n         * Merge the `newSettings` given as parameters into the current element settings.\n         *\n         * WARNING: Using `Object.assign()` here means the merge is not recursive and only one depth is merged.\n         * cf. http://stackoverflow.com/a/39188108/2834898\n         * cf. tests on http://codepen.io/AnotherLinuxUser/pen/KaJORq?editors=0011\n         *\n         * @param {object} newSettings\n         * @private\n         */\n\n    }, {\n        key: '_mergeSettings',\n        value: function _mergeSettings() {\n            for (var _len3 = arguments.length, newSettings = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {\n                newSettings[_key3] = arguments[_key3];\n            }\n\n            _extends.apply(undefined, [this.settings].concat(newSettings));\n        }\n\n        /**\n         * Return a new object with the current element settings merged with the new settings.\n         *\n         * @param {object} newSettings\n         * @returns {object}\n         * @private\n         */\n\n    }, {\n        key: '_cloneAndMergeSettings',\n        value: function _cloneAndMergeSettings() {\n            var result = {};\n\n            for (var _len4 = arguments.length, newSettings = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {\n                newSettings[_key4] = arguments[_key4];\n            }\n\n            _extends.apply(undefined, [result, this.settings].concat(newSettings));\n\n            return result;\n        }\n\n        /**\n         * Validate the given option object.\n         * If the options are valid, this function returns nothing, otherwise if the options are invalid, this function throws an error.\n         *\n         * This tests if the options are not conflicting and are well formatted.\n         * This function is lenient since it only tests the settings properties ; it ignores any other properties the options object could have.\n         *\n         * @param {*} userOptions\n         * @param {Boolean} shouldExtendDefaultOptions If `true`, then this function will extends the `userOptions` passed by the user, with the default options.\n         * @param {object|null} originalOptions The user can pass the original options (and not the one that are generated from the default settings and the various usability corrections), in order to add compatibility and conflicts checks.\n         * @throws Error This throws if the `userOptions` are not valid\n         */\n\n    }, {\n        key: '_updatePredefinedOptions',\n\n\n        // Pre-defined options can be called to update the current default options with their specificities\n        //XXX A better way would be to not initialize first, but that's not possible since `new` is called first and we do not pass the language options (ie. `French`) to the constructor\n\n        /**\n         * Update the AutoNumeric object with the predefined options, and possibly some option overrides.\n         *\n         * @param {object} predefinedOption\n         * @param {object} optionOverride\n         * @private\n         * @returns {AutoNumeric}\n         */\n        value: function _updatePredefinedOptions(predefinedOption) {\n            var optionOverride = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n            if (!_AutoNumericHelper2.default.isNull(optionOverride)) {\n                this._mergeSettings(predefinedOption, optionOverride);\n                this.update(this.settings);\n            } else {\n                this.update(predefinedOption);\n            }\n\n            return this;\n        }\n\n        /**\n         * Update the settings to use the French pre-defined language options.\n         * Those pre-defined options can be overridden by passing an option object as a parameter.\n         *\n         * @param {object} optionOverride\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'french',\n        value: function french() {\n            var optionOverride = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            this._updatePredefinedOptions(AutoNumeric.getPredefinedOptions().French, optionOverride);\n\n            return this;\n        }\n\n        /**\n         * Update the settings to use the North American pre-defined language options.\n         * Those pre-defined options can be overridden by passing an option object as a parameter.\n         *\n         * @param {object} optionOverride\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'northAmerican',\n        value: function northAmerican() {\n            var optionOverride = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            this._updatePredefinedOptions(AutoNumeric.getPredefinedOptions().NorthAmerican, optionOverride);\n\n            return this;\n        }\n\n        /**\n         * Update the settings to use the British pre-defined language options.\n         * Those pre-defined options can be overridden by passing an option object as a parameter.\n         *\n         * @param {object} optionOverride\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'british',\n        value: function british() {\n            var optionOverride = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            this._updatePredefinedOptions(AutoNumeric.getPredefinedOptions().British, optionOverride);\n\n            return this;\n        }\n\n        /**\n         * Update the settings to use the Swiss pre-defined language options.\n         * Those pre-defined options can be overridden by passing an option object as a parameter.\n         *\n         * @param {object} optionOverride\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'swiss',\n        value: function swiss() {\n            var optionOverride = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            this._updatePredefinedOptions(AutoNumeric.getPredefinedOptions().Swiss, optionOverride);\n\n            return this;\n        }\n\n        /**\n         * Update the settings to use the Japanese pre-defined language options.\n         * Those pre-defined options can be overridden by passing an option object as a parameter.\n         *\n         * @param {object} optionOverride\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'japanese',\n        value: function japanese() {\n            var optionOverride = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            this._updatePredefinedOptions(AutoNumeric.getPredefinedOptions().Japanese, optionOverride);\n\n            return this;\n        }\n\n        /**\n         * Update the settings to use the Spanish pre-defined language options.\n         * Those pre-defined options can be overridden by passing an option object as a parameter.\n         *\n         * @param {object} optionOverride\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'spanish',\n        value: function spanish() {\n            var optionOverride = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            this._updatePredefinedOptions(AutoNumeric.getPredefinedOptions().Spanish, optionOverride);\n\n            return this;\n        }\n\n        /**\n         * Update the settings to use the Chinese pre-defined language options.\n         * Those pre-defined options can be overridden by passing an option object as a parameter.\n         *\n         * @param {object} optionOverride\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'chinese',\n        value: function chinese() {\n            var optionOverride = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            this._updatePredefinedOptions(AutoNumeric.getPredefinedOptions().Chinese, optionOverride);\n\n            return this;\n        }\n\n        /**\n         * Update the settings to use the Brazilian pre-defined language options.\n         * Those pre-defined options can be overridden by passing an option object as a parameter.\n         *\n         * @param {object} optionOverride\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'brazilian',\n        value: function brazilian() {\n            var optionOverride = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            this._updatePredefinedOptions(AutoNumeric.getPredefinedOptions().Brazilian, optionOverride);\n\n            return this;\n        }\n\n        // Internal private functions\n        /**\n         * Run any callbacks found in the settings object in order to set the settings value back.\n         * Any parameter can have a callback defined.\n         * The callback takes the current AutoNumeric element as the first argument, and the key name as the second.\n         * @example callback(this, 'currencySymbol')\n         */\n\n    }, {\n        key: '_runCallbacksFoundInTheSettingsObject',\n        value: function _runCallbacksFoundInTheSettingsObject() {\n            //FIXME test this\n            // Loops through the this.settings object (option array) to find the following\n            for (var key in this.settings) {\n                if (this.settings.hasOwnProperty(key)) {\n                    var value = this.settings[key];\n\n                    if (typeof value === 'function') {\n                        this.settings[key] = value(this, key);\n                    } else {\n                        // Calls the attached function from the html5 data. For instance: <tag data-currency-symbol=\"functionName\"></tag>\n                        var htmlAttribute = this.domElement.getAttribute(key); //TODO Use `dataset` instead of `getAttribute` when we won't need to support obsolete browsers\n                        htmlAttribute = _AutoNumericHelper2.default.camelize(htmlAttribute);\n                        if (typeof this.settings[htmlAttribute] === 'function') {\n                            this.settings[key] = htmlAttribute(this, key);\n                        }\n                    }\n                }\n            }\n        }\n\n        /**\n         * Keep track if the settings configuration leads to a trailing negative sign (only when the raw value is negative), so we do not have to test the settings values every time we need to know that.\n         * `isTrailingNegative` is set to `true` if the settings result in a trailing negative character, `false` otherwise.\n         * Note: This returns `true` even if the raw value is positive.\n         * @private\n         */\n\n    }, {\n        key: '_setTrailingNegativeSignInfo',\n        value: function _setTrailingNegativeSignInfo() {\n            this.isTrailingNegative = this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix && this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.suffix || this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix && (this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.left || this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.right);\n        }\n\n        /**\n         * Strip all the unwanted non-number characters.\n         * However it does not reorder the localized negative sign.\n         *\n         * @param {string} s\n         * @param {object} settings\n         * @param {boolean} stripZeros If set to `false`, then the leading zero(s) are not stripped, otherwise if set to `true`, the `leadingZero` option is followed\n         * @param {boolean} isFocused If the element is focused, then this is `true`\n         * @returns {string}\n         * @private\n         */\n\n    }, {\n        key: '_modifyNegativeSignAndDecimalCharacterForRawValue',\n\n\n        /**\n         * Modify the negative sign and the decimal character of the given string value to an hyphen (-) and a dot (.) in order to make that value 'typecastable' to a real number.\n         *\n         * @param {string} s The formatted value\n         * @returns {string} The value with the 'normal' minus sign and decimal character\n         */\n        value: function _modifyNegativeSignAndDecimalCharacterForRawValue(s) {\n            if (this.settings.decimalCharacter !== '.') {\n                s = s.replace(this.settings.decimalCharacter, '.');\n            }\n\n            if (this.settings.negativeSignCharacter !== '-' && this.settings.isNegativeSignAllowed) {\n                s = s.replace(this.settings.negativeSignCharacter, '-');\n            }\n\n            if (!s.match(/\\d/)) {\n                // The default value returned by `get` is not formatted with decimals\n                s += '0';\n            }\n\n            return s;\n        }\n\n        /**\n         * Modify the negative sign and the decimal character to use those defined in the settings.\n         *\n         * @param {string} s\n         * @param {object} settings\n         * @returns {string}\n         */\n\n    }, {\n        key: '_initialCaretPosition',\n\n\n        /**\n         * Calculate where to put the caret position on focus if the element content is not selected.\n         * This calculation is affected by the `caretPositionOnFocus` option which can be either `null`, `'start'`, `'end'`, `'decimalLeft'` or 'decimalRight'`, and will decide where to put the caret (on the left or right of the value or the decimal character, respectively) :\n         * - `null` : the caret position is not forced\n         * - `'start'` : the caret is positioned on the left hand side of the value\n         * - `'end'` : the caret is positioned on the right hand side of the value\n         * - `'decimalLeft'` : the caret is positioned on the left side of the decimal character\n         * - `'decimalRight'` : the caret is positioned on the right side of the decimal character\n         *\n         * @param {string} value The formatted string stripped of the currency symbol and negative/positive sign\n         * @returns {number}\n         * @throws\n         * @private\n         */\n        value: function _initialCaretPosition(value) {\n            if (_AutoNumericHelper2.default.isNull(this.settings.caretPositionOnFocus) && this.settings.selectOnFocus === AutoNumeric.options.selectOnFocus.doNotSelect) {\n                _AutoNumericHelper2.default.throwError('`_initialCaretPosition()` should never be called when the `caretPositionOnFocus` option is `null`.');\n            }\n\n            var isValueNegative = this.rawValue < 0;\n            var isZeroOrHasNoValue = _AutoNumericHelper2.default.isZeroOrHasNoValue(value);\n            var totalLength = value.length;\n\n            var valueSize = 0;\n            var integerSize = 0;\n            var hasDecimalChar = false;\n            var offsetDecimalChar = 0;\n            if (this.settings.caretPositionOnFocus !== AutoNumeric.options.caretPositionOnFocus.start) {\n                value = value.replace(this.settings.negativeSignCharacter, '');\n                value = value.replace(this.settings.positiveSignCharacter, '');\n                value = value.replace(this.settings.currencySymbol, '');\n                valueSize = value.length;\n                hasDecimalChar = _AutoNumericHelper2.default.contains(value, this.settings.decimalCharacter);\n\n                if (this.settings.caretPositionOnFocus === AutoNumeric.options.caretPositionOnFocus.decimalLeft || this.settings.caretPositionOnFocus === AutoNumeric.options.caretPositionOnFocus.decimalRight) {\n                    if (hasDecimalChar) {\n                        integerSize = value.indexOf(this.settings.decimalCharacter);\n                        offsetDecimalChar = this.settings.decimalCharacter.length;\n                    } else {\n                        integerSize = valueSize;\n                        offsetDecimalChar = 0;\n                    }\n                }\n            }\n\n            var signToUse = '';\n            if (isValueNegative) {\n                signToUse = this.settings.negativeSignCharacter;\n            } else if (this.settings.showPositiveSign && !isZeroOrHasNoValue) {\n                signToUse = this.settings.positiveSignCharacter;\n            }\n\n            var positiveNegativeSignSize = signToUse.length;\n            var currencySymbolSize = this.settings.currencySymbol.length;\n\n            // Calculate the caret position based on `currencySymbolPlacement`, `negativePositiveSignPlacement` and `caretPositionOnFocus`\n            var caretPosition = void 0;\n            if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix) {\n                if (this.settings.caretPositionOnFocus === AutoNumeric.options.caretPositionOnFocus.start) {\n                    if (this.settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.none && (isValueNegative || !isValueNegative && this.settings.showPositiveSign && !isZeroOrHasNoValue)) {\n                        switch (this.settings.negativePositiveSignPlacement) {\n                            case AutoNumeric.options.negativePositiveSignPlacement.prefix: // +€|12.34\n                            case AutoNumeric.options.negativePositiveSignPlacement.left: // +€|12.34\n                            case AutoNumeric.options.negativePositiveSignPlacement.right:\n                                // €+|12.34\n                                caretPosition = positiveNegativeSignSize + currencySymbolSize;\n                                break;\n                            case AutoNumeric.options.negativePositiveSignPlacement.suffix:\n                                // €|12.34+\n                                caretPosition = currencySymbolSize;\n                                break;\n                        }\n                    } else {\n                        // €|12.34\n                        caretPosition = currencySymbolSize;\n                    }\n                } else if (this.settings.caretPositionOnFocus === AutoNumeric.options.caretPositionOnFocus.end) {\n                    if (this.settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.none && (isValueNegative || !isValueNegative && this.settings.showPositiveSign && !isZeroOrHasNoValue)) {\n                        switch (this.settings.negativePositiveSignPlacement) {\n                            case AutoNumeric.options.negativePositiveSignPlacement.prefix: // +€12.34|\n                            case AutoNumeric.options.negativePositiveSignPlacement.left: // +€12.34|\n                            case AutoNumeric.options.negativePositiveSignPlacement.right:\n                                // €+12.34|\n                                caretPosition = totalLength;\n                                break;\n                            case AutoNumeric.options.negativePositiveSignPlacement.suffix:\n                                // €12.34|+\n                                caretPosition = currencySymbolSize + valueSize;\n                                break;\n                        }\n                    } else {\n                        // €12.34|\n                        caretPosition = totalLength;\n                    }\n                } else if (this.settings.caretPositionOnFocus === AutoNumeric.options.caretPositionOnFocus.decimalLeft) {\n                    if (this.settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.none && (isValueNegative || !isValueNegative && this.settings.showPositiveSign && !isZeroOrHasNoValue)) {\n                        switch (this.settings.negativePositiveSignPlacement) {\n                            case AutoNumeric.options.negativePositiveSignPlacement.prefix: // +€12|.34\n                            case AutoNumeric.options.negativePositiveSignPlacement.left: // +€12|.34\n                            case AutoNumeric.options.negativePositiveSignPlacement.right:\n                                // €+12|.34\n                                caretPosition = positiveNegativeSignSize + currencySymbolSize + integerSize;\n                                break;\n                            case AutoNumeric.options.negativePositiveSignPlacement.suffix:\n                                // €12|.34+\n                                caretPosition = currencySymbolSize + integerSize;\n                                break;\n                        }\n                    } else {\n                        // €12|.34\n                        caretPosition = currencySymbolSize + integerSize;\n                    }\n                } else if (this.settings.caretPositionOnFocus === AutoNumeric.options.caretPositionOnFocus.decimalRight) {\n                    if (this.settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.none && (isValueNegative || !isValueNegative && this.settings.showPositiveSign && !isZeroOrHasNoValue)) {\n                        switch (this.settings.negativePositiveSignPlacement) {\n                            case AutoNumeric.options.negativePositiveSignPlacement.prefix: // +€12.|34\n                            case AutoNumeric.options.negativePositiveSignPlacement.left: // +€12.|34\n                            case AutoNumeric.options.negativePositiveSignPlacement.right:\n                                // €+12.|34\n                                caretPosition = positiveNegativeSignSize + currencySymbolSize + integerSize + offsetDecimalChar;\n                                break;\n                            case AutoNumeric.options.negativePositiveSignPlacement.suffix:\n                                // €12.|34+\n                                caretPosition = currencySymbolSize + integerSize + offsetDecimalChar;\n                                break;\n                        }\n                    } else {\n                        // €12.|34\n                        caretPosition = currencySymbolSize + integerSize + offsetDecimalChar;\n                    }\n                }\n            } else if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) {\n                if (this.settings.caretPositionOnFocus === AutoNumeric.options.caretPositionOnFocus.start) {\n                    if (this.settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.none && (isValueNegative || !isValueNegative && this.settings.showPositiveSign && !isZeroOrHasNoValue)) {\n                        switch (this.settings.negativePositiveSignPlacement) {\n                            case AutoNumeric.options.negativePositiveSignPlacement.suffix: // |12.34€+\n                            case AutoNumeric.options.negativePositiveSignPlacement.right: // |12.34€+\n                            case AutoNumeric.options.negativePositiveSignPlacement.left:\n                                // |12.34+€\n                                caretPosition = 0;\n                                break;\n                            case AutoNumeric.options.negativePositiveSignPlacement.prefix:\n                                // +|12.34€\n                                caretPosition = positiveNegativeSignSize;\n                                break;\n                        }\n                    } else {\n                        // |12.34€\n                        caretPosition = 0;\n                    }\n                } else if (this.settings.caretPositionOnFocus === AutoNumeric.options.caretPositionOnFocus.end) {\n                    if (this.settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.none && (isValueNegative || !isValueNegative && this.settings.showPositiveSign && !isZeroOrHasNoValue)) {\n                        switch (this.settings.negativePositiveSignPlacement) {\n                            case AutoNumeric.options.negativePositiveSignPlacement.suffix: // 12.34|€+\n                            case AutoNumeric.options.negativePositiveSignPlacement.right: // 12.34|€+\n                            case AutoNumeric.options.negativePositiveSignPlacement.left:\n                                // 12.34|+€\n                                caretPosition = valueSize;\n                                break;\n                            case AutoNumeric.options.negativePositiveSignPlacement.prefix:\n                                // +12.34|€\n                                caretPosition = positiveNegativeSignSize + valueSize;\n                                break;\n                        }\n                    } else {\n                        // 12.34|€\n                        caretPosition = valueSize;\n                    }\n                } else if (this.settings.caretPositionOnFocus === AutoNumeric.options.caretPositionOnFocus.decimalLeft) {\n                    if (this.settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.none && (isValueNegative || !isValueNegative && this.settings.showPositiveSign && !isZeroOrHasNoValue)) {\n                        switch (this.settings.negativePositiveSignPlacement) {\n                            case AutoNumeric.options.negativePositiveSignPlacement.suffix: // 12|.34€+\n                            case AutoNumeric.options.negativePositiveSignPlacement.right: // 12|.34€+\n                            case AutoNumeric.options.negativePositiveSignPlacement.left:\n                                // 12|.34+€\n                                caretPosition = integerSize;\n                                break;\n                            case AutoNumeric.options.negativePositiveSignPlacement.prefix:\n                                // +12|.34€\n                                caretPosition = positiveNegativeSignSize + integerSize;\n                                break;\n                        }\n                    } else {\n                        // 12|.34€\n                        caretPosition = integerSize;\n                    }\n                } else if (this.settings.caretPositionOnFocus === AutoNumeric.options.caretPositionOnFocus.decimalRight) {\n                    if (this.settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.none && (isValueNegative || !isValueNegative && this.settings.showPositiveSign && !isZeroOrHasNoValue)) {\n                        switch (this.settings.negativePositiveSignPlacement) {\n                            case AutoNumeric.options.negativePositiveSignPlacement.suffix: // 12.|34€+\n                            case AutoNumeric.options.negativePositiveSignPlacement.right: // 12.|34€+\n                            case AutoNumeric.options.negativePositiveSignPlacement.left:\n                                // 12.|34+€\n                                caretPosition = integerSize + offsetDecimalChar;\n                                break;\n                            case AutoNumeric.options.negativePositiveSignPlacement.prefix:\n                                // +12.|34€\n                                caretPosition = positiveNegativeSignSize + integerSize + offsetDecimalChar;\n                                break;\n                        }\n                    } else {\n                        // 12.|34€\n                        caretPosition = integerSize + offsetDecimalChar;\n                    }\n                }\n            }\n\n            return caretPosition;\n        }\n\n        /**\n         * Truncate the trailing zeroes to the given number of decimal places\n         *\n         * @param {string} roundedInputValue\n         * @param {int} decimalPlacesNeeded The number of decimal places to keep\n         * @returns {string}\n         */\n\n    }, {\n        key: '_keepAnOriginalSettingsCopy',\n\n\n        /**\n         * Original settings saved for use when the `decimalPlacesShownOnFocus` and `showOnlyNumbersOnFocus` options are used.\n         * Those original settings are used exclusively in the `focusin` and `focusout` event handlers.\n         */\n        value: function _keepAnOriginalSettingsCopy() {\n            this.originalDigitGroupSeparator = this.settings.digitGroupSeparator;\n            this.originalCurrencySymbol = this.settings.currencySymbol;\n            this.originalSuffixText = this.settings.suffixText;\n        }\n\n        /**\n         * Original settings saved for use when `decimalPlacesShownOnFocus` & `showOnlyNumbersOnFocus` options are being used.\n         * This is taken from Quirksmode.\n         *\n         * @param {string} name\n         * @returns {*}\n         */\n\n    }, {\n        key: '_trimLeadingAndTrailingZeros',\n\n\n        /**\n         * Removes any zeros in excess in the front and back of the given `value`, according to the `settings`.\n         * This also manages the cases where the decimal point is on the far left or far right of the `value`.\n         *\n         * @param {string} value\n         * @returns {string|null}\n         */\n        value: function _trimLeadingAndTrailingZeros(value) {\n            // Return the empty string is the value is already empty. This prevent converting that value to '0'.\n            if (value === '' || value === null) {\n                return value;\n            }\n\n            if (this.settings.leadingZero !== AutoNumeric.options.leadingZero.keep) {\n                if (Number(value) === 0) {\n                    // Return '0' if the value is zero\n                    return '0';\n                }\n\n                // Trim the leading zeros, while leaving one zero to the left of the decimal point if needed\n                value = value.replace(/^(-)?0+(?=\\d)/g, '$1');\n            }\n\n            //TODO remove this from that function and use `trimPaddedZerosFromDecimalPlaces()` instead\n            // Trim the trailing zeros after the last decimal place not being a zero (ie. 1.2300 -> 1.23)\n            if (_AutoNumericHelper2.default.contains(value, '.')) {\n                value = value.replace(/(\\.[0-9]*?)0+$/, '$1');\n            }\n\n            // Remove any trailing decimal point\n            value = value.replace(/\\.$/, '');\n\n            return value;\n        }\n\n        /**\n         * Generate the name for the persistent stored data variable\n         * @private\n         */\n\n    }, {\n        key: '_setPersistentStorageName',\n        value: function _setPersistentStorageName() {\n            if (this.settings.saveValueToSessionStorage) {\n                if (this.domElement.name !== '' && !_AutoNumericHelper2.default.isUndefined(this.domElement.name)) {\n                    this.rawValueStorageName = '' + this.storageNamePrefix + decodeURIComponent(this.domElement.name);\n                } else {\n                    this.rawValueStorageName = '' + this.storageNamePrefix + this.domElement.id;\n                }\n            }\n        }\n\n        /**\n         * Save the raw Value into sessionStorage or a cookie depending on what the browser is supporting.\n         * @private\n         */\n\n    }, {\n        key: '_saveValueToPersistentStorage',\n        value: function _saveValueToPersistentStorage() {\n            if (this.settings.saveValueToSessionStorage) {\n                if (this.sessionStorageAvailable) {\n                    sessionStorage.setItem(this.rawValueStorageName, this.rawValue);\n                } else {\n                    // Use cookies for obsolete browsers that do not support sessionStorage (ie. IE 6 & 7)\n                    document.cookie = this.rawValueStorageName + '=' + this.rawValue + '; expires= ; path=/';\n                }\n            }\n        }\n\n        /**\n         * Retrieve the raw value from sessionStorage or the cookie depending on what the browser is supporting.\n         *\n         * @returns {*}\n         * @private\n         */\n\n    }, {\n        key: '_getValueFromPersistentStorage',\n        value: function _getValueFromPersistentStorage() {\n            if (this.settings.saveValueToSessionStorage) {\n                var result = void 0;\n                if (this.sessionStorageAvailable) {\n                    result = sessionStorage.getItem(this.rawValueStorageName);\n                } else {\n                    result = this.constructor._readCookie(this.rawValueStorageName);\n                }\n\n                return result;\n            }\n\n            _AutoNumericHelper2.default.warning('`_getValueFromPersistentStorage()` is called but `settings.saveValueToSessionStorage` is false. There must be an error that needs fixing.', this.settings.showWarnings);\n\n            return null;\n        }\n\n        /**\n         * Remove the raw value data from sessionStorage or the cookie depending on what the browser is supporting.\n         * @private\n         */\n\n    }, {\n        key: '_removeValueFromPersistentStorage',\n        value: function _removeValueFromPersistentStorage() {\n            if (this.settings.saveValueToSessionStorage) {\n                if (this.sessionStorageAvailable) {\n                    sessionStorage.removeItem(this.rawValueStorageName);\n                } else {\n                    var date = new Date();\n                    date.setTime(date.getTime() - 86400000); // -86400000 === -1 * 24 * 60 * 60 * 1000\n                    var expires = '; expires=' + date.toUTCString();\n                    document.cookie = this.rawValueStorageName + '=\\'\\' ;' + expires + '; path=/';\n                }\n            }\n        }\n\n        /**\n         * Get the default value from the html `value` attribute.\n         * Return the empty string if such attribute is not found.\n         *\n         * @param {HTMLElement} domElement\n         *\n         * @returns {string}\n         * @private\n         */\n\n    }, {\n        key: '_getDefaultValue',\n        value: function _getDefaultValue(domElement) {\n            // Get the default html value\n            // Note: we do not use the simpler `return domElement.defaultValue;` code since the given domElement can sometime be a `contenteditable` element which does not support the `defaultValue` attribute.\n            var value = domElement.getAttribute('value');\n\n            if (_AutoNumericHelper2.default.isNull(value)) {\n                return '';\n            }\n\n            return value;\n        }\n\n        /**\n         * Handler for 'focusin' and 'mouseenter' events\n         * On focusin, multiple things happens :\n         * - If `Alt` is pressed, unformat\n         * - Remove the separators if `showOnlyNumbersOnFocus` is set\n         * - Depending on `emptyInputBehavior`, reformat the empty formatted value\n         * - Display the correct number of decimal places (on focus/blur)\n         * - Place the caret correctly if the element is empty\n         *\n         * Note: On focusin, the `rawValue` is never changed. Only the formatted value can be modified.\n         *\n         * @param {KeyboardEvent|MouseEvent} e\n         * @private\n         */\n\n    }, {\n        key: '_onFocusInAndMouseEnter',\n        value: function _onFocusInAndMouseEnter(e) {\n            //TODO Create separate handlers for the focus and mouseenter events\n            this.isEditing = false; // Just in case no `keyUp` event have been sent (ie. if the user lost the focus from the current window while typing)\n\n            if (this.settings.unformatOnHover && e.type === 'mouseenter' && e.altKey) {\n                this.constructor._unformatAltHovered(this);\n\n                return;\n            }\n\n            if (e.type === 'focus') {\n                //TODO Move that back to the 'focus' event handler when the separation between the 'focus' and 'mouseenter' handler will be done\n                // Keep track if the element is currently focused\n                this.isFocused = true;\n                this.rawValueOnFocus = this.rawValue; // Keep track of the initial rawValue. This is needed to define if a change event must be dispatched later\n            }\n\n            if (e.type === 'focus' && this.settings.unformatOnHover && this.hoveredWithAlt) {\n                this.constructor._reformatAltHovered(this);\n            }\n\n            if (e.type === 'focus' || e.type === 'mouseenter' && !this.isFocused) {\n                var elementValueToSet = null; // Store the value we want to set on the element, and only call `_setElementValue()` once\n\n                if (this.settings.emptyInputBehavior === AutoNumeric.options.emptyInputBehavior.focus && this.rawValue < 0 && this.settings.negativeBracketsTypeOnBlur !== null && this.settings.isNegativeSignAllowed) {\n                    //FIXME this is called a second time in _addGroupSeparators too. Prevent this, if possible.\n                    // Only remove the brackets if the value is negative\n                    elementValueToSet = this.constructor._removeBrackets(_AutoNumericHelper2.default.getElementValue(this.domElement), this.settings);\n                    //FIXME The element value is set here, why continue and set it again later in that same parent logic block?\n                }\n\n                // Use the `rawValue`, multiplied by `rawValueDivisor` if defined\n                var rawValueToFormat = this._getRawValueToFormat(this.rawValue);\n\n                // Modify the element value according to the number of decimal places to show on focus or the `showOnlyNumbersOnFocus` option\n                if (rawValueToFormat !== '') {\n                    // Round the given value according to the object state (focus/unfocused)\n                    var roundedValue = this.constructor._roundFormattedValueShownOnFocusOrBlur(rawValueToFormat, this.settings, this.isFocused);\n\n                    if (this.settings.showOnlyNumbersOnFocus === AutoNumeric.options.showOnlyNumbersOnFocus.onlyNumbers) {\n                        //TODO Use a `this.settingsOverride` object instead of modifying the `this.settings` object\n                        this.settings.digitGroupSeparator = '';\n                        this.settings.currencySymbol = '';\n                        this.settings.suffixText = '';\n                        elementValueToSet = roundedValue.replace('.', this.settings.decimalCharacter);\n                    } else {\n                        var formattedValue = void 0;\n                        if (_AutoNumericHelper2.default.isNull(roundedValue)) {\n                            formattedValue = '';\n                        } else {\n                            formattedValue = this.constructor._addGroupSeparators(roundedValue.replace('.', this.settings.decimalCharacter), this.settings, this.isFocused, rawValueToFormat);\n                        }\n\n                        elementValueToSet = formattedValue;\n                    }\n                }\n\n                // In order to send a 'native' change event when blurring the input, we need to first store the initial input value on focus.\n                if (_AutoNumericHelper2.default.isNull(elementValueToSet)) {\n                    this.valueOnFocus = '';\n                } else {\n                    this.valueOnFocus = elementValueToSet;\n                }\n\n                this.lastVal = this.valueOnFocus;\n                var isEmptyValue = this.constructor._isElementValueEmptyOrOnlyTheNegativeSign(this.valueOnFocus, this.settings);\n                var orderedValue = this.constructor._orderValueCurrencySymbolAndSuffixText(this.valueOnFocus, this.settings, true); // This displays the currency sign on hover even if the rawValue is empty\n                var orderedValueTest = isEmptyValue && orderedValue !== '' && this.settings.emptyInputBehavior === AutoNumeric.options.emptyInputBehavior.focus;\n                if (orderedValueTest) {\n                    elementValueToSet = orderedValue;\n                }\n\n                if (!_AutoNumericHelper2.default.isNull(elementValueToSet)) {\n                    this._setElementValue(elementValueToSet);\n                }\n\n                if (orderedValueTest && orderedValue === this.settings.currencySymbol && this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) {\n                    // If there is a currency symbol and its on the right hand side, then we place the caret accordingly on the far left side\n                    _AutoNumericHelper2.default.setElementSelection(e.target, 0);\n                }\n            }\n        }\n\n        /**\n         * Handler for the 'focus' event.\n         * We update the info of the focused state in the `this.isFocused` variable when the element gets focused.\n         * @private\n         */\n\n    }, {\n        key: '_onFocus',\n        value: function _onFocus() {\n            if (this.settings.isCancellable) {\n                // Save the current unformatted value for later use by the 'cancellable' feature\n                this._saveCancellableValue();\n            }\n        }\n\n        /**\n         * Handler for the 'focusin' event.\n         * This is called before the 'focus' event, and is necessary to change the selection on focus under Firefox for instance.\n         *\n         * @param {Event} e\n         * @private\n         */\n\n    }, {\n        key: '_onFocusIn',\n        value: function _onFocusIn(e) {\n            if (this.settings.selectOnFocus) {\n                // The whole input content is selected on focus (following the `selectOnFocus` and `selectNumberOnly` options)\n                //XXX Firefox <47 does not respect this selection...Oh well.\n                this.select();\n            } else {\n                // Or we decide where to put the caret using the `caretPositionOnFocus` option\n                if (!_AutoNumericHelper2.default.isNull(this.settings.caretPositionOnFocus)) {\n                    _AutoNumericHelper2.default.setElementSelection(e.target, this._initialCaretPosition(_AutoNumericHelper2.default.getElementValue(this.domElement)));\n                }\n            }\n        }\n\n        /**\n         * Handler for 'keydown' events.\n         * The user just started pushing any key, hence one event is sent.\n         *\n         * Note :\n         * By default a 'normal' input output those events in the right order when inputting a character key (ie. 'a') :\n         * - keydown\n         * - keypress\n         * - input\n         * - keyup\n         *\n         * ...when inputting a modifier key (ie. 'ctrl') :\n         * - keydown\n         * - keyup\n         *\n         * If 'delete' or 'backspace' is entered, the following events are sent :\n         * - keydown\n         * - input\n         * - keyup\n         *\n         * If 'enter' is entered and the value has not changed, the following events are sent :\n         * - keydown\n         * - keypress\n         * - keyup\n         *\n         * If 'enter' is entered and the value has been changed, the following events are sent :\n         * - keydown\n         * - keypress\n         * - change\n         * - keyup\n         *\n         * When a paste is done, the following events are sent :\n         * - input (if paste is done with the mouse)\n         *\n         * - keydown (if paste is done with ctrl+v)\n         * - keydown\n         * - input\n         * - keyup\n         * - keyup\n         *\n         * @param {KeyboardEvent} e\n         */\n\n    }, {\n        key: '_onKeydown',\n        value: function _onKeydown(e) {\n            this.formatted = false; // Keep track if the element has been formatted already. If that's the case, prevent further format calculations.\n            this.isEditing = true; // Keep track if the user is currently editing the element manually\n\n            if (!this.isFocused && this.settings.unformatOnHover && e.altKey && this.domElement === _AutoNumericHelper2.default.getHoveredElement()) {\n                // Here I prevent calling _unformatAltHovered if the element is already focused, since the global 'keydown' listener will pick it up as well\n                this.constructor._unformatAltHovered(this);\n\n                return;\n            }\n\n            this._updateEventKeyInfo(e);\n            this.initialValueOnKeydown = _AutoNumericHelper2.default.getElementValue(e.target); // This is needed in `onKeyup()` to check if the value as changed during the key press\n            this.initialRawValueOnKeydown = this.rawValue;\n\n            if (this.domElement.readOnly) {\n                this.processed = true;\n\n                return;\n            }\n\n            if (this.eventKey === _AutoNumericEnum2.default.keyName.Esc) {\n                //XXX The default 'Escape' key behavior differs between Firefox and Chrome, Firefox already having a built-in 'cancellable-like' feature. This is why we call `e.preventDefault()` here instead of just when `isCancellable` is set to `true`. This allow us to keep the same behavior across browsers.\n                e.preventDefault();\n\n                if (this.settings.isCancellable) {\n                    // If the user wants to cancel his modifications:\n                    // We set back the saved value\n                    if (this.rawValue !== this.savedCancellableValue) {\n                        // Do not set the value again if it has not changed\n                        this.set(this.savedCancellableValue);\n                        // And we need to send an 'input' event when setting back the initial value in order to make other scripts aware of the value change...\n                        this._triggerEvent(AutoNumeric.events.native.input, e.target);\n                    }\n                }\n\n                // ..and lastly we update the caret selection, even if the option `isCancellable` is false\n                this.select();\n                //TODO Add an option to select either the integer or decimal part with `Esc`\n            }\n\n            // The \"enter\" key throws a `change` event if the raw value has changed since the `focus` event\n            var targetValue = _AutoNumericHelper2.default.getElementValue(e.target);\n            if (this.eventKey === _AutoNumericEnum2.default.keyName.Enter && this.rawValue !== this.rawValueOnFocus) {\n                this._triggerEvent(AutoNumeric.events.native.change, e.target);\n                this.valueOnFocus = targetValue;\n                this.rawValueOnFocus = this.rawValue;\n\n                if (this.settings.isCancellable) {\n                    // If the user activated the 'cancellable' feature, we save the validated value when 'Enter' is hit\n                    this._saveCancellableValue();\n                }\n            }\n\n            this._updateInternalProperties(e);\n\n            if (this._processNonPrintableKeysAndShortcuts(e)) {\n                this.processed = true;\n\n                return;\n            }\n\n            // Check if the key is a delete/backspace key\n            if (this.eventKey === _AutoNumericEnum2.default.keyName.Backspace || this.eventKey === _AutoNumericEnum2.default.keyName.Delete) {\n                this._processCharacterDeletion(); // Because backspace and delete only triggers keydown and keyup events, not keypress\n                this.processed = true;\n                this._formatValue(e);\n\n                // If and only if the resulting value has changed after that backspace/delete, then we have to send an 'input' event like browsers normally do.\n                targetValue = _AutoNumericHelper2.default.getElementValue(e.target); // Update the value since it could have been changed during the deletion\n                if (targetValue !== this.lastVal && this.throwInput) {\n                    // Throw an input event when a character deletion is detected\n                    this._triggerEvent(AutoNumeric.events.native.input, e.target);\n                    e.preventDefault(); // ...and immediately prevent the browser to delete a second character\n                }\n\n                this.lastVal = targetValue;\n                this.throwInput = true;\n            }\n        }\n\n        /**\n         * Handler for 'keypress' events.\n         * The user is still pressing the key, which will output a character (ie. '2') continuously until he releases the key.\n         * Note: 'keypress' events are not sent for delete keys like Backspace/Delete.\n         *\n         * @param {KeyboardEvent} e\n         */\n\n    }, {\n        key: '_onKeypress',\n        value: function _onKeypress(e) {\n            if (this.eventKey === _AutoNumericEnum2.default.keyName.Insert) {\n                return;\n            }\n\n            var processed = this.processed;\n            this._updateInternalProperties(e);\n\n            if (this._processNonPrintableKeysAndShortcuts(e)) {\n                return;\n            }\n\n            if (processed) {\n                e.preventDefault();\n\n                return;\n            }\n\n            var isCharacterInsertionAllowed = this._processCharacterInsertion();\n            if (isCharacterInsertionAllowed) {\n                this._formatValue(e);\n                var targetValue = _AutoNumericHelper2.default.getElementValue(e.target);\n                if (targetValue !== this.lastVal && this.throwInput) {\n                    // Throws input event on adding a character\n                    this._triggerEvent(AutoNumeric.events.native.input, e.target);\n                    e.preventDefault(); // ...and immediately prevent the browser to add a second character\n                } else {\n                    if ((this.eventKey === this.settings.decimalCharacter || this.eventKey === this.settings.decimalCharacterAlternative) && _AutoNumericHelper2.default.getElementSelection(e.target).start === _AutoNumericHelper2.default.getElementSelection(e.target).end && _AutoNumericHelper2.default.getElementSelection(e.target).start === targetValue.indexOf(this.settings.decimalCharacter)) {\n                        var position = _AutoNumericHelper2.default.getElementSelection(e.target).start + 1;\n                        _AutoNumericHelper2.default.setElementSelection(e.target, position);\n                    }\n\n                    e.preventDefault();\n                }\n\n                this.lastVal = _AutoNumericHelper2.default.getElementValue(e.target);\n                this.throwInput = true;\n\n                return;\n            }\n\n            e.preventDefault();\n        }\n\n        /**\n         * Handler for 'keyup' events.\n         * The user just released any key, hence one event is sent.\n         *\n         * @param {KeyboardEvent} e\n         */\n\n    }, {\n        key: '_onKeyup',\n        value: function _onKeyup(e) {\n            this.isEditing = false;\n\n            if (this.settings.isCancellable && this.eventKey === _AutoNumericEnum2.default.keyName.Esc) {\n                // If the user wants to cancel its modifications, we drop the 'keyup' event for the Esc key\n                e.preventDefault();\n\n                return;\n            }\n\n            // Manage the undo/redo events\n            if (this.eventKey === _AutoNumericEnum2.default.keyName.Z || this.eventKey === _AutoNumericEnum2.default.keyName.z) {\n                if (e.ctrlKey && e.shiftKey) {\n                    // Redo\n                    e.preventDefault();\n                    this._historyTableRedo();\n                    this.onGoingRedo = true;\n\n                    return;\n                } else if (e.ctrlKey && !e.shiftKey) {\n                    if (this.onGoingRedo) {\n                        // Prevent an 'undo' to be launch when releasing the shift key before the ctrl key after a 'redo' shortcut\n                        this.onGoingRedo = false;\n                    } else {\n                        e.preventDefault();\n                        // Undo\n                        this._historyTableUndo();\n\n                        return;\n                    }\n                }\n            }\n\n            if (this.onGoingRedo && (e.ctrlKey || e.shiftKey)) {\n                // Special case where if the user has entered `Control+Shift+z`, then release `z`, keeping `Control` or `Shift` pressed, then `this.onGoingRedo` is never changed back to `false` when the user release `Control` or `Shift`\n                this.onGoingRedo = false;\n            }\n\n            // Manage the Cut event\n            if ((e.ctrlKey || e.metaKey) && this.eventKey === _AutoNumericEnum2.default.keyName.x) {\n                // Save the caret position at the start of the selection\n                var caretPosition = _AutoNumericHelper2.default.getElementSelection(this.domElement).start;\n                // Convert the remaining 'formatted' numbers in a Js number\n                var cutNumber = this.constructor._toNumericValue(_AutoNumericHelper2.default.getElementValue(e.target), this.settings);\n                // Try to set that value with `set()`\n                this.set(cutNumber);\n                // Set back the initial caret position\n                this._setCaretPosition(caretPosition);\n            }\n\n            // Manage the reformat when hovered with the Alt key pressed\n            if (this.eventKey === _AutoNumericEnum2.default.keyName.Alt && this.hoveredWithAlt) {\n                this.constructor._reformatAltHovered(this);\n\n                return;\n            }\n\n            this._updateInternalProperties(e);\n\n            var skip = this._processNonPrintableKeysAndShortcuts(e);\n            delete this.valuePartsBeforePaste;\n            var targetValue = _AutoNumericHelper2.default.getElementValue(e.target);\n            if (skip || targetValue === '') {\n                return;\n            }\n\n            // Added to properly place the caret when only the currency sign is present\n            if (targetValue === this.settings.currencySymbol) {\n                if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) {\n                    _AutoNumericHelper2.default.setElementSelection(e.target, 0);\n                } else {\n                    _AutoNumericHelper2.default.setElementSelection(e.target, this.settings.currencySymbol.length);\n                }\n            } else if (this.eventKey === _AutoNumericEnum2.default.keyName.Tab) {\n                _AutoNumericHelper2.default.setElementSelection(e.target, 0, targetValue.length);\n            }\n\n            if (targetValue === this.settings.suffixText || this.rawValue === '' && this.settings.currencySymbol !== '' && this.settings.suffixText !== '') {\n                _AutoNumericHelper2.default.setElementSelection(e.target, 0);\n            }\n\n            // Saves the extended decimal to preserve the data when navigating away from the page\n            if (this.settings.decimalPlacesShownOnFocus !== null) {\n                this._saveValueToPersistentStorage();\n            }\n\n            if (!this.formatted) {\n                //TODO Is this line needed? Considering that onKeydown and onKeypress both finish by setting it to false...\n                this._formatValue(e);\n            }\n\n            // Force the `rawValue` update on Android Chrome\n            this._saveRawValueForAndroid();\n\n            // If the input value has changed during the key press event chain, an event is sent to alert that a formatting has been done (cf. Issue #187)\n            if (targetValue !== this.initialValueOnKeydown) {\n                this._triggerEvent(AutoNumeric.events.formatted, e.target, {\n                    oldValue: this.initialValueOnKeydown,\n                    newValue: targetValue,\n                    oldRawValue: this.initialRawValueOnKeydown,\n                    newRawValue: this.rawValue,\n                    isPristine: this.isPristine(false),\n                    error: null,\n                    aNElement: this\n                });\n            }\n\n            // Update the selection of the current element of the history table\n            if (this.historyTable.length > 1) {\n                var selection = _AutoNumericHelper2.default.getElementSelection(this.domElement);\n                this.selectionStart = selection.start;\n                this.selectionEnd = selection.end;\n                this.historyTable[this.historyTableIndex].start = this.selectionStart;\n                this.historyTable[this.historyTableIndex].end = this.selectionEnd;\n            }\n        }\n\n        /**\n         * On Android Chrome, the `rawValue` is not updated when the user changes the input value.\n         * This function updates the `rawValue` accordingly.\n         * @private\n         */\n\n    }, {\n        key: '_saveRawValueForAndroid',\n        value: function _saveRawValueForAndroid() {\n            if (this.eventKey === _AutoNumericEnum2.default.keyName.AndroidDefault) {\n                var normalizedValue = this.constructor._stripAllNonNumberCharactersExceptCustomDecimalChar(this.getFormatted(), this.settings, true, this.isFocused);\n                normalizedValue = this.constructor._convertToNumericString(normalizedValue, this.settings);\n\n                this._setRawValue(normalizedValue);\n            }\n        }\n\n        /**\n         * Handler for 'focusout' events\n         * On focusout, multiple things happens :\n         * - The element value is formatted back if the `Alt` key was pressed,\n         * - The element value is formatted back if `showOnlyNumbersOnFocus` was set to only show numbers,\n         * - The element value is multiplied by `rawValueDivisor` on `blur`\n         *\n         * Note: On focusout, the `rawValue` is never changed. Only the formatted value can be modified.\n         *\n         * @param {Event} e\n         */\n\n    }, {\n        key: '_onFocusOutAndMouseLeave',\n        value: function _onFocusOutAndMouseLeave(e) {\n            //TODO Create separate handlers for blur and mouseleave\n            this.isEditing = false; // Just in case no `keyUp` event have been sent (if the user lost the focus to the window while typing)\n\n            //FIXME Do not call `set()` if the current raw value is the same as the one we are trying to set (currently, on focus out, `set()` is always called, even if the value has not changed\n            if (this.settings.unformatOnHover && e.type === 'mouseleave' && this.hoveredWithAlt) {\n                this.constructor._reformatAltHovered(this);\n\n                return;\n            }\n\n            if (e.type === 'mouseleave' && !this.isFocused || e.type === 'blur') {\n                this._saveValueToPersistentStorage();\n                if (this.settings.showOnlyNumbersOnFocus === AutoNumeric.options.showOnlyNumbersOnFocus.onlyNumbers) {\n                    this.settings.digitGroupSeparator = this.originalDigitGroupSeparator;\n                    this.settings.currencySymbol = this.originalCurrencySymbol;\n                    this.settings.suffixText = this.originalSuffixText;\n                }\n\n                // Use the rawValue, multiplied by `rawValueDivisor` if defined\n                var rawValueToFormat = this._getRawValueToFormat(this.rawValue);\n                var isRawValueNull = _AutoNumericHelper2.default.isNull(rawValueToFormat);\n\n                var _constructor$_checkIf5 = this.constructor._checkIfInRangeWithOverrideOption(rawValueToFormat, this.settings),\n                    _constructor$_checkIf6 = _slicedToArray(_constructor$_checkIf5, 2),\n                    minTest = _constructor$_checkIf6[0],\n                    maxTest = _constructor$_checkIf6[1];\n\n                // Directly set the formatted value if the `rawValue` is found in `valuesToStrings`\n\n\n                var elementValueIsAlreadySet = false;\n                if (rawValueToFormat !== '' && !isRawValueNull) {\n                    if (!minTest) {\n                        this._triggerEvent(AutoNumeric.events.minRangeExceeded, this.domElement);\n                    }\n\n                    if (!maxTest) {\n                        this._triggerEvent(AutoNumeric.events.maxRangeExceeded, this.domElement);\n                    }\n\n                    if (this.settings.valuesToStrings && this._checkValuesToStrings(rawValueToFormat)) {\n                        // Set the formatted value with the corresponding string\n                        this._setElementValue(this.settings.valuesToStrings[rawValueToFormat]);\n                        elementValueIsAlreadySet = true;\n                    }\n                }\n\n                // Only generate the formatted value if no `valuesToStrings` have been found\n                if (!elementValueIsAlreadySet) {\n                    var value = void 0;\n                    if (isRawValueNull || rawValueToFormat === '') {\n                        value = rawValueToFormat;\n                    } else {\n                        value = String(rawValueToFormat);\n                    }\n\n                    if (rawValueToFormat !== '' && !isRawValueNull) {\n                        if (minTest && maxTest && !this.constructor._isElementValueEmptyOrOnlyTheNegativeSign(rawValueToFormat, this.settings)) {\n                            value = this._modifyNegativeSignAndDecimalCharacterForRawValue(value);\n\n                            if (this.settings.divisorWhenUnfocused && !_AutoNumericHelper2.default.isNull(value)) {\n                                value = value / this.settings.divisorWhenUnfocused;\n                                value = value.toString();\n                            }\n\n                            value = this.constructor._roundFormattedValueShownOnBlur(value, this.settings);\n                            value = this.constructor._modifyNegativeSignAndDecimalCharacterForFormattedValue(value, this.settings);\n                        } else {\n                            if (!minTest) {\n                                this._triggerEvent(AutoNumeric.events.minRangeExceeded, this.domElement);\n                            }\n\n                            if (!maxTest) {\n                                this._triggerEvent(AutoNumeric.events.maxRangeExceeded, this.domElement);\n                            }\n                        }\n                    } else if (rawValueToFormat === '') {\n                        switch (this.settings.emptyInputBehavior) {\n                            case AutoNumeric.options.emptyInputBehavior.zero:\n                                this._setRawValue('0');\n                                value = this.constructor._roundValue('0', this.settings, 0);\n                                break;\n                            case AutoNumeric.options.emptyInputBehavior.min:\n                                this._setRawValue(this.settings.minimumValue);\n                                value = this.constructor._roundFormattedValueShownOnFocusOrBlur(this.settings.minimumValue, this.settings, this.isFocused);\n                                break;\n                            case AutoNumeric.options.emptyInputBehavior.max:\n                                this._setRawValue(this.settings.maximumValue);\n                                value = this.constructor._roundFormattedValueShownOnFocusOrBlur(this.settings.maximumValue, this.settings, this.isFocused);\n                                break;\n                            default:\n                                if (_AutoNumericHelper2.default.isNumber(this.settings.emptyInputBehavior)) {\n                                    this._setRawValue(this.settings.emptyInputBehavior);\n                                    value = this.constructor._roundFormattedValueShownOnFocusOrBlur(this.settings.emptyInputBehavior, this.settings, this.isFocused);\n                                }\n                        }\n                    }\n\n                    var groupedValue = this.constructor._orderValueCurrencySymbolAndSuffixText(value, this.settings, false);\n                    if (!(this.constructor._isElementValueEmptyOrOnlyTheNegativeSign(value, this.settings) || isRawValueNull && this.settings.emptyInputBehavior === AutoNumeric.options.emptyInputBehavior.null)) {\n                        groupedValue = this.constructor._addGroupSeparators(value, this.settings, false, rawValueToFormat);\n                    }\n\n                    // Testing for `allowDecimalPadding.never` or `allowDecimalPadding.floats` is needed to make sure we do not keep a trailing decimalCharacter (like '500.') in the element, since the raw value would still be a correctly formatted integer ('500')\n                    if (groupedValue !== rawValueToFormat || rawValueToFormat === '' || // This make sure we get rid on any currency symbol or suffix that might have been added on focus\n                    this.settings.allowDecimalPadding === AutoNumeric.options.allowDecimalPadding.never || this.settings.allowDecimalPadding === AutoNumeric.options.allowDecimalPadding.floats) {\n                        if (this.settings.symbolWhenUnfocused && rawValueToFormat !== '' && rawValueToFormat !== null) {\n                            groupedValue = '' + groupedValue + this.settings.symbolWhenUnfocused;\n                        }\n\n                        this._setElementValue(groupedValue);\n                    }\n                }\n\n                if (e.type === 'blur') {\n                    //TODO Create separate handlers for blur and mouseleave, really.\n                    this._onBlur(e);\n                }\n            }\n        }\n\n        /**\n         * Handler for 'paste' event\n         *\n         * @param {Event|ClipboardEvent} e\n         */\n\n    }, {\n        key: '_onPaste',\n        value: function _onPaste(e) {\n            //FIXME When pasting '000' on a thousand group selection, the whole selection gets deleted, and only one '0' is pasted (cf. issue #302)\n            // The event is prevented by default, since otherwise the user would be able to paste invalid characters into the input\n            e.preventDefault();\n\n            if (this.settings.readOnly || this.domElement.readOnly || this.domElement.disabled) {\n                // Do not allow pasting in a readonly element (fix issue #505)\n                return;\n            }\n\n            var rawPastedText = void 0;\n            if (window.clipboardData && window.clipboardData.getData) {\n                // Special case for the obsolete and non-standard IE browsers 10 and 11\n                rawPastedText = window.clipboardData.getData('Text');\n            } else if (e.clipboardData && e.clipboardData.getData) {\n                // Normal case with modern browsers\n                rawPastedText = e.clipboardData.getData('text/plain');\n            } else {\n                _AutoNumericHelper2.default.throwError('Unable to retrieve the pasted value. Please use a modern browser (ie. Firefox or Chromium).');\n            }\n\n            // Fix for firefox paste handling on `contenteditable` elements where `e.target` is the the text node, not the element\n            var eventTarget = void 0;\n            if (!e.target.tagName) {\n                eventTarget = e.explicitOriginalTarget;\n            } else {\n                eventTarget = e.target;\n            }\n\n            // 0. Special case if the user has selected all the input text before pasting\n            var initialFormattedValue = _AutoNumericHelper2.default.getElementValue(eventTarget);\n            var selectionStart = eventTarget.selectionStart || 0;\n            var selectionEnd = eventTarget.selectionEnd || 0;\n            var selectionSize = selectionEnd - selectionStart;\n\n            if (selectionSize === initialFormattedValue.length) {\n                // If all the element text is selected\n                //TODO Refactor this with the tests below\n                // Since the whole element content will be replaced, no need to complicate things and directly test for the validity of the pasted content, then set the `rawValue` and caret position (fix issue #482)\n                // 1. Strip all thousand separators, brackets and currency sign, and convert the decimal character to a dot\n                var _untranslatedPastedText = this._preparePastedText(rawPastedText);\n                var pastedRawValue = _AutoNumericHelper2.default.arabicToLatinNumbers(_untranslatedPastedText, false, false, false); // Allow pasting arabic numbers\n\n                // 2. Check that the paste is a valid number once it has been normalized to a raw value\n                if (pastedRawValue === '.' || pastedRawValue === '' || pastedRawValue !== '.' && !_AutoNumericHelper2.default.isNumber(pastedRawValue)) {\n                    this.formatted = true; // This prevent the `keyup` event on the `v` key during a paste to try to format an empty value.\n                    // If the user tries to paste a single decimal character (that has been translated to '.' already) or the empty value, ignore the paste\n                    if (this.settings.onInvalidPaste === AutoNumeric.options.onInvalidPaste.error) {\n                        _AutoNumericHelper2.default.throwError('The pasted value \\'' + rawPastedText + '\\' is not a valid paste content.');\n                    }\n\n                    return;\n                }\n\n                // 3. Then try to set it as the new value. The `set()` method will run the additional tests (ie. limits) as needed.\n                this.set(pastedRawValue);\n                this.formatted = true;\n\n                // 4. On a 'normal' non-autoNumeric input, an `input` event is sent when a paste is done. We mimic that.\n                this._triggerEvent(AutoNumeric.events.native.input, eventTarget);\n\n                // 5. Return since the job is done\n                return;\n            }\n\n            // 1. Check if the paste has a negative sign (only if it's the first character), and store that information for later use\n            var isPasteNegative = _AutoNumericHelper2.default.isNegativeStrict(rawPastedText, this.settings.negativeSignCharacter);\n            if (isPasteNegative) {\n                // 1a. Remove the negative sign from the pasted text\n                rawPastedText = rawPastedText.slice(1, rawPastedText.length);\n            }\n\n            // 2. Strip all thousand separators, brackets and currency sign, and convert the decimal character to a dot\n            var untranslatedPastedText = this._preparePastedText(rawPastedText);\n\n            var pastedText = void 0;\n            if (untranslatedPastedText === '.') {\n                // Special case : If the user tries to paste a single decimal character (that has been translated to '.' already)\n                pastedText = '.';\n            } else {\n                // Normal case\n                // Allow pasting arabic numbers\n                pastedText = _AutoNumericHelper2.default.arabicToLatinNumbers(untranslatedPastedText, false, false, false);\n            }\n\n            // 3. Test if the paste is valid (only has numbers and eventually a decimal character). If it's not valid, stop here.\n            if (pastedText !== '.' && (!_AutoNumericHelper2.default.isNumber(pastedText) || pastedText === '')) {\n                this.formatted = true; // This prevent the `keyup` event on the `v` key during a paste to try to format an empty value (fix issue #484)\n                if (this.settings.onInvalidPaste === AutoNumeric.options.onInvalidPaste.error) {\n                    _AutoNumericHelper2.default.throwError('The pasted value \\'' + rawPastedText + '\\' is not a valid paste content.');\n                }\n\n                return;\n            }\n\n            // 4. Calculate the paste result\n            var caretPositionOnInitialTextAfterPasting = void 0;\n            var isInitialValueNegative = _AutoNumericHelper2.default.isNegativeStrict(this.getNumericString(), this.settings.negativeSignCharacter);\n            var isPasteNegativeAndInitialValueIsPositive = void 0;\n            var result = void 0;\n\n            // If the pasted content is negative, then the result will be negative too\n            if (isPasteNegative && !isInitialValueNegative) {\n                isInitialValueNegative = true;\n                isPasteNegativeAndInitialValueIsPositive = true;\n            } else {\n                isPasteNegativeAndInitialValueIsPositive = false;\n            }\n\n            // 1. Generate the unformatted result\n            var leftFormattedPart = initialFormattedValue.slice(0, selectionStart);\n            var rightFormattedPart = initialFormattedValue.slice(selectionEnd, initialFormattedValue.length);\n\n            if (selectionStart !== selectionEnd) {\n                // a. If there is a selection, remove the selected part, and return the left and right part\n                result = this._preparePastedText(leftFormattedPart + rightFormattedPart);\n            } else {\n                // b. Else if this is only one caret (and therefore no selection), then return the left and right part\n                result = this._preparePastedText(initialFormattedValue);\n            }\n\n            // Add back the negative sign if needed\n            if (isInitialValueNegative) {\n                result = _AutoNumericHelper2.default.setRawNegativeSign(result);\n            }\n\n            // Build the unformatted result string\n            caretPositionOnInitialTextAfterPasting = _AutoNumericHelper2.default.convertCharacterCountToIndexPosition(_AutoNumericHelper2.default.countNumberCharactersOnTheCaretLeftSide(initialFormattedValue, selectionStart, this.settings.decimalCharacter));\n            if (isPasteNegativeAndInitialValueIsPositive) {\n                // If the initial paste is negative and the initial value is not, then I must offset the caret position by one place to the right to take the additional hyphen into account\n                caretPositionOnInitialTextAfterPasting++;\n                //TODO Quid if the negative sign is not on the left (negativePositiveSignPlacement and currencySymbolPlacement)?\n                //TODO Quid if the positive sign is shown?\n            }\n\n            var leftPart = result.slice(0, caretPositionOnInitialTextAfterPasting);\n            var rightPart = result.slice(caretPositionOnInitialTextAfterPasting, result.length);\n            var leftPartContainedADot = false;\n            if (pastedText === '.') {\n                if (_AutoNumericHelper2.default.contains(leftPart, '.')) {\n                    // If I remove a dot here, then I need to update the caret position (decrement it by 1) when positioning it\n                    // To do so, we keep that info in order to modify the caret position later\n                    leftPartContainedADot = true;\n                    leftPart = leftPart.replace('.', '');\n                }\n\n                rightPart = rightPart.replace('.', '');\n            }\n\n            // Manage the case where a negative number is pasted onto another negative number that is entirely selected (cf. issue #593)\n            var negativePasteOnNegativeNumber = false;\n            if (leftPart === '' && rightPart === '-') {\n                leftPart = '-';\n                rightPart = '';\n                // When pasting a negative number on a negative number, we need to offset the caret position one place to the right to take into account the negative sign\n                negativePasteOnNegativeNumber = true;\n            }\n\n            // -- Here, we are good to go to continue on the same basis for each value of the `onInvalidPaste` option\n\n            switch (this.settings.onInvalidPaste) {\n                /* 4a. Truncate paste behavior:\n                 * Insert as many numbers as possible on the right hand side of the caret from the pasted text content, until the input reach its range limit.\n                 * If there is more characters in the clipboard once a limit is reached, drop the extraneous characters.\n                 * Otherwise paste all the numbers from the clipboard.\n                 * While doing so, we check if the result is within the minimum and maximum values allowed, and stop as soon as we encounter one of those.\n                 *\n                 * 4b. Replace paste behavior:\n                 * Idem than the 'truncate' paste behavior, except that when a range limit is hit, we try to replace the subsequent initial numbers with the pasted ones, until we hit the range limit a second (and last) time, or we run out of numbers to paste\n                 */\n                /* eslint no-case-declarations: 0 */\n                case AutoNumeric.options.onInvalidPaste.truncate:\n                case AutoNumeric.options.onInvalidPaste.replace:\n                    // c. Add numbers one by one at the caret position, while testing if the result is valid and within the range of the minimum and maximum value\n                    //    Continue until you either run out of numbers to paste, or that you get out of the range limits\n                    var minParse = _AutoNumericHelper2.default.parseStr(this.settings.minimumValue);\n                    var maxParse = _AutoNumericHelper2.default.parseStr(this.settings.maximumValue);\n                    var lastGoodKnownResult = result; // This is set as the default, in case we do not add even one number\n                    var pastedTextIndex = 0;\n                    var modifiedLeftPart = leftPart;\n\n                    while (pastedTextIndex < pastedText.length) {\n                        // Modify the result with another pasted character\n                        modifiedLeftPart += pastedText[pastedTextIndex];\n                        result = modifiedLeftPart + rightPart;\n\n                        // Check the range limits\n                        if (!this.constructor._checkIfInRange(result, minParse, maxParse)) {\n                            // The result is out of the range limits, stop the loop here\n                            break;\n                        }\n\n                        // Save the last good known result\n                        lastGoodKnownResult = result;\n\n                        // Update the local variables for the next loop\n                        pastedTextIndex++;\n                    }\n\n                    // Update the last caret position where to insert a new number\n                    caretPositionOnInitialTextAfterPasting += pastedTextIndex;\n                    if (negativePasteOnNegativeNumber) caretPositionOnInitialTextAfterPasting++;\n\n                    //XXX Here we have the result for the `truncate` option\n                    if (this.settings.onInvalidPaste === AutoNumeric.options.onInvalidPaste.truncate) {\n                        //TODO If the user as defined a truncate callback and there are still some numbers (that will be dropped), then call this callback with the initial paste as well as the remaining numbers\n                        result = lastGoodKnownResult;\n\n                        if (leftPartContainedADot) {\n                            // If a dot has been removed for the part on the left of the caret, we decrement the caret index position\n                            caretPositionOnInitialTextAfterPasting--;\n                        }\n                        break;\n                    }\n                    //XXX ...else we need to continue modifying the result for the 'replace' option\n\n                    // d. Until there are numbers to paste, replace the initial numbers one by one, and still do the range test.\n                    //    Stop when you have no more numbers to paste, or if you are out of the range limits.\n                    //    If you do get to the range limits, use the previous known good value within those limits.\n                    //    Note: The numbers are replaced one by one, in the integer then decimal part, while ignoring the decimal character\n                    //TODO What should happen if the user try to paste a decimal number? Should we override the current initial decimal character in favor of this new one? If we do, then we have to recalculate the vMin/vMax from the start in order to take into account this new decimal character position..\n                    var lastGoodKnownResultIndex = caretPositionOnInitialTextAfterPasting;\n                    var lastGoodKnownResultSize = lastGoodKnownResult.length;\n\n                    while (pastedTextIndex < pastedText.length && lastGoodKnownResultIndex < lastGoodKnownResultSize) {\n                        if (lastGoodKnownResult[lastGoodKnownResultIndex] === '.') {\n                            // We skip the decimal character 'replacement'. That way, we do not change the decimal character position regarding the remaining numbers.\n                            lastGoodKnownResultIndex++;\n                            continue;\n                        }\n\n                        // This replace one character at a time\n                        result = _AutoNumericHelper2.default.replaceCharAt(lastGoodKnownResult, lastGoodKnownResultIndex, pastedText[pastedTextIndex]);\n\n                        // Check the range limits\n                        if (!this.constructor._checkIfInRange(result, minParse, maxParse)) {\n                            // The result is out of the range limits, stop the loop here\n                            break;\n                        }\n\n                        // Save the last good known result\n                        lastGoodKnownResult = result;\n\n                        // Update the local variables for the next loop\n                        pastedTextIndex++;\n                        lastGoodKnownResultIndex++;\n                    }\n\n                    // Update the last caret position where to insert a new number\n                    caretPositionOnInitialTextAfterPasting = lastGoodKnownResultIndex;\n\n                    if (leftPartContainedADot) {\n                        // If a dot has been removed for the part on the left of the caret, we decrement the caret index position\n                        caretPositionOnInitialTextAfterPasting--;\n                    }\n\n                    result = lastGoodKnownResult;\n\n                    break;\n                /* 4c. Normal paste behavior:\n                 * Insert the pasted number inside the current unformatted text, at the correct caret position or selection\n                 */\n                case AutoNumeric.options.onInvalidPaste.error:\n                case AutoNumeric.options.onInvalidPaste.ignore:\n                case AutoNumeric.options.onInvalidPaste.clamp:\n                default:\n                    // Generate the unformatted result\n                    result = '' + leftPart + pastedText + rightPart;\n\n                    // 2. Calculate the caret position in the unformatted value, for later use\n                    if (selectionStart === selectionEnd) {\n                        // There is no selection, then the caret position is set after the pasted text\n                        var indexWherePastedTextHasBeenInserted = _AutoNumericHelper2.default.convertCharacterCountToIndexPosition(_AutoNumericHelper2.default.countNumberCharactersOnTheCaretLeftSide(initialFormattedValue, selectionStart, this.settings.decimalCharacter));\n                        caretPositionOnInitialTextAfterPasting = indexWherePastedTextHasBeenInserted + pastedText.length; // I must not count the characters that have been removed from the pasted text (ie. '.')\n                    } else if (rightPart === '') {\n                        // If the user selected from the caret position to the end of the input (on the far right)\n                        caretPositionOnInitialTextAfterPasting = _AutoNumericHelper2.default.convertCharacterCountToIndexPosition(_AutoNumericHelper2.default.countNumberCharactersOnTheCaretLeftSide(initialFormattedValue, selectionStart, this.settings.decimalCharacter)) + pastedText.length;\n                        if (negativePasteOnNegativeNumber) caretPositionOnInitialTextAfterPasting++;\n                    } else {\n                        // Usual case\n                        var indexSelectionEndInRawValue = _AutoNumericHelper2.default.convertCharacterCountToIndexPosition(_AutoNumericHelper2.default.countNumberCharactersOnTheCaretLeftSide(initialFormattedValue, selectionEnd, this.settings.decimalCharacter));\n\n                        // Here I must not count the characters that have been removed from the pasted text (ie. '.'), or the thousand separators in the initial selected text\n                        var selectedText = _AutoNumericHelper2.default.getElementValue(eventTarget).slice(selectionStart, selectionEnd);\n                        caretPositionOnInitialTextAfterPasting = indexSelectionEndInRawValue - selectionSize + _AutoNumericHelper2.default.countCharInText(this.settings.digitGroupSeparator, selectedText) + pastedText.length;\n                    }\n\n                    // Modify the caret position for special cases, only if the whole input has not been selected\n                    if (isPasteNegativeAndInitialValueIsPositive) {\n                        // If the pasted value has a negative sign ('-'), but the initial value does not, offset the index by one\n                        caretPositionOnInitialTextAfterPasting++;\n                    }\n\n                    if (leftPartContainedADot) {\n                        // If a dot has been removed for the part on the left of the caret, we decrement the caret index position\n                        caretPositionOnInitialTextAfterPasting--;\n                    }\n            }\n\n            // 5. Check if the result is a valid number, if not, drop the paste and do nothing.\n            if (!_AutoNumericHelper2.default.isNumber(result) || result === '') {\n                if (this.settings.onInvalidPaste === AutoNumeric.options.onInvalidPaste.error) {\n                    _AutoNumericHelper2.default.throwError('The pasted value \\'' + rawPastedText + '\\' would result into an invalid content \\'' + result + '\\'.'); //TODO Should we send a warning instead of throwing an error?\n                    //TODO This is not DRY ; refactor with above\n                }\n                return;\n            }\n\n            // 6. If it's a valid number, check if it falls inside the minimum and maximum value. If this fails, modify the value following this procedure :\n            /*\n             * If 'error' (this is the default) :\n             *      - Normal paste behavior.\n             *      - Try to set the new value, if it fails, then throw an error in the console.\n             *      - Do not change the input value, do not change the current selection.\n             * If 'ignore' :\n             *      - Normal paste behavior.\n             *      - Try to set the new value, if it fails, do nothing more.\n             *      - Do not change the input value, do not change the current selection.\n             * If 'clamp' :\n             *      - Normal paste behavior.\n             *      - Try to set the new value, if it fails, set the value to the minimum or maximum limit, whichever is closest to the\n             *        paste result.\n             *      - Change the caret position to be positioned on the left hand side of the decimal character.\n             * If 'truncate' :\n             *      - Truncate paste behavior.\n             *      - Try to set the new value, until it fails (if the result is out of the min and max value limits).\n             *      - Drop the remaining non-pasted numbers, and keep the last known non-failing result.\n             *      - Change the caret position to be positioned after the last pasted character.\n             * If 'replace' :\n             *      - Replace paste behavior.\n             *      - Try to set the new value, until it fails (if the result is out of the min and max value limits).\n             *      - Then try to replace as many numbers as possible with the pasted ones. Once it fails, keep the last known non-failing result.\n             *      - Change the caret position to be positioned after the last pasted character.\n             */\n            var valueHasBeenSet = false;\n            var valueHasBeenClamped = false;\n            try {\n                this.set(result);\n                valueHasBeenSet = true;\n            } catch (error) {\n                var clampedValue = void 0;\n                switch (this.settings.onInvalidPaste) {\n                    case AutoNumeric.options.onInvalidPaste.clamp:\n                        clampedValue = _AutoNumericHelper2.default.clampToRangeLimits(result, this.settings);\n                        try {\n                            this.set(clampedValue);\n                        } catch (error) {\n                            _AutoNumericHelper2.default.throwError('Fatal error: Unable to set the clamped value \\'' + clampedValue + '\\'.');\n                        }\n\n                        valueHasBeenClamped = true;\n                        valueHasBeenSet = true;\n                        result = clampedValue; // This is used only for setting the caret position later\n                        break;\n                    case AutoNumeric.options.onInvalidPaste.error:\n                    case AutoNumeric.options.onInvalidPaste.truncate:\n                    case AutoNumeric.options.onInvalidPaste.replace:\n                        // Throw an error message\n                        _AutoNumericHelper2.default.throwError('The pasted value \\'' + rawPastedText + '\\' results in a value \\'' + result + '\\' that is outside of the minimum [' + this.settings.minimumValue + '] and maximum [' + this.settings.maximumValue + '] value range.');\n                    // falls through\n                    case AutoNumeric.options.onInvalidPaste.ignore:\n                    // Do nothing\n                    // falls through\n                    default:\n                        return; // ...and nothing else should be changed\n                }\n            }\n\n            // 7. Then lastly, set the caret position at the right logical place\n            var targetValue = _AutoNumericHelper2.default.getElementValue(eventTarget);\n            var caretPositionInFormattedNumber = void 0;\n            if (valueHasBeenSet) {\n                switch (this.settings.onInvalidPaste) {\n                    case AutoNumeric.options.onInvalidPaste.clamp:\n                        if (valueHasBeenClamped) {\n                            if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) {\n                                _AutoNumericHelper2.default.setElementSelection(eventTarget, targetValue.length - this.settings.currencySymbol.length); // This puts the caret on the right of the last decimal place\n                            } else {\n                                _AutoNumericHelper2.default.setElementSelection(eventTarget, targetValue.length); // ..and this on the far right\n                            }\n\n                            break;\n                        } // else if the value has not been clamped, the default behavior is used...\n                    // falls through\n                    case AutoNumeric.options.onInvalidPaste.error:\n                    case AutoNumeric.options.onInvalidPaste.ignore:\n                    case AutoNumeric.options.onInvalidPaste.truncate:\n                    case AutoNumeric.options.onInvalidPaste.replace:\n                    default:\n                        // Whenever one or multiple characters are pasted, this means we have to manage the potential thousand separators that could be added by the formatting\n                        caretPositionInFormattedNumber = _AutoNumericHelper2.default.findCaretPositionInFormattedNumber(result, caretPositionOnInitialTextAfterPasting, targetValue, this.settings.decimalCharacter);\n                        _AutoNumericHelper2.default.setElementSelection(eventTarget, caretPositionInFormattedNumber);\n                }\n            }\n\n            // 8. We make sure we send an input event only if the result is different than the initial value before the paste\n            if (valueHasBeenSet && initialFormattedValue !== targetValue) {\n                // On a 'normal' non-autoNumeric input, an `input` event is sent when a paste is done. We mimic that.\n                this._triggerEvent(AutoNumeric.events.native.input, eventTarget);\n            }\n        }\n\n        /**\n         * When focusing out of the input, we check if the value has changed, and if it has, then we send a `change` event (since the native one would have been prevented by `e.preventDefault()` called in the other event listeners).\n         * We also update the info of the focused state in the `this.isFocused` variable.\n         *\n         * @param {Event} e\n         */\n\n    }, {\n        key: '_onBlur',\n        value: function _onBlur(e) {\n            // Keep track if the element is currently focused\n            this.isFocused = false;\n            // Keep track if the user is currently editing the element\n            this.isEditing = false;\n\n            // Send a `change` event if the raw value has been changed since the last focus or 'enter' validation\n            if (this.rawValue !== this.rawValueOnFocus) {\n                this._triggerEvent(AutoNumeric.events.native.change, e.target);\n            }\n\n            this.rawValueOnFocus = void 0; // Reset the tracker\n        }\n\n        /**\n         * Handler for 'wheel' event\n         *\n         * @param {WheelEvent} e\n         */\n\n    }, {\n        key: '_onWheel',\n        value: function _onWheel(e) {\n            if (this.settings.readOnly || this.domElement.readOnly || this.domElement.disabled) {\n                // Do not allow scrolling in a readonly element (fix issue #541)\n                return;\n            }\n\n            if (this.settings.modifyValueOnWheel) {\n                if (this.settings.wheelOn === AutoNumeric.options.wheelOn.focus) {\n                    if (this.isFocused) {\n                        if (!e.shiftKey) {\n                            this.wheelAction(e);\n                        }\n                    } else if (e.shiftKey) {\n                        this.wheelAction(e);\n                    }\n                } else if (this.settings.wheelOn === AutoNumeric.options.wheelOn.hover) {\n                    if (!e.shiftKey) {\n                        this.wheelAction(e);\n                    } else {\n                        // Note: When not `defaultPrevented`, Shift + mouse wheel is reserved by the browsers for horizontal scrolling.\n                        // Hence, using the Shift key with the `wheelOn` 'hover' option will only scroll the page if we prevent the default behavior\n                        e.preventDefault(); // Do not scroll horizontally\n\n                        // Scroll vertically\n                        window.scrollBy(0, _AutoNumericHelper2.default.isNegativeStrict(String(e.deltaY)) ? -50 : 50); // `e.deltaY` is usually too small compared to how the page is scrolled. That's why we use a fixed offset.\n                    }\n                } else {\n                    _AutoNumericHelper2.default.throwError('Unknown `wheelOn` option.');\n                }\n            }\n        }\n\n        /**\n         * Increment or decrement the element value according to the `wheelStep` option chosen\n         *\n         * @param {WheelEvent} e The `wheel` event\n         */\n\n    }, {\n        key: 'wheelAction',\n        value: function wheelAction(e) {\n            this.isWheelEvent = true; // Keep the info that we are currently managing a mouse wheel event\n\n            // 0) First, save the caret position so we can set it back once the value has been changed\n            var selectionStart = e.target.selectionStart || 0;\n            var selectionEnd = e.target.selectionEnd || 0;\n\n            // 1) Get the unformatted value\n            var currentUnformattedValue = this.rawValue;\n\n            var result = void 0;\n            if (_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(currentUnformattedValue)) {\n                // If by default the input is empty, start at '0'\n                if (this.settings.minimumValue > 0 || this.settings.maximumValue < 0) {\n                    // or if '0' is not between min and max value, 'minimumValue' if the user does a wheelup, 'maximumValue' if the user does a wheeldown\n                    if (_AutoNumericHelper2.default.isWheelUpEvent(e)) {\n                        result = this.settings.minimumValue;\n                    } else if (_AutoNumericHelper2.default.isWheelDownEvent(e)) {\n                        result = this.settings.maximumValue;\n                    } else {\n                        _AutoNumericHelper2.default.throwError('The event is not a \\'wheel\\' event.');\n                    }\n                } else {\n                    result = 0;\n                }\n            } else {\n                result = currentUnformattedValue;\n            }\n\n            result = +result; // Typecast to a number needed for the following addition/subtraction\n\n            // 2) Increment/Decrement the value\n            // But first, choose the increment/decrement method ; fixed or progressive\n            if (_AutoNumericHelper2.default.isNumber(this.settings.wheelStep)) {\n                var step = +this.settings.wheelStep; // Typecast to a number needed for the following addition/subtraction\n                // Fixed method\n                // This is the simplest method, where a fixed offset in added/subtracted from the current value\n                if (_AutoNumericHelper2.default.isWheelUpEvent(e)) {\n                    // Increment\n                    result += step;\n                } else if (_AutoNumericHelper2.default.isWheelDownEvent(e)) {\n                    // Decrement\n                    result -= step;\n                }\n            } else {\n                // Progressive method\n                // For this method, we calculate an offset that is in relation to the size of the current number (using only the integer part size).\n                // The bigger the number, the bigger the offset (usually the number count in the integer part minus 3, except for small numbers where a different behavior is better for the user experience).\n                //TODO Known limitation : The progressive method does not play well with numbers between 0 and 1 where to modify the decimal places the rawValue first has to go from '1' to '0'\n                if (_AutoNumericHelper2.default.isWheelUpEvent(e)) {\n                    // Increment\n                    result = _AutoNumericHelper2.default.addAndRoundToNearestAuto(result, this.settings.decimalPlacesRawValue);\n                } else if (_AutoNumericHelper2.default.isWheelDownEvent(e)) {\n                    // Decrement\n                    result = _AutoNumericHelper2.default.subtractAndRoundToNearestAuto(result, this.settings.decimalPlacesRawValue);\n                }\n            }\n\n            // 3) Set the new value so it gets formatted\n            // First clamp the result if needed\n            result = _AutoNumericHelper2.default.clampToRangeLimits(result, this.settings);\n            if (result !== +currentUnformattedValue) {\n                // Only 'set' the value if it has changed. For instance 'set' should not happen if the user hits a limit and continue to try to go past it since we clamp the value.\n                this.set(result);\n\n                // Since we changed the input value, we send a native `input` event\n                this._triggerEvent(AutoNumeric.events.native.input, e.target);\n            }\n\n            //XXX Do not prevent if the value is not modified? From a UX point of view, preventing the wheel event when the user use it on top of an autoNumeric element should always be done, even if the value does not change. Perhaps that could affect other scripts relying on this event to be sent though.\n            e.preventDefault(); // We prevent the page to scroll while we increment/decrement the value\n\n            // 4) Finally, we set back the caret position/selection\n            // There is no need to take into account the fact that the number count could be different at the end of the wheel event ; it would be too complex and most of the time unreliable\n            this._setSelection(selectionStart, selectionEnd);\n\n            this.isWheelEvent = false; // Set back the mouse wheel indicator to its default\n        }\n\n        /**\n         * Handler for 'drop' event\n         *\n         * @param {DragEvent} e\n         */\n\n    }, {\n        key: '_onDrop',\n        value: function _onDrop(e) {\n            // Note: by default browsers already prevent the drop on readOnly and disabled elements\n            this.isDropEvent = true;\n            e.preventDefault();\n            var format = void 0;\n            if (_AutoNumericHelper2.default.isIE11()) {\n                format = 'text';\n            } else {\n                format = 'text/plain';\n            }\n\n            var droppedText = e.dataTransfer.getData(format);\n            var cleanedValue = this.unformatOther(droppedText);\n            this.set(cleanedValue);\n            this.isDropEvent = false;\n        }\n\n        /**\n         * Handler for 'submit' events happening on the parent <form> element.\n         * If `unformatOnSubmit` is set to `true`, the element value is first unformatted before the form is submitted.\n         *\n         * @returns {boolean}\n         */\n\n    }, {\n        key: '_onFormSubmit',\n        value: function _onFormSubmit() {\n            var _this10 = this;\n\n            // Search for all the AutoNumeric children of the form element and call the `_unformatOnSubmit()` function\n            var inputElements = this._getFormAutoNumericChildren(this.parentForm);\n            var aNElements = inputElements.map(function (aNElement) {\n                return _this10.constructor.getAutoNumericElement(aNElement);\n            });\n            aNElements.forEach(function (aNElement) {\n                return aNElement._unformatOnSubmit();\n            });\n\n            return true;\n        }\n\n        /**\n         * Handler for 'reset' events caught on the parent <form> element.\n         * When such event is detected, then every child AutoNumeric elements must format their default value that the browser is forcing upon them.\n         *\n         * @private\n         */\n\n    }, {\n        key: '_onFormReset',\n        value: function _onFormReset() {\n            var _this11 = this;\n\n            var inputElements = this._getFormAutoNumericChildren(this.parentForm);\n            var aNElements = inputElements.map(function (aNElement) {\n                return _this11.constructor.getAutoNumericElement(aNElement);\n            });\n            // Tell all the AutoNumeric children to format their default value\n            aNElements.forEach(function (aNElement) {\n                var val = _this11._getDefaultValue(aNElement.node());\n                // aNElement.set(val); //XXX If I use that line, the format is first correctly done, but the form reset is still not finished and will overwrite the formatting. This is why we need to use the following setTimeout line.\n                setTimeout(function () {\n                    return aNElement.set(val);\n                }, 0); //XXX This is an ugly hack, but it seems to be the accepted answer to this problem (https://stackoverflow.com/a/8152960/2834898). This is sad. Do note that I use '0ms' here since using `setTimeout` will push that code on the event stack, and as soon as the reset will be finished, this will be run (see https://stackoverflow.com/a/23987283/2834898).\n            });\n        }\n\n        /**\n         * Unformat the element value according to the `unformatOnSubmit` option\n         *\n         * @private\n         */\n\n    }, {\n        key: '_unformatOnSubmit',\n        value: function _unformatOnSubmit() {\n            if (this.settings.unformatOnSubmit) {\n                this._setElementValue(this.rawValue);\n            }\n        }\n\n        /**\n         * Listen for the `alt` key keydown event globally, and if the event is caught, unformat the AutoNumeric element that is hovered by the mouse.\n         *\n         * @param {KeyboardEvent} e\n         * @private\n         */\n\n    }, {\n        key: '_onKeydownGlobal',\n        value: function _onKeydownGlobal(e) {\n            //TODO Find a way to keep the caret position between the alt keyup/keydown states\n            if (_AutoNumericHelper2.default.character(e) === _AutoNumericEnum2.default.keyName.Alt) {\n                var hoveredElement = _AutoNumericHelper2.default.getHoveredElement();\n                if (AutoNumeric.isManagedByAutoNumeric(hoveredElement)) {\n                    var anElement = AutoNumeric.getAutoNumericElement(hoveredElement);\n                    this.constructor._unformatAltHovered(anElement);\n                }\n            }\n        }\n\n        /**\n         * Listen for the `alt` key keyup event globally, and if the event is caught, reformat the AutoNumeric element that is hovered by the mouse.\n         *\n         * @param {KeyboardEvent} e\n         * @private\n         */\n\n    }, {\n        key: '_onKeyupGlobal',\n        value: function _onKeyupGlobal(e) {\n            if (_AutoNumericHelper2.default.character(e) === _AutoNumericEnum2.default.keyName.Alt) {\n                var hoveredElement = _AutoNumericHelper2.default.getHoveredElement();\n                if (AutoNumeric.isManagedByAutoNumeric(hoveredElement)) {\n                    var anElement = AutoNumeric.getAutoNumericElement(hoveredElement);\n                    this.constructor._reformatAltHovered(anElement);\n                }\n            }\n        }\n\n        /**\n         * Return `true` if the DOM element is supported by autoNumeric.\n         * A supported element is an element whitelisted in the `allowedTagList`.\n         *\n         * @returns {boolean}\n         * @private\n         */\n\n    }, {\n        key: '_isElementTagSupported',\n        value: function _isElementTagSupported() {\n            if (!_AutoNumericHelper2.default.isElement(this.domElement)) {\n                _AutoNumericHelper2.default.throwError('The DOM element is not valid, ' + this.domElement + ' given.');\n            }\n\n            return _AutoNumericHelper2.default.isInArray(this.domElement.tagName.toLowerCase(), this.allowedTagList);\n        }\n\n        /**\n         * Return `true` in the DOM element is an <input>.\n         *\n         * @returns {boolean}\n         * @private\n         */\n\n    }, {\n        key: '_isInputElement',\n        value: function _isInputElement() {\n            return this.domElement.tagName.toLowerCase() === 'input';\n        }\n\n        /**\n         * Return `true` if the input type is supported by AutoNumeric\n         *\n         * @returns {boolean}\n         * @throws\n         */\n\n    }, {\n        key: '_isInputTypeSupported',\n        value: function _isInputTypeSupported() {\n            return this.domElement.type === 'text' || this.domElement.type === 'hidden' || this.domElement.type === 'tel' || _AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(this.domElement.type);\n        }\n\n        /**\n         * Check if the DOM element is supported by autoNumeric.\n         * A supported element is either an <input> element with the correct 'type' attribute, or a tag whitelisted in the `allowedTagList` array.\n         * If the check fails, this method throws.\n         * This function also sets the info `this.isInputElement` which keep tracks if the DOM element is an <input> or not, and the `this.isContentEditable` if the element has the `contenteditable` attribute set to `true` initially.\n         *\n         * @throws\n         * @private\n         */\n\n    }, {\n        key: '_checkElement',\n        value: function _checkElement() {\n            var currentElementTag = this.domElement.tagName.toLowerCase();\n\n            if (!this._isElementTagSupported()) {\n                _AutoNumericHelper2.default.throwError('The <' + currentElementTag + '> tag is not supported by autoNumeric');\n            }\n\n            if (this._isInputElement()) {\n                if (!this._isInputTypeSupported()) {\n                    _AutoNumericHelper2.default.throwError('The input type \"' + this.domElement.type + '\" is not supported by autoNumeric');\n                }\n\n                this.isInputElement = true;\n            } else {\n                this.isInputElement = false;\n                this.isContentEditable = this.domElement.hasAttribute('contenteditable') && this.domElement.getAttribute('contenteditable') === 'true';\n            }\n        }\n\n        /**\n         * Formats the default value on page load.\n         * This is called only if the `formatOnPageLoad` option is set to `true`.\n         *\n         * @param {number|string|null} forcedInitialValue The value that should be used for initialization, in place on the eventual html one\n         */\n\n    }, {\n        key: '_formatDefaultValueOnPageLoad',\n        value: function _formatDefaultValueOnPageLoad() {\n            var forcedInitialValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n            var setValue = true;\n            var currentValue = void 0;\n            if (!_AutoNumericHelper2.default.isNull(forcedInitialValue)) {\n                currentValue = forcedInitialValue;\n            } else {\n                // Make sure the initial value does not have any superfluous whitespaces around it (Fix issue #479)\n                currentValue = _AutoNumericHelper2.default.getElementValue(this.domElement).trim();\n                // Correct the DOM attribute in case some whitespaces were present\n                this.domElement.setAttribute('value', currentValue);\n            }\n\n            if (this.isInputElement || this.isContentEditable) {\n                /*\n                 * If the input value has been set by the dev, but not directly as an attribute in the html, then it takes\n                 * precedence and should get formatted during the initialization (if this input value is a valid number and that the\n                 * developer wants it formatted on init (cf. the `settings.formatOnPageLoad` option)).\n                 * Note; this is true whatever the developer has set for `data-default-value-override` in the html (asp.net users).\n                 *\n                 * In other words : if `defaultValueOverride` is not null, it means the developer is trying to prevent postback problems.\n                 * But if `input.value` is set to a number, and the html `value` attribute is not set, then it means the dev has\n                 * changed the input value, and then it means we should not overwrite his own decision to do so.\n                 * Hence, if `defaultValueOverride` is not null, but `input.value` is a number and `this.domElement.hasAttribute('value')`\n                 * is false, we should ignore `defaultValueOverride` altogether.\n                 */\n                var unLocalizedCurrentValue = this.constructor._toNumericValue(currentValue, this.settings); // This allows to use a localized value on startup\n                if (!this.domElement.hasAttribute('value') || this.domElement.getAttribute('value') === '') {\n                    // Check if the `value` is valid or not\n                    if (!isNaN(Number(unLocalizedCurrentValue)) && Infinity !== unLocalizedCurrentValue) {\n                        this.set(unLocalizedCurrentValue);\n                        setValue = false;\n                    } else {\n                        // If not, inform the developer that nothing usable has been provided\n                        _AutoNumericHelper2.default.throwError('The value [' + currentValue + '] used in the input is not a valid value autoNumeric can work with.');\n                    }\n                } else {\n                    /* Checks for :\n                     * - page reload from back button, and\n                     * - ASP.net form post back\n                     *      The following HTML data attribute is REQUIRED (data-an-default=\"same value as the value attribute\")\n                     *      example: <asp:TextBox runat=\"server\" id=\"someID\" text=\"1234.56\" data-an-default=\"1234.56\">\n                     */\n                    if (this.settings.defaultValueOverride !== null && this.settings.defaultValueOverride.toString() !== currentValue || this.settings.defaultValueOverride === null && currentValue !== '' && currentValue !== this.domElement.getAttribute('value') || currentValue !== '' && this.domElement.getAttribute('type') === 'hidden' && !_AutoNumericHelper2.default.isNumber(unLocalizedCurrentValue)) {\n                        if (this.settings.saveValueToSessionStorage && (this.settings.decimalPlacesShownOnFocus !== null || this.settings.divisorWhenUnfocused)) {\n                            this._setRawValue(this._getValueFromPersistentStorage());\n                        }\n\n                        // If the decimalPlacesShownOnFocus value should NOT be saved in sessionStorage\n                        if (!this.settings.saveValueToSessionStorage) {\n                            var toStrip = this.constructor._removeBrackets(currentValue, this.settings);\n                            if ((this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.suffix || this.settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.prefix && this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) && this.settings.negativeSignCharacter !== '' && _AutoNumericHelper2.default.isNegative(currentValue, this.settings.negativeSignCharacter)) {\n                                this._setRawValue('-' + this.constructor._stripAllNonNumberCharacters(toStrip, this.settings, true, this.isFocused));\n                            } else {\n                                this._setRawValue(this.constructor._stripAllNonNumberCharacters(toStrip, this.settings, true, this.isFocused));\n                            }\n                        }\n\n                        setValue = false;\n                    }\n                }\n\n                if (currentValue === '') {\n                    switch (this.settings.emptyInputBehavior) {\n                        case AutoNumeric.options.emptyInputBehavior.focus:\n                        case AutoNumeric.options.emptyInputBehavior.null:\n                        case AutoNumeric.options.emptyInputBehavior.press:\n                            break;\n                        case AutoNumeric.options.emptyInputBehavior.always:\n                            this._setElementValue(this.settings.currencySymbol);\n                            break;\n                        case AutoNumeric.options.emptyInputBehavior.min:\n                            this.set(this.settings.minimumValue);\n                            break;\n                        case AutoNumeric.options.emptyInputBehavior.max:\n                            this.set(this.settings.maximumValue);\n                            break;\n                        case AutoNumeric.options.emptyInputBehavior.zero:\n                            this.set('0');\n                            break;\n                        // When `emptyInputBehavior` is a number or a string representing a number\n                        default:\n                            this.set(this.settings.emptyInputBehavior);\n                    }\n                } else if (setValue && currentValue === this.domElement.getAttribute('value')) {\n                    this.set(currentValue);\n                }\n            } else if (this.settings.defaultValueOverride === null || this.settings.defaultValueOverride === currentValue) {\n                this.set(currentValue);\n            }\n        }\n\n        /**\n         * Enhance the user experience by modifying the default `negativePositiveSignPlacement` option depending on `currencySymbol` and `currencySymbolPlacement`.\n         *\n         * If the user has not set the placement of the negative sign (`negativePositiveSignPlacement`), but has set a currency symbol (`currencySymbol`),\n         * then we modify the default value of `negativePositiveSignPlacement` in order to keep the resulting output logical by default :\n         * - \"$-1,234.56\" instead of \"-$1,234.56\" ({currencySymbol: \"$\", negativePositiveSignPlacement: \"r\"})\n         * - \"-1,234.56$\" instead of \"1,234.56-$\" ({currencySymbol: \"$\", currencySymbolPlacement: \"s\", negativePositiveSignPlacement: \"p\"})\n         *\n         * @param {object} settings\n         */\n\n    }, {\n        key: '_calculateVMinAndVMaxIntegerSizes',\n\n\n        /**\n         * Analyze and save the minimumValue and maximumValue integer size for later uses\n         * @private\n         */\n        value: function _calculateVMinAndVMaxIntegerSizes() {\n            var _settings$maximumValu = this.settings.maximumValue.toString().split('.'),\n                _settings$maximumValu2 = _slicedToArray(_settings$maximumValu, 1),\n                maximumValueIntegerPart = _settings$maximumValu2[0];\n\n            var _ref = !this.settings.minimumValue && this.settings.minimumValue !== 0 ? [] : this.settings.minimumValue.toString().split('.'),\n                _ref2 = _slicedToArray(_ref, 1),\n                minimumValueIntegerPart = _ref2[0];\n\n            maximumValueIntegerPart = maximumValueIntegerPart.replace(this.settings.negativeSignCharacter, '');\n            minimumValueIntegerPart = minimumValueIntegerPart.replace(this.settings.negativeSignCharacter, '');\n\n            this.settings.mIntPos = Math.max(maximumValueIntegerPart.length, 1);\n            this.settings.mIntNeg = Math.max(minimumValueIntegerPart.length, 1);\n        }\n\n        /**\n         * Calculate once what are the `valuesToStrings` option keys.\n         * @private\n         */\n\n    }, {\n        key: '_calculateValuesToStringsKeys',\n        value: function _calculateValuesToStringsKeys() {\n            if (this.settings.valuesToStrings) {\n                this.valuesToStringsKeys = Object.keys(this.settings.valuesToStrings);\n            } else {\n                this.valuesToStringsKeys = [];\n            }\n        }\n\n        /**\n         * Caches regular expressions for _stripAllNonNumberCharactersExceptCustomDecimalChar\n         *\n         * @param {object} settings\n         * @param {object} regex\n         */\n\n    }, {\n        key: '_transformOptionsValuesToDefaultTypes',\n\n\n        /**\n         * Modify the user settings to make them 'exploitable' later.\n         */\n        value: function _transformOptionsValuesToDefaultTypes() {\n            for (var key in this.settings) {\n                if (this.settings.hasOwnProperty(key)) {\n                    var value = this.settings[key];\n\n                    // Convert the strings 'true' and 'false' to booleans\n                    if (value === 'true' || value === 'false') {\n                        this.settings[key] = value === 'true';\n                    }\n\n                    // Convert numbers in options to strings\n                    //TODO Only transform the values of type 'Number' to 'String' if it's a currency number (so that we can have big numbers). Do not convert other numbers (ie. `historySize`)\n                    if (typeof value === 'number') {\n                        this.settings[key] = value.toString();\n                    }\n                }\n            }\n        }\n\n        /**\n         * Convert the old settings options name to new ones.\n         *\n         * @param {object} options\n         */\n\n    }, {\n        key: '_setSettings',\n\n\n        /**\n         * Analyse the settings/options passed by the user, validate and clean them, then set them into `this.settings`.\n         * Note: This sets the settings to `null` if somehow the settings objet is undefined or empty\n         *       If only `decimalPlaces` is defined in the option, overwrite the other decimalPlaces* options, otherwise, use those options\n         *\n         * @param {object} options\n         * @param {boolean} update - If set to `true`, then the settings already exists and this function only updates them instead of recreating them from scratch\n         * @throws\n         */\n        value: function _setSettings(options) {\n            var update = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n\n            // If the user used old options, we convert them to new ones\n            if (update || !_AutoNumericHelper2.default.isNull(options)) {\n                this.constructor._convertOldOptionsToNewOnes(options);\n            }\n\n            if (update) {\n                // The settings are updated\n                // Update the original data, if it has changed\n                var decimalPlacesRawValueInOptions = 'decimalPlacesRawValue' in options;\n                if (decimalPlacesRawValueInOptions) {\n                    this.settings.originalDecimalPlacesRawValue = options.decimalPlacesRawValue;\n                }\n\n                var decimalPlacesInOptions = 'decimalPlaces' in options;\n                if (decimalPlacesInOptions) {\n                    this.settings.originalDecimalPlaces = options.decimalPlaces;\n                }\n\n                // Then update all the `decimalPlaces*` options\n                this.constructor._calculateDecimalPlacesOnUpdate(options, this.settings);\n\n                // Finally generate the updated settings object to use\n                this._mergeSettings(options); //TODO Check that the `styleRules` option is correctly cloned (due to depth cloning limitation)\n            } else {\n                // The settings are generated for the first time\n                this.settings = {};\n                // If we couldn't grab any settings, create them from the default ones and combine them with the options passed as a parameter as well as with the HTML5 `data-*` info (via `this.domElement.dataset`), if any.\n                this._mergeSettings(this.constructor.getDefaultConfig(), this.domElement.dataset, options, { rawValue: this.defaultRawValue });\n                this.caretFix = false;\n                this.throwInput = true; // Throw input event\n                this.allowedTagList = _AutoNumericEnum2.default.allowedTagList;\n                this.runOnce = false;\n                this.hoveredWithAlt = false; // Keep tracks if the current AutoNumeric element is hovered by the mouse cursor while `Alt` is pressed\n            }\n\n            // Modify the user settings to make them 'exploitable'\n            this._transformOptionsValuesToDefaultTypes();\n\n            // Immediately run the callbacks that could update the settings object\n            this._runCallbacksFoundInTheSettingsObject();\n\n            // Improve the `negativePositiveSignPlacement` option if needed\n            this.constructor._correctNegativePositiveSignPlacementOption(this.settings);\n\n            // Set the `caretPositionOnFocus` and `selectOnFocus` options so that they do not conflict, if one of those have been set manually by the user.\n            // If order to check that, we take a look at the original options the user passed as an argument, not `this.settings` that have been merged with the default settings. //TODO Check the validity of that comment\n            this.constructor._correctCaretPositionOnFocusAndSelectOnFocusOptions(this.settings);\n\n            // Define if the negative or positive signs are allowed\n            this.constructor._setNegativePositiveSignPermissions(this.settings);\n\n            // Calculate the number of decimal places (during the element initialization)\n            if (!update) {\n                // Make sure the `originalDecimalPlaces` info is set\n                if (_AutoNumericHelper2.default.isNull(options) || !options.decimalPlaces) {\n                    this.settings.originalDecimalPlaces = null;\n                } else {\n                    this.settings.originalDecimalPlaces = options.decimalPlaces;\n                }\n\n                // Save the `originalDecimalPlacesRawValue` info\n                this.settings.originalDecimalPlacesRawValue = this.settings.decimalPlacesRawValue;\n\n                // Then update all the `decimalPlaces*` options\n                this.constructor._calculateDecimalPlacesOnInit(this.settings);\n            }\n\n            // Additional changes to the settings object\n            this._calculateVMinAndVMaxIntegerSizes();\n            this._setTrailingNegativeSignInfo();\n            this.regex = {}; // Create the object that will store the regular expressions\n            this.constructor._cachesUsualRegularExpressions(this.settings, this.regex);\n            this.constructor._setBrackets(this.settings);\n            this._calculateValuesToStringsKeys();\n\n            // Validate the settings. Both tests throws if necessary.\n            if (_AutoNumericHelper2.default.isEmptyObj(this.settings)) {\n                _AutoNumericHelper2.default.throwError('Unable to set the settings, those are invalid ; an empty object was given.');\n            }\n\n            this.constructor.validate(this.settings, false, options);\n\n            // Original settings saved for use when decimalPlacesShownOnFocus, divisorWhenUnfocused & showOnlyNumbersOnFocus options are being used\n            this._keepAnOriginalSettingsCopy();\n        }\n\n        /**\n         * Define if the negative or positive signs are allowed, and update the given settings object directly.\n         *\n         * @param {object} settings\n         * @private\n         */\n\n    }, {\n        key: '_preparePastedText',\n\n\n        /**\n         * Return the pasted text that will be used, by stripping most non-numeric characters\n         *\n         * @param {string} text\n         * @returns {string}\n         */\n        value: function _preparePastedText(text) {\n            return this.constructor._stripAllNonNumberCharacters(text, this.settings, true, this.isFocused);\n        }\n\n        /**\n         * Return TRUE if the given value (a number as a string) is within the range set in the settings `minimumValue` and `maximumValue`, FALSE otherwise.\n         *\n         * @param {string} value\n         * @param {object} parsedMinValue Parsed via the `parseStr()` function\n         * @param {object} parsedMaxValue Parsed via the `parseStr()` function\n         * @returns {boolean}\n         */\n\n    }, {\n        key: '_updateInternalProperties',\n\n\n        /**\n         * Update the selection values as well as resets the internal state of the current AutoNumeric object.\n         * This keeps tracks of the current selection and resets the 'processed' state.\n         *\n         * Note : This state can change between the keydown, keypress and keyup events, that's why\n         *        this function is called on each event handler.\n         *\n         * @private\n         */\n        value: function _updateInternalProperties() {\n            this.selection = _AutoNumericHelper2.default.getElementSelection(this.domElement);\n            this.processed = false;\n        }\n\n        /**\n         * Update the `event.key` attribute that triggered the given event.\n         *\n         * `event.key` describes:\n         * - the key name (if a non-printable character),\n         * - or directly the character that result from the key press used to trigger the event.\n         *\n         * @link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key\n         * The key list is described here:\n         * @link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values\n         *\n         * @param {Event|KeyboardEvent} e\n         * @private\n         */\n\n    }, {\n        key: '_updateEventKeyInfo',\n        value: function _updateEventKeyInfo(e) {\n            this.eventKey = _AutoNumericHelper2.default.character(e);\n        }\n\n        /**\n         * Save the unformatted element value.\n         * This is used in the 'cancellable' feature where the element value is saved on focus and input validation, to be used if the user wants to cancel his modifications by hitting the 'Escape' key.\n         *\n         * @private\n         */\n\n    }, {\n        key: '_saveCancellableValue',\n        value: function _saveCancellableValue() {\n            this.savedCancellableValue = this.rawValue;\n        }\n\n        /**\n         * Set the text selection inside the input with the given start and end position.\n         *\n         * @param {int} start\n         * @param {int} end\n         * @private\n         */\n\n    }, {\n        key: '_setSelection',\n        value: function _setSelection(start, end) {\n            //TODO use this function to replace the direct calls to `setElementSelection()`, wherever possible\n            start = Math.max(start, 0);\n            end = Math.min(end, _AutoNumericHelper2.default.getElementValue(this.domElement).length);\n            this.selection = {\n                start: start,\n                end: end,\n                length: end - start\n            };\n\n            _AutoNumericHelper2.default.setElementSelection(this.domElement, start, end);\n        }\n\n        /**\n         * Set the caret position inside the input at the given position.\n         *\n         * @param {int} position\n         * @private\n         */\n\n    }, {\n        key: '_setCaretPosition',\n        value: function _setCaretPosition(position) {\n            this._setSelection(position, position);\n        }\n\n        /**\n         * Return an array containing the string parts located on the left and right side of the caret or selection.\n         * Those parts are left 'untouched', ie. formatted by autoNumeric.\n         *\n         * @returns {[string, string]} The parts on the left and right of the caret or selection\n         * @private\n         */\n\n    }, {\n        key: '_getLeftAndRightPartAroundTheSelection',\n        value: function _getLeftAndRightPartAroundTheSelection() {\n            var value = _AutoNumericHelper2.default.getElementValue(this.domElement);\n            var left = value.substring(0, this.selection.start);\n            var right = value.substring(this.selection.end, value.length);\n\n            return [left, right];\n        }\n\n        /**\n         * Return an array containing the string parts located on the left and right side of the caret or selection.\n         * Those parts are unformatted (stripped) of any non-numbers characters, and any trailing negative character is put back on the left hand side of the number.\n         *\n         * @returns {[string, string]} The parts on the left and right of the caret or selection, unformatted.\n         * @private\n         */\n\n    }, {\n        key: '_getUnformattedLeftAndRightPartAroundTheSelection',\n        value: function _getUnformattedLeftAndRightPartAroundTheSelection() {\n            var _getLeftAndRightPartA = this._getLeftAndRightPartAroundTheSelection(),\n                _getLeftAndRightPartA2 = _slicedToArray(_getLeftAndRightPartA, 2),\n                left = _getLeftAndRightPartA2[0],\n                right = _getLeftAndRightPartA2[1];\n\n            if (left === '' && right === '') {\n                return ['', ''];\n            }\n\n            // If changing the sign and `left` is equal to the number zero, prevent stripping the leading zero(s)\n            var stripZeros = true;\n            if ((this.eventKey === _AutoNumericEnum2.default.keyName.Hyphen || this.eventKey === _AutoNumericEnum2.default.keyName.Minus) && Number(left) === 0) {\n                stripZeros = false;\n            }\n\n            //TODO DRY that with `_normalizeParts()` -->\n            if (this.isTrailingNegative && (_AutoNumericHelper2.default.isNegative(right, this.settings.negativeSignCharacter) && // The caret is placed on the left of the negative sign\n            !_AutoNumericHelper2.default.isNegative(left, this.settings.negativeSignCharacter) || right === '' && // ..or the caret is placed on the far right of the input (Fix issue #481)\n            _AutoNumericHelper2.default.isNegative(left, this.settings.negativeSignCharacter, true))) {\n                left = left.replace(this.settings.negativeSignCharacter, '');\n                right = right.replace(this.settings.negativeSignCharacter, '');\n                // This is done here because `_getUnformattedLeftAndRightPartAroundTheSelection()` is called multiple times during the same key event, and at one point the left/right value has been normalized already..\n                left = left.replace('-', '');\n                right = right.replace('-', '');\n\n                // Then finally set back the normalized minus character at the right place\n                left = '-' + left;\n            }\n\n            left = AutoNumeric._stripAllNonNumberCharactersExceptCustomDecimalChar(left, this.settings, stripZeros, this.isFocused);\n            right = AutoNumeric._stripAllNonNumberCharactersExceptCustomDecimalChar(right, this.settings, false, this.isFocused);\n\n            return [left, right];\n        }\n\n        /**\n         * Strip parts from excess characters and leading zeros.\n         *\n         * @param {string} left\n         * @param {string} right\n         * @returns {[*,*,*]}\n         * @private\n         */\n\n    }, {\n        key: '_normalizeParts',\n        value: function _normalizeParts(left, right) {\n            //TODO Refactor with `_getUnformattedLeftAndRightPartAroundTheSelection` which share a lot of similar code\n            // If changing the sign and left is equal to the number zero - prevents stripping the leading zeros\n            var stripZeros = true;\n            if ((this.eventKey === _AutoNumericEnum2.default.keyName.Hyphen || this.eventKey === _AutoNumericEnum2.default.keyName.Minus) && Number(left) === 0) {\n                stripZeros = false;\n            }\n\n            if (this.isTrailingNegative && _AutoNumericHelper2.default.isNegative(right, this.settings.negativeSignCharacter) && !_AutoNumericHelper2.default.isNegative(left, this.settings.negativeSignCharacter)) {\n                // Only set the negative sign if the value is negative\n                left = '-' + left;\n                right = right.replace(this.settings.negativeSignCharacter, '');\n            }\n\n            left = AutoNumeric._stripAllNonNumberCharactersExceptCustomDecimalChar(left, this.settings, stripZeros, this.isFocused);\n            right = AutoNumeric._stripAllNonNumberCharactersExceptCustomDecimalChar(right, this.settings, false, this.isFocused);\n\n            // Prevents multiple leading zeros from being entered\n            if (this.settings.leadingZero === AutoNumeric.options.leadingZero.deny && (this.eventKey === _AutoNumericEnum2.default.keyName.num0 || this.eventKey === _AutoNumericEnum2.default.keyName.numpad0) && Number(left) === 0 &&\n            // If `right` is not empty and the first character is not `decimalCharacter`\n            !_AutoNumericHelper2.default.contains(left, this.settings.decimalCharacter) && right !== '') {\n                left = left.substring(0, left.length - 1);\n            }\n\n            // Insert zero there is a leading dot\n            var newValue = left + right;\n            if (this.settings.decimalCharacter) {\n                var m = newValue.match(new RegExp('^' + this.regex.aNegRegAutoStrip + '\\\\' + this.settings.decimalCharacter));\n                if (m) {\n                    left = left.replace(m[1], m[1] + '0');\n                    newValue = left + right;\n                }\n            }\n\n            return [left, right, newValue];\n        }\n\n        /**\n         * Set the formatted element value as well as the `rawValue`.\n         * This returns `true` if the element and raw value have been modified, `false` otherwise.\n         * This method also adjust the caret position according to the `leadingZero` option and the normalized value. //TODO What about the cursor *selection*?\n         *\n         * @param {string} left\n         * @param {string} right\n         * @param {boolean} isPaste\n         * @returns {boolean}\n         * @private\n         */\n\n    }, {\n        key: '_setValueParts',\n        value: function _setValueParts(left, right) {\n            var isPaste = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n\n            var _normalizeParts2 = this._normalizeParts(left, right),\n                _normalizeParts3 = _slicedToArray(_normalizeParts2, 3),\n                normalizedLeft = _normalizeParts3[0],\n                normalizedRight = _normalizeParts3[1],\n                normalizedNewValue = _normalizeParts3[2];\n\n            var _AutoNumeric$_checkIf = AutoNumeric._checkIfInRangeWithOverrideOption(normalizedNewValue, this.settings),\n                _AutoNumeric$_checkIf2 = _slicedToArray(_AutoNumeric$_checkIf, 2),\n                minTest = _AutoNumeric$_checkIf2[0],\n                maxTest = _AutoNumeric$_checkIf2[1];\n\n            if (minTest && maxTest) {\n                // First, set the raw value\n                var roundedRawValue = AutoNumeric._truncateDecimalPlaces(normalizedNewValue, this.settings, isPaste, this.settings.decimalPlacesRawValue);\n                var testValue = roundedRawValue.replace(this.settings.decimalCharacter, '.');\n\n                if (testValue === '' || testValue === this.settings.negativeSignCharacter) {\n                    var valueToSetOnEmpty = void 0;\n                    switch (this.settings.emptyInputBehavior) {\n                        case AutoNumeric.options.emptyInputBehavior.focus:\n                        case AutoNumeric.options.emptyInputBehavior.press:\n                        case AutoNumeric.options.emptyInputBehavior.always:\n                            valueToSetOnEmpty = '';\n                            break;\n                        case AutoNumeric.options.emptyInputBehavior.min:\n                            valueToSetOnEmpty = this.settings.minimumValue;\n                            break;\n                        case AutoNumeric.options.emptyInputBehavior.max:\n                            valueToSetOnEmpty = this.settings.maximumValue;\n                            break;\n                        case AutoNumeric.options.emptyInputBehavior.zero:\n                            valueToSetOnEmpty = '0';\n                            break;\n                        case AutoNumeric.options.emptyInputBehavior.null:\n                            valueToSetOnEmpty = null;\n                            break;\n                        // When `emptyInputBehavior` is a number or a string representing a number\n                        default:\n                            valueToSetOnEmpty = this.settings.emptyInputBehavior;\n                    }\n\n                    this._setRawValue(valueToSetOnEmpty);\n                } else {\n                    this._setRawValue(this._trimLeadingAndTrailingZeros(testValue));\n                }\n\n                // Then set the formatted value\n                var roundedValueToShow = AutoNumeric._truncateDecimalPlaces(normalizedNewValue, this.settings, isPaste, this.settings.decimalPlacesShownOnFocus);\n                var position = normalizedLeft.length;\n                if (position > roundedValueToShow.length) {\n                    position = roundedValueToShow.length;\n                }\n\n                // Make sure when the user enter a '0' on the far left with a leading zero option set to 'deny', that the caret does not moves since the input is dropped (fix issue #283)\n                if (position === 1 && normalizedLeft === '0' && this.settings.leadingZero === AutoNumeric.options.leadingZero.deny) {\n                    // If the user enter `0`, then the caret is put on the right side of it (Fix issue #299)\n                    if (normalizedRight === '' || normalizedLeft === '0' && normalizedRight !== '') {\n                        position = 1;\n                    } else {\n                        position = 0;\n                    }\n                }\n\n                this._setElementValue(roundedValueToShow, false);\n                this._setCaretPosition(position);\n\n                return true;\n            }\n\n            if (!minTest) {\n                this._triggerEvent(AutoNumeric.events.minRangeExceeded, this.domElement);\n            } else if (!maxTest) {\n                this._triggerEvent(AutoNumeric.events.maxRangeExceeded, this.domElement);\n            }\n\n            return false;\n        }\n\n        /**\n         * Helper function for `_expandSelectionOnSign()`.\n         *\n         * @returns {Array} Array containing [signPosition, currencySymbolPosition] of a formatted value\n         * @private\n         */\n\n    }, {\n        key: '_getSignPosition',\n        value: function _getSignPosition() {\n            var result = void 0;\n            if (this.settings.currencySymbol) {\n                var currencySymbolLen = this.settings.currencySymbol.length;\n                var value = _AutoNumericHelper2.default.getElementValue(this.domElement);\n                if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix) {\n                    var hasNeg = this.settings.negativeSignCharacter && value && value.charAt(0) === this.settings.negativeSignCharacter;\n                    if (hasNeg) {\n                        result = [1, currencySymbolLen + 1];\n                    } else {\n                        result = [0, currencySymbolLen];\n                    }\n                } else {\n                    var valueLen = value.length;\n                    result = [valueLen - currencySymbolLen, valueLen];\n                }\n            } else {\n                result = [1000, -1];\n            }\n\n            return result;\n        }\n\n        /**\n         * Expands selection to cover whole sign\n         * Prevents partial deletion/copying/overwriting of a sign\n         * @private\n         */\n\n    }, {\n        key: '_expandSelectionOnSign',\n        value: function _expandSelectionOnSign() {\n            var _getSignPosition2 = this._getSignPosition(),\n                _getSignPosition3 = _slicedToArray(_getSignPosition2, 2),\n                signPosition = _getSignPosition3[0],\n                currencySymbolPosition = _getSignPosition3[1];\n\n            var selection = this.selection;\n\n            // If selection catches something except sign and catches only space from sign\n            if (selection.start < currencySymbolPosition && selection.end > signPosition) {\n                // Then select without empty space\n                if ((selection.start < signPosition || selection.end > currencySymbolPosition) && _AutoNumericHelper2.default.getElementValue(this.domElement).substring(Math.max(selection.start, signPosition), Math.min(selection.end, currencySymbolPosition)).match(/^\\s*$/)) {\n                    if (selection.start < signPosition) {\n                        this._setSelection(selection.start, signPosition);\n                    } else {\n                        this._setSelection(currencySymbolPosition, selection.end);\n                    }\n                } else {\n                    // Else select with whole sign\n                    this._setSelection(Math.min(selection.start, signPosition), Math.max(selection.end, currencySymbolPosition));\n                }\n            }\n        }\n\n        /**\n         * Try to strip pasted value to digits\n         */\n\n    }, {\n        key: '_checkPaste',\n        value: function _checkPaste() {\n            // Do not process anything if the value has already been formatted\n            if (this.formatted) {\n                return;\n            }\n\n            if (!_AutoNumericHelper2.default.isUndefined(this.valuePartsBeforePaste)) {\n                var oldParts = this.valuePartsBeforePaste;\n\n                var _getLeftAndRightPartA3 = this._getLeftAndRightPartAroundTheSelection(),\n                    _getLeftAndRightPartA4 = _slicedToArray(_getLeftAndRightPartA3, 2),\n                    left = _getLeftAndRightPartA4[0],\n                    right = _getLeftAndRightPartA4[1];\n\n                // Try to strip the pasted value first\n\n\n                delete this.valuePartsBeforePaste;\n\n                var modifiedLeftPart = left.substr(0, oldParts[0].length) + AutoNumeric._stripAllNonNumberCharactersExceptCustomDecimalChar(left.substr(oldParts[0].length), this.settings, true, this.isFocused);\n                if (!this._setValueParts(modifiedLeftPart, right, true)) {\n                    this._setElementValue(oldParts.join(''), false);\n                    this._setCaretPosition(oldParts[0].length);\n                }\n            }\n        }\n\n        /**\n         * Return `true` if the given key should be ignored or not.\n         *\n         * @param {string} eventKeyName\n         * @returns {boolean}\n         * @private\n         */\n\n    }, {\n        key: '_processNonPrintableKeysAndShortcuts',\n\n\n        /**\n         * Process copying, cutting and pasting, as well as undo/redoing and cursor moving.\n         * Return `true` if further processing should not be performed.\n         *\n         * @param {KeyboardEvent} e\n         * @returns {boolean}\n         * @private\n         */\n        value: function _processNonPrintableKeysAndShortcuts(e) {\n            // Catch the ctrl up on ctrl-v\n            if ((e.ctrlKey || e.metaKey) && e.type === 'keyup' && !_AutoNumericHelper2.default.isUndefined(this.valuePartsBeforePaste) || e.shiftKey && this.eventKey === _AutoNumericEnum2.default.keyName.Insert) {\n                //TODO Move this test inside the `onKeyup` handler\n                this._checkPaste();\n\n                return false;\n            }\n\n            // Skip all function keys (F1-F12), Windows keys, tab and other special keys\n            if (this.constructor._shouldSkipEventKey(this.eventKey)) {\n                return true;\n            }\n\n            // If a \"Select all\" keyboard shortcut is detected (ctrl + a)\n            if ((e.ctrlKey || e.metaKey) && this.eventKey === _AutoNumericEnum2.default.keyName.a) {\n                if (this.settings.selectNumberOnly) {\n                    // `preventDefault()` is used here to prevent the browser to first select all the input text (including the currency sign), otherwise we would see that whole selection first in a flash, then the selection with only the number part without the currency sign.\n                    e.preventDefault();\n                    //TODO replace `selectNumber` by `select`?\n                    this.selectNumber();\n                }\n\n                return true;\n            }\n\n            // If a \"Copy\", \"Paste\" or \"Cut\" keyboard shortcut is detected (respectively 'ctrl + c', 'ctrl + v' or 'ctrl + x')\n            if ((e.ctrlKey || e.metaKey) && (this.eventKey === _AutoNumericEnum2.default.keyName.c || this.eventKey === _AutoNumericEnum2.default.keyName.v || this.eventKey === _AutoNumericEnum2.default.keyName.x)) {\n                if (e.type === 'keydown') {\n                    this._expandSelectionOnSign();\n                }\n\n                // Try to prevent wrong paste\n                if (this.eventKey === _AutoNumericEnum2.default.keyName.v || this.eventKey === _AutoNumericEnum2.default.keyName.Insert) {\n                    if (e.type === 'keydown' || e.type === 'keypress') {\n                        if (_AutoNumericHelper2.default.isUndefined(this.valuePartsBeforePaste)) {\n                            this.valuePartsBeforePaste = this._getLeftAndRightPartAroundTheSelection();\n                        }\n                    } else {\n                        this._checkPaste();\n                    }\n                }\n\n                return e.type === 'keydown' || e.type === 'keypress' || this.eventKey === _AutoNumericEnum2.default.keyName.c;\n            }\n\n            // The undo shortcut\n            if (e.ctrlKey || e.metaKey) {\n                return !(this.eventKey === _AutoNumericEnum2.default.keyName.Z || this.eventKey === _AutoNumericEnum2.default.keyName.z);\n            }\n\n            // Jump over the thousand separator\n            //TODO Move this test inside the `onKeydown` handler\n            if (this.eventKey === _AutoNumericEnum2.default.keyName.LeftArrow || this.eventKey === _AutoNumericEnum2.default.keyName.RightArrow) {\n                if (e.type === 'keydown' && !e.shiftKey) {\n                    var value = _AutoNumericHelper2.default.getElementValue(this.domElement);\n                    if (this.eventKey === _AutoNumericEnum2.default.keyName.LeftArrow && (value.charAt(this.selection.start - 2) === this.settings.digitGroupSeparator || value.charAt(this.selection.start - 2) === this.settings.decimalCharacter)) {\n                        this._setCaretPosition(this.selection.start - 1);\n                    } else if (this.eventKey === _AutoNumericEnum2.default.keyName.RightArrow && (value.charAt(this.selection.start + 1) === this.settings.digitGroupSeparator || value.charAt(this.selection.start + 1) === this.settings.decimalCharacter)) {\n                        this._setCaretPosition(this.selection.start + 1);\n                    }\n                }\n\n                return true;\n            }\n\n            return _AutoNumericHelper2.default.isInArray(this.eventKey, _AutoNumericEnum2.default.keyName._directionKeys);\n        }\n\n        /**\n         * Process deletion of characters when the minus sign is to the right of the numeric characters.\n         *\n         * @param {string} left The part on the left of the caret or selection\n         * @param {string} right The part on the right of the caret or selection\n         * @returns {[string, string]}\n         * @private\n         */\n\n    }, {\n        key: '_processCharacterDeletionIfTrailingNegativeSign',\n        value: function _processCharacterDeletionIfTrailingNegativeSign(_ref3) {\n            var _ref4 = _slicedToArray(_ref3, 2),\n                left = _ref4[0],\n                right = _ref4[1];\n\n            var value = _AutoNumericHelper2.default.getElementValue(this.domElement);\n            var isValNegative = _AutoNumericHelper2.default.isNegative(value, this.settings.negativeSignCharacter);\n\n            if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix && this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.suffix) {\n                if (this.eventKey === _AutoNumericEnum2.default.keyName.Backspace) {\n                    this.caretFix = this.selection.start >= value.indexOf(this.settings.suffixText) && this.settings.suffixText !== '';\n                    if (value.charAt(this.selection.start - 1) === '-') {\n                        left = left.substring(1);\n                    } else if (this.selection.start <= value.length - this.settings.suffixText.length) {\n                        left = left.substring(0, left.length - 1);\n                    }\n                } else {\n                    this.caretFix = this.selection.start >= value.indexOf(this.settings.suffixText) && this.settings.suffixText !== '';\n                    if (this.selection.start >= value.indexOf(this.settings.currencySymbol) + this.settings.currencySymbol.length) {\n                        right = right.substring(1, right.length);\n                    }\n                    if (_AutoNumericHelper2.default.isNegative(left, this.settings.negativeSignCharacter) && value.charAt(this.selection.start) === '-') {\n                        left = left.substring(1);\n                    }\n                }\n            }\n\n            if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) {\n                switch (this.settings.negativePositiveSignPlacement) {\n                    case AutoNumeric.options.negativePositiveSignPlacement.left:\n                        this.caretFix = this.selection.start >= value.indexOf(this.settings.negativeSignCharacter) + this.settings.negativeSignCharacter.length;\n                        if (this.eventKey === _AutoNumericEnum2.default.keyName.Backspace) {\n                            if (this.selection.start === value.indexOf(this.settings.negativeSignCharacter) + this.settings.negativeSignCharacter.length && isValNegative) {\n                                left = left.substring(1);\n                            } else if (left !== '-' && (this.selection.start <= value.indexOf(this.settings.negativeSignCharacter) || !isValNegative)) {\n                                left = left.substring(0, left.length - 1);\n                            }\n                        } else {\n                            if (left[0] === '-') {\n                                right = right.substring(1);\n                            }\n                            if (this.selection.start === value.indexOf(this.settings.negativeSignCharacter) && isValNegative) {\n                                left = left.substring(1);\n                            }\n                        }\n                        break;\n                    case AutoNumeric.options.negativePositiveSignPlacement.right:\n                        this.caretFix = this.selection.start >= value.indexOf(this.settings.negativeSignCharacter) + this.settings.negativeSignCharacter.length;\n                        if (this.eventKey === _AutoNumericEnum2.default.keyName.Backspace) {\n                            if (this.selection.start === value.indexOf(this.settings.negativeSignCharacter) + this.settings.negativeSignCharacter.length) {\n                                left = left.substring(1);\n                            } else if (left !== '-' && this.selection.start <= value.indexOf(this.settings.negativeSignCharacter) - this.settings.currencySymbol.length) {\n                                left = left.substring(0, left.length - 1);\n                            } else if (left !== '' && !isValNegative) {\n                                left = left.substring(0, left.length - 1);\n                            }\n                        } else {\n                            this.caretFix = this.selection.start >= value.indexOf(this.settings.currencySymbol) && this.settings.currencySymbol !== '';\n                            if (this.selection.start === value.indexOf(this.settings.negativeSignCharacter)) {\n                                left = left.substring(1);\n                            }\n\n                            right = right.substring(1);\n                        }\n                        break;\n                }\n            }\n\n            return [left, right];\n        }\n\n        /**\n         * Process the deletion of characters.\n         */\n\n    }, {\n        key: '_processCharacterDeletion',\n        value: function _processCharacterDeletion() {\n            var left = void 0;\n            var right = void 0;\n\n            if (!this.selection.length) {\n                var _getUnformattedLeftAn = this._getUnformattedLeftAndRightPartAroundTheSelection();\n\n                var _getUnformattedLeftAn2 = _slicedToArray(_getUnformattedLeftAn, 2);\n\n                left = _getUnformattedLeftAn2[0];\n                right = _getUnformattedLeftAn2[1];\n\n                if (left === '' && right === '') {\n                    this.throwInput = false;\n                }\n\n                if (this.isTrailingNegative && _AutoNumericHelper2.default.isNegative(_AutoNumericHelper2.default.getElementValue(this.domElement), this.settings.negativeSignCharacter)) {\n                    var _processCharacterDele = this._processCharacterDeletionIfTrailingNegativeSign([left, right]);\n\n                    var _processCharacterDele2 = _slicedToArray(_processCharacterDele, 2);\n\n                    left = _processCharacterDele2[0];\n                    right = _processCharacterDele2[1];\n                } else {\n                    if (this.eventKey === _AutoNumericEnum2.default.keyName.Backspace) {\n                        left = left.substring(0, left.length - 1);\n                    } else {\n                        right = right.substring(1, right.length);\n                    }\n                }\n            } else {\n                this._expandSelectionOnSign();\n\n                var _getUnformattedLeftAn3 = this._getUnformattedLeftAndRightPartAroundTheSelection();\n\n                var _getUnformattedLeftAn4 = _slicedToArray(_getUnformattedLeftAn3, 2);\n\n                left = _getUnformattedLeftAn4[0];\n                right = _getUnformattedLeftAn4[1];\n            }\n\n            this._setValueParts(left, right);\n        }\n\n        /**\n         * Return `true` if a decimal character is allowed to be typed.\n         * If the number of decimal places shown on focus is zero, then the decimal character is not allowed.\n         *\n         * @returns {boolean}\n         * @private\n         */\n\n    }, {\n        key: '_isDecimalCharacterInsertionAllowed',\n        value: function _isDecimalCharacterInsertionAllowed() {\n            return String(this.settings.decimalPlacesShownOnFocus) !== String(AutoNumeric.options.decimalPlacesShownOnFocus.none) && String(this.settings.decimalPlaces) !== String(AutoNumeric.options.decimalPlaces.none);\n        }\n\n        /**\n         * Return `true` if the key is allowed.\n         * This function decides if the key pressed should be dropped or accepted, and modify the value 'on-the-fly' accordingly.\n         * //TODO This should use another function in order to separate the test and the modification\n         *\n         * @returns {boolean}\n         */\n\n    }, {\n        key: '_processCharacterInsertion',\n        value: function _processCharacterInsertion() {\n            var _getUnformattedLeftAn5 = this._getUnformattedLeftAndRightPartAroundTheSelection(),\n                _getUnformattedLeftAn6 = _slicedToArray(_getUnformattedLeftAn5, 2),\n                left = _getUnformattedLeftAn6[0],\n                right = _getUnformattedLeftAn6[1];\n\n            if (this.eventKey !== _AutoNumericEnum2.default.keyName.AndroidDefault) {\n                this.throwInput = true;\n            }\n\n            // Start rules when the decimal character key is pressed always use numeric pad dot to insert decimal separator\n            // Do not allow decimal character if no decimal part allowed\n            if (this.eventKey === this.settings.decimalCharacter || this.settings.decimalCharacterAlternative && this.eventKey === this.settings.decimalCharacterAlternative) {\n                if (!this._isDecimalCharacterInsertionAllowed() || !this.settings.decimalCharacter) {\n                    return false;\n                }\n\n                if (this.settings.alwaysAllowDecimalCharacter) {\n                    // Remove any previous decimal character\n                    left = left.replace(this.settings.decimalCharacter, '');\n                    right = right.replace(this.settings.decimalCharacter, '');\n                } else {\n                    // Do not allow a decimal character if another decimal character is already present\n                    if (_AutoNumericHelper2.default.contains(left, this.settings.decimalCharacter)) {\n                        return true;\n                    }\n\n                    // Prevent adding a decimal character at the far right of the number\n                    if (right.indexOf(this.settings.decimalCharacter) > 0) {\n                        return true;\n                    }\n\n                    // Remove the decimal character is found on the far left of the right part\n                    if (right.indexOf(this.settings.decimalCharacter) === 0) {\n                        right = right.substr(1);\n                    }\n                }\n\n                // If the user is trying to add a decimal character on the far left of the number, we allow it\n                if (this.settings.negativeSignCharacter && _AutoNumericHelper2.default.contains(right, this.settings.negativeSignCharacter)) {\n                    // We need however to move the negative sign from the right to the left part\n                    left = '' + this.settings.negativeSignCharacter + left;\n                    right = right.replace(this.settings.negativeSignCharacter, '');\n                }\n\n                this._setValueParts(left + this.settings.decimalCharacter, right);\n\n                return true;\n            }\n\n            // Prevent entering the minus sign if it's not allowed (Note: `this.settings.isNegativeSignAllowed` is only set to `true` if the minimumValue is lower than zero, allowing negative numbers to be entered)\n            if ((this.eventKey === '-' || this.eventKey === '+') && this.settings.isNegativeSignAllowed) {\n                // Here, the left and right parts have been normalized already, hence the minus sign usage\n                if (left === '' && _AutoNumericHelper2.default.contains(right, '-')) {\n                    // The value is originally negative (with a trailing negative sign)\n                    right = right.replace('-', '');\n                } else if (_AutoNumericHelper2.default.isNegativeStrict(left, '-')) {\n                    // The value is originally negative (with a leading negative sign)\n                    // Remove the negative sign, effectively converting the value to a positive one\n                    left = left.replace('-', ''); //TODO replace with '+' if `showPositiveSign` too?\n                } else {\n                    // The value is originally positive, so we toggle the state to a negative one (unformatted, which means even with a trailing negative sign, we add the minus sign on the far left)\n                    left = '' + this.settings.negativeSignCharacter + left;\n                }\n\n                this._setValueParts(left, right);\n\n                return true;\n            }\n\n            var eventNumber = Number(this.eventKey);\n            if (eventNumber >= 0 && eventNumber <= 9) {\n                // If the user tries to insert a digit\n                if (this.settings.isNegativeSignAllowed && left === '' && _AutoNumericHelper2.default.contains(right, '-')) {\n                    // ...and that digit is before the minus sign\n                    left = '-';\n                    right = right.substring(1, right.length);\n                }\n\n                if (this.settings.maximumValue <= 0 && this.settings.minimumValue < this.settings.maximumValue && !_AutoNumericHelper2.default.contains(_AutoNumericHelper2.default.getElementValue(this.domElement), this.settings.negativeSignCharacter) && this.eventKey !== '0') {\n                    left = '-' + left;\n                }\n\n                this._setValueParts('' + left + this.eventKey, right);\n\n                return true;\n            }\n\n            // Prevent any other characters\n            this.throwInput = false;\n\n            return false;\n        }\n\n        /**\n         * Formatting of just processed value while keeping the cursor position\n         *\n         * @param {Event} e\n         * @private\n         */\n\n    }, {\n        key: '_formatValue',\n        value: function _formatValue(e) {\n            //TODO Break apart and simplify this really long function\n            var elementValue = _AutoNumericHelper2.default.getElementValue(this.domElement);\n\n            var _getUnformattedLeftAn7 = this._getUnformattedLeftAndRightPartAroundTheSelection(),\n                _getUnformattedLeftAn8 = _slicedToArray(_getUnformattedLeftAn7, 1),\n                left = _getUnformattedLeftAn8[0];\n\n            // No grouping separator and no currency sign\n\n\n            if ((this.settings.digitGroupSeparator === '' || this.settings.digitGroupSeparator !== '' && !_AutoNumericHelper2.default.contains(elementValue, this.settings.digitGroupSeparator)) && (this.settings.currencySymbol === '' || this.settings.currencySymbol !== '' && !_AutoNumericHelper2.default.contains(elementValue, this.settings.currencySymbol))) {\n                var _elementValue$split = elementValue.split(this.settings.decimalCharacter),\n                    _elementValue$split2 = _slicedToArray(_elementValue$split, 1),\n                    subParts = _elementValue$split2[0];\n\n                var negativeSign = '';\n                if (_AutoNumericHelper2.default.isNegative(subParts, this.settings.negativeSignCharacter)) {\n                    negativeSign = this.settings.negativeSignCharacter;\n                    subParts = subParts.replace(this.settings.negativeSignCharacter, '');\n                    left = left.replace('-', ''); // Here we modify the unformatted value (with the 'normal' minus sign)\n                }\n\n                // Strip leading zero on positive value if needed\n                if (negativeSign === '' && subParts.length > this.settings.mIntPos && left.charAt(0) === '0') {\n                    left = left.slice(1);\n                }\n\n                // Strip leading zero on negative value if needed\n                if (negativeSign === this.settings.negativeSignCharacter && subParts.length > this.settings.mIntNeg && left.charAt(0) === '0') {\n                    left = left.slice(1);\n                }\n\n                if (!this.isTrailingNegative) {\n                    // Only add the minus sign if it's needed on that side of the numbers\n                    left = '' + negativeSign + left;\n                }\n            }\n\n            var value = this.constructor._addGroupSeparators(elementValue, this.settings, this.isFocused, this.rawValue);\n            var position = value.length;\n            if (value) {\n                // Prepare regexp which searches for cursor position from unformatted left part\n                var leftAr = left.split('');\n\n                // Fixes caret position with trailing minus sign\n                if ((this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.suffix || this.settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.prefix && this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) && leftAr[0] === this.settings.negativeSignCharacter && !this.settings.isNegativeSignAllowed) {\n                    leftAr.shift(); // Remove the negative sign character\n\n                    if ((this.eventKey === _AutoNumericEnum2.default.keyName.Backspace || this.eventKey === _AutoNumericEnum2.default.keyName.Delete) && this.caretFix) {\n                        if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix && this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.left || this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix && this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.suffix) {\n                            leftAr.push(this.settings.negativeSignCharacter);\n                            this.caretFix = e.type === 'keydown';\n                        }\n\n                        if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix && this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.right) {\n                            var signParts = this.settings.currencySymbol.split('');\n                            var escapeChr = ['\\\\', '^', '$', '.', '|', '?', '*', '+', '(', ')', '['];\n                            var escapedParts = [];\n                            signParts.forEach(function (i, miniParts) {\n                                miniParts = signParts[i];\n                                if (_AutoNumericHelper2.default.isInArray(miniParts, escapeChr)) {\n                                    escapedParts.push('\\\\' + miniParts);\n                                } else {\n                                    escapedParts.push(miniParts);\n                                }\n                            });\n\n                            if (this.eventKey === _AutoNumericEnum2.default.keyName.Backspace && this.settings.negativeSignCharacter === '-') {\n                                escapedParts.push('-');\n                            }\n\n                            // Pushing the escaped sign\n                            leftAr.push(escapedParts.join(''));\n                            this.caretFix = e.type === 'keydown';\n                        }\n                    }\n                }\n\n                for (var i = 0; i < leftAr.length; i++) {\n                    if (!leftAr[i].match('\\\\d')) {\n                        leftAr[i] = '\\\\' + leftAr[i];\n                    }\n                }\n\n                var leftReg = new RegExp('^.*?' + leftAr.join('.*?'));\n\n                // Search cursor position in formatted value\n                var newLeft = value.match(leftReg);\n                if (newLeft) {\n                    position = newLeft[0].length;\n\n                    // If the positive sign is shown, calculate the caret position accordingly\n                    if (this.settings.showPositiveSign) {\n                        if (position === 0 && newLeft.input.charAt(0) === this.settings.positiveSignCharacter) {\n                            position = newLeft.input.indexOf(this.settings.currencySymbol) === 1 ? this.settings.currencySymbol.length + 1 : 1;\n                        }\n\n                        if (position === 0 && newLeft.input.charAt(this.settings.currencySymbol.length) === this.settings.positiveSignCharacter) {\n                            position = this.settings.currencySymbol.length + 1;\n                        }\n                    }\n\n                    // If we are just before the sign which is in prefix position\n                    if ((position === 0 && value.charAt(0) !== this.settings.negativeSignCharacter || position === 1 && value.charAt(0) === this.settings.negativeSignCharacter) && this.settings.currencySymbol && this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix) {\n                        // Place caret after prefix sign\n                        //TODO Should the test be 'isNegative' instead of 'isNegativeStrict' in order to search for '-' everywhere in the string?\n                        position = this.settings.currencySymbol.length + (_AutoNumericHelper2.default.isNegativeStrict(value, this.settings.negativeSignCharacter) ? 1 : 0);\n                    }\n                } else {\n                    if (this.settings.currencySymbol && this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) {\n                        // If we could not find a place for cursor and have a sign as a suffix\n                        // Place caret before suffix currency sign\n                        position -= this.settings.currencySymbol.length;\n                    }\n\n                    if (this.settings.suffixText) {\n                        // If we could not find a place for cursor and have a suffix\n                        // Place caret before suffix\n                        position -= this.settings.suffixText.length;\n                    }\n                }\n            }\n\n            // Only update the value if it has changed. This prevents modifying the selection, if any.\n            if (value !== elementValue) {\n                this._setElementValue(value, false);\n                this._setCaretPosition(position);\n            }\n\n            this.formatted = true; //TODO Rename `this.formatted` to `this._formatExecuted`, since it's possible this function does not need to format anything (in the case where the keycode is dropped for instance)\n        }\n\n        /**\n         * Serialize the form child <input> element values to a string, or an Array.\n         * The output format is defined with the `formatType` argument.\n         * This is loosely based upon http://stackoverflow.com/a/40705993/2834898.\n         *\n         * @param {HTMLFormElement} form\n         * @param {boolean} intoAnArray If `true`, instead of generating a string, it generates an Array.\n         * @param {string} formatType If `'unformatted'`, then the AutoNumeric elements values are unformatted, if `'localized'`, then the AutoNumeric elements values are localized, and if `'formatted'`, then the AutoNumeric elements values are kept formatted. In either way, this function does not modify the value of each DOM element, but only affect the value that is returned by that serialize function.\n         * @param {string} serializedSpaceCharacter Can either be the '+' character, or the '%20' string.\n         * @param {string|null} forcedOutputFormat If set, then this is the format that is used for the localization, instead of the default `outputFormat` option.\n         * @returns {string|Array}\n         * @private\n         */\n\n    }], [{\n        key: 'version',\n        value: function version() {\n            return '4.4.0';\n        }\n\n        /**\n         * Take the parameters given to the AutoNumeric object, and output the three variables that are needed to finish initializing it :\n         * - domElement : The target DOM element\n         * - initialValue : The initial value, or `null` if none is given\n         * - userOptions : The option object\n         *\n         * @param {object|Array|number|string} arg1\n         * @param {object|Array|number|string|null} arg2\n         * @param {object|Array|number|string|null} arg3\n         * @returns {{domElement: *, initialValue: *, userOptions: *}}\n         * @throws\n         * @private\n         */\n\n    }, {\n        key: '_setArgumentsValues',\n        value: function _setArgumentsValues(arg1, arg2, arg3) {\n            // Basic check on the argument count\n            if (_AutoNumericHelper2.default.isNull(arg1)) {\n                _AutoNumericHelper2.default.throwError('At least one valid parameter is needed in order to initialize an AutoNumeric object');\n            }\n\n            // Prepare the arguments in order to create the AutoNumeric object with the right values\n            // Test the argument types\n            var isArg1Element = _AutoNumericHelper2.default.isElement(arg1);\n            var isArg1String = _AutoNumericHelper2.default.isString(arg1);\n\n            var isArg2Object = _AutoNumericHelper2.default.isObject(arg2);\n            var isArg2Array = Array.isArray(arg2) && arg2.length > 0;\n            var isArg2Number = _AutoNumericHelper2.default.isNumberOrArabic(arg2) || arg2 === '';\n            var isArg2PreDefinedOptionName = this._isPreDefinedOptionValid(arg2);\n            var isArg2Null = _AutoNumericHelper2.default.isNull(arg2);\n            var isArg2EmptyString = _AutoNumericHelper2.default.isEmptyString(arg2);\n\n            var isArg3Object = _AutoNumericHelper2.default.isObject(arg3);\n            var isArg3Array = Array.isArray(arg3) && arg3.length > 0;\n            var isArg3Null = _AutoNumericHelper2.default.isNull(arg3);\n            var isArg3PreDefinedOptionName = this._isPreDefinedOptionValid(arg3);\n\n            // Given the parameters passed, sort the data and return a stable state before the initialization\n            var domElement = void 0;\n            var userOptions = void 0;\n            var initialValue = void 0;\n\n            //TODO Simplify those tests -->\n            if (isArg1Element && isArg2Null && isArg3Null) {\n                // new AutoNumeric(domElement); // With the default options\n                domElement = arg1;\n                initialValue = null;\n                userOptions = null;\n            } else if (isArg1Element && isArg2Number && isArg3Null) {\n                // new AutoNumeric(domElement, 12345.789); // With the default options, and an initial value\n                // new AutoNumeric(domElement, '12345.789');\n                domElement = arg1;\n                initialValue = arg2;\n                userOptions = null;\n            } else if (isArg1Element && isArg2Object && isArg3Null) {\n                // new AutoNumeric(domElement, { options }); // With one option object\n                domElement = arg1;\n                initialValue = null;\n                userOptions = arg2;\n            } else if (isArg1Element && isArg2PreDefinedOptionName && isArg3Null) {\n                // new AutoNumeric(domElement, 'euroPos'); // With one pre-defined option name\n                domElement = arg1;\n                initialValue = null;\n                userOptions = this._getOptionObject(arg2);\n            } else if (isArg1Element && isArg2Array && isArg3Null) {\n                // new AutoNumeric(domElement, [{ options1 }, { options2 }]); // With multiple option objects (the latest option overwriting the previous ones)\n                domElement = arg1;\n                initialValue = null;\n                userOptions = this.mergeOptions(arg2);\n            } else if (isArg1Element && (isArg2Null || isArg2EmptyString) && isArg3Object) {\n                // new AutoNumeric(domElement, null, { options }); // With one option object\n                domElement = arg1;\n                initialValue = null;\n                userOptions = arg3;\n            } else if (isArg1Element && (isArg2Null || isArg2EmptyString) && isArg3Array) {\n                // new AutoNumeric(domElement, null, [{ options1 }, { options2 }]); // With multiple option objects\n                domElement = arg1;\n                initialValue = null;\n                userOptions = this.mergeOptions(arg3);\n            } else if (isArg1String && isArg2Null && isArg3Null) {\n                // new AutoNumeric('.myCssClass > input');\n                domElement = document.querySelector(arg1);\n                initialValue = null;\n                userOptions = null;\n            } else if (isArg1String && isArg2Object && isArg3Null) {\n                // new AutoNumeric('.myCssClass > input', { options });\n                domElement = document.querySelector(arg1);\n                initialValue = null;\n                userOptions = arg2;\n            } else if (isArg1String && isArg2PreDefinedOptionName && isArg3Null) {\n                // new AutoNumeric('.myCssClass > input', 'euroPos');\n                domElement = document.querySelector(arg1);\n                initialValue = null;\n                userOptions = this._getOptionObject(arg2);\n            } else if (isArg1String && isArg2Array && isArg3Null) {\n                // new AutoNumeric('.myCssClass > input', [{ options1 }, { options2 }]); // With multiple option objects\n                domElement = document.querySelector(arg1);\n                initialValue = null;\n                userOptions = this.mergeOptions(arg2);\n            } else if (isArg1String && (isArg2Null || isArg2EmptyString) && isArg3Object) {\n                // new AutoNumeric('.myCssClass > input', null, { options });\n                domElement = document.querySelector(arg1);\n                initialValue = null;\n                userOptions = arg3;\n            } else if (isArg1String && (isArg2Null || isArg2EmptyString) && isArg3Array) {\n                // new AutoNumeric('.myCssClass > input', null, [{ options1 }, { options2 }]); // With multiple option objects\n                domElement = document.querySelector(arg1);\n                initialValue = null;\n                userOptions = this.mergeOptions(arg3);\n            } else if (isArg1String && isArg2Number && isArg3Null) {\n                // new AutoNumeric('.myCssClass > input', 12345.789);\n                // new AutoNumeric('.myCssClass > input', '12345.789');\n                // new AutoNumeric('.myCssClass > input', '');\n                domElement = document.querySelector(arg1);\n                initialValue = arg2;\n                userOptions = null;\n            } else if (isArg1String && isArg2Number && isArg3Object) {\n                // new AutoNumeric('.myCssClass > input', 12345.789, { options });\n                // new AutoNumeric('.myCssClass > input', '12345.789', { options });\n                // new AutoNumeric('.myCssClass > input', '', { options });\n                domElement = document.querySelector(arg1);\n                initialValue = arg2;\n                userOptions = arg3;\n            } else if (isArg1String && isArg2Number && isArg3PreDefinedOptionName) {\n                // new AutoNumeric('.myCssClass > input', 12345.789, 'euroPos');\n                // new AutoNumeric('.myCssClass > input', '12345.789', 'euroPos');\n                // new AutoNumeric('.myCssClass > input', '', 'euroPos');\n                domElement = document.querySelector(arg1);\n                initialValue = arg2;\n                userOptions = this._getOptionObject(arg3);\n            } else if (isArg1String && isArg2Number && isArg3Array) {\n                // new AutoNumeric('.myCssClass > input', 12345.789, [{ options1 }, 'euroPos', { options2 }]);\n                // new AutoNumeric('.myCssClass > input', '12345.789', [{ options1 }, 'euroPos', { options2 }]);\n                // new AutoNumeric('.myCssClass > input', '', [{ options1 }, 'euroPos', { options2 }]);\n                domElement = document.querySelector(arg1);\n                initialValue = arg2;\n                userOptions = this.mergeOptions(arg3);\n            } else if (isArg1Element && isArg2Number && isArg3Object) {\n                // new AutoNumeric(domElement, 12345.789, { options });\n                // new AutoNumeric(domElement, '12345.789', { options });\n                // new AutoNumeric(domElement, '', { options });\n                domElement = arg1;\n                initialValue = arg2;\n                userOptions = arg3;\n            } else if (isArg1Element && isArg2Number && isArg3PreDefinedOptionName) {\n                // new AutoNumeric(domElement, 12345.789, 'euroPos');\n                // new AutoNumeric(domElement, '12345.789', 'euroPos');\n                // new AutoNumeric(domElement, '', 'euroPos');\n                domElement = arg1;\n                initialValue = arg2;\n                userOptions = this._getOptionObject(arg3);\n            } else if (isArg1Element && isArg2Number && isArg3Array) {\n                // new AutoNumeric(domElement, 12345.789, [{ options1 }, { options2 }]);\n                // new AutoNumeric(domElement, '12345.789', [{ options1 }, { options2 }]);\n                // new AutoNumeric(domElement, '', [{ options1 }, { options2 }]);\n                domElement = arg1;\n                initialValue = arg2;\n                userOptions = this.mergeOptions(arg3);\n            } else {\n                _AutoNumericHelper2.default.throwError('The parameters given to the AutoNumeric object are not valid, \\'' + arg1 + '\\', \\'' + arg2 + '\\' and \\'' + arg3 + '\\' given.');\n            }\n\n            if (_AutoNumericHelper2.default.isNull(domElement)) {\n                _AutoNumericHelper2.default.throwError('The selector \\'' + arg1 + '\\' did not select any valid DOM element. Please check on which element you called AutoNumeric.');\n            }\n\n            return { domElement: domElement, initialValue: initialValue, userOptions: userOptions };\n        }\n\n        /**\n         * Merge the option objects found in the given array `optionsArray`.\n         * If a `string` is found, then we try to get the related pre-defined option using that string as its name.\n         * When merging the options, the latest option overwrite any previously set. This allows to fine tune a pre-defined option for instance.\n         *\n         * @param {Array<object|string>} optionsArray\n         * @returns {{}}\n         */\n\n    }, {\n        key: 'mergeOptions',\n        value: function mergeOptions(optionsArray) {\n            var _this12 = this;\n\n            // This allows the user to use multiple options (strings or objects) in an array, and overwrite the previous one with the next option element ; this is useful to tune the wanted format\n            var mergedOptions = {};\n            optionsArray.forEach(function (optionObjectOrPredefinedOptionString) {\n                _extends(mergedOptions, _this12._getOptionObject(optionObjectOrPredefinedOptionString));\n            });\n\n            return mergedOptions;\n        }\n\n        /**\n         * Return `true` if the given pre-defined option name is an attribute of the `AutoNumeric.predefinedOptions` object\n         *\n         * @param {string} preDefinedOptionName\n         * @returns {boolean}\n         * @private\n         */\n\n    }, {\n        key: '_isPreDefinedOptionValid',\n        value: function _isPreDefinedOptionValid(preDefinedOptionName) {\n            return AutoNumeric.predefinedOptions.hasOwnProperty(preDefinedOptionName);\n        }\n\n        /**\n         * Return an option object based on the given parameter.\n         * If `optionObjectOrPredefinedName` is as string, then we retrieve the pre-defined option object, if it's an object, we use it as is.\n         *\n         * @param {object|string} optionObjectOrPredefinedName\n         * @returns {object}\n         */\n\n    }, {\n        key: '_getOptionObject',\n        value: function _getOptionObject(optionObjectOrPredefinedName) {\n            var options = void 0;\n            if (_AutoNumericHelper2.default.isString(optionObjectOrPredefinedName)) {\n                options = AutoNumeric.getPredefinedOptions()[optionObjectOrPredefinedName];\n                if (options === void 0 || options === null) {\n                    // If the given pre-defined name does not exist, warn that something is wrong, and continue the execution of the initialization\n                    _AutoNumericHelper2.default.warning('The given pre-defined option [' + optionObjectOrPredefinedName + '] is not recognized by autoNumeric. Please check that pre-defined option name.', true);\n                }\n            } else {\n                // A `settings` object\n                options = optionObjectOrPredefinedName;\n            }\n\n            return options;\n        }\n    }, {\n        key: '_doesFormHandlerListExists',\n        value: function _doesFormHandlerListExists() {\n            var type = _typeof(window.aNFormHandlerMap);\n\n            return type !== 'undefined' && type === 'object';\n        }\n\n        /**\n         * Create the global form handler list on the `window` object.\n         *\n         * @private\n         */\n\n    }, {\n        key: '_createFormHandlerList',\n        value: function _createFormHandlerList() {\n            window.aNFormHandlerMap = new Map(); // I would have used a `WeakMap` here, but that does not allow using non-object for keys\n        }\n    }, {\n        key: '_checkValuesToStringsArray',\n        value: function _checkValuesToStringsArray(key, stringsArray) {\n            return _AutoNumericHelper2.default.isInArray(String(key), stringsArray);\n        }\n\n        /**\n         * Static helper for checking if the given `key` is found in the settings' `valuesToStrings` option object.\n         *\n         * @param {number|string} key\n         * @param {object} settings\n         * @returns {boolean}\n         * @private\n         */\n\n    }, {\n        key: '_checkValuesToStringsSettings',\n        value: function _checkValuesToStringsSettings(key, settings) {\n            return this._checkValuesToStringsArray(key, Object.keys(settings.valuesToStrings));\n        }\n\n        /**\n         * Static helper for checking if the given `value` is found in the settings' `valuesToStrings` option object.\n         *\n         * @param {number|string} value\n         * @param {object} settings\n         * @returns {boolean}\n         * @private\n         */\n\n    }, {\n        key: '_checkStringsToValuesSettings',\n        value: function _checkStringsToValuesSettings(value, settings) {\n            return this._checkValuesToStringsArray(value, Object.values(settings.valuesToStrings));\n        }\n    }, {\n        key: '_unformatAltHovered',\n        value: function _unformatAltHovered(anElement) {\n            anElement.hoveredWithAlt = true;\n            anElement.unformat();\n        }\n\n        /**\n         * Reformat the given AutoNumeric element, and update the `hoveredWithAlt` variable.\n         *\n         * @param {AutoNumeric} anElement\n         * @private\n         */\n\n    }, {\n        key: '_reformatAltHovered',\n        value: function _reformatAltHovered(anElement) {\n            anElement.hoveredWithAlt = false;\n            anElement.reformat();\n        }\n\n        /**\n         * Return an array of autoNumeric elements, child of the <form> element passed as a parameter.\n         *\n         * @param {HTMLElement} formNode\n         * @returns {Array}\n         * @private\n         */\n\n    }, {\n        key: '_getChildANInputElement',\n        value: function _getChildANInputElement(formNode) {\n            var _this13 = this;\n\n            //FIXME test this\n            var inputList = formNode.getElementsByTagName('input');\n\n            // Loop this list and keep only the inputs that are managed by AutoNumeric\n            var autoNumericInputs = [];\n            var inputElements = Array.prototype.slice.call(inputList, 0);\n            inputElements.forEach(function (input) {\n                if (_this13.test(input)) {\n                    autoNumericInputs.push(input);\n                }\n            });\n\n            return autoNumericInputs;\n        }\n\n        // Static methods\n        /**\n         * Test if the given DOM element, or the element selected by the given selector string is already managed by AutoNumeric (if it has been initialized on the current page).\n         *\n         * @param {HTMLElement|string} domElementOrSelector Accepts either directly a DOM element to test, or a string selector (that will return one and only one element, if any)\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'test',\n        value: function test(domElementOrSelector) {\n            return this._isInGlobalList(_AutoNumericHelper2.default.domElement(domElementOrSelector));\n        }\n\n        /**\n         * Create a WeakMap with the given name.\n         *\n         * @param {string} weakMapName\n         * @private\n         */\n\n    }, {\n        key: '_createWeakMap',\n        value: function _createWeakMap(weakMapName) {\n            window[weakMapName] = new WeakMap();\n        }\n\n        /**\n         * Create a list of all the AutoNumeric elements that are initialized on the current page.\n         * This is needed in order to determine if a given dom element is already managed by autoNumeric.\n         * This uses a WeakMap in order to limit potential garbage collection problems.\n         * (cf. my tests on http://codepen.io/AnotherLinuxUser/pen/pRQGaM?editors=1011)\n         * @private\n         */\n\n    }, {\n        key: '_createGlobalList',\n        value: function _createGlobalList() {\n            // The check that this global list does not exists already is done in the add and remove functions already\n            this.autoNumericGlobalListName = 'autoNumericGlobalList'; //XXX This looks weird to set a variable on `this.` in a static method, but that really declare that variable like a static property\n            // Note: I should not get any memory leaks for referencing the DOM element in the `value`, this DOM element also being the `key`, according to the spec : http://www.ecma-international.org/ecma-262/6.0/#sec-weakmap-objects\n            this._createWeakMap(this.autoNumericGlobalListName);\n        }\n\n        /**\n         * Return `true` if the global AutoNumeric element list exists.\n         *\n         * @returns {boolean}\n         * @private\n         */\n\n    }, {\n        key: '_doesGlobalListExists',\n        value: function _doesGlobalListExists() {\n            var type = _typeof(window[this.autoNumericGlobalListName]);\n            return type !== 'undefined' && type === 'object';\n        }\n\n        /**\n         * Add the given object to the global AutoNumeric element list.\n         *\n         * @param {AutoNumeric} autoNumericObject\n         * @private\n         */\n\n    }, {\n        key: '_addToGlobalList',\n        value: function _addToGlobalList(autoNumericObject) {\n            if (!this._doesGlobalListExists()) {\n                this._createGlobalList();\n            }\n\n            var domElement = autoNumericObject.node();\n            // This checks if the object is not already in the global list before adding it.\n            // This could happen if an AutoNumeric element is initialized, then the DOM element is removed directly via `removeChild` (hence the reference does not get removed from the global list), then it get recreated and initialized again\n            if (this._isInGlobalList(domElement)) {\n                if (this._getFromGlobalList(domElement) === this) {\n                    // Do not add this AutoNumeric object again since it's already in that global list\n                    return;\n                } else {\n                    // Print a warning to warn that the domElement already has a reference in the global map (but we cannot for sure starts deleting those old references since they could still be used by another AutoNumeric object)\n                    _AutoNumericHelper2.default.warning('A reference to the DOM element you just initialized already exists in the global AutoNumeric element list. Please make sure to not initialize the same DOM element multiple times.', autoNumericObject.getSettings().showWarnings);\n                }\n            }\n\n            window[this.autoNumericGlobalListName].set(domElement, autoNumericObject);\n        }\n\n        /**\n         * Remove the given object from the global AutoNumeric element list.\n         *\n         * @param {AutoNumeric} autoNumericObject\n         * @private\n         */\n\n    }, {\n        key: '_removeFromGlobalList',\n        value: function _removeFromGlobalList(autoNumericObject) {\n            //FIXME test this\n            if (this._doesGlobalListExists()) {\n                window[this.autoNumericGlobalListName].delete(autoNumericObject.node());\n            }\n        }\n\n        /**\n         * Return the value associated to the key `domElement` passed as a parameter.\n         * The value is the AutoNumeric object that manages the DOM element `domElement`.\n         *\n         * @param {HTMLElement|HTMLInputElement} domElement\n         * @returns {null|AutoNumeric}\n         * @private\n         */\n\n    }, {\n        key: '_getFromGlobalList',\n        value: function _getFromGlobalList(domElement) {\n            //FIXME test this\n            if (this._doesGlobalListExists()) {\n                return window[this.autoNumericGlobalListName].get(domElement);\n            }\n\n            return null;\n        }\n\n        /**\n         * Check if the given DOM element is in the global AutoNumeric element list.\n         *\n         * @param {HTMLElement|HTMLInputElement} domElement\n         * @returns {boolean}\n         * @private\n         */\n\n    }, {\n        key: '_isInGlobalList',\n        value: function _isInGlobalList(domElement) {\n            //FIXME test this\n            if (!this._doesGlobalListExists()) {\n                return false;\n            }\n\n            return window[this.autoNumericGlobalListName].has(domElement);\n        }\n    }, {\n        key: 'validate',\n        value: function validate(userOptions) {\n            var shouldExtendDefaultOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n            var originalOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\n            if (_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(userOptions) || !_AutoNumericHelper2.default.isObject(userOptions)) {\n                _AutoNumericHelper2.default.throwError('The userOptions are invalid ; it should be a valid object, [' + userOptions + '] given.');\n            }\n\n            var isOriginalOptionAnObject = _AutoNumericHelper2.default.isObject(originalOptions);\n            if (!isOriginalOptionAnObject && !_AutoNumericHelper2.default.isNull(originalOptions)) {\n                _AutoNumericHelper2.default.throwError('The \\'originalOptions\\' parameter is invalid ; it should either be a valid option object or `null`, [' + userOptions + '] given.');\n            }\n\n            // If the user used old options, we convert them to new ones\n            if (!_AutoNumericHelper2.default.isNull(userOptions)) {\n                this._convertOldOptionsToNewOnes(userOptions);\n            }\n\n            // The user can choose if the `userOptions` has already been extended with the default options, or not\n            var options = void 0;\n            if (shouldExtendDefaultOptions) {\n                options = _extends({}, this.getDefaultConfig(), userOptions);\n            } else {\n                options = userOptions;\n            }\n\n            // First things first, we test that the `showWarnings` option is valid\n            if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.showWarnings) && !_AutoNumericHelper2.default.isBoolean(options.showWarnings)) {\n                _AutoNumericHelper2.default.throwError('The debug option \\'showWarnings\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.showWarnings + '] given.');\n            }\n\n            // Define the regular expressions needed for the following tests\n            var testPositiveInteger = /^[0-9]+$/;\n            var testNumericalCharacters = /[0-9]+/;\n            // const testFloatAndPossibleNegativeSign = /^-?[0-9]+(\\.?[0-9]+)$/;\n            var testFloatOrIntegerAndPossibleNegativeSign = /^-?[0-9]+(\\.?[0-9]+)?$/;\n            var testPositiveFloatOrInteger = /^[0-9]+(\\.?[0-9]+)?$/;\n\n            // Then tests the options individually\n            if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.allowDecimalPadding) && !_AutoNumericHelper2.default.isBoolean(options.allowDecimalPadding) && options.allowDecimalPadding !== AutoNumeric.options.allowDecimalPadding.floats) {\n                _AutoNumericHelper2.default.throwError('The decimal padding option \\'allowDecimalPadding\\' is invalid ; it should either be `false`, `true` or `\\'floats\\'`, [' + options.allowDecimalPadding + '] given.');\n            }\n\n            if ((options.allowDecimalPadding === AutoNumeric.options.allowDecimalPadding.never || options.allowDecimalPadding === 'false') && (options.decimalPlaces !== AutoNumeric.options.decimalPlaces.none || options.decimalPlacesShownOnBlur !== AutoNumeric.options.decimalPlacesShownOnBlur.none || options.decimalPlacesShownOnFocus !== AutoNumeric.options.decimalPlacesShownOnFocus.none)) {\n                _AutoNumericHelper2.default.warning('Setting \\'allowDecimalPadding\\' to [' + options.allowDecimalPadding + '] will override the current \\'decimalPlaces*\\' settings [' + options.decimalPlaces + ', ' + options.decimalPlacesShownOnBlur + ' and ' + options.decimalPlacesShownOnFocus + '].', options.showWarnings);\n            }\n\n            if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.alwaysAllowDecimalCharacter) && !_AutoNumericHelper2.default.isBoolean(options.alwaysAllowDecimalCharacter)) {\n                _AutoNumericHelper2.default.throwError('The option \\'alwaysAllowDecimalCharacter\\' is invalid ; it should either be `true` or `false`, [' + options.alwaysAllowDecimalCharacter + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isNull(options.caretPositionOnFocus) && !_AutoNumericHelper2.default.isInArray(options.caretPositionOnFocus, [AutoNumeric.options.caretPositionOnFocus.start, AutoNumeric.options.caretPositionOnFocus.end, AutoNumeric.options.caretPositionOnFocus.decimalLeft, AutoNumeric.options.caretPositionOnFocus.decimalRight])) {\n                _AutoNumericHelper2.default.throwError('The display on empty string option \\'caretPositionOnFocus\\' is invalid ; it should either be `null`, \\'focus\\', \\'press\\', \\'always\\' or \\'zero\\', [' + options.caretPositionOnFocus + '] given.');\n            }\n\n            // Special case here for `caretPositionOnFocus` and `selectOnFocus` where we need to check the original non-tempered version of the options in order to check for conflicts, since using the default settings remove those and would prevent us warning the user that his option object is not correct.\n            var optionsToUse = void 0;\n            if (isOriginalOptionAnObject) {\n                optionsToUse = originalOptions;\n            } else {\n                optionsToUse = this._correctCaretPositionOnFocusAndSelectOnFocusOptions(userOptions);\n            }\n\n            if (!_AutoNumericHelper2.default.isNull(optionsToUse) && optionsToUse.caretPositionOnFocus !== AutoNumeric.options.caretPositionOnFocus.doNoForceCaretPosition && optionsToUse.selectOnFocus === AutoNumeric.options.selectOnFocus.select) {\n                _AutoNumericHelper2.default.warning('The \\'selectOnFocus\\' option is set to \\'select\\', which is in conflict with the \\'caretPositionOnFocus\\' which is set to \\'' + optionsToUse.caretPositionOnFocus + '\\'. As a result, if this has been called when instantiating an AutoNumeric object, the \\'selectOnFocus\\' option is forced to \\'doNotSelect\\'.', options.showWarnings);\n            }\n\n            if (!_AutoNumericHelper2.default.isInArray(options.digitGroupSeparator, [AutoNumeric.options.digitGroupSeparator.comma, AutoNumeric.options.digitGroupSeparator.dot, AutoNumeric.options.digitGroupSeparator.normalSpace, AutoNumeric.options.digitGroupSeparator.thinSpace, AutoNumeric.options.digitGroupSeparator.narrowNoBreakSpace, AutoNumeric.options.digitGroupSeparator.noBreakSpace, AutoNumeric.options.digitGroupSeparator.noSeparator, AutoNumeric.options.digitGroupSeparator.apostrophe, AutoNumeric.options.digitGroupSeparator.arabicThousandsSeparator, AutoNumeric.options.digitGroupSeparator.dotAbove])) {\n                _AutoNumericHelper2.default.throwError('The thousand separator character option \\'digitGroupSeparator\\' is invalid ; it should be \\',\\', \\'.\\', \\'\\u066C\\', \\'\\u02D9\\', \"\\'\", \\' \\', \\'\\u2009\\', \\'\\u202F\\', \\'\\xA0\\' or empty (\\'\\'), [' + options.digitGroupSeparator + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.showOnlyNumbersOnFocus) && !_AutoNumericHelper2.default.isBoolean(options.showOnlyNumbersOnFocus)) {\n                _AutoNumericHelper2.default.throwError('The \\'showOnlyNumbersOnFocus\\' option is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.showOnlyNumbersOnFocus + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isInArray(options.digitalGroupSpacing, [AutoNumeric.options.digitalGroupSpacing.two, AutoNumeric.options.digitalGroupSpacing.twoScaled, AutoNumeric.options.digitalGroupSpacing.three, AutoNumeric.options.digitalGroupSpacing.four]) && !(options.digitalGroupSpacing >= 2 && options.digitalGroupSpacing <= 4)) {\n                _AutoNumericHelper2.default.throwError('The grouping separator option for thousands \\'digitalGroupSpacing\\' is invalid ; it should be \\'2\\', \\'2s\\', \\'3\\', or \\'4\\', [' + options.digitalGroupSpacing + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isInArray(options.decimalCharacter, [AutoNumeric.options.decimalCharacter.comma, AutoNumeric.options.decimalCharacter.dot, AutoNumeric.options.decimalCharacter.middleDot, AutoNumeric.options.decimalCharacter.arabicDecimalSeparator, AutoNumeric.options.decimalCharacter.decimalSeparatorKeySymbol])) {\n                _AutoNumericHelper2.default.throwError('The decimal separator character option \\'decimalCharacter\\' is invalid ; it should be \\'.\\', \\',\\', \\'\\xB7\\', \\'\\u2396\\' or \\'\\u066B\\', [' + options.decimalCharacter + '] given.');\n            }\n\n            // Checks if the decimal and thousand characters are the same\n            if (options.decimalCharacter === options.digitGroupSeparator) {\n                _AutoNumericHelper2.default.throwError('autoNumeric will not function properly when the decimal character \\'decimalCharacter\\' [' + options.decimalCharacter + '] and the thousand separator \\'digitGroupSeparator\\' [' + options.digitGroupSeparator + '] are the same character.');\n            }\n\n            if (!_AutoNumericHelper2.default.isNull(options.decimalCharacterAlternative) && !_AutoNumericHelper2.default.isString(options.decimalCharacterAlternative)) {\n                _AutoNumericHelper2.default.throwError('The alternate decimal separator character option \\'decimalCharacterAlternative\\' is invalid ; it should be a string, [' + options.decimalCharacterAlternative + '] given.');\n            }\n\n            if (options.currencySymbol !== '' && !_AutoNumericHelper2.default.isString(options.currencySymbol)) {\n                _AutoNumericHelper2.default.throwError('The currency symbol option \\'currencySymbol\\' is invalid ; it should be a string, [' + options.currencySymbol + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isInArray(options.currencySymbolPlacement, [AutoNumeric.options.currencySymbolPlacement.prefix, AutoNumeric.options.currencySymbolPlacement.suffix])) {\n                _AutoNumericHelper2.default.throwError('The placement of the currency sign option \\'currencySymbolPlacement\\' is invalid ; it should either be \\'p\\' (prefix) or \\'s\\' (suffix), [' + options.currencySymbolPlacement + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isInArray(options.negativePositiveSignPlacement, [AutoNumeric.options.negativePositiveSignPlacement.prefix, AutoNumeric.options.negativePositiveSignPlacement.suffix, AutoNumeric.options.negativePositiveSignPlacement.left, AutoNumeric.options.negativePositiveSignPlacement.right, AutoNumeric.options.negativePositiveSignPlacement.none])) {\n                _AutoNumericHelper2.default.throwError('The placement of the negative sign option \\'negativePositiveSignPlacement\\' is invalid ; it should either be \\'p\\' (prefix), \\'s\\' (suffix), \\'l\\' (left), \\'r\\' (right) or \\'null\\', [' + options.negativePositiveSignPlacement + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.showPositiveSign) && !_AutoNumericHelper2.default.isBoolean(options.showPositiveSign)) {\n                _AutoNumericHelper2.default.throwError('The show positive sign option \\'showPositiveSign\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.showPositiveSign + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isString(options.suffixText) || options.suffixText !== '' && (_AutoNumericHelper2.default.isNegative(options.suffixText, options.negativeSignCharacter) || testNumericalCharacters.test(options.suffixText))) {\n                _AutoNumericHelper2.default.throwError('The additional suffix option \\'suffixText\\' is invalid ; it should not contains the negative sign \\'' + options.negativeSignCharacter + '\\' nor any numerical characters, [' + options.suffixText + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isString(options.negativeSignCharacter) || options.negativeSignCharacter.length !== 1 || _AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(options.negativeSignCharacter) || testNumericalCharacters.test(options.negativeSignCharacter)) {\n                _AutoNumericHelper2.default.throwError('The negative sign character option \\'negativeSignCharacter\\' is invalid ; it should be a single character, and cannot be any numerical characters, [' + options.negativeSignCharacter + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isString(options.positiveSignCharacter) || options.positiveSignCharacter.length !== 1 || _AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(options.positiveSignCharacter) || testNumericalCharacters.test(options.positiveSignCharacter)) {\n                _AutoNumericHelper2.default.throwError('The positive sign character option \\'positiveSignCharacter\\' is invalid ; it should be a single character, and cannot be any numerical characters, [' + options.positiveSignCharacter + '] given.\\nIf you want to hide the positive sign character, you need to set the `showPositiveSign` option to `true`.');\n            }\n\n            if (options.negativeSignCharacter === options.positiveSignCharacter) {\n                _AutoNumericHelper2.default.throwError('The positive \\'positiveSignCharacter\\' and negative \\'negativeSignCharacter\\' sign characters cannot be identical ; [' + options.negativeSignCharacter + '] given.');\n            }\n\n            var _ref5 = _AutoNumericHelper2.default.isNull(options.negativeBracketsTypeOnBlur) ? ['', ''] : options.negativeBracketsTypeOnBlur.split(','),\n                _ref6 = _slicedToArray(_ref5, 2),\n                leftBracket = _ref6[0],\n                rightBracket = _ref6[1];\n\n            if (_AutoNumericHelper2.default.contains(options.digitGroupSeparator, options.negativeSignCharacter) || _AutoNumericHelper2.default.contains(options.decimalCharacter, options.negativeSignCharacter) || _AutoNumericHelper2.default.contains(options.decimalCharacterAlternative, options.negativeSignCharacter) || _AutoNumericHelper2.default.contains(leftBracket, options.negativeSignCharacter) || _AutoNumericHelper2.default.contains(rightBracket, options.negativeSignCharacter) || _AutoNumericHelper2.default.contains(options.suffixText, options.negativeSignCharacter)) {\n                _AutoNumericHelper2.default.throwError('The negative sign character option \\'negativeSignCharacter\\' is invalid ; it should not be equal or a part of the digit separator, the decimal character, the decimal character alternative, the negative brackets or the suffix text, [' + options.negativeSignCharacter + '] given.');\n            }\n\n            if (_AutoNumericHelper2.default.contains(options.digitGroupSeparator, options.positiveSignCharacter) || _AutoNumericHelper2.default.contains(options.decimalCharacter, options.positiveSignCharacter) || _AutoNumericHelper2.default.contains(options.decimalCharacterAlternative, options.positiveSignCharacter) || _AutoNumericHelper2.default.contains(leftBracket, options.positiveSignCharacter) || _AutoNumericHelper2.default.contains(rightBracket, options.positiveSignCharacter) || _AutoNumericHelper2.default.contains(options.suffixText, options.positiveSignCharacter)) {\n                _AutoNumericHelper2.default.throwError('The positive sign character option \\'positiveSignCharacter\\' is invalid ; it should not be equal or a part of the digit separator, the decimal character, the decimal character alternative, the negative brackets or the suffix text, [' + options.positiveSignCharacter + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isNull(options.overrideMinMaxLimits) && !_AutoNumericHelper2.default.isInArray(options.overrideMinMaxLimits, [AutoNumeric.options.overrideMinMaxLimits.ceiling, AutoNumeric.options.overrideMinMaxLimits.floor, AutoNumeric.options.overrideMinMaxLimits.ignore])) {\n                _AutoNumericHelper2.default.throwError('The override min & max limits option \\'overrideMinMaxLimits\\' is invalid ; it should either be \\'ceiling\\', \\'floor\\' or \\'ignore\\', [' + options.overrideMinMaxLimits + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isString(options.maximumValue) || !testFloatOrIntegerAndPossibleNegativeSign.test(options.maximumValue)) {\n                _AutoNumericHelper2.default.throwError('The maximum possible value option \\'maximumValue\\' is invalid ; it should be a string that represents a positive or negative number, [' + options.maximumValue + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isString(options.minimumValue) || !testFloatOrIntegerAndPossibleNegativeSign.test(options.minimumValue)) {\n                _AutoNumericHelper2.default.throwError('The minimum possible value option \\'minimumValue\\' is invalid ; it should be a string that represents a positive or negative number, [' + options.minimumValue + '] given.');\n            }\n\n            if (parseFloat(options.minimumValue) > parseFloat(options.maximumValue)) {\n                _AutoNumericHelper2.default.throwError('The minimum possible value option is greater than the maximum possible value option ; \\'minimumValue\\' [' + options.minimumValue + '] should be smaller than \\'maximumValue\\' [' + options.maximumValue + '].');\n            }\n\n            if (!(_AutoNumericHelper2.default.isInt(options.decimalPlaces) && options.decimalPlaces >= 0 || // If integer option\n            _AutoNumericHelper2.default.isString(options.decimalPlaces) && testPositiveInteger.test(options.decimalPlaces)) // If string option\n            ) {\n                    _AutoNumericHelper2.default.throwError('The number of decimal places option \\'decimalPlaces\\' is invalid ; it should be a positive integer, [' + options.decimalPlaces + '] given.');\n                }\n\n            if (!(_AutoNumericHelper2.default.isNull(options.decimalPlacesRawValue) || _AutoNumericHelper2.default.isInt(options.decimalPlacesRawValue) && options.decimalPlacesRawValue >= 0 || // If integer option\n            _AutoNumericHelper2.default.isString(options.decimalPlacesRawValue) && testPositiveInteger.test(options.decimalPlacesRawValue)) // If string option\n            ) {\n                    _AutoNumericHelper2.default.throwError('The number of decimal places for the raw value option \\'decimalPlacesRawValue\\' is invalid ; it should be a positive integer or `null`, [' + options.decimalPlacesRawValue + '] given.');\n                }\n\n            // Checks if the number of decimal places for the raw value is lower than the `decimalPlaces`, `decimalPlacesShownOnFocus` and/or `decimalPlacesShownOnBlur` options\n            this._validateDecimalPlacesRawValue(options);\n\n            if (!_AutoNumericHelper2.default.isNull(options.decimalPlacesShownOnFocus) && !testPositiveInteger.test(String(options.decimalPlacesShownOnFocus))) {\n                _AutoNumericHelper2.default.throwError('The number of expanded decimal places option \\'decimalPlacesShownOnFocus\\' is invalid ; it should be a positive integer or `null`, [' + options.decimalPlacesShownOnFocus + '] given.');\n            }\n\n            // Checks if the extended decimal places \"decimalPlacesShownOnFocus\" is greater than the decimal places number `decimalPlaces`\n            if (!_AutoNumericHelper2.default.isNull(options.decimalPlacesShownOnFocus) && Number(options.decimalPlaces) > Number(options.decimalPlacesShownOnFocus)) {\n                _AutoNumericHelper2.default.warning('The extended decimal places \\'decimalPlacesShownOnFocus\\' [' + options.decimalPlacesShownOnFocus + '] should be greater than the \\'decimalPlaces\\' [' + options.decimalPlaces + '] value. Currently, this will limit the ability of your user to manually change some of the decimal places. Do you really want to do that?', options.showWarnings);\n            }\n\n            if (!_AutoNumericHelper2.default.isNull(options.divisorWhenUnfocused) && !testPositiveFloatOrInteger.test(options.divisorWhenUnfocused) || options.divisorWhenUnfocused === 0 || options.divisorWhenUnfocused === '0' || options.divisorWhenUnfocused === 1 || options.divisorWhenUnfocused === '1') {\n                _AutoNumericHelper2.default.throwError('The divisor option \\'divisorWhenUnfocused\\' is invalid ; it should be a positive number higher than one, preferably an integer, [' + options.divisorWhenUnfocused + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isNull(options.decimalPlacesShownOnBlur) && !testPositiveInteger.test(options.decimalPlacesShownOnBlur)) {\n                _AutoNumericHelper2.default.throwError('The number of decimals shown when unfocused option \\'decimalPlacesShownOnBlur\\' is invalid ; it should be a positive integer or `null`, [' + options.decimalPlacesShownOnBlur + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isNull(options.symbolWhenUnfocused) && !_AutoNumericHelper2.default.isString(options.symbolWhenUnfocused)) {\n                _AutoNumericHelper2.default.throwError('The symbol to show when unfocused option \\'symbolWhenUnfocused\\' is invalid ; it should be a string, [' + options.symbolWhenUnfocused + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.saveValueToSessionStorage) && !_AutoNumericHelper2.default.isBoolean(options.saveValueToSessionStorage)) {\n                _AutoNumericHelper2.default.throwError('The save to session storage option \\'saveValueToSessionStorage\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.saveValueToSessionStorage + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isInArray(options.onInvalidPaste, [AutoNumeric.options.onInvalidPaste.error, AutoNumeric.options.onInvalidPaste.ignore, AutoNumeric.options.onInvalidPaste.clamp, AutoNumeric.options.onInvalidPaste.truncate, AutoNumeric.options.onInvalidPaste.replace])) {\n                _AutoNumericHelper2.default.throwError('The paste behavior option \\'onInvalidPaste\\' is invalid ; it should either be \\'error\\', \\'ignore\\', \\'clamp\\', \\'truncate\\' or \\'replace\\' (cf. documentation), [' + options.onInvalidPaste + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isInArray(options.roundingMethod, [AutoNumeric.options.roundingMethod.halfUpSymmetric, AutoNumeric.options.roundingMethod.halfUpAsymmetric, AutoNumeric.options.roundingMethod.halfDownSymmetric, AutoNumeric.options.roundingMethod.halfDownAsymmetric, AutoNumeric.options.roundingMethod.halfEvenBankersRounding, AutoNumeric.options.roundingMethod.upRoundAwayFromZero, AutoNumeric.options.roundingMethod.downRoundTowardZero, AutoNumeric.options.roundingMethod.toCeilingTowardPositiveInfinity, AutoNumeric.options.roundingMethod.toFloorTowardNegativeInfinity, AutoNumeric.options.roundingMethod.toNearest05, AutoNumeric.options.roundingMethod.toNearest05Alt, AutoNumeric.options.roundingMethod.upToNext05, AutoNumeric.options.roundingMethod.downToNext05])) {\n                _AutoNumericHelper2.default.throwError('The rounding method option \\'roundingMethod\\' is invalid ; it should either be \\'S\\', \\'A\\', \\'s\\', \\'a\\', \\'B\\', \\'U\\', \\'D\\', \\'C\\', \\'F\\', \\'N05\\', \\'CHF\\', \\'U05\\' or \\'D05\\' (cf. documentation), [' + options.roundingMethod + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isNull(options.negativeBracketsTypeOnBlur) && !_AutoNumericHelper2.default.isInArray(options.negativeBracketsTypeOnBlur, [AutoNumeric.options.negativeBracketsTypeOnBlur.parentheses, AutoNumeric.options.negativeBracketsTypeOnBlur.brackets, AutoNumeric.options.negativeBracketsTypeOnBlur.chevrons, AutoNumeric.options.negativeBracketsTypeOnBlur.curlyBraces, AutoNumeric.options.negativeBracketsTypeOnBlur.angleBrackets, AutoNumeric.options.negativeBracketsTypeOnBlur.japaneseQuotationMarks, AutoNumeric.options.negativeBracketsTypeOnBlur.halfBrackets, AutoNumeric.options.negativeBracketsTypeOnBlur.whiteSquareBrackets, AutoNumeric.options.negativeBracketsTypeOnBlur.quotationMarks, AutoNumeric.options.negativeBracketsTypeOnBlur.guillemets])) {\n                _AutoNumericHelper2.default.throwError('The brackets for negative values option \\'negativeBracketsTypeOnBlur\\' is invalid ; it should either be \\'(,)\\', \\'[,]\\', \\'<,>\\', \\'{,}\\', \\'\\u3008,\\u3009\\', \\'\\uFF62,\\uFF63\\', \\'\\u2E24,\\u2E25\\', \\'\\u27E6,\\u27E7\\', \\'\\u2039,\\u203A\\' or \\'\\xAB,\\xBB\\', [' + options.negativeBracketsTypeOnBlur + '] given.');\n            }\n\n            if (!(_AutoNumericHelper2.default.isString(options.emptyInputBehavior) || _AutoNumericHelper2.default.isNumber(options.emptyInputBehavior)) || !(_AutoNumericHelper2.default.isInArray(options.emptyInputBehavior, [AutoNumeric.options.emptyInputBehavior.focus, AutoNumeric.options.emptyInputBehavior.press, AutoNumeric.options.emptyInputBehavior.always, AutoNumeric.options.emptyInputBehavior.min, AutoNumeric.options.emptyInputBehavior.max, AutoNumeric.options.emptyInputBehavior.zero, AutoNumeric.options.emptyInputBehavior.null]) || testFloatOrIntegerAndPossibleNegativeSign.test(options.emptyInputBehavior))) {\n                _AutoNumericHelper2.default.throwError('The display on empty string option \\'emptyInputBehavior\\' is invalid ; it should either be \\'focus\\', \\'press\\', \\'always\\', \\'min\\', \\'max\\', \\'zero\\', \\'null\\', a number, or a string that represents a number, [' + options.emptyInputBehavior + '] given.');\n            }\n\n            if (options.emptyInputBehavior === AutoNumeric.options.emptyInputBehavior.zero && (options.minimumValue > 0 || options.maximumValue < 0)) {\n                _AutoNumericHelper2.default.throwError('The \\'emptyInputBehavior\\' option is set to \\'zero\\', but this value is outside of the range defined by \\'minimumValue\\' and \\'maximumValue\\' [' + options.minimumValue + ', ' + options.maximumValue + '].');\n            }\n\n            if (testFloatOrIntegerAndPossibleNegativeSign.test(String(options.emptyInputBehavior))) {\n                var _checkIfInRangeWithOv = this._checkIfInRangeWithOverrideOption(options.emptyInputBehavior, options),\n                    _checkIfInRangeWithOv2 = _slicedToArray(_checkIfInRangeWithOv, 2),\n                    minTest = _checkIfInRangeWithOv2[0],\n                    maxTest = _checkIfInRangeWithOv2[1];\n\n                if (!minTest || !maxTest) {\n                    _AutoNumericHelper2.default.throwError('The \\'emptyInputBehavior\\' option is set to a number or a string that represents a number, but its value [' + options.emptyInputBehavior + '] is outside of the range defined by the \\'minimumValue\\' and \\'maximumValue\\' options [' + options.minimumValue + ', ' + options.maximumValue + '].');\n                }\n            }\n\n            if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.eventBubbles) && !_AutoNumericHelper2.default.isBoolean(options.eventBubbles)) {\n                _AutoNumericHelper2.default.throwError('The event bubbles option \\'eventBubbles\\' is invalid ; it should be either \\'true\\' or \\'false\\', [' + options.eventBubbles + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.eventIsCancelable) && !_AutoNumericHelper2.default.isBoolean(options.eventIsCancelable)) {\n                _AutoNumericHelper2.default.throwError('The event is cancelable option \\'eventIsCancelable\\' is invalid ; it should be either \\'true\\' or \\'false\\', [' + options.eventIsCancelable + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isInArray(options.leadingZero, [AutoNumeric.options.leadingZero.allow, AutoNumeric.options.leadingZero.deny, AutoNumeric.options.leadingZero.keep])) {\n                _AutoNumericHelper2.default.throwError('The leading zero behavior option \\'leadingZero\\' is invalid ; it should either be \\'allow\\', \\'deny\\' or \\'keep\\', [' + options.leadingZero + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.formatOnPageLoad) && !_AutoNumericHelper2.default.isBoolean(options.formatOnPageLoad)) {\n                _AutoNumericHelper2.default.throwError('The format on initialization option \\'formatOnPageLoad\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.formatOnPageLoad + '] given.');\n            }\n\n            if (!testPositiveInteger.test(options.historySize) || options.historySize === 0) {\n                _AutoNumericHelper2.default.throwError('The history size option \\'historySize\\' is invalid ; it should be a positive integer, [' + options.historySize + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.selectNumberOnly) && !_AutoNumericHelper2.default.isBoolean(options.selectNumberOnly)) {\n                _AutoNumericHelper2.default.throwError('The select number only option \\'selectNumberOnly\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.selectNumberOnly + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.selectOnFocus) && !_AutoNumericHelper2.default.isBoolean(options.selectOnFocus)) {\n                _AutoNumericHelper2.default.throwError('The select on focus option \\'selectOnFocus\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.selectOnFocus + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isNull(options.defaultValueOverride) && options.defaultValueOverride !== '' && !testFloatOrIntegerAndPossibleNegativeSign.test(options.defaultValueOverride)) {\n                _AutoNumericHelper2.default.throwError('The unformatted default value option \\'defaultValueOverride\\' is invalid ; it should be a string that represents a positive or negative number, [' + options.defaultValueOverride + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.unformatOnSubmit) && !_AutoNumericHelper2.default.isBoolean(options.unformatOnSubmit)) {\n                _AutoNumericHelper2.default.throwError('The remove formatting on submit option \\'unformatOnSubmit\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.unformatOnSubmit + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isNull(options.valuesToStrings) && !_AutoNumericHelper2.default.isObject(options.valuesToStrings)) {\n                _AutoNumericHelper2.default.throwError('The option \\'valuesToStrings\\' is invalid ; it should be an object, ideally with \\'key -> value\\' entries, [' + options.valuesToStrings + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isNull(options.outputFormat) && !_AutoNumericHelper2.default.isInArray(options.outputFormat, [AutoNumeric.options.outputFormat.string, AutoNumeric.options.outputFormat.number, AutoNumeric.options.outputFormat.dot, AutoNumeric.options.outputFormat.negativeDot, AutoNumeric.options.outputFormat.comma, AutoNumeric.options.outputFormat.negativeComma, AutoNumeric.options.outputFormat.dotNegative, AutoNumeric.options.outputFormat.commaNegative])) {\n                _AutoNumericHelper2.default.throwError('The custom locale format option \\'outputFormat\\' is invalid ; it should either be null, \\'string\\', \\'number\\', \\'.\\', \\'-.\\', \\',\\', \\'-,\\', \\'.-\\' or \\',-\\', [' + options.outputFormat + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.isCancellable) && !_AutoNumericHelper2.default.isBoolean(options.isCancellable)) {\n                _AutoNumericHelper2.default.throwError('The cancellable behavior option \\'isCancellable\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.isCancellable + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.modifyValueOnWheel) && !_AutoNumericHelper2.default.isBoolean(options.modifyValueOnWheel)) {\n                _AutoNumericHelper2.default.throwError('The increment/decrement on mouse wheel option \\'modifyValueOnWheel\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.modifyValueOnWheel + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.watchExternalChanges) && !_AutoNumericHelper2.default.isBoolean(options.watchExternalChanges)) {\n                _AutoNumericHelper2.default.throwError('The option \\'watchExternalChanges\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.watchExternalChanges + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isInArray(options.wheelOn, [AutoNumeric.options.wheelOn.focus, AutoNumeric.options.wheelOn.hover])) {\n                _AutoNumericHelper2.default.throwError('The wheel behavior option \\'wheelOn\\' is invalid ; it should either be \\'focus\\' or \\'hover\\', [' + options.wheelOn + '] given.');\n            }\n\n            if (!(_AutoNumericHelper2.default.isString(options.wheelStep) || _AutoNumericHelper2.default.isNumber(options.wheelStep)) || options.wheelStep !== 'progressive' && !testPositiveFloatOrInteger.test(options.wheelStep) || Number(options.wheelStep) === 0) {\n                // A step equal to '0' is rejected\n                _AutoNumericHelper2.default.throwError('The wheel step value option \\'wheelStep\\' is invalid ; it should either be the string \\'progressive\\', or a number or a string that represents a positive number (excluding zero), [' + options.wheelStep + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isInArray(options.serializeSpaces, [AutoNumeric.options.serializeSpaces.plus, AutoNumeric.options.serializeSpaces.percent])) {\n                _AutoNumericHelper2.default.throwError('The space replacement character option \\'serializeSpaces\\' is invalid ; it should either be \\'+\\' or \\'%20\\', [' + options.serializeSpaces + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.noEventListeners) && !_AutoNumericHelper2.default.isBoolean(options.noEventListeners)) {\n                _AutoNumericHelper2.default.throwError('The option \\'noEventListeners\\' that prevent the creation of event listeners is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.noEventListeners + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isNull(options.styleRules) && !(_AutoNumericHelper2.default.isObject(options.styleRules) && (options.styleRules.hasOwnProperty('positive') || options.styleRules.hasOwnProperty('negative') || options.styleRules.hasOwnProperty('ranges') || options.styleRules.hasOwnProperty('userDefined')))) {\n                _AutoNumericHelper2.default.throwError('The option \\'styleRules\\' is invalid ; it should be a correctly structured object, with one or more \\'positive\\', \\'negative\\', \\'ranges\\' or \\'userDefined\\' attributes, [' + options.styleRules + '] given.');\n            }\n\n            // Deeper tests of the `styleRules` object : Check that the callback, if defined, is a function\n            if (!_AutoNumericHelper2.default.isNull(options.styleRules) && options.styleRules.hasOwnProperty('userDefined') && !_AutoNumericHelper2.default.isNull(options.styleRules.userDefined)) {\n                options.styleRules.userDefined.forEach(function (rule) {\n                    if (rule.hasOwnProperty('callback') && !_AutoNumericHelper2.default.isFunction(rule.callback)) {\n                        _AutoNumericHelper2.default.throwError('The callback defined in the `userDefined` attribute is not a function, ' + _typeof(rule.callback) + ' given.');\n                    }\n                });\n            }\n\n            if (!_AutoNumericHelper2.default.isNull(options.rawValueDivisor) && !testPositiveFloatOrInteger.test(options.rawValueDivisor) || options.rawValueDivisor === 0 || options.rawValueDivisor === '0' || options.rawValueDivisor === 1 || options.rawValueDivisor === '1') {\n                _AutoNumericHelper2.default.throwError('The raw value divisor option \\'rawValueDivisor\\' is invalid ; it should be a positive number higher than one, preferably an integer, [' + options.rawValueDivisor + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.readOnly) && !_AutoNumericHelper2.default.isBoolean(options.readOnly)) {\n                _AutoNumericHelper2.default.throwError('The option \\'readOnly\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.readOnly + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.unformatOnHover) && !_AutoNumericHelper2.default.isBoolean(options.unformatOnHover)) {\n                _AutoNumericHelper2.default.throwError('The option \\'unformatOnHover\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.unformatOnHover + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.failOnUnknownOption) && !_AutoNumericHelper2.default.isBoolean(options.failOnUnknownOption)) {\n                _AutoNumericHelper2.default.throwError('The debug option \\'failOnUnknownOption\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.failOnUnknownOption + '] given.');\n            }\n\n            if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.createLocalList) && !_AutoNumericHelper2.default.isBoolean(options.createLocalList)) {\n                _AutoNumericHelper2.default.throwError('The debug option \\'createLocalList\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.createLocalList + '] given.');\n            }\n        }\n\n        /**\n         * Check the `decimalPlaces*` options and output the relevant warnings if some of those will get overwritten during the initialization or settings update.\n         *\n         * @param {object} options\n         * @private\n         */\n\n    }, {\n        key: '_validateDecimalPlacesRawValue',\n        value: function _validateDecimalPlacesRawValue(options) {\n            // Checks if the number of decimal places for the raw value is lower than the `decimalPlaces`, `decimalPlacesShownOnFocus` and/or `decimalPlacesShownOnBlur` options\n            if (!_AutoNumericHelper2.default.isNull(options.decimalPlacesRawValue)) {\n                if (options.decimalPlacesRawValue < options.decimalPlaces) {\n                    _AutoNumericHelper2.default.warning('The number of decimal places to store in the raw value [' + options.decimalPlacesRawValue + '] is lower than the ones to display [' + options.decimalPlaces + ']. This will likely confuse your users.\\nTo solve that, you\\'d need to either set `decimalPlacesRawValue` to `null`, or set a number of decimal places for the raw value equal of bigger than `decimalPlaces`.', options.showWarnings);\n                }\n\n                if (options.decimalPlacesRawValue < options.decimalPlacesShownOnFocus) {\n                    _AutoNumericHelper2.default.warning('The number of decimal places to store in the raw value [' + options.decimalPlacesRawValue + '] is lower than the ones shown on focus [' + options.decimalPlacesShownOnFocus + ']. This will likely confuse your users.\\nTo solve that, you\\'d need to either set `decimalPlacesRawValue` to `null`, or set a number of decimal places for the raw value equal of bigger than `decimalPlacesShownOnFocus`.', options.showWarnings);\n                }\n\n                if (options.decimalPlacesRawValue < options.decimalPlacesShownOnBlur) {\n                    _AutoNumericHelper2.default.warning('The number of decimal places to store in the raw value [' + options.decimalPlacesRawValue + '] is lower than the ones shown when unfocused [' + options.decimalPlacesShownOnBlur + ']. This will likely confuse your users.\\nTo solve that, you\\'d need to either set `decimalPlacesRawValue` to `null`, or set a number of decimal places for the raw value equal of bigger than `decimalPlacesShownOnBlur`.', options.showWarnings);\n                }\n            }\n        }\n\n        /**\n         * Return `true` if the settings/options are valid, `false` otherwise.\n         *\n         * @param {object} options\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'areSettingsValid',\n        value: function areSettingsValid(options) {\n            var isValid = true;\n            try {\n                this.validate(options, true);\n            } catch (error) {\n                isValid = false;\n            }\n\n            return isValid;\n        }\n\n        /**\n         * Return the default autoNumeric settings.\n         *\n         * @returns {object}\n         */\n\n    }, {\n        key: 'getDefaultConfig',\n        value: function getDefaultConfig() {\n            return AutoNumeric.defaultSettings;\n        }\n\n        /**\n         * Return all the predefined language options in one object.\n         * You can also access a specific language object directly by using `AutoNumeric.getPredefinedOptions().French` for instance.\n         *\n         * @returns {object}\n         */\n\n    }, {\n        key: 'getPredefinedOptions',\n        value: function getPredefinedOptions() {\n            return AutoNumeric.predefinedOptions;\n        }\n\n        /**\n         * Analyse the given array `options` and return a single 'merged' option objet.\n         * `options` can be `null`, or an array of an option objects, or an array containing another array of option objects / strings (pre-defined option names)\n         *\n         * @param {null|Array<object|string|Array<string|object>>} options\n         * @returns {null|object}\n         * @private\n         */\n\n    }, {\n        key: '_generateOptionsObjectFromOptionsArray',\n        value: function _generateOptionsObjectFromOptionsArray(options) {\n            var _this14 = this;\n\n            var optionsResult = void 0;\n            if (_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(options) || options.length === 0) {\n                optionsResult = null;\n            } else {\n                optionsResult = {};\n                if (options.length === 1 && Array.isArray(options[0])) {\n                    options[0].forEach(function (optionObject) {\n                        // Using `_getOptionObject()` allows using pre-defined names in the `options` array\n                        _extends(optionsResult, _this14._getOptionObject(optionObject));\n                    });\n                } else if (options.length >= 1) {\n                    options.forEach(function (optionObject) {\n                        _extends(optionsResult, _this14._getOptionObject(optionObject));\n                    });\n                }\n            }\n\n            return optionsResult;\n        }\n\n        /**\n         * Format the given number (or numeric string) with the given options. This returns the formatted value as a string.\n         * This can also format the given DOM element value with the given options and returns the formatted value as a string.\n         * Note : This function does *not* update that element value with the newly formatted value.\n         * This basically allows to get the formatted value without first having to initialize an AutoNumeric object.\n         *\n         * @param {number|string|HTMLElement|HTMLInputElement} numericStringOrDomElement A number, or a string that represent a javascript number, or a DOM element\n         * @param {object|null} options Multiple objects can be passed, the latter overwriting the settings from the former ones\n         * @returns {string|null}\n         */\n\n    }, {\n        key: 'format',\n        value: function format(numericStringOrDomElement) {\n            if (_AutoNumericHelper2.default.isUndefined(numericStringOrDomElement) || numericStringOrDomElement === null) {\n                return null;\n            }\n\n            // Retrieve the value to format\n            var value = void 0;\n            if (_AutoNumericHelper2.default.isElement(numericStringOrDomElement)) {\n                value = _AutoNumericHelper2.default.getElementValue(numericStringOrDomElement);\n            } else {\n                value = numericStringOrDomElement;\n            }\n\n            if (!_AutoNumericHelper2.default.isString(value) && !_AutoNumericHelper2.default.isNumber(value)) {\n                _AutoNumericHelper2.default.throwError('The value \"' + value + '\" being \"set\" is not numeric and therefore cannot be used appropriately.');\n            }\n\n            // Manage options\n\n            for (var _len5 = arguments.length, options = Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) {\n                options[_key5 - 1] = arguments[_key5];\n            }\n\n            var optionsToUse = this._generateOptionsObjectFromOptionsArray(options);\n\n            // Initiate a very basic settings object\n            var settings = _extends({}, this.getDefaultConfig(), optionsToUse);\n            settings.isNegativeSignAllowed = value < 0;\n            settings.isPositiveSignAllowed = value >= 0;\n            this._setBrackets(settings);\n\n            var regex = {};\n            this._cachesUsualRegularExpressions(settings, regex); // This is needed by `_stripAllNonNumberCharactersExceptCustomDecimalChar` that uses those regex\n\n            // Check the validity of the `value` parameter\n            // Convert the value to a numeric string, stripping unnecessary characters in the process\n            var valueString = this._toNumericValue(value, settings);\n            if (isNaN(Number(valueString))) {\n                _AutoNumericHelper2.default.throwError('The value [' + valueString + '] that you are trying to format is not a recognized number.');\n            }\n\n            // Basic tests to check if the given valueString is valid\n\n            var _checkIfInRangeWithOv3 = this._checkIfInRangeWithOverrideOption(valueString, settings),\n                _checkIfInRangeWithOv4 = _slicedToArray(_checkIfInRangeWithOv3, 2),\n                minTest = _checkIfInRangeWithOv4[0],\n                maxTest = _checkIfInRangeWithOv4[1];\n\n            if (!minTest || !maxTest) {\n                // Throw a custom event\n                _AutoNumericHelper2.default.triggerEvent(AutoNumeric.events.formatted, document, {\n                    oldValue: null,\n                    newValue: null,\n                    oldRawValue: null,\n                    newRawValue: null,\n                    isPristine: null,\n                    error: 'Range test failed',\n                    aNElement: null\n                }, true, true);\n                _AutoNumericHelper2.default.throwError('The value [' + valueString + '] being set falls outside of the minimumValue [' + settings.minimumValue + '] and maximumValue [' + settings.maximumValue + '] range set for this element');\n            }\n\n            // Directly format any `valuesToStrings` values, if found\n            if (settings.valuesToStrings && this._checkValuesToStringsSettings(value, settings)) {\n                return settings.valuesToStrings[value];\n            }\n\n            // Generate the `negativePositiveSignPlacement` option as needed\n            this._correctNegativePositiveSignPlacementOption(settings);\n            // Calculate the needed decimal places\n            this._calculateDecimalPlacesOnInit(settings);\n\n            // Multiply the raw value with `rawValueDivisor` if defined\n            if (!_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(settings.rawValueDivisor) && settings.rawValueDivisor !== 0 && // Only divide if the `rawValueDivisor` option is set\n            valueString !== '' && valueString !== null) {\n                // Do not modify the `valueString` if it's an empty string or null\n                valueString *= settings.rawValueDivisor;\n            }\n\n            // Everything is ok, proceed to rounding, formatting and grouping\n            valueString = this._roundFormattedValueShownOnFocus(valueString, settings);\n            valueString = this._modifyNegativeSignAndDecimalCharacterForFormattedValue(valueString, settings);\n            valueString = this._addGroupSeparators(valueString, settings, false, valueString);\n\n            return valueString;\n        }\n\n        /**\n         * Format the given DOM element value, and set the resulting value back as the element value.\n         *\n         * @param {HTMLElement|HTMLInputElement} domElement\n         * @param {object} options\n         * @returns {string|null}\n         */\n\n    }, {\n        key: 'formatAndSet',\n        value: function formatAndSet(domElement) {\n            var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n            //FIXME test this\n            var formattedValue = this.format(domElement, options);\n            _AutoNumericHelper2.default.setElementValue(domElement, formattedValue);\n\n            return formattedValue;\n        }\n\n        /**\n         * Unformat the given formatted string with the given options. This returns a numeric string.\n         * It can also unformat the given DOM element value with the given options and returns the unformatted numeric string.\n         * Note: This does *not* update that element value.\n         * This basically allows to get the unformatted value without first having to initialize an AutoNumeric object.\n         *\n         * @param {string|number|HTMLElement|HTMLInputElement} numericStringOrDomElement A number, or a string that represent a javascript number, or a DOM element\n         * @param {object|null} options Multiple objects can be passed, the latter overwriting the settings from the former ones\n         * @returns {string|number|NaN}\n         */\n\n    }, {\n        key: 'unformat',\n        value: function unformat(numericStringOrDomElement) {\n            if (_AutoNumericHelper2.default.isNumberStrict(numericStringOrDomElement)) {\n                // Giving an unformatted value should return the same unformatted value, whatever the options passed as a parameter\n                return numericStringOrDomElement;\n            }\n\n            // Retrieve the value to unformat\n            var value = void 0;\n            if (_AutoNumericHelper2.default.isElement(numericStringOrDomElement)) {\n                value = _AutoNumericHelper2.default.getElementValue(numericStringOrDomElement);\n            } else {\n                value = numericStringOrDomElement;\n            }\n\n            if (value === '') {\n                // This allows to be coherent when serializing forms with empty inputs. Fix issue #512.\n                return '';\n            }\n\n            if (_AutoNumericHelper2.default.isUndefined(value) || value === null) {\n                return null;\n            }\n\n            if (_AutoNumericHelper2.default.isArray(value) || _AutoNumericHelper2.default.isObject(value)) {\n                // Check the validity of the `value` parameter\n                _AutoNumericHelper2.default.throwError('A number or a string representing a number is needed to be able to unformat it, [' + value + '] given.');\n            }\n\n            // Manage options\n\n            for (var _len6 = arguments.length, options = Array(_len6 > 1 ? _len6 - 1 : 0), _key6 = 1; _key6 < _len6; _key6++) {\n                options[_key6 - 1] = arguments[_key6];\n            }\n\n            var optionsToUse = this._generateOptionsObjectFromOptionsArray(options);\n\n            // Generate the settings\n            var settings = _extends({}, this.getDefaultConfig(), optionsToUse);\n            settings.isNegativeSignAllowed = false;\n            settings.isPositiveSignAllowed = true;\n            value = value.toString();\n\n            // Directly unformat any `valuesToStrings` values, if found\n            if (settings.valuesToStrings && this._checkStringsToValuesSettings(value, settings)) {\n                return _AutoNumericHelper2.default.objectKeyLookup(settings.valuesToStrings, value);\n            }\n\n            // This checks if a negative sign is anywhere in the `value`, not just on the very first character (ie. '12345.67-')\n            if (_AutoNumericHelper2.default.isNegative(value, settings.negativeSignCharacter)) {\n                settings.isNegativeSignAllowed = true;\n                settings.isPositiveSignAllowed = false;\n            } else if (!_AutoNumericHelper2.default.isNull(settings.negativeBracketsTypeOnBlur)) {\n                var _settings$negativeBra = settings.negativeBracketsTypeOnBlur.split(',');\n\n                var _settings$negativeBra2 = _slicedToArray(_settings$negativeBra, 2);\n\n                settings.firstBracket = _settings$negativeBra2[0];\n                settings.lastBracket = _settings$negativeBra2[1];\n\n                if (value.charAt(0) === settings.firstBracket && value.charAt(value.length - 1) === settings.lastBracket) {\n                    settings.isNegativeSignAllowed = true;\n                    settings.isPositiveSignAllowed = false;\n                    value = this._removeBrackets(value, settings, false);\n                }\n            }\n\n            value = this._convertToNumericString(value, settings);\n            var unwantedCharacters = new RegExp('[^+-0123456789.]', 'gi');\n            if (unwantedCharacters.test(value)) {\n                return NaN;\n            }\n\n            // Generate the `negativePositiveSignPlacement` option as needed\n            this._correctNegativePositiveSignPlacementOption(settings);\n            // Calculate the needed decimal places\n            if (settings.decimalPlacesRawValue) {\n                // `originalDecimalPlacesRawValue` needs to be defined\n                settings.originalDecimalPlacesRawValue = settings.decimalPlacesRawValue;\n            } else {\n                settings.originalDecimalPlacesRawValue = settings.decimalPlaces;\n            }\n\n            this._calculateDecimalPlacesOnInit(settings);\n\n            // Divide the raw value with `rawValueDivisor` if defined\n            if (!_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(settings.rawValueDivisor) && settings.rawValueDivisor !== 0 && // Only divide if the `rawValueDivisor` option is set\n            value !== '' && value !== null) {\n                // Do not modify the `value` if it's an empty string or null\n                value /= settings.rawValueDivisor;\n            }\n\n            value = this._roundRawValue(value, settings);\n            value = value.replace(settings.decimalCharacter, '.'); // Here we need to convert back the decimal character to a period since `_roundValue` adds it in some cases\n            value = this._toLocale(value, settings.outputFormat, settings);\n\n            return value;\n        }\n\n        /**\n         * Unformat the given DOM element value, and set the resulting value back as the element value.\n         *\n         * @param {HTMLElement|HTMLInputElement} domElement\n         * @param {object} options\n         * @returns {*}\n         */\n\n    }, {\n        key: 'unformatAndSet',\n        value: function unformatAndSet(domElement) {\n            var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n            //FIXME test this\n            var unformattedValue = this.unformat(domElement, options);\n            _AutoNumericHelper2.default.setElementValue(domElement, unformattedValue);\n\n            return unformattedValue;\n        }\n\n        /**\n         * Unformat and localize the given formatted string with the given options. This returns a numeric string.\n         * It can also unformat and localize the given DOM element value with the given options and returns the unformatted numeric string.\n         * Note: This does *not* update that element value.\n         * This basically allows to get the localized value without first having to initialize an AutoNumeric object.\n         *\n         * @param {string|number|HTMLElement|HTMLInputElement} numericStringOrDomElement\n         * @param {object} settings\n         * @returns {*}\n         */\n\n    }, {\n        key: 'localize',\n        value: function localize(numericStringOrDomElement) {\n            var settings = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n            var value = void 0;\n            if (_AutoNumericHelper2.default.isElement(numericStringOrDomElement)) {\n                value = _AutoNumericHelper2.default.getElementValue(numericStringOrDomElement);\n            } else {\n                value = numericStringOrDomElement;\n            }\n\n            if (value === '') {\n                // This allows to be coherent when serializing forms with empty inputs. Fix issue #512.\n                return '';\n            }\n\n            if (_AutoNumericHelper2.default.isNull(settings)) {\n                settings = AutoNumeric.defaultSettings;\n            }\n\n            value = this.unformat(value, settings);\n\n            //XXX The following code is pretty close to the one you can find in `getLocalized()`, but different enough so we won't refactor it.\n            if (Number(value) === 0 && settings.leadingZero !== AutoNumeric.options.leadingZero.keep) {\n                value = '0';\n            }\n\n            var outputFormatToUse = void 0;\n            if (_AutoNumericHelper2.default.isNull(settings)) {\n                outputFormatToUse = settings.outputFormat;\n            } else {\n                outputFormatToUse = AutoNumeric.defaultSettings.outputFormat;\n            }\n\n            return this._toLocale(value, outputFormatToUse, settings);\n        }\n    }, {\n        key: 'localizeAndSet',\n        value: function localizeAndSet(domElement) {\n            var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n            //FIXME test this\n            var localizedValue = this.localize(domElement, options);\n            _AutoNumericHelper2.default.setElementValue(domElement, localizedValue);\n\n            return localizedValue;\n        }\n\n        /**\n         * Return `true` if the given DOM element has an AutoNumeric object that manages it.\n         * This function also accepts a selector string.\n         *\n         * @param {HTMLElement|string} domElementOrSelector Accepts either directly a DOM element to test, or a string selector (that will return one and only one element, if any)\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isManagedByAutoNumeric',\n        value: function isManagedByAutoNumeric(domElementOrSelector) {\n            //FIXME test this\n            return this._isInGlobalList(_AutoNumericHelper2.default.domElement(domElementOrSelector));\n        }\n\n        /**\n         * Return the AutoNumeric object that manages the given DOM element.\n         * This function also accepts a selector string.\n         *\n         * @param {HTMLElement|string} domElementOrSelector Accepts either directly a DOM element to test, or a string selector (that will return one and only one element, if any)\n         * @returns {null|AutoNumeric}\n         */\n\n    }, {\n        key: 'getAutoNumericElement',\n        value: function getAutoNumericElement(domElementOrSelector) {\n            var domElement = _AutoNumericHelper2.default.domElement(domElementOrSelector);\n\n            if (!this.isManagedByAutoNumeric(domElement)) {\n                return null;\n            }\n\n            return this._getFromGlobalList(domElement);\n        }\n\n        /**\n         * Set the given element value, and format it immediately.\n         * Return `null` if no AutoNumeric object is found, else, return the AutoNumeric object.\n         *\n         * @param {HTMLElement|string} domElementOrSelector Either a DOM element reference, or a selector string can be used\n         * @param {number|string|null} newValue The value must be a Number, a numeric string or `null` (if `emptyInputBehavior` is set to `'null'`)\n         * @param {object} options A settings object that will override the current settings. Note: the update is done only if the `newValue` is defined.\n         * @param {boolean} saveChangeToHistory If set to `true`, then the change is recorded in the history table\n         * @returns {AutoNumeric|null}\n         */\n\n    }, {\n        key: 'set',\n        value: function set(domElementOrSelector, newValue) {\n            var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n            var saveChangeToHistory = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;\n\n            var domElement = _AutoNumericHelper2.default.domElement(domElementOrSelector);\n\n            if (!this.isManagedByAutoNumeric(domElement)) {\n                var showWarnings = void 0;\n                if (!_AutoNumericHelper2.default.isNull(options) && options.hasOwnProperty('showWarnings')) {\n                    showWarnings = options.showWarnings;\n                } else {\n                    showWarnings = true;\n                }\n\n                _AutoNumericHelper2.default.warning('Impossible to find an AutoNumeric object for the given DOM element or selector.', showWarnings);\n\n                return null;\n            }\n\n            return this.getAutoNumericElement(domElement).set(newValue, options, saveChangeToHistory);\n        }\n\n        /**\n         * Return the unformatted value as a string from the given DOM element or query selector.\n         * This can also return `null` if `rawValue` is null.\n         *\n         * @param {HTMLElement|string} domElementOrSelector\n         * @param {function|null} callback\n         * @returns {string|null}\n         */\n\n    }, {\n        key: 'getNumericString',\n        value: function getNumericString(domElementOrSelector) {\n            var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n            return this._get(domElementOrSelector, 'getNumericString', callback);\n        }\n\n        /**\n         * Return the current formatted value of the AutoNumeric element as a string, from the given DOM element or query selector.\n         *\n         * @param {HTMLElement|string} domElementOrSelector\n         * @param {function|null} callback\n         * @returns {string}\n         */\n\n    }, {\n        key: 'getFormatted',\n        value: function getFormatted(domElementOrSelector) {\n            var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n            return this._get(domElementOrSelector, 'getFormatted', callback);\n        }\n\n        /**\n         * Return the element unformatted value as a real Javascript number, from the given DOM element or query selector.\n         * Warning: This can lead to precision problems with big numbers that should be stored as strings.\n         *\n         * @param {HTMLElement|string} domElementOrSelector\n         * @param {function|null} callback\n         * @returns {number|null}\n         */\n\n    }, {\n        key: 'getNumber',\n        value: function getNumber(domElementOrSelector) {\n            var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n            return this._get(domElementOrSelector, 'getNumber', callback);\n        }\n\n        /**\n         * DRY the code between the static `get*` functions\n         *\n         * @param {HTMLElement|string} domElementOrSelector\n         * @param {string} getFunction The name of the non-static `get*` function as a string\n         * @param {function|null} callback\n         * @returns {*}\n         * @private\n         */\n\n    }, {\n        key: '_get',\n        value: function _get(domElementOrSelector, getFunction) {\n            var callback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\n            var domElement = _AutoNumericHelper2.default.domElement(domElementOrSelector);\n\n            if (!this.isManagedByAutoNumeric(domElement)) {\n                _AutoNumericHelper2.default.throwError('Impossible to find an AutoNumeric object for the given DOM element or selector.');\n            }\n\n            return this.getAutoNumericElement(domElement)[getFunction](callback);\n        }\n\n        /**\n         * Returns the unformatted value following the `outputFormat` setting, from the given DOM element or query selector.\n         * See the non-static `getLocalized()` method documentation for more details.\n         *\n         * @param {HTMLElement|string} domElementOrSelector\n         * @param {null|string|function} forcedOutputFormat\n         * @param {function|null} callback\n         * @returns {*}\n         */\n\n    }, {\n        key: 'getLocalized',\n        value: function getLocalized(domElementOrSelector) {\n            var forcedOutputFormat = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n            var callback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\n            var domElement = _AutoNumericHelper2.default.domElement(domElementOrSelector);\n\n            if (!this.isManagedByAutoNumeric(domElement)) {\n                _AutoNumericHelper2.default.throwError('Impossible to find an AutoNumeric object for the given DOM element or selector.');\n            }\n\n            return this.getAutoNumericElement(domElement).getLocalized(forcedOutputFormat, callback);\n        }\n    }, {\n        key: '_stripAllNonNumberCharacters',\n        value: function _stripAllNonNumberCharacters(s, settings, stripZeros, isFocused) {\n            return this._stripAllNonNumberCharactersExceptCustomDecimalChar(s, settings, stripZeros, isFocused).replace(settings.decimalCharacter, '.');\n        }\n\n        /**\n         * Strip all unwanted non-number characters except the custom decimal character.\n         *\n         * It converts the custom negative sign and removes the positive sign (custom or not).\n         * This keeps :\n         * - the numbers,\n         * - the normal negative sign '-' if any,\n         * - and the *custom* decimal character.\n         *\n         * @param {string} s\n         * @param {object} settings\n         * @param {boolean} stripZeros If set to `false`, then the leading zero(s) are not stripped, otherwise if set to `true`, the `leadingZero` option is followed\n         * @param {boolean} isFocused If the element is focused, then this is `true`\n         * @returns {string|*}\n         */\n\n    }, {\n        key: '_stripAllNonNumberCharactersExceptCustomDecimalChar',\n        value: function _stripAllNonNumberCharactersExceptCustomDecimalChar(s, settings, stripZeros, isFocused) {\n            //XXX Note; this function is static since we need to pass a `settings` object when calling the static `AutoNumeric.format()` method\n            //TODO This function is called 10 times (sic!) on each key input, couldn't we lower that number? cf. issue #325\n            s = this._normalizeCurrencySuffixAndNegativeSignCharacters(s, settings);\n\n            // Then remove all the characters that are not numbers, the normal negative sign '-', or the custom decimal character (note: this also remove any custom positive sign)\n            s = s.replace(settings.allowedAutoStrip, '');\n\n            // Get only number string\n            var m = s.match(settings.numRegAutoStrip);\n            s = m ? [m[1], m[2], m[3]].join('') : '';\n\n            if (settings.leadingZero === AutoNumeric.options.leadingZero.allow || settings.leadingZero === AutoNumeric.options.leadingZero.keep) {\n                var negativeSign = '';\n\n                var _s$split = s.split(settings.decimalCharacter),\n                    _s$split2 = _slicedToArray(_s$split, 2),\n                    integerPart = _s$split2[0],\n                    decimalPart = _s$split2[1];\n\n                var modifiedIntegerPart = integerPart;\n                if (_AutoNumericHelper2.default.contains(modifiedIntegerPart, settings.negativeSignCharacter)) {\n                    negativeSign = settings.negativeSignCharacter;\n                    modifiedIntegerPart = modifiedIntegerPart.replace(settings.negativeSignCharacter, '');\n                }\n\n                // Strip leading zero on positive value if needed\n                if (negativeSign === '' && modifiedIntegerPart.length > settings.mIntPos && modifiedIntegerPart.charAt(0) === '0') {\n                    modifiedIntegerPart = modifiedIntegerPart.slice(1);\n                }\n\n                // Strip leading zero on negative value if needed\n                if (negativeSign !== '' && modifiedIntegerPart.length > settings.mIntNeg && modifiedIntegerPart.charAt(0) === '0') {\n                    modifiedIntegerPart = modifiedIntegerPart.slice(1);\n                }\n\n                s = '' + negativeSign + modifiedIntegerPart + (_AutoNumericHelper2.default.isUndefined(decimalPart) ? '' : settings.decimalCharacter + decimalPart);\n            }\n\n            if (stripZeros && settings.leadingZero === AutoNumeric.options.leadingZero.deny || !isFocused && settings.leadingZero === AutoNumeric.options.leadingZero.allow) {\n                s = s.replace(settings.stripReg, '$1$2');\n            }\n\n            return s;\n        }\n\n        /**\n         * Sets or removes brackets on negative values, depending on the focus state, which is passed as `isFocused`.\n         * The focus state is 'stored' in that object property.\n         *\n         * @param {string} value\n         * @param {object} settings\n         * @param {boolean} isFocused\n         * @returns {*}\n         */\n\n    }, {\n        key: '_toggleNegativeBracket',\n        value: function _toggleNegativeBracket(value, settings, isFocused) {\n            //XXX Note; this function is static since we need to pass a `settings` object when calling the static `AutoNumeric.format()` method\n            var result = void 0;\n            if (isFocused) {\n                result = this._removeBrackets(value, settings);\n            } else {\n                result = this._addBrackets(value, settings);\n            }\n\n            return result;\n        }\n\n        /**\n         * Add the bracket types specified in the `settings` object, to the given string `value`.\n         *\n         * @param {string} value\n         * @param {object} settings\n         * @returns {string}\n         * @private\n         */\n\n    }, {\n        key: '_addBrackets',\n        value: function _addBrackets(value, settings) {\n            if (_AutoNumericHelper2.default.isNull(settings.negativeBracketsTypeOnBlur)) {\n                return value;\n            }\n\n            return '' + settings.firstBracket + value.replace(settings.negativeSignCharacter, '') + settings.lastBracket;\n        }\n\n        /**\n         * Remove the bracket types specified in the `settings` object, from the given string `value`.\n         *\n         * @param {string} value\n         * @param {object} settings\n         * @param {boolean} rearrangeSignsAndValueOrder If set to `true`, then only the brackets are remove and a negative sign is added, without reordering the negative sign, currency symbol and value according to the settings.\n         * @returns {string}\n         * @private\n         */\n\n    }, {\n        key: '_removeBrackets',\n        value: function _removeBrackets(value, settings) {\n            var rearrangeSignsAndValueOrder = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;\n\n            var result = void 0;\n            if (!_AutoNumericHelper2.default.isNull(settings.negativeBracketsTypeOnBlur) && value.charAt(0) === settings.firstBracket) {\n                // Remove the brackets if they are present\n                result = value.replace(settings.firstBracket, '');\n                result = result.replace(settings.lastBracket, '');\n\n                // Add back the negative sign at the right place\n                if (rearrangeSignsAndValueOrder) {\n                    // First we need to remove the currency symbol from the value, since we want to be able to add back the negative sign at the right place (including between the value and the currency sign)\n                    result = result.replace(settings.currencySymbol, '');\n                    result = this._mergeCurrencySignNegativePositiveSignAndValue(result, settings, true, false); //TODO This assume the value is negative and non-empty. Is this always the case?\n                } else {\n                    // Here we only want to add the negative sign since we removed the brackets, without reordering\n                    result = '' + settings.negativeSignCharacter + result;\n                }\n            } else {\n                result = value;\n            }\n\n            return result;\n        }\n\n        /**\n         * Analyze the `negativeBracketsTypeOnBlur` options and keep track of the first and last bracket characters to use.\n         *\n         * @param {object} settings\n         * @private\n         */\n\n    }, {\n        key: '_setBrackets',\n        value: function _setBrackets(settings) {\n            if (_AutoNumericHelper2.default.isNull(settings.negativeBracketsTypeOnBlur)) {\n                settings.firstBracket = '';\n                settings.lastBracket = '';\n            } else {\n                // Use temporary variables to fix the MS Edge destructuring issue (see pull request #564)\n                var _settings$negativeBra3 = settings.negativeBracketsTypeOnBlur.split(','),\n                    _settings$negativeBra4 = _slicedToArray(_settings$negativeBra3, 2),\n                    firstBracket = _settings$negativeBra4[0],\n                    lastBracket = _settings$negativeBra4[1];\n\n                settings.firstBracket = firstBracket;\n                settings.lastBracket = lastBracket;\n            }\n        }\n\n        /**\n         * Return a number as a numeric string that can be typecast to a Number that Javascript will understand.\n         *\n         * This function returns the given string by stripping:\n         * - the currency sign (currencySymbol),\n         * - the grouping separators (digitalGroupSpacing),\n         * - the suffix text (suffixText),\n         * - the positive sign (positiveSignCharacter),\n         * - the brackets if any,\n         * - by replacing the negative sign character with an hyphen,\n         * - and by replacing the decimal character (decimalCharacter) by a dot.\n         *\n         * Lastly, it also put the negative sign back to its normal position if needed.\n         * Bonus; it converts any arabic numbers found to the latin ones.\n         *\n         * @param {string} s\n         * @param {object} settings\n         * @returns {string|void|*}\n         */\n\n    }, {\n        key: '_convertToNumericString',\n        value: function _convertToNumericString(s, settings) {\n            // Remove the custom brackets\n            s = this._removeBrackets(s, settings, false);\n            s = this._normalizeCurrencySuffixAndNegativeSignCharacters(s, settings);\n\n            // Remove the grouping separators (thousands separators usually)\n            s = s.replace(new RegExp('[' + settings.digitGroupSeparator + ']', 'g'), '');\n\n            // Replace the decimal character by a dot\n            if (settings.decimalCharacter !== '.') {\n                s = s.replace(settings.decimalCharacter, '.');\n            }\n\n            // Move the trailing negative sign, if any, to the usual leftmost position\n            if (_AutoNumericHelper2.default.isNegative(s) && s.lastIndexOf('-') === s.length - 1) {\n                s = s.replace('-', '');\n                s = '-' + s;\n            }\n\n            // Replace the custom positive sign\n            if (settings.showPositiveSign) {\n                s = s.replace(settings.positiveSignCharacter, '');\n            }\n\n            // Convert arabic numbers to latin ones, if any\n            var convertToNumber = settings.leadingZero !== AutoNumeric.options.leadingZero.keep;\n            var temp = _AutoNumericHelper2.default.arabicToLatinNumbers(s, convertToNumber, false, false);\n            if (!isNaN(temp)) {\n                s = temp.toString();\n            }\n\n            return s;\n        }\n\n        /**\n         * Removes the currency symbol and the suffix text from the given string, and replace the custom negative sign with an hyphen.\n         *\n         * @param {string} s\n         * @param {object} settings\n         * @returns {string | *}\n         * @private\n         */\n\n    }, {\n        key: '_normalizeCurrencySuffixAndNegativeSignCharacters',\n        value: function _normalizeCurrencySuffixAndNegativeSignCharacters(s, settings) {\n            s = String(s); // Typecast to to a string, in case that the given value is a number\n\n            // Remove the currency symbol\n            if (settings.currencySymbol !== AutoNumeric.options.currencySymbol.none) {\n                s = s.replace(settings.currencySymbol, '');\n            }\n\n            // Remove the suffixText\n            if (settings.suffixText !== AutoNumeric.options.suffixText.none) {\n                s = s.replace(settings.suffixText, '');\n            }\n\n            // Replace the custom negative sign with an hyphen\n            if (settings.negativeSignCharacter !== AutoNumeric.options.negativeSignCharacter.hyphen) {\n                s = s.replace(settings.negativeSignCharacter, '-');\n            }\n\n            return s;\n        }\n\n        /**\n         * Converts the ISO numeric string to the locale decimal and minus sign placement.\n         * See the \"outputFormat\" option definition for more details.\n         * Note: If the `outputFormat` is set to a number, the custom `negativeSignCharacter` is ignored.\n         *\n         * @param {string|null} value The unformatted value\n         * @param {string|null} locale\n         * @param {object} settings\n         * @returns {*}\n         */\n\n    }, {\n        key: '_toLocale',\n        value: function _toLocale(value, locale, settings) {\n            if (_AutoNumericHelper2.default.isNull(locale) || locale === AutoNumeric.options.outputFormat.string) {\n                return value;\n            }\n\n            var result = void 0;\n            switch (locale) {\n                case AutoNumeric.options.outputFormat.number:\n                    result = Number(value);\n                    break;\n                case AutoNumeric.options.outputFormat.dotNegative:\n                    result = _AutoNumericHelper2.default.isNegative(value) ? value.replace('-', '') + '-' : value;\n                    break;\n                case AutoNumeric.options.outputFormat.comma:\n                case AutoNumeric.options.outputFormat.negativeComma:\n                    result = value.replace('.', ',');\n                    break;\n                case AutoNumeric.options.outputFormat.commaNegative:\n                    result = value.replace('.', ',');\n                    result = _AutoNumericHelper2.default.isNegative(result) ? result.replace('-', '') + '-' : result;\n                    break;\n                // The default case\n                case AutoNumeric.options.outputFormat.dot:\n                case AutoNumeric.options.outputFormat.negativeDot:\n                    result = value;\n                    break;\n                default:\n                    _AutoNumericHelper2.default.throwError('The given outputFormat [' + locale + '] option is not recognized.');\n            }\n\n            if (locale !== AutoNumeric.options.outputFormat.number && settings.negativeSignCharacter !== '-') {\n                // Modify the default minus sign with the custom one, if any\n                result = result.replace('-', settings.negativeSignCharacter);\n            }\n\n            return result;\n        }\n    }, {\n        key: '_modifyNegativeSignAndDecimalCharacterForFormattedValue',\n        value: function _modifyNegativeSignAndDecimalCharacterForFormattedValue(s, settings) {\n            //XXX Note; this function is static since we need to pass a `settings` object when calling the static `AutoNumeric.format()` method\n            if (settings.negativeSignCharacter !== '-') {\n                s = s.replace('-', settings.negativeSignCharacter);\n            }\n\n            if (settings.decimalCharacter !== '.') {\n                s = s.replace('.', settings.decimalCharacter);\n            }\n\n            return s;\n        }\n\n        /**\n         * Return `true` if the given value is empty or is equal to the negative sign character defined in the given settings.\n         *\n         * @param {string} value\n         * @param {object} settings\n         * @returns {boolean}\n         * @private\n         */\n\n    }, {\n        key: '_isElementValueEmptyOrOnlyTheNegativeSign',\n        value: function _isElementValueEmptyOrOnlyTheNegativeSign(value, settings) {\n            return value === '' || value === settings.negativeSignCharacter;\n        }\n\n        /**\n         * Return the value with the currency symbol and the suffix text ordered according to the given settings.\n         *\n         * @param {string} value\n         * @param {object} settings\n         * @param {boolean} signOnEmpty\n         * @returns {*}\n         * @private\n         */\n\n    }, {\n        key: '_orderValueCurrencySymbolAndSuffixText',\n        value: function _orderValueCurrencySymbolAndSuffixText(value, settings, signOnEmpty) {\n            var result = void 0;\n            if (settings.emptyInputBehavior === AutoNumeric.options.emptyInputBehavior.always || signOnEmpty) {\n                switch (settings.negativePositiveSignPlacement) {\n                    case AutoNumeric.options.negativePositiveSignPlacement.left:\n                    case AutoNumeric.options.negativePositiveSignPlacement.prefix:\n                    case AutoNumeric.options.negativePositiveSignPlacement.none:\n                        result = value + settings.currencySymbol + settings.suffixText;\n                        break;\n                    default:\n                        result = settings.currencySymbol + value + settings.suffixText;\n                }\n            } else {\n                result = value;\n            }\n\n            return result;\n        }\n\n        /**\n         * Modify the input value by adding the group separators, as defined in the settings, and the negative brackets if needed.\n         *\n         * @param {string} inputValue The formatted value (ie. with the `decimalCharacter` defined in the settings, not the raw value)\n         * @param {object} settings\n         * @param {boolean} isFocused\n         * @param {number|string|null} currentRawValue The object current raw value (`this.rawValue`)\n         * @param {number|string|null} forcedRawValue If this is set, then this rawValue is used instead of the one passed through the `settings` object. This is useful is some very specific cases where we need to set the raw value *after* settings the formatted value, using the `_addGroupSeparators()` method.\n         * @returns {*}\n         */\n\n    }, {\n        key: '_addGroupSeparators',\n        value: function _addGroupSeparators(inputValue, settings, isFocused, currentRawValue) {\n            var forcedRawValue = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;\n\n            //TODO Test if `inputValue` === '', and return '' directly if that's the case,\n            //XXX Note; this function is static since we need to pass a `settings` object when calling the static `AutoNumeric.format()` method\n            var isValueNegative = void 0;\n            if (!_AutoNumericHelper2.default.isNull(forcedRawValue)) {\n                // Prefer directly testing if the raw value is negative in order for the test to be more performant than manipulating the formatted value\n                isValueNegative = forcedRawValue < 0;\n            } else {\n                isValueNegative = _AutoNumericHelper2.default.isNegative(inputValue, settings.negativeSignCharacter) || _AutoNumericHelper2.default.isNegativeWithBrackets(inputValue, settings.firstBracket, settings.lastBracket); // Test if the value is negative before removing the negative sign\n            }\n\n            inputValue = this._stripAllNonNumberCharactersExceptCustomDecimalChar(inputValue, settings, false, isFocused);\n\n            if (this._isElementValueEmptyOrOnlyTheNegativeSign(inputValue, settings)) {\n                return this._orderValueCurrencySymbolAndSuffixText(inputValue, settings, true);\n            }\n\n            var isZeroOrHasNoValue = _AutoNumericHelper2.default.isZeroOrHasNoValue(inputValue);\n\n            // Temporarily remove the negative sign if present\n            if (isValueNegative) {\n                inputValue = inputValue.replace('-', ''); // At this point the `inputValue` has been normalized with a 'normal' negative sign `'-'` //TODO Check that comment validity, since `_stripAllNonNumberCharactersExceptCustomDecimalChar` *does not* convert the negative sign\n            }\n\n            settings.digitalGroupSpacing = settings.digitalGroupSpacing.toString();\n            var digitalGroup = void 0;\n            switch (settings.digitalGroupSpacing) {\n                case AutoNumeric.options.digitalGroupSpacing.two:\n                    digitalGroup = /(\\d)((\\d)(\\d{2}?)+)$/;\n                    break;\n                case AutoNumeric.options.digitalGroupSpacing.twoScaled:\n                    digitalGroup = /(\\d)((?:\\d{2}){0,2}\\d{3}(?:(?:\\d{2}){2}\\d{3})*?)$/;\n                    break;\n                case AutoNumeric.options.digitalGroupSpacing.four:\n                    digitalGroup = /(\\d)((\\d{4}?)+)$/;\n                    break;\n                case AutoNumeric.options.digitalGroupSpacing.three:\n                default:\n                    digitalGroup = /(\\d)((\\d{3}?)+)$/;\n            }\n\n            // Splits the string at the decimal string\n\n            var _inputValue$split = inputValue.split(settings.decimalCharacter),\n                _inputValue$split2 = _slicedToArray(_inputValue$split, 2),\n                integerPart = _inputValue$split2[0],\n                decimalPart = _inputValue$split2[1];\n\n            if (settings.decimalCharacterAlternative && _AutoNumericHelper2.default.isUndefined(decimalPart)) {\n                var _inputValue$split3 = inputValue.split(settings.decimalCharacterAlternative);\n\n                var _inputValue$split4 = _slicedToArray(_inputValue$split3, 2);\n\n                integerPart = _inputValue$split4[0];\n                decimalPart = _inputValue$split4[1];\n            }\n\n            if (settings.digitGroupSeparator !== '') {\n                // Re-inserts the thousand separator via a regular expression\n                while (digitalGroup.test(integerPart)) {\n                    integerPart = integerPart.replace(digitalGroup, '$1' + settings.digitGroupSeparator + '$2');\n                }\n            }\n\n            // Find out how many decimal places should be kept, depending on the object state (isFocused)\n            var decimalPlacesToRoundTo = void 0;\n            if (isFocused) {\n                decimalPlacesToRoundTo = settings.decimalPlacesShownOnFocus;\n            } else {\n                decimalPlacesToRoundTo = settings.decimalPlacesShownOnBlur;\n            }\n\n            if (decimalPlacesToRoundTo !== 0 && !_AutoNumericHelper2.default.isUndefined(decimalPart)) {\n                if (decimalPart.length > decimalPlacesToRoundTo) {\n                    // Trim the excessive number of decimal places\n                    decimalPart = decimalPart.substring(0, decimalPlacesToRoundTo);\n                }\n\n                // Joins the whole number with the decimal value\n                inputValue = '' + integerPart + settings.decimalCharacter + decimalPart;\n            } else {\n                // Otherwise if it's an integer\n                inputValue = integerPart;\n            }\n\n            // Add back the negative/positive sign and the currency symbol, at the right positions\n            inputValue = AutoNumeric._mergeCurrencySignNegativePositiveSignAndValue(inputValue, settings, isValueNegative, isZeroOrHasNoValue); //TODO this function is called again in `_toggleNegativeBracket` if the brackets are removed; let's DRY this\n\n            if (_AutoNumericHelper2.default.isNull(forcedRawValue)) {\n                // If the raw value is not forced, use the default one from the settings object\n                forcedRawValue = currentRawValue;\n            }\n\n            // Toggle the negative sign and brackets\n            if (settings.negativeBracketsTypeOnBlur !== null && (forcedRawValue < 0 || _AutoNumericHelper2.default.isNegativeStrict(inputValue, settings.negativeSignCharacter))) {\n                inputValue = this._toggleNegativeBracket(inputValue, settings, isFocused);\n            }\n\n            var result = void 0;\n            if (settings.suffixText) {\n                result = '' + inputValue + settings.suffixText;\n            } else {\n                result = inputValue;\n            }\n\n            return result;\n        }\n\n        /**\n         * Return a semi-formatted string where the input value, the negative or positive sign, and the currency symbol are stitched together at the right positions, using the options set in the `settings` object.\n         * Note : the `inputValue` is usually not a numeric string since the grouping symbols are already added to it at this point.\n         *\n         * @param {string} inputValue\n         * @param {object} settings\n         * @param {boolean} isValueNegative\n         * @param {boolean} isZeroOrHasNoValue\n         * @returns {*}\n         * @throws\n         * @private\n         */\n\n    }, {\n        key: '_mergeCurrencySignNegativePositiveSignAndValue',\n        value: function _mergeCurrencySignNegativePositiveSignAndValue(inputValue, settings, isValueNegative, isZeroOrHasNoValue) {\n            var signToUse = '';\n            if (isValueNegative) {\n                signToUse = settings.negativeSignCharacter;\n            } else if (settings.showPositiveSign && !isZeroOrHasNoValue) {\n                signToUse = settings.positiveSignCharacter;\n            }\n\n            var result = void 0;\n            if (settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix) {\n                if (settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.none && (isValueNegative || !isValueNegative && settings.showPositiveSign && !isZeroOrHasNoValue)) {\n                    switch (settings.negativePositiveSignPlacement) {\n                        case AutoNumeric.options.negativePositiveSignPlacement.prefix:\n                        case AutoNumeric.options.negativePositiveSignPlacement.left:\n                            result = '' + signToUse + settings.currencySymbol + inputValue;\n                            break;\n                        case AutoNumeric.options.negativePositiveSignPlacement.right:\n                            result = '' + settings.currencySymbol + signToUse + inputValue;\n                            break;\n                        case AutoNumeric.options.negativePositiveSignPlacement.suffix:\n                            result = '' + settings.currencySymbol + inputValue + signToUse;\n                            break;\n                    }\n                } else {\n                    result = settings.currencySymbol + inputValue;\n                }\n            } else if (settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) {\n                if (settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.none && (isValueNegative || !isValueNegative && settings.showPositiveSign && !isZeroOrHasNoValue)) {\n                    switch (settings.negativePositiveSignPlacement) {\n                        case AutoNumeric.options.negativePositiveSignPlacement.suffix:\n                        case AutoNumeric.options.negativePositiveSignPlacement.right:\n                            result = '' + inputValue + settings.currencySymbol + signToUse;\n                            break;\n                        case AutoNumeric.options.negativePositiveSignPlacement.left:\n                            result = '' + inputValue + signToUse + settings.currencySymbol;\n                            break;\n                        case AutoNumeric.options.negativePositiveSignPlacement.prefix:\n                            result = '' + signToUse + inputValue + settings.currencySymbol;\n                            break;\n                    }\n                } else {\n                    result = inputValue + settings.currencySymbol;\n                }\n            }\n\n            return result;\n        }\n    }, {\n        key: '_truncateZeros',\n        value: function _truncateZeros(roundedInputValue, decimalPlacesNeeded) {\n            var regex = void 0;\n            switch (decimalPlacesNeeded) {\n                case 0:\n                    // Prevents padding - removes trailing zeros until the first significant digit is encountered\n                    regex = /(\\.(?:\\d*[1-9])?)0*$/;\n                    break;\n                case 1:\n                    // Allows padding when decimalPlacesNeeded equals one - leaves one zero trailing the decimal character\n                    regex = /(\\.\\d(?:\\d*[1-9])?)0*$/;\n                    break;\n                default:\n                    // Removes superfluous zeros after the decimalPlacesNeeded length\n                    regex = new RegExp('(\\\\.\\\\d{' + decimalPlacesNeeded + '}(?:\\\\d*[1-9])?)0*');\n            }\n\n            // If there are no decimal places, we don't need a decimal point at the end\n            roundedInputValue = roundedInputValue.replace(regex, '$1');\n            if (decimalPlacesNeeded === 0) {\n                roundedInputValue = roundedInputValue.replace(/\\.$/, '');\n            }\n\n            return roundedInputValue;\n        }\n\n        /**\n         * Round the given `value` with the number of decimal places to keep for the raw value.\n         *\n         * @param {string|null} value An unformatted numeric value\n         * @param {object} settings\n         * @returns {*}\n         * @private\n         */\n\n    }, {\n        key: '_roundRawValue',\n        value: function _roundRawValue(value, settings) {\n            return this._roundValue(value, settings, settings.decimalPlacesRawValue);\n        }\n\n        /**\n         * Round the given `value` with the number of decimal places to show for the element if focused.\n         *\n         * @param {string|null} value An unformatted numeric value\n         * @param {object} settings\n         * @returns {*}\n         * @private\n         */\n\n    }, {\n        key: '_roundFormattedValueShownOnFocus',\n        value: function _roundFormattedValueShownOnFocus(value, settings) {\n            return this._roundValue(value, settings, Number(settings.decimalPlacesShownOnFocus));\n        }\n\n        /**\n         * Round the given `value` with the number of decimal places to show for the element if unfocused.\n         *\n         * @param {string|null} value An unformatted numeric value\n         * @param {object} settings\n         * @returns {*}\n         * @private\n         */\n\n    }, {\n        key: '_roundFormattedValueShownOnBlur',\n        value: function _roundFormattedValueShownOnBlur(value, settings) {\n            return this._roundValue(value, settings, Number(settings.decimalPlacesShownOnBlur));\n        }\n\n        /**\n         * Round the given `value` with the number of decimal places to show for the element based on the value of isFocused.\n         *\n         * @param {string|null} value An unformatted numeric value\n         * @param {object} settings\n         * @param {boolean} isFocused\n         * @returns {*}\n         * @private\n         */\n\n    }, {\n        key: '_roundFormattedValueShownOnFocusOrBlur',\n        value: function _roundFormattedValueShownOnFocusOrBlur(value, settings, isFocused) {\n            if (isFocused) {\n                return this._roundFormattedValueShownOnFocus(value, settings);\n            } else {\n                return this._roundFormattedValueShownOnBlur(value, settings);\n            }\n        }\n\n        /**\n         * Round the input value using the rounding method defined in the settings.\n         * This function accepts multiple rounding methods. See the documentation for more details about those.\n         *\n         * Note : This is handled as text since JavaScript math functions can return inaccurate values.\n         *\n         * @param {string|null} inputValue An unformatted numeric value\n         * @param {object} settings\n         * @param {int} decimalPlacesToRoundTo\n         * @returns {*}\n         */\n\n    }, {\n        key: '_roundValue',\n        value: function _roundValue(inputValue, settings, decimalPlacesToRoundTo) {\n            //XXX Note; this function is static since we need to pass a `settings` object when calling the static `AutoNumeric.format()` method\n            if (_AutoNumericHelper2.default.isNull(inputValue)) {\n                // Prevent rounding a `null` value\n                return inputValue;\n            }\n\n            //TODO Divide this function to make it easier to understand\n            inputValue = inputValue === '' ? '0' : inputValue.toString();\n            if (settings.roundingMethod === AutoNumeric.options.roundingMethod.toNearest05 || settings.roundingMethod === AutoNumeric.options.roundingMethod.toNearest05Alt || settings.roundingMethod === AutoNumeric.options.roundingMethod.upToNext05 || settings.roundingMethod === AutoNumeric.options.roundingMethod.downToNext05) {\n                return this._roundCloseTo05(inputValue, settings);\n            }\n\n            var _AutoNumeric$_prepare = AutoNumeric._prepareValueForRounding(inputValue, settings),\n                _AutoNumeric$_prepare2 = _slicedToArray(_AutoNumeric$_prepare, 2),\n                negativeSign = _AutoNumeric$_prepare2[0],\n                preparedValue = _AutoNumeric$_prepare2[1];\n\n            inputValue = preparedValue;\n\n            var decimalCharacterPosition = inputValue.lastIndexOf('.');\n            var inputValueHasNoDot = decimalCharacterPosition === -1; // No dot character is found in the `inputValue`\n\n            var _inputValue$split5 = inputValue.split('.'),\n                _inputValue$split6 = _slicedToArray(_inputValue$split5, 2),\n                decimalPart = _inputValue$split6[1]; // Here the decimal character is always a period '.'\n\n\n            var hasDecimals = decimalPart > 0;\n\n            // If no decimals are detected\n            if (!hasDecimals && (settings.allowDecimalPadding === AutoNumeric.options.allowDecimalPadding.never || settings.allowDecimalPadding === AutoNumeric.options.allowDecimalPadding.floats)) {\n                return Number(inputValue) === 0 ? inputValue : '' + negativeSign + inputValue;\n            }\n\n            // Else there are some decimal places that may need to be rounded\n            // Sets the truncate zero method\n            var temporaryDecimalPlacesOverride = void 0;\n            if (settings.allowDecimalPadding === AutoNumeric.options.allowDecimalPadding.always || settings.allowDecimalPadding === AutoNumeric.options.allowDecimalPadding.floats) {\n                temporaryDecimalPlacesOverride = decimalPlacesToRoundTo;\n            } else {\n                temporaryDecimalPlacesOverride = 0;\n            }\n\n            // Define the decimal position to use (use the very last position if there are no dot in the initial inputValue)\n            var decimalPositionToUse = inputValueHasNoDot ? inputValue.length - 1 : decimalCharacterPosition;\n            // Checks decimal places to determine if rounding is required\n            var checkDecimalPlaces = inputValue.length - 1 - decimalPositionToUse;\n            var inputValueRounded = '';\n\n            // Check if no rounding is required\n            if (checkDecimalPlaces <= decimalPlacesToRoundTo) {\n                // Check if we need to pad with zeros\n                inputValueRounded = inputValue;\n                if (checkDecimalPlaces < temporaryDecimalPlacesOverride) {\n                    if (inputValueHasNoDot) {\n                        inputValueRounded = '' + inputValueRounded + settings.decimalCharacter;\n                    }\n\n                    var zeros = '000000'; //TODO Change that string with a longer one to prevent having to loop numerous times in the next `while` statement?\n                    while (checkDecimalPlaces < temporaryDecimalPlacesOverride) {\n                        zeros = zeros.substring(0, temporaryDecimalPlacesOverride - checkDecimalPlaces);\n                        inputValueRounded += zeros;\n                        checkDecimalPlaces += zeros.length;\n                    }\n                } else if (checkDecimalPlaces > temporaryDecimalPlacesOverride) {\n                    inputValueRounded = this._truncateZeros(inputValueRounded, temporaryDecimalPlacesOverride);\n                } else if (checkDecimalPlaces === 0 && temporaryDecimalPlacesOverride === 0) {\n                    // Remove any trailing dot, if any\n                    inputValueRounded = inputValueRounded.replace(/\\.$/, '');\n                }\n\n                return Number(inputValueRounded) === 0 ? inputValueRounded : '' + negativeSign + inputValueRounded;\n            }\n\n            // Rounded length of the string after rounding\n            var roundedStrLength = void 0;\n            if (inputValueHasNoDot) {\n                roundedStrLength = decimalPlacesToRoundTo - 1;\n            } else {\n                roundedStrLength = Number(decimalPlacesToRoundTo) + Number(decimalCharacterPosition);\n            }\n\n            var lastDigit = Number(inputValue.charAt(roundedStrLength + 1));\n            var inputValueArray = inputValue.substring(0, roundedStrLength + 1).split('');\n            var odd = void 0;\n            if (inputValue.charAt(roundedStrLength) === '.') {\n                odd = inputValue.charAt(roundedStrLength - 1) % 2;\n            } else {\n                odd = inputValue.charAt(roundedStrLength) % 2;\n            }\n\n            if (this._shouldRoundUp(lastDigit, settings, negativeSign, odd)) {\n                // Round up the last digit if required, and continue until no more 9's are found\n                for (var i = inputValueArray.length - 1; i >= 0; i -= 1) {\n                    if (inputValueArray[i] !== '.') {\n                        inputValueArray[i] = +inputValueArray[i] + 1;\n                        if (inputValueArray[i] < 10) {\n                            break;\n                        }\n\n                        if (i > 0) {\n                            inputValueArray[i] = '0';\n                        }\n                    }\n                }\n            }\n\n            // Reconstruct the string, converting any 10's to 0's\n            inputValueArray = inputValueArray.slice(0, roundedStrLength + 1);\n\n            // Return the rounded value\n            inputValueRounded = this._truncateZeros(inputValueArray.join(''), temporaryDecimalPlacesOverride);\n\n            return Number(inputValueRounded) === 0 ? inputValueRounded : '' + negativeSign + inputValueRounded;\n        }\n\n        /**\n         * Round the `value` when the rounding method deals with '.05'\n         *\n         * @param {string} value\n         * @param {object} settings\n         * @returns {string}\n         * @private\n         */\n\n    }, {\n        key: '_roundCloseTo05',\n        value: function _roundCloseTo05(value, settings) {\n            switch (settings.roundingMethod) {\n                case AutoNumeric.options.roundingMethod.toNearest05:\n                case AutoNumeric.options.roundingMethod.toNearest05Alt:\n                    value = (Math.round(value * 20) / 20).toString();\n                    break;\n                case AutoNumeric.options.roundingMethod.upToNext05:\n                    value = (Math.ceil(value * 20) / 20).toString();\n                    break;\n                default:\n                    value = (Math.floor(value * 20) / 20).toString();\n            }\n\n            var result = void 0;\n            if (!_AutoNumericHelper2.default.contains(value, '.')) {\n                result = value + '.00';\n            } else if (value.length - value.indexOf('.') < 3) {\n                result = value + '0';\n            } else {\n                result = value;\n            }\n\n            return result;\n        }\n\n        /**\n         * Modify the given `value` in order to make it usable for the rest of the rounding function.\n         * This convert the `value` to a positive one, trim any leading zeros and make sure it does not starts with a leading dot.\n         *\n         * @param {string} value The unformatted value\n         * @param {object} settings\n         * @returns {[string, string]}\n         * @private\n         */\n\n    }, {\n        key: '_prepareValueForRounding',\n        value: function _prepareValueForRounding(value, settings) {\n            // Checks if `inputValue` is a negative value\n            var negativeSign = '';\n            if (_AutoNumericHelper2.default.isNegativeStrict(value, '-')) {\n                // The value being unformatted, we check for the minus sign\n                negativeSign = '-';\n\n                // Removes the negative sign that will be added back later if required\n                value = value.replace('-', '');\n            }\n\n            // Append a zero if the first character is not a digit (then it is likely a dot)\n            if (!value.match(/^\\d/)) {\n                value = '0' + value;\n            }\n\n            // Determines if the value is equal to zero. If it is, remove the negative sign\n            if (Number(value) === 0) {\n                negativeSign = '';\n            }\n\n            // Trims leading zero's as needed\n            if (Number(value) > 0 && settings.leadingZero !== AutoNumeric.options.leadingZero.keep || value.length > 0 && settings.leadingZero === AutoNumeric.options.leadingZero.allow) {\n                value = value.replace(/^0*(\\d)/, '$1');\n            }\n\n            return [negativeSign, value];\n        }\n\n        /**\n         * Return `true` if a round up should be done given the last digit, the settings and other information about the value.\n         *\n         * @param {number} lastDigit\n         * @param {object} settings\n         * @param {string} negativeSign This variable comes from `_prepareValueForRounding()`, which return `'-'` if the initial value was negative\n         * @param {number} odd\n         * @returns {boolean}\n         * @private\n         */\n\n    }, {\n        key: '_shouldRoundUp',\n        value: function _shouldRoundUp(lastDigit, settings, negativeSign, odd) {\n            return lastDigit > 4 && settings.roundingMethod === AutoNumeric.options.roundingMethod.halfUpSymmetric || // Round half up symmetric\n            lastDigit > 4 && settings.roundingMethod === AutoNumeric.options.roundingMethod.halfUpAsymmetric && negativeSign === '' || // Round half up asymmetric positive values\n            lastDigit > 5 && settings.roundingMethod === AutoNumeric.options.roundingMethod.halfUpAsymmetric && negativeSign === '-' || // Round half up asymmetric negative values\n            lastDigit > 5 && settings.roundingMethod === AutoNumeric.options.roundingMethod.halfDownSymmetric || // Round half down symmetric\n            lastDigit > 5 && settings.roundingMethod === AutoNumeric.options.roundingMethod.halfDownAsymmetric && negativeSign === '' || // Round half down asymmetric positive values\n            lastDigit > 4 && settings.roundingMethod === AutoNumeric.options.roundingMethod.halfDownAsymmetric && negativeSign === '-' || // Round half down asymmetric negative values\n            lastDigit > 5 && settings.roundingMethod === AutoNumeric.options.roundingMethod.halfEvenBankersRounding || lastDigit === 5 && settings.roundingMethod === AutoNumeric.options.roundingMethod.halfEvenBankersRounding && odd === 1 || lastDigit > 0 && settings.roundingMethod === AutoNumeric.options.roundingMethod.toCeilingTowardPositiveInfinity && negativeSign === '' || lastDigit > 0 && settings.roundingMethod === AutoNumeric.options.roundingMethod.toFloorTowardNegativeInfinity && negativeSign === '-' || lastDigit > 0 && settings.roundingMethod === AutoNumeric.options.roundingMethod.upRoundAwayFromZero; // Round up away from zero\n        }\n\n        /**\n         * Truncates the decimal part of a number to the given number of decimal places `decimalPlacesToRoundTo`.\n         *\n         * @param {string} value\n         * @param {object} settings\n         * @param {boolean} isPaste\n         * @param {int} decimalPlacesToRoundTo\n         * @returns {*}\n         */\n\n    }, {\n        key: '_truncateDecimalPlaces',\n        value: function _truncateDecimalPlaces(value, settings, isPaste, decimalPlacesToRoundTo) {\n            if (isPaste) {\n                value = this._roundFormattedValueShownOnFocus(value, settings);\n            }\n\n            var _value$split = value.split(settings.decimalCharacter),\n                _value$split2 = _slicedToArray(_value$split, 2),\n                integerPart = _value$split2[0],\n                decimalPart = _value$split2[1];\n\n            // Truncate the decimal part to the satisfying length since we would round it anyway\n\n\n            if (decimalPart && decimalPart.length > decimalPlacesToRoundTo) {\n                if (decimalPlacesToRoundTo > 0) {\n                    var modifiedDecimalPart = decimalPart.substring(0, decimalPlacesToRoundTo);\n                    value = '' + integerPart + settings.decimalCharacter + modifiedDecimalPart;\n                } else {\n                    value = integerPart;\n                }\n            }\n\n            return value;\n        }\n\n        /**\n         * Check that the number satisfy the format conditions\n         * and lays between settings.minimumValue and settings.maximumValue\n         * and the string length does not exceed the digits in settings.minimumValue and settings.maximumValue\n         *\n         * @param {string} value\n         * @param {object} settings\n         * @returns {*}\n         */\n\n    }, {\n        key: '_checkIfInRangeWithOverrideOption',\n        value: function _checkIfInRangeWithOverrideOption(value, settings) {\n            if (_AutoNumericHelper2.default.isNull(value) && settings.emptyInputBehavior === AutoNumeric.options.emptyInputBehavior.null) {\n                // When the `null` value is accepted as the `rawValue`, the limits are ignored\n                return [true, true];\n            }\n\n            value = value.toString();\n            value = value.replace(',', '.');\n            var minParse = _AutoNumericHelper2.default.parseStr(settings.minimumValue);\n            var maxParse = _AutoNumericHelper2.default.parseStr(settings.maximumValue);\n            var valParse = _AutoNumericHelper2.default.parseStr(value);\n\n            var result = void 0;\n            switch (settings.overrideMinMaxLimits) {\n                case AutoNumeric.options.overrideMinMaxLimits.floor:\n                    result = [_AutoNumericHelper2.default.testMinMax(minParse, valParse) > -1, true];\n                    break;\n                case AutoNumeric.options.overrideMinMaxLimits.ceiling:\n                    result = [true, _AutoNumericHelper2.default.testMinMax(maxParse, valParse) < 1];\n                    break;\n                case AutoNumeric.options.overrideMinMaxLimits.ignore:\n                    result = [true, true];\n                    break;\n                default:\n                    result = [_AutoNumericHelper2.default.testMinMax(minParse, valParse) > -1, _AutoNumericHelper2.default.testMinMax(maxParse, valParse) < 1];\n            }\n\n            return result;\n        }\n    }, {\n        key: '_readCookie',\n        value: function _readCookie(name) {\n            var nameEQ = name + '=';\n            var ca = document.cookie.split(';');\n            var c = '';\n            for (var i = 0; i < ca.length; i += 1) {\n                c = ca[i];\n                while (c.charAt(0) === ' ') {\n                    c = c.substring(1, c.length);\n                }\n                if (c.indexOf(nameEQ) === 0) {\n                    return c.substring(nameEQ.length, c.length);\n                }\n            }\n\n            return null;\n        }\n\n        /**\n         * Test if sessionStorage is supported.\n         * This is taken from Modernizr.\n         *\n         * @returns {boolean}\n         */\n\n    }, {\n        key: '_storageTest',\n        value: function _storageTest() {\n            var mod = 'modernizr';\n            try {\n                sessionStorage.setItem(mod, mod);\n                sessionStorage.removeItem(mod);\n                return true;\n            } catch (e) {\n                return false;\n            }\n        }\n    }, {\n        key: '_correctNegativePositiveSignPlacementOption',\n        value: function _correctNegativePositiveSignPlacementOption(settings) {\n            //XXX Note; this function is static since we need to pass a `settings` object when calling the static `AutoNumeric.format()` method\n            // If negativePositiveSignPlacement is already set, we do not overwrite it\n            if (!_AutoNumericHelper2.default.isNull(settings.negativePositiveSignPlacement)) {\n                return;\n            }\n\n            if (!_AutoNumericHelper2.default.isUndefined(settings) && _AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(settings.negativePositiveSignPlacement) && !_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(settings.currencySymbol)) {\n                switch (settings.currencySymbolPlacement) {\n                    case AutoNumeric.options.currencySymbolPlacement.suffix:\n                        settings.negativePositiveSignPlacement = AutoNumeric.options.negativePositiveSignPlacement.prefix; // Default -1,234.56 €\n                        break;\n                    case AutoNumeric.options.currencySymbolPlacement.prefix:\n                        settings.negativePositiveSignPlacement = AutoNumeric.options.negativePositiveSignPlacement.left; // Default -$1,234.56\n                        break;\n                    default:\n                    //\n                }\n            } else {\n                // Sets the default value if `negativePositiveSignPlacement` is `null`\n                settings.negativePositiveSignPlacement = AutoNumeric.options.negativePositiveSignPlacement.left;\n            }\n        }\n\n        /**\n         * Correct the `caretPositionOnFocus` and `selectOnFocus` options, since setting both leads to a conflict.\n         * This method directly modifies the `options` object passed as a parameter, then returns it.\n         * It returns `null` if the given option is `null`.\n         *\n         * @param {object} options The options passed as an argument by the user\n         * @returns {object|null}\n         * @private\n         */\n\n    }, {\n        key: '_correctCaretPositionOnFocusAndSelectOnFocusOptions',\n        value: function _correctCaretPositionOnFocusAndSelectOnFocusOptions(options) {\n            if (_AutoNumericHelper2.default.isNull(options)) {\n                return null;\n            }\n\n            // If the user has set the `caretPositionOnFocus` option, do not set `selectOnFocus` to `true` by default\n            if (!_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(options.caretPositionOnFocus) && _AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(options.selectOnFocus)) {\n                options.selectOnFocus = AutoNumeric.options.selectOnFocus.doNotSelect;\n            }\n\n            // If the user has set the `selectOnFocus` option to `true`, set `caretPositionOnFocus` to `doNoForceCaretPosition`\n            if (_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(options.caretPositionOnFocus) && !_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(options.selectOnFocus) && options.selectOnFocus === AutoNumeric.options.selectOnFocus.select) {\n                options.caretPositionOnFocus = AutoNumeric.options.caretPositionOnFocus.doNoForceCaretPosition;\n            }\n\n            return options;\n        }\n\n        /**\n         * Calculate the number de decimal places to be used by the AutoNumeric object, for each of its state, and for its formatted and raw value.\n         * By default, the `rawValue` precision is the same as the formatted value one.\n         *\n         * This method is called during the AutoNumeric object initialization. This assumes some internal variable state.\n         *\n         * This methods set the following options accordingly to their own value and the mandatory `decimalPlaces` option:\n         * - decimalPlacesRawValue     (nullable)\n         * - decimalPlacesShownOnBlur  (nullable)\n         * - decimalPlacesShownOnFocus (nullable)\n         *\n         * Note: the `decimalPlaces` option is only used here and only serve to define those three previous options value.\n         * AutoNumeric will then *only* use `decimalPlacesRawValue`, `decimalPlacesShownOnBlur` and `decimalPlacesShownOnFocus` from there.\n         *\n         * This methods directly modifies the `settings` object passed as a parameter.\n         *\n         * @param {object} settings This is an object with the new settings to use.\n         * @private\n         */\n\n    }, {\n        key: '_calculateDecimalPlacesOnInit',\n        value: function _calculateDecimalPlacesOnInit(settings) {\n            // Check the `decimalPlaces*` options and output any warnings as needed, before modifying those options\n            this._validateDecimalPlacesRawValue(settings);\n\n            // Initialization phase\n            //XXX This assumes at this stage, `settings.decimalPlaces` as been set from the default options\n\n            // Overwrite the `decimalPlaces*` values if the `decimalPlaces*` options are not set in the `settings`\n            // Sets `decimalPlacesShownOnBlur` (previously known as `scaleDecimalPlaces`)\n            if (settings.decimalPlacesShownOnFocus === AutoNumeric.options.decimalPlacesShownOnFocus.useDefault) {\n                settings.decimalPlacesShownOnFocus = settings.decimalPlaces;\n            }\n\n            if (settings.decimalPlacesShownOnBlur === AutoNumeric.options.decimalPlacesShownOnBlur.useDefault) {\n                settings.decimalPlacesShownOnBlur = settings.decimalPlaces;\n            }\n\n            if (settings.decimalPlacesRawValue === AutoNumeric.options.decimalPlacesRawValue.useDefault) {\n                settings.decimalPlacesRawValue = settings.decimalPlaces;\n            }\n\n            // Add the additional decimal places to the raw value\n            var additionalDecimalPlacesRawValue = 0;\n            if (settings.rawValueDivisor && settings.rawValueDivisor !== AutoNumeric.options.rawValueDivisor.none) {\n                additionalDecimalPlacesRawValue = String(settings.rawValueDivisor).length - 1; // ie. Dividing by '100' adds 2 decimal places to the needed precision\n                if (additionalDecimalPlacesRawValue < 0) {\n                    additionalDecimalPlacesRawValue = 0;\n                }\n            }\n\n            settings.decimalPlacesRawValue = Math.max(Math.max(settings.decimalPlacesShownOnBlur, settings.decimalPlacesShownOnFocus) + additionalDecimalPlacesRawValue, Number(settings.originalDecimalPlacesRawValue) + additionalDecimalPlacesRawValue);\n        }\n\n        /**\n         * Recalculate the number de decimal places to be used by the AutoNumeric object, for each of its state, and for its formatted and raw value.\n         * By default, the `rawValue` precision is the same as the formatted value one.\n         *\n         * This method is close to the one called during initialization, `_calculateDecimalPlacesOnInit()`, but with slight difference so that the `decimalPlaces*` options are correctly updated as needed.\n         *\n         * This methods set the following options accordingly to their own value and the mandatory `decimalPlaces` option:\n         * - decimalPlacesRawValue     (nullable)\n         * - decimalPlacesShownOnBlur  (nullable)\n         * - decimalPlacesShownOnFocus (nullable)\n         *\n         * Note: the `decimalPlaces` option is only used here and only serve to define those three previous options value.\n         * AutoNumeric will then *only* use `decimalPlacesRawValue`, `decimalPlacesShownOnBlur` and `decimalPlacesShownOnFocus` from there.\n         *\n         * This methods directly modifies the `settings` object passed as a parameter.\n         *\n         * @param {object} settings This is an object with the new settings to use.\n         * @param {object} currentSettings This is the current settings (`this.settings`) used by the element.\n         * @private\n         */\n\n    }, {\n        key: '_calculateDecimalPlacesOnUpdate',\n        value: function _calculateDecimalPlacesOnUpdate(settings) {\n            var currentSettings = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n            // Check the `decimalPlaces*` options and output any warnings as needed, before modifying those options\n            this._validateDecimalPlacesRawValue(settings);\n\n            // Update phase\n            if (_AutoNumericHelper2.default.isNull(currentSettings)) {\n                _AutoNumericHelper2.default.throwError('When updating the settings, the previous ones should be passed as an argument.');\n            }\n\n            var decimalPlacesInOptions = 'decimalPlaces' in settings;\n            if (!(decimalPlacesInOptions || 'decimalPlacesRawValue' in settings || 'decimalPlacesShownOnFocus' in settings || 'decimalPlacesShownOnBlur' in settings || 'rawValueDivisor' in settings)) {\n                // Do Nothing if no decimal places-related options are modified\n                return;\n            }\n\n            // Overwrite the `decimalPlaces*` values if the `decimalPlaces*` options are not set in the `settings`\n            if (decimalPlacesInOptions) {\n                if (!('decimalPlacesShownOnFocus' in settings) || settings.decimalPlacesShownOnFocus === AutoNumeric.options.decimalPlacesShownOnFocus.useDefault) {\n                    settings.decimalPlacesShownOnFocus = settings.decimalPlaces;\n                }\n\n                if (!('decimalPlacesShownOnBlur' in settings) || settings.decimalPlacesShownOnBlur === AutoNumeric.options.decimalPlacesShownOnBlur.useDefault) {\n                    settings.decimalPlacesShownOnBlur = settings.decimalPlaces;\n                }\n\n                if (!('decimalPlacesRawValue' in settings) || settings.decimalPlacesRawValue === AutoNumeric.options.decimalPlacesRawValue.useDefault) {\n                    settings.decimalPlacesRawValue = settings.decimalPlaces;\n                }\n            } else {\n                if (_AutoNumericHelper2.default.isUndefined(settings.decimalPlacesShownOnFocus)) {\n                    settings.decimalPlacesShownOnFocus = currentSettings.decimalPlacesShownOnFocus;\n                }\n\n                if (_AutoNumericHelper2.default.isUndefined(settings.decimalPlacesShownOnBlur)) {\n                    settings.decimalPlacesShownOnBlur = currentSettings.decimalPlacesShownOnBlur;\n                }\n            }\n\n            // Add the additional decimal places to the raw value\n            var additionalDecimalPlacesRawValue = 0;\n            if (settings.rawValueDivisor && settings.rawValueDivisor !== AutoNumeric.options.rawValueDivisor.none) {\n                additionalDecimalPlacesRawValue = String(settings.rawValueDivisor).length - 1; // ie. Dividing by '100' adds 2 decimal places to the needed precision\n                if (additionalDecimalPlacesRawValue < 0) {\n                    additionalDecimalPlacesRawValue = 0;\n                }\n            }\n\n            if (!settings.decimalPlaces && !settings.decimalPlacesRawValue) {\n                settings.decimalPlacesRawValue = Math.max(Math.max(settings.decimalPlacesShownOnBlur, settings.decimalPlacesShownOnFocus) + additionalDecimalPlacesRawValue, Number(currentSettings.originalDecimalPlacesRawValue) + additionalDecimalPlacesRawValue);\n            } else {\n                settings.decimalPlacesRawValue = Math.max(Math.max(settings.decimalPlacesShownOnBlur, settings.decimalPlacesShownOnFocus) + additionalDecimalPlacesRawValue, Number(settings.decimalPlacesRawValue) + additionalDecimalPlacesRawValue);\n            }\n        }\n    }, {\n        key: '_cachesUsualRegularExpressions',\n        value: function _cachesUsualRegularExpressions(settings, regex) {\n            // Test if there is a negative character in the string\n            var negativeSignReg = void 0;\n            if (settings.negativeSignCharacter !== AutoNumeric.options.negativeSignCharacter.hyphen) {\n                negativeSignReg = '([-\\\\' + settings.negativeSignCharacter + ']?)';\n            } else {\n                negativeSignReg = '(-?)';\n            }\n\n            regex.aNegRegAutoStrip = negativeSignReg;\n            settings.allowedAutoStrip = new RegExp('[^-0123456789\\\\' + settings.decimalCharacter + ']', 'g');\n            settings.numRegAutoStrip = new RegExp(negativeSignReg + '(?:\\\\' + settings.decimalCharacter + '?([0-9]+\\\\' + settings.decimalCharacter + '[0-9]+)|([0-9]*(?:\\\\' + settings.decimalCharacter + '[0-9]*)?))');\n\n            // Using this regex version `^${regex.aNegRegAutoStrip}0*(\\\\d|$)` entirely clear the input on blur\n            settings.stripReg = new RegExp('^' + regex.aNegRegAutoStrip + '0*([0-9])');\n        }\n    }, {\n        key: '_convertOldOptionsToNewOnes',\n        value: function _convertOldOptionsToNewOnes(options) {\n            //TODO Delete this function once the old options are not used anymore\n            var oldOptionsConverter = {\n                // Old option names, with their corresponding new names\n                aSep: 'digitGroupSeparator',\n                nSep: 'showOnlyNumbersOnFocus',\n                dGroup: 'digitalGroupSpacing',\n                aDec: 'decimalCharacter',\n                altDec: 'decimalCharacterAlternative',\n                aSign: 'currencySymbol',\n                pSign: 'currencySymbolPlacement',\n                pNeg: 'negativePositiveSignPlacement',\n                aSuffix: 'suffixText',\n                oLimits: 'overrideMinMaxLimits',\n                vMax: 'maximumValue',\n                vMin: 'minimumValue',\n                mDec: 'decimalPlacesOverride',\n                eDec: 'decimalPlacesShownOnFocus',\n                scaleDecimal: 'decimalPlacesShownOnBlur',\n                aStor: 'saveValueToSessionStorage',\n                mRound: 'roundingMethod',\n                aPad: 'allowDecimalPadding',\n                nBracket: 'negativeBracketsTypeOnBlur',\n                wEmpty: 'emptyInputBehavior',\n                lZero: 'leadingZero',\n                aForm: 'formatOnPageLoad',\n                sNumber: 'selectNumberOnly',\n                anDefault: 'defaultValueOverride',\n                unSetOnSubmit: 'unformatOnSubmit',\n                outputType: 'outputFormat',\n                debug: 'showWarnings',\n\n                // Current options :\n                allowDecimalPadding: true,\n                alwaysAllowDecimalCharacter: true,\n                caretPositionOnFocus: true,\n                createLocalList: true,\n                currencySymbol: true,\n                currencySymbolPlacement: true,\n                decimalCharacter: true,\n                decimalCharacterAlternative: true,\n                decimalPlaces: true,\n                decimalPlacesRawValue: true,\n                decimalPlacesShownOnBlur: true,\n                decimalPlacesShownOnFocus: true,\n                defaultValueOverride: true,\n                digitalGroupSpacing: true,\n                digitGroupSeparator: true,\n                divisorWhenUnfocused: true,\n                emptyInputBehavior: true,\n                eventBubbles: true,\n                eventIsCancelable: true,\n                failOnUnknownOption: true,\n                formatOnPageLoad: true,\n                historySize: true,\n                isCancellable: true,\n                leadingZero: true,\n                maximumValue: true,\n                minimumValue: true,\n                modifyValueOnWheel: true,\n                negativeBracketsTypeOnBlur: true,\n                negativePositiveSignPlacement: true,\n                negativeSignCharacter: true,\n                noEventListeners: true,\n                onInvalidPaste: true,\n                outputFormat: true,\n                overrideMinMaxLimits: true,\n                positiveSignCharacter: true,\n                rawValueDivisor: true,\n                readOnly: true,\n                roundingMethod: true,\n                saveValueToSessionStorage: true,\n                selectNumberOnly: true,\n                selectOnFocus: true,\n                serializeSpaces: true,\n                showOnlyNumbersOnFocus: true,\n                showPositiveSign: true,\n                showWarnings: true,\n                styleRules: true,\n                suffixText: true,\n                symbolWhenUnfocused: true,\n                unformatOnHover: true,\n                unformatOnSubmit: true,\n                valuesToStrings: true,\n                watchExternalChanges: true,\n                wheelOn: true,\n                wheelStep: true,\n\n                // Additional information that are added to the `settings` object :\n                //TODO Find a way to exclude those internal data from the settings object (ideally by using another object, or better yet, class attributes) -->\n                allowedAutoStrip: true,\n                isNegativeSignAllowed: true,\n                isPositiveSignAllowed: true,\n                mIntNeg: true,\n                mIntPos: true,\n                numRegAutoStrip: true,\n                originalDecimalPlaces: true,\n                originalDecimalPlacesRawValue: true,\n                stripReg: true\n            };\n\n            for (var option in options) {\n                if (options.hasOwnProperty(option)) {\n                    if (oldOptionsConverter[option] === true) {\n                        // If the option is a 'new' option, we continue looping\n                        continue;\n                    }\n\n                    if (oldOptionsConverter.hasOwnProperty(option)) {\n                        // Else we have an 'old' option name\n                        _AutoNumericHelper2.default.warning('You are using the deprecated option name \\'' + option + '\\'. Please use \\'' + oldOptionsConverter[option] + '\\' instead from now on. The old option name will be dropped very soon\\u2122.', true);\n\n                        // Then we modify the initial option object to use the new options instead of the old ones\n                        options[oldOptionsConverter[option]] = options[option];\n                        delete options[option];\n                    } else if (options.failOnUnknownOption) {\n                        // ...or the option name is unknown. This means there is a problem with the options object, therefore we throw an error.\n                        _AutoNumericHelper2.default.throwError('Option name \\'' + option + '\\' is unknown. Please fix the options passed to autoNumeric');\n                    }\n                }\n            }\n\n            if ('mDec' in options) {\n                _AutoNumericHelper2.default.warning('The old `mDec` option has been deprecated in favor of more accurate options ; `decimalPlaces`, `decimalPlacesRawValue`, `decimalPlacesShownOnFocus` and `decimalPlacesShownOnBlur`.', true);\n            }\n        }\n    }, {\n        key: '_setNegativePositiveSignPermissions',\n        value: function _setNegativePositiveSignPermissions(settings) {\n            settings.isNegativeSignAllowed = settings.minimumValue < 0;\n            settings.isPositiveSignAllowed = settings.maximumValue >= 0;\n        }\n\n        /**\n         * Convert the `value` parameter that can either be :\n         * - a real number,\n         * - a number represented in the scientific notation (ie. -123.4567e-6)\n         * - a string representing a real number, or\n         * - a string representing a localized number (with specific group separators and decimal character),\n         * ...to a string representing a real 'javascript' number (ie. '1234' or '1234.567').\n         *\n         * This function returns `NaN` if such conversion fails.\n         *\n         * @param {int|float|string} value\n         * @param {object} settings\n         * @returns {string|NaN}\n         */\n\n    }, {\n        key: '_toNumericValue',\n        value: function _toNumericValue(value, settings) {\n            //XXX Note; this function is static since we need to pass a `settings` object when calling the static `AutoNumeric.format()` method\n            var result = void 0;\n            if (_AutoNumericHelper2.default.isNumber(Number(value))) {\n                // The value has either already been stripped, or a 'real' javascript number is passed as a parameter\n                result = _AutoNumericHelper2.default.scientificToDecimal(value);\n            } else {\n                // Else if it's a string that `Number()` cannot typecast, then we try to convert the localized numeric string to a numeric one\n                // Convert the value to a numeric string, stripping unnecessary characters in the process\n                result = this._convertToNumericString(value.toString(), settings);\n\n                // If the result is still not a numeric string, then we throw a warning\n                if (!_AutoNumericHelper2.default.isNumber(Number(result))) {\n                    _AutoNumericHelper2.default.warning('The given value \"' + value + '\" cannot be converted to a numeric one and therefore cannot be used appropriately.', settings.showWarnings);\n                    result = NaN;\n                }\n            }\n\n            return result;\n        }\n    }, {\n        key: '_checkIfInRange',\n        value: function _checkIfInRange(value, parsedMinValue, parsedMaxValue) {\n            var parsedValue = _AutoNumericHelper2.default.parseStr(value);\n            return _AutoNumericHelper2.default.testMinMax(parsedMinValue, parsedValue) > -1 && _AutoNumericHelper2.default.testMinMax(parsedMaxValue, parsedValue) < 1;\n        }\n    }, {\n        key: '_shouldSkipEventKey',\n        value: function _shouldSkipEventKey(eventKeyName) {\n            var isFnKeys = _AutoNumericHelper2.default.isInArray(eventKeyName, _AutoNumericEnum2.default.keyName._allFnKeys);\n            var isOSKeys = eventKeyName === _AutoNumericEnum2.default.keyName.OSLeft || eventKeyName === _AutoNumericEnum2.default.keyName.OSRight;\n            var isContextMenu = eventKeyName === _AutoNumericEnum2.default.keyName.ContextMenu;\n            var isSomeNonPrintableKeys = _AutoNumericHelper2.default.isInArray(eventKeyName, _AutoNumericEnum2.default.keyName._someNonPrintableKeys);\n            var isOtherNonPrintableKeys = eventKeyName === _AutoNumericEnum2.default.keyName.NumLock || eventKeyName === _AutoNumericEnum2.default.keyName.ScrollLock || eventKeyName === _AutoNumericEnum2.default.keyName.Insert || eventKeyName === _AutoNumericEnum2.default.keyName.Command;\n            var isUnrecognizableKeys = eventKeyName === _AutoNumericEnum2.default.keyName.Unidentified;\n\n            return isFnKeys || isOSKeys || isContextMenu || isSomeNonPrintableKeys || isUnrecognizableKeys || isOtherNonPrintableKeys;\n        }\n    }, {\n        key: '_serialize',\n        value: function _serialize(form) {\n            var intoAnArray = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n            var formatType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'unformatted';\n\n            var _this15 = this;\n\n            var serializedSpaceCharacter = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '+';\n            var forcedOutputFormat = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;\n\n            var result = [];\n\n            if ((typeof form === 'undefined' ? 'undefined' : _typeof(form)) === 'object' && form.nodeName.toLowerCase() === 'form') {\n                Array.prototype.slice.call(form.elements).forEach(function (element) {\n                    if (element.name && !element.disabled && ['file', 'reset', 'submit', 'button'].indexOf(element.type) === -1) {\n                        if (element.type === 'select-multiple') {\n                            Array.prototype.slice.call(element.options).forEach(function (option) {\n                                if (option.selected) {\n                                    //TODO Should we unformat/format/localize the selection option (which be default should be read-only)?\n                                    if (intoAnArray) {\n                                        result.push({ name: element.name, value: option.value });\n                                    } else {\n                                        // into a string\n                                        result.push(encodeURIComponent(element.name) + '=' + encodeURIComponent(option.value));\n                                    }\n                                }\n                            });\n                        } else if (['checkbox', 'radio'].indexOf(element.type) === -1 || element.checked) {\n                            var valueResult = void 0;\n                            if (_this15.isManagedByAutoNumeric(element)) {\n                                var anObject = void 0;\n                                switch (formatType) {\n                                    case 'unformatted':\n                                        anObject = _this15.getAutoNumericElement(element);\n                                        if (!_AutoNumericHelper2.default.isNull(anObject)) {\n                                            valueResult = _this15.unformat(element, anObject.getSettings());\n                                        }\n\n                                        break;\n                                    case 'localized':\n                                        anObject = _this15.getAutoNumericElement(element);\n                                        if (!_AutoNumericHelper2.default.isNull(anObject)) {\n                                            // Here I need to clone the setting object, otherwise I would modify it when changing the `outputFormat` option value\n                                            var currentSettings = _AutoNumericHelper2.default.cloneObject(anObject.getSettings());\n                                            if (!_AutoNumericHelper2.default.isNull(forcedOutputFormat)) {\n                                                currentSettings.outputFormat = forcedOutputFormat;\n                                            }\n\n                                            valueResult = _this15.localize(element, currentSettings);\n                                        }\n\n                                        break;\n                                    case 'formatted':\n                                    default:\n                                        valueResult = element.value;\n                                }\n                            } else {\n                                valueResult = element.value;\n                            }\n\n                            if (_AutoNumericHelper2.default.isUndefined(valueResult)) {\n                                _AutoNumericHelper2.default.throwError('This error should never be hit. If it has, something really wrong happened!');\n                            }\n\n                            if (intoAnArray) {\n                                result.push({ name: element.name, value: valueResult });\n                            } else {\n                                // into a string\n                                result.push(encodeURIComponent(element.name) + '=' + encodeURIComponent(valueResult));\n                            }\n                        }\n                    }\n                });\n            }\n\n            var finalResult = void 0;\n\n            if (intoAnArray) {\n                // Result as an Array\n                // Note: `serializedSpaceCharacter` does not affect the array result since we do not change the space character for this one\n                finalResult = result;\n            } else {\n                // Result as a string\n                finalResult = result.join('&');\n\n                if ('+' === serializedSpaceCharacter) {\n                    finalResult = finalResult.replace(/%20/g, '+');\n                }\n            }\n\n            return finalResult;\n        }\n\n        /**\n         * Serialize the form values to a string, outputting numeric strings for each AutoNumeric-managed element values.\n         *\n         * @param {HTMLFormElement} form\n         * @param {string} serializedSpaceCharacter\n         * @returns {string}\n         */\n\n    }, {\n        key: '_serializeNumericString',\n        value: function _serializeNumericString(form) {\n            var serializedSpaceCharacter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '+';\n\n            return this._serialize(form, false, 'unformatted', serializedSpaceCharacter);\n        }\n\n        /**\n         * Serialize the form values to a string, outputting the formatted value as strings for each AutoNumeric-managed elements.\n         *\n         * @param {HTMLFormElement} form\n         * @param {string} serializedSpaceCharacter\n         * @returns {string}\n         */\n\n    }, {\n        key: '_serializeFormatted',\n        value: function _serializeFormatted(form) {\n            var serializedSpaceCharacter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '+';\n\n            return this._serialize(form, false, 'formatted', serializedSpaceCharacter);\n        }\n\n        /**\n         * Serialize the form values to a string, outputting localized strings for each AutoNumeric-managed element values.\n         *\n         * @param {HTMLFormElement} form\n         * @param {string} serializedSpaceCharacter\n         * @param {string|null} forcedOutputFormat If set, then this is the format that is used for the localization, instead of the default `outputFormat` option.\n         * @returns {string}\n         */\n\n    }, {\n        key: '_serializeLocalized',\n        value: function _serializeLocalized(form) {\n            var serializedSpaceCharacter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '+';\n            var forcedOutputFormat = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\n            return this._serialize(form, false, 'localized', serializedSpaceCharacter, forcedOutputFormat);\n        }\n\n        /**\n         * Generate an Array with the form values, outputting numeric strings for each AutoNumeric-managed element values.\n         *\n         * @param {HTMLFormElement} form\n         * @param {string} serializedSpaceCharacter\n         * @returns {Array}\n         */\n\n    }, {\n        key: '_serializeNumericStringArray',\n        value: function _serializeNumericStringArray(form) {\n            var serializedSpaceCharacter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '+';\n\n            return this._serialize(form, true, 'unformatted', serializedSpaceCharacter);\n        }\n\n        /**\n         * Generate an Array with the form values, outputting the formatted value as strings for each AutoNumeric-managed elements.\n         *\n         * @param {HTMLFormElement} form\n         * @param {string} serializedSpaceCharacter\n         * @returns {Array}\n         */\n\n    }, {\n        key: '_serializeFormattedArray',\n        value: function _serializeFormattedArray(form) {\n            var serializedSpaceCharacter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '+';\n\n            return this._serialize(form, true, 'formatted', serializedSpaceCharacter);\n        }\n\n        /**\n         * Generate an Array with the form values, outputting localized strings for each AutoNumeric-managed element values.\n         *\n         * @param {HTMLFormElement} form\n         * @param {string} serializedSpaceCharacter\n         * @param {string|null} forcedOutputFormat If set, then this is the format that is used for the localization, instead of the default `outputFormat` option.\n         * @returns {Array}\n         */\n\n    }, {\n        key: '_serializeLocalizedArray',\n        value: function _serializeLocalizedArray(form) {\n            var serializedSpaceCharacter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '+';\n            var forcedOutputFormat = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\n            return this._serialize(form, true, 'localized', serializedSpaceCharacter, forcedOutputFormat);\n        }\n    }]);\n\n    return AutoNumeric;\n}();\n\n/**\n * Initialize multiple DOM elements in one call (and possibly pass multiple values that will be mapped to each DOM element).\n *\n * @example\n * // Init multiple DOM elements in one call (and possibly pass multiple values that will be mapped to each DOM element)\n * [anElement1, anElement2, anElement3] = AutoNumeric.multiple([domElement1, domElement2, domElement3], { options });\n * [anElement1, anElement2, anElement3] = AutoNumeric.multiple([domElement1, domElement2, domElement3], [{ options }, 'euroPos']);\n * [anElement1, anElement2, anElement3] = AutoNumeric.multiple([domElement1, domElement2, domElement3], 12345.789, { options });\n * [anElement1, anElement2, anElement3] = AutoNumeric.multiple([domElement1, domElement2, domElement3], 12345.789, [{ options }, 'euroPos']);\n * [anElement1, anElement2, anElement3] = AutoNumeric.multiple.french([domElement1, domElement2, domElement3], [12345.789, 234.78, null], { options });\n * [anElement1, anElement2, anElement3] = AutoNumeric.multiple.french([domElement1, domElement2, domElement3], [12345.789, 234.78, null], [{ options }, 'euroPos']);\n *\n * // Special case, if a <form> element is passed (or any other 'parent' (or 'root') DOM element), then autoNumeric will initialize each child `<input>` elements recursively, ignoring those referenced in the `exclude` attribute\n * [anElement1, anElement2] = AutoNumeric.multiple({ rootElement: formElement }, { options });\n * [anElement1, anElement2] = AutoNumeric.multiple({ rootElement: formElement, exclude : [hiddenElement, tokenElement] }, { options });\n * [anElement1, anElement2] = AutoNumeric.multiple({ rootElement: formElement, exclude : [hiddenElement, tokenElement] }, [12345.789, null], { options });\n *\n * // If you want to select multiple elements via a css selector, then you must use the `multiple` function. Under the hood `QuerySelectorAll` is used.\n * [anElement1, anElement2] = AutoNumeric.multiple('.myCssClass > input', { options }); // This always return an Array, even if there is only one element selected\n * [anElement1, anElement2] = AutoNumeric.multiple('.myCssClass > input', [null, 12345.789], { options }); // Idem above, but with passing the initial values too\n *\n * @param {string|Array|{ rootElement: HTMLElement }|{ rootElement: HTMLElement, exclude: Array<HTMLInputElement>}} arg1\n * @param {number|Array|object|null} initialValue\n * @param {object|Array|null} options\n * @returns {Array}\n */\n\n\nexports.default = AutoNumeric;\nAutoNumeric.multiple = function (arg1) {\n    var initialValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n    var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\n    var result = [];\n\n    // Analyze the arguments and transform them to make them exploitable\n    if (_AutoNumericHelper2.default.isObject(initialValue)) {\n        // If the user gave an option object as the second argument, instead of the initial values\n        options = initialValue;\n        initialValue = null;\n    }\n\n    if (_AutoNumericHelper2.default.isString(arg1)) {\n        arg1 = [].concat(_toConsumableArray(document.querySelectorAll(arg1))); // Convert a NodeList to an Array (cf. http://stackoverflow.com/a/37297292/2834898)\n    } else if (_AutoNumericHelper2.default.isObject(arg1)) {\n        if (!arg1.hasOwnProperty('rootElement')) {\n            _AutoNumericHelper2.default.throwError('The object passed to the \\'multiple\\' function is invalid ; no \\'rootElement\\' attribute found.');\n        }\n\n        // Retrieve the DOM element list from the given <form> element\n        var elements = [].concat(_toConsumableArray(arg1.rootElement.querySelectorAll('input')));\n        if (arg1.hasOwnProperty('exclude')) {\n            if (!Array.isArray(arg1.exclude)) {\n                _AutoNumericHelper2.default.throwError('The \\'exclude\\' array passed to the \\'multiple\\' function is invalid.');\n            }\n\n            // Filter out the excluded elements\n            arg1 = _AutoNumericHelper2.default.filterOut(elements, arg1.exclude);\n        } else {\n            arg1 = elements;\n        }\n    } else if (!_AutoNumericHelper2.default.isArray(arg1)) {\n        _AutoNumericHelper2.default.throwError('The given parameters to the \\'multiple\\' function are invalid.');\n    }\n\n    if (arg1.length === 0) {\n        var showWarnings = true;\n        if (!_AutoNumericHelper2.default.isNull(options) && _AutoNumericHelper2.default.isBoolean(options.showWarnings)) {\n            showWarnings = options.showWarnings;\n        }\n\n        _AutoNumericHelper2.default.warning('No valid DOM elements were given hence no AutoNumeric object were instantiated.', showWarnings);\n\n        return [];\n    }\n\n    // At this point, we know `arg1` is an array of DOM elements\n\n    // This function can be initialized with two types of array, one for the initial values, and/or one for the options.\n    // So we need to find out if an array is detected if the user passed an array of initial values, or an array of options\n    // Therefore, we analyze the content of the arrays for the second and third arguments\n    // ...for the second parameter :\n    var isInitialValueArray = _AutoNumericHelper2.default.isArray(initialValue);\n    var isInitialValueArrayAndNotEmpty = isInitialValueArray && initialValue.length >= 1;\n    var secondArgumentIsInitialValueArray = false;\n    var secondArgumentIsOptionArray = false;\n    // Any of the arrays can be either an array of initial values, or an array of option object/pre-defined option names\n    if (isInitialValueArrayAndNotEmpty) {\n        var typeOfFirstArrayElement = _typeof(Number(initialValue[0]));\n        // First we test the second argument\n        secondArgumentIsInitialValueArray = typeOfFirstArrayElement === 'number' && !isNaN(Number(initialValue[0]));\n\n        if (!secondArgumentIsInitialValueArray) {\n            // If the second argument is an array, but not an array of values, check if it's instead an array of options/pre-defined option names\n            if (typeOfFirstArrayElement === 'string' || isNaN(typeOfFirstArrayElement) || typeOfFirstArrayElement === 'object') {\n                secondArgumentIsOptionArray = true;\n            }\n        }\n    }\n\n    // ...for the third parameter :\n    var isOptionsArrayAndNotEmpty = _AutoNumericHelper2.default.isArray(options) && options.length >= 1;\n    var thirdArgumentIsOptionArray = false;\n    if (isOptionsArrayAndNotEmpty) {\n        var _typeOfFirstArrayElement = _typeof(options[0]);\n        if (_typeOfFirstArrayElement === 'string' || _typeOfFirstArrayElement === 'object') {\n            // If the third argument is an array of options/pre-defined option names\n            thirdArgumentIsOptionArray = true;\n        }\n    }\n\n    // Depending of our findings, we generate the options variable to use `optionsToUse`, either directly, or merged\n    var optionsToUse = void 0;\n    if (secondArgumentIsOptionArray) {\n        optionsToUse = AutoNumeric.mergeOptions(initialValue);\n    } else if (thirdArgumentIsOptionArray) {\n        optionsToUse = AutoNumeric.mergeOptions(options);\n    } else {\n        optionsToUse = options;\n    }\n\n    // Initialize the initial values\n    var isInitialValueNumber = _AutoNumericHelper2.default.isNumber(initialValue);\n    var initialValueArraySize = void 0;\n    if (secondArgumentIsInitialValueArray) {\n        initialValueArraySize = initialValue.length;\n    }\n\n    // Instantiate each AutoNumeric objects\n    arg1.forEach(function (domElement, index) {\n        if (isInitialValueNumber) {\n            // We set the same value for each elements\n            result.push(new AutoNumeric(domElement, initialValue, optionsToUse));\n        } else if (secondArgumentIsInitialValueArray && index <= initialValueArraySize) {\n            result.push(new AutoNumeric(domElement, initialValue[index], optionsToUse));\n        } else {\n            result.push(new AutoNumeric(domElement, null, optionsToUse));\n        }\n    });\n\n    return result;\n};\n\n/**\n * Polyfill for obsolete browsers like IE\n */\n(function () {\n    // Polyfill for `Array.from()` (Fix issue #495)\n    if (!Array.from) {\n        Array.from = function (object) {\n            return [].slice.call(object);\n        };\n    }\n\n    // Polyfill for `CustomEvent` (cf. https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent)\n    if (typeof window === 'undefined' || typeof window.CustomEvent === 'function') {\n        return false;\n    }\n\n    function CustomEvent(event, params) {\n        params = params || { bubbles: false, cancelable: false, detail: void 0 };\n        var evt = document.createEvent('CustomEvent');\n        evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);\n        return evt;\n    }\n\n    CustomEvent.prototype = window.Event.prototype;\n    window.CustomEvent = CustomEvent;\n})();\nmodule.exports = exports['default'];\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvQXV0b051bWVyaWMuanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9BdXRvTnVtZXJpYy9zcmMvQXV0b051bWVyaWMuanM/ZTE0NyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqICAgICAgICAgICAgICAgQXV0b051bWVyaWMuanNcbiAqXG4gKiBAdmVyc2lvbiAgICAgIDQuNC4wXG4gKiBAZGF0ZSAgICAgICAgIDIwMTgtMDgtMDQgVVRDIDA3OjQ0XG4gKlxuICogQGF1dGhvcnMgICAgICBCb2IgS25vdGhlLCBBbGV4YW5kcmUgQm9ubmVhdVxuICogQGNvbnRyaWJ1dG9ycyBTb2tvbG92IFl1cmEgYW5kIG90aGVycywgY2YuIEFVVEhPUlNcbiAqIEBjb3B5cmlnaHQgICAgMjAwOSBSb2JlcnQgSi4gS25vdGhlXG4gKiBAc2luY2UgICAgICAgIDIwMDktMDgtMDlcbiAqXG4gKiBAc3VtbWFyeSAgICAgIGF1dG9OdW1lcmljIGlzIGEgc3RhbmRhbG9uZSBKYXZhc2NyaXB0IGxpYnJhcnlcbiAqICAgICAgICAgICAgICAgdGhhdCBwcm92aWRlcyBsaXZlICphcy15b3UtdHlwZSogZm9ybWF0dGluZyBmb3JcbiAqICAgICAgICAgICAgICAgaW50ZXJuYXRpb25hbCBudW1iZXJzIGFuZCBjdXJyZW5jaWVzLlxuICpcbiAqIEBsaW5rICAgICAgICAgaHR0cDovL2F1dG9udW1lcmljLm9yZ1xuICpcbiAqICAgICAgICAgICAgICAgTm90ZSA6IFNvbWUgZnVuY3Rpb25zIGFyZSBib3Jyb3dlZCBmcm9tIGJpZy5qc1xuICogQHNlZSAgICAgICAgICBodHRwczovL2dpdGh1Yi5jb20vTWlrZU1jbC9iaWcuanMvXG4gKlxuICogUGxlYXNlIHJlcG9ydCBhbnkgYnVncyB0byBodHRwczovL2dpdGh1Yi5jb20vYXV0b051bWVyaWMvYXV0b051bWVyaWNcbiAqXG4gKiBAbGljZW5zZSAgICAgIFJlbGVhc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICogQGxpbmsgICAgICAgICBodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL21pdC1saWNlbnNlLnBocFxuICpcbiAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uXG4gKiBvYnRhaW5pbmcgYSBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvblxuICogZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0XG4gKiByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSxcbiAqIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YiBsaWNlbnNlLCBhbmQvb3Igc2VsbFxuICogY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlXG4gKiBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZ1xuICogY29uZGl0aW9uczpcbiAqXG4gKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZVxuICogaW5jbHVkZWQgaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4gKlxuICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCxcbiAqIEVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFU1xuICogT0YgTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkRcbiAqIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUXG4gKiBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSxcbiAqIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lOR1xuICogRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUlxuICogT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuICovXG5cbi8vVE9ETyBQcmV2ZW50IGhhdmluZyB0byBlbnRlciByZWxhdGl2ZSBwYXRoIGluIHRoZSBqcyBmaWxlcyAoaWUuIHVzaW5nIGAuL0F1dG9OdW1lcmljSGVscGVyYCBpbnN0ZWFkIG9mIGp1c3QgYEF1dG9OdW1lcmljSGVscGVyYCkgKGNmLiBodHRwOi8vbW9kdXNjcmVhdGUuY29tL2VzNi1lczIwMTUtaW1wb3J0LW5vLXJlbGF0aXZlLXBhdGgtd2VicGFjay8pXG5pbXBvcnQgQXV0b051bWVyaWNIZWxwZXIgZnJvbSAnLi9BdXRvTnVtZXJpY0hlbHBlcic7XG5pbXBvcnQgQXV0b051bWVyaWNFbnVtIGZyb20gJy4vQXV0b051bWVyaWNFbnVtJztcblxuLyoqXG4gKiBDbGFzcyBkZWNsYXJhdGlvbiBmb3IgdGhlIEF1dG9OdW1lcmljIG9iamVjdC5cbiAqXG4gKiBBbiBBdXRvTnVtZXJpYyBlbGVtZW50IGlzIGFuIG9iamVjdCB3cmFwcGVyIHRoYXQga2VlcHMgYSByZWZlcmVuY2UgdG8gdGhlIERPTSBlbGVtZW50IGl0IG1hbmFnZXMgKHVzdWFsbHkgYW4gPGlucHV0PiBvbmUpLCBhbmQgcHJvdmlkZXMgYXV0b051bWVyaWMtc3BlY2lmaWMgdmFyaWFibGVzIGFuZCBmdW5jdGlvbnMuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEF1dG9OdW1lcmljIHtcbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplIHRoZSBBdXRvTnVtZXJpYyBvYmplY3Qgb250byB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQsIGFuZCBhdHRhY2ggdGhlIHNldHRpbmdzIGFuZCByZWxhdGVkIGV2ZW50IGxpc3RlbmVycyB0byBpdC5cbiAgICAgKiBUaGUgb3B0aW9ucyBwYXNzZWQgYXMgYSBwYXJhbWV0ZXIgaXMgYW4gb2JqZWN0IHRoYXQgY29udGFpbnMgdGhlIHNldHRpbmdzIChpZS4ge2RpZ2l0R3JvdXBTZXBhcmF0b3I6IFwiLlwiLCBkZWNpbWFsQ2hhcmFjdGVyOiBcIixcIiwgY3VycmVuY3lTeW1ib2w6ICfigqwgJ30pXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50KTsgLy8gV2l0aCB0aGUgZGVmYXVsdCBvcHRpb25zXG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIHsgb3B0aW9ucyB9KTsgLy8gV2l0aCBvbmUgb3B0aW9uIG9iamVjdFxuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAnZXVyb1BvcycpOyAvLyBXaXRoIGEgbmFtZWQgcHJlLWRlZmluZWQgc3RyaW5nXG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIFt7IG9wdGlvbnMxIH0sICdldXJvUG9zJywgeyBvcHRpb25zMiB9XSk7IC8vIFdpdGggbXVsdGlwbGUgb3B0aW9uIG9iamVjdHMgKHRoZSBsYXRlc3Qgb3B0aW9uIG92ZXJ3cml0aW5nIHRoZSBwcmV2aW91cyBvbmVzKVxuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCBudWxsLCB7IG9wdGlvbnMgfSk7IC8vIFdpdGggb25lIG9wdGlvbiBvYmplY3QsIGFuZCBhIGZhaWxlZCBpbml0aWFsIHZhbHVlXG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQpLmZyZW5jaCgpOyAvLyBXaXRoIG9uZSBwcmUtZGVmaW5lZCBsYW5ndWFnZSBvYmplY3RcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCkuZnJlbmNoKHsgb3B0aW9ucyB9KTsvLyBXaXRoIG9uZSBwcmUtZGVmaW5lZCBsYW5ndWFnZSBvYmplY3QgYW5kIGFkZGl0aW9uYWwgb3B0aW9ucyB0aGF0IHdpbGwgb3ZlcnJpZGUgdGhlIGRlZmF1bHRzXG4gICAgICpcbiAgICAgKiAvLyAuLi5vciBpbml0IGFuZCBzZXQgdGhlIHZhbHVlIGluIG9uZSBjYWxsIDpcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgMTIzNDUuNzg5KTsgLy8gV2l0aCB0aGUgZGVmYXVsdCBvcHRpb25zLCBhbmQgYW4gaW5pdGlhbCB2YWx1ZVxuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAxMjM0NS43ODksIHsgb3B0aW9ucyB9KTtcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgJzEyMzQ1Ljc4OScsIHsgb3B0aW9ucyB9KTtcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgMTIzNDUuNzg5LCAnZXVyb1BvcycpO1xuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAxMjM0NS43ODksIFt7IG9wdGlvbnMxIH0sICdldXJvUG9zJywgeyBvcHRpb25zMiB9XSk7XG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIDEyMzQ1Ljc4OSkuZnJlbmNoKHsgb3B0aW9ucyB9KTtcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgMTIzNDUuNzg5LCB7IG9wdGlvbnMgfSkuZnJlbmNoKHsgb3B0aW9ucyB9KTsgLy8gTm90IHJlYWxseSBoZWxwZnVsLCBidXQgcG9zc2libGVcbiAgICAgKlxuICAgICAqIC8vIFRoZSBBdXRvTnVtZXJpYyBjb25zdHJ1Y3RvciBjbGFzcyBjYW4gYWxzbyBhY2NlcHQgYSBzdHJpbmcgYXMgYSBjc3Mgc2VsZWN0b3IuIFVuZGVyIHRoZSBob29kIHRoaXMgdXNlIGBRdWVyeVNlbGVjdG9yYCBhbmQgbGltaXQgaXRzZWxmIHRvIG9ubHkgdGhlIGZpcnN0IGVsZW1lbnQgaXQgZmluZHMuXG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0Jyk7XG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgeyBvcHRpb25zIH0pO1xuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsICdldXJvUG9zJyk7XG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgW3sgb3B0aW9uczEgfSwgJ2V1cm9Qb3MnLCB7IG9wdGlvbnMyIH1dKTtcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCAxMjM0NS43ODkpO1xuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsIDEyMzQ1Ljc4OSwgeyBvcHRpb25zIH0pO1xuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsIDEyMzQ1Ljc4OSwgJ2V1cm9Qb3MnKTtcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCAxMjM0NS43ODksIFt7IG9wdGlvbnMxIH0sICdldXJvUG9zJywgeyBvcHRpb25zMiB9XSk7XG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgbnVsbCwgeyBvcHRpb25zIH0pOyAvLyBXaXRoIGEgZmFpbGVkIGluaXRpYWwgdmFsdWVcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCAxMjM0NS43ODkpLmZyZW5jaCh7IG9wdGlvbnMgfSk7XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdHxBcnJheXxudW1iZXJ8c3RyaW5nfSBhcmcxXG4gICAgICogQHBhcmFtIHtvYmplY3R8QXJyYXl8bnVtYmVyfHN0cmluZ3xudWxsfSBhcmcyXG4gICAgICogQHBhcmFtIHtvYmplY3R8QXJyYXl8bnVtYmVyfHN0cmluZ3xudWxsfSBhcmczXG4gICAgICogQHRocm93c1xuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGFyZzEgPSBudWxsLCBhcmcyID0gbnVsbCwgYXJnMyA9IG51bGwpIHtcbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0gSW5pdGlhbGl6YXRpb25cbiAgICAgICAgLy8gSW5pdGlhbGl6ZSB0aGUgYXJndW1lbnRzXG4gICAgICAgIGNvbnN0IHsgZG9tRWxlbWVudCwgaW5pdGlhbFZhbHVlLCB1c2VyT3B0aW9ucyB9ID0gQXV0b051bWVyaWMuX3NldEFyZ3VtZW50c1ZhbHVlcyhhcmcxLCBhcmcyLCBhcmczKTtcblxuICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBlbGVtZW50XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudCA9IGRvbUVsZW1lbnQ7XG5cbiAgICAgICAgLy8gR2VuZXJhdGUgdGhlIHNldHRpbmdzXG4gICAgICAgIHRoaXMuZGVmYXVsdFJhd1ZhbHVlID0gJyc7IC8vIFRoZSBkZWZhdWx0IHJhdyB2YWx1ZSB0byBzZXQgd2hlbiBpbml0aWFsaXppbmcgYW4gQXV0b051bWVyaWMgb2JqZWN0XG4gICAgICAgIHRoaXMuX3NldFNldHRpbmdzKHVzZXJPcHRpb25zLCBmYWxzZSk7XG4gICAgICAgIC8vVE9ETyBJZiBgc3R5bGVSdWxlc2AgaXMgbm90IG51bGwsIGFkZCBieSBkZWZhdWx0IGEgY2xhc3MgJ2F1dG9OdW1lcmljJyB0aGF0IGFkZHMgdHJhbnNpdGlvbiB0byBjb2xvciwgYmFja2dyb3VuZC1jb2xvciwgYm9yZGVyLWNvbG9yIHByb3BlcnRpZXNcbiAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIERPTSBlbGVtZW50IGlzIHN1cHBvcnRlZFxuICAgICAgICB0aGlzLl9jaGVja0VsZW1lbnQoKTtcblxuICAgICAgICAvLyBTdG9yZSB0aGUgYWRkaXRpb25hbCBhdHRyaWJ1dGVzIGluc2lkZSB0aGUgQXV0b051bWVyaWMgb2JqZWN0XG4gICAgICAgIC8vIE5vdGU6IFRoaXMgdmFyaWFibGUgaXMgbmVlZGVkIGFuZCBub3QgYSBkdXBsaWNhdGUgb2YgYGluaXRpYWxWYWx1ZU9uS2V5ZG93bmAgbm9yIGB2YWx1ZU9uRm9jdXNgIHNpbmNlIGl0IHNlcnZlcyBhIGRpZmZlcmVudCBwdXJwb3NlIGFuZCBoYXMgYSBkaWZmZXJlbnQgbGlmZWN5Y2xlXG4gICAgICAgIHRoaXMuc2F2ZWRDYW5jZWxsYWJsZVZhbHVlID0gbnVsbDtcblxuICAgICAgICAvLyBJbml0aWFsaXplIHRoZSB1bmRvL3JlZG8gdmFyaWFibGVzXG4gICAgICAgIHRoaXMuaGlzdG9yeVRhYmxlID0gW107IC8vIEtlZXAgdHJhY2sgb2YgKmFsbCogdmFsaWQgc3RhdGVzIG9mIHRoZSBlbGVtZW50IHZhbHVlXG4gICAgICAgIHRoaXMuaGlzdG9yeVRhYmxlSW5kZXggPSAtMTsgLy8gUG9pbnRlciB0byB0aGUgY3VycmVudCB1bmRvL3JlZG8gc3RhdGUuIFRoaXMgd2lsbCBiZSBzZXQgdG8gJzAnIGR1cmluZyBpbml0aWFsaXphdGlvbiBzaW5jZSBpdCBmaXJzdCBhZGRzIGl0c2VsZi5cbiAgICAgICAgdGhpcy5vbkdvaW5nUmVkbyA9IGZhbHNlOyAvLyBWYXJpYWJsZSB0aGF0IGtlZXBzIHRyYWNrIGlmIGEgJ3JlZG8nIGlzIG9uZ29pbmcgKGluIG9yZGVyIHRvIHByZXZlbnQgYW4gJ3VuZG8nIHRvIGJlIGxhdW5jaCB3aGVuIHJlbGVhc2luZyB0aGUgc2hpZnQga2V5IGJlZm9yZSB0aGUgY3RybCBrZXkgYWZ0ZXIgYSAncmVkbycgc2hvcnRjdXQpXG5cbiAgICAgICAgLy8gSW5pdGlhbGl6ZSB0aGUgcGFyZW50IGZvcm0gZWxlbWVudCwgaWYgYW55XG4gICAgICAgIHRoaXMucGFyZW50Rm9ybSA9IHRoaXMuX2dldFBhcmVudEZvcm0oKTtcblxuICAgICAgICAvLyBTZXQgdGhlIGluaXRpYWwgdmFsdWUgaWYgaXQgZXhpc3RzIGFuZCBpZiB0aGUgYGZvcm1hdE9uUGFnZUxvYWRgIG9wdGlvbiB3aWxsIGFsbG93IGl0XG4gICAgICAgIGlmICghdGhpcy5ydW5PbmNlICYmIHRoaXMuc2V0dGluZ3MuZm9ybWF0T25QYWdlTG9hZCkge1xuICAgICAgICAgICAgLy8gRm9ybWF0IHRoZSBlbGVtZW50IHZhbHVlIGlmIG5lZWRlZFxuICAgICAgICAgICAgdGhpcy5fZm9ybWF0RGVmYXVsdFZhbHVlT25QYWdlTG9hZChpbml0aWFsVmFsdWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIHNldCB0aGUgYHJhd1ZhbHVlYCBhbmQgdGhlIGVsZW1lbnQgdmFsdWUsIGJ1dCBkbyBub3QgZm9ybWF0IHRoZSBsYXR0ZXIgeWV0XG4gICAgICAgICAgICBsZXQgdmFsdWVUb1NldDtcbiAgICAgICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoaW5pdGlhbFZhbHVlKSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5zZXR0aW5ncy5lbXB0eUlucHV0QmVoYXZpb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5taW46XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVRvU2V0ID0gdGhpcy5zZXR0aW5ncy5taW5pbXVtVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5tYXg6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVRvU2V0ID0gdGhpcy5zZXR0aW5ncy5tYXhpbXVtVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci56ZXJvOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVUb1NldCA9ICcwJztcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAvLyBJbiBvcmRlciB0byBzdGF5IGNvbnNpc3RlbnQgd2hlbiBgZm9ybWF0T25QYWdlTG9hZGAgaXMgc2V0IHRvIGB0cnVlYCwgaXQncyBzdGlsbCBpbXBvc3NpYmxlIHRvIHNldCB0aGUgYG51bGxgIHZhbHVlIGFzIHRoZSBpbml0aWFsIHZhbHVlXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IuZm9jdXM6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IucHJlc3M6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IuYWx3YXlzOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLm51bGw6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVRvU2V0ID0gJyc7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgLy8gV2hlbiBgZW1wdHlJbnB1dEJlaGF2aW9yYCBpcyBhIG51bWJlciBvciBhIHN0cmluZyByZXByZXNlbnRpbmcgYSBudW1iZXJcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdCA6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVRvU2V0ID0gdGhpcy5zZXR0aW5ncy5lbXB0eUlucHV0QmVoYXZpb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YWx1ZVRvU2V0ID0gaW5pdGlhbFZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9zZXRFbGVtZW50QW5kUmF3VmFsdWUodmFsdWVUb1NldCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnJ1bk9uY2UgPSB0cnVlO1xuXG4gICAgICAgIC8vIEFkZCB0aGUgZXZlbnRzIGxpc3RlbmVycyBvbmx5IG9uIGlucHV0IG9yIGVkaXRhYmxlIGVsZW1lbnRzXG4gICAgICAgIHRoaXMuaGFzRXZlbnRMaXN0ZW5lcnMgPSBmYWxzZTtcbiAgICAgICAgaWYgKHRoaXMuaXNJbnB1dEVsZW1lbnQgfHwgdGhpcy5pc0NvbnRlbnRFZGl0YWJsZSkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLnNldHRpbmdzLm5vRXZlbnRMaXN0ZW5lcnMpIHtcbiAgICAgICAgICAgICAgICAvL1hYWCBIZXJlIHdlIG1ha2Ugc3VyZSB0aGUgZ2xvYmFsIGxpc3QgaXMgY3JlYXRlZCBhZnRlciBjcmVhdGluZyB0aGUgZXZlbnQgbGlzdGVuZXJzLCB0byBvbmx5IGNyZWF0ZSB0aGUgZXZlbnQgbGlzdGVuZXJzIG9uIGBkb2N1bWVudGAgb25jZVxuICAgICAgICAgICAgICAgIHRoaXMuX2NyZWF0ZUV2ZW50TGlzdGVuZXJzKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX3NldFdyaXRlUGVybWlzc2lvbnMoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNhdmUgdGhlIGluaXRpYWwgdmFsdWVzIChodG1sIGF0dHJpYnV0ZSArIGVsZW1lbnQudmFsdWUpIGZvciB0aGUgcHJpc3RpbmUgdGVzdFxuICAgICAgICB0aGlzLl9zYXZlSW5pdGlhbFZhbHVlcyhpbml0aWFsVmFsdWUpO1xuICAgICAgICBcbiAgICAgICAgLy8gU2V0dXAgdGhlIGRhdGEgZm9yIHRoZSBwZXJzaXN0ZW50IHN0b3JhZ2Ugc29sdXRpb24gKGllLiBzZXNzaW9uU3RvcmFnZSBvciBjb29raWVzKVxuICAgICAgICB0aGlzLnNlc3Npb25TdG9yYWdlQXZhaWxhYmxlID0gdGhpcy5jb25zdHJ1Y3Rvci5fc3RvcmFnZVRlc3QoKTtcbiAgICAgICAgdGhpcy5zdG9yYWdlTmFtZVByZWZpeCA9ICdBVVRPXyc7IC8vIFRoZSBwcmVmaXggZm9yIHRoZSByYXcgdmFsdWUgc3RvcmFnZSBuYW1lIHZhcmlhYmxlIGNhbiBiZSBtb2RpZmllZCBoZXJlXG4gICAgICAgIHRoaXMuX3NldFBlcnNpc3RlbnRTdG9yYWdlTmFtZSgpO1xuXG4gICAgICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgIC8vIC0tLS0tLS0tLS0tLS0tIFRyYWNraW5nXG4gICAgICAgIC8vIEtlZXAgdHJhY2sgaWYgdGhlIGVsZW1lbnQgaXMgY3VycmVudGx5IGZvY3VzZWRcbiAgICAgICAgdGhpcy5pc0ZvY3VzZWQgPSBmYWxzZTtcbiAgICAgICAgLy8gS2VlcCB0cmFjayBpZiBhIG1vdXNlIHdoZWVsIGV2ZW50IGlzIGN1cnJlbnRseSBvbmdvaW5nXG4gICAgICAgIHRoaXMuaXNXaGVlbEV2ZW50ID0gZmFsc2U7XG4gICAgICAgIC8vIEtlZXAgdHJhY2sgaWYgYSBkcm9wIGV2ZW50IGlzIGN1cnJlbnRseSBvbmdvaW5nXG4gICAgICAgIHRoaXMuaXNEcm9wRXZlbnQgPSBmYWxzZTtcbiAgICAgICAgLy8gS2VlcCB0cmFjayBpZiB0aGUgdXNlciBpcyBjdXJyZW50bHkgZWRpdGluZyB0aGUgZWxlbWVudFxuICAgICAgICB0aGlzLmlzRWRpdGluZyA9IGZhbHNlO1xuICAgICAgICAvLyBLZWVwIHRyYWNrIG9mIHRoZSByYXdWYWx1ZSAobmVlZGVkIHRvIGRlZmluZSBpZiBhIGNoYW5nZSBldmVudCBtdXN0IGJlIHNlbnQgb24gYmx1ciBvciBlbnRlciBrZXkpXG4gICAgICAgIHRoaXMucmF3VmFsdWVPbkZvY3VzID0gdm9pZCgwKTtcbiAgICAgICAgLy8gV2F0Y2ggYW55IGV4dGVybmFsIGNoYW5nZXMgdG8gdGhlIGVsZW1lbnQgdmFsdWUvdGV4dENvbnRlbnQvbm9kZVZhbHVlIGFuZCBgc2V0KClgIHRoZSBuZXcgdmFsdWUgc28gdGhhdCBpdCBnZXRzIGZvcm1hdHRlZC9zYXZlZCBpbiB0aGUgaGlzdG9yeVxuICAgICAgICB0aGlzLmludGVybmFsTW9kaWZpY2F0aW9uID0gZmFsc2U7IC8vIFRoaXMgaXMgdGVtcG9yYXJpbHkgc2V0IHRvIGB0cnVlYCBvbmx5IHdoZW4gdGhlIEF1dG9OdW1lcmljIG9iamVjdCBkb2VzIHVwZGF0ZSB0aGUgZWxlbWVudCB2YWx1ZVxuICAgICAgICB0aGlzLmF0dHJpYnV0ZVRvV2F0Y2ggPSB0aGlzLl9nZXRBdHRyaWJ1dGVUb1dhdGNoKCk7XG4gICAgICAgIHRoaXMuZ2V0dGVyU2V0dGVyID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0aGlzLmRvbUVsZW1lbnQuX19wcm90b19fLCB0aGlzLmF0dHJpYnV0ZVRvV2F0Y2gpO1xuICAgICAgICB0aGlzLl9hZGRXYXRjaGVyKCk7XG5cbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY3JlYXRlTG9jYWxMaXN0KSB7XG4gICAgICAgICAgICAvLyBLZWVwIHRyYWNrIG9mIGV2ZXJ5IEF1dG9OdW1lcmljIGVsZW1lbnRzIHRoYXQgdGhpcyBvYmplY3QgaW5pdGlhbGl6ZWRcbiAgICAgICAgICAgIHRoaXMuX2NyZWF0ZUxvY2FsTGlzdCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gS2VlcCB0cmFjayBvZiBhbGwgQXV0b051bWVyaWMgZWxlbWVudHMgaW4gdGhlIGN1cnJlbnQgd2ViIHBhZ2VcbiAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5fYWRkVG9HbG9iYWxMaXN0KHRoaXMpO1xuXG4gICAgICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgIC8vIC0tLS0tLS0tLS0tLS0tIE1ldGhvZHNcbiAgICAgICAgLy8gQ3JlYXRlIHRoZSBnbG9iYWwgZnVuY3Rpb25zXG4gICAgICAgIHRoaXMuZ2xvYmFsID0ge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBTZXQgdGhlIHNhbWUgZ2l2ZW4gZWxlbWVudCB2YWx1ZSBmb3IgZWFjaCBlbGVtZW50cyBpbiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0LCBhbmQgZm9ybWF0IHRob3NlIGVsZW1lbnRzIGltbWVkaWF0ZWx5XG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfSBuZXdWYWx1ZSBUaGUgdmFsdWUgbXVzdCBiZSBhIG51bWJlciBvciBhIG51bWVyaWMgc3RyaW5nXG4gICAgICAgICAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9ucyBBIHNldHRpbmdzIG9iamVjdCB0aGF0IHdpbGwgb3ZlcnJpZGUgdGhlIGN1cnJlbnQgc2V0dGluZ3MuIE5vdGU6IHRoZSB1cGRhdGUgaXMgZG9uZSBvbmx5IGlmIHRoZSBgbmV3VmFsdWVgIGlzIGRlZmluZWQuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHNldDogKG5ld1ZhbHVlLCBvcHRpb25zID0gbnVsbCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QuZm9yRWFjaChhTk9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFOT2JqZWN0LnNldChuZXdWYWx1ZSwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNldCB0aGUgdmFsdWUgZ2l2ZW4gdmFsdWUgZGlyZWN0bHkgYXMgdGhlIERPTSBlbGVtZW50IHZhbHVlLCB3aXRob3V0IGZvcm1hdHRpbmcgaXQgYmVmb3JlaGFuZC5cbiAgICAgICAgICAgICAqIFRoaXMgc2V0cyB0aGUgc2FtZSB1bmZvcm1hdHRlZCB2YWx1ZSBmb3IgZWFjaCBlbGVtZW50cyBpbiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0LlxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ30gdmFsdWVcbiAgICAgICAgICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHNldFVuZm9ybWF0dGVkOiAodmFsdWUsIG9wdGlvbnMgPSBudWxsKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYU5PYmplY3Quc2V0VW5mb3JtYXR0ZWQodmFsdWUsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBUaGlzIGlzIGFuIGFsaWFzIG9mIHRoZSBgZ2V0TnVtZXJpY1N0cmluZygpYCBmdW5jdGlvbiwgYW5kIHNob3VsZCBub3QgYmUgdXNlZCBhbnltb3JlLlxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEBwYXJhbSB7ZnVuY3Rpb258bnVsbH0gY2FsbGJhY2sgSWYgYSBjYWxsYmFjayBpcyBwYXNzZWQsIHRoZW4gdGhlIHJlc3VsdCBpcyBwYXNzZWQgdG8gaXQgYXMgaXRzIGZpcnN0IGFyZ3VtZW50LCBhbmQgdGhlIEF1dG9OdW1lcmljIG9iamVjdCBoYXMgaXRzIHNlY29uZFxuICAgICAgICAgICAgICogQHJldHVybnMge0FycmF5PHN0cmluZz59XG4gICAgICAgICAgICAgKiBAZGVwcmVjYXRlZFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IChjYWxsYmFjayA9IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChhTk9iamVjdC5nZXQoKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5fZXhlY3V0ZUNhbGxiYWNrKHJlc3VsdCwgY2FsbGJhY2spO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogUmV0dXJuIGFuIGFycmF5IG9mIHRoZSB1bmZvcm1hdHRlZCB2YWx1ZXMgKGFzIGEgc3RyaW5nKSBvZiBlYWNoIEF1dG9OdW1lcmljIGVsZW1lbnQgb2YgdGhlIGxvY2FsIEF1dG9OdW1lcmljIGVsZW1lbnQgbGlzdFxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEBwYXJhbSB7ZnVuY3Rpb258bnVsbH0gY2FsbGJhY2sgSWYgYSBjYWxsYmFjayBpcyBwYXNzZWQsIHRoZW4gdGhlIHJlc3VsdCBpcyBwYXNzZWQgdG8gaXQgYXMgaXRzIGZpcnN0IGFyZ3VtZW50LCBhbmQgdGhlIEF1dG9OdW1lcmljIG9iamVjdCBoYXMgaXRzIHNlY29uZFxuICAgICAgICAgICAgICogQHJldHVybnMge0FycmF5PHN0cmluZz59XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldE51bWVyaWNTdHJpbmc6IChjYWxsYmFjayA9IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChhTk9iamVjdC5nZXROdW1lcmljU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHRoaXMuX2V4ZWN1dGVDYWxsYmFjayhyZXN1bHQsIGNhbGxiYWNrKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFJldHVybiBhbiBhcnJheSBvZiB0aGUgY3VycmVudCBmb3JtYXR0ZWQgdmFsdWVzIChhcyBhIHN0cmluZykgb2YgZWFjaCBBdXRvTnVtZXJpYyBlbGVtZW50IG9mIHRoZSBsb2NhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3RcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufG51bGx9IGNhbGxiYWNrIElmIGEgY2FsbGJhY2sgaXMgcGFzc2VkLCB0aGVuIHRoZSByZXN1bHQgaXMgcGFzc2VkIHRvIGl0IGFzIGl0cyBmaXJzdCBhcmd1bWVudCwgYW5kIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QgaGFzIGl0cyBzZWNvbmRcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBcnJheTxzdHJpbmc+fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXRGb3JtYXR0ZWQ6IChjYWxsYmFjayA9IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChhTk9iamVjdC5nZXRGb3JtYXR0ZWQoKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5fZXhlY3V0ZUNhbGxiYWNrKHJlc3VsdCwgY2FsbGJhY2spO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogUmV0dXJuIGFuIGFycmF5IG9mIHRoZSBlbGVtZW50IHVuZm9ybWF0dGVkIHZhbHVlcyAoYXMgYSByZWFsIEphdmFzY3JpcHQgbnVtYmVyKSwgZm9yIGVhY2ggZWxlbWVudCBvZiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0XG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHBhcmFtIHtmdW5jdGlvbnxudWxsfSBjYWxsYmFjayBJZiBhIGNhbGxiYWNrIGlzIHBhc3NlZCwgdGhlbiB0aGUgcmVzdWx0IGlzIHBhc3NlZCB0byBpdCBhcyBpdHMgZmlyc3QgYXJndW1lbnQsIGFuZCB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGhhcyBpdHMgc2Vjb25kXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXk8bnVtYmVyPn1cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0TnVtYmVyOiAoY2FsbGJhY2sgPSBudWxsKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gW107XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goYU5PYmplY3QuZ2V0TnVtYmVyKCkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHRoaXMuX2V4ZWN1dGVDYWxsYmFjayhyZXN1bHQsIGNhbGxiYWNrKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFJldHVybnMgdGhlIHVuZm9ybWF0dGVkIHZhbHVlcyAoZm9sbG93aW5nIHRoZSBgb3V0cHV0Rm9ybWF0YCBzZXR0aW5nKSBvZiBlYWNoIGVsZW1lbnQgb2YgdGhlIGxvY2FsIEF1dG9OdW1lcmljIGVsZW1lbnQgbGlzdCBpbnRvIGFuIGFycmF5XG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHBhcmFtIHtmdW5jdGlvbnxudWxsfSBjYWxsYmFjayBJZiBhIGNhbGxiYWNrIGlzIHBhc3NlZCwgdGhlbiB0aGUgcmVzdWx0IGlzIHBhc3NlZCB0byBpdCBhcyBpdHMgZmlyc3QgYXJndW1lbnQsIGFuZCB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGhhcyBpdHMgc2Vjb25kXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXk8c3RyaW5nPn1cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0TG9jYWxpemVkOiAoY2FsbGJhY2sgPSBudWxsKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gW107XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goYU5PYmplY3QuZ2V0TG9jYWxpemVkKCkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHRoaXMuX2V4ZWN1dGVDYWxsYmFjayhyZXN1bHQsIGNhbGxiYWNrKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEZvcmNlIGVhY2ggZWxlbWVudCBvZiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0IHRvIHJlZm9ybWF0IGl0cyB2YWx1ZVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICByZWZvcm1hdDogKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QuZm9yRWFjaChhTk9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFOT2JqZWN0LnJlZm9ybWF0KCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFJlbW92ZSB0aGUgZm9ybWF0dGluZyBhbmQga2VlcCBvbmx5IHRoZSByYXcgdW5mb3JtYXR0ZWQgdmFsdWUgKGFzIGEgbnVtZXJpY1N0cmluZykgaW4gZWFjaCBlbGVtZW50cyBvZiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHVuZm9ybWF0OiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYU5PYmplY3QudW5mb3JtYXQoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogUmVtb3ZlIHRoZSBmb3JtYXR0aW5nIGFuZCBrZWVwIG9ubHkgdGhlIGxvY2FsaXplZCB1bmZvcm1hdHRlZCB2YWx1ZSBpbiB0aGUgZWxlbWVudCwgd2l0aCB0aGUgb3B0aW9uIHRvIG92ZXJyaWRlIHRoZSBkZWZhdWx0IG91dHB1dEZvcm1hdCBpZiBuZWVkZWRcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBAcGFyYW0ge251bGx8c3RyaW5nfSBmb3JjZWRPdXRwdXRGb3JtYXQgSWYgc2V0IHRvIHNvbWV0aGluZyBkaWZmZXJlbnQgdGhhbiBgbnVsbGAsIHRoZW4gdGhpcyBpcyB1c2VkIGFzIGFuIG92ZXJyaWRpbmcgb3V0cHV0Rm9ybWF0IG9wdGlvblxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICB1bmZvcm1hdExvY2FsaXplZDogKGZvcmNlZE91dHB1dEZvcm1hdCA9IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICBhTk9iamVjdC51bmZvcm1hdExvY2FsaXplZChmb3JjZWRPdXRwdXRGb3JtYXQpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBVcGRhdGVzIHRoZSBBdXRvTnVtZXJpYyBzZXR0aW5ncywgYW5kIGltbWVkaWF0ZWx5IGZvcm1hdCB0aGUgZWxlbWVudHMgYWNjb3JkaW5nbHksIGZvciBlYWNoIGVsZW1lbnRzIG9mIHRoZSBsb2NhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3RcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBAcGFyYW0ge29iamVjdH0gbmV3T3B0aW9ucyBUaGlzIGNhbiBiZSBlaXRoZXIgb25lIG9yIG1vcmUgb3B0aW9uIG9iamVjdHNcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgdXBkYXRlOiAoLi4ubmV3T3B0aW9ucykgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QuZm9yRWFjaChhTk9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFOT2JqZWN0LnVwZGF0ZSguLi5uZXdPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogUmV0dXJuIGB0cnVlYCBpZiAqYWxsKiB0aGUgYXV0b051bWVyaWMtbWFuYWdlZCBlbGVtZW50cyBhcmUgcHJpc3RpbmUsIGlmIHRoZWlyIHJhdyB2YWx1ZSBoYXNuJ3QgY2hhbmdlZC5cbiAgICAgICAgICAgICAqIEJ5IGRlZmF1bHQsIHRoaXMgcmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHJhdyB1bmZvcm1hdHRlZCB2YWx1ZSBpcyBzdGlsbCB0aGUgc2FtZSBldmVuIGlmIHRoZSBmb3JtYXR0ZWQgb25lIGhhcyBjaGFuZ2VkIChkdWUgdG8gYSBjb25maWd1cmF0aW9uIHVwZGF0ZSBmb3IgaW5zdGFuY2UpLlxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gY2hlY2tPbmx5UmF3VmFsdWUgSWYgc2V0IHRvIGB0cnVlYCwgdGhlIHByaXN0aW5lIHZhbHVlIGlzIGRvbmUgb24gdGhlIHJhdyB1bmZvcm1hdHRlZCB2YWx1ZSwgbm90IHRoZSBmb3JtYXR0ZWQgb25lLiBJZiBzZXQgdG8gYGZhbHNlYCwgdGhpcyBhbHNvIGNoZWNrcyB0aGF0IHRoZSBmb3JtYXR0ZWQgdmFsdWUgaGFzbid0IGNoYW5nZWQuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgaXNQcmlzdGluZTogKGNoZWNrT25seVJhd1ZhbHVlID0gdHJ1ZSkgPT4ge1xuICAgICAgICAgICAgICAgIGxldCBpc1ByaXN0aW5lID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNQcmlzdGluZSAmJiAhYU5PYmplY3QuaXNQcmlzdGluZShjaGVja09ubHlSYXdWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzUHJpc3RpbmUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzUHJpc3RpbmU7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEV4ZWN1dGUgdGhlIGBjbGVhcigpYCBtZXRob2Qgb24gZWFjaCBBdXRvTnVtZXJpYyBvYmplY3QgaW4gdGhlIGxvY2FsIEF1dG9OdW1lcmljIGVsZW1lbnQgbGlzdFxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gZm9yY2VDbGVhckFsbFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBjbGVhcjogKGZvcmNlQ2xlYXJBbGwgPSBmYWxzZSkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QuZm9yRWFjaChhTk9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFOT2JqZWN0LmNsZWFyKGZvcmNlQ2xlYXJBbGwpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBFeGVjdXRlIHRoZSBgcmVtb3ZlKClgIG1ldGhvZCBvbiBlYWNoIEF1dG9OdW1lcmljIG9iamVjdCBpbiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHJlbW92ZTogKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QuZm9yRWFjaChhTk9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFOT2JqZWN0LnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBFeGVjdXRlIHRoZSBgd2lwZSgpYCBtZXRob2Qgb24gZWFjaCBBdXRvTnVtZXJpYyBvYmplY3QgaW4gdGhlIGxvY2FsIEF1dG9OdW1lcmljIGVsZW1lbnQgbGlzdFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICB3aXBlOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYU5PYmplY3Qud2lwZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBFeGVjdXRlIHRoZSBgbnVrZSgpYCBtZXRob2Qgb24gZWFjaCBBdXRvTnVtZXJpYyBvYmplY3QgaW4gdGhlIGxvY2FsIEF1dG9OdW1lcmljIGVsZW1lbnQgbGlzdFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBudWtlOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYU5PYmplY3QubnVrZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBnaXZlbiBBdXRvTnVtZXJpYyBvYmplY3QgKG9yIERPTSBlbGVtZW50KSBpcyBpbiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0XG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fEF1dG9OdW1lcmljfSBkb21FbGVtZW50T3JBdXRvTnVtZXJpY09iamVjdFxuICAgICAgICAgICAgICogQHJldHVybnMgeyp9XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGhhczogZG9tRWxlbWVudE9yQXV0b051bWVyaWNPYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgICAgICAgICAgaWYgKGRvbUVsZW1lbnRPckF1dG9OdW1lcmljT2JqZWN0IGluc3RhbmNlb2YgQXV0b051bWVyaWMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5oYXMoZG9tRWxlbWVudE9yQXV0b051bWVyaWNPYmplY3Qubm9kZSgpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0Lmhhcyhkb21FbGVtZW50T3JBdXRvTnVtZXJpY09iamVjdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQWRkIGFuIGV4aXN0aW5nIEF1dG9OdW1lcmljIG9iamVjdCAob3IgRE9NIGVsZW1lbnQpIHRvIHRoZSBsb2NhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3QsIHVzaW5nIHRoZSBET00gZWxlbWVudCBhcyB0aGUga2V5LlxuICAgICAgICAgICAgICogVGhpcyBtYW5hZ2VzIHRoZSBjYXNlIHdoZXJlIGBhZGRPYmplY3RgIGlzIHVzZWQgb24gYW4gQXV0b051bWVyaWMgb2JqZWN0IHRoYXQgYWxyZWFkeSBoYXMgbXVsdGlwbGUgZWxlbWVudHMgaW4gaXRzIGxvY2FsIGxpc3QuXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fEF1dG9OdW1lcmljfSBkb21FbGVtZW50T3JBdXRvTnVtZXJpY09iamVjdFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBhZGRPYmplY3Q6IGRvbUVsZW1lbnRPckF1dG9OdW1lcmljT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAvLyBTdGFydCB3aXRoIHRoZSBzYW1lIGRhdGEsIHdoYXRldmVyIHRoZSB1c2VyIHBhc3NlZCBhcyBhcmd1bWVudHNcbiAgICAgICAgICAgICAgICBsZXQgZG9tRWxlbWVudDtcbiAgICAgICAgICAgICAgICBsZXQgb3RoZXJBdXRvTnVtZXJpY09iamVjdDtcbiAgICAgICAgICAgICAgICBpZiAoZG9tRWxlbWVudE9yQXV0b051bWVyaWNPYmplY3QgaW5zdGFuY2VvZiBBdXRvTnVtZXJpYykge1xuICAgICAgICAgICAgICAgICAgICBkb21FbGVtZW50ID0gZG9tRWxlbWVudE9yQXV0b051bWVyaWNPYmplY3Qubm9kZSgpO1xuICAgICAgICAgICAgICAgICAgICBvdGhlckF1dG9OdW1lcmljT2JqZWN0ID0gZG9tRWxlbWVudE9yQXV0b051bWVyaWNPYmplY3Q7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZG9tRWxlbWVudCA9IGRvbUVsZW1lbnRPckF1dG9OdW1lcmljT2JqZWN0O1xuICAgICAgICAgICAgICAgICAgICBvdGhlckF1dG9OdW1lcmljT2JqZWN0ID0gQXV0b051bWVyaWMuZ2V0QXV0b051bWVyaWNFbGVtZW50KGRvbUVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIHRoZSBjdXJyZW50IGF1dG9OdW1lcmljIG9iamVjdCBoYXMgYSBsb2NhbCBsaXN0XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9oYXNMb2NhbExpc3QoKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jcmVhdGVMb2NhbExpc3QoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiB0aGUgb3RoZXIgYXV0b051bWVyaWMgb2JqZWN0IGhhcyBhIGxvY2FsIGxpc3QuLi5cbiAgICAgICAgICAgICAgICBsZXQgb3RoZXJBTkxvY2FsTGlzdCA9IG90aGVyQXV0b051bWVyaWNPYmplY3QuX2dldExvY2FsTGlzdCgpO1xuICAgICAgICAgICAgICAgIGlmIChvdGhlckFOTG9jYWxMaXN0LnNpemUgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gU3BlY2lhbCBjYXNlIGlmIHRoZSBvdGhlciBBdXRvTnVtZXJpYyBvYmplY3QgaGFzIGFuIGVtcHR5IGxvY2FsIGxpc3QsIHRoZW4gcG9wdWxhdGUgaXRzZWxmIHRvIGl0XG4gICAgICAgICAgICAgICAgICAgIG90aGVyQXV0b051bWVyaWNPYmplY3QuX2NyZWF0ZUxvY2FsTGlzdCgpO1xuICAgICAgICAgICAgICAgICAgICBvdGhlckFOTG9jYWxMaXN0ID0gb3RoZXJBdXRvTnVtZXJpY09iamVjdC5fZ2V0TG9jYWxMaXN0KCk7IC8vIFVwZGF0ZSB0aGUgb3RoZXIgbG9jYWwgbGlzdFxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGxldCBtZXJnZWRMb2NhbExpc3RzO1xuICAgICAgICAgICAgICAgIGlmIChvdGhlckFOTG9jYWxMaXN0IGluc3RhbmNlb2YgTWFwKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIC4uLklmIGl0IGRvZXMsIG1lcmdlIHRoZSBsb2NhbCBsaXN0cyB0b2dldGhlclxuICAgICAgICAgICAgICAgICAgICBtZXJnZWRMb2NhbExpc3RzID0gQXV0b051bWVyaWNIZWxwZXIubWVyZ2VNYXBzKHRoaXMuX2dldExvY2FsTGlzdCgpLCBvdGhlckFOTG9jYWxMaXN0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyAuLi5JZiBub3QsIGp1c3Qgc2V0IHRoZSBjdXJyZW50IGxvY2FsIGxpc3Qgb250byB0aGUgb3RoZXIgQXV0b051bWVyaWMgb2JqZWN0XG4gICAgICAgICAgICAgICAgICAgIC8vIFdlIG5lZWQgdG8gc3BlY2lmeSB0aGUgQXV0b051bWVyaWMgb2JqZWN0LCBvdGhlcndpc2UgdGhlIGBfYWRkVG9Mb2NhbExpc3RgIGZ1bmN0aW9uIHdvdWxkIG5vdCBjb3JyZWN0bHkgYWRkIHRoZSBBdXRvTnVtZXJpYyBvYmplY3Qgc2luY2Ugd2Ugd291bGQgbm90IGhhdmUgYSByZWZlcmVuY2UgdG8gaXQsIGJ1dCBhIHJlZmVyZW5jZSB0byB0aGUgY3VycmVudCBBdXRvTnVtZXJpYyBvYmplY3Qgb24gd2hpY2ggaXMgY2FsbGVkIHRoaXMgbWV0aG9kLlxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9hZGRUb0xvY2FsTGlzdChkb21FbGVtZW50LCBvdGhlckF1dG9OdW1lcmljT2JqZWN0KTtcbiAgICAgICAgICAgICAgICAgICAgbWVyZ2VkTG9jYWxMaXN0cyA9IHRoaXMuX2dldExvY2FsTGlzdCgpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgcmVzdWx0aW5nIGxpc3QsIG9uIGFsbCB0aGUgb2JqZWN0cyBvZiB0aGF0IGxvY2FsIGxpc3QgKHNvIHRoYXQgd2UgY2FuIGluZGlmZmVyZW50bHkgdXNlIGBpbml0KClgIG9uIGFueSBvYmplY3QgYmVsb25naW5nIHRvIHRoYXQgbGlzdClcbiAgICAgICAgICAgICAgICBtZXJnZWRMb2NhbExpc3RzLmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICBhTk9iamVjdC5fc2V0TG9jYWxMaXN0KG1lcmdlZExvY2FsTGlzdHMpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBSZW1vdmUgdGhlIGdpdmVuIEF1dG9OdW1lcmljIG9iamVjdCAob3IgRE9NIGVsZW1lbnQpIGZyb20gdGhlIGxvY2FsIEF1dG9OdW1lcmljIGVsZW1lbnQgbGlzdCwgdXNpbmcgdGhlIERPTSBlbGVtZW50IGFzIHRoZSBrZXkuXG4gICAgICAgICAgICAgKiBJZiB0aGlzIGZ1bmN0aW9uIGF0dGVtcHRzIHRvIHJlbW92ZSB0aGUgY3VycmVudCBBdXRvTnVtZXJpYyBvYmplY3QgZnJvbSB0aGUgbG9jYWwgbGlzdCwgYSB3YXJuaW5nIGlzIHNob3duLCBidXQgdGhlIGRlbGV0aW9uIGlzIHN0aWxsIGRvbmUuXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogU3BlY2lhbCBjYXNlcyA6XG4gICAgICAgICAgICAgKiAtIElmIHRoZSBjdXJyZW50IG9iamVjdCByZW1vdmVzIGl0c2VsZiwgdGhlbiBpdCdzIHJlbW92ZWQgZnJvbSB0aGUgc2hhcmVkIGxvY2FsIGxpc3QsIHRoZW4gYSBuZXcgZW1wdHkgbG9jYWwgbGlzdCBpcyB1c2VkL2NyZWF0ZWRcbiAgICAgICAgICAgICAqIC0gSWYgYW5vdGhlciBvYmplY3QgcmVtb3ZlIHRoaXMgb2JqZWN0LCB0aGVuIGEgbG9jYWwgbGlzdCB3aXRoIG9ubHkgdGhpcyBvYmplY3QgaXMgdXNlZC9jcmVhdGVkXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fEF1dG9OdW1lcmljfSBkb21FbGVtZW50T3JBdXRvTnVtZXJpY09iamVjdFxuICAgICAgICAgICAgICogQHBhcmFtIHtib29sZWFufSBrZWVwQ3VycmVudEFOT2JqZWN0IElmIHNldCB0byBgZmFsc2VgLCB0aGVuIHRoZSBmdW5jdGlvbiB3aWxsIGFsc28gcmVtb3ZlIHRoZSBjdXJyZW50IEF1dG9OdW1lcmljIG9iamVjdCBpZiBhc2tlZCwgb3RoZXJ3aXNlIGl0IHdpbGwgaWdub3JlIGl0IGFuZCBwcmludCBhIHdhcm5pbmcgbWVzc2FnZVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICByZW1vdmVPYmplY3Q6IChkb21FbGVtZW50T3JBdXRvTnVtZXJpY09iamVjdCwga2VlcEN1cnJlbnRBTk9iamVjdCA9IGZhbHNlKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gU3RhcnQgd2l0aCB0aGUgc2FtZSBkYXRhLCB3aGF0ZXZlciB0aGUgdXNlciBwYXNzZWQgYXMgYXJndW1lbnRzXG4gICAgICAgICAgICAgICAgbGV0IGRvbUVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgbGV0IG90aGVyQXV0b051bWVyaWNPYmplY3Q7XG4gICAgICAgICAgICAgICAgaWYgKGRvbUVsZW1lbnRPckF1dG9OdW1lcmljT2JqZWN0IGluc3RhbmNlb2YgQXV0b051bWVyaWMpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9tRWxlbWVudCA9IGRvbUVsZW1lbnRPckF1dG9OdW1lcmljT2JqZWN0Lm5vZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgb3RoZXJBdXRvTnVtZXJpY09iamVjdCA9IGRvbUVsZW1lbnRPckF1dG9OdW1lcmljT2JqZWN0O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBkb21FbGVtZW50T3JBdXRvTnVtZXJpY09iamVjdDtcbiAgICAgICAgICAgICAgICAgICAgb3RoZXJBdXRvTnVtZXJpY09iamVjdCA9IEF1dG9OdW1lcmljLmdldEF1dG9OdW1lcmljRWxlbWVudChkb21FbGVtZW50KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBSZW1vdmUgdGhlIG90aGVyIG9iamVjdCBmcm9tIHRoZSBsb2NhbCBsaXN0XG4gICAgICAgICAgICAgICAgY29uc3QgaW5pdGlhbENvbXBsZXRlTG9jYWxMaXN0ID0gdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdDtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LmRlbGV0ZShkb21FbGVtZW50KTtcblxuICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgbG9jYWwgbGlzdCBmb3IgYWxsIG9iamVjdHMgaW4gaXRcbiAgICAgICAgICAgICAgICBpbml0aWFsQ29tcGxldGVMb2NhbExpc3QuZm9yRWFjaChhTk9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFOT2JqZWN0Ll9zZXRMb2NhbExpc3QodGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdCk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICBpZiAoIWtlZXBDdXJyZW50QU5PYmplY3QgJiYgZG9tRWxlbWVudCA9PT0gdGhpcy5ub2RlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBvYmplY3QgaXMgcmVtb3ZlZCBieSBpdHNlbGZcbiAgICAgICAgICAgICAgICAgICAgLy8gRW1wdHkgdGhlIG9iamVjdCBsb2NhbCBsaXN0XG4gICAgICAgICAgICAgICAgICAgIG90aGVyQXV0b051bWVyaWNPYmplY3QuX3NldExvY2FsTGlzdChuZXcgTWFwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIG9iamVjdCBpcyByZW1vdmVkIGJ5IGFub3RoZXIgb2JqZWN0XG4gICAgICAgICAgICAgICAgICAgIC8vIFNldCB0aGUgbG9jYWwgbGlzdCBmb3IgdGhlIHJlbW92ZWQgb2JqZWN0LCB3aXRoIG9ubHkgdGhpcyBvYmplY3QgaW4gaXRcbiAgICAgICAgICAgICAgICAgICAgb3RoZXJBdXRvTnVtZXJpY09iamVjdC5fY3JlYXRlTG9jYWxMaXN0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBSZW1vdmUgYWxsIGVsZW1lbnRzIGZyb20gdGhlIHNoYXJlZCBsaXN0LCBlZmZlY3RpdmVseSBlbXB0eWluZyBpdC5cbiAgICAgICAgICAgICAqIFRoaXMgaXMgdGhlIGVxdWl2YWxlbnQgb2YgY2FsbGluZyBgZGV0YWNoKClgIG9uIGVhY2ggb2YgaXRzIGVsZW1lbnRzLlxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0ga2VlcEVhY2hBTk9iamVjdEluSXRzT3duTGlzdCBJZiBzZXQgdG8gYHRydWVgLCB0aGVuIGluc3RlYWQgb2YgY29tcGxldGVseSBlbXB0eWluZyB0aGUgbG9jYWwgbGlzdCBvZiBlYWNoIEF1dG9OdW1lcmljIG9iamVjdHMsIGVhY2ggb25lIG9mIHRob3NlIGtlZXBzIGl0c2VsZiBpbiBpdHMgb3duIGxvY2FsIGxpc3RcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZW1wdHk6IChrZWVwRWFjaEFOT2JqZWN0SW5JdHNPd25MaXN0ID0gZmFsc2UpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBpbml0aWFsQ29tcGxldGVMb2NhbExpc3QgPSB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0O1xuXG4gICAgICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBsb2NhbCBsaXN0IGZvciBhbGwgb2JqZWN0cyBpbiBpdFxuICAgICAgICAgICAgICAgIGluaXRpYWxDb21wbGV0ZUxvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtlZXBFYWNoQU5PYmplY3RJbkl0c093bkxpc3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFOT2JqZWN0Ll9jcmVhdGVMb2NhbExpc3QoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFOT2JqZWN0Ll9zZXRMb2NhbExpc3QobmV3IE1hcCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogUmV0dXJuIGFuIGFycmF5IGNvbnRhaW5pbmcgYWxsIHRoZSBBdXRvTnVtZXJpYyBET00gZWxlbWVudHMgdGhhdCBoYXZlIGJlZW4gaW5pdGlhbGl6ZWQgYnkgZWFjaCBvdGhlclxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBcnJheTxIVE1MRWxlbWVudD59XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGVsZW1lbnRzOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gW107XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goYU5PYmplY3Qubm9kZSgpKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFJldHVybiB0aGUgYE1hcGAgb2JqZWN0IGRpcmVjdGx5XG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7TWFwfVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXRMaXN0OiAoKSA9PiB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFJldHVybiB0aGUgbnVtYmVyIG9mIGVsZW1lbnQgaW4gdGhlIGxvY2FsIEF1dG9OdW1lcmljIGVsZW1lbnQgbGlzdFxuICAgICAgICAgICAgICogQHJldHVybnMge251bWJlcn1cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgc2l6ZTogKCkgPT4gdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5zaXplLFxuICAgICAgICB9O1xuXG4gICAgICAgIC8vIENyZWF0ZSB0aGUgZnVuY3Rpb25zIHRoYXQgd2lsbCBhbGxvdyB0byBjaGFuZ2UgZWFjaCBzZXR0aW5nIG9uZSBieSBvbmVcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEZvciBlYWNoIG9wdGlvbnMsIHdlIGRlZmluZSBpZiB3ZSBuZWVkIHRvIHJlZm9ybWF0IHRoZSBlbGVtZW50IGNvbnRlbnQgKGRvZXMgY2hhbmdpbmcgdGhlIG9wdGlvbnMgc2hvdWxkIGNoYW5nZSB0aGUgd2F5IGl0cyB2YWx1ZSBpcyBkaXNwbGF5ZWQ/KS5cbiAgICAgICAgICogSWYgeWVzLCB0aGVuIHdlIHVzZSB0aGUgYHVwZGF0ZSgpYCBmb3IgZm9yY2UgYSByZWZvcm1hdCwgb3RoZXJ3aXNlLCB3ZSBqdXN0IHVwZGF0ZSB0aGUgYHNldHRpbmdzYCBvYmplY3QuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLm9wdGlvbnMgPSB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFJlc2V0IGFueSBvcHRpb25zIHNldCBwcmV2aW91c2x5LCBieSBvdmVyd3JpdGluZyB0aGVtIHdpdGggdGhlIGRlZmF1bHQgc2V0dGluZ3NcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHJlc2V0ICAgICAgICAgICAgICAgICAgICAgICAgOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgLy9UT0RPIEFkZCBhIGBzZXR0aW5nc2AgcGFyYW1ldGVyIHNvIHRoYXQgdGhlIHVzZXIgY2FuIHJlc2V0IHRvIGEgc3BlY2lmaWMgc2V0IG9mIHNldHRpbmdzLiBUaGlzIGlzIGRpZmZlcmVudCB0aGFuIHVwZGF0ZSBzaW5jZSBpdCBkcm9wcyBhbnkgbm9uLWRlZmF1bHQgc2V0dGluZ3MgYmVmb3JlIHVzaW5nIHRob3NlIG5ldyBzZXR0aW5ncy5cbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzID0geyByYXdWYWx1ZSA6IHRoaXMuZGVmYXVsdFJhd1ZhbHVlIH07IC8vIEhlcmUgd2UgcGFzcyB0aGUgZGVmYXVsdCByYXdWYWx1ZSBpbiBvcmRlciB0byBwcmV2ZW50IHNob3dpbmcgYSB3YXJuaW5nIHRoYXQgd2UgdHJ5IHRvIHNldCBhbiBgdW5kZWZpbmVkYCB2YWx1ZVxuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKEF1dG9OdW1lcmljLmRlZmF1bHRTZXR0aW5ncyk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBhbGxvd0RlY2ltYWxQYWRkaW5nICAgICAgICAgIDogYWxsb3dEZWNpbWFsUGFkZGluZyA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBhbGxvd0RlY2ltYWxQYWRkaW5nIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYWx3YXlzQWxsb3dEZWNpbWFsQ2hhcmFjdGVyICA6IGFsd2F5c0FsbG93RGVjaW1hbENoYXJhY3RlciA9PiB7IC8vRklYTUUgVGVzdCB0aGlzXG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBhbHdheXNBbGxvd0RlY2ltYWxDaGFyYWN0ZXIgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Gb2N1cyAgICAgICAgIDogY2FyZXRQb3NpdGlvbk9uRm9jdXMgPT4geyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuY2FyZXRQb3NpdGlvbk9uRm9jdXMgPSBjYXJldFBvc2l0aW9uT25Gb2N1cztcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNyZWF0ZUxvY2FsTGlzdCAgICAgICAgICAgICAgOiBjcmVhdGVMb2NhbExpc3QgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuY3JlYXRlTG9jYWxMaXN0ID0gY3JlYXRlTG9jYWxMaXN0O1xuXG4gICAgICAgICAgICAgICAgLy8gRGVsZXRlIHRoZSBsb2NhbCBsaXN0IHdoZW4gdGhpcyBpcyBzZXQgdG8gYGZhbHNlYCwgY3JlYXRlIGl0IGlmIHRoaXMgaXMgc2V0IHRvIGB0cnVlYCBhbmQgdGhlcmUgaXMgbm90IHByZS1leGlzdGluZyBsaXN0XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY3JlYXRlTG9jYWxMaXN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5faGFzTG9jYWxMaXN0KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NyZWF0ZUxvY2FsTGlzdCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGVsZXRlTG9jYWxMaXN0KCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY3VycmVuY3lTeW1ib2wgICAgICAgICAgICAgICA6IGN1cnJlbmN5U3ltYm9sID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IGN1cnJlbmN5U3ltYm9sIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgICAgICA6IGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50IH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGVjaW1hbENoYXJhY3RlciAgICAgICAgICAgICA6IGRlY2ltYWxDaGFyYWN0ZXIgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgZGVjaW1hbENoYXJhY3RlciB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZSAgOiBkZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlID0gZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBVcGRhdGUgdGhlIGRlY2ltYWwgcGxhY2VzIGdsb2JhbGx5LCB3aGljaCBtZWFucyB0aGlzIG92ZXJyaWRlIGFueSBwcmV2aW91c2x5IHNldCBudW1iZXIgb2YgZGVjaW1hbCBzaG93biBvbiBmb2N1cywgb24gYmx1ciwgb3IgaW4gdGhlIHJhdyB2YWx1ZS5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBAcGFyYW0ge2ludH0gZGVjaW1hbFBsYWNlc1xuICAgICAgICAgICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBkZWNpbWFsUGxhY2VzICAgICAgICAgICAgICAgIDogZGVjaW1hbFBsYWNlcyA9PiB7XG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZygnVXNpbmcgYG9wdGlvbnMuZGVjaW1hbFBsYWNlcygpYCBpbnN0ZWFkIG9mIGNhbGxpbmcgdGhlIHNwZWNpZmljIGBvcHRpb25zLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSgpYCwgYG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cygpYCBhbmQgYG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyKClgIG1ldGhvZHMgd2lsbCByZXNldCB0aG9zZSBvcHRpb25zLlxcblBsZWFzZSBjYWxsIHRoZSBzcGVjaWZpYyBtZXRob2RzIGlmIHlvdSBkbyBub3Qgd2FudCB0byByZXNldCB0aG9zZS4nLCB0aGlzLnNldHRpbmdzLnNob3dXYXJuaW5ncyk7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBkZWNpbWFsUGxhY2VzIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlICAgICAgICA6IGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9PiB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIgICAgIDogZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IGRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMgICAgOiBkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkZWZhdWx0VmFsdWVPdmVycmlkZSAgICAgICAgIDogZGVmYXVsdFZhbHVlT3ZlcnJpZGUgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgZGVmYXVsdFZhbHVlT3ZlcnJpZGUgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkaWdpdGFsR3JvdXBTcGFjaW5nICAgICAgICAgIDogZGlnaXRhbEdyb3VwU3BhY2luZyA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBkaWdpdGFsR3JvdXBTcGFjaW5nIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGlnaXRHcm91cFNlcGFyYXRvciAgICAgICAgICA6IGRpZ2l0R3JvdXBTZXBhcmF0b3IgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgZGlnaXRHcm91cFNlcGFyYXRvciB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRpdmlzb3JXaGVuVW5mb2N1c2VkICAgICAgICAgOiBkaXZpc29yV2hlblVuZm9jdXNlZCA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBkaXZpc29yV2hlblVuZm9jdXNlZCB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVtcHR5SW5wdXRCZWhhdmlvciAgICAgICAgICAgOiBlbXB0eUlucHV0QmVoYXZpb3IgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnJhd1ZhbHVlID09PSBudWxsICYmIGVtcHR5SW5wdXRCZWhhdmlvciAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IubnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBTcGVjaWFsIGNhc2UgOiBpZiB0aGUgY3VycmVudCBgcmF3VmFsdWVgIGlzIGBudWxsYCBhbmQgdGhlIGBlbXB0eUlucHV0QmVoYXZpb3JgIGlzIGNoYW5nZWQgdG8gc29tZXRoaW5nIGVsc2UgdGhhbiBgJ251bGwnYCwgdGhlbiBpdCBtYWtlcyB0aGF0IGByYXdWYWx1ZWAgaW52YWxpZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gSGVyZSB3ZSBjYW4gZWl0aGVyIHByZXZlbnQgdGhlIG9wdGlvbiB1cGRhdGUgYW5kIHRocm93IGFuIGVycm9yLCBvciBzdGlsbCBhY2NlcHQgdGhlIG9wdGlvbiB1cGRhdGUgYW5kIHVwZGF0ZSB0aGUgdmFsdWUgZnJvbSBgbnVsbGAgdG8gYCcnYC5cbiAgICAgICAgICAgICAgICAgICAgLy8gV2UgY2Fubm90IGtlZXAgYHJhd1ZhbHVlYCB0byBgbnVsbGAgc2luY2UgaWYgYGVtcHR5SW5wdXRCZWhhdmlvcmAgaXMgbm90IHNldCB0byBgbnVsbGAsIGxvdHMgb2YgZnVuY3Rpb24gYXNzdW1lIGByYXdWYWx1ZWAgaXMgYSBzdHJpbmcuXG4gICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLndhcm5pbmcoYFlvdSBhcmUgdHJ5aW5nIHRvIG1vZGlmeSB0aGUgXFxgZW1wdHlJbnB1dEJlaGF2aW9yXFxgIG9wdGlvbiB0byBzb21ldGhpbmcgZGlmZmVyZW50IHRoYW4gXFxgJ251bGwnXFxgICgke2VtcHR5SW5wdXRCZWhhdmlvcn0pLCBidXQgdGhlIGVsZW1lbnQgcmF3IHZhbHVlIGlzIGN1cnJlbnRseSBzZXQgdG8gXFxgbnVsbFxcYC4gVGhpcyB3b3VsZCByZXN1bHQgaW4gYW4gaW52YWxpZCBcXGByYXdWYWx1ZVxcYC4gSW4gb3JkZXIgdG8gZml4IHRoYXQsIHRoZSBlbGVtZW50IHZhbHVlIGhhcyBiZWVuIGNoYW5nZWQgdG8gdGhlIGVtcHR5IHN0cmluZyBcXGAnJ1xcYC5gLCB0aGlzLnNldHRpbmdzLnNob3dXYXJuaW5ncyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmF3VmFsdWUgPSAnJztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IGVtcHR5SW5wdXRCZWhhdmlvciB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGV2ZW50QnViYmxlcyAgICAgICAgICAgICAgICAgOiBldmVudEJ1YmJsZXMgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuZXZlbnRCdWJibGVzID0gZXZlbnRCdWJibGVzO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZXZlbnRJc0NhbmNlbGFibGUgICAgICAgICAgICA6IGV2ZW50SXNDYW5jZWxhYmxlID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmV2ZW50SXNDYW5jZWxhYmxlID0gZXZlbnRJc0NhbmNlbGFibGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBmYWlsT25Vbmtub3duT3B0aW9uICAgICAgICAgIDogZmFpbE9uVW5rbm93bk9wdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5mYWlsT25Vbmtub3duT3B0aW9uID0gZmFpbE9uVW5rbm93bk9wdGlvbjsgLy9GSVhNRSB0ZXN0IHRoaXNcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZvcm1hdE9uUGFnZUxvYWQgICAgICAgICAgICAgOiBmb3JtYXRPblBhZ2VMb2FkID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmZvcm1hdE9uUGFnZUxvYWQgPSBmb3JtYXRPblBhZ2VMb2FkOyAvL0ZJWE1FIHRlc3QgdGhpc1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaGlzdG9yeVNpemUgICAgICAgICAgICAgICAgICA6IGhpc3RvcnlTaXplID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmhpc3RvcnlTaXplID0gaGlzdG9yeVNpemU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpc0NhbmNlbGxhYmxlICAgICAgICAgICAgICAgIDogaXNDYW5jZWxsYWJsZSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5pc0NhbmNlbGxhYmxlID0gaXNDYW5jZWxsYWJsZTsgLy9GSVhNRSB0ZXN0IHRoaXNcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxlYWRpbmdaZXJvICAgICAgICAgICAgICAgICAgOiBsZWFkaW5nWmVybyA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBsZWFkaW5nWmVybyB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG1heGltdW1WYWx1ZSAgICAgICAgICAgICAgICAgOiBtYXhpbXVtVmFsdWUgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgbWF4aW11bVZhbHVlIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbWluaW11bVZhbHVlICAgICAgICAgICAgICAgICA6IG1pbmltdW1WYWx1ZSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBtaW5pbXVtVmFsdWUgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBtb2RpZnlWYWx1ZU9uV2hlZWwgICAgICAgICAgIDogbW9kaWZ5VmFsdWVPbldoZWVsID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLm1vZGlmeVZhbHVlT25XaGVlbCA9IG1vZGlmeVZhbHVlT25XaGVlbDsgLy9GSVhNRSB0ZXN0IHRoaXNcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyICAgOiBuZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ciA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBuZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ciB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50OiBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG5lZ2F0aXZlU2lnbkNoYXJhY3RlciAgICAgICAgOiBuZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgbmVnYXRpdmVTaWduQ2hhcmFjdGVyIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbm9FdmVudExpc3RlbmVycyAgICAgICAgICAgICA6IG5vRXZlbnRMaXN0ZW5lcnMgPT4geyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICAgICAgICAgIGlmIChub0V2ZW50TGlzdGVuZXJzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5vRXZlbnRMaXN0ZW5lcnMubm9FdmVudHMgJiYgdGhpcy5zZXR0aW5ncy5ub0V2ZW50TGlzdGVuZXJzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5vRXZlbnRMaXN0ZW5lcnMuYWRkRXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSB0aGUgZXZlbnRzIG9uY2VcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVtb3ZlRXZlbnRMaXN0ZW5lcnMoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IG5vRXZlbnRMaXN0ZW5lcnMgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvbkludmFsaWRQYXN0ZSAgICAgICAgICAgICAgIDogb25JbnZhbGlkUGFzdGUgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Mub25JbnZhbGlkUGFzdGUgPSBvbkludmFsaWRQYXN0ZTsgLy9GSVhNRSB0ZXN0IHRoaXNcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG91dHB1dEZvcm1hdCAgICAgICAgICAgICAgICAgOiBvdXRwdXRGb3JtYXQgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Mub3V0cHV0Rm9ybWF0ID0gb3V0cHV0Rm9ybWF0O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb3ZlcnJpZGVNaW5NYXhMaW1pdHMgICAgICAgICA6IG92ZXJyaWRlTWluTWF4TGltaXRzID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IG92ZXJyaWRlTWluTWF4TGltaXRzIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcG9zaXRpdmVTaWduQ2hhcmFjdGVyICAgICAgICA6IHBvc2l0aXZlU2lnbkNoYXJhY3RlciA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBwb3NpdGl2ZVNpZ25DaGFyYWN0ZXIgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByYXdWYWx1ZURpdmlzb3IgICAgICAgICAgICAgIDogcmF3VmFsdWVEaXZpc29yID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IHJhd1ZhbHVlRGl2aXNvciB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJlYWRPbmx5ICAgICAgICAgICAgICAgICAgICAgOiByZWFkT25seSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gV2hlbiBjaGFuZ2luZyB0aGUgcmVhZE9ubHkgYXR0cmlidXRlLCB0aGUgcmF3IGFuZCBmb3JtYXR0ZWQgdmFsdWVzIGRvIG5vdCBjaGFuZ2UsIHNvIG5vIG5lZWQgdG8gY2FsbCB0aGUgY29zdGx5ICd1cGRhdGUoKWAgbWV0aG9kXG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5yZWFkT25seSA9IHJlYWRPbmx5O1xuICAgICAgICAgICAgICAgIHRoaXMuX3NldFdyaXRlUGVybWlzc2lvbnMoKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJvdW5kaW5nTWV0aG9kICAgICAgICAgICAgICAgOiByb3VuZGluZ01ldGhvZCA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyByb3VuZGluZ01ldGhvZCB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNhdmVWYWx1ZVRvU2Vzc2lvblN0b3JhZ2UgICAgOiBzYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IHNhdmVWYWx1ZVRvU2Vzc2lvblN0b3JhZ2UgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzeW1ib2xXaGVuVW5mb2N1c2VkICAgICAgICAgIDogc3ltYm9sV2hlblVuZm9jdXNlZCA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBzeW1ib2xXaGVuVW5mb2N1c2VkIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2VsZWN0TnVtYmVyT25seSAgICAgICAgICAgICA6IHNlbGVjdE51bWJlck9ubHkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Muc2VsZWN0TnVtYmVyT25seSA9IHNlbGVjdE51bWJlck9ubHk7IC8vRklYTUUgdGVzdCB0aGlzXG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzZWxlY3RPbkZvY3VzICAgICAgICAgICAgICAgIDogc2VsZWN0T25Gb2N1cyA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5zZWxlY3RPbkZvY3VzID0gc2VsZWN0T25Gb2N1czsgLy9GSVhNRSB0ZXN0IHRoaXNcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNlcmlhbGl6ZVNwYWNlcyAgICAgICAgICAgICAgOiBzZXJpYWxpemVTcGFjZXMgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Muc2VyaWFsaXplU3BhY2VzID0gc2VyaWFsaXplU3BhY2VzOyAvL0ZJWE1FIHRlc3QgdGhpc1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2hvd09ubHlOdW1iZXJzT25Gb2N1cyAgICAgICA6IHNob3dPbmx5TnVtYmVyc09uRm9jdXMgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgc2hvd09ubHlOdW1iZXJzT25Gb2N1cyB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNob3dQb3NpdGl2ZVNpZ24gICAgICAgICAgICAgOiBzaG93UG9zaXRpdmVTaWduID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IHNob3dQb3NpdGl2ZVNpZ24gfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzaG93V2FybmluZ3MgICAgICAgICAgICAgICAgIDogc2hvd1dhcm5pbmdzID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLnNob3dXYXJuaW5ncyA9IHNob3dXYXJuaW5nczsgLy9GSVhNRSB0ZXN0IHRoaXNcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHN0eWxlUnVsZXMgICAgICAgICAgICAgICAgICAgOiBzdHlsZVJ1bGVzID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IHN0eWxlUnVsZXMgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzdWZmaXhUZXh0ICAgICAgICAgICAgICAgICAgIDogc3VmZml4VGV4dCA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBzdWZmaXhUZXh0IH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdW5mb3JtYXRPbkhvdmVyICAgICAgICAgICAgICA6IHVuZm9ybWF0T25Ib3ZlciA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy51bmZvcm1hdE9uSG92ZXIgPSB1bmZvcm1hdE9uSG92ZXI7IC8vRklYTUUgdGVzdCB0aGlzXG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB1bmZvcm1hdE9uU3VibWl0ICAgICAgICAgICAgIDogdW5mb3JtYXRPblN1Ym1pdCA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy51bmZvcm1hdE9uU3VibWl0ID0gdW5mb3JtYXRPblN1Ym1pdDsgLy9GSVhNRSB0ZXN0IHRoaXNcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHZhbHVlc1RvU3RyaW5ncyAgICAgICAgICAgICAgOiB2YWx1ZXNUb1N0cmluZ3MgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgdmFsdWVzVG9TdHJpbmdzIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgd2F0Y2hFeHRlcm5hbENoYW5nZXMgICAgICAgICA6IHdhdGNoRXh0ZXJuYWxDaGFuZ2VzID0+IHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IHdhdGNoRXh0ZXJuYWxDaGFuZ2VzIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgd2hlZWxPbiAgICAgICAgICAgICAgICAgICAgICA6IHdoZWVsT24gPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Mud2hlZWxPbiA9IHdoZWVsT247IC8vRklYTUUgdGVzdCB0aGlzXG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB3aGVlbFN0ZXAgICAgICAgICAgICAgICAgICAgIDogd2hlZWxTdGVwID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLndoZWVsU3RlcCA9IHdoZWVsU3RlcDsgLy9GSVhNRSB0ZXN0IHRoaXNcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBPbmNlIHRoZSBhdXRvTnVtZXJpYyBlbGVtZW50IGhhcyBiZWVuIGluaXRpYWxpemVkLCBicm9hZGNhc3QgdGhhdCBtZXNzYWdlIHdpdGggYWRkaXRpb25hbCBpbmZvLlxuICAgICAgICAvLyBOb3RlOiBXaGVuIHVzaW5nIGBBdXRvTnVtZXJpYy5tdWx0aXBsZSgpYCwgb25lIGV2ZW50IGlzIHNlbnQgKnBlciogZWxlbWVudCBpbml0aWFsaXplZFxuICAgICAgICB0aGlzLl90cmlnZ2VyRXZlbnQoQXV0b051bWVyaWMuZXZlbnRzLmluaXRpYWxpemVkLCB0aGlzLmRvbUVsZW1lbnQsIHtcbiAgICAgICAgICAgIG5ld1ZhbHVlICAgOiBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50KSxcbiAgICAgICAgICAgIG5ld1Jhd1ZhbHVlOiB0aGlzLnJhd1ZhbHVlLFxuICAgICAgICAgICAgZXJyb3IgICAgICA6IG51bGwsXG4gICAgICAgICAgICBhTkVsZW1lbnQgIDogdGhpcyxcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBhdXRvTnVtZXJpYyB2ZXJzaW9uIG51bWJlciAoZm9yIGRlYnVnZ2luZyBwdXJwb3NlKVxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgdmVyc2lvbigpIHtcbiAgICAgICAgcmV0dXJuICc0LjQuMCc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGFrZSB0aGUgcGFyYW1ldGVycyBnaXZlbiB0byB0aGUgQXV0b051bWVyaWMgb2JqZWN0LCBhbmQgb3V0cHV0IHRoZSB0aHJlZSB2YXJpYWJsZXMgdGhhdCBhcmUgbmVlZGVkIHRvIGZpbmlzaCBpbml0aWFsaXppbmcgaXQgOlxuICAgICAqIC0gZG9tRWxlbWVudCA6IFRoZSB0YXJnZXQgRE9NIGVsZW1lbnRcbiAgICAgKiAtIGluaXRpYWxWYWx1ZSA6IFRoZSBpbml0aWFsIHZhbHVlLCBvciBgbnVsbGAgaWYgbm9uZSBpcyBnaXZlblxuICAgICAqIC0gdXNlck9wdGlvbnMgOiBUaGUgb3B0aW9uIG9iamVjdFxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R8QXJyYXl8bnVtYmVyfHN0cmluZ30gYXJnMVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fEFycmF5fG51bWJlcnxzdHJpbmd8bnVsbH0gYXJnMlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fEFycmF5fG51bWJlcnxzdHJpbmd8bnVsbH0gYXJnM1xuICAgICAqIEByZXR1cm5zIHt7ZG9tRWxlbWVudDogKiwgaW5pdGlhbFZhbHVlOiAqLCB1c2VyT3B0aW9uczogKn19XG4gICAgICogQHRocm93c1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9zZXRBcmd1bWVudHNWYWx1ZXMoYXJnMSwgYXJnMiwgYXJnMykge1xuICAgICAgICAvLyBCYXNpYyBjaGVjayBvbiB0aGUgYXJndW1lbnQgY291bnRcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChhcmcxKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcignQXQgbGVhc3Qgb25lIHZhbGlkIHBhcmFtZXRlciBpcyBuZWVkZWQgaW4gb3JkZXIgdG8gaW5pdGlhbGl6ZSBhbiBBdXRvTnVtZXJpYyBvYmplY3QnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFByZXBhcmUgdGhlIGFyZ3VtZW50cyBpbiBvcmRlciB0byBjcmVhdGUgdGhlIEF1dG9OdW1lcmljIG9iamVjdCB3aXRoIHRoZSByaWdodCB2YWx1ZXNcbiAgICAgICAgLy8gVGVzdCB0aGUgYXJndW1lbnQgdHlwZXNcbiAgICAgICAgY29uc3QgaXNBcmcxRWxlbWVudCA9IEF1dG9OdW1lcmljSGVscGVyLmlzRWxlbWVudChhcmcxKTtcbiAgICAgICAgY29uc3QgaXNBcmcxU3RyaW5nID0gQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcoYXJnMSk7XG5cbiAgICAgICAgY29uc3QgaXNBcmcyT2JqZWN0ID0gQXV0b051bWVyaWNIZWxwZXIuaXNPYmplY3QoYXJnMik7XG4gICAgICAgIGNvbnN0IGlzQXJnMkFycmF5ID0gQXJyYXkuaXNBcnJheShhcmcyKSAmJiBhcmcyLmxlbmd0aCA+IDA7XG4gICAgICAgIGNvbnN0IGlzQXJnMk51bWJlciA9IEF1dG9OdW1lcmljSGVscGVyLmlzTnVtYmVyT3JBcmFiaWMoYXJnMikgfHwgYXJnMiA9PT0gJyc7XG4gICAgICAgIGNvbnN0IGlzQXJnMlByZURlZmluZWRPcHRpb25OYW1lID0gdGhpcy5faXNQcmVEZWZpbmVkT3B0aW9uVmFsaWQoYXJnMik7XG4gICAgICAgIGNvbnN0IGlzQXJnMk51bGwgPSBBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoYXJnMik7XG4gICAgICAgIGNvbnN0IGlzQXJnMkVtcHR5U3RyaW5nID0gQXV0b051bWVyaWNIZWxwZXIuaXNFbXB0eVN0cmluZyhhcmcyKTtcblxuICAgICAgICBjb25zdCBpc0FyZzNPYmplY3QgPSBBdXRvTnVtZXJpY0hlbHBlci5pc09iamVjdChhcmczKTtcbiAgICAgICAgY29uc3QgaXNBcmczQXJyYXkgPSBBcnJheS5pc0FycmF5KGFyZzMpICYmIGFyZzMubGVuZ3RoID4gMDtcbiAgICAgICAgY29uc3QgaXNBcmczTnVsbCA9IEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChhcmczKTtcbiAgICAgICAgY29uc3QgaXNBcmczUHJlRGVmaW5lZE9wdGlvbk5hbWUgPSB0aGlzLl9pc1ByZURlZmluZWRPcHRpb25WYWxpZChhcmczKTtcblxuICAgICAgICAvLyBHaXZlbiB0aGUgcGFyYW1ldGVycyBwYXNzZWQsIHNvcnQgdGhlIGRhdGEgYW5kIHJldHVybiBhIHN0YWJsZSBzdGF0ZSBiZWZvcmUgdGhlIGluaXRpYWxpemF0aW9uXG4gICAgICAgIGxldCBkb21FbGVtZW50O1xuICAgICAgICBsZXQgdXNlck9wdGlvbnM7XG4gICAgICAgIGxldCBpbml0aWFsVmFsdWU7XG5cbiAgICAgICAgLy9UT0RPIFNpbXBsaWZ5IHRob3NlIHRlc3RzIC0tPlxuICAgICAgICBpZiAoaXNBcmcxRWxlbWVudCAmJiBpc0FyZzJOdWxsICYmIGlzQXJnM051bGwpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50KTsgLy8gV2l0aCB0aGUgZGVmYXVsdCBvcHRpb25zXG4gICAgICAgICAgICBkb21FbGVtZW50ID0gYXJnMTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IG51bGw7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IG51bGw7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxRWxlbWVudCAmJiBpc0FyZzJOdW1iZXIgJiYgaXNBcmczTnVsbCkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIDEyMzQ1Ljc4OSk7IC8vIFdpdGggdGhlIGRlZmF1bHQgb3B0aW9ucywgYW5kIGFuIGluaXRpYWwgdmFsdWVcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAnMTIzNDUuNzg5Jyk7XG4gICAgICAgICAgICBkb21FbGVtZW50ID0gYXJnMTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IGFyZzI7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IG51bGw7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxRWxlbWVudCAmJiBpc0FyZzJPYmplY3QgJiYgaXNBcmczTnVsbCkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIHsgb3B0aW9ucyB9KTsgLy8gV2l0aCBvbmUgb3B0aW9uIG9iamVjdFxuICAgICAgICAgICAgZG9tRWxlbWVudCA9IGFyZzE7XG4gICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgdXNlck9wdGlvbnMgPSBhcmcyO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJnMUVsZW1lbnQgJiYgaXNBcmcyUHJlRGVmaW5lZE9wdGlvbk5hbWUgJiYgaXNBcmczTnVsbCkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsICdldXJvUG9zJyk7IC8vIFdpdGggb25lIHByZS1kZWZpbmVkIG9wdGlvbiBuYW1lXG4gICAgICAgICAgICBkb21FbGVtZW50ID0gYXJnMTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IG51bGw7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IHRoaXMuX2dldE9wdGlvbk9iamVjdChhcmcyKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc0FyZzFFbGVtZW50ICYmIGlzQXJnMkFycmF5ICYmIGlzQXJnM051bGwpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCBbeyBvcHRpb25zMSB9LCB7IG9wdGlvbnMyIH1dKTsgLy8gV2l0aCBtdWx0aXBsZSBvcHRpb24gb2JqZWN0cyAodGhlIGxhdGVzdCBvcHRpb24gb3ZlcndyaXRpbmcgdGhlIHByZXZpb3VzIG9uZXMpXG4gICAgICAgICAgICBkb21FbGVtZW50ID0gYXJnMTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IG51bGw7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IHRoaXMubWVyZ2VPcHRpb25zKGFyZzIpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJnMUVsZW1lbnQgJiYgKGlzQXJnMk51bGwgfHwgaXNBcmcyRW1wdHlTdHJpbmcpICYmIGlzQXJnM09iamVjdCkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIG51bGwsIHsgb3B0aW9ucyB9KTsgLy8gV2l0aCBvbmUgb3B0aW9uIG9iamVjdFxuICAgICAgICAgICAgZG9tRWxlbWVudCA9IGFyZzE7XG4gICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgdXNlck9wdGlvbnMgPSBhcmczO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJnMUVsZW1lbnQgJiYgKGlzQXJnMk51bGwgfHwgaXNBcmcyRW1wdHlTdHJpbmcpICYmIGlzQXJnM0FycmF5KSB7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgbnVsbCwgW3sgb3B0aW9uczEgfSwgeyBvcHRpb25zMiB9XSk7IC8vIFdpdGggbXVsdGlwbGUgb3B0aW9uIG9iamVjdHNcbiAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBhcmcxO1xuICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gbnVsbDtcbiAgICAgICAgICAgIHVzZXJPcHRpb25zID0gdGhpcy5tZXJnZU9wdGlvbnMoYXJnMyk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxU3RyaW5nICYmIGlzQXJnMk51bGwgJiYgaXNBcmczTnVsbCkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0Jyk7XG4gICAgICAgICAgICBkb21FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihhcmcxKTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IG51bGw7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IG51bGw7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxU3RyaW5nICYmIGlzQXJnMk9iamVjdCAmJiBpc0FyZzNOdWxsKSB7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCB7IG9wdGlvbnMgfSk7XG4gICAgICAgICAgICBkb21FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihhcmcxKTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IG51bGw7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IGFyZzI7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxU3RyaW5nICYmIGlzQXJnMlByZURlZmluZWRPcHRpb25OYW1lICYmIGlzQXJnM051bGwpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsICdldXJvUG9zJyk7XG4gICAgICAgICAgICBkb21FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihhcmcxKTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IG51bGw7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IHRoaXMuX2dldE9wdGlvbk9iamVjdChhcmcyKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc0FyZzFTdHJpbmcgJiYgaXNBcmcyQXJyYXkgJiYgaXNBcmczTnVsbCkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgW3sgb3B0aW9uczEgfSwgeyBvcHRpb25zMiB9XSk7IC8vIFdpdGggbXVsdGlwbGUgb3B0aW9uIG9iamVjdHNcbiAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGFyZzEpO1xuICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gbnVsbDtcbiAgICAgICAgICAgIHVzZXJPcHRpb25zID0gdGhpcy5tZXJnZU9wdGlvbnMoYXJnMik7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxU3RyaW5nICYmIChpc0FyZzJOdWxsIHx8IGlzQXJnMkVtcHR5U3RyaW5nKSAmJiBpc0FyZzNPYmplY3QpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsIG51bGwsIHsgb3B0aW9ucyB9KTtcbiAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGFyZzEpO1xuICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gbnVsbDtcbiAgICAgICAgICAgIHVzZXJPcHRpb25zID0gYXJnMztcbiAgICAgICAgfSBlbHNlIGlmIChpc0FyZzFTdHJpbmcgJiYgKGlzQXJnMk51bGwgfHwgaXNBcmcyRW1wdHlTdHJpbmcpICYmIGlzQXJnM0FycmF5KSB7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCBudWxsLCBbeyBvcHRpb25zMSB9LCB7IG9wdGlvbnMyIH1dKTsgLy8gV2l0aCBtdWx0aXBsZSBvcHRpb24gb2JqZWN0c1xuICAgICAgICAgICAgZG9tRWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYXJnMSk7XG4gICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgdXNlck9wdGlvbnMgPSB0aGlzLm1lcmdlT3B0aW9ucyhhcmczKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc0FyZzFTdHJpbmcgJiYgaXNBcmcyTnVtYmVyICYmIGlzQXJnM051bGwpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsIDEyMzQ1Ljc4OSk7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCAnMTIzNDUuNzg5Jyk7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCAnJyk7XG4gICAgICAgICAgICBkb21FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihhcmcxKTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IGFyZzI7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IG51bGw7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxU3RyaW5nICYmIGlzQXJnMk51bWJlciAmJiBpc0FyZzNPYmplY3QpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsIDEyMzQ1Ljc4OSwgeyBvcHRpb25zIH0pO1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgJzEyMzQ1Ljc4OScsIHsgb3B0aW9ucyB9KTtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsICcnLCB7IG9wdGlvbnMgfSk7XG4gICAgICAgICAgICBkb21FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihhcmcxKTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IGFyZzI7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IGFyZzM7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxU3RyaW5nICYmIGlzQXJnMk51bWJlciAmJiBpc0FyZzNQcmVEZWZpbmVkT3B0aW9uTmFtZSkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgMTIzNDUuNzg5LCAnZXVyb1BvcycpO1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgJzEyMzQ1Ljc4OScsICdldXJvUG9zJyk7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCAnJywgJ2V1cm9Qb3MnKTtcbiAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGFyZzEpO1xuICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gYXJnMjtcbiAgICAgICAgICAgIHVzZXJPcHRpb25zID0gdGhpcy5fZ2V0T3B0aW9uT2JqZWN0KGFyZzMpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJnMVN0cmluZyAmJiBpc0FyZzJOdW1iZXIgJiYgaXNBcmczQXJyYXkpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsIDEyMzQ1Ljc4OSwgW3sgb3B0aW9uczEgfSwgJ2V1cm9Qb3MnLCB7IG9wdGlvbnMyIH1dKTtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsICcxMjM0NS43ODknLCBbeyBvcHRpb25zMSB9LCAnZXVyb1BvcycsIHsgb3B0aW9uczIgfV0pO1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgJycsIFt7IG9wdGlvbnMxIH0sICdldXJvUG9zJywgeyBvcHRpb25zMiB9XSk7XG4gICAgICAgICAgICBkb21FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihhcmcxKTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IGFyZzI7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IHRoaXMubWVyZ2VPcHRpb25zKGFyZzMpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJnMUVsZW1lbnQgJiYgaXNBcmcyTnVtYmVyICYmIGlzQXJnM09iamVjdCkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIDEyMzQ1Ljc4OSwgeyBvcHRpb25zIH0pO1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsICcxMjM0NS43ODknLCB7IG9wdGlvbnMgfSk7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgJycsIHsgb3B0aW9ucyB9KTtcbiAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBhcmcxO1xuICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gYXJnMjtcbiAgICAgICAgICAgIHVzZXJPcHRpb25zID0gYXJnMztcbiAgICAgICAgfSBlbHNlIGlmIChpc0FyZzFFbGVtZW50ICYmIGlzQXJnMk51bWJlciAmJiBpc0FyZzNQcmVEZWZpbmVkT3B0aW9uTmFtZSkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIDEyMzQ1Ljc4OSwgJ2V1cm9Qb3MnKTtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAnMTIzNDUuNzg5JywgJ2V1cm9Qb3MnKTtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAnJywgJ2V1cm9Qb3MnKTtcbiAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBhcmcxO1xuICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gYXJnMjtcbiAgICAgICAgICAgIHVzZXJPcHRpb25zID0gdGhpcy5fZ2V0T3B0aW9uT2JqZWN0KGFyZzMpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJnMUVsZW1lbnQgJiYgaXNBcmcyTnVtYmVyICYmIGlzQXJnM0FycmF5KSB7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgMTIzNDUuNzg5LCBbeyBvcHRpb25zMSB9LCB7IG9wdGlvbnMyIH1dKTtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAnMTIzNDUuNzg5JywgW3sgb3B0aW9uczEgfSwgeyBvcHRpb25zMiB9XSk7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgJycsIFt7IG9wdGlvbnMxIH0sIHsgb3B0aW9uczIgfV0pO1xuICAgICAgICAgICAgZG9tRWxlbWVudCA9IGFyZzE7XG4gICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBhcmcyO1xuICAgICAgICAgICAgdXNlck9wdGlvbnMgPSB0aGlzLm1lcmdlT3B0aW9ucyhhcmczKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBwYXJhbWV0ZXJzIGdpdmVuIHRvIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QgYXJlIG5vdCB2YWxpZCwgJyR7YXJnMX0nLCAnJHthcmcyfScgYW5kICcke2FyZzN9JyBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoZG9tRWxlbWVudCkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBzZWxlY3RvciAnJHthcmcxfScgZGlkIG5vdCBzZWxlY3QgYW55IHZhbGlkIERPTSBlbGVtZW50LiBQbGVhc2UgY2hlY2sgb24gd2hpY2ggZWxlbWVudCB5b3UgY2FsbGVkIEF1dG9OdW1lcmljLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHsgZG9tRWxlbWVudCwgaW5pdGlhbFZhbHVlLCB1c2VyT3B0aW9ucyB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1lcmdlIHRoZSBvcHRpb24gb2JqZWN0cyBmb3VuZCBpbiB0aGUgZ2l2ZW4gYXJyYXkgYG9wdGlvbnNBcnJheWAuXG4gICAgICogSWYgYSBgc3RyaW5nYCBpcyBmb3VuZCwgdGhlbiB3ZSB0cnkgdG8gZ2V0IHRoZSByZWxhdGVkIHByZS1kZWZpbmVkIG9wdGlvbiB1c2luZyB0aGF0IHN0cmluZyBhcyBpdHMgbmFtZS5cbiAgICAgKiBXaGVuIG1lcmdpbmcgdGhlIG9wdGlvbnMsIHRoZSBsYXRlc3Qgb3B0aW9uIG92ZXJ3cml0ZSBhbnkgcHJldmlvdXNseSBzZXQuIFRoaXMgYWxsb3dzIHRvIGZpbmUgdHVuZSBhIHByZS1kZWZpbmVkIG9wdGlvbiBmb3IgaW5zdGFuY2UuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FycmF5PG9iamVjdHxzdHJpbmc+fSBvcHRpb25zQXJyYXlcbiAgICAgKiBAcmV0dXJucyB7e319XG4gICAgICovXG4gICAgc3RhdGljIG1lcmdlT3B0aW9ucyhvcHRpb25zQXJyYXkpIHtcbiAgICAgICAgLy8gVGhpcyBhbGxvd3MgdGhlIHVzZXIgdG8gdXNlIG11bHRpcGxlIG9wdGlvbnMgKHN0cmluZ3Mgb3Igb2JqZWN0cykgaW4gYW4gYXJyYXksIGFuZCBvdmVyd3JpdGUgdGhlIHByZXZpb3VzIG9uZSB3aXRoIHRoZSBuZXh0IG9wdGlvbiBlbGVtZW50IDsgdGhpcyBpcyB1c2VmdWwgdG8gdHVuZSB0aGUgd2FudGVkIGZvcm1hdFxuICAgICAgICBjb25zdCBtZXJnZWRPcHRpb25zID0ge307XG4gICAgICAgIG9wdGlvbnNBcnJheS5mb3JFYWNoKG9wdGlvbk9iamVjdE9yUHJlZGVmaW5lZE9wdGlvblN0cmluZyA9PiB7XG4gICAgICAgICAgICBPYmplY3QuYXNzaWduKG1lcmdlZE9wdGlvbnMsIHRoaXMuX2dldE9wdGlvbk9iamVjdChvcHRpb25PYmplY3RPclByZWRlZmluZWRPcHRpb25TdHJpbmcpKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIG1lcmdlZE9wdGlvbnM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgZ2l2ZW4gcHJlLWRlZmluZWQgb3B0aW9uIG5hbWUgaXMgYW4gYXR0cmlidXRlIG9mIHRoZSBgQXV0b051bWVyaWMucHJlZGVmaW5lZE9wdGlvbnNgIG9iamVjdFxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHByZURlZmluZWRPcHRpb25OYW1lXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2lzUHJlRGVmaW5lZE9wdGlvblZhbGlkKHByZURlZmluZWRPcHRpb25OYW1lKSB7XG4gICAgICAgIHJldHVybiBBdXRvTnVtZXJpYy5wcmVkZWZpbmVkT3B0aW9ucy5oYXNPd25Qcm9wZXJ0eShwcmVEZWZpbmVkT3B0aW9uTmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGFuIG9wdGlvbiBvYmplY3QgYmFzZWQgb24gdGhlIGdpdmVuIHBhcmFtZXRlci5cbiAgICAgKiBJZiBgb3B0aW9uT2JqZWN0T3JQcmVkZWZpbmVkTmFtZWAgaXMgYXMgc3RyaW5nLCB0aGVuIHdlIHJldHJpZXZlIHRoZSBwcmUtZGVmaW5lZCBvcHRpb24gb2JqZWN0LCBpZiBpdCdzIGFuIG9iamVjdCwgd2UgdXNlIGl0IGFzIGlzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R8c3RyaW5nfSBvcHRpb25PYmplY3RPclByZWRlZmluZWROYW1lXG4gICAgICogQHJldHVybnMge29iamVjdH1cbiAgICAgKi9cbiAgICBzdGF0aWMgX2dldE9wdGlvbk9iamVjdChvcHRpb25PYmplY3RPclByZWRlZmluZWROYW1lKSB7XG4gICAgICAgIGxldCBvcHRpb25zO1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcob3B0aW9uT2JqZWN0T3JQcmVkZWZpbmVkTmFtZSkpIHtcbiAgICAgICAgICAgIG9wdGlvbnMgPSBBdXRvTnVtZXJpYy5nZXRQcmVkZWZpbmVkT3B0aW9ucygpW29wdGlvbk9iamVjdE9yUHJlZGVmaW5lZE5hbWVdO1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQoMCkgfHwgb3B0aW9ucyA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBnaXZlbiBwcmUtZGVmaW5lZCBuYW1lIGRvZXMgbm90IGV4aXN0LCB3YXJuIHRoYXQgc29tZXRoaW5nIGlzIHdyb25nLCBhbmQgY29udGludWUgdGhlIGV4ZWN1dGlvbiBvZiB0aGUgaW5pdGlhbGl6YXRpb25cbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKGBUaGUgZ2l2ZW4gcHJlLWRlZmluZWQgb3B0aW9uIFske29wdGlvbk9iamVjdE9yUHJlZGVmaW5lZE5hbWV9XSBpcyBub3QgcmVjb2duaXplZCBieSBhdXRvTnVtZXJpYy4gUGxlYXNlIGNoZWNrIHRoYXQgcHJlLWRlZmluZWQgb3B0aW9uIG5hbWUuYCwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7IC8vIEEgYHNldHRpbmdzYCBvYmplY3RcbiAgICAgICAgICAgIG9wdGlvbnMgPSBvcHRpb25PYmplY3RPclByZWRlZmluZWROYW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG9wdGlvbnM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2F2ZSB0aGUgaW5pdGlhbCBlbGVtZW50IHZhbHVlcyBmb3IgbGF0ZXIgdXNlIGluIHRoZSBwcmlzdGluZSB0ZXN0LlxuICAgICAqIFRob3NlIHZhbHVlcyBhcmUgOlxuICAgICAqIC0gdGhlIGh0bWwgYXR0cmlidXRlIChpZS4gPGlucHV0IHZhbHVlPSc0Mic+KSwgYW5kXG4gICAgICogLSB0aGUgc2NyaXB0IGB2YWx1ZWAgKGllLiBgbGV0IGRvbUVsZW1lbnQudmFsdWVgKVxuICAgICAqXG4gICAgICogQHBhcmFtIHtudWxsfG51bWJlcnxzdHJpbmd9IGluaXRpYWxWYWx1ZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3NhdmVJbml0aWFsVmFsdWVzKGluaXRpYWxWYWx1ZSkge1xuICAgICAgICAvLyBLZWVwIHRoZSB2ZXJ5IGZpcnN0IGluaXRpYWwgdmFsdWVzIChpbiB0aGUgaHRtbCBhdHRyaWJ1dGUgYW5kIHNldCBieSB0aGUgc2NyaXB0KS4gVGhpcyBpcyBuZWVkZWQgdG8gY2hlY2sgaWYgdGhlIGVsZW1lbnQgaXMgcHJpc3RpbmUuXG4gICAgICAgIC8vIFNhdmUgdGhlIGh0bWwgYXR0cmlidXRlICd2YWx1ZSdcbiAgICAgICAgdGhpcy5pbml0aWFsVmFsdWVIdG1sQXR0cmlidXRlID0gQXV0b051bWVyaWNIZWxwZXIuc2NpZW50aWZpY1RvRGVjaW1hbCh0aGlzLmRvbUVsZW1lbnQuZ2V0QXR0cmlidXRlKCd2YWx1ZScpKTtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbCh0aGlzLmluaXRpYWxWYWx1ZUh0bWxBdHRyaWJ1dGUpKSB7XG4gICAgICAgICAgICAvLyBTZXQgdGhlIGRlZmF1bHQgZW1wdHkgdmFsdWUgYXR0cmlidXRlIGluc3RlYWQgb2YgYG51bGxgLCBzaW5jZSBpZiB0aGUgaW5pdGlhbCB2YWx1ZSBpcyBudWxsLCB0aGUgZW1wdHkgc3RyaW5nIGlzIHVzZWRcbiAgICAgICAgICAgIHRoaXMuaW5pdGlhbFZhbHVlSHRtbEF0dHJpYnV0ZSA9ICcnO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2F2ZSB0aGUgJ3NjcmlwdCcgdmFsdWVcbiAgICAgICAgdGhpcy5pbml0aWFsVmFsdWUgPSBpbml0aWFsVmFsdWU7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwodGhpcy5pbml0aWFsVmFsdWUpKSB7XG4gICAgICAgICAgICAvLyBTYW1lIGFzIGFib3ZlXG4gICAgICAgICAgICB0aGlzLmluaXRpYWxWYWx1ZSA9ICcnO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGUgYWxsIHRoZSBldmVudCBsaXN0ZW5lcnMgZm9yIHRoZSBnaXZlbiBET00gZWxlbWVudFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2NyZWF0ZUV2ZW50TGlzdGVuZXJzKCkge1xuICAgICAgICAvLyBDcmVhdGUgcmVmZXJlbmNlcyB0byB0aGUgZXZlbnQgaGFuZGxlciBmdW5jdGlvbnMsIHNvIHdlIGNhbiB0aGVuIGNsZWFubHkgcmVtb3ZlcyB0aG9zZSBsaXN0ZW5lcnMgaWYgbmVlZGVkXG4gICAgICAgIC8vIFRoYXQgd291bGQgbm90IGJlIHBvc3NpYmxlIGlmIHdlIHVzZWQgY2xvc3VyZXMgZGlyZWN0bHkgaW4gdGhlIGV2ZW50IGhhbmRsZXIgZGVjbGFyYXRpb25zXG4gICAgICAgIHRoaXMuX29uRm9jdXNJbkZ1bmMgPSBlID0+IHsgdGhpcy5fb25Gb2N1c0luKGUpOyB9O1xuICAgICAgICB0aGlzLl9vbkZvY3VzSW5BbmRNb3VzZUVudGVyRnVuYyA9IGUgPT4geyB0aGlzLl9vbkZvY3VzSW5BbmRNb3VzZUVudGVyKGUpOyB9O1xuICAgICAgICB0aGlzLl9vbkZvY3VzRnVuYyA9ICgpID0+IHsgdGhpcy5fb25Gb2N1cygpOyB9O1xuICAgICAgICB0aGlzLl9vbktleWRvd25GdW5jID0gZSA9PiB7IHRoaXMuX29uS2V5ZG93bihlKTsgfTtcbiAgICAgICAgdGhpcy5fb25LZXlwcmVzc0Z1bmMgPSBlID0+IHsgdGhpcy5fb25LZXlwcmVzcyhlKTsgfTtcbiAgICAgICAgdGhpcy5fb25LZXl1cEZ1bmMgPSBlID0+IHsgdGhpcy5fb25LZXl1cChlKTsgfTtcbiAgICAgICAgdGhpcy5fb25Gb2N1c091dEFuZE1vdXNlTGVhdmVGdW5jID0gZSA9PiB7IHRoaXMuX29uRm9jdXNPdXRBbmRNb3VzZUxlYXZlKGUpOyB9O1xuICAgICAgICB0aGlzLl9vblBhc3RlRnVuYyA9IGUgPT4geyB0aGlzLl9vblBhc3RlKGUpOyB9O1xuICAgICAgICB0aGlzLl9vbldoZWVsRnVuYyA9IGUgPT4geyB0aGlzLl9vbldoZWVsKGUpOyB9O1xuICAgICAgICB0aGlzLl9vbkRyb3BGdW5jID0gZSA9PiB7IHRoaXMuX29uRHJvcChlKTsgfTtcbiAgICAgICAgdGhpcy5fb25LZXlkb3duR2xvYmFsRnVuYyA9IGUgPT4geyB0aGlzLl9vbktleWRvd25HbG9iYWwoZSk7IH07XG4gICAgICAgIHRoaXMuX29uS2V5dXBHbG9iYWxGdW5jID0gZSA9PiB7IHRoaXMuX29uS2V5dXBHbG9iYWwoZSk7IH07XG5cbiAgICAgICAgLy8gQWRkIHRoZSBldmVudCBsaXN0ZW5lcnNcbiAgICAgICAgdGhpcy5kb21FbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2ZvY3VzaW4nLCB0aGlzLl9vbkZvY3VzSW5GdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuX29uRm9jdXNJbkFuZE1vdXNlRW50ZXJGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuX29uRm9jdXNGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWVudGVyJywgdGhpcy5fb25Gb2N1c0luQW5kTW91c2VFbnRlckZ1bmMsIGZhbHNlKTtcbiAgICAgICAgdGhpcy5kb21FbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCB0aGlzLl9vbktleWRvd25GdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdrZXlwcmVzcycsIHRoaXMuX29uS2V5cHJlc3NGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdrZXl1cCcsIHRoaXMuX29uS2V5dXBGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdibHVyJywgdGhpcy5fb25Gb2N1c091dEFuZE1vdXNlTGVhdmVGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWxlYXZlJywgdGhpcy5fb25Gb2N1c091dEFuZE1vdXNlTGVhdmVGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdwYXN0ZScsIHRoaXMuX29uUGFzdGVGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCd3aGVlbCcsIHRoaXMuX29uV2hlZWxGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdkcm9wJywgdGhpcy5fb25Ecm9wRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLl9zZXR1cEZvcm1MaXN0ZW5lcigpO1xuXG4gICAgICAgIC8vIEtlZXAgdHJhY2sgaWYgdGhlIGV2ZW50IGxpc3RlbmVycyBoYXZlIGJlZW4gaW5pdGlhbGl6ZWQgb24gdGhpcyBvYmplY3RcbiAgICAgICAgdGhpcy5oYXNFdmVudExpc3RlbmVycyA9IHRydWU7XG5cbiAgICAgICAgLy8gQ3JlYXRlIG9uZSBnbG9iYWwgZXZlbnQgbGlzdGVuZXIgZm9yIHRoZSBrZXl1cCBldmVudCBvbiB0aGUgZG9jdW1lbnQgb2JqZWN0LCB3aGljaCB3aWxsIGJlIHNoYXJlZCBieSBhbGwgdGhlIGF1dG9OdW1lcmljIGVsZW1lbnRzXG4gICAgICAgIGlmICghQXV0b051bWVyaWMuX2RvZXNHbG9iYWxMaXN0RXhpc3RzKCkpIHtcbiAgICAgICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCB0aGlzLl9vbktleWRvd25HbG9iYWxGdW5jLCBmYWxzZSk7XG4gICAgICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdrZXl1cCcsIHRoaXMuX29uS2V5dXBHbG9iYWxGdW5jLCBmYWxzZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgYWxsIHRoZSBhdXRvTnVtZXJpYy1yZWxhdGVkIGV2ZW50IGxpc3RlbmVycyBmb3IgdGhlIGdpdmVuIERPTSBlbGVtZW50XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfcmVtb3ZlRXZlbnRMaXN0ZW5lcnMoKSB7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdmb2N1c2luJywgdGhpcy5fb25Gb2N1c0luRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0aGlzLl9vbkZvY3VzSW5BbmRNb3VzZUVudGVyRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0aGlzLl9vbkZvY3VzRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2VlbnRlcicsIHRoaXMuX29uRm9jdXNJbkFuZE1vdXNlRW50ZXJGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdibHVyJywgdGhpcy5fb25Gb2N1c091dEFuZE1vdXNlTGVhdmVGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWxlYXZlJywgdGhpcy5fb25Gb2N1c091dEFuZE1vdXNlTGVhdmVGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdrZXlkb3duJywgdGhpcy5fb25LZXlkb3duRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5cHJlc3MnLCB0aGlzLl9vbktleXByZXNzRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5dXAnLCB0aGlzLl9vbktleXVwRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigncGFzdGUnLCB0aGlzLl9vblBhc3RlRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignd2hlZWwnLCB0aGlzLl9vbldoZWVsRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignZHJvcCcsIHRoaXMuX29uRHJvcEZ1bmMsIGZhbHNlKTtcbiAgICAgICAgdGhpcy5fcmVtb3ZlRm9ybUxpc3RlbmVyKCk7XG5cbiAgICAgICAgLy8gS2VlcCB0cmFjayBpZiB0aGUgZXZlbnQgbGlzdGVuZXJzIGhhdmUgYmVlbiBpbml0aWFsaXplZCBvbiB0aGlzIG9iamVjdFxuICAgICAgICB0aGlzLmhhc0V2ZW50TGlzdGVuZXJzID0gZmFsc2U7XG5cbiAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIHRoaXMuX29uS2V5ZG93bkdsb2JhbEZ1bmMsIGZhbHNlKTtcbiAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5dXAnLCB0aGlzLl9vbktleXVwR2xvYmFsRnVuYywgZmFsc2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRvZ2dsZSB0aGUgZXZlbnQgbGlzdGVuZXJzIGFjY29yZGluZyB0byB0aGUgYG5vRXZlbnRMaXN0ZW5lcnNgIG9wdGlvbiwgaWYgdGhvc2Ugd2VyZSBub3QgYWN0aXZhdGVkL2RlYWN0aXZhdGVkIGJlZm9yZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3VwZGF0ZUV2ZW50TGlzdGVuZXJzKCkge1xuICAgICAgICBpZiAoIXRoaXMuc2V0dGluZ3Mubm9FdmVudExpc3RlbmVycyAmJiAhdGhpcy5oYXNFdmVudExpc3RlbmVycykge1xuICAgICAgICAgICAgLy8gU3BlY2lhbCBjYXNlIHdoZXJlIGFuIHVwZGF0ZSBpcyBkb25lIG9uIGFuIGVsZW1lbnQgdGhhdCBkaWQgbm90IGFjdGl2YXRlIGl0cyBldmVudCBsaXN0ZW5lcnMgaW4gdGhlIGZpcnN0IHBsYWNlXG4gICAgICAgICAgICAvLyBpZS4gd2hlbiBhbiBlbGVtZW50IGlzIGZpcnN0IGNyZWF0ZWQgd2l0aCBgY29udGVudGVkaXRhYmxlPVwiZmFsc2VcImAsIHRoZW4gYW4gdXBkYXRlIGlzIGRvbmUgd2l0aCBgYW5FbGVtZW50LmZyZW5jaCgpYFxuICAgICAgICAgICAgdGhpcy5fY3JlYXRlRXZlbnRMaXN0ZW5lcnMoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLm5vRXZlbnRMaXN0ZW5lcnMgJiYgdGhpcy5oYXNFdmVudExpc3RlbmVycykge1xuICAgICAgICAgICAgdGhpcy5fcmVtb3ZlRXZlbnRMaXN0ZW5lcnMoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1hcmsgdGhlIHBhcmVudCA8Zm9ybT4gc28gdGhhdCBvdGhlciBBdXRvTnVtZXJpYyBvYmplY3Qgd2lsbCBub3QgYWRkIG1vcmUgbGlzdGVuZXJzLlxuICAgICAqIEFkZCBhIGNvdW50ZXIgc28gdGhhdCB3aGVuIHJlbW92aW5nIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QsIHdlIG9ubHkgcmVtb3ZlIHRoZSBzdWJtaXQgbGlzdGVuZXIgaWYgdGhhdCBjb3VudCBpcyBlcXVhbCB0byAwLlxuICAgICAqIEFsc28ga2VlcCBhIHJlZmVyZW5jZSB0byB0aGUgJ3N1Ym1pdCcgZXZlbnQgaGFuZGxlciBmdW5jdGlvbiB0byBiZSBhYmxlIHRvIHJlbW92ZSB0aGF0IGhhbmRsZXIgbGF0ZXIgaWYgdGhlIGBfcmVtb3ZlRm9ybUxpc3RlbmVyKClgIGZ1bmN0aW9uIGlzIGNhbGxlZCBmcm9tIGFub3RoZXIgQXV0b051bWVyaWMgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfc2V0dXBGb3JtTGlzdGVuZXIoKSB7XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKHRoaXMucGFyZW50Rm9ybSkpIHtcbiAgICAgICAgICAgIC8vIFNldHVwIHRoZSBoYW5kbGVyIGZ1bmN0aW9uXG4gICAgICAgICAgICB0aGlzLl9vbkZvcm1TdWJtaXRGdW5jID0gKCkgPT4geyB0aGlzLl9vbkZvcm1TdWJtaXQoKTsgfTtcbiAgICAgICAgICAgIHRoaXMuX29uRm9ybVJlc2V0RnVuYyA9ICgpID0+IHsgdGhpcy5fb25Gb3JtUmVzZXQoKTsgfTtcblxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIHBhcmVudCBmb3JtIGFscmVhZHkgaGFzIHRoZSBBdXRvTnVtZXJpYyBtYXJrXG4gICAgICAgICAgICBpZiAodGhpcy5faGFzUGFyZW50Rm9ybUNvdW50ZXIoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2luY3JlbWVudFBhcmVudEZvcm1Db3VudGVyKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIElmIG5vdCwgYWRkIHRoZSBjb3VudGVyXG4gICAgICAgICAgICAgICAgdGhpcy5faW5pdGlhbGl6ZUZvcm1Db3VudGVyVG9PbmUoKTtcbiAgICAgICAgICAgICAgICAvLyBBbmQgYWRkIHRoZSBzdWJtaXQgYW5kIHJlc2V0IGV2ZW50IGxpc3RlbmVyc1xuICAgICAgICAgICAgICAgIHRoaXMucGFyZW50Rm9ybS5hZGRFdmVudExpc3RlbmVyKCdzdWJtaXQnLCB0aGlzLl9vbkZvcm1TdWJtaXRGdW5jLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXJlbnRGb3JtLmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2V0JywgdGhpcy5fb25Gb3JtUmVzZXRGdW5jLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgLy8gQWxzbyBrZWVwIGEgcmVmZXJlbmNlIHRvIHRoZSBoYW5kbGVyIGZ1bmN0aW9uIHNvIHRoYXQgd2UgY2FuIHJlbW92ZSBpdCBsYXRlclxuICAgICAgICAgICAgICAgIHRoaXMuX3N0b3JlRm9ybUhhbmRsZXJGdW5jdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIHRoZSBmb3JtICdzdWJtaXQnIGV2ZW50IGxpc3RlbmVyLCBhcyB3ZWxsIGFzIHRoZSBgZGF0YXNldGAgaW5mbyAoYGFuQ291bnRgIGFuZCBgYW5Gb3JtSGFuZGxlcmApIGZyb20gdGhlIHBhcmVudCBmb3JtLCBvbmx5IHdoZW4gdGhlcmUgYXJlIG9ubHkgb25lIEF1dG9OdW1lcmljIGNoaWxkIGVsZW1lbnQgbGVmdCBpbiB0aGF0IDxmb3JtPi5cbiAgICAgKiBPdGhlcndpc2UgZGVjcmVtZW50IHRoZSBgYW5Db3VudGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9yZW1vdmVGb3JtTGlzdGVuZXIoKSB7XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKHRoaXMucGFyZW50Rm9ybSkpIHtcbiAgICAgICAgICAgIC8vIENoZWNrIHRoZSBwYXJlbnQgZm9ybSBjb3VudGVyIHZhbHVlXG4gICAgICAgICAgICBjb25zdCBhbkNvdW50ID0gdGhpcy5fZ2V0UGFyZW50Rm9ybUNvdW50ZXIoKTtcblxuICAgICAgICAgICAgaWYgKGFuQ291bnQgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiBpdCdzIDEsIHJlbW92ZSB0aGUgbGlzdGVuZXJzXG4gICAgICAgICAgICAgICAgdGhpcy5wYXJlbnRGb3JtLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3N1Ym1pdCcsIHRoaXMuX2dldEZvcm1IYW5kbGVyRnVuY3Rpb24oKS5zdWJtaXRGbiwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIHRoaXMucGFyZW50Rm9ybS5yZW1vdmVFdmVudExpc3RlbmVyKCdyZXNldCcsIHRoaXMuX2dldEZvcm1IYW5kbGVyRnVuY3Rpb24oKS5yZXNldEZuLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgLy8gQWxzbyByZW1vdmUgdGhlIGRhdGFzZXQgaW5mb1xuICAgICAgICAgICAgICAgIHRoaXMuX3JlbW92ZUZvcm1EYXRhU2V0SW5mbygpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChhbkNvdW50ID4gMSkge1xuICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBpZiBpdCdzID4xIGRlY3JlbWVudCB0aGUgY291bnRlclxuICAgICAgICAgICAgICAgIHRoaXMuX2RlY3JlbWVudFBhcmVudEZvcm1Db3VudGVyKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIElmIGl0J3MgPDEsIHRocm93IGFuIGVycm9yXG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIEF1dG9OdW1lcmljIG9iamVjdCBjb3VudCBvbiB0aGUgZm9ybSBpcyBpbmNvaGVyZW50LmApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyZW50IGZvcm0gaGFzIHRoZSBmb3JtIGNvdW50ZXIgYXR0cmlidXRlXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9oYXNQYXJlbnRGb3JtQ291bnRlcigpIHtcbiAgICAgICAgcmV0dXJuICdhbkNvdW50JyBpbiB0aGlzLnBhcmVudEZvcm0uZGF0YXNldDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIGNvdW50IG9mIEF1dG9OdW1lcmljIGZvcm0gY2hpbGRyZW5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZ2V0UGFyZW50Rm9ybUNvdW50ZXIoKSB7XG4gICAgICAgIHJldHVybiBOdW1iZXIodGhpcy5wYXJlbnRGb3JtLmRhdGFzZXQuYW5Db3VudCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBjb3VudCBvZiBBdXRvTnVtZXJpYyBmb3JtIGNoaWxkcmVuIHRvIDEgZm9yIHRoZSBnaXZlbiBmb3JtIGVsZW1lbnQsIG9yIGlmIG5vbmUgYXJlIHBhc3NlZCwgdGhlIGN1cnJlbnQgYHRoaXMucGFyZW50Rm9ybWAgb25lLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRm9ybUVsZW1lbnR8bnVsbH0gZm9ybUVsZW1lbnRcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9pbml0aWFsaXplRm9ybUNvdW50ZXJUb09uZShmb3JtRWxlbWVudCA9IG51bGwpIHtcbiAgICAgICAgdGhpcy5fZ2V0Rm9ybUVsZW1lbnQoZm9ybUVsZW1lbnQpLmRhdGFzZXQuYW5Db3VudCA9IDE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5jcmVtZW50IHRoZSBBdXRvTnVtZXJpYyBmb3JtIGNoaWxkcmVuIGNvdW50IGZvciB0aGUgZ2l2ZW4gZm9ybSBlbGVtZW50LCBvciBpZiBub25lIGFyZSBwYXNzZWQsIHRoZSBjdXJyZW50IGB0aGlzLnBhcmVudEZvcm1gIG9uZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEZvcm1FbGVtZW50fG51bGx9IGZvcm1FbGVtZW50XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfaW5jcmVtZW50UGFyZW50Rm9ybUNvdW50ZXIoZm9ybUVsZW1lbnQgPSBudWxsKSB7XG4gICAgICAgIHRoaXMuX2dldEZvcm1FbGVtZW50KGZvcm1FbGVtZW50KS5kYXRhc2V0LmFuQ291bnQrKztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZWNyZW1lbnQgdGhlIEF1dG9OdW1lcmljIGZvcm0gY2hpbGRyZW4gY291bnQgZm9yIHRoZSBjdXJyZW50IGB0aGlzLnBhcmVudEZvcm1gIGZvcm0gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2RlY3JlbWVudFBhcmVudEZvcm1Db3VudGVyKCkge1xuICAgICAgICB0aGlzLnBhcmVudEZvcm0uZGF0YXNldC5hbkNvdW50LS07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgZ2xvYmFsIGZvcm0gaGFuZGxlciBsaXN0IGV4aXN0cyBvbiB0aGUgYHdpbmRvd2Agb2JqZWN0LlxuICAgICAqXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2RvZXNGb3JtSGFuZGxlckxpc3RFeGlzdHMoKSB7XG4gICAgICAgIGNvbnN0IHR5cGUgPSB0eXBlb2Ygd2luZG93LmFORm9ybUhhbmRsZXJNYXA7XG5cbiAgICAgICAgcmV0dXJuIHR5cGUgIT09ICd1bmRlZmluZWQnICYmIHR5cGUgPT09ICdvYmplY3QnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSB0aGUgZ2xvYmFsIGZvcm0gaGFuZGxlciBsaXN0IG9uIHRoZSBgd2luZG93YCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfY3JlYXRlRm9ybUhhbmRsZXJMaXN0KCkge1xuICAgICAgICB3aW5kb3cuYU5Gb3JtSGFuZGxlck1hcCA9IG5ldyBNYXAoKTsgLy8gSSB3b3VsZCBoYXZlIHVzZWQgYSBgV2Vha01hcGAgaGVyZSwgYnV0IHRoYXQgZG9lcyBub3QgYWxsb3cgdXNpbmcgbm9uLW9iamVjdCBmb3Iga2V5c1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGdpdmVuIGZvcm0gZWxlbWVudCwgb3IgaWYgbm9uZSBhcmUgcGFzc2VkLCB0aGUgY3VycmVudCBgdGhpcy5wYXJlbnRGb3JtYCBvbmUgaGFzIGEgZm9ybSBoYW5kbGVyIG5hbWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxGb3JtRWxlbWVudHxudWxsfSBmb3JtRWxlbWVudFxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2hhc0Zvcm1IYW5kbGVyRnVuY3Rpb24oZm9ybUVsZW1lbnQgPSBudWxsKSB7XG4gICAgICAgIHJldHVybiAnYW5Gb3JtSGFuZGxlcicgaW4gdGhpcy5fZ2V0Rm9ybUVsZW1lbnQoZm9ybUVsZW1lbnQpLmRhdGFzZXQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBnaXZlbiBmb3JtIGVsZW1lbnQsIG9yIGRlZmF1bHRzIHRvIGB0aGlzLnBhcmVudEZvcm1gIGlmIG5vIGFyZ3VtZW50IGlzIHBhc3NlZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEZvcm1FbGVtZW50fG51bGx9IGZvcm1FbGVtZW50XG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZ2V0Rm9ybUVsZW1lbnQoZm9ybUVsZW1lbnQgPSBudWxsKSB7XG4gICAgICAgIGxldCBmb3JtRWxlbWVudFRvVXNlO1xuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChmb3JtRWxlbWVudCkpIHtcbiAgICAgICAgICAgIGZvcm1FbGVtZW50VG9Vc2UgPSBmb3JtRWxlbWVudDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZvcm1FbGVtZW50VG9Vc2UgPSB0aGlzLnBhcmVudEZvcm07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZm9ybUVsZW1lbnRUb1VzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBhIGZvcm0gaGFuZGxlciB1bmlxdWUgbmFtZSBhbmQgc3RvcmUgaXQgaW4gdGhlIGdsb2JhbCBmb3JtIGhhbmRsZXIgbGlzdC5cbiAgICAgKiBUaGlzIGFsc28gc2F2ZSB0aGF0IG5hbWUgaW4gdGhlIGRhdGFzZXQgb2YgdGhlIGdpdmVuIGZvcm0gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEZvcm1FbGVtZW50fG51bGx9IGZvcm1FbGVtZW50XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfc3RvcmVGb3JtSGFuZGxlckZ1bmN0aW9uKGZvcm1FbGVtZW50ID0gbnVsbCkge1xuICAgICAgICAvLyBDcmVhdGUgdGhlIHdlYWtNYXAgaWYgaXQgZG9lcyBub3QgZXhpc3RcbiAgICAgICAgaWYgKCF0aGlzLmNvbnN0cnVjdG9yLl9kb2VzRm9ybUhhbmRsZXJMaXN0RXhpc3RzKCkpIHtcbiAgICAgICAgICAgIHRoaXMuY29uc3RydWN0b3IuX2NyZWF0ZUZvcm1IYW5kbGVyTGlzdCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gR2VuZXJhdGUgYSB1bmlxdWUgbmFtZSBhbmQgc2F2ZSBpdCBpbiB0aGUgZm9ybSBkYXRhc2V0XG4gICAgICAgIGNvbnN0IGZvcm1IYW5kbGVyTmFtZSA9IEF1dG9OdW1lcmljSGVscGVyLnJhbmRvbVN0cmluZygpO1xuICAgICAgICB0aGlzLl9nZXRGb3JtRWxlbWVudChmb3JtRWxlbWVudCkuZGF0YXNldC5hbkZvcm1IYW5kbGVyID0gZm9ybUhhbmRsZXJOYW1lO1xuXG4gICAgICAgIC8vIEFkZCB0aGUgZm9ybSBoYW5kbGVyIG5hbWUgYW5kIGhhbmRsZSBmdW5jdGlvbiByZWZlcmVuY2UgdG8gdGhlIFdlYWtNYXBcbiAgICAgICAgd2luZG93LmFORm9ybUhhbmRsZXJNYXAuc2V0KGZvcm1IYW5kbGVyTmFtZSwgeyBzdWJtaXRGbjogdGhpcy5fb25Gb3JtU3VibWl0RnVuYywgcmVzZXRGbjogdGhpcy5fb25Gb3JtUmVzZXRGdW5jIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgZm9ybSBoYW5kbGVyIGtleSBuYW1lIGZyb20gdGhlIHBhcmVudCBmb3JtIGVsZW1lbnQsIGZvciB0aGUgZ2xvYmFsIGZvcm0gaGFuZGxlciBsaXN0LlxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ3wqfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2dldEZvcm1IYW5kbGVyS2V5KCkge1xuICAgICAgICBpZiAoIXRoaXMuX2hhc0Zvcm1IYW5kbGVyRnVuY3Rpb24oKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVW5hYmxlIHRvIHJldHJpZXZlIHRoZSBmb3JtIGhhbmRsZXIgbmFtZWApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZm9ybUhhbmRsZXJOYW1lID0gdGhpcy5wYXJlbnRGb3JtLmRhdGFzZXQuYW5Gb3JtSGFuZGxlcjtcbiAgICAgICAgaWYgKGZvcm1IYW5kbGVyTmFtZSA9PT0gJycpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBmb3JtIGhhbmRsZXIgbmFtZSBpcyBpbnZhbGlkYCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZm9ybUhhbmRsZXJOYW1lO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgJ3N1Ym1pdCcgZXZlbnQgaGFuZGxlciBmdW5jdGlvbiB1c2VkIGZvciB0aGUgcGFyZW50IGZvcm0uXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7ZnVuY3Rpb259XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZ2V0Rm9ybUhhbmRsZXJGdW5jdGlvbigpIHtcbiAgICAgICAgY29uc3QgZm9ybUhhbmRsZXJOYW1lID0gdGhpcy5fZ2V0Rm9ybUhhbmRsZXJLZXkoKTtcblxuICAgICAgICByZXR1cm4gd2luZG93LmFORm9ybUhhbmRsZXJNYXAuZ2V0KGZvcm1IYW5kbGVyTmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIHRoZSBkYXRhc2V0IGF0dHJpYnV0ZXMgYGRhdGEtYW4tY291bnRgIGFuZCBgZGF0YS1hbi1mb3JtLWhhbmRsZXJgIGZyb20gdGhlIHBhcmVudCBmb3JtIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9yZW1vdmVGb3JtRGF0YVNldEluZm8oKSB7XG4gICAgICAgIC8vIEp1c3QgaW4gY2FzZSwgc2V0IHRoZSBjb3VudGVyIHRvIDBcbiAgICAgICAgdGhpcy5fZGVjcmVtZW50UGFyZW50Rm9ybUNvdW50ZXIoKTtcbiAgICAgICAgLy8gUmVtb3ZlIHRoZSBmb3JtIGhhbmRsZXIgZnVuY3Rpb24gZnJvbSB0aGUgRm9ybUhhbmRsZXJGdW5jdGlvbiBNYXBcbiAgICAgICAgd2luZG93LmFORm9ybUhhbmRsZXJNYXAuZGVsZXRlKHRoaXMuX2dldEZvcm1IYW5kbGVyS2V5KCkpO1xuICAgICAgICAvLyBMYXN0bHksIHJlbW92ZSB0aGUgZGF0YXNldCBhdHRyaWJ1dGVzXG4gICAgICAgIHRoaXMucGFyZW50Rm9ybS5yZW1vdmVBdHRyaWJ1dGUoJ2RhdGEtYW4tY291bnQnKTtcbiAgICAgICAgdGhpcy5wYXJlbnRGb3JtLnJlbW92ZUF0dHJpYnV0ZSgnZGF0YS1hbi1mb3JtLWhhbmRsZXInKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIERPTSBlbGVtZW50IHdyaXRlIHBlcm1pc3Npb25zIGFjY29yZGluZyB0byB0aGUgY3VycmVudCBzZXR0aW5ncywgYnkgc2V0dGluZyB0aGUgYHJlYWRvbmx5YCBvciBgY29udGVudGVkaXRhYmxlYCBhdHRyaWJ1dGVzIGRlcGVuZGluZyBvZiBpdHMgdGFnIHR5cGUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9zZXRXcml0ZVBlcm1pc3Npb25zKCkge1xuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5yZWFkT25seSkge1xuICAgICAgICAgICAgdGhpcy5fc2V0UmVhZE9ubHkoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX3NldFJlYWRXcml0ZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBlbGVtZW50IHRvIGJlIHJlYWQtb25seS5cbiAgICAgKiBJZiB0aGUgRE9NIGVsZW1lbnQgdGFnIGlzIG5vdCBhbiBgaW5wdXRgLCB0aGVuIGl0IGBjb250ZW50ZWRpdGFibGVgIGF0dHJpYnV0ZSBpcyBzZXQgdG8gYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3NldFJlYWRPbmx5KCkge1xuICAgICAgICBpZiAodGhpcy5pc0lucHV0RWxlbWVudCkge1xuICAgICAgICAgICAgdGhpcy5kb21FbGVtZW50LnJlYWRPbmx5ID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZG9tRWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2NvbnRlbnRlZGl0YWJsZScsIGZhbHNlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgZWxlbWVudCB0byBiZSByZWFkLXdyaXRlLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfc2V0UmVhZFdyaXRlKCkge1xuICAgICAgICBpZiAodGhpcy5pc0lucHV0RWxlbWVudCkge1xuICAgICAgICAgICAgdGhpcy5kb21FbGVtZW50LnJlYWRPbmx5ID0gZmFsc2U7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmRvbUVsZW1lbnQuc2V0QXR0cmlidXRlKCdjb250ZW50ZWRpdGFibGUnLCB0cnVlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZCBhIHdhdGNoZXIgc28gdGhhdCBhbnkgZXh0ZXJuYWwgY2hhbmdlIHRvIHRoZSBBdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnQgd291bGQgYmUgZGV0ZWN0ZWQuXG4gICAgICogQXMgc29vbiBhcyBzdWNoIGNoYW5nZSBpcyBkZXRlY3RlZCwgQXV0b051bWVyaWMgdGhlbiB0cmllcyB0byBgc2V0KClgIHRoZSB2YWx1ZSBzbyB0aGF0IGl0IGdldHMgZm9ybWF0dGVkIGFuZCBzdG9yZWQgaW4gdGhlIGhpc3RvcnkuXG4gICAgICogLy9YWFggRm9yIG5vdywgdGhpcyBvbmx5IHdvcmtzIHdoZW4gd2F0Y2hpbmcgdGhlIGB2YWx1ZWAgYXR0cmlidXRlLCBub3QgdGhlIGB0ZXh0Q29udGVudGAgb25lXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfYWRkV2F0Y2hlcigpIHtcbiAgICAgICAgLy8gYGdldHRlclNldHRlcmAgY2FuIGJlIHVuZGVmaW5lZCB3aGVuIGEgbm9uLWlucHV0IGVsZW1lbnQgaXMgdXNlZFxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkKHRoaXMuZ2V0dGVyU2V0dGVyKSkge1xuICAgICAgICAgICAgY29uc3QgeyBzZXQ6IHNldHRlciwgZ2V0OiBnZXR0ZXIgfSA9IHRoaXMuZ2V0dGVyU2V0dGVyO1xuICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMuZG9tRWxlbWVudCwgdGhpcy5hdHRyaWJ1dGVUb1dhdGNoLCB7XG4gICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLCAvLyBUaGlzIGlzIG5lZWRlZCBpbiBzb21lIHJhcmUgY2FzZXNcbiAgICAgICAgICAgICAgICBnZXQgICAgICAgICA6ICgpID0+IGdldHRlci5jYWxsKHRoaXMuZG9tRWxlbWVudCksXG4gICAgICAgICAgICAgICAgc2V0ICAgICAgICAgOiB2YWwgPT4ge1xuICAgICAgICAgICAgICAgICAgICBzZXR0ZXIuY2FsbCh0aGlzLmRvbUVsZW1lbnQsIHZhbCk7XG4gICAgICAgICAgICAgICAgICAgIC8vIE9ubHkgYHNldCgpYCB0aGUgdmFsdWUgaWYgdGhlIG1vZGlmaWNhdGlvbiBjb21lcyBmcm9tIGFuIGV4dGVybmFsIHNvdXJjZVxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy53YXRjaEV4dGVybmFsQ2hhbmdlcyAmJiAhdGhpcy5pbnRlcm5hbE1vZGlmaWNhdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXQodmFsKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vRklYTUUgVGhlIGNvZGUgYWJvdmUgZmFpbHMgZm9yIHRoZSBgdGV4dENvbnRlbnRgIGF0dHJpYnV0ZSBzaW5jZSBgdGhpcy5nZXR0ZXJTZXR0ZXJgIGlzIHVuZGVmaW5lZCB3aGVuIHVzaW5nIGBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoKWBcbiAgICAgICAgLyogLy9YWFggVGhlIGNvZGUgYmVsb3cgKmFsbW9zdCogd29yayBmb3IgdGhlIHRleHRDb250ZW50LCBidXQgYnJlYWtzIHNvbWUgdW5pdCB0ZXN0c1xuICAgICAgICB0aGlzLnZhbHVlV2F0Y2hlZCA9IHRoaXMuZG9tRWxlbWVudFt0aGlzLmF0dHJpYnV0ZVRvV2F0Y2hdO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcy5kb21FbGVtZW50LCB0aGlzLmF0dHJpYnV0ZVRvV2F0Y2gsIHtcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwgLy8gVGhpcyBpcyBuZWVkZWQgaW4gc29tZSByYXJlIGNhc2VzXG4gICAgICAgICAgICBnZXQgICAgICAgICA6ICgpID0+IHRoaXMudmFsdWVXYXRjaGVkLFxuICAgICAgICAgICAgc2V0ICAgICAgICAgOiB2YWwgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudmFsdWVXYXRjaGVkID0gdmFsO1xuICAgICAgICAgICAgICAgIC8vIE9ubHkgYHNldCgpYCB0aGUgdmFsdWUgaWYgdGhlIG1vZGlmaWNhdGlvbiBjb21lcyBmcm9tIGFuIGV4dGVybmFsIHNvdXJjZVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLndhdGNoRXh0ZXJuYWxDaGFuZ2VzICYmICF0aGlzLmludGVybmFsTW9kaWZpY2F0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0KHZhbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgICovXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIHRoZSB3YXRjaGVyIG9uIHRoZSBBdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnRcbiAgICAgKiBOb3RlOiBUaGlzIG5lZWRzIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBBdXRvTnVtZXJpYyBlbGVtZW50IGlzICdyZW1vdmVkJywgb3RoZXJ3aXNlIHRoZSBnZXR0ZXIvc2V0dGVyIHN0YXlzIG9uIHRoZSBET00gZWxlbWVudCBhbmQgdGhhdCBjYW4gbGVhZCB0byBwcm9ibGVtIGlmIHRoZSB1c2VyIGluaXRpYWxpemUgYW5vdGhlciBBdXRvTnVtZXJpYyBvYmplY3Qgb24gaXQuXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfcmVtb3ZlV2F0Y2hlcigpIHtcbiAgICAgICAgLy8gYGdldHRlclNldHRlcmAgY2FuIGJlIHVuZGVmaW5lZCB3aGVuIGEgbm9uLWlucHV0IGVsZW1lbnQgaXMgdXNlZFxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkKHRoaXMuZ2V0dGVyU2V0dGVyKSkge1xuICAgICAgICAgICAgY29uc3QgeyBzZXQ6IHNldHRlciwgZ2V0OiBnZXR0ZXIgfSA9IHRoaXMuZ2V0dGVyU2V0dGVyO1xuICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMuZG9tRWxlbWVudCwgdGhpcy5hdHRyaWJ1dGVUb1dhdGNoLCB7XG4gICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLCAvLyBUaGlzIGlzIG5lZWRlZCBpbiBzb21lIHJhcmUgY2FzZXNcbiAgICAgICAgICAgICAgICBnZXQgICAgICAgICA6ICgpID0+IGdldHRlci5jYWxsKHRoaXMuZG9tRWxlbWVudCksXG4gICAgICAgICAgICAgICAgc2V0ICAgICAgICAgOiB2YWwgPT4ge1xuICAgICAgICAgICAgICAgICAgICBzZXR0ZXIuY2FsbCh0aGlzLmRvbUVsZW1lbnQsIHZhbCk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy9GSVhNRSBUaGUgY29kZSBhYm92ZSBmYWlscyBmb3IgdGhlIGB0ZXh0Q29udGVudGAgYXR0cmlidXRlIHNpbmNlIGB0aGlzLmdldHRlclNldHRlcmAgaXMgdW5kZWZpbmVkIHdoZW4gdXNpbmcgYGdldE93blByb3BlcnR5RGVzY3JpcHRvcigpYFxuICAgICAgICAvKiAvL1hYWCBUaGUgY29kZSBiZWxvdyAqYWxtb3N0KiB3b3JrIGZvciB0aGUgdGV4dENvbnRlbnQsIGJ1dCBicmVha3Mgc29tZSB1bml0IHRlc3RzXG4gICAgICAgIHRoaXMudmFsdWVXYXRjaGVkID0gdGhpcy5kb21FbGVtZW50W3RoaXMuYXR0cmlidXRlVG9XYXRjaF07XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLmRvbUVsZW1lbnQsIHRoaXMuYXR0cmlidXRlVG9XYXRjaCwge1xuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLCAvLyBUaGlzIGlzIG5lZWRlZCBpbiBzb21lIHJhcmUgY2FzZXNcbiAgICAgICAgICAgIGdldCAgICAgICAgIDogKCkgPT4gdGhpcy52YWx1ZVdhdGNoZWQsXG4gICAgICAgICAgICBzZXQgICAgICAgICA6IHZhbCA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZVdhdGNoZWQgPSB2YWw7XG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgICAgKi9cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIG5hbWUgb2YgdGhlIG9iamVjdCBhdHRyaWJ1dGUgdGhhdCBzdG9yZSB0aGUgY3VycmVudCBmb3JtYXR0ZWQgZGF0YSBpbiB0aGUgRE9NIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2dldEF0dHJpYnV0ZVRvV2F0Y2goKSB7XG4gICAgICAgIGxldCBhdHRyaWJ1dGVUb1dhdGNoO1xuICAgICAgICBpZiAodGhpcy5pc0lucHV0RWxlbWVudCkge1xuICAgICAgICAgICAgYXR0cmlidXRlVG9XYXRjaCA9ICd2YWx1ZSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBub2RlVHlwZSA9IHRoaXMuZG9tRWxlbWVudC5ub2RlVHlwZTtcbiAgICAgICAgICAgIGlmIChub2RlVHlwZSA9PT0gTm9kZS5FTEVNRU5UX05PREUgfHxcbiAgICAgICAgICAgICAgICBub2RlVHlwZSA9PT0gTm9kZS5ET0NVTUVOVF9OT0RFIHx8XG4gICAgICAgICAgICAgICAgbm9kZVR5cGUgPT09IE5vZGUuRE9DVU1FTlRfRlJBR01FTlRfTk9ERSkge1xuICAgICAgICAgICAgICAgIGF0dHJpYnV0ZVRvV2F0Y2ggPSAndGV4dENvbnRlbnQnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChub2RlVHlwZSA9PT0gTm9kZS5URVhUX05PREUpIHtcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGVUb1dhdGNoID0gJ25vZGVWYWx1ZSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYXR0cmlidXRlVG9XYXRjaDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTYXZlIHRoZSBjdXJyZW50IHJhdyB2YWx1ZSBpbnRvIHRoZSBoaXN0b3J5IHRhYmxlLCBhbG9uZyB3aXRoIHRoZSBzZWxlY3Rpb24gaW5mb3JtYXRpb24uXG4gICAgICpcbiAgICAgKiBJZiB0aGUgdXNlciBoYXMgZG9uZSBzb21lIHVuZG9zIGFuZCB0cmllcyB0byBlbnRlcjpcbiAgICAgKiAtIGEgbmV3IGFuZCBkaWZmZXJlbnQgbnVtYmVyIHRoYW4gdGhlICduZXh0JyBzdGF0ZSwgdGhpcyBkcm9wcyB0aGUgcmVzdCBvZiB0aGUgaGlzdG9yeSB0YWJsZVxuICAgICAqIC0gdGhlIHZlcnkgc2FtZSBudW1iZXIgdGhhdCByZXN1bHQgaW4gdGhlIHNhbWUgcmF3VmFsdWUgdGhhbiB0aGUgJ25leHQnIHN0YXRlLCB3ZSBvbmx5IG1vdmUgdGhlIGhpc3RvcnkgdGFibGUgcG9pbnRlciB0byB0aGUgbmV4dCBzdGF0ZVxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfaGlzdG9yeVRhYmxlQWRkKCkge1xuICAgICAgICAvL1RPRE8gQWRkIGEgYHRoaXMuc2V0dGluZ3Muc2F2ZVNlbGVjdGlvbnNJbnRvSGlzdG9yeWAgb3B0aW9uIHRvIHByZXZlbnQgc2F2aW5nIHRoZSBzZWxlY3Rpb25zIChpbiBvcmRlciB0byBnYWluIHBlcmZvcm1hbmNlKVxuICAgICAgICBjb25zdCBpc0VtcHR5SGlzdG9yeVRhYmxlID0gdGhpcy5oaXN0b3J5VGFibGUubGVuZ3RoID09PSAwO1xuICAgICAgICAvLyBPbmx5IGFkZCBhIG5ldyB2YWx1ZSBpZiBpdCdzIGRpZmZlcmVudCB0aGFuIHRoZSBwcmV2aW91cyBvbmUgKHRvIHByZXZlbnQgaW5maW5pdGVseSBhZGRpbmcgdmFsdWVzIG9uIG1vdXNlb3ZlciBmb3IgaW5zdGFuY2UpXG4gICAgICAgIGlmIChpc0VtcHR5SGlzdG9yeVRhYmxlIHx8IHRoaXMucmF3VmFsdWUgIT09IHRoaXMuX2hpc3RvcnlUYWJsZUN1cnJlbnRWYWx1ZVVzZWQoKSkge1xuICAgICAgICAgICAgLy8gVHJpbSB0aGUgaGlzdG9yeSB0YWJsZSBpZiB0aGUgdXNlciBjaGFuZ2VkIHRoZSB2YWx1ZSBvZiBhbiBpbnRlcm1lZGlhcnkgc3RhdGVcbiAgICAgICAgICAgIGxldCBhZGROZXdIaXN0b3J5U3RhdGUgPSB0cnVlO1xuICAgICAgICAgICAgaWYgKCFpc0VtcHR5SGlzdG9yeVRhYmxlKSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgc29tZSB1bmRvIGhhcyBiZWVuIGRvbmUgYW5kIHRoZSB1c2VyIHR5cGUgdGhlIGV4YWN0IHNhbWUgZGF0YSB0aGFuIHRoZSBuZXh0IGVudHJ5IGFmdGVyIHRoZSBjdXJyZW50IGhpc3RvcnkgcG9pbnRlciwgZG8gbm8gZHJvcCB0aGUgcmVzdCBvZiB0aGUgJ3JlZG8nIGxpc3QsIGFuZCBqdXN0IGFkdmFuY2UgdGhlIGhpc3RvcnlUYWJsZUluZGV4XG4gICAgICAgICAgICAgICAgY29uc3QgbmV4dEhpc3RvcnlTdGF0ZUluZGV4ID0gdGhpcy5oaXN0b3J5VGFibGVJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgaWYgKG5leHRIaXN0b3J5U3RhdGVJbmRleCA8IHRoaXMuaGlzdG9yeVRhYmxlLmxlbmd0aCAmJiB0aGlzLnJhd1ZhbHVlID09PSB0aGlzLmhpc3RvcnlUYWJsZVtuZXh0SGlzdG9yeVN0YXRlSW5kZXhdLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBjaGFyYWN0ZXIgaW5wdXQgcmVzdWx0IGluIHRoZSBzYW1lIHN0YXRlIHRoYW4gdGhlIG5leHQgb25lLCBkbyBub3QgcmVtb3ZlIHRoZSBuZXh0IGhpc3Rvcnkgc3RhdGVzIG5vciBhZGQgYSBuZXcgb25lXG4gICAgICAgICAgICAgICAgICAgIGFkZE5ld0hpc3RvcnlTdGF0ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcnN0IHJlbW92ZSBhbnl0aGluZyB0aGF0IGlzIGFmdGVyIHRoZSBjdXJyZW50IGluZGV4XG4gICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLmFycmF5VHJpbSh0aGlzLmhpc3RvcnlUYWJsZSwgdGhpcy5oaXN0b3J5VGFibGVJbmRleCArIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBoaXN0b3J5IHBvaW50ZXJcbiAgICAgICAgICAgIHRoaXMuaGlzdG9yeVRhYmxlSW5kZXgrKztcblxuICAgICAgICAgICAgLy8gQWRkIHRoZSBuZXcgaGlzdG9yeSBzdGF0ZSwgaWYgbmVlZGVkXG4gICAgICAgICAgICBpZiAoYWRkTmV3SGlzdG9yeVN0YXRlKSB7XG4gICAgICAgICAgICAgICAgLy8gU2F2ZSB0aGUgc2VsZWN0aW9uIGluZm9cbiAgICAgICAgICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50U2VsZWN0aW9uKHRoaXMuZG9tRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3Rpb25TdGFydCA9IHNlbGVjdGlvbi5zdGFydDtcbiAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdGlvbkVuZCA9IHNlbGVjdGlvbi5lbmQ7XG5cbiAgICAgICAgICAgICAgICAvLyBUaGVuIGFkZCB0aGUgbmV3IHJhdyB2YWx1ZVxuICAgICAgICAgICAgICAgIHRoaXMuaGlzdG9yeVRhYmxlLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAvLyBTYXZlIHRoZSByYXdWYWx1ZSBhbmQgc2VsZWN0aW9uIHN0YXJ0L2VuZFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy5yYXdWYWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhlIHNlbGVjdGlvbiBmb3IgdGhpcyBlbGVtZW50IGlzIHRlbXBvcmFyeSwgYW5kIHdpbGwgYmUgdXBkYXRlZCB3aGVuIHRoZSBuZXh0IGhpc3Rvcnkgc3RhdGUgd2lsbCBiZSByZWNvcmRlZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhhdCB3YXksIHdlIGFyZSBhbHdheXMgc3VyZSB3ZSBzYXZlIHRoZSBsYXN0IGNhcmV0IG9yIHNlbGVjdGlvbiBwb3NpdGlvbnMganVzdCBiZWZvcmUgdGhlIHZhbHVlIGlzIGNoYW5nZWQuIE90aGVyd2lzZSB3ZSB3b3VsZCBvbmx5IHNhdmUgdGhvc2UgcG9zaXRpb25zIHdoZW4gdGhlIHZhbHVlIGlzIGZpcnN0IGNoYW5nZWQsIGFuZCB3b3VsZCBub3QgdGFrZSBpbnRvIGFjY291bnQgdGhhdCB0aGUgdXNlciBjb3VsZCBtb3ZlIHRoZSBjYXJldCBhcm91bmQgYWZ0ZXJ3YXJkLlxuICAgICAgICAgICAgICAgICAgICAvLyBGb3IgaW5zdGFuY2UsIHRoaXMgaXMgbmVlZGVkIGlmIHRoZSB1c2VyIGNoYW5nZSB0aGUgZWxlbWVudCB2YWx1ZSwgYW5kIGltbWVkaWF0ZWx5IHVuZG8gaXQgOyBpZiBoZSB0aGVuIGRvZXMgYSByZWRvLCBoZSdsbCBzZWUgdGhlIHZhbHVlIGFuZCB0aGUgcmlnaHQgc2VsZWN0aW9uXG4gICAgICAgICAgICAgICAgICAgIC8vIFRvIHN1bSB1cDsgVGhlIHNlbGVjdGlvbiBwb3NpdGlvbiBhcmUgbm90IGFsd2F5cyArMSBjaGFyYWN0ZXIsIHNpbmNlIGl0IGNvdWxkIGFsc28gYmUgJzInIGlmIGEgZ3JvdXAgc2VwYXJhdG9yIGlzIGFkZGVkIHdoZW4gZW50ZXJpbmcgb25lIGNoYXJhY3Rlci4gVGhhdCdzIHdoeSB0aGUgY3VycmVudCBoaXN0b3J5IHN0YXRlIGNhcmV0L3NlbGVjdGlvbiBwb3NpdGlvbiBpcyB1cGRhdGVkIG9uIGVhY2ggYGtleXVwYCBldmVudC5cbiAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IHRoaXMuc2VsZWN0aW9uU3RhcnQgKyAxLCAvLyBIZXJlIHdlIGFkZCBvbmUgc2luY2UgdGhlIHVzZXIgYWRkZWQgb25lIGNoYXJhY3RlciB0b29cbiAgICAgICAgICAgICAgICAgICAgZW5kICA6IHRoaXMuc2VsZWN0aW9uRW5kICsgMSxcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgc2VsZWN0aW9uIGluIHRoZSBwcmV2aW91cyBlbnRyeSwgaW4gb3JkZXIgdG8ga2VlcCB0cmFjayBvZiB0aGUgdXBkYXRlZCBjYXJldC9zZWxlY3Rpb24gcG9zaXRpb25zXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaGlzdG9yeVRhYmxlLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5oaXN0b3J5VGFibGVbdGhpcy5oaXN0b3J5VGFibGVJbmRleCAtIDFdLnN0YXJ0ID0gdGhpcy5zZWxlY3Rpb25TdGFydDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5oaXN0b3J5VGFibGVbdGhpcy5oaXN0b3J5VGFibGVJbmRleCAtIDFdLmVuZCA9IHRoaXMuc2VsZWN0aW9uRW5kO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTGltaXQgdGhlIGhpc3RvcnkgdGFibGUgc2l6ZSBhY2NvcmRpbmcgdG8gdGhlIGBoaXN0b3J5U2l6ZWAgb3B0aW9uXG4gICAgICAgICAgICBpZiAodGhpcy5oaXN0b3J5VGFibGUubGVuZ3RoID4gdGhpcy5zZXR0aW5ncy5oaXN0b3J5U2l6ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2hpc3RvcnlUYWJsZUZvcmdldCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGVidWcgZnVuY3Rpb24gZm9yIHRoZSBoaXN0b3J5IHRhYmxlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICAvKlxuICAgIF9kZWJ1Z0hpc3RvcnlUYWJsZSgpIHtcbiAgICAgICAgbGV0IGkgPSAwO1xuICAgICAgICBsZXQgbWFyaztcbiAgICAgICAgdGhpcy5oaXN0b3J5VGFibGUuZm9yRWFjaChoaXN0b3J5ID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLmhpc3RvcnlUYWJsZUluZGV4ID09PSBpKSB7XG4gICAgICAgICAgICAgICAgbWFyayA9ICc+ICc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG1hcmsgPSAnJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGAke21hcmt9JHtpKyt9OiAke2hpc3RvcnkudmFsdWV9ICR7aGlzdG9yeS5zdGFydH18JHtoaXN0b3J5LmVuZH0gW29uR29pbmdSZWRvOiAke3RoaXMub25Hb2luZ1JlZG99XWApOyAvL0RFQlVHXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAqL1xuXG4gICAgLyoqXG4gICAgICogJ1VuZG8nIG9yICdSZWRvJyB0aGUgbGFzdC9uZXh0IHVzZXIgZW50cnkgaW4gdGhlIGhpc3RvcnkgdGFibGUuXG4gICAgICogVGhpcyBkb2VzIG5vdCBtb2RpZnkgdGhlIGhpc3RvcnkgdGFibGUsIG9ubHkgdGhlIHBvaW50ZXIgdG8gdGhlIGN1cnJlbnQgc3RhdGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHVuZG8gSWYgc2V0IHRvIGB0cnVlYCwgdGhlbiB0aGlzIGZ1bmN0aW9uIGRvZXMgYW4gJ1VuZG8nLCBvdGhlcndpc2UgaXQgZG9lcyBhICdSZWRvJ1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2hpc3RvcnlUYWJsZVVuZG9PclJlZG8odW5kbyA9IHRydWUpIHtcbiAgICAgICAgbGV0IGNoZWNrO1xuICAgICAgICBpZiAodW5kbykge1xuICAgICAgICAgICAgLy8gT25seSAndW5kbycgaWYgdGhlcmUgYXJlIHNvbWUgaW5mbyB0byB1bmRvXG4gICAgICAgICAgICBjaGVjayA9IHRoaXMuaGlzdG9yeVRhYmxlSW5kZXggPiAwO1xuICAgICAgICAgICAgaWYgKGNoZWNrKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaXN0b3J5VGFibGVJbmRleC0tO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gT25seSAncmVkbycgaWYgdGhlcmUgYXJlIHNvbWUgaW5mbyB0byByZWRvIGF0IHRoZSBlbmQgb2YgdGhlIGhpc3RvcnkgdGFibGVcbiAgICAgICAgICAgIGNoZWNrID0gdGhpcy5oaXN0b3J5VGFibGVJbmRleCArIDEgPCB0aGlzLmhpc3RvcnlUYWJsZS5sZW5ndGg7XG4gICAgICAgICAgICBpZiAoY2hlY2spIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpc3RvcnlUYWJsZUluZGV4Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY2hlY2spIHtcbiAgICAgICAgICAgIC8vIFNldCB0aGUgdmFsdWUgYmFja1xuICAgICAgICAgICAgY29uc3QgdW5kb0luZm8gPSB0aGlzLmhpc3RvcnlUYWJsZVt0aGlzLmhpc3RvcnlUYWJsZUluZGV4XTtcbiAgICAgICAgICAgIHRoaXMuc2V0KHVuZG9JbmZvLnZhbHVlLCBudWxsLCBmYWxzZSk7IC8vIG5leHQgb3IgcHJldmlvdXMgcmF3IHZhbHVlXG5cbiAgICAgICAgICAgIC8vIFNldCB0aGUgc2VsZWN0aW9uIGJhY2tcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRTZWxlY3Rpb24odGhpcy5kb21FbGVtZW50LCB1bmRvSW5mby5zdGFydCwgdW5kb0luZm8uZW5kKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqICdVbmRvJyB0aGUgbGFzdCB1c2VyIGVudHJ5IGJ5IGdvaW5nIGJhY2sgb25lIGVudHJ5IGluIHRoZSBoaXN0b3J5IHRhYmxlLlxuICAgICAqIFRoaXMga2VlcHMgdGhlIGZvbGxvd2luZyBlbnRyaWVzIGluIG9yZGVyIHRvIGFsbG93IGZvciBhICdyZWRvJy5cbiAgICAgKiBUaGlzIGRvZXMgbm90IG1vZGlmeSB0aGUgaGlzdG9yeSB0YWJsZSwgb25seSB0aGUgcG9pbnRlciB0byB0aGUgY3VycmVudCBzdGF0ZS5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9oaXN0b3J5VGFibGVVbmRvKCkge1xuICAgICAgICB0aGlzLl9oaXN0b3J5VGFibGVVbmRvT3JSZWRvKHRydWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqICdSZWRvJyB0aGUgbmV4dCB1c2VyIGVudHJ5IGluIHRoZSBoaXN0b3J5IHRhYmxlLlxuICAgICAqIFRoaXMgZG9lcyBub3QgbW9kaWZ5IHRoZSBoaXN0b3J5IHRhYmxlLCBvbmx5IHRoZSBwb2ludGVyIHRvIHRoZSBjdXJyZW50IHN0YXRlLlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2hpc3RvcnlUYWJsZVJlZG8oKSB7XG4gICAgICAgIHRoaXMuX2hpc3RvcnlUYWJsZVVuZG9PclJlZG8oZmFsc2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc2V0IHRoZSBoaXN0b3J5IHRhYmxlIHRvIGl0cyBpbml0aWFsIHN0YXRlLCBhbmQgc2VsZWN0IHRoZSB2YWx1ZS5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIC8qXG4gICAgcmVzZXRIaXN0b3J5VGFibGUoKSB7IC8vRklYTUUgVGVzdCB0aGlzXG4gICAgICAgIHRoaXMuc2V0KHRoaXMucmF3VmFsdWUsIG51bGwsIGZhbHNlKTtcbiAgICAgICAgdGhpcy5zZWxlY3QoKTtcbiAgICAgICAgY29uc3Qgc2VsZWN0aW9uID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFNlbGVjdGlvbih0aGlzLmRvbUVsZW1lbnQpO1xuICAgICAgICB0aGlzLmhpc3RvcnlUYWJsZUluZGV4ID0gMDtcbiAgICAgICAgdGhpcy5oaXN0b3J5VGFibGUgPSBbe1xuICAgICAgICAgICAgLy8gU2F2ZSB0aGUgcmF3VmFsdWUgYW5kIHNlbGVjdGlvbiBzdGFydC9lbmRcbiAgICAgICAgICAgIHZhbHVlOiB0aGlzLnJhd1ZhbHVlLFxuICAgICAgICAgICAgc3RhcnQ6IHNlbGVjdGlvbi5zdGFydCxcbiAgICAgICAgICAgIGVuZCAgOiBzZWxlY3Rpb24uZW5kLFxuICAgICAgICB9XTtcbiAgICB9XG4gICAgKi9cblxuICAgIC8qKlxuICAgICAqIE1ha2UgdGhlIGhpc3RvcnkgdGFibGUgZm9yZ2V0IGl0cyBmaXJzdCBOIGVsZW1lbnRzLCBzaGlmdGluZyBpdHMgaW5kZXhlcyBpbiB0aGUgcHJvY2Vzcy5cbiAgICAgKiBgTmAgYmVpbmcgZ2l2ZW4gYXMgdGhlIGBudW1iZXJPZkVudHJpZXNUb0ZvcmdldGAgcGFyYW1ldGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IG51bWJlck9mRW50cmllc1RvRm9yZ2V0XG4gICAgICogQHJldHVybnMge29iamVjdHxBcnJheTxvYmplY3Q+fSBUaGUgZGlzY2FyZGVkIG9iamVjdHMsIGluIGFuIEFycmF5LlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2hpc3RvcnlUYWJsZUZvcmdldChudW1iZXJPZkVudHJpZXNUb0ZvcmdldCA9IDEpIHtcbiAgICAgICAgY29uc3Qgc2hpZnRlZEF3YXkgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1iZXJPZkVudHJpZXNUb0ZvcmdldDsgaSsrKSB7XG4gICAgICAgICAgICBzaGlmdGVkQXdheS5wdXNoKHRoaXMuaGlzdG9yeVRhYmxlLnNoaWZ0KCkpO1xuICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBoaXN0b3J5IHRhYmxlIGluZGV4IGFjY29yZGluZ2x5XG4gICAgICAgICAgICB0aGlzLmhpc3RvcnlUYWJsZUluZGV4LS07XG4gICAgICAgICAgICBpZiAodGhpcy5oaXN0b3J5VGFibGVJbmRleCA8IDApIHtcbiAgICAgICAgICAgICAgICAvLyBJbiBjYXNlIHRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIG1vcmUgdGltZXMgdGhhbiB0aGVyZSBpcyBzdGF0ZXMgaW4gdGhlIGhpc3RvcnkgdGFibGVcbiAgICAgICAgICAgICAgICB0aGlzLmhpc3RvcnlUYWJsZUluZGV4ID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzaGlmdGVkQXdheS5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgIHJldHVybiBzaGlmdGVkQXdheVswXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzaGlmdGVkQXdheTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIGN1cnJlbnRseSB1c2VkIHZhbHVlIGZyb20gdGhlIGhpc3RvcnkgdGFibGUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bWJlcn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9oaXN0b3J5VGFibGVDdXJyZW50VmFsdWVVc2VkKCkge1xuICAgICAgICBsZXQgaW5kZXhUb1VzZSA9IHRoaXMuaGlzdG9yeVRhYmxlSW5kZXg7XG4gICAgICAgIGlmIChpbmRleFRvVXNlIDwgMCkge1xuICAgICAgICAgICAgaW5kZXhUb1VzZSA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KHRoaXMuaGlzdG9yeVRhYmxlW2luZGV4VG9Vc2VdKSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gJyc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQgPSB0aGlzLmhpc3RvcnlUYWJsZVtpbmRleFRvVXNlXS52YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGFyc2UgdGhlIGBzdHlsZVJ1bGVzYCBvcHRpb24gYW5kIHJ1biB0aGUgdGVzdCBmb3IgZWFjaCBnaXZlbiBydWxlcywgZWl0aGVyIHByZS1kZWZpbmVkIG9uZXMgbGlrZSBgcG9zaXRpdmVgLCBgbmVnYXRpdmVgIGFuZCBgcmFuZ2VzYCwgb3IgdXNlciBkZWZpbmVkIGNhbGxiYWNrcyB3aXRoaW4gdGhlIGB1c2VyRGVmaW5lZGAgYXR0cmlidXRlLlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3BhcnNlU3R5bGVSdWxlcygpIHtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eSh0aGlzLnNldHRpbmdzLnN0eWxlUnVsZXMpIHx8IHRoaXMucmF3VmFsdWUgPT09ICcnKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyAncG9zaXRpdmUnIGF0dHJpYnV0ZVxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eSh0aGlzLnNldHRpbmdzLnN0eWxlUnVsZXMucG9zaXRpdmUpKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5yYXdWYWx1ZSA+PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fYWRkQ1NTQ2xhc3ModGhpcy5zZXR0aW5ncy5zdHlsZVJ1bGVzLnBvc2l0aXZlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVtb3ZlQ1NTQ2xhc3ModGhpcy5zZXR0aW5ncy5zdHlsZVJ1bGVzLnBvc2l0aXZlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vICduZWdhdGl2ZScgYXR0cmlidXRlXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KHRoaXMuc2V0dGluZ3Muc3R5bGVSdWxlcy5uZWdhdGl2ZSkpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnJhd1ZhbHVlIDwgMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2FkZENTU0NsYXNzKHRoaXMuc2V0dGluZ3Muc3R5bGVSdWxlcy5uZWdhdGl2ZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuX3JlbW92ZUNTU0NsYXNzKHRoaXMuc2V0dGluZ3Muc3R5bGVSdWxlcy5uZWdhdGl2ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyAncmFuZ2VzJyBhdHRyaWJ1dGVcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkodGhpcy5zZXR0aW5ncy5zdHlsZVJ1bGVzLnJhbmdlcykgJiYgdGhpcy5zZXR0aW5ncy5zdHlsZVJ1bGVzLnJhbmdlcy5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Muc3R5bGVSdWxlcy5yYW5nZXMuZm9yRWFjaChyYW5nZSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucmF3VmFsdWUgPj0gcmFuZ2UubWluICYmIHRoaXMucmF3VmFsdWUgPCByYW5nZS5tYXgpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fYWRkQ1NTQ2xhc3MocmFuZ2UuY2xhc3MpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlbW92ZUNTU0NsYXNzKHJhbmdlLmNsYXNzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vICd1c2VyRGVmaW5lZCcgYXR0cmlidXRlXG4gICAgICAgIC8vVE9ETyBBbHNvIHBhc3MgdGhlIG9sZCByYXcgdmFsdWUgYXMgYSBwYXJhbWV0ZXIsIGFuZCBub3Qgb25seSB0aGUgbmV3IHJhdyB2YWx1ZVxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eSh0aGlzLnNldHRpbmdzLnN0eWxlUnVsZXMudXNlckRlZmluZWQpICYmIHRoaXMuc2V0dGluZ3Muc3R5bGVSdWxlcy51c2VyRGVmaW5lZC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Muc3R5bGVSdWxlcy51c2VyRGVmaW5lZC5mb3JFYWNoKHVzZXJPYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0Z1bmN0aW9uKHVzZXJPYmplY3QuY2FsbGJhY2spKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRlc3QgZm9yIHRoZSB0eXBlIG9mIHRoZSBgY2xhc3Nlc2AgYXR0cmlidXRlLCB3aGljaCBjaGFuZ2VzIHRoZSBmdW5jdGlvbiBiZWhhdmlvclxuICAgICAgICAgICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcodXNlck9iamVjdC5jbGFzc2VzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgJ2NsYXNzZXMnIGlzIGEgc3RyaW5nLCBzZXQgaXQgaWYgYHRydWVgLCByZW1vdmUgaXQgaWYgYGZhbHNlYFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHVzZXJPYmplY3QuY2FsbGJhY2sodGhpcy5yYXdWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9hZGRDU1NDbGFzcyh1c2VyT2JqZWN0LmNsYXNzZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZW1vdmVDU1NDbGFzcyh1c2VyT2JqZWN0LmNsYXNzZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzQXJyYXkodXNlck9iamVjdC5jbGFzc2VzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHVzZXJPYmplY3QuY2xhc3Nlcy5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiAnY2xhc3NlcycgaXMgYW4gYXJyYXkgd2l0aCBvbmx5IDIgZWxlbWVudHMsIHNldCB0aGUgZmlyc3QgY2xhc3MgaWYgYHRydWVgLCB0aGUgc2Vjb25kIGlmIGBmYWxzZWBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodXNlck9iamVjdC5jYWxsYmFjayh0aGlzLnJhd1ZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9hZGRDU1NDbGFzcyh1c2VyT2JqZWN0LmNsYXNzZXNbMF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZW1vdmVDU1NDbGFzcyh1c2VyT2JqZWN0LmNsYXNzZXNbMV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlbW92ZUNTU0NsYXNzKHVzZXJPYmplY3QuY2xhc3Nlc1swXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2FkZENTU0NsYXNzKHVzZXJPYmplY3QuY2xhc3Nlc1sxXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh1c2VyT2JqZWN0LmNsYXNzZXMubGVuZ3RoID4gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSBjYWxsYmFjayByZXR1cm5zIGFuIGFycmF5IG9mIGluZGV4ZXMgdG8gdXNlIG9uIHRoZSBgY2xhc3Nlc2AgYXJyYXlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYWxsYmFja1Jlc3VsdCA9IHVzZXJPYmplY3QuY2FsbGJhY2sodGhpcy5yYXdWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzQXJyYXkoY2FsbGJhY2tSZXN1bHQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIG11bHRpcGxlIGluZGV4ZXMgYXJlIHJldHVybmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZXJPYmplY3QuY2xhc3Nlcy5mb3JFYWNoKCh1c2VyQ2xhc3MsIGluZGV4KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KGluZGV4LCBjYWxsYmFja1Jlc3VsdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9hZGRDU1NDbGFzcyh1c2VyQ2xhc3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZW1vdmVDU1NDbGFzcyh1c2VyQ2xhc3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzSW50KGNhbGxiYWNrUmVzdWx0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiBvbmx5IG9uZSBpbmRleCBpcyByZXR1cm5lZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2VyT2JqZWN0LmNsYXNzZXMuZm9yRWFjaCgodXNlckNsYXNzLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ID09PSBjYWxsYmFja1Jlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2FkZENTU0NsYXNzKHVzZXJDbGFzcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlbW92ZUNTU0NsYXNzKHVzZXJDbGFzcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGNhbGxiYWNrUmVzdWx0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgYWxsIHRoZSBjbGFzc2VzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZXJPYmplY3QuY2xhc3Nlcy5mb3JFYWNoKHVzZXJDbGFzcyA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZW1vdmVDU1NDbGFzcyh1c2VyQ2xhc3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgY2FsbGJhY2sgcmVzdWx0IGlzIG5vdCBhbiBhcnJheSBub3IgYSB2YWxpZCBhcnJheSBpbmRleCwgJHt0eXBlb2YgY2FsbGJhY2tSZXN1bHR9IGdpdmVuLmApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcignVGhlIGNsYXNzZXMgYXR0cmlidXRlIGlzIG5vdCB2YWxpZCBmb3IgdGhlIGBzdHlsZVJ1bGVzYCBvcHRpb24uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KHVzZXJPYmplY3QuY2xhc3NlcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmICdjbGFzc2VzJyBpcyBgdW5kZWZpbmVkYCBvciBgbnVsbGAsIHRoZW4gdGhlIGNhbGxiYWNrIGlzIGNhbGxlZCB3aXRoIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QgcGFzc2VkIGFzIGEgcGFyYW1ldGVyXG4gICAgICAgICAgICAgICAgICAgICAgICB1c2VyT2JqZWN0LmNhbGxiYWNrKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcignVGhlIGNhbGxiYWNrL2NsYXNzZXMgc3RydWN0dXJlIGlzIG5vdCB2YWxpZCBmb3IgdGhlIGBzdHlsZVJ1bGVzYCBvcHRpb24uJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKGBUaGUgZ2l2ZW4gXFxgc3R5bGVSdWxlc1xcYCBjYWxsYmFjayBpcyBub3QgYSBmdW5jdGlvbiwgJHt0eXBlb2YgY2FsbGJhY2t9IGdpdmVuLmAsIHRoaXMuc2V0dGluZ3Muc2hvd1dhcm5pbmdzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZCB0aGUgZ2l2ZW4gQ1NTIGNsYXNzIHRvIHRoZSBET00gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBjc3NDbGFzc05hbWVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9hZGRDU1NDbGFzcyhjc3NDbGFzc05hbWUpIHtcbiAgICAgICAgdGhpcy5kb21FbGVtZW50LmNsYXNzTGlzdC5hZGQoY3NzQ2xhc3NOYW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgdGhlIGdpdmVuIENTUyBjbGFzcyBmcm9tIHRoZSBET00gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBjc3NDbGFzc05hbWVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9yZW1vdmVDU1NDbGFzcyhjc3NDbGFzc05hbWUpIHtcbiAgICAgICAgdGhpcy5kb21FbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoY3NzQ2xhc3NOYW1lKTtcbiAgICB9XG5cbiAgICAvLyBUaGlzIGFyZSB0aGUgcHVibGljIGZ1bmN0aW9uIGF2YWlsYWJsZSBvbiBlYWNoIGF1dG9OdW1lcmljLW1hbmFnZWQgZWxlbWVudFxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIHRoYXQgdXBkYXRlcyB0aGUgQXV0b051bWVyaWMgc2V0dGluZ3MsIGFuZCBpbW1lZGlhdGVseSBmb3JtYXQgdGhlIGVsZW1lbnQgYWNjb3JkaW5nbHkuXG4gICAgICogVGhlIG9wdGlvbnMgcGFzc2VkIGFzIHBhcmFtZXRlcihzKSBpcyBlaXRoZXIgb25lIG9yIG1hbnkgb2JqZWN0cyB0aGF0IGVhY2ggY29udGFpbnMgc29tZSBzZXR0aW5ncywgaWUuIDpcbiAgICAgKiB7XG4gICAgICogICAgIGRpZ2l0R3JvdXBTZXBhcmF0b3I6IFwiLlwiLFxuICAgICAqICAgICBkZWNpbWFsQ2hhcmFjdGVyOiBcIixcIixcbiAgICAgKiAgICAgY3VycmVuY3lTeW1ib2w6ICfigqwgJyxcbiAgICAgKiB9XG4gICAgICogSWYgbXVsdGlwbGUgb3B0aW9ucyBhcmUgcGFzc2VkLCB0aGUgbGF0dGVyIG92ZXJ3cml0ZSB0aGUgcHJldmlvdXMgb25lcy5cbiAgICAgKlxuICAgICAqIE5vdGU6IElmIHRoZSBuZXcgc2V0dGluZ3MgYXJlIG5vdCB2YWxpZGF0ZWQsIG9yIHRoZSBjYWxsIHRvIGBzZXQoKWAgZmFpbHMsIHRoZW4gdGhlIHByZXZpb3VzIHZhbGlkIHNldHRpbmdzIGFyZSByZXZlcnRlZCBiYWNrIHRvLlxuICAgICAqXG4gICAgICogQGV4YW1wbGUgYW5FbGVtZW50LnVwZGF0ZSh7IG9wdGlvbnMgfSkgLy8gVXBkYXRlcyB0aGUgc2V0dGluZ3NcbiAgICAgKiBAZXhhbXBsZSBhbkVsZW1lbnQudXBkYXRlKHsgb3B0aW9uczEgfSwgeyBvcHRpb25zMiB9KSAvLyBVcGRhdGVzIHRoZSBzZXR0aW5ncyB3aXRoIG11bHRpcGxlIG9wdGlvbiBvYmplY3RzXG4gICAgICogQGV4YW1wbGUgYW5FbGVtZW50LnVwZGF0ZShbeyBvcHRpb25zMSB9LCB7IG9wdGlvbnMyIH1dKSAvLyBVcGRhdGVzIHRoZSBzZXR0aW5ncyB3aXRoIG11bHRpcGxlIG9wdGlvbiBvYmplY3RzIGluIGEgc2luZ2xlIGFycmF5XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdHxzdHJpbmd8YXJyYXl9IG5ld09wdGlvbnNcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgdXBkYXRlKC4uLm5ld09wdGlvbnMpIHtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkobmV3T3B0aW9ucykgJiYgQXJyYXkuaXNBcnJheShuZXdPcHRpb25zWzBdKSkge1xuICAgICAgICAgICAgLy8gQWxsb3dzIHRvIHBhc3MgYSBzaW5nbGUgYXJyYXkgb2Ygb3B0aW9uc1xuICAgICAgICAgICAgbmV3T3B0aW9ucyA9IG5ld09wdGlvbnNbMF07XG4gICAgICAgIH1cblxuICAgICAgICAvLyBLZWVwIGEgY29weSBvZiB0aGUgb3JpZ2luYWwgc2V0dGluZ3MgYmVmb3JlIGNoYW5naW5nIHRoZW0sIGluIGNhc2UgdGhleSBkbyBub3QgdmFsaWRhdGUgY29ycmVjdGx5LCBzbyB3ZSBjYW4gc3dpdGNoIGJhY2sgdG8gdGhlbVxuICAgICAgICBjb25zdCBvcmlnaW5hbFNldHRpbmdzID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QodGhpcy5zZXR0aW5ncyk7IC8vVE9ETyBDaGVjayB0aGF0IHRoZSBgc3R5bGVSdWxlc2Agb3B0aW9uIGlzIGNvcnJlY3RseSBjbG9uZWQgKGR1ZSB0byBkZXB0aCBjbG9uaW5nIGxpbWl0YXRpb24pXG5cbiAgICAgICAgLy8gU3RvcmUgdGhlIGN1cnJlbnQgdW5mb3JtYXR0ZWQgaW5wdXQgdmFsdWVcbiAgICAgICAgY29uc3QgbnVtZXJpY1N0cmluZyA9IHRoaXMucmF3VmFsdWU7XG5cbiAgICAgICAgLy8gR2VuZXJhdGUgYSBzaW5nbGUgb3B0aW9uIG9iamVjdCB3aXRoIHRoZSBzZXR0aW5ncyBmcm9tIHRoZSBsYXR0ZXIgb3ZlcndyaXRpbmcgdGhvc2UgZnJvbSB0aGUgZm9ybWVyXG4gICAgICAgIGxldCBvcHRpb25zVG9Vc2UgPSB7fTtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eShuZXdPcHRpb25zKSB8fCBuZXdPcHRpb25zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgb3B0aW9uc1RvVXNlID0gbnVsbDtcbiAgICAgICAgfSBlbHNlIGlmIChuZXdPcHRpb25zLmxlbmd0aCA+PSAxKSB7XG4gICAgICAgICAgICBuZXdPcHRpb25zLmZvckVhY2gob3B0aW9uT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25zdHJ1Y3Rvci5faXNQcmVEZWZpbmVkT3B0aW9uVmFsaWQob3B0aW9uT2JqZWN0KSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBUaGUgb3B0aW9uIG9iamVjdCBpcyBhIHByZWRlZmluZWQgb3B0aW9uIG5hbWUgKGllLiAnZXVybycpXG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbk9iamVjdCA9IHRoaXMuY29uc3RydWN0b3IuX2dldE9wdGlvbk9iamVjdChvcHRpb25PYmplY3QpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIE9iamVjdC5hc3NpZ24ob3B0aW9uc1RvVXNlLCBvcHRpb25PYmplY3QpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBVcGRhdGUgdGhlIHNldHRpbmdzXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICB0aGlzLl9zZXRTZXR0aW5ncyhvcHRpb25zVG9Vc2UsIHRydWUpO1xuICAgICAgICAgICAgdGhpcy5fc2V0V3JpdGVQZXJtaXNzaW9ucygpOyAvLyBVcGRhdGUgdGhlIHJlYWQvd3JpdGUgcGVybWlzc2lvbnNcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZUV2ZW50TGlzdGVuZXJzKCk7XG5cbiAgICAgICAgICAgIC8vIFJlZm9ybWF0IHRoZSBpbnB1dCB2YWx1ZSB3aXRoIHRoZSBuZXcgc2V0dGluZ3NcbiAgICAgICAgICAgIC8vIE5vdGU6IHdlIGFsd2F5cyBgc2V0YCwgZXZlbiB3aGVuIGBudW1lcmljU3RyaW5nYCBpcyB0aGUgZW1wdHkgc3RyaW5nICcnLCBzaW5jZSBgZW1wdHlJbnB1dEJlaGF2aW9yYCAoc2V0IHRvIGBhbHdheXNgIG9yIGB6ZXJvYCkgY2FuIGNoYW5nZSBob3cgdGhlIGVtcHR5IGlucHV0IGlzIGZvcm1hdHRlZFxuICAgICAgICAgICAgdGhpcy5zZXQobnVtZXJpY1N0cmluZyk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAvLyBJZiB0aGUgc2V0dGluZ3MgdmFsaWRhdGlvbiBmYWlscywgdGhlbiB3ZSBzd2l0Y2ggYmFjayB0byB0aGUgcHJldmlvdXMgdmFsaWQgc2V0dGluZ3NcbiAgICAgICAgICAgIHRoaXMuX3NldFNldHRpbmdzKG9yaWdpbmFsU2V0dGluZ3MsIHRydWUpOyAvLyBgX3NldFNldHRpbmdzKClgIGlzIHVzZWQgaGVyZSBpbnN0ZWFkIG9mIGRpcmVjdGx5IGRvaW5nIGB0aGlzLnNldHRpbmdzID0gb3JpZ2luYWxTZXR0aW5ncztgIHNpbmNlIGxvdHMgb2Ygc2lkZSB2YXJpYWJsZXMgYXJlIGNhbGN1bGF0ZWQgZnJvbSB0aGUgc2V0dGluZ3MsIGFuZCB3ZSBuZWVkIHRvIGdldCB0aG9zZSBiYWNrIHRvIHRoZWlyIHByZXZpb3VzIHN0YXRlLiBOb3RlOiBgX3NldFNldHRpbmdzKClgIGlzIGNhbGxlZCBpbiB0aGUgJ3VwZGF0ZScgbW9kZSBpbiBvcmRlciB0byBjb3JyZWN0bHkgc2V0IGJhY2sgdGhlIGBvcmlnaW5hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZWAgdmFsdWUuXG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBVbmFibGUgdG8gdXBkYXRlIHRoZSBzZXR0aW5ncywgdGhvc2UgYXJlIGludmFsaWQ6IFske2Vycm9yfV1gKTtcblxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIG9wdGlvbnMgb2JqZWN0IGNvbnRhaW5pbmcgYWxsIHRoZSBjdXJyZW50IGF1dG9OdW1lcmljIHNldHRpbmdzIGluIGVmZmVjdC5cbiAgICAgKiBZb3UgY2FuIHRoZW4gZGlyZWN0bHkgYWNjZXNzIGVhY2ggb3B0aW9uIGJ5IHVzaW5nIGl0cyBuYW1lIDogYGFuRWxlbWVudC5nZXRTZXR0aW5ncygpLm9wdGlvbk5hbWVBdXRvQ29tcGxldGVkYC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYW5FbGVtZW50LmdldFNldHRpbmdzKClcbiAgICAgKiBhbkVsZW1lbnQuZ2V0U2V0dGluZ3MoKS5kZWNpbWFsQ2hhcmFjdGVyIC8vIFJldHVybiB0aGUgZGVjaW1hbENoYXJhY3RlciBzZXR0aW5nIGFzIGEgc3RyaW5nIC0gYW55IHZhbGlkIG9wdGlvbiBuYW1lIGNhbiBiZSB1c2VkXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7b2JqZWN0fVxuICAgICAqL1xuICAgIGdldFNldHRpbmdzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zZXR0aW5ncztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGdpdmVuIGVsZW1lbnQgdmFsdWUsIGFuZCBmb3JtYXQgaXQgaW1tZWRpYXRlbHkuXG4gICAgICogQWRkaXRpb25hbGx5LCB0aGlzIGBzZXQoKWAgbWV0aG9kIGNhbiBhY2NlcHQgb3B0aW9ucyB0aGF0IHdpbGwgYmUgbWVyZ2VkIGludG8gdGhlIGN1cnJlbnQgQXV0b051bWVyaWMgZWxlbWVudCwgdGFraW5nIHByZWNlZGVuY2Ugb3ZlciBhbnkgcHJldmlvdXMgc2V0dGluZ3MuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZSBhbkVsZW1lbnQuc2V0KCcxMjM0NS42NycpIC8vIEZvcm1hdHMgdGhlIHZhbHVlXG4gICAgICogQGV4YW1wbGUgYW5FbGVtZW50LnNldCgxMjM0NS42NykgLy8gRm9ybWF0cyB0aGUgdmFsdWVcbiAgICAgKiBAZXhhbXBsZSBhbkVsZW1lbnQuc2V0KDEyMzQ1LjY3LCB7IGRlY2ltYWxDaGFyYWN0ZXIgOiAnLCcgfSkgLy8gVXBkYXRlIHRoZSBzZXR0aW5ncyBhbmQgZm9ybWF0cyB0aGUgdmFsdWUgaW4gb25lIGdvXG4gICAgICogQGV4YW1wbGUgYW5FbGVtZW50Lm5vcnRoQW1lcmljYW4oKS5zZXQoJyQxMiwzNDUuNjcnKSAvLyBTZXQgYW4gYWxyZWFkeSBmb3JtYXR0ZWQgdmFsdWUgKHRoaXMgZG9lcyBub3QgX2V4YWN0bHlfIHJlc3BlY3QgdGhlIGN1cnJlbmN5IHN5bWJvbC9uZWdhdGl2ZSBwbGFjZW1lbnRzLCBidXQgb25seSByZW1vdmUgYWxsIG5vbi1udW1iZXJzIGNoYXJhY3RlcnMsIGFjY29yZGluZyB0byB0aGUgb25lcyBnaXZlbiBpbiB0aGUgc2V0dGluZ3MpXG4gICAgICogQGV4YW1wbGUgYW5FbGVtZW50LnNldChudWxsKSAvLyBTZXQgdGhlIHJhd1ZhbHVlIGFuZCBlbGVtZW50IHZhbHVlIHRvIGBudWxsYFxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfG51bGx9IG5ld1ZhbHVlIFRoZSB2YWx1ZSBtdXN0IGJlIGEgTnVtYmVyLCBhIG51bWVyaWMgc3RyaW5nIG9yIGBudWxsYCAoaWYgYGVtcHR5SW5wdXRCZWhhdmlvcmAgaXMgc2V0IHRvIGAnbnVsbCdgKVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zIEEgc2V0dGluZ3Mgb2JqZWN0IHRoYXQgd2lsbCBvdmVycmlkZSB0aGUgY3VycmVudCBzZXR0aW5ncy4gTm90ZTogdGhlIHVwZGF0ZSBpcyBkb25lIG9ubHkgaWYgdGhlIGBuZXdWYWx1ZWAgaXMgZGVmaW5lZC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHNhdmVDaGFuZ2VUb0hpc3RvcnkgSWYgc2V0IHRvIGB0cnVlYCwgdGhlbiB0aGUgY2hhbmdlIGlzIHJlY29yZGVkIGluIHRoZSBoaXN0b3J5IHRhYmxlXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqIEB0aHJvd3NcbiAgICAgKi9cbiAgICBzZXQobmV3VmFsdWUsIG9wdGlvbnMgPSBudWxsLCBzYXZlQ2hhbmdlVG9IaXN0b3J5ID0gdHJ1ZSkge1xuICAgICAgICAvL1RPRE8gQWRkIHRoZSBgc2F2ZVNldHRpbmdzYCBvcHRpb25zLiBJZiBgdHJ1ZWAsIHRoZW4gd2hlbiBgb3B0aW9uc2AgaXMgcGFzc2VkLCB0aGVuIGl0IG92ZXJ3cml0ZSB0aGUgY3VycmVudCBgdGhpcy5zZXR0aW5nc2AuIElmIGBmYWxzZWAgdGhlIGBvcHRpb25zYCBhcmUgb25seSB1c2VkIG9uY2UgYW5kIGB0aGlzLnNldHRpbmdzYCBpcyBub3QgbW9kaWZpZWRcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkKG5ld1ZhbHVlKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZyhgWW91IGFyZSB0cnlpbmcgdG8gc2V0IGFuICd1bmRlZmluZWQnIHZhbHVlIDsgYW4gZXJyb3IgY291bGQgaGF2ZSBvY2N1cnJlZC5gLCB0aGlzLnNldHRpbmdzLnNob3dXYXJuaW5ncyk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRoZSBvcHRpb25zIHVwZGF0ZSBpcyBkb25lIG9ubHkgaWYgdGhlIGBuZXdWYWx1ZWAgaXMgbm90IGB1bmRlZmluZWRgXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMpKSB7XG4gICAgICAgICAgICB0aGlzLl9zZXRTZXR0aW5ncyhvcHRpb25zLCB0cnVlKTsgLy8gV2UgZG8gbm90IGNhbGwgYHVwZGF0ZWAgaGVyZSBzaW5jZSB0aGlzIHdvdWxkIGNhbGwgYHNldGAgdG9vXG4gICAgICAgIH1cblxuICAgICAgICBpZiAobmV3VmFsdWUgPT09IG51bGwgJiYgdGhpcy5zZXR0aW5ncy5lbXB0eUlucHV0QmVoYXZpb3IgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLm51bGwpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLndhcm5pbmcoYFlvdSBhcmUgdHJ5aW5nIHRvIHNldCB0aGUgXFxgbnVsbFxcYCB2YWx1ZSB3aGlsZSB0aGUgXFxgZW1wdHlJbnB1dEJlaGF2aW9yXFxgIG9wdGlvbiBpcyBzZXQgdG8gJHt0aGlzLnNldHRpbmdzLmVtcHR5SW5wdXRCZWhhdmlvcn0uIElmIHlvdSB3YW50IHRvIGJlIGFibGUgdG8gc2V0IHRoZSBcXGBudWxsXFxgIHZhbHVlLCB5b3UgbmVlZCB0byBjaGFuZ2UgdGhlICdlbXB0eUlucHV0QmVoYXZpb3InIG9wdGlvbiB0byBcXGAnbnVsbCdcXGAuYCwgdGhpcy5zZXR0aW5ncy5zaG93V2FybmluZ3MpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgdmFsdWU7XG4gICAgICAgIGlmIChuZXdWYWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgLy9UT0RPIE1lcmdlIHRoaXMgaW50byBhIGdsb2JhbCBgaWYgKG5ld1ZhbHVlID09PSBudWxsKSB7YCB0ZXN0LCB3aXRoIHRoZSB0ZXN0IGFib3ZlXG4gICAgICAgICAgICAvLyBIZXJlIHRoaXMuc2V0dGluZ3MuZW1wdHlJbnB1dEJlaGF2aW9yID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5udWxsXG4gICAgICAgICAgICB0aGlzLl9zZXRFbGVtZW50QW5kUmF3VmFsdWUobnVsbCwgbnVsbCwgc2F2ZUNoYW5nZVRvSGlzdG9yeSk7XG4gICAgICAgICAgICB0aGlzLl9zYXZlVmFsdWVUb1BlcnNpc3RlbnRTdG9yYWdlKCk7XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl90b051bWVyaWNWYWx1ZShuZXdWYWx1ZSwgdGhpcy5zZXR0aW5ncyk7XG4gICAgICAgIGlmIChpc05hTihOdW1iZXIodmFsdWUpKSkge1xuICAgICAgICAgICAgLy9UT0RPIERvIG5vdCBtb2RpZnkgdGhlIGVsZW1lbnQgdmFsdWUgaWYgdGhlIG5ld1ZhbHVlIHJlc3VsdHMgaW4gYE5hTmAuIE1ha2Ugc3VyZSB0aGUgc2V0dGluZ3MsIGlmIG1vZGlmaWVkLCBhcmUgcmV2ZXJ0IGJhY2sgdG9vLlxuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZyhgVGhlIHZhbHVlIHlvdSBhcmUgdHJ5aW5nIHRvIHNldCByZXN1bHRzIGluIFxcYE5hTlxcYC4gVGhlIGVsZW1lbnQgdmFsdWUgaXMgc2V0IHRvIHRoZSBlbXB0eSBzdHJpbmcgaW5zdGVhZC5gLCB0aGlzLnNldHRpbmdzLnNob3dXYXJuaW5ncyk7XG4gICAgICAgICAgICB0aGlzLnNldFZhbHVlKCcnLCBzYXZlQ2hhbmdlVG9IaXN0b3J5KTtcblxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodmFsdWUgPT09ICcnKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuc2V0dGluZ3MuZW1wdHlJbnB1dEJlaGF2aW9yKSB7XG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci56ZXJvOlxuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IDA7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IubWluOlxuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHRoaXMuc2V0dGluZ3MubWluaW11bVZhbHVlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLm1heDpcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSB0aGlzLnNldHRpbmdzLm1heGltdW1WYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVtYmVyKHRoaXMuc2V0dGluZ3MuZW1wdHlJbnB1dEJlaGF2aW9yKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBOdW1iZXIodGhpcy5zZXR0aW5ncy5lbXB0eUlucHV0QmVoYXZpb3IpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodmFsdWUgIT09ICcnKSB7XG4gICAgICAgICAgICBjb25zdCBbbWluVGVzdCwgbWF4VGVzdF0gPSB0aGlzLmNvbnN0cnVjdG9yLl9jaGVja0lmSW5SYW5nZVdpdGhPdmVycmlkZU9wdGlvbih2YWx1ZSwgdGhpcy5zZXR0aW5ncyk7XG5cbiAgICAgICAgICAgIC8vIE1vZGlmeSB0aGUgZm9ybWF0dGVkIHZhbHVlIGlmIHRoZSByYXdWYWx1ZSBpcyBmb3VuZCBpbiB0aGUgYHZhbHVlc1RvU3RyaW5nc2Agb3B0aW9uXG4gICAgICAgICAgICBpZiAobWluVGVzdCAmJiBtYXhUZXN0ICYmIHRoaXMuc2V0dGluZ3MudmFsdWVzVG9TdHJpbmdzICYmIHRoaXMuX2NoZWNrVmFsdWVzVG9TdHJpbmdzKHZhbHVlKSkge1xuICAgICAgICAgICAgICAgIC8vIFNldCB0aGUgcmF3IHZhbHVlIG5vcm1hbGx5LCBhbmQgdGhlIGZvcm1hdHRlZCB2YWx1ZSB3aXRoIHRoZSBjb3JyZXNwb25kaW5nIHN0cmluZ1xuICAgICAgICAgICAgICAgIHRoaXMuX3NldEVsZW1lbnRBbmRSYXdWYWx1ZSh0aGlzLnNldHRpbmdzLnZhbHVlc1RvU3RyaW5nc1t2YWx1ZV0sIHZhbHVlLCBzYXZlQ2hhbmdlVG9IaXN0b3J5KTtcbiAgICAgICAgICAgICAgICB0aGlzLl9zYXZlVmFsdWVUb1BlcnNpc3RlbnRTdG9yYWdlKCk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gVGhpcyB0ZXN0IGlzIG5lZWRlZCBieSB0aGUgYHNob3dQb3NpdGl2ZVNpZ25gIG9wdGlvblxuICAgICAgICAgICAgY29uc3QgaXNaZXJvID0gQXV0b051bWVyaWNIZWxwZXIuaXNaZXJvT3JIYXNOb1ZhbHVlKHZhbHVlKTtcbiAgICAgICAgICAgIGlmIChpc1plcm8pIHtcbiAgICAgICAgICAgICAgICB2YWx1ZSA9ICcwJztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG1pblRlc3QgJiYgbWF4VGVzdCkge1xuICAgICAgICAgICAgICAgIGxldCBmb3JjZWRSYXdWYWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX3JvdW5kUmF3VmFsdWUodmFsdWUsIHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICAgICAgICAgIGZvcmNlZFJhd1ZhbHVlID0gdGhpcy5fdHJpbUxlYWRpbmdBbmRUcmFpbGluZ1plcm9zKGZvcmNlZFJhd1ZhbHVlLnJlcGxhY2UodGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyLCAnLicpKTsgLy8gTW92ZSB0aGUgYHNldFJhd1ZhbHVlYCBjYWxsIGFmdGVyIHRoZSBgc2V0RWxlbWVudFZhbHVlYCBvbmVcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IHRoaXMuX2dldFJhd1ZhbHVlVG9Gb3JtYXQodmFsdWUpOyAvLyBNdWx0aXBseSB0aGUgcmF3IHZhbHVlIHRvIG9idGFpbiB0aGUgZm9ybWF0dGVkIHZhbHVlXG5cbiAgICAgICAgICAgICAgICAvLyBSb3VuZCB0aGUgZ2l2ZW4gdmFsdWUgYWNjb3JkaW5nIHRvIHRoZSBvYmplY3Qgc3RhdGUgKGZvY3VzZWQvdW5mb2N1c2VkKVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzRm9jdXNlZCkge1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX3JvdW5kRm9ybWF0dGVkVmFsdWVTaG93bk9uRm9jdXModmFsdWUsIHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmRpdmlzb3JXaGVuVW5mb2N1c2VkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHZhbHVlIC8gdGhpcy5zZXR0aW5ncy5kaXZpc29yV2hlblVuZm9jdXNlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWUudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdGhpcy5jb25zdHJ1Y3Rvci5fcm91bmRGb3JtYXR0ZWRWYWx1ZVNob3duT25CbHVyKHZhbHVlLCB0aGlzLnNldHRpbmdzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX21vZGlmeU5lZ2F0aXZlU2lnbkFuZERlY2ltYWxDaGFyYWN0ZXJGb3JGb3JtYXR0ZWRWYWx1ZSh2YWx1ZSwgdGhpcy5zZXR0aW5ncyk7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9hZGRHcm91cFNlcGFyYXRvcnModmFsdWUsIHRoaXMuc2V0dGluZ3MsIHRoaXMuaXNGb2N1c2VkLCB0aGlzLnJhd1ZhbHVlLCBmb3JjZWRSYXdWYWx1ZSk7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmlzRm9jdXNlZCAmJiB0aGlzLnNldHRpbmdzLnN5bWJvbFdoZW5VbmZvY3VzZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBgJHt2YWx1ZX0ke3RoaXMuc2V0dGluZ3Muc3ltYm9sV2hlblVuZm9jdXNlZH1gO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMgfHwgdGhpcy5zZXR0aW5ncy5kaXZpc29yV2hlblVuZm9jdXNlZCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zYXZlVmFsdWVUb1BlcnNpc3RlbnRTdG9yYWdlKCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0RWxlbWVudEFuZFJhd1ZhbHVlKHZhbHVlLCBmb3JjZWRSYXdWYWx1ZSwgc2F2ZUNoYW5nZVRvSGlzdG9yeSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKCFtaW5UZXN0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMubWluUmFuZ2VFeGNlZWRlZCwgdGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIW1heFRlc3QpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fdHJpZ2dlckV2ZW50KEF1dG9OdW1lcmljLmV2ZW50cy5tYXhSYW5nZUV4Y2VlZGVkLCB0aGlzLmRvbUVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSB2YWx1ZSBbJHt2YWx1ZX1dIGJlaW5nIHNldCBmYWxscyBvdXRzaWRlIG9mIHRoZSBtaW5pbXVtVmFsdWUgWyR7dGhpcy5zZXR0aW5ncy5taW5pbXVtVmFsdWV9XSBhbmQgbWF4aW11bVZhbHVlIFske3RoaXMuc2V0dGluZ3MubWF4aW11bVZhbHVlfV0gcmFuZ2Ugc2V0IGZvciB0aGlzIGVsZW1lbnRgKTtcblxuICAgICAgICAgICAgICAgIHRoaXMuX3JlbW92ZVZhbHVlRnJvbVBlcnNpc3RlbnRTdG9yYWdlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRWYWx1ZSgnJywgc2F2ZUNoYW5nZVRvSGlzdG9yeSk7IC8vVE9ETyBTaG91bGRuJ3Qgd2UganVzdCBkcm9wIHRoYXQgZmF1bHR5IG5ld1ZhbHVlIGFuZCBrZWVwIHRoZSBwcmV2aW91cyBvbmU/IFRoaXMgaXMgYmVoaW5kIGEgYHRocm93RXJyb3IoKWAgY2FsbCBhbnl3YXkuLlxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBIZXJlLCBgdmFsdWVgIGVxdWFsIHRoZSBlbXB0eSBzdHJpbmcgYCcnYFxuICAgICAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmVtcHR5SW5wdXRCZWhhdmlvciA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IuYWx3YXlzKSB7XG4gICAgICAgICAgICAgICAgLy8gS2VlcCB0aGUgY3VycmVuY3kgc3ltYm9sIGFzIHBlciBlbXB0eUlucHV0QmVoYXZpb3JcbiAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSAnJztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fc2V0RWxlbWVudEFuZFJhd1ZhbHVlKHJlc3VsdCwgJycsIHNhdmVDaGFuZ2VUb0hpc3RvcnkpO1xuXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgZ2l2ZW4gdmFsdWUgZGlyZWN0bHkgYXMgdGhlIERPTSBlbGVtZW50IHZhbHVlLCB3aXRob3V0IGZvcm1hdHRpbmcgaXQgYmVmb3JlaGFuZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gc2V0IHRoZSB2YWx1ZSBhbmQgdXBkYXRlIHRoZSBzZXR0aW5nIGluIG9uZSBnbyAodGhlIHZhbHVlIHdpbGwgYWdhaW4gbm90IGJlIGZvcm1hdHRlZCBpbW1lZGlhdGVseSkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd9IHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnNcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICogQHRocm93c1xuICAgICAqL1xuICAgIHNldFVuZm9ybWF0dGVkKHZhbHVlLCBvcHRpb25zID0gbnVsbCkge1xuICAgICAgICAvL1RPRE8gU2hvdWxkIHdlIHVzZSBgQXV0b051bWVyaWMudW5mb3JtYXQoKWAgaGVyZSBhbmQgc2V0IHRoZSB1bmZvcm1hdHRlZCByZXN1bHQgaW4gY2FzZSBgdmFsdWVgIGlzIGZvcm1hdHRlZD9cbiAgICAgICAgaWYgKHZhbHVlID09PSBudWxsIHx8IEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkKHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUaGUgb3B0aW9ucyB1cGRhdGUgaXMgZG9uZSBvbmx5IGlmIHRoZSBgdmFsdWVgIGlzIG5vdCBudWxsXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMpKSB7XG4gICAgICAgICAgICB0aGlzLl9zZXRTZXR0aW5ncyhvcHRpb25zLCB0cnVlKTsgLy8gV2UgZG8gbm90IGNhbGwgYHVwZGF0ZWAgaGVyZSBzaW5jZSB0aGlzIHdvdWxkIGNhbGwgYHNldGAgdG9vXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBzdHJpcHBlZFZhbHVlID0gdGhpcy5jb25zdHJ1Y3Rvci5fcmVtb3ZlQnJhY2tldHModmFsdWUsIHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICBjb25zdCBub3JtYWxpemVkVmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9zdHJpcEFsbE5vbk51bWJlckNoYXJhY3RlcnMoc3RyaXBwZWRWYWx1ZSwgdGhpcy5zZXR0aW5ncywgdHJ1ZSwgdGhpcy5pc0ZvY3VzZWQpO1xuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVtYmVyKG5vcm1hbGl6ZWRWYWx1ZSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSB2YWx1ZSBpcyBub3QgYSB2YWxpZCBvbmUsIGl0J3Mgbm90IGEgbnVtZXJpYyBzdHJpbmcgbm9yIGEgcmVjb2duaXplZCBjdXJyZW5jeS5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IFttaW5UZXN0LCBtYXhUZXN0XSA9IHRoaXMuY29uc3RydWN0b3IuX2NoZWNrSWZJblJhbmdlV2l0aE92ZXJyaWRlT3B0aW9uKG5vcm1hbGl6ZWRWYWx1ZSwgdGhpcy5zZXR0aW5ncyk7XG4gICAgICAgIGlmIChtaW5UZXN0ICYmIG1heFRlc3QpIHtcbiAgICAgICAgICAgIC8vIElmIHRoZSBgbm9ybWFsaXplZFZhbHVlYCBpcyBpbiB0aGUgcmFuZ2VcbiAgICAgICAgICAgIHRoaXMuc2V0VmFsdWUodmFsdWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHZhbHVlIGlzIG91dCBvZiB0aGUgcmFuZ2UgbGltaXRzIFske3RoaXMuc2V0dGluZ3MubWluaW11bVZhbHVlfSwgJHt0aGlzLnNldHRpbmdzLm1heGltdW1WYWx1ZX1dLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBnaXZlbiB2YWx1ZSBkaXJlY3RseSBhcyB0aGUgRE9NIGVsZW1lbnQgdmFsdWUsIHdpdGhvdXQgZm9ybWF0dGluZyBpdCBiZWZvcmVoYW5kLCBhbmQgd2l0aG91dCBjaGVja2luZyBpdHMgdmFsaWRpdHkuXG4gICAgICogVGhpcyBhbHNvIHVwZGF0ZXMgdGhlIGByYXdWYWx1ZWAgd2l0aCB0aGUgZ2l2ZW4gYG5ld1ZhbHVlYCwgd2l0aG91dCBjaGVja2luZyBpdCB0b28gOyBpZiBpdCdzIG5vdCBmb3JtYXR0ZWQgbGlrZSBhIG51bWJlciByZWNvZ25pemVkIGJ5IEphdmFzY3JpcHQsIHRoaXMgKndpbGwqIGxpa2VseSBtYWtlIG90aGVyIEF1dG9OdW1lcmljIG1ldGhvZHMgZmFpbC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcnxudWxsfSBuZXdWYWx1ZSBUaGUgbmV3IHZhbHVlIHRvIHNldCBvbiB0aGUgZWxlbWVudFxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gc2F2ZUNoYW5nZVRvSGlzdG9yeSBJZiBzZXQgdG8gYHRydWVgLCB0aGVuIHRoZSBjaGFuZ2UgaXMgcmVjb3JkZWQgaW4gdGhlIGhpc3RvcnkgYXJyYXksIG90aGVyd2lzZSBpdCBpcyBub3RcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgc2V0VmFsdWUobmV3VmFsdWUsIHNhdmVDaGFuZ2VUb0hpc3RvcnkgPSB0cnVlKSB7XG4gICAgICAgIHRoaXMuX3NldEVsZW1lbnRBbmRSYXdWYWx1ZShuZXdWYWx1ZSwgc2F2ZUNoYW5nZVRvSGlzdG9yeSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2F2ZSB0aGUgcmF3IHZhbHVlIGluc2lkZSB0aGUgQXV0b051bWVyaWMgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfG51bGx9IHJhd1ZhbHVlIFRoZSBudW1lcmljIHZhbHVlIGFzIHVuZGVyc3Rvb2QgYnkgSmF2YXNjcmlwdCBsaWtlIGEgYE51bWJlcmBcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHNhdmVDaGFuZ2VUb0hpc3RvcnkgSWYgc2V0IHRvIGB0cnVlYCwgdGhlbiB0aGUgY2hhbmdlIGlzIHJlY29yZGVkIGluIHRoZSBoaXN0b3J5IGFycmF5LCBvdGhlcndpc2UgaXQgaXMgbm90XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfc2V0UmF3VmFsdWUocmF3VmFsdWUsIHNhdmVDaGFuZ2VUb0hpc3RvcnkgPSB0cnVlKSB7XG4gICAgICAgIC8vIE9ubHkgc2V0IHRoZSByYXcgdmFsdWUgaWYgdGhlIGdpdmVuIHZhbHVlIGlzIGRpZmZlcmVudCB0aGFuIHRoZSBjdXJyZW50IG9uZVxuICAgICAgICBpZiAodGhpcy5yYXdWYWx1ZSAhPT0gcmF3VmFsdWUpIHsgLy9UT0RPIE1hbmFnZSB0aGUgY2FzZSB3aGVyZSBvbmUgdmFsdWUgaXMgYSBzdHJpbmcgd2hpbGUgdGhlIG90aGVyIGlzIGEgbnVtYmVyP1xuICAgICAgICAgICAgY29uc3Qgb2xkUmF3VmFsdWUgPSB0aGlzLnJhd1ZhbHVlO1xuICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSByYXcgdmFsdWVcbiAgICAgICAgICAgIHRoaXMucmF3VmFsdWUgPSByYXdWYWx1ZTsgLy8gQnkgZGVmYXVsdCwgaWYgdGhlIGByYXdWYWx1ZWAgaXMgY2hhbmdlZCBwcm9ncmFtbWF0aWNhbGx5XG5cbiAgICAgICAgICAgIGlmICgoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbCh0aGlzLnNldHRpbmdzLnJhd1ZhbHVlRGl2aXNvcikgJiYgdGhpcy5zZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3IgIT09IDApICYmIC8vIE9ubHkgZGl2aWRlIGlmIHRoZSBgcmF3VmFsdWVEaXZpc29yYCBvcHRpb24gaXMgc2V0XG4gICAgICAgICAgICAgICAgcmF3VmFsdWUgIT09ICcnICYmIHJhd1ZhbHVlICE9PSBudWxsICYmIC8vIERvIG5vdCBtb2RpZnkgdGhlIGByYXdWYWx1ZWAgaWYgaXQncyBhbiBlbXB0eSBzdHJpbmcgb3IgbnVsbFxuICAgICAgICAgICAgICAgIHRoaXMuX2lzVXNlck1hbnVhbGx5RWRpdGluZ1RoZVZhbHVlKCkpIHsgLy8gSWYgdGhlIHVzZXIgaXMgbWFudWFsbHkgY2hhbmdpbmcgdGhlIGVsZW1lbnQgdmFsdWVcbiAgICAgICAgICAgICAgICB0aGlzLnJhd1ZhbHVlIC89IHRoaXMuc2V0dGluZ3MucmF3VmFsdWVEaXZpc29yO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBCcm9hZGNhc3QgdGhlIGByYXdWYWx1ZU1vZGlmaWVkYCBldmVudCBzaW5jZSB0aGUgYHJhd1ZhbHVlYCBoYXMgYmVlbiBtb2RpZmllZFxuICAgICAgICAgICAgdGhpcy5fdHJpZ2dlckV2ZW50KEF1dG9OdW1lcmljLmV2ZW50cy5yYXdWYWx1ZU1vZGlmaWVkLCB0aGlzLmRvbUVsZW1lbnQsIHtcbiAgICAgICAgICAgICAgICBvbGRSYXdWYWx1ZSxcbiAgICAgICAgICAgICAgICBuZXdSYXdWYWx1ZTogdGhpcy5yYXdWYWx1ZSxcbiAgICAgICAgICAgICAgICBpc1ByaXN0aW5lIDogdGhpcy5pc1ByaXN0aW5lKHRydWUpLFxuICAgICAgICAgICAgICAgIGVycm9yICAgICAgOiBudWxsLFxuICAgICAgICAgICAgICAgIGFORWxlbWVudCAgOiB0aGlzLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIENoYW5nZSB0aGUgZWxlbWVudCBzdHlsZSBvciB1c2UgdGhlIHJlbGV2YW50IGNhbGxiYWNrc1xuICAgICAgICAgICAgdGhpcy5fcGFyc2VTdHlsZVJ1bGVzKCk7XG5cbiAgICAgICAgICAgIGlmIChzYXZlQ2hhbmdlVG9IaXN0b3J5KSB7XG4gICAgICAgICAgICAgICAgLy8gU2F2ZSBpbiB0aGUgaGlzdG9yeSB0aGUgbGFzdCBrbm93biByYXcgdmFsdWUgYW5kIGZvcm1hdHRlZCByZXN1bHQgc2VsZWN0aW9uXG4gICAgICAgICAgICAgICAgdGhpcy5faGlzdG9yeVRhYmxlQWRkKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGdpdmVuIHZhbHVlIG9uIHRoZSBET00gZWxlbWVudCwgd2l0aG91dCBhZmZlY3RpbmcgdGhlIGByYXdWYWx1ZWAuXG4gICAgICogVGhpcyBzZW5kIGFuICdhdXRvTnVtZXJpYzpmb3JtYXR0ZWQnIGV2ZW50IGlmIHRoZSBuZXcgdmFsdWUgaXMgZGlmZmVyZW50IHRoYW4gdGhlIG9sZCBvbmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd9IG5ld0VsZW1lbnRWYWx1ZVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gc2VuZEZvcm1hdHRlZEV2ZW50IElmIHNldCB0byBgdHJ1ZWAsIHRoZW4gdGhlIGBBdXRvTnVtZXJpYy5ldmVudHMuZm9ybWF0dGVkYCBldmVudCBpcyBzZW50IGlmIHRoZSB2YWx1ZSBoYXMgY2hhbmdlZFxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9zZXRFbGVtZW50VmFsdWUobmV3RWxlbWVudFZhbHVlLCBzZW5kRm9ybWF0dGVkRXZlbnQgPSB0cnVlKSB7XG4gICAgICAgIC8vVE9ETyBVc2UgYW4gaW50ZXJuYWwgYXR0cmlidXRlIHRvIHRyYWNrIHRoZSBjdXJyZW50IHZhbHVlIG9mIHRoZSBlbGVtZW50IGBmb3JtYXR0ZWRWYWx1ZWAgKGxpa2UgaXRzIGNvdW50ZXJwYXJ0IGByYXdWYWx1ZWApLiBUaGlzIHdvdWxkIGFsbG93IHVzIHRvIGF2b2lkIGNhbGxpbmcgYGdldEVsZW1lbnRWYWx1ZWAgbWFueSB0aW1lc1xuICAgICAgICBjb25zdCBvbGRFbGVtZW50VmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50KTtcblxuICAgICAgICAvLyBPbmx5IHVwZGF0ZSB0aGUgdmFsdWUgaWYgaXQncyBkaWZmZXJlbnQgZnJvbSB0aGUgY3VycmVudCBvbmVcbiAgICAgICAgaWYgKG5ld0VsZW1lbnRWYWx1ZSAhPT0gb2xkRWxlbWVudFZhbHVlKSB7XG4gICAgICAgICAgICB0aGlzLmludGVybmFsTW9kaWZpY2F0aW9uID0gdHJ1ZTtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQsIG5ld0VsZW1lbnRWYWx1ZSk7XG4gICAgICAgICAgICB0aGlzLmludGVybmFsTW9kaWZpY2F0aW9uID0gZmFsc2U7XG5cbiAgICAgICAgICAgIGlmIChzZW5kRm9ybWF0dGVkRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl90cmlnZ2VyRXZlbnQoQXV0b051bWVyaWMuZXZlbnRzLmZvcm1hdHRlZCwgdGhpcy5kb21FbGVtZW50LCB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFZhbHVlICAgOiBvbGRFbGVtZW50VmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIG5ld1ZhbHVlICAgOiBuZXdFbGVtZW50VmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIG9sZFJhd1ZhbHVlOiB0aGlzLnJhd1ZhbHVlLFxuICAgICAgICAgICAgICAgICAgICBuZXdSYXdWYWx1ZTogdGhpcy5yYXdWYWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgaXNQcmlzdGluZSA6IHRoaXMuaXNQcmlzdGluZShmYWxzZSksXG4gICAgICAgICAgICAgICAgICAgIGVycm9yICAgICAgOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICBhTkVsZW1lbnQgIDogdGhpcyxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgZ2l2ZW4gdmFsdWUgb24gdGhlIERPTSBlbGVtZW50LCBhbmQgdGhlIHJhdyB2YWx1ZSBvbiBgdGhpcy5yYXdWYWx1ZWAsIGlmIGJvdGggYXJlIGdpdmVuLlxuICAgICAqIElmIG9ubHkgb25lIHZhbHVlIGlzIGdpdmVuLCB0aGVuIGJvdGggdGhlIERPTSBlbGVtZW50IHZhbHVlIGFuZCB0aGUgcmF3IHZhbHVlIGFyZSBzZXQgd2l0aCB0aGF0IHZhbHVlLlxuICAgICAqIFRoZSB0aGlyZCBhcmd1bWVudCBgc2F2ZUNoYW5nZVRvSGlzdG9yeWAgZGVmaW5lcyBpZiB0aGUgY2hhbmdlIHNob3VsZCBiZSByZWNvcmRlZCBpbiB0aGUgaGlzdG9yeSBhcnJheS5cbiAgICAgKiBOb3RlOiBpZiB0aGUgc2Vjb25kIGFyZ3VtZW50IGByYXdWYWx1ZWAgaXMgYSBib29sZWFuLCB3ZSBjb25zaWRlciB0aGF0IGlzIHJlYWxseSBpcyB0aGUgYHNhdmVDaGFuZ2VUb0hpc3RvcnlgIGFyZ3VtZW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfG51bGx9IG5ld0VsZW1lbnRWYWx1ZVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ3xudWxsfGJvb2xlYW59IHJhd1ZhbHVlXG4gICAgICogQHBhcmFtIHtib29sZWFufSBzYXZlQ2hhbmdlVG9IaXN0b3J5XG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3NldEVsZW1lbnRBbmRSYXdWYWx1ZShuZXdFbGVtZW50VmFsdWUsIHJhd1ZhbHVlID0gbnVsbCwgc2F2ZUNoYW5nZVRvSGlzdG9yeSA9IHRydWUpIHtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChyYXdWYWx1ZSkpIHtcbiAgICAgICAgICAgIHJhd1ZhbHVlID0gbmV3RWxlbWVudFZhbHVlO1xuICAgICAgICB9IGVsc2UgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihyYXdWYWx1ZSkpIHtcbiAgICAgICAgICAgIHNhdmVDaGFuZ2VUb0hpc3RvcnkgPSByYXdWYWx1ZTtcbiAgICAgICAgICAgIHJhd1ZhbHVlID0gbmV3RWxlbWVudFZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy9YWFggVGhlIG9yZGVyIGhlcmUgaXMgaW1wb3J0YW50IDsgdGhlIHZhbHVlIHNob3VsZCBmaXJzdCBiZSBzZXQgb24gdGhlIGVsZW1lbnQsIHRoZW4gYW5kIG9ubHkgdGhlbiB3ZSBzaG91bGQgdXBkYXRlIHRoZSByYXcgdmFsdWVcbiAgICAgICAgLy8gSW4gdGhlIGBzZXQoKWAgZnVuY3Rpb24sIHdlIG1ha2Ugc3VyZSB0byBjYWxsIGBfc2V0UmF3VmFsdWVgICphZnRlciogYHNldEVsZW1lbnRWYWx1ZWAgc28gdGhhdCBpZiBgX3NldFJhd1ZhbHVlYCBjYWxscyBhIGNhbGxiYWNrIHRoYXQgbW9kaWZ5IHRoZSBgcmF3VmFsdWVgLCB0aGVuIHRoZSBuZXcgdmFsdWUgaXMgc2V0IGNvcnJlY3RseSAoYWZ0ZXIgYHNldEVsZW1lbnRWYWx1ZWAgYnJpZWZseSBzZXQgaXRzIHZhbHVlIGZpcnN0KVxuICAgICAgICB0aGlzLl9zZXRFbGVtZW50VmFsdWUobmV3RWxlbWVudFZhbHVlKTtcbiAgICAgICAgdGhpcy5fc2V0UmF3VmFsdWUocmF3VmFsdWUsIHNhdmVDaGFuZ2VUb0hpc3RvcnkpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgbXVsdGlwbGllZCByYXcgdmFsdWUgd2l0aCB0aGUgYHJhd1ZhbHVlRGl2aXNvcmAuXG4gICAgICogVGhpcyBpcyB1c2VkIHRvIGRpc3BsYXkgZGlmZmVyZW50IHZhbHVlcyBiZXR3ZWVuIHRoZSByYXcgYW5kIGZvcm1hdHRlZCB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd8bnVsbH0gcmF3VmFsdWUgVGhlIG51bWVyaWMgdmFsdWUgYXMgdW5kZXJzdG9vZCBieSBKYXZhc2NyaXB0IGxpa2UgYSBgTnVtYmVyYFxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ8c3RyaW5nfG51bGx9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZ2V0UmF3VmFsdWVUb0Zvcm1hdChyYXdWYWx1ZSkge1xuICAgICAgICBsZXQgcmF3VmFsdWVGb3JUaGVFbGVtZW50VmFsdWU7XG4gICAgICAgIGlmICgoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbCh0aGlzLnNldHRpbmdzLnJhd1ZhbHVlRGl2aXNvcikgJiYgdGhpcy5zZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3IgIT09IDApICYmIC8vIE9ubHkgbXVsdGlwbHkgaWYgdGhlIGByYXdWYWx1ZURpdmlzb3JgIG9wdGlvbiBpcyBzZXRcbiAgICAgICAgICAgIHJhd1ZhbHVlICE9PSAnJyAmJiByYXdWYWx1ZSAhPT0gbnVsbCkgeyAvLyBEbyBub3QgbW9kaWZ5IHRoZSBgcmF3VmFsdWVgIGlmIGl0J3MgYW4gZW1wdHkgc3RyaW5nIG9yIG51bGxcbiAgICAgICAgICAgIC8vICF0aGlzLl9pc1VzZXJNYW51YWxseUVkaXRpbmdUaGVWYWx1ZSgpKSB7IC8vIElmIHRoZSB1c2VyIGlzIE5PVCBtYW51YWxseSBjaGFuZ2luZyB0aGUgZWxlbWVudCB2YWx1ZSwgYnV0IHRoYXQgaXMgZG9uZSBwcm9ncmFtbWF0aWNhbGx5XG4gICAgICAgICAgICByYXdWYWx1ZUZvclRoZUVsZW1lbnRWYWx1ZSA9IHJhd1ZhbHVlICogdGhpcy5zZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3I7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByYXdWYWx1ZUZvclRoZUVsZW1lbnRWYWx1ZSA9IHJhd1ZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJhd1ZhbHVlRm9yVGhlRWxlbWVudFZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIHRoZSBnaXZlbiB2YWx1ZSBoYXMgYSBjb3JyZXNwb25kaW5nIGtleSBpbiB0aGUgYHZhbHVlc1RvU3RyaW5nc2Agb3B0aW9uIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ30gdmFsdWVcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgc3VjaCBhIGtleSBpcyBmb3VuZC5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9jaGVja1ZhbHVlc1RvU3RyaW5ncyh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3Rvci5fY2hlY2tWYWx1ZXNUb1N0cmluZ3NBcnJheSh2YWx1ZSwgdGhpcy52YWx1ZXNUb1N0cmluZ3NLZXlzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiB0aGUgZ2l2ZW4gdmFsdWUgaGFzIGEgY29ycmVzcG9uZGluZyBrZXkgaW4gdGhlIGBzdHJpbmdzQXJyYXlgIGFycmF5LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfSBrZXlcbiAgICAgKiBAcGFyYW0ge2FycmF5fSBzdHJpbmdzQXJyYXkgQXJyYXkgd2hlcmUgdGhlIGBrZXlgIGlzIGNoZWNrZWQgYWdhaW5zdCBpdHMga2V5c1xuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBzdWNoIGEga2V5IGlzIGZvdW5kLlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9jaGVja1ZhbHVlc1RvU3RyaW5nc0FycmF5KGtleSwgc3RyaW5nc0FycmF5KSB7XG4gICAgICAgIHJldHVybiBBdXRvTnVtZXJpY0hlbHBlci5pc0luQXJyYXkoU3RyaW5nKGtleSksIHN0cmluZ3NBcnJheSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3RhdGljIGhlbHBlciBmb3IgY2hlY2tpbmcgaWYgdGhlIGdpdmVuIGBrZXlgIGlzIGZvdW5kIGluIHRoZSBzZXR0aW5ncycgYHZhbHVlc1RvU3RyaW5nc2Agb3B0aW9uIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ30ga2V5XG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2NoZWNrVmFsdWVzVG9TdHJpbmdzU2V0dGluZ3Moa2V5LCBzZXR0aW5ncykge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2hlY2tWYWx1ZXNUb1N0cmluZ3NBcnJheShrZXksIE9iamVjdC5rZXlzKHNldHRpbmdzLnZhbHVlc1RvU3RyaW5ncykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN0YXRpYyBoZWxwZXIgZm9yIGNoZWNraW5nIGlmIHRoZSBnaXZlbiBgdmFsdWVgIGlzIGZvdW5kIGluIHRoZSBzZXR0aW5ncycgYHZhbHVlc1RvU3RyaW5nc2Agb3B0aW9uIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ30gdmFsdWVcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfY2hlY2tTdHJpbmdzVG9WYWx1ZXNTZXR0aW5ncyh2YWx1ZSwgc2V0dGluZ3MpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NoZWNrVmFsdWVzVG9TdHJpbmdzQXJyYXkodmFsdWUsIE9iamVjdC52YWx1ZXMoc2V0dGluZ3MudmFsdWVzVG9TdHJpbmdzKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgdXNlciBpcyBjdXJyZW50bHkgbW9kaWZ5aW5nIHRoZSBlbGVtZW50IHZhbHVlIG1hbnVhbGx5LlxuICAgICAqXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfaXNVc2VyTWFudWFsbHlFZGl0aW5nVGhlVmFsdWUoKSB7XG4gICAgICAgIC8vIHJldHVybiAodGhpcy5pc0ZvY3VzZWQgJiYgdGhpcy5pc0VkaXRpbmcpIHx8IHRoaXMuaXNXaGVlbEV2ZW50IHx8IHRoaXMuaXNEcm9wRXZlbnQ7XG4gICAgICAgIHJldHVybiAodGhpcy5pc0ZvY3VzZWQgJiYgdGhpcy5pc0VkaXRpbmcpIHx8IHRoaXMuaXNEcm9wRXZlbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXhlY3V0ZSB0aGUgZ2l2ZW4gY2FsbGJhY2sgZnVuY3Rpb24gdXNpbmcgdGhlIGdpdmVuIHJlc3VsdCBhcyBpdHMgZmlyc3QgcGFyYW1ldGVyLCBhbmQgdGhlIEF1dG9OdW1lcmljIG9iamVjdCBhcyBpdHMgc2Vjb25kLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfEFycmF5fG51bGx9IHJlc3VsdFxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb258bnVsbH0gY2FsbGJhY2sgSWYgYSBjYWxsYmFjayBpcyBwYXNzZWQsIHRoZW4gdGhlIHJlc3VsdCBpcyBwYXNzZWQgdG8gaXQgYXMgaXRzIGZpcnN0IGFyZ3VtZW50LCBhbmQgdGhlIEF1dG9OdW1lcmljIG9iamVjdCBoYXMgaXRzIHNlY29uZFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2V4ZWN1dGVDYWxsYmFjayhyZXN1bHQsIGNhbGxiYWNrKSB7XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGNhbGxiYWNrKSAmJiBBdXRvTnVtZXJpY0hlbHBlci5pc0Z1bmN0aW9uKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgY2FsbGJhY2socmVzdWx0LCB0aGlzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRyaWdnZXIgdGhlIGdpdmVuIGV2ZW50IG9uIHRoZSBnaXZlbiBlbGVtZW50IHdpdGggdGhlIGdpdmVuIGRldGFpbC5cbiAgICAgKiBUaGlzIHRha2VzIGludG8gYWNjb3VudCB0aGUgYGV2ZW50QnViYmxlc2AgYW5kIGBldmVudElzQ2FuY2VsYWJsZWAgb3B0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fEhUTUxEb2N1bWVudHxFdmVudFRhcmdldH0gZWxlbWVudFxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBkZXRhaWxcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF90cmlnZ2VyRXZlbnQoZXZlbnROYW1lLCBlbGVtZW50ID0gZG9jdW1lbnQsIGRldGFpbCA9IG51bGwpIHtcbiAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudHJpZ2dlckV2ZW50KGV2ZW50TmFtZSwgZWxlbWVudCwgZGV0YWlsLCB0aGlzLnNldHRpbmdzLmV2ZW50QnViYmxlcywgdGhpcy5zZXR0aW5ncy5ldmVudElzQ2FuY2VsYWJsZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgdGhlIGBnZXROdW1lcmljU3RyaW5nKClgIGZ1bmN0aW9uLlxuICAgICAqIERldmVsb3BlcnMgc2hvdWxkIHVzZSBvbmUgb2YgdGhlIG1vcmUgZXhwbGljaXQgZnVuY3Rpb24gbmFtZXMgdG8gZ2V0IHdoYXQgdGhleSB3YW50IDpcbiAgICAgKiAtIGEgbnVtZXJpYyBzdHJpbmcgOiBgZ2V0TnVtZXJpY1N0cmluZygpYFxuICAgICAqIC0gYSBmb3JtYXR0ZWQgc3RyaW5nIDogYGdldEZvcm1hdHRlZCgpYFxuICAgICAqIC0gYSBudW1iZXIgOiBgZ2V0TnVtYmVyKClgLCBvclxuICAgICAqIC0gYSBsb2NhbGl6ZWQgbnVtZXJpYyBzdHJpbmcgOiBgZ2V0TG9jYWxpemVkKClgXG4gICAgICpcbiAgICAgKiBAdXNhZ2UgYW5FbGVtZW50LmdldCgpO1xuICAgICAqXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbnxudWxsfSBjYWxsYmFjayBJZiBhIGNhbGxiYWNrIGlzIHBhc3NlZCwgdGhlbiB0aGUgcmVzdWx0IGlzIHBhc3NlZCB0byBpdCBhcyBpdHMgZmlyc3QgYXJndW1lbnQsIGFuZCB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGhhcyBpdHMgc2Vjb25kXG4gICAgICpcbiAgICAgKiBAZGVwcmVjYXRlZFxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH1cbiAgICAgKi9cbiAgICBnZXQoY2FsbGJhY2sgPSBudWxsKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldE51bWVyaWNTdHJpbmcoY2FsbGJhY2spO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgdW5mb3JtYXR0ZWQgdmFsdWUgYXMgYSBzdHJpbmcuXG4gICAgICogVGhpcyBjYW4gYWxzbyByZXR1cm4gYG51bGxgIGlmIGByYXdWYWx1ZWAgaXMgbnVsbC5cbiAgICAgKlxuICAgICAqIEB1c2FnZSBhbkVsZW1lbnQuZ2V0TnVtZXJpY1N0cmluZygpO1xuICAgICAqXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbnxudWxsfSBjYWxsYmFjayBJZiBhIGNhbGxiYWNrIGlzIHBhc3NlZCwgdGhlbiB0aGUgcmVzdWx0IGlzIHBhc3NlZCB0byBpdCBhcyBpdHMgZmlyc3QgYXJndW1lbnQsIGFuZCB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGhhcyBpdHMgc2Vjb25kXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9XG4gICAgICovXG4gICAgZ2V0TnVtZXJpY1N0cmluZyhjYWxsYmFjayA9IG51bGwpIHtcbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbCh0aGlzLnJhd1ZhbHVlKSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gbnVsbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEFsd2F5cyByZXR1cm4gYSBudW1lcmljIHN0cmluZ1xuICAgICAgICAgICAgLy8gVGhlIGZvbGxvd2luZyBzdGF0ZW1lbnQgZ2V0cyByaWQgb2YgdGhlIHRyYWlsaW5nIHplcm9zIGluIHRoZSBkZWNpbWFsIHBsYWNlcyBzaW5jZSB0aGUgY3VycmVudCBtZXRob2QgZG9lcyBub3QgcGFkIGRlY2ltYWxzXG4gICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpY0hlbHBlci50cmltUGFkZGVkWmVyb3NGcm9tRGVjaW1hbFBsYWNlcyh0aGlzLnJhd1ZhbHVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2V4ZWN1dGVDYWxsYmFjayhyZXN1bHQsIGNhbGxiYWNrKTtcblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgY3VycmVudCBmb3JtYXR0ZWQgdmFsdWUgb2YgdGhlIEF1dG9OdW1lcmljIGVsZW1lbnQgYXMgYSBzdHJpbmdcbiAgICAgKlxuICAgICAqIEB1c2FnZSBhbkVsZW1lbnQuZ2V0Rm9ybWF0dGVkKClcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb258bnVsbH0gY2FsbGJhY2sgSWYgYSBjYWxsYmFjayBpcyBwYXNzZWQsIHRoZW4gdGhlIHJlc3VsdCBpcyBwYXNzZWQgdG8gaXQgYXMgaXRzIGZpcnN0IGFyZ3VtZW50LCBhbmQgdGhlIEF1dG9OdW1lcmljIG9iamVjdCBoYXMgaXRzIHNlY29uZFxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBnZXRGb3JtYXR0ZWQoY2FsbGJhY2sgPSBudWxsKSB7XG4gICAgICAgIGlmICghKCd2YWx1ZScgaW4gdGhpcy5kb21FbGVtZW50IHx8ICd0ZXh0Q29udGVudCcgaW4gdGhpcy5kb21FbGVtZW50KSkge1xuICAgICAgICAgICAgLy8gTWFrZSBzdXJlIGAudmFsdWVgIG9yIGAudGV4dENvbnRlbnQnIGV4aXN0cyBiZWZvcmUgdHJ5aW5nIHRvIGFjY2VzcyB0aG9zZSBwcm9wZXJ0aWVzXG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKCdVbmFibGUgdG8gZ2V0IHRoZSBmb3JtYXR0ZWQgc3RyaW5nIGZyb20gdGhlIGVsZW1lbnQuJyk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXN1bHQgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgdGhpcy5fZXhlY3V0ZUNhbGxiYWNrKHJlc3VsdCwgY2FsbGJhY2spO1xuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBlbGVtZW50IHVuZm9ybWF0dGVkIHZhbHVlIGFzIGEgcmVhbCBKYXZhc2NyaXB0IG51bWJlci5cbiAgICAgKiBXYXJuaW5nOiBUaGlzIGNhbiBsZWFkIHRvIHByZWNpc2lvbiBwcm9ibGVtcyB3aXRoIGJpZyBudW1iZXJzIHRoYXQgc2hvdWxkIGJlIHN0b3JlZCBhcyBzdHJpbmdzLlxuICAgICAqXG4gICAgICogQHVzYWdlIGFuRWxlbWVudC5nZXROdW1iZXIoKVxuICAgICAqXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbnxudWxsfSBjYWxsYmFjayBJZiBhIGNhbGxiYWNrIGlzIHBhc3NlZCwgdGhlbiB0aGUgcmVzdWx0IGlzIHBhc3NlZCB0byBpdCBhcyBpdHMgZmlyc3QgYXJndW1lbnQsIGFuZCB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGhhcyBpdHMgc2Vjb25kXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfG51bGx9XG4gICAgICovXG4gICAgZ2V0TnVtYmVyKGNhbGxiYWNrID0gbnVsbCkge1xuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBpZiAodGhpcy5yYXdWYWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmVzdWx0ID0gbnVsbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuY29uc3RydWN0b3IuX3RvTG9jYWxlKHRoaXMuZ2V0TnVtZXJpY1N0cmluZygpLCAnbnVtYmVyJywgdGhpcy5zZXR0aW5ncyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9leGVjdXRlQ2FsbGJhY2socmVzdWx0LCBjYWxsYmFjayk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSB1bmZvcm1hdHRlZCB2YWx1ZSwgYnV0IGZvbGxvd2luZyB0aGUgYG91dHB1dEZvcm1hdGAgc2V0dGluZywgd2hpY2ggbWVhbnMgdGhlIG91dHB1dCBjYW4gZWl0aGVyIGJlIDpcbiAgICAgKiAtIGEgc3RyaW5nICh0aGF0IGNvdWxkIG9yIGNvdWxkIG5vdCByZXByZXNlbnQgYSBudW1iZXIgKGllLiBcIjEyMzQ1LDY3LVwiKSksIG9yXG4gICAgICogLSBhIHBsYWluIG51bWJlciAoaWYgdGhlIHNldHRpbmcgJ251bWJlcicgaXMgdXNlZCkuXG4gICAgICpcbiAgICAgKiBCeSBkZWZhdWx0IHRoZSByZXR1cm5lZCB2YWx1ZXMgYXJlIGFuIElTTyBudW1lcmljIHN0cmluZyBcIjEyMzQuNTZcIiBvciBcIi0xMjM0LjU2XCIgd2hlcmUgdGhlIGRlY2ltYWwgY2hhcmFjdGVyIGlzIGEgcGVyaW9kLlxuICAgICAqIENoZWNrIHRoZSBcIm91dHB1dEZvcm1hdFwiIG9wdGlvbiBkZWZpbml0aW9uIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICpcbiAgICAgKiBAdXNhZ2UgYW5FbGVtZW50LmdldExvY2FsaXplZCgpO1xuICAgICAqXG4gICAgICogQHBhcmFtIHtudWxsfHN0cmluZ3xmdW5jdGlvbn0gZm9yY2VkT3V0cHV0Rm9ybWF0IElmIHNldCB0byBzb21ldGhpbmcgZGlmZmVyZW50IHRoYW4gYG51bGxgLCB0aGVuIHRoaXMgaXMgdXNlZCBhcyBhbiBvdmVycmlkaW5nIG91dHB1dEZvcm1hdCBvcHRpb25cbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufG51bGx9IGNhbGxiYWNrIElmIGEgY2FsbGJhY2sgaXMgcGFzc2VkLCB0aGVuIHRoZSByZXN1bHQgaXMgcGFzc2VkIHRvIGl0IGFzIGl0cyBmaXJzdCBhcmd1bWVudCwgYW5kIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QgaGFzIGl0cyBzZWNvbmRcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIGdldExvY2FsaXplZChmb3JjZWRPdXRwdXRGb3JtYXQgPSBudWxsLCBjYWxsYmFjayA9IG51bGwpIHtcbiAgICAgICAgLy8gRmlyc3QsIGNoZWNrIGlmIG9ubHkgYSBjYWxsYmFjayBoYXMgYmVlbiBwYXNzZWQsIGFuZCBpZiBzbywgc2FuaXRpemUgdGhlIHBhcmFtZXRlcnNcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzRnVuY3Rpb24oZm9yY2VkT3V0cHV0Rm9ybWF0KSAmJiBBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoY2FsbGJhY2spKSB7XG4gICAgICAgICAgICBjYWxsYmFjayA9IGZvcmNlZE91dHB1dEZvcm1hdDtcbiAgICAgICAgICAgIGZvcmNlZE91dHB1dEZvcm1hdCA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUaGVuIGdldCB0aGUgbG9jYWxpemVkIHZhbHVlXG4gICAgICAgIGxldCB2YWx1ZTtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzRW1wdHlTdHJpbmcodGhpcy5yYXdWYWx1ZSkpIHtcbiAgICAgICAgICAgIHZhbHVlID0gJyc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBIZXJlIEkgdXNlIGB0aGlzLnJhd1ZhbHVlYCBpbnN0ZWFkIG9mIGB0aGlzLmdldE51bWVyaWNTdHJpbmcoKWAgc2luY2UgdGhlIGN1cnJlbnQgaW5wdXQgdmFsdWUgY291bGQgYmUgdW5mb3JtYXR0ZWQgd2l0aCBhIGxvY2FsaXphdGlvbiAoaWUuICcxMjM0NTY3LDg5LScpLlxuICAgICAgICAgICAgLy8gSSBhbHNvIGNvbnZlcnQgdGhlIHJhd1ZhbHVlIHRvIGEgbnVtYmVyLCB0aGVuIGJhY2sgdG8gYSBzdHJpbmcgaW4gb3JkZXIgdG8gZHJvcCB0aGUgZGVjaW1hbCBwYXJ0IGlmIHRoZSByYXdWYWx1ZSBpcyBhbiBpbnRlZ2VyLlxuICAgICAgICAgICAgdmFsdWUgPSAnJytOdW1iZXIodGhpcy5yYXdWYWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodmFsdWUgIT09ICcnICYmIE51bWJlcih2YWx1ZSkgPT09IDAgJiYgdGhpcy5zZXR0aW5ncy5sZWFkaW5nWmVybyAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5sZWFkaW5nWmVyby5rZWVwKSB7XG4gICAgICAgICAgICB2YWx1ZSA9ICcwJztcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBvdXRwdXRGb3JtYXRUb1VzZTtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChmb3JjZWRPdXRwdXRGb3JtYXQpKSB7XG4gICAgICAgICAgICBvdXRwdXRGb3JtYXRUb1VzZSA9IHRoaXMuc2V0dGluZ3Mub3V0cHV0Rm9ybWF0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb3V0cHV0Rm9ybWF0VG9Vc2UgPSBmb3JjZWRPdXRwdXRGb3JtYXQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXN1bHQgPSB0aGlzLmNvbnN0cnVjdG9yLl90b0xvY2FsZSh2YWx1ZSwgb3V0cHV0Rm9ybWF0VG9Vc2UsIHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICB0aGlzLl9leGVjdXRlQ2FsbGJhY2socmVzdWx0LCBjYWxsYmFjayk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb3JjZSB0aGUgZWxlbWVudCB0byByZWZvcm1hdCBpdHMgdmFsdWUgYWdhaW4gKGp1c3QgaW4gY2FzZSB0aGUgZm9ybWF0dGluZyBoYXMgYmVlbiBsb3N0KS5cbiAgICAgKiBUaGlzIGNhbiBiZSB1c2VkIHJpZ2h0IGFmdGVyIGEgZm9ybSBzdWJtaXNzaW9uIGZvciBpbnN0YW5jZSAoYWZ0ZXIgYSBwcmV2aW91cyBjYWxsIHRvIGB1bmZvcm1hdGApLlxuICAgICAqXG4gICAgICogQGV4YW1wbGUgYW5FbGVtZW50LnJlZm9ybWF0KClcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICByZWZvcm1hdCgpIHtcbiAgICAgICAgLy8gYHRoaXMucmF3VmFsdWVgIGlzIHVzZWQgaW5zdGVhZCBvZiBgdGhpcy5kb21FbGVtZW50LnZhbHVlYCBiZWNhdXNlIHdoZW4gdGhlIGNvbnRlbnQgaXMgYHVuZm9ybWF0TG9jYWxpemVkYCwgaXQgY2FuIGJlY29tZSBhIHN0cmluZyB0aGF0IGNhbm5vdCBiZSBjb252ZXJ0ZWQgdG8gYSBudW1iZXIgZWFzaWx5XG4gICAgICAgIHRoaXMuc2V0KHRoaXMucmF3VmFsdWUpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZSB0aGUgZm9ybWF0dGluZyBhbmQga2VlcCBvbmx5IHRoZSByYXcgdW5mb3JtYXR0ZWQgdmFsdWUgaW4gdGhlIGVsZW1lbnQgKGFzIGEgbnVtZXJpY1N0cmluZylcbiAgICAgKiBOb3RlOiB0aGlzIGlzIGxvb3NlbHkgYmFzZWQgb24gdGhlIHByZXZpb3VzICd1blNldCgpJyBmdW5jdGlvblxuICAgICAqXG4gICAgICogQnkgZGVmYXVsdCwgdmFsdWVzIGFyZSByZXR1cm5lZCBhcyBJU08gbnVtZXJpYyBzdHJpbmdzIChpZS4gXCIxMjM0LjU2XCIgb3IgXCItMTIzNC41NlwiKSwgd2hlcmUgdGhlIGRlY2ltYWwgY2hhcmFjdGVyIGlzIGEgcGVyaW9kLlxuICAgICAqIEBleGFtcGxlIGFuRWxlbWVudC51bmZvcm1hdCgpXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgdW5mb3JtYXQoKSB7XG4gICAgICAgIHRoaXMuX3NldEVsZW1lbnRWYWx1ZSh0aGlzLmdldE51bWVyaWNTdHJpbmcoKSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIHRoZSBmb3JtYXR0aW5nIGFuZCBrZWVwIG9ubHkgdGhlIGxvY2FsaXplZCB1bmZvcm1hdHRlZCB2YWx1ZSBpbiB0aGUgZWxlbWVudCwgd2l0aCB0aGUgb3B0aW9uIHRvIG92ZXJyaWRlIHRoZSBkZWZhdWx0IG91dHB1dEZvcm1hdCBpZiBuZWVkZWRcbiAgICAgKlxuICAgICAqIExvY2FsZSBmb3JtYXRzIGFyZSBzdXBwb3J0ZWQgXCIxMjM0LjU2LVwiIG9yIFwiMTIzNCw1NlwiIG9yIFwiLTEyMzQsNTYgb3IgXCIxMjM0LDU2LVwiLCBvciBldmVuIHBsYWluIG51bWJlcnMuXG4gICAgICogVGFrZSBhIGxvb2sgYXQgdGhlIGBvdXRwdXRGb3JtYXRgIG9wdGlvbiBkZWZpbml0aW9uIGluIHRoZSBkZWZhdWx0IHNldHRpbmdzIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bGx8c3RyaW5nfSBmb3JjZWRPdXRwdXRGb3JtYXQgSWYgc2V0IHRvIHNvbWV0aGluZyBkaWZmZXJlbnQgdGhhbiBgbnVsbGAsIHRoZW4gdGhpcyBpcyB1c2VkIGFzIGFuIG92ZXJyaWRpbmcgb3V0cHV0Rm9ybWF0IG9wdGlvblxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICB1bmZvcm1hdExvY2FsaXplZChmb3JjZWRPdXRwdXRGb3JtYXQgPSBudWxsKSB7XG4gICAgICAgIHRoaXMuX3NldEVsZW1lbnRWYWx1ZSh0aGlzLmdldExvY2FsaXplZChmb3JjZWRPdXRwdXRGb3JtYXQpKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBjdXJyZW50IHZhbHVlIGlzIHRoZSBzYW1lIGFzIHdoZW4gdGhlIGVsZW1lbnQgZ290IGluaXRpYWxpemVkLlxuICAgICAqIE5vdGU6IEJ5IGRlZmF1bHQsIHRoaXMgcmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHJhdyB1bmZvcm1hdHRlZCB2YWx1ZSBpcyBzdGlsbCB0aGUgc2FtZSBldmVuIGlmIHRoZSBmb3JtYXR0ZWQgb25lIGhhcyBjaGFuZ2VkIChkdWUgdG8gYSBjb25maWd1cmF0aW9uIHVwZGF0ZSBmb3IgaW5zdGFuY2UpLlxuICAgICAqIEluIG9yZGVyIHRvIHRlc3QgaWYgdGhlIGZvcm1hdHRlZCB2YWx1ZSBpcyB0aGUgc2FtZSAod2hpY2ggbWVhbnMgbmVpdGhlciB0aGUgcmF3IHZhbHVlIG5vciB0aGUgc2V0dGluZ3MgaGF2ZSBiZWVuIGNoYW5nZWQpLCB0aGVuIHlvdSBtdXN0IHBhc3MgYGZhbHNlYCBhcyBpdHMgYXJndW1lbnQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGNoZWNrT25seVJhd1ZhbHVlIElmIHNldCB0byBgdHJ1ZWAsIHRoZSBwcmlzdGluZSB2YWx1ZSBpcyBkb25lIG9uIHRoZSByYXcgdW5mb3JtYXR0ZWQgdmFsdWUsIG5vdCB0aGUgZm9ybWF0dGVkIG9uZS4gIElmIHNldCB0byBgZmFsc2VgLCB0aGlzIGFsc28gY2hlY2tzIHRoYXQgdGhlIGZvcm1hdHRlZCB2YWx1ZSBoYXNuJ3QgY2hhbmdlZC5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBpc1ByaXN0aW5lKGNoZWNrT25seVJhd1ZhbHVlID0gdHJ1ZSkge1xuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBpZiAoY2hlY2tPbmx5UmF3VmFsdWUpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuaW5pdGlhbFZhbHVlID09PSB0aGlzLmdldE51bWVyaWNTdHJpbmcoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuaW5pdGlhbFZhbHVlSHRtbEF0dHJpYnV0ZSA9PT0gdGhpcy5nZXRGb3JtYXR0ZWQoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VsZWN0IHRoZSBmb3JtYXR0ZWQgZWxlbWVudCBjb250ZW50LCBiYXNlZCBvbiB0aGUgYHNlbGVjdE51bWJlck9ubHlgIG9wdGlvblxuICAgICAqXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIHNlbGVjdCgpIHtcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3Muc2VsZWN0TnVtYmVyT25seSkge1xuICAgICAgICAgICAgdGhpcy5zZWxlY3ROdW1iZXIoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX2RlZmF1bHRTZWxlY3RBbGwoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbGVjdCB0aGUgd2hvbGUgZWxlbWVudCBjb250ZW50IChpbmNsdWRpbmcgdGhlIGN1cnJlbmN5IHN5bWJvbCkuXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZGVmYXVsdFNlbGVjdEFsbCgpIHtcbiAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFNlbGVjdGlvbih0aGlzLmRvbUVsZW1lbnQsIDAsIEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQpLmxlbmd0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VsZWN0IG9ubHkgdGhlIG51bWJlcnMgaW4gdGhlIGZvcm1hdHRlZCBlbGVtZW50IGNvbnRlbnQsIGxlYXZpbmcgb3V0IHRoZSBjdXJyZW5jeSBzeW1ib2wsIHdoYXRldmVyIHRoZSB2YWx1ZSBvZiB0aGUgYHNlbGVjdE51bWJlck9ubHlgIG9wdGlvblxuICAgICAqXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIHNlbGVjdE51bWJlcigpIHtcbiAgICAgICAgLy9UT0RPIE1ha2Ugc3VyZSB0aGUgc2VsZWN0aW9uIGlzIG9rIHdoZW4gc2hvd1Bvc2l0aXZlU2lnbiBpcyBzZXQgdG8gYHRydWVgIChzZWxlY3QgdGhlIG5lZ2F0aXZlIHNpZ24sIGJ1dCBub3QgdGhlIHBvc2l0aXZlIG9uZSlcbiAgICAgICAgY29uc3QgdW5mb3JtYXR0ZWRWYWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQpO1xuICAgICAgICBjb25zdCB2YWx1ZUxlbiA9IHVuZm9ybWF0dGVkVmFsdWUubGVuZ3RoO1xuICAgICAgICBjb25zdCBjdXJyZW5jeVN5bWJvbFNpemUgPSB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sLmxlbmd0aDtcbiAgICAgICAgY29uc3QgY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPSB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50O1xuICAgICAgICBjb25zdCBuZWdMZW4gPSAoIUF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmUodW5mb3JtYXR0ZWRWYWx1ZSwgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpKT8wOjE7XG4gICAgICAgIGNvbnN0IHN1ZmZpeFRleHRMZW4gPSB0aGlzLnNldHRpbmdzLnN1ZmZpeFRleHQubGVuZ3RoO1xuXG4gICAgICAgIGxldCBzdGFydDtcbiAgICAgICAgaWYgKGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeCkge1xuICAgICAgICAgICAgc3RhcnQgPSAwO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdCAmJlxuICAgICAgICAgICAgbmVnTGVuID09PSAxICYmIGN1cnJlbmN5U3ltYm9sU2l6ZSA+IDApIHtcbiAgICAgICAgICAgIHN0YXJ0ID0gY3VycmVuY3lTeW1ib2xTaXplICsgMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHN0YXJ0ID0gY3VycmVuY3lTeW1ib2xTaXplO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGVuZDtcbiAgICAgICAgaWYgKGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnByZWZpeCkge1xuICAgICAgICAgICAgZW5kID0gdmFsdWVMZW4gLSBzdWZmaXhUZXh0TGVuO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LmxlZnQ6XG4gICAgICAgICAgICAgICAgICAgIGVuZCA9IHZhbHVlTGVuIC0gKHN1ZmZpeFRleHRMZW4gKyBjdXJyZW5jeVN5bWJvbFNpemUpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQ6XG4gICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW5jeVN5bWJvbFNpemUgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSB2YWx1ZUxlbiAtIChjdXJyZW5jeVN5bWJvbFNpemUgKyBuZWdMZW4gKyBzdWZmaXhUZXh0TGVuKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVuZCA9IHZhbHVlTGVuIC0gKGN1cnJlbmN5U3ltYm9sU2l6ZSArIHN1ZmZpeFRleHRMZW4pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQgOlxuICAgICAgICAgICAgICAgICAgICBlbmQgPSB2YWx1ZUxlbiAtIChjdXJyZW5jeVN5bWJvbFNpemUgKyBzdWZmaXhUZXh0TGVuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRTZWxlY3Rpb24odGhpcy5kb21FbGVtZW50LCBzdGFydCwgZW5kKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWxlY3Qgb25seSB0aGUgaW50ZWdlciBwYXJ0IGluIHRoZSBmb3JtYXR0ZWQgZWxlbWVudCBjb250ZW50LCB3aGF0ZXZlciB0aGUgdmFsdWUgb2YgYHNlbGVjdE51bWJlck9ubHlgXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgc2VsZWN0SW50ZWdlcigpIHtcbiAgICAgICAgbGV0IHN0YXJ0ID0gMDtcbiAgICAgICAgY29uc3QgaXNQb3NpdGl2ZSA9IHRoaXMucmF3VmFsdWUgPj0gMDtcblxuICAgICAgICAvLyBOZWdhdGl2ZSBvciBwb3NpdGl2ZSBzaWduLCBpZiBhbnlcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQucHJlZml4IHx8XG4gICAgICAgICAgICAodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5zdWZmaXggJiZcbiAgICAgICAgICAgICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnByZWZpeCB8fFxuICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5ub25lKSkpIHtcbiAgICAgICAgICAgIGlmICgodGhpcy5zZXR0aW5ncy5zaG93UG9zaXRpdmVTaWduICYmIGlzUG9zaXRpdmUpIHx8ICAvLyBUaGlzIG9ubHkgZXhjbHVkZSB0aGUgcG9zaXRpdmUgc2lnbiBmcm9tIGJlaW5nIHNlbGVjdGVkXG4gICAgICAgICAgICAgICAgKCFpc1Bvc2l0aXZlICYmIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQucHJlZml4ICYmIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdCkpIHsgLy8gQW5kIHRoaXMgZXhjbHVkZSB0aGUgbmVnYXRpdmUgc2lnbiBmcm9tIGJlaW5nIHNlbGVjdGVkIGluIHRoaXMgc3BlY2lhbCBjYXNlIDogJy3igqwgMS4yMzQsNTdzdWZmaXhUZXh0J1xuICAgICAgICAgICAgICAgIHN0YXJ0ID0gc3RhcnQgKyAxO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ3VycmVuY3kgc3ltYm9sXG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnByZWZpeCkge1xuICAgICAgICAgICAgc3RhcnQgPSBzdGFydCArIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wubGVuZ3RoO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBzZWxlY3Rpb24gZW5kIHBvc2l0aW9uXG4gICAgICAgIGNvbnN0IGVsZW1lbnRWYWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQpO1xuICAgICAgICBsZXQgZW5kID0gZWxlbWVudFZhbHVlLmluZGV4T2YodGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKTtcbiAgICAgICAgaWYgKGVuZCA9PT0gLTEpIHtcbiAgICAgICAgICAgIC8vIE5vIGRlY2ltYWwgY2hhcmFjdGVyIGZvdW5kXG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5zdWZmaXgpIHtcbiAgICAgICAgICAgICAgICBlbmQgPSBlbGVtZW50VmFsdWUubGVuZ3RoIC0gdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbC5sZW5ndGg7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVuZCA9IGVsZW1lbnRWYWx1ZS5sZW5ndGg7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFRyYWlsaW5nIG5lZ2F0aXZlIHNpZ25cbiAgICAgICAgICAgIGlmICghaXNQb3NpdGl2ZSAmJlxuICAgICAgICAgICAgICAgICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnN1ZmZpeCB8fFxuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQuc3VmZml4KSkge1xuICAgICAgICAgICAgICAgIGVuZCA9IGVuZCAtIDE7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEF2b2lkIHNlbGVjdGluZyB0aGUgc3VmZml4IHRlc3RcbiAgICAgICAgICAgIGVuZCA9IGVuZCAtIHRoaXMuc2V0dGluZ3Muc3VmZml4VGV4dC5sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5zZXRFbGVtZW50U2VsZWN0aW9uKHRoaXMuZG9tRWxlbWVudCwgc3RhcnQsIGVuZCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VsZWN0IG9ubHkgdGhlIGRlY2ltYWwgcGFydCBpbiB0aGUgZm9ybWF0dGVkIGVsZW1lbnQgY29udGVudCwgd2hhdGV2ZXIgdGhlIHZhbHVlIG9mIGBzZWxlY3ROdW1iZXJPbmx5YFxuICAgICAqIE11bHRpcGxlIGNhc2VzIGFyZSBwb3NzaWJsZSA6XG4gICAgICogKzEuMjM0LDU3c3VmZml4VGV4dFxuICAgICAqXG4gICAgICog4oKsICsxLjIzNCw1N3N1ZmZpeFRleHRcbiAgICAgKiAr4oKsIDEuMjM0LDU3c3VmZml4VGV4dFxuICAgICAqIOKCrCAxLjIzNCw1NytzdWZmaXhUZXh0XG4gICAgICpcbiAgICAgKiAxLjIzNCw1Nysg4oKsc3VmZml4VGV4dFxuICAgICAqIDEuMjM0LDU3IOKCrCtzdWZmaXhUZXh0XG4gICAgICogKzEuMjM0LDU3IOKCrHN1ZmZpeFRleHRcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBzZWxlY3REZWNpbWFsKCkge1xuICAgICAgICBsZXQgc3RhcnQgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50KS5pbmRleE9mKHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlcik7XG4gICAgICAgIGxldCBlbmQ7XG5cbiAgICAgICAgaWYgKHN0YXJ0ID09PSAtMSkge1xuICAgICAgICAgICAgLy8gVGhlIGRlY2ltYWwgY2hhcmFjdGVyIGhhcyBub3QgYmVlbiBmb3VuZCwgd2UgZGVzZWxlY3QgYWxsXG4gICAgICAgICAgICBzdGFydCA9IDA7XG4gICAgICAgICAgICBlbmQgPSAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gQSBkZWNpbWFsIGNoYXJhY3RlciBoYXMgYmVlbiBmb3VuZFxuICAgICAgICAgICAgc3RhcnQgPSBzdGFydCArIDE7IC8vIFdlIGFkZCAxIHRvIGV4Y2x1ZGUgdGhlIGRlY2ltYWwgY2hhcmFjdGVyIGZyb20gdGhlIHNlbGVjdGlvblxuXG4gICAgICAgICAgICBsZXQgZGVjaW1hbENvdW50O1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNGb2N1c2VkKSB7XG4gICAgICAgICAgICAgICAgZGVjaW1hbENvdW50ID0gdGhpcy5zZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkZWNpbWFsQ291bnQgPSB0aGlzLnNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1cjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZW5kID0gc3RhcnQgKyBOdW1iZXIoZGVjaW1hbENvdW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRTZWxlY3Rpb24odGhpcy5kb21FbGVtZW50LCBzdGFydCwgZW5kKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIERPTSBlbGVtZW50IHJlZmVyZW5jZSBvZiB0aGUgYXV0b051bWVyaWMtbWFuYWdlZCBlbGVtZW50XG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7SFRNTEVsZW1lbnR8SFRNTElucHV0RWxlbWVudH1cbiAgICAgKi9cbiAgICBub2RlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kb21FbGVtZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgRE9NIGVsZW1lbnQgcmVmZXJlbmNlIG9mIHRoZSBwYXJlbnQgbm9kZSBvZiB0aGUgYXV0b051bWVyaWMtbWFuYWdlZCBlbGVtZW50XG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7SFRNTEVsZW1lbnR8SFRNTElucHV0RWxlbWVudHxOb2RlfVxuICAgICAqL1xuICAgIHBhcmVudCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZG9tRWxlbWVudC5wYXJlbnROb2RlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERldGFjaCB0aGUgY3VycmVudCBBdXRvTnVtZXJpYyBlbGVtZW50IGZyb20gdGhlIHNoYXJlZCBsb2NhbCAnaW5pdCcgbGlzdC5cbiAgICAgKiBUaGlzIG1lYW5zIGFueSBjaGFuZ2VzIG1hZGUgb24gdGhhdCBsb2NhbCBzaGFyZWQgbGlzdCB3aWxsIG5vdCBiZSB0cmFuc21pdHRlZCB0byB0aGF0IGVsZW1lbnQgYW55bW9yZS5cbiAgICAgKiBOb3RlIDogVGhlIHVzZXIgY2FuIHByb3ZpZGUgYW5vdGhlciBBdXRvTnVtZXJpYyBlbGVtZW50LCBhbmQgZGV0YWNoIHRoaXMgb25lIGluc3RlYWQgb2YgdGhlIGN1cnJlbnQgb25lLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtBdXRvTnVtZXJpY30gb3RoZXJBbkVsZW1lbnRcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgZGV0YWNoKG90aGVyQW5FbGVtZW50ID0gbnVsbCkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICBsZXQgZG9tRWxlbWVudFRvRGV0YWNoO1xuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvdGhlckFuRWxlbWVudCkpIHtcbiAgICAgICAgICAgIGRvbUVsZW1lbnRUb0RldGFjaCA9IG90aGVyQW5FbGVtZW50Lm5vZGUoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRvbUVsZW1lbnRUb0RldGFjaCA9IHRoaXMuZG9tRWxlbWVudDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX3JlbW92ZUZyb21Mb2NhbExpc3QoZG9tRWxlbWVudFRvRGV0YWNoKTsgLy9GSVhNRSBXaGF0IGhhcHBlbnMgaWYgdGhlIHNlbGVjdGVkIGRvbSBlbGVtZW50IGRvZXMgbm90IGV4aXN0IGluIHRoZSBsaXN0P1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEF0dGFjaCB0aGUgZ2l2ZW4gQXV0b051bWVyaWMgZWxlbWVudCB0byB0aGUgc2hhcmVkIGxvY2FsICdpbml0JyBsaXN0LlxuICAgICAqIFdoZW4gZG9pbmcgdGhhdCwgYnkgZGVmYXVsdCB0aGUgRE9NIGNvbnRlbnQgaXMgbGVmdCB1bnRvdWNoZWQuXG4gICAgICogVGhlIHVzZXIgY2FuIGZvcmNlIGEgcmVmb3JtYXQgd2l0aCB0aGUgbmV3IHNoYXJlZCBsaXN0IG9wdGlvbnMgYnkgcGFzc2luZyBhIHNlY29uZCBhcmd1bWVudCB0byBgdHJ1ZWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0F1dG9OdW1lcmljfSBvdGhlckFuRWxlbWVudFxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gcmVGb3JtYXRcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgYXR0YWNoKG90aGVyQW5FbGVtZW50LCByZUZvcm1hdCA9IHRydWUpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgdGhpcy5fYWRkVG9Mb2NhbExpc3Qob3RoZXJBbkVsZW1lbnQubm9kZSgpKTsgLy9GSVhNRSBTaG91bGQgd2UgbWFrZSBzdXJlIHRoZSBlbGVtZW50IGlzIG5vdCBhbHJlYWR5IGluIHRoZSBsaXN0P1xuICAgICAgICBpZiAocmVGb3JtYXQpIHtcbiAgICAgICAgICAgIG90aGVyQW5FbGVtZW50LnVwZGF0ZSh0aGlzLnNldHRpbmdzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZvcm1hdCBhbmQgcmV0dXJuIHRoZSBnaXZlbiB2YWx1ZSwgb3Igc2V0IHRoZSBmb3JtYXR0ZWQgdmFsdWUgaW50byB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQgaWYgb25lIGlzIHBhc3NlZCBhcyBhbiBhcmd1bWVudC5cbiAgICAgKiBCeSBkZWZhdWx0LCB0aGlzIHVzZSB0aGUgY3VycmVudCBlbGVtZW50IHNldHRpbmdzLlxuICAgICAqIFRoZSB1c2VyIGNhbiBvdmVycmlkZSBhbnkgb3B0aW9uIG9mIGl0cyBjaG9vc2luZyBieSBwYXNzaW5nIGFuIG9wdGlvbiBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcnxIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fSB2YWx1ZU9yRWxlbWVudFxuICAgICAqIEBwYXJhbSB7bnVsbHxvYmplY3R9IG9wdGlvbk92ZXJyaWRlXG4gICAgICogQHJldHVybnMge3N0cmluZ3xudWxsfVxuICAgICAqL1xuICAgIGZvcm1hdE90aGVyKHZhbHVlT3JFbGVtZW50LCBvcHRpb25PdmVycmlkZSA9IG51bGwpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Zvcm1hdE9yVW5mb3JtYXRPdGhlcih0cnVlLCB2YWx1ZU9yRWxlbWVudCwgb3B0aW9uT3ZlcnJpZGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVuZm9ybWF0IGFuZCByZXR1cm4gdGhlIHJhdyBudW1lcmljIHN0cmluZyBjb3JyZXNwb25kaW5nIHRvIHRoZSBnaXZlbiB2YWx1ZSwgb3IgZGlyZWN0bHkgc2V0IHRoZSB1bmZvcm1hdHRlZCB2YWx1ZSBpbnRvIHRoZSBnaXZlbiBET00gZWxlbWVudCBpZiBvbmUgaXMgcGFzc2VkIGFzIGFuIGFyZ3VtZW50LlxuICAgICAqIEJ5IGRlZmF1bHQsIHRoaXMgdXNlIHRoZSBjdXJyZW50IGVsZW1lbnQgc2V0dGluZ3MuXG4gICAgICogVGhlIHVzZXIgY2FuIG92ZXJyaWRlIGFueSBvcHRpb24gb2YgaXRzIGNob29zaW5nIGJ5IHBhc3NpbmcgYW4gb3B0aW9uIG9iamVjdC5cblxuICAgICAqIEBwYXJhbSB7c3RyaW5nfEhUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR9IHN0cmluZ09yRWxlbWVudFxuICAgICAqIEBwYXJhbSB7bnVsbHxvYmplY3R9IG9wdGlvbk92ZXJyaWRlXG4gICAgICogQHJldHVybnMge3N0cmluZ3xudWxsfVxuICAgICAqL1xuICAgIHVuZm9ybWF0T3RoZXIoc3RyaW5nT3JFbGVtZW50LCBvcHRpb25PdmVycmlkZSA9IG51bGwpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Zvcm1hdE9yVW5mb3JtYXRPdGhlcihmYWxzZSwgc3RyaW5nT3JFbGVtZW50LCBvcHRpb25PdmVycmlkZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIHRoYXQgZWl0aGVyIGZvcm1hdCBvciB1bmZvcm1hdCB0aGUgdmFsdWUgb2YgYW5vdGhlciBlbGVtZW50LlxuICAgICAqXG4gICAgICogLSBGb3JtYXQgYW5kIHJldHVybiB0aGUgZ2l2ZW4gdmFsdWUsIG9yIHNldCB0aGUgZm9ybWF0dGVkIHZhbHVlIGludG8gdGhlIGdpdmVuIERPTSBlbGVtZW50IGlmIG9uZSBpcyBwYXNzZWQgYXMgYW4gYXJndW1lbnQuXG4gICAgICogLSBVbmZvcm1hdCBhbmQgcmV0dXJuIHRoZSByYXcgbnVtZXJpYyBzdHJpbmcgY29ycmVzcG9uZGluZyB0byB0aGUgZ2l2ZW4gdmFsdWUsIG9yIGRpcmVjdGx5IHNldCB0aGUgdW5mb3JtYXR0ZWQgdmFsdWUgaW50byB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQgaWYgb25lIGlzIHBhc3NlZCBhcyBhbiBhcmd1bWVudC5cbiAgICAgKlxuICAgICAqIEJ5IGRlZmF1bHQsIHRoaXMgdXNlIHRoZSBjdXJyZW50IGVsZW1lbnQgc2V0dGluZ3MuXG4gICAgICogVGhlIHVzZXIgY2FuIG92ZXJyaWRlIGFueSBvcHRpb24gb2YgaXRzIGNob29zaW5nIGJ5IHBhc3NpbmcgYW4gb3B0aW9uIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNGb3JtYXR0aW5nIElmIHNldCB0byBgdHJ1ZWAsIHRoZW4gdGhlIG1ldGhvZCBmb3JtYXRzLCBvdGhlcndpc2UgaWYgc2V0IHRvIGBmYWxzZWAsIGl0IHVuZm9ybWF0c1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ3xIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fSB2YWx1ZU9yU3RyaW5nT3JFbGVtZW50XG4gICAgICogQHBhcmFtIHtudWxsfG9iamVjdH0gb3B0aW9uT3ZlcnJpZGVcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZm9ybWF0T3JVbmZvcm1hdE90aGVyKGlzRm9ybWF0dGluZywgdmFsdWVPclN0cmluZ09yRWxlbWVudCwgb3B0aW9uT3ZlcnJpZGUgPSBudWxsKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIC8vIElmIHRoZSB1c2VyIHdhbnRzIHRvIG92ZXJyaWRlIHRoZSBjdXJyZW50IGVsZW1lbnQgc2V0dGluZ3MgdGVtcG9yYXJpbHlcbiAgICAgICAgbGV0IHNldHRpbmdzVG9Vc2U7XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbk92ZXJyaWRlKSkge1xuICAgICAgICAgICAgc2V0dGluZ3NUb1VzZSA9IHRoaXMuX2Nsb25lQW5kTWVyZ2VTZXR0aW5ncyhvcHRpb25PdmVycmlkZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzZXR0aW5nc1RvVXNlID0gdGhpcy5zZXR0aW5ncztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRoZW4gdGhlIHVuZm9ybWF0dGluZyBpcyBkb25lLi4uXG4gICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0VsZW1lbnQodmFsdWVPclN0cmluZ09yRWxlbWVudCkpIHtcbiAgICAgICAgICAgIC8vIC4uLmVpdGhlciBkaXJlY3RseSBvbiB0aGUgRE9NIGVsZW1lbnQgdmFsdWVcbiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnRWYWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh2YWx1ZU9yU3RyaW5nT3JFbGVtZW50KTtcbiAgICAgICAgICAgIGlmIChpc0Zvcm1hdHRpbmcpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpYy5mb3JtYXQoZWxlbWVudFZhbHVlLCBzZXR0aW5nc1RvVXNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljLnVuZm9ybWF0KGVsZW1lbnRWYWx1ZSwgc2V0dGluZ3NUb1VzZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRWYWx1ZSh2YWx1ZU9yU3RyaW5nT3JFbGVtZW50LCByZXN1bHQpOyAvL1RPRE8gVXNlIGB1bmZvcm1hdEFuZFNldGAgYW5kIGBmb3JtYXRBbmRTZXRgaW5zdGVhZFxuXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIC4uLm9yIG9uIHRoZSBnaXZlbiB2YWx1ZVxuICAgICAgICBpZiAoaXNGb3JtYXR0aW5nKSB7XG4gICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpYy5mb3JtYXQodmFsdWVPclN0cmluZ09yRWxlbWVudCwgc2V0dGluZ3NUb1VzZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpYy51bmZvcm1hdCh2YWx1ZU9yU3RyaW5nT3JFbGVtZW50LCBzZXR0aW5nc1RvVXNlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXNlIHRoZSBjdXJyZW50IEF1dG9OdW1lcmljIGVsZW1lbnQgc2V0dGluZ3MgdG8gaW5pdGlhbGl6ZSB0aGUgRE9NIGVsZW1lbnQocykgZ2l2ZW4gYXMgYSBwYXJhbWV0ZXIuXG4gICAgICogRG9pbmcgc28gd2lsbCAqbGluayogdGhlIEF1dG9OdW1lcmljIGVsZW1lbnRzIHRvZ2V0aGVyIHNpbmNlIHRoZXkgd2lsbCBzaGFyZSB0aGUgc2FtZSBsb2NhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3QuXG4gICAgICogKGNmLiBwcm90b3R5cGUgcGF0dGVybiA6IGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1Byb3RvdHlwZV9wYXR0ZXJuKVxuICAgICAqXG4gICAgICogWW91IGNhbiBgaW5pdGAgZWl0aGVyIGEgc2luZ2xlIERPTSBlbGVtZW50IChpbiB0aGF0IGNhc2UgYW4gQXV0b051bWVyaWMgb2JqZWN0IHdpbGwgYmUgcmV0dXJuZWQpLCBvciBhbiBhcnJheSBvZiBET00gZWxlbWVudHMgb3IgYSBzdHJpbmcgdGhhdCB3aWxsIGJlIHVzZWQgYXMgYSBDU1Mgc2VsZWN0b3IuIEluIHRoZSBsYXR0ZXIgY2FzZXMsIGFuIGFycmF5IG9mIEF1dG9OdW1lcmljIG9iamVjdHMgd2lsbCB0aGVuIGJlIHJldHVybmVkIChvciBhbiBlbXB0eSBhcnJheSBpZiBub3RoaW5nIGdldHMgc2VsZWN0ZWQgYnkgdGhlIENTUyBzZWxlY3RvcikuXG4gICAgICpcbiAgICAgKiBVc2UgY2FzZSA6IE9uY2UgeW91IGhhdmUgYW4gQXV0b051bWVyaWMgZWxlbWVudCBhbHJlYWR5IHNldHVwIGNvcnJlY3RseSB3aXRoIHRoZSByaWdodCBvcHRpb25zLCB5b3UgY2FuIHVzZSBpdCBhcyBtYW55IHRpbWVzIHlvdSB3YW50IHRvIGluaXRpYWxpemUgYXMgbWFueSBvdGhlciBET00gZWxlbWVudHMgYXMgbmVlZGVkLlxuICAgICAqIE5vdGUgOiB0aGlzIHdvcmtzIG9ubHkgb24gZWxlbWVudHMgdGhhdCBjYW4gYmUgbWFuYWdlZCBieSBhdXRvTnVtZXJpYy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8SFRNTElucHV0RWxlbWVudHxBcnJheTxIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50PnxzdHJpbmd9IGRvbUVsZW1lbnRPckFycmF5T3JTdHJpbmdcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGF0dGFjaGVkIElmIHNldCB0byBgZmFsc2VgLCB0aGVuIHRoZSBuZXdseSBnZW5lcmF0ZWQgQXV0b051bWVyaWMgZWxlbWVudCB3aWxsIG5vdCBzaGFyZSB0aGUgc2FtZSBsb2NhbCBlbGVtZW50IGxpc3RcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN8W0F1dG9OdW1lcmljXX1cbiAgICAgKi9cbiAgICBpbml0KGRvbUVsZW1lbnRPckFycmF5T3JTdHJpbmcsIGF0dGFjaGVkID0gdHJ1ZSkge1xuICAgICAgICBsZXQgcmV0dXJuQVNpbmdsZUF1dG9OdW1lcmljT2JqZWN0ID0gZmFsc2U7IC8vIEJ5IGRlZmF1bHQsIHRoaXMgZnVuY3Rpb24gcmV0dXJucyBhbiBhcnJheSBvZiBBdXRvTnVtZXJpYyBvYmplY3RzXG4gICAgICAgIGxldCBkb21FbGVtZW50c0FycmF5ID0gW107XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc1N0cmluZyhkb21FbGVtZW50T3JBcnJheU9yU3RyaW5nKSkge1xuICAgICAgICAgICAgZG9tRWxlbWVudHNBcnJheSA9IFsuLi4gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChkb21FbGVtZW50T3JBcnJheU9yU3RyaW5nKV07IC8vIENvbnZlcnQgYSBOb2RlTGlzdCB0byBhbiBBcnJheVxuICAgICAgICB9IGVsc2UgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzRWxlbWVudChkb21FbGVtZW50T3JBcnJheU9yU3RyaW5nKSkge1xuICAgICAgICAgICAgZG9tRWxlbWVudHNBcnJheS5wdXNoKGRvbUVsZW1lbnRPckFycmF5T3JTdHJpbmcpO1xuICAgICAgICAgICAgcmV0dXJuQVNpbmdsZUF1dG9OdW1lcmljT2JqZWN0ID0gdHJ1ZTsgLy8gU3BlY2lhbCBjYXNlIHdoZW4gb25seSBvbmUgRE9NIGVsZW1lbnQgaXMgcGFzc2VkIGFzIGEgcGFyYW1ldGVyXG4gICAgICAgIH0gZWxzZSBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNBcnJheShkb21FbGVtZW50T3JBcnJheU9yU3RyaW5nKSkge1xuICAgICAgICAgICAgZG9tRWxlbWVudHNBcnJheSA9IGRvbUVsZW1lbnRPckFycmF5T3JTdHJpbmc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZ2l2ZW4gcGFyYW1ldGVycyB0byB0aGUgJ2luaXQnIGZ1bmN0aW9uIGFyZSBpbnZhbGlkLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRvbUVsZW1lbnRzQXJyYXkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKGBObyB2YWxpZCBET00gZWxlbWVudHMgd2VyZSBnaXZlbiBoZW5jZSBubyBBdXRvTnVtZXJpYyBvYmplY3Qgd2VyZSBpbnN0YW50aWF0ZWQuYCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGN1cnJlbnRMb2NhbExpc3QgPSB0aGlzLl9nZXRMb2NhbExpc3QoKTtcbiAgICAgICAgY29uc3QgYXV0b051bWVyaWNPYmplY3RzQXJyYXkgPSBbXTtcblxuICAgICAgICAvLyBJbnN0YW50aWF0ZSAoYW5kIGxpbmsgZGVwZW5kaW5nIG9uIGBhdHRhY2hlZGApIGVhY2ggQXV0b051bWVyaWMgb2JqZWN0c1xuICAgICAgICBkb21FbGVtZW50c0FycmF5LmZvckVhY2goZG9tRWxlbWVudCA9PiB7XG4gICAgICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBuZXcgQXV0b051bWVyaWMgZWxlbWVudFxuICAgICAgICAgICAgY29uc3Qgb3JpZ2luYWxDcmVhdGVMb2NhbExpc3RTZXR0aW5nID0gdGhpcy5zZXR0aW5ncy5jcmVhdGVMb2NhbExpc3Q7XG4gICAgICAgICAgICBpZiAoYXR0YWNoZWQpIHtcbiAgICAgICAgICAgICAgICAvLyBUZW1wb3JhcnkgdmFyaWFibGUgdG8ga25vdyBpZiB3ZSBzaG91bGQgY3JlYXRlIHRoZSBsb2NhbCBsaXN0IGR1cmluZyB0aGUgaW5pdGlhbGl6YXRpb24gKHNpbmNlIHdlJ2xsIHJlbW92ZSBpdCBhZnRlcndhcmRzKVxuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuY3JlYXRlTG9jYWxMaXN0ID0gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IG5ld0F1dG9OdW1lcmljRWxlbWVudCA9ICBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKGRvbUVsZW1lbnQpLCB0aGlzLnNldHRpbmdzKTtcblxuICAgICAgICAgICAgLy8gU2V0IHRoZSBjb21tb24gc2hhcmVkIGxvY2FsIGxpc3QgaWYgbmVlZGVkXG4gICAgICAgICAgICAvLyBJZiB0aGUgdXNlciB3YW50cyB0byBjcmVhdGUgYSBkZXRhY2hlZCBuZXcgQXV0b051bWVyaWMgZWxlbWVudCwgdGhlbiBza2lwIHRoZSBmb2xsb3dpbmcgc3RlcCB0aGF0IGJpbmQgdGhlIHR3byBlbGVtZW50cyB0b2dldGhlciBieSBkZWZhdWx0XG4gICAgICAgICAgICBpZiAoYXR0YWNoZWQpIHtcbiAgICAgICAgICAgICAgICAvLyAxKSBTZXQgdGhlIGxvY2FsIGxpc3QgcmVmZXJlbmNlIHRvIHBvaW50IHRvIHRoZSBpbml0aWFsaXplcidzIG9uZVxuICAgICAgICAgICAgICAgIG5ld0F1dG9OdW1lcmljRWxlbWVudC5fc2V0TG9jYWxMaXN0KGN1cnJlbnRMb2NhbExpc3QpO1xuXG4gICAgICAgICAgICAgICAgLy8gMikgQWRkIHRoZSBuZXcgZWxlbWVudCB0byB0aGF0IGV4aXN0aW5nIGxpc3RcbiAgICAgICAgICAgICAgICB0aGlzLl9hZGRUb0xvY2FsTGlzdChkb21FbGVtZW50LCBuZXdBdXRvTnVtZXJpY0VsZW1lbnQpOyAvLyBIZXJlIHdlIHVzZSB0aGUgKm5ldyogQXV0b051bWVyaWMgb2JqZWN0IHJlZmVyZW5jZSB0byBhZGQgdG8gdGhlIGxvY2FsIGxpc3QsIHNpbmNlIHdlJ2xsIG5lZWQgdGhlIHJlZmVyZW5jZSB0byBgdGhpc2AgaW4gdGhlIG1ldGhvZHMgdG8gcG9pbnRzIHRvIHRoYXQgbmV3IEF1dG9OdW1lcmljIG9iamVjdC5cbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmNyZWF0ZUxvY2FsTGlzdCA9IG9yaWdpbmFsQ3JlYXRlTG9jYWxMaXN0U2V0dGluZztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYXV0b051bWVyaWNPYmplY3RzQXJyYXkucHVzaChuZXdBdXRvTnVtZXJpY0VsZW1lbnQpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAocmV0dXJuQVNpbmdsZUF1dG9OdW1lcmljT2JqZWN0KSB7XG4gICAgICAgICAgICAvLyBJZiBhIHNpbmdsZSBET00gZWxlbWVudCB3YXMgdXNlZCBhcyB0aGUgcGFyYW1ldGVyLCB0aGVuIHdlIHJldHVybiBhbiBBdXRvTnVtZXJpYyBvYmplY3QgZGlyZWN0bHlcbiAgICAgICAgICAgIHJldHVybiBhdXRvTnVtZXJpY09iamVjdHNBcnJheVswXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIC4uLm90aGVyd2lzZSB3ZSByZXR1cm4gYW4gQXJyYXkgb2YgQXV0b051bWVyaWMgb2JqZWN0c1xuICAgICAgICByZXR1cm4gYXV0b051bWVyaWNPYmplY3RzQXJyYXk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVzZXQgdGhlIGVsZW1lbnQgdmFsdWUgZWl0aGVyIHRvIHRoZSBlbXB0eSBzdHJpbmcgJycsIG9yIHRoZSBjdXJyZW5jeSBzaWduLCBkZXBlbmRpbmcgb24gdGhlIGBlbXB0eUlucHV0QmVoYXZpb3JgIG9wdGlvbiB2YWx1ZS5cbiAgICAgKiBJZiB5b3Ugc2V0IHRoZSBgZm9yY2VDbGVhckFsbGAgYXJndW1lbnQgdG8gYHRydWVgLCB0aGVuIHRoZSBgZW1wdHlJbnB1dEJlaGF2aW9yYCBvcHRpb24gaXMgb3ZlcnJpZGRlbiBhbmQgdGhlIHdob2xlIGlucHV0IGlzIGNsZWFyLCBpbmNsdWRpbmcgYW55IGN1cnJlbmN5IHNpZ24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGZvcmNlQ2xlYXJBbGxcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgY2xlYXIoZm9yY2VDbGVhckFsbCA9IGZhbHNlKSB7XG4gICAgICAgIGlmIChmb3JjZUNsZWFyQWxsKSB7XG4gICAgICAgICAgICBjb25zdCB0ZW1wb3JhcnlGb3JjZWRPcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIGVtcHR5SW5wdXRCZWhhdmlvcjogQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IuZm9jdXMsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy5zZXQoJycsIHRlbXBvcmFyeUZvcmNlZE9wdGlvbnMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zZXQoJycpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIHRoZSBhdXRvTnVtZXJpYyBkYXRhIGFuZCBldmVudCBsaXN0ZW5lcnMgZnJvbSB0aGUgZWxlbWVudCwgYnV0IGtlZXAgdGhlIGVsZW1lbnQgY29udGVudCBpbnRhY3QuXG4gICAgICogVGhpcyBhbHNvIGNsZWFycyB0aGUgdmFsdWUgZnJvbSBzZXNzaW9uU3RvcmFnZSAob3IgY29va2llLCBkZXBlbmRpbmcgb24gYnJvd3NlciBzdXBwb3J0cykuXG4gICAgICogTm90ZTogdGhpcyBkb2VzIG5vdCByZW1vdmUgdGhlIGZvcm1hdHRpbmcuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZSBhbkVsZW1lbnQucmVtb3ZlKClcbiAgICAgKi9cbiAgICByZW1vdmUoKSB7XG4gICAgICAgIHRoaXMuX3JlbW92ZVZhbHVlRnJvbVBlcnNpc3RlbnRTdG9yYWdlKCk7XG4gICAgICAgIHRoaXMuX3JlbW92ZUV2ZW50TGlzdGVuZXJzKCk7XG4gICAgICAgIHRoaXMuX3JlbW92ZVdhdGNoZXIoKTtcblxuICAgICAgICAvLyBBbHNvIHJlbW92ZSB0aGUgZWxlbWVudCBmcm9tIHRoZSBsb2NhbCBBdXRvTnVtZXJpYyBsaXN0XG4gICAgICAgIHRoaXMuX3JlbW92ZUZyb21Mb2NhbExpc3QodGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgLy8gQWxzbyByZW1vdmUgdGhlIGVsZW1lbnQgZnJvbSB0aGUgZ2xvYmFsIEF1dG9OdW1lcmljIGxpc3RcbiAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5fcmVtb3ZlRnJvbUdsb2JhbExpc3QodGhpcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIHRoZSBhdXRvTnVtZXJpYyBkYXRhIGFuZCBldmVudCBsaXN0ZW5lcnMgZnJvbSB0aGUgZWxlbWVudCwgYW5kIHJlc2V0IGl0cyB2YWx1ZSB0byB0aGUgZW1wdHkgc3RyaW5nICcnLlxuICAgICAqIFRoaXMgYWxzbyBjbGVhcnMgdGhlIHZhbHVlIGZyb20gc2Vzc2lvblN0b3JhZ2UgKG9yIGNvb2tpZSwgZGVwZW5kaW5nIG9uIGJyb3dzZXIgc3VwcG9ydHMpLlxuICAgICAqXG4gICAgICogQGV4YW1wbGUgYW5FbGVtZW50LndpcGUoKVxuICAgICAqL1xuICAgIHdpcGUoKSB7XG4gICAgICAgIHRoaXMuX3NldEVsZW1lbnRWYWx1ZSgnJywgZmFsc2UpOyAvLyBEbyBub3Qgc2VuZCB0aGUgJ0F1dG9OdW1lcmljLmV2ZW50cy5mb3JtYXR0ZWQnIGV2ZW50IHdoZW4gd2lwaW5nIGFuIEF1dG9OdW1lcmljIG9iamVjdFxuICAgICAgICB0aGlzLnJlbW92ZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZSB0aGUgYXV0b051bWVyaWMgZGF0YSBhbmQgZXZlbnQgbGlzdGVuZXJzIGZyb20gdGhlIGVsZW1lbnQsIGFuZCBkZWxldGUgdGhlIERPTSBlbGVtZW50IGFsdG9nZXRoZXJcbiAgICAgKi9cbiAgICBudWtlKCkge1xuICAgICAgICB0aGlzLnJlbW92ZSgpO1xuICAgICAgICAvLyBSZW1vdmUgdGhlIGVsZW1lbnQgZnJvbSB0aGUgRE9NXG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMuZG9tRWxlbWVudCk7XG4gICAgfVxuXG5cbiAgICAvLyBTcGVjaWFsIGZ1bmN0aW9ucyB0aGF0IHJlYWxseSB3b3JrIG9uIHRoZSBwYXJlbnQgPGZvcm0+IGVsZW1lbnQsIGluc3RlYWQgb2YgdGhlIDxpbnB1dD4gZWxlbWVudCBpdHNlbGZcblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhIHJlZmVyZW5jZSB0byB0aGUgcGFyZW50IDxmb3JtPiBlbGVtZW50IGlmIGl0IGV4aXN0cywgb3RoZXJ3aXNlIHJldHVybiBgbnVsbGAuXG4gICAgICogSWYgdGhlIHBhcmVudCBmb3JtIGVsZW1lbnQgYXMgYWxyZWFkeSBiZWVuIGZvdW5kLCB0aGlzIGRpcmVjdGx5IHJldHVybiBhIHJlZmVyZW5jZSB0byBpdC5cbiAgICAgKiBIb3dldmVyLCB5b3UgY2FuIGZvcmNlIEF1dG9OdW1lcmljIHRvIHNlYXJjaCBhZ2FpbiBmb3IgaXRzIHJlZmVyZW5jZSBieSBwYXNzaW5nIGB0cnVlYCBhcyBhIHBhcmFtZXRlciB0byB0aGlzIG1ldGhvZC5cbiAgICAgKiBUaGlzIG1ldGhvZCB1cGRhdGVzIHRoZSBgdGhpcy5wYXJlbnRGb3JtYCBhdHRyaWJ1dGUuXG4gICAgICpcbiAgICAgKiBJbiBlaXRoZXIgY2FzZSwgd2hlbmV2ZXIgYSBuZXcgcGFyZW50IGZvcm0gaXMgc2V0IGZvciB0aGUgY3VycmVudCBBdXRvTnVtZXJpYyBlbGVtZW50LCB3ZSBtYWtlIHN1cmUgdG8gdXBkYXRlIHRoZSBhbkNvdW50IGFuZCBhbkZvcm1IYW5kbGVyIGF0dHJpYnV0ZXMgb24gYm90aCB0aGUgb2xkIGZvcm0gYW5kIHRoZSBuZXcgb25lIChmb3IgaW5zdGFuY2UgaW4gY2FzZSB0aGUgdXNlciBtb3ZlZCB0aGUgaW5wdXQgZWxlbWVudHMgd2l0aCBgYXBwZW5kQ2hpbGQoKWAgc2luY2UgQXV0b051bWVyaWMgY2Fubm90IG5vdCBkZXRlY3QgdGhhdCkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGZvcmNlU2VhcmNoIElmIHNldCB0byBgdHJ1ZWAsIHRoZSBwYXJlbnQgZm9ybSBpcyBzZWFyY2hlZCBhZ2FpbiwgZXZlbiBpZiBgdGhpcy5wYXJlbnRGb3JtYCBpcyBhbHJlYWR5IHNldC5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtIVE1MRm9ybUVsZW1lbnR8bnVsbH1cbiAgICAgKi9cbiAgICBmb3JtKGZvcmNlU2VhcmNoID0gZmFsc2UpIHtcbiAgICAgICAgaWYgKGZvcmNlU2VhcmNoIHx8IEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eSh0aGlzLnBhcmVudEZvcm0pKSB7XG4gICAgICAgICAgICBjb25zdCBuZXdQYXJlbnRGb3JtID0gdGhpcy5fZ2V0UGFyZW50Rm9ybSgpO1xuICAgICAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwobmV3UGFyZW50Rm9ybSkgJiYgbmV3UGFyZW50Rm9ybSAhPT0gdGhpcy5wYXJlbnRGb3JtKSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIGN1cnJlbnQgcGFyZW50IGZvcm0gZXhpc3RzIGFuZCBpcyBkaWZmZXJlbnQgZnJvbSB0aGUgcHJldmlvdXMgcGFyZW50IGZvcm1cblxuICAgICAgICAgICAgICAgIC8vIFNlYXJjaCBmb3IgYWxsIHRoZSBBdXRvTnVtZXJpYyBlbGVtZW50cyBpbiB0aGUgb2xkIHBhcmVudCBmb3JtXG4gICAgICAgICAgICAgICAgY29uc3Qgb2xkQU5DaGlsZHJlbiA9IHRoaXMuX2dldEZvcm1BdXRvTnVtZXJpY0NoaWxkcmVuKHRoaXMucGFyZW50Rm9ybSk7XG4gICAgICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBhbkNvdW50IHdpdGggdGhlIGNvcnJlY3QgbnVtYmVyIG9mIEF1dG9OdW1lcmljIGVsZW1lbnRzXG4gICAgICAgICAgICAgICAgdGhpcy5wYXJlbnRGb3JtLmRhdGFzZXQuYW5Db3VudCA9IG9sZEFOQ2hpbGRyZW4ubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIG5ldyBwYXJlbnQgZm9ybSBhbHJlYWR5IGhhcyBhIGFuRm9ybUhhbmRsZXIgbmFtZVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9oYXNGb3JtSGFuZGxlckZ1bmN0aW9uKG5ld1BhcmVudEZvcm0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2luY3JlbWVudFBhcmVudEZvcm1Db3VudGVyKG5ld1BhcmVudEZvcm0pOyAvLyBJbmNyZW1lbnQgaXRzIGNvdW50ZXJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBDcmVhdGUgb25lIGFuZCBzZXQgdGhlIGFuQ291bnQgdG8gMVxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zdG9yZUZvcm1IYW5kbGVyRnVuY3Rpb24obmV3UGFyZW50Rm9ybSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2luaXRpYWxpemVGb3JtQ291bnRlclRvT25lKG5ld1BhcmVudEZvcm0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5wYXJlbnRGb3JtID0gbmV3UGFyZW50Rm9ybTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLnBhcmVudEZvcm07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGFuIGFycmF5IG9mIHRoZSBBdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnRzIGZvciB0aGUgZ2l2ZW4gZm9ybSBlbGVtZW50IGlzIHBhc3NlZCwgb3RoZXJ3aXNlIGZvciB0aGUgY3VycmVudCBgdGhpcy5wYXJlbnRGb3JtYCBlbGVtZW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRm9ybUVsZW1lbnR8bnVsbH0gZm9ybUVsZW1lbnRcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtBcnJheS48SFRNTElucHV0RWxlbWVudD59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZ2V0Rm9ybUF1dG9OdW1lcmljQ2hpbGRyZW4oZm9ybUVsZW1lbnQpIHtcbiAgICAgICAgLy8gU2VhcmNoIGZvciBhbGwgdGhlIGNoaWxkIEF1dG9OdW1lcmljIGVsZW1lbnRzIGluIHRoYXQgcGFyZW50IGZvcm1cbiAgICAgICAgLy9UT0RPIFRoaXMgb25seSBzZWFyY2ggZm9yIDxpbnB1dD4gZWxlbWVudHMsIG5vdCBjb250ZW50ZWRpdGFibGUgbm9uLWlucHV0IHRhZyBvbmVzLCBmb3Igbm93LiBBZGQgYSBwYXJhbWV0ZXIgdG8gYWxsb3cgdGhpcyBmdW5jdGlvbiB0byBzZWFyY2ggb24gZXZlcnkgdGFncy5cbiAgICAgICAgY29uc3QgaW5wdXRMaXN0ID0gWy4uLiBmb3JtRWxlbWVudC5xdWVyeVNlbGVjdG9yQWxsKCdpbnB1dCcpXTtcblxuICAgICAgICByZXR1cm4gaW5wdXRMaXN0LmZpbHRlcihpbnB1dCA9PiB0aGlzLmNvbnN0cnVjdG9yLmlzTWFuYWdlZEJ5QXV0b051bWVyaWMoaW5wdXQpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYSByZWZlcmVuY2UgdG8gdGhlIHBhcmVudCA8Zm9ybT4gZWxlbWVudCBpZiBpdCBleGlzdHMsIG90aGVyd2lzZSByZXR1cm4gYG51bGxgLlxuICAgICAqXG4gICAgICogQHJldHVybnMge0hUTUxGb3JtRWxlbWVudHxudWxsfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2dldFBhcmVudEZvcm0oKSB7XG4gICAgICAgIGlmICh0aGlzLmRvbUVsZW1lbnQudGFnTmFtZS50b0xvd2VyQ2FzZSgpID09PSAnYm9keScpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IG5vZGUgPSB0aGlzLmRvbUVsZW1lbnQ7XG4gICAgICAgIGxldCB0YWdOYW1lO1xuICAgICAgICBkbyB7XG4gICAgICAgICAgICBub2RlID0gbm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChub2RlKSkge1xuICAgICAgICAgICAgICAgIC8vIFNwZWNpYWwgY2FzZSB3aGVuIHVzaW5nIHRlbXBsYXRlcyB3aXRoIGZyYW1ld29ya3MgbGlrZSBWdWUuanMsIHdoZXJlIHRoZSBpbnB1dCBlbGVtZW50IGNhbiBiZSAnZGV0YWNoZWQnIHdoZW4gaW5pdGlhbGl6aW5nIHRoZSBET00gc3RydWN0dXJlXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChub2RlLnRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICB0YWdOYW1lID0gbm9kZS50YWdOYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRhZ05hbWUgPSAnJztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRhZ05hbWUgPT09ICdib2R5Jykge1xuICAgICAgICAgICAgICAgIC8vIEdldCBvdXQgb2YgdGhlIGxvb3AgaWYgd2UgZ2V0IHVwIHRvIHRoZSBgPGJvZHk+YCBlbGVtZW50XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gd2hpbGUgKHRhZ05hbWUgIT09ICdmb3JtJyk7XG5cbiAgICAgICAgaWYgKHRhZ05hbWUgPT09ICdmb3JtJykge1xuICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhIHN0cmluZyBpbiBzdGFuZGFyZCBVUkwtZW5jb2RlZCBub3RhdGlvbiB3aXRoIHRoZSBmb3JtIGlucHV0IHZhbHVlcyBiZWluZyB1bmZvcm1hdHRlZC5cbiAgICAgKiBUaGlzIHN0cmluZyBjYW4gYmUgdXNlZCBhcyBhIHF1ZXJ5IGZvciBpbnN0YW5jZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgZm9ybU51bWVyaWNTdHJpbmcoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbnN0cnVjdG9yLl9zZXJpYWxpemVOdW1lcmljU3RyaW5nKHRoaXMuZm9ybSgpLCB0aGlzLnNldHRpbmdzLnNlcmlhbGl6ZVNwYWNlcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGEgc3RyaW5nIGluIHN0YW5kYXJkIFVSTC1lbmNvZGVkIG5vdGF0aW9uIHdpdGggdGhlIGZvcm0gaW5wdXQgdmFsdWVzIGJlaW5nIGZvcm1hdHRlZC5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgZm9ybUZvcm1hdHRlZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IuX3NlcmlhbGl6ZUZvcm1hdHRlZCh0aGlzLmZvcm0oKSwgdGhpcy5zZXR0aW5ncy5zZXJpYWxpemVTcGFjZXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhIHN0cmluZyBpbiBzdGFuZGFyZCBVUkwtZW5jb2RlZCBub3RhdGlvbiB3aXRoIHRoZSBmb3JtIGlucHV0IHZhbHVlcywgd2l0aCBsb2NhbGl6ZWQgdmFsdWVzLlxuICAgICAqIFRoZSBkZWZhdWx0IG91dHB1dCBmb3JtYXQgY2FuIGJlIG92ZXJyaWRkZW4gYnkgcGFzc2luZyB0aGUgb3B0aW9uIGFzIGEgcGFyYW1ldGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudWxsfHN0cmluZ30gZm9yY2VkT3V0cHV0Rm9ybWF0IElmIHNldCB0byBzb21ldGhpbmcgZGlmZmVyZW50IHRoYW4gYG51bGxgLCB0aGVuIHRoaXMgaXMgdXNlZCBhcyBhbiBvdmVycmlkaW5nIG91dHB1dEZvcm1hdCBvcHRpb25cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIGZvcm1Mb2NhbGl6ZWQoZm9yY2VkT3V0cHV0Rm9ybWF0ID0gbnVsbCkge1xuICAgICAgICBsZXQgb3V0cHV0Rm9ybWF0VG9Vc2U7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoZm9yY2VkT3V0cHV0Rm9ybWF0KSkge1xuICAgICAgICAgICAgb3V0cHV0Rm9ybWF0VG9Vc2UgPSB0aGlzLnNldHRpbmdzLm91dHB1dEZvcm1hdDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG91dHB1dEZvcm1hdFRvVXNlID0gZm9yY2VkT3V0cHV0Rm9ybWF0O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IuX3NlcmlhbGl6ZUxvY2FsaXplZCh0aGlzLmZvcm0oKSwgdGhpcy5zZXR0aW5ncy5zZXJpYWxpemVTcGFjZXMsIG91dHB1dEZvcm1hdFRvVXNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYW4gYXJyYXkgY29udGFpbmluZyBhbiBvYmplY3QgZm9yIGVhY2ggZm9ybSA8aW5wdXQ+IGVsZW1lbnQuXG4gICAgICogVGhvc2Ugb2JqZWN0cyBhcmUgb2YgdGhlIGZvbGxvd2luZyBzdHJ1Y3R1cmUgYHsgbmFtZTogZm9vLCB2YWx1ZTogJzQyJyB9YCwgd2hlcmUgdGhlIGBuYW1lYCBpcyB0aGUgRE9NIGVsZW1lbnQgbmFtZSwgYW5kIHRoZSBgdmFsdWVgIGlzIGFuIHVuZm9ybWF0dGVkIG51bWVyaWMgc3RyaW5nLlxuICAgICAqXG4gICAgICogQHJldHVybnMge0FycmF5fVxuICAgICAqL1xuICAgIGZvcm1BcnJheU51bWVyaWNTdHJpbmcoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbnN0cnVjdG9yLl9zZXJpYWxpemVOdW1lcmljU3RyaW5nQXJyYXkodGhpcy5mb3JtKCksIHRoaXMuc2V0dGluZ3Muc2VyaWFsaXplU3BhY2VzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYW4gYXJyYXkgY29udGFpbmluZyBhbiBvYmplY3QgZm9yIGVhY2ggZm9ybSA8aW5wdXQ+IGVsZW1lbnQuXG4gICAgICogVGhvc2Ugb2JqZWN0cyBhcmUgb2YgdGhlIGZvbGxvd2luZyBzdHJ1Y3R1cmUgYHsgbmFtZTogZm9vLCB2YWx1ZTogJzQyJyB9YCwgd2hlcmUgdGhlIGBuYW1lYCBpcyB0aGUgRE9NIGVsZW1lbnQgbmFtZSwgYW5kIHRoZSBgdmFsdWVgIGlzIHRoZSBmb3JtYXR0ZWQgc3RyaW5nLlxuICAgICAqXG4gICAgICogQHJldHVybnMge0FycmF5fVxuICAgICAqL1xuICAgIGZvcm1BcnJheUZvcm1hdHRlZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IuX3NlcmlhbGl6ZUZvcm1hdHRlZEFycmF5KHRoaXMuZm9ybSgpLCB0aGlzLnNldHRpbmdzLnNlcmlhbGl6ZVNwYWNlcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGFuIGFycmF5IGNvbnRhaW5pbmcgYW4gb2JqZWN0IGZvciBlYWNoIGZvcm0gPGlucHV0PiBlbGVtZW50LlxuICAgICAqIFRob3NlIG9iamVjdHMgYXJlIG9mIHRoZSBmb2xsb3dpbmcgc3RydWN0dXJlIGB7IG5hbWU6IGZvbywgdmFsdWU6ICc0MicgfWAsIHdoZXJlIHRoZSBgbmFtZWAgaXMgdGhlIERPTSBlbGVtZW50IG5hbWUsIGFuZCB0aGUgYHZhbHVlYCBpcyB0aGUgbG9jYWxpemVkIG51bWVyaWMgc3RyaW5nLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudWxsfHN0cmluZ30gZm9yY2VkT3V0cHV0Rm9ybWF0IElmIHNldCB0byBzb21ldGhpbmcgZGlmZmVyZW50IHRoYW4gYG51bGxgLCB0aGVuIHRoaXMgaXMgdXNlZCBhcyBhbiBvdmVycmlkaW5nIG91dHB1dEZvcm1hdCBvcHRpb25cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9XG4gICAgICovXG4gICAgZm9ybUFycmF5TG9jYWxpemVkKGZvcmNlZE91dHB1dEZvcm1hdCA9IG51bGwpIHtcbiAgICAgICAgbGV0IG91dHB1dEZvcm1hdFRvVXNlO1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGZvcmNlZE91dHB1dEZvcm1hdCkpIHtcbiAgICAgICAgICAgIG91dHB1dEZvcm1hdFRvVXNlID0gdGhpcy5zZXR0aW5ncy5vdXRwdXRGb3JtYXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvdXRwdXRGb3JtYXRUb1VzZSA9IGZvcmNlZE91dHB1dEZvcm1hdDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLmNvbnN0cnVjdG9yLl9zZXJpYWxpemVMb2NhbGl6ZWRBcnJheSh0aGlzLmZvcm0oKSwgdGhpcy5zZXR0aW5ncy5zZXJpYWxpemVTcGFjZXMsIG91dHB1dEZvcm1hdFRvVXNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYSBKU09OIHN0cmluZyBjb250YWluaW5nIGFuIG9iamVjdCByZXByZXNlbnRpbmcgdGhlIGZvcm0gaW5wdXQgdmFsdWVzLlxuICAgICAqIFRoaXMgaXMgYmFzZWQgb24gdGhlIHJlc3VsdCBvZiB0aGUgYGZvcm1BcnJheU51bWVyaWNTdHJpbmcoKWAgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIGZvcm1Kc29uTnVtZXJpY1N0cmluZygpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHRoaXMuZm9ybUFycmF5TnVtZXJpY1N0cmluZygpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYSBKU09OIHN0cmluZyBjb250YWluaW5nIGFuIG9iamVjdCByZXByZXNlbnRpbmcgdGhlIGZvcm0gaW5wdXQgdmFsdWVzLlxuICAgICAqIFRoaXMgaXMgYmFzZWQgb24gdGhlIHJlc3VsdCBvZiB0aGUgYGZvcm1BcnJheUZvcm1hdHRlZCgpYCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgZm9ybUpzb25Gb3JtYXR0ZWQoKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh0aGlzLmZvcm1BcnJheUZvcm1hdHRlZCgpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYSBKU09OIHN0cmluZyBjb250YWluaW5nIGFuIG9iamVjdCByZXByZXNlbnRpbmcgdGhlIGZvcm0gaW5wdXQgdmFsdWVzLlxuICAgICAqIFRoaXMgaXMgYmFzZWQgb24gdGhlIHJlc3VsdCBvZiB0aGUgYGZvcm1BcnJheUxvY2FsaXplZCgpYCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVsbHxzdHJpbmd9IGZvcmNlZE91dHB1dEZvcm1hdCBJZiBzZXQgdG8gc29tZXRoaW5nIGRpZmZlcmVudCB0aGFuIGBudWxsYCwgdGhlbiB0aGlzIGlzIHVzZWQgYXMgYW4gb3ZlcnJpZGluZyBvdXRwdXRGb3JtYXQgb3B0aW9uXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBmb3JtSnNvbkxvY2FsaXplZChmb3JjZWRPdXRwdXRGb3JtYXQgPSBudWxsKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh0aGlzLmZvcm1BcnJheUxvY2FsaXplZChmb3JjZWRPdXRwdXRGb3JtYXQpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVbmZvcm1hdCBhbGwgdGhlIGF1dG9OdW1lcmljLW1hbmFnZWQgZWxlbWVudHMgdGhhdCBhcmUgYSBjaGlsZCBvZiB0aGUgcGFyZW50IDxmb3JtPiBlbGVtZW50IG9mIHRoaXMgRE9NIGVsZW1lbnQsIHRvIG51bWVyaWMgc3RyaW5nc1xuICAgICAqXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGZvcm1VbmZvcm1hdCgpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgY29uc3QgaW5wdXRzID0gdGhpcy5jb25zdHJ1Y3Rvci5fZ2V0Q2hpbGRBTklucHV0RWxlbWVudCh0aGlzLmZvcm0oKSk7XG4gICAgICAgIGlucHV0cy5mb3JFYWNoKGlucHV0ID0+IHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLmdldEF1dG9OdW1lcmljRWxlbWVudChpbnB1dCkudW5mb3JtYXQoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVW5mb3JtYXQgYWxsIHRoZSBhdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnRzIHRoYXQgYXJlIGEgY2hpbGQgb2YgdGhlIHBhcmVudCA8Zm9ybT4gZWxlbWVudCBvZiB0aGlzIERPTSBlbGVtZW50LCB0byBsb2NhbGl6ZWQgc3RyaW5nc1xuICAgICAqXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGZvcm1VbmZvcm1hdExvY2FsaXplZCgpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgY29uc3QgaW5wdXRzID0gdGhpcy5jb25zdHJ1Y3Rvci5fZ2V0Q2hpbGRBTklucHV0RWxlbWVudCh0aGlzLmZvcm0oKSk7XG4gICAgICAgIGlucHV0cy5mb3JFYWNoKGlucHV0ID0+IHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLmdldEF1dG9OdW1lcmljRWxlbWVudChpbnB1dCkudW5mb3JtYXRMb2NhbGl6ZWQoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVmb3JtYXQgYWxsIHRoZSBhdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnRzIHRoYXQgYXJlIGEgY2hpbGQgb2YgdGhlIHBhcmVudCA8Zm9ybT4gZWxlbWVudCBvZiB0aGlzIERPTSBlbGVtZW50XG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgZm9ybVJlZm9ybWF0KCkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICBjb25zdCBpbnB1dHMgPSB0aGlzLmNvbnN0cnVjdG9yLl9nZXRDaGlsZEFOSW5wdXRFbGVtZW50KHRoaXMuZm9ybSgpKTtcbiAgICAgICAgaW5wdXRzLmZvckVhY2goaW5wdXQgPT4ge1xuICAgICAgICAgICAgQXV0b051bWVyaWMuZ2V0QXV0b051bWVyaWNFbGVtZW50KGlucHV0KS5yZWZvcm1hdCgpO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0IHRoZSBpbnB1dCB2YWx1ZXMgdG8gbnVtZXJpYyBzdHJpbmdzLCBzdWJtaXQgdGhlIGZvcm0sIHRoZW4gcmVmb3JtYXQgdGhvc2UgYmFjay5cbiAgICAgKiBUaGUgZnVuY3Rpb24gY2FuIGVpdGhlciB0YWtlIGEgY2FsbGJhY2ssIG9yIG5vdC4gSWYgaXQgZG9lc24ndCwgdGhlIGRlZmF1bHQgYGZvcm0uc3VibWl0KClgIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkLlxuICAgICAqIE90aGVyd2lzZSwgaXQgcnVucyBgY2FsbGJhY2sodmFsdWUpYCB3aXRoIGB2YWx1ZWAgYmVpbmcgZXF1YWwgdG8gdGhlIHJlc3VsdCBvZiBgZm9ybU51bWVyaWNTdHJpbmcoKWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufG51bGx9IGNhbGxiYWNrXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGZvcm1TdWJtaXROdW1lcmljU3RyaW5nKGNhbGxiYWNrID0gbnVsbCkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgdGhpcy5mb3JtVW5mb3JtYXQoKTtcbiAgICAgICAgICAgIHRoaXMuZm9ybSgpLnN1Ym1pdCgpO1xuICAgICAgICAgICAgdGhpcy5mb3JtUmVmb3JtYXQoKTtcbiAgICAgICAgfSBlbHNlIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0Z1bmN0aW9uKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgY2FsbGJhY2sodGhpcy5mb3JtTnVtZXJpY1N0cmluZygpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBnaXZlbiBjYWxsYmFjayBpcyBub3QgYSBmdW5jdGlvbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN1Ym1pdCB0aGUgZm9ybSB3aXRoIHRoZSBjdXJyZW50IGZvcm1hdHRlZCB2YWx1ZXMuXG4gICAgICogVGhlIGZ1bmN0aW9uIGNhbiBlaXRoZXIgdGFrZSBhIGNhbGxiYWNrLCBvciBub3QuIElmIGl0IGRvZXNuJ3QsIHRoZSBkZWZhdWx0IGBmb3JtLnN1Ym1pdCgpYCBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZC5cbiAgICAgKiBPdGhlcndpc2UsIGl0IHJ1bnMgYGNhbGxiYWNrKHZhbHVlKWAgd2l0aCBgdmFsdWVgIGJlaW5nIGVxdWFsIHRvIHRoZSByZXN1bHQgb2YgYGZvcm1Gb3JtYXR0ZWQoKWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufG51bGx9IGNhbGxiYWNrXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGZvcm1TdWJtaXRGb3JtYXR0ZWQoY2FsbGJhY2sgPSBudWxsKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoY2FsbGJhY2spKSB7XG4gICAgICAgICAgICB0aGlzLmZvcm0oKS5zdWJtaXQoKTtcbiAgICAgICAgfSBlbHNlIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0Z1bmN0aW9uKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgY2FsbGJhY2sodGhpcy5mb3JtRm9ybWF0dGVkKCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGdpdmVuIGNhbGxiYWNrIGlzIG5vdCBhIGZ1bmN0aW9uLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydCB0aGUgaW5wdXQgdmFsdWVzIHRvIGxvY2FsaXplZCBzdHJpbmdzLCBzdWJtaXQgdGhlIGZvcm0sIHRoZW4gcmVmb3JtYXQgdGhvc2UgYmFjay5cbiAgICAgKiBUaGUgZnVuY3Rpb24gY2FuIGVpdGhlciB0YWtlIGEgY2FsbGJhY2ssIG9yIG5vdC4gSWYgaXQgZG9lc24ndCwgdGhlIGRlZmF1bHQgYGZvcm0uc3VibWl0KClgIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkLlxuICAgICAqIE90aGVyd2lzZSwgaXQgcnVucyBgY2FsbGJhY2sodmFsdWUpYCB3aXRoIGB2YWx1ZWAgYmVpbmcgZXF1YWwgdG8gdGhlIHJlc3VsdCBvZiBgZm9ybUxvY2FsaXplZCgpYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVsbHxzdHJpbmd9IGZvcmNlZE91dHB1dEZvcm1hdCBJZiBzZXQgdG8gc29tZXRoaW5nIGRpZmZlcmVudCB0aGFuIGBudWxsYCwgdGhlbiB0aGlzIGlzIHVzZWQgYXMgYW4gb3ZlcnJpZGluZyBvdXRwdXRGb3JtYXQgb3B0aW9uXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbnxudWxsfSBjYWxsYmFja1xuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBmb3JtU3VibWl0TG9jYWxpemVkKGZvcmNlZE91dHB1dEZvcm1hdCA9IG51bGwsIGNhbGxiYWNrID0gbnVsbCkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgdGhpcy5mb3JtVW5mb3JtYXRMb2NhbGl6ZWQoKTtcbiAgICAgICAgICAgIHRoaXMuZm9ybSgpLnN1Ym1pdCgpO1xuICAgICAgICAgICAgdGhpcy5mb3JtUmVmb3JtYXQoKTtcbiAgICAgICAgfSBlbHNlIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0Z1bmN0aW9uKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgY2FsbGJhY2sodGhpcy5mb3JtTG9jYWxpemVkKGZvcmNlZE91dHB1dEZvcm1hdCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGdpdmVuIGNhbGxiYWNrIGlzIG5vdCBhIGZ1bmN0aW9uLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGUgYW4gYXJyYXkgb2YgbnVtZXJpYyBzdHJpbmdzIGZyb20gdGhlIGA8aW5wdXQ+YCBlbGVtZW50cywgYW5kIHBhc3MgaXQgdG8gdGhlIGdpdmVuIGNhbGxiYWNrLlxuICAgICAqIFVuZGVyIHRoZSBob29kLCB0aGUgYXJyYXkgaXMgZ2VuZXJhdGVkIHZpYSBhIGNhbGwgdG8gYGZvcm1BcnJheU51bWVyaWNTdHJpbmcoKWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFja1xuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBmb3JtU3VibWl0QXJyYXlOdW1lcmljU3RyaW5nKGNhbGxiYWNrKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0Z1bmN0aW9uKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgY2FsbGJhY2sodGhpcy5mb3JtQXJyYXlOdW1lcmljU3RyaW5nKCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGdpdmVuIGNhbGxiYWNrIGlzIG5vdCBhIGZ1bmN0aW9uLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGUgYW4gYXJyYXkgb2YgdGhlIGN1cnJlbnQgZm9ybWF0dGVkIHZhbHVlcyBmcm9tIHRoZSBgPGlucHV0PmAgZWxlbWVudHMsIGFuZCBwYXNzIGl0IHRvIHRoZSBnaXZlbiBjYWxsYmFjay5cbiAgICAgKiBVbmRlciB0aGUgaG9vZCwgdGhlIGFycmF5IGlzIGdlbmVyYXRlZCB2aWEgYSBjYWxsIHRvIGBmb3JtQXJyYXlGb3JtYXR0ZWQoKWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFja1xuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBmb3JtU3VibWl0QXJyYXlGb3JtYXR0ZWQoY2FsbGJhY2spIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzRnVuY3Rpb24oY2FsbGJhY2spKSB7XG4gICAgICAgICAgICBjYWxsYmFjayh0aGlzLmZvcm1BcnJheUZvcm1hdHRlZCgpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBnaXZlbiBjYWxsYmFjayBpcyBub3QgYSBmdW5jdGlvbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGFuIGFycmF5IG9mIGxvY2FsaXplZCBzdHJpbmdzIGZyb20gdGhlIGA8aW5wdXQ+YCBlbGVtZW50cywgYW5kIHBhc3MgaXQgdG8gdGhlIGdpdmVuIGNhbGxiYWNrLlxuICAgICAqIFVuZGVyIHRoZSBob29kLCB0aGUgYXJyYXkgaXMgZ2VuZXJhdGVkIHZpYSBhIGNhbGwgdG8gYGZvcm1BcnJheUxvY2FsaXplZCgpYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gICAgICogQHBhcmFtIHtudWxsfHN0cmluZ30gZm9yY2VkT3V0cHV0Rm9ybWF0IElmIHNldCB0byBzb21ldGhpbmcgZGlmZmVyZW50IHRoYW4gYG51bGxgLCB0aGVuIHRoaXMgaXMgdXNlZCBhcyBhbiBvdmVycmlkaW5nIG91dHB1dEZvcm1hdCBvcHRpb25cbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgZm9ybVN1Ym1pdEFycmF5TG9jYWxpemVkKGNhbGxiYWNrLCBmb3JjZWRPdXRwdXRGb3JtYXQgPSBudWxsKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0Z1bmN0aW9uKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgY2FsbGJhY2sodGhpcy5mb3JtQXJyYXlMb2NhbGl6ZWQoZm9yY2VkT3V0cHV0Rm9ybWF0KSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZ2l2ZW4gY2FsbGJhY2sgaXMgbm90IGEgZnVuY3Rpb24uYCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBhIEpTT04gc3RyaW5nIHdpdGggdGhlIG51bWVyaWMgc3RyaW5ncyB2YWx1ZXMgZnJvbSB0aGUgYDxpbnB1dD5gIGVsZW1lbnRzLCBhbmQgcGFzcyBpdCB0byB0aGUgZ2l2ZW4gY2FsbGJhY2suXG4gICAgICogVW5kZXIgdGhlIGhvb2QsIHRoZSBhcnJheSBpcyBnZW5lcmF0ZWQgdmlhIGEgY2FsbCB0byBgZm9ybUpzb25OdW1lcmljU3RyaW5nKClgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgZm9ybVN1Ym1pdEpzb25OdW1lcmljU3RyaW5nKGNhbGxiYWNrKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0Z1bmN0aW9uKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgY2FsbGJhY2sodGhpcy5mb3JtSnNvbk51bWVyaWNTdHJpbmcoKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZ2l2ZW4gY2FsbGJhY2sgaXMgbm90IGEgZnVuY3Rpb24uYCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBhIEpTT04gc3RyaW5nIHdpdGggdGhlIGN1cnJlbnQgZm9ybWF0dGVkIHZhbHVlcyBmcm9tIHRoZSBgPGlucHV0PmAgZWxlbWVudHMsIGFuZCBwYXNzIGl0IHRvIHRoZSBnaXZlbiBjYWxsYmFjay5cbiAgICAgKiBVbmRlciB0aGUgaG9vZCwgdGhlIGFycmF5IGlzIGdlbmVyYXRlZCB2aWEgYSBjYWxsIHRvIGBmb3JtSnNvbkZvcm1hdHRlZCgpYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGZvcm1TdWJtaXRKc29uRm9ybWF0dGVkKGNhbGxiYWNrKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0Z1bmN0aW9uKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgY2FsbGJhY2sodGhpcy5mb3JtSnNvbkZvcm1hdHRlZCgpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBnaXZlbiBjYWxsYmFjayBpcyBub3QgYSBmdW5jdGlvbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgSlNPTiBzdHJpbmcgd2l0aCB0aGUgbG9jYWxpemVkIHN0cmluZ3MgdmFsdWVzIGZyb20gdGhlIGA8aW5wdXQ+YCBlbGVtZW50cywgYW5kIHBhc3MgaXQgdG8gdGhlIGdpdmVuIGNhbGxiYWNrLlxuICAgICAqIFVuZGVyIHRoZSBob29kLCB0aGUgYXJyYXkgaXMgZ2VuZXJhdGVkIHZpYSBhIGNhbGwgdG8gYGZvcm1Kc29uTG9jYWxpemVkKClgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAgICAgKiBAcGFyYW0ge251bGx8c3RyaW5nfSBmb3JjZWRPdXRwdXRGb3JtYXQgSWYgc2V0IHRvIHNvbWV0aGluZyBkaWZmZXJlbnQgdGhhbiBgbnVsbGAsIHRoZW4gdGhpcyBpcyB1c2VkIGFzIGFuIG92ZXJyaWRpbmcgb3V0cHV0Rm9ybWF0IG9wdGlvblxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBmb3JtU3VibWl0SnNvbkxvY2FsaXplZChjYWxsYmFjaywgZm9yY2VkT3V0cHV0Rm9ybWF0ID0gbnVsbCkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNGdW5jdGlvbihjYWxsYmFjaykpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKHRoaXMuZm9ybUpzb25Mb2NhbGl6ZWQoZm9yY2VkT3V0cHV0Rm9ybWF0KSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZ2l2ZW4gY2FsbGJhY2sgaXMgbm90IGEgZnVuY3Rpb24uYCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVbmZvcm1hdCB0aGUgZ2l2ZW4gQXV0b051bWVyaWMgZWxlbWVudCwgYW5kIHVwZGF0ZSB0aGUgYGhvdmVyZWRXaXRoQWx0YCB2YXJpYWJsZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7QXV0b051bWVyaWN9IGFuRWxlbWVudFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF91bmZvcm1hdEFsdEhvdmVyZWQoYW5FbGVtZW50KSB7XG4gICAgICAgIGFuRWxlbWVudC5ob3ZlcmVkV2l0aEFsdCA9IHRydWU7XG4gICAgICAgIGFuRWxlbWVudC51bmZvcm1hdCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlZm9ybWF0IHRoZSBnaXZlbiBBdXRvTnVtZXJpYyBlbGVtZW50LCBhbmQgdXBkYXRlIHRoZSBgaG92ZXJlZFdpdGhBbHRgIHZhcmlhYmxlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtBdXRvTnVtZXJpY30gYW5FbGVtZW50XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX3JlZm9ybWF0QWx0SG92ZXJlZChhbkVsZW1lbnQpIHtcbiAgICAgICAgYW5FbGVtZW50LmhvdmVyZWRXaXRoQWx0ID0gZmFsc2U7XG4gICAgICAgIGFuRWxlbWVudC5yZWZvcm1hdCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhbiBhcnJheSBvZiBhdXRvTnVtZXJpYyBlbGVtZW50cywgY2hpbGQgb2YgdGhlIDxmb3JtPiBlbGVtZW50IHBhc3NlZCBhcyBhIHBhcmFtZXRlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGZvcm1Ob2RlXG4gICAgICogQHJldHVybnMge0FycmF5fVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9nZXRDaGlsZEFOSW5wdXRFbGVtZW50KGZvcm1Ob2RlKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGNvbnN0IGlucHV0TGlzdCA9IGZvcm1Ob2RlLmdldEVsZW1lbnRzQnlUYWdOYW1lKCdpbnB1dCcpO1xuXG4gICAgICAgIC8vIExvb3AgdGhpcyBsaXN0IGFuZCBrZWVwIG9ubHkgdGhlIGlucHV0cyB0aGF0IGFyZSBtYW5hZ2VkIGJ5IEF1dG9OdW1lcmljXG4gICAgICAgIGNvbnN0IGF1dG9OdW1lcmljSW5wdXRzID0gW107XG4gICAgICAgIGNvbnN0IGlucHV0RWxlbWVudHMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChpbnB1dExpc3QsIDApO1xuICAgICAgICBpbnB1dEVsZW1lbnRzLmZvckVhY2goaW5wdXQgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMudGVzdChpbnB1dCkpIHtcbiAgICAgICAgICAgICAgICBhdXRvTnVtZXJpY0lucHV0cy5wdXNoKGlucHV0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIGF1dG9OdW1lcmljSW5wdXRzO1xuICAgIH1cblxuICAgIC8vIFN0YXRpYyBtZXRob2RzXG4gICAgLyoqXG4gICAgICogVGVzdCBpZiB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQsIG9yIHRoZSBlbGVtZW50IHNlbGVjdGVkIGJ5IHRoZSBnaXZlbiBzZWxlY3RvciBzdHJpbmcgaXMgYWxyZWFkeSBtYW5hZ2VkIGJ5IEF1dG9OdW1lcmljIChpZiBpdCBoYXMgYmVlbiBpbml0aWFsaXplZCBvbiB0aGUgY3VycmVudCBwYWdlKS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8c3RyaW5nfSBkb21FbGVtZW50T3JTZWxlY3RvciBBY2NlcHRzIGVpdGhlciBkaXJlY3RseSBhIERPTSBlbGVtZW50IHRvIHRlc3QsIG9yIGEgc3RyaW5nIHNlbGVjdG9yICh0aGF0IHdpbGwgcmV0dXJuIG9uZSBhbmQgb25seSBvbmUgZWxlbWVudCwgaWYgYW55KVxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIHN0YXRpYyB0ZXN0KGRvbUVsZW1lbnRPclNlbGVjdG9yKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc0luR2xvYmFsTGlzdChBdXRvTnVtZXJpY0hlbHBlci5kb21FbGVtZW50KGRvbUVsZW1lbnRPclNlbGVjdG9yKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGEgV2Vha01hcCB3aXRoIHRoZSBnaXZlbiBuYW1lLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHdlYWtNYXBOYW1lXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2NyZWF0ZVdlYWtNYXAod2Vha01hcE5hbWUpIHtcbiAgICAgICAgd2luZG93W3dlYWtNYXBOYW1lXSA9IG5ldyBXZWFrTWFwKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGEgbGlzdCBvZiBhbGwgdGhlIEF1dG9OdW1lcmljIGVsZW1lbnRzIHRoYXQgYXJlIGluaXRpYWxpemVkIG9uIHRoZSBjdXJyZW50IHBhZ2UuXG4gICAgICogVGhpcyBpcyBuZWVkZWQgaW4gb3JkZXIgdG8gZGV0ZXJtaW5lIGlmIGEgZ2l2ZW4gZG9tIGVsZW1lbnQgaXMgYWxyZWFkeSBtYW5hZ2VkIGJ5IGF1dG9OdW1lcmljLlxuICAgICAqIFRoaXMgdXNlcyBhIFdlYWtNYXAgaW4gb3JkZXIgdG8gbGltaXQgcG90ZW50aWFsIGdhcmJhZ2UgY29sbGVjdGlvbiBwcm9ibGVtcy5cbiAgICAgKiAoY2YuIG15IHRlc3RzIG9uIGh0dHA6Ly9jb2RlcGVuLmlvL0Fub3RoZXJMaW51eFVzZXIvcGVuL3BSUUdhTT9lZGl0b3JzPTEwMTEpXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2NyZWF0ZUdsb2JhbExpc3QoKSB7XG4gICAgICAgIC8vIFRoZSBjaGVjayB0aGF0IHRoaXMgZ2xvYmFsIGxpc3QgZG9lcyBub3QgZXhpc3RzIGFscmVhZHkgaXMgZG9uZSBpbiB0aGUgYWRkIGFuZCByZW1vdmUgZnVuY3Rpb25zIGFscmVhZHlcbiAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0dsb2JhbExpc3ROYW1lID0gJ2F1dG9OdW1lcmljR2xvYmFsTGlzdCc7IC8vWFhYIFRoaXMgbG9va3Mgd2VpcmQgdG8gc2V0IGEgdmFyaWFibGUgb24gYHRoaXMuYCBpbiBhIHN0YXRpYyBtZXRob2QsIGJ1dCB0aGF0IHJlYWxseSBkZWNsYXJlIHRoYXQgdmFyaWFibGUgbGlrZSBhIHN0YXRpYyBwcm9wZXJ0eVxuICAgICAgICAvLyBOb3RlOiBJIHNob3VsZCBub3QgZ2V0IGFueSBtZW1vcnkgbGVha3MgZm9yIHJlZmVyZW5jaW5nIHRoZSBET00gZWxlbWVudCBpbiB0aGUgYHZhbHVlYCwgdGhpcyBET00gZWxlbWVudCBhbHNvIGJlaW5nIHRoZSBga2V5YCwgYWNjb3JkaW5nIHRvIHRoZSBzcGVjIDogaHR0cDovL3d3dy5lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzYuMC8jc2VjLXdlYWttYXAtb2JqZWN0c1xuICAgICAgICB0aGlzLl9jcmVhdGVXZWFrTWFwKHRoaXMuYXV0b051bWVyaWNHbG9iYWxMaXN0TmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgZ2xvYmFsIEF1dG9OdW1lcmljIGVsZW1lbnQgbGlzdCBleGlzdHMuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfZG9lc0dsb2JhbExpc3RFeGlzdHMoKSB7XG4gICAgICAgIGNvbnN0IHR5cGUgPSB0eXBlb2Ygd2luZG93W3RoaXMuYXV0b051bWVyaWNHbG9iYWxMaXN0TmFtZV07XG4gICAgICAgIHJldHVybiB0eXBlICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgICAgdHlwZSA9PT0gJ29iamVjdCc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkIHRoZSBnaXZlbiBvYmplY3QgdG8gdGhlIGdsb2JhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0F1dG9OdW1lcmljfSBhdXRvTnVtZXJpY09iamVjdFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9hZGRUb0dsb2JhbExpc3QoYXV0b051bWVyaWNPYmplY3QpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9kb2VzR2xvYmFsTGlzdEV4aXN0cygpKSB7XG4gICAgICAgICAgICB0aGlzLl9jcmVhdGVHbG9iYWxMaXN0KCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBkb21FbGVtZW50ID0gYXV0b051bWVyaWNPYmplY3Qubm9kZSgpO1xuICAgICAgICAvLyBUaGlzIGNoZWNrcyBpZiB0aGUgb2JqZWN0IGlzIG5vdCBhbHJlYWR5IGluIHRoZSBnbG9iYWwgbGlzdCBiZWZvcmUgYWRkaW5nIGl0LlxuICAgICAgICAvLyBUaGlzIGNvdWxkIGhhcHBlbiBpZiBhbiBBdXRvTnVtZXJpYyBlbGVtZW50IGlzIGluaXRpYWxpemVkLCB0aGVuIHRoZSBET00gZWxlbWVudCBpcyByZW1vdmVkIGRpcmVjdGx5IHZpYSBgcmVtb3ZlQ2hpbGRgIChoZW5jZSB0aGUgcmVmZXJlbmNlIGRvZXMgbm90IGdldCByZW1vdmVkIGZyb20gdGhlIGdsb2JhbCBsaXN0KSwgdGhlbiBpdCBnZXQgcmVjcmVhdGVkIGFuZCBpbml0aWFsaXplZCBhZ2FpblxuICAgICAgICBpZiAodGhpcy5faXNJbkdsb2JhbExpc3QoZG9tRWxlbWVudCkpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9nZXRGcm9tR2xvYmFsTGlzdChkb21FbGVtZW50KSA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgIC8vIERvIG5vdCBhZGQgdGhpcyBBdXRvTnVtZXJpYyBvYmplY3QgYWdhaW4gc2luY2UgaXQncyBhbHJlYWR5IGluIHRoYXQgZ2xvYmFsIGxpc3RcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFByaW50IGEgd2FybmluZyB0byB3YXJuIHRoYXQgdGhlIGRvbUVsZW1lbnQgYWxyZWFkeSBoYXMgYSByZWZlcmVuY2UgaW4gdGhlIGdsb2JhbCBtYXAgKGJ1dCB3ZSBjYW5ub3QgZm9yIHN1cmUgc3RhcnRzIGRlbGV0aW5nIHRob3NlIG9sZCByZWZlcmVuY2VzIHNpbmNlIHRoZXkgY291bGQgc3RpbGwgYmUgdXNlZCBieSBhbm90aGVyIEF1dG9OdW1lcmljIG9iamVjdClcbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKGBBIHJlZmVyZW5jZSB0byB0aGUgRE9NIGVsZW1lbnQgeW91IGp1c3QgaW5pdGlhbGl6ZWQgYWxyZWFkeSBleGlzdHMgaW4gdGhlIGdsb2JhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3QuIFBsZWFzZSBtYWtlIHN1cmUgdG8gbm90IGluaXRpYWxpemUgdGhlIHNhbWUgRE9NIGVsZW1lbnQgbXVsdGlwbGUgdGltZXMuYCwgYXV0b051bWVyaWNPYmplY3QuZ2V0U2V0dGluZ3MoKS5zaG93V2FybmluZ3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgd2luZG93W3RoaXMuYXV0b051bWVyaWNHbG9iYWxMaXN0TmFtZV0uc2V0KGRvbUVsZW1lbnQsIGF1dG9OdW1lcmljT2JqZWN0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgdGhlIGdpdmVuIG9iamVjdCBmcm9tIHRoZSBnbG9iYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtBdXRvTnVtZXJpY30gYXV0b051bWVyaWNPYmplY3RcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfcmVtb3ZlRnJvbUdsb2JhbExpc3QoYXV0b051bWVyaWNPYmplY3QpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgaWYgKHRoaXMuX2RvZXNHbG9iYWxMaXN0RXhpc3RzKCkpIHtcbiAgICAgICAgICAgIHdpbmRvd1t0aGlzLmF1dG9OdW1lcmljR2xvYmFsTGlzdE5hbWVdLmRlbGV0ZShhdXRvTnVtZXJpY09iamVjdC5ub2RlKCkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHRvIHRoZSBrZXkgYGRvbUVsZW1lbnRgIHBhc3NlZCBhcyBhIHBhcmFtZXRlci5cbiAgICAgKiBUaGUgdmFsdWUgaXMgdGhlIEF1dG9OdW1lcmljIG9iamVjdCB0aGF0IG1hbmFnZXMgdGhlIERPTSBlbGVtZW50IGBkb21FbGVtZW50YC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8SFRNTElucHV0RWxlbWVudH0gZG9tRWxlbWVudFxuICAgICAqIEByZXR1cm5zIHtudWxsfEF1dG9OdW1lcmljfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9nZXRGcm9tR2xvYmFsTGlzdChkb21FbGVtZW50KSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGlmICh0aGlzLl9kb2VzR2xvYmFsTGlzdEV4aXN0cygpKSB7XG4gICAgICAgICAgICByZXR1cm4gd2luZG93W3RoaXMuYXV0b051bWVyaWNHbG9iYWxMaXN0TmFtZV0uZ2V0KGRvbUVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgdGhlIGdpdmVuIERPTSBlbGVtZW50IGlzIGluIHRoZSBnbG9iYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fSBkb21FbGVtZW50XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2lzSW5HbG9iYWxMaXN0KGRvbUVsZW1lbnQpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgaWYgKCF0aGlzLl9kb2VzR2xvYmFsTGlzdEV4aXN0cygpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gd2luZG93W3RoaXMuYXV0b051bWVyaWNHbG9iYWxMaXN0TmFtZV0uaGFzKGRvbUVsZW1lbnQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIGBNYXBgIHRoYXQgd2lsbCBzdG9yZXMgYWxsIHRoZSBhdXRvTnVtZXJpYyBlbGVtZW50cyB0aGF0IGFyZSBpbml0aWFsaXplZCBmcm9tIHRoaXMgY3VycmVudCBlbGVtZW50LlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2NyZWF0ZUxvY2FsTGlzdCgpIHtcbiAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdCA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5fYWRkVG9Mb2NhbExpc3QodGhpcy5kb21FbGVtZW50KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbiBzb21lIHJhcmUgY2FzZXMsIHlvdSBjb3VsZCB3YW50IHRvIGRlbGV0ZSB0aGUgbG9jYWwgbGlzdCBnZW5lcmF0ZWQgZHVyaW5nIHRoZSBlbGVtZW50IGluaXRpYWxpemF0aW9uIChpbiBvcmRlciB0byB1c2UgYW5vdGhlciBvbmUgaW5zdGVhZCBmb3IgaW5zdGFuY2UpLlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2RlbGV0ZUxvY2FsTGlzdCgpIHtcbiAgICAgICAgZGVsZXRlIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3Q7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBsb2NhbCBsaXN0IHdpdGggdGhlIGdpdmVuIE1hcCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge01hcH0gbG9jYWxMaXN0XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfc2V0TG9jYWxMaXN0KGxvY2FsTGlzdCkge1xuICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0ID0gbG9jYWxMaXN0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgbG9jYWwgbGlzdCBNYXAgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHJldHVybnMgeyp8TWFwfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2dldExvY2FsTGlzdCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3Q7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGhhcyBhIGxvY2FsIGxpc3QgZGVmaW5lZCBhbHJlYWR5IGFuZCBoYXMgYXQgbGVhc3Qgb25lIGVsZW1lbnQgaW4gaXQgKGl0c2VsZiB1c3VhbGx5KS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2hhc0xvY2FsTGlzdCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QgaW5zdGFuY2VvZiBNYXAgJiYgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5zaXplICE9PSAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZCB0aGUgZ2l2ZW4gb2JqZWN0IHRvIHRoZSBsb2NhbCBhdXRvTnVtZXJpYyBlbGVtZW50IGxpc3QuXG4gICAgICogTm90ZTogaW4gb3JkZXIgdG8ga2VlcCBhIGNvaGVyZW50IGxpc3QsIHdlIG9ubHkgYWRkIERPTSBlbGVtZW50cyBpbiBpdCwgbm90IHRoZSBhdXRvTnVtZXJpYyBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR9IGRvbUVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge0F1dG9OdW1lcmljfSBhdXRvTnVtZXJpY09iamVjdCBBIHJlZmVyZW5jZSB0byB0aGUgQXV0b051bWVyaWMgb2JqZWN0IHRoYXQgbWFuYWdlIHRoZSBnaXZlbiBET00gZWxlbWVudFxuICAgICAqIEB0aHJvd3NcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9hZGRUb0xvY2FsTGlzdChkb21FbGVtZW50LCBhdXRvTnVtZXJpY09iamVjdCA9IG51bGwpIHtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChhdXRvTnVtZXJpY09iamVjdCkpIHtcbiAgICAgICAgICAgIGF1dG9OdW1lcmljT2JqZWN0ID0gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWQodGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdCkpIHtcbiAgICAgICAgICAgIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3Quc2V0KGRvbUVsZW1lbnQsIGF1dG9OdW1lcmljT2JqZWN0KTsgLy8gVXNlIHRoZSBET00gZWxlbWVudCBhcyBrZXksIGFuZCB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGFzIHRoZSB2YWx1ZVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGxvY2FsIGxpc3QgcHJvdmlkZWQgZG9lcyBub3QgZXhpc3RzIHdoZW4gdHJ5aW5nIHRvIGFkZCBhbiBlbGVtZW50LiBbJHt0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0fV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgdGhlIGdpdmVuIG9iamVjdCBmcm9tIHRoZSBsb2NhbCBhdXRvTnVtZXJpYyBlbGVtZW50IGxpc3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR9IGRvbUVsZW1lbnRcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9yZW1vdmVGcm9tTG9jYWxMaXN0KGRvbUVsZW1lbnQpIHtcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZCh0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0KSkge1xuICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5kZWxldGUoZG9tRWxlbWVudCk7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXR0aW5ncy5jcmVhdGVMb2NhbExpc3QpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBsb2NhbCBsaXN0IHByb3ZpZGVkIGRvZXMgbm90IGV4aXN0cyB3aGVuIHRyeWluZyB0byByZW1vdmUgYW4gZWxlbWVudC4gWyR7dGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdH1dIGdpdmVuLmApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWVyZ2UgdGhlIGBuZXdTZXR0aW5nc2AgZ2l2ZW4gYXMgcGFyYW1ldGVycyBpbnRvIHRoZSBjdXJyZW50IGVsZW1lbnQgc2V0dGluZ3MuXG4gICAgICpcbiAgICAgKiBXQVJOSU5HOiBVc2luZyBgT2JqZWN0LmFzc2lnbigpYCBoZXJlIG1lYW5zIHRoZSBtZXJnZSBpcyBub3QgcmVjdXJzaXZlIGFuZCBvbmx5IG9uZSBkZXB0aCBpcyBtZXJnZWQuXG4gICAgICogY2YuIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzM5MTg4MTA4LzI4MzQ4OThcbiAgICAgKiBjZi4gdGVzdHMgb24gaHR0cDovL2NvZGVwZW4uaW8vQW5vdGhlckxpbnV4VXNlci9wZW4vS2FKT1JxP2VkaXRvcnM9MDAxMVxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG5ld1NldHRpbmdzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfbWVyZ2VTZXR0aW5ncyguLi5uZXdTZXR0aW5ncykge1xuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMuc2V0dGluZ3MsIC4uLm5ld1NldHRpbmdzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYSBuZXcgb2JqZWN0IHdpdGggdGhlIGN1cnJlbnQgZWxlbWVudCBzZXR0aW5ncyBtZXJnZWQgd2l0aCB0aGUgbmV3IHNldHRpbmdzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG5ld1NldHRpbmdzXG4gICAgICogQHJldHVybnMge29iamVjdH1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9jbG9uZUFuZE1lcmdlU2V0dGluZ3MoLi4ubmV3U2V0dGluZ3MpIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0ge307XG4gICAgICAgIE9iamVjdC5hc3NpZ24ocmVzdWx0LCB0aGlzLnNldHRpbmdzLCAuLi5uZXdTZXR0aW5ncyk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBWYWxpZGF0ZSB0aGUgZ2l2ZW4gb3B0aW9uIG9iamVjdC5cbiAgICAgKiBJZiB0aGUgb3B0aW9ucyBhcmUgdmFsaWQsIHRoaXMgZnVuY3Rpb24gcmV0dXJucyBub3RoaW5nLCBvdGhlcndpc2UgaWYgdGhlIG9wdGlvbnMgYXJlIGludmFsaWQsIHRoaXMgZnVuY3Rpb24gdGhyb3dzIGFuIGVycm9yLlxuICAgICAqXG4gICAgICogVGhpcyB0ZXN0cyBpZiB0aGUgb3B0aW9ucyBhcmUgbm90IGNvbmZsaWN0aW5nIGFuZCBhcmUgd2VsbCBmb3JtYXR0ZWQuXG4gICAgICogVGhpcyBmdW5jdGlvbiBpcyBsZW5pZW50IHNpbmNlIGl0IG9ubHkgdGVzdHMgdGhlIHNldHRpbmdzIHByb3BlcnRpZXMgOyBpdCBpZ25vcmVzIGFueSBvdGhlciBwcm9wZXJ0aWVzIHRoZSBvcHRpb25zIG9iamVjdCBjb3VsZCBoYXZlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSB1c2VyT3B0aW9uc1xuICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gc2hvdWxkRXh0ZW5kRGVmYXVsdE9wdGlvbnMgSWYgYHRydWVgLCB0aGVuIHRoaXMgZnVuY3Rpb24gd2lsbCBleHRlbmRzIHRoZSBgdXNlck9wdGlvbnNgIHBhc3NlZCBieSB0aGUgdXNlciwgd2l0aCB0aGUgZGVmYXVsdCBvcHRpb25zLlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fG51bGx9IG9yaWdpbmFsT3B0aW9ucyBUaGUgdXNlciBjYW4gcGFzcyB0aGUgb3JpZ2luYWwgb3B0aW9ucyAoYW5kIG5vdCB0aGUgb25lIHRoYXQgYXJlIGdlbmVyYXRlZCBmcm9tIHRoZSBkZWZhdWx0IHNldHRpbmdzIGFuZCB0aGUgdmFyaW91cyB1c2FiaWxpdHkgY29ycmVjdGlvbnMpLCBpbiBvcmRlciB0byBhZGQgY29tcGF0aWJpbGl0eSBhbmQgY29uZmxpY3RzIGNoZWNrcy5cbiAgICAgKiBAdGhyb3dzIEVycm9yIFRoaXMgdGhyb3dzIGlmIHRoZSBgdXNlck9wdGlvbnNgIGFyZSBub3QgdmFsaWRcbiAgICAgKi9cbiAgICBzdGF0aWMgdmFsaWRhdGUodXNlck9wdGlvbnMsIHNob3VsZEV4dGVuZERlZmF1bHRPcHRpb25zID0gdHJ1ZSwgb3JpZ2luYWxPcHRpb25zID0gbnVsbCkge1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KHVzZXJPcHRpb25zKSB8fCAhQXV0b051bWVyaWNIZWxwZXIuaXNPYmplY3QodXNlck9wdGlvbnMpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgdXNlck9wdGlvbnMgYXJlIGludmFsaWQgOyBpdCBzaG91bGQgYmUgYSB2YWxpZCBvYmplY3QsIFske3VzZXJPcHRpb25zfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBpc09yaWdpbmFsT3B0aW9uQW5PYmplY3QgPSBBdXRvTnVtZXJpY0hlbHBlci5pc09iamVjdChvcmlnaW5hbE9wdGlvbnMpO1xuICAgICAgICBpZiAoIWlzT3JpZ2luYWxPcHRpb25Bbk9iamVjdCAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9yaWdpbmFsT3B0aW9ucykpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSAnb3JpZ2luYWxPcHRpb25zJyBwYXJhbWV0ZXIgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBlaXRoZXIgYmUgYSB2YWxpZCBvcHRpb24gb2JqZWN0IG9yIFxcYG51bGxcXGAsIFske3VzZXJPcHRpb25zfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB0aGUgdXNlciB1c2VkIG9sZCBvcHRpb25zLCB3ZSBjb252ZXJ0IHRoZW0gdG8gbmV3IG9uZXNcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwodXNlck9wdGlvbnMpKSB7XG4gICAgICAgICAgICB0aGlzLl9jb252ZXJ0T2xkT3B0aW9uc1RvTmV3T25lcyh1c2VyT3B0aW9ucyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUaGUgdXNlciBjYW4gY2hvb3NlIGlmIHRoZSBgdXNlck9wdGlvbnNgIGhhcyBhbHJlYWR5IGJlZW4gZXh0ZW5kZWQgd2l0aCB0aGUgZGVmYXVsdCBvcHRpb25zLCBvciBub3RcbiAgICAgICAgbGV0IG9wdGlvbnM7XG4gICAgICAgIGlmIChzaG91bGRFeHRlbmREZWZhdWx0T3B0aW9ucykge1xuICAgICAgICAgICAgb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oe30sIHRoaXMuZ2V0RGVmYXVsdENvbmZpZygpLCB1c2VyT3B0aW9ucyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvcHRpb25zID0gdXNlck9wdGlvbnM7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBGaXJzdCB0aGluZ3MgZmlyc3QsIHdlIHRlc3QgdGhhdCB0aGUgYHNob3dXYXJuaW5nc2Agb3B0aW9uIGlzIHZhbGlkXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLnNob3dXYXJuaW5ncykgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLnNob3dXYXJuaW5ncykpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBkZWJ1ZyBvcHRpb24gJ3Nob3dXYXJuaW5ncycgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBlaXRoZXIgJ2ZhbHNlJyBvciAndHJ1ZScsIFske29wdGlvbnMuc2hvd1dhcm5pbmdzfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEZWZpbmUgdGhlIHJlZ3VsYXIgZXhwcmVzc2lvbnMgbmVlZGVkIGZvciB0aGUgZm9sbG93aW5nIHRlc3RzXG4gICAgICAgIGNvbnN0IHRlc3RQb3NpdGl2ZUludGVnZXIgPSAvXlswLTldKyQvO1xuICAgICAgICBjb25zdCB0ZXN0TnVtZXJpY2FsQ2hhcmFjdGVycyA9IC9bMC05XSsvO1xuICAgICAgICAvLyBjb25zdCB0ZXN0RmxvYXRBbmRQb3NzaWJsZU5lZ2F0aXZlU2lnbiA9IC9eLT9bMC05XSsoXFwuP1swLTldKykkLztcbiAgICAgICAgY29uc3QgdGVzdEZsb2F0T3JJbnRlZ2VyQW5kUG9zc2libGVOZWdhdGl2ZVNpZ24gPSAvXi0/WzAtOV0rKFxcLj9bMC05XSspPyQvO1xuICAgICAgICBjb25zdCB0ZXN0UG9zaXRpdmVGbG9hdE9ySW50ZWdlciA9IC9eWzAtOV0rKFxcLj9bMC05XSspPyQvO1xuXG4gICAgICAgIC8vIFRoZW4gdGVzdHMgdGhlIG9wdGlvbnMgaW5kaXZpZHVhbGx5XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmcpICYmXG4gICAgICAgICAgICAhQXV0b051bWVyaWNIZWxwZXIuaXNCb29sZWFuKG9wdGlvbnMuYWxsb3dEZWNpbWFsUGFkZGluZykgJiZcbiAgICAgICAgICAgIG9wdGlvbnMuYWxsb3dEZWNpbWFsUGFkZGluZyAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5hbGxvd0RlY2ltYWxQYWRkaW5nLmZsb2F0cykge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGRlY2ltYWwgcGFkZGluZyBvcHRpb24gJ2FsbG93RGVjaW1hbFBhZGRpbmcnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgZWl0aGVyIGJlIFxcYGZhbHNlXFxgLCBcXGB0cnVlXFxgIG9yIFxcYCdmbG9hdHMnXFxgLCBbJHtvcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmd9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgob3B0aW9ucy5hbGxvd0RlY2ltYWxQYWRkaW5nID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmcubmV2ZXIgfHxcbiAgICAgICAgICAgIG9wdGlvbnMuYWxsb3dEZWNpbWFsUGFkZGluZyA9PT0gJ2ZhbHNlJykgJiZcbiAgICAgICAgICAgIChvcHRpb25zLmRlY2ltYWxQbGFjZXMgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbFBsYWNlcy5ub25lIHx8XG4gICAgICAgICAgICBvcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIubm9uZSB8fFxuICAgICAgICAgICAgb3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMubm9uZSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLndhcm5pbmcoYFNldHRpbmcgJ2FsbG93RGVjaW1hbFBhZGRpbmcnIHRvIFske29wdGlvbnMuYWxsb3dEZWNpbWFsUGFkZGluZ31dIHdpbGwgb3ZlcnJpZGUgdGhlIGN1cnJlbnQgJ2RlY2ltYWxQbGFjZXMqJyBzZXR0aW5ncyBbJHtvcHRpb25zLmRlY2ltYWxQbGFjZXN9LCAke29wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyfSBhbmQgJHtvcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXN9XS5gLCBvcHRpb25zLnNob3dXYXJuaW5ncyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVHJ1ZU9yRmFsc2VTdHJpbmcob3B0aW9ucy5hbHdheXNBbGxvd0RlY2ltYWxDaGFyYWN0ZXIpICYmXG4gICAgICAgICAgICAhQXV0b051bWVyaWNIZWxwZXIuaXNCb29sZWFuKG9wdGlvbnMuYWx3YXlzQWxsb3dEZWNpbWFsQ2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIG9wdGlvbiAnYWx3YXlzQWxsb3dEZWNpbWFsQ2hhcmFjdGVyJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGVpdGhlciBiZSBcXGB0cnVlXFxgIG9yIFxcYGZhbHNlXFxgLCBbJHtvcHRpb25zLmFsd2F5c0FsbG93RGVjaW1hbENoYXJhY3Rlcn1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1cykgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzSW5BcnJheShvcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLCBbXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLnN0YXJ0LFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1cy5lbmQsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLmRlY2ltYWxMZWZ0LFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1cy5kZWNpbWFsUmlnaHQsXG4gICAgICAgIF0pKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZGlzcGxheSBvbiBlbXB0eSBzdHJpbmcgb3B0aW9uICdjYXJldFBvc2l0aW9uT25Gb2N1cycgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBlaXRoZXIgYmUgXFxgbnVsbFxcYCwgJ2ZvY3VzJywgJ3ByZXNzJywgJ2Fsd2F5cycgb3IgJ3plcm8nLCBbJHtvcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTcGVjaWFsIGNhc2UgaGVyZSBmb3IgYGNhcmV0UG9zaXRpb25PbkZvY3VzYCBhbmQgYHNlbGVjdE9uRm9jdXNgIHdoZXJlIHdlIG5lZWQgdG8gY2hlY2sgdGhlIG9yaWdpbmFsIG5vbi10ZW1wZXJlZCB2ZXJzaW9uIG9mIHRoZSBvcHRpb25zIGluIG9yZGVyIHRvIGNoZWNrIGZvciBjb25mbGljdHMsIHNpbmNlIHVzaW5nIHRoZSBkZWZhdWx0IHNldHRpbmdzIHJlbW92ZSB0aG9zZSBhbmQgd291bGQgcHJldmVudCB1cyB3YXJuaW5nIHRoZSB1c2VyIHRoYXQgaGlzIG9wdGlvbiBvYmplY3QgaXMgbm90IGNvcnJlY3QuXG4gICAgICAgIGxldCBvcHRpb25zVG9Vc2U7XG4gICAgICAgIGlmIChpc09yaWdpbmFsT3B0aW9uQW5PYmplY3QpIHtcbiAgICAgICAgICAgIG9wdGlvbnNUb1VzZSA9IG9yaWdpbmFsT3B0aW9ucztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG9wdGlvbnNUb1VzZSA9IHRoaXMuX2NvcnJlY3RDYXJldFBvc2l0aW9uT25Gb2N1c0FuZFNlbGVjdE9uRm9jdXNPcHRpb25zKHVzZXJPcHRpb25zKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnNUb1VzZSkgJiZcbiAgICAgICAgICAgICgob3B0aW9uc1RvVXNlLmNhcmV0UG9zaXRpb25PbkZvY3VzICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLmRvTm9Gb3JjZUNhcmV0UG9zaXRpb24gJiZcbiAgICAgICAgICAgIG9wdGlvbnNUb1VzZS5zZWxlY3RPbkZvY3VzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLnNlbGVjdE9uRm9jdXMuc2VsZWN0KSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLndhcm5pbmcoYFRoZSAnc2VsZWN0T25Gb2N1cycgb3B0aW9uIGlzIHNldCB0byAnc2VsZWN0Jywgd2hpY2ggaXMgaW4gY29uZmxpY3Qgd2l0aCB0aGUgJ2NhcmV0UG9zaXRpb25PbkZvY3VzJyB3aGljaCBpcyBzZXQgdG8gJyR7b3B0aW9uc1RvVXNlLmNhcmV0UG9zaXRpb25PbkZvY3VzfScuIEFzIGEgcmVzdWx0LCBpZiB0aGlzIGhhcyBiZWVuIGNhbGxlZCB3aGVuIGluc3RhbnRpYXRpbmcgYW4gQXV0b051bWVyaWMgb2JqZWN0LCB0aGUgJ3NlbGVjdE9uRm9jdXMnIG9wdGlvbiBpcyBmb3JjZWQgdG8gJ2RvTm90U2VsZWN0Jy5gLCBvcHRpb25zLnNob3dXYXJuaW5ncyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzSW5BcnJheShvcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3IsIFtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci5jb21tYSxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci5kb3QsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3Iubm9ybWFsU3BhY2UsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3IudGhpblNwYWNlLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLm5hcnJvd05vQnJlYWtTcGFjZSxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci5ub0JyZWFrU3BhY2UsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3Iubm9TZXBhcmF0b3IsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3IuYXBvc3Ryb3BoZSxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci5hcmFiaWNUaG91c2FuZHNTZXBhcmF0b3IsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3IuZG90QWJvdmUsXG4gICAgICAgIF0pKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgdGhvdXNhbmQgc2VwYXJhdG9yIGNoYXJhY3RlciBvcHRpb24gJ2RpZ2l0R3JvdXBTZXBhcmF0b3InIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgJywnLCAnLicsICfZrCcsICfLmScsIFwiJ1wiLCAnICcsICdcXHUyMDA5JywgJ1xcdTIwMmYnLCAnXFx1MDBhMCcgb3IgZW1wdHkgKCcnKSwgWyR7b3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVHJ1ZU9yRmFsc2VTdHJpbmcob3B0aW9ucy5zaG93T25seU51bWJlcnNPbkZvY3VzKSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNCb29sZWFuKG9wdGlvbnMuc2hvd09ubHlOdW1iZXJzT25Gb2N1cykpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSAnc2hvd09ubHlOdW1iZXJzT25Gb2N1cycgb3B0aW9uIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLnNob3dPbmx5TnVtYmVyc09uRm9jdXN9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KG9wdGlvbnMuZGlnaXRhbEdyb3VwU3BhY2luZywgW1xuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdGFsR3JvdXBTcGFjaW5nLnR3byxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRhbEdyb3VwU3BhY2luZy50d29TY2FsZWQsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0YWxHcm91cFNwYWNpbmcudGhyZWUsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0YWxHcm91cFNwYWNpbmcuZm91cixcbiAgICAgICAgXSkgJiYgIShvcHRpb25zLmRpZ2l0YWxHcm91cFNwYWNpbmcgPj0gMiAmJiBvcHRpb25zLmRpZ2l0YWxHcm91cFNwYWNpbmcgPD0gNCkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBncm91cGluZyBzZXBhcmF0b3Igb3B0aW9uIGZvciB0aG91c2FuZHMgJ2RpZ2l0YWxHcm91cFNwYWNpbmcnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgJzInLCAnMnMnLCAnMycsIG9yICc0JywgWyR7b3B0aW9ucy5kaWdpdGFsR3JvdXBTcGFjaW5nfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzSW5BcnJheShvcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXIsIFtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3Rlci5jb21tYSxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3Rlci5kb3QsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXIubWlkZGxlRG90LFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyLmFyYWJpY0RlY2ltYWxTZXBhcmF0b3IsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXIuZGVjaW1hbFNlcGFyYXRvcktleVN5bWJvbCxcbiAgICAgICAgXSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBkZWNpbWFsIHNlcGFyYXRvciBjaGFyYWN0ZXIgb3B0aW9uICdkZWNpbWFsQ2hhcmFjdGVyJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlICcuJywgJywnLCAnwrcnLCAn4o6WJyBvciAn2asnLCBbJHtvcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXJ9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENoZWNrcyBpZiB0aGUgZGVjaW1hbCBhbmQgdGhvdXNhbmQgY2hhcmFjdGVycyBhcmUgdGhlIHNhbWVcbiAgICAgICAgaWYgKG9wdGlvbnMuZGVjaW1hbENoYXJhY3RlciA9PT0gb3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBhdXRvTnVtZXJpYyB3aWxsIG5vdCBmdW5jdGlvbiBwcm9wZXJseSB3aGVuIHRoZSBkZWNpbWFsIGNoYXJhY3RlciAnZGVjaW1hbENoYXJhY3RlcicgWyR7b3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyfV0gYW5kIHRoZSB0aG91c2FuZCBzZXBhcmF0b3IgJ2RpZ2l0R3JvdXBTZXBhcmF0b3InIFske29wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvcn1dIGFyZSB0aGUgc2FtZSBjaGFyYWN0ZXIuYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZSkgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzU3RyaW5nKG9wdGlvbnMuZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGFsdGVybmF0ZSBkZWNpbWFsIHNlcGFyYXRvciBjaGFyYWN0ZXIgb3B0aW9uICdkZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgYSBzdHJpbmcsIFske29wdGlvbnMuZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAob3B0aW9ucy5jdXJyZW5jeVN5bWJvbCAhPT0gJycgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzU3RyaW5nKG9wdGlvbnMuY3VycmVuY3lTeW1ib2wpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgY3VycmVuY3kgc3ltYm9sIG9wdGlvbiAnY3VycmVuY3lTeW1ib2wnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgYSBzdHJpbmcsIFske29wdGlvbnMuY3VycmVuY3lTeW1ib2x9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KG9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQsIFtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQucHJlZml4LFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5zdWZmaXgsXG4gICAgICAgIF0pKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgcGxhY2VtZW50IG9mIHRoZSBjdXJyZW5jeSBzaWduIG9wdGlvbiAnY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgZWl0aGVyIGJlICdwJyAocHJlZml4KSBvciAncycgKHN1ZmZpeCksIFske29wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnR9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KG9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQsIFtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4LFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5zdWZmaXgsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LmxlZnQsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnJpZ2h0LFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5ub25lLFxuICAgICAgICBdKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHBsYWNlbWVudCBvZiB0aGUgbmVnYXRpdmUgc2lnbiBvcHRpb24gJ25lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50JyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGVpdGhlciBiZSAncCcgKHByZWZpeCksICdzJyAoc3VmZml4KSwgJ2wnIChsZWZ0KSwgJ3InIChyaWdodCkgb3IgJ251bGwnLCBbJHtvcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50fV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVHJ1ZU9yRmFsc2VTdHJpbmcob3B0aW9ucy5zaG93UG9zaXRpdmVTaWduKSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNCb29sZWFuKG9wdGlvbnMuc2hvd1Bvc2l0aXZlU2lnbikpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBzaG93IHBvc2l0aXZlIHNpZ24gb3B0aW9uICdzaG93UG9zaXRpdmVTaWduJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGVpdGhlciAnZmFsc2UnIG9yICd0cnVlJywgWyR7b3B0aW9ucy5zaG93UG9zaXRpdmVTaWdufV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzU3RyaW5nKG9wdGlvbnMuc3VmZml4VGV4dCkgfHwgKG9wdGlvbnMuc3VmZml4VGV4dCAhPT0gJycgJiYgKEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmUob3B0aW9ucy5zdWZmaXhUZXh0LCBvcHRpb25zLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikgfHwgdGVzdE51bWVyaWNhbENoYXJhY3RlcnMudGVzdChvcHRpb25zLnN1ZmZpeFRleHQpKSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBhZGRpdGlvbmFsIHN1ZmZpeCBvcHRpb24gJ3N1ZmZpeFRleHQnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgbm90IGNvbnRhaW5zIHRoZSBuZWdhdGl2ZSBzaWduICcke29wdGlvbnMubmVnYXRpdmVTaWduQ2hhcmFjdGVyfScgbm9yIGFueSBudW1lcmljYWwgY2hhcmFjdGVycywgWyR7b3B0aW9ucy5zdWZmaXhUZXh0fV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzU3RyaW5nKG9wdGlvbnMubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSB8fFxuICAgICAgICAgICAgb3B0aW9ucy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIubGVuZ3RoICE9PSAxIHx8XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkob3B0aW9ucy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpIHx8XG4gICAgICAgICAgICB0ZXN0TnVtZXJpY2FsQ2hhcmFjdGVycy50ZXN0KG9wdGlvbnMubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIG5lZ2F0aXZlIHNpZ24gY2hhcmFjdGVyIG9wdGlvbiAnbmVnYXRpdmVTaWduQ2hhcmFjdGVyJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGEgc2luZ2xlIGNoYXJhY3RlciwgYW5kIGNhbm5vdCBiZSBhbnkgbnVtZXJpY2FsIGNoYXJhY3RlcnMsIFske29wdGlvbnMubmVnYXRpdmVTaWduQ2hhcmFjdGVyfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzU3RyaW5nKG9wdGlvbnMucG9zaXRpdmVTaWduQ2hhcmFjdGVyKSB8fFxuICAgICAgICAgICAgb3B0aW9ucy5wb3NpdGl2ZVNpZ25DaGFyYWN0ZXIubGVuZ3RoICE9PSAxIHx8XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkob3B0aW9ucy5wb3NpdGl2ZVNpZ25DaGFyYWN0ZXIpIHx8XG4gICAgICAgICAgICB0ZXN0TnVtZXJpY2FsQ2hhcmFjdGVycy50ZXN0KG9wdGlvbnMucG9zaXRpdmVTaWduQ2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHBvc2l0aXZlIHNpZ24gY2hhcmFjdGVyIG9wdGlvbiAncG9zaXRpdmVTaWduQ2hhcmFjdGVyJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGEgc2luZ2xlIGNoYXJhY3RlciwgYW5kIGNhbm5vdCBiZSBhbnkgbnVtZXJpY2FsIGNoYXJhY3RlcnMsIFske29wdGlvbnMucG9zaXRpdmVTaWduQ2hhcmFjdGVyfV0gZ2l2ZW4uXFxuSWYgeW91IHdhbnQgdG8gaGlkZSB0aGUgcG9zaXRpdmUgc2lnbiBjaGFyYWN0ZXIsIHlvdSBuZWVkIHRvIHNldCB0aGUgXFxgc2hvd1Bvc2l0aXZlU2lnblxcYCBvcHRpb24gdG8gXFxgdHJ1ZVxcYC5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvcHRpb25zLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciA9PT0gb3B0aW9ucy5wb3NpdGl2ZVNpZ25DaGFyYWN0ZXIpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBwb3NpdGl2ZSAncG9zaXRpdmVTaWduQ2hhcmFjdGVyJyBhbmQgbmVnYXRpdmUgJ25lZ2F0aXZlU2lnbkNoYXJhY3Rlcicgc2lnbiBjaGFyYWN0ZXJzIGNhbm5vdCBiZSBpZGVudGljYWwgOyBbJHtvcHRpb25zLm5lZ2F0aXZlU2lnbkNoYXJhY3Rlcn1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgW2xlZnRCcmFja2V0LCByaWdodEJyYWNrZXRdID0gQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIpP1snJywgJyddOm9wdGlvbnMubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIuc3BsaXQoJywnKTtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmNvbnRhaW5zKG9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvciwgb3B0aW9ucy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpIHx8XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyhvcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXIsIG9wdGlvbnMubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSB8fFxuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMob3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUsIG9wdGlvbnMubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSB8fFxuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMobGVmdEJyYWNrZXQsIG9wdGlvbnMubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSB8fFxuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMocmlnaHRCcmFja2V0LCBvcHRpb25zLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikgfHxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLmNvbnRhaW5zKG9wdGlvbnMuc3VmZml4VGV4dCwgb3B0aW9ucy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgbmVnYXRpdmUgc2lnbiBjaGFyYWN0ZXIgb3B0aW9uICduZWdhdGl2ZVNpZ25DaGFyYWN0ZXInIGlzIGludmFsaWQgOyBpdCBzaG91bGQgbm90IGJlIGVxdWFsIG9yIGEgcGFydCBvZiB0aGUgZGlnaXQgc2VwYXJhdG9yLCB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIsIHRoZSBkZWNpbWFsIGNoYXJhY3RlciBhbHRlcm5hdGl2ZSwgdGhlIG5lZ2F0aXZlIGJyYWNrZXRzIG9yIHRoZSBzdWZmaXggdGV4dCwgWyR7b3B0aW9ucy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXJ9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyhvcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3IsIG9wdGlvbnMucG9zaXRpdmVTaWduQ2hhcmFjdGVyKSB8fFxuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMob3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyLCBvcHRpb25zLnBvc2l0aXZlU2lnbkNoYXJhY3RlcikgfHxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLmNvbnRhaW5zKG9wdGlvbnMuZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlLCBvcHRpb25zLnBvc2l0aXZlU2lnbkNoYXJhY3RlcikgfHxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLmNvbnRhaW5zKGxlZnRCcmFja2V0LCBvcHRpb25zLnBvc2l0aXZlU2lnbkNoYXJhY3RlcikgfHxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLmNvbnRhaW5zKHJpZ2h0QnJhY2tldCwgb3B0aW9ucy5wb3NpdGl2ZVNpZ25DaGFyYWN0ZXIpIHx8XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyhvcHRpb25zLnN1ZmZpeFRleHQsIG9wdGlvbnMucG9zaXRpdmVTaWduQ2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHBvc2l0aXZlIHNpZ24gY2hhcmFjdGVyIG9wdGlvbiAncG9zaXRpdmVTaWduQ2hhcmFjdGVyJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIG5vdCBiZSBlcXVhbCBvciBhIHBhcnQgb2YgdGhlIGRpZ2l0IHNlcGFyYXRvciwgdGhlIGRlY2ltYWwgY2hhcmFjdGVyLCB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgYWx0ZXJuYXRpdmUsIHRoZSBuZWdhdGl2ZSBicmFja2V0cyBvciB0aGUgc3VmZml4IHRleHQsIFske29wdGlvbnMucG9zaXRpdmVTaWduQ2hhcmFjdGVyfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zLm92ZXJyaWRlTWluTWF4TGltaXRzKSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KG9wdGlvbnMub3ZlcnJpZGVNaW5NYXhMaW1pdHMsIFtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMub3ZlcnJpZGVNaW5NYXhMaW1pdHMuY2VpbGluZyxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMub3ZlcnJpZGVNaW5NYXhMaW1pdHMuZmxvb3IsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm92ZXJyaWRlTWluTWF4TGltaXRzLmlnbm9yZSxcbiAgICAgICAgXSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBvdmVycmlkZSBtaW4gJiBtYXggbGltaXRzIG9wdGlvbiAnb3ZlcnJpZGVNaW5NYXhMaW1pdHMnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgZWl0aGVyIGJlICdjZWlsaW5nJywgJ2Zsb29yJyBvciAnaWdub3JlJywgWyR7b3B0aW9ucy5vdmVycmlkZU1pbk1heExpbWl0c31dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1N0cmluZyhvcHRpb25zLm1heGltdW1WYWx1ZSkgfHwgIXRlc3RGbG9hdE9ySW50ZWdlckFuZFBvc3NpYmxlTmVnYXRpdmVTaWduLnRlc3Qob3B0aW9ucy5tYXhpbXVtVmFsdWUpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgbWF4aW11bSBwb3NzaWJsZSB2YWx1ZSBvcHRpb24gJ21heGltdW1WYWx1ZScgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBhIHN0cmluZyB0aGF0IHJlcHJlc2VudHMgYSBwb3NpdGl2ZSBvciBuZWdhdGl2ZSBudW1iZXIsIFske29wdGlvbnMubWF4aW11bVZhbHVlfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzU3RyaW5nKG9wdGlvbnMubWluaW11bVZhbHVlKSB8fCAhdGVzdEZsb2F0T3JJbnRlZ2VyQW5kUG9zc2libGVOZWdhdGl2ZVNpZ24udGVzdChvcHRpb25zLm1pbmltdW1WYWx1ZSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBtaW5pbXVtIHBvc3NpYmxlIHZhbHVlIG9wdGlvbiAnbWluaW11bVZhbHVlJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGEgc3RyaW5nIHRoYXQgcmVwcmVzZW50cyBhIHBvc2l0aXZlIG9yIG5lZ2F0aXZlIG51bWJlciwgWyR7b3B0aW9ucy5taW5pbXVtVmFsdWV9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwYXJzZUZsb2F0KG9wdGlvbnMubWluaW11bVZhbHVlKSA+IHBhcnNlRmxvYXQob3B0aW9ucy5tYXhpbXVtVmFsdWUpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgbWluaW11bSBwb3NzaWJsZSB2YWx1ZSBvcHRpb24gaXMgZ3JlYXRlciB0aGFuIHRoZSBtYXhpbXVtIHBvc3NpYmxlIHZhbHVlIG9wdGlvbiA7ICdtaW5pbXVtVmFsdWUnIFske29wdGlvbnMubWluaW11bVZhbHVlfV0gc2hvdWxkIGJlIHNtYWxsZXIgdGhhbiAnbWF4aW11bVZhbHVlJyBbJHtvcHRpb25zLm1heGltdW1WYWx1ZX1dLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEoKEF1dG9OdW1lcmljSGVscGVyLmlzSW50KG9wdGlvbnMuZGVjaW1hbFBsYWNlcykgJiYgb3B0aW9ucy5kZWNpbWFsUGxhY2VzID49IDApIHx8IC8vIElmIGludGVnZXIgb3B0aW9uXG4gICAgICAgICAgICAoQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcob3B0aW9ucy5kZWNpbWFsUGxhY2VzKSAmJiB0ZXN0UG9zaXRpdmVJbnRlZ2VyLnRlc3Qob3B0aW9ucy5kZWNpbWFsUGxhY2VzKSkpIC8vIElmIHN0cmluZyBvcHRpb25cbiAgICAgICAgKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIG9wdGlvbiAnZGVjaW1hbFBsYWNlcycgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBhIHBvc2l0aXZlIGludGVnZXIsIFske29wdGlvbnMuZGVjaW1hbFBsYWNlc31dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlKSB8fFxuICAgICAgICAgICAgKEF1dG9OdW1lcmljSGVscGVyLmlzSW50KG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlKSAmJiBvcHRpb25zLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA+PSAwKSB8fCAvLyBJZiBpbnRlZ2VyIG9wdGlvblxuICAgICAgICAgICAgKEF1dG9OdW1lcmljSGVscGVyLmlzU3RyaW5nKG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlKSAmJiB0ZXN0UG9zaXRpdmVJbnRlZ2VyLnRlc3Qob3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUpKSkgLy8gSWYgc3RyaW5nIG9wdGlvblxuICAgICAgICApIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgZm9yIHRoZSByYXcgdmFsdWUgb3B0aW9uICdkZWNpbWFsUGxhY2VzUmF3VmFsdWUnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgYSBwb3NpdGl2ZSBpbnRlZ2VyIG9yIFxcYG51bGxcXGAsIFske29wdGlvbnMuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVja3MgaWYgdGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyBmb3IgdGhlIHJhdyB2YWx1ZSBpcyBsb3dlciB0aGFuIHRoZSBgZGVjaW1hbFBsYWNlc2AsIGBkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzYCBhbmQvb3IgYGRlY2ltYWxQbGFjZXNTaG93bk9uQmx1cmAgb3B0aW9uc1xuICAgICAgICB0aGlzLl92YWxpZGF0ZURlY2ltYWxQbGFjZXNSYXdWYWx1ZShvcHRpb25zKTtcblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMpICYmXG4gICAgICAgICAgICAhdGVzdFBvc2l0aXZlSW50ZWdlci50ZXN0KFN0cmluZyhvcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMpKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIG51bWJlciBvZiBleHBhbmRlZCBkZWNpbWFsIHBsYWNlcyBvcHRpb24gJ2RlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgYSBwb3NpdGl2ZSBpbnRlZ2VyIG9yIFxcYG51bGxcXGAsIFske29wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1c31dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2tzIGlmIHRoZSBleHRlbmRlZCBkZWNpbWFsIHBsYWNlcyBcImRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXNcIiBpcyBncmVhdGVyIHRoYW4gdGhlIGRlY2ltYWwgcGxhY2VzIG51bWJlciBgZGVjaW1hbFBsYWNlc2BcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzKSAmJiBOdW1iZXIob3B0aW9ucy5kZWNpbWFsUGxhY2VzKSA+IE51bWJlcihvcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKGBUaGUgZXh0ZW5kZWQgZGVjaW1hbCBwbGFjZXMgJ2RlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMnIFske29wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1c31dIHNob3VsZCBiZSBncmVhdGVyIHRoYW4gdGhlICdkZWNpbWFsUGxhY2VzJyBbJHtvcHRpb25zLmRlY2ltYWxQbGFjZXN9XSB2YWx1ZS4gQ3VycmVudGx5LCB0aGlzIHdpbGwgbGltaXQgdGhlIGFiaWxpdHkgb2YgeW91ciB1c2VyIHRvIG1hbnVhbGx5IGNoYW5nZSBzb21lIG9mIHRoZSBkZWNpbWFsIHBsYWNlcy4gRG8geW91IHJlYWxseSB3YW50IHRvIGRvIHRoYXQ/YCwgb3B0aW9ucy5zaG93V2FybmluZ3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucy5kaXZpc29yV2hlblVuZm9jdXNlZCkgJiZcbiAgICAgICAgICAgICF0ZXN0UG9zaXRpdmVGbG9hdE9ySW50ZWdlci50ZXN0KG9wdGlvbnMuZGl2aXNvcldoZW5VbmZvY3VzZWQpIHx8XG4gICAgICAgICAgICBvcHRpb25zLmRpdmlzb3JXaGVuVW5mb2N1c2VkID09PSAwIHx8IG9wdGlvbnMuZGl2aXNvcldoZW5VbmZvY3VzZWQgPT09ICcwJyB8fFxuICAgICAgICAgICAgb3B0aW9ucy5kaXZpc29yV2hlblVuZm9jdXNlZCA9PT0gMSB8fCBvcHRpb25zLmRpdmlzb3JXaGVuVW5mb2N1c2VkID09PSAnMScpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBkaXZpc29yIG9wdGlvbiAnZGl2aXNvcldoZW5VbmZvY3VzZWQnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgYSBwb3NpdGl2ZSBudW1iZXIgaGlnaGVyIHRoYW4gb25lLCBwcmVmZXJhYmx5IGFuIGludGVnZXIsIFske29wdGlvbnMuZGl2aXNvcldoZW5VbmZvY3VzZWR9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyKSAmJiAhdGVzdFBvc2l0aXZlSW50ZWdlci50ZXN0KG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIG51bWJlciBvZiBkZWNpbWFscyBzaG93biB3aGVuIHVuZm9jdXNlZCBvcHRpb24gJ2RlY2ltYWxQbGFjZXNTaG93bk9uQmx1cicgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBhIHBvc2l0aXZlIGludGVnZXIgb3IgXFxgbnVsbFxcYCwgWyR7b3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXJ9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMuc3ltYm9sV2hlblVuZm9jdXNlZCkgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzU3RyaW5nKG9wdGlvbnMuc3ltYm9sV2hlblVuZm9jdXNlZCkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBzeW1ib2wgdG8gc2hvdyB3aGVuIHVuZm9jdXNlZCBvcHRpb24gJ3N5bWJvbFdoZW5VbmZvY3VzZWQnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgYSBzdHJpbmcsIFske29wdGlvbnMuc3ltYm9sV2hlblVuZm9jdXNlZH1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1RydWVPckZhbHNlU3RyaW5nKG9wdGlvbnMuc2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZSkgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLnNhdmVWYWx1ZVRvU2Vzc2lvblN0b3JhZ2UpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgc2F2ZSB0byBzZXNzaW9uIHN0b3JhZ2Ugb3B0aW9uICdzYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGVpdGhlciAnZmFsc2UnIG9yICd0cnVlJywgWyR7b3B0aW9ucy5zYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzSW5BcnJheShvcHRpb25zLm9uSW52YWxpZFBhc3RlLCBbXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLmVycm9yLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS5pZ25vcmUsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLmNsYW1wLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS50cnVuY2F0ZSxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUucmVwbGFjZSxcbiAgICAgICAgXSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBwYXN0ZSBiZWhhdmlvciBvcHRpb24gJ29uSW52YWxpZFBhc3RlJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGVpdGhlciBiZSAnZXJyb3InLCAnaWdub3JlJywgJ2NsYW1wJywgJ3RydW5jYXRlJyBvciAncmVwbGFjZScgKGNmLiBkb2N1bWVudGF0aW9uKSwgWyR7b3B0aW9ucy5vbkludmFsaWRQYXN0ZX1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc0luQXJyYXkob3B0aW9ucy5yb3VuZGluZ01ldGhvZCwgW1xuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC5oYWxmVXBTeW1tZXRyaWMsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmhhbGZVcEFzeW1tZXRyaWMsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmhhbGZEb3duU3ltbWV0cmljLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC5oYWxmRG93bkFzeW1tZXRyaWMsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmhhbGZFdmVuQmFua2Vyc1JvdW5kaW5nLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC51cFJvdW5kQXdheUZyb21aZXJvLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC5kb3duUm91bmRUb3dhcmRaZXJvLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC50b0NlaWxpbmdUb3dhcmRQb3NpdGl2ZUluZmluaXR5LFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC50b0Zsb29yVG93YXJkTmVnYXRpdmVJbmZpbml0eSxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QudG9OZWFyZXN0MDUsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLnRvTmVhcmVzdDA1QWx0LFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC51cFRvTmV4dDA1LFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC5kb3duVG9OZXh0MDUsXG4gICAgICAgIF0pKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgcm91bmRpbmcgbWV0aG9kIG9wdGlvbiAncm91bmRpbmdNZXRob2QnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgZWl0aGVyIGJlICdTJywgJ0EnLCAncycsICdhJywgJ0InLCAnVScsICdEJywgJ0MnLCAnRicsICdOMDUnLCAnQ0hGJywgJ1UwNScgb3IgJ0QwNScgKGNmLiBkb2N1bWVudGF0aW9uKSwgWyR7b3B0aW9ucy5yb3VuZGluZ01ldGhvZH1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1cikgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzSW5BcnJheShvcHRpb25zLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyLCBbXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyLnBhcmVudGhlc2VzLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ci5icmFja2V0cyxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIuY2hldnJvbnMsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyLmN1cmx5QnJhY2VzLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ci5hbmdsZUJyYWNrZXRzLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ci5qYXBhbmVzZVF1b3RhdGlvbk1hcmtzLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ci5oYWxmQnJhY2tldHMsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyLndoaXRlU3F1YXJlQnJhY2tldHMsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyLnF1b3RhdGlvbk1hcmtzLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ci5ndWlsbGVtZXRzLFxuICAgICAgICBdKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGJyYWNrZXRzIGZvciBuZWdhdGl2ZSB2YWx1ZXMgb3B0aW9uICduZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1cicgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBlaXRoZXIgYmUgJygsKScsICdbLF0nLCAnPCw+JywgJ3ssfScsICfjgIgs44CJJywgJ++9oizvvaMnLCAn4rikLOK4pScsICfin6Ys4p+nJywgJ+KAuSzigLonIG9yICfCqyzCuycsIFske29wdGlvbnMubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXJ9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghKEF1dG9OdW1lcmljSGVscGVyLmlzU3RyaW5nKG9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yKSB8fCBBdXRvTnVtZXJpY0hlbHBlci5pc051bWJlcihvcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvcikpIHx8XG4gICAgICAgICAgICAhKEF1dG9OdW1lcmljSGVscGVyLmlzSW5BcnJheShvcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvciwgW1xuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLmZvY3VzLFxuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLnByZXNzLFxuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLmFsd2F5cyxcbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5taW4sXG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IubWF4LFxuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLnplcm8sXG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IubnVsbCxcbiAgICAgICAgICAgIF0pIHx8IHRlc3RGbG9hdE9ySW50ZWdlckFuZFBvc3NpYmxlTmVnYXRpdmVTaWduLnRlc3Qob3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IpKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGRpc3BsYXkgb24gZW1wdHkgc3RyaW5nIG9wdGlvbiAnZW1wdHlJbnB1dEJlaGF2aW9yJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGVpdGhlciBiZSAnZm9jdXMnLCAncHJlc3MnLCAnYWx3YXlzJywgJ21pbicsICdtYXgnLCAnemVybycsICdudWxsJywgYSBudW1iZXIsIG9yIGEgc3RyaW5nIHRoYXQgcmVwcmVzZW50cyBhIG51bWJlciwgWyR7b3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3J9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvciA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IuemVybyAmJlxuICAgICAgICAgICAgKG9wdGlvbnMubWluaW11bVZhbHVlID4gMCB8fCBvcHRpb25zLm1heGltdW1WYWx1ZSA8IDApKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgJ2VtcHR5SW5wdXRCZWhhdmlvcicgb3B0aW9uIGlzIHNldCB0byAnemVybycsIGJ1dCB0aGlzIHZhbHVlIGlzIG91dHNpZGUgb2YgdGhlIHJhbmdlIGRlZmluZWQgYnkgJ21pbmltdW1WYWx1ZScgYW5kICdtYXhpbXVtVmFsdWUnIFske29wdGlvbnMubWluaW11bVZhbHVlfSwgJHtvcHRpb25zLm1heGltdW1WYWx1ZX1dLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRlc3RGbG9hdE9ySW50ZWdlckFuZFBvc3NpYmxlTmVnYXRpdmVTaWduLnRlc3QoU3RyaW5nKG9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yKSkpIHtcbiAgICAgICAgICAgIGNvbnN0IFttaW5UZXN0LCBtYXhUZXN0XSA9IHRoaXMuX2NoZWNrSWZJblJhbmdlV2l0aE92ZXJyaWRlT3B0aW9uKG9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLCBvcHRpb25zKTtcbiAgICAgICAgICAgIGlmICgoIW1pblRlc3QgfHwgIW1heFRlc3QpKSB7XG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlICdlbXB0eUlucHV0QmVoYXZpb3InIG9wdGlvbiBpcyBzZXQgdG8gYSBudW1iZXIgb3IgYSBzdHJpbmcgdGhhdCByZXByZXNlbnRzIGEgbnVtYmVyLCBidXQgaXRzIHZhbHVlIFske29wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yfV0gaXMgb3V0c2lkZSBvZiB0aGUgcmFuZ2UgZGVmaW5lZCBieSB0aGUgJ21pbmltdW1WYWx1ZScgYW5kICdtYXhpbXVtVmFsdWUnIG9wdGlvbnMgWyR7b3B0aW9ucy5taW5pbXVtVmFsdWV9LCAke29wdGlvbnMubWF4aW11bVZhbHVlfV0uYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVHJ1ZU9yRmFsc2VTdHJpbmcob3B0aW9ucy5ldmVudEJ1YmJsZXMpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ob3B0aW9ucy5ldmVudEJ1YmJsZXMpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZXZlbnQgYnViYmxlcyBvcHRpb24gJ2V2ZW50QnViYmxlcycgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBlaXRoZXIgJ3RydWUnIG9yICdmYWxzZScsIFske29wdGlvbnMuZXZlbnRCdWJibGVzfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVHJ1ZU9yRmFsc2VTdHJpbmcob3B0aW9ucy5ldmVudElzQ2FuY2VsYWJsZSkgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLmV2ZW50SXNDYW5jZWxhYmxlKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGV2ZW50IGlzIGNhbmNlbGFibGUgb3B0aW9uICdldmVudElzQ2FuY2VsYWJsZScgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBlaXRoZXIgJ3RydWUnIG9yICdmYWxzZScsIFske29wdGlvbnMuZXZlbnRJc0NhbmNlbGFibGV9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KG9wdGlvbnMubGVhZGluZ1plcm8sIFtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMubGVhZGluZ1plcm8uYWxsb3csXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmxlYWRpbmdaZXJvLmRlbnksXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmxlYWRpbmdaZXJvLmtlZXAsXG4gICAgICAgIF0pKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgbGVhZGluZyB6ZXJvIGJlaGF2aW9yIG9wdGlvbiAnbGVhZGluZ1plcm8nIGlzIGludmFsaWQgOyBpdCBzaG91bGQgZWl0aGVyIGJlICdhbGxvdycsICdkZW55JyBvciAna2VlcCcsIFske29wdGlvbnMubGVhZGluZ1plcm99XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLmZvcm1hdE9uUGFnZUxvYWQpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ob3B0aW9ucy5mb3JtYXRPblBhZ2VMb2FkKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGZvcm1hdCBvbiBpbml0aWFsaXphdGlvbiBvcHRpb24gJ2Zvcm1hdE9uUGFnZUxvYWQnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLmZvcm1hdE9uUGFnZUxvYWR9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGVzdFBvc2l0aXZlSW50ZWdlci50ZXN0KG9wdGlvbnMuaGlzdG9yeVNpemUpIHx8IG9wdGlvbnMuaGlzdG9yeVNpemUgPT09IDApIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBoaXN0b3J5IHNpemUgb3B0aW9uICdoaXN0b3J5U2l6ZScgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBhIHBvc2l0aXZlIGludGVnZXIsIFske29wdGlvbnMuaGlzdG9yeVNpemV9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLnNlbGVjdE51bWJlck9ubHkpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ob3B0aW9ucy5zZWxlY3ROdW1iZXJPbmx5KSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHNlbGVjdCBudW1iZXIgb25seSBvcHRpb24gJ3NlbGVjdE51bWJlck9ubHknIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLnNlbGVjdE51bWJlck9ubHl9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLnNlbGVjdE9uRm9jdXMpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ob3B0aW9ucy5zZWxlY3RPbkZvY3VzKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHNlbGVjdCBvbiBmb2N1cyBvcHRpb24gJ3NlbGVjdE9uRm9jdXMnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLnNlbGVjdE9uRm9jdXN9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMuZGVmYXVsdFZhbHVlT3ZlcnJpZGUpICYmIChvcHRpb25zLmRlZmF1bHRWYWx1ZU92ZXJyaWRlICE9PSAnJyAmJiAhdGVzdEZsb2F0T3JJbnRlZ2VyQW5kUG9zc2libGVOZWdhdGl2ZVNpZ24udGVzdChvcHRpb25zLmRlZmF1bHRWYWx1ZU92ZXJyaWRlKSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSB1bmZvcm1hdHRlZCBkZWZhdWx0IHZhbHVlIG9wdGlvbiAnZGVmYXVsdFZhbHVlT3ZlcnJpZGUnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgYSBzdHJpbmcgdGhhdCByZXByZXNlbnRzIGEgcG9zaXRpdmUgb3IgbmVnYXRpdmUgbnVtYmVyLCBbJHtvcHRpb25zLmRlZmF1bHRWYWx1ZU92ZXJyaWRlfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVHJ1ZU9yRmFsc2VTdHJpbmcob3B0aW9ucy51bmZvcm1hdE9uU3VibWl0KSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNCb29sZWFuKG9wdGlvbnMudW5mb3JtYXRPblN1Ym1pdCkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSByZW1vdmUgZm9ybWF0dGluZyBvbiBzdWJtaXQgb3B0aW9uICd1bmZvcm1hdE9uU3VibWl0JyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGVpdGhlciAnZmFsc2UnIG9yICd0cnVlJywgWyR7b3B0aW9ucy51bmZvcm1hdE9uU3VibWl0fV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zLnZhbHVlc1RvU3RyaW5ncykgJiZcbiAgICAgICAgICAgICEoQXV0b051bWVyaWNIZWxwZXIuaXNPYmplY3Qob3B0aW9ucy52YWx1ZXNUb1N0cmluZ3MpKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIG9wdGlvbiAndmFsdWVzVG9TdHJpbmdzJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGFuIG9iamVjdCwgaWRlYWxseSB3aXRoICdrZXkgLT4gdmFsdWUnIGVudHJpZXMsIFske29wdGlvbnMudmFsdWVzVG9TdHJpbmdzfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zLm91dHB1dEZvcm1hdCkgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzSW5BcnJheShvcHRpb25zLm91dHB1dEZvcm1hdCwgW1xuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5vdXRwdXRGb3JtYXQuc3RyaW5nLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5vdXRwdXRGb3JtYXQubnVtYmVyLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5vdXRwdXRGb3JtYXQuZG90LFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5vdXRwdXRGb3JtYXQubmVnYXRpdmVEb3QsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm91dHB1dEZvcm1hdC5jb21tYSxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMub3V0cHV0Rm9ybWF0Lm5lZ2F0aXZlQ29tbWEsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm91dHB1dEZvcm1hdC5kb3ROZWdhdGl2ZSxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMub3V0cHV0Rm9ybWF0LmNvbW1hTmVnYXRpdmUsXG4gICAgICAgIF0pKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgY3VzdG9tIGxvY2FsZSBmb3JtYXQgb3B0aW9uICdvdXRwdXRGb3JtYXQnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgZWl0aGVyIGJlIG51bGwsICdzdHJpbmcnLCAnbnVtYmVyJywgJy4nLCAnLS4nLCAnLCcsICctLCcsICcuLScgb3IgJywtJywgWyR7b3B0aW9ucy5vdXRwdXRGb3JtYXR9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLmlzQ2FuY2VsbGFibGUpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ob3B0aW9ucy5pc0NhbmNlbGxhYmxlKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGNhbmNlbGxhYmxlIGJlaGF2aW9yIG9wdGlvbiAnaXNDYW5jZWxsYWJsZScgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBlaXRoZXIgJ2ZhbHNlJyBvciAndHJ1ZScsIFske29wdGlvbnMuaXNDYW5jZWxsYWJsZX1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1RydWVPckZhbHNlU3RyaW5nKG9wdGlvbnMubW9kaWZ5VmFsdWVPbldoZWVsKSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNCb29sZWFuKG9wdGlvbnMubW9kaWZ5VmFsdWVPbldoZWVsKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGluY3JlbWVudC9kZWNyZW1lbnQgb24gbW91c2Ugd2hlZWwgb3B0aW9uICdtb2RpZnlWYWx1ZU9uV2hlZWwnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLm1vZGlmeVZhbHVlT25XaGVlbH1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1RydWVPckZhbHNlU3RyaW5nKG9wdGlvbnMud2F0Y2hFeHRlcm5hbENoYW5nZXMpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ob3B0aW9ucy53YXRjaEV4dGVybmFsQ2hhbmdlcykpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBvcHRpb24gJ3dhdGNoRXh0ZXJuYWxDaGFuZ2VzJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGVpdGhlciAnZmFsc2UnIG9yICd0cnVlJywgWyR7b3B0aW9ucy53YXRjaEV4dGVybmFsQ2hhbmdlc31dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc0luQXJyYXkob3B0aW9ucy53aGVlbE9uLCBbXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLndoZWVsT24uZm9jdXMsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLndoZWVsT24uaG92ZXIsXG4gICAgICAgIF0pKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgd2hlZWwgYmVoYXZpb3Igb3B0aW9uICd3aGVlbE9uJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGVpdGhlciBiZSAnZm9jdXMnIG9yICdob3ZlcicsIFske29wdGlvbnMud2hlZWxPbn1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEoQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcob3B0aW9ucy53aGVlbFN0ZXApIHx8IEF1dG9OdW1lcmljSGVscGVyLmlzTnVtYmVyKG9wdGlvbnMud2hlZWxTdGVwKSkgfHxcbiAgICAgICAgICAgIChvcHRpb25zLndoZWVsU3RlcCAhPT0gJ3Byb2dyZXNzaXZlJyAmJiAhdGVzdFBvc2l0aXZlRmxvYXRPckludGVnZXIudGVzdChvcHRpb25zLndoZWVsU3RlcCkpIHx8XG4gICAgICAgICAgICBOdW1iZXIob3B0aW9ucy53aGVlbFN0ZXApID09PSAwKSB7XG4gICAgICAgICAgICAvLyBBIHN0ZXAgZXF1YWwgdG8gJzAnIGlzIHJlamVjdGVkXG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgd2hlZWwgc3RlcCB2YWx1ZSBvcHRpb24gJ3doZWVsU3RlcCcgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBlaXRoZXIgYmUgdGhlIHN0cmluZyAncHJvZ3Jlc3NpdmUnLCBvciBhIG51bWJlciBvciBhIHN0cmluZyB0aGF0IHJlcHJlc2VudHMgYSBwb3NpdGl2ZSBudW1iZXIgKGV4Y2x1ZGluZyB6ZXJvKSwgWyR7b3B0aW9ucy53aGVlbFN0ZXB9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KG9wdGlvbnMuc2VyaWFsaXplU3BhY2VzLCBbXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnNlcmlhbGl6ZVNwYWNlcy5wbHVzLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5zZXJpYWxpemVTcGFjZXMucGVyY2VudCxcbiAgICAgICAgXSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBzcGFjZSByZXBsYWNlbWVudCBjaGFyYWN0ZXIgb3B0aW9uICdzZXJpYWxpemVTcGFjZXMnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgZWl0aGVyIGJlICcrJyBvciAnJTIwJywgWyR7b3B0aW9ucy5zZXJpYWxpemVTcGFjZXN9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLm5vRXZlbnRMaXN0ZW5lcnMpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ob3B0aW9ucy5ub0V2ZW50TGlzdGVuZXJzKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIG9wdGlvbiAnbm9FdmVudExpc3RlbmVycycgdGhhdCBwcmV2ZW50IHRoZSBjcmVhdGlvbiBvZiBldmVudCBsaXN0ZW5lcnMgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBlaXRoZXIgJ2ZhbHNlJyBvciAndHJ1ZScsIFske29wdGlvbnMubm9FdmVudExpc3RlbmVyc31dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucy5zdHlsZVJ1bGVzKSAmJlxuICAgICAgICAgICAgIShBdXRvTnVtZXJpY0hlbHBlci5pc09iamVjdChvcHRpb25zLnN0eWxlUnVsZXMpICYmXG4gICAgICAgICAgICAoKG9wdGlvbnMuc3R5bGVSdWxlcy5oYXNPd25Qcm9wZXJ0eSgncG9zaXRpdmUnKSB8fFxuICAgICAgICAgICAgb3B0aW9ucy5zdHlsZVJ1bGVzLmhhc093blByb3BlcnR5KCduZWdhdGl2ZScpIHx8XG4gICAgICAgICAgICBvcHRpb25zLnN0eWxlUnVsZXMuaGFzT3duUHJvcGVydHkoJ3JhbmdlcycpIHx8XG4gICAgICAgICAgICBvcHRpb25zLnN0eWxlUnVsZXMuaGFzT3duUHJvcGVydHkoJ3VzZXJEZWZpbmVkJykpKSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBvcHRpb24gJ3N0eWxlUnVsZXMnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgYSBjb3JyZWN0bHkgc3RydWN0dXJlZCBvYmplY3QsIHdpdGggb25lIG9yIG1vcmUgJ3Bvc2l0aXZlJywgJ25lZ2F0aXZlJywgJ3Jhbmdlcycgb3IgJ3VzZXJEZWZpbmVkJyBhdHRyaWJ1dGVzLCBbJHtvcHRpb25zLnN0eWxlUnVsZXN9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERlZXBlciB0ZXN0cyBvZiB0aGUgYHN0eWxlUnVsZXNgIG9iamVjdCA6IENoZWNrIHRoYXQgdGhlIGNhbGxiYWNrLCBpZiBkZWZpbmVkLCBpcyBhIGZ1bmN0aW9uXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMuc3R5bGVSdWxlcykgJiZcbiAgICAgICAgICAgIG9wdGlvbnMuc3R5bGVSdWxlcy5oYXNPd25Qcm9wZXJ0eSgndXNlckRlZmluZWQnKSAmJlxuICAgICAgICAgICAgIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zLnN0eWxlUnVsZXMudXNlckRlZmluZWQpKSB7XG4gICAgICAgICAgICBvcHRpb25zLnN0eWxlUnVsZXMudXNlckRlZmluZWQuZm9yRWFjaChydWxlID0+IHtcbiAgICAgICAgICAgICAgICBpZiAocnVsZS5oYXNPd25Qcm9wZXJ0eSgnY2FsbGJhY2snKSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNGdW5jdGlvbihydWxlLmNhbGxiYWNrKSkge1xuICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgY2FsbGJhY2sgZGVmaW5lZCBpbiB0aGUgXFxgdXNlckRlZmluZWRcXGAgYXR0cmlidXRlIGlzIG5vdCBhIGZ1bmN0aW9uLCAke3R5cGVvZiBydWxlLmNhbGxiYWNrfSBnaXZlbi5gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMucmF3VmFsdWVEaXZpc29yKSAmJlxuICAgICAgICAgICAgIXRlc3RQb3NpdGl2ZUZsb2F0T3JJbnRlZ2VyLnRlc3Qob3B0aW9ucy5yYXdWYWx1ZURpdmlzb3IpIHx8XG4gICAgICAgICAgICBvcHRpb25zLnJhd1ZhbHVlRGl2aXNvciA9PT0gMCB8fCBvcHRpb25zLnJhd1ZhbHVlRGl2aXNvciA9PT0gJzAnIHx8XG4gICAgICAgICAgICBvcHRpb25zLnJhd1ZhbHVlRGl2aXNvciA9PT0gMSB8fCBvcHRpb25zLnJhd1ZhbHVlRGl2aXNvciA9PT0gJzEnKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgcmF3IHZhbHVlIGRpdmlzb3Igb3B0aW9uICdyYXdWYWx1ZURpdmlzb3InIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgYSBwb3NpdGl2ZSBudW1iZXIgaGlnaGVyIHRoYW4gb25lLCBwcmVmZXJhYmx5IGFuIGludGVnZXIsIFske29wdGlvbnMucmF3VmFsdWVEaXZpc29yfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVHJ1ZU9yRmFsc2VTdHJpbmcob3B0aW9ucy5yZWFkT25seSkgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLnJlYWRPbmx5KSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIG9wdGlvbiAncmVhZE9ubHknIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLnJlYWRPbmx5fV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVHJ1ZU9yRmFsc2VTdHJpbmcob3B0aW9ucy51bmZvcm1hdE9uSG92ZXIpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ob3B0aW9ucy51bmZvcm1hdE9uSG92ZXIpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgb3B0aW9uICd1bmZvcm1hdE9uSG92ZXInIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLnVuZm9ybWF0T25Ib3Zlcn1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1RydWVPckZhbHNlU3RyaW5nKG9wdGlvbnMuZmFpbE9uVW5rbm93bk9wdGlvbikgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLmZhaWxPblVua25vd25PcHRpb24pKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZGVidWcgb3B0aW9uICdmYWlsT25Vbmtub3duT3B0aW9uJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGVpdGhlciAnZmFsc2UnIG9yICd0cnVlJywgWyR7b3B0aW9ucy5mYWlsT25Vbmtub3duT3B0aW9ufV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVHJ1ZU9yRmFsc2VTdHJpbmcob3B0aW9ucy5jcmVhdGVMb2NhbExpc3QpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ob3B0aW9ucy5jcmVhdGVMb2NhbExpc3QpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZGVidWcgb3B0aW9uICdjcmVhdGVMb2NhbExpc3QnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLmNyZWF0ZUxvY2FsTGlzdH1dIGdpdmVuLmApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgdGhlIGBkZWNpbWFsUGxhY2VzKmAgb3B0aW9ucyBhbmQgb3V0cHV0IHRoZSByZWxldmFudCB3YXJuaW5ncyBpZiBzb21lIG9mIHRob3NlIHdpbGwgZ2V0IG92ZXJ3cml0dGVuIGR1cmluZyB0aGUgaW5pdGlhbGl6YXRpb24gb3Igc2V0dGluZ3MgdXBkYXRlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfdmFsaWRhdGVEZWNpbWFsUGxhY2VzUmF3VmFsdWUob3B0aW9ucykge1xuICAgICAgICAvLyBDaGVja3MgaWYgdGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyBmb3IgdGhlIHJhdyB2YWx1ZSBpcyBsb3dlciB0aGFuIHRoZSBgZGVjaW1hbFBsYWNlc2AsIGBkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzYCBhbmQvb3IgYGRlY2ltYWxQbGFjZXNTaG93bk9uQmx1cmAgb3B0aW9uc1xuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSkpIHtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA8IG9wdGlvbnMuZGVjaW1hbFBsYWNlcykge1xuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLndhcm5pbmcoYFRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgdG8gc3RvcmUgaW4gdGhlIHJhdyB2YWx1ZSBbJHtvcHRpb25zLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZX1dIGlzIGxvd2VyIHRoYW4gdGhlIG9uZXMgdG8gZGlzcGxheSBbJHtvcHRpb25zLmRlY2ltYWxQbGFjZXN9XS4gVGhpcyB3aWxsIGxpa2VseSBjb25mdXNlIHlvdXIgdXNlcnMuXG5UbyBzb2x2ZSB0aGF0LCB5b3UnZCBuZWVkIHRvIGVpdGhlciBzZXQgXFxgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlXFxgIHRvIFxcYG51bGxcXGAsIG9yIHNldCBhIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyBmb3IgdGhlIHJhdyB2YWx1ZSBlcXVhbCBvZiBiaWdnZXIgdGhhbiBcXGBkZWNpbWFsUGxhY2VzXFxgLmAsIG9wdGlvbnMuc2hvd1dhcm5pbmdzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDwgb3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzKSB7XG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZyhgVGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyB0byBzdG9yZSBpbiB0aGUgcmF3IHZhbHVlIFske29wdGlvbnMuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlfV0gaXMgbG93ZXIgdGhhbiB0aGUgb25lcyBzaG93biBvbiBmb2N1cyBbJHtvcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXN9XS4gVGhpcyB3aWxsIGxpa2VseSBjb25mdXNlIHlvdXIgdXNlcnMuXG5UbyBzb2x2ZSB0aGF0LCB5b3UnZCBuZWVkIHRvIGVpdGhlciBzZXQgXFxgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlXFxgIHRvIFxcYG51bGxcXGAsIG9yIHNldCBhIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyBmb3IgdGhlIHJhdyB2YWx1ZSBlcXVhbCBvZiBiaWdnZXIgdGhhbiBcXGBkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzXFxgLmAsIG9wdGlvbnMuc2hvd1dhcm5pbmdzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDwgb3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIpIHtcbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKGBUaGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHRvIHN0b3JlIGluIHRoZSByYXcgdmFsdWUgWyR7b3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWV9XSBpcyBsb3dlciB0aGFuIHRoZSBvbmVzIHNob3duIHdoZW4gdW5mb2N1c2VkIFske29wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyfV0uIFRoaXMgd2lsbCBsaWtlbHkgY29uZnVzZSB5b3VyIHVzZXJzLlxuVG8gc29sdmUgdGhhdCwgeW91J2QgbmVlZCB0byBlaXRoZXIgc2V0IFxcYGRlY2ltYWxQbGFjZXNSYXdWYWx1ZVxcYCB0byBcXGBudWxsXFxgLCBvciBzZXQgYSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgZm9yIHRoZSByYXcgdmFsdWUgZXF1YWwgb2YgYmlnZ2VyIHRoYW4gXFxgZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyXFxgLmAsIG9wdGlvbnMuc2hvd1dhcm5pbmdzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIHNldHRpbmdzL29wdGlvbnMgYXJlIHZhbGlkLCBgZmFsc2VgIG90aGVyd2lzZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGFyZVNldHRpbmdzVmFsaWQob3B0aW9ucykge1xuICAgICAgICBsZXQgaXNWYWxpZCA9IHRydWU7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICB0aGlzLnZhbGlkYXRlKG9wdGlvbnMsIHRydWUpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgaXNWYWxpZCA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGlzVmFsaWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBkZWZhdWx0IGF1dG9OdW1lcmljIHNldHRpbmdzLlxuICAgICAqXG4gICAgICogQHJldHVybnMge29iamVjdH1cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0RGVmYXVsdENvbmZpZygpIHtcbiAgICAgICAgcmV0dXJuIEF1dG9OdW1lcmljLmRlZmF1bHRTZXR0aW5ncztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYWxsIHRoZSBwcmVkZWZpbmVkIGxhbmd1YWdlIG9wdGlvbnMgaW4gb25lIG9iamVjdC5cbiAgICAgKiBZb3UgY2FuIGFsc28gYWNjZXNzIGEgc3BlY2lmaWMgbGFuZ3VhZ2Ugb2JqZWN0IGRpcmVjdGx5IGJ5IHVzaW5nIGBBdXRvTnVtZXJpYy5nZXRQcmVkZWZpbmVkT3B0aW9ucygpLkZyZW5jaGAgZm9yIGluc3RhbmNlLlxuICAgICAqXG4gICAgICogQHJldHVybnMge29iamVjdH1cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0UHJlZGVmaW5lZE9wdGlvbnMoKSB7XG4gICAgICAgIHJldHVybiBBdXRvTnVtZXJpYy5wcmVkZWZpbmVkT3B0aW9ucztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbmFseXNlIHRoZSBnaXZlbiBhcnJheSBgb3B0aW9uc2AgYW5kIHJldHVybiBhIHNpbmdsZSAnbWVyZ2VkJyBvcHRpb24gb2JqZXQuXG4gICAgICogYG9wdGlvbnNgIGNhbiBiZSBgbnVsbGAsIG9yIGFuIGFycmF5IG9mIGFuIG9wdGlvbiBvYmplY3RzLCBvciBhbiBhcnJheSBjb250YWluaW5nIGFub3RoZXIgYXJyYXkgb2Ygb3B0aW9uIG9iamVjdHMgLyBzdHJpbmdzIChwcmUtZGVmaW5lZCBvcHRpb24gbmFtZXMpXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bGx8QXJyYXk8b2JqZWN0fHN0cmluZ3xBcnJheTxzdHJpbmd8b2JqZWN0Pj59IG9wdGlvbnNcbiAgICAgKiBAcmV0dXJucyB7bnVsbHxvYmplY3R9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2dlbmVyYXRlT3B0aW9uc09iamVjdEZyb21PcHRpb25zQXJyYXkob3B0aW9ucykge1xuICAgICAgICBsZXQgb3B0aW9uc1Jlc3VsdDtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eShvcHRpb25zKSB8fCBvcHRpb25zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgb3B0aW9uc1Jlc3VsdCA9IG51bGw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvcHRpb25zUmVzdWx0ID0ge307XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5sZW5ndGggPT09IDEgJiYgQXJyYXkuaXNBcnJheShvcHRpb25zWzBdKSkge1xuICAgICAgICAgICAgICAgIG9wdGlvbnNbMF0uZm9yRWFjaChvcHRpb25PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICAvLyBVc2luZyBgX2dldE9wdGlvbk9iamVjdCgpYCBhbGxvd3MgdXNpbmcgcHJlLWRlZmluZWQgbmFtZXMgaW4gdGhlIGBvcHRpb25zYCBhcnJheVxuICAgICAgICAgICAgICAgICAgICBPYmplY3QuYXNzaWduKG9wdGlvbnNSZXN1bHQsIHRoaXMuX2dldE9wdGlvbk9iamVjdChvcHRpb25PYmplY3QpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAob3B0aW9ucy5sZW5ndGggPj0gMSkge1xuICAgICAgICAgICAgICAgIG9wdGlvbnMuZm9yRWFjaChvcHRpb25PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICBPYmplY3QuYXNzaWduKG9wdGlvbnNSZXN1bHQsIHRoaXMuX2dldE9wdGlvbk9iamVjdChvcHRpb25PYmplY3QpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBvcHRpb25zUmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZvcm1hdCB0aGUgZ2l2ZW4gbnVtYmVyIChvciBudW1lcmljIHN0cmluZykgd2l0aCB0aGUgZ2l2ZW4gb3B0aW9ucy4gVGhpcyByZXR1cm5zIHRoZSBmb3JtYXR0ZWQgdmFsdWUgYXMgYSBzdHJpbmcuXG4gICAgICogVGhpcyBjYW4gYWxzbyBmb3JtYXQgdGhlIGdpdmVuIERPTSBlbGVtZW50IHZhbHVlIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMgYW5kIHJldHVybnMgdGhlIGZvcm1hdHRlZCB2YWx1ZSBhcyBhIHN0cmluZy5cbiAgICAgKiBOb3RlIDogVGhpcyBmdW5jdGlvbiBkb2VzICpub3QqIHVwZGF0ZSB0aGF0IGVsZW1lbnQgdmFsdWUgd2l0aCB0aGUgbmV3bHkgZm9ybWF0dGVkIHZhbHVlLlxuICAgICAqIFRoaXMgYmFzaWNhbGx5IGFsbG93cyB0byBnZXQgdGhlIGZvcm1hdHRlZCB2YWx1ZSB3aXRob3V0IGZpcnN0IGhhdmluZyB0byBpbml0aWFsaXplIGFuIEF1dG9OdW1lcmljIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ3xIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fSBudW1lcmljU3RyaW5nT3JEb21FbGVtZW50IEEgbnVtYmVyLCBvciBhIHN0cmluZyB0aGF0IHJlcHJlc2VudCBhIGphdmFzY3JpcHQgbnVtYmVyLCBvciBhIERPTSBlbGVtZW50XG4gICAgICogQHBhcmFtIHtvYmplY3R8bnVsbH0gb3B0aW9ucyBNdWx0aXBsZSBvYmplY3RzIGNhbiBiZSBwYXNzZWQsIHRoZSBsYXR0ZXIgb3ZlcndyaXRpbmcgdGhlIHNldHRpbmdzIGZyb20gdGhlIGZvcm1lciBvbmVzXG4gICAgICogQHJldHVybnMge3N0cmluZ3xudWxsfVxuICAgICAqL1xuICAgIHN0YXRpYyBmb3JtYXQobnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudCwgLi4ub3B0aW9ucykge1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWQobnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudCkgfHwgbnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZXRyaWV2ZSB0aGUgdmFsdWUgdG8gZm9ybWF0XG4gICAgICAgIGxldCB2YWx1ZTtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzRWxlbWVudChudW1lcmljU3RyaW5nT3JEb21FbGVtZW50KSkge1xuICAgICAgICAgICAgdmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUobnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YWx1ZSA9IG51bWVyaWNTdHJpbmdPckRvbUVsZW1lbnQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzU3RyaW5nKHZhbHVlKSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNOdW1iZXIodmFsdWUpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgdmFsdWUgXCIke3ZhbHVlfVwiIGJlaW5nIFwic2V0XCIgaXMgbm90IG51bWVyaWMgYW5kIHRoZXJlZm9yZSBjYW5ub3QgYmUgdXNlZCBhcHByb3ByaWF0ZWx5LmApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTWFuYWdlIG9wdGlvbnNcbiAgICAgICAgY29uc3Qgb3B0aW9uc1RvVXNlID0gdGhpcy5fZ2VuZXJhdGVPcHRpb25zT2JqZWN0RnJvbU9wdGlvbnNBcnJheShvcHRpb25zKTtcblxuICAgICAgICAvLyBJbml0aWF0ZSBhIHZlcnkgYmFzaWMgc2V0dGluZ3Mgb2JqZWN0XG4gICAgICAgIGNvbnN0IHNldHRpbmdzID0gT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5nZXREZWZhdWx0Q29uZmlnKCksIG9wdGlvbnNUb1VzZSk7XG4gICAgICAgIHNldHRpbmdzLmlzTmVnYXRpdmVTaWduQWxsb3dlZCA9IHZhbHVlIDwgMDtcbiAgICAgICAgc2V0dGluZ3MuaXNQb3NpdGl2ZVNpZ25BbGxvd2VkID0gdmFsdWUgPj0gMDtcbiAgICAgICAgdGhpcy5fc2V0QnJhY2tldHMoc2V0dGluZ3MpO1xuXG4gICAgICAgIGNvbnN0IHJlZ2V4ID0ge307XG4gICAgICAgIHRoaXMuX2NhY2hlc1VzdWFsUmVndWxhckV4cHJlc3Npb25zKHNldHRpbmdzLCByZWdleCk7IC8vIFRoaXMgaXMgbmVlZGVkIGJ5IGBfc3RyaXBBbGxOb25OdW1iZXJDaGFyYWN0ZXJzRXhjZXB0Q3VzdG9tRGVjaW1hbENoYXJgIHRoYXQgdXNlcyB0aG9zZSByZWdleFxuXG4gICAgICAgIC8vIENoZWNrIHRoZSB2YWxpZGl0eSBvZiB0aGUgYHZhbHVlYCBwYXJhbWV0ZXJcbiAgICAgICAgLy8gQ29udmVydCB0aGUgdmFsdWUgdG8gYSBudW1lcmljIHN0cmluZywgc3RyaXBwaW5nIHVubmVjZXNzYXJ5IGNoYXJhY3RlcnMgaW4gdGhlIHByb2Nlc3NcbiAgICAgICAgbGV0IHZhbHVlU3RyaW5nID0gdGhpcy5fdG9OdW1lcmljVmFsdWUodmFsdWUsIHNldHRpbmdzKTtcbiAgICAgICAgaWYgKGlzTmFOKE51bWJlcih2YWx1ZVN0cmluZykpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgdmFsdWUgWyR7dmFsdWVTdHJpbmd9XSB0aGF0IHlvdSBhcmUgdHJ5aW5nIHRvIGZvcm1hdCBpcyBub3QgYSByZWNvZ25pemVkIG51bWJlci5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEJhc2ljIHRlc3RzIHRvIGNoZWNrIGlmIHRoZSBnaXZlbiB2YWx1ZVN0cmluZyBpcyB2YWxpZFxuICAgICAgICBjb25zdCBbbWluVGVzdCwgbWF4VGVzdF0gPSB0aGlzLl9jaGVja0lmSW5SYW5nZVdpdGhPdmVycmlkZU9wdGlvbih2YWx1ZVN0cmluZywgc2V0dGluZ3MpO1xuICAgICAgICBpZiAoIW1pblRlc3QgfHwgIW1heFRlc3QpIHtcbiAgICAgICAgICAgIC8vIFRocm93IGEgY3VzdG9tIGV2ZW50XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50cmlnZ2VyRXZlbnQoQXV0b051bWVyaWMuZXZlbnRzLmZvcm1hdHRlZCwgZG9jdW1lbnQsIHtcbiAgICAgICAgICAgICAgICBvbGRWYWx1ZSAgIDogbnVsbCxcbiAgICAgICAgICAgICAgICBuZXdWYWx1ZSAgIDogbnVsbCxcbiAgICAgICAgICAgICAgICBvbGRSYXdWYWx1ZTogbnVsbCxcbiAgICAgICAgICAgICAgICBuZXdSYXdWYWx1ZTogbnVsbCxcbiAgICAgICAgICAgICAgICBpc1ByaXN0aW5lIDogbnVsbCxcbiAgICAgICAgICAgICAgICBlcnJvciAgICAgIDogJ1JhbmdlIHRlc3QgZmFpbGVkJyxcbiAgICAgICAgICAgICAgICBhTkVsZW1lbnQgIDogbnVsbCxcbiAgICAgICAgICAgIH0sIHRydWUsIHRydWUpO1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHZhbHVlIFske3ZhbHVlU3RyaW5nfV0gYmVpbmcgc2V0IGZhbGxzIG91dHNpZGUgb2YgdGhlIG1pbmltdW1WYWx1ZSBbJHtzZXR0aW5ncy5taW5pbXVtVmFsdWV9XSBhbmQgbWF4aW11bVZhbHVlIFske3NldHRpbmdzLm1heGltdW1WYWx1ZX1dIHJhbmdlIHNldCBmb3IgdGhpcyBlbGVtZW50YCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEaXJlY3RseSBmb3JtYXQgYW55IGB2YWx1ZXNUb1N0cmluZ3NgIHZhbHVlcywgaWYgZm91bmRcbiAgICAgICAgaWYgKHNldHRpbmdzLnZhbHVlc1RvU3RyaW5ncyAmJiB0aGlzLl9jaGVja1ZhbHVlc1RvU3RyaW5nc1NldHRpbmdzKHZhbHVlLCBzZXR0aW5ncykpIHtcbiAgICAgICAgICAgIHJldHVybiBzZXR0aW5ncy52YWx1ZXNUb1N0cmluZ3NbdmFsdWVdO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gR2VuZXJhdGUgdGhlIGBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudGAgb3B0aW9uIGFzIG5lZWRlZFxuICAgICAgICB0aGlzLl9jb3JyZWN0TmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnRPcHRpb24oc2V0dGluZ3MpO1xuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIG5lZWRlZCBkZWNpbWFsIHBsYWNlc1xuICAgICAgICB0aGlzLl9jYWxjdWxhdGVEZWNpbWFsUGxhY2VzT25Jbml0KHNldHRpbmdzKTtcblxuICAgICAgICAvLyBNdWx0aXBseSB0aGUgcmF3IHZhbHVlIHdpdGggYHJhd1ZhbHVlRGl2aXNvcmAgaWYgZGVmaW5lZFxuICAgICAgICBpZiAoKCFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkoc2V0dGluZ3MucmF3VmFsdWVEaXZpc29yKSAmJiBzZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3IgIT09IDApICYmIC8vIE9ubHkgZGl2aWRlIGlmIHRoZSBgcmF3VmFsdWVEaXZpc29yYCBvcHRpb24gaXMgc2V0XG4gICAgICAgICAgICB2YWx1ZVN0cmluZyAhPT0gJycgJiYgdmFsdWVTdHJpbmcgIT09IG51bGwpIHsgLy8gRG8gbm90IG1vZGlmeSB0aGUgYHZhbHVlU3RyaW5nYCBpZiBpdCdzIGFuIGVtcHR5IHN0cmluZyBvciBudWxsXG4gICAgICAgICAgICB2YWx1ZVN0cmluZyAqPSBzZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3I7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBFdmVyeXRoaW5nIGlzIG9rLCBwcm9jZWVkIHRvIHJvdW5kaW5nLCBmb3JtYXR0aW5nIGFuZCBncm91cGluZ1xuICAgICAgICB2YWx1ZVN0cmluZyA9IHRoaXMuX3JvdW5kRm9ybWF0dGVkVmFsdWVTaG93bk9uRm9jdXModmFsdWVTdHJpbmcsIHNldHRpbmdzKTtcbiAgICAgICAgdmFsdWVTdHJpbmcgPSB0aGlzLl9tb2RpZnlOZWdhdGl2ZVNpZ25BbmREZWNpbWFsQ2hhcmFjdGVyRm9yRm9ybWF0dGVkVmFsdWUodmFsdWVTdHJpbmcsIHNldHRpbmdzKTtcbiAgICAgICAgdmFsdWVTdHJpbmcgPSB0aGlzLl9hZGRHcm91cFNlcGFyYXRvcnModmFsdWVTdHJpbmcsIHNldHRpbmdzLCBmYWxzZSwgdmFsdWVTdHJpbmcpO1xuXG4gICAgICAgIHJldHVybiB2YWx1ZVN0cmluZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb3JtYXQgdGhlIGdpdmVuIERPTSBlbGVtZW50IHZhbHVlLCBhbmQgc2V0IHRoZSByZXN1bHRpbmcgdmFsdWUgYmFjayBhcyB0aGUgZWxlbWVudCB2YWx1ZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8SFRNTElucHV0RWxlbWVudH0gZG9tRWxlbWVudFxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zXG4gICAgICogQHJldHVybnMge3N0cmluZ3xudWxsfVxuICAgICAqL1xuICAgIHN0YXRpYyBmb3JtYXRBbmRTZXQoZG9tRWxlbWVudCwgb3B0aW9ucyA9IG51bGwpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgY29uc3QgZm9ybWF0dGVkVmFsdWUgPSB0aGlzLmZvcm1hdChkb21FbGVtZW50LCBvcHRpb25zKTtcbiAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFZhbHVlKGRvbUVsZW1lbnQsIGZvcm1hdHRlZFZhbHVlKTtcblxuICAgICAgICByZXR1cm4gZm9ybWF0dGVkVmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVW5mb3JtYXQgdGhlIGdpdmVuIGZvcm1hdHRlZCBzdHJpbmcgd2l0aCB0aGUgZ2l2ZW4gb3B0aW9ucy4gVGhpcyByZXR1cm5zIGEgbnVtZXJpYyBzdHJpbmcuXG4gICAgICogSXQgY2FuIGFsc28gdW5mb3JtYXQgdGhlIGdpdmVuIERPTSBlbGVtZW50IHZhbHVlIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMgYW5kIHJldHVybnMgdGhlIHVuZm9ybWF0dGVkIG51bWVyaWMgc3RyaW5nLlxuICAgICAqIE5vdGU6IFRoaXMgZG9lcyAqbm90KiB1cGRhdGUgdGhhdCBlbGVtZW50IHZhbHVlLlxuICAgICAqIFRoaXMgYmFzaWNhbGx5IGFsbG93cyB0byBnZXQgdGhlIHVuZm9ybWF0dGVkIHZhbHVlIHdpdGhvdXQgZmlyc3QgaGF2aW5nIHRvIGluaXRpYWxpemUgYW4gQXV0b051bWVyaWMgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfEhUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR9IG51bWVyaWNTdHJpbmdPckRvbUVsZW1lbnQgQSBudW1iZXIsIG9yIGEgc3RyaW5nIHRoYXQgcmVwcmVzZW50IGEgamF2YXNjcmlwdCBudW1iZXIsIG9yIGEgRE9NIGVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge29iamVjdHxudWxsfSBvcHRpb25zIE11bHRpcGxlIG9iamVjdHMgY2FuIGJlIHBhc3NlZCwgdGhlIGxhdHRlciBvdmVyd3JpdGluZyB0aGUgc2V0dGluZ3MgZnJvbSB0aGUgZm9ybWVyIG9uZXNcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bWJlcnxOYU59XG4gICAgICovXG4gICAgc3RhdGljIHVuZm9ybWF0KG51bWVyaWNTdHJpbmdPckRvbUVsZW1lbnQsIC4uLm9wdGlvbnMpIHtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVtYmVyU3RyaWN0KG51bWVyaWNTdHJpbmdPckRvbUVsZW1lbnQpKSB7XG4gICAgICAgICAgICAvLyBHaXZpbmcgYW4gdW5mb3JtYXR0ZWQgdmFsdWUgc2hvdWxkIHJldHVybiB0aGUgc2FtZSB1bmZvcm1hdHRlZCB2YWx1ZSwgd2hhdGV2ZXIgdGhlIG9wdGlvbnMgcGFzc2VkIGFzIGEgcGFyYW1ldGVyXG4gICAgICAgICAgICByZXR1cm4gbnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJldHJpZXZlIHRoZSB2YWx1ZSB0byB1bmZvcm1hdFxuICAgICAgICBsZXQgdmFsdWU7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0VsZW1lbnQobnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudCkpIHtcbiAgICAgICAgICAgIHZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKG51bWVyaWNTdHJpbmdPckRvbUVsZW1lbnQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFsdWUgPSBudW1lcmljU3RyaW5nT3JEb21FbGVtZW50O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHZhbHVlID09PSAnJykge1xuICAgICAgICAgICAgLy8gVGhpcyBhbGxvd3MgdG8gYmUgY29oZXJlbnQgd2hlbiBzZXJpYWxpemluZyBmb3JtcyB3aXRoIGVtcHR5IGlucHV0cy4gRml4IGlzc3VlICM1MTIuXG4gICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWQodmFsdWUpIHx8IHZhbHVlID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0FycmF5KHZhbHVlKSB8fCBBdXRvTnVtZXJpY0hlbHBlci5pc09iamVjdCh2YWx1ZSkpIHtcbiAgICAgICAgICAgIC8vIENoZWNrIHRoZSB2YWxpZGl0eSBvZiB0aGUgYHZhbHVlYCBwYXJhbWV0ZXJcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYEEgbnVtYmVyIG9yIGEgc3RyaW5nIHJlcHJlc2VudGluZyBhIG51bWJlciBpcyBuZWVkZWQgdG8gYmUgYWJsZSB0byB1bmZvcm1hdCBpdCwgWyR7dmFsdWV9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE1hbmFnZSBvcHRpb25zXG4gICAgICAgIGNvbnN0IG9wdGlvbnNUb1VzZSA9IHRoaXMuX2dlbmVyYXRlT3B0aW9uc09iamVjdEZyb21PcHRpb25zQXJyYXkob3B0aW9ucyk7XG5cbiAgICAgICAgLy8gR2VuZXJhdGUgdGhlIHNldHRpbmdzXG4gICAgICAgIGNvbnN0IHNldHRpbmdzID0gT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5nZXREZWZhdWx0Q29uZmlnKCksIG9wdGlvbnNUb1VzZSk7XG4gICAgICAgIHNldHRpbmdzLmlzTmVnYXRpdmVTaWduQWxsb3dlZCA9IGZhbHNlO1xuICAgICAgICBzZXR0aW5ncy5pc1Bvc2l0aXZlU2lnbkFsbG93ZWQgPSB0cnVlO1xuICAgICAgICB2YWx1ZSA9IHZhbHVlLnRvU3RyaW5nKCk7XG5cbiAgICAgICAgLy8gRGlyZWN0bHkgdW5mb3JtYXQgYW55IGB2YWx1ZXNUb1N0cmluZ3NgIHZhbHVlcywgaWYgZm91bmRcbiAgICAgICAgaWYgKHNldHRpbmdzLnZhbHVlc1RvU3RyaW5ncyAmJiB0aGlzLl9jaGVja1N0cmluZ3NUb1ZhbHVlc1NldHRpbmdzKHZhbHVlLCBzZXR0aW5ncykpIHtcbiAgICAgICAgICAgIHJldHVybiBBdXRvTnVtZXJpY0hlbHBlci5vYmplY3RLZXlMb29rdXAoc2V0dGluZ3MudmFsdWVzVG9TdHJpbmdzLCB2YWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUaGlzIGNoZWNrcyBpZiBhIG5lZ2F0aXZlIHNpZ24gaXMgYW55d2hlcmUgaW4gdGhlIGB2YWx1ZWAsIG5vdCBqdXN0IG9uIHRoZSB2ZXJ5IGZpcnN0IGNoYXJhY3RlciAoaWUuICcxMjM0NS42Ny0nKVxuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZSh2YWx1ZSwgc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgc2V0dGluZ3MuaXNOZWdhdGl2ZVNpZ25BbGxvd2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIHNldHRpbmdzLmlzUG9zaXRpdmVTaWduQWxsb3dlZCA9IGZhbHNlO1xuICAgICAgICB9IGVsc2UgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoc2V0dGluZ3MubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIpKSB7XG4gICAgICAgICAgICBbc2V0dGluZ3MuZmlyc3RCcmFja2V0LCBzZXR0aW5ncy5sYXN0QnJhY2tldF0gPSBzZXR0aW5ncy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ci5zcGxpdCgnLCcpO1xuICAgICAgICAgICAgaWYgKHZhbHVlLmNoYXJBdCgwKSA9PT0gc2V0dGluZ3MuZmlyc3RCcmFja2V0ICYmXG4gICAgICAgICAgICAgICAgdmFsdWUuY2hhckF0KHZhbHVlLmxlbmd0aCAtIDEpID09PSBzZXR0aW5ncy5sYXN0QnJhY2tldCkge1xuICAgICAgICAgICAgICAgIHNldHRpbmdzLmlzTmVnYXRpdmVTaWduQWxsb3dlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgc2V0dGluZ3MuaXNQb3NpdGl2ZVNpZ25BbGxvd2VkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSB0aGlzLl9yZW1vdmVCcmFja2V0cyh2YWx1ZSwgc2V0dGluZ3MsIGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhbHVlID0gdGhpcy5fY29udmVydFRvTnVtZXJpY1N0cmluZyh2YWx1ZSwgc2V0dGluZ3MpO1xuICAgICAgICBjb25zdCB1bndhbnRlZENoYXJhY3RlcnMgPSBuZXcgUmVnRXhwKGBbXistMDEyMzQ1Njc4OS5dYCwgJ2dpJyk7XG4gICAgICAgIGlmICh1bndhbnRlZENoYXJhY3RlcnMudGVzdCh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBHZW5lcmF0ZSB0aGUgYG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50YCBvcHRpb24gYXMgbmVlZGVkXG4gICAgICAgIHRoaXMuX2NvcnJlY3ROZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudE9wdGlvbihzZXR0aW5ncyk7XG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgbmVlZGVkIGRlY2ltYWwgcGxhY2VzXG4gICAgICAgIGlmIChzZXR0aW5ncy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUpIHsgLy8gYG9yaWdpbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlYCBuZWVkcyB0byBiZSBkZWZpbmVkXG4gICAgICAgICAgICBzZXR0aW5ncy5vcmlnaW5hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9IHNldHRpbmdzLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNldHRpbmdzLm9yaWdpbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlID0gc2V0dGluZ3MuZGVjaW1hbFBsYWNlcztcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2NhbGN1bGF0ZURlY2ltYWxQbGFjZXNPbkluaXQoc2V0dGluZ3MpO1xuXG4gICAgICAgIC8vIERpdmlkZSB0aGUgcmF3IHZhbHVlIHdpdGggYHJhd1ZhbHVlRGl2aXNvcmAgaWYgZGVmaW5lZFxuICAgICAgICBpZiAoKCFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkoc2V0dGluZ3MucmF3VmFsdWVEaXZpc29yKSAmJiBzZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3IgIT09IDApICYmIC8vIE9ubHkgZGl2aWRlIGlmIHRoZSBgcmF3VmFsdWVEaXZpc29yYCBvcHRpb24gaXMgc2V0XG4gICAgICAgICAgICB2YWx1ZSAhPT0gJycgJiYgdmFsdWUgIT09IG51bGwpIHsgLy8gRG8gbm90IG1vZGlmeSB0aGUgYHZhbHVlYCBpZiBpdCdzIGFuIGVtcHR5IHN0cmluZyBvciBudWxsXG4gICAgICAgICAgICB2YWx1ZSAvPSBzZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3I7XG4gICAgICAgIH1cblxuICAgICAgICB2YWx1ZSA9IHRoaXMuX3JvdW5kUmF3VmFsdWUodmFsdWUsIHNldHRpbmdzKTtcbiAgICAgICAgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKHNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIsICcuJyk7IC8vIEhlcmUgd2UgbmVlZCB0byBjb252ZXJ0IGJhY2sgdGhlIGRlY2ltYWwgY2hhcmFjdGVyIHRvIGEgcGVyaW9kIHNpbmNlIGBfcm91bmRWYWx1ZWAgYWRkcyBpdCBpbiBzb21lIGNhc2VzXG4gICAgICAgIHZhbHVlID0gdGhpcy5fdG9Mb2NhbGUodmFsdWUsIHNldHRpbmdzLm91dHB1dEZvcm1hdCwgc2V0dGluZ3MpO1xuXG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVbmZvcm1hdCB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQgdmFsdWUsIGFuZCBzZXQgdGhlIHJlc3VsdGluZyB2YWx1ZSBiYWNrIGFzIHRoZSBlbGVtZW50IHZhbHVlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fSBkb21FbGVtZW50XG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnNcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBzdGF0aWMgdW5mb3JtYXRBbmRTZXQoZG9tRWxlbWVudCwgb3B0aW9ucyA9IG51bGwpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgY29uc3QgdW5mb3JtYXR0ZWRWYWx1ZSA9IHRoaXMudW5mb3JtYXQoZG9tRWxlbWVudCwgb3B0aW9ucyk7XG4gICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRWYWx1ZShkb21FbGVtZW50LCB1bmZvcm1hdHRlZFZhbHVlKTtcblxuICAgICAgICByZXR1cm4gdW5mb3JtYXR0ZWRWYWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVbmZvcm1hdCBhbmQgbG9jYWxpemUgdGhlIGdpdmVuIGZvcm1hdHRlZCBzdHJpbmcgd2l0aCB0aGUgZ2l2ZW4gb3B0aW9ucy4gVGhpcyByZXR1cm5zIGEgbnVtZXJpYyBzdHJpbmcuXG4gICAgICogSXQgY2FuIGFsc28gdW5mb3JtYXQgYW5kIGxvY2FsaXplIHRoZSBnaXZlbiBET00gZWxlbWVudCB2YWx1ZSB3aXRoIHRoZSBnaXZlbiBvcHRpb25zIGFuZCByZXR1cm5zIHRoZSB1bmZvcm1hdHRlZCBudW1lcmljIHN0cmluZy5cbiAgICAgKiBOb3RlOiBUaGlzIGRvZXMgKm5vdCogdXBkYXRlIHRoYXQgZWxlbWVudCB2YWx1ZS5cbiAgICAgKiBUaGlzIGJhc2ljYWxseSBhbGxvd3MgdG8gZ2V0IHRoZSBsb2NhbGl6ZWQgdmFsdWUgd2l0aG91dCBmaXJzdCBoYXZpbmcgdG8gaW5pdGlhbGl6ZSBhbiBBdXRvTnVtZXJpYyBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ8SFRNTEVsZW1lbnR8SFRNTElucHV0RWxlbWVudH0gbnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudFxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyBsb2NhbGl6ZShudW1lcmljU3RyaW5nT3JEb21FbGVtZW50LCBzZXR0aW5ncyA9IG51bGwpIHtcbiAgICAgICAgbGV0IHZhbHVlO1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNFbGVtZW50KG51bWVyaWNTdHJpbmdPckRvbUVsZW1lbnQpKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZShudW1lcmljU3RyaW5nT3JEb21FbGVtZW50KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhbHVlID0gbnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh2YWx1ZSA9PT0gJycpIHtcbiAgICAgICAgICAgIC8vIFRoaXMgYWxsb3dzIHRvIGJlIGNvaGVyZW50IHdoZW4gc2VyaWFsaXppbmcgZm9ybXMgd2l0aCBlbXB0eSBpbnB1dHMuIEZpeCBpc3N1ZSAjNTEyLlxuICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChzZXR0aW5ncykpIHtcbiAgICAgICAgICAgIHNldHRpbmdzID0gQXV0b051bWVyaWMuZGVmYXVsdFNldHRpbmdzO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFsdWUgPSB0aGlzLnVuZm9ybWF0KHZhbHVlLCBzZXR0aW5ncyk7XG5cbiAgICAgICAgLy9YWFggVGhlIGZvbGxvd2luZyBjb2RlIGlzIHByZXR0eSBjbG9zZSB0byB0aGUgb25lIHlvdSBjYW4gZmluZCBpbiBgZ2V0TG9jYWxpemVkKClgLCBidXQgZGlmZmVyZW50IGVub3VnaCBzbyB3ZSB3b24ndCByZWZhY3RvciBpdC5cbiAgICAgICAgaWYgKE51bWJlcih2YWx1ZSkgPT09IDAgJiYgc2V0dGluZ3MubGVhZGluZ1plcm8gIT09IEF1dG9OdW1lcmljLm9wdGlvbnMubGVhZGluZ1plcm8ua2VlcCkge1xuICAgICAgICAgICAgdmFsdWUgPSAnMCc7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgb3V0cHV0Rm9ybWF0VG9Vc2U7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoc2V0dGluZ3MpKSB7XG4gICAgICAgICAgICBvdXRwdXRGb3JtYXRUb1VzZSA9IHNldHRpbmdzLm91dHB1dEZvcm1hdDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG91dHB1dEZvcm1hdFRvVXNlID0gQXV0b051bWVyaWMuZGVmYXVsdFNldHRpbmdzLm91dHB1dEZvcm1hdDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLl90b0xvY2FsZSh2YWx1ZSwgb3V0cHV0Rm9ybWF0VG9Vc2UsIHNldHRpbmdzKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgbG9jYWxpemVBbmRTZXQoZG9tRWxlbWVudCwgb3B0aW9ucyA9IG51bGwpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgY29uc3QgbG9jYWxpemVkVmFsdWUgPSB0aGlzLmxvY2FsaXplKGRvbUVsZW1lbnQsIG9wdGlvbnMpO1xuICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5zZXRFbGVtZW50VmFsdWUoZG9tRWxlbWVudCwgbG9jYWxpemVkVmFsdWUpO1xuXG4gICAgICAgIHJldHVybiBsb2NhbGl6ZWRWYWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBnaXZlbiBET00gZWxlbWVudCBoYXMgYW4gQXV0b051bWVyaWMgb2JqZWN0IHRoYXQgbWFuYWdlcyBpdC5cbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGFsc28gYWNjZXB0cyBhIHNlbGVjdG9yIHN0cmluZy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8c3RyaW5nfSBkb21FbGVtZW50T3JTZWxlY3RvciBBY2NlcHRzIGVpdGhlciBkaXJlY3RseSBhIERPTSBlbGVtZW50IHRvIHRlc3QsIG9yIGEgc3RyaW5nIHNlbGVjdG9yICh0aGF0IHdpbGwgcmV0dXJuIG9uZSBhbmQgb25seSBvbmUgZWxlbWVudCwgaWYgYW55KVxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIHN0YXRpYyBpc01hbmFnZWRCeUF1dG9OdW1lcmljKGRvbUVsZW1lbnRPclNlbGVjdG9yKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIHJldHVybiB0aGlzLl9pc0luR2xvYmFsTGlzdChBdXRvTnVtZXJpY0hlbHBlci5kb21FbGVtZW50KGRvbUVsZW1lbnRPclNlbGVjdG9yKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QgdGhhdCBtYW5hZ2VzIHRoZSBnaXZlbiBET00gZWxlbWVudC5cbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGFsc28gYWNjZXB0cyBhIHNlbGVjdG9yIHN0cmluZy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8c3RyaW5nfSBkb21FbGVtZW50T3JTZWxlY3RvciBBY2NlcHRzIGVpdGhlciBkaXJlY3RseSBhIERPTSBlbGVtZW50IHRvIHRlc3QsIG9yIGEgc3RyaW5nIHNlbGVjdG9yICh0aGF0IHdpbGwgcmV0dXJuIG9uZSBhbmQgb25seSBvbmUgZWxlbWVudCwgaWYgYW55KVxuICAgICAqIEByZXR1cm5zIHtudWxsfEF1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRBdXRvTnVtZXJpY0VsZW1lbnQoZG9tRWxlbWVudE9yU2VsZWN0b3IpIHtcbiAgICAgICAgY29uc3QgZG9tRWxlbWVudCA9IEF1dG9OdW1lcmljSGVscGVyLmRvbUVsZW1lbnQoZG9tRWxlbWVudE9yU2VsZWN0b3IpO1xuXG4gICAgICAgIGlmICghdGhpcy5pc01hbmFnZWRCeUF1dG9OdW1lcmljKGRvbUVsZW1lbnQpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRGcm9tR2xvYmFsTGlzdChkb21FbGVtZW50KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGdpdmVuIGVsZW1lbnQgdmFsdWUsIGFuZCBmb3JtYXQgaXQgaW1tZWRpYXRlbHkuXG4gICAgICogUmV0dXJuIGBudWxsYCBpZiBubyBBdXRvTnVtZXJpYyBvYmplY3QgaXMgZm91bmQsIGVsc2UsIHJldHVybiB0aGUgQXV0b051bWVyaWMgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxzdHJpbmd9IGRvbUVsZW1lbnRPclNlbGVjdG9yIEVpdGhlciBhIERPTSBlbGVtZW50IHJlZmVyZW5jZSwgb3IgYSBzZWxlY3RvciBzdHJpbmcgY2FuIGJlIHVzZWRcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd8bnVsbH0gbmV3VmFsdWUgVGhlIHZhbHVlIG11c3QgYmUgYSBOdW1iZXIsIGEgbnVtZXJpYyBzdHJpbmcgb3IgYG51bGxgIChpZiBgZW1wdHlJbnB1dEJlaGF2aW9yYCBpcyBzZXQgdG8gYCdudWxsJ2ApXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnMgQSBzZXR0aW5ncyBvYmplY3QgdGhhdCB3aWxsIG92ZXJyaWRlIHRoZSBjdXJyZW50IHNldHRpbmdzLiBOb3RlOiB0aGUgdXBkYXRlIGlzIGRvbmUgb25seSBpZiB0aGUgYG5ld1ZhbHVlYCBpcyBkZWZpbmVkLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gc2F2ZUNoYW5nZVRvSGlzdG9yeSBJZiBzZXQgdG8gYHRydWVgLCB0aGVuIHRoZSBjaGFuZ2UgaXMgcmVjb3JkZWQgaW4gdGhlIGhpc3RvcnkgdGFibGVcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN8bnVsbH1cbiAgICAgKi9cbiAgICBzdGF0aWMgc2V0KGRvbUVsZW1lbnRPclNlbGVjdG9yLCBuZXdWYWx1ZSwgb3B0aW9ucyA9IG51bGwsIHNhdmVDaGFuZ2VUb0hpc3RvcnkgPSB0cnVlKSB7XG4gICAgICAgIGNvbnN0IGRvbUVsZW1lbnQgPSBBdXRvTnVtZXJpY0hlbHBlci5kb21FbGVtZW50KGRvbUVsZW1lbnRPclNlbGVjdG9yKTtcblxuICAgICAgICBpZiAoIXRoaXMuaXNNYW5hZ2VkQnlBdXRvTnVtZXJpYyhkb21FbGVtZW50KSkge1xuICAgICAgICAgICAgbGV0IHNob3dXYXJuaW5ncztcbiAgICAgICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMpICYmIG9wdGlvbnMuaGFzT3duUHJvcGVydHkoJ3Nob3dXYXJuaW5ncycpKSB7XG4gICAgICAgICAgICAgICAgc2hvd1dhcm5pbmdzID0gb3B0aW9ucy5zaG93V2FybmluZ3M7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNob3dXYXJuaW5ncyA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLndhcm5pbmcoYEltcG9zc2libGUgdG8gZmluZCBhbiBBdXRvTnVtZXJpYyBvYmplY3QgZm9yIHRoZSBnaXZlbiBET00gZWxlbWVudCBvciBzZWxlY3Rvci5gLCBzaG93V2FybmluZ3MpO1xuXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLmdldEF1dG9OdW1lcmljRWxlbWVudChkb21FbGVtZW50KS5zZXQobmV3VmFsdWUsIG9wdGlvbnMsIHNhdmVDaGFuZ2VUb0hpc3RvcnkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgdW5mb3JtYXR0ZWQgdmFsdWUgYXMgYSBzdHJpbmcgZnJvbSB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQgb3IgcXVlcnkgc2VsZWN0b3IuXG4gICAgICogVGhpcyBjYW4gYWxzbyByZXR1cm4gYG51bGxgIGlmIGByYXdWYWx1ZWAgaXMgbnVsbC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8c3RyaW5nfSBkb21FbGVtZW50T3JTZWxlY3RvclxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb258bnVsbH0gY2FsbGJhY2tcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9XG4gICAgICovXG4gICAgc3RhdGljIGdldE51bWVyaWNTdHJpbmcoZG9tRWxlbWVudE9yU2VsZWN0b3IsIGNhbGxiYWNrID0gbnVsbCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0KGRvbUVsZW1lbnRPclNlbGVjdG9yLCAnZ2V0TnVtZXJpY1N0cmluZycsIGNhbGxiYWNrKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIGN1cnJlbnQgZm9ybWF0dGVkIHZhbHVlIG9mIHRoZSBBdXRvTnVtZXJpYyBlbGVtZW50IGFzIGEgc3RyaW5nLCBmcm9tIHRoZSBnaXZlbiBET00gZWxlbWVudCBvciBxdWVyeSBzZWxlY3Rvci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8c3RyaW5nfSBkb21FbGVtZW50T3JTZWxlY3RvclxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb258bnVsbH0gY2FsbGJhY2tcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRGb3JtYXR0ZWQoZG9tRWxlbWVudE9yU2VsZWN0b3IsIGNhbGxiYWNrID0gbnVsbCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0KGRvbUVsZW1lbnRPclNlbGVjdG9yLCAnZ2V0Rm9ybWF0dGVkJywgY2FsbGJhY2spO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgZWxlbWVudCB1bmZvcm1hdHRlZCB2YWx1ZSBhcyBhIHJlYWwgSmF2YXNjcmlwdCBudW1iZXIsIGZyb20gdGhlIGdpdmVuIERPTSBlbGVtZW50IG9yIHF1ZXJ5IHNlbGVjdG9yLlxuICAgICAqIFdhcm5pbmc6IFRoaXMgY2FuIGxlYWQgdG8gcHJlY2lzaW9uIHByb2JsZW1zIHdpdGggYmlnIG51bWJlcnMgdGhhdCBzaG91bGQgYmUgc3RvcmVkIGFzIHN0cmluZ3MuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fHN0cmluZ30gZG9tRWxlbWVudE9yU2VsZWN0b3JcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufG51bGx9IGNhbGxiYWNrXG4gICAgICogQHJldHVybnMge251bWJlcnxudWxsfVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXROdW1iZXIoZG9tRWxlbWVudE9yU2VsZWN0b3IsIGNhbGxiYWNrID0gbnVsbCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0KGRvbUVsZW1lbnRPclNlbGVjdG9yLCAnZ2V0TnVtYmVyJywgY2FsbGJhY2spO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERSWSB0aGUgY29kZSBiZXR3ZWVuIHRoZSBzdGF0aWMgYGdldCpgIGZ1bmN0aW9uc1xuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxzdHJpbmd9IGRvbUVsZW1lbnRPclNlbGVjdG9yXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGdldEZ1bmN0aW9uIFRoZSBuYW1lIG9mIHRoZSBub24tc3RhdGljIGBnZXQqYCBmdW5jdGlvbiBhcyBhIHN0cmluZ1xuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb258bnVsbH0gY2FsbGJhY2tcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfZ2V0KGRvbUVsZW1lbnRPclNlbGVjdG9yLCBnZXRGdW5jdGlvbiwgY2FsbGJhY2sgPSBudWxsKSB7XG4gICAgICAgIGNvbnN0IGRvbUVsZW1lbnQgPSBBdXRvTnVtZXJpY0hlbHBlci5kb21FbGVtZW50KGRvbUVsZW1lbnRPclNlbGVjdG9yKTtcblxuICAgICAgICBpZiAoIXRoaXMuaXNNYW5hZ2VkQnlBdXRvTnVtZXJpYyhkb21FbGVtZW50KSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgSW1wb3NzaWJsZSB0byBmaW5kIGFuIEF1dG9OdW1lcmljIG9iamVjdCBmb3IgdGhlIGdpdmVuIERPTSBlbGVtZW50IG9yIHNlbGVjdG9yLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0QXV0b051bWVyaWNFbGVtZW50KGRvbUVsZW1lbnQpW2dldEZ1bmN0aW9uXShjYWxsYmFjayk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgdW5mb3JtYXR0ZWQgdmFsdWUgZm9sbG93aW5nIHRoZSBgb3V0cHV0Rm9ybWF0YCBzZXR0aW5nLCBmcm9tIHRoZSBnaXZlbiBET00gZWxlbWVudCBvciBxdWVyeSBzZWxlY3Rvci5cbiAgICAgKiBTZWUgdGhlIG5vbi1zdGF0aWMgYGdldExvY2FsaXplZCgpYCBtZXRob2QgZG9jdW1lbnRhdGlvbiBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxzdHJpbmd9IGRvbUVsZW1lbnRPclNlbGVjdG9yXG4gICAgICogQHBhcmFtIHtudWxsfHN0cmluZ3xmdW5jdGlvbn0gZm9yY2VkT3V0cHV0Rm9ybWF0XG4gICAgICogQHBhcmFtIHtmdW5jdGlvbnxudWxsfSBjYWxsYmFja1xuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRMb2NhbGl6ZWQoZG9tRWxlbWVudE9yU2VsZWN0b3IsIGZvcmNlZE91dHB1dEZvcm1hdCA9IG51bGwsIGNhbGxiYWNrID0gbnVsbCkge1xuICAgICAgICBjb25zdCBkb21FbGVtZW50ID0gQXV0b051bWVyaWNIZWxwZXIuZG9tRWxlbWVudChkb21FbGVtZW50T3JTZWxlY3Rvcik7XG5cbiAgICAgICAgaWYgKCF0aGlzLmlzTWFuYWdlZEJ5QXV0b051bWVyaWMoZG9tRWxlbWVudCkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYEltcG9zc2libGUgdG8gZmluZCBhbiBBdXRvTnVtZXJpYyBvYmplY3QgZm9yIHRoZSBnaXZlbiBET00gZWxlbWVudCBvciBzZWxlY3Rvci5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLmdldEF1dG9OdW1lcmljRWxlbWVudChkb21FbGVtZW50KS5nZXRMb2NhbGl6ZWQoZm9yY2VkT3V0cHV0Rm9ybWF0LCBjYWxsYmFjayk7XG4gICAgfVxuXG4gICAgLy8gUHJlLWRlZmluZWQgb3B0aW9ucyBjYW4gYmUgY2FsbGVkIHRvIHVwZGF0ZSB0aGUgY3VycmVudCBkZWZhdWx0IG9wdGlvbnMgd2l0aCB0aGVpciBzcGVjaWZpY2l0aWVzXG4gICAgLy9YWFggQSBiZXR0ZXIgd2F5IHdvdWxkIGJlIHRvIG5vdCBpbml0aWFsaXplIGZpcnN0LCBidXQgdGhhdCdzIG5vdCBwb3NzaWJsZSBzaW5jZSBgbmV3YCBpcyBjYWxsZWQgZmlyc3QgYW5kIHdlIGRvIG5vdCBwYXNzIHRoZSBsYW5ndWFnZSBvcHRpb25zIChpZS4gYEZyZW5jaGApIHRvIHRoZSBjb25zdHJ1Y3RvclxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlIHRoZSBBdXRvTnVtZXJpYyBvYmplY3Qgd2l0aCB0aGUgcHJlZGVmaW5lZCBvcHRpb25zLCBhbmQgcG9zc2libHkgc29tZSBvcHRpb24gb3ZlcnJpZGVzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHByZWRlZmluZWRPcHRpb25cbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uT3ZlcnJpZGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBfdXBkYXRlUHJlZGVmaW5lZE9wdGlvbnMocHJlZGVmaW5lZE9wdGlvbiwgb3B0aW9uT3ZlcnJpZGUgPSBudWxsKSB7XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbk92ZXJyaWRlKSkge1xuICAgICAgICAgICAgdGhpcy5fbWVyZ2VTZXR0aW5ncyhwcmVkZWZpbmVkT3B0aW9uLCBvcHRpb25PdmVycmlkZSk7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZSh0aGlzLnNldHRpbmdzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlKHByZWRlZmluZWRPcHRpb24pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlIHRoZSBzZXR0aW5ncyB0byB1c2UgdGhlIEZyZW5jaCBwcmUtZGVmaW5lZCBsYW5ndWFnZSBvcHRpb25zLlxuICAgICAqIFRob3NlIHByZS1kZWZpbmVkIG9wdGlvbnMgY2FuIGJlIG92ZXJyaWRkZW4gYnkgcGFzc2luZyBhbiBvcHRpb24gb2JqZWN0IGFzIGEgcGFyYW1ldGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbk92ZXJyaWRlXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGZyZW5jaChvcHRpb25PdmVycmlkZSA9IG51bGwpIHtcbiAgICAgICAgdGhpcy5fdXBkYXRlUHJlZGVmaW5lZE9wdGlvbnMoQXV0b051bWVyaWMuZ2V0UHJlZGVmaW5lZE9wdGlvbnMoKS5GcmVuY2gsIG9wdGlvbk92ZXJyaWRlKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGhlIHNldHRpbmdzIHRvIHVzZSB0aGUgTm9ydGggQW1lcmljYW4gcHJlLWRlZmluZWQgbGFuZ3VhZ2Ugb3B0aW9ucy5cbiAgICAgKiBUaG9zZSBwcmUtZGVmaW5lZCBvcHRpb25zIGNhbiBiZSBvdmVycmlkZGVuIGJ5IHBhc3NpbmcgYW4gb3B0aW9uIG9iamVjdCBhcyBhIHBhcmFtZXRlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25PdmVycmlkZVxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBub3J0aEFtZXJpY2FuKG9wdGlvbk92ZXJyaWRlID0gbnVsbCkge1xuICAgICAgICB0aGlzLl91cGRhdGVQcmVkZWZpbmVkT3B0aW9ucyhBdXRvTnVtZXJpYy5nZXRQcmVkZWZpbmVkT3B0aW9ucygpLk5vcnRoQW1lcmljYW4sIG9wdGlvbk92ZXJyaWRlKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGhlIHNldHRpbmdzIHRvIHVzZSB0aGUgQnJpdGlzaCBwcmUtZGVmaW5lZCBsYW5ndWFnZSBvcHRpb25zLlxuICAgICAqIFRob3NlIHByZS1kZWZpbmVkIG9wdGlvbnMgY2FuIGJlIG92ZXJyaWRkZW4gYnkgcGFzc2luZyBhbiBvcHRpb24gb2JqZWN0IGFzIGEgcGFyYW1ldGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbk92ZXJyaWRlXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGJyaXRpc2gob3B0aW9uT3ZlcnJpZGUgPSBudWxsKSB7XG4gICAgICAgIHRoaXMuX3VwZGF0ZVByZWRlZmluZWRPcHRpb25zKEF1dG9OdW1lcmljLmdldFByZWRlZmluZWRPcHRpb25zKCkuQnJpdGlzaCwgb3B0aW9uT3ZlcnJpZGUpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZSB0aGUgc2V0dGluZ3MgdG8gdXNlIHRoZSBTd2lzcyBwcmUtZGVmaW5lZCBsYW5ndWFnZSBvcHRpb25zLlxuICAgICAqIFRob3NlIHByZS1kZWZpbmVkIG9wdGlvbnMgY2FuIGJlIG92ZXJyaWRkZW4gYnkgcGFzc2luZyBhbiBvcHRpb24gb2JqZWN0IGFzIGEgcGFyYW1ldGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbk92ZXJyaWRlXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIHN3aXNzKG9wdGlvbk92ZXJyaWRlID0gbnVsbCkge1xuICAgICAgICB0aGlzLl91cGRhdGVQcmVkZWZpbmVkT3B0aW9ucyhBdXRvTnVtZXJpYy5nZXRQcmVkZWZpbmVkT3B0aW9ucygpLlN3aXNzLCBvcHRpb25PdmVycmlkZSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlIHRoZSBzZXR0aW5ncyB0byB1c2UgdGhlIEphcGFuZXNlIHByZS1kZWZpbmVkIGxhbmd1YWdlIG9wdGlvbnMuXG4gICAgICogVGhvc2UgcHJlLWRlZmluZWQgb3B0aW9ucyBjYW4gYmUgb3ZlcnJpZGRlbiBieSBwYXNzaW5nIGFuIG9wdGlvbiBvYmplY3QgYXMgYSBwYXJhbWV0ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uT3ZlcnJpZGVcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgamFwYW5lc2Uob3B0aW9uT3ZlcnJpZGUgPSBudWxsKSB7XG4gICAgICAgIHRoaXMuX3VwZGF0ZVByZWRlZmluZWRPcHRpb25zKEF1dG9OdW1lcmljLmdldFByZWRlZmluZWRPcHRpb25zKCkuSmFwYW5lc2UsIG9wdGlvbk92ZXJyaWRlKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGhlIHNldHRpbmdzIHRvIHVzZSB0aGUgU3BhbmlzaCBwcmUtZGVmaW5lZCBsYW5ndWFnZSBvcHRpb25zLlxuICAgICAqIFRob3NlIHByZS1kZWZpbmVkIG9wdGlvbnMgY2FuIGJlIG92ZXJyaWRkZW4gYnkgcGFzc2luZyBhbiBvcHRpb24gb2JqZWN0IGFzIGEgcGFyYW1ldGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbk92ZXJyaWRlXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIHNwYW5pc2gob3B0aW9uT3ZlcnJpZGUgPSBudWxsKSB7XG4gICAgICAgIHRoaXMuX3VwZGF0ZVByZWRlZmluZWRPcHRpb25zKEF1dG9OdW1lcmljLmdldFByZWRlZmluZWRPcHRpb25zKCkuU3BhbmlzaCwgb3B0aW9uT3ZlcnJpZGUpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZSB0aGUgc2V0dGluZ3MgdG8gdXNlIHRoZSBDaGluZXNlIHByZS1kZWZpbmVkIGxhbmd1YWdlIG9wdGlvbnMuXG4gICAgICogVGhvc2UgcHJlLWRlZmluZWQgb3B0aW9ucyBjYW4gYmUgb3ZlcnJpZGRlbiBieSBwYXNzaW5nIGFuIG9wdGlvbiBvYmplY3QgYXMgYSBwYXJhbWV0ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uT3ZlcnJpZGVcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgY2hpbmVzZShvcHRpb25PdmVycmlkZSA9IG51bGwpIHtcbiAgICAgICAgdGhpcy5fdXBkYXRlUHJlZGVmaW5lZE9wdGlvbnMoQXV0b051bWVyaWMuZ2V0UHJlZGVmaW5lZE9wdGlvbnMoKS5DaGluZXNlLCBvcHRpb25PdmVycmlkZSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlIHRoZSBzZXR0aW5ncyB0byB1c2UgdGhlIEJyYXppbGlhbiBwcmUtZGVmaW5lZCBsYW5ndWFnZSBvcHRpb25zLlxuICAgICAqIFRob3NlIHByZS1kZWZpbmVkIG9wdGlvbnMgY2FuIGJlIG92ZXJyaWRkZW4gYnkgcGFzc2luZyBhbiBvcHRpb24gb2JqZWN0IGFzIGEgcGFyYW1ldGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbk92ZXJyaWRlXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGJyYXppbGlhbihvcHRpb25PdmVycmlkZSA9IG51bGwpIHtcbiAgICAgICAgdGhpcy5fdXBkYXRlUHJlZGVmaW5lZE9wdGlvbnMoQXV0b051bWVyaWMuZ2V0UHJlZGVmaW5lZE9wdGlvbnMoKS5CcmF6aWxpYW4sIG9wdGlvbk92ZXJyaWRlKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8vIEludGVybmFsIHByaXZhdGUgZnVuY3Rpb25zXG4gICAgLyoqXG4gICAgICogUnVuIGFueSBjYWxsYmFja3MgZm91bmQgaW4gdGhlIHNldHRpbmdzIG9iamVjdCBpbiBvcmRlciB0byBzZXQgdGhlIHNldHRpbmdzIHZhbHVlIGJhY2suXG4gICAgICogQW55IHBhcmFtZXRlciBjYW4gaGF2ZSBhIGNhbGxiYWNrIGRlZmluZWQuXG4gICAgICogVGhlIGNhbGxiYWNrIHRha2VzIHRoZSBjdXJyZW50IEF1dG9OdW1lcmljIGVsZW1lbnQgYXMgdGhlIGZpcnN0IGFyZ3VtZW50LCBhbmQgdGhlIGtleSBuYW1lIGFzIHRoZSBzZWNvbmQuXG4gICAgICogQGV4YW1wbGUgY2FsbGJhY2sodGhpcywgJ2N1cnJlbmN5U3ltYm9sJylcbiAgICAgKi9cbiAgICBfcnVuQ2FsbGJhY2tzRm91bmRJblRoZVNldHRpbmdzT2JqZWN0KCkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICAvLyBMb29wcyB0aHJvdWdoIHRoZSB0aGlzLnNldHRpbmdzIG9iamVjdCAob3B0aW9uIGFycmF5KSB0byBmaW5kIHRoZSBmb2xsb3dpbmdcbiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gdGhpcy5zZXR0aW5ncykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gdGhpcy5zZXR0aW5nc1trZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzW2tleV0gPSB2YWx1ZSh0aGlzLCBrZXkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIENhbGxzIHRoZSBhdHRhY2hlZCBmdW5jdGlvbiBmcm9tIHRoZSBodG1sNSBkYXRhLiBGb3IgaW5zdGFuY2U6IDx0YWcgZGF0YS1jdXJyZW5jeS1zeW1ib2w9XCJmdW5jdGlvbk5hbWVcIj48L3RhZz5cbiAgICAgICAgICAgICAgICAgICAgbGV0IGh0bWxBdHRyaWJ1dGUgPSB0aGlzLmRvbUVsZW1lbnQuZ2V0QXR0cmlidXRlKGtleSk7IC8vVE9ETyBVc2UgYGRhdGFzZXRgIGluc3RlYWQgb2YgYGdldEF0dHJpYnV0ZWAgd2hlbiB3ZSB3b24ndCBuZWVkIHRvIHN1cHBvcnQgb2Jzb2xldGUgYnJvd3NlcnNcbiAgICAgICAgICAgICAgICAgICAgaHRtbEF0dHJpYnV0ZSA9IEF1dG9OdW1lcmljSGVscGVyLmNhbWVsaXplKGh0bWxBdHRyaWJ1dGUpO1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMuc2V0dGluZ3NbaHRtbEF0dHJpYnV0ZV0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Nba2V5XSA9IGh0bWxBdHRyaWJ1dGUodGhpcywga2V5KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEtlZXAgdHJhY2sgaWYgdGhlIHNldHRpbmdzIGNvbmZpZ3VyYXRpb24gbGVhZHMgdG8gYSB0cmFpbGluZyBuZWdhdGl2ZSBzaWduIChvbmx5IHdoZW4gdGhlIHJhdyB2YWx1ZSBpcyBuZWdhdGl2ZSksIHNvIHdlIGRvIG5vdCBoYXZlIHRvIHRlc3QgdGhlIHNldHRpbmdzIHZhbHVlcyBldmVyeSB0aW1lIHdlIG5lZWQgdG8ga25vdyB0aGF0LlxuICAgICAqIGBpc1RyYWlsaW5nTmVnYXRpdmVgIGlzIHNldCB0byBgdHJ1ZWAgaWYgdGhlIHNldHRpbmdzIHJlc3VsdCBpbiBhIHRyYWlsaW5nIG5lZ2F0aXZlIGNoYXJhY3RlciwgYGZhbHNlYCBvdGhlcndpc2UuXG4gICAgICogTm90ZTogVGhpcyByZXR1cm5zIGB0cnVlYCBldmVuIGlmIHRoZSByYXcgdmFsdWUgaXMgcG9zaXRpdmUuXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfc2V0VHJhaWxpbmdOZWdhdGl2ZVNpZ25JbmZvKCkge1xuICAgICAgICB0aGlzLmlzVHJhaWxpbmdOZWdhdGl2ZSA9ICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnByZWZpeCAmJiB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnN1ZmZpeCkgfHxcbiAgICAgICAgKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQuc3VmZml4ICYmXG4gICAgICAgICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LmxlZnQgfHwgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN0cmlwIGFsbCB0aGUgdW53YW50ZWQgbm9uLW51bWJlciBjaGFyYWN0ZXJzLlxuICAgICAqIEhvd2V2ZXIgaXQgZG9lcyBub3QgcmVvcmRlciB0aGUgbG9jYWxpemVkIG5lZ2F0aXZlIHNpZ24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc1xuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gc3RyaXBaZXJvcyBJZiBzZXQgdG8gYGZhbHNlYCwgdGhlbiB0aGUgbGVhZGluZyB6ZXJvKHMpIGFyZSBub3Qgc3RyaXBwZWQsIG90aGVyd2lzZSBpZiBzZXQgdG8gYHRydWVgLCB0aGUgYGxlYWRpbmdaZXJvYCBvcHRpb24gaXMgZm9sbG93ZWRcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGlzRm9jdXNlZCBJZiB0aGUgZWxlbWVudCBpcyBmb2N1c2VkLCB0aGVuIHRoaXMgaXMgYHRydWVgXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfc3RyaXBBbGxOb25OdW1iZXJDaGFyYWN0ZXJzKHMsIHNldHRpbmdzLCBzdHJpcFplcm9zLCBpc0ZvY3VzZWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3N0cmlwQWxsTm9uTnVtYmVyQ2hhcmFjdGVyc0V4Y2VwdEN1c3RvbURlY2ltYWxDaGFyKHMsIHNldHRpbmdzLCBzdHJpcFplcm9zLCBpc0ZvY3VzZWQpLnJlcGxhY2Uoc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlciwgJy4nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTdHJpcCBhbGwgdW53YW50ZWQgbm9uLW51bWJlciBjaGFyYWN0ZXJzIGV4Y2VwdCB0aGUgY3VzdG9tIGRlY2ltYWwgY2hhcmFjdGVyLlxuICAgICAqXG4gICAgICogSXQgY29udmVydHMgdGhlIGN1c3RvbSBuZWdhdGl2ZSBzaWduIGFuZCByZW1vdmVzIHRoZSBwb3NpdGl2ZSBzaWduIChjdXN0b20gb3Igbm90KS5cbiAgICAgKiBUaGlzIGtlZXBzIDpcbiAgICAgKiAtIHRoZSBudW1iZXJzLFxuICAgICAqIC0gdGhlIG5vcm1hbCBuZWdhdGl2ZSBzaWduICctJyBpZiBhbnksXG4gICAgICogLSBhbmQgdGhlICpjdXN0b20qIGRlY2ltYWwgY2hhcmFjdGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHN0cmlwWmVyb3MgSWYgc2V0IHRvIGBmYWxzZWAsIHRoZW4gdGhlIGxlYWRpbmcgemVybyhzKSBhcmUgbm90IHN0cmlwcGVkLCBvdGhlcndpc2UgaWYgc2V0IHRvIGB0cnVlYCwgdGhlIGBsZWFkaW5nWmVyb2Agb3B0aW9uIGlzIGZvbGxvd2VkXG4gICAgICogQHBhcmFtIHtib29sZWFufSBpc0ZvY3VzZWQgSWYgdGhlIGVsZW1lbnQgaXMgZm9jdXNlZCwgdGhlbiB0aGlzIGlzIGB0cnVlYFxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8Kn1cbiAgICAgKi9cbiAgICBzdGF0aWMgX3N0cmlwQWxsTm9uTnVtYmVyQ2hhcmFjdGVyc0V4Y2VwdEN1c3RvbURlY2ltYWxDaGFyKHMsIHNldHRpbmdzLCBzdHJpcFplcm9zLCBpc0ZvY3VzZWQpIHtcbiAgICAgICAgLy9YWFggTm90ZTsgdGhpcyBmdW5jdGlvbiBpcyBzdGF0aWMgc2luY2Ugd2UgbmVlZCB0byBwYXNzIGEgYHNldHRpbmdzYCBvYmplY3Qgd2hlbiBjYWxsaW5nIHRoZSBzdGF0aWMgYEF1dG9OdW1lcmljLmZvcm1hdCgpYCBtZXRob2RcbiAgICAgICAgLy9UT0RPIFRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIDEwIHRpbWVzIChzaWMhKSBvbiBlYWNoIGtleSBpbnB1dCwgY291bGRuJ3Qgd2UgbG93ZXIgdGhhdCBudW1iZXI/IGNmLiBpc3N1ZSAjMzI1XG4gICAgICAgIHMgPSB0aGlzLl9ub3JtYWxpemVDdXJyZW5jeVN1ZmZpeEFuZE5lZ2F0aXZlU2lnbkNoYXJhY3RlcnMocywgc2V0dGluZ3MpO1xuXG4gICAgICAgIC8vIFRoZW4gcmVtb3ZlIGFsbCB0aGUgY2hhcmFjdGVycyB0aGF0IGFyZSBub3QgbnVtYmVycywgdGhlIG5vcm1hbCBuZWdhdGl2ZSBzaWduICctJywgb3IgdGhlIGN1c3RvbSBkZWNpbWFsIGNoYXJhY3RlciAobm90ZTogdGhpcyBhbHNvIHJlbW92ZSBhbnkgY3VzdG9tIHBvc2l0aXZlIHNpZ24pXG4gICAgICAgIHMgPSBzLnJlcGxhY2Uoc2V0dGluZ3MuYWxsb3dlZEF1dG9TdHJpcCwgJycpO1xuXG4gICAgICAgIC8vIEdldCBvbmx5IG51bWJlciBzdHJpbmdcbiAgICAgICAgY29uc3QgbSA9IHMubWF0Y2goc2V0dGluZ3MubnVtUmVnQXV0b1N0cmlwKTtcbiAgICAgICAgcyA9IG0gPyBbbVsxXSwgbVsyXSwgbVszXV0uam9pbignJykgOiAnJztcblxuICAgICAgICBpZiAoc2V0dGluZ3MubGVhZGluZ1plcm8gPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubGVhZGluZ1plcm8uYWxsb3cgfHwgc2V0dGluZ3MubGVhZGluZ1plcm8gPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubGVhZGluZ1plcm8ua2VlcCkge1xuICAgICAgICAgICAgbGV0IG5lZ2F0aXZlU2lnbiA9ICcnO1xuICAgICAgICAgICAgY29uc3QgW2ludGVnZXJQYXJ0LCBkZWNpbWFsUGFydF0gPSBzLnNwbGl0KHNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpO1xuICAgICAgICAgICAgbGV0IG1vZGlmaWVkSW50ZWdlclBhcnQgPSBpbnRlZ2VyUGFydDtcbiAgICAgICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyhtb2RpZmllZEludGVnZXJQYXJ0LCBzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpKSB7XG4gICAgICAgICAgICAgICAgbmVnYXRpdmVTaWduID0gc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyO1xuICAgICAgICAgICAgICAgIG1vZGlmaWVkSW50ZWdlclBhcnQgPSBtb2RpZmllZEludGVnZXJQYXJ0LnJlcGxhY2Uoc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyLCAnJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN0cmlwIGxlYWRpbmcgemVybyBvbiBwb3NpdGl2ZSB2YWx1ZSBpZiBuZWVkZWRcbiAgICAgICAgICAgIGlmIChuZWdhdGl2ZVNpZ24gPT09ICcnICYmIG1vZGlmaWVkSW50ZWdlclBhcnQubGVuZ3RoID4gc2V0dGluZ3MubUludFBvcyAmJiBtb2RpZmllZEludGVnZXJQYXJ0LmNoYXJBdCgwKSA9PT0gJzAnKSB7XG4gICAgICAgICAgICAgICAgbW9kaWZpZWRJbnRlZ2VyUGFydCA9IG1vZGlmaWVkSW50ZWdlclBhcnQuc2xpY2UoMSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN0cmlwIGxlYWRpbmcgemVybyBvbiBuZWdhdGl2ZSB2YWx1ZSBpZiBuZWVkZWRcbiAgICAgICAgICAgIGlmIChuZWdhdGl2ZVNpZ24gIT09ICcnICYmIG1vZGlmaWVkSW50ZWdlclBhcnQubGVuZ3RoID4gc2V0dGluZ3MubUludE5lZyAmJiBtb2RpZmllZEludGVnZXJQYXJ0LmNoYXJBdCgwKSA9PT0gJzAnKSB7XG4gICAgICAgICAgICAgICAgbW9kaWZpZWRJbnRlZ2VyUGFydCA9IG1vZGlmaWVkSW50ZWdlclBhcnQuc2xpY2UoMSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHMgPSBgJHtuZWdhdGl2ZVNpZ259JHttb2RpZmllZEludGVnZXJQYXJ0fSR7QXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWQoZGVjaW1hbFBhcnQpPycnOnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIgKyBkZWNpbWFsUGFydH1gO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKChzdHJpcFplcm9zICYmIHNldHRpbmdzLmxlYWRpbmdaZXJvID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmxlYWRpbmdaZXJvLmRlbnkpIHx8XG4gICAgICAgICAgICAoIWlzRm9jdXNlZCAmJiBzZXR0aW5ncy5sZWFkaW5nWmVybyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5sZWFkaW5nWmVyby5hbGxvdykpIHtcbiAgICAgICAgICAgIHMgPSBzLnJlcGxhY2Uoc2V0dGluZ3Muc3RyaXBSZWcsICckMSQyJyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIG9yIHJlbW92ZXMgYnJhY2tldHMgb24gbmVnYXRpdmUgdmFsdWVzLCBkZXBlbmRpbmcgb24gdGhlIGZvY3VzIHN0YXRlLCB3aGljaCBpcyBwYXNzZWQgYXMgYGlzRm9jdXNlZGAuXG4gICAgICogVGhlIGZvY3VzIHN0YXRlIGlzICdzdG9yZWQnIGluIHRoYXQgb2JqZWN0IHByb3BlcnR5LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHBhcmFtIHtib29sZWFufSBpc0ZvY3VzZWRcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBzdGF0aWMgX3RvZ2dsZU5lZ2F0aXZlQnJhY2tldCh2YWx1ZSwgc2V0dGluZ3MsIGlzRm9jdXNlZCkge1xuICAgICAgICAvL1hYWCBOb3RlOyB0aGlzIGZ1bmN0aW9uIGlzIHN0YXRpYyBzaW5jZSB3ZSBuZWVkIHRvIHBhc3MgYSBgc2V0dGluZ3NgIG9iamVjdCB3aGVuIGNhbGxpbmcgdGhlIHN0YXRpYyBgQXV0b051bWVyaWMuZm9ybWF0KClgIG1ldGhvZFxuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBpZiAoaXNGb2N1c2VkKSB7XG4gICAgICAgICAgICByZXN1bHQgPSB0aGlzLl9yZW1vdmVCcmFja2V0cyh2YWx1ZSwgc2V0dGluZ3MpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzdWx0ID0gdGhpcy5fYWRkQnJhY2tldHModmFsdWUsIHNldHRpbmdzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkIHRoZSBicmFja2V0IHR5cGVzIHNwZWNpZmllZCBpbiB0aGUgYHNldHRpbmdzYCBvYmplY3QsIHRvIHRoZSBnaXZlbiBzdHJpbmcgYHZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2FkZEJyYWNrZXRzKHZhbHVlLCBzZXR0aW5ncykge1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKHNldHRpbmdzLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyKSkge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGAke3NldHRpbmdzLmZpcnN0QnJhY2tldH0ke3ZhbHVlLnJlcGxhY2Uoc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyLCAnJyl9JHtzZXR0aW5ncy5sYXN0QnJhY2tldH1gO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZSB0aGUgYnJhY2tldCB0eXBlcyBzcGVjaWZpZWQgaW4gdGhlIGBzZXR0aW5nc2Agb2JqZWN0LCBmcm9tIHRoZSBnaXZlbiBzdHJpbmcgYHZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gcmVhcnJhbmdlU2lnbnNBbmRWYWx1ZU9yZGVyIElmIHNldCB0byBgdHJ1ZWAsIHRoZW4gb25seSB0aGUgYnJhY2tldHMgYXJlIHJlbW92ZSBhbmQgYSBuZWdhdGl2ZSBzaWduIGlzIGFkZGVkLCB3aXRob3V0IHJlb3JkZXJpbmcgdGhlIG5lZ2F0aXZlIHNpZ24sIGN1cnJlbmN5IHN5bWJvbCBhbmQgdmFsdWUgYWNjb3JkaW5nIHRvIHRoZSBzZXR0aW5ncy5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9yZW1vdmVCcmFja2V0cyh2YWx1ZSwgc2V0dGluZ3MsIHJlYXJyYW5nZVNpZ25zQW5kVmFsdWVPcmRlciA9IHRydWUpIHtcbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoc2V0dGluZ3MubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIpICYmIHZhbHVlLmNoYXJBdCgwKSA9PT0gc2V0dGluZ3MuZmlyc3RCcmFja2V0KSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgdGhlIGJyYWNrZXRzIGlmIHRoZXkgYXJlIHByZXNlbnRcbiAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlLnJlcGxhY2Uoc2V0dGluZ3MuZmlyc3RCcmFja2V0LCAnJyk7XG4gICAgICAgICAgICByZXN1bHQgPSByZXN1bHQucmVwbGFjZShzZXR0aW5ncy5sYXN0QnJhY2tldCwgJycpO1xuXG4gICAgICAgICAgICAvLyBBZGQgYmFjayB0aGUgbmVnYXRpdmUgc2lnbiBhdCB0aGUgcmlnaHQgcGxhY2VcbiAgICAgICAgICAgIGlmIChyZWFycmFuZ2VTaWduc0FuZFZhbHVlT3JkZXIpIHtcbiAgICAgICAgICAgICAgICAvLyBGaXJzdCB3ZSBuZWVkIHRvIHJlbW92ZSB0aGUgY3VycmVuY3kgc3ltYm9sIGZyb20gdGhlIHZhbHVlLCBzaW5jZSB3ZSB3YW50IHRvIGJlIGFibGUgdG8gYWRkIGJhY2sgdGhlIG5lZ2F0aXZlIHNpZ24gYXQgdGhlIHJpZ2h0IHBsYWNlIChpbmNsdWRpbmcgYmV0d2VlbiB0aGUgdmFsdWUgYW5kIHRoZSBjdXJyZW5jeSBzaWduKVxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKHNldHRpbmdzLmN1cnJlbmN5U3ltYm9sLCAnJyk7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdGhpcy5fbWVyZ2VDdXJyZW5jeVNpZ25OZWdhdGl2ZVBvc2l0aXZlU2lnbkFuZFZhbHVlKHJlc3VsdCwgc2V0dGluZ3MsIHRydWUsIGZhbHNlKTsgLy9UT0RPIFRoaXMgYXNzdW1lIHRoZSB2YWx1ZSBpcyBuZWdhdGl2ZSBhbmQgbm9uLWVtcHR5LiBJcyB0aGlzIGFsd2F5cyB0aGUgY2FzZT9cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gSGVyZSB3ZSBvbmx5IHdhbnQgdG8gYWRkIHRoZSBuZWdhdGl2ZSBzaWduIHNpbmNlIHdlIHJlbW92ZWQgdGhlIGJyYWNrZXRzLCB3aXRob3V0IHJlb3JkZXJpbmdcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBgJHtzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXJ9JHtyZXN1bHR9YDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbmFseXplIHRoZSBgbmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXJgIG9wdGlvbnMgYW5kIGtlZXAgdHJhY2sgb2YgdGhlIGZpcnN0IGFuZCBsYXN0IGJyYWNrZXQgY2hhcmFjdGVycyB0byB1c2UuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfc2V0QnJhY2tldHMoc2V0dGluZ3MpIHtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChzZXR0aW5ncy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1cikpIHtcbiAgICAgICAgICAgIHNldHRpbmdzLmZpcnN0QnJhY2tldCA9ICcnO1xuICAgICAgICAgICAgc2V0dGluZ3MubGFzdEJyYWNrZXQgID0gJyc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBVc2UgdGVtcG9yYXJ5IHZhcmlhYmxlcyB0byBmaXggdGhlIE1TIEVkZ2UgZGVzdHJ1Y3R1cmluZyBpc3N1ZSAoc2VlIHB1bGwgcmVxdWVzdCAjNTY0KVxuICAgICAgICAgICAgY29uc3QgW2ZpcnN0QnJhY2tldCwgbGFzdEJyYWNrZXRdID0gc2V0dGluZ3MubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIuc3BsaXQoJywnKTtcbiAgICAgICAgICAgIHNldHRpbmdzLmZpcnN0QnJhY2tldCA9IGZpcnN0QnJhY2tldDtcbiAgICAgICAgICAgIHNldHRpbmdzLmxhc3RCcmFja2V0ID0gbGFzdEJyYWNrZXQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYSBudW1iZXIgYXMgYSBudW1lcmljIHN0cmluZyB0aGF0IGNhbiBiZSB0eXBlY2FzdCB0byBhIE51bWJlciB0aGF0IEphdmFzY3JpcHQgd2lsbCB1bmRlcnN0YW5kLlxuICAgICAqXG4gICAgICogVGhpcyBmdW5jdGlvbiByZXR1cm5zIHRoZSBnaXZlbiBzdHJpbmcgYnkgc3RyaXBwaW5nOlxuICAgICAqIC0gdGhlIGN1cnJlbmN5IHNpZ24gKGN1cnJlbmN5U3ltYm9sKSxcbiAgICAgKiAtIHRoZSBncm91cGluZyBzZXBhcmF0b3JzIChkaWdpdGFsR3JvdXBTcGFjaW5nKSxcbiAgICAgKiAtIHRoZSBzdWZmaXggdGV4dCAoc3VmZml4VGV4dCksXG4gICAgICogLSB0aGUgcG9zaXRpdmUgc2lnbiAocG9zaXRpdmVTaWduQ2hhcmFjdGVyKSxcbiAgICAgKiAtIHRoZSBicmFja2V0cyBpZiBhbnksXG4gICAgICogLSBieSByZXBsYWNpbmcgdGhlIG5lZ2F0aXZlIHNpZ24gY2hhcmFjdGVyIHdpdGggYW4gaHlwaGVuLFxuICAgICAqIC0gYW5kIGJ5IHJlcGxhY2luZyB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgKGRlY2ltYWxDaGFyYWN0ZXIpIGJ5IGEgZG90LlxuICAgICAqXG4gICAgICogTGFzdGx5LCBpdCBhbHNvIHB1dCB0aGUgbmVnYXRpdmUgc2lnbiBiYWNrIHRvIGl0cyBub3JtYWwgcG9zaXRpb24gaWYgbmVlZGVkLlxuICAgICAqIEJvbnVzOyBpdCBjb252ZXJ0cyBhbnkgYXJhYmljIG51bWJlcnMgZm91bmQgdG8gdGhlIGxhdGluIG9uZXMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc1xuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8dm9pZHwqfVxuICAgICAqL1xuICAgIHN0YXRpYyBfY29udmVydFRvTnVtZXJpY1N0cmluZyhzLCBzZXR0aW5ncykge1xuICAgICAgICAvLyBSZW1vdmUgdGhlIGN1c3RvbSBicmFja2V0c1xuICAgICAgICBzID0gdGhpcy5fcmVtb3ZlQnJhY2tldHMocywgc2V0dGluZ3MsIGZhbHNlKTtcbiAgICAgICAgcyA9IHRoaXMuX25vcm1hbGl6ZUN1cnJlbmN5U3VmZml4QW5kTmVnYXRpdmVTaWduQ2hhcmFjdGVycyhzLCBzZXR0aW5ncyk7XG5cbiAgICAgICAgLy8gUmVtb3ZlIHRoZSBncm91cGluZyBzZXBhcmF0b3JzICh0aG91c2FuZHMgc2VwYXJhdG9ycyB1c3VhbGx5KVxuICAgICAgICBzID0gcy5yZXBsYWNlKG5ldyBSZWdFeHAoYFske3NldHRpbmdzLmRpZ2l0R3JvdXBTZXBhcmF0b3J9XWAsICdnJyksICcnKTtcblxuICAgICAgICAvLyBSZXBsYWNlIHRoZSBkZWNpbWFsIGNoYXJhY3RlciBieSBhIGRvdFxuICAgICAgICBpZiAoc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlciAhPT0gJy4nKSB7XG4gICAgICAgICAgICBzID0gcy5yZXBsYWNlKHNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIsICcuJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBNb3ZlIHRoZSB0cmFpbGluZyBuZWdhdGl2ZSBzaWduLCBpZiBhbnksIHRvIHRoZSB1c3VhbCBsZWZ0bW9zdCBwb3NpdGlvblxuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZShzKSAmJiBzLmxhc3RJbmRleE9mKCctJykgPT09IHMubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgcyA9IHMucmVwbGFjZSgnLScsICcnKTtcbiAgICAgICAgICAgIHMgPSBgLSR7c31gO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVwbGFjZSB0aGUgY3VzdG9tIHBvc2l0aXZlIHNpZ25cbiAgICAgICAgaWYgKHNldHRpbmdzLnNob3dQb3NpdGl2ZVNpZ24pIHtcbiAgICAgICAgICAgIHMgPSBzLnJlcGxhY2Uoc2V0dGluZ3MucG9zaXRpdmVTaWduQ2hhcmFjdGVyLCAnJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDb252ZXJ0IGFyYWJpYyBudW1iZXJzIHRvIGxhdGluIG9uZXMsIGlmIGFueVxuICAgICAgICBjb25zdCBjb252ZXJ0VG9OdW1iZXIgPSBzZXR0aW5ncy5sZWFkaW5nWmVybyAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5sZWFkaW5nWmVyby5rZWVwO1xuICAgICAgICBjb25zdCB0ZW1wID0gQXV0b051bWVyaWNIZWxwZXIuYXJhYmljVG9MYXRpbk51bWJlcnMocywgY29udmVydFRvTnVtYmVyLCBmYWxzZSwgZmFsc2UpO1xuICAgICAgICBpZiAoIWlzTmFOKHRlbXApKSB7XG4gICAgICAgICAgICBzID0gdGVtcC50b1N0cmluZygpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgY3VycmVuY3kgc3ltYm9sIGFuZCB0aGUgc3VmZml4IHRleHQgZnJvbSB0aGUgZ2l2ZW4gc3RyaW5nLCBhbmQgcmVwbGFjZSB0aGUgY3VzdG9tIG5lZ2F0aXZlIHNpZ24gd2l0aCBhbiBoeXBoZW4uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc1xuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEByZXR1cm5zIHtzdHJpbmcgfCAqfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9ub3JtYWxpemVDdXJyZW5jeVN1ZmZpeEFuZE5lZ2F0aXZlU2lnbkNoYXJhY3RlcnMocywgc2V0dGluZ3MpIHtcbiAgICAgICAgcyA9IFN0cmluZyhzKTsgLy8gVHlwZWNhc3QgdG8gdG8gYSBzdHJpbmcsIGluIGNhc2UgdGhhdCB0aGUgZ2l2ZW4gdmFsdWUgaXMgYSBudW1iZXJcblxuICAgICAgICAvLyBSZW1vdmUgdGhlIGN1cnJlbmN5IHN5bWJvbFxuICAgICAgICBpZiAoc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2wubm9uZSkge1xuICAgICAgICAgICAgcyA9IHMucmVwbGFjZShzZXR0aW5ncy5jdXJyZW5jeVN5bWJvbCwgJycpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVtb3ZlIHRoZSBzdWZmaXhUZXh0XG4gICAgICAgIGlmIChzZXR0aW5ncy5zdWZmaXhUZXh0ICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLnN1ZmZpeFRleHQubm9uZSkge1xuICAgICAgICAgICAgcyA9IHMucmVwbGFjZShzZXR0aW5ncy5zdWZmaXhUZXh0LCAnJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZXBsYWNlIHRoZSBjdXN0b20gbmVnYXRpdmUgc2lnbiB3aXRoIGFuIGh5cGhlblxuICAgICAgICBpZiAoc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlU2lnbkNoYXJhY3Rlci5oeXBoZW4pIHtcbiAgICAgICAgICAgIHMgPSBzLnJlcGxhY2Uoc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyLCAnLScpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgdGhlIElTTyBudW1lcmljIHN0cmluZyB0byB0aGUgbG9jYWxlIGRlY2ltYWwgYW5kIG1pbnVzIHNpZ24gcGxhY2VtZW50LlxuICAgICAqIFNlZSB0aGUgXCJvdXRwdXRGb3JtYXRcIiBvcHRpb24gZGVmaW5pdGlvbiBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqIE5vdGU6IElmIHRoZSBgb3V0cHV0Rm9ybWF0YCBpcyBzZXQgdG8gYSBudW1iZXIsIHRoZSBjdXN0b20gYG5lZ2F0aXZlU2lnbkNoYXJhY3RlcmAgaXMgaWdub3JlZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfG51bGx9IHZhbHVlIFRoZSB1bmZvcm1hdHRlZCB2YWx1ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfG51bGx9IGxvY2FsZVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyBfdG9Mb2NhbGUodmFsdWUsIGxvY2FsZSwgc2V0dGluZ3MpIHtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChsb2NhbGUpIHx8IGxvY2FsZSA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5vdXRwdXRGb3JtYXQuc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBzd2l0Y2ggKGxvY2FsZSkge1xuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm91dHB1dEZvcm1hdC5udW1iZXI6XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gTnVtYmVyKHZhbHVlKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5vdXRwdXRGb3JtYXQuZG90TmVnYXRpdmU6XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZSh2YWx1ZSkgPyB2YWx1ZS5yZXBsYWNlKCctJywgJycpICsgJy0nIDogdmFsdWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub3V0cHV0Rm9ybWF0LmNvbW1hOlxuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm91dHB1dEZvcm1hdC5uZWdhdGl2ZUNvbW1hOlxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlLnJlcGxhY2UoJy4nLCAnLCcpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm91dHB1dEZvcm1hdC5jb21tYU5lZ2F0aXZlOlxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlLnJlcGxhY2UoJy4nLCAnLCcpO1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmUocmVzdWx0KSA/IHJlc3VsdC5yZXBsYWNlKCctJywgJycpICsgJy0nIDogcmVzdWx0O1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgLy8gVGhlIGRlZmF1bHQgY2FzZVxuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm91dHB1dEZvcm1hdC5kb3Q6XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub3V0cHV0Rm9ybWF0Lm5lZ2F0aXZlRG90OlxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdCA6XG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGdpdmVuIG91dHB1dEZvcm1hdCBbJHtsb2NhbGV9XSBvcHRpb24gaXMgbm90IHJlY29nbml6ZWQuYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobG9jYWxlICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLm91dHB1dEZvcm1hdC5udW1iZXIgJiYgc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyICE9PSAnLScpIHtcbiAgICAgICAgICAgIC8vIE1vZGlmeSB0aGUgZGVmYXVsdCBtaW51cyBzaWduIHdpdGggdGhlIGN1c3RvbSBvbmUsIGlmIGFueVxuICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LnJlcGxhY2UoJy0nLCBzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNb2RpZnkgdGhlIG5lZ2F0aXZlIHNpZ24gYW5kIHRoZSBkZWNpbWFsIGNoYXJhY3RlciBvZiB0aGUgZ2l2ZW4gc3RyaW5nIHZhbHVlIHRvIGFuIGh5cGhlbiAoLSkgYW5kIGEgZG90ICguKSBpbiBvcmRlciB0byBtYWtlIHRoYXQgdmFsdWUgJ3R5cGVjYXN0YWJsZScgdG8gYSByZWFsIG51bWJlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzIFRoZSBmb3JtYXR0ZWQgdmFsdWVcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgdmFsdWUgd2l0aCB0aGUgJ25vcm1hbCcgbWludXMgc2lnbiBhbmQgZGVjaW1hbCBjaGFyYWN0ZXJcbiAgICAgKi9cbiAgICBfbW9kaWZ5TmVnYXRpdmVTaWduQW5kRGVjaW1hbENoYXJhY3RlckZvclJhd1ZhbHVlKHMpIHtcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlciAhPT0gJy4nKSB7XG4gICAgICAgICAgICBzID0gcy5yZXBsYWNlKHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlciwgJy4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciAhPT0gJy0nICYmIHRoaXMuc2V0dGluZ3MuaXNOZWdhdGl2ZVNpZ25BbGxvd2VkKSB7XG4gICAgICAgICAgICBzID0gcy5yZXBsYWNlKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyLCAnLScpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFzLm1hdGNoKC9cXGQvKSkge1xuICAgICAgICAgICAgLy8gVGhlIGRlZmF1bHQgdmFsdWUgcmV0dXJuZWQgYnkgYGdldGAgaXMgbm90IGZvcm1hdHRlZCB3aXRoIGRlY2ltYWxzXG4gICAgICAgICAgICBzICs9ICcwJztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1vZGlmeSB0aGUgbmVnYXRpdmUgc2lnbiBhbmQgdGhlIGRlY2ltYWwgY2hhcmFjdGVyIHRvIHVzZSB0aG9zZSBkZWZpbmVkIGluIHRoZSBzZXR0aW5ncy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgX21vZGlmeU5lZ2F0aXZlU2lnbkFuZERlY2ltYWxDaGFyYWN0ZXJGb3JGb3JtYXR0ZWRWYWx1ZShzLCBzZXR0aW5ncykge1xuICAgICAgICAvL1hYWCBOb3RlOyB0aGlzIGZ1bmN0aW9uIGlzIHN0YXRpYyBzaW5jZSB3ZSBuZWVkIHRvIHBhc3MgYSBgc2V0dGluZ3NgIG9iamVjdCB3aGVuIGNhbGxpbmcgdGhlIHN0YXRpYyBgQXV0b051bWVyaWMuZm9ybWF0KClgIG1ldGhvZFxuICAgICAgICBpZiAoc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyICE9PSAnLScpIHtcbiAgICAgICAgICAgIHMgPSBzLnJlcGxhY2UoJy0nLCBzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIgIT09ICcuJykge1xuICAgICAgICAgICAgcyA9IHMucmVwbGFjZSgnLicsIHNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgZ2l2ZW4gdmFsdWUgaXMgZW1wdHkgb3IgaXMgZXF1YWwgdG8gdGhlIG5lZ2F0aXZlIHNpZ24gY2hhcmFjdGVyIGRlZmluZWQgaW4gdGhlIGdpdmVuIHNldHRpbmdzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2lzRWxlbWVudFZhbHVlRW1wdHlPck9ubHlUaGVOZWdhdGl2ZVNpZ24odmFsdWUsIHNldHRpbmdzKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZSA9PT0gJycgfHwgdmFsdWUgPT09IHNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIHZhbHVlIHdpdGggdGhlIGN1cnJlbmN5IHN5bWJvbCBhbmQgdGhlIHN1ZmZpeCB0ZXh0IG9yZGVyZWQgYWNjb3JkaW5nIHRvIHRoZSBnaXZlbiBzZXR0aW5ncy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gc2lnbk9uRW1wdHlcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfb3JkZXJWYWx1ZUN1cnJlbmN5U3ltYm9sQW5kU3VmZml4VGV4dCh2YWx1ZSwgc2V0dGluZ3MsIHNpZ25PbkVtcHR5KSB7XG4gICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgIGlmIChzZXR0aW5ncy5lbXB0eUlucHV0QmVoYXZpb3IgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLmFsd2F5cyB8fCBzaWduT25FbXB0eSkge1xuICAgICAgICAgICAgc3dpdGNoIChzZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCkge1xuICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5sZWZ0OlxuICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXg6XG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50Lm5vbmU6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlICsgc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wgKyBzZXR0aW5ncy5zdWZmaXhUZXh0O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0IDpcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wgKyB2YWx1ZSArIHNldHRpbmdzLnN1ZmZpeFRleHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQgPSB2YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTW9kaWZ5IHRoZSBpbnB1dCB2YWx1ZSBieSBhZGRpbmcgdGhlIGdyb3VwIHNlcGFyYXRvcnMsIGFzIGRlZmluZWQgaW4gdGhlIHNldHRpbmdzLCBhbmQgdGhlIG5lZ2F0aXZlIGJyYWNrZXRzIGlmIG5lZWRlZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBpbnB1dFZhbHVlIFRoZSBmb3JtYXR0ZWQgdmFsdWUgKGllLiB3aXRoIHRoZSBgZGVjaW1hbENoYXJhY3RlcmAgZGVmaW5lZCBpbiB0aGUgc2V0dGluZ3MsIG5vdCB0aGUgcmF3IHZhbHVlKVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNGb2N1c2VkXG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfG51bGx9IGN1cnJlbnRSYXdWYWx1ZSBUaGUgb2JqZWN0IGN1cnJlbnQgcmF3IHZhbHVlIChgdGhpcy5yYXdWYWx1ZWApXG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfG51bGx9IGZvcmNlZFJhd1ZhbHVlIElmIHRoaXMgaXMgc2V0LCB0aGVuIHRoaXMgcmF3VmFsdWUgaXMgdXNlZCBpbnN0ZWFkIG9mIHRoZSBvbmUgcGFzc2VkIHRocm91Z2ggdGhlIGBzZXR0aW5nc2Agb2JqZWN0LiBUaGlzIGlzIHVzZWZ1bCBpcyBzb21lIHZlcnkgc3BlY2lmaWMgY2FzZXMgd2hlcmUgd2UgbmVlZCB0byBzZXQgdGhlIHJhdyB2YWx1ZSAqYWZ0ZXIqIHNldHRpbmdzIHRoZSBmb3JtYXR0ZWQgdmFsdWUsIHVzaW5nIHRoZSBgX2FkZEdyb3VwU2VwYXJhdG9ycygpYCBtZXRob2QuXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgc3RhdGljIF9hZGRHcm91cFNlcGFyYXRvcnMoaW5wdXRWYWx1ZSwgc2V0dGluZ3MsIGlzRm9jdXNlZCwgY3VycmVudFJhd1ZhbHVlLCBmb3JjZWRSYXdWYWx1ZSA9IG51bGwpIHtcbiAgICAgICAgLy9UT0RPIFRlc3QgaWYgYGlucHV0VmFsdWVgID09PSAnJywgYW5kIHJldHVybiAnJyBkaXJlY3RseSBpZiB0aGF0J3MgdGhlIGNhc2UsXG4gICAgICAgIC8vWFhYIE5vdGU7IHRoaXMgZnVuY3Rpb24gaXMgc3RhdGljIHNpbmNlIHdlIG5lZWQgdG8gcGFzcyBhIGBzZXR0aW5nc2Agb2JqZWN0IHdoZW4gY2FsbGluZyB0aGUgc3RhdGljIGBBdXRvTnVtZXJpYy5mb3JtYXQoKWAgbWV0aG9kXG4gICAgICAgIGxldCBpc1ZhbHVlTmVnYXRpdmU7XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGZvcmNlZFJhd1ZhbHVlKSkge1xuICAgICAgICAgICAgLy8gUHJlZmVyIGRpcmVjdGx5IHRlc3RpbmcgaWYgdGhlIHJhdyB2YWx1ZSBpcyBuZWdhdGl2ZSBpbiBvcmRlciBmb3IgdGhlIHRlc3QgdG8gYmUgbW9yZSBwZXJmb3JtYW50IHRoYW4gbWFuaXB1bGF0aW5nIHRoZSBmb3JtYXR0ZWQgdmFsdWVcbiAgICAgICAgICAgIGlzVmFsdWVOZWdhdGl2ZSA9IGZvcmNlZFJhd1ZhbHVlIDwgMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlzVmFsdWVOZWdhdGl2ZSA9IEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmUoaW5wdXRWYWx1ZSwgc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSB8fCBBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlV2l0aEJyYWNrZXRzKGlucHV0VmFsdWUsIHNldHRpbmdzLmZpcnN0QnJhY2tldCwgc2V0dGluZ3MubGFzdEJyYWNrZXQpOyAvLyBUZXN0IGlmIHRoZSB2YWx1ZSBpcyBuZWdhdGl2ZSBiZWZvcmUgcmVtb3ZpbmcgdGhlIG5lZ2F0aXZlIHNpZ25cbiAgICAgICAgfVxuXG4gICAgICAgIGlucHV0VmFsdWUgPSB0aGlzLl9zdHJpcEFsbE5vbk51bWJlckNoYXJhY3RlcnNFeGNlcHRDdXN0b21EZWNpbWFsQ2hhcihpbnB1dFZhbHVlLCBzZXR0aW5ncywgZmFsc2UsIGlzRm9jdXNlZCk7XG5cbiAgICAgICAgaWYgKHRoaXMuX2lzRWxlbWVudFZhbHVlRW1wdHlPck9ubHlUaGVOZWdhdGl2ZVNpZ24oaW5wdXRWYWx1ZSwgc2V0dGluZ3MpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb3JkZXJWYWx1ZUN1cnJlbmN5U3ltYm9sQW5kU3VmZml4VGV4dChpbnB1dFZhbHVlLCBzZXR0aW5ncywgdHJ1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBpc1plcm9Pckhhc05vVmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5pc1plcm9Pckhhc05vVmFsdWUoaW5wdXRWYWx1ZSk7XG5cbiAgICAgICAgLy8gVGVtcG9yYXJpbHkgcmVtb3ZlIHRoZSBuZWdhdGl2ZSBzaWduIGlmIHByZXNlbnRcbiAgICAgICAgaWYgKGlzVmFsdWVOZWdhdGl2ZSkge1xuICAgICAgICAgICAgaW5wdXRWYWx1ZSA9IGlucHV0VmFsdWUucmVwbGFjZSgnLScsICcnKTsgLy8gQXQgdGhpcyBwb2ludCB0aGUgYGlucHV0VmFsdWVgIGhhcyBiZWVuIG5vcm1hbGl6ZWQgd2l0aCBhICdub3JtYWwnIG5lZ2F0aXZlIHNpZ24gYCctJ2AgLy9UT0RPIENoZWNrIHRoYXQgY29tbWVudCB2YWxpZGl0eSwgc2luY2UgYF9zdHJpcEFsbE5vbk51bWJlckNoYXJhY3RlcnNFeGNlcHRDdXN0b21EZWNpbWFsQ2hhcmAgKmRvZXMgbm90KiBjb252ZXJ0IHRoZSBuZWdhdGl2ZSBzaWduXG4gICAgICAgIH1cblxuICAgICAgICBzZXR0aW5ncy5kaWdpdGFsR3JvdXBTcGFjaW5nID0gc2V0dGluZ3MuZGlnaXRhbEdyb3VwU3BhY2luZy50b1N0cmluZygpO1xuICAgICAgICBsZXQgZGlnaXRhbEdyb3VwO1xuICAgICAgICBzd2l0Y2ggKHNldHRpbmdzLmRpZ2l0YWxHcm91cFNwYWNpbmcpIHtcbiAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdGFsR3JvdXBTcGFjaW5nLnR3bzpcbiAgICAgICAgICAgICAgICBkaWdpdGFsR3JvdXAgPSAvKFxcZCkoKFxcZCkoXFxkezJ9PykrKSQvO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0YWxHcm91cFNwYWNpbmcudHdvU2NhbGVkOlxuICAgICAgICAgICAgICAgIGRpZ2l0YWxHcm91cCA9IC8oXFxkKSgoPzpcXGR7Mn0pezAsMn1cXGR7M30oPzooPzpcXGR7Mn0pezJ9XFxkezN9KSo/KSQvO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0YWxHcm91cFNwYWNpbmcuZm91cjpcbiAgICAgICAgICAgICAgICBkaWdpdGFsR3JvdXAgPSAvKFxcZCkoKFxcZHs0fT8pKykkLztcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdGFsR3JvdXBTcGFjaW5nLnRocmVlOlxuICAgICAgICAgICAgZGVmYXVsdCA6XG4gICAgICAgICAgICAgICAgZGlnaXRhbEdyb3VwID0gLyhcXGQpKChcXGR7M30/KSspJC87XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTcGxpdHMgdGhlIHN0cmluZyBhdCB0aGUgZGVjaW1hbCBzdHJpbmdcbiAgICAgICAgbGV0IFtpbnRlZ2VyUGFydCwgZGVjaW1hbFBhcnRdID0gaW5wdXRWYWx1ZS5zcGxpdChzZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKTtcbiAgICAgICAgaWYgKHNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZSAmJiBBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZChkZWNpbWFsUGFydCkpIHtcbiAgICAgICAgICAgIFtpbnRlZ2VyUGFydCwgZGVjaW1hbFBhcnRdID0gaW5wdXRWYWx1ZS5zcGxpdChzZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNldHRpbmdzLmRpZ2l0R3JvdXBTZXBhcmF0b3IgIT09ICcnKSB7XG4gICAgICAgICAgICAvLyBSZS1pbnNlcnRzIHRoZSB0aG91c2FuZCBzZXBhcmF0b3IgdmlhIGEgcmVndWxhciBleHByZXNzaW9uXG4gICAgICAgICAgICB3aGlsZSAoZGlnaXRhbEdyb3VwLnRlc3QoaW50ZWdlclBhcnQpKSB7XG4gICAgICAgICAgICAgICAgaW50ZWdlclBhcnQgPSBpbnRlZ2VyUGFydC5yZXBsYWNlKGRpZ2l0YWxHcm91cCwgYCQxJHtzZXR0aW5ncy5kaWdpdEdyb3VwU2VwYXJhdG9yfSQyYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBGaW5kIG91dCBob3cgbWFueSBkZWNpbWFsIHBsYWNlcyBzaG91bGQgYmUga2VwdCwgZGVwZW5kaW5nIG9uIHRoZSBvYmplY3Qgc3RhdGUgKGlzRm9jdXNlZClcbiAgICAgICAgbGV0IGRlY2ltYWxQbGFjZXNUb1JvdW5kVG87XG4gICAgICAgIGlmIChpc0ZvY3VzZWQpIHtcbiAgICAgICAgICAgIGRlY2ltYWxQbGFjZXNUb1JvdW5kVG8gPSBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGVjaW1hbFBsYWNlc1RvUm91bmRUbyA9IHNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1cjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkZWNpbWFsUGxhY2VzVG9Sb3VuZFRvICE9PSAwICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZChkZWNpbWFsUGFydCkpIHtcbiAgICAgICAgICAgIGlmIChkZWNpbWFsUGFydC5sZW5ndGggPiBkZWNpbWFsUGxhY2VzVG9Sb3VuZFRvKSB7XG4gICAgICAgICAgICAgICAgLy8gVHJpbSB0aGUgZXhjZXNzaXZlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlc1xuICAgICAgICAgICAgICAgIGRlY2ltYWxQYXJ0ID0gZGVjaW1hbFBhcnQuc3Vic3RyaW5nKDAsIGRlY2ltYWxQbGFjZXNUb1JvdW5kVG8pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBKb2lucyB0aGUgd2hvbGUgbnVtYmVyIHdpdGggdGhlIGRlY2ltYWwgdmFsdWVcbiAgICAgICAgICAgIGlucHV0VmFsdWUgPSBgJHtpbnRlZ2VyUGFydH0ke3NldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXJ9JHtkZWNpbWFsUGFydH1gO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIGlmIGl0J3MgYW4gaW50ZWdlclxuICAgICAgICAgICAgaW5wdXRWYWx1ZSA9IGludGVnZXJQYXJ0O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkIGJhY2sgdGhlIG5lZ2F0aXZlL3Bvc2l0aXZlIHNpZ24gYW5kIHRoZSBjdXJyZW5jeSBzeW1ib2wsIGF0IHRoZSByaWdodCBwb3NpdGlvbnNcbiAgICAgICAgaW5wdXRWYWx1ZSA9IEF1dG9OdW1lcmljLl9tZXJnZUN1cnJlbmN5U2lnbk5lZ2F0aXZlUG9zaXRpdmVTaWduQW5kVmFsdWUoaW5wdXRWYWx1ZSwgc2V0dGluZ3MsIGlzVmFsdWVOZWdhdGl2ZSwgaXNaZXJvT3JIYXNOb1ZhbHVlKTsgLy9UT0RPIHRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIGFnYWluIGluIGBfdG9nZ2xlTmVnYXRpdmVCcmFja2V0YCBpZiB0aGUgYnJhY2tldHMgYXJlIHJlbW92ZWQ7IGxldCdzIERSWSB0aGlzXG5cbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChmb3JjZWRSYXdWYWx1ZSkpIHtcbiAgICAgICAgICAgIC8vIElmIHRoZSByYXcgdmFsdWUgaXMgbm90IGZvcmNlZCwgdXNlIHRoZSBkZWZhdWx0IG9uZSBmcm9tIHRoZSBzZXR0aW5ncyBvYmplY3RcbiAgICAgICAgICAgIGZvcmNlZFJhd1ZhbHVlID0gY3VycmVudFJhd1ZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVG9nZ2xlIHRoZSBuZWdhdGl2ZSBzaWduIGFuZCBicmFja2V0c1xuICAgICAgICBpZiAoc2V0dGluZ3MubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIgIT09IG51bGwgJiYgKGZvcmNlZFJhd1ZhbHVlIDwgMCB8fCBBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlU3RyaWN0KGlucHV0VmFsdWUsIHNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikpKSB7XG4gICAgICAgICAgICBpbnB1dFZhbHVlID0gdGhpcy5fdG9nZ2xlTmVnYXRpdmVCcmFja2V0KGlucHV0VmFsdWUsIHNldHRpbmdzLCBpc0ZvY3VzZWQpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgaWYgKHNldHRpbmdzLnN1ZmZpeFRleHQpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IGAke2lucHV0VmFsdWV9JHtzZXR0aW5ncy5zdWZmaXhUZXh0fWA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQgPSBpbnB1dFZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYSBzZW1pLWZvcm1hdHRlZCBzdHJpbmcgd2hlcmUgdGhlIGlucHV0IHZhbHVlLCB0aGUgbmVnYXRpdmUgb3IgcG9zaXRpdmUgc2lnbiwgYW5kIHRoZSBjdXJyZW5jeSBzeW1ib2wgYXJlIHN0aXRjaGVkIHRvZ2V0aGVyIGF0IHRoZSByaWdodCBwb3NpdGlvbnMsIHVzaW5nIHRoZSBvcHRpb25zIHNldCBpbiB0aGUgYHNldHRpbmdzYCBvYmplY3QuXG4gICAgICogTm90ZSA6IHRoZSBgaW5wdXRWYWx1ZWAgaXMgdXN1YWxseSBub3QgYSBudW1lcmljIHN0cmluZyBzaW5jZSB0aGUgZ3JvdXBpbmcgc3ltYm9scyBhcmUgYWxyZWFkeSBhZGRlZCB0byBpdCBhdCB0aGlzIHBvaW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGlucHV0VmFsdWVcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGlzVmFsdWVOZWdhdGl2ZVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNaZXJvT3JIYXNOb1ZhbHVlXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICogQHRocm93c1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9tZXJnZUN1cnJlbmN5U2lnbk5lZ2F0aXZlUG9zaXRpdmVTaWduQW5kVmFsdWUoaW5wdXRWYWx1ZSwgc2V0dGluZ3MsIGlzVmFsdWVOZWdhdGl2ZSwgaXNaZXJvT3JIYXNOb1ZhbHVlKSB7XG4gICAgICAgIGxldCBzaWduVG9Vc2UgPSAnJztcbiAgICAgICAgaWYgKGlzVmFsdWVOZWdhdGl2ZSkge1xuICAgICAgICAgICAgc2lnblRvVXNlID0gc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyO1xuICAgICAgICB9IGVsc2UgaWYgKHNldHRpbmdzLnNob3dQb3NpdGl2ZVNpZ24gJiYgIWlzWmVyb09ySGFzTm9WYWx1ZSkge1xuICAgICAgICAgICAgc2lnblRvVXNlID0gc2V0dGluZ3MucG9zaXRpdmVTaWduQ2hhcmFjdGVyO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgaWYgKHNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnByZWZpeCkge1xuICAgICAgICAgICAgaWYgKHNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50Lm5vbmUgJiZcbiAgICAgICAgICAgICAgICAoaXNWYWx1ZU5lZ2F0aXZlIHx8ICghaXNWYWx1ZU5lZ2F0aXZlICYmIHNldHRpbmdzLnNob3dQb3NpdGl2ZVNpZ24gJiYgIWlzWmVyb09ySGFzTm9WYWx1ZSkpKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChzZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4OlxuICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGAke3NpZ25Ub1VzZX0ke3NldHRpbmdzLmN1cnJlbmN5U3ltYm9sfSR7aW5wdXRWYWx1ZX1gO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGAke3NldHRpbmdzLmN1cnJlbmN5U3ltYm9sfSR7c2lnblRvVXNlfSR7aW5wdXRWYWx1ZX1gO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5zdWZmaXg6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBgJHtzZXR0aW5ncy5jdXJyZW5jeVN5bWJvbH0ke2lucHV0VmFsdWV9JHtzaWduVG9Vc2V9YDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wgKyBpbnB1dFZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeCkge1xuICAgICAgICAgICAgaWYgKHNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50Lm5vbmUgJiZcbiAgICAgICAgICAgICAgICAoaXNWYWx1ZU5lZ2F0aXZlIHx8ICghaXNWYWx1ZU5lZ2F0aXZlICYmIHNldHRpbmdzLnNob3dQb3NpdGl2ZVNpZ24gJiYgIWlzWmVyb09ySGFzTm9WYWx1ZSkpKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChzZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQuc3VmZml4OlxuICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBgJHtpbnB1dFZhbHVlfSR7c2V0dGluZ3MuY3VycmVuY3lTeW1ib2x9JHtzaWduVG9Vc2V9YDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGAke2lucHV0VmFsdWV9JHtzaWduVG9Vc2V9JHtzZXR0aW5ncy5jdXJyZW5jeVN5bWJvbH1gO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXg6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBgJHtzaWduVG9Vc2V9JHtpbnB1dFZhbHVlfSR7c2V0dGluZ3MuY3VycmVuY3lTeW1ib2x9YDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gaW5wdXRWYWx1ZSArIHNldHRpbmdzLmN1cnJlbmN5U3ltYm9sO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYWxjdWxhdGUgd2hlcmUgdG8gcHV0IHRoZSBjYXJldCBwb3NpdGlvbiBvbiBmb2N1cyBpZiB0aGUgZWxlbWVudCBjb250ZW50IGlzIG5vdCBzZWxlY3RlZC5cbiAgICAgKiBUaGlzIGNhbGN1bGF0aW9uIGlzIGFmZmVjdGVkIGJ5IHRoZSBgY2FyZXRQb3NpdGlvbk9uRm9jdXNgIG9wdGlvbiB3aGljaCBjYW4gYmUgZWl0aGVyIGBudWxsYCwgYCdzdGFydCdgLCBgJ2VuZCdgLCBgJ2RlY2ltYWxMZWZ0J2Agb3IgJ2RlY2ltYWxSaWdodCdgLCBhbmQgd2lsbCBkZWNpZGUgd2hlcmUgdG8gcHV0IHRoZSBjYXJldCAob24gdGhlIGxlZnQgb3IgcmlnaHQgb2YgdGhlIHZhbHVlIG9yIHRoZSBkZWNpbWFsIGNoYXJhY3RlciwgcmVzcGVjdGl2ZWx5KSA6XG4gICAgICogLSBgbnVsbGAgOiB0aGUgY2FyZXQgcG9zaXRpb24gaXMgbm90IGZvcmNlZFxuICAgICAqIC0gYCdzdGFydCdgIDogdGhlIGNhcmV0IGlzIHBvc2l0aW9uZWQgb24gdGhlIGxlZnQgaGFuZCBzaWRlIG9mIHRoZSB2YWx1ZVxuICAgICAqIC0gYCdlbmQnYCA6IHRoZSBjYXJldCBpcyBwb3NpdGlvbmVkIG9uIHRoZSByaWdodCBoYW5kIHNpZGUgb2YgdGhlIHZhbHVlXG4gICAgICogLSBgJ2RlY2ltYWxMZWZ0J2AgOiB0aGUgY2FyZXQgaXMgcG9zaXRpb25lZCBvbiB0aGUgbGVmdCBzaWRlIG9mIHRoZSBkZWNpbWFsIGNoYXJhY3RlclxuICAgICAqIC0gYCdkZWNpbWFsUmlnaHQnYCA6IHRoZSBjYXJldCBpcyBwb3NpdGlvbmVkIG9uIHRoZSByaWdodCBzaWRlIG9mIHRoZSBkZWNpbWFsIGNoYXJhY3RlclxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIFRoZSBmb3JtYXR0ZWQgc3RyaW5nIHN0cmlwcGVkIG9mIHRoZSBjdXJyZW5jeSBzeW1ib2wgYW5kIG5lZ2F0aXZlL3Bvc2l0aXZlIHNpZ25cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqIEB0aHJvd3NcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9pbml0aWFsQ2FyZXRQb3NpdGlvbih2YWx1ZSkge1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKHRoaXMuc2V0dGluZ3MuY2FyZXRQb3NpdGlvbk9uRm9jdXMpICYmXG4gICAgICAgICAgICB0aGlzLnNldHRpbmdzLnNlbGVjdE9uRm9jdXMgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuc2VsZWN0T25Gb2N1cy5kb05vdFNlbGVjdCkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcignYF9pbml0aWFsQ2FyZXRQb3NpdGlvbigpYCBzaG91bGQgbmV2ZXIgYmUgY2FsbGVkIHdoZW4gdGhlIGBjYXJldFBvc2l0aW9uT25Gb2N1c2Agb3B0aW9uIGlzIGBudWxsYC4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGlzVmFsdWVOZWdhdGl2ZSA9IHRoaXMucmF3VmFsdWUgPCAwO1xuICAgICAgICBjb25zdCBpc1plcm9Pckhhc05vVmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5pc1plcm9Pckhhc05vVmFsdWUodmFsdWUpO1xuICAgICAgICBjb25zdCB0b3RhbExlbmd0aCA9IHZhbHVlLmxlbmd0aDtcblxuICAgICAgICBsZXQgdmFsdWVTaXplID0gMDtcbiAgICAgICAgbGV0IGludGVnZXJTaXplID0gMDtcbiAgICAgICAgbGV0IGhhc0RlY2ltYWxDaGFyID0gZmFsc2U7XG4gICAgICAgIGxldCBvZmZzZXREZWNpbWFsQ2hhciA9IDA7XG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmNhcmV0UG9zaXRpb25PbkZvY3VzICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLnN0YXJ0KSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnJlcGxhY2UodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIsICcnKTtcbiAgICAgICAgICAgIHZhbHVlID0gdmFsdWUucmVwbGFjZSh0aGlzLnNldHRpbmdzLnBvc2l0aXZlU2lnbkNoYXJhY3RlciwgJycpO1xuICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wsICcnKTtcbiAgICAgICAgICAgIHZhbHVlU2l6ZSA9IHZhbHVlLmxlbmd0aDtcbiAgICAgICAgICAgIGhhc0RlY2ltYWxDaGFyID0gQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnModmFsdWUsIHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlcik7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmNhcmV0UG9zaXRpb25PbkZvY3VzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLmRlY2ltYWxMZWZ0IHx8XG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5jYXJldFBvc2l0aW9uT25Gb2N1cyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1cy5kZWNpbWFsUmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaGFzRGVjaW1hbENoYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgaW50ZWdlclNpemUgPSB2YWx1ZS5pbmRleE9mKHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlcik7XG4gICAgICAgICAgICAgICAgICAgIG9mZnNldERlY2ltYWxDaGFyID0gdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpbnRlZ2VyU2l6ZSA9IHZhbHVlU2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgb2Zmc2V0RGVjaW1hbENoYXIgPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBzaWduVG9Vc2UgPSAnJztcbiAgICAgICAgaWYgKGlzVmFsdWVOZWdhdGl2ZSkge1xuICAgICAgICAgICAgc2lnblRvVXNlID0gdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXI7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXR0aW5ncy5zaG93UG9zaXRpdmVTaWduICYmICFpc1plcm9Pckhhc05vVmFsdWUpIHtcbiAgICAgICAgICAgIHNpZ25Ub1VzZSA9IHRoaXMuc2V0dGluZ3MucG9zaXRpdmVTaWduQ2hhcmFjdGVyO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcG9zaXRpdmVOZWdhdGl2ZVNpZ25TaXplID0gc2lnblRvVXNlLmxlbmd0aDtcbiAgICAgICAgY29uc3QgY3VycmVuY3lTeW1ib2xTaXplID0gdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbC5sZW5ndGg7XG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBjYXJldCBwb3NpdGlvbiBiYXNlZCBvbiBgY3VycmVuY3lTeW1ib2xQbGFjZW1lbnRgLCBgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnRgIGFuZCBgY2FyZXRQb3NpdGlvbk9uRm9jdXNgXG4gICAgICAgIGxldCBjYXJldFBvc2l0aW9uO1xuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmNhcmV0UG9zaXRpb25PbkZvY3VzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLnN0YXJ0KSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubm9uZSAmJlxuICAgICAgICAgICAgICAgICAgICAoaXNWYWx1ZU5lZ2F0aXZlIHx8ICghaXNWYWx1ZU5lZ2F0aXZlICYmIHRoaXMuc2V0dGluZ3Muc2hvd1Bvc2l0aXZlU2lnbiAmJiAhaXNaZXJvT3JIYXNOb1ZhbHVlKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4OiAvLyAr4oKsfDEyLjM0XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdDogICAvLyAr4oKsfDEyLjM0XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQ6ICAvLyDigqwrfDEyLjM0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IHBvc2l0aXZlTmVnYXRpdmVTaWduU2l6ZSArIGN1cnJlbmN5U3ltYm9sU2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5zdWZmaXg6IC8vIOKCrHwxMi4zNCtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gY3VycmVuY3lTeW1ib2xTaXplO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyDigqx8MTIuMzRcbiAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IGN1cnJlbmN5U3ltYm9sU2l6ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc2V0dGluZ3MuY2FyZXRQb3NpdGlvbk9uRm9jdXMgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMuZW5kKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubm9uZSAmJlxuICAgICAgICAgICAgICAgICAgICAoaXNWYWx1ZU5lZ2F0aXZlIHx8ICghaXNWYWx1ZU5lZ2F0aXZlICYmIHRoaXMuc2V0dGluZ3Muc2hvd1Bvc2l0aXZlU2lnbiAmJiAhaXNaZXJvT3JIYXNOb1ZhbHVlKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4OiAvLyAr4oKsMTIuMzR8XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdDogICAvLyAr4oKsMTIuMzR8XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQ6ICAvLyDigqwrMTIuMzR8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IHRvdGFsTGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnN1ZmZpeDogLy8g4oKsMTIuMzR8K1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSBjdXJyZW5jeVN5bWJvbFNpemUgKyB2YWx1ZVNpemU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIOKCrDEyLjM0fFxuICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gdG90YWxMZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNldHRpbmdzLmNhcmV0UG9zaXRpb25PbkZvY3VzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLmRlY2ltYWxMZWZ0KSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubm9uZSAmJlxuICAgICAgICAgICAgICAgICAgICAoaXNWYWx1ZU5lZ2F0aXZlIHx8ICghaXNWYWx1ZU5lZ2F0aXZlICYmIHRoaXMuc2V0dGluZ3Muc2hvd1Bvc2l0aXZlU2lnbiAmJiAhaXNaZXJvT3JIYXNOb1ZhbHVlKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4OiAvLyAr4oKsMTJ8LjM0XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdDogICAvLyAr4oKsMTJ8LjM0XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQ6ICAvLyDigqwrMTJ8LjM0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IHBvc2l0aXZlTmVnYXRpdmVTaWduU2l6ZSArIGN1cnJlbmN5U3ltYm9sU2l6ZSArIGludGVnZXJTaXplO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnN1ZmZpeDogLy8g4oKsMTJ8LjM0K1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSBjdXJyZW5jeVN5bWJvbFNpemUgKyBpbnRlZ2VyU2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8g4oKsMTJ8LjM0XG4gICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSBjdXJyZW5jeVN5bWJvbFNpemUgKyBpbnRlZ2VyU2l6ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc2V0dGluZ3MuY2FyZXRQb3NpdGlvbk9uRm9jdXMgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMuZGVjaW1hbFJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubm9uZSAmJlxuICAgICAgICAgICAgICAgICAgICAoaXNWYWx1ZU5lZ2F0aXZlIHx8ICghaXNWYWx1ZU5lZ2F0aXZlICYmIHRoaXMuc2V0dGluZ3Muc2hvd1Bvc2l0aXZlU2lnbiAmJiAhaXNaZXJvT3JIYXNOb1ZhbHVlKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4OiAvLyAr4oKsMTIufDM0XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdDogICAvLyAr4oKsMTIufDM0XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQ6ICAvLyDigqwrMTIufDM0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IHBvc2l0aXZlTmVnYXRpdmVTaWduU2l6ZSArIGN1cnJlbmN5U3ltYm9sU2l6ZSArIGludGVnZXJTaXplICsgb2Zmc2V0RGVjaW1hbENoYXI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQuc3VmZml4OiAvLyDigqwxMi58MzQrXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IGN1cnJlbmN5U3ltYm9sU2l6ZSArIGludGVnZXJTaXplICsgb2Zmc2V0RGVjaW1hbENoYXI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIOKCrDEyLnwzNFxuICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gY3VycmVuY3lTeW1ib2xTaXplICsgaW50ZWdlclNpemUgKyBvZmZzZXREZWNpbWFsQ2hhcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5zdWZmaXgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmNhcmV0UG9zaXRpb25PbkZvY3VzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLnN0YXJ0KSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubm9uZSAmJlxuICAgICAgICAgICAgICAgICAgICAoaXNWYWx1ZU5lZ2F0aXZlIHx8ICghaXNWYWx1ZU5lZ2F0aXZlICYmIHRoaXMuc2V0dGluZ3Muc2hvd1Bvc2l0aXZlU2lnbiAmJiAhaXNaZXJvT3JIYXNOb1ZhbHVlKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQuc3VmZml4OiAvLyB8MTIuMzTigqwrXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQ6ICAvLyB8MTIuMzTigqwrXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdDogICAvLyB8MTIuMzQr4oKsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4OiAvLyArfDEyLjM04oKsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IHBvc2l0aXZlTmVnYXRpdmVTaWduU2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gfDEyLjM04oKsXG4gICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXR0aW5ncy5jYXJldFBvc2l0aW9uT25Gb2N1cyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1cy5lbmQpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5ub25lICYmXG4gICAgICAgICAgICAgICAgICAgIChpc1ZhbHVlTmVnYXRpdmUgfHwgKCFpc1ZhbHVlTmVnYXRpdmUgJiYgdGhpcy5zZXR0aW5ncy5zaG93UG9zaXRpdmVTaWduICYmICFpc1plcm9Pckhhc05vVmFsdWUpKSkge1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5zdWZmaXg6IC8vIDEyLjM0fOKCrCtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodDogIC8vIDEyLjM0fOKCrCtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5sZWZ0OiAgIC8vIDEyLjM0fCvigqxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gdmFsdWVTaXplO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnByZWZpeDogLy8gKzEyLjM0fOKCrFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSBwb3NpdGl2ZU5lZ2F0aXZlU2lnblNpemUgKyB2YWx1ZVNpemU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDEyLjM0fOKCrFxuICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gdmFsdWVTaXplO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXR0aW5ncy5jYXJldFBvc2l0aW9uT25Gb2N1cyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1cy5kZWNpbWFsTGVmdCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50Lm5vbmUgJiZcbiAgICAgICAgICAgICAgICAgICAgKGlzVmFsdWVOZWdhdGl2ZSB8fCAoIWlzVmFsdWVOZWdhdGl2ZSAmJiB0aGlzLnNldHRpbmdzLnNob3dQb3NpdGl2ZVNpZ24gJiYgIWlzWmVyb09ySGFzTm9WYWx1ZSkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnN1ZmZpeDogLy8gMTJ8LjM04oKsK1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnJpZ2h0OiAgLy8gMTJ8LjM04oKsK1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LmxlZnQ6ICAgLy8gMTJ8LjM0K+KCrFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSBpbnRlZ2VyU2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXg6IC8vICsxMnwuMzTigqxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gcG9zaXRpdmVOZWdhdGl2ZVNpZ25TaXplICsgaW50ZWdlclNpemU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDEyfC4zNOKCrFxuICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gaW50ZWdlclNpemU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNldHRpbmdzLmNhcmV0UG9zaXRpb25PbkZvY3VzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLmRlY2ltYWxSaWdodCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50Lm5vbmUgJiZcbiAgICAgICAgICAgICAgICAgICAgKGlzVmFsdWVOZWdhdGl2ZSB8fCAoIWlzVmFsdWVOZWdhdGl2ZSAmJiB0aGlzLnNldHRpbmdzLnNob3dQb3NpdGl2ZVNpZ24gJiYgIWlzWmVyb09ySGFzTm9WYWx1ZSkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnN1ZmZpeDogLy8gMTIufDM04oKsK1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnJpZ2h0OiAgLy8gMTIufDM04oKsK1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LmxlZnQ6ICAgLy8gMTIufDM0K+KCrFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSBpbnRlZ2VyU2l6ZSArIG9mZnNldERlY2ltYWxDaGFyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnByZWZpeDogLy8gKzEyLnwzNOKCrFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSBwb3NpdGl2ZU5lZ2F0aXZlU2lnblNpemUgKyBpbnRlZ2VyU2l6ZSArIG9mZnNldERlY2ltYWxDaGFyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAxMi58MzTigqxcbiAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IGludGVnZXJTaXplICsgb2Zmc2V0RGVjaW1hbENoYXI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGNhcmV0UG9zaXRpb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVHJ1bmNhdGUgdGhlIHRyYWlsaW5nIHplcm9lcyB0byB0aGUgZ2l2ZW4gbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcm91bmRlZElucHV0VmFsdWVcbiAgICAgKiBAcGFyYW0ge2ludH0gZGVjaW1hbFBsYWNlc05lZWRlZCBUaGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHRvIGtlZXBcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIHN0YXRpYyBfdHJ1bmNhdGVaZXJvcyhyb3VuZGVkSW5wdXRWYWx1ZSwgZGVjaW1hbFBsYWNlc05lZWRlZCkge1xuICAgICAgICBsZXQgcmVnZXg7XG4gICAgICAgIHN3aXRjaCAoZGVjaW1hbFBsYWNlc05lZWRlZCkge1xuICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgIC8vIFByZXZlbnRzIHBhZGRpbmcgLSByZW1vdmVzIHRyYWlsaW5nIHplcm9zIHVudGlsIHRoZSBmaXJzdCBzaWduaWZpY2FudCBkaWdpdCBpcyBlbmNvdW50ZXJlZFxuICAgICAgICAgICAgICAgIHJlZ2V4ID0gLyhcXC4oPzpcXGQqWzEtOV0pPykwKiQvO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIC8vIEFsbG93cyBwYWRkaW5nIHdoZW4gZGVjaW1hbFBsYWNlc05lZWRlZCBlcXVhbHMgb25lIC0gbGVhdmVzIG9uZSB6ZXJvIHRyYWlsaW5nIHRoZSBkZWNpbWFsIGNoYXJhY3RlclxuICAgICAgICAgICAgICAgIHJlZ2V4ID0gLyhcXC5cXGQoPzpcXGQqWzEtOV0pPykwKiQvO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdCA6XG4gICAgICAgICAgICAgICAgLy8gUmVtb3ZlcyBzdXBlcmZsdW91cyB6ZXJvcyBhZnRlciB0aGUgZGVjaW1hbFBsYWNlc05lZWRlZCBsZW5ndGhcbiAgICAgICAgICAgICAgICByZWdleCA9IG5ldyBSZWdFeHAoYChcXFxcLlxcXFxkeyR7ZGVjaW1hbFBsYWNlc05lZWRlZH19KD86XFxcXGQqWzEtOV0pPykwKmApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgdGhlcmUgYXJlIG5vIGRlY2ltYWwgcGxhY2VzLCB3ZSBkb24ndCBuZWVkIGEgZGVjaW1hbCBwb2ludCBhdCB0aGUgZW5kXG4gICAgICAgIHJvdW5kZWRJbnB1dFZhbHVlID0gcm91bmRlZElucHV0VmFsdWUucmVwbGFjZShyZWdleCwgJyQxJyk7XG4gICAgICAgIGlmIChkZWNpbWFsUGxhY2VzTmVlZGVkID09PSAwKSB7XG4gICAgICAgICAgICByb3VuZGVkSW5wdXRWYWx1ZSA9IHJvdW5kZWRJbnB1dFZhbHVlLnJlcGxhY2UoL1xcLiQvLCAnJyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcm91bmRlZElucHV0VmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUm91bmQgdGhlIGdpdmVuIGB2YWx1ZWAgd2l0aCB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHRvIGtlZXAgZm9yIHRoZSByYXcgdmFsdWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xudWxsfSB2YWx1ZSBBbiB1bmZvcm1hdHRlZCBudW1lcmljIHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX3JvdW5kUmF3VmFsdWUodmFsdWUsIHNldHRpbmdzKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9yb3VuZFZhbHVlKHZhbHVlLCBzZXR0aW5ncywgc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSb3VuZCB0aGUgZ2l2ZW4gYHZhbHVlYCB3aXRoIHRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgdG8gc2hvdyBmb3IgdGhlIGVsZW1lbnQgaWYgZm9jdXNlZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfG51bGx9IHZhbHVlIEFuIHVuZm9ybWF0dGVkIG51bWVyaWMgdmFsdWVcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfcm91bmRGb3JtYXR0ZWRWYWx1ZVNob3duT25Gb2N1cyh2YWx1ZSwgc2V0dGluZ3MpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3JvdW5kVmFsdWUodmFsdWUsIHNldHRpbmdzLCBOdW1iZXIoc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJvdW5kIHRoZSBnaXZlbiBgdmFsdWVgIHdpdGggdGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyB0byBzaG93IGZvciB0aGUgZWxlbWVudCBpZiB1bmZvY3VzZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xudWxsfSB2YWx1ZSBBbiB1bmZvcm1hdHRlZCBudW1lcmljIHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX3JvdW5kRm9ybWF0dGVkVmFsdWVTaG93bk9uQmx1cih2YWx1ZSwgc2V0dGluZ3MpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3JvdW5kVmFsdWUodmFsdWUsIHNldHRpbmdzLCBOdW1iZXIoc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUm91bmQgdGhlIGdpdmVuIGB2YWx1ZWAgd2l0aCB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHRvIHNob3cgZm9yIHRoZSBlbGVtZW50IGJhc2VkIG9uIHRoZSB2YWx1ZSBvZiBpc0ZvY3VzZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xudWxsfSB2YWx1ZSBBbiB1bmZvcm1hdHRlZCBudW1lcmljIHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHBhcmFtIHtib29sZWFufSBpc0ZvY3VzZWRcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfcm91bmRGb3JtYXR0ZWRWYWx1ZVNob3duT25Gb2N1c09yQmx1cih2YWx1ZSwgc2V0dGluZ3MsIGlzRm9jdXNlZCkge1xuICAgICAgICBpZiAoaXNGb2N1c2VkKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fcm91bmRGb3JtYXR0ZWRWYWx1ZVNob3duT25Gb2N1cyh2YWx1ZSwgc2V0dGluZ3MpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3JvdW5kRm9ybWF0dGVkVmFsdWVTaG93bk9uQmx1cih2YWx1ZSwgc2V0dGluZ3MpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUm91bmQgdGhlIGlucHV0IHZhbHVlIHVzaW5nIHRoZSByb3VuZGluZyBtZXRob2QgZGVmaW5lZCBpbiB0aGUgc2V0dGluZ3MuXG4gICAgICogVGhpcyBmdW5jdGlvbiBhY2NlcHRzIG11bHRpcGxlIHJvdW5kaW5nIG1ldGhvZHMuIFNlZSB0aGUgZG9jdW1lbnRhdGlvbiBmb3IgbW9yZSBkZXRhaWxzIGFib3V0IHRob3NlLlxuICAgICAqXG4gICAgICogTm90ZSA6IFRoaXMgaXMgaGFuZGxlZCBhcyB0ZXh0IHNpbmNlIEphdmFTY3JpcHQgbWF0aCBmdW5jdGlvbnMgY2FuIHJldHVybiBpbmFjY3VyYXRlIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfG51bGx9IGlucHV0VmFsdWUgQW4gdW5mb3JtYXR0ZWQgbnVtZXJpYyB2YWx1ZVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEBwYXJhbSB7aW50fSBkZWNpbWFsUGxhY2VzVG9Sb3VuZFRvXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgc3RhdGljIF9yb3VuZFZhbHVlKGlucHV0VmFsdWUsIHNldHRpbmdzLCBkZWNpbWFsUGxhY2VzVG9Sb3VuZFRvKSB7XG4gICAgICAgIC8vWFhYIE5vdGU7IHRoaXMgZnVuY3Rpb24gaXMgc3RhdGljIHNpbmNlIHdlIG5lZWQgdG8gcGFzcyBhIGBzZXR0aW5nc2Agb2JqZWN0IHdoZW4gY2FsbGluZyB0aGUgc3RhdGljIGBBdXRvTnVtZXJpYy5mb3JtYXQoKWAgbWV0aG9kXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoaW5wdXRWYWx1ZSkpIHtcbiAgICAgICAgICAgIC8vIFByZXZlbnQgcm91bmRpbmcgYSBgbnVsbGAgdmFsdWVcbiAgICAgICAgICAgIHJldHVybiBpbnB1dFZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy9UT0RPIERpdmlkZSB0aGlzIGZ1bmN0aW9uIHRvIG1ha2UgaXQgZWFzaWVyIHRvIHVuZGVyc3RhbmRcbiAgICAgICAgaW5wdXRWYWx1ZSA9IChpbnB1dFZhbHVlID09PSAnJykgPyAnMCcgOiBpbnB1dFZhbHVlLnRvU3RyaW5nKCk7XG4gICAgICAgIGlmIChzZXR0aW5ncy5yb3VuZGluZ01ldGhvZCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC50b05lYXJlc3QwNSB8fFxuICAgICAgICAgICAgc2V0dGluZ3Mucm91bmRpbmdNZXRob2QgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QudG9OZWFyZXN0MDVBbHQgfHxcbiAgICAgICAgICAgIHNldHRpbmdzLnJvdW5kaW5nTWV0aG9kID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLnVwVG9OZXh0MDUgfHxcbiAgICAgICAgICAgIHNldHRpbmdzLnJvdW5kaW5nTWV0aG9kID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmRvd25Ub05leHQwNSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3JvdW5kQ2xvc2VUbzA1KGlucHV0VmFsdWUsIHNldHRpbmdzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IFtuZWdhdGl2ZVNpZ24sIHByZXBhcmVkVmFsdWVdID0gQXV0b051bWVyaWMuX3ByZXBhcmVWYWx1ZUZvclJvdW5kaW5nKGlucHV0VmFsdWUsIHNldHRpbmdzKTtcbiAgICAgICAgaW5wdXRWYWx1ZSA9IHByZXBhcmVkVmFsdWU7XG5cbiAgICAgICAgY29uc3QgZGVjaW1hbENoYXJhY3RlclBvc2l0aW9uID0gaW5wdXRWYWx1ZS5sYXN0SW5kZXhPZignLicpO1xuICAgICAgICBjb25zdCBpbnB1dFZhbHVlSGFzTm9Eb3QgPSBkZWNpbWFsQ2hhcmFjdGVyUG9zaXRpb24gPT09IC0xOyAvLyBObyBkb3QgY2hhcmFjdGVyIGlzIGZvdW5kIGluIHRoZSBgaW5wdXRWYWx1ZWBcbiAgICAgICAgY29uc3QgWywgZGVjaW1hbFBhcnRdID0gaW5wdXRWYWx1ZS5zcGxpdCgnLicpOyAvLyBIZXJlIHRoZSBkZWNpbWFsIGNoYXJhY3RlciBpcyBhbHdheXMgYSBwZXJpb2QgJy4nXG4gICAgICAgIGNvbnN0IGhhc0RlY2ltYWxzID0gZGVjaW1hbFBhcnQgPiAwO1xuXG4gICAgICAgIC8vIElmIG5vIGRlY2ltYWxzIGFyZSBkZXRlY3RlZFxuICAgICAgICBpZiAoIWhhc0RlY2ltYWxzICYmXG4gICAgICAgICAgICAoc2V0dGluZ3MuYWxsb3dEZWNpbWFsUGFkZGluZyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5hbGxvd0RlY2ltYWxQYWRkaW5nLm5ldmVyIHx8XG4gICAgICAgICAgICBzZXR0aW5ncy5hbGxvd0RlY2ltYWxQYWRkaW5nID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmcuZmxvYXRzKSkge1xuICAgICAgICAgICAgcmV0dXJuIChOdW1iZXIoaW5wdXRWYWx1ZSkgPT09IDApID8gaW5wdXRWYWx1ZSA6IGAke25lZ2F0aXZlU2lnbn0ke2lucHV0VmFsdWV9YDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEVsc2UgdGhlcmUgYXJlIHNvbWUgZGVjaW1hbCBwbGFjZXMgdGhhdCBtYXkgbmVlZCB0byBiZSByb3VuZGVkXG4gICAgICAgIC8vIFNldHMgdGhlIHRydW5jYXRlIHplcm8gbWV0aG9kXG4gICAgICAgIGxldCB0ZW1wb3JhcnlEZWNpbWFsUGxhY2VzT3ZlcnJpZGU7XG4gICAgICAgIGlmIChzZXR0aW5ncy5hbGxvd0RlY2ltYWxQYWRkaW5nID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmcuYWx3YXlzIHx8XG4gICAgICAgICAgICBzZXR0aW5ncy5hbGxvd0RlY2ltYWxQYWRkaW5nID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmcuZmxvYXRzKSB7XG4gICAgICAgICAgICB0ZW1wb3JhcnlEZWNpbWFsUGxhY2VzT3ZlcnJpZGUgPSBkZWNpbWFsUGxhY2VzVG9Sb3VuZFRvO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGVtcG9yYXJ5RGVjaW1hbFBsYWNlc092ZXJyaWRlID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERlZmluZSB0aGUgZGVjaW1hbCBwb3NpdGlvbiB0byB1c2UgKHVzZSB0aGUgdmVyeSBsYXN0IHBvc2l0aW9uIGlmIHRoZXJlIGFyZSBubyBkb3QgaW4gdGhlIGluaXRpYWwgaW5wdXRWYWx1ZSlcbiAgICAgICAgY29uc3QgZGVjaW1hbFBvc2l0aW9uVG9Vc2UgPSBpbnB1dFZhbHVlSGFzTm9Eb3QgPyBpbnB1dFZhbHVlLmxlbmd0aCAtIDEgOiBkZWNpbWFsQ2hhcmFjdGVyUG9zaXRpb247XG4gICAgICAgIC8vIENoZWNrcyBkZWNpbWFsIHBsYWNlcyB0byBkZXRlcm1pbmUgaWYgcm91bmRpbmcgaXMgcmVxdWlyZWRcbiAgICAgICAgbGV0IGNoZWNrRGVjaW1hbFBsYWNlcyA9IChpbnB1dFZhbHVlLmxlbmd0aCAtIDEpIC0gZGVjaW1hbFBvc2l0aW9uVG9Vc2U7XG4gICAgICAgIGxldCBpbnB1dFZhbHVlUm91bmRlZCA9ICcnO1xuXG4gICAgICAgIC8vIENoZWNrIGlmIG5vIHJvdW5kaW5nIGlzIHJlcXVpcmVkXG4gICAgICAgIGlmIChjaGVja0RlY2ltYWxQbGFjZXMgPD0gZGVjaW1hbFBsYWNlc1RvUm91bmRUbykge1xuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgd2UgbmVlZCB0byBwYWQgd2l0aCB6ZXJvc1xuICAgICAgICAgICAgaW5wdXRWYWx1ZVJvdW5kZWQgPSBpbnB1dFZhbHVlO1xuICAgICAgICAgICAgaWYgKGNoZWNrRGVjaW1hbFBsYWNlcyA8IHRlbXBvcmFyeURlY2ltYWxQbGFjZXNPdmVycmlkZSkge1xuICAgICAgICAgICAgICAgIGlmIChpbnB1dFZhbHVlSGFzTm9Eb3QpIHtcbiAgICAgICAgICAgICAgICAgICAgaW5wdXRWYWx1ZVJvdW5kZWQgPSBgJHtpbnB1dFZhbHVlUm91bmRlZH0ke3NldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXJ9YDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBsZXQgemVyb3MgPSAnMDAwMDAwJzsgLy9UT0RPIENoYW5nZSB0aGF0IHN0cmluZyB3aXRoIGEgbG9uZ2VyIG9uZSB0byBwcmV2ZW50IGhhdmluZyB0byBsb29wIG51bWVyb3VzIHRpbWVzIGluIHRoZSBuZXh0IGB3aGlsZWAgc3RhdGVtZW50P1xuICAgICAgICAgICAgICAgIHdoaWxlIChjaGVja0RlY2ltYWxQbGFjZXMgPCB0ZW1wb3JhcnlEZWNpbWFsUGxhY2VzT3ZlcnJpZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgemVyb3MgPSB6ZXJvcy5zdWJzdHJpbmcoMCwgdGVtcG9yYXJ5RGVjaW1hbFBsYWNlc092ZXJyaWRlIC0gY2hlY2tEZWNpbWFsUGxhY2VzKTtcbiAgICAgICAgICAgICAgICAgICAgaW5wdXRWYWx1ZVJvdW5kZWQgKz0gemVyb3M7XG4gICAgICAgICAgICAgICAgICAgIGNoZWNrRGVjaW1hbFBsYWNlcyArPSB6ZXJvcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChjaGVja0RlY2ltYWxQbGFjZXMgPiB0ZW1wb3JhcnlEZWNpbWFsUGxhY2VzT3ZlcnJpZGUpIHtcbiAgICAgICAgICAgICAgICBpbnB1dFZhbHVlUm91bmRlZCA9IHRoaXMuX3RydW5jYXRlWmVyb3MoaW5wdXRWYWx1ZVJvdW5kZWQsIHRlbXBvcmFyeURlY2ltYWxQbGFjZXNPdmVycmlkZSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNoZWNrRGVjaW1hbFBsYWNlcyA9PT0gMCAmJiB0ZW1wb3JhcnlEZWNpbWFsUGxhY2VzT3ZlcnJpZGUgPT09IDApIHtcbiAgICAgICAgICAgICAgICAvLyBSZW1vdmUgYW55IHRyYWlsaW5nIGRvdCwgaWYgYW55XG4gICAgICAgICAgICAgICAgaW5wdXRWYWx1ZVJvdW5kZWQgPSBpbnB1dFZhbHVlUm91bmRlZC5yZXBsYWNlKC9cXC4kLywgJycpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gKE51bWJlcihpbnB1dFZhbHVlUm91bmRlZCkgPT09IDApID8gaW5wdXRWYWx1ZVJvdW5kZWQgOiBgJHtuZWdhdGl2ZVNpZ259JHtpbnB1dFZhbHVlUm91bmRlZH1gO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUm91bmRlZCBsZW5ndGggb2YgdGhlIHN0cmluZyBhZnRlciByb3VuZGluZ1xuICAgICAgICBsZXQgcm91bmRlZFN0ckxlbmd0aDtcbiAgICAgICAgaWYgKGlucHV0VmFsdWVIYXNOb0RvdCkge1xuICAgICAgICAgICAgcm91bmRlZFN0ckxlbmd0aCA9IGRlY2ltYWxQbGFjZXNUb1JvdW5kVG8gLSAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcm91bmRlZFN0ckxlbmd0aCA9IE51bWJlcihkZWNpbWFsUGxhY2VzVG9Sb3VuZFRvKSArIE51bWJlcihkZWNpbWFsQ2hhcmFjdGVyUG9zaXRpb24pO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbGFzdERpZ2l0ID0gTnVtYmVyKGlucHV0VmFsdWUuY2hhckF0KHJvdW5kZWRTdHJMZW5ndGggKyAxKSk7XG4gICAgICAgIGxldCBpbnB1dFZhbHVlQXJyYXkgPSBpbnB1dFZhbHVlLnN1YnN0cmluZygwLCByb3VuZGVkU3RyTGVuZ3RoICsgMSkuc3BsaXQoJycpO1xuICAgICAgICBsZXQgb2RkO1xuICAgICAgICBpZiAoaW5wdXRWYWx1ZS5jaGFyQXQocm91bmRlZFN0ckxlbmd0aCkgPT09ICcuJykge1xuICAgICAgICAgICAgb2RkID0gaW5wdXRWYWx1ZS5jaGFyQXQocm91bmRlZFN0ckxlbmd0aCAtIDEpICUgMjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG9kZCA9IGlucHV0VmFsdWUuY2hhckF0KHJvdW5kZWRTdHJMZW5ndGgpICUgMjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLl9zaG91bGRSb3VuZFVwKGxhc3REaWdpdCwgc2V0dGluZ3MsIG5lZ2F0aXZlU2lnbiwgb2RkKSkge1xuICAgICAgICAgICAgLy8gUm91bmQgdXAgdGhlIGxhc3QgZGlnaXQgaWYgcmVxdWlyZWQsIGFuZCBjb250aW51ZSB1bnRpbCBubyBtb3JlIDkncyBhcmUgZm91bmRcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAoaW5wdXRWYWx1ZUFycmF5Lmxlbmd0aCAtIDEpOyBpID49IDA7IGkgLT0gMSkge1xuICAgICAgICAgICAgICAgIGlmIChpbnB1dFZhbHVlQXJyYXlbaV0gIT09ICcuJykge1xuICAgICAgICAgICAgICAgICAgICBpbnB1dFZhbHVlQXJyYXlbaV0gPSAraW5wdXRWYWx1ZUFycmF5W2ldICsgMTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlucHV0VmFsdWVBcnJheVtpXSA8IDEwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXRWYWx1ZUFycmF5W2ldID0gJzAnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVjb25zdHJ1Y3QgdGhlIHN0cmluZywgY29udmVydGluZyBhbnkgMTAncyB0byAwJ3NcbiAgICAgICAgaW5wdXRWYWx1ZUFycmF5ID0gaW5wdXRWYWx1ZUFycmF5LnNsaWNlKDAsIHJvdW5kZWRTdHJMZW5ndGggKyAxKTtcblxuICAgICAgICAvLyBSZXR1cm4gdGhlIHJvdW5kZWQgdmFsdWVcbiAgICAgICAgaW5wdXRWYWx1ZVJvdW5kZWQgPSB0aGlzLl90cnVuY2F0ZVplcm9zKGlucHV0VmFsdWVBcnJheS5qb2luKCcnKSwgdGVtcG9yYXJ5RGVjaW1hbFBsYWNlc092ZXJyaWRlKTtcblxuICAgICAgICByZXR1cm4gKE51bWJlcihpbnB1dFZhbHVlUm91bmRlZCkgPT09IDApID8gaW5wdXRWYWx1ZVJvdW5kZWQgOiBgJHtuZWdhdGl2ZVNpZ259JHtpbnB1dFZhbHVlUm91bmRlZH1gO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJvdW5kIHRoZSBgdmFsdWVgIHdoZW4gdGhlIHJvdW5kaW5nIG1ldGhvZCBkZWFscyB3aXRoICcuMDUnXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9yb3VuZENsb3NlVG8wNSh2YWx1ZSwgc2V0dGluZ3MpIHtcbiAgICAgICAgc3dpdGNoIChzZXR0aW5ncy5yb3VuZGluZ01ldGhvZCkge1xuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLnRvTmVhcmVzdDA1OlxuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLnRvTmVhcmVzdDA1QWx0OlxuICAgICAgICAgICAgICAgIHZhbHVlID0gKE1hdGgucm91bmQodmFsdWUgKiAyMCkgLyAyMCkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC51cFRvTmV4dDA1OlxuICAgICAgICAgICAgICAgIHZhbHVlID0gKE1hdGguY2VpbCh2YWx1ZSAqIDIwKSAvIDIwKS50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdCA6XG4gICAgICAgICAgICAgICAgdmFsdWUgPSAoTWF0aC5mbG9vcih2YWx1ZSAqIDIwKSAvIDIwKS50b1N0cmluZygpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyh2YWx1ZSwgJy4nKSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWUgKyAnLjAwJztcbiAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5sZW5ndGggLSB2YWx1ZS5pbmRleE9mKCcuJykgPCAzKSB7XG4gICAgICAgICAgICByZXN1bHQgPSB2YWx1ZSArICcwJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNb2RpZnkgdGhlIGdpdmVuIGB2YWx1ZWAgaW4gb3JkZXIgdG8gbWFrZSBpdCB1c2FibGUgZm9yIHRoZSByZXN0IG9mIHRoZSByb3VuZGluZyBmdW5jdGlvbi5cbiAgICAgKiBUaGlzIGNvbnZlcnQgdGhlIGB2YWx1ZWAgdG8gYSBwb3NpdGl2ZSBvbmUsIHRyaW0gYW55IGxlYWRpbmcgemVyb3MgYW5kIG1ha2Ugc3VyZSBpdCBkb2VzIG5vdCBzdGFydHMgd2l0aCBhIGxlYWRpbmcgZG90LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIFRoZSB1bmZvcm1hdHRlZCB2YWx1ZVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEByZXR1cm5zIHtbc3RyaW5nLCBzdHJpbmddfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9wcmVwYXJlVmFsdWVGb3JSb3VuZGluZyh2YWx1ZSwgc2V0dGluZ3MpIHtcbiAgICAgICAgLy8gQ2hlY2tzIGlmIGBpbnB1dFZhbHVlYCBpcyBhIG5lZ2F0aXZlIHZhbHVlXG4gICAgICAgIGxldCBuZWdhdGl2ZVNpZ24gPSAnJztcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmVTdHJpY3QodmFsdWUsICctJykpIHsgLy8gVGhlIHZhbHVlIGJlaW5nIHVuZm9ybWF0dGVkLCB3ZSBjaGVjayBmb3IgdGhlIG1pbnVzIHNpZ25cbiAgICAgICAgICAgIG5lZ2F0aXZlU2lnbiA9ICctJztcblxuICAgICAgICAgICAgLy8gUmVtb3ZlcyB0aGUgbmVnYXRpdmUgc2lnbiB0aGF0IHdpbGwgYmUgYWRkZWQgYmFjayBsYXRlciBpZiByZXF1aXJlZFxuICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKCctJywgJycpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQXBwZW5kIGEgemVybyBpZiB0aGUgZmlyc3QgY2hhcmFjdGVyIGlzIG5vdCBhIGRpZ2l0ICh0aGVuIGl0IGlzIGxpa2VseSBhIGRvdClcbiAgICAgICAgaWYgKCF2YWx1ZS5tYXRjaCgvXlxcZC8pKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IGAwJHt2YWx1ZX1gO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGV0ZXJtaW5lcyBpZiB0aGUgdmFsdWUgaXMgZXF1YWwgdG8gemVyby4gSWYgaXQgaXMsIHJlbW92ZSB0aGUgbmVnYXRpdmUgc2lnblxuICAgICAgICBpZiAoTnVtYmVyKHZhbHVlKSA9PT0gMCkge1xuICAgICAgICAgICAgbmVnYXRpdmVTaWduID0gJyc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUcmltcyBsZWFkaW5nIHplcm8ncyBhcyBuZWVkZWRcbiAgICAgICAgaWYgKChOdW1iZXIodmFsdWUpID4gMCAmJiBzZXR0aW5ncy5sZWFkaW5nWmVybyAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5sZWFkaW5nWmVyby5rZWVwKSB8fFxuICAgICAgICAgICAgKHZhbHVlLmxlbmd0aCA+IDAgJiYgc2V0dGluZ3MubGVhZGluZ1plcm8gPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubGVhZGluZ1plcm8uYWxsb3cpKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnJlcGxhY2UoL14wKihcXGQpLywgJyQxJyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gW25lZ2F0aXZlU2lnbiwgdmFsdWVdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgYSByb3VuZCB1cCBzaG91bGQgYmUgZG9uZSBnaXZlbiB0aGUgbGFzdCBkaWdpdCwgdGhlIHNldHRpbmdzIGFuZCBvdGhlciBpbmZvcm1hdGlvbiBhYm91dCB0aGUgdmFsdWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbGFzdERpZ2l0XG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5lZ2F0aXZlU2lnbiBUaGlzIHZhcmlhYmxlIGNvbWVzIGZyb20gYF9wcmVwYXJlVmFsdWVGb3JSb3VuZGluZygpYCwgd2hpY2ggcmV0dXJuIGAnLSdgIGlmIHRoZSBpbml0aWFsIHZhbHVlIHdhcyBuZWdhdGl2ZVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBvZGRcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfc2hvdWxkUm91bmRVcChsYXN0RGlnaXQsIHNldHRpbmdzLCBuZWdhdGl2ZVNpZ24sIG9kZCkge1xuICAgICAgICByZXR1cm4gKGxhc3REaWdpdCA+IDQgJiYgc2V0dGluZ3Mucm91bmRpbmdNZXRob2QgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QuaGFsZlVwU3ltbWV0cmljKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8fCAvLyBSb3VuZCBoYWxmIHVwIHN5bW1ldHJpY1xuICAgICAgICAgICAgKGxhc3REaWdpdCA+IDQgJiYgc2V0dGluZ3Mucm91bmRpbmdNZXRob2QgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QuaGFsZlVwQXN5bW1ldHJpYyAmJiBuZWdhdGl2ZVNpZ24gPT09ICcnKSAgICAgICAgICAgICAgICB8fCAvLyBSb3VuZCBoYWxmIHVwIGFzeW1tZXRyaWMgcG9zaXRpdmUgdmFsdWVzXG4gICAgICAgICAgICAobGFzdERpZ2l0ID4gNSAmJiBzZXR0aW5ncy5yb3VuZGluZ01ldGhvZCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC5oYWxmVXBBc3ltbWV0cmljICYmIG5lZ2F0aXZlU2lnbiA9PT0gJy0nKSAgICAgICAgICAgICAgIHx8IC8vIFJvdW5kIGhhbGYgdXAgYXN5bW1ldHJpYyBuZWdhdGl2ZSB2YWx1ZXNcbiAgICAgICAgICAgIChsYXN0RGlnaXQgPiA1ICYmIHNldHRpbmdzLnJvdW5kaW5nTWV0aG9kID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmhhbGZEb3duU3ltbWV0cmljKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfHwgLy8gUm91bmQgaGFsZiBkb3duIHN5bW1ldHJpY1xuICAgICAgICAgICAgKGxhc3REaWdpdCA+IDUgJiYgc2V0dGluZ3Mucm91bmRpbmdNZXRob2QgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QuaGFsZkRvd25Bc3ltbWV0cmljICYmIG5lZ2F0aXZlU2lnbiA9PT0gJycpICAgICAgICAgICAgICB8fCAvLyBSb3VuZCBoYWxmIGRvd24gYXN5bW1ldHJpYyBwb3NpdGl2ZSB2YWx1ZXNcbiAgICAgICAgICAgIChsYXN0RGlnaXQgPiA0ICYmIHNldHRpbmdzLnJvdW5kaW5nTWV0aG9kID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmhhbGZEb3duQXN5bW1ldHJpYyAmJiBuZWdhdGl2ZVNpZ24gPT09ICctJykgICAgICAgICAgICAgfHwgLy8gUm91bmQgaGFsZiBkb3duIGFzeW1tZXRyaWMgbmVnYXRpdmUgdmFsdWVzXG4gICAgICAgICAgICAobGFzdERpZ2l0ID4gNSAmJiBzZXR0aW5ncy5yb3VuZGluZ01ldGhvZCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC5oYWxmRXZlbkJhbmtlcnNSb3VuZGluZykgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHx8XG4gICAgICAgICAgICAobGFzdERpZ2l0ID09PSA1ICYmIHNldHRpbmdzLnJvdW5kaW5nTWV0aG9kID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmhhbGZFdmVuQmFua2Vyc1JvdW5kaW5nICYmIG9kZCA9PT0gMSkgICAgICAgICAgICAgICAgIHx8XG4gICAgICAgICAgICAobGFzdERpZ2l0ID4gMCAmJiBzZXR0aW5ncy5yb3VuZGluZ01ldGhvZCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC50b0NlaWxpbmdUb3dhcmRQb3NpdGl2ZUluZmluaXR5ICYmIG5lZ2F0aXZlU2lnbiA9PT0gJycpIHx8XG4gICAgICAgICAgICAobGFzdERpZ2l0ID4gMCAmJiBzZXR0aW5ncy5yb3VuZGluZ01ldGhvZCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC50b0Zsb29yVG93YXJkTmVnYXRpdmVJbmZpbml0eSAmJiBuZWdhdGl2ZVNpZ24gPT09ICctJykgIHx8XG4gICAgICAgICAgICAobGFzdERpZ2l0ID4gMCAmJiBzZXR0aW5ncy5yb3VuZGluZ01ldGhvZCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC51cFJvdW5kQXdheUZyb21aZXJvKTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJvdW5kIHVwIGF3YXkgZnJvbSB6ZXJvXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVHJ1bmNhdGVzIHRoZSBkZWNpbWFsIHBhcnQgb2YgYSBudW1iZXIgdG8gdGhlIGdpdmVuIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyBgZGVjaW1hbFBsYWNlc1RvUm91bmRUb2AuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGlzUGFzdGVcbiAgICAgKiBAcGFyYW0ge2ludH0gZGVjaW1hbFBsYWNlc1RvUm91bmRUb1xuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyBfdHJ1bmNhdGVEZWNpbWFsUGxhY2VzKHZhbHVlLCBzZXR0aW5ncywgaXNQYXN0ZSwgZGVjaW1hbFBsYWNlc1RvUm91bmRUbykge1xuICAgICAgICBpZiAoaXNQYXN0ZSkge1xuICAgICAgICAgICAgdmFsdWUgPSB0aGlzLl9yb3VuZEZvcm1hdHRlZFZhbHVlU2hvd25PbkZvY3VzKHZhbHVlLCBzZXR0aW5ncyk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBbaW50ZWdlclBhcnQsIGRlY2ltYWxQYXJ0XSA9IHZhbHVlLnNwbGl0KHNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpO1xuXG4gICAgICAgIC8vIFRydW5jYXRlIHRoZSBkZWNpbWFsIHBhcnQgdG8gdGhlIHNhdGlzZnlpbmcgbGVuZ3RoIHNpbmNlIHdlIHdvdWxkIHJvdW5kIGl0IGFueXdheVxuICAgICAgICBpZiAoZGVjaW1hbFBhcnQgJiYgZGVjaW1hbFBhcnQubGVuZ3RoID4gZGVjaW1hbFBsYWNlc1RvUm91bmRUbykge1xuICAgICAgICAgICAgaWYgKGRlY2ltYWxQbGFjZXNUb1JvdW5kVG8gPiAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbW9kaWZpZWREZWNpbWFsUGFydCA9IGRlY2ltYWxQYXJ0LnN1YnN0cmluZygwLCBkZWNpbWFsUGxhY2VzVG9Sb3VuZFRvKTtcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IGAke2ludGVnZXJQYXJ0fSR7c2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlcn0ke21vZGlmaWVkRGVjaW1hbFBhcnR9YDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSBpbnRlZ2VyUGFydDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayB0aGF0IHRoZSBudW1iZXIgc2F0aXNmeSB0aGUgZm9ybWF0IGNvbmRpdGlvbnNcbiAgICAgKiBhbmQgbGF5cyBiZXR3ZWVuIHNldHRpbmdzLm1pbmltdW1WYWx1ZSBhbmQgc2V0dGluZ3MubWF4aW11bVZhbHVlXG4gICAgICogYW5kIHRoZSBzdHJpbmcgbGVuZ3RoIGRvZXMgbm90IGV4Y2VlZCB0aGUgZGlnaXRzIGluIHNldHRpbmdzLm1pbmltdW1WYWx1ZSBhbmQgc2V0dGluZ3MubWF4aW11bVZhbHVlXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBzdGF0aWMgX2NoZWNrSWZJblJhbmdlV2l0aE92ZXJyaWRlT3B0aW9uKHZhbHVlLCBzZXR0aW5ncykge1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKHZhbHVlKSAmJiBzZXR0aW5ncy5lbXB0eUlucHV0QmVoYXZpb3IgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLm51bGwpIHtcbiAgICAgICAgICAgIC8vIFdoZW4gdGhlIGBudWxsYCB2YWx1ZSBpcyBhY2NlcHRlZCBhcyB0aGUgYHJhd1ZhbHVlYCwgdGhlIGxpbWl0cyBhcmUgaWdub3JlZFxuICAgICAgICAgICAgcmV0dXJuIFt0cnVlLCB0cnVlXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhbHVlID0gdmFsdWUudG9TdHJpbmcoKTtcbiAgICAgICAgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKCcsJywgJy4nKTtcbiAgICAgICAgY29uc3QgbWluUGFyc2UgPSBBdXRvTnVtZXJpY0hlbHBlci5wYXJzZVN0cihzZXR0aW5ncy5taW5pbXVtVmFsdWUpO1xuICAgICAgICBjb25zdCBtYXhQYXJzZSA9IEF1dG9OdW1lcmljSGVscGVyLnBhcnNlU3RyKHNldHRpbmdzLm1heGltdW1WYWx1ZSk7XG4gICAgICAgIGNvbnN0IHZhbFBhcnNlID0gQXV0b051bWVyaWNIZWxwZXIucGFyc2VTdHIodmFsdWUpO1xuXG4gICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgIHN3aXRjaCAoc2V0dGluZ3Mub3ZlcnJpZGVNaW5NYXhMaW1pdHMpIHtcbiAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5vdmVycmlkZU1pbk1heExpbWl0cy5mbG9vcjpcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBbQXV0b051bWVyaWNIZWxwZXIudGVzdE1pbk1heChtaW5QYXJzZSwgdmFsUGFyc2UpID4gLTEsIHRydWVdO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm92ZXJyaWRlTWluTWF4TGltaXRzLmNlaWxpbmc6XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gW3RydWUsIEF1dG9OdW1lcmljSGVscGVyLnRlc3RNaW5NYXgobWF4UGFyc2UsIHZhbFBhcnNlKSA8IDFdO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm92ZXJyaWRlTWluTWF4TGltaXRzLmlnbm9yZTpcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBbdHJ1ZSwgdHJ1ZV07XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IFtBdXRvTnVtZXJpY0hlbHBlci50ZXN0TWluTWF4KG1pblBhcnNlLCB2YWxQYXJzZSkgPiAtMSwgQXV0b051bWVyaWNIZWxwZXIudGVzdE1pbk1heChtYXhQYXJzZSwgdmFsUGFyc2UpIDwgMV07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE9yaWdpbmFsIHNldHRpbmdzIHNhdmVkIGZvciB1c2Ugd2hlbiB0aGUgYGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXNgIGFuZCBgc2hvd09ubHlOdW1iZXJzT25Gb2N1c2Agb3B0aW9ucyBhcmUgdXNlZC5cbiAgICAgKiBUaG9zZSBvcmlnaW5hbCBzZXR0aW5ncyBhcmUgdXNlZCBleGNsdXNpdmVseSBpbiB0aGUgYGZvY3VzaW5gIGFuZCBgZm9jdXNvdXRgIGV2ZW50IGhhbmRsZXJzLlxuICAgICAqL1xuICAgIF9rZWVwQW5PcmlnaW5hbFNldHRpbmdzQ29weSgpIHtcbiAgICAgICAgdGhpcy5vcmlnaW5hbERpZ2l0R3JvdXBTZXBhcmF0b3IgPSB0aGlzLnNldHRpbmdzLmRpZ2l0R3JvdXBTZXBhcmF0b3I7XG4gICAgICAgIHRoaXMub3JpZ2luYWxDdXJyZW5jeVN5bWJvbCAgICAgID0gdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbDtcbiAgICAgICAgdGhpcy5vcmlnaW5hbFN1ZmZpeFRleHQgICAgICAgICAgPSB0aGlzLnNldHRpbmdzLnN1ZmZpeFRleHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT3JpZ2luYWwgc2V0dGluZ3Mgc2F2ZWQgZm9yIHVzZSB3aGVuIGBkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzYCAmIGBzaG93T25seU51bWJlcnNPbkZvY3VzYCBvcHRpb25zIGFyZSBiZWluZyB1c2VkLlxuICAgICAqIFRoaXMgaXMgdGFrZW4gZnJvbSBRdWlya3Ntb2RlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBzdGF0aWMgX3JlYWRDb29raWUobmFtZSkge1xuICAgICAgICBjb25zdCBuYW1lRVEgPSBuYW1lICsgJz0nO1xuICAgICAgICBjb25zdCBjYSA9IGRvY3VtZW50LmNvb2tpZS5zcGxpdCgnOycpO1xuICAgICAgICBsZXQgYyA9ICcnO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNhLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBjID0gY2FbaV07XG4gICAgICAgICAgICB3aGlsZSAoYy5jaGFyQXQoMCkgPT09ICcgJykge1xuICAgICAgICAgICAgICAgIGMgPSBjLnN1YnN0cmluZygxLCBjLmxlbmd0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYy5pbmRleE9mKG5hbWVFUSkgPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYy5zdWJzdHJpbmcobmFtZUVRLmxlbmd0aCwgYy5sZW5ndGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGVzdCBpZiBzZXNzaW9uU3RvcmFnZSBpcyBzdXBwb3J0ZWQuXG4gICAgICogVGhpcyBpcyB0YWtlbiBmcm9tIE1vZGVybml6ci5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIHN0YXRpYyBfc3RvcmFnZVRlc3QoKSB7XG4gICAgICAgIGNvbnN0IG1vZCA9ICdtb2Rlcm5penInO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgc2Vzc2lvblN0b3JhZ2Uuc2V0SXRlbShtb2QsIG1vZCk7XG4gICAgICAgICAgICBzZXNzaW9uU3RvcmFnZS5yZW1vdmVJdGVtKG1vZCk7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhbnkgemVyb3MgaW4gZXhjZXNzIGluIHRoZSBmcm9udCBhbmQgYmFjayBvZiB0aGUgZ2l2ZW4gYHZhbHVlYCwgYWNjb3JkaW5nIHRvIHRoZSBgc2V0dGluZ3NgLlxuICAgICAqIFRoaXMgYWxzbyBtYW5hZ2VzIHRoZSBjYXNlcyB3aGVyZSB0aGUgZGVjaW1hbCBwb2ludCBpcyBvbiB0aGUgZmFyIGxlZnQgb3IgZmFyIHJpZ2h0IG9mIHRoZSBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAgICogQHJldHVybnMge3N0cmluZ3xudWxsfVxuICAgICAqL1xuICAgIF90cmltTGVhZGluZ0FuZFRyYWlsaW5nWmVyb3ModmFsdWUpIHtcbiAgICAgICAgLy8gUmV0dXJuIHRoZSBlbXB0eSBzdHJpbmcgaXMgdGhlIHZhbHVlIGlzIGFscmVhZHkgZW1wdHkuIFRoaXMgcHJldmVudCBjb252ZXJ0aW5nIHRoYXQgdmFsdWUgdG8gJzAnLlxuICAgICAgICBpZiAodmFsdWUgPT09ICcnIHx8IHZhbHVlID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5sZWFkaW5nWmVybyAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5sZWFkaW5nWmVyby5rZWVwKSB7XG4gICAgICAgICAgICBpZiAoTnVtYmVyKHZhbHVlKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIC8vIFJldHVybiAnMCcgaWYgdGhlIHZhbHVlIGlzIHplcm9cbiAgICAgICAgICAgICAgICByZXR1cm4gJzAnO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBUcmltIHRoZSBsZWFkaW5nIHplcm9zLCB3aGlsZSBsZWF2aW5nIG9uZSB6ZXJvIHRvIHRoZSBsZWZ0IG9mIHRoZSBkZWNpbWFsIHBvaW50IGlmIG5lZWRlZFxuICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKC9eKC0pPzArKD89XFxkKS9nLCckMScpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy9UT0RPIHJlbW92ZSB0aGlzIGZyb20gdGhhdCBmdW5jdGlvbiBhbmQgdXNlIGB0cmltUGFkZGVkWmVyb3NGcm9tRGVjaW1hbFBsYWNlcygpYCBpbnN0ZWFkXG4gICAgICAgIC8vIFRyaW0gdGhlIHRyYWlsaW5nIHplcm9zIGFmdGVyIHRoZSBsYXN0IGRlY2ltYWwgcGxhY2Ugbm90IGJlaW5nIGEgemVybyAoaWUuIDEuMjMwMCAtPiAxLjIzKVxuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnModmFsdWUsICcuJykpIHtcbiAgICAgICAgICAgIHZhbHVlID0gdmFsdWUucmVwbGFjZSgvKFxcLlswLTldKj8pMCskLywgJyQxJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZW1vdmUgYW55IHRyYWlsaW5nIGRlY2ltYWwgcG9pbnRcbiAgICAgICAgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKC9cXC4kLywgJycpO1xuXG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSB0aGUgbmFtZSBmb3IgdGhlIHBlcnNpc3RlbnQgc3RvcmVkIGRhdGEgdmFyaWFibGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9zZXRQZXJzaXN0ZW50U3RvcmFnZU5hbWUoKSB7XG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLnNhdmVWYWx1ZVRvU2Vzc2lvblN0b3JhZ2UpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmRvbUVsZW1lbnQubmFtZSAhPT0gJycgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkKHRoaXMuZG9tRWxlbWVudC5uYW1lKSkge1xuICAgICAgICAgICAgICAgIHRoaXMucmF3VmFsdWVTdG9yYWdlTmFtZSA9IGAke3RoaXMuc3RvcmFnZU5hbWVQcmVmaXh9JHtkZWNvZGVVUklDb21wb25lbnQodGhpcy5kb21FbGVtZW50Lm5hbWUpfWA7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMucmF3VmFsdWVTdG9yYWdlTmFtZSA9IGAke3RoaXMuc3RvcmFnZU5hbWVQcmVmaXh9JHt0aGlzLmRvbUVsZW1lbnQuaWR9YDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNhdmUgdGhlIHJhdyBWYWx1ZSBpbnRvIHNlc3Npb25TdG9yYWdlIG9yIGEgY29va2llIGRlcGVuZGluZyBvbiB3aGF0IHRoZSBicm93c2VyIGlzIHN1cHBvcnRpbmcuXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfc2F2ZVZhbHVlVG9QZXJzaXN0ZW50U3RvcmFnZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3Muc2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuc2Vzc2lvblN0b3JhZ2VBdmFpbGFibGUpIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uU3RvcmFnZS5zZXRJdGVtKHRoaXMucmF3VmFsdWVTdG9yYWdlTmFtZSwgdGhpcy5yYXdWYWx1ZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFVzZSBjb29raWVzIGZvciBvYnNvbGV0ZSBicm93c2VycyB0aGF0IGRvIG5vdCBzdXBwb3J0IHNlc3Npb25TdG9yYWdlIChpZS4gSUUgNiAmIDcpXG4gICAgICAgICAgICAgICAgZG9jdW1lbnQuY29va2llID0gYCR7dGhpcy5yYXdWYWx1ZVN0b3JhZ2VOYW1lfT0ke3RoaXMucmF3VmFsdWV9OyBleHBpcmVzPSA7IHBhdGg9L2A7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZSB0aGUgcmF3IHZhbHVlIGZyb20gc2Vzc2lvblN0b3JhZ2Ugb3IgdGhlIGNvb2tpZSBkZXBlbmRpbmcgb24gd2hhdCB0aGUgYnJvd3NlciBpcyBzdXBwb3J0aW5nLlxuICAgICAqXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZ2V0VmFsdWVGcm9tUGVyc2lzdGVudFN0b3JhZ2UoKSB7XG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLnNhdmVWYWx1ZVRvU2Vzc2lvblN0b3JhZ2UpIHtcbiAgICAgICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgICAgICBpZiAodGhpcy5zZXNzaW9uU3RvcmFnZUF2YWlsYWJsZSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHNlc3Npb25TdG9yYWdlLmdldEl0ZW0odGhpcy5yYXdWYWx1ZVN0b3JhZ2VOYW1lKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdGhpcy5jb25zdHJ1Y3Rvci5fcmVhZENvb2tpZSh0aGlzLnJhd1ZhbHVlU3RvcmFnZU5hbWUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZygnYF9nZXRWYWx1ZUZyb21QZXJzaXN0ZW50U3RvcmFnZSgpYCBpcyBjYWxsZWQgYnV0IGBzZXR0aW5ncy5zYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlYCBpcyBmYWxzZS4gVGhlcmUgbXVzdCBiZSBhbiBlcnJvciB0aGF0IG5lZWRzIGZpeGluZy4nLCB0aGlzLnNldHRpbmdzLnNob3dXYXJuaW5ncyk7XG5cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIHRoZSByYXcgdmFsdWUgZGF0YSBmcm9tIHNlc3Npb25TdG9yYWdlIG9yIHRoZSBjb29raWUgZGVwZW5kaW5nIG9uIHdoYXQgdGhlIGJyb3dzZXIgaXMgc3VwcG9ydGluZy5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9yZW1vdmVWYWx1ZUZyb21QZXJzaXN0ZW50U3RvcmFnZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3Muc2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuc2Vzc2lvblN0b3JhZ2VBdmFpbGFibGUpIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uU3RvcmFnZS5yZW1vdmVJdGVtKHRoaXMucmF3VmFsdWVTdG9yYWdlTmFtZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZSgpO1xuICAgICAgICAgICAgICAgIGRhdGUuc2V0VGltZShkYXRlLmdldFRpbWUoKSAtIDg2NDAwMDAwKTsgLy8gLTg2NDAwMDAwID09PSAtMSAqIDI0ICogNjAgKiA2MCAqIDEwMDBcbiAgICAgICAgICAgICAgICBjb25zdCBleHBpcmVzID0gYDsgZXhwaXJlcz0ke2RhdGUudG9VVENTdHJpbmcoKX1gO1xuICAgICAgICAgICAgICAgIGRvY3VtZW50LmNvb2tpZSA9IGAke3RoaXMucmF3VmFsdWVTdG9yYWdlTmFtZX09JycgOyR7ZXhwaXJlc307IHBhdGg9L2A7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGRlZmF1bHQgdmFsdWUgZnJvbSB0aGUgaHRtbCBgdmFsdWVgIGF0dHJpYnV0ZS5cbiAgICAgKiBSZXR1cm4gdGhlIGVtcHR5IHN0cmluZyBpZiBzdWNoIGF0dHJpYnV0ZSBpcyBub3QgZm91bmQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBkb21FbGVtZW50XG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2dldERlZmF1bHRWYWx1ZShkb21FbGVtZW50KSB7XG4gICAgICAgIC8vIEdldCB0aGUgZGVmYXVsdCBodG1sIHZhbHVlXG4gICAgICAgIC8vIE5vdGU6IHdlIGRvIG5vdCB1c2UgdGhlIHNpbXBsZXIgYHJldHVybiBkb21FbGVtZW50LmRlZmF1bHRWYWx1ZTtgIGNvZGUgc2luY2UgdGhlIGdpdmVuIGRvbUVsZW1lbnQgY2FuIHNvbWV0aW1lIGJlIGEgYGNvbnRlbnRlZGl0YWJsZWAgZWxlbWVudCB3aGljaCBkb2VzIG5vdCBzdXBwb3J0IHRoZSBgZGVmYXVsdFZhbHVlYCBhdHRyaWJ1dGUuXG4gICAgICAgIGNvbnN0IHZhbHVlID0gZG9tRWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3ZhbHVlJyk7XG5cbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbCh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVyIGZvciAnZm9jdXNpbicgYW5kICdtb3VzZWVudGVyJyBldmVudHNcbiAgICAgKiBPbiBmb2N1c2luLCBtdWx0aXBsZSB0aGluZ3MgaGFwcGVucyA6XG4gICAgICogLSBJZiBgQWx0YCBpcyBwcmVzc2VkLCB1bmZvcm1hdFxuICAgICAqIC0gUmVtb3ZlIHRoZSBzZXBhcmF0b3JzIGlmIGBzaG93T25seU51bWJlcnNPbkZvY3VzYCBpcyBzZXRcbiAgICAgKiAtIERlcGVuZGluZyBvbiBgZW1wdHlJbnB1dEJlaGF2aW9yYCwgcmVmb3JtYXQgdGhlIGVtcHR5IGZvcm1hdHRlZCB2YWx1ZVxuICAgICAqIC0gRGlzcGxheSB0aGUgY29ycmVjdCBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgKG9uIGZvY3VzL2JsdXIpXG4gICAgICogLSBQbGFjZSB0aGUgY2FyZXQgY29ycmVjdGx5IGlmIHRoZSBlbGVtZW50IGlzIGVtcHR5XG4gICAgICpcbiAgICAgKiBOb3RlOiBPbiBmb2N1c2luLCB0aGUgYHJhd1ZhbHVlYCBpcyBuZXZlciBjaGFuZ2VkLiBPbmx5IHRoZSBmb3JtYXR0ZWQgdmFsdWUgY2FuIGJlIG1vZGlmaWVkLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtLZXlib2FyZEV2ZW50fE1vdXNlRXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9vbkZvY3VzSW5BbmRNb3VzZUVudGVyKGUpIHtcbiAgICAgICAgLy9UT0RPIENyZWF0ZSBzZXBhcmF0ZSBoYW5kbGVycyBmb3IgdGhlIGZvY3VzIGFuZCBtb3VzZWVudGVyIGV2ZW50c1xuICAgICAgICB0aGlzLmlzRWRpdGluZyA9IGZhbHNlOyAvLyBKdXN0IGluIGNhc2Ugbm8gYGtleVVwYCBldmVudCBoYXZlIGJlZW4gc2VudCAoaWUuIGlmIHRoZSB1c2VyIGxvc3QgdGhlIGZvY3VzIGZyb20gdGhlIGN1cnJlbnQgd2luZG93IHdoaWxlIHR5cGluZylcblxuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy51bmZvcm1hdE9uSG92ZXIgJiYgZS50eXBlID09PSAnbW91c2VlbnRlcicgJiYgZS5hbHRLZXkpIHtcbiAgICAgICAgICAgIHRoaXMuY29uc3RydWN0b3IuX3VuZm9ybWF0QWx0SG92ZXJlZCh0aGlzKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGUudHlwZSA9PT0gJ2ZvY3VzJykgeyAvL1RPRE8gTW92ZSB0aGF0IGJhY2sgdG8gdGhlICdmb2N1cycgZXZlbnQgaGFuZGxlciB3aGVuIHRoZSBzZXBhcmF0aW9uIGJldHdlZW4gdGhlICdmb2N1cycgYW5kICdtb3VzZWVudGVyJyBoYW5kbGVyIHdpbGwgYmUgZG9uZVxuICAgICAgICAgICAgLy8gS2VlcCB0cmFjayBpZiB0aGUgZWxlbWVudCBpcyBjdXJyZW50bHkgZm9jdXNlZFxuICAgICAgICAgICAgdGhpcy5pc0ZvY3VzZWQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5yYXdWYWx1ZU9uRm9jdXMgPSB0aGlzLnJhd1ZhbHVlOyAvLyBLZWVwIHRyYWNrIG9mIHRoZSBpbml0aWFsIHJhd1ZhbHVlLiBUaGlzIGlzIG5lZWRlZCB0byBkZWZpbmUgaWYgYSBjaGFuZ2UgZXZlbnQgbXVzdCBiZSBkaXNwYXRjaGVkIGxhdGVyXG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZS50eXBlID09PSAnZm9jdXMnICYmIHRoaXMuc2V0dGluZ3MudW5mb3JtYXRPbkhvdmVyICYmIHRoaXMuaG92ZXJlZFdpdGhBbHQpIHtcbiAgICAgICAgICAgIHRoaXMuY29uc3RydWN0b3IuX3JlZm9ybWF0QWx0SG92ZXJlZCh0aGlzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChlLnR5cGUgPT09ICdmb2N1cycgfHwgZS50eXBlID09PSAnbW91c2VlbnRlcicgJiYgIXRoaXMuaXNGb2N1c2VkKSB7XG4gICAgICAgICAgICBsZXQgZWxlbWVudFZhbHVlVG9TZXQgPSBudWxsOyAvLyBTdG9yZSB0aGUgdmFsdWUgd2Ugd2FudCB0byBzZXQgb24gdGhlIGVsZW1lbnQsIGFuZCBvbmx5IGNhbGwgYF9zZXRFbGVtZW50VmFsdWUoKWAgb25jZVxuXG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5lbXB0eUlucHV0QmVoYXZpb3IgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLmZvY3VzICYmXG4gICAgICAgICAgICAgICAgdGhpcy5yYXdWYWx1ZSA8IDAgJiYgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ciAhPT0gbnVsbCAmJiB0aGlzLnNldHRpbmdzLmlzTmVnYXRpdmVTaWduQWxsb3dlZCkgeyAvL0ZJWE1FIHRoaXMgaXMgY2FsbGVkIGEgc2Vjb25kIHRpbWUgaW4gX2FkZEdyb3VwU2VwYXJhdG9ycyB0b28uIFByZXZlbnQgdGhpcywgaWYgcG9zc2libGUuXG4gICAgICAgICAgICAgICAgLy8gT25seSByZW1vdmUgdGhlIGJyYWNrZXRzIGlmIHRoZSB2YWx1ZSBpcyBuZWdhdGl2ZVxuICAgICAgICAgICAgICAgIGVsZW1lbnRWYWx1ZVRvU2V0ID0gdGhpcy5jb25zdHJ1Y3Rvci5fcmVtb3ZlQnJhY2tldHMoQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCksIHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICAgICAgICAgIC8vRklYTUUgVGhlIGVsZW1lbnQgdmFsdWUgaXMgc2V0IGhlcmUsIHdoeSBjb250aW51ZSBhbmQgc2V0IGl0IGFnYWluIGxhdGVyIGluIHRoYXQgc2FtZSBwYXJlbnQgbG9naWMgYmxvY2s/XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFVzZSB0aGUgYHJhd1ZhbHVlYCwgbXVsdGlwbGllZCBieSBgcmF3VmFsdWVEaXZpc29yYCBpZiBkZWZpbmVkXG4gICAgICAgICAgICBjb25zdCByYXdWYWx1ZVRvRm9ybWF0ID0gdGhpcy5fZ2V0UmF3VmFsdWVUb0Zvcm1hdCh0aGlzLnJhd1ZhbHVlKTtcblxuICAgICAgICAgICAgLy8gTW9kaWZ5IHRoZSBlbGVtZW50IHZhbHVlIGFjY29yZGluZyB0byB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHRvIHNob3cgb24gZm9jdXMgb3IgdGhlIGBzaG93T25seU51bWJlcnNPbkZvY3VzYCBvcHRpb25cbiAgICAgICAgICAgIGlmIChyYXdWYWx1ZVRvRm9ybWF0ICE9PSAnJykge1xuICAgICAgICAgICAgICAgIC8vIFJvdW5kIHRoZSBnaXZlbiB2YWx1ZSBhY2NvcmRpbmcgdG8gdGhlIG9iamVjdCBzdGF0ZSAoZm9jdXMvdW5mb2N1c2VkKVxuICAgICAgICAgICAgICAgIGNvbnN0IHJvdW5kZWRWYWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX3JvdW5kRm9ybWF0dGVkVmFsdWVTaG93bk9uRm9jdXNPckJsdXIocmF3VmFsdWVUb0Zvcm1hdCwgdGhpcy5zZXR0aW5ncywgdGhpcy5pc0ZvY3VzZWQpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3Muc2hvd09ubHlOdW1iZXJzT25Gb2N1cyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5zaG93T25seU51bWJlcnNPbkZvY3VzLm9ubHlOdW1iZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vVE9ETyBVc2UgYSBgdGhpcy5zZXR0aW5nc092ZXJyaWRlYCBvYmplY3QgaW5zdGVhZCBvZiBtb2RpZnlpbmcgdGhlIGB0aGlzLnNldHRpbmdzYCBvYmplY3RcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5kaWdpdEdyb3VwU2VwYXJhdG9yID0gJyc7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wgICAgICA9ICcnO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLnN1ZmZpeFRleHQgICAgICAgICAgPSAnJztcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudFZhbHVlVG9TZXQgPSByb3VuZGVkVmFsdWUucmVwbGFjZSgnLicsIHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGZvcm1hdHRlZFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKHJvdW5kZWRWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1hdHRlZFZhbHVlID0gJyc7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JtYXR0ZWRWYWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX2FkZEdyb3VwU2VwYXJhdG9ycyhyb3VuZGVkVmFsdWUucmVwbGFjZSgnLicsIHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlciksIHRoaXMuc2V0dGluZ3MsIHRoaXMuaXNGb2N1c2VkLCByYXdWYWx1ZVRvRm9ybWF0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnRWYWx1ZVRvU2V0ID0gZm9ybWF0dGVkVmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBJbiBvcmRlciB0byBzZW5kIGEgJ25hdGl2ZScgY2hhbmdlIGV2ZW50IHdoZW4gYmx1cnJpbmcgdGhlIGlucHV0LCB3ZSBuZWVkIHRvIGZpcnN0IHN0b3JlIHRoZSBpbml0aWFsIGlucHV0IHZhbHVlIG9uIGZvY3VzLlxuICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChlbGVtZW50VmFsdWVUb1NldCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlT25Gb2N1cyA9ICcnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlT25Gb2N1cyA9IGVsZW1lbnRWYWx1ZVRvU2V0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmxhc3RWYWwgPSB0aGlzLnZhbHVlT25Gb2N1cztcbiAgICAgICAgICAgIGNvbnN0IGlzRW1wdHlWYWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX2lzRWxlbWVudFZhbHVlRW1wdHlPck9ubHlUaGVOZWdhdGl2ZVNpZ24odGhpcy52YWx1ZU9uRm9jdXMsIHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICAgICAgY29uc3Qgb3JkZXJlZFZhbHVlID0gdGhpcy5jb25zdHJ1Y3Rvci5fb3JkZXJWYWx1ZUN1cnJlbmN5U3ltYm9sQW5kU3VmZml4VGV4dCh0aGlzLnZhbHVlT25Gb2N1cywgdGhpcy5zZXR0aW5ncywgdHJ1ZSk7IC8vIFRoaXMgZGlzcGxheXMgdGhlIGN1cnJlbmN5IHNpZ24gb24gaG92ZXIgZXZlbiBpZiB0aGUgcmF3VmFsdWUgaXMgZW1wdHlcbiAgICAgICAgICAgIGNvbnN0IG9yZGVyZWRWYWx1ZVRlc3QgPSAoaXNFbXB0eVZhbHVlICYmIG9yZGVyZWRWYWx1ZSAhPT0gJycpICYmIHRoaXMuc2V0dGluZ3MuZW1wdHlJbnB1dEJlaGF2aW9yID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5mb2N1cztcbiAgICAgICAgICAgIGlmIChvcmRlcmVkVmFsdWVUZXN0KSB7XG4gICAgICAgICAgICAgICAgZWxlbWVudFZhbHVlVG9TZXQgPSBvcmRlcmVkVmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGVsZW1lbnRWYWx1ZVRvU2V0KSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3NldEVsZW1lbnRWYWx1ZShlbGVtZW50VmFsdWVUb1NldCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChvcmRlcmVkVmFsdWVUZXN0ICYmIG9yZGVyZWRWYWx1ZSA9PT0gdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbCAmJiB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeCkge1xuICAgICAgICAgICAgICAgIC8vIElmIHRoZXJlIGlzIGEgY3VycmVuY3kgc3ltYm9sIGFuZCBpdHMgb24gdGhlIHJpZ2h0IGhhbmQgc2lkZSwgdGhlbiB3ZSBwbGFjZSB0aGUgY2FyZXQgYWNjb3JkaW5nbHkgb24gdGhlIGZhciBsZWZ0IHNpZGVcbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5zZXRFbGVtZW50U2VsZWN0aW9uKGUudGFyZ2V0LCAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXIgZm9yIHRoZSAnZm9jdXMnIGV2ZW50LlxuICAgICAqIFdlIHVwZGF0ZSB0aGUgaW5mbyBvZiB0aGUgZm9jdXNlZCBzdGF0ZSBpbiB0aGUgYHRoaXMuaXNGb2N1c2VkYCB2YXJpYWJsZSB3aGVuIHRoZSBlbGVtZW50IGdldHMgZm9jdXNlZC5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9vbkZvY3VzKCkge1xuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5pc0NhbmNlbGxhYmxlKSB7XG4gICAgICAgICAgICAvLyBTYXZlIHRoZSBjdXJyZW50IHVuZm9ybWF0dGVkIHZhbHVlIGZvciBsYXRlciB1c2UgYnkgdGhlICdjYW5jZWxsYWJsZScgZmVhdHVyZVxuICAgICAgICAgICAgdGhpcy5fc2F2ZUNhbmNlbGxhYmxlVmFsdWUoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXIgZm9yIHRoZSAnZm9jdXNpbicgZXZlbnQuXG4gICAgICogVGhpcyBpcyBjYWxsZWQgYmVmb3JlIHRoZSAnZm9jdXMnIGV2ZW50LCBhbmQgaXMgbmVjZXNzYXJ5IHRvIGNoYW5nZSB0aGUgc2VsZWN0aW9uIG9uIGZvY3VzIHVuZGVyIEZpcmVmb3ggZm9yIGluc3RhbmNlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX29uRm9jdXNJbihlKSB7XG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLnNlbGVjdE9uRm9jdXMpIHtcbiAgICAgICAgICAgIC8vIFRoZSB3aG9sZSBpbnB1dCBjb250ZW50IGlzIHNlbGVjdGVkIG9uIGZvY3VzIChmb2xsb3dpbmcgdGhlIGBzZWxlY3RPbkZvY3VzYCBhbmQgYHNlbGVjdE51bWJlck9ubHlgIG9wdGlvbnMpXG4gICAgICAgICAgICAvL1hYWCBGaXJlZm94IDw0NyBkb2VzIG5vdCByZXNwZWN0IHRoaXMgc2VsZWN0aW9uLi4uT2ggd2VsbC5cbiAgICAgICAgICAgIHRoaXMuc2VsZWN0KCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBPciB3ZSBkZWNpZGUgd2hlcmUgdG8gcHV0IHRoZSBjYXJldCB1c2luZyB0aGUgYGNhcmV0UG9zaXRpb25PbkZvY3VzYCBvcHRpb25cbiAgICAgICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKHRoaXMuc2V0dGluZ3MuY2FyZXRQb3NpdGlvbk9uRm9jdXMpKSB7XG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFNlbGVjdGlvbihlLnRhcmdldCwgdGhpcy5faW5pdGlhbENhcmV0UG9zaXRpb24oQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXIgZm9yICdrZXlkb3duJyBldmVudHMuXG4gICAgICogVGhlIHVzZXIganVzdCBzdGFydGVkIHB1c2hpbmcgYW55IGtleSwgaGVuY2Ugb25lIGV2ZW50IGlzIHNlbnQuXG4gICAgICpcbiAgICAgKiBOb3RlIDpcbiAgICAgKiBCeSBkZWZhdWx0IGEgJ25vcm1hbCcgaW5wdXQgb3V0cHV0IHRob3NlIGV2ZW50cyBpbiB0aGUgcmlnaHQgb3JkZXIgd2hlbiBpbnB1dHRpbmcgYSBjaGFyYWN0ZXIga2V5IChpZS4gJ2EnKSA6XG4gICAgICogLSBrZXlkb3duXG4gICAgICogLSBrZXlwcmVzc1xuICAgICAqIC0gaW5wdXRcbiAgICAgKiAtIGtleXVwXG4gICAgICpcbiAgICAgKiAuLi53aGVuIGlucHV0dGluZyBhIG1vZGlmaWVyIGtleSAoaWUuICdjdHJsJykgOlxuICAgICAqIC0ga2V5ZG93blxuICAgICAqIC0ga2V5dXBcbiAgICAgKlxuICAgICAqIElmICdkZWxldGUnIG9yICdiYWNrc3BhY2UnIGlzIGVudGVyZWQsIHRoZSBmb2xsb3dpbmcgZXZlbnRzIGFyZSBzZW50IDpcbiAgICAgKiAtIGtleWRvd25cbiAgICAgKiAtIGlucHV0XG4gICAgICogLSBrZXl1cFxuICAgICAqXG4gICAgICogSWYgJ2VudGVyJyBpcyBlbnRlcmVkIGFuZCB0aGUgdmFsdWUgaGFzIG5vdCBjaGFuZ2VkLCB0aGUgZm9sbG93aW5nIGV2ZW50cyBhcmUgc2VudCA6XG4gICAgICogLSBrZXlkb3duXG4gICAgICogLSBrZXlwcmVzc1xuICAgICAqIC0ga2V5dXBcbiAgICAgKlxuICAgICAqIElmICdlbnRlcicgaXMgZW50ZXJlZCBhbmQgdGhlIHZhbHVlIGhhcyBiZWVuIGNoYW5nZWQsIHRoZSBmb2xsb3dpbmcgZXZlbnRzIGFyZSBzZW50IDpcbiAgICAgKiAtIGtleWRvd25cbiAgICAgKiAtIGtleXByZXNzXG4gICAgICogLSBjaGFuZ2VcbiAgICAgKiAtIGtleXVwXG4gICAgICpcbiAgICAgKiBXaGVuIGEgcGFzdGUgaXMgZG9uZSwgdGhlIGZvbGxvd2luZyBldmVudHMgYXJlIHNlbnQgOlxuICAgICAqIC0gaW5wdXQgKGlmIHBhc3RlIGlzIGRvbmUgd2l0aCB0aGUgbW91c2UpXG4gICAgICpcbiAgICAgKiAtIGtleWRvd24gKGlmIHBhc3RlIGlzIGRvbmUgd2l0aCBjdHJsK3YpXG4gICAgICogLSBrZXlkb3duXG4gICAgICogLSBpbnB1dFxuICAgICAqIC0ga2V5dXBcbiAgICAgKiAtIGtleXVwXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0tleWJvYXJkRXZlbnR9IGVcbiAgICAgKi9cbiAgICBfb25LZXlkb3duKGUpIHtcbiAgICAgICAgdGhpcy5mb3JtYXR0ZWQgPSBmYWxzZTsgLy8gS2VlcCB0cmFjayBpZiB0aGUgZWxlbWVudCBoYXMgYmVlbiBmb3JtYXR0ZWQgYWxyZWFkeS4gSWYgdGhhdCdzIHRoZSBjYXNlLCBwcmV2ZW50IGZ1cnRoZXIgZm9ybWF0IGNhbGN1bGF0aW9ucy5cbiAgICAgICAgdGhpcy5pc0VkaXRpbmcgPSB0cnVlOyAvLyBLZWVwIHRyYWNrIGlmIHRoZSB1c2VyIGlzIGN1cnJlbnRseSBlZGl0aW5nIHRoZSBlbGVtZW50IG1hbnVhbGx5XG5cbiAgICAgICAgaWYgKCF0aGlzLmlzRm9jdXNlZCAmJiB0aGlzLnNldHRpbmdzLnVuZm9ybWF0T25Ib3ZlciAmJiBlLmFsdEtleSAmJiB0aGlzLmRvbUVsZW1lbnQgPT09IEF1dG9OdW1lcmljSGVscGVyLmdldEhvdmVyZWRFbGVtZW50KCkpIHtcbiAgICAgICAgICAgIC8vIEhlcmUgSSBwcmV2ZW50IGNhbGxpbmcgX3VuZm9ybWF0QWx0SG92ZXJlZCBpZiB0aGUgZWxlbWVudCBpcyBhbHJlYWR5IGZvY3VzZWQsIHNpbmNlIHRoZSBnbG9iYWwgJ2tleWRvd24nIGxpc3RlbmVyIHdpbGwgcGljayBpdCB1cCBhcyB3ZWxsXG4gICAgICAgICAgICB0aGlzLmNvbnN0cnVjdG9yLl91bmZvcm1hdEFsdEhvdmVyZWQodGhpcyk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX3VwZGF0ZUV2ZW50S2V5SW5mbyhlKTtcbiAgICAgICAgdGhpcy5pbml0aWFsVmFsdWVPbktleWRvd24gPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUoZS50YXJnZXQpOyAvLyBUaGlzIGlzIG5lZWRlZCBpbiBgb25LZXl1cCgpYCB0byBjaGVjayBpZiB0aGUgdmFsdWUgYXMgY2hhbmdlZCBkdXJpbmcgdGhlIGtleSBwcmVzc1xuICAgICAgICB0aGlzLmluaXRpYWxSYXdWYWx1ZU9uS2V5ZG93biA9IHRoaXMucmF3VmFsdWU7XG5cbiAgICAgICAgaWYgKHRoaXMuZG9tRWxlbWVudC5yZWFkT25seSkge1xuICAgICAgICAgICAgdGhpcy5wcm9jZXNzZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuRXNjKSB7XG4gICAgICAgICAgICAvL1hYWCBUaGUgZGVmYXVsdCAnRXNjYXBlJyBrZXkgYmVoYXZpb3IgZGlmZmVycyBiZXR3ZWVuIEZpcmVmb3ggYW5kIENocm9tZSwgRmlyZWZveCBhbHJlYWR5IGhhdmluZyBhIGJ1aWx0LWluICdjYW5jZWxsYWJsZS1saWtlJyBmZWF0dXJlLiBUaGlzIGlzIHdoeSB3ZSBjYWxsIGBlLnByZXZlbnREZWZhdWx0KClgIGhlcmUgaW5zdGVhZCBvZiBqdXN0IHdoZW4gYGlzQ2FuY2VsbGFibGVgIGlzIHNldCB0byBgdHJ1ZWAuIFRoaXMgYWxsb3cgdXMgdG8ga2VlcCB0aGUgc2FtZSBiZWhhdmlvciBhY3Jvc3MgYnJvd3NlcnMuXG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmlzQ2FuY2VsbGFibGUpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgdXNlciB3YW50cyB0byBjYW5jZWwgaGlzIG1vZGlmaWNhdGlvbnM6XG4gICAgICAgICAgICAgICAgLy8gV2Ugc2V0IGJhY2sgdGhlIHNhdmVkIHZhbHVlXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucmF3VmFsdWUgIT09IHRoaXMuc2F2ZWRDYW5jZWxsYWJsZVZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIERvIG5vdCBzZXQgdGhlIHZhbHVlIGFnYWluIGlmIGl0IGhhcyBub3QgY2hhbmdlZFxuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldCh0aGlzLnNhdmVkQ2FuY2VsbGFibGVWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIC8vIEFuZCB3ZSBuZWVkIHRvIHNlbmQgYW4gJ2lucHV0JyBldmVudCB3aGVuIHNldHRpbmcgYmFjayB0aGUgaW5pdGlhbCB2YWx1ZSBpbiBvcmRlciB0byBtYWtlIG90aGVyIHNjcmlwdHMgYXdhcmUgb2YgdGhlIHZhbHVlIGNoYW5nZS4uLlxuICAgICAgICAgICAgICAgICAgICB0aGlzLl90cmlnZ2VyRXZlbnQoQXV0b051bWVyaWMuZXZlbnRzLm5hdGl2ZS5pbnB1dCwgZS50YXJnZXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gLi5hbmQgbGFzdGx5IHdlIHVwZGF0ZSB0aGUgY2FyZXQgc2VsZWN0aW9uLCBldmVuIGlmIHRoZSBvcHRpb24gYGlzQ2FuY2VsbGFibGVgIGlzIGZhbHNlXG4gICAgICAgICAgICB0aGlzLnNlbGVjdCgpO1xuICAgICAgICAgICAgLy9UT0RPIEFkZCBhbiBvcHRpb24gdG8gc2VsZWN0IGVpdGhlciB0aGUgaW50ZWdlciBvciBkZWNpbWFsIHBhcnQgd2l0aCBgRXNjYFxuICAgICAgICB9XG5cbiAgICAgICAgLy8gVGhlIFwiZW50ZXJcIiBrZXkgdGhyb3dzIGEgYGNoYW5nZWAgZXZlbnQgaWYgdGhlIHJhdyB2YWx1ZSBoYXMgY2hhbmdlZCBzaW5jZSB0aGUgYGZvY3VzYCBldmVudFxuICAgICAgICBsZXQgdGFyZ2V0VmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUoZS50YXJnZXQpO1xuICAgICAgICBpZiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuRW50ZXIgJiYgdGhpcy5yYXdWYWx1ZSAhPT0gdGhpcy5yYXdWYWx1ZU9uRm9jdXMpIHtcbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMubmF0aXZlLmNoYW5nZSwgZS50YXJnZXQpO1xuICAgICAgICAgICAgdGhpcy52YWx1ZU9uRm9jdXMgPSB0YXJnZXRWYWx1ZTtcbiAgICAgICAgICAgIHRoaXMucmF3VmFsdWVPbkZvY3VzID0gdGhpcy5yYXdWYWx1ZTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuaXNDYW5jZWxsYWJsZSkge1xuICAgICAgICAgICAgICAgIC8vIElmIHRoZSB1c2VyIGFjdGl2YXRlZCB0aGUgJ2NhbmNlbGxhYmxlJyBmZWF0dXJlLCB3ZSBzYXZlIHRoZSB2YWxpZGF0ZWQgdmFsdWUgd2hlbiAnRW50ZXInIGlzIGhpdFxuICAgICAgICAgICAgICAgIHRoaXMuX3NhdmVDYW5jZWxsYWJsZVZhbHVlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl91cGRhdGVJbnRlcm5hbFByb3BlcnRpZXMoZSk7XG5cbiAgICAgICAgaWYgKHRoaXMuX3Byb2Nlc3NOb25QcmludGFibGVLZXlzQW5kU2hvcnRjdXRzKGUpKSB7XG4gICAgICAgICAgICB0aGlzLnByb2Nlc3NlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENoZWNrIGlmIHRoZSBrZXkgaXMgYSBkZWxldGUvYmFja3NwYWNlIGtleVxuICAgICAgICBpZiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuQmFja3NwYWNlIHx8IHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkRlbGV0ZSkge1xuICAgICAgICAgICAgdGhpcy5fcHJvY2Vzc0NoYXJhY3RlckRlbGV0aW9uKCk7IC8vIEJlY2F1c2UgYmFja3NwYWNlIGFuZCBkZWxldGUgb25seSB0cmlnZ2VycyBrZXlkb3duIGFuZCBrZXl1cCBldmVudHMsIG5vdCBrZXlwcmVzc1xuICAgICAgICAgICAgdGhpcy5wcm9jZXNzZWQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5fZm9ybWF0VmFsdWUoZSk7XG5cbiAgICAgICAgICAgIC8vIElmIGFuZCBvbmx5IGlmIHRoZSByZXN1bHRpbmcgdmFsdWUgaGFzIGNoYW5nZWQgYWZ0ZXIgdGhhdCBiYWNrc3BhY2UvZGVsZXRlLCB0aGVuIHdlIGhhdmUgdG8gc2VuZCBhbiAnaW5wdXQnIGV2ZW50IGxpa2UgYnJvd3NlcnMgbm9ybWFsbHkgZG8uXG4gICAgICAgICAgICB0YXJnZXRWYWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZShlLnRhcmdldCk7IC8vIFVwZGF0ZSB0aGUgdmFsdWUgc2luY2UgaXQgY291bGQgaGF2ZSBiZWVuIGNoYW5nZWQgZHVyaW5nIHRoZSBkZWxldGlvblxuICAgICAgICAgICAgaWYgKCh0YXJnZXRWYWx1ZSAhPT0gdGhpcy5sYXN0VmFsKSAmJiB0aGlzLnRocm93SW5wdXQpIHtcbiAgICAgICAgICAgICAgICAvLyBUaHJvdyBhbiBpbnB1dCBldmVudCB3aGVuIGEgY2hhcmFjdGVyIGRlbGV0aW9uIGlzIGRldGVjdGVkXG4gICAgICAgICAgICAgICAgdGhpcy5fdHJpZ2dlckV2ZW50KEF1dG9OdW1lcmljLmV2ZW50cy5uYXRpdmUuaW5wdXQsIGUudGFyZ2V0KTtcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7IC8vIC4uLmFuZCBpbW1lZGlhdGVseSBwcmV2ZW50IHRoZSBicm93c2VyIHRvIGRlbGV0ZSBhIHNlY29uZCBjaGFyYWN0ZXJcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5sYXN0VmFsID0gdGFyZ2V0VmFsdWU7XG4gICAgICAgICAgICB0aGlzLnRocm93SW5wdXQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlciBmb3IgJ2tleXByZXNzJyBldmVudHMuXG4gICAgICogVGhlIHVzZXIgaXMgc3RpbGwgcHJlc3NpbmcgdGhlIGtleSwgd2hpY2ggd2lsbCBvdXRwdXQgYSBjaGFyYWN0ZXIgKGllLiAnMicpIGNvbnRpbnVvdXNseSB1bnRpbCBoZSByZWxlYXNlcyB0aGUga2V5LlxuICAgICAqIE5vdGU6ICdrZXlwcmVzcycgZXZlbnRzIGFyZSBub3Qgc2VudCBmb3IgZGVsZXRlIGtleXMgbGlrZSBCYWNrc3BhY2UvRGVsZXRlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtLZXlib2FyZEV2ZW50fSBlXG4gICAgICovXG4gICAgX29uS2V5cHJlc3MoZSkge1xuICAgICAgICBpZiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuSW5zZXJ0KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwcm9jZXNzZWQgPSB0aGlzLnByb2Nlc3NlZDtcbiAgICAgICAgdGhpcy5fdXBkYXRlSW50ZXJuYWxQcm9wZXJ0aWVzKGUpO1xuXG4gICAgICAgIGlmICh0aGlzLl9wcm9jZXNzTm9uUHJpbnRhYmxlS2V5c0FuZFNob3J0Y3V0cyhlKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHByb2Nlc3NlZCkge1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBpc0NoYXJhY3Rlckluc2VydGlvbkFsbG93ZWQgPSB0aGlzLl9wcm9jZXNzQ2hhcmFjdGVySW5zZXJ0aW9uKCk7XG4gICAgICAgIGlmIChpc0NoYXJhY3Rlckluc2VydGlvbkFsbG93ZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX2Zvcm1hdFZhbHVlKGUpO1xuICAgICAgICAgICAgY29uc3QgdGFyZ2V0VmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUoZS50YXJnZXQpO1xuICAgICAgICAgICAgaWYgKCh0YXJnZXRWYWx1ZSAhPT0gdGhpcy5sYXN0VmFsKSAmJiB0aGlzLnRocm93SW5wdXQpIHtcbiAgICAgICAgICAgICAgICAvLyBUaHJvd3MgaW5wdXQgZXZlbnQgb24gYWRkaW5nIGEgY2hhcmFjdGVyXG4gICAgICAgICAgICAgICAgdGhpcy5fdHJpZ2dlckV2ZW50KEF1dG9OdW1lcmljLmV2ZW50cy5uYXRpdmUuaW5wdXQsIGUudGFyZ2V0KTtcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7IC8vIC4uLmFuZCBpbW1lZGlhdGVseSBwcmV2ZW50IHRoZSBicm93c2VyIHRvIGFkZCBhIHNlY29uZCBjaGFyYWN0ZXJcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKCh0aGlzLmV2ZW50S2V5ID09PSB0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIgfHwgdGhpcy5ldmVudEtleSA9PT0gdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUpICYmXG4gICAgICAgICAgICAgICAgICAgIChBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50U2VsZWN0aW9uKGUudGFyZ2V0KS5zdGFydCA9PT0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFNlbGVjdGlvbihlLnRhcmdldCkuZW5kKSAmJlxuICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50U2VsZWN0aW9uKGUudGFyZ2V0KS5zdGFydCA9PT0gdGFyZ2V0VmFsdWUuaW5kZXhPZih0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFNlbGVjdGlvbihlLnRhcmdldCkuc3RhcnQgKyAxO1xuICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5zZXRFbGVtZW50U2VsZWN0aW9uKGUudGFyZ2V0LCBwb3NpdGlvbik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmxhc3RWYWwgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUoZS50YXJnZXQpO1xuICAgICAgICAgICAgdGhpcy50aHJvd0lucHV0ID0gdHJ1ZTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXIgZm9yICdrZXl1cCcgZXZlbnRzLlxuICAgICAqIFRoZSB1c2VyIGp1c3QgcmVsZWFzZWQgYW55IGtleSwgaGVuY2Ugb25lIGV2ZW50IGlzIHNlbnQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0tleWJvYXJkRXZlbnR9IGVcbiAgICAgKi9cbiAgICBfb25LZXl1cChlKSB7XG4gICAgICAgIHRoaXMuaXNFZGl0aW5nID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuaXNDYW5jZWxsYWJsZSAmJiB0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5Fc2MpIHtcbiAgICAgICAgICAgIC8vIElmIHRoZSB1c2VyIHdhbnRzIHRvIGNhbmNlbCBpdHMgbW9kaWZpY2F0aW9ucywgd2UgZHJvcCB0aGUgJ2tleXVwJyBldmVudCBmb3IgdGhlIEVzYyBrZXlcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTWFuYWdlIHRoZSB1bmRvL3JlZG8gZXZlbnRzXG4gICAgICAgIGlmICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5aIHx8IHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLnopIHtcbiAgICAgICAgICAgIGlmIChlLmN0cmxLZXkgJiYgZS5zaGlmdEtleSkge1xuICAgICAgICAgICAgICAgIC8vIFJlZG9cbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5faGlzdG9yeVRhYmxlUmVkbygpO1xuICAgICAgICAgICAgICAgIHRoaXMub25Hb2luZ1JlZG8gPSB0cnVlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChlLmN0cmxLZXkgJiYgIWUuc2hpZnRLZXkpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5vbkdvaW5nUmVkbykge1xuICAgICAgICAgICAgICAgICAgICAvLyBQcmV2ZW50IGFuICd1bmRvJyB0byBiZSBsYXVuY2ggd2hlbiByZWxlYXNpbmcgdGhlIHNoaWZ0IGtleSBiZWZvcmUgdGhlIGN0cmwga2V5IGFmdGVyIGEgJ3JlZG8nIHNob3J0Y3V0XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25Hb2luZ1JlZG8gPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIC8vIFVuZG9cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5faGlzdG9yeVRhYmxlVW5kbygpO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5vbkdvaW5nUmVkbyAmJiAoZS5jdHJsS2V5IHx8IGUuc2hpZnRLZXkpKSB7XG4gICAgICAgICAgICAvLyBTcGVjaWFsIGNhc2Ugd2hlcmUgaWYgdGhlIHVzZXIgaGFzIGVudGVyZWQgYENvbnRyb2wrU2hpZnQremAsIHRoZW4gcmVsZWFzZSBgemAsIGtlZXBpbmcgYENvbnRyb2xgIG9yIGBTaGlmdGAgcHJlc3NlZCwgdGhlbiBgdGhpcy5vbkdvaW5nUmVkb2AgaXMgbmV2ZXIgY2hhbmdlZCBiYWNrIHRvIGBmYWxzZWAgd2hlbiB0aGUgdXNlciByZWxlYXNlIGBDb250cm9sYCBvciBgU2hpZnRgXG4gICAgICAgICAgICB0aGlzLm9uR29pbmdSZWRvID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBNYW5hZ2UgdGhlIEN1dCBldmVudFxuICAgICAgICBpZiAoKGUuY3RybEtleSB8fCBlLm1ldGFLZXkpICYmIHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLngpIHtcbiAgICAgICAgICAgIC8vIFNhdmUgdGhlIGNhcmV0IHBvc2l0aW9uIGF0IHRoZSBzdGFydCBvZiB0aGUgc2VsZWN0aW9uXG4gICAgICAgICAgICBjb25zdCBjYXJldFBvc2l0aW9uID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFNlbGVjdGlvbih0aGlzLmRvbUVsZW1lbnQpLnN0YXJ0O1xuICAgICAgICAgICAgLy8gQ29udmVydCB0aGUgcmVtYWluaW5nICdmb3JtYXR0ZWQnIG51bWJlcnMgaW4gYSBKcyBudW1iZXJcbiAgICAgICAgICAgIGNvbnN0IGN1dE51bWJlciA9IHRoaXMuY29uc3RydWN0b3IuX3RvTnVtZXJpY1ZhbHVlKEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZShlLnRhcmdldCksIHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICAgICAgLy8gVHJ5IHRvIHNldCB0aGF0IHZhbHVlIHdpdGggYHNldCgpYFxuICAgICAgICAgICAgdGhpcy5zZXQoY3V0TnVtYmVyKTtcbiAgICAgICAgICAgIC8vIFNldCBiYWNrIHRoZSBpbml0aWFsIGNhcmV0IHBvc2l0aW9uXG4gICAgICAgICAgICB0aGlzLl9zZXRDYXJldFBvc2l0aW9uKGNhcmV0UG9zaXRpb24pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTWFuYWdlIHRoZSByZWZvcm1hdCB3aGVuIGhvdmVyZWQgd2l0aCB0aGUgQWx0IGtleSBwcmVzc2VkXG4gICAgICAgIGlmICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5BbHQgJiYgdGhpcy5ob3ZlcmVkV2l0aEFsdCkge1xuICAgICAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5fcmVmb3JtYXRBbHRIb3ZlcmVkKHRoaXMpO1xuXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl91cGRhdGVJbnRlcm5hbFByb3BlcnRpZXMoZSk7XG5cbiAgICAgICAgY29uc3Qgc2tpcCA9IHRoaXMuX3Byb2Nlc3NOb25QcmludGFibGVLZXlzQW5kU2hvcnRjdXRzKGUpO1xuICAgICAgICBkZWxldGUgdGhpcy52YWx1ZVBhcnRzQmVmb3JlUGFzdGU7XG4gICAgICAgIGNvbnN0IHRhcmdldFZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKGUudGFyZ2V0KTtcbiAgICAgICAgaWYgKHNraXAgfHwgdGFyZ2V0VmFsdWUgPT09ICcnKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGRlZCB0byBwcm9wZXJseSBwbGFjZSB0aGUgY2FyZXQgd2hlbiBvbmx5IHRoZSBjdXJyZW5jeSBzaWduIGlzIHByZXNlbnRcbiAgICAgICAgaWYgKHRhcmdldFZhbHVlID09PSB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5zdWZmaXgpIHtcbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5zZXRFbGVtZW50U2VsZWN0aW9uKGUudGFyZ2V0LCAwKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFNlbGVjdGlvbihlLnRhcmdldCwgdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbC5sZW5ndGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLlRhYikge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFNlbGVjdGlvbihlLnRhcmdldCwgMCwgdGFyZ2V0VmFsdWUubGVuZ3RoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgodGFyZ2V0VmFsdWUgPT09IHRoaXMuc2V0dGluZ3Muc3VmZml4VGV4dCkgfHxcbiAgICAgICAgICAgICh0aGlzLnJhd1ZhbHVlID09PSAnJyAmJiB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sICE9PSAnJyAmJiB0aGlzLnNldHRpbmdzLnN1ZmZpeFRleHQgIT09ICcnKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFNlbGVjdGlvbihlLnRhcmdldCwgMCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTYXZlcyB0aGUgZXh0ZW5kZWQgZGVjaW1hbCB0byBwcmVzZXJ2ZSB0aGUgZGF0YSB3aGVuIG5hdmlnYXRpbmcgYXdheSBmcm9tIHRoZSBwYWdlXG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuX3NhdmVWYWx1ZVRvUGVyc2lzdGVudFN0b3JhZ2UoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5mb3JtYXR0ZWQpIHsgIC8vVE9ETyBJcyB0aGlzIGxpbmUgbmVlZGVkPyBDb25zaWRlcmluZyB0aGF0IG9uS2V5ZG93biBhbmQgb25LZXlwcmVzcyBib3RoIGZpbmlzaCBieSBzZXR0aW5nIGl0IHRvIGZhbHNlLi4uXG4gICAgICAgICAgICB0aGlzLl9mb3JtYXRWYWx1ZShlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEZvcmNlIHRoZSBgcmF3VmFsdWVgIHVwZGF0ZSBvbiBBbmRyb2lkIENocm9tZVxuICAgICAgICB0aGlzLl9zYXZlUmF3VmFsdWVGb3JBbmRyb2lkKCk7XG5cbiAgICAgICAgLy8gSWYgdGhlIGlucHV0IHZhbHVlIGhhcyBjaGFuZ2VkIGR1cmluZyB0aGUga2V5IHByZXNzIGV2ZW50IGNoYWluLCBhbiBldmVudCBpcyBzZW50IHRvIGFsZXJ0IHRoYXQgYSBmb3JtYXR0aW5nIGhhcyBiZWVuIGRvbmUgKGNmLiBJc3N1ZSAjMTg3KVxuICAgICAgICBpZiAodGFyZ2V0VmFsdWUgIT09IHRoaXMuaW5pdGlhbFZhbHVlT25LZXlkb3duKSB7XG4gICAgICAgICAgICB0aGlzLl90cmlnZ2VyRXZlbnQoQXV0b051bWVyaWMuZXZlbnRzLmZvcm1hdHRlZCwgZS50YXJnZXQsIHtcbiAgICAgICAgICAgICAgICBvbGRWYWx1ZSAgIDogdGhpcy5pbml0aWFsVmFsdWVPbktleWRvd24sXG4gICAgICAgICAgICAgICAgbmV3VmFsdWUgICA6IHRhcmdldFZhbHVlLFxuICAgICAgICAgICAgICAgIG9sZFJhd1ZhbHVlOiB0aGlzLmluaXRpYWxSYXdWYWx1ZU9uS2V5ZG93bixcbiAgICAgICAgICAgICAgICBuZXdSYXdWYWx1ZTogdGhpcy5yYXdWYWx1ZSxcbiAgICAgICAgICAgICAgICBpc1ByaXN0aW5lIDogdGhpcy5pc1ByaXN0aW5lKGZhbHNlKSxcbiAgICAgICAgICAgICAgICBlcnJvciAgICAgIDogbnVsbCxcbiAgICAgICAgICAgICAgICBhTkVsZW1lbnQgIDogdGhpcyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXBkYXRlIHRoZSBzZWxlY3Rpb24gb2YgdGhlIGN1cnJlbnQgZWxlbWVudCBvZiB0aGUgaGlzdG9yeSB0YWJsZVxuICAgICAgICBpZiAodGhpcy5oaXN0b3J5VGFibGUubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgY29uc3Qgc2VsZWN0aW9uID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFNlbGVjdGlvbih0aGlzLmRvbUVsZW1lbnQpO1xuICAgICAgICAgICAgdGhpcy5zZWxlY3Rpb25TdGFydCA9IHNlbGVjdGlvbi5zdGFydDtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0aW9uRW5kID0gc2VsZWN0aW9uLmVuZDtcbiAgICAgICAgICAgIHRoaXMuaGlzdG9yeVRhYmxlW3RoaXMuaGlzdG9yeVRhYmxlSW5kZXhdLnN0YXJ0ID0gdGhpcy5zZWxlY3Rpb25TdGFydDtcbiAgICAgICAgICAgIHRoaXMuaGlzdG9yeVRhYmxlW3RoaXMuaGlzdG9yeVRhYmxlSW5kZXhdLmVuZCA9IHRoaXMuc2VsZWN0aW9uRW5kO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT24gQW5kcm9pZCBDaHJvbWUsIHRoZSBgcmF3VmFsdWVgIGlzIG5vdCB1cGRhdGVkIHdoZW4gdGhlIHVzZXIgY2hhbmdlcyB0aGUgaW5wdXQgdmFsdWUuXG4gICAgICogVGhpcyBmdW5jdGlvbiB1cGRhdGVzIHRoZSBgcmF3VmFsdWVgIGFjY29yZGluZ2x5LlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3NhdmVSYXdWYWx1ZUZvckFuZHJvaWQoKSB7XG4gICAgICAgIGlmICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5BbmRyb2lkRGVmYXVsdCkge1xuICAgICAgICAgICAgbGV0IG5vcm1hbGl6ZWRWYWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX3N0cmlwQWxsTm9uTnVtYmVyQ2hhcmFjdGVyc0V4Y2VwdEN1c3RvbURlY2ltYWxDaGFyKHRoaXMuZ2V0Rm9ybWF0dGVkKCksIHRoaXMuc2V0dGluZ3MsIHRydWUsIHRoaXMuaXNGb2N1c2VkKTtcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRWYWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX2NvbnZlcnRUb051bWVyaWNTdHJpbmcobm9ybWFsaXplZFZhbHVlLCB0aGlzLnNldHRpbmdzKTtcblxuICAgICAgICAgICAgdGhpcy5fc2V0UmF3VmFsdWUobm9ybWFsaXplZFZhbHVlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXIgZm9yICdmb2N1c291dCcgZXZlbnRzXG4gICAgICogT24gZm9jdXNvdXQsIG11bHRpcGxlIHRoaW5ncyBoYXBwZW5zIDpcbiAgICAgKiAtIFRoZSBlbGVtZW50IHZhbHVlIGlzIGZvcm1hdHRlZCBiYWNrIGlmIHRoZSBgQWx0YCBrZXkgd2FzIHByZXNzZWQsXG4gICAgICogLSBUaGUgZWxlbWVudCB2YWx1ZSBpcyBmb3JtYXR0ZWQgYmFjayBpZiBgc2hvd09ubHlOdW1iZXJzT25Gb2N1c2Agd2FzIHNldCB0byBvbmx5IHNob3cgbnVtYmVycyxcbiAgICAgKiAtIFRoZSBlbGVtZW50IHZhbHVlIGlzIG11bHRpcGxpZWQgYnkgYHJhd1ZhbHVlRGl2aXNvcmAgb24gYGJsdXJgXG4gICAgICpcbiAgICAgKiBOb3RlOiBPbiBmb2N1c291dCwgdGhlIGByYXdWYWx1ZWAgaXMgbmV2ZXIgY2hhbmdlZC4gT25seSB0aGUgZm9ybWF0dGVkIHZhbHVlIGNhbiBiZSBtb2RpZmllZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKi9cbiAgICBfb25Gb2N1c091dEFuZE1vdXNlTGVhdmUoZSkge1xuICAgICAgICAvL1RPRE8gQ3JlYXRlIHNlcGFyYXRlIGhhbmRsZXJzIGZvciBibHVyIGFuZCBtb3VzZWxlYXZlXG4gICAgICAgIHRoaXMuaXNFZGl0aW5nID0gZmFsc2U7IC8vIEp1c3QgaW4gY2FzZSBubyBga2V5VXBgIGV2ZW50IGhhdmUgYmVlbiBzZW50IChpZiB0aGUgdXNlciBsb3N0IHRoZSBmb2N1cyB0byB0aGUgd2luZG93IHdoaWxlIHR5cGluZylcblxuICAgICAgICAvL0ZJWE1FIERvIG5vdCBjYWxsIGBzZXQoKWAgaWYgdGhlIGN1cnJlbnQgcmF3IHZhbHVlIGlzIHRoZSBzYW1lIGFzIHRoZSBvbmUgd2UgYXJlIHRyeWluZyB0byBzZXQgKGN1cnJlbnRseSwgb24gZm9jdXMgb3V0LCBgc2V0KClgIGlzIGFsd2F5cyBjYWxsZWQsIGV2ZW4gaWYgdGhlIHZhbHVlIGhhcyBub3QgY2hhbmdlZFxuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy51bmZvcm1hdE9uSG92ZXIgJiYgZS50eXBlID09PSAnbW91c2VsZWF2ZScgJiYgdGhpcy5ob3ZlcmVkV2l0aEFsdCkge1xuICAgICAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5fcmVmb3JtYXRBbHRIb3ZlcmVkKHRoaXMpO1xuXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoKGUudHlwZSA9PT0gJ21vdXNlbGVhdmUnICYmICF0aGlzLmlzRm9jdXNlZCkgfHwgZS50eXBlID09PSAnYmx1cicpIHtcbiAgICAgICAgICAgIHRoaXMuX3NhdmVWYWx1ZVRvUGVyc2lzdGVudFN0b3JhZ2UoKTtcbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLnNob3dPbmx5TnVtYmVyc09uRm9jdXMgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuc2hvd09ubHlOdW1iZXJzT25Gb2N1cy5vbmx5TnVtYmVycykge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuZGlnaXRHcm91cFNlcGFyYXRvciA9IHRoaXMub3JpZ2luYWxEaWdpdEdyb3VwU2VwYXJhdG9yO1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wgPSB0aGlzLm9yaWdpbmFsQ3VycmVuY3lTeW1ib2w7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5zdWZmaXhUZXh0ID0gdGhpcy5vcmlnaW5hbFN1ZmZpeFRleHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFVzZSB0aGUgcmF3VmFsdWUsIG11bHRpcGxpZWQgYnkgYHJhd1ZhbHVlRGl2aXNvcmAgaWYgZGVmaW5lZFxuICAgICAgICAgICAgY29uc3QgcmF3VmFsdWVUb0Zvcm1hdCA9IHRoaXMuX2dldFJhd1ZhbHVlVG9Gb3JtYXQodGhpcy5yYXdWYWx1ZSk7XG4gICAgICAgICAgICBjb25zdCBpc1Jhd1ZhbHVlTnVsbCA9IEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChyYXdWYWx1ZVRvRm9ybWF0KTtcbiAgICAgICAgICAgIGNvbnN0IFttaW5UZXN0LCBtYXhUZXN0XSA9IHRoaXMuY29uc3RydWN0b3IuX2NoZWNrSWZJblJhbmdlV2l0aE92ZXJyaWRlT3B0aW9uKHJhd1ZhbHVlVG9Gb3JtYXQsIHRoaXMuc2V0dGluZ3MpO1xuXG4gICAgICAgICAgICAvLyBEaXJlY3RseSBzZXQgdGhlIGZvcm1hdHRlZCB2YWx1ZSBpZiB0aGUgYHJhd1ZhbHVlYCBpcyBmb3VuZCBpbiBgdmFsdWVzVG9TdHJpbmdzYFxuICAgICAgICAgICAgbGV0IGVsZW1lbnRWYWx1ZUlzQWxyZWFkeVNldCA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKHJhd1ZhbHVlVG9Gb3JtYXQgIT09ICcnICYmICFpc1Jhd1ZhbHVlTnVsbCkge1xuICAgICAgICAgICAgICAgIGlmICghbWluVGVzdCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl90cmlnZ2VyRXZlbnQoQXV0b051bWVyaWMuZXZlbnRzLm1pblJhbmdlRXhjZWVkZWQsIHRoaXMuZG9tRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFtYXhUZXN0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMubWF4UmFuZ2VFeGNlZWRlZCwgdGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy52YWx1ZXNUb1N0cmluZ3MgJiYgdGhpcy5fY2hlY2tWYWx1ZXNUb1N0cmluZ3MocmF3VmFsdWVUb0Zvcm1hdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gU2V0IHRoZSBmb3JtYXR0ZWQgdmFsdWUgd2l0aCB0aGUgY29ycmVzcG9uZGluZyBzdHJpbmdcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0RWxlbWVudFZhbHVlKHRoaXMuc2V0dGluZ3MudmFsdWVzVG9TdHJpbmdzW3Jhd1ZhbHVlVG9Gb3JtYXRdKTtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudFZhbHVlSXNBbHJlYWR5U2V0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIE9ubHkgZ2VuZXJhdGUgdGhlIGZvcm1hdHRlZCB2YWx1ZSBpZiBubyBgdmFsdWVzVG9TdHJpbmdzYCBoYXZlIGJlZW4gZm91bmRcbiAgICAgICAgICAgIGlmICghZWxlbWVudFZhbHVlSXNBbHJlYWR5U2V0KSB7XG4gICAgICAgICAgICAgICAgbGV0IHZhbHVlO1xuICAgICAgICAgICAgICAgIGlmIChpc1Jhd1ZhbHVlTnVsbCB8fCByYXdWYWx1ZVRvRm9ybWF0ID09PSAnJykge1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHJhd1ZhbHVlVG9Gb3JtYXQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBTdHJpbmcocmF3VmFsdWVUb0Zvcm1hdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHJhd1ZhbHVlVG9Gb3JtYXQgIT09ICcnICYmICFpc1Jhd1ZhbHVlTnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAobWluVGVzdCAmJiBtYXhUZXN0ICYmICF0aGlzLmNvbnN0cnVjdG9yLl9pc0VsZW1lbnRWYWx1ZUVtcHR5T3JPbmx5VGhlTmVnYXRpdmVTaWduKHJhd1ZhbHVlVG9Gb3JtYXQsIHRoaXMuc2V0dGluZ3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHRoaXMuX21vZGlmeU5lZ2F0aXZlU2lnbkFuZERlY2ltYWxDaGFyYWN0ZXJGb3JSYXdWYWx1ZSh2YWx1ZSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmRpdmlzb3JXaGVuVW5mb2N1c2VkICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZSAvIHRoaXMuc2V0dGluZ3MuZGl2aXNvcldoZW5VbmZvY3VzZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZS50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX3JvdW5kRm9ybWF0dGVkVmFsdWVTaG93bk9uQmx1cih2YWx1ZSwgdGhpcy5zZXR0aW5ncyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX21vZGlmeU5lZ2F0aXZlU2lnbkFuZERlY2ltYWxDaGFyYWN0ZXJGb3JGb3JtYXR0ZWRWYWx1ZSh2YWx1ZSwgdGhpcy5zZXR0aW5ncyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW1pblRlc3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl90cmlnZ2VyRXZlbnQoQXV0b051bWVyaWMuZXZlbnRzLm1pblJhbmdlRXhjZWVkZWQsIHRoaXMuZG9tRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghbWF4VGVzdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMubWF4UmFuZ2VFeGNlZWRlZCwgdGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocmF3VmFsdWVUb0Zvcm1hdCA9PT0gJycpIHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLnNldHRpbmdzLmVtcHR5SW5wdXRCZWhhdmlvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci56ZXJvOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFJhd1ZhbHVlKCcwJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9yb3VuZFZhbHVlKCcwJywgdGhpcy5zZXR0aW5ncywgMCk7IFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5taW46XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0UmF3VmFsdWUodGhpcy5zZXR0aW5ncy5taW5pbXVtVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdGhpcy5jb25zdHJ1Y3Rvci5fcm91bmRGb3JtYXR0ZWRWYWx1ZVNob3duT25Gb2N1c09yQmx1cih0aGlzLnNldHRpbmdzLm1pbmltdW1WYWx1ZSwgdGhpcy5zZXR0aW5ncywgdGhpcy5pc0ZvY3VzZWQpOyBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IubWF4OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFJhd1ZhbHVlKHRoaXMuc2V0dGluZ3MubWF4aW11bVZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX3JvdW5kRm9ybWF0dGVkVmFsdWVTaG93bk9uRm9jdXNPckJsdXIodGhpcy5zZXR0aW5ncy5tYXhpbXVtVmFsdWUsIHRoaXMuc2V0dGluZ3MsIHRoaXMuaXNGb2N1c2VkKTsgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bWJlcih0aGlzLnNldHRpbmdzLmVtcHR5SW5wdXRCZWhhdmlvcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0UmF3VmFsdWUodGhpcy5zZXR0aW5ncy5lbXB0eUlucHV0QmVoYXZpb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX3JvdW5kRm9ybWF0dGVkVmFsdWVTaG93bk9uRm9jdXNPckJsdXIodGhpcy5zZXR0aW5ncy5lbXB0eUlucHV0QmVoYXZpb3IsIHRoaXMuc2V0dGluZ3MsIHRoaXMuaXNGb2N1c2VkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cblxuICAgICAgICAgICAgICAgIGxldCBncm91cGVkVmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9vcmRlclZhbHVlQ3VycmVuY3lTeW1ib2xBbmRTdWZmaXhUZXh0KHZhbHVlLCB0aGlzLnNldHRpbmdzLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcy5jb25zdHJ1Y3Rvci5faXNFbGVtZW50VmFsdWVFbXB0eU9yT25seVRoZU5lZ2F0aXZlU2lnbih2YWx1ZSwgdGhpcy5zZXR0aW5ncykgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIChpc1Jhd1ZhbHVlTnVsbCAmJiB0aGlzLnNldHRpbmdzLmVtcHR5SW5wdXRCZWhhdmlvciA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IubnVsbCkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGdyb3VwZWRWYWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX2FkZEdyb3VwU2VwYXJhdG9ycyh2YWx1ZSwgdGhpcy5zZXR0aW5ncywgZmFsc2UsIHJhd1ZhbHVlVG9Gb3JtYXQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIFRlc3RpbmcgZm9yIGBhbGxvd0RlY2ltYWxQYWRkaW5nLm5ldmVyYCBvciBgYWxsb3dEZWNpbWFsUGFkZGluZy5mbG9hdHNgIGlzIG5lZWRlZCB0byBtYWtlIHN1cmUgd2UgZG8gbm90IGtlZXAgYSB0cmFpbGluZyBkZWNpbWFsQ2hhcmFjdGVyIChsaWtlICc1MDAuJykgaW4gdGhlIGVsZW1lbnQsIHNpbmNlIHRoZSByYXcgdmFsdWUgd291bGQgc3RpbGwgYmUgYSBjb3JyZWN0bHkgZm9ybWF0dGVkIGludGVnZXIgKCc1MDAnKVxuICAgICAgICAgICAgICAgIGlmIChncm91cGVkVmFsdWUgIT09IHJhd1ZhbHVlVG9Gb3JtYXQgfHxcbiAgICAgICAgICAgICAgICAgICAgcmF3VmFsdWVUb0Zvcm1hdCA9PT0gJycgfHwgLy8gVGhpcyBtYWtlIHN1cmUgd2UgZ2V0IHJpZCBvbiBhbnkgY3VycmVuY3kgc3ltYm9sIG9yIHN1ZmZpeCB0aGF0IG1pZ2h0IGhhdmUgYmVlbiBhZGRlZCBvbiBmb2N1c1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmFsbG93RGVjaW1hbFBhZGRpbmcgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuYWxsb3dEZWNpbWFsUGFkZGluZy5uZXZlciB8fFxuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmFsbG93RGVjaW1hbFBhZGRpbmcgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuYWxsb3dEZWNpbWFsUGFkZGluZy5mbG9hdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3Muc3ltYm9sV2hlblVuZm9jdXNlZCAmJiByYXdWYWx1ZVRvRm9ybWF0ICE9PSAnJyAmJiByYXdWYWx1ZVRvRm9ybWF0ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBncm91cGVkVmFsdWUgPSBgJHtncm91cGVkVmFsdWV9JHt0aGlzLnNldHRpbmdzLnN5bWJvbFdoZW5VbmZvY3VzZWR9YDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldEVsZW1lbnRWYWx1ZShncm91cGVkVmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGUudHlwZSA9PT0gJ2JsdXInKSB7XG4gICAgICAgICAgICAgICAgLy9UT0RPIENyZWF0ZSBzZXBhcmF0ZSBoYW5kbGVycyBmb3IgYmx1ciBhbmQgbW91c2VsZWF2ZSwgcmVhbGx5LlxuICAgICAgICAgICAgICAgIHRoaXMuX29uQmx1cihlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXIgZm9yICdwYXN0ZScgZXZlbnRcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RXZlbnR8Q2xpcGJvYXJkRXZlbnR9IGVcbiAgICAgKi9cbiAgICBfb25QYXN0ZShlKSB7XG4gICAgICAgIC8vRklYTUUgV2hlbiBwYXN0aW5nICcwMDAnIG9uIGEgdGhvdXNhbmQgZ3JvdXAgc2VsZWN0aW9uLCB0aGUgd2hvbGUgc2VsZWN0aW9uIGdldHMgZGVsZXRlZCwgYW5kIG9ubHkgb25lICcwJyBpcyBwYXN0ZWQgKGNmLiBpc3N1ZSAjMzAyKVxuICAgICAgICAvLyBUaGUgZXZlbnQgaXMgcHJldmVudGVkIGJ5IGRlZmF1bHQsIHNpbmNlIG90aGVyd2lzZSB0aGUgdXNlciB3b3VsZCBiZSBhYmxlIHRvIHBhc3RlIGludmFsaWQgY2hhcmFjdGVycyBpbnRvIHRoZSBpbnB1dFxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MucmVhZE9ubHkgfHwgdGhpcy5kb21FbGVtZW50LnJlYWRPbmx5IHx8IHRoaXMuZG9tRWxlbWVudC5kaXNhYmxlZCkge1xuICAgICAgICAgICAgLy8gRG8gbm90IGFsbG93IHBhc3RpbmcgaW4gYSByZWFkb25seSBlbGVtZW50IChmaXggaXNzdWUgIzUwNSlcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByYXdQYXN0ZWRUZXh0O1xuICAgICAgICBpZiAod2luZG93LmNsaXBib2FyZERhdGEgJiYgd2luZG93LmNsaXBib2FyZERhdGEuZ2V0RGF0YSkge1xuICAgICAgICAgICAgLy8gU3BlY2lhbCBjYXNlIGZvciB0aGUgb2Jzb2xldGUgYW5kIG5vbi1zdGFuZGFyZCBJRSBicm93c2VycyAxMCBhbmQgMTFcbiAgICAgICAgICAgIHJhd1Bhc3RlZFRleHQgPSB3aW5kb3cuY2xpcGJvYXJkRGF0YS5nZXREYXRhKCdUZXh0Jyk7XG4gICAgICAgIH0gZWxzZSBpZiAoZS5jbGlwYm9hcmREYXRhICYmIGUuY2xpcGJvYXJkRGF0YS5nZXREYXRhKSB7XG4gICAgICAgICAgICAvLyBOb3JtYWwgY2FzZSB3aXRoIG1vZGVybiBicm93c2Vyc1xuICAgICAgICAgICAgcmF3UGFzdGVkVGV4dCA9IGUuY2xpcGJvYXJkRGF0YS5nZXREYXRhKCd0ZXh0L3BsYWluJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKCdVbmFibGUgdG8gcmV0cmlldmUgdGhlIHBhc3RlZCB2YWx1ZS4gUGxlYXNlIHVzZSBhIG1vZGVybiBicm93c2VyIChpZS4gRmlyZWZveCBvciBDaHJvbWl1bSkuJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBGaXggZm9yIGZpcmVmb3ggcGFzdGUgaGFuZGxpbmcgb24gYGNvbnRlbnRlZGl0YWJsZWAgZWxlbWVudHMgd2hlcmUgYGUudGFyZ2V0YCBpcyB0aGUgdGhlIHRleHQgbm9kZSwgbm90IHRoZSBlbGVtZW50XG4gICAgICAgIGxldCBldmVudFRhcmdldDtcbiAgICAgICAgaWYgKCFlLnRhcmdldC50YWdOYW1lKSB7XG4gICAgICAgICAgICBldmVudFRhcmdldCA9IGUuZXhwbGljaXRPcmlnaW5hbFRhcmdldDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGV2ZW50VGFyZ2V0ID0gZS50YXJnZXQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyAwLiBTcGVjaWFsIGNhc2UgaWYgdGhlIHVzZXIgaGFzIHNlbGVjdGVkIGFsbCB0aGUgaW5wdXQgdGV4dCBiZWZvcmUgcGFzdGluZ1xuICAgICAgICBjb25zdCBpbml0aWFsRm9ybWF0dGVkVmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUoZXZlbnRUYXJnZXQpO1xuICAgICAgICBjb25zdCBzZWxlY3Rpb25TdGFydCA9IGV2ZW50VGFyZ2V0LnNlbGVjdGlvblN0YXJ0IHx8IDA7XG4gICAgICAgIGNvbnN0IHNlbGVjdGlvbkVuZCA9IGV2ZW50VGFyZ2V0LnNlbGVjdGlvbkVuZCB8fCAwO1xuICAgICAgICBjb25zdCBzZWxlY3Rpb25TaXplID0gc2VsZWN0aW9uRW5kIC0gc2VsZWN0aW9uU3RhcnQ7XG5cbiAgICAgICAgaWYgKHNlbGVjdGlvblNpemUgPT09IGluaXRpYWxGb3JtYXR0ZWRWYWx1ZS5sZW5ndGgpIHsgLy8gSWYgYWxsIHRoZSBlbGVtZW50IHRleHQgaXMgc2VsZWN0ZWRcbiAgICAgICAgICAgIC8vVE9ETyBSZWZhY3RvciB0aGlzIHdpdGggdGhlIHRlc3RzIGJlbG93XG4gICAgICAgICAgICAvLyBTaW5jZSB0aGUgd2hvbGUgZWxlbWVudCBjb250ZW50IHdpbGwgYmUgcmVwbGFjZWQsIG5vIG5lZWQgdG8gY29tcGxpY2F0ZSB0aGluZ3MgYW5kIGRpcmVjdGx5IHRlc3QgZm9yIHRoZSB2YWxpZGl0eSBvZiB0aGUgcGFzdGVkIGNvbnRlbnQsIHRoZW4gc2V0IHRoZSBgcmF3VmFsdWVgIGFuZCBjYXJldCBwb3NpdGlvbiAoZml4IGlzc3VlICM0ODIpXG4gICAgICAgICAgICAvLyAxLiBTdHJpcCBhbGwgdGhvdXNhbmQgc2VwYXJhdG9ycywgYnJhY2tldHMgYW5kIGN1cnJlbmN5IHNpZ24sIGFuZCBjb252ZXJ0IHRoZSBkZWNpbWFsIGNoYXJhY3RlciB0byBhIGRvdFxuICAgICAgICAgICAgY29uc3QgdW50cmFuc2xhdGVkUGFzdGVkVGV4dCA9IHRoaXMuX3ByZXBhcmVQYXN0ZWRUZXh0KHJhd1Bhc3RlZFRleHQpO1xuICAgICAgICAgICAgY29uc3QgcGFzdGVkUmF3VmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5hcmFiaWNUb0xhdGluTnVtYmVycyh1bnRyYW5zbGF0ZWRQYXN0ZWRUZXh0LCBmYWxzZSwgZmFsc2UsIGZhbHNlKTsgLy8gQWxsb3cgcGFzdGluZyBhcmFiaWMgbnVtYmVyc1xuXG4gICAgICAgICAgICAvLyAyLiBDaGVjayB0aGF0IHRoZSBwYXN0ZSBpcyBhIHZhbGlkIG51bWJlciBvbmNlIGl0IGhhcyBiZWVuIG5vcm1hbGl6ZWQgdG8gYSByYXcgdmFsdWVcbiAgICAgICAgICAgIGlmIChwYXN0ZWRSYXdWYWx1ZSA9PT0gJy4nIHx8IHBhc3RlZFJhd1ZhbHVlID09PSAnJyB8fCAocGFzdGVkUmF3VmFsdWUgIT09ICcuJyAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNOdW1iZXIocGFzdGVkUmF3VmFsdWUpKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZm9ybWF0dGVkID0gdHJ1ZTsgLy8gVGhpcyBwcmV2ZW50IHRoZSBga2V5dXBgIGV2ZW50IG9uIHRoZSBgdmAga2V5IGR1cmluZyBhIHBhc3RlIHRvIHRyeSB0byBmb3JtYXQgYW4gZW1wdHkgdmFsdWUuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIHVzZXIgdHJpZXMgdG8gcGFzdGUgYSBzaW5nbGUgZGVjaW1hbCBjaGFyYWN0ZXIgKHRoYXQgaGFzIGJlZW4gdHJhbnNsYXRlZCB0byAnLicgYWxyZWFkeSkgb3IgdGhlIGVtcHR5IHZhbHVlLCBpZ25vcmUgdGhlIHBhc3RlXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3Mub25JbnZhbGlkUGFzdGUgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUuZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHBhc3RlZCB2YWx1ZSAnJHtyYXdQYXN0ZWRUZXh0fScgaXMgbm90IGEgdmFsaWQgcGFzdGUgY29udGVudC5gKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIDMuIFRoZW4gdHJ5IHRvIHNldCBpdCBhcyB0aGUgbmV3IHZhbHVlLiBUaGUgYHNldCgpYCBtZXRob2Qgd2lsbCBydW4gdGhlIGFkZGl0aW9uYWwgdGVzdHMgKGllLiBsaW1pdHMpIGFzIG5lZWRlZC5cbiAgICAgICAgICAgIHRoaXMuc2V0KHBhc3RlZFJhd1ZhbHVlKTtcbiAgICAgICAgICAgIHRoaXMuZm9ybWF0dGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgLy8gNC4gT24gYSAnbm9ybWFsJyBub24tYXV0b051bWVyaWMgaW5wdXQsIGFuIGBpbnB1dGAgZXZlbnQgaXMgc2VudCB3aGVuIGEgcGFzdGUgaXMgZG9uZS4gV2UgbWltaWMgdGhhdC5cbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMubmF0aXZlLmlucHV0LCBldmVudFRhcmdldCk7XG5cbiAgICAgICAgICAgIC8vIDUuIFJldHVybiBzaW5jZSB0aGUgam9iIGlzIGRvbmVcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIDEuIENoZWNrIGlmIHRoZSBwYXN0ZSBoYXMgYSBuZWdhdGl2ZSBzaWduIChvbmx5IGlmIGl0J3MgdGhlIGZpcnN0IGNoYXJhY3RlciksIGFuZCBzdG9yZSB0aGF0IGluZm9ybWF0aW9uIGZvciBsYXRlciB1c2VcbiAgICAgICAgY29uc3QgaXNQYXN0ZU5lZ2F0aXZlID0gQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZVN0cmljdChyYXdQYXN0ZWRUZXh0LCB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3Rlcik7XG4gICAgICAgIGlmIChpc1Bhc3RlTmVnYXRpdmUpIHtcbiAgICAgICAgICAgIC8vIDFhLiBSZW1vdmUgdGhlIG5lZ2F0aXZlIHNpZ24gZnJvbSB0aGUgcGFzdGVkIHRleHRcbiAgICAgICAgICAgIHJhd1Bhc3RlZFRleHQgPSByYXdQYXN0ZWRUZXh0LnNsaWNlKDEsIHJhd1Bhc3RlZFRleHQubGVuZ3RoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIDIuIFN0cmlwIGFsbCB0aG91c2FuZCBzZXBhcmF0b3JzLCBicmFja2V0cyBhbmQgY3VycmVuY3kgc2lnbiwgYW5kIGNvbnZlcnQgdGhlIGRlY2ltYWwgY2hhcmFjdGVyIHRvIGEgZG90XG4gICAgICAgIGNvbnN0IHVudHJhbnNsYXRlZFBhc3RlZFRleHQgPSB0aGlzLl9wcmVwYXJlUGFzdGVkVGV4dChyYXdQYXN0ZWRUZXh0KTtcblxuICAgICAgICBsZXQgcGFzdGVkVGV4dDtcbiAgICAgICAgaWYgKHVudHJhbnNsYXRlZFBhc3RlZFRleHQgPT09ICcuJykge1xuICAgICAgICAgICAgLy8gU3BlY2lhbCBjYXNlIDogSWYgdGhlIHVzZXIgdHJpZXMgdG8gcGFzdGUgYSBzaW5nbGUgZGVjaW1hbCBjaGFyYWN0ZXIgKHRoYXQgaGFzIGJlZW4gdHJhbnNsYXRlZCB0byAnLicgYWxyZWFkeSlcbiAgICAgICAgICAgIHBhc3RlZFRleHQgPSAnLic7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBOb3JtYWwgY2FzZVxuICAgICAgICAgICAgLy8gQWxsb3cgcGFzdGluZyBhcmFiaWMgbnVtYmVyc1xuICAgICAgICAgICAgcGFzdGVkVGV4dCA9IEF1dG9OdW1lcmljSGVscGVyLmFyYWJpY1RvTGF0aW5OdW1iZXJzKHVudHJhbnNsYXRlZFBhc3RlZFRleHQsIGZhbHNlLCBmYWxzZSwgZmFsc2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gMy4gVGVzdCBpZiB0aGUgcGFzdGUgaXMgdmFsaWQgKG9ubHkgaGFzIG51bWJlcnMgYW5kIGV2ZW50dWFsbHkgYSBkZWNpbWFsIGNoYXJhY3RlcikuIElmIGl0J3Mgbm90IHZhbGlkLCBzdG9wIGhlcmUuXG4gICAgICAgIGlmIChwYXN0ZWRUZXh0ICE9PSAnLicgJiYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bWJlcihwYXN0ZWRUZXh0KSB8fCBwYXN0ZWRUZXh0ID09PSAnJykpIHtcbiAgICAgICAgICAgIHRoaXMuZm9ybWF0dGVkID0gdHJ1ZTsgLy8gVGhpcyBwcmV2ZW50IHRoZSBga2V5dXBgIGV2ZW50IG9uIHRoZSBgdmAga2V5IGR1cmluZyBhIHBhc3RlIHRvIHRyeSB0byBmb3JtYXQgYW4gZW1wdHkgdmFsdWUgKGZpeCBpc3N1ZSAjNDg0KVxuICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3Mub25JbnZhbGlkUGFzdGUgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUuZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgcGFzdGVkIHZhbHVlICcke3Jhd1Bhc3RlZFRleHR9JyBpcyBub3QgYSB2YWxpZCBwYXN0ZSBjb250ZW50LmApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyA0LiBDYWxjdWxhdGUgdGhlIHBhc3RlIHJlc3VsdFxuICAgICAgICBsZXQgY2FyZXRQb3NpdGlvbk9uSW5pdGlhbFRleHRBZnRlclBhc3Rpbmc7XG4gICAgICAgIGxldCBpc0luaXRpYWxWYWx1ZU5lZ2F0aXZlID0gQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZVN0cmljdCh0aGlzLmdldE51bWVyaWNTdHJpbmcoKSwgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpO1xuICAgICAgICBsZXQgaXNQYXN0ZU5lZ2F0aXZlQW5kSW5pdGlhbFZhbHVlSXNQb3NpdGl2ZTtcbiAgICAgICAgbGV0IHJlc3VsdDtcblxuICAgICAgICAvLyBJZiB0aGUgcGFzdGVkIGNvbnRlbnQgaXMgbmVnYXRpdmUsIHRoZW4gdGhlIHJlc3VsdCB3aWxsIGJlIG5lZ2F0aXZlIHRvb1xuICAgICAgICBpZiAoaXNQYXN0ZU5lZ2F0aXZlICYmICFpc0luaXRpYWxWYWx1ZU5lZ2F0aXZlKSB7XG4gICAgICAgICAgICBpc0luaXRpYWxWYWx1ZU5lZ2F0aXZlID0gdHJ1ZTtcbiAgICAgICAgICAgIGlzUGFzdGVOZWdhdGl2ZUFuZEluaXRpYWxWYWx1ZUlzUG9zaXRpdmUgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaXNQYXN0ZU5lZ2F0aXZlQW5kSW5pdGlhbFZhbHVlSXNQb3NpdGl2ZSA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gMS4gR2VuZXJhdGUgdGhlIHVuZm9ybWF0dGVkIHJlc3VsdFxuICAgICAgICBjb25zdCBsZWZ0Rm9ybWF0dGVkUGFydCAgPSBpbml0aWFsRm9ybWF0dGVkVmFsdWUuc2xpY2UoMCwgc2VsZWN0aW9uU3RhcnQpO1xuICAgICAgICBjb25zdCByaWdodEZvcm1hdHRlZFBhcnQgPSBpbml0aWFsRm9ybWF0dGVkVmFsdWUuc2xpY2Uoc2VsZWN0aW9uRW5kLCBpbml0aWFsRm9ybWF0dGVkVmFsdWUubGVuZ3RoKTtcblxuICAgICAgICBpZiAoc2VsZWN0aW9uU3RhcnQgIT09IHNlbGVjdGlvbkVuZCkge1xuICAgICAgICAgICAgLy8gYS4gSWYgdGhlcmUgaXMgYSBzZWxlY3Rpb24sIHJlbW92ZSB0aGUgc2VsZWN0ZWQgcGFydCwgYW5kIHJldHVybiB0aGUgbGVmdCBhbmQgcmlnaHQgcGFydFxuICAgICAgICAgICAgcmVzdWx0ID0gdGhpcy5fcHJlcGFyZVBhc3RlZFRleHQobGVmdEZvcm1hdHRlZFBhcnQgKyByaWdodEZvcm1hdHRlZFBhcnQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gYi4gRWxzZSBpZiB0aGlzIGlzIG9ubHkgb25lIGNhcmV0IChhbmQgdGhlcmVmb3JlIG5vIHNlbGVjdGlvbiksIHRoZW4gcmV0dXJuIHRoZSBsZWZ0IGFuZCByaWdodCBwYXJ0XG4gICAgICAgICAgICByZXN1bHQgPSB0aGlzLl9wcmVwYXJlUGFzdGVkVGV4dChpbml0aWFsRm9ybWF0dGVkVmFsdWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkIGJhY2sgdGhlIG5lZ2F0aXZlIHNpZ24gaWYgbmVlZGVkXG4gICAgICAgIGlmIChpc0luaXRpYWxWYWx1ZU5lZ2F0aXZlKSB7XG4gICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpY0hlbHBlci5zZXRSYXdOZWdhdGl2ZVNpZ24ocmVzdWx0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEJ1aWxkIHRoZSB1bmZvcm1hdHRlZCByZXN1bHQgc3RyaW5nXG4gICAgICAgIGNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nID0gQXV0b051bWVyaWNIZWxwZXIuY29udmVydENoYXJhY3RlckNvdW50VG9JbmRleFBvc2l0aW9uKEF1dG9OdW1lcmljSGVscGVyLmNvdW50TnVtYmVyQ2hhcmFjdGVyc09uVGhlQ2FyZXRMZWZ0U2lkZShpbml0aWFsRm9ybWF0dGVkVmFsdWUsIHNlbGVjdGlvblN0YXJ0LCB0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpKTtcbiAgICAgICAgaWYgKGlzUGFzdGVOZWdhdGl2ZUFuZEluaXRpYWxWYWx1ZUlzUG9zaXRpdmUpIHtcbiAgICAgICAgICAgIC8vIElmIHRoZSBpbml0aWFsIHBhc3RlIGlzIG5lZ2F0aXZlIGFuZCB0aGUgaW5pdGlhbCB2YWx1ZSBpcyBub3QsIHRoZW4gSSBtdXN0IG9mZnNldCB0aGUgY2FyZXQgcG9zaXRpb24gYnkgb25lIHBsYWNlIHRvIHRoZSByaWdodCB0byB0YWtlIHRoZSBhZGRpdGlvbmFsIGh5cGhlbiBpbnRvIGFjY291bnRcbiAgICAgICAgICAgIGNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nKys7XG4gICAgICAgICAgICAvL1RPRE8gUXVpZCBpZiB0aGUgbmVnYXRpdmUgc2lnbiBpcyBub3Qgb24gdGhlIGxlZnQgKG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50IGFuZCBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudCk/XG4gICAgICAgICAgICAvL1RPRE8gUXVpZCBpZiB0aGUgcG9zaXRpdmUgc2lnbiBpcyBzaG93bj9cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBsZWZ0UGFydCAgPSByZXN1bHQuc2xpY2UoMCwgY2FyZXRQb3NpdGlvbk9uSW5pdGlhbFRleHRBZnRlclBhc3RpbmcpO1xuICAgICAgICBsZXQgcmlnaHRQYXJ0ID0gcmVzdWx0LnNsaWNlKGNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nLCByZXN1bHQubGVuZ3RoKTtcbiAgICAgICAgbGV0IGxlZnRQYXJ0Q29udGFpbmVkQURvdCA9IGZhbHNlO1xuICAgICAgICBpZiAocGFzdGVkVGV4dCA9PT0gJy4nKSB7XG4gICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMobGVmdFBhcnQsICcuJykpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiBJIHJlbW92ZSBhIGRvdCBoZXJlLCB0aGVuIEkgbmVlZCB0byB1cGRhdGUgdGhlIGNhcmV0IHBvc2l0aW9uIChkZWNyZW1lbnQgaXQgYnkgMSkgd2hlbiBwb3NpdGlvbmluZyBpdFxuICAgICAgICAgICAgICAgIC8vIFRvIGRvIHNvLCB3ZSBrZWVwIHRoYXQgaW5mbyBpbiBvcmRlciB0byBtb2RpZnkgdGhlIGNhcmV0IHBvc2l0aW9uIGxhdGVyXG4gICAgICAgICAgICAgICAgbGVmdFBhcnRDb250YWluZWRBRG90ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBsZWZ0UGFydCAgICAgICAgICAgICAgPSBsZWZ0UGFydC5yZXBsYWNlKCcuJywgJycpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByaWdodFBhcnQgPSByaWdodFBhcnQucmVwbGFjZSgnLicsICcnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE1hbmFnZSB0aGUgY2FzZSB3aGVyZSBhIG5lZ2F0aXZlIG51bWJlciBpcyBwYXN0ZWQgb250byBhbm90aGVyIG5lZ2F0aXZlIG51bWJlciB0aGF0IGlzIGVudGlyZWx5IHNlbGVjdGVkIChjZi4gaXNzdWUgIzU5MylcbiAgICAgICAgbGV0IG5lZ2F0aXZlUGFzdGVPbk5lZ2F0aXZlTnVtYmVyID0gZmFsc2U7XG4gICAgICAgIGlmIChsZWZ0UGFydCA9PT0gJycgJiYgcmlnaHRQYXJ0ID09PSAnLScpIHtcbiAgICAgICAgICAgIGxlZnRQYXJ0ID0gJy0nO1xuICAgICAgICAgICAgcmlnaHRQYXJ0ID0gJyc7XG4gICAgICAgICAgICAvLyBXaGVuIHBhc3RpbmcgYSBuZWdhdGl2ZSBudW1iZXIgb24gYSBuZWdhdGl2ZSBudW1iZXIsIHdlIG5lZWQgdG8gb2Zmc2V0IHRoZSBjYXJldCBwb3NpdGlvbiBvbmUgcGxhY2UgdG8gdGhlIHJpZ2h0IHRvIHRha2UgaW50byBhY2NvdW50IHRoZSBuZWdhdGl2ZSBzaWduXG4gICAgICAgICAgICBuZWdhdGl2ZVBhc3RlT25OZWdhdGl2ZU51bWJlciA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyAtLSBIZXJlLCB3ZSBhcmUgZ29vZCB0byBnbyB0byBjb250aW51ZSBvbiB0aGUgc2FtZSBiYXNpcyBmb3IgZWFjaCB2YWx1ZSBvZiB0aGUgYG9uSW52YWxpZFBhc3RlYCBvcHRpb25cblxuICAgICAgICBzd2l0Y2ggKHRoaXMuc2V0dGluZ3Mub25JbnZhbGlkUGFzdGUpIHtcbiAgICAgICAgICAgIC8qIDRhLiBUcnVuY2F0ZSBwYXN0ZSBiZWhhdmlvcjpcbiAgICAgICAgICAgICAqIEluc2VydCBhcyBtYW55IG51bWJlcnMgYXMgcG9zc2libGUgb24gdGhlIHJpZ2h0IGhhbmQgc2lkZSBvZiB0aGUgY2FyZXQgZnJvbSB0aGUgcGFzdGVkIHRleHQgY29udGVudCwgdW50aWwgdGhlIGlucHV0IHJlYWNoIGl0cyByYW5nZSBsaW1pdC5cbiAgICAgICAgICAgICAqIElmIHRoZXJlIGlzIG1vcmUgY2hhcmFjdGVycyBpbiB0aGUgY2xpcGJvYXJkIG9uY2UgYSBsaW1pdCBpcyByZWFjaGVkLCBkcm9wIHRoZSBleHRyYW5lb3VzIGNoYXJhY3RlcnMuXG4gICAgICAgICAgICAgKiBPdGhlcndpc2UgcGFzdGUgYWxsIHRoZSBudW1iZXJzIGZyb20gdGhlIGNsaXBib2FyZC5cbiAgICAgICAgICAgICAqIFdoaWxlIGRvaW5nIHNvLCB3ZSBjaGVjayBpZiB0aGUgcmVzdWx0IGlzIHdpdGhpbiB0aGUgbWluaW11bSBhbmQgbWF4aW11bSB2YWx1ZXMgYWxsb3dlZCwgYW5kIHN0b3AgYXMgc29vbiBhcyB3ZSBlbmNvdW50ZXIgb25lIG9mIHRob3NlLlxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIDRiLiBSZXBsYWNlIHBhc3RlIGJlaGF2aW9yOlxuICAgICAgICAgICAgICogSWRlbSB0aGFuIHRoZSAndHJ1bmNhdGUnIHBhc3RlIGJlaGF2aW9yLCBleGNlcHQgdGhhdCB3aGVuIGEgcmFuZ2UgbGltaXQgaXMgaGl0LCB3ZSB0cnkgdG8gcmVwbGFjZSB0aGUgc3Vic2VxdWVudCBpbml0aWFsIG51bWJlcnMgd2l0aCB0aGUgcGFzdGVkIG9uZXMsIHVudGlsIHdlIGhpdCB0aGUgcmFuZ2UgbGltaXQgYSBzZWNvbmQgKGFuZCBsYXN0KSB0aW1lLCBvciB3ZSBydW4gb3V0IG9mIG51bWJlcnMgdG8gcGFzdGVcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgLyogZXNsaW50IG5vLWNhc2UtZGVjbGFyYXRpb25zOiAwICovXG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUudHJ1bmNhdGU6XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUucmVwbGFjZTpcbiAgICAgICAgICAgICAgICAvLyBjLiBBZGQgbnVtYmVycyBvbmUgYnkgb25lIGF0IHRoZSBjYXJldCBwb3NpdGlvbiwgd2hpbGUgdGVzdGluZyBpZiB0aGUgcmVzdWx0IGlzIHZhbGlkIGFuZCB3aXRoaW4gdGhlIHJhbmdlIG9mIHRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtIHZhbHVlXG4gICAgICAgICAgICAgICAgLy8gICAgQ29udGludWUgdW50aWwgeW91IGVpdGhlciBydW4gb3V0IG9mIG51bWJlcnMgdG8gcGFzdGUsIG9yIHRoYXQgeW91IGdldCBvdXQgb2YgdGhlIHJhbmdlIGxpbWl0c1xuICAgICAgICAgICAgICAgIGNvbnN0IG1pblBhcnNlID0gQXV0b051bWVyaWNIZWxwZXIucGFyc2VTdHIodGhpcy5zZXR0aW5ncy5taW5pbXVtVmFsdWUpO1xuICAgICAgICAgICAgICAgIGNvbnN0IG1heFBhcnNlID0gQXV0b051bWVyaWNIZWxwZXIucGFyc2VTdHIodGhpcy5zZXR0aW5ncy5tYXhpbXVtVmFsdWUpO1xuICAgICAgICAgICAgICAgIGxldCBsYXN0R29vZEtub3duUmVzdWx0ID0gcmVzdWx0OyAvLyBUaGlzIGlzIHNldCBhcyB0aGUgZGVmYXVsdCwgaW4gY2FzZSB3ZSBkbyBub3QgYWRkIGV2ZW4gb25lIG51bWJlclxuICAgICAgICAgICAgICAgIGxldCBwYXN0ZWRUZXh0SW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIGxldCBtb2RpZmllZExlZnRQYXJ0ID0gbGVmdFBhcnQ7XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAocGFzdGVkVGV4dEluZGV4IDwgcGFzdGVkVGV4dC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gTW9kaWZ5IHRoZSByZXN1bHQgd2l0aCBhbm90aGVyIHBhc3RlZCBjaGFyYWN0ZXJcbiAgICAgICAgICAgICAgICAgICAgbW9kaWZpZWRMZWZ0UGFydCArPSBwYXN0ZWRUZXh0W3Bhc3RlZFRleHRJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IG1vZGlmaWVkTGVmdFBhcnQgKyByaWdodFBhcnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gQ2hlY2sgdGhlIHJhbmdlIGxpbWl0c1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY29uc3RydWN0b3IuX2NoZWNrSWZJblJhbmdlKHJlc3VsdCwgbWluUGFyc2UsIG1heFBhcnNlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlIHJlc3VsdCBpcyBvdXQgb2YgdGhlIHJhbmdlIGxpbWl0cywgc3RvcCB0aGUgbG9vcCBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIFNhdmUgdGhlIGxhc3QgZ29vZCBrbm93biByZXN1bHRcbiAgICAgICAgICAgICAgICAgICAgbGFzdEdvb2RLbm93blJlc3VsdCA9IHJlc3VsdDtcblxuICAgICAgICAgICAgICAgICAgICAvLyBVcGRhdGUgdGhlIGxvY2FsIHZhcmlhYmxlcyBmb3IgdGhlIG5leHQgbG9vcFxuICAgICAgICAgICAgICAgICAgICBwYXN0ZWRUZXh0SW5kZXgrKztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgdGhlIGxhc3QgY2FyZXQgcG9zaXRpb24gd2hlcmUgdG8gaW5zZXJ0IGEgbmV3IG51bWJlclxuICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nICs9IHBhc3RlZFRleHRJbmRleDtcbiAgICAgICAgICAgICAgICBpZiAobmVnYXRpdmVQYXN0ZU9uTmVnYXRpdmVOdW1iZXIpIGNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nKys7XG5cbiAgICAgICAgICAgICAgICAvL1hYWCBIZXJlIHdlIGhhdmUgdGhlIHJlc3VsdCBmb3IgdGhlIGB0cnVuY2F0ZWAgb3B0aW9uXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3Mub25JbnZhbGlkUGFzdGUgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUudHJ1bmNhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy9UT0RPIElmIHRoZSB1c2VyIGFzIGRlZmluZWQgYSB0cnVuY2F0ZSBjYWxsYmFjayBhbmQgdGhlcmUgYXJlIHN0aWxsIHNvbWUgbnVtYmVycyAodGhhdCB3aWxsIGJlIGRyb3BwZWQpLCB0aGVuIGNhbGwgdGhpcyBjYWxsYmFjayB3aXRoIHRoZSBpbml0aWFsIHBhc3RlIGFzIHdlbGwgYXMgdGhlIHJlbWFpbmluZyBudW1iZXJzXG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGxhc3RHb29kS25vd25SZXN1bHQ7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxlZnRQYXJ0Q29udGFpbmVkQURvdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBkb3QgaGFzIGJlZW4gcmVtb3ZlZCBmb3IgdGhlIHBhcnQgb24gdGhlIGxlZnQgb2YgdGhlIGNhcmV0LCB3ZSBkZWNyZW1lbnQgdGhlIGNhcmV0IGluZGV4IHBvc2l0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZy0tO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvL1hYWCAuLi5lbHNlIHdlIG5lZWQgdG8gY29udGludWUgbW9kaWZ5aW5nIHRoZSByZXN1bHQgZm9yIHRoZSAncmVwbGFjZScgb3B0aW9uXG5cbiAgICAgICAgICAgICAgICAvLyBkLiBVbnRpbCB0aGVyZSBhcmUgbnVtYmVycyB0byBwYXN0ZSwgcmVwbGFjZSB0aGUgaW5pdGlhbCBudW1iZXJzIG9uZSBieSBvbmUsIGFuZCBzdGlsbCBkbyB0aGUgcmFuZ2UgdGVzdC5cbiAgICAgICAgICAgICAgICAvLyAgICBTdG9wIHdoZW4geW91IGhhdmUgbm8gbW9yZSBudW1iZXJzIHRvIHBhc3RlLCBvciBpZiB5b3UgYXJlIG91dCBvZiB0aGUgcmFuZ2UgbGltaXRzLlxuICAgICAgICAgICAgICAgIC8vICAgIElmIHlvdSBkbyBnZXQgdG8gdGhlIHJhbmdlIGxpbWl0cywgdXNlIHRoZSBwcmV2aW91cyBrbm93biBnb29kIHZhbHVlIHdpdGhpbiB0aG9zZSBsaW1pdHMuXG4gICAgICAgICAgICAgICAgLy8gICAgTm90ZTogVGhlIG51bWJlcnMgYXJlIHJlcGxhY2VkIG9uZSBieSBvbmUsIGluIHRoZSBpbnRlZ2VyIHRoZW4gZGVjaW1hbCBwYXJ0LCB3aGlsZSBpZ25vcmluZyB0aGUgZGVjaW1hbCBjaGFyYWN0ZXJcbiAgICAgICAgICAgICAgICAvL1RPRE8gV2hhdCBzaG91bGQgaGFwcGVuIGlmIHRoZSB1c2VyIHRyeSB0byBwYXN0ZSBhIGRlY2ltYWwgbnVtYmVyPyBTaG91bGQgd2Ugb3ZlcnJpZGUgdGhlIGN1cnJlbnQgaW5pdGlhbCBkZWNpbWFsIGNoYXJhY3RlciBpbiBmYXZvciBvZiB0aGlzIG5ldyBvbmU/IElmIHdlIGRvLCB0aGVuIHdlIGhhdmUgdG8gcmVjYWxjdWxhdGUgdGhlIHZNaW4vdk1heCBmcm9tIHRoZSBzdGFydCBpbiBvcmRlciB0byB0YWtlIGludG8gYWNjb3VudCB0aGlzIG5ldyBkZWNpbWFsIGNoYXJhY3RlciBwb3NpdGlvbi4uXG4gICAgICAgICAgICAgICAgbGV0IGxhc3RHb29kS25vd25SZXN1bHRJbmRleCA9IGNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nO1xuICAgICAgICAgICAgICAgIGNvbnN0IGxhc3RHb29kS25vd25SZXN1bHRTaXplID0gbGFzdEdvb2RLbm93blJlc3VsdC5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAocGFzdGVkVGV4dEluZGV4IDwgcGFzdGVkVGV4dC5sZW5ndGggJiYgbGFzdEdvb2RLbm93blJlc3VsdEluZGV4IDwgbGFzdEdvb2RLbm93blJlc3VsdFNpemUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RHb29kS25vd25SZXN1bHRbbGFzdEdvb2RLbm93blJlc3VsdEluZGV4XSA9PT0gJy4nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBza2lwIHRoZSBkZWNpbWFsIGNoYXJhY3RlciAncmVwbGFjZW1lbnQnLiBUaGF0IHdheSwgd2UgZG8gbm90IGNoYW5nZSB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgcG9zaXRpb24gcmVnYXJkaW5nIHRoZSByZW1haW5pbmcgbnVtYmVycy5cbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RHb29kS25vd25SZXN1bHRJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHJlcGxhY2Ugb25lIGNoYXJhY3RlciBhdCBhIHRpbWVcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNIZWxwZXIucmVwbGFjZUNoYXJBdChsYXN0R29vZEtub3duUmVzdWx0LCBsYXN0R29vZEtub3duUmVzdWx0SW5kZXgsIHBhc3RlZFRleHRbcGFzdGVkVGV4dEluZGV4XSk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gQ2hlY2sgdGhlIHJhbmdlIGxpbWl0c1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY29uc3RydWN0b3IuX2NoZWNrSWZJblJhbmdlKHJlc3VsdCwgbWluUGFyc2UsIG1heFBhcnNlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlIHJlc3VsdCBpcyBvdXQgb2YgdGhlIHJhbmdlIGxpbWl0cywgc3RvcCB0aGUgbG9vcCBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIFNhdmUgdGhlIGxhc3QgZ29vZCBrbm93biByZXN1bHRcbiAgICAgICAgICAgICAgICAgICAgbGFzdEdvb2RLbm93blJlc3VsdCA9IHJlc3VsdDtcblxuICAgICAgICAgICAgICAgICAgICAvLyBVcGRhdGUgdGhlIGxvY2FsIHZhcmlhYmxlcyBmb3IgdGhlIG5leHQgbG9vcFxuICAgICAgICAgICAgICAgICAgICBwYXN0ZWRUZXh0SW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgbGFzdEdvb2RLbm93blJlc3VsdEluZGV4Kys7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBsYXN0IGNhcmV0IHBvc2l0aW9uIHdoZXJlIHRvIGluc2VydCBhIG5ldyBudW1iZXJcbiAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZyA9IGxhc3RHb29kS25vd25SZXN1bHRJbmRleDtcblxuICAgICAgICAgICAgICAgIGlmIChsZWZ0UGFydENvbnRhaW5lZEFEb3QpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBkb3QgaGFzIGJlZW4gcmVtb3ZlZCBmb3IgdGhlIHBhcnQgb24gdGhlIGxlZnQgb2YgdGhlIGNhcmV0LCB3ZSBkZWNyZW1lbnQgdGhlIGNhcmV0IGluZGV4IHBvc2l0aW9uXG4gICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nLS07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gbGFzdEdvb2RLbm93blJlc3VsdDtcblxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgLyogNGMuIE5vcm1hbCBwYXN0ZSBiZWhhdmlvcjpcbiAgICAgICAgICAgICAqIEluc2VydCB0aGUgcGFzdGVkIG51bWJlciBpbnNpZGUgdGhlIGN1cnJlbnQgdW5mb3JtYXR0ZWQgdGV4dCwgYXQgdGhlIGNvcnJlY3QgY2FyZXQgcG9zaXRpb24gb3Igc2VsZWN0aW9uXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS5lcnJvcjpcbiAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS5pZ25vcmU6XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUuY2xhbXA6XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIC8vIEdlbmVyYXRlIHRoZSB1bmZvcm1hdHRlZCByZXN1bHRcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBgJHtsZWZ0UGFydH0ke3Bhc3RlZFRleHR9JHtyaWdodFBhcnR9YDtcblxuICAgICAgICAgICAgICAgIC8vIDIuIENhbGN1bGF0ZSB0aGUgY2FyZXQgcG9zaXRpb24gaW4gdGhlIHVuZm9ybWF0dGVkIHZhbHVlLCBmb3IgbGF0ZXIgdXNlXG4gICAgICAgICAgICAgICAgaWYgKHNlbGVjdGlvblN0YXJ0ID09PSBzZWxlY3Rpb25FbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhlcmUgaXMgbm8gc2VsZWN0aW9uLCB0aGVuIHRoZSBjYXJldCBwb3NpdGlvbiBpcyBzZXQgYWZ0ZXIgdGhlIHBhc3RlZCB0ZXh0XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4V2hlcmVQYXN0ZWRUZXh0SGFzQmVlbkluc2VydGVkID0gQXV0b051bWVyaWNIZWxwZXIuY29udmVydENoYXJhY3RlckNvdW50VG9JbmRleFBvc2l0aW9uKEF1dG9OdW1lcmljSGVscGVyLmNvdW50TnVtYmVyQ2hhcmFjdGVyc09uVGhlQ2FyZXRMZWZ0U2lkZShpbml0aWFsRm9ybWF0dGVkVmFsdWUsIHNlbGVjdGlvblN0YXJ0LCB0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpKTtcbiAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbk9uSW5pdGlhbFRleHRBZnRlclBhc3RpbmcgPSBpbmRleFdoZXJlUGFzdGVkVGV4dEhhc0JlZW5JbnNlcnRlZCArIHBhc3RlZFRleHQubGVuZ3RoOyAvLyBJIG11c3Qgbm90IGNvdW50IHRoZSBjaGFyYWN0ZXJzIHRoYXQgaGF2ZSBiZWVuIHJlbW92ZWQgZnJvbSB0aGUgcGFzdGVkIHRleHQgKGllLiAnLicpXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChyaWdodFBhcnQgPT09ICcnKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSB1c2VyIHNlbGVjdGVkIGZyb20gdGhlIGNhcmV0IHBvc2l0aW9uIHRvIHRoZSBlbmQgb2YgdGhlIGlucHV0IChvbiB0aGUgZmFyIHJpZ2h0KVxuICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZyA9IEF1dG9OdW1lcmljSGVscGVyLmNvbnZlcnRDaGFyYWN0ZXJDb3VudFRvSW5kZXhQb3NpdGlvbihBdXRvTnVtZXJpY0hlbHBlci5jb3VudE51bWJlckNoYXJhY3RlcnNPblRoZUNhcmV0TGVmdFNpZGUoaW5pdGlhbEZvcm1hdHRlZFZhbHVlLCBzZWxlY3Rpb25TdGFydCwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKSkgKyBwYXN0ZWRUZXh0Lmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5lZ2F0aXZlUGFzdGVPbk5lZ2F0aXZlTnVtYmVyKSBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZysrO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFVzdWFsIGNhc2VcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5kZXhTZWxlY3Rpb25FbmRJblJhd1ZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuY29udmVydENoYXJhY3RlckNvdW50VG9JbmRleFBvc2l0aW9uKEF1dG9OdW1lcmljSGVscGVyLmNvdW50TnVtYmVyQ2hhcmFjdGVyc09uVGhlQ2FyZXRMZWZ0U2lkZShpbml0aWFsRm9ybWF0dGVkVmFsdWUsIHNlbGVjdGlvbkVuZCwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSGVyZSBJIG11c3Qgbm90IGNvdW50IHRoZSBjaGFyYWN0ZXJzIHRoYXQgaGF2ZSBiZWVuIHJlbW92ZWQgZnJvbSB0aGUgcGFzdGVkIHRleHQgKGllLiAnLicpLCBvciB0aGUgdGhvdXNhbmQgc2VwYXJhdG9ycyBpbiB0aGUgaW5pdGlhbCBzZWxlY3RlZCB0ZXh0XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNlbGVjdGVkVGV4dCA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZShldmVudFRhcmdldCkuc2xpY2Uoc2VsZWN0aW9uU3RhcnQsIHNlbGVjdGlvbkVuZCk7XG4gICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nID0gaW5kZXhTZWxlY3Rpb25FbmRJblJhd1ZhbHVlIC0gc2VsZWN0aW9uU2l6ZSArIEF1dG9OdW1lcmljSGVscGVyLmNvdW50Q2hhckluVGV4dCh0aGlzLnNldHRpbmdzLmRpZ2l0R3JvdXBTZXBhcmF0b3IsIHNlbGVjdGVkVGV4dCkgKyBwYXN0ZWRUZXh0Lmxlbmd0aDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBNb2RpZnkgdGhlIGNhcmV0IHBvc2l0aW9uIGZvciBzcGVjaWFsIGNhc2VzLCBvbmx5IGlmIHRoZSB3aG9sZSBpbnB1dCBoYXMgbm90IGJlZW4gc2VsZWN0ZWRcbiAgICAgICAgICAgICAgICBpZiAoaXNQYXN0ZU5lZ2F0aXZlQW5kSW5pdGlhbFZhbHVlSXNQb3NpdGl2ZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgcGFzdGVkIHZhbHVlIGhhcyBhIG5lZ2F0aXZlIHNpZ24gKCctJyksIGJ1dCB0aGUgaW5pdGlhbCB2YWx1ZSBkb2VzIG5vdCwgb2Zmc2V0IHRoZSBpbmRleCBieSBvbmVcbiAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbk9uSW5pdGlhbFRleHRBZnRlclBhc3RpbmcrKztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAobGVmdFBhcnRDb250YWluZWRBRG90KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGEgZG90IGhhcyBiZWVuIHJlbW92ZWQgZm9yIHRoZSBwYXJ0IG9uIHRoZSBsZWZ0IG9mIHRoZSBjYXJldCwgd2UgZGVjcmVtZW50IHRoZSBjYXJldCBpbmRleCBwb3NpdGlvblxuICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZy0tO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIDUuIENoZWNrIGlmIHRoZSByZXN1bHQgaXMgYSB2YWxpZCBudW1iZXIsIGlmIG5vdCwgZHJvcCB0aGUgcGFzdGUgYW5kIGRvIG5vdGhpbmcuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdW1iZXIocmVzdWx0KSB8fCByZXN1bHQgPT09ICcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5vbkludmFsaWRQYXN0ZSA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS5lcnJvcikge1xuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBwYXN0ZWQgdmFsdWUgJyR7cmF3UGFzdGVkVGV4dH0nIHdvdWxkIHJlc3VsdCBpbnRvIGFuIGludmFsaWQgY29udGVudCAnJHtyZXN1bHR9Jy5gKTsgLy9UT0RPIFNob3VsZCB3ZSBzZW5kIGEgd2FybmluZyBpbnN0ZWFkIG9mIHRocm93aW5nIGFuIGVycm9yP1xuICAgICAgICAgICAgICAgIC8vVE9ETyBUaGlzIGlzIG5vdCBEUlkgOyByZWZhY3RvciB3aXRoIGFib3ZlXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyA2LiBJZiBpdCdzIGEgdmFsaWQgbnVtYmVyLCBjaGVjayBpZiBpdCBmYWxscyBpbnNpZGUgdGhlIG1pbmltdW0gYW5kIG1heGltdW0gdmFsdWUuIElmIHRoaXMgZmFpbHMsIG1vZGlmeSB0aGUgdmFsdWUgZm9sbG93aW5nIHRoaXMgcHJvY2VkdXJlIDpcbiAgICAgICAgLypcbiAgICAgICAgICogSWYgJ2Vycm9yJyAodGhpcyBpcyB0aGUgZGVmYXVsdCkgOlxuICAgICAgICAgKiAgICAgIC0gTm9ybWFsIHBhc3RlIGJlaGF2aW9yLlxuICAgICAgICAgKiAgICAgIC0gVHJ5IHRvIHNldCB0aGUgbmV3IHZhbHVlLCBpZiBpdCBmYWlscywgdGhlbiB0aHJvdyBhbiBlcnJvciBpbiB0aGUgY29uc29sZS5cbiAgICAgICAgICogICAgICAtIERvIG5vdCBjaGFuZ2UgdGhlIGlucHV0IHZhbHVlLCBkbyBub3QgY2hhbmdlIHRoZSBjdXJyZW50IHNlbGVjdGlvbi5cbiAgICAgICAgICogSWYgJ2lnbm9yZScgOlxuICAgICAgICAgKiAgICAgIC0gTm9ybWFsIHBhc3RlIGJlaGF2aW9yLlxuICAgICAgICAgKiAgICAgIC0gVHJ5IHRvIHNldCB0aGUgbmV3IHZhbHVlLCBpZiBpdCBmYWlscywgZG8gbm90aGluZyBtb3JlLlxuICAgICAgICAgKiAgICAgIC0gRG8gbm90IGNoYW5nZSB0aGUgaW5wdXQgdmFsdWUsIGRvIG5vdCBjaGFuZ2UgdGhlIGN1cnJlbnQgc2VsZWN0aW9uLlxuICAgICAgICAgKiBJZiAnY2xhbXAnIDpcbiAgICAgICAgICogICAgICAtIE5vcm1hbCBwYXN0ZSBiZWhhdmlvci5cbiAgICAgICAgICogICAgICAtIFRyeSB0byBzZXQgdGhlIG5ldyB2YWx1ZSwgaWYgaXQgZmFpbHMsIHNldCB0aGUgdmFsdWUgdG8gdGhlIG1pbmltdW0gb3IgbWF4aW11bSBsaW1pdCwgd2hpY2hldmVyIGlzIGNsb3Nlc3QgdG8gdGhlXG4gICAgICAgICAqICAgICAgICBwYXN0ZSByZXN1bHQuXG4gICAgICAgICAqICAgICAgLSBDaGFuZ2UgdGhlIGNhcmV0IHBvc2l0aW9uIHRvIGJlIHBvc2l0aW9uZWQgb24gdGhlIGxlZnQgaGFuZCBzaWRlIG9mIHRoZSBkZWNpbWFsIGNoYXJhY3Rlci5cbiAgICAgICAgICogSWYgJ3RydW5jYXRlJyA6XG4gICAgICAgICAqICAgICAgLSBUcnVuY2F0ZSBwYXN0ZSBiZWhhdmlvci5cbiAgICAgICAgICogICAgICAtIFRyeSB0byBzZXQgdGhlIG5ldyB2YWx1ZSwgdW50aWwgaXQgZmFpbHMgKGlmIHRoZSByZXN1bHQgaXMgb3V0IG9mIHRoZSBtaW4gYW5kIG1heCB2YWx1ZSBsaW1pdHMpLlxuICAgICAgICAgKiAgICAgIC0gRHJvcCB0aGUgcmVtYWluaW5nIG5vbi1wYXN0ZWQgbnVtYmVycywgYW5kIGtlZXAgdGhlIGxhc3Qga25vd24gbm9uLWZhaWxpbmcgcmVzdWx0LlxuICAgICAgICAgKiAgICAgIC0gQ2hhbmdlIHRoZSBjYXJldCBwb3NpdGlvbiB0byBiZSBwb3NpdGlvbmVkIGFmdGVyIHRoZSBsYXN0IHBhc3RlZCBjaGFyYWN0ZXIuXG4gICAgICAgICAqIElmICdyZXBsYWNlJyA6XG4gICAgICAgICAqICAgICAgLSBSZXBsYWNlIHBhc3RlIGJlaGF2aW9yLlxuICAgICAgICAgKiAgICAgIC0gVHJ5IHRvIHNldCB0aGUgbmV3IHZhbHVlLCB1bnRpbCBpdCBmYWlscyAoaWYgdGhlIHJlc3VsdCBpcyBvdXQgb2YgdGhlIG1pbiBhbmQgbWF4IHZhbHVlIGxpbWl0cykuXG4gICAgICAgICAqICAgICAgLSBUaGVuIHRyeSB0byByZXBsYWNlIGFzIG1hbnkgbnVtYmVycyBhcyBwb3NzaWJsZSB3aXRoIHRoZSBwYXN0ZWQgb25lcy4gT25jZSBpdCBmYWlscywga2VlcCB0aGUgbGFzdCBrbm93biBub24tZmFpbGluZyByZXN1bHQuXG4gICAgICAgICAqICAgICAgLSBDaGFuZ2UgdGhlIGNhcmV0IHBvc2l0aW9uIHRvIGJlIHBvc2l0aW9uZWQgYWZ0ZXIgdGhlIGxhc3QgcGFzdGVkIGNoYXJhY3Rlci5cbiAgICAgICAgICovXG4gICAgICAgIGxldCB2YWx1ZUhhc0JlZW5TZXQgPSBmYWxzZTtcbiAgICAgICAgbGV0IHZhbHVlSGFzQmVlbkNsYW1wZWQgPSBmYWxzZTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHRoaXMuc2V0KHJlc3VsdCk7XG4gICAgICAgICAgICB2YWx1ZUhhc0JlZW5TZXQgPSB0cnVlO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgbGV0IGNsYW1wZWRWYWx1ZTtcbiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5zZXR0aW5ncy5vbkludmFsaWRQYXN0ZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS5jbGFtcDpcbiAgICAgICAgICAgICAgICAgICAgY2xhbXBlZFZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuY2xhbXBUb1JhbmdlTGltaXRzKHJlc3VsdCwgdGhpcy5zZXR0aW5ncyk7XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldChjbGFtcGVkVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgRmF0YWwgZXJyb3I6IFVuYWJsZSB0byBzZXQgdGhlIGNsYW1wZWQgdmFsdWUgJyR7Y2xhbXBlZFZhbHVlfScuYCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YWx1ZUhhc0JlZW5DbGFtcGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWVIYXNCZWVuU2V0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gY2xhbXBlZFZhbHVlOyAvLyBUaGlzIGlzIHVzZWQgb25seSBmb3Igc2V0dGluZyB0aGUgY2FyZXQgcG9zaXRpb24gbGF0ZXJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLmVycm9yOlxuICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS50cnVuY2F0ZTpcbiAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUucmVwbGFjZTpcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhyb3cgYW4gZXJyb3IgbWVzc2FnZVxuICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgcGFzdGVkIHZhbHVlICcke3Jhd1Bhc3RlZFRleHR9JyByZXN1bHRzIGluIGEgdmFsdWUgJyR7cmVzdWx0fScgdGhhdCBpcyBvdXRzaWRlIG9mIHRoZSBtaW5pbXVtIFske3RoaXMuc2V0dGluZ3MubWluaW11bVZhbHVlfV0gYW5kIG1heGltdW0gWyR7dGhpcy5zZXR0aW5ncy5tYXhpbXVtVmFsdWV9XSB2YWx1ZSByYW5nZS5gKTtcbiAgICAgICAgICAgICAgICAvLyBmYWxscyB0aHJvdWdoXG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLmlnbm9yZTpcbiAgICAgICAgICAgICAgICAvLyBEbyBub3RoaW5nXG4gICAgICAgICAgICAgICAgLy8gZmFsbHMgdGhyb3VnaFxuICAgICAgICAgICAgICAgIGRlZmF1bHQgOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm47IC8vIC4uLmFuZCBub3RoaW5nIGVsc2Ugc2hvdWxkIGJlIGNoYW5nZWRcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIDcuIFRoZW4gbGFzdGx5LCBzZXQgdGhlIGNhcmV0IHBvc2l0aW9uIGF0IHRoZSByaWdodCBsb2dpY2FsIHBsYWNlXG4gICAgICAgIGNvbnN0IHRhcmdldFZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKGV2ZW50VGFyZ2V0KTtcbiAgICAgICAgbGV0IGNhcmV0UG9zaXRpb25JbkZvcm1hdHRlZE51bWJlcjtcbiAgICAgICAgaWYgKHZhbHVlSGFzQmVlblNldCkge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLnNldHRpbmdzLm9uSW52YWxpZFBhc3RlKSB7XG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLmNsYW1wOlxuICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWVIYXNCZWVuQ2xhbXBlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQuc3VmZml4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFNlbGVjdGlvbihldmVudFRhcmdldCwgdGFyZ2V0VmFsdWUubGVuZ3RoIC0gdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbC5sZW5ndGgpOyAvLyBUaGlzIHB1dHMgdGhlIGNhcmV0IG9uIHRoZSByaWdodCBvZiB0aGUgbGFzdCBkZWNpbWFsIHBsYWNlXG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRTZWxlY3Rpb24oZXZlbnRUYXJnZXQsIHRhcmdldFZhbHVlLmxlbmd0aCk7IC8vIC4uYW5kIHRoaXMgb24gdGhlIGZhciByaWdodFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfSAvLyBlbHNlIGlmIHRoZSB2YWx1ZSBoYXMgbm90IGJlZW4gY2xhbXBlZCwgdGhlIGRlZmF1bHQgYmVoYXZpb3IgaXMgdXNlZC4uLlxuICAgICAgICAgICAgICAgIC8vIGZhbGxzIHRocm91Z2hcbiAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUuZXJyb3I6XG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLmlnbm9yZTpcbiAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUudHJ1bmNhdGU6XG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLnJlcGxhY2U6XG4gICAgICAgICAgICAgICAgZGVmYXVsdCA6XG4gICAgICAgICAgICAgICAgICAgIC8vIFdoZW5ldmVyIG9uZSBvciBtdWx0aXBsZSBjaGFyYWN0ZXJzIGFyZSBwYXN0ZWQsIHRoaXMgbWVhbnMgd2UgaGF2ZSB0byBtYW5hZ2UgdGhlIHBvdGVudGlhbCB0aG91c2FuZCBzZXBhcmF0b3JzIHRoYXQgY291bGQgYmUgYWRkZWQgYnkgdGhlIGZvcm1hdHRpbmdcbiAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbkluRm9ybWF0dGVkTnVtYmVyID0gQXV0b051bWVyaWNIZWxwZXIuZmluZENhcmV0UG9zaXRpb25JbkZvcm1hdHRlZE51bWJlcihyZXN1bHQsIGNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nLCB0YXJnZXRWYWx1ZSwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKTtcbiAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFNlbGVjdGlvbihldmVudFRhcmdldCwgY2FyZXRQb3NpdGlvbkluRm9ybWF0dGVkTnVtYmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIDguIFdlIG1ha2Ugc3VyZSB3ZSBzZW5kIGFuIGlucHV0IGV2ZW50IG9ubHkgaWYgdGhlIHJlc3VsdCBpcyBkaWZmZXJlbnQgdGhhbiB0aGUgaW5pdGlhbCB2YWx1ZSBiZWZvcmUgdGhlIHBhc3RlXG4gICAgICAgIGlmICh2YWx1ZUhhc0JlZW5TZXQgJiYgaW5pdGlhbEZvcm1hdHRlZFZhbHVlICE9PSB0YXJnZXRWYWx1ZSkge1xuICAgICAgICAgICAgLy8gT24gYSAnbm9ybWFsJyBub24tYXV0b051bWVyaWMgaW5wdXQsIGFuIGBpbnB1dGAgZXZlbnQgaXMgc2VudCB3aGVuIGEgcGFzdGUgaXMgZG9uZS4gV2UgbWltaWMgdGhhdC5cbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMubmF0aXZlLmlucHV0LCBldmVudFRhcmdldCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXaGVuIGZvY3VzaW5nIG91dCBvZiB0aGUgaW5wdXQsIHdlIGNoZWNrIGlmIHRoZSB2YWx1ZSBoYXMgY2hhbmdlZCwgYW5kIGlmIGl0IGhhcywgdGhlbiB3ZSBzZW5kIGEgYGNoYW5nZWAgZXZlbnQgKHNpbmNlIHRoZSBuYXRpdmUgb25lIHdvdWxkIGhhdmUgYmVlbiBwcmV2ZW50ZWQgYnkgYGUucHJldmVudERlZmF1bHQoKWAgY2FsbGVkIGluIHRoZSBvdGhlciBldmVudCBsaXN0ZW5lcnMpLlxuICAgICAqIFdlIGFsc28gdXBkYXRlIHRoZSBpbmZvIG9mIHRoZSBmb2N1c2VkIHN0YXRlIGluIHRoZSBgdGhpcy5pc0ZvY3VzZWRgIHZhcmlhYmxlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqL1xuICAgIF9vbkJsdXIoZSkge1xuICAgICAgICAvLyBLZWVwIHRyYWNrIGlmIHRoZSBlbGVtZW50IGlzIGN1cnJlbnRseSBmb2N1c2VkXG4gICAgICAgIHRoaXMuaXNGb2N1c2VkID0gZmFsc2U7XG4gICAgICAgIC8vIEtlZXAgdHJhY2sgaWYgdGhlIHVzZXIgaXMgY3VycmVudGx5IGVkaXRpbmcgdGhlIGVsZW1lbnRcbiAgICAgICAgdGhpcy5pc0VkaXRpbmcgPSBmYWxzZTtcblxuICAgICAgICAvLyBTZW5kIGEgYGNoYW5nZWAgZXZlbnQgaWYgdGhlIHJhdyB2YWx1ZSBoYXMgYmVlbiBjaGFuZ2VkIHNpbmNlIHRoZSBsYXN0IGZvY3VzIG9yICdlbnRlcicgdmFsaWRhdGlvblxuICAgICAgICBpZiAodGhpcy5yYXdWYWx1ZSAhPT0gdGhpcy5yYXdWYWx1ZU9uRm9jdXMpIHtcbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMubmF0aXZlLmNoYW5nZSwgZS50YXJnZXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5yYXdWYWx1ZU9uRm9jdXMgPSB2b2lkKDApOyAvLyBSZXNldCB0aGUgdHJhY2tlclxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXIgZm9yICd3aGVlbCcgZXZlbnRcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7V2hlZWxFdmVudH0gZVxuICAgICAqL1xuICAgIF9vbldoZWVsKGUpIHtcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MucmVhZE9ubHkgfHwgdGhpcy5kb21FbGVtZW50LnJlYWRPbmx5IHx8IHRoaXMuZG9tRWxlbWVudC5kaXNhYmxlZCkge1xuICAgICAgICAgICAgLy8gRG8gbm90IGFsbG93IHNjcm9sbGluZyBpbiBhIHJlYWRvbmx5IGVsZW1lbnQgKGZpeCBpc3N1ZSAjNTQxKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MubW9kaWZ5VmFsdWVPbldoZWVsKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy53aGVlbE9uID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLndoZWVsT24uZm9jdXMpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc0ZvY3VzZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFlLnNoaWZ0S2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLndoZWVsQWN0aW9uKGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlLnNoaWZ0S2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2hlZWxBY3Rpb24oZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNldHRpbmdzLndoZWVsT24gPT09IEF1dG9OdW1lcmljLm9wdGlvbnMud2hlZWxPbi5ob3Zlcikge1xuICAgICAgICAgICAgICAgIGlmICghZS5zaGlmdEtleSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLndoZWVsQWN0aW9uKGUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE5vdGU6IFdoZW4gbm90IGBkZWZhdWx0UHJldmVudGVkYCwgU2hpZnQgKyBtb3VzZSB3aGVlbCBpcyByZXNlcnZlZCBieSB0aGUgYnJvd3NlcnMgZm9yIGhvcml6b250YWwgc2Nyb2xsaW5nLlxuICAgICAgICAgICAgICAgICAgICAvLyBIZW5jZSwgdXNpbmcgdGhlIFNoaWZ0IGtleSB3aXRoIHRoZSBgd2hlZWxPbmAgJ2hvdmVyJyBvcHRpb24gd2lsbCBvbmx5IHNjcm9sbCB0aGUgcGFnZSBpZiB3ZSBwcmV2ZW50IHRoZSBkZWZhdWx0IGJlaGF2aW9yXG4gICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTsgLy8gRG8gbm90IHNjcm9sbCBob3Jpem9udGFsbHlcblxuICAgICAgICAgICAgICAgICAgICAvLyBTY3JvbGwgdmVydGljYWxseVxuICAgICAgICAgICAgICAgICAgICB3aW5kb3cuc2Nyb2xsQnkoMCwgQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZVN0cmljdChTdHJpbmcoZS5kZWx0YVkpKT8tNTA6NTApOyAvLyBgZS5kZWx0YVlgIGlzIHVzdWFsbHkgdG9vIHNtYWxsIGNvbXBhcmVkIHRvIGhvdyB0aGUgcGFnZSBpcyBzY3JvbGxlZC4gVGhhdCdzIHdoeSB3ZSB1c2UgYSBmaXhlZCBvZmZzZXQuXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKCdVbmtub3duIGB3aGVlbE9uYCBvcHRpb24uJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbmNyZW1lbnQgb3IgZGVjcmVtZW50IHRoZSBlbGVtZW50IHZhbHVlIGFjY29yZGluZyB0byB0aGUgYHdoZWVsU3RlcGAgb3B0aW9uIGNob3NlblxuICAgICAqXG4gICAgICogQHBhcmFtIHtXaGVlbEV2ZW50fSBlIFRoZSBgd2hlZWxgIGV2ZW50XG4gICAgICovXG4gICAgd2hlZWxBY3Rpb24oZSkge1xuICAgICAgICB0aGlzLmlzV2hlZWxFdmVudCA9IHRydWU7IC8vIEtlZXAgdGhlIGluZm8gdGhhdCB3ZSBhcmUgY3VycmVudGx5IG1hbmFnaW5nIGEgbW91c2Ugd2hlZWwgZXZlbnRcblxuICAgICAgICAvLyAwKSBGaXJzdCwgc2F2ZSB0aGUgY2FyZXQgcG9zaXRpb24gc28gd2UgY2FuIHNldCBpdCBiYWNrIG9uY2UgdGhlIHZhbHVlIGhhcyBiZWVuIGNoYW5nZWRcbiAgICAgICAgY29uc3Qgc2VsZWN0aW9uU3RhcnQgPSBlLnRhcmdldC5zZWxlY3Rpb25TdGFydCB8fCAwO1xuICAgICAgICBjb25zdCBzZWxlY3Rpb25FbmQgPSBlLnRhcmdldC5zZWxlY3Rpb25FbmQgfHwgMDtcblxuICAgICAgICAvLyAxKSBHZXQgdGhlIHVuZm9ybWF0dGVkIHZhbHVlXG4gICAgICAgIGNvbnN0IGN1cnJlbnRVbmZvcm1hdHRlZFZhbHVlID0gdGhpcy5yYXdWYWx1ZTtcblxuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KGN1cnJlbnRVbmZvcm1hdHRlZFZhbHVlKSkge1xuICAgICAgICAgICAgLy8gSWYgYnkgZGVmYXVsdCB0aGUgaW5wdXQgaXMgZW1wdHksIHN0YXJ0IGF0ICcwJ1xuICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MubWluaW11bVZhbHVlID4gMCB8fCB0aGlzLnNldHRpbmdzLm1heGltdW1WYWx1ZSA8IDApIHtcbiAgICAgICAgICAgICAgICAvLyBvciBpZiAnMCcgaXMgbm90IGJldHdlZW4gbWluIGFuZCBtYXggdmFsdWUsICdtaW5pbXVtVmFsdWUnIGlmIHRoZSB1c2VyIGRvZXMgYSB3aGVlbHVwLCAnbWF4aW11bVZhbHVlJyBpZiB0aGUgdXNlciBkb2VzIGEgd2hlZWxkb3duXG4gICAgICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzV2hlZWxVcEV2ZW50KGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuc2V0dGluZ3MubWluaW11bVZhbHVlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNXaGVlbERvd25FdmVudChlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLnNldHRpbmdzLm1heGltdW1WYWx1ZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZXZlbnQgaXMgbm90IGEgJ3doZWVsJyBldmVudC5gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQgPSBjdXJyZW50VW5mb3JtYXR0ZWRWYWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlc3VsdCA9ICtyZXN1bHQ7IC8vIFR5cGVjYXN0IHRvIGEgbnVtYmVyIG5lZWRlZCBmb3IgdGhlIGZvbGxvd2luZyBhZGRpdGlvbi9zdWJ0cmFjdGlvblxuXG4gICAgICAgIC8vIDIpIEluY3JlbWVudC9EZWNyZW1lbnQgdGhlIHZhbHVlXG4gICAgICAgIC8vIEJ1dCBmaXJzdCwgY2hvb3NlIHRoZSBpbmNyZW1lbnQvZGVjcmVtZW50IG1ldGhvZCA7IGZpeGVkIG9yIHByb2dyZXNzaXZlXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bWJlcih0aGlzLnNldHRpbmdzLndoZWVsU3RlcCkpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0ZXAgPSArdGhpcy5zZXR0aW5ncy53aGVlbFN0ZXA7IC8vIFR5cGVjYXN0IHRvIGEgbnVtYmVyIG5lZWRlZCBmb3IgdGhlIGZvbGxvd2luZyBhZGRpdGlvbi9zdWJ0cmFjdGlvblxuICAgICAgICAgICAgLy8gRml4ZWQgbWV0aG9kXG4gICAgICAgICAgICAvLyBUaGlzIGlzIHRoZSBzaW1wbGVzdCBtZXRob2QsIHdoZXJlIGEgZml4ZWQgb2Zmc2V0IGluIGFkZGVkL3N1YnRyYWN0ZWQgZnJvbSB0aGUgY3VycmVudCB2YWx1ZVxuICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzV2hlZWxVcEV2ZW50KGUpKSB7IC8vIEluY3JlbWVudFxuICAgICAgICAgICAgICAgIHJlc3VsdCArPSBzdGVwO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc1doZWVsRG93bkV2ZW50KGUpKSB7IC8vIERlY3JlbWVudFxuICAgICAgICAgICAgICAgIHJlc3VsdCAtPSBzdGVwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gUHJvZ3Jlc3NpdmUgbWV0aG9kXG4gICAgICAgICAgICAvLyBGb3IgdGhpcyBtZXRob2QsIHdlIGNhbGN1bGF0ZSBhbiBvZmZzZXQgdGhhdCBpcyBpbiByZWxhdGlvbiB0byB0aGUgc2l6ZSBvZiB0aGUgY3VycmVudCBudW1iZXIgKHVzaW5nIG9ubHkgdGhlIGludGVnZXIgcGFydCBzaXplKS5cbiAgICAgICAgICAgIC8vIFRoZSBiaWdnZXIgdGhlIG51bWJlciwgdGhlIGJpZ2dlciB0aGUgb2Zmc2V0ICh1c3VhbGx5IHRoZSBudW1iZXIgY291bnQgaW4gdGhlIGludGVnZXIgcGFydCBtaW51cyAzLCBleGNlcHQgZm9yIHNtYWxsIG51bWJlcnMgd2hlcmUgYSBkaWZmZXJlbnQgYmVoYXZpb3IgaXMgYmV0dGVyIGZvciB0aGUgdXNlciBleHBlcmllbmNlKS5cbiAgICAgICAgICAgIC8vVE9ETyBLbm93biBsaW1pdGF0aW9uIDogVGhlIHByb2dyZXNzaXZlIG1ldGhvZCBkb2VzIG5vdCBwbGF5IHdlbGwgd2l0aCBudW1iZXJzIGJldHdlZW4gMCBhbmQgMSB3aGVyZSB0byBtb2RpZnkgdGhlIGRlY2ltYWwgcGxhY2VzIHRoZSByYXdWYWx1ZSBmaXJzdCBoYXMgdG8gZ28gZnJvbSAnMScgdG8gJzAnXG4gICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNXaGVlbFVwRXZlbnQoZSkpIHsgLy8gSW5jcmVtZW50XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNIZWxwZXIuYWRkQW5kUm91bmRUb05lYXJlc3RBdXRvKHJlc3VsdCwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc1doZWVsRG93bkV2ZW50KGUpKSB7IC8vIERlY3JlbWVudFxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljSGVscGVyLnN1YnRyYWN0QW5kUm91bmRUb05lYXJlc3RBdXRvKHJlc3VsdCwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gMykgU2V0IHRoZSBuZXcgdmFsdWUgc28gaXQgZ2V0cyBmb3JtYXR0ZWRcbiAgICAgICAgLy8gRmlyc3QgY2xhbXAgdGhlIHJlc3VsdCBpZiBuZWVkZWRcbiAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNIZWxwZXIuY2xhbXBUb1JhbmdlTGltaXRzKHJlc3VsdCwgdGhpcy5zZXR0aW5ncyk7XG4gICAgICAgIGlmIChyZXN1bHQgIT09ICtjdXJyZW50VW5mb3JtYXR0ZWRWYWx1ZSkge1xuICAgICAgICAgICAgLy8gT25seSAnc2V0JyB0aGUgdmFsdWUgaWYgaXQgaGFzIGNoYW5nZWQuIEZvciBpbnN0YW5jZSAnc2V0JyBzaG91bGQgbm90IGhhcHBlbiBpZiB0aGUgdXNlciBoaXRzIGEgbGltaXQgYW5kIGNvbnRpbnVlIHRvIHRyeSB0byBnbyBwYXN0IGl0IHNpbmNlIHdlIGNsYW1wIHRoZSB2YWx1ZS5cbiAgICAgICAgICAgIHRoaXMuc2V0KHJlc3VsdCk7XG5cbiAgICAgICAgICAgIC8vIFNpbmNlIHdlIGNoYW5nZWQgdGhlIGlucHV0IHZhbHVlLCB3ZSBzZW5kIGEgbmF0aXZlIGBpbnB1dGAgZXZlbnRcbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMubmF0aXZlLmlucHV0LCBlLnRhcmdldCk7XG4gICAgICAgIH1cblxuICAgICAgICAvL1hYWCBEbyBub3QgcHJldmVudCBpZiB0aGUgdmFsdWUgaXMgbm90IG1vZGlmaWVkPyBGcm9tIGEgVVggcG9pbnQgb2YgdmlldywgcHJldmVudGluZyB0aGUgd2hlZWwgZXZlbnQgd2hlbiB0aGUgdXNlciB1c2UgaXQgb24gdG9wIG9mIGFuIGF1dG9OdW1lcmljIGVsZW1lbnQgc2hvdWxkIGFsd2F5cyBiZSBkb25lLCBldmVuIGlmIHRoZSB2YWx1ZSBkb2VzIG5vdCBjaGFuZ2UuIFBlcmhhcHMgdGhhdCBjb3VsZCBhZmZlY3Qgb3RoZXIgc2NyaXB0cyByZWx5aW5nIG9uIHRoaXMgZXZlbnQgdG8gYmUgc2VudCB0aG91Z2guXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTsgLy8gV2UgcHJldmVudCB0aGUgcGFnZSB0byBzY3JvbGwgd2hpbGUgd2UgaW5jcmVtZW50L2RlY3JlbWVudCB0aGUgdmFsdWVcblxuICAgICAgICAvLyA0KSBGaW5hbGx5LCB3ZSBzZXQgYmFjayB0aGUgY2FyZXQgcG9zaXRpb24vc2VsZWN0aW9uXG4gICAgICAgIC8vIFRoZXJlIGlzIG5vIG5lZWQgdG8gdGFrZSBpbnRvIGFjY291bnQgdGhlIGZhY3QgdGhhdCB0aGUgbnVtYmVyIGNvdW50IGNvdWxkIGJlIGRpZmZlcmVudCBhdCB0aGUgZW5kIG9mIHRoZSB3aGVlbCBldmVudCA7IGl0IHdvdWxkIGJlIHRvbyBjb21wbGV4IGFuZCBtb3N0IG9mIHRoZSB0aW1lIHVucmVsaWFibGVcbiAgICAgICAgdGhpcy5fc2V0U2VsZWN0aW9uKHNlbGVjdGlvblN0YXJ0LCBzZWxlY3Rpb25FbmQpO1xuXG4gICAgICAgIHRoaXMuaXNXaGVlbEV2ZW50ID0gZmFsc2U7IC8vIFNldCBiYWNrIHRoZSBtb3VzZSB3aGVlbCBpbmRpY2F0b3IgdG8gaXRzIGRlZmF1bHRcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVyIGZvciAnZHJvcCcgZXZlbnRcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RHJhZ0V2ZW50fSBlXG4gICAgICovXG4gICAgX29uRHJvcChlKSB7XG4gICAgICAgIC8vIE5vdGU6IGJ5IGRlZmF1bHQgYnJvd3NlcnMgYWxyZWFkeSBwcmV2ZW50IHRoZSBkcm9wIG9uIHJlYWRPbmx5IGFuZCBkaXNhYmxlZCBlbGVtZW50c1xuICAgICAgICB0aGlzLmlzRHJvcEV2ZW50ID0gdHJ1ZTtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBsZXQgZm9ybWF0O1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNJRTExKCkpIHtcbiAgICAgICAgICAgIGZvcm1hdCA9ICd0ZXh0JztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZvcm1hdCA9ICd0ZXh0L3BsYWluJztcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGRyb3BwZWRUZXh0ID0gZS5kYXRhVHJhbnNmZXIuZ2V0RGF0YShmb3JtYXQpO1xuICAgICAgICBjb25zdCBjbGVhbmVkVmFsdWUgPSB0aGlzLnVuZm9ybWF0T3RoZXIoZHJvcHBlZFRleHQpO1xuICAgICAgICB0aGlzLnNldChjbGVhbmVkVmFsdWUpO1xuICAgICAgICB0aGlzLmlzRHJvcEV2ZW50ID0gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlciBmb3IgJ3N1Ym1pdCcgZXZlbnRzIGhhcHBlbmluZyBvbiB0aGUgcGFyZW50IDxmb3JtPiBlbGVtZW50LlxuICAgICAqIElmIGB1bmZvcm1hdE9uU3VibWl0YCBpcyBzZXQgdG8gYHRydWVgLCB0aGUgZWxlbWVudCB2YWx1ZSBpcyBmaXJzdCB1bmZvcm1hdHRlZCBiZWZvcmUgdGhlIGZvcm0gaXMgc3VibWl0dGVkLlxuICAgICAqXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgX29uRm9ybVN1Ym1pdCgpIHtcbiAgICAgICAgLy8gU2VhcmNoIGZvciBhbGwgdGhlIEF1dG9OdW1lcmljIGNoaWxkcmVuIG9mIHRoZSBmb3JtIGVsZW1lbnQgYW5kIGNhbGwgdGhlIGBfdW5mb3JtYXRPblN1Ym1pdCgpYCBmdW5jdGlvblxuICAgICAgICBjb25zdCBpbnB1dEVsZW1lbnRzID0gdGhpcy5fZ2V0Rm9ybUF1dG9OdW1lcmljQ2hpbGRyZW4odGhpcy5wYXJlbnRGb3JtKTtcbiAgICAgICAgY29uc3QgYU5FbGVtZW50cyA9IGlucHV0RWxlbWVudHMubWFwKGFORWxlbWVudCA9PiB0aGlzLmNvbnN0cnVjdG9yLmdldEF1dG9OdW1lcmljRWxlbWVudChhTkVsZW1lbnQpKTtcbiAgICAgICAgYU5FbGVtZW50cy5mb3JFYWNoKGFORWxlbWVudCA9PiBhTkVsZW1lbnQuX3VuZm9ybWF0T25TdWJtaXQoKSk7XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlciBmb3IgJ3Jlc2V0JyBldmVudHMgY2F1Z2h0IG9uIHRoZSBwYXJlbnQgPGZvcm0+IGVsZW1lbnQuXG4gICAgICogV2hlbiBzdWNoIGV2ZW50IGlzIGRldGVjdGVkLCB0aGVuIGV2ZXJ5IGNoaWxkIEF1dG9OdW1lcmljIGVsZW1lbnRzIG11c3QgZm9ybWF0IHRoZWlyIGRlZmF1bHQgdmFsdWUgdGhhdCB0aGUgYnJvd3NlciBpcyBmb3JjaW5nIHVwb24gdGhlbS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX29uRm9ybVJlc2V0KCkge1xuICAgICAgICBjb25zdCBpbnB1dEVsZW1lbnRzID0gdGhpcy5fZ2V0Rm9ybUF1dG9OdW1lcmljQ2hpbGRyZW4odGhpcy5wYXJlbnRGb3JtKTtcbiAgICAgICAgY29uc3QgYU5FbGVtZW50cyA9IGlucHV0RWxlbWVudHMubWFwKGFORWxlbWVudCA9PiB0aGlzLmNvbnN0cnVjdG9yLmdldEF1dG9OdW1lcmljRWxlbWVudChhTkVsZW1lbnQpKTtcbiAgICAgICAgLy8gVGVsbCBhbGwgdGhlIEF1dG9OdW1lcmljIGNoaWxkcmVuIHRvIGZvcm1hdCB0aGVpciBkZWZhdWx0IHZhbHVlXG4gICAgICAgIGFORWxlbWVudHMuZm9yRWFjaChhTkVsZW1lbnQgPT4ge1xuICAgICAgICAgICAgY29uc3QgdmFsID0gdGhpcy5fZ2V0RGVmYXVsdFZhbHVlKGFORWxlbWVudC5ub2RlKCkpO1xuICAgICAgICAgICAgLy8gYU5FbGVtZW50LnNldCh2YWwpOyAvL1hYWCBJZiBJIHVzZSB0aGF0IGxpbmUsIHRoZSBmb3JtYXQgaXMgZmlyc3QgY29ycmVjdGx5IGRvbmUsIGJ1dCB0aGUgZm9ybSByZXNldCBpcyBzdGlsbCBub3QgZmluaXNoZWQgYW5kIHdpbGwgb3ZlcndyaXRlIHRoZSBmb3JtYXR0aW5nLiBUaGlzIGlzIHdoeSB3ZSBuZWVkIHRvIHVzZSB0aGUgZm9sbG93aW5nIHNldFRpbWVvdXQgbGluZS5cbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gYU5FbGVtZW50LnNldCh2YWwpLCAwKTsgLy9YWFggVGhpcyBpcyBhbiB1Z2x5IGhhY2ssIGJ1dCBpdCBzZWVtcyB0byBiZSB0aGUgYWNjZXB0ZWQgYW5zd2VyIHRvIHRoaXMgcHJvYmxlbSAoaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzgxNTI5NjAvMjgzNDg5OCkuIFRoaXMgaXMgc2FkLiBEbyBub3RlIHRoYXQgSSB1c2UgJzBtcycgaGVyZSBzaW5jZSB1c2luZyBgc2V0VGltZW91dGAgd2lsbCBwdXNoIHRoYXQgY29kZSBvbiB0aGUgZXZlbnQgc3RhY2ssIGFuZCBhcyBzb29uIGFzIHRoZSByZXNldCB3aWxsIGJlIGZpbmlzaGVkLCB0aGlzIHdpbGwgYmUgcnVuIChzZWUgaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzIzOTg3MjgzLzI4MzQ4OTgpLlxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVbmZvcm1hdCB0aGUgZWxlbWVudCB2YWx1ZSBhY2NvcmRpbmcgdG8gdGhlIGB1bmZvcm1hdE9uU3VibWl0YCBvcHRpb25cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3VuZm9ybWF0T25TdWJtaXQoKSB7XG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLnVuZm9ybWF0T25TdWJtaXQpIHtcbiAgICAgICAgICAgIHRoaXMuX3NldEVsZW1lbnRWYWx1ZSh0aGlzLnJhd1ZhbHVlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExpc3RlbiBmb3IgdGhlIGBhbHRgIGtleSBrZXlkb3duIGV2ZW50IGdsb2JhbGx5LCBhbmQgaWYgdGhlIGV2ZW50IGlzIGNhdWdodCwgdW5mb3JtYXQgdGhlIEF1dG9OdW1lcmljIGVsZW1lbnQgdGhhdCBpcyBob3ZlcmVkIGJ5IHRoZSBtb3VzZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7S2V5Ym9hcmRFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX29uS2V5ZG93bkdsb2JhbChlKSB7XG4gICAgICAgIC8vVE9ETyBGaW5kIGEgd2F5IHRvIGtlZXAgdGhlIGNhcmV0IHBvc2l0aW9uIGJldHdlZW4gdGhlIGFsdCBrZXl1cC9rZXlkb3duIHN0YXRlc1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuY2hhcmFjdGVyKGUpID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5BbHQpIHtcbiAgICAgICAgICAgIGNvbnN0IGhvdmVyZWRFbGVtZW50ID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0SG92ZXJlZEVsZW1lbnQoKTtcbiAgICAgICAgICAgIGlmIChBdXRvTnVtZXJpYy5pc01hbmFnZWRCeUF1dG9OdW1lcmljKGhvdmVyZWRFbGVtZW50KSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGFuRWxlbWVudCA9IEF1dG9OdW1lcmljLmdldEF1dG9OdW1lcmljRWxlbWVudChob3ZlcmVkRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5fdW5mb3JtYXRBbHRIb3ZlcmVkKGFuRWxlbWVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMaXN0ZW4gZm9yIHRoZSBgYWx0YCBrZXkga2V5dXAgZXZlbnQgZ2xvYmFsbHksIGFuZCBpZiB0aGUgZXZlbnQgaXMgY2F1Z2h0LCByZWZvcm1hdCB0aGUgQXV0b051bWVyaWMgZWxlbWVudCB0aGF0IGlzIGhvdmVyZWQgYnkgdGhlIG1vdXNlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtLZXlib2FyZEV2ZW50fSBlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfb25LZXl1cEdsb2JhbChlKSB7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5jaGFyYWN0ZXIoZSkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkFsdCkge1xuICAgICAgICAgICAgY29uc3QgaG92ZXJlZEVsZW1lbnQgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRIb3ZlcmVkRWxlbWVudCgpO1xuICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljLmlzTWFuYWdlZEJ5QXV0b051bWVyaWMoaG92ZXJlZEVsZW1lbnQpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYW5FbGVtZW50ID0gQXV0b051bWVyaWMuZ2V0QXV0b051bWVyaWNFbGVtZW50KGhvdmVyZWRFbGVtZW50KTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnN0cnVjdG9yLl9yZWZvcm1hdEFsdEhvdmVyZWQoYW5FbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIERPTSBlbGVtZW50IGlzIHN1cHBvcnRlZCBieSBhdXRvTnVtZXJpYy5cbiAgICAgKiBBIHN1cHBvcnRlZCBlbGVtZW50IGlzIGFuIGVsZW1lbnQgd2hpdGVsaXN0ZWQgaW4gdGhlIGBhbGxvd2VkVGFnTGlzdGAuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9pc0VsZW1lbnRUYWdTdXBwb3J0ZWQoKSB7XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNFbGVtZW50KHRoaXMuZG9tRWxlbWVudCkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBET00gZWxlbWVudCBpcyBub3QgdmFsaWQsICR7dGhpcy5kb21FbGVtZW50fSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBBdXRvTnVtZXJpY0hlbHBlci5pc0luQXJyYXkodGhpcy5kb21FbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKSwgdGhpcy5hbGxvd2VkVGFnTGlzdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpbiB0aGUgRE9NIGVsZW1lbnQgaXMgYW4gPGlucHV0Pi5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2lzSW5wdXRFbGVtZW50KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kb21FbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ2lucHV0JztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBpbnB1dCB0eXBlIGlzIHN1cHBvcnRlZCBieSBBdXRvTnVtZXJpY1xuICAgICAqXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHRocm93c1xuICAgICAqL1xuICAgIF9pc0lucHV0VHlwZVN1cHBvcnRlZCgpIHtcbiAgICAgICAgcmV0dXJuICh0aGlzLmRvbUVsZW1lbnQudHlwZSA9PT0gJ3RleHQnIHx8XG4gICAgICAgICAgICAgICAgdGhpcy5kb21FbGVtZW50LnR5cGUgPT09ICdoaWRkZW4nIHx8XG4gICAgICAgICAgICAgICAgdGhpcy5kb21FbGVtZW50LnR5cGUgPT09ICd0ZWwnIHx8XG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KHRoaXMuZG9tRWxlbWVudC50eXBlKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgdGhlIERPTSBlbGVtZW50IGlzIHN1cHBvcnRlZCBieSBhdXRvTnVtZXJpYy5cbiAgICAgKiBBIHN1cHBvcnRlZCBlbGVtZW50IGlzIGVpdGhlciBhbiA8aW5wdXQ+IGVsZW1lbnQgd2l0aCB0aGUgY29ycmVjdCAndHlwZScgYXR0cmlidXRlLCBvciBhIHRhZyB3aGl0ZWxpc3RlZCBpbiB0aGUgYGFsbG93ZWRUYWdMaXN0YCBhcnJheS5cbiAgICAgKiBJZiB0aGUgY2hlY2sgZmFpbHMsIHRoaXMgbWV0aG9kIHRocm93cy5cbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGFsc28gc2V0cyB0aGUgaW5mbyBgdGhpcy5pc0lucHV0RWxlbWVudGAgd2hpY2gga2VlcCB0cmFja3MgaWYgdGhlIERPTSBlbGVtZW50IGlzIGFuIDxpbnB1dD4gb3Igbm90LCBhbmQgdGhlIGB0aGlzLmlzQ29udGVudEVkaXRhYmxlYCBpZiB0aGUgZWxlbWVudCBoYXMgdGhlIGBjb250ZW50ZWRpdGFibGVgIGF0dHJpYnV0ZSBzZXQgdG8gYHRydWVgIGluaXRpYWxseS5cbiAgICAgKlxuICAgICAqIEB0aHJvd3NcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9jaGVja0VsZW1lbnQoKSB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRFbGVtZW50VGFnID0gdGhpcy5kb21FbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKTtcblxuICAgICAgICBpZiAoIXRoaXMuX2lzRWxlbWVudFRhZ1N1cHBvcnRlZCgpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgPCR7Y3VycmVudEVsZW1lbnRUYWd9PiB0YWcgaXMgbm90IHN1cHBvcnRlZCBieSBhdXRvTnVtZXJpY2ApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuX2lzSW5wdXRFbGVtZW50KCkpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5faXNJbnB1dFR5cGVTdXBwb3J0ZWQoKSkge1xuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBpbnB1dCB0eXBlIFwiJHt0aGlzLmRvbUVsZW1lbnQudHlwZX1cIiBpcyBub3Qgc3VwcG9ydGVkIGJ5IGF1dG9OdW1lcmljYCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuaXNJbnB1dEVsZW1lbnQgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5pc0lucHV0RWxlbWVudCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5pc0NvbnRlbnRFZGl0YWJsZSA9IHRoaXMuZG9tRWxlbWVudC5oYXNBdHRyaWJ1dGUoJ2NvbnRlbnRlZGl0YWJsZScpICYmIHRoaXMuZG9tRWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2NvbnRlbnRlZGl0YWJsZScpID09PSAndHJ1ZSc7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb3JtYXRzIHRoZSBkZWZhdWx0IHZhbHVlIG9uIHBhZ2UgbG9hZC5cbiAgICAgKiBUaGlzIGlzIGNhbGxlZCBvbmx5IGlmIHRoZSBgZm9ybWF0T25QYWdlTG9hZGAgb3B0aW9uIGlzIHNldCB0byBgdHJ1ZWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd8bnVsbH0gZm9yY2VkSW5pdGlhbFZhbHVlIFRoZSB2YWx1ZSB0aGF0IHNob3VsZCBiZSB1c2VkIGZvciBpbml0aWFsaXphdGlvbiwgaW4gcGxhY2Ugb24gdGhlIGV2ZW50dWFsIGh0bWwgb25lXG4gICAgICovXG4gICAgX2Zvcm1hdERlZmF1bHRWYWx1ZU9uUGFnZUxvYWQoZm9yY2VkSW5pdGlhbFZhbHVlID0gbnVsbCkge1xuICAgICAgICBsZXQgc2V0VmFsdWUgPSB0cnVlO1xuICAgICAgICBsZXQgY3VycmVudFZhbHVlO1xuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChmb3JjZWRJbml0aWFsVmFsdWUpKSB7XG4gICAgICAgICAgICBjdXJyZW50VmFsdWUgPSBmb3JjZWRJbml0aWFsVmFsdWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBNYWtlIHN1cmUgdGhlIGluaXRpYWwgdmFsdWUgZG9lcyBub3QgaGF2ZSBhbnkgc3VwZXJmbHVvdXMgd2hpdGVzcGFjZXMgYXJvdW5kIGl0IChGaXggaXNzdWUgIzQ3OSlcbiAgICAgICAgICAgIGN1cnJlbnRWYWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQpLnRyaW0oKTtcbiAgICAgICAgICAgIC8vIENvcnJlY3QgdGhlIERPTSBhdHRyaWJ1dGUgaW4gY2FzZSBzb21lIHdoaXRlc3BhY2VzIHdlcmUgcHJlc2VudFxuICAgICAgICAgICAgdGhpcy5kb21FbGVtZW50LnNldEF0dHJpYnV0ZSgndmFsdWUnLCBjdXJyZW50VmFsdWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuaXNJbnB1dEVsZW1lbnQgfHwgdGhpcy5pc0NvbnRlbnRFZGl0YWJsZSkge1xuICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAqIElmIHRoZSBpbnB1dCB2YWx1ZSBoYXMgYmVlbiBzZXQgYnkgdGhlIGRldiwgYnV0IG5vdCBkaXJlY3RseSBhcyBhbiBhdHRyaWJ1dGUgaW4gdGhlIGh0bWwsIHRoZW4gaXQgdGFrZXNcbiAgICAgICAgICAgICAqIHByZWNlZGVuY2UgYW5kIHNob3VsZCBnZXQgZm9ybWF0dGVkIGR1cmluZyB0aGUgaW5pdGlhbGl6YXRpb24gKGlmIHRoaXMgaW5wdXQgdmFsdWUgaXMgYSB2YWxpZCBudW1iZXIgYW5kIHRoYXQgdGhlXG4gICAgICAgICAgICAgKiBkZXZlbG9wZXIgd2FudHMgaXQgZm9ybWF0dGVkIG9uIGluaXQgKGNmLiB0aGUgYHNldHRpbmdzLmZvcm1hdE9uUGFnZUxvYWRgIG9wdGlvbikpLlxuICAgICAgICAgICAgICogTm90ZTsgdGhpcyBpcyB0cnVlIHdoYXRldmVyIHRoZSBkZXZlbG9wZXIgaGFzIHNldCBmb3IgYGRhdGEtZGVmYXVsdC12YWx1ZS1vdmVycmlkZWAgaW4gdGhlIGh0bWwgKGFzcC5uZXQgdXNlcnMpLlxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEluIG90aGVyIHdvcmRzIDogaWYgYGRlZmF1bHRWYWx1ZU92ZXJyaWRlYCBpcyBub3QgbnVsbCwgaXQgbWVhbnMgdGhlIGRldmVsb3BlciBpcyB0cnlpbmcgdG8gcHJldmVudCBwb3N0YmFjayBwcm9ibGVtcy5cbiAgICAgICAgICAgICAqIEJ1dCBpZiBgaW5wdXQudmFsdWVgIGlzIHNldCB0byBhIG51bWJlciwgYW5kIHRoZSBodG1sIGB2YWx1ZWAgYXR0cmlidXRlIGlzIG5vdCBzZXQsIHRoZW4gaXQgbWVhbnMgdGhlIGRldiBoYXNcbiAgICAgICAgICAgICAqIGNoYW5nZWQgdGhlIGlucHV0IHZhbHVlLCBhbmQgdGhlbiBpdCBtZWFucyB3ZSBzaG91bGQgbm90IG92ZXJ3cml0ZSBoaXMgb3duIGRlY2lzaW9uIHRvIGRvIHNvLlxuICAgICAgICAgICAgICogSGVuY2UsIGlmIGBkZWZhdWx0VmFsdWVPdmVycmlkZWAgaXMgbm90IG51bGwsIGJ1dCBgaW5wdXQudmFsdWVgIGlzIGEgbnVtYmVyIGFuZCBgdGhpcy5kb21FbGVtZW50Lmhhc0F0dHJpYnV0ZSgndmFsdWUnKWBcbiAgICAgICAgICAgICAqIGlzIGZhbHNlLCB3ZSBzaG91bGQgaWdub3JlIGBkZWZhdWx0VmFsdWVPdmVycmlkZWAgYWx0b2dldGhlci5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgY29uc3QgdW5Mb2NhbGl6ZWRDdXJyZW50VmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl90b051bWVyaWNWYWx1ZShjdXJyZW50VmFsdWUsIHRoaXMuc2V0dGluZ3MpOyAvLyBUaGlzIGFsbG93cyB0byB1c2UgYSBsb2NhbGl6ZWQgdmFsdWUgb24gc3RhcnR1cFxuICAgICAgICAgICAgaWYgKCF0aGlzLmRvbUVsZW1lbnQuaGFzQXR0cmlidXRlKCd2YWx1ZScpIHx8IHRoaXMuZG9tRWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3ZhbHVlJykgPT09ICcnKSB7XG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIGB2YWx1ZWAgaXMgdmFsaWQgb3Igbm90XG4gICAgICAgICAgICAgICAgaWYgKCFpc05hTihOdW1iZXIodW5Mb2NhbGl6ZWRDdXJyZW50VmFsdWUpKSAmJiBJbmZpbml0eSAhPT0gdW5Mb2NhbGl6ZWRDdXJyZW50VmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXQodW5Mb2NhbGl6ZWRDdXJyZW50VmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICBzZXRWYWx1ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIG5vdCwgaW5mb3JtIHRoZSBkZXZlbG9wZXIgdGhhdCBub3RoaW5nIHVzYWJsZSBoYXMgYmVlbiBwcm92aWRlZFxuICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgdmFsdWUgWyR7Y3VycmVudFZhbHVlfV0gdXNlZCBpbiB0aGUgaW5wdXQgaXMgbm90IGEgdmFsaWQgdmFsdWUgYXV0b051bWVyaWMgY2FuIHdvcmsgd2l0aC5gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8qIENoZWNrcyBmb3IgOlxuICAgICAgICAgICAgICAgICAqIC0gcGFnZSByZWxvYWQgZnJvbSBiYWNrIGJ1dHRvbiwgYW5kXG4gICAgICAgICAgICAgICAgICogLSBBU1AubmV0IGZvcm0gcG9zdCBiYWNrXG4gICAgICAgICAgICAgICAgICogICAgICBUaGUgZm9sbG93aW5nIEhUTUwgZGF0YSBhdHRyaWJ1dGUgaXMgUkVRVUlSRUQgKGRhdGEtYW4tZGVmYXVsdD1cInNhbWUgdmFsdWUgYXMgdGhlIHZhbHVlIGF0dHJpYnV0ZVwiKVxuICAgICAgICAgICAgICAgICAqICAgICAgZXhhbXBsZTogPGFzcDpUZXh0Qm94IHJ1bmF0PVwic2VydmVyXCIgaWQ9XCJzb21lSURcIiB0ZXh0PVwiMTIzNC41NlwiIGRhdGEtYW4tZGVmYXVsdD1cIjEyMzQuNTZcIj5cbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICBpZiAoKHRoaXMuc2V0dGluZ3MuZGVmYXVsdFZhbHVlT3ZlcnJpZGUgIT09IG51bGwgJiYgdGhpcy5zZXR0aW5ncy5kZWZhdWx0VmFsdWVPdmVycmlkZS50b1N0cmluZygpICE9PSBjdXJyZW50VmFsdWUpIHx8XG4gICAgICAgICAgICAgICAgICAgICh0aGlzLnNldHRpbmdzLmRlZmF1bHRWYWx1ZU92ZXJyaWRlID09PSBudWxsICYmIGN1cnJlbnRWYWx1ZSAhPT0gJycgJiYgY3VycmVudFZhbHVlICE9PSB0aGlzLmRvbUVsZW1lbnQuZ2V0QXR0cmlidXRlKCd2YWx1ZScpKSB8fFxuICAgICAgICAgICAgICAgICAgICAoY3VycmVudFZhbHVlICE9PSAnJyAmJiB0aGlzLmRvbUVsZW1lbnQuZ2V0QXR0cmlidXRlKCd0eXBlJykgPT09ICdoaWRkZW4nICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc051bWJlcih1bkxvY2FsaXplZEN1cnJlbnRWYWx1ZSkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLnNhdmVWYWx1ZVRvU2Vzc2lvblN0b3JhZ2UgJiYgKHRoaXMuc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyAhPT0gbnVsbCB8fCB0aGlzLnNldHRpbmdzLmRpdmlzb3JXaGVuVW5mb2N1c2VkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0UmF3VmFsdWUodGhpcy5fZ2V0VmFsdWVGcm9tUGVyc2lzdGVudFN0b3JhZ2UoKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyB2YWx1ZSBzaG91bGQgTk9UIGJlIHNhdmVkIGluIHNlc3Npb25TdG9yYWdlXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5zZXR0aW5ncy5zYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0b1N0cmlwID0gdGhpcy5jb25zdHJ1Y3Rvci5fcmVtb3ZlQnJhY2tldHMoY3VycmVudFZhbHVlLCB0aGlzLnNldHRpbmdzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5zdWZmaXggfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXggJiYgdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5zdWZmaXgpKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyICE9PSAnJyAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmUoY3VycmVudFZhbHVlLCB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRSYXdWYWx1ZShgLSR7dGhpcy5jb25zdHJ1Y3Rvci5fc3RyaXBBbGxOb25OdW1iZXJDaGFyYWN0ZXJzKHRvU3RyaXAsIHRoaXMuc2V0dGluZ3MsIHRydWUsIHRoaXMuaXNGb2N1c2VkKX1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0UmF3VmFsdWUodGhpcy5jb25zdHJ1Y3Rvci5fc3RyaXBBbGxOb25OdW1iZXJDaGFyYWN0ZXJzKHRvU3RyaXAsIHRoaXMuc2V0dGluZ3MsIHRydWUsIHRoaXMuaXNGb2N1c2VkKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBzZXRWYWx1ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGN1cnJlbnRWYWx1ZSA9PT0gJycpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuc2V0dGluZ3MuZW1wdHlJbnB1dEJlaGF2aW9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IuZm9jdXM6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IubnVsbDpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5wcmVzczpcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLmFsd2F5czpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldEVsZW1lbnRWYWx1ZSh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLm1pbjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0KHRoaXMuc2V0dGluZ3MubWluaW11bVZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLm1heDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0KHRoaXMuc2V0dGluZ3MubWF4aW11bVZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLnplcm86XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldCgnMCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdoZW4gYGVtcHR5SW5wdXRCZWhhdmlvcmAgaXMgYSBudW1iZXIgb3IgYSBzdHJpbmcgcmVwcmVzZW50aW5nIGEgbnVtYmVyXG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldCh0aGlzLnNldHRpbmdzLmVtcHR5SW5wdXRCZWhhdmlvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChzZXRWYWx1ZSAmJiBjdXJyZW50VmFsdWUgPT09IHRoaXMuZG9tRWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3ZhbHVlJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldChjdXJyZW50VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc2V0dGluZ3MuZGVmYXVsdFZhbHVlT3ZlcnJpZGUgPT09IG51bGwgfHxcbiAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuZGVmYXVsdFZhbHVlT3ZlcnJpZGUgPT09IGN1cnJlbnRWYWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5zZXQoY3VycmVudFZhbHVlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEVuaGFuY2UgdGhlIHVzZXIgZXhwZXJpZW5jZSBieSBtb2RpZnlpbmcgdGhlIGRlZmF1bHQgYG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50YCBvcHRpb24gZGVwZW5kaW5nIG9uIGBjdXJyZW5jeVN5bWJvbGAgYW5kIGBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudGAuXG4gICAgICpcbiAgICAgKiBJZiB0aGUgdXNlciBoYXMgbm90IHNldCB0aGUgcGxhY2VtZW50IG9mIHRoZSBuZWdhdGl2ZSBzaWduIChgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnRgKSwgYnV0IGhhcyBzZXQgYSBjdXJyZW5jeSBzeW1ib2wgKGBjdXJyZW5jeVN5bWJvbGApLFxuICAgICAqIHRoZW4gd2UgbW9kaWZ5IHRoZSBkZWZhdWx0IHZhbHVlIG9mIGBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudGAgaW4gb3JkZXIgdG8ga2VlcCB0aGUgcmVzdWx0aW5nIG91dHB1dCBsb2dpY2FsIGJ5IGRlZmF1bHQgOlxuICAgICAqIC0gXCIkLTEsMjM0LjU2XCIgaW5zdGVhZCBvZiBcIi0kMSwyMzQuNTZcIiAoe2N1cnJlbmN5U3ltYm9sOiBcIiRcIiwgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQ6IFwiclwifSlcbiAgICAgKiAtIFwiLTEsMjM0LjU2JFwiIGluc3RlYWQgb2YgXCIxLDIzNC41Ni0kXCIgKHtjdXJyZW5jeVN5bWJvbDogXCIkXCIsIGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50OiBcInNcIiwgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQ6IFwicFwifSlcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqL1xuICAgIHN0YXRpYyBfY29ycmVjdE5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50T3B0aW9uKHNldHRpbmdzKSB7XG4gICAgICAgIC8vWFhYIE5vdGU7IHRoaXMgZnVuY3Rpb24gaXMgc3RhdGljIHNpbmNlIHdlIG5lZWQgdG8gcGFzcyBhIGBzZXR0aW5nc2Agb2JqZWN0IHdoZW4gY2FsbGluZyB0aGUgc3RhdGljIGBBdXRvTnVtZXJpYy5mb3JtYXQoKWAgbWV0aG9kXG4gICAgICAgIC8vIElmIG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50IGlzIGFscmVhZHkgc2V0LCB3ZSBkbyBub3Qgb3ZlcndyaXRlIGl0XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKHNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50KSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZChzZXR0aW5ncykgJiZcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eShzZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCkgJiZcbiAgICAgICAgICAgICFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkoc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wpKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeDpcbiAgICAgICAgICAgICAgICAgICAgc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnByZWZpeDsgLy8gRGVmYXVsdCAtMSwyMzQuNTYg4oKsXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXg6XG4gICAgICAgICAgICAgICAgICAgIHNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5sZWZ0OyAvLyBEZWZhdWx0IC0kMSwyMzQuNTZcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdCA6XG4gICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFNldHMgdGhlIGRlZmF1bHQgdmFsdWUgaWYgYG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50YCBpcyBgbnVsbGBcbiAgICAgICAgICAgIHNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5sZWZ0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29ycmVjdCB0aGUgYGNhcmV0UG9zaXRpb25PbkZvY3VzYCBhbmQgYHNlbGVjdE9uRm9jdXNgIG9wdGlvbnMsIHNpbmNlIHNldHRpbmcgYm90aCBsZWFkcyB0byBhIGNvbmZsaWN0LlxuICAgICAqIFRoaXMgbWV0aG9kIGRpcmVjdGx5IG1vZGlmaWVzIHRoZSBgb3B0aW9uc2Agb2JqZWN0IHBhc3NlZCBhcyBhIHBhcmFtZXRlciwgdGhlbiByZXR1cm5zIGl0LlxuICAgICAqIEl0IHJldHVybnMgYG51bGxgIGlmIHRoZSBnaXZlbiBvcHRpb24gaXMgYG51bGxgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnMgVGhlIG9wdGlvbnMgcGFzc2VkIGFzIGFuIGFyZ3VtZW50IGJ5IHRoZSB1c2VyXG4gICAgICogQHJldHVybnMge29iamVjdHxudWxsfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9jb3JyZWN0Q2FyZXRQb3NpdGlvbk9uRm9jdXNBbmRTZWxlY3RPbkZvY3VzT3B0aW9ucyhvcHRpb25zKSB7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucykpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgdGhlIHVzZXIgaGFzIHNldCB0aGUgYGNhcmV0UG9zaXRpb25PbkZvY3VzYCBvcHRpb24sIGRvIG5vdCBzZXQgYHNlbGVjdE9uRm9jdXNgIHRvIGB0cnVlYCBieSBkZWZhdWx0XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KG9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMpICYmIEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eShvcHRpb25zLnNlbGVjdE9uRm9jdXMpKSB7XG4gICAgICAgICAgICBvcHRpb25zLnNlbGVjdE9uRm9jdXMgPSBBdXRvTnVtZXJpYy5vcHRpb25zLnNlbGVjdE9uRm9jdXMuZG9Ob3RTZWxlY3Q7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB0aGUgdXNlciBoYXMgc2V0IHRoZSBgc2VsZWN0T25Gb2N1c2Agb3B0aW9uIHRvIGB0cnVlYCwgc2V0IGBjYXJldFBvc2l0aW9uT25Gb2N1c2AgdG8gYGRvTm9Gb3JjZUNhcmV0UG9zaXRpb25gXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkob3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1cykgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eShvcHRpb25zLnNlbGVjdE9uRm9jdXMpICYmIG9wdGlvbnMuc2VsZWN0T25Gb2N1cyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5zZWxlY3RPbkZvY3VzLnNlbGVjdCkge1xuICAgICAgICAgICAgb3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1cyA9IEF1dG9OdW1lcmljLm9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMuZG9Ob0ZvcmNlQ2FyZXRQb3NpdGlvbjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBvcHRpb25zO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbGN1bGF0ZSB0aGUgbnVtYmVyIGRlIGRlY2ltYWwgcGxhY2VzIHRvIGJlIHVzZWQgYnkgdGhlIEF1dG9OdW1lcmljIG9iamVjdCwgZm9yIGVhY2ggb2YgaXRzIHN0YXRlLCBhbmQgZm9yIGl0cyBmb3JtYXR0ZWQgYW5kIHJhdyB2YWx1ZS5cbiAgICAgKiBCeSBkZWZhdWx0LCB0aGUgYHJhd1ZhbHVlYCBwcmVjaXNpb24gaXMgdGhlIHNhbWUgYXMgdGhlIGZvcm1hdHRlZCB2YWx1ZSBvbmUuXG4gICAgICpcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgZHVyaW5nIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QgaW5pdGlhbGl6YXRpb24uIFRoaXMgYXNzdW1lcyBzb21lIGludGVybmFsIHZhcmlhYmxlIHN0YXRlLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRob2RzIHNldCB0aGUgZm9sbG93aW5nIG9wdGlvbnMgYWNjb3JkaW5nbHkgdG8gdGhlaXIgb3duIHZhbHVlIGFuZCB0aGUgbWFuZGF0b3J5IGBkZWNpbWFsUGxhY2VzYCBvcHRpb246XG4gICAgICogLSBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgICAgIChudWxsYWJsZSlcbiAgICAgKiAtIGRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciAgKG51bGxhYmxlKVxuICAgICAqIC0gZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyAobnVsbGFibGUpXG4gICAgICpcbiAgICAgKiBOb3RlOiB0aGUgYGRlY2ltYWxQbGFjZXNgIG9wdGlvbiBpcyBvbmx5IHVzZWQgaGVyZSBhbmQgb25seSBzZXJ2ZSB0byBkZWZpbmUgdGhvc2UgdGhyZWUgcHJldmlvdXMgb3B0aW9ucyB2YWx1ZS5cbiAgICAgKiBBdXRvTnVtZXJpYyB3aWxsIHRoZW4gKm9ubHkqIHVzZSBgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlYCwgYGRlY2ltYWxQbGFjZXNTaG93bk9uQmx1cmAgYW5kIGBkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzYCBmcm9tIHRoZXJlLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRob2RzIGRpcmVjdGx5IG1vZGlmaWVzIHRoZSBgc2V0dGluZ3NgIG9iamVjdCBwYXNzZWQgYXMgYSBwYXJhbWV0ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgVGhpcyBpcyBhbiBvYmplY3Qgd2l0aCB0aGUgbmV3IHNldHRpbmdzIHRvIHVzZS5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfY2FsY3VsYXRlRGVjaW1hbFBsYWNlc09uSW5pdChzZXR0aW5ncykge1xuICAgICAgICAvLyBDaGVjayB0aGUgYGRlY2ltYWxQbGFjZXMqYCBvcHRpb25zIGFuZCBvdXRwdXQgYW55IHdhcm5pbmdzIGFzIG5lZWRlZCwgYmVmb3JlIG1vZGlmeWluZyB0aG9zZSBvcHRpb25zXG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlKHNldHRpbmdzKTtcblxuICAgICAgICAvLyBJbml0aWFsaXphdGlvbiBwaGFzZVxuICAgICAgICAvL1hYWCBUaGlzIGFzc3VtZXMgYXQgdGhpcyBzdGFnZSwgYHNldHRpbmdzLmRlY2ltYWxQbGFjZXNgIGFzIGJlZW4gc2V0IGZyb20gdGhlIGRlZmF1bHQgb3B0aW9uc1xuXG4gICAgICAgIC8vIE92ZXJ3cml0ZSB0aGUgYGRlY2ltYWxQbGFjZXMqYCB2YWx1ZXMgaWYgdGhlIGBkZWNpbWFsUGxhY2VzKmAgb3B0aW9ucyBhcmUgbm90IHNldCBpbiB0aGUgYHNldHRpbmdzYFxuICAgICAgICAvLyBTZXRzIGBkZWNpbWFsUGxhY2VzU2hvd25PbkJsdXJgIChwcmV2aW91c2x5IGtub3duIGFzIGBzY2FsZURlY2ltYWxQbGFjZXNgKVxuICAgICAgICBpZiAoc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzLnVzZURlZmF1bHQpICB7XG4gICAgICAgICAgICBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzID0gc2V0dGluZ3MuZGVjaW1hbFBsYWNlcztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyLnVzZURlZmF1bHQpICB7XG4gICAgICAgICAgICBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIgPSBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNldHRpbmdzLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUudXNlRGVmYXVsdCkgIHtcbiAgICAgICAgICAgIHNldHRpbmdzLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9IHNldHRpbmdzLmRlY2ltYWxQbGFjZXM7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgdGhlIGFkZGl0aW9uYWwgZGVjaW1hbCBwbGFjZXMgdG8gdGhlIHJhdyB2YWx1ZVxuICAgICAgICBsZXQgYWRkaXRpb25hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9IDA7XG4gICAgICAgIGlmIChzZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3IgJiYgc2V0dGluZ3MucmF3VmFsdWVEaXZpc29yICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLnJhd1ZhbHVlRGl2aXNvci5ub25lKSB7XG4gICAgICAgICAgICBhZGRpdGlvbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlID0gU3RyaW5nKHNldHRpbmdzLnJhd1ZhbHVlRGl2aXNvcikubGVuZ3RoIC0gMTsgLy8gaWUuIERpdmlkaW5nIGJ5ICcxMDAnIGFkZHMgMiBkZWNpbWFsIHBsYWNlcyB0byB0aGUgbmVlZGVkIHByZWNpc2lvblxuICAgICAgICAgICAgaWYgKGFkZGl0aW9uYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWUgPCAwKSB7XG4gICAgICAgICAgICAgICAgYWRkaXRpb25hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUgPSBNYXRoLm1heChcbiAgICAgICAgICAgIE1hdGgubWF4KHNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciwgc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cykgKyBhZGRpdGlvbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlLFxuICAgICAgICAgICAgTnVtYmVyKHNldHRpbmdzLm9yaWdpbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlKSArIGFkZGl0aW9uYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWVcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWNhbGN1bGF0ZSB0aGUgbnVtYmVyIGRlIGRlY2ltYWwgcGxhY2VzIHRvIGJlIHVzZWQgYnkgdGhlIEF1dG9OdW1lcmljIG9iamVjdCwgZm9yIGVhY2ggb2YgaXRzIHN0YXRlLCBhbmQgZm9yIGl0cyBmb3JtYXR0ZWQgYW5kIHJhdyB2YWx1ZS5cbiAgICAgKiBCeSBkZWZhdWx0LCB0aGUgYHJhd1ZhbHVlYCBwcmVjaXNpb24gaXMgdGhlIHNhbWUgYXMgdGhlIGZvcm1hdHRlZCB2YWx1ZSBvbmUuXG4gICAgICpcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBjbG9zZSB0byB0aGUgb25lIGNhbGxlZCBkdXJpbmcgaW5pdGlhbGl6YXRpb24sIGBfY2FsY3VsYXRlRGVjaW1hbFBsYWNlc09uSW5pdCgpYCwgYnV0IHdpdGggc2xpZ2h0IGRpZmZlcmVuY2Ugc28gdGhhdCB0aGUgYGRlY2ltYWxQbGFjZXMqYCBvcHRpb25zIGFyZSBjb3JyZWN0bHkgdXBkYXRlZCBhcyBuZWVkZWQuXG4gICAgICpcbiAgICAgKiBUaGlzIG1ldGhvZHMgc2V0IHRoZSBmb2xsb3dpbmcgb3B0aW9ucyBhY2NvcmRpbmdseSB0byB0aGVpciBvd24gdmFsdWUgYW5kIHRoZSBtYW5kYXRvcnkgYGRlY2ltYWxQbGFjZXNgIG9wdGlvbjpcbiAgICAgKiAtIGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSAgICAgKG51bGxhYmxlKVxuICAgICAqIC0gZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyICAobnVsbGFibGUpXG4gICAgICogLSBkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzIChudWxsYWJsZSlcbiAgICAgKlxuICAgICAqIE5vdGU6IHRoZSBgZGVjaW1hbFBsYWNlc2Agb3B0aW9uIGlzIG9ubHkgdXNlZCBoZXJlIGFuZCBvbmx5IHNlcnZlIHRvIGRlZmluZSB0aG9zZSB0aHJlZSBwcmV2aW91cyBvcHRpb25zIHZhbHVlLlxuICAgICAqIEF1dG9OdW1lcmljIHdpbGwgdGhlbiAqb25seSogdXNlIGBkZWNpbWFsUGxhY2VzUmF3VmFsdWVgLCBgZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyYCBhbmQgYGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXNgIGZyb20gdGhlcmUuXG4gICAgICpcbiAgICAgKiBUaGlzIG1ldGhvZHMgZGlyZWN0bHkgbW9kaWZpZXMgdGhlIGBzZXR0aW5nc2Agb2JqZWN0IHBhc3NlZCBhcyBhIHBhcmFtZXRlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBUaGlzIGlzIGFuIG9iamVjdCB3aXRoIHRoZSBuZXcgc2V0dGluZ3MgdG8gdXNlLlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBjdXJyZW50U2V0dGluZ3MgVGhpcyBpcyB0aGUgY3VycmVudCBzZXR0aW5ncyAoYHRoaXMuc2V0dGluZ3NgKSB1c2VkIGJ5IHRoZSBlbGVtZW50LlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9jYWxjdWxhdGVEZWNpbWFsUGxhY2VzT25VcGRhdGUoc2V0dGluZ3MsIGN1cnJlbnRTZXR0aW5ncyA9IG51bGwpIHtcbiAgICAgICAgLy8gQ2hlY2sgdGhlIGBkZWNpbWFsUGxhY2VzKmAgb3B0aW9ucyBhbmQgb3V0cHV0IGFueSB3YXJuaW5ncyBhcyBuZWVkZWQsIGJlZm9yZSBtb2RpZnlpbmcgdGhvc2Ugb3B0aW9uc1xuICAgICAgICB0aGlzLl92YWxpZGF0ZURlY2ltYWxQbGFjZXNSYXdWYWx1ZShzZXR0aW5ncyk7XG5cbiAgICAgICAgLy8gVXBkYXRlIHBoYXNlXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoY3VycmVudFNldHRpbmdzKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgV2hlbiB1cGRhdGluZyB0aGUgc2V0dGluZ3MsIHRoZSBwcmV2aW91cyBvbmVzIHNob3VsZCBiZSBwYXNzZWQgYXMgYW4gYXJndW1lbnQuYCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBkZWNpbWFsUGxhY2VzSW5PcHRpb25zID0gJ2RlY2ltYWxQbGFjZXMnIGluIHNldHRpbmdzO1xuICAgICAgICBpZiAoIShkZWNpbWFsUGxhY2VzSW5PcHRpb25zIHx8XG4gICAgICAgICAgICAgICAgJ2RlY2ltYWxQbGFjZXNSYXdWYWx1ZScgaW4gc2V0dGluZ3MgfHxcbiAgICAgICAgICAgICAgICAnZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cycgaW4gc2V0dGluZ3MgfHxcbiAgICAgICAgICAgICAgICAnZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyJyBpbiBzZXR0aW5ncyB8fFxuICAgICAgICAgICAgICAgICdyYXdWYWx1ZURpdmlzb3InIGluIHNldHRpbmdzKSkge1xuICAgICAgICAgICAgLy8gRG8gTm90aGluZyBpZiBubyBkZWNpbWFsIHBsYWNlcy1yZWxhdGVkIG9wdGlvbnMgYXJlIG1vZGlmaWVkXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBPdmVyd3JpdGUgdGhlIGBkZWNpbWFsUGxhY2VzKmAgdmFsdWVzIGlmIHRoZSBgZGVjaW1hbFBsYWNlcypgIG9wdGlvbnMgYXJlIG5vdCBzZXQgaW4gdGhlIGBzZXR0aW5nc2BcbiAgICAgICAgaWYgKGRlY2ltYWxQbGFjZXNJbk9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghKCdkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzJyBpbiBzZXR0aW5ncykgfHxcbiAgICAgICAgICAgICAgICBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMudXNlRGVmYXVsdCkgIHtcbiAgICAgICAgICAgICAgICBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzID0gc2V0dGluZ3MuZGVjaW1hbFBsYWNlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEoJ2RlY2ltYWxQbGFjZXNTaG93bk9uQmx1cicgaW4gc2V0dGluZ3MpIHx8XG4gICAgICAgICAgICAgICAgc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ci51c2VEZWZhdWx0KSAge1xuICAgICAgICAgICAgICAgIHNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciA9IHNldHRpbmdzLmRlY2ltYWxQbGFjZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghKCdkZWNpbWFsUGxhY2VzUmF3VmFsdWUnIGluIHNldHRpbmdzKSB8fFxuICAgICAgICAgICAgICAgIHNldHRpbmdzLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUudXNlRGVmYXVsdCkgIHtcbiAgICAgICAgICAgICAgICBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUgPSBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkKHNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMpKSB7XG4gICAgICAgICAgICAgICAgc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyA9IGN1cnJlbnRTZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWQoc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyKSkge1xuICAgICAgICAgICAgICAgIHNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciA9IGN1cnJlbnRTZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgdGhlIGFkZGl0aW9uYWwgZGVjaW1hbCBwbGFjZXMgdG8gdGhlIHJhdyB2YWx1ZVxuICAgICAgICBsZXQgYWRkaXRpb25hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9IDA7XG4gICAgICAgIGlmIChzZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3IgJiYgc2V0dGluZ3MucmF3VmFsdWVEaXZpc29yICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLnJhd1ZhbHVlRGl2aXNvci5ub25lKSB7XG4gICAgICAgICAgICBhZGRpdGlvbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlID0gU3RyaW5nKHNldHRpbmdzLnJhd1ZhbHVlRGl2aXNvcikubGVuZ3RoIC0gMTsgLy8gaWUuIERpdmlkaW5nIGJ5ICcxMDAnIGFkZHMgMiBkZWNpbWFsIHBsYWNlcyB0byB0aGUgbmVlZGVkIHByZWNpc2lvblxuICAgICAgICAgICAgaWYgKGFkZGl0aW9uYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWUgPCAwKSB7XG4gICAgICAgICAgICAgICAgYWRkaXRpb25hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXNldHRpbmdzLmRlY2ltYWxQbGFjZXMgJiYgIXNldHRpbmdzLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSkge1xuICAgICAgICAgICAgc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlID0gTWF0aC5tYXgoXG4gICAgICAgICAgICAgICAgTWF0aC5tYXgoc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyLCBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzKSArIGFkZGl0aW9uYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWUsXG4gICAgICAgICAgICAgICAgTnVtYmVyKGN1cnJlbnRTZXR0aW5ncy5vcmlnaW5hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZSkgKyBhZGRpdGlvbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlXG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlID0gTWF0aC5tYXgoXG4gICAgICAgICAgICAgICAgTWF0aC5tYXgoc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyLCBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzKSArIGFkZGl0aW9uYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWUsXG4gICAgICAgICAgICAgICAgTnVtYmVyKHNldHRpbmdzLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSkgKyBhZGRpdGlvbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQW5hbHl6ZSBhbmQgc2F2ZSB0aGUgbWluaW11bVZhbHVlIGFuZCBtYXhpbXVtVmFsdWUgaW50ZWdlciBzaXplIGZvciBsYXRlciB1c2VzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfY2FsY3VsYXRlVk1pbkFuZFZNYXhJbnRlZ2VyU2l6ZXMoKSB7XG4gICAgICAgIGxldCBbbWF4aW11bVZhbHVlSW50ZWdlclBhcnRdID0gdGhpcy5zZXR0aW5ncy5tYXhpbXVtVmFsdWUudG9TdHJpbmcoKS5zcGxpdCgnLicpO1xuICAgICAgICBsZXQgW21pbmltdW1WYWx1ZUludGVnZXJQYXJ0XSA9ICghdGhpcy5zZXR0aW5ncy5taW5pbXVtVmFsdWUgJiYgdGhpcy5zZXR0aW5ncy5taW5pbXVtVmFsdWUgIT09IDApP1tdOnRoaXMuc2V0dGluZ3MubWluaW11bVZhbHVlLnRvU3RyaW5nKCkuc3BsaXQoJy4nKTtcbiAgICAgICAgbWF4aW11bVZhbHVlSW50ZWdlclBhcnQgPSBtYXhpbXVtVmFsdWVJbnRlZ2VyUGFydC5yZXBsYWNlKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyLCAnJyk7XG4gICAgICAgIG1pbmltdW1WYWx1ZUludGVnZXJQYXJ0ID0gbWluaW11bVZhbHVlSW50ZWdlclBhcnQucmVwbGFjZSh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciwgJycpO1xuXG4gICAgICAgIHRoaXMuc2V0dGluZ3MubUludFBvcyA9IE1hdGgubWF4KG1heGltdW1WYWx1ZUludGVnZXJQYXJ0Lmxlbmd0aCwgMSk7XG4gICAgICAgIHRoaXMuc2V0dGluZ3MubUludE5lZyA9IE1hdGgubWF4KG1pbmltdW1WYWx1ZUludGVnZXJQYXJ0Lmxlbmd0aCwgMSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2FsY3VsYXRlIG9uY2Ugd2hhdCBhcmUgdGhlIGB2YWx1ZXNUb1N0cmluZ3NgIG9wdGlvbiBrZXlzLlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2NhbGN1bGF0ZVZhbHVlc1RvU3RyaW5nc0tleXMoKSB7XG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLnZhbHVlc1RvU3RyaW5ncykge1xuICAgICAgICAgICAgdGhpcy52YWx1ZXNUb1N0cmluZ3NLZXlzID0gT2JqZWN0LmtleXModGhpcy5zZXR0aW5ncy52YWx1ZXNUb1N0cmluZ3MpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy52YWx1ZXNUb1N0cmluZ3NLZXlzID0gW107XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYWNoZXMgcmVndWxhciBleHByZXNzaW9ucyBmb3IgX3N0cmlwQWxsTm9uTnVtYmVyQ2hhcmFjdGVyc0V4Y2VwdEN1c3RvbURlY2ltYWxDaGFyXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gcmVnZXhcbiAgICAgKi9cbiAgICBzdGF0aWMgX2NhY2hlc1VzdWFsUmVndWxhckV4cHJlc3Npb25zKHNldHRpbmdzLCByZWdleCkge1xuICAgICAgICAvLyBUZXN0IGlmIHRoZXJlIGlzIGEgbmVnYXRpdmUgY2hhcmFjdGVyIGluIHRoZSBzdHJpbmdcbiAgICAgICAgbGV0IG5lZ2F0aXZlU2lnblJlZztcbiAgICAgICAgaWYgKHNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIuaHlwaGVuKSB7XG4gICAgICAgICAgICBuZWdhdGl2ZVNpZ25SZWcgPSBgKFstXFxcXCR7c2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyfV0/KWA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBuZWdhdGl2ZVNpZ25SZWcgPSAnKC0/KSc7XG4gICAgICAgIH1cblxuICAgICAgICByZWdleC5hTmVnUmVnQXV0b1N0cmlwID0gbmVnYXRpdmVTaWduUmVnO1xuICAgICAgICBzZXR0aW5ncy5hbGxvd2VkQXV0b1N0cmlwID0gbmV3IFJlZ0V4cChgW14tMDEyMzQ1Njc4OVxcXFwke3NldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXJ9XWAsICdnJyk7XG4gICAgICAgIHNldHRpbmdzLm51bVJlZ0F1dG9TdHJpcCA9IG5ldyBSZWdFeHAoYCR7bmVnYXRpdmVTaWduUmVnfSg/OlxcXFwke3NldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXJ9PyhbMC05XStcXFxcJHtzZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyfVswLTldKyl8KFswLTldKig/OlxcXFwke3NldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXJ9WzAtOV0qKT8pKWApO1xuXG4gICAgICAgIC8vIFVzaW5nIHRoaXMgcmVnZXggdmVyc2lvbiBgXiR7cmVnZXguYU5lZ1JlZ0F1dG9TdHJpcH0wKihcXFxcZHwkKWAgZW50aXJlbHkgY2xlYXIgdGhlIGlucHV0IG9uIGJsdXJcbiAgICAgICAgc2V0dGluZ3Muc3RyaXBSZWcgPSBuZXcgUmVnRXhwKGBeJHtyZWdleC5hTmVnUmVnQXV0b1N0cmlwfTAqKFswLTldKWApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1vZGlmeSB0aGUgdXNlciBzZXR0aW5ncyB0byBtYWtlIHRoZW0gJ2V4cGxvaXRhYmxlJyBsYXRlci5cbiAgICAgKi9cbiAgICBfdHJhbnNmb3JtT3B0aW9uc1ZhbHVlc1RvRGVmYXVsdFR5cGVzKCkge1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiB0aGlzLnNldHRpbmdzKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLnNldHRpbmdzW2tleV07XG5cbiAgICAgICAgICAgICAgICAvLyBDb252ZXJ0IHRoZSBzdHJpbmdzICd0cnVlJyBhbmQgJ2ZhbHNlJyB0byBib29sZWFuc1xuICAgICAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gJ3RydWUnIHx8IHZhbHVlID09PSAnZmFsc2UnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Nba2V5XSA9IHZhbHVlID09PSAndHJ1ZSc7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gQ29udmVydCBudW1iZXJzIGluIG9wdGlvbnMgdG8gc3RyaW5nc1xuICAgICAgICAgICAgICAgIC8vVE9ETyBPbmx5IHRyYW5zZm9ybSB0aGUgdmFsdWVzIG9mIHR5cGUgJ051bWJlcicgdG8gJ1N0cmluZycgaWYgaXQncyBhIGN1cnJlbmN5IG51bWJlciAoc28gdGhhdCB3ZSBjYW4gaGF2ZSBiaWcgbnVtYmVycykuIERvIG5vdCBjb252ZXJ0IG90aGVyIG51bWJlcnMgKGllLiBgaGlzdG9yeVNpemVgKVxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Nba2V5XSA9IHZhbHVlLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydCB0aGUgb2xkIHNldHRpbmdzIG9wdGlvbnMgbmFtZSB0byBuZXcgb25lcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zXG4gICAgICovXG4gICAgc3RhdGljIF9jb252ZXJ0T2xkT3B0aW9uc1RvTmV3T25lcyhvcHRpb25zKSB7XG4gICAgICAgIC8vVE9ETyBEZWxldGUgdGhpcyBmdW5jdGlvbiBvbmNlIHRoZSBvbGQgb3B0aW9ucyBhcmUgbm90IHVzZWQgYW55bW9yZVxuICAgICAgICBjb25zdCBvbGRPcHRpb25zQ29udmVydGVyID0ge1xuICAgICAgICAgICAgLy8gT2xkIG9wdGlvbiBuYW1lcywgd2l0aCB0aGVpciBjb3JyZXNwb25kaW5nIG5ldyBuYW1lc1xuICAgICAgICAgICAgYVNlcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2RpZ2l0R3JvdXBTZXBhcmF0b3InLFxuICAgICAgICAgICAgblNlcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ3Nob3dPbmx5TnVtYmVyc09uRm9jdXMnLFxuICAgICAgICAgICAgZEdyb3VwICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2RpZ2l0YWxHcm91cFNwYWNpbmcnLFxuICAgICAgICAgICAgYURlYyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2RlY2ltYWxDaGFyYWN0ZXInLFxuICAgICAgICAgICAgYWx0RGVjICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2RlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZScsXG4gICAgICAgICAgICBhU2lnbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnY3VycmVuY3lTeW1ib2wnLFxuICAgICAgICAgICAgcFNpZ24gICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2N1cnJlbmN5U3ltYm9sUGxhY2VtZW50JyxcbiAgICAgICAgICAgIHBOZWcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICduZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCcsXG4gICAgICAgICAgICBhU3VmZml4ICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnc3VmZml4VGV4dCcsXG4gICAgICAgICAgICBvTGltaXRzICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnb3ZlcnJpZGVNaW5NYXhMaW1pdHMnLFxuICAgICAgICAgICAgdk1heCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ21heGltdW1WYWx1ZScsXG4gICAgICAgICAgICB2TWluICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnbWluaW11bVZhbHVlJyxcbiAgICAgICAgICAgIG1EZWMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICdkZWNpbWFsUGxhY2VzT3ZlcnJpZGUnLFxuICAgICAgICAgICAgZURlYyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2RlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMnLFxuICAgICAgICAgICAgc2NhbGVEZWNpbWFsICAgICAgICAgICAgICAgICAgICAgIDogJ2RlY2ltYWxQbGFjZXNTaG93bk9uQmx1cicsXG4gICAgICAgICAgICBhU3RvciAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnc2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZScsXG4gICAgICAgICAgICBtUm91bmQgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAncm91bmRpbmdNZXRob2QnLFxuICAgICAgICAgICAgYVBhZCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2FsbG93RGVjaW1hbFBhZGRpbmcnLFxuICAgICAgICAgICAgbkJyYWNrZXQgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ25lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyJyxcbiAgICAgICAgICAgIHdFbXB0eSAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICdlbXB0eUlucHV0QmVoYXZpb3InLFxuICAgICAgICAgICAgbFplcm8gICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2xlYWRpbmdaZXJvJyxcbiAgICAgICAgICAgIGFGb3JtICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICdmb3JtYXRPblBhZ2VMb2FkJyxcbiAgICAgICAgICAgIHNOdW1iZXIgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICdzZWxlY3ROdW1iZXJPbmx5JyxcbiAgICAgICAgICAgIGFuRGVmYXVsdCAgICAgICAgICAgICAgICAgICAgICAgICA6ICdkZWZhdWx0VmFsdWVPdmVycmlkZScsXG4gICAgICAgICAgICB1blNldE9uU3VibWl0ICAgICAgICAgICAgICAgICAgICAgOiAndW5mb3JtYXRPblN1Ym1pdCcsXG4gICAgICAgICAgICBvdXRwdXRUeXBlICAgICAgICAgICAgICAgICAgICAgICAgOiAnb3V0cHV0Rm9ybWF0JyxcbiAgICAgICAgICAgIGRlYnVnICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICdzaG93V2FybmluZ3MnLFxuXG4gICAgICAgICAgICAvLyBDdXJyZW50IG9wdGlvbnMgOlxuICAgICAgICAgICAgYWxsb3dEZWNpbWFsUGFkZGluZyAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGFsd2F5c0FsbG93RGVjaW1hbENoYXJhY3RlciAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Gb2N1cyAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgY3JlYXRlTG9jYWxMaXN0ICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGN1cnJlbmN5U3ltYm9sICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudCAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgZGVjaW1hbENoYXJhY3RlciAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZSAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBkZWNpbWFsUGxhY2VzICAgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgZGVmYXVsdFZhbHVlT3ZlcnJpZGUgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGRpZ2l0YWxHcm91cFNwYWNpbmcgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBkaWdpdEdyb3VwU2VwYXJhdG9yICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgZGl2aXNvcldoZW5VbmZvY3VzZWQgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGVtcHR5SW5wdXRCZWhhdmlvciAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBldmVudEJ1YmJsZXMgICAgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgZXZlbnRJc0NhbmNlbGFibGUgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGZhaWxPblVua25vd25PcHRpb24gICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBmb3JtYXRPblBhZ2VMb2FkICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgaGlzdG9yeVNpemUgICAgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGlzQ2FuY2VsbGFibGUgICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBsZWFkaW5nWmVybyAgICAgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgbWF4aW11bVZhbHVlICAgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIG1pbmltdW1WYWx1ZSAgICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBtb2RpZnlWYWx1ZU9uV2hlZWwgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgbmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ICAgICA6IHRydWUsXG4gICAgICAgICAgICBuZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgbm9FdmVudExpc3RlbmVycyAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIG9uSW52YWxpZFBhc3RlICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBvdXRwdXRGb3JtYXQgICAgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgb3ZlcnJpZGVNaW5NYXhMaW1pdHMgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIHBvc2l0aXZlU2lnbkNoYXJhY3RlciAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICByYXdWYWx1ZURpdmlzb3IgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgcmVhZE9ubHkgICAgICAgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIHJvdW5kaW5nTWV0aG9kICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBzYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgc2VsZWN0TnVtYmVyT25seSAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIHNlbGVjdE9uRm9jdXMgICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBzZXJpYWxpemVTcGFjZXMgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgc2hvd09ubHlOdW1iZXJzT25Gb2N1cyAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIHNob3dQb3NpdGl2ZVNpZ24gICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBzaG93V2FybmluZ3MgICAgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgc3R5bGVSdWxlcyAgICAgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIHN1ZmZpeFRleHQgICAgICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBzeW1ib2xXaGVuVW5mb2N1c2VkICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgdW5mb3JtYXRPbkhvdmVyICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIHVuZm9ybWF0T25TdWJtaXQgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICB2YWx1ZXNUb1N0cmluZ3MgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgd2F0Y2hFeHRlcm5hbENoYW5nZXMgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIHdoZWVsT24gICAgICAgICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICB3aGVlbFN0ZXAgICAgICAgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuXG4gICAgICAgICAgICAvLyBBZGRpdGlvbmFsIGluZm9ybWF0aW9uIHRoYXQgYXJlIGFkZGVkIHRvIHRoZSBgc2V0dGluZ3NgIG9iamVjdCA6XG4gICAgICAgICAgICAvL1RPRE8gRmluZCBhIHdheSB0byBleGNsdWRlIHRob3NlIGludGVybmFsIGRhdGEgZnJvbSB0aGUgc2V0dGluZ3Mgb2JqZWN0IChpZGVhbGx5IGJ5IHVzaW5nIGFub3RoZXIgb2JqZWN0LCBvciBiZXR0ZXIgeWV0LCBjbGFzcyBhdHRyaWJ1dGVzKSAtLT5cbiAgICAgICAgICAgIGFsbG93ZWRBdXRvU3RyaXAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBpc05lZ2F0aXZlU2lnbkFsbG93ZWQgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgaXNQb3NpdGl2ZVNpZ25BbGxvd2VkICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIG1JbnROZWcgICAgICAgICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBtSW50UG9zICAgICAgICAgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgbnVtUmVnQXV0b1N0cmlwICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIG9yaWdpbmFsRGVjaW1hbFBsYWNlcyAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBvcmlnaW5hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZSAgICAgOiB0cnVlLFxuICAgICAgICAgICAgc3RyaXBSZWcgICAgICAgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgfTtcblxuICAgICAgICBmb3IgKGNvbnN0IG9wdGlvbiBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5oYXNPd25Qcm9wZXJ0eShvcHRpb24pKSB7XG4gICAgICAgICAgICAgICAgaWYgKG9sZE9wdGlvbnNDb252ZXJ0ZXJbb3B0aW9uXSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgb3B0aW9uIGlzIGEgJ25ldycgb3B0aW9uLCB3ZSBjb250aW51ZSBsb29waW5nXG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChvbGRPcHRpb25zQ29udmVydGVyLmhhc093blByb3BlcnR5KG9wdGlvbikpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRWxzZSB3ZSBoYXZlIGFuICdvbGQnIG9wdGlvbiBuYW1lXG4gICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLndhcm5pbmcoYFlvdSBhcmUgdXNpbmcgdGhlIGRlcHJlY2F0ZWQgb3B0aW9uIG5hbWUgJyR7b3B0aW9ufScuIFBsZWFzZSB1c2UgJyR7b2xkT3B0aW9uc0NvbnZlcnRlcltvcHRpb25dfScgaW5zdGVhZCBmcm9tIG5vdyBvbi4gVGhlIG9sZCBvcHRpb24gbmFtZSB3aWxsIGJlIGRyb3BwZWQgdmVyeSBzb29u4oSiLmAsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZW4gd2UgbW9kaWZ5IHRoZSBpbml0aWFsIG9wdGlvbiBvYmplY3QgdG8gdXNlIHRoZSBuZXcgb3B0aW9ucyBpbnN0ZWFkIG9mIHRoZSBvbGQgb25lc1xuICAgICAgICAgICAgICAgICAgICBvcHRpb25zW29sZE9wdGlvbnNDb252ZXJ0ZXJbb3B0aW9uXV0gPSBvcHRpb25zW29wdGlvbl07XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBvcHRpb25zW29wdGlvbl07XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChvcHRpb25zLmZhaWxPblVua25vd25PcHRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gLi4ub3IgdGhlIG9wdGlvbiBuYW1lIGlzIHVua25vd24uIFRoaXMgbWVhbnMgdGhlcmUgaXMgYSBwcm9ibGVtIHdpdGggdGhlIG9wdGlvbnMgb2JqZWN0LCB0aGVyZWZvcmUgd2UgdGhyb3cgYW4gZXJyb3IuXG4gICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYE9wdGlvbiBuYW1lICcke29wdGlvbn0nIGlzIHVua25vd24uIFBsZWFzZSBmaXggdGhlIG9wdGlvbnMgcGFzc2VkIHRvIGF1dG9OdW1lcmljYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCdtRGVjJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKCdUaGUgb2xkIGBtRGVjYCBvcHRpb24gaGFzIGJlZW4gZGVwcmVjYXRlZCBpbiBmYXZvciBvZiBtb3JlIGFjY3VyYXRlIG9wdGlvbnMgOyBgZGVjaW1hbFBsYWNlc2AsIGBkZWNpbWFsUGxhY2VzUmF3VmFsdWVgLCBgZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1c2AgYW5kIGBkZWNpbWFsUGxhY2VzU2hvd25PbkJsdXJgLicsIHRydWUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQW5hbHlzZSB0aGUgc2V0dGluZ3Mvb3B0aW9ucyBwYXNzZWQgYnkgdGhlIHVzZXIsIHZhbGlkYXRlIGFuZCBjbGVhbiB0aGVtLCB0aGVuIHNldCB0aGVtIGludG8gYHRoaXMuc2V0dGluZ3NgLlxuICAgICAqIE5vdGU6IFRoaXMgc2V0cyB0aGUgc2V0dGluZ3MgdG8gYG51bGxgIGlmIHNvbWVob3cgdGhlIHNldHRpbmdzIG9iamV0IGlzIHVuZGVmaW5lZCBvciBlbXB0eVxuICAgICAqICAgICAgIElmIG9ubHkgYGRlY2ltYWxQbGFjZXNgIGlzIGRlZmluZWQgaW4gdGhlIG9wdGlvbiwgb3ZlcndyaXRlIHRoZSBvdGhlciBkZWNpbWFsUGxhY2VzKiBvcHRpb25zLCBvdGhlcndpc2UsIHVzZSB0aG9zZSBvcHRpb25zXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uc1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gdXBkYXRlIC0gSWYgc2V0IHRvIGB0cnVlYCwgdGhlbiB0aGUgc2V0dGluZ3MgYWxyZWFkeSBleGlzdHMgYW5kIHRoaXMgZnVuY3Rpb24gb25seSB1cGRhdGVzIHRoZW0gaW5zdGVhZCBvZiByZWNyZWF0aW5nIHRoZW0gZnJvbSBzY3JhdGNoXG4gICAgICogQHRocm93c1xuICAgICAqL1xuICAgIF9zZXRTZXR0aW5ncyhvcHRpb25zLCB1cGRhdGUgPSBmYWxzZSkge1xuICAgICAgICAvLyBJZiB0aGUgdXNlciB1c2VkIG9sZCBvcHRpb25zLCB3ZSBjb252ZXJ0IHRoZW0gdG8gbmV3IG9uZXNcbiAgICAgICAgaWYgKHVwZGF0ZSB8fCAhQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMpKSB7XG4gICAgICAgICAgICB0aGlzLmNvbnN0cnVjdG9yLl9jb252ZXJ0T2xkT3B0aW9uc1RvTmV3T25lcyhvcHRpb25zKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh1cGRhdGUpIHtcbiAgICAgICAgICAgIC8vIFRoZSBzZXR0aW5ncyBhcmUgdXBkYXRlZFxuICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBvcmlnaW5hbCBkYXRhLCBpZiBpdCBoYXMgY2hhbmdlZFxuICAgICAgICAgICAgY29uc3QgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlSW5PcHRpb25zID0gJ2RlY2ltYWxQbGFjZXNSYXdWYWx1ZScgaW4gb3B0aW9ucztcbiAgICAgICAgICAgIGlmIChkZWNpbWFsUGxhY2VzUmF3VmFsdWVJbk9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLm9yaWdpbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlID0gb3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGRlY2ltYWxQbGFjZXNJbk9wdGlvbnMgPSAnZGVjaW1hbFBsYWNlcycgaW4gb3B0aW9ucztcbiAgICAgICAgICAgIGlmIChkZWNpbWFsUGxhY2VzSW5PcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5vcmlnaW5hbERlY2ltYWxQbGFjZXMgPSBvcHRpb25zLmRlY2ltYWxQbGFjZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFRoZW4gdXBkYXRlIGFsbCB0aGUgYGRlY2ltYWxQbGFjZXMqYCBvcHRpb25zXG4gICAgICAgICAgICB0aGlzLmNvbnN0cnVjdG9yLl9jYWxjdWxhdGVEZWNpbWFsUGxhY2VzT25VcGRhdGUob3B0aW9ucywgdGhpcy5zZXR0aW5ncyk7XG5cbiAgICAgICAgICAgIC8vIEZpbmFsbHkgZ2VuZXJhdGUgdGhlIHVwZGF0ZWQgc2V0dGluZ3Mgb2JqZWN0IHRvIHVzZVxuICAgICAgICAgICAgdGhpcy5fbWVyZ2VTZXR0aW5ncyhvcHRpb25zKTsgLy9UT0RPIENoZWNrIHRoYXQgdGhlIGBzdHlsZVJ1bGVzYCBvcHRpb24gaXMgY29ycmVjdGx5IGNsb25lZCAoZHVlIHRvIGRlcHRoIGNsb25pbmcgbGltaXRhdGlvbilcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFRoZSBzZXR0aW5ncyBhcmUgZ2VuZXJhdGVkIGZvciB0aGUgZmlyc3QgdGltZVxuICAgICAgICAgICAgdGhpcy5zZXR0aW5ncyA9IHt9O1xuICAgICAgICAgICAgLy8gSWYgd2UgY291bGRuJ3QgZ3JhYiBhbnkgc2V0dGluZ3MsIGNyZWF0ZSB0aGVtIGZyb20gdGhlIGRlZmF1bHQgb25lcyBhbmQgY29tYmluZSB0aGVtIHdpdGggdGhlIG9wdGlvbnMgcGFzc2VkIGFzIGEgcGFyYW1ldGVyIGFzIHdlbGwgYXMgd2l0aCB0aGUgSFRNTDUgYGRhdGEtKmAgaW5mbyAodmlhIGB0aGlzLmRvbUVsZW1lbnQuZGF0YXNldGApLCBpZiBhbnkuXG4gICAgICAgICAgICB0aGlzLl9tZXJnZVNldHRpbmdzKHRoaXMuY29uc3RydWN0b3IuZ2V0RGVmYXVsdENvbmZpZygpLCB0aGlzLmRvbUVsZW1lbnQuZGF0YXNldCwgb3B0aW9ucywgeyByYXdWYWx1ZSA6IHRoaXMuZGVmYXVsdFJhd1ZhbHVlIH0pO1xuICAgICAgICAgICAgdGhpcy5jYXJldEZpeCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy50aHJvd0lucHV0ID0gdHJ1ZTsgLy8gVGhyb3cgaW5wdXQgZXZlbnRcbiAgICAgICAgICAgIHRoaXMuYWxsb3dlZFRhZ0xpc3QgPSBBdXRvTnVtZXJpY0VudW0uYWxsb3dlZFRhZ0xpc3Q7XG4gICAgICAgICAgICB0aGlzLnJ1bk9uY2UgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuaG92ZXJlZFdpdGhBbHQgPSBmYWxzZTsgLy8gS2VlcCB0cmFja3MgaWYgdGhlIGN1cnJlbnQgQXV0b051bWVyaWMgZWxlbWVudCBpcyBob3ZlcmVkIGJ5IHRoZSBtb3VzZSBjdXJzb3Igd2hpbGUgYEFsdGAgaXMgcHJlc3NlZFxuICAgICAgICB9XG5cbiAgICAgICAgLy8gTW9kaWZ5IHRoZSB1c2VyIHNldHRpbmdzIHRvIG1ha2UgdGhlbSAnZXhwbG9pdGFibGUnXG4gICAgICAgIHRoaXMuX3RyYW5zZm9ybU9wdGlvbnNWYWx1ZXNUb0RlZmF1bHRUeXBlcygpO1xuXG4gICAgICAgIC8vIEltbWVkaWF0ZWx5IHJ1biB0aGUgY2FsbGJhY2tzIHRoYXQgY291bGQgdXBkYXRlIHRoZSBzZXR0aW5ncyBvYmplY3RcbiAgICAgICAgdGhpcy5fcnVuQ2FsbGJhY2tzRm91bmRJblRoZVNldHRpbmdzT2JqZWN0KCk7XG5cbiAgICAgICAgLy8gSW1wcm92ZSB0aGUgYG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50YCBvcHRpb24gaWYgbmVlZGVkXG4gICAgICAgIHRoaXMuY29uc3RydWN0b3IuX2NvcnJlY3ROZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudE9wdGlvbih0aGlzLnNldHRpbmdzKTtcblxuICAgICAgICAvLyBTZXQgdGhlIGBjYXJldFBvc2l0aW9uT25Gb2N1c2AgYW5kIGBzZWxlY3RPbkZvY3VzYCBvcHRpb25zIHNvIHRoYXQgdGhleSBkbyBub3QgY29uZmxpY3QsIGlmIG9uZSBvZiB0aG9zZSBoYXZlIGJlZW4gc2V0IG1hbnVhbGx5IGJ5IHRoZSB1c2VyLlxuICAgICAgICAvLyBJZiBvcmRlciB0byBjaGVjayB0aGF0LCB3ZSB0YWtlIGEgbG9vayBhdCB0aGUgb3JpZ2luYWwgb3B0aW9ucyB0aGUgdXNlciBwYXNzZWQgYXMgYW4gYXJndW1lbnQsIG5vdCBgdGhpcy5zZXR0aW5nc2AgdGhhdCBoYXZlIGJlZW4gbWVyZ2VkIHdpdGggdGhlIGRlZmF1bHQgc2V0dGluZ3MuIC8vVE9ETyBDaGVjayB0aGUgdmFsaWRpdHkgb2YgdGhhdCBjb21tZW50XG4gICAgICAgIHRoaXMuY29uc3RydWN0b3IuX2NvcnJlY3RDYXJldFBvc2l0aW9uT25Gb2N1c0FuZFNlbGVjdE9uRm9jdXNPcHRpb25zKHRoaXMuc2V0dGluZ3MpO1xuXG4gICAgICAgIC8vIERlZmluZSBpZiB0aGUgbmVnYXRpdmUgb3IgcG9zaXRpdmUgc2lnbnMgYXJlIGFsbG93ZWRcbiAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5fc2V0TmVnYXRpdmVQb3NpdGl2ZVNpZ25QZXJtaXNzaW9ucyh0aGlzLnNldHRpbmdzKTtcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyAoZHVyaW5nIHRoZSBlbGVtZW50IGluaXRpYWxpemF0aW9uKVxuICAgICAgICBpZiAoIXVwZGF0ZSkge1xuICAgICAgICAgICAgLy8gTWFrZSBzdXJlIHRoZSBgb3JpZ2luYWxEZWNpbWFsUGxhY2VzYCBpbmZvIGlzIHNldFxuICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zKSB8fCAhb3B0aW9ucy5kZWNpbWFsUGxhY2VzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5vcmlnaW5hbERlY2ltYWxQbGFjZXMgPSBudWxsO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLm9yaWdpbmFsRGVjaW1hbFBsYWNlcyA9IG9wdGlvbnMuZGVjaW1hbFBsYWNlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2F2ZSB0aGUgYG9yaWdpbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlYCBpbmZvXG4gICAgICAgICAgICB0aGlzLnNldHRpbmdzLm9yaWdpbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlID0gdGhpcy5zZXR0aW5ncy5kZWNpbWFsUGxhY2VzUmF3VmFsdWU7XG5cbiAgICAgICAgICAgIC8vIFRoZW4gdXBkYXRlIGFsbCB0aGUgYGRlY2ltYWxQbGFjZXMqYCBvcHRpb25zXG4gICAgICAgICAgICB0aGlzLmNvbnN0cnVjdG9yLl9jYWxjdWxhdGVEZWNpbWFsUGxhY2VzT25Jbml0KHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkaXRpb25hbCBjaGFuZ2VzIHRvIHRoZSBzZXR0aW5ncyBvYmplY3RcbiAgICAgICAgdGhpcy5fY2FsY3VsYXRlVk1pbkFuZFZNYXhJbnRlZ2VyU2l6ZXMoKTtcbiAgICAgICAgdGhpcy5fc2V0VHJhaWxpbmdOZWdhdGl2ZVNpZ25JbmZvKCk7XG4gICAgICAgIHRoaXMucmVnZXggPSB7fTsgLy8gQ3JlYXRlIHRoZSBvYmplY3QgdGhhdCB3aWxsIHN0b3JlIHRoZSByZWd1bGFyIGV4cHJlc3Npb25zXG4gICAgICAgIHRoaXMuY29uc3RydWN0b3IuX2NhY2hlc1VzdWFsUmVndWxhckV4cHJlc3Npb25zKHRoaXMuc2V0dGluZ3MsIHRoaXMucmVnZXgpO1xuICAgICAgICB0aGlzLmNvbnN0cnVjdG9yLl9zZXRCcmFja2V0cyh0aGlzLnNldHRpbmdzKTtcbiAgICAgICAgdGhpcy5fY2FsY3VsYXRlVmFsdWVzVG9TdHJpbmdzS2V5cygpO1xuXG4gICAgICAgIC8vIFZhbGlkYXRlIHRoZSBzZXR0aW5ncy4gQm90aCB0ZXN0cyB0aHJvd3MgaWYgbmVjZXNzYXJ5LlxuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNFbXB0eU9iaih0aGlzLnNldHRpbmdzKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcignVW5hYmxlIHRvIHNldCB0aGUgc2V0dGluZ3MsIHRob3NlIGFyZSBpbnZhbGlkIDsgYW4gZW1wdHkgb2JqZWN0IHdhcyBnaXZlbi4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY29uc3RydWN0b3IudmFsaWRhdGUodGhpcy5zZXR0aW5ncywgZmFsc2UsIG9wdGlvbnMpO1xuXG4gICAgICAgIC8vIE9yaWdpbmFsIHNldHRpbmdzIHNhdmVkIGZvciB1c2Ugd2hlbiBkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzLCBkaXZpc29yV2hlblVuZm9jdXNlZCAmIHNob3dPbmx5TnVtYmVyc09uRm9jdXMgb3B0aW9ucyBhcmUgYmVpbmcgdXNlZFxuICAgICAgICB0aGlzLl9rZWVwQW5PcmlnaW5hbFNldHRpbmdzQ29weSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERlZmluZSBpZiB0aGUgbmVnYXRpdmUgb3IgcG9zaXRpdmUgc2lnbnMgYXJlIGFsbG93ZWQsIGFuZCB1cGRhdGUgdGhlIGdpdmVuIHNldHRpbmdzIG9iamVjdCBkaXJlY3RseS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9zZXROZWdhdGl2ZVBvc2l0aXZlU2lnblBlcm1pc3Npb25zKHNldHRpbmdzKSB7XG4gICAgICAgIHNldHRpbmdzLmlzTmVnYXRpdmVTaWduQWxsb3dlZCA9IHNldHRpbmdzLm1pbmltdW1WYWx1ZSA8IDA7XG4gICAgICAgIHNldHRpbmdzLmlzUG9zaXRpdmVTaWduQWxsb3dlZCA9IHNldHRpbmdzLm1heGltdW1WYWx1ZSA+PSAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnQgdGhlIGB2YWx1ZWAgcGFyYW1ldGVyIHRoYXQgY2FuIGVpdGhlciBiZSA6XG4gICAgICogLSBhIHJlYWwgbnVtYmVyLFxuICAgICAqIC0gYSBudW1iZXIgcmVwcmVzZW50ZWQgaW4gdGhlIHNjaWVudGlmaWMgbm90YXRpb24gKGllLiAtMTIzLjQ1NjdlLTYpXG4gICAgICogLSBhIHN0cmluZyByZXByZXNlbnRpbmcgYSByZWFsIG51bWJlciwgb3JcbiAgICAgKiAtIGEgc3RyaW5nIHJlcHJlc2VudGluZyBhIGxvY2FsaXplZCBudW1iZXIgKHdpdGggc3BlY2lmaWMgZ3JvdXAgc2VwYXJhdG9ycyBhbmQgZGVjaW1hbCBjaGFyYWN0ZXIpLFxuICAgICAqIC4uLnRvIGEgc3RyaW5nIHJlcHJlc2VudGluZyBhIHJlYWwgJ2phdmFzY3JpcHQnIG51bWJlciAoaWUuICcxMjM0JyBvciAnMTIzNC41NjcnKS5cbiAgICAgKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gcmV0dXJucyBgTmFOYCBpZiBzdWNoIGNvbnZlcnNpb24gZmFpbHMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2ludHxmbG9hdHxzdHJpbmd9IHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHJldHVybnMge3N0cmluZ3xOYU59XG4gICAgICovXG4gICAgc3RhdGljIF90b051bWVyaWNWYWx1ZSh2YWx1ZSwgc2V0dGluZ3MpIHtcbiAgICAgICAgLy9YWFggTm90ZTsgdGhpcyBmdW5jdGlvbiBpcyBzdGF0aWMgc2luY2Ugd2UgbmVlZCB0byBwYXNzIGEgYHNldHRpbmdzYCBvYmplY3Qgd2hlbiBjYWxsaW5nIHRoZSBzdGF0aWMgYEF1dG9OdW1lcmljLmZvcm1hdCgpYCBtZXRob2RcbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVtYmVyKE51bWJlcih2YWx1ZSkpKSB7XG4gICAgICAgICAgICAvLyBUaGUgdmFsdWUgaGFzIGVpdGhlciBhbHJlYWR5IGJlZW4gc3RyaXBwZWQsIG9yIGEgJ3JlYWwnIGphdmFzY3JpcHQgbnVtYmVyIGlzIHBhc3NlZCBhcyBhIHBhcmFtZXRlclxuICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNIZWxwZXIuc2NpZW50aWZpY1RvRGVjaW1hbCh2YWx1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBFbHNlIGlmIGl0J3MgYSBzdHJpbmcgdGhhdCBgTnVtYmVyKClgIGNhbm5vdCB0eXBlY2FzdCwgdGhlbiB3ZSB0cnkgdG8gY29udmVydCB0aGUgbG9jYWxpemVkIG51bWVyaWMgc3RyaW5nIHRvIGEgbnVtZXJpYyBvbmVcbiAgICAgICAgICAgIC8vIENvbnZlcnQgdGhlIHZhbHVlIHRvIGEgbnVtZXJpYyBzdHJpbmcsIHN0cmlwcGluZyB1bm5lY2Vzc2FyeSBjaGFyYWN0ZXJzIGluIHRoZSBwcm9jZXNzXG4gICAgICAgICAgICByZXN1bHQgPSB0aGlzLl9jb252ZXJ0VG9OdW1lcmljU3RyaW5nKHZhbHVlLnRvU3RyaW5nKCksIHNldHRpbmdzKTtcblxuICAgICAgICAgICAgLy8gSWYgdGhlIHJlc3VsdCBpcyBzdGlsbCBub3QgYSBudW1lcmljIHN0cmluZywgdGhlbiB3ZSB0aHJvdyBhIHdhcm5pbmdcbiAgICAgICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdW1iZXIoTnVtYmVyKHJlc3VsdCkpKSB7XG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZyhgVGhlIGdpdmVuIHZhbHVlIFwiJHt2YWx1ZX1cIiBjYW5ub3QgYmUgY29udmVydGVkIHRvIGEgbnVtZXJpYyBvbmUgYW5kIHRoZXJlZm9yZSBjYW5ub3QgYmUgdXNlZCBhcHByb3ByaWF0ZWx5LmAsIHNldHRpbmdzLnNob3dXYXJuaW5ncyk7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gTmFOO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIHBhc3RlZCB0ZXh0IHRoYXQgd2lsbCBiZSB1c2VkLCBieSBzdHJpcHBpbmcgbW9zdCBub24tbnVtZXJpYyBjaGFyYWN0ZXJzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdGV4dFxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgX3ByZXBhcmVQYXN0ZWRUZXh0KHRleHQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IuX3N0cmlwQWxsTm9uTnVtYmVyQ2hhcmFjdGVycyh0ZXh0LCB0aGlzLnNldHRpbmdzLCB0cnVlLCB0aGlzLmlzRm9jdXNlZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIFRSVUUgaWYgdGhlIGdpdmVuIHZhbHVlIChhIG51bWJlciBhcyBhIHN0cmluZykgaXMgd2l0aGluIHRoZSByYW5nZSBzZXQgaW4gdGhlIHNldHRpbmdzIGBtaW5pbXVtVmFsdWVgIGFuZCBgbWF4aW11bVZhbHVlYCwgRkFMU0Ugb3RoZXJ3aXNlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHBhcnNlZE1pblZhbHVlIFBhcnNlZCB2aWEgdGhlIGBwYXJzZVN0cigpYCBmdW5jdGlvblxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBwYXJzZWRNYXhWYWx1ZSBQYXJzZWQgdmlhIHRoZSBgcGFyc2VTdHIoKWAgZnVuY3Rpb25cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgX2NoZWNrSWZJblJhbmdlKHZhbHVlLCBwYXJzZWRNaW5WYWx1ZSwgcGFyc2VkTWF4VmFsdWUpIHtcbiAgICAgICAgY29uc3QgcGFyc2VkVmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5wYXJzZVN0cih2YWx1ZSk7XG4gICAgICAgIHJldHVybiBBdXRvTnVtZXJpY0hlbHBlci50ZXN0TWluTWF4KHBhcnNlZE1pblZhbHVlLCBwYXJzZWRWYWx1ZSkgPiAtMSAmJiBBdXRvTnVtZXJpY0hlbHBlci50ZXN0TWluTWF4KHBhcnNlZE1heFZhbHVlLCBwYXJzZWRWYWx1ZSkgPCAxO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZSB0aGUgc2VsZWN0aW9uIHZhbHVlcyBhcyB3ZWxsIGFzIHJlc2V0cyB0aGUgaW50ZXJuYWwgc3RhdGUgb2YgdGhlIGN1cnJlbnQgQXV0b051bWVyaWMgb2JqZWN0LlxuICAgICAqIFRoaXMga2VlcHMgdHJhY2tzIG9mIHRoZSBjdXJyZW50IHNlbGVjdGlvbiBhbmQgcmVzZXRzIHRoZSAncHJvY2Vzc2VkJyBzdGF0ZS5cbiAgICAgKlxuICAgICAqIE5vdGUgOiBUaGlzIHN0YXRlIGNhbiBjaGFuZ2UgYmV0d2VlbiB0aGUga2V5ZG93biwga2V5cHJlc3MgYW5kIGtleXVwIGV2ZW50cywgdGhhdCdzIHdoeVxuICAgICAqICAgICAgICB0aGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBvbiBlYWNoIGV2ZW50IGhhbmRsZXIuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF91cGRhdGVJbnRlcm5hbFByb3BlcnRpZXMoKSB7XG4gICAgICAgIHRoaXMuc2VsZWN0aW9uID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFNlbGVjdGlvbih0aGlzLmRvbUVsZW1lbnQpO1xuICAgICAgICB0aGlzLnByb2Nlc3NlZCA9IGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZSB0aGUgYGV2ZW50LmtleWAgYXR0cmlidXRlIHRoYXQgdHJpZ2dlcmVkIHRoZSBnaXZlbiBldmVudC5cbiAgICAgKlxuICAgICAqIGBldmVudC5rZXlgIGRlc2NyaWJlczpcbiAgICAgKiAtIHRoZSBrZXkgbmFtZSAoaWYgYSBub24tcHJpbnRhYmxlIGNoYXJhY3RlciksXG4gICAgICogLSBvciBkaXJlY3RseSB0aGUgY2hhcmFjdGVyIHRoYXQgcmVzdWx0IGZyb20gdGhlIGtleSBwcmVzcyB1c2VkIHRvIHRyaWdnZXIgdGhlIGV2ZW50LlxuICAgICAqXG4gICAgICogQGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0tleWJvYXJkRXZlbnQva2V5XG4gICAgICogVGhlIGtleSBsaXN0IGlzIGRlc2NyaWJlZCBoZXJlOlxuICAgICAqIEBsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9LZXlib2FyZEV2ZW50L2tleS9LZXlfVmFsdWVzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0V2ZW50fEtleWJvYXJkRXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF91cGRhdGVFdmVudEtleUluZm8oZSkge1xuICAgICAgICB0aGlzLmV2ZW50S2V5ID0gQXV0b051bWVyaWNIZWxwZXIuY2hhcmFjdGVyKGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNhdmUgdGhlIHVuZm9ybWF0dGVkIGVsZW1lbnQgdmFsdWUuXG4gICAgICogVGhpcyBpcyB1c2VkIGluIHRoZSAnY2FuY2VsbGFibGUnIGZlYXR1cmUgd2hlcmUgdGhlIGVsZW1lbnQgdmFsdWUgaXMgc2F2ZWQgb24gZm9jdXMgYW5kIGlucHV0IHZhbGlkYXRpb24sIHRvIGJlIHVzZWQgaWYgdGhlIHVzZXIgd2FudHMgdG8gY2FuY2VsIGhpcyBtb2RpZmljYXRpb25zIGJ5IGhpdHRpbmcgdGhlICdFc2NhcGUnIGtleS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3NhdmVDYW5jZWxsYWJsZVZhbHVlKCkge1xuICAgICAgICB0aGlzLnNhdmVkQ2FuY2VsbGFibGVWYWx1ZSA9IHRoaXMucmF3VmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSB0ZXh0IHNlbGVjdGlvbiBpbnNpZGUgdGhlIGlucHV0IHdpdGggdGhlIGdpdmVuIHN0YXJ0IGFuZCBlbmQgcG9zaXRpb24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2ludH0gc3RhcnRcbiAgICAgKiBAcGFyYW0ge2ludH0gZW5kXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfc2V0U2VsZWN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgICAgICAgLy9UT0RPIHVzZSB0aGlzIGZ1bmN0aW9uIHRvIHJlcGxhY2UgdGhlIGRpcmVjdCBjYWxscyB0byBgc2V0RWxlbWVudFNlbGVjdGlvbigpYCwgd2hlcmV2ZXIgcG9zc2libGVcbiAgICAgICAgc3RhcnQgPSBNYXRoLm1heChzdGFydCwgMCk7XG4gICAgICAgIGVuZCA9IE1hdGgubWluKGVuZCwgQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCkubGVuZ3RoKTtcbiAgICAgICAgdGhpcy5zZWxlY3Rpb24gPSB7XG4gICAgICAgICAgICBzdGFydCxcbiAgICAgICAgICAgIGVuZCxcbiAgICAgICAgICAgIGxlbmd0aDogZW5kIC0gc3RhcnQsXG4gICAgICAgIH07XG5cbiAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFNlbGVjdGlvbih0aGlzLmRvbUVsZW1lbnQsIHN0YXJ0LCBlbmQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgY2FyZXQgcG9zaXRpb24gaW5zaWRlIHRoZSBpbnB1dCBhdCB0aGUgZ2l2ZW4gcG9zaXRpb24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2ludH0gcG9zaXRpb25cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9zZXRDYXJldFBvc2l0aW9uKHBvc2l0aW9uKSB7XG4gICAgICAgIHRoaXMuX3NldFNlbGVjdGlvbihwb3NpdGlvbiwgcG9zaXRpb24pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhbiBhcnJheSBjb250YWluaW5nIHRoZSBzdHJpbmcgcGFydHMgbG9jYXRlZCBvbiB0aGUgbGVmdCBhbmQgcmlnaHQgc2lkZSBvZiB0aGUgY2FyZXQgb3Igc2VsZWN0aW9uLlxuICAgICAqIFRob3NlIHBhcnRzIGFyZSBsZWZ0ICd1bnRvdWNoZWQnLCBpZS4gZm9ybWF0dGVkIGJ5IGF1dG9OdW1lcmljLlxuICAgICAqXG4gICAgICogQHJldHVybnMge1tzdHJpbmcsIHN0cmluZ119IFRoZSBwYXJ0cyBvbiB0aGUgbGVmdCBhbmQgcmlnaHQgb2YgdGhlIGNhcmV0IG9yIHNlbGVjdGlvblxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2dldExlZnRBbmRSaWdodFBhcnRBcm91bmRUaGVTZWxlY3Rpb24oKSB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCk7XG4gICAgICAgIGNvbnN0IGxlZnQgPSB2YWx1ZS5zdWJzdHJpbmcoMCwgdGhpcy5zZWxlY3Rpb24uc3RhcnQpO1xuICAgICAgICBjb25zdCByaWdodCA9IHZhbHVlLnN1YnN0cmluZyh0aGlzLnNlbGVjdGlvbi5lbmQsIHZhbHVlLmxlbmd0aCk7XG5cbiAgICAgICAgcmV0dXJuIFtsZWZ0LCByaWdodF07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIHN0cmluZyBwYXJ0cyBsb2NhdGVkIG9uIHRoZSBsZWZ0IGFuZCByaWdodCBzaWRlIG9mIHRoZSBjYXJldCBvciBzZWxlY3Rpb24uXG4gICAgICogVGhvc2UgcGFydHMgYXJlIHVuZm9ybWF0dGVkIChzdHJpcHBlZCkgb2YgYW55IG5vbi1udW1iZXJzIGNoYXJhY3RlcnMsIGFuZCBhbnkgdHJhaWxpbmcgbmVnYXRpdmUgY2hhcmFjdGVyIGlzIHB1dCBiYWNrIG9uIHRoZSBsZWZ0IGhhbmQgc2lkZSBvZiB0aGUgbnVtYmVyLlxuICAgICAqXG4gICAgICogQHJldHVybnMge1tzdHJpbmcsIHN0cmluZ119IFRoZSBwYXJ0cyBvbiB0aGUgbGVmdCBhbmQgcmlnaHQgb2YgdGhlIGNhcmV0IG9yIHNlbGVjdGlvbiwgdW5mb3JtYXR0ZWQuXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZ2V0VW5mb3JtYXR0ZWRMZWZ0QW5kUmlnaHRQYXJ0QXJvdW5kVGhlU2VsZWN0aW9uKCkge1xuICAgICAgICBsZXQgW2xlZnQsIHJpZ2h0XSA9IHRoaXMuX2dldExlZnRBbmRSaWdodFBhcnRBcm91bmRUaGVTZWxlY3Rpb24oKTtcbiAgICAgICAgaWYgKGxlZnQgPT09ICcnICYmIHJpZ2h0ID09PSAnJykge1xuICAgICAgICAgICAgcmV0dXJuIFsnJywgJyddO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgY2hhbmdpbmcgdGhlIHNpZ24gYW5kIGBsZWZ0YCBpcyBlcXVhbCB0byB0aGUgbnVtYmVyIHplcm8sIHByZXZlbnQgc3RyaXBwaW5nIHRoZSBsZWFkaW5nIHplcm8ocylcbiAgICAgICAgbGV0IHN0cmlwWmVyb3MgPSB0cnVlO1xuICAgICAgICBpZiAoKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkh5cGhlbiB8fCB0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5NaW51cykgJiYgTnVtYmVyKGxlZnQpID09PSAwKSB7XG4gICAgICAgICAgICBzdHJpcFplcm9zID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICAvL1RPRE8gRFJZIHRoYXQgd2l0aCBgX25vcm1hbGl6ZVBhcnRzKClgIC0tPlxuICAgICAgICBpZiAodGhpcy5pc1RyYWlsaW5nTmVnYXRpdmUgJiZcbiAgICAgICAgICAgICgoQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZShyaWdodCwgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpICYmIC8vIFRoZSBjYXJldCBpcyBwbGFjZWQgb24gdGhlIGxlZnQgb2YgdGhlIG5lZ2F0aXZlIHNpZ25cbiAgICAgICAgICAgICFBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlKGxlZnQsIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSkgfHxcbiAgICAgICAgICAgIChyaWdodCA9PT0gJycgJiYgLy8gLi5vciB0aGUgY2FyZXQgaXMgcGxhY2VkIG9uIHRoZSBmYXIgcmlnaHQgb2YgdGhlIGlucHV0IChGaXggaXNzdWUgIzQ4MSlcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmUobGVmdCwgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIsIHRydWUpKSkpIHtcbiAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnJlcGxhY2UodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIsICcnKTtcbiAgICAgICAgICAgIHJpZ2h0ID0gcmlnaHQucmVwbGFjZSh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciwgJycpO1xuICAgICAgICAgICAgLy8gVGhpcyBpcyBkb25lIGhlcmUgYmVjYXVzZSBgX2dldFVuZm9ybWF0dGVkTGVmdEFuZFJpZ2h0UGFydEFyb3VuZFRoZVNlbGVjdGlvbigpYCBpcyBjYWxsZWQgbXVsdGlwbGUgdGltZXMgZHVyaW5nIHRoZSBzYW1lIGtleSBldmVudCwgYW5kIGF0IG9uZSBwb2ludCB0aGUgbGVmdC9yaWdodCB2YWx1ZSBoYXMgYmVlbiBub3JtYWxpemVkIGFscmVhZHkuLlxuICAgICAgICAgICAgbGVmdCA9IGxlZnQucmVwbGFjZSgnLScsICcnKTtcbiAgICAgICAgICAgIHJpZ2h0ID0gcmlnaHQucmVwbGFjZSgnLScsICcnKTtcblxuICAgICAgICAgICAgLy8gVGhlbiBmaW5hbGx5IHNldCBiYWNrIHRoZSBub3JtYWxpemVkIG1pbnVzIGNoYXJhY3RlciBhdCB0aGUgcmlnaHQgcGxhY2VcbiAgICAgICAgICAgIGxlZnQgPSBgLSR7bGVmdH1gO1xuICAgICAgICB9XG5cbiAgICAgICAgbGVmdCA9IEF1dG9OdW1lcmljLl9zdHJpcEFsbE5vbk51bWJlckNoYXJhY3RlcnNFeGNlcHRDdXN0b21EZWNpbWFsQ2hhcihsZWZ0LCB0aGlzLnNldHRpbmdzLCBzdHJpcFplcm9zLCB0aGlzLmlzRm9jdXNlZCk7XG4gICAgICAgIHJpZ2h0ID0gQXV0b051bWVyaWMuX3N0cmlwQWxsTm9uTnVtYmVyQ2hhcmFjdGVyc0V4Y2VwdEN1c3RvbURlY2ltYWxDaGFyKHJpZ2h0LCB0aGlzLnNldHRpbmdzLCBmYWxzZSwgdGhpcy5pc0ZvY3VzZWQpO1xuXG4gICAgICAgIHJldHVybiBbbGVmdCwgcmlnaHRdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN0cmlwIHBhcnRzIGZyb20gZXhjZXNzIGNoYXJhY3RlcnMgYW5kIGxlYWRpbmcgemVyb3MuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGVmdFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSByaWdodFxuICAgICAqIEByZXR1cm5zIHtbKiwqLCpdfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX25vcm1hbGl6ZVBhcnRzKGxlZnQsIHJpZ2h0KSB7XG4gICAgICAgIC8vVE9ETyBSZWZhY3RvciB3aXRoIGBfZ2V0VW5mb3JtYXR0ZWRMZWZ0QW5kUmlnaHRQYXJ0QXJvdW5kVGhlU2VsZWN0aW9uYCB3aGljaCBzaGFyZSBhIGxvdCBvZiBzaW1pbGFyIGNvZGVcbiAgICAgICAgLy8gSWYgY2hhbmdpbmcgdGhlIHNpZ24gYW5kIGxlZnQgaXMgZXF1YWwgdG8gdGhlIG51bWJlciB6ZXJvIC0gcHJldmVudHMgc3RyaXBwaW5nIHRoZSBsZWFkaW5nIHplcm9zXG4gICAgICAgIGxldCBzdHJpcFplcm9zID0gdHJ1ZTtcbiAgICAgICAgaWYgKCh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5IeXBoZW4gfHwgdGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuTWludXMpICYmIE51bWJlcihsZWZ0KSA9PT0gMCkge1xuICAgICAgICAgICAgc3RyaXBaZXJvcyA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuaXNUcmFpbGluZ05lZ2F0aXZlICYmXG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlKHJpZ2h0LCB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikgJiZcbiAgICAgICAgICAgICFBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlKGxlZnQsIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgLy8gT25seSBzZXQgdGhlIG5lZ2F0aXZlIHNpZ24gaWYgdGhlIHZhbHVlIGlzIG5lZ2F0aXZlXG4gICAgICAgICAgICBsZWZ0ID0gYC0ke2xlZnR9YDtcbiAgICAgICAgICAgIHJpZ2h0ID0gcmlnaHQucmVwbGFjZSh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciwgJycpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGVmdCA9IEF1dG9OdW1lcmljLl9zdHJpcEFsbE5vbk51bWJlckNoYXJhY3RlcnNFeGNlcHRDdXN0b21EZWNpbWFsQ2hhcihsZWZ0LCB0aGlzLnNldHRpbmdzLCBzdHJpcFplcm9zLCB0aGlzLmlzRm9jdXNlZCk7XG4gICAgICAgIHJpZ2h0ID0gQXV0b051bWVyaWMuX3N0cmlwQWxsTm9uTnVtYmVyQ2hhcmFjdGVyc0V4Y2VwdEN1c3RvbURlY2ltYWxDaGFyKHJpZ2h0LCB0aGlzLnNldHRpbmdzLCBmYWxzZSwgdGhpcy5pc0ZvY3VzZWQpO1xuXG4gICAgICAgIC8vIFByZXZlbnRzIG11bHRpcGxlIGxlYWRpbmcgemVyb3MgZnJvbSBiZWluZyBlbnRlcmVkXG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmxlYWRpbmdaZXJvID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmxlYWRpbmdaZXJvLmRlbnkgJiZcbiAgICAgICAgICAgICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5udW0wIHx8IHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLm51bXBhZDApICYmXG4gICAgICAgICAgICBOdW1iZXIobGVmdCkgPT09IDAgJiZcbiAgICAgICAgICAgIC8vIElmIGByaWdodGAgaXMgbm90IGVtcHR5IGFuZCB0aGUgZmlyc3QgY2hhcmFjdGVyIGlzIG5vdCBgZGVjaW1hbENoYXJhY3RlcmBcbiAgICAgICAgICAgICFBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyhsZWZ0LCB0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpICYmIHJpZ2h0ICE9PSAnJykge1xuICAgICAgICAgICAgbGVmdCA9IGxlZnQuc3Vic3RyaW5nKDAsIGxlZnQubGVuZ3RoIC0gMSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJbnNlcnQgemVybyB0aGVyZSBpcyBhIGxlYWRpbmcgZG90XG4gICAgICAgIGxldCBuZXdWYWx1ZSA9IGxlZnQgKyByaWdodDtcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlcikge1xuICAgICAgICAgICAgY29uc3QgbSA9IG5ld1ZhbHVlLm1hdGNoKG5ldyBSZWdFeHAoYF4ke3RoaXMucmVnZXguYU5lZ1JlZ0F1dG9TdHJpcH1cXFxcJHt0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXJ9YCkpO1xuICAgICAgICAgICAgaWYgKG0pIHtcbiAgICAgICAgICAgICAgICBsZWZ0ID0gbGVmdC5yZXBsYWNlKG1bMV0sIG1bMV0gKyAnMCcpO1xuICAgICAgICAgICAgICAgIG5ld1ZhbHVlID0gbGVmdCArIHJpZ2h0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFtsZWZ0LCByaWdodCwgbmV3VmFsdWVdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgZm9ybWF0dGVkIGVsZW1lbnQgdmFsdWUgYXMgd2VsbCBhcyB0aGUgYHJhd1ZhbHVlYC5cbiAgICAgKiBUaGlzIHJldHVybnMgYHRydWVgIGlmIHRoZSBlbGVtZW50IGFuZCByYXcgdmFsdWUgaGF2ZSBiZWVuIG1vZGlmaWVkLCBgZmFsc2VgIG90aGVyd2lzZS5cbiAgICAgKiBUaGlzIG1ldGhvZCBhbHNvIGFkanVzdCB0aGUgY2FyZXQgcG9zaXRpb24gYWNjb3JkaW5nIHRvIHRoZSBgbGVhZGluZ1plcm9gIG9wdGlvbiBhbmQgdGhlIG5vcm1hbGl6ZWQgdmFsdWUuIC8vVE9ETyBXaGF0IGFib3V0IHRoZSBjdXJzb3IgKnNlbGVjdGlvbio/XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGVmdFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSByaWdodFxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNQYXN0ZVxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3NldFZhbHVlUGFydHMobGVmdCwgcmlnaHQsIGlzUGFzdGUgPSBmYWxzZSkge1xuICAgICAgICBjb25zdCBbbm9ybWFsaXplZExlZnQsIG5vcm1hbGl6ZWRSaWdodCwgbm9ybWFsaXplZE5ld1ZhbHVlXSA9IHRoaXMuX25vcm1hbGl6ZVBhcnRzKGxlZnQsIHJpZ2h0KTtcbiAgICAgICAgY29uc3QgW21pblRlc3QsIG1heFRlc3RdID0gQXV0b051bWVyaWMuX2NoZWNrSWZJblJhbmdlV2l0aE92ZXJyaWRlT3B0aW9uKG5vcm1hbGl6ZWROZXdWYWx1ZSwgdGhpcy5zZXR0aW5ncyk7XG5cbiAgICAgICAgaWYgKG1pblRlc3QgJiYgbWF4VGVzdCkge1xuICAgICAgICAgICAgLy8gRmlyc3QsIHNldCB0aGUgcmF3IHZhbHVlXG4gICAgICAgICAgICBjb25zdCByb3VuZGVkUmF3VmFsdWUgPSBBdXRvTnVtZXJpYy5fdHJ1bmNhdGVEZWNpbWFsUGxhY2VzKG5vcm1hbGl6ZWROZXdWYWx1ZSwgdGhpcy5zZXR0aW5ncywgaXNQYXN0ZSwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUpO1xuICAgICAgICAgICAgY29uc3QgdGVzdFZhbHVlID0gcm91bmRlZFJhd1ZhbHVlLnJlcGxhY2UodGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyLCAnLicpO1xuXG4gICAgICAgICAgICBpZiAodGVzdFZhbHVlID09PSAnJyB8fCB0ZXN0VmFsdWUgPT09IHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSB7XG4gICAgICAgICAgICAgICAgbGV0IHZhbHVlVG9TZXRPbkVtcHR5O1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5zZXR0aW5ncy5lbXB0eUlucHV0QmVoYXZpb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5mb2N1czpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5wcmVzczpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5hbHdheXM6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVRvU2V0T25FbXB0eSA9ICcnO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IubWluOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVUb1NldE9uRW1wdHkgPSB0aGlzLnNldHRpbmdzLm1pbmltdW1WYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLm1heDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlVG9TZXRPbkVtcHR5ID0gdGhpcy5zZXR0aW5ncy5tYXhpbXVtVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci56ZXJvOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVUb1NldE9uRW1wdHkgPSAnMCc7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5udWxsOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVUb1NldE9uRW1wdHkgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdoZW4gYGVtcHR5SW5wdXRCZWhhdmlvcmAgaXMgYSBudW1iZXIgb3IgYSBzdHJpbmcgcmVwcmVzZW50aW5nIGEgbnVtYmVyXG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVRvU2V0T25FbXB0eSA9IHRoaXMuc2V0dGluZ3MuZW1wdHlJbnB1dEJlaGF2aW9yO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuX3NldFJhd1ZhbHVlKHZhbHVlVG9TZXRPbkVtcHR5KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0UmF3VmFsdWUodGhpcy5fdHJpbUxlYWRpbmdBbmRUcmFpbGluZ1plcm9zKHRlc3RWYWx1ZSkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBUaGVuIHNldCB0aGUgZm9ybWF0dGVkIHZhbHVlXG4gICAgICAgICAgICBjb25zdCByb3VuZGVkVmFsdWVUb1Nob3cgPSBBdXRvTnVtZXJpYy5fdHJ1bmNhdGVEZWNpbWFsUGxhY2VzKG5vcm1hbGl6ZWROZXdWYWx1ZSwgdGhpcy5zZXR0aW5ncywgaXNQYXN0ZSwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzKTtcbiAgICAgICAgICAgIGxldCBwb3NpdGlvbiA9IG5vcm1hbGl6ZWRMZWZ0Lmxlbmd0aDtcbiAgICAgICAgICAgIGlmIChwb3NpdGlvbiA+IHJvdW5kZWRWYWx1ZVRvU2hvdy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHJvdW5kZWRWYWx1ZVRvU2hvdy5sZW5ndGg7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIE1ha2Ugc3VyZSB3aGVuIHRoZSB1c2VyIGVudGVyIGEgJzAnIG9uIHRoZSBmYXIgbGVmdCB3aXRoIGEgbGVhZGluZyB6ZXJvIG9wdGlvbiBzZXQgdG8gJ2RlbnknLCB0aGF0IHRoZSBjYXJldCBkb2VzIG5vdCBtb3ZlcyBzaW5jZSB0aGUgaW5wdXQgaXMgZHJvcHBlZCAoZml4IGlzc3VlICMyODMpXG4gICAgICAgICAgICBpZiAocG9zaXRpb24gPT09IDEgJiYgbm9ybWFsaXplZExlZnQgPT09ICcwJyAmJiB0aGlzLnNldHRpbmdzLmxlYWRpbmdaZXJvID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmxlYWRpbmdaZXJvLmRlbnkpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgdXNlciBlbnRlciBgMGAsIHRoZW4gdGhlIGNhcmV0IGlzIHB1dCBvbiB0aGUgcmlnaHQgc2lkZSBvZiBpdCAoRml4IGlzc3VlICMyOTkpXG4gICAgICAgICAgICAgICAgaWYgKG5vcm1hbGl6ZWRSaWdodCA9PT0gJycgfHwgbm9ybWFsaXplZExlZnQgPT09ICcwJyAmJiBub3JtYWxpemVkUmlnaHQgIT09ICcnKSB7XG4gICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gMTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9zZXRFbGVtZW50VmFsdWUocm91bmRlZFZhbHVlVG9TaG93LCBmYWxzZSk7XG4gICAgICAgICAgICB0aGlzLl9zZXRDYXJldFBvc2l0aW9uKHBvc2l0aW9uKTtcblxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIW1pblRlc3QpIHtcbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMubWluUmFuZ2VFeGNlZWRlZCwgdGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgfSBlbHNlIGlmICghbWF4VGVzdCkge1xuICAgICAgICAgICAgdGhpcy5fdHJpZ2dlckV2ZW50KEF1dG9OdW1lcmljLmV2ZW50cy5tYXhSYW5nZUV4Y2VlZGVkLCB0aGlzLmRvbUVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhlbHBlciBmdW5jdGlvbiBmb3IgYF9leHBhbmRTZWxlY3Rpb25PblNpZ24oKWAuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IGNvbnRhaW5pbmcgW3NpZ25Qb3NpdGlvbiwgY3VycmVuY3lTeW1ib2xQb3NpdGlvbl0gb2YgYSBmb3JtYXR0ZWQgdmFsdWVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9nZXRTaWduUG9zaXRpb24oKSB7XG4gICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sKSB7XG4gICAgICAgICAgICBjb25zdCBjdXJyZW5jeVN5bWJvbExlbiA9IHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wubGVuZ3RoO1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnByZWZpeCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGhhc05lZyA9IHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyICYmIHZhbHVlICYmIHZhbHVlLmNoYXJBdCgwKSA9PT0gdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXI7XG4gICAgICAgICAgICAgICAgaWYgKGhhc05lZykge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBbMSwgY3VycmVuY3lTeW1ib2xMZW4gKyAxXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBbMCwgY3VycmVuY3lTeW1ib2xMZW5dO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdmFsdWVMZW4gPSB2YWx1ZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gW3ZhbHVlTGVuIC0gY3VycmVuY3lTeW1ib2xMZW4sIHZhbHVlTGVuXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IFsxMDAwLCAtMV07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV4cGFuZHMgc2VsZWN0aW9uIHRvIGNvdmVyIHdob2xlIHNpZ25cbiAgICAgKiBQcmV2ZW50cyBwYXJ0aWFsIGRlbGV0aW9uL2NvcHlpbmcvb3ZlcndyaXRpbmcgb2YgYSBzaWduXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZXhwYW5kU2VsZWN0aW9uT25TaWduKCkge1xuICAgICAgICBjb25zdCBbc2lnblBvc2l0aW9uLCBjdXJyZW5jeVN5bWJvbFBvc2l0aW9uXSA9IHRoaXMuX2dldFNpZ25Qb3NpdGlvbigpO1xuICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSB0aGlzLnNlbGVjdGlvbjtcblxuICAgICAgICAvLyBJZiBzZWxlY3Rpb24gY2F0Y2hlcyBzb21ldGhpbmcgZXhjZXB0IHNpZ24gYW5kIGNhdGNoZXMgb25seSBzcGFjZSBmcm9tIHNpZ25cbiAgICAgICAgaWYgKHNlbGVjdGlvbi5zdGFydCA8IGN1cnJlbmN5U3ltYm9sUG9zaXRpb24gJiYgc2VsZWN0aW9uLmVuZCA+IHNpZ25Qb3NpdGlvbikge1xuICAgICAgICAgICAgLy8gVGhlbiBzZWxlY3Qgd2l0aG91dCBlbXB0eSBzcGFjZVxuICAgICAgICAgICAgaWYgKChzZWxlY3Rpb24uc3RhcnQgPCBzaWduUG9zaXRpb24gfHwgc2VsZWN0aW9uLmVuZCA+IGN1cnJlbmN5U3ltYm9sUG9zaXRpb24pICYmXG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCkuc3Vic3RyaW5nKE1hdGgubWF4KHNlbGVjdGlvbi5zdGFydCwgc2lnblBvc2l0aW9uKSwgTWF0aC5taW4oc2VsZWN0aW9uLmVuZCwgY3VycmVuY3lTeW1ib2xQb3NpdGlvbikpXG4gICAgICAgICAgICAgICAgICAgIC5tYXRjaCgvXlxccyokLykpIHtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZWN0aW9uLnN0YXJ0IDwgc2lnblBvc2l0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFNlbGVjdGlvbihzZWxlY3Rpb24uc3RhcnQsIHNpZ25Qb3NpdGlvbik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0U2VsZWN0aW9uKGN1cnJlbmN5U3ltYm9sUG9zaXRpb24sIHNlbGVjdGlvbi5lbmQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gRWxzZSBzZWxlY3Qgd2l0aCB3aG9sZSBzaWduXG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0U2VsZWN0aW9uKE1hdGgubWluKHNlbGVjdGlvbi5zdGFydCwgc2lnblBvc2l0aW9uKSwgTWF0aC5tYXgoc2VsZWN0aW9uLmVuZCwgY3VycmVuY3lTeW1ib2xQb3NpdGlvbikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVHJ5IHRvIHN0cmlwIHBhc3RlZCB2YWx1ZSB0byBkaWdpdHNcbiAgICAgKi9cbiAgICBfY2hlY2tQYXN0ZSgpIHtcbiAgICAgICAgLy8gRG8gbm90IHByb2Nlc3MgYW55dGhpbmcgaWYgdGhlIHZhbHVlIGhhcyBhbHJlYWR5IGJlZW4gZm9ybWF0dGVkXG4gICAgICAgIGlmICh0aGlzLmZvcm1hdHRlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZCh0aGlzLnZhbHVlUGFydHNCZWZvcmVQYXN0ZSkpIHtcbiAgICAgICAgICAgIGNvbnN0IG9sZFBhcnRzID0gdGhpcy52YWx1ZVBhcnRzQmVmb3JlUGFzdGU7XG4gICAgICAgICAgICBjb25zdCBbbGVmdCwgcmlnaHRdID0gdGhpcy5fZ2V0TGVmdEFuZFJpZ2h0UGFydEFyb3VuZFRoZVNlbGVjdGlvbigpO1xuXG4gICAgICAgICAgICAvLyBUcnkgdG8gc3RyaXAgdGhlIHBhc3RlZCB2YWx1ZSBmaXJzdFxuICAgICAgICAgICAgZGVsZXRlIHRoaXMudmFsdWVQYXJ0c0JlZm9yZVBhc3RlO1xuXG4gICAgICAgICAgICBjb25zdCBtb2RpZmllZExlZnRQYXJ0ID0gbGVmdC5zdWJzdHIoMCwgb2xkUGFydHNbMF0ubGVuZ3RoKSArIEF1dG9OdW1lcmljLl9zdHJpcEFsbE5vbk51bWJlckNoYXJhY3RlcnNFeGNlcHRDdXN0b21EZWNpbWFsQ2hhcihsZWZ0LnN1YnN0cihvbGRQYXJ0c1swXS5sZW5ndGgpLCB0aGlzLnNldHRpbmdzLCB0cnVlLCB0aGlzLmlzRm9jdXNlZCk7XG4gICAgICAgICAgICBpZiAoIXRoaXMuX3NldFZhbHVlUGFydHMobW9kaWZpZWRMZWZ0UGFydCwgcmlnaHQsIHRydWUpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0RWxlbWVudFZhbHVlKG9sZFBhcnRzLmpvaW4oJycpLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0Q2FyZXRQb3NpdGlvbihvbGRQYXJ0c1swXS5sZW5ndGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgZ2l2ZW4ga2V5IHNob3VsZCBiZSBpZ25vcmVkIG9yIG5vdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBldmVudEtleU5hbWVcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfc2hvdWxkU2tpcEV2ZW50S2V5KGV2ZW50S2V5TmFtZSkge1xuICAgICAgICBjb25zdCBpc0ZuS2V5cyA9IEF1dG9OdW1lcmljSGVscGVyLmlzSW5BcnJheShldmVudEtleU5hbWUsIEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLl9hbGxGbktleXMpO1xuICAgICAgICBjb25zdCBpc09TS2V5cyA9IGV2ZW50S2V5TmFtZSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuT1NMZWZ0IHx8IGV2ZW50S2V5TmFtZSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuT1NSaWdodDtcbiAgICAgICAgY29uc3QgaXNDb250ZXh0TWVudSA9IGV2ZW50S2V5TmFtZSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuQ29udGV4dE1lbnU7XG4gICAgICAgIGNvbnN0IGlzU29tZU5vblByaW50YWJsZUtleXMgPSBBdXRvTnVtZXJpY0hlbHBlci5pc0luQXJyYXkoZXZlbnRLZXlOYW1lLCBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5fc29tZU5vblByaW50YWJsZUtleXMpO1xuICAgICAgICBjb25zdCBpc090aGVyTm9uUHJpbnRhYmxlS2V5cyA9IGV2ZW50S2V5TmFtZSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuTnVtTG9jayB8fFxuICAgICAgICAgICAgZXZlbnRLZXlOYW1lID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5TY3JvbGxMb2NrIHx8XG4gICAgICAgICAgICBldmVudEtleU5hbWUgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkluc2VydCB8fFxuICAgICAgICAgICAgZXZlbnRLZXlOYW1lID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5Db21tYW5kO1xuICAgICAgICBjb25zdCBpc1VucmVjb2duaXphYmxlS2V5cyA9IGV2ZW50S2V5TmFtZSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuVW5pZGVudGlmaWVkO1xuXG4gICAgICAgIHJldHVybiBpc0ZuS2V5cyB8fCBpc09TS2V5cyB8fCBpc0NvbnRleHRNZW51IHx8IGlzU29tZU5vblByaW50YWJsZUtleXMgfHwgaXNVbnJlY29nbml6YWJsZUtleXMgfHwgaXNPdGhlck5vblByaW50YWJsZUtleXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJvY2VzcyBjb3B5aW5nLCBjdXR0aW5nIGFuZCBwYXN0aW5nLCBhcyB3ZWxsIGFzIHVuZG8vcmVkb2luZyBhbmQgY3Vyc29yIG1vdmluZy5cbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIGZ1cnRoZXIgcHJvY2Vzc2luZyBzaG91bGQgbm90IGJlIHBlcmZvcm1lZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7S2V5Ym9hcmRFdmVudH0gZVxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3Byb2Nlc3NOb25QcmludGFibGVLZXlzQW5kU2hvcnRjdXRzKGUpIHtcbiAgICAgICAgLy8gQ2F0Y2ggdGhlIGN0cmwgdXAgb24gY3RybC12XG4gICAgICAgIGlmICgoKGUuY3RybEtleSB8fCBlLm1ldGFLZXkpICYmIGUudHlwZSA9PT0gJ2tleXVwJyAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWQodGhpcy52YWx1ZVBhcnRzQmVmb3JlUGFzdGUpKSB8fCAoZS5zaGlmdEtleSAmJiB0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5JbnNlcnQpKSB7XG4gICAgICAgICAgICAvL1RPRE8gTW92ZSB0aGlzIHRlc3QgaW5zaWRlIHRoZSBgb25LZXl1cGAgaGFuZGxlclxuICAgICAgICAgICAgdGhpcy5fY2hlY2tQYXN0ZSgpO1xuXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTa2lwIGFsbCBmdW5jdGlvbiBrZXlzIChGMS1GMTIpLCBXaW5kb3dzIGtleXMsIHRhYiBhbmQgb3RoZXIgc3BlY2lhbCBrZXlzXG4gICAgICAgIGlmICh0aGlzLmNvbnN0cnVjdG9yLl9zaG91bGRTa2lwRXZlbnRLZXkodGhpcy5ldmVudEtleSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgYSBcIlNlbGVjdCBhbGxcIiBrZXlib2FyZCBzaG9ydGN1dCBpcyBkZXRlY3RlZCAoY3RybCArIGEpXG4gICAgICAgIGlmICgoZS5jdHJsS2V5IHx8IGUubWV0YUtleSkgJiYgdGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuYSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3Muc2VsZWN0TnVtYmVyT25seSkge1xuICAgICAgICAgICAgICAgIC8vIGBwcmV2ZW50RGVmYXVsdCgpYCBpcyB1c2VkIGhlcmUgdG8gcHJldmVudCB0aGUgYnJvd3NlciB0byBmaXJzdCBzZWxlY3QgYWxsIHRoZSBpbnB1dCB0ZXh0IChpbmNsdWRpbmcgdGhlIGN1cnJlbmN5IHNpZ24pLCBvdGhlcndpc2Ugd2Ugd291bGQgc2VlIHRoYXQgd2hvbGUgc2VsZWN0aW9uIGZpcnN0IGluIGEgZmxhc2gsIHRoZW4gdGhlIHNlbGVjdGlvbiB3aXRoIG9ubHkgdGhlIG51bWJlciBwYXJ0IHdpdGhvdXQgdGhlIGN1cnJlbmN5IHNpZ24uXG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIC8vVE9ETyByZXBsYWNlIGBzZWxlY3ROdW1iZXJgIGJ5IGBzZWxlY3RgP1xuICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0TnVtYmVyKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgYSBcIkNvcHlcIiwgXCJQYXN0ZVwiIG9yIFwiQ3V0XCIga2V5Ym9hcmQgc2hvcnRjdXQgaXMgZGV0ZWN0ZWQgKHJlc3BlY3RpdmVseSAnY3RybCArIGMnLCAnY3RybCArIHYnIG9yICdjdHJsICsgeCcpXG4gICAgICAgIGlmICgoZS5jdHJsS2V5IHx8IGUubWV0YUtleSkgJiZcbiAgICAgICAgICAgICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5jIHx8XG4gICAgICAgICAgICAgdGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUudiB8fFxuICAgICAgICAgICAgIHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLngpKSB7XG4gICAgICAgICAgICBpZiAoZS50eXBlID09PSAna2V5ZG93bicpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9leHBhbmRTZWxlY3Rpb25PblNpZ24oKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gVHJ5IHRvIHByZXZlbnQgd3JvbmcgcGFzdGVcbiAgICAgICAgICAgIGlmICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS52IHx8IHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkluc2VydCkge1xuICAgICAgICAgICAgICAgIGlmIChlLnR5cGUgPT09ICdrZXlkb3duJyB8fCBlLnR5cGUgPT09ICdrZXlwcmVzcycpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkKHRoaXMudmFsdWVQYXJ0c0JlZm9yZVBhc3RlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy52YWx1ZVBhcnRzQmVmb3JlUGFzdGUgPSB0aGlzLl9nZXRMZWZ0QW5kUmlnaHRQYXJ0QXJvdW5kVGhlU2VsZWN0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jaGVja1Bhc3RlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gZS50eXBlID09PSAna2V5ZG93bicgfHwgZS50eXBlID09PSAna2V5cHJlc3MnIHx8IHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLmM7XG4gICAgICAgIH1cblxuXG4gICAgICAgIC8vIFRoZSB1bmRvIHNob3J0Y3V0XG4gICAgICAgIGlmIChlLmN0cmxLZXkgfHwgZS5tZXRhS2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gISh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5aIHx8IHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLnopO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSnVtcCBvdmVyIHRoZSB0aG91c2FuZCBzZXBhcmF0b3JcbiAgICAgICAgLy9UT0RPIE1vdmUgdGhpcyB0ZXN0IGluc2lkZSB0aGUgYG9uS2V5ZG93bmAgaGFuZGxlclxuICAgICAgICBpZiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuTGVmdEFycm93IHx8IHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLlJpZ2h0QXJyb3cpIHtcbiAgICAgICAgICAgIGlmIChlLnR5cGUgPT09ICdrZXlkb3duJyAmJiAhZS5zaGlmdEtleSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkxlZnRBcnJvdyAmJlxuICAgICAgICAgICAgICAgICAgICAodmFsdWUuY2hhckF0KHRoaXMuc2VsZWN0aW9uLnN0YXJ0IC0gMikgPT09IHRoaXMuc2V0dGluZ3MuZGlnaXRHcm91cFNlcGFyYXRvciB8fFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZS5jaGFyQXQodGhpcy5zZWxlY3Rpb24uc3RhcnQgLSAyKSA9PT0gdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRDYXJldFBvc2l0aW9uKHRoaXMuc2VsZWN0aW9uLnN0YXJ0IC0gMSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5SaWdodEFycm93ICYmXG4gICAgICAgICAgICAgICAgICAgICh2YWx1ZS5jaGFyQXQodGhpcy5zZWxlY3Rpb24uc3RhcnQgKyAxKSA9PT0gdGhpcy5zZXR0aW5ncy5kaWdpdEdyb3VwU2VwYXJhdG9yIHx8XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlLmNoYXJBdCh0aGlzLnNlbGVjdGlvbi5zdGFydCArIDEpID09PSB0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldENhcmV0UG9zaXRpb24odGhpcy5zZWxlY3Rpb24uc3RhcnQgKyAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIEF1dG9OdW1lcmljSGVscGVyLmlzSW5BcnJheSh0aGlzLmV2ZW50S2V5LCBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5fZGlyZWN0aW9uS2V5cyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJvY2VzcyBkZWxldGlvbiBvZiBjaGFyYWN0ZXJzIHdoZW4gdGhlIG1pbnVzIHNpZ24gaXMgdG8gdGhlIHJpZ2h0IG9mIHRoZSBudW1lcmljIGNoYXJhY3RlcnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGVmdCBUaGUgcGFydCBvbiB0aGUgbGVmdCBvZiB0aGUgY2FyZXQgb3Igc2VsZWN0aW9uXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHJpZ2h0IFRoZSBwYXJ0IG9uIHRoZSByaWdodCBvZiB0aGUgY2FyZXQgb3Igc2VsZWN0aW9uXG4gICAgICogQHJldHVybnMge1tzdHJpbmcsIHN0cmluZ119XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfcHJvY2Vzc0NoYXJhY3RlckRlbGV0aW9uSWZUcmFpbGluZ05lZ2F0aXZlU2lnbihbbGVmdCwgcmlnaHRdKSB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCk7XG4gICAgICAgIGNvbnN0IGlzVmFsTmVnYXRpdmUgPSBBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlKHZhbHVlLCB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3Rlcik7XG5cbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQucHJlZml4ICYmIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQuc3VmZml4KSB7XG4gICAgICAgICAgICBpZiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuQmFja3NwYWNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jYXJldEZpeCA9ICh0aGlzLnNlbGVjdGlvbi5zdGFydCA+PSB2YWx1ZS5pbmRleE9mKHRoaXMuc2V0dGluZ3Muc3VmZml4VGV4dCkgJiYgdGhpcy5zZXR0aW5ncy5zdWZmaXhUZXh0ICE9PSAnJyk7XG4gICAgICAgICAgICAgICAgaWYgKHZhbHVlLmNoYXJBdCh0aGlzLnNlbGVjdGlvbi5zdGFydCAtIDEpID09PSAnLScpIHtcbiAgICAgICAgICAgICAgICAgICAgbGVmdCA9IGxlZnQuc3Vic3RyaW5nKDEpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZWxlY3Rpb24uc3RhcnQgPD0gdmFsdWUubGVuZ3RoIC0gdGhpcy5zZXR0aW5ncy5zdWZmaXhUZXh0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBsZWZ0ID0gbGVmdC5zdWJzdHJpbmcoMCwgbGVmdC5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuY2FyZXRGaXggPSAodGhpcy5zZWxlY3Rpb24uc3RhcnQgPj0gdmFsdWUuaW5kZXhPZih0aGlzLnNldHRpbmdzLnN1ZmZpeFRleHQpICYmIHRoaXMuc2V0dGluZ3Muc3VmZml4VGV4dCAhPT0gJycpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNlbGVjdGlvbi5zdGFydCA+PSB2YWx1ZS5pbmRleE9mKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wpICsgdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmlnaHQgPSByaWdodC5zdWJzdHJpbmcoMSwgcmlnaHQubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmUobGVmdCwgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpICYmIHZhbHVlLmNoYXJBdCh0aGlzLnNlbGVjdGlvbi5zdGFydCkgPT09ICctJykge1xuICAgICAgICAgICAgICAgICAgICBsZWZ0ID0gbGVmdC5zdWJzdHJpbmcoMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQuc3VmZml4KSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQpIHtcbiAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdDpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jYXJldEZpeCA9ICh0aGlzLnNlbGVjdGlvbi5zdGFydCA+PSB2YWx1ZS5pbmRleE9mKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSArIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5CYWNrc3BhY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNlbGVjdGlvbi5zdGFydCA9PT0gKHZhbHVlLmluZGV4T2YodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpICsgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIubGVuZ3RoKSAmJiBpc1ZhbE5lZ2F0aXZlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVmdCA9IGxlZnQuc3Vic3RyaW5nKDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChsZWZ0ICE9PSAnLScgJiYgKCh0aGlzLnNlbGVjdGlvbi5zdGFydCA8PSB2YWx1ZS5pbmRleE9mKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSkgfHwgIWlzVmFsTmVnYXRpdmUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVmdCA9IGxlZnQuc3Vic3RyaW5nKDAsIGxlZnQubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGVmdFswXSA9PT0gJy0nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmlnaHQgPSByaWdodC5zdWJzdHJpbmcoMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zZWxlY3Rpb24uc3RhcnQgPT09IHZhbHVlLmluZGV4T2YodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpICYmIGlzVmFsTmVnYXRpdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWZ0ID0gbGVmdC5zdWJzdHJpbmcoMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnJpZ2h0OlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNhcmV0Rml4ID0gKHRoaXMuc2VsZWN0aW9uLnN0YXJ0ID49IHZhbHVlLmluZGV4T2YodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpICsgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkJhY2tzcGFjZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc2VsZWN0aW9uLnN0YXJ0ID09PSAodmFsdWUuaW5kZXhPZih0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikgKyB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3Rlci5sZW5ndGgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVmdCA9IGxlZnQuc3Vic3RyaW5nKDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChsZWZ0ICE9PSAnLScgJiYgdGhpcy5zZWxlY3Rpb24uc3RhcnQgPD0gKHZhbHVlLmluZGV4T2YodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpIC0gdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbC5sZW5ndGgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVmdCA9IGxlZnQuc3Vic3RyaW5nKDAsIGxlZnQubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGxlZnQgIT09ICcnICYmICFpc1ZhbE5lZ2F0aXZlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVmdCA9IGxlZnQuc3Vic3RyaW5nKDAsIGxlZnQubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhcmV0Rml4ID0gKHRoaXMuc2VsZWN0aW9uLnN0YXJ0ID49IHZhbHVlLmluZGV4T2YodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbCkgJiYgdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbCAhPT0gJycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc2VsZWN0aW9uLnN0YXJ0ID09PSB2YWx1ZS5pbmRleE9mKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnN1YnN0cmluZygxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgcmlnaHQgPSByaWdodC5zdWJzdHJpbmcoMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gW2xlZnQsIHJpZ2h0XTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcm9jZXNzIHRoZSBkZWxldGlvbiBvZiBjaGFyYWN0ZXJzLlxuICAgICAqL1xuICAgIF9wcm9jZXNzQ2hhcmFjdGVyRGVsZXRpb24oKSB7XG4gICAgICAgIGxldCBsZWZ0O1xuICAgICAgICBsZXQgcmlnaHQ7XG5cbiAgICAgICAgaWYgKCF0aGlzLnNlbGVjdGlvbi5sZW5ndGgpIHtcbiAgICAgICAgICAgIFtsZWZ0LCByaWdodF0gPSB0aGlzLl9nZXRVbmZvcm1hdHRlZExlZnRBbmRSaWdodFBhcnRBcm91bmRUaGVTZWxlY3Rpb24oKTtcbiAgICAgICAgICAgIGlmIChsZWZ0ID09PSAnJyAmJiByaWdodCA9PT0gJycpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRocm93SW5wdXQgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuaXNUcmFpbGluZ05lZ2F0aXZlICYmIEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmUoQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCksIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgICAgIFtsZWZ0LCByaWdodF0gPSB0aGlzLl9wcm9jZXNzQ2hhcmFjdGVyRGVsZXRpb25JZlRyYWlsaW5nTmVnYXRpdmVTaWduKFtsZWZ0LCByaWdodF0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuQmFja3NwYWNlKSB7XG4gICAgICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnN1YnN0cmluZygwLCBsZWZ0Lmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJpZ2h0ID0gcmlnaHQuc3Vic3RyaW5nKDEsIHJpZ2h0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fZXhwYW5kU2VsZWN0aW9uT25TaWduKCk7XG4gICAgICAgICAgICBbbGVmdCwgcmlnaHRdID0gdGhpcy5fZ2V0VW5mb3JtYXR0ZWRMZWZ0QW5kUmlnaHRQYXJ0QXJvdW5kVGhlU2VsZWN0aW9uKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9zZXRWYWx1ZVBhcnRzKGxlZnQsIHJpZ2h0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIGEgZGVjaW1hbCBjaGFyYWN0ZXIgaXMgYWxsb3dlZCB0byBiZSB0eXBlZC5cbiAgICAgKiBJZiB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHNob3duIG9uIGZvY3VzIGlzIHplcm8sIHRoZW4gdGhlIGRlY2ltYWwgY2hhcmFjdGVyIGlzIG5vdCBhbGxvd2VkLlxuICAgICAqXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfaXNEZWNpbWFsQ2hhcmFjdGVySW5zZXJ0aW9uQWxsb3dlZCgpIHtcbiAgICAgICAgcmV0dXJuIFN0cmluZyh0aGlzLnNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMpICE9PSBTdHJpbmcoQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzLm5vbmUpICYmXG4gICAgICAgICAgICBTdHJpbmcodGhpcy5zZXR0aW5ncy5kZWNpbWFsUGxhY2VzKSAhPT0gU3RyaW5nKEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbFBsYWNlcy5ub25lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBrZXkgaXMgYWxsb3dlZC5cbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGRlY2lkZXMgaWYgdGhlIGtleSBwcmVzc2VkIHNob3VsZCBiZSBkcm9wcGVkIG9yIGFjY2VwdGVkLCBhbmQgbW9kaWZ5IHRoZSB2YWx1ZSAnb24tdGhlLWZseScgYWNjb3JkaW5nbHkuXG4gICAgICogLy9UT0RPIFRoaXMgc2hvdWxkIHVzZSBhbm90aGVyIGZ1bmN0aW9uIGluIG9yZGVyIHRvIHNlcGFyYXRlIHRoZSB0ZXN0IGFuZCB0aGUgbW9kaWZpY2F0aW9uXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBfcHJvY2Vzc0NoYXJhY3Rlckluc2VydGlvbigpIHtcbiAgICAgICAgbGV0IFtsZWZ0LCByaWdodF0gPSB0aGlzLl9nZXRVbmZvcm1hdHRlZExlZnRBbmRSaWdodFBhcnRBcm91bmRUaGVTZWxlY3Rpb24oKTtcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRLZXkgIT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkFuZHJvaWREZWZhdWx0KSB7XG4gICAgICAgICAgICB0aGlzLnRocm93SW5wdXQgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU3RhcnQgcnVsZXMgd2hlbiB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIga2V5IGlzIHByZXNzZWQgYWx3YXlzIHVzZSBudW1lcmljIHBhZCBkb3QgdG8gaW5zZXJ0IGRlY2ltYWwgc2VwYXJhdG9yXG4gICAgICAgIC8vIERvIG5vdCBhbGxvdyBkZWNpbWFsIGNoYXJhY3RlciBpZiBubyBkZWNpbWFsIHBhcnQgYWxsb3dlZFxuICAgICAgICBpZiAodGhpcy5ldmVudEtleSA9PT0gdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyIHx8XG4gICAgICAgICAgICAodGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUgJiYgdGhpcy5ldmVudEtleSA9PT0gdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUpKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuX2lzRGVjaW1hbENoYXJhY3Rlckluc2VydGlvbkFsbG93ZWQoKSB8fCAhdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5hbHdheXNBbGxvd0RlY2ltYWxDaGFyYWN0ZXIpIHtcbiAgICAgICAgICAgICAgICAvLyBSZW1vdmUgYW55IHByZXZpb3VzIGRlY2ltYWwgY2hhcmFjdGVyXG4gICAgICAgICAgICAgICAgbGVmdCA9IGxlZnQucmVwbGFjZSh0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIsICcnKTtcbiAgICAgICAgICAgICAgICByaWdodCA9IHJpZ2h0LnJlcGxhY2UodGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyLCAnJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIERvIG5vdCBhbGxvdyBhIGRlY2ltYWwgY2hhcmFjdGVyIGlmIGFub3RoZXIgZGVjaW1hbCBjaGFyYWN0ZXIgaXMgYWxyZWFkeSBwcmVzZW50XG4gICAgICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmNvbnRhaW5zKGxlZnQsIHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gUHJldmVudCBhZGRpbmcgYSBkZWNpbWFsIGNoYXJhY3RlciBhdCB0aGUgZmFyIHJpZ2h0IG9mIHRoZSBudW1iZXJcbiAgICAgICAgICAgICAgICBpZiAocmlnaHQuaW5kZXhPZih0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpID4gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBSZW1vdmUgdGhlIGRlY2ltYWwgY2hhcmFjdGVyIGlzIGZvdW5kIG9uIHRoZSBmYXIgbGVmdCBvZiB0aGUgcmlnaHQgcGFydFxuICAgICAgICAgICAgICAgIGlmIChyaWdodC5pbmRleE9mKHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlcikgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmlnaHQgPSByaWdodC5zdWJzdHIoMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBJZiB0aGUgdXNlciBpcyB0cnlpbmcgdG8gYWRkIGEgZGVjaW1hbCBjaGFyYWN0ZXIgb24gdGhlIGZhciBsZWZ0IG9mIHRoZSBudW1iZXIsIHdlIGFsbG93IGl0XG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgJiYgQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMocmlnaHQsIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgICAgIC8vIFdlIG5lZWQgaG93ZXZlciB0byBtb3ZlIHRoZSBuZWdhdGl2ZSBzaWduIGZyb20gdGhlIHJpZ2h0IHRvIHRoZSBsZWZ0IHBhcnRcbiAgICAgICAgICAgICAgICBsZWZ0ID0gYCR7dGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXJ9JHtsZWZ0fWA7XG4gICAgICAgICAgICAgICAgcmlnaHQgPSByaWdodC5yZXBsYWNlKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyLCAnJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlUGFydHMobGVmdCArIHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlciwgcmlnaHQpO1xuXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFByZXZlbnQgZW50ZXJpbmcgdGhlIG1pbnVzIHNpZ24gaWYgaXQncyBub3QgYWxsb3dlZCAoTm90ZTogYHRoaXMuc2V0dGluZ3MuaXNOZWdhdGl2ZVNpZ25BbGxvd2VkYCBpcyBvbmx5IHNldCB0byBgdHJ1ZWAgaWYgdGhlIG1pbmltdW1WYWx1ZSBpcyBsb3dlciB0aGFuIHplcm8sIGFsbG93aW5nIG5lZ2F0aXZlIG51bWJlcnMgdG8gYmUgZW50ZXJlZClcbiAgICAgICAgaWYgKCh0aGlzLmV2ZW50S2V5ID09PSAnLScgfHwgdGhpcy5ldmVudEtleSA9PT0gJysnKSAmJiB0aGlzLnNldHRpbmdzLmlzTmVnYXRpdmVTaWduQWxsb3dlZCkge1xuICAgICAgICAgICAgLy8gSGVyZSwgdGhlIGxlZnQgYW5kIHJpZ2h0IHBhcnRzIGhhdmUgYmVlbiBub3JtYWxpemVkIGFscmVhZHksIGhlbmNlIHRoZSBtaW51cyBzaWduIHVzYWdlXG4gICAgICAgICAgICBpZiAobGVmdCA9PT0gJycgJiYgQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMocmlnaHQsICctJykpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGUgdmFsdWUgaXMgb3JpZ2luYWxseSBuZWdhdGl2ZSAod2l0aCBhIHRyYWlsaW5nIG5lZ2F0aXZlIHNpZ24pXG4gICAgICAgICAgICAgICAgcmlnaHQgPSByaWdodC5yZXBsYWNlKCctJywgJycpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlU3RyaWN0KGxlZnQsICctJykpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGUgdmFsdWUgaXMgb3JpZ2luYWxseSBuZWdhdGl2ZSAod2l0aCBhIGxlYWRpbmcgbmVnYXRpdmUgc2lnbilcbiAgICAgICAgICAgICAgICAvLyBSZW1vdmUgdGhlIG5lZ2F0aXZlIHNpZ24sIGVmZmVjdGl2ZWx5IGNvbnZlcnRpbmcgdGhlIHZhbHVlIHRvIGEgcG9zaXRpdmUgb25lXG4gICAgICAgICAgICAgICAgbGVmdCA9IGxlZnQucmVwbGFjZSgnLScsICcnKTsgLy9UT0RPIHJlcGxhY2Ugd2l0aCAnKycgaWYgYHNob3dQb3NpdGl2ZVNpZ25gIHRvbz9cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlIHZhbHVlIGlzIG9yaWdpbmFsbHkgcG9zaXRpdmUsIHNvIHdlIHRvZ2dsZSB0aGUgc3RhdGUgdG8gYSBuZWdhdGl2ZSBvbmUgKHVuZm9ybWF0dGVkLCB3aGljaCBtZWFucyBldmVuIHdpdGggYSB0cmFpbGluZyBuZWdhdGl2ZSBzaWduLCB3ZSBhZGQgdGhlIG1pbnVzIHNpZ24gb24gdGhlIGZhciBsZWZ0KVxuICAgICAgICAgICAgICAgIGxlZnQgPSBgJHt0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3Rlcn0ke2xlZnR9YDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWVQYXJ0cyhsZWZ0LCByaWdodCk7XG5cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZXZlbnROdW1iZXIgPSBOdW1iZXIodGhpcy5ldmVudEtleSk7XG4gICAgICAgIGlmIChldmVudE51bWJlciA+PSAwICYmIGV2ZW50TnVtYmVyIDw9IDkpIHtcbiAgICAgICAgICAgIC8vIElmIHRoZSB1c2VyIHRyaWVzIHRvIGluc2VydCBhIGRpZ2l0XG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5pc05lZ2F0aXZlU2lnbkFsbG93ZWQgJiYgbGVmdCA9PT0gJycgJiYgQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMocmlnaHQsICctJykpIHtcbiAgICAgICAgICAgICAgICAvLyAuLi5hbmQgdGhhdCBkaWdpdCBpcyBiZWZvcmUgdGhlIG1pbnVzIHNpZ25cbiAgICAgICAgICAgICAgICBsZWZ0ID0gJy0nO1xuICAgICAgICAgICAgICAgIHJpZ2h0ID0gcmlnaHQuc3Vic3RyaW5nKDEsIHJpZ2h0Lmxlbmd0aCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLm1heGltdW1WYWx1ZSA8PSAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5taW5pbXVtVmFsdWUgPCB0aGlzLnNldHRpbmdzLm1heGltdW1WYWx1ZSAmJlxuICAgICAgICAgICAgICAgICFBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyhBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50KSwgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpICYmXG4gICAgICAgICAgICAgICAgdGhpcy5ldmVudEtleSAhPT0gJzAnKSB7XG4gICAgICAgICAgICAgICAgbGVmdCA9IGAtJHtsZWZ0fWA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlUGFydHMoYCR7bGVmdH0ke3RoaXMuZXZlbnRLZXl9YCwgcmlnaHQpO1xuXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFByZXZlbnQgYW55IG90aGVyIGNoYXJhY3RlcnNcbiAgICAgICAgdGhpcy50aHJvd0lucHV0ID0gZmFsc2U7XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZvcm1hdHRpbmcgb2YganVzdCBwcm9jZXNzZWQgdmFsdWUgd2hpbGUga2VlcGluZyB0aGUgY3Vyc29yIHBvc2l0aW9uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZm9ybWF0VmFsdWUoZSkge1xuICAgICAgICAvL1RPRE8gQnJlYWsgYXBhcnQgYW5kIHNpbXBsaWZ5IHRoaXMgcmVhbGx5IGxvbmcgZnVuY3Rpb25cbiAgICAgICAgY29uc3QgZWxlbWVudFZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCk7XG4gICAgICAgIGxldCBbbGVmdF0gPSB0aGlzLl9nZXRVbmZvcm1hdHRlZExlZnRBbmRSaWdodFBhcnRBcm91bmRUaGVTZWxlY3Rpb24oKTtcblxuICAgICAgICAvLyBObyBncm91cGluZyBzZXBhcmF0b3IgYW5kIG5vIGN1cnJlbmN5IHNpZ25cbiAgICAgICAgaWYgKCh0aGlzLnNldHRpbmdzLmRpZ2l0R3JvdXBTZXBhcmF0b3IgID09PSAnJyB8fCAodGhpcy5zZXR0aW5ncy5kaWdpdEdyb3VwU2VwYXJhdG9yICE9PSAnJyAgJiYgIUF1dG9OdW1lcmljSGVscGVyLmNvbnRhaW5zKGVsZW1lbnRWYWx1ZSwgdGhpcy5zZXR0aW5ncy5kaWdpdEdyb3VwU2VwYXJhdG9yKSkpICYmXG4gICAgICAgICAgICAodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbCA9PT0gJycgfHwgKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wgIT09ICcnICYmICFBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyhlbGVtZW50VmFsdWUsIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wpKSkpIHtcbiAgICAgICAgICAgIGxldCBbc3ViUGFydHNdID0gZWxlbWVudFZhbHVlLnNwbGl0KHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlcik7XG4gICAgICAgICAgICBsZXQgbmVnYXRpdmVTaWduID0gJyc7XG4gICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZShzdWJQYXJ0cywgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpKSB7XG4gICAgICAgICAgICAgICAgbmVnYXRpdmVTaWduID0gdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXI7XG4gICAgICAgICAgICAgICAgc3ViUGFydHMgPSBzdWJQYXJ0cy5yZXBsYWNlKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyLCAnJyk7XG4gICAgICAgICAgICAgICAgbGVmdCA9IGxlZnQucmVwbGFjZSgnLScsICcnKTsgLy8gSGVyZSB3ZSBtb2RpZnkgdGhlIHVuZm9ybWF0dGVkIHZhbHVlICh3aXRoIHRoZSAnbm9ybWFsJyBtaW51cyBzaWduKVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTdHJpcCBsZWFkaW5nIHplcm8gb24gcG9zaXRpdmUgdmFsdWUgaWYgbmVlZGVkXG4gICAgICAgICAgICBpZiAobmVnYXRpdmVTaWduID09PSAnJyAmJiBzdWJQYXJ0cy5sZW5ndGggPiB0aGlzLnNldHRpbmdzLm1JbnRQb3MgJiYgbGVmdC5jaGFyQXQoMCkgPT09ICcwJykge1xuICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnNsaWNlKDEpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTdHJpcCBsZWFkaW5nIHplcm8gb24gbmVnYXRpdmUgdmFsdWUgaWYgbmVlZGVkXG4gICAgICAgICAgICBpZiAobmVnYXRpdmVTaWduID09PSB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciAmJiBzdWJQYXJ0cy5sZW5ndGggPiB0aGlzLnNldHRpbmdzLm1JbnROZWcgJiYgbGVmdC5jaGFyQXQoMCkgPT09ICcwJykge1xuICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnNsaWNlKDEpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIXRoaXMuaXNUcmFpbGluZ05lZ2F0aXZlKSB7IC8vIE9ubHkgYWRkIHRoZSBtaW51cyBzaWduIGlmIGl0J3MgbmVlZGVkIG9uIHRoYXQgc2lkZSBvZiB0aGUgbnVtYmVyc1xuICAgICAgICAgICAgICAgIGxlZnQgPSBgJHtuZWdhdGl2ZVNpZ259JHtsZWZ0fWA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2YWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX2FkZEdyb3VwU2VwYXJhdG9ycyhlbGVtZW50VmFsdWUsIHRoaXMuc2V0dGluZ3MsIHRoaXMuaXNGb2N1c2VkLCB0aGlzLnJhd1ZhbHVlKTtcbiAgICAgICAgbGV0IHBvc2l0aW9uID0gdmFsdWUubGVuZ3RoO1xuICAgICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgICAgIC8vIFByZXBhcmUgcmVnZXhwIHdoaWNoIHNlYXJjaGVzIGZvciBjdXJzb3IgcG9zaXRpb24gZnJvbSB1bmZvcm1hdHRlZCBsZWZ0IHBhcnRcbiAgICAgICAgICAgIGNvbnN0IGxlZnRBciA9IGxlZnQuc3BsaXQoJycpO1xuXG4gICAgICAgICAgICAvLyBGaXhlcyBjYXJldCBwb3NpdGlvbiB3aXRoIHRyYWlsaW5nIG1pbnVzIHNpZ25cbiAgICAgICAgICAgIGlmICgodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5zdWZmaXggfHxcbiAgICAgICAgICAgICAgICAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXggJiYgdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5zdWZmaXgpKSAmJlxuICAgICAgICAgICAgICAgIGxlZnRBclswXSA9PT0gdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgJiYgIXRoaXMuc2V0dGluZ3MuaXNOZWdhdGl2ZVNpZ25BbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgbGVmdEFyLnNoaWZ0KCk7IC8vIFJlbW92ZSB0aGUgbmVnYXRpdmUgc2lnbiBjaGFyYWN0ZXJcblxuICAgICAgICAgICAgICAgIGlmICgodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuQmFja3NwYWNlIHx8IHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkRlbGV0ZSkgJiZcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jYXJldEZpeCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQuc3VmZml4ICYmIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdCkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnByZWZpeCAmJiB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnN1ZmZpeCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxlZnRBci5wdXNoKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FyZXRGaXggPSBlLnR5cGUgPT09ICdrZXlkb3duJztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2lnblBhcnRzID0gdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbC5zcGxpdCgnJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlc2NhcGVDaHIgPSBbJ1xcXFwnLCAnXicsICckJywgJy4nLCAnfCcsICc/JywgJyonLCAnKycsICcoJywgJyknLCAnWyddO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXNjYXBlZFBhcnRzID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICBzaWduUGFydHMuZm9yRWFjaCgoaSwgbWluaVBhcnRzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluaVBhcnRzID0gc2lnblBhcnRzW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0luQXJyYXkobWluaVBhcnRzLCBlc2NhcGVDaHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVzY2FwZWRQYXJ0cy5wdXNoKCdcXFxcJyArIG1pbmlQYXJ0cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXNjYXBlZFBhcnRzLnB1c2gobWluaVBhcnRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkJhY2tzcGFjZSAmJiB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciA9PT0gJy0nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXNjYXBlZFBhcnRzLnB1c2goJy0nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUHVzaGluZyB0aGUgZXNjYXBlZCBzaWduXG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0QXIucHVzaChlc2NhcGVkUGFydHMuam9pbignJykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jYXJldEZpeCA9IGUudHlwZSA9PT0gJ2tleWRvd24nO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlZnRBci5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmICghbGVmdEFyW2ldLm1hdGNoKCdcXFxcZCcpKSB7XG4gICAgICAgICAgICAgICAgICAgIGxlZnRBcltpXSA9ICdcXFxcJyArIGxlZnRBcltpXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGxlZnRSZWcgPSBuZXcgUmVnRXhwKCdeLio/JyArIGxlZnRBci5qb2luKCcuKj8nKSk7XG5cbiAgICAgICAgICAgIC8vIFNlYXJjaCBjdXJzb3IgcG9zaXRpb24gaW4gZm9ybWF0dGVkIHZhbHVlXG4gICAgICAgICAgICBjb25zdCBuZXdMZWZ0ID0gdmFsdWUubWF0Y2gobGVmdFJlZyk7XG4gICAgICAgICAgICBpZiAobmV3TGVmdCkge1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gbmV3TGVmdFswXS5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgcG9zaXRpdmUgc2lnbiBpcyBzaG93biwgY2FsY3VsYXRlIHRoZSBjYXJldCBwb3NpdGlvbiBhY2NvcmRpbmdseVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLnNob3dQb3NpdGl2ZVNpZ24pIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBvc2l0aW9uID09PSAwICYmIG5ld0xlZnQuaW5wdXQuY2hhckF0KDApID09PSB0aGlzLnNldHRpbmdzLnBvc2l0aXZlU2lnbkNoYXJhY3Rlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSAobmV3TGVmdC5pbnB1dC5pbmRleE9mKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wpID09PSAxKSA/IHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wubGVuZ3RoICsgMSA6IDE7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAocG9zaXRpb24gPT09IDAgJiYgbmV3TGVmdC5pbnB1dC5jaGFyQXQodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbC5sZW5ndGgpID09PSB0aGlzLnNldHRpbmdzLnBvc2l0aXZlU2lnbkNoYXJhY3Rlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sLmxlbmd0aCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBJZiB3ZSBhcmUganVzdCBiZWZvcmUgdGhlIHNpZ24gd2hpY2ggaXMgaW4gcHJlZml4IHBvc2l0aW9uXG4gICAgICAgICAgICAgICAgaWYgKCgocG9zaXRpb24gPT09IDAgJiYgdmFsdWUuY2hhckF0KDApICE9PSB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikgfHwgKHBvc2l0aW9uID09PSAxICYmIHZhbHVlLmNoYXJBdCgwKSA9PT0gdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpKSAmJiB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sICYmIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQucHJlZml4KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFBsYWNlIGNhcmV0IGFmdGVyIHByZWZpeCBzaWduXG4gICAgICAgICAgICAgICAgICAgIC8vVE9ETyBTaG91bGQgdGhlIHRlc3QgYmUgJ2lzTmVnYXRpdmUnIGluc3RlYWQgb2YgJ2lzTmVnYXRpdmVTdHJpY3QnIGluIG9yZGVyIHRvIHNlYXJjaCBmb3IgJy0nIGV2ZXJ5d2hlcmUgaW4gdGhlIHN0cmluZz9cbiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sLmxlbmd0aCArIChBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlU3RyaWN0KHZhbHVlLCB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikgPyAxIDogMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbCAmJiB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB3ZSBjb3VsZCBub3QgZmluZCBhIHBsYWNlIGZvciBjdXJzb3IgYW5kIGhhdmUgYSBzaWduIGFzIGEgc3VmZml4XG4gICAgICAgICAgICAgICAgICAgIC8vIFBsYWNlIGNhcmV0IGJlZm9yZSBzdWZmaXggY3VycmVuY3kgc2lnblxuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbiAtPSB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5zdWZmaXhUZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHdlIGNvdWxkIG5vdCBmaW5kIGEgcGxhY2UgZm9yIGN1cnNvciBhbmQgaGF2ZSBhIHN1ZmZpeFxuICAgICAgICAgICAgICAgICAgICAvLyBQbGFjZSBjYXJldCBiZWZvcmUgc3VmZml4XG4gICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uIC09IHRoaXMuc2V0dGluZ3Muc3VmZml4VGV4dC5sZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gT25seSB1cGRhdGUgdGhlIHZhbHVlIGlmIGl0IGhhcyBjaGFuZ2VkLiBUaGlzIHByZXZlbnRzIG1vZGlmeWluZyB0aGUgc2VsZWN0aW9uLCBpZiBhbnkuXG4gICAgICAgIGlmICh2YWx1ZSAhPT0gZWxlbWVudFZhbHVlKSB7XG4gICAgICAgICAgICB0aGlzLl9zZXRFbGVtZW50VmFsdWUodmFsdWUsIGZhbHNlKTtcbiAgICAgICAgICAgIHRoaXMuX3NldENhcmV0UG9zaXRpb24ocG9zaXRpb24pO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5mb3JtYXR0ZWQgPSB0cnVlOyAvL1RPRE8gUmVuYW1lIGB0aGlzLmZvcm1hdHRlZGAgdG8gYHRoaXMuX2Zvcm1hdEV4ZWN1dGVkYCwgc2luY2UgaXQncyBwb3NzaWJsZSB0aGlzIGZ1bmN0aW9uIGRvZXMgbm90IG5lZWQgdG8gZm9ybWF0IGFueXRoaW5nIChpbiB0aGUgY2FzZSB3aGVyZSB0aGUga2V5Y29kZSBpcyBkcm9wcGVkIGZvciBpbnN0YW5jZSlcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXJpYWxpemUgdGhlIGZvcm0gY2hpbGQgPGlucHV0PiBlbGVtZW50IHZhbHVlcyB0byBhIHN0cmluZywgb3IgYW4gQXJyYXkuXG4gICAgICogVGhlIG91dHB1dCBmb3JtYXQgaXMgZGVmaW5lZCB3aXRoIHRoZSBgZm9ybWF0VHlwZWAgYXJndW1lbnQuXG4gICAgICogVGhpcyBpcyBsb29zZWx5IGJhc2VkIHVwb24gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvNDA3MDU5OTMvMjgzNDg5OC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEZvcm1FbGVtZW50fSBmb3JtXG4gICAgICogQHBhcmFtIHtib29sZWFufSBpbnRvQW5BcnJheSBJZiBgdHJ1ZWAsIGluc3RlYWQgb2YgZ2VuZXJhdGluZyBhIHN0cmluZywgaXQgZ2VuZXJhdGVzIGFuIEFycmF5LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBmb3JtYXRUeXBlIElmIGAndW5mb3JtYXR0ZWQnYCwgdGhlbiB0aGUgQXV0b051bWVyaWMgZWxlbWVudHMgdmFsdWVzIGFyZSB1bmZvcm1hdHRlZCwgaWYgYCdsb2NhbGl6ZWQnYCwgdGhlbiB0aGUgQXV0b051bWVyaWMgZWxlbWVudHMgdmFsdWVzIGFyZSBsb2NhbGl6ZWQsIGFuZCBpZiBgJ2Zvcm1hdHRlZCdgLCB0aGVuIHRoZSBBdXRvTnVtZXJpYyBlbGVtZW50cyB2YWx1ZXMgYXJlIGtlcHQgZm9ybWF0dGVkLiBJbiBlaXRoZXIgd2F5LCB0aGlzIGZ1bmN0aW9uIGRvZXMgbm90IG1vZGlmeSB0aGUgdmFsdWUgb2YgZWFjaCBET00gZWxlbWVudCwgYnV0IG9ubHkgYWZmZWN0IHRoZSB2YWx1ZSB0aGF0IGlzIHJldHVybmVkIGJ5IHRoYXQgc2VyaWFsaXplIGZ1bmN0aW9uLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzZXJpYWxpemVkU3BhY2VDaGFyYWN0ZXIgQ2FuIGVpdGhlciBiZSB0aGUgJysnIGNoYXJhY3Rlciwgb3IgdGhlICclMjAnIHN0cmluZy5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xudWxsfSBmb3JjZWRPdXRwdXRGb3JtYXQgSWYgc2V0LCB0aGVuIHRoaXMgaXMgdGhlIGZvcm1hdCB0aGF0IGlzIHVzZWQgZm9yIHRoZSBsb2NhbGl6YXRpb24sIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgYG91dHB1dEZvcm1hdGAgb3B0aW9uLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8QXJyYXl9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX3NlcmlhbGl6ZShmb3JtLCBpbnRvQW5BcnJheSA9IGZhbHNlLCBmb3JtYXRUeXBlID0gJ3VuZm9ybWF0dGVkJywgc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyID0gJysnLCBmb3JjZWRPdXRwdXRGb3JtYXQgPSBudWxsKSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuXG4gICAgICAgIGlmICh0eXBlb2YgZm9ybSA9PT0gJ29iamVjdCcgJiYgZm9ybS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpID09PSAnZm9ybScpIHtcbiAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGZvcm0uZWxlbWVudHMpLmZvckVhY2goZWxlbWVudCA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQubmFtZSAmJlxuICAgICAgICAgICAgICAgICAgICAhZWxlbWVudC5kaXNhYmxlZCAmJlxuICAgICAgICAgICAgICAgICAgICBbJ2ZpbGUnLCAncmVzZXQnLCAnc3VibWl0JywgJ2J1dHRvbiddLmluZGV4T2YoZWxlbWVudC50eXBlKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQudHlwZSA9PT0gJ3NlbGVjdC1tdWx0aXBsZScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGVsZW1lbnQub3B0aW9ucykuZm9yRWFjaChvcHRpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb24uc2VsZWN0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9UT0RPIFNob3VsZCB3ZSB1bmZvcm1hdC9mb3JtYXQvbG9jYWxpemUgdGhlIHNlbGVjdGlvbiBvcHRpb24gKHdoaWNoIGJlIGRlZmF1bHQgc2hvdWxkIGJlIHJlYWQtb25seSk/XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbnRvQW5BcnJheSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goeyBuYW1lOiBlbGVtZW50Lm5hbWUsIHZhbHVlOiBvcHRpb24udmFsdWUgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7IC8vIGludG8gYSBzdHJpbmdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKGAke2VuY29kZVVSSUNvbXBvbmVudChlbGVtZW50Lm5hbWUpfT0ke2VuY29kZVVSSUNvbXBvbmVudChvcHRpb24udmFsdWUpfWApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoWydjaGVja2JveCcsICdyYWRpbyddLmluZGV4T2YoZWxlbWVudC50eXBlKSA9PT0gLTEgfHwgZWxlbWVudC5jaGVja2VkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgdmFsdWVSZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5pc01hbmFnZWRCeUF1dG9OdW1lcmljKGVsZW1lbnQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGFuT2JqZWN0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoZm9ybWF0VHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICd1bmZvcm1hdHRlZCc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbk9iamVjdCA9IHRoaXMuZ2V0QXV0b051bWVyaWNFbGVtZW50KGVsZW1lbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoYW5PYmplY3QpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVSZXN1bHQgPSB0aGlzLnVuZm9ybWF0KGVsZW1lbnQsIGFuT2JqZWN0LmdldFNldHRpbmdzKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbG9jYWxpemVkJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuT2JqZWN0ID0gdGhpcy5nZXRBdXRvTnVtZXJpY0VsZW1lbnQoZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChhbk9iamVjdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIZXJlIEkgbmVlZCB0byBjbG9uZSB0aGUgc2V0dGluZyBvYmplY3QsIG90aGVyd2lzZSBJIHdvdWxkIG1vZGlmeSBpdCB3aGVuIGNoYW5naW5nIHRoZSBgb3V0cHV0Rm9ybWF0YCBvcHRpb24gdmFsdWVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50U2V0dGluZ3MgPSBBdXRvTnVtZXJpY0hlbHBlci5jbG9uZU9iamVjdChhbk9iamVjdC5nZXRTZXR0aW5ncygpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChmb3JjZWRPdXRwdXRGb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTZXR0aW5ncy5vdXRwdXRGb3JtYXQgPSBmb3JjZWRPdXRwdXRGb3JtYXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVSZXN1bHQgPSB0aGlzLmxvY2FsaXplKGVsZW1lbnQsIGN1cnJlbnRTZXR0aW5ncyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdmb3JtYXR0ZWQnOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVSZXN1bHQgPSBlbGVtZW50LnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVSZXN1bHQgPSBlbGVtZW50LnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWQodmFsdWVSZXN1bHQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcignVGhpcyBlcnJvciBzaG91bGQgbmV2ZXIgYmUgaGl0LiBJZiBpdCBoYXMsIHNvbWV0aGluZyByZWFsbHkgd3JvbmcgaGFwcGVuZWQhJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbnRvQW5BcnJheSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKHsgbmFtZTogZWxlbWVudC5uYW1lLCB2YWx1ZTogdmFsdWVSZXN1bHQgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgeyAvLyBpbnRvIGEgc3RyaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goYCR7ZW5jb2RlVVJJQ29tcG9uZW50KGVsZW1lbnQubmFtZSl9PSR7ZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlUmVzdWx0KX1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGZpbmFsUmVzdWx0O1xuXG4gICAgICAgIGlmIChpbnRvQW5BcnJheSkge1xuICAgICAgICAgICAgLy8gUmVzdWx0IGFzIGFuIEFycmF5XG4gICAgICAgICAgICAvLyBOb3RlOiBgc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyYCBkb2VzIG5vdCBhZmZlY3QgdGhlIGFycmF5IHJlc3VsdCBzaW5jZSB3ZSBkbyBub3QgY2hhbmdlIHRoZSBzcGFjZSBjaGFyYWN0ZXIgZm9yIHRoaXMgb25lXG4gICAgICAgICAgICBmaW5hbFJlc3VsdCA9IHJlc3VsdDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFJlc3VsdCBhcyBhIHN0cmluZ1xuICAgICAgICAgICAgZmluYWxSZXN1bHQgPSByZXN1bHQuam9pbignJicpO1xuXG4gICAgICAgICAgICBpZiAoJysnID09PSBzZXJpYWxpemVkU3BhY2VDaGFyYWN0ZXIpIHtcbiAgICAgICAgICAgICAgICBmaW5hbFJlc3VsdCA9IGZpbmFsUmVzdWx0LnJlcGxhY2UoLyUyMC9nLCAnKycpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZpbmFsUmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlcmlhbGl6ZSB0aGUgZm9ybSB2YWx1ZXMgdG8gYSBzdHJpbmcsIG91dHB1dHRpbmcgbnVtZXJpYyBzdHJpbmdzIGZvciBlYWNoIEF1dG9OdW1lcmljLW1hbmFnZWQgZWxlbWVudCB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxGb3JtRWxlbWVudH0gZm9ybVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzZXJpYWxpemVkU3BhY2VDaGFyYWN0ZXJcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIHN0YXRpYyBfc2VyaWFsaXplTnVtZXJpY1N0cmluZyhmb3JtLCBzZXJpYWxpemVkU3BhY2VDaGFyYWN0ZXIgPSAnKycpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NlcmlhbGl6ZShmb3JtLCBmYWxzZSwgJ3VuZm9ybWF0dGVkJywgc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXJpYWxpemUgdGhlIGZvcm0gdmFsdWVzIHRvIGEgc3RyaW5nLCBvdXRwdXR0aW5nIHRoZSBmb3JtYXR0ZWQgdmFsdWUgYXMgc3RyaW5ncyBmb3IgZWFjaCBBdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnRzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRm9ybUVsZW1lbnR9IGZvcm1cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgX3NlcmlhbGl6ZUZvcm1hdHRlZChmb3JtLCBzZXJpYWxpemVkU3BhY2VDaGFyYWN0ZXIgPSAnKycpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NlcmlhbGl6ZShmb3JtLCBmYWxzZSwgJ2Zvcm1hdHRlZCcsIHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3Rlcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VyaWFsaXplIHRoZSBmb3JtIHZhbHVlcyB0byBhIHN0cmluZywgb3V0cHV0dGluZyBsb2NhbGl6ZWQgc3RyaW5ncyBmb3IgZWFjaCBBdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnQgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRm9ybUVsZW1lbnR9IGZvcm1cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyXG4gICAgICogQHBhcmFtIHtzdHJpbmd8bnVsbH0gZm9yY2VkT3V0cHV0Rm9ybWF0IElmIHNldCwgdGhlbiB0aGlzIGlzIHRoZSBmb3JtYXQgdGhhdCBpcyB1c2VkIGZvciB0aGUgbG9jYWxpemF0aW9uLCBpbnN0ZWFkIG9mIHRoZSBkZWZhdWx0IGBvdXRwdXRGb3JtYXRgIG9wdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIHN0YXRpYyBfc2VyaWFsaXplTG9jYWxpemVkKGZvcm0sIHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3RlciA9ICcrJywgZm9yY2VkT3V0cHV0Rm9ybWF0ID0gbnVsbCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fc2VyaWFsaXplKGZvcm0sIGZhbHNlLCAnbG9jYWxpemVkJywgc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyLCBmb3JjZWRPdXRwdXRGb3JtYXQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGFuIEFycmF5IHdpdGggdGhlIGZvcm0gdmFsdWVzLCBvdXRwdXR0aW5nIG51bWVyaWMgc3RyaW5ncyBmb3IgZWFjaCBBdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnQgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRm9ybUVsZW1lbnR9IGZvcm1cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyXG4gICAgICogQHJldHVybnMge0FycmF5fVxuICAgICAqL1xuICAgIHN0YXRpYyBfc2VyaWFsaXplTnVtZXJpY1N0cmluZ0FycmF5KGZvcm0sIHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3RlciA9ICcrJykge1xuICAgICAgICByZXR1cm4gdGhpcy5fc2VyaWFsaXplKGZvcm0sIHRydWUsICd1bmZvcm1hdHRlZCcsIHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3Rlcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGUgYW4gQXJyYXkgd2l0aCB0aGUgZm9ybSB2YWx1ZXMsIG91dHB1dHRpbmcgdGhlIGZvcm1hdHRlZCB2YWx1ZSBhcyBzdHJpbmdzIGZvciBlYWNoIEF1dG9OdW1lcmljLW1hbmFnZWQgZWxlbWVudHMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxGb3JtRWxlbWVudH0gZm9ybVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzZXJpYWxpemVkU3BhY2VDaGFyYWN0ZXJcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9XG4gICAgICovXG4gICAgc3RhdGljIF9zZXJpYWxpemVGb3JtYXR0ZWRBcnJheShmb3JtLCBzZXJpYWxpemVkU3BhY2VDaGFyYWN0ZXIgPSAnKycpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NlcmlhbGl6ZShmb3JtLCB0cnVlLCAnZm9ybWF0dGVkJywgc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBhbiBBcnJheSB3aXRoIHRoZSBmb3JtIHZhbHVlcywgb3V0cHV0dGluZyBsb2NhbGl6ZWQgc3RyaW5ncyBmb3IgZWFjaCBBdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnQgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRm9ybUVsZW1lbnR9IGZvcm1cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyXG4gICAgICogQHBhcmFtIHtzdHJpbmd8bnVsbH0gZm9yY2VkT3V0cHV0Rm9ybWF0IElmIHNldCwgdGhlbiB0aGlzIGlzIHRoZSBmb3JtYXQgdGhhdCBpcyB1c2VkIGZvciB0aGUgbG9jYWxpemF0aW9uLCBpbnN0ZWFkIG9mIHRoZSBkZWZhdWx0IGBvdXRwdXRGb3JtYXRgIG9wdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9XG4gICAgICovXG4gICAgc3RhdGljIF9zZXJpYWxpemVMb2NhbGl6ZWRBcnJheShmb3JtLCBzZXJpYWxpemVkU3BhY2VDaGFyYWN0ZXIgPSAnKycsIGZvcmNlZE91dHB1dEZvcm1hdCA9IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NlcmlhbGl6ZShmb3JtLCB0cnVlLCAnbG9jYWxpemVkJywgc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyLCBmb3JjZWRPdXRwdXRGb3JtYXQpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBJbml0aWFsaXplIG11bHRpcGxlIERPTSBlbGVtZW50cyBpbiBvbmUgY2FsbCAoYW5kIHBvc3NpYmx5IHBhc3MgbXVsdGlwbGUgdmFsdWVzIHRoYXQgd2lsbCBiZSBtYXBwZWQgdG8gZWFjaCBET00gZWxlbWVudCkuXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIEluaXQgbXVsdGlwbGUgRE9NIGVsZW1lbnRzIGluIG9uZSBjYWxsIChhbmQgcG9zc2libHkgcGFzcyBtdWx0aXBsZSB2YWx1ZXMgdGhhdCB3aWxsIGJlIG1hcHBlZCB0byBlYWNoIERPTSBlbGVtZW50KVxuICogW2FuRWxlbWVudDEsIGFuRWxlbWVudDIsIGFuRWxlbWVudDNdID0gQXV0b051bWVyaWMubXVsdGlwbGUoW2RvbUVsZW1lbnQxLCBkb21FbGVtZW50MiwgZG9tRWxlbWVudDNdLCB7IG9wdGlvbnMgfSk7XG4gKiBbYW5FbGVtZW50MSwgYW5FbGVtZW50MiwgYW5FbGVtZW50M10gPSBBdXRvTnVtZXJpYy5tdWx0aXBsZShbZG9tRWxlbWVudDEsIGRvbUVsZW1lbnQyLCBkb21FbGVtZW50M10sIFt7IG9wdGlvbnMgfSwgJ2V1cm9Qb3MnXSk7XG4gKiBbYW5FbGVtZW50MSwgYW5FbGVtZW50MiwgYW5FbGVtZW50M10gPSBBdXRvTnVtZXJpYy5tdWx0aXBsZShbZG9tRWxlbWVudDEsIGRvbUVsZW1lbnQyLCBkb21FbGVtZW50M10sIDEyMzQ1Ljc4OSwgeyBvcHRpb25zIH0pO1xuICogW2FuRWxlbWVudDEsIGFuRWxlbWVudDIsIGFuRWxlbWVudDNdID0gQXV0b051bWVyaWMubXVsdGlwbGUoW2RvbUVsZW1lbnQxLCBkb21FbGVtZW50MiwgZG9tRWxlbWVudDNdLCAxMjM0NS43ODksIFt7IG9wdGlvbnMgfSwgJ2V1cm9Qb3MnXSk7XG4gKiBbYW5FbGVtZW50MSwgYW5FbGVtZW50MiwgYW5FbGVtZW50M10gPSBBdXRvTnVtZXJpYy5tdWx0aXBsZS5mcmVuY2goW2RvbUVsZW1lbnQxLCBkb21FbGVtZW50MiwgZG9tRWxlbWVudDNdLCBbMTIzNDUuNzg5LCAyMzQuNzgsIG51bGxdLCB7IG9wdGlvbnMgfSk7XG4gKiBbYW5FbGVtZW50MSwgYW5FbGVtZW50MiwgYW5FbGVtZW50M10gPSBBdXRvTnVtZXJpYy5tdWx0aXBsZS5mcmVuY2goW2RvbUVsZW1lbnQxLCBkb21FbGVtZW50MiwgZG9tRWxlbWVudDNdLCBbMTIzNDUuNzg5LCAyMzQuNzgsIG51bGxdLCBbeyBvcHRpb25zIH0sICdldXJvUG9zJ10pO1xuICpcbiAqIC8vIFNwZWNpYWwgY2FzZSwgaWYgYSA8Zm9ybT4gZWxlbWVudCBpcyBwYXNzZWQgKG9yIGFueSBvdGhlciAncGFyZW50JyAob3IgJ3Jvb3QnKSBET00gZWxlbWVudCksIHRoZW4gYXV0b051bWVyaWMgd2lsbCBpbml0aWFsaXplIGVhY2ggY2hpbGQgYDxpbnB1dD5gIGVsZW1lbnRzIHJlY3Vyc2l2ZWx5LCBpZ25vcmluZyB0aG9zZSByZWZlcmVuY2VkIGluIHRoZSBgZXhjbHVkZWAgYXR0cmlidXRlXG4gKiBbYW5FbGVtZW50MSwgYW5FbGVtZW50Ml0gPSBBdXRvTnVtZXJpYy5tdWx0aXBsZSh7IHJvb3RFbGVtZW50OiBmb3JtRWxlbWVudCB9LCB7IG9wdGlvbnMgfSk7XG4gKiBbYW5FbGVtZW50MSwgYW5FbGVtZW50Ml0gPSBBdXRvTnVtZXJpYy5tdWx0aXBsZSh7IHJvb3RFbGVtZW50OiBmb3JtRWxlbWVudCwgZXhjbHVkZSA6IFtoaWRkZW5FbGVtZW50LCB0b2tlbkVsZW1lbnRdIH0sIHsgb3B0aW9ucyB9KTtcbiAqIFthbkVsZW1lbnQxLCBhbkVsZW1lbnQyXSA9IEF1dG9OdW1lcmljLm11bHRpcGxlKHsgcm9vdEVsZW1lbnQ6IGZvcm1FbGVtZW50LCBleGNsdWRlIDogW2hpZGRlbkVsZW1lbnQsIHRva2VuRWxlbWVudF0gfSwgWzEyMzQ1Ljc4OSwgbnVsbF0sIHsgb3B0aW9ucyB9KTtcbiAqXG4gKiAvLyBJZiB5b3Ugd2FudCB0byBzZWxlY3QgbXVsdGlwbGUgZWxlbWVudHMgdmlhIGEgY3NzIHNlbGVjdG9yLCB0aGVuIHlvdSBtdXN0IHVzZSB0aGUgYG11bHRpcGxlYCBmdW5jdGlvbi4gVW5kZXIgdGhlIGhvb2QgYFF1ZXJ5U2VsZWN0b3JBbGxgIGlzIHVzZWQuXG4gKiBbYW5FbGVtZW50MSwgYW5FbGVtZW50Ml0gPSBBdXRvTnVtZXJpYy5tdWx0aXBsZSgnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsIHsgb3B0aW9ucyB9KTsgLy8gVGhpcyBhbHdheXMgcmV0dXJuIGFuIEFycmF5LCBldmVuIGlmIHRoZXJlIGlzIG9ubHkgb25lIGVsZW1lbnQgc2VsZWN0ZWRcbiAqIFthbkVsZW1lbnQxLCBhbkVsZW1lbnQyXSA9IEF1dG9OdW1lcmljLm11bHRpcGxlKCcubXlDc3NDbGFzcyA+IGlucHV0JywgW251bGwsIDEyMzQ1Ljc4OV0sIHsgb3B0aW9ucyB9KTsgLy8gSWRlbSBhYm92ZSwgYnV0IHdpdGggcGFzc2luZyB0aGUgaW5pdGlhbCB2YWx1ZXMgdG9vXG4gKlxuICogQHBhcmFtIHtzdHJpbmd8QXJyYXl8eyByb290RWxlbWVudDogSFRNTEVsZW1lbnQgfXx7IHJvb3RFbGVtZW50OiBIVE1MRWxlbWVudCwgZXhjbHVkZTogQXJyYXk8SFRNTElucHV0RWxlbWVudD59fSBhcmcxXG4gKiBAcGFyYW0ge251bWJlcnxBcnJheXxvYmplY3R8bnVsbH0gaW5pdGlhbFZhbHVlXG4gKiBAcGFyYW0ge29iamVjdHxBcnJheXxudWxsfSBvcHRpb25zXG4gKiBAcmV0dXJucyB7QXJyYXl9XG4gKi9cbkF1dG9OdW1lcmljLm11bHRpcGxlID0gKGFyZzEsIGluaXRpYWxWYWx1ZSA9IG51bGwsIG9wdGlvbnMgPSBudWxsKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gW107XG5cbiAgICAvLyBBbmFseXplIHRoZSBhcmd1bWVudHMgYW5kIHRyYW5zZm9ybSB0aGVtIHRvIG1ha2UgdGhlbSBleHBsb2l0YWJsZVxuICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc09iamVjdChpbml0aWFsVmFsdWUpKSB7XG4gICAgICAgIC8vIElmIHRoZSB1c2VyIGdhdmUgYW4gb3B0aW9uIG9iamVjdCBhcyB0aGUgc2Vjb25kIGFyZ3VtZW50LCBpbnN0ZWFkIG9mIHRoZSBpbml0aWFsIHZhbHVlc1xuICAgICAgICBvcHRpb25zID0gaW5pdGlhbFZhbHVlO1xuICAgICAgICBpbml0aWFsVmFsdWUgPSBudWxsO1xuICAgIH1cblxuICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc1N0cmluZyhhcmcxKSkge1xuICAgICAgICBhcmcxID0gWy4uLiBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKGFyZzEpXTsgLy8gQ29udmVydCBhIE5vZGVMaXN0IHRvIGFuIEFycmF5IChjZi4gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzcyOTcyOTIvMjgzNDg5OClcbiAgICB9IGVsc2UgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzT2JqZWN0KGFyZzEpKSB7XG4gICAgICAgIGlmICghYXJnMS5oYXNPd25Qcm9wZXJ0eSgncm9vdEVsZW1lbnQnKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIG9iamVjdCBwYXNzZWQgdG8gdGhlICdtdWx0aXBsZScgZnVuY3Rpb24gaXMgaW52YWxpZCA7IG5vICdyb290RWxlbWVudCcgYXR0cmlidXRlIGZvdW5kLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmV0cmlldmUgdGhlIERPTSBlbGVtZW50IGxpc3QgZnJvbSB0aGUgZ2l2ZW4gPGZvcm0+IGVsZW1lbnRcbiAgICAgICAgY29uc3QgZWxlbWVudHMgPSBbLi4uIGFyZzEucm9vdEVsZW1lbnQucXVlcnlTZWxlY3RvckFsbCgnaW5wdXQnKV07XG4gICAgICAgIGlmIChhcmcxLmhhc093blByb3BlcnR5KCdleGNsdWRlJykpIHtcbiAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShhcmcxLmV4Y2x1ZGUpKSB7XG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlICdleGNsdWRlJyBhcnJheSBwYXNzZWQgdG8gdGhlICdtdWx0aXBsZScgZnVuY3Rpb24gaXMgaW52YWxpZC5gKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRmlsdGVyIG91dCB0aGUgZXhjbHVkZWQgZWxlbWVudHNcbiAgICAgICAgICAgIGFyZzEgPSBBdXRvTnVtZXJpY0hlbHBlci5maWx0ZXJPdXQoZWxlbWVudHMsIGFyZzEuZXhjbHVkZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhcmcxID0gZWxlbWVudHM7XG4gICAgICAgIH1cbiAgICB9IGVsc2UgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc0FycmF5KGFyZzEpKSB7XG4gICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBnaXZlbiBwYXJhbWV0ZXJzIHRvIHRoZSAnbXVsdGlwbGUnIGZ1bmN0aW9uIGFyZSBpbnZhbGlkLmApO1xuICAgIH1cblxuICAgIGlmIChhcmcxLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBsZXQgc2hvd1dhcm5pbmdzID0gdHJ1ZTtcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucykgJiYgQXV0b051bWVyaWNIZWxwZXIuaXNCb29sZWFuKG9wdGlvbnMuc2hvd1dhcm5pbmdzKSkge1xuICAgICAgICAgICAgc2hvd1dhcm5pbmdzID0gb3B0aW9ucy5zaG93V2FybmluZ3M7XG4gICAgICAgIH1cblxuICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKGBObyB2YWxpZCBET00gZWxlbWVudHMgd2VyZSBnaXZlbiBoZW5jZSBubyBBdXRvTnVtZXJpYyBvYmplY3Qgd2VyZSBpbnN0YW50aWF0ZWQuYCwgc2hvd1dhcm5pbmdzKTtcblxuICAgICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgLy8gQXQgdGhpcyBwb2ludCwgd2Uga25vdyBgYXJnMWAgaXMgYW4gYXJyYXkgb2YgRE9NIGVsZW1lbnRzXG5cbiAgICAvLyBUaGlzIGZ1bmN0aW9uIGNhbiBiZSBpbml0aWFsaXplZCB3aXRoIHR3byB0eXBlcyBvZiBhcnJheSwgb25lIGZvciB0aGUgaW5pdGlhbCB2YWx1ZXMsIGFuZC9vciBvbmUgZm9yIHRoZSBvcHRpb25zLlxuICAgIC8vIFNvIHdlIG5lZWQgdG8gZmluZCBvdXQgaWYgYW4gYXJyYXkgaXMgZGV0ZWN0ZWQgaWYgdGhlIHVzZXIgcGFzc2VkIGFuIGFycmF5IG9mIGluaXRpYWwgdmFsdWVzLCBvciBhbiBhcnJheSBvZiBvcHRpb25zXG4gICAgLy8gVGhlcmVmb3JlLCB3ZSBhbmFseXplIHRoZSBjb250ZW50IG9mIHRoZSBhcnJheXMgZm9yIHRoZSBzZWNvbmQgYW5kIHRoaXJkIGFyZ3VtZW50c1xuICAgIC8vIC4uLmZvciB0aGUgc2Vjb25kIHBhcmFtZXRlciA6XG4gICAgY29uc3QgaXNJbml0aWFsVmFsdWVBcnJheSA9IEF1dG9OdW1lcmljSGVscGVyLmlzQXJyYXkoaW5pdGlhbFZhbHVlKTtcbiAgICBjb25zdCBpc0luaXRpYWxWYWx1ZUFycmF5QW5kTm90RW1wdHkgPSBpc0luaXRpYWxWYWx1ZUFycmF5ICYmIGluaXRpYWxWYWx1ZS5sZW5ndGggPj0gMTtcbiAgICBsZXQgc2Vjb25kQXJndW1lbnRJc0luaXRpYWxWYWx1ZUFycmF5ID0gZmFsc2U7XG4gICAgbGV0IHNlY29uZEFyZ3VtZW50SXNPcHRpb25BcnJheSA9IGZhbHNlO1xuICAgIC8vIEFueSBvZiB0aGUgYXJyYXlzIGNhbiBiZSBlaXRoZXIgYW4gYXJyYXkgb2YgaW5pdGlhbCB2YWx1ZXMsIG9yIGFuIGFycmF5IG9mIG9wdGlvbiBvYmplY3QvcHJlLWRlZmluZWQgb3B0aW9uIG5hbWVzXG4gICAgaWYgKGlzSW5pdGlhbFZhbHVlQXJyYXlBbmROb3RFbXB0eSkge1xuICAgICAgICBjb25zdCB0eXBlT2ZGaXJzdEFycmF5RWxlbWVudCA9IHR5cGVvZiBOdW1iZXIoaW5pdGlhbFZhbHVlWzBdKTtcbiAgICAgICAgLy8gRmlyc3Qgd2UgdGVzdCB0aGUgc2Vjb25kIGFyZ3VtZW50XG4gICAgICAgIHNlY29uZEFyZ3VtZW50SXNJbml0aWFsVmFsdWVBcnJheSA9IHR5cGVPZkZpcnN0QXJyYXlFbGVtZW50ID09PSAnbnVtYmVyJyAmJiAhaXNOYU4oTnVtYmVyKGluaXRpYWxWYWx1ZVswXSkpO1xuXG4gICAgICAgIGlmICghc2Vjb25kQXJndW1lbnRJc0luaXRpYWxWYWx1ZUFycmF5KSB7XG4gICAgICAgICAgICAvLyBJZiB0aGUgc2Vjb25kIGFyZ3VtZW50IGlzIGFuIGFycmF5LCBidXQgbm90IGFuIGFycmF5IG9mIHZhbHVlcywgY2hlY2sgaWYgaXQncyBpbnN0ZWFkIGFuIGFycmF5IG9mIG9wdGlvbnMvcHJlLWRlZmluZWQgb3B0aW9uIG5hbWVzXG4gICAgICAgICAgICBpZiAodHlwZU9mRmlyc3RBcnJheUVsZW1lbnQgPT09ICdzdHJpbmcnIHx8IGlzTmFOKHR5cGVPZkZpcnN0QXJyYXlFbGVtZW50KSB8fCB0eXBlT2ZGaXJzdEFycmF5RWxlbWVudCA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICBzZWNvbmRBcmd1bWVudElzT3B0aW9uQXJyYXkgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gLi4uZm9yIHRoZSB0aGlyZCBwYXJhbWV0ZXIgOlxuICAgIGNvbnN0IGlzT3B0aW9uc0FycmF5QW5kTm90RW1wdHkgPSBBdXRvTnVtZXJpY0hlbHBlci5pc0FycmF5KG9wdGlvbnMpICYmIG9wdGlvbnMubGVuZ3RoID49IDE7XG4gICAgbGV0IHRoaXJkQXJndW1lbnRJc09wdGlvbkFycmF5ID0gZmFsc2U7XG4gICAgaWYgKGlzT3B0aW9uc0FycmF5QW5kTm90RW1wdHkpIHtcbiAgICAgICAgY29uc3QgdHlwZU9mRmlyc3RBcnJheUVsZW1lbnQgPSB0eXBlb2Ygb3B0aW9uc1swXTtcbiAgICAgICAgaWYgKHR5cGVPZkZpcnN0QXJyYXlFbGVtZW50ID09PSAnc3RyaW5nJyB8fCB0eXBlT2ZGaXJzdEFycmF5RWxlbWVudCA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIC8vIElmIHRoZSB0aGlyZCBhcmd1bWVudCBpcyBhbiBhcnJheSBvZiBvcHRpb25zL3ByZS1kZWZpbmVkIG9wdGlvbiBuYW1lc1xuICAgICAgICAgICAgdGhpcmRBcmd1bWVudElzT3B0aW9uQXJyYXkgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gRGVwZW5kaW5nIG9mIG91ciBmaW5kaW5ncywgd2UgZ2VuZXJhdGUgdGhlIG9wdGlvbnMgdmFyaWFibGUgdG8gdXNlIGBvcHRpb25zVG9Vc2VgLCBlaXRoZXIgZGlyZWN0bHksIG9yIG1lcmdlZFxuICAgIGxldCBvcHRpb25zVG9Vc2U7XG4gICAgaWYgKHNlY29uZEFyZ3VtZW50SXNPcHRpb25BcnJheSkge1xuICAgICAgICBvcHRpb25zVG9Vc2UgPSBBdXRvTnVtZXJpYy5tZXJnZU9wdGlvbnMoaW5pdGlhbFZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHRoaXJkQXJndW1lbnRJc09wdGlvbkFycmF5KSB7XG4gICAgICAgIG9wdGlvbnNUb1VzZSA9IEF1dG9OdW1lcmljLm1lcmdlT3B0aW9ucyhvcHRpb25zKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBvcHRpb25zVG9Vc2UgPSBvcHRpb25zO1xuICAgIH1cblxuXG4gICAgLy8gSW5pdGlhbGl6ZSB0aGUgaW5pdGlhbCB2YWx1ZXNcbiAgICBjb25zdCBpc0luaXRpYWxWYWx1ZU51bWJlciA9IEF1dG9OdW1lcmljSGVscGVyLmlzTnVtYmVyKGluaXRpYWxWYWx1ZSk7XG4gICAgbGV0IGluaXRpYWxWYWx1ZUFycmF5U2l6ZTtcbiAgICBpZiAoc2Vjb25kQXJndW1lbnRJc0luaXRpYWxWYWx1ZUFycmF5KSB7XG4gICAgICAgIGluaXRpYWxWYWx1ZUFycmF5U2l6ZSA9IGluaXRpYWxWYWx1ZS5sZW5ndGg7XG4gICAgfVxuXG4gICAgLy8gSW5zdGFudGlhdGUgZWFjaCBBdXRvTnVtZXJpYyBvYmplY3RzXG4gICAgYXJnMS5mb3JFYWNoKChkb21FbGVtZW50LCBpbmRleCkgPT4ge1xuICAgICAgICBpZiAoaXNJbml0aWFsVmFsdWVOdW1iZXIpIHtcbiAgICAgICAgICAgIC8vIFdlIHNldCB0aGUgc2FtZSB2YWx1ZSBmb3IgZWFjaCBlbGVtZW50c1xuICAgICAgICAgICAgcmVzdWx0LnB1c2gobmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIGluaXRpYWxWYWx1ZSwgb3B0aW9uc1RvVXNlKSk7XG4gICAgICAgIH0gZWxzZSBpZiAoc2Vjb25kQXJndW1lbnRJc0luaXRpYWxWYWx1ZUFycmF5ICYmIGluZGV4IDw9IGluaXRpYWxWYWx1ZUFycmF5U2l6ZSkge1xuICAgICAgICAgICAgcmVzdWx0LnB1c2gobmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIGluaXRpYWxWYWx1ZVtpbmRleF0sIG9wdGlvbnNUb1VzZSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzdWx0LnB1c2gobmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIG51bGwsIG9wdGlvbnNUb1VzZSkpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xufTtcblxuLyoqXG4gKiBQb2x5ZmlsbCBmb3Igb2Jzb2xldGUgYnJvd3NlcnMgbGlrZSBJRVxuICovXG4oZnVuY3Rpb24oKSB7XG4vLyBQb2x5ZmlsbCBmb3IgYEFycmF5LmZyb20oKWAgKEZpeCBpc3N1ZSAjNDk1KVxuaWYgKCFBcnJheS5mcm9tKSB7XG4gICAgQXJyYXkuZnJvbSA9IG9iamVjdCA9PiBbXS5zbGljZS5jYWxsKG9iamVjdCk7XG59XG5cbi8vIFBvbHlmaWxsIGZvciBgQ3VzdG9tRXZlbnRgIChjZi4gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0N1c3RvbUV2ZW50L0N1c3RvbUV2ZW50KVxuaWYgKHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnIHx8IHR5cGVvZiB3aW5kb3cuQ3VzdG9tRXZlbnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIEN1c3RvbUV2ZW50KGV2ZW50LCBwYXJhbXMpIHtcbiAgICBwYXJhbXMgPSBwYXJhbXMgfHwgeyBidWJibGVzOiBmYWxzZSwgY2FuY2VsYWJsZTogZmFsc2UsIGRldGFpbDogdm9pZCgwKSB9O1xuICAgIGNvbnN0IGV2dCA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdDdXN0b21FdmVudCcpO1xuICAgIGV2dC5pbml0Q3VzdG9tRXZlbnQoZXZlbnQsIHBhcmFtcy5idWJibGVzLCBwYXJhbXMuY2FuY2VsYWJsZSwgcGFyYW1zLmRldGFpbCk7XG4gICAgcmV0dXJuIGV2dDtcbn1cblxuQ3VzdG9tRXZlbnQucHJvdG90eXBlID0gd2luZG93LkV2ZW50LnByb3RvdHlwZTtcbndpbmRvdy5DdXN0b21FdmVudCA9IEN1c3RvbUV2ZW50O1xufSkoKTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBK0NBO0FBQ0E7QUFDQTtBQURBO0FBQ0E7OztBQUFBO0FBQ0E7Ozs7Ozs7OztBQUNBOzs7OztBQUtBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQXVDQTtBQUFBO0FBQ0E7QUFEQTtBQUNBO0FBREE7QUFBQTtBQUNBO0FBREE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUhBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFLQTtBQUNBO0FBQ0E7QUFEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQW5CQTtBQXFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7QUFNQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7QUFPQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7QUFPQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7O0FBTUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7OztBQU1BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7QUFNQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7O0FBTUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUFLQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FBS0E7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FBS0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVdBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7OztBQU1BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FBSUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTs7OztBQUlBO0FBQUE7QUFBQTtBQWxXQTtBQUNBO0FBb1dBO0FBQ0E7Ozs7QUFJQTtBQUNBOzs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQXpUQTtBQUNBO0FBMlRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSkE7QUFNQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBb09BOzs7Ozs7Ozs7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7QUFJQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFxQkE7Ozs7Ozs7QUFPQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBVEE7QUFXQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7QUFjQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBS0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUxBO0FBT0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFVQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQVNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVJBO0FBQ0E7QUFVQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUFJQTs7Ozs7Ozs7Ozs7Ozs7O0FBZUE7Ozs7Ozs7Ozs7QUFPQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUFJQTs7Ozs7Ozs7Ozs7Ozs7O0FBZUE7Ozs7Ozs7Ozs7O0FBUUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7QUFJQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBbUJBO0FBQUE7QUFDQTtBQURBO0FBQUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQVVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFnQkE7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBYkE7QUFlQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FBU0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFoQkE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQWlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUxBO0FBQ0E7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUFTQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFQQTtBQVNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7QUFZQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7QUFvQ0E7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUFTQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFlQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQVVBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FBU0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7O0FBVUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQWVBO0FBQUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FBU0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQVNBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFaQTtBQWNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBZUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUFTQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQVNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFlQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7OztBQWNBO0FBQUE7QUFDQTtBQURBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFEQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7OztBQVlBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBS0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7QUFLQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7OztBQUtBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQVNBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFpS0E7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUFTQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQVVBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUZBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7OztBQTY3QkE7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBUUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUdBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7OztBQWlTQTs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUFzT0E7Ozs7Ozs7Ozs7Ozs7O0FBY0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBUkE7QUFVQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBUkE7QUFVQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBUkE7QUFVQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBUkE7QUFVQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQVJBO0FBVUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQVJBO0FBVUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQVJBO0FBVUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQVJBO0FBVUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FBcVhBOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQXlDQTs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFjQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTBDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVBBO0FBU0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7O0FBV0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVhBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFZQTtBQUNBO0FBQ0E7QUFEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBakJBO0FBbUJBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUF4SUE7QUFDQTtBQTBJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBeUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBdkJBO0FBeUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFuQkE7QUFxQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUlBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FBU0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQVlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7O0FBTUE7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFuQkE7QUFxQkE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7QUE2TUE7Ozs7QUFJQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBREE7QUFBQTtBQUFBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQXVCQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQW9JQTs7Ozs7Ozs7O0FBU0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQThDQTs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQWFBOzs7Ozs7Ozs7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBY0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFIQTtBQUNBO0FBS0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7OztBQVdBO0FBQUE7QUFDQTtBQURBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQURBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQXBCQTtBQUNBO0FBc0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7QUFLQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRkE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQXFCQTs7Ozs7Ozs7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBcENBO0FBc0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFEQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFEQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRkE7QUFDQTtBQURBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBSEE7QUFBQTtBQUFBO0FBQ0E7QUFJQTtBQUNBO0FBQ0E7QUFEQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7QUF4elBBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7QUFhQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFpT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBS0E7QUFDQTtBQUNBOzs7QUEyOUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUNBO0FBQ0E7OztBQWtrQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUFBO0FBQ0E7QUFEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQTRIQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBWUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQTNLQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBNEtBO0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFEQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFGQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQWVBO0FBQ0E7QUFDQTtBQUNBO0FBWUE7QUFDQTtBQUNBO0FBQ0E7QUFVQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBVUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7O0FBVUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFsQkE7QUFBQTtBQUFBO0FBQ0E7QUFpQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQXJDQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBcUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBUEE7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7QUFVQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUE3QkE7QUFBQTtBQUFBO0FBQ0E7QUE0QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQURBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7O0FBVUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBRUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7O0FBVUE7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUFTQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FBU0E7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFtTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBZUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRkE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FBU0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUFTQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFEQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBbUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7QUFVQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQXJCQTtBQUNBO0FBdUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFnQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBUEE7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7O0FBVUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVpBO0FBQ0E7QUFjQTtBQUNBO0FBMUNBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUEwQ0E7QUFBQTtBQUNBO0FBREE7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7OztBQVlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBVkE7QUFZQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVZBO0FBWUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQTZNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBWEE7QUFDQTtBQWFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7O0FBV0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBQ0E7QUFmQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBZ0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFyQkE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQW9CQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVRBO0FBQ0E7QUFXQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FBU0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7O0FBVUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUtBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FBU0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUpBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFNQTtBQUNBO0FBQ0E7QUFEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FBU0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFYQTtBQUNBO0FBYUE7QUFDQTs7O0FBbUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQWcvQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVJBO0FBVUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQVNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBbUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQW9CQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBSUE7QUFDQTs7O0FBa0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUE2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBaEdBO0FBQ0E7QUFrR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQXdHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBY0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBb0JBO0FBQ0E7QUFDQTtBQUNBOzs7QUE0VkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7OztBQXNjQTtBQUFBO0FBQUE7QUFDQTtBQURBO0FBQ0E7QUFEQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUF2QkE7QUF5QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUNBOzs7Ozs7QUFHQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTd5UkE7QUF1MFJBO0FBQUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0EiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./src/AutoNumeric.js\n");

/***/ }),

/***/ "./src/AutoNumericDefaultSettings.js":
/*!*******************************************!*\
  !*** ./src/AutoNumericDefaultSettings.js ***!
  \*******************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

"use strict";
eval("\n\nvar _AutoNumeric = __webpack_require__(/*! ./AutoNumeric */ \"./src/AutoNumeric.js\");\n\nvar _AutoNumeric2 = _interopRequireDefault(_AutoNumeric);\n\nvar _AutoNumericOptions = __webpack_require__(/*! ./AutoNumericOptions */ \"./src/AutoNumericOptions.js\");\n\nvar _AutoNumericOptions2 = _interopRequireDefault(_AutoNumericOptions);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/* eslint no-unused-vars: 0 */\n\n/**\n * The defaults options.\n * These can be overridden by the following methods:\n * - HTML5 data attributes (ie. `<input type=\"text\" data-currency-symbol=\" €\">`)\n * - Options passed to the `update` method (ie. `anElement.update({ currencySymbol: ' €' });`), or simply during the initialization (ie. `new AutoNumeric(domElement, { options });`)\n */\n/**\n * Default settings for autoNumeric.js\n * @author Alexandre Bonneau <alexandre.bonneau@linuxfr.eu>\n * @copyright © 2016 Alexandre Bonneau\n *\n * The MIT License (http://www.opensource.org/licenses/mit-license.php)\n *\n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sub license, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n_AutoNumeric2.default.defaultSettings = {\n  allowDecimalPadding: _AutoNumeric2.default.options.allowDecimalPadding.always,\n  alwaysAllowDecimalCharacter: _AutoNumeric2.default.options.alwaysAllowDecimalCharacter.doNotAllow,\n  caretPositionOnFocus: _AutoNumeric2.default.options.caretPositionOnFocus.doNoForceCaretPosition,\n  createLocalList: _AutoNumeric2.default.options.createLocalList.createList,\n  currencySymbol: _AutoNumeric2.default.options.currencySymbol.none,\n  currencySymbolPlacement: _AutoNumeric2.default.options.currencySymbolPlacement.prefix,\n  decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.dot,\n  decimalCharacterAlternative: _AutoNumeric2.default.options.decimalCharacterAlternative.none,\n  decimalPlaces: _AutoNumeric2.default.options.decimalPlaces.two,\n  decimalPlacesRawValue: _AutoNumeric2.default.options.decimalPlacesRawValue.useDefault,\n  decimalPlacesShownOnBlur: _AutoNumeric2.default.options.decimalPlacesShownOnBlur.useDefault,\n  decimalPlacesShownOnFocus: _AutoNumeric2.default.options.decimalPlacesShownOnFocus.useDefault,\n  defaultValueOverride: _AutoNumeric2.default.options.defaultValueOverride.doNotOverride,\n  digitalGroupSpacing: _AutoNumeric2.default.options.digitalGroupSpacing.three,\n  digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.comma,\n  divisorWhenUnfocused: _AutoNumeric2.default.options.divisorWhenUnfocused.none,\n  emptyInputBehavior: _AutoNumeric2.default.options.emptyInputBehavior.focus,\n  eventBubbles: _AutoNumeric2.default.options.eventBubbles.bubbles,\n  eventIsCancelable: _AutoNumeric2.default.options.eventIsCancelable.isCancelable,\n  failOnUnknownOption: _AutoNumeric2.default.options.failOnUnknownOption.ignore,\n  formatOnPageLoad: _AutoNumeric2.default.options.formatOnPageLoad.format,\n  historySize: _AutoNumeric2.default.options.historySize.medium,\n  isCancellable: _AutoNumeric2.default.options.isCancellable.cancellable,\n  leadingZero: _AutoNumeric2.default.options.leadingZero.deny,\n  maximumValue: _AutoNumeric2.default.options.maximumValue.tenTrillions,\n  minimumValue: _AutoNumeric2.default.options.minimumValue.tenTrillions,\n  modifyValueOnWheel: _AutoNumeric2.default.options.modifyValueOnWheel.modifyValue,\n  negativeBracketsTypeOnBlur: _AutoNumeric2.default.options.negativeBracketsTypeOnBlur.none,\n  negativePositiveSignPlacement: _AutoNumeric2.default.options.negativePositiveSignPlacement.none,\n  negativeSignCharacter: _AutoNumeric2.default.options.negativeSignCharacter.hyphen,\n  noEventListeners: _AutoNumeric2.default.options.noEventListeners.addEvents,\n  //TODO Shouldn't we use `truncate` as the default value?\n  onInvalidPaste: _AutoNumeric2.default.options.onInvalidPaste.error,\n  outputFormat: _AutoNumeric2.default.options.outputFormat.none,\n  overrideMinMaxLimits: _AutoNumeric2.default.options.overrideMinMaxLimits.doNotOverride,\n  positiveSignCharacter: _AutoNumeric2.default.options.positiveSignCharacter.plus,\n  rawValueDivisor: _AutoNumeric2.default.options.rawValueDivisor.none,\n  readOnly: _AutoNumeric2.default.options.readOnly.readWrite,\n  roundingMethod: _AutoNumeric2.default.options.roundingMethod.halfUpSymmetric,\n  saveValueToSessionStorage: _AutoNumeric2.default.options.saveValueToSessionStorage.doNotSave,\n  selectNumberOnly: _AutoNumeric2.default.options.selectNumberOnly.selectNumbersOnly,\n  selectOnFocus: _AutoNumeric2.default.options.selectOnFocus.select,\n  serializeSpaces: _AutoNumeric2.default.options.serializeSpaces.plus,\n  showOnlyNumbersOnFocus: _AutoNumeric2.default.options.showOnlyNumbersOnFocus.showAll,\n  showPositiveSign: _AutoNumeric2.default.options.showPositiveSign.hide,\n  showWarnings: _AutoNumeric2.default.options.showWarnings.show,\n  styleRules: _AutoNumeric2.default.options.styleRules.none,\n  suffixText: _AutoNumeric2.default.options.suffixText.none,\n  symbolWhenUnfocused: _AutoNumeric2.default.options.symbolWhenUnfocused.none,\n  unformatOnHover: _AutoNumeric2.default.options.unformatOnHover.unformat,\n  unformatOnSubmit: _AutoNumeric2.default.options.unformatOnSubmit.keepCurrentValue,\n  valuesToStrings: _AutoNumeric2.default.options.valuesToStrings.none,\n  watchExternalChanges: _AutoNumeric2.default.options.watchExternalChanges.doNotWatch,\n  wheelOn: _AutoNumeric2.default.options.wheelOn.focus,\n  wheelStep: _AutoNumeric2.default.options.wheelStep.progressive\n};\n\nObject.freeze(_AutoNumeric2.default.defaultSettings);\nObject.defineProperty(_AutoNumeric2.default, 'defaultSettings', { configurable: false, writable: false });\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvQXV0b051bWVyaWNEZWZhdWx0U2V0dGluZ3MuanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9BdXRvTnVtZXJpYy9zcmMvQXV0b051bWVyaWNEZWZhdWx0U2V0dGluZ3MuanM/NTJkNiJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIERlZmF1bHQgc2V0dGluZ3MgZm9yIGF1dG9OdW1lcmljLmpzXG4gKiBAYXV0aG9yIEFsZXhhbmRyZSBCb25uZWF1IDxhbGV4YW5kcmUuYm9ubmVhdUBsaW51eGZyLmV1PlxuICogQGNvcHlyaWdodCDCqSAyMDE2IEFsZXhhbmRyZSBCb25uZWF1XG4gKlxuICogVGhlIE1JVCBMaWNlbnNlIChodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL21pdC1saWNlbnNlLnBocClcbiAqXG4gKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvblxuICogb2J0YWluaW5nIGEgY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb25cbiAqIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dFxuICogcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsXG4gKiBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWIgbGljZW5zZSwgYW5kL29yIHNlbGxcbiAqIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZVxuICogU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmdcbiAqIGNvbmRpdGlvbnM6XG4gKlxuICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmVcbiAqIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICpcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsXG4gKiBFWFBSRVNTIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVNcbiAqIE9GIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EXG4gKiBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVFxuICogSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksXG4gKiBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkdcbiAqIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1JcbiAqIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cbiAqL1xuXG5pbXBvcnQgQXV0b051bWVyaWMgZnJvbSAnLi9BdXRvTnVtZXJpYyc7XG5pbXBvcnQgQXV0b051bWVyaWNPcHRpb25zIGZyb20gJy4vQXV0b051bWVyaWNPcHRpb25zJztcblxuLyogZXNsaW50IG5vLXVudXNlZC12YXJzOiAwICovXG5cbi8qKlxuICogVGhlIGRlZmF1bHRzIG9wdGlvbnMuXG4gKiBUaGVzZSBjYW4gYmUgb3ZlcnJpZGRlbiBieSB0aGUgZm9sbG93aW5nIG1ldGhvZHM6XG4gKiAtIEhUTUw1IGRhdGEgYXR0cmlidXRlcyAoaWUuIGA8aW5wdXQgdHlwZT1cInRleHRcIiBkYXRhLWN1cnJlbmN5LXN5bWJvbD1cIiDigqxcIj5gKVxuICogLSBPcHRpb25zIHBhc3NlZCB0byB0aGUgYHVwZGF0ZWAgbWV0aG9kIChpZS4gYGFuRWxlbWVudC51cGRhdGUoeyBjdXJyZW5jeVN5bWJvbDogJyDigqwnIH0pO2ApLCBvciBzaW1wbHkgZHVyaW5nIHRoZSBpbml0aWFsaXphdGlvbiAoaWUuIGBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgeyBvcHRpb25zIH0pO2ApXG4gKi9cbkF1dG9OdW1lcmljLmRlZmF1bHRTZXR0aW5ncyA9IHtcbiAgICBhbGxvd0RlY2ltYWxQYWRkaW5nICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5hbGxvd0RlY2ltYWxQYWRkaW5nLmFsd2F5cyxcbiAgICBhbHdheXNBbGxvd0RlY2ltYWxDaGFyYWN0ZXIgIDogQXV0b051bWVyaWMub3B0aW9ucy5hbHdheXNBbGxvd0RlY2ltYWxDaGFyYWN0ZXIuZG9Ob3RBbGxvdyxcbiAgICBjYXJldFBvc2l0aW9uT25Gb2N1cyAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1cy5kb05vRm9yY2VDYXJldFBvc2l0aW9uLFxuICAgIGNyZWF0ZUxvY2FsTGlzdCAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmNyZWF0ZUxvY2FsTGlzdC5jcmVhdGVMaXN0LFxuICAgIGN1cnJlbmN5U3ltYm9sICAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sLm5vbmUsXG4gICAgY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQucHJlZml4LFxuICAgIGRlY2ltYWxDaGFyYWN0ZXIgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXIuZG90LFxuICAgIGRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZSAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZS5ub25lLFxuICAgIGRlY2ltYWxQbGFjZXMgICAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxQbGFjZXMudHdvLFxuICAgIGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZS51c2VEZWZhdWx0LFxuICAgIGRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ci51c2VEZWZhdWx0LFxuICAgIGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMudXNlRGVmYXVsdCxcbiAgICBkZWZhdWx0VmFsdWVPdmVycmlkZSAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kZWZhdWx0VmFsdWVPdmVycmlkZS5kb05vdE92ZXJyaWRlLFxuICAgIGRpZ2l0YWxHcm91cFNwYWNpbmcgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0YWxHcm91cFNwYWNpbmcudGhyZWUsXG4gICAgZGlnaXRHcm91cFNlcGFyYXRvciAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci5jb21tYSxcbiAgICBkaXZpc29yV2hlblVuZm9jdXNlZCAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kaXZpc29yV2hlblVuZm9jdXNlZC5ub25lLFxuICAgIGVtcHR5SW5wdXRCZWhhdmlvciAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5mb2N1cyxcbiAgICBldmVudEJ1YmJsZXMgICAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5ldmVudEJ1YmJsZXMuYnViYmxlcyxcbiAgICBldmVudElzQ2FuY2VsYWJsZSAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5ldmVudElzQ2FuY2VsYWJsZS5pc0NhbmNlbGFibGUsXG4gICAgZmFpbE9uVW5rbm93bk9wdGlvbiAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZmFpbE9uVW5rbm93bk9wdGlvbi5pZ25vcmUsXG4gICAgZm9ybWF0T25QYWdlTG9hZCAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZm9ybWF0T25QYWdlTG9hZC5mb3JtYXQsXG4gICAgaGlzdG9yeVNpemUgICAgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuaGlzdG9yeVNpemUubWVkaXVtLFxuICAgIGlzQ2FuY2VsbGFibGUgICAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmlzQ2FuY2VsbGFibGUuY2FuY2VsbGFibGUsXG4gICAgbGVhZGluZ1plcm8gICAgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMubGVhZGluZ1plcm8uZGVueSxcbiAgICBtYXhpbXVtVmFsdWUgICAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5tYXhpbXVtVmFsdWUudGVuVHJpbGxpb25zLFxuICAgIG1pbmltdW1WYWx1ZSAgICAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLm1pbmltdW1WYWx1ZS50ZW5UcmlsbGlvbnMsXG4gICAgbW9kaWZ5VmFsdWVPbldoZWVsICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMubW9kaWZ5VmFsdWVPbldoZWVsLm1vZGlmeVZhbHVlLFxuICAgIG5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyLm5vbmUsXG4gICAgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQ6IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubm9uZSxcbiAgICBuZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIuaHlwaGVuLFxuICAgIG5vRXZlbnRMaXN0ZW5lcnMgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLm5vRXZlbnRMaXN0ZW5lcnMuYWRkRXZlbnRzLFxuICAgIC8vVE9ETyBTaG91bGRuJ3Qgd2UgdXNlIGB0cnVuY2F0ZWAgYXMgdGhlIGRlZmF1bHQgdmFsdWU/XG4gICAgb25JbnZhbGlkUGFzdGUgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUuZXJyb3IsXG4gICAgb3V0cHV0Rm9ybWF0ICAgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMub3V0cHV0Rm9ybWF0Lm5vbmUsXG4gICAgb3ZlcnJpZGVNaW5NYXhMaW1pdHMgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMub3ZlcnJpZGVNaW5NYXhMaW1pdHMuZG9Ob3RPdmVycmlkZSxcbiAgICBwb3NpdGl2ZVNpZ25DaGFyYWN0ZXIgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5wb3NpdGl2ZVNpZ25DaGFyYWN0ZXIucGx1cyxcbiAgICByYXdWYWx1ZURpdmlzb3IgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5yYXdWYWx1ZURpdmlzb3Iubm9uZSxcbiAgICByZWFkT25seSAgICAgICAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5yZWFkT25seS5yZWFkV3JpdGUsXG4gICAgcm91bmRpbmdNZXRob2QgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QuaGFsZlVwU3ltbWV0cmljLFxuICAgIHNhdmVWYWx1ZVRvU2Vzc2lvblN0b3JhZ2UgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLnNhdmVWYWx1ZVRvU2Vzc2lvblN0b3JhZ2UuZG9Ob3RTYXZlLFxuICAgIHNlbGVjdE51bWJlck9ubHkgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLnNlbGVjdE51bWJlck9ubHkuc2VsZWN0TnVtYmVyc09ubHksXG4gICAgc2VsZWN0T25Gb2N1cyAgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuc2VsZWN0T25Gb2N1cy5zZWxlY3QsXG4gICAgc2VyaWFsaXplU3BhY2VzICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuc2VyaWFsaXplU3BhY2VzLnBsdXMsXG4gICAgc2hvd09ubHlOdW1iZXJzT25Gb2N1cyAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuc2hvd09ubHlOdW1iZXJzT25Gb2N1cy5zaG93QWxsLFxuICAgIHNob3dQb3NpdGl2ZVNpZ24gICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLnNob3dQb3NpdGl2ZVNpZ24uaGlkZSxcbiAgICBzaG93V2FybmluZ3MgICAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5zaG93V2FybmluZ3Muc2hvdyxcbiAgICBzdHlsZVJ1bGVzICAgICAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5zdHlsZVJ1bGVzLm5vbmUsXG4gICAgc3VmZml4VGV4dCAgICAgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuc3VmZml4VGV4dC5ub25lLFxuICAgIHN5bWJvbFdoZW5VbmZvY3VzZWQgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLnN5bWJvbFdoZW5VbmZvY3VzZWQubm9uZSxcbiAgICB1bmZvcm1hdE9uSG92ZXIgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy51bmZvcm1hdE9uSG92ZXIudW5mb3JtYXQsXG4gICAgdW5mb3JtYXRPblN1Ym1pdCAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMudW5mb3JtYXRPblN1Ym1pdC5rZWVwQ3VycmVudFZhbHVlLFxuICAgIHZhbHVlc1RvU3RyaW5ncyAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLnZhbHVlc1RvU3RyaW5ncy5ub25lLFxuICAgIHdhdGNoRXh0ZXJuYWxDaGFuZ2VzICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLndhdGNoRXh0ZXJuYWxDaGFuZ2VzLmRvTm90V2F0Y2gsXG4gICAgd2hlZWxPbiAgICAgICAgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMud2hlZWxPbi5mb2N1cyxcbiAgICB3aGVlbFN0ZXAgICAgICAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy53aGVlbFN0ZXAucHJvZ3Jlc3NpdmUsXG59O1xuXG5PYmplY3QuZnJlZXplKEF1dG9OdW1lcmljLmRlZmF1bHRTZXR0aW5ncyk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoQXV0b051bWVyaWMsICdkZWZhdWx0U2V0dGluZ3MnLCB7IGNvbmZpZ3VyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiBmYWxzZSB9KTtcbiJdLCJtYXBwaW5ncyI6Ijs7QUE2QkE7QUFDQTs7O0FBQUE7QUFDQTs7Ozs7QUFDQTtBQUNBO0FBQ0E7Ozs7OztBQWxDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUF3Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQXZEQTtBQUNBO0FBeURBO0FBQ0EiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./src/AutoNumericDefaultSettings.js\n");

/***/ }),

/***/ "./src/AutoNumericEnum.js":
/*!********************************!*\
  !*** ./src/AutoNumericEnum.js ***!
  \********************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

"use strict";
eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\n/**\n * Enumerations for autoNumeric.js\n * @author Alexandre Bonneau <alexandre.bonneau@linuxfr.eu>\n * @copyright © 2016 Alexandre Bonneau\n *\n * The MIT License (http://www.opensource.org/licenses/mit-license.php)\n *\n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sub license, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n/**\n * Object that store the helper enumerations\n * @type {{ allowedTagList: [string], keyCode: {}, fromCharCodeKeyCode: [string], keyName: {} }}\n */\nvar AutoNumericEnum = {};\n\n/**\n * List of allowed tag on which autoNumeric can be used.\n */\nAutoNumericEnum.allowedTagList = ['b', 'caption', 'cite', 'code', 'const', 'dd', 'del', 'div', 'dfn', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'input', 'ins', 'kdb', 'label', 'li', 'option', 'output', 'p', 'q', 's', 'sample', 'span', 'strong', 'td', 'th', 'u'];\nObject.freeze(AutoNumericEnum.allowedTagList);\nObject.defineProperty(AutoNumericEnum, 'allowedTagList', { configurable: false, writable: false });\n\n/**\n * Wrapper variable that hold named keyboard keys with their respective keyCode as seen in DOM events.\n * cf. https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode\n *\n * This deprecated information is used for obsolete browsers.\n * @deprecated\n */\nAutoNumericEnum.keyCode = {\n  Backspace: 8,\n  Tab: 9,\n  // No 10, 11\n  // 12 === NumpadEqual on Windows\n  // 12 === NumLock on Mac\n  Enter: 13,\n  // 14 reserved, but not used\n  // 15 does not exists\n  Shift: 16,\n  Ctrl: 17,\n  Alt: 18,\n  Pause: 19,\n  CapsLock: 20,\n  // 21, 22, 23, 24, 25 : Asiatic key codes\n  // 26 does not exists\n  Esc: 27,\n  // 28, 29, 30, 31 : Convert, NonConvert, Accept and ModeChange keys\n  Space: 32,\n  PageUp: 33,\n  PageDown: 34,\n  End: 35,\n  Home: 36,\n  LeftArrow: 37,\n  UpArrow: 38,\n  RightArrow: 39,\n  DownArrow: 40,\n  Insert: 45,\n  Delete: 46,\n  num0: 48,\n  num1: 49,\n  num2: 50,\n  num3: 51,\n  num4: 52,\n  num5: 53,\n  num6: 54,\n  num7: 55,\n  num8: 56,\n  num9: 57,\n  a: 65,\n  b: 66,\n  c: 67,\n  d: 68,\n  e: 69,\n  f: 70,\n  g: 71,\n  h: 72,\n  i: 73,\n  j: 74,\n  k: 75,\n  l: 76,\n  m: 77,\n  n: 78,\n  o: 79,\n  p: 80,\n  q: 81,\n  r: 82,\n  s: 83,\n  t: 84,\n  u: 85,\n  v: 86,\n  w: 87,\n  x: 88,\n  y: 89,\n  z: 90,\n  OSLeft: 91,\n  OSRight: 92,\n  ContextMenu: 93,\n  numpad0: 96,\n  numpad1: 97,\n  numpad2: 98,\n  numpad3: 99,\n  numpad4: 100,\n  numpad5: 101,\n  numpad6: 102,\n  numpad7: 103,\n  numpad8: 104,\n  numpad9: 105,\n  MultiplyNumpad: 106,\n  PlusNumpad: 107,\n  MinusNumpad: 109,\n  DotNumpad: 110,\n  SlashNumpad: 111,\n  F1: 112,\n  F2: 113,\n  F3: 114,\n  F4: 115,\n  F5: 116,\n  F6: 117,\n  F7: 118,\n  F8: 119,\n  F9: 120,\n  F10: 121,\n  F11: 122,\n  F12: 123,\n  NumLock: 144,\n  ScrollLock: 145,\n  HyphenFirefox: 173, // On the latest Linux and Windows OS, cf. https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode and https://bugzilla.mozilla.org/show_bug.cgi?id=787504 and https://stackoverflow.com/a/35473259/2834898\n  MyComputer: 182,\n  MyCalculator: 183,\n  Semicolon: 186,\n  Equal: 187,\n  Comma: 188,\n  Hyphen: 189,\n  Dot: 190,\n  Slash: 191,\n  Backquote: 192,\n  LeftBracket: 219,\n  Backslash: 220,\n  RightBracket: 221,\n  Quote: 222,\n  Command: 224,\n  AltGraph: 225,\n  AndroidDefault: 229 // Android Chrome returns the same keycode number 229 for all keys pressed\n};\nObject.freeze(AutoNumericEnum.keyCode);\nObject.defineProperty(AutoNumericEnum, 'keyCode', { configurable: false, writable: false });\n\n/**\n * This object is the reverse of `keyCode`, and is used to translate the key code to named keys when no valid characters can be obtained by `String.fromCharCode`.\n * This object keys correspond to the `event.keyCode` number, and returns the corresponding key name (à la event.key)\n */\nAutoNumericEnum.fromCharCodeKeyCode = {\n  0: 'LaunchCalculator',\n  8: 'Backspace',\n  9: 'Tab',\n  13: 'Enter',\n  16: 'Shift',\n  17: 'Ctrl',\n  18: 'Alt',\n  19: 'Pause',\n  20: 'CapsLock',\n  27: 'Escape',\n  32: ' ',\n  33: 'PageUp',\n  34: 'PageDown',\n  35: 'End',\n  36: 'Home',\n  37: 'ArrowLeft',\n  38: 'ArrowUp',\n  39: 'ArrowRight',\n  40: 'ArrowDown',\n  45: 'Insert',\n  46: 'Delete',\n  48: '0',\n  49: '1',\n  50: '2',\n  51: '3',\n  52: '4',\n  53: '5',\n  54: '6',\n  55: '7',\n  56: '8',\n  57: '9',\n  // 65: 'a',\n  // 66: 'b',\n  // 67: 'c',\n  // 68: 'd',\n  // 69: 'e',\n  // 70: 'f',\n  // 71: 'g',\n  // 72: 'h',\n  // 73: 'i',\n  // 74: 'j',\n  // 75: 'k',\n  // 76: 'l',\n  // 77: 'm',\n  // 78: 'n',\n  // 79: 'o',\n  // 80: 'p',\n  // 81: 'q',\n  // 82: 'r',\n  // 83: 's',\n  // 84: 't',\n  // 85: 'u',\n  // 86: 'v',\n  // 87: 'w',\n  // 88: 'x',\n  // 89: 'y',\n  // 90: 'z',\n  91: 'OS', // Note: Firefox and Chrome reports 'OS' instead of 'OSLeft'\n  92: 'OSRight',\n  93: 'ContextMenu',\n  96: '0',\n  97: '1',\n  98: '2',\n  99: '3',\n  100: '4',\n  101: '5',\n  102: '6',\n  103: '7',\n  104: '8',\n  105: '9',\n  106: '*',\n  107: '+',\n  109: '-', // The 'NumpadSubtract' code\n  110: '.',\n  111: '/',\n  112: 'F1',\n  113: 'F2',\n  114: 'F3',\n  115: 'F4',\n  116: 'F5',\n  117: 'F6',\n  118: 'F7',\n  119: 'F8',\n  120: 'F9',\n  121: 'F10',\n  122: 'F11',\n  123: 'F12',\n  144: 'NumLock',\n  145: 'ScrollLock',\n  173: '-', // The 'Minus' sign on Firefox. This is only needed when using the Selenium bot though.\n  182: 'MyComputer',\n  183: 'MyCalculator',\n  186: ';',\n  187: '=',\n  188: ',',\n  189: '-', // The 'Minus' sign on all other browsers\n  190: '.',\n  191: '/',\n  192: '`',\n  219: '[',\n  220: '\\\\',\n  221: ']',\n  222: '\\'',\n  224: 'Meta',\n  225: 'AltGraph'\n};\nObject.freeze(AutoNumericEnum.fromCharCodeKeyCode);\nObject.defineProperty(AutoNumericEnum, 'fromCharCodeKeyCode', { configurable: false, writable: false });\n\n/**\n * Wrapper variable that hold named keyboard keys with their respective key name (as set in KeyboardEvent.key).\n * Those names are listed here :\n * @link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values\n */\nAutoNumericEnum.keyName = {\n  // Special values\n  Unidentified: 'Unidentified',\n  AndroidDefault: 'AndroidDefault',\n\n  // Modifier keys\n  Alt: 'Alt',\n  AltGr: 'AltGraph',\n  CapsLock: 'CapsLock', // Under Chrome, e.key is empty for CapsLock\n  Ctrl: 'Control',\n  Fn: 'Fn',\n  FnLock: 'FnLock',\n  Hyper: 'Hyper', // 'OS' under Firefox\n  Meta: 'Meta',\n  OSLeft: 'OS',\n  OSRight: 'OS',\n  Command: 'OS',\n  NumLock: 'NumLock',\n  ScrollLock: 'ScrollLock',\n  Shift: 'Shift',\n  Super: 'Super', // 'OS' under Firefox\n  Symbol: 'Symbol',\n  SymbolLock: 'SymbolLock',\n\n  // Whitespace keys\n  Enter: 'Enter',\n  Tab: 'Tab',\n  Space: ' ', // 'Spacebar' for Firefox <37, and IE9\n\n  // Navigation keys\n  LeftArrow: 'ArrowLeft', // 'Left' for Firefox <=36, and IE9\n  UpArrow: 'ArrowUp', // 'Up' for Firefox <=36, and IE9\n  RightArrow: 'ArrowRight', // 'Right' for Firefox <=36, and IE9\n  DownArrow: 'ArrowDown', // 'Down' for Firefox <=36, and IE9\n  End: 'End',\n  Home: 'Home',\n  PageUp: 'PageUp',\n  PageDown: 'PageDown',\n\n  // Editing keys\n  Backspace: 'Backspace',\n  Clear: 'Clear',\n  Copy: 'Copy',\n  CrSel: 'CrSel', // 'Crsel' for Firefox <=36, and IE9\n  Cut: 'Cut',\n  Delete: 'Delete', // 'Del' for Firefox <=36, and IE9\n  EraseEof: 'EraseEof',\n  ExSel: 'ExSel', // 'Exsel' for Firefox <=36, and IE9\n  Insert: 'Insert',\n  Paste: 'Paste',\n  Redo: 'Redo',\n  Undo: 'Undo',\n\n  // UI keys\n  Accept: 'Accept',\n  Again: 'Again',\n  Attn: 'Attn', // 'Unidentified' for Firefox, Chrome, and IE9 ('KanaMode' when using the Japanese keyboard layout)\n  Cancel: 'Cancel',\n  ContextMenu: 'ContextMenu', // 'Apps' for Firefox <=36, and IE9\n  Esc: 'Escape', // 'Esc' for Firefox <=36, and IE9\n  Execute: 'Execute',\n  Find: 'Find',\n  Finish: 'Finish', // 'Unidentified' for Firefox, Chrome, and IE9 ('Katakana' when using the Japanese keyboard layout)\n  Help: 'Help',\n  Pause: 'Pause',\n  Play: 'Play',\n  Props: 'Props',\n  Select: 'Select',\n  ZoomIn: 'ZoomIn',\n  ZoomOut: 'ZoomOut',\n\n  // Device keys\n  BrightnessDown: 'BrightnessDown',\n  BrightnessUp: 'BrightnessUp',\n  Eject: 'Eject',\n  LogOff: 'LogOff',\n  Power: 'Power',\n  PowerOff: 'PowerOff',\n  PrintScreen: 'PrintScreen',\n  Hibernate: 'Hibernate', // 'Unidentified' for Firefox <=37\n  Standby: 'Standby', // 'Unidentified' for Firefox <=36, and IE9\n  WakeUp: 'WakeUp',\n\n  // IME and composition keys\n  Compose: 'Compose',\n  Dead: 'Dead',\n\n  // Function keys\n  F1: 'F1',\n  F2: 'F2',\n  F3: 'F3',\n  F4: 'F4',\n  F5: 'F5',\n  F6: 'F6',\n  F7: 'F7',\n  F8: 'F8',\n  F9: 'F9',\n  F10: 'F10',\n  F11: 'F11',\n  F12: 'F12',\n\n  // Document keys\n  Print: 'Print',\n\n  // 'Normal' keys\n  num0: '0',\n  num1: '1',\n  num2: '2',\n  num3: '3',\n  num4: '4',\n  num5: '5',\n  num6: '6',\n  num7: '7',\n  num8: '8',\n  num9: '9',\n  a: 'a',\n  b: 'b',\n  c: 'c',\n  d: 'd',\n  e: 'e',\n  f: 'f',\n  g: 'g',\n  h: 'h',\n  i: 'i',\n  j: 'j',\n  k: 'k',\n  l: 'l',\n  m: 'm',\n  n: 'n',\n  o: 'o',\n  p: 'p',\n  q: 'q',\n  r: 'r',\n  s: 's',\n  t: 't',\n  u: 'u',\n  v: 'v',\n  w: 'w',\n  x: 'x',\n  y: 'y',\n  z: 'z',\n  A: 'A',\n  B: 'B',\n  C: 'C',\n  D: 'D',\n  E: 'E',\n  F: 'F',\n  G: 'G',\n  H: 'H',\n  I: 'I',\n  J: 'J',\n  K: 'K',\n  L: 'L',\n  M: 'M',\n  N: 'N',\n  O: 'O',\n  P: 'P',\n  Q: 'Q',\n  R: 'R',\n  S: 'S',\n  T: 'T',\n  U: 'U',\n  V: 'V',\n  W: 'W',\n  X: 'X',\n  Y: 'Y',\n  Z: 'Z',\n  Semicolon: ';',\n  Equal: '=',\n  Comma: ',',\n  Hyphen: '-',\n  Minus: '-',\n  Plus: '+',\n  Dot: '.',\n  Slash: '/',\n  Backquote: '`',\n  LeftBracket: '[',\n  RightBracket: ']',\n  Backslash: '\\\\',\n  Quote: '\\'',\n\n  // Numeric keypad keys\n  numpad0: '0',\n  numpad1: '1',\n  numpad2: '2',\n  numpad3: '3',\n  numpad4: '4',\n  numpad5: '5',\n  numpad6: '6',\n  numpad7: '7',\n  numpad8: '8',\n  numpad9: '9',\n  NumpadDot: '.',\n  NumpadDotAlt: ',', // Modern browsers automatically adapt the character sent by this key to the decimal character of the current language\n  NumpadMultiply: '*',\n  NumpadPlus: '+',\n  NumpadMinus: '-',\n  NumpadSubtract: '-',\n  NumpadSlash: '/',\n  NumpadDotObsoleteBrowsers: 'Decimal',\n  NumpadMultiplyObsoleteBrowsers: 'Multiply',\n  NumpadPlusObsoleteBrowsers: 'Add',\n  NumpadMinusObsoleteBrowsers: 'Subtract',\n  NumpadSlashObsoleteBrowsers: 'Divide',\n\n  // Special arrays for quicker tests\n  _allFnKeys: ['F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12'],\n  _someNonPrintableKeys: ['Tab', 'Enter', 'Shift', 'ShiftLeft', 'ShiftRight', 'Control', 'ControlLeft', 'ControlRight', 'Alt', 'AltLeft', 'AltRight', 'Pause', 'CapsLock', 'Escape'],\n  _directionKeys: ['PageUp', 'PageDown', 'End', 'Home', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'ArrowUp']\n};\nObject.freeze(AutoNumericEnum.keyName._allFnKeys);\nObject.freeze(AutoNumericEnum.keyName._someNonPrintableKeys);\nObject.freeze(AutoNumericEnum.keyName._directionKeys);\nObject.freeze(AutoNumericEnum.keyName);\nObject.defineProperty(AutoNumericEnum, 'keyName', { configurable: false, writable: false });\n\nObject.freeze(AutoNumericEnum);\n\nexports.default = AutoNumericEnum;\nmodule.exports = exports['default'];\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvQXV0b051bWVyaWNFbnVtLmpzLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vQXV0b051bWVyaWMvc3JjL0F1dG9OdW1lcmljRW51bS5qcz8xNTA2Il0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRW51bWVyYXRpb25zIGZvciBhdXRvTnVtZXJpYy5qc1xuICogQGF1dGhvciBBbGV4YW5kcmUgQm9ubmVhdSA8YWxleGFuZHJlLmJvbm5lYXVAbGludXhmci5ldT5cbiAqIEBjb3B5cmlnaHQgwqkgMjAxNiBBbGV4YW5kcmUgQm9ubmVhdVxuICpcbiAqIFRoZSBNSVQgTGljZW5zZSAoaHR0cDovL3d3dy5vcGVuc291cmNlLm9yZy9saWNlbnNlcy9taXQtbGljZW5zZS5waHApXG4gKlxuICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb25cbiAqIG9idGFpbmluZyBhIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uXG4gKiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXRcbiAqIHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLFxuICogY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3ViIGxpY2Vuc2UsIGFuZC9vciBzZWxsXG4gKiBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGVcbiAqIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nXG4gKiBjb25kaXRpb25zOlxuICpcbiAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlXG4gKiBpbmNsdWRlZCBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbiAqXG4gKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELFxuICogRVhQUkVTUyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTXG4gKiBPRiBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORFxuICogTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFRcbiAqIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLFxuICogV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HXG4gKiBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SXG4gKiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG4gKi9cblxuLyoqXG4gKiBPYmplY3QgdGhhdCBzdG9yZSB0aGUgaGVscGVyIGVudW1lcmF0aW9uc1xuICogQHR5cGUge3sgYWxsb3dlZFRhZ0xpc3Q6IFtzdHJpbmddLCBrZXlDb2RlOiB7fSwgZnJvbUNoYXJDb2RlS2V5Q29kZTogW3N0cmluZ10sIGtleU5hbWU6IHt9IH19XG4gKi9cbmNvbnN0IEF1dG9OdW1lcmljRW51bSA9IHt9O1xuXG4vKipcbiAqIExpc3Qgb2YgYWxsb3dlZCB0YWcgb24gd2hpY2ggYXV0b051bWVyaWMgY2FuIGJlIHVzZWQuXG4gKi9cbkF1dG9OdW1lcmljRW51bS5hbGxvd2VkVGFnTGlzdCA9IFtcbiAgICAnYicsXG4gICAgJ2NhcHRpb24nLFxuICAgICdjaXRlJyxcbiAgICAnY29kZScsXG4gICAgJ2NvbnN0JyxcbiAgICAnZGQnLFxuICAgICdkZWwnLFxuICAgICdkaXYnLFxuICAgICdkZm4nLFxuICAgICdkdCcsXG4gICAgJ2VtJyxcbiAgICAnaDEnLFxuICAgICdoMicsXG4gICAgJ2gzJyxcbiAgICAnaDQnLFxuICAgICdoNScsXG4gICAgJ2g2JyxcbiAgICAnaW5wdXQnLFxuICAgICdpbnMnLFxuICAgICdrZGInLFxuICAgICdsYWJlbCcsXG4gICAgJ2xpJyxcbiAgICAnb3B0aW9uJyxcbiAgICAnb3V0cHV0JyxcbiAgICAncCcsXG4gICAgJ3EnLFxuICAgICdzJyxcbiAgICAnc2FtcGxlJyxcbiAgICAnc3BhbicsXG4gICAgJ3N0cm9uZycsXG4gICAgJ3RkJyxcbiAgICAndGgnLFxuICAgICd1Jyxcbl07XG5PYmplY3QuZnJlZXplKEF1dG9OdW1lcmljRW51bS5hbGxvd2VkVGFnTGlzdCk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoQXV0b051bWVyaWNFbnVtLCAnYWxsb3dlZFRhZ0xpc3QnLCB7IGNvbmZpZ3VyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiBmYWxzZSB9KTtcblxuLyoqXG4gKiBXcmFwcGVyIHZhcmlhYmxlIHRoYXQgaG9sZCBuYW1lZCBrZXlib2FyZCBrZXlzIHdpdGggdGhlaXIgcmVzcGVjdGl2ZSBrZXlDb2RlIGFzIHNlZW4gaW4gRE9NIGV2ZW50cy5cbiAqIGNmLiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvS2V5Ym9hcmRFdmVudC9rZXlDb2RlXG4gKlxuICogVGhpcyBkZXByZWNhdGVkIGluZm9ybWF0aW9uIGlzIHVzZWQgZm9yIG9ic29sZXRlIGJyb3dzZXJzLlxuICogQGRlcHJlY2F0ZWRcbiAqL1xuQXV0b051bWVyaWNFbnVtLmtleUNvZGUgPSB7XG4gICAgQmFja3NwYWNlICAgICA6IDgsXG4gICAgVGFiICAgICAgICAgICA6IDksXG4gICAgLy8gTm8gMTAsIDExXG4gICAgLy8gMTIgPT09IE51bXBhZEVxdWFsIG9uIFdpbmRvd3NcbiAgICAvLyAxMiA9PT0gTnVtTG9jayBvbiBNYWNcbiAgICBFbnRlciAgICAgICAgIDogMTMsXG4gICAgLy8gMTQgcmVzZXJ2ZWQsIGJ1dCBub3QgdXNlZFxuICAgIC8vIDE1IGRvZXMgbm90IGV4aXN0c1xuICAgIFNoaWZ0ICAgICAgICAgOiAxNixcbiAgICBDdHJsICAgICAgICAgIDogMTcsXG4gICAgQWx0ICAgICAgICAgICA6IDE4LFxuICAgIFBhdXNlICAgICAgICAgOiAxOSxcbiAgICBDYXBzTG9jayAgICAgIDogMjAsXG4gICAgLy8gMjEsIDIyLCAyMywgMjQsIDI1IDogQXNpYXRpYyBrZXkgY29kZXNcbiAgICAvLyAyNiBkb2VzIG5vdCBleGlzdHNcbiAgICBFc2MgICAgICAgICAgIDogMjcsXG4gICAgLy8gMjgsIDI5LCAzMCwgMzEgOiBDb252ZXJ0LCBOb25Db252ZXJ0LCBBY2NlcHQgYW5kIE1vZGVDaGFuZ2Uga2V5c1xuICAgIFNwYWNlICAgICAgICAgOiAzMixcbiAgICBQYWdlVXAgICAgICAgIDogMzMsXG4gICAgUGFnZURvd24gICAgICA6IDM0LFxuICAgIEVuZCAgICAgICAgICAgOiAzNSxcbiAgICBIb21lICAgICAgICAgIDogMzYsXG4gICAgTGVmdEFycm93ICAgICA6IDM3LFxuICAgIFVwQXJyb3cgICAgICAgOiAzOCxcbiAgICBSaWdodEFycm93ICAgIDogMzksXG4gICAgRG93bkFycm93ICAgICA6IDQwLFxuICAgIEluc2VydCAgICAgICAgOiA0NSxcbiAgICBEZWxldGUgICAgICAgIDogNDYsXG4gICAgbnVtMCAgICAgICAgICA6IDQ4LFxuICAgIG51bTEgICAgICAgICAgOiA0OSxcbiAgICBudW0yICAgICAgICAgIDogNTAsXG4gICAgbnVtMyAgICAgICAgICA6IDUxLFxuICAgIG51bTQgICAgICAgICAgOiA1MixcbiAgICBudW01ICAgICAgICAgIDogNTMsXG4gICAgbnVtNiAgICAgICAgICA6IDU0LFxuICAgIG51bTcgICAgICAgICAgOiA1NSxcbiAgICBudW04ICAgICAgICAgIDogNTYsXG4gICAgbnVtOSAgICAgICAgICA6IDU3LFxuICAgIGEgICAgICAgICAgICAgOiA2NSxcbiAgICBiICAgICAgICAgICAgIDogNjYsXG4gICAgYyAgICAgICAgICAgICA6IDY3LFxuICAgIGQgICAgICAgICAgICAgOiA2OCxcbiAgICBlICAgICAgICAgICAgIDogNjksXG4gICAgZiAgICAgICAgICAgICA6IDcwLFxuICAgIGcgICAgICAgICAgICAgOiA3MSxcbiAgICBoICAgICAgICAgICAgIDogNzIsXG4gICAgaSAgICAgICAgICAgICA6IDczLFxuICAgIGogICAgICAgICAgICAgOiA3NCxcbiAgICBrICAgICAgICAgICAgIDogNzUsXG4gICAgbCAgICAgICAgICAgICA6IDc2LFxuICAgIG0gICAgICAgICAgICAgOiA3NyxcbiAgICBuICAgICAgICAgICAgIDogNzgsXG4gICAgbyAgICAgICAgICAgICA6IDc5LFxuICAgIHAgICAgICAgICAgICAgOiA4MCxcbiAgICBxICAgICAgICAgICAgIDogODEsXG4gICAgciAgICAgICAgICAgICA6IDgyLFxuICAgIHMgICAgICAgICAgICAgOiA4MyxcbiAgICB0ICAgICAgICAgICAgIDogODQsXG4gICAgdSAgICAgICAgICAgICA6IDg1LFxuICAgIHYgICAgICAgICAgICAgOiA4NixcbiAgICB3ICAgICAgICAgICAgIDogODcsXG4gICAgeCAgICAgICAgICAgICA6IDg4LFxuICAgIHkgICAgICAgICAgICAgOiA4OSxcbiAgICB6ICAgICAgICAgICAgIDogOTAsXG4gICAgT1NMZWZ0ICAgICAgICA6IDkxLFxuICAgIE9TUmlnaHQgICAgICAgOiA5MixcbiAgICBDb250ZXh0TWVudSAgIDogOTMsXG4gICAgbnVtcGFkMCAgICAgICA6IDk2LFxuICAgIG51bXBhZDEgICAgICAgOiA5NyxcbiAgICBudW1wYWQyICAgICAgIDogOTgsXG4gICAgbnVtcGFkMyAgICAgICA6IDk5LFxuICAgIG51bXBhZDQgICAgICAgOiAxMDAsXG4gICAgbnVtcGFkNSAgICAgICA6IDEwMSxcbiAgICBudW1wYWQ2ICAgICAgIDogMTAyLFxuICAgIG51bXBhZDcgICAgICAgOiAxMDMsXG4gICAgbnVtcGFkOCAgICAgICA6IDEwNCxcbiAgICBudW1wYWQ5ICAgICAgIDogMTA1LFxuICAgIE11bHRpcGx5TnVtcGFkOiAxMDYsXG4gICAgUGx1c051bXBhZCAgICA6IDEwNyxcbiAgICBNaW51c051bXBhZCAgIDogMTA5LFxuICAgIERvdE51bXBhZCAgICAgOiAxMTAsXG4gICAgU2xhc2hOdW1wYWQgICA6IDExMSxcbiAgICBGMSAgICAgICAgICAgIDogMTEyLFxuICAgIEYyICAgICAgICAgICAgOiAxMTMsXG4gICAgRjMgICAgICAgICAgICA6IDExNCxcbiAgICBGNCAgICAgICAgICAgIDogMTE1LFxuICAgIEY1ICAgICAgICAgICAgOiAxMTYsXG4gICAgRjYgICAgICAgICAgICA6IDExNyxcbiAgICBGNyAgICAgICAgICAgIDogMTE4LFxuICAgIEY4ICAgICAgICAgICAgOiAxMTksXG4gICAgRjkgICAgICAgICAgICA6IDEyMCxcbiAgICBGMTAgICAgICAgICAgIDogMTIxLFxuICAgIEYxMSAgICAgICAgICAgOiAxMjIsXG4gICAgRjEyICAgICAgICAgICA6IDEyMyxcbiAgICBOdW1Mb2NrICAgICAgIDogMTQ0LFxuICAgIFNjcm9sbExvY2sgICAgOiAxNDUsXG4gICAgSHlwaGVuRmlyZWZveCA6IDE3MywgLy8gT24gdGhlIGxhdGVzdCBMaW51eCBhbmQgV2luZG93cyBPUywgY2YuIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9LZXlib2FyZEV2ZW50L2tleUNvZGUgYW5kIGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTc4NzUwNCBhbmQgaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzM1NDczMjU5LzI4MzQ4OThcbiAgICBNeUNvbXB1dGVyICAgIDogMTgyLFxuICAgIE15Q2FsY3VsYXRvciAgOiAxODMsXG4gICAgU2VtaWNvbG9uICAgICA6IDE4NixcbiAgICBFcXVhbCAgICAgICAgIDogMTg3LFxuICAgIENvbW1hICAgICAgICAgOiAxODgsXG4gICAgSHlwaGVuICAgICAgICA6IDE4OSxcbiAgICBEb3QgICAgICAgICAgIDogMTkwLFxuICAgIFNsYXNoICAgICAgICAgOiAxOTEsXG4gICAgQmFja3F1b3RlICAgICA6IDE5MixcbiAgICBMZWZ0QnJhY2tldCAgIDogMjE5LFxuICAgIEJhY2tzbGFzaCAgICAgOiAyMjAsXG4gICAgUmlnaHRCcmFja2V0ICA6IDIyMSxcbiAgICBRdW90ZSAgICAgICAgIDogMjIyLFxuICAgIENvbW1hbmQgICAgICAgOiAyMjQsXG4gICAgQWx0R3JhcGggICAgICA6IDIyNSxcbiAgICBBbmRyb2lkRGVmYXVsdDogMjI5LCAvLyBBbmRyb2lkIENocm9tZSByZXR1cm5zIHRoZSBzYW1lIGtleWNvZGUgbnVtYmVyIDIyOSBmb3IgYWxsIGtleXMgcHJlc3NlZFxufTtcbk9iamVjdC5mcmVlemUoQXV0b051bWVyaWNFbnVtLmtleUNvZGUpO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KEF1dG9OdW1lcmljRW51bSwgJ2tleUNvZGUnLCB7IGNvbmZpZ3VyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiBmYWxzZSB9KTtcblxuLyoqXG4gKiBUaGlzIG9iamVjdCBpcyB0aGUgcmV2ZXJzZSBvZiBga2V5Q29kZWAsIGFuZCBpcyB1c2VkIHRvIHRyYW5zbGF0ZSB0aGUga2V5IGNvZGUgdG8gbmFtZWQga2V5cyB3aGVuIG5vIHZhbGlkIGNoYXJhY3RlcnMgY2FuIGJlIG9idGFpbmVkIGJ5IGBTdHJpbmcuZnJvbUNoYXJDb2RlYC5cbiAqIFRoaXMgb2JqZWN0IGtleXMgY29ycmVzcG9uZCB0byB0aGUgYGV2ZW50LmtleUNvZGVgIG51bWJlciwgYW5kIHJldHVybnMgdGhlIGNvcnJlc3BvbmRpbmcga2V5IG5hbWUgKMOgIGxhIGV2ZW50LmtleSlcbiAqL1xuQXV0b051bWVyaWNFbnVtLmZyb21DaGFyQ29kZUtleUNvZGUgPSB7XG4gICAgMCAgOiAnTGF1bmNoQ2FsY3VsYXRvcicsXG4gICAgOCAgOiAnQmFja3NwYWNlJyxcbiAgICA5ICA6ICdUYWInLFxuICAgIDEzIDogJ0VudGVyJyxcbiAgICAxNiA6ICdTaGlmdCcsXG4gICAgMTcgOiAnQ3RybCcsXG4gICAgMTggOiAnQWx0JyxcbiAgICAxOSA6ICdQYXVzZScsXG4gICAgMjAgOiAnQ2Fwc0xvY2snLFxuICAgIDI3IDogJ0VzY2FwZScsXG4gICAgMzIgOiAnICcsXG4gICAgMzMgOiAnUGFnZVVwJyxcbiAgICAzNCA6ICdQYWdlRG93bicsXG4gICAgMzUgOiAnRW5kJyxcbiAgICAzNiA6ICdIb21lJyxcbiAgICAzNyA6ICdBcnJvd0xlZnQnLFxuICAgIDM4IDogJ0Fycm93VXAnLFxuICAgIDM5IDogJ0Fycm93UmlnaHQnLFxuICAgIDQwIDogJ0Fycm93RG93bicsXG4gICAgNDUgOiAnSW5zZXJ0JyxcbiAgICA0NiA6ICdEZWxldGUnLFxuICAgIDQ4IDogJzAnLFxuICAgIDQ5IDogJzEnLFxuICAgIDUwIDogJzInLFxuICAgIDUxIDogJzMnLFxuICAgIDUyIDogJzQnLFxuICAgIDUzIDogJzUnLFxuICAgIDU0IDogJzYnLFxuICAgIDU1IDogJzcnLFxuICAgIDU2IDogJzgnLFxuICAgIDU3IDogJzknLFxuICAgIC8vIDY1OiAnYScsXG4gICAgLy8gNjY6ICdiJyxcbiAgICAvLyA2NzogJ2MnLFxuICAgIC8vIDY4OiAnZCcsXG4gICAgLy8gNjk6ICdlJyxcbiAgICAvLyA3MDogJ2YnLFxuICAgIC8vIDcxOiAnZycsXG4gICAgLy8gNzI6ICdoJyxcbiAgICAvLyA3MzogJ2knLFxuICAgIC8vIDc0OiAnaicsXG4gICAgLy8gNzU6ICdrJyxcbiAgICAvLyA3NjogJ2wnLFxuICAgIC8vIDc3OiAnbScsXG4gICAgLy8gNzg6ICduJyxcbiAgICAvLyA3OTogJ28nLFxuICAgIC8vIDgwOiAncCcsXG4gICAgLy8gODE6ICdxJyxcbiAgICAvLyA4MjogJ3InLFxuICAgIC8vIDgzOiAncycsXG4gICAgLy8gODQ6ICd0JyxcbiAgICAvLyA4NTogJ3UnLFxuICAgIC8vIDg2OiAndicsXG4gICAgLy8gODc6ICd3JyxcbiAgICAvLyA4ODogJ3gnLFxuICAgIC8vIDg5OiAneScsXG4gICAgLy8gOTA6ICd6JyxcbiAgICA5MSA6ICdPUycsIC8vIE5vdGU6IEZpcmVmb3ggYW5kIENocm9tZSByZXBvcnRzICdPUycgaW5zdGVhZCBvZiAnT1NMZWZ0J1xuICAgIDkyIDogJ09TUmlnaHQnLFxuICAgIDkzIDogJ0NvbnRleHRNZW51JyxcbiAgICA5NiA6ICcwJyxcbiAgICA5NyA6ICcxJyxcbiAgICA5OCA6ICcyJyxcbiAgICA5OSA6ICczJyxcbiAgICAxMDA6ICc0JyxcbiAgICAxMDE6ICc1JyxcbiAgICAxMDI6ICc2JyxcbiAgICAxMDM6ICc3JyxcbiAgICAxMDQ6ICc4JyxcbiAgICAxMDU6ICc5JyxcbiAgICAxMDY6ICcqJyxcbiAgICAxMDc6ICcrJyxcbiAgICAxMDk6ICctJywgLy8gVGhlICdOdW1wYWRTdWJ0cmFjdCcgY29kZVxuICAgIDExMDogJy4nLFxuICAgIDExMTogJy8nLFxuICAgIDExMjogJ0YxJyxcbiAgICAxMTM6ICdGMicsXG4gICAgMTE0OiAnRjMnLFxuICAgIDExNTogJ0Y0JyxcbiAgICAxMTY6ICdGNScsXG4gICAgMTE3OiAnRjYnLFxuICAgIDExODogJ0Y3JyxcbiAgICAxMTk6ICdGOCcsXG4gICAgMTIwOiAnRjknLFxuICAgIDEyMTogJ0YxMCcsXG4gICAgMTIyOiAnRjExJyxcbiAgICAxMjM6ICdGMTInLFxuICAgIDE0NDogJ051bUxvY2snLFxuICAgIDE0NTogJ1Njcm9sbExvY2snLFxuICAgIDE3MzogJy0nLCAvLyBUaGUgJ01pbnVzJyBzaWduIG9uIEZpcmVmb3guIFRoaXMgaXMgb25seSBuZWVkZWQgd2hlbiB1c2luZyB0aGUgU2VsZW5pdW0gYm90IHRob3VnaC5cbiAgICAxODI6ICdNeUNvbXB1dGVyJyxcbiAgICAxODM6ICdNeUNhbGN1bGF0b3InLFxuICAgIDE4NjogJzsnLFxuICAgIDE4NzogJz0nLFxuICAgIDE4ODogJywnLFxuICAgIDE4OTogJy0nLCAvLyBUaGUgJ01pbnVzJyBzaWduIG9uIGFsbCBvdGhlciBicm93c2Vyc1xuICAgIDE5MDogJy4nLFxuICAgIDE5MTogJy8nLFxuICAgIDE5MjogJ2AnLFxuICAgIDIxOTogJ1snLFxuICAgIDIyMDogJ1xcXFwnLFxuICAgIDIyMTogJ10nLFxuICAgIDIyMjogJ1xcJycsXG4gICAgMjI0OiAnTWV0YScsXG4gICAgMjI1OiAnQWx0R3JhcGgnLFxufTtcbk9iamVjdC5mcmVlemUoQXV0b051bWVyaWNFbnVtLmZyb21DaGFyQ29kZUtleUNvZGUpO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KEF1dG9OdW1lcmljRW51bSwgJ2Zyb21DaGFyQ29kZUtleUNvZGUnLCB7IGNvbmZpZ3VyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiBmYWxzZSB9KTtcblxuLyoqXG4gKiBXcmFwcGVyIHZhcmlhYmxlIHRoYXQgaG9sZCBuYW1lZCBrZXlib2FyZCBrZXlzIHdpdGggdGhlaXIgcmVzcGVjdGl2ZSBrZXkgbmFtZSAoYXMgc2V0IGluIEtleWJvYXJkRXZlbnQua2V5KS5cbiAqIFRob3NlIG5hbWVzIGFyZSBsaXN0ZWQgaGVyZSA6XG4gKiBAbGluayBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvS2V5Ym9hcmRFdmVudC9rZXkvS2V5X1ZhbHVlc1xuICovXG5BdXRvTnVtZXJpY0VudW0ua2V5TmFtZSA9IHtcbiAgICAvLyBTcGVjaWFsIHZhbHVlc1xuICAgIFVuaWRlbnRpZmllZCAgOiAnVW5pZGVudGlmaWVkJyxcbiAgICBBbmRyb2lkRGVmYXVsdDogJ0FuZHJvaWREZWZhdWx0JyxcblxuICAgIC8vIE1vZGlmaWVyIGtleXNcbiAgICBBbHQgICAgICAgOiAnQWx0JyxcbiAgICBBbHRHciAgICAgOiAnQWx0R3JhcGgnLFxuICAgIENhcHNMb2NrICA6ICdDYXBzTG9jaycsIC8vIFVuZGVyIENocm9tZSwgZS5rZXkgaXMgZW1wdHkgZm9yIENhcHNMb2NrXG4gICAgQ3RybCAgICAgIDogJ0NvbnRyb2wnLFxuICAgIEZuICAgICAgICA6ICdGbicsXG4gICAgRm5Mb2NrICAgIDogJ0ZuTG9jaycsXG4gICAgSHlwZXIgICAgIDogJ0h5cGVyJywgLy8gJ09TJyB1bmRlciBGaXJlZm94XG4gICAgTWV0YSAgICAgIDogJ01ldGEnLFxuICAgIE9TTGVmdCAgICA6ICdPUycsXG4gICAgT1NSaWdodCAgIDogJ09TJyxcbiAgICBDb21tYW5kICAgOiAnT1MnLFxuICAgIE51bUxvY2sgICA6ICdOdW1Mb2NrJyxcbiAgICBTY3JvbGxMb2NrOiAnU2Nyb2xsTG9jaycsXG4gICAgU2hpZnQgICAgIDogJ1NoaWZ0JyxcbiAgICBTdXBlciAgICAgOiAnU3VwZXInLCAvLyAnT1MnIHVuZGVyIEZpcmVmb3hcbiAgICBTeW1ib2wgICAgOiAnU3ltYm9sJyxcbiAgICBTeW1ib2xMb2NrOiAnU3ltYm9sTG9jaycsXG5cbiAgICAvLyBXaGl0ZXNwYWNlIGtleXNcbiAgICBFbnRlcjogJ0VudGVyJyxcbiAgICBUYWIgIDogJ1RhYicsXG4gICAgU3BhY2U6ICcgJywgLy8gJ1NwYWNlYmFyJyBmb3IgRmlyZWZveCA8MzcsIGFuZCBJRTlcblxuICAgIC8vIE5hdmlnYXRpb24ga2V5c1xuICAgIExlZnRBcnJvdyA6ICdBcnJvd0xlZnQnLCAvLyAnTGVmdCcgZm9yIEZpcmVmb3ggPD0zNiwgYW5kIElFOVxuICAgIFVwQXJyb3cgICA6ICdBcnJvd1VwJywgLy8gJ1VwJyBmb3IgRmlyZWZveCA8PTM2LCBhbmQgSUU5XG4gICAgUmlnaHRBcnJvdzogJ0Fycm93UmlnaHQnLCAvLyAnUmlnaHQnIGZvciBGaXJlZm94IDw9MzYsIGFuZCBJRTlcbiAgICBEb3duQXJyb3cgOiAnQXJyb3dEb3duJywgLy8gJ0Rvd24nIGZvciBGaXJlZm94IDw9MzYsIGFuZCBJRTlcbiAgICBFbmQgICAgICAgOiAnRW5kJyxcbiAgICBIb21lICAgICAgOiAnSG9tZScsXG4gICAgUGFnZVVwICAgIDogJ1BhZ2VVcCcsXG4gICAgUGFnZURvd24gIDogJ1BhZ2VEb3duJyxcblxuICAgIC8vIEVkaXRpbmcga2V5c1xuICAgIEJhY2tzcGFjZTogJ0JhY2tzcGFjZScsXG4gICAgQ2xlYXIgICAgOiAnQ2xlYXInLFxuICAgIENvcHkgICAgIDogJ0NvcHknLFxuICAgIENyU2VsICAgIDogJ0NyU2VsJywgLy8gJ0Nyc2VsJyBmb3IgRmlyZWZveCA8PTM2LCBhbmQgSUU5XG4gICAgQ3V0ICAgICAgOiAnQ3V0JyxcbiAgICBEZWxldGUgICA6ICdEZWxldGUnLCAvLyAnRGVsJyBmb3IgRmlyZWZveCA8PTM2LCBhbmQgSUU5XG4gICAgRXJhc2VFb2YgOiAnRXJhc2VFb2YnLFxuICAgIEV4U2VsICAgIDogJ0V4U2VsJywgLy8gJ0V4c2VsJyBmb3IgRmlyZWZveCA8PTM2LCBhbmQgSUU5XG4gICAgSW5zZXJ0ICAgOiAnSW5zZXJ0JyxcbiAgICBQYXN0ZSAgICA6ICdQYXN0ZScsXG4gICAgUmVkbyAgICAgOiAnUmVkbycsXG4gICAgVW5kbyAgICAgOiAnVW5kbycsXG5cbiAgICAvLyBVSSBrZXlzXG4gICAgQWNjZXB0ICAgICA6ICdBY2NlcHQnLFxuICAgIEFnYWluICAgICAgOiAnQWdhaW4nLFxuICAgIEF0dG4gICAgICAgOiAnQXR0bicsIC8vICdVbmlkZW50aWZpZWQnIGZvciBGaXJlZm94LCBDaHJvbWUsIGFuZCBJRTkgKCdLYW5hTW9kZScgd2hlbiB1c2luZyB0aGUgSmFwYW5lc2Uga2V5Ym9hcmQgbGF5b3V0KVxuICAgIENhbmNlbCAgICAgOiAnQ2FuY2VsJyxcbiAgICBDb250ZXh0TWVudTogJ0NvbnRleHRNZW51JywgLy8gJ0FwcHMnIGZvciBGaXJlZm94IDw9MzYsIGFuZCBJRTlcbiAgICBFc2MgICAgICAgIDogJ0VzY2FwZScsIC8vICdFc2MnIGZvciBGaXJlZm94IDw9MzYsIGFuZCBJRTlcbiAgICBFeGVjdXRlICAgIDogJ0V4ZWN1dGUnLFxuICAgIEZpbmQgICAgICAgOiAnRmluZCcsXG4gICAgRmluaXNoICAgICA6ICdGaW5pc2gnLCAvLyAnVW5pZGVudGlmaWVkJyBmb3IgRmlyZWZveCwgQ2hyb21lLCBhbmQgSUU5ICgnS2F0YWthbmEnIHdoZW4gdXNpbmcgdGhlIEphcGFuZXNlIGtleWJvYXJkIGxheW91dClcbiAgICBIZWxwICAgICAgIDogJ0hlbHAnLFxuICAgIFBhdXNlICAgICAgOiAnUGF1c2UnLFxuICAgIFBsYXkgICAgICAgOiAnUGxheScsXG4gICAgUHJvcHMgICAgICA6ICdQcm9wcycsXG4gICAgU2VsZWN0ICAgICA6ICdTZWxlY3QnLFxuICAgIFpvb21JbiAgICAgOiAnWm9vbUluJyxcbiAgICBab29tT3V0ICAgIDogJ1pvb21PdXQnLFxuXG4gICAgLy8gRGV2aWNlIGtleXNcbiAgICBCcmlnaHRuZXNzRG93bjogJ0JyaWdodG5lc3NEb3duJyxcbiAgICBCcmlnaHRuZXNzVXAgIDogJ0JyaWdodG5lc3NVcCcsXG4gICAgRWplY3QgICAgICAgICA6ICdFamVjdCcsXG4gICAgTG9nT2ZmICAgICAgICA6ICdMb2dPZmYnLFxuICAgIFBvd2VyICAgICAgICAgOiAnUG93ZXInLFxuICAgIFBvd2VyT2ZmICAgICAgOiAnUG93ZXJPZmYnLFxuICAgIFByaW50U2NyZWVuICAgOiAnUHJpbnRTY3JlZW4nLFxuICAgIEhpYmVybmF0ZSAgICAgOiAnSGliZXJuYXRlJywgLy8gJ1VuaWRlbnRpZmllZCcgZm9yIEZpcmVmb3ggPD0zN1xuICAgIFN0YW5kYnkgICAgICAgOiAnU3RhbmRieScsIC8vICdVbmlkZW50aWZpZWQnIGZvciBGaXJlZm94IDw9MzYsIGFuZCBJRTlcbiAgICBXYWtlVXAgICAgICAgIDogJ1dha2VVcCcsXG5cbiAgICAvLyBJTUUgYW5kIGNvbXBvc2l0aW9uIGtleXNcbiAgICBDb21wb3NlOiAnQ29tcG9zZScsXG4gICAgRGVhZCAgIDogJ0RlYWQnLFxuXG4gICAgLy8gRnVuY3Rpb24ga2V5c1xuICAgIEYxIDogJ0YxJyxcbiAgICBGMiA6ICdGMicsXG4gICAgRjMgOiAnRjMnLFxuICAgIEY0IDogJ0Y0JyxcbiAgICBGNSA6ICdGNScsXG4gICAgRjYgOiAnRjYnLFxuICAgIEY3IDogJ0Y3JyxcbiAgICBGOCA6ICdGOCcsXG4gICAgRjkgOiAnRjknLFxuICAgIEYxMDogJ0YxMCcsXG4gICAgRjExOiAnRjExJyxcbiAgICBGMTI6ICdGMTInLFxuXG4gICAgLy8gRG9jdW1lbnQga2V5c1xuICAgIFByaW50OiAnUHJpbnQnLFxuXG4gICAgLy8gJ05vcm1hbCcga2V5c1xuICAgIG51bTAgICAgICAgICA6ICcwJyxcbiAgICBudW0xICAgICAgICAgOiAnMScsXG4gICAgbnVtMiAgICAgICAgIDogJzInLFxuICAgIG51bTMgICAgICAgICA6ICczJyxcbiAgICBudW00ICAgICAgICAgOiAnNCcsXG4gICAgbnVtNSAgICAgICAgIDogJzUnLFxuICAgIG51bTYgICAgICAgICA6ICc2JyxcbiAgICBudW03ICAgICAgICAgOiAnNycsXG4gICAgbnVtOCAgICAgICAgIDogJzgnLFxuICAgIG51bTkgICAgICAgICA6ICc5JyxcbiAgICBhICAgICAgICAgICAgOiAnYScsXG4gICAgYiAgICAgICAgICAgIDogJ2InLFxuICAgIGMgICAgICAgICAgICA6ICdjJyxcbiAgICBkICAgICAgICAgICAgOiAnZCcsXG4gICAgZSAgICAgICAgICAgIDogJ2UnLFxuICAgIGYgICAgICAgICAgICA6ICdmJyxcbiAgICBnICAgICAgICAgICAgOiAnZycsXG4gICAgaCAgICAgICAgICAgIDogJ2gnLFxuICAgIGkgICAgICAgICAgICA6ICdpJyxcbiAgICBqICAgICAgICAgICAgOiAnaicsXG4gICAgayAgICAgICAgICAgIDogJ2snLFxuICAgIGwgICAgICAgICAgICA6ICdsJyxcbiAgICBtICAgICAgICAgICAgOiAnbScsXG4gICAgbiAgICAgICAgICAgIDogJ24nLFxuICAgIG8gICAgICAgICAgICA6ICdvJyxcbiAgICBwICAgICAgICAgICAgOiAncCcsXG4gICAgcSAgICAgICAgICAgIDogJ3EnLFxuICAgIHIgICAgICAgICAgICA6ICdyJyxcbiAgICBzICAgICAgICAgICAgOiAncycsXG4gICAgdCAgICAgICAgICAgIDogJ3QnLFxuICAgIHUgICAgICAgICAgICA6ICd1JyxcbiAgICB2ICAgICAgICAgICAgOiAndicsXG4gICAgdyAgICAgICAgICAgIDogJ3cnLFxuICAgIHggICAgICAgICAgICA6ICd4JyxcbiAgICB5ICAgICAgICAgICAgOiAneScsXG4gICAgeiAgICAgICAgICAgIDogJ3onLFxuICAgIEEgICAgICAgICAgICA6ICdBJyxcbiAgICBCICAgICAgICAgICAgOiAnQicsXG4gICAgQyAgICAgICAgICAgIDogJ0MnLFxuICAgIEQgICAgICAgICAgICA6ICdEJyxcbiAgICBFICAgICAgICAgICAgOiAnRScsXG4gICAgRiAgICAgICAgICAgIDogJ0YnLFxuICAgIEcgICAgICAgICAgICA6ICdHJyxcbiAgICBIICAgICAgICAgICAgOiAnSCcsXG4gICAgSSAgICAgICAgICAgIDogJ0knLFxuICAgIEogICAgICAgICAgICA6ICdKJyxcbiAgICBLICAgICAgICAgICAgOiAnSycsXG4gICAgTCAgICAgICAgICAgIDogJ0wnLFxuICAgIE0gICAgICAgICAgICA6ICdNJyxcbiAgICBOICAgICAgICAgICAgOiAnTicsXG4gICAgTyAgICAgICAgICAgIDogJ08nLFxuICAgIFAgICAgICAgICAgICA6ICdQJyxcbiAgICBRICAgICAgICAgICAgOiAnUScsXG4gICAgUiAgICAgICAgICAgIDogJ1InLFxuICAgIFMgICAgICAgICAgICA6ICdTJyxcbiAgICBUICAgICAgICAgICAgOiAnVCcsXG4gICAgVSAgICAgICAgICAgIDogJ1UnLFxuICAgIFYgICAgICAgICAgICA6ICdWJyxcbiAgICBXICAgICAgICAgICAgOiAnVycsXG4gICAgWCAgICAgICAgICAgIDogJ1gnLFxuICAgIFkgICAgICAgICAgICA6ICdZJyxcbiAgICBaICAgICAgICAgICAgOiAnWicsXG4gICAgU2VtaWNvbG9uICAgIDogJzsnLFxuICAgIEVxdWFsICAgICAgICA6ICc9JyxcbiAgICBDb21tYSAgICAgICAgOiAnLCcsXG4gICAgSHlwaGVuICAgICAgIDogJy0nLFxuICAgIE1pbnVzICAgICAgICA6ICctJyxcbiAgICBQbHVzICAgICAgICAgOiAnKycsXG4gICAgRG90ICAgICAgICAgIDogJy4nLFxuICAgIFNsYXNoICAgICAgICA6ICcvJyxcbiAgICBCYWNrcXVvdGUgICAgOiAnYCcsXG4gICAgTGVmdEJyYWNrZXQgIDogJ1snLFxuICAgIFJpZ2h0QnJhY2tldCA6ICddJyxcbiAgICBCYWNrc2xhc2ggICAgOiAnXFxcXCcsXG4gICAgUXVvdGUgICAgICAgIDogJ1xcJycsXG5cbiAgICAvLyBOdW1lcmljIGtleXBhZCBrZXlzXG4gICAgbnVtcGFkMCAgICAgICAgICAgICAgICAgICAgICAgOiAnMCcsXG4gICAgbnVtcGFkMSAgICAgICAgICAgICAgICAgICAgICAgOiAnMScsXG4gICAgbnVtcGFkMiAgICAgICAgICAgICAgICAgICAgICAgOiAnMicsXG4gICAgbnVtcGFkMyAgICAgICAgICAgICAgICAgICAgICAgOiAnMycsXG4gICAgbnVtcGFkNCAgICAgICAgICAgICAgICAgICAgICAgOiAnNCcsXG4gICAgbnVtcGFkNSAgICAgICAgICAgICAgICAgICAgICAgOiAnNScsXG4gICAgbnVtcGFkNiAgICAgICAgICAgICAgICAgICAgICAgOiAnNicsXG4gICAgbnVtcGFkNyAgICAgICAgICAgICAgICAgICAgICAgOiAnNycsXG4gICAgbnVtcGFkOCAgICAgICAgICAgICAgICAgICAgICAgOiAnOCcsXG4gICAgbnVtcGFkOSAgICAgICAgICAgICAgICAgICAgICAgOiAnOScsXG4gICAgTnVtcGFkRG90ICAgICAgICAgICAgICAgICAgICAgOiAnLicsXG4gICAgTnVtcGFkRG90QWx0ICAgICAgICAgICAgICAgICAgOiAnLCcsIC8vIE1vZGVybiBicm93c2VycyBhdXRvbWF0aWNhbGx5IGFkYXB0IHRoZSBjaGFyYWN0ZXIgc2VudCBieSB0aGlzIGtleSB0byB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgb2YgdGhlIGN1cnJlbnQgbGFuZ3VhZ2VcbiAgICBOdW1wYWRNdWx0aXBseSAgICAgICAgICAgICAgICA6ICcqJyxcbiAgICBOdW1wYWRQbHVzICAgICAgICAgICAgICAgICAgICA6ICcrJyxcbiAgICBOdW1wYWRNaW51cyAgICAgICAgICAgICAgICAgICA6ICctJyxcbiAgICBOdW1wYWRTdWJ0cmFjdCAgICAgICAgICAgICAgICA6ICctJyxcbiAgICBOdW1wYWRTbGFzaCAgICAgICAgICAgICAgICAgICA6ICcvJyxcbiAgICBOdW1wYWREb3RPYnNvbGV0ZUJyb3dzZXJzICAgICA6ICdEZWNpbWFsJyxcbiAgICBOdW1wYWRNdWx0aXBseU9ic29sZXRlQnJvd3NlcnM6ICdNdWx0aXBseScsXG4gICAgTnVtcGFkUGx1c09ic29sZXRlQnJvd3NlcnMgICAgOiAnQWRkJyxcbiAgICBOdW1wYWRNaW51c09ic29sZXRlQnJvd3NlcnMgICA6ICdTdWJ0cmFjdCcsXG4gICAgTnVtcGFkU2xhc2hPYnNvbGV0ZUJyb3dzZXJzICAgOiAnRGl2aWRlJyxcblxuICAgIC8vIFNwZWNpYWwgYXJyYXlzIGZvciBxdWlja2VyIHRlc3RzXG4gICAgX2FsbEZuS2V5cyAgICAgICAgICAgOiBbJ0YxJywgJ0YyJywgJ0YzJywgJ0Y0JywgJ0Y1JywgJ0Y2JywgJ0Y3JywgJ0Y4JywgJ0Y5JywgJ0YxMCcsICdGMTEnLCAnRjEyJ10sXG4gICAgX3NvbWVOb25QcmludGFibGVLZXlzOiBbJ1RhYicsICdFbnRlcicsICdTaGlmdCcsICdTaGlmdExlZnQnLCAnU2hpZnRSaWdodCcsICdDb250cm9sJywgJ0NvbnRyb2xMZWZ0JywgJ0NvbnRyb2xSaWdodCcsICdBbHQnLCAnQWx0TGVmdCcsICdBbHRSaWdodCcsICdQYXVzZScsICdDYXBzTG9jaycsICdFc2NhcGUnXSxcbiAgICBfZGlyZWN0aW9uS2V5cyAgICAgICA6IFsnUGFnZVVwJywgJ1BhZ2VEb3duJywgJ0VuZCcsICdIb21lJywgJ0Fycm93RG93bicsICdBcnJvd0xlZnQnLCAnQXJyb3dSaWdodCcsICdBcnJvd1VwJ10sXG59O1xuT2JqZWN0LmZyZWV6ZShBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5fYWxsRm5LZXlzKTtcbk9iamVjdC5mcmVlemUoQXV0b051bWVyaWNFbnVtLmtleU5hbWUuX3NvbWVOb25QcmludGFibGVLZXlzKTtcbk9iamVjdC5mcmVlemUoQXV0b051bWVyaWNFbnVtLmtleU5hbWUuX2RpcmVjdGlvbktleXMpO1xuT2JqZWN0LmZyZWV6ZShBdXRvTnVtZXJpY0VudW0ua2V5TmFtZSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoQXV0b051bWVyaWNFbnVtLCAna2V5TmFtZScsIHsgY29uZmlndXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IGZhbHNlIH0pO1xuXG5PYmplY3QuZnJlZXplKEF1dG9OdW1lcmljRW51bSk7XG5cbmV4cG9ydCBkZWZhdWx0IEF1dG9OdW1lcmljRW51bTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUE2QkE7Ozs7QUFJQTtBQUNBO0FBQ0E7OztBQUdBO0FBbUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBakhBO0FBbUhBO0FBQ0E7QUFDQTtBQUNBOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUF6R0E7QUEyR0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQWhOQTtBQWtOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./src/AutoNumericEnum.js\n");

/***/ }),

/***/ "./src/AutoNumericEvents.js":
/*!**********************************!*\
  !*** ./src/AutoNumericEvents.js ***!
  \**********************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

"use strict";
eval("\n\nvar _AutoNumeric = __webpack_require__(/*! ./AutoNumeric */ \"./src/AutoNumeric.js\");\n\nvar _AutoNumeric2 = _interopRequireDefault(_AutoNumeric);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * Event list managed by AutoNumeric\n *\n * @type {{initialized: string, formatted: string, minRangeExceeded: string, maxRangeExceeded: string, native: {input: string, change: string}}}\n */\n_AutoNumeric2.default.events = {\n  initialized: 'autoNumeric:initialized',\n  formatted: 'autoNumeric:formatted',\n  rawValueModified: 'autoNumeric:rawValueModified',\n  minRangeExceeded: 'autoNumeric:minExceeded',\n  maxRangeExceeded: 'autoNumeric:maxExceeded',\n  native: {\n    input: 'input',\n    change: 'change'\n  }\n}; /**\n    * Options for autoNumeric.js\n    * @author Alexandre Bonneau <alexandre.bonneau@linuxfr.eu>\n    * @copyright © 2017 Alexandre Bonneau\n    *\n    * The MIT License (http://www.opensource.org/licenses/mit-license.php)\n    *\n    * Permission is hereby granted, free of charge, to any person\n    * obtaining a copy of this software and associated documentation\n    * files (the \"Software\"), to deal in the Software without\n    * restriction, including without limitation the rights to use,\n    * copy, modify, merge, publish, distribute, sub license, and/or sell\n    * copies of the Software, and to permit persons to whom the\n    * Software is furnished to do so, subject to the following\n    * conditions:\n    *\n    * The above copyright notice and this permission notice shall be\n    * included in all copies or substantial portions of the Software.\n    *\n    * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n    * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n    * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n    * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n    * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n    * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n    * OTHER DEALINGS IN THE SOFTWARE.\n    */\n\nObject.freeze(_AutoNumeric2.default.events.native);\nObject.freeze(_AutoNumeric2.default.events);\nObject.defineProperty(_AutoNumeric2.default, 'events', { configurable: false, writable: false });\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvQXV0b051bWVyaWNFdmVudHMuanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9BdXRvTnVtZXJpYy9zcmMvQXV0b051bWVyaWNFdmVudHMuanM/MmViNSJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIE9wdGlvbnMgZm9yIGF1dG9OdW1lcmljLmpzXG4gKiBAYXV0aG9yIEFsZXhhbmRyZSBCb25uZWF1IDxhbGV4YW5kcmUuYm9ubmVhdUBsaW51eGZyLmV1PlxuICogQGNvcHlyaWdodCDCqSAyMDE3IEFsZXhhbmRyZSBCb25uZWF1XG4gKlxuICogVGhlIE1JVCBMaWNlbnNlIChodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL21pdC1saWNlbnNlLnBocClcbiAqXG4gKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvblxuICogb2J0YWluaW5nIGEgY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb25cbiAqIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dFxuICogcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsXG4gKiBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWIgbGljZW5zZSwgYW5kL29yIHNlbGxcbiAqIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZVxuICogU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmdcbiAqIGNvbmRpdGlvbnM6XG4gKlxuICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmVcbiAqIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICpcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsXG4gKiBFWFBSRVNTIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVNcbiAqIE9GIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EXG4gKiBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVFxuICogSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksXG4gKiBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkdcbiAqIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1JcbiAqIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cbiAqL1xuXG5pbXBvcnQgQXV0b051bWVyaWMgZnJvbSAnLi9BdXRvTnVtZXJpYyc7XG5cbi8qKlxuICogRXZlbnQgbGlzdCBtYW5hZ2VkIGJ5IEF1dG9OdW1lcmljXG4gKlxuICogQHR5cGUge3tpbml0aWFsaXplZDogc3RyaW5nLCBmb3JtYXR0ZWQ6IHN0cmluZywgbWluUmFuZ2VFeGNlZWRlZDogc3RyaW5nLCBtYXhSYW5nZUV4Y2VlZGVkOiBzdHJpbmcsIG5hdGl2ZToge2lucHV0OiBzdHJpbmcsIGNoYW5nZTogc3RyaW5nfX19XG4gKi9cbkF1dG9OdW1lcmljLmV2ZW50cyA9IHtcbiAgICBpbml0aWFsaXplZCAgICAgOiAnYXV0b051bWVyaWM6aW5pdGlhbGl6ZWQnLFxuICAgIGZvcm1hdHRlZCAgICAgICA6ICdhdXRvTnVtZXJpYzpmb3JtYXR0ZWQnLFxuICAgIHJhd1ZhbHVlTW9kaWZpZWQ6ICdhdXRvTnVtZXJpYzpyYXdWYWx1ZU1vZGlmaWVkJyxcbiAgICBtaW5SYW5nZUV4Y2VlZGVkOiAnYXV0b051bWVyaWM6bWluRXhjZWVkZWQnLFxuICAgIG1heFJhbmdlRXhjZWVkZWQ6ICdhdXRvTnVtZXJpYzptYXhFeGNlZWRlZCcsXG4gICAgbmF0aXZlICAgICAgICAgIDoge1xuICAgICAgICBpbnB1dCA6ICdpbnB1dCcsXG4gICAgICAgIGNoYW5nZTogJ2NoYW5nZScsXG4gICAgfSxcbn07XG5cbk9iamVjdC5mcmVlemUoQXV0b051bWVyaWMuZXZlbnRzLm5hdGl2ZSk7XG5PYmplY3QuZnJlZXplKEF1dG9OdW1lcmljLmV2ZW50cyk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoQXV0b051bWVyaWMsICdldmVudHMnLCB7IGNvbmZpZ3VyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiBmYWxzZSB9KTtcbiJdLCJtYXBwaW5ncyI6Ijs7QUE2QkE7QUFDQTs7Ozs7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFGQTtBQU5BOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQVlBO0FBQ0E7QUFDQSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./src/AutoNumericEvents.js\n");

/***/ }),

/***/ "./src/AutoNumericHelper.js":
/*!**********************************!*\
  !*** ./src/AutoNumericHelper.js ***!
  \**********************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

"use strict";
eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n    value: true\n});\n\nvar _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };\n\nvar _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\"); } }; }();\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * Helper functions for autoNumeric.js\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @author Alexandre Bonneau <alexandre.bonneau@linuxfr.eu>\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @copyright © 2016 Alexandre Bonneau\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * The MIT License (http://www.opensource.org/licenses/mit-license.php)\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * Permission is hereby granted, free of charge, to any person\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * obtaining a copy of this software and associated documentation\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * files (the \"Software\"), to deal in the Software without\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * restriction, including without limitation the rights to use,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * copy, modify, merge, publish, distribute, sub license, and/or sell\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * copies of the Software, and to permit persons to whom the\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * Software is furnished to do so, subject to the following\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * conditions:\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * The above copyright notice and this permission notice shall be\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * included in all copies or substantial portions of the Software.\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * OTHER DEALINGS IN THE SOFTWARE.\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      */\n\nvar _AutoNumericEnum = __webpack_require__(/*! ./AutoNumericEnum */ \"./src/AutoNumericEnum.js\");\n\nvar _AutoNumericEnum2 = _interopRequireDefault(_AutoNumericEnum);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _toConsumableArray(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); } }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n/**\n * Static class that holds all the helper functions autoNumeric uses.\n * Note : none of the functions in there are aware of any autoNumeric internals (which means there are no references to autoNumeric-specific info like options names or data structures).\n */\nvar AutoNumericHelper = function () {\n    function AutoNumericHelper() {\n        _classCallCheck(this, AutoNumericHelper);\n    }\n\n    _createClass(AutoNumericHelper, null, [{\n        key: 'isNull',\n\n        /**\n         * Return `true` if the `value` is null\n         *\n         * @static\n         * @param {*} value The value to test\n         * @returns {boolean} Return `true` if the `value` is null, FALSE otherwise\n         */\n        value: function isNull(value) {\n            return value === null;\n        }\n\n        /**\n         * Return `true` if the `value` is undefined\n         *\n         * @static\n         * @param {*} value The value to test\n         * @returns {boolean} Return `true` if the `value` is undefined, FALSE otherwise\n         */\n\n    }, {\n        key: 'isUndefined',\n        value: function isUndefined(value) {\n            return value === void 0;\n        }\n\n        /**\n         * Return `true` if the `value` is undefined, null or empty\n         *\n         * @param {*} value\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isUndefinedOrNullOrEmpty',\n        value: function isUndefinedOrNullOrEmpty(value) {\n            return value === null || value === void 0 || '' === value;\n        }\n\n        /**\n         * Return `true` if the given parameter is a String\n         *\n         * @param {*} str\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isString',\n        value: function isString(str) {\n            return typeof str === 'string' || str instanceof String;\n        }\n        /**\n         * Return `true` if the `value` is an empty string ''\n         *\n         * @static\n         * @param {*} value The value to test\n         * @returns {boolean} Return `true` if the `value` is an empty string '', FALSE otherwise\n         */\n\n    }, {\n        key: 'isEmptyString',\n        value: function isEmptyString(value) {\n            return value === '';\n        }\n\n        /**\n         * Return `true` if the parameter is a boolean\n         *\n         * @static\n         * @param {*} value\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isBoolean',\n        value: function isBoolean(value) {\n            return typeof value === 'boolean';\n        }\n\n        /**\n         * Return `true` if the parameter is a string 'true' or 'false'\n         *\n         * This function accepts any cases for those strings.\n         * @param {string} value\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isTrueOrFalseString',\n        value: function isTrueOrFalseString(value) {\n            var lowercaseValue = String(value).toLowerCase();\n            return lowercaseValue === 'true' || lowercaseValue === 'false';\n        }\n\n        /**\n         * Return `true` if the parameter is an object\n         *\n         * @param {*} reference\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isObject',\n        value: function isObject(reference) {\n            return (typeof reference === 'undefined' ? 'undefined' : _typeof(reference)) === 'object' && reference !== null && !Array.isArray(reference);\n        }\n\n        /**\n         * Return `true` if the given object is empty\n         * cf. http://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object and http://jsperf.com/empty-object-test\n         *\n         * @param {object} obj\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isEmptyObj',\n        value: function isEmptyObj(obj) {\n            for (var prop in obj) {\n                if (obj.hasOwnProperty(prop)) {\n                    return false;\n                }\n            }\n            return true;\n        }\n\n        /**\n         * Return `true` if the parameter is a real number (and not a numeric string).\n         *\n         * @param {*} n\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isNumberStrict',\n        value: function isNumberStrict(n) {\n            return typeof n === 'number';\n        }\n\n        /**\n         * Return `true` if the parameter is a number (or a number written as a string).\n         *\n         * @param {*} n\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isNumber',\n        value: function isNumber(n) {\n            return !this.isArray(n) && !isNaN(parseFloat(n)) && isFinite(n);\n        }\n\n        /**\n         * Return `true` if the parameter is a number (or a number written as a string).\n         * This version also accepts Arabic and Persian numbers.\n         *\n         * @param {*} n\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isNumberOrArabic',\n        value: function isNumberOrArabic(n) {\n            var latinConvertedNumber = this.arabicToLatinNumbers(n, false, true, true);\n            return this.isNumber(latinConvertedNumber);\n        }\n\n        /**\n         * Return `true` if the parameter is an integer (and not a float).\n         *\n         * @param {*} n\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isInt',\n        value: function isInt(n) {\n            return typeof n === 'number' && parseFloat(n) === parseInt(n, 10) && !isNaN(n);\n        }\n\n        /**\n         * Return `true` if the parameter is a function.\n         *\n         * @param {function} func\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isFunction',\n        value: function isFunction(func) {\n            return typeof func === 'function';\n        }\n\n        /**\n         * Return `true` if the current browser is the obsolete Internet Explorer 11 (IE11) one\n         * cf. https://stackoverflow.com/a/21825207/2834898\n         *\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isIE11',\n        value: function isIE11() {\n            // noinspection JSUnresolvedVariable\n            return !!window.MSInputMethodContext && !!document.documentMode;\n        }\n\n        /**\n         * Return `true` is the string `str` contains the string `needle`\n         * Note: this function does not coerce the parameters types\n         *\n         * @param {string} str\n         * @param {string} needle\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'contains',\n        value: function contains(str, needle) {\n            //TODO Use `Array.prototype.includes()` when available (cf. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes)\n            if (!this.isString(str) || !this.isString(needle) || str === '' || needle === '') {\n                return false;\n            }\n\n            return str.indexOf(needle) !== -1;\n        }\n\n        /**\n         * Return `true` if the `needle` is in the array\n         *\n         * @param {*} needle\n         * @param {Array} array\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isInArray',\n        value: function isInArray(needle, array) {\n            if (!this.isArray(array) || array === [] || this.isUndefined(needle)) {\n                return false;\n            }\n\n            return array.indexOf(needle) !== -1;\n        }\n\n        /**\n         * Return `true` if the parameter is an Array\n         * //TODO Replace this by the default `Array.isArray()` function?\n         *\n         * @param {*} arr\n         * @throws Error\n         * @returns {*|boolean}\n         */\n\n    }, {\n        key: 'isArray',\n        value: function isArray(arr) {\n            if (Object.prototype.toString.call([]) === '[object Array]') {\n                // Make sure an array has a class attribute of [object Array]\n                // Test passed, now check if is an Array\n                return Array.isArray(arr) || (typeof arr === 'undefined' ? 'undefined' : _typeof(arr)) === 'object' && Object.prototype.toString.call(arr) === '[object Array]';\n            } else {\n                throw new Error('toString message changed for Object Array'); // Verify that the string returned by `toString` does not change in the future (cf. http://stackoverflow.com/a/8365215)\n            }\n        }\n\n        /**\n         * Return `true` if the parameter is a DOM element\n         * cf. http://stackoverflow.com/a/4754104/2834898\n         *\n         * @param {*} obj\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isElement',\n        value: function isElement(obj) {\n            // return !!(obj && obj.nodeName);\n            // return obj && 'nodeType' in obj;\n            // return obj instanceof Element || obj instanceof HTMLInputElement || obj instanceof HTMLElement;\n            if (typeof Element === 'undefined') {\n                // This test is needed in environnements where the Element object does not exist (ie. in web workers)\n                return false;\n            }\n\n            return obj instanceof Element;\n        }\n\n        /**\n         * Return `true` in the given DOM element is an <input>.\n         *\n         * @param {HTMLElement|HTMLInputElement} domElement\n         * @returns {boolean}\n         * @private\n         */\n\n    }, {\n        key: 'isInputElement',\n        value: function isInputElement(domElement) {\n            return this.isElement(domElement) && domElement.tagName.toLowerCase() === 'input';\n        }\n\n        /**\n         * Return `true` if the parameter is a string that represents a float number, and that number has a decimal part\n         *\n         * @param {string} str\n         * @returns {boolean}\n         */\n        // static hasDecimals(str) {\n        //     const [, decimalPart] = str.split('.');\n        //     return !isUndefined(decimalPart);\n        // }\n\n        /**\n         * Return the number of decimal places if the parameter is a string that represents a float number, and that number has a decimal part.\n         *\n         * @param {string} str\n         * @returns {int}\n         */\n\n    }, {\n        key: 'decimalPlaces',\n        value: function decimalPlaces(str) {\n            var _str$split = str.split('.'),\n                _str$split2 = _slicedToArray(_str$split, 2),\n                decimalPart = _str$split2[1];\n\n            if (!this.isUndefined(decimalPart)) {\n                return decimalPart.length;\n            }\n\n            return 0;\n        }\n\n        /**\n         * Return the index of the first non-zero decimal place in the given value.\n         * The index starts after the decimal point, if any, and begins at '1'.\n         * If no decimal places are found in the value, this function returns `0`.\n         *\n         * @example\n         * indexFirstNonZeroDecimalPlace('0.00') -> 0\n         * indexFirstNonZeroDecimalPlace('1.00') -> 0\n         * indexFirstNonZeroDecimalPlace('0.12') -> 1\n         * indexFirstNonZeroDecimalPlace('0.1234') -> 1\n         * indexFirstNonZeroDecimalPlace('0.01234') -> 2\n         * indexFirstNonZeroDecimalPlace('0.001234') -> 3\n         * indexFirstNonZeroDecimalPlace('0.0001234') -> 4\n         *\n         * @param {number} value\n         * @returns {Number|number}\n         */\n\n    }, {\n        key: 'indexFirstNonZeroDecimalPlace',\n        value: function indexFirstNonZeroDecimalPlace(value) {\n            var _String$split = String(Math.abs(value)).split('.'),\n                _String$split2 = _slicedToArray(_String$split, 2),\n                decimalPart = _String$split2[1];\n\n            if (this.isUndefined(decimalPart)) {\n                return 0;\n            }\n\n            var result = decimalPart.lastIndexOf('0');\n            if (result === -1) {\n                result = 0;\n            } else {\n                result += 2;\n            }\n\n            return result;\n        }\n\n        /**\n         * Return the code for the key used to generate the given event.\n         *\n         * @param {Event} event\n         * @returns {string|Number}\n         */\n\n    }, {\n        key: 'keyCodeNumber',\n        value: function keyCodeNumber(event) {\n            // `event.keyCode` and `event.which` are deprecated, `KeyboardEvent.key` (https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) must be used now\n            // Also, do note that Firefox generate a 'keypress' event (e.keyCode === 0) for the keys that do not print a character (ie. 'Insert', 'Delete', 'Fn' keys, 'PageUp', 'PageDown' etc.). 'Shift' on the other hand does not generate a keypress event.\n            return typeof event.which === 'undefined' ? event.keyCode : event.which;\n        }\n\n        /**\n         * Return the character from the event key code.\n         * If the KeyboardEvent does not represent a printable character, then the key name is used (ie. 'Meta', 'Shift', 'F1', etc.)\n         * @example character(50) => '2'\n         *\n         * @param {KeyboardEvent} event\n         * @returns {string}\n         */\n\n    }, {\n        key: 'character',\n        value: function character(event) {\n            var result = void 0;\n            if (event.key === 'Unidentified' || event.key === void 0 || this.isSeleniumBot()) {\n                //XXX The selenium geckodriver do not understand `event.key`, hence when using it, we need to rely on the old deprecated `keyCode` attribute, cf. upstream issue https://github.com/mozilla/geckodriver/issues/440\n                // Use the old deprecated keyCode property, if the new `key` one is not supported\n                var keyCode = this.keyCodeNumber(event);\n                if (keyCode === _AutoNumericEnum2.default.keyCode.AndroidDefault) {\n                    return _AutoNumericEnum2.default.keyName.AndroidDefault;\n                }\n\n                var potentialResult = _AutoNumericEnum2.default.fromCharCodeKeyCode[keyCode];\n                if (!AutoNumericHelper.isUndefinedOrNullOrEmpty(potentialResult)) {\n                    // Since `String.fromCharCode` do not return named keys for some keys ('Escape' and 'Enter' for instance), we convert the characters to the key names\n                    result = potentialResult;\n                } else {\n                    result = String.fromCharCode(keyCode);\n                }\n            } else {\n                var browser = void 0;\n                switch (event.key) {\n                    // Manages all the special cases for obsolete browsers that return the non-standard names\n                    case 'Add':\n                        result = _AutoNumericEnum2.default.keyName.NumpadPlus;\n                        break;\n                    case 'Apps':\n                        result = _AutoNumericEnum2.default.keyName.ContextMenu;\n                        break;\n                    case 'Crsel':\n                        result = _AutoNumericEnum2.default.keyName.CrSel;\n                        break;\n                    case 'Decimal':\n                        result = _AutoNumericEnum2.default.keyName.NumpadDot;\n                        break;\n                    case 'Del':\n                        browser = this.browser();\n                        if (browser.name === 'firefox' && browser.version <= 36 || browser.name === 'ie' && browser.version <= 9) {\n                            // Special workaround for the obsolete browser IE11 which output a 'Delete' key when using the numpad 'dot' one! This fixes issue #401\n                            // This workaround break the usage of the 'Delete' key for Firefox <=36, and IE9, since those browser send 'Del' instead of 'Delete', therefore we only use it for those obsolete browsers\n                            result = _AutoNumericEnum2.default.keyName.Dot;\n                        } else {\n                            result = _AutoNumericEnum2.default.keyName.Delete;\n                        }\n                        break;\n                    case 'Divide':\n                        result = _AutoNumericEnum2.default.keyName.NumpadSlash;\n                        break;\n                    case 'Down':\n                        result = _AutoNumericEnum2.default.keyName.DownArrow;\n                        break;\n                    case 'Esc':\n                        result = _AutoNumericEnum2.default.keyName.Esc;\n                        break;\n                    case 'Exsel':\n                        result = _AutoNumericEnum2.default.keyName.ExSel;\n                        break;\n                    case 'Left':\n                        result = _AutoNumericEnum2.default.keyName.LeftArrow;\n                        break;\n                    case 'Meta':\n                    case 'Super':\n                        result = _AutoNumericEnum2.default.keyName.OSLeft;\n                        break;\n                    case 'Multiply':\n                        result = _AutoNumericEnum2.default.keyName.NumpadMultiply;\n                        break;\n                    case 'Right':\n                        result = _AutoNumericEnum2.default.keyName.RightArrow;\n                        break;\n                    case 'Spacebar':\n                        result = _AutoNumericEnum2.default.keyName.Space;\n                        break;\n                    case 'Subtract':\n                        result = _AutoNumericEnum2.default.keyName.NumpadMinus;\n                        break;\n                    case 'Up':\n                        result = _AutoNumericEnum2.default.keyName.UpArrow;\n                        break;\n                    default:\n                        // The normal case\n                        result = event.key;\n                }\n            }\n\n            return result;\n        }\n\n        /**\n         * Return an object containing the name and version of the current browser.\n         * @example `browserVersion()` => { name: 'Firefox', version: '42' }\n         * Based on http://stackoverflow.com/a/38080051/2834898\n         *\n         * @returns {{ name: string, version: string }}\n         */\n\n    }, {\n        key: 'browser',\n        value: function browser() {\n            var ua = navigator.userAgent;\n            var tem = void 0;\n            var M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\\/))\\/?\\s*(\\d+)/i) || [];\n\n            if (/trident/i.test(M[1])) {\n                tem = /\\brv[ :]+(\\d+)/g.exec(ua) || [];\n                return { name: 'ie', version: tem[1] || '' };\n            }\n\n            if (M[1] === 'Chrome') {\n                tem = ua.match(/\\b(OPR|Edge)\\/(\\d+)/);\n                if (tem !== null) {\n                    return { name: tem[1].replace('OPR', 'opera'), version: tem[2] };\n                }\n            }\n\n            M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];\n            if ((tem = ua.match(/version\\/(\\d+)/i)) !== null) {\n                M.splice(1, 1, tem[1]);\n            }\n\n            return { name: M[0].toLowerCase(), version: M[1] };\n        }\n\n        /**\n         * Check if the browser is controlled by Selenium.\n         * Note: This only works within the geckodriver.\n         * cf. http://stackoverflow.com/questions/33225947/can-a-website-detect-when-you-are-using-selenium-with-chromedriver\n         *\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isSeleniumBot',\n        value: function isSeleniumBot() {\n            // noinspection JSUnresolvedVariable\n            return window.navigator.webdriver === true;\n        }\n\n        /**\n         * Return `true` if the given number is negative, or if the given string contains a negative sign :\n         * - everywhere in the string (by default), or\n         * - on the first character only if the `checkEverywhere` parameter is set to `false`.\n         *\n         * Note: `-0` is not a negative number since it's equal to `0`.\n         *\n         * @param {number|string} numberOrNumericString A Number, or a number represented by a string\n         * @param {string} negativeSignCharacter The single character that represent the negative sign\n         * @param {boolean} checkEverywhere If TRUE, then the negative sign is search everywhere in the numeric string (this is needed for instance if the string is '1234.56-')\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isNegative',\n        value: function isNegative(numberOrNumericString) {\n            var negativeSignCharacter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '-';\n            var checkEverywhere = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;\n\n            if (numberOrNumericString === negativeSignCharacter) {\n                return true;\n            }\n\n            if (numberOrNumericString === '') {\n                return false;\n            }\n\n            if (AutoNumericHelper.isNumber(numberOrNumericString)) {\n                return numberOrNumericString < 0;\n            }\n\n            if (checkEverywhere) {\n                return this.contains(numberOrNumericString, negativeSignCharacter);\n            }\n\n            return this.isNegativeStrict(numberOrNumericString, negativeSignCharacter);\n        }\n\n        /**\n         * Return `true` if the given string contains a negative sign on the first character (on the far left).\n         *\n         * @example isNegativeStrict('1234.56')     => false\n         * @example isNegativeStrict('1234.56-')    => false\n         * @example isNegativeStrict('-1234.56')    => true\n         * @example isNegativeStrict('-1,234.56 €') => true\n         *\n         * @param {string} numericString\n         * @param {string} negativeSignCharacter The single character that represent the negative sign\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isNegativeStrict',\n        value: function isNegativeStrict(numericString) {\n            var negativeSignCharacter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '-';\n\n            return numericString.charAt(0) === negativeSignCharacter;\n        }\n\n        /**\n         * Return `true` if the very first character is the opening bracket, and if the rest of the `valueString` also has the closing bracket.\n         *\n         * @param {string} valueString\n         * @param {string} leftBracket\n         * @param {string} rightBracket\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isNegativeWithBrackets',\n        value: function isNegativeWithBrackets(valueString, leftBracket, rightBracket) {\n            return valueString.charAt(0) === leftBracket && this.contains(valueString, rightBracket);\n        }\n\n        /**\n         * Return `true` if the formatted or unformatted numeric string represent the value 0 (ie. '0,00 €'), or is empty (' €').\n         * This works since we test if there are any numbers from 1 to 9 in the string. If there is none, then the number is zero (or the string is empty).\n         *\n         * @param {string} numericString\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isZeroOrHasNoValue',\n        value: function isZeroOrHasNoValue(numericString) {\n            return !/[1-9]/g.test(numericString);\n        }\n\n        /**\n         * Return the negative version of the value (represented as a string) given as a parameter.\n         * The numeric string is a valid Javascript number when typecast to a `Number`.\n         *\n         * @param {string} value\n         * @returns {*}\n         */\n\n    }, {\n        key: 'setRawNegativeSign',\n        value: function setRawNegativeSign(value) {\n            if (!this.isNegativeStrict(value, '-')) {\n                return '-' + value;\n            }\n\n            return value;\n        }\n\n        /**\n         * Replace the character at the position `index` in the string `string` by the character(s) `newCharacter`.\n         *\n         * @param {string} string\n         * @param {int} index\n         * @param {string} newCharacter\n         * @returns {string}\n         */\n\n    }, {\n        key: 'replaceCharAt',\n        value: function replaceCharAt(string, index, newCharacter) {\n            return '' + string.substr(0, index) + newCharacter + string.substr(index + newCharacter.length);\n        }\n\n        /**\n         * Return the value clamped to the nearest minimum/maximum value, as defined in the settings.\n         *\n         * @param {string|number} value\n         * @param {object} settings\n         * @returns {number}\n         */\n\n    }, {\n        key: 'clampToRangeLimits',\n        value: function clampToRangeLimits(value, settings) {\n            //XXX This function always assume `settings.minimumValue` is lower than `settings.maximumValue`\n            return Math.max(settings.minimumValue, Math.min(settings.maximumValue, value));\n        }\n\n        /**\n         * Return the number of number or dot characters on the left side of the caret, in a formatted number.\n         *\n         * @param {string} formattedNumberString\n         * @param {int} caretPosition This must be a positive integer\n         * @param {string} decimalCharacter\n         * @returns {number}\n         */\n\n    }, {\n        key: 'countNumberCharactersOnTheCaretLeftSide',\n        value: function countNumberCharactersOnTheCaretLeftSide(formattedNumberString, caretPosition, decimalCharacter) {\n            // Here we count the dot and report it as a number character too, since it will 'stay' in the Javascript number when unformatted\n            var numberDotOrNegativeSign = new RegExp('[0-9' + decimalCharacter + '-]'); // No need to escape the decimal character here, since it's in `[]`\n\n            var numberDotAndNegativeSignCount = 0;\n            for (var i = 0; i < caretPosition; i++) {\n                // Test if the character is a number, a dot or an hyphen. If it is, count it, otherwise ignore it\n                if (numberDotOrNegativeSign.test(formattedNumberString[i])) {\n                    numberDotAndNegativeSignCount++;\n                }\n            }\n\n            return numberDotAndNegativeSignCount;\n        }\n\n        /**\n         * Walk the `formattedNumberString` from left to right, one char by one, counting the `formattedNumberStringIndex`.\n         * If the char is in the `rawNumberString` (starting at index 0), then `rawNumberStringIndex++`, and continue until\n         * there is no more characters in `rawNumberString`) or that `rawNumberStringIndex === caretPositionInRawValue`.\n         * When you stop, the `formattedNumberStringIndex` is the position where the caret should be set.\n         *\n         * @example\n         * 1234567|89.01   : position 7 (rawNumberString)\n         * 123.456.7|89,01 : position 9 (formattedNumberString)\n         *\n         * @param {string} rawNumberString\n         * @param {int} caretPositionInRawValue\n         * @param {string} formattedNumberString\n         * @param {string} decimalCharacter\n         * @returns {*}\n         */\n\n    }, {\n        key: 'findCaretPositionInFormattedNumber',\n        value: function findCaretPositionInFormattedNumber(rawNumberString, caretPositionInRawValue, formattedNumberString, decimalCharacter) {\n            var formattedNumberStringSize = formattedNumberString.length;\n            var rawNumberStringSize = rawNumberString.length;\n\n            var formattedNumberStringIndex = void 0;\n            var rawNumberStringIndex = 0;\n            for (formattedNumberStringIndex = 0; formattedNumberStringIndex < formattedNumberStringSize && rawNumberStringIndex < rawNumberStringSize && rawNumberStringIndex < caretPositionInRawValue; formattedNumberStringIndex++) {\n                if (rawNumberString[rawNumberStringIndex] === formattedNumberString[formattedNumberStringIndex] || rawNumberString[rawNumberStringIndex] === '.' && formattedNumberString[formattedNumberStringIndex] === decimalCharacter) {\n                    rawNumberStringIndex++;\n                }\n            }\n\n            return formattedNumberStringIndex;\n        }\n\n        /**\n         * Count the number of occurrence of the given character, in the given text.\n         *\n         * @param {string} character\n         * @param {string} text\n         * @returns {number}\n         */\n\n    }, {\n        key: 'countCharInText',\n        value: function countCharInText(character, text) {\n            var charCounter = 0;\n            for (var i = 0; i < text.length; i++) {\n                if (text[i] === character) {\n                    charCounter++;\n                }\n            }\n\n            return charCounter;\n        }\n\n        /**\n         * Return the index that can be used to set the caret position.\n         * This takes into account that the position is starting at '0', not 1.\n         *\n         * @param {int} characterCount\n         * @returns {number}\n         */\n\n    }, {\n        key: 'convertCharacterCountToIndexPosition',\n        value: function convertCharacterCountToIndexPosition(characterCount) {\n            return Math.max(characterCount, characterCount - 1);\n        }\n\n        /**\n         * Cross browser routine for getting selected range/cursor position.\n         * Note: this also works with edge cases like contenteditable-enabled elements, and hidden inputs.\n         *\n         * @param {HTMLInputElement|EventTarget} element\n         * @returns {{}}\n         */\n\n    }, {\n        key: 'getElementSelection',\n        value: function getElementSelection(element) {\n            var position = {};\n\n            var isSelectionStartUndefined = void 0;\n            try {\n                isSelectionStartUndefined = this.isUndefined(element.selectionStart);\n            } catch (error) {\n                isSelectionStartUndefined = false;\n            }\n\n            try {\n                if (isSelectionStartUndefined) {\n                    var selection = window.getSelection();\n                    var selectionInfo = selection.getRangeAt(0);\n                    position.start = selectionInfo.startOffset;\n                    position.end = selectionInfo.endOffset;\n                    position.length = position.end - position.start;\n                } else {\n                    position.start = element.selectionStart;\n                    position.end = element.selectionEnd;\n                    position.length = position.end - position.start;\n                }\n            } catch (error) {\n                // Manages the cases where :\n                // - the 'contenteditable' elements that have no selections\n                // - the <input> element is of type 'hidden'\n                position.start = 0;\n                position.end = 0;\n                position.length = 0;\n            }\n\n            return position;\n        }\n\n        /**\n         * Cross browser routine for setting selected range/cursor position\n         *\n         * @param {HTMLInputElement|EventTarget} element\n         * @param {int} start\n         * @param {int|null} end\n         */\n\n    }, {\n        key: 'setElementSelection',\n        value: function setElementSelection(element, start) {\n            var end = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\n            if (this.isUndefinedOrNullOrEmpty(end)) {\n                end = start;\n            }\n\n            if (this.isInputElement(element)) {\n                element.setSelectionRange(start, end);\n            } else if (!AutoNumericHelper.isNull(element.firstChild)) {\n                var range = document.createRange();\n                range.setStart(element.firstChild, start);\n                range.setEnd(element.firstChild, end);\n                var selection = window.getSelection();\n                selection.removeAllRanges();\n                selection.addRange(range);\n            }\n        }\n\n        /**\n         * Function that throw error messages\n         *\n         * @param {string} message\n         * @throws\n         */\n\n    }, {\n        key: 'throwError',\n        value: function throwError(message) {\n            throw new Error(message);\n        }\n\n        /**\n         * Function that display a warning messages, according to the debug level.\n         *\n         * @param {string} message\n         * @param {boolean} showWarning If FALSE, then the warning message is not displayed\n         */\n\n    }, {\n        key: 'warning',\n        value: function warning(message) {\n            var showWarning = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n\n            if (showWarning) {\n                /* eslint no-console: 0 */\n                console.warn('Warning: ' + message);\n            }\n        }\n\n        /**\n         * Return `true` if the given event is a wheelup event\n         *\n         * @param {WheelEvent} wheelEvent\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isWheelUpEvent',\n        value: function isWheelUpEvent(wheelEvent) {\n            if (!wheelEvent.deltaY) {\n                this.throwError('The event passed as a parameter is not a valid wheel event, \\'' + wheelEvent.type + '\\' given.');\n            }\n\n            return wheelEvent.deltaY < 0;\n        }\n\n        /**\n         * Return `true` if the given event is a wheeldown event\n         *\n         * @param {WheelEvent} wheelEvent\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isWheelDownEvent',\n        value: function isWheelDownEvent(wheelEvent) {\n            if (!wheelEvent.deltaY) {\n                this.throwError('The event passed as a parameter is not a valid wheel event, \\'' + wheelEvent.type + '\\' given.');\n            }\n\n            return wheelEvent.deltaY > 0;\n        }\n\n        /**\n         * Return the given raw value truncated at the given number of decimal places `decimalPlaces`.\n         * This function does not round the value.\n         *\n         * @example\n         * forceDecimalPlaces(123.45678, 0) -> '123.45678'\n         * forceDecimalPlaces(123.45678, 1) -> '123.4'\n         * forceDecimalPlaces(123.45678, 2) -> '123.45'\n         * forceDecimalPlaces(123.45678, 3) -> '123.456'\n         *\n         * @param {number} value\n         * @param {int} decimalPlaces\n         * @returns {number|string}\n         */\n\n    }, {\n        key: 'forceDecimalPlaces',\n        value: function forceDecimalPlaces(value, decimalPlaces) {\n            // We could make sure `decimalPlaces` is an integer and positive, but we'll leave that to the dev calling this function.\n            var _String$split3 = String(value).split('.'),\n                _String$split4 = _slicedToArray(_String$split3, 2),\n                integerPart = _String$split4[0],\n                decimalPart = _String$split4[1];\n\n            if (!decimalPart) {\n                return value;\n            }\n\n            return integerPart + '.' + decimalPart.substr(0, decimalPlaces);\n        }\n\n        /**\n         * Return the 'nearest rounded' value, according to the given step size.\n         * @example roundToNearest(264789, 10000)) => 260000\n         *\n         * @param {number} value\n         * @param {number} stepPlace\n         * @returns {*}\n         */\n\n    }, {\n        key: 'roundToNearest',\n        value: function roundToNearest(value) {\n            var stepPlace = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1000;\n\n            if (0 === value) {\n                return 0;\n            }\n\n            if (stepPlace === 0) {\n                this.throwError('The `stepPlace` used to round is equal to `0`. This value must not be equal to zero.');\n            }\n\n            return Math.round(value / stepPlace) * stepPlace;\n        }\n\n        /**\n         * Return the 'nearest rounded' value by automatically adding or subtracting the calculated offset to the initial value.\n         * This is done without having to pass a step to this function, and based on the size of the given `value`.\n         *\n         * @example                    Calculated offset\n         *           1 ->           1 (1)\n         *          14 ->          10 (10)\n         *         143 ->         140 (10)\n         *       1.278 ->       1.300 (100)\n         *      28.456 ->      28.500 (100)\n         *     276.345 ->     276.000 (1.000)\n         *   4.534.061 ->   4.530.000 (10.000)\n         *  66.723.844 ->  66.700.000 (100.000)\n         * 257.833.411 -> 258.000.000 (1.000.000)\n         *\n         *                           Initial   Added   Offset\n         * 2 decimalPlacesRawValue : 1.12   -> 2.00   (1)\n         * 3 decimalPlacesRawValue : 1.123  -> 2.000  (1)\n         *\n         * Special case when the `value` to round is between -1 and 1, excluded :\n         * @example\n         *     Number of             Initial   Result  Calculated\n         *     decimal places        value     (add)   offset\n         * 2 decimalPlacesRawValue : 0.12   -> 0.13    (0.01) : Math.pow(10, -2)\n         * 2 decimalPlacesRawValue : 0.01   -> 0.02    (0.01)\n         * 2 decimalPlacesRawValue : 0.00   -> 0.01    (0.01)\n         *\n         * 3 decimalPlacesRawValue : 0.123  -> 0.133   (0.01)  : Math.pow(10, -2)\n         * 3 decimalPlacesRawValue : 0.012  -> 0.013   (0.001) : Math.pow(10, -3)\n         * 3 decimalPlacesRawValue : 0.001  -> 0.001   (0.001)\n         * 3 decimalPlacesRawValue : 0.000  -> 0.001   (0.001)\n         *\n         * 4 decimalPlacesRawValue : 0.4123 -> 0.4200  (0.01)   : Math.pow(10, -2)\n         * 4 decimalPlacesRawValue : 0.0412 -> 0.0420  (0.001)  : Math.pow(10, -3)\n         * 4 decimalPlacesRawValue : 0.0041 -> 0.0042  (0.0001) : Math.pow(10, -4)\n         * 4 decimalPlacesRawValue : 0.0004 -> 0.0005  (0.0001)\n         * 4 decimalPlacesRawValue : 0.0000 -> 0.0001  (0.0001)\n         *\n         * @param {number} value\n         * @param {boolean} isAddition\n         * @param {int} decimalPlacesRawValue The precision needed by the `rawValue`\n         * @returns {*}\n         */\n\n    }, {\n        key: 'modifyAndRoundToNearestAuto',\n        value: function modifyAndRoundToNearestAuto(value, isAddition, decimalPlacesRawValue) {\n            value = Number(this.forceDecimalPlaces(value, decimalPlacesRawValue)); // Make sure that '0.13000000001' is converted to the number of rawValue decimal places '0.13'\n\n            var absValue = Math.abs(value);\n            if (absValue >= 0 && absValue < 1) {\n                var rawValueMinimumOffset = Math.pow(10, -decimalPlacesRawValue);\n                if (value === 0) {\n                    // 4 decimalPlacesRawValue : 0.0000 -> 0.0001 (0.0001)\n                    return isAddition ? rawValueMinimumOffset : -rawValueMinimumOffset;\n                }\n\n                var offset = void 0;\n                var minimumOffsetFirstDecimalPlaceIndex = decimalPlacesRawValue;\n                // Find where is the first non-zero decimal places\n                var indexFirstNonZeroDecimalPlace = this.indexFirstNonZeroDecimalPlace(value);\n                if (indexFirstNonZeroDecimalPlace >= minimumOffsetFirstDecimalPlaceIndex - 1) {\n                    /* 4 decimalPlacesRawValue : 0.0041 -> 0.0042 (0.0001) : Math.pow(10, -4)\n                     * 4 decimalPlacesRawValue : 0.0004 -> 0.0005 (0.0001)\n                     */\n                    offset = rawValueMinimumOffset;\n                } else {\n                    offset = Math.pow(10, -(indexFirstNonZeroDecimalPlace + 1));\n                }\n\n                var result = void 0;\n                if (isAddition) {\n                    result = value + offset;\n                } else {\n                    result = value - offset;\n                }\n\n                return this.roundToNearest(result, offset);\n            } else {\n                // For values >= 1\n                value = parseInt(value, 10);\n                var lengthValue = Math.abs(value).toString().length; // `Math.abs()` is needed here to omit the negative sign '-' in case of a negative value\n\n                var pow = void 0;\n                switch (lengthValue) {\n                    // Special cases for small numbers\n                    case 1:\n                        pow = 0;\n                        break;\n                    case 2:\n                    case 3:\n                        pow = 1;\n                        break;\n                    case 4:\n                    case 5:\n                        pow = 2;\n                        break;\n                    // Default behavior\n                    default:\n                        pow = lengthValue - 3;\n                }\n                var _offset = Math.pow(10, pow);\n\n                var _result = void 0;\n                if (isAddition) {\n                    _result = value + _offset;\n                } else {\n                    _result = value - _offset;\n                }\n\n                if (_result <= 10 && _result >= -10) {\n                    return _result;\n                }\n\n                return this.roundToNearest(_result, _offset);\n            }\n        }\n\n        /**\n         * Return the 'nearest rounded' value automatically by adding the calculated offset to the initial value.\n         * This will limit the result to the given number of decimal places `decimalPlacesLimit`.\n         *\n         * @param {number} value\n         * @param {int} decimalPlacesLimit\n         * @returns {*}\n         */\n\n    }, {\n        key: 'addAndRoundToNearestAuto',\n        value: function addAndRoundToNearestAuto(value, decimalPlacesLimit) {\n            return this.modifyAndRoundToNearestAuto(value, true, decimalPlacesLimit);\n        }\n\n        /**\n         * Return the 'nearest rounded' value automatically by subtracting the calculated offset to the initial value.\n         * This will limit the result to the given number of decimal places `decimalPlacesLimit`.\n         *\n         * @param {number} value\n         * @param {int} decimalPlacesLimit\n         * @returns {*}\n         */\n\n    }, {\n        key: 'subtractAndRoundToNearestAuto',\n        value: function subtractAndRoundToNearestAuto(value, decimalPlacesLimit) {\n            return this.modifyAndRoundToNearestAuto(value, false, decimalPlacesLimit);\n        }\n\n        /**\n         * Take an arabic number as a string and return a javascript number.\n         * By default, this function does not try to convert the arabic decimal and thousand separator characters.\n         * This returns `NaN` is the conversion is not possible.\n         * Based on http://stackoverflow.com/a/17025392/2834898\n         *\n         * @param {string} arabicNumbers\n         * @param {boolean} returnANumber If `true`, return a Number, otherwise return a String\n         * @param {boolean} parseDecimalCharacter\n         * @param {boolean} parseThousandSeparator\n         * @returns {string|number|NaN}\n         */\n\n    }, {\n        key: 'arabicToLatinNumbers',\n        value: function arabicToLatinNumbers(arabicNumbers) {\n            var returnANumber = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n            var parseDecimalCharacter = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n            var parseThousandSeparator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;\n\n            if (this.isNull(arabicNumbers)) {\n                return arabicNumbers;\n            }\n\n            var result = arabicNumbers.toString();\n            if (result === '') {\n                return arabicNumbers;\n            }\n\n            if (result.match(/[٠١٢٣٤٥٦٧٨٩۴۵۶]/g) === null) {\n                // If no Arabic/Persian numbers are found, return the numeric string or number directly\n                if (returnANumber) {\n                    result = Number(result);\n                }\n\n                return result;\n            }\n\n            if (parseDecimalCharacter) {\n                result = result.replace(/٫/, '.'); // Decimal character\n            }\n\n            if (parseThousandSeparator) {\n                result = result.replace(/٬/g, ''); // Thousand separator\n            }\n\n            // Replace the numbers only\n            result = result.replace(/[٠١٢٣٤٥٦٧٨٩]/g, function (d) {\n                return d.charCodeAt(0) - 1632;\n            }) // Arabic numbers\n            .replace(/[۰۱۲۳۴۵۶۷۸۹]/g, function (d) {\n                return d.charCodeAt(0) - 1776;\n            }); // Persian numbers\n\n            // `NaN` has precedence over the string `'NaN'`\n            var resultAsNumber = Number(result);\n            if (isNaN(resultAsNumber)) {\n                return resultAsNumber;\n            }\n\n            if (returnANumber) {\n                result = resultAsNumber;\n            }\n\n            return result;\n        }\n\n        /**\n         * Create a custom event and immediately sent it from the given element.\n         * By default, if no element is given, the event is thrown from `document`.\n         *\n         * @param {string} eventName\n         * @param {HTMLElement|HTMLDocument|EventTarget} element\n         * @param {object} detail\n         * @param {boolean} bubbles Set to `true` if the event must bubble up\n         * @param {boolean} cancelable Set to `true` if the event must be cancelable\n         */\n\n    }, {\n        key: 'triggerEvent',\n        value: function triggerEvent(eventName) {\n            var element = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document;\n            var detail = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n            var bubbles = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;\n            var cancelable = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;\n\n            var event = void 0;\n            if (window.CustomEvent) {\n                event = new CustomEvent(eventName, { detail: detail, bubbles: bubbles, cancelable: cancelable }); // This is not supported by default by IE ; We use the polyfill for IE9 and later.\n            } else {\n                event = document.createEvent('CustomEvent');\n                event.initCustomEvent(eventName, bubbles, cancelable, { detail: detail });\n            }\n\n            element.dispatchEvent(event);\n        }\n\n        /**\n         * Function to parse minimumValue, maximumValue & the input value to prepare for testing to determine if the value falls within the min / max range.\n         * Return an object example: minimumValue: \"999999999999999.99\" returns the following \"{s: -1, e: 12, c: Array[15]}\".\n         *\n         * This function is adapted from Big.js https://github.com/MikeMcl/big.js/. Many thanks to Mike.\n         *\n         * @param {number|string} n A numeric value.\n         * @returns {{}}\n         */\n\n    }, {\n        key: 'parseStr',\n        value: function parseStr(n) {\n            var x = {}; // A Big number instance.\n            var e = void 0;\n            var i = void 0;\n            var nL = void 0;\n            var j = void 0;\n\n            // Minus zero?\n            if (n === 0 && 1 / n < 0) {\n                n = '-0';\n            }\n\n            // Determine sign. 1 positive, -1 negative\n            n = n.toString();\n            if (this.isNegativeStrict(n, '-')) {\n                n = n.slice(1);\n                x.s = -1;\n            } else {\n                x.s = 1;\n            }\n\n            // Decimal point?\n            e = n.indexOf('.');\n            if (e > -1) {\n                n = n.replace('.', '');\n            }\n\n            // Length of string if no decimal character\n            if (e < 0) {\n                // Integer\n                e = n.length;\n            }\n\n            // Determine leading zeros\n            i = n.search(/[1-9]/i) === -1 ? n.length : n.search(/[1-9]/i);\n            nL = n.length;\n            if (i === nL) {\n                // Zero\n                x.e = 0;\n                x.c = [0];\n            } else {\n                // Determine trailing zeros\n                for (j = nL - 1; n.charAt(j) === '0'; j -= 1) {\n                    nL -= 1;\n                }\n                nL -= 1;\n\n                // Decimal location\n                x.e = e - i - 1;\n                x.c = [];\n\n                // Convert string to array of digits without leading/trailing zeros\n                for (e = 0; i <= nL; i += 1) {\n                    x.c[e] = +n.charAt(i);\n                    e += 1;\n                }\n            }\n\n            return x;\n        }\n\n        /**\n         * Function to test if the input value falls with the Min / Max settings.\n         * This uses the parsed strings for the above parseStr function.\n         *\n         * This function is adapted from Big.js https://github.com/MikeMcl/big.js/. Many thanks to Mike.\n         *\n         * @param {object} y Big number instance\n         * @param {object} x Big number instance\n         * @returns {*}\n         */\n\n    }, {\n        key: 'testMinMax',\n        value: function testMinMax(y, x) {\n            var xc = x.c;\n            var yc = y.c;\n            var i = x.s;\n            var j = y.s;\n            var k = x.e;\n            var l = y.e;\n\n            // Either zero?\n            if (!xc[0] || !yc[0]) {\n                var _result2 = void 0;\n                if (!xc[0]) {\n                    _result2 = !yc[0] ? 0 : -j;\n                } else {\n                    _result2 = i;\n                }\n                return _result2;\n            }\n\n            // Signs differ?\n            if (i !== j) {\n                return i;\n            }\n            var xNeg = i < 0;\n\n            // Compare exponents\n            if (k !== l) {\n                return k > l ^ xNeg ? 1 : -1;\n            }\n            i = -1;\n            k = xc.length;\n            l = yc.length;\n            j = k < l ? k : l;\n\n            // Compare digit by digit\n            for (i += 1; i < j; i += 1) {\n                if (xc[i] !== yc[i]) {\n                    return xc[i] > yc[i] ^ xNeg ? 1 : -1;\n                }\n            }\n\n            // Compare lengths\n            var result = void 0;\n            if (k === l) {\n                result = 0;\n            } else {\n                result = k > l ^ xNeg ? 1 : -1;\n            }\n\n            return result;\n        }\n\n        /**\n         * Generate a random string.\n         * cf. http://stackoverflow.com/a/8084248/2834898\n         *\n         * @param {Number} strLength Length of the generated string (in character count)\n         * @returns {string}\n         */\n\n    }, {\n        key: 'randomString',\n        value: function randomString() {\n            var strLength = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 5;\n\n            return Math.random().toString(36).substr(2, strLength);\n        }\n\n        /**\n         * Return the DOM element when passed either a DOM element or a selector string.\n         *\n         * @param {HTMLElement|string} domElementOrSelector\n         * @returns {HTMLElement}\n         */\n\n    }, {\n        key: 'domElement',\n        value: function domElement(domElementOrSelector) {\n            var domElement = void 0;\n            if (AutoNumericHelper.isString(domElementOrSelector)) {\n                domElement = document.querySelector(domElementOrSelector);\n            } else {\n                domElement = domElementOrSelector;\n            }\n\n            return domElement;\n        }\n\n        /**\n         * Retrieve the current element value.\n         *\n         * @param {HTMLElement|HTMLInputElement|EventTarget} element\n         * @returns {number|string|null}\n         */\n\n    }, {\n        key: 'getElementValue',\n        value: function getElementValue(element) {\n            if (element.tagName.toLowerCase() === 'input') {\n                return element.value;\n            }\n\n            return this.text(element);\n        }\n\n        /**\n         * Modify the element value directly.\n         *\n         * @param {HTMLElement|HTMLInputElement} element\n         * @param {number|string|null} value\n         */\n\n    }, {\n        key: 'setElementValue',\n        value: function setElementValue(element) {\n            var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n            if (element.tagName.toLowerCase() === 'input') {\n                element.value = value;\n            } else {\n                element.textContent = value;\n            }\n        }\n\n        /**\n         * This clone the given object, and return it.\n         * WARNING: This does not do a deep cloning.\n         * cf. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Examples\n         * //TODO Add a `deep` option to clone object with more than one depth\n         *\n         * @param {object} obj\n         * @returns {object}\n         */\n\n    }, {\n        key: 'cloneObject',\n        value: function cloneObject(obj) {\n            return _extends({}, obj);\n        }\n\n        /**\n         * Return a 'camelized' version of the given string.\n         * By default, this assume that :\n         * - the separators are hyphens '-',\n         * - the 'data-' string should be removed, and\n         * - that the very first word should not be capitalized.\n         *\n         * @example camelize('data-currency-symbol') => 'currencySymbol'\n         *\n         * @param {string} str Text to camelize\n         * @param {string} separator Character that separate each word\n         * @param {boolean} removeData If set to `true`, remove the `data-` part that you can find on some html attributes\n         * @param {boolean} skipFirstWord If set to `true`, do not capitalize the very first word\n         * @returns {string|null}\n         */\n\n    }, {\n        key: 'camelize',\n        value: function camelize(str) {\n            var separator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '-';\n            var removeData = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;\n            var skipFirstWord = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;\n\n            if (this.isNull(str)) {\n                return null;\n            }\n\n            if (removeData) {\n                str = str.replace(/^data-/, '');\n            }\n\n            // Cut the string into words\n            var words = str.split(separator);\n\n            // Capitalize each word\n            var result = words.map(function (word) {\n                return '' + word.charAt(0).toUpperCase() + word.slice(1);\n            });\n\n            // Then concatenate them back\n            result = result.join('');\n\n            if (skipFirstWord) {\n                // Skip the very first letter\n                result = '' + result.charAt(0).toLowerCase() + result.slice(1);\n            }\n\n            return result;\n        }\n\n        /**\n         * Return the text component of the given DOM element.\n         *\n         * @param {Element} domElement\n         * @returns {string}\n         */\n\n    }, {\n        key: 'text',\n        value: function text(domElement) {\n            var nodeType = domElement.nodeType;\n\n            var result = void 0;\n            // cf. https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType\n            if (nodeType === Node.ELEMENT_NODE || nodeType === Node.DOCUMENT_NODE || nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\n                result = domElement.textContent;\n            } else if (nodeType === Node.TEXT_NODE) {\n                result = domElement.nodeValue;\n            } else {\n                result = '';\n            }\n\n            return result;\n        }\n\n        /**\n         * Set the text content of the given DOM element.\n         * @param {Element} domElement\n         * @param {string} text\n         */\n\n    }, {\n        key: 'setText',\n        value: function setText(domElement, text) {\n            var nodeType = domElement.nodeType;\n            if (nodeType === Node.ELEMENT_NODE || nodeType === Node.DOCUMENT_NODE || nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\n                domElement.textContent = text;\n            }\n            //TODO Display a warning if that function does not do anything?\n        }\n\n        /**\n         * Filter out the given `arr` array with the elements found in `excludedElements`.\n         * This returns a new array and does not modify the source.\n         * cf. verification here : http://codepen.io/AnotherLinuxUser/pen/XpvrMg?editors=0012\n         *\n         * @param {Array} arr\n         * @param {Array} excludedElements\n         * @returns {*|Array.<T>}\n         */\n\n    }, {\n        key: 'filterOut',\n        value: function filterOut(arr, excludedElements) {\n            var _this = this;\n\n            return arr.filter(function (element) {\n                return !_this.isInArray(element, excludedElements);\n            });\n        }\n\n        /**\n         * Remove the trailing zeros in the decimal part of a number.\n         *\n         * @param {string} numericString\n         * @returns {*}\n         */\n\n    }, {\n        key: 'trimPaddedZerosFromDecimalPlaces',\n        value: function trimPaddedZerosFromDecimalPlaces(numericString) {\n            numericString = String(numericString);\n            if (numericString === '') {\n                return '';\n            }\n\n            var _numericString$split = numericString.split('.'),\n                _numericString$split2 = _slicedToArray(_numericString$split, 2),\n                integerPart = _numericString$split2[0],\n                decimalPart = _numericString$split2[1];\n\n            if (this.isUndefinedOrNullOrEmpty(decimalPart)) {\n                return integerPart;\n            }\n\n            var trimmedDecimalPart = decimalPart.replace(/0+$/g, '');\n\n            var result = void 0;\n            if (trimmedDecimalPart === '') {\n                result = integerPart;\n            } else {\n                result = integerPart + '.' + trimmedDecimalPart;\n            }\n\n            return result;\n        }\n\n        /**\n         * Return the top-most hovered item by the mouse cursor.\n         *\n         * @returns {*}\n         */\n\n    }, {\n        key: 'getHoveredElement',\n        value: function getHoveredElement() {\n            var hoveredElements = [].concat(_toConsumableArray(document.querySelectorAll(':hover')));\n            return hoveredElements[hoveredElements.length - 1];\n        }\n\n        /**\n         * Return the given array trimmed to the given length.\n         * @example arrayTrim([1, 2, 3, 4], 2) -> [1, 2]\n         *\n         * @param {Array} array\n         * @param {Number} length\n         * @returns {*}\n         */\n\n    }, {\n        key: 'arrayTrim',\n        value: function arrayTrim(array, length) {\n            var arrLength = array.length;\n            if (arrLength === 0 || length > arrLength) {\n                // Also manage the case where `length` is higher than the current length\n                return array;\n            }\n\n            if (length < 0) {\n                return [];\n            }\n\n            array.length = parseInt(length, 10);\n\n            return array;\n        }\n\n        /**\n         * Merge all the given arrays by keeping only unique elements, and return an array with de-duplicated values.\n         * cf. http://stackoverflow.com/a/27664971/2834898\n         *\n         * @param {...array} arrays\n         * @returns {[*]}\n         */\n\n    }, {\n        key: 'arrayUnique',\n        value: function arrayUnique() {\n            var _ref;\n\n            //FIXME à tester\n            return [].concat(_toConsumableArray(new Set((_ref = []).concat.apply(_ref, arguments))));\n        }\n\n        /**\n         * Merge all the given Maps by keeping only unique elements, and return a new Map with de-duplicated keys.\n         *\n         * @param {...Map} mapObjects\n         * @returns {Map}\n         */\n\n    }, {\n        key: 'mergeMaps',\n        value: function mergeMaps() {\n            for (var _len = arguments.length, mapObjects = Array(_len), _key = 0; _key < _len; _key++) {\n                mapObjects[_key] = arguments[_key];\n            }\n\n            return new Map(mapObjects.reduce(function (as, b) {\n                return as.concat([].concat(_toConsumableArray(b)));\n            }, []));\n        }\n\n        /**\n         * Search the given `value` in the object `obj`, and return the very first key it finds\n         *\n         * @param {object} obj\n         * @param {string|number} value\n         * @returns {*|null}\n         */\n\n    }, {\n        key: 'objectKeyLookup',\n        value: function objectKeyLookup(obj, value) {\n            var result = Object.entries(obj).find(function (array) {\n                return array[1] === value;\n            });\n            var key = null;\n            if (result !== void 0) {\n                key = result[0];\n            }\n\n            return key;\n        }\n\n        /**\n         * Insert the single character `char` in the string `str` at the given position `index`\n         *\n         * @param {string} str\n         * @param {string} char\n         * @param {int} index\n         * @returns {string}\n         */\n\n    }, {\n        key: 'insertAt',\n        value: function insertAt(str, char, index) {\n            str = String(str);\n\n            if (index > str.length) {\n                throw new Error('The given index is out of the string range.');\n            }\n\n            if (char.length !== 1) {\n                throw new Error('The given string `char` should be only one character long.');\n            }\n\n            if (str === '' && index === 0) {\n                return char;\n            }\n\n            return '' + str.slice(0, index) + char + str.slice(index);\n        }\n\n        /**\n         * Convert the given scientific notation to the 'expanded' decimal notation\n         *\n         * @example scientificToDecimal('-123.4567e-6') returns '-0.0001234567'\n         *\n         * @param {number|string} val\n         * @returns {number|string}\n         */\n\n    }, {\n        key: 'scientificToDecimal',\n        value: function scientificToDecimal(val) {\n            // Check that the val is a Number\n            var numericValue = Number(val);\n            if (isNaN(numericValue)) {\n                return NaN;\n            }\n\n            // Check if the number is in a scientific notation\n            val = String(val);\n            var isScientific = this.contains(val, 'e') || this.contains(val, 'E');\n\n            if (!isScientific) {\n                return val;\n            }\n\n            // Convert the scientific notation to a numeric string\n\n            var _val$split = val.split(/e/i),\n                _val$split2 = _slicedToArray(_val$split, 2),\n                value = _val$split2[0],\n                exponent = _val$split2[1];\n\n            var isNegative = value < 0;\n            if (isNegative) {\n                value = value.replace('-', '');\n            }\n\n            var isNegativeExponent = +exponent < 0;\n            if (isNegativeExponent) {\n                exponent = exponent.replace('-', ''); // Remove the negative sign\n            }\n\n            var _value$split = value.split(/\\./),\n                _value$split2 = _slicedToArray(_value$split, 2),\n                int = _value$split2[0],\n                float = _value$split2[1];\n\n            var result = void 0;\n            if (isNegativeExponent) {\n                if (int.length > exponent) {\n                    // Place the decimal point at the int length count minus exponent\n                    result = this.insertAt(int, '.', int.length - exponent);\n                } else {\n                    // If that decimal point is greater than the int length, pad with zeros (ie. Number('-123.4567e-6') --> -0.0001234567)\n                    result = '0.' + '0'.repeat(exponent - int.length) + int;\n                }\n\n                result = '' + result + (float ? float : '');\n            } else {\n                // Positive exponent\n                if (float) {\n                    value = '' + int + float; // Remove the '.', if any\n                    if (exponent < float.length) {\n                        result = this.insertAt(value, '.', +exponent + int.length);\n                    } else {\n                        result = '' + value + '0'.repeat(exponent - float.length);\n                    }\n                } else {\n                    value = value.replace('.', ''); // Single case where val is '1.e4'\n                    result = '' + value + '0'.repeat(Number(exponent));\n                }\n            }\n\n            if (isNegative) {\n                // Put back the negative sign, if any\n                result = '-' + result;\n            }\n\n            return result;\n        }\n    }]);\n\n    return AutoNumericHelper;\n}();\n\nexports.default = AutoNumericHelper;\nmodule.exports = exports['default'];\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvQXV0b051bWVyaWNIZWxwZXIuanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9BdXRvTnVtZXJpYy9zcmMvQXV0b051bWVyaWNIZWxwZXIuanM/ZTlhZiJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEhlbHBlciBmdW5jdGlvbnMgZm9yIGF1dG9OdW1lcmljLmpzXG4gKiBAYXV0aG9yIEFsZXhhbmRyZSBCb25uZWF1IDxhbGV4YW5kcmUuYm9ubmVhdUBsaW51eGZyLmV1PlxuICogQGNvcHlyaWdodCDCqSAyMDE2IEFsZXhhbmRyZSBCb25uZWF1XG4gKlxuICogVGhlIE1JVCBMaWNlbnNlIChodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL21pdC1saWNlbnNlLnBocClcbiAqXG4gKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvblxuICogb2J0YWluaW5nIGEgY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb25cbiAqIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dFxuICogcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsXG4gKiBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWIgbGljZW5zZSwgYW5kL29yIHNlbGxcbiAqIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZVxuICogU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmdcbiAqIGNvbmRpdGlvbnM6XG4gKlxuICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmVcbiAqIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICpcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsXG4gKiBFWFBSRVNTIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVNcbiAqIE9GIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EXG4gKiBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVFxuICogSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksXG4gKiBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkdcbiAqIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1JcbiAqIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cbiAqL1xuXG5pbXBvcnQgQXV0b051bWVyaWNFbnVtIGZyb20gJy4vQXV0b051bWVyaWNFbnVtJztcblxuLyoqXG4gKiBTdGF0aWMgY2xhc3MgdGhhdCBob2xkcyBhbGwgdGhlIGhlbHBlciBmdW5jdGlvbnMgYXV0b051bWVyaWMgdXNlcy5cbiAqIE5vdGUgOiBub25lIG9mIHRoZSBmdW5jdGlvbnMgaW4gdGhlcmUgYXJlIGF3YXJlIG9mIGFueSBhdXRvTnVtZXJpYyBpbnRlcm5hbHMgKHdoaWNoIG1lYW5zIHRoZXJlIGFyZSBubyByZWZlcmVuY2VzIHRvIGF1dG9OdW1lcmljLXNwZWNpZmljIGluZm8gbGlrZSBvcHRpb25zIG5hbWVzIG9yIGRhdGEgc3RydWN0dXJlcykuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEF1dG9OdW1lcmljSGVscGVyIHtcbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBgdmFsdWVgIGlzIG51bGxcbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byB0ZXN0XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybiBgdHJ1ZWAgaWYgdGhlIGB2YWx1ZWAgaXMgbnVsbCwgRkFMU0Ugb3RoZXJ3aXNlXG4gICAgICovXG4gICAgc3RhdGljIGlzTnVsbCh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgPT09IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgYHZhbHVlYCBpcyB1bmRlZmluZWRcbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byB0ZXN0XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybiBgdHJ1ZWAgaWYgdGhlIGB2YWx1ZWAgaXMgdW5kZWZpbmVkLCBGQUxTRSBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBzdGF0aWMgaXNVbmRlZmluZWQodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlID09PSB2b2lkKDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGB2YWx1ZWAgaXMgdW5kZWZpbmVkLCBudWxsIG9yIGVtcHR5XG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eSh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHZvaWQoMCkgfHwgJycgPT09IHZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGdpdmVuIHBhcmFtZXRlciBpcyBhIFN0cmluZ1xuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSBzdHJcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNTdHJpbmcoc3RyKSB7XG4gICAgICAgIHJldHVybiAodHlwZW9mIHN0ciA9PT0gJ3N0cmluZycgfHwgc3RyIGluc3RhbmNlb2YgU3RyaW5nKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgYHZhbHVlYCBpcyBhbiBlbXB0eSBzdHJpbmcgJydcbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byB0ZXN0XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybiBgdHJ1ZWAgaWYgdGhlIGB2YWx1ZWAgaXMgYW4gZW1wdHkgc3RyaW5nICcnLCBGQUxTRSBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBzdGF0aWMgaXNFbXB0eVN0cmluZyh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgPT09ICcnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIHBhcmFtZXRlciBpcyBhIGJvb2xlYW5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzQm9vbGVhbih2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdHlwZW9mKHZhbHVlKSA9PT0gJ2Jvb2xlYW4nO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIHBhcmFtZXRlciBpcyBhIHN0cmluZyAndHJ1ZScgb3IgJ2ZhbHNlJ1xuICAgICAqXG4gICAgICogVGhpcyBmdW5jdGlvbiBhY2NlcHRzIGFueSBjYXNlcyBmb3IgdGhvc2Ugc3RyaW5ncy5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNUcnVlT3JGYWxzZVN0cmluZyh2YWx1ZSkge1xuICAgICAgICBjb25zdCBsb3dlcmNhc2VWYWx1ZSA9IFN0cmluZyh2YWx1ZSkudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgcmV0dXJuIGxvd2VyY2FzZVZhbHVlID09PSAndHJ1ZScgfHwgbG93ZXJjYXNlVmFsdWUgPT09ICdmYWxzZSc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyYW1ldGVyIGlzIGFuIG9iamVjdFxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSByZWZlcmVuY2VcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNPYmplY3QocmVmZXJlbmNlKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgcmVmZXJlbmNlID09PSAnb2JqZWN0JyAmJiByZWZlcmVuY2UgIT09IG51bGwgJiYgIUFycmF5LmlzQXJyYXkocmVmZXJlbmNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBnaXZlbiBvYmplY3QgaXMgZW1wdHlcbiAgICAgKiBjZi4gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82Nzk5MTUvaG93LWRvLWktdGVzdC1mb3ItYW4tZW1wdHktamF2YXNjcmlwdC1vYmplY3QgYW5kIGh0dHA6Ly9qc3BlcmYuY29tL2VtcHR5LW9iamVjdC10ZXN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb2JqXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzRW1wdHlPYmoob2JqKSB7XG4gICAgICAgIGZvciAoY29uc3QgcHJvcCBpbiBvYmopIHtcbiAgICAgICAgICAgIGlmIChvYmouaGFzT3duUHJvcGVydHkocHJvcCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyYW1ldGVyIGlzIGEgcmVhbCBudW1iZXIgKGFuZCBub3QgYSBudW1lcmljIHN0cmluZykuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IG5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNOdW1iZXJTdHJpY3Qobikge1xuICAgICAgICByZXR1cm4gdHlwZW9mIG4gPT09ICdudW1iZXInO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIHBhcmFtZXRlciBpcyBhIG51bWJlciAob3IgYSBudW1iZXIgd3JpdHRlbiBhcyBhIHN0cmluZykuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IG5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNOdW1iZXIobikge1xuICAgICAgICByZXR1cm4gIXRoaXMuaXNBcnJheShuKSAmJiAhaXNOYU4ocGFyc2VGbG9hdChuKSkgJiYgaXNGaW5pdGUobik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyYW1ldGVyIGlzIGEgbnVtYmVyIChvciBhIG51bWJlciB3cml0dGVuIGFzIGEgc3RyaW5nKS5cbiAgICAgKiBUaGlzIHZlcnNpb24gYWxzbyBhY2NlcHRzIEFyYWJpYyBhbmQgUGVyc2lhbiBudW1iZXJzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSBuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzTnVtYmVyT3JBcmFiaWMobikge1xuICAgICAgICBjb25zdCBsYXRpbkNvbnZlcnRlZE51bWJlciA9IHRoaXMuYXJhYmljVG9MYXRpbk51bWJlcnMobiwgZmFsc2UsIHRydWUsIHRydWUpO1xuICAgICAgICByZXR1cm4gdGhpcy5pc051bWJlcihsYXRpbkNvbnZlcnRlZE51bWJlcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyYW1ldGVyIGlzIGFuIGludGVnZXIgKGFuZCBub3QgYSBmbG9hdCkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IG5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNJbnQobikge1xuICAgICAgICByZXR1cm4gdHlwZW9mIG4gPT09ICdudW1iZXInICYmIHBhcnNlRmxvYXQobikgPT09IHBhcnNlSW50KG4sIDEwKSAmJiAhaXNOYU4obik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyYW1ldGVyIGlzIGEgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBmdW5jXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzRnVuY3Rpb24oZnVuYykge1xuICAgICAgICByZXR1cm4gdHlwZW9mIGZ1bmMgPT09ICdmdW5jdGlvbic7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgY3VycmVudCBicm93c2VyIGlzIHRoZSBvYnNvbGV0ZSBJbnRlcm5ldCBFeHBsb3JlciAxMSAoSUUxMSkgb25lXG4gICAgICogY2YuIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8yMTgyNTIwNy8yODM0ODk4XG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNJRTExKCkge1xuICAgICAgICAvLyBub2luc3BlY3Rpb24gSlNVbnJlc29sdmVkVmFyaWFibGVcbiAgICAgICAgcmV0dXJuICEhd2luZG93Lk1TSW5wdXRNZXRob2RDb250ZXh0ICYmICEhZG9jdW1lbnQuZG9jdW1lbnRNb2RlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaXMgdGhlIHN0cmluZyBgc3RyYCBjb250YWlucyB0aGUgc3RyaW5nIGBuZWVkbGVgXG4gICAgICogTm90ZTogdGhpcyBmdW5jdGlvbiBkb2VzIG5vdCBjb2VyY2UgdGhlIHBhcmFtZXRlcnMgdHlwZXNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmVlZGxlXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGNvbnRhaW5zKHN0ciwgbmVlZGxlKSB7XG4gICAgICAgIC8vVE9ETyBVc2UgYEFycmF5LnByb3RvdHlwZS5pbmNsdWRlcygpYCB3aGVuIGF2YWlsYWJsZSAoY2YuIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0FycmF5L2luY2x1ZGVzKVxuICAgICAgICBpZiAoIXRoaXMuaXNTdHJpbmcoc3RyKSB8fCAhdGhpcy5pc1N0cmluZyhuZWVkbGUpIHx8IHN0ciA9PT0gJycgfHwgbmVlZGxlID09PSAnJykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHN0ci5pbmRleE9mKG5lZWRsZSkgIT09IC0xO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGBuZWVkbGVgIGlzIGluIHRoZSBhcnJheVxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSBuZWVkbGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheVxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIHN0YXRpYyBpc0luQXJyYXkobmVlZGxlLCBhcnJheSkge1xuICAgICAgICBpZiAoIXRoaXMuaXNBcnJheShhcnJheSkgfHwgYXJyYXkgPT09IFtdIHx8IHRoaXMuaXNVbmRlZmluZWQobmVlZGxlKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGFycmF5LmluZGV4T2YobmVlZGxlKSAhPT0gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyYW1ldGVyIGlzIGFuIEFycmF5XG4gICAgICogLy9UT0RPIFJlcGxhY2UgdGhpcyBieSB0aGUgZGVmYXVsdCBgQXJyYXkuaXNBcnJheSgpYCBmdW5jdGlvbj9cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Kn0gYXJyXG4gICAgICogQHRocm93cyBFcnJvclxuICAgICAqIEByZXR1cm5zIHsqfGJvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzQXJyYXkoYXJyKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoW10pID09PSAnW29iamVjdCBBcnJheV0nKSB7IC8vIE1ha2Ugc3VyZSBhbiBhcnJheSBoYXMgYSBjbGFzcyBhdHRyaWJ1dGUgb2YgW29iamVjdCBBcnJheV1cbiAgICAgICAgICAgIC8vIFRlc3QgcGFzc2VkLCBub3cgY2hlY2sgaWYgaXMgYW4gQXJyYXlcbiAgICAgICAgICAgIHJldHVybiBBcnJheS5pc0FycmF5KGFycikgfHwgKHR5cGVvZiBhcnIgPT09ICdvYmplY3QnICYmIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChhcnIpID09PSAnW29iamVjdCBBcnJheV0nKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigndG9TdHJpbmcgbWVzc2FnZSBjaGFuZ2VkIGZvciBPYmplY3QgQXJyYXknKTsgLy8gVmVyaWZ5IHRoYXQgdGhlIHN0cmluZyByZXR1cm5lZCBieSBgdG9TdHJpbmdgIGRvZXMgbm90IGNoYW5nZSBpbiB0aGUgZnV0dXJlIChjZi4gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvODM2NTIxNSlcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIHBhcmFtZXRlciBpcyBhIERPTSBlbGVtZW50XG4gICAgICogY2YuIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzQ3NTQxMDQvMjgzNDg5OFxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSBvYmpcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNFbGVtZW50KG9iaikge1xuICAgICAgICAvLyByZXR1cm4gISEob2JqICYmIG9iai5ub2RlTmFtZSk7XG4gICAgICAgIC8vIHJldHVybiBvYmogJiYgJ25vZGVUeXBlJyBpbiBvYmo7XG4gICAgICAgIC8vIHJldHVybiBvYmogaW5zdGFuY2VvZiBFbGVtZW50IHx8IG9iaiBpbnN0YW5jZW9mIEhUTUxJbnB1dEVsZW1lbnQgfHwgb2JqIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQ7XG4gICAgICAgIGlmICh0eXBlb2YgRWxlbWVudCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIC8vIFRoaXMgdGVzdCBpcyBuZWVkZWQgaW4gZW52aXJvbm5lbWVudHMgd2hlcmUgdGhlIEVsZW1lbnQgb2JqZWN0IGRvZXMgbm90IGV4aXN0IChpZS4gaW4gd2ViIHdvcmtlcnMpXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gb2JqIGluc3RhbmNlb2YgRWxlbWVudDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGluIHRoZSBnaXZlbiBET00gZWxlbWVudCBpcyBhbiA8aW5wdXQ+LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fSBkb21FbGVtZW50XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgaXNJbnB1dEVsZW1lbnQoZG9tRWxlbWVudCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pc0VsZW1lbnQoZG9tRWxlbWVudCkgJiYgZG9tRWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdpbnB1dCc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyYW1ldGVyIGlzIGEgc3RyaW5nIHRoYXQgcmVwcmVzZW50cyBhIGZsb2F0IG51bWJlciwgYW5kIHRoYXQgbnVtYmVyIGhhcyBhIGRlY2ltYWwgcGFydFxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0clxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIC8vIHN0YXRpYyBoYXNEZWNpbWFscyhzdHIpIHtcbiAgICAvLyAgICAgY29uc3QgWywgZGVjaW1hbFBhcnRdID0gc3RyLnNwbGl0KCcuJyk7XG4gICAgLy8gICAgIHJldHVybiAhaXNVbmRlZmluZWQoZGVjaW1hbFBhcnQpO1xuICAgIC8vIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIGlmIHRoZSBwYXJhbWV0ZXIgaXMgYSBzdHJpbmcgdGhhdCByZXByZXNlbnRzIGEgZmxvYXQgbnVtYmVyLCBhbmQgdGhhdCBudW1iZXIgaGFzIGEgZGVjaW1hbCBwYXJ0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0clxuICAgICAqIEByZXR1cm5zIHtpbnR9XG4gICAgICovXG4gICAgc3RhdGljIGRlY2ltYWxQbGFjZXMoc3RyKSB7XG4gICAgICAgIGNvbnN0IFssIGRlY2ltYWxQYXJ0XSA9IHN0ci5zcGxpdCgnLicpO1xuICAgICAgICBpZiAoIXRoaXMuaXNVbmRlZmluZWQoZGVjaW1hbFBhcnQpKSB7XG4gICAgICAgICAgICByZXR1cm4gZGVjaW1hbFBhcnQubGVuZ3RoO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBpbmRleCBvZiB0aGUgZmlyc3Qgbm9uLXplcm8gZGVjaW1hbCBwbGFjZSBpbiB0aGUgZ2l2ZW4gdmFsdWUuXG4gICAgICogVGhlIGluZGV4IHN0YXJ0cyBhZnRlciB0aGUgZGVjaW1hbCBwb2ludCwgaWYgYW55LCBhbmQgYmVnaW5zIGF0ICcxJy5cbiAgICAgKiBJZiBubyBkZWNpbWFsIHBsYWNlcyBhcmUgZm91bmQgaW4gdGhlIHZhbHVlLCB0aGlzIGZ1bmN0aW9uIHJldHVybnMgYDBgLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBpbmRleEZpcnN0Tm9uWmVyb0RlY2ltYWxQbGFjZSgnMC4wMCcpIC0+IDBcbiAgICAgKiBpbmRleEZpcnN0Tm9uWmVyb0RlY2ltYWxQbGFjZSgnMS4wMCcpIC0+IDBcbiAgICAgKiBpbmRleEZpcnN0Tm9uWmVyb0RlY2ltYWxQbGFjZSgnMC4xMicpIC0+IDFcbiAgICAgKiBpbmRleEZpcnN0Tm9uWmVyb0RlY2ltYWxQbGFjZSgnMC4xMjM0JykgLT4gMVxuICAgICAqIGluZGV4Rmlyc3ROb25aZXJvRGVjaW1hbFBsYWNlKCcwLjAxMjM0JykgLT4gMlxuICAgICAqIGluZGV4Rmlyc3ROb25aZXJvRGVjaW1hbFBsYWNlKCcwLjAwMTIzNCcpIC0+IDNcbiAgICAgKiBpbmRleEZpcnN0Tm9uWmVyb0RlY2ltYWxQbGFjZSgnMC4wMDAxMjM0JykgLT4gNFxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gICAgICogQHJldHVybnMge051bWJlcnxudW1iZXJ9XG4gICAgICovXG4gICAgc3RhdGljIGluZGV4Rmlyc3ROb25aZXJvRGVjaW1hbFBsYWNlKHZhbHVlKSB7XG4gICAgICAgIGNvbnN0IFssIGRlY2ltYWxQYXJ0XSA9IFN0cmluZyhNYXRoLmFicyh2YWx1ZSkpLnNwbGl0KCcuJyk7XG5cbiAgICAgICAgaWYgKHRoaXMuaXNVbmRlZmluZWQoZGVjaW1hbFBhcnQpKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZXN1bHQgPSBkZWNpbWFsUGFydC5sYXN0SW5kZXhPZignMCcpO1xuICAgICAgICBpZiAocmVzdWx0ID09PSAtMSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdCArPSAyO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIGNvZGUgZm9yIHRoZSBrZXkgdXNlZCB0byBnZW5lcmF0ZSB0aGUgZ2l2ZW4gZXZlbnQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBldmVudFxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8TnVtYmVyfVxuICAgICAqL1xuICAgIHN0YXRpYyBrZXlDb2RlTnVtYmVyKGV2ZW50KSB7XG4gICAgICAgIC8vIGBldmVudC5rZXlDb2RlYCBhbmQgYGV2ZW50LndoaWNoYCBhcmUgZGVwcmVjYXRlZCwgYEtleWJvYXJkRXZlbnQua2V5YCAoaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0tleWJvYXJkRXZlbnQva2V5KSBtdXN0IGJlIHVzZWQgbm93XG4gICAgICAgIC8vIEFsc28sIGRvIG5vdGUgdGhhdCBGaXJlZm94IGdlbmVyYXRlIGEgJ2tleXByZXNzJyBldmVudCAoZS5rZXlDb2RlID09PSAwKSBmb3IgdGhlIGtleXMgdGhhdCBkbyBub3QgcHJpbnQgYSBjaGFyYWN0ZXIgKGllLiAnSW5zZXJ0JywgJ0RlbGV0ZScsICdGbicga2V5cywgJ1BhZ2VVcCcsICdQYWdlRG93bicgZXRjLikuICdTaGlmdCcgb24gdGhlIG90aGVyIGhhbmQgZG9lcyBub3QgZ2VuZXJhdGUgYSBrZXlwcmVzcyBldmVudC5cbiAgICAgICAgcmV0dXJuICh0eXBlb2YgZXZlbnQud2hpY2ggPT09ICd1bmRlZmluZWQnKT9ldmVudC5rZXlDb2RlOmV2ZW50LndoaWNoO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgY2hhcmFjdGVyIGZyb20gdGhlIGV2ZW50IGtleSBjb2RlLlxuICAgICAqIElmIHRoZSBLZXlib2FyZEV2ZW50IGRvZXMgbm90IHJlcHJlc2VudCBhIHByaW50YWJsZSBjaGFyYWN0ZXIsIHRoZW4gdGhlIGtleSBuYW1lIGlzIHVzZWQgKGllLiAnTWV0YScsICdTaGlmdCcsICdGMScsIGV0Yy4pXG4gICAgICogQGV4YW1wbGUgY2hhcmFjdGVyKDUwKSA9PiAnMidcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7S2V5Ym9hcmRFdmVudH0gZXZlbnRcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIHN0YXRpYyBjaGFyYWN0ZXIoZXZlbnQpIHtcbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgaWYgKGV2ZW50LmtleSA9PT0gJ1VuaWRlbnRpZmllZCcgfHwgZXZlbnQua2V5ID09PSB2b2lkKDApIHx8IHRoaXMuaXNTZWxlbml1bUJvdCgpKSB7XG4gICAgICAgICAgICAvL1hYWCBUaGUgc2VsZW5pdW0gZ2Vja29kcml2ZXIgZG8gbm90IHVuZGVyc3RhbmQgYGV2ZW50LmtleWAsIGhlbmNlIHdoZW4gdXNpbmcgaXQsIHdlIG5lZWQgdG8gcmVseSBvbiB0aGUgb2xkIGRlcHJlY2F0ZWQgYGtleUNvZGVgIGF0dHJpYnV0ZSwgY2YuIHVwc3RyZWFtIGlzc3VlIGh0dHBzOi8vZ2l0aHViLmNvbS9tb3ppbGxhL2dlY2tvZHJpdmVyL2lzc3Vlcy80NDBcbiAgICAgICAgICAgIC8vIFVzZSB0aGUgb2xkIGRlcHJlY2F0ZWQga2V5Q29kZSBwcm9wZXJ0eSwgaWYgdGhlIG5ldyBga2V5YCBvbmUgaXMgbm90IHN1cHBvcnRlZFxuICAgICAgICAgICAgY29uc3Qga2V5Q29kZSA9IHRoaXMua2V5Q29kZU51bWJlcihldmVudCk7XG4gICAgICAgICAgICBpZiAoa2V5Q29kZSA9PT0gQXV0b051bWVyaWNFbnVtLmtleUNvZGUuQW5kcm9pZERlZmF1bHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuQW5kcm9pZERlZmF1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IHBvdGVudGlhbFJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5mcm9tQ2hhckNvZGVLZXlDb2RlW2tleUNvZGVdO1xuICAgICAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkocG90ZW50aWFsUmVzdWx0KSkge1xuICAgICAgICAgICAgICAgIC8vIFNpbmNlIGBTdHJpbmcuZnJvbUNoYXJDb2RlYCBkbyBub3QgcmV0dXJuIG5hbWVkIGtleXMgZm9yIHNvbWUga2V5cyAoJ0VzY2FwZScgYW5kICdFbnRlcicgZm9yIGluc3RhbmNlKSwgd2UgY29udmVydCB0aGUgY2hhcmFjdGVycyB0byB0aGUga2V5IG5hbWVzXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gcG90ZW50aWFsUmVzdWx0O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGtleUNvZGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbGV0IGJyb3dzZXI7XG4gICAgICAgICAgICBzd2l0Y2ggKGV2ZW50LmtleSkge1xuICAgICAgICAgICAgICAgIC8vIE1hbmFnZXMgYWxsIHRoZSBzcGVjaWFsIGNhc2VzIGZvciBvYnNvbGV0ZSBicm93c2VycyB0aGF0IHJldHVybiB0aGUgbm9uLXN0YW5kYXJkIG5hbWVzXG4gICAgICAgICAgICAgICAgY2FzZSAnQWRkJzpcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuTnVtcGFkUGx1cztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnQXBwcyc6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkNvbnRleHRNZW51O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdDcnNlbCc6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkNyU2VsO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdEZWNpbWFsJzpcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuTnVtcGFkRG90O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdEZWwnOlxuICAgICAgICAgICAgICAgICAgICBicm93c2VyID0gdGhpcy5icm93c2VyKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICgoYnJvd3Nlci5uYW1lID09PSAnZmlyZWZveCcgJiYgYnJvd3Nlci52ZXJzaW9uIDw9IDM2KSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgKGJyb3dzZXIubmFtZSA9PT0gJ2llJyAmJiBicm93c2VyLnZlcnNpb24gPD0gOSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNwZWNpYWwgd29ya2Fyb3VuZCBmb3IgdGhlIG9ic29sZXRlIGJyb3dzZXIgSUUxMSB3aGljaCBvdXRwdXQgYSAnRGVsZXRlJyBrZXkgd2hlbiB1c2luZyB0aGUgbnVtcGFkICdkb3QnIG9uZSEgVGhpcyBmaXhlcyBpc3N1ZSAjNDAxXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHdvcmthcm91bmQgYnJlYWsgdGhlIHVzYWdlIG9mIHRoZSAnRGVsZXRlJyBrZXkgZm9yIEZpcmVmb3ggPD0zNiwgYW5kIElFOSwgc2luY2UgdGhvc2UgYnJvd3NlciBzZW5kICdEZWwnIGluc3RlYWQgb2YgJ0RlbGV0ZScsIHRoZXJlZm9yZSB3ZSBvbmx5IHVzZSBpdCBmb3IgdGhvc2Ugb2Jzb2xldGUgYnJvd3NlcnNcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkRvdDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkRlbGV0ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdEaXZpZGUnOlxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5OdW1wYWRTbGFzaDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnRG93bic6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkRvd25BcnJvdztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnRXNjJzpcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuRXNjO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdFeHNlbCc6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkV4U2VsO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdMZWZ0JzpcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuTGVmdEFycm93O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdNZXRhJzpcbiAgICAgICAgICAgICAgICBjYXNlICdTdXBlcic6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLk9TTGVmdDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnTXVsdGlwbHknOlxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5OdW1wYWRNdWx0aXBseTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnUmlnaHQnOlxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5SaWdodEFycm93O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdTcGFjZWJhcic6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLlNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdTdWJ0cmFjdCc6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLk51bXBhZE1pbnVzO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdVcCc6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLlVwQXJyb3c7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZSBub3JtYWwgY2FzZVxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBldmVudC5rZXk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhbiBvYmplY3QgY29udGFpbmluZyB0aGUgbmFtZSBhbmQgdmVyc2lvbiBvZiB0aGUgY3VycmVudCBicm93c2VyLlxuICAgICAqIEBleGFtcGxlIGBicm93c2VyVmVyc2lvbigpYCA9PiB7IG5hbWU6ICdGaXJlZm94JywgdmVyc2lvbjogJzQyJyB9XG4gICAgICogQmFzZWQgb24gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzgwODAwNTEvMjgzNDg5OFxuICAgICAqXG4gICAgICogQHJldHVybnMge3sgbmFtZTogc3RyaW5nLCB2ZXJzaW9uOiBzdHJpbmcgfX1cbiAgICAgKi9cbiAgICBzdGF0aWMgYnJvd3NlcigpIHtcbiAgICAgICAgY29uc3QgdWEgPSBuYXZpZ2F0b3IudXNlckFnZW50O1xuICAgICAgICBsZXQgdGVtO1xuICAgICAgICBsZXQgTSA9IHVhLm1hdGNoKC8ob3BlcmF8Y2hyb21lfHNhZmFyaXxmaXJlZm94fG1zaWV8dHJpZGVudCg/PVxcLykpXFwvP1xccyooXFxkKykvaSkgfHwgW107XG5cbiAgICAgICAgaWYgKC90cmlkZW50L2kudGVzdChNWzFdKSkge1xuICAgICAgICAgICAgdGVtID0gL1xcYnJ2WyA6XSsoXFxkKykvZy5leGVjKHVhKSB8fCBbXTtcbiAgICAgICAgICAgIHJldHVybiB7IG5hbWU6ICdpZScsIHZlcnNpb246ICh0ZW1bMV0gfHwgJycpIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoTVsxXSA9PT0gJ0Nocm9tZScpIHtcbiAgICAgICAgICAgIHRlbSA9IHVhLm1hdGNoKC9cXGIoT1BSfEVkZ2UpXFwvKFxcZCspLyk7XG4gICAgICAgICAgICBpZiAodGVtICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgbmFtZTogdGVtWzFdLnJlcGxhY2UoJ09QUicsICdvcGVyYScpLCB2ZXJzaW9uOiB0ZW1bMl0gfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIE0gPSBNWzJdP1tNWzFdLCBNWzJdXTpbbmF2aWdhdG9yLmFwcE5hbWUsIG5hdmlnYXRvci5hcHBWZXJzaW9uLCAnLT8nXTtcbiAgICAgICAgaWYgKCh0ZW0gPSB1YS5tYXRjaCgvdmVyc2lvblxcLyhcXGQrKS9pKSkgIT09IG51bGwpIHtcbiAgICAgICAgICAgIE0uc3BsaWNlKDEsIDEsIHRlbVsxXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4geyBuYW1lOiBNWzBdLnRvTG93ZXJDYXNlKCksIHZlcnNpb246IE1bMV0gfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiB0aGUgYnJvd3NlciBpcyBjb250cm9sbGVkIGJ5IFNlbGVuaXVtLlxuICAgICAqIE5vdGU6IFRoaXMgb25seSB3b3JrcyB3aXRoaW4gdGhlIGdlY2tvZHJpdmVyLlxuICAgICAqIGNmLiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzMzMjI1OTQ3L2Nhbi1hLXdlYnNpdGUtZGV0ZWN0LXdoZW4teW91LWFyZS11c2luZy1zZWxlbml1bS13aXRoLWNocm9tZWRyaXZlclxuICAgICAqXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzU2VsZW5pdW1Cb3QoKSB7XG4gICAgICAgIC8vIG5vaW5zcGVjdGlvbiBKU1VucmVzb2x2ZWRWYXJpYWJsZVxuICAgICAgICByZXR1cm4gd2luZG93Lm5hdmlnYXRvci53ZWJkcml2ZXIgPT09IHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgZ2l2ZW4gbnVtYmVyIGlzIG5lZ2F0aXZlLCBvciBpZiB0aGUgZ2l2ZW4gc3RyaW5nIGNvbnRhaW5zIGEgbmVnYXRpdmUgc2lnbiA6XG4gICAgICogLSBldmVyeXdoZXJlIGluIHRoZSBzdHJpbmcgKGJ5IGRlZmF1bHQpLCBvclxuICAgICAqIC0gb24gdGhlIGZpcnN0IGNoYXJhY3RlciBvbmx5IGlmIHRoZSBgY2hlY2tFdmVyeXdoZXJlYCBwYXJhbWV0ZXIgaXMgc2V0IHRvIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBOb3RlOiBgLTBgIGlzIG5vdCBhIG5lZ2F0aXZlIG51bWJlciBzaW5jZSBpdCdzIGVxdWFsIHRvIGAwYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ30gbnVtYmVyT3JOdW1lcmljU3RyaW5nIEEgTnVtYmVyLCBvciBhIG51bWJlciByZXByZXNlbnRlZCBieSBhIHN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgVGhlIHNpbmdsZSBjaGFyYWN0ZXIgdGhhdCByZXByZXNlbnQgdGhlIG5lZ2F0aXZlIHNpZ25cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGNoZWNrRXZlcnl3aGVyZSBJZiBUUlVFLCB0aGVuIHRoZSBuZWdhdGl2ZSBzaWduIGlzIHNlYXJjaCBldmVyeXdoZXJlIGluIHRoZSBudW1lcmljIHN0cmluZyAodGhpcyBpcyBuZWVkZWQgZm9yIGluc3RhbmNlIGlmIHRoZSBzdHJpbmcgaXMgJzEyMzQuNTYtJylcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNOZWdhdGl2ZShudW1iZXJPck51bWVyaWNTdHJpbmcsIG5lZ2F0aXZlU2lnbkNoYXJhY3RlciA9ICctJywgY2hlY2tFdmVyeXdoZXJlID0gdHJ1ZSkge1xuICAgICAgICBpZiAobnVtYmVyT3JOdW1lcmljU3RyaW5nID09PSBuZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG51bWJlck9yTnVtZXJpY1N0cmluZyA9PT0gJycpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bWJlcihudW1iZXJPck51bWVyaWNTdHJpbmcpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyT3JOdW1lcmljU3RyaW5nIDwgMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjaGVja0V2ZXJ5d2hlcmUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnRhaW5zKG51bWJlck9yTnVtZXJpY1N0cmluZywgbmVnYXRpdmVTaWduQ2hhcmFjdGVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLmlzTmVnYXRpdmVTdHJpY3QobnVtYmVyT3JOdW1lcmljU3RyaW5nLCBuZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGdpdmVuIHN0cmluZyBjb250YWlucyBhIG5lZ2F0aXZlIHNpZ24gb24gdGhlIGZpcnN0IGNoYXJhY3RlciAob24gdGhlIGZhciBsZWZ0KS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlIGlzTmVnYXRpdmVTdHJpY3QoJzEyMzQuNTYnKSAgICAgPT4gZmFsc2VcbiAgICAgKiBAZXhhbXBsZSBpc05lZ2F0aXZlU3RyaWN0KCcxMjM0LjU2LScpICAgID0+IGZhbHNlXG4gICAgICogQGV4YW1wbGUgaXNOZWdhdGl2ZVN0cmljdCgnLTEyMzQuNTYnKSAgICA9PiB0cnVlXG4gICAgICogQGV4YW1wbGUgaXNOZWdhdGl2ZVN0cmljdCgnLTEsMjM0LjU2IOKCrCcpID0+IHRydWVcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBudW1lcmljU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5lZ2F0aXZlU2lnbkNoYXJhY3RlciBUaGUgc2luZ2xlIGNoYXJhY3RlciB0aGF0IHJlcHJlc2VudCB0aGUgbmVnYXRpdmUgc2lnblxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIHN0YXRpYyBpc05lZ2F0aXZlU3RyaWN0KG51bWVyaWNTdHJpbmcsIG5lZ2F0aXZlU2lnbkNoYXJhY3RlciA9ICctJykge1xuICAgICAgICByZXR1cm4gbnVtZXJpY1N0cmluZy5jaGFyQXQoMCkgPT09IG5lZ2F0aXZlU2lnbkNoYXJhY3RlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSB2ZXJ5IGZpcnN0IGNoYXJhY3RlciBpcyB0aGUgb3BlbmluZyBicmFja2V0LCBhbmQgaWYgdGhlIHJlc3Qgb2YgdGhlIGB2YWx1ZVN0cmluZ2AgYWxzbyBoYXMgdGhlIGNsb3NpbmcgYnJhY2tldC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZVN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBsZWZ0QnJhY2tldFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSByaWdodEJyYWNrZXRcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNOZWdhdGl2ZVdpdGhCcmFja2V0cyh2YWx1ZVN0cmluZywgbGVmdEJyYWNrZXQsIHJpZ2h0QnJhY2tldCkge1xuICAgICAgICByZXR1cm4gdmFsdWVTdHJpbmcuY2hhckF0KDApID09PSBsZWZ0QnJhY2tldCAmJiB0aGlzLmNvbnRhaW5zKHZhbHVlU3RyaW5nLCByaWdodEJyYWNrZXQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGZvcm1hdHRlZCBvciB1bmZvcm1hdHRlZCBudW1lcmljIHN0cmluZyByZXByZXNlbnQgdGhlIHZhbHVlIDAgKGllLiAnMCwwMCDigqwnKSwgb3IgaXMgZW1wdHkgKCcg4oKsJykuXG4gICAgICogVGhpcyB3b3JrcyBzaW5jZSB3ZSB0ZXN0IGlmIHRoZXJlIGFyZSBhbnkgbnVtYmVycyBmcm9tIDEgdG8gOSBpbiB0aGUgc3RyaW5nLiBJZiB0aGVyZSBpcyBub25lLCB0aGVuIHRoZSBudW1iZXIgaXMgemVybyAob3IgdGhlIHN0cmluZyBpcyBlbXB0eSkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbnVtZXJpY1N0cmluZ1xuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIHN0YXRpYyBpc1plcm9Pckhhc05vVmFsdWUobnVtZXJpY1N0cmluZykge1xuICAgICAgICByZXR1cm4gISgvWzEtOV0vZykudGVzdChudW1lcmljU3RyaW5nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIG5lZ2F0aXZlIHZlcnNpb24gb2YgdGhlIHZhbHVlIChyZXByZXNlbnRlZCBhcyBhIHN0cmluZykgZ2l2ZW4gYXMgYSBwYXJhbWV0ZXIuXG4gICAgICogVGhlIG51bWVyaWMgc3RyaW5nIGlzIGEgdmFsaWQgSmF2YXNjcmlwdCBudW1iZXIgd2hlbiB0eXBlY2FzdCB0byBhIGBOdW1iZXJgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgc3RhdGljIHNldFJhd05lZ2F0aXZlU2lnbih2YWx1ZSkge1xuICAgICAgICBpZiAoIXRoaXMuaXNOZWdhdGl2ZVN0cmljdCh2YWx1ZSwgJy0nKSkge1xuICAgICAgICAgICAgcmV0dXJuIGAtJHt2YWx1ZX1gO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlcGxhY2UgdGhlIGNoYXJhY3RlciBhdCB0aGUgcG9zaXRpb24gYGluZGV4YCBpbiB0aGUgc3RyaW5nIGBzdHJpbmdgIGJ5IHRoZSBjaGFyYWN0ZXIocykgYG5ld0NoYXJhY3RlcmAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nXG4gICAgICogQHBhcmFtIHtpbnR9IGluZGV4XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5ld0NoYXJhY3RlclxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgc3RhdGljIHJlcGxhY2VDaGFyQXQoc3RyaW5nLCBpbmRleCwgbmV3Q2hhcmFjdGVyKSB7XG4gICAgICAgIHJldHVybiBgJHtzdHJpbmcuc3Vic3RyKDAsIGluZGV4KX0ke25ld0NoYXJhY3Rlcn0ke3N0cmluZy5zdWJzdHIoaW5kZXggKyBuZXdDaGFyYWN0ZXIubGVuZ3RoKX1gO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgdmFsdWUgY2xhbXBlZCB0byB0aGUgbmVhcmVzdCBtaW5pbXVtL21heGltdW0gdmFsdWUsIGFzIGRlZmluZWQgaW4gdGhlIHNldHRpbmdzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSB2YWx1ZVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgc3RhdGljIGNsYW1wVG9SYW5nZUxpbWl0cyh2YWx1ZSwgc2V0dGluZ3MpIHtcbiAgICAgICAgLy9YWFggVGhpcyBmdW5jdGlvbiBhbHdheXMgYXNzdW1lIGBzZXR0aW5ncy5taW5pbXVtVmFsdWVgIGlzIGxvd2VyIHRoYW4gYHNldHRpbmdzLm1heGltdW1WYWx1ZWBcbiAgICAgICAgcmV0dXJuIE1hdGgubWF4KHNldHRpbmdzLm1pbmltdW1WYWx1ZSwgTWF0aC5taW4oc2V0dGluZ3MubWF4aW11bVZhbHVlLCB2YWx1ZSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgbnVtYmVyIG9mIG51bWJlciBvciBkb3QgY2hhcmFjdGVycyBvbiB0aGUgbGVmdCBzaWRlIG9mIHRoZSBjYXJldCwgaW4gYSBmb3JtYXR0ZWQgbnVtYmVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGZvcm1hdHRlZE51bWJlclN0cmluZ1xuICAgICAqIEBwYXJhbSB7aW50fSBjYXJldFBvc2l0aW9uIFRoaXMgbXVzdCBiZSBhIHBvc2l0aXZlIGludGVnZXJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZGVjaW1hbENoYXJhY3RlclxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgc3RhdGljIGNvdW50TnVtYmVyQ2hhcmFjdGVyc09uVGhlQ2FyZXRMZWZ0U2lkZShmb3JtYXR0ZWROdW1iZXJTdHJpbmcsIGNhcmV0UG9zaXRpb24sIGRlY2ltYWxDaGFyYWN0ZXIpIHtcbiAgICAgICAgLy8gSGVyZSB3ZSBjb3VudCB0aGUgZG90IGFuZCByZXBvcnQgaXQgYXMgYSBudW1iZXIgY2hhcmFjdGVyIHRvbywgc2luY2UgaXQgd2lsbCAnc3RheScgaW4gdGhlIEphdmFzY3JpcHQgbnVtYmVyIHdoZW4gdW5mb3JtYXR0ZWRcbiAgICAgICAgY29uc3QgbnVtYmVyRG90T3JOZWdhdGl2ZVNpZ24gPSBuZXcgUmVnRXhwKGBbMC05JHtkZWNpbWFsQ2hhcmFjdGVyfS1dYCk7IC8vIE5vIG5lZWQgdG8gZXNjYXBlIHRoZSBkZWNpbWFsIGNoYXJhY3RlciBoZXJlLCBzaW5jZSBpdCdzIGluIGBbXWBcblxuICAgICAgICBsZXQgbnVtYmVyRG90QW5kTmVnYXRpdmVTaWduQ291bnQgPSAwO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNhcmV0UG9zaXRpb247IGkrKykge1xuICAgICAgICAgICAgLy8gVGVzdCBpZiB0aGUgY2hhcmFjdGVyIGlzIGEgbnVtYmVyLCBhIGRvdCBvciBhbiBoeXBoZW4uIElmIGl0IGlzLCBjb3VudCBpdCwgb3RoZXJ3aXNlIGlnbm9yZSBpdFxuICAgICAgICAgICAgaWYgKG51bWJlckRvdE9yTmVnYXRpdmVTaWduLnRlc3QoZm9ybWF0dGVkTnVtYmVyU3RyaW5nW2ldKSkge1xuICAgICAgICAgICAgICAgIG51bWJlckRvdEFuZE5lZ2F0aXZlU2lnbkNvdW50Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVtYmVyRG90QW5kTmVnYXRpdmVTaWduQ291bnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV2FsayB0aGUgYGZvcm1hdHRlZE51bWJlclN0cmluZ2AgZnJvbSBsZWZ0IHRvIHJpZ2h0LCBvbmUgY2hhciBieSBvbmUsIGNvdW50aW5nIHRoZSBgZm9ybWF0dGVkTnVtYmVyU3RyaW5nSW5kZXhgLlxuICAgICAqIElmIHRoZSBjaGFyIGlzIGluIHRoZSBgcmF3TnVtYmVyU3RyaW5nYCAoc3RhcnRpbmcgYXQgaW5kZXggMCksIHRoZW4gYHJhd051bWJlclN0cmluZ0luZGV4KytgLCBhbmQgY29udGludWUgdW50aWxcbiAgICAgKiB0aGVyZSBpcyBubyBtb3JlIGNoYXJhY3RlcnMgaW4gYHJhd051bWJlclN0cmluZ2ApIG9yIHRoYXQgYHJhd051bWJlclN0cmluZ0luZGV4ID09PSBjYXJldFBvc2l0aW9uSW5SYXdWYWx1ZWAuXG4gICAgICogV2hlbiB5b3Ugc3RvcCwgdGhlIGBmb3JtYXR0ZWROdW1iZXJTdHJpbmdJbmRleGAgaXMgdGhlIHBvc2l0aW9uIHdoZXJlIHRoZSBjYXJldCBzaG91bGQgYmUgc2V0LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiAxMjM0NTY3fDg5LjAxICAgOiBwb3NpdGlvbiA3IChyYXdOdW1iZXJTdHJpbmcpXG4gICAgICogMTIzLjQ1Ni43fDg5LDAxIDogcG9zaXRpb24gOSAoZm9ybWF0dGVkTnVtYmVyU3RyaW5nKVxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHJhd051bWJlclN0cmluZ1xuICAgICAqIEBwYXJhbSB7aW50fSBjYXJldFBvc2l0aW9uSW5SYXdWYWx1ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBmb3JtYXR0ZWROdW1iZXJTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZGVjaW1hbENoYXJhY3RlclxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyBmaW5kQ2FyZXRQb3NpdGlvbkluRm9ybWF0dGVkTnVtYmVyKHJhd051bWJlclN0cmluZywgY2FyZXRQb3NpdGlvbkluUmF3VmFsdWUsIGZvcm1hdHRlZE51bWJlclN0cmluZywgZGVjaW1hbENoYXJhY3Rlcikge1xuICAgICAgICBjb25zdCBmb3JtYXR0ZWROdW1iZXJTdHJpbmdTaXplID0gZm9ybWF0dGVkTnVtYmVyU3RyaW5nLmxlbmd0aDtcbiAgICAgICAgY29uc3QgcmF3TnVtYmVyU3RyaW5nU2l6ZSA9IHJhd051bWJlclN0cmluZy5sZW5ndGg7XG5cbiAgICAgICAgbGV0IGZvcm1hdHRlZE51bWJlclN0cmluZ0luZGV4O1xuICAgICAgICBsZXQgcmF3TnVtYmVyU3RyaW5nSW5kZXggPSAwO1xuICAgICAgICBmb3IgKGZvcm1hdHRlZE51bWJlclN0cmluZ0luZGV4ID0gMDtcbiAgICAgICAgICAgIGZvcm1hdHRlZE51bWJlclN0cmluZ0luZGV4IDwgZm9ybWF0dGVkTnVtYmVyU3RyaW5nU2l6ZSAmJlxuICAgICAgICAgICAgcmF3TnVtYmVyU3RyaW5nSW5kZXggPCByYXdOdW1iZXJTdHJpbmdTaXplICYmXG4gICAgICAgICAgICByYXdOdW1iZXJTdHJpbmdJbmRleCA8IGNhcmV0UG9zaXRpb25JblJhd1ZhbHVlO1xuICAgICAgICAgICAgZm9ybWF0dGVkTnVtYmVyU3RyaW5nSW5kZXgrKykge1xuICAgICAgICAgICAgaWYgKHJhd051bWJlclN0cmluZ1tyYXdOdW1iZXJTdHJpbmdJbmRleF0gPT09IGZvcm1hdHRlZE51bWJlclN0cmluZ1tmb3JtYXR0ZWROdW1iZXJTdHJpbmdJbmRleF0gfHxcbiAgICAgICAgICAgICAgICAocmF3TnVtYmVyU3RyaW5nW3Jhd051bWJlclN0cmluZ0luZGV4XSA9PT0gJy4nICYmIGZvcm1hdHRlZE51bWJlclN0cmluZ1tmb3JtYXR0ZWROdW1iZXJTdHJpbmdJbmRleF0gPT09IGRlY2ltYWxDaGFyYWN0ZXIpKSB7XG4gICAgICAgICAgICAgICAgcmF3TnVtYmVyU3RyaW5nSW5kZXgrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmb3JtYXR0ZWROdW1iZXJTdHJpbmdJbmRleDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb3VudCB0aGUgbnVtYmVyIG9mIG9jY3VycmVuY2Ugb2YgdGhlIGdpdmVuIGNoYXJhY3RlciwgaW4gdGhlIGdpdmVuIHRleHQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gY2hhcmFjdGVyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHRleHRcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqL1xuICAgIHN0YXRpYyBjb3VudENoYXJJblRleHQoY2hhcmFjdGVyLCB0ZXh0KSB7XG4gICAgICAgIGxldCBjaGFyQ291bnRlciA9IDA7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGV4dC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHRleHRbaV0gPT09IGNoYXJhY3Rlcikge1xuICAgICAgICAgICAgICAgIGNoYXJDb3VudGVyKys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY2hhckNvdW50ZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBpbmRleCB0aGF0IGNhbiBiZSB1c2VkIHRvIHNldCB0aGUgY2FyZXQgcG9zaXRpb24uXG4gICAgICogVGhpcyB0YWtlcyBpbnRvIGFjY291bnQgdGhhdCB0aGUgcG9zaXRpb24gaXMgc3RhcnRpbmcgYXQgJzAnLCBub3QgMS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7aW50fSBjaGFyYWN0ZXJDb3VudFxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgc3RhdGljIGNvbnZlcnRDaGFyYWN0ZXJDb3VudFRvSW5kZXhQb3NpdGlvbihjaGFyYWN0ZXJDb3VudCkge1xuICAgICAgICByZXR1cm4gTWF0aC5tYXgoY2hhcmFjdGVyQ291bnQsIGNoYXJhY3RlckNvdW50IC0gMSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3Jvc3MgYnJvd3NlciByb3V0aW5lIGZvciBnZXR0aW5nIHNlbGVjdGVkIHJhbmdlL2N1cnNvciBwb3NpdGlvbi5cbiAgICAgKiBOb3RlOiB0aGlzIGFsc28gd29ya3Mgd2l0aCBlZGdlIGNhc2VzIGxpa2UgY29udGVudGVkaXRhYmxlLWVuYWJsZWQgZWxlbWVudHMsIGFuZCBoaWRkZW4gaW5wdXRzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MSW5wdXRFbGVtZW50fEV2ZW50VGFyZ2V0fSBlbGVtZW50XG4gICAgICogQHJldHVybnMge3t9fVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRFbGVtZW50U2VsZWN0aW9uKGVsZW1lbnQpIHtcbiAgICAgICAgY29uc3QgcG9zaXRpb24gPSB7fTtcblxuICAgICAgICBsZXQgaXNTZWxlY3Rpb25TdGFydFVuZGVmaW5lZDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlzU2VsZWN0aW9uU3RhcnRVbmRlZmluZWQgPSB0aGlzLmlzVW5kZWZpbmVkKGVsZW1lbnQuc2VsZWN0aW9uU3RhcnQpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgaXNTZWxlY3Rpb25TdGFydFVuZGVmaW5lZCA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmIChpc1NlbGVjdGlvblN0YXJ0VW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2VsZWN0aW9uID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHNlbGVjdGlvbkluZm8gPSBzZWxlY3Rpb24uZ2V0UmFuZ2VBdCgwKTtcbiAgICAgICAgICAgICAgICBwb3NpdGlvbi5zdGFydCA9IHNlbGVjdGlvbkluZm8uc3RhcnRPZmZzZXQ7XG4gICAgICAgICAgICAgICAgcG9zaXRpb24uZW5kID0gc2VsZWN0aW9uSW5mby5lbmRPZmZzZXQ7XG4gICAgICAgICAgICAgICAgcG9zaXRpb24ubGVuZ3RoID0gcG9zaXRpb24uZW5kIC0gcG9zaXRpb24uc3RhcnQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uLnN0YXJ0ID0gZWxlbWVudC5zZWxlY3Rpb25TdGFydDtcbiAgICAgICAgICAgICAgICBwb3NpdGlvbi5lbmQgPSBlbGVtZW50LnNlbGVjdGlvbkVuZDtcbiAgICAgICAgICAgICAgICBwb3NpdGlvbi5sZW5ndGggPSBwb3NpdGlvbi5lbmQgLSBwb3NpdGlvbi5zdGFydDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIC8vIE1hbmFnZXMgdGhlIGNhc2VzIHdoZXJlIDpcbiAgICAgICAgICAgIC8vIC0gdGhlICdjb250ZW50ZWRpdGFibGUnIGVsZW1lbnRzIHRoYXQgaGF2ZSBubyBzZWxlY3Rpb25zXG4gICAgICAgICAgICAvLyAtIHRoZSA8aW5wdXQ+IGVsZW1lbnQgaXMgb2YgdHlwZSAnaGlkZGVuJ1xuICAgICAgICAgICAgcG9zaXRpb24uc3RhcnQgPSAwO1xuICAgICAgICAgICAgcG9zaXRpb24uZW5kID0gMDtcbiAgICAgICAgICAgIHBvc2l0aW9uLmxlbmd0aCA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcG9zaXRpb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3Jvc3MgYnJvd3NlciByb3V0aW5lIGZvciBzZXR0aW5nIHNlbGVjdGVkIHJhbmdlL2N1cnNvciBwb3NpdGlvblxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MSW5wdXRFbGVtZW50fEV2ZW50VGFyZ2V0fSBlbGVtZW50XG4gICAgICogQHBhcmFtIHtpbnR9IHN0YXJ0XG4gICAgICogQHBhcmFtIHtpbnR8bnVsbH0gZW5kXG4gICAgICovXG4gICAgc3RhdGljIHNldEVsZW1lbnRTZWxlY3Rpb24oZWxlbWVudCwgc3RhcnQsIGVuZCA9IG51bGwpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KGVuZCkpIHtcbiAgICAgICAgICAgIGVuZCA9IHN0YXJ0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuaXNJbnB1dEVsZW1lbnQoZWxlbWVudCkpIHtcbiAgICAgICAgICAgIGVsZW1lbnQuc2V0U2VsZWN0aW9uUmFuZ2Uoc3RhcnQsIGVuZCk7XG4gICAgICAgIH0gZWxzZSBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChlbGVtZW50LmZpcnN0Q2hpbGQpKSB7XG4gICAgICAgICAgICBjb25zdCByYW5nZSA9IGRvY3VtZW50LmNyZWF0ZVJhbmdlKCk7XG4gICAgICAgICAgICByYW5nZS5zZXRTdGFydChlbGVtZW50LmZpcnN0Q2hpbGQsIHN0YXJ0KTtcbiAgICAgICAgICAgIHJhbmdlLnNldEVuZChlbGVtZW50LmZpcnN0Q2hpbGQsIGVuZCk7XG4gICAgICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSB3aW5kb3cuZ2V0U2VsZWN0aW9uKCk7XG4gICAgICAgICAgICBzZWxlY3Rpb24ucmVtb3ZlQWxsUmFuZ2VzKCk7XG4gICAgICAgICAgICBzZWxlY3Rpb24uYWRkUmFuZ2UocmFuZ2UpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRnVuY3Rpb24gdGhhdCB0aHJvdyBlcnJvciBtZXNzYWdlc1xuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcbiAgICAgKiBAdGhyb3dzXG4gICAgICovXG4gICAgc3RhdGljIHRocm93RXJyb3IobWVzc2FnZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRnVuY3Rpb24gdGhhdCBkaXNwbGF5IGEgd2FybmluZyBtZXNzYWdlcywgYWNjb3JkaW5nIHRvIHRoZSBkZWJ1ZyBsZXZlbC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gICAgICogQHBhcmFtIHtib29sZWFufSBzaG93V2FybmluZyBJZiBGQUxTRSwgdGhlbiB0aGUgd2FybmluZyBtZXNzYWdlIGlzIG5vdCBkaXNwbGF5ZWRcbiAgICAgKi9cbiAgICBzdGF0aWMgd2FybmluZyhtZXNzYWdlLCBzaG93V2FybmluZyA9IHRydWUpIHtcbiAgICAgICAgaWYgKHNob3dXYXJuaW5nKSB7XG4gICAgICAgICAgICAvKiBlc2xpbnQgbm8tY29uc29sZTogMCAqL1xuICAgICAgICAgICAgY29uc29sZS53YXJuKGBXYXJuaW5nOiAke21lc3NhZ2V9YCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBnaXZlbiBldmVudCBpcyBhIHdoZWVsdXAgZXZlbnRcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7V2hlZWxFdmVudH0gd2hlZWxFdmVudFxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIHN0YXRpYyBpc1doZWVsVXBFdmVudCh3aGVlbEV2ZW50KSB7XG4gICAgICAgIGlmICghd2hlZWxFdmVudC5kZWx0YVkpIHtcbiAgICAgICAgICAgIHRoaXMudGhyb3dFcnJvcihgVGhlIGV2ZW50IHBhc3NlZCBhcyBhIHBhcmFtZXRlciBpcyBub3QgYSB2YWxpZCB3aGVlbCBldmVudCwgJyR7d2hlZWxFdmVudC50eXBlfScgZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gd2hlZWxFdmVudC5kZWx0YVkgPCAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGdpdmVuIGV2ZW50IGlzIGEgd2hlZWxkb3duIGV2ZW50XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1doZWVsRXZlbnR9IHdoZWVsRXZlbnRcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNXaGVlbERvd25FdmVudCh3aGVlbEV2ZW50KSB7XG4gICAgICAgIGlmICghd2hlZWxFdmVudC5kZWx0YVkpIHtcbiAgICAgICAgICAgIHRoaXMudGhyb3dFcnJvcihgVGhlIGV2ZW50IHBhc3NlZCBhcyBhIHBhcmFtZXRlciBpcyBub3QgYSB2YWxpZCB3aGVlbCBldmVudCwgJyR7d2hlZWxFdmVudC50eXBlfScgZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gd2hlZWxFdmVudC5kZWx0YVkgPiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgZ2l2ZW4gcmF3IHZhbHVlIHRydW5jYXRlZCBhdCB0aGUgZ2l2ZW4gbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIGBkZWNpbWFsUGxhY2VzYC5cbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGRvZXMgbm90IHJvdW5kIHRoZSB2YWx1ZS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogZm9yY2VEZWNpbWFsUGxhY2VzKDEyMy40NTY3OCwgMCkgLT4gJzEyMy40NTY3OCdcbiAgICAgKiBmb3JjZURlY2ltYWxQbGFjZXMoMTIzLjQ1Njc4LCAxKSAtPiAnMTIzLjQnXG4gICAgICogZm9yY2VEZWNpbWFsUGxhY2VzKDEyMy40NTY3OCwgMikgLT4gJzEyMy40NSdcbiAgICAgKiBmb3JjZURlY2ltYWxQbGFjZXMoMTIzLjQ1Njc4LCAzKSAtPiAnMTIzLjQ1NidcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZVxuICAgICAqIEBwYXJhbSB7aW50fSBkZWNpbWFsUGxhY2VzXG4gICAgICogQHJldHVybnMge251bWJlcnxzdHJpbmd9XG4gICAgICovXG4gICAgc3RhdGljIGZvcmNlRGVjaW1hbFBsYWNlcyh2YWx1ZSwgZGVjaW1hbFBsYWNlcykge1xuICAgICAgICAvLyBXZSBjb3VsZCBtYWtlIHN1cmUgYGRlY2ltYWxQbGFjZXNgIGlzIGFuIGludGVnZXIgYW5kIHBvc2l0aXZlLCBidXQgd2UnbGwgbGVhdmUgdGhhdCB0byB0aGUgZGV2IGNhbGxpbmcgdGhpcyBmdW5jdGlvbi5cbiAgICAgICAgY29uc3QgW2ludGVnZXJQYXJ0LCBkZWNpbWFsUGFydF0gPSBTdHJpbmcodmFsdWUpLnNwbGl0KCcuJyk7XG4gICAgICAgIGlmICghZGVjaW1hbFBhcnQpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBgJHtpbnRlZ2VyUGFydH0uJHtkZWNpbWFsUGFydC5zdWJzdHIoMCwgZGVjaW1hbFBsYWNlcyl9YDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlICduZWFyZXN0IHJvdW5kZWQnIHZhbHVlLCBhY2NvcmRpbmcgdG8gdGhlIGdpdmVuIHN0ZXAgc2l6ZS5cbiAgICAgKiBAZXhhbXBsZSByb3VuZFRvTmVhcmVzdCgyNjQ3ODksIDEwMDAwKSkgPT4gMjYwMDAwXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gc3RlcFBsYWNlXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgc3RhdGljIHJvdW5kVG9OZWFyZXN0KHZhbHVlLCBzdGVwUGxhY2UgPSAxMDAwKSB7XG4gICAgICAgIGlmICgwID09PSB2YWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3RlcFBsYWNlID09PSAwKSB7XG4gICAgICAgICAgICB0aGlzLnRocm93RXJyb3IoJ1RoZSBgc3RlcFBsYWNlYCB1c2VkIHRvIHJvdW5kIGlzIGVxdWFsIHRvIGAwYC4gVGhpcyB2YWx1ZSBtdXN0IG5vdCBiZSBlcXVhbCB0byB6ZXJvLicpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIE1hdGgucm91bmQodmFsdWUgLyBzdGVwUGxhY2UpICogc3RlcFBsYWNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgJ25lYXJlc3Qgcm91bmRlZCcgdmFsdWUgYnkgYXV0b21hdGljYWxseSBhZGRpbmcgb3Igc3VidHJhY3RpbmcgdGhlIGNhbGN1bGF0ZWQgb2Zmc2V0IHRvIHRoZSBpbml0aWFsIHZhbHVlLlxuICAgICAqIFRoaXMgaXMgZG9uZSB3aXRob3V0IGhhdmluZyB0byBwYXNzIGEgc3RlcCB0byB0aGlzIGZ1bmN0aW9uLCBhbmQgYmFzZWQgb24gdGhlIHNpemUgb2YgdGhlIGdpdmVuIGB2YWx1ZWAuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZSAgICAgICAgICAgICAgICAgICAgQ2FsY3VsYXRlZCBvZmZzZXRcbiAgICAgKiAgICAgICAgICAgMSAtPiAgICAgICAgICAgMSAoMSlcbiAgICAgKiAgICAgICAgICAxNCAtPiAgICAgICAgICAxMCAoMTApXG4gICAgICogICAgICAgICAxNDMgLT4gICAgICAgICAxNDAgKDEwKVxuICAgICAqICAgICAgIDEuMjc4IC0+ICAgICAgIDEuMzAwICgxMDApXG4gICAgICogICAgICAyOC40NTYgLT4gICAgICAyOC41MDAgKDEwMClcbiAgICAgKiAgICAgMjc2LjM0NSAtPiAgICAgMjc2LjAwMCAoMS4wMDApXG4gICAgICogICA0LjUzNC4wNjEgLT4gICA0LjUzMC4wMDAgKDEwLjAwMClcbiAgICAgKiAgNjYuNzIzLjg0NCAtPiAgNjYuNzAwLjAwMCAoMTAwLjAwMClcbiAgICAgKiAyNTcuODMzLjQxMSAtPiAyNTguMDAwLjAwMCAoMS4wMDAuMDAwKVxuICAgICAqXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICBJbml0aWFsICAgQWRkZWQgICBPZmZzZXRcbiAgICAgKiAyIGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA6IDEuMTIgICAtPiAyLjAwICAgKDEpXG4gICAgICogMyBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgOiAxLjEyMyAgLT4gMi4wMDAgICgxKVxuICAgICAqXG4gICAgICogU3BlY2lhbCBjYXNlIHdoZW4gdGhlIGB2YWx1ZWAgdG8gcm91bmQgaXMgYmV0d2VlbiAtMSBhbmQgMSwgZXhjbHVkZWQgOlxuICAgICAqIEBleGFtcGxlXG4gICAgICogICAgIE51bWJlciBvZiAgICAgICAgICAgICBJbml0aWFsICAgUmVzdWx0ICBDYWxjdWxhdGVkXG4gICAgICogICAgIGRlY2ltYWwgcGxhY2VzICAgICAgICB2YWx1ZSAgICAgKGFkZCkgICBvZmZzZXRcbiAgICAgKiAyIGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA6IDAuMTIgICAtPiAwLjEzICAgICgwLjAxKSA6IE1hdGgucG93KDEwLCAtMilcbiAgICAgKiAyIGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA6IDAuMDEgICAtPiAwLjAyICAgICgwLjAxKVxuICAgICAqIDIgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDogMC4wMCAgIC0+IDAuMDEgICAgKDAuMDEpXG4gICAgICpcbiAgICAgKiAzIGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA6IDAuMTIzICAtPiAwLjEzMyAgICgwLjAxKSAgOiBNYXRoLnBvdygxMCwgLTIpXG4gICAgICogMyBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgOiAwLjAxMiAgLT4gMC4wMTMgICAoMC4wMDEpIDogTWF0aC5wb3coMTAsIC0zKVxuICAgICAqIDMgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDogMC4wMDEgIC0+IDAuMDAxICAgKDAuMDAxKVxuICAgICAqIDMgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDogMC4wMDAgIC0+IDAuMDAxICAgKDAuMDAxKVxuICAgICAqXG4gICAgICogNCBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgOiAwLjQxMjMgLT4gMC40MjAwICAoMC4wMSkgICA6IE1hdGgucG93KDEwLCAtMilcbiAgICAgKiA0IGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA6IDAuMDQxMiAtPiAwLjA0MjAgICgwLjAwMSkgIDogTWF0aC5wb3coMTAsIC0zKVxuICAgICAqIDQgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDogMC4wMDQxIC0+IDAuMDA0MiAgKDAuMDAwMSkgOiBNYXRoLnBvdygxMCwgLTQpXG4gICAgICogNCBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgOiAwLjAwMDQgLT4gMC4wMDA1ICAoMC4wMDAxKVxuICAgICAqIDQgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDogMC4wMDAwIC0+IDAuMDAwMSAgKDAuMDAwMSlcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNBZGRpdGlvblxuICAgICAqIEBwYXJhbSB7aW50fSBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgVGhlIHByZWNpc2lvbiBuZWVkZWQgYnkgdGhlIGByYXdWYWx1ZWBcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBzdGF0aWMgbW9kaWZ5QW5kUm91bmRUb05lYXJlc3RBdXRvKHZhbHVlLCBpc0FkZGl0aW9uLCBkZWNpbWFsUGxhY2VzUmF3VmFsdWUpIHtcbiAgICAgICAgdmFsdWUgPSBOdW1iZXIodGhpcy5mb3JjZURlY2ltYWxQbGFjZXModmFsdWUsIGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSkpOyAvLyBNYWtlIHN1cmUgdGhhdCAnMC4xMzAwMDAwMDAwMScgaXMgY29udmVydGVkIHRvIHRoZSBudW1iZXIgb2YgcmF3VmFsdWUgZGVjaW1hbCBwbGFjZXMgJzAuMTMnXG5cbiAgICAgICAgY29uc3QgYWJzVmFsdWUgPSBNYXRoLmFicyh2YWx1ZSk7XG4gICAgICAgIGlmIChhYnNWYWx1ZSA+PSAwICYmIGFic1ZhbHVlIDwgMSkge1xuICAgICAgICAgICAgY29uc3QgcmF3VmFsdWVNaW5pbXVtT2Zmc2V0ID0gTWF0aC5wb3coMTAsIC1kZWNpbWFsUGxhY2VzUmF3VmFsdWUpO1xuICAgICAgICAgICAgaWYgKHZhbHVlID09PSAwKSB7XG4gICAgICAgICAgICAgICAgLy8gNCBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgOiAwLjAwMDAgLT4gMC4wMDAxICgwLjAwMDEpXG4gICAgICAgICAgICAgICAgcmV0dXJuIChpc0FkZGl0aW9uKT9yYXdWYWx1ZU1pbmltdW1PZmZzZXQ6LXJhd1ZhbHVlTWluaW11bU9mZnNldDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IG9mZnNldDtcbiAgICAgICAgICAgIGNvbnN0IG1pbmltdW1PZmZzZXRGaXJzdERlY2ltYWxQbGFjZUluZGV4ID0gZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlO1xuICAgICAgICAgICAgLy8gRmluZCB3aGVyZSBpcyB0aGUgZmlyc3Qgbm9uLXplcm8gZGVjaW1hbCBwbGFjZXNcbiAgICAgICAgICAgIGNvbnN0IGluZGV4Rmlyc3ROb25aZXJvRGVjaW1hbFBsYWNlID0gdGhpcy5pbmRleEZpcnN0Tm9uWmVyb0RlY2ltYWxQbGFjZSh2YWx1ZSk7XG4gICAgICAgICAgICBpZiAoaW5kZXhGaXJzdE5vblplcm9EZWNpbWFsUGxhY2UgPj0gbWluaW11bU9mZnNldEZpcnN0RGVjaW1hbFBsYWNlSW5kZXggLSAxKSB7XG4gICAgICAgICAgICAgICAgLyogNCBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgOiAwLjAwNDEgLT4gMC4wMDQyICgwLjAwMDEpIDogTWF0aC5wb3coMTAsIC00KVxuICAgICAgICAgICAgICAgICAqIDQgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDogMC4wMDA0IC0+IDAuMDAwNSAoMC4wMDAxKVxuICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgIG9mZnNldCA9IHJhd1ZhbHVlTWluaW11bU9mZnNldDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgb2Zmc2V0ID0gTWF0aC5wb3coMTAsIC0oaW5kZXhGaXJzdE5vblplcm9EZWNpbWFsUGxhY2UgKyAxKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgICAgICBpZiAoaXNBZGRpdGlvbikge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlICsgb2Zmc2V0O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSB2YWx1ZSAtIG9mZnNldDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHRoaXMucm91bmRUb05lYXJlc3QocmVzdWx0LCBvZmZzZXQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gRm9yIHZhbHVlcyA+PSAxXG4gICAgICAgICAgICB2YWx1ZSA9IHBhcnNlSW50KHZhbHVlLCAxMCk7XG4gICAgICAgICAgICBjb25zdCBsZW5ndGhWYWx1ZSA9IE1hdGguYWJzKHZhbHVlKS50b1N0cmluZygpLmxlbmd0aDsgLy8gYE1hdGguYWJzKClgIGlzIG5lZWRlZCBoZXJlIHRvIG9taXQgdGhlIG5lZ2F0aXZlIHNpZ24gJy0nIGluIGNhc2Ugb2YgYSBuZWdhdGl2ZSB2YWx1ZVxuXG4gICAgICAgICAgICBsZXQgcG93O1xuICAgICAgICAgICAgc3dpdGNoIChsZW5ndGhWYWx1ZSkge1xuICAgICAgICAgICAgICAgIC8vIFNwZWNpYWwgY2FzZXMgZm9yIHNtYWxsIG51bWJlcnNcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIHBvdyA9IDA7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIHBvdyA9IDE7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgIHBvdyA9IDI7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIC8vIERlZmF1bHQgYmVoYXZpb3JcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBwb3cgPSBsZW5ndGhWYWx1ZSAtIDM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBvZmZzZXQgPSBNYXRoLnBvdygxMCwgcG93KTtcblxuICAgICAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgICAgIGlmIChpc0FkZGl0aW9uKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWUgKyBvZmZzZXQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlIC0gb2Zmc2V0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAocmVzdWx0IDw9IDEwICYmIHJlc3VsdCA+PSAtMTApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yb3VuZFRvTmVhcmVzdChyZXN1bHQsIG9mZnNldCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlICduZWFyZXN0IHJvdW5kZWQnIHZhbHVlIGF1dG9tYXRpY2FsbHkgYnkgYWRkaW5nIHRoZSBjYWxjdWxhdGVkIG9mZnNldCB0byB0aGUgaW5pdGlhbCB2YWx1ZS5cbiAgICAgKiBUaGlzIHdpbGwgbGltaXQgdGhlIHJlc3VsdCB0byB0aGUgZ2l2ZW4gbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIGBkZWNpbWFsUGxhY2VzTGltaXRgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gICAgICogQHBhcmFtIHtpbnR9IGRlY2ltYWxQbGFjZXNMaW1pdFxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRBbmRSb3VuZFRvTmVhcmVzdEF1dG8odmFsdWUsIGRlY2ltYWxQbGFjZXNMaW1pdCkge1xuICAgICAgICByZXR1cm4gdGhpcy5tb2RpZnlBbmRSb3VuZFRvTmVhcmVzdEF1dG8odmFsdWUsIHRydWUsIGRlY2ltYWxQbGFjZXNMaW1pdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSAnbmVhcmVzdCByb3VuZGVkJyB2YWx1ZSBhdXRvbWF0aWNhbGx5IGJ5IHN1YnRyYWN0aW5nIHRoZSBjYWxjdWxhdGVkIG9mZnNldCB0byB0aGUgaW5pdGlhbCB2YWx1ZS5cbiAgICAgKiBUaGlzIHdpbGwgbGltaXQgdGhlIHJlc3VsdCB0byB0aGUgZ2l2ZW4gbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIGBkZWNpbWFsUGxhY2VzTGltaXRgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gICAgICogQHBhcmFtIHtpbnR9IGRlY2ltYWxQbGFjZXNMaW1pdFxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyBzdWJ0cmFjdEFuZFJvdW5kVG9OZWFyZXN0QXV0byh2YWx1ZSwgZGVjaW1hbFBsYWNlc0xpbWl0KSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1vZGlmeUFuZFJvdW5kVG9OZWFyZXN0QXV0byh2YWx1ZSwgZmFsc2UsIGRlY2ltYWxQbGFjZXNMaW1pdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGFrZSBhbiBhcmFiaWMgbnVtYmVyIGFzIGEgc3RyaW5nIGFuZCByZXR1cm4gYSBqYXZhc2NyaXB0IG51bWJlci5cbiAgICAgKiBCeSBkZWZhdWx0LCB0aGlzIGZ1bmN0aW9uIGRvZXMgbm90IHRyeSB0byBjb252ZXJ0IHRoZSBhcmFiaWMgZGVjaW1hbCBhbmQgdGhvdXNhbmQgc2VwYXJhdG9yIGNoYXJhY3RlcnMuXG4gICAgICogVGhpcyByZXR1cm5zIGBOYU5gIGlzIHRoZSBjb252ZXJzaW9uIGlzIG5vdCBwb3NzaWJsZS5cbiAgICAgKiBCYXNlZCBvbiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8xNzAyNTM5Mi8yODM0ODk4XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gYXJhYmljTnVtYmVyc1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gcmV0dXJuQU51bWJlciBJZiBgdHJ1ZWAsIHJldHVybiBhIE51bWJlciwgb3RoZXJ3aXNlIHJldHVybiBhIFN0cmluZ1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gcGFyc2VEZWNpbWFsQ2hhcmFjdGVyXG4gICAgICogQHBhcmFtIHtib29sZWFufSBwYXJzZVRob3VzYW5kU2VwYXJhdG9yXG4gICAgICogQHJldHVybnMge3N0cmluZ3xudW1iZXJ8TmFOfVxuICAgICAqL1xuICAgIHN0YXRpYyBhcmFiaWNUb0xhdGluTnVtYmVycyhhcmFiaWNOdW1iZXJzLCByZXR1cm5BTnVtYmVyID0gdHJ1ZSwgcGFyc2VEZWNpbWFsQ2hhcmFjdGVyID0gZmFsc2UsIHBhcnNlVGhvdXNhbmRTZXBhcmF0b3IgPSBmYWxzZSkge1xuICAgICAgICBpZiAodGhpcy5pc051bGwoYXJhYmljTnVtYmVycykpIHtcbiAgICAgICAgICAgIHJldHVybiBhcmFiaWNOdW1iZXJzO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHJlc3VsdCA9IGFyYWJpY051bWJlcnMudG9TdHJpbmcoKTtcbiAgICAgICAgaWYgKHJlc3VsdCA9PT0gJycpIHtcbiAgICAgICAgICAgIHJldHVybiBhcmFiaWNOdW1iZXJzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJlc3VsdC5tYXRjaCgvW9mg2aHZotmj2aTZpdmm2afZqNmp27Tbtdu2XS9nKSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgLy8gSWYgbm8gQXJhYmljL1BlcnNpYW4gbnVtYmVycyBhcmUgZm91bmQsIHJldHVybiB0aGUgbnVtZXJpYyBzdHJpbmcgb3IgbnVtYmVyIGRpcmVjdGx5XG4gICAgICAgICAgICBpZiAocmV0dXJuQU51bWJlcikge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IE51bWJlcihyZXN1bHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcnNlRGVjaW1hbENoYXJhY3Rlcikge1xuICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LnJlcGxhY2UoL9mrLywgJy4nKTsgLy8gRGVjaW1hbCBjaGFyYWN0ZXJcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwYXJzZVRob3VzYW5kU2VwYXJhdG9yKSB7XG4gICAgICAgICAgICByZXN1bHQgPSByZXN1bHQucmVwbGFjZSgv2awvZywgJycpOyAvLyBUaG91c2FuZCBzZXBhcmF0b3JcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlcGxhY2UgdGhlIG51bWJlcnMgb25seVxuICAgICAgICByZXN1bHQgPSByZXN1bHQucmVwbGFjZSgvW9mg2aHZotmj2aTZpdmm2afZqNmpXS9nLCBkID0+IGQuY2hhckNvZGVBdCgwKSAtIDE2MzIpIC8vIEFyYWJpYyBudW1iZXJzXG4gICAgICAgICAgICAucmVwbGFjZSgvW9uw27Hbstuz27Tbtdu227fbuNu5XS9nLCBkID0+IGQuY2hhckNvZGVBdCgwKSAtIDE3NzYpOyAvLyBQZXJzaWFuIG51bWJlcnNcblxuICAgICAgICAvLyBgTmFOYCBoYXMgcHJlY2VkZW5jZSBvdmVyIHRoZSBzdHJpbmcgYCdOYU4nYFxuICAgICAgICBjb25zdCByZXN1bHRBc051bWJlciA9IE51bWJlcihyZXN1bHQpO1xuICAgICAgICBpZiAoaXNOYU4ocmVzdWx0QXNOdW1iZXIpKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0QXNOdW1iZXI7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocmV0dXJuQU51bWJlcikge1xuICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0QXNOdW1iZXI7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIGN1c3RvbSBldmVudCBhbmQgaW1tZWRpYXRlbHkgc2VudCBpdCBmcm9tIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqIEJ5IGRlZmF1bHQsIGlmIG5vIGVsZW1lbnQgaXMgZ2l2ZW4sIHRoZSBldmVudCBpcyB0aHJvd24gZnJvbSBgZG9jdW1lbnRgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8SFRNTERvY3VtZW50fEV2ZW50VGFyZ2V0fSBlbGVtZW50XG4gICAgICogQHBhcmFtIHtvYmplY3R9IGRldGFpbFxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gYnViYmxlcyBTZXQgdG8gYHRydWVgIGlmIHRoZSBldmVudCBtdXN0IGJ1YmJsZSB1cFxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gY2FuY2VsYWJsZSBTZXQgdG8gYHRydWVgIGlmIHRoZSBldmVudCBtdXN0IGJlIGNhbmNlbGFibGVcbiAgICAgKi9cbiAgICBzdGF0aWMgdHJpZ2dlckV2ZW50KGV2ZW50TmFtZSwgZWxlbWVudCA9IGRvY3VtZW50LCBkZXRhaWwgPSBudWxsLCBidWJibGVzID0gdHJ1ZSwgY2FuY2VsYWJsZSA9IHRydWUpIHtcbiAgICAgICAgbGV0IGV2ZW50O1xuICAgICAgICBpZiAod2luZG93LkN1c3RvbUV2ZW50KSB7XG4gICAgICAgICAgICBldmVudCA9IG5ldyBDdXN0b21FdmVudChldmVudE5hbWUsIHsgZGV0YWlsLCBidWJibGVzICwgY2FuY2VsYWJsZSB9KTsgLy8gVGhpcyBpcyBub3Qgc3VwcG9ydGVkIGJ5IGRlZmF1bHQgYnkgSUUgOyBXZSB1c2UgdGhlIHBvbHlmaWxsIGZvciBJRTkgYW5kIGxhdGVyLlxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZXZlbnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnQ3VzdG9tRXZlbnQnKTtcbiAgICAgICAgICAgIGV2ZW50LmluaXRDdXN0b21FdmVudChldmVudE5hbWUsIGJ1YmJsZXMsIGNhbmNlbGFibGUsIHsgZGV0YWlsIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgZWxlbWVudC5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGdW5jdGlvbiB0byBwYXJzZSBtaW5pbXVtVmFsdWUsIG1heGltdW1WYWx1ZSAmIHRoZSBpbnB1dCB2YWx1ZSB0byBwcmVwYXJlIGZvciB0ZXN0aW5nIHRvIGRldGVybWluZSBpZiB0aGUgdmFsdWUgZmFsbHMgd2l0aGluIHRoZSBtaW4gLyBtYXggcmFuZ2UuXG4gICAgICogUmV0dXJuIGFuIG9iamVjdCBleGFtcGxlOiBtaW5pbXVtVmFsdWU6IFwiOTk5OTk5OTk5OTk5OTk5Ljk5XCIgcmV0dXJucyB0aGUgZm9sbG93aW5nIFwie3M6IC0xLCBlOiAxMiwgYzogQXJyYXlbMTVdfVwiLlxuICAgICAqXG4gICAgICogVGhpcyBmdW5jdGlvbiBpcyBhZGFwdGVkIGZyb20gQmlnLmpzIGh0dHBzOi8vZ2l0aHViLmNvbS9NaWtlTWNsL2JpZy5qcy8uIE1hbnkgdGhhbmtzIHRvIE1pa2UuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd9IG4gQSBudW1lcmljIHZhbHVlLlxuICAgICAqIEByZXR1cm5zIHt7fX1cbiAgICAgKi9cbiAgICBzdGF0aWMgcGFyc2VTdHIobikge1xuICAgICAgICBjb25zdCB4ID0ge307IC8vIEEgQmlnIG51bWJlciBpbnN0YW5jZS5cbiAgICAgICAgbGV0IGU7XG4gICAgICAgIGxldCBpO1xuICAgICAgICBsZXQgbkw7XG4gICAgICAgIGxldCBqO1xuXG4gICAgICAgIC8vIE1pbnVzIHplcm8/XG4gICAgICAgIGlmIChuID09PSAwICYmIDEgLyBuIDwgMCkge1xuICAgICAgICAgICAgbiA9ICctMCc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEZXRlcm1pbmUgc2lnbi4gMSBwb3NpdGl2ZSwgLTEgbmVnYXRpdmVcbiAgICAgICAgbiA9IG4udG9TdHJpbmcoKTtcbiAgICAgICAgaWYgKHRoaXMuaXNOZWdhdGl2ZVN0cmljdChuLCAnLScpKSB7XG4gICAgICAgICAgICBuID0gbi5zbGljZSgxKTtcbiAgICAgICAgICAgIHgucyA9IC0xO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgeC5zID0gMTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERlY2ltYWwgcG9pbnQ/XG4gICAgICAgIGUgPSBuLmluZGV4T2YoJy4nKTtcbiAgICAgICAgaWYgKGUgPiAtMSkge1xuICAgICAgICAgICAgbiA9IG4ucmVwbGFjZSgnLicsICcnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIExlbmd0aCBvZiBzdHJpbmcgaWYgbm8gZGVjaW1hbCBjaGFyYWN0ZXJcbiAgICAgICAgaWYgKGUgPCAwKSB7XG4gICAgICAgICAgICAvLyBJbnRlZ2VyXG4gICAgICAgICAgICBlID0gbi5sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEZXRlcm1pbmUgbGVhZGluZyB6ZXJvc1xuICAgICAgICBpID0gKG4uc2VhcmNoKC9bMS05XS9pKSA9PT0gLTEpID8gbi5sZW5ndGggOiBuLnNlYXJjaCgvWzEtOV0vaSk7XG4gICAgICAgIG5MID0gbi5sZW5ndGg7XG4gICAgICAgIGlmIChpID09PSBuTCkge1xuICAgICAgICAgICAgLy8gWmVyb1xuICAgICAgICAgICAgeC5lID0gMDtcbiAgICAgICAgICAgIHguYyA9IFswXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIERldGVybWluZSB0cmFpbGluZyB6ZXJvc1xuICAgICAgICAgICAgZm9yIChqID0gbkwgLSAxOyBuLmNoYXJBdChqKSA9PT0gJzAnOyBqIC09IDEpIHtcbiAgICAgICAgICAgICAgICBuTCAtPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbkwgLT0gMTtcblxuICAgICAgICAgICAgLy8gRGVjaW1hbCBsb2NhdGlvblxuICAgICAgICAgICAgeC5lID0gZSAtIGkgLSAxO1xuICAgICAgICAgICAgeC5jID0gW107XG5cbiAgICAgICAgICAgIC8vIENvbnZlcnQgc3RyaW5nIHRvIGFycmF5IG9mIGRpZ2l0cyB3aXRob3V0IGxlYWRpbmcvdHJhaWxpbmcgemVyb3NcbiAgICAgICAgICAgIGZvciAoZSA9IDA7IGkgPD0gbkw7IGkgKz0gMSkge1xuICAgICAgICAgICAgICAgIHguY1tlXSA9ICtuLmNoYXJBdChpKTtcbiAgICAgICAgICAgICAgICBlICs9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4geDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGdW5jdGlvbiB0byB0ZXN0IGlmIHRoZSBpbnB1dCB2YWx1ZSBmYWxscyB3aXRoIHRoZSBNaW4gLyBNYXggc2V0dGluZ3MuXG4gICAgICogVGhpcyB1c2VzIHRoZSBwYXJzZWQgc3RyaW5ncyBmb3IgdGhlIGFib3ZlIHBhcnNlU3RyIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogVGhpcyBmdW5jdGlvbiBpcyBhZGFwdGVkIGZyb20gQmlnLmpzIGh0dHBzOi8vZ2l0aHViLmNvbS9NaWtlTWNsL2JpZy5qcy8uIE1hbnkgdGhhbmtzIHRvIE1pa2UuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0geSBCaWcgbnVtYmVyIGluc3RhbmNlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHggQmlnIG51bWJlciBpbnN0YW5jZVxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyB0ZXN0TWluTWF4KHksIHgpIHtcbiAgICAgICAgY29uc3QgeGMgPSB4LmM7XG4gICAgICAgIGNvbnN0IHljID0geS5jO1xuICAgICAgICBsZXQgaSA9IHgucztcbiAgICAgICAgbGV0IGogPSB5LnM7XG4gICAgICAgIGxldCBrID0geC5lO1xuICAgICAgICBsZXQgbCA9IHkuZTtcblxuICAgICAgICAvLyBFaXRoZXIgemVybz9cbiAgICAgICAgaWYgKCF4Y1swXSB8fCAheWNbMF0pIHtcbiAgICAgICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgICAgICBpZiAoIXhjWzBdKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gIXljWzBdPzA6LWo7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IGk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2lnbnMgZGlmZmVyP1xuICAgICAgICBpZiAoaSAhPT0gaikge1xuICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgeE5lZyA9IGkgPCAwO1xuXG4gICAgICAgIC8vIENvbXBhcmUgZXhwb25lbnRzXG4gICAgICAgIGlmIChrICE9PSBsKSB7XG4gICAgICAgICAgICByZXR1cm4gKGsgPiBsIF4geE5lZyk/MTotMTtcbiAgICAgICAgfVxuICAgICAgICBpID0gLTE7XG4gICAgICAgIGsgPSB4Yy5sZW5ndGg7XG4gICAgICAgIGwgPSB5Yy5sZW5ndGg7XG4gICAgICAgIGogPSAoayA8IGwpID8gayA6IGw7XG5cbiAgICAgICAgLy8gQ29tcGFyZSBkaWdpdCBieSBkaWdpdFxuICAgICAgICBmb3IgKGkgKz0gMTsgaSA8IGo7IGkgKz0gMSkge1xuICAgICAgICAgICAgaWYgKHhjW2ldICE9PSB5Y1tpXSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAoeGNbaV0gPiB5Y1tpXSBeIHhOZWcpPzE6LTE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDb21wYXJlIGxlbmd0aHNcbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgaWYgKGsgPT09IGwpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IDA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQgPSAoayA+IGwgXiB4TmVnKT8xOi0xO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBhIHJhbmRvbSBzdHJpbmcuXG4gICAgICogY2YuIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzgwODQyNDgvMjgzNDg5OFxuICAgICAqXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IHN0ckxlbmd0aCBMZW5ndGggb2YgdGhlIGdlbmVyYXRlZCBzdHJpbmcgKGluIGNoYXJhY3RlciBjb3VudClcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIHN0YXRpYyByYW5kb21TdHJpbmcoc3RyTGVuZ3RoID0gNSkge1xuICAgICAgICByZXR1cm4gTWF0aC5yYW5kb20oKVxuICAgICAgICAgICAgLnRvU3RyaW5nKDM2KVxuICAgICAgICAgICAgLnN1YnN0cigyLCBzdHJMZW5ndGgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgRE9NIGVsZW1lbnQgd2hlbiBwYXNzZWQgZWl0aGVyIGEgRE9NIGVsZW1lbnQgb3IgYSBzZWxlY3RvciBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fHN0cmluZ30gZG9tRWxlbWVudE9yU2VsZWN0b3JcbiAgICAgKiBAcmV0dXJucyB7SFRNTEVsZW1lbnR9XG4gICAgICovXG4gICAgc3RhdGljIGRvbUVsZW1lbnQoZG9tRWxlbWVudE9yU2VsZWN0b3IpIHtcbiAgICAgICAgbGV0IGRvbUVsZW1lbnQ7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc1N0cmluZyhkb21FbGVtZW50T3JTZWxlY3RvcikpIHtcbiAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGRvbUVsZW1lbnRPclNlbGVjdG9yKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBkb21FbGVtZW50T3JTZWxlY3RvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkb21FbGVtZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlIHRoZSBjdXJyZW50IGVsZW1lbnQgdmFsdWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR8RXZlbnRUYXJnZXR9IGVsZW1lbnRcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfHN0cmluZ3xudWxsfVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRFbGVtZW50VmFsdWUoZWxlbWVudCkge1xuICAgICAgICBpZiAoZWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdpbnB1dCcpIHtcbiAgICAgICAgICAgIHJldHVybiBlbGVtZW50LnZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMudGV4dChlbGVtZW50KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNb2RpZnkgdGhlIGVsZW1lbnQgdmFsdWUgZGlyZWN0bHkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR9IGVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd8bnVsbH0gdmFsdWVcbiAgICAgKi9cbiAgICBzdGF0aWMgc2V0RWxlbWVudFZhbHVlKGVsZW1lbnQsIHZhbHVlID0gbnVsbCkge1xuICAgICAgICBpZiAoZWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdpbnB1dCcpIHtcbiAgICAgICAgICAgIGVsZW1lbnQudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVsZW1lbnQudGV4dENvbnRlbnQgPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgY2xvbmUgdGhlIGdpdmVuIG9iamVjdCwgYW5kIHJldHVybiBpdC5cbiAgICAgKiBXQVJOSU5HOiBUaGlzIGRvZXMgbm90IGRvIGEgZGVlcCBjbG9uaW5nLlxuICAgICAqIGNmLiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9PYmplY3QvYXNzaWduI0V4YW1wbGVzXG4gICAgICogLy9UT0RPIEFkZCBhIGBkZWVwYCBvcHRpb24gdG8gY2xvbmUgb2JqZWN0IHdpdGggbW9yZSB0aGFuIG9uZSBkZXB0aFxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9ialxuICAgICAqIEByZXR1cm5zIHtvYmplY3R9XG4gICAgICovXG4gICAgc3RhdGljIGNsb25lT2JqZWN0KG9iaikge1xuICAgICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgb2JqKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYSAnY2FtZWxpemVkJyB2ZXJzaW9uIG9mIHRoZSBnaXZlbiBzdHJpbmcuXG4gICAgICogQnkgZGVmYXVsdCwgdGhpcyBhc3N1bWUgdGhhdCA6XG4gICAgICogLSB0aGUgc2VwYXJhdG9ycyBhcmUgaHlwaGVucyAnLScsXG4gICAgICogLSB0aGUgJ2RhdGEtJyBzdHJpbmcgc2hvdWxkIGJlIHJlbW92ZWQsIGFuZFxuICAgICAqIC0gdGhhdCB0aGUgdmVyeSBmaXJzdCB3b3JkIHNob3VsZCBub3QgYmUgY2FwaXRhbGl6ZWQuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZSBjYW1lbGl6ZSgnZGF0YS1jdXJyZW5jeS1zeW1ib2wnKSA9PiAnY3VycmVuY3lTeW1ib2wnXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyIFRleHQgdG8gY2FtZWxpemVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc2VwYXJhdG9yIENoYXJhY3RlciB0aGF0IHNlcGFyYXRlIGVhY2ggd29yZFxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gcmVtb3ZlRGF0YSBJZiBzZXQgdG8gYHRydWVgLCByZW1vdmUgdGhlIGBkYXRhLWAgcGFydCB0aGF0IHlvdSBjYW4gZmluZCBvbiBzb21lIGh0bWwgYXR0cmlidXRlc1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gc2tpcEZpcnN0V29yZCBJZiBzZXQgdG8gYHRydWVgLCBkbyBub3QgY2FwaXRhbGl6ZSB0aGUgdmVyeSBmaXJzdCB3b3JkXG4gICAgICogQHJldHVybnMge3N0cmluZ3xudWxsfVxuICAgICAqL1xuICAgIHN0YXRpYyBjYW1lbGl6ZShzdHIsIHNlcGFyYXRvciA9ICctJywgcmVtb3ZlRGF0YSA9IHRydWUsIHNraXBGaXJzdFdvcmQgPSB0cnVlKSB7XG4gICAgICAgIGlmICh0aGlzLmlzTnVsbChzdHIpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyZW1vdmVEYXRhKSB7XG4gICAgICAgICAgICBzdHIgPSBzdHIucmVwbGFjZSgvXmRhdGEtLywgJycpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ3V0IHRoZSBzdHJpbmcgaW50byB3b3Jkc1xuICAgICAgICBjb25zdCB3b3JkcyA9IHN0ci5zcGxpdChzZXBhcmF0b3IpO1xuXG4gICAgICAgIC8vIENhcGl0YWxpemUgZWFjaCB3b3JkXG4gICAgICAgIGxldCByZXN1bHQgPSB3b3Jkcy5tYXAod29yZCA9PiBgJHt3b3JkLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpfSR7d29yZC5zbGljZSgxKX1gKTtcblxuICAgICAgICAvLyBUaGVuIGNvbmNhdGVuYXRlIHRoZW0gYmFja1xuICAgICAgICByZXN1bHQgPSByZXN1bHQuam9pbignJyk7XG5cbiAgICAgICAgaWYgKHNraXBGaXJzdFdvcmQpIHtcbiAgICAgICAgICAgIC8vIFNraXAgdGhlIHZlcnkgZmlyc3QgbGV0dGVyXG4gICAgICAgICAgICByZXN1bHQgPSBgJHtyZXN1bHQuY2hhckF0KDApLnRvTG93ZXJDYXNlKCl9JHtyZXN1bHQuc2xpY2UoMSl9YDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSB0ZXh0IGNvbXBvbmVudCBvZiB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0VsZW1lbnR9IGRvbUVsZW1lbnRcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIHN0YXRpYyB0ZXh0KGRvbUVsZW1lbnQpIHtcbiAgICAgICAgY29uc3Qgbm9kZVR5cGUgPSBkb21FbGVtZW50Lm5vZGVUeXBlO1xuXG4gICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgIC8vIGNmLiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvTm9kZS9ub2RlVHlwZVxuICAgICAgICBpZiAobm9kZVR5cGUgPT09IE5vZGUuRUxFTUVOVF9OT0RFIHx8XG4gICAgICAgICAgICBub2RlVHlwZSA9PT0gTm9kZS5ET0NVTUVOVF9OT0RFIHx8XG4gICAgICAgICAgICBub2RlVHlwZSA9PT0gTm9kZS5ET0NVTUVOVF9GUkFHTUVOVF9OT0RFKSB7XG4gICAgICAgICAgICByZXN1bHQgPSBkb21FbGVtZW50LnRleHRDb250ZW50O1xuICAgICAgICB9IGVsc2UgaWYgKG5vZGVUeXBlID09PSBOb2RlLlRFWFRfTk9ERSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gZG9tRWxlbWVudC5ub2RlVmFsdWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQgPSAnJztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSB0ZXh0IGNvbnRlbnQgb2YgdGhlIGdpdmVuIERPTSBlbGVtZW50LlxuICAgICAqIEBwYXJhbSB7RWxlbWVudH0gZG9tRWxlbWVudFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0XG4gICAgICovXG4gICAgc3RhdGljIHNldFRleHQoZG9tRWxlbWVudCwgdGV4dCkge1xuICAgICAgICBjb25zdCBub2RlVHlwZSA9IGRvbUVsZW1lbnQubm9kZVR5cGU7XG4gICAgICAgIGlmIChub2RlVHlwZSA9PT0gTm9kZS5FTEVNRU5UX05PREUgfHxcbiAgICAgICAgICAgIG5vZGVUeXBlID09PSBOb2RlLkRPQ1VNRU5UX05PREUgfHxcbiAgICAgICAgICAgIG5vZGVUeXBlID09PSBOb2RlLkRPQ1VNRU5UX0ZSQUdNRU5UX05PREUpIHtcbiAgICAgICAgICAgIGRvbUVsZW1lbnQudGV4dENvbnRlbnQgPSB0ZXh0O1xuICAgICAgICB9XG4gICAgICAgIC8vVE9ETyBEaXNwbGF5IGEgd2FybmluZyBpZiB0aGF0IGZ1bmN0aW9uIGRvZXMgbm90IGRvIGFueXRoaW5nP1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZpbHRlciBvdXQgdGhlIGdpdmVuIGBhcnJgIGFycmF5IHdpdGggdGhlIGVsZW1lbnRzIGZvdW5kIGluIGBleGNsdWRlZEVsZW1lbnRzYC5cbiAgICAgKiBUaGlzIHJldHVybnMgYSBuZXcgYXJyYXkgYW5kIGRvZXMgbm90IG1vZGlmeSB0aGUgc291cmNlLlxuICAgICAqIGNmLiB2ZXJpZmljYXRpb24gaGVyZSA6IGh0dHA6Ly9jb2RlcGVuLmlvL0Fub3RoZXJMaW51eFVzZXIvcGVuL1hwdnJNZz9lZGl0b3JzPTAwMTJcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFyclxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGV4Y2x1ZGVkRWxlbWVudHNcbiAgICAgKiBAcmV0dXJucyB7KnxBcnJheS48VD59XG4gICAgICovXG4gICAgc3RhdGljIGZpbHRlck91dChhcnIsIGV4Y2x1ZGVkRWxlbWVudHMpIHtcbiAgICAgICAgcmV0dXJuIGFyci5maWx0ZXIoZWxlbWVudCA9PiAhdGhpcy5pc0luQXJyYXkoZWxlbWVudCwgZXhjbHVkZWRFbGVtZW50cykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZSB0aGUgdHJhaWxpbmcgemVyb3MgaW4gdGhlIGRlY2ltYWwgcGFydCBvZiBhIG51bWJlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBudW1lcmljU3RyaW5nXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgc3RhdGljIHRyaW1QYWRkZWRaZXJvc0Zyb21EZWNpbWFsUGxhY2VzKG51bWVyaWNTdHJpbmcpIHtcbiAgICAgICAgbnVtZXJpY1N0cmluZyA9IFN0cmluZyhudW1lcmljU3RyaW5nKTtcbiAgICAgICAgaWYgKG51bWVyaWNTdHJpbmcgPT09ICcnKSB7XG4gICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBbaW50ZWdlclBhcnQsIGRlY2ltYWxQYXJ0XSA9IG51bWVyaWNTdHJpbmcuc3BsaXQoJy4nKTtcbiAgICAgICAgaWYgKHRoaXMuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KGRlY2ltYWxQYXJ0KSkge1xuICAgICAgICAgICAgcmV0dXJuIGludGVnZXJQYXJ0O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdHJpbW1lZERlY2ltYWxQYXJ0ID0gZGVjaW1hbFBhcnQucmVwbGFjZSgvMCskL2csICcnKTtcblxuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBpZiAodHJpbW1lZERlY2ltYWxQYXJ0ID09PSAnJykge1xuICAgICAgICAgICAgcmVzdWx0ID0gaW50ZWdlclBhcnQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQgPSBgJHtpbnRlZ2VyUGFydH0uJHt0cmltbWVkRGVjaW1hbFBhcnR9YDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSB0b3AtbW9zdCBob3ZlcmVkIGl0ZW0gYnkgdGhlIG1vdXNlIGN1cnNvci5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRIb3ZlcmVkRWxlbWVudCgpIHtcbiAgICAgICAgY29uc3QgaG92ZXJlZEVsZW1lbnRzID0gWy4uLmRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJzpob3ZlcicpXTtcbiAgICAgICAgcmV0dXJuIGhvdmVyZWRFbGVtZW50c1tob3ZlcmVkRWxlbWVudHMubGVuZ3RoIC0gMV07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBnaXZlbiBhcnJheSB0cmltbWVkIHRvIHRoZSBnaXZlbiBsZW5ndGguXG4gICAgICogQGV4YW1wbGUgYXJyYXlUcmltKFsxLCAyLCAzLCA0XSwgMikgLT4gWzEsIDJdXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheVxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBsZW5ndGhcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBzdGF0aWMgYXJyYXlUcmltKGFycmF5LCBsZW5ndGgpIHtcbiAgICAgICAgY29uc3QgYXJyTGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuICAgICAgICBpZiAoYXJyTGVuZ3RoID09PSAwIHx8IGxlbmd0aCA+IGFyckxlbmd0aCkge1xuICAgICAgICAgICAgLy8gQWxzbyBtYW5hZ2UgdGhlIGNhc2Ugd2hlcmUgYGxlbmd0aGAgaXMgaGlnaGVyIHRoYW4gdGhlIGN1cnJlbnQgbGVuZ3RoXG4gICAgICAgICAgICByZXR1cm4gYXJyYXk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobGVuZ3RoIDwgMCkge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG5cbiAgICAgICAgYXJyYXkubGVuZ3RoID0gcGFyc2VJbnQobGVuZ3RoLCAxMCk7XG5cbiAgICAgICAgcmV0dXJuIGFycmF5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1lcmdlIGFsbCB0aGUgZ2l2ZW4gYXJyYXlzIGJ5IGtlZXBpbmcgb25seSB1bmlxdWUgZWxlbWVudHMsIGFuZCByZXR1cm4gYW4gYXJyYXkgd2l0aCBkZS1kdXBsaWNhdGVkIHZhbHVlcy5cbiAgICAgKiBjZi4gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMjc2NjQ5NzEvMjgzNDg5OFxuICAgICAqXG4gICAgICogQHBhcmFtIHsuLi5hcnJheX0gYXJyYXlzXG4gICAgICogQHJldHVybnMge1sqXX1cbiAgICAgKi9cbiAgICBzdGF0aWMgYXJyYXlVbmlxdWUoLi4uYXJyYXlzKSB7IC8vRklYTUUgw6AgdGVzdGVyXG4gICAgICAgIHJldHVybiBbLi4ubmV3IFNldChbXS5jb25jYXQoLi4uYXJyYXlzKSldO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1lcmdlIGFsbCB0aGUgZ2l2ZW4gTWFwcyBieSBrZWVwaW5nIG9ubHkgdW5pcXVlIGVsZW1lbnRzLCBhbmQgcmV0dXJuIGEgbmV3IE1hcCB3aXRoIGRlLWR1cGxpY2F0ZWQga2V5cy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Li4uTWFwfSBtYXBPYmplY3RzXG4gICAgICogQHJldHVybnMge01hcH1cbiAgICAgKi9cbiAgICBzdGF0aWMgbWVyZ2VNYXBzKC4uLm1hcE9iamVjdHMpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBNYXAobWFwT2JqZWN0cy5yZWR1Y2UoKGFzLCBiKSA9PiBhcy5jb25jYXQoWy4uLmJdKSwgW10pKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWFyY2ggdGhlIGdpdmVuIGB2YWx1ZWAgaW4gdGhlIG9iamVjdCBgb2JqYCwgYW5kIHJldHVybiB0aGUgdmVyeSBmaXJzdCBrZXkgaXQgZmluZHNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvYmpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IHZhbHVlXG4gICAgICogQHJldHVybnMgeyp8bnVsbH1cbiAgICAgKi9cbiAgICBzdGF0aWMgb2JqZWN0S2V5TG9va3VwKG9iaiwgdmFsdWUpIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gT2JqZWN0LmVudHJpZXMob2JqKS5maW5kKGFycmF5ID0+IGFycmF5WzFdID09PSB2YWx1ZSk7XG4gICAgICAgIGxldCBrZXkgPSBudWxsO1xuICAgICAgICBpZiAocmVzdWx0ICE9PSB2b2lkKDApKSB7XG4gICAgICAgICAgICBrZXkgPSByZXN1bHRbMF07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ga2V5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluc2VydCB0aGUgc2luZ2xlIGNoYXJhY3RlciBgY2hhcmAgaW4gdGhlIHN0cmluZyBgc3RyYCBhdCB0aGUgZ2l2ZW4gcG9zaXRpb24gYGluZGV4YFxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0clxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBjaGFyXG4gICAgICogQHBhcmFtIHtpbnR9IGluZGV4XG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgaW5zZXJ0QXQoc3RyLCBjaGFyLCBpbmRleCkge1xuICAgICAgICBzdHIgPSBTdHJpbmcoc3RyKTtcblxuICAgICAgICBpZiAoaW5kZXggPiBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZSBnaXZlbiBpbmRleCBpcyBvdXQgb2YgdGhlIHN0cmluZyByYW5nZS5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjaGFyLmxlbmd0aCAhPT0gMSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgZ2l2ZW4gc3RyaW5nIGBjaGFyYCBzaG91bGQgYmUgb25seSBvbmUgY2hhcmFjdGVyIGxvbmcuJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3RyID09PSAnJyAmJiBpbmRleCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIGNoYXI7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYCR7c3RyLnNsaWNlKDAsIGluZGV4KX0ke2NoYXJ9JHtzdHIuc2xpY2UoaW5kZXgpfWA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydCB0aGUgZ2l2ZW4gc2NpZW50aWZpYyBub3RhdGlvbiB0byB0aGUgJ2V4cGFuZGVkJyBkZWNpbWFsIG5vdGF0aW9uXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZSBzY2llbnRpZmljVG9EZWNpbWFsKCctMTIzLjQ1NjdlLTYnKSByZXR1cm5zICctMC4wMDAxMjM0NTY3J1xuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfSB2YWxcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfHN0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgc2NpZW50aWZpY1RvRGVjaW1hbCh2YWwpIHtcbiAgICAgICAgLy8gQ2hlY2sgdGhhdCB0aGUgdmFsIGlzIGEgTnVtYmVyXG4gICAgICAgIGNvbnN0IG51bWVyaWNWYWx1ZSA9IE51bWJlcih2YWwpO1xuICAgICAgICBpZiAoaXNOYU4obnVtZXJpY1ZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENoZWNrIGlmIHRoZSBudW1iZXIgaXMgaW4gYSBzY2llbnRpZmljIG5vdGF0aW9uXG4gICAgICAgIHZhbCAgICAgICAgICAgICAgICA9IFN0cmluZyh2YWwpO1xuICAgICAgICBjb25zdCBpc1NjaWVudGlmaWMgPSB0aGlzLmNvbnRhaW5zKHZhbCwgJ2UnKSB8fCB0aGlzLmNvbnRhaW5zKHZhbCwgJ0UnKTtcblxuICAgICAgICBpZiAoIWlzU2NpZW50aWZpYykge1xuICAgICAgICAgICAgcmV0dXJuIHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENvbnZlcnQgdGhlIHNjaWVudGlmaWMgbm90YXRpb24gdG8gYSBudW1lcmljIHN0cmluZ1xuICAgICAgICBsZXQgW3ZhbHVlLCBleHBvbmVudF0gPSB2YWwuc3BsaXQoL2UvaSk7XG4gICAgICAgIGNvbnN0IGlzTmVnYXRpdmUgPSB2YWx1ZSA8IDA7XG4gICAgICAgIGlmIChpc05lZ2F0aXZlKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnJlcGxhY2UoJy0nLCAnJyk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBpc05lZ2F0aXZlRXhwb25lbnQgPSArZXhwb25lbnQgPCAwO1xuICAgICAgICBpZiAoaXNOZWdhdGl2ZUV4cG9uZW50KSB7XG4gICAgICAgICAgICBleHBvbmVudCA9IGV4cG9uZW50LnJlcGxhY2UoJy0nLCAnJyk7IC8vIFJlbW92ZSB0aGUgbmVnYXRpdmUgc2lnblxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgW2ludCwgZmxvYXRdID0gdmFsdWUuc3BsaXQoL1xcLi8pO1xuXG4gICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgIGlmIChpc05lZ2F0aXZlRXhwb25lbnQpIHtcbiAgICAgICAgICAgIGlmIChpbnQubGVuZ3RoID4gZXhwb25lbnQpIHtcbiAgICAgICAgICAgICAgICAvLyBQbGFjZSB0aGUgZGVjaW1hbCBwb2ludCBhdCB0aGUgaW50IGxlbmd0aCBjb3VudCBtaW51cyBleHBvbmVudFxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuaW5zZXJ0QXQoaW50LCAnLicsIGludC5sZW5ndGggLSBleHBvbmVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIElmIHRoYXQgZGVjaW1hbCBwb2ludCBpcyBncmVhdGVyIHRoYW4gdGhlIGludCBsZW5ndGgsIHBhZCB3aXRoIHplcm9zIChpZS4gTnVtYmVyKCctMTIzLjQ1NjdlLTYnKSAtLT4gLTAuMDAwMTIzNDU2NylcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBgMC4keycwJy5yZXBlYXQoZXhwb25lbnQgLSBpbnQubGVuZ3RoKX0ke2ludH1gO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXN1bHQgPSBgJHtyZXN1bHR9JHtmbG9hdD9mbG9hdDonJ31gO1xuICAgICAgICB9IGVsc2UgeyAvLyBQb3NpdGl2ZSBleHBvbmVudFxuICAgICAgICAgICAgaWYgKGZsb2F0KSB7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSBgJHtpbnR9JHtmbG9hdH1gOyAvLyBSZW1vdmUgdGhlICcuJywgaWYgYW55XG4gICAgICAgICAgICAgICAgaWYgKGV4cG9uZW50IDwgZmxvYXQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuaW5zZXJ0QXQodmFsdWUsICcuJywgK2V4cG9uZW50ICsgaW50Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gYCR7dmFsdWV9JHsnMCcucmVwZWF0KGV4cG9uZW50IC0gZmxvYXQubGVuZ3RoKX1gO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKCcuJywgJycpOyAvLyBTaW5nbGUgY2FzZSB3aGVyZSB2YWwgaXMgJzEuZTQnXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gYCR7dmFsdWV9JHsnMCcucmVwZWF0KE51bWJlcihleHBvbmVudCkpfWA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaXNOZWdhdGl2ZSkge1xuICAgICAgICAgICAgLy8gUHV0IGJhY2sgdGhlIG5lZ2F0aXZlIHNpZ24sIGlmIGFueVxuICAgICAgICAgICAgcmVzdWx0ID0gYC0ke3Jlc3VsdH1gO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTZCQTtBQUNBOzs7Ozs7Ozs7QUFDQTs7OztBQUlBOzs7Ozs7OztBQUNBOzs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBaUJBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUE3REE7QUErREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7O0FBWUE7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7QUFZQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBZ0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBS0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBY0E7QUFDQTtBQURBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTJDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBZkE7QUFpQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7O0FBWUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQVVBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FBU0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQVVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUFBO0FBQ0E7QUFBQTtBQUdBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQVNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQWVBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQVNBO0FBQUE7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBTEE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUFBO0FBQ0E7QUFEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQWhCQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBZ0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBMUJBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUE0QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7QUFsL0NBO0EiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./src/AutoNumericHelper.js\n");

/***/ }),

/***/ "./src/AutoNumericOptions.js":
/*!***********************************!*\
  !*** ./src/AutoNumericOptions.js ***!
  \***********************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

"use strict";
eval("\n\nvar _AutoNumeric = __webpack_require__(/*! ./AutoNumeric */ \"./src/AutoNumeric.js\");\n\nvar _AutoNumeric2 = _interopRequireDefault(_AutoNumeric);\n\nvar _AutoNumericHelper = __webpack_require__(/*! ./AutoNumericHelper */ \"./src/AutoNumericHelper.js\");\n\nvar _AutoNumericHelper2 = _interopRequireDefault(_AutoNumericHelper);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * Options values enumeration\n */\n/**\n * Options for autoNumeric.js\n * @author Alexandre Bonneau <alexandre.bonneau@linuxfr.eu>\n * @copyright © 2016 Alexandre Bonneau\n *\n * The MIT License (http://www.opensource.org/licenses/mit-license.php)\n *\n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sub license, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n_AutoNumeric2.default.options = {\n    /* Defines if the decimal places should be padded with zeroes\n     * `true`     : always pad decimals with zeros (ie. '12.3400')\n     * `false`    : never pad with zeros (ie. '12.34')\n     * `'floats'` : pad with zeroes only when there are decimals (ie. '12' and '12.3400')\n     * Note: setting allowDecimalPadding to 'false' will override the 'decimalPlaces' setting.\n     */\n    allowDecimalPadding: {\n        always: true,\n        never: false,\n        floats: 'floats'\n    },\n\n    /* Defines if the decimal character or decimal character alternative should be accepted when there is already a decimal character shown in the element.\n     * If set to `true`, any decimal character input will be accepted and will subsequently modify the decimal character position, as well as the `rawValue`.\n     * If set to `false`, the decimal character and its alternative key will be dropped as before. This is the default setting.\n     */\n    alwaysAllowDecimalCharacter: {\n        alwaysAllow: true,\n        doNotAllow: false\n    },\n\n    /* Defines where should be positioned the caret on focus\n     * null : Do not enforce any caret positioning on focus (this is needed when using `selectOnFocus`)\n     * `'start'` : put the caret of the far left side of the value (excluding the positive/negative sign and currency symbol, if any)\n     * `'end'` : put the caret of the far right side of the value (excluding the positive/negative sign and currency symbol, if any)\n     * `'decimalLeft'` : put the caret of the left of the decimal character if any\n     * `'decimalRight'` : put the caret of the right of the decimal character if any\n     */\n    caretPositionOnFocus: {\n        start: 'start',\n        end: 'end',\n        decimalLeft: 'decimalLeft',\n        decimalRight: 'decimalRight',\n        doNoForceCaretPosition: null\n    },\n\n    /* Defines if a local list of AutoNumeric objects should be kept when initializing this object.\n     * This list is used by the `global.*` functions.\n     */\n    createLocalList: {\n        createList: true,\n        doNotCreateList: false\n    },\n\n    /* Defines the currency symbol string.\n     * It can be a string of more than one character (allowing for instance to use a space on either side of it, example: '$ ' or ' $')\n     * cf. https://en.wikipedia.org/wiki/Currency_symbol\n     */\n    currencySymbol: {\n        none: '',\n        currencySign: '¤',\n        austral: '₳', // ARA\n        australCentavo: '¢',\n        baht: '฿', // THB\n        cedi: '₵', // GHS\n        cent: '¢',\n        colon: '₡', // CRC\n        cruzeiro: '₢', // BRB - Not used anymore since 1993\n        dollar: '$',\n        dong: '₫', // VND\n        drachma: '₯', // GRD (or 'Δρχ.' or 'Δρ.')\n        dram: '​֏', // AMD\n        european: '₠', // XEU (old currency before the Euro)\n        euro: '€', // EUR\n        florin: 'ƒ',\n        franc: '₣', // FRF\n        guarani: '₲', // PYG\n        hryvnia: '₴', // грн\n        kip: '₭', // LAK\n        att: 'ອັດ', // cents of the Kip\n        lepton: 'Λ.', // cents of the Drachma\n        lira: '₺', // TRY\n        liraOld: '₤',\n        lari: '₾', // GEL\n        mark: 'ℳ',\n        mill: '₥',\n        naira: '₦', // NGN\n        peseta: '₧',\n        peso: '₱', // PHP\n        pfennig: '₰', // cents of the Mark\n        pound: '£',\n        real: 'R$', // Brazilian real\n        riel: '៛', // KHR\n        ruble: '₽', // RUB\n        rupee: '₹', // INR\n        rupeeOld: '₨',\n        shekel: '₪',\n        shekelAlt: 'ש״ח‎‎',\n        taka: '৳', // BDT\n        tenge: '₸', // KZT\n        togrog: '₮', // MNT\n        won: '₩',\n        yen: '¥'\n    },\n\n    /* Defines where the currency symbol should be placed (before of after the numbers)\n     * for prefix currencySymbolPlacement: \"p\" (default)\n     * for suffix currencySymbolPlacement: \"s\"\n     */\n    currencySymbolPlacement: {\n        prefix: 'p',\n        suffix: 's'\n    },\n\n    /* Defines what decimal separator character is used\n     */\n    decimalCharacter: {\n        comma: ',',\n        dot: '.',\n        middleDot: '·',\n        arabicDecimalSeparator: '٫',\n        decimalSeparatorKeySymbol: '⎖'\n    },\n\n    /* Allow to declare an alternative decimal separator which is automatically replaced by `decimalCharacter` when typed.\n     * This is used by countries that use a comma ',' as the decimal character and have keyboards with a numeric pads that have\n     * a period 'full stop' as the decimal character (France or Spain for instance).\n     */\n    decimalCharacterAlternative: {\n        none: null,\n        comma: ',',\n        dot: '.'\n    },\n\n    /* Defines the default number of decimal places to show on the formatted value, and keep for the precision.\n     * Incidentally, since we need to be able to show that many decimal places, this also defines the raw value precision by default.\n     */\n    decimalPlaces: {\n        none: 0,\n        one: 1,\n        two: 2,\n        three: 3,\n        four: 4,\n        five: 5,\n        six: 6\n    },\n\n    /* Defines how many decimal places should be kept for the raw value (ie. This is the precision for float values).\n     *\n     * If this option is set to `null` (which is the default), then the value of `decimalPlaces` is used for `decimalPlacesRawValue` as well.\n     * Note: Setting this to a lower number of decimal places than the one to be shown will lead to confusion for the users.\n     */\n    decimalPlacesRawValue: {\n        useDefault: null,\n        none: 0,\n        one: 1,\n        two: 2,\n        three: 3,\n        four: 4,\n        five: 5,\n        six: 6\n    },\n\n    /* Defines how many decimal places should be visible when the element is unfocused.\n     * If this is set to `null`, then this option is ignored, and the `decimalPlaces` option value will be used instead.\n     * This means this is optional ; if omitted the decimal places will be the same when the input has the focus.\n     *\n     * This option can be used in conjonction with the two other `scale*` options, which allows to display a different formatted value when the element is unfocused, while another formatted value is shown when focused.\n     * For those `scale*` options to have any effect, `divisorWhenUnfocused` must not be `null`.\n     */\n    decimalPlacesShownOnBlur: {\n        useDefault: null,\n        none: 0,\n        one: 1,\n        two: 2,\n        three: 3,\n        four: 4,\n        five: 5,\n        six: 6\n    },\n\n    /* Defines how many decimal places should be visible when the element has the focus.\n     * If this is set to `null`, then this option is ignored, and the `decimalPlaces` option value will be used instead.\n     *\n     * Example:\n     * For instance if `decimalPlacesShownOnFocus` is set to `5` and the default number of decimal places is `2`, then on focus `1,000.12345` will be shown, while without focus `1,000.12` will be set back.\n     * Note 1: the results depends on the rounding method used.\n     * Note 2: the `getNumericString()` method returns the extended decimal places\n     */\n    decimalPlacesShownOnFocus: {\n        useDefault: null,\n        none: 0,\n        one: 1,\n        two: 2,\n        three: 3,\n        four: 4,\n        five: 5,\n        six: 6\n    },\n\n    /* Helper option for ASP.NET postback\n     * This should be set as the value of the unformatted default value\n     * examples:\n     * no default value=\"\" {defaultValueOverride: \"\"}\n     * value=1234.56 {defaultValueOverride: '1234.56'}\n     */\n    defaultValueOverride: {\n        doNotOverride: null\n    },\n\n    /* Defines how many numbers should be grouped together (usually for the thousand separator)\n     * - \"2\",  results in 99,99,99,999 India's lakhs\n     * - \"2s\", results in 99,999,99,99,999 India's lakhs scaled\n     * - \"3\",  results in 999,999,999 (default)\n     * - \"4\",  results in 9999,9999,9999 used in some Asian countries\n     * Note: This option does not accept other grouping choice.\n     */\n    digitalGroupSpacing: {\n        two: '2',\n        twoScaled: '2s',\n        three: '3',\n        four: '4'\n    },\n\n    /* Defines the thousand grouping separator character\n     * Example : If `'.'` is set, then you'll get `'1.234.567'`\n     */\n    digitGroupSeparator: {\n        comma: ',',\n        dot: '.',\n        normalSpace: ' ',\n        thinSpace: '\\u2009',\n        narrowNoBreakSpace: '\\u202F',\n        noBreakSpace: '\\xA0',\n        noSeparator: '',\n        apostrophe: '\\'',\n        arabicThousandsSeparator: '٬',\n        dotAbove: '˙'\n    },\n\n    /* The `divisorWhenUnfocused` divide the element value on focus.\n     * On blur, the element value is multiplied back.\n     *\n     * Example : Display percentages using { divisorWhenUnfocused: 100 } (or directly in the Html with `<input data-divisor-when-unfocused=\"100\">`)\n     * The divisor value does not need to be an integer, but please understand that Javascript has limited accuracy in math ; use with caution.\n     * Note: The `getNumericString` method returns the full value, including the 'hidden' decimals.\n     */\n    divisorWhenUnfocused: {\n        none: null,\n        percentage: 100,\n        permille: 1000,\n        basisPoint: 10000\n    },\n\n    /* Defines what should be displayed in the element if the raw value is an empty string ('').\n     * - 'focus'  : The currency sign is displayed when the input receives focus (default)\n     * - 'press'  : The currency sign is displayed whenever a key is being pressed\n     * - 'always' : The currency sign is always displayed\n     * - 'zero'   : A zero is displayed ('rounded' with or without a currency sign) if the input has no value on focus out\n     * - 'min'    : The minimum value is displayed if the input has no value on focus out\n     * - 'max'    : The maximum value is displayed if the input has no value on focus out\n     * - 'null'   : When the element is empty, the `rawValue` and the element value/text is set to `null`. This also allows to set the value to `null` using `anElement.set(null)`.\n     */\n    emptyInputBehavior: {\n        focus: 'focus',\n        press: 'press',\n        always: 'always',\n        zero: 'zero',\n        min: 'min',\n        max: 'max',\n        null: 'null'\n    },\n\n    /* Defines if the custom and native events triggered by AutoNumeric should bubble up or not.\n     */\n    eventBubbles: {\n        bubbles: true,\n        doesNotBubble: false\n    },\n\n    /* Defines if the custom and native events triggered by AutoNumeric should be cancelable.\n     */\n    eventIsCancelable: {\n        isCancelable: true,\n        isNotCancelable: false\n    },\n\n    /* This option is the 'strict mode' (aka 'debug' mode), which allows autoNumeric to strictly analyse the options passed, and fails if an unknown options is used in the settings object.\n     * You should set that to `true` if you want to make sure you are only using 'pure' autoNumeric settings objects in your code.\n     * If you see uncaught errors in the console and your code starts to fail, this means somehow those options gets polluted by another program (which usually happens when using frameworks).\n     */\n    failOnUnknownOption: {\n        fail: true,\n        ignore: false\n    },\n\n    /* Determine if the default value will be formatted on initialization.\n     */\n    formatOnPageLoad: {\n        format: true, // automatically formats the default value on initialization\n        doNotFormat: false // will not format the default value on initialization\n    },\n\n    /* Set the undo/redo history table size.\n     * Each record keeps the raw value as well and the last known caret/selection positions.\n     */\n    historySize: {\n        verySmall: 5,\n        small: 10,\n        medium: 20,\n        large: 50,\n        veryLarge: 100,\n        insane: Number.MAX_SAFE_INTEGER\n    },\n\n    /* Allow the user to 'cancel' and undo the changes he made to the given autonumeric-managed element, by pressing the 'Escape' key.\n     * Whenever the user 'validate' the input (either by hitting 'Enter', or blurring the element), the new value is saved for subsequent 'cancellation'.\n     *\n     * The process :\n     *   - save the input value on focus\n     *   - if the user change the input value, and hit `Escape`, then the initial value saved on focus is set back\n     *   - on the other hand if the user either have used `Enter` to validate (`Enter` throws a change event) his entries, or if the input value has been changed by another script in the mean time, then we save the new input value\n     *   - on a successful 'cancel', select the whole value (while respecting the `selectNumberOnly` option)\n     *   - bonus; if the value has not changed, hitting 'Esc' just select all the input value (while respecting the `selectNumberOnly` option)\n     */\n    isCancellable: {\n        cancellable: true,\n        notCancellable: false\n    },\n\n    /* Controls the leading zero behavior\n     * - 'allow' : allows leading zeros to be entered. Zeros will be truncated when entering additional digits. On focusout zeros will be deleted\n     * - 'deny'  : allows only one leading zero on values that are between 1 and -1\n     * - 'keep'  : allows leading zeros to be entered. on focusout zeros will be retained\n     */\n    leadingZero: {\n        allow: 'allow',\n        deny: 'deny',\n        keep: 'keep'\n    },\n\n    /* Defines the maximum possible value a user can enter.\n     * Notes:\n     * - this value must be a string and use the period for the decimal point\n     * - this value needs to be larger than `minimumValue`\n     */\n    maximumValue: {\n        tenTrillions: '10000000000000', // 10000 billions\n        oneBillion: '1000000000',\n        zero: '0'\n    },\n\n    /* Defines the minimum possible value a user can enter.\n     * Notes:\n     * - this value must be a string and use the period for the decimal point\n     * - this value needs to be smaller than `maximumValue`\n     * - if this is superior to 0, then you'll effectively prevent your user to entirely delete the content of your element\n     */\n    minimumValue: {\n        tenTrillions: '-10000000000000', // 10000 billions\n        oneBillion: '-1000000000',\n        zero: '0'\n    },\n\n    /* Allows the user to increment or decrement the element value with the mouse wheel.\n     * The wheel behavior can be modified by the `wheelStep` option.\n     * This `wheelStep` option can be used in two ways, either by setting:\n     * - a 'fixed' step value (`wheelStep : 1000`), or\n     * - the 'progressive' string (`wheelStep : 'progressive'`), which will then activate a special mode where the step is automatically calculated based on the element value size.\n     *\n     * Note :\n     * You can activate/deactivate the wheel event for each `wheelOn` option value by using the 'Shift' modifier key while using the mouse wheel.\n     */\n    modifyValueOnWheel: {\n        modifyValue: true,\n        doNothing: false\n    },\n\n    /* Adds brackets on negative values (ie. transforms '-$ 999.99' to '($999.99)')\n     * Those brackets are visible only when the field does NOT have the focus.\n     * The left and right symbols should be enclosed in quotes and separated by a comma.\n     */\n    negativeBracketsTypeOnBlur: {\n        parentheses: '(,)',\n        brackets: '[,]',\n        chevrons: '<,>',\n        curlyBraces: '{,}',\n        angleBrackets: '〈,〉',\n        japaneseQuotationMarks: '｢,｣',\n        halfBrackets: '⸤,⸥',\n        whiteSquareBrackets: '⟦,⟧',\n        quotationMarks: '‹,›',\n        guillemets: '«,»',\n        none: null // This is the default value, which deactivate this feature\n    },\n\n    /* Placement of the negative/positive sign relative to the `currencySymbol` option.\n     *\n     * Example:\n     * // Default values\n     * -1,234.56  => default no options required\n     * $-1,234.56 => {currencySymbol: \"$\", negativePositiveSignPlacement: \"r\"} // Default if negativePositiveSignPlacement is 'null' and currencySymbol is not empty\n     *\n     * // Sign on the left hand side of the whole number\n     * -$1,234.56 => {currencySymbol: \"$\"} or {currencySymbol: \"$\", negativePositiveSignPlacement: \"l\"}\n     * -1,234.56$ => {currencySymbol: \"$\", currencySymbolPlacement: \"s\", negativePositiveSignPlacement: \"p\"} // Default if negativePositiveSignPlacement is 'null' and currencySymbol is not empty\n     *\n     * // Sign on the right hand side of the whole number\n     * 1,234.56-  => {negativePositiveSignPlacement: \"s\"}\n     * $1,234.56- => {currencySymbol: \"$\", negativePositiveSignPlacement: \"s\"}\n     * 1,234.56-$ => {currencySymbol: \"$\", currencySymbolPlacement: \"s\"}\n     * 1,234.56$- => {currencySymbol: \"$\", currencySymbolPlacement: \"s\", negativePositiveSignPlacement: \"r\"}\n     */\n    negativePositiveSignPlacement: {\n        prefix: 'p',\n        suffix: 's',\n        left: 'l',\n        right: 'r',\n        none: null\n    },\n\n    /* Defines the negative sign symbol.\n     * It can be a string of only one character.\n     */\n    negativeSignCharacter: {\n        hyphen: '-',\n        minus: '−',\n        heavyMinus: '➖',\n        fullWidthHyphen: '－',\n        circledMinus: '⊖',\n        squaredMinus: '⊟',\n        triangleMinus: '⨺',\n        plusMinus: '±',\n        minusPlus: '∓',\n        dotMinus: '∸',\n        minusTilde: '≂',\n        not: '¬'\n    },\n\n    /* Defines if the element should have event listeners activated on it.\n     * By default, those event listeners are only added to <input> elements and html element with the `contenteditable` attribute set to `true`, but not on the other html tags.\n     * This allows to initialize elements without any event listeners.\n     * Warning: Since AutoNumeric will not check the input content after its initialization, using some autoNumeric methods afterwards *will* probably leads to formatting problems.\n     */\n    noEventListeners: {\n        noEvents: true,\n        addEvents: false\n    },\n\n    /* Manage how autoNumeric react when the user tries to paste an invalid number.\n     * - 'error'    : (This is the default behavior) The input value is not changed and an error is output in the console.\n     * - 'ignore'   : idem than 'error', but fail silently without outputting any error/warning in the console.\n     * - 'clamp'    : if the pasted value is either too small or too big regarding the minimumValue and maximumValue range, then the result is clamped to those limits.\n     * - 'truncate' : autoNumeric will insert as many pasted numbers it can at the initial caret/selection, until everything is pasted, or the range limit is hit.\n     *                The non-pasted numbers are dropped and therefore not used at all.\n     * - 'replace'  : autoNumeric will first insert as many pasted numbers it can at the initial caret/selection, then if the range limit is hit, it will try\n     *                to replace one by one the remaining initial numbers (on the right side of the caret) with the rest of the pasted numbers.\n     *\n     * Note 1 : A paste content starting with a negative sign '-' will be accepted anywhere in the input, and will set the resulting value as a negative number\n     * Note 2 : A paste content starting with a number will be accepted, even if the rest is gibberish (ie. '123foobar456').\n     *          Only the first number will be used (here '123').\n     * Note 3 : The paste event works with the `decimalPlacesShownOnFocus` option too.\n     */\n    onInvalidPaste: {\n        error: 'error',\n        ignore: 'ignore',\n        clamp: 'clamp',\n        truncate: 'truncate',\n        replace: 'replace'\n    },\n\n    /* Defines how the value should be formatted when wanting a 'localized' version of it.\n     * - null or 'string' => 'nnnn.nn' or '-nnnn.nn' as text type. This is the default behavior.\n     * - 'number'         => nnnn.nn or -nnnn.nn as a Number (Warning: this works only for integers inferior to Number.MAX_SAFE_INTEGER)\n     * - ',' or '-,'      => 'nnnn,nn' or '-nnnn,nn'\n     * - '.-'             => 'nnnn.nn' or 'nnnn.nn-'\n     * - ',-'             => 'nnnn,nn' or 'nnnn,nn-'\n     *\n     * Note: The hyphen '-' is translated to the custom negative sign defined in `negativeSignCharacter`\n     */\n    outputFormat: {\n        string: 'string',\n        number: 'number',\n        dot: '.',\n        negativeDot: '-.',\n        comma: ',',\n        negativeComma: '-,',\n        dotNegative: '.-',\n        commaNegative: ',-',\n        none: null\n    },\n\n    /* Override the minimum and maximum limits\n     * overrideMinMaxLimits: \"ceiling\" adheres to maximumValue and ignores minimumValue settings\n     * overrideMinMaxLimits: \"floor\" adheres to minimumValue and ignores maximumValue settings\n     * overrideMinMaxLimits: \"ignore\" ignores both minimumValue & maximumValue\n     */\n    overrideMinMaxLimits: {\n        ceiling: 'ceiling',\n        floor: 'floor',\n        ignore: 'ignore',\n        doNotOverride: null\n    },\n\n    /* Defines the positive sign symbol.\n     * It can be a string of only one character.\n     * This is shown only if `showPositiveSign` is set to `true`.\n     */\n    positiveSignCharacter: {\n        plus: '+',\n        fullWidthPlus: '＋',\n        heavyPlus: '➕',\n        doublePlus: '⧺',\n        triplePlus: '⧻',\n        circledPlus: '⊕',\n        squaredPlus: '⊞',\n        trianglePlus: '⨹',\n        plusMinus: '±',\n        minusPlus: '∓',\n        dotPlus: '∔',\n        altHebrewPlus: '﬩',\n        normalSpace: ' ',\n        thinSpace: '\\u2009',\n        narrowNoBreakSpace: '\\u202F',\n        noBreakSpace: '\\xA0'\n    },\n\n    /* The `rawValueDivisor` divides the formatted value shown in the AutoNumeric element and store the result in `rawValue`.\n     * @example { rawValueDivisor: '100' } or <input data-raw-value-divisor=\"100\">\n     * Given the `0.01234` raw value, the formatted value will be displayed as `'1.234'`.\n     * This is useful when displaying percentage for instance, and avoid the need to divide/multiply by 100 between the number shown and the raw value.\n     */\n    rawValueDivisor: {\n        none: null,\n        percentage: 100,\n        permille: 1000,\n        basisPoint: 10000\n    },\n\n    /* Defines if the element (`<input>` or another allowed html tag) should be set as read-only on initialization.\n     * When set to `true`, then:\n     * - the `readonly` html property is added to the <input> element on initialization, or\n     * - the `contenteditable` attribute is set to `false` on non-input elements.\n     */\n    readOnly: {\n        readOnly: true,\n        readWrite: false\n    },\n\n    /* Defines the rounding method to use.\n     * roundingMethod: \"S\", Round-Half-Up Symmetric (default)\n     * roundingMethod: \"A\", Round-Half-Up Asymmetric\n     * roundingMethod: \"s\", Round-Half-Down Symmetric (lower case s)\n     * roundingMethod: \"a\", Round-Half-Down Asymmetric (lower case a)\n     * roundingMethod: \"B\", Round-Half-Even \"Bankers Rounding\"\n     * roundingMethod: \"U\", Round Up \"Round-Away-From-Zero\"\n     * roundingMethod: \"D\", Round Down \"Round-Toward-Zero\" - same as truncate\n     * roundingMethod: \"C\", Round to Ceiling \"Toward Positive Infinity\"\n     * roundingMethod: \"F\", Round to Floor \"Toward Negative Infinity\"\n     * roundingMethod: \"N05\" Rounds to the nearest .05 => same as \"CHF\" used in 1.9X and still valid\n     * roundingMethod: \"U05\" Rounds up to next .05\n     * roundingMethod: \"D05\" Rounds down to next .05\n     */\n    roundingMethod: {\n        halfUpSymmetric: 'S',\n        halfUpAsymmetric: 'A',\n        halfDownSymmetric: 's',\n        halfDownAsymmetric: 'a',\n        halfEvenBankersRounding: 'B',\n        upRoundAwayFromZero: 'U',\n        downRoundTowardZero: 'D',\n        toCeilingTowardPositiveInfinity: 'C',\n        toFloorTowardNegativeInfinity: 'F',\n        toNearest05: 'N05',\n        toNearest05Alt: 'CHF',\n        upToNext05: 'U05',\n        downToNext05: 'D05'\n    },\n\n    /* Set to `true` to allow the `decimalPlacesShownOnFocus` value to be saved with sessionStorage\n     * If IE 6 or 7 is detected, the value will be saved as a session cookie.\n     */\n    saveValueToSessionStorage: {\n        save: true,\n        doNotSave: false\n    },\n\n    /* Determine if the select all keyboard command will select the complete input text, or only the input numeric value\n     * Note : If the currency symbol is between the numeric value and the negative sign, only the numeric value will be selected\n     */\n    selectNumberOnly: {\n        selectNumbersOnly: true,\n        selectAll: false\n    },\n\n    /* Defines if the element value should be selected on focus.\n     * Note: The selection is done using the `selectNumberOnly` option.\n     */\n    selectOnFocus: {\n        select: true,\n        doNotSelect: false\n    },\n\n    /* Defines how the serialize functions should treat the spaces.\n     * Those spaces ' ' can either be converted to the plus sign '+', which is the default, or to '%20'.\n     * Both values being valid per the spec (http://www.w3.org/Addressing/URL/uri-spec.html).\n     * Also see the summed up answer on http://stackoverflow.com/a/33939287.\n     *\n     * tl;dr : Spaces should be converted to '%20' before the '?' sign, then converted to '+' after.\n     * In our case since we serialize the query, we use '+' as the default (but allow the user to get back the old *wrong* behavior).\n     */\n    serializeSpaces: {\n        plus: '+',\n        percent: '%20'\n    },\n\n    /* Defines if the element value should be converted to the raw value on focus (and back to the formatted on blur).\n     * If set to `true`, then autoNumeric remove the thousand separator, currency symbol and suffix on focus.\n     * Example:\n     * If the input value is '$ 1,999.88 suffix', on focus it becomes '1999.88' and back to '$ 1,999.88 suffix' on blur.\n     */\n    showOnlyNumbersOnFocus: {\n        onlyNumbers: true,\n        showAll: false\n    },\n\n    /* Allow the positive sign symbol `+` to be displayed for positive numbers.\n     * By default, this positive sign is not shown.\n     * The sign placement is controlled by the 'negativePositiveSignPlacement' option, mimicking the negative sign placement rules.\n     */\n    showPositiveSign: {\n        show: true,\n        hide: false\n    },\n\n    /* Defines if warnings should be shown in the console.\n     * Those warnings can be ignored, but are usually printed when something could be improved by the user (ie. option conflicts).\n     */\n    showWarnings: {\n        show: true, // All warning are shown\n        hide: false // No warnings are shown, only the thrown errors\n    },\n\n    /* Defines the rules that calculate the CSS class(es) to apply on the element, based on the raw unformatted value.\n     * This can also be used to call callbacks whenever the `rawValue` is updated.\n     * Important: all callbacks must return `null` if no ranges/userDefined classes are selected\n     * @example\n     * {\n     *     positive   : 'autoNumeric-positive', // Or `null` to not use it\n     *     negative   : 'autoNumeric-negative',\n     *     ranges     : [\n     *         { min: 0, max: 25, class: 'autoNumeric-red' },\n     *         { min: 25, max: 50, class: 'autoNumeric-orange' },\n     *         { min: 50, max: 75, class: 'autoNumeric-yellow' },\n     *         { min: 75, max: Number.MAX_SAFE_INTEGER, class: 'autoNumeric-green' },\n     *     ],\n     *     userDefined: [\n     *         // If 'classes' is a string, set it if `true`, remove it if `false`\n     *         { callback: rawValue => { return true; }, classes: 'thisIsTrue' },\n     *         // If 'classes' is an array with only 2 elements, set the first class if `true`, the second if `false`\n     *         { callback: rawValue => rawValue % 2 === 0, classes: ['autoNumeric-even', 'autoNumeric-odd'] },\n     *         // Return only one index to use on the `classes` array (here, 'class3')\n     *         { callback: rawValue => { return 2; }, classes: ['class1', 'class2', 'class3'] },\n     *         // Return an array of indexes to use on the `classes` array (here, 'class1' and 'class3')\n     *         { callback: rawValue => { return [0, 2]; }, classes: ['class1', 'class2', 'class3'] },\n     *         // If 'classes' is `undefined` or `null`, then the callback is called with the AutoNumeric object passed as a parameter\n     *         { callback: anElement => { return anElement.getFormatted(); } },\n     *     ],\n     * }\n     */\n    styleRules: {\n        none: null,\n        positiveNegative: {\n            positive: 'autoNumeric-positive',\n            negative: 'autoNumeric-negative'\n        },\n        range0To100With4Steps: {\n            ranges: [{ min: 0, max: 25, class: 'autoNumeric-red' }, { min: 25, max: 50, class: 'autoNumeric-orange' }, { min: 50, max: 75, class: 'autoNumeric-yellow' }, { min: 75, max: 100, class: 'autoNumeric-green' }]\n        },\n        evenOdd: {\n            userDefined: [{ callback: function callback(rawValue) {\n                    return rawValue % 2 === 0;\n                }, classes: ['autoNumeric-even', 'autoNumeric-odd'] }]\n        },\n        rangeSmallAndZero: {\n            userDefined: [{\n                callback: function callback(rawValue) {\n                    if (rawValue >= -1 && rawValue < 0) {\n                        return 0;\n                    }\n                    if (Number(rawValue) === 0) {\n                        return 1;\n                    }\n                    if (rawValue > 0 && rawValue <= 1) {\n                        return 2;\n                    }\n\n                    return null; // In case the rawValue is outside those ranges\n                },\n                classes: ['autoNumeric-small-negative', 'autoNumeric-zero', 'autoNumeric-small-positive']\n            }]\n        }\n    },\n\n    /* Add a text on the right hand side of the element value.\n     * This suffix text can have any characters in its string, except numeric characters and the negative/positive sign.\n     * Example: ' dollars'\n     */\n    suffixText: {\n        none: '',\n        percentage: '%',\n        permille: '‰',\n        basisPoint: '‱'\n    },\n\n    /* The three options (divisorWhenUnfocused, decimalPlacesShownOnBlur & symbolWhenUnfocused) handle scaling of the input when the input does not have focus\n     * Please note that the non-scaled value is held in data and it is advised that you use the `saveValueToSessionStorage` option to ensure retaining the value\n     * [\"divisor\", \"decimal places\", \"symbol\"]\n     * Example: with the following options set {divisorWhenUnfocused: '1000', decimalPlacesShownOnBlur: '1', symbolWhenUnfocused: ' K'}\n     * Example: focusin value \"1,111.11\" focusout value \"1.1 K\"\n     */\n\n    /* The `symbolWhenUnfocused` option is a symbol placed as a suffix when not in focus.\n     * This is optional too.\n     */\n    symbolWhenUnfocused: {\n        none: null,\n        percentage: '%',\n        permille: '‰',\n        basisPoint: '‱'\n    },\n\n    /* Defines if the element value should be unformatted when the user hover his mouse over it while holding the `Alt` key.\n     * Unformatting there means that this removes any non-number characters and displays the *raw* value, as understood by Javascript (ie. `12.34` is a valid number, while `12,34` is not).\n     *\n     * We reformat back before anything else if :\n     * - the user focus on the element by tabbing or clicking into it,\n     * - the user releases the `Alt` key, and\n     * - if we detect a mouseleave event.\n     *\n     * We unformat again if :\n     * - while the mouse is over the element, the user hit `Alt` again\n     */\n    unformatOnHover: {\n        unformat: true,\n        doNotUnformat: false //TODO Rename to `keepFormat`\n    },\n\n    /* Removes the formatting and use the raw value in each autoNumeric elements of the parent form element, on the form `submit` event.\n     * The output format is a numeric string (nnnn.nn or -nnnn.nn).\n     */\n    unformatOnSubmit: {\n        unformat: true,\n        keepCurrentValue: false\n    },\n\n    /* Provides a way for automatically replacing the formatted value with a pre-defined string, when the raw value is equal to a specific value\n     * Here you can specify as many 'conversion' as needed.\n     */\n    valuesToStrings: {\n        none: null,\n        zeroDash: {\n            0: '-'\n        },\n        oneAroundZero: {\n            '-1': 'Min',\n            1: 'Max'\n        }\n    },\n\n    /* Defines if the AutoNumeric element should watch external changes made without using `.set()`, but by using the basic `aNElement.node().value = 42` notation.\n     * If set to `watch`, then AutoNumeric will format the new value using `.set()` internally.\n     * Otherwise it will neither format it, nor save it in the history.\n     */\n    watchExternalChanges: {\n        watch: true,\n        doNotWatch: false\n    },\n\n    /* Defines when the wheel event will increment or decrement the element value.\n     * When set to `'focus'`, the AutoNumeric-managed element needs to be focused for the wheel event to change the value.\n     * When set to `'hover'`, using the wheel event while the mouse is hovering the element is sufficient (no focus needed).\n     *\n     * Note :\n     * When `wheelOn` is set to `'focus'`, you can use the 'Shift' modifier key while using the mouse wheel in order to temporarily activate the increment/decrement feature even if the element is not focused.\n     * When `wheelOn` is set to `'hover'`, you can use the 'Shift' modifier key while using the mouse wheel in order to temporarily disable the increment/decrement feature even if the element is not hovered.\n     */\n    wheelOn: {\n        focus: 'focus',\n        hover: 'hover'\n    },\n\n    /* That option is linked to the `modifyValueOnWheel` one and will only be used if the latter is set to `true`.\n     * This option will modify the wheel behavior and can be used in two ways, either by setting :\n     * - a 'fixed' step value (a positive float or integer number `1000`), or\n     * - the `'progressive'` string.\n     *\n     * The 'fixed' mode always increment/decrement the element value by that amount, while respecting the `minimumValue` and `maximumValue` settings.\n     * The 'progressive' mode will increment/decrement the element value based on its current value. The bigger the number, the bigger the step, and vice versa.\n     */\n    wheelStep: {\n        progressive: 'progressive'\n    }\n};\n\n/**\n * Simple function that will semi-deep freeze the `AutoNumeric.options` object.\n * By 'semi' it means the nested objects in the `styleRules` option are not frozen.\n * The ones in the `valuesToStrings` are though, since they are much more simple.\n *\n * @param {object} options\n * @returns {ReadonlyArray<any>}\n */\nfunction freezeOptions(options) {\n    // Freeze each property objects\n    Object.getOwnPropertyNames(options).forEach(function (optionName) {\n        if (optionName === 'valuesToStrings') {\n            var vsProps = Object.getOwnPropertyNames(options.valuesToStrings);\n            vsProps.forEach(function (valuesToStringObjectName) {\n                if (!_AutoNumericHelper2.default.isIE11() || options.valuesToStrings[valuesToStringObjectName] !== null) {\n                    Object.freeze(options.valuesToStrings[valuesToStringObjectName]);\n                }\n            });\n        } else if (optionName !== 'styleRules') {\n            if (!_AutoNumericHelper2.default.isIE11() || options[optionName] !== null) {\n                Object.freeze(options[optionName]);\n            }\n        }\n    });\n\n    // Then freeze the options object globally\n    return Object.freeze(options);\n}\n\nfreezeOptions(_AutoNumeric2.default.options);\nObject.defineProperty(_AutoNumeric2.default, 'options', { configurable: false, writable: false });\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvQXV0b051bWVyaWNPcHRpb25zLmpzLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vQXV0b051bWVyaWMvc3JjL0F1dG9OdW1lcmljT3B0aW9ucy5qcz9mMWI3Il0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogT3B0aW9ucyBmb3IgYXV0b051bWVyaWMuanNcbiAqIEBhdXRob3IgQWxleGFuZHJlIEJvbm5lYXUgPGFsZXhhbmRyZS5ib25uZWF1QGxpbnV4ZnIuZXU+XG4gKiBAY29weXJpZ2h0IMKpIDIwMTYgQWxleGFuZHJlIEJvbm5lYXVcbiAqXG4gKiBUaGUgTUlUIExpY2Vuc2UgKGh0dHA6Ly93d3cub3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvbWl0LWxpY2Vuc2UucGhwKVxuICpcbiAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uXG4gKiBvYnRhaW5pbmcgYSBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvblxuICogZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0XG4gKiByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSxcbiAqIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YiBsaWNlbnNlLCBhbmQvb3Igc2VsbFxuICogY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlXG4gKiBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZ1xuICogY29uZGl0aW9uczpcbiAqXG4gKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZVxuICogaW5jbHVkZWQgaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4gKlxuICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCxcbiAqIEVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFU1xuICogT0YgTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkRcbiAqIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUXG4gKiBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSxcbiAqIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lOR1xuICogRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUlxuICogT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuICovXG5cbmltcG9ydCBBdXRvTnVtZXJpYyBmcm9tICcuL0F1dG9OdW1lcmljJztcbmltcG9ydCBBdXRvTnVtZXJpY0hlbHBlciBmcm9tICcuL0F1dG9OdW1lcmljSGVscGVyJztcblxuLyoqXG4gKiBPcHRpb25zIHZhbHVlcyBlbnVtZXJhdGlvblxuICovXG5BdXRvTnVtZXJpYy5vcHRpb25zID0ge1xuICAgIC8qIERlZmluZXMgaWYgdGhlIGRlY2ltYWwgcGxhY2VzIHNob3VsZCBiZSBwYWRkZWQgd2l0aCB6ZXJvZXNcbiAgICAgKiBgdHJ1ZWAgICAgIDogYWx3YXlzIHBhZCBkZWNpbWFscyB3aXRoIHplcm9zIChpZS4gJzEyLjM0MDAnKVxuICAgICAqIGBmYWxzZWAgICAgOiBuZXZlciBwYWQgd2l0aCB6ZXJvcyAoaWUuICcxMi4zNCcpXG4gICAgICogYCdmbG9hdHMnYCA6IHBhZCB3aXRoIHplcm9lcyBvbmx5IHdoZW4gdGhlcmUgYXJlIGRlY2ltYWxzIChpZS4gJzEyJyBhbmQgJzEyLjM0MDAnKVxuICAgICAqIE5vdGU6IHNldHRpbmcgYWxsb3dEZWNpbWFsUGFkZGluZyB0byAnZmFsc2UnIHdpbGwgb3ZlcnJpZGUgdGhlICdkZWNpbWFsUGxhY2VzJyBzZXR0aW5nLlxuICAgICAqL1xuICAgIGFsbG93RGVjaW1hbFBhZGRpbmc6IHtcbiAgICAgICAgYWx3YXlzOiB0cnVlLFxuICAgICAgICBuZXZlciA6IGZhbHNlLFxuICAgICAgICBmbG9hdHM6ICdmbG9hdHMnLFxuICAgIH0sXG5cbiAgICAvKiBEZWZpbmVzIGlmIHRoZSBkZWNpbWFsIGNoYXJhY3RlciBvciBkZWNpbWFsIGNoYXJhY3RlciBhbHRlcm5hdGl2ZSBzaG91bGQgYmUgYWNjZXB0ZWQgd2hlbiB0aGVyZSBpcyBhbHJlYWR5IGEgZGVjaW1hbCBjaGFyYWN0ZXIgc2hvd24gaW4gdGhlIGVsZW1lbnQuXG4gICAgICogSWYgc2V0IHRvIGB0cnVlYCwgYW55IGRlY2ltYWwgY2hhcmFjdGVyIGlucHV0IHdpbGwgYmUgYWNjZXB0ZWQgYW5kIHdpbGwgc3Vic2VxdWVudGx5IG1vZGlmeSB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgcG9zaXRpb24sIGFzIHdlbGwgYXMgdGhlIGByYXdWYWx1ZWAuXG4gICAgICogSWYgc2V0IHRvIGBmYWxzZWAsIHRoZSBkZWNpbWFsIGNoYXJhY3RlciBhbmQgaXRzIGFsdGVybmF0aXZlIGtleSB3aWxsIGJlIGRyb3BwZWQgYXMgYmVmb3JlLiBUaGlzIGlzIHRoZSBkZWZhdWx0IHNldHRpbmcuXG4gICAgICovXG4gICAgYWx3YXlzQWxsb3dEZWNpbWFsQ2hhcmFjdGVyOiB7XG4gICAgICAgIGFsd2F5c0FsbG93OiB0cnVlLFxuICAgICAgICBkb05vdEFsbG93OiBmYWxzZSxcbiAgICB9LFxuXG4gICAgLyogRGVmaW5lcyB3aGVyZSBzaG91bGQgYmUgcG9zaXRpb25lZCB0aGUgY2FyZXQgb24gZm9jdXNcbiAgICAgKiBudWxsIDogRG8gbm90IGVuZm9yY2UgYW55IGNhcmV0IHBvc2l0aW9uaW5nIG9uIGZvY3VzICh0aGlzIGlzIG5lZWRlZCB3aGVuIHVzaW5nIGBzZWxlY3RPbkZvY3VzYClcbiAgICAgKiBgJ3N0YXJ0J2AgOiBwdXQgdGhlIGNhcmV0IG9mIHRoZSBmYXIgbGVmdCBzaWRlIG9mIHRoZSB2YWx1ZSAoZXhjbHVkaW5nIHRoZSBwb3NpdGl2ZS9uZWdhdGl2ZSBzaWduIGFuZCBjdXJyZW5jeSBzeW1ib2wsIGlmIGFueSlcbiAgICAgKiBgJ2VuZCdgIDogcHV0IHRoZSBjYXJldCBvZiB0aGUgZmFyIHJpZ2h0IHNpZGUgb2YgdGhlIHZhbHVlIChleGNsdWRpbmcgdGhlIHBvc2l0aXZlL25lZ2F0aXZlIHNpZ24gYW5kIGN1cnJlbmN5IHN5bWJvbCwgaWYgYW55KVxuICAgICAqIGAnZGVjaW1hbExlZnQnYCA6IHB1dCB0aGUgY2FyZXQgb2YgdGhlIGxlZnQgb2YgdGhlIGRlY2ltYWwgY2hhcmFjdGVyIGlmIGFueVxuICAgICAqIGAnZGVjaW1hbFJpZ2h0J2AgOiBwdXQgdGhlIGNhcmV0IG9mIHRoZSByaWdodCBvZiB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgaWYgYW55XG4gICAgICovXG4gICAgY2FyZXRQb3NpdGlvbk9uRm9jdXM6IHtcbiAgICAgICAgc3RhcnQgICAgICAgICAgICAgICAgIDogJ3N0YXJ0JyxcbiAgICAgICAgZW5kICAgICAgICAgICAgICAgICAgIDogJ2VuZCcsXG4gICAgICAgIGRlY2ltYWxMZWZ0ICAgICAgICAgICA6ICdkZWNpbWFsTGVmdCcsXG4gICAgICAgIGRlY2ltYWxSaWdodCAgICAgICAgICA6ICdkZWNpbWFsUmlnaHQnLFxuICAgICAgICBkb05vRm9yY2VDYXJldFBvc2l0aW9uOiBudWxsLFxuICAgIH0sXG5cbiAgICAvKiBEZWZpbmVzIGlmIGEgbG9jYWwgbGlzdCBvZiBBdXRvTnVtZXJpYyBvYmplY3RzIHNob3VsZCBiZSBrZXB0IHdoZW4gaW5pdGlhbGl6aW5nIHRoaXMgb2JqZWN0LlxuICAgICAqIFRoaXMgbGlzdCBpcyB1c2VkIGJ5IHRoZSBgZ2xvYmFsLipgIGZ1bmN0aW9ucy5cbiAgICAgKi9cbiAgICBjcmVhdGVMb2NhbExpc3Q6IHtcbiAgICAgICAgY3JlYXRlTGlzdCAgICAgOiB0cnVlLFxuICAgICAgICBkb05vdENyZWF0ZUxpc3Q6IGZhbHNlLFxuICAgIH0sXG5cbiAgICAvKiBEZWZpbmVzIHRoZSBjdXJyZW5jeSBzeW1ib2wgc3RyaW5nLlxuICAgICAqIEl0IGNhbiBiZSBhIHN0cmluZyBvZiBtb3JlIHRoYW4gb25lIGNoYXJhY3RlciAoYWxsb3dpbmcgZm9yIGluc3RhbmNlIHRvIHVzZSBhIHNwYWNlIG9uIGVpdGhlciBzaWRlIG9mIGl0LCBleGFtcGxlOiAnJCAnIG9yICcgJCcpXG4gICAgICogY2YuIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0N1cnJlbmN5X3N5bWJvbFxuICAgICAqL1xuICAgIGN1cnJlbmN5U3ltYm9sOiB7XG4gICAgICAgIG5vbmUgICAgICAgICAgOiAnJyxcbiAgICAgICAgY3VycmVuY3lTaWduICA6ICfCpCcsXG4gICAgICAgIGF1c3RyYWwgICAgICAgOiAn4oKzJywgLy8gQVJBXG4gICAgICAgIGF1c3RyYWxDZW50YXZvOiAnwqInLFxuICAgICAgICBiYWh0ICAgICAgICAgIDogJ+C4vycsIC8vIFRIQlxuICAgICAgICBjZWRpICAgICAgICAgIDogJ+KCtScsIC8vIEdIU1xuICAgICAgICBjZW50ICAgICAgICAgIDogJ8KiJyxcbiAgICAgICAgY29sb24gICAgICAgICA6ICfigqEnLCAvLyBDUkNcbiAgICAgICAgY3J1emVpcm8gICAgICA6ICfigqInLCAvLyBCUkIgLSBOb3QgdXNlZCBhbnltb3JlIHNpbmNlIDE5OTNcbiAgICAgICAgZG9sbGFyICAgICAgICA6ICckJyxcbiAgICAgICAgZG9uZyAgICAgICAgICA6ICfigqsnLCAvLyBWTkRcbiAgICAgICAgZHJhY2htYSAgICAgICA6ICfigq8nLCAvLyBHUkQgKG9yICfOlM+Bz4cuJyBvciAnzpTPgS4nKVxuICAgICAgICBkcmFtICAgICAgICAgIDogJ+KAi9aPJywgLy8gQU1EXG4gICAgICAgIGV1cm9wZWFuICAgICAgOiAn4oKgJywgLy8gWEVVIChvbGQgY3VycmVuY3kgYmVmb3JlIHRoZSBFdXJvKVxuICAgICAgICBldXJvICAgICAgICAgIDogJ+KCrCcsIC8vIEVVUlxuICAgICAgICBmbG9yaW4gICAgICAgIDogJ8aSJyxcbiAgICAgICAgZnJhbmMgICAgICAgICA6ICfigqMnLCAvLyBGUkZcbiAgICAgICAgZ3VhcmFuaSAgICAgICA6ICfigrInLCAvLyBQWUdcbiAgICAgICAgaHJ5dm5pYSAgICAgICA6ICfigrQnLCAvLyDQs9GA0L1cbiAgICAgICAga2lwICAgICAgICAgICA6ICfigq0nLCAvLyBMQUtcbiAgICAgICAgYXR0ICAgICAgICAgICA6ICfguq3gurHgupQnLCAvLyBjZW50cyBvZiB0aGUgS2lwXG4gICAgICAgIGxlcHRvbiAgICAgICAgOiAnzpsuJywgLy8gY2VudHMgb2YgdGhlIERyYWNobWFcbiAgICAgICAgbGlyYSAgICAgICAgICA6ICfigronLCAvLyBUUllcbiAgICAgICAgbGlyYU9sZCAgICAgICA6ICfigqQnLFxuICAgICAgICBsYXJpICAgICAgICAgIDogJ+KCvicsIC8vIEdFTFxuICAgICAgICBtYXJrICAgICAgICAgIDogJ+KEsycsXG4gICAgICAgIG1pbGwgICAgICAgICAgOiAn4oKlJyxcbiAgICAgICAgbmFpcmEgICAgICAgICA6ICfigqYnLCAvLyBOR05cbiAgICAgICAgcGVzZXRhICAgICAgICA6ICfigqcnLFxuICAgICAgICBwZXNvICAgICAgICAgIDogJ+KCsScsIC8vIFBIUFxuICAgICAgICBwZmVubmlnICAgICAgIDogJ+KCsCcsIC8vIGNlbnRzIG9mIHRoZSBNYXJrXG4gICAgICAgIHBvdW5kICAgICAgICAgOiAnwqMnLFxuICAgICAgICByZWFsICAgICAgICAgIDogJ1IkJywgLy8gQnJhemlsaWFuIHJlYWxcbiAgICAgICAgcmllbCAgICAgICAgICA6ICfhn5snLCAvLyBLSFJcbiAgICAgICAgcnVibGUgICAgICAgICA6ICfigr0nLCAvLyBSVUJcbiAgICAgICAgcnVwZWUgICAgICAgICA6ICfigrknLCAvLyBJTlJcbiAgICAgICAgcnVwZWVPbGQgICAgICA6ICfigqgnLFxuICAgICAgICBzaGVrZWwgICAgICAgIDogJ+KCqicsXG4gICAgICAgIHNoZWtlbEFsdCAgICAgOiAn16nXtNeX4oCO4oCOJyxcbiAgICAgICAgdGFrYSAgICAgICAgICA6ICfgp7MnLCAvLyBCRFRcbiAgICAgICAgdGVuZ2UgICAgICAgICA6ICfigrgnLCAvLyBLWlRcbiAgICAgICAgdG9ncm9nICAgICAgICA6ICfigq4nLCAvLyBNTlRcbiAgICAgICAgd29uICAgICAgICAgICA6ICfigqknLFxuICAgICAgICB5ZW4gICAgICAgICAgIDogJ8KlJyxcbiAgICB9LFxuXG4gICAgLyogRGVmaW5lcyB3aGVyZSB0aGUgY3VycmVuY3kgc3ltYm9sIHNob3VsZCBiZSBwbGFjZWQgKGJlZm9yZSBvZiBhZnRlciB0aGUgbnVtYmVycylcbiAgICAgKiBmb3IgcHJlZml4IGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50OiBcInBcIiAoZGVmYXVsdClcbiAgICAgKiBmb3Igc3VmZml4IGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50OiBcInNcIlxuICAgICAqL1xuICAgIGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50OiB7XG4gICAgICAgIHByZWZpeDogJ3AnLFxuICAgICAgICBzdWZmaXg6ICdzJyxcbiAgICB9LFxuXG4gICAgLyogRGVmaW5lcyB3aGF0IGRlY2ltYWwgc2VwYXJhdG9yIGNoYXJhY3RlciBpcyB1c2VkXG4gICAgICovXG4gICAgZGVjaW1hbENoYXJhY3Rlcjoge1xuICAgICAgICBjb21tYSAgICAgICAgICAgICAgICAgICAgOiAnLCcsXG4gICAgICAgIGRvdCAgICAgICAgICAgICAgICAgICAgICA6ICcuJyxcbiAgICAgICAgbWlkZGxlRG90ICAgICAgICAgICAgICAgIDogJ8K3JyxcbiAgICAgICAgYXJhYmljRGVjaW1hbFNlcGFyYXRvciAgIDogJ9mrJyxcbiAgICAgICAgZGVjaW1hbFNlcGFyYXRvcktleVN5bWJvbDogJ+KOlicsXG4gICAgfSxcblxuICAgIC8qIEFsbG93IHRvIGRlY2xhcmUgYW4gYWx0ZXJuYXRpdmUgZGVjaW1hbCBzZXBhcmF0b3Igd2hpY2ggaXMgYXV0b21hdGljYWxseSByZXBsYWNlZCBieSBgZGVjaW1hbENoYXJhY3RlcmAgd2hlbiB0eXBlZC5cbiAgICAgKiBUaGlzIGlzIHVzZWQgYnkgY291bnRyaWVzIHRoYXQgdXNlIGEgY29tbWEgJywnIGFzIHRoZSBkZWNpbWFsIGNoYXJhY3RlciBhbmQgaGF2ZSBrZXlib2FyZHMgd2l0aCBhIG51bWVyaWMgcGFkcyB0aGF0IGhhdmVcbiAgICAgKiBhIHBlcmlvZCAnZnVsbCBzdG9wJyBhcyB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgKEZyYW5jZSBvciBTcGFpbiBmb3IgaW5zdGFuY2UpLlxuICAgICAqL1xuICAgIGRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZToge1xuICAgICAgICBub25lIDogbnVsbCxcbiAgICAgICAgY29tbWE6ICcsJyxcbiAgICAgICAgZG90ICA6ICcuJyxcbiAgICB9LFxuXG4gICAgLyogRGVmaW5lcyB0aGUgZGVmYXVsdCBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgdG8gc2hvdyBvbiB0aGUgZm9ybWF0dGVkIHZhbHVlLCBhbmQga2VlcCBmb3IgdGhlIHByZWNpc2lvbi5cbiAgICAgKiBJbmNpZGVudGFsbHksIHNpbmNlIHdlIG5lZWQgdG8gYmUgYWJsZSB0byBzaG93IHRoYXQgbWFueSBkZWNpbWFsIHBsYWNlcywgdGhpcyBhbHNvIGRlZmluZXMgdGhlIHJhdyB2YWx1ZSBwcmVjaXNpb24gYnkgZGVmYXVsdC5cbiAgICAgKi9cbiAgICBkZWNpbWFsUGxhY2VzOiB7XG4gICAgICAgIG5vbmUgOiAwLFxuICAgICAgICBvbmUgIDogMSxcbiAgICAgICAgdHdvICA6IDIsXG4gICAgICAgIHRocmVlOiAzLFxuICAgICAgICBmb3VyIDogNCxcbiAgICAgICAgZml2ZSA6IDUsXG4gICAgICAgIHNpeCAgOiA2LFxuICAgIH0sXG5cbiAgICAvKiBEZWZpbmVzIGhvdyBtYW55IGRlY2ltYWwgcGxhY2VzIHNob3VsZCBiZSBrZXB0IGZvciB0aGUgcmF3IHZhbHVlIChpZS4gVGhpcyBpcyB0aGUgcHJlY2lzaW9uIGZvciBmbG9hdCB2YWx1ZXMpLlxuICAgICAqXG4gICAgICogSWYgdGhpcyBvcHRpb24gaXMgc2V0IHRvIGBudWxsYCAod2hpY2ggaXMgdGhlIGRlZmF1bHQpLCB0aGVuIHRoZSB2YWx1ZSBvZiBgZGVjaW1hbFBsYWNlc2AgaXMgdXNlZCBmb3IgYGRlY2ltYWxQbGFjZXNSYXdWYWx1ZWAgYXMgd2VsbC5cbiAgICAgKiBOb3RlOiBTZXR0aW5nIHRoaXMgdG8gYSBsb3dlciBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgdGhhbiB0aGUgb25lIHRvIGJlIHNob3duIHdpbGwgbGVhZCB0byBjb25mdXNpb24gZm9yIHRoZSB1c2Vycy5cbiAgICAgKi9cbiAgICBkZWNpbWFsUGxhY2VzUmF3VmFsdWU6IHtcbiAgICAgICAgdXNlRGVmYXVsdDogbnVsbCxcbiAgICAgICAgbm9uZSAgICAgIDogMCxcbiAgICAgICAgb25lICAgICAgIDogMSxcbiAgICAgICAgdHdvICAgICAgIDogMixcbiAgICAgICAgdGhyZWUgICAgIDogMyxcbiAgICAgICAgZm91ciAgICAgIDogNCxcbiAgICAgICAgZml2ZSAgICAgIDogNSxcbiAgICAgICAgc2l4ICAgICAgIDogNixcbiAgICB9LFxuXG4gICAgLyogRGVmaW5lcyBob3cgbWFueSBkZWNpbWFsIHBsYWNlcyBzaG91bGQgYmUgdmlzaWJsZSB3aGVuIHRoZSBlbGVtZW50IGlzIHVuZm9jdXNlZC5cbiAgICAgKiBJZiB0aGlzIGlzIHNldCB0byBgbnVsbGAsIHRoZW4gdGhpcyBvcHRpb24gaXMgaWdub3JlZCwgYW5kIHRoZSBgZGVjaW1hbFBsYWNlc2Agb3B0aW9uIHZhbHVlIHdpbGwgYmUgdXNlZCBpbnN0ZWFkLlxuICAgICAqIFRoaXMgbWVhbnMgdGhpcyBpcyBvcHRpb25hbCA7IGlmIG9taXR0ZWQgdGhlIGRlY2ltYWwgcGxhY2VzIHdpbGwgYmUgdGhlIHNhbWUgd2hlbiB0aGUgaW5wdXQgaGFzIHRoZSBmb2N1cy5cbiAgICAgKlxuICAgICAqIFRoaXMgb3B0aW9uIGNhbiBiZSB1c2VkIGluIGNvbmpvbmN0aW9uIHdpdGggdGhlIHR3byBvdGhlciBgc2NhbGUqYCBvcHRpb25zLCB3aGljaCBhbGxvd3MgdG8gZGlzcGxheSBhIGRpZmZlcmVudCBmb3JtYXR0ZWQgdmFsdWUgd2hlbiB0aGUgZWxlbWVudCBpcyB1bmZvY3VzZWQsIHdoaWxlIGFub3RoZXIgZm9ybWF0dGVkIHZhbHVlIGlzIHNob3duIHdoZW4gZm9jdXNlZC5cbiAgICAgKiBGb3IgdGhvc2UgYHNjYWxlKmAgb3B0aW9ucyB0byBoYXZlIGFueSBlZmZlY3QsIGBkaXZpc29yV2hlblVuZm9jdXNlZGAgbXVzdCBub3QgYmUgYG51bGxgLlxuICAgICAqL1xuICAgIGRlY2ltYWxQbGFjZXNTaG93bk9uQmx1cjoge1xuICAgICAgICB1c2VEZWZhdWx0OiBudWxsLFxuICAgICAgICBub25lICAgICAgOiAwLFxuICAgICAgICBvbmUgICAgICAgOiAxLFxuICAgICAgICB0d28gICAgICAgOiAyLFxuICAgICAgICB0aHJlZSAgICAgOiAzLFxuICAgICAgICBmb3VyICAgICAgOiA0LFxuICAgICAgICBmaXZlICAgICAgOiA1LFxuICAgICAgICBzaXggICAgICAgOiA2LFxuICAgIH0sXG5cbiAgICAvKiBEZWZpbmVzIGhvdyBtYW55IGRlY2ltYWwgcGxhY2VzIHNob3VsZCBiZSB2aXNpYmxlIHdoZW4gdGhlIGVsZW1lbnQgaGFzIHRoZSBmb2N1cy5cbiAgICAgKiBJZiB0aGlzIGlzIHNldCB0byBgbnVsbGAsIHRoZW4gdGhpcyBvcHRpb24gaXMgaWdub3JlZCwgYW5kIHRoZSBgZGVjaW1hbFBsYWNlc2Agb3B0aW9uIHZhbHVlIHdpbGwgYmUgdXNlZCBpbnN0ZWFkLlxuICAgICAqXG4gICAgICogRXhhbXBsZTpcbiAgICAgKiBGb3IgaW5zdGFuY2UgaWYgYGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXNgIGlzIHNldCB0byBgNWAgYW5kIHRoZSBkZWZhdWx0IG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyBpcyBgMmAsIHRoZW4gb24gZm9jdXMgYDEsMDAwLjEyMzQ1YCB3aWxsIGJlIHNob3duLCB3aGlsZSB3aXRob3V0IGZvY3VzIGAxLDAwMC4xMmAgd2lsbCBiZSBzZXQgYmFjay5cbiAgICAgKiBOb3RlIDE6IHRoZSByZXN1bHRzIGRlcGVuZHMgb24gdGhlIHJvdW5kaW5nIG1ldGhvZCB1c2VkLlxuICAgICAqIE5vdGUgMjogdGhlIGBnZXROdW1lcmljU3RyaW5nKClgIG1ldGhvZCByZXR1cm5zIHRoZSBleHRlbmRlZCBkZWNpbWFsIHBsYWNlc1xuICAgICAqL1xuICAgIGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXM6IHtcbiAgICAgICAgdXNlRGVmYXVsdDogbnVsbCxcbiAgICAgICAgbm9uZSAgICAgIDogMCxcbiAgICAgICAgb25lICAgICAgIDogMSxcbiAgICAgICAgdHdvICAgICAgIDogMixcbiAgICAgICAgdGhyZWUgICAgIDogMyxcbiAgICAgICAgZm91ciAgICAgIDogNCxcbiAgICAgICAgZml2ZSAgICAgIDogNSxcbiAgICAgICAgc2l4ICAgICAgIDogNixcbiAgICB9LFxuXG4gICAgLyogSGVscGVyIG9wdGlvbiBmb3IgQVNQLk5FVCBwb3N0YmFja1xuICAgICAqIFRoaXMgc2hvdWxkIGJlIHNldCBhcyB0aGUgdmFsdWUgb2YgdGhlIHVuZm9ybWF0dGVkIGRlZmF1bHQgdmFsdWVcbiAgICAgKiBleGFtcGxlczpcbiAgICAgKiBubyBkZWZhdWx0IHZhbHVlPVwiXCIge2RlZmF1bHRWYWx1ZU92ZXJyaWRlOiBcIlwifVxuICAgICAqIHZhbHVlPTEyMzQuNTYge2RlZmF1bHRWYWx1ZU92ZXJyaWRlOiAnMTIzNC41Nid9XG4gICAgICovXG4gICAgZGVmYXVsdFZhbHVlT3ZlcnJpZGU6IHtcbiAgICAgICAgZG9Ob3RPdmVycmlkZTogbnVsbCxcbiAgICB9LFxuXG4gICAgLyogRGVmaW5lcyBob3cgbWFueSBudW1iZXJzIHNob3VsZCBiZSBncm91cGVkIHRvZ2V0aGVyICh1c3VhbGx5IGZvciB0aGUgdGhvdXNhbmQgc2VwYXJhdG9yKVxuICAgICAqIC0gXCIyXCIsICByZXN1bHRzIGluIDk5LDk5LDk5LDk5OSBJbmRpYSdzIGxha2hzXG4gICAgICogLSBcIjJzXCIsIHJlc3VsdHMgaW4gOTksOTk5LDk5LDk5LDk5OSBJbmRpYSdzIGxha2hzIHNjYWxlZFxuICAgICAqIC0gXCIzXCIsICByZXN1bHRzIGluIDk5OSw5OTksOTk5IChkZWZhdWx0KVxuICAgICAqIC0gXCI0XCIsICByZXN1bHRzIGluIDk5OTksOTk5OSw5OTk5IHVzZWQgaW4gc29tZSBBc2lhbiBjb3VudHJpZXNcbiAgICAgKiBOb3RlOiBUaGlzIG9wdGlvbiBkb2VzIG5vdCBhY2NlcHQgb3RoZXIgZ3JvdXBpbmcgY2hvaWNlLlxuICAgICAqL1xuICAgIGRpZ2l0YWxHcm91cFNwYWNpbmc6IHtcbiAgICAgICAgdHdvICAgICAgOiAnMicsXG4gICAgICAgIHR3b1NjYWxlZDogJzJzJyxcbiAgICAgICAgdGhyZWUgICAgOiAnMycsXG4gICAgICAgIGZvdXIgICAgIDogJzQnLFxuICAgIH0sXG5cbiAgICAvKiBEZWZpbmVzIHRoZSB0aG91c2FuZCBncm91cGluZyBzZXBhcmF0b3IgY2hhcmFjdGVyXG4gICAgICogRXhhbXBsZSA6IElmIGAnLidgIGlzIHNldCwgdGhlbiB5b3UnbGwgZ2V0IGAnMS4yMzQuNTY3J2BcbiAgICAgKi9cbiAgICBkaWdpdEdyb3VwU2VwYXJhdG9yOiB7XG4gICAgICAgIGNvbW1hICAgICAgICAgICAgICAgICAgIDogJywnLFxuICAgICAgICBkb3QgICAgICAgICAgICAgICAgICAgICA6ICcuJyxcbiAgICAgICAgbm9ybWFsU3BhY2UgICAgICAgICAgICAgOiAnICcsXG4gICAgICAgIHRoaW5TcGFjZSAgICAgICAgICAgICAgIDogJ1xcdTIwMDknLFxuICAgICAgICBuYXJyb3dOb0JyZWFrU3BhY2UgICAgICA6ICdcXHUyMDJmJyxcbiAgICAgICAgbm9CcmVha1NwYWNlICAgICAgICAgICAgOiAnXFx1MDBhMCcsXG4gICAgICAgIG5vU2VwYXJhdG9yICAgICAgICAgICAgIDogJycsXG4gICAgICAgIGFwb3N0cm9waGUgICAgICAgICAgICAgIDogYCdgLFxuICAgICAgICBhcmFiaWNUaG91c2FuZHNTZXBhcmF0b3I6ICfZrCcsXG4gICAgICAgIGRvdEFib3ZlICAgICAgICAgICAgICAgIDogJ8uZJyxcbiAgICB9LFxuXG4gICAgLyogVGhlIGBkaXZpc29yV2hlblVuZm9jdXNlZGAgZGl2aWRlIHRoZSBlbGVtZW50IHZhbHVlIG9uIGZvY3VzLlxuICAgICAqIE9uIGJsdXIsIHRoZSBlbGVtZW50IHZhbHVlIGlzIG11bHRpcGxpZWQgYmFjay5cbiAgICAgKlxuICAgICAqIEV4YW1wbGUgOiBEaXNwbGF5IHBlcmNlbnRhZ2VzIHVzaW5nIHsgZGl2aXNvcldoZW5VbmZvY3VzZWQ6IDEwMCB9IChvciBkaXJlY3RseSBpbiB0aGUgSHRtbCB3aXRoIGA8aW5wdXQgZGF0YS1kaXZpc29yLXdoZW4tdW5mb2N1c2VkPVwiMTAwXCI+YClcbiAgICAgKiBUaGUgZGl2aXNvciB2YWx1ZSBkb2VzIG5vdCBuZWVkIHRvIGJlIGFuIGludGVnZXIsIGJ1dCBwbGVhc2UgdW5kZXJzdGFuZCB0aGF0IEphdmFzY3JpcHQgaGFzIGxpbWl0ZWQgYWNjdXJhY3kgaW4gbWF0aCA7IHVzZSB3aXRoIGNhdXRpb24uXG4gICAgICogTm90ZTogVGhlIGBnZXROdW1lcmljU3RyaW5nYCBtZXRob2QgcmV0dXJucyB0aGUgZnVsbCB2YWx1ZSwgaW5jbHVkaW5nIHRoZSAnaGlkZGVuJyBkZWNpbWFscy5cbiAgICAgKi9cbiAgICBkaXZpc29yV2hlblVuZm9jdXNlZDoge1xuICAgICAgICBub25lICAgICAgOiBudWxsLFxuICAgICAgICBwZXJjZW50YWdlOiAxMDAsXG4gICAgICAgIHBlcm1pbGxlICA6IDEwMDAsXG4gICAgICAgIGJhc2lzUG9pbnQ6IDEwMDAwLFxuICAgIH0sXG5cbiAgICAvKiBEZWZpbmVzIHdoYXQgc2hvdWxkIGJlIGRpc3BsYXllZCBpbiB0aGUgZWxlbWVudCBpZiB0aGUgcmF3IHZhbHVlIGlzIGFuIGVtcHR5IHN0cmluZyAoJycpLlxuICAgICAqIC0gJ2ZvY3VzJyAgOiBUaGUgY3VycmVuY3kgc2lnbiBpcyBkaXNwbGF5ZWQgd2hlbiB0aGUgaW5wdXQgcmVjZWl2ZXMgZm9jdXMgKGRlZmF1bHQpXG4gICAgICogLSAncHJlc3MnICA6IFRoZSBjdXJyZW5jeSBzaWduIGlzIGRpc3BsYXllZCB3aGVuZXZlciBhIGtleSBpcyBiZWluZyBwcmVzc2VkXG4gICAgICogLSAnYWx3YXlzJyA6IFRoZSBjdXJyZW5jeSBzaWduIGlzIGFsd2F5cyBkaXNwbGF5ZWRcbiAgICAgKiAtICd6ZXJvJyAgIDogQSB6ZXJvIGlzIGRpc3BsYXllZCAoJ3JvdW5kZWQnIHdpdGggb3Igd2l0aG91dCBhIGN1cnJlbmN5IHNpZ24pIGlmIHRoZSBpbnB1dCBoYXMgbm8gdmFsdWUgb24gZm9jdXMgb3V0XG4gICAgICogLSAnbWluJyAgICA6IFRoZSBtaW5pbXVtIHZhbHVlIGlzIGRpc3BsYXllZCBpZiB0aGUgaW5wdXQgaGFzIG5vIHZhbHVlIG9uIGZvY3VzIG91dFxuICAgICAqIC0gJ21heCcgICAgOiBUaGUgbWF4aW11bSB2YWx1ZSBpcyBkaXNwbGF5ZWQgaWYgdGhlIGlucHV0IGhhcyBubyB2YWx1ZSBvbiBmb2N1cyBvdXRcbiAgICAgKiAtICdudWxsJyAgIDogV2hlbiB0aGUgZWxlbWVudCBpcyBlbXB0eSwgdGhlIGByYXdWYWx1ZWAgYW5kIHRoZSBlbGVtZW50IHZhbHVlL3RleHQgaXMgc2V0IHRvIGBudWxsYC4gVGhpcyBhbHNvIGFsbG93cyB0byBzZXQgdGhlIHZhbHVlIHRvIGBudWxsYCB1c2luZyBgYW5FbGVtZW50LnNldChudWxsKWAuXG4gICAgICovXG4gICAgZW1wdHlJbnB1dEJlaGF2aW9yOiB7XG4gICAgICAgIGZvY3VzIDogJ2ZvY3VzJyxcbiAgICAgICAgcHJlc3MgOiAncHJlc3MnLFxuICAgICAgICBhbHdheXM6ICdhbHdheXMnLFxuICAgICAgICB6ZXJvICA6ICd6ZXJvJyxcbiAgICAgICAgbWluICAgOiAnbWluJyxcbiAgICAgICAgbWF4ICAgOiAnbWF4JyxcbiAgICAgICAgbnVsbCAgOiAnbnVsbCcsXG4gICAgfSxcblxuICAgIC8qIERlZmluZXMgaWYgdGhlIGN1c3RvbSBhbmQgbmF0aXZlIGV2ZW50cyB0cmlnZ2VyZWQgYnkgQXV0b051bWVyaWMgc2hvdWxkIGJ1YmJsZSB1cCBvciBub3QuXG4gICAgICovXG4gICAgZXZlbnRCdWJibGVzOiB7XG4gICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgIGRvZXNOb3RCdWJibGU6IGZhbHNlLFxuICAgIH0sXG5cbiAgICAvKiBEZWZpbmVzIGlmIHRoZSBjdXN0b20gYW5kIG5hdGl2ZSBldmVudHMgdHJpZ2dlcmVkIGJ5IEF1dG9OdW1lcmljIHNob3VsZCBiZSBjYW5jZWxhYmxlLlxuICAgICAqL1xuICAgIGV2ZW50SXNDYW5jZWxhYmxlOiB7XG4gICAgICAgIGlzQ2FuY2VsYWJsZTogdHJ1ZSxcbiAgICAgICAgaXNOb3RDYW5jZWxhYmxlOiBmYWxzZSxcbiAgICB9LFxuXG4gICAgLyogVGhpcyBvcHRpb24gaXMgdGhlICdzdHJpY3QgbW9kZScgKGFrYSAnZGVidWcnIG1vZGUpLCB3aGljaCBhbGxvd3MgYXV0b051bWVyaWMgdG8gc3RyaWN0bHkgYW5hbHlzZSB0aGUgb3B0aW9ucyBwYXNzZWQsIGFuZCBmYWlscyBpZiBhbiB1bmtub3duIG9wdGlvbnMgaXMgdXNlZCBpbiB0aGUgc2V0dGluZ3Mgb2JqZWN0LlxuICAgICAqIFlvdSBzaG91bGQgc2V0IHRoYXQgdG8gYHRydWVgIGlmIHlvdSB3YW50IHRvIG1ha2Ugc3VyZSB5b3UgYXJlIG9ubHkgdXNpbmcgJ3B1cmUnIGF1dG9OdW1lcmljIHNldHRpbmdzIG9iamVjdHMgaW4geW91ciBjb2RlLlxuICAgICAqIElmIHlvdSBzZWUgdW5jYXVnaHQgZXJyb3JzIGluIHRoZSBjb25zb2xlIGFuZCB5b3VyIGNvZGUgc3RhcnRzIHRvIGZhaWwsIHRoaXMgbWVhbnMgc29tZWhvdyB0aG9zZSBvcHRpb25zIGdldHMgcG9sbHV0ZWQgYnkgYW5vdGhlciBwcm9ncmFtICh3aGljaCB1c3VhbGx5IGhhcHBlbnMgd2hlbiB1c2luZyBmcmFtZXdvcmtzKS5cbiAgICAgKi9cbiAgICBmYWlsT25Vbmtub3duT3B0aW9uOiB7XG4gICAgICAgIGZhaWwgIDogdHJ1ZSxcbiAgICAgICAgaWdub3JlOiBmYWxzZSxcbiAgICB9LFxuXG4gICAgLyogRGV0ZXJtaW5lIGlmIHRoZSBkZWZhdWx0IHZhbHVlIHdpbGwgYmUgZm9ybWF0dGVkIG9uIGluaXRpYWxpemF0aW9uLlxuICAgICAqL1xuICAgIGZvcm1hdE9uUGFnZUxvYWQ6IHtcbiAgICAgICAgZm9ybWF0ICAgICA6IHRydWUsIC8vIGF1dG9tYXRpY2FsbHkgZm9ybWF0cyB0aGUgZGVmYXVsdCB2YWx1ZSBvbiBpbml0aWFsaXphdGlvblxuICAgICAgICBkb05vdEZvcm1hdDogZmFsc2UsIC8vIHdpbGwgbm90IGZvcm1hdCB0aGUgZGVmYXVsdCB2YWx1ZSBvbiBpbml0aWFsaXphdGlvblxuICAgIH0sXG5cbiAgICAvKiBTZXQgdGhlIHVuZG8vcmVkbyBoaXN0b3J5IHRhYmxlIHNpemUuXG4gICAgICogRWFjaCByZWNvcmQga2VlcHMgdGhlIHJhdyB2YWx1ZSBhcyB3ZWxsIGFuZCB0aGUgbGFzdCBrbm93biBjYXJldC9zZWxlY3Rpb24gcG9zaXRpb25zLlxuICAgICAqL1xuICAgIGhpc3RvcnlTaXplOiB7XG4gICAgICAgIHZlcnlTbWFsbDogNSxcbiAgICAgICAgc21hbGwgICAgOiAxMCxcbiAgICAgICAgbWVkaXVtICAgOiAyMCxcbiAgICAgICAgbGFyZ2UgICAgOiA1MCxcbiAgICAgICAgdmVyeUxhcmdlOiAxMDAsXG4gICAgICAgIGluc2FuZSAgIDogTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIsXG4gICAgfSxcblxuICAgIC8qIEFsbG93IHRoZSB1c2VyIHRvICdjYW5jZWwnIGFuZCB1bmRvIHRoZSBjaGFuZ2VzIGhlIG1hZGUgdG8gdGhlIGdpdmVuIGF1dG9udW1lcmljLW1hbmFnZWQgZWxlbWVudCwgYnkgcHJlc3NpbmcgdGhlICdFc2NhcGUnIGtleS5cbiAgICAgKiBXaGVuZXZlciB0aGUgdXNlciAndmFsaWRhdGUnIHRoZSBpbnB1dCAoZWl0aGVyIGJ5IGhpdHRpbmcgJ0VudGVyJywgb3IgYmx1cnJpbmcgdGhlIGVsZW1lbnQpLCB0aGUgbmV3IHZhbHVlIGlzIHNhdmVkIGZvciBzdWJzZXF1ZW50ICdjYW5jZWxsYXRpb24nLlxuICAgICAqXG4gICAgICogVGhlIHByb2Nlc3MgOlxuICAgICAqICAgLSBzYXZlIHRoZSBpbnB1dCB2YWx1ZSBvbiBmb2N1c1xuICAgICAqICAgLSBpZiB0aGUgdXNlciBjaGFuZ2UgdGhlIGlucHV0IHZhbHVlLCBhbmQgaGl0IGBFc2NhcGVgLCB0aGVuIHRoZSBpbml0aWFsIHZhbHVlIHNhdmVkIG9uIGZvY3VzIGlzIHNldCBiYWNrXG4gICAgICogICAtIG9uIHRoZSBvdGhlciBoYW5kIGlmIHRoZSB1c2VyIGVpdGhlciBoYXZlIHVzZWQgYEVudGVyYCB0byB2YWxpZGF0ZSAoYEVudGVyYCB0aHJvd3MgYSBjaGFuZ2UgZXZlbnQpIGhpcyBlbnRyaWVzLCBvciBpZiB0aGUgaW5wdXQgdmFsdWUgaGFzIGJlZW4gY2hhbmdlZCBieSBhbm90aGVyIHNjcmlwdCBpbiB0aGUgbWVhbiB0aW1lLCB0aGVuIHdlIHNhdmUgdGhlIG5ldyBpbnB1dCB2YWx1ZVxuICAgICAqICAgLSBvbiBhIHN1Y2Nlc3NmdWwgJ2NhbmNlbCcsIHNlbGVjdCB0aGUgd2hvbGUgdmFsdWUgKHdoaWxlIHJlc3BlY3RpbmcgdGhlIGBzZWxlY3ROdW1iZXJPbmx5YCBvcHRpb24pXG4gICAgICogICAtIGJvbnVzOyBpZiB0aGUgdmFsdWUgaGFzIG5vdCBjaGFuZ2VkLCBoaXR0aW5nICdFc2MnIGp1c3Qgc2VsZWN0IGFsbCB0aGUgaW5wdXQgdmFsdWUgKHdoaWxlIHJlc3BlY3RpbmcgdGhlIGBzZWxlY3ROdW1iZXJPbmx5YCBvcHRpb24pXG4gICAgICovXG4gICAgaXNDYW5jZWxsYWJsZToge1xuICAgICAgICBjYW5jZWxsYWJsZSAgIDogdHJ1ZSxcbiAgICAgICAgbm90Q2FuY2VsbGFibGU6IGZhbHNlLFxuICAgIH0sXG5cbiAgICAvKiBDb250cm9scyB0aGUgbGVhZGluZyB6ZXJvIGJlaGF2aW9yXG4gICAgICogLSAnYWxsb3cnIDogYWxsb3dzIGxlYWRpbmcgemVyb3MgdG8gYmUgZW50ZXJlZC4gWmVyb3Mgd2lsbCBiZSB0cnVuY2F0ZWQgd2hlbiBlbnRlcmluZyBhZGRpdGlvbmFsIGRpZ2l0cy4gT24gZm9jdXNvdXQgemVyb3Mgd2lsbCBiZSBkZWxldGVkXG4gICAgICogLSAnZGVueScgIDogYWxsb3dzIG9ubHkgb25lIGxlYWRpbmcgemVybyBvbiB2YWx1ZXMgdGhhdCBhcmUgYmV0d2VlbiAxIGFuZCAtMVxuICAgICAqIC0gJ2tlZXAnICA6IGFsbG93cyBsZWFkaW5nIHplcm9zIHRvIGJlIGVudGVyZWQuIG9uIGZvY3Vzb3V0IHplcm9zIHdpbGwgYmUgcmV0YWluZWRcbiAgICAgKi9cbiAgICBsZWFkaW5nWmVybzoge1xuICAgICAgICBhbGxvdzogJ2FsbG93JyxcbiAgICAgICAgZGVueSA6ICdkZW55JyxcbiAgICAgICAga2VlcCA6ICdrZWVwJyxcbiAgICB9LFxuXG4gICAgLyogRGVmaW5lcyB0aGUgbWF4aW11bSBwb3NzaWJsZSB2YWx1ZSBhIHVzZXIgY2FuIGVudGVyLlxuICAgICAqIE5vdGVzOlxuICAgICAqIC0gdGhpcyB2YWx1ZSBtdXN0IGJlIGEgc3RyaW5nIGFuZCB1c2UgdGhlIHBlcmlvZCBmb3IgdGhlIGRlY2ltYWwgcG9pbnRcbiAgICAgKiAtIHRoaXMgdmFsdWUgbmVlZHMgdG8gYmUgbGFyZ2VyIHRoYW4gYG1pbmltdW1WYWx1ZWBcbiAgICAgKi9cbiAgICBtYXhpbXVtVmFsdWU6IHtcbiAgICAgICAgdGVuVHJpbGxpb25zICAgICAgICAgIDogJzEwMDAwMDAwMDAwMDAwJywgLy8gMTAwMDAgYmlsbGlvbnNcbiAgICAgICAgb25lQmlsbGlvbiAgICAgICAgICAgIDogJzEwMDAwMDAwMDAnLFxuICAgICAgICB6ZXJvICAgICAgICAgICAgICAgICAgOiAnMCcsXG4gICAgfSxcblxuICAgIC8qIERlZmluZXMgdGhlIG1pbmltdW0gcG9zc2libGUgdmFsdWUgYSB1c2VyIGNhbiBlbnRlci5cbiAgICAgKiBOb3RlczpcbiAgICAgKiAtIHRoaXMgdmFsdWUgbXVzdCBiZSBhIHN0cmluZyBhbmQgdXNlIHRoZSBwZXJpb2QgZm9yIHRoZSBkZWNpbWFsIHBvaW50XG4gICAgICogLSB0aGlzIHZhbHVlIG5lZWRzIHRvIGJlIHNtYWxsZXIgdGhhbiBgbWF4aW11bVZhbHVlYFxuICAgICAqIC0gaWYgdGhpcyBpcyBzdXBlcmlvciB0byAwLCB0aGVuIHlvdSdsbCBlZmZlY3RpdmVseSBwcmV2ZW50IHlvdXIgdXNlciB0byBlbnRpcmVseSBkZWxldGUgdGhlIGNvbnRlbnQgb2YgeW91ciBlbGVtZW50XG4gICAgICovXG4gICAgbWluaW11bVZhbHVlOiB7XG4gICAgICAgIHRlblRyaWxsaW9ucyAgICAgICAgICA6ICctMTAwMDAwMDAwMDAwMDAnLCAvLyAxMDAwMCBiaWxsaW9uc1xuICAgICAgICBvbmVCaWxsaW9uICAgICAgICAgICAgOiAnLTEwMDAwMDAwMDAnLFxuICAgICAgICB6ZXJvICAgICAgICAgICAgICAgICAgOiAnMCcsXG4gICAgfSxcblxuICAgIC8qIEFsbG93cyB0aGUgdXNlciB0byBpbmNyZW1lbnQgb3IgZGVjcmVtZW50IHRoZSBlbGVtZW50IHZhbHVlIHdpdGggdGhlIG1vdXNlIHdoZWVsLlxuICAgICAqIFRoZSB3aGVlbCBiZWhhdmlvciBjYW4gYmUgbW9kaWZpZWQgYnkgdGhlIGB3aGVlbFN0ZXBgIG9wdGlvbi5cbiAgICAgKiBUaGlzIGB3aGVlbFN0ZXBgIG9wdGlvbiBjYW4gYmUgdXNlZCBpbiB0d28gd2F5cywgZWl0aGVyIGJ5IHNldHRpbmc6XG4gICAgICogLSBhICdmaXhlZCcgc3RlcCB2YWx1ZSAoYHdoZWVsU3RlcCA6IDEwMDBgKSwgb3JcbiAgICAgKiAtIHRoZSAncHJvZ3Jlc3NpdmUnIHN0cmluZyAoYHdoZWVsU3RlcCA6ICdwcm9ncmVzc2l2ZSdgKSwgd2hpY2ggd2lsbCB0aGVuIGFjdGl2YXRlIGEgc3BlY2lhbCBtb2RlIHdoZXJlIHRoZSBzdGVwIGlzIGF1dG9tYXRpY2FsbHkgY2FsY3VsYXRlZCBiYXNlZCBvbiB0aGUgZWxlbWVudCB2YWx1ZSBzaXplLlxuICAgICAqXG4gICAgICogTm90ZSA6XG4gICAgICogWW91IGNhbiBhY3RpdmF0ZS9kZWFjdGl2YXRlIHRoZSB3aGVlbCBldmVudCBmb3IgZWFjaCBgd2hlZWxPbmAgb3B0aW9uIHZhbHVlIGJ5IHVzaW5nIHRoZSAnU2hpZnQnIG1vZGlmaWVyIGtleSB3aGlsZSB1c2luZyB0aGUgbW91c2Ugd2hlZWwuXG4gICAgICovXG4gICAgbW9kaWZ5VmFsdWVPbldoZWVsOiB7XG4gICAgICAgIG1vZGlmeVZhbHVlOiB0cnVlLFxuICAgICAgICBkb05vdGhpbmcgIDogZmFsc2UsXG4gICAgfSxcblxuICAgIC8qIEFkZHMgYnJhY2tldHMgb24gbmVnYXRpdmUgdmFsdWVzIChpZS4gdHJhbnNmb3JtcyAnLSQgOTk5Ljk5JyB0byAnKCQ5OTkuOTkpJylcbiAgICAgKiBUaG9zZSBicmFja2V0cyBhcmUgdmlzaWJsZSBvbmx5IHdoZW4gdGhlIGZpZWxkIGRvZXMgTk9UIGhhdmUgdGhlIGZvY3VzLlxuICAgICAqIFRoZSBsZWZ0IGFuZCByaWdodCBzeW1ib2xzIHNob3VsZCBiZSBlbmNsb3NlZCBpbiBxdW90ZXMgYW5kIHNlcGFyYXRlZCBieSBhIGNvbW1hLlxuICAgICAqL1xuICAgIG5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyOiB7XG4gICAgICAgIHBhcmVudGhlc2VzICAgICAgICAgICA6ICcoLCknLFxuICAgICAgICBicmFja2V0cyAgICAgICAgICAgICAgOiAnWyxdJyxcbiAgICAgICAgY2hldnJvbnMgICAgICAgICAgICAgIDogJzwsPicsXG4gICAgICAgIGN1cmx5QnJhY2VzICAgICAgICAgICA6ICd7LH0nLFxuICAgICAgICBhbmdsZUJyYWNrZXRzICAgICAgICAgOiAn44CILOOAiScsXG4gICAgICAgIGphcGFuZXNlUXVvdGF0aW9uTWFya3M6ICfvvaIs772jJyxcbiAgICAgICAgaGFsZkJyYWNrZXRzICAgICAgICAgIDogJ+K4pCziuKUnLFxuICAgICAgICB3aGl0ZVNxdWFyZUJyYWNrZXRzICAgOiAn4p+mLOKfpycsXG4gICAgICAgIHF1b3RhdGlvbk1hcmtzICAgICAgICA6ICfigLks4oC6JyxcbiAgICAgICAgZ3VpbGxlbWV0cyAgICAgICAgICAgIDogJ8KrLMK7JyxcbiAgICAgICAgbm9uZSAgICAgICAgICAgICAgICAgIDogbnVsbCwgLy8gVGhpcyBpcyB0aGUgZGVmYXVsdCB2YWx1ZSwgd2hpY2ggZGVhY3RpdmF0ZSB0aGlzIGZlYXR1cmVcbiAgICB9LFxuXG4gICAgLyogUGxhY2VtZW50IG9mIHRoZSBuZWdhdGl2ZS9wb3NpdGl2ZSBzaWduIHJlbGF0aXZlIHRvIHRoZSBgY3VycmVuY3lTeW1ib2xgIG9wdGlvbi5cbiAgICAgKlxuICAgICAqIEV4YW1wbGU6XG4gICAgICogLy8gRGVmYXVsdCB2YWx1ZXNcbiAgICAgKiAtMSwyMzQuNTYgID0+IGRlZmF1bHQgbm8gb3B0aW9ucyByZXF1aXJlZFxuICAgICAqICQtMSwyMzQuNTYgPT4ge2N1cnJlbmN5U3ltYm9sOiBcIiRcIiwgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQ6IFwiclwifSAvLyBEZWZhdWx0IGlmIG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50IGlzICdudWxsJyBhbmQgY3VycmVuY3lTeW1ib2wgaXMgbm90IGVtcHR5XG4gICAgICpcbiAgICAgKiAvLyBTaWduIG9uIHRoZSBsZWZ0IGhhbmQgc2lkZSBvZiB0aGUgd2hvbGUgbnVtYmVyXG4gICAgICogLSQxLDIzNC41NiA9PiB7Y3VycmVuY3lTeW1ib2w6IFwiJFwifSBvciB7Y3VycmVuY3lTeW1ib2w6IFwiJFwiLCBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudDogXCJsXCJ9XG4gICAgICogLTEsMjM0LjU2JCA9PiB7Y3VycmVuY3lTeW1ib2w6IFwiJFwiLCBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudDogXCJzXCIsIG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50OiBcInBcIn0gLy8gRGVmYXVsdCBpZiBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCBpcyAnbnVsbCcgYW5kIGN1cnJlbmN5U3ltYm9sIGlzIG5vdCBlbXB0eVxuICAgICAqXG4gICAgICogLy8gU2lnbiBvbiB0aGUgcmlnaHQgaGFuZCBzaWRlIG9mIHRoZSB3aG9sZSBudW1iZXJcbiAgICAgKiAxLDIzNC41Ni0gID0+IHtuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudDogXCJzXCJ9XG4gICAgICogJDEsMjM0LjU2LSA9PiB7Y3VycmVuY3lTeW1ib2w6IFwiJFwiLCBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudDogXCJzXCJ9XG4gICAgICogMSwyMzQuNTYtJCA9PiB7Y3VycmVuY3lTeW1ib2w6IFwiJFwiLCBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudDogXCJzXCJ9XG4gICAgICogMSwyMzQuNTYkLSA9PiB7Y3VycmVuY3lTeW1ib2w6IFwiJFwiLCBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudDogXCJzXCIsIG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50OiBcInJcIn1cbiAgICAgKi9cbiAgICBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudDoge1xuICAgICAgICBwcmVmaXg6ICdwJyxcbiAgICAgICAgc3VmZml4OiAncycsXG4gICAgICAgIGxlZnQgIDogJ2wnLFxuICAgICAgICByaWdodCA6ICdyJyxcbiAgICAgICAgbm9uZSAgOiBudWxsLFxuICAgIH0sXG5cbiAgICAvKiBEZWZpbmVzIHRoZSBuZWdhdGl2ZSBzaWduIHN5bWJvbC5cbiAgICAgKiBJdCBjYW4gYmUgYSBzdHJpbmcgb2Ygb25seSBvbmUgY2hhcmFjdGVyLlxuICAgICAqL1xuICAgIG5lZ2F0aXZlU2lnbkNoYXJhY3Rlcjoge1xuICAgICAgICBoeXBoZW4gICAgICAgICA6ICctJyxcbiAgICAgICAgbWludXMgICAgICAgICAgOiAn4oiSJyxcbiAgICAgICAgaGVhdnlNaW51cyAgICAgOiAn4p6WJyxcbiAgICAgICAgZnVsbFdpZHRoSHlwaGVuOiAn77yNJyxcbiAgICAgICAgY2lyY2xlZE1pbnVzICAgOiAn4oqWJyxcbiAgICAgICAgc3F1YXJlZE1pbnVzICAgOiAn4oqfJyxcbiAgICAgICAgdHJpYW5nbGVNaW51cyAgOiAn4qi6JyxcbiAgICAgICAgcGx1c01pbnVzICAgICAgOiAnwrEnLFxuICAgICAgICBtaW51c1BsdXMgICAgICA6ICfiiJMnLFxuICAgICAgICBkb3RNaW51cyAgICAgICA6ICfiiLgnLFxuICAgICAgICBtaW51c1RpbGRlICAgICA6ICfiiYInLFxuICAgICAgICBub3QgICAgICAgICAgICA6ICfCrCcsXG4gICAgfSxcblxuICAgIC8qIERlZmluZXMgaWYgdGhlIGVsZW1lbnQgc2hvdWxkIGhhdmUgZXZlbnQgbGlzdGVuZXJzIGFjdGl2YXRlZCBvbiBpdC5cbiAgICAgKiBCeSBkZWZhdWx0LCB0aG9zZSBldmVudCBsaXN0ZW5lcnMgYXJlIG9ubHkgYWRkZWQgdG8gPGlucHV0PiBlbGVtZW50cyBhbmQgaHRtbCBlbGVtZW50IHdpdGggdGhlIGBjb250ZW50ZWRpdGFibGVgIGF0dHJpYnV0ZSBzZXQgdG8gYHRydWVgLCBidXQgbm90IG9uIHRoZSBvdGhlciBodG1sIHRhZ3MuXG4gICAgICogVGhpcyBhbGxvd3MgdG8gaW5pdGlhbGl6ZSBlbGVtZW50cyB3aXRob3V0IGFueSBldmVudCBsaXN0ZW5lcnMuXG4gICAgICogV2FybmluZzogU2luY2UgQXV0b051bWVyaWMgd2lsbCBub3QgY2hlY2sgdGhlIGlucHV0IGNvbnRlbnQgYWZ0ZXIgaXRzIGluaXRpYWxpemF0aW9uLCB1c2luZyBzb21lIGF1dG9OdW1lcmljIG1ldGhvZHMgYWZ0ZXJ3YXJkcyAqd2lsbCogcHJvYmFibHkgbGVhZHMgdG8gZm9ybWF0dGluZyBwcm9ibGVtcy5cbiAgICAgKi9cbiAgICBub0V2ZW50TGlzdGVuZXJzOiB7XG4gICAgICAgIG5vRXZlbnRzIDogdHJ1ZSxcbiAgICAgICAgYWRkRXZlbnRzOiBmYWxzZSxcbiAgICB9LFxuXG4gICAgLyogTWFuYWdlIGhvdyBhdXRvTnVtZXJpYyByZWFjdCB3aGVuIHRoZSB1c2VyIHRyaWVzIHRvIHBhc3RlIGFuIGludmFsaWQgbnVtYmVyLlxuICAgICAqIC0gJ2Vycm9yJyAgICA6IChUaGlzIGlzIHRoZSBkZWZhdWx0IGJlaGF2aW9yKSBUaGUgaW5wdXQgdmFsdWUgaXMgbm90IGNoYW5nZWQgYW5kIGFuIGVycm9yIGlzIG91dHB1dCBpbiB0aGUgY29uc29sZS5cbiAgICAgKiAtICdpZ25vcmUnICAgOiBpZGVtIHRoYW4gJ2Vycm9yJywgYnV0IGZhaWwgc2lsZW50bHkgd2l0aG91dCBvdXRwdXR0aW5nIGFueSBlcnJvci93YXJuaW5nIGluIHRoZSBjb25zb2xlLlxuICAgICAqIC0gJ2NsYW1wJyAgICA6IGlmIHRoZSBwYXN0ZWQgdmFsdWUgaXMgZWl0aGVyIHRvbyBzbWFsbCBvciB0b28gYmlnIHJlZ2FyZGluZyB0aGUgbWluaW11bVZhbHVlIGFuZCBtYXhpbXVtVmFsdWUgcmFuZ2UsIHRoZW4gdGhlIHJlc3VsdCBpcyBjbGFtcGVkIHRvIHRob3NlIGxpbWl0cy5cbiAgICAgKiAtICd0cnVuY2F0ZScgOiBhdXRvTnVtZXJpYyB3aWxsIGluc2VydCBhcyBtYW55IHBhc3RlZCBudW1iZXJzIGl0IGNhbiBhdCB0aGUgaW5pdGlhbCBjYXJldC9zZWxlY3Rpb24sIHVudGlsIGV2ZXJ5dGhpbmcgaXMgcGFzdGVkLCBvciB0aGUgcmFuZ2UgbGltaXQgaXMgaGl0LlxuICAgICAqICAgICAgICAgICAgICAgIFRoZSBub24tcGFzdGVkIG51bWJlcnMgYXJlIGRyb3BwZWQgYW5kIHRoZXJlZm9yZSBub3QgdXNlZCBhdCBhbGwuXG4gICAgICogLSAncmVwbGFjZScgIDogYXV0b051bWVyaWMgd2lsbCBmaXJzdCBpbnNlcnQgYXMgbWFueSBwYXN0ZWQgbnVtYmVycyBpdCBjYW4gYXQgdGhlIGluaXRpYWwgY2FyZXQvc2VsZWN0aW9uLCB0aGVuIGlmIHRoZSByYW5nZSBsaW1pdCBpcyBoaXQsIGl0IHdpbGwgdHJ5XG4gICAgICogICAgICAgICAgICAgICAgdG8gcmVwbGFjZSBvbmUgYnkgb25lIHRoZSByZW1haW5pbmcgaW5pdGlhbCBudW1iZXJzIChvbiB0aGUgcmlnaHQgc2lkZSBvZiB0aGUgY2FyZXQpIHdpdGggdGhlIHJlc3Qgb2YgdGhlIHBhc3RlZCBudW1iZXJzLlxuICAgICAqXG4gICAgICogTm90ZSAxIDogQSBwYXN0ZSBjb250ZW50IHN0YXJ0aW5nIHdpdGggYSBuZWdhdGl2ZSBzaWduICctJyB3aWxsIGJlIGFjY2VwdGVkIGFueXdoZXJlIGluIHRoZSBpbnB1dCwgYW5kIHdpbGwgc2V0IHRoZSByZXN1bHRpbmcgdmFsdWUgYXMgYSBuZWdhdGl2ZSBudW1iZXJcbiAgICAgKiBOb3RlIDIgOiBBIHBhc3RlIGNvbnRlbnQgc3RhcnRpbmcgd2l0aCBhIG51bWJlciB3aWxsIGJlIGFjY2VwdGVkLCBldmVuIGlmIHRoZSByZXN0IGlzIGdpYmJlcmlzaCAoaWUuICcxMjNmb29iYXI0NTYnKS5cbiAgICAgKiAgICAgICAgICBPbmx5IHRoZSBmaXJzdCBudW1iZXIgd2lsbCBiZSB1c2VkIChoZXJlICcxMjMnKS5cbiAgICAgKiBOb3RlIDMgOiBUaGUgcGFzdGUgZXZlbnQgd29ya3Mgd2l0aCB0aGUgYGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXNgIG9wdGlvbiB0b28uXG4gICAgICovXG4gICAgb25JbnZhbGlkUGFzdGU6IHtcbiAgICAgICAgZXJyb3IgICA6ICdlcnJvcicsXG4gICAgICAgIGlnbm9yZSAgOiAnaWdub3JlJyxcbiAgICAgICAgY2xhbXAgICA6ICdjbGFtcCcsXG4gICAgICAgIHRydW5jYXRlOiAndHJ1bmNhdGUnLFxuICAgICAgICByZXBsYWNlIDogJ3JlcGxhY2UnLFxuICAgIH0sXG5cbiAgICAvKiBEZWZpbmVzIGhvdyB0aGUgdmFsdWUgc2hvdWxkIGJlIGZvcm1hdHRlZCB3aGVuIHdhbnRpbmcgYSAnbG9jYWxpemVkJyB2ZXJzaW9uIG9mIGl0LlxuICAgICAqIC0gbnVsbCBvciAnc3RyaW5nJyA9PiAnbm5ubi5ubicgb3IgJy1ubm5uLm5uJyBhcyB0ZXh0IHR5cGUuIFRoaXMgaXMgdGhlIGRlZmF1bHQgYmVoYXZpb3IuXG4gICAgICogLSAnbnVtYmVyJyAgICAgICAgID0+IG5ubm4ubm4gb3IgLW5ubm4ubm4gYXMgYSBOdW1iZXIgKFdhcm5pbmc6IHRoaXMgd29ya3Mgb25seSBmb3IgaW50ZWdlcnMgaW5mZXJpb3IgdG8gTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIpXG4gICAgICogLSAnLCcgb3IgJy0sJyAgICAgID0+ICdubm5uLG5uJyBvciAnLW5ubm4sbm4nXG4gICAgICogLSAnLi0nICAgICAgICAgICAgID0+ICdubm5uLm5uJyBvciAnbm5ubi5ubi0nXG4gICAgICogLSAnLC0nICAgICAgICAgICAgID0+ICdubm5uLG5uJyBvciAnbm5ubixubi0nXG4gICAgICpcbiAgICAgKiBOb3RlOiBUaGUgaHlwaGVuICctJyBpcyB0cmFuc2xhdGVkIHRvIHRoZSBjdXN0b20gbmVnYXRpdmUgc2lnbiBkZWZpbmVkIGluIGBuZWdhdGl2ZVNpZ25DaGFyYWN0ZXJgXG4gICAgICovXG4gICAgb3V0cHV0Rm9ybWF0OiB7XG4gICAgICAgIHN0cmluZyAgICAgICA6ICdzdHJpbmcnLFxuICAgICAgICBudW1iZXIgICAgICAgOiAnbnVtYmVyJyxcbiAgICAgICAgZG90ICAgICAgICAgIDogJy4nLFxuICAgICAgICBuZWdhdGl2ZURvdCAgOiAnLS4nLFxuICAgICAgICBjb21tYSAgICAgICAgOiAnLCcsXG4gICAgICAgIG5lZ2F0aXZlQ29tbWE6ICctLCcsXG4gICAgICAgIGRvdE5lZ2F0aXZlICA6ICcuLScsXG4gICAgICAgIGNvbW1hTmVnYXRpdmU6ICcsLScsXG4gICAgICAgIG5vbmUgICAgICAgICA6IG51bGwsXG4gICAgfSxcblxuICAgIC8qIE92ZXJyaWRlIHRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtIGxpbWl0c1xuICAgICAqIG92ZXJyaWRlTWluTWF4TGltaXRzOiBcImNlaWxpbmdcIiBhZGhlcmVzIHRvIG1heGltdW1WYWx1ZSBhbmQgaWdub3JlcyBtaW5pbXVtVmFsdWUgc2V0dGluZ3NcbiAgICAgKiBvdmVycmlkZU1pbk1heExpbWl0czogXCJmbG9vclwiIGFkaGVyZXMgdG8gbWluaW11bVZhbHVlIGFuZCBpZ25vcmVzIG1heGltdW1WYWx1ZSBzZXR0aW5nc1xuICAgICAqIG92ZXJyaWRlTWluTWF4TGltaXRzOiBcImlnbm9yZVwiIGlnbm9yZXMgYm90aCBtaW5pbXVtVmFsdWUgJiBtYXhpbXVtVmFsdWVcbiAgICAgKi9cbiAgICBvdmVycmlkZU1pbk1heExpbWl0czoge1xuICAgICAgICBjZWlsaW5nICAgICAgOiAnY2VpbGluZycsXG4gICAgICAgIGZsb29yICAgICAgICA6ICdmbG9vcicsXG4gICAgICAgIGlnbm9yZSAgICAgICA6ICdpZ25vcmUnLFxuICAgICAgICBkb05vdE92ZXJyaWRlOiBudWxsLFxuICAgIH0sXG5cbiAgICAvKiBEZWZpbmVzIHRoZSBwb3NpdGl2ZSBzaWduIHN5bWJvbC5cbiAgICAgKiBJdCBjYW4gYmUgYSBzdHJpbmcgb2Ygb25seSBvbmUgY2hhcmFjdGVyLlxuICAgICAqIFRoaXMgaXMgc2hvd24gb25seSBpZiBgc2hvd1Bvc2l0aXZlU2lnbmAgaXMgc2V0IHRvIGB0cnVlYC5cbiAgICAgKi9cbiAgICBwb3NpdGl2ZVNpZ25DaGFyYWN0ZXI6IHtcbiAgICAgICAgcGx1cyAgICAgICAgICAgICAgOiAnKycsXG4gICAgICAgIGZ1bGxXaWR0aFBsdXMgICAgIDogJ++8iycsXG4gICAgICAgIGhlYXZ5UGx1cyAgICAgICAgIDogJ+KelScsXG4gICAgICAgIGRvdWJsZVBsdXMgICAgICAgIDogJ+KnuicsXG4gICAgICAgIHRyaXBsZVBsdXMgICAgICAgIDogJ+KnuycsXG4gICAgICAgIGNpcmNsZWRQbHVzICAgICAgIDogJ+KKlScsXG4gICAgICAgIHNxdWFyZWRQbHVzICAgICAgIDogJ+KKnicsXG4gICAgICAgIHRyaWFuZ2xlUGx1cyAgICAgIDogJ+KouScsXG4gICAgICAgIHBsdXNNaW51cyAgICAgICAgIDogJ8KxJyxcbiAgICAgICAgbWludXNQbHVzICAgICAgICAgOiAn4oiTJyxcbiAgICAgICAgZG90UGx1cyAgICAgICAgICAgOiAn4oiUJyxcbiAgICAgICAgYWx0SGVicmV3UGx1cyAgICAgOiAn76ypJyxcbiAgICAgICAgbm9ybWFsU3BhY2UgICAgICAgOiAnICcsXG4gICAgICAgIHRoaW5TcGFjZSAgICAgICAgIDogJ1xcdTIwMDknLFxuICAgICAgICBuYXJyb3dOb0JyZWFrU3BhY2U6ICdcXHUyMDJmJyxcbiAgICAgICAgbm9CcmVha1NwYWNlICAgICAgOiAnXFx1MDBhMCcsXG4gICAgfSxcblxuICAgIC8qIFRoZSBgcmF3VmFsdWVEaXZpc29yYCBkaXZpZGVzIHRoZSBmb3JtYXR0ZWQgdmFsdWUgc2hvd24gaW4gdGhlIEF1dG9OdW1lcmljIGVsZW1lbnQgYW5kIHN0b3JlIHRoZSByZXN1bHQgaW4gYHJhd1ZhbHVlYC5cbiAgICAgKiBAZXhhbXBsZSB7IHJhd1ZhbHVlRGl2aXNvcjogJzEwMCcgfSBvciA8aW5wdXQgZGF0YS1yYXctdmFsdWUtZGl2aXNvcj1cIjEwMFwiPlxuICAgICAqIEdpdmVuIHRoZSBgMC4wMTIzNGAgcmF3IHZhbHVlLCB0aGUgZm9ybWF0dGVkIHZhbHVlIHdpbGwgYmUgZGlzcGxheWVkIGFzIGAnMS4yMzQnYC5cbiAgICAgKiBUaGlzIGlzIHVzZWZ1bCB3aGVuIGRpc3BsYXlpbmcgcGVyY2VudGFnZSBmb3IgaW5zdGFuY2UsIGFuZCBhdm9pZCB0aGUgbmVlZCB0byBkaXZpZGUvbXVsdGlwbHkgYnkgMTAwIGJldHdlZW4gdGhlIG51bWJlciBzaG93biBhbmQgdGhlIHJhdyB2YWx1ZS5cbiAgICAgKi9cbiAgICByYXdWYWx1ZURpdmlzb3I6IHtcbiAgICAgICAgbm9uZSAgICAgIDogbnVsbCxcbiAgICAgICAgcGVyY2VudGFnZTogMTAwLFxuICAgICAgICBwZXJtaWxsZSAgOiAxMDAwLFxuICAgICAgICBiYXNpc1BvaW50OiAxMDAwMCxcbiAgICB9LFxuXG4gICAgLyogRGVmaW5lcyBpZiB0aGUgZWxlbWVudCAoYDxpbnB1dD5gIG9yIGFub3RoZXIgYWxsb3dlZCBodG1sIHRhZykgc2hvdWxkIGJlIHNldCBhcyByZWFkLW9ubHkgb24gaW5pdGlhbGl6YXRpb24uXG4gICAgICogV2hlbiBzZXQgdG8gYHRydWVgLCB0aGVuOlxuICAgICAqIC0gdGhlIGByZWFkb25seWAgaHRtbCBwcm9wZXJ0eSBpcyBhZGRlZCB0byB0aGUgPGlucHV0PiBlbGVtZW50IG9uIGluaXRpYWxpemF0aW9uLCBvclxuICAgICAqIC0gdGhlIGBjb250ZW50ZWRpdGFibGVgIGF0dHJpYnV0ZSBpcyBzZXQgdG8gYGZhbHNlYCBvbiBub24taW5wdXQgZWxlbWVudHMuXG4gICAgICovXG4gICAgcmVhZE9ubHk6IHtcbiAgICAgICAgcmVhZE9ubHkgOiB0cnVlLFxuICAgICAgICByZWFkV3JpdGU6IGZhbHNlLFxuICAgIH0sXG5cbiAgICAvKiBEZWZpbmVzIHRoZSByb3VuZGluZyBtZXRob2QgdG8gdXNlLlxuICAgICAqIHJvdW5kaW5nTWV0aG9kOiBcIlNcIiwgUm91bmQtSGFsZi1VcCBTeW1tZXRyaWMgKGRlZmF1bHQpXG4gICAgICogcm91bmRpbmdNZXRob2Q6IFwiQVwiLCBSb3VuZC1IYWxmLVVwIEFzeW1tZXRyaWNcbiAgICAgKiByb3VuZGluZ01ldGhvZDogXCJzXCIsIFJvdW5kLUhhbGYtRG93biBTeW1tZXRyaWMgKGxvd2VyIGNhc2UgcylcbiAgICAgKiByb3VuZGluZ01ldGhvZDogXCJhXCIsIFJvdW5kLUhhbGYtRG93biBBc3ltbWV0cmljIChsb3dlciBjYXNlIGEpXG4gICAgICogcm91bmRpbmdNZXRob2Q6IFwiQlwiLCBSb3VuZC1IYWxmLUV2ZW4gXCJCYW5rZXJzIFJvdW5kaW5nXCJcbiAgICAgKiByb3VuZGluZ01ldGhvZDogXCJVXCIsIFJvdW5kIFVwIFwiUm91bmQtQXdheS1Gcm9tLVplcm9cIlxuICAgICAqIHJvdW5kaW5nTWV0aG9kOiBcIkRcIiwgUm91bmQgRG93biBcIlJvdW5kLVRvd2FyZC1aZXJvXCIgLSBzYW1lIGFzIHRydW5jYXRlXG4gICAgICogcm91bmRpbmdNZXRob2Q6IFwiQ1wiLCBSb3VuZCB0byBDZWlsaW5nIFwiVG93YXJkIFBvc2l0aXZlIEluZmluaXR5XCJcbiAgICAgKiByb3VuZGluZ01ldGhvZDogXCJGXCIsIFJvdW5kIHRvIEZsb29yIFwiVG93YXJkIE5lZ2F0aXZlIEluZmluaXR5XCJcbiAgICAgKiByb3VuZGluZ01ldGhvZDogXCJOMDVcIiBSb3VuZHMgdG8gdGhlIG5lYXJlc3QgLjA1ID0+IHNhbWUgYXMgXCJDSEZcIiB1c2VkIGluIDEuOVggYW5kIHN0aWxsIHZhbGlkXG4gICAgICogcm91bmRpbmdNZXRob2Q6IFwiVTA1XCIgUm91bmRzIHVwIHRvIG5leHQgLjA1XG4gICAgICogcm91bmRpbmdNZXRob2Q6IFwiRDA1XCIgUm91bmRzIGRvd24gdG8gbmV4dCAuMDVcbiAgICAgKi9cbiAgICByb3VuZGluZ01ldGhvZDoge1xuICAgICAgICBoYWxmVXBTeW1tZXRyaWMgICAgICAgICAgICAgICAgOiAnUycsXG4gICAgICAgIGhhbGZVcEFzeW1tZXRyaWMgICAgICAgICAgICAgICA6ICdBJyxcbiAgICAgICAgaGFsZkRvd25TeW1tZXRyaWMgICAgICAgICAgICAgIDogJ3MnLFxuICAgICAgICBoYWxmRG93bkFzeW1tZXRyaWMgICAgICAgICAgICAgOiAnYScsXG4gICAgICAgIGhhbGZFdmVuQmFua2Vyc1JvdW5kaW5nICAgICAgICA6ICdCJyxcbiAgICAgICAgdXBSb3VuZEF3YXlGcm9tWmVybyAgICAgICAgICAgIDogJ1UnLFxuICAgICAgICBkb3duUm91bmRUb3dhcmRaZXJvICAgICAgICAgICAgOiAnRCcsXG4gICAgICAgIHRvQ2VpbGluZ1Rvd2FyZFBvc2l0aXZlSW5maW5pdHk6ICdDJyxcbiAgICAgICAgdG9GbG9vclRvd2FyZE5lZ2F0aXZlSW5maW5pdHkgIDogJ0YnLFxuICAgICAgICB0b05lYXJlc3QwNSAgICAgICAgICAgICAgICAgICAgOiAnTjA1JyxcbiAgICAgICAgdG9OZWFyZXN0MDVBbHQgICAgICAgICAgICAgICAgIDogJ0NIRicsXG4gICAgICAgIHVwVG9OZXh0MDUgICAgICAgICAgICAgICAgICAgICA6ICdVMDUnLFxuICAgICAgICBkb3duVG9OZXh0MDUgICAgICAgICAgICAgICAgICAgOiAnRDA1JyxcbiAgICB9LFxuXG4gICAgLyogU2V0IHRvIGB0cnVlYCB0byBhbGxvdyB0aGUgYGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXNgIHZhbHVlIHRvIGJlIHNhdmVkIHdpdGggc2Vzc2lvblN0b3JhZ2VcbiAgICAgKiBJZiBJRSA2IG9yIDcgaXMgZGV0ZWN0ZWQsIHRoZSB2YWx1ZSB3aWxsIGJlIHNhdmVkIGFzIGEgc2Vzc2lvbiBjb29raWUuXG4gICAgICovXG4gICAgc2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZToge1xuICAgICAgICBzYXZlICAgICA6IHRydWUsXG4gICAgICAgIGRvTm90U2F2ZTogZmFsc2UsXG4gICAgfSxcblxuICAgIC8qIERldGVybWluZSBpZiB0aGUgc2VsZWN0IGFsbCBrZXlib2FyZCBjb21tYW5kIHdpbGwgc2VsZWN0IHRoZSBjb21wbGV0ZSBpbnB1dCB0ZXh0LCBvciBvbmx5IHRoZSBpbnB1dCBudW1lcmljIHZhbHVlXG4gICAgICogTm90ZSA6IElmIHRoZSBjdXJyZW5jeSBzeW1ib2wgaXMgYmV0d2VlbiB0aGUgbnVtZXJpYyB2YWx1ZSBhbmQgdGhlIG5lZ2F0aXZlIHNpZ24sIG9ubHkgdGhlIG51bWVyaWMgdmFsdWUgd2lsbCBiZSBzZWxlY3RlZFxuICAgICAqL1xuICAgIHNlbGVjdE51bWJlck9ubHk6IHtcbiAgICAgICAgc2VsZWN0TnVtYmVyc09ubHk6IHRydWUsXG4gICAgICAgIHNlbGVjdEFsbCAgICAgICAgOiBmYWxzZSxcbiAgICB9LFxuXG4gICAgLyogRGVmaW5lcyBpZiB0aGUgZWxlbWVudCB2YWx1ZSBzaG91bGQgYmUgc2VsZWN0ZWQgb24gZm9jdXMuXG4gICAgICogTm90ZTogVGhlIHNlbGVjdGlvbiBpcyBkb25lIHVzaW5nIHRoZSBgc2VsZWN0TnVtYmVyT25seWAgb3B0aW9uLlxuICAgICAqL1xuICAgIHNlbGVjdE9uRm9jdXM6IHtcbiAgICAgICAgc2VsZWN0ICAgICA6IHRydWUsXG4gICAgICAgIGRvTm90U2VsZWN0OiBmYWxzZSxcbiAgICB9LFxuXG4gICAgLyogRGVmaW5lcyBob3cgdGhlIHNlcmlhbGl6ZSBmdW5jdGlvbnMgc2hvdWxkIHRyZWF0IHRoZSBzcGFjZXMuXG4gICAgICogVGhvc2Ugc3BhY2VzICcgJyBjYW4gZWl0aGVyIGJlIGNvbnZlcnRlZCB0byB0aGUgcGx1cyBzaWduICcrJywgd2hpY2ggaXMgdGhlIGRlZmF1bHQsIG9yIHRvICclMjAnLlxuICAgICAqIEJvdGggdmFsdWVzIGJlaW5nIHZhbGlkIHBlciB0aGUgc3BlYyAoaHR0cDovL3d3dy53My5vcmcvQWRkcmVzc2luZy9VUkwvdXJpLXNwZWMuaHRtbCkuXG4gICAgICogQWxzbyBzZWUgdGhlIHN1bW1lZCB1cCBhbnN3ZXIgb24gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzM5MzkyODcuXG4gICAgICpcbiAgICAgKiB0bDtkciA6IFNwYWNlcyBzaG91bGQgYmUgY29udmVydGVkIHRvICclMjAnIGJlZm9yZSB0aGUgJz8nIHNpZ24sIHRoZW4gY29udmVydGVkIHRvICcrJyBhZnRlci5cbiAgICAgKiBJbiBvdXIgY2FzZSBzaW5jZSB3ZSBzZXJpYWxpemUgdGhlIHF1ZXJ5LCB3ZSB1c2UgJysnIGFzIHRoZSBkZWZhdWx0IChidXQgYWxsb3cgdGhlIHVzZXIgdG8gZ2V0IGJhY2sgdGhlIG9sZCAqd3JvbmcqIGJlaGF2aW9yKS5cbiAgICAgKi9cbiAgICBzZXJpYWxpemVTcGFjZXM6IHtcbiAgICAgICAgcGx1cyAgIDogJysnLFxuICAgICAgICBwZXJjZW50OiAnJTIwJyxcbiAgICB9LFxuXG4gICAgLyogRGVmaW5lcyBpZiB0aGUgZWxlbWVudCB2YWx1ZSBzaG91bGQgYmUgY29udmVydGVkIHRvIHRoZSByYXcgdmFsdWUgb24gZm9jdXMgKGFuZCBiYWNrIHRvIHRoZSBmb3JtYXR0ZWQgb24gYmx1cikuXG4gICAgICogSWYgc2V0IHRvIGB0cnVlYCwgdGhlbiBhdXRvTnVtZXJpYyByZW1vdmUgdGhlIHRob3VzYW5kIHNlcGFyYXRvciwgY3VycmVuY3kgc3ltYm9sIGFuZCBzdWZmaXggb24gZm9jdXMuXG4gICAgICogRXhhbXBsZTpcbiAgICAgKiBJZiB0aGUgaW5wdXQgdmFsdWUgaXMgJyQgMSw5OTkuODggc3VmZml4Jywgb24gZm9jdXMgaXQgYmVjb21lcyAnMTk5OS44OCcgYW5kIGJhY2sgdG8gJyQgMSw5OTkuODggc3VmZml4JyBvbiBibHVyLlxuICAgICAqL1xuICAgIHNob3dPbmx5TnVtYmVyc09uRm9jdXM6IHtcbiAgICAgICAgb25seU51bWJlcnM6IHRydWUsXG4gICAgICAgIHNob3dBbGwgICAgOiBmYWxzZSxcbiAgICB9LFxuXG4gICAgLyogQWxsb3cgdGhlIHBvc2l0aXZlIHNpZ24gc3ltYm9sIGArYCB0byBiZSBkaXNwbGF5ZWQgZm9yIHBvc2l0aXZlIG51bWJlcnMuXG4gICAgICogQnkgZGVmYXVsdCwgdGhpcyBwb3NpdGl2ZSBzaWduIGlzIG5vdCBzaG93bi5cbiAgICAgKiBUaGUgc2lnbiBwbGFjZW1lbnQgaXMgY29udHJvbGxlZCBieSB0aGUgJ25lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50JyBvcHRpb24sIG1pbWlja2luZyB0aGUgbmVnYXRpdmUgc2lnbiBwbGFjZW1lbnQgcnVsZXMuXG4gICAgICovXG4gICAgc2hvd1Bvc2l0aXZlU2lnbjoge1xuICAgICAgICBzaG93OiB0cnVlLFxuICAgICAgICBoaWRlOiBmYWxzZSxcbiAgICB9LFxuXG4gICAgLyogRGVmaW5lcyBpZiB3YXJuaW5ncyBzaG91bGQgYmUgc2hvd24gaW4gdGhlIGNvbnNvbGUuXG4gICAgICogVGhvc2Ugd2FybmluZ3MgY2FuIGJlIGlnbm9yZWQsIGJ1dCBhcmUgdXN1YWxseSBwcmludGVkIHdoZW4gc29tZXRoaW5nIGNvdWxkIGJlIGltcHJvdmVkIGJ5IHRoZSB1c2VyIChpZS4gb3B0aW9uIGNvbmZsaWN0cykuXG4gICAgICovXG4gICAgc2hvd1dhcm5pbmdzOiB7XG4gICAgICAgIHNob3c6IHRydWUsIC8vIEFsbCB3YXJuaW5nIGFyZSBzaG93blxuICAgICAgICBoaWRlOiBmYWxzZSwgLy8gTm8gd2FybmluZ3MgYXJlIHNob3duLCBvbmx5IHRoZSB0aHJvd24gZXJyb3JzXG4gICAgfSxcblxuICAgIC8qIERlZmluZXMgdGhlIHJ1bGVzIHRoYXQgY2FsY3VsYXRlIHRoZSBDU1MgY2xhc3MoZXMpIHRvIGFwcGx5IG9uIHRoZSBlbGVtZW50LCBiYXNlZCBvbiB0aGUgcmF3IHVuZm9ybWF0dGVkIHZhbHVlLlxuICAgICAqIFRoaXMgY2FuIGFsc28gYmUgdXNlZCB0byBjYWxsIGNhbGxiYWNrcyB3aGVuZXZlciB0aGUgYHJhd1ZhbHVlYCBpcyB1cGRhdGVkLlxuICAgICAqIEltcG9ydGFudDogYWxsIGNhbGxiYWNrcyBtdXN0IHJldHVybiBgbnVsbGAgaWYgbm8gcmFuZ2VzL3VzZXJEZWZpbmVkIGNsYXNzZXMgYXJlIHNlbGVjdGVkXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiB7XG4gICAgICogICAgIHBvc2l0aXZlICAgOiAnYXV0b051bWVyaWMtcG9zaXRpdmUnLCAvLyBPciBgbnVsbGAgdG8gbm90IHVzZSBpdFxuICAgICAqICAgICBuZWdhdGl2ZSAgIDogJ2F1dG9OdW1lcmljLW5lZ2F0aXZlJyxcbiAgICAgKiAgICAgcmFuZ2VzICAgICA6IFtcbiAgICAgKiAgICAgICAgIHsgbWluOiAwLCBtYXg6IDI1LCBjbGFzczogJ2F1dG9OdW1lcmljLXJlZCcgfSxcbiAgICAgKiAgICAgICAgIHsgbWluOiAyNSwgbWF4OiA1MCwgY2xhc3M6ICdhdXRvTnVtZXJpYy1vcmFuZ2UnIH0sXG4gICAgICogICAgICAgICB7IG1pbjogNTAsIG1heDogNzUsIGNsYXNzOiAnYXV0b051bWVyaWMteWVsbG93JyB9LFxuICAgICAqICAgICAgICAgeyBtaW46IDc1LCBtYXg6IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSLCBjbGFzczogJ2F1dG9OdW1lcmljLWdyZWVuJyB9LFxuICAgICAqICAgICBdLFxuICAgICAqICAgICB1c2VyRGVmaW5lZDogW1xuICAgICAqICAgICAgICAgLy8gSWYgJ2NsYXNzZXMnIGlzIGEgc3RyaW5nLCBzZXQgaXQgaWYgYHRydWVgLCByZW1vdmUgaXQgaWYgYGZhbHNlYFxuICAgICAqICAgICAgICAgeyBjYWxsYmFjazogcmF3VmFsdWUgPT4geyByZXR1cm4gdHJ1ZTsgfSwgY2xhc3NlczogJ3RoaXNJc1RydWUnIH0sXG4gICAgICogICAgICAgICAvLyBJZiAnY2xhc3NlcycgaXMgYW4gYXJyYXkgd2l0aCBvbmx5IDIgZWxlbWVudHMsIHNldCB0aGUgZmlyc3QgY2xhc3MgaWYgYHRydWVgLCB0aGUgc2Vjb25kIGlmIGBmYWxzZWBcbiAgICAgKiAgICAgICAgIHsgY2FsbGJhY2s6IHJhd1ZhbHVlID0+IHJhd1ZhbHVlICUgMiA9PT0gMCwgY2xhc3NlczogWydhdXRvTnVtZXJpYy1ldmVuJywgJ2F1dG9OdW1lcmljLW9kZCddIH0sXG4gICAgICogICAgICAgICAvLyBSZXR1cm4gb25seSBvbmUgaW5kZXggdG8gdXNlIG9uIHRoZSBgY2xhc3Nlc2AgYXJyYXkgKGhlcmUsICdjbGFzczMnKVxuICAgICAqICAgICAgICAgeyBjYWxsYmFjazogcmF3VmFsdWUgPT4geyByZXR1cm4gMjsgfSwgY2xhc3NlczogWydjbGFzczEnLCAnY2xhc3MyJywgJ2NsYXNzMyddIH0sXG4gICAgICogICAgICAgICAvLyBSZXR1cm4gYW4gYXJyYXkgb2YgaW5kZXhlcyB0byB1c2Ugb24gdGhlIGBjbGFzc2VzYCBhcnJheSAoaGVyZSwgJ2NsYXNzMScgYW5kICdjbGFzczMnKVxuICAgICAqICAgICAgICAgeyBjYWxsYmFjazogcmF3VmFsdWUgPT4geyByZXR1cm4gWzAsIDJdOyB9LCBjbGFzc2VzOiBbJ2NsYXNzMScsICdjbGFzczInLCAnY2xhc3MzJ10gfSxcbiAgICAgKiAgICAgICAgIC8vIElmICdjbGFzc2VzJyBpcyBgdW5kZWZpbmVkYCBvciBgbnVsbGAsIHRoZW4gdGhlIGNhbGxiYWNrIGlzIGNhbGxlZCB3aXRoIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QgcGFzc2VkIGFzIGEgcGFyYW1ldGVyXG4gICAgICogICAgICAgICB7IGNhbGxiYWNrOiBhbkVsZW1lbnQgPT4geyByZXR1cm4gYW5FbGVtZW50LmdldEZvcm1hdHRlZCgpOyB9IH0sXG4gICAgICogICAgIF0sXG4gICAgICogfVxuICAgICAqL1xuICAgIHN0eWxlUnVsZXM6IHtcbiAgICAgICAgbm9uZSAgICAgICAgICAgICAgICAgOiBudWxsLFxuICAgICAgICBwb3NpdGl2ZU5lZ2F0aXZlICAgICA6IHtcbiAgICAgICAgICAgIHBvc2l0aXZlOiAnYXV0b051bWVyaWMtcG9zaXRpdmUnLFxuICAgICAgICAgICAgbmVnYXRpdmU6ICdhdXRvTnVtZXJpYy1uZWdhdGl2ZScsXG4gICAgICAgIH0sXG4gICAgICAgIHJhbmdlMFRvMTAwV2l0aDRTdGVwczoge1xuICAgICAgICAgICAgcmFuZ2VzOiBbXG4gICAgICAgICAgICAgICAgeyBtaW46IDAsIG1heDogMjUsIGNsYXNzOiAnYXV0b051bWVyaWMtcmVkJyB9LFxuICAgICAgICAgICAgICAgIHsgbWluOiAyNSwgbWF4OiA1MCwgY2xhc3M6ICdhdXRvTnVtZXJpYy1vcmFuZ2UnIH0sXG4gICAgICAgICAgICAgICAgeyBtaW46IDUwLCBtYXg6IDc1LCBjbGFzczogJ2F1dG9OdW1lcmljLXllbGxvdycgfSxcbiAgICAgICAgICAgICAgICB7IG1pbjogNzUsIG1heDogMTAwLCBjbGFzczogJ2F1dG9OdW1lcmljLWdyZWVuJyB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgICAgZXZlbk9kZCAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICB1c2VyRGVmaW5lZDogW1xuICAgICAgICAgICAgICAgIHsgY2FsbGJhY2s6IHJhd1ZhbHVlID0+IHJhd1ZhbHVlICUgMiA9PT0gMCwgY2xhc3NlczogWydhdXRvTnVtZXJpYy1ldmVuJywgJ2F1dG9OdW1lcmljLW9kZCddIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgICByYW5nZVNtYWxsQW5kWmVybyAgICA6IHtcbiAgICAgICAgICAgIHVzZXJEZWZpbmVkOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayAgOiByYXdWYWx1ZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmF3VmFsdWUgPj0gLTEgJiYgcmF3VmFsdWUgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoTnVtYmVyKHJhd1ZhbHVlKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJhd1ZhbHVlID4gMCAmJiByYXdWYWx1ZSA8PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIDI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsOyAgLy8gSW4gY2FzZSB0aGUgcmF3VmFsdWUgaXMgb3V0c2lkZSB0aG9zZSByYW5nZXNcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgY2xhc3NlczogW1xuICAgICAgICAgICAgICAgICAgICAgICAgJ2F1dG9OdW1lcmljLXNtYWxsLW5lZ2F0aXZlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICdhdXRvTnVtZXJpYy16ZXJvJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICdhdXRvTnVtZXJpYy1zbWFsbC1wb3NpdGl2ZScsXG4gICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgfSxcblxuICAgIC8qIEFkZCBhIHRleHQgb24gdGhlIHJpZ2h0IGhhbmQgc2lkZSBvZiB0aGUgZWxlbWVudCB2YWx1ZS5cbiAgICAgKiBUaGlzIHN1ZmZpeCB0ZXh0IGNhbiBoYXZlIGFueSBjaGFyYWN0ZXJzIGluIGl0cyBzdHJpbmcsIGV4Y2VwdCBudW1lcmljIGNoYXJhY3RlcnMgYW5kIHRoZSBuZWdhdGl2ZS9wb3NpdGl2ZSBzaWduLlxuICAgICAqIEV4YW1wbGU6ICcgZG9sbGFycydcbiAgICAgKi9cbiAgICBzdWZmaXhUZXh0OiB7XG4gICAgICAgIG5vbmUgICAgICA6ICcnLFxuICAgICAgICBwZXJjZW50YWdlOiAnJScsXG4gICAgICAgIHBlcm1pbGxlICA6ICfigLAnLFxuICAgICAgICBiYXNpc1BvaW50OiAn4oCxJyxcbiAgICB9LFxuXG4gICAgLyogVGhlIHRocmVlIG9wdGlvbnMgKGRpdmlzb3JXaGVuVW5mb2N1c2VkLCBkZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIgJiBzeW1ib2xXaGVuVW5mb2N1c2VkKSBoYW5kbGUgc2NhbGluZyBvZiB0aGUgaW5wdXQgd2hlbiB0aGUgaW5wdXQgZG9lcyBub3QgaGF2ZSBmb2N1c1xuICAgICAqIFBsZWFzZSBub3RlIHRoYXQgdGhlIG5vbi1zY2FsZWQgdmFsdWUgaXMgaGVsZCBpbiBkYXRhIGFuZCBpdCBpcyBhZHZpc2VkIHRoYXQgeW91IHVzZSB0aGUgYHNhdmVWYWx1ZVRvU2Vzc2lvblN0b3JhZ2VgIG9wdGlvbiB0byBlbnN1cmUgcmV0YWluaW5nIHRoZSB2YWx1ZVxuICAgICAqIFtcImRpdmlzb3JcIiwgXCJkZWNpbWFsIHBsYWNlc1wiLCBcInN5bWJvbFwiXVxuICAgICAqIEV4YW1wbGU6IHdpdGggdGhlIGZvbGxvd2luZyBvcHRpb25zIHNldCB7ZGl2aXNvcldoZW5VbmZvY3VzZWQ6ICcxMDAwJywgZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyOiAnMScsIHN5bWJvbFdoZW5VbmZvY3VzZWQ6ICcgSyd9XG4gICAgICogRXhhbXBsZTogZm9jdXNpbiB2YWx1ZSBcIjEsMTExLjExXCIgZm9jdXNvdXQgdmFsdWUgXCIxLjEgS1wiXG4gICAgICovXG5cbiAgICAvKiBUaGUgYHN5bWJvbFdoZW5VbmZvY3VzZWRgIG9wdGlvbiBpcyBhIHN5bWJvbCBwbGFjZWQgYXMgYSBzdWZmaXggd2hlbiBub3QgaW4gZm9jdXMuXG4gICAgICogVGhpcyBpcyBvcHRpb25hbCB0b28uXG4gICAgICovXG4gICAgc3ltYm9sV2hlblVuZm9jdXNlZDoge1xuICAgICAgICBub25lICAgICAgOiBudWxsLFxuICAgICAgICBwZXJjZW50YWdlOiAnJScsXG4gICAgICAgIHBlcm1pbGxlICA6ICfigLAnLFxuICAgICAgICBiYXNpc1BvaW50OiAn4oCxJyxcbiAgICB9LFxuXG4gICAgLyogRGVmaW5lcyBpZiB0aGUgZWxlbWVudCB2YWx1ZSBzaG91bGQgYmUgdW5mb3JtYXR0ZWQgd2hlbiB0aGUgdXNlciBob3ZlciBoaXMgbW91c2Ugb3ZlciBpdCB3aGlsZSBob2xkaW5nIHRoZSBgQWx0YCBrZXkuXG4gICAgICogVW5mb3JtYXR0aW5nIHRoZXJlIG1lYW5zIHRoYXQgdGhpcyByZW1vdmVzIGFueSBub24tbnVtYmVyIGNoYXJhY3RlcnMgYW5kIGRpc3BsYXlzIHRoZSAqcmF3KiB2YWx1ZSwgYXMgdW5kZXJzdG9vZCBieSBKYXZhc2NyaXB0IChpZS4gYDEyLjM0YCBpcyBhIHZhbGlkIG51bWJlciwgd2hpbGUgYDEyLDM0YCBpcyBub3QpLlxuICAgICAqXG4gICAgICogV2UgcmVmb3JtYXQgYmFjayBiZWZvcmUgYW55dGhpbmcgZWxzZSBpZiA6XG4gICAgICogLSB0aGUgdXNlciBmb2N1cyBvbiB0aGUgZWxlbWVudCBieSB0YWJiaW5nIG9yIGNsaWNraW5nIGludG8gaXQsXG4gICAgICogLSB0aGUgdXNlciByZWxlYXNlcyB0aGUgYEFsdGAga2V5LCBhbmRcbiAgICAgKiAtIGlmIHdlIGRldGVjdCBhIG1vdXNlbGVhdmUgZXZlbnQuXG4gICAgICpcbiAgICAgKiBXZSB1bmZvcm1hdCBhZ2FpbiBpZiA6XG4gICAgICogLSB3aGlsZSB0aGUgbW91c2UgaXMgb3ZlciB0aGUgZWxlbWVudCwgdGhlIHVzZXIgaGl0IGBBbHRgIGFnYWluXG4gICAgICovXG4gICAgdW5mb3JtYXRPbkhvdmVyOiB7XG4gICAgICAgIHVuZm9ybWF0ICAgICA6IHRydWUsXG4gICAgICAgIGRvTm90VW5mb3JtYXQ6IGZhbHNlLCAvL1RPRE8gUmVuYW1lIHRvIGBrZWVwRm9ybWF0YFxuICAgIH0sXG5cbiAgICAvKiBSZW1vdmVzIHRoZSBmb3JtYXR0aW5nIGFuZCB1c2UgdGhlIHJhdyB2YWx1ZSBpbiBlYWNoIGF1dG9OdW1lcmljIGVsZW1lbnRzIG9mIHRoZSBwYXJlbnQgZm9ybSBlbGVtZW50LCBvbiB0aGUgZm9ybSBgc3VibWl0YCBldmVudC5cbiAgICAgKiBUaGUgb3V0cHV0IGZvcm1hdCBpcyBhIG51bWVyaWMgc3RyaW5nIChubm5uLm5uIG9yIC1ubm5uLm5uKS5cbiAgICAgKi9cbiAgICB1bmZvcm1hdE9uU3VibWl0OiB7XG4gICAgICAgIHVuZm9ybWF0ICAgICAgICA6IHRydWUsXG4gICAgICAgIGtlZXBDdXJyZW50VmFsdWU6IGZhbHNlLFxuICAgIH0sXG5cbiAgICAvKiBQcm92aWRlcyBhIHdheSBmb3IgYXV0b21hdGljYWxseSByZXBsYWNpbmcgdGhlIGZvcm1hdHRlZCB2YWx1ZSB3aXRoIGEgcHJlLWRlZmluZWQgc3RyaW5nLCB3aGVuIHRoZSByYXcgdmFsdWUgaXMgZXF1YWwgdG8gYSBzcGVjaWZpYyB2YWx1ZVxuICAgICAqIEhlcmUgeW91IGNhbiBzcGVjaWZ5IGFzIG1hbnkgJ2NvbnZlcnNpb24nIGFzIG5lZWRlZC5cbiAgICAgKi9cbiAgICB2YWx1ZXNUb1N0cmluZ3M6IHtcbiAgICAgICAgbm9uZSAgICAgICAgIDogbnVsbCxcbiAgICAgICAgemVyb0Rhc2ggICAgIDoge1xuICAgICAgICAgICAgMDogJy0nLFxuICAgICAgICB9LFxuICAgICAgICBvbmVBcm91bmRaZXJvOiB7XG4gICAgICAgICAgICAnLTEnOiAnTWluJyxcbiAgICAgICAgICAgIDEgICA6ICdNYXgnLFxuICAgICAgICB9LFxuICAgIH0sXG5cbiAgICAvKiBEZWZpbmVzIGlmIHRoZSBBdXRvTnVtZXJpYyBlbGVtZW50IHNob3VsZCB3YXRjaCBleHRlcm5hbCBjaGFuZ2VzIG1hZGUgd2l0aG91dCB1c2luZyBgLnNldCgpYCwgYnV0IGJ5IHVzaW5nIHRoZSBiYXNpYyBgYU5FbGVtZW50Lm5vZGUoKS52YWx1ZSA9IDQyYCBub3RhdGlvbi5cbiAgICAgKiBJZiBzZXQgdG8gYHdhdGNoYCwgdGhlbiBBdXRvTnVtZXJpYyB3aWxsIGZvcm1hdCB0aGUgbmV3IHZhbHVlIHVzaW5nIGAuc2V0KClgIGludGVybmFsbHkuXG4gICAgICogT3RoZXJ3aXNlIGl0IHdpbGwgbmVpdGhlciBmb3JtYXQgaXQsIG5vciBzYXZlIGl0IGluIHRoZSBoaXN0b3J5LlxuICAgICAqL1xuICAgIHdhdGNoRXh0ZXJuYWxDaGFuZ2VzOiB7XG4gICAgICAgIHdhdGNoICAgICA6IHRydWUsXG4gICAgICAgIGRvTm90V2F0Y2g6IGZhbHNlLFxuICAgIH0sXG5cbiAgICAvKiBEZWZpbmVzIHdoZW4gdGhlIHdoZWVsIGV2ZW50IHdpbGwgaW5jcmVtZW50IG9yIGRlY3JlbWVudCB0aGUgZWxlbWVudCB2YWx1ZS5cbiAgICAgKiBXaGVuIHNldCB0byBgJ2ZvY3VzJ2AsIHRoZSBBdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnQgbmVlZHMgdG8gYmUgZm9jdXNlZCBmb3IgdGhlIHdoZWVsIGV2ZW50IHRvIGNoYW5nZSB0aGUgdmFsdWUuXG4gICAgICogV2hlbiBzZXQgdG8gYCdob3ZlcidgLCB1c2luZyB0aGUgd2hlZWwgZXZlbnQgd2hpbGUgdGhlIG1vdXNlIGlzIGhvdmVyaW5nIHRoZSBlbGVtZW50IGlzIHN1ZmZpY2llbnQgKG5vIGZvY3VzIG5lZWRlZCkuXG4gICAgICpcbiAgICAgKiBOb3RlIDpcbiAgICAgKiBXaGVuIGB3aGVlbE9uYCBpcyBzZXQgdG8gYCdmb2N1cydgLCB5b3UgY2FuIHVzZSB0aGUgJ1NoaWZ0JyBtb2RpZmllciBrZXkgd2hpbGUgdXNpbmcgdGhlIG1vdXNlIHdoZWVsIGluIG9yZGVyIHRvIHRlbXBvcmFyaWx5IGFjdGl2YXRlIHRoZSBpbmNyZW1lbnQvZGVjcmVtZW50IGZlYXR1cmUgZXZlbiBpZiB0aGUgZWxlbWVudCBpcyBub3QgZm9jdXNlZC5cbiAgICAgKiBXaGVuIGB3aGVlbE9uYCBpcyBzZXQgdG8gYCdob3ZlcidgLCB5b3UgY2FuIHVzZSB0aGUgJ1NoaWZ0JyBtb2RpZmllciBrZXkgd2hpbGUgdXNpbmcgdGhlIG1vdXNlIHdoZWVsIGluIG9yZGVyIHRvIHRlbXBvcmFyaWx5IGRpc2FibGUgdGhlIGluY3JlbWVudC9kZWNyZW1lbnQgZmVhdHVyZSBldmVuIGlmIHRoZSBlbGVtZW50IGlzIG5vdCBob3ZlcmVkLlxuICAgICAqL1xuICAgIHdoZWVsT246IHtcbiAgICAgICAgZm9jdXM6ICdmb2N1cycsXG4gICAgICAgIGhvdmVyOiAnaG92ZXInLFxuICAgIH0sXG5cbiAgICAvKiBUaGF0IG9wdGlvbiBpcyBsaW5rZWQgdG8gdGhlIGBtb2RpZnlWYWx1ZU9uV2hlZWxgIG9uZSBhbmQgd2lsbCBvbmx5IGJlIHVzZWQgaWYgdGhlIGxhdHRlciBpcyBzZXQgdG8gYHRydWVgLlxuICAgICAqIFRoaXMgb3B0aW9uIHdpbGwgbW9kaWZ5IHRoZSB3aGVlbCBiZWhhdmlvciBhbmQgY2FuIGJlIHVzZWQgaW4gdHdvIHdheXMsIGVpdGhlciBieSBzZXR0aW5nIDpcbiAgICAgKiAtIGEgJ2ZpeGVkJyBzdGVwIHZhbHVlIChhIHBvc2l0aXZlIGZsb2F0IG9yIGludGVnZXIgbnVtYmVyIGAxMDAwYCksIG9yXG4gICAgICogLSB0aGUgYCdwcm9ncmVzc2l2ZSdgIHN0cmluZy5cbiAgICAgKlxuICAgICAqIFRoZSAnZml4ZWQnIG1vZGUgYWx3YXlzIGluY3JlbWVudC9kZWNyZW1lbnQgdGhlIGVsZW1lbnQgdmFsdWUgYnkgdGhhdCBhbW91bnQsIHdoaWxlIHJlc3BlY3RpbmcgdGhlIGBtaW5pbXVtVmFsdWVgIGFuZCBgbWF4aW11bVZhbHVlYCBzZXR0aW5ncy5cbiAgICAgKiBUaGUgJ3Byb2dyZXNzaXZlJyBtb2RlIHdpbGwgaW5jcmVtZW50L2RlY3JlbWVudCB0aGUgZWxlbWVudCB2YWx1ZSBiYXNlZCBvbiBpdHMgY3VycmVudCB2YWx1ZS4gVGhlIGJpZ2dlciB0aGUgbnVtYmVyLCB0aGUgYmlnZ2VyIHRoZSBzdGVwLCBhbmQgdmljZSB2ZXJzYS5cbiAgICAgKi9cbiAgICB3aGVlbFN0ZXA6IHtcbiAgICAgICAgcHJvZ3Jlc3NpdmU6ICdwcm9ncmVzc2l2ZScsXG4gICAgfSxcbn07XG5cbi8qKlxuICogU2ltcGxlIGZ1bmN0aW9uIHRoYXQgd2lsbCBzZW1pLWRlZXAgZnJlZXplIHRoZSBgQXV0b051bWVyaWMub3B0aW9uc2Agb2JqZWN0LlxuICogQnkgJ3NlbWknIGl0IG1lYW5zIHRoZSBuZXN0ZWQgb2JqZWN0cyBpbiB0aGUgYHN0eWxlUnVsZXNgIG9wdGlvbiBhcmUgbm90IGZyb3plbi5cbiAqIFRoZSBvbmVzIGluIHRoZSBgdmFsdWVzVG9TdHJpbmdzYCBhcmUgdGhvdWdoLCBzaW5jZSB0aGV5IGFyZSBtdWNoIG1vcmUgc2ltcGxlLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zXG4gKiBAcmV0dXJucyB7UmVhZG9ubHlBcnJheTxhbnk+fVxuICovXG5mdW5jdGlvbiBmcmVlemVPcHRpb25zKG9wdGlvbnMpIHtcbiAgICAvLyBGcmVlemUgZWFjaCBwcm9wZXJ0eSBvYmplY3RzXG4gICAgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMob3B0aW9ucykuZm9yRWFjaChvcHRpb25OYW1lID0+IHtcbiAgICAgICAgaWYgKG9wdGlvbk5hbWUgPT09ICd2YWx1ZXNUb1N0cmluZ3MnKSB7XG4gICAgICAgICAgICBjb25zdCB2c1Byb3BzID0gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMob3B0aW9ucy52YWx1ZXNUb1N0cmluZ3MpO1xuICAgICAgICAgICAgdnNQcm9wcy5mb3JFYWNoKHZhbHVlc1RvU3RyaW5nT2JqZWN0TmFtZSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc0lFMTEoKSB8fCBvcHRpb25zLnZhbHVlc1RvU3RyaW5nc1t2YWx1ZXNUb1N0cmluZ09iamVjdE5hbWVdICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5mcmVlemUob3B0aW9ucy52YWx1ZXNUb1N0cmluZ3NbdmFsdWVzVG9TdHJpbmdPYmplY3ROYW1lXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAob3B0aW9uTmFtZSAhPT0gJ3N0eWxlUnVsZXMnKSB7XG4gICAgICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzSUUxMSgpIHx8IG9wdGlvbnNbb3B0aW9uTmFtZV0gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBPYmplY3QuZnJlZXplKG9wdGlvbnNbb3B0aW9uTmFtZV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBUaGVuIGZyZWV6ZSB0aGUgb3B0aW9ucyBvYmplY3QgZ2xvYmFsbHlcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShvcHRpb25zKTtcbn1cblxuZnJlZXplT3B0aW9ucyhBdXRvTnVtZXJpYy5vcHRpb25zKTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShBdXRvTnVtZXJpYywgJ29wdGlvbnMnLCB7IGNvbmZpZ3VyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiBmYWxzZSB9KTtcbiJdLCJtYXBwaW5ncyI6Ijs7QUE2QkE7QUFDQTs7O0FBQUE7QUFDQTs7Ozs7QUFDQTs7O0FBaENBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQW1DQTtBQUNBOzs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUhBO0FBQ0E7QUFLQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUZBO0FBQ0E7QUFJQTs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUxBO0FBQ0E7QUFPQTs7O0FBR0E7QUFDQTtBQUNBO0FBRkE7QUFDQTtBQUlBOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBNUNBO0FBQ0E7QUE4Q0E7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFGQTtBQUNBO0FBSUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBTEE7QUFDQTtBQU9BOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFIQTtBQUNBO0FBS0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFQQTtBQUNBO0FBU0E7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBUkE7QUFDQTtBQVVBOzs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBUkE7QUFDQTtBQVVBOzs7Ozs7OztBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVJBO0FBQ0E7QUFVQTs7Ozs7O0FBTUE7QUFDQTtBQURBO0FBQ0E7QUFHQTs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFKQTtBQUNBO0FBTUE7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFWQTtBQUNBO0FBWUE7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSkE7QUFDQTtBQU1BOzs7Ozs7Ozs7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBUEE7QUFDQTtBQVNBOztBQUVBO0FBQ0E7QUFDQTtBQUZBO0FBQ0E7QUFJQTs7QUFFQTtBQUNBO0FBQ0E7QUFGQTtBQUNBO0FBSUE7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFGQTtBQUNBO0FBSUE7O0FBRUE7QUFDQTtBQUNBO0FBRkE7QUFDQTtBQUlBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQU5BO0FBQ0E7QUFRQTs7Ozs7Ozs7OztBQVVBO0FBQ0E7QUFDQTtBQUZBO0FBQ0E7QUFJQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUhBO0FBQ0E7QUFLQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUhBO0FBQ0E7QUFLQTs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFIQTtBQUNBO0FBS0E7Ozs7Ozs7OztBQVNBO0FBQ0E7QUFDQTtBQUZBO0FBQ0E7QUFJQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVhBO0FBQ0E7QUFhQTs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFpQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBTEE7QUFDQTtBQU9BOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVpBO0FBQ0E7QUFjQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFGQTtBQUNBO0FBSUE7Ozs7Ozs7Ozs7Ozs7O0FBY0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBTEE7QUFDQTtBQU9BOzs7Ozs7Ozs7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVRBO0FBQ0E7QUFXQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSkE7QUFDQTtBQU1BOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQWhCQTtBQUNBO0FBa0JBOzs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFKQTtBQUNBO0FBTUE7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBRkE7QUFDQTtBQUlBOzs7Ozs7Ozs7Ozs7OztBQWNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFiQTtBQUNBO0FBZUE7OztBQUdBO0FBQ0E7QUFDQTtBQUZBO0FBQ0E7QUFJQTs7O0FBR0E7QUFDQTtBQUNBO0FBRkE7QUFDQTtBQUlBOzs7QUFHQTtBQUNBO0FBQ0E7QUFGQTtBQUNBO0FBSUE7Ozs7Ozs7O0FBUUE7QUFDQTtBQUNBO0FBRkE7QUFDQTtBQUlBOzs7OztBQUtBO0FBQ0E7QUFDQTtBQUZBO0FBQ0E7QUFJQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUZBO0FBQ0E7QUFJQTs7O0FBR0E7QUFDQTtBQUNBO0FBRkE7QUFDQTtBQUlBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUEyQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUZBO0FBSUE7QUFDQTtBQURBO0FBUUE7QUFDQTtBQUNBO0FBQUE7QUFGQTtBQUtBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBZEE7QUFGQTtBQW5CQTtBQUNBO0FBNENBOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUpBO0FBQ0E7QUFNQTs7Ozs7OztBQU9BOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSkE7QUFDQTtBQU1BOzs7Ozs7Ozs7OztBQVdBO0FBQ0E7QUFDQTtBQUZBO0FBQ0E7QUFJQTs7O0FBR0E7QUFDQTtBQUNBO0FBRkE7QUFDQTtBQUlBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQURBO0FBR0E7QUFDQTtBQUNBO0FBRkE7QUFMQTtBQUNBO0FBVUE7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFGQTtBQUNBO0FBSUE7Ozs7Ozs7O0FBUUE7QUFDQTtBQUNBO0FBRkE7QUFDQTtBQUlBOzs7Ozs7OztBQVFBO0FBQ0E7QUFEQTtBQWx5QkE7QUFDQTtBQXN5QkE7Ozs7Ozs7O0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./src/AutoNumericOptions.js\n");

/***/ }),

/***/ "./src/AutoNumericPredefinedOptions.js":
/*!*********************************************!*\
  !*** ./src/AutoNumericPredefinedOptions.js ***!
  \*********************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

"use strict";
eval("\n\nvar _AutoNumeric = __webpack_require__(/*! ./AutoNumeric */ \"./src/AutoNumeric.js\");\n\nvar _AutoNumeric2 = _interopRequireDefault(_AutoNumeric);\n\nvar _AutoNumericHelper = __webpack_require__(/*! ./AutoNumericHelper */ \"./src/AutoNumericHelper.js\");\n\nvar _AutoNumericHelper2 = _interopRequireDefault(_AutoNumericHelper);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * Pre-defined options for autoNumeric.js\n * @author Alexandre Bonneau <alexandre.bonneau@linuxfr.eu>\n * @copyright © 2016 Alexandre Bonneau\n *\n * The MIT License (http://www.opensource.org/licenses/mit-license.php)\n *\n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sub license, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\nvar euro = { // Français\n    digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.dot, // or '\\u202f'\n    decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.comma,\n    decimalCharacterAlternative: _AutoNumeric2.default.options.decimalCharacterAlternative.dot,\n    currencySymbol: '\\u202F\\u20AC',\n    currencySymbolPlacement: _AutoNumeric2.default.options.currencySymbolPlacement.suffix,\n    negativePositiveSignPlacement: _AutoNumeric2.default.options.negativePositiveSignPlacement.prefix\n};\n\nvar dollar = {\n    digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.comma,\n    decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.dot,\n    currencySymbol: _AutoNumeric2.default.options.currencySymbol.dollar,\n    currencySymbolPlacement: _AutoNumeric2.default.options.currencySymbolPlacement.prefix,\n    negativePositiveSignPlacement: _AutoNumeric2.default.options.negativePositiveSignPlacement.right\n};\n\nvar japanese = { // 日本語\n    digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.comma,\n    decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.dot,\n    currencySymbol: _AutoNumeric2.default.options.currencySymbol.yen,\n    currencySymbolPlacement: _AutoNumeric2.default.options.currencySymbolPlacement.prefix,\n    negativePositiveSignPlacement: _AutoNumeric2.default.options.negativePositiveSignPlacement.right\n};\n\n// Here we need to clone the initial objects in order to be able to edit the clones without affecting the originals\nvar euroPos = _AutoNumericHelper2.default.cloneObject(euro);\neuroPos.minimumValue = 0;\nvar euroNeg = _AutoNumericHelper2.default.cloneObject(euro);\neuroNeg.maximumValue = 0;\neuroNeg.negativePositiveSignPlacement = _AutoNumeric2.default.options.negativePositiveSignPlacement.prefix;\n\nvar euroSpace = _AutoNumericHelper2.default.cloneObject(euro);\neuroSpace.digitGroupSeparator = _AutoNumeric2.default.options.digitGroupSeparator.normalSpace;\nvar euroSpacePos = _AutoNumericHelper2.default.cloneObject(euroSpace);\neuroSpacePos.minimumValue = 0;\nvar euroSpaceNeg = _AutoNumericHelper2.default.cloneObject(euroSpace);\neuroSpaceNeg.maximumValue = 0;\neuroSpaceNeg.negativePositiveSignPlacement = _AutoNumeric2.default.options.negativePositiveSignPlacement.prefix;\n\nvar percentageEU2dec = _AutoNumericHelper2.default.cloneObject(euro);\npercentageEU2dec.currencySymbol = _AutoNumeric2.default.options.currencySymbol.none;\npercentageEU2dec.suffixText = '\\u202F' + _AutoNumeric2.default.options.suffixText.percentage;\npercentageEU2dec.wheelStep = 0.0001; // This targets the `rawValue`, not the formatted one\npercentageEU2dec.rawValueDivisor = _AutoNumeric2.default.options.rawValueDivisor.percentage;\nvar percentageEU2decPos = _AutoNumericHelper2.default.cloneObject(percentageEU2dec);\npercentageEU2decPos.minimumValue = 0;\nvar percentageEU2decNeg = _AutoNumericHelper2.default.cloneObject(percentageEU2dec);\npercentageEU2decNeg.maximumValue = 0;\npercentageEU2decNeg.negativePositiveSignPlacement = _AutoNumeric2.default.options.negativePositiveSignPlacement.prefix;\n\nvar percentageEU3dec = _AutoNumericHelper2.default.cloneObject(percentageEU2dec);\npercentageEU3dec.decimalPlaces = 3;\nvar percentageEU3decPos = _AutoNumericHelper2.default.cloneObject(percentageEU2decPos);\npercentageEU3decPos.decimalPlaces = 3;\nvar percentageEU3decNeg = _AutoNumericHelper2.default.cloneObject(percentageEU2decNeg);\npercentageEU3decNeg.decimalPlaces = 3;\n\nvar dollarPos = _AutoNumericHelper2.default.cloneObject(dollar);\ndollarPos.minimumValue = 0;\nvar dollarNeg = _AutoNumericHelper2.default.cloneObject(dollar);\ndollarNeg.maximumValue = 0;\ndollarNeg.negativePositiveSignPlacement = _AutoNumeric2.default.options.negativePositiveSignPlacement.prefix;\nvar dollarNegBrackets = _AutoNumericHelper2.default.cloneObject(dollarNeg);\ndollarNegBrackets.negativeBracketsTypeOnBlur = _AutoNumeric2.default.options.negativeBracketsTypeOnBlur.parentheses;\n\nvar percentageUS2dec = _AutoNumericHelper2.default.cloneObject(dollar);\npercentageUS2dec.currencySymbol = _AutoNumeric2.default.options.currencySymbol.none;\npercentageUS2dec.suffixText = _AutoNumeric2.default.options.suffixText.percentage;\npercentageUS2dec.wheelStep = 0.0001;\npercentageUS2dec.rawValueDivisor = _AutoNumeric2.default.options.rawValueDivisor.percentage;\nvar percentageUS2decPos = _AutoNumericHelper2.default.cloneObject(percentageUS2dec);\npercentageUS2decPos.minimumValue = 0;\nvar percentageUS2decNeg = _AutoNumericHelper2.default.cloneObject(percentageUS2dec);\npercentageUS2decNeg.maximumValue = 0;\npercentageUS2decNeg.negativePositiveSignPlacement = _AutoNumeric2.default.options.negativePositiveSignPlacement.prefix;\n\nvar percentageUS3dec = _AutoNumericHelper2.default.cloneObject(percentageUS2dec);\npercentageUS3dec.decimalPlaces = 3;\nvar percentageUS3decPos = _AutoNumericHelper2.default.cloneObject(percentageUS2decPos);\npercentageUS3decPos.decimalPlaces = 3;\nvar percentageUS3decNeg = _AutoNumericHelper2.default.cloneObject(percentageUS2decNeg);\npercentageUS3decNeg.decimalPlaces = 3;\n\nvar turkish = _AutoNumericHelper2.default.cloneObject(euro);\nturkish.currencySymbol = _AutoNumeric2.default.options.currencySymbol.lira;\n\n/**\n * Predefined options for the most common languages\n */\n_AutoNumeric2.default.predefinedOptions = {\n    euro: euro,\n    euroPos: euroPos,\n    euroNeg: euroNeg,\n    euroSpace: euroSpace,\n    euroSpacePos: euroSpacePos,\n    euroSpaceNeg: euroSpaceNeg,\n    percentageEU2dec: percentageEU2dec,\n    percentageEU2decPos: percentageEU2decPos,\n    percentageEU2decNeg: percentageEU2decNeg,\n    percentageEU3dec: percentageEU3dec,\n    percentageEU3decPos: percentageEU3decPos,\n    percentageEU3decNeg: percentageEU3decNeg,\n    dollar: dollar,\n    dollarPos: dollarPos,\n    dollarNeg: dollarNeg,\n    dollarNegBrackets: dollarNegBrackets,\n    percentageUS2dec: percentageUS2dec,\n    percentageUS2decPos: percentageUS2decPos,\n    percentageUS2decNeg: percentageUS2decNeg,\n    percentageUS3dec: percentageUS3dec,\n    percentageUS3decPos: percentageUS3decPos,\n    percentageUS3decNeg: percentageUS3decNeg,\n    French: euro, // Français\n    Spanish: euro, // Español\n    NorthAmerican: dollar,\n    British: {\n        digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.comma,\n        decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.dot,\n        currencySymbol: _AutoNumeric2.default.options.currencySymbol.pound,\n        currencySymbolPlacement: _AutoNumeric2.default.options.currencySymbolPlacement.prefix,\n        negativePositiveSignPlacement: _AutoNumeric2.default.options.negativePositiveSignPlacement.right\n    },\n    Swiss: { // Suisse\n        digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.apostrophe,\n        decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.dot,\n        currencySymbol: '\\u202FCHF',\n        currencySymbolPlacement: _AutoNumeric2.default.options.currencySymbolPlacement.suffix,\n        negativePositiveSignPlacement: _AutoNumeric2.default.options.negativePositiveSignPlacement.prefix\n    },\n    Japanese: japanese, // 日本語\n    Chinese: japanese, // 中国語 (Chinese)\n    Brazilian: {\n        digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.dot,\n        decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.comma,\n        currencySymbol: _AutoNumeric2.default.options.currencySymbol.real,\n        currencySymbolPlacement: _AutoNumeric2.default.options.currencySymbolPlacement.prefix,\n        negativePositiveSignPlacement: _AutoNumeric2.default.options.negativePositiveSignPlacement.right\n    },\n    Turkish: turkish,\n    dotDecimalCharCommaSeparator: {\n        digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.comma,\n        decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.dot\n    },\n    commaDecimalCharDotSeparator: {\n        digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.dot,\n        decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.comma,\n        decimalCharacterAlternative: _AutoNumeric2.default.options.decimalCharacterAlternative.dot\n    },\n    integer: {\n        decimalPlaces: 0\n    },\n    integerPos: {\n        minimumValue: _AutoNumeric2.default.options.minimumValue.zero,\n        decimalPlaces: 0\n    },\n    integerNeg: {\n        maximumValue: _AutoNumeric2.default.options.maximumValue.zero,\n        decimalPlaces: 0\n    },\n    float: {\n        allowDecimalPadding: _AutoNumeric2.default.options.allowDecimalPadding.never\n    },\n    floatPos: {\n        allowDecimalPadding: _AutoNumeric2.default.options.allowDecimalPadding.never,\n        minimumValue: _AutoNumeric2.default.options.minimumValue.zero,\n        maximumValue: _AutoNumeric2.default.options.maximumValue.tenTrillions\n    },\n    floatNeg: {\n        allowDecimalPadding: _AutoNumeric2.default.options.allowDecimalPadding.never,\n        minimumValue: _AutoNumeric2.default.options.minimumValue.tenTrillions,\n        maximumValue: _AutoNumeric2.default.options.maximumValue.zero\n    },\n    numeric: {\n        digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.noSeparator,\n        decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.dot,\n        currencySymbol: _AutoNumeric2.default.options.currencySymbol.none\n    },\n    numericPos: {\n        digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.noSeparator,\n        decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.dot,\n        currencySymbol: _AutoNumeric2.default.options.currencySymbol.none,\n        minimumValue: _AutoNumeric2.default.options.minimumValue.zero,\n        maximumValue: _AutoNumeric2.default.options.maximumValue.tenTrillions\n    },\n    numericNeg: {\n        digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.noSeparator,\n        decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.dot,\n        currencySymbol: _AutoNumeric2.default.options.currencySymbol.none,\n        minimumValue: _AutoNumeric2.default.options.minimumValue.tenTrillions,\n        maximumValue: _AutoNumeric2.default.options.maximumValue.zero\n    }\n};\n\nObject.getOwnPropertyNames(_AutoNumeric2.default.predefinedOptions).forEach(function (optionName) {\n    Object.freeze(_AutoNumeric2.default.predefinedOptions[optionName]);\n});\nObject.freeze(_AutoNumeric2.default.predefinedOptions);\nObject.defineProperty(_AutoNumeric2.default, 'predefinedOptions', { configurable: false, writable: false });\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvQXV0b051bWVyaWNQcmVkZWZpbmVkT3B0aW9ucy5qcy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovL0F1dG9OdW1lcmljL3NyYy9BdXRvTnVtZXJpY1ByZWRlZmluZWRPcHRpb25zLmpzPzFlZTMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBQcmUtZGVmaW5lZCBvcHRpb25zIGZvciBhdXRvTnVtZXJpYy5qc1xuICogQGF1dGhvciBBbGV4YW5kcmUgQm9ubmVhdSA8YWxleGFuZHJlLmJvbm5lYXVAbGludXhmci5ldT5cbiAqIEBjb3B5cmlnaHQgwqkgMjAxNiBBbGV4YW5kcmUgQm9ubmVhdVxuICpcbiAqIFRoZSBNSVQgTGljZW5zZSAoaHR0cDovL3d3dy5vcGVuc291cmNlLm9yZy9saWNlbnNlcy9taXQtbGljZW5zZS5waHApXG4gKlxuICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb25cbiAqIG9idGFpbmluZyBhIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uXG4gKiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXRcbiAqIHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLFxuICogY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3ViIGxpY2Vuc2UsIGFuZC9vciBzZWxsXG4gKiBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGVcbiAqIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nXG4gKiBjb25kaXRpb25zOlxuICpcbiAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlXG4gKiBpbmNsdWRlZCBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbiAqXG4gKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELFxuICogRVhQUkVTUyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTXG4gKiBPRiBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORFxuICogTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFRcbiAqIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLFxuICogV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HXG4gKiBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SXG4gKiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG4gKi9cblxuaW1wb3J0IEF1dG9OdW1lcmljIGZyb20gJy4vQXV0b051bWVyaWMnO1xuaW1wb3J0IEF1dG9OdW1lcmljSGVscGVyIGZyb20gJy4vQXV0b051bWVyaWNIZWxwZXInO1xuXG5jb25zdCBldXJvID0geyAvLyBGcmFuw6dhaXNcbiAgICBkaWdpdEdyb3VwU2VwYXJhdG9yICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmRvdCwgLy8gb3IgJ1xcdTIwMmYnXG4gICAgZGVjaW1hbENoYXJhY3RlciAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3Rlci5jb21tYSxcbiAgICBkZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUgIDogQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUuZG90LFxuICAgIGN1cnJlbmN5U3ltYm9sICAgICAgICAgICAgICAgOiAnXFx1MjAyZuKCrCcsXG4gICAgY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQuc3VmZml4LFxuICAgIG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50OiBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnByZWZpeCxcbn07XG5cbmNvbnN0IGRvbGxhciA9IHtcbiAgICBkaWdpdEdyb3VwU2VwYXJhdG9yICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmNvbW1hLFxuICAgIGRlY2ltYWxDaGFyYWN0ZXIgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXIuZG90LFxuICAgIGN1cnJlbmN5U3ltYm9sICAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sLmRvbGxhcixcbiAgICBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudCAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXgsXG4gICAgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQ6IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQsXG59O1xuXG5jb25zdCBqYXBhbmVzZSA9IHsgLy8g5pel5pys6KqeXG4gICAgZGlnaXRHcm91cFNlcGFyYXRvciAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci5jb21tYSxcbiAgICBkZWNpbWFsQ2hhcmFjdGVyICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyLmRvdCxcbiAgICBjdXJyZW5jeVN5bWJvbCAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbC55ZW4sXG4gICAgY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQucHJlZml4LFxuICAgIG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50OiBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnJpZ2h0LFxufTtcblxuXG4vLyBIZXJlIHdlIG5lZWQgdG8gY2xvbmUgdGhlIGluaXRpYWwgb2JqZWN0cyBpbiBvcmRlciB0byBiZSBhYmxlIHRvIGVkaXQgdGhlIGNsb25lcyB3aXRob3V0IGFmZmVjdGluZyB0aGUgb3JpZ2luYWxzXG5jb25zdCBldXJvUG9zICAgICAgICAgICAgICAgICAgICAgICAgID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QoZXVybyk7XG5ldXJvUG9zLm1pbmltdW1WYWx1ZSAgICAgICAgICAgICAgICAgID0gMDtcbmNvbnN0IGV1cm9OZWcgICAgICAgICAgICAgICAgICAgICAgICAgPSBBdXRvTnVtZXJpY0hlbHBlci5jbG9uZU9iamVjdChldXJvKTtcbmV1cm9OZWcubWF4aW11bVZhbHVlICAgICAgICAgICAgICAgICAgPSAwO1xuZXVyb05lZy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4O1xuXG5jb25zdCBldXJvU3BhY2UgICAgICAgICAgICAgICAgICAgICAgICAgICAgPSBBdXRvTnVtZXJpY0hlbHBlci5jbG9uZU9iamVjdChldXJvKTtcbmV1cm9TcGFjZS5kaWdpdEdyb3VwU2VwYXJhdG9yICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci5ub3JtYWxTcGFjZTtcbmNvbnN0IGV1cm9TcGFjZVBvcyAgICAgICAgICAgICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KGV1cm9TcGFjZSk7XG5ldXJvU3BhY2VQb3MubWluaW11bVZhbHVlICAgICAgICAgICAgICAgICAgPSAwO1xuY29uc3QgZXVyb1NwYWNlTmVnICAgICAgICAgICAgICAgICAgICAgICAgID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QoZXVyb1NwYWNlKTtcbmV1cm9TcGFjZU5lZy5tYXhpbXVtVmFsdWUgICAgICAgICAgICAgICAgICA9IDA7XG5ldXJvU3BhY2VOZWcubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnByZWZpeDtcblxuY29uc3QgcGVyY2VudGFnZUVVMmRlYyAgICAgICAgICAgICAgICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KGV1cm8pO1xucGVyY2VudGFnZUVVMmRlYy5jdXJyZW5jeVN5bWJvbCAgICAgICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2wubm9uZTtcbnBlcmNlbnRhZ2VFVTJkZWMuc3VmZml4VGV4dCAgICAgICAgICAgICAgICAgICAgICAgPSBgXFx1MjAyZiR7QXV0b051bWVyaWMub3B0aW9ucy5zdWZmaXhUZXh0LnBlcmNlbnRhZ2V9YDtcbnBlcmNlbnRhZ2VFVTJkZWMud2hlZWxTdGVwICAgICAgICAgICAgICAgICAgICAgICAgPSAwLjAwMDE7IC8vIFRoaXMgdGFyZ2V0cyB0aGUgYHJhd1ZhbHVlYCwgbm90IHRoZSBmb3JtYXR0ZWQgb25lXG5wZXJjZW50YWdlRVUyZGVjLnJhd1ZhbHVlRGl2aXNvciAgICAgICAgICAgICAgICAgID0gQXV0b051bWVyaWMub3B0aW9ucy5yYXdWYWx1ZURpdmlzb3IucGVyY2VudGFnZTtcbmNvbnN0IHBlcmNlbnRhZ2VFVTJkZWNQb3MgICAgICAgICAgICAgICAgICAgICAgICAgPSBBdXRvTnVtZXJpY0hlbHBlci5jbG9uZU9iamVjdChwZXJjZW50YWdlRVUyZGVjKTtcbnBlcmNlbnRhZ2VFVTJkZWNQb3MubWluaW11bVZhbHVlICAgICAgICAgICAgICAgICAgPSAwO1xuY29uc3QgcGVyY2VudGFnZUVVMmRlY05lZyAgICAgICAgICAgICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KHBlcmNlbnRhZ2VFVTJkZWMpO1xucGVyY2VudGFnZUVVMmRlY05lZy5tYXhpbXVtVmFsdWUgICAgICAgICAgICAgICAgICA9IDA7XG5wZXJjZW50YWdlRVUyZGVjTmVnLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXg7XG5cbmNvbnN0IHBlcmNlbnRhZ2VFVTNkZWMgICAgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KHBlcmNlbnRhZ2VFVTJkZWMpO1xucGVyY2VudGFnZUVVM2RlYy5kZWNpbWFsUGxhY2VzICAgID0gMztcbmNvbnN0IHBlcmNlbnRhZ2VFVTNkZWNQb3MgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KHBlcmNlbnRhZ2VFVTJkZWNQb3MpO1xucGVyY2VudGFnZUVVM2RlY1Bvcy5kZWNpbWFsUGxhY2VzID0gMztcbmNvbnN0IHBlcmNlbnRhZ2VFVTNkZWNOZWcgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KHBlcmNlbnRhZ2VFVTJkZWNOZWcpO1xucGVyY2VudGFnZUVVM2RlY05lZy5kZWNpbWFsUGxhY2VzID0gMztcblxuY29uc3QgZG9sbGFyUG9zICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPSBBdXRvTnVtZXJpY0hlbHBlci5jbG9uZU9iamVjdChkb2xsYXIpO1xuZG9sbGFyUG9zLm1pbmltdW1WYWx1ZSAgICAgICAgICAgICAgICAgICAgICAgPSAwO1xuY29uc3QgZG9sbGFyTmVnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPSBBdXRvTnVtZXJpY0hlbHBlci5jbG9uZU9iamVjdChkb2xsYXIpO1xuZG9sbGFyTmVnLm1heGltdW1WYWx1ZSAgICAgICAgICAgICAgICAgICAgICAgPSAwO1xuZG9sbGFyTmVnLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ICAgICAgPSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnByZWZpeDtcbmNvbnN0IGRvbGxhck5lZ0JyYWNrZXRzICAgICAgICAgICAgICAgICAgICAgID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QoZG9sbGFyTmVnKTtcbmRvbGxhck5lZ0JyYWNrZXRzLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyID0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ci5wYXJlbnRoZXNlcztcblxuY29uc3QgcGVyY2VudGFnZVVTMmRlYyAgICAgICAgICAgICAgICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KGRvbGxhcik7XG5wZXJjZW50YWdlVVMyZGVjLmN1cnJlbmN5U3ltYm9sICAgICAgICAgICAgICAgICAgID0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbC5ub25lO1xucGVyY2VudGFnZVVTMmRlYy5zdWZmaXhUZXh0ICAgICAgICAgICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljLm9wdGlvbnMuc3VmZml4VGV4dC5wZXJjZW50YWdlO1xucGVyY2VudGFnZVVTMmRlYy53aGVlbFN0ZXAgICAgICAgICAgICAgICAgICAgICAgICA9IDAuMDAwMTtcbnBlcmNlbnRhZ2VVUzJkZWMucmF3VmFsdWVEaXZpc29yICAgICAgICAgICAgICAgICAgPSBBdXRvTnVtZXJpYy5vcHRpb25zLnJhd1ZhbHVlRGl2aXNvci5wZXJjZW50YWdlO1xuY29uc3QgcGVyY2VudGFnZVVTMmRlY1BvcyAgICAgICAgICAgICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KHBlcmNlbnRhZ2VVUzJkZWMpO1xucGVyY2VudGFnZVVTMmRlY1Bvcy5taW5pbXVtVmFsdWUgICAgICAgICAgICAgICAgICA9IDA7XG5jb25zdCBwZXJjZW50YWdlVVMyZGVjTmVnICAgICAgICAgICAgICAgICAgICAgICAgID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QocGVyY2VudGFnZVVTMmRlYyk7XG5wZXJjZW50YWdlVVMyZGVjTmVnLm1heGltdW1WYWx1ZSAgICAgICAgICAgICAgICAgID0gMDtcbnBlcmNlbnRhZ2VVUzJkZWNOZWcubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnByZWZpeDtcblxuY29uc3QgcGVyY2VudGFnZVVTM2RlYyAgICAgICAgICAgID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QocGVyY2VudGFnZVVTMmRlYyk7XG5wZXJjZW50YWdlVVMzZGVjLmRlY2ltYWxQbGFjZXMgICAgPSAzO1xuY29uc3QgcGVyY2VudGFnZVVTM2RlY1BvcyAgICAgICAgID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QocGVyY2VudGFnZVVTMmRlY1Bvcyk7XG5wZXJjZW50YWdlVVMzZGVjUG9zLmRlY2ltYWxQbGFjZXMgPSAzO1xuY29uc3QgcGVyY2VudGFnZVVTM2RlY05lZyAgICAgICAgID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QocGVyY2VudGFnZVVTMmRlY05lZyk7XG5wZXJjZW50YWdlVVMzZGVjTmVnLmRlY2ltYWxQbGFjZXMgPSAzO1xuXG5jb25zdCB0dXJraXNoID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QoZXVybyk7XG50dXJraXNoLmN1cnJlbmN5U3ltYm9sID0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbC5saXJhO1xuXG4vKipcbiAqIFByZWRlZmluZWQgb3B0aW9ucyBmb3IgdGhlIG1vc3QgY29tbW9uIGxhbmd1YWdlc1xuICovXG5BdXRvTnVtZXJpYy5wcmVkZWZpbmVkT3B0aW9ucyA9IHtcbiAgICBldXJvLFxuICAgIGV1cm9Qb3MsXG4gICAgZXVyb05lZyxcbiAgICBldXJvU3BhY2UsXG4gICAgZXVyb1NwYWNlUG9zLFxuICAgIGV1cm9TcGFjZU5lZyxcbiAgICBwZXJjZW50YWdlRVUyZGVjLFxuICAgIHBlcmNlbnRhZ2VFVTJkZWNQb3MsXG4gICAgcGVyY2VudGFnZUVVMmRlY05lZyxcbiAgICBwZXJjZW50YWdlRVUzZGVjLFxuICAgIHBlcmNlbnRhZ2VFVTNkZWNQb3MsXG4gICAgcGVyY2VudGFnZUVVM2RlY05lZyxcbiAgICBkb2xsYXIsXG4gICAgZG9sbGFyUG9zLFxuICAgIGRvbGxhck5lZyxcbiAgICBkb2xsYXJOZWdCcmFja2V0cyxcbiAgICBwZXJjZW50YWdlVVMyZGVjLFxuICAgIHBlcmNlbnRhZ2VVUzJkZWNQb3MsXG4gICAgcGVyY2VudGFnZVVTMmRlY05lZyxcbiAgICBwZXJjZW50YWdlVVMzZGVjLFxuICAgIHBlcmNlbnRhZ2VVUzNkZWNQb3MsXG4gICAgcGVyY2VudGFnZVVTM2RlY05lZyxcbiAgICBGcmVuY2ggICAgICAgICAgICAgICAgICAgICAgOiBldXJvLCAvLyBGcmFuw6dhaXNcbiAgICBTcGFuaXNoICAgICAgICAgICAgICAgICAgICAgOiBldXJvLCAvLyBFc3Bhw7FvbFxuICAgIE5vcnRoQW1lcmljYW4gICAgICAgICAgICAgICA6IGRvbGxhcixcbiAgICBCcml0aXNoICAgICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgIGRpZ2l0R3JvdXBTZXBhcmF0b3IgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3IuY29tbWEsXG4gICAgICAgIGRlY2ltYWxDaGFyYWN0ZXIgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXIuZG90LFxuICAgICAgICBjdXJyZW5jeVN5bWJvbCAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbC5wb3VuZCxcbiAgICAgICAgY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQucHJlZml4LFxuICAgICAgICBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudDogQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodCxcbiAgICB9LFxuICAgIFN3aXNzICAgICAgICAgICAgICAgICAgICAgICA6IHsgLy8gU3Vpc3NlXG4gICAgICAgIGRpZ2l0R3JvdXBTZXBhcmF0b3IgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3IuYXBvc3Ryb3BoZSxcbiAgICAgICAgZGVjaW1hbENoYXJhY3RlciAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3Rlci5kb3QsXG4gICAgICAgIGN1cnJlbmN5U3ltYm9sICAgICAgICAgICAgICAgOiAnXFx1MjAyZkNIRicsXG4gICAgICAgIGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeCxcbiAgICAgICAgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQ6IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4LFxuICAgIH0sXG4gICAgSmFwYW5lc2UgICAgICAgICAgICAgICAgICAgIDogamFwYW5lc2UsIC8vIOaXpeacrOiqnlxuICAgIENoaW5lc2UgICAgICAgICAgICAgICAgICAgICA6IGphcGFuZXNlLCAvLyDkuK3lm73oqp4gKENoaW5lc2UpXG4gICAgQnJhemlsaWFuICAgICAgICAgICAgICAgICAgIDoge1xuICAgICAgICBkaWdpdEdyb3VwU2VwYXJhdG9yICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmRvdCxcbiAgICAgICAgZGVjaW1hbENoYXJhY3RlciAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3Rlci5jb21tYSxcbiAgICAgICAgY3VycmVuY3lTeW1ib2wgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2wucmVhbCxcbiAgICAgICAgY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQucHJlZml4LFxuICAgICAgICBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudDogQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodCxcbiAgICB9LFxuICAgIFR1cmtpc2ggICAgICAgICAgICAgICAgICAgICA6IHR1cmtpc2gsXG4gICAgZG90RGVjaW1hbENoYXJDb21tYVNlcGFyYXRvcjoge1xuICAgICAgICBkaWdpdEdyb3VwU2VwYXJhdG9yOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3IuY29tbWEsXG4gICAgICAgIGRlY2ltYWxDaGFyYWN0ZXIgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3Rlci5kb3QsXG4gICAgfSxcbiAgICBjb21tYURlY2ltYWxDaGFyRG90U2VwYXJhdG9yOiB7XG4gICAgICAgIGRpZ2l0R3JvdXBTZXBhcmF0b3IgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmRvdCxcbiAgICAgICAgZGVjaW1hbENoYXJhY3RlciAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXIuY29tbWEsXG4gICAgICAgIGRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZTogQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUuZG90LFxuICAgIH0sXG4gICAgaW50ZWdlciAgICAgICAgICAgICAgICAgICAgIDoge1xuICAgICAgICBkZWNpbWFsUGxhY2VzOiAwLFxuICAgIH0sXG4gICAgaW50ZWdlclBvcyAgICAgICAgICAgICAgICAgIDoge1xuICAgICAgICBtaW5pbXVtVmFsdWUgOiBBdXRvTnVtZXJpYy5vcHRpb25zLm1pbmltdW1WYWx1ZS56ZXJvLFxuICAgICAgICBkZWNpbWFsUGxhY2VzOiAwLFxuICAgIH0sXG4gICAgaW50ZWdlck5lZyAgICAgICAgICAgICAgICAgIDoge1xuICAgICAgICBtYXhpbXVtVmFsdWUgOiBBdXRvTnVtZXJpYy5vcHRpb25zLm1heGltdW1WYWx1ZS56ZXJvLFxuICAgICAgICBkZWNpbWFsUGxhY2VzOiAwLFxuICAgIH0sXG4gICAgZmxvYXQgICAgICAgICAgICAgICAgICAgICAgIDoge1xuICAgICAgICBhbGxvd0RlY2ltYWxQYWRkaW5nOiBBdXRvTnVtZXJpYy5vcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmcubmV2ZXIsXG4gICAgfSxcbiAgICBmbG9hdFBvcyAgICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgIGFsbG93RGVjaW1hbFBhZGRpbmc6IEF1dG9OdW1lcmljLm9wdGlvbnMuYWxsb3dEZWNpbWFsUGFkZGluZy5uZXZlcixcbiAgICAgICAgbWluaW11bVZhbHVlICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5taW5pbXVtVmFsdWUuemVybyxcbiAgICAgICAgbWF4aW11bVZhbHVlICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5tYXhpbXVtVmFsdWUudGVuVHJpbGxpb25zLFxuICAgIH0sXG4gICAgZmxvYXROZWcgICAgICAgICAgICAgICAgICAgIDoge1xuICAgICAgICBhbGxvd0RlY2ltYWxQYWRkaW5nOiBBdXRvTnVtZXJpYy5vcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmcubmV2ZXIsXG4gICAgICAgIG1pbmltdW1WYWx1ZSAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMubWluaW11bVZhbHVlLnRlblRyaWxsaW9ucyxcbiAgICAgICAgbWF4aW11bVZhbHVlICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5tYXhpbXVtVmFsdWUuemVybyxcbiAgICB9LFxuICAgIG51bWVyaWMgICAgICAgICAgICAgICAgICAgICA6IHtcbiAgICAgICAgZGlnaXRHcm91cFNlcGFyYXRvcjogQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLm5vU2VwYXJhdG9yLFxuICAgICAgICBkZWNpbWFsQ2hhcmFjdGVyICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXIuZG90LFxuICAgICAgICBjdXJyZW5jeVN5bWJvbCAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sLm5vbmUsXG4gICAgfSxcbiAgICBudW1lcmljUG9zICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgIGRpZ2l0R3JvdXBTZXBhcmF0b3I6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci5ub1NlcGFyYXRvcixcbiAgICAgICAgZGVjaW1hbENoYXJhY3RlciAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyLmRvdCxcbiAgICAgICAgY3VycmVuY3lTeW1ib2wgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbC5ub25lLFxuICAgICAgICBtaW5pbXVtVmFsdWUgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLm1pbmltdW1WYWx1ZS56ZXJvLFxuICAgICAgICBtYXhpbXVtVmFsdWUgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLm1heGltdW1WYWx1ZS50ZW5UcmlsbGlvbnMsXG4gICAgfSxcbiAgICBudW1lcmljTmVnICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgIGRpZ2l0R3JvdXBTZXBhcmF0b3I6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci5ub1NlcGFyYXRvcixcbiAgICAgICAgZGVjaW1hbENoYXJhY3RlciAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyLmRvdCxcbiAgICAgICAgY3VycmVuY3lTeW1ib2wgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbC5ub25lLFxuICAgICAgICBtaW5pbXVtVmFsdWUgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLm1pbmltdW1WYWx1ZS50ZW5UcmlsbGlvbnMsXG4gICAgICAgIG1heGltdW1WYWx1ZSAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMubWF4aW11bVZhbHVlLnplcm8sXG4gICAgfSxcbn07XG5cbk9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKEF1dG9OdW1lcmljLnByZWRlZmluZWRPcHRpb25zKS5mb3JFYWNoKG9wdGlvbk5hbWUgPT4ge1xuICAgIE9iamVjdC5mcmVlemUoQXV0b051bWVyaWMucHJlZGVmaW5lZE9wdGlvbnNbb3B0aW9uTmFtZV0pO1xufSk7XG5PYmplY3QuZnJlZXplKEF1dG9OdW1lcmljLnByZWRlZmluZWRPcHRpb25zKTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShBdXRvTnVtZXJpYywgJ3ByZWRlZmluZWRPcHRpb25zJywgeyBjb25maWd1cmFibGU6IGZhbHNlLCB3cml0YWJsZTogZmFsc2UgfSk7XG4iXSwibWFwcGluZ3MiOiI7O0FBNkJBO0FBQ0E7OztBQUFBO0FBQ0E7Ozs7O0FBL0JBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQWdDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQU5BO0FBQ0E7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFMQTtBQUNBO0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBTEE7QUFDQTtBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUxBO0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBTEE7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBTEE7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUZBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFIQTtBQUtBO0FBQ0E7QUFEQTtBQUdBO0FBQ0E7QUFDQTtBQUZBO0FBSUE7QUFDQTtBQUNBO0FBRkE7QUFJQTtBQUNBO0FBREE7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUhBO0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFIQTtBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBSEE7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFMQTtBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUxBO0FBL0ZBO0FBQ0E7QUF1R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./src/AutoNumericPredefinedOptions.js\n");

/***/ }),

/***/ "./src/main.js":
/*!*********************!*\
  !*** ./src/main.js ***!
  \*********************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

"use strict";
eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\n\nvar _AutoNumeric = __webpack_require__(/*! ./AutoNumeric */ \"./src/AutoNumeric.js\");\n\nvar _AutoNumeric2 = _interopRequireDefault(_AutoNumeric);\n\nvar _AutoNumericEvents = __webpack_require__(/*! ./AutoNumericEvents */ \"./src/AutoNumericEvents.js\");\n\nvar _AutoNumericEvents2 = _interopRequireDefault(_AutoNumericEvents);\n\nvar _AutoNumericOptions = __webpack_require__(/*! ./AutoNumericOptions */ \"./src/AutoNumericOptions.js\");\n\nvar _AutoNumericOptions2 = _interopRequireDefault(_AutoNumericOptions);\n\nvar _AutoNumericDefaultSettings = __webpack_require__(/*! ./AutoNumericDefaultSettings */ \"./src/AutoNumericDefaultSettings.js\");\n\nvar _AutoNumericDefaultSettings2 = _interopRequireDefault(_AutoNumericDefaultSettings);\n\nvar _AutoNumericPredefinedOptions = __webpack_require__(/*! ./AutoNumericPredefinedOptions */ \"./src/AutoNumericPredefinedOptions.js\");\n\nvar _AutoNumericPredefinedOptions2 = _interopRequireDefault(_AutoNumericPredefinedOptions);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/* eslint no-unused-vars: 0 */\n\n/**\n * This file serve as the main entry point to the library.\n *\n * @type {AutoNumeric}\n */\nexports.default = _AutoNumeric2.default; /**\n                                          * Babel + Webpack workaround for autoNumeric\n                                          *\n                                          * @author Alexandre Bonneau <alexandre.bonneau@linuxfr.eu>\n                                          * @copyright © 2017 Alexandre Bonneau\n                                          *\n                                          * The MIT License (http://www.opensource.org/licenses/mit-license.php)\n                                          *\n                                          * Permission is hereby granted, free of charge, to any person\n                                          * obtaining a copy of this software and associated documentation\n                                          * files (the \"Software\"), to deal in the Software without\n                                          * restriction, including without limitation the rights to use,\n                                          * copy, modify, merge, publish, distribute, sub license, and/or sell\n                                          * copies of the Software, and to permit persons to whom the\n                                          * Software is furnished to do so, subject to the following\n                                          * conditions:\n                                          *\n                                          * The above copyright notice and this permission notice shall be\n                                          * included in all copies or substantial portions of the Software.\n                                          *\n                                          * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n                                          * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n                                          * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n                                          * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n                                          * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n                                          * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n                                          * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n                                          * OTHER DEALINGS IN THE SOFTWARE.\n                                          */\n\nmodule.exports = exports['default'];\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvbWFpbi5qcy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovL0F1dG9OdW1lcmljL3NyYy9tYWluLmpzPzJlZTIiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBCYWJlbCArIFdlYnBhY2sgd29ya2Fyb3VuZCBmb3IgYXV0b051bWVyaWNcbiAqXG4gKiBAYXV0aG9yIEFsZXhhbmRyZSBCb25uZWF1IDxhbGV4YW5kcmUuYm9ubmVhdUBsaW51eGZyLmV1PlxuICogQGNvcHlyaWdodCDCqSAyMDE3IEFsZXhhbmRyZSBCb25uZWF1XG4gKlxuICogVGhlIE1JVCBMaWNlbnNlIChodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL21pdC1saWNlbnNlLnBocClcbiAqXG4gKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvblxuICogb2J0YWluaW5nIGEgY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb25cbiAqIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dFxuICogcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsXG4gKiBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWIgbGljZW5zZSwgYW5kL29yIHNlbGxcbiAqIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZVxuICogU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmdcbiAqIGNvbmRpdGlvbnM6XG4gKlxuICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmVcbiAqIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICpcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsXG4gKiBFWFBSRVNTIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVNcbiAqIE9GIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EXG4gKiBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVFxuICogSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksXG4gKiBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkdcbiAqIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1JcbiAqIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cbiAqL1xuXG5pbXBvcnQgQXV0b051bWVyaWMgZnJvbSAnLi9BdXRvTnVtZXJpYyc7XG5pbXBvcnQgQXV0b051bWVyaWNFdmVudHMgZnJvbSAnLi9BdXRvTnVtZXJpY0V2ZW50cyc7XG5pbXBvcnQgQXV0b051bWVyaWNPcHRpb25zIGZyb20gJy4vQXV0b051bWVyaWNPcHRpb25zJztcbmltcG9ydCBBdXRvTnVtZXJpY0RlZmF1bHRTZXR0aW5ncyBmcm9tICcuL0F1dG9OdW1lcmljRGVmYXVsdFNldHRpbmdzJztcbmltcG9ydCBBdXRvTnVtZXJpY1ByZWRlZmluZWRPcHRpb25zIGZyb20gJy4vQXV0b051bWVyaWNQcmVkZWZpbmVkT3B0aW9ucyc7XG5cbi8qIGVzbGludCBuby11bnVzZWQtdmFyczogMCAqL1xuXG4vKipcbiAqIFRoaXMgZmlsZSBzZXJ2ZSBhcyB0aGUgbWFpbiBlbnRyeSBwb2ludCB0byB0aGUgbGlicmFyeS5cbiAqXG4gKiBAdHlwZSB7QXV0b051bWVyaWN9XG4gKi9cbmV4cG9ydCBkZWZhdWx0IEF1dG9OdW1lcmljO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUE4QkE7QUFDQTs7O0FBQUE7QUFDQTs7O0FBQUE7QUFDQTs7O0FBQUE7QUFDQTs7O0FBQUE7QUFDQTs7Ozs7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FBdENBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./src/main.js\n");

/***/ })

/******/ });
});;
(function () {
    var dropdown = $('.dropdown-accordion.dropdown');
    dropdown.closeable = true;
    dropdown.on({
        'show.bs.dropdown': function (event) {
            // Collapse accordion every time dropdown is shown
            var accordion = $(this).find($(this).data('accordion'));
            accordion.find('.panel-collapse.in').collapse('hide');
            $('body').click(); // Needed in order to allow focusing within dropdown on button click
        },
        "hide.bs.dropdown": function(e) {
            if (onHomePage())
                return false;

            var closeable = dropdown.closeable;
            dropdown.closeable = true;
            return closeable;
        }
    });
    $('#product-menu-button').on('click', function (event) {
        var parent = $(this).parent();
        if (parent.hasClass("open"))
            dropdown.closeable = true;
    });

    $('#createCustomLabel').click((e) => {
        $.get('/api/cart?calaculateCart=false').then((data) => {
            if (!data.isAnonymous) {
                return data;
            };
            toastr.info("Please sign into your account if you would like to create a custom label.");
            setTimeout(() => window.location.href = '/account/login', 3000);
        }).then((data) => {
            if (data) {
                if (data.userCartKey !== "" && data.userCartKey !== null) {
                    $.ajax({
                        url: `/api/customorder/updatemodify?userCartKey=${data.userCartKey}`,
                        type: "PUT",
                        contentType: 'application/json'
                    })
                    .then(() => {
                        window.location.href = `https://nashvillewrapsstage.clickprint.com?UserCartKey=${data.userCartKey}`;
                    });
                } else {
                    $.post('/api/customorder/createusercartkey').then((data) => {
                        // TODO: REFACTOR URL
                        window.location.href = `https://nashvillewrapsstage.clickprint.com?UserCartKey=${data}`;
                    }).catch(e => console.log("error: ", e));
                }
            };
        }).catch(e => console.log("error: ", e));
    });

    $('.dropdown-menu').click(function (e) {
        if (!$(this).closest('ul').hasClass('menu')) {
            dropdown.closeable = false;
        }
    });

    $('.dropdown-accordion li a').click(function (e) {
            dropdown.closeable = true;
    });

    function toggleCaret(e) {
        $(e.target)
            .prev('.panel-heading')
            .find('span.caret')
            .toggleClass('open-caret');
    }

    function onHomePage() {
        var pathname = window.location.pathname;
        return !pathname || pathname === '/';
    }

    $('#accordion').on('hidden.bs.collapse', toggleCaret);
    $('#accordion').on('show.bs.collapse', toggleCaret);

    $('#product-detail-accordion-mobile').on('hidden.bs.collapse', toggleCaret);
    $('#product-detail-accordion-mobile').on('show.bs.collapse', toggleCaret);
    
})();;
(function () {
    var defaultActivate = function() {
    };
    
    ko.bindDataIsland = function (vm, target, data) {
        var instance = new vm();
        var result = (instance.activate || defaultActivate).call(instance,data);
        $.when(result)
            .then(function() {
                ko.applyBindings(instance, document.getElementById(target));
            });
    };
})();;
(function () {
    // The object value only gets updated if it is
    // a writeable observable that is not an instance.
    function updateProperty(prop, value) {
        if (ko.isWriteableObservable(prop)) {
            if (_.isArray(ko.utils.unwrapObservable(prop)) && _.isArray(value)) {
                mapArray(prop, value);
            }
            else {
                if (prop.ctor) {
                    var created = ko.object.create(prop.ctor, value);
                    prop(created);
                }
                else {
                    prop(value);
                }
            }
        }
        else if (isInstance(prop)) {
            ko.object.map(prop, value);
        }
    }
    function mapInstance(destination, source) {
        var unwrapped = ko.utils.unwrapObservable(destination);
        _.each(source, function (v, k) {
            var prop = unwrapped[k];
            //TODO: NEED TO handle undefined,0,false, etc.
            if (prop) {
                updateProperty(prop, v);
            }
        });
    }
    function isInstance(obj) {
        if (_.isObject(obj) && !_.isFunction(obj)) {
            return true;
        }
        return false;
    }
    function mapArray(mapped, obj) {
        var unwrapped = ko.utils.unwrapObservable(mapped);
        var items = _.map(obj, function (value) {
            if (mapped.ctor) {
                return ko.object.create(mapped.ctor, value);
            }
            else {
                return value;
            }
        });
        var args = [0, unwrapped.length].concat(items);
        mapped.splice.apply(mapped, args);
        if (mapped.valueHasMutated)
            mapped.valueHasMutated();
    }
    ko.extenders.ctor = function (target, ctor) {
        target.ctor = ctor;
        return target;
    };
    ko.isObservableInstance = function (instance) {
        if (ko.isObservable(instance) && isInstance(instance())) {
            return true;
        }
        return false;
    };
    ko.object = {
        create: function (ctor, obj) {
            // Only allow functions, not including observables.
            if (ko.isObservable(ctor) || !_.isFunction(ctor)) {
                return null;
            }
            var created = new ctor();
            ko.object.map(created, obj);
            if (created.init)
                created.init();
            return created;
        },
        map: function (mapped, obj) {
            // The mapped object should be an instance.
            if (!isInstance(mapped) && !ko.isObservableInstance(mapped))
                return;
            // The object to map should be an instance.
            if (!isInstance(obj))
                return;
            // Check if the mapped object and object to map are arrays.
            if (_.isArray(ko.utils.unwrapObservable(mapped)) && _.isArray(obj)) {
                mapArray(mapped, obj);
            }
            else {
                mapInstance(mapped, obj);
            }
        }
    };
})();;
// Credit: http://stackoverflow.com/questions/27369871/knockoutjs-intercept-to-one-decimal-place/27372190
(function () {
    ko.bindingHandlers.decimalInput = {
        init: function (el, valueAccessor, bindingsAccessor, viewModel) {
            var $el = $(el),
              bindings = bindingsAccessor(),
              settings = bindings.settings,
              value = valueAccessor();
         
            var autoNumeric = new AutoNumeric(el, settings)
                .set(parseFloat(ko.utils.unwrapObservable(value())));
            $el.change(function () {
                value(parseFloat(autoNumeric.getNumericString()));
            });
        },
        update: function (el, valueAccessor, bindingsAccessor, viewModel) {
            var autoNumeric = AutoNumeric.getAutoNumericElement(el),
              newValue = ko.utils.unwrapObservable(valueAccessor()),
                elementValue = autoNumeric.getNumericString(),
              valueHasChanged = (newValue != elementValue);

            if ((newValue === 0) && (elementValue !== 0) && (elementValue !== "0")) {
                valueHasChanged = true;
            }
            
            if (valueHasChanged) {
                autoNumeric.set(newValue);
            }
        }
    }
})();

;
(function () {
	'use strict';

	ko.bindingHandlers.disableClick = {
		init: function (element, valueAccessor) {

			$(element).click(function (evt) {
				if (valueAccessor()) {
					evt.preventDefault();
					evt.stopImmediatePropagation();
				}
			});

			var events = $._data(element, "events");
			var handlers = events['click'];

			if (handlers.length == 1) {
				return;
			}

			handlers.splice(0, 0, handlers.pop());
		},

		update: function (element, valueAccessor) {
			var value = ko.utils.unwrapObservable(valueAccessor());
			ko.bindingHandlers.css.update(element, function () {
				return {
					'btn-disabled': value
				};
			});
		}
	};
})();;
(function () {
    'use strict';

    ko.bindingHandlers.googleAddressAutocomplete = {
        init: function (element, valueAccessor, allBindingsAccessor) {
            var value = valueAccessor(), allBindings = allBindingsAccessor();

            var options = { types: ['geocode'] };
            ko.utils.extend(options, allBindings.autocompleteOptions)

            var autocomplete = new google.maps.places.Autocomplete(element, options);
            autocomplete.setComponentRestrictions({ 'country': ['us', 'ca', 'pr', 'vi'] });

            google.maps.event.addListener(autocomplete, 'place_changed', function () {
                var result = autocomplete.getPlace();

                if (result.address_components) {
                    var components = _.groupBy(result.address_components, function (c) { return c.types[0]; });

                    setAddress(components, allBindings['address']);
                    setCity(components, allBindings['city']);
                    setCountry(components, allBindings['country']);
                    setState(components, allBindings['state']);
                    setZip(components, allBindings['zip']);
                }
                else if (result.name) { // Google does not have address components for this address yet. Try to parse by name since the suggestion existed. Example: 1385 Hunter Road, Franklin, TN, USA
                    var addressComponents = result.name.split(', ');
                    allBindings['address'](addressComponents[0]);

                    if (addressComponents.length == 4) { // Only fill out city, country, and state for known 4 part name.
                        allBindings['city'](addressComponents[1]);
                        allBindings['country'](addressComponents[3]); //Set country before state
                        allBindings['state'](addressComponents[2]);
                    }
                }

                function setAddress(components, observable) {
                    if (components.street_number && components.route)
                        observable(components.street_number[0].short_name + ' ' + components.route[0].short_name);
                    else
                        observable(result.name);

                    observable.valueHasMutated(); // Handles case where same address selected twice in a row
                }

                function setCity(components, observable) {
                    if (components.locality)
                        observable(components.locality[0].short_name);
                    else
                        observable(undefined);
                }

                function setCountry(components, observable) {
                    if (components.country)
                        observable(components.country[0].short_name == 'CA' ? 'CANADA' : 'USA');
                    else
                        observable('USA');
                }

                function setState(components, observable) {
                    if (components.country && (components.country[0].short_name == 'PR' || components.country[0].short_name == 'VI')) {
                        observable(components.country[0].short_name);
                    }
                    else {
                        if (components.administrative_area_level_1)
                            observable(components.administrative_area_level_1[0].short_name);
                        else
                            observable(undefined);
                    }
                }

                function setZip(components, observable) {
                    if (components.postal_code) {
                        var postalCode = components.postal_code[0].short_name;
                        if (components.postal_code_suffix)
                            postalCode += '-' + components.postal_code_suffix[0].short_name;
                        observable(postalCode);
                    }
                    else
                        observable(undefined);
                }
            });
        },
        update: function (element, valueAccessor, allBindingsAccessor) {
            ko.bindingHandlers.value.update(element, valueAccessor);
        }
    };
})();;
(function () {
	ko.bindingHandlers.hasSelectedFocus = {
	    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
	        ko.bindingHandlers['hasfocus'].init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
	    },
	    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
	        var focusBefore = $(element).is(':focus');
	        ko.bindingHandlers['hasfocus'].update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);

	        var selected = ko.utils.unwrapObservable(valueAccessor());
	        if (selected && !focusBefore) {
	            setTimeout(function () {
	                element.select();
	                //element.setSelectionRange(0, 9999); This is not valid for number inputs. Need to replace number inputs.
	            }, 10);
	        }
	    }
	};
})();;
(function(){
    ko.bindingHandlers.href = {
        init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        },
        update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
            var path = valueAccessor();
            var replaced = path.replace(/:([A-Za-z_]+)/g, function(m, token) {
                 return ko.unwrap(viewModel[token]);
            });
            replaced=replaced.replace(/\$([A-Za-z_]+)/g, function (m, token) {
                return ko.unwrap(bindingContext.$parent[token]);
            });
            replaced = replaced.replace(/\^([A-Za-z_]+)/g, function (m, token) {
                return ko.unwrap(bindingContext.$root[token]);
            });
            element.href = replaced;
        }
    };
})();;
(function () {
    var getIEVersion = function () {
        var myNav = navigator.userAgent.toLowerCase();
        return (myNav.indexOf('msie') != -1) ? parseInt(myNav.split('msie')[1]) : false;
    };

    ko.bindingHandlers.imageGrid = {
        init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
            var el = $(element);
            var container = el.children('.images-container');
            var expander = el.children('.images-expander');

            var toggleContainer = function() {
                container.collapse('toggle');
                //ie 9 toggle does not work correctly so we have to manually do it
                if (getIEVersion() === 9) {
                    if (expander.text() == "Less") {
                        container.height(0);
                    } else {
                        container.height('auto');
                        container.addClass('in');
                    }
                }
                expander.text(function(i, text) {
                    return text === "More" ? "Less" : "More";
                });
            };
            expander.on('click', function() {
                toggleContainer();
            });

            var collapseContainerIfOpen = function() {
                if (container.hasClass('in')) {
                    toggleContainer();
                }
            };

            el.on('click', '.swatch-button img', function (e) {
                //this fixes a weird bug where image is not clickable on IE 11
                var input = $(e.target).siblings("input");
                var name = input.attr('name');
                var value = input.val();
                ko.contextFor(e.target).$data.selectedAttributes[name](value);
                collapseContainerIfOpen();
                e.stopPropagation();
            });

            el.on('click', '.swatch-button input', function (e) {
                collapseContainerIfOpen();
            });
        },
        update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
            var value = ko.unwrap(valueAccessor());
            var container = $(element).children('.images-container');
            var img = container.find('img[title=\'' + value + '\']');
            //if the item isn't in the first row shift it to the first spot
            if (img.length && img.position().top > 50) {
                img.parent()
                    .tooltip('hide')
                    .prependTo(container);
            }
            
        }
    };
})();;
(function(){
    ko.bindingHandlers.magnificPopup = {
        update: function (element, valueAccessor) {
            var imagePath = ko.utils.unwrapObservable(valueAccessor());

            $(element).magnificPopup({
                items: {
                    src: imagePath
                },
                type: 'image' // this is default type
            });
        }
    };
})();;
(function(){
    ko.bindingHandlers.select = {
        update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
            var selected = ko.utils.unwrapObservable(valueAccessor());
            if (selected) {
                if (navigator.vendor && navigator.vendor.startsWith && navigator.vendor.startsWith("Apple"))
                    element.setSelectionRange(0, 9999);
                else
                    element.select();
            }
        }
    };
})();;
(function () {
    ko.bindingHandlers.textDate = {
        update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
            var value = ko.unwrap(valueAccessor());
            if (value === null || typeof value === 'undefined')
                return;
            var format = allBindings.get('dateFormat') || 'MMMM Do YY, h:mm:ss a';
            var convertToLocalTime = allBindings.get('convertToLocalTime') || false;
            var time = moment.utc(value);
            if (convertToLocalTime)
                time = time.local();
            element.innerHTML = time.format(format);
        }
    };
})();;
(function () {

    ko.bindingHandlers.textMoney = {
        update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
            var value = ko.unwrap(valueAccessor());
            if (value === null || typeof value === 'undefined')
                return;
            element.innerHTML = accounting.formatMoney(value);

        }
    };

    ko.extenders.money = function (target) {

        target.formatted = ko.computed({
            read: function() {
                return accounting.formatMoney(target());
            },
            write: function(value) {
                var current = target(),
                    valueToWrite = accounting.unformat(value);

                    target(valueToWrite);
            },
            owner: target
        });

        return target;
    };


})();;
(function () {

    ko.bindingHandlers.textMoneyTo3 = {
        update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
            var value = ko.unwrap(valueAccessor());
            if (value === null || typeof value === 'undefined')
                return;
            element.innerHTML = value < 0.01 ?
                accounting.formatMoney(value, { precision: 3 }) :
                accounting.formatMoney(value, { precision: 2 });

        }
    };

    ko.extenders.moneyTo3 = function (target) {

        target.formatted = ko.computed({
            read: function () {
                return value < 0.01 ?
                    accounting.formatMoney(target(), { precision: 3 }) :
                    accounting.formatMoney(target(), { precision: 2 });
            },
            write: function (value) {
                var current = target(),
                    valueToWrite = accounting.unformat(value);

                target(valueToWrite);
            },
            owner: target
        });

        return target;
    };


})();;
(function () {
	'use strict';

    ko.bindingHandlers.toggleSwitch = {
        init: toggleSwitch
    }

    function toggleSwitch(element, valueAccessor, allBindingsAccessor) {
        var input = $(element);
        var observable = allBindingsAccessor().checked;
        input.bootstrapToggle(options(valueAccessor()));

        bindToggleToObservable(input, observable);
        bindObservableToToggle(input, observable);
        respondToKeyboard(input);
    }

    function respondToKeyboard(input) {
        input
            .parent("div.toggle")
            .attr("tabindex", 0)
            .keydown(clickOnSpace);
    }

    function bindToggleToObservable(input, observable) {
        input._isBeingChangedByUser = false;
        input.change(function () {
            input._isBeingChangedByUser = true;
            observable($(this).prop('checked'));
            input._isBeingChangedByUser = false;
        });
        addDisposeCallback(input, subscribe(input, observable));
    }

    function subscribe(input, observable) {
        return observable.subscribe(function (value) {
            if (!input._isBeingChangedByUser)
                input.bootstrapToggle(!!value ? "on" : "off");
        });

    }

    function addDisposeCallback(input, subscription) {
        ko.utils.domNodeDisposal.addDisposeCallback(input[0], function () {
            subscription.dispose()
            input.bootstrapToggle("destroy");
        });
    }

    function bindObservableToToggle(input, observable) {
        input.bootstrapToggle(!!observable() ? "on" : "off");
    }

    function clickOnSpace(event) {
        if (event.keyCode === 32) {
            event.stopPropagation();
            event.preventDefault();
            return $(this).trigger('click');
        }
    }

    function options(defaults) {
        return $.extend({
            onstyle: 'info',
            offstyle: 'default',
            size: 'small',
            on: 'On',
            off: 'Off'
        }, defaults);
    }
})();;
(function () {
    'use strict';

    ko.bindingHandlers.truncate = {
        init: truncateBinding,
        update: truncateBinding
    };

    function truncateBinding(element, valueAccessor, allBindingsAccessor) {
        var length = valueAccessor();
        var content = getContent(allBindingsAccessor())

        if (length && content) {
            var truncated = truncate(content, length, '...');
            var truncatedAndDecoded = $('<div />').html(truncated).text();
            $(element).html(truncatedAndDecoded);
        }
    }

    function getContent(bindings) {
        var text = ko.utils.unwrapObservable(bindings.text);
        var html = ko.utils.unwrapObservable(bindings.html);
        return html || text;
    }

    function truncate(content, length, suffixIfTruncated) {
        if (!(content && length))
            return content;

        var text = stripHtml(content);
        var append = (text.length > length ? (suffixIfTruncated || '') : '');
        return text.substring(0, length) + append;
    }

    function stripHtml(content) {
        var html = '<span>{0}</span>'.replace('{0}', content);
        return $(html).text();
    }
})();;
ko.bindingHandlers.popover = {
    init: function (element, valueAccessor) {
        var local = ko.utils.unwrapObservable(valueAccessor()),
            options = { animation: true, trigger: 'focus', container: 'body', html: true };

        ko.utils.extend(options, ko.bindingHandlers.popover.options);
        ko.utils.extend(options, local);

        $(element).attr('tabindex', '0').popover(options);

        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).popover("destroy");
        });
    },
    options: {
        placement: "bottom",
		container: "body"
    }
};

ko.bindingHandlers.tooltip = {
    init: function (element, valueAccessor) {
        var local = ko.utils.unwrapObservable(valueAccessor()),
            options = {};

        ko.utils.extend(options, ko.bindingHandlers.tooltip.options);
        ko.utils.extend(options, local);

        $(element).tooltip(options);

        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).tooltip("destroy");
        });
    },
    options: {
        container: "body"
    }
};;
(function() {
	ko.subscribable.fn.trackChanges = function () {
		var target = this;
		var original = ko.observable(target());
	    
		this.cleanValue = ko.computed(function () {
		    return original();
		});

		var updating = ko.observable(false);
		this.isUpdating = ko.computed(function () {
			return updating();
		});

		this.update = function (promise) {
			var self = this;

			updating(true);

			// Make the update appear to run for a minimum amount of time.
			// Otherwise, UI elements triggered on isUpdating could just briefly flash making things look broken.
			var timeout = $.Deferred();
			setTimeout(function () {
				timeout.resolve();
			}, 500);

			$.when(promise, timeout.promise())
				.then(function () {
            		self.reset();
            		updating(false);
				}).fail(function () {
            		updating(false);
				});
		};


		this.isDirty = ko.computed(function () {
			return target() != original() && !updating();
		});

		this.reset = function () {
			original(target());
		};

	    this.undo = function() {
	        target(original());
	    };

		return this;
	};
})();;
(function () {
    ko.lazyComputed=function(fn,context) {
        return ko.computed(fn, context, { deferEvaluation: true });
    };
})();;
(function () {
    ko.isObservableMoment = function (observable) {
        if (ko.isObservable(observable) && observable.moment) {
            return true;
        }
        return false;
    };

    ko.observableMoment = function (initialValue) {
        var observable = ko.observable(initialValue);

        ko.utils.extend(observable, {
            moment: ko.computed(function () {
                if (!observable()) {
                    return undefined;
                }
                return moment.utc(observable());
            }),

            add: function (input, val) {
                observable(observable.moment().add(input, val).toDate());
                return observable;
            },

            subtract: function (input, val) {
                observable(observable.moment().subtract(input, val).toDate());
                return observable;
            },

            format: function (inputString) {
                return ko.computed(function () {
                    if (!observable()) {
                        return undefined;
                    }
                    return observable.moment().local().format(inputString);
                });
            },

            calendar: function () {
                return observable.moment().calendar();
            }
        });

        observable.longFormat = observable.format('MMMM Do YY, h:mm:ss a');
        observable.monthDayYear = observable.format('LL');

        return observable;
    };
})();;
(function() {
ko.extenders.paging = function (target, options) {
    options = options || {};
    options.isLoadingDataEnabled = options.isLoadingDataEnabled || false;

    var _pageSize = ko.observable(options.pageSize || 10),
        _currentPage = ko.observable(1),
        loadDataCallback = options.loadDataCallback,
        criteriaForceUpdate = ko.observable();

    target.pageSize = ko.computed({
        read: _pageSize,
        write: function (newValue) {
            if (newValue > 0) {
                _pageSize(newValue);
            }
            else {
                _pageSize(10);
            }
        }
    });

    target.currentPage = ko.computed({
        read: _currentPage,
        write: function (newValue) {
            if (newValue > target.pageCount()) {
                _currentPage(target.pageCount());
            }
            else if (newValue <= 0) {
                _currentPage(1);
            }
            else {
                _currentPage(newValue);
            }
        }
    });

    target.enteredPage = ko.observable();

    target.clearPaging = function() {
        target.isLoadingDataEnabled(false);
        target.totalCount(undefined);
        target.currentPage(1);
        target.sortFieldName(options.defaultSortFieldName);
        target.sortOrder(options.defaultSortOrder || "desc");
    };
    
    target.refreshData = function () {
        if (!target.isLoadingDataEnabled()) {
            target.isLoadingDataEnabled(true);
        }
        return getData();
    };

    target.isLoadingDataEnabled = ko.observable(options.isLoadingDataEnabled);

    target.totalCount = ko.observable();

    target.sortFieldName = ko.observable(options.defaultSortFieldName);
    target.sortOrder = ko.observable(options.defaultSortOrder || "desc");

    target.toggleSort = function(sortFieldName) {
        var columnBefore = target.sortFieldName(),
            wasDescending = target.sortOrder() === "desc";
        if (columnBefore === sortFieldName) {
            target.sortOrder(wasDescending ? "asc" : "desc");
        } else {
            target.sortOrder("asc");
        }
        target.sortFieldName(sortFieldName);
    };
    
    target.isSorted = function(sortFieldName, sortOrder) {
        return sortFieldName === target.sortFieldName() &&  sortOrder === target.sortOrder();
    };

    target.criteriaChanged = ko.computed(function() {
        target.currentPage(), target.pageSize(), target.sortFieldName(), target.sortOrder();

    }).extend({ async: 200, notify: 'always' }); //throttle so we dont request twice when sort name and order are set

    var getData = function() {
        if (target.isLoadingDataEnabled()) {
            //callback must match this signature and return type
            return loadDataCallback(target.currentPage(), target.pageSize(), target.sortFieldName(), target.sortOrder())
            .then(function (result) {
                target.totalCount(result.totalCount);
                if (target.ctor) {
                    ko.object.map(target, result.items);
                } else {
                    target(result.items);
                }
            });
        }
    };
    //subscribe so that observables inside the callback dont make the criteria changed computed fire
    target.criteriaChanged.subscribe(function() {
        getData();
    });

    target.pageCount = ko.computed(function () {
        return Math.ceil(target.totalCount() / target.pageSize()) || 1;
    });

    target.pages = ko.computed(function () {
        var pages = target.pageCount(),
            page = target.currentPage(),
            firstVisible = page <= 5 ? 1 : Math.min(page - 4, pages - 9),
            lastVisible = page > pages - 5 ? pages : Math.max(page + 5, 10);

        var pagesToShow = _.filter(_.range(1, pages + 1), function (i) { return i >= firstVisible && i <= lastVisible; });

        return _.map(pagesToShow, function (i) {
            return {
                page: i, action: function () {
                    target.currentPage(i);
                    handlePageChange();
                }, isCurrent: page === i
            };
        });
    });

    target.canMoveNext = ko.computed(function () {
        return target.currentPage() < target.pages().length;
    });
    target.canMovePrevious = ko.computed(function () {
        return target.currentPage() > 1;
    });
    target.moveFirst = function () {
        target.currentPage(1);
        handlePageChange();
    };
    target.movePrevious = function () {
        if (!target.canMovePrevious()) {
            target.moveLast();
        } else {
            target.currentPage(target.currentPage() - 1);
        }
        handlePageChange();
    };
    target.moveNext = function () {
        if (!target.canMoveNext()) {
            target.moveFirst();
        } else {
            target.currentPage(target.currentPage() + 1);
        }
        handlePageChange();
    };
    target.moveLast = function () {
        target.currentPage(target.pageCount());
        handlePageChange();
    };
    target.moveToEnteredPage = function () {
        if (!isNaN(target.enteredPage())) {
            target.currentPage(Number(target.enteredPage()));
        }
        handlePageChange();
    };

    function handlePageChange() {
        if (options.pageClickHandler)
            options.pageClickHandler();
    }

    return target;
};
})();
;
!function(e){e(["jquery"],function(e){return function(){function t(e,t,n){return f({type:O.error,iconClass:g().iconClasses.error,message:e,optionsOverride:n,title:t})}function n(t,n){return t||(t=g()),v=e("#"+t.containerId),v.length?v:(n&&(v=c(t)),v)}function i(e,t,n){return f({type:O.info,iconClass:g().iconClasses.info,message:e,optionsOverride:n,title:t})}function o(e){w=e}function s(e,t,n){return f({type:O.success,iconClass:g().iconClasses.success,message:e,optionsOverride:n,title:t})}function a(e,t,n){return f({type:O.warning,iconClass:g().iconClasses.warning,message:e,optionsOverride:n,title:t})}function r(e){var t=g();v||n(t),l(e,t)||u(t)}function d(t){var i=g();return v||n(i),t&&0===e(":focus",t).length?void h(t):void(v.children().length&&v.remove())}function u(t){for(var n=v.children(),i=n.length-1;i>=0;i--)l(e(n[i]),t)}function l(t,n){return t&&0===e(":focus",t).length?(t[n.hideMethod]({duration:n.hideDuration,easing:n.hideEasing,complete:function(){h(t)}}),!0):!1}function c(t){return v=e("<div/>").attr("id",t.containerId).addClass(t.positionClass).attr("aria-live","polite").attr("role","alert"),v.appendTo(e(t.target)),v}function p(){return{tapToDismiss:!0,toastClass:"toast",containerId:"toast-container",debug:!1,showMethod:"fadeIn",showDuration:300,showEasing:"swing",onShown:void 0,hideMethod:"fadeOut",hideDuration:1e3,hideEasing:"swing",onHidden:void 0,extendedTimeOut:1e3,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},iconClass:"toast-info",positionClass:"toast-top-right",timeOut:5e3,titleClass:"toast-title",messageClass:"toast-message",target:"body",closeHtml:'<button type="button">&times;</button>',newestOnTop:!0,preventDuplicates:!1,progressBar:!1}}function m(e){w&&w(e)}function f(t){function i(t){return!e(":focus",l).length||t?(clearTimeout(O.intervalId),l[r.hideMethod]({duration:r.hideDuration,easing:r.hideEasing,complete:function(){h(l),r.onHidden&&"hidden"!==b.state&&r.onHidden(),b.state="hidden",b.endTime=new Date,m(b)}})):void 0}function o(){(r.timeOut>0||r.extendedTimeOut>0)&&(u=setTimeout(i,r.extendedTimeOut),O.maxHideTime=parseFloat(r.extendedTimeOut),O.hideEta=(new Date).getTime()+O.maxHideTime)}function s(){clearTimeout(u),O.hideEta=0,l.stop(!0,!0)[r.showMethod]({duration:r.showDuration,easing:r.showEasing})}function a(){var e=(O.hideEta-(new Date).getTime())/O.maxHideTime*100;f.width(e+"%")}var r=g(),d=t.iconClass||r.iconClass;if("undefined"!=typeof t.optionsOverride&&(r=e.extend(r,t.optionsOverride),d=t.optionsOverride.iconClass||d),r.preventDuplicates){if(t.message===C)return;C=t.message}T++,v=n(r,!0);var u=null,l=e("<div/>"),c=e("<div/>"),p=e("<div/>"),f=e("<div/>"),w=e(r.closeHtml),O={intervalId:null,hideEta:null,maxHideTime:null},b={toastId:T,state:"visible",startTime:new Date,options:r,map:t};return t.iconClass&&l.addClass(r.toastClass).addClass(d),t.title&&(c.append(t.title).addClass(r.titleClass),l.append(c)),t.message&&(p.append(t.message).addClass(r.messageClass),l.append(p)),r.closeButton&&(w.addClass("toast-close-button").attr("role","button"),l.prepend(w)),r.progressBar&&(f.addClass("toast-progress"),l.prepend(f)),l.hide(),r.newestOnTop?v.prepend(l):v.append(l),l[r.showMethod]({duration:r.showDuration,easing:r.showEasing,complete:r.onShown}),r.timeOut>0&&(u=setTimeout(i,r.timeOut),O.maxHideTime=parseFloat(r.timeOut),O.hideEta=(new Date).getTime()+O.maxHideTime,r.progressBar&&(O.intervalId=setInterval(a,10))),l.hover(s,o),!r.onclick&&r.tapToDismiss&&l.click(i),r.closeButton&&w&&w.click(function(e){e.stopPropagation?e.stopPropagation():void 0!==e.cancelBubble&&e.cancelBubble!==!0&&(e.cancelBubble=!0),i(!0)}),r.onclick&&l.click(function(){r.onclick(),i()}),m(b),r.debug&&console&&console.log(b),l}function g(){return e.extend({},p(),b.options)}function h(e){v||(v=n()),e.is(":visible")||(e.remove(),e=null,0===v.children().length&&(v.remove(),C=void 0))}var v,w,C,T=0,O={error:"error",info:"info",success:"success",warning:"warning"},b={clear:r,remove:d,error:t,getContainer:n,info:i,options:{},subscribe:o,success:s,version:"2.1.0",warning:a};return b}()})}("function"==typeof define&&define.amd?define:function(e,t){"undefined"!=typeof module&&module.exports?module.exports=t(require("jquery")):window.toastr=t(window.jQuery)});
//# sourceMappingURL=toastr.js.map
;
