<?php

use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Extension\CoreExtension;
use Twig\Extension\SandboxExtension;
use Twig\Markup;
use Twig\Sandbox\SecurityError;
use Twig\Sandbox\SecurityNotAllowedTagError;
use Twig\Sandbox\SecurityNotAllowedFilterError;
use Twig\Sandbox\SecurityNotAllowedFunctionError;
use Twig\Source;
use Twig\Template;

/* @public_path/build/vendors-node_modules_bootstrap-table_dist_bootstrap-table-locale-all_min_js-node_modules_boot-3f0fd0.js */
class __TwigTemplate_5be2f9a9b9387e5459819a43c2938bfa5491c3526f012187a96948394d7e3580 extends Template
{
    private $source;
    private $macros = [];

    public function __construct(Environment $env)
    {
        parent::__construct($env);

        $this->source = $this->getSourceContext();

        $this->parent = false;

        $this->blocks = [
        ];
    }

    protected function doDisplay(array $context, array $blocks = [])
    {
        $macros = $this->macros;
        $__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
        $__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e->enter($__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template", "@public_path/build/vendors-node_modules_bootstrap-table_dist_bootstrap-table-locale-all_min_js-node_modules_boot-3f0fd0.js"));

        $__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02 = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
        $__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02->enter($__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template", "@public_path/build/vendors-node_modules_bootstrap-table_dist_bootstrap-table-locale-all_min_js-node_modules_boot-3f0fd0.js"));

        yield "(self[\"webpackChunk\"] = self[\"webpackChunk\"] || []).push([[\"vendors-node_modules_bootstrap-table_dist_bootstrap-table-locale-all_min_js-node_modules_boot-3f0fd0\"],{

/***/ \"./node_modules/bootstrap-table/dist/bootstrap-table-locale-all.min.js\":
/*!*****************************************************************************!*\\
  !*** ./node_modules/bootstrap-table/dist/bootstrap-table-locale-all.min.js ***!
  \\*****************************************************************************/
/***/ (function(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) {

/**
  * bootstrap-table - An extended table to integration with some of the most widely used CSS frameworks. (Supports Bootstrap, Semantic UI, Bulma, Material Design, Foundation)
  *
  * @version v1.18.3
  * @homepage https://bootstrap-table.com
  * @author wenzhixin <wenzhixin2010@gmail.com> (http://wenzhixin.net.cn/)
  * @license MIT
  */

!function(t,n){ true?n(__webpack_require__(/*! jquery */ \"./node_modules/jquery/dist/jquery.js\")):0}(this,(function(t){\"use strict\";function n(t){return t&&\"object\"==typeof t&&\"default\"in t?t:{default:t}}var o=n(t),r=\"undefined\"!=typeof globalThis?globalThis:\"undefined\"!=typeof window?window:\"undefined\"!=typeof __webpack_require__.g?__webpack_require__.g:\"undefined\"!=typeof self?self:{};function e(t,n){return t(n={exports:{}},n.exports),n.exports}var a=function(t){return t&&t.Math==Math&&t},i=a(\"object\"==typeof globalThis&&globalThis)||a(\"object\"==typeof window&&window)||a(\"object\"==typeof self&&self)||a(\"object\"==typeof r&&r)||function(){return this}()||Function(\"return this\")(),u=function(t){try{return!!t()}catch(t){return!0}},f=!u((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]})),c={}.propertyIsEnumerable,l=Object.getOwnPropertyDescriptor,s={f:l&&!c.call({1:2},1)?function(t){var n=l(this,t);return!!n&&n.enumerable}:c},m=function(t,n){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:n}},g={}.toString,d=function(t){return g.call(t).slice(8,-1)},h=\"\".split,p=u((function(){return!Object(\"z\").propertyIsEnumerable(0)}))?function(t){return\"String\"==d(t)?h.call(t,\"\"):Object(t)}:Object,w=function(t){if(null==t)throw TypeError(\"Can't call method on \"+t);return t},S=function(t){return p(w(t))},P=function(t){return\"object\"==typeof t?null!==t:\"function\"==typeof t},T=function(t,n){if(!P(t))return t;var o,r;if(n&&\"function\"==typeof(o=t.toString)&&!P(r=o.call(t)))return r;if(\"function\"==typeof(o=t.valueOf)&&!P(r=o.call(t)))return r;if(!n&&\"function\"==typeof(o=t.toString)&&!P(r=o.call(t)))return r;throw TypeError(\"Can't convert object to primitive value\")},R={}.hasOwnProperty,C=function(t,n){return R.call(t,n)},b=i.document,v=P(b)&&P(b.createElement),A=!f&&!u((function(){return 7!=Object.defineProperty((t=\"div\",v?b.createElement(t):{}),\"a\",{get:function(){return 7}}).a;var t})),x=Object.getOwnPropertyDescriptor,F={f:f?x:function(t,n){if(t=S(t),n=T(n,!0),A)try{return x(t,n)}catch(t){}if(C(t,n))return m(!s.f.call(t,n),t[n])}},y=function(t){if(!P(t))throw TypeError(String(t)+\" is not an object\");return t},k=Object.defineProperty,H={f:f?k:function(t,n,o){if(y(t),n=T(n,!0),y(o),A)try{return k(t,n,o)}catch(t){}if(\"get\"in o||\"set\"in o)throw TypeError(\"Accessors not supported\");return\"value\"in o&&(t[n]=o.value),t}},O=f?function(t,n,o){return H.f(t,n,m(1,o))}:function(t,n,o){return t[n]=o,t},M=function(t,n){try{O(i,t,n)}catch(o){i[t]=n}return n},E=\"__core-js_shared__\",N=i[E]||M(E,{}),D=Function.toString;\"function\"!=typeof N.inspectSource&&(N.inspectSource=function(t){return D.call(t)});var z,L,j,B,U=N.inspectSource,J=i.WeakMap,G=\"function\"==typeof J&&/native code/.test(U(J)),V=e((function(t){(t.exports=function(t,n){return N[t]||(N[t]=void 0!==n?n:{})})(\"versions\",[]).push({version:\"3.9.1\",mode:\"global\",copyright:\"© 2021 Denis Pushkarev (zloirock.ru)\"})})),Z=0,I=Math.random(),q=function(t){return\"Symbol(\"+String(void 0===t?\"\":t)+\")_\"+(++Z+I).toString(36)},K=V(\"keys\"),W={},Y=i.WeakMap;if(G){var _=N.state||(N.state=new Y),Q=_.get,X=_.has,\$=_.set;z=function(t,n){return n.facade=t,\$.call(_,t,n),n},L=function(t){return Q.call(_,t)||{}},j=function(t){return X.call(_,t)}}else{var tt=K[B=\"state\"]||(K[B]=q(B));W[tt]=!0,z=function(t,n){return n.facade=t,O(t,tt,n),n},L=function(t){return C(t,tt)?t[tt]:{}},j=function(t){return C(t,tt)}}var nt,ot,rt={set:z,get:L,has:j,enforce:function(t){return j(t)?L(t):z(t,{})},getterFor:function(t){return function(n){var o;if(!P(n)||(o=L(n)).type!==t)throw TypeError(\"Incompatible receiver, \"+t+\" required\");return o}}},et=e((function(t){var n=rt.get,o=rt.enforce,r=String(String).split(\"String\");(t.exports=function(t,n,e,a){var u,f=!!a&&!!a.unsafe,c=!!a&&!!a.enumerable,l=!!a&&!!a.noTargetGet;\"function\"==typeof e&&(\"string\"!=typeof n||C(e,\"name\")||O(e,\"name\",n),(u=o(e)).source||(u.source=r.join(\"string\"==typeof n?n:\"\"))),t!==i?(f?!l&&t[n]&&(c=!0):delete t[n],c?t[n]=e:O(t,n,e)):c?t[n]=e:M(n,e)})(Function.prototype,\"toString\",(function(){return\"function\"==typeof this&&n(this).source||U(this)}))})),at=i,it=function(t){return\"function\"==typeof t?t:void 0},ut=function(t,n){return arguments.length<2?it(at[t])||it(i[t]):at[t]&&at[t][n]||i[t]&&i[t][n]},ft=Math.ceil,ct=Math.floor,lt=function(t){return isNaN(t=+t)?0:(t>0?ct:ft)(t)},st=Math.min,mt=function(t){return t>0?st(lt(t),9007199254740991):0},gt=Math.max,dt=Math.min,ht=function(t){return function(n,o,r){var e,a=S(n),i=mt(a.length),u=function(t,n){var o=lt(t);return o<0?gt(o+n,0):dt(o,n)}(r,i);if(t&&o!=o){for(;i>u;)if((e=a[u++])!=e)return!0}else for(;i>u;u++)if((t||u in a)&&a[u]===o)return t||u||0;return!t&&-1}},pt={includes:ht(!0),indexOf:ht(!1)}.indexOf,wt=[\"constructor\",\"hasOwnProperty\",\"isPrototypeOf\",\"propertyIsEnumerable\",\"toLocaleString\",\"toString\",\"valueOf\"].concat(\"length\",\"prototype\"),St={f:Object.getOwnPropertyNames||function(t){return function(t,n){var o,r=S(t),e=0,a=[];for(o in r)!C(W,o)&&C(r,o)&&a.push(o);for(;n.length>e;)C(r,o=n[e++])&&(~pt(a,o)||a.push(o));return a}(t,wt)}},Pt={f:Object.getOwnPropertySymbols},Tt=ut(\"Reflect\",\"ownKeys\")||function(t){var n=St.f(y(t)),o=Pt.f;return o?n.concat(o(t)):n},Rt=function(t,n){for(var o=Tt(n),r=H.f,e=F.f,a=0;a<o.length;a++){var i=o[a];C(t,i)||r(t,i,e(n,i))}},Ct=/#|\\.prototype\\./,bt=function(t,n){var o=At[vt(t)];return o==Ft||o!=xt&&(\"function\"==typeof n?u(n):!!n)},vt=bt.normalize=function(t){return String(t).replace(Ct,\".\").toLowerCase()},At=bt.data={},xt=bt.NATIVE=\"N\",Ft=bt.POLYFILL=\"P\",yt=bt,kt=F.f,Ht=Array.isArray||function(t){return\"Array\"==d(t)},Ot=function(t){return Object(w(t))},Mt=function(t,n,o){var r=T(n);r in t?H.f(t,r,m(0,o)):t[r]=o},Et=\"process\"==d(i.process),Nt=ut(\"navigator\",\"userAgent\")||\"\",Dt=i.process,zt=Dt&&Dt.versions,Lt=zt&&zt.v8;Lt?ot=(nt=Lt.split(\".\"))[0]+nt[1]:Nt&&(!(nt=Nt.match(/Edge\\/(\\d+)/))||nt[1]>=74)&&(nt=Nt.match(/Chrome\\/(\\d+)/))&&(ot=nt[1]);var jt,Bt=ot&&+ot,Ut=!!Object.getOwnPropertySymbols&&!u((function(){return!Symbol.sham&&(Et?38===Bt:Bt>37&&Bt<41)})),Jt=Ut&&!Symbol.sham&&\"symbol\"==typeof Symbol.iterator,Gt=V(\"wks\"),Vt=i.Symbol,Zt=Jt?Vt:Vt&&Vt.withoutSetter||q,It=function(t){return C(Gt,t)&&(Ut||\"string\"==typeof Gt[t])||(Ut&&C(Vt,t)?Gt[t]=Vt[t]:Gt[t]=Zt(\"Symbol.\"+t)),Gt[t]},qt=It(\"species\"),Kt=function(t,n){var o;return Ht(t)&&(\"function\"!=typeof(o=t.constructor)||o!==Array&&!Ht(o.prototype)?P(o)&&null===(o=o[qt])&&(o=void 0):o=void 0),new(void 0===o?Array:o)(0===n?0:n)},Wt=It(\"species\"),Yt=It(\"isConcatSpreadable\"),_t=9007199254740991,Qt=\"Maximum allowed index exceeded\",Xt=Bt>=51||!u((function(){var t=[];return t[Yt]=!1,t.concat()[0]!==t})),\$t=(jt=\"concat\",Bt>=51||!u((function(){var t=[];return(t.constructor={})[Wt]=function(){return{foo:1}},1!==t[jt](Boolean).foo}))),tn=function(t){if(!P(t))return!1;var n=t[Yt];return void 0!==n?!!n:Ht(t)};!function(t,n){var o,r,e,a,u,f=t.target,c=t.global,l=t.stat;if(o=c?i:l?i[f]||M(f,{}):(i[f]||{}).prototype)for(r in n){if(a=n[r],e=t.noTargetGet?(u=kt(o,r))&&u.value:o[r],!yt(c?r:f+(l?\".\":\"#\")+r,t.forced)&&void 0!==e){if(typeof a==typeof e)continue;Rt(a,e)}(t.sham||e&&e.sham)&&O(a,\"sham\",!0),et(o,r,a,t)}}({target:\"Array\",proto:!0,forced:!Xt||!\$t},{concat:function(t){var n,o,r,e,a,i=Ot(this),u=Kt(i,0),f=0;for(n=-1,r=arguments.length;n<r;n++)if(tn(a=-1===n?i:arguments[n])){if(f+(e=mt(a.length))>_t)throw TypeError(Qt);for(o=0;o<e;o++,f++)o in a&&Mt(u,f,a[o])}else{if(f>=_t)throw TypeError(Qt);Mt(u,f++,a)}return u.length=f,u}}),o.default.fn.bootstrapTable.locales[\"af-ZA\"]=o.default.fn.bootstrapTable.locales.af={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Besig om te laai, wag asseblief\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" rekords per bladsy\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Resultate \".concat(t,\" tot \").concat(n,\" van \").concat(o,\" rye (filtered from \").concat(r,\" total rows)\"):\"Resultate \".concat(t,\" tot \").concat(n,\" van \").concat(o,\" rye\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Soek\"},formatNoMatches:function(){return\"Geen rekords gevind nie\"},formatPaginationSwitch:function(){return\"Wys/verberg bladsy nummering\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Herlaai\"},formatToggle:function(){return\"Wissel\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Kolomme\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"af-ZA\"]),o.default.fn.bootstrapTable.locales[\"ar-SA\"]=o.default.fn.bootstrapTable.locales.ar={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"جاري التحميل, يرجى الإنتظار\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" سجل لكل صفحة\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"الظاهر \".concat(t,\" إلى \").concat(n,\" من \").concat(o,\" سجل \").concat(r,\" total rows)\"):\"الظاهر \".concat(t,\" إلى \").concat(n,\" من \").concat(o,\" سجل\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"بحث\"},formatNoMatches:function(){return\"لا توجد نتائج مطابقة للبحث\"},formatPaginationSwitch:function(){return\"إخفاءإظهار ترقيم الصفحات\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"تحديث\"},formatToggle:function(){return\"تغيير\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"أعمدة\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"ar-SA\"]),o.default.fn.bootstrapTable.locales[\"bg-BG\"]=o.default.fn.bootstrapTable.locales.bg={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Зареждане, моля изчакайте\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" реда на страница\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Показани редове от \".concat(t,\" до \").concat(n,\" от \").concat(o,\" реда (филтрирани от общо \").concat(r,\" реда)\"):\"Показани редове от \".concat(t,\" до \").concat(n,\" от общо \").concat(o,\" реда\")},formatSRPaginationPreText:function(){return\"предишна страница\"},formatSRPaginationPageText:function(t){return\"до страница \".concat(t)},formatSRPaginationNextText:function(){return\"следваща страница\"},formatDetailPagination:function(t){return\"Показани \".concat(t,\" реда\")},formatClearSearch:function(){return\"Изчистване на търсенето\"},formatSearch:function(){return\"Търсене\"},formatNoMatches:function(){return\"Не са намерени съвпадащи записи\"},formatPaginationSwitch:function(){return\"Скриване/Показване на странициране\"},formatPaginationSwitchDown:function(){return\"Показване на странициране\"},formatPaginationSwitchUp:function(){return\"Скриване на странициране\"},formatRefresh:function(){return\"Обновяване\"},formatToggle:function(){return\"Превключване\"},formatToggleOn:function(){return\"Показване на изглед карта\"},formatToggleOff:function(){return\"Скриване на изглед карта\"},formatColumns:function(){return\"Колони\"},formatColumnsToggleAll:function(){return\"Превключване на всички\"},formatFullscreen:function(){return\"Цял екран\"},formatAllRows:function(){return\"Всички\"},formatAutoRefresh:function(){return\"Автоматично обновяване\"},formatExport:function(){return\"Експорт на данни\"},formatJumpTo:function(){return\"ОТИДИ\"},formatAdvancedSearch:function(){return\"Разширено търсене\"},formatAdvancedCloseButton:function(){return\"Затваряне\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"bg-BG\"]),o.default.fn.bootstrapTable.locales[\"ca-ES\"]=o.default.fn.bootstrapTable.locales.ca={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Espereu, si us plau\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" resultats per pàgina\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Mostrant de \".concat(t,\" fins \").concat(n,\" - total \").concat(o,\" resultats (filtered from \").concat(r,\" total rows)\"):\"Mostrant de \".concat(t,\" fins \").concat(n,\" - total \").concat(o,\" resultats\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Cerca\"},formatNoMatches:function(){return\"No s'han trobat resultats\"},formatPaginationSwitch:function(){return\"Amaga/Mostra paginació\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Refresca\"},formatToggle:function(){return\"Alterna formatació\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Columnes\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Tots\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"ca-ES\"]),o.default.fn.bootstrapTable.locales[\"cs-CZ\"]=o.default.fn.bootstrapTable.locales.cs={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Čekejte, prosím\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" položek na stránku\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Zobrazena \".concat(t,\". - \").concat(n,\" . položka z celkových \").concat(o,\" (filtered from \").concat(r,\" total rows)\"):\"Zobrazena \".concat(t,\". - \").concat(n,\" . položka z celkových \").concat(o)},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Vyhledávání\"},formatNoMatches:function(){return\"Nenalezena žádná vyhovující položka\"},formatPaginationSwitch:function(){return\"Skrýt/Zobrazit stránkování\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Aktualizovat\"},formatToggle:function(){return\"Přepni\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Sloupce\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Vše\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"cs-CZ\"]),o.default.fn.bootstrapTable.locales[\"da-DK\"]=o.default.fn.bootstrapTable.locales.da={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Indlæser, vent venligst\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" poster pr side\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Viser \".concat(t,\" til \").concat(n,\" af \").concat(o,\" række\").concat(o>1?\"r\":\"\",\" (filtered from \").concat(r,\" total rows)\"):\"Viser \".concat(t,\" til \").concat(n,\" af \").concat(o,\" række\").concat(o>1?\"r\":\"\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Viser \".concat(t,\" række\").concat(t>1?\"r\":\"\")},formatClearSearch:function(){return\"Ryd filtre\"},formatSearch:function(){return\"Søg\"},formatNoMatches:function(){return\"Ingen poster fundet\"},formatPaginationSwitch:function(){return\"Skjul/vis nummerering\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Opdater\"},formatToggle:function(){return\"Skift\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Kolonner\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Alle\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Eksporter\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"da-DK\"]),o.default.fn.bootstrapTable.locales[\"de-DE\"]=o.default.fn.bootstrapTable.locales.de={formatCopyRows:function(){return\"Zeilen kopieren\"},formatPrint:function(){return\"Drucken\"},formatLoadingMessage:function(){return\"Lade, bitte warten\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" Zeilen pro Seite.\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Zeige Zeile \".concat(t,\" bis \").concat(n,\" von \").concat(o,\" Zeile\").concat(o>1?\"n\":\"\",\" (Gefiltert von \").concat(r,\" Zeile\").concat(r>1?\"n\":\"\",\")\"):\"Zeige Zeile \".concat(t,\" bis \").concat(n,\" von \").concat(o,\" Zeile\").concat(o>1?\"n\":\"\",\".\")},formatSRPaginationPreText:function(){return\"Vorherige Seite\"},formatSRPaginationPageText:function(t){return\"Zu Seite \".concat(t)},formatSRPaginationNextText:function(){return\"Nächste Seite\"},formatDetailPagination:function(t){return\"Zeige \".concat(t,\" Zeile\").concat(t>1?\"n\":\"\",\".\")},formatClearSearch:function(){return\"Lösche Filter\"},formatSearch:function(){return\"Suchen\"},formatNoMatches:function(){return\"Keine passenden Ergebnisse gefunden\"},formatPaginationSwitch:function(){return\"Verstecke/Zeige Nummerierung\"},formatPaginationSwitchDown:function(){return\"Zeige Nummerierung\"},formatPaginationSwitchUp:function(){return\"Verstecke Nummerierung\"},formatRefresh:function(){return\"Neu laden\"},formatToggle:function(){return\"Umschalten\"},formatToggleOn:function(){return\"Normale Ansicht\"},formatToggleOff:function(){return\"Kartenansicht\"},formatColumns:function(){return\"Spalten\"},formatColumnsToggleAll:function(){return\"Alle umschalten\"},formatFullscreen:function(){return\"Vollbild\"},formatAllRows:function(){return\"Alle\"},formatAutoRefresh:function(){return\"Automatisches Neuladen\"},formatExport:function(){return\"Datenexport\"},formatJumpTo:function(){return\"Springen\"},formatAdvancedSearch:function(){return\"Erweiterte Suche\"},formatAdvancedCloseButton:function(){return\"Schließen\"},formatFilterControlSwitch:function(){return\"Verstecke/Zeige Filter\"},formatFilterControlSwitchHide:function(){return\"Verstecke Filter\"},formatFilterControlSwitchShow:function(){return\"Zeige Filter\"},formatAddLevel:function(){return\"Ebene hinzufügen\"},formatCancel:function(){return\"Abbrechen\"},formatColumn:function(){return\"Spalte\"},formatDeleteLevel:function(){return\"Ebene entfernen\"},formatDuplicateAlertTitle:function(){return\"Doppelte Einträge gefunden!\"},formatDuplicateAlertDescription:function(){return\"Bitte doppelte Spalten entfenen oder ändern\"},formatMultipleSort:function(){return\"Mehrfachsortierung\"},formatOrder:function(){return\"Reihenfolge\"},formatSort:function(){return\"Sortieren\"},formatSortBy:function(){return\"Sortieren nach\"},formatThenBy:function(){return\"anschließend\"},formatSortOrders:function(){return{asc:\"Aufsteigend\",desc:\"Absteigend\"}}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"de-DE\"]),o.default.fn.bootstrapTable.locales[\"el-GR\"]=o.default.fn.bootstrapTable.locales.el={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Φορτώνει, παρακαλώ περιμένετε\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" αποτελέσματα ανά σελίδα\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Εμφανίζονται από την \".concat(t,\" ως την \").concat(n,\" από σύνολο \").concat(o,\" σειρών (filtered from \").concat(r,\" total rows)\"):\"Εμφανίζονται από την \".concat(t,\" ως την \").concat(n,\" από σύνολο \").concat(o,\" σειρών\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Αναζητήστε\"},formatNoMatches:function(){return\"Δεν βρέθηκαν αποτελέσματα\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Refresh\"},formatToggle:function(){return\"Toggle\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Columns\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"el-GR\"]),o.default.fn.bootstrapTable.locales[\"en-US\"]=o.default.fn.bootstrapTable.locales.en={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Loading, please wait\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" rows per page\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Showing \".concat(t,\" to \").concat(n,\" of \").concat(o,\" rows (filtered from \").concat(r,\" total rows)\"):\"Showing \".concat(t,\" to \").concat(n,\" of \").concat(o,\" rows\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Search\"},formatNoMatches:function(){return\"No matching records found\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Refresh\"},formatToggle:function(){return\"Toggle\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Columns\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"en-US\"]),o.default.fn.bootstrapTable.locales[\"es-AR\"]={formatCopyRows:function(){return\"Copiar Filas\"},formatPrint:function(){return\"Imprimir\"},formatLoadingMessage:function(){return\"Cargando, espere por favor\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" registros por página\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Mostrando desde \".concat(t,\" a \").concat(n,\" de \").concat(o,\" filas (filtrado de \").concat(r,\" columnas totales)\"):\"Mostrando desde \".concat(t,\" a \").concat(n,\" de \").concat(o,\" filas\")},formatSRPaginationPreText:function(){return\"página anterior\"},formatSRPaginationPageText:function(t){return\"a la página \".concat(t)},formatSRPaginationNextText:function(){return\"siguiente página\"},formatDetailPagination:function(t){return\"Mostrando \".concat(t,\" columnas\")},formatClearSearch:function(){return\"Limpiar búsqueda\"},formatSearch:function(){return\"Buscar\"},formatNoMatches:function(){return\"No se encontraron registros\"},formatPaginationSwitch:function(){return\"Ocultar/Mostrar paginación\"},formatPaginationSwitchDown:function(){return\"Mostrar paginación\"},formatPaginationSwitchUp:function(){return\"Ocultar paginación\"},formatRefresh:function(){return\"Recargar\"},formatToggle:function(){return\"Cambiar\"},formatToggleOn:function(){return\"Mostrar vista de carta\"},formatToggleOff:function(){return\"Ocultar vista de carta\"},formatColumns:function(){return\"Columnas\"},formatColumnsToggleAll:function(){return\"Cambiar todo\"},formatFullscreen:function(){return\"Pantalla completa\"},formatAllRows:function(){return\"Todo\"},formatAutoRefresh:function(){return\"Auto Recargar\"},formatExport:function(){return\"Exportar datos\"},formatJumpTo:function(){return\"Ir\"},formatAdvancedSearch:function(){return\"Búsqueda avanzada\"},formatAdvancedCloseButton:function(){return\"Cerrar\"},formatFilterControlSwitch:function(){return\"Ocultar/Mostrar controles\"},formatFilterControlSwitchHide:function(){return\"Ocultar controles\"},formatFilterControlSwitchShow:function(){return\"Mostrar controles\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"es-AR\"]),o.default.fn.bootstrapTable.locales[\"es-CL\"]={formatCopyRows:function(){return\"Copiar Filas\"},formatPrint:function(){return\"Imprimir\"},formatLoadingMessage:function(){return\"Cargando, espere por favor\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" filas por página\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Mostrando \".concat(t,\" a \").concat(n,\" de \").concat(o,\" filas (filtrado de \").concat(r,\" filas totales)\"):\"Mostrando \".concat(t,\" a \").concat(n,\" de \").concat(o,\" filas\")},formatSRPaginationPreText:function(){return\"página anterior\"},formatSRPaginationPageText:function(t){return\"a la página \".concat(t)},formatSRPaginationNextText:function(){return\"siguiente página\"},formatDetailPagination:function(t){return\"Mostrando \".concat(t,\" filas\")},formatClearSearch:function(){return\"Limpiar búsqueda\"},formatSearch:function(){return\"Buscar\"},formatNoMatches:function(){return\"No se encontraron registros\"},formatPaginationSwitch:function(){return\"Ocultar/Mostrar paginación\"},formatPaginationSwitchDown:function(){return\"Mostrar paginación\"},formatPaginationSwitchUp:function(){return\"Ocultar paginación\"},formatRefresh:function(){return\"Refrescar\"},formatToggle:function(){return\"Cambiar\"},formatToggleOn:function(){return\"Mostrar vista de carta\"},formatToggleOff:function(){return\"Ocultar vista de carta\"},formatColumns:function(){return\"Columnas\"},formatColumnsToggleAll:function(){return\"Cambiar todo\"},formatFullscreen:function(){return\"Pantalla completa\"},formatAllRows:function(){return\"Todo\"},formatAutoRefresh:function(){return\"Auto Recargar\"},formatExport:function(){return\"Exportar datos\"},formatJumpTo:function(){return\"IR\"},formatAdvancedSearch:function(){return\"Búsqueda avanzada\"},formatAdvancedCloseButton:function(){return\"Cerrar\"},formatFilterControlSwitch:function(){return\"Ocultar/Mostrar controles\"},formatFilterControlSwitchHide:function(){return\"Ocultar controles\"},formatFilterControlSwitchShow:function(){return\"Mostrar controles\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"es-CL\"]),o.default.fn.bootstrapTable.locales[\"es-CR\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Cargando, por favor espere\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" registros por página\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Mostrando de \".concat(t,\" a \").concat(n,\" registros de \").concat(o,\" registros en total (filtered from \").concat(r,\" total rows)\"):\"Mostrando de \".concat(t,\" a \").concat(n,\" registros de \").concat(o,\" registros en total\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Limpiar búsqueda\"},formatSearch:function(){return\"Buscar\"},formatNoMatches:function(){return\"No se encontraron registros\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Refrescar\"},formatToggle:function(){return\"Alternar\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Columnas\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Todo\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Ocultar/Mostrar controles\"},formatFilterControlSwitchHide:function(){return\"Ocultar controles\"},formatFilterControlSwitchShow:function(){return\"Mostrar controles\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"es-CR\"]),o.default.fn.bootstrapTable.locales[\"es-ES\"]=o.default.fn.bootstrapTable.locales.es={formatCopyRows:function(){return\"Copiar filas\"},formatPrint:function(){return\"Imprimir\"},formatLoadingMessage:function(){return\"Por favor espere\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" resultados por página\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Mostrando desde \".concat(t,\" hasta \").concat(n,\" - En total \").concat(o,\" resultados (filtrado de \").concat(r,\" filas totales)\"):\"Mostrando desde \".concat(t,\" hasta \").concat(n,\" - En total \").concat(o,\" resultados\")},formatSRPaginationPreText:function(){return\"página anterior\"},formatSRPaginationPageText:function(t){return\"a la página \".concat(t)},formatSRPaginationNextText:function(){return\"siguiente página\"},formatDetailPagination:function(t){return\"Mostrando \".concat(t,\" filas\")},formatClearSearch:function(){return\"Limpiar búsqueda\"},formatSearch:function(){return\"Buscar\"},formatNoMatches:function(){return\"No se encontraron resultados\"},formatPaginationSwitch:function(){return\"Ocultar/Mostrar paginación\"},formatPaginationSwitchDown:function(){return\"Mostrar paginación\"},formatPaginationSwitchUp:function(){return\"Ocultar paginación\"},formatRefresh:function(){return\"Recargar\"},formatToggle:function(){return\"Ocultar/Mostrar\"},formatToggleOn:function(){return\"Mostrar vista de carta\"},formatToggleOff:function(){return\"Ocultar vista de carta\"},formatColumns:function(){return\"Columnas\"},formatColumnsToggleAll:function(){return\"Cambiar todo\"},formatFullscreen:function(){return\"Pantalla completa\"},formatAllRows:function(){return\"Todos\"},formatAutoRefresh:function(){return\"Auto Recargar\"},formatExport:function(){return\"Exportar los datos\"},formatJumpTo:function(){return\"IR\"},formatAdvancedSearch:function(){return\"Búsqueda avanzada\"},formatAdvancedCloseButton:function(){return\"Cerrar\"},formatFilterControlSwitch:function(){return\"Ocultar/Mostrar controles\"},formatFilterControlSwitchHide:function(){return\"Ocultar controles\"},formatFilterControlSwitchShow:function(){return\"Mostrar controles\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"es-ES\"]),o.default.fn.bootstrapTable.locales[\"es-MX\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Cargando, espere por favor\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" registros por página\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Mostrando \".concat(t,\" a \").concat(n,\" de \").concat(o,\" filas (filtered from \").concat(r,\" total rows)\"):\"Mostrando \".concat(t,\" a \").concat(n,\" de \").concat(o,\" filas\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Mostrando \".concat(t,\" filas\")},formatClearSearch:function(){return\"Limpiar búsqueda\"},formatSearch:function(){return\"Buscar\"},formatNoMatches:function(){return\"No se encontraron registros que coincidan\"},formatPaginationSwitch:function(){return\"Mostrar/ocultar paginación\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Actualizar\"},formatToggle:function(){return\"Cambiar vista\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Columnas\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Pantalla completa\"},formatAllRows:function(){return\"Todo\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Ocultar/Mostrar controles\"},formatFilterControlSwitchHide:function(){return\"Ocultar controles\"},formatFilterControlSwitchShow:function(){return\"Mostrar controles\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"es-MX\"]),o.default.fn.bootstrapTable.locales[\"es-NI\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Cargando, por favor espere\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" registros por página\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Mostrando de \".concat(t,\" a \").concat(n,\" registros de \").concat(o,\" registros en total (filtered from \").concat(r,\" total rows)\"):\"Mostrando de \".concat(t,\" a \").concat(n,\" registros de \").concat(o,\" registros en total\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Limpiar búsqueda\"},formatSearch:function(){return\"Buscar\"},formatNoMatches:function(){return\"No se encontraron registros\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Refrescar\"},formatToggle:function(){return\"Alternar\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Columnas\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Todo\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Ocultar/Mostrar controles\"},formatFilterControlSwitchHide:function(){return\"Ocultar controles\"},formatFilterControlSwitchShow:function(){return\"Mostrar controles\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"es-NI\"]),o.default.fn.bootstrapTable.locales[\"es-SP\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Cargando, por favor espera\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" registros por p&#225;gina.\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"\".concat(t,\" - \").concat(n,\" de \").concat(o,\" registros (filtered from \").concat(r,\" total rows)\"):\"\".concat(t,\" - \").concat(n,\" de \").concat(o,\" registros.\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Limpiar búsqueda\"},formatSearch:function(){return\"Buscar\"},formatNoMatches:function(){return\"No se han encontrado registros.\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Actualizar\"},formatToggle:function(){return\"Alternar\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Columnas\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Todo\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Ocultar/Mostrar controles\"},formatFilterControlSwitchHide:function(){return\"Ocultar controles\"},formatFilterControlSwitchShow:function(){return\"Mostrar controles\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"es-SP\"]),o.default.fn.bootstrapTable.locales[\"et-EE\"]=o.default.fn.bootstrapTable.locales.et={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Päring käib, palun oota\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" rida lehe kohta\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Näitan tulemusi \".concat(t,\" kuni \").concat(n,\" - kokku \").concat(o,\" tulemust (filtered from \").concat(r,\" total rows)\"):\"Näitan tulemusi \".concat(t,\" kuni \").concat(n,\" - kokku \").concat(o,\" tulemust\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Otsi\"},formatNoMatches:function(){return\"Päringu tingimustele ei vastanud ühtegi tulemust\"},formatPaginationSwitch:function(){return\"Näita/Peida lehtedeks jagamine\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Värskenda\"},formatToggle:function(){return\"Lülita\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Veerud\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Kõik\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"et-EE\"]),o.default.fn.bootstrapTable.locales[\"eu-EU\"]=o.default.fn.bootstrapTable.locales.eu={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Itxaron mesedez\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" emaitza orriko.\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"\".concat(o,\" erregistroetatik \").concat(t,\"etik \").concat(n,\"erakoak erakusten (filtered from \").concat(r,\" total rows)\"):\"\".concat(o,\" erregistroetatik \").concat(t,\"etik \").concat(n,\"erakoak erakusten.\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Bilatu\"},formatNoMatches:function(){return\"Ez da emaitzarik aurkitu\"},formatPaginationSwitch:function(){return\"Ezkutatu/Erakutsi orrikatzea\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Eguneratu\"},formatToggle:function(){return\"Ezkutatu/Erakutsi\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Zutabeak\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Guztiak\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"eu-EU\"]),o.default.fn.bootstrapTable.locales[\"fa-IR\"]=o.default.fn.bootstrapTable.locales.fa={formatCopyRows:function(){return\"کپی ردیف ها\"},formatPrint:function(){return\"پرینت\"},formatLoadingMessage:function(){return\"در حال بارگذاری, لطفا صبر کنید\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" رکورد در صفحه\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"نمایش \".concat(t,\" تا \").concat(n,\" از \").concat(o,\" ردیف (filtered from \").concat(r,\" total rows)\"):\"نمایش \".concat(t,\" تا \").concat(n,\" از \").concat(o,\" ردیف\")},formatSRPaginationPreText:function(){return\"صفحه قبلی\"},formatSRPaginationPageText:function(t){return\"به صفحه \".concat(t)},formatSRPaginationNextText:function(){return\"صفحه بعدی\"},formatDetailPagination:function(t){return\"نمایش \".concat(t,\" سطرها\")},formatClearSearch:function(){return\"پاک کردن جستجو\"},formatSearch:function(){return\"جستجو\"},formatNoMatches:function(){return\"رکوردی یافت نشد.\"},formatPaginationSwitch:function(){return\"نمایش/مخفی صفحه بندی\"},formatPaginationSwitchDown:function(){return\"نمایش صفحه بندی\"},formatPaginationSwitchUp:function(){return\"پنهان کردن صفحه بندی\"},formatRefresh:function(){return\"به روز رسانی\"},formatToggle:function(){return\"تغییر نمایش\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"سطر ها\"},formatColumnsToggleAll:function(){return\"تغییر وضعیت همه\"},formatFullscreen:function(){return\"تمام صفحه\"},formatAllRows:function(){return\"همه\"},formatAutoRefresh:function(){return\"رفرش اتوماتیک\"},formatExport:function(){return\"خروجی دیتا\"},formatJumpTo:function(){return\"برو\"},formatAdvancedSearch:function(){return\"جستجوی پیشرفته\"},formatAdvancedCloseButton:function(){return\"بستن\"},formatFilterControlSwitch:function(){return\"پنهان/نمایش دادن کنترل ها\"},formatFilterControlSwitchHide:function(){return\"پنهان کردن کنترل ها\"},formatFilterControlSwitchShow:function(){return\"نمایش کنترل ها\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"fa-IR\"]),o.default.fn.bootstrapTable.locales[\"fi-FI\"]=o.default.fn.bootstrapTable.locales.fi={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Ladataan, ole hyvä ja odota\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" riviä sivulla\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Näytetään rivit \".concat(t,\" - \").concat(n,\" / \").concat(o,\" (filtered from \").concat(r,\" total rows)\"):\"Näytetään rivit \".concat(t,\" - \").concat(n,\" / \").concat(o)},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Poista suodattimet\"},formatSearch:function(){return\"Hae\"},formatNoMatches:function(){return\"Hakuehtoja vastaavia tuloksia ei löytynyt\"},formatPaginationSwitch:function(){return\"Näytä/Piilota sivutus\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Päivitä\"},formatToggle:function(){return\"Valitse\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Sarakkeet\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Kaikki\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Vie tiedot\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"fi-FI\"]),o.default.fn.bootstrapTable.locales[\"fr-BE\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Chargement en cours\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" lignes par page\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Affiche de \".concat(t,\" à \").concat(n,\" sur \").concat(o,\" lignes (filtrés à partir de \").concat(r,\" lignes)\"):\"Affiche de \".concat(t,\" à \").concat(n,\" sur \").concat(o,\" lignes\")},formatSRPaginationPreText:function(){return\"page précédente\"},formatSRPaginationPageText:function(t){return\"vers la page \".concat(t)},formatSRPaginationNextText:function(){return\"page suivante\"},formatDetailPagination:function(t){return\"Affiche \".concat(t,\" lignes\")},formatClearSearch:function(){return\"Effacer la recherche\"},formatSearch:function(){return\"Recherche\"},formatNoMatches:function(){return\"Pas de lignes trouvés\"},formatPaginationSwitch:function(){return\"Cacher/Afficher pagination\"},formatPaginationSwitchDown:function(){return\"Afficher pagination\"},formatPaginationSwitchUp:function(){return\"Cacher pagination\"},formatRefresh:function(){return\"Rafraichir\"},formatToggle:function(){return\"Basculer\"},formatToggleOn:function(){return\"Afficher vue carte\"},formatToggleOff:function(){return\"Cacher vue carte\"},formatColumns:function(){return\"Colonnes\"},formatColumnsToggleAll:function(){return\"Tout basculer\"},formatFullscreen:function(){return\"Plein écran\"},formatAllRows:function(){return\"Tout\"},formatAutoRefresh:function(){return\"Rafraîchissement automatique\"},formatExport:function(){return\"Exporter les données\"},formatJumpTo:function(){return\"Aller à\"},formatAdvancedSearch:function(){return\"Recherche avancée\"},formatAdvancedCloseButton:function(){return\"Fermer\"},formatFilterControlSwitch:function(){return\"Cacher/Afficher controls\"},formatFilterControlSwitchHide:function(){return\"Cacher controls\"},formatFilterControlSwitchShow:function(){return\"Afficher controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"fr-BE\"]),o.default.fn.bootstrapTable.locales[\"fr-CH\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Chargement en cours\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" lignes par page\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Affiche de \".concat(t,\" à \").concat(n,\" sur \").concat(o,\" lignes (filtrés à partir de \").concat(r,\" lignes)\"):\"Affiche de \".concat(t,\" à \").concat(n,\" sur \").concat(o,\" lignes\")},formatSRPaginationPreText:function(){return\"page précédente\"},formatSRPaginationPageText:function(t){return\"vers la page \".concat(t)},formatSRPaginationNextText:function(){return\"page suivante\"},formatDetailPagination:function(t){return\"Affiche \".concat(t,\" lignes\")},formatClearSearch:function(){return\"Effacer la recherche\"},formatSearch:function(){return\"Recherche\"},formatNoMatches:function(){return\"Pas de lignes trouvés\"},formatPaginationSwitch:function(){return\"Cacher/Afficher pagination\"},formatPaginationSwitchDown:function(){return\"Afficher pagination\"},formatPaginationSwitchUp:function(){return\"Cacher pagination\"},formatRefresh:function(){return\"Rafraichir\"},formatToggle:function(){return\"Basculer\"},formatToggleOn:function(){return\"Afficher vue carte\"},formatToggleOff:function(){return\"Cacher vue carte\"},formatColumns:function(){return\"Colonnes\"},formatColumnsToggleAll:function(){return\"Tout basculer\"},formatFullscreen:function(){return\"Plein écran\"},formatAllRows:function(){return\"Tout\"},formatAutoRefresh:function(){return\"Rafraîchissement automatique\"},formatExport:function(){return\"Exporter les données\"},formatJumpTo:function(){return\"Aller à\"},formatAdvancedSearch:function(){return\"Recherche avancée\"},formatAdvancedCloseButton:function(){return\"Fermer\"},formatFilterControlSwitch:function(){return\"Cacher/Afficher controls\"},formatFilterControlSwitchHide:function(){return\"Cacher controls\"},formatFilterControlSwitchShow:function(){return\"Afficher controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"fr-CH\"]),o.default.fn.bootstrapTable.locales[\"fr-FR\"]=o.default.fn.bootstrapTable.locales.fr={formatCopyRows:function(){return\"Copier les lignes\"},formatPrint:function(){return\"Imprimer\"},formatLoadingMessage:function(){return\"Chargement en cours\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" lignes par page\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Affiche de \".concat(t,\" à \").concat(n,\" sur \").concat(o,\" lignes (filtrés à partir de \").concat(r,\" lignes)\"):\"Affiche de \".concat(t,\" à \").concat(n,\" sur \").concat(o,\" lignes\")},formatSRPaginationPreText:function(){return\"page précédente\"},formatSRPaginationPageText:function(t){return\"vers la page \".concat(t)},formatSRPaginationNextText:function(){return\"page suivante\"},formatDetailPagination:function(t){return\"Affiche \".concat(t,\" lignes\")},formatClearSearch:function(){return\"Effacer la recherche\"},formatSearch:function(){return\"Recherche\"},formatNoMatches:function(){return\"Aucun résultat\"},formatPaginationSwitch:function(){return\"Masquer/Afficher la pagination\"},formatPaginationSwitchDown:function(){return\"Afficher la pagination\"},formatPaginationSwitchUp:function(){return\"Masquer la pagination\"},formatRefresh:function(){return\"Actualiser\"},formatToggle:function(){return\"Basculer\"},formatToggleOn:function(){return\"Afficher la vue carte\"},formatToggleOff:function(){return\"Masquer la vue carte\"},formatColumns:function(){return\"Colonnes\"},formatColumnsToggleAll:function(){return\"Tout basculer\"},formatFullscreen:function(){return\"Plein écran\"},formatAllRows:function(){return\"Tout\"},formatAutoRefresh:function(){return\"Actualisation automatique\"},formatExport:function(){return\"Exporter les données\"},formatJumpTo:function(){return\"ALLER\"},formatAdvancedSearch:function(){return\"Recherche avancée\"},formatAdvancedCloseButton:function(){return\"Fermer\"},formatFilterControlSwitch:function(){return\"Masquer/Afficher les contrôles\"},formatFilterControlSwitchHide:function(){return\"Masquer les contrôles\"},formatFilterControlSwitchShow:function(){return\"Afficher les contrôles\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"fr-FR\"]),o.default.fn.bootstrapTable.locales[\"fr-LU\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Chargement en cours\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" lignes par page\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Affiche de \".concat(t,\" à \").concat(n,\" sur \").concat(o,\" lignes (filtrés à partir de \").concat(r,\" lignes)\"):\"Affiche de \".concat(t,\" à \").concat(n,\" sur \").concat(o,\" lignes\")},formatSRPaginationPreText:function(){return\"page précédente\"},formatSRPaginationPageText:function(t){return\"vers la page \".concat(t)},formatSRPaginationNextText:function(){return\"page suivante\"},formatDetailPagination:function(t){return\"Affiche \".concat(t,\" lignes\")},formatClearSearch:function(){return\"Effacer la recherche\"},formatSearch:function(){return\"Recherche\"},formatNoMatches:function(){return\"Pas de lignes trouvés\"},formatPaginationSwitch:function(){return\"Cacher/Afficher pagination\"},formatPaginationSwitchDown:function(){return\"Afficher pagination\"},formatPaginationSwitchUp:function(){return\"Cacher pagination\"},formatRefresh:function(){return\"Rafraichir\"},formatToggle:function(){return\"Basculer\"},formatToggleOn:function(){return\"Afficher vue carte\"},formatToggleOff:function(){return\"Cacher vue carte\"},formatColumns:function(){return\"Colonnes\"},formatColumnsToggleAll:function(){return\"Tout basculer\"},formatFullscreen:function(){return\"Plein écran\"},formatAllRows:function(){return\"Tout\"},formatAutoRefresh:function(){return\"Rafraîchissement automatique\"},formatExport:function(){return\"Exporter les données\"},formatJumpTo:function(){return\"Aller à\"},formatAdvancedSearch:function(){return\"Recherche avancée\"},formatAdvancedCloseButton:function(){return\"Fermer\"},formatFilterControlSwitch:function(){return\"Cacher/Afficher controls\"},formatFilterControlSwitchHide:function(){return\"Cacher controls\"},formatFilterControlSwitchShow:function(){return\"Afficher controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"fr-LU\"]),o.default.fn.bootstrapTable.locales[\"he-IL\"]=o.default.fn.bootstrapTable.locales.he={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"טוען, נא להמתין\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" שורות בעמוד\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"מציג \".concat(t,\" עד \").concat(n,\" מ-\").concat(o,\"שורות\").concat(r,\" total rows)\"):\"מציג \".concat(t,\" עד \").concat(n,\" מ-\").concat(o,\" שורות\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"חיפוש\"},formatNoMatches:function(){return\"לא נמצאו רשומות תואמות\"},formatPaginationSwitch:function(){return\"הסתר/הצג מספור דפים\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"רענן\"},formatToggle:function(){return\"החלף תצוגה\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"עמודות\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"הכל\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"he-IL\"]),o.default.fn.bootstrapTable.locales[\"hr-HR\"]=o.default.fn.bootstrapTable.locales.hr={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Molimo pričekajte\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" broj zapisa po stranici\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Prikazujem \".concat(t,\". - \").concat(n,\". od ukupnog broja zapisa \").concat(o,\" (filtered from \").concat(r,\" total rows)\"):\"Prikazujem \".concat(t,\". - \").concat(n,\". od ukupnog broja zapisa \").concat(o)},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Pretraži\"},formatNoMatches:function(){return\"Nije pronađen niti jedan zapis\"},formatPaginationSwitch:function(){return\"Prikaži/sakrij stranice\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Osvježi\"},formatToggle:function(){return\"Promijeni prikaz\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Kolone\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Sve\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"hr-HR\"]),o.default.fn.bootstrapTable.locales[\"hu-HU\"]=o.default.fn.bootstrapTable.locales.hu={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Betöltés, kérem várjon\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" rekord per oldal\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Megjelenítve \".concat(t,\" - \").concat(n,\" / \").concat(o,\" összesen (filtered from \").concat(r,\" total rows)\"):\"Megjelenítve \".concat(t,\" - \").concat(n,\" / \").concat(o,\" összesen\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Keresés\"},formatNoMatches:function(){return\"Nincs találat\"},formatPaginationSwitch:function(){return\"Lapozó elrejtése/megjelenítése\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Frissítés\"},formatToggle:function(){return\"Összecsuk/Kinyit\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Oszlopok\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Összes\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"hu-HU\"]),o.default.fn.bootstrapTable.locales[\"id-ID\"]=o.default.fn.bootstrapTable.locales.id={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Memuat, mohon tunggu\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" baris per halaman\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Menampilkan \".concat(t,\" sampai \").concat(n,\" dari \").concat(o,\" baris (filtered from \").concat(r,\" total rows)\"):\"Menampilkan \".concat(t,\" sampai \").concat(n,\" dari \").concat(o,\" baris\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Bersihkan filter\"},formatSearch:function(){return\"Pencarian\"},formatNoMatches:function(){return\"Tidak ditemukan data yang cocok\"},formatPaginationSwitch:function(){return\"Sembunyikan/Tampilkan halaman\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Muat ulang\"},formatToggle:function(){return\"Beralih\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"kolom\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Semua\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Ekspor data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"id-ID\"]),o.default.fn.bootstrapTable.locales[\"it-IT\"]=o.default.fn.bootstrapTable.locales.it={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Caricamento in corso\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" elementi per pagina\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Visualizzazione da \".concat(t,\" a \").concat(n,\" di \").concat(o,\" elementi (filtrati da \").concat(r,\" elementi totali)\"):\"Visualizzazione da \".concat(t,\" a \").concat(n,\" di \").concat(o,\" elementi\")},formatSRPaginationPreText:function(){return\"pagina precedente\"},formatSRPaginationPageText:function(t){return\"alla pagina \".concat(t)},formatSRPaginationNextText:function(){return\"pagina successiva\"},formatDetailPagination:function(t){return\"Mostrando \".concat(t,\" elementi\")},formatClearSearch:function(){return\"Pulisci filtri\"},formatSearch:function(){return\"Cerca\"},formatNoMatches:function(){return\"Nessun elemento trovato\"},formatPaginationSwitch:function(){return\"Nascondi/Mostra paginazione\"},formatPaginationSwitchDown:function(){return\"Mostra paginazione\"},formatPaginationSwitchUp:function(){return\"Nascondi paginazione\"},formatRefresh:function(){return\"Aggiorna\"},formatToggle:function(){return\"Attiva/Disattiva\"},formatToggleOn:function(){return\"Mostra visuale a scheda\"},formatToggleOff:function(){return\"Nascondi visuale a scheda\"},formatColumns:function(){return\"Colonne\"},formatColumnsToggleAll:function(){return\"Mostra tutte\"},formatFullscreen:function(){return\"Schermo intero\"},formatAllRows:function(){return\"Tutto\"},formatAutoRefresh:function(){return\"Auto Aggiornamento\"},formatExport:function(){return\"Esporta dati\"},formatJumpTo:function(){return\"VAI\"},formatAdvancedSearch:function(){return\"Filtri avanzati\"},formatAdvancedCloseButton:function(){return\"Chiudi\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"it-IT\"]),o.default.fn.bootstrapTable.locales[\"ja-JP\"]=o.default.fn.bootstrapTable.locales.ja={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"読み込み中です。少々お待ちください。\"},formatRecordsPerPage:function(t){return\"ページ当たり最大\".concat(t,\"件\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"全\".concat(o,\"件から、\").concat(t,\"から\").concat(n,\"件目まで表示しています (filtered from \").concat(r,\" total rows)\"):\"全\".concat(o,\"件から、\").concat(t,\"から\").concat(n,\"件目まで表示しています\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"検索\"},formatNoMatches:function(){return\"該当するレコードが見つかりません\"},formatPaginationSwitch:function(){return\"ページ数を表示・非表示\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"更新\"},formatToggle:function(){return\"トグル\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"列\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"すべて\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"ja-JP\"]),o.default.fn.bootstrapTable.locales[\"ka-GE\"]=o.default.fn.bootstrapTable.locales.ka={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"იტვირთება, გთხოვთ მოიცადოთ\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" ჩანაწერი თითო გვერდზე\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"ნაჩვენებია \".concat(t,\"-დან \").concat(n,\"-მდე ჩანაწერი ჯამური \").concat(o,\"-დან (filtered from \").concat(r,\" total rows)\"):\"ნაჩვენებია \".concat(t,\"-დან \").concat(n,\"-მდე ჩანაწერი ჯამური \").concat(o,\"-დან\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"ძებნა\"},formatNoMatches:function(){return\"მონაცემები არ არის\"},formatPaginationSwitch:function(){return\"გვერდების გადამრთველის დამალვა/გამოჩენა\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"განახლება\"},formatToggle:function(){return\"ჩართვა/გამორთვა\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"სვეტები\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"ka-GE\"]),o.default.fn.bootstrapTable.locales[\"ko-KR\"]=o.default.fn.bootstrapTable.locales.ko={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"데이터를 불러오는 중입니다\"},formatRecordsPerPage:function(t){return\"페이지 당 \".concat(t,\"개 데이터 출력\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"전체 \".concat(o,\"개 중 \").concat(t,\"~\").concat(n,\"번째 데이터 출력, (filtered from \").concat(r,\" total rows)\"):\"전체 \".concat(o,\"개 중 \").concat(t,\"~\").concat(n,\"번째 데이터 출력,\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"검색\"},formatNoMatches:function(){return\"조회된 데이터가 없습니다.\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"새로 고침\"},formatToggle:function(){return\"전환\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"컬럼 필터링\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"ko-KR\"]),o.default.fn.bootstrapTable.locales[\"ms-MY\"]=o.default.fn.bootstrapTable.locales.ms={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Permintaan sedang dimuatkan. Sila tunggu sebentar\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" rekod setiap muka surat\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Sedang memaparkan rekod \".concat(t,\" hingga \").concat(n,\" daripada jumlah \").concat(o,\" rekod (filtered from \").concat(r,\" total rows)\"):\"Sedang memaparkan rekod \".concat(t,\" hingga \").concat(n,\" daripada jumlah \").concat(o,\" rekod\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Cari\"},formatNoMatches:function(){return\"Tiada rekod yang menyamai permintaan\"},formatPaginationSwitch:function(){return\"Tunjuk/sembunyi muka surat\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Muatsemula\"},formatToggle:function(){return\"Tukar\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Lajur\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Semua\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"ms-MY\"]),o.default.fn.bootstrapTable.locales[\"nb-NO\"]=o.default.fn.bootstrapTable.locales.nb={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Oppdaterer, vennligst vent\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" poster pr side\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Viser \".concat(t,\" til \").concat(n,\" av \").concat(o,\" rekker (filtered from \").concat(r,\" total rows)\"):\"Viser \".concat(t,\" til \").concat(n,\" av \").concat(o,\" rekker\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Søk\"},formatNoMatches:function(){return\"Ingen poster funnet\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Oppdater\"},formatToggle:function(){return\"Endre\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Kolonner\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"nb-NO\"]),o.default.fn.bootstrapTable.locales[\"nl-BE\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Laden, even geduld\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" records per pagina\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Toon \".concat(t,\" tot \").concat(n,\" van \").concat(o,\" record\").concat(o>1?\"s\":\"\",\" (gefilterd van \").concat(r,\" records in totaal)\"):\"Toon \".concat(t,\" tot \").concat(n,\" van \").concat(o,\" record\").concat(o>1?\"s\":\"\")},formatSRPaginationPreText:function(){return\"vorige pagina\"},formatSRPaginationPageText:function(t){return\"tot pagina \".concat(t)},formatSRPaginationNextText:function(){return\"volgende pagina\"},formatDetailPagination:function(t){return\"Toon \".concat(t,\" record\").concat(t>1?\"s\":\"\")},formatClearSearch:function(){return\"Verwijder filters\"},formatSearch:function(){return\"Zoeken\"},formatNoMatches:function(){return\"Geen resultaten gevonden\"},formatPaginationSwitch:function(){return\"Verberg/Toon paginering\"},formatPaginationSwitchDown:function(){return\"Toon paginering\"},formatPaginationSwitchUp:function(){return\"Verberg paginering\"},formatRefresh:function(){return\"Vernieuwen\"},formatToggle:function(){return\"Omschakelen\"},formatToggleOn:function(){return\"Toon kaartweergave\"},formatToggleOff:function(){return\"Verberg kaartweergave\"},formatColumns:function(){return\"Kolommen\"},formatColumnsToggleAll:function(){return\"Allen omschakelen\"},formatFullscreen:function(){return\"Volledig scherm\"},formatAllRows:function(){return\"Alle\"},formatAutoRefresh:function(){return\"Automatisch vernieuwen\"},formatExport:function(){return\"Exporteer gegevens\"},formatJumpTo:function(){return\"GA\"},formatAdvancedSearch:function(){return\"Geavanceerd zoeken\"},formatAdvancedCloseButton:function(){return\"Sluiten\"},formatFilterControlSwitch:function(){return\"Verberg/Toon controls\"},formatFilterControlSwitchHide:function(){return\"Verberg controls\"},formatFilterControlSwitchShow:function(){return\"Toon controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"nl-BE\"]),o.default.fn.bootstrapTable.locales[\"nl-NL\"]=o.default.fn.bootstrapTable.locales.nl={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Laden, even geduld\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" records per pagina\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Toon \".concat(t,\" tot \").concat(n,\" van \").concat(o,\" record\").concat(o>1?\"s\":\"\",\" (gefilterd van \").concat(r,\" records in totaal)\"):\"Toon \".concat(t,\" tot \").concat(n,\" van \").concat(o,\" record\").concat(o>1?\"s\":\"\")},formatSRPaginationPreText:function(){return\"vorige pagina\"},formatSRPaginationPageText:function(t){return\"tot pagina \".concat(t)},formatSRPaginationNextText:function(){return\"volgende pagina\"},formatDetailPagination:function(t){return\"Toon \".concat(t,\" record\").concat(t>1?\"s\":\"\")},formatClearSearch:function(){return\"Verwijder filters\"},formatSearch:function(){return\"Zoeken\"},formatNoMatches:function(){return\"Geen resultaten gevonden\"},formatPaginationSwitch:function(){return\"Verberg/Toon paginering\"},formatPaginationSwitchDown:function(){return\"Toon paginering\"},formatPaginationSwitchUp:function(){return\"Verberg paginering\"},formatRefresh:function(){return\"Vernieuwen\"},formatToggle:function(){return\"Omschakelen\"},formatToggleOn:function(){return\"Toon kaartweergave\"},formatToggleOff:function(){return\"Verberg kaartweergave\"},formatColumns:function(){return\"Kolommen\"},formatColumnsToggleAll:function(){return\"Allen omschakelen\"},formatFullscreen:function(){return\"Volledig scherm\"},formatAllRows:function(){return\"Alle\"},formatAutoRefresh:function(){return\"Automatisch vernieuwen\"},formatExport:function(){return\"Exporteer gegevens\"},formatJumpTo:function(){return\"GA\"},formatAdvancedSearch:function(){return\"Geavanceerd zoeken\"},formatAdvancedCloseButton:function(){return\"Sluiten\"},formatFilterControlSwitch:function(){return\"Verberg/Toon controls\"},formatFilterControlSwitchHide:function(){return\"Verberg controls\"},formatFilterControlSwitchShow:function(){return\"Toon controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"nl-NL\"]),o.default.fn.bootstrapTable.locales[\"pl-PL\"]=o.default.fn.bootstrapTable.locales.pl={formatCopyRows:function(){return\"Kopiuj wiersze\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Ładowanie, proszę czekać\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" rekordów na stronę\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Wyświetlanie rekordów od \".concat(t,\" do \").concat(n,\" z \").concat(o,\" (filtered from \").concat(r,\" total rows)\"):\"Wyświetlanie rekordów od \".concat(t,\" do \").concat(n,\" z \").concat(o)},formatSRPaginationPreText:function(){return\"poprzednia strona\"},formatSRPaginationPageText:function(t){return\"z \".concat(t)},formatSRPaginationNextText:function(){return\"następna strona\"},formatDetailPagination:function(t){return\"Wyświetla \".concat(t,\" wierszy\")},formatClearSearch:function(){return\"Wyczyść wyszukiwanie\"},formatSearch:function(){return\"Szukaj\"},formatNoMatches:function(){return\"Niestety, nic nie znaleziono\"},formatPaginationSwitch:function(){return\"Pokaż/ukryj stronicowanie\"},formatPaginationSwitchDown:function(){return\"Pokaż stronicowanie\"},formatPaginationSwitchUp:function(){return\"Ukryj stronicowanie\"},formatRefresh:function(){return\"Odśwież\"},formatToggle:function(){return\"Przełącz\"},formatToggleOn:function(){return\"Pokaż układ karty\"},formatToggleOff:function(){return\"Ukryj układ karty\"},formatColumns:function(){return\"Kolumny\"},formatColumnsToggleAll:function(){return\"Zaznacz wszystko\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Wszystkie\"},formatAutoRefresh:function(){return\"Auto odświeżanie\"},formatExport:function(){return\"Eksport danych\"},formatJumpTo:function(){return\"Przejdź\"},formatAdvancedSearch:function(){return\"Wyszukiwanie zaawansowane\"},formatAdvancedCloseButton:function(){return\"Zamknij\"},formatFilterControlSwitch:function(){return\"Pokaż/Ukryj\"},formatFilterControlSwitchHide:function(){return\"Pokaż\"},formatFilterControlSwitchShow:function(){return\"Ukryj\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"pl-PL\"]),o.default.fn.bootstrapTable.locales[\"pt-BR\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Carregando, aguarde\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" registros por página\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Exibindo \".concat(t,\" até \").concat(n,\" de \").concat(o,\" linhas (filtradas de um total de \").concat(r,\" linhas)\"):\"Exibindo \".concat(t,\" até \").concat(n,\" de \").concat(o,\" linhas\")},formatSRPaginationPreText:function(){return\"página anterior\"},formatSRPaginationPageText:function(t){return\"Para a página \".concat(t)},formatSRPaginationNextText:function(){return\"próxima página\"},formatDetailPagination:function(t){return\"Mostrando \".concat(t,\" linhas\")},formatClearSearch:function(){return\"Limpar Pesquisa\"},formatSearch:function(){return\"Pesquisar\"},formatNoMatches:function(){return\"Nenhum registro encontrado\"},formatPaginationSwitch:function(){return\"Ocultar/Exibir paginação\"},formatPaginationSwitchDown:function(){return\"Mostrar Paginação\"},formatPaginationSwitchUp:function(){return\"Esconder Paginação\"},formatRefresh:function(){return\"Recarregar\"},formatToggle:function(){return\"Alternar\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Colunas\"},formatColumnsToggleAll:function(){return\"Alternar tudo\"},formatFullscreen:function(){return\"Tela cheia\"},formatAllRows:function(){return\"Tudo\"},formatAutoRefresh:function(){return\"Atualização Automática\"},formatExport:function(){return\"Exportar dados\"},formatJumpTo:function(){return\"IR\"},formatAdvancedSearch:function(){return\"Pesquisa Avançada\"},formatAdvancedCloseButton:function(){return\"Fechar\"},formatFilterControlSwitch:function(){return\"Ocultar/Exibir controles\"},formatFilterControlSwitchHide:function(){return\"Ocultar controles\"},formatFilterControlSwitchShow:function(){return\"Exibir controles\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"pt-BR\"]),o.default.fn.bootstrapTable.locales[\"pt-PT\"]=o.default.fn.bootstrapTable.locales.pt={formatCopyRows:function(){return\"Copiar Linhas\"},formatPrint:function(){return\"Imprimir\"},formatLoadingMessage:function(){return\"A carregar, por favor aguarde\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" registos por página\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"A mostrar \".concat(t,\" at&eacute; \").concat(n,\" de \").concat(o,\" linhas (filtered from \").concat(r,\" total rows)\"):\"A mostrar \".concat(t,\" até \").concat(n,\" de \").concat(o,\" linhas\")},formatSRPaginationPreText:function(){return\"página anterior\"},formatSRPaginationPageText:function(t){return\"ir para página \".concat(t)},formatSRPaginationNextText:function(){return\"próxima página\"},formatDetailPagination:function(t){return\"Mostrando \".concat(t,\" linhas\")},formatClearSearch:function(){return\"Limpar Pesquisa\"},formatSearch:function(){return\"Pesquisa\"},formatNoMatches:function(){return\"Nenhum registo encontrado\"},formatPaginationSwitch:function(){return\"Esconder/Mostrar paginação\"},formatPaginationSwitchDown:function(){return\"Mostrar página\"},formatPaginationSwitchUp:function(){return\"Esconder página\"},formatRefresh:function(){return\"Actualizar\"},formatToggle:function(){return\"Alternar\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Colunas\"},formatColumnsToggleAll:function(){return\"Activar tudo\"},formatFullscreen:function(){return\"Ecrã completo\"},formatAllRows:function(){return\"Tudo\"},formatAutoRefresh:function(){return\"Actualização autmática\"},formatExport:function(){return\"Exportar dados\"},formatJumpTo:function(){return\"Avançar\"},formatAdvancedSearch:function(){return\"Pesquisa avançada\"},formatAdvancedCloseButton:function(){return\"Fechar\"},formatFilterControlSwitch:function(){return\"Esconder/Exibir controlos\"},formatFilterControlSwitchHide:function(){return\"Esconder controlos\"},formatFilterControlSwitchShow:function(){return\"Exibir controlos\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"pt-PT\"]),o.default.fn.bootstrapTable.locales[\"ro-RO\"]=o.default.fn.bootstrapTable.locales.ro={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Se incarca, va rugam asteptati\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" inregistrari pe pagina\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Arata de la \".concat(t,\" pana la \").concat(n,\" din \").concat(o,\" randuri (filtered from \").concat(r,\" total rows)\"):\"Arata de la \".concat(t,\" pana la \").concat(n,\" din \").concat(o,\" randuri\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Cauta\"},formatNoMatches:function(){return\"Nu au fost gasite inregistrari\"},formatPaginationSwitch:function(){return\"Ascunde/Arata paginatia\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Reincarca\"},formatToggle:function(){return\"Comuta\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Coloane\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Toate\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"ro-RO\"]),o.default.fn.bootstrapTable.locales[\"ru-RU\"]=o.default.fn.bootstrapTable.locales.ru={formatCopyRows:function(){return\"Скопировать строки\"},formatPrint:function(){return\"Печать\"},formatLoadingMessage:function(){return\"Пожалуйста, подождите, идёт загрузка\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" записей на страницу\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Записи с \".concat(t,\" по \").concat(n,\" из \").concat(o,\" (отфильтровано, всего на сервере \").concat(r,\" записей)\"):\"Записи с \".concat(t,\" по \").concat(n,\" из \").concat(o)},formatSRPaginationPreText:function(){return\"предыдущая страница\"},formatSRPaginationPageText:function(t){return\"перейти к странице \".concat(t)},formatSRPaginationNextText:function(){return\"следующая страница\"},formatDetailPagination:function(t){return\"Загружено \".concat(t,\" строк\")},formatClearSearch:function(){return\"Очистить фильтры\"},formatSearch:function(){return\"Поиск\"},formatNoMatches:function(){return\"Ничего не найдено\"},formatPaginationSwitch:function(){return\"Скрыть/Показать постраничную навигацию\"},formatPaginationSwitchDown:function(){return\"Показать постраничную навигацию\"},formatPaginationSwitchUp:function(){return\"Скрыть постраничную навигацию\"},formatRefresh:function(){return\"Обновить\"},formatToggle:function(){return\"Переключить\"},formatToggleOn:function(){return\"Показать записи в виде карточек\"},formatToggleOff:function(){return\"Табличный режим просмотра\"},formatColumns:function(){return\"Колонки\"},formatColumnsToggleAll:function(){return\"Выбрать все\"},formatFullscreen:function(){return\"Полноэкранный режим\"},formatAllRows:function(){return\"Все\"},formatAutoRefresh:function(){return\"Автоматическое обновление\"},formatExport:function(){return\"Экспортировать данные\"},formatJumpTo:function(){return\"Стр.\"},formatAdvancedSearch:function(){return\"Расширенный поиск\"},formatAdvancedCloseButton:function(){return\"Закрыть\"},formatFilterControlSwitch:function(){return\"Скрыть/Показать панель инструментов\"},formatFilterControlSwitchHide:function(){return\"Скрыть панель инструментов\"},formatFilterControlSwitchShow:function(){return\"Показать панель инструментов\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"ru-RU\"]),o.default.fn.bootstrapTable.locales[\"sk-SK\"]=o.default.fn.bootstrapTable.locales.sk={formatCopyRows:function(){return\"Skopírovať riadky\"},formatPrint:function(){return\"Vytlačiť\"},formatLoadingMessage:function(){return\"Prosím čakajte\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" záznamov na stranu\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Zobrazená \".concat(t,\". - \").concat(n,\". položka z celkových \").concat(o,\" (filtered from \").concat(r,\" total rows)\"):\"Zobrazená \".concat(t,\". - \").concat(n,\". položka z celkových \").concat(o)},formatSRPaginationPreText:function(){return\"Predchádzajúca strana\"},formatSRPaginationPageText:function(t){return\"na stranu \".concat(t)},formatSRPaginationNextText:function(){return\"Nasledujúca strana\"},formatDetailPagination:function(t){return\"Zobrazuje sa \".concat(t,\" riadkov\")},formatClearSearch:function(){return\"Odstráň filtre\"},formatSearch:function(){return\"Vyhľadávanie\"},formatNoMatches:function(){return\"Nenájdená žiadna vyhovujúca položka\"},formatPaginationSwitch:function(){return\"Skry/Zobraz stránkovanie\"},formatPaginationSwitchDown:function(){return\"Zobraziť stránkovanie\"},formatPaginationSwitchUp:function(){return\"Skryť stránkovanie\"},formatRefresh:function(){return\"Obnoviť\"},formatToggle:function(){return\"Prepni\"},formatToggleOn:function(){return\"Zobraziť kartové zobrazenie\"},formatToggleOff:function(){return\"skryť kartové zobrazenie\"},formatColumns:function(){return\"Stĺpce\"},formatColumnsToggleAll:function(){return\"Prepnúť všetky\"},formatFullscreen:function(){return\"Celá obrazovka\"},formatAllRows:function(){return\"Všetky\"},formatAutoRefresh:function(){return\"Automatické obnovenie\"},formatExport:function(){return\"Exportuj dáta\"},formatJumpTo:function(){return\"Ísť\"},formatAdvancedSearch:function(){return\"Pokročilé vyhľadávanie\"},formatAdvancedCloseButton:function(){return\"Zatvoriť\"},formatFilterControlSwitch:function(){return\"Zobraziť/Skryť tlačidlá\"},formatFilterControlSwitchHide:function(){return\"Skryť tlačidlá\"},formatFilterControlSwitchShow:function(){return\"Zobraziť tlačidlá\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"sk-SK\"]),o.default.fn.bootstrapTable.locales[\"sr-Cyrl-RS\"]=o.default.fn.bootstrapTable.locales.sr={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Молим сачекај\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" редова по страни\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Приказано \".concat(t,\". - \").concat(n,\". од укупног броја редова \").concat(o,\" (филтрирано од \").concat(r,\")\"):\"Приказано \".concat(t,\". - \").concat(n,\". од укупног броја редова \").concat(o)},formatSRPaginationPreText:function(){return\"претходна страна\"},formatSRPaginationPageText:function(t){return\"на страну \".concat(t)},formatSRPaginationNextText:function(){return\"следећа страна\"},formatDetailPagination:function(t){return\"Приказано \".concat(t,\" редова\")},formatClearSearch:function(){return\"Обриши претрагу\"},formatSearch:function(){return\"Пронађи\"},formatNoMatches:function(){return\"Није пронађен ни један податак\"},formatPaginationSwitch:function(){return\"Прикажи/сакриј пагинацију\"},formatPaginationSwitchDown:function(){return\"Прикажи пагинацију\"},formatPaginationSwitchUp:function(){return\"Сакриј пагинацију\"},formatRefresh:function(){return\"Освежи\"},formatToggle:function(){return\"Промени приказ\"},formatToggleOn:function(){return\"Прикажи картице\"},formatToggleOff:function(){return\"Сакриј картице\"},formatColumns:function(){return\"Колоне\"},formatColumnsToggleAll:function(){return\"Прикажи/сакриј све\"},formatFullscreen:function(){return\"Цео екран\"},formatAllRows:function(){return\"Све\"},formatAutoRefresh:function(){return\"Аутоматско освежавање\"},formatExport:function(){return\"Извези податке\"},formatJumpTo:function(){return\"Иди\"},formatAdvancedSearch:function(){return\"Напредна претрага\"},formatAdvancedCloseButton:function(){return\"Затвори\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"sr-Cyrl-RS\"]),o.default.fn.bootstrapTable.locales[\"sr-Latn-RS\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Molim sačekaj\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" redova po strani\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Prikazano \".concat(t,\". - \").concat(n,\". od ukupnog broja redova \").concat(o,\" (filtrirano od \").concat(r,\")\"):\"Prikazano \".concat(t,\". - \").concat(n,\". od ukupnog broja redova \").concat(o)},formatSRPaginationPreText:function(){return\"prethodna strana\"},formatSRPaginationPageText:function(t){return\"na stranu \".concat(t)},formatSRPaginationNextText:function(){return\"sledeća strana\"},formatDetailPagination:function(t){return\"Prikazano \".concat(t,\" redova\")},formatClearSearch:function(){return\"Obriši pretragu\"},formatSearch:function(){return\"Pronađi\"},formatNoMatches:function(){return\"Nije pronađen ni jedan podatak\"},formatPaginationSwitch:function(){return\"Prikaži/sakrij paginaciju\"},formatPaginationSwitchDown:function(){return\"Prikaži paginaciju\"},formatPaginationSwitchUp:function(){return\"Sakrij paginaciju\"},formatRefresh:function(){return\"Osveži\"},formatToggle:function(){return\"Promeni prikaz\"},formatToggleOn:function(){return\"Prikaži kartice\"},formatToggleOff:function(){return\"Sakrij kartice\"},formatColumns:function(){return\"Kolone\"},formatColumnsToggleAll:function(){return\"Prikaži/sakrij sve\"},formatFullscreen:function(){return\"Ceo ekran\"},formatAllRows:function(){return\"Sve\"},formatAutoRefresh:function(){return\"Automatsko osvežavanje\"},formatExport:function(){return\"Izvezi podatke\"},formatJumpTo:function(){return\"Idi\"},formatAdvancedSearch:function(){return\"Napredna pretraga\"},formatAdvancedCloseButton:function(){return\"Zatvori\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"sr-Latn-RS\"]),o.default.fn.bootstrapTable.locales[\"sv-SE\"]=o.default.fn.bootstrapTable.locales.sv={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Laddar, vänligen vänta\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" rader per sida\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Visa \".concat(t,\" till \").concat(n,\" av \").concat(o,\" rader (filtered from \").concat(r,\" total rows)\"):\"Visa \".concat(t,\" till \").concat(n,\" av \").concat(o,\" rader\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Sök\"},formatNoMatches:function(){return\"Inga matchande resultat funna.\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Uppdatera\"},formatToggle:function(){return\"Skifta\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"kolumn\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"sv-SE\"]),o.default.fn.bootstrapTable.locales[\"th-TH\"]=o.default.fn.bootstrapTable.locales.th={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"กำลังโหลดข้อมูล, กรุณารอสักครู่\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" รายการต่อหน้า\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"รายการที่ \".concat(t,\" ถึง \").concat(n,\" จากทั้งหมด \").concat(o,\" รายการ (filtered from \").concat(r,\" total rows)\"):\"รายการที่ \".concat(t,\" ถึง \").concat(n,\" จากทั้งหมด \").concat(o,\" รายการ\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"ค้นหา\"},formatNoMatches:function(){return\"ไม่พบรายการที่ค้นหา !\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"รีเฟรส\"},formatToggle:function(){return\"สลับมุมมอง\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"คอลัมน์\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"th-TH\"]),o.default.fn.bootstrapTable.locales[\"tr-TR\"]=o.default.fn.bootstrapTable.locales.tr={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Yükleniyor, lütfen bekleyin\"},formatRecordsPerPage:function(t){return\"Sayfa başına \".concat(t,\" kayıt.\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"\".concat(o,\" kayıttan \").concat(t,\"-\").concat(n,\" arası gösteriliyor (filtered from \").concat(r,\" total rows).\"):\"\".concat(o,\" kayıttan \").concat(t,\"-\").concat(n,\" arası gösteriliyor.\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Ara\"},formatNoMatches:function(){return\"Eşleşen kayıt bulunamadı.\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Yenile\"},formatToggle:function(){return\"Değiştir\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Sütunlar\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Tüm Satırlar\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"tr-TR\"]),o.default.fn.bootstrapTable.locales[\"uk-UA\"]=o.default.fn.bootstrapTable.locales.uk={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Завантаження, будь ласка, зачекайте\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" записів на сторінку\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Показано з \".concat(t,\" по \").concat(n,\". Всього: \").concat(o,\" (filtered from \").concat(r,\" total rows)\"):\"Показано з \".concat(t,\" по \").concat(n,\". Всього: \").concat(o)},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Очистити фільтри\"},formatSearch:function(){return\"Пошук\"},formatNoMatches:function(){return\"Не знайдено жодного запису\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Оновити\"},formatToggle:function(){return\"Змінити\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Стовпці\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"uk-UA\"]),o.default.fn.bootstrapTable.locales[\"ur-PK\"]=o.default.fn.bootstrapTable.locales.ur={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"براۓ مہربانی انتظار کیجئے\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" ریکارڈز فی صفہ \")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"دیکھیں \".concat(t,\" سے \").concat(n,\" کے \").concat(o,\"ریکارڈز (filtered from \").concat(r,\" total rows)\"):\"دیکھیں \".concat(t,\" سے \").concat(n,\" کے \").concat(o,\"ریکارڈز\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"تلاش\"},formatNoMatches:function(){return\"کوئی ریکارڈ نہیں ملا\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"تازہ کریں\"},formatToggle:function(){return\"تبدیل کریں\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"کالم\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"ur-PK\"]),o.default.fn.bootstrapTable.locales[\"uz-Latn-UZ\"]=o.default.fn.bootstrapTable.locales.uz={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Yuklanyapti, iltimos kuting\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" qator har sahifada\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Ko'rsatypati \".concat(t,\" dan \").concat(n,\" gacha \").concat(o,\" qatorlarni (filtered from \").concat(r,\" total rows)\"):\"Ko'rsatypati \".concat(t,\" dan \").concat(n,\" gacha \").concat(o,\" qatorlarni\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Filtrlarni tozalash\"},formatSearch:function(){return\"Qidirish\"},formatNoMatches:function(){return\"Hech narsa topilmadi\"},formatPaginationSwitch:function(){return\"Sahifalashni yashirish/ko'rsatish\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Yangilash\"},formatToggle:function(){return\"Ko'rinish\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Ustunlar\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Hammasi\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Eksport\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"uz-Latn-UZ\"]),o.default.fn.bootstrapTable.locales[\"vi-VN\"]=o.default.fn.bootstrapTable.locales.vi={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Đang tải\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" bản ghi mỗi trang\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Hiển thị từ trang \".concat(t,\" đến \").concat(n,\" của \").concat(o,\" bảng ghi (filtered from \").concat(r,\" total rows)\"):\"Hiển thị từ trang \".concat(t,\" đến \").concat(n,\" của \").concat(o,\" bảng ghi\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Tìm kiếm\"},formatNoMatches:function(){return\"Không có dữ liệu\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Refresh\"},formatToggle:function(){return\"Toggle\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Columns\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"vi-VN\"]),o.default.fn.bootstrapTable.locales[\"zh-CN\"]=o.default.fn.bootstrapTable.locales.zh={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"正在努力地加载数据中，请稍候\"},formatRecordsPerPage:function(t){return\"每页显示 \".concat(t,\" 条记录\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"显示第 \".concat(t,\" 到第 \").concat(n,\" 条记录，总共 \").concat(o,\" 条记录（从 \").concat(r,\" 总记录中过滤）\"):\"显示第 \".concat(t,\" 到第 \").concat(n,\" 条记录，总共 \").concat(o,\" 条记录\")},formatSRPaginationPreText:function(){return\"上一页\"},formatSRPaginationPageText:function(t){return\"第\".concat(t,\"页\")},formatSRPaginationNextText:function(){return\"下一页\"},formatDetailPagination:function(t){return\"总共 \".concat(t,\" 条记录\")},formatClearSearch:function(){return\"清空过滤\"},formatSearch:function(){return\"搜索\"},formatNoMatches:function(){return\"没有找到匹配的记录\"},formatPaginationSwitch:function(){return\"隐藏/显示分页\"},formatPaginationSwitchDown:function(){return\"显示分页\"},formatPaginationSwitchUp:function(){return\"隐藏分页\"},formatRefresh:function(){return\"刷新\"},formatToggle:function(){return\"切换\"},formatToggleOn:function(){return\"显示卡片视图\"},formatToggleOff:function(){return\"隐藏卡片视图\"},formatColumns:function(){return\"列\"},formatColumnsToggleAll:function(){return\"切换所有\"},formatFullscreen:function(){return\"全屏\"},formatAllRows:function(){return\"所有\"},formatAutoRefresh:function(){return\"自动刷新\"},formatExport:function(){return\"导出数据\"},formatJumpTo:function(){return\"跳转\"},formatAdvancedSearch:function(){return\"高级搜索\"},formatAdvancedCloseButton:function(){return\"关闭\"},formatFilterControlSwitch:function(){return\"隐藏/显示过滤控制\"},formatFilterControlSwitchHide:function(){return\"隐藏过滤控制\"},formatFilterControlSwitchShow:function(){return\"显示过滤控制\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"zh-CN\"]),o.default.fn.bootstrapTable.locales[\"zh-TW\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"正在努力地載入資料，請稍候\"},formatRecordsPerPage:function(t){return\"每頁顯示 \".concat(t,\" 項記錄\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"顯示第 \".concat(t,\" 到第 \").concat(n,\" 項記錄，總共 \").concat(o,\" 項記錄（從 \").concat(r,\" 總記錄中過濾）\"):\"顯示第 \".concat(t,\" 到第 \").concat(n,\" 項記錄，總共 \").concat(o,\" 項記錄\")},formatSRPaginationPreText:function(){return\"上一頁\"},formatSRPaginationPageText:function(t){return\"第\".concat(t,\"頁\")},formatSRPaginationNextText:function(){return\"下一頁\"},formatDetailPagination:function(t){return\"總共 \".concat(t,\" 項記錄\")},formatClearSearch:function(){return\"清空過濾\"},formatSearch:function(){return\"搜尋\"},formatNoMatches:function(){return\"沒有找到符合的結果\"},formatPaginationSwitch:function(){return\"隱藏/顯示分頁\"},formatPaginationSwitchDown:function(){return\"顯示分頁\"},formatPaginationSwitchUp:function(){return\"隱藏分頁\"},formatRefresh:function(){return\"重新整理\"},formatToggle:function(){return\"切換\"},formatToggleOn:function(){return\"顯示卡片視圖\"},formatToggleOff:function(){return\"隱藏卡片視圖\"},formatColumns:function(){return\"列\"},formatColumnsToggleAll:function(){return\"切換所有\"},formatFullscreen:function(){return\"全屏\"},formatAllRows:function(){return\"所有\"},formatAutoRefresh:function(){return\"自動刷新\"},formatExport:function(){return\"導出數據\"},formatJumpTo:function(){return\"跳轉\"},formatAdvancedSearch:function(){return\"高級搜尋\"},formatAdvancedCloseButton:function(){return\"關閉\"},formatFilterControlSwitch:function(){return\"隱藏/顯示過濾控制\"},formatFilterControlSwitchHide:function(){return\"隱藏過濾控制\"},formatFilterControlSwitchShow:function(){return\"顯示過濾控制\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"zh-TW\"])}));


/***/ }),

/***/ \"./node_modules/bootstrap-table/dist/bootstrap-table.js\":
/*!**************************************************************!*\\
  !*** ./node_modules/bootstrap-table/dist/bootstrap-table.js ***!
  \\**************************************************************/
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {

(function (global, factory) {
   true ? module.exports = factory(__webpack_require__(/*! jquery */ \"./node_modules/jquery/dist/jquery.js\")) :
  0;
}(this, (function (\$) { 'use strict';

  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

  var \$__default = /*#__PURE__*/_interopDefaultLegacy(\$);

  function _typeof(obj) {
    \"@babel/helpers - typeof\";

    if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") {
      _typeof = function (obj) {
        return typeof obj;
      };
    } else {
      _typeof = function (obj) {
        return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;
      };
    }

    return _typeof(obj);
  }

  function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError(\"Cannot call a class as a 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);
    }
  }

  function _createClass(Constructor, protoProps, staticProps) {
    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
    if (staticProps) _defineProperties(Constructor, staticProps);
    return Constructor;
  }

  function _slicedToArray(arr, i) {
    return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
  }

  function _toConsumableArray(arr) {
    return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
  }

  function _arrayWithoutHoles(arr) {
    if (Array.isArray(arr)) return _arrayLikeToArray(arr);
  }

  function _arrayWithHoles(arr) {
    if (Array.isArray(arr)) return arr;
  }

  function _iterableToArray(iter) {
    if (typeof Symbol !== \"undefined\" && Symbol.iterator in Object(iter)) return Array.from(iter);
  }

  function _iterableToArrayLimit(arr, i) {
    if (typeof Symbol === \"undefined\" || !(Symbol.iterator in Object(arr))) return;
    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\"] != null) _i[\"return\"]();
      } finally {
        if (_d) throw _e;
      }
    }

    return _arr;
  }

  function _unsupportedIterableToArray(o, minLen) {
    if (!o) return;
    if (typeof o === \"string\") return _arrayLikeToArray(o, minLen);
    var n = Object.prototype.toString.call(o).slice(8, -1);
    if (n === \"Object\" && o.constructor) n = o.constructor.name;
    if (n === \"Map\" || n === \"Set\") return Array.from(o);
    if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array\$/.test(n)) return _arrayLikeToArray(o, minLen);
  }

  function _arrayLikeToArray(arr, len) {
    if (len == null || len > arr.length) len = arr.length;

    for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];

    return arr2;
  }

  function _nonIterableSpread() {
    throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");
  }

  function _nonIterableRest() {
    throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");
  }

  function _createForOfIteratorHelper(o, allowArrayLike) {
    var it;

    if (typeof Symbol === \"undefined\" || o[Symbol.iterator] == null) {
      if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === \"number\") {
        if (it) o = it;
        var i = 0;

        var F = function () {};

        return {
          s: F,
          n: function () {
            if (i >= o.length) return {
              done: true
            };
            return {
              done: false,
              value: o[i++]
            };
          },
          e: function (e) {
            throw e;
          },
          f: F
        };
      }

      throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");
    }

    var normalCompletion = true,
        didErr = false,
        err;
    return {
      s: function () {
        it = o[Symbol.iterator]();
      },
      n: function () {
        var step = it.next();
        normalCompletion = step.done;
        return step;
      },
      e: function (e) {
        didErr = true;
        err = e;
      },
      f: function () {
        try {
          if (!normalCompletion && it.return != null) it.return();
        } finally {
          if (didErr) throw err;
        }
      }
    };
  }

  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof __webpack_require__.g !== 'undefined' ? __webpack_require__.g : typeof self !== 'undefined' ? self : {};

  function createCommonjsModule(fn, module) {
  \treturn module = { exports: {} }, fn(module, module.exports), module.exports;
  }

  var check = function (it) {
    return it && it.Math == Math && it;
  };

  // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
  var global_1 =
    /* global globalThis -- safe */
    check(typeof globalThis == 'object' && globalThis) ||
    check(typeof window == 'object' && window) ||
    check(typeof self == 'object' && self) ||
    check(typeof commonjsGlobal == 'object' && commonjsGlobal) ||
    // eslint-disable-next-line no-new-func -- fallback
    (function () { return this; })() || Function('return this')();

  var fails = function (exec) {
    try {
      return !!exec();
    } catch (error) {
      return true;
    }
  };

  // Detect IE8's incomplete defineProperty implementation
  var descriptors = !fails(function () {
    return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] != 7;
  });

  var nativePropertyIsEnumerable = {}.propertyIsEnumerable;
  var getOwnPropertyDescriptor\$4 = Object.getOwnPropertyDescriptor;

  // Nashorn ~ JDK8 bug
  var NASHORN_BUG = getOwnPropertyDescriptor\$4 && !nativePropertyIsEnumerable.call({ 1: 2 }, 1);

  // `Object.prototype.propertyIsEnumerable` method implementation
  // https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
  var f\$4 = NASHORN_BUG ? function propertyIsEnumerable(V) {
    var descriptor = getOwnPropertyDescriptor\$4(this, V);
    return !!descriptor && descriptor.enumerable;
  } : nativePropertyIsEnumerable;

  var objectPropertyIsEnumerable = {
  \tf: f\$4
  };

  var createPropertyDescriptor = function (bitmap, value) {
    return {
      enumerable: !(bitmap & 1),
      configurable: !(bitmap & 2),
      writable: !(bitmap & 4),
      value: value
    };
  };

  var toString = {}.toString;

  var classofRaw = function (it) {
    return toString.call(it).slice(8, -1);
  };

  var split = ''.split;

  // fallback for non-array-like ES3 and non-enumerable old V8 strings
  var indexedObject = fails(function () {
    // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
    // eslint-disable-next-line no-prototype-builtins -- safe
    return !Object('z').propertyIsEnumerable(0);
  }) ? function (it) {
    return classofRaw(it) == 'String' ? split.call(it, '') : Object(it);
  } : Object;

  // `RequireObjectCoercible` abstract operation
  // https://tc39.es/ecma262/#sec-requireobjectcoercible
  var requireObjectCoercible = function (it) {
    if (it == undefined) throw TypeError(\"Can't call method on \" + it);
    return it;
  };

  // toObject with fallback for non-array-like ES3 strings



  var toIndexedObject = function (it) {
    return indexedObject(requireObjectCoercible(it));
  };

  var isObject = function (it) {
    return typeof it === 'object' ? it !== null : typeof it === 'function';
  };

  // `ToPrimitive` abstract operation
  // https://tc39.es/ecma262/#sec-toprimitive
  // instead of the ES6 spec version, we didn't implement @@toPrimitive case
  // and the second argument - flag - preferred type is a string
  var toPrimitive = function (input, PREFERRED_STRING) {
    if (!isObject(input)) return input;
    var fn, val;
    if (PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val;
    if (typeof (fn = input.valueOf) == 'function' && !isObject(val = fn.call(input))) return val;
    if (!PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val;
    throw TypeError(\"Can't convert object to primitive value\");
  };

  var hasOwnProperty = {}.hasOwnProperty;

  var has\$1 = function (it, key) {
    return hasOwnProperty.call(it, key);
  };

  var document\$1 = global_1.document;
  // typeof document.createElement is 'object' in old IE
  var EXISTS = isObject(document\$1) && isObject(document\$1.createElement);

  var documentCreateElement = function (it) {
    return EXISTS ? document\$1.createElement(it) : {};
  };

  // Thank's IE8 for his funny defineProperty
  var ie8DomDefine = !descriptors && !fails(function () {
    return Object.defineProperty(documentCreateElement('div'), 'a', {
      get: function () { return 7; }
    }).a != 7;
  });

  var nativeGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;

  // `Object.getOwnPropertyDescriptor` method
  // https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
  var f\$3 = descriptors ? nativeGetOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) {
    O = toIndexedObject(O);
    P = toPrimitive(P, true);
    if (ie8DomDefine) try {
      return nativeGetOwnPropertyDescriptor(O, P);
    } catch (error) { /* empty */ }
    if (has\$1(O, P)) return createPropertyDescriptor(!objectPropertyIsEnumerable.f.call(O, P), O[P]);
  };

  var objectGetOwnPropertyDescriptor = {
  \tf: f\$3
  };

  var anObject = function (it) {
    if (!isObject(it)) {
      throw TypeError(String(it) + ' is not an object');
    } return it;
  };

  var nativeDefineProperty = Object.defineProperty;

  // `Object.defineProperty` method
  // https://tc39.es/ecma262/#sec-object.defineproperty
  var f\$2 = descriptors ? nativeDefineProperty : function defineProperty(O, P, Attributes) {
    anObject(O);
    P = toPrimitive(P, true);
    anObject(Attributes);
    if (ie8DomDefine) try {
      return nativeDefineProperty(O, P, Attributes);
    } catch (error) { /* empty */ }
    if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported');
    if ('value' in Attributes) O[P] = Attributes.value;
    return O;
  };

  var objectDefineProperty = {
  \tf: f\$2
  };

  var createNonEnumerableProperty = descriptors ? function (object, key, value) {
    return objectDefineProperty.f(object, key, createPropertyDescriptor(1, value));
  } : function (object, key, value) {
    object[key] = value;
    return object;
  };

  var setGlobal = function (key, value) {
    try {
      createNonEnumerableProperty(global_1, key, value);
    } catch (error) {
      global_1[key] = value;
    } return value;
  };

  var SHARED = '__core-js_shared__';
  var store\$1 = global_1[SHARED] || setGlobal(SHARED, {});

  var sharedStore = store\$1;

  var functionToString = Function.toString;

  // this helper broken in `3.4.1-3.4.4`, so we can't use `shared` helper
  if (typeof sharedStore.inspectSource != 'function') {
    sharedStore.inspectSource = function (it) {
      return functionToString.call(it);
    };
  }

  var inspectSource = sharedStore.inspectSource;

  var WeakMap\$1 = global_1.WeakMap;

  var nativeWeakMap = typeof WeakMap\$1 === 'function' && /native code/.test(inspectSource(WeakMap\$1));

  var shared = createCommonjsModule(function (module) {
  (module.exports = function (key, value) {
    return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {});
  })('versions', []).push({
    version: '3.9.1',
    mode: 'global',
    copyright: '© 2021 Denis Pushkarev (zloirock.ru)'
  });
  });

  var id = 0;
  var postfix = Math.random();

  var uid = function (key) {
    return 'Symbol(' + String(key === undefined ? '' : key) + ')_' + (++id + postfix).toString(36);
  };

  var keys\$2 = shared('keys');

  var sharedKey = function (key) {
    return keys\$2[key] || (keys\$2[key] = uid(key));
  };

  var hiddenKeys\$1 = {};

  var WeakMap = global_1.WeakMap;
  var set, get, has;

  var enforce = function (it) {
    return has(it) ? get(it) : set(it, {});
  };

  var getterFor = function (TYPE) {
    return function (it) {
      var state;
      if (!isObject(it) || (state = get(it)).type !== TYPE) {
        throw TypeError('Incompatible receiver, ' + TYPE + ' required');
      } return state;
    };
  };

  if (nativeWeakMap) {
    var store = sharedStore.state || (sharedStore.state = new WeakMap());
    var wmget = store.get;
    var wmhas = store.has;
    var wmset = store.set;
    set = function (it, metadata) {
      metadata.facade = it;
      wmset.call(store, it, metadata);
      return metadata;
    };
    get = function (it) {
      return wmget.call(store, it) || {};
    };
    has = function (it) {
      return wmhas.call(store, it);
    };
  } else {
    var STATE = sharedKey('state');
    hiddenKeys\$1[STATE] = true;
    set = function (it, metadata) {
      metadata.facade = it;
      createNonEnumerableProperty(it, STATE, metadata);
      return metadata;
    };
    get = function (it) {
      return has\$1(it, STATE) ? it[STATE] : {};
    };
    has = function (it) {
      return has\$1(it, STATE);
    };
  }

  var internalState = {
    set: set,
    get: get,
    has: has,
    enforce: enforce,
    getterFor: getterFor
  };

  var redefine = createCommonjsModule(function (module) {
  var getInternalState = internalState.get;
  var enforceInternalState = internalState.enforce;
  var TEMPLATE = String(String).split('String');

  (module.exports = function (O, key, value, options) {
    var unsafe = options ? !!options.unsafe : false;
    var simple = options ? !!options.enumerable : false;
    var noTargetGet = options ? !!options.noTargetGet : false;
    var state;
    if (typeof value == 'function') {
      if (typeof key == 'string' && !has\$1(value, 'name')) {
        createNonEnumerableProperty(value, 'name', key);
      }
      state = enforceInternalState(value);
      if (!state.source) {
        state.source = TEMPLATE.join(typeof key == 'string' ? key : '');
      }
    }
    if (O === global_1) {
      if (simple) O[key] = value;
      else setGlobal(key, value);
      return;
    } else if (!unsafe) {
      delete O[key];
    } else if (!noTargetGet && O[key]) {
      simple = true;
    }
    if (simple) O[key] = value;
    else createNonEnumerableProperty(O, key, value);
  // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
  })(Function.prototype, 'toString', function toString() {
    return typeof this == 'function' && getInternalState(this).source || inspectSource(this);
  });
  });

  var path = global_1;

  var aFunction\$1 = function (variable) {
    return typeof variable == 'function' ? variable : undefined;
  };

  var getBuiltIn = function (namespace, method) {
    return arguments.length < 2 ? aFunction\$1(path[namespace]) || aFunction\$1(global_1[namespace])
      : path[namespace] && path[namespace][method] || global_1[namespace] && global_1[namespace][method];
  };

  var ceil = Math.ceil;
  var floor\$1 = Math.floor;

  // `ToInteger` abstract operation
  // https://tc39.es/ecma262/#sec-tointeger
  var toInteger = function (argument) {
    return isNaN(argument = +argument) ? 0 : (argument > 0 ? floor\$1 : ceil)(argument);
  };

  var min\$6 = Math.min;

  // `ToLength` abstract operation
  // https://tc39.es/ecma262/#sec-tolength
  var toLength = function (argument) {
    return argument > 0 ? min\$6(toInteger(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991
  };

  var max\$3 = Math.max;
  var min\$5 = Math.min;

  // Helper for a popular repeating case of the spec:
  // Let integer be ? ToInteger(index).
  // If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length).
  var toAbsoluteIndex = function (index, length) {
    var integer = toInteger(index);
    return integer < 0 ? max\$3(integer + length, 0) : min\$5(integer, length);
  };

  // `Array.prototype.{ indexOf, includes }` methods implementation
  var createMethod\$4 = function (IS_INCLUDES) {
    return function (\$this, el, fromIndex) {
      var O = toIndexedObject(\$this);
      var length = toLength(O.length);
      var index = toAbsoluteIndex(fromIndex, length);
      var value;
      // Array#includes uses SameValueZero equality algorithm
      // eslint-disable-next-line no-self-compare -- NaN check
      if (IS_INCLUDES && el != el) while (length > index) {
        value = O[index++];
        // eslint-disable-next-line no-self-compare -- NaN check
        if (value != value) return true;
      // Array#indexOf ignores holes, Array#includes - not
      } else for (;length > index; index++) {
        if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
      } return !IS_INCLUDES && -1;
    };
  };

  var arrayIncludes = {
    // `Array.prototype.includes` method
    // https://tc39.es/ecma262/#sec-array.prototype.includes
    includes: createMethod\$4(true),
    // `Array.prototype.indexOf` method
    // https://tc39.es/ecma262/#sec-array.prototype.indexof
    indexOf: createMethod\$4(false)
  };

  var indexOf = arrayIncludes.indexOf;


  var objectKeysInternal = function (object, names) {
    var O = toIndexedObject(object);
    var i = 0;
    var result = [];
    var key;
    for (key in O) !has\$1(hiddenKeys\$1, key) && has\$1(O, key) && result.push(key);
    // Don't enum bug & hidden keys
    while (names.length > i) if (has\$1(O, key = names[i++])) {
      ~indexOf(result, key) || result.push(key);
    }
    return result;
  };

  // IE8- don't enum bug keys
  var enumBugKeys = [
    'constructor',
    'hasOwnProperty',
    'isPrototypeOf',
    'propertyIsEnumerable',
    'toLocaleString',
    'toString',
    'valueOf'
  ];

  var hiddenKeys = enumBugKeys.concat('length', 'prototype');

  // `Object.getOwnPropertyNames` method
  // https://tc39.es/ecma262/#sec-object.getownpropertynames
  var f\$1 = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
    return objectKeysInternal(O, hiddenKeys);
  };

  var objectGetOwnPropertyNames = {
  \tf: f\$1
  };

  var f = Object.getOwnPropertySymbols;

  var objectGetOwnPropertySymbols = {
  \tf: f
  };

  // all object keys, includes non-enumerable and symbols
  var ownKeys = getBuiltIn('Reflect', 'ownKeys') || function ownKeys(it) {
    var keys = objectGetOwnPropertyNames.f(anObject(it));
    var getOwnPropertySymbols = objectGetOwnPropertySymbols.f;
    return getOwnPropertySymbols ? keys.concat(getOwnPropertySymbols(it)) : keys;
  };

  var copyConstructorProperties = function (target, source) {
    var keys = ownKeys(source);
    var defineProperty = objectDefineProperty.f;
    var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f;
    for (var i = 0; i < keys.length; i++) {
      var key = keys[i];
      if (!has\$1(target, key)) defineProperty(target, key, getOwnPropertyDescriptor(source, key));
    }
  };

  var replacement = /#|\\.prototype\\./;

  var isForced = function (feature, detection) {
    var value = data[normalize(feature)];
    return value == POLYFILL ? true
      : value == NATIVE ? false
      : typeof detection == 'function' ? fails(detection)
      : !!detection;
  };

  var normalize = isForced.normalize = function (string) {
    return String(string).replace(replacement, '.').toLowerCase();
  };

  var data = isForced.data = {};
  var NATIVE = isForced.NATIVE = 'N';
  var POLYFILL = isForced.POLYFILL = 'P';

  var isForced_1 = isForced;

  var getOwnPropertyDescriptor\$3 = objectGetOwnPropertyDescriptor.f;






  /*
    options.target      - name of the target object
    options.global      - target is the global object
    options.stat        - export as static methods of target
    options.proto       - export as prototype methods of target
    options.real        - real prototype method for the `pure` version
    options.forced      - export even if the native feature is available
    options.bind        - bind methods to the target, required for the `pure` version
    options.wrap        - wrap constructors to preventing global pollution, required for the `pure` version
    options.unsafe      - use the simple assignment of property instead of delete + defineProperty
    options.sham        - add a flag to not completely full polyfills
    options.enumerable  - export as enumerable property
    options.noTargetGet - prevent calling a getter on target
  */
  var _export = function (options, source) {
    var TARGET = options.target;
    var GLOBAL = options.global;
    var STATIC = options.stat;
    var FORCED, target, key, targetProperty, sourceProperty, descriptor;
    if (GLOBAL) {
      target = global_1;
    } else if (STATIC) {
      target = global_1[TARGET] || setGlobal(TARGET, {});
    } else {
      target = (global_1[TARGET] || {}).prototype;
    }
    if (target) for (key in source) {
      sourceProperty = source[key];
      if (options.noTargetGet) {
        descriptor = getOwnPropertyDescriptor\$3(target, key);
        targetProperty = descriptor && descriptor.value;
      } else targetProperty = target[key];
      FORCED = isForced_1(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced);
      // contained in target
      if (!FORCED && targetProperty !== undefined) {
        if (typeof sourceProperty === typeof targetProperty) continue;
        copyConstructorProperties(sourceProperty, targetProperty);
      }
      // add a flag to not completely full polyfills
      if (options.sham || (targetProperty && targetProperty.sham)) {
        createNonEnumerableProperty(sourceProperty, 'sham', true);
      }
      // extend global
      redefine(target, key, sourceProperty, options);
    }
  };

  // a string of all valid unicode whitespaces
  var whitespaces = '\\u0009\\u000A\\u000B\\u000C\\u000D\\u0020\\u00A0\\u1680\\u2000\\u2001\\u2002' +
    '\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\u2028\\u2029\\uFEFF';

  var whitespace = '[' + whitespaces + ']';
  var ltrim = RegExp('^' + whitespace + whitespace + '*');
  var rtrim = RegExp(whitespace + whitespace + '*\$');

  // `String.prototype.{ trim, trimStart, trimEnd, trimLeft, trimRight }` methods implementation
  var createMethod\$3 = function (TYPE) {
    return function (\$this) {
      var string = String(requireObjectCoercible(\$this));
      if (TYPE & 1) string = string.replace(ltrim, '');
      if (TYPE & 2) string = string.replace(rtrim, '');
      return string;
    };
  };

  var stringTrim = {
    // `String.prototype.{ trimLeft, trimStart }` methods
    // https://tc39.es/ecma262/#sec-string.prototype.trimstart
    start: createMethod\$3(1),
    // `String.prototype.{ trimRight, trimEnd }` methods
    // https://tc39.es/ecma262/#sec-string.prototype.trimend
    end: createMethod\$3(2),
    // `String.prototype.trim` method
    // https://tc39.es/ecma262/#sec-string.prototype.trim
    trim: createMethod\$3(3)
  };

  var non = '\\u200B\\u0085\\u180E';

  // check that a method works with the correct list
  // of whitespaces and has a correct name
  var stringTrimForced = function (METHOD_NAME) {
    return fails(function () {
      return !!whitespaces[METHOD_NAME]() || non[METHOD_NAME]() != non || whitespaces[METHOD_NAME].name !== METHOD_NAME;
    });
  };

  var \$trim = stringTrim.trim;


  // `String.prototype.trim` method
  // https://tc39.es/ecma262/#sec-string.prototype.trim
  _export({ target: 'String', proto: true, forced: stringTrimForced('trim') }, {
    trim: function trim() {
      return \$trim(this);
    }
  });

  var arrayMethodIsStrict = function (METHOD_NAME, argument) {
    var method = [][METHOD_NAME];
    return !!method && fails(function () {
      // eslint-disable-next-line no-useless-call,no-throw-literal -- required for testing
      method.call(null, argument || function () { throw 1; }, 1);
    });
  };

  var nativeJoin = [].join;

  var ES3_STRINGS = indexedObject != Object;
  var STRICT_METHOD\$3 = arrayMethodIsStrict('join', ',');

  // `Array.prototype.join` method
  // https://tc39.es/ecma262/#sec-array.prototype.join
  _export({ target: 'Array', proto: true, forced: ES3_STRINGS || !STRICT_METHOD\$3 }, {
    join: function join(separator) {
      return nativeJoin.call(toIndexedObject(this), separator === undefined ? ',' : separator);
    }
  });

  // `RegExp.prototype.flags` getter implementation
  // https://tc39.es/ecma262/#sec-get-regexp.prototype.flags
  var regexpFlags = function () {
    var that = anObject(this);
    var result = '';
    if (that.global) result += 'g';
    if (that.ignoreCase) result += 'i';
    if (that.multiline) result += 'm';
    if (that.dotAll) result += 's';
    if (that.unicode) result += 'u';
    if (that.sticky) result += 'y';
    return result;
  };

  // babel-minify transpiles RegExp('a', 'y') -> /a/y and it causes SyntaxError,
  // so we use an intermediate function.
  function RE(s, f) {
    return RegExp(s, f);
  }

  var UNSUPPORTED_Y\$2 = fails(function () {
    // babel-minify transpiles RegExp('a', 'y') -> /a/y and it causes SyntaxError
    var re = RE('a', 'y');
    re.lastIndex = 2;
    return re.exec('abcd') != null;
  });

  var BROKEN_CARET = fails(function () {
    // https://bugzilla.mozilla.org/show_bug.cgi?id=773687
    var re = RE('^r', 'gy');
    re.lastIndex = 2;
    return re.exec('str') != null;
  });

  var regexpStickyHelpers = {
  \tUNSUPPORTED_Y: UNSUPPORTED_Y\$2,
  \tBROKEN_CARET: BROKEN_CARET
  };

  var nativeExec = RegExp.prototype.exec;
  // This always refers to the native implementation, because the
  // String#replace polyfill uses ./fix-regexp-well-known-symbol-logic.js,
  // which loads this file before patching the method.
  var nativeReplace = String.prototype.replace;

  var patchedExec = nativeExec;

  var UPDATES_LAST_INDEX_WRONG = (function () {
    var re1 = /a/;
    var re2 = /b*/g;
    nativeExec.call(re1, 'a');
    nativeExec.call(re2, 'a');
    return re1.lastIndex !== 0 || re2.lastIndex !== 0;
  })();

  var UNSUPPORTED_Y\$1 = regexpStickyHelpers.UNSUPPORTED_Y || regexpStickyHelpers.BROKEN_CARET;

  // nonparticipating capturing group, copied from es5-shim's String#split patch.
  // eslint-disable-next-line regexp/no-assertion-capturing-group, regexp/no-empty-group -- required for testing
  var NPCG_INCLUDED = /()??/.exec('')[1] !== undefined;

  var PATCH = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED || UNSUPPORTED_Y\$1;

  if (PATCH) {
    patchedExec = function exec(str) {
      var re = this;
      var lastIndex, reCopy, match, i;
      var sticky = UNSUPPORTED_Y\$1 && re.sticky;
      var flags = regexpFlags.call(re);
      var source = re.source;
      var charsAdded = 0;
      var strCopy = str;

      if (sticky) {
        flags = flags.replace('y', '');
        if (flags.indexOf('g') === -1) {
          flags += 'g';
        }

        strCopy = String(str).slice(re.lastIndex);
        // Support anchored sticky behavior.
        if (re.lastIndex > 0 && (!re.multiline || re.multiline && str[re.lastIndex - 1] !== '\\n')) {
          source = '(?: ' + source + ')';
          strCopy = ' ' + strCopy;
          charsAdded++;
        }
        // ^(? + rx + ) is needed, in combination with some str slicing, to
        // simulate the 'y' flag.
        reCopy = new RegExp('^(?:' + source + ')', flags);
      }

      if (NPCG_INCLUDED) {
        reCopy = new RegExp('^' + source + '\$(?!\\\\s)', flags);
      }
      if (UPDATES_LAST_INDEX_WRONG) lastIndex = re.lastIndex;

      match = nativeExec.call(sticky ? reCopy : re, strCopy);

      if (sticky) {
        if (match) {
          match.input = match.input.slice(charsAdded);
          match[0] = match[0].slice(charsAdded);
          match.index = re.lastIndex;
          re.lastIndex += match[0].length;
        } else re.lastIndex = 0;
      } else if (UPDATES_LAST_INDEX_WRONG && match) {
        re.lastIndex = re.global ? match.index + match[0].length : lastIndex;
      }
      if (NPCG_INCLUDED && match && match.length > 1) {
        // Fix browsers whose `exec` methods don't consistently return `undefined`
        // for NPCG, like IE8. NOTE: This doesn' work for /(.?)?/
        nativeReplace.call(match[0], reCopy, function () {
          for (i = 1; i < arguments.length - 2; i++) {
            if (arguments[i] === undefined) match[i] = undefined;
          }
        });
      }

      return match;
    };
  }

  var regexpExec = patchedExec;

  // `RegExp.prototype.exec` method
  // https://tc39.es/ecma262/#sec-regexp.prototype.exec
  _export({ target: 'RegExp', proto: true, forced: /./.exec !== regexpExec }, {
    exec: regexpExec
  });

  var engineIsNode = classofRaw(global_1.process) == 'process';

  var engineUserAgent = getBuiltIn('navigator', 'userAgent') || '';

  var process = global_1.process;
  var versions = process && process.versions;
  var v8 = versions && versions.v8;
  var match, version;

  if (v8) {
    match = v8.split('.');
    version = match[0] + match[1];
  } else if (engineUserAgent) {
    match = engineUserAgent.match(/Edge\\/(\\d+)/);
    if (!match || match[1] >= 74) {
      match = engineUserAgent.match(/Chrome\\/(\\d+)/);
      if (match) version = match[1];
    }
  }

  var engineV8Version = version && +version;

  var nativeSymbol = !!Object.getOwnPropertySymbols && !fails(function () {
    /* global Symbol -- required for testing */
    return !Symbol.sham &&
      // Chrome 38 Symbol has incorrect toString conversion
      // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
      (engineIsNode ? engineV8Version === 38 : engineV8Version > 37 && engineV8Version < 41);
  });

  var useSymbolAsUid = nativeSymbol
    /* global Symbol -- safe */
    && !Symbol.sham
    && typeof Symbol.iterator == 'symbol';

  var WellKnownSymbolsStore = shared('wks');
  var Symbol\$1 = global_1.Symbol;
  var createWellKnownSymbol = useSymbolAsUid ? Symbol\$1 : Symbol\$1 && Symbol\$1.withoutSetter || uid;

  var wellKnownSymbol = function (name) {
    if (!has\$1(WellKnownSymbolsStore, name) || !(nativeSymbol || typeof WellKnownSymbolsStore[name] == 'string')) {
      if (nativeSymbol && has\$1(Symbol\$1, name)) {
        WellKnownSymbolsStore[name] = Symbol\$1[name];
      } else {
        WellKnownSymbolsStore[name] = createWellKnownSymbol('Symbol.' + name);
      }
    } return WellKnownSymbolsStore[name];
  };

  // TODO: Remove from `core-js@4` since it's moved to entry points







  var SPECIES\$5 = wellKnownSymbol('species');

  var REPLACE_SUPPORTS_NAMED_GROUPS = !fails(function () {
    // #replace needs built-in support for named groups.
    // #match works fine because it just return the exec results, even if it has
    // a \"grops\" property.
    var re = /./;
    re.exec = function () {
      var result = [];
      result.groups = { a: '7' };
      return result;
    };
    return ''.replace(re, '\$<a>') !== '7';
  });

  // IE <= 11 replaces \$0 with the whole match, as if it was \$&
  // https://stackoverflow.com/questions/6024666/getting-ie-to-replace-a-regex-with-the-literal-string-0
  var REPLACE_KEEPS_\$0 = (function () {
    return 'a'.replace(/./, '\$0') === '\$0';
  })();

  var REPLACE = wellKnownSymbol('replace');
  // Safari <= 13.0.3(?) substitutes nth capture where n>m with an empty string
  var REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE = (function () {
    if (/./[REPLACE]) {
      return /./[REPLACE]('a', '\$0') === '';
    }
    return false;
  })();

  // Chrome 51 has a buggy \"split\" implementation when RegExp#exec !== nativeExec
  // Weex JS has frozen built-in prototypes, so use try / catch wrapper
  var SPLIT_WORKS_WITH_OVERWRITTEN_EXEC = !fails(function () {
    // eslint-disable-next-line regexp/no-empty-group -- required for testing
    var re = /(?:)/;
    var originalExec = re.exec;
    re.exec = function () { return originalExec.apply(this, arguments); };
    var result = 'ab'.split(re);
    return result.length !== 2 || result[0] !== 'a' || result[1] !== 'b';
  });

  var fixRegexpWellKnownSymbolLogic = function (KEY, length, exec, sham) {
    var SYMBOL = wellKnownSymbol(KEY);

    var DELEGATES_TO_SYMBOL = !fails(function () {
      // String methods call symbol-named RegEp methods
      var O = {};
      O[SYMBOL] = function () { return 7; };
      return ''[KEY](O) != 7;
    });

    var DELEGATES_TO_EXEC = DELEGATES_TO_SYMBOL && !fails(function () {
      // Symbol-named RegExp methods call .exec
      var execCalled = false;
      var re = /a/;

      if (KEY === 'split') {
        // We can't use real regex here since it causes deoptimization
        // and serious performance degradation in V8
        // https://github.com/zloirock/core-js/issues/306
        re = {};
        // RegExp[@@split] doesn't call the regex's exec method, but first creates
        // a new one. We need to return the patched regex when creating the new one.
        re.constructor = {};
        re.constructor[SPECIES\$5] = function () { return re; };
        re.flags = '';
        re[SYMBOL] = /./[SYMBOL];
      }

      re.exec = function () { execCalled = true; return null; };

      re[SYMBOL]('');
      return !execCalled;
    });

    if (
      !DELEGATES_TO_SYMBOL ||
      !DELEGATES_TO_EXEC ||
      (KEY === 'replace' && !(
        REPLACE_SUPPORTS_NAMED_GROUPS &&
        REPLACE_KEEPS_\$0 &&
        !REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE
      )) ||
      (KEY === 'split' && !SPLIT_WORKS_WITH_OVERWRITTEN_EXEC)
    ) {
      var nativeRegExpMethod = /./[SYMBOL];
      var methods = exec(SYMBOL, ''[KEY], function (nativeMethod, regexp, str, arg2, forceStringMethod) {
        if (regexp.exec === regexpExec) {
          if (DELEGATES_TO_SYMBOL && !forceStringMethod) {
            // The native String method already delegates to @@method (this
            // polyfilled function), leasing to infinite recursion.
            // We avoid it by directly calling the native @@method method.
            return { done: true, value: nativeRegExpMethod.call(regexp, str, arg2) };
          }
          return { done: true, value: nativeMethod.call(str, regexp, arg2) };
        }
        return { done: false };
      }, {
        REPLACE_KEEPS_\$0: REPLACE_KEEPS_\$0,
        REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE: REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE
      });
      var stringMethod = methods[0];
      var regexMethod = methods[1];

      redefine(String.prototype, KEY, stringMethod);
      redefine(RegExp.prototype, SYMBOL, length == 2
        // 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue)
        // 21.2.5.11 RegExp.prototype[@@split](string, limit)
        ? function (string, arg) { return regexMethod.call(string, this, arg); }
        // 21.2.5.6 RegExp.prototype[@@match](string)
        // 21.2.5.9 RegExp.prototype[@@search](string)
        : function (string) { return regexMethod.call(string, this); }
      );
    }

    if (sham) createNonEnumerableProperty(RegExp.prototype[SYMBOL], 'sham', true);
  };

  var MATCH\$2 = wellKnownSymbol('match');

  // `IsRegExp` abstract operation
  // https://tc39.es/ecma262/#sec-isregexp
  var isRegexp = function (it) {
    var isRegExp;
    return isObject(it) && ((isRegExp = it[MATCH\$2]) !== undefined ? !!isRegExp : classofRaw(it) == 'RegExp');
  };

  var aFunction = function (it) {
    if (typeof it != 'function') {
      throw TypeError(String(it) + ' is not a function');
    } return it;
  };

  var SPECIES\$4 = wellKnownSymbol('species');

  // `SpeciesConstructor` abstract operation
  // https://tc39.es/ecma262/#sec-speciesconstructor
  var speciesConstructor = function (O, defaultConstructor) {
    var C = anObject(O).constructor;
    var S;
    return C === undefined || (S = anObject(C)[SPECIES\$4]) == undefined ? defaultConstructor : aFunction(S);
  };

  // `String.prototype.{ codePointAt, at }` methods implementation
  var createMethod\$2 = function (CONVERT_TO_STRING) {
    return function (\$this, pos) {
      var S = String(requireObjectCoercible(\$this));
      var position = toInteger(pos);
      var size = S.length;
      var first, second;
      if (position < 0 || position >= size) return CONVERT_TO_STRING ? '' : undefined;
      first = S.charCodeAt(position);
      return first < 0xD800 || first > 0xDBFF || position + 1 === size
        || (second = S.charCodeAt(position + 1)) < 0xDC00 || second > 0xDFFF
          ? CONVERT_TO_STRING ? S.charAt(position) : first
          : CONVERT_TO_STRING ? S.slice(position, position + 2) : (first - 0xD800 << 10) + (second - 0xDC00) + 0x10000;
    };
  };

  var stringMultibyte = {
    // `String.prototype.codePointAt` method
    // https://tc39.es/ecma262/#sec-string.prototype.codepointat
    codeAt: createMethod\$2(false),
    // `String.prototype.at` method
    // https://github.com/mathiasbynens/String.prototype.at
    charAt: createMethod\$2(true)
  };

  var charAt = stringMultibyte.charAt;

  // `AdvanceStringIndex` abstract operation
  // https://tc39.es/ecma262/#sec-advancestringindex
  var advanceStringIndex = function (S, index, unicode) {
    return index + (unicode ? charAt(S, index).length : 1);
  };

  // `RegExpExec` abstract operation
  // https://tc39.es/ecma262/#sec-regexpexec
  var regexpExecAbstract = function (R, S) {
    var exec = R.exec;
    if (typeof exec === 'function') {
      var result = exec.call(R, S);
      if (typeof result !== 'object') {
        throw TypeError('RegExp exec method returned something other than an Object or null');
      }
      return result;
    }

    if (classofRaw(R) !== 'RegExp') {
      throw TypeError('RegExp#exec called on incompatible receiver');
    }

    return regexpExec.call(R, S);
  };

  var arrayPush = [].push;
  var min\$4 = Math.min;
  var MAX_UINT32 = 0xFFFFFFFF;

  // babel-minify transpiles RegExp('x', 'y') -> /x/y and it causes SyntaxError
  var SUPPORTS_Y = !fails(function () { return !RegExp(MAX_UINT32, 'y'); });

  // @@split logic
  fixRegexpWellKnownSymbolLogic('split', 2, function (SPLIT, nativeSplit, maybeCallNative) {
    var internalSplit;
    if (
      'abbc'.split(/(b)*/)[1] == 'c' ||
      // eslint-disable-next-line regexp/no-empty-group -- required for testing
      'test'.split(/(?:)/, -1).length != 4 ||
      'ab'.split(/(?:ab)*/).length != 2 ||
      '.'.split(/(.?)(.?)/).length != 4 ||
      // eslint-disable-next-line regexp/no-assertion-capturing-group, regexp/no-empty-group -- required for testing
      '.'.split(/()()/).length > 1 ||
      ''.split(/.?/).length
    ) {
      // based on es5-shim implementation, need to rework it
      internalSplit = function (separator, limit) {
        var string = String(requireObjectCoercible(this));
        var lim = limit === undefined ? MAX_UINT32 : limit >>> 0;
        if (lim === 0) return [];
        if (separator === undefined) return [string];
        // If `separator` is not a regex, use native split
        if (!isRegexp(separator)) {
          return nativeSplit.call(string, separator, lim);
        }
        var output = [];
        var flags = (separator.ignoreCase ? 'i' : '') +
                    (separator.multiline ? 'm' : '') +
                    (separator.unicode ? 'u' : '') +
                    (separator.sticky ? 'y' : '');
        var lastLastIndex = 0;
        // Make `global` and avoid `lastIndex` issues by working with a copy
        var separatorCopy = new RegExp(separator.source, flags + 'g');
        var match, lastIndex, lastLength;
        while (match = regexpExec.call(separatorCopy, string)) {
          lastIndex = separatorCopy.lastIndex;
          if (lastIndex > lastLastIndex) {
            output.push(string.slice(lastLastIndex, match.index));
            if (match.length > 1 && match.index < string.length) arrayPush.apply(output, match.slice(1));
            lastLength = match[0].length;
            lastLastIndex = lastIndex;
            if (output.length >= lim) break;
          }
          if (separatorCopy.lastIndex === match.index) separatorCopy.lastIndex++; // Avoid an infinite loop
        }
        if (lastLastIndex === string.length) {
          if (lastLength || !separatorCopy.test('')) output.push('');
        } else output.push(string.slice(lastLastIndex));
        return output.length > lim ? output.slice(0, lim) : output;
      };
    // Chakra, V8
    } else if ('0'.split(undefined, 0).length) {
      internalSplit = function (separator, limit) {
        return separator === undefined && limit === 0 ? [] : nativeSplit.call(this, separator, limit);
      };
    } else internalSplit = nativeSplit;

    return [
      // `String.prototype.split` method
      // https://tc39.es/ecma262/#sec-string.prototype.split
      function split(separator, limit) {
        var O = requireObjectCoercible(this);
        var splitter = separator == undefined ? undefined : separator[SPLIT];
        return splitter !== undefined
          ? splitter.call(separator, O, limit)
          : internalSplit.call(String(O), separator, limit);
      },
      // `RegExp.prototype[@@split]` method
      // https://tc39.es/ecma262/#sec-regexp.prototype-@@split
      //
      // NOTE: This cannot be properly polyfilled in engines that don't support
      // the 'y' flag.
      function (regexp, limit) {
        var res = maybeCallNative(internalSplit, regexp, this, limit, internalSplit !== nativeSplit);
        if (res.done) return res.value;

        var rx = anObject(regexp);
        var S = String(this);
        var C = speciesConstructor(rx, RegExp);

        var unicodeMatching = rx.unicode;
        var flags = (rx.ignoreCase ? 'i' : '') +
                    (rx.multiline ? 'm' : '') +
                    (rx.unicode ? 'u' : '') +
                    (SUPPORTS_Y ? 'y' : 'g');

        // ^(? + rx + ) is needed, in combination with some S slicing, to
        // simulate the 'y' flag.
        var splitter = new C(SUPPORTS_Y ? rx : '^(?:' + rx.source + ')', flags);
        var lim = limit === undefined ? MAX_UINT32 : limit >>> 0;
        if (lim === 0) return [];
        if (S.length === 0) return regexpExecAbstract(splitter, S) === null ? [S] : [];
        var p = 0;
        var q = 0;
        var A = [];
        while (q < S.length) {
          splitter.lastIndex = SUPPORTS_Y ? q : 0;
          var z = regexpExecAbstract(splitter, SUPPORTS_Y ? S : S.slice(q));
          var e;
          if (
            z === null ||
            (e = min\$4(toLength(splitter.lastIndex + (SUPPORTS_Y ? 0 : q)), S.length)) === p
          ) {
            q = advanceStringIndex(S, q, unicodeMatching);
          } else {
            A.push(S.slice(p, q));
            if (A.length === lim) return A;
            for (var i = 1; i <= z.length - 1; i++) {
              A.push(z[i]);
              if (A.length === lim) return A;
            }
            q = p = e;
          }
        }
        A.push(S.slice(p));
        return A;
      }
    ];
  }, !SUPPORTS_Y);

  // `Object.keys` method
  // https://tc39.es/ecma262/#sec-object.keys
  var objectKeys = Object.keys || function keys(O) {
    return objectKeysInternal(O, enumBugKeys);
  };

  // `Object.defineProperties` method
  // https://tc39.es/ecma262/#sec-object.defineproperties
  var objectDefineProperties = descriptors ? Object.defineProperties : function defineProperties(O, Properties) {
    anObject(O);
    var keys = objectKeys(Properties);
    var length = keys.length;
    var index = 0;
    var key;
    while (length > index) objectDefineProperty.f(O, key = keys[index++], Properties[key]);
    return O;
  };

  var html = getBuiltIn('document', 'documentElement');

  var GT = '>';
  var LT = '<';
  var PROTOTYPE = 'prototype';
  var SCRIPT = 'script';
  var IE_PROTO\$1 = sharedKey('IE_PROTO');

  var EmptyConstructor = function () { /* empty */ };

  var scriptTag = function (content) {
    return LT + SCRIPT + GT + content + LT + '/' + SCRIPT + GT;
  };

  // Create object with fake `null` prototype: use ActiveX Object with cleared prototype
  var NullProtoObjectViaActiveX = function (activeXDocument) {
    activeXDocument.write(scriptTag(''));
    activeXDocument.close();
    var temp = activeXDocument.parentWindow.Object;
    activeXDocument = null; // avoid memory leak
    return temp;
  };

  // Create object with fake `null` prototype: use iframe Object with cleared prototype
  var NullProtoObjectViaIFrame = function () {
    // Thrash, waste and sodomy: IE GC bug
    var iframe = documentCreateElement('iframe');
    var JS = 'java' + SCRIPT + ':';
    var iframeDocument;
    iframe.style.display = 'none';
    html.appendChild(iframe);
    // https://github.com/zloirock/core-js/issues/475
    iframe.src = String(JS);
    iframeDocument = iframe.contentWindow.document;
    iframeDocument.open();
    iframeDocument.write(scriptTag('document.F=Object'));
    iframeDocument.close();
    return iframeDocument.F;
  };

  // Check for document.domain and active x support
  // No need to use active x approach when document.domain is not set
  // see https://github.com/es-shims/es5-shim/issues/150
  // variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346
  // avoid IE GC bug
  var activeXDocument;
  var NullProtoObject = function () {
    try {
      /* global ActiveXObject -- old IE */
      activeXDocument = document.domain && new ActiveXObject('htmlfile');
    } catch (error) { /* ignore */ }
    NullProtoObject = activeXDocument ? NullProtoObjectViaActiveX(activeXDocument) : NullProtoObjectViaIFrame();
    var length = enumBugKeys.length;
    while (length--) delete NullProtoObject[PROTOTYPE][enumBugKeys[length]];
    return NullProtoObject();
  };

  hiddenKeys\$1[IE_PROTO\$1] = true;

  // `Object.create` method
  // https://tc39.es/ecma262/#sec-object.create
  var objectCreate = Object.create || function create(O, Properties) {
    var result;
    if (O !== null) {
      EmptyConstructor[PROTOTYPE] = anObject(O);
      result = new EmptyConstructor();
      EmptyConstructor[PROTOTYPE] = null;
      // add \"__proto__\" for Object.getPrototypeOf polyfill
      result[IE_PROTO\$1] = O;
    } else result = NullProtoObject();
    return Properties === undefined ? result : objectDefineProperties(result, Properties);
  };

  var UNSCOPABLES = wellKnownSymbol('unscopables');
  var ArrayPrototype = Array.prototype;

  // Array.prototype[@@unscopables]
  // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
  if (ArrayPrototype[UNSCOPABLES] == undefined) {
    objectDefineProperty.f(ArrayPrototype, UNSCOPABLES, {
      configurable: true,
      value: objectCreate(null)
    });
  }

  // add a key to Array.prototype[@@unscopables]
  var addToUnscopables = function (key) {
    ArrayPrototype[UNSCOPABLES][key] = true;
  };

  var \$includes = arrayIncludes.includes;


  // `Array.prototype.includes` method
  // https://tc39.es/ecma262/#sec-array.prototype.includes
  _export({ target: 'Array', proto: true }, {
    includes: function includes(el /* , fromIndex = 0 */) {
      return \$includes(this, el, arguments.length > 1 ? arguments[1] : undefined);
    }
  });

  // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
  addToUnscopables('includes');

  // `IsArray` abstract operation
  // https://tc39.es/ecma262/#sec-isarray
  var isArray = Array.isArray || function isArray(arg) {
    return classofRaw(arg) == 'Array';
  };

  // `ToObject` abstract operation
  // https://tc39.es/ecma262/#sec-toobject
  var toObject = function (argument) {
    return Object(requireObjectCoercible(argument));
  };

  var createProperty = function (object, key, value) {
    var propertyKey = toPrimitive(key);
    if (propertyKey in object) objectDefineProperty.f(object, propertyKey, createPropertyDescriptor(0, value));
    else object[propertyKey] = value;
  };

  var SPECIES\$3 = wellKnownSymbol('species');

  // `ArraySpeciesCreate` abstract operation
  // https://tc39.es/ecma262/#sec-arrayspeciescreate
  var arraySpeciesCreate = function (originalArray, length) {
    var C;
    if (isArray(originalArray)) {
      C = originalArray.constructor;
      // cross-realm fallback
      if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined;
      else if (isObject(C)) {
        C = C[SPECIES\$3];
        if (C === null) C = undefined;
      }
    } return new (C === undefined ? Array : C)(length === 0 ? 0 : length);
  };

  var SPECIES\$2 = wellKnownSymbol('species');

  var arrayMethodHasSpeciesSupport = function (METHOD_NAME) {
    // We can't use this feature detection in V8 since it causes
    // deoptimization and serious performance degradation
    // https://github.com/zloirock/core-js/issues/677
    return engineV8Version >= 51 || !fails(function () {
      var array = [];
      var constructor = array.constructor = {};
      constructor[SPECIES\$2] = function () {
        return { foo: 1 };
      };
      return array[METHOD_NAME](Boolean).foo !== 1;
    });
  };

  var IS_CONCAT_SPREADABLE = wellKnownSymbol('isConcatSpreadable');
  var MAX_SAFE_INTEGER\$1 = 0x1FFFFFFFFFFFFF;
  var MAXIMUM_ALLOWED_INDEX_EXCEEDED = 'Maximum allowed index exceeded';

  // We can't use this feature detection in V8 since it causes
  // deoptimization and serious performance degradation
  // https://github.com/zloirock/core-js/issues/679
  var IS_CONCAT_SPREADABLE_SUPPORT = engineV8Version >= 51 || !fails(function () {
    var array = [];
    array[IS_CONCAT_SPREADABLE] = false;
    return array.concat()[0] !== array;
  });

  var SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('concat');

  var isConcatSpreadable = function (O) {
    if (!isObject(O)) return false;
    var spreadable = O[IS_CONCAT_SPREADABLE];
    return spreadable !== undefined ? !!spreadable : isArray(O);
  };

  var FORCED\$4 = !IS_CONCAT_SPREADABLE_SUPPORT || !SPECIES_SUPPORT;

  // `Array.prototype.concat` method
  // https://tc39.es/ecma262/#sec-array.prototype.concat
  // with adding support of @@isConcatSpreadable and @@species
  _export({ target: 'Array', proto: true, forced: FORCED\$4 }, {
    // eslint-disable-next-line no-unused-vars -- required for `.length`
    concat: function concat(arg) {
      var O = toObject(this);
      var A = arraySpeciesCreate(O, 0);
      var n = 0;
      var i, k, length, len, E;
      for (i = -1, length = arguments.length; i < length; i++) {
        E = i === -1 ? O : arguments[i];
        if (isConcatSpreadable(E)) {
          len = toLength(E.length);
          if (n + len > MAX_SAFE_INTEGER\$1) throw TypeError(MAXIMUM_ALLOWED_INDEX_EXCEEDED);
          for (k = 0; k < len; k++, n++) if (k in E) createProperty(A, n, E[k]);
        } else {
          if (n >= MAX_SAFE_INTEGER\$1) throw TypeError(MAXIMUM_ALLOWED_INDEX_EXCEEDED);
          createProperty(A, n++, E);
        }
      }
      A.length = n;
      return A;
    }
  });

  // optional / simple context binding
  var functionBindContext = function (fn, that, length) {
    aFunction(fn);
    if (that === undefined) return fn;
    switch (length) {
      case 0: return function () {
        return fn.call(that);
      };
      case 1: return function (a) {
        return fn.call(that, a);
      };
      case 2: return function (a, b) {
        return fn.call(that, a, b);
      };
      case 3: return function (a, b, c) {
        return fn.call(that, a, b, c);
      };
    }
    return function (/* ...args */) {
      return fn.apply(that, arguments);
    };
  };

  var push = [].push;

  // `Array.prototype.{ forEach, map, filter, some, every, find, findIndex, filterOut }` methods implementation
  var createMethod\$1 = function (TYPE) {
    var IS_MAP = TYPE == 1;
    var IS_FILTER = TYPE == 2;
    var IS_SOME = TYPE == 3;
    var IS_EVERY = TYPE == 4;
    var IS_FIND_INDEX = TYPE == 6;
    var IS_FILTER_OUT = TYPE == 7;
    var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;
    return function (\$this, callbackfn, that, specificCreate) {
      var O = toObject(\$this);
      var self = indexedObject(O);
      var boundFunction = functionBindContext(callbackfn, that, 3);
      var length = toLength(self.length);
      var index = 0;
      var create = specificCreate || arraySpeciesCreate;
      var target = IS_MAP ? create(\$this, length) : IS_FILTER || IS_FILTER_OUT ? create(\$this, 0) : undefined;
      var value, result;
      for (;length > index; index++) if (NO_HOLES || index in self) {
        value = self[index];
        result = boundFunction(value, index, O);
        if (TYPE) {
          if (IS_MAP) target[index] = result; // map
          else if (result) switch (TYPE) {
            case 3: return true;              // some
            case 5: return value;             // find
            case 6: return index;             // findIndex
            case 2: push.call(target, value); // filter
          } else switch (TYPE) {
            case 4: return false;             // every
            case 7: push.call(target, value); // filterOut
          }
        }
      }
      return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : target;
    };
  };

  var arrayIteration = {
    // `Array.prototype.forEach` method
    // https://tc39.es/ecma262/#sec-array.prototype.foreach
    forEach: createMethod\$1(0),
    // `Array.prototype.map` method
    // https://tc39.es/ecma262/#sec-array.prototype.map
    map: createMethod\$1(1),
    // `Array.prototype.filter` method
    // https://tc39.es/ecma262/#sec-array.prototype.filter
    filter: createMethod\$1(2),
    // `Array.prototype.some` method
    // https://tc39.es/ecma262/#sec-array.prototype.some
    some: createMethod\$1(3),
    // `Array.prototype.every` method
    // https://tc39.es/ecma262/#sec-array.prototype.every
    every: createMethod\$1(4),
    // `Array.prototype.find` method
    // https://tc39.es/ecma262/#sec-array.prototype.find
    find: createMethod\$1(5),
    // `Array.prototype.findIndex` method
    // https://tc39.es/ecma262/#sec-array.prototype.findIndex
    findIndex: createMethod\$1(6),
    // `Array.prototype.filterOut` method
    // https://github.com/tc39/proposal-array-filtering
    filterOut: createMethod\$1(7)
  };

  var \$find = arrayIteration.find;


  var FIND = 'find';
  var SKIPS_HOLES\$1 = true;

  // Shouldn't skip holes
  if (FIND in []) Array(1)[FIND](function () { SKIPS_HOLES\$1 = false; });

  // `Array.prototype.find` method
  // https://tc39.es/ecma262/#sec-array.prototype.find
  _export({ target: 'Array', proto: true, forced: SKIPS_HOLES\$1 }, {
    find: function find(callbackfn /* , that = undefined */) {
      return \$find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
    }
  });

  // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
  addToUnscopables(FIND);

  var notARegexp = function (it) {
    if (isRegexp(it)) {
      throw TypeError(\"The method doesn't accept regular expressions\");
    } return it;
  };

  var MATCH\$1 = wellKnownSymbol('match');

  var correctIsRegexpLogic = function (METHOD_NAME) {
    var regexp = /./;
    try {
      '/./'[METHOD_NAME](regexp);
    } catch (error1) {
      try {
        regexp[MATCH\$1] = false;
        return '/./'[METHOD_NAME](regexp);
      } catch (error2) { /* empty */ }
    } return false;
  };

  // `String.prototype.includes` method
  // https://tc39.es/ecma262/#sec-string.prototype.includes
  _export({ target: 'String', proto: true, forced: !correctIsRegexpLogic('includes') }, {
    includes: function includes(searchString /* , position = 0 */) {
      return !!~String(requireObjectCoercible(this))
        .indexOf(notARegexp(searchString), arguments.length > 1 ? arguments[1] : undefined);
    }
  });

  // iterable DOM collections
  // flag - `iterable` interface - 'entries', 'keys', 'values', 'forEach' methods
  var domIterables = {
    CSSRuleList: 0,
    CSSStyleDeclaration: 0,
    CSSValueList: 0,
    ClientRectList: 0,
    DOMRectList: 0,
    DOMStringList: 0,
    DOMTokenList: 1,
    DataTransferItemList: 0,
    FileList: 0,
    HTMLAllCollection: 0,
    HTMLCollection: 0,
    HTMLFormElement: 0,
    HTMLSelectElement: 0,
    MediaList: 0,
    MimeTypeArray: 0,
    NamedNodeMap: 0,
    NodeList: 1,
    PaintRequestList: 0,
    Plugin: 0,
    PluginArray: 0,
    SVGLengthList: 0,
    SVGNumberList: 0,
    SVGPathSegList: 0,
    SVGPointList: 0,
    SVGStringList: 0,
    SVGTransformList: 0,
    SourceBufferList: 0,
    StyleSheetList: 0,
    TextTrackCueList: 0,
    TextTrackList: 0,
    TouchList: 0
  };

  var \$forEach = arrayIteration.forEach;


  var STRICT_METHOD\$2 = arrayMethodIsStrict('forEach');

  // `Array.prototype.forEach` method implementation
  // https://tc39.es/ecma262/#sec-array.prototype.foreach
  var arrayForEach = !STRICT_METHOD\$2 ? function forEach(callbackfn /* , thisArg */) {
    return \$forEach(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
  } : [].forEach;

  for (var COLLECTION_NAME\$1 in domIterables) {
    var Collection\$1 = global_1[COLLECTION_NAME\$1];
    var CollectionPrototype\$1 = Collection\$1 && Collection\$1.prototype;
    // some Chrome versions have non-configurable methods on DOMTokenList
    if (CollectionPrototype\$1 && CollectionPrototype\$1.forEach !== arrayForEach) try {
      createNonEnumerableProperty(CollectionPrototype\$1, 'forEach', arrayForEach);
    } catch (error) {
      CollectionPrototype\$1.forEach = arrayForEach;
    }
  }

  var trim\$2 = stringTrim.trim;


  var \$parseFloat = global_1.parseFloat;
  var FORCED\$3 = 1 / \$parseFloat(whitespaces + '-0') !== -Infinity;

  // `parseFloat` method
  // https://tc39.es/ecma262/#sec-parsefloat-string
  var numberParseFloat = FORCED\$3 ? function parseFloat(string) {
    var trimmedString = trim\$2(String(string));
    var result = \$parseFloat(trimmedString);
    return result === 0 && trimmedString.charAt(0) == '-' ? -0 : result;
  } : \$parseFloat;

  // `parseFloat` method
  // https://tc39.es/ecma262/#sec-parsefloat-string
  _export({ global: true, forced: parseFloat != numberParseFloat }, {
    parseFloat: numberParseFloat
  });

  var propertyIsEnumerable = objectPropertyIsEnumerable.f;

  // `Object.{ entries, values }` methods implementation
  var createMethod = function (TO_ENTRIES) {
    return function (it) {
      var O = toIndexedObject(it);
      var keys = objectKeys(O);
      var length = keys.length;
      var i = 0;
      var result = [];
      var key;
      while (length > i) {
        key = keys[i++];
        if (!descriptors || propertyIsEnumerable.call(O, key)) {
          result.push(TO_ENTRIES ? [key, O[key]] : O[key]);
        }
      }
      return result;
    };
  };

  var objectToArray = {
    // `Object.entries` method
    // https://tc39.es/ecma262/#sec-object.entries
    entries: createMethod(true),
    // `Object.values` method
    // https://tc39.es/ecma262/#sec-object.values
    values: createMethod(false)
  };

  var \$entries = objectToArray.entries;

  // `Object.entries` method
  // https://tc39.es/ecma262/#sec-object.entries
  _export({ target: 'Object', stat: true }, {
    entries: function entries(O) {
      return \$entries(O);
    }
  });

  var \$indexOf = arrayIncludes.indexOf;


  var nativeIndexOf = [].indexOf;

  var NEGATIVE_ZERO = !!nativeIndexOf && 1 / [1].indexOf(1, -0) < 0;
  var STRICT_METHOD\$1 = arrayMethodIsStrict('indexOf');

  // `Array.prototype.indexOf` method
  // https://tc39.es/ecma262/#sec-array.prototype.indexof
  _export({ target: 'Array', proto: true, forced: NEGATIVE_ZERO || !STRICT_METHOD\$1 }, {
    indexOf: function indexOf(searchElement /* , fromIndex = 0 */) {
      return NEGATIVE_ZERO
        // convert -0 to +0
        ? nativeIndexOf.apply(this, arguments) || 0
        : \$indexOf(this, searchElement, arguments.length > 1 ? arguments[1] : undefined);
    }
  });

  var test\$2 = [];
  var nativeSort = test\$2.sort;

  // IE8-
  var FAILS_ON_UNDEFINED = fails(function () {
    test\$2.sort(undefined);
  });
  // V8 bug
  var FAILS_ON_NULL = fails(function () {
    test\$2.sort(null);
  });
  // Old WebKit
  var STRICT_METHOD = arrayMethodIsStrict('sort');

  var FORCED\$2 = FAILS_ON_UNDEFINED || !FAILS_ON_NULL || !STRICT_METHOD;

  // `Array.prototype.sort` method
  // https://tc39.es/ecma262/#sec-array.prototype.sort
  _export({ target: 'Array', proto: true, forced: FORCED\$2 }, {
    sort: function sort(comparefn) {
      return comparefn === undefined
        ? nativeSort.call(toObject(this))
        : nativeSort.call(toObject(this), aFunction(comparefn));
    }
  });

  var floor = Math.floor;
  var replace = ''.replace;
  var SUBSTITUTION_SYMBOLS = /\\\$([\$&'`]|\\d{1,2}|<[^>]*>)/g;
  var SUBSTITUTION_SYMBOLS_NO_NAMED = /\\\$([\$&'`]|\\d{1,2})/g;

  // https://tc39.es/ecma262/#sec-getsubstitution
  var getSubstitution = function (matched, str, position, captures, namedCaptures, replacement) {
    var tailPos = position + matched.length;
    var m = captures.length;
    var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED;
    if (namedCaptures !== undefined) {
      namedCaptures = toObject(namedCaptures);
      symbols = SUBSTITUTION_SYMBOLS;
    }
    return replace.call(replacement, symbols, function (match, ch) {
      var capture;
      switch (ch.charAt(0)) {
        case '\$': return '\$';
        case '&': return matched;
        case '`': return str.slice(0, position);
        case \"'\": return str.slice(tailPos);
        case '<':
          capture = namedCaptures[ch.slice(1, -1)];
          break;
        default: // \\d\\d?
          var n = +ch;
          if (n === 0) return match;
          if (n > m) {
            var f = floor(n / 10);
            if (f === 0) return match;
            if (f <= m) return captures[f - 1] === undefined ? ch.charAt(1) : captures[f - 1] + ch.charAt(1);
            return match;
          }
          capture = captures[n - 1];
      }
      return capture === undefined ? '' : capture;
    });
  };

  var max\$2 = Math.max;
  var min\$3 = Math.min;

  var maybeToString = function (it) {
    return it === undefined ? it : String(it);
  };

  // @@replace logic
  fixRegexpWellKnownSymbolLogic('replace', 2, function (REPLACE, nativeReplace, maybeCallNative, reason) {
    var REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE = reason.REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE;
    var REPLACE_KEEPS_\$0 = reason.REPLACE_KEEPS_\$0;
    var UNSAFE_SUBSTITUTE = REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE ? '\$' : '\$0';

    return [
      // `String.prototype.replace` method
      // https://tc39.es/ecma262/#sec-string.prototype.replace
      function replace(searchValue, replaceValue) {
        var O = requireObjectCoercible(this);
        var replacer = searchValue == undefined ? undefined : searchValue[REPLACE];
        return replacer !== undefined
          ? replacer.call(searchValue, O, replaceValue)
          : nativeReplace.call(String(O), searchValue, replaceValue);
      },
      // `RegExp.prototype[@@replace]` method
      // https://tc39.es/ecma262/#sec-regexp.prototype-@@replace
      function (regexp, replaceValue) {
        if (
          (!REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE && REPLACE_KEEPS_\$0) ||
          (typeof replaceValue === 'string' && replaceValue.indexOf(UNSAFE_SUBSTITUTE) === -1)
        ) {
          var res = maybeCallNative(nativeReplace, regexp, this, replaceValue);
          if (res.done) return res.value;
        }

        var rx = anObject(regexp);
        var S = String(this);

        var functionalReplace = typeof replaceValue === 'function';
        if (!functionalReplace) replaceValue = String(replaceValue);

        var global = rx.global;
        if (global) {
          var fullUnicode = rx.unicode;
          rx.lastIndex = 0;
        }
        var results = [];
        while (true) {
          var result = regexpExecAbstract(rx, S);
          if (result === null) break;

          results.push(result);
          if (!global) break;

          var matchStr = String(result[0]);
          if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength(rx.lastIndex), fullUnicode);
        }

        var accumulatedResult = '';
        var nextSourcePosition = 0;
        for (var i = 0; i < results.length; i++) {
          result = results[i];

          var matched = String(result[0]);
          var position = max\$2(min\$3(toInteger(result.index), S.length), 0);
          var captures = [];
          // NOTE: This is equivalent to
          //   captures = result.slice(1).map(maybeToString)
          // but for some reason `nativeSlice.call(result, 1, result.length)` (called in
          // the slice polyfill when slicing native arrays) \"doesn't work\" in safari 9 and
          // causes a crash (https://pastebin.com/N21QzeQA) when trying to debug it.
          for (var j = 1; j < result.length; j++) captures.push(maybeToString(result[j]));
          var namedCaptures = result.groups;
          if (functionalReplace) {
            var replacerArgs = [matched].concat(captures, position, S);
            if (namedCaptures !== undefined) replacerArgs.push(namedCaptures);
            var replacement = String(replaceValue.apply(undefined, replacerArgs));
          } else {
            replacement = getSubstitution(matched, S, position, captures, namedCaptures, replaceValue);
          }
          if (position >= nextSourcePosition) {
            accumulatedResult += S.slice(nextSourcePosition, position) + replacement;
            nextSourcePosition = position + matched.length;
          }
        }
        return accumulatedResult + S.slice(nextSourcePosition);
      }
    ];
  });

  var nativeAssign = Object.assign;
  var defineProperty\$3 = Object.defineProperty;

  // `Object.assign` method
  // https://tc39.es/ecma262/#sec-object.assign
  var objectAssign = !nativeAssign || fails(function () {
    // should have correct order of operations (Edge bug)
    if (descriptors && nativeAssign({ b: 1 }, nativeAssign(defineProperty\$3({}, 'a', {
      enumerable: true,
      get: function () {
        defineProperty\$3(this, 'b', {
          value: 3,
          enumerable: false
        });
      }
    }), { b: 2 })).b !== 1) return true;
    // should work with symbols and should have deterministic property order (V8 bug)
    var A = {};
    var B = {};
    /* global Symbol -- required for testing */
    var symbol = Symbol();
    var alphabet = 'abcdefghijklmnopqrst';
    A[symbol] = 7;
    alphabet.split('').forEach(function (chr) { B[chr] = chr; });
    return nativeAssign({}, A)[symbol] != 7 || objectKeys(nativeAssign({}, B)).join('') != alphabet;
  }) ? function assign(target, source) { // eslint-disable-line no-unused-vars -- required for `.length`
    var T = toObject(target);
    var argumentsLength = arguments.length;
    var index = 1;
    var getOwnPropertySymbols = objectGetOwnPropertySymbols.f;
    var propertyIsEnumerable = objectPropertyIsEnumerable.f;
    while (argumentsLength > index) {
      var S = indexedObject(arguments[index++]);
      var keys = getOwnPropertySymbols ? objectKeys(S).concat(getOwnPropertySymbols(S)) : objectKeys(S);
      var length = keys.length;
      var j = 0;
      var key;
      while (length > j) {
        key = keys[j++];
        if (!descriptors || propertyIsEnumerable.call(S, key)) T[key] = S[key];
      }
    } return T;
  } : nativeAssign;

  // `Object.assign` method
  // https://tc39.es/ecma262/#sec-object.assign
  _export({ target: 'Object', stat: true, forced: Object.assign !== objectAssign }, {
    assign: objectAssign
  });

  var \$filter = arrayIteration.filter;


  var HAS_SPECIES_SUPPORT\$3 = arrayMethodHasSpeciesSupport('filter');

  // `Array.prototype.filter` method
  // https://tc39.es/ecma262/#sec-array.prototype.filter
  // with adding support of @@species
  _export({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT\$3 }, {
    filter: function filter(callbackfn /* , thisArg */) {
      return \$filter(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
    }
  });

  // `SameValue` abstract operation
  // https://tc39.es/ecma262/#sec-samevalue
  var sameValue = Object.is || function is(x, y) {
    // eslint-disable-next-line no-self-compare -- NaN check
    return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y;
  };

  // @@search logic
  fixRegexpWellKnownSymbolLogic('search', 1, function (SEARCH, nativeSearch, maybeCallNative) {
    return [
      // `String.prototype.search` method
      // https://tc39.es/ecma262/#sec-string.prototype.search
      function search(regexp) {
        var O = requireObjectCoercible(this);
        var searcher = regexp == undefined ? undefined : regexp[SEARCH];
        return searcher !== undefined ? searcher.call(regexp, O) : new RegExp(regexp)[SEARCH](String(O));
      },
      // `RegExp.prototype[@@search]` method
      // https://tc39.es/ecma262/#sec-regexp.prototype-@@search
      function (regexp) {
        var res = maybeCallNative(nativeSearch, regexp, this);
        if (res.done) return res.value;

        var rx = anObject(regexp);
        var S = String(this);

        var previousLastIndex = rx.lastIndex;
        if (!sameValue(previousLastIndex, 0)) rx.lastIndex = 0;
        var result = regexpExecAbstract(rx, S);
        if (!sameValue(rx.lastIndex, previousLastIndex)) rx.lastIndex = previousLastIndex;
        return result === null ? -1 : result.index;
      }
    ];
  });

  var trim\$1 = stringTrim.trim;


  var \$parseInt = global_1.parseInt;
  var hex = /^[+-]?0[Xx]/;
  var FORCED\$1 = \$parseInt(whitespaces + '08') !== 8 || \$parseInt(whitespaces + '0x16') !== 22;

  // `parseInt` method
  // https://tc39.es/ecma262/#sec-parseint-string-radix
  var numberParseInt = FORCED\$1 ? function parseInt(string, radix) {
    var S = trim\$1(String(string));
    return \$parseInt(S, (radix >>> 0) || (hex.test(S) ? 16 : 10));
  } : \$parseInt;

  // `parseInt` method
  // https://tc39.es/ecma262/#sec-parseint-string-radix
  _export({ global: true, forced: parseInt != numberParseInt }, {
    parseInt: numberParseInt
  });

  var \$map = arrayIteration.map;


  var HAS_SPECIES_SUPPORT\$2 = arrayMethodHasSpeciesSupport('map');

  // `Array.prototype.map` method
  // https://tc39.es/ecma262/#sec-array.prototype.map
  // with adding support of @@species
  _export({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT\$2 }, {
    map: function map(callbackfn /* , thisArg */) {
      return \$map(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
    }
  });

  var \$findIndex = arrayIteration.findIndex;


  var FIND_INDEX = 'findIndex';
  var SKIPS_HOLES = true;

  // Shouldn't skip holes
  if (FIND_INDEX in []) Array(1)[FIND_INDEX](function () { SKIPS_HOLES = false; });

  // `Array.prototype.findIndex` method
  // https://tc39.es/ecma262/#sec-array.prototype.findindex
  _export({ target: 'Array', proto: true, forced: SKIPS_HOLES }, {
    findIndex: function findIndex(callbackfn /* , that = undefined */) {
      return \$findIndex(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
    }
  });

  // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
  addToUnscopables(FIND_INDEX);

  var aPossiblePrototype = function (it) {
    if (!isObject(it) && it !== null) {
      throw TypeError(\"Can't set \" + String(it) + ' as a prototype');
    } return it;
  };

  /* eslint-disable no-proto -- safe */



  // `Object.setPrototypeOf` method
  // https://tc39.es/ecma262/#sec-object.setprototypeof
  // Works with __proto__ only. Old v8 can't work with null proto objects.
  var objectSetPrototypeOf = Object.setPrototypeOf || ('__proto__' in {} ? function () {
    var CORRECT_SETTER = false;
    var test = {};
    var setter;
    try {
      setter = Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').set;
      setter.call(test, []);
      CORRECT_SETTER = test instanceof Array;
    } catch (error) { /* empty */ }
    return function setPrototypeOf(O, proto) {
      anObject(O);
      aPossiblePrototype(proto);
      if (CORRECT_SETTER) setter.call(O, proto);
      else O.__proto__ = proto;
      return O;
    };
  }() : undefined);

  // makes subclassing work correct for wrapped built-ins
  var inheritIfRequired = function (\$this, dummy, Wrapper) {
    var NewTarget, NewTargetPrototype;
    if (
      // it can work only with native `setPrototypeOf`
      objectSetPrototypeOf &&
      // we haven't completely correct pre-ES6 way for getting `new.target`, so use this
      typeof (NewTarget = dummy.constructor) == 'function' &&
      NewTarget !== Wrapper &&
      isObject(NewTargetPrototype = NewTarget.prototype) &&
      NewTargetPrototype !== Wrapper.prototype
    ) objectSetPrototypeOf(\$this, NewTargetPrototype);
    return \$this;
  };

  var SPECIES\$1 = wellKnownSymbol('species');

  var setSpecies = function (CONSTRUCTOR_NAME) {
    var Constructor = getBuiltIn(CONSTRUCTOR_NAME);
    var defineProperty = objectDefineProperty.f;

    if (descriptors && Constructor && !Constructor[SPECIES\$1]) {
      defineProperty(Constructor, SPECIES\$1, {
        configurable: true,
        get: function () { return this; }
      });
    }
  };

  var defineProperty\$2 = objectDefineProperty.f;
  var getOwnPropertyNames\$1 = objectGetOwnPropertyNames.f;





  var setInternalState\$1 = internalState.set;



  var MATCH = wellKnownSymbol('match');
  var NativeRegExp = global_1.RegExp;
  var RegExpPrototype\$1 = NativeRegExp.prototype;
  var re1 = /a/g;
  var re2 = /a/g;

  // \"new\" should create a new object, old webkit bug
  var CORRECT_NEW = new NativeRegExp(re1) !== re1;

  var UNSUPPORTED_Y = regexpStickyHelpers.UNSUPPORTED_Y;

  var FORCED = descriptors && isForced_1('RegExp', (!CORRECT_NEW || UNSUPPORTED_Y || fails(function () {
    re2[MATCH] = false;
    // RegExp constructor can alter flags and IsRegExp works correct with @@match
    return NativeRegExp(re1) != re1 || NativeRegExp(re2) == re2 || NativeRegExp(re1, 'i') != '/a/i';
  })));

  // `RegExp` constructor
  // https://tc39.es/ecma262/#sec-regexp-constructor
  if (FORCED) {
    var RegExpWrapper = function RegExp(pattern, flags) {
      var thisIsRegExp = this instanceof RegExpWrapper;
      var patternIsRegExp = isRegexp(pattern);
      var flagsAreUndefined = flags === undefined;
      var sticky;

      if (!thisIsRegExp && patternIsRegExp && pattern.constructor === RegExpWrapper && flagsAreUndefined) {
        return pattern;
      }

      if (CORRECT_NEW) {
        if (patternIsRegExp && !flagsAreUndefined) pattern = pattern.source;
      } else if (pattern instanceof RegExpWrapper) {
        if (flagsAreUndefined) flags = regexpFlags.call(pattern);
        pattern = pattern.source;
      }

      if (UNSUPPORTED_Y) {
        sticky = !!flags && flags.indexOf('y') > -1;
        if (sticky) flags = flags.replace(/y/g, '');
      }

      var result = inheritIfRequired(
        CORRECT_NEW ? new NativeRegExp(pattern, flags) : NativeRegExp(pattern, flags),
        thisIsRegExp ? this : RegExpPrototype\$1,
        RegExpWrapper
      );

      if (UNSUPPORTED_Y && sticky) setInternalState\$1(result, { sticky: sticky });

      return result;
    };
    var proxy = function (key) {
      key in RegExpWrapper || defineProperty\$2(RegExpWrapper, key, {
        configurable: true,
        get: function () { return NativeRegExp[key]; },
        set: function (it) { NativeRegExp[key] = it; }
      });
    };
    var keys\$1 = getOwnPropertyNames\$1(NativeRegExp);
    var index = 0;
    while (keys\$1.length > index) proxy(keys\$1[index++]);
    RegExpPrototype\$1.constructor = RegExpWrapper;
    RegExpWrapper.prototype = RegExpPrototype\$1;
    redefine(global_1, 'RegExp', RegExpWrapper);
  }

  // https://tc39.es/ecma262/#sec-get-regexp-@@species
  setSpecies('RegExp');

  var TO_STRING = 'toString';
  var RegExpPrototype = RegExp.prototype;
  var nativeToString = RegExpPrototype[TO_STRING];

  var NOT_GENERIC = fails(function () { return nativeToString.call({ source: 'a', flags: 'b' }) != '/a/b'; });
  // FF44- RegExp#toString has a wrong name
  var INCORRECT_NAME = nativeToString.name != TO_STRING;

  // `RegExp.prototype.toString` method
  // https://tc39.es/ecma262/#sec-regexp.prototype.tostring
  if (NOT_GENERIC || INCORRECT_NAME) {
    redefine(RegExp.prototype, TO_STRING, function toString() {
      var R = anObject(this);
      var p = String(R.source);
      var rf = R.flags;
      var f = String(rf === undefined && R instanceof RegExp && !('flags' in RegExpPrototype) ? regexpFlags.call(R) : rf);
      return '/' + p + '/' + f;
    }, { unsafe: true });
  }

  var TO_STRING_TAG\$3 = wellKnownSymbol('toStringTag');
  var test\$1 = {};

  test\$1[TO_STRING_TAG\$3] = 'z';

  var toStringTagSupport = String(test\$1) === '[object z]';

  var TO_STRING_TAG\$2 = wellKnownSymbol('toStringTag');
  // ES3 wrong here
  var CORRECT_ARGUMENTS = classofRaw(function () { return arguments; }()) == 'Arguments';

  // fallback for IE11 Script Access Denied error
  var tryGet = function (it, key) {
    try {
      return it[key];
    } catch (error) { /* empty */ }
  };

  // getting tag from ES6+ `Object.prototype.toString`
  var classof = toStringTagSupport ? classofRaw : function (it) {
    var O, tag, result;
    return it === undefined ? 'Undefined' : it === null ? 'Null'
      // @@toStringTag case
      : typeof (tag = tryGet(O = Object(it), TO_STRING_TAG\$2)) == 'string' ? tag
      // builtinTag case
      : CORRECT_ARGUMENTS ? classofRaw(O)
      // ES3 arguments fallback
      : (result = classofRaw(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : result;
  };

  // `Object.prototype.toString` method implementation
  // https://tc39.es/ecma262/#sec-object.prototype.tostring
  var objectToString = toStringTagSupport ? {}.toString : function toString() {
    return '[object ' + classof(this) + ']';
  };

  // `Object.prototype.toString` method
  // https://tc39.es/ecma262/#sec-object.prototype.tostring
  if (!toStringTagSupport) {
    redefine(Object.prototype, 'toString', objectToString, { unsafe: true });
  }

  var HAS_SPECIES_SUPPORT\$1 = arrayMethodHasSpeciesSupport('slice');

  var SPECIES = wellKnownSymbol('species');
  var nativeSlice = [].slice;
  var max\$1 = Math.max;

  // `Array.prototype.slice` method
  // https://tc39.es/ecma262/#sec-array.prototype.slice
  // fallback for not array-like ES3 strings and DOM objects
  _export({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT\$1 }, {
    slice: function slice(start, end) {
      var O = toIndexedObject(this);
      var length = toLength(O.length);
      var k = toAbsoluteIndex(start, length);
      var fin = toAbsoluteIndex(end === undefined ? length : end, length);
      // inline `ArraySpeciesCreate` for usage native `Array#slice` where it's possible
      var Constructor, result, n;
      if (isArray(O)) {
        Constructor = O.constructor;
        // cross-realm fallback
        if (typeof Constructor == 'function' && (Constructor === Array || isArray(Constructor.prototype))) {
          Constructor = undefined;
        } else if (isObject(Constructor)) {
          Constructor = Constructor[SPECIES];
          if (Constructor === null) Constructor = undefined;
        }
        if (Constructor === Array || Constructor === undefined) {
          return nativeSlice.call(O, k, fin);
        }
      }
      result = new (Constructor === undefined ? Array : Constructor)(max\$1(fin - k, 0));
      for (n = 0; k < fin; k++, n++) if (k in O) createProperty(result, n, O[k]);
      result.length = n;
      return result;
    }
  });

  var correctPrototypeGetter = !fails(function () {
    function F() { /* empty */ }
    F.prototype.constructor = null;
    return Object.getPrototypeOf(new F()) !== F.prototype;
  });

  var IE_PROTO = sharedKey('IE_PROTO');
  var ObjectPrototype = Object.prototype;

  // `Object.getPrototypeOf` method
  // https://tc39.es/ecma262/#sec-object.getprototypeof
  var objectGetPrototypeOf = correctPrototypeGetter ? Object.getPrototypeOf : function (O) {
    O = toObject(O);
    if (has\$1(O, IE_PROTO)) return O[IE_PROTO];
    if (typeof O.constructor == 'function' && O instanceof O.constructor) {
      return O.constructor.prototype;
    } return O instanceof Object ? ObjectPrototype : null;
  };

  var ITERATOR\$2 = wellKnownSymbol('iterator');
  var BUGGY_SAFARI_ITERATORS\$1 = false;

  var returnThis\$1 = function () { return this; };

  // `%IteratorPrototype%` object
  // https://tc39.es/ecma262/#sec-%iteratorprototype%-object
  var IteratorPrototype\$2, PrototypeOfArrayIteratorPrototype, arrayIterator;

  if ([].keys) {
    arrayIterator = [].keys();
    // Safari 8 has buggy iterators w/o `next`
    if (!('next' in arrayIterator)) BUGGY_SAFARI_ITERATORS\$1 = true;
    else {
      PrototypeOfArrayIteratorPrototype = objectGetPrototypeOf(objectGetPrototypeOf(arrayIterator));
      if (PrototypeOfArrayIteratorPrototype !== Object.prototype) IteratorPrototype\$2 = PrototypeOfArrayIteratorPrototype;
    }
  }

  var NEW_ITERATOR_PROTOTYPE = IteratorPrototype\$2 == undefined || fails(function () {
    var test = {};
    // FF44- legacy iterators case
    return IteratorPrototype\$2[ITERATOR\$2].call(test) !== test;
  });

  if (NEW_ITERATOR_PROTOTYPE) IteratorPrototype\$2 = {};

  // 25.1.2.1.1 %IteratorPrototype%[@@iterator]()
  if (!has\$1(IteratorPrototype\$2, ITERATOR\$2)) {
    createNonEnumerableProperty(IteratorPrototype\$2, ITERATOR\$2, returnThis\$1);
  }

  var iteratorsCore = {
    IteratorPrototype: IteratorPrototype\$2,
    BUGGY_SAFARI_ITERATORS: BUGGY_SAFARI_ITERATORS\$1
  };

  var defineProperty\$1 = objectDefineProperty.f;



  var TO_STRING_TAG\$1 = wellKnownSymbol('toStringTag');

  var setToStringTag = function (it, TAG, STATIC) {
    if (it && !has\$1(it = STATIC ? it : it.prototype, TO_STRING_TAG\$1)) {
      defineProperty\$1(it, TO_STRING_TAG\$1, { configurable: true, value: TAG });
    }
  };

  var IteratorPrototype\$1 = iteratorsCore.IteratorPrototype;

  var createIteratorConstructor = function (IteratorConstructor, NAME, next) {
    var TO_STRING_TAG = NAME + ' Iterator';
    IteratorConstructor.prototype = objectCreate(IteratorPrototype\$1, { next: createPropertyDescriptor(1, next) });
    setToStringTag(IteratorConstructor, TO_STRING_TAG, false);
    return IteratorConstructor;
  };

  var IteratorPrototype = iteratorsCore.IteratorPrototype;
  var BUGGY_SAFARI_ITERATORS = iteratorsCore.BUGGY_SAFARI_ITERATORS;
  var ITERATOR\$1 = wellKnownSymbol('iterator');
  var KEYS = 'keys';
  var VALUES = 'values';
  var ENTRIES = 'entries';

  var returnThis = function () { return this; };

  var defineIterator = function (Iterable, NAME, IteratorConstructor, next, DEFAULT, IS_SET, FORCED) {
    createIteratorConstructor(IteratorConstructor, NAME, next);

    var getIterationMethod = function (KIND) {
      if (KIND === DEFAULT && defaultIterator) return defaultIterator;
      if (!BUGGY_SAFARI_ITERATORS && KIND in IterablePrototype) return IterablePrototype[KIND];
      switch (KIND) {
        case KEYS: return function keys() { return new IteratorConstructor(this, KIND); };
        case VALUES: return function values() { return new IteratorConstructor(this, KIND); };
        case ENTRIES: return function entries() { return new IteratorConstructor(this, KIND); };
      } return function () { return new IteratorConstructor(this); };
    };

    var TO_STRING_TAG = NAME + ' Iterator';
    var INCORRECT_VALUES_NAME = false;
    var IterablePrototype = Iterable.prototype;
    var nativeIterator = IterablePrototype[ITERATOR\$1]
      || IterablePrototype['@@iterator']
      || DEFAULT && IterablePrototype[DEFAULT];
    var defaultIterator = !BUGGY_SAFARI_ITERATORS && nativeIterator || getIterationMethod(DEFAULT);
    var anyNativeIterator = NAME == 'Array' ? IterablePrototype.entries || nativeIterator : nativeIterator;
    var CurrentIteratorPrototype, methods, KEY;

    // fix native
    if (anyNativeIterator) {
      CurrentIteratorPrototype = objectGetPrototypeOf(anyNativeIterator.call(new Iterable()));
      if (IteratorPrototype !== Object.prototype && CurrentIteratorPrototype.next) {
        if (objectGetPrototypeOf(CurrentIteratorPrototype) !== IteratorPrototype) {
          if (objectSetPrototypeOf) {
            objectSetPrototypeOf(CurrentIteratorPrototype, IteratorPrototype);
          } else if (typeof CurrentIteratorPrototype[ITERATOR\$1] != 'function') {
            createNonEnumerableProperty(CurrentIteratorPrototype, ITERATOR\$1, returnThis);
          }
        }
        // Set @@toStringTag to native iterators
        setToStringTag(CurrentIteratorPrototype, TO_STRING_TAG, true);
      }
    }

    // fix Array#{values, @@iterator}.name in V8 / FF
    if (DEFAULT == VALUES && nativeIterator && nativeIterator.name !== VALUES) {
      INCORRECT_VALUES_NAME = true;
      defaultIterator = function values() { return nativeIterator.call(this); };
    }

    // define iterator
    if (IterablePrototype[ITERATOR\$1] !== defaultIterator) {
      createNonEnumerableProperty(IterablePrototype, ITERATOR\$1, defaultIterator);
    }

    // export additional methods
    if (DEFAULT) {
      methods = {
        values: getIterationMethod(VALUES),
        keys: IS_SET ? defaultIterator : getIterationMethod(KEYS),
        entries: getIterationMethod(ENTRIES)
      };
      if (FORCED) for (KEY in methods) {
        if (BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME || !(KEY in IterablePrototype)) {
          redefine(IterablePrototype, KEY, methods[KEY]);
        }
      } else _export({ target: NAME, proto: true, forced: BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME }, methods);
    }

    return methods;
  };

  var ARRAY_ITERATOR = 'Array Iterator';
  var setInternalState = internalState.set;
  var getInternalState = internalState.getterFor(ARRAY_ITERATOR);

  // `Array.prototype.entries` method
  // https://tc39.es/ecma262/#sec-array.prototype.entries
  // `Array.prototype.keys` method
  // https://tc39.es/ecma262/#sec-array.prototype.keys
  // `Array.prototype.values` method
  // https://tc39.es/ecma262/#sec-array.prototype.values
  // `Array.prototype[@@iterator]` method
  // https://tc39.es/ecma262/#sec-array.prototype-@@iterator
  // `CreateArrayIterator` internal method
  // https://tc39.es/ecma262/#sec-createarrayiterator
  var es_array_iterator = defineIterator(Array, 'Array', function (iterated, kind) {
    setInternalState(this, {
      type: ARRAY_ITERATOR,
      target: toIndexedObject(iterated), // target
      index: 0,                          // next index
      kind: kind                         // kind
    });
  // `%ArrayIteratorPrototype%.next` method
  // https://tc39.es/ecma262/#sec-%arrayiteratorprototype%.next
  }, function () {
    var state = getInternalState(this);
    var target = state.target;
    var kind = state.kind;
    var index = state.index++;
    if (!target || index >= target.length) {
      state.target = undefined;
      return { value: undefined, done: true };
    }
    if (kind == 'keys') return { value: index, done: false };
    if (kind == 'values') return { value: target[index], done: false };
    return { value: [index, target[index]], done: false };
  }, 'values');

  // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
  addToUnscopables('keys');
  addToUnscopables('values');
  addToUnscopables('entries');

  var ITERATOR = wellKnownSymbol('iterator');
  var TO_STRING_TAG = wellKnownSymbol('toStringTag');
  var ArrayValues = es_array_iterator.values;

  for (var COLLECTION_NAME in domIterables) {
    var Collection = global_1[COLLECTION_NAME];
    var CollectionPrototype = Collection && Collection.prototype;
    if (CollectionPrototype) {
      // some Chrome versions have non-configurable methods on DOMTokenList
      if (CollectionPrototype[ITERATOR] !== ArrayValues) try {
        createNonEnumerableProperty(CollectionPrototype, ITERATOR, ArrayValues);
      } catch (error) {
        CollectionPrototype[ITERATOR] = ArrayValues;
      }
      if (!CollectionPrototype[TO_STRING_TAG]) {
        createNonEnumerableProperty(CollectionPrototype, TO_STRING_TAG, COLLECTION_NAME);
      }
      if (domIterables[COLLECTION_NAME]) for (var METHOD_NAME in es_array_iterator) {
        // some Chrome versions have non-configurable methods on DOMTokenList
        if (CollectionPrototype[METHOD_NAME] !== es_array_iterator[METHOD_NAME]) try {
          createNonEnumerableProperty(CollectionPrototype, METHOD_NAME, es_array_iterator[METHOD_NAME]);
        } catch (error) {
          CollectionPrototype[METHOD_NAME] = es_array_iterator[METHOD_NAME];
        }
      }
    }
  }

  var HAS_SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('splice');

  var max = Math.max;
  var min\$2 = Math.min;
  var MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF;
  var MAXIMUM_ALLOWED_LENGTH_EXCEEDED = 'Maximum allowed length exceeded';

  // `Array.prototype.splice` method
  // https://tc39.es/ecma262/#sec-array.prototype.splice
  // with adding support of @@species
  _export({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT }, {
    splice: function splice(start, deleteCount /* , ...items */) {
      var O = toObject(this);
      var len = toLength(O.length);
      var actualStart = toAbsoluteIndex(start, len);
      var argumentsLength = arguments.length;
      var insertCount, actualDeleteCount, A, k, from, to;
      if (argumentsLength === 0) {
        insertCount = actualDeleteCount = 0;
      } else if (argumentsLength === 1) {
        insertCount = 0;
        actualDeleteCount = len - actualStart;
      } else {
        insertCount = argumentsLength - 2;
        actualDeleteCount = min\$2(max(toInteger(deleteCount), 0), len - actualStart);
      }
      if (len + insertCount - actualDeleteCount > MAX_SAFE_INTEGER) {
        throw TypeError(MAXIMUM_ALLOWED_LENGTH_EXCEEDED);
      }
      A = arraySpeciesCreate(O, actualDeleteCount);
      for (k = 0; k < actualDeleteCount; k++) {
        from = actualStart + k;
        if (from in O) createProperty(A, k, O[from]);
      }
      A.length = actualDeleteCount;
      if (insertCount < actualDeleteCount) {
        for (k = actualStart; k < len - actualDeleteCount; k++) {
          from = k + actualDeleteCount;
          to = k + insertCount;
          if (from in O) O[to] = O[from];
          else delete O[to];
        }
        for (k = len; k > len - actualDeleteCount + insertCount; k--) delete O[k - 1];
      } else if (insertCount > actualDeleteCount) {
        for (k = len - actualDeleteCount; k > actualStart; k--) {
          from = k + actualDeleteCount - 1;
          to = k + insertCount - 1;
          if (from in O) O[to] = O[from];
          else delete O[to];
        }
      }
      for (k = 0; k < insertCount; k++) {
        O[k + actualStart] = arguments[k + 2];
      }
      O.length = len - actualDeleteCount + insertCount;
      return A;
    }
  });

  var getOwnPropertyNames = objectGetOwnPropertyNames.f;
  var getOwnPropertyDescriptor\$2 = objectGetOwnPropertyDescriptor.f;
  var defineProperty = objectDefineProperty.f;
  var trim = stringTrim.trim;

  var NUMBER = 'Number';
  var NativeNumber = global_1[NUMBER];
  var NumberPrototype = NativeNumber.prototype;

  // Opera ~12 has broken Object#toString
  var BROKEN_CLASSOF = classofRaw(objectCreate(NumberPrototype)) == NUMBER;

  // `ToNumber` abstract operation
  // https://tc39.es/ecma262/#sec-tonumber
  var toNumber = function (argument) {
    var it = toPrimitive(argument, false);
    var first, third, radix, maxCode, digits, length, index, code;
    if (typeof it == 'string' && it.length > 2) {
      it = trim(it);
      first = it.charCodeAt(0);
      if (first === 43 || first === 45) {
        third = it.charCodeAt(2);
        if (third === 88 || third === 120) return NaN; // Number('+0x1') should be NaN, old V8 fix
      } else if (first === 48) {
        switch (it.charCodeAt(1)) {
          case 66: case 98: radix = 2; maxCode = 49; break; // fast equal of /^0b[01]+\$/i
          case 79: case 111: radix = 8; maxCode = 55; break; // fast equal of /^0o[0-7]+\$/i
          default: return +it;
        }
        digits = it.slice(2);
        length = digits.length;
        for (index = 0; index < length; index++) {
          code = digits.charCodeAt(index);
          // parseInt parses a string to a first unavailable symbol
          // but ToNumber should return NaN if a string contains unavailable symbols
          if (code < 48 || code > maxCode) return NaN;
        } return parseInt(digits, radix);
      }
    } return +it;
  };

  // `Number` constructor
  // https://tc39.es/ecma262/#sec-number-constructor
  if (isForced_1(NUMBER, !NativeNumber(' 0o1') || !NativeNumber('0b1') || NativeNumber('+0x1'))) {
    var NumberWrapper = function Number(value) {
      var it = arguments.length < 1 ? 0 : value;
      var dummy = this;
      return dummy instanceof NumberWrapper
        // check on 1..constructor(foo) case
        && (BROKEN_CLASSOF ? fails(function () { NumberPrototype.valueOf.call(dummy); }) : classofRaw(dummy) != NUMBER)
          ? inheritIfRequired(new NativeNumber(toNumber(it)), dummy, NumberWrapper) : toNumber(it);
    };
    for (var keys = descriptors ? getOwnPropertyNames(NativeNumber) : (
      // ES3:
      'MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,' +
      // ES2015 (in case, if modules with ES2015 Number statics required before):
      'EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,' +
      'MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger,' +
      // ESNext
      'fromString,range'
    ).split(','), j = 0, key; keys.length > j; j++) {
      if (has\$1(NativeNumber, key = keys[j]) && !has\$1(NumberWrapper, key)) {
        defineProperty(NumberWrapper, key, getOwnPropertyDescriptor\$2(NativeNumber, key));
      }
    }
    NumberWrapper.prototype = NumberPrototype;
    NumberPrototype.constructor = NumberWrapper;
    redefine(global_1, NUMBER, NumberWrapper);
  }

  var nativeReverse = [].reverse;
  var test = [1, 2];

  // `Array.prototype.reverse` method
  // https://tc39.es/ecma262/#sec-array.prototype.reverse
  // fix for Safari 12.0 bug
  // https://bugs.webkit.org/show_bug.cgi?id=188794
  _export({ target: 'Array', proto: true, forced: String(test) === String(test.reverse()) }, {
    reverse: function reverse() {
      // eslint-disable-next-line no-self-assign -- dirty hack
      if (isArray(this)) this.length = this.length;
      return nativeReverse.call(this);
    }
  });

  /* eslint-disable no-unused-vars */

  var VERSION = '1.18.3';
  var bootstrapVersion = 4;

  try {
    var rawVersion = \$__default['default'].fn.dropdown.Constructor.VERSION; // Only try to parse VERSION if it is defined.
    // It is undefined in older versions of Bootstrap (tested with 3.1.1).

    if (rawVersion !== undefined) {
      bootstrapVersion = parseInt(rawVersion, 10);
    }
  } catch (e) {// ignore
  }

  try {
    // eslint-disable-next-line no-undef
    var _rawVersion = bootstrap.Tooltip.VERSION;

    if (_rawVersion !== undefined) {
      bootstrapVersion = parseInt(_rawVersion, 10);
    }
  } catch (e) {// ignore
  }

  var CONSTANTS = {
    3: {
      iconsPrefix: 'glyphicon',
      icons: {
        paginationSwitchDown: 'glyphicon-collapse-down icon-chevron-down',
        paginationSwitchUp: 'glyphicon-collapse-up icon-chevron-up',
        refresh: 'glyphicon-refresh icon-refresh',
        toggleOff: 'glyphicon-list-alt icon-list-alt',
        toggleOn: 'glyphicon-list-alt icon-list-alt',
        columns: 'glyphicon-th icon-th',
        detailOpen: 'glyphicon-plus icon-plus',
        detailClose: 'glyphicon-minus icon-minus',
        fullscreen: 'glyphicon-fullscreen',
        search: 'glyphicon-search',
        clearSearch: 'glyphicon-trash'
      },
      classes: {
        buttonsPrefix: 'btn',
        buttons: 'default',
        buttonsGroup: 'btn-group',
        buttonsDropdown: 'btn-group',
        pull: 'pull',
        inputGroup: 'input-group',
        inputPrefix: 'input-',
        input: 'form-control',
        paginationDropdown: 'btn-group dropdown',
        dropup: 'dropup',
        dropdownActive: 'active',
        paginationActive: 'active',
        buttonActive: 'active'
      },
      html: {
        toolbarDropdown: ['<ul class=\"dropdown-menu\" role=\"menu\">', '</ul>'],
        toolbarDropdownItem: '<li class=\"dropdown-item-marker\" role=\"menuitem\"><label>%s</label></li>',
        toolbarDropdownSeparator: '<li class=\"divider\"></li>',
        pageDropdown: ['<ul class=\"dropdown-menu\" role=\"menu\">', '</ul>'],
        pageDropdownItem: '<li role=\"menuitem\" class=\"%s\"><a href=\"#\">%s</a></li>',
        dropdownCaret: '<span class=\"caret\"></span>',
        pagination: ['<ul class=\"pagination%s\">', '</ul>'],
        paginationItem: '<li class=\"page-item%s\"><a class=\"page-link\" aria-label=\"%s\" href=\"javascript:void(0)\">%s</a></li>',
        icon: '<i class=\"%s %s\"></i>',
        inputGroup: '<div class=\"input-group\">%s<span class=\"input-group-btn\">%s</span></div>',
        searchInput: '<input class=\"%s%s\" type=\"text\" placeholder=\"%s\">',
        searchButton: '<button class=\"%s\" type=\"button\" name=\"search\" title=\"%s\">%s %s</button>',
        searchClearButton: '<button class=\"%s\" type=\"button\" name=\"clearSearch\" title=\"%s\">%s %s</button>'
      }
    },
    4: {
      iconsPrefix: 'fa',
      icons: {
        paginationSwitchDown: 'fa-caret-square-down',
        paginationSwitchUp: 'fa-caret-square-up',
        refresh: 'fa-sync',
        toggleOff: 'fa-toggle-off',
        toggleOn: 'fa-toggle-on',
        columns: 'fa-th-list',
        detailOpen: 'fa-plus',
        detailClose: 'fa-minus',
        fullscreen: 'fa-arrows-alt',
        search: 'fa-search',
        clearSearch: 'fa-trash'
      },
      classes: {
        buttonsPrefix: 'btn',
        buttons: 'secondary',
        buttonsGroup: 'btn-group',
        buttonsDropdown: 'btn-group',
        pull: 'float',
        inputGroup: 'btn-group',
        inputPrefix: 'form-control-',
        input: 'form-control',
        paginationDropdown: 'btn-group dropdown',
        dropup: 'dropup',
        dropdownActive: 'active',
        paginationActive: 'active',
        buttonActive: 'active'
      },
      html: {
        toolbarDropdown: ['<div class=\"dropdown-menu dropdown-menu-right\">', '</div>'],
        toolbarDropdownItem: '<label class=\"dropdown-item dropdown-item-marker\">%s</label>',
        pageDropdown: ['<div class=\"dropdown-menu\">', '</div>'],
        pageDropdownItem: '<a class=\"dropdown-item %s\" href=\"#\">%s</a>',
        toolbarDropdownSeparator: '<div class=\"dropdown-divider\"></div>',
        dropdownCaret: '<span class=\"caret\"></span>',
        pagination: ['<ul class=\"pagination%s\">', '</ul>'],
        paginationItem: '<li class=\"page-item%s\"><a class=\"page-link\" aria-label=\"%s\" href=\"javascript:void(0)\">%s</a></li>',
        icon: '<i class=\"%s %s\"></i>',
        inputGroup: '<div class=\"input-group\">%s<div class=\"input-group-append\">%s</div></div>',
        searchInput: '<input class=\"%s%s\" type=\"text\" placeholder=\"%s\">',
        searchButton: '<button class=\"%s\" type=\"button\" name=\"search\" title=\"%s\">%s %s</button>',
        searchClearButton: '<button class=\"%s\" type=\"button\" name=\"clearSearch\" title=\"%s\">%s %s</button>'
      }
    },
    5: {
      iconsPrefix: 'fa',
      icons: {
        paginationSwitchDown: 'fa-caret-square-down',
        paginationSwitchUp: 'fa-caret-square-up',
        refresh: 'fa-sync',
        toggleOff: 'fa-toggle-off',
        toggleOn: 'fa-toggle-on',
        columns: 'fa-th-list',
        detailOpen: 'fa-plus',
        detailClose: 'fa-minus',
        fullscreen: 'fa-arrows-alt',
        search: 'fa-search',
        clearSearch: 'fa-trash'
      },
      classes: {
        buttonsPrefix: 'btn',
        buttons: 'secondary',
        buttonsGroup: 'btn-group',
        buttonsDropdown: 'btn-group',
        pull: 'float',
        inputGroup: 'btn-group',
        inputPrefix: 'form-control-',
        input: 'form-control',
        paginationDropdown: 'btn-group dropdown',
        dropup: 'dropup',
        dropdownActive: 'active',
        paginationActive: 'active',
        buttonActive: 'active'
      },
      html: {
        dataToggle: 'data-bs-toggle',
        toolbarDropdown: ['<div class=\"dropdown-menu dropdown-menu-right\">', '</div>'],
        toolbarDropdownItem: '<label class=\"dropdown-item dropdown-item-marker\">%s</label>',
        pageDropdown: ['<div class=\"dropdown-menu\">', '</div>'],
        pageDropdownItem: '<a class=\"dropdown-item %s\" href=\"#\">%s</a>',
        toolbarDropdownSeparator: '<div class=\"dropdown-divider\"></div>',
        dropdownCaret: '<span class=\"caret\"></span>',
        pagination: ['<ul class=\"pagination%s\">', '</ul>'],
        paginationItem: '<li class=\"page-item%s\"><a class=\"page-link\" aria-label=\"%s\" href=\"javascript:void(0)\">%s</a></li>',
        icon: '<i class=\"%s %s\"></i>',
        inputGroup: '<div class=\"input-group\">%s<div class=\"input-group-append\">%s</div></div>',
        searchInput: '<input class=\"%s%s\" type=\"text\" placeholder=\"%s\">',
        searchButton: '<button class=\"%s\" type=\"button\" name=\"search\" title=\"%s\">%s %s</button>',
        searchClearButton: '<button class=\"%s\" type=\"button\" name=\"clearSearch\" title=\"%s\">%s %s</button>'
      }
    }
  }[bootstrapVersion];
  var DEFAULTS = {
    height: undefined,
    classes: 'table table-bordered table-hover',
    buttons: {},
    theadClasses: '',
    headerStyle: function headerStyle(column) {
      return {};
    },
    rowStyle: function rowStyle(row, index) {
      return {};
    },
    rowAttributes: function rowAttributes(row, index) {
      return {};
    },
    undefinedText: '-',
    locale: undefined,
    virtualScroll: false,
    virtualScrollItemHeight: undefined,
    sortable: true,
    sortClass: undefined,
    silentSort: true,
    sortName: undefined,
    sortOrder: undefined,
    sortReset: false,
    sortStable: false,
    rememberOrder: false,
    serverSort: true,
    customSort: undefined,
    columns: [[]],
    data: [],
    url: undefined,
    method: 'get',
    cache: true,
    contentType: 'application/json',
    dataType: 'json',
    ajax: undefined,
    ajaxOptions: {},
    queryParams: function queryParams(params) {
      return params;
    },
    queryParamsType: 'limit',
    // 'limit', undefined
    responseHandler: function responseHandler(res) {
      return res;
    },
    totalField: 'total',
    totalNotFilteredField: 'totalNotFiltered',
    dataField: 'rows',
    footerField: 'footer',
    pagination: false,
    paginationParts: ['pageInfo', 'pageSize', 'pageList'],
    showExtendedPagination: false,
    paginationLoop: true,
    sidePagination: 'client',
    // client or server
    totalRows: 0,
    totalNotFiltered: 0,
    pageNumber: 1,
    pageSize: 10,
    pageList: [10, 25, 50, 100],
    paginationHAlign: 'right',
    // right, left
    paginationVAlign: 'bottom',
    // bottom, top, both
    paginationDetailHAlign: 'left',
    // right, left
    paginationPreText: '&lsaquo;',
    paginationNextText: '&rsaquo;',
    paginationSuccessivelySize: 5,
    // Maximum successively number of pages in a row
    paginationPagesBySide: 1,
    // Number of pages on each side (right, left) of the current page.
    paginationUseIntermediate: false,
    // Calculate intermediate pages for quick access
    search: false,
    searchHighlight: false,
    searchOnEnterKey: false,
    strictSearch: false,
    searchSelector: false,
    visibleSearch: false,
    showButtonIcons: true,
    showButtonText: false,
    showSearchButton: false,
    showSearchClearButton: false,
    trimOnSearch: true,
    searchAlign: 'right',
    searchTimeOut: 500,
    searchText: '',
    customSearch: undefined,
    showHeader: true,
    showFooter: false,
    footerStyle: function footerStyle(column) {
      return {};
    },
    searchAccentNeutralise: false,
    showColumns: false,
    showColumnsToggleAll: false,
    showColumnsSearch: false,
    minimumCountColumns: 1,
    showPaginationSwitch: false,
    showRefresh: false,
    showToggle: false,
    showFullscreen: false,
    smartDisplay: true,
    escape: false,
    filterOptions: {
      filterAlgorithm: 'and'
    },
    idField: undefined,
    selectItemName: 'btSelectItem',
    clickToSelect: false,
    ignoreClickToSelectOn: function ignoreClickToSelectOn(_ref) {
      var tagName = _ref.tagName;
      return ['A', 'BUTTON'].includes(tagName);
    },
    singleSelect: false,
    checkboxHeader: true,
    maintainMetaData: false,
    multipleSelectRow: false,
    uniqueId: undefined,
    cardView: false,
    detailView: false,
    detailViewIcon: true,
    detailViewByClick: false,
    detailViewAlign: 'left',
    detailFormatter: function detailFormatter(index, row) {
      return '';
    },
    detailFilter: function detailFilter(index, row) {
      return true;
    },
    toolbar: undefined,
    toolbarAlign: 'left',
    buttonsToolbar: undefined,
    buttonsAlign: 'right',
    buttonsOrder: ['paginationSwitch', 'refresh', 'toggle', 'fullscreen', 'columns'],
    buttonsPrefix: CONSTANTS.classes.buttonsPrefix,
    buttonsClass: CONSTANTS.classes.buttons,
    icons: CONSTANTS.icons,
    iconSize: undefined,
    iconsPrefix: CONSTANTS.iconsPrefix,
    // glyphicon or fa(font-awesome)
    loadingFontSize: 'auto',
    loadingTemplate: function loadingTemplate(loadingMessage) {
      return \"<span class=\\\"loading-wrap\\\">\\n      <span class=\\\"loading-text\\\">\".concat(loadingMessage, \"</span>\\n      <span class=\\\"animation-wrap\\\"><span class=\\\"animation-dot\\\"></span></span>\\n      </span>\\n    \");
    },
    onAll: function onAll(name, args) {
      return false;
    },
    onClickCell: function onClickCell(field, value, row, \$element) {
      return false;
    },
    onDblClickCell: function onDblClickCell(field, value, row, \$element) {
      return false;
    },
    onClickRow: function onClickRow(item, \$element) {
      return false;
    },
    onDblClickRow: function onDblClickRow(item, \$element) {
      return false;
    },
    onSort: function onSort(name, order) {
      return false;
    },
    onCheck: function onCheck(row) {
      return false;
    },
    onUncheck: function onUncheck(row) {
      return false;
    },
    onCheckAll: function onCheckAll(rows) {
      return false;
    },
    onUncheckAll: function onUncheckAll(rows) {
      return false;
    },
    onCheckSome: function onCheckSome(rows) {
      return false;
    },
    onUncheckSome: function onUncheckSome(rows) {
      return false;
    },
    onLoadSuccess: function onLoadSuccess(data) {
      return false;
    },
    onLoadError: function onLoadError(status) {
      return false;
    },
    onColumnSwitch: function onColumnSwitch(field, checked) {
      return false;
    },
    onPageChange: function onPageChange(number, size) {
      return false;
    },
    onSearch: function onSearch(text) {
      return false;
    },
    onToggle: function onToggle(cardView) {
      return false;
    },
    onPreBody: function onPreBody(data) {
      return false;
    },
    onPostBody: function onPostBody() {
      return false;
    },
    onPostHeader: function onPostHeader() {
      return false;
    },
    onPostFooter: function onPostFooter() {
      return false;
    },
    onExpandRow: function onExpandRow(index, row, \$detail) {
      return false;
    },
    onCollapseRow: function onCollapseRow(index, row) {
      return false;
    },
    onRefreshOptions: function onRefreshOptions(options) {
      return false;
    },
    onRefresh: function onRefresh(params) {
      return false;
    },
    onResetView: function onResetView() {
      return false;
    },
    onScrollBody: function onScrollBody() {
      return false;
    }
  };
  var EN = {
    formatLoadingMessage: function formatLoadingMessage() {
      return 'Loading, please wait';
    },
    formatRecordsPerPage: function formatRecordsPerPage(pageNumber) {
      return \"\".concat(pageNumber, \" rows per page\");
    },
    formatShowingRows: function formatShowingRows(pageFrom, pageTo, totalRows, totalNotFiltered) {
      if (totalNotFiltered !== undefined && totalNotFiltered > 0 && totalNotFiltered > totalRows) {
        return \"Showing \".concat(pageFrom, \" to \").concat(pageTo, \" of \").concat(totalRows, \" rows (filtered from \").concat(totalNotFiltered, \" total rows)\");
      }

      return \"Showing \".concat(pageFrom, \" to \").concat(pageTo, \" of \").concat(totalRows, \" rows\");
    },
    formatSRPaginationPreText: function formatSRPaginationPreText() {
      return 'previous page';
    },
    formatSRPaginationPageText: function formatSRPaginationPageText(page) {
      return \"to page \".concat(page);
    },
    formatSRPaginationNextText: function formatSRPaginationNextText() {
      return 'next page';
    },
    formatDetailPagination: function formatDetailPagination(totalRows) {
      return \"Showing \".concat(totalRows, \" rows\");
    },
    formatSearch: function formatSearch() {
      return 'Search';
    },
    formatClearSearch: function formatClearSearch() {
      return 'Clear Search';
    },
    formatNoMatches: function formatNoMatches() {
      return 'No matching records found';
    },
    formatPaginationSwitch: function formatPaginationSwitch() {
      return 'Hide/Show pagination';
    },
    formatPaginationSwitchDown: function formatPaginationSwitchDown() {
      return 'Show pagination';
    },
    formatPaginationSwitchUp: function formatPaginationSwitchUp() {
      return 'Hide pagination';
    },
    formatRefresh: function formatRefresh() {
      return 'Refresh';
    },
    formatToggle: function formatToggle() {
      return 'Toggle';
    },
    formatToggleOn: function formatToggleOn() {
      return 'Show card view';
    },
    formatToggleOff: function formatToggleOff() {
      return 'Hide card view';
    },
    formatColumns: function formatColumns() {
      return 'Columns';
    },
    formatColumnsToggleAll: function formatColumnsToggleAll() {
      return 'Toggle all';
    },
    formatFullscreen: function formatFullscreen() {
      return 'Fullscreen';
    },
    formatAllRows: function formatAllRows() {
      return 'All';
    }
  };
  var COLUMN_DEFAULTS = {
    field: undefined,
    title: undefined,
    titleTooltip: undefined,
    class: undefined,
    width: undefined,
    widthUnit: 'px',
    rowspan: undefined,
    colspan: undefined,
    align: undefined,
    // left, right, center
    halign: undefined,
    // left, right, center
    falign: undefined,
    // left, right, center
    valign: undefined,
    // top, middle, bottom
    cellStyle: undefined,
    radio: false,
    checkbox: false,
    checkboxEnabled: true,
    clickToSelect: true,
    showSelectTitle: false,
    sortable: false,
    sortName: undefined,
    order: 'asc',
    // asc, desc
    sorter: undefined,
    visible: true,
    switchable: true,
    cardVisible: true,
    searchable: true,
    formatter: undefined,
    footerFormatter: undefined,
    detailFormatter: undefined,
    searchFormatter: true,
    searchHighlightFormatter: false,
    escape: false,
    events: undefined
  };
  var METHODS = ['getOptions', 'refreshOptions', 'getData', 'getSelections', 'load', 'append', 'prepend', 'remove', 'removeAll', 'insertRow', 'updateRow', 'getRowByUniqueId', 'updateByUniqueId', 'removeByUniqueId', 'updateCell', 'updateCellByUniqueId', 'showRow', 'hideRow', 'getHiddenRows', 'showColumn', 'hideColumn', 'getVisibleColumns', 'getHiddenColumns', 'showAllColumns', 'hideAllColumns', 'mergeCells', 'checkAll', 'uncheckAll', 'checkInvert', 'check', 'uncheck', 'checkBy', 'uncheckBy', 'refresh', 'destroy', 'resetView', 'showLoading', 'hideLoading', 'togglePagination', 'toggleFullscreen', 'toggleView', 'resetSearch', 'filterBy', 'scrollTo', 'getScrollPosition', 'selectPage', 'prevPage', 'nextPage', 'toggleDetailView', 'expandRow', 'collapseRow', 'expandRowByUniqueId', 'collapseRowByUniqueId', 'expandAllRows', 'collapseAllRows', 'updateColumnTitle', 'updateFormatText'];
  var EVENTS = {
    'all.bs.table': 'onAll',
    'click-row.bs.table': 'onClickRow',
    'dbl-click-row.bs.table': 'onDblClickRow',
    'click-cell.bs.table': 'onClickCell',
    'dbl-click-cell.bs.table': 'onDblClickCell',
    'sort.bs.table': 'onSort',
    'check.bs.table': 'onCheck',
    'uncheck.bs.table': 'onUncheck',
    'check-all.bs.table': 'onCheckAll',
    'uncheck-all.bs.table': 'onUncheckAll',
    'check-some.bs.table': 'onCheckSome',
    'uncheck-some.bs.table': 'onUncheckSome',
    'load-success.bs.table': 'onLoadSuccess',
    'load-error.bs.table': 'onLoadError',
    'column-switch.bs.table': 'onColumnSwitch',
    'page-change.bs.table': 'onPageChange',
    'search.bs.table': 'onSearch',
    'toggle.bs.table': 'onToggle',
    'pre-body.bs.table': 'onPreBody',
    'post-body.bs.table': 'onPostBody',
    'post-header.bs.table': 'onPostHeader',
    'post-footer.bs.table': 'onPostFooter',
    'expand-row.bs.table': 'onExpandRow',
    'collapse-row.bs.table': 'onCollapseRow',
    'refresh-options.bs.table': 'onRefreshOptions',
    'reset-view.bs.table': 'onResetView',
    'refresh.bs.table': 'onRefresh',
    'scroll-body.bs.table': 'onScrollBody'
  };
  Object.assign(DEFAULTS, EN);
  var Constants = {
    VERSION: VERSION,
    THEME: \"bootstrap\".concat(bootstrapVersion),
    CONSTANTS: CONSTANTS,
    DEFAULTS: DEFAULTS,
    COLUMN_DEFAULTS: COLUMN_DEFAULTS,
    METHODS: METHODS,
    EVENTS: EVENTS,
    LOCALES: {
      en: EN,
      'en-US': EN
    }
  };

  var FAILS_ON_PRIMITIVES = fails(function () { objectKeys(1); });

  // `Object.keys` method
  // https://tc39.es/ecma262/#sec-object.keys
  _export({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES }, {
    keys: function keys(it) {
      return objectKeys(toObject(it));
    }
  });

  var getOwnPropertyDescriptor\$1 = objectGetOwnPropertyDescriptor.f;






  var nativeStartsWith = ''.startsWith;
  var min\$1 = Math.min;

  var CORRECT_IS_REGEXP_LOGIC\$1 = correctIsRegexpLogic('startsWith');
  // https://github.com/zloirock/core-js/pull/702
  var MDN_POLYFILL_BUG\$1 = !CORRECT_IS_REGEXP_LOGIC\$1 && !!function () {
    var descriptor = getOwnPropertyDescriptor\$1(String.prototype, 'startsWith');
    return descriptor && !descriptor.writable;
  }();

  // `String.prototype.startsWith` method
  // https://tc39.es/ecma262/#sec-string.prototype.startswith
  _export({ target: 'String', proto: true, forced: !MDN_POLYFILL_BUG\$1 && !CORRECT_IS_REGEXP_LOGIC\$1 }, {
    startsWith: function startsWith(searchString /* , position = 0 */) {
      var that = String(requireObjectCoercible(this));
      notARegexp(searchString);
      var index = toLength(min\$1(arguments.length > 1 ? arguments[1] : undefined, that.length));
      var search = String(searchString);
      return nativeStartsWith
        ? nativeStartsWith.call(that, search, index)
        : that.slice(index, index + search.length) === search;
    }
  });

  var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f;






  var nativeEndsWith = ''.endsWith;
  var min = Math.min;

  var CORRECT_IS_REGEXP_LOGIC = correctIsRegexpLogic('endsWith');
  // https://github.com/zloirock/core-js/pull/702
  var MDN_POLYFILL_BUG = !CORRECT_IS_REGEXP_LOGIC && !!function () {
    var descriptor = getOwnPropertyDescriptor(String.prototype, 'endsWith');
    return descriptor && !descriptor.writable;
  }();

  // `String.prototype.endsWith` method
  // https://tc39.es/ecma262/#sec-string.prototype.endswith
  _export({ target: 'String', proto: true, forced: !MDN_POLYFILL_BUG && !CORRECT_IS_REGEXP_LOGIC }, {
    endsWith: function endsWith(searchString /* , endPosition = @length */) {
      var that = String(requireObjectCoercible(this));
      notARegexp(searchString);
      var endPosition = arguments.length > 1 ? arguments[1] : undefined;
      var len = toLength(that.length);
      var end = endPosition === undefined ? len : min(toLength(endPosition), len);
      var search = String(searchString);
      return nativeEndsWith
        ? nativeEndsWith.call(that, search, end)
        : that.slice(end - search.length, end) === search;
    }
  });

  var Utils = {
    getSearchInput: function getSearchInput(that) {
      if (typeof that.options.searchSelector === 'string') {
        return \$__default['default'](that.options.searchSelector);
      }

      return that.\$toolbar.find('.search input');
    },
    // it only does '%s', and return '' when arguments are undefined
    sprintf: function sprintf(_str) {
      for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
        args[_key - 1] = arguments[_key];
      }

      var flag = true;
      var i = 0;

      var str = _str.replace(/%s/g, function () {
        var arg = args[i++];

        if (typeof arg === 'undefined') {
          flag = false;
          return '';
        }

        return arg;
      });

      return flag ? str : '';
    },
    isObject: function isObject(val) {
      return val instanceof Object && !Array.isArray(val);
    },
    isEmptyObject: function isEmptyObject() {
      var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      return Object.entries(obj).length === 0 && obj.constructor === Object;
    },
    isNumeric: function isNumeric(n) {
      return !isNaN(parseFloat(n)) && isFinite(n);
    },
    getFieldTitle: function getFieldTitle(list, value) {
      var _iterator = _createForOfIteratorHelper(list),
          _step;

      try {
        for (_iterator.s(); !(_step = _iterator.n()).done;) {
          var item = _step.value;

          if (item.field === value) {
            return item.title;
          }
        }
      } catch (err) {
        _iterator.e(err);
      } finally {
        _iterator.f();
      }

      return '';
    },
    setFieldIndex: function setFieldIndex(columns) {
      var totalCol = 0;
      var flag = [];

      var _iterator2 = _createForOfIteratorHelper(columns[0]),
          _step2;

      try {
        for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
          var column = _step2.value;
          totalCol += column.colspan || 1;
        }
      } catch (err) {
        _iterator2.e(err);
      } finally {
        _iterator2.f();
      }

      for (var i = 0; i < columns.length; i++) {
        flag[i] = [];

        for (var j = 0; j < totalCol; j++) {
          flag[i][j] = false;
        }
      }

      for (var _i = 0; _i < columns.length; _i++) {
        var _iterator3 = _createForOfIteratorHelper(columns[_i]),
            _step3;

        try {
          for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
            var r = _step3.value;
            var rowspan = r.rowspan || 1;
            var colspan = r.colspan || 1;

            var index = flag[_i].indexOf(false);

            r.colspanIndex = index;

            if (colspan === 1) {
              r.fieldIndex = index; // when field is undefined, use index instead

              if (typeof r.field === 'undefined') {
                r.field = index;
              }
            } else {
              r.colspanGroup = r.colspan;
            }

            for (var _j = 0; _j < rowspan; _j++) {
              for (var k = 0; k < colspan; k++) {
                flag[_i + _j][index + k] = true;
              }
            }
          }
        } catch (err) {
          _iterator3.e(err);
        } finally {
          _iterator3.f();
        }
      }
    },
    normalizeAccent: function normalizeAccent(value) {
      if (typeof value !== 'string') {
        return value;
      }

      return value.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '');
    },
    updateFieldGroup: function updateFieldGroup(columns) {
      var _ref;

      var allColumns = (_ref = []).concat.apply(_ref, _toConsumableArray(columns));

      var _iterator4 = _createForOfIteratorHelper(columns),
          _step4;

      try {
        for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
          var c = _step4.value;

          var _iterator5 = _createForOfIteratorHelper(c),
              _step5;

          try {
            for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
              var r = _step5.value;

              if (r.colspanGroup > 1) {
                var colspan = 0;

                var _loop = function _loop(i) {
                  var column = allColumns.find(function (col) {
                    return col.fieldIndex === i;
                  });

                  if (column.visible) {
                    colspan++;
                  }
                };

                for (var i = r.colspanIndex; i < r.colspanIndex + r.colspanGroup; i++) {
                  _loop(i);
                }

                r.colspan = colspan;
                r.visible = colspan > 0;
              }
            }
          } catch (err) {
            _iterator5.e(err);
          } finally {
            _iterator5.f();
          }
        }
      } catch (err) {
        _iterator4.e(err);
      } finally {
        _iterator4.f();
      }
    },
    getScrollBarWidth: function getScrollBarWidth() {
      if (this.cachedWidth === undefined) {
        var \$inner = \$__default['default']('<div/>').addClass('fixed-table-scroll-inner');
        var \$outer = \$__default['default']('<div/>').addClass('fixed-table-scroll-outer');
        \$outer.append(\$inner);
        \$__default['default']('body').append(\$outer);
        var w1 = \$inner[0].offsetWidth;
        \$outer.css('overflow', 'scroll');
        var w2 = \$inner[0].offsetWidth;

        if (w1 === w2) {
          w2 = \$outer[0].clientWidth;
        }

        \$outer.remove();
        this.cachedWidth = w1 - w2;
      }

      return this.cachedWidth;
    },
    calculateObjectValue: function calculateObjectValue(self, name, args, defaultValue) {
      var func = name;

      if (typeof name === 'string') {
        // support obj.func1.func2
        var names = name.split('.');

        if (names.length > 1) {
          func = window;

          var _iterator6 = _createForOfIteratorHelper(names),
              _step6;

          try {
            for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
              var f = _step6.value;
              func = func[f];
            }
          } catch (err) {
            _iterator6.e(err);
          } finally {
            _iterator6.f();
          }
        } else {
          func = window[name];
        }
      }

      if (func !== null && _typeof(func) === 'object') {
        return func;
      }

      if (typeof func === 'function') {
        return func.apply(self, args || []);
      }

      if (!func && typeof name === 'string' && this.sprintf.apply(this, [name].concat(_toConsumableArray(args)))) {
        return this.sprintf.apply(this, [name].concat(_toConsumableArray(args)));
      }

      return defaultValue;
    },
    compareObjects: function compareObjects(objectA, objectB, compareLength) {
      var aKeys = Object.keys(objectA);
      var bKeys = Object.keys(objectB);

      if (compareLength && aKeys.length !== bKeys.length) {
        return false;
      }

      for (var _i2 = 0, _aKeys = aKeys; _i2 < _aKeys.length; _i2++) {
        var key = _aKeys[_i2];

        if (bKeys.includes(key) && objectA[key] !== objectB[key]) {
          return false;
        }
      }

      return true;
    },
    escapeHTML: function escapeHTML(text) {
      if (typeof text === 'string') {
        return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;').replace(/'/g, '&#039;').replace(/`/g, '&#x60;');
      }

      return text;
    },
    unescapeHTML: function unescapeHTML(text) {
      if (typeof text === 'string') {
        return text.replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '\"').replace(/&#039;/g, '\\'').replace(/&#x60;/g, '`');
      }

      return text;
    },
    getRealDataAttr: function getRealDataAttr(dataAttr) {
      for (var _i3 = 0, _Object\$entries = Object.entries(dataAttr); _i3 < _Object\$entries.length; _i3++) {
        var _Object\$entries\$_i = _slicedToArray(_Object\$entries[_i3], 2),
            attr = _Object\$entries\$_i[0],
            value = _Object\$entries\$_i[1];

        var auxAttr = attr.split(/(?=[A-Z])/).join('-').toLowerCase();

        if (auxAttr !== attr) {
          dataAttr[auxAttr] = value;
          delete dataAttr[attr];
        }
      }

      return dataAttr;
    },
    getItemField: function getItemField(item, field, escape) {
      var value = item;

      if (typeof field !== 'string' || item.hasOwnProperty(field)) {
        return escape ? this.escapeHTML(item[field]) : item[field];
      }

      var props = field.split('.');

      var _iterator7 = _createForOfIteratorHelper(props),
          _step7;

      try {
        for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
          var p = _step7.value;
          value = value && value[p];
        }
      } catch (err) {
        _iterator7.e(err);
      } finally {
        _iterator7.f();
      }

      return escape ? this.escapeHTML(value) : value;
    },
    isIEBrowser: function isIEBrowser() {
      return navigator.userAgent.includes('MSIE ') || /Trident.*rv:11\\./.test(navigator.userAgent);
    },
    findIndex: function findIndex(items, item) {
      var _iterator8 = _createForOfIteratorHelper(items),
          _step8;

      try {
        for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
          var it = _step8.value;

          if (JSON.stringify(it) === JSON.stringify(item)) {
            return items.indexOf(it);
          }
        }
      } catch (err) {
        _iterator8.e(err);
      } finally {
        _iterator8.f();
      }

      return -1;
    },
    trToData: function trToData(columns, \$els) {
      var _this = this;

      var data = [];
      var m = [];
      \$els.each(function (y, el) {
        var \$el = \$__default['default'](el);
        var row = {}; // save tr's id, class and data-* attributes

        row._id = \$el.attr('id');
        row._class = \$el.attr('class');
        row._data = _this.getRealDataAttr(\$el.data());
        row._style = \$el.attr('style');
        \$el.find('>td,>th').each(function (_x, el) {
          var \$el = \$__default['default'](el);
          var cspan = +\$el.attr('colspan') || 1;
          var rspan = +\$el.attr('rowspan') || 1;
          var x = _x; // skip already occupied cells in current row

          for (; m[y] && m[y][x]; x++) {// ignore
          } // mark matrix elements occupied by current cell with true


          for (var tx = x; tx < x + cspan; tx++) {
            for (var ty = y; ty < y + rspan; ty++) {
              if (!m[ty]) {
                // fill missing rows
                m[ty] = [];
              }

              m[ty][tx] = true;
            }
          }

          var field = columns[x].field;
          row[field] = \$el.html().trim(); // save td's id, class and data-* attributes

          row[\"_\".concat(field, \"_id\")] = \$el.attr('id');
          row[\"_\".concat(field, \"_class\")] = \$el.attr('class');
          row[\"_\".concat(field, \"_rowspan\")] = \$el.attr('rowspan');
          row[\"_\".concat(field, \"_colspan\")] = \$el.attr('colspan');
          row[\"_\".concat(field, \"_title\")] = \$el.attr('title');
          row[\"_\".concat(field, \"_data\")] = _this.getRealDataAttr(\$el.data());
          row[\"_\".concat(field, \"_style\")] = \$el.attr('style');
        });
        data.push(row);
      });
      return data;
    },
    sort: function sort(a, b, order, sortStable, aPosition, bPosition) {
      if (a === undefined || a === null) {
        a = '';
      }

      if (b === undefined || b === null) {
        b = '';
      }

      if (sortStable && a === b) {
        a = aPosition;
        b = bPosition;
      } // If both values are numeric, do a numeric comparison


      if (this.isNumeric(a) && this.isNumeric(b)) {
        // Convert numerical values form string to float.
        a = parseFloat(a);
        b = parseFloat(b);

        if (a < b) {
          return order * -1;
        }

        if (a > b) {
          return order;
        }

        return 0;
      }

      if (a === b) {
        return 0;
      } // If value is not a string, convert to string


      if (typeof a !== 'string') {
        a = a.toString();
      }

      if (a.localeCompare(b) === -1) {
        return order * -1;
      }

      return order;
    },
    getEventName: function getEventName(eventPrefix) {
      var id = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
      id = id || \"\".concat(+new Date()).concat(~~(Math.random() * 1000000));
      return \"\".concat(eventPrefix, \"-\").concat(id);
    },
    hasDetailViewIcon: function hasDetailViewIcon(options) {
      return options.detailView && options.detailViewIcon && !options.cardView;
    },
    getDetailViewIndexOffset: function getDetailViewIndexOffset(options) {
      return this.hasDetailViewIcon(options) && options.detailViewAlign !== 'right' ? 1 : 0;
    },
    checkAutoMergeCells: function checkAutoMergeCells(data) {
      var _iterator9 = _createForOfIteratorHelper(data),
          _step9;

      try {
        for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
          var row = _step9.value;

          for (var _i4 = 0, _Object\$keys = Object.keys(row); _i4 < _Object\$keys.length; _i4++) {
            var key = _Object\$keys[_i4];

            if (key.startsWith('_') && (key.endsWith('_rowspan') || key.endsWith('_colspan'))) {
              return true;
            }
          }
        }
      } catch (err) {
        _iterator9.e(err);
      } finally {
        _iterator9.f();
      }

      return false;
    },
    deepCopy: function deepCopy(arg) {
      if (arg === undefined) {
        return arg;
      }

      return \$__default['default'].extend(true, Array.isArray(arg) ? [] : {}, arg);
    }
  };

  var BLOCK_ROWS = 50;
  var CLUSTER_BLOCKS = 4;

  var VirtualScroll = /*#__PURE__*/function () {
    function VirtualScroll(options) {
      var _this = this;

      _classCallCheck(this, VirtualScroll);

      this.rows = options.rows;
      this.scrollEl = options.scrollEl;
      this.contentEl = options.contentEl;
      this.callback = options.callback;
      this.itemHeight = options.itemHeight;
      this.cache = {};
      this.scrollTop = this.scrollEl.scrollTop;
      this.initDOM(this.rows, options.fixedScroll);
      this.scrollEl.scrollTop = this.scrollTop;
      this.lastCluster = 0;

      var onScroll = function onScroll() {
        if (_this.lastCluster !== (_this.lastCluster = _this.getNum())) {
          _this.initDOM(_this.rows);

          _this.callback();
        }
      };

      this.scrollEl.addEventListener('scroll', onScroll, false);

      this.destroy = function () {
        _this.contentEl.innerHtml = '';

        _this.scrollEl.removeEventListener('scroll', onScroll, false);
      };
    }

    _createClass(VirtualScroll, [{
      key: \"initDOM\",
      value: function initDOM(rows, fixedScroll) {
        if (typeof this.clusterHeight === 'undefined') {
          this.cache.scrollTop = this.scrollEl.scrollTop;
          this.cache.data = this.contentEl.innerHTML = rows[0] + rows[0] + rows[0];
          this.getRowsHeight(rows);
        }

        var data = this.initData(rows, this.getNum(fixedScroll));
        var thisRows = data.rows.join('');
        var dataChanged = this.checkChanges('data', thisRows);
        var topOffsetChanged = this.checkChanges('top', data.topOffset);
        var bottomOffsetChanged = this.checkChanges('bottom', data.bottomOffset);
        var html = [];

        if (dataChanged && topOffsetChanged) {
          if (data.topOffset) {
            html.push(this.getExtra('top', data.topOffset));
          }

          html.push(thisRows);

          if (data.bottomOffset) {
            html.push(this.getExtra('bottom', data.bottomOffset));
          }

          this.contentEl.innerHTML = html.join('');

          if (fixedScroll) {
            this.contentEl.scrollTop = this.cache.scrollTop;
          }
        } else if (bottomOffsetChanged) {
          this.contentEl.lastChild.style.height = \"\".concat(data.bottomOffset, \"px\");
        }
      }
    }, {
      key: \"getRowsHeight\",
      value: function getRowsHeight() {
        if (typeof this.itemHeight === 'undefined') {
          var nodes = this.contentEl.children;
          var node = nodes[Math.floor(nodes.length / 2)];
          this.itemHeight = node.offsetHeight;
        }

        this.blockHeight = this.itemHeight * BLOCK_ROWS;
        this.clusterRows = BLOCK_ROWS * CLUSTER_BLOCKS;
        this.clusterHeight = this.blockHeight * CLUSTER_BLOCKS;
      }
    }, {
      key: \"getNum\",
      value: function getNum(fixedScroll) {
        this.scrollTop = fixedScroll ? this.cache.scrollTop : this.scrollEl.scrollTop;
        return Math.floor(this.scrollTop / (this.clusterHeight - this.blockHeight)) || 0;
      }
    }, {
      key: \"initData\",
      value: function initData(rows, num) {
        if (rows.length < BLOCK_ROWS) {
          return {
            topOffset: 0,
            bottomOffset: 0,
            rowsAbove: 0,
            rows: rows
          };
        }

        var start = Math.max((this.clusterRows - BLOCK_ROWS) * num, 0);
        var end = start + this.clusterRows;
        var topOffset = Math.max(start * this.itemHeight, 0);
        var bottomOffset = Math.max((rows.length - end) * this.itemHeight, 0);
        var thisRows = [];
        var rowsAbove = start;

        if (topOffset < 1) {
          rowsAbove++;
        }

        for (var i = start; i < end; i++) {
          rows[i] && thisRows.push(rows[i]);
        }

        return {
          topOffset: topOffset,
          bottomOffset: bottomOffset,
          rowsAbove: rowsAbove,
          rows: thisRows
        };
      }
    }, {
      key: \"checkChanges\",
      value: function checkChanges(type, value) {
        var changed = value !== this.cache[type];
        this.cache[type] = value;
        return changed;
      }
    }, {
      key: \"getExtra\",
      value: function getExtra(className, height) {
        var tag = document.createElement('tr');
        tag.className = \"virtual-scroll-\".concat(className);

        if (height) {
          tag.style.height = \"\".concat(height, \"px\");
        }

        return tag.outerHTML;
      }
    }]);

    return VirtualScroll;
  }();

  var BootstrapTable = /*#__PURE__*/function () {
    function BootstrapTable(el, options) {
      _classCallCheck(this, BootstrapTable);

      this.options = options;
      this.\$el = \$__default['default'](el);
      this.\$el_ = this.\$el.clone();
      this.timeoutId_ = 0;
      this.timeoutFooter_ = 0;
    }

    _createClass(BootstrapTable, [{
      key: \"init\",
      value: function init() {
        this.initConstants();
        this.initLocale();
        this.initContainer();
        this.initTable();
        this.initHeader();
        this.initData();
        this.initHiddenRows();
        this.initToolbar();
        this.initPagination();
        this.initBody();
        this.initSearchText();
        this.initServer();
      }
    }, {
      key: \"initConstants\",
      value: function initConstants() {
        var opts = this.options;
        this.constants = Constants.CONSTANTS;
        this.constants.theme = \$__default['default'].fn.bootstrapTable.theme;
        this.constants.dataToggle = this.constants.html.dataToggle || 'data-toggle';
        var buttonsPrefix = opts.buttonsPrefix ? \"\".concat(opts.buttonsPrefix, \"-\") : '';
        this.constants.buttonsClass = [opts.buttonsPrefix, buttonsPrefix + opts.buttonsClass, Utils.sprintf(\"\".concat(buttonsPrefix, \"%s\"), opts.iconSize)].join(' ').trim();
        this.buttons = Utils.calculateObjectValue(this, opts.buttons, [], {});

        if (_typeof(this.buttons) !== 'object') {
          this.buttons = {};
        }

        if (typeof opts.icons === 'string') {
          opts.icons = Utils.calculateObjectValue(null, opts.icons);
        }
      }
    }, {
      key: \"initLocale\",
      value: function initLocale() {
        if (this.options.locale) {
          var locales = \$__default['default'].fn.bootstrapTable.locales;
          var parts = this.options.locale.split(/-|_/);
          parts[0] = parts[0].toLowerCase();

          if (parts[1]) {
            parts[1] = parts[1].toUpperCase();
          }

          if (locales[this.options.locale]) {
            \$__default['default'].extend(this.options, locales[this.options.locale]);
          } else if (locales[parts.join('-')]) {
            \$__default['default'].extend(this.options, locales[parts.join('-')]);
          } else if (locales[parts[0]]) {
            \$__default['default'].extend(this.options, locales[parts[0]]);
          }
        }
      }
    }, {
      key: \"initContainer\",
      value: function initContainer() {
        var topPagination = ['top', 'both'].includes(this.options.paginationVAlign) ? '<div class=\"fixed-table-pagination clearfix\"></div>' : '';
        var bottomPagination = ['bottom', 'both'].includes(this.options.paginationVAlign) ? '<div class=\"fixed-table-pagination\"></div>' : '';
        var loadingTemplate = Utils.calculateObjectValue(this.options, this.options.loadingTemplate, [this.options.formatLoadingMessage()]);
        this.\$container = \$__default['default'](\"\\n      <div class=\\\"bootstrap-table \".concat(this.constants.theme, \"\\\">\\n      <div class=\\\"fixed-table-toolbar\\\"></div>\\n      \").concat(topPagination, \"\\n      <div class=\\\"fixed-table-container\\\">\\n      <div class=\\\"fixed-table-header\\\"><table></table></div>\\n      <div class=\\\"fixed-table-body\\\">\\n      <div class=\\\"fixed-table-loading\\\">\\n      \").concat(loadingTemplate, \"\\n      </div>\\n      </div>\\n      <div class=\\\"fixed-table-footer\\\"></div>\\n      </div>\\n      \").concat(bottomPagination, \"\\n      </div>\\n    \"));
        this.\$container.insertAfter(this.\$el);
        this.\$tableContainer = this.\$container.find('.fixed-table-container');
        this.\$tableHeader = this.\$container.find('.fixed-table-header');
        this.\$tableBody = this.\$container.find('.fixed-table-body');
        this.\$tableLoading = this.\$container.find('.fixed-table-loading');
        this.\$tableFooter = this.\$el.find('tfoot'); // checking if custom table-toolbar exists or not

        if (this.options.buttonsToolbar) {
          this.\$toolbar = \$__default['default']('body').find(this.options.buttonsToolbar);
        } else {
          this.\$toolbar = this.\$container.find('.fixed-table-toolbar');
        }

        this.\$pagination = this.\$container.find('.fixed-table-pagination');
        this.\$tableBody.append(this.\$el);
        this.\$container.after('<div class=\"clearfix\"></div>');
        this.\$el.addClass(this.options.classes);
        this.\$tableLoading.addClass(this.options.classes);

        if (this.options.height) {
          this.\$tableContainer.addClass('fixed-height');

          if (this.options.showFooter) {
            this.\$tableContainer.addClass('has-footer');
          }

          if (this.options.classes.split(' ').includes('table-bordered')) {
            this.\$tableBody.append('<div class=\"fixed-table-border\"></div>');
            this.\$tableBorder = this.\$tableBody.find('.fixed-table-border');
            this.\$tableLoading.addClass('fixed-table-border');
          }

          this.\$tableFooter = this.\$container.find('.fixed-table-footer');
        }
      }
    }, {
      key: \"initTable\",
      value: function initTable() {
        var _this = this;

        var columns = [];
        this.\$header = this.\$el.find('>thead');

        if (!this.\$header.length) {
          this.\$header = \$__default['default'](\"<thead class=\\\"\".concat(this.options.theadClasses, \"\\\"></thead>\")).appendTo(this.\$el);
        } else if (this.options.theadClasses) {
          this.\$header.addClass(this.options.theadClasses);
        }

        this._headerTrClasses = [];
        this._headerTrStyles = [];
        this.\$header.find('tr').each(function (i, el) {
          var \$tr = \$__default['default'](el);
          var column = [];
          \$tr.find('th').each(function (i, el) {
            var \$th = \$__default['default'](el); // #2014: getFieldIndex and elsewhere assume this is string, causes issues if not

            if (typeof \$th.data('field') !== 'undefined') {
              \$th.data('field', \"\".concat(\$th.data('field')));
            }

            column.push(\$__default['default'].extend({}, {
              title: \$th.html(),
              class: \$th.attr('class'),
              titleTooltip: \$th.attr('title'),
              rowspan: \$th.attr('rowspan') ? +\$th.attr('rowspan') : undefined,
              colspan: \$th.attr('colspan') ? +\$th.attr('colspan') : undefined
            }, \$th.data()));
          });
          columns.push(column);

          if (\$tr.attr('class')) {
            _this._headerTrClasses.push(\$tr.attr('class'));
          }

          if (\$tr.attr('style')) {
            _this._headerTrStyles.push(\$tr.attr('style'));
          }
        });

        if (!Array.isArray(this.options.columns[0])) {
          this.options.columns = [this.options.columns];
        }

        this.options.columns = \$__default['default'].extend(true, [], columns, this.options.columns);
        this.columns = [];
        this.fieldsColumnsIndex = [];
        Utils.setFieldIndex(this.options.columns);
        this.options.columns.forEach(function (columns, i) {
          columns.forEach(function (_column, j) {
            var column = \$__default['default'].extend({}, BootstrapTable.COLUMN_DEFAULTS, _column);

            if (typeof column.fieldIndex !== 'undefined') {
              _this.columns[column.fieldIndex] = column;
              _this.fieldsColumnsIndex[column.field] = column.fieldIndex;
            }

            _this.options.columns[i][j] = column;
          });
        }); // if options.data is setting, do not process tbody and tfoot data

        if (!this.options.data.length) {
          var htmlData = Utils.trToData(this.columns, this.\$el.find('>tbody>tr'));

          if (htmlData.length) {
            this.options.data = htmlData;
            this.fromHtml = true;
          }
        }

        if (!(this.options.pagination && this.options.sidePagination !== 'server')) {
          this.footerData = Utils.trToData(this.columns, this.\$el.find('>tfoot>tr'));
        }

        if (this.footerData) {
          this.\$el.find('tfoot').html('<tr></tr>');
        }

        if (!this.options.showFooter || this.options.cardView) {
          this.\$tableFooter.hide();
        } else {
          this.\$tableFooter.show();
        }
      }
    }, {
      key: \"initHeader\",
      value: function initHeader() {
        var _this2 = this;

        var visibleColumns = {};
        var headerHtml = [];
        this.header = {
          fields: [],
          styles: [],
          classes: [],
          formatters: [],
          detailFormatters: [],
          events: [],
          sorters: [],
          sortNames: [],
          cellStyles: [],
          searchables: []
        };
        Utils.updateFieldGroup(this.options.columns);
        this.options.columns.forEach(function (columns, i) {
          var html = [];
          html.push(\"<tr\".concat(Utils.sprintf(' class=\"%s\"', _this2._headerTrClasses[i]), \" \").concat(Utils.sprintf(' style=\"%s\"', _this2._headerTrStyles[i]), \">\"));
          var detailViewTemplate = '';

          if (i === 0 && Utils.hasDetailViewIcon(_this2.options)) {
            var rowspan = _this2.options.columns.length > 1 ? \" rowspan=\\\"\".concat(_this2.options.columns.length, \"\\\"\") : '';
            detailViewTemplate = \"<th class=\\\"detail\\\"\".concat(rowspan, \">\\n          <div class=\\\"fht-cell\\\"></div>\\n          </th>\");
          }

          if (detailViewTemplate && _this2.options.detailViewAlign !== 'right') {
            html.push(detailViewTemplate);
          }

          columns.forEach(function (column, j) {
            var class_ = Utils.sprintf(' class=\"%s\"', column['class']);
            var unitWidth = column.widthUnit;
            var width = parseFloat(column.width);
            var halign = Utils.sprintf('text-align: %s; ', column.halign ? column.halign : column.align);
            var align = Utils.sprintf('text-align: %s; ', column.align);
            var style = Utils.sprintf('vertical-align: %s; ', column.valign);
            style += Utils.sprintf('width: %s; ', (column.checkbox || column.radio) && !width ? !column.showSelectTitle ? '36px' : undefined : width ? width + unitWidth : undefined);

            if (typeof column.fieldIndex === 'undefined' && !column.visible) {
              return;
            }

            var headerStyle = Utils.calculateObjectValue(null, _this2.options.headerStyle, [column]);
            var csses = [];
            var classes = '';

            if (headerStyle && headerStyle.css) {
              for (var _i = 0, _Object\$entries = Object.entries(headerStyle.css); _i < _Object\$entries.length; _i++) {
                var _Object\$entries\$_i = _slicedToArray(_Object\$entries[_i], 2),
                    key = _Object\$entries\$_i[0],
                    value = _Object\$entries\$_i[1];

                csses.push(\"\".concat(key, \": \").concat(value));
              }
            }

            if (headerStyle && headerStyle.classes) {
              classes = Utils.sprintf(' class=\"%s\"', column['class'] ? [column['class'], headerStyle.classes].join(' ') : headerStyle.classes);
            }

            if (typeof column.fieldIndex !== 'undefined') {
              _this2.header.fields[column.fieldIndex] = column.field;
              _this2.header.styles[column.fieldIndex] = align + style;
              _this2.header.classes[column.fieldIndex] = class_;
              _this2.header.formatters[column.fieldIndex] = column.formatter;
              _this2.header.detailFormatters[column.fieldIndex] = column.detailFormatter;
              _this2.header.events[column.fieldIndex] = column.events;
              _this2.header.sorters[column.fieldIndex] = column.sorter;
              _this2.header.sortNames[column.fieldIndex] = column.sortName;
              _this2.header.cellStyles[column.fieldIndex] = column.cellStyle;
              _this2.header.searchables[column.fieldIndex] = column.searchable;

              if (!column.visible) {
                return;
              }

              if (_this2.options.cardView && !column.cardVisible) {
                return;
              }

              visibleColumns[column.field] = column;
            }

            html.push(\"<th\".concat(Utils.sprintf(' title=\"%s\"', column.titleTooltip)), column.checkbox || column.radio ? Utils.sprintf(' class=\"bs-checkbox %s\"', column['class'] || '') : classes || class_, Utils.sprintf(' style=\"%s\"', halign + style + csses.join('; ')), Utils.sprintf(' rowspan=\"%s\"', column.rowspan), Utils.sprintf(' colspan=\"%s\"', column.colspan), Utils.sprintf(' data-field=\"%s\"', column.field), // If `column` is not the first element of `this.options.columns[0]`, then className 'data-not-first-th' should be added.
            j === 0 && i > 0 ? ' data-not-first-th' : '', '>');
            html.push(Utils.sprintf('<div class=\"th-inner %s\">', _this2.options.sortable && column.sortable ? 'sortable both' : ''));
            var text = _this2.options.escape ? Utils.escapeHTML(column.title) : column.title;
            var title = text;

            if (column.checkbox) {
              text = '';

              if (!_this2.options.singleSelect && _this2.options.checkboxHeader) {
                text = '<label><input name=\"btSelectAll\" type=\"checkbox\" /><span></span></label>';
              }

              _this2.header.stateField = column.field;
            }

            if (column.radio) {
              text = '';
              _this2.header.stateField = column.field;
            }

            if (!text && column.showSelectTitle) {
              text += title;
            }

            html.push(text);
            html.push('</div>');
            html.push('<div class=\"fht-cell\"></div>');
            html.push('</div>');
            html.push('</th>');
          });

          if (detailViewTemplate && _this2.options.detailViewAlign === 'right') {
            html.push(detailViewTemplate);
          }

          html.push('</tr>');

          if (html.length > 3) {
            headerHtml.push(html.join(''));
          }
        });
        this.\$header.html(headerHtml.join(''));
        this.\$header.find('th[data-field]').each(function (i, el) {
          \$__default['default'](el).data(visibleColumns[\$__default['default'](el).data('field')]);
        });
        this.\$container.off('click', '.th-inner').on('click', '.th-inner', function (e) {
          var \$this = \$__default['default'](e.currentTarget);

          if (_this2.options.detailView && !\$this.parent().hasClass('bs-checkbox')) {
            if (\$this.closest('.bootstrap-table')[0] !== _this2.\$container[0]) {
              return false;
            }
          }

          if (_this2.options.sortable && \$this.parent().data().sortable) {
            _this2.onSort(e);
          }
        });
        this.\$header.children().children().off('keypress').on('keypress', function (e) {
          if (_this2.options.sortable && \$__default['default'](e.currentTarget).data().sortable) {
            var code = e.keyCode || e.which;

            if (code === 13) {
              // Enter keycode
              _this2.onSort(e);
            }
          }
        });
        var resizeEvent = Utils.getEventName('resize.bootstrap-table', this.\$el.attr('id'));
        \$__default['default'](window).off(resizeEvent);

        if (!this.options.showHeader || this.options.cardView) {
          this.\$header.hide();
          this.\$tableHeader.hide();
          this.\$tableLoading.css('top', 0);
        } else {
          this.\$header.show();
          this.\$tableHeader.show();
          this.\$tableLoading.css('top', this.\$header.outerHeight() + 1); // Assign the correct sortable arrow

          this.getCaret();
          \$__default['default'](window).on(resizeEvent, function () {
            return _this2.resetView();
          });
        }

        this.\$selectAll = this.\$header.find('[name=\"btSelectAll\"]');
        this.\$selectAll.off('click').on('click', function (e) {
          e.stopPropagation();
          var checked = \$__default['default'](e.currentTarget).prop('checked');

          _this2[checked ? 'checkAll' : 'uncheckAll']();

          _this2.updateSelected();
        });
      }
    }, {
      key: \"initData\",
      value: function initData(data, type) {
        if (type === 'append') {
          this.options.data = this.options.data.concat(data);
        } else if (type === 'prepend') {
          this.options.data = [].concat(data).concat(this.options.data);
        } else {
          data = data || Utils.deepCopy(this.options.data);
          this.options.data = Array.isArray(data) ? data : data[this.options.dataField];
        }

        this.data = _toConsumableArray(this.options.data);

        if (this.options.sortReset) {
          this.unsortedData = _toConsumableArray(this.data);
        }

        if (this.options.sidePagination === 'server') {
          return;
        }

        this.initSort();
      }
    }, {
      key: \"initSort\",
      value: function initSort() {
        var _this3 = this;

        var name = this.options.sortName;
        var order = this.options.sortOrder === 'desc' ? -1 : 1;
        var index = this.header.fields.indexOf(this.options.sortName);
        var timeoutId = 0;

        if (index !== -1) {
          if (this.options.sortStable) {
            this.data.forEach(function (row, i) {
              if (!row.hasOwnProperty('_position')) {
                row._position = i;
              }
            });
          }

          if (this.options.customSort) {
            Utils.calculateObjectValue(this.options, this.options.customSort, [this.options.sortName, this.options.sortOrder, this.data]);
          } else {
            this.data.sort(function (a, b) {
              if (_this3.header.sortNames[index]) {
                name = _this3.header.sortNames[index];
              }

              var aa = Utils.getItemField(a, name, _this3.options.escape);
              var bb = Utils.getItemField(b, name, _this3.options.escape);
              var value = Utils.calculateObjectValue(_this3.header, _this3.header.sorters[index], [aa, bb, a, b]);

              if (value !== undefined) {
                if (_this3.options.sortStable && value === 0) {
                  return order * (a._position - b._position);
                }

                return order * value;
              }

              return Utils.sort(aa, bb, order, _this3.options.sortStable, a._position, b._position);
            });
          }

          if (this.options.sortClass !== undefined) {
            clearTimeout(timeoutId);
            timeoutId = setTimeout(function () {
              _this3.\$el.removeClass(_this3.options.sortClass);

              var index = _this3.\$header.find(\"[data-field=\\\"\".concat(_this3.options.sortName, \"\\\"]\")).index();

              _this3.\$el.find(\"tr td:nth-child(\".concat(index + 1, \")\")).addClass(_this3.options.sortClass);
            }, 250);
          }
        } else if (this.options.sortReset) {
          this.data = _toConsumableArray(this.unsortedData);
        }
      }
    }, {
      key: \"onSort\",
      value: function onSort(_ref) {
        var type = _ref.type,
            currentTarget = _ref.currentTarget;
        var \$this = type === 'keypress' ? \$__default['default'](currentTarget) : \$__default['default'](currentTarget).parent();
        var \$this_ = this.\$header.find('th').eq(\$this.index());
        this.\$header.add(this.\$header_).find('span.order').remove();

        if (this.options.sortName === \$this.data('field')) {
          var currentSortOrder = this.options.sortOrder;

          if (currentSortOrder === undefined) {
            this.options.sortOrder = 'asc';
          } else if (currentSortOrder === 'asc') {
            this.options.sortOrder = 'desc';
          } else if (this.options.sortOrder === 'desc') {
            this.options.sortOrder = this.options.sortReset ? undefined : 'asc';
          }

          if (this.options.sortOrder === undefined) {
            this.options.sortName = undefined;
          }
        } else {
          this.options.sortName = \$this.data('field');

          if (this.options.rememberOrder) {
            this.options.sortOrder = \$this.data('order') === 'asc' ? 'desc' : 'asc';
          } else {
            this.options.sortOrder = this.columns[this.fieldsColumnsIndex[\$this.data('field')]].sortOrder || this.columns[this.fieldsColumnsIndex[\$this.data('field')]].order;
          }
        }

        this.trigger('sort', this.options.sortName, this.options.sortOrder);
        \$this.add(\$this_).data('order', this.options.sortOrder); // Assign the correct sortable arrow

        this.getCaret();

        if (this.options.sidePagination === 'server' && this.options.serverSort) {
          this.options.pageNumber = 1;
          this.initServer(this.options.silentSort);
          return;
        }

        this.initSort();
        this.initBody();
      }
    }, {
      key: \"initToolbar\",
      value: function initToolbar() {
        var _this4 = this;

        var opts = this.options;
        var html = [];
        var timeoutId = 0;
        var \$keepOpen;
        var switchableCount = 0;

        if (this.\$toolbar.find('.bs-bars').children().length) {
          \$__default['default']('body').append(\$__default['default'](opts.toolbar));
        }

        this.\$toolbar.html('');

        if (typeof opts.toolbar === 'string' || _typeof(opts.toolbar) === 'object') {
          \$__default['default'](Utils.sprintf('<div class=\"bs-bars %s-%s\"></div>', this.constants.classes.pull, opts.toolbarAlign)).appendTo(this.\$toolbar).append(\$__default['default'](opts.toolbar));
        } // showColumns, showToggle, showRefresh


        html = [\"<div class=\\\"\".concat(['columns', \"columns-\".concat(opts.buttonsAlign), this.constants.classes.buttonsGroup, \"\".concat(this.constants.classes.pull, \"-\").concat(opts.buttonsAlign)].join(' '), \"\\\">\")];

        if (typeof opts.buttonsOrder === 'string') {
          opts.buttonsOrder = opts.buttonsOrder.replace(/\\[|\\]| |'/g, '').split(',');
        }

        this.buttons = Object.assign(this.buttons, {
          paginationSwitch: {
            text: opts.pagination ? opts.formatPaginationSwitchUp() : opts.formatPaginationSwitchDown(),
            icon: opts.pagination ? opts.icons.paginationSwitchDown : opts.icons.paginationSwitchUp,
            render: false,
            event: this.togglePagination,
            attributes: {
              'aria-label': opts.formatPaginationSwitch(),
              title: opts.formatPaginationSwitch()
            }
          },
          refresh: {
            text: opts.formatRefresh(),
            icon: opts.icons.refresh,
            render: false,
            event: this.refresh,
            attributes: {
              'aria-label': opts.formatRefresh(),
              title: opts.formatRefresh()
            }
          },
          toggle: {
            text: opts.formatToggle(),
            icon: opts.icons.toggleOff,
            render: false,
            event: this.toggleView,
            attributes: {
              'aria-label': opts.formatToggleOn(),
              title: opts.formatToggleOn()
            }
          },
          fullscreen: {
            text: opts.formatFullscreen(),
            icon: opts.icons.fullscreen,
            render: false,
            event: this.toggleFullscreen,
            attributes: {
              'aria-label': opts.formatFullscreen(),
              title: opts.formatFullscreen()
            }
          },
          columns: {
            render: false,
            html: function html() {
              var html = [];
              html.push(\"<div class=\\\"keep-open \".concat(_this4.constants.classes.buttonsDropdown, \"\\\" title=\\\"\").concat(opts.formatColumns(), \"\\\">\\n            <button class=\\\"\").concat(_this4.constants.buttonsClass, \" dropdown-toggle\\\" type=\\\"button\\\" \").concat(_this4.constants.dataToggle, \"=\\\"dropdown\\\"\\n            aria-label=\\\"Columns\\\" title=\\\"\").concat(opts.formatColumns(), \"\\\">\\n            \").concat(opts.showButtonIcons ? Utils.sprintf(_this4.constants.html.icon, opts.iconsPrefix, opts.icons.columns) : '', \"\\n            \").concat(opts.showButtonText ? opts.formatColumns() : '', \"\\n            \").concat(_this4.constants.html.dropdownCaret, \"\\n            </button>\\n            \").concat(_this4.constants.html.toolbarDropdown[0]));

              if (opts.showColumnsSearch) {
                html.push(Utils.sprintf(_this4.constants.html.toolbarDropdownItem, Utils.sprintf('<input type=\"text\" class=\"%s\" name=\"columnsSearch\" placeholder=\"%s\" autocomplete=\"off\">', _this4.constants.classes.input, opts.formatSearch())));
                html.push(_this4.constants.html.toolbarDropdownSeparator);
              }

              if (opts.showColumnsToggleAll) {
                var allFieldsVisible = _this4.getVisibleColumns().length === _this4.columns.filter(function (column) {
                  return !_this4.isSelectionColumn(column);
                }).length;

                html.push(Utils.sprintf(_this4.constants.html.toolbarDropdownItem, Utils.sprintf('<input type=\"checkbox\" class=\"toggle-all\" %s> <span>%s</span>', allFieldsVisible ? 'checked=\"checked\"' : '', opts.formatColumnsToggleAll())));
                html.push(_this4.constants.html.toolbarDropdownSeparator);
              }

              var visibleColumns = 0;

              _this4.columns.forEach(function (column) {
                if (column.visible) {
                  visibleColumns++;
                }
              });

              _this4.columns.forEach(function (column, i) {
                if (_this4.isSelectionColumn(column)) {
                  return;
                }

                if (opts.cardView && !column.cardVisible) {
                  return;
                }

                var checked = column.visible ? ' checked=\"checked\"' : '';
                var disabled = visibleColumns <= opts.minimumCountColumns && checked ? ' disabled=\"disabled\"' : '';

                if (column.switchable) {
                  html.push(Utils.sprintf(_this4.constants.html.toolbarDropdownItem, Utils.sprintf('<input type=\"checkbox\" data-field=\"%s\" value=\"%s\"%s%s> <span>%s</span>', column.field, i, checked, disabled, column.title)));
                  switchableCount++;
                }
              });

              html.push(_this4.constants.html.toolbarDropdown[1], '</div>');
              return html.join('');
            }
          }
        });
        var buttonsHtml = {};

        for (var _i2 = 0, _Object\$entries2 = Object.entries(this.buttons); _i2 < _Object\$entries2.length; _i2++) {
          var _Object\$entries2\$_i = _slicedToArray(_Object\$entries2[_i2], 2),
              buttonName = _Object\$entries2\$_i[0],
              buttonConfig = _Object\$entries2\$_i[1];

          var buttonHtml = void 0;

          if (buttonConfig.hasOwnProperty('html')) {
            if (typeof buttonConfig.html === 'function') {
              buttonHtml = buttonConfig.html();
            } else if (typeof buttonConfig.html === 'string') {
              buttonHtml = buttonConfig.html;
            }
          } else {
            buttonHtml = \"<button class=\\\"\".concat(this.constants.buttonsClass, \"\\\" type=\\\"button\\\" name=\\\"\").concat(buttonName, \"\\\"\");

            if (buttonConfig.hasOwnProperty('attributes')) {
              for (var _i3 = 0, _Object\$entries3 = Object.entries(buttonConfig.attributes); _i3 < _Object\$entries3.length; _i3++) {
                var _Object\$entries3\$_i = _slicedToArray(_Object\$entries3[_i3], 2),
                    attributeName = _Object\$entries3\$_i[0],
                    value = _Object\$entries3\$_i[1];

                buttonHtml += \" \".concat(attributeName, \"=\\\"\").concat(value, \"\\\"\");
              }
            }

            buttonHtml += '>';

            if (opts.showButtonIcons && buttonConfig.hasOwnProperty('icon')) {
              buttonHtml += \"\".concat(Utils.sprintf(this.constants.html.icon, opts.iconsPrefix, buttonConfig.icon), \" \");
            }

            if (opts.showButtonText && buttonConfig.hasOwnProperty('text')) {
              buttonHtml += buttonConfig.text;
            }

            buttonHtml += '</button>';
          }

          buttonsHtml[buttonName] = buttonHtml;
          var optionName = \"show\".concat(buttonName.charAt(0).toUpperCase()).concat(buttonName.substring(1));
          var showOption = opts[optionName];

          if ((!buttonConfig.hasOwnProperty('render') || buttonConfig.hasOwnProperty('render') && buttonConfig.render) && (showOption === undefined || showOption === true)) {
            opts[optionName] = true;
          }

          if (!opts.buttonsOrder.includes(buttonName)) {
            opts.buttonsOrder.push(buttonName);
          }
        } // Adding the button html to the final toolbar html when the showOption is true


        var _iterator = _createForOfIteratorHelper(opts.buttonsOrder),
            _step;

        try {
          for (_iterator.s(); !(_step = _iterator.n()).done;) {
            var button = _step.value;
            var _showOption = opts[\"show\".concat(button.charAt(0).toUpperCase()).concat(button.substring(1))];

            if (_showOption) {
              html.push(buttonsHtml[button]);
            }
          }
        } catch (err) {
          _iterator.e(err);
        } finally {
          _iterator.f();
        }

        html.push('</div>'); // Fix #188: this.showToolbar is for extensions

        if (this.showToolbar || html.length > 2) {
          this.\$toolbar.append(html.join(''));
        }

        for (var _i4 = 0, _Object\$entries4 = Object.entries(this.buttons); _i4 < _Object\$entries4.length; _i4++) {
          var _Object\$entries4\$_i = _slicedToArray(_Object\$entries4[_i4], 2),
              _buttonName = _Object\$entries4\$_i[0],
              _buttonConfig = _Object\$entries4\$_i[1];

          if (_buttonConfig.hasOwnProperty('event')) {
            if (typeof _buttonConfig.event === 'function' || typeof _buttonConfig.event === 'string') {
              var _ret = function () {
                var event = typeof _buttonConfig.event === 'string' ? window[_buttonConfig.event] : _buttonConfig.event;

                _this4.\$toolbar.find(\"button[name=\\\"\".concat(_buttonName, \"\\\"]\")).off('click').on('click', function () {
                  return event.call(_this4);
                });

                return \"continue\";
              }();

              if (_ret === \"continue\") continue;
            }

            var _loop = function _loop() {
              var _Object\$entries5\$_i = _slicedToArray(_Object\$entries5[_i5], 2),
                  eventType = _Object\$entries5\$_i[0],
                  eventFunction = _Object\$entries5\$_i[1];

              var event = typeof eventFunction === 'string' ? window[eventFunction] : eventFunction;

              _this4.\$toolbar.find(\"button[name=\\\"\".concat(_buttonName, \"\\\"]\")).off(eventType).on(eventType, function () {
                return event.call(_this4);
              });
            };

            for (var _i5 = 0, _Object\$entries5 = Object.entries(_buttonConfig.event); _i5 < _Object\$entries5.length; _i5++) {
              _loop();
            }
          }
        }

        if (opts.showColumns) {
          \$keepOpen = this.\$toolbar.find('.keep-open');
          var \$checkboxes = \$keepOpen.find('input[type=\"checkbox\"]:not(\".toggle-all\")');
          var \$toggleAll = \$keepOpen.find('input[type=\"checkbox\"].toggle-all');

          if (switchableCount <= opts.minimumCountColumns) {
            \$keepOpen.find('input').prop('disabled', true);
          }

          \$keepOpen.find('li, label').off('click').on('click', function (e) {
            e.stopImmediatePropagation();
          });
          \$checkboxes.off('click').on('click', function (_ref2) {
            var currentTarget = _ref2.currentTarget;
            var \$this = \$__default['default'](currentTarget);

            _this4._toggleColumn(\$this.val(), \$this.prop('checked'), false);

            _this4.trigger('column-switch', \$this.data('field'), \$this.prop('checked'));

            \$toggleAll.prop('checked', \$checkboxes.filter(':checked').length === _this4.columns.filter(function (column) {
              return !_this4.isSelectionColumn(column);
            }).length);
          });
          \$toggleAll.off('click').on('click', function (_ref3) {
            var currentTarget = _ref3.currentTarget;

            _this4._toggleAllColumns(\$__default['default'](currentTarget).prop('checked'));
          });

          if (opts.showColumnsSearch) {
            var \$columnsSearch = \$keepOpen.find('[name=\"columnsSearch\"]');
            var \$listItems = \$keepOpen.find('.dropdown-item-marker');
            \$columnsSearch.on('keyup paste change', function (_ref4) {
              var currentTarget = _ref4.currentTarget;
              var \$this = \$__default['default'](currentTarget);
              var searchValue = \$this.val().toLowerCase();
              \$listItems.show();
              \$checkboxes.each(function (i, el) {
                var \$checkbox = \$__default['default'](el);
                var \$listItem = \$checkbox.parents('.dropdown-item-marker');
                var text = \$listItem.text().toLowerCase();

                if (!text.includes(searchValue)) {
                  \$listItem.hide();
                }
              });
            });
          }
        }

        var handleInputEvent = function handleInputEvent(\$searchInput) {
          var eventTriggers = 'keyup drop blur mouseup';
          \$searchInput.off(eventTriggers).on(eventTriggers, function (event) {
            if (opts.searchOnEnterKey && event.keyCode !== 13) {
              return;
            }

            if ([37, 38, 39, 40].includes(event.keyCode)) {
              return;
            }

            clearTimeout(timeoutId); // doesn't matter if it's 0

            timeoutId = setTimeout(function () {
              _this4.onSearch({
                currentTarget: event.currentTarget
              });
            }, opts.searchTimeOut);
          });
        }; // Fix #4516: this.showSearchClearButton is for extensions


        if ((opts.search || this.showSearchClearButton) && typeof opts.searchSelector !== 'string') {
          html = [];
          var showSearchButton = Utils.sprintf(this.constants.html.searchButton, this.constants.buttonsClass, opts.formatSearch(), opts.showButtonIcons ? Utils.sprintf(this.constants.html.icon, opts.iconsPrefix, opts.icons.search) : '', opts.showButtonText ? opts.formatSearch() : '');
          var showSearchClearButton = Utils.sprintf(this.constants.html.searchClearButton, this.constants.buttonsClass, opts.formatClearSearch(), opts.showButtonIcons ? Utils.sprintf(this.constants.html.icon, opts.iconsPrefix, opts.icons.clearSearch) : '', opts.showButtonText ? opts.formatClearSearch() : '');
          var searchInputHtml = \"<input class=\\\"\".concat(this.constants.classes.input, \"\\n        \").concat(Utils.sprintf(' %s%s', this.constants.classes.inputPrefix, opts.iconSize), \"\\n        search-input\\\" type=\\\"search\\\" placeholder=\\\"\").concat(opts.formatSearch(), \"\\\" autocomplete=\\\"off\\\">\");
          var searchInputFinalHtml = searchInputHtml;

          if (opts.showSearchButton || opts.showSearchClearButton) {
            var _buttonsHtml = (opts.showSearchButton ? showSearchButton : '') + (opts.showSearchClearButton ? showSearchClearButton : '');

            searchInputFinalHtml = opts.search ? Utils.sprintf(this.constants.html.inputGroup, searchInputHtml, _buttonsHtml) : _buttonsHtml;
          }

          html.push(Utils.sprintf(\"\\n        <div class=\\\"\".concat(this.constants.classes.pull, \"-\").concat(opts.searchAlign, \" search \").concat(this.constants.classes.inputGroup, \"\\\">\\n          %s\\n        </div>\\n      \"), searchInputFinalHtml));
          this.\$toolbar.append(html.join(''));
          var \$searchInput = Utils.getSearchInput(this);

          if (opts.showSearchButton) {
            this.\$toolbar.find('.search button[name=search]').off('click').on('click', function () {
              clearTimeout(timeoutId); // doesn't matter if it's 0

              timeoutId = setTimeout(function () {
                _this4.onSearch({
                  currentTarget: \$searchInput
                });
              }, opts.searchTimeOut);
            });

            if (opts.searchOnEnterKey) {
              handleInputEvent(\$searchInput);
            }
          } else {
            handleInputEvent(\$searchInput);
          }

          if (opts.showSearchClearButton) {
            this.\$toolbar.find('.search button[name=clearSearch]').click(function () {
              _this4.resetSearch();
            });
          }
        } else if (typeof opts.searchSelector === 'string') {
          var _\$searchInput = Utils.getSearchInput(this);

          handleInputEvent(_\$searchInput);
        }
      }
    }, {
      key: \"onSearch\",
      value: function onSearch() {
        var _ref5 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
            currentTarget = _ref5.currentTarget,
            firedByInitSearchText = _ref5.firedByInitSearchText;

        var overwriteSearchText = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;

        if (currentTarget !== undefined && \$__default['default'](currentTarget).length && overwriteSearchText) {
          var text = \$__default['default'](currentTarget).val().trim();

          if (this.options.trimOnSearch && \$__default['default'](currentTarget).val() !== text) {
            \$__default['default'](currentTarget).val(text);
          }

          if (this.searchText === text) {
            return;
          }

          if (currentTarget === Utils.getSearchInput(this)[0] || \$__default['default'](currentTarget).hasClass('search-input')) {
            this.searchText = text;
            this.options.searchText = text;
          }
        }

        if (!firedByInitSearchText) {
          this.options.pageNumber = 1;
        }

        this.initSearch();

        if (firedByInitSearchText) {
          if (this.options.sidePagination === 'client') {
            this.updatePagination();
          }
        } else {
          this.updatePagination();
        }

        this.trigger('search', this.searchText);
      }
    }, {
      key: \"initSearch\",
      value: function initSearch() {
        var _this5 = this;

        this.filterOptions = this.filterOptions || this.options.filterOptions;

        if (this.options.sidePagination !== 'server') {
          if (this.options.customSearch) {
            this.data = Utils.calculateObjectValue(this.options, this.options.customSearch, [this.options.data, this.searchText, this.filterColumns]);

            if (this.options.sortReset) {
              this.unsortedData = _toConsumableArray(this.data);
            }

            return;
          }

          var s = this.searchText && (this.fromHtml ? Utils.escapeHTML(this.searchText) : this.searchText).toLowerCase();
          var f = Utils.isEmptyObject(this.filterColumns) ? null : this.filterColumns;

          if (this.options.searchAccentNeutralise) {
            s = Utils.normalizeAccent(s);
          } // Check filter


          if (typeof this.filterOptions.filterAlgorithm === 'function') {
            this.data = this.options.data.filter(function (item) {
              return _this5.filterOptions.filterAlgorithm.apply(null, [item, f]);
            });
          } else if (typeof this.filterOptions.filterAlgorithm === 'string') {
            this.data = f ? this.options.data.filter(function (item) {
              var filterAlgorithm = _this5.filterOptions.filterAlgorithm;

              if (filterAlgorithm === 'and') {
                for (var key in f) {
                  if (Array.isArray(f[key]) && !f[key].includes(item[key]) || !Array.isArray(f[key]) && item[key] !== f[key]) {
                    return false;
                  }
                }
              } else if (filterAlgorithm === 'or') {
                var match = false;

                for (var _key in f) {
                  if (Array.isArray(f[_key]) && f[_key].includes(item[_key]) || !Array.isArray(f[_key]) && item[_key] === f[_key]) {
                    match = true;
                  }
                }

                return match;
              }

              return true;
            }) : _toConsumableArray(this.options.data);
          }

          var visibleFields = this.getVisibleFields();
          this.data = s ? this.data.filter(function (item, i) {
            for (var j = 0; j < _this5.header.fields.length; j++) {
              if (!_this5.header.searchables[j] || _this5.options.visibleSearch && visibleFields.indexOf(_this5.header.fields[j]) === -1) {
                continue;
              }

              var key = Utils.isNumeric(_this5.header.fields[j]) ? parseInt(_this5.header.fields[j], 10) : _this5.header.fields[j];
              var column = _this5.columns[_this5.fieldsColumnsIndex[key]];
              var value = void 0;

              if (typeof key === 'string') {
                value = item;
                var props = key.split('.');

                for (var _i6 = 0; _i6 < props.length; _i6++) {
                  if (value[props[_i6]] !== null) {
                    value = value[props[_i6]];
                  }
                }
              } else {
                value = item[key];
              }

              if (_this5.options.searchAccentNeutralise) {
                value = Utils.normalizeAccent(value);
              } // Fix #142: respect searchFormatter boolean


              if (column && column.searchFormatter) {
                value = Utils.calculateObjectValue(column, _this5.header.formatters[j], [value, item, i, column.field], value);
              }

              if (typeof value === 'string' || typeof value === 'number') {
                if (_this5.options.strictSearch) {
                  if (\"\".concat(value).toLowerCase() === s) {
                    return true;
                  }
                } else {
                  var largerSmallerEqualsRegex = /(?:(<=|=>|=<|>=|>|<)(?:\\s+)?(-?\\d+)?|(-?\\d+)?(\\s+)?(<=|=>|=<|>=|>|<))/gm;
                  var matches = largerSmallerEqualsRegex.exec(_this5.searchText);
                  var comparisonCheck = false;

                  if (matches) {
                    var operator = matches[1] || \"\".concat(matches[5], \"l\");
                    var comparisonValue = matches[2] || matches[3];
                    var int = parseInt(value, 10);
                    var comparisonInt = parseInt(comparisonValue, 10);

                    switch (operator) {
                      case '>':
                      case '<l':
                        comparisonCheck = int > comparisonInt;
                        break;

                      case '<':
                      case '>l':
                        comparisonCheck = int < comparisonInt;
                        break;

                      case '<=':
                      case '=<':
                      case '>=l':
                      case '=>l':
                        comparisonCheck = int <= comparisonInt;
                        break;

                      case '>=':
                      case '=>':
                      case '<=l':
                      case '=<l':
                        comparisonCheck = int >= comparisonInt;
                        break;
                    }
                  }

                  if (comparisonCheck || \"\".concat(value).toLowerCase().includes(s)) {
                    return true;
                  }
                }
              }
            }

            return false;
          }) : this.data;

          if (this.options.sortReset) {
            this.unsortedData = _toConsumableArray(this.data);
          }

          this.initSort();
        }
      }
    }, {
      key: \"initPagination\",
      value: function initPagination() {
        var _this6 = this;

        var opts = this.options;

        if (!opts.pagination) {
          this.\$pagination.hide();
          return;
        }

        this.\$pagination.show();
        var html = [];
        var allSelected = false;
        var i;
        var from;
        var to;
        var \$pageList;
        var \$pre;
        var \$next;
        var \$number;
        var data = this.getData({
          includeHiddenRows: false
        });
        var pageList = opts.pageList;

        if (typeof pageList === 'string') {
          pageList = pageList.replace(/\\[|\\]| /g, '').toLowerCase().split(',');
        }

        pageList = pageList.map(function (value) {
          if (typeof value === 'string') {
            return value.toLowerCase() === opts.formatAllRows().toLowerCase() || ['all', 'unlimited'].includes(value.toLowerCase()) ? opts.formatAllRows() : +value;
          }

          return value;
        });
        this.paginationParts = opts.paginationParts;

        if (typeof this.paginationParts === 'string') {
          this.paginationParts = this.paginationParts.replace(/\\[|\\]| |'/g, '').split(',');
        }

        if (opts.sidePagination !== 'server') {
          opts.totalRows = data.length;
        }

        this.totalPages = 0;

        if (opts.totalRows) {
          if (opts.pageSize === opts.formatAllRows()) {
            opts.pageSize = opts.totalRows;
            allSelected = true;
          }

          this.totalPages = ~~((opts.totalRows - 1) / opts.pageSize) + 1;
          opts.totalPages = this.totalPages;
        }

        if (this.totalPages > 0 && opts.pageNumber > this.totalPages) {
          opts.pageNumber = this.totalPages;
        }

        this.pageFrom = (opts.pageNumber - 1) * opts.pageSize + 1;
        this.pageTo = opts.pageNumber * opts.pageSize;

        if (this.pageTo > opts.totalRows) {
          this.pageTo = opts.totalRows;
        }

        if (this.options.pagination && this.options.sidePagination !== 'server') {
          this.options.totalNotFiltered = this.options.data.length;
        }

        if (!this.options.showExtendedPagination) {
          this.options.totalNotFiltered = undefined;
        }

        if (this.paginationParts.includes('pageInfo') || this.paginationParts.includes('pageInfoShort') || this.paginationParts.includes('pageSize')) {
          html.push(\"<div class=\\\"\".concat(this.constants.classes.pull, \"-\").concat(opts.paginationDetailHAlign, \" pagination-detail\\\">\"));
        }

        if (this.paginationParts.includes('pageInfo') || this.paginationParts.includes('pageInfoShort')) {
          var paginationInfo = this.paginationParts.includes('pageInfoShort') ? opts.formatDetailPagination(opts.totalRows) : opts.formatShowingRows(this.pageFrom, this.pageTo, opts.totalRows, opts.totalNotFiltered);
          html.push(\"<span class=\\\"pagination-info\\\">\\n      \".concat(paginationInfo, \"\\n      </span>\"));
        }

        if (this.paginationParts.includes('pageSize')) {
          html.push('<div class=\"page-list\">');
          var pageNumber = [\"<div class=\\\"\".concat(this.constants.classes.paginationDropdown, \"\\\">\\n        <button class=\\\"\").concat(this.constants.buttonsClass, \" dropdown-toggle\\\" type=\\\"button\\\" \").concat(this.constants.dataToggle, \"=\\\"dropdown\\\">\\n        <span class=\\\"page-size\\\">\\n        \").concat(allSelected ? opts.formatAllRows() : opts.pageSize, \"\\n        </span>\\n        \").concat(this.constants.html.dropdownCaret, \"\\n        </button>\\n        \").concat(this.constants.html.pageDropdown[0])];
          pageList.forEach(function (page, i) {
            if (!opts.smartDisplay || i === 0 || pageList[i - 1] < opts.totalRows || page === opts.formatAllRows()) {
              var active;

              if (allSelected) {
                active = page === opts.formatAllRows() ? _this6.constants.classes.dropdownActive : '';
              } else {
                active = page === opts.pageSize ? _this6.constants.classes.dropdownActive : '';
              }

              pageNumber.push(Utils.sprintf(_this6.constants.html.pageDropdownItem, active, page));
            }
          });
          pageNumber.push(\"\".concat(this.constants.html.pageDropdown[1], \"</div>\"));
          html.push(opts.formatRecordsPerPage(pageNumber.join('')));
        }

        if (this.paginationParts.includes('pageInfo') || this.paginationParts.includes('pageInfoShort') || this.paginationParts.includes('pageSize')) {
          html.push('</div></div>');
        }

        if (this.paginationParts.includes('pageList')) {
          html.push(\"<div class=\\\"\".concat(this.constants.classes.pull, \"-\").concat(opts.paginationHAlign, \" pagination\\\">\"), Utils.sprintf(this.constants.html.pagination[0], Utils.sprintf(' pagination-%s', opts.iconSize)), Utils.sprintf(this.constants.html.paginationItem, ' page-pre', opts.formatSRPaginationPreText(), opts.paginationPreText));

          if (this.totalPages < opts.paginationSuccessivelySize) {
            from = 1;
            to = this.totalPages;
          } else {
            from = opts.pageNumber - opts.paginationPagesBySide;
            to = from + opts.paginationPagesBySide * 2;
          }

          if (opts.pageNumber < opts.paginationSuccessivelySize - 1) {
            to = opts.paginationSuccessivelySize;
          }

          if (opts.paginationSuccessivelySize > this.totalPages - from) {
            from = from - (opts.paginationSuccessivelySize - (this.totalPages - from)) + 1;
          }

          if (from < 1) {
            from = 1;
          }

          if (to > this.totalPages) {
            to = this.totalPages;
          }

          var middleSize = Math.round(opts.paginationPagesBySide / 2);

          var pageItem = function pageItem(i) {
            var classes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
            return Utils.sprintf(_this6.constants.html.paginationItem, classes + (i === opts.pageNumber ? \" \".concat(_this6.constants.classes.paginationActive) : ''), opts.formatSRPaginationPageText(i), i);
          };

          if (from > 1) {
            var max = opts.paginationPagesBySide;
            if (max >= from) max = from - 1;

            for (i = 1; i <= max; i++) {
              html.push(pageItem(i));
            }

            if (from - 1 === max + 1) {
              i = from - 1;
              html.push(pageItem(i));
            } else if (from - 1 > max) {
              if (from - opts.paginationPagesBySide * 2 > opts.paginationPagesBySide && opts.paginationUseIntermediate) {
                i = Math.round((from - middleSize) / 2 + middleSize);
                html.push(pageItem(i, ' page-intermediate'));
              } else {
                html.push(Utils.sprintf(this.constants.html.paginationItem, ' page-first-separator disabled', '', '...'));
              }
            }
          }

          for (i = from; i <= to; i++) {
            html.push(pageItem(i));
          }

          if (this.totalPages > to) {
            var min = this.totalPages - (opts.paginationPagesBySide - 1);
            if (to >= min) min = to + 1;

            if (to + 1 === min - 1) {
              i = to + 1;
              html.push(pageItem(i));
            } else if (min > to + 1) {
              if (this.totalPages - to > opts.paginationPagesBySide * 2 && opts.paginationUseIntermediate) {
                i = Math.round((this.totalPages - middleSize - to) / 2 + to);
                html.push(pageItem(i, ' page-intermediate'));
              } else {
                html.push(Utils.sprintf(this.constants.html.paginationItem, ' page-last-separator disabled', '', '...'));
              }
            }

            for (i = min; i <= this.totalPages; i++) {
              html.push(pageItem(i));
            }
          }

          html.push(Utils.sprintf(this.constants.html.paginationItem, ' page-next', opts.formatSRPaginationNextText(), opts.paginationNextText));
          html.push(this.constants.html.pagination[1], '</div>');
        }

        this.\$pagination.html(html.join(''));
        var dropupClass = ['bottom', 'both'].includes(opts.paginationVAlign) ? \" \".concat(this.constants.classes.dropup) : '';
        this.\$pagination.last().find('.page-list > div').addClass(dropupClass);

        if (!opts.onlyInfoPagination) {
          \$pageList = this.\$pagination.find('.page-list a');
          \$pre = this.\$pagination.find('.page-pre');
          \$next = this.\$pagination.find('.page-next');
          \$number = this.\$pagination.find('.page-item').not('.page-next, .page-pre, .page-last-separator, .page-first-separator');

          if (this.totalPages <= 1) {
            this.\$pagination.find('div.pagination').hide();
          }

          if (opts.smartDisplay) {
            if (pageList.length < 2 || opts.totalRows <= pageList[0]) {
              this.\$pagination.find('span.page-list').hide();
            }
          } // when data is empty, hide the pagination


          this.\$pagination[this.getData().length ? 'show' : 'hide']();

          if (!opts.paginationLoop) {
            if (opts.pageNumber === 1) {
              \$pre.addClass('disabled');
            }

            if (opts.pageNumber === this.totalPages) {
              \$next.addClass('disabled');
            }
          }

          if (allSelected) {
            opts.pageSize = opts.formatAllRows();
          } // removed the events for last and first, onPageNumber executeds the same logic


          \$pageList.off('click').on('click', function (e) {
            return _this6.onPageListChange(e);
          });
          \$pre.off('click').on('click', function (e) {
            return _this6.onPagePre(e);
          });
          \$next.off('click').on('click', function (e) {
            return _this6.onPageNext(e);
          });
          \$number.off('click').on('click', function (e) {
            return _this6.onPageNumber(e);
          });
        }
      }
    }, {
      key: \"updatePagination\",
      value: function updatePagination(event) {
        // Fix #171: IE disabled button can be clicked bug.
        if (event && \$__default['default'](event.currentTarget).hasClass('disabled')) {
          return;
        }

        if (!this.options.maintainMetaData) {
          this.resetRows();
        }

        this.initPagination();
        this.trigger('page-change', this.options.pageNumber, this.options.pageSize);

        if (this.options.sidePagination === 'server') {
          this.initServer();
        } else {
          this.initBody();
        }
      }
    }, {
      key: \"onPageListChange\",
      value: function onPageListChange(event) {
        event.preventDefault();
        var \$this = \$__default['default'](event.currentTarget);
        \$this.parent().addClass(this.constants.classes.dropdownActive).siblings().removeClass(this.constants.classes.dropdownActive);
        this.options.pageSize = \$this.text().toUpperCase() === this.options.formatAllRows().toUpperCase() ? this.options.formatAllRows() : +\$this.text();
        this.\$toolbar.find('.page-size').text(this.options.pageSize);
        this.updatePagination(event);
        return false;
      }
    }, {
      key: \"onPagePre\",
      value: function onPagePre(event) {
        event.preventDefault();

        if (this.options.pageNumber - 1 === 0) {
          this.options.pageNumber = this.options.totalPages;
        } else {
          this.options.pageNumber--;
        }

        this.updatePagination(event);
        return false;
      }
    }, {
      key: \"onPageNext\",
      value: function onPageNext(event) {
        event.preventDefault();

        if (this.options.pageNumber + 1 > this.options.totalPages) {
          this.options.pageNumber = 1;
        } else {
          this.options.pageNumber++;
        }

        this.updatePagination(event);
        return false;
      }
    }, {
      key: \"onPageNumber\",
      value: function onPageNumber(event) {
        event.preventDefault();

        if (this.options.pageNumber === +\$__default['default'](event.currentTarget).text()) {
          return;
        }

        this.options.pageNumber = +\$__default['default'](event.currentTarget).text();
        this.updatePagination(event);
        return false;
      } // eslint-disable-next-line no-unused-vars

    }, {
      key: \"initRow\",
      value: function initRow(item, i, data, trFragments) {
        var _this7 = this;

        var html = [];
        var style = {};
        var csses = [];
        var data_ = '';
        var attributes = {};
        var htmlAttributes = [];

        if (Utils.findIndex(this.hiddenRows, item) > -1) {
          return;
        }

        style = Utils.calculateObjectValue(this.options, this.options.rowStyle, [item, i], style);

        if (style && style.css) {
          for (var _i7 = 0, _Object\$entries6 = Object.entries(style.css); _i7 < _Object\$entries6.length; _i7++) {
            var _Object\$entries6\$_i = _slicedToArray(_Object\$entries6[_i7], 2),
                key = _Object\$entries6\$_i[0],
                value = _Object\$entries6\$_i[1];

            csses.push(\"\".concat(key, \": \").concat(value));
          }
        }

        attributes = Utils.calculateObjectValue(this.options, this.options.rowAttributes, [item, i], attributes);

        if (attributes) {
          for (var _i8 = 0, _Object\$entries7 = Object.entries(attributes); _i8 < _Object\$entries7.length; _i8++) {
            var _Object\$entries7\$_i = _slicedToArray(_Object\$entries7[_i8], 2),
                _key2 = _Object\$entries7\$_i[0],
                _value = _Object\$entries7\$_i[1];

            htmlAttributes.push(\"\".concat(_key2, \"=\\\"\").concat(Utils.escapeHTML(_value), \"\\\"\"));
          }
        }

        if (item._data && !Utils.isEmptyObject(item._data)) {
          for (var _i9 = 0, _Object\$entries8 = Object.entries(item._data); _i9 < _Object\$entries8.length; _i9++) {
            var _Object\$entries8\$_i = _slicedToArray(_Object\$entries8[_i9], 2),
                k = _Object\$entries8\$_i[0],
                v = _Object\$entries8\$_i[1];

            // ignore data-index
            if (k === 'index') {
              return;
            }

            data_ += \" data-\".concat(k, \"='\").concat(_typeof(v) === 'object' ? JSON.stringify(v) : v, \"'\");
          }
        }

        html.push('<tr', Utils.sprintf(' %s', htmlAttributes.length ? htmlAttributes.join(' ') : undefined), Utils.sprintf(' id=\"%s\"', Array.isArray(item) ? undefined : item._id), Utils.sprintf(' class=\"%s\"', style.classes || (Array.isArray(item) ? undefined : item._class)), Utils.sprintf(' style=\"%s\"', Array.isArray(item) ? undefined : item._style), \" data-index=\\\"\".concat(i, \"\\\"\"), Utils.sprintf(' data-uniqueid=\"%s\"', Utils.getItemField(item, this.options.uniqueId, false)), Utils.sprintf(' data-has-detail-view=\"%s\"', this.options.detailView && Utils.calculateObjectValue(null, this.options.detailFilter, [i, item]) ? 'true' : undefined), Utils.sprintf('%s', data_), '>');

        if (this.options.cardView) {
          html.push(\"<td colspan=\\\"\".concat(this.header.fields.length, \"\\\"><div class=\\\"card-views\\\">\"));
        }

        var detailViewTemplate = '';

        if (Utils.hasDetailViewIcon(this.options)) {
          detailViewTemplate = '<td>';

          if (Utils.calculateObjectValue(null, this.options.detailFilter, [i, item])) {
            detailViewTemplate += \"\\n          <a class=\\\"detail-icon\\\" href=\\\"#\\\">\\n          \".concat(Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, this.options.icons.detailOpen), \"\\n          </a>\\n        \");
          }

          detailViewTemplate += '</td>';
        }

        if (detailViewTemplate && this.options.detailViewAlign !== 'right') {
          html.push(detailViewTemplate);
        }

        this.header.fields.forEach(function (field, j) {
          var text = '';
          var value_ = Utils.getItemField(item, field, _this7.options.escape);
          var value = '';
          var type = '';
          var cellStyle = {};
          var id_ = '';
          var class_ = _this7.header.classes[j];
          var style_ = '';
          var styleToAdd_ = '';
          var data_ = '';
          var rowspan_ = '';
          var colspan_ = '';
          var title_ = '';
          var column = _this7.columns[j];

          if ((_this7.fromHtml || _this7.autoMergeCells) && typeof value_ === 'undefined') {
            if (!column.checkbox && !column.radio) {
              return;
            }
          }

          if (!column.visible) {
            return;
          }

          if (_this7.options.cardView && !column.cardVisible) {
            return;
          }

          if (column.escape) {
            value_ = Utils.escapeHTML(value_);
          } // Style concat


          if (csses.concat([_this7.header.styles[j]]).length) {
            styleToAdd_ += \"\".concat(csses.concat([_this7.header.styles[j]]).join('; '));
          }

          if (item[\"_\".concat(field, \"_style\")]) {
            styleToAdd_ += \"\".concat(item[\"_\".concat(field, \"_style\")]);
          }

          if (styleToAdd_) {
            style_ = \" style=\\\"\".concat(styleToAdd_, \"\\\"\");
          } // Style concat
          // handle id and class of td


          if (item[\"_\".concat(field, \"_id\")]) {
            id_ = Utils.sprintf(' id=\"%s\"', item[\"_\".concat(field, \"_id\")]);
          }

          if (item[\"_\".concat(field, \"_class\")]) {
            class_ = Utils.sprintf(' class=\"%s\"', item[\"_\".concat(field, \"_class\")]);
          }

          if (item[\"_\".concat(field, \"_rowspan\")]) {
            rowspan_ = Utils.sprintf(' rowspan=\"%s\"', item[\"_\".concat(field, \"_rowspan\")]);
          }

          if (item[\"_\".concat(field, \"_colspan\")]) {
            colspan_ = Utils.sprintf(' colspan=\"%s\"', item[\"_\".concat(field, \"_colspan\")]);
          }

          if (item[\"_\".concat(field, \"_title\")]) {
            title_ = Utils.sprintf(' title=\"%s\"', item[\"_\".concat(field, \"_title\")]);
          }

          cellStyle = Utils.calculateObjectValue(_this7.header, _this7.header.cellStyles[j], [value_, item, i, field], cellStyle);

          if (cellStyle.classes) {
            class_ = \" class=\\\"\".concat(cellStyle.classes, \"\\\"\");
          }

          if (cellStyle.css) {
            var csses_ = [];

            for (var _i10 = 0, _Object\$entries9 = Object.entries(cellStyle.css); _i10 < _Object\$entries9.length; _i10++) {
              var _Object\$entries9\$_i = _slicedToArray(_Object\$entries9[_i10], 2),
                  _key3 = _Object\$entries9\$_i[0],
                  _value2 = _Object\$entries9\$_i[1];

              csses_.push(\"\".concat(_key3, \": \").concat(_value2));
            }

            style_ = \" style=\\\"\".concat(csses_.concat(_this7.header.styles[j]).join('; '), \"\\\"\");
          }

          value = Utils.calculateObjectValue(column, _this7.header.formatters[j], [value_, item, i, field], value_);

          if (!(column.checkbox || column.radio)) {
            value = typeof value === 'undefined' || value === null ? _this7.options.undefinedText : value;
          }

          if (column.searchable && _this7.searchText && _this7.options.searchHighlight) {
            var defValue = '';
            var regExp = new RegExp(\"(\".concat(_this7.searchText.replace(/[.*+?^\${}()|[\\]\\\\]/g, '\\\\\$&'), \")\"), 'gim');
            var marker = '<mark>\$1</mark>';
            var isHTML = value && /<(?=.*? .*?\\/ ?>|br|hr|input|!--|wbr)[a-z]+.*?>|<([a-z]+).*?<\\/\\1>/i.test(value);

            if (isHTML) {
              // value can contains a HTML tags
              var textContent = new DOMParser().parseFromString(value.toString(), 'text/html').documentElement.textContent;
              var textReplaced = textContent.replace(regExp, marker);
              defValue = value.replace(new RegExp(\"(>\\\\s*)(\".concat(textContent, \")(\\\\s*)\"), 'gm'), \"\$1\".concat(textReplaced, \"\$3\"));
            } else {
              // but usually not
              defValue = value.toString().replace(regExp, marker);
            }

            value = Utils.calculateObjectValue(column, column.searchHighlightFormatter, [value, _this7.searchText], defValue);
          }

          if (item[\"_\".concat(field, \"_data\")] && !Utils.isEmptyObject(item[\"_\".concat(field, \"_data\")])) {
            for (var _i11 = 0, _Object\$entries10 = Object.entries(item[\"_\".concat(field, \"_data\")]); _i11 < _Object\$entries10.length; _i11++) {
              var _Object\$entries10\$_i = _slicedToArray(_Object\$entries10[_i11], 2),
                  _k = _Object\$entries10\$_i[0],
                  _v = _Object\$entries10\$_i[1];

              // ignore data-index
              if (_k === 'index') {
                return;
              }

              data_ += \" data-\".concat(_k, \"=\\\"\").concat(_v, \"\\\"\");
            }
          }

          if (column.checkbox || column.radio) {
            type = column.checkbox ? 'checkbox' : type;
            type = column.radio ? 'radio' : type;
            var c = column['class'] || '';
            var isChecked = Utils.isObject(value) && value.hasOwnProperty('checked') ? value.checked : (value === true || value_) && value !== false;
            var isDisabled = !column.checkboxEnabled || value && value.disabled;
            text = [_this7.options.cardView ? \"<div class=\\\"card-view \".concat(c, \"\\\">\") : \"<td class=\\\"bs-checkbox \".concat(c, \"\\\"\").concat(class_).concat(style_, \">\"), \"<label>\\n            <input\\n            data-index=\\\"\".concat(i, \"\\\"\\n            name=\\\"\").concat(_this7.options.selectItemName, \"\\\"\\n            type=\\\"\").concat(type, \"\\\"\\n            \").concat(Utils.sprintf('value=\"%s\"', item[_this7.options.idField]), \"\\n            \").concat(Utils.sprintf('checked=\"%s\"', isChecked ? 'checked' : undefined), \"\\n            \").concat(Utils.sprintf('disabled=\"%s\"', isDisabled ? 'disabled' : undefined), \" />\\n            <span></span>\\n            </label>\"), _this7.header.formatters[j] && typeof value === 'string' ? value : '', _this7.options.cardView ? '</div>' : '</td>'].join('');
            item[_this7.header.stateField] = value === true || !!value_ || value && value.checked;
          } else if (_this7.options.cardView) {
            var cardTitle = _this7.options.showHeader ? \"<span class=\\\"card-view-title \".concat(cellStyle.classes, \"\\\"\").concat(style_, \">\").concat(Utils.getFieldTitle(_this7.columns, field), \"</span>\") : '';
            text = \"<div class=\\\"card-view\\\">\".concat(cardTitle, \"<span class=\\\"card-view-value \").concat(cellStyle.classes, \"\\\"\").concat(style_, \">\").concat(value, \"</span></div>\");

            if (_this7.options.smartDisplay && value === '') {
              text = '<div class=\"card-view\"></div>';
            }
          } else {
            text = \"<td\".concat(id_).concat(class_).concat(style_).concat(data_).concat(rowspan_).concat(colspan_).concat(title_, \">\").concat(value, \"</td>\");
          }

          html.push(text);
        });

        if (detailViewTemplate && this.options.detailViewAlign === 'right') {
          html.push(detailViewTemplate);
        }

        if (this.options.cardView) {
          html.push('</div></td>');
        }

        html.push('</tr>');
        return html.join('');
      }
    }, {
      key: \"initBody\",
      value: function initBody(fixedScroll) {
        var _this8 = this;

        var data = this.getData();
        this.trigger('pre-body', data);
        this.\$body = this.\$el.find('>tbody');

        if (!this.\$body.length) {
          this.\$body = \$__default['default']('<tbody></tbody>').appendTo(this.\$el);
        } // Fix #389 Bootstrap-table-flatJSON is not working


        if (!this.options.pagination || this.options.sidePagination === 'server') {
          this.pageFrom = 1;
          this.pageTo = data.length;
        }

        var rows = [];
        var trFragments = \$__default['default'](document.createDocumentFragment());
        var hasTr = false;
        this.autoMergeCells = Utils.checkAutoMergeCells(data.slice(this.pageFrom - 1, this.pageTo));

        for (var i = this.pageFrom - 1; i < this.pageTo; i++) {
          var item = data[i];
          var tr = this.initRow(item, i, data, trFragments);
          hasTr = hasTr || !!tr;

          if (tr && typeof tr === 'string') {
            if (!this.options.virtualScroll) {
              trFragments.append(tr);
            } else {
              rows.push(tr);
            }
          }
        } // show no records


        if (!hasTr) {
          this.\$body.html(\"<tr class=\\\"no-records-found\\\">\".concat(Utils.sprintf('<td colspan=\"%s\">%s</td>', this.getVisibleFields().length + Utils.getDetailViewIndexOffset(this.options), this.options.formatNoMatches()), \"</tr>\"));
        } else if (!this.options.virtualScroll) {
          this.\$body.html(trFragments);
        } else {
          if (this.virtualScroll) {
            this.virtualScroll.destroy();
          }

          this.virtualScroll = new VirtualScroll({
            rows: rows,
            fixedScroll: fixedScroll,
            scrollEl: this.\$tableBody[0],
            contentEl: this.\$body[0],
            itemHeight: this.options.virtualScrollItemHeight,
            callback: function callback() {
              _this8.fitHeader();

              _this8.initBodyEvent();
            }
          });
        }

        if (!fixedScroll) {
          this.scrollTo(0);
        }

        this.initBodyEvent();
        this.updateSelected();
        this.initFooter();
        this.resetView();

        if (this.options.sidePagination !== 'server') {
          this.options.totalRows = data.length;
        }

        this.trigger('post-body', data);
      }
    }, {
      key: \"initBodyEvent\",
      value: function initBodyEvent() {
        var _this9 = this;

        // click to select by column
        this.\$body.find('> tr[data-index] > td').off('click dblclick').on('click dblclick', function (e) {
          var \$td = \$__default['default'](e.currentTarget);
          var \$tr = \$td.parent();
          var \$cardViewArr = \$__default['default'](e.target).parents('.card-views').children();
          var \$cardViewTarget = \$__default['default'](e.target).parents('.card-view');
          var rowIndex = \$tr.data('index');
          var item = _this9.data[rowIndex];
          var index = _this9.options.cardView ? \$cardViewArr.index(\$cardViewTarget) : \$td[0].cellIndex;

          var fields = _this9.getVisibleFields();

          var field = fields[index - Utils.getDetailViewIndexOffset(_this9.options)];
          var column = _this9.columns[_this9.fieldsColumnsIndex[field]];
          var value = Utils.getItemField(item, field, _this9.options.escape);

          if (\$td.find('.detail-icon').length) {
            return;
          }

          _this9.trigger(e.type === 'click' ? 'click-cell' : 'dbl-click-cell', field, value, item, \$td);

          _this9.trigger(e.type === 'click' ? 'click-row' : 'dbl-click-row', item, \$tr, field); // if click to select - then trigger the checkbox/radio click


          if (e.type === 'click' && _this9.options.clickToSelect && column.clickToSelect && !Utils.calculateObjectValue(_this9.options, _this9.options.ignoreClickToSelectOn, [e.target])) {
            var \$selectItem = \$tr.find(Utils.sprintf('[name=\"%s\"]', _this9.options.selectItemName));

            if (\$selectItem.length) {
              \$selectItem[0].click();
            }
          }

          if (e.type === 'click' && _this9.options.detailViewByClick) {
            _this9.toggleDetailView(rowIndex, _this9.header.detailFormatters[_this9.fieldsColumnsIndex[field]]);
          }
        }).off('mousedown').on('mousedown', function (e) {
          // https://github.com/jquery/jquery/issues/1741
          _this9.multipleSelectRowCtrlKey = e.ctrlKey || e.metaKey;
          _this9.multipleSelectRowShiftKey = e.shiftKey;
        });
        this.\$body.find('> tr[data-index] > td > .detail-icon').off('click').on('click', function (e) {
          e.preventDefault();

          _this9.toggleDetailView(\$__default['default'](e.currentTarget).parent().parent().data('index'));

          return false;
        });
        this.\$selectItem = this.\$body.find(Utils.sprintf('[name=\"%s\"]', this.options.selectItemName));
        this.\$selectItem.off('click').on('click', function (e) {
          e.stopImmediatePropagation();
          var \$this = \$__default['default'](e.currentTarget);

          _this9._toggleCheck(\$this.prop('checked'), \$this.data('index'));
        });
        this.header.events.forEach(function (_events, i) {
          var events = _events;

          if (!events) {
            return;
          } // fix bug, if events is defined with namespace


          if (typeof events === 'string') {
            events = Utils.calculateObjectValue(null, events);
          }

          var field = _this9.header.fields[i];

          var fieldIndex = _this9.getVisibleFields().indexOf(field);

          if (fieldIndex === -1) {
            return;
          }

          fieldIndex += Utils.getDetailViewIndexOffset(_this9.options);

          var _loop2 = function _loop2(key) {
            if (!events.hasOwnProperty(key)) {
              return \"continue\";
            }

            var event = events[key];

            _this9.\$body.find('>tr:not(.no-records-found)').each(function (i, tr) {
              var \$tr = \$__default['default'](tr);
              var \$td = \$tr.find(_this9.options.cardView ? '.card-views>.card-view' : '>td').eq(fieldIndex);
              var index = key.indexOf(' ');
              var name = key.substring(0, index);
              var el = key.substring(index + 1);
              \$td.find(el).off(name).on(name, function (e) {
                var index = \$tr.data('index');
                var row = _this9.data[index];
                var value = row[field];
                event.apply(_this9, [e, value, row, index]);
              });
            });
          };

          for (var key in events) {
            var _ret2 = _loop2(key);

            if (_ret2 === \"continue\") continue;
          }
        });
      }
    }, {
      key: \"initServer\",
      value: function initServer(silent, query, url) {
        var _this10 = this;

        var data = {};
        var index = this.header.fields.indexOf(this.options.sortName);
        var params = {
          searchText: this.searchText,
          sortName: this.options.sortName,
          sortOrder: this.options.sortOrder
        };

        if (this.header.sortNames[index]) {
          params.sortName = this.header.sortNames[index];
        }

        if (this.options.pagination && this.options.sidePagination === 'server') {
          params.pageSize = this.options.pageSize === this.options.formatAllRows() ? this.options.totalRows : this.options.pageSize;
          params.pageNumber = this.options.pageNumber;
        }

        if (!(url || this.options.url) && !this.options.ajax) {
          return;
        }

        if (this.options.queryParamsType === 'limit') {
          params = {
            search: params.searchText,
            sort: params.sortName,
            order: params.sortOrder
          };

          if (this.options.pagination && this.options.sidePagination === 'server') {
            params.offset = this.options.pageSize === this.options.formatAllRows() ? 0 : this.options.pageSize * (this.options.pageNumber - 1);
            params.limit = this.options.pageSize === this.options.formatAllRows() ? this.options.totalRows : this.options.pageSize;

            if (params.limit === 0) {
              delete params.limit;
            }
          }
        }

        if (this.options.search && this.options.sidePagination === 'server' && this.columns.filter(function (column) {
          return !column.searchable;
        }).length) {
          params.searchable = [];

          var _iterator2 = _createForOfIteratorHelper(this.columns),
              _step2;

          try {
            for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
              var column = _step2.value;

              if (!column.checkbox && column.searchable && (this.options.visibleSearch && column.visible || !this.options.visibleSearch)) {
                params.searchable.push(column.field);
              }
            }
          } catch (err) {
            _iterator2.e(err);
          } finally {
            _iterator2.f();
          }
        }

        if (!Utils.isEmptyObject(this.filterColumnsPartial)) {
          params.filter = JSON.stringify(this.filterColumnsPartial, null);
        }

        \$__default['default'].extend(params, query || {});
        data = Utils.calculateObjectValue(this.options, this.options.queryParams, [params], data); // false to stop request

        if (data === false) {
          return;
        }

        if (!silent) {
          this.showLoading();
        }

        var request = \$__default['default'].extend({}, Utils.calculateObjectValue(null, this.options.ajaxOptions), {
          type: this.options.method,
          url: url || this.options.url,
          data: this.options.contentType === 'application/json' && this.options.method === 'post' ? JSON.stringify(data) : data,
          cache: this.options.cache,
          contentType: this.options.contentType,
          dataType: this.options.dataType,
          success: function success(_res, textStatus, jqXHR) {
            var res = Utils.calculateObjectValue(_this10.options, _this10.options.responseHandler, [_res, jqXHR], _res);

            _this10.load(res);

            _this10.trigger('load-success', res, jqXHR && jqXHR.status, jqXHR);

            if (!silent) {
              _this10.hideLoading();
            }

            if (_this10.options.sidePagination === 'server' && res[_this10.options.totalField] > 0 && !res[_this10.options.dataField].length) {
              _this10.updatePagination();
            }
          },
          error: function error(jqXHR) {
            var data = [];

            if (_this10.options.sidePagination === 'server') {
              data = {};
              data[_this10.options.totalField] = 0;
              data[_this10.options.dataField] = [];
            }

            _this10.load(data);

            _this10.trigger('load-error', jqXHR && jqXHR.status, jqXHR);

            if (!silent) _this10.\$tableLoading.hide();
          }
        });

        if (this.options.ajax) {
          Utils.calculateObjectValue(this, this.options.ajax, [request], null);
        } else {
          if (this._xhr && this._xhr.readyState !== 4) {
            this._xhr.abort();
          }

          this._xhr = \$__default['default'].ajax(request);
        }

        return data;
      }
    }, {
      key: \"initSearchText\",
      value: function initSearchText() {
        if (this.options.search) {
          this.searchText = '';

          if (this.options.searchText !== '') {
            var \$search = Utils.getSearchInput(this);
            \$search.val(this.options.searchText);
            this.onSearch({
              currentTarget: \$search,
              firedByInitSearchText: true
            });
          }
        }
      }
    }, {
      key: \"getCaret\",
      value: function getCaret() {
        var _this11 = this;

        this.\$header.find('th').each(function (i, th) {
          \$__default['default'](th).find('.sortable').removeClass('desc asc').addClass(\$__default['default'](th).data('field') === _this11.options.sortName ? _this11.options.sortOrder : 'both');
        });
      }
    }, {
      key: \"updateSelected\",
      value: function updateSelected() {
        var checkAll = this.\$selectItem.filter(':enabled').length && this.\$selectItem.filter(':enabled').length === this.\$selectItem.filter(':enabled').filter(':checked').length;
        this.\$selectAll.add(this.\$selectAll_).prop('checked', checkAll);
        this.\$selectItem.each(function (i, el) {
          \$__default['default'](el).closest('tr')[\$__default['default'](el).prop('checked') ? 'addClass' : 'removeClass']('selected');
        });
      }
    }, {
      key: \"updateRows\",
      value: function updateRows() {
        var _this12 = this;

        this.\$selectItem.each(function (i, el) {
          _this12.data[\$__default['default'](el).data('index')][_this12.header.stateField] = \$__default['default'](el).prop('checked');
        });
      }
    }, {
      key: \"resetRows\",
      value: function resetRows() {
        var _iterator3 = _createForOfIteratorHelper(this.data),
            _step3;

        try {
          for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
            var row = _step3.value;
            this.\$selectAll.prop('checked', false);
            this.\$selectItem.prop('checked', false);

            if (this.header.stateField) {
              row[this.header.stateField] = false;
            }
          }
        } catch (err) {
          _iterator3.e(err);
        } finally {
          _iterator3.f();
        }

        this.initHiddenRows();
      }
    }, {
      key: \"trigger\",
      value: function trigger(_name) {
        var _this\$options, _this\$options2;

        var name = \"\".concat(_name, \".bs.table\");

        for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key4 = 1; _key4 < _len; _key4++) {
          args[_key4 - 1] = arguments[_key4];
        }

        (_this\$options = this.options)[BootstrapTable.EVENTS[name]].apply(_this\$options, [].concat(args, [this]));

        this.\$el.trigger(\$__default['default'].Event(name, {
          sender: this
        }), args);

        (_this\$options2 = this.options).onAll.apply(_this\$options2, [name].concat([].concat(args, [this])));

        this.\$el.trigger(\$__default['default'].Event('all.bs.table', {
          sender: this
        }), [name, args]);
      }
    }, {
      key: \"resetHeader\",
      value: function resetHeader() {
        var _this13 = this;

        // fix #61: the hidden table reset header bug.
        // fix bug: get \$el.css('width') error sometime (height = 500)
        clearTimeout(this.timeoutId_);
        this.timeoutId_ = setTimeout(function () {
          return _this13.fitHeader();
        }, this.\$el.is(':hidden') ? 100 : 0);
      }
    }, {
      key: \"fitHeader\",
      value: function fitHeader() {
        var _this14 = this;

        if (this.\$el.is(':hidden')) {
          this.timeoutId_ = setTimeout(function () {
            return _this14.fitHeader();
          }, 100);
          return;
        }

        var fixedBody = this.\$tableBody.get(0);
        var scrollWidth = fixedBody.scrollWidth > fixedBody.clientWidth && fixedBody.scrollHeight > fixedBody.clientHeight + this.\$header.outerHeight() ? Utils.getScrollBarWidth() : 0;
        this.\$el.css('margin-top', -this.\$header.outerHeight());
        var focused = \$__default['default'](':focus');

        if (focused.length > 0) {
          var \$th = focused.parents('th');

          if (\$th.length > 0) {
            var dataField = \$th.attr('data-field');

            if (dataField !== undefined) {
              var \$headerTh = this.\$header.find(\"[data-field='\".concat(dataField, \"']\"));

              if (\$headerTh.length > 0) {
                \$headerTh.find(':input').addClass('focus-temp');
              }
            }
          }
        }

        this.\$header_ = this.\$header.clone(true, true);
        this.\$selectAll_ = this.\$header_.find('[name=\"btSelectAll\"]');
        this.\$tableHeader.css('margin-right', scrollWidth).find('table').css('width', this.\$el.outerWidth()).html('').attr('class', this.\$el.attr('class')).append(this.\$header_);
        this.\$tableLoading.css('width', this.\$el.outerWidth());
        var focusedTemp = \$__default['default']('.focus-temp:visible:eq(0)');

        if (focusedTemp.length > 0) {
          focusedTemp.focus();
          this.\$header.find('.focus-temp').removeClass('focus-temp');
        } // fix bug: \$.data() is not working as expected after \$.append()


        this.\$header.find('th[data-field]').each(function (i, el) {
          _this14.\$header_.find(Utils.sprintf('th[data-field=\"%s\"]', \$__default['default'](el).data('field'))).data(\$__default['default'](el).data());
        });
        var visibleFields = this.getVisibleFields();
        var \$ths = this.\$header_.find('th');
        var \$tr = this.\$body.find('>tr:not(.no-records-found,.virtual-scroll-top)').eq(0);

        while (\$tr.length && \$tr.find('>td[colspan]:not([colspan=\"1\"])').length) {
          \$tr = \$tr.next();
        }

        var trLength = \$tr.find('> *').length;
        \$tr.find('> *').each(function (i, el) {
          var \$this = \$__default['default'](el);

          if (Utils.hasDetailViewIcon(_this14.options)) {
            if (i === 0 && _this14.options.detailViewAlign !== 'right' || i === trLength - 1 && _this14.options.detailViewAlign === 'right') {
              var \$thDetail = \$ths.filter('.detail');

              var _zoomWidth = \$thDetail.innerWidth() - \$thDetail.find('.fht-cell').width();

              \$thDetail.find('.fht-cell').width(\$this.innerWidth() - _zoomWidth);
              return;
            }
          }

          var index = i - Utils.getDetailViewIndexOffset(_this14.options);

          var \$th = _this14.\$header_.find(Utils.sprintf('th[data-field=\"%s\"]', visibleFields[index]));

          if (\$th.length > 1) {
            \$th = \$__default['default'](\$ths[\$this[0].cellIndex]);
          }

          var zoomWidth = \$th.innerWidth() - \$th.find('.fht-cell').width();
          \$th.find('.fht-cell').width(\$this.innerWidth() - zoomWidth);
        });
        this.horizontalScroll();
        this.trigger('post-header');
      }
    }, {
      key: \"initFooter\",
      value: function initFooter() {
        if (!this.options.showFooter || this.options.cardView) {
          // do nothing
          return;
        }

        var data = this.getData();
        var html = [];
        var detailTemplate = '';

        if (Utils.hasDetailViewIcon(this.options)) {
          detailTemplate = '<th class=\"detail\"><div class=\"th-inner\"></div><div class=\"fht-cell\"></div></th>';
        }

        if (detailTemplate && this.options.detailViewAlign !== 'right') {
          html.push(detailTemplate);
        }

        var _iterator4 = _createForOfIteratorHelper(this.columns),
            _step4;

        try {
          for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
            var column = _step4.value;
            var falign = '';
            var valign = '';
            var csses = [];
            var style = {};
            var class_ = Utils.sprintf(' class=\"%s\"', column['class']);

            if (!column.visible || this.footerData && this.footerData.length > 0 && !(column.field in this.footerData[0])) {
              continue;
            }

            if (this.options.cardView && !column.cardVisible) {
              return;
            }

            falign = Utils.sprintf('text-align: %s; ', column.falign ? column.falign : column.align);
            valign = Utils.sprintf('vertical-align: %s; ', column.valign);
            style = Utils.calculateObjectValue(null, this.options.footerStyle, [column]);

            if (style && style.css) {
              for (var _i12 = 0, _Object\$entries11 = Object.entries(style.css); _i12 < _Object\$entries11.length; _i12++) {
                var _Object\$entries11\$_i = _slicedToArray(_Object\$entries11[_i12], 2),
                    key = _Object\$entries11\$_i[0],
                    _value3 = _Object\$entries11\$_i[1];

                csses.push(\"\".concat(key, \": \").concat(_value3));
              }
            }

            if (style && style.classes) {
              class_ = Utils.sprintf(' class=\"%s\"', column['class'] ? [column['class'], style.classes].join(' ') : style.classes);
            }

            html.push('<th', class_, Utils.sprintf(' style=\"%s\"', falign + valign + csses.concat().join('; ')));
            var colspan = 0;

            if (this.footerData && this.footerData.length > 0) {
              colspan = this.footerData[0][\"_\".concat(column.field, \"_colspan\")] || 0;
            }

            if (colspan) {
              html.push(\" colspan=\\\"\".concat(colspan, \"\\\" \"));
            }

            html.push('>');
            html.push('<div class=\"th-inner\">');
            var value = '';

            if (this.footerData && this.footerData.length > 0) {
              value = this.footerData[0][column.field] || '';
            }

            html.push(Utils.calculateObjectValue(column, column.footerFormatter, [data, value], value));
            html.push('</div>');
            html.push('<div class=\"fht-cell\"></div>');
            html.push('</div>');
            html.push('</th>');
          }
        } catch (err) {
          _iterator4.e(err);
        } finally {
          _iterator4.f();
        }

        if (detailTemplate && this.options.detailViewAlign === 'right') {
          html.push(detailTemplate);
        }

        if (!this.options.height && !this.\$tableFooter.length) {
          this.\$el.append('<tfoot><tr></tr></tfoot>');
          this.\$tableFooter = this.\$el.find('tfoot');
        }

        if (!this.\$tableFooter.find('tr').length) {
          this.\$tableFooter.html('<table><thead><tr></tr></thead></table>');
        }

        this.\$tableFooter.find('tr').html(html.join(''));
        this.trigger('post-footer', this.\$tableFooter);
      }
    }, {
      key: \"fitFooter\",
      value: function fitFooter() {
        var _this15 = this;

        if (this.\$el.is(':hidden')) {
          setTimeout(function () {
            return _this15.fitFooter();
          }, 100);
          return;
        }

        var fixedBody = this.\$tableBody.get(0);
        var scrollWidth = fixedBody.scrollWidth > fixedBody.clientWidth && fixedBody.scrollHeight > fixedBody.clientHeight + this.\$header.outerHeight() ? Utils.getScrollBarWidth() : 0;
        this.\$tableFooter.css('margin-right', scrollWidth).find('table').css('width', this.\$el.outerWidth()).attr('class', this.\$el.attr('class'));
        var \$ths = this.\$tableFooter.find('th');
        var \$tr = this.\$body.find('>tr:first-child:not(.no-records-found)');
        \$ths.find('.fht-cell').width('auto');

        while (\$tr.length && \$tr.find('>td[colspan]:not([colspan=\"1\"])').length) {
          \$tr = \$tr.next();
        }

        var trLength = \$tr.find('> *').length;
        \$tr.find('> *').each(function (i, el) {
          var \$this = \$__default['default'](el);

          if (Utils.hasDetailViewIcon(_this15.options)) {
            if (i === 0 && _this15.options.detailViewAlign === 'left' || i === trLength - 1 && _this15.options.detailViewAlign === 'right') {
              var \$thDetail = \$ths.filter('.detail');

              var _zoomWidth2 = \$thDetail.innerWidth() - \$thDetail.find('.fht-cell').width();

              \$thDetail.find('.fht-cell').width(\$this.innerWidth() - _zoomWidth2);
              return;
            }
          }

          var \$th = \$ths.eq(i);
          var zoomWidth = \$th.innerWidth() - \$th.find('.fht-cell').width();
          \$th.find('.fht-cell').width(\$this.innerWidth() - zoomWidth);
        });
        this.horizontalScroll();
      }
    }, {
      key: \"horizontalScroll\",
      value: function horizontalScroll() {
        var _this16 = this;

        // horizontal scroll event
        // TODO: it's probably better improving the layout than binding to scroll event
        this.\$tableBody.off('scroll').on('scroll', function () {
          var scrollLeft = _this16.\$tableBody.scrollLeft();

          if (_this16.options.showHeader && _this16.options.height) {
            _this16.\$tableHeader.scrollLeft(scrollLeft);
          }

          if (_this16.options.showFooter && !_this16.options.cardView) {
            _this16.\$tableFooter.scrollLeft(scrollLeft);
          }

          _this16.trigger('scroll-body', _this16.\$tableBody);
        });
      }
    }, {
      key: \"getVisibleFields\",
      value: function getVisibleFields() {
        var visibleFields = [];

        var _iterator5 = _createForOfIteratorHelper(this.header.fields),
            _step5;

        try {
          for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
            var field = _step5.value;
            var column = this.columns[this.fieldsColumnsIndex[field]];

            if (!column || !column.visible) {
              continue;
            }

            visibleFields.push(field);
          }
        } catch (err) {
          _iterator5.e(err);
        } finally {
          _iterator5.f();
        }

        return visibleFields;
      }
    }, {
      key: \"initHiddenRows\",
      value: function initHiddenRows() {
        this.hiddenRows = [];
      } // PUBLIC FUNCTION DEFINITION
      // =======================

    }, {
      key: \"getOptions\",
      value: function getOptions() {
        // deep copy and remove data
        var options = \$__default['default'].extend({}, this.options);
        delete options.data;
        return \$__default['default'].extend(true, {}, options);
      }
    }, {
      key: \"refreshOptions\",
      value: function refreshOptions(options) {
        // If the objects are equivalent then avoid the call of destroy / init methods
        if (Utils.compareObjects(this.options, options, true)) {
          return;
        }

        this.options = \$__default['default'].extend(this.options, options);
        this.trigger('refresh-options', this.options);
        this.destroy();
        this.init();
      }
    }, {
      key: \"getData\",
      value: function getData(params) {
        var _this17 = this;

        var data = this.options.data;

        if ((this.searchText || this.options.customSearch || this.options.sortName !== undefined || this.enableCustomSort || // Fix #4616: this.enableCustomSort is for extensions
        !Utils.isEmptyObject(this.filterColumns) || !Utils.isEmptyObject(this.filterColumnsPartial)) && (!params || !params.unfiltered)) {
          data = this.data;
        }

        if (params && params.useCurrentPage) {
          data = data.slice(this.pageFrom - 1, this.pageTo);
        }

        if (params && !params.includeHiddenRows) {
          var hiddenRows = this.getHiddenRows();
          data = data.filter(function (row) {
            return Utils.findIndex(hiddenRows, row) === -1;
          });
        }

        if (params && params.formatted) {
          data.forEach(function (row) {
            for (var _i13 = 0, _Object\$entries12 = Object.entries(row); _i13 < _Object\$entries12.length; _i13++) {
              var _Object\$entries12\$_i = _slicedToArray(_Object\$entries12[_i13], 2),
                  key = _Object\$entries12\$_i[0],
                  value = _Object\$entries12\$_i[1];

              var column = _this17.columns[_this17.fieldsColumnsIndex[key]];

              if (!column) {
                return;
              }

              row[key] = Utils.calculateObjectValue(column, _this17.header.formatters[column.fieldIndex], [value, row, row.index, column.field], value);
            }
          });
        }

        return data;
      }
    }, {
      key: \"getSelections\",
      value: function getSelections() {
        var _this18 = this;

        return (this.options.maintainMetaData ? this.options.data : this.data).filter(function (row) {
          return row[_this18.header.stateField] === true;
        });
      }
    }, {
      key: \"load\",
      value: function load(_data) {
        var fixedScroll = false;
        var data = _data; // #431: support pagination

        if (this.options.pagination && this.options.sidePagination === 'server') {
          this.options.totalRows = data[this.options.totalField];
          this.options.totalNotFiltered = data[this.options.totalNotFilteredField];
          this.footerData = data[this.options.footerField] ? [data[this.options.footerField]] : undefined;
        }

        fixedScroll = data.fixedScroll;
        data = Array.isArray(data) ? data : data[this.options.dataField];
        this.initData(data);
        this.initSearch();
        this.initPagination();
        this.initBody(fixedScroll);
      }
    }, {
      key: \"append\",
      value: function append(data) {
        this.initData(data, 'append');
        this.initSearch();
        this.initPagination();
        this.initSort();
        this.initBody(true);
      }
    }, {
      key: \"prepend\",
      value: function prepend(data) {
        this.initData(data, 'prepend');
        this.initSearch();
        this.initPagination();
        this.initSort();
        this.initBody(true);
      }
    }, {
      key: \"remove\",
      value: function remove(params) {
        var removed = 0;

        for (var i = this.options.data.length - 1; i >= 0; i--) {
          var row = this.options.data[i];

          if (!row.hasOwnProperty(params.field) && params.field !== '\$index') {
            continue;
          }

          if (!row.hasOwnProperty(params.field) && params.field === '\$index' && params.values.includes(i) || params.values.includes(row[params.field])) {
            removed++;
            this.options.data.splice(i, 1);
          }
        }

        if (!removed) {
          return;
        }

        if (this.options.sidePagination === 'server') {
          this.options.totalRows -= removed;
          this.data = _toConsumableArray(this.options.data);
        }

        this.initSearch();
        this.initPagination();
        this.initSort();
        this.initBody(true);
      }
    }, {
      key: \"removeAll\",
      value: function removeAll() {
        if (this.options.data.length > 0) {
          this.options.data.splice(0, this.options.data.length);
          this.initSearch();
          this.initPagination();
          this.initBody(true);
        }
      }
    }, {
      key: \"insertRow\",
      value: function insertRow(params) {
        if (!params.hasOwnProperty('index') || !params.hasOwnProperty('row')) {
          return;
        }

        this.options.data.splice(params.index, 0, params.row);
        this.initSearch();
        this.initPagination();
        this.initSort();
        this.initBody(true);
      }
    }, {
      key: \"updateRow\",
      value: function updateRow(params) {
        var allParams = Array.isArray(params) ? params : [params];

        var _iterator6 = _createForOfIteratorHelper(allParams),
            _step6;

        try {
          for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
            var _params = _step6.value;

            if (!_params.hasOwnProperty('index') || !_params.hasOwnProperty('row')) {
              continue;
            }

            if (_params.hasOwnProperty('replace') && _params.replace) {
              this.options.data[_params.index] = _params.row;
            } else {
              \$__default['default'].extend(this.options.data[_params.index], _params.row);
            }
          }
        } catch (err) {
          _iterator6.e(err);
        } finally {
          _iterator6.f();
        }

        this.initSearch();
        this.initPagination();
        this.initSort();
        this.initBody(true);
      }
    }, {
      key: \"getRowByUniqueId\",
      value: function getRowByUniqueId(_id) {
        var uniqueId = this.options.uniqueId;
        var len = this.options.data.length;
        var id = _id;
        var dataRow = null;
        var i;
        var row;
        var rowUniqueId;

        for (i = len - 1; i >= 0; i--) {
          row = this.options.data[i];

          if (row.hasOwnProperty(uniqueId)) {
            // uniqueId is a column
            rowUniqueId = row[uniqueId];
          } else if (row._data && row._data.hasOwnProperty(uniqueId)) {
            // uniqueId is a row data property
            rowUniqueId = row._data[uniqueId];
          } else {
            continue;
          }

          if (typeof rowUniqueId === 'string') {
            id = id.toString();
          } else if (typeof rowUniqueId === 'number') {
            if (Number(rowUniqueId) === rowUniqueId && rowUniqueId % 1 === 0) {
              id = parseInt(id);
            } else if (rowUniqueId === Number(rowUniqueId) && rowUniqueId !== 0) {
              id = parseFloat(id);
            }
          }

          if (rowUniqueId === id) {
            dataRow = row;
            break;
          }
        }

        return dataRow;
      }
    }, {
      key: \"updateByUniqueId\",
      value: function updateByUniqueId(params) {
        var allParams = Array.isArray(params) ? params : [params];

        var _iterator7 = _createForOfIteratorHelper(allParams),
            _step7;

        try {
          for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
            var _params2 = _step7.value;

            if (!_params2.hasOwnProperty('id') || !_params2.hasOwnProperty('row')) {
              continue;
            }

            var rowId = this.options.data.indexOf(this.getRowByUniqueId(_params2.id));

            if (rowId === -1) {
              continue;
            }

            if (_params2.hasOwnProperty('replace') && _params2.replace) {
              this.options.data[rowId] = _params2.row;
            } else {
              \$__default['default'].extend(this.options.data[rowId], _params2.row);
            }
          }
        } catch (err) {
          _iterator7.e(err);
        } finally {
          _iterator7.f();
        }

        this.initSearch();
        this.initPagination();
        this.initSort();
        this.initBody(true);
      }
    }, {
      key: \"removeByUniqueId\",
      value: function removeByUniqueId(id) {
        var len = this.options.data.length;
        var row = this.getRowByUniqueId(id);

        if (row) {
          this.options.data.splice(this.options.data.indexOf(row), 1);
        }

        if (len === this.options.data.length) {
          return;
        }

        if (this.options.sidePagination === 'server') {
          this.options.totalRows -= 1;
          this.data = _toConsumableArray(this.options.data);
        }

        this.initSearch();
        this.initPagination();
        this.initBody(true);
      }
    }, {
      key: \"updateCell\",
      value: function updateCell(params) {
        if (!params.hasOwnProperty('index') || !params.hasOwnProperty('field') || !params.hasOwnProperty('value')) {
          return;
        }

        this.data[params.index][params.field] = params.value;

        if (params.reinit === false) {
          return;
        }

        this.initSort();
        this.initBody(true);
      }
    }, {
      key: \"updateCellByUniqueId\",
      value: function updateCellByUniqueId(params) {
        var _this19 = this;

        var allParams = Array.isArray(params) ? params : [params];
        allParams.forEach(function (_ref6) {
          var id = _ref6.id,
              field = _ref6.field,
              value = _ref6.value;

          var rowId = _this19.options.data.indexOf(_this19.getRowByUniqueId(id));

          if (rowId === -1) {
            return;
          }

          _this19.options.data[rowId][field] = value;
        });

        if (params.reinit === false) {
          return;
        }

        this.initSort();
        this.initBody(true);
      }
    }, {
      key: \"showRow\",
      value: function showRow(params) {
        this._toggleRow(params, true);
      }
    }, {
      key: \"hideRow\",
      value: function hideRow(params) {
        this._toggleRow(params, false);
      }
    }, {
      key: \"_toggleRow\",
      value: function _toggleRow(params, visible) {
        var row;

        if (params.hasOwnProperty('index')) {
          row = this.getData()[params.index];
        } else if (params.hasOwnProperty('uniqueId')) {
          row = this.getRowByUniqueId(params.uniqueId);
        }

        if (!row) {
          return;
        }

        var index = Utils.findIndex(this.hiddenRows, row);

        if (!visible && index === -1) {
          this.hiddenRows.push(row);
        } else if (visible && index > -1) {
          this.hiddenRows.splice(index, 1);
        }

        this.initBody(true);
        this.initPagination();
      }
    }, {
      key: \"getHiddenRows\",
      value: function getHiddenRows(show) {
        if (show) {
          this.initHiddenRows();
          this.initBody(true);
          this.initPagination();
          return;
        }

        var data = this.getData();
        var rows = [];

        var _iterator8 = _createForOfIteratorHelper(data),
            _step8;

        try {
          for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
            var row = _step8.value;

            if (this.hiddenRows.includes(row)) {
              rows.push(row);
            }
          }
        } catch (err) {
          _iterator8.e(err);
        } finally {
          _iterator8.f();
        }

        this.hiddenRows = rows;
        return rows;
      }
    }, {
      key: \"showColumn\",
      value: function showColumn(field) {
        var _this20 = this;

        var fields = Array.isArray(field) ? field : [field];
        fields.forEach(function (field) {
          _this20._toggleColumn(_this20.fieldsColumnsIndex[field], true, true);
        });
      }
    }, {
      key: \"hideColumn\",
      value: function hideColumn(field) {
        var _this21 = this;

        var fields = Array.isArray(field) ? field : [field];
        fields.forEach(function (field) {
          _this21._toggleColumn(_this21.fieldsColumnsIndex[field], false, true);
        });
      }
    }, {
      key: \"_toggleColumn\",
      value: function _toggleColumn(index, checked, needUpdate) {
        if (index === -1 || this.columns[index].visible === checked) {
          return;
        }

        this.columns[index].visible = checked;
        this.initHeader();
        this.initSearch();
        this.initPagination();
        this.initBody();

        if (this.options.showColumns) {
          var \$items = this.\$toolbar.find('.keep-open input:not(\".toggle-all\")').prop('disabled', false);

          if (needUpdate) {
            \$items.filter(Utils.sprintf('[value=\"%s\"]', index)).prop('checked', checked);
          }

          if (\$items.filter(':checked').length <= this.options.minimumCountColumns) {
            \$items.filter(':checked').prop('disabled', true);
          }
        }
      }
    }, {
      key: \"getVisibleColumns\",
      value: function getVisibleColumns() {
        var _this22 = this;

        return this.columns.filter(function (column) {
          return column.visible && !_this22.isSelectionColumn(column);
        });
      }
    }, {
      key: \"getHiddenColumns\",
      value: function getHiddenColumns() {
        return this.columns.filter(function (_ref7) {
          var visible = _ref7.visible;
          return !visible;
        });
      }
    }, {
      key: \"isSelectionColumn\",
      value: function isSelectionColumn(column) {
        return column.radio || column.checkbox;
      }
    }, {
      key: \"showAllColumns\",
      value: function showAllColumns() {
        this._toggleAllColumns(true);
      }
    }, {
      key: \"hideAllColumns\",
      value: function hideAllColumns() {
        this._toggleAllColumns(false);
      }
    }, {
      key: \"_toggleAllColumns\",
      value: function _toggleAllColumns(visible) {
        var _this23 = this;

        var _iterator9 = _createForOfIteratorHelper(this.columns.slice().reverse()),
            _step9;

        try {
          for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
            var column = _step9.value;

            if (column.switchable) {
              if (!visible && this.options.showColumns && this.getVisibleColumns().length === this.options.minimumCountColumns) {
                continue;
              }

              column.visible = visible;
            }
          }
        } catch (err) {
          _iterator9.e(err);
        } finally {
          _iterator9.f();
        }

        this.initHeader();
        this.initSearch();
        this.initPagination();
        this.initBody();

        if (this.options.showColumns) {
          var \$items = this.\$toolbar.find('.keep-open input[type=\"checkbox\"]:not(\".toggle-all\")').prop('disabled', false);

          if (visible) {
            \$items.prop('checked', visible);
          } else {
            \$items.get().reverse().forEach(function (item) {
              if (\$items.filter(':checked').length > _this23.options.minimumCountColumns) {
                \$__default['default'](item).prop('checked', visible);
              }
            });
          }

          if (\$items.filter(':checked').length <= this.options.minimumCountColumns) {
            \$items.filter(':checked').prop('disabled', true);
          }
        }
      }
    }, {
      key: \"mergeCells\",
      value: function mergeCells(options) {
        var row = options.index;
        var col = this.getVisibleFields().indexOf(options.field);
        var rowspan = options.rowspan || 1;
        var colspan = options.colspan || 1;
        var i;
        var j;
        var \$tr = this.\$body.find('>tr');
        col += Utils.getDetailViewIndexOffset(this.options);
        var \$td = \$tr.eq(row).find('>td').eq(col);

        if (row < 0 || col < 0 || row >= this.data.length) {
          return;
        }

        for (i = row; i < row + rowspan; i++) {
          for (j = col; j < col + colspan; j++) {
            \$tr.eq(i).find('>td').eq(j).hide();
          }
        }

        \$td.attr('rowspan', rowspan).attr('colspan', colspan).show();
      }
    }, {
      key: \"checkAll\",
      value: function checkAll() {
        this._toggleCheckAll(true);
      }
    }, {
      key: \"uncheckAll\",
      value: function uncheckAll() {
        this._toggleCheckAll(false);
      }
    }, {
      key: \"_toggleCheckAll\",
      value: function _toggleCheckAll(checked) {
        var rowsBefore = this.getSelections();
        this.\$selectAll.add(this.\$selectAll_).prop('checked', checked);
        this.\$selectItem.filter(':enabled').prop('checked', checked);
        this.updateRows();
        this.updateSelected();
        var rowsAfter = this.getSelections();

        if (checked) {
          this.trigger('check-all', rowsAfter, rowsBefore);
          return;
        }

        this.trigger('uncheck-all', rowsAfter, rowsBefore);
      }
    }, {
      key: \"checkInvert\",
      value: function checkInvert() {
        var \$items = this.\$selectItem.filter(':enabled');
        var checked = \$items.filter(':checked');
        \$items.each(function (i, el) {
          \$__default['default'](el).prop('checked', !\$__default['default'](el).prop('checked'));
        });
        this.updateRows();
        this.updateSelected();
        this.trigger('uncheck-some', checked);
        checked = this.getSelections();
        this.trigger('check-some', checked);
      }
    }, {
      key: \"check\",
      value: function check(index) {
        this._toggleCheck(true, index);
      }
    }, {
      key: \"uncheck\",
      value: function uncheck(index) {
        this._toggleCheck(false, index);
      }
    }, {
      key: \"_toggleCheck\",
      value: function _toggleCheck(checked, index) {
        var \$el = this.\$selectItem.filter(\"[data-index=\\\"\".concat(index, \"\\\"]\"));
        var row = this.data[index];

        if (\$el.is(':radio') || this.options.singleSelect || this.options.multipleSelectRow && !this.multipleSelectRowCtrlKey && !this.multipleSelectRowShiftKey) {
          var _iterator10 = _createForOfIteratorHelper(this.options.data),
              _step10;

          try {
            for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) {
              var r = _step10.value;
              r[this.header.stateField] = false;
            }
          } catch (err) {
            _iterator10.e(err);
          } finally {
            _iterator10.f();
          }

          this.\$selectItem.filter(':checked').not(\$el).prop('checked', false);
        }

        row[this.header.stateField] = checked;

        if (this.options.multipleSelectRow) {
          if (this.multipleSelectRowShiftKey && this.multipleSelectRowLastSelectedIndex >= 0) {
            var _ref8 = this.multipleSelectRowLastSelectedIndex < index ? [this.multipleSelectRowLastSelectedIndex, index] : [index, this.multipleSelectRowLastSelectedIndex],
                _ref9 = _slicedToArray(_ref8, 2),
                fromIndex = _ref9[0],
                toIndex = _ref9[1];

            for (var i = fromIndex + 1; i < toIndex; i++) {
              this.data[i][this.header.stateField] = true;
              this.\$selectItem.filter(\"[data-index=\\\"\".concat(i, \"\\\"]\")).prop('checked', true);
            }
          }

          this.multipleSelectRowCtrlKey = false;
          this.multipleSelectRowShiftKey = false;
          this.multipleSelectRowLastSelectedIndex = checked ? index : -1;
        }

        \$el.prop('checked', checked);
        this.updateSelected();
        this.trigger(checked ? 'check' : 'uncheck', this.data[index], \$el);
      }
    }, {
      key: \"checkBy\",
      value: function checkBy(obj) {
        this._toggleCheckBy(true, obj);
      }
    }, {
      key: \"uncheckBy\",
      value: function uncheckBy(obj) {
        this._toggleCheckBy(false, obj);
      }
    }, {
      key: \"_toggleCheckBy\",
      value: function _toggleCheckBy(checked, obj) {
        var _this24 = this;

        if (!obj.hasOwnProperty('field') || !obj.hasOwnProperty('values')) {
          return;
        }

        var rows = [];
        this.data.forEach(function (row, i) {
          if (!row.hasOwnProperty(obj.field)) {
            return false;
          }

          if (obj.values.includes(row[obj.field])) {
            var \$el = _this24.\$selectItem.filter(':enabled').filter(Utils.sprintf('[data-index=\"%s\"]', i));

            \$el = checked ? \$el.not(':checked') : \$el.filter(':checked');

            if (!\$el.length) {
              return;
            }

            \$el.prop('checked', checked);
            row[_this24.header.stateField] = checked;
            rows.push(row);

            _this24.trigger(checked ? 'check' : 'uncheck', row, \$el);
          }
        });
        this.updateSelected();
        this.trigger(checked ? 'check-some' : 'uncheck-some', rows);
      }
    }, {
      key: \"refresh\",
      value: function refresh(params) {
        if (params && params.url) {
          this.options.url = params.url;
        }

        if (params && params.pageNumber) {
          this.options.pageNumber = params.pageNumber;
        }

        if (params && params.pageSize) {
          this.options.pageSize = params.pageSize;
        }

        this.trigger('refresh', this.initServer(params && params.silent, params && params.query, params && params.url));
      }
    }, {
      key: \"destroy\",
      value: function destroy() {
        this.\$el.insertBefore(this.\$container);
        \$__default['default'](this.options.toolbar).insertBefore(this.\$el);
        this.\$container.next().remove();
        this.\$container.remove();
        this.\$el.html(this.\$el_.html()).css('margin-top', '0').attr('class', this.\$el_.attr('class') || ''); // reset the class
      }
    }, {
      key: \"resetView\",
      value: function resetView(params) {
        var padding = 0;

        if (params && params.height) {
          this.options.height = params.height;
        }

        this.\$selectAll.prop('checked', this.\$selectItem.length > 0 && this.\$selectItem.length === this.\$selectItem.filter(':checked').length);
        this.\$tableContainer.toggleClass('has-card-view', this.options.cardView);

        if (!this.options.cardView && this.options.showHeader && this.options.height) {
          this.\$tableHeader.show();
          this.resetHeader();
          padding += this.\$header.outerHeight(true) + 1;
        } else {
          this.\$tableHeader.hide();
          this.trigger('post-header');
        }

        if (!this.options.cardView && this.options.showFooter) {
          this.\$tableFooter.show();
          this.fitFooter();

          if (this.options.height) {
            padding += this.\$tableFooter.outerHeight(true);
          }
        }

        if (this.\$container.hasClass('fullscreen')) {
          this.\$tableContainer.css('height', '');
          this.\$tableContainer.css('width', '');
        } else if (this.options.height) {
          if (this.\$tableBorder) {
            this.\$tableBorder.css('width', '');
            this.\$tableBorder.css('height', '');
          }

          var toolbarHeight = this.\$toolbar.outerHeight(true);
          var paginationHeight = this.\$pagination.outerHeight(true);
          var height = this.options.height - toolbarHeight - paginationHeight;
          var \$bodyTable = this.\$tableBody.find('>table');
          var tableHeight = \$bodyTable.outerHeight();
          this.\$tableContainer.css('height', \"\".concat(height, \"px\"));

          if (this.\$tableBorder && \$bodyTable.is(':visible')) {
            var tableBorderHeight = height - tableHeight - 2;

            if (this.\$tableBody[0].scrollWidth - this.\$tableBody.innerWidth()) {
              tableBorderHeight -= Utils.getScrollBarWidth();
            }

            this.\$tableBorder.css('width', \"\".concat(\$bodyTable.outerWidth(), \"px\"));
            this.\$tableBorder.css('height', \"\".concat(tableBorderHeight, \"px\"));
          }
        }

        if (this.options.cardView) {
          // remove the element css
          this.\$el.css('margin-top', '0');
          this.\$tableContainer.css('padding-bottom', '0');
          this.\$tableFooter.hide();
        } else {
          // Assign the correct sortable arrow
          this.getCaret();
          this.\$tableContainer.css('padding-bottom', \"\".concat(padding, \"px\"));
        }

        this.trigger('reset-view');
      }
    }, {
      key: \"showLoading\",
      value: function showLoading() {
        this.\$tableLoading.toggleClass('open', true);
        var fontSize = this.options.loadingFontSize;

        if (this.options.loadingFontSize === 'auto') {
          fontSize = this.\$tableLoading.width() * 0.04;
          fontSize = Math.max(12, fontSize);
          fontSize = Math.min(32, fontSize);
          fontSize = \"\".concat(fontSize, \"px\");
        }

        this.\$tableLoading.find('.loading-text').css('font-size', fontSize);
      }
    }, {
      key: \"hideLoading\",
      value: function hideLoading() {
        this.\$tableLoading.toggleClass('open', false);
      }
    }, {
      key: \"togglePagination\",
      value: function togglePagination() {
        this.options.pagination = !this.options.pagination;
        var icon = this.options.showButtonIcons ? this.options.pagination ? this.options.icons.paginationSwitchDown : this.options.icons.paginationSwitchUp : '';
        var text = this.options.showButtonText ? this.options.pagination ? this.options.formatPaginationSwitchUp() : this.options.formatPaginationSwitchDown() : '';
        this.\$toolbar.find('button[name=\"paginationSwitch\"]').html(\"\".concat(Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, icon), \" \").concat(text));
        this.updatePagination();
      }
    }, {
      key: \"toggleFullscreen\",
      value: function toggleFullscreen() {
        this.\$el.closest('.bootstrap-table').toggleClass('fullscreen');
        this.resetView();
      }
    }, {
      key: \"toggleView\",
      value: function toggleView() {
        this.options.cardView = !this.options.cardView;
        this.initHeader();
        var icon = this.options.showButtonIcons ? this.options.cardView ? this.options.icons.toggleOn : this.options.icons.toggleOff : '';
        var text = this.options.showButtonText ? this.options.cardView ? this.options.formatToggleOff() : this.options.formatToggleOn() : '';
        this.\$toolbar.find('button[name=\"toggle\"]').html(\"\".concat(Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, icon), \" \").concat(text));
        this.initBody();
        this.trigger('toggle', this.options.cardView);
      }
    }, {
      key: \"resetSearch\",
      value: function resetSearch(text) {
        var \$search = Utils.getSearchInput(this);
        \$search.val(text || '');
        this.onSearch({
          currentTarget: \$search
        });
      }
    }, {
      key: \"filterBy\",
      value: function filterBy(columns, options) {
        this.filterOptions = Utils.isEmptyObject(options) ? this.options.filterOptions : \$__default['default'].extend(this.options.filterOptions, options);
        this.filterColumns = Utils.isEmptyObject(columns) ? {} : columns;
        this.options.pageNumber = 1;
        this.initSearch();
        this.updatePagination();
      }
    }, {
      key: \"scrollTo\",
      value: function scrollTo(params) {
        var options = {
          unit: 'px',
          value: 0
        };

        if (_typeof(params) === 'object') {
          options = Object.assign(options, params);
        } else if (typeof params === 'string' && params === 'bottom') {
          options.value = this.\$tableBody[0].scrollHeight;
        } else if (typeof params === 'string' || typeof params === 'number') {
          options.value = params;
        }

        var scrollTo = options.value;

        if (options.unit === 'rows') {
          scrollTo = 0;
          this.\$body.find(\"> tr:lt(\".concat(options.value, \")\")).each(function (i, el) {
            scrollTo += \$__default['default'](el).outerHeight(true);
          });
        }

        this.\$tableBody.scrollTop(scrollTo);
      }
    }, {
      key: \"getScrollPosition\",
      value: function getScrollPosition() {
        return this.\$tableBody.scrollTop();
      }
    }, {
      key: \"selectPage\",
      value: function selectPage(page) {
        if (page > 0 && page <= this.options.totalPages) {
          this.options.pageNumber = page;
          this.updatePagination();
        }
      }
    }, {
      key: \"prevPage\",
      value: function prevPage() {
        if (this.options.pageNumber > 1) {
          this.options.pageNumber--;
          this.updatePagination();
        }
      }
    }, {
      key: \"nextPage\",
      value: function nextPage() {
        if (this.options.pageNumber < this.options.totalPages) {
          this.options.pageNumber++;
          this.updatePagination();
        }
      }
    }, {
      key: \"toggleDetailView\",
      value: function toggleDetailView(index, _columnDetailFormatter) {
        var \$tr = this.\$body.find(Utils.sprintf('> tr[data-index=\"%s\"]', index));

        if (\$tr.next().is('tr.detail-view')) {
          this.collapseRow(index);
        } else {
          this.expandRow(index, _columnDetailFormatter);
        }

        this.resetView();
      }
    }, {
      key: \"expandRow\",
      value: function expandRow(index, _columnDetailFormatter) {
        var row = this.data[index];
        var \$tr = this.\$body.find(Utils.sprintf('> tr[data-index=\"%s\"][data-has-detail-view]', index));

        if (\$tr.next().is('tr.detail-view')) {
          return;
        }

        if (this.options.detailViewIcon) {
          \$tr.find('a.detail-icon').html(Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, this.options.icons.detailClose));
        }

        \$tr.after(Utils.sprintf('<tr class=\"detail-view\"><td colspan=\"%s\"></td></tr>', \$tr.children('td').length));
        var \$element = \$tr.next().find('td');
        var detailFormatter = _columnDetailFormatter || this.options.detailFormatter;
        var content = Utils.calculateObjectValue(this.options, detailFormatter, [index, row, \$element], '');

        if (\$element.length === 1) {
          \$element.append(content);
        }

        this.trigger('expand-row', index, row, \$element);
      }
    }, {
      key: \"expandRowByUniqueId\",
      value: function expandRowByUniqueId(uniqueId) {
        var row = this.getRowByUniqueId(uniqueId);

        if (!row) {
          return;
        }

        this.expandRow(this.data.indexOf(row));
      }
    }, {
      key: \"collapseRow\",
      value: function collapseRow(index) {
        var row = this.data[index];
        var \$tr = this.\$body.find(Utils.sprintf('> tr[data-index=\"%s\"][data-has-detail-view]', index));

        if (!\$tr.next().is('tr.detail-view')) {
          return;
        }

        if (this.options.detailViewIcon) {
          \$tr.find('a.detail-icon').html(Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, this.options.icons.detailOpen));
        }

        this.trigger('collapse-row', index, row, \$tr.next());
        \$tr.next().remove();
      }
    }, {
      key: \"collapseRowByUniqueId\",
      value: function collapseRowByUniqueId(uniqueId) {
        var row = this.getRowByUniqueId(uniqueId);

        if (!row) {
          return;
        }

        this.collapseRow(this.data.indexOf(row));
      }
    }, {
      key: \"expandAllRows\",
      value: function expandAllRows() {
        var trs = this.\$body.find('> tr[data-index][data-has-detail-view]');

        for (var i = 0; i < trs.length; i++) {
          this.expandRow(\$__default['default'](trs[i]).data('index'));
        }
      }
    }, {
      key: \"collapseAllRows\",
      value: function collapseAllRows() {
        var trs = this.\$body.find('> tr[data-index][data-has-detail-view]');

        for (var i = 0; i < trs.length; i++) {
          this.collapseRow(\$__default['default'](trs[i]).data('index'));
        }
      }
    }, {
      key: \"updateColumnTitle\",
      value: function updateColumnTitle(params) {
        if (!params.hasOwnProperty('field') || !params.hasOwnProperty('title')) {
          return;
        }

        this.columns[this.fieldsColumnsIndex[params.field]].title = this.options.escape ? Utils.escapeHTML(params.title) : params.title;

        if (this.columns[this.fieldsColumnsIndex[params.field]].visible) {
          this.\$header.find('th[data-field]').each(function (i, el) {
            if (\$__default['default'](el).data('field') === params.field) {
              \$__default['default'](\$__default['default'](el).find('.th-inner')[0]).text(params.title);
              return false;
            }
          });
          this.resetView();
        }
      }
    }, {
      key: \"updateFormatText\",
      value: function updateFormatText(formatName, text) {
        if (!/^format/.test(formatName) || !this.options[formatName]) {
          return;
        }

        if (typeof text === 'string') {
          this.options[formatName] = function () {
            return text;
          };
        } else if (typeof text === 'function') {
          this.options[formatName] = text;
        }

        this.initToolbar();
        this.initPagination();
        this.initBody();
      }
    }]);

    return BootstrapTable;
  }();

  BootstrapTable.VERSION = Constants.VERSION;
  BootstrapTable.DEFAULTS = Constants.DEFAULTS;
  BootstrapTable.LOCALES = Constants.LOCALES;
  BootstrapTable.COLUMN_DEFAULTS = Constants.COLUMN_DEFAULTS;
  BootstrapTable.METHODS = Constants.METHODS;
  BootstrapTable.EVENTS = Constants.EVENTS; // BOOTSTRAP TABLE PLUGIN DEFINITION
  // =======================

  \$__default['default'].BootstrapTable = BootstrapTable;

  \$__default['default'].fn.bootstrapTable = function (option) {
    for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key5 = 1; _key5 < _len2; _key5++) {
      args[_key5 - 1] = arguments[_key5];
    }

    var value;
    this.each(function (i, el) {
      var data = \$__default['default'](el).data('bootstrap.table');
      var options = \$__default['default'].extend({}, BootstrapTable.DEFAULTS, \$__default['default'](el).data(), _typeof(option) === 'object' && option);

      if (typeof option === 'string') {
        var _data2;

        if (!Constants.METHODS.includes(option)) {
          throw new Error(\"Unknown method: \".concat(option));
        }

        if (!data) {
          return;
        }

        value = (_data2 = data)[option].apply(_data2, args);

        if (option === 'destroy') {
          \$__default['default'](el).removeData('bootstrap.table');
        }
      }

      if (!data) {
        data = new \$__default['default'].BootstrapTable(el, options);
        \$__default['default'](el).data('bootstrap.table', data);
        data.init();
      }
    });
    return typeof value === 'undefined' ? this : value;
  };

  \$__default['default'].fn.bootstrapTable.Constructor = BootstrapTable;
  \$__default['default'].fn.bootstrapTable.theme = Constants.THEME;
  \$__default['default'].fn.bootstrapTable.VERSION = Constants.VERSION;
  \$__default['default'].fn.bootstrapTable.defaults = BootstrapTable.DEFAULTS;
  \$__default['default'].fn.bootstrapTable.columnDefaults = BootstrapTable.COLUMN_DEFAULTS;
  \$__default['default'].fn.bootstrapTable.events = BootstrapTable.EVENTS;
  \$__default['default'].fn.bootstrapTable.locales = BootstrapTable.LOCALES;
  \$__default['default'].fn.bootstrapTable.methods = BootstrapTable.METHODS;
  \$__default['default'].fn.bootstrapTable.utils = Utils; // BOOTSTRAP TABLE INIT
  // =======================

  \$__default['default'](function () {
    \$__default['default']('[data-toggle=\"table\"]').bootstrapTable();
  });

  return BootstrapTable;

})));


/***/ }),

/***/ \"./node_modules/core-js/internals/array-fill.js\":
/*!******************************************************!*\\
  !*** ./node_modules/core-js/internals/array-fill.js ***!
  \\******************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var toObject = __webpack_require__(/*! ../internals/to-object */ \"./node_modules/core-js/internals/to-object.js\");
var toAbsoluteIndex = __webpack_require__(/*! ../internals/to-absolute-index */ \"./node_modules/core-js/internals/to-absolute-index.js\");
var toLength = __webpack_require__(/*! ../internals/to-length */ \"./node_modules/core-js/internals/to-length.js\");

// `Array.prototype.fill` method implementation
// https://tc39.es/ecma262/#sec-array.prototype.fill
module.exports = function fill(value /* , start = 0, end = @length */) {
  var O = toObject(this);
  var length = toLength(O.length);
  var argumentsLength = arguments.length;
  var index = toAbsoluteIndex(argumentsLength > 1 ? arguments[1] : undefined, length);
  var end = argumentsLength > 2 ? arguments[2] : undefined;
  var endPos = end === undefined ? length : toAbsoluteIndex(end, length);
  while (endPos > index) O[index++] = value;
  return O;
};


/***/ }),

/***/ \"./node_modules/core-js/internals/array-reduce.js\":
/*!********************************************************!*\\
  !*** ./node_modules/core-js/internals/array-reduce.js ***!
  \\********************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

var aFunction = __webpack_require__(/*! ../internals/a-function */ \"./node_modules/core-js/internals/a-function.js\");
var toObject = __webpack_require__(/*! ../internals/to-object */ \"./node_modules/core-js/internals/to-object.js\");
var IndexedObject = __webpack_require__(/*! ../internals/indexed-object */ \"./node_modules/core-js/internals/indexed-object.js\");
var toLength = __webpack_require__(/*! ../internals/to-length */ \"./node_modules/core-js/internals/to-length.js\");

// `Array.prototype.{ reduce, reduceRight }` methods implementation
var createMethod = function (IS_RIGHT) {
  return function (that, callbackfn, argumentsLength, memo) {
    aFunction(callbackfn);
    var O = toObject(that);
    var self = IndexedObject(O);
    var length = toLength(O.length);
    var index = IS_RIGHT ? length - 1 : 0;
    var i = IS_RIGHT ? -1 : 1;
    if (argumentsLength < 2) while (true) {
      if (index in self) {
        memo = self[index];
        index += i;
        break;
      }
      index += i;
      if (IS_RIGHT ? index < 0 : length <= index) {
        throw TypeError('Reduce of empty array with no initial value');
      }
    }
    for (;IS_RIGHT ? index >= 0 : length > index; index += i) if (index in self) {
      memo = callbackfn(memo, self[index], index, O);
    }
    return memo;
  };
};

module.exports = {
  // `Array.prototype.reduce` method
  // https://tc39.es/ecma262/#sec-array.prototype.reduce
  left: createMethod(false),
  // `Array.prototype.reduceRight` method
  // https://tc39.es/ecma262/#sec-array.prototype.reduceright
  right: createMethod(true)
};


/***/ }),

/***/ \"./node_modules/core-js/internals/engine-is-node.js\":
/*!**********************************************************!*\\
  !*** ./node_modules/core-js/internals/engine-is-node.js ***!
  \\**********************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

var classof = __webpack_require__(/*! ../internals/classof-raw */ \"./node_modules/core-js/internals/classof-raw.js\");
var global = __webpack_require__(/*! ../internals/global */ \"./node_modules/core-js/internals/global.js\");

module.exports = classof(global.process) == 'process';


/***/ }),

/***/ \"./node_modules/core-js/internals/inherit-if-required.js\":
/*!***************************************************************!*\\
  !*** ./node_modules/core-js/internals/inherit-if-required.js ***!
  \\***************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

var isObject = __webpack_require__(/*! ../internals/is-object */ \"./node_modules/core-js/internals/is-object.js\");
var setPrototypeOf = __webpack_require__(/*! ../internals/object-set-prototype-of */ \"./node_modules/core-js/internals/object-set-prototype-of.js\");

// makes subclassing work correct for wrapped built-ins
module.exports = function (\$this, dummy, Wrapper) {
  var NewTarget, NewTargetPrototype;
  if (
    // it can work only with native `setPrototypeOf`
    setPrototypeOf &&
    // we haven't completely correct pre-ES6 way for getting `new.target`, so use this
    typeof (NewTarget = dummy.constructor) == 'function' &&
    NewTarget !== Wrapper &&
    isObject(NewTargetPrototype = NewTarget.prototype) &&
    NewTargetPrototype !== Wrapper.prototype
  ) setPrototypeOf(\$this, NewTargetPrototype);
  return \$this;
};


/***/ }),

/***/ \"./node_modules/core-js/internals/number-parse-float.js\":
/*!**************************************************************!*\\
  !*** ./node_modules/core-js/internals/number-parse-float.js ***!
  \\**************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

var global = __webpack_require__(/*! ../internals/global */ \"./node_modules/core-js/internals/global.js\");
var trim = __webpack_require__(/*! ../internals/string-trim */ \"./node_modules/core-js/internals/string-trim.js\").trim;
var whitespaces = __webpack_require__(/*! ../internals/whitespaces */ \"./node_modules/core-js/internals/whitespaces.js\");

var \$parseFloat = global.parseFloat;
var FORCED = 1 / \$parseFloat(whitespaces + '-0') !== -Infinity;

// `parseFloat` method
// https://tc39.es/ecma262/#sec-parsefloat-string
module.exports = FORCED ? function parseFloat(string) {
  var trimmedString = trim(String(string));
  var result = \$parseFloat(trimmedString);
  return result === 0 && trimmedString.charAt(0) == '-' ? -0 : result;
} : \$parseFloat;


/***/ }),

/***/ \"./node_modules/core-js/internals/same-value.js\":
/*!******************************************************!*\\
  !*** ./node_modules/core-js/internals/same-value.js ***!
  \\******************************************************/
/***/ ((module) => {

// `SameValue` abstract operation
// https://tc39.es/ecma262/#sec-samevalue
// eslint-disable-next-line es/no-object-is -- safe
module.exports = Object.is || function is(x, y) {
  // eslint-disable-next-line no-self-compare -- NaN check
  return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y;
};


/***/ }),

/***/ \"./node_modules/core-js/internals/set-species.js\":
/*!*******************************************************!*\\
  !*** ./node_modules/core-js/internals/set-species.js ***!
  \\*******************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var getBuiltIn = __webpack_require__(/*! ../internals/get-built-in */ \"./node_modules/core-js/internals/get-built-in.js\");
var definePropertyModule = __webpack_require__(/*! ../internals/object-define-property */ \"./node_modules/core-js/internals/object-define-property.js\");
var wellKnownSymbol = __webpack_require__(/*! ../internals/well-known-symbol */ \"./node_modules/core-js/internals/well-known-symbol.js\");
var DESCRIPTORS = __webpack_require__(/*! ../internals/descriptors */ \"./node_modules/core-js/internals/descriptors.js\");

var SPECIES = wellKnownSymbol('species');

module.exports = function (CONSTRUCTOR_NAME) {
  var Constructor = getBuiltIn(CONSTRUCTOR_NAME);
  var defineProperty = definePropertyModule.f;

  if (DESCRIPTORS && Constructor && !Constructor[SPECIES]) {
    defineProperty(Constructor, SPECIES, {
      configurable: true,
      get: function () { return this; }
    });
  }
};


/***/ }),

/***/ \"./node_modules/core-js/internals/string-repeat.js\":
/*!*********************************************************!*\\
  !*** ./node_modules/core-js/internals/string-repeat.js ***!
  \\*********************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var toInteger = __webpack_require__(/*! ../internals/to-integer */ \"./node_modules/core-js/internals/to-integer.js\");
var requireObjectCoercible = __webpack_require__(/*! ../internals/require-object-coercible */ \"./node_modules/core-js/internals/require-object-coercible.js\");

// `String.prototype.repeat` method implementation
// https://tc39.es/ecma262/#sec-string.prototype.repeat
module.exports = function repeat(count) {
  var str = String(requireObjectCoercible(this));
  var result = '';
  var n = toInteger(count);
  if (n < 0 || n == Infinity) throw RangeError('Wrong number of repetitions');
  for (;n > 0; (n >>>= 1) && (str += str)) if (n & 1) result += str;
  return result;
};


/***/ }),

/***/ \"./node_modules/core-js/internals/this-number-value.js\":
/*!*************************************************************!*\\
  !*** ./node_modules/core-js/internals/this-number-value.js ***!
  \\*************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

var classof = __webpack_require__(/*! ../internals/classof-raw */ \"./node_modules/core-js/internals/classof-raw.js\");

// `thisNumberValue` abstract operation
// https://tc39.es/ecma262/#sec-thisnumbervalue
module.exports = function (value) {
  if (typeof value != 'number' && classof(value) != 'Number') {
    throw TypeError('Incorrect invocation');
  }
  return +value;
};


/***/ }),

/***/ \"./node_modules/core-js/modules/es.array.fill.js\":
/*!*******************************************************!*\\
  !*** ./node_modules/core-js/modules/es.array.fill.js ***!
  \\*******************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var fill = __webpack_require__(/*! ../internals/array-fill */ \"./node_modules/core-js/internals/array-fill.js\");
var addToUnscopables = __webpack_require__(/*! ../internals/add-to-unscopables */ \"./node_modules/core-js/internals/add-to-unscopables.js\");

// `Array.prototype.fill` method
// https://tc39.es/ecma262/#sec-array.prototype.fill
\$({ target: 'Array', proto: true }, {
  fill: fill
});

// https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
addToUnscopables('fill');


/***/ }),

/***/ \"./node_modules/core-js/modules/es.array.find.js\":
/*!*******************************************************!*\\
  !*** ./node_modules/core-js/modules/es.array.find.js ***!
  \\*******************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var \$find = __webpack_require__(/*! ../internals/array-iteration */ \"./node_modules/core-js/internals/array-iteration.js\").find;
var addToUnscopables = __webpack_require__(/*! ../internals/add-to-unscopables */ \"./node_modules/core-js/internals/add-to-unscopables.js\");

var FIND = 'find';
var SKIPS_HOLES = true;

// Shouldn't skip holes
if (FIND in []) Array(1)[FIND](function () { SKIPS_HOLES = false; });

// `Array.prototype.find` method
// https://tc39.es/ecma262/#sec-array.prototype.find
\$({ target: 'Array', proto: true, forced: SKIPS_HOLES }, {
  find: function find(callbackfn /* , that = undefined */) {
    return \$find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
  }
});

// https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
addToUnscopables(FIND);


/***/ }),

/***/ \"./node_modules/core-js/modules/es.array.includes.js\":
/*!***********************************************************!*\\
  !*** ./node_modules/core-js/modules/es.array.includes.js ***!
  \\***********************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var \$includes = __webpack_require__(/*! ../internals/array-includes */ \"./node_modules/core-js/internals/array-includes.js\").includes;
var addToUnscopables = __webpack_require__(/*! ../internals/add-to-unscopables */ \"./node_modules/core-js/internals/add-to-unscopables.js\");

// `Array.prototype.includes` method
// https://tc39.es/ecma262/#sec-array.prototype.includes
\$({ target: 'Array', proto: true }, {
  includes: function includes(el /* , fromIndex = 0 */) {
    return \$includes(this, el, arguments.length > 1 ? arguments[1] : undefined);
  }
});

// https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
addToUnscopables('includes');


/***/ }),

/***/ \"./node_modules/core-js/modules/es.array.index-of.js\":
/*!***********************************************************!*\\
  !*** ./node_modules/core-js/modules/es.array.index-of.js ***!
  \\***********************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

/* eslint-disable es/no-array-prototype-indexof -- required for testing */
var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var \$indexOf = __webpack_require__(/*! ../internals/array-includes */ \"./node_modules/core-js/internals/array-includes.js\").indexOf;
var arrayMethodIsStrict = __webpack_require__(/*! ../internals/array-method-is-strict */ \"./node_modules/core-js/internals/array-method-is-strict.js\");

var nativeIndexOf = [].indexOf;

var NEGATIVE_ZERO = !!nativeIndexOf && 1 / [1].indexOf(1, -0) < 0;
var STRICT_METHOD = arrayMethodIsStrict('indexOf');

// `Array.prototype.indexOf` method
// https://tc39.es/ecma262/#sec-array.prototype.indexof
\$({ target: 'Array', proto: true, forced: NEGATIVE_ZERO || !STRICT_METHOD }, {
  indexOf: function indexOf(searchElement /* , fromIndex = 0 */) {
    return NEGATIVE_ZERO
      // convert -0 to +0
      ? nativeIndexOf.apply(this, arguments) || 0
      : \$indexOf(this, searchElement, arguments.length > 1 ? arguments[1] : undefined);
  }
});


/***/ }),

/***/ \"./node_modules/core-js/modules/es.array.is-array.js\":
/*!***********************************************************!*\\
  !*** ./node_modules/core-js/modules/es.array.is-array.js ***!
  \\***********************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var isArray = __webpack_require__(/*! ../internals/is-array */ \"./node_modules/core-js/internals/is-array.js\");

// `Array.isArray` method
// https://tc39.es/ecma262/#sec-array.isarray
\$({ target: 'Array', stat: true }, {
  isArray: isArray
});


/***/ }),

/***/ \"./node_modules/core-js/modules/es.array.reduce.js\":
/*!*********************************************************!*\\
  !*** ./node_modules/core-js/modules/es.array.reduce.js ***!
  \\*********************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var \$reduce = __webpack_require__(/*! ../internals/array-reduce */ \"./node_modules/core-js/internals/array-reduce.js\").left;
var arrayMethodIsStrict = __webpack_require__(/*! ../internals/array-method-is-strict */ \"./node_modules/core-js/internals/array-method-is-strict.js\");
var CHROME_VERSION = __webpack_require__(/*! ../internals/engine-v8-version */ \"./node_modules/core-js/internals/engine-v8-version.js\");
var IS_NODE = __webpack_require__(/*! ../internals/engine-is-node */ \"./node_modules/core-js/internals/engine-is-node.js\");

var STRICT_METHOD = arrayMethodIsStrict('reduce');
// Chrome 80-82 has a critical bug
// https://bugs.chromium.org/p/chromium/issues/detail?id=1049982
var CHROME_BUG = !IS_NODE && CHROME_VERSION > 79 && CHROME_VERSION < 83;

// `Array.prototype.reduce` method
// https://tc39.es/ecma262/#sec-array.prototype.reduce
\$({ target: 'Array', proto: true, forced: !STRICT_METHOD || CHROME_BUG }, {
  reduce: function reduce(callbackfn /* , initialValue */) {
    return \$reduce(this, callbackfn, arguments.length, arguments.length > 1 ? arguments[1] : undefined);
  }
});


/***/ }),

/***/ \"./node_modules/core-js/modules/es.array.some.js\":
/*!*******************************************************!*\\
  !*** ./node_modules/core-js/modules/es.array.some.js ***!
  \\*******************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var \$some = __webpack_require__(/*! ../internals/array-iteration */ \"./node_modules/core-js/internals/array-iteration.js\").some;
var arrayMethodIsStrict = __webpack_require__(/*! ../internals/array-method-is-strict */ \"./node_modules/core-js/internals/array-method-is-strict.js\");

var STRICT_METHOD = arrayMethodIsStrict('some');

// `Array.prototype.some` method
// https://tc39.es/ecma262/#sec-array.prototype.some
\$({ target: 'Array', proto: true, forced: !STRICT_METHOD }, {
  some: function some(callbackfn /* , thisArg */) {
    return \$some(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
  }
});


/***/ }),

/***/ \"./node_modules/core-js/modules/es.array.splice.js\":
/*!*********************************************************!*\\
  !*** ./node_modules/core-js/modules/es.array.splice.js ***!
  \\*********************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var toAbsoluteIndex = __webpack_require__(/*! ../internals/to-absolute-index */ \"./node_modules/core-js/internals/to-absolute-index.js\");
var toInteger = __webpack_require__(/*! ../internals/to-integer */ \"./node_modules/core-js/internals/to-integer.js\");
var toLength = __webpack_require__(/*! ../internals/to-length */ \"./node_modules/core-js/internals/to-length.js\");
var toObject = __webpack_require__(/*! ../internals/to-object */ \"./node_modules/core-js/internals/to-object.js\");
var arraySpeciesCreate = __webpack_require__(/*! ../internals/array-species-create */ \"./node_modules/core-js/internals/array-species-create.js\");
var createProperty = __webpack_require__(/*! ../internals/create-property */ \"./node_modules/core-js/internals/create-property.js\");
var arrayMethodHasSpeciesSupport = __webpack_require__(/*! ../internals/array-method-has-species-support */ \"./node_modules/core-js/internals/array-method-has-species-support.js\");

var HAS_SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('splice');

var max = Math.max;
var min = Math.min;
var MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF;
var MAXIMUM_ALLOWED_LENGTH_EXCEEDED = 'Maximum allowed length exceeded';

// `Array.prototype.splice` method
// https://tc39.es/ecma262/#sec-array.prototype.splice
// with adding support of @@species
\$({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT }, {
  splice: function splice(start, deleteCount /* , ...items */) {
    var O = toObject(this);
    var len = toLength(O.length);
    var actualStart = toAbsoluteIndex(start, len);
    var argumentsLength = arguments.length;
    var insertCount, actualDeleteCount, A, k, from, to;
    if (argumentsLength === 0) {
      insertCount = actualDeleteCount = 0;
    } else if (argumentsLength === 1) {
      insertCount = 0;
      actualDeleteCount = len - actualStart;
    } else {
      insertCount = argumentsLength - 2;
      actualDeleteCount = min(max(toInteger(deleteCount), 0), len - actualStart);
    }
    if (len + insertCount - actualDeleteCount > MAX_SAFE_INTEGER) {
      throw TypeError(MAXIMUM_ALLOWED_LENGTH_EXCEEDED);
    }
    A = arraySpeciesCreate(O, actualDeleteCount);
    for (k = 0; k < actualDeleteCount; k++) {
      from = actualStart + k;
      if (from in O) createProperty(A, k, O[from]);
    }
    A.length = actualDeleteCount;
    if (insertCount < actualDeleteCount) {
      for (k = actualStart; k < len - actualDeleteCount; k++) {
        from = k + actualDeleteCount;
        to = k + insertCount;
        if (from in O) O[to] = O[from];
        else delete O[to];
      }
      for (k = len; k > len - actualDeleteCount + insertCount; k--) delete O[k - 1];
    } else if (insertCount > actualDeleteCount) {
      for (k = len - actualDeleteCount; k > actualStart; k--) {
        from = k + actualDeleteCount - 1;
        to = k + insertCount - 1;
        if (from in O) O[to] = O[from];
        else delete O[to];
      }
    }
    for (k = 0; k < insertCount; k++) {
      O[k + actualStart] = arguments[k + 2];
    }
    O.length = len - actualDeleteCount + insertCount;
    return A;
  }
});


/***/ }),

/***/ \"./node_modules/core-js/modules/es.function.bind.js\":
/*!**********************************************************!*\\
  !*** ./node_modules/core-js/modules/es.function.bind.js ***!
  \\**********************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var bind = __webpack_require__(/*! ../internals/function-bind */ \"./node_modules/core-js/internals/function-bind.js\");

// `Function.prototype.bind` method
// https://tc39.es/ecma262/#sec-function.prototype.bind
\$({ target: 'Function', proto: true }, {
  bind: bind
});


/***/ }),

/***/ \"./node_modules/core-js/modules/es.number.constructor.js\":
/*!***************************************************************!*\\
  !*** ./node_modules/core-js/modules/es.number.constructor.js ***!
  \\***************************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var DESCRIPTORS = __webpack_require__(/*! ../internals/descriptors */ \"./node_modules/core-js/internals/descriptors.js\");
var global = __webpack_require__(/*! ../internals/global */ \"./node_modules/core-js/internals/global.js\");
var isForced = __webpack_require__(/*! ../internals/is-forced */ \"./node_modules/core-js/internals/is-forced.js\");
var redefine = __webpack_require__(/*! ../internals/redefine */ \"./node_modules/core-js/internals/redefine.js\");
var has = __webpack_require__(/*! ../internals/has */ \"./node_modules/core-js/internals/has.js\");
var classof = __webpack_require__(/*! ../internals/classof-raw */ \"./node_modules/core-js/internals/classof-raw.js\");
var inheritIfRequired = __webpack_require__(/*! ../internals/inherit-if-required */ \"./node_modules/core-js/internals/inherit-if-required.js\");
var toPrimitive = __webpack_require__(/*! ../internals/to-primitive */ \"./node_modules/core-js/internals/to-primitive.js\");
var fails = __webpack_require__(/*! ../internals/fails */ \"./node_modules/core-js/internals/fails.js\");
var create = __webpack_require__(/*! ../internals/object-create */ \"./node_modules/core-js/internals/object-create.js\");
var getOwnPropertyNames = __webpack_require__(/*! ../internals/object-get-own-property-names */ \"./node_modules/core-js/internals/object-get-own-property-names.js\").f;
var getOwnPropertyDescriptor = __webpack_require__(/*! ../internals/object-get-own-property-descriptor */ \"./node_modules/core-js/internals/object-get-own-property-descriptor.js\").f;
var defineProperty = __webpack_require__(/*! ../internals/object-define-property */ \"./node_modules/core-js/internals/object-define-property.js\").f;
var trim = __webpack_require__(/*! ../internals/string-trim */ \"./node_modules/core-js/internals/string-trim.js\").trim;

var NUMBER = 'Number';
var NativeNumber = global[NUMBER];
var NumberPrototype = NativeNumber.prototype;

// Opera ~12 has broken Object#toString
var BROKEN_CLASSOF = classof(create(NumberPrototype)) == NUMBER;

// `ToNumber` abstract operation
// https://tc39.es/ecma262/#sec-tonumber
var toNumber = function (argument) {
  var it = toPrimitive(argument, false);
  var first, third, radix, maxCode, digits, length, index, code;
  if (typeof it == 'string' && it.length > 2) {
    it = trim(it);
    first = it.charCodeAt(0);
    if (first === 43 || first === 45) {
      third = it.charCodeAt(2);
      if (third === 88 || third === 120) return NaN; // Number('+0x1') should be NaN, old V8 fix
    } else if (first === 48) {
      switch (it.charCodeAt(1)) {
        case 66: case 98: radix = 2; maxCode = 49; break; // fast equal of /^0b[01]+\$/i
        case 79: case 111: radix = 8; maxCode = 55; break; // fast equal of /^0o[0-7]+\$/i
        default: return +it;
      }
      digits = it.slice(2);
      length = digits.length;
      for (index = 0; index < length; index++) {
        code = digits.charCodeAt(index);
        // parseInt parses a string to a first unavailable symbol
        // but ToNumber should return NaN if a string contains unavailable symbols
        if (code < 48 || code > maxCode) return NaN;
      } return parseInt(digits, radix);
    }
  } return +it;
};

// `Number` constructor
// https://tc39.es/ecma262/#sec-number-constructor
if (isForced(NUMBER, !NativeNumber(' 0o1') || !NativeNumber('0b1') || NativeNumber('+0x1'))) {
  var NumberWrapper = function Number(value) {
    var it = arguments.length < 1 ? 0 : value;
    var dummy = this;
    return dummy instanceof NumberWrapper
      // check on 1..constructor(foo) case
      && (BROKEN_CLASSOF ? fails(function () { NumberPrototype.valueOf.call(dummy); }) : classof(dummy) != NUMBER)
        ? inheritIfRequired(new NativeNumber(toNumber(it)), dummy, NumberWrapper) : toNumber(it);
  };
  for (var keys = DESCRIPTORS ? getOwnPropertyNames(NativeNumber) : (
    // ES3:
    'MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,' +
    // ES2015 (in case, if modules with ES2015 Number statics required before):
    'EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,' +
    'MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger,' +
    // ESNext
    'fromString,range'
  ).split(','), j = 0, key; keys.length > j; j++) {
    if (has(NativeNumber, key = keys[j]) && !has(NumberWrapper, key)) {
      defineProperty(NumberWrapper, key, getOwnPropertyDescriptor(NativeNumber, key));
    }
  }
  NumberWrapper.prototype = NumberPrototype;
  NumberPrototype.constructor = NumberWrapper;
  redefine(global, NUMBER, NumberWrapper);
}


/***/ }),

/***/ \"./node_modules/core-js/modules/es.number.to-fixed.js\":
/*!************************************************************!*\\
  !*** ./node_modules/core-js/modules/es.number.to-fixed.js ***!
  \\************************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var toInteger = __webpack_require__(/*! ../internals/to-integer */ \"./node_modules/core-js/internals/to-integer.js\");
var thisNumberValue = __webpack_require__(/*! ../internals/this-number-value */ \"./node_modules/core-js/internals/this-number-value.js\");
var repeat = __webpack_require__(/*! ../internals/string-repeat */ \"./node_modules/core-js/internals/string-repeat.js\");
var fails = __webpack_require__(/*! ../internals/fails */ \"./node_modules/core-js/internals/fails.js\");

var nativeToFixed = 1.0.toFixed;
var floor = Math.floor;

var pow = function (x, n, acc) {
  return n === 0 ? acc : n % 2 === 1 ? pow(x, n - 1, acc * x) : pow(x * x, n / 2, acc);
};

var log = function (x) {
  var n = 0;
  var x2 = x;
  while (x2 >= 4096) {
    n += 12;
    x2 /= 4096;
  }
  while (x2 >= 2) {
    n += 1;
    x2 /= 2;
  } return n;
};

var multiply = function (data, n, c) {
  var index = -1;
  var c2 = c;
  while (++index < 6) {
    c2 += n * data[index];
    data[index] = c2 % 1e7;
    c2 = floor(c2 / 1e7);
  }
};

var divide = function (data, n) {
  var index = 6;
  var c = 0;
  while (--index >= 0) {
    c += data[index];
    data[index] = floor(c / n);
    c = (c % n) * 1e7;
  }
};

var dataToString = function (data) {
  var index = 6;
  var s = '';
  while (--index >= 0) {
    if (s !== '' || index === 0 || data[index] !== 0) {
      var t = String(data[index]);
      s = s === '' ? t : s + repeat.call('0', 7 - t.length) + t;
    }
  } return s;
};

var FORCED = nativeToFixed && (
  0.00008.toFixed(3) !== '0.000' ||
  0.9.toFixed(0) !== '1' ||
  1.255.toFixed(2) !== '1.25' ||
  1000000000000000128.0.toFixed(0) !== '1000000000000000128'
) || !fails(function () {
  // V8 ~ Android 4.3-
  nativeToFixed.call({});
});

// `Number.prototype.toFixed` method
// https://tc39.es/ecma262/#sec-number.prototype.tofixed
\$({ target: 'Number', proto: true, forced: FORCED }, {
  toFixed: function toFixed(fractionDigits) {
    var number = thisNumberValue(this);
    var fractDigits = toInteger(fractionDigits);
    var data = [0, 0, 0, 0, 0, 0];
    var sign = '';
    var result = '0';
    var e, z, j, k;

    if (fractDigits < 0 || fractDigits > 20) throw RangeError('Incorrect fraction digits');
    // eslint-disable-next-line no-self-compare -- NaN check
    if (number != number) return 'NaN';
    if (number <= -1e21 || number >= 1e21) return String(number);
    if (number < 0) {
      sign = '-';
      number = -number;
    }
    if (number > 1e-21) {
      e = log(number * pow(2, 69, 1)) - 69;
      z = e < 0 ? number * pow(2, -e, 1) : number / pow(2, e, 1);
      z *= 0x10000000000000;
      e = 52 - e;
      if (e > 0) {
        multiply(data, 0, z);
        j = fractDigits;
        while (j >= 7) {
          multiply(data, 1e7, 0);
          j -= 7;
        }
        multiply(data, pow(10, j, 1), 0);
        j = e - 1;
        while (j >= 23) {
          divide(data, 1 << 23);
          j -= 23;
        }
        divide(data, 1 << j);
        multiply(data, 1, 1);
        divide(data, 2);
        result = dataToString(data);
      } else {
        multiply(data, 0, z);
        multiply(data, 1 << -e, 0);
        result = dataToString(data) + repeat.call('0', fractDigits);
      }
    }
    if (fractDigits > 0) {
      k = result.length;
      result = sign + (k <= fractDigits
        ? '0.' + repeat.call('0', fractDigits - k) + result
        : result.slice(0, k - fractDigits) + '.' + result.slice(k - fractDigits));
    } else {
      result = sign + result;
    } return result;
  }
});


/***/ }),

/***/ \"./node_modules/core-js/modules/es.parse-float.js\":
/*!********************************************************!*\\
  !*** ./node_modules/core-js/modules/es.parse-float.js ***!
  \\********************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var parseFloatImplementation = __webpack_require__(/*! ../internals/number-parse-float */ \"./node_modules/core-js/internals/number-parse-float.js\");

// `parseFloat` method
// https://tc39.es/ecma262/#sec-parsefloat-string
\$({ global: true, forced: parseFloat != parseFloatImplementation }, {
  parseFloat: parseFloatImplementation
});


/***/ }),

/***/ \"./node_modules/core-js/modules/es.regexp.constructor.js\":
/*!***************************************************************!*\\
  !*** ./node_modules/core-js/modules/es.regexp.constructor.js ***!
  \\***************************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

var DESCRIPTORS = __webpack_require__(/*! ../internals/descriptors */ \"./node_modules/core-js/internals/descriptors.js\");
var global = __webpack_require__(/*! ../internals/global */ \"./node_modules/core-js/internals/global.js\");
var isForced = __webpack_require__(/*! ../internals/is-forced */ \"./node_modules/core-js/internals/is-forced.js\");
var inheritIfRequired = __webpack_require__(/*! ../internals/inherit-if-required */ \"./node_modules/core-js/internals/inherit-if-required.js\");
var defineProperty = __webpack_require__(/*! ../internals/object-define-property */ \"./node_modules/core-js/internals/object-define-property.js\").f;
var getOwnPropertyNames = __webpack_require__(/*! ../internals/object-get-own-property-names */ \"./node_modules/core-js/internals/object-get-own-property-names.js\").f;
var isRegExp = __webpack_require__(/*! ../internals/is-regexp */ \"./node_modules/core-js/internals/is-regexp.js\");
var getFlags = __webpack_require__(/*! ../internals/regexp-flags */ \"./node_modules/core-js/internals/regexp-flags.js\");
var stickyHelpers = __webpack_require__(/*! ../internals/regexp-sticky-helpers */ \"./node_modules/core-js/internals/regexp-sticky-helpers.js\");
var redefine = __webpack_require__(/*! ../internals/redefine */ \"./node_modules/core-js/internals/redefine.js\");
var fails = __webpack_require__(/*! ../internals/fails */ \"./node_modules/core-js/internals/fails.js\");
var enforceInternalState = __webpack_require__(/*! ../internals/internal-state */ \"./node_modules/core-js/internals/internal-state.js\").enforce;
var setSpecies = __webpack_require__(/*! ../internals/set-species */ \"./node_modules/core-js/internals/set-species.js\");
var wellKnownSymbol = __webpack_require__(/*! ../internals/well-known-symbol */ \"./node_modules/core-js/internals/well-known-symbol.js\");

var MATCH = wellKnownSymbol('match');
var NativeRegExp = global.RegExp;
var RegExpPrototype = NativeRegExp.prototype;
var re1 = /a/g;
var re2 = /a/g;

// \"new\" should create a new object, old webkit bug
var CORRECT_NEW = new NativeRegExp(re1) !== re1;

var UNSUPPORTED_Y = stickyHelpers.UNSUPPORTED_Y;

var FORCED = DESCRIPTORS && isForced('RegExp', (!CORRECT_NEW || UNSUPPORTED_Y || fails(function () {
  re2[MATCH] = false;
  // RegExp constructor can alter flags and IsRegExp works correct with @@match
  return NativeRegExp(re1) != re1 || NativeRegExp(re2) == re2 || NativeRegExp(re1, 'i') != '/a/i';
})));

// `RegExp` constructor
// https://tc39.es/ecma262/#sec-regexp-constructor
if (FORCED) {
  var RegExpWrapper = function RegExp(pattern, flags) {
    var thisIsRegExp = this instanceof RegExpWrapper;
    var patternIsRegExp = isRegExp(pattern);
    var flagsAreUndefined = flags === undefined;
    var sticky;

    if (!thisIsRegExp && patternIsRegExp && pattern.constructor === RegExpWrapper && flagsAreUndefined) {
      return pattern;
    }

    if (CORRECT_NEW) {
      if (patternIsRegExp && !flagsAreUndefined) pattern = pattern.source;
    } else if (pattern instanceof RegExpWrapper) {
      if (flagsAreUndefined) flags = getFlags.call(pattern);
      pattern = pattern.source;
    }

    if (UNSUPPORTED_Y) {
      sticky = !!flags && flags.indexOf('y') > -1;
      if (sticky) flags = flags.replace(/y/g, '');
    }

    var result = inheritIfRequired(
      CORRECT_NEW ? new NativeRegExp(pattern, flags) : NativeRegExp(pattern, flags),
      thisIsRegExp ? this : RegExpPrototype,
      RegExpWrapper
    );

    if (UNSUPPORTED_Y && sticky) {
      var state = enforceInternalState(result);
      state.sticky = true;
    }

    return result;
  };
  var proxy = function (key) {
    key in RegExpWrapper || defineProperty(RegExpWrapper, key, {
      configurable: true,
      get: function () { return NativeRegExp[key]; },
      set: function (it) { NativeRegExp[key] = it; }
    });
  };
  var keys = getOwnPropertyNames(NativeRegExp);
  var index = 0;
  while (keys.length > index) proxy(keys[index++]);
  RegExpPrototype.constructor = RegExpWrapper;
  RegExpWrapper.prototype = RegExpPrototype;
  redefine(global, 'RegExp', RegExpWrapper);
}

// https://tc39.es/ecma262/#sec-get-regexp-@@species
setSpecies('RegExp');


/***/ }),

/***/ \"./node_modules/core-js/modules/es.regexp.to-string.js\":
/*!*************************************************************!*\\
  !*** ./node_modules/core-js/modules/es.regexp.to-string.js ***!
  \\*************************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var redefine = __webpack_require__(/*! ../internals/redefine */ \"./node_modules/core-js/internals/redefine.js\");
var anObject = __webpack_require__(/*! ../internals/an-object */ \"./node_modules/core-js/internals/an-object.js\");
var fails = __webpack_require__(/*! ../internals/fails */ \"./node_modules/core-js/internals/fails.js\");
var flags = __webpack_require__(/*! ../internals/regexp-flags */ \"./node_modules/core-js/internals/regexp-flags.js\");

var TO_STRING = 'toString';
var RegExpPrototype = RegExp.prototype;
var nativeToString = RegExpPrototype[TO_STRING];

var NOT_GENERIC = fails(function () { return nativeToString.call({ source: 'a', flags: 'b' }) != '/a/b'; });
// FF44- RegExp#toString has a wrong name
var INCORRECT_NAME = nativeToString.name != TO_STRING;

// `RegExp.prototype.toString` method
// https://tc39.es/ecma262/#sec-regexp.prototype.tostring
if (NOT_GENERIC || INCORRECT_NAME) {
  redefine(RegExp.prototype, TO_STRING, function toString() {
    var R = anObject(this);
    var p = String(R.source);
    var rf = R.flags;
    var f = String(rf === undefined && R instanceof RegExp && !('flags' in RegExpPrototype) ? flags.call(R) : rf);
    return '/' + p + '/' + f;
  }, { unsafe: true });
}


/***/ }),

/***/ \"./node_modules/core-js/modules/es.string.search.js\":
/*!**********************************************************!*\\
  !*** ./node_modules/core-js/modules/es.string.search.js ***!
  \\**********************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var fixRegExpWellKnownSymbolLogic = __webpack_require__(/*! ../internals/fix-regexp-well-known-symbol-logic */ \"./node_modules/core-js/internals/fix-regexp-well-known-symbol-logic.js\");
var anObject = __webpack_require__(/*! ../internals/an-object */ \"./node_modules/core-js/internals/an-object.js\");
var requireObjectCoercible = __webpack_require__(/*! ../internals/require-object-coercible */ \"./node_modules/core-js/internals/require-object-coercible.js\");
var sameValue = __webpack_require__(/*! ../internals/same-value */ \"./node_modules/core-js/internals/same-value.js\");
var regExpExec = __webpack_require__(/*! ../internals/regexp-exec-abstract */ \"./node_modules/core-js/internals/regexp-exec-abstract.js\");

// @@search logic
fixRegExpWellKnownSymbolLogic('search', 1, function (SEARCH, nativeSearch, maybeCallNative) {
  return [
    // `String.prototype.search` method
    // https://tc39.es/ecma262/#sec-string.prototype.search
    function search(regexp) {
      var O = requireObjectCoercible(this);
      var searcher = regexp == undefined ? undefined : regexp[SEARCH];
      return searcher !== undefined ? searcher.call(regexp, O) : new RegExp(regexp)[SEARCH](String(O));
    },
    // `RegExp.prototype[@@search]` method
    // https://tc39.es/ecma262/#sec-regexp.prototype-@@search
    function (regexp) {
      var res = maybeCallNative(nativeSearch, regexp, this);
      if (res.done) return res.value;

      var rx = anObject(regexp);
      var S = String(this);

      var previousLastIndex = rx.lastIndex;
      if (!sameValue(previousLastIndex, 0)) rx.lastIndex = 0;
      var result = regExpExec(rx, S);
      if (!sameValue(rx.lastIndex, previousLastIndex)) rx.lastIndex = previousLastIndex;
      return result === null ? -1 : result.index;
    }
  ];
});


/***/ }),

/***/ \"./node_modules/core-js/modules/web.timers.js\":
/*!****************************************************!*\\
  !*** ./node_modules/core-js/modules/web.timers.js ***!
  \\****************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var global = __webpack_require__(/*! ../internals/global */ \"./node_modules/core-js/internals/global.js\");
var userAgent = __webpack_require__(/*! ../internals/engine-user-agent */ \"./node_modules/core-js/internals/engine-user-agent.js\");

var slice = [].slice;
var MSIE = /MSIE .\\./.test(userAgent); // <- dirty ie9- check

var wrap = function (scheduler) {
  return function (handler, timeout /* , ...arguments */) {
    var boundArgs = arguments.length > 2;
    var args = boundArgs ? slice.call(arguments, 2) : undefined;
    return scheduler(boundArgs ? function () {
      // eslint-disable-next-line no-new-func -- spec requirement
      (typeof handler == 'function' ? handler : Function(handler)).apply(this, args);
    } : handler, timeout);
  };
};

// ie9- setTimeout & setInterval additional parameters fix
// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers
\$({ global: true, bind: true, forced: MSIE }, {
  // `setTimeout` method
  // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-settimeout
  setTimeout: wrap(global.setTimeout),
  // `setInterval` method
  // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-setinterval
  setInterval: wrap(global.setInterval)
});


/***/ }),

/***/ \"./node_modules/leaflet/dist/leaflet-src.js\":
/*!**************************************************!*\\
  !*** ./node_modules/leaflet/dist/leaflet-src.js ***!
  \\**************************************************/
/***/ (function(__unused_webpack_module, exports) {

/* @preserve
 * Leaflet 1.9.4, a JS library for interactive maps. https://leafletjs.com
 * (c) 2010-2023 Vladimir Agafonkin, (c) 2010-2011 CloudMade
 */

(function (global, factory) {
   true ? factory(exports) :
  0;
})(this, (function (exports) { 'use strict';

  var version = \"1.9.4\";

  /*
   * @namespace Util
   *
   * Various utility functions, used by Leaflet internally.
   */

  // @function extend(dest: Object, src?: Object): Object
  // Merges the properties of the `src` object (or multiple objects) into `dest` object and returns the latter. Has an `L.extend` shortcut.
  function extend(dest) {
  \tvar i, j, len, src;

  \tfor (j = 1, len = arguments.length; j < len; j++) {
  \t\tsrc = arguments[j];
  \t\tfor (i in src) {
  \t\t\tdest[i] = src[i];
  \t\t}
  \t}
  \treturn dest;
  }

  // @function create(proto: Object, properties?: Object): Object
  // Compatibility polyfill for [Object.create](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/create)
  var create\$2 = Object.create || (function () {
  \tfunction F() {}
  \treturn function (proto) {
  \t\tF.prototype = proto;
  \t\treturn new F();
  \t};
  })();

  // @function bind(fn: Function, …): Function
  // Returns a new function bound to the arguments passed, like [Function.prototype.bind](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Function/bind).
  // Has a `L.bind()` shortcut.
  function bind(fn, obj) {
  \tvar slice = Array.prototype.slice;

  \tif (fn.bind) {
  \t\treturn fn.bind.apply(fn, slice.call(arguments, 1));
  \t}

  \tvar args = slice.call(arguments, 2);

  \treturn function () {
  \t\treturn fn.apply(obj, args.length ? args.concat(slice.call(arguments)) : arguments);
  \t};
  }

  // @property lastId: Number
  // Last unique ID used by [`stamp()`](#util-stamp)
  var lastId = 0;

  // @function stamp(obj: Object): Number
  // Returns the unique ID of an object, assigning it one if it doesn't have it.
  function stamp(obj) {
  \tif (!('_leaflet_id' in obj)) {
  \t\tobj['_leaflet_id'] = ++lastId;
  \t}
  \treturn obj._leaflet_id;
  }

  // @function throttle(fn: Function, time: Number, context: Object): Function
  // Returns a function which executes function `fn` with the given scope `context`
  // (so that the `this` keyword refers to `context` inside `fn`'s code). The function
  // `fn` will be called no more than one time per given amount of `time`. The arguments
  // received by the bound function will be any arguments passed when binding the
  // function, followed by any arguments passed when invoking the bound function.
  // Has an `L.throttle` shortcut.
  function throttle(fn, time, context) {
  \tvar lock, args, wrapperFn, later;

  \tlater = function () {
  \t\t// reset lock and call if queued
  \t\tlock = false;
  \t\tif (args) {
  \t\t\twrapperFn.apply(context, args);
  \t\t\targs = false;
  \t\t}
  \t};

  \twrapperFn = function () {
  \t\tif (lock) {
  \t\t\t// called too soon, queue to call later
  \t\t\targs = arguments;

  \t\t} else {
  \t\t\t// call and lock until later
  \t\t\tfn.apply(context, arguments);
  \t\t\tsetTimeout(later, time);
  \t\t\tlock = true;
  \t\t}
  \t};

  \treturn wrapperFn;
  }

  // @function wrapNum(num: Number, range: Number[], includeMax?: Boolean): Number
  // Returns the number `num` modulo `range` in such a way so it lies within
  // `range[0]` and `range[1]`. The returned value will be always smaller than
  // `range[1]` unless `includeMax` is set to `true`.
  function wrapNum(x, range, includeMax) {
  \tvar max = range[1],
  \t    min = range[0],
  \t    d = max - min;
  \treturn x === max && includeMax ? x : ((x - min) % d + d) % d + min;
  }

  // @function falseFn(): Function
  // Returns a function which always returns `false`.
  function falseFn() { return false; }

  // @function formatNum(num: Number, precision?: Number|false): Number
  // Returns the number `num` rounded with specified `precision`.
  // The default `precision` value is 6 decimal places.
  // `false` can be passed to skip any processing (can be useful to avoid round-off errors).
  function formatNum(num, precision) {
  \tif (precision === false) { return num; }
  \tvar pow = Math.pow(10, precision === undefined ? 6 : precision);
  \treturn Math.round(num * pow) / pow;
  }

  // @function trim(str: String): String
  // Compatibility polyfill for [String.prototype.trim](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/Trim)
  function trim(str) {
  \treturn str.trim ? str.trim() : str.replace(/^\\s+|\\s+\$/g, '');
  }

  // @function splitWords(str: String): String[]
  // Trims and splits the string on whitespace and returns the array of parts.
  function splitWords(str) {
  \treturn trim(str).split(/\\s+/);
  }

  // @function setOptions(obj: Object, options: Object): Object
  // Merges the given properties to the `options` of the `obj` object, returning the resulting options. See `Class options`. Has an `L.setOptions` shortcut.
  function setOptions(obj, options) {
  \tif (!Object.prototype.hasOwnProperty.call(obj, 'options')) {
  \t\tobj.options = obj.options ? create\$2(obj.options) : {};
  \t}
  \tfor (var i in options) {
  \t\tobj.options[i] = options[i];
  \t}
  \treturn obj.options;
  }

  // @function getParamString(obj: Object, existingUrl?: String, uppercase?: Boolean): String
  // Converts an object into a parameter URL string, e.g. `{a: \"foo\", b: \"bar\"}`
  // translates to `'?a=foo&b=bar'`. If `existingUrl` is set, the parameters will
  // be appended at the end. If `uppercase` is `true`, the parameter names will
  // be uppercased (e.g. `'?A=foo&B=bar'`)
  function getParamString(obj, existingUrl, uppercase) {
  \tvar params = [];
  \tfor (var i in obj) {
  \t\tparams.push(encodeURIComponent(uppercase ? i.toUpperCase() : i) + '=' + encodeURIComponent(obj[i]));
  \t}
  \treturn ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&');
  }

  var templateRe = /\\{ *([\\w_ -]+) *\\}/g;

  // @function template(str: String, data: Object): String
  // Simple templating facility, accepts a template string of the form `'Hello {a}, {b}'`
  // and a data object like `{a: 'foo', b: 'bar'}`, returns evaluated string
  // `('Hello foo, bar')`. You can also specify functions instead of strings for
  // data values — they will be evaluated passing `data` as an argument.
  function template(str, data) {
  \treturn str.replace(templateRe, function (str, key) {
  \t\tvar value = data[key];

  \t\tif (value === undefined) {
  \t\t\tthrow new Error('No value provided for variable ' + str);

  \t\t} else if (typeof value === 'function') {
  \t\t\tvalue = value(data);
  \t\t}
  \t\treturn value;
  \t});
  }

  // @function isArray(obj): Boolean
  // Compatibility polyfill for [Array.isArray](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray)
  var isArray = Array.isArray || function (obj) {
  \treturn (Object.prototype.toString.call(obj) === '[object Array]');
  };

  // @function indexOf(array: Array, el: Object): Number
  // Compatibility polyfill for [Array.prototype.indexOf](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf)
  function indexOf(array, el) {
  \tfor (var i = 0; i < array.length; i++) {
  \t\tif (array[i] === el) { return i; }
  \t}
  \treturn -1;
  }

  // @property emptyImageUrl: String
  // Data URI string containing a base64-encoded empty GIF image.
  // Used as a hack to free memory from unused images on WebKit-powered
  // mobile devices (by setting image `src` to this string).
  var emptyImageUrl = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';

  // inspired by https://paulirish.com/2011/requestanimationframe-for-smart-animating/

  function getPrefixed(name) {
  \treturn window['webkit' + name] || window['moz' + name] || window['ms' + name];
  }

  var lastTime = 0;

  // fallback for IE 7-8
  function timeoutDefer(fn) {
  \tvar time = +new Date(),
  \t    timeToCall = Math.max(0, 16 - (time - lastTime));

  \tlastTime = time + timeToCall;
  \treturn window.setTimeout(fn, timeToCall);
  }

  var requestFn = window.requestAnimationFrame || getPrefixed('RequestAnimationFrame') || timeoutDefer;
  var cancelFn = window.cancelAnimationFrame || getPrefixed('CancelAnimationFrame') ||
  \t\tgetPrefixed('CancelRequestAnimationFrame') || function (id) { window.clearTimeout(id); };

  // @function requestAnimFrame(fn: Function, context?: Object, immediate?: Boolean): Number
  // Schedules `fn` to be executed when the browser repaints. `fn` is bound to
  // `context` if given. When `immediate` is set, `fn` is called immediately if
  // the browser doesn't have native support for
  // [`window.requestAnimationFrame`](https://developer.mozilla.org/docs/Web/API/window/requestAnimationFrame),
  // otherwise it's delayed. Returns a request ID that can be used to cancel the request.
  function requestAnimFrame(fn, context, immediate) {
  \tif (immediate && requestFn === timeoutDefer) {
  \t\tfn.call(context);
  \t} else {
  \t\treturn requestFn.call(window, bind(fn, context));
  \t}
  }

  // @function cancelAnimFrame(id: Number): undefined
  // Cancels a previous `requestAnimFrame`. See also [window.cancelAnimationFrame](https://developer.mozilla.org/docs/Web/API/window/cancelAnimationFrame).
  function cancelAnimFrame(id) {
  \tif (id) {
  \t\tcancelFn.call(window, id);
  \t}
  }

  var Util = {
    __proto__: null,
    extend: extend,
    create: create\$2,
    bind: bind,
    get lastId () { return lastId; },
    stamp: stamp,
    throttle: throttle,
    wrapNum: wrapNum,
    falseFn: falseFn,
    formatNum: formatNum,
    trim: trim,
    splitWords: splitWords,
    setOptions: setOptions,
    getParamString: getParamString,
    template: template,
    isArray: isArray,
    indexOf: indexOf,
    emptyImageUrl: emptyImageUrl,
    requestFn: requestFn,
    cancelFn: cancelFn,
    requestAnimFrame: requestAnimFrame,
    cancelAnimFrame: cancelAnimFrame
  };

  // @class Class
  // @aka L.Class

  // @section
  // @uninheritable

  // Thanks to John Resig and Dean Edwards for inspiration!

  function Class() {}

  Class.extend = function (props) {

  \t// @function extend(props: Object): Function
  \t// [Extends the current class](#class-inheritance) given the properties to be included.
  \t// Returns a Javascript function that is a class constructor (to be called with `new`).
  \tvar NewClass = function () {

  \t\tsetOptions(this);

  \t\t// call the constructor
  \t\tif (this.initialize) {
  \t\t\tthis.initialize.apply(this, arguments);
  \t\t}

  \t\t// call all constructor hooks
  \t\tthis.callInitHooks();
  \t};

  \tvar parentProto = NewClass.__super__ = this.prototype;

  \tvar proto = create\$2(parentProto);
  \tproto.constructor = NewClass;

  \tNewClass.prototype = proto;

  \t// inherit parent's statics
  \tfor (var i in this) {
  \t\tif (Object.prototype.hasOwnProperty.call(this, i) && i !== 'prototype' && i !== '__super__') {
  \t\t\tNewClass[i] = this[i];
  \t\t}
  \t}

  \t// mix static properties into the class
  \tif (props.statics) {
  \t\textend(NewClass, props.statics);
  \t}

  \t// mix includes into the prototype
  \tif (props.includes) {
  \t\tcheckDeprecatedMixinEvents(props.includes);
  \t\textend.apply(null, [proto].concat(props.includes));
  \t}

  \t// mix given properties into the prototype
  \textend(proto, props);
  \tdelete proto.statics;
  \tdelete proto.includes;

  \t// merge options
  \tif (proto.options) {
  \t\tproto.options = parentProto.options ? create\$2(parentProto.options) : {};
  \t\textend(proto.options, props.options);
  \t}

  \tproto._initHooks = [];

  \t// add method for calling all hooks
  \tproto.callInitHooks = function () {

  \t\tif (this._initHooksCalled) { return; }

  \t\tif (parentProto.callInitHooks) {
  \t\t\tparentProto.callInitHooks.call(this);
  \t\t}

  \t\tthis._initHooksCalled = true;

  \t\tfor (var i = 0, len = proto._initHooks.length; i < len; i++) {
  \t\t\tproto._initHooks[i].call(this);
  \t\t}
  \t};

  \treturn NewClass;
  };


  // @function include(properties: Object): this
  // [Includes a mixin](#class-includes) into the current class.
  Class.include = function (props) {
  \tvar parentOptions = this.prototype.options;
  \textend(this.prototype, props);
  \tif (props.options) {
  \t\tthis.prototype.options = parentOptions;
  \t\tthis.mergeOptions(props.options);
  \t}
  \treturn this;
  };

  // @function mergeOptions(options: Object): this
  // [Merges `options`](#class-options) into the defaults of the class.
  Class.mergeOptions = function (options) {
  \textend(this.prototype.options, options);
  \treturn this;
  };

  // @function addInitHook(fn: Function): this
  // Adds a [constructor hook](#class-constructor-hooks) to the class.
  Class.addInitHook = function (fn) { // (Function) || (String, args...)
  \tvar args = Array.prototype.slice.call(arguments, 1);

  \tvar init = typeof fn === 'function' ? fn : function () {
  \t\tthis[fn].apply(this, args);
  \t};

  \tthis.prototype._initHooks = this.prototype._initHooks || [];
  \tthis.prototype._initHooks.push(init);
  \treturn this;
  };

  function checkDeprecatedMixinEvents(includes) {
  \t/* global L: true */
  \tif (typeof L === 'undefined' || !L || !L.Mixin) { return; }

  \tincludes = isArray(includes) ? includes : [includes];

  \tfor (var i = 0; i < includes.length; i++) {
  \t\tif (includes[i] === L.Mixin.Events) {
  \t\t\tconsole.warn('Deprecated include of L.Mixin.Events: ' +
  \t\t\t\t'this property will be removed in future releases, ' +
  \t\t\t\t'please inherit from L.Evented instead.', new Error().stack);
  \t\t}
  \t}
  }

  /*
   * @class Evented
   * @aka L.Evented
   * @inherits Class
   *
   * A set of methods shared between event-powered classes (like `Map` and `Marker`). Generally, events allow you to execute some function when something happens with an object (e.g. the user clicks on the map, causing the map to fire `'click'` event).
   *
   * @example
   *
   * ```js
   * map.on('click', function(e) {
   * \talert(e.latlng);
   * } );
   * ```
   *
   * Leaflet deals with event listeners by reference, so if you want to add a listener and then remove it, define it as a function:
   *
   * ```js
   * function onClick(e) { ... }
   *
   * map.on('click', onClick);
   * map.off('click', onClick);
   * ```
   */

  var Events = {
  \t/* @method on(type: String, fn: Function, context?: Object): this
  \t * Adds a listener function (`fn`) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. `'click dblclick'`).
  \t *
  \t * @alternative
  \t * @method on(eventMap: Object): this
  \t * Adds a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}`
  \t */
  \ton: function (types, fn, context) {

  \t\t// types can be a map of types/handlers
  \t\tif (typeof types === 'object') {
  \t\t\tfor (var type in types) {
  \t\t\t\t// we don't process space-separated events here for performance;
  \t\t\t\t// it's a hot path since Layer uses the on(obj) syntax
  \t\t\t\tthis._on(type, types[type], fn);
  \t\t\t}

  \t\t} else {
  \t\t\t// types can be a string of space-separated words
  \t\t\ttypes = splitWords(types);

  \t\t\tfor (var i = 0, len = types.length; i < len; i++) {
  \t\t\t\tthis._on(types[i], fn, context);
  \t\t\t}
  \t\t}

  \t\treturn this;
  \t},

  \t/* @method off(type: String, fn?: Function, context?: Object): this
  \t * Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to `on`, you must pass the same context to `off` in order to remove the listener.
  \t *
  \t * @alternative
  \t * @method off(eventMap: Object): this
  \t * Removes a set of type/listener pairs.
  \t *
  \t * @alternative
  \t * @method off: this
  \t * Removes all listeners to all events on the object. This includes implicitly attached events.
  \t */
  \toff: function (types, fn, context) {

  \t\tif (!arguments.length) {
  \t\t\t// clear all listeners if called without arguments
  \t\t\tdelete this._events;

  \t\t} else if (typeof types === 'object') {
  \t\t\tfor (var type in types) {
  \t\t\t\tthis._off(type, types[type], fn);
  \t\t\t}

  \t\t} else {
  \t\t\ttypes = splitWords(types);

  \t\t\tvar removeAll = arguments.length === 1;
  \t\t\tfor (var i = 0, len = types.length; i < len; i++) {
  \t\t\t\tif (removeAll) {
  \t\t\t\t\tthis._off(types[i]);
  \t\t\t\t} else {
  \t\t\t\t\tthis._off(types[i], fn, context);
  \t\t\t\t}
  \t\t\t}
  \t\t}

  \t\treturn this;
  \t},

  \t// attach listener (without syntactic sugar now)
  \t_on: function (type, fn, context, _once) {
  \t\tif (typeof fn !== 'function') {
  \t\t\tconsole.warn('wrong listener type: ' + typeof fn);
  \t\t\treturn;
  \t\t}

  \t\t// check if fn already there
  \t\tif (this._listens(type, fn, context) !== false) {
  \t\t\treturn;
  \t\t}

  \t\tif (context === this) {
  \t\t\t// Less memory footprint.
  \t\t\tcontext = undefined;
  \t\t}

  \t\tvar newListener = {fn: fn, ctx: context};
  \t\tif (_once) {
  \t\t\tnewListener.once = true;
  \t\t}

  \t\tthis._events = this._events || {};
  \t\tthis._events[type] = this._events[type] || [];
  \t\tthis._events[type].push(newListener);
  \t},

  \t_off: function (type, fn, context) {
  \t\tvar listeners,
  \t\t    i,
  \t\t    len;

  \t\tif (!this._events) {
  \t\t\treturn;
  \t\t}

  \t\tlisteners = this._events[type];
  \t\tif (!listeners) {
  \t\t\treturn;
  \t\t}

  \t\tif (arguments.length === 1) { // remove all
  \t\t\tif (this._firingCount) {
  \t\t\t\t// Set all removed listeners to noop
  \t\t\t\t// so they are not called if remove happens in fire
  \t\t\t\tfor (i = 0, len = listeners.length; i < len; i++) {
  \t\t\t\t\tlisteners[i].fn = falseFn;
  \t\t\t\t}
  \t\t\t}
  \t\t\t// clear all listeners for a type if function isn't specified
  \t\t\tdelete this._events[type];
  \t\t\treturn;
  \t\t}

  \t\tif (typeof fn !== 'function') {
  \t\t\tconsole.warn('wrong listener type: ' + typeof fn);
  \t\t\treturn;
  \t\t}

  \t\t// find fn and remove it
  \t\tvar index = this._listens(type, fn, context);
  \t\tif (index !== false) {
  \t\t\tvar listener = listeners[index];
  \t\t\tif (this._firingCount) {
  \t\t\t\t// set the removed listener to noop so that's not called if remove happens in fire
  \t\t\t\tlistener.fn = falseFn;

  \t\t\t\t/* copy array in case events are being fired */
  \t\t\t\tthis._events[type] = listeners = listeners.slice();
  \t\t\t}
  \t\t\tlisteners.splice(index, 1);
  \t\t}
  \t},

  \t// @method fire(type: String, data?: Object, propagate?: Boolean): this
  \t// Fires an event of the specified type. You can optionally provide a data
  \t// object — the first argument of the listener function will contain its
  \t// properties. The event can optionally be propagated to event parents.
  \tfire: function (type, data, propagate) {
  \t\tif (!this.listens(type, propagate)) { return this; }

  \t\tvar event = extend({}, data, {
  \t\t\ttype: type,
  \t\t\ttarget: this,
  \t\t\tsourceTarget: data && data.sourceTarget || this
  \t\t});

  \t\tif (this._events) {
  \t\t\tvar listeners = this._events[type];
  \t\t\tif (listeners) {
  \t\t\t\tthis._firingCount = (this._firingCount + 1) || 1;
  \t\t\t\tfor (var i = 0, len = listeners.length; i < len; i++) {
  \t\t\t\t\tvar l = listeners[i];
  \t\t\t\t\t// off overwrites l.fn, so we need to copy fn to a var
  \t\t\t\t\tvar fn = l.fn;
  \t\t\t\t\tif (l.once) {
  \t\t\t\t\t\tthis.off(type, fn, l.ctx);
  \t\t\t\t\t}
  \t\t\t\t\tfn.call(l.ctx || this, event);
  \t\t\t\t}

  \t\t\t\tthis._firingCount--;
  \t\t\t}
  \t\t}

  \t\tif (propagate) {
  \t\t\t// propagate the event to parents (set with addEventParent)
  \t\t\tthis._propagateEvent(event);
  \t\t}

  \t\treturn this;
  \t},

  \t// @method listens(type: String, propagate?: Boolean): Boolean
  \t// @method listens(type: String, fn: Function, context?: Object, propagate?: Boolean): Boolean
  \t// Returns `true` if a particular event type has any listeners attached to it.
  \t// The verification can optionally be propagated, it will return `true` if parents have the listener attached to it.
  \tlistens: function (type, fn, context, propagate) {
  \t\tif (typeof type !== 'string') {
  \t\t\tconsole.warn('\"string\" type argument expected');
  \t\t}

  \t\t// we don't overwrite the input `fn` value, because we need to use it for propagation
  \t\tvar _fn = fn;
  \t\tif (typeof fn !== 'function') {
  \t\t\tpropagate = !!fn;
  \t\t\t_fn = undefined;
  \t\t\tcontext = undefined;
  \t\t}

  \t\tvar listeners = this._events && this._events[type];
  \t\tif (listeners && listeners.length) {
  \t\t\tif (this._listens(type, _fn, context) !== false) {
  \t\t\t\treturn true;
  \t\t\t}
  \t\t}

  \t\tif (propagate) {
  \t\t\t// also check parents for listeners if event propagates
  \t\t\tfor (var id in this._eventParents) {
  \t\t\t\tif (this._eventParents[id].listens(type, fn, context, propagate)) { return true; }
  \t\t\t}
  \t\t}
  \t\treturn false;
  \t},

  \t// returns the index (number) or false
  \t_listens: function (type, fn, context) {
  \t\tif (!this._events) {
  \t\t\treturn false;
  \t\t}

  \t\tvar listeners = this._events[type] || [];
  \t\tif (!fn) {
  \t\t\treturn !!listeners.length;
  \t\t}

  \t\tif (context === this) {
  \t\t\t// Less memory footprint.
  \t\t\tcontext = undefined;
  \t\t}

  \t\tfor (var i = 0, len = listeners.length; i < len; i++) {
  \t\t\tif (listeners[i].fn === fn && listeners[i].ctx === context) {
  \t\t\t\treturn i;
  \t\t\t}
  \t\t}
  \t\treturn false;

  \t},

  \t// @method once(…): this
  \t// Behaves as [`on(…)`](#evented-on), except the listener will only get fired once and then removed.
  \tonce: function (types, fn, context) {

  \t\t// types can be a map of types/handlers
  \t\tif (typeof types === 'object') {
  \t\t\tfor (var type in types) {
  \t\t\t\t// we don't process space-separated events here for performance;
  \t\t\t\t// it's a hot path since Layer uses the on(obj) syntax
  \t\t\t\tthis._on(type, types[type], fn, true);
  \t\t\t}

  \t\t} else {
  \t\t\t// types can be a string of space-separated words
  \t\t\ttypes = splitWords(types);

  \t\t\tfor (var i = 0, len = types.length; i < len; i++) {
  \t\t\t\tthis._on(types[i], fn, context, true);
  \t\t\t}
  \t\t}

  \t\treturn this;
  \t},

  \t// @method addEventParent(obj: Evented): this
  \t// Adds an event parent - an `Evented` that will receive propagated events
  \taddEventParent: function (obj) {
  \t\tthis._eventParents = this._eventParents || {};
  \t\tthis._eventParents[stamp(obj)] = obj;
  \t\treturn this;
  \t},

  \t// @method removeEventParent(obj: Evented): this
  \t// Removes an event parent, so it will stop receiving propagated events
  \tremoveEventParent: function (obj) {
  \t\tif (this._eventParents) {
  \t\t\tdelete this._eventParents[stamp(obj)];
  \t\t}
  \t\treturn this;
  \t},

  \t_propagateEvent: function (e) {
  \t\tfor (var id in this._eventParents) {
  \t\t\tthis._eventParents[id].fire(e.type, extend({
  \t\t\t\tlayer: e.target,
  \t\t\t\tpropagatedFrom: e.target
  \t\t\t}, e), true);
  \t\t}
  \t}
  };

  // aliases; we should ditch those eventually

  // @method addEventListener(…): this
  // Alias to [`on(…)`](#evented-on)
  Events.addEventListener = Events.on;

  // @method removeEventListener(…): this
  // Alias to [`off(…)`](#evented-off)

  // @method clearAllEventListeners(…): this
  // Alias to [`off()`](#evented-off)
  Events.removeEventListener = Events.clearAllEventListeners = Events.off;

  // @method addOneTimeEventListener(…): this
  // Alias to [`once(…)`](#evented-once)
  Events.addOneTimeEventListener = Events.once;

  // @method fireEvent(…): this
  // Alias to [`fire(…)`](#evented-fire)
  Events.fireEvent = Events.fire;

  // @method hasEventListeners(…): Boolean
  // Alias to [`listens(…)`](#evented-listens)
  Events.hasEventListeners = Events.listens;

  var Evented = Class.extend(Events);

  /*
   * @class Point
   * @aka L.Point
   *
   * Represents a point with `x` and `y` coordinates in pixels.
   *
   * @example
   *
   * ```js
   * var point = L.point(200, 300);
   * ```
   *
   * All Leaflet methods and options that accept `Point` objects also accept them in a simple Array form (unless noted otherwise), so these lines are equivalent:
   *
   * ```js
   * map.panBy([200, 300]);
   * map.panBy(L.point(200, 300));
   * ```
   *
   * Note that `Point` does not inherit from Leaflet's `Class` object,
   * which means new classes can't inherit from it, and new methods
   * can't be added to it with the `include` function.
   */

  function Point(x, y, round) {
  \t// @property x: Number; The `x` coordinate of the point
  \tthis.x = (round ? Math.round(x) : x);
  \t// @property y: Number; The `y` coordinate of the point
  \tthis.y = (round ? Math.round(y) : y);
  }

  var trunc = Math.trunc || function (v) {
  \treturn v > 0 ? Math.floor(v) : Math.ceil(v);
  };

  Point.prototype = {

  \t// @method clone(): Point
  \t// Returns a copy of the current point.
  \tclone: function () {
  \t\treturn new Point(this.x, this.y);
  \t},

  \t// @method add(otherPoint: Point): Point
  \t// Returns the result of addition of the current and the given points.
  \tadd: function (point) {
  \t\t// non-destructive, returns a new point
  \t\treturn this.clone()._add(toPoint(point));
  \t},

  \t_add: function (point) {
  \t\t// destructive, used directly for performance in situations where it's safe to modify existing point
  \t\tthis.x += point.x;
  \t\tthis.y += point.y;
  \t\treturn this;
  \t},

  \t// @method subtract(otherPoint: Point): Point
  \t// Returns the result of subtraction of the given point from the current.
  \tsubtract: function (point) {
  \t\treturn this.clone()._subtract(toPoint(point));
  \t},

  \t_subtract: function (point) {
  \t\tthis.x -= point.x;
  \t\tthis.y -= point.y;
  \t\treturn this;
  \t},

  \t// @method divideBy(num: Number): Point
  \t// Returns the result of division of the current point by the given number.
  \tdivideBy: function (num) {
  \t\treturn this.clone()._divideBy(num);
  \t},

  \t_divideBy: function (num) {
  \t\tthis.x /= num;
  \t\tthis.y /= num;
  \t\treturn this;
  \t},

  \t// @method multiplyBy(num: Number): Point
  \t// Returns the result of multiplication of the current point by the given number.
  \tmultiplyBy: function (num) {
  \t\treturn this.clone()._multiplyBy(num);
  \t},

  \t_multiplyBy: function (num) {
  \t\tthis.x *= num;
  \t\tthis.y *= num;
  \t\treturn this;
  \t},

  \t// @method scaleBy(scale: Point): Point
  \t// Multiply each coordinate of the current point by each coordinate of
  \t// `scale`. In linear algebra terms, multiply the point by the
  \t// [scaling matrix](https://en.wikipedia.org/wiki/Scaling_%28geometry%29#Matrix_representation)
  \t// defined by `scale`.
  \tscaleBy: function (point) {
  \t\treturn new Point(this.x * point.x, this.y * point.y);
  \t},

  \t// @method unscaleBy(scale: Point): Point
  \t// Inverse of `scaleBy`. Divide each coordinate of the current point by
  \t// each coordinate of `scale`.
  \tunscaleBy: function (point) {
  \t\treturn new Point(this.x / point.x, this.y / point.y);
  \t},

  \t// @method round(): Point
  \t// Returns a copy of the current point with rounded coordinates.
  \tround: function () {
  \t\treturn this.clone()._round();
  \t},

  \t_round: function () {
  \t\tthis.x = Math.round(this.x);
  \t\tthis.y = Math.round(this.y);
  \t\treturn this;
  \t},

  \t// @method floor(): Point
  \t// Returns a copy of the current point with floored coordinates (rounded down).
  \tfloor: function () {
  \t\treturn this.clone()._floor();
  \t},

  \t_floor: function () {
  \t\tthis.x = Math.floor(this.x);
  \t\tthis.y = Math.floor(this.y);
  \t\treturn this;
  \t},

  \t// @method ceil(): Point
  \t// Returns a copy of the current point with ceiled coordinates (rounded up).
  \tceil: function () {
  \t\treturn this.clone()._ceil();
  \t},

  \t_ceil: function () {
  \t\tthis.x = Math.ceil(this.x);
  \t\tthis.y = Math.ceil(this.y);
  \t\treturn this;
  \t},

  \t// @method trunc(): Point
  \t// Returns a copy of the current point with truncated coordinates (rounded towards zero).
  \ttrunc: function () {
  \t\treturn this.clone()._trunc();
  \t},

  \t_trunc: function () {
  \t\tthis.x = trunc(this.x);
  \t\tthis.y = trunc(this.y);
  \t\treturn this;
  \t},

  \t// @method distanceTo(otherPoint: Point): Number
  \t// Returns the cartesian distance between the current and the given points.
  \tdistanceTo: function (point) {
  \t\tpoint = toPoint(point);

  \t\tvar x = point.x - this.x,
  \t\t    y = point.y - this.y;

  \t\treturn Math.sqrt(x * x + y * y);
  \t},

  \t// @method equals(otherPoint: Point): Boolean
  \t// Returns `true` if the given point has the same coordinates.
  \tequals: function (point) {
  \t\tpoint = toPoint(point);

  \t\treturn point.x === this.x &&
  \t\t       point.y === this.y;
  \t},

  \t// @method contains(otherPoint: Point): Boolean
  \t// Returns `true` if both coordinates of the given point are less than the corresponding current point coordinates (in absolute values).
  \tcontains: function (point) {
  \t\tpoint = toPoint(point);

  \t\treturn Math.abs(point.x) <= Math.abs(this.x) &&
  \t\t       Math.abs(point.y) <= Math.abs(this.y);
  \t},

  \t// @method toString(): String
  \t// Returns a string representation of the point for debugging purposes.
  \ttoString: function () {
  \t\treturn 'Point(' +
  \t\t        formatNum(this.x) + ', ' +
  \t\t        formatNum(this.y) + ')';
  \t}
  };

  // @factory L.point(x: Number, y: Number, round?: Boolean)
  // Creates a Point object with the given `x` and `y` coordinates. If optional `round` is set to true, rounds the `x` and `y` values.

  // @alternative
  // @factory L.point(coords: Number[])
  // Expects an array of the form `[x, y]` instead.

  // @alternative
  // @factory L.point(coords: Object)
  // Expects a plain object of the form `{x: Number, y: Number}` instead.
  function toPoint(x, y, round) {
  \tif (x instanceof Point) {
  \t\treturn x;
  \t}
  \tif (isArray(x)) {
  \t\treturn new Point(x[0], x[1]);
  \t}
  \tif (x === undefined || x === null) {
  \t\treturn x;
  \t}
  \tif (typeof x === 'object' && 'x' in x && 'y' in x) {
  \t\treturn new Point(x.x, x.y);
  \t}
  \treturn new Point(x, y, round);
  }

  /*
   * @class Bounds
   * @aka L.Bounds
   *
   * Represents a rectangular area in pixel coordinates.
   *
   * @example
   *
   * ```js
   * var p1 = L.point(10, 10),
   * p2 = L.point(40, 60),
   * bounds = L.bounds(p1, p2);
   * ```
   *
   * All Leaflet methods that accept `Bounds` objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this:
   *
   * ```js
   * otherBounds.intersects([[10, 10], [40, 60]]);
   * ```
   *
   * Note that `Bounds` does not inherit from Leaflet's `Class` object,
   * which means new classes can't inherit from it, and new methods
   * can't be added to it with the `include` function.
   */

  function Bounds(a, b) {
  \tif (!a) { return; }

  \tvar points = b ? [a, b] : a;

  \tfor (var i = 0, len = points.length; i < len; i++) {
  \t\tthis.extend(points[i]);
  \t}
  }

  Bounds.prototype = {
  \t// @method extend(point: Point): this
  \t// Extends the bounds to contain the given point.

  \t// @alternative
  \t// @method extend(otherBounds: Bounds): this
  \t// Extend the bounds to contain the given bounds
  \textend: function (obj) {
  \t\tvar min2, max2;
  \t\tif (!obj) { return this; }

  \t\tif (obj instanceof Point || typeof obj[0] === 'number' || 'x' in obj) {
  \t\t\tmin2 = max2 = toPoint(obj);
  \t\t} else {
  \t\t\tobj = toBounds(obj);
  \t\t\tmin2 = obj.min;
  \t\t\tmax2 = obj.max;

  \t\t\tif (!min2 || !max2) { return this; }
  \t\t}

  \t\t// @property min: Point
  \t\t// The top left corner of the rectangle.
  \t\t// @property max: Point
  \t\t// The bottom right corner of the rectangle.
  \t\tif (!this.min && !this.max) {
  \t\t\tthis.min = min2.clone();
  \t\t\tthis.max = max2.clone();
  \t\t} else {
  \t\t\tthis.min.x = Math.min(min2.x, this.min.x);
  \t\t\tthis.max.x = Math.max(max2.x, this.max.x);
  \t\t\tthis.min.y = Math.min(min2.y, this.min.y);
  \t\t\tthis.max.y = Math.max(max2.y, this.max.y);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method getCenter(round?: Boolean): Point
  \t// Returns the center point of the bounds.
  \tgetCenter: function (round) {
  \t\treturn toPoint(
  \t\t        (this.min.x + this.max.x) / 2,
  \t\t        (this.min.y + this.max.y) / 2, round);
  \t},

  \t// @method getBottomLeft(): Point
  \t// Returns the bottom-left point of the bounds.
  \tgetBottomLeft: function () {
  \t\treturn toPoint(this.min.x, this.max.y);
  \t},

  \t// @method getTopRight(): Point
  \t// Returns the top-right point of the bounds.
  \tgetTopRight: function () { // -> Point
  \t\treturn toPoint(this.max.x, this.min.y);
  \t},

  \t// @method getTopLeft(): Point
  \t// Returns the top-left point of the bounds (i.e. [`this.min`](#bounds-min)).
  \tgetTopLeft: function () {
  \t\treturn this.min; // left, top
  \t},

  \t// @method getBottomRight(): Point
  \t// Returns the bottom-right point of the bounds (i.e. [`this.max`](#bounds-max)).
  \tgetBottomRight: function () {
  \t\treturn this.max; // right, bottom
  \t},

  \t// @method getSize(): Point
  \t// Returns the size of the given bounds
  \tgetSize: function () {
  \t\treturn this.max.subtract(this.min);
  \t},

  \t// @method contains(otherBounds: Bounds): Boolean
  \t// Returns `true` if the rectangle contains the given one.
  \t// @alternative
  \t// @method contains(point: Point): Boolean
  \t// Returns `true` if the rectangle contains the given point.
  \tcontains: function (obj) {
  \t\tvar min, max;

  \t\tif (typeof obj[0] === 'number' || obj instanceof Point) {
  \t\t\tobj = toPoint(obj);
  \t\t} else {
  \t\t\tobj = toBounds(obj);
  \t\t}

  \t\tif (obj instanceof Bounds) {
  \t\t\tmin = obj.min;
  \t\t\tmax = obj.max;
  \t\t} else {
  \t\t\tmin = max = obj;
  \t\t}

  \t\treturn (min.x >= this.min.x) &&
  \t\t       (max.x <= this.max.x) &&
  \t\t       (min.y >= this.min.y) &&
  \t\t       (max.y <= this.max.y);
  \t},

  \t// @method intersects(otherBounds: Bounds): Boolean
  \t// Returns `true` if the rectangle intersects the given bounds. Two bounds
  \t// intersect if they have at least one point in common.
  \tintersects: function (bounds) { // (Bounds) -> Boolean
  \t\tbounds = toBounds(bounds);

  \t\tvar min = this.min,
  \t\t    max = this.max,
  \t\t    min2 = bounds.min,
  \t\t    max2 = bounds.max,
  \t\t    xIntersects = (max2.x >= min.x) && (min2.x <= max.x),
  \t\t    yIntersects = (max2.y >= min.y) && (min2.y <= max.y);

  \t\treturn xIntersects && yIntersects;
  \t},

  \t// @method overlaps(otherBounds: Bounds): Boolean
  \t// Returns `true` if the rectangle overlaps the given bounds. Two bounds
  \t// overlap if their intersection is an area.
  \toverlaps: function (bounds) { // (Bounds) -> Boolean
  \t\tbounds = toBounds(bounds);

  \t\tvar min = this.min,
  \t\t    max = this.max,
  \t\t    min2 = bounds.min,
  \t\t    max2 = bounds.max,
  \t\t    xOverlaps = (max2.x > min.x) && (min2.x < max.x),
  \t\t    yOverlaps = (max2.y > min.y) && (min2.y < max.y);

  \t\treturn xOverlaps && yOverlaps;
  \t},

  \t// @method isValid(): Boolean
  \t// Returns `true` if the bounds are properly initialized.
  \tisValid: function () {
  \t\treturn !!(this.min && this.max);
  \t},


  \t// @method pad(bufferRatio: Number): Bounds
  \t// Returns bounds created by extending or retracting the current bounds by a given ratio in each direction.
  \t// For example, a ratio of 0.5 extends the bounds by 50% in each direction.
  \t// Negative values will retract the bounds.
  \tpad: function (bufferRatio) {
  \t\tvar min = this.min,
  \t\tmax = this.max,
  \t\theightBuffer = Math.abs(min.x - max.x) * bufferRatio,
  \t\twidthBuffer = Math.abs(min.y - max.y) * bufferRatio;


  \t\treturn toBounds(
  \t\t\ttoPoint(min.x - heightBuffer, min.y - widthBuffer),
  \t\t\ttoPoint(max.x + heightBuffer, max.y + widthBuffer));
  \t},


  \t// @method equals(otherBounds: Bounds): Boolean
  \t// Returns `true` if the rectangle is equivalent to the given bounds.
  \tequals: function (bounds) {
  \t\tif (!bounds) { return false; }

  \t\tbounds = toBounds(bounds);

  \t\treturn this.min.equals(bounds.getTopLeft()) &&
  \t\t\tthis.max.equals(bounds.getBottomRight());
  \t},
  };


  // @factory L.bounds(corner1: Point, corner2: Point)
  // Creates a Bounds object from two corners coordinate pairs.
  // @alternative
  // @factory L.bounds(points: Point[])
  // Creates a Bounds object from the given array of points.
  function toBounds(a, b) {
  \tif (!a || a instanceof Bounds) {
  \t\treturn a;
  \t}
  \treturn new Bounds(a, b);
  }

  /*
   * @class LatLngBounds
   * @aka L.LatLngBounds
   *
   * Represents a rectangular geographical area on a map.
   *
   * @example
   *
   * ```js
   * var corner1 = L.latLng(40.712, -74.227),
   * corner2 = L.latLng(40.774, -74.125),
   * bounds = L.latLngBounds(corner1, corner2);
   * ```
   *
   * All Leaflet methods that accept LatLngBounds objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this:
   *
   * ```js
   * map.fitBounds([
   * \t[40.712, -74.227],
   * \t[40.774, -74.125]
   * ]);
   * ```
   *
   * Caution: if the area crosses the antimeridian (often confused with the International Date Line), you must specify corners _outside_ the [-180, 180] degrees longitude range.
   *
   * Note that `LatLngBounds` does not inherit from Leaflet's `Class` object,
   * which means new classes can't inherit from it, and new methods
   * can't be added to it with the `include` function.
   */

  function LatLngBounds(corner1, corner2) { // (LatLng, LatLng) or (LatLng[])
  \tif (!corner1) { return; }

  \tvar latlngs = corner2 ? [corner1, corner2] : corner1;

  \tfor (var i = 0, len = latlngs.length; i < len; i++) {
  \t\tthis.extend(latlngs[i]);
  \t}
  }

  LatLngBounds.prototype = {

  \t// @method extend(latlng: LatLng): this
  \t// Extend the bounds to contain the given point

  \t// @alternative
  \t// @method extend(otherBounds: LatLngBounds): this
  \t// Extend the bounds to contain the given bounds
  \textend: function (obj) {
  \t\tvar sw = this._southWest,
  \t\t    ne = this._northEast,
  \t\t    sw2, ne2;

  \t\tif (obj instanceof LatLng) {
  \t\t\tsw2 = obj;
  \t\t\tne2 = obj;

  \t\t} else if (obj instanceof LatLngBounds) {
  \t\t\tsw2 = obj._southWest;
  \t\t\tne2 = obj._northEast;

  \t\t\tif (!sw2 || !ne2) { return this; }

  \t\t} else {
  \t\t\treturn obj ? this.extend(toLatLng(obj) || toLatLngBounds(obj)) : this;
  \t\t}

  \t\tif (!sw && !ne) {
  \t\t\tthis._southWest = new LatLng(sw2.lat, sw2.lng);
  \t\t\tthis._northEast = new LatLng(ne2.lat, ne2.lng);
  \t\t} else {
  \t\t\tsw.lat = Math.min(sw2.lat, sw.lat);
  \t\t\tsw.lng = Math.min(sw2.lng, sw.lng);
  \t\t\tne.lat = Math.max(ne2.lat, ne.lat);
  \t\t\tne.lng = Math.max(ne2.lng, ne.lng);
  \t\t}

  \t\treturn this;
  \t},

  \t// @method pad(bufferRatio: Number): LatLngBounds
  \t// Returns bounds created by extending or retracting the current bounds by a given ratio in each direction.
  \t// For example, a ratio of 0.5 extends the bounds by 50% in each direction.
  \t// Negative values will retract the bounds.
  \tpad: function (bufferRatio) {
  \t\tvar sw = this._southWest,
  \t\t    ne = this._northEast,
  \t\t    heightBuffer = Math.abs(sw.lat - ne.lat) * bufferRatio,
  \t\t    widthBuffer = Math.abs(sw.lng - ne.lng) * bufferRatio;

  \t\treturn new LatLngBounds(
  \t\t        new LatLng(sw.lat - heightBuffer, sw.lng - widthBuffer),
  \t\t        new LatLng(ne.lat + heightBuffer, ne.lng + widthBuffer));
  \t},

  \t// @method getCenter(): LatLng
  \t// Returns the center point of the bounds.
  \tgetCenter: function () {
  \t\treturn new LatLng(
  \t\t        (this._southWest.lat + this._northEast.lat) / 2,
  \t\t        (this._southWest.lng + this._northEast.lng) / 2);
  \t},

  \t// @method getSouthWest(): LatLng
  \t// Returns the south-west point of the bounds.
  \tgetSouthWest: function () {
  \t\treturn this._southWest;
  \t},

  \t// @method getNorthEast(): LatLng
  \t// Returns the north-east point of the bounds.
  \tgetNorthEast: function () {
  \t\treturn this._northEast;
  \t},

  \t// @method getNorthWest(): LatLng
  \t// Returns the north-west point of the bounds.
  \tgetNorthWest: function () {
  \t\treturn new LatLng(this.getNorth(), this.getWest());
  \t},

  \t// @method getSouthEast(): LatLng
  \t// Returns the south-east point of the bounds.
  \tgetSouthEast: function () {
  \t\treturn new LatLng(this.getSouth(), this.getEast());
  \t},

  \t// @method getWest(): Number
  \t// Returns the west longitude of the bounds
  \tgetWest: function () {
  \t\treturn this._southWest.lng;
  \t},

  \t// @method getSouth(): Number
  \t// Returns the south latitude of the bounds
  \tgetSouth: function () {
  \t\treturn this._southWest.lat;
  \t},

  \t// @method getEast(): Number
  \t// Returns the east longitude of the bounds
  \tgetEast: function () {
  \t\treturn this._northEast.lng;
  \t},

  \t// @method getNorth(): Number
  \t// Returns the north latitude of the bounds
  \tgetNorth: function () {
  \t\treturn this._northEast.lat;
  \t},

  \t// @method contains(otherBounds: LatLngBounds): Boolean
  \t// Returns `true` if the rectangle contains the given one.

  \t// @alternative
  \t// @method contains (latlng: LatLng): Boolean
  \t// Returns `true` if the rectangle contains the given point.
  \tcontains: function (obj) { // (LatLngBounds) or (LatLng) -> Boolean
  \t\tif (typeof obj[0] === 'number' || obj instanceof LatLng || 'lat' in obj) {
  \t\t\tobj = toLatLng(obj);
  \t\t} else {
  \t\t\tobj = toLatLngBounds(obj);
  \t\t}

  \t\tvar sw = this._southWest,
  \t\t    ne = this._northEast,
  \t\t    sw2, ne2;

  \t\tif (obj instanceof LatLngBounds) {
  \t\t\tsw2 = obj.getSouthWest();
  \t\t\tne2 = obj.getNorthEast();
  \t\t} else {
  \t\t\tsw2 = ne2 = obj;
  \t\t}

  \t\treturn (sw2.lat >= sw.lat) && (ne2.lat <= ne.lat) &&
  \t\t       (sw2.lng >= sw.lng) && (ne2.lng <= ne.lng);
  \t},

  \t// @method intersects(otherBounds: LatLngBounds): Boolean
  \t// Returns `true` if the rectangle intersects the given bounds. Two bounds intersect if they have at least one point in common.
  \tintersects: function (bounds) {
  \t\tbounds = toLatLngBounds(bounds);

  \t\tvar sw = this._southWest,
  \t\t    ne = this._northEast,
  \t\t    sw2 = bounds.getSouthWest(),
  \t\t    ne2 = bounds.getNorthEast(),

  \t\t    latIntersects = (ne2.lat >= sw.lat) && (sw2.lat <= ne.lat),
  \t\t    lngIntersects = (ne2.lng >= sw.lng) && (sw2.lng <= ne.lng);

  \t\treturn latIntersects && lngIntersects;
  \t},

  \t// @method overlaps(otherBounds: LatLngBounds): Boolean
  \t// Returns `true` if the rectangle overlaps the given bounds. Two bounds overlap if their intersection is an area.
  \toverlaps: function (bounds) {
  \t\tbounds = toLatLngBounds(bounds);

  \t\tvar sw = this._southWest,
  \t\t    ne = this._northEast,
  \t\t    sw2 = bounds.getSouthWest(),
  \t\t    ne2 = bounds.getNorthEast(),

  \t\t    latOverlaps = (ne2.lat > sw.lat) && (sw2.lat < ne.lat),
  \t\t    lngOverlaps = (ne2.lng > sw.lng) && (sw2.lng < ne.lng);

  \t\treturn latOverlaps && lngOverlaps;
  \t},

  \t// @method toBBoxString(): String
  \t// Returns a string with bounding box coordinates in a 'southwest_lng,southwest_lat,northeast_lng,northeast_lat' format. Useful for sending requests to web services that return geo data.
  \ttoBBoxString: function () {
  \t\treturn [this.getWest(), this.getSouth(), this.getEast(), this.getNorth()].join(',');
  \t},

  \t// @method equals(otherBounds: LatLngBounds, maxMargin?: Number): Boolean
  \t// Returns `true` if the rectangle is equivalent (within a small margin of error) to the given bounds. The margin of error can be overridden by setting `maxMargin` to a small number.
  \tequals: function (bounds, maxMargin) {
  \t\tif (!bounds) { return false; }

  \t\tbounds = toLatLngBounds(bounds);

  \t\treturn this._southWest.equals(bounds.getSouthWest(), maxMargin) &&
  \t\t       this._northEast.equals(bounds.getNorthEast(), maxMargin);
  \t},

  \t// @method isValid(): Boolean
  \t// Returns `true` if the bounds are properly initialized.
  \tisValid: function () {
  \t\treturn !!(this._southWest && this._northEast);
  \t}
  };

  // TODO International date line?

  // @factory L.latLngBounds(corner1: LatLng, corner2: LatLng)
  // Creates a `LatLngBounds` object by defining two diagonally opposite corners of the rectangle.

  // @alternative
  // @factory L.latLngBounds(latlngs: LatLng[])
  // Creates a `LatLngBounds` object defined by the geographical points it contains. Very useful for zooming the map to fit a particular set of locations with [`fitBounds`](#map-fitbounds).
  function toLatLngBounds(a, b) {
  \tif (a instanceof LatLngBounds) {
  \t\treturn a;
  \t}
  \treturn new LatLngBounds(a, b);
  }

  /* @class LatLng
   * @aka L.LatLng
   *
   * Represents a geographical point with a certain latitude and longitude.
   *
   * @example
   *
   * ```
   * var latlng = L.latLng(50.5, 30.5);
   * ```
   *
   * All Leaflet methods that accept LatLng objects also accept them in a simple Array form and simple object form (unless noted otherwise), so these lines are equivalent:
   *
   * ```
   * map.panTo([50, 30]);
   * map.panTo({lon: 30, lat: 50});
   * map.panTo({lat: 50, lng: 30});
   * map.panTo(L.latLng(50, 30));
   * ```
   *
   * Note that `LatLng` does not inherit from Leaflet's `Class` object,
   * which means new classes can't inherit from it, and new methods
   * can't be added to it with the `include` function.
   */

  function LatLng(lat, lng, alt) {
  \tif (isNaN(lat) || isNaN(lng)) {
  \t\tthrow new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')');
  \t}

  \t// @property lat: Number
  \t// Latitude in degrees
  \tthis.lat = +lat;

  \t// @property lng: Number
  \t// Longitude in degrees
  \tthis.lng = +lng;

  \t// @property alt: Number
  \t// Altitude in meters (optional)
  \tif (alt !== undefined) {
  \t\tthis.alt = +alt;
  \t}
  }

  LatLng.prototype = {
  \t// @method equals(otherLatLng: LatLng, maxMargin?: Number): Boolean
  \t// Returns `true` if the given `LatLng` point is at the same position (within a small margin of error). The margin of error can be overridden by setting `maxMargin` to a small number.
  \tequals: function (obj, maxMargin) {
  \t\tif (!obj) { return false; }

  \t\tobj = toLatLng(obj);

  \t\tvar margin = Math.max(
  \t\t        Math.abs(this.lat - obj.lat),
  \t\t        Math.abs(this.lng - obj.lng));

  \t\treturn margin <= (maxMargin === undefined ? 1.0E-9 : maxMargin);
  \t},

  \t// @method toString(): String
  \t// Returns a string representation of the point (for debugging purposes).
  \ttoString: function (precision) {
  \t\treturn 'LatLng(' +
  \t\t        formatNum(this.lat, precision) + ', ' +
  \t\t        formatNum(this.lng, precision) + ')';
  \t},

  \t// @method distanceTo(otherLatLng: LatLng): Number
  \t// Returns the distance (in meters) to the given `LatLng` calculated using the [Spherical Law of Cosines](https://en.wikipedia.org/wiki/Spherical_law_of_cosines).
  \tdistanceTo: function (other) {
  \t\treturn Earth.distance(this, toLatLng(other));
  \t},

  \t// @method wrap(): LatLng
  \t// Returns a new `LatLng` object with the longitude wrapped so it's always between -180 and +180 degrees.
  \twrap: function () {
  \t\treturn Earth.wrapLatLng(this);
  \t},

  \t// @method toBounds(sizeInMeters: Number): LatLngBounds
  \t// Returns a new `LatLngBounds` object in which each boundary is `sizeInMeters/2` meters apart from the `LatLng`.
  \ttoBounds: function (sizeInMeters) {
  \t\tvar latAccuracy = 180 * sizeInMeters / 40075017,
  \t\t    lngAccuracy = latAccuracy / Math.cos((Math.PI / 180) * this.lat);

  \t\treturn toLatLngBounds(
  \t\t        [this.lat - latAccuracy, this.lng - lngAccuracy],
  \t\t        [this.lat + latAccuracy, this.lng + lngAccuracy]);
  \t},

  \tclone: function () {
  \t\treturn new LatLng(this.lat, this.lng, this.alt);
  \t}
  };



  // @factory L.latLng(latitude: Number, longitude: Number, altitude?: Number): LatLng
  // Creates an object representing a geographical point with the given latitude and longitude (and optionally altitude).

  // @alternative
  // @factory L.latLng(coords: Array): LatLng
  // Expects an array of the form `[Number, Number]` or `[Number, Number, Number]` instead.

  // @alternative
  // @factory L.latLng(coords: Object): LatLng
  // Expects an plain object of the form `{lat: Number, lng: Number}` or `{lat: Number, lng: Number, alt: Number}` instead.

  function toLatLng(a, b, c) {
  \tif (a instanceof LatLng) {
  \t\treturn a;
  \t}
  \tif (isArray(a) && typeof a[0] !== 'object') {
  \t\tif (a.length === 3) {
  \t\t\treturn new LatLng(a[0], a[1], a[2]);
  \t\t}
  \t\tif (a.length === 2) {
  \t\t\treturn new LatLng(a[0], a[1]);
  \t\t}
  \t\treturn null;
  \t}
  \tif (a === undefined || a === null) {
  \t\treturn a;
  \t}
  \tif (typeof a === 'object' && 'lat' in a) {
  \t\treturn new LatLng(a.lat, 'lng' in a ? a.lng : a.lon, a.alt);
  \t}
  \tif (b === undefined) {
  \t\treturn null;
  \t}
  \treturn new LatLng(a, b, c);
  }

  /*
   * @namespace CRS
   * @crs L.CRS.Base
   * Object that defines coordinate reference systems for projecting
   * geographical points into pixel (screen) coordinates and back (and to
   * coordinates in other units for [WMS](https://en.wikipedia.org/wiki/Web_Map_Service) services). See
   * [spatial reference system](https://en.wikipedia.org/wiki/Spatial_reference_system).
   *
   * Leaflet defines the most usual CRSs by default. If you want to use a
   * CRS not defined by default, take a look at the
   * [Proj4Leaflet](https://github.com/kartena/Proj4Leaflet) plugin.
   *
   * Note that the CRS instances do not inherit from Leaflet's `Class` object,
   * and can't be instantiated. Also, new classes can't inherit from them,
   * and methods can't be added to them with the `include` function.
   */

  var CRS = {
  \t// @method latLngToPoint(latlng: LatLng, zoom: Number): Point
  \t// Projects geographical coordinates into pixel coordinates for a given zoom.
  \tlatLngToPoint: function (latlng, zoom) {
  \t\tvar projectedPoint = this.projection.project(latlng),
  \t\t    scale = this.scale(zoom);

  \t\treturn this.transformation._transform(projectedPoint, scale);
  \t},

  \t// @method pointToLatLng(point: Point, zoom: Number): LatLng
  \t// The inverse of `latLngToPoint`. Projects pixel coordinates on a given
  \t// zoom into geographical coordinates.
  \tpointToLatLng: function (point, zoom) {
  \t\tvar scale = this.scale(zoom),
  \t\t    untransformedPoint = this.transformation.untransform(point, scale);

  \t\treturn this.projection.unproject(untransformedPoint);
  \t},

  \t// @method project(latlng: LatLng): Point
  \t// Projects geographical coordinates into coordinates in units accepted for
  \t// this CRS (e.g. meters for EPSG:3857, for passing it to WMS services).
  \tproject: function (latlng) {
  \t\treturn this.projection.project(latlng);
  \t},

  \t// @method unproject(point: Point): LatLng
  \t// Given a projected coordinate returns the corresponding LatLng.
  \t// The inverse of `project`.
  \tunproject: function (point) {
  \t\treturn this.projection.unproject(point);
  \t},

  \t// @method scale(zoom: Number): Number
  \t// Returns the scale used when transforming projected coordinates into
  \t// pixel coordinates for a particular zoom. For example, it returns
  \t// `256 * 2^zoom` for Mercator-based CRS.
  \tscale: function (zoom) {
  \t\treturn 256 * Math.pow(2, zoom);
  \t},

  \t// @method zoom(scale: Number): Number
  \t// Inverse of `scale()`, returns the zoom level corresponding to a scale
  \t// factor of `scale`.
  \tzoom: function (scale) {
  \t\treturn Math.log(scale / 256) / Math.LN2;
  \t},

  \t// @method getProjectedBounds(zoom: Number): Bounds
  \t// Returns the projection's bounds scaled and transformed for the provided `zoom`.
  \tgetProjectedBounds: function (zoom) {
  \t\tif (this.infinite) { return null; }

  \t\tvar b = this.projection.bounds,
  \t\t    s = this.scale(zoom),
  \t\t    min = this.transformation.transform(b.min, s),
  \t\t    max = this.transformation.transform(b.max, s);

  \t\treturn new Bounds(min, max);
  \t},

  \t// @method distance(latlng1: LatLng, latlng2: LatLng): Number
  \t// Returns the distance between two geographical coordinates.

  \t// @property code: String
  \t// Standard code name of the CRS passed into WMS services (e.g. `'EPSG:3857'`)
  \t//
  \t// @property wrapLng: Number[]
  \t// An array of two numbers defining whether the longitude (horizontal) coordinate
  \t// axis wraps around a given range and how. Defaults to `[-180, 180]` in most
  \t// geographical CRSs. If `undefined`, the longitude axis does not wrap around.
  \t//
  \t// @property wrapLat: Number[]
  \t// Like `wrapLng`, but for the latitude (vertical) axis.

  \t// wrapLng: [min, max],
  \t// wrapLat: [min, max],

  \t// @property infinite: Boolean
  \t// If true, the coordinate space will be unbounded (infinite in both axes)
  \tinfinite: false,

  \t// @method wrapLatLng(latlng: LatLng): LatLng
  \t// Returns a `LatLng` where lat and lng has been wrapped according to the
  \t// CRS's `wrapLat` and `wrapLng` properties, if they are outside the CRS's bounds.
  \twrapLatLng: function (latlng) {
  \t\tvar lng = this.wrapLng ? wrapNum(latlng.lng, this.wrapLng, true) : latlng.lng,
  \t\t    lat = this.wrapLat ? wrapNum(latlng.lat, this.wrapLat, true) : latlng.lat,
  \t\t    alt = latlng.alt;

  \t\treturn new LatLng(lat, lng, alt);
  \t},

  \t// @method wrapLatLngBounds(bounds: LatLngBounds): LatLngBounds
  \t// Returns a `LatLngBounds` with the same size as the given one, ensuring
  \t// that its center is within the CRS's bounds.
  \t// Only accepts actual `L.LatLngBounds` instances, not arrays.
  \twrapLatLngBounds: function (bounds) {
  \t\tvar center = bounds.getCenter(),
  \t\t    newCenter = this.wrapLatLng(center),
  \t\t    latShift = center.lat - newCenter.lat,
  \t\t    lngShift = center.lng - newCenter.lng;

  \t\tif (latShift === 0 && lngShift === 0) {
  \t\t\treturn bounds;
  \t\t}

  \t\tvar sw = bounds.getSouthWest(),
  \t\t    ne = bounds.getNorthEast(),
  \t\t    newSw = new LatLng(sw.lat - latShift, sw.lng - lngShift),
  \t\t    newNe = new LatLng(ne.lat - latShift, ne.lng - lngShift);

  \t\treturn new LatLngBounds(newSw, newNe);
  \t}
  };

  /*
   * @namespace CRS
   * @crs L.CRS.Earth
   *
   * Serves as the base for CRS that are global such that they cover the earth.
   * Can only be used as the base for other CRS and cannot be used directly,
   * since it does not have a `code`, `projection` or `transformation`. `distance()` returns
   * meters.
   */

  var Earth = extend({}, CRS, {
  \twrapLng: [-180, 180],

  \t// Mean Earth Radius, as recommended for use by
  \t// the International Union of Geodesy and Geophysics,
  \t// see https://rosettacode.org/wiki/Haversine_formula
  \tR: 6371000,

  \t// distance between two geographical points using spherical law of cosines approximation
  \tdistance: function (latlng1, latlng2) {
  \t\tvar rad = Math.PI / 180,
  \t\t    lat1 = latlng1.lat * rad,
  \t\t    lat2 = latlng2.lat * rad,
  \t\t    sinDLat = Math.sin((latlng2.lat - latlng1.lat) * rad / 2),
  \t\t    sinDLon = Math.sin((latlng2.lng - latlng1.lng) * rad / 2),
  \t\t    a = sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon,
  \t\t    c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  \t\treturn this.R * c;
  \t}
  });

  /*
   * @namespace Projection
   * @projection L.Projection.SphericalMercator
   *
   * Spherical Mercator projection — the most common projection for online maps,
   * used by almost all free and commercial tile providers. Assumes that Earth is
   * a sphere. Used by the `EPSG:3857` CRS.
   */

  var earthRadius = 6378137;

  var SphericalMercator = {

  \tR: earthRadius,
  \tMAX_LATITUDE: 85.0511287798,

  \tproject: function (latlng) {
  \t\tvar d = Math.PI / 180,
  \t\t    max = this.MAX_LATITUDE,
  \t\t    lat = Math.max(Math.min(max, latlng.lat), -max),
  \t\t    sin = Math.sin(lat * d);

  \t\treturn new Point(
  \t\t\tthis.R * latlng.lng * d,
  \t\t\tthis.R * Math.log((1 + sin) / (1 - sin)) / 2);
  \t},

  \tunproject: function (point) {
  \t\tvar d = 180 / Math.PI;

  \t\treturn new LatLng(
  \t\t\t(2 * Math.atan(Math.exp(point.y / this.R)) - (Math.PI / 2)) * d,
  \t\t\tpoint.x * d / this.R);
  \t},

  \tbounds: (function () {
  \t\tvar d = earthRadius * Math.PI;
  \t\treturn new Bounds([-d, -d], [d, d]);
  \t})()
  };

  /*
   * @class Transformation
   * @aka L.Transformation
   *
   * Represents an affine transformation: a set of coefficients `a`, `b`, `c`, `d`
   * for transforming a point of a form `(x, y)` into `(a*x + b, c*y + d)` and doing
   * the reverse. Used by Leaflet in its projections code.
   *
   * @example
   *
   * ```js
   * var transformation = L.transformation(2, 5, -1, 10),
   * \tp = L.point(1, 2),
   * \tp2 = transformation.transform(p), //  L.point(7, 8)
   * \tp3 = transformation.untransform(p2); //  L.point(1, 2)
   * ```
   */


  // factory new L.Transformation(a: Number, b: Number, c: Number, d: Number)
  // Creates a `Transformation` object with the given coefficients.
  function Transformation(a, b, c, d) {
  \tif (isArray(a)) {
  \t\t// use array properties
  \t\tthis._a = a[0];
  \t\tthis._b = a[1];
  \t\tthis._c = a[2];
  \t\tthis._d = a[3];
  \t\treturn;
  \t}
  \tthis._a = a;
  \tthis._b = b;
  \tthis._c = c;
  \tthis._d = d;
  }

  Transformation.prototype = {
  \t// @method transform(point: Point, scale?: Number): Point
  \t// Returns a transformed point, optionally multiplied by the given scale.
  \t// Only accepts actual `L.Point` instances, not arrays.
  \ttransform: function (point, scale) { // (Point, Number) -> Point
  \t\treturn this._transform(point.clone(), scale);
  \t},

  \t// destructive transform (faster)
  \t_transform: function (point, scale) {
  \t\tscale = scale || 1;
  \t\tpoint.x = scale * (this._a * point.x + this._b);
  \t\tpoint.y = scale * (this._c * point.y + this._d);
  \t\treturn point;
  \t},

  \t// @method untransform(point: Point, scale?: Number): Point
  \t// Returns the reverse transformation of the given point, optionally divided
  \t// by the given scale. Only accepts actual `L.Point` instances, not arrays.
  \tuntransform: function (point, scale) {
  \t\tscale = scale || 1;
  \t\treturn new Point(
  \t\t        (point.x / scale - this._b) / this._a,
  \t\t        (point.y / scale - this._d) / this._c);
  \t}
  };

  // factory L.transformation(a: Number, b: Number, c: Number, d: Number)

  // @factory L.transformation(a: Number, b: Number, c: Number, d: Number)
  // Instantiates a Transformation object with the given coefficients.

  // @alternative
  // @factory L.transformation(coefficients: Array): Transformation
  // Expects an coefficients array of the form
  // `[a: Number, b: Number, c: Number, d: Number]`.

  function toTransformation(a, b, c, d) {
  \treturn new Transformation(a, b, c, d);
  }

  /*
   * @namespace CRS
   * @crs L.CRS.EPSG3857
   *
   * The most common CRS for online maps, used by almost all free and commercial
   * tile providers. Uses Spherical Mercator projection. Set in by default in
   * Map's `crs` option.
   */

  var EPSG3857 = extend({}, Earth, {
  \tcode: 'EPSG:3857',
  \tprojection: SphericalMercator,

  \ttransformation: (function () {
  \t\tvar scale = 0.5 / (Math.PI * SphericalMercator.R);
  \t\treturn toTransformation(scale, 0.5, -scale, 0.5);
  \t}())
  });

  var EPSG900913 = extend({}, EPSG3857, {
  \tcode: 'EPSG:900913'
  });

  // @namespace SVG; @section
  // There are several static functions which can be called without instantiating L.SVG:

  // @function create(name: String): SVGElement
  // Returns a instance of [SVGElement](https://developer.mozilla.org/docs/Web/API/SVGElement),
  // corresponding to the class name passed. For example, using 'line' will return
  // an instance of [SVGLineElement](https://developer.mozilla.org/docs/Web/API/SVGLineElement).
  function svgCreate(name) {
  \treturn document.createElementNS('http://www.w3.org/2000/svg', name);
  }

  // @function pointsToPath(rings: Point[], closed: Boolean): String
  // Generates a SVG path string for multiple rings, with each ring turning
  // into \"M..L..L..\" instructions
  function pointsToPath(rings, closed) {
  \tvar str = '',
  \ti, j, len, len2, points, p;

  \tfor (i = 0, len = rings.length; i < len; i++) {
  \t\tpoints = rings[i];

  \t\tfor (j = 0, len2 = points.length; j < len2; j++) {
  \t\t\tp = points[j];
  \t\t\tstr += (j ? 'L' : 'M') + p.x + ' ' + p.y;
  \t\t}

  \t\t// closes the ring for polygons; \"x\" is VML syntax
  \t\tstr += closed ? (Browser.svg ? 'z' : 'x') : '';
  \t}

  \t// SVG complains about empty path strings
  \treturn str || 'M0 0';
  }

  /*
   * @namespace Browser
   * @aka L.Browser
   *
   * A namespace with static properties for browser/feature detection used by Leaflet internally.
   *
   * @example
   *
   * ```js
   * if (L.Browser.ielt9) {
   *   alert('Upgrade your browser, dude!');
   * }
   * ```
   */

  var style = document.documentElement.style;

  // @property ie: Boolean; `true` for all Internet Explorer versions (not Edge).
  var ie = 'ActiveXObject' in window;

  // @property ielt9: Boolean; `true` for Internet Explorer versions less than 9.
  var ielt9 = ie && !document.addEventListener;

  // @property edge: Boolean; `true` for the Edge web browser.
  var edge = 'msLaunchUri' in navigator && !('documentMode' in document);

  // @property webkit: Boolean;
  // `true` for webkit-based browsers like Chrome and Safari (including mobile versions).
  var webkit = userAgentContains('webkit');

  // @property android: Boolean
  // **Deprecated.** `true` for any browser running on an Android platform.
  var android = userAgentContains('android');

  // @property android23: Boolean; **Deprecated.** `true` for browsers running on Android 2 or Android 3.
  var android23 = userAgentContains('android 2') || userAgentContains('android 3');

  /* See https://stackoverflow.com/a/17961266 for details on detecting stock Android */
  var webkitVer = parseInt(/WebKit\\/([0-9]+)|\$/.exec(navigator.userAgent)[1], 10); // also matches AppleWebKit
  // @property androidStock: Boolean; **Deprecated.** `true` for the Android stock browser (i.e. not Chrome)
  var androidStock = android && userAgentContains('Google') && webkitVer < 537 && !('AudioNode' in window);

  // @property opera: Boolean; `true` for the Opera browser
  var opera = !!window.opera;

  // @property chrome: Boolean; `true` for the Chrome browser.
  var chrome = !edge && userAgentContains('chrome');

  // @property gecko: Boolean; `true` for gecko-based browsers like Firefox.
  var gecko = userAgentContains('gecko') && !webkit && !opera && !ie;

  // @property safari: Boolean; `true` for the Safari browser.
  var safari = !chrome && userAgentContains('safari');

  var phantom = userAgentContains('phantom');

  // @property opera12: Boolean
  // `true` for the Opera browser supporting CSS transforms (version 12 or later).
  var opera12 = 'OTransition' in style;

  // @property win: Boolean; `true` when the browser is running in a Windows platform
  var win = navigator.platform.indexOf('Win') === 0;

  // @property ie3d: Boolean; `true` for all Internet Explorer versions supporting CSS transforms.
  var ie3d = ie && ('transition' in style);

  // @property webkit3d: Boolean; `true` for webkit-based browsers supporting CSS transforms.
  var webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()) && !android23;

  // @property gecko3d: Boolean; `true` for gecko-based browsers supporting CSS transforms.
  var gecko3d = 'MozPerspective' in style;

  // @property any3d: Boolean
  // `true` for all browsers supporting CSS transforms.
  var any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d) && !opera12 && !phantom;

  // @property mobile: Boolean; `true` for all browsers running in a mobile device.
  var mobile = typeof orientation !== 'undefined' || userAgentContains('mobile');

  // @property mobileWebkit: Boolean; `true` for all webkit-based browsers in a mobile device.
  var mobileWebkit = mobile && webkit;

  // @property mobileWebkit3d: Boolean
  // `true` for all webkit-based browsers in a mobile device supporting CSS transforms.
  var mobileWebkit3d = mobile && webkit3d;

  // @property msPointer: Boolean
  // `true` for browsers implementing the Microsoft touch events model (notably IE10).
  var msPointer = !window.PointerEvent && window.MSPointerEvent;

  // @property pointer: Boolean
  // `true` for all browsers supporting [pointer events](https://msdn.microsoft.com/en-us/library/dn433244%28v=vs.85%29.aspx).
  var pointer = !!(window.PointerEvent || msPointer);

  // @property touchNative: Boolean
  // `true` for all browsers supporting [touch events](https://developer.mozilla.org/docs/Web/API/Touch_events).
  // **This does not necessarily mean** that the browser is running in a computer with
  // a touchscreen, it only means that the browser is capable of understanding
  // touch events.
  var touchNative = 'ontouchstart' in window || !!window.TouchEvent;

  // @property touch: Boolean
  // `true` for all browsers supporting either [touch](#browser-touch) or [pointer](#browser-pointer) events.
  // Note: pointer events will be preferred (if available), and processed for all `touch*` listeners.
  var touch = !window.L_NO_TOUCH && (touchNative || pointer);

  // @property mobileOpera: Boolean; `true` for the Opera browser in a mobile device.
  var mobileOpera = mobile && opera;

  // @property mobileGecko: Boolean
  // `true` for gecko-based browsers running in a mobile device.
  var mobileGecko = mobile && gecko;

  // @property retina: Boolean
  // `true` for browsers on a high-resolution \"retina\" screen or on any screen when browser's display zoom is more than 100%.
  var retina = (window.devicePixelRatio || (window.screen.deviceXDPI / window.screen.logicalXDPI)) > 1;

  // @property passiveEvents: Boolean
  // `true` for browsers that support passive events.
  var passiveEvents = (function () {
  \tvar supportsPassiveOption = false;
  \ttry {
  \t\tvar opts = Object.defineProperty({}, 'passive', {
  \t\t\tget: function () { // eslint-disable-line getter-return
  \t\t\t\tsupportsPassiveOption = true;
  \t\t\t}
  \t\t});
  \t\twindow.addEventListener('testPassiveEventSupport', falseFn, opts);
  \t\twindow.removeEventListener('testPassiveEventSupport', falseFn, opts);
  \t} catch (e) {
  \t\t// Errors can safely be ignored since this is only a browser support test.
  \t}
  \treturn supportsPassiveOption;
  }());

  // @property canvas: Boolean
  // `true` when the browser supports [`<canvas>`](https://developer.mozilla.org/docs/Web/API/Canvas_API).
  var canvas\$1 = (function () {
  \treturn !!document.createElement('canvas').getContext;
  }());

  // @property svg: Boolean
  // `true` when the browser supports [SVG](https://developer.mozilla.org/docs/Web/SVG).
  var svg\$1 = !!(document.createElementNS && svgCreate('svg').createSVGRect);

  var inlineSvg = !!svg\$1 && (function () {
  \tvar div = document.createElement('div');
  \tdiv.innerHTML = '<svg/>';
  \treturn (div.firstChild && div.firstChild.namespaceURI) === 'http://www.w3.org/2000/svg';
  })();

  // @property vml: Boolean
  // `true` if the browser supports [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language).
  var vml = !svg\$1 && (function () {
  \ttry {
  \t\tvar div = document.createElement('div');
  \t\tdiv.innerHTML = '<v:shape adj=\"1\"/>';

  \t\tvar shape = div.firstChild;
  \t\tshape.style.behavior = 'url(#default#VML)';

  \t\treturn shape && (typeof shape.adj === 'object');

  \t} catch (e) {
  \t\treturn false;
  \t}
  }());


  // @property mac: Boolean; `true` when the browser is running in a Mac platform
  var mac = navigator.platform.indexOf('Mac') === 0;

  // @property mac: Boolean; `true` when the browser is running in a Linux platform
  var linux = navigator.platform.indexOf('Linux') === 0;

  function userAgentContains(str) {
  \treturn navigator.userAgent.toLowerCase().indexOf(str) >= 0;
  }


  var Browser = {
  \tie: ie,
  \tielt9: ielt9,
  \tedge: edge,
  \twebkit: webkit,
  \tandroid: android,
  \tandroid23: android23,
  \tandroidStock: androidStock,
  \topera: opera,
  \tchrome: chrome,
  \tgecko: gecko,
  \tsafari: safari,
  \tphantom: phantom,
  \topera12: opera12,
  \twin: win,
  \tie3d: ie3d,
  \twebkit3d: webkit3d,
  \tgecko3d: gecko3d,
  \tany3d: any3d,
  \tmobile: mobile,
  \tmobileWebkit: mobileWebkit,
  \tmobileWebkit3d: mobileWebkit3d,
  \tmsPointer: msPointer,
  \tpointer: pointer,
  \ttouch: touch,
  \ttouchNative: touchNative,
  \tmobileOpera: mobileOpera,
  \tmobileGecko: mobileGecko,
  \tretina: retina,
  \tpassiveEvents: passiveEvents,
  \tcanvas: canvas\$1,
  \tsvg: svg\$1,
  \tvml: vml,
  \tinlineSvg: inlineSvg,
  \tmac: mac,
  \tlinux: linux
  };

  /*
   * Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices.
   */

  var POINTER_DOWN =   Browser.msPointer ? 'MSPointerDown'   : 'pointerdown';
  var POINTER_MOVE =   Browser.msPointer ? 'MSPointerMove'   : 'pointermove';
  var POINTER_UP =     Browser.msPointer ? 'MSPointerUp'     : 'pointerup';
  var POINTER_CANCEL = Browser.msPointer ? 'MSPointerCancel' : 'pointercancel';
  var pEvent = {
  \ttouchstart  : POINTER_DOWN,
  \ttouchmove   : POINTER_MOVE,
  \ttouchend    : POINTER_UP,
  \ttouchcancel : POINTER_CANCEL
  };
  var handle = {
  \ttouchstart  : _onPointerStart,
  \ttouchmove   : _handlePointer,
  \ttouchend    : _handlePointer,
  \ttouchcancel : _handlePointer
  };
  var _pointers = {};
  var _pointerDocListener = false;

  // Provides a touch events wrapper for (ms)pointer events.
  // ref https://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890

  function addPointerListener(obj, type, handler) {
  \tif (type === 'touchstart') {
  \t\t_addPointerDocListener();
  \t}
  \tif (!handle[type]) {
  \t\tconsole.warn('wrong event specified:', type);
  \t\treturn falseFn;
  \t}
  \thandler = handle[type].bind(this, handler);
  \tobj.addEventListener(pEvent[type], handler, false);
  \treturn handler;
  }

  function removePointerListener(obj, type, handler) {
  \tif (!pEvent[type]) {
  \t\tconsole.warn('wrong event specified:', type);
  \t\treturn;
  \t}
  \tobj.removeEventListener(pEvent[type], handler, false);
  }

  function _globalPointerDown(e) {
  \t_pointers[e.pointerId] = e;
  }

  function _globalPointerMove(e) {
  \tif (_pointers[e.pointerId]) {
  \t\t_pointers[e.pointerId] = e;
  \t}
  }

  function _globalPointerUp(e) {
  \tdelete _pointers[e.pointerId];
  }

  function _addPointerDocListener() {
  \t// need to keep track of what pointers and how many are active to provide e.touches emulation
  \tif (!_pointerDocListener) {
  \t\t// we listen document as any drags that end by moving the touch off the screen get fired there
  \t\tdocument.addEventListener(POINTER_DOWN, _globalPointerDown, true);
  \t\tdocument.addEventListener(POINTER_MOVE, _globalPointerMove, true);
  \t\tdocument.addEventListener(POINTER_UP, _globalPointerUp, true);
  \t\tdocument.addEventListener(POINTER_CANCEL, _globalPointerUp, true);

  \t\t_pointerDocListener = true;
  \t}
  }

  function _handlePointer(handler, e) {
  \tif (e.pointerType === (e.MSPOINTER_TYPE_MOUSE || 'mouse')) { return; }

  \te.touches = [];
  \tfor (var i in _pointers) {
  \t\te.touches.push(_pointers[i]);
  \t}
  \te.changedTouches = [e];

  \thandler(e);
  }

  function _onPointerStart(handler, e) {
  \t// IE10 specific: MsTouch needs preventDefault. See #2000
  \tif (e.MSPOINTER_TYPE_TOUCH && e.pointerType === e.MSPOINTER_TYPE_TOUCH) {
  \t\tpreventDefault(e);
  \t}
  \t_handlePointer(handler, e);
  }

  /*
   * Extends the event handling code with double tap support for mobile browsers.
   *
   * Note: currently most browsers fire native dblclick, with only a few exceptions
   * (see https://github.com/Leaflet/Leaflet/issues/7012#issuecomment-595087386)
   */

  function makeDblclick(event) {
  \t// in modern browsers `type` cannot be just overridden:
  \t// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Getter_only
  \tvar newEvent = {},
  \t    prop, i;
  \tfor (i in event) {
  \t\tprop = event[i];
  \t\tnewEvent[i] = prop && prop.bind ? prop.bind(event) : prop;
  \t}
  \tevent = newEvent;
  \tnewEvent.type = 'dblclick';
  \tnewEvent.detail = 2;
  \tnewEvent.isTrusted = false;
  \tnewEvent._simulated = true; // for debug purposes
  \treturn newEvent;
  }

  var delay = 200;
  function addDoubleTapListener(obj, handler) {
  \t// Most browsers handle double tap natively
  \tobj.addEventListener('dblclick', handler);

  \t// On some platforms the browser doesn't fire native dblclicks for touch events.
  \t// It seems that in all such cases `detail` property of `click` event is always `1`.
  \t// So here we rely on that fact to avoid excessive 'dblclick' simulation when not needed.
  \tvar last = 0,
  \t    detail;
  \tfunction simDblclick(e) {
  \t\tif (e.detail !== 1) {
  \t\t\tdetail = e.detail; // keep in sync to avoid false dblclick in some cases
  \t\t\treturn;
  \t\t}

  \t\tif (e.pointerType === 'mouse' ||
  \t\t\t(e.sourceCapabilities && !e.sourceCapabilities.firesTouchEvents)) {

  \t\t\treturn;
  \t\t}

  \t\t// When clicking on an <input>, the browser generates a click on its
  \t\t// <label> (and vice versa) triggering two clicks in quick succession.
  \t\t// This ignores clicks on elements which are a label with a 'for'
  \t\t// attribute (or children of such a label), but not children of
  \t\t// a <input>.
  \t\tvar path = getPropagationPath(e);
  \t\tif (path.some(function (el) {
  \t\t\treturn el instanceof HTMLLabelElement && el.attributes.for;
  \t\t}) &&
  \t\t\t!path.some(function (el) {
  \t\t\t\treturn (
  \t\t\t\t\tel instanceof HTMLInputElement ||
  \t\t\t\t\tel instanceof HTMLSelectElement
  \t\t\t\t);
  \t\t\t})
  \t\t) {
  \t\t\treturn;
  \t\t}

  \t\tvar now = Date.now();
  \t\tif (now - last <= delay) {
  \t\t\tdetail++;
  \t\t\tif (detail === 2) {
  \t\t\t\thandler(makeDblclick(e));
  \t\t\t}
  \t\t} else {
  \t\t\tdetail = 1;
  \t\t}
  \t\tlast = now;
  \t}

  \tobj.addEventListener('click', simDblclick);

  \treturn {
  \t\tdblclick: handler,
  \t\tsimDblclick: simDblclick
  \t};
  }

  function removeDoubleTapListener(obj, handlers) {
  \tobj.removeEventListener('dblclick', handlers.dblclick);
  \tobj.removeEventListener('click', handlers.simDblclick);
  }

  /*
   * @namespace DomUtil
   *
   * Utility functions to work with the [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model)
   * tree, used by Leaflet internally.
   *
   * Most functions expecting or returning a `HTMLElement` also work for
   * SVG elements. The only difference is that classes refer to CSS classes
   * in HTML and SVG classes in SVG.
   */


  // @property TRANSFORM: String
  // Vendor-prefixed transform style name (e.g. `'webkitTransform'` for WebKit).
  var TRANSFORM = testProp(
  \t['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform']);

  // webkitTransition comes first because some browser versions that drop vendor prefix don't do
  // the same for the transitionend event, in particular the Android 4.1 stock browser

  // @property TRANSITION: String
  // Vendor-prefixed transition style name.
  var TRANSITION = testProp(
  \t['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']);

  // @property TRANSITION_END: String
  // Vendor-prefixed transitionend event name.
  var TRANSITION_END =
  \tTRANSITION === 'webkitTransition' || TRANSITION === 'OTransition' ? TRANSITION + 'End' : 'transitionend';


  // @function get(id: String|HTMLElement): HTMLElement
  // Returns an element given its DOM id, or returns the element itself
  // if it was passed directly.
  function get(id) {
  \treturn typeof id === 'string' ? document.getElementById(id) : id;
  }

  // @function getStyle(el: HTMLElement, styleAttrib: String): String
  // Returns the value for a certain style attribute on an element,
  // including computed values or values set through CSS.
  function getStyle(el, style) {
  \tvar value = el.style[style] || (el.currentStyle && el.currentStyle[style]);

  \tif ((!value || value === 'auto') && document.defaultView) {
  \t\tvar css = document.defaultView.getComputedStyle(el, null);
  \t\tvalue = css ? css[style] : null;
  \t}
  \treturn value === 'auto' ? null : value;
  }

  // @function create(tagName: String, className?: String, container?: HTMLElement): HTMLElement
  // Creates an HTML element with `tagName`, sets its class to `className`, and optionally appends it to `container` element.
  function create\$1(tagName, className, container) {
  \tvar el = document.createElement(tagName);
  \tel.className = className || '';

  \tif (container) {
  \t\tcontainer.appendChild(el);
  \t}
  \treturn el;
  }

  // @function remove(el: HTMLElement)
  // Removes `el` from its parent element
  function remove(el) {
  \tvar parent = el.parentNode;
  \tif (parent) {
  \t\tparent.removeChild(el);
  \t}
  }

  // @function empty(el: HTMLElement)
  // Removes all of `el`'s children elements from `el`
  function empty(el) {
  \twhile (el.firstChild) {
  \t\tel.removeChild(el.firstChild);
  \t}
  }

  // @function toFront(el: HTMLElement)
  // Makes `el` the last child of its parent, so it renders in front of the other children.
  function toFront(el) {
  \tvar parent = el.parentNode;
  \tif (parent && parent.lastChild !== el) {
  \t\tparent.appendChild(el);
  \t}
  }

  // @function toBack(el: HTMLElement)
  // Makes `el` the first child of its parent, so it renders behind the other children.
  function toBack(el) {
  \tvar parent = el.parentNode;
  \tif (parent && parent.firstChild !== el) {
  \t\tparent.insertBefore(el, parent.firstChild);
  \t}
  }

  // @function hasClass(el: HTMLElement, name: String): Boolean
  // Returns `true` if the element's class attribute contains `name`.
  function hasClass(el, name) {
  \tif (el.classList !== undefined) {
  \t\treturn el.classList.contains(name);
  \t}
  \tvar className = getClass(el);
  \treturn className.length > 0 && new RegExp('(^|\\\\s)' + name + '(\\\\s|\$)').test(className);
  }

  // @function addClass(el: HTMLElement, name: String)
  // Adds `name` to the element's class attribute.
  function addClass(el, name) {
  \tif (el.classList !== undefined) {
  \t\tvar classes = splitWords(name);
  \t\tfor (var i = 0, len = classes.length; i < len; i++) {
  \t\t\tel.classList.add(classes[i]);
  \t\t}
  \t} else if (!hasClass(el, name)) {
  \t\tvar className = getClass(el);
  \t\tsetClass(el, (className ? className + ' ' : '') + name);
  \t}
  }

  // @function removeClass(el: HTMLElement, name: String)
  // Removes `name` from the element's class attribute.
  function removeClass(el, name) {
  \tif (el.classList !== undefined) {
  \t\tel.classList.remove(name);
  \t} else {
  \t\tsetClass(el, trim((' ' + getClass(el) + ' ').replace(' ' + name + ' ', ' ')));
  \t}
  }

  // @function setClass(el: HTMLElement, name: String)
  // Sets the element's class.
  function setClass(el, name) {
  \tif (el.className.baseVal === undefined) {
  \t\tel.className = name;
  \t} else {
  \t\t// in case of SVG element
  \t\tel.className.baseVal = name;
  \t}
  }

  // @function getClass(el: HTMLElement): String
  // Returns the element's class.
  function getClass(el) {
  \t// Check if the element is an SVGElementInstance and use the correspondingElement instead
  \t// (Required for linked SVG elements in IE11.)
  \tif (el.correspondingElement) {
  \t\tel = el.correspondingElement;
  \t}
  \treturn el.className.baseVal === undefined ? el.className : el.className.baseVal;
  }

  // @function setOpacity(el: HTMLElement, opacity: Number)
  // Set the opacity of an element (including old IE support).
  // `opacity` must be a number from `0` to `1`.
  function setOpacity(el, value) {
  \tif ('opacity' in el.style) {
  \t\tel.style.opacity = value;
  \t} else if ('filter' in el.style) {
  \t\t_setOpacityIE(el, value);
  \t}
  }

  function _setOpacityIE(el, value) {
  \tvar filter = false,
  \t    filterName = 'DXImageTransform.Microsoft.Alpha';

  \t// filters collection throws an error if we try to retrieve a filter that doesn't exist
  \ttry {
  \t\tfilter = el.filters.item(filterName);
  \t} catch (e) {
  \t\t// don't set opacity to 1 if we haven't already set an opacity,
  \t\t// it isn't needed and breaks transparent pngs.
  \t\tif (value === 1) { return; }
  \t}

  \tvalue = Math.round(value * 100);

  \tif (filter) {
  \t\tfilter.Enabled = (value !== 100);
  \t\tfilter.Opacity = value;
  \t} else {
  \t\tel.style.filter += ' progid:' + filterName + '(opacity=' + value + ')';
  \t}
  }

  // @function testProp(props: String[]): String|false
  // Goes through the array of style names and returns the first name
  // that is a valid style name for an element. If no such name is found,
  // it returns false. Useful for vendor-prefixed styles like `transform`.
  function testProp(props) {
  \tvar style = document.documentElement.style;

  \tfor (var i = 0; i < props.length; i++) {
  \t\tif (props[i] in style) {
  \t\t\treturn props[i];
  \t\t}
  \t}
  \treturn false;
  }

  // @function setTransform(el: HTMLElement, offset: Point, scale?: Number)
  // Resets the 3D CSS transform of `el` so it is translated by `offset` pixels
  // and optionally scaled by `scale`. Does not have an effect if the
  // browser doesn't support 3D CSS transforms.
  function setTransform(el, offset, scale) {
  \tvar pos = offset || new Point(0, 0);

  \tel.style[TRANSFORM] =
  \t\t(Browser.ie3d ?
  \t\t\t'translate(' + pos.x + 'px,' + pos.y + 'px)' :
  \t\t\t'translate3d(' + pos.x + 'px,' + pos.y + 'px,0)') +
  \t\t(scale ? ' scale(' + scale + ')' : '');
  }

  // @function setPosition(el: HTMLElement, position: Point)
  // Sets the position of `el` to coordinates specified by `position`,
  // using CSS translate or top/left positioning depending on the browser
  // (used by Leaflet internally to position its layers).
  function setPosition(el, point) {

  \t/*eslint-disable */
  \tel._leaflet_pos = point;
  \t/* eslint-enable */

  \tif (Browser.any3d) {
  \t\tsetTransform(el, point);
  \t} else {
  \t\tel.style.left = point.x + 'px';
  \t\tel.style.top = point.y + 'px';
  \t}
  }

  // @function getPosition(el: HTMLElement): Point
  // Returns the coordinates of an element previously positioned with setPosition.
  function getPosition(el) {
  \t// this method is only used for elements previously positioned using setPosition,
  \t// so it's safe to cache the position for performance

  \treturn el._leaflet_pos || new Point(0, 0);
  }

  // @function disableTextSelection()
  // Prevents the user from generating `selectstart` DOM events, usually generated
  // when the user drags the mouse through a page with text. Used internally
  // by Leaflet to override the behaviour of any click-and-drag interaction on
  // the map. Affects drag interactions on the whole document.

  // @function enableTextSelection()
  // Cancels the effects of a previous [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection).
  var disableTextSelection;
  var enableTextSelection;
  var _userSelect;
  if ('onselectstart' in document) {
  \tdisableTextSelection = function () {
  \t\ton(window, 'selectstart', preventDefault);
  \t};
  \tenableTextSelection = function () {
  \t\toff(window, 'selectstart', preventDefault);
  \t};
  } else {
  \tvar userSelectProperty = testProp(
  \t\t['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']);

  \tdisableTextSelection = function () {
  \t\tif (userSelectProperty) {
  \t\t\tvar style = document.documentElement.style;
  \t\t\t_userSelect = style[userSelectProperty];
  \t\t\tstyle[userSelectProperty] = 'none';
  \t\t}
  \t};
  \tenableTextSelection = function () {
  \t\tif (userSelectProperty) {
  \t\t\tdocument.documentElement.style[userSelectProperty] = _userSelect;
  \t\t\t_userSelect = undefined;
  \t\t}
  \t};
  }

  // @function disableImageDrag()
  // As [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection), but
  // for `dragstart` DOM events, usually generated when the user drags an image.
  function disableImageDrag() {
  \ton(window, 'dragstart', preventDefault);
  }

  // @function enableImageDrag()
  // Cancels the effects of a previous [`L.DomUtil.disableImageDrag`](#domutil-disabletextselection).
  function enableImageDrag() {
  \toff(window, 'dragstart', preventDefault);
  }

  var _outlineElement, _outlineStyle;
  // @function preventOutline(el: HTMLElement)
  // Makes the [outline](https://developer.mozilla.org/docs/Web/CSS/outline)
  // of the element `el` invisible. Used internally by Leaflet to prevent
  // focusable elements from displaying an outline when the user performs a
  // drag interaction on them.
  function preventOutline(element) {
  \twhile (element.tabIndex === -1) {
  \t\telement = element.parentNode;
  \t}
  \tif (!element.style) { return; }
  \trestoreOutline();
  \t_outlineElement = element;
  \t_outlineStyle = element.style.outlineStyle;
  \telement.style.outlineStyle = 'none';
  \ton(window, 'keydown', restoreOutline);
  }

  // @function restoreOutline()
  // Cancels the effects of a previous [`L.DomUtil.preventOutline`]().
  function restoreOutline() {
  \tif (!_outlineElement) { return; }
  \t_outlineElement.style.outlineStyle = _outlineStyle;
  \t_outlineElement = undefined;
  \t_outlineStyle = undefined;
  \toff(window, 'keydown', restoreOutline);
  }

  // @function getSizedParentNode(el: HTMLElement): HTMLElement
  // Finds the closest parent node which size (width and height) is not null.
  function getSizedParentNode(element) {
  \tdo {
  \t\telement = element.parentNode;
  \t} while ((!element.offsetWidth || !element.offsetHeight) && element !== document.body);
  \treturn element;
  }

  // @function getScale(el: HTMLElement): Object
  // Computes the CSS scale currently applied on the element.
  // Returns an object with `x` and `y` members as horizontal and vertical scales respectively,
  // and `boundingClientRect` as the result of [`getBoundingClientRect()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect).
  function getScale(element) {
  \tvar rect = element.getBoundingClientRect(); // Read-only in old browsers.

  \treturn {
  \t\tx: rect.width / element.offsetWidth || 1,
  \t\ty: rect.height / element.offsetHeight || 1,
  \t\tboundingClientRect: rect
  \t};
  }

  var DomUtil = {
    __proto__: null,
    TRANSFORM: TRANSFORM,
    TRANSITION: TRANSITION,
    TRANSITION_END: TRANSITION_END,
    get: get,
    getStyle: getStyle,
    create: create\$1,
    remove: remove,
    empty: empty,
    toFront: toFront,
    toBack: toBack,
    hasClass: hasClass,
    addClass: addClass,
    removeClass: removeClass,
    setClass: setClass,
    getClass: getClass,
    setOpacity: setOpacity,
    testProp: testProp,
    setTransform: setTransform,
    setPosition: setPosition,
    getPosition: getPosition,
    get disableTextSelection () { return disableTextSelection; },
    get enableTextSelection () { return enableTextSelection; },
    disableImageDrag: disableImageDrag,
    enableImageDrag: enableImageDrag,
    preventOutline: preventOutline,
    restoreOutline: restoreOutline,
    getSizedParentNode: getSizedParentNode,
    getScale: getScale
  };

  /*
   * @namespace DomEvent
   * Utility functions to work with the [DOM events](https://developer.mozilla.org/docs/Web/API/Event), used by Leaflet internally.
   */

  // Inspired by John Resig, Dean Edwards and YUI addEvent implementations.

  // @function on(el: HTMLElement, types: String, fn: Function, context?: Object): this
  // Adds a listener function (`fn`) to a particular DOM event type of the
  // element `el`. You can optionally specify the context of the listener
  // (object the `this` keyword will point to). You can also pass several
  // space-separated types (e.g. `'click dblclick'`).

  // @alternative
  // @function on(el: HTMLElement, eventMap: Object, context?: Object): this
  // Adds a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}`
  function on(obj, types, fn, context) {

  \tif (types && typeof types === 'object') {
  \t\tfor (var type in types) {
  \t\t\taddOne(obj, type, types[type], fn);
  \t\t}
  \t} else {
  \t\ttypes = splitWords(types);

  \t\tfor (var i = 0, len = types.length; i < len; i++) {
  \t\t\taddOne(obj, types[i], fn, context);
  \t\t}
  \t}

  \treturn this;
  }

  var eventsKey = '_leaflet_events';

  // @function off(el: HTMLElement, types: String, fn: Function, context?: Object): this
  // Removes a previously added listener function.
  // Note that if you passed a custom context to on, you must pass the same
  // context to `off` in order to remove the listener.

  // @alternative
  // @function off(el: HTMLElement, eventMap: Object, context?: Object): this
  // Removes a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}`

  // @alternative
  // @function off(el: HTMLElement, types: String): this
  // Removes all previously added listeners of given types.

  // @alternative
  // @function off(el: HTMLElement): this
  // Removes all previously added listeners from given HTMLElement
  function off(obj, types, fn, context) {

  \tif (arguments.length === 1) {
  \t\tbatchRemove(obj);
  \t\tdelete obj[eventsKey];

  \t} else if (types && typeof types === 'object') {
  \t\tfor (var type in types) {
  \t\t\tremoveOne(obj, type, types[type], fn);
  \t\t}

  \t} else {
  \t\ttypes = splitWords(types);

  \t\tif (arguments.length === 2) {
  \t\t\tbatchRemove(obj, function (type) {
  \t\t\t\treturn indexOf(types, type) !== -1;
  \t\t\t});
  \t\t} else {
  \t\t\tfor (var i = 0, len = types.length; i < len; i++) {
  \t\t\t\tremoveOne(obj, types[i], fn, context);
  \t\t\t}
  \t\t}
  \t}

  \treturn this;
  }

  function batchRemove(obj, filterFn) {
  \tfor (var id in obj[eventsKey]) {
  \t\tvar type = id.split(/\\d/)[0];
  \t\tif (!filterFn || filterFn(type)) {
  \t\t\tremoveOne(obj, type, null, null, id);
  \t\t}
  \t}
  }

  var mouseSubst = {
  \tmouseenter: 'mouseover',
  \tmouseleave: 'mouseout',
  \twheel: !('onwheel' in window) && 'mousewheel'
  };

  function addOne(obj, type, fn, context) {
  \tvar id = type + stamp(fn) + (context ? '_' + stamp(context) : '');

  \tif (obj[eventsKey] && obj[eventsKey][id]) { return this; }

  \tvar handler = function (e) {
  \t\treturn fn.call(context || obj, e || window.event);
  \t};

  \tvar originalHandler = handler;

  \tif (!Browser.touchNative && Browser.pointer && type.indexOf('touch') === 0) {
  \t\t// Needs DomEvent.Pointer.js
  \t\thandler = addPointerListener(obj, type, handler);

  \t} else if (Browser.touch && (type === 'dblclick')) {
  \t\thandler = addDoubleTapListener(obj, handler);

  \t} else if ('addEventListener' in obj) {

  \t\tif (type === 'touchstart' || type === 'touchmove' || type === 'wheel' ||  type === 'mousewheel') {
  \t\t\tobj.addEventListener(mouseSubst[type] || type, handler, Browser.passiveEvents ? {passive: false} : false);

  \t\t} else if (type === 'mouseenter' || type === 'mouseleave') {
  \t\t\thandler = function (e) {
  \t\t\t\te = e || window.event;
  \t\t\t\tif (isExternalTarget(obj, e)) {
  \t\t\t\t\toriginalHandler(e);
  \t\t\t\t}
  \t\t\t};
  \t\t\tobj.addEventListener(mouseSubst[type], handler, false);

  \t\t} else {
  \t\t\tobj.addEventListener(type, originalHandler, false);
  \t\t}

  \t} else {
  \t\tobj.attachEvent('on' + type, handler);
  \t}

  \tobj[eventsKey] = obj[eventsKey] || {};
  \tobj[eventsKey][id] = handler;
  }

  function removeOne(obj, type, fn, context, id) {
  \tid = id || type + stamp(fn) + (context ? '_' + stamp(context) : '');
  \tvar handler = obj[eventsKey] && obj[eventsKey][id];

  \tif (!handler) { return this; }

  \tif (!Browser.touchNative && Browser.pointer && type.indexOf('touch') === 0) {
  \t\tremovePointerListener(obj, type, handler);

  \t} else if (Browser.touch && (type === 'dblclick')) {
  \t\tremoveDoubleTapListener(obj, handler);

  \t} else if ('removeEventListener' in obj) {

  \t\tobj.removeEventListener(mouseSubst[type] || type, handler, false);

  \t} else {
  \t\tobj.detachEvent('on' + type, handler);
  \t}

  \tobj[eventsKey][id] = null;
  }

  // @function stopPropagation(ev: DOMEvent): this
  // Stop the given event from propagation to parent elements. Used inside the listener functions:
  // ```js
  // L.DomEvent.on(div, 'click', function (ev) {
  // \tL.DomEvent.stopPropagation(ev);
  // });
  // ```
  function stopPropagation(e) {

  \tif (e.stopPropagation) {
  \t\te.stopPropagation();
  \t} else if (e.originalEvent) {  // In case of Leaflet event.
  \t\te.originalEvent._stopped = true;
  \t} else {
  \t\te.cancelBubble = true;
  \t}

  \treturn this;
  }

  // @function disableScrollPropagation(el: HTMLElement): this
  // Adds `stopPropagation` to the element's `'wheel'` events (plus browser variants).
  function disableScrollPropagation(el) {
  \taddOne(el, 'wheel', stopPropagation);
  \treturn this;
  }

  // @function disableClickPropagation(el: HTMLElement): this
  // Adds `stopPropagation` to the element's `'click'`, `'dblclick'`, `'contextmenu'`,
  // `'mousedown'` and `'touchstart'` events (plus browser variants).
  function disableClickPropagation(el) {
  \ton(el, 'mousedown touchstart dblclick contextmenu', stopPropagation);
  \tel['_leaflet_disable_click'] = true;
  \treturn this;
  }

  // @function preventDefault(ev: DOMEvent): this
  // Prevents the default action of the DOM Event `ev` from happening (such as
  // following a link in the href of the a element, or doing a POST request
  // with page reload when a `<form>` is submitted).
  // Use it inside listener functions.
  function preventDefault(e) {
  \tif (e.preventDefault) {
  \t\te.preventDefault();
  \t} else {
  \t\te.returnValue = false;
  \t}
  \treturn this;
  }

  // @function stop(ev: DOMEvent): this
  // Does `stopPropagation` and `preventDefault` at the same time.
  function stop(e) {
  \tpreventDefault(e);
  \tstopPropagation(e);
  \treturn this;
  }

  // @function getPropagationPath(ev: DOMEvent): Array
  // Compatibility polyfill for [`Event.composedPath()`](https://developer.mozilla.org/en-US/docs/Web/API/Event/composedPath).
  // Returns an array containing the `HTMLElement`s that the given DOM event
  // should propagate to (if not stopped).
  function getPropagationPath(ev) {
  \tif (ev.composedPath) {
  \t\treturn ev.composedPath();
  \t}

  \tvar path = [];
  \tvar el = ev.target;

  \twhile (el) {
  \t\tpath.push(el);
  \t\tel = el.parentNode;
  \t}
  \treturn path;
  }


  // @function getMousePosition(ev: DOMEvent, container?: HTMLElement): Point
  // Gets normalized mouse position from a DOM event relative to the
  // `container` (border excluded) or to the whole page if not specified.
  function getMousePosition(e, container) {
  \tif (!container) {
  \t\treturn new Point(e.clientX, e.clientY);
  \t}

  \tvar scale = getScale(container),
  \t    offset = scale.boundingClientRect; // left and top  values are in page scale (like the event clientX/Y)

  \treturn new Point(
  \t\t// offset.left/top values are in page scale (like clientX/Y),
  \t\t// whereas clientLeft/Top (border width) values are the original values (before CSS scale applies).
  \t\t(e.clientX - offset.left) / scale.x - container.clientLeft,
  \t\t(e.clientY - offset.top) / scale.y - container.clientTop
  \t);
  }


  //  except , Safari and
  // We need double the scroll pixels (see #7403 and #4538) for all Browsers
  // except OSX (Mac) -> 3x, Chrome running on Linux 1x

  var wheelPxFactor =
  \t(Browser.linux && Browser.chrome) ? window.devicePixelRatio :
  \tBrowser.mac ? window.devicePixelRatio * 3 :
  \twindow.devicePixelRatio > 0 ? 2 * window.devicePixelRatio : 1;
  // @function getWheelDelta(ev: DOMEvent): Number
  // Gets normalized wheel delta from a wheel DOM event, in vertical
  // pixels scrolled (negative if scrolling down).
  // Events from pointing devices without precise scrolling are mapped to
  // a best guess of 60 pixels.
  function getWheelDelta(e) {
  \treturn (Browser.edge) ? e.wheelDeltaY / 2 : // Don't trust window-geometry-based delta
  \t       (e.deltaY && e.deltaMode === 0) ? -e.deltaY / wheelPxFactor : // Pixels
  \t       (e.deltaY && e.deltaMode === 1) ? -e.deltaY * 20 : // Lines
  \t       (e.deltaY && e.deltaMode === 2) ? -e.deltaY * 60 : // Pages
  \t       (e.deltaX || e.deltaZ) ? 0 :\t// Skip horizontal/depth wheel events
  \t       e.wheelDelta ? (e.wheelDeltaY || e.wheelDelta) / 2 : // Legacy IE pixels
  \t       (e.detail && Math.abs(e.detail) < 32765) ? -e.detail * 20 : // Legacy Moz lines
  \t       e.detail ? e.detail / -32765 * 60 : // Legacy Moz pages
  \t       0;
  }

  // check if element really left/entered the event target (for mouseenter/mouseleave)
  function isExternalTarget(el, e) {

  \tvar related = e.relatedTarget;

  \tif (!related) { return true; }

  \ttry {
  \t\twhile (related && (related !== el)) {
  \t\t\trelated = related.parentNode;
  \t\t}
  \t} catch (err) {
  \t\treturn false;
  \t}
  \treturn (related !== el);
  }

  var DomEvent = {
    __proto__: null,
    on: on,
    off: off,
    stopPropagation: stopPropagation,
    disableScrollPropagation: disableScrollPropagation,
    disableClickPropagation: disableClickPropagation,
    preventDefault: preventDefault,
    stop: stop,
    getPropagationPath: getPropagationPath,
    getMousePosition: getMousePosition,
    getWheelDelta: getWheelDelta,
    isExternalTarget: isExternalTarget,
    addListener: on,
    removeListener: off
  };

  /*
   * @class PosAnimation
   * @aka L.PosAnimation
   * @inherits Evented
   * Used internally for panning animations, utilizing CSS3 Transitions for modern browsers and a timer fallback for IE6-9.
   *
   * @example
   * ```js
   * var myPositionMarker = L.marker([48.864716, 2.294694]).addTo(map);
   *
   * myPositionMarker.on(\"click\", function() {
   * \tvar pos = map.latLngToLayerPoint(myPositionMarker.getLatLng());
   * \tpos.y -= 25;
   * \tvar fx = new L.PosAnimation();
   *
   * \tfx.once('end',function() {
   * \t\tpos.y += 25;
   * \t\tfx.run(myPositionMarker._icon, pos, 0.8);
   * \t});
   *
   * \tfx.run(myPositionMarker._icon, pos, 0.3);
   * });
   *
   * ```
   *
   * @constructor L.PosAnimation()
   * Creates a `PosAnimation` object.
   *
   */

  var PosAnimation = Evented.extend({

  \t// @method run(el: HTMLElement, newPos: Point, duration?: Number, easeLinearity?: Number)
  \t// Run an animation of a given element to a new position, optionally setting
  \t// duration in seconds (`0.25` by default) and easing linearity factor (3rd
  \t// argument of the [cubic bezier curve](https://cubic-bezier.com/#0,0,.5,1),
  \t// `0.5` by default).
  \trun: function (el, newPos, duration, easeLinearity) {
  \t\tthis.stop();

  \t\tthis._el = el;
  \t\tthis._inProgress = true;
  \t\tthis._duration = duration || 0.25;
  \t\tthis._easeOutPower = 1 / Math.max(easeLinearity || 0.5, 0.2);

  \t\tthis._startPos = getPosition(el);
  \t\tthis._offset = newPos.subtract(this._startPos);
  \t\tthis._startTime = +new Date();

  \t\t// @event start: Event
  \t\t// Fired when the animation starts
  \t\tthis.fire('start');

  \t\tthis._animate();
  \t},

  \t// @method stop()
  \t// Stops the animation (if currently running).
  \tstop: function () {
  \t\tif (!this._inProgress) { return; }

  \t\tthis._step(true);
  \t\tthis._complete();
  \t},

  \t_animate: function () {
  \t\t// animation loop
  \t\tthis._animId = requestAnimFrame(this._animate, this);
  \t\tthis._step();
  \t},

  \t_step: function (round) {
  \t\tvar elapsed = (+new Date()) - this._startTime,
  \t\t    duration = this._duration * 1000;

  \t\tif (elapsed < duration) {
  \t\t\tthis._runFrame(this._easeOut(elapsed / duration), round);
  \t\t} else {
  \t\t\tthis._runFrame(1);
  \t\t\tthis._complete();
  \t\t}
  \t},

  \t_runFrame: function (progress, round) {
  \t\tvar pos = this._startPos.add(this._offset.multiplyBy(progress));
  \t\tif (round) {
  \t\t\tpos._round();
  \t\t}
  \t\tsetPosition(this._el, pos);

  \t\t// @event step: Event
  \t\t// Fired continuously during the animation.
  \t\tthis.fire('step');
  \t},

  \t_complete: function () {
  \t\tcancelAnimFrame(this._animId);

  \t\tthis._inProgress = false;
  \t\t// @event end: Event
  \t\t// Fired when the animation ends.
  \t\tthis.fire('end');
  \t},

  \t_easeOut: function (t) {
  \t\treturn 1 - Math.pow(1 - t, this._easeOutPower);
  \t}
  });

  /*
   * @class Map
   * @aka L.Map
   * @inherits Evented
   *
   * The central class of the API — it is used to create a map on a page and manipulate it.
   *
   * @example
   *
   * ```js
   * // initialize the map on the \"map\" div with a given center and zoom
   * var map = L.map('map', {
   * \tcenter: [51.505, -0.09],
   * \tzoom: 13
   * });
   * ```
   *
   */

  var Map = Evented.extend({

  \toptions: {
  \t\t// @section Map State Options
  \t\t// @option crs: CRS = L.CRS.EPSG3857
  \t\t// The [Coordinate Reference System](#crs) to use. Don't change this if you're not
  \t\t// sure what it means.
  \t\tcrs: EPSG3857,

  \t\t// @option center: LatLng = undefined
  \t\t// Initial geographic center of the map
  \t\tcenter: undefined,

  \t\t// @option zoom: Number = undefined
  \t\t// Initial map zoom level
  \t\tzoom: undefined,

  \t\t// @option minZoom: Number = *
  \t\t// Minimum zoom level of the map.
  \t\t// If not specified and at least one `GridLayer` or `TileLayer` is in the map,
  \t\t// the lowest of their `minZoom` options will be used instead.
  \t\tminZoom: undefined,

  \t\t// @option maxZoom: Number = *
  \t\t// Maximum zoom level of the map.
  \t\t// If not specified and at least one `GridLayer` or `TileLayer` is in the map,
  \t\t// the highest of their `maxZoom` options will be used instead.
  \t\tmaxZoom: undefined,

  \t\t// @option layers: Layer[] = []
  \t\t// Array of layers that will be added to the map initially
  \t\tlayers: [],

  \t\t// @option maxBounds: LatLngBounds = null
  \t\t// When this option is set, the map restricts the view to the given
  \t\t// geographical bounds, bouncing the user back if the user tries to pan
  \t\t// outside the view. To set the restriction dynamically, use
  \t\t// [`setMaxBounds`](#map-setmaxbounds) method.
  \t\tmaxBounds: undefined,

  \t\t// @option renderer: Renderer = *
  \t\t// The default method for drawing vector layers on the map. `L.SVG`
  \t\t// or `L.Canvas` by default depending on browser support.
  \t\trenderer: undefined,


  \t\t// @section Animation Options
  \t\t// @option zoomAnimation: Boolean = true
  \t\t// Whether the map zoom animation is enabled. By default it's enabled
  \t\t// in all browsers that support CSS3 Transitions except Android.
  \t\tzoomAnimation: true,

  \t\t// @option zoomAnimationThreshold: Number = 4
  \t\t// Won't animate zoom if the zoom difference exceeds this value.
  \t\tzoomAnimationThreshold: 4,

  \t\t// @option fadeAnimation: Boolean = true
  \t\t// Whether the tile fade animation is enabled. By default it's enabled
  \t\t// in all browsers that support CSS3 Transitions except Android.
  \t\tfadeAnimation: true,

  \t\t// @option markerZoomAnimation: Boolean = true
  \t\t// Whether markers animate their zoom with the zoom animation, if disabled
  \t\t// they will disappear for the length of the animation. By default it's
  \t\t// enabled in all browsers that support CSS3 Transitions except Android.
  \t\tmarkerZoomAnimation: true,

  \t\t// @option transform3DLimit: Number = 2^23
  \t\t// Defines the maximum size of a CSS translation transform. The default
  \t\t// value should not be changed unless a web browser positions layers in
  \t\t// the wrong place after doing a large `panBy`.
  \t\ttransform3DLimit: 8388608, // Precision limit of a 32-bit float

  \t\t// @section Interaction Options
  \t\t// @option zoomSnap: Number = 1
  \t\t// Forces the map's zoom level to always be a multiple of this, particularly
  \t\t// right after a [`fitBounds()`](#map-fitbounds) or a pinch-zoom.
  \t\t// By default, the zoom level snaps to the nearest integer; lower values
  \t\t// (e.g. `0.5` or `0.1`) allow for greater granularity. A value of `0`
  \t\t// means the zoom level will not be snapped after `fitBounds` or a pinch-zoom.
  \t\tzoomSnap: 1,

  \t\t// @option zoomDelta: Number = 1
  \t\t// Controls how much the map's zoom level will change after a
  \t\t// [`zoomIn()`](#map-zoomin), [`zoomOut()`](#map-zoomout), pressing `+`
  \t\t// or `-` on the keyboard, or using the [zoom controls](#control-zoom).
  \t\t// Values smaller than `1` (e.g. `0.5`) allow for greater granularity.
  \t\tzoomDelta: 1,

  \t\t// @option trackResize: Boolean = true
  \t\t// Whether the map automatically handles browser window resize to update itself.
  \t\ttrackResize: true
  \t},

  \tinitialize: function (id, options) { // (HTMLElement or String, Object)
  \t\toptions = setOptions(this, options);

  \t\t// Make sure to assign internal flags at the beginning,
  \t\t// to avoid inconsistent state in some edge cases.
  \t\tthis._handlers = [];
  \t\tthis._layers = {};
  \t\tthis._zoomBoundLayers = {};
  \t\tthis._sizeChanged = true;

  \t\tthis._initContainer(id);
  \t\tthis._initLayout();

  \t\t// hack for https://github.com/Leaflet/Leaflet/issues/1980
  \t\tthis._onResize = bind(this._onResize, this);

  \t\tthis._initEvents();

  \t\tif (options.maxBounds) {
  \t\t\tthis.setMaxBounds(options.maxBounds);
  \t\t}

  \t\tif (options.zoom !== undefined) {
  \t\t\tthis._zoom = this._limitZoom(options.zoom);
  \t\t}

  \t\tif (options.center && options.zoom !== undefined) {
  \t\t\tthis.setView(toLatLng(options.center), options.zoom, {reset: true});
  \t\t}

  \t\tthis.callInitHooks();

  \t\t// don't animate on browsers without hardware-accelerated transitions or old Android/Opera
  \t\tthis._zoomAnimated = TRANSITION && Browser.any3d && !Browser.mobileOpera &&
  \t\t\t\tthis.options.zoomAnimation;

  \t\t// zoom transitions run with the same duration for all layers, so if one of transitionend events
  \t\t// happens after starting zoom animation (propagating to the map pane), we know that it ended globally
  \t\tif (this._zoomAnimated) {
  \t\t\tthis._createAnimProxy();
  \t\t\ton(this._proxy, TRANSITION_END, this._catchTransitionEnd, this);
  \t\t}

  \t\tthis._addLayers(this.options.layers);
  \t},


  \t// @section Methods for modifying map state

  \t// @method setView(center: LatLng, zoom: Number, options?: Zoom/pan options): this
  \t// Sets the view of the map (geographical center and zoom) with the given
  \t// animation options.
  \tsetView: function (center, zoom, options) {

  \t\tzoom = zoom === undefined ? this._zoom : this._limitZoom(zoom);
  \t\tcenter = this._limitCenter(toLatLng(center), zoom, this.options.maxBounds);
  \t\toptions = options || {};

  \t\tthis._stop();

  \t\tif (this._loaded && !options.reset && options !== true) {

  \t\t\tif (options.animate !== undefined) {
  \t\t\t\toptions.zoom = extend({animate: options.animate}, options.zoom);
  \t\t\t\toptions.pan = extend({animate: options.animate, duration: options.duration}, options.pan);
  \t\t\t}

  \t\t\t// try animating pan or zoom
  \t\t\tvar moved = (this._zoom !== zoom) ?
  \t\t\t\tthis._tryAnimatedZoom && this._tryAnimatedZoom(center, zoom, options.zoom) :
  \t\t\t\tthis._tryAnimatedPan(center, options.pan);

  \t\t\tif (moved) {
  \t\t\t\t// prevent resize handler call, the view will refresh after animation anyway
  \t\t\t\tclearTimeout(this._sizeTimer);
  \t\t\t\treturn this;
  \t\t\t}
  \t\t}

  \t\t// animation didn't start, just reset the map view
  \t\tthis._resetView(center, zoom, options.pan && options.pan.noMoveStart);

  \t\treturn this;
  \t},

  \t// @method setZoom(zoom: Number, options?: Zoom/pan options): this
  \t// Sets the zoom of the map.
  \tsetZoom: function (zoom, options) {
  \t\tif (!this._loaded) {
  \t\t\tthis._zoom = zoom;
  \t\t\treturn this;
  \t\t}
  \t\treturn this.setView(this.getCenter(), zoom, {zoom: options});
  \t},

  \t// @method zoomIn(delta?: Number, options?: Zoom options): this
  \t// Increases the zoom of the map by `delta` ([`zoomDelta`](#map-zoomdelta) by default).
  \tzoomIn: function (delta, options) {
  \t\tdelta = delta || (Browser.any3d ? this.options.zoomDelta : 1);
  \t\treturn this.setZoom(this._zoom + delta, options);
  \t},

  \t// @method zoomOut(delta?: Number, options?: Zoom options): this
  \t// Decreases the zoom of the map by `delta` ([`zoomDelta`](#map-zoomdelta) by default).
  \tzoomOut: function (delta, options) {
  \t\tdelta = delta || (Browser.any3d ? this.options.zoomDelta : 1);
  \t\treturn this.setZoom(this._zoom - delta, options);
  \t},

  \t// @method setZoomAround(latlng: LatLng, zoom: Number, options: Zoom options): this
  \t// Zooms the map while keeping a specified geographical point on the map
  \t// stationary (e.g. used internally for scroll zoom and double-click zoom).
  \t// @alternative
  \t// @method setZoomAround(offset: Point, zoom: Number, options: Zoom options): this
  \t// Zooms the map while keeping a specified pixel on the map (relative to the top-left corner) stationary.
  \tsetZoomAround: function (latlng, zoom, options) {
  \t\tvar scale = this.getZoomScale(zoom),
  \t\t    viewHalf = this.getSize().divideBy(2),
  \t\t    containerPoint = latlng instanceof Point ? latlng : this.latLngToContainerPoint(latlng),

  \t\t    centerOffset = containerPoint.subtract(viewHalf).multiplyBy(1 - 1 / scale),
  \t\t    newCenter = this.containerPointToLatLng(viewHalf.add(centerOffset));

  \t\treturn this.setView(newCenter, zoom, {zoom: options});
  \t},

  \t_getBoundsCenterZoom: function (bounds, options) {

  \t\toptions = options || {};
  \t\tbounds = bounds.getBounds ? bounds.getBounds() : toLatLngBounds(bounds);

  \t\tvar paddingTL = toPoint(options.paddingTopLeft || options.padding || [0, 0]),
  \t\t    paddingBR = toPoint(options.paddingBottomRight || options.padding || [0, 0]),

  \t\t    zoom = this.getBoundsZoom(bounds, false, paddingTL.add(paddingBR));

  \t\tzoom = (typeof options.maxZoom === 'number') ? Math.min(options.maxZoom, zoom) : zoom;

  \t\tif (zoom === Infinity) {
  \t\t\treturn {
  \t\t\t\tcenter: bounds.getCenter(),
  \t\t\t\tzoom: zoom
  \t\t\t};
  \t\t}

  \t\tvar paddingOffset = paddingBR.subtract(paddingTL).divideBy(2),

  \t\t    swPoint = this.project(bounds.getSouthWest(), zoom),
  \t\t    nePoint = this.project(bounds.getNorthEast(), zoom),
  \t\t    center = this.unproject(swPoint.add(nePoint).divideBy(2).add(paddingOffset), zoom);

  \t\treturn {
  \t\t\tcenter: center,
  \t\t\tzoom: zoom
  \t\t};
  \t},

  \t// @method fitBounds(bounds: LatLngBounds, options?: fitBounds options): this
  \t// Sets a map view that contains the given geographical bounds with the
  \t// maximum zoom level possible.
  \tfitBounds: function (bounds, options) {

  \t\tbounds = toLatLngBounds(bounds);

  \t\tif (!bounds.isValid()) {
  \t\t\tthrow new Error('Bounds are not valid.');
  \t\t}

  \t\tvar target = this._getBoundsCenterZoom(bounds, options);
  \t\treturn this.setView(target.center, target.zoom, options);
  \t},

  \t// @method fitWorld(options?: fitBounds options): this
  \t// Sets a map view that mostly contains the whole world with the maximum
  \t// zoom level possible.
  \tfitWorld: function (options) {
  \t\treturn this.fitBounds([[-90, -180], [90, 180]], options);
  \t},

  \t// @method panTo(latlng: LatLng, options?: Pan options): this
  \t// Pans the map to a given center.
  \tpanTo: function (center, options) { // (LatLng)
  \t\treturn this.setView(center, this._zoom, {pan: options});
  \t},

  \t// @method panBy(offset: Point, options?: Pan options): this
  \t// Pans the map by a given number of pixels (animated).
  \tpanBy: function (offset, options) {
  \t\toffset = toPoint(offset).round();
  \t\toptions = options || {};

  \t\tif (!offset.x && !offset.y) {
  \t\t\treturn this.fire('moveend');
  \t\t}
  \t\t// If we pan too far, Chrome gets issues with tiles
  \t\t// and makes them disappear or appear in the wrong place (slightly offset) #2602
  \t\tif (options.animate !== true && !this.getSize().contains(offset)) {
  \t\t\tthis._resetView(this.unproject(this.project(this.getCenter()).add(offset)), this.getZoom());
  \t\t\treturn this;
  \t\t}

  \t\tif (!this._panAnim) {
  \t\t\tthis._panAnim = new PosAnimation();

  \t\t\tthis._panAnim.on({
  \t\t\t\t'step': this._onPanTransitionStep,
  \t\t\t\t'end': this._onPanTransitionEnd
  \t\t\t}, this);
  \t\t}

  \t\t// don't fire movestart if animating inertia
  \t\tif (!options.noMoveStart) {
  \t\t\tthis.fire('movestart');
  \t\t}

  \t\t// animate pan unless animate: false specified
  \t\tif (options.animate !== false) {
  \t\t\taddClass(this._mapPane, 'leaflet-pan-anim');

  \t\t\tvar newPos = this._getMapPanePos().subtract(offset).round();
  \t\t\tthis._panAnim.run(this._mapPane, newPos, options.duration || 0.25, options.easeLinearity);
  \t\t} else {
  \t\t\tthis._rawPanBy(offset);
  \t\t\tthis.fire('move').fire('moveend');
  \t\t}

  \t\treturn this;
  \t},

  \t// @method flyTo(latlng: LatLng, zoom?: Number, options?: Zoom/pan options): this
  \t// Sets the view of the map (geographical center and zoom) performing a smooth
  \t// pan-zoom animation.
  \tflyTo: function (targetCenter, targetZoom, options) {

  \t\toptions = options || {};
  \t\tif (options.animate === false || !Browser.any3d) {
  \t\t\treturn this.setView(targetCenter, targetZoom, options);
  \t\t}

  \t\tthis._stop();

  \t\tvar from = this.project(this.getCenter()),
  \t\t    to = this.project(targetCenter),
  \t\t    size = this.getSize(),
  \t\t    startZoom = this._zoom;

  \t\ttargetCenter = toLatLng(targetCenter);
  \t\ttargetZoom = targetZoom === undefined ? startZoom : targetZoom;

  \t\tvar w0 = Math.max(size.x, size.y),
  \t\t    w1 = w0 * this.getZoomScale(startZoom, targetZoom),
  \t\t    u1 = (to.distanceTo(from)) || 1,
  \t\t    rho = 1.42,
  \t\t    rho2 = rho * rho;

  \t\tfunction r(i) {
  \t\t\tvar s1 = i ? -1 : 1,
  \t\t\t    s2 = i ? w1 : w0,
  \t\t\t    t1 = w1 * w1 - w0 * w0 + s1 * rho2 * rho2 * u1 * u1,
  \t\t\t    b1 = 2 * s2 * rho2 * u1,
  \t\t\t    b = t1 / b1,
  \t\t\t    sq = Math.sqrt(b * b + 1) - b;

  \t\t\t    // workaround for floating point precision bug when sq = 0, log = -Infinite,
  \t\t\t    // thus triggering an infinite loop in flyTo
  \t\t\t    var log = sq < 0.000000001 ? -18 : Math.log(sq);

  \t\t\treturn log;
  \t\t}

  \t\tfunction sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; }
  \t\tfunction cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; }
  \t\tfunction tanh(n) { return sinh(n) / cosh(n); }

  \t\tvar r0 = r(0);

  \t\tfunction w(s) { return w0 * (cosh(r0) / cosh(r0 + rho * s)); }
  \t\tfunction u(s) { return w0 * (cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2; }

  \t\tfunction easeOut(t) { return 1 - Math.pow(1 - t, 1.5); }

  \t\tvar start = Date.now(),
  \t\t    S = (r(1) - r0) / rho,
  \t\t    duration = options.duration ? 1000 * options.duration : 1000 * S * 0.8;

  \t\tfunction frame() {
  \t\t\tvar t = (Date.now() - start) / duration,
  \t\t\t    s = easeOut(t) * S;

  \t\t\tif (t <= 1) {
  \t\t\t\tthis._flyToFrame = requestAnimFrame(frame, this);

  \t\t\t\tthis._move(
  \t\t\t\t\tthis.unproject(from.add(to.subtract(from).multiplyBy(u(s) / u1)), startZoom),
  \t\t\t\t\tthis.getScaleZoom(w0 / w(s), startZoom),
  \t\t\t\t\t{flyTo: true});

  \t\t\t} else {
  \t\t\t\tthis
  \t\t\t\t\t._move(targetCenter, targetZoom)
  \t\t\t\t\t._moveEnd(true);
  \t\t\t}
  \t\t}

  \t\tthis._moveStart(true, options.noMoveStart);

  \t\tframe.call(this);
  \t\treturn this;
  \t},

  \t// @method flyToBounds(bounds: LatLngBounds, options?: fitBounds options): this
  \t// Sets the view of the map with a smooth animation like [`flyTo`](#map-flyto),
  \t// but takes a bounds parameter like [`fitBounds`](#map-fitbounds).
  \tflyToBounds: function (bounds, options) {
  \t\tvar target = this._getBoundsCenterZoom(bounds, options);
  \t\treturn this.flyTo(target.center, target.zoom, options);
  \t},

  \t// @method setMaxBounds(bounds: LatLngBounds): this
  \t// Restricts the map view to the given bounds (see the [maxBounds](#map-maxbounds) option).
  \tsetMaxBounds: function (bounds) {
  \t\tbounds = toLatLngBounds(bounds);

  \t\tif (this.listens('moveend', this._panInsideMaxBounds)) {
  \t\t\tthis.off('moveend', this._panInsideMaxBounds);
  \t\t}

  \t\tif (!bounds.isValid()) {
  \t\t\tthis.options.maxBounds = null;
  \t\t\treturn this;
  \t\t}

  \t\tthis.options.maxBounds = bounds;

  \t\tif (this._loaded) {
  \t\t\tthis._panInsideMaxBounds();
  \t\t}

  \t\treturn this.on('moveend', this._panInsideMaxBounds);
  \t},

  \t// @method setMinZoom(zoom: Number): this
  \t// Sets the lower limit for the available zoom levels (see the [minZoom](#map-minzoom) option).
  \tsetMinZoom: function (zoom) {
  \t\tvar oldZoom = this.options.minZoom;
  \t\tthis.options.minZoom = zoom;

  \t\tif (this._loaded && oldZoom !== zoom) {
  \t\t\tthis.fire('zoomlevelschange');

  \t\t\tif (this.getZoom() < this.options.minZoom) {
  \t\t\t\treturn this.setZoom(zoom);
  \t\t\t}
  \t\t}

  \t\treturn this;
  \t},

  \t// @method setMaxZoom(zoom: Number): this
  \t// Sets the upper limit for the available zoom levels (see the [maxZoom](#map-maxzoom) option).
  \tsetMaxZoom: function (zoom) {
  \t\tvar oldZoom = this.options.maxZoom;
  \t\tthis.options.maxZoom = zoom;

  \t\tif (this._loaded && oldZoom !== zoom) {
  \t\t\tthis.fire('zoomlevelschange');

  \t\t\tif (this.getZoom() > this.options.maxZoom) {
  \t\t\t\treturn this.setZoom(zoom);
  \t\t\t}
  \t\t}

  \t\treturn this;
  \t},

  \t// @method panInsideBounds(bounds: LatLngBounds, options?: Pan options): this
  \t// Pans the map to the closest view that would lie inside the given bounds (if it's not already), controlling the animation using the options specific, if any.
  \tpanInsideBounds: function (bounds, options) {
  \t\tthis._enforcingBounds = true;
  \t\tvar center = this.getCenter(),
  \t\t    newCenter = this._limitCenter(center, this._zoom, toLatLngBounds(bounds));

  \t\tif (!center.equals(newCenter)) {
  \t\t\tthis.panTo(newCenter, options);
  \t\t}

  \t\tthis._enforcingBounds = false;
  \t\treturn this;
  \t},

  \t// @method panInside(latlng: LatLng, options?: padding options): this
  \t// Pans the map the minimum amount to make the `latlng` visible. Use
  \t// padding options to fit the display to more restricted bounds.
  \t// If `latlng` is already within the (optionally padded) display bounds,
  \t// the map will not be panned.
  \tpanInside: function (latlng, options) {
  \t\toptions = options || {};

  \t\tvar paddingTL = toPoint(options.paddingTopLeft || options.padding || [0, 0]),
  \t\t    paddingBR = toPoint(options.paddingBottomRight || options.padding || [0, 0]),
  \t\t    pixelCenter = this.project(this.getCenter()),
  \t\t    pixelPoint = this.project(latlng),
  \t\t    pixelBounds = this.getPixelBounds(),
  \t\t    paddedBounds = toBounds([pixelBounds.min.add(paddingTL), pixelBounds.max.subtract(paddingBR)]),
  \t\t    paddedSize = paddedBounds.getSize();

  \t\tif (!paddedBounds.contains(pixelPoint)) {
  \t\t\tthis._enforcingBounds = true;
  \t\t\tvar centerOffset = pixelPoint.subtract(paddedBounds.getCenter());
  \t\t\tvar offset = paddedBounds.extend(pixelPoint).getSize().subtract(paddedSize);
  \t\t\tpixelCenter.x += centerOffset.x < 0 ? -offset.x : offset.x;
  \t\t\tpixelCenter.y += centerOffset.y < 0 ? -offset.y : offset.y;
  \t\t\tthis.panTo(this.unproject(pixelCenter), options);
  \t\t\tthis._enforcingBounds = false;
  \t\t}
  \t\treturn this;
  \t},

  \t// @method invalidateSize(options: Zoom/pan options): this
  \t// Checks if the map container size changed and updates the map if so —
  \t// call it after you've changed the map size dynamically, also animating
  \t// pan by default. If `options.pan` is `false`, panning will not occur.
  \t// If `options.debounceMoveend` is `true`, it will delay `moveend` event so
  \t// that it doesn't happen often even if the method is called many
  \t// times in a row.

  \t// @alternative
  \t// @method invalidateSize(animate: Boolean): this
  \t// Checks if the map container size changed and updates the map if so —
  \t// call it after you've changed the map size dynamically, also animating
  \t// pan by default.
  \tinvalidateSize: function (options) {
  \t\tif (!this._loaded) { return this; }

  \t\toptions = extend({
  \t\t\tanimate: false,
  \t\t\tpan: true
  \t\t}, options === true ? {animate: true} : options);

  \t\tvar oldSize = this.getSize();
  \t\tthis._sizeChanged = true;
  \t\tthis._lastCenter = null;

  \t\tvar newSize = this.getSize(),
  \t\t    oldCenter = oldSize.divideBy(2).round(),
  \t\t    newCenter = newSize.divideBy(2).round(),
  \t\t    offset = oldCenter.subtract(newCenter);

  \t\tif (!offset.x && !offset.y) { return this; }

  \t\tif (options.animate && options.pan) {
  \t\t\tthis.panBy(offset);

  \t\t} else {
  \t\t\tif (options.pan) {
  \t\t\t\tthis._rawPanBy(offset);
  \t\t\t}

  \t\t\tthis.fire('move');

  \t\t\tif (options.debounceMoveend) {
  \t\t\t\tclearTimeout(this._sizeTimer);
  \t\t\t\tthis._sizeTimer = setTimeout(bind(this.fire, this, 'moveend'), 200);
  \t\t\t} else {
  \t\t\t\tthis.fire('moveend');
  \t\t\t}
  \t\t}

  \t\t// @section Map state change events
  \t\t// @event resize: ResizeEvent
  \t\t// Fired when the map is resized.
  \t\treturn this.fire('resize', {
  \t\t\toldSize: oldSize,
  \t\t\tnewSize: newSize
  \t\t});
  \t},

  \t// @section Methods for modifying map state
  \t// @method stop(): this
  \t// Stops the currently running `panTo` or `flyTo` animation, if any.
  \tstop: function () {
  \t\tthis.setZoom(this._limitZoom(this._zoom));
  \t\tif (!this.options.zoomSnap) {
  \t\t\tthis.fire('viewreset');
  \t\t}
  \t\treturn this._stop();
  \t},

  \t// @section Geolocation methods
  \t// @method locate(options?: Locate options): this
  \t// Tries to locate the user using the Geolocation API, firing a [`locationfound`](#map-locationfound)
  \t// event with location data on success or a [`locationerror`](#map-locationerror) event on failure,
  \t// and optionally sets the map view to the user's location with respect to
  \t// detection accuracy (or to the world view if geolocation failed).
  \t// Note that, if your page doesn't use HTTPS, this method will fail in
  \t// modern browsers ([Chrome 50 and newer](https://sites.google.com/a/chromium.org/dev/Home/chromium-security/deprecating-powerful-features-on-insecure-origins))
  \t// See `Locate options` for more details.
  \tlocate: function (options) {

  \t\toptions = this._locateOptions = extend({
  \t\t\ttimeout: 10000,
  \t\t\twatch: false
  \t\t\t// setView: false
  \t\t\t// maxZoom: <Number>
  \t\t\t// maximumAge: 0
  \t\t\t// enableHighAccuracy: false
  \t\t}, options);

  \t\tif (!('geolocation' in navigator)) {
  \t\t\tthis._handleGeolocationError({
  \t\t\t\tcode: 0,
  \t\t\t\tmessage: 'Geolocation not supported.'
  \t\t\t});
  \t\t\treturn this;
  \t\t}

  \t\tvar onResponse = bind(this._handleGeolocationResponse, this),
  \t\t    onError = bind(this._handleGeolocationError, this);

  \t\tif (options.watch) {
  \t\t\tthis._locationWatchId =
  \t\t\t        navigator.geolocation.watchPosition(onResponse, onError, options);
  \t\t} else {
  \t\t\tnavigator.geolocation.getCurrentPosition(onResponse, onError, options);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method stopLocate(): this
  \t// Stops watching location previously initiated by `map.locate({watch: true})`
  \t// and aborts resetting the map view if map.locate was called with
  \t// `{setView: true}`.
  \tstopLocate: function () {
  \t\tif (navigator.geolocation && navigator.geolocation.clearWatch) {
  \t\t\tnavigator.geolocation.clearWatch(this._locationWatchId);
  \t\t}
  \t\tif (this._locateOptions) {
  \t\t\tthis._locateOptions.setView = false;
  \t\t}
  \t\treturn this;
  \t},

  \t_handleGeolocationError: function (error) {
  \t\tif (!this._container._leaflet_id) { return; }

  \t\tvar c = error.code,
  \t\t    message = error.message ||
  \t\t            (c === 1 ? 'permission denied' :
  \t\t            (c === 2 ? 'position unavailable' : 'timeout'));

  \t\tif (this._locateOptions.setView && !this._loaded) {
  \t\t\tthis.fitWorld();
  \t\t}

  \t\t// @section Location events
  \t\t// @event locationerror: ErrorEvent
  \t\t// Fired when geolocation (using the [`locate`](#map-locate) method) failed.
  \t\tthis.fire('locationerror', {
  \t\t\tcode: c,
  \t\t\tmessage: 'Geolocation error: ' + message + '.'
  \t\t});
  \t},

  \t_handleGeolocationResponse: function (pos) {
  \t\tif (!this._container._leaflet_id) { return; }

  \t\tvar lat = pos.coords.latitude,
  \t\t    lng = pos.coords.longitude,
  \t\t    latlng = new LatLng(lat, lng),
  \t\t    bounds = latlng.toBounds(pos.coords.accuracy * 2),
  \t\t    options = this._locateOptions;

  \t\tif (options.setView) {
  \t\t\tvar zoom = this.getBoundsZoom(bounds);
  \t\t\tthis.setView(latlng, options.maxZoom ? Math.min(zoom, options.maxZoom) : zoom);
  \t\t}

  \t\tvar data = {
  \t\t\tlatlng: latlng,
  \t\t\tbounds: bounds,
  \t\t\ttimestamp: pos.timestamp
  \t\t};

  \t\tfor (var i in pos.coords) {
  \t\t\tif (typeof pos.coords[i] === 'number') {
  \t\t\t\tdata[i] = pos.coords[i];
  \t\t\t}
  \t\t}

  \t\t// @event locationfound: LocationEvent
  \t\t// Fired when geolocation (using the [`locate`](#map-locate) method)
  \t\t// went successfully.
  \t\tthis.fire('locationfound', data);
  \t},

  \t// TODO Appropriate docs section?
  \t// @section Other Methods
  \t// @method addHandler(name: String, HandlerClass: Function): this
  \t// Adds a new `Handler` to the map, given its name and constructor function.
  \taddHandler: function (name, HandlerClass) {
  \t\tif (!HandlerClass) { return this; }

  \t\tvar handler = this[name] = new HandlerClass(this);

  \t\tthis._handlers.push(handler);

  \t\tif (this.options[name]) {
  \t\t\thandler.enable();
  \t\t}

  \t\treturn this;
  \t},

  \t// @method remove(): this
  \t// Destroys the map and clears all related event listeners.
  \tremove: function () {

  \t\tthis._initEvents(true);
  \t\tif (this.options.maxBounds) { this.off('moveend', this._panInsideMaxBounds); }

  \t\tif (this._containerId !== this._container._leaflet_id) {
  \t\t\tthrow new Error('Map container is being reused by another instance');
  \t\t}

  \t\ttry {
  \t\t\t// throws error in IE6-8
  \t\t\tdelete this._container._leaflet_id;
  \t\t\tdelete this._containerId;
  \t\t} catch (e) {
  \t\t\t/*eslint-disable */
  \t\t\tthis._container._leaflet_id = undefined;
  \t\t\t/* eslint-enable */
  \t\t\tthis._containerId = undefined;
  \t\t}

  \t\tif (this._locationWatchId !== undefined) {
  \t\t\tthis.stopLocate();
  \t\t}

  \t\tthis._stop();

  \t\tremove(this._mapPane);

  \t\tif (this._clearControlPos) {
  \t\t\tthis._clearControlPos();
  \t\t}
  \t\tif (this._resizeRequest) {
  \t\t\tcancelAnimFrame(this._resizeRequest);
  \t\t\tthis._resizeRequest = null;
  \t\t}

  \t\tthis._clearHandlers();

  \t\tif (this._loaded) {
  \t\t\t// @section Map state change events
  \t\t\t// @event unload: Event
  \t\t\t// Fired when the map is destroyed with [remove](#map-remove) method.
  \t\t\tthis.fire('unload');
  \t\t}

  \t\tvar i;
  \t\tfor (i in this._layers) {
  \t\t\tthis._layers[i].remove();
  \t\t}
  \t\tfor (i in this._panes) {
  \t\t\tremove(this._panes[i]);
  \t\t}

  \t\tthis._layers = [];
  \t\tthis._panes = [];
  \t\tdelete this._mapPane;
  \t\tdelete this._renderer;

  \t\treturn this;
  \t},

  \t// @section Other Methods
  \t// @method createPane(name: String, container?: HTMLElement): HTMLElement
  \t// Creates a new [map pane](#map-pane) with the given name if it doesn't exist already,
  \t// then returns it. The pane is created as a child of `container`, or
  \t// as a child of the main map pane if not set.
  \tcreatePane: function (name, container) {
  \t\tvar className = 'leaflet-pane' + (name ? ' leaflet-' + name.replace('Pane', '') + '-pane' : ''),
  \t\t    pane = create\$1('div', className, container || this._mapPane);

  \t\tif (name) {
  \t\t\tthis._panes[name] = pane;
  \t\t}
  \t\treturn pane;
  \t},

  \t// @section Methods for Getting Map State

  \t// @method getCenter(): LatLng
  \t// Returns the geographical center of the map view
  \tgetCenter: function () {
  \t\tthis._checkIfLoaded();

  \t\tif (this._lastCenter && !this._moved()) {
  \t\t\treturn this._lastCenter.clone();
  \t\t}
  \t\treturn this.layerPointToLatLng(this._getCenterLayerPoint());
  \t},

  \t// @method getZoom(): Number
  \t// Returns the current zoom level of the map view
  \tgetZoom: function () {
  \t\treturn this._zoom;
  \t},

  \t// @method getBounds(): LatLngBounds
  \t// Returns the geographical bounds visible in the current map view
  \tgetBounds: function () {
  \t\tvar bounds = this.getPixelBounds(),
  \t\t    sw = this.unproject(bounds.getBottomLeft()),
  \t\t    ne = this.unproject(bounds.getTopRight());

  \t\treturn new LatLngBounds(sw, ne);
  \t},

  \t// @method getMinZoom(): Number
  \t// Returns the minimum zoom level of the map (if set in the `minZoom` option of the map or of any layers), or `0` by default.
  \tgetMinZoom: function () {
  \t\treturn this.options.minZoom === undefined ? this._layersMinZoom || 0 : this.options.minZoom;
  \t},

  \t// @method getMaxZoom(): Number
  \t// Returns the maximum zoom level of the map (if set in the `maxZoom` option of the map or of any layers).
  \tgetMaxZoom: function () {
  \t\treturn this.options.maxZoom === undefined ?
  \t\t\t(this._layersMaxZoom === undefined ? Infinity : this._layersMaxZoom) :
  \t\t\tthis.options.maxZoom;
  \t},

  \t// @method getBoundsZoom(bounds: LatLngBounds, inside?: Boolean, padding?: Point): Number
  \t// Returns the maximum zoom level on which the given bounds fit to the map
  \t// view in its entirety. If `inside` (optional) is set to `true`, the method
  \t// instead returns the minimum zoom level on which the map view fits into
  \t// the given bounds in its entirety.
  \tgetBoundsZoom: function (bounds, inside, padding) { // (LatLngBounds[, Boolean, Point]) -> Number
  \t\tbounds = toLatLngBounds(bounds);
  \t\tpadding = toPoint(padding || [0, 0]);

  \t\tvar zoom = this.getZoom() || 0,
  \t\t    min = this.getMinZoom(),
  \t\t    max = this.getMaxZoom(),
  \t\t    nw = bounds.getNorthWest(),
  \t\t    se = bounds.getSouthEast(),
  \t\t    size = this.getSize().subtract(padding),
  \t\t    boundsSize = toBounds(this.project(se, zoom), this.project(nw, zoom)).getSize(),
  \t\t    snap = Browser.any3d ? this.options.zoomSnap : 1,
  \t\t    scalex = size.x / boundsSize.x,
  \t\t    scaley = size.y / boundsSize.y,
  \t\t    scale = inside ? Math.max(scalex, scaley) : Math.min(scalex, scaley);

  \t\tzoom = this.getScaleZoom(scale, zoom);

  \t\tif (snap) {
  \t\t\tzoom = Math.round(zoom / (snap / 100)) * (snap / 100); // don't jump if within 1% of a snap level
  \t\t\tzoom = inside ? Math.ceil(zoom / snap) * snap : Math.floor(zoom / snap) * snap;
  \t\t}

  \t\treturn Math.max(min, Math.min(max, zoom));
  \t},

  \t// @method getSize(): Point
  \t// Returns the current size of the map container (in pixels).
  \tgetSize: function () {
  \t\tif (!this._size || this._sizeChanged) {
  \t\t\tthis._size = new Point(
  \t\t\t\tthis._container.clientWidth || 0,
  \t\t\t\tthis._container.clientHeight || 0);

  \t\t\tthis._sizeChanged = false;
  \t\t}
  \t\treturn this._size.clone();
  \t},

  \t// @method getPixelBounds(): Bounds
  \t// Returns the bounds of the current map view in projected pixel
  \t// coordinates (sometimes useful in layer and overlay implementations).
  \tgetPixelBounds: function (center, zoom) {
  \t\tvar topLeftPoint = this._getTopLeftPoint(center, zoom);
  \t\treturn new Bounds(topLeftPoint, topLeftPoint.add(this.getSize()));
  \t},

  \t// TODO: Check semantics - isn't the pixel origin the 0,0 coord relative to
  \t// the map pane? \"left point of the map layer\" can be confusing, specially
  \t// since there can be negative offsets.
  \t// @method getPixelOrigin(): Point
  \t// Returns the projected pixel coordinates of the top left point of
  \t// the map layer (useful in custom layer and overlay implementations).
  \tgetPixelOrigin: function () {
  \t\tthis._checkIfLoaded();
  \t\treturn this._pixelOrigin;
  \t},

  \t// @method getPixelWorldBounds(zoom?: Number): Bounds
  \t// Returns the world's bounds in pixel coordinates for zoom level `zoom`.
  \t// If `zoom` is omitted, the map's current zoom level is used.
  \tgetPixelWorldBounds: function (zoom) {
  \t\treturn this.options.crs.getProjectedBounds(zoom === undefined ? this.getZoom() : zoom);
  \t},

  \t// @section Other Methods

  \t// @method getPane(pane: String|HTMLElement): HTMLElement
  \t// Returns a [map pane](#map-pane), given its name or its HTML element (its identity).
  \tgetPane: function (pane) {
  \t\treturn typeof pane === 'string' ? this._panes[pane] : pane;
  \t},

  \t// @method getPanes(): Object
  \t// Returns a plain object containing the names of all [panes](#map-pane) as keys and
  \t// the panes as values.
  \tgetPanes: function () {
  \t\treturn this._panes;
  \t},

  \t// @method getContainer: HTMLElement
  \t// Returns the HTML element that contains the map.
  \tgetContainer: function () {
  \t\treturn this._container;
  \t},


  \t// @section Conversion Methods

  \t// @method getZoomScale(toZoom: Number, fromZoom: Number): Number
  \t// Returns the scale factor to be applied to a map transition from zoom level
  \t// `fromZoom` to `toZoom`. Used internally to help with zoom animations.
  \tgetZoomScale: function (toZoom, fromZoom) {
  \t\t// TODO replace with universal implementation after refactoring projections
  \t\tvar crs = this.options.crs;
  \t\tfromZoom = fromZoom === undefined ? this._zoom : fromZoom;
  \t\treturn crs.scale(toZoom) / crs.scale(fromZoom);
  \t},

  \t// @method getScaleZoom(scale: Number, fromZoom: Number): Number
  \t// Returns the zoom level that the map would end up at, if it is at `fromZoom`
  \t// level and everything is scaled by a factor of `scale`. Inverse of
  \t// [`getZoomScale`](#map-getZoomScale).
  \tgetScaleZoom: function (scale, fromZoom) {
  \t\tvar crs = this.options.crs;
  \t\tfromZoom = fromZoom === undefined ? this._zoom : fromZoom;
  \t\tvar zoom = crs.zoom(scale * crs.scale(fromZoom));
  \t\treturn isNaN(zoom) ? Infinity : zoom;
  \t},

  \t// @method project(latlng: LatLng, zoom: Number): Point
  \t// Projects a geographical coordinate `LatLng` according to the projection
  \t// of the map's CRS, then scales it according to `zoom` and the CRS's
  \t// `Transformation`. The result is pixel coordinate relative to
  \t// the CRS origin.
  \tproject: function (latlng, zoom) {
  \t\tzoom = zoom === undefined ? this._zoom : zoom;
  \t\treturn this.options.crs.latLngToPoint(toLatLng(latlng), zoom);
  \t},

  \t// @method unproject(point: Point, zoom: Number): LatLng
  \t// Inverse of [`project`](#map-project).
  \tunproject: function (point, zoom) {
  \t\tzoom = zoom === undefined ? this._zoom : zoom;
  \t\treturn this.options.crs.pointToLatLng(toPoint(point), zoom);
  \t},

  \t// @method layerPointToLatLng(point: Point): LatLng
  \t// Given a pixel coordinate relative to the [origin pixel](#map-getpixelorigin),
  \t// returns the corresponding geographical coordinate (for the current zoom level).
  \tlayerPointToLatLng: function (point) {
  \t\tvar projectedPoint = toPoint(point).add(this.getPixelOrigin());
  \t\treturn this.unproject(projectedPoint);
  \t},

  \t// @method latLngToLayerPoint(latlng: LatLng): Point
  \t// Given a geographical coordinate, returns the corresponding pixel coordinate
  \t// relative to the [origin pixel](#map-getpixelorigin).
  \tlatLngToLayerPoint: function (latlng) {
  \t\tvar projectedPoint = this.project(toLatLng(latlng))._round();
  \t\treturn projectedPoint._subtract(this.getPixelOrigin());
  \t},

  \t// @method wrapLatLng(latlng: LatLng): LatLng
  \t// Returns a `LatLng` where `lat` and `lng` has been wrapped according to the
  \t// map's CRS's `wrapLat` and `wrapLng` properties, if they are outside the
  \t// CRS's bounds.
  \t// By default this means longitude is wrapped around the dateline so its
  \t// value is between -180 and +180 degrees.
  \twrapLatLng: function (latlng) {
  \t\treturn this.options.crs.wrapLatLng(toLatLng(latlng));
  \t},

  \t// @method wrapLatLngBounds(bounds: LatLngBounds): LatLngBounds
  \t// Returns a `LatLngBounds` with the same size as the given one, ensuring that
  \t// its center is within the CRS's bounds.
  \t// By default this means the center longitude is wrapped around the dateline so its
  \t// value is between -180 and +180 degrees, and the majority of the bounds
  \t// overlaps the CRS's bounds.
  \twrapLatLngBounds: function (latlng) {
  \t\treturn this.options.crs.wrapLatLngBounds(toLatLngBounds(latlng));
  \t},

  \t// @method distance(latlng1: LatLng, latlng2: LatLng): Number
  \t// Returns the distance between two geographical coordinates according to
  \t// the map's CRS. By default this measures distance in meters.
  \tdistance: function (latlng1, latlng2) {
  \t\treturn this.options.crs.distance(toLatLng(latlng1), toLatLng(latlng2));
  \t},

  \t// @method containerPointToLayerPoint(point: Point): Point
  \t// Given a pixel coordinate relative to the map container, returns the corresponding
  \t// pixel coordinate relative to the [origin pixel](#map-getpixelorigin).
  \tcontainerPointToLayerPoint: function (point) { // (Point)
  \t\treturn toPoint(point).subtract(this._getMapPanePos());
  \t},

  \t// @method layerPointToContainerPoint(point: Point): Point
  \t// Given a pixel coordinate relative to the [origin pixel](#map-getpixelorigin),
  \t// returns the corresponding pixel coordinate relative to the map container.
  \tlayerPointToContainerPoint: function (point) { // (Point)
  \t\treturn toPoint(point).add(this._getMapPanePos());
  \t},

  \t// @method containerPointToLatLng(point: Point): LatLng
  \t// Given a pixel coordinate relative to the map container, returns
  \t// the corresponding geographical coordinate (for the current zoom level).
  \tcontainerPointToLatLng: function (point) {
  \t\tvar layerPoint = this.containerPointToLayerPoint(toPoint(point));
  \t\treturn this.layerPointToLatLng(layerPoint);
  \t},

  \t// @method latLngToContainerPoint(latlng: LatLng): Point
  \t// Given a geographical coordinate, returns the corresponding pixel coordinate
  \t// relative to the map container.
  \tlatLngToContainerPoint: function (latlng) {
  \t\treturn this.layerPointToContainerPoint(this.latLngToLayerPoint(toLatLng(latlng)));
  \t},

  \t// @method mouseEventToContainerPoint(ev: MouseEvent): Point
  \t// Given a MouseEvent object, returns the pixel coordinate relative to the
  \t// map container where the event took place.
  \tmouseEventToContainerPoint: function (e) {
  \t\treturn getMousePosition(e, this._container);
  \t},

  \t// @method mouseEventToLayerPoint(ev: MouseEvent): Point
  \t// Given a MouseEvent object, returns the pixel coordinate relative to
  \t// the [origin pixel](#map-getpixelorigin) where the event took place.
  \tmouseEventToLayerPoint: function (e) {
  \t\treturn this.containerPointToLayerPoint(this.mouseEventToContainerPoint(e));
  \t},

  \t// @method mouseEventToLatLng(ev: MouseEvent): LatLng
  \t// Given a MouseEvent object, returns geographical coordinate where the
  \t// event took place.
  \tmouseEventToLatLng: function (e) { // (MouseEvent)
  \t\treturn this.layerPointToLatLng(this.mouseEventToLayerPoint(e));
  \t},


  \t// map initialization methods

  \t_initContainer: function (id) {
  \t\tvar container = this._container = get(id);

  \t\tif (!container) {
  \t\t\tthrow new Error('Map container not found.');
  \t\t} else if (container._leaflet_id) {
  \t\t\tthrow new Error('Map container is already initialized.');
  \t\t}

  \t\ton(container, 'scroll', this._onScroll, this);
  \t\tthis._containerId = stamp(container);
  \t},

  \t_initLayout: function () {
  \t\tvar container = this._container;

  \t\tthis._fadeAnimated = this.options.fadeAnimation && Browser.any3d;

  \t\taddClass(container, 'leaflet-container' +
  \t\t\t(Browser.touch ? ' leaflet-touch' : '') +
  \t\t\t(Browser.retina ? ' leaflet-retina' : '') +
  \t\t\t(Browser.ielt9 ? ' leaflet-oldie' : '') +
  \t\t\t(Browser.safari ? ' leaflet-safari' : '') +
  \t\t\t(this._fadeAnimated ? ' leaflet-fade-anim' : ''));

  \t\tvar position = getStyle(container, 'position');

  \t\tif (position !== 'absolute' && position !== 'relative' && position !== 'fixed' && position !== 'sticky') {
  \t\t\tcontainer.style.position = 'relative';
  \t\t}

  \t\tthis._initPanes();

  \t\tif (this._initControlPos) {
  \t\t\tthis._initControlPos();
  \t\t}
  \t},

  \t_initPanes: function () {
  \t\tvar panes = this._panes = {};
  \t\tthis._paneRenderers = {};

  \t\t// @section
  \t\t//
  \t\t// Panes are DOM elements used to control the ordering of layers on the map. You
  \t\t// can access panes with [`map.getPane`](#map-getpane) or
  \t\t// [`map.getPanes`](#map-getpanes) methods. New panes can be created with the
  \t\t// [`map.createPane`](#map-createpane) method.
  \t\t//
  \t\t// Every map has the following default panes that differ only in zIndex.
  \t\t//
  \t\t// @pane mapPane: HTMLElement = 'auto'
  \t\t// Pane that contains all other map panes

  \t\tthis._mapPane = this.createPane('mapPane', this._container);
  \t\tsetPosition(this._mapPane, new Point(0, 0));

  \t\t// @pane tilePane: HTMLElement = 200
  \t\t// Pane for `GridLayer`s and `TileLayer`s
  \t\tthis.createPane('tilePane');
  \t\t// @pane overlayPane: HTMLElement = 400
  \t\t// Pane for vectors (`Path`s, like `Polyline`s and `Polygon`s), `ImageOverlay`s and `VideoOverlay`s
  \t\tthis.createPane('overlayPane');
  \t\t// @pane shadowPane: HTMLElement = 500
  \t\t// Pane for overlay shadows (e.g. `Marker` shadows)
  \t\tthis.createPane('shadowPane');
  \t\t// @pane markerPane: HTMLElement = 600
  \t\t// Pane for `Icon`s of `Marker`s
  \t\tthis.createPane('markerPane');
  \t\t// @pane tooltipPane: HTMLElement = 650
  \t\t// Pane for `Tooltip`s.
  \t\tthis.createPane('tooltipPane');
  \t\t// @pane popupPane: HTMLElement = 700
  \t\t// Pane for `Popup`s.
  \t\tthis.createPane('popupPane');

  \t\tif (!this.options.markerZoomAnimation) {
  \t\t\taddClass(panes.markerPane, 'leaflet-zoom-hide');
  \t\t\taddClass(panes.shadowPane, 'leaflet-zoom-hide');
  \t\t}
  \t},


  \t// private methods that modify map state

  \t// @section Map state change events
  \t_resetView: function (center, zoom, noMoveStart) {
  \t\tsetPosition(this._mapPane, new Point(0, 0));

  \t\tvar loading = !this._loaded;
  \t\tthis._loaded = true;
  \t\tzoom = this._limitZoom(zoom);

  \t\tthis.fire('viewprereset');

  \t\tvar zoomChanged = this._zoom !== zoom;
  \t\tthis
  \t\t\t._moveStart(zoomChanged, noMoveStart)
  \t\t\t._move(center, zoom)
  \t\t\t._moveEnd(zoomChanged);

  \t\t// @event viewreset: Event
  \t\t// Fired when the map needs to redraw its content (this usually happens
  \t\t// on map zoom or load). Very useful for creating custom overlays.
  \t\tthis.fire('viewreset');

  \t\t// @event load: Event
  \t\t// Fired when the map is initialized (when its center and zoom are set
  \t\t// for the first time).
  \t\tif (loading) {
  \t\t\tthis.fire('load');
  \t\t}
  \t},

  \t_moveStart: function (zoomChanged, noMoveStart) {
  \t\t// @event zoomstart: Event
  \t\t// Fired when the map zoom is about to change (e.g. before zoom animation).
  \t\t// @event movestart: Event
  \t\t// Fired when the view of the map starts changing (e.g. user starts dragging the map).
  \t\tif (zoomChanged) {
  \t\t\tthis.fire('zoomstart');
  \t\t}
  \t\tif (!noMoveStart) {
  \t\t\tthis.fire('movestart');
  \t\t}
  \t\treturn this;
  \t},

  \t_move: function (center, zoom, data, supressEvent) {
  \t\tif (zoom === undefined) {
  \t\t\tzoom = this._zoom;
  \t\t}
  \t\tvar zoomChanged = this._zoom !== zoom;

  \t\tthis._zoom = zoom;
  \t\tthis._lastCenter = center;
  \t\tthis._pixelOrigin = this._getNewPixelOrigin(center);

  \t\tif (!supressEvent) {
  \t\t\t// @event zoom: Event
  \t\t\t// Fired repeatedly during any change in zoom level,
  \t\t\t// including zoom and fly animations.
  \t\t\tif (zoomChanged || (data && data.pinch)) {\t// Always fire 'zoom' if pinching because #3530
  \t\t\t\tthis.fire('zoom', data);
  \t\t\t}

  \t\t\t// @event move: Event
  \t\t\t// Fired repeatedly during any movement of the map,
  \t\t\t// including pan and fly animations.
  \t\t\tthis.fire('move', data);
  \t\t} else if (data && data.pinch) {\t// Always fire 'zoom' if pinching because #3530
  \t\t\tthis.fire('zoom', data);
  \t\t}
  \t\treturn this;
  \t},

  \t_moveEnd: function (zoomChanged) {
  \t\t// @event zoomend: Event
  \t\t// Fired when the map zoom changed, after any animations.
  \t\tif (zoomChanged) {
  \t\t\tthis.fire('zoomend');
  \t\t}

  \t\t// @event moveend: Event
  \t\t// Fired when the center of the map stops changing
  \t\t// (e.g. user stopped dragging the map or after non-centered zoom).
  \t\treturn this.fire('moveend');
  \t},

  \t_stop: function () {
  \t\tcancelAnimFrame(this._flyToFrame);
  \t\tif (this._panAnim) {
  \t\t\tthis._panAnim.stop();
  \t\t}
  \t\treturn this;
  \t},

  \t_rawPanBy: function (offset) {
  \t\tsetPosition(this._mapPane, this._getMapPanePos().subtract(offset));
  \t},

  \t_getZoomSpan: function () {
  \t\treturn this.getMaxZoom() - this.getMinZoom();
  \t},

  \t_panInsideMaxBounds: function () {
  \t\tif (!this._enforcingBounds) {
  \t\t\tthis.panInsideBounds(this.options.maxBounds);
  \t\t}
  \t},

  \t_checkIfLoaded: function () {
  \t\tif (!this._loaded) {
  \t\t\tthrow new Error('Set map center and zoom first.');
  \t\t}
  \t},

  \t// DOM event handling

  \t// @section Interaction events
  \t_initEvents: function (remove) {
  \t\tthis._targets = {};
  \t\tthis._targets[stamp(this._container)] = this;

  \t\tvar onOff = remove ? off : on;

  \t\t// @event click: MouseEvent
  \t\t// Fired when the user clicks (or taps) the map.
  \t\t// @event dblclick: MouseEvent
  \t\t// Fired when the user double-clicks (or double-taps) the map.
  \t\t// @event mousedown: MouseEvent
  \t\t// Fired when the user pushes the mouse button on the map.
  \t\t// @event mouseup: MouseEvent
  \t\t// Fired when the user releases the mouse button on the map.
  \t\t// @event mouseover: MouseEvent
  \t\t// Fired when the mouse enters the map.
  \t\t// @event mouseout: MouseEvent
  \t\t// Fired when the mouse leaves the map.
  \t\t// @event mousemove: MouseEvent
  \t\t// Fired while the mouse moves over the map.
  \t\t// @event contextmenu: MouseEvent
  \t\t// Fired when the user pushes the right mouse button on the map, prevents
  \t\t// default browser context menu from showing if there are listeners on
  \t\t// this event. Also fired on mobile when the user holds a single touch
  \t\t// for a second (also called long press).
  \t\t// @event keypress: KeyboardEvent
  \t\t// Fired when the user presses a key from the keyboard that produces a character value while the map is focused.
  \t\t// @event keydown: KeyboardEvent
  \t\t// Fired when the user presses a key from the keyboard while the map is focused. Unlike the `keypress` event,
  \t\t// the `keydown` event is fired for keys that produce a character value and for keys
  \t\t// that do not produce a character value.
  \t\t// @event keyup: KeyboardEvent
  \t\t// Fired when the user releases a key from the keyboard while the map is focused.
  \t\tonOff(this._container, 'click dblclick mousedown mouseup ' +
  \t\t\t'mouseover mouseout mousemove contextmenu keypress keydown keyup', this._handleDOMEvent, this);

  \t\tif (this.options.trackResize) {
  \t\t\tonOff(window, 'resize', this._onResize, this);
  \t\t}

  \t\tif (Browser.any3d && this.options.transform3DLimit) {
  \t\t\t(remove ? this.off : this.on).call(this, 'moveend', this._onMoveEnd);
  \t\t}
  \t},

  \t_onResize: function () {
  \t\tcancelAnimFrame(this._resizeRequest);
  \t\tthis._resizeRequest = requestAnimFrame(
  \t\t        function () { this.invalidateSize({debounceMoveend: true}); }, this);
  \t},

  \t_onScroll: function () {
  \t\tthis._container.scrollTop  = 0;
  \t\tthis._container.scrollLeft = 0;
  \t},

  \t_onMoveEnd: function () {
  \t\tvar pos = this._getMapPanePos();
  \t\tif (Math.max(Math.abs(pos.x), Math.abs(pos.y)) >= this.options.transform3DLimit) {
  \t\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=1203873 but Webkit also have
  \t\t\t// a pixel offset on very high values, see: https://jsfiddle.net/dg6r5hhb/
  \t\t\tthis._resetView(this.getCenter(), this.getZoom());
  \t\t}
  \t},

  \t_findEventTargets: function (e, type) {
  \t\tvar targets = [],
  \t\t    target,
  \t\t    isHover = type === 'mouseout' || type === 'mouseover',
  \t\t    src = e.target || e.srcElement,
  \t\t    dragging = false;

  \t\twhile (src) {
  \t\t\ttarget = this._targets[stamp(src)];
  \t\t\tif (target && (type === 'click' || type === 'preclick') && this._draggableMoved(target)) {
  \t\t\t\t// Prevent firing click after you just dragged an object.
  \t\t\t\tdragging = true;
  \t\t\t\tbreak;
  \t\t\t}
  \t\t\tif (target && target.listens(type, true)) {
  \t\t\t\tif (isHover && !isExternalTarget(src, e)) { break; }
  \t\t\t\ttargets.push(target);
  \t\t\t\tif (isHover) { break; }
  \t\t\t}
  \t\t\tif (src === this._container) { break; }
  \t\t\tsrc = src.parentNode;
  \t\t}
  \t\tif (!targets.length && !dragging && !isHover && this.listens(type, true)) {
  \t\t\ttargets = [this];
  \t\t}
  \t\treturn targets;
  \t},

  \t_isClickDisabled: function (el) {
  \t\twhile (el && el !== this._container) {
  \t\t\tif (el['_leaflet_disable_click']) { return true; }
  \t\t\tel = el.parentNode;
  \t\t}
  \t},

  \t_handleDOMEvent: function (e) {
  \t\tvar el = (e.target || e.srcElement);
  \t\tif (!this._loaded || el['_leaflet_disable_events'] || e.type === 'click' && this._isClickDisabled(el)) {
  \t\t\treturn;
  \t\t}

  \t\tvar type = e.type;

  \t\tif (type === 'mousedown') {
  \t\t\t// prevents outline when clicking on keyboard-focusable element
  \t\t\tpreventOutline(el);
  \t\t}

  \t\tthis._fireDOMEvent(e, type);
  \t},

  \t_mouseEvents: ['click', 'dblclick', 'mouseover', 'mouseout', 'contextmenu'],

  \t_fireDOMEvent: function (e, type, canvasTargets) {

  \t\tif (e.type === 'click') {
  \t\t\t// Fire a synthetic 'preclick' event which propagates up (mainly for closing popups).
  \t\t\t// @event preclick: MouseEvent
  \t\t\t// Fired before mouse click on the map (sometimes useful when you
  \t\t\t// want something to happen on click before any existing click
  \t\t\t// handlers start running).
  \t\t\tvar synth = extend({}, e);
  \t\t\tsynth.type = 'preclick';
  \t\t\tthis._fireDOMEvent(synth, synth.type, canvasTargets);
  \t\t}

  \t\t// Find the layer the event is propagating from and its parents.
  \t\tvar targets = this._findEventTargets(e, type);

  \t\tif (canvasTargets) {
  \t\t\tvar filtered = []; // pick only targets with listeners
  \t\t\tfor (var i = 0; i < canvasTargets.length; i++) {
  \t\t\t\tif (canvasTargets[i].listens(type, true)) {
  \t\t\t\t\tfiltered.push(canvasTargets[i]);
  \t\t\t\t}
  \t\t\t}
  \t\t\ttargets = filtered.concat(targets);
  \t\t}

  \t\tif (!targets.length) { return; }

  \t\tif (type === 'contextmenu') {
  \t\t\tpreventDefault(e);
  \t\t}

  \t\tvar target = targets[0];
  \t\tvar data = {
  \t\t\toriginalEvent: e
  \t\t};

  \t\tif (e.type !== 'keypress' && e.type !== 'keydown' && e.type !== 'keyup') {
  \t\t\tvar isMarker = target.getLatLng && (!target._radius || target._radius <= 10);
  \t\t\tdata.containerPoint = isMarker ?
  \t\t\t\tthis.latLngToContainerPoint(target.getLatLng()) : this.mouseEventToContainerPoint(e);
  \t\t\tdata.layerPoint = this.containerPointToLayerPoint(data.containerPoint);
  \t\t\tdata.latlng = isMarker ? target.getLatLng() : this.layerPointToLatLng(data.layerPoint);
  \t\t}

  \t\tfor (i = 0; i < targets.length; i++) {
  \t\t\ttargets[i].fire(type, data, true);
  \t\t\tif (data.originalEvent._stopped ||
  \t\t\t\t(targets[i].options.bubblingMouseEvents === false && indexOf(this._mouseEvents, type) !== -1)) { return; }
  \t\t}
  \t},

  \t_draggableMoved: function (obj) {
  \t\tobj = obj.dragging && obj.dragging.enabled() ? obj : this;
  \t\treturn (obj.dragging && obj.dragging.moved()) || (this.boxZoom && this.boxZoom.moved());
  \t},

  \t_clearHandlers: function () {
  \t\tfor (var i = 0, len = this._handlers.length; i < len; i++) {
  \t\t\tthis._handlers[i].disable();
  \t\t}
  \t},

  \t// @section Other Methods

  \t// @method whenReady(fn: Function, context?: Object): this
  \t// Runs the given function `fn` when the map gets initialized with
  \t// a view (center and zoom) and at least one layer, or immediately
  \t// if it's already initialized, optionally passing a function context.
  \twhenReady: function (callback, context) {
  \t\tif (this._loaded) {
  \t\t\tcallback.call(context || this, {target: this});
  \t\t} else {
  \t\t\tthis.on('load', callback, context);
  \t\t}
  \t\treturn this;
  \t},


  \t// private methods for getting map state

  \t_getMapPanePos: function () {
  \t\treturn getPosition(this._mapPane) || new Point(0, 0);
  \t},

  \t_moved: function () {
  \t\tvar pos = this._getMapPanePos();
  \t\treturn pos && !pos.equals([0, 0]);
  \t},

  \t_getTopLeftPoint: function (center, zoom) {
  \t\tvar pixelOrigin = center && zoom !== undefined ?
  \t\t\tthis._getNewPixelOrigin(center, zoom) :
  \t\t\tthis.getPixelOrigin();
  \t\treturn pixelOrigin.subtract(this._getMapPanePos());
  \t},

  \t_getNewPixelOrigin: function (center, zoom) {
  \t\tvar viewHalf = this.getSize()._divideBy(2);
  \t\treturn this.project(center, zoom)._subtract(viewHalf)._add(this._getMapPanePos())._round();
  \t},

  \t_latLngToNewLayerPoint: function (latlng, zoom, center) {
  \t\tvar topLeft = this._getNewPixelOrigin(center, zoom);
  \t\treturn this.project(latlng, zoom)._subtract(topLeft);
  \t},

  \t_latLngBoundsToNewLayerBounds: function (latLngBounds, zoom, center) {
  \t\tvar topLeft = this._getNewPixelOrigin(center, zoom);
  \t\treturn toBounds([
  \t\t\tthis.project(latLngBounds.getSouthWest(), zoom)._subtract(topLeft),
  \t\t\tthis.project(latLngBounds.getNorthWest(), zoom)._subtract(topLeft),
  \t\t\tthis.project(latLngBounds.getSouthEast(), zoom)._subtract(topLeft),
  \t\t\tthis.project(latLngBounds.getNorthEast(), zoom)._subtract(topLeft)
  \t\t]);
  \t},

  \t// layer point of the current center
  \t_getCenterLayerPoint: function () {
  \t\treturn this.containerPointToLayerPoint(this.getSize()._divideBy(2));
  \t},

  \t// offset of the specified place to the current center in pixels
  \t_getCenterOffset: function (latlng) {
  \t\treturn this.latLngToLayerPoint(latlng).subtract(this._getCenterLayerPoint());
  \t},

  \t// adjust center for view to get inside bounds
  \t_limitCenter: function (center, zoom, bounds) {

  \t\tif (!bounds) { return center; }

  \t\tvar centerPoint = this.project(center, zoom),
  \t\t    viewHalf = this.getSize().divideBy(2),
  \t\t    viewBounds = new Bounds(centerPoint.subtract(viewHalf), centerPoint.add(viewHalf)),
  \t\t    offset = this._getBoundsOffset(viewBounds, bounds, zoom);

  \t\t// If offset is less than a pixel, ignore.
  \t\t// This prevents unstable projections from getting into
  \t\t// an infinite loop of tiny offsets.
  \t\tif (Math.abs(offset.x) <= 1 && Math.abs(offset.y) <= 1) {
  \t\t\treturn center;
  \t\t}

  \t\treturn this.unproject(centerPoint.add(offset), zoom);
  \t},

  \t// adjust offset for view to get inside bounds
  \t_limitOffset: function (offset, bounds) {
  \t\tif (!bounds) { return offset; }

  \t\tvar viewBounds = this.getPixelBounds(),
  \t\t    newBounds = new Bounds(viewBounds.min.add(offset), viewBounds.max.add(offset));

  \t\treturn offset.add(this._getBoundsOffset(newBounds, bounds));
  \t},

  \t// returns offset needed for pxBounds to get inside maxBounds at a specified zoom
  \t_getBoundsOffset: function (pxBounds, maxBounds, zoom) {
  \t\tvar projectedMaxBounds = toBounds(
  \t\t        this.project(maxBounds.getNorthEast(), zoom),
  \t\t        this.project(maxBounds.getSouthWest(), zoom)
  \t\t    ),
  \t\t    minOffset = projectedMaxBounds.min.subtract(pxBounds.min),
  \t\t    maxOffset = projectedMaxBounds.max.subtract(pxBounds.max),

  \t\t    dx = this._rebound(minOffset.x, -maxOffset.x),
  \t\t    dy = this._rebound(minOffset.y, -maxOffset.y);

  \t\treturn new Point(dx, dy);
  \t},

  \t_rebound: function (left, right) {
  \t\treturn left + right > 0 ?
  \t\t\tMath.round(left - right) / 2 :
  \t\t\tMath.max(0, Math.ceil(left)) - Math.max(0, Math.floor(right));
  \t},

  \t_limitZoom: function (zoom) {
  \t\tvar min = this.getMinZoom(),
  \t\t    max = this.getMaxZoom(),
  \t\t    snap = Browser.any3d ? this.options.zoomSnap : 1;
  \t\tif (snap) {
  \t\t\tzoom = Math.round(zoom / snap) * snap;
  \t\t}
  \t\treturn Math.max(min, Math.min(max, zoom));
  \t},

  \t_onPanTransitionStep: function () {
  \t\tthis.fire('move');
  \t},

  \t_onPanTransitionEnd: function () {
  \t\tremoveClass(this._mapPane, 'leaflet-pan-anim');
  \t\tthis.fire('moveend');
  \t},

  \t_tryAnimatedPan: function (center, options) {
  \t\t// difference between the new and current centers in pixels
  \t\tvar offset = this._getCenterOffset(center)._trunc();

  \t\t// don't animate too far unless animate: true specified in options
  \t\tif ((options && options.animate) !== true && !this.getSize().contains(offset)) { return false; }

  \t\tthis.panBy(offset, options);

  \t\treturn true;
  \t},

  \t_createAnimProxy: function () {

  \t\tvar proxy = this._proxy = create\$1('div', 'leaflet-proxy leaflet-zoom-animated');
  \t\tthis._panes.mapPane.appendChild(proxy);

  \t\tthis.on('zoomanim', function (e) {
  \t\t\tvar prop = TRANSFORM,
  \t\t\t    transform = this._proxy.style[prop];

  \t\t\tsetTransform(this._proxy, this.project(e.center, e.zoom), this.getZoomScale(e.zoom, 1));

  \t\t\t// workaround for case when transform is the same and so transitionend event is not fired
  \t\t\tif (transform === this._proxy.style[prop] && this._animatingZoom) {
  \t\t\t\tthis._onZoomTransitionEnd();
  \t\t\t}
  \t\t}, this);

  \t\tthis.on('load moveend', this._animMoveEnd, this);

  \t\tthis._on('unload', this._destroyAnimProxy, this);
  \t},

  \t_destroyAnimProxy: function () {
  \t\tremove(this._proxy);
  \t\tthis.off('load moveend', this._animMoveEnd, this);
  \t\tdelete this._proxy;
  \t},

  \t_animMoveEnd: function () {
  \t\tvar c = this.getCenter(),
  \t\t    z = this.getZoom();
  \t\tsetTransform(this._proxy, this.project(c, z), this.getZoomScale(z, 1));
  \t},

  \t_catchTransitionEnd: function (e) {
  \t\tif (this._animatingZoom && e.propertyName.indexOf('transform') >= 0) {
  \t\t\tthis._onZoomTransitionEnd();
  \t\t}
  \t},

  \t_nothingToAnimate: function () {
  \t\treturn !this._container.getElementsByClassName('leaflet-zoom-animated').length;
  \t},

  \t_tryAnimatedZoom: function (center, zoom, options) {

  \t\tif (this._animatingZoom) { return true; }

  \t\toptions = options || {};

  \t\t// don't animate if disabled, not supported or zoom difference is too large
  \t\tif (!this._zoomAnimated || options.animate === false || this._nothingToAnimate() ||
  \t\t        Math.abs(zoom - this._zoom) > this.options.zoomAnimationThreshold) { return false; }

  \t\t// offset is the pixel coords of the zoom origin relative to the current center
  \t\tvar scale = this.getZoomScale(zoom),
  \t\t    offset = this._getCenterOffset(center)._divideBy(1 - 1 / scale);

  \t\t// don't animate if the zoom origin isn't within one screen from the current center, unless forced
  \t\tif (options.animate !== true && !this.getSize().contains(offset)) { return false; }

  \t\trequestAnimFrame(function () {
  \t\t\tthis
  \t\t\t    ._moveStart(true, options.noMoveStart || false)
  \t\t\t    ._animateZoom(center, zoom, true);
  \t\t}, this);

  \t\treturn true;
  \t},

  \t_animateZoom: function (center, zoom, startAnim, noUpdate) {
  \t\tif (!this._mapPane) { return; }

  \t\tif (startAnim) {
  \t\t\tthis._animatingZoom = true;

  \t\t\t// remember what center/zoom to set after animation
  \t\t\tthis._animateToCenter = center;
  \t\t\tthis._animateToZoom = zoom;

  \t\t\taddClass(this._mapPane, 'leaflet-zoom-anim');
  \t\t}

  \t\t// @section Other Events
  \t\t// @event zoomanim: ZoomAnimEvent
  \t\t// Fired at least once per zoom animation. For continuous zoom, like pinch zooming, fired once per frame during zoom.
  \t\tthis.fire('zoomanim', {
  \t\t\tcenter: center,
  \t\t\tzoom: zoom,
  \t\t\tnoUpdate: noUpdate
  \t\t});

  \t\tif (!this._tempFireZoomEvent) {
  \t\t\tthis._tempFireZoomEvent = this._zoom !== this._animateToZoom;
  \t\t}

  \t\tthis._move(this._animateToCenter, this._animateToZoom, undefined, true);

  \t\t// Work around webkit not firing 'transitionend', see https://github.com/Leaflet/Leaflet/issues/3689, 2693
  \t\tsetTimeout(bind(this._onZoomTransitionEnd, this), 250);
  \t},

  \t_onZoomTransitionEnd: function () {
  \t\tif (!this._animatingZoom) { return; }

  \t\tif (this._mapPane) {
  \t\t\tremoveClass(this._mapPane, 'leaflet-zoom-anim');
  \t\t}

  \t\tthis._animatingZoom = false;

  \t\tthis._move(this._animateToCenter, this._animateToZoom, undefined, true);

  \t\tif (this._tempFireZoomEvent) {
  \t\t\tthis.fire('zoom');
  \t\t}
  \t\tdelete this._tempFireZoomEvent;

  \t\tthis.fire('move');

  \t\tthis._moveEnd(true);
  \t}
  });

  // @section

  // @factory L.map(id: String, options?: Map options)
  // Instantiates a map object given the DOM ID of a `<div>` element
  // and optionally an object literal with `Map options`.
  //
  // @alternative
  // @factory L.map(el: HTMLElement, options?: Map options)
  // Instantiates a map object given an instance of a `<div>` HTML element
  // and optionally an object literal with `Map options`.
  function createMap(id, options) {
  \treturn new Map(id, options);
  }

  /*
   * @class Control
   * @aka L.Control
   * @inherits Class
   *
   * L.Control is a base class for implementing map controls. Handles positioning.
   * All other controls extend from this class.
   */

  var Control = Class.extend({
  \t// @section
  \t// @aka Control Options
  \toptions: {
  \t\t// @option position: String = 'topright'
  \t\t// The position of the control (one of the map corners). Possible values are `'topleft'`,
  \t\t// `'topright'`, `'bottomleft'` or `'bottomright'`
  \t\tposition: 'topright'
  \t},

  \tinitialize: function (options) {
  \t\tsetOptions(this, options);
  \t},

  \t/* @section
  \t * Classes extending L.Control will inherit the following methods:
  \t *
  \t * @method getPosition: string
  \t * Returns the position of the control.
  \t */
  \tgetPosition: function () {
  \t\treturn this.options.position;
  \t},

  \t// @method setPosition(position: string): this
  \t// Sets the position of the control.
  \tsetPosition: function (position) {
  \t\tvar map = this._map;

  \t\tif (map) {
  \t\t\tmap.removeControl(this);
  \t\t}

  \t\tthis.options.position = position;

  \t\tif (map) {
  \t\t\tmap.addControl(this);
  \t\t}

  \t\treturn this;
  \t},

  \t// @method getContainer: HTMLElement
  \t// Returns the HTMLElement that contains the control.
  \tgetContainer: function () {
  \t\treturn this._container;
  \t},

  \t// @method addTo(map: Map): this
  \t// Adds the control to the given map.
  \taddTo: function (map) {
  \t\tthis.remove();
  \t\tthis._map = map;

  \t\tvar container = this._container = this.onAdd(map),
  \t\t    pos = this.getPosition(),
  \t\t    corner = map._controlCorners[pos];

  \t\taddClass(container, 'leaflet-control');

  \t\tif (pos.indexOf('bottom') !== -1) {
  \t\t\tcorner.insertBefore(container, corner.firstChild);
  \t\t} else {
  \t\t\tcorner.appendChild(container);
  \t\t}

  \t\tthis._map.on('unload', this.remove, this);

  \t\treturn this;
  \t},

  \t// @method remove: this
  \t// Removes the control from the map it is currently active on.
  \tremove: function () {
  \t\tif (!this._map) {
  \t\t\treturn this;
  \t\t}

  \t\tremove(this._container);

  \t\tif (this.onRemove) {
  \t\t\tthis.onRemove(this._map);
  \t\t}

  \t\tthis._map.off('unload', this.remove, this);
  \t\tthis._map = null;

  \t\treturn this;
  \t},

  \t_refocusOnMap: function (e) {
  \t\t// if map exists and event is not a keyboard event
  \t\tif (this._map && e && e.screenX > 0 && e.screenY > 0) {
  \t\t\tthis._map.getContainer().focus();
  \t\t}
  \t}
  });

  var control = function (options) {
  \treturn new Control(options);
  };

  /* @section Extension methods
   * @uninheritable
   *
   * Every control should extend from `L.Control` and (re-)implement the following methods.
   *
   * @method onAdd(map: Map): HTMLElement
   * Should return the container DOM element for the control and add listeners on relevant map events. Called on [`control.addTo(map)`](#control-addTo).
   *
   * @method onRemove(map: Map)
   * Optional method. Should contain all clean up code that removes the listeners previously added in [`onAdd`](#control-onadd). Called on [`control.remove()`](#control-remove).
   */

  /* @namespace Map
   * @section Methods for Layers and Controls
   */
  Map.include({
  \t// @method addControl(control: Control): this
  \t// Adds the given control to the map
  \taddControl: function (control) {
  \t\tcontrol.addTo(this);
  \t\treturn this;
  \t},

  \t// @method removeControl(control: Control): this
  \t// Removes the given control from the map
  \tremoveControl: function (control) {
  \t\tcontrol.remove();
  \t\treturn this;
  \t},

  \t_initControlPos: function () {
  \t\tvar corners = this._controlCorners = {},
  \t\t    l = 'leaflet-',
  \t\t    container = this._controlContainer =
  \t\t            create\$1('div', l + 'control-container', this._container);

  \t\tfunction createCorner(vSide, hSide) {
  \t\t\tvar className = l + vSide + ' ' + l + hSide;

  \t\t\tcorners[vSide + hSide] = create\$1('div', className, container);
  \t\t}

  \t\tcreateCorner('top', 'left');
  \t\tcreateCorner('top', 'right');
  \t\tcreateCorner('bottom', 'left');
  \t\tcreateCorner('bottom', 'right');
  \t},

  \t_clearControlPos: function () {
  \t\tfor (var i in this._controlCorners) {
  \t\t\tremove(this._controlCorners[i]);
  \t\t}
  \t\tremove(this._controlContainer);
  \t\tdelete this._controlCorners;
  \t\tdelete this._controlContainer;
  \t}
  });

  /*
   * @class Control.Layers
   * @aka L.Control.Layers
   * @inherits Control
   *
   * The layers control gives users the ability to switch between different base layers and switch overlays on/off (check out the [detailed example](https://leafletjs.com/examples/layers-control/)). Extends `Control`.
   *
   * @example
   *
   * ```js
   * var baseLayers = {
   * \t\"Mapbox\": mapbox,
   * \t\"OpenStreetMap\": osm
   * };
   *
   * var overlays = {
   * \t\"Marker\": marker,
   * \t\"Roads\": roadsLayer
   * };
   *
   * L.control.layers(baseLayers, overlays).addTo(map);
   * ```
   *
   * The `baseLayers` and `overlays` parameters are object literals with layer names as keys and `Layer` objects as values:
   *
   * ```js
   * {
   *     \"<someName1>\": layer1,
   *     \"<someName2>\": layer2
   * }
   * ```
   *
   * The layer names can contain HTML, which allows you to add additional styling to the items:
   *
   * ```js
   * {\"<img src='my-layer-icon' /> <span class='my-layer-item'>My Layer</span>\": myLayer}
   * ```
   */

  var Layers = Control.extend({
  \t// @section
  \t// @aka Control.Layers options
  \toptions: {
  \t\t// @option collapsed: Boolean = true
  \t\t// If `true`, the control will be collapsed into an icon and expanded on mouse hover, touch, or keyboard activation.
  \t\tcollapsed: true,
  \t\tposition: 'topright',

  \t\t// @option autoZIndex: Boolean = true
  \t\t// If `true`, the control will assign zIndexes in increasing order to all of its layers so that the order is preserved when switching them on/off.
  \t\tautoZIndex: true,

  \t\t// @option hideSingleBase: Boolean = false
  \t\t// If `true`, the base layers in the control will be hidden when there is only one.
  \t\thideSingleBase: false,

  \t\t// @option sortLayers: Boolean = false
  \t\t// Whether to sort the layers. When `false`, layers will keep the order
  \t\t// in which they were added to the control.
  \t\tsortLayers: false,

  \t\t// @option sortFunction: Function = *
  \t\t// A [compare function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)
  \t\t// that will be used for sorting the layers, when `sortLayers` is `true`.
  \t\t// The function receives both the `L.Layer` instances and their names, as in
  \t\t// `sortFunction(layerA, layerB, nameA, nameB)`.
  \t\t// By default, it sorts layers alphabetically by their name.
  \t\tsortFunction: function (layerA, layerB, nameA, nameB) {
  \t\t\treturn nameA < nameB ? -1 : (nameB < nameA ? 1 : 0);
  \t\t}
  \t},

  \tinitialize: function (baseLayers, overlays, options) {
  \t\tsetOptions(this, options);

  \t\tthis._layerControlInputs = [];
  \t\tthis._layers = [];
  \t\tthis._lastZIndex = 0;
  \t\tthis._handlingClick = false;
  \t\tthis._preventClick = false;

  \t\tfor (var i in baseLayers) {
  \t\t\tthis._addLayer(baseLayers[i], i);
  \t\t}

  \t\tfor (i in overlays) {
  \t\t\tthis._addLayer(overlays[i], i, true);
  \t\t}
  \t},

  \tonAdd: function (map) {
  \t\tthis._initLayout();
  \t\tthis._update();

  \t\tthis._map = map;
  \t\tmap.on('zoomend', this._checkDisabledLayers, this);

  \t\tfor (var i = 0; i < this._layers.length; i++) {
  \t\t\tthis._layers[i].layer.on('add remove', this._onLayerChange, this);
  \t\t}

  \t\treturn this._container;
  \t},

  \taddTo: function (map) {
  \t\tControl.prototype.addTo.call(this, map);
  \t\t// Trigger expand after Layers Control has been inserted into DOM so that is now has an actual height.
  \t\treturn this._expandIfNotCollapsed();
  \t},

  \tonRemove: function () {
  \t\tthis._map.off('zoomend', this._checkDisabledLayers, this);

  \t\tfor (var i = 0; i < this._layers.length; i++) {
  \t\t\tthis._layers[i].layer.off('add remove', this._onLayerChange, this);
  \t\t}
  \t},

  \t// @method addBaseLayer(layer: Layer, name: String): this
  \t// Adds a base layer (radio button entry) with the given name to the control.
  \taddBaseLayer: function (layer, name) {
  \t\tthis._addLayer(layer, name);
  \t\treturn (this._map) ? this._update() : this;
  \t},

  \t// @method addOverlay(layer: Layer, name: String): this
  \t// Adds an overlay (checkbox entry) with the given name to the control.
  \taddOverlay: function (layer, name) {
  \t\tthis._addLayer(layer, name, true);
  \t\treturn (this._map) ? this._update() : this;
  \t},

  \t// @method removeLayer(layer: Layer): this
  \t// Remove the given layer from the control.
  \tremoveLayer: function (layer) {
  \t\tlayer.off('add remove', this._onLayerChange, this);

  \t\tvar obj = this._getLayer(stamp(layer));
  \t\tif (obj) {
  \t\t\tthis._layers.splice(this._layers.indexOf(obj), 1);
  \t\t}
  \t\treturn (this._map) ? this._update() : this;
  \t},

  \t// @method expand(): this
  \t// Expand the control container if collapsed.
  \texpand: function () {
  \t\taddClass(this._container, 'leaflet-control-layers-expanded');
  \t\tthis._section.style.height = null;
  \t\tvar acceptableHeight = this._map.getSize().y - (this._container.offsetTop + 50);
  \t\tif (acceptableHeight < this._section.clientHeight) {
  \t\t\taddClass(this._section, 'leaflet-control-layers-scrollbar');
  \t\t\tthis._section.style.height = acceptableHeight + 'px';
  \t\t} else {
  \t\t\tremoveClass(this._section, 'leaflet-control-layers-scrollbar');
  \t\t}
  \t\tthis._checkDisabledLayers();
  \t\treturn this;
  \t},

  \t// @method collapse(): this
  \t// Collapse the control container if expanded.
  \tcollapse: function () {
  \t\tremoveClass(this._container, 'leaflet-control-layers-expanded');
  \t\treturn this;
  \t},

  \t_initLayout: function () {
  \t\tvar className = 'leaflet-control-layers',
  \t\t    container = this._container = create\$1('div', className),
  \t\t    collapsed = this.options.collapsed;

  \t\t// makes this work on IE touch devices by stopping it from firing a mouseout event when the touch is released
  \t\tcontainer.setAttribute('aria-haspopup', true);

  \t\tdisableClickPropagation(container);
  \t\tdisableScrollPropagation(container);

  \t\tvar section = this._section = create\$1('section', className + '-list');

  \t\tif (collapsed) {
  \t\t\tthis._map.on('click', this.collapse, this);

  \t\t\ton(container, {
  \t\t\t\tmouseenter: this._expandSafely,
  \t\t\t\tmouseleave: this.collapse
  \t\t\t}, this);
  \t\t}

  \t\tvar link = this._layersLink = create\$1('a', className + '-toggle', container);
  \t\tlink.href = '#';
  \t\tlink.title = 'Layers';
  \t\tlink.setAttribute('role', 'button');

  \t\ton(link, {
  \t\t\tkeydown: function (e) {
  \t\t\t\tif (e.keyCode === 13) {
  \t\t\t\t\tthis._expandSafely();
  \t\t\t\t}
  \t\t\t},
  \t\t\t// Certain screen readers intercept the key event and instead send a click event
  \t\t\tclick: function (e) {
  \t\t\t\tpreventDefault(e);
  \t\t\t\tthis._expandSafely();
  \t\t\t}
  \t\t}, this);

  \t\tif (!collapsed) {
  \t\t\tthis.expand();
  \t\t}

  \t\tthis._baseLayersList = create\$1('div', className + '-base', section);
  \t\tthis._separator = create\$1('div', className + '-separator', section);
  \t\tthis._overlaysList = create\$1('div', className + '-overlays', section);

  \t\tcontainer.appendChild(section);
  \t},

  \t_getLayer: function (id) {
  \t\tfor (var i = 0; i < this._layers.length; i++) {

  \t\t\tif (this._layers[i] && stamp(this._layers[i].layer) === id) {
  \t\t\t\treturn this._layers[i];
  \t\t\t}
  \t\t}
  \t},

  \t_addLayer: function (layer, name, overlay) {
  \t\tif (this._map) {
  \t\t\tlayer.on('add remove', this._onLayerChange, this);
  \t\t}

  \t\tthis._layers.push({
  \t\t\tlayer: layer,
  \t\t\tname: name,
  \t\t\toverlay: overlay
  \t\t});

  \t\tif (this.options.sortLayers) {
  \t\t\tthis._layers.sort(bind(function (a, b) {
  \t\t\t\treturn this.options.sortFunction(a.layer, b.layer, a.name, b.name);
  \t\t\t}, this));
  \t\t}

  \t\tif (this.options.autoZIndex && layer.setZIndex) {
  \t\t\tthis._lastZIndex++;
  \t\t\tlayer.setZIndex(this._lastZIndex);
  \t\t}

  \t\tthis._expandIfNotCollapsed();
  \t},

  \t_update: function () {
  \t\tif (!this._container) { return this; }

  \t\tempty(this._baseLayersList);
  \t\tempty(this._overlaysList);

  \t\tthis._layerControlInputs = [];
  \t\tvar baseLayersPresent, overlaysPresent, i, obj, baseLayersCount = 0;

  \t\tfor (i = 0; i < this._layers.length; i++) {
  \t\t\tobj = this._layers[i];
  \t\t\tthis._addItem(obj);
  \t\t\toverlaysPresent = overlaysPresent || obj.overlay;
  \t\t\tbaseLayersPresent = baseLayersPresent || !obj.overlay;
  \t\t\tbaseLayersCount += !obj.overlay ? 1 : 0;
  \t\t}

  \t\t// Hide base layers section if there's only one layer.
  \t\tif (this.options.hideSingleBase) {
  \t\t\tbaseLayersPresent = baseLayersPresent && baseLayersCount > 1;
  \t\t\tthis._baseLayersList.style.display = baseLayersPresent ? '' : 'none';
  \t\t}

  \t\tthis._separator.style.display = overlaysPresent && baseLayersPresent ? '' : 'none';

  \t\treturn this;
  \t},

  \t_onLayerChange: function (e) {
  \t\tif (!this._handlingClick) {
  \t\t\tthis._update();
  \t\t}

  \t\tvar obj = this._getLayer(stamp(e.target));

  \t\t// @namespace Map
  \t\t// @section Layer events
  \t\t// @event baselayerchange: LayersControlEvent
  \t\t// Fired when the base layer is changed through the [layers control](#control-layers).
  \t\t// @event overlayadd: LayersControlEvent
  \t\t// Fired when an overlay is selected through the [layers control](#control-layers).
  \t\t// @event overlayremove: LayersControlEvent
  \t\t// Fired when an overlay is deselected through the [layers control](#control-layers).
  \t\t// @namespace Control.Layers
  \t\tvar type = obj.overlay ?
  \t\t\t(e.type === 'add' ? 'overlayadd' : 'overlayremove') :
  \t\t\t(e.type === 'add' ? 'baselayerchange' : null);

  \t\tif (type) {
  \t\t\tthis._map.fire(type, obj);
  \t\t}
  \t},

  \t// IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see https://stackoverflow.com/a/119079)
  \t_createRadioElement: function (name, checked) {

  \t\tvar radioHtml = '<input type=\"radio\" class=\"leaflet-control-layers-selector\" name=\"' +
  \t\t\t\tname + '\"' + (checked ? ' checked=\"checked\"' : '') + '/>';

  \t\tvar radioFragment = document.createElement('div');
  \t\tradioFragment.innerHTML = radioHtml;

  \t\treturn radioFragment.firstChild;
  \t},

  \t_addItem: function (obj) {
  \t\tvar label = document.createElement('label'),
  \t\t    checked = this._map.hasLayer(obj.layer),
  \t\t    input;

  \t\tif (obj.overlay) {
  \t\t\tinput = document.createElement('input');
  \t\t\tinput.type = 'checkbox';
  \t\t\tinput.className = 'leaflet-control-layers-selector';
  \t\t\tinput.defaultChecked = checked;
  \t\t} else {
  \t\t\tinput = this._createRadioElement('leaflet-base-layers_' + stamp(this), checked);
  \t\t}

  \t\tthis._layerControlInputs.push(input);
  \t\tinput.layerId = stamp(obj.layer);

  \t\ton(input, 'click', this._onInputClick, this);

  \t\tvar name = document.createElement('span');
  \t\tname.innerHTML = ' ' + obj.name;

  \t\t// Helps from preventing layer control flicker when checkboxes are disabled
  \t\t// https://github.com/Leaflet/Leaflet/issues/2771
  \t\tvar holder = document.createElement('span');

  \t\tlabel.appendChild(holder);
  \t\tholder.appendChild(input);
  \t\tholder.appendChild(name);

  \t\tvar container = obj.overlay ? this._overlaysList : this._baseLayersList;
  \t\tcontainer.appendChild(label);

  \t\tthis._checkDisabledLayers();
  \t\treturn label;
  \t},

  \t_onInputClick: function () {
  \t\t// expanding the control on mobile with a click can cause adding a layer - we don't want this
  \t\tif (this._preventClick) {
  \t\t\treturn;
  \t\t}

  \t\tvar inputs = this._layerControlInputs,
  \t\t    input, layer;
  \t\tvar addedLayers = [],
  \t\t    removedLayers = [];

  \t\tthis._handlingClick = true;

  \t\tfor (var i = inputs.length - 1; i >= 0; i--) {
  \t\t\tinput = inputs[i];
  \t\t\tlayer = this._getLayer(input.layerId).layer;

  \t\t\tif (input.checked) {
  \t\t\t\taddedLayers.push(layer);
  \t\t\t} else if (!input.checked) {
  \t\t\t\tremovedLayers.push(layer);
  \t\t\t}
  \t\t}

  \t\t// Bugfix issue 2318: Should remove all old layers before readding new ones
  \t\tfor (i = 0; i < removedLayers.length; i++) {
  \t\t\tif (this._map.hasLayer(removedLayers[i])) {
  \t\t\t\tthis._map.removeLayer(removedLayers[i]);
  \t\t\t}
  \t\t}
  \t\tfor (i = 0; i < addedLayers.length; i++) {
  \t\t\tif (!this._map.hasLayer(addedLayers[i])) {
  \t\t\t\tthis._map.addLayer(addedLayers[i]);
  \t\t\t}
  \t\t}

  \t\tthis._handlingClick = false;

  \t\tthis._refocusOnMap();
  \t},

  \t_checkDisabledLayers: function () {
  \t\tvar inputs = this._layerControlInputs,
  \t\t    input,
  \t\t    layer,
  \t\t    zoom = this._map.getZoom();

  \t\tfor (var i = inputs.length - 1; i >= 0; i--) {
  \t\t\tinput = inputs[i];
  \t\t\tlayer = this._getLayer(input.layerId).layer;
  \t\t\tinput.disabled = (layer.options.minZoom !== undefined && zoom < layer.options.minZoom) ||
  \t\t\t                 (layer.options.maxZoom !== undefined && zoom > layer.options.maxZoom);

  \t\t}
  \t},

  \t_expandIfNotCollapsed: function () {
  \t\tif (this._map && !this.options.collapsed) {
  \t\t\tthis.expand();
  \t\t}
  \t\treturn this;
  \t},

  \t_expandSafely: function () {
  \t\tvar section = this._section;
  \t\tthis._preventClick = true;
  \t\ton(section, 'click', preventDefault);
  \t\tthis.expand();
  \t\tvar that = this;
  \t\tsetTimeout(function () {
  \t\t\toff(section, 'click', preventDefault);
  \t\t\tthat._preventClick = false;
  \t\t});
  \t}

  });


  // @factory L.control.layers(baselayers?: Object, overlays?: Object, options?: Control.Layers options)
  // Creates a layers control with the given layers. Base layers will be switched with radio buttons, while overlays will be switched with checkboxes. Note that all base layers should be passed in the base layers object, but only one should be added to the map during map instantiation.
  var layers = function (baseLayers, overlays, options) {
  \treturn new Layers(baseLayers, overlays, options);
  };

  /*
   * @class Control.Zoom
   * @aka L.Control.Zoom
   * @inherits Control
   *
   * A basic zoom control with two buttons (zoom in and zoom out). It is put on the map by default unless you set its [`zoomControl` option](#map-zoomcontrol) to `false`. Extends `Control`.
   */

  var Zoom = Control.extend({
  \t// @section
  \t// @aka Control.Zoom options
  \toptions: {
  \t\tposition: 'topleft',

  \t\t// @option zoomInText: String = '<span aria-hidden=\"true\">+</span>'
  \t\t// The text set on the 'zoom in' button.
  \t\tzoomInText: '<span aria-hidden=\"true\">+</span>',

  \t\t// @option zoomInTitle: String = 'Zoom in'
  \t\t// The title set on the 'zoom in' button.
  \t\tzoomInTitle: 'Zoom in',

  \t\t// @option zoomOutText: String = '<span aria-hidden=\"true\">&#x2212;</span>'
  \t\t// The text set on the 'zoom out' button.
  \t\tzoomOutText: '<span aria-hidden=\"true\">&#x2212;</span>',

  \t\t// @option zoomOutTitle: String = 'Zoom out'
  \t\t// The title set on the 'zoom out' button.
  \t\tzoomOutTitle: 'Zoom out'
  \t},

  \tonAdd: function (map) {
  \t\tvar zoomName = 'leaflet-control-zoom',
  \t\t    container = create\$1('div', zoomName + ' leaflet-bar'),
  \t\t    options = this.options;

  \t\tthis._zoomInButton  = this._createButton(options.zoomInText, options.zoomInTitle,
  \t\t        zoomName + '-in',  container, this._zoomIn);
  \t\tthis._zoomOutButton = this._createButton(options.zoomOutText, options.zoomOutTitle,
  \t\t        zoomName + '-out', container, this._zoomOut);

  \t\tthis._updateDisabled();
  \t\tmap.on('zoomend zoomlevelschange', this._updateDisabled, this);

  \t\treturn container;
  \t},

  \tonRemove: function (map) {
  \t\tmap.off('zoomend zoomlevelschange', this._updateDisabled, this);
  \t},

  \tdisable: function () {
  \t\tthis._disabled = true;
  \t\tthis._updateDisabled();
  \t\treturn this;
  \t},

  \tenable: function () {
  \t\tthis._disabled = false;
  \t\tthis._updateDisabled();
  \t\treturn this;
  \t},

  \t_zoomIn: function (e) {
  \t\tif (!this._disabled && this._map._zoom < this._map.getMaxZoom()) {
  \t\t\tthis._map.zoomIn(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1));
  \t\t}
  \t},

  \t_zoomOut: function (e) {
  \t\tif (!this._disabled && this._map._zoom > this._map.getMinZoom()) {
  \t\t\tthis._map.zoomOut(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1));
  \t\t}
  \t},

  \t_createButton: function (html, title, className, container, fn) {
  \t\tvar link = create\$1('a', className, container);
  \t\tlink.innerHTML = html;
  \t\tlink.href = '#';
  \t\tlink.title = title;

  \t\t/*
  \t\t * Will force screen readers like VoiceOver to read this as \"Zoom in - button\"
  \t\t */
  \t\tlink.setAttribute('role', 'button');
  \t\tlink.setAttribute('aria-label', title);

  \t\tdisableClickPropagation(link);
  \t\ton(link, 'click', stop);
  \t\ton(link, 'click', fn, this);
  \t\ton(link, 'click', this._refocusOnMap, this);

  \t\treturn link;
  \t},

  \t_updateDisabled: function () {
  \t\tvar map = this._map,
  \t\t    className = 'leaflet-disabled';

  \t\tremoveClass(this._zoomInButton, className);
  \t\tremoveClass(this._zoomOutButton, className);
  \t\tthis._zoomInButton.setAttribute('aria-disabled', 'false');
  \t\tthis._zoomOutButton.setAttribute('aria-disabled', 'false');

  \t\tif (this._disabled || map._zoom === map.getMinZoom()) {
  \t\t\taddClass(this._zoomOutButton, className);
  \t\t\tthis._zoomOutButton.setAttribute('aria-disabled', 'true');
  \t\t}
  \t\tif (this._disabled || map._zoom === map.getMaxZoom()) {
  \t\t\taddClass(this._zoomInButton, className);
  \t\t\tthis._zoomInButton.setAttribute('aria-disabled', 'true');
  \t\t}
  \t}
  });

  // @namespace Map
  // @section Control options
  // @option zoomControl: Boolean = true
  // Whether a [zoom control](#control-zoom) is added to the map by default.
  Map.mergeOptions({
  \tzoomControl: true
  });

  Map.addInitHook(function () {
  \tif (this.options.zoomControl) {
  \t\t// @section Controls
  \t\t// @property zoomControl: Control.Zoom
  \t\t// The default zoom control (only available if the
  \t\t// [`zoomControl` option](#map-zoomcontrol) was `true` when creating the map).
  \t\tthis.zoomControl = new Zoom();
  \t\tthis.addControl(this.zoomControl);
  \t}
  });

  // @namespace Control.Zoom
  // @factory L.control.zoom(options: Control.Zoom options)
  // Creates a zoom control
  var zoom = function (options) {
  \treturn new Zoom(options);
  };

  /*
   * @class Control.Scale
   * @aka L.Control.Scale
   * @inherits Control
   *
   * A simple scale control that shows the scale of the current center of screen in metric (m/km) and imperial (mi/ft) systems. Extends `Control`.
   *
   * @example
   *
   * ```js
   * L.control.scale().addTo(map);
   * ```
   */

  var Scale = Control.extend({
  \t// @section
  \t// @aka Control.Scale options
  \toptions: {
  \t\tposition: 'bottomleft',

  \t\t// @option maxWidth: Number = 100
  \t\t// Maximum width of the control in pixels. The width is set dynamically to show round values (e.g. 100, 200, 500).
  \t\tmaxWidth: 100,

  \t\t// @option metric: Boolean = True
  \t\t// Whether to show the metric scale line (m/km).
  \t\tmetric: true,

  \t\t// @option imperial: Boolean = True
  \t\t// Whether to show the imperial scale line (mi/ft).
  \t\timperial: true

  \t\t// @option updateWhenIdle: Boolean = false
  \t\t// If `true`, the control is updated on [`moveend`](#map-moveend), otherwise it's always up-to-date (updated on [`move`](#map-move)).
  \t},

  \tonAdd: function (map) {
  \t\tvar className = 'leaflet-control-scale',
  \t\t    container = create\$1('div', className),
  \t\t    options = this.options;

  \t\tthis._addScales(options, className + '-line', container);

  \t\tmap.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this);
  \t\tmap.whenReady(this._update, this);

  \t\treturn container;
  \t},

  \tonRemove: function (map) {
  \t\tmap.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this);
  \t},

  \t_addScales: function (options, className, container) {
  \t\tif (options.metric) {
  \t\t\tthis._mScale = create\$1('div', className, container);
  \t\t}
  \t\tif (options.imperial) {
  \t\t\tthis._iScale = create\$1('div', className, container);
  \t\t}
  \t},

  \t_update: function () {
  \t\tvar map = this._map,
  \t\t    y = map.getSize().y / 2;

  \t\tvar maxMeters = map.distance(
  \t\t\tmap.containerPointToLatLng([0, y]),
  \t\t\tmap.containerPointToLatLng([this.options.maxWidth, y]));

  \t\tthis._updateScales(maxMeters);
  \t},

  \t_updateScales: function (maxMeters) {
  \t\tif (this.options.metric && maxMeters) {
  \t\t\tthis._updateMetric(maxMeters);
  \t\t}
  \t\tif (this.options.imperial && maxMeters) {
  \t\t\tthis._updateImperial(maxMeters);
  \t\t}
  \t},

  \t_updateMetric: function (maxMeters) {
  \t\tvar meters = this._getRoundNum(maxMeters),
  \t\t    label = meters < 1000 ? meters + ' m' : (meters / 1000) + ' km';

  \t\tthis._updateScale(this._mScale, label, meters / maxMeters);
  \t},

  \t_updateImperial: function (maxMeters) {
  \t\tvar maxFeet = maxMeters * 3.2808399,
  \t\t    maxMiles, miles, feet;

  \t\tif (maxFeet > 5280) {
  \t\t\tmaxMiles = maxFeet / 5280;
  \t\t\tmiles = this._getRoundNum(maxMiles);
  \t\t\tthis._updateScale(this._iScale, miles + ' mi', miles / maxMiles);

  \t\t} else {
  \t\t\tfeet = this._getRoundNum(maxFeet);
  \t\t\tthis._updateScale(this._iScale, feet + ' ft', feet / maxFeet);
  \t\t}
  \t},

  \t_updateScale: function (scale, text, ratio) {
  \t\tscale.style.width = Math.round(this.options.maxWidth * ratio) + 'px';
  \t\tscale.innerHTML = text;
  \t},

  \t_getRoundNum: function (num) {
  \t\tvar pow10 = Math.pow(10, (Math.floor(num) + '').length - 1),
  \t\t    d = num / pow10;

  \t\td = d >= 10 ? 10 :
  \t\t    d >= 5 ? 5 :
  \t\t    d >= 3 ? 3 :
  \t\t    d >= 2 ? 2 : 1;

  \t\treturn pow10 * d;
  \t}
  });


  // @factory L.control.scale(options?: Control.Scale options)
  // Creates an scale control with the given options.
  var scale = function (options) {
  \treturn new Scale(options);
  };

  var ukrainianFlag = '<svg aria-hidden=\"true\" xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"8\" viewBox=\"0 0 12 8\" class=\"leaflet-attribution-flag\"><path fill=\"#4C7BE1\" d=\"M0 0h12v4H0z\"/><path fill=\"#FFD500\" d=\"M0 4h12v3H0z\"/><path fill=\"#E0BC00\" d=\"M0 7h12v1H0z\"/></svg>';


  /*
   * @class Control.Attribution
   * @aka L.Control.Attribution
   * @inherits Control
   *
   * The attribution control allows you to display attribution data in a small text box on a map. It is put on the map by default unless you set its [`attributionControl` option](#map-attributioncontrol) to `false`, and it fetches attribution texts from layers with the [`getAttribution` method](#layer-getattribution) automatically. Extends Control.
   */

  var Attribution = Control.extend({
  \t// @section
  \t// @aka Control.Attribution options
  \toptions: {
  \t\tposition: 'bottomright',

  \t\t// @option prefix: String|false = 'Leaflet'
  \t\t// The HTML text shown before the attributions. Pass `false` to disable.
  \t\tprefix: '<a href=\"https://leafletjs.com\" title=\"A JavaScript library for interactive maps\">' + (Browser.inlineSvg ? ukrainianFlag + ' ' : '') + 'Leaflet</a>'
  \t},

  \tinitialize: function (options) {
  \t\tsetOptions(this, options);

  \t\tthis._attributions = {};
  \t},

  \tonAdd: function (map) {
  \t\tmap.attributionControl = this;
  \t\tthis._container = create\$1('div', 'leaflet-control-attribution');
  \t\tdisableClickPropagation(this._container);

  \t\t// TODO ugly, refactor
  \t\tfor (var i in map._layers) {
  \t\t\tif (map._layers[i].getAttribution) {
  \t\t\t\tthis.addAttribution(map._layers[i].getAttribution());
  \t\t\t}
  \t\t}

  \t\tthis._update();

  \t\tmap.on('layeradd', this._addAttribution, this);

  \t\treturn this._container;
  \t},

  \tonRemove: function (map) {
  \t\tmap.off('layeradd', this._addAttribution, this);
  \t},

  \t_addAttribution: function (ev) {
  \t\tif (ev.layer.getAttribution) {
  \t\t\tthis.addAttribution(ev.layer.getAttribution());
  \t\t\tev.layer.once('remove', function () {
  \t\t\t\tthis.removeAttribution(ev.layer.getAttribution());
  \t\t\t}, this);
  \t\t}
  \t},

  \t// @method setPrefix(prefix: String|false): this
  \t// The HTML text shown before the attributions. Pass `false` to disable.
  \tsetPrefix: function (prefix) {
  \t\tthis.options.prefix = prefix;
  \t\tthis._update();
  \t\treturn this;
  \t},

  \t// @method addAttribution(text: String): this
  \t// Adds an attribution text (e.g. `'&copy; OpenStreetMap contributors'`).
  \taddAttribution: function (text) {
  \t\tif (!text) { return this; }

  \t\tif (!this._attributions[text]) {
  \t\t\tthis._attributions[text] = 0;
  \t\t}
  \t\tthis._attributions[text]++;

  \t\tthis._update();

  \t\treturn this;
  \t},

  \t// @method removeAttribution(text: String): this
  \t// Removes an attribution text.
  \tremoveAttribution: function (text) {
  \t\tif (!text) { return this; }

  \t\tif (this._attributions[text]) {
  \t\t\tthis._attributions[text]--;
  \t\t\tthis._update();
  \t\t}

  \t\treturn this;
  \t},

  \t_update: function () {
  \t\tif (!this._map) { return; }

  \t\tvar attribs = [];

  \t\tfor (var i in this._attributions) {
  \t\t\tif (this._attributions[i]) {
  \t\t\t\tattribs.push(i);
  \t\t\t}
  \t\t}

  \t\tvar prefixAndAttribs = [];

  \t\tif (this.options.prefix) {
  \t\t\tprefixAndAttribs.push(this.options.prefix);
  \t\t}
  \t\tif (attribs.length) {
  \t\t\tprefixAndAttribs.push(attribs.join(', '));
  \t\t}

  \t\tthis._container.innerHTML = prefixAndAttribs.join(' <span aria-hidden=\"true\">|</span> ');
  \t}
  });

  // @namespace Map
  // @section Control options
  // @option attributionControl: Boolean = true
  // Whether a [attribution control](#control-attribution) is added to the map by default.
  Map.mergeOptions({
  \tattributionControl: true
  });

  Map.addInitHook(function () {
  \tif (this.options.attributionControl) {
  \t\tnew Attribution().addTo(this);
  \t}
  });

  // @namespace Control.Attribution
  // @factory L.control.attribution(options: Control.Attribution options)
  // Creates an attribution control.
  var attribution = function (options) {
  \treturn new Attribution(options);
  };

  Control.Layers = Layers;
  Control.Zoom = Zoom;
  Control.Scale = Scale;
  Control.Attribution = Attribution;

  control.layers = layers;
  control.zoom = zoom;
  control.scale = scale;
  control.attribution = attribution;

  /*
  \tL.Handler is a base class for handler classes that are used internally to inject
  \tinteraction features like dragging to classes like Map and Marker.
  */

  // @class Handler
  // @aka L.Handler
  // Abstract class for map interaction handlers

  var Handler = Class.extend({
  \tinitialize: function (map) {
  \t\tthis._map = map;
  \t},

  \t// @method enable(): this
  \t// Enables the handler
  \tenable: function () {
  \t\tif (this._enabled) { return this; }

  \t\tthis._enabled = true;
  \t\tthis.addHooks();
  \t\treturn this;
  \t},

  \t// @method disable(): this
  \t// Disables the handler
  \tdisable: function () {
  \t\tif (!this._enabled) { return this; }

  \t\tthis._enabled = false;
  \t\tthis.removeHooks();
  \t\treturn this;
  \t},

  \t// @method enabled(): Boolean
  \t// Returns `true` if the handler is enabled
  \tenabled: function () {
  \t\treturn !!this._enabled;
  \t}

  \t// @section Extension methods
  \t// Classes inheriting from `Handler` must implement the two following methods:
  \t// @method addHooks()
  \t// Called when the handler is enabled, should add event hooks.
  \t// @method removeHooks()
  \t// Called when the handler is disabled, should remove the event hooks added previously.
  });

  // @section There is static function which can be called without instantiating L.Handler:
  // @function addTo(map: Map, name: String): this
  // Adds a new Handler to the given map with the given name.
  Handler.addTo = function (map, name) {
  \tmap.addHandler(name, this);
  \treturn this;
  };

  var Mixin = {Events: Events};

  /*
   * @class Draggable
   * @aka L.Draggable
   * @inherits Evented
   *
   * A class for making DOM elements draggable (including touch support).
   * Used internally for map and marker dragging. Only works for elements
   * that were positioned with [`L.DomUtil.setPosition`](#domutil-setposition).
   *
   * @example
   * ```js
   * var draggable = new L.Draggable(elementToDrag);
   * draggable.enable();
   * ```
   */

  var START = Browser.touch ? 'touchstart mousedown' : 'mousedown';

  var Draggable = Evented.extend({

  \toptions: {
  \t\t// @section
  \t\t// @aka Draggable options
  \t\t// @option clickTolerance: Number = 3
  \t\t// The max number of pixels a user can shift the mouse pointer during a click
  \t\t// for it to be considered a valid click (as opposed to a mouse drag).
  \t\tclickTolerance: 3
  \t},

  \t// @constructor L.Draggable(el: HTMLElement, dragHandle?: HTMLElement, preventOutline?: Boolean, options?: Draggable options)
  \t// Creates a `Draggable` object for moving `el` when you start dragging the `dragHandle` element (equals `el` itself by default).
  \tinitialize: function (element, dragStartTarget, preventOutline, options) {
  \t\tsetOptions(this, options);

  \t\tthis._element = element;
  \t\tthis._dragStartTarget = dragStartTarget || element;
  \t\tthis._preventOutline = preventOutline;
  \t},

  \t// @method enable()
  \t// Enables the dragging ability
  \tenable: function () {
  \t\tif (this._enabled) { return; }

  \t\ton(this._dragStartTarget, START, this._onDown, this);

  \t\tthis._enabled = true;
  \t},

  \t// @method disable()
  \t// Disables the dragging ability
  \tdisable: function () {
  \t\tif (!this._enabled) { return; }

  \t\t// If we're currently dragging this draggable,
  \t\t// disabling it counts as first ending the drag.
  \t\tif (Draggable._dragging === this) {
  \t\t\tthis.finishDrag(true);
  \t\t}

  \t\toff(this._dragStartTarget, START, this._onDown, this);

  \t\tthis._enabled = false;
  \t\tthis._moved = false;
  \t},

  \t_onDown: function (e) {
  \t\t// Ignore the event if disabled; this happens in IE11
  \t\t// under some circumstances, see #3666.
  \t\tif (!this._enabled) { return; }

  \t\tthis._moved = false;

  \t\tif (hasClass(this._element, 'leaflet-zoom-anim')) { return; }

  \t\tif (e.touches && e.touches.length !== 1) {
  \t\t\t// Finish dragging to avoid conflict with touchZoom
  \t\t\tif (Draggable._dragging === this) {
  \t\t\t\tthis.finishDrag();
  \t\t\t}
  \t\t\treturn;
  \t\t}

  \t\tif (Draggable._dragging || e.shiftKey || ((e.which !== 1) && (e.button !== 1) && !e.touches)) { return; }
  \t\tDraggable._dragging = this;  // Prevent dragging multiple objects at once.

  \t\tif (this._preventOutline) {
  \t\t\tpreventOutline(this._element);
  \t\t}

  \t\tdisableImageDrag();
  \t\tdisableTextSelection();

  \t\tif (this._moving) { return; }

  \t\t// @event down: Event
  \t\t// Fired when a drag is about to start.
  \t\tthis.fire('down');

  \t\tvar first = e.touches ? e.touches[0] : e,
  \t\t    sizedParent = getSizedParentNode(this._element);

  \t\tthis._startPoint = new Point(first.clientX, first.clientY);
  \t\tthis._startPos = getPosition(this._element);

  \t\t// Cache the scale, so that we can continuously compensate for it during drag (_onMove).
  \t\tthis._parentScale = getScale(sizedParent);

  \t\tvar mouseevent = e.type === 'mousedown';
  \t\ton(document, mouseevent ? 'mousemove' : 'touchmove', this._onMove, this);
  \t\ton(document, mouseevent ? 'mouseup' : 'touchend touchcancel', this._onUp, this);
  \t},

  \t_onMove: function (e) {
  \t\t// Ignore the event if disabled; this happens in IE11
  \t\t// under some circumstances, see #3666.
  \t\tif (!this._enabled) { return; }

  \t\tif (e.touches && e.touches.length > 1) {
  \t\t\tthis._moved = true;
  \t\t\treturn;
  \t\t}

  \t\tvar first = (e.touches && e.touches.length === 1 ? e.touches[0] : e),
  \t\t    offset = new Point(first.clientX, first.clientY)._subtract(this._startPoint);

  \t\tif (!offset.x && !offset.y) { return; }
  \t\tif (Math.abs(offset.x) + Math.abs(offset.y) < this.options.clickTolerance) { return; }

  \t\t// We assume that the parent container's position, border and scale do not change for the duration of the drag.
  \t\t// Therefore there is no need to account for the position and border (they are eliminated by the subtraction)
  \t\t// and we can use the cached value for the scale.
  \t\toffset.x /= this._parentScale.x;
  \t\toffset.y /= this._parentScale.y;

  \t\tpreventDefault(e);

  \t\tif (!this._moved) {
  \t\t\t// @event dragstart: Event
  \t\t\t// Fired when a drag starts
  \t\t\tthis.fire('dragstart');

  \t\t\tthis._moved = true;

  \t\t\taddClass(document.body, 'leaflet-dragging');

  \t\t\tthis._lastTarget = e.target || e.srcElement;
  \t\t\t// IE and Edge do not give the <use> element, so fetch it
  \t\t\t// if necessary
  \t\t\tif (window.SVGElementInstance && this._lastTarget instanceof window.SVGElementInstance) {
  \t\t\t\tthis._lastTarget = this._lastTarget.correspondingUseElement;
  \t\t\t}
  \t\t\taddClass(this._lastTarget, 'leaflet-drag-target');
  \t\t}

  \t\tthis._newPos = this._startPos.add(offset);
  \t\tthis._moving = true;

  \t\tthis._lastEvent = e;
  \t\tthis._updatePosition();
  \t},

  \t_updatePosition: function () {
  \t\tvar e = {originalEvent: this._lastEvent};

  \t\t// @event predrag: Event
  \t\t// Fired continuously during dragging *before* each corresponding
  \t\t// update of the element's position.
  \t\tthis.fire('predrag', e);
  \t\tsetPosition(this._element, this._newPos);

  \t\t// @event drag: Event
  \t\t// Fired continuously during dragging.
  \t\tthis.fire('drag', e);
  \t},

  \t_onUp: function () {
  \t\t// Ignore the event if disabled; this happens in IE11
  \t\t// under some circumstances, see #3666.
  \t\tif (!this._enabled) { return; }
  \t\tthis.finishDrag();
  \t},

  \tfinishDrag: function (noInertia) {
  \t\tremoveClass(document.body, 'leaflet-dragging');

  \t\tif (this._lastTarget) {
  \t\t\tremoveClass(this._lastTarget, 'leaflet-drag-target');
  \t\t\tthis._lastTarget = null;
  \t\t}

  \t\toff(document, 'mousemove touchmove', this._onMove, this);
  \t\toff(document, 'mouseup touchend touchcancel', this._onUp, this);

  \t\tenableImageDrag();
  \t\tenableTextSelection();

  \t\tvar fireDragend = this._moved && this._moving;

  \t\tthis._moving = false;
  \t\tDraggable._dragging = false;

  \t\tif (fireDragend) {
  \t\t\t// @event dragend: DragEndEvent
  \t\t\t// Fired when the drag ends.
  \t\t\tthis.fire('dragend', {
  \t\t\t\tnoInertia: noInertia,
  \t\t\t\tdistance: this._newPos.distanceTo(this._startPos)
  \t\t\t});
  \t\t}
  \t}

  });

  /*
   * @namespace PolyUtil
   * Various utility functions for polygon geometries.
   */

  /* @function clipPolygon(points: Point[], bounds: Bounds, round?: Boolean): Point[]
   * Clips the polygon geometry defined by the given `points` by the given bounds (using the [Sutherland-Hodgman algorithm](https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm)).
   * Used by Leaflet to only show polygon points that are on the screen or near, increasing
   * performance. Note that polygon points needs different algorithm for clipping
   * than polyline, so there's a separate method for it.
   */
  function clipPolygon(points, bounds, round) {
  \tvar clippedPoints,
  \t    edges = [1, 4, 2, 8],
  \t    i, j, k,
  \t    a, b,
  \t    len, edge, p;

  \tfor (i = 0, len = points.length; i < len; i++) {
  \t\tpoints[i]._code = _getBitCode(points[i], bounds);
  \t}

  \t// for each edge (left, bottom, right, top)
  \tfor (k = 0; k < 4; k++) {
  \t\tedge = edges[k];
  \t\tclippedPoints = [];

  \t\tfor (i = 0, len = points.length, j = len - 1; i < len; j = i++) {
  \t\t\ta = points[i];
  \t\t\tb = points[j];

  \t\t\t// if a is inside the clip window
  \t\t\tif (!(a._code & edge)) {
  \t\t\t\t// if b is outside the clip window (a->b goes out of screen)
  \t\t\t\tif (b._code & edge) {
  \t\t\t\t\tp = _getEdgeIntersection(b, a, edge, bounds, round);
  \t\t\t\t\tp._code = _getBitCode(p, bounds);
  \t\t\t\t\tclippedPoints.push(p);
  \t\t\t\t}
  \t\t\t\tclippedPoints.push(a);

  \t\t\t// else if b is inside the clip window (a->b enters the screen)
  \t\t\t} else if (!(b._code & edge)) {
  \t\t\t\tp = _getEdgeIntersection(b, a, edge, bounds, round);
  \t\t\t\tp._code = _getBitCode(p, bounds);
  \t\t\t\tclippedPoints.push(p);
  \t\t\t}
  \t\t}
  \t\tpoints = clippedPoints;
  \t}

  \treturn points;
  }

  /* @function polygonCenter(latlngs: LatLng[], crs: CRS): LatLng
   * Returns the center ([centroid](http://en.wikipedia.org/wiki/Centroid)) of the passed LatLngs (first ring) from a polygon.
   */
  function polygonCenter(latlngs, crs) {
  \tvar i, j, p1, p2, f, area, x, y, center;

  \tif (!latlngs || latlngs.length === 0) {
  \t\tthrow new Error('latlngs not passed');
  \t}

  \tif (!isFlat(latlngs)) {
  \t\tconsole.warn('latlngs are not flat! Only the first ring will be used');
  \t\tlatlngs = latlngs[0];
  \t}

  \tvar centroidLatLng = toLatLng([0, 0]);

  \tvar bounds = toLatLngBounds(latlngs);
  \tvar areaBounds = bounds.getNorthWest().distanceTo(bounds.getSouthWest()) * bounds.getNorthEast().distanceTo(bounds.getNorthWest());
  \t// tests showed that below 1700 rounding errors are happening
  \tif (areaBounds < 1700) {
  \t\t// getting a inexact center, to move the latlngs near to [0, 0] to prevent rounding errors
  \t\tcentroidLatLng = centroid(latlngs);
  \t}

  \tvar len = latlngs.length;
  \tvar points = [];
  \tfor (i = 0; i < len; i++) {
  \t\tvar latlng = toLatLng(latlngs[i]);
  \t\tpoints.push(crs.project(toLatLng([latlng.lat - centroidLatLng.lat, latlng.lng - centroidLatLng.lng])));
  \t}

  \tarea = x = y = 0;

  \t// polygon centroid algorithm;
  \tfor (i = 0, j = len - 1; i < len; j = i++) {
  \t\tp1 = points[i];
  \t\tp2 = points[j];

  \t\tf = p1.y * p2.x - p2.y * p1.x;
  \t\tx += (p1.x + p2.x) * f;
  \t\ty += (p1.y + p2.y) * f;
  \t\tarea += f * 3;
  \t}

  \tif (area === 0) {
  \t\t// Polygon is so small that all points are on same pixel.
  \t\tcenter = points[0];
  \t} else {
  \t\tcenter = [x / area, y / area];
  \t}

  \tvar latlngCenter = crs.unproject(toPoint(center));
  \treturn toLatLng([latlngCenter.lat + centroidLatLng.lat, latlngCenter.lng + centroidLatLng.lng]);
  }

  /* @function centroid(latlngs: LatLng[]): LatLng
   * Returns the 'center of mass' of the passed LatLngs.
   */
  function centroid(coords) {
  \tvar latSum = 0;
  \tvar lngSum = 0;
  \tvar len = 0;
  \tfor (var i = 0; i < coords.length; i++) {
  \t\tvar latlng = toLatLng(coords[i]);
  \t\tlatSum += latlng.lat;
  \t\tlngSum += latlng.lng;
  \t\tlen++;
  \t}
  \treturn toLatLng([latSum / len, lngSum / len]);
  }

  var PolyUtil = {
    __proto__: null,
    clipPolygon: clipPolygon,
    polygonCenter: polygonCenter,
    centroid: centroid
  };

  /*
   * @namespace LineUtil
   *
   * Various utility functions for polyline points processing, used by Leaflet internally to make polylines lightning-fast.
   */

  // Simplify polyline with vertex reduction and Douglas-Peucker simplification.
  // Improves rendering performance dramatically by lessening the number of points to draw.

  // @function simplify(points: Point[], tolerance: Number): Point[]
  // Dramatically reduces the number of points in a polyline while retaining
  // its shape and returns a new array of simplified points, using the
  // [Ramer-Douglas-Peucker algorithm](https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm).
  // Used for a huge performance boost when processing/displaying Leaflet polylines for
  // each zoom level and also reducing visual noise. tolerance affects the amount of
  // simplification (lesser value means higher quality but slower and with more points).
  // Also released as a separated micro-library [Simplify.js](https://mourner.github.io/simplify-js/).
  function simplify(points, tolerance) {
  \tif (!tolerance || !points.length) {
  \t\treturn points.slice();
  \t}

  \tvar sqTolerance = tolerance * tolerance;

  \t    // stage 1: vertex reduction
  \t    points = _reducePoints(points, sqTolerance);

  \t    // stage 2: Douglas-Peucker simplification
  \t    points = _simplifyDP(points, sqTolerance);

  \treturn points;
  }

  // @function pointToSegmentDistance(p: Point, p1: Point, p2: Point): Number
  // Returns the distance between point `p` and segment `p1` to `p2`.
  function pointToSegmentDistance(p, p1, p2) {
  \treturn Math.sqrt(_sqClosestPointOnSegment(p, p1, p2, true));
  }

  // @function closestPointOnSegment(p: Point, p1: Point, p2: Point): Number
  // Returns the closest point from a point `p` on a segment `p1` to `p2`.
  function closestPointOnSegment(p, p1, p2) {
  \treturn _sqClosestPointOnSegment(p, p1, p2);
  }

  // Ramer-Douglas-Peucker simplification, see https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
  function _simplifyDP(points, sqTolerance) {

  \tvar len = points.length,
  \t    ArrayConstructor = typeof Uint8Array !== undefined + '' ? Uint8Array : Array,
  \t    markers = new ArrayConstructor(len);

  \t    markers[0] = markers[len - 1] = 1;

  \t_simplifyDPStep(points, markers, sqTolerance, 0, len - 1);

  \tvar i,
  \t    newPoints = [];

  \tfor (i = 0; i < len; i++) {
  \t\tif (markers[i]) {
  \t\t\tnewPoints.push(points[i]);
  \t\t}
  \t}

  \treturn newPoints;
  }

  function _simplifyDPStep(points, markers, sqTolerance, first, last) {

  \tvar maxSqDist = 0,
  \tindex, i, sqDist;

  \tfor (i = first + 1; i <= last - 1; i++) {
  \t\tsqDist = _sqClosestPointOnSegment(points[i], points[first], points[last], true);

  \t\tif (sqDist > maxSqDist) {
  \t\t\tindex = i;
  \t\t\tmaxSqDist = sqDist;
  \t\t}
  \t}

  \tif (maxSqDist > sqTolerance) {
  \t\tmarkers[index] = 1;

  \t\t_simplifyDPStep(points, markers, sqTolerance, first, index);
  \t\t_simplifyDPStep(points, markers, sqTolerance, index, last);
  \t}
  }

  // reduce points that are too close to each other to a single point
  function _reducePoints(points, sqTolerance) {
  \tvar reducedPoints = [points[0]];

  \tfor (var i = 1, prev = 0, len = points.length; i < len; i++) {
  \t\tif (_sqDist(points[i], points[prev]) > sqTolerance) {
  \t\t\treducedPoints.push(points[i]);
  \t\t\tprev = i;
  \t\t}
  \t}
  \tif (prev < len - 1) {
  \t\treducedPoints.push(points[len - 1]);
  \t}
  \treturn reducedPoints;
  }

  var _lastCode;

  // @function clipSegment(a: Point, b: Point, bounds: Bounds, useLastCode?: Boolean, round?: Boolean): Point[]|Boolean
  // Clips the segment a to b by rectangular bounds with the
  // [Cohen-Sutherland algorithm](https://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland_algorithm)
  // (modifying the segment points directly!). Used by Leaflet to only show polyline
  // points that are on the screen or near, increasing performance.
  function clipSegment(a, b, bounds, useLastCode, round) {
  \tvar codeA = useLastCode ? _lastCode : _getBitCode(a, bounds),
  \t    codeB = _getBitCode(b, bounds),

  \t    codeOut, p, newCode;

  \t    // save 2nd code to avoid calculating it on the next segment
  \t    _lastCode = codeB;

  \twhile (true) {
  \t\t// if a,b is inside the clip window (trivial accept)
  \t\tif (!(codeA | codeB)) {
  \t\t\treturn [a, b];
  \t\t}

  \t\t// if a,b is outside the clip window (trivial reject)
  \t\tif (codeA & codeB) {
  \t\t\treturn false;
  \t\t}

  \t\t// other cases
  \t\tcodeOut = codeA || codeB;
  \t\tp = _getEdgeIntersection(a, b, codeOut, bounds, round);
  \t\tnewCode = _getBitCode(p, bounds);

  \t\tif (codeOut === codeA) {
  \t\t\ta = p;
  \t\t\tcodeA = newCode;
  \t\t} else {
  \t\t\tb = p;
  \t\t\tcodeB = newCode;
  \t\t}
  \t}
  }

  function _getEdgeIntersection(a, b, code, bounds, round) {
  \tvar dx = b.x - a.x,
  \t    dy = b.y - a.y,
  \t    min = bounds.min,
  \t    max = bounds.max,
  \t    x, y;

  \tif (code & 8) { // top
  \t\tx = a.x + dx * (max.y - a.y) / dy;
  \t\ty = max.y;

  \t} else if (code & 4) { // bottom
  \t\tx = a.x + dx * (min.y - a.y) / dy;
  \t\ty = min.y;

  \t} else if (code & 2) { // right
  \t\tx = max.x;
  \t\ty = a.y + dy * (max.x - a.x) / dx;

  \t} else if (code & 1) { // left
  \t\tx = min.x;
  \t\ty = a.y + dy * (min.x - a.x) / dx;
  \t}

  \treturn new Point(x, y, round);
  }

  function _getBitCode(p, bounds) {
  \tvar code = 0;

  \tif (p.x < bounds.min.x) { // left
  \t\tcode |= 1;
  \t} else if (p.x > bounds.max.x) { // right
  \t\tcode |= 2;
  \t}

  \tif (p.y < bounds.min.y) { // bottom
  \t\tcode |= 4;
  \t} else if (p.y > bounds.max.y) { // top
  \t\tcode |= 8;
  \t}

  \treturn code;
  }

  // square distance (to avoid unnecessary Math.sqrt calls)
  function _sqDist(p1, p2) {
  \tvar dx = p2.x - p1.x,
  \t    dy = p2.y - p1.y;
  \treturn dx * dx + dy * dy;
  }

  // return closest point on segment or distance to that point
  function _sqClosestPointOnSegment(p, p1, p2, sqDist) {
  \tvar x = p1.x,
  \t    y = p1.y,
  \t    dx = p2.x - x,
  \t    dy = p2.y - y,
  \t    dot = dx * dx + dy * dy,
  \t    t;

  \tif (dot > 0) {
  \t\tt = ((p.x - x) * dx + (p.y - y) * dy) / dot;

  \t\tif (t > 1) {
  \t\t\tx = p2.x;
  \t\t\ty = p2.y;
  \t\t} else if (t > 0) {
  \t\t\tx += dx * t;
  \t\t\ty += dy * t;
  \t\t}
  \t}

  \tdx = p.x - x;
  \tdy = p.y - y;

  \treturn sqDist ? dx * dx + dy * dy : new Point(x, y);
  }


  // @function isFlat(latlngs: LatLng[]): Boolean
  // Returns true if `latlngs` is a flat array, false is nested.
  function isFlat(latlngs) {
  \treturn !isArray(latlngs[0]) || (typeof latlngs[0][0] !== 'object' && typeof latlngs[0][0] !== 'undefined');
  }

  function _flat(latlngs) {
  \tconsole.warn('Deprecated use of _flat, please use L.LineUtil.isFlat instead.');
  \treturn isFlat(latlngs);
  }

  /* @function polylineCenter(latlngs: LatLng[], crs: CRS): LatLng
   * Returns the center ([centroid](http://en.wikipedia.org/wiki/Centroid)) of the passed LatLngs (first ring) from a polyline.
   */
  function polylineCenter(latlngs, crs) {
  \tvar i, halfDist, segDist, dist, p1, p2, ratio, center;

  \tif (!latlngs || latlngs.length === 0) {
  \t\tthrow new Error('latlngs not passed');
  \t}

  \tif (!isFlat(latlngs)) {
  \t\tconsole.warn('latlngs are not flat! Only the first ring will be used');
  \t\tlatlngs = latlngs[0];
  \t}

  \tvar centroidLatLng = toLatLng([0, 0]);

  \tvar bounds = toLatLngBounds(latlngs);
  \tvar areaBounds = bounds.getNorthWest().distanceTo(bounds.getSouthWest()) * bounds.getNorthEast().distanceTo(bounds.getNorthWest());
  \t// tests showed that below 1700 rounding errors are happening
  \tif (areaBounds < 1700) {
  \t\t// getting a inexact center, to move the latlngs near to [0, 0] to prevent rounding errors
  \t\tcentroidLatLng = centroid(latlngs);
  \t}

  \tvar len = latlngs.length;
  \tvar points = [];
  \tfor (i = 0; i < len; i++) {
  \t\tvar latlng = toLatLng(latlngs[i]);
  \t\tpoints.push(crs.project(toLatLng([latlng.lat - centroidLatLng.lat, latlng.lng - centroidLatLng.lng])));
  \t}

  \tfor (i = 0, halfDist = 0; i < len - 1; i++) {
  \t\thalfDist += points[i].distanceTo(points[i + 1]) / 2;
  \t}

  \t// The line is so small in the current view that all points are on the same pixel.
  \tif (halfDist === 0) {
  \t\tcenter = points[0];
  \t} else {
  \t\tfor (i = 0, dist = 0; i < len - 1; i++) {
  \t\t\tp1 = points[i];
  \t\t\tp2 = points[i + 1];
  \t\t\tsegDist = p1.distanceTo(p2);
  \t\t\tdist += segDist;

  \t\t\tif (dist > halfDist) {
  \t\t\t\tratio = (dist - halfDist) / segDist;
  \t\t\t\tcenter = [
  \t\t\t\t\tp2.x - ratio * (p2.x - p1.x),
  \t\t\t\t\tp2.y - ratio * (p2.y - p1.y)
  \t\t\t\t];
  \t\t\t\tbreak;
  \t\t\t}
  \t\t}
  \t}

  \tvar latlngCenter = crs.unproject(toPoint(center));
  \treturn toLatLng([latlngCenter.lat + centroidLatLng.lat, latlngCenter.lng + centroidLatLng.lng]);
  }

  var LineUtil = {
    __proto__: null,
    simplify: simplify,
    pointToSegmentDistance: pointToSegmentDistance,
    closestPointOnSegment: closestPointOnSegment,
    clipSegment: clipSegment,
    _getEdgeIntersection: _getEdgeIntersection,
    _getBitCode: _getBitCode,
    _sqClosestPointOnSegment: _sqClosestPointOnSegment,
    isFlat: isFlat,
    _flat: _flat,
    polylineCenter: polylineCenter
  };

  /*
   * @namespace Projection
   * @section
   * Leaflet comes with a set of already defined Projections out of the box:
   *
   * @projection L.Projection.LonLat
   *
   * Equirectangular, or Plate Carree projection — the most simple projection,
   * mostly used by GIS enthusiasts. Directly maps `x` as longitude, and `y` as
   * latitude. Also suitable for flat worlds, e.g. game maps. Used by the
   * `EPSG:4326` and `Simple` CRS.
   */

  var LonLat = {
  \tproject: function (latlng) {
  \t\treturn new Point(latlng.lng, latlng.lat);
  \t},

  \tunproject: function (point) {
  \t\treturn new LatLng(point.y, point.x);
  \t},

  \tbounds: new Bounds([-180, -90], [180, 90])
  };

  /*
   * @namespace Projection
   * @projection L.Projection.Mercator
   *
   * Elliptical Mercator projection — more complex than Spherical Mercator. Assumes that Earth is an ellipsoid. Used by the EPSG:3395 CRS.
   */

  var Mercator = {
  \tR: 6378137,
  \tR_MINOR: 6356752.314245179,

  \tbounds: new Bounds([-20037508.34279, -15496570.73972], [20037508.34279, 18764656.23138]),

  \tproject: function (latlng) {
  \t\tvar d = Math.PI / 180,
  \t\t    r = this.R,
  \t\t    y = latlng.lat * d,
  \t\t    tmp = this.R_MINOR / r,
  \t\t    e = Math.sqrt(1 - tmp * tmp),
  \t\t    con = e * Math.sin(y);

  \t\tvar ts = Math.tan(Math.PI / 4 - y / 2) / Math.pow((1 - con) / (1 + con), e / 2);
  \t\ty = -r * Math.log(Math.max(ts, 1E-10));

  \t\treturn new Point(latlng.lng * d * r, y);
  \t},

  \tunproject: function (point) {
  \t\tvar d = 180 / Math.PI,
  \t\t    r = this.R,
  \t\t    tmp = this.R_MINOR / r,
  \t\t    e = Math.sqrt(1 - tmp * tmp),
  \t\t    ts = Math.exp(-point.y / r),
  \t\t    phi = Math.PI / 2 - 2 * Math.atan(ts);

  \t\tfor (var i = 0, dphi = 0.1, con; i < 15 && Math.abs(dphi) > 1e-7; i++) {
  \t\t\tcon = e * Math.sin(phi);
  \t\t\tcon = Math.pow((1 - con) / (1 + con), e / 2);
  \t\t\tdphi = Math.PI / 2 - 2 * Math.atan(ts * con) - phi;
  \t\t\tphi += dphi;
  \t\t}

  \t\treturn new LatLng(phi * d, point.x * d / r);
  \t}
  };

  /*
   * @class Projection

   * An object with methods for projecting geographical coordinates of the world onto
   * a flat surface (and back). See [Map projection](https://en.wikipedia.org/wiki/Map_projection).

   * @property bounds: Bounds
   * The bounds (specified in CRS units) where the projection is valid

   * @method project(latlng: LatLng): Point
   * Projects geographical coordinates into a 2D point.
   * Only accepts actual `L.LatLng` instances, not arrays.

   * @method unproject(point: Point): LatLng
   * The inverse of `project`. Projects a 2D point into a geographical location.
   * Only accepts actual `L.Point` instances, not arrays.

   * Note that the projection instances do not inherit from Leaflet's `Class` object,
   * and can't be instantiated. Also, new classes can't inherit from them,
   * and methods can't be added to them with the `include` function.

   */

  var index = {
    __proto__: null,
    LonLat: LonLat,
    Mercator: Mercator,
    SphericalMercator: SphericalMercator
  };

  /*
   * @namespace CRS
   * @crs L.CRS.EPSG3395
   *
   * Rarely used by some commercial tile providers. Uses Elliptical Mercator projection.
   */
  var EPSG3395 = extend({}, Earth, {
  \tcode: 'EPSG:3395',
  \tprojection: Mercator,

  \ttransformation: (function () {
  \t\tvar scale = 0.5 / (Math.PI * Mercator.R);
  \t\treturn toTransformation(scale, 0.5, -scale, 0.5);
  \t}())
  });

  /*
   * @namespace CRS
   * @crs L.CRS.EPSG4326
   *
   * A common CRS among GIS enthusiasts. Uses simple Equirectangular projection.
   *
   * Leaflet 1.0.x complies with the [TMS coordinate scheme for EPSG:4326](https://wiki.osgeo.org/wiki/Tile_Map_Service_Specification#global-geodetic),
   * which is a breaking change from 0.7.x behaviour.  If you are using a `TileLayer`
   * with this CRS, ensure that there are two 256x256 pixel tiles covering the
   * whole earth at zoom level zero, and that the tile coordinate origin is (-180,+90),
   * or (-180,-90) for `TileLayer`s with [the `tms` option](#tilelayer-tms) set.
   */

  var EPSG4326 = extend({}, Earth, {
  \tcode: 'EPSG:4326',
  \tprojection: LonLat,
  \ttransformation: toTransformation(1 / 180, 1, -1 / 180, 0.5)
  });

  /*
   * @namespace CRS
   * @crs L.CRS.Simple
   *
   * A simple CRS that maps longitude and latitude into `x` and `y` directly.
   * May be used for maps of flat surfaces (e.g. game maps). Note that the `y`
   * axis should still be inverted (going from bottom to top). `distance()` returns
   * simple euclidean distance.
   */

  var Simple = extend({}, CRS, {
  \tprojection: LonLat,
  \ttransformation: toTransformation(1, 0, -1, 0),

  \tscale: function (zoom) {
  \t\treturn Math.pow(2, zoom);
  \t},

  \tzoom: function (scale) {
  \t\treturn Math.log(scale) / Math.LN2;
  \t},

  \tdistance: function (latlng1, latlng2) {
  \t\tvar dx = latlng2.lng - latlng1.lng,
  \t\t    dy = latlng2.lat - latlng1.lat;

  \t\treturn Math.sqrt(dx * dx + dy * dy);
  \t},

  \tinfinite: true
  });

  CRS.Earth = Earth;
  CRS.EPSG3395 = EPSG3395;
  CRS.EPSG3857 = EPSG3857;
  CRS.EPSG900913 = EPSG900913;
  CRS.EPSG4326 = EPSG4326;
  CRS.Simple = Simple;

  /*
   * @class Layer
   * @inherits Evented
   * @aka L.Layer
   * @aka ILayer
   *
   * A set of methods from the Layer base class that all Leaflet layers use.
   * Inherits all methods, options and events from `L.Evented`.
   *
   * @example
   *
   * ```js
   * var layer = L.marker(latlng).addTo(map);
   * layer.addTo(map);
   * layer.remove();
   * ```
   *
   * @event add: Event
   * Fired after the layer is added to a map
   *
   * @event remove: Event
   * Fired after the layer is removed from a map
   */


  var Layer = Evented.extend({

  \t// Classes extending `L.Layer` will inherit the following options:
  \toptions: {
  \t\t// @option pane: String = 'overlayPane'
  \t\t// By default the layer will be added to the map's [overlay pane](#map-overlaypane). Overriding this option will cause the layer to be placed on another pane by default.
  \t\tpane: 'overlayPane',

  \t\t// @option attribution: String = null
  \t\t// String to be shown in the attribution control, e.g. \"© OpenStreetMap contributors\". It describes the layer data and is often a legal obligation towards copyright holders and tile providers.
  \t\tattribution: null,

  \t\tbubblingMouseEvents: true
  \t},

  \t/* @section
  \t * Classes extending `L.Layer` will inherit the following methods:
  \t *
  \t * @method addTo(map: Map|LayerGroup): this
  \t * Adds the layer to the given map or layer group.
  \t */
  \taddTo: function (map) {
  \t\tmap.addLayer(this);
  \t\treturn this;
  \t},

  \t// @method remove: this
  \t// Removes the layer from the map it is currently active on.
  \tremove: function () {
  \t\treturn this.removeFrom(this._map || this._mapToAdd);
  \t},

  \t// @method removeFrom(map: Map): this
  \t// Removes the layer from the given map
  \t//
  \t// @alternative
  \t// @method removeFrom(group: LayerGroup): this
  \t// Removes the layer from the given `LayerGroup`
  \tremoveFrom: function (obj) {
  \t\tif (obj) {
  \t\t\tobj.removeLayer(this);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method getPane(name? : String): HTMLElement
  \t// Returns the `HTMLElement` representing the named pane on the map. If `name` is omitted, returns the pane for this layer.
  \tgetPane: function (name) {
  \t\treturn this._map.getPane(name ? (this.options[name] || name) : this.options.pane);
  \t},

  \taddInteractiveTarget: function (targetEl) {
  \t\tthis._map._targets[stamp(targetEl)] = this;
  \t\treturn this;
  \t},

  \tremoveInteractiveTarget: function (targetEl) {
  \t\tdelete this._map._targets[stamp(targetEl)];
  \t\treturn this;
  \t},

  \t// @method getAttribution: String
  \t// Used by the `attribution control`, returns the [attribution option](#gridlayer-attribution).
  \tgetAttribution: function () {
  \t\treturn this.options.attribution;
  \t},

  \t_layerAdd: function (e) {
  \t\tvar map = e.target;

  \t\t// check in case layer gets added and then removed before the map is ready
  \t\tif (!map.hasLayer(this)) { return; }

  \t\tthis._map = map;
  \t\tthis._zoomAnimated = map._zoomAnimated;

  \t\tif (this.getEvents) {
  \t\t\tvar events = this.getEvents();
  \t\t\tmap.on(events, this);
  \t\t\tthis.once('remove', function () {
  \t\t\t\tmap.off(events, this);
  \t\t\t}, this);
  \t\t}

  \t\tthis.onAdd(map);

  \t\tthis.fire('add');
  \t\tmap.fire('layeradd', {layer: this});
  \t}
  });

  /* @section Extension methods
   * @uninheritable
   *
   * Every layer should extend from `L.Layer` and (re-)implement the following methods.
   *
   * @method onAdd(map: Map): this
   * Should contain code that creates DOM elements for the layer, adds them to `map panes` where they should belong and puts listeners on relevant map events. Called on [`map.addLayer(layer)`](#map-addlayer).
   *
   * @method onRemove(map: Map): this
   * Should contain all clean up code that removes the layer's elements from the DOM and removes listeners previously added in [`onAdd`](#layer-onadd). Called on [`map.removeLayer(layer)`](#map-removelayer).
   *
   * @method getEvents(): Object
   * This optional method should return an object like `{ viewreset: this._reset }` for [`addEventListener`](#evented-addeventlistener). The event handlers in this object will be automatically added and removed from the map with your layer.
   *
   * @method getAttribution(): String
   * This optional method should return a string containing HTML to be shown on the `Attribution control` whenever the layer is visible.
   *
   * @method beforeAdd(map: Map): this
   * Optional method. Called on [`map.addLayer(layer)`](#map-addlayer), before the layer is added to the map, before events are initialized, without waiting until the map is in a usable state. Use for early initialization only.
   */


  /* @namespace Map
   * @section Layer events
   *
   * @event layeradd: LayerEvent
   * Fired when a new layer is added to the map.
   *
   * @event layerremove: LayerEvent
   * Fired when some layer is removed from the map
   *
   * @section Methods for Layers and Controls
   */
  Map.include({
  \t// @method addLayer(layer: Layer): this
  \t// Adds the given layer to the map
  \taddLayer: function (layer) {
  \t\tif (!layer._layerAdd) {
  \t\t\tthrow new Error('The provided object is not a Layer.');
  \t\t}

  \t\tvar id = stamp(layer);
  \t\tif (this._layers[id]) { return this; }
  \t\tthis._layers[id] = layer;

  \t\tlayer._mapToAdd = this;

  \t\tif (layer.beforeAdd) {
  \t\t\tlayer.beforeAdd(this);
  \t\t}

  \t\tthis.whenReady(layer._layerAdd, layer);

  \t\treturn this;
  \t},

  \t// @method removeLayer(layer: Layer): this
  \t// Removes the given layer from the map.
  \tremoveLayer: function (layer) {
  \t\tvar id = stamp(layer);

  \t\tif (!this._layers[id]) { return this; }

  \t\tif (this._loaded) {
  \t\t\tlayer.onRemove(this);
  \t\t}

  \t\tdelete this._layers[id];

  \t\tif (this._loaded) {
  \t\t\tthis.fire('layerremove', {layer: layer});
  \t\t\tlayer.fire('remove');
  \t\t}

  \t\tlayer._map = layer._mapToAdd = null;

  \t\treturn this;
  \t},

  \t// @method hasLayer(layer: Layer): Boolean
  \t// Returns `true` if the given layer is currently added to the map
  \thasLayer: function (layer) {
  \t\treturn stamp(layer) in this._layers;
  \t},

  \t/* @method eachLayer(fn: Function, context?: Object): this
  \t * Iterates over the layers of the map, optionally specifying context of the iterator function.
  \t * ```
  \t * map.eachLayer(function(layer){
  \t *     layer.bindPopup('Hello');
  \t * });
  \t * ```
  \t */
  \teachLayer: function (method, context) {
  \t\tfor (var i in this._layers) {
  \t\t\tmethod.call(context, this._layers[i]);
  \t\t}
  \t\treturn this;
  \t},

  \t_addLayers: function (layers) {
  \t\tlayers = layers ? (isArray(layers) ? layers : [layers]) : [];

  \t\tfor (var i = 0, len = layers.length; i < len; i++) {
  \t\t\tthis.addLayer(layers[i]);
  \t\t}
  \t},

  \t_addZoomLimit: function (layer) {
  \t\tif (!isNaN(layer.options.maxZoom) || !isNaN(layer.options.minZoom)) {
  \t\t\tthis._zoomBoundLayers[stamp(layer)] = layer;
  \t\t\tthis._updateZoomLevels();
  \t\t}
  \t},

  \t_removeZoomLimit: function (layer) {
  \t\tvar id = stamp(layer);

  \t\tif (this._zoomBoundLayers[id]) {
  \t\t\tdelete this._zoomBoundLayers[id];
  \t\t\tthis._updateZoomLevels();
  \t\t}
  \t},

  \t_updateZoomLevels: function () {
  \t\tvar minZoom = Infinity,
  \t\t    maxZoom = -Infinity,
  \t\t    oldZoomSpan = this._getZoomSpan();

  \t\tfor (var i in this._zoomBoundLayers) {
  \t\t\tvar options = this._zoomBoundLayers[i].options;

  \t\t\tminZoom = options.minZoom === undefined ? minZoom : Math.min(minZoom, options.minZoom);
  \t\t\tmaxZoom = options.maxZoom === undefined ? maxZoom : Math.max(maxZoom, options.maxZoom);
  \t\t}

  \t\tthis._layersMaxZoom = maxZoom === -Infinity ? undefined : maxZoom;
  \t\tthis._layersMinZoom = minZoom === Infinity ? undefined : minZoom;

  \t\t// @section Map state change events
  \t\t// @event zoomlevelschange: Event
  \t\t// Fired when the number of zoomlevels on the map is changed due
  \t\t// to adding or removing a layer.
  \t\tif (oldZoomSpan !== this._getZoomSpan()) {
  \t\t\tthis.fire('zoomlevelschange');
  \t\t}

  \t\tif (this.options.maxZoom === undefined && this._layersMaxZoom && this.getZoom() > this._layersMaxZoom) {
  \t\t\tthis.setZoom(this._layersMaxZoom);
  \t\t}
  \t\tif (this.options.minZoom === undefined && this._layersMinZoom && this.getZoom() < this._layersMinZoom) {
  \t\t\tthis.setZoom(this._layersMinZoom);
  \t\t}
  \t}
  });

  /*
   * @class LayerGroup
   * @aka L.LayerGroup
   * @inherits Interactive layer
   *
   * Used to group several layers and handle them as one. If you add it to the map,
   * any layers added or removed from the group will be added/removed on the map as
   * well. Extends `Layer`.
   *
   * @example
   *
   * ```js
   * L.layerGroup([marker1, marker2])
   * \t.addLayer(polyline)
   * \t.addTo(map);
   * ```
   */

  var LayerGroup = Layer.extend({

  \tinitialize: function (layers, options) {
  \t\tsetOptions(this, options);

  \t\tthis._layers = {};

  \t\tvar i, len;

  \t\tif (layers) {
  \t\t\tfor (i = 0, len = layers.length; i < len; i++) {
  \t\t\t\tthis.addLayer(layers[i]);
  \t\t\t}
  \t\t}
  \t},

  \t// @method addLayer(layer: Layer): this
  \t// Adds the given layer to the group.
  \taddLayer: function (layer) {
  \t\tvar id = this.getLayerId(layer);

  \t\tthis._layers[id] = layer;

  \t\tif (this._map) {
  \t\t\tthis._map.addLayer(layer);
  \t\t}

  \t\treturn this;
  \t},

  \t// @method removeLayer(layer: Layer): this
  \t// Removes the given layer from the group.
  \t// @alternative
  \t// @method removeLayer(id: Number): this
  \t// Removes the layer with the given internal ID from the group.
  \tremoveLayer: function (layer) {
  \t\tvar id = layer in this._layers ? layer : this.getLayerId(layer);

  \t\tif (this._map && this._layers[id]) {
  \t\t\tthis._map.removeLayer(this._layers[id]);
  \t\t}

  \t\tdelete this._layers[id];

  \t\treturn this;
  \t},

  \t// @method hasLayer(layer: Layer): Boolean
  \t// Returns `true` if the given layer is currently added to the group.
  \t// @alternative
  \t// @method hasLayer(id: Number): Boolean
  \t// Returns `true` if the given internal ID is currently added to the group.
  \thasLayer: function (layer) {
  \t\tvar layerId = typeof layer === 'number' ? layer : this.getLayerId(layer);
  \t\treturn layerId in this._layers;
  \t},

  \t// @method clearLayers(): this
  \t// Removes all the layers from the group.
  \tclearLayers: function () {
  \t\treturn this.eachLayer(this.removeLayer, this);
  \t},

  \t// @method invoke(methodName: String, …): this
  \t// Calls `methodName` on every layer contained in this group, passing any
  \t// additional parameters. Has no effect if the layers contained do not
  \t// implement `methodName`.
  \tinvoke: function (methodName) {
  \t\tvar args = Array.prototype.slice.call(arguments, 1),
  \t\t    i, layer;

  \t\tfor (i in this._layers) {
  \t\t\tlayer = this._layers[i];

  \t\t\tif (layer[methodName]) {
  \t\t\t\tlayer[methodName].apply(layer, args);
  \t\t\t}
  \t\t}

  \t\treturn this;
  \t},

  \tonAdd: function (map) {
  \t\tthis.eachLayer(map.addLayer, map);
  \t},

  \tonRemove: function (map) {
  \t\tthis.eachLayer(map.removeLayer, map);
  \t},

  \t// @method eachLayer(fn: Function, context?: Object): this
  \t// Iterates over the layers of the group, optionally specifying context of the iterator function.
  \t// ```js
  \t// group.eachLayer(function (layer) {
  \t// \tlayer.bindPopup('Hello');
  \t// });
  \t// ```
  \teachLayer: function (method, context) {
  \t\tfor (var i in this._layers) {
  \t\t\tmethod.call(context, this._layers[i]);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method getLayer(id: Number): Layer
  \t// Returns the layer with the given internal ID.
  \tgetLayer: function (id) {
  \t\treturn this._layers[id];
  \t},

  \t// @method getLayers(): Layer[]
  \t// Returns an array of all the layers added to the group.
  \tgetLayers: function () {
  \t\tvar layers = [];
  \t\tthis.eachLayer(layers.push, layers);
  \t\treturn layers;
  \t},

  \t// @method setZIndex(zIndex: Number): this
  \t// Calls `setZIndex` on every layer contained in this group, passing the z-index.
  \tsetZIndex: function (zIndex) {
  \t\treturn this.invoke('setZIndex', zIndex);
  \t},

  \t// @method getLayerId(layer: Layer): Number
  \t// Returns the internal ID for a layer
  \tgetLayerId: function (layer) {
  \t\treturn stamp(layer);
  \t}
  });


  // @factory L.layerGroup(layers?: Layer[], options?: Object)
  // Create a layer group, optionally given an initial set of layers and an `options` object.
  var layerGroup = function (layers, options) {
  \treturn new LayerGroup(layers, options);
  };

  /*
   * @class FeatureGroup
   * @aka L.FeatureGroup
   * @inherits LayerGroup
   *
   * Extended `LayerGroup` that makes it easier to do the same thing to all its member layers:
   *  * [`bindPopup`](#layer-bindpopup) binds a popup to all of the layers at once (likewise with [`bindTooltip`](#layer-bindtooltip))
   *  * Events are propagated to the `FeatureGroup`, so if the group has an event
   * handler, it will handle events from any of the layers. This includes mouse events
   * and custom events.
   *  * Has `layeradd` and `layerremove` events
   *
   * @example
   *
   * ```js
   * L.featureGroup([marker1, marker2, polyline])
   * \t.bindPopup('Hello world!')
   * \t.on('click', function() { alert('Clicked on a member of the group!'); })
   * \t.addTo(map);
   * ```
   */

  var FeatureGroup = LayerGroup.extend({

  \taddLayer: function (layer) {
  \t\tif (this.hasLayer(layer)) {
  \t\t\treturn this;
  \t\t}

  \t\tlayer.addEventParent(this);

  \t\tLayerGroup.prototype.addLayer.call(this, layer);

  \t\t// @event layeradd: LayerEvent
  \t\t// Fired when a layer is added to this `FeatureGroup`
  \t\treturn this.fire('layeradd', {layer: layer});
  \t},

  \tremoveLayer: function (layer) {
  \t\tif (!this.hasLayer(layer)) {
  \t\t\treturn this;
  \t\t}
  \t\tif (layer in this._layers) {
  \t\t\tlayer = this._layers[layer];
  \t\t}

  \t\tlayer.removeEventParent(this);

  \t\tLayerGroup.prototype.removeLayer.call(this, layer);

  \t\t// @event layerremove: LayerEvent
  \t\t// Fired when a layer is removed from this `FeatureGroup`
  \t\treturn this.fire('layerremove', {layer: layer});
  \t},

  \t// @method setStyle(style: Path options): this
  \t// Sets the given path options to each layer of the group that has a `setStyle` method.
  \tsetStyle: function (style) {
  \t\treturn this.invoke('setStyle', style);
  \t},

  \t// @method bringToFront(): this
  \t// Brings the layer group to the top of all other layers
  \tbringToFront: function () {
  \t\treturn this.invoke('bringToFront');
  \t},

  \t// @method bringToBack(): this
  \t// Brings the layer group to the back of all other layers
  \tbringToBack: function () {
  \t\treturn this.invoke('bringToBack');
  \t},

  \t// @method getBounds(): LatLngBounds
  \t// Returns the LatLngBounds of the Feature Group (created from bounds and coordinates of its children).
  \tgetBounds: function () {
  \t\tvar bounds = new LatLngBounds();

  \t\tfor (var id in this._layers) {
  \t\t\tvar layer = this._layers[id];
  \t\t\tbounds.extend(layer.getBounds ? layer.getBounds() : layer.getLatLng());
  \t\t}
  \t\treturn bounds;
  \t}
  });

  // @factory L.featureGroup(layers?: Layer[], options?: Object)
  // Create a feature group, optionally given an initial set of layers and an `options` object.
  var featureGroup = function (layers, options) {
  \treturn new FeatureGroup(layers, options);
  };

  /*
   * @class Icon
   * @aka L.Icon
   *
   * Represents an icon to provide when creating a marker.
   *
   * @example
   *
   * ```js
   * var myIcon = L.icon({
   *     iconUrl: 'my-icon.png',
   *     iconRetinaUrl: 'my-icon@2x.png',
   *     iconSize: [38, 95],
   *     iconAnchor: [22, 94],
   *     popupAnchor: [-3, -76],
   *     shadowUrl: 'my-icon-shadow.png',
   *     shadowRetinaUrl: 'my-icon-shadow@2x.png',
   *     shadowSize: [68, 95],
   *     shadowAnchor: [22, 94]
   * });
   *
   * L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
   * ```
   *
   * `L.Icon.Default` extends `L.Icon` and is the blue icon Leaflet uses for markers by default.
   *
   */

  var Icon = Class.extend({

  \t/* @section
  \t * @aka Icon options
  \t *
  \t * @option iconUrl: String = null
  \t * **(required)** The URL to the icon image (absolute or relative to your script path).
  \t *
  \t * @option iconRetinaUrl: String = null
  \t * The URL to a retina sized version of the icon image (absolute or relative to your
  \t * script path). Used for Retina screen devices.
  \t *
  \t * @option iconSize: Point = null
  \t * Size of the icon image in pixels.
  \t *
  \t * @option iconAnchor: Point = null
  \t * The coordinates of the \"tip\" of the icon (relative to its top left corner). The icon
  \t * will be aligned so that this point is at the marker's geographical location. Centered
  \t * by default if size is specified, also can be set in CSS with negative margins.
  \t *
  \t * @option popupAnchor: Point = [0, 0]
  \t * The coordinates of the point from which popups will \"open\", relative to the icon anchor.
  \t *
  \t * @option tooltipAnchor: Point = [0, 0]
  \t * The coordinates of the point from which tooltips will \"open\", relative to the icon anchor.
  \t *
  \t * @option shadowUrl: String = null
  \t * The URL to the icon shadow image. If not specified, no shadow image will be created.
  \t *
  \t * @option shadowRetinaUrl: String = null
  \t *
  \t * @option shadowSize: Point = null
  \t * Size of the shadow image in pixels.
  \t *
  \t * @option shadowAnchor: Point = null
  \t * The coordinates of the \"tip\" of the shadow (relative to its top left corner) (the same
  \t * as iconAnchor if not specified).
  \t *
  \t * @option className: String = ''
  \t * A custom class name to assign to both icon and shadow images. Empty by default.
  \t */

  \toptions: {
  \t\tpopupAnchor: [0, 0],
  \t\ttooltipAnchor: [0, 0],

  \t\t// @option crossOrigin: Boolean|String = false
  \t\t// Whether the crossOrigin attribute will be added to the tiles.
  \t\t// If a String is provided, all tiles will have their crossOrigin attribute set to the String provided. This is needed if you want to access tile pixel data.
  \t\t// Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values.
  \t\tcrossOrigin: false
  \t},

  \tinitialize: function (options) {
  \t\tsetOptions(this, options);
  \t},

  \t// @method createIcon(oldIcon?: HTMLElement): HTMLElement
  \t// Called internally when the icon has to be shown, returns a `<img>` HTML element
  \t// styled according to the options.
  \tcreateIcon: function (oldIcon) {
  \t\treturn this._createIcon('icon', oldIcon);
  \t},

  \t// @method createShadow(oldIcon?: HTMLElement): HTMLElement
  \t// As `createIcon`, but for the shadow beneath it.
  \tcreateShadow: function (oldIcon) {
  \t\treturn this._createIcon('shadow', oldIcon);
  \t},

  \t_createIcon: function (name, oldIcon) {
  \t\tvar src = this._getIconUrl(name);

  \t\tif (!src) {
  \t\t\tif (name === 'icon') {
  \t\t\t\tthrow new Error('iconUrl not set in Icon options (see the docs).');
  \t\t\t}
  \t\t\treturn null;
  \t\t}

  \t\tvar img = this._createImg(src, oldIcon && oldIcon.tagName === 'IMG' ? oldIcon : null);
  \t\tthis._setIconStyles(img, name);

  \t\tif (this.options.crossOrigin || this.options.crossOrigin === '') {
  \t\t\timg.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin;
  \t\t}

  \t\treturn img;
  \t},

  \t_setIconStyles: function (img, name) {
  \t\tvar options = this.options;
  \t\tvar sizeOption = options[name + 'Size'];

  \t\tif (typeof sizeOption === 'number') {
  \t\t\tsizeOption = [sizeOption, sizeOption];
  \t\t}

  \t\tvar size = toPoint(sizeOption),
  \t\t    anchor = toPoint(name === 'shadow' && options.shadowAnchor || options.iconAnchor ||
  \t\t            size && size.divideBy(2, true));

  \t\timg.className = 'leaflet-marker-' + name + ' ' + (options.className || '');

  \t\tif (anchor) {
  \t\t\timg.style.marginLeft = (-anchor.x) + 'px';
  \t\t\timg.style.marginTop  = (-anchor.y) + 'px';
  \t\t}

  \t\tif (size) {
  \t\t\timg.style.width  = size.x + 'px';
  \t\t\timg.style.height = size.y + 'px';
  \t\t}
  \t},

  \t_createImg: function (src, el) {
  \t\tel = el || document.createElement('img');
  \t\tel.src = src;
  \t\treturn el;
  \t},

  \t_getIconUrl: function (name) {
  \t\treturn Browser.retina && this.options[name + 'RetinaUrl'] || this.options[name + 'Url'];
  \t}
  });


  // @factory L.icon(options: Icon options)
  // Creates an icon instance with the given options.
  function icon(options) {
  \treturn new Icon(options);
  }

  /*
   * @miniclass Icon.Default (Icon)
   * @aka L.Icon.Default
   * @section
   *
   * A trivial subclass of `Icon`, represents the icon to use in `Marker`s when
   * no icon is specified. Points to the blue marker image distributed with Leaflet
   * releases.
   *
   * In order to customize the default icon, just change the properties of `L.Icon.Default.prototype.options`
   * (which is a set of `Icon options`).
   *
   * If you want to _completely_ replace the default icon, override the
   * `L.Marker.prototype.options.icon` with your own icon instead.
   */

  var IconDefault = Icon.extend({

  \toptions: {
  \t\ticonUrl:       'marker-icon.png',
  \t\ticonRetinaUrl: 'marker-icon-2x.png',
  \t\tshadowUrl:     'marker-shadow.png',
  \t\ticonSize:    [25, 41],
  \t\ticonAnchor:  [12, 41],
  \t\tpopupAnchor: [1, -34],
  \t\ttooltipAnchor: [16, -28],
  \t\tshadowSize:  [41, 41]
  \t},

  \t_getIconUrl: function (name) {
  \t\tif (typeof IconDefault.imagePath !== 'string') {\t// Deprecated, backwards-compatibility only
  \t\t\tIconDefault.imagePath = this._detectIconPath();
  \t\t}

  \t\t// @option imagePath: String
  \t\t// `Icon.Default` will try to auto-detect the location of the
  \t\t// blue icon images. If you are placing these images in a non-standard
  \t\t// way, set this option to point to the right path.
  \t\treturn (this.options.imagePath || IconDefault.imagePath) + Icon.prototype._getIconUrl.call(this, name);
  \t},

  \t_stripUrl: function (path) {\t// separate function to use in tests
  \t\tvar strip = function (str, re, idx) {
  \t\t\tvar match = re.exec(str);
  \t\t\treturn match && match[idx];
  \t\t};
  \t\tpath = strip(path, /^url\\((['\"])?(.+)\\1\\)\$/, 2);
  \t\treturn path && strip(path, /^(.*)marker-icon\\.png\$/, 1);
  \t},

  \t_detectIconPath: function () {
  \t\tvar el = create\$1('div',  'leaflet-default-icon-path', document.body);
  \t\tvar path = getStyle(el, 'background-image') ||
  \t\t           getStyle(el, 'backgroundImage');\t// IE8

  \t\tdocument.body.removeChild(el);
  \t\tpath = this._stripUrl(path);
  \t\tif (path) { return path; }
  \t\tvar link = document.querySelector('link[href\$=\"leaflet.css\"]');
  \t\tif (!link) { return ''; }
  \t\treturn link.href.substring(0, link.href.length - 'leaflet.css'.length - 1);
  \t}
  });

  /*
   * L.Handler.MarkerDrag is used internally by L.Marker to make the markers draggable.
   */


  /* @namespace Marker
   * @section Interaction handlers
   *
   * Interaction handlers are properties of a marker instance that allow you to control interaction behavior in runtime, enabling or disabling certain features such as dragging (see `Handler` methods). Example:
   *
   * ```js
   * marker.dragging.disable();
   * ```
   *
   * @property dragging: Handler
   * Marker dragging handler (by both mouse and touch). Only valid when the marker is on the map (Otherwise set [`marker.options.draggable`](#marker-draggable)).
   */

  var MarkerDrag = Handler.extend({
  \tinitialize: function (marker) {
  \t\tthis._marker = marker;
  \t},

  \taddHooks: function () {
  \t\tvar icon = this._marker._icon;

  \t\tif (!this._draggable) {
  \t\t\tthis._draggable = new Draggable(icon, icon, true);
  \t\t}

  \t\tthis._draggable.on({
  \t\t\tdragstart: this._onDragStart,
  \t\t\tpredrag: this._onPreDrag,
  \t\t\tdrag: this._onDrag,
  \t\t\tdragend: this._onDragEnd
  \t\t}, this).enable();

  \t\taddClass(icon, 'leaflet-marker-draggable');
  \t},

  \tremoveHooks: function () {
  \t\tthis._draggable.off({
  \t\t\tdragstart: this._onDragStart,
  \t\t\tpredrag: this._onPreDrag,
  \t\t\tdrag: this._onDrag,
  \t\t\tdragend: this._onDragEnd
  \t\t}, this).disable();

  \t\tif (this._marker._icon) {
  \t\t\tremoveClass(this._marker._icon, 'leaflet-marker-draggable');
  \t\t}
  \t},

  \tmoved: function () {
  \t\treturn this._draggable && this._draggable._moved;
  \t},

  \t_adjustPan: function (e) {
  \t\tvar marker = this._marker,
  \t\t    map = marker._map,
  \t\t    speed = this._marker.options.autoPanSpeed,
  \t\t    padding = this._marker.options.autoPanPadding,
  \t\t    iconPos = getPosition(marker._icon),
  \t\t    bounds = map.getPixelBounds(),
  \t\t    origin = map.getPixelOrigin();

  \t\tvar panBounds = toBounds(
  \t\t\tbounds.min._subtract(origin).add(padding),
  \t\t\tbounds.max._subtract(origin).subtract(padding)
  \t\t);

  \t\tif (!panBounds.contains(iconPos)) {
  \t\t\t// Compute incremental movement
  \t\t\tvar movement = toPoint(
  \t\t\t\t(Math.max(panBounds.max.x, iconPos.x) - panBounds.max.x) / (bounds.max.x - panBounds.max.x) -
  \t\t\t\t(Math.min(panBounds.min.x, iconPos.x) - panBounds.min.x) / (bounds.min.x - panBounds.min.x),

  \t\t\t\t(Math.max(panBounds.max.y, iconPos.y) - panBounds.max.y) / (bounds.max.y - panBounds.max.y) -
  \t\t\t\t(Math.min(panBounds.min.y, iconPos.y) - panBounds.min.y) / (bounds.min.y - panBounds.min.y)
  \t\t\t).multiplyBy(speed);

  \t\t\tmap.panBy(movement, {animate: false});

  \t\t\tthis._draggable._newPos._add(movement);
  \t\t\tthis._draggable._startPos._add(movement);

  \t\t\tsetPosition(marker._icon, this._draggable._newPos);
  \t\t\tthis._onDrag(e);

  \t\t\tthis._panRequest = requestAnimFrame(this._adjustPan.bind(this, e));
  \t\t}
  \t},

  \t_onDragStart: function () {
  \t\t// @section Dragging events
  \t\t// @event dragstart: Event
  \t\t// Fired when the user starts dragging the marker.

  \t\t// @event movestart: Event
  \t\t// Fired when the marker starts moving (because of dragging).

  \t\tthis._oldLatLng = this._marker.getLatLng();

  \t\t// When using ES6 imports it could not be set when `Popup` was not imported as well
  \t\tthis._marker.closePopup && this._marker.closePopup();

  \t\tthis._marker
  \t\t\t.fire('movestart')
  \t\t\t.fire('dragstart');
  \t},

  \t_onPreDrag: function (e) {
  \t\tif (this._marker.options.autoPan) {
  \t\t\tcancelAnimFrame(this._panRequest);
  \t\t\tthis._panRequest = requestAnimFrame(this._adjustPan.bind(this, e));
  \t\t}
  \t},

  \t_onDrag: function (e) {
  \t\tvar marker = this._marker,
  \t\t    shadow = marker._shadow,
  \t\t    iconPos = getPosition(marker._icon),
  \t\t    latlng = marker._map.layerPointToLatLng(iconPos);

  \t\t// update shadow position
  \t\tif (shadow) {
  \t\t\tsetPosition(shadow, iconPos);
  \t\t}

  \t\tmarker._latlng = latlng;
  \t\te.latlng = latlng;
  \t\te.oldLatLng = this._oldLatLng;

  \t\t// @event drag: Event
  \t\t// Fired repeatedly while the user drags the marker.
  \t\tmarker
  \t\t    .fire('move', e)
  \t\t    .fire('drag', e);
  \t},

  \t_onDragEnd: function (e) {
  \t\t// @event dragend: DragEndEvent
  \t\t// Fired when the user stops dragging the marker.

  \t\t cancelAnimFrame(this._panRequest);

  \t\t// @event moveend: Event
  \t\t// Fired when the marker stops moving (because of dragging).
  \t\tdelete this._oldLatLng;
  \t\tthis._marker
  \t\t    .fire('moveend')
  \t\t    .fire('dragend', e);
  \t}
  });

  /*
   * @class Marker
   * @inherits Interactive layer
   * @aka L.Marker
   * L.Marker is used to display clickable/draggable icons on the map. Extends `Layer`.
   *
   * @example
   *
   * ```js
   * L.marker([50.5, 30.5]).addTo(map);
   * ```
   */

  var Marker = Layer.extend({

  \t// @section
  \t// @aka Marker options
  \toptions: {
  \t\t// @option icon: Icon = *
  \t\t// Icon instance to use for rendering the marker.
  \t\t// See [Icon documentation](#L.Icon) for details on how to customize the marker icon.
  \t\t// If not specified, a common instance of `L.Icon.Default` is used.
  \t\ticon: new IconDefault(),

  \t\t// Option inherited from \"Interactive layer\" abstract class
  \t\tinteractive: true,

  \t\t// @option keyboard: Boolean = true
  \t\t// Whether the marker can be tabbed to with a keyboard and clicked by pressing enter.
  \t\tkeyboard: true,

  \t\t// @option title: String = ''
  \t\t// Text for the browser tooltip that appear on marker hover (no tooltip by default).
  \t\t// [Useful for accessibility](https://leafletjs.com/examples/accessibility/#markers-must-be-labelled).
  \t\ttitle: '',

  \t\t// @option alt: String = 'Marker'
  \t\t// Text for the `alt` attribute of the icon image.
  \t\t// [Useful for accessibility](https://leafletjs.com/examples/accessibility/#markers-must-be-labelled).
  \t\talt: 'Marker',

  \t\t// @option zIndexOffset: Number = 0
  \t\t// By default, marker images zIndex is set automatically based on its latitude. Use this option if you want to put the marker on top of all others (or below), specifying a high value like `1000` (or high negative value, respectively).
  \t\tzIndexOffset: 0,

  \t\t// @option opacity: Number = 1.0
  \t\t// The opacity of the marker.
  \t\topacity: 1,

  \t\t// @option riseOnHover: Boolean = false
  \t\t// If `true`, the marker will get on top of others when you hover the mouse over it.
  \t\triseOnHover: false,

  \t\t// @option riseOffset: Number = 250
  \t\t// The z-index offset used for the `riseOnHover` feature.
  \t\triseOffset: 250,

  \t\t// @option pane: String = 'markerPane'
  \t\t// `Map pane` where the markers icon will be added.
  \t\tpane: 'markerPane',

  \t\t// @option shadowPane: String = 'shadowPane'
  \t\t// `Map pane` where the markers shadow will be added.
  \t\tshadowPane: 'shadowPane',

  \t\t// @option bubblingMouseEvents: Boolean = false
  \t\t// When `true`, a mouse event on this marker will trigger the same event on the map
  \t\t// (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used).
  \t\tbubblingMouseEvents: false,

  \t\t// @option autoPanOnFocus: Boolean = true
  \t\t// When `true`, the map will pan whenever the marker is focused (via
  \t\t// e.g. pressing `tab` on the keyboard) to ensure the marker is
  \t\t// visible within the map's bounds
  \t\tautoPanOnFocus: true,

  \t\t// @section Draggable marker options
  \t\t// @option draggable: Boolean = false
  \t\t// Whether the marker is draggable with mouse/touch or not.
  \t\tdraggable: false,

  \t\t// @option autoPan: Boolean = false
  \t\t// Whether to pan the map when dragging this marker near its edge or not.
  \t\tautoPan: false,

  \t\t// @option autoPanPadding: Point = Point(50, 50)
  \t\t// Distance (in pixels to the left/right and to the top/bottom) of the
  \t\t// map edge to start panning the map.
  \t\tautoPanPadding: [50, 50],

  \t\t// @option autoPanSpeed: Number = 10
  \t\t// Number of pixels the map should pan by.
  \t\tautoPanSpeed: 10
  \t},

  \t/* @section
  \t *
  \t * In addition to [shared layer methods](#Layer) like `addTo()` and `remove()` and [popup methods](#Popup) like bindPopup() you can also use the following methods:
  \t */

  \tinitialize: function (latlng, options) {
  \t\tsetOptions(this, options);
  \t\tthis._latlng = toLatLng(latlng);
  \t},

  \tonAdd: function (map) {
  \t\tthis._zoomAnimated = this._zoomAnimated && map.options.markerZoomAnimation;

  \t\tif (this._zoomAnimated) {
  \t\t\tmap.on('zoomanim', this._animateZoom, this);
  \t\t}

  \t\tthis._initIcon();
  \t\tthis.update();
  \t},

  \tonRemove: function (map) {
  \t\tif (this.dragging && this.dragging.enabled()) {
  \t\t\tthis.options.draggable = true;
  \t\t\tthis.dragging.removeHooks();
  \t\t}
  \t\tdelete this.dragging;

  \t\tif (this._zoomAnimated) {
  \t\t\tmap.off('zoomanim', this._animateZoom, this);
  \t\t}

  \t\tthis._removeIcon();
  \t\tthis._removeShadow();
  \t},

  \tgetEvents: function () {
  \t\treturn {
  \t\t\tzoom: this.update,
  \t\t\tviewreset: this.update
  \t\t};
  \t},

  \t// @method getLatLng: LatLng
  \t// Returns the current geographical position of the marker.
  \tgetLatLng: function () {
  \t\treturn this._latlng;
  \t},

  \t// @method setLatLng(latlng: LatLng): this
  \t// Changes the marker position to the given point.
  \tsetLatLng: function (latlng) {
  \t\tvar oldLatLng = this._latlng;
  \t\tthis._latlng = toLatLng(latlng);
  \t\tthis.update();

  \t\t// @event move: Event
  \t\t// Fired when the marker is moved via [`setLatLng`](#marker-setlatlng) or by [dragging](#marker-dragging). Old and new coordinates are included in event arguments as `oldLatLng`, `latlng`.
  \t\treturn this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng});
  \t},

  \t// @method setZIndexOffset(offset: Number): this
  \t// Changes the [zIndex offset](#marker-zindexoffset) of the marker.
  \tsetZIndexOffset: function (offset) {
  \t\tthis.options.zIndexOffset = offset;
  \t\treturn this.update();
  \t},

  \t// @method getIcon: Icon
  \t// Returns the current icon used by the marker
  \tgetIcon: function () {
  \t\treturn this.options.icon;
  \t},

  \t// @method setIcon(icon: Icon): this
  \t// Changes the marker icon.
  \tsetIcon: function (icon) {

  \t\tthis.options.icon = icon;

  \t\tif (this._map) {
  \t\t\tthis._initIcon();
  \t\t\tthis.update();
  \t\t}

  \t\tif (this._popup) {
  \t\t\tthis.bindPopup(this._popup, this._popup.options);
  \t\t}

  \t\treturn this;
  \t},

  \tgetElement: function () {
  \t\treturn this._icon;
  \t},

  \tupdate: function () {

  \t\tif (this._icon && this._map) {
  \t\t\tvar pos = this._map.latLngToLayerPoint(this._latlng).round();
  \t\t\tthis._setPos(pos);
  \t\t}

  \t\treturn this;
  \t},

  \t_initIcon: function () {
  \t\tvar options = this.options,
  \t\t    classToAdd = 'leaflet-zoom-' + (this._zoomAnimated ? 'animated' : 'hide');

  \t\tvar icon = options.icon.createIcon(this._icon),
  \t\t    addIcon = false;

  \t\t// if we're not reusing the icon, remove the old one and init new one
  \t\tif (icon !== this._icon) {
  \t\t\tif (this._icon) {
  \t\t\t\tthis._removeIcon();
  \t\t\t}
  \t\t\taddIcon = true;

  \t\t\tif (options.title) {
  \t\t\t\ticon.title = options.title;
  \t\t\t}

  \t\t\tif (icon.tagName === 'IMG') {
  \t\t\t\ticon.alt = options.alt || '';
  \t\t\t}
  \t\t}

  \t\taddClass(icon, classToAdd);

  \t\tif (options.keyboard) {
  \t\t\ticon.tabIndex = '0';
  \t\t\ticon.setAttribute('role', 'button');
  \t\t}

  \t\tthis._icon = icon;

  \t\tif (options.riseOnHover) {
  \t\t\tthis.on({
  \t\t\t\tmouseover: this._bringToFront,
  \t\t\t\tmouseout: this._resetZIndex
  \t\t\t});
  \t\t}

  \t\tif (this.options.autoPanOnFocus) {
  \t\t\ton(icon, 'focus', this._panOnFocus, this);
  \t\t}

  \t\tvar newShadow = options.icon.createShadow(this._shadow),
  \t\t    addShadow = false;

  \t\tif (newShadow !== this._shadow) {
  \t\t\tthis._removeShadow();
  \t\t\taddShadow = true;
  \t\t}

  \t\tif (newShadow) {
  \t\t\taddClass(newShadow, classToAdd);
  \t\t\tnewShadow.alt = '';
  \t\t}
  \t\tthis._shadow = newShadow;


  \t\tif (options.opacity < 1) {
  \t\t\tthis._updateOpacity();
  \t\t}


  \t\tif (addIcon) {
  \t\t\tthis.getPane().appendChild(this._icon);
  \t\t}
  \t\tthis._initInteraction();
  \t\tif (newShadow && addShadow) {
  \t\t\tthis.getPane(options.shadowPane).appendChild(this._shadow);
  \t\t}
  \t},

  \t_removeIcon: function () {
  \t\tif (this.options.riseOnHover) {
  \t\t\tthis.off({
  \t\t\t\tmouseover: this._bringToFront,
  \t\t\t\tmouseout: this._resetZIndex
  \t\t\t});
  \t\t}

  \t\tif (this.options.autoPanOnFocus) {
  \t\t\toff(this._icon, 'focus', this._panOnFocus, this);
  \t\t}

  \t\tremove(this._icon);
  \t\tthis.removeInteractiveTarget(this._icon);

  \t\tthis._icon = null;
  \t},

  \t_removeShadow: function () {
  \t\tif (this._shadow) {
  \t\t\tremove(this._shadow);
  \t\t}
  \t\tthis._shadow = null;
  \t},

  \t_setPos: function (pos) {

  \t\tif (this._icon) {
  \t\t\tsetPosition(this._icon, pos);
  \t\t}

  \t\tif (this._shadow) {
  \t\t\tsetPosition(this._shadow, pos);
  \t\t}

  \t\tthis._zIndex = pos.y + this.options.zIndexOffset;

  \t\tthis._resetZIndex();
  \t},

  \t_updateZIndex: function (offset) {
  \t\tif (this._icon) {
  \t\t\tthis._icon.style.zIndex = this._zIndex + offset;
  \t\t}
  \t},

  \t_animateZoom: function (opt) {
  \t\tvar pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round();

  \t\tthis._setPos(pos);
  \t},

  \t_initInteraction: function () {

  \t\tif (!this.options.interactive) { return; }

  \t\taddClass(this._icon, 'leaflet-interactive');

  \t\tthis.addInteractiveTarget(this._icon);

  \t\tif (MarkerDrag) {
  \t\t\tvar draggable = this.options.draggable;
  \t\t\tif (this.dragging) {
  \t\t\t\tdraggable = this.dragging.enabled();
  \t\t\t\tthis.dragging.disable();
  \t\t\t}

  \t\t\tthis.dragging = new MarkerDrag(this);

  \t\t\tif (draggable) {
  \t\t\t\tthis.dragging.enable();
  \t\t\t}
  \t\t}
  \t},

  \t// @method setOpacity(opacity: Number): this
  \t// Changes the opacity of the marker.
  \tsetOpacity: function (opacity) {
  \t\tthis.options.opacity = opacity;
  \t\tif (this._map) {
  \t\t\tthis._updateOpacity();
  \t\t}

  \t\treturn this;
  \t},

  \t_updateOpacity: function () {
  \t\tvar opacity = this.options.opacity;

  \t\tif (this._icon) {
  \t\t\tsetOpacity(this._icon, opacity);
  \t\t}

  \t\tif (this._shadow) {
  \t\t\tsetOpacity(this._shadow, opacity);
  \t\t}
  \t},

  \t_bringToFront: function () {
  \t\tthis._updateZIndex(this.options.riseOffset);
  \t},

  \t_resetZIndex: function () {
  \t\tthis._updateZIndex(0);
  \t},

  \t_panOnFocus: function () {
  \t\tvar map = this._map;
  \t\tif (!map) { return; }

  \t\tvar iconOpts = this.options.icon.options;
  \t\tvar size = iconOpts.iconSize ? toPoint(iconOpts.iconSize) : toPoint(0, 0);
  \t\tvar anchor = iconOpts.iconAnchor ? toPoint(iconOpts.iconAnchor) : toPoint(0, 0);

  \t\tmap.panInside(this._latlng, {
  \t\t\tpaddingTopLeft: anchor,
  \t\t\tpaddingBottomRight: size.subtract(anchor)
  \t\t});
  \t},

  \t_getPopupAnchor: function () {
  \t\treturn this.options.icon.options.popupAnchor;
  \t},

  \t_getTooltipAnchor: function () {
  \t\treturn this.options.icon.options.tooltipAnchor;
  \t}
  });


  // factory L.marker(latlng: LatLng, options? : Marker options)

  // @factory L.marker(latlng: LatLng, options? : Marker options)
  // Instantiates a Marker object given a geographical point and optionally an options object.
  function marker(latlng, options) {
  \treturn new Marker(latlng, options);
  }

  /*
   * @class Path
   * @aka L.Path
   * @inherits Interactive layer
   *
   * An abstract class that contains options and constants shared between vector
   * overlays (Polygon, Polyline, Circle). Do not use it directly. Extends `Layer`.
   */

  var Path = Layer.extend({

  \t// @section
  \t// @aka Path options
  \toptions: {
  \t\t// @option stroke: Boolean = true
  \t\t// Whether to draw stroke along the path. Set it to `false` to disable borders on polygons or circles.
  \t\tstroke: true,

  \t\t// @option color: String = '#3388ff'
  \t\t// Stroke color
  \t\tcolor: '#3388ff',

  \t\t// @option weight: Number = 3
  \t\t// Stroke width in pixels
  \t\tweight: 3,

  \t\t// @option opacity: Number = 1.0
  \t\t// Stroke opacity
  \t\topacity: 1,

  \t\t// @option lineCap: String= 'round'
  \t\t// A string that defines [shape to be used at the end](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linecap) of the stroke.
  \t\tlineCap: 'round',

  \t\t// @option lineJoin: String = 'round'
  \t\t// A string that defines [shape to be used at the corners](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linejoin) of the stroke.
  \t\tlineJoin: 'round',

  \t\t// @option dashArray: String = null
  \t\t// A string that defines the stroke [dash pattern](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dasharray). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility).
  \t\tdashArray: null,

  \t\t// @option dashOffset: String = null
  \t\t// A string that defines the [distance into the dash pattern to start the dash](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dashoffset). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility).
  \t\tdashOffset: null,

  \t\t// @option fill: Boolean = depends
  \t\t// Whether to fill the path with color. Set it to `false` to disable filling on polygons or circles.
  \t\tfill: false,

  \t\t// @option fillColor: String = *
  \t\t// Fill color. Defaults to the value of the [`color`](#path-color) option
  \t\tfillColor: null,

  \t\t// @option fillOpacity: Number = 0.2
  \t\t// Fill opacity.
  \t\tfillOpacity: 0.2,

  \t\t// @option fillRule: String = 'evenodd'
  \t\t// A string that defines [how the inside of a shape](https://developer.mozilla.org/docs/Web/SVG/Attribute/fill-rule) is determined.
  \t\tfillRule: 'evenodd',

  \t\t// className: '',

  \t\t// Option inherited from \"Interactive layer\" abstract class
  \t\tinteractive: true,

  \t\t// @option bubblingMouseEvents: Boolean = true
  \t\t// When `true`, a mouse event on this path will trigger the same event on the map
  \t\t// (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used).
  \t\tbubblingMouseEvents: true
  \t},

  \tbeforeAdd: function (map) {
  \t\t// Renderer is set here because we need to call renderer.getEvents
  \t\t// before this.getEvents.
  \t\tthis._renderer = map.getRenderer(this);
  \t},

  \tonAdd: function () {
  \t\tthis._renderer._initPath(this);
  \t\tthis._reset();
  \t\tthis._renderer._addPath(this);
  \t},

  \tonRemove: function () {
  \t\tthis._renderer._removePath(this);
  \t},

  \t// @method redraw(): this
  \t// Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.
  \tredraw: function () {
  \t\tif (this._map) {
  \t\t\tthis._renderer._updatePath(this);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method setStyle(style: Path options): this
  \t// Changes the appearance of a Path based on the options in the `Path options` object.
  \tsetStyle: function (style) {
  \t\tsetOptions(this, style);
  \t\tif (this._renderer) {
  \t\t\tthis._renderer._updateStyle(this);
  \t\t\tif (this.options.stroke && style && Object.prototype.hasOwnProperty.call(style, 'weight')) {
  \t\t\t\tthis._updateBounds();
  \t\t\t}
  \t\t}
  \t\treturn this;
  \t},

  \t// @method bringToFront(): this
  \t// Brings the layer to the top of all path layers.
  \tbringToFront: function () {
  \t\tif (this._renderer) {
  \t\t\tthis._renderer._bringToFront(this);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method bringToBack(): this
  \t// Brings the layer to the bottom of all path layers.
  \tbringToBack: function () {
  \t\tif (this._renderer) {
  \t\t\tthis._renderer._bringToBack(this);
  \t\t}
  \t\treturn this;
  \t},

  \tgetElement: function () {
  \t\treturn this._path;
  \t},

  \t_reset: function () {
  \t\t// defined in child classes
  \t\tthis._project();
  \t\tthis._update();
  \t},

  \t_clickTolerance: function () {
  \t\t// used when doing hit detection for Canvas layers
  \t\treturn (this.options.stroke ? this.options.weight / 2 : 0) +
  \t\t  (this._renderer.options.tolerance || 0);
  \t}
  });

  /*
   * @class CircleMarker
   * @aka L.CircleMarker
   * @inherits Path
   *
   * A circle of a fixed size with radius specified in pixels. Extends `Path`.
   */

  var CircleMarker = Path.extend({

  \t// @section
  \t// @aka CircleMarker options
  \toptions: {
  \t\tfill: true,

  \t\t// @option radius: Number = 10
  \t\t// Radius of the circle marker, in pixels
  \t\tradius: 10
  \t},

  \tinitialize: function (latlng, options) {
  \t\tsetOptions(this, options);
  \t\tthis._latlng = toLatLng(latlng);
  \t\tthis._radius = this.options.radius;
  \t},

  \t// @method setLatLng(latLng: LatLng): this
  \t// Sets the position of a circle marker to a new location.
  \tsetLatLng: function (latlng) {
  \t\tvar oldLatLng = this._latlng;
  \t\tthis._latlng = toLatLng(latlng);
  \t\tthis.redraw();

  \t\t// @event move: Event
  \t\t// Fired when the marker is moved via [`setLatLng`](#circlemarker-setlatlng). Old and new coordinates are included in event arguments as `oldLatLng`, `latlng`.
  \t\treturn this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng});
  \t},

  \t// @method getLatLng(): LatLng
  \t// Returns the current geographical position of the circle marker
  \tgetLatLng: function () {
  \t\treturn this._latlng;
  \t},

  \t// @method setRadius(radius: Number): this
  \t// Sets the radius of a circle marker. Units are in pixels.
  \tsetRadius: function (radius) {
  \t\tthis.options.radius = this._radius = radius;
  \t\treturn this.redraw();
  \t},

  \t// @method getRadius(): Number
  \t// Returns the current radius of the circle
  \tgetRadius: function () {
  \t\treturn this._radius;
  \t},

  \tsetStyle : function (options) {
  \t\tvar radius = options && options.radius || this._radius;
  \t\tPath.prototype.setStyle.call(this, options);
  \t\tthis.setRadius(radius);
  \t\treturn this;
  \t},

  \t_project: function () {
  \t\tthis._point = this._map.latLngToLayerPoint(this._latlng);
  \t\tthis._updateBounds();
  \t},

  \t_updateBounds: function () {
  \t\tvar r = this._radius,
  \t\t    r2 = this._radiusY || r,
  \t\t    w = this._clickTolerance(),
  \t\t    p = [r + w, r2 + w];
  \t\tthis._pxBounds = new Bounds(this._point.subtract(p), this._point.add(p));
  \t},

  \t_update: function () {
  \t\tif (this._map) {
  \t\t\tthis._updatePath();
  \t\t}
  \t},

  \t_updatePath: function () {
  \t\tthis._renderer._updateCircle(this);
  \t},

  \t_empty: function () {
  \t\treturn this._radius && !this._renderer._bounds.intersects(this._pxBounds);
  \t},

  \t// Needed by the `Canvas` renderer for interactivity
  \t_containsPoint: function (p) {
  \t\treturn p.distanceTo(this._point) <= this._radius + this._clickTolerance();
  \t}
  });


  // @factory L.circleMarker(latlng: LatLng, options?: CircleMarker options)
  // Instantiates a circle marker object given a geographical point, and an optional options object.
  function circleMarker(latlng, options) {
  \treturn new CircleMarker(latlng, options);
  }

  /*
   * @class Circle
   * @aka L.Circle
   * @inherits CircleMarker
   *
   * A class for drawing circle overlays on a map. Extends `CircleMarker`.
   *
   * It's an approximation and starts to diverge from a real circle closer to poles (due to projection distortion).
   *
   * @example
   *
   * ```js
   * L.circle([50.5, 30.5], {radius: 200}).addTo(map);
   * ```
   */

  var Circle = CircleMarker.extend({

  \tinitialize: function (latlng, options, legacyOptions) {
  \t\tif (typeof options === 'number') {
  \t\t\t// Backwards compatibility with 0.7.x factory (latlng, radius, options?)
  \t\t\toptions = extend({}, legacyOptions, {radius: options});
  \t\t}
  \t\tsetOptions(this, options);
  \t\tthis._latlng = toLatLng(latlng);

  \t\tif (isNaN(this.options.radius)) { throw new Error('Circle radius cannot be NaN'); }

  \t\t// @section
  \t\t// @aka Circle options
  \t\t// @option radius: Number; Radius of the circle, in meters.
  \t\tthis._mRadius = this.options.radius;
  \t},

  \t// @method setRadius(radius: Number): this
  \t// Sets the radius of a circle. Units are in meters.
  \tsetRadius: function (radius) {
  \t\tthis._mRadius = radius;
  \t\treturn this.redraw();
  \t},

  \t// @method getRadius(): Number
  \t// Returns the current radius of a circle. Units are in meters.
  \tgetRadius: function () {
  \t\treturn this._mRadius;
  \t},

  \t// @method getBounds(): LatLngBounds
  \t// Returns the `LatLngBounds` of the path.
  \tgetBounds: function () {
  \t\tvar half = [this._radius, this._radiusY || this._radius];

  \t\treturn new LatLngBounds(
  \t\t\tthis._map.layerPointToLatLng(this._point.subtract(half)),
  \t\t\tthis._map.layerPointToLatLng(this._point.add(half)));
  \t},

  \tsetStyle: Path.prototype.setStyle,

  \t_project: function () {

  \t\tvar lng = this._latlng.lng,
  \t\t    lat = this._latlng.lat,
  \t\t    map = this._map,
  \t\t    crs = map.options.crs;

  \t\tif (crs.distance === Earth.distance) {
  \t\t\tvar d = Math.PI / 180,
  \t\t\t    latR = (this._mRadius / Earth.R) / d,
  \t\t\t    top = map.project([lat + latR, lng]),
  \t\t\t    bottom = map.project([lat - latR, lng]),
  \t\t\t    p = top.add(bottom).divideBy(2),
  \t\t\t    lat2 = map.unproject(p).lat,
  \t\t\t    lngR = Math.acos((Math.cos(latR * d) - Math.sin(lat * d) * Math.sin(lat2 * d)) /
  \t\t\t            (Math.cos(lat * d) * Math.cos(lat2 * d))) / d;

  \t\t\tif (isNaN(lngR) || lngR === 0) {
  \t\t\t\tlngR = latR / Math.cos(Math.PI / 180 * lat); // Fallback for edge case, #2425
  \t\t\t}

  \t\t\tthis._point = p.subtract(map.getPixelOrigin());
  \t\t\tthis._radius = isNaN(lngR) ? 0 : p.x - map.project([lat2, lng - lngR]).x;
  \t\t\tthis._radiusY = p.y - top.y;

  \t\t} else {
  \t\t\tvar latlng2 = crs.unproject(crs.project(this._latlng).subtract([this._mRadius, 0]));

  \t\t\tthis._point = map.latLngToLayerPoint(this._latlng);
  \t\t\tthis._radius = this._point.x - map.latLngToLayerPoint(latlng2).x;
  \t\t}

  \t\tthis._updateBounds();
  \t}
  });

  // @factory L.circle(latlng: LatLng, options?: Circle options)
  // Instantiates a circle object given a geographical point, and an options object
  // which contains the circle radius.
  // @alternative
  // @factory L.circle(latlng: LatLng, radius: Number, options?: Circle options)
  // Obsolete way of instantiating a circle, for compatibility with 0.7.x code.
  // Do not use in new applications or plugins.
  function circle(latlng, options, legacyOptions) {
  \treturn new Circle(latlng, options, legacyOptions);
  }

  /*
   * @class Polyline
   * @aka L.Polyline
   * @inherits Path
   *
   * A class for drawing polyline overlays on a map. Extends `Path`.
   *
   * @example
   *
   * ```js
   * // create a red polyline from an array of LatLng points
   * var latlngs = [
   * \t[45.51, -122.68],
   * \t[37.77, -122.43],
   * \t[34.04, -118.2]
   * ];
   *
   * var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map);
   *
   * // zoom the map to the polyline
   * map.fitBounds(polyline.getBounds());
   * ```
   *
   * You can also pass a multi-dimensional array to represent a `MultiPolyline` shape:
   *
   * ```js
   * // create a red polyline from an array of arrays of LatLng points
   * var latlngs = [
   * \t[[45.51, -122.68],
   * \t [37.77, -122.43],
   * \t [34.04, -118.2]],
   * \t[[40.78, -73.91],
   * \t [41.83, -87.62],
   * \t [32.76, -96.72]]
   * ];
   * ```
   */


  var Polyline = Path.extend({

  \t// @section
  \t// @aka Polyline options
  \toptions: {
  \t\t// @option smoothFactor: Number = 1.0
  \t\t// How much to simplify the polyline on each zoom level. More means
  \t\t// better performance and smoother look, and less means more accurate representation.
  \t\tsmoothFactor: 1.0,

  \t\t// @option noClip: Boolean = false
  \t\t// Disable polyline clipping.
  \t\tnoClip: false
  \t},

  \tinitialize: function (latlngs, options) {
  \t\tsetOptions(this, options);
  \t\tthis._setLatLngs(latlngs);
  \t},

  \t// @method getLatLngs(): LatLng[]
  \t// Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.
  \tgetLatLngs: function () {
  \t\treturn this._latlngs;
  \t},

  \t// @method setLatLngs(latlngs: LatLng[]): this
  \t// Replaces all the points in the polyline with the given array of geographical points.
  \tsetLatLngs: function (latlngs) {
  \t\tthis._setLatLngs(latlngs);
  \t\treturn this.redraw();
  \t},

  \t// @method isEmpty(): Boolean
  \t// Returns `true` if the Polyline has no LatLngs.
  \tisEmpty: function () {
  \t\treturn !this._latlngs.length;
  \t},

  \t// @method closestLayerPoint(p: Point): Point
  \t// Returns the point closest to `p` on the Polyline.
  \tclosestLayerPoint: function (p) {
  \t\tvar minDistance = Infinity,
  \t\t    minPoint = null,
  \t\t    closest = _sqClosestPointOnSegment,
  \t\t    p1, p2;

  \t\tfor (var j = 0, jLen = this._parts.length; j < jLen; j++) {
  \t\t\tvar points = this._parts[j];

  \t\t\tfor (var i = 1, len = points.length; i < len; i++) {
  \t\t\t\tp1 = points[i - 1];
  \t\t\t\tp2 = points[i];

  \t\t\t\tvar sqDist = closest(p, p1, p2, true);

  \t\t\t\tif (sqDist < minDistance) {
  \t\t\t\t\tminDistance = sqDist;
  \t\t\t\t\tminPoint = closest(p, p1, p2);
  \t\t\t\t}
  \t\t\t}
  \t\t}
  \t\tif (minPoint) {
  \t\t\tminPoint.distance = Math.sqrt(minDistance);
  \t\t}
  \t\treturn minPoint;
  \t},

  \t// @method getCenter(): LatLng
  \t// Returns the center ([centroid](https://en.wikipedia.org/wiki/Centroid)) of the polyline.
  \tgetCenter: function () {
  \t\t// throws error when not yet added to map as this center calculation requires projected coordinates
  \t\tif (!this._map) {
  \t\t\tthrow new Error('Must add layer to map before using getCenter()');
  \t\t}
  \t\treturn polylineCenter(this._defaultShape(), this._map.options.crs);
  \t},

  \t// @method getBounds(): LatLngBounds
  \t// Returns the `LatLngBounds` of the path.
  \tgetBounds: function () {
  \t\treturn this._bounds;
  \t},

  \t// @method addLatLng(latlng: LatLng, latlngs?: LatLng[]): this
  \t// Adds a given point to the polyline. By default, adds to the first ring of
  \t// the polyline in case of a multi-polyline, but can be overridden by passing
  \t// a specific ring as a LatLng array (that you can earlier access with [`getLatLngs`](#polyline-getlatlngs)).
  \taddLatLng: function (latlng, latlngs) {
  \t\tlatlngs = latlngs || this._defaultShape();
  \t\tlatlng = toLatLng(latlng);
  \t\tlatlngs.push(latlng);
  \t\tthis._bounds.extend(latlng);
  \t\treturn this.redraw();
  \t},

  \t_setLatLngs: function (latlngs) {
  \t\tthis._bounds = new LatLngBounds();
  \t\tthis._latlngs = this._convertLatLngs(latlngs);
  \t},

  \t_defaultShape: function () {
  \t\treturn isFlat(this._latlngs) ? this._latlngs : this._latlngs[0];
  \t},

  \t// recursively convert latlngs input into actual LatLng instances; calculate bounds along the way
  \t_convertLatLngs: function (latlngs) {
  \t\tvar result = [],
  \t\t    flat = isFlat(latlngs);

  \t\tfor (var i = 0, len = latlngs.length; i < len; i++) {
  \t\t\tif (flat) {
  \t\t\t\tresult[i] = toLatLng(latlngs[i]);
  \t\t\t\tthis._bounds.extend(result[i]);
  \t\t\t} else {
  \t\t\t\tresult[i] = this._convertLatLngs(latlngs[i]);
  \t\t\t}
  \t\t}

  \t\treturn result;
  \t},

  \t_project: function () {
  \t\tvar pxBounds = new Bounds();
  \t\tthis._rings = [];
  \t\tthis._projectLatlngs(this._latlngs, this._rings, pxBounds);

  \t\tif (this._bounds.isValid() && pxBounds.isValid()) {
  \t\t\tthis._rawPxBounds = pxBounds;
  \t\t\tthis._updateBounds();
  \t\t}
  \t},

  \t_updateBounds: function () {
  \t\tvar w = this._clickTolerance(),
  \t\t    p = new Point(w, w);

  \t\tif (!this._rawPxBounds) {
  \t\t\treturn;
  \t\t}

  \t\tthis._pxBounds = new Bounds([
  \t\t\tthis._rawPxBounds.min.subtract(p),
  \t\t\tthis._rawPxBounds.max.add(p)
  \t\t]);
  \t},

  \t// recursively turns latlngs into a set of rings with projected coordinates
  \t_projectLatlngs: function (latlngs, result, projectedBounds) {
  \t\tvar flat = latlngs[0] instanceof LatLng,
  \t\t    len = latlngs.length,
  \t\t    i, ring;

  \t\tif (flat) {
  \t\t\tring = [];
  \t\t\tfor (i = 0; i < len; i++) {
  \t\t\t\tring[i] = this._map.latLngToLayerPoint(latlngs[i]);
  \t\t\t\tprojectedBounds.extend(ring[i]);
  \t\t\t}
  \t\t\tresult.push(ring);
  \t\t} else {
  \t\t\tfor (i = 0; i < len; i++) {
  \t\t\t\tthis._projectLatlngs(latlngs[i], result, projectedBounds);
  \t\t\t}
  \t\t}
  \t},

  \t// clip polyline by renderer bounds so that we have less to render for performance
  \t_clipPoints: function () {
  \t\tvar bounds = this._renderer._bounds;

  \t\tthis._parts = [];
  \t\tif (!this._pxBounds || !this._pxBounds.intersects(bounds)) {
  \t\t\treturn;
  \t\t}

  \t\tif (this.options.noClip) {
  \t\t\tthis._parts = this._rings;
  \t\t\treturn;
  \t\t}

  \t\tvar parts = this._parts,
  \t\t    i, j, k, len, len2, segment, points;

  \t\tfor (i = 0, k = 0, len = this._rings.length; i < len; i++) {
  \t\t\tpoints = this._rings[i];

  \t\t\tfor (j = 0, len2 = points.length; j < len2 - 1; j++) {
  \t\t\t\tsegment = clipSegment(points[j], points[j + 1], bounds, j, true);

  \t\t\t\tif (!segment) { continue; }

  \t\t\t\tparts[k] = parts[k] || [];
  \t\t\t\tparts[k].push(segment[0]);

  \t\t\t\t// if segment goes out of screen, or it's the last one, it's the end of the line part
  \t\t\t\tif ((segment[1] !== points[j + 1]) || (j === len2 - 2)) {
  \t\t\t\t\tparts[k].push(segment[1]);
  \t\t\t\t\tk++;
  \t\t\t\t}
  \t\t\t}
  \t\t}
  \t},

  \t// simplify each clipped part of the polyline for performance
  \t_simplifyPoints: function () {
  \t\tvar parts = this._parts,
  \t\t    tolerance = this.options.smoothFactor;

  \t\tfor (var i = 0, len = parts.length; i < len; i++) {
  \t\t\tparts[i] = simplify(parts[i], tolerance);
  \t\t}
  \t},

  \t_update: function () {
  \t\tif (!this._map) { return; }

  \t\tthis._clipPoints();
  \t\tthis._simplifyPoints();
  \t\tthis._updatePath();
  \t},

  \t_updatePath: function () {
  \t\tthis._renderer._updatePoly(this);
  \t},

  \t// Needed by the `Canvas` renderer for interactivity
  \t_containsPoint: function (p, closed) {
  \t\tvar i, j, k, len, len2, part,
  \t\t    w = this._clickTolerance();

  \t\tif (!this._pxBounds || !this._pxBounds.contains(p)) { return false; }

  \t\t// hit detection for polylines
  \t\tfor (i = 0, len = this._parts.length; i < len; i++) {
  \t\t\tpart = this._parts[i];

  \t\t\tfor (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {
  \t\t\t\tif (!closed && (j === 0)) { continue; }

  \t\t\t\tif (pointToSegmentDistance(p, part[k], part[j]) <= w) {
  \t\t\t\t\treturn true;
  \t\t\t\t}
  \t\t\t}
  \t\t}
  \t\treturn false;
  \t}
  });

  // @factory L.polyline(latlngs: LatLng[], options?: Polyline options)
  // Instantiates a polyline object given an array of geographical points and
  // optionally an options object. You can create a `Polyline` object with
  // multiple separate lines (`MultiPolyline`) by passing an array of arrays
  // of geographic points.
  function polyline(latlngs, options) {
  \treturn new Polyline(latlngs, options);
  }

  // Retrocompat. Allow plugins to support Leaflet versions before and after 1.1.
  Polyline._flat = _flat;

  /*
   * @class Polygon
   * @aka L.Polygon
   * @inherits Polyline
   *
   * A class for drawing polygon overlays on a map. Extends `Polyline`.
   *
   * Note that points you pass when creating a polygon shouldn't have an additional last point equal to the first one — it's better to filter out such points.
   *
   *
   * @example
   *
   * ```js
   * // create a red polygon from an array of LatLng points
   * var latlngs = [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]];
   *
   * var polygon = L.polygon(latlngs, {color: 'red'}).addTo(map);
   *
   * // zoom the map to the polygon
   * map.fitBounds(polygon.getBounds());
   * ```
   *
   * You can also pass an array of arrays of latlngs, with the first array representing the outer shape and the other arrays representing holes in the outer shape:
   *
   * ```js
   * var latlngs = [
   *   [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring
   *   [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole
   * ];
   * ```
   *
   * Additionally, you can pass a multi-dimensional array to represent a MultiPolygon shape.
   *
   * ```js
   * var latlngs = [
   *   [ // first polygon
   *     [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring
   *     [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole
   *   ],
   *   [ // second polygon
   *     [[41, -111.03],[45, -111.04],[45, -104.05],[41, -104.05]]
   *   ]
   * ];
   * ```
   */

  var Polygon = Polyline.extend({

  \toptions: {
  \t\tfill: true
  \t},

  \tisEmpty: function () {
  \t\treturn !this._latlngs.length || !this._latlngs[0].length;
  \t},

  \t// @method getCenter(): LatLng
  \t// Returns the center ([centroid](http://en.wikipedia.org/wiki/Centroid)) of the Polygon.
  \tgetCenter: function () {
  \t\t// throws error when not yet added to map as this center calculation requires projected coordinates
  \t\tif (!this._map) {
  \t\t\tthrow new Error('Must add layer to map before using getCenter()');
  \t\t}
  \t\treturn polygonCenter(this._defaultShape(), this._map.options.crs);
  \t},

  \t_convertLatLngs: function (latlngs) {
  \t\tvar result = Polyline.prototype._convertLatLngs.call(this, latlngs),
  \t\t    len = result.length;

  \t\t// remove last point if it equals first one
  \t\tif (len >= 2 && result[0] instanceof LatLng && result[0].equals(result[len - 1])) {
  \t\t\tresult.pop();
  \t\t}
  \t\treturn result;
  \t},

  \t_setLatLngs: function (latlngs) {
  \t\tPolyline.prototype._setLatLngs.call(this, latlngs);
  \t\tif (isFlat(this._latlngs)) {
  \t\t\tthis._latlngs = [this._latlngs];
  \t\t}
  \t},

  \t_defaultShape: function () {
  \t\treturn isFlat(this._latlngs[0]) ? this._latlngs[0] : this._latlngs[0][0];
  \t},

  \t_clipPoints: function () {
  \t\t// polygons need a different clipping algorithm so we redefine that

  \t\tvar bounds = this._renderer._bounds,
  \t\t    w = this.options.weight,
  \t\t    p = new Point(w, w);

  \t\t// increase clip padding by stroke width to avoid stroke on clip edges
  \t\tbounds = new Bounds(bounds.min.subtract(p), bounds.max.add(p));

  \t\tthis._parts = [];
  \t\tif (!this._pxBounds || !this._pxBounds.intersects(bounds)) {
  \t\t\treturn;
  \t\t}

  \t\tif (this.options.noClip) {
  \t\t\tthis._parts = this._rings;
  \t\t\treturn;
  \t\t}

  \t\tfor (var i = 0, len = this._rings.length, clipped; i < len; i++) {
  \t\t\tclipped = clipPolygon(this._rings[i], bounds, true);
  \t\t\tif (clipped.length) {
  \t\t\t\tthis._parts.push(clipped);
  \t\t\t}
  \t\t}
  \t},

  \t_updatePath: function () {
  \t\tthis._renderer._updatePoly(this, true);
  \t},

  \t// Needed by the `Canvas` renderer for interactivity
  \t_containsPoint: function (p) {
  \t\tvar inside = false,
  \t\t    part, p1, p2, i, j, k, len, len2;

  \t\tif (!this._pxBounds || !this._pxBounds.contains(p)) { return false; }

  \t\t// ray casting algorithm for detecting if point is in polygon
  \t\tfor (i = 0, len = this._parts.length; i < len; i++) {
  \t\t\tpart = this._parts[i];

  \t\t\tfor (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {
  \t\t\t\tp1 = part[j];
  \t\t\t\tp2 = part[k];

  \t\t\t\tif (((p1.y > p.y) !== (p2.y > p.y)) && (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x)) {
  \t\t\t\t\tinside = !inside;
  \t\t\t\t}
  \t\t\t}
  \t\t}

  \t\t// also check if it's on polygon stroke
  \t\treturn inside || Polyline.prototype._containsPoint.call(this, p, true);
  \t}

  });


  // @factory L.polygon(latlngs: LatLng[], options?: Polyline options)
  function polygon(latlngs, options) {
  \treturn new Polygon(latlngs, options);
  }

  /*
   * @class GeoJSON
   * @aka L.GeoJSON
   * @inherits FeatureGroup
   *
   * Represents a GeoJSON object or an array of GeoJSON objects. Allows you to parse
   * GeoJSON data and display it on the map. Extends `FeatureGroup`.
   *
   * @example
   *
   * ```js
   * L.geoJSON(data, {
   * \tstyle: function (feature) {
   * \t\treturn {color: feature.properties.color};
   * \t}
   * }).bindPopup(function (layer) {
   * \treturn layer.feature.properties.description;
   * }).addTo(map);
   * ```
   */

  var GeoJSON = FeatureGroup.extend({

  \t/* @section
  \t * @aka GeoJSON options
  \t *
  \t * @option pointToLayer: Function = *
  \t * A `Function` defining how GeoJSON points spawn Leaflet layers. It is internally
  \t * called when data is added, passing the GeoJSON point feature and its `LatLng`.
  \t * The default is to spawn a default `Marker`:
  \t * ```js
  \t * function(geoJsonPoint, latlng) {
  \t * \treturn L.marker(latlng);
  \t * }
  \t * ```
  \t *
  \t * @option style: Function = *
  \t * A `Function` defining the `Path options` for styling GeoJSON lines and polygons,
  \t * called internally when data is added.
  \t * The default value is to not override any defaults:
  \t * ```js
  \t * function (geoJsonFeature) {
  \t * \treturn {}
  \t * }
  \t * ```
  \t *
  \t * @option onEachFeature: Function = *
  \t * A `Function` that will be called once for each created `Feature`, after it has
  \t * been created and styled. Useful for attaching events and popups to features.
  \t * The default is to do nothing with the newly created layers:
  \t * ```js
  \t * function (feature, layer) {}
  \t * ```
  \t *
  \t * @option filter: Function = *
  \t * A `Function` that will be used to decide whether to include a feature or not.
  \t * The default is to include all features:
  \t * ```js
  \t * function (geoJsonFeature) {
  \t * \treturn true;
  \t * }
  \t * ```
  \t * Note: dynamically changing the `filter` option will have effect only on newly
  \t * added data. It will _not_ re-evaluate already included features.
  \t *
  \t * @option coordsToLatLng: Function = *
  \t * A `Function` that will be used for converting GeoJSON coordinates to `LatLng`s.
  \t * The default is the `coordsToLatLng` static method.
  \t *
  \t * @option markersInheritOptions: Boolean = false
  \t * Whether default Markers for \"Point\" type Features inherit from group options.
  \t */

  \tinitialize: function (geojson, options) {
  \t\tsetOptions(this, options);

  \t\tthis._layers = {};

  \t\tif (geojson) {
  \t\t\tthis.addData(geojson);
  \t\t}
  \t},

  \t// @method addData( <GeoJSON> data ): this
  \t// Adds a GeoJSON object to the layer.
  \taddData: function (geojson) {
  \t\tvar features = isArray(geojson) ? geojson : geojson.features,
  \t\t    i, len, feature;

  \t\tif (features) {
  \t\t\tfor (i = 0, len = features.length; i < len; i++) {
  \t\t\t\t// only add this if geometry or geometries are set and not null
  \t\t\t\tfeature = features[i];
  \t\t\t\tif (feature.geometries || feature.geometry || feature.features || feature.coordinates) {
  \t\t\t\t\tthis.addData(feature);
  \t\t\t\t}
  \t\t\t}
  \t\t\treturn this;
  \t\t}

  \t\tvar options = this.options;

  \t\tif (options.filter && !options.filter(geojson)) { return this; }

  \t\tvar layer = geometryToLayer(geojson, options);
  \t\tif (!layer) {
  \t\t\treturn this;
  \t\t}
  \t\tlayer.feature = asFeature(geojson);

  \t\tlayer.defaultOptions = layer.options;
  \t\tthis.resetStyle(layer);

  \t\tif (options.onEachFeature) {
  \t\t\toptions.onEachFeature(geojson, layer);
  \t\t}

  \t\treturn this.addLayer(layer);
  \t},

  \t// @method resetStyle( <Path> layer? ): this
  \t// Resets the given vector layer's style to the original GeoJSON style, useful for resetting style after hover events.
  \t// If `layer` is omitted, the style of all features in the current layer is reset.
  \tresetStyle: function (layer) {
  \t\tif (layer === undefined) {
  \t\t\treturn this.eachLayer(this.resetStyle, this);
  \t\t}
  \t\t// reset any custom styles
  \t\tlayer.options = extend({}, layer.defaultOptions);
  \t\tthis._setLayerStyle(layer, this.options.style);
  \t\treturn this;
  \t},

  \t// @method setStyle( <Function> style ): this
  \t// Changes styles of GeoJSON vector layers with the given style function.
  \tsetStyle: function (style) {
  \t\treturn this.eachLayer(function (layer) {
  \t\t\tthis._setLayerStyle(layer, style);
  \t\t}, this);
  \t},

  \t_setLayerStyle: function (layer, style) {
  \t\tif (layer.setStyle) {
  \t\t\tif (typeof style === 'function') {
  \t\t\t\tstyle = style(layer.feature);
  \t\t\t}
  \t\t\tlayer.setStyle(style);
  \t\t}
  \t}
  });

  // @section
  // There are several static functions which can be called without instantiating L.GeoJSON:

  // @function geometryToLayer(featureData: Object, options?: GeoJSON options): Layer
  // Creates a `Layer` from a given GeoJSON feature. Can use a custom
  // [`pointToLayer`](#geojson-pointtolayer) and/or [`coordsToLatLng`](#geojson-coordstolatlng)
  // functions if provided as options.
  function geometryToLayer(geojson, options) {

  \tvar geometry = geojson.type === 'Feature' ? geojson.geometry : geojson,
  \t    coords = geometry ? geometry.coordinates : null,
  \t    layers = [],
  \t    pointToLayer = options && options.pointToLayer,
  \t    _coordsToLatLng = options && options.coordsToLatLng || coordsToLatLng,
  \t    latlng, latlngs, i, len;

  \tif (!coords && !geometry) {
  \t\treturn null;
  \t}

  \tswitch (geometry.type) {
  \tcase 'Point':
  \t\tlatlng = _coordsToLatLng(coords);
  \t\treturn _pointToLayer(pointToLayer, geojson, latlng, options);

  \tcase 'MultiPoint':
  \t\tfor (i = 0, len = coords.length; i < len; i++) {
  \t\t\tlatlng = _coordsToLatLng(coords[i]);
  \t\t\tlayers.push(_pointToLayer(pointToLayer, geojson, latlng, options));
  \t\t}
  \t\treturn new FeatureGroup(layers);

  \tcase 'LineString':
  \tcase 'MultiLineString':
  \t\tlatlngs = coordsToLatLngs(coords, geometry.type === 'LineString' ? 0 : 1, _coordsToLatLng);
  \t\treturn new Polyline(latlngs, options);

  \tcase 'Polygon':
  \tcase 'MultiPolygon':
  \t\tlatlngs = coordsToLatLngs(coords, geometry.type === 'Polygon' ? 1 : 2, _coordsToLatLng);
  \t\treturn new Polygon(latlngs, options);

  \tcase 'GeometryCollection':
  \t\tfor (i = 0, len = geometry.geometries.length; i < len; i++) {
  \t\t\tvar geoLayer = geometryToLayer({
  \t\t\t\tgeometry: geometry.geometries[i],
  \t\t\t\ttype: 'Feature',
  \t\t\t\tproperties: geojson.properties
  \t\t\t}, options);

  \t\t\tif (geoLayer) {
  \t\t\t\tlayers.push(geoLayer);
  \t\t\t}
  \t\t}
  \t\treturn new FeatureGroup(layers);

  \tcase 'FeatureCollection':
  \t\tfor (i = 0, len = geometry.features.length; i < len; i++) {
  \t\t\tvar featureLayer = geometryToLayer(geometry.features[i], options);

  \t\t\tif (featureLayer) {
  \t\t\t\tlayers.push(featureLayer);
  \t\t\t}
  \t\t}
  \t\treturn new FeatureGroup(layers);

  \tdefault:
  \t\tthrow new Error('Invalid GeoJSON object.');
  \t}
  }

  function _pointToLayer(pointToLayerFn, geojson, latlng, options) {
  \treturn pointToLayerFn ?
  \t\tpointToLayerFn(geojson, latlng) :
  \t\tnew Marker(latlng, options && options.markersInheritOptions && options);
  }

  // @function coordsToLatLng(coords: Array): LatLng
  // Creates a `LatLng` object from an array of 2 numbers (longitude, latitude)
  // or 3 numbers (longitude, latitude, altitude) used in GeoJSON for points.
  function coordsToLatLng(coords) {
  \treturn new LatLng(coords[1], coords[0], coords[2]);
  }

  // @function coordsToLatLngs(coords: Array, levelsDeep?: Number, coordsToLatLng?: Function): Array
  // Creates a multidimensional array of `LatLng`s from a GeoJSON coordinates array.
  // `levelsDeep` specifies the nesting level (0 is for an array of points, 1 for an array of arrays of points, etc., 0 by default).
  // Can use a custom [`coordsToLatLng`](#geojson-coordstolatlng) function.
  function coordsToLatLngs(coords, levelsDeep, _coordsToLatLng) {
  \tvar latlngs = [];

  \tfor (var i = 0, len = coords.length, latlng; i < len; i++) {
  \t\tlatlng = levelsDeep ?
  \t\t\tcoordsToLatLngs(coords[i], levelsDeep - 1, _coordsToLatLng) :
  \t\t\t(_coordsToLatLng || coordsToLatLng)(coords[i]);

  \t\tlatlngs.push(latlng);
  \t}

  \treturn latlngs;
  }

  // @function latLngToCoords(latlng: LatLng, precision?: Number|false): Array
  // Reverse of [`coordsToLatLng`](#geojson-coordstolatlng)
  // Coordinates values are rounded with [`formatNum`](#util-formatnum) function.
  function latLngToCoords(latlng, precision) {
  \tlatlng = toLatLng(latlng);
  \treturn latlng.alt !== undefined ?
  \t\t[formatNum(latlng.lng, precision), formatNum(latlng.lat, precision), formatNum(latlng.alt, precision)] :
  \t\t[formatNum(latlng.lng, precision), formatNum(latlng.lat, precision)];
  }

  // @function latLngsToCoords(latlngs: Array, levelsDeep?: Number, closed?: Boolean, precision?: Number|false): Array
  // Reverse of [`coordsToLatLngs`](#geojson-coordstolatlngs)
  // `closed` determines whether the first point should be appended to the end of the array to close the feature, only used when `levelsDeep` is 0. False by default.
  // Coordinates values are rounded with [`formatNum`](#util-formatnum) function.
  function latLngsToCoords(latlngs, levelsDeep, closed, precision) {
  \tvar coords = [];

  \tfor (var i = 0, len = latlngs.length; i < len; i++) {
  \t\t// Check for flat arrays required to ensure unbalanced arrays are correctly converted in recursion
  \t\tcoords.push(levelsDeep ?
  \t\t\tlatLngsToCoords(latlngs[i], isFlat(latlngs[i]) ? 0 : levelsDeep - 1, closed, precision) :
  \t\t\tlatLngToCoords(latlngs[i], precision));
  \t}

  \tif (!levelsDeep && closed && coords.length > 0) {
  \t\tcoords.push(coords[0].slice());
  \t}

  \treturn coords;
  }

  function getFeature(layer, newGeometry) {
  \treturn layer.feature ?
  \t\textend({}, layer.feature, {geometry: newGeometry}) :
  \t\tasFeature(newGeometry);
  }

  // @function asFeature(geojson: Object): Object
  // Normalize GeoJSON geometries/features into GeoJSON features.
  function asFeature(geojson) {
  \tif (geojson.type === 'Feature' || geojson.type === 'FeatureCollection') {
  \t\treturn geojson;
  \t}

  \treturn {
  \t\ttype: 'Feature',
  \t\tproperties: {},
  \t\tgeometry: geojson
  \t};
  }

  var PointToGeoJSON = {
  \ttoGeoJSON: function (precision) {
  \t\treturn getFeature(this, {
  \t\t\ttype: 'Point',
  \t\t\tcoordinates: latLngToCoords(this.getLatLng(), precision)
  \t\t});
  \t}
  };

  // @namespace Marker
  // @section Other methods
  // @method toGeoJSON(precision?: Number|false): Object
  // Coordinates values are rounded with [`formatNum`](#util-formatnum) function with given `precision`.
  // Returns a [`GeoJSON`](https://en.wikipedia.org/wiki/GeoJSON) representation of the marker (as a GeoJSON `Point` Feature).
  Marker.include(PointToGeoJSON);

  // @namespace CircleMarker
  // @method toGeoJSON(precision?: Number|false): Object
  // Coordinates values are rounded with [`formatNum`](#util-formatnum) function with given `precision`.
  // Returns a [`GeoJSON`](https://en.wikipedia.org/wiki/GeoJSON) representation of the circle marker (as a GeoJSON `Point` Feature).
  Circle.include(PointToGeoJSON);
  CircleMarker.include(PointToGeoJSON);


  // @namespace Polyline
  // @method toGeoJSON(precision?: Number|false): Object
  // Coordinates values are rounded with [`formatNum`](#util-formatnum) function with given `precision`.
  // Returns a [`GeoJSON`](https://en.wikipedia.org/wiki/GeoJSON) representation of the polyline (as a GeoJSON `LineString` or `MultiLineString` Feature).
  Polyline.include({
  \ttoGeoJSON: function (precision) {
  \t\tvar multi = !isFlat(this._latlngs);

  \t\tvar coords = latLngsToCoords(this._latlngs, multi ? 1 : 0, false, precision);

  \t\treturn getFeature(this, {
  \t\t\ttype: (multi ? 'Multi' : '') + 'LineString',
  \t\t\tcoordinates: coords
  \t\t});
  \t}
  });

  // @namespace Polygon
  // @method toGeoJSON(precision?: Number|false): Object
  // Coordinates values are rounded with [`formatNum`](#util-formatnum) function with given `precision`.
  // Returns a [`GeoJSON`](https://en.wikipedia.org/wiki/GeoJSON) representation of the polygon (as a GeoJSON `Polygon` or `MultiPolygon` Feature).
  Polygon.include({
  \ttoGeoJSON: function (precision) {
  \t\tvar holes = !isFlat(this._latlngs),
  \t\t    multi = holes && !isFlat(this._latlngs[0]);

  \t\tvar coords = latLngsToCoords(this._latlngs, multi ? 2 : holes ? 1 : 0, true, precision);

  \t\tif (!holes) {
  \t\t\tcoords = [coords];
  \t\t}

  \t\treturn getFeature(this, {
  \t\t\ttype: (multi ? 'Multi' : '') + 'Polygon',
  \t\t\tcoordinates: coords
  \t\t});
  \t}
  });


  // @namespace LayerGroup
  LayerGroup.include({
  \ttoMultiPoint: function (precision) {
  \t\tvar coords = [];

  \t\tthis.eachLayer(function (layer) {
  \t\t\tcoords.push(layer.toGeoJSON(precision).geometry.coordinates);
  \t\t});

  \t\treturn getFeature(this, {
  \t\t\ttype: 'MultiPoint',
  \t\t\tcoordinates: coords
  \t\t});
  \t},

  \t// @method toGeoJSON(precision?: Number|false): Object
  \t// Coordinates values are rounded with [`formatNum`](#util-formatnum) function with given `precision`.
  \t// Returns a [`GeoJSON`](https://en.wikipedia.org/wiki/GeoJSON) representation of the layer group (as a GeoJSON `FeatureCollection`, `GeometryCollection`, or `MultiPoint`).
  \ttoGeoJSON: function (precision) {

  \t\tvar type = this.feature && this.feature.geometry && this.feature.geometry.type;

  \t\tif (type === 'MultiPoint') {
  \t\t\treturn this.toMultiPoint(precision);
  \t\t}

  \t\tvar isGeometryCollection = type === 'GeometryCollection',
  \t\t    jsons = [];

  \t\tthis.eachLayer(function (layer) {
  \t\t\tif (layer.toGeoJSON) {
  \t\t\t\tvar json = layer.toGeoJSON(precision);
  \t\t\t\tif (isGeometryCollection) {
  \t\t\t\t\tjsons.push(json.geometry);
  \t\t\t\t} else {
  \t\t\t\t\tvar feature = asFeature(json);
  \t\t\t\t\t// Squash nested feature collections
  \t\t\t\t\tif (feature.type === 'FeatureCollection') {
  \t\t\t\t\t\tjsons.push.apply(jsons, feature.features);
  \t\t\t\t\t} else {
  \t\t\t\t\t\tjsons.push(feature);
  \t\t\t\t\t}
  \t\t\t\t}
  \t\t\t}
  \t\t});

  \t\tif (isGeometryCollection) {
  \t\t\treturn getFeature(this, {
  \t\t\t\tgeometries: jsons,
  \t\t\t\ttype: 'GeometryCollection'
  \t\t\t});
  \t\t}

  \t\treturn {
  \t\t\ttype: 'FeatureCollection',
  \t\t\tfeatures: jsons
  \t\t};
  \t}
  });

  // @namespace GeoJSON
  // @factory L.geoJSON(geojson?: Object, options?: GeoJSON options)
  // Creates a GeoJSON layer. Optionally accepts an object in
  // [GeoJSON format](https://tools.ietf.org/html/rfc7946) to display on the map
  // (you can alternatively add it later with `addData` method) and an `options` object.
  function geoJSON(geojson, options) {
  \treturn new GeoJSON(geojson, options);
  }

  // Backward compatibility.
  var geoJson = geoJSON;

  /*
   * @class ImageOverlay
   * @aka L.ImageOverlay
   * @inherits Interactive layer
   *
   * Used to load and display a single image over specific bounds of the map. Extends `Layer`.
   *
   * @example
   *
   * ```js
   * var imageUrl = 'https://maps.lib.utexas.edu/maps/historical/newark_nj_1922.jpg',
   * \timageBounds = [[40.712216, -74.22655], [40.773941, -74.12544]];
   * L.imageOverlay(imageUrl, imageBounds).addTo(map);
   * ```
   */

  var ImageOverlay = Layer.extend({

  \t// @section
  \t// @aka ImageOverlay options
  \toptions: {
  \t\t// @option opacity: Number = 1.0
  \t\t// The opacity of the image overlay.
  \t\topacity: 1,

  \t\t// @option alt: String = ''
  \t\t// Text for the `alt` attribute of the image (useful for accessibility).
  \t\talt: '',

  \t\t// @option interactive: Boolean = false
  \t\t// If `true`, the image overlay will emit [mouse events](#interactive-layer) when clicked or hovered.
  \t\tinteractive: false,

  \t\t// @option crossOrigin: Boolean|String = false
  \t\t// Whether the crossOrigin attribute will be added to the image.
  \t\t// If a String is provided, the image will have its crossOrigin attribute set to the String provided. This is needed if you want to access image pixel data.
  \t\t// Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values.
  \t\tcrossOrigin: false,

  \t\t// @option errorOverlayUrl: String = ''
  \t\t// URL to the overlay image to show in place of the overlay that failed to load.
  \t\terrorOverlayUrl: '',

  \t\t// @option zIndex: Number = 1
  \t\t// The explicit [zIndex](https://developer.mozilla.org/docs/Web/CSS/CSS_Positioning/Understanding_z_index) of the overlay layer.
  \t\tzIndex: 1,

  \t\t// @option className: String = ''
  \t\t// A custom class name to assign to the image. Empty by default.
  \t\tclassName: ''
  \t},

  \tinitialize: function (url, bounds, options) { // (String, LatLngBounds, Object)
  \t\tthis._url = url;
  \t\tthis._bounds = toLatLngBounds(bounds);

  \t\tsetOptions(this, options);
  \t},

  \tonAdd: function () {
  \t\tif (!this._image) {
  \t\t\tthis._initImage();

  \t\t\tif (this.options.opacity < 1) {
  \t\t\t\tthis._updateOpacity();
  \t\t\t}
  \t\t}

  \t\tif (this.options.interactive) {
  \t\t\taddClass(this._image, 'leaflet-interactive');
  \t\t\tthis.addInteractiveTarget(this._image);
  \t\t}

  \t\tthis.getPane().appendChild(this._image);
  \t\tthis._reset();
  \t},

  \tonRemove: function () {
  \t\tremove(this._image);
  \t\tif (this.options.interactive) {
  \t\t\tthis.removeInteractiveTarget(this._image);
  \t\t}
  \t},

  \t// @method setOpacity(opacity: Number): this
  \t// Sets the opacity of the overlay.
  \tsetOpacity: function (opacity) {
  \t\tthis.options.opacity = opacity;

  \t\tif (this._image) {
  \t\t\tthis._updateOpacity();
  \t\t}
  \t\treturn this;
  \t},

  \tsetStyle: function (styleOpts) {
  \t\tif (styleOpts.opacity) {
  \t\t\tthis.setOpacity(styleOpts.opacity);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method bringToFront(): this
  \t// Brings the layer to the top of all overlays.
  \tbringToFront: function () {
  \t\tif (this._map) {
  \t\t\ttoFront(this._image);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method bringToBack(): this
  \t// Brings the layer to the bottom of all overlays.
  \tbringToBack: function () {
  \t\tif (this._map) {
  \t\t\ttoBack(this._image);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method setUrl(url: String): this
  \t// Changes the URL of the image.
  \tsetUrl: function (url) {
  \t\tthis._url = url;

  \t\tif (this._image) {
  \t\t\tthis._image.src = url;
  \t\t}
  \t\treturn this;
  \t},

  \t// @method setBounds(bounds: LatLngBounds): this
  \t// Update the bounds that this ImageOverlay covers
  \tsetBounds: function (bounds) {
  \t\tthis._bounds = toLatLngBounds(bounds);

  \t\tif (this._map) {
  \t\t\tthis._reset();
  \t\t}
  \t\treturn this;
  \t},

  \tgetEvents: function () {
  \t\tvar events = {
  \t\t\tzoom: this._reset,
  \t\t\tviewreset: this._reset
  \t\t};

  \t\tif (this._zoomAnimated) {
  \t\t\tevents.zoomanim = this._animateZoom;
  \t\t}

  \t\treturn events;
  \t},

  \t// @method setZIndex(value: Number): this
  \t// Changes the [zIndex](#imageoverlay-zindex) of the image overlay.
  \tsetZIndex: function (value) {
  \t\tthis.options.zIndex = value;
  \t\tthis._updateZIndex();
  \t\treturn this;
  \t},

  \t// @method getBounds(): LatLngBounds
  \t// Get the bounds that this ImageOverlay covers
  \tgetBounds: function () {
  \t\treturn this._bounds;
  \t},

  \t// @method getElement(): HTMLElement
  \t// Returns the instance of [`HTMLImageElement`](https://developer.mozilla.org/docs/Web/API/HTMLImageElement)
  \t// used by this overlay.
  \tgetElement: function () {
  \t\treturn this._image;
  \t},

  \t_initImage: function () {
  \t\tvar wasElementSupplied = this._url.tagName === 'IMG';
  \t\tvar img = this._image = wasElementSupplied ? this._url : create\$1('img');

  \t\taddClass(img, 'leaflet-image-layer');
  \t\tif (this._zoomAnimated) { addClass(img, 'leaflet-zoom-animated'); }
  \t\tif (this.options.className) { addClass(img, this.options.className); }

  \t\timg.onselectstart = falseFn;
  \t\timg.onmousemove = falseFn;

  \t\t// @event load: Event
  \t\t// Fired when the ImageOverlay layer has loaded its image
  \t\timg.onload = bind(this.fire, this, 'load');
  \t\timg.onerror = bind(this._overlayOnError, this, 'error');

  \t\tif (this.options.crossOrigin || this.options.crossOrigin === '') {
  \t\t\timg.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin;
  \t\t}

  \t\tif (this.options.zIndex) {
  \t\t\tthis._updateZIndex();
  \t\t}

  \t\tif (wasElementSupplied) {
  \t\t\tthis._url = img.src;
  \t\t\treturn;
  \t\t}

  \t\timg.src = this._url;
  \t\timg.alt = this.options.alt;
  \t},

  \t_animateZoom: function (e) {
  \t\tvar scale = this._map.getZoomScale(e.zoom),
  \t\t    offset = this._map._latLngBoundsToNewLayerBounds(this._bounds, e.zoom, e.center).min;

  \t\tsetTransform(this._image, offset, scale);
  \t},

  \t_reset: function () {
  \t\tvar image = this._image,
  \t\t    bounds = new Bounds(
  \t\t        this._map.latLngToLayerPoint(this._bounds.getNorthWest()),
  \t\t        this._map.latLngToLayerPoint(this._bounds.getSouthEast())),
  \t\t    size = bounds.getSize();

  \t\tsetPosition(image, bounds.min);

  \t\timage.style.width  = size.x + 'px';
  \t\timage.style.height = size.y + 'px';
  \t},

  \t_updateOpacity: function () {
  \t\tsetOpacity(this._image, this.options.opacity);
  \t},

  \t_updateZIndex: function () {
  \t\tif (this._image && this.options.zIndex !== undefined && this.options.zIndex !== null) {
  \t\t\tthis._image.style.zIndex = this.options.zIndex;
  \t\t}
  \t},

  \t_overlayOnError: function () {
  \t\t// @event error: Event
  \t\t// Fired when the ImageOverlay layer fails to load its image
  \t\tthis.fire('error');

  \t\tvar errorUrl = this.options.errorOverlayUrl;
  \t\tif (errorUrl && this._url !== errorUrl) {
  \t\t\tthis._url = errorUrl;
  \t\t\tthis._image.src = errorUrl;
  \t\t}
  \t},

  \t// @method getCenter(): LatLng
  \t// Returns the center of the ImageOverlay.
  \tgetCenter: function () {
  \t\treturn this._bounds.getCenter();
  \t}
  });

  // @factory L.imageOverlay(imageUrl: String, bounds: LatLngBounds, options?: ImageOverlay options)
  // Instantiates an image overlay object given the URL of the image and the
  // geographical bounds it is tied to.
  var imageOverlay = function (url, bounds, options) {
  \treturn new ImageOverlay(url, bounds, options);
  };

  /*
   * @class VideoOverlay
   * @aka L.VideoOverlay
   * @inherits ImageOverlay
   *
   * Used to load and display a video player over specific bounds of the map. Extends `ImageOverlay`.
   *
   * A video overlay uses the [`<video>`](https://developer.mozilla.org/docs/Web/HTML/Element/video)
   * HTML5 element.
   *
   * @example
   *
   * ```js
   * var videoUrl = 'https://www.mapbox.com/bites/00188/patricia_nasa.webm',
   * \tvideoBounds = [[ 32, -130], [ 13, -100]];
   * L.videoOverlay(videoUrl, videoBounds ).addTo(map);
   * ```
   */

  var VideoOverlay = ImageOverlay.extend({

  \t// @section
  \t// @aka VideoOverlay options
  \toptions: {
  \t\t// @option autoplay: Boolean = true
  \t\t// Whether the video starts playing automatically when loaded.
  \t\t// On some browsers autoplay will only work with `muted: true`
  \t\tautoplay: true,

  \t\t// @option loop: Boolean = true
  \t\t// Whether the video will loop back to the beginning when played.
  \t\tloop: true,

  \t\t// @option keepAspectRatio: Boolean = true
  \t\t// Whether the video will save aspect ratio after the projection.
  \t\t// Relevant for supported browsers. See [browser compatibility](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit)
  \t\tkeepAspectRatio: true,

  \t\t// @option muted: Boolean = false
  \t\t// Whether the video starts on mute when loaded.
  \t\tmuted: false,

  \t\t// @option playsInline: Boolean = true
  \t\t// Mobile browsers will play the video right where it is instead of open it up in fullscreen mode.
  \t\tplaysInline: true
  \t},

  \t_initImage: function () {
  \t\tvar wasElementSupplied = this._url.tagName === 'VIDEO';
  \t\tvar vid = this._image = wasElementSupplied ? this._url : create\$1('video');

  \t\taddClass(vid, 'leaflet-image-layer');
  \t\tif (this._zoomAnimated) { addClass(vid, 'leaflet-zoom-animated'); }
  \t\tif (this.options.className) { addClass(vid, this.options.className); }

  \t\tvid.onselectstart = falseFn;
  \t\tvid.onmousemove = falseFn;

  \t\t// @event load: Event
  \t\t// Fired when the video has finished loading the first frame
  \t\tvid.onloadeddata = bind(this.fire, this, 'load');

  \t\tif (wasElementSupplied) {
  \t\t\tvar sourceElements = vid.getElementsByTagName('source');
  \t\t\tvar sources = [];
  \t\t\tfor (var j = 0; j < sourceElements.length; j++) {
  \t\t\t\tsources.push(sourceElements[j].src);
  \t\t\t}

  \t\t\tthis._url = (sourceElements.length > 0) ? sources : [vid.src];
  \t\t\treturn;
  \t\t}

  \t\tif (!isArray(this._url)) { this._url = [this._url]; }

  \t\tif (!this.options.keepAspectRatio && Object.prototype.hasOwnProperty.call(vid.style, 'objectFit')) {
  \t\t\tvid.style['objectFit'] = 'fill';
  \t\t}
  \t\tvid.autoplay = !!this.options.autoplay;
  \t\tvid.loop = !!this.options.loop;
  \t\tvid.muted = !!this.options.muted;
  \t\tvid.playsInline = !!this.options.playsInline;
  \t\tfor (var i = 0; i < this._url.length; i++) {
  \t\t\tvar source = create\$1('source');
  \t\t\tsource.src = this._url[i];
  \t\t\tvid.appendChild(source);
  \t\t}
  \t}

  \t// @method getElement(): HTMLVideoElement
  \t// Returns the instance of [`HTMLVideoElement`](https://developer.mozilla.org/docs/Web/API/HTMLVideoElement)
  \t// used by this overlay.
  });


  // @factory L.videoOverlay(video: String|Array|HTMLVideoElement, bounds: LatLngBounds, options?: VideoOverlay options)
  // Instantiates an image overlay object given the URL of the video (or array of URLs, or even a video element) and the
  // geographical bounds it is tied to.

  function videoOverlay(video, bounds, options) {
  \treturn new VideoOverlay(video, bounds, options);
  }

  /*
   * @class SVGOverlay
   * @aka L.SVGOverlay
   * @inherits ImageOverlay
   *
   * Used to load, display and provide DOM access to an SVG file over specific bounds of the map. Extends `ImageOverlay`.
   *
   * An SVG overlay uses the [`<svg>`](https://developer.mozilla.org/docs/Web/SVG/Element/svg) element.
   *
   * @example
   *
   * ```js
   * var svgElement = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");
   * svgElement.setAttribute('xmlns', \"http://www.w3.org/2000/svg\");
   * svgElement.setAttribute('viewBox', \"0 0 200 200\");
   * svgElement.innerHTML = '<rect width=\"200\" height=\"200\"/><rect x=\"75\" y=\"23\" width=\"50\" height=\"50\" style=\"fill:red\"/><rect x=\"75\" y=\"123\" width=\"50\" height=\"50\" style=\"fill:#0013ff\"/>';
   * var svgElementBounds = [ [ 32, -130 ], [ 13, -100 ] ];
   * L.svgOverlay(svgElement, svgElementBounds).addTo(map);
   * ```
   */

  var SVGOverlay = ImageOverlay.extend({
  \t_initImage: function () {
  \t\tvar el = this._image = this._url;

  \t\taddClass(el, 'leaflet-image-layer');
  \t\tif (this._zoomAnimated) { addClass(el, 'leaflet-zoom-animated'); }
  \t\tif (this.options.className) { addClass(el, this.options.className); }

  \t\tel.onselectstart = falseFn;
  \t\tel.onmousemove = falseFn;
  \t}

  \t// @method getElement(): SVGElement
  \t// Returns the instance of [`SVGElement`](https://developer.mozilla.org/docs/Web/API/SVGElement)
  \t// used by this overlay.
  });


  // @factory L.svgOverlay(svg: String|SVGElement, bounds: LatLngBounds, options?: SVGOverlay options)
  // Instantiates an image overlay object given an SVG element and the geographical bounds it is tied to.
  // A viewBox attribute is required on the SVG element to zoom in and out properly.

  function svgOverlay(el, bounds, options) {
  \treturn new SVGOverlay(el, bounds, options);
  }

  /*
   * @class DivOverlay
   * @inherits Interactive layer
   * @aka L.DivOverlay
   * Base model for L.Popup and L.Tooltip. Inherit from it for custom overlays like plugins.
   */

  // @namespace DivOverlay
  var DivOverlay = Layer.extend({

  \t// @section
  \t// @aka DivOverlay options
  \toptions: {
  \t\t// @option interactive: Boolean = false
  \t\t// If true, the popup/tooltip will listen to the mouse events.
  \t\tinteractive: false,

  \t\t// @option offset: Point = Point(0, 0)
  \t\t// The offset of the overlay position.
  \t\toffset: [0, 0],

  \t\t// @option className: String = ''
  \t\t// A custom CSS class name to assign to the overlay.
  \t\tclassName: '',

  \t\t// @option pane: String = undefined
  \t\t// `Map pane` where the overlay will be added.
  \t\tpane: undefined,

  \t\t// @option content: String|HTMLElement|Function = ''
  \t\t// Sets the HTML content of the overlay while initializing. If a function is passed the source layer will be
  \t\t// passed to the function. The function should return a `String` or `HTMLElement` to be used in the overlay.
  \t\tcontent: ''
  \t},

  \tinitialize: function (options, source) {
  \t\tif (options && (options instanceof LatLng || isArray(options))) {
  \t\t\tthis._latlng = toLatLng(options);
  \t\t\tsetOptions(this, source);
  \t\t} else {
  \t\t\tsetOptions(this, options);
  \t\t\tthis._source = source;
  \t\t}
  \t\tif (this.options.content) {
  \t\t\tthis._content = this.options.content;
  \t\t}
  \t},

  \t// @method openOn(map: Map): this
  \t// Adds the overlay to the map.
  \t// Alternative to `map.openPopup(popup)`/`.openTooltip(tooltip)`.
  \topenOn: function (map) {
  \t\tmap = arguments.length ? map : this._source._map; // experimental, not the part of public api
  \t\tif (!map.hasLayer(this)) {
  \t\t\tmap.addLayer(this);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method close(): this
  \t// Closes the overlay.
  \t// Alternative to `map.closePopup(popup)`/`.closeTooltip(tooltip)`
  \t// and `layer.closePopup()`/`.closeTooltip()`.
  \tclose: function () {
  \t\tif (this._map) {
  \t\t\tthis._map.removeLayer(this);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method toggle(layer?: Layer): this
  \t// Opens or closes the overlay bound to layer depending on its current state.
  \t// Argument may be omitted only for overlay bound to layer.
  \t// Alternative to `layer.togglePopup()`/`.toggleTooltip()`.
  \ttoggle: function (layer) {
  \t\tif (this._map) {
  \t\t\tthis.close();
  \t\t} else {
  \t\t\tif (arguments.length) {
  \t\t\t\tthis._source = layer;
  \t\t\t} else {
  \t\t\t\tlayer = this._source;
  \t\t\t}
  \t\t\tthis._prepareOpen();

  \t\t\t// open the overlay on the map
  \t\t\tthis.openOn(layer._map);
  \t\t}
  \t\treturn this;
  \t},

  \tonAdd: function (map) {
  \t\tthis._zoomAnimated = map._zoomAnimated;

  \t\tif (!this._container) {
  \t\t\tthis._initLayout();
  \t\t}

  \t\tif (map._fadeAnimated) {
  \t\t\tsetOpacity(this._container, 0);
  \t\t}

  \t\tclearTimeout(this._removeTimeout);
  \t\tthis.getPane().appendChild(this._container);
  \t\tthis.update();

  \t\tif (map._fadeAnimated) {
  \t\t\tsetOpacity(this._container, 1);
  \t\t}

  \t\tthis.bringToFront();

  \t\tif (this.options.interactive) {
  \t\t\taddClass(this._container, 'leaflet-interactive');
  \t\t\tthis.addInteractiveTarget(this._container);
  \t\t}
  \t},

  \tonRemove: function (map) {
  \t\tif (map._fadeAnimated) {
  \t\t\tsetOpacity(this._container, 0);
  \t\t\tthis._removeTimeout = setTimeout(bind(remove, undefined, this._container), 200);
  \t\t} else {
  \t\t\tremove(this._container);
  \t\t}

  \t\tif (this.options.interactive) {
  \t\t\tremoveClass(this._container, 'leaflet-interactive');
  \t\t\tthis.removeInteractiveTarget(this._container);
  \t\t}
  \t},

  \t// @namespace DivOverlay
  \t// @method getLatLng: LatLng
  \t// Returns the geographical point of the overlay.
  \tgetLatLng: function () {
  \t\treturn this._latlng;
  \t},

  \t// @method setLatLng(latlng: LatLng): this
  \t// Sets the geographical point where the overlay will open.
  \tsetLatLng: function (latlng) {
  \t\tthis._latlng = toLatLng(latlng);
  \t\tif (this._map) {
  \t\t\tthis._updatePosition();
  \t\t\tthis._adjustPan();
  \t\t}
  \t\treturn this;
  \t},

  \t// @method getContent: String|HTMLElement
  \t// Returns the content of the overlay.
  \tgetContent: function () {
  \t\treturn this._content;
  \t},

  \t// @method setContent(htmlContent: String|HTMLElement|Function): this
  \t// Sets the HTML content of the overlay. If a function is passed the source layer will be passed to the function.
  \t// The function should return a `String` or `HTMLElement` to be used in the overlay.
  \tsetContent: function (content) {
  \t\tthis._content = content;
  \t\tthis.update();
  \t\treturn this;
  \t},

  \t// @method getElement: String|HTMLElement
  \t// Returns the HTML container of the overlay.
  \tgetElement: function () {
  \t\treturn this._container;
  \t},

  \t// @method update: null
  \t// Updates the overlay content, layout and position. Useful for updating the overlay after something inside changed, e.g. image loaded.
  \tupdate: function () {
  \t\tif (!this._map) { return; }

  \t\tthis._container.style.visibility = 'hidden';

  \t\tthis._updateContent();
  \t\tthis._updateLayout();
  \t\tthis._updatePosition();

  \t\tthis._container.style.visibility = '';

  \t\tthis._adjustPan();
  \t},

  \tgetEvents: function () {
  \t\tvar events = {
  \t\t\tzoom: this._updatePosition,
  \t\t\tviewreset: this._updatePosition
  \t\t};

  \t\tif (this._zoomAnimated) {
  \t\t\tevents.zoomanim = this._animateZoom;
  \t\t}
  \t\treturn events;
  \t},

  \t// @method isOpen: Boolean
  \t// Returns `true` when the overlay is visible on the map.
  \tisOpen: function () {
  \t\treturn !!this._map && this._map.hasLayer(this);
  \t},

  \t// @method bringToFront: this
  \t// Brings this overlay in front of other overlays (in the same map pane).
  \tbringToFront: function () {
  \t\tif (this._map) {
  \t\t\ttoFront(this._container);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method bringToBack: this
  \t// Brings this overlay to the back of other overlays (in the same map pane).
  \tbringToBack: function () {
  \t\tif (this._map) {
  \t\t\ttoBack(this._container);
  \t\t}
  \t\treturn this;
  \t},

  \t// prepare bound overlay to open: update latlng pos / content source (for FeatureGroup)
  \t_prepareOpen: function (latlng) {
  \t\tvar source = this._source;
  \t\tif (!source._map) { return false; }

  \t\tif (source instanceof FeatureGroup) {
  \t\t\tsource = null;
  \t\t\tvar layers = this._source._layers;
  \t\t\tfor (var id in layers) {
  \t\t\t\tif (layers[id]._map) {
  \t\t\t\t\tsource = layers[id];
  \t\t\t\t\tbreak;
  \t\t\t\t}
  \t\t\t}
  \t\t\tif (!source) { return false; } // Unable to get source layer.

  \t\t\t// set overlay source to this layer
  \t\t\tthis._source = source;
  \t\t}

  \t\tif (!latlng) {
  \t\t\tif (source.getCenter) {
  \t\t\t\tlatlng = source.getCenter();
  \t\t\t} else if (source.getLatLng) {
  \t\t\t\tlatlng = source.getLatLng();
  \t\t\t} else if (source.getBounds) {
  \t\t\t\tlatlng = source.getBounds().getCenter();
  \t\t\t} else {
  \t\t\t\tthrow new Error('Unable to get source layer LatLng.');
  \t\t\t}
  \t\t}
  \t\tthis.setLatLng(latlng);

  \t\tif (this._map) {
  \t\t\t// update the overlay (content, layout, etc...)
  \t\t\tthis.update();
  \t\t}

  \t\treturn true;
  \t},

  \t_updateContent: function () {
  \t\tif (!this._content) { return; }

  \t\tvar node = this._contentNode;
  \t\tvar content = (typeof this._content === 'function') ? this._content(this._source || this) : this._content;

  \t\tif (typeof content === 'string') {
  \t\t\tnode.innerHTML = content;
  \t\t} else {
  \t\t\twhile (node.hasChildNodes()) {
  \t\t\t\tnode.removeChild(node.firstChild);
  \t\t\t}
  \t\t\tnode.appendChild(content);
  \t\t}

  \t\t// @namespace DivOverlay
  \t\t// @section DivOverlay events
  \t\t// @event contentupdate: Event
  \t\t// Fired when the content of the overlay is updated
  \t\tthis.fire('contentupdate');
  \t},

  \t_updatePosition: function () {
  \t\tif (!this._map) { return; }

  \t\tvar pos = this._map.latLngToLayerPoint(this._latlng),
  \t\t    offset = toPoint(this.options.offset),
  \t\t    anchor = this._getAnchor();

  \t\tif (this._zoomAnimated) {
  \t\t\tsetPosition(this._container, pos.add(anchor));
  \t\t} else {
  \t\t\toffset = offset.add(pos).add(anchor);
  \t\t}

  \t\tvar bottom = this._containerBottom = -offset.y,
  \t\t    left = this._containerLeft = -Math.round(this._containerWidth / 2) + offset.x;

  \t\t// bottom position the overlay in case the height of the overlay changes (images loading etc)
  \t\tthis._container.style.bottom = bottom + 'px';
  \t\tthis._container.style.left = left + 'px';
  \t},

  \t_getAnchor: function () {
  \t\treturn [0, 0];
  \t}

  });

  Map.include({
  \t_initOverlay: function (OverlayClass, content, latlng, options) {
  \t\tvar overlay = content;
  \t\tif (!(overlay instanceof OverlayClass)) {
  \t\t\toverlay = new OverlayClass(options).setContent(content);
  \t\t}
  \t\tif (latlng) {
  \t\t\toverlay.setLatLng(latlng);
  \t\t}
  \t\treturn overlay;
  \t}
  });


  Layer.include({
  \t_initOverlay: function (OverlayClass, old, content, options) {
  \t\tvar overlay = content;
  \t\tif (overlay instanceof OverlayClass) {
  \t\t\tsetOptions(overlay, options);
  \t\t\toverlay._source = this;
  \t\t} else {
  \t\t\toverlay = (old && !options) ? old : new OverlayClass(options, this);
  \t\t\toverlay.setContent(content);
  \t\t}
  \t\treturn overlay;
  \t}
  });

  /*
   * @class Popup
   * @inherits DivOverlay
   * @aka L.Popup
   * Used to open popups in certain places of the map. Use [Map.openPopup](#map-openpopup) to
   * open popups while making sure that only one popup is open at one time
   * (recommended for usability), or use [Map.addLayer](#map-addlayer) to open as many as you want.
   *
   * @example
   *
   * If you want to just bind a popup to marker click and then open it, it's really easy:
   *
   * ```js
   * marker.bindPopup(popupContent).openPopup();
   * ```
   * Path overlays like polylines also have a `bindPopup` method.
   *
   * A popup can be also standalone:
   *
   * ```js
   * var popup = L.popup()
   * \t.setLatLng(latlng)
   * \t.setContent('<p>Hello world!<br />This is a nice popup.</p>')
   * \t.openOn(map);
   * ```
   * or
   * ```js
   * var popup = L.popup(latlng, {content: '<p>Hello world!<br />This is a nice popup.</p>')
   * \t.openOn(map);
   * ```
   */


  // @namespace Popup
  var Popup = DivOverlay.extend({

  \t// @section
  \t// @aka Popup options
  \toptions: {
  \t\t// @option pane: String = 'popupPane'
  \t\t// `Map pane` where the popup will be added.
  \t\tpane: 'popupPane',

  \t\t// @option offset: Point = Point(0, 7)
  \t\t// The offset of the popup position.
  \t\toffset: [0, 7],

  \t\t// @option maxWidth: Number = 300
  \t\t// Max width of the popup, in pixels.
  \t\tmaxWidth: 300,

  \t\t// @option minWidth: Number = 50
  \t\t// Min width of the popup, in pixels.
  \t\tminWidth: 50,

  \t\t// @option maxHeight: Number = null
  \t\t// If set, creates a scrollable container of the given height
  \t\t// inside a popup if its content exceeds it.
  \t\t// The scrollable container can be styled using the
  \t\t// `leaflet-popup-scrolled` CSS class selector.
  \t\tmaxHeight: null,

  \t\t// @option autoPan: Boolean = true
  \t\t// Set it to `false` if you don't want the map to do panning animation
  \t\t// to fit the opened popup.
  \t\tautoPan: true,

  \t\t// @option autoPanPaddingTopLeft: Point = null
  \t\t// The margin between the popup and the top left corner of the map
  \t\t// view after autopanning was performed.
  \t\tautoPanPaddingTopLeft: null,

  \t\t// @option autoPanPaddingBottomRight: Point = null
  \t\t// The margin between the popup and the bottom right corner of the map
  \t\t// view after autopanning was performed.
  \t\tautoPanPaddingBottomRight: null,

  \t\t// @option autoPanPadding: Point = Point(5, 5)
  \t\t// Equivalent of setting both top left and bottom right autopan padding to the same value.
  \t\tautoPanPadding: [5, 5],

  \t\t// @option keepInView: Boolean = false
  \t\t// Set it to `true` if you want to prevent users from panning the popup
  \t\t// off of the screen while it is open.
  \t\tkeepInView: false,

  \t\t// @option closeButton: Boolean = true
  \t\t// Controls the presence of a close button in the popup.
  \t\tcloseButton: true,

  \t\t// @option autoClose: Boolean = true
  \t\t// Set it to `false` if you want to override the default behavior of
  \t\t// the popup closing when another popup is opened.
  \t\tautoClose: true,

  \t\t// @option closeOnEscapeKey: Boolean = true
  \t\t// Set it to `false` if you want to override the default behavior of
  \t\t// the ESC key for closing of the popup.
  \t\tcloseOnEscapeKey: true,

  \t\t// @option closeOnClick: Boolean = *
  \t\t// Set it if you want to override the default behavior of the popup closing when user clicks
  \t\t// on the map. Defaults to the map's [`closePopupOnClick`](#map-closepopuponclick) option.

  \t\t// @option className: String = ''
  \t\t// A custom CSS class name to assign to the popup.
  \t\tclassName: ''
  \t},

  \t// @namespace Popup
  \t// @method openOn(map: Map): this
  \t// Alternative to `map.openPopup(popup)`.
  \t// Adds the popup to the map and closes the previous one.
  \topenOn: function (map) {
  \t\tmap = arguments.length ? map : this._source._map; // experimental, not the part of public api

  \t\tif (!map.hasLayer(this) && map._popup && map._popup.options.autoClose) {
  \t\t\tmap.removeLayer(map._popup);
  \t\t}
  \t\tmap._popup = this;

  \t\treturn DivOverlay.prototype.openOn.call(this, map);
  \t},

  \tonAdd: function (map) {
  \t\tDivOverlay.prototype.onAdd.call(this, map);

  \t\t// @namespace Map
  \t\t// @section Popup events
  \t\t// @event popupopen: PopupEvent
  \t\t// Fired when a popup is opened in the map
  \t\tmap.fire('popupopen', {popup: this});

  \t\tif (this._source) {
  \t\t\t// @namespace Layer
  \t\t\t// @section Popup events
  \t\t\t// @event popupopen: PopupEvent
  \t\t\t// Fired when a popup bound to this layer is opened
  \t\t\tthis._source.fire('popupopen', {popup: this}, true);
  \t\t\t// For non-path layers, we toggle the popup when clicking
  \t\t\t// again the layer, so prevent the map to reopen it.
  \t\t\tif (!(this._source instanceof Path)) {
  \t\t\t\tthis._source.on('preclick', stopPropagation);
  \t\t\t}
  \t\t}
  \t},

  \tonRemove: function (map) {
  \t\tDivOverlay.prototype.onRemove.call(this, map);

  \t\t// @namespace Map
  \t\t// @section Popup events
  \t\t// @event popupclose: PopupEvent
  \t\t// Fired when a popup in the map is closed
  \t\tmap.fire('popupclose', {popup: this});

  \t\tif (this._source) {
  \t\t\t// @namespace Layer
  \t\t\t// @section Popup events
  \t\t\t// @event popupclose: PopupEvent
  \t\t\t// Fired when a popup bound to this layer is closed
  \t\t\tthis._source.fire('popupclose', {popup: this}, true);
  \t\t\tif (!(this._source instanceof Path)) {
  \t\t\t\tthis._source.off('preclick', stopPropagation);
  \t\t\t}
  \t\t}
  \t},

  \tgetEvents: function () {
  \t\tvar events = DivOverlay.prototype.getEvents.call(this);

  \t\tif (this.options.closeOnClick !== undefined ? this.options.closeOnClick : this._map.options.closePopupOnClick) {
  \t\t\tevents.preclick = this.close;
  \t\t}

  \t\tif (this.options.keepInView) {
  \t\t\tevents.moveend = this._adjustPan;
  \t\t}

  \t\treturn events;
  \t},

  \t_initLayout: function () {
  \t\tvar prefix = 'leaflet-popup',
  \t\t    container = this._container = create\$1('div',
  \t\t\tprefix + ' ' + (this.options.className || '') +
  \t\t\t' leaflet-zoom-animated');

  \t\tvar wrapper = this._wrapper = create\$1('div', prefix + '-content-wrapper', container);
  \t\tthis._contentNode = create\$1('div', prefix + '-content', wrapper);

  \t\tdisableClickPropagation(container);
  \t\tdisableScrollPropagation(this._contentNode);
  \t\ton(container, 'contextmenu', stopPropagation);

  \t\tthis._tipContainer = create\$1('div', prefix + '-tip-container', container);
  \t\tthis._tip = create\$1('div', prefix + '-tip', this._tipContainer);

  \t\tif (this.options.closeButton) {
  \t\t\tvar closeButton = this._closeButton = create\$1('a', prefix + '-close-button', container);
  \t\t\tcloseButton.setAttribute('role', 'button'); // overrides the implicit role=link of <a> elements #7399
  \t\t\tcloseButton.setAttribute('aria-label', 'Close popup');
  \t\t\tcloseButton.href = '#close';
  \t\t\tcloseButton.innerHTML = '<span aria-hidden=\"true\">&#215;</span>';

  \t\t\ton(closeButton, 'click', function (ev) {
  \t\t\t\tpreventDefault(ev);
  \t\t\t\tthis.close();
  \t\t\t}, this);
  \t\t}
  \t},

  \t_updateLayout: function () {
  \t\tvar container = this._contentNode,
  \t\t    style = container.style;

  \t\tstyle.width = '';
  \t\tstyle.whiteSpace = 'nowrap';

  \t\tvar width = container.offsetWidth;
  \t\twidth = Math.min(width, this.options.maxWidth);
  \t\twidth = Math.max(width, this.options.minWidth);

  \t\tstyle.width = (width + 1) + 'px';
  \t\tstyle.whiteSpace = '';

  \t\tstyle.height = '';

  \t\tvar height = container.offsetHeight,
  \t\t    maxHeight = this.options.maxHeight,
  \t\t    scrolledClass = 'leaflet-popup-scrolled';

  \t\tif (maxHeight && height > maxHeight) {
  \t\t\tstyle.height = maxHeight + 'px';
  \t\t\taddClass(container, scrolledClass);
  \t\t} else {
  \t\t\tremoveClass(container, scrolledClass);
  \t\t}

  \t\tthis._containerWidth = this._container.offsetWidth;
  \t},

  \t_animateZoom: function (e) {
  \t\tvar pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center),
  \t\t    anchor = this._getAnchor();
  \t\tsetPosition(this._container, pos.add(anchor));
  \t},

  \t_adjustPan: function () {
  \t\tif (!this.options.autoPan) { return; }
  \t\tif (this._map._panAnim) { this._map._panAnim.stop(); }

  \t\t// We can endlessly recurse if keepInView is set and the view resets.
  \t\t// Let's guard against that by exiting early if we're responding to our own autopan.
  \t\tif (this._autopanning) {
  \t\t\tthis._autopanning = false;
  \t\t\treturn;
  \t\t}

  \t\tvar map = this._map,
  \t\t    marginBottom = parseInt(getStyle(this._container, 'marginBottom'), 10) || 0,
  \t\t    containerHeight = this._container.offsetHeight + marginBottom,
  \t\t    containerWidth = this._containerWidth,
  \t\t    layerPos = new Point(this._containerLeft, -containerHeight - this._containerBottom);

  \t\tlayerPos._add(getPosition(this._container));

  \t\tvar containerPos = map.layerPointToContainerPoint(layerPos),
  \t\t    padding = toPoint(this.options.autoPanPadding),
  \t\t    paddingTL = toPoint(this.options.autoPanPaddingTopLeft || padding),
  \t\t    paddingBR = toPoint(this.options.autoPanPaddingBottomRight || padding),
  \t\t    size = map.getSize(),
  \t\t    dx = 0,
  \t\t    dy = 0;

  \t\tif (containerPos.x + containerWidth + paddingBR.x > size.x) { // right
  \t\t\tdx = containerPos.x + containerWidth - size.x + paddingBR.x;
  \t\t}
  \t\tif (containerPos.x - dx - paddingTL.x < 0) { // left
  \t\t\tdx = containerPos.x - paddingTL.x;
  \t\t}
  \t\tif (containerPos.y + containerHeight + paddingBR.y > size.y) { // bottom
  \t\t\tdy = containerPos.y + containerHeight - size.y + paddingBR.y;
  \t\t}
  \t\tif (containerPos.y - dy - paddingTL.y < 0) { // top
  \t\t\tdy = containerPos.y - paddingTL.y;
  \t\t}

  \t\t// @namespace Map
  \t\t// @section Popup events
  \t\t// @event autopanstart: Event
  \t\t// Fired when the map starts autopanning when opening a popup.
  \t\tif (dx || dy) {
  \t\t\t// Track that we're autopanning, as this function will be re-ran on moveend
  \t\t\tif (this.options.keepInView) {
  \t\t\t\tthis._autopanning = true;
  \t\t\t}

  \t\t\tmap
  \t\t\t    .fire('autopanstart')
  \t\t\t    .panBy([dx, dy]);
  \t\t}
  \t},

  \t_getAnchor: function () {
  \t\t// Where should we anchor the popup on the source layer?
  \t\treturn toPoint(this._source && this._source._getPopupAnchor ? this._source._getPopupAnchor() : [0, 0]);
  \t}

  });

  // @namespace Popup
  // @factory L.popup(options?: Popup options, source?: Layer)
  // Instantiates a `Popup` object given an optional `options` object that describes its appearance and location and an optional `source` object that is used to tag the popup with a reference to the Layer to which it refers.
  // @alternative
  // @factory L.popup(latlng: LatLng, options?: Popup options)
  // Instantiates a `Popup` object given `latlng` where the popup will open and an optional `options` object that describes its appearance and location.
  var popup = function (options, source) {
  \treturn new Popup(options, source);
  };


  /* @namespace Map
   * @section Interaction Options
   * @option closePopupOnClick: Boolean = true
   * Set it to `false` if you don't want popups to close when user clicks the map.
   */
  Map.mergeOptions({
  \tclosePopupOnClick: true
  });


  // @namespace Map
  // @section Methods for Layers and Controls
  Map.include({
  \t// @method openPopup(popup: Popup): this
  \t// Opens the specified popup while closing the previously opened (to make sure only one is opened at one time for usability).
  \t// @alternative
  \t// @method openPopup(content: String|HTMLElement, latlng: LatLng, options?: Popup options): this
  \t// Creates a popup with the specified content and options and opens it in the given point on a map.
  \topenPopup: function (popup, latlng, options) {
  \t\tthis._initOverlay(Popup, popup, latlng, options)
  \t\t  .openOn(this);

  \t\treturn this;
  \t},

  \t// @method closePopup(popup?: Popup): this
  \t// Closes the popup previously opened with [openPopup](#map-openpopup) (or the given one).
  \tclosePopup: function (popup) {
  \t\tpopup = arguments.length ? popup : this._popup;
  \t\tif (popup) {
  \t\t\tpopup.close();
  \t\t}
  \t\treturn this;
  \t}
  });

  /*
   * @namespace Layer
   * @section Popup methods example
   *
   * All layers share a set of methods convenient for binding popups to it.
   *
   * ```js
   * var layer = L.Polygon(latlngs).bindPopup('Hi There!').addTo(map);
   * layer.openPopup();
   * layer.closePopup();
   * ```
   *
   * Popups will also be automatically opened when the layer is clicked on and closed when the layer is removed from the map or another popup is opened.
   */

  // @section Popup methods
  Layer.include({

  \t// @method bindPopup(content: String|HTMLElement|Function|Popup, options?: Popup options): this
  \t// Binds a popup to the layer with the passed `content` and sets up the
  \t// necessary event listeners. If a `Function` is passed it will receive
  \t// the layer as the first argument and should return a `String` or `HTMLElement`.
  \tbindPopup: function (content, options) {
  \t\tthis._popup = this._initOverlay(Popup, this._popup, content, options);
  \t\tif (!this._popupHandlersAdded) {
  \t\t\tthis.on({
  \t\t\t\tclick: this._openPopup,
  \t\t\t\tkeypress: this._onKeyPress,
  \t\t\t\tremove: this.closePopup,
  \t\t\t\tmove: this._movePopup
  \t\t\t});
  \t\t\tthis._popupHandlersAdded = true;
  \t\t}

  \t\treturn this;
  \t},

  \t// @method unbindPopup(): this
  \t// Removes the popup previously bound with `bindPopup`.
  \tunbindPopup: function () {
  \t\tif (this._popup) {
  \t\t\tthis.off({
  \t\t\t\tclick: this._openPopup,
  \t\t\t\tkeypress: this._onKeyPress,
  \t\t\t\tremove: this.closePopup,
  \t\t\t\tmove: this._movePopup
  \t\t\t});
  \t\t\tthis._popupHandlersAdded = false;
  \t\t\tthis._popup = null;
  \t\t}
  \t\treturn this;
  \t},

  \t// @method openPopup(latlng?: LatLng): this
  \t// Opens the bound popup at the specified `latlng` or at the default popup anchor if no `latlng` is passed.
  \topenPopup: function (latlng) {
  \t\tif (this._popup) {
  \t\t\tif (!(this instanceof FeatureGroup)) {
  \t\t\t\tthis._popup._source = this;
  \t\t\t}
  \t\t\tif (this._popup._prepareOpen(latlng || this._latlng)) {
  \t\t\t\t// open the popup on the map
  \t\t\t\tthis._popup.openOn(this._map);
  \t\t\t}
  \t\t}
  \t\treturn this;
  \t},

  \t// @method closePopup(): this
  \t// Closes the popup bound to this layer if it is open.
  \tclosePopup: function () {
  \t\tif (this._popup) {
  \t\t\tthis._popup.close();
  \t\t}
  \t\treturn this;
  \t},

  \t// @method togglePopup(): this
  \t// Opens or closes the popup bound to this layer depending on its current state.
  \ttogglePopup: function () {
  \t\tif (this._popup) {
  \t\t\tthis._popup.toggle(this);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method isPopupOpen(): boolean
  \t// Returns `true` if the popup bound to this layer is currently open.
  \tisPopupOpen: function () {
  \t\treturn (this._popup ? this._popup.isOpen() : false);
  \t},

  \t// @method setPopupContent(content: String|HTMLElement|Popup): this
  \t// Sets the content of the popup bound to this layer.
  \tsetPopupContent: function (content) {
  \t\tif (this._popup) {
  \t\t\tthis._popup.setContent(content);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method getPopup(): Popup
  \t// Returns the popup bound to this layer.
  \tgetPopup: function () {
  \t\treturn this._popup;
  \t},

  \t_openPopup: function (e) {
  \t\tif (!this._popup || !this._map) {
  \t\t\treturn;
  \t\t}
  \t\t// prevent map click
  \t\tstop(e);

  \t\tvar target = e.layer || e.target;
  \t\tif (this._popup._source === target && !(target instanceof Path)) {
  \t\t\t// treat it like a marker and figure out
  \t\t\t// if we should toggle it open/closed
  \t\t\tif (this._map.hasLayer(this._popup)) {
  \t\t\t\tthis.closePopup();
  \t\t\t} else {
  \t\t\t\tthis.openPopup(e.latlng);
  \t\t\t}
  \t\t\treturn;
  \t\t}
  \t\tthis._popup._source = target;
  \t\tthis.openPopup(e.latlng);
  \t},

  \t_movePopup: function (e) {
  \t\tthis._popup.setLatLng(e.latlng);
  \t},

  \t_onKeyPress: function (e) {
  \t\tif (e.originalEvent.keyCode === 13) {
  \t\t\tthis._openPopup(e);
  \t\t}
  \t}
  });

  /*
   * @class Tooltip
   * @inherits DivOverlay
   * @aka L.Tooltip
   * Used to display small texts on top of map layers.
   *
   * @example
   * If you want to just bind a tooltip to marker:
   *
   * ```js
   * marker.bindTooltip(\"my tooltip text\").openTooltip();
   * ```
   * Path overlays like polylines also have a `bindTooltip` method.
   *
   * A tooltip can be also standalone:
   *
   * ```js
   * var tooltip = L.tooltip()
   * \t.setLatLng(latlng)
   * \t.setContent('Hello world!<br />This is a nice tooltip.')
   * \t.addTo(map);
   * ```
   * or
   * ```js
   * var tooltip = L.tooltip(latlng, {content: 'Hello world!<br />This is a nice tooltip.'})
   * \t.addTo(map);
   * ```
   *
   *
   * Note about tooltip offset. Leaflet takes two options in consideration
   * for computing tooltip offsetting:
   * - the `offset` Tooltip option: it defaults to [0, 0], and it's specific to one tooltip.
   *   Add a positive x offset to move the tooltip to the right, and a positive y offset to
   *   move it to the bottom. Negatives will move to the left and top.
   * - the `tooltipAnchor` Icon option: this will only be considered for Marker. You
   *   should adapt this value if you use a custom icon.
   */


  // @namespace Tooltip
  var Tooltip = DivOverlay.extend({

  \t// @section
  \t// @aka Tooltip options
  \toptions: {
  \t\t// @option pane: String = 'tooltipPane'
  \t\t// `Map pane` where the tooltip will be added.
  \t\tpane: 'tooltipPane',

  \t\t// @option offset: Point = Point(0, 0)
  \t\t// Optional offset of the tooltip position.
  \t\toffset: [0, 0],

  \t\t// @option direction: String = 'auto'
  \t\t// Direction where to open the tooltip. Possible values are: `right`, `left`,
  \t\t// `top`, `bottom`, `center`, `auto`.
  \t\t// `auto` will dynamically switch between `right` and `left` according to the tooltip
  \t\t// position on the map.
  \t\tdirection: 'auto',

  \t\t// @option permanent: Boolean = false
  \t\t// Whether to open the tooltip permanently or only on mouseover.
  \t\tpermanent: false,

  \t\t// @option sticky: Boolean = false
  \t\t// If true, the tooltip will follow the mouse instead of being fixed at the feature center.
  \t\tsticky: false,

  \t\t// @option opacity: Number = 0.9
  \t\t// Tooltip container opacity.
  \t\topacity: 0.9
  \t},

  \tonAdd: function (map) {
  \t\tDivOverlay.prototype.onAdd.call(this, map);
  \t\tthis.setOpacity(this.options.opacity);

  \t\t// @namespace Map
  \t\t// @section Tooltip events
  \t\t// @event tooltipopen: TooltipEvent
  \t\t// Fired when a tooltip is opened in the map.
  \t\tmap.fire('tooltipopen', {tooltip: this});

  \t\tif (this._source) {
  \t\t\tthis.addEventParent(this._source);

  \t\t\t// @namespace Layer
  \t\t\t// @section Tooltip events
  \t\t\t// @event tooltipopen: TooltipEvent
  \t\t\t// Fired when a tooltip bound to this layer is opened.
  \t\t\tthis._source.fire('tooltipopen', {tooltip: this}, true);
  \t\t}
  \t},

  \tonRemove: function (map) {
  \t\tDivOverlay.prototype.onRemove.call(this, map);

  \t\t// @namespace Map
  \t\t// @section Tooltip events
  \t\t// @event tooltipclose: TooltipEvent
  \t\t// Fired when a tooltip in the map is closed.
  \t\tmap.fire('tooltipclose', {tooltip: this});

  \t\tif (this._source) {
  \t\t\tthis.removeEventParent(this._source);

  \t\t\t// @namespace Layer
  \t\t\t// @section Tooltip events
  \t\t\t// @event tooltipclose: TooltipEvent
  \t\t\t// Fired when a tooltip bound to this layer is closed.
  \t\t\tthis._source.fire('tooltipclose', {tooltip: this}, true);
  \t\t}
  \t},

  \tgetEvents: function () {
  \t\tvar events = DivOverlay.prototype.getEvents.call(this);

  \t\tif (!this.options.permanent) {
  \t\t\tevents.preclick = this.close;
  \t\t}

  \t\treturn events;
  \t},

  \t_initLayout: function () {
  \t\tvar prefix = 'leaflet-tooltip',
  \t\t    className = prefix + ' ' + (this.options.className || '') + ' leaflet-zoom-' + (this._zoomAnimated ? 'animated' : 'hide');

  \t\tthis._contentNode = this._container = create\$1('div', className);

  \t\tthis._container.setAttribute('role', 'tooltip');
  \t\tthis._container.setAttribute('id', 'leaflet-tooltip-' + stamp(this));
  \t},

  \t_updateLayout: function () {},

  \t_adjustPan: function () {},

  \t_setPosition: function (pos) {
  \t\tvar subX, subY,
  \t\t    map = this._map,
  \t\t    container = this._container,
  \t\t    centerPoint = map.latLngToContainerPoint(map.getCenter()),
  \t\t    tooltipPoint = map.layerPointToContainerPoint(pos),
  \t\t    direction = this.options.direction,
  \t\t    tooltipWidth = container.offsetWidth,
  \t\t    tooltipHeight = container.offsetHeight,
  \t\t    offset = toPoint(this.options.offset),
  \t\t    anchor = this._getAnchor();

  \t\tif (direction === 'top') {
  \t\t\tsubX = tooltipWidth / 2;
  \t\t\tsubY = tooltipHeight;
  \t\t} else if (direction === 'bottom') {
  \t\t\tsubX = tooltipWidth / 2;
  \t\t\tsubY = 0;
  \t\t} else if (direction === 'center') {
  \t\t\tsubX = tooltipWidth / 2;
  \t\t\tsubY = tooltipHeight / 2;
  \t\t} else if (direction === 'right') {
  \t\t\tsubX = 0;
  \t\t\tsubY = tooltipHeight / 2;
  \t\t} else if (direction === 'left') {
  \t\t\tsubX = tooltipWidth;
  \t\t\tsubY = tooltipHeight / 2;
  \t\t} else if (tooltipPoint.x < centerPoint.x) {
  \t\t\tdirection = 'right';
  \t\t\tsubX = 0;
  \t\t\tsubY = tooltipHeight / 2;
  \t\t} else {
  \t\t\tdirection = 'left';
  \t\t\tsubX = tooltipWidth + (offset.x + anchor.x) * 2;
  \t\t\tsubY = tooltipHeight / 2;
  \t\t}

  \t\tpos = pos.subtract(toPoint(subX, subY, true)).add(offset).add(anchor);

  \t\tremoveClass(container, 'leaflet-tooltip-right');
  \t\tremoveClass(container, 'leaflet-tooltip-left');
  \t\tremoveClass(container, 'leaflet-tooltip-top');
  \t\tremoveClass(container, 'leaflet-tooltip-bottom');
  \t\taddClass(container, 'leaflet-tooltip-' + direction);
  \t\tsetPosition(container, pos);
  \t},

  \t_updatePosition: function () {
  \t\tvar pos = this._map.latLngToLayerPoint(this._latlng);
  \t\tthis._setPosition(pos);
  \t},

  \tsetOpacity: function (opacity) {
  \t\tthis.options.opacity = opacity;

  \t\tif (this._container) {
  \t\t\tsetOpacity(this._container, opacity);
  \t\t}
  \t},

  \t_animateZoom: function (e) {
  \t\tvar pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center);
  \t\tthis._setPosition(pos);
  \t},

  \t_getAnchor: function () {
  \t\t// Where should we anchor the tooltip on the source layer?
  \t\treturn toPoint(this._source && this._source._getTooltipAnchor && !this.options.sticky ? this._source._getTooltipAnchor() : [0, 0]);
  \t}

  });

  // @namespace Tooltip
  // @factory L.tooltip(options?: Tooltip options, source?: Layer)
  // Instantiates a `Tooltip` object given an optional `options` object that describes its appearance and location and an optional `source` object that is used to tag the tooltip with a reference to the Layer to which it refers.
  // @alternative
  // @factory L.tooltip(latlng: LatLng, options?: Tooltip options)
  // Instantiates a `Tooltip` object given `latlng` where the tooltip will open and an optional `options` object that describes its appearance and location.
  var tooltip = function (options, source) {
  \treturn new Tooltip(options, source);
  };

  // @namespace Map
  // @section Methods for Layers and Controls
  Map.include({

  \t// @method openTooltip(tooltip: Tooltip): this
  \t// Opens the specified tooltip.
  \t// @alternative
  \t// @method openTooltip(content: String|HTMLElement, latlng: LatLng, options?: Tooltip options): this
  \t// Creates a tooltip with the specified content and options and open it.
  \topenTooltip: function (tooltip, latlng, options) {
  \t\tthis._initOverlay(Tooltip, tooltip, latlng, options)
  \t\t  .openOn(this);

  \t\treturn this;
  \t},

  \t// @method closeTooltip(tooltip: Tooltip): this
  \t// Closes the tooltip given as parameter.
  \tcloseTooltip: function (tooltip) {
  \t\ttooltip.close();
  \t\treturn this;
  \t}

  });

  /*
   * @namespace Layer
   * @section Tooltip methods example
   *
   * All layers share a set of methods convenient for binding tooltips to it.
   *
   * ```js
   * var layer = L.Polygon(latlngs).bindTooltip('Hi There!').addTo(map);
   * layer.openTooltip();
   * layer.closeTooltip();
   * ```
   */

  // @section Tooltip methods
  Layer.include({

  \t// @method bindTooltip(content: String|HTMLElement|Function|Tooltip, options?: Tooltip options): this
  \t// Binds a tooltip to the layer with the passed `content` and sets up the
  \t// necessary event listeners. If a `Function` is passed it will receive
  \t// the layer as the first argument and should return a `String` or `HTMLElement`.
  \tbindTooltip: function (content, options) {

  \t\tif (this._tooltip && this.isTooltipOpen()) {
  \t\t\tthis.unbindTooltip();
  \t\t}

  \t\tthis._tooltip = this._initOverlay(Tooltip, this._tooltip, content, options);
  \t\tthis._initTooltipInteractions();

  \t\tif (this._tooltip.options.permanent && this._map && this._map.hasLayer(this)) {
  \t\t\tthis.openTooltip();
  \t\t}

  \t\treturn this;
  \t},

  \t// @method unbindTooltip(): this
  \t// Removes the tooltip previously bound with `bindTooltip`.
  \tunbindTooltip: function () {
  \t\tif (this._tooltip) {
  \t\t\tthis._initTooltipInteractions(true);
  \t\t\tthis.closeTooltip();
  \t\t\tthis._tooltip = null;
  \t\t}
  \t\treturn this;
  \t},

  \t_initTooltipInteractions: function (remove) {
  \t\tif (!remove && this._tooltipHandlersAdded) { return; }
  \t\tvar onOff = remove ? 'off' : 'on',
  \t\t    events = {
  \t\t\tremove: this.closeTooltip,
  \t\t\tmove: this._moveTooltip
  \t\t    };
  \t\tif (!this._tooltip.options.permanent) {
  \t\t\tevents.mouseover = this._openTooltip;
  \t\t\tevents.mouseout = this.closeTooltip;
  \t\t\tevents.click = this._openTooltip;
  \t\t\tif (this._map) {
  \t\t\t\tthis._addFocusListeners();
  \t\t\t} else {
  \t\t\t\tevents.add = this._addFocusListeners;
  \t\t\t}
  \t\t} else {
  \t\t\tevents.add = this._openTooltip;
  \t\t}
  \t\tif (this._tooltip.options.sticky) {
  \t\t\tevents.mousemove = this._moveTooltip;
  \t\t}
  \t\tthis[onOff](events);
  \t\tthis._tooltipHandlersAdded = !remove;
  \t},

  \t// @method openTooltip(latlng?: LatLng): this
  \t// Opens the bound tooltip at the specified `latlng` or at the default tooltip anchor if no `latlng` is passed.
  \topenTooltip: function (latlng) {
  \t\tif (this._tooltip) {
  \t\t\tif (!(this instanceof FeatureGroup)) {
  \t\t\t\tthis._tooltip._source = this;
  \t\t\t}
  \t\t\tif (this._tooltip._prepareOpen(latlng)) {
  \t\t\t\t// open the tooltip on the map
  \t\t\t\tthis._tooltip.openOn(this._map);

  \t\t\t\tif (this.getElement) {
  \t\t\t\t\tthis._setAriaDescribedByOnLayer(this);
  \t\t\t\t} else if (this.eachLayer) {
  \t\t\t\t\tthis.eachLayer(this._setAriaDescribedByOnLayer, this);
  \t\t\t\t}
  \t\t\t}
  \t\t}
  \t\treturn this;
  \t},

  \t// @method closeTooltip(): this
  \t// Closes the tooltip bound to this layer if it is open.
  \tcloseTooltip: function () {
  \t\tif (this._tooltip) {
  \t\t\treturn this._tooltip.close();
  \t\t}
  \t},

  \t// @method toggleTooltip(): this
  \t// Opens or closes the tooltip bound to this layer depending on its current state.
  \ttoggleTooltip: function () {
  \t\tif (this._tooltip) {
  \t\t\tthis._tooltip.toggle(this);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method isTooltipOpen(): boolean
  \t// Returns `true` if the tooltip bound to this layer is currently open.
  \tisTooltipOpen: function () {
  \t\treturn this._tooltip.isOpen();
  \t},

  \t// @method setTooltipContent(content: String|HTMLElement|Tooltip): this
  \t// Sets the content of the tooltip bound to this layer.
  \tsetTooltipContent: function (content) {
  \t\tif (this._tooltip) {
  \t\t\tthis._tooltip.setContent(content);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method getTooltip(): Tooltip
  \t// Returns the tooltip bound to this layer.
  \tgetTooltip: function () {
  \t\treturn this._tooltip;
  \t},

  \t_addFocusListeners: function () {
  \t\tif (this.getElement) {
  \t\t\tthis._addFocusListenersOnLayer(this);
  \t\t} else if (this.eachLayer) {
  \t\t\tthis.eachLayer(this._addFocusListenersOnLayer, this);
  \t\t}
  \t},

  \t_addFocusListenersOnLayer: function (layer) {
  \t\tvar el = typeof layer.getElement === 'function' && layer.getElement();
  \t\tif (el) {
  \t\t\ton(el, 'focus', function () {
  \t\t\t\tthis._tooltip._source = layer;
  \t\t\t\tthis.openTooltip();
  \t\t\t}, this);
  \t\t\ton(el, 'blur', this.closeTooltip, this);
  \t\t}
  \t},

  \t_setAriaDescribedByOnLayer: function (layer) {
  \t\tvar el = typeof layer.getElement === 'function' && layer.getElement();
  \t\tif (el) {
  \t\t\tel.setAttribute('aria-describedby', this._tooltip._container.id);
  \t\t}
  \t},


  \t_openTooltip: function (e) {
  \t\tif (!this._tooltip || !this._map) {
  \t\t\treturn;
  \t\t}

  \t\t// If the map is moving, we will show the tooltip after it's done.
  \t\tif (this._map.dragging && this._map.dragging.moving() && !this._openOnceFlag) {
  \t\t\tthis._openOnceFlag = true;
  \t\t\tvar that = this;
  \t\t\tthis._map.once('moveend', function () {
  \t\t\t\tthat._openOnceFlag = false;
  \t\t\t\tthat._openTooltip(e);
  \t\t\t});
  \t\t\treturn;
  \t\t}

  \t\tthis._tooltip._source = e.layer || e.target;

  \t\tthis.openTooltip(this._tooltip.options.sticky ? e.latlng : undefined);
  \t},

  \t_moveTooltip: function (e) {
  \t\tvar latlng = e.latlng, containerPoint, layerPoint;
  \t\tif (this._tooltip.options.sticky && e.originalEvent) {
  \t\t\tcontainerPoint = this._map.mouseEventToContainerPoint(e.originalEvent);
  \t\t\tlayerPoint = this._map.containerPointToLayerPoint(containerPoint);
  \t\t\tlatlng = this._map.layerPointToLatLng(layerPoint);
  \t\t}
  \t\tthis._tooltip.setLatLng(latlng);
  \t}
  });

  /*
   * @class DivIcon
   * @aka L.DivIcon
   * @inherits Icon
   *
   * Represents a lightweight icon for markers that uses a simple `<div>`
   * element instead of an image. Inherits from `Icon` but ignores the `iconUrl` and shadow options.
   *
   * @example
   * ```js
   * var myIcon = L.divIcon({className: 'my-div-icon'});
   * // you can set .my-div-icon styles in CSS
   *
   * L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
   * ```
   *
   * By default, it has a 'leaflet-div-icon' CSS class and is styled as a little white square with a shadow.
   */

  var DivIcon = Icon.extend({
  \toptions: {
  \t\t// @section
  \t\t// @aka DivIcon options
  \t\ticonSize: [12, 12], // also can be set through CSS

  \t\t// iconAnchor: (Point),
  \t\t// popupAnchor: (Point),

  \t\t// @option html: String|HTMLElement = ''
  \t\t// Custom HTML code to put inside the div element, empty by default. Alternatively,
  \t\t// an instance of `HTMLElement`.
  \t\thtml: false,

  \t\t// @option bgPos: Point = [0, 0]
  \t\t// Optional relative position of the background, in pixels
  \t\tbgPos: null,

  \t\tclassName: 'leaflet-div-icon'
  \t},

  \tcreateIcon: function (oldIcon) {
  \t\tvar div = (oldIcon && oldIcon.tagName === 'DIV') ? oldIcon : document.createElement('div'),
  \t\t    options = this.options;

  \t\tif (options.html instanceof Element) {
  \t\t\tempty(div);
  \t\t\tdiv.appendChild(options.html);
  \t\t} else {
  \t\t\tdiv.innerHTML = options.html !== false ? options.html : '';
  \t\t}

  \t\tif (options.bgPos) {
  \t\t\tvar bgPos = toPoint(options.bgPos);
  \t\t\tdiv.style.backgroundPosition = (-bgPos.x) + 'px ' + (-bgPos.y) + 'px';
  \t\t}
  \t\tthis._setIconStyles(div, 'icon');

  \t\treturn div;
  \t},

  \tcreateShadow: function () {
  \t\treturn null;
  \t}
  });

  // @factory L.divIcon(options: DivIcon options)
  // Creates a `DivIcon` instance with the given options.
  function divIcon(options) {
  \treturn new DivIcon(options);
  }

  Icon.Default = IconDefault;

  /*
   * @class GridLayer
   * @inherits Layer
   * @aka L.GridLayer
   *
   * Generic class for handling a tiled grid of HTML elements. This is the base class for all tile layers and replaces `TileLayer.Canvas`.
   * GridLayer can be extended to create a tiled grid of HTML elements like `<canvas>`, `<img>` or `<div>`. GridLayer will handle creating and animating these DOM elements for you.
   *
   *
   * @section Synchronous usage
   * @example
   *
   * To create a custom layer, extend GridLayer and implement the `createTile()` method, which will be passed a `Point` object with the `x`, `y`, and `z` (zoom level) coordinates to draw your tile.
   *
   * ```js
   * var CanvasLayer = L.GridLayer.extend({
   *     createTile: function(coords){
   *         // create a <canvas> element for drawing
   *         var tile = L.DomUtil.create('canvas', 'leaflet-tile');
   *
   *         // setup tile width and height according to the options
   *         var size = this.getTileSize();
   *         tile.width = size.x;
   *         tile.height = size.y;
   *
   *         // get a canvas context and draw something on it using coords.x, coords.y and coords.z
   *         var ctx = tile.getContext('2d');
   *
   *         // return the tile so it can be rendered on screen
   *         return tile;
   *     }
   * });
   * ```
   *
   * @section Asynchronous usage
   * @example
   *
   * Tile creation can also be asynchronous, this is useful when using a third-party drawing library. Once the tile is finished drawing it can be passed to the `done()` callback.
   *
   * ```js
   * var CanvasLayer = L.GridLayer.extend({
   *     createTile: function(coords, done){
   *         var error;
   *
   *         // create a <canvas> element for drawing
   *         var tile = L.DomUtil.create('canvas', 'leaflet-tile');
   *
   *         // setup tile width and height according to the options
   *         var size = this.getTileSize();
   *         tile.width = size.x;
   *         tile.height = size.y;
   *
   *         // draw something asynchronously and pass the tile to the done() callback
   *         setTimeout(function() {
   *             done(error, tile);
   *         }, 1000);
   *
   *         return tile;
   *     }
   * });
   * ```
   *
   * @section
   */


  var GridLayer = Layer.extend({

  \t// @section
  \t// @aka GridLayer options
  \toptions: {
  \t\t// @option tileSize: Number|Point = 256
  \t\t// Width and height of tiles in the grid. Use a number if width and height are equal, or `L.point(width, height)` otherwise.
  \t\ttileSize: 256,

  \t\t// @option opacity: Number = 1.0
  \t\t// Opacity of the tiles. Can be used in the `createTile()` function.
  \t\topacity: 1,

  \t\t// @option updateWhenIdle: Boolean = (depends)
  \t\t// Load new tiles only when panning ends.
  \t\t// `true` by default on mobile browsers, in order to avoid too many requests and keep smooth navigation.
  \t\t// `false` otherwise in order to display new tiles _during_ panning, since it is easy to pan outside the
  \t\t// [`keepBuffer`](#gridlayer-keepbuffer) option in desktop browsers.
  \t\tupdateWhenIdle: Browser.mobile,

  \t\t// @option updateWhenZooming: Boolean = true
  \t\t// By default, a smooth zoom animation (during a [touch zoom](#map-touchzoom) or a [`flyTo()`](#map-flyto)) will update grid layers every integer zoom level. Setting this option to `false` will update the grid layer only when the smooth animation ends.
  \t\tupdateWhenZooming: true,

  \t\t// @option updateInterval: Number = 200
  \t\t// Tiles will not update more than once every `updateInterval` milliseconds when panning.
  \t\tupdateInterval: 200,

  \t\t// @option zIndex: Number = 1
  \t\t// The explicit zIndex of the tile layer.
  \t\tzIndex: 1,

  \t\t// @option bounds: LatLngBounds = undefined
  \t\t// If set, tiles will only be loaded inside the set `LatLngBounds`.
  \t\tbounds: null,

  \t\t// @option minZoom: Number = 0
  \t\t// The minimum zoom level down to which this layer will be displayed (inclusive).
  \t\tminZoom: 0,

  \t\t// @option maxZoom: Number = undefined
  \t\t// The maximum zoom level up to which this layer will be displayed (inclusive).
  \t\tmaxZoom: undefined,

  \t\t// @option maxNativeZoom: Number = undefined
  \t\t// Maximum zoom number the tile source has available. If it is specified,
  \t\t// the tiles on all zoom levels higher than `maxNativeZoom` will be loaded
  \t\t// from `maxNativeZoom` level and auto-scaled.
  \t\tmaxNativeZoom: undefined,

  \t\t// @option minNativeZoom: Number = undefined
  \t\t// Minimum zoom number the tile source has available. If it is specified,
  \t\t// the tiles on all zoom levels lower than `minNativeZoom` will be loaded
  \t\t// from `minNativeZoom` level and auto-scaled.
  \t\tminNativeZoom: undefined,

  \t\t// @option noWrap: Boolean = false
  \t\t// Whether the layer is wrapped around the antimeridian. If `true`, the
  \t\t// GridLayer will only be displayed once at low zoom levels. Has no
  \t\t// effect when the [map CRS](#map-crs) doesn't wrap around. Can be used
  \t\t// in combination with [`bounds`](#gridlayer-bounds) to prevent requesting
  \t\t// tiles outside the CRS limits.
  \t\tnoWrap: false,

  \t\t// @option pane: String = 'tilePane'
  \t\t// `Map pane` where the grid layer will be added.
  \t\tpane: 'tilePane',

  \t\t// @option className: String = ''
  \t\t// A custom class name to assign to the tile layer. Empty by default.
  \t\tclassName: '',

  \t\t// @option keepBuffer: Number = 2
  \t\t// When panning the map, keep this many rows and columns of tiles before unloading them.
  \t\tkeepBuffer: 2
  \t},

  \tinitialize: function (options) {
  \t\tsetOptions(this, options);
  \t},

  \tonAdd: function () {
  \t\tthis._initContainer();

  \t\tthis._levels = {};
  \t\tthis._tiles = {};

  \t\tthis._resetView(); // implicit _update() call
  \t},

  \tbeforeAdd: function (map) {
  \t\tmap._addZoomLimit(this);
  \t},

  \tonRemove: function (map) {
  \t\tthis._removeAllTiles();
  \t\tremove(this._container);
  \t\tmap._removeZoomLimit(this);
  \t\tthis._container = null;
  \t\tthis._tileZoom = undefined;
  \t},

  \t// @method bringToFront: this
  \t// Brings the tile layer to the top of all tile layers.
  \tbringToFront: function () {
  \t\tif (this._map) {
  \t\t\ttoFront(this._container);
  \t\t\tthis._setAutoZIndex(Math.max);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method bringToBack: this
  \t// Brings the tile layer to the bottom of all tile layers.
  \tbringToBack: function () {
  \t\tif (this._map) {
  \t\t\ttoBack(this._container);
  \t\t\tthis._setAutoZIndex(Math.min);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method getContainer: HTMLElement
  \t// Returns the HTML element that contains the tiles for this layer.
  \tgetContainer: function () {
  \t\treturn this._container;
  \t},

  \t// @method setOpacity(opacity: Number): this
  \t// Changes the [opacity](#gridlayer-opacity) of the grid layer.
  \tsetOpacity: function (opacity) {
  \t\tthis.options.opacity = opacity;
  \t\tthis._updateOpacity();
  \t\treturn this;
  \t},

  \t// @method setZIndex(zIndex: Number): this
  \t// Changes the [zIndex](#gridlayer-zindex) of the grid layer.
  \tsetZIndex: function (zIndex) {
  \t\tthis.options.zIndex = zIndex;
  \t\tthis._updateZIndex();

  \t\treturn this;
  \t},

  \t// @method isLoading: Boolean
  \t// Returns `true` if any tile in the grid layer has not finished loading.
  \tisLoading: function () {
  \t\treturn this._loading;
  \t},

  \t// @method redraw: this
  \t// Causes the layer to clear all the tiles and request them again.
  \tredraw: function () {
  \t\tif (this._map) {
  \t\t\tthis._removeAllTiles();
  \t\t\tvar tileZoom = this._clampZoom(this._map.getZoom());
  \t\t\tif (tileZoom !== this._tileZoom) {
  \t\t\t\tthis._tileZoom = tileZoom;
  \t\t\t\tthis._updateLevels();
  \t\t\t}
  \t\t\tthis._update();
  \t\t}
  \t\treturn this;
  \t},

  \tgetEvents: function () {
  \t\tvar events = {
  \t\t\tviewprereset: this._invalidateAll,
  \t\t\tviewreset: this._resetView,
  \t\t\tzoom: this._resetView,
  \t\t\tmoveend: this._onMoveEnd
  \t\t};

  \t\tif (!this.options.updateWhenIdle) {
  \t\t\t// update tiles on move, but not more often than once per given interval
  \t\t\tif (!this._onMove) {
  \t\t\t\tthis._onMove = throttle(this._onMoveEnd, this.options.updateInterval, this);
  \t\t\t}

  \t\t\tevents.move = this._onMove;
  \t\t}

  \t\tif (this._zoomAnimated) {
  \t\t\tevents.zoomanim = this._animateZoom;
  \t\t}

  \t\treturn events;
  \t},

  \t// @section Extension methods
  \t// Layers extending `GridLayer` shall reimplement the following method.
  \t// @method createTile(coords: Object, done?: Function): HTMLElement
  \t// Called only internally, must be overridden by classes extending `GridLayer`.
  \t// Returns the `HTMLElement` corresponding to the given `coords`. If the `done` callback
  \t// is specified, it must be called when the tile has finished loading and drawing.
  \tcreateTile: function () {
  \t\treturn document.createElement('div');
  \t},

  \t// @section
  \t// @method getTileSize: Point
  \t// Normalizes the [tileSize option](#gridlayer-tilesize) into a point. Used by the `createTile()` method.
  \tgetTileSize: function () {
  \t\tvar s = this.options.tileSize;
  \t\treturn s instanceof Point ? s : new Point(s, s);
  \t},

  \t_updateZIndex: function () {
  \t\tif (this._container && this.options.zIndex !== undefined && this.options.zIndex !== null) {
  \t\t\tthis._container.style.zIndex = this.options.zIndex;
  \t\t}
  \t},

  \t_setAutoZIndex: function (compare) {
  \t\t// go through all other layers of the same pane, set zIndex to max + 1 (front) or min - 1 (back)

  \t\tvar layers = this.getPane().children,
  \t\t    edgeZIndex = -compare(-Infinity, Infinity); // -Infinity for max, Infinity for min

  \t\tfor (var i = 0, len = layers.length, zIndex; i < len; i++) {

  \t\t\tzIndex = layers[i].style.zIndex;

  \t\t\tif (layers[i] !== this._container && zIndex) {
  \t\t\t\tedgeZIndex = compare(edgeZIndex, +zIndex);
  \t\t\t}
  \t\t}

  \t\tif (isFinite(edgeZIndex)) {
  \t\t\tthis.options.zIndex = edgeZIndex + compare(-1, 1);
  \t\t\tthis._updateZIndex();
  \t\t}
  \t},

  \t_updateOpacity: function () {
  \t\tif (!this._map) { return; }

  \t\t// IE doesn't inherit filter opacity properly, so we're forced to set it on tiles
  \t\tif (Browser.ielt9) { return; }

  \t\tsetOpacity(this._container, this.options.opacity);

  \t\tvar now = +new Date(),
  \t\t    nextFrame = false,
  \t\t    willPrune = false;

  \t\tfor (var key in this._tiles) {
  \t\t\tvar tile = this._tiles[key];
  \t\t\tif (!tile.current || !tile.loaded) { continue; }

  \t\t\tvar fade = Math.min(1, (now - tile.loaded) / 200);

  \t\t\tsetOpacity(tile.el, fade);
  \t\t\tif (fade < 1) {
  \t\t\t\tnextFrame = true;
  \t\t\t} else {
  \t\t\t\tif (tile.active) {
  \t\t\t\t\twillPrune = true;
  \t\t\t\t} else {
  \t\t\t\t\tthis._onOpaqueTile(tile);
  \t\t\t\t}
  \t\t\t\ttile.active = true;
  \t\t\t}
  \t\t}

  \t\tif (willPrune && !this._noPrune) { this._pruneTiles(); }

  \t\tif (nextFrame) {
  \t\t\tcancelAnimFrame(this._fadeFrame);
  \t\t\tthis._fadeFrame = requestAnimFrame(this._updateOpacity, this);
  \t\t}
  \t},

  \t_onOpaqueTile: falseFn,

  \t_initContainer: function () {
  \t\tif (this._container) { return; }

  \t\tthis._container = create\$1('div', 'leaflet-layer ' + (this.options.className || ''));
  \t\tthis._updateZIndex();

  \t\tif (this.options.opacity < 1) {
  \t\t\tthis._updateOpacity();
  \t\t}

  \t\tthis.getPane().appendChild(this._container);
  \t},

  \t_updateLevels: function () {

  \t\tvar zoom = this._tileZoom,
  \t\t    maxZoom = this.options.maxZoom;

  \t\tif (zoom === undefined) { return undefined; }

  \t\tfor (var z in this._levels) {
  \t\t\tz = Number(z);
  \t\t\tif (this._levels[z].el.children.length || z === zoom) {
  \t\t\t\tthis._levels[z].el.style.zIndex = maxZoom - Math.abs(zoom - z);
  \t\t\t\tthis._onUpdateLevel(z);
  \t\t\t} else {
  \t\t\t\tremove(this._levels[z].el);
  \t\t\t\tthis._removeTilesAtZoom(z);
  \t\t\t\tthis._onRemoveLevel(z);
  \t\t\t\tdelete this._levels[z];
  \t\t\t}
  \t\t}

  \t\tvar level = this._levels[zoom],
  \t\t    map = this._map;

  \t\tif (!level) {
  \t\t\tlevel = this._levels[zoom] = {};

  \t\t\tlevel.el = create\$1('div', 'leaflet-tile-container leaflet-zoom-animated', this._container);
  \t\t\tlevel.el.style.zIndex = maxZoom;

  \t\t\tlevel.origin = map.project(map.unproject(map.getPixelOrigin()), zoom).round();
  \t\t\tlevel.zoom = zoom;

  \t\t\tthis._setZoomTransform(level, map.getCenter(), map.getZoom());

  \t\t\t// force the browser to consider the newly added element for transition
  \t\t\tfalseFn(level.el.offsetWidth);

  \t\t\tthis._onCreateLevel(level);
  \t\t}

  \t\tthis._level = level;

  \t\treturn level;
  \t},

  \t_onUpdateLevel: falseFn,

  \t_onRemoveLevel: falseFn,

  \t_onCreateLevel: falseFn,

  \t_pruneTiles: function () {
  \t\tif (!this._map) {
  \t\t\treturn;
  \t\t}

  \t\tvar key, tile;

  \t\tvar zoom = this._map.getZoom();
  \t\tif (zoom > this.options.maxZoom ||
  \t\t\tzoom < this.options.minZoom) {
  \t\t\tthis._removeAllTiles();
  \t\t\treturn;
  \t\t}

  \t\tfor (key in this._tiles) {
  \t\t\ttile = this._tiles[key];
  \t\t\ttile.retain = tile.current;
  \t\t}

  \t\tfor (key in this._tiles) {
  \t\t\ttile = this._tiles[key];
  \t\t\tif (tile.current && !tile.active) {
  \t\t\t\tvar coords = tile.coords;
  \t\t\t\tif (!this._retainParent(coords.x, coords.y, coords.z, coords.z - 5)) {
  \t\t\t\t\tthis._retainChildren(coords.x, coords.y, coords.z, coords.z + 2);
  \t\t\t\t}
  \t\t\t}
  \t\t}

  \t\tfor (key in this._tiles) {
  \t\t\tif (!this._tiles[key].retain) {
  \t\t\t\tthis._removeTile(key);
  \t\t\t}
  \t\t}
  \t},

  \t_removeTilesAtZoom: function (zoom) {
  \t\tfor (var key in this._tiles) {
  \t\t\tif (this._tiles[key].coords.z !== zoom) {
  \t\t\t\tcontinue;
  \t\t\t}
  \t\t\tthis._removeTile(key);
  \t\t}
  \t},

  \t_removeAllTiles: function () {
  \t\tfor (var key in this._tiles) {
  \t\t\tthis._removeTile(key);
  \t\t}
  \t},

  \t_invalidateAll: function () {
  \t\tfor (var z in this._levels) {
  \t\t\tremove(this._levels[z].el);
  \t\t\tthis._onRemoveLevel(Number(z));
  \t\t\tdelete this._levels[z];
  \t\t}
  \t\tthis._removeAllTiles();

  \t\tthis._tileZoom = undefined;
  \t},

  \t_retainParent: function (x, y, z, minZoom) {
  \t\tvar x2 = Math.floor(x / 2),
  \t\t    y2 = Math.floor(y / 2),
  \t\t    z2 = z - 1,
  \t\t    coords2 = new Point(+x2, +y2);
  \t\tcoords2.z = +z2;

  \t\tvar key = this._tileCoordsToKey(coords2),
  \t\t    tile = this._tiles[key];

  \t\tif (tile && tile.active) {
  \t\t\ttile.retain = true;
  \t\t\treturn true;

  \t\t} else if (tile && tile.loaded) {
  \t\t\ttile.retain = true;
  \t\t}

  \t\tif (z2 > minZoom) {
  \t\t\treturn this._retainParent(x2, y2, z2, minZoom);
  \t\t}

  \t\treturn false;
  \t},

  \t_retainChildren: function (x, y, z, maxZoom) {

  \t\tfor (var i = 2 * x; i < 2 * x + 2; i++) {
  \t\t\tfor (var j = 2 * y; j < 2 * y + 2; j++) {

  \t\t\t\tvar coords = new Point(i, j);
  \t\t\t\tcoords.z = z + 1;

  \t\t\t\tvar key = this._tileCoordsToKey(coords),
  \t\t\t\t    tile = this._tiles[key];

  \t\t\t\tif (tile && tile.active) {
  \t\t\t\t\ttile.retain = true;
  \t\t\t\t\tcontinue;

  \t\t\t\t} else if (tile && tile.loaded) {
  \t\t\t\t\ttile.retain = true;
  \t\t\t\t}

  \t\t\t\tif (z + 1 < maxZoom) {
  \t\t\t\t\tthis._retainChildren(i, j, z + 1, maxZoom);
  \t\t\t\t}
  \t\t\t}
  \t\t}
  \t},

  \t_resetView: function (e) {
  \t\tvar animating = e && (e.pinch || e.flyTo);
  \t\tthis._setView(this._map.getCenter(), this._map.getZoom(), animating, animating);
  \t},

  \t_animateZoom: function (e) {
  \t\tthis._setView(e.center, e.zoom, true, e.noUpdate);
  \t},

  \t_clampZoom: function (zoom) {
  \t\tvar options = this.options;

  \t\tif (undefined !== options.minNativeZoom && zoom < options.minNativeZoom) {
  \t\t\treturn options.minNativeZoom;
  \t\t}

  \t\tif (undefined !== options.maxNativeZoom && options.maxNativeZoom < zoom) {
  \t\t\treturn options.maxNativeZoom;
  \t\t}

  \t\treturn zoom;
  \t},

  \t_setView: function (center, zoom, noPrune, noUpdate) {
  \t\tvar tileZoom = Math.round(zoom);
  \t\tif ((this.options.maxZoom !== undefined && tileZoom > this.options.maxZoom) ||
  \t\t    (this.options.minZoom !== undefined && tileZoom < this.options.minZoom)) {
  \t\t\ttileZoom = undefined;
  \t\t} else {
  \t\t\ttileZoom = this._clampZoom(tileZoom);
  \t\t}

  \t\tvar tileZoomChanged = this.options.updateWhenZooming && (tileZoom !== this._tileZoom);

  \t\tif (!noUpdate || tileZoomChanged) {

  \t\t\tthis._tileZoom = tileZoom;

  \t\t\tif (this._abortLoading) {
  \t\t\t\tthis._abortLoading();
  \t\t\t}

  \t\t\tthis._updateLevels();
  \t\t\tthis._resetGrid();

  \t\t\tif (tileZoom !== undefined) {
  \t\t\t\tthis._update(center);
  \t\t\t}

  \t\t\tif (!noPrune) {
  \t\t\t\tthis._pruneTiles();
  \t\t\t}

  \t\t\t// Flag to prevent _updateOpacity from pruning tiles during
  \t\t\t// a zoom anim or a pinch gesture
  \t\t\tthis._noPrune = !!noPrune;
  \t\t}

  \t\tthis._setZoomTransforms(center, zoom);
  \t},

  \t_setZoomTransforms: function (center, zoom) {
  \t\tfor (var i in this._levels) {
  \t\t\tthis._setZoomTransform(this._levels[i], center, zoom);
  \t\t}
  \t},

  \t_setZoomTransform: function (level, center, zoom) {
  \t\tvar scale = this._map.getZoomScale(zoom, level.zoom),
  \t\t    translate = level.origin.multiplyBy(scale)
  \t\t        .subtract(this._map._getNewPixelOrigin(center, zoom)).round();

  \t\tif (Browser.any3d) {
  \t\t\tsetTransform(level.el, translate, scale);
  \t\t} else {
  \t\t\tsetPosition(level.el, translate);
  \t\t}
  \t},

  \t_resetGrid: function () {
  \t\tvar map = this._map,
  \t\t    crs = map.options.crs,
  \t\t    tileSize = this._tileSize = this.getTileSize(),
  \t\t    tileZoom = this._tileZoom;

  \t\tvar bounds = this._map.getPixelWorldBounds(this._tileZoom);
  \t\tif (bounds) {
  \t\t\tthis._globalTileRange = this._pxBoundsToTileRange(bounds);
  \t\t}

  \t\tthis._wrapX = crs.wrapLng && !this.options.noWrap && [
  \t\t\tMath.floor(map.project([0, crs.wrapLng[0]], tileZoom).x / tileSize.x),
  \t\t\tMath.ceil(map.project([0, crs.wrapLng[1]], tileZoom).x / tileSize.y)
  \t\t];
  \t\tthis._wrapY = crs.wrapLat && !this.options.noWrap && [
  \t\t\tMath.floor(map.project([crs.wrapLat[0], 0], tileZoom).y / tileSize.x),
  \t\t\tMath.ceil(map.project([crs.wrapLat[1], 0], tileZoom).y / tileSize.y)
  \t\t];
  \t},

  \t_onMoveEnd: function () {
  \t\tif (!this._map || this._map._animatingZoom) { return; }

  \t\tthis._update();
  \t},

  \t_getTiledPixelBounds: function (center) {
  \t\tvar map = this._map,
  \t\t    mapZoom = map._animatingZoom ? Math.max(map._animateToZoom, map.getZoom()) : map.getZoom(),
  \t\t    scale = map.getZoomScale(mapZoom, this._tileZoom),
  \t\t    pixelCenter = map.project(center, this._tileZoom).floor(),
  \t\t    halfSize = map.getSize().divideBy(scale * 2);

  \t\treturn new Bounds(pixelCenter.subtract(halfSize), pixelCenter.add(halfSize));
  \t},

  \t// Private method to load tiles in the grid's active zoom level according to map bounds
  \t_update: function (center) {
  \t\tvar map = this._map;
  \t\tif (!map) { return; }
  \t\tvar zoom = this._clampZoom(map.getZoom());

  \t\tif (center === undefined) { center = map.getCenter(); }
  \t\tif (this._tileZoom === undefined) { return; }\t// if out of minzoom/maxzoom

  \t\tvar pixelBounds = this._getTiledPixelBounds(center),
  \t\t    tileRange = this._pxBoundsToTileRange(pixelBounds),
  \t\t    tileCenter = tileRange.getCenter(),
  \t\t    queue = [],
  \t\t    margin = this.options.keepBuffer,
  \t\t    noPruneRange = new Bounds(tileRange.getBottomLeft().subtract([margin, -margin]),
  \t\t                              tileRange.getTopRight().add([margin, -margin]));

  \t\t// Sanity check: panic if the tile range contains Infinity somewhere.
  \t\tif (!(isFinite(tileRange.min.x) &&
  \t\t      isFinite(tileRange.min.y) &&
  \t\t      isFinite(tileRange.max.x) &&
  \t\t      isFinite(tileRange.max.y))) { throw new Error('Attempted to load an infinite number of tiles'); }

  \t\tfor (var key in this._tiles) {
  \t\t\tvar c = this._tiles[key].coords;
  \t\t\tif (c.z !== this._tileZoom || !noPruneRange.contains(new Point(c.x, c.y))) {
  \t\t\t\tthis._tiles[key].current = false;
  \t\t\t}
  \t\t}

  \t\t// _update just loads more tiles. If the tile zoom level differs too much
  \t\t// from the map's, let _setView reset levels and prune old tiles.
  \t\tif (Math.abs(zoom - this._tileZoom) > 1) { this._setView(center, zoom); return; }

  \t\t// create a queue of coordinates to load tiles from
  \t\tfor (var j = tileRange.min.y; j <= tileRange.max.y; j++) {
  \t\t\tfor (var i = tileRange.min.x; i <= tileRange.max.x; i++) {
  \t\t\t\tvar coords = new Point(i, j);
  \t\t\t\tcoords.z = this._tileZoom;

  \t\t\t\tif (!this._isValidTile(coords)) { continue; }

  \t\t\t\tvar tile = this._tiles[this._tileCoordsToKey(coords)];
  \t\t\t\tif (tile) {
  \t\t\t\t\ttile.current = true;
  \t\t\t\t} else {
  \t\t\t\t\tqueue.push(coords);
  \t\t\t\t}
  \t\t\t}
  \t\t}

  \t\t// sort tile queue to load tiles in order of their distance to center
  \t\tqueue.sort(function (a, b) {
  \t\t\treturn a.distanceTo(tileCenter) - b.distanceTo(tileCenter);
  \t\t});

  \t\tif (queue.length !== 0) {
  \t\t\t// if it's the first batch of tiles to load
  \t\t\tif (!this._loading) {
  \t\t\t\tthis._loading = true;
  \t\t\t\t// @event loading: Event
  \t\t\t\t// Fired when the grid layer starts loading tiles.
  \t\t\t\tthis.fire('loading');
  \t\t\t}

  \t\t\t// create DOM fragment to append tiles in one batch
  \t\t\tvar fragment = document.createDocumentFragment();

  \t\t\tfor (i = 0; i < queue.length; i++) {
  \t\t\t\tthis._addTile(queue[i], fragment);
  \t\t\t}

  \t\t\tthis._level.el.appendChild(fragment);
  \t\t}
  \t},

  \t_isValidTile: function (coords) {
  \t\tvar crs = this._map.options.crs;

  \t\tif (!crs.infinite) {
  \t\t\t// don't load tile if it's out of bounds and not wrapped
  \t\t\tvar bounds = this._globalTileRange;
  \t\t\tif ((!crs.wrapLng && (coords.x < bounds.min.x || coords.x > bounds.max.x)) ||
  \t\t\t    (!crs.wrapLat && (coords.y < bounds.min.y || coords.y > bounds.max.y))) { return false; }
  \t\t}

  \t\tif (!this.options.bounds) { return true; }

  \t\t// don't load tile if it doesn't intersect the bounds in options
  \t\tvar tileBounds = this._tileCoordsToBounds(coords);
  \t\treturn toLatLngBounds(this.options.bounds).overlaps(tileBounds);
  \t},

  \t_keyToBounds: function (key) {
  \t\treturn this._tileCoordsToBounds(this._keyToTileCoords(key));
  \t},

  \t_tileCoordsToNwSe: function (coords) {
  \t\tvar map = this._map,
  \t\t    tileSize = this.getTileSize(),
  \t\t    nwPoint = coords.scaleBy(tileSize),
  \t\t    sePoint = nwPoint.add(tileSize),
  \t\t    nw = map.unproject(nwPoint, coords.z),
  \t\t    se = map.unproject(sePoint, coords.z);
  \t\treturn [nw, se];
  \t},

  \t// converts tile coordinates to its geographical bounds
  \t_tileCoordsToBounds: function (coords) {
  \t\tvar bp = this._tileCoordsToNwSe(coords),
  \t\t    bounds = new LatLngBounds(bp[0], bp[1]);

  \t\tif (!this.options.noWrap) {
  \t\t\tbounds = this._map.wrapLatLngBounds(bounds);
  \t\t}
  \t\treturn bounds;
  \t},
  \t// converts tile coordinates to key for the tile cache
  \t_tileCoordsToKey: function (coords) {
  \t\treturn coords.x + ':' + coords.y + ':' + coords.z;
  \t},

  \t// converts tile cache key to coordinates
  \t_keyToTileCoords: function (key) {
  \t\tvar k = key.split(':'),
  \t\t    coords = new Point(+k[0], +k[1]);
  \t\tcoords.z = +k[2];
  \t\treturn coords;
  \t},

  \t_removeTile: function (key) {
  \t\tvar tile = this._tiles[key];
  \t\tif (!tile) { return; }

  \t\tremove(tile.el);

  \t\tdelete this._tiles[key];

  \t\t// @event tileunload: TileEvent
  \t\t// Fired when a tile is removed (e.g. when a tile goes off the screen).
  \t\tthis.fire('tileunload', {
  \t\t\ttile: tile.el,
  \t\t\tcoords: this._keyToTileCoords(key)
  \t\t});
  \t},

  \t_initTile: function (tile) {
  \t\taddClass(tile, 'leaflet-tile');

  \t\tvar tileSize = this.getTileSize();
  \t\ttile.style.width = tileSize.x + 'px';
  \t\ttile.style.height = tileSize.y + 'px';

  \t\ttile.onselectstart = falseFn;
  \t\ttile.onmousemove = falseFn;

  \t\t// update opacity on tiles in IE7-8 because of filter inheritance problems
  \t\tif (Browser.ielt9 && this.options.opacity < 1) {
  \t\t\tsetOpacity(tile, this.options.opacity);
  \t\t}
  \t},

  \t_addTile: function (coords, container) {
  \t\tvar tilePos = this._getTilePos(coords),
  \t\t    key = this._tileCoordsToKey(coords);

  \t\tvar tile = this.createTile(this._wrapCoords(coords), bind(this._tileReady, this, coords));

  \t\tthis._initTile(tile);

  \t\t// if createTile is defined with a second argument (\"done\" callback),
  \t\t// we know that tile is async and will be ready later; otherwise
  \t\tif (this.createTile.length < 2) {
  \t\t\t// mark tile as ready, but delay one frame for opacity animation to happen
  \t\t\trequestAnimFrame(bind(this._tileReady, this, coords, null, tile));
  \t\t}

  \t\tsetPosition(tile, tilePos);

  \t\t// save tile in cache
  \t\tthis._tiles[key] = {
  \t\t\tel: tile,
  \t\t\tcoords: coords,
  \t\t\tcurrent: true
  \t\t};

  \t\tcontainer.appendChild(tile);
  \t\t// @event tileloadstart: TileEvent
  \t\t// Fired when a tile is requested and starts loading.
  \t\tthis.fire('tileloadstart', {
  \t\t\ttile: tile,
  \t\t\tcoords: coords
  \t\t});
  \t},

  \t_tileReady: function (coords, err, tile) {
  \t\tif (err) {
  \t\t\t// @event tileerror: TileErrorEvent
  \t\t\t// Fired when there is an error loading a tile.
  \t\t\tthis.fire('tileerror', {
  \t\t\t\terror: err,
  \t\t\t\ttile: tile,
  \t\t\t\tcoords: coords
  \t\t\t});
  \t\t}

  \t\tvar key = this._tileCoordsToKey(coords);

  \t\ttile = this._tiles[key];
  \t\tif (!tile) { return; }

  \t\ttile.loaded = +new Date();
  \t\tif (this._map._fadeAnimated) {
  \t\t\tsetOpacity(tile.el, 0);
  \t\t\tcancelAnimFrame(this._fadeFrame);
  \t\t\tthis._fadeFrame = requestAnimFrame(this._updateOpacity, this);
  \t\t} else {
  \t\t\ttile.active = true;
  \t\t\tthis._pruneTiles();
  \t\t}

  \t\tif (!err) {
  \t\t\taddClass(tile.el, 'leaflet-tile-loaded');

  \t\t\t// @event tileload: TileEvent
  \t\t\t// Fired when a tile loads.
  \t\t\tthis.fire('tileload', {
  \t\t\t\ttile: tile.el,
  \t\t\t\tcoords: coords
  \t\t\t});
  \t\t}

  \t\tif (this._noTilesToLoad()) {
  \t\t\tthis._loading = false;
  \t\t\t// @event load: Event
  \t\t\t// Fired when the grid layer loaded all visible tiles.
  \t\t\tthis.fire('load');

  \t\t\tif (Browser.ielt9 || !this._map._fadeAnimated) {
  \t\t\t\trequestAnimFrame(this._pruneTiles, this);
  \t\t\t} else {
  \t\t\t\t// Wait a bit more than 0.2 secs (the duration of the tile fade-in)
  \t\t\t\t// to trigger a pruning.
  \t\t\t\tsetTimeout(bind(this._pruneTiles, this), 250);
  \t\t\t}
  \t\t}
  \t},

  \t_getTilePos: function (coords) {
  \t\treturn coords.scaleBy(this.getTileSize()).subtract(this._level.origin);
  \t},

  \t_wrapCoords: function (coords) {
  \t\tvar newCoords = new Point(
  \t\t\tthis._wrapX ? wrapNum(coords.x, this._wrapX) : coords.x,
  \t\t\tthis._wrapY ? wrapNum(coords.y, this._wrapY) : coords.y);
  \t\tnewCoords.z = coords.z;
  \t\treturn newCoords;
  \t},

  \t_pxBoundsToTileRange: function (bounds) {
  \t\tvar tileSize = this.getTileSize();
  \t\treturn new Bounds(
  \t\t\tbounds.min.unscaleBy(tileSize).floor(),
  \t\t\tbounds.max.unscaleBy(tileSize).ceil().subtract([1, 1]));
  \t},

  \t_noTilesToLoad: function () {
  \t\tfor (var key in this._tiles) {
  \t\t\tif (!this._tiles[key].loaded) { return false; }
  \t\t}
  \t\treturn true;
  \t}
  });

  // @factory L.gridLayer(options?: GridLayer options)
  // Creates a new instance of GridLayer with the supplied options.
  function gridLayer(options) {
  \treturn new GridLayer(options);
  }

  /*
   * @class TileLayer
   * @inherits GridLayer
   * @aka L.TileLayer
   * Used to load and display tile layers on the map. Note that most tile servers require attribution, which you can set under `Layer`. Extends `GridLayer`.
   *
   * @example
   *
   * ```js
   * L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar', attribution: '&copy; <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors'}).addTo(map);
   * ```
   *
   * @section URL template
   * @example
   *
   * A string of the following form:
   *
   * ```
   * 'https://{s}.somedomain.com/blabla/{z}/{x}/{y}{r}.png'
   * ```
   *
   * `{s}` means one of the available subdomains (used sequentially to help with browser parallel requests per domain limitation; subdomain values are specified in options; `a`, `b` or `c` by default, can be omitted), `{z}` — zoom level, `{x}` and `{y}` — tile coordinates. `{r}` can be used to add \"&commat;2x\" to the URL to load retina tiles.
   *
   * You can use custom keys in the template, which will be [evaluated](#util-template) from TileLayer options, like this:
   *
   * ```
   * L.tileLayer('https://{s}.somedomain.com/{foo}/{z}/{x}/{y}.png', {foo: 'bar'});
   * ```
   */


  var TileLayer = GridLayer.extend({

  \t// @section
  \t// @aka TileLayer options
  \toptions: {
  \t\t// @option minZoom: Number = 0
  \t\t// The minimum zoom level down to which this layer will be displayed (inclusive).
  \t\tminZoom: 0,

  \t\t// @option maxZoom: Number = 18
  \t\t// The maximum zoom level up to which this layer will be displayed (inclusive).
  \t\tmaxZoom: 18,

  \t\t// @option subdomains: String|String[] = 'abc'
  \t\t// Subdomains of the tile service. Can be passed in the form of one string (where each letter is a subdomain name) or an array of strings.
  \t\tsubdomains: 'abc',

  \t\t// @option errorTileUrl: String = ''
  \t\t// URL to the tile image to show in place of the tile that failed to load.
  \t\terrorTileUrl: '',

  \t\t// @option zoomOffset: Number = 0
  \t\t// The zoom number used in tile URLs will be offset with this value.
  \t\tzoomOffset: 0,

  \t\t// @option tms: Boolean = false
  \t\t// If `true`, inverses Y axis numbering for tiles (turn this on for [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) services).
  \t\ttms: false,

  \t\t// @option zoomReverse: Boolean = false
  \t\t// If set to true, the zoom number used in tile URLs will be reversed (`maxZoom - zoom` instead of `zoom`)
  \t\tzoomReverse: false,

  \t\t// @option detectRetina: Boolean = false
  \t\t// If `true` and user is on a retina display, it will request four tiles of half the specified size and a bigger zoom level in place of one to utilize the high resolution.
  \t\tdetectRetina: false,

  \t\t// @option crossOrigin: Boolean|String = false
  \t\t// Whether the crossOrigin attribute will be added to the tiles.
  \t\t// If a String is provided, all tiles will have their crossOrigin attribute set to the String provided. This is needed if you want to access tile pixel data.
  \t\t// Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values.
  \t\tcrossOrigin: false,

  \t\t// @option referrerPolicy: Boolean|String = false
  \t\t// Whether the referrerPolicy attribute will be added to the tiles.
  \t\t// If a String is provided, all tiles will have their referrerPolicy attribute set to the String provided.
  \t\t// This may be needed if your map's rendering context has a strict default but your tile provider expects a valid referrer
  \t\t// (e.g. to validate an API token).
  \t\t// Refer to [HTMLImageElement.referrerPolicy](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/referrerPolicy) for valid String values.
  \t\treferrerPolicy: false
  \t},

  \tinitialize: function (url, options) {

  \t\tthis._url = url;

  \t\toptions = setOptions(this, options);

  \t\t// detecting retina displays, adjusting tileSize and zoom levels
  \t\tif (options.detectRetina && Browser.retina && options.maxZoom > 0) {

  \t\t\toptions.tileSize = Math.floor(options.tileSize / 2);

  \t\t\tif (!options.zoomReverse) {
  \t\t\t\toptions.zoomOffset++;
  \t\t\t\toptions.maxZoom = Math.max(options.minZoom, options.maxZoom - 1);
  \t\t\t} else {
  \t\t\t\toptions.zoomOffset--;
  \t\t\t\toptions.minZoom = Math.min(options.maxZoom, options.minZoom + 1);
  \t\t\t}

  \t\t\toptions.minZoom = Math.max(0, options.minZoom);
  \t\t} else if (!options.zoomReverse) {
  \t\t\t// make sure maxZoom is gte minZoom
  \t\t\toptions.maxZoom = Math.max(options.minZoom, options.maxZoom);
  \t\t} else {
  \t\t\t// make sure minZoom is lte maxZoom
  \t\t\toptions.minZoom = Math.min(options.maxZoom, options.minZoom);
  \t\t}

  \t\tif (typeof options.subdomains === 'string') {
  \t\t\toptions.subdomains = options.subdomains.split('');
  \t\t}

  \t\tthis.on('tileunload', this._onTileRemove);
  \t},

  \t// @method setUrl(url: String, noRedraw?: Boolean): this
  \t// Updates the layer's URL template and redraws it (unless `noRedraw` is set to `true`).
  \t// If the URL does not change, the layer will not be redrawn unless
  \t// the noRedraw parameter is set to false.
  \tsetUrl: function (url, noRedraw) {
  \t\tif (this._url === url && noRedraw === undefined) {
  \t\t\tnoRedraw = true;
  \t\t}

  \t\tthis._url = url;

  \t\tif (!noRedraw) {
  \t\t\tthis.redraw();
  \t\t}
  \t\treturn this;
  \t},

  \t// @method createTile(coords: Object, done?: Function): HTMLElement
  \t// Called only internally, overrides GridLayer's [`createTile()`](#gridlayer-createtile)
  \t// to return an `<img>` HTML element with the appropriate image URL given `coords`. The `done`
  \t// callback is called when the tile has been loaded.
  \tcreateTile: function (coords, done) {
  \t\tvar tile = document.createElement('img');

  \t\ton(tile, 'load', bind(this._tileOnLoad, this, done, tile));
  \t\ton(tile, 'error', bind(this._tileOnError, this, done, tile));

  \t\tif (this.options.crossOrigin || this.options.crossOrigin === '') {
  \t\t\ttile.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin;
  \t\t}

  \t\t// for this new option we follow the documented behavior
  \t\t// more closely by only setting the property when string
  \t\tif (typeof this.options.referrerPolicy === 'string') {
  \t\t\ttile.referrerPolicy = this.options.referrerPolicy;
  \t\t}

  \t\t// The alt attribute is set to the empty string,
  \t\t// allowing screen readers to ignore the decorative image tiles.
  \t\t// https://www.w3.org/WAI/tutorials/images/decorative/
  \t\t// https://www.w3.org/TR/html-aria/#el-img-empty-alt
  \t\ttile.alt = '';

  \t\ttile.src = this.getTileUrl(coords);

  \t\treturn tile;
  \t},

  \t// @section Extension methods
  \t// @uninheritable
  \t// Layers extending `TileLayer` might reimplement the following method.
  \t// @method getTileUrl(coords: Object): String
  \t// Called only internally, returns the URL for a tile given its coordinates.
  \t// Classes extending `TileLayer` can override this function to provide custom tile URL naming schemes.
  \tgetTileUrl: function (coords) {
  \t\tvar data = {
  \t\t\tr: Browser.retina ? '@2x' : '',
  \t\t\ts: this._getSubdomain(coords),
  \t\t\tx: coords.x,
  \t\t\ty: coords.y,
  \t\t\tz: this._getZoomForUrl()
  \t\t};
  \t\tif (this._map && !this._map.options.crs.infinite) {
  \t\t\tvar invertedY = this._globalTileRange.max.y - coords.y;
  \t\t\tif (this.options.tms) {
  \t\t\t\tdata['y'] = invertedY;
  \t\t\t}
  \t\t\tdata['-y'] = invertedY;
  \t\t}

  \t\treturn template(this._url, extend(data, this.options));
  \t},

  \t_tileOnLoad: function (done, tile) {
  \t\t// For https://github.com/Leaflet/Leaflet/issues/3332
  \t\tif (Browser.ielt9) {
  \t\t\tsetTimeout(bind(done, this, null, tile), 0);
  \t\t} else {
  \t\t\tdone(null, tile);
  \t\t}
  \t},

  \t_tileOnError: function (done, tile, e) {
  \t\tvar errorUrl = this.options.errorTileUrl;
  \t\tif (errorUrl && tile.getAttribute('src') !== errorUrl) {
  \t\t\ttile.src = errorUrl;
  \t\t}
  \t\tdone(e, tile);
  \t},

  \t_onTileRemove: function (e) {
  \t\te.tile.onload = null;
  \t},

  \t_getZoomForUrl: function () {
  \t\tvar zoom = this._tileZoom,
  \t\tmaxZoom = this.options.maxZoom,
  \t\tzoomReverse = this.options.zoomReverse,
  \t\tzoomOffset = this.options.zoomOffset;

  \t\tif (zoomReverse) {
  \t\t\tzoom = maxZoom - zoom;
  \t\t}

  \t\treturn zoom + zoomOffset;
  \t},

  \t_getSubdomain: function (tilePoint) {
  \t\tvar index = Math.abs(tilePoint.x + tilePoint.y) % this.options.subdomains.length;
  \t\treturn this.options.subdomains[index];
  \t},

  \t// stops loading all tiles in the background layer
  \t_abortLoading: function () {
  \t\tvar i, tile;
  \t\tfor (i in this._tiles) {
  \t\t\tif (this._tiles[i].coords.z !== this._tileZoom) {
  \t\t\t\ttile = this._tiles[i].el;

  \t\t\t\ttile.onload = falseFn;
  \t\t\t\ttile.onerror = falseFn;

  \t\t\t\tif (!tile.complete) {
  \t\t\t\t\ttile.src = emptyImageUrl;
  \t\t\t\t\tvar coords = this._tiles[i].coords;
  \t\t\t\t\tremove(tile);
  \t\t\t\t\tdelete this._tiles[i];
  \t\t\t\t\t// @event tileabort: TileEvent
  \t\t\t\t\t// Fired when a tile was loading but is now not wanted.
  \t\t\t\t\tthis.fire('tileabort', {
  \t\t\t\t\t\ttile: tile,
  \t\t\t\t\t\tcoords: coords
  \t\t\t\t\t});
  \t\t\t\t}
  \t\t\t}
  \t\t}
  \t},

  \t_removeTile: function (key) {
  \t\tvar tile = this._tiles[key];
  \t\tif (!tile) { return; }

  \t\t// Cancels any pending http requests associated with the tile
  \t\ttile.el.setAttribute('src', emptyImageUrl);

  \t\treturn GridLayer.prototype._removeTile.call(this, key);
  \t},

  \t_tileReady: function (coords, err, tile) {
  \t\tif (!this._map || (tile && tile.getAttribute('src') === emptyImageUrl)) {
  \t\t\treturn;
  \t\t}

  \t\treturn GridLayer.prototype._tileReady.call(this, coords, err, tile);
  \t}
  });


  // @factory L.tilelayer(urlTemplate: String, options?: TileLayer options)
  // Instantiates a tile layer object given a `URL template` and optionally an options object.

  function tileLayer(url, options) {
  \treturn new TileLayer(url, options);
  }

  /*
   * @class TileLayer.WMS
   * @inherits TileLayer
   * @aka L.TileLayer.WMS
   * Used to display [WMS](https://en.wikipedia.org/wiki/Web_Map_Service) services as tile layers on the map. Extends `TileLayer`.
   *
   * @example
   *
   * ```js
   * var nexrad = L.tileLayer.wms(\"http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi\", {
   * \tlayers: 'nexrad-n0r-900913',
   * \tformat: 'image/png',
   * \ttransparent: true,
   * \tattribution: \"Weather data © 2012 IEM Nexrad\"
   * });
   * ```
   */

  var TileLayerWMS = TileLayer.extend({

  \t// @section
  \t// @aka TileLayer.WMS options
  \t// If any custom options not documented here are used, they will be sent to the
  \t// WMS server as extra parameters in each request URL. This can be useful for
  \t// [non-standard vendor WMS parameters](https://docs.geoserver.org/stable/en/user/services/wms/vendor.html).
  \tdefaultWmsParams: {
  \t\tservice: 'WMS',
  \t\trequest: 'GetMap',

  \t\t// @option layers: String = ''
  \t\t// **(required)** Comma-separated list of WMS layers to show.
  \t\tlayers: '',

  \t\t// @option styles: String = ''
  \t\t// Comma-separated list of WMS styles.
  \t\tstyles: '',

  \t\t// @option format: String = 'image/jpeg'
  \t\t// WMS image format (use `'image/png'` for layers with transparency).
  \t\tformat: 'image/jpeg',

  \t\t// @option transparent: Boolean = false
  \t\t// If `true`, the WMS service will return images with transparency.
  \t\ttransparent: false,

  \t\t// @option version: String = '1.1.1'
  \t\t// Version of the WMS service to use
  \t\tversion: '1.1.1'
  \t},

  \toptions: {
  \t\t// @option crs: CRS = null
  \t\t// Coordinate Reference System to use for the WMS requests, defaults to
  \t\t// map CRS. Don't change this if you're not sure what it means.
  \t\tcrs: null,

  \t\t// @option uppercase: Boolean = false
  \t\t// If `true`, WMS request parameter keys will be uppercase.
  \t\tuppercase: false
  \t},

  \tinitialize: function (url, options) {

  \t\tthis._url = url;

  \t\tvar wmsParams = extend({}, this.defaultWmsParams);

  \t\t// all keys that are not TileLayer options go to WMS params
  \t\tfor (var i in options) {
  \t\t\tif (!(i in this.options)) {
  \t\t\t\twmsParams[i] = options[i];
  \t\t\t}
  \t\t}

  \t\toptions = setOptions(this, options);

  \t\tvar realRetina = options.detectRetina && Browser.retina ? 2 : 1;
  \t\tvar tileSize = this.getTileSize();
  \t\twmsParams.width = tileSize.x * realRetina;
  \t\twmsParams.height = tileSize.y * realRetina;

  \t\tthis.wmsParams = wmsParams;
  \t},

  \tonAdd: function (map) {

  \t\tthis._crs = this.options.crs || map.options.crs;
  \t\tthis._wmsVersion = parseFloat(this.wmsParams.version);

  \t\tvar projectionKey = this._wmsVersion >= 1.3 ? 'crs' : 'srs';
  \t\tthis.wmsParams[projectionKey] = this._crs.code;

  \t\tTileLayer.prototype.onAdd.call(this, map);
  \t},

  \tgetTileUrl: function (coords) {

  \t\tvar tileBounds = this._tileCoordsToNwSe(coords),
  \t\t    crs = this._crs,
  \t\t    bounds = toBounds(crs.project(tileBounds[0]), crs.project(tileBounds[1])),
  \t\t    min = bounds.min,
  \t\t    max = bounds.max,
  \t\t    bbox = (this._wmsVersion >= 1.3 && this._crs === EPSG4326 ?
  \t\t    [min.y, min.x, max.y, max.x] :
  \t\t    [min.x, min.y, max.x, max.y]).join(','),
  \t\t    url = TileLayer.prototype.getTileUrl.call(this, coords);
  \t\treturn url +
  \t\t\tgetParamString(this.wmsParams, url, this.options.uppercase) +
  \t\t\t(this.options.uppercase ? '&BBOX=' : '&bbox=') + bbox;
  \t},

  \t// @method setParams(params: Object, noRedraw?: Boolean): this
  \t// Merges an object with the new parameters and re-requests tiles on the current screen (unless `noRedraw` was set to true).
  \tsetParams: function (params, noRedraw) {

  \t\textend(this.wmsParams, params);

  \t\tif (!noRedraw) {
  \t\t\tthis.redraw();
  \t\t}

  \t\treturn this;
  \t}
  });


  // @factory L.tileLayer.wms(baseUrl: String, options: TileLayer.WMS options)
  // Instantiates a WMS tile layer object given a base URL of the WMS service and a WMS parameters/options object.
  function tileLayerWMS(url, options) {
  \treturn new TileLayerWMS(url, options);
  }

  TileLayer.WMS = TileLayerWMS;
  tileLayer.wms = tileLayerWMS;

  /*
   * @class Renderer
   * @inherits Layer
   * @aka L.Renderer
   *
   * Base class for vector renderer implementations (`SVG`, `Canvas`). Handles the
   * DOM container of the renderer, its bounds, and its zoom animation.
   *
   * A `Renderer` works as an implicit layer group for all `Path`s - the renderer
   * itself can be added or removed to the map. All paths use a renderer, which can
   * be implicit (the map will decide the type of renderer and use it automatically)
   * or explicit (using the [`renderer`](#path-renderer) option of the path).
   *
   * Do not use this class directly, use `SVG` and `Canvas` instead.
   *
   * @event update: Event
   * Fired when the renderer updates its bounds, center and zoom, for example when
   * its map has moved
   */

  var Renderer = Layer.extend({

  \t// @section
  \t// @aka Renderer options
  \toptions: {
  \t\t// @option padding: Number = 0.1
  \t\t// How much to extend the clip area around the map view (relative to its size)
  \t\t// e.g. 0.1 would be 10% of map view in each direction
  \t\tpadding: 0.1
  \t},

  \tinitialize: function (options) {
  \t\tsetOptions(this, options);
  \t\tstamp(this);
  \t\tthis._layers = this._layers || {};
  \t},

  \tonAdd: function () {
  \t\tif (!this._container) {
  \t\t\tthis._initContainer(); // defined by renderer implementations

  \t\t\t// always keep transform-origin as 0 0
  \t\t\taddClass(this._container, 'leaflet-zoom-animated');
  \t\t}

  \t\tthis.getPane().appendChild(this._container);
  \t\tthis._update();
  \t\tthis.on('update', this._updatePaths, this);
  \t},

  \tonRemove: function () {
  \t\tthis.off('update', this._updatePaths, this);
  \t\tthis._destroyContainer();
  \t},

  \tgetEvents: function () {
  \t\tvar events = {
  \t\t\tviewreset: this._reset,
  \t\t\tzoom: this._onZoom,
  \t\t\tmoveend: this._update,
  \t\t\tzoomend: this._onZoomEnd
  \t\t};
  \t\tif (this._zoomAnimated) {
  \t\t\tevents.zoomanim = this._onAnimZoom;
  \t\t}
  \t\treturn events;
  \t},

  \t_onAnimZoom: function (ev) {
  \t\tthis._updateTransform(ev.center, ev.zoom);
  \t},

  \t_onZoom: function () {
  \t\tthis._updateTransform(this._map.getCenter(), this._map.getZoom());
  \t},

  \t_updateTransform: function (center, zoom) {
  \t\tvar scale = this._map.getZoomScale(zoom, this._zoom),
  \t\t    viewHalf = this._map.getSize().multiplyBy(0.5 + this.options.padding),
  \t\t    currentCenterPoint = this._map.project(this._center, zoom),

  \t\t    topLeftOffset = viewHalf.multiplyBy(-scale).add(currentCenterPoint)
  \t\t\t\t  .subtract(this._map._getNewPixelOrigin(center, zoom));

  \t\tif (Browser.any3d) {
  \t\t\tsetTransform(this._container, topLeftOffset, scale);
  \t\t} else {
  \t\t\tsetPosition(this._container, topLeftOffset);
  \t\t}
  \t},

  \t_reset: function () {
  \t\tthis._update();
  \t\tthis._updateTransform(this._center, this._zoom);

  \t\tfor (var id in this._layers) {
  \t\t\tthis._layers[id]._reset();
  \t\t}
  \t},

  \t_onZoomEnd: function () {
  \t\tfor (var id in this._layers) {
  \t\t\tthis._layers[id]._project();
  \t\t}
  \t},

  \t_updatePaths: function () {
  \t\tfor (var id in this._layers) {
  \t\t\tthis._layers[id]._update();
  \t\t}
  \t},

  \t_update: function () {
  \t\t// Update pixel bounds of renderer container (for positioning/sizing/clipping later)
  \t\t// Subclasses are responsible of firing the 'update' event.
  \t\tvar p = this.options.padding,
  \t\t    size = this._map.getSize(),
  \t\t    min = this._map.containerPointToLayerPoint(size.multiplyBy(-p)).round();

  \t\tthis._bounds = new Bounds(min, min.add(size.multiplyBy(1 + p * 2)).round());

  \t\tthis._center = this._map.getCenter();
  \t\tthis._zoom = this._map.getZoom();
  \t}
  });

  /*
   * @class Canvas
   * @inherits Renderer
   * @aka L.Canvas
   *
   * Allows vector layers to be displayed with [`<canvas>`](https://developer.mozilla.org/docs/Web/API/Canvas_API).
   * Inherits `Renderer`.
   *
   * Due to [technical limitations](https://caniuse.com/canvas), Canvas is not
   * available in all web browsers, notably IE8, and overlapping geometries might
   * not display properly in some edge cases.
   *
   * @example
   *
   * Use Canvas by default for all paths in the map:
   *
   * ```js
   * var map = L.map('map', {
   * \trenderer: L.canvas()
   * });
   * ```
   *
   * Use a Canvas renderer with extra padding for specific vector geometries:
   *
   * ```js
   * var map = L.map('map');
   * var myRenderer = L.canvas({ padding: 0.5 });
   * var line = L.polyline( coordinates, { renderer: myRenderer } );
   * var circle = L.circle( center, { renderer: myRenderer } );
   * ```
   */

  var Canvas = Renderer.extend({

  \t// @section
  \t// @aka Canvas options
  \toptions: {
  \t\t// @option tolerance: Number = 0
  \t\t// How much to extend the click tolerance around a path/object on the map.
  \t\ttolerance: 0
  \t},

  \tgetEvents: function () {
  \t\tvar events = Renderer.prototype.getEvents.call(this);
  \t\tevents.viewprereset = this._onViewPreReset;
  \t\treturn events;
  \t},

  \t_onViewPreReset: function () {
  \t\t// Set a flag so that a viewprereset+moveend+viewreset only updates&redraws once
  \t\tthis._postponeUpdatePaths = true;
  \t},

  \tonAdd: function () {
  \t\tRenderer.prototype.onAdd.call(this);

  \t\t// Redraw vectors since canvas is cleared upon removal,
  \t\t// in case of removing the renderer itself from the map.
  \t\tthis._draw();
  \t},

  \t_initContainer: function () {
  \t\tvar container = this._container = document.createElement('canvas');

  \t\ton(container, 'mousemove', this._onMouseMove, this);
  \t\ton(container, 'click dblclick mousedown mouseup contextmenu', this._onClick, this);
  \t\ton(container, 'mouseout', this._handleMouseOut, this);
  \t\tcontainer['_leaflet_disable_events'] = true;

  \t\tthis._ctx = container.getContext('2d');
  \t},

  \t_destroyContainer: function () {
  \t\tcancelAnimFrame(this._redrawRequest);
  \t\tdelete this._ctx;
  \t\tremove(this._container);
  \t\toff(this._container);
  \t\tdelete this._container;
  \t},

  \t_updatePaths: function () {
  \t\tif (this._postponeUpdatePaths) { return; }

  \t\tvar layer;
  \t\tthis._redrawBounds = null;
  \t\tfor (var id in this._layers) {
  \t\t\tlayer = this._layers[id];
  \t\t\tlayer._update();
  \t\t}
  \t\tthis._redraw();
  \t},

  \t_update: function () {
  \t\tif (this._map._animatingZoom && this._bounds) { return; }

  \t\tRenderer.prototype._update.call(this);

  \t\tvar b = this._bounds,
  \t\t    container = this._container,
  \t\t    size = b.getSize(),
  \t\t    m = Browser.retina ? 2 : 1;

  \t\tsetPosition(container, b.min);

  \t\t// set canvas size (also clearing it); use double size on retina
  \t\tcontainer.width = m * size.x;
  \t\tcontainer.height = m * size.y;
  \t\tcontainer.style.width = size.x + 'px';
  \t\tcontainer.style.height = size.y + 'px';

  \t\tif (Browser.retina) {
  \t\t\tthis._ctx.scale(2, 2);
  \t\t}

  \t\t// translate so we use the same path coordinates after canvas element moves
  \t\tthis._ctx.translate(-b.min.x, -b.min.y);

  \t\t// Tell paths to redraw themselves
  \t\tthis.fire('update');
  \t},

  \t_reset: function () {
  \t\tRenderer.prototype._reset.call(this);

  \t\tif (this._postponeUpdatePaths) {
  \t\t\tthis._postponeUpdatePaths = false;
  \t\t\tthis._updatePaths();
  \t\t}
  \t},

  \t_initPath: function (layer) {
  \t\tthis._updateDashArray(layer);
  \t\tthis._layers[stamp(layer)] = layer;

  \t\tvar order = layer._order = {
  \t\t\tlayer: layer,
  \t\t\tprev: this._drawLast,
  \t\t\tnext: null
  \t\t};
  \t\tif (this._drawLast) { this._drawLast.next = order; }
  \t\tthis._drawLast = order;
  \t\tthis._drawFirst = this._drawFirst || this._drawLast;
  \t},

  \t_addPath: function (layer) {
  \t\tthis._requestRedraw(layer);
  \t},

  \t_removePath: function (layer) {
  \t\tvar order = layer._order;
  \t\tvar next = order.next;
  \t\tvar prev = order.prev;

  \t\tif (next) {
  \t\t\tnext.prev = prev;
  \t\t} else {
  \t\t\tthis._drawLast = prev;
  \t\t}
  \t\tif (prev) {
  \t\t\tprev.next = next;
  \t\t} else {
  \t\t\tthis._drawFirst = next;
  \t\t}

  \t\tdelete layer._order;

  \t\tdelete this._layers[stamp(layer)];

  \t\tthis._requestRedraw(layer);
  \t},

  \t_updatePath: function (layer) {
  \t\t// Redraw the union of the layer's old pixel
  \t\t// bounds and the new pixel bounds.
  \t\tthis._extendRedrawBounds(layer);
  \t\tlayer._project();
  \t\tlayer._update();
  \t\t// The redraw will extend the redraw bounds
  \t\t// with the new pixel bounds.
  \t\tthis._requestRedraw(layer);
  \t},

  \t_updateStyle: function (layer) {
  \t\tthis._updateDashArray(layer);
  \t\tthis._requestRedraw(layer);
  \t},

  \t_updateDashArray: function (layer) {
  \t\tif (typeof layer.options.dashArray === 'string') {
  \t\t\tvar parts = layer.options.dashArray.split(/[, ]+/),
  \t\t\t    dashArray = [],
  \t\t\t    dashValue,
  \t\t\t    i;
  \t\t\tfor (i = 0; i < parts.length; i++) {
  \t\t\t\tdashValue = Number(parts[i]);
  \t\t\t\t// Ignore dash array containing invalid lengths
  \t\t\t\tif (isNaN(dashValue)) { return; }
  \t\t\t\tdashArray.push(dashValue);
  \t\t\t}
  \t\t\tlayer.options._dashArray = dashArray;
  \t\t} else {
  \t\t\tlayer.options._dashArray = layer.options.dashArray;
  \t\t}
  \t},

  \t_requestRedraw: function (layer) {
  \t\tif (!this._map) { return; }

  \t\tthis._extendRedrawBounds(layer);
  \t\tthis._redrawRequest = this._redrawRequest || requestAnimFrame(this._redraw, this);
  \t},

  \t_extendRedrawBounds: function (layer) {
  \t\tif (layer._pxBounds) {
  \t\t\tvar padding = (layer.options.weight || 0) + 1;
  \t\t\tthis._redrawBounds = this._redrawBounds || new Bounds();
  \t\t\tthis._redrawBounds.extend(layer._pxBounds.min.subtract([padding, padding]));
  \t\t\tthis._redrawBounds.extend(layer._pxBounds.max.add([padding, padding]));
  \t\t}
  \t},

  \t_redraw: function () {
  \t\tthis._redrawRequest = null;

  \t\tif (this._redrawBounds) {
  \t\t\tthis._redrawBounds.min._floor();
  \t\t\tthis._redrawBounds.max._ceil();
  \t\t}

  \t\tthis._clear(); // clear layers in redraw bounds
  \t\tthis._draw(); // draw layers

  \t\tthis._redrawBounds = null;
  \t},

  \t_clear: function () {
  \t\tvar bounds = this._redrawBounds;
  \t\tif (bounds) {
  \t\t\tvar size = bounds.getSize();
  \t\t\tthis._ctx.clearRect(bounds.min.x, bounds.min.y, size.x, size.y);
  \t\t} else {
  \t\t\tthis._ctx.save();
  \t\t\tthis._ctx.setTransform(1, 0, 0, 1, 0, 0);
  \t\t\tthis._ctx.clearRect(0, 0, this._container.width, this._container.height);
  \t\t\tthis._ctx.restore();
  \t\t}
  \t},

  \t_draw: function () {
  \t\tvar layer, bounds = this._redrawBounds;
  \t\tthis._ctx.save();
  \t\tif (bounds) {
  \t\t\tvar size = bounds.getSize();
  \t\t\tthis._ctx.beginPath();
  \t\t\tthis._ctx.rect(bounds.min.x, bounds.min.y, size.x, size.y);
  \t\t\tthis._ctx.clip();
  \t\t}

  \t\tthis._drawing = true;

  \t\tfor (var order = this._drawFirst; order; order = order.next) {
  \t\t\tlayer = order.layer;
  \t\t\tif (!bounds || (layer._pxBounds && layer._pxBounds.intersects(bounds))) {
  \t\t\t\tlayer._updatePath();
  \t\t\t}
  \t\t}

  \t\tthis._drawing = false;

  \t\tthis._ctx.restore();  // Restore state before clipping.
  \t},

  \t_updatePoly: function (layer, closed) {
  \t\tif (!this._drawing) { return; }

  \t\tvar i, j, len2, p,
  \t\t    parts = layer._parts,
  \t\t    len = parts.length,
  \t\t    ctx = this._ctx;

  \t\tif (!len) { return; }

  \t\tctx.beginPath();

  \t\tfor (i = 0; i < len; i++) {
  \t\t\tfor (j = 0, len2 = parts[i].length; j < len2; j++) {
  \t\t\t\tp = parts[i][j];
  \t\t\t\tctx[j ? 'lineTo' : 'moveTo'](p.x, p.y);
  \t\t\t}
  \t\t\tif (closed) {
  \t\t\t\tctx.closePath();
  \t\t\t}
  \t\t}

  \t\tthis._fillStroke(ctx, layer);

  \t\t// TODO optimization: 1 fill/stroke for all features with equal style instead of 1 for each feature
  \t},

  \t_updateCircle: function (layer) {

  \t\tif (!this._drawing || layer._empty()) { return; }

  \t\tvar p = layer._point,
  \t\t    ctx = this._ctx,
  \t\t    r = Math.max(Math.round(layer._radius), 1),
  \t\t    s = (Math.max(Math.round(layer._radiusY), 1) || r) / r;

  \t\tif (s !== 1) {
  \t\t\tctx.save();
  \t\t\tctx.scale(1, s);
  \t\t}

  \t\tctx.beginPath();
  \t\tctx.arc(p.x, p.y / s, r, 0, Math.PI * 2, false);

  \t\tif (s !== 1) {
  \t\t\tctx.restore();
  \t\t}

  \t\tthis._fillStroke(ctx, layer);
  \t},

  \t_fillStroke: function (ctx, layer) {
  \t\tvar options = layer.options;

  \t\tif (options.fill) {
  \t\t\tctx.globalAlpha = options.fillOpacity;
  \t\t\tctx.fillStyle = options.fillColor || options.color;
  \t\t\tctx.fill(options.fillRule || 'evenodd');
  \t\t}

  \t\tif (options.stroke && options.weight !== 0) {
  \t\t\tif (ctx.setLineDash) {
  \t\t\t\tctx.setLineDash(layer.options && layer.options._dashArray || []);
  \t\t\t}
  \t\t\tctx.globalAlpha = options.opacity;
  \t\t\tctx.lineWidth = options.weight;
  \t\t\tctx.strokeStyle = options.color;
  \t\t\tctx.lineCap = options.lineCap;
  \t\t\tctx.lineJoin = options.lineJoin;
  \t\t\tctx.stroke();
  \t\t}
  \t},

  \t// Canvas obviously doesn't have mouse events for individual drawn objects,
  \t// so we emulate that by calculating what's under the mouse on mousemove/click manually

  \t_onClick: function (e) {
  \t\tvar point = this._map.mouseEventToLayerPoint(e), layer, clickedLayer;

  \t\tfor (var order = this._drawFirst; order; order = order.next) {
  \t\t\tlayer = order.layer;
  \t\t\tif (layer.options.interactive && layer._containsPoint(point)) {
  \t\t\t\tif (!(e.type === 'click' || e.type === 'preclick') || !this._map._draggableMoved(layer)) {
  \t\t\t\t\tclickedLayer = layer;
  \t\t\t\t}
  \t\t\t}
  \t\t}
  \t\tthis._fireEvent(clickedLayer ? [clickedLayer] : false, e);
  \t},

  \t_onMouseMove: function (e) {
  \t\tif (!this._map || this._map.dragging.moving() || this._map._animatingZoom) { return; }

  \t\tvar point = this._map.mouseEventToLayerPoint(e);
  \t\tthis._handleMouseHover(e, point);
  \t},


  \t_handleMouseOut: function (e) {
  \t\tvar layer = this._hoveredLayer;
  \t\tif (layer) {
  \t\t\t// if we're leaving the layer, fire mouseout
  \t\t\tremoveClass(this._container, 'leaflet-interactive');
  \t\t\tthis._fireEvent([layer], e, 'mouseout');
  \t\t\tthis._hoveredLayer = null;
  \t\t\tthis._mouseHoverThrottled = false;
  \t\t}
  \t},

  \t_handleMouseHover: function (e, point) {
  \t\tif (this._mouseHoverThrottled) {
  \t\t\treturn;
  \t\t}

  \t\tvar layer, candidateHoveredLayer;

  \t\tfor (var order = this._drawFirst; order; order = order.next) {
  \t\t\tlayer = order.layer;
  \t\t\tif (layer.options.interactive && layer._containsPoint(point)) {
  \t\t\t\tcandidateHoveredLayer = layer;
  \t\t\t}
  \t\t}

  \t\tif (candidateHoveredLayer !== this._hoveredLayer) {
  \t\t\tthis._handleMouseOut(e);

  \t\t\tif (candidateHoveredLayer) {
  \t\t\t\taddClass(this._container, 'leaflet-interactive'); // change cursor
  \t\t\t\tthis._fireEvent([candidateHoveredLayer], e, 'mouseover');
  \t\t\t\tthis._hoveredLayer = candidateHoveredLayer;
  \t\t\t}
  \t\t}

  \t\tthis._fireEvent(this._hoveredLayer ? [this._hoveredLayer] : false, e);

  \t\tthis._mouseHoverThrottled = true;
  \t\tsetTimeout(bind(function () {
  \t\t\tthis._mouseHoverThrottled = false;
  \t\t}, this), 32);
  \t},

  \t_fireEvent: function (layers, e, type) {
  \t\tthis._map._fireDOMEvent(e, type || e.type, layers);
  \t},

  \t_bringToFront: function (layer) {
  \t\tvar order = layer._order;

  \t\tif (!order) { return; }

  \t\tvar next = order.next;
  \t\tvar prev = order.prev;

  \t\tif (next) {
  \t\t\tnext.prev = prev;
  \t\t} else {
  \t\t\t// Already last
  \t\t\treturn;
  \t\t}
  \t\tif (prev) {
  \t\t\tprev.next = next;
  \t\t} else if (next) {
  \t\t\t// Update first entry unless this is the
  \t\t\t// single entry
  \t\t\tthis._drawFirst = next;
  \t\t}

  \t\torder.prev = this._drawLast;
  \t\tthis._drawLast.next = order;

  \t\torder.next = null;
  \t\tthis._drawLast = order;

  \t\tthis._requestRedraw(layer);
  \t},

  \t_bringToBack: function (layer) {
  \t\tvar order = layer._order;

  \t\tif (!order) { return; }

  \t\tvar next = order.next;
  \t\tvar prev = order.prev;

  \t\tif (prev) {
  \t\t\tprev.next = next;
  \t\t} else {
  \t\t\t// Already first
  \t\t\treturn;
  \t\t}
  \t\tif (next) {
  \t\t\tnext.prev = prev;
  \t\t} else if (prev) {
  \t\t\t// Update last entry unless this is the
  \t\t\t// single entry
  \t\t\tthis._drawLast = prev;
  \t\t}

  \t\torder.prev = null;

  \t\torder.next = this._drawFirst;
  \t\tthis._drawFirst.prev = order;
  \t\tthis._drawFirst = order;

  \t\tthis._requestRedraw(layer);
  \t}
  });

  // @factory L.canvas(options?: Renderer options)
  // Creates a Canvas renderer with the given options.
  function canvas(options) {
  \treturn Browser.canvas ? new Canvas(options) : null;
  }

  /*
   * Thanks to Dmitry Baranovsky and his Raphael library for inspiration!
   */


  var vmlCreate = (function () {
  \ttry {
  \t\tdocument.namespaces.add('lvml', 'urn:schemas-microsoft-com:vml');
  \t\treturn function (name) {
  \t\t\treturn document.createElement('<lvml:' + name + ' class=\"lvml\">');
  \t\t};
  \t} catch (e) {
  \t\t// Do not return fn from catch block so `e` can be garbage collected
  \t\t// See https://github.com/Leaflet/Leaflet/pull/7279
  \t}
  \treturn function (name) {
  \t\treturn document.createElement('<' + name + ' xmlns=\"urn:schemas-microsoft.com:vml\" class=\"lvml\">');
  \t};
  })();


  /*
   * @class SVG
   *
   *
   * VML was deprecated in 2012, which means VML functionality exists only for backwards compatibility
   * with old versions of Internet Explorer.
   */

  // mixin to redefine some SVG methods to handle VML syntax which is similar but with some differences
  var vmlMixin = {

  \t_initContainer: function () {
  \t\tthis._container = create\$1('div', 'leaflet-vml-container');
  \t},

  \t_update: function () {
  \t\tif (this._map._animatingZoom) { return; }
  \t\tRenderer.prototype._update.call(this);
  \t\tthis.fire('update');
  \t},

  \t_initPath: function (layer) {
  \t\tvar container = layer._container = vmlCreate('shape');

  \t\taddClass(container, 'leaflet-vml-shape ' + (this.options.className || ''));

  \t\tcontainer.coordsize = '1 1';

  \t\tlayer._path = vmlCreate('path');
  \t\tcontainer.appendChild(layer._path);

  \t\tthis._updateStyle(layer);
  \t\tthis._layers[stamp(layer)] = layer;
  \t},

  \t_addPath: function (layer) {
  \t\tvar container = layer._container;
  \t\tthis._container.appendChild(container);

  \t\tif (layer.options.interactive) {
  \t\t\tlayer.addInteractiveTarget(container);
  \t\t}
  \t},

  \t_removePath: function (layer) {
  \t\tvar container = layer._container;
  \t\tremove(container);
  \t\tlayer.removeInteractiveTarget(container);
  \t\tdelete this._layers[stamp(layer)];
  \t},

  \t_updateStyle: function (layer) {
  \t\tvar stroke = layer._stroke,
  \t\t    fill = layer._fill,
  \t\t    options = layer.options,
  \t\t    container = layer._container;

  \t\tcontainer.stroked = !!options.stroke;
  \t\tcontainer.filled = !!options.fill;

  \t\tif (options.stroke) {
  \t\t\tif (!stroke) {
  \t\t\t\tstroke = layer._stroke = vmlCreate('stroke');
  \t\t\t}
  \t\t\tcontainer.appendChild(stroke);
  \t\t\tstroke.weight = options.weight + 'px';
  \t\t\tstroke.color = options.color;
  \t\t\tstroke.opacity = options.opacity;

  \t\t\tif (options.dashArray) {
  \t\t\t\tstroke.dashStyle = isArray(options.dashArray) ?
  \t\t\t\t    options.dashArray.join(' ') :
  \t\t\t\t    options.dashArray.replace(/( *, *)/g, ' ');
  \t\t\t} else {
  \t\t\t\tstroke.dashStyle = '';
  \t\t\t}
  \t\t\tstroke.endcap = options.lineCap.replace('butt', 'flat');
  \t\t\tstroke.joinstyle = options.lineJoin;

  \t\t} else if (stroke) {
  \t\t\tcontainer.removeChild(stroke);
  \t\t\tlayer._stroke = null;
  \t\t}

  \t\tif (options.fill) {
  \t\t\tif (!fill) {
  \t\t\t\tfill = layer._fill = vmlCreate('fill');
  \t\t\t}
  \t\t\tcontainer.appendChild(fill);
  \t\t\tfill.color = options.fillColor || options.color;
  \t\t\tfill.opacity = options.fillOpacity;

  \t\t} else if (fill) {
  \t\t\tcontainer.removeChild(fill);
  \t\t\tlayer._fill = null;
  \t\t}
  \t},

  \t_updateCircle: function (layer) {
  \t\tvar p = layer._point.round(),
  \t\t    r = Math.round(layer._radius),
  \t\t    r2 = Math.round(layer._radiusY || r);

  \t\tthis._setPath(layer, layer._empty() ? 'M0 0' :
  \t\t\t'AL ' + p.x + ',' + p.y + ' ' + r + ',' + r2 + ' 0,' + (65535 * 360));
  \t},

  \t_setPath: function (layer, path) {
  \t\tlayer._path.v = path;
  \t},

  \t_bringToFront: function (layer) {
  \t\ttoFront(layer._container);
  \t},

  \t_bringToBack: function (layer) {
  \t\ttoBack(layer._container);
  \t}
  };

  var create = Browser.vml ? vmlCreate : svgCreate;

  /*
   * @class SVG
   * @inherits Renderer
   * @aka L.SVG
   *
   * Allows vector layers to be displayed with [SVG](https://developer.mozilla.org/docs/Web/SVG).
   * Inherits `Renderer`.
   *
   * Due to [technical limitations](https://caniuse.com/svg), SVG is not
   * available in all web browsers, notably Android 2.x and 3.x.
   *
   * Although SVG is not available on IE7 and IE8, these browsers support
   * [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language)
   * (a now deprecated technology), and the SVG renderer will fall back to VML in
   * this case.
   *
   * @example
   *
   * Use SVG by default for all paths in the map:
   *
   * ```js
   * var map = L.map('map', {
   * \trenderer: L.svg()
   * });
   * ```
   *
   * Use a SVG renderer with extra padding for specific vector geometries:
   *
   * ```js
   * var map = L.map('map');
   * var myRenderer = L.svg({ padding: 0.5 });
   * var line = L.polyline( coordinates, { renderer: myRenderer } );
   * var circle = L.circle( center, { renderer: myRenderer } );
   * ```
   */

  var SVG = Renderer.extend({

  \t_initContainer: function () {
  \t\tthis._container = create('svg');

  \t\t// makes it possible to click through svg root; we'll reset it back in individual paths
  \t\tthis._container.setAttribute('pointer-events', 'none');

  \t\tthis._rootGroup = create('g');
  \t\tthis._container.appendChild(this._rootGroup);
  \t},

  \t_destroyContainer: function () {
  \t\tremove(this._container);
  \t\toff(this._container);
  \t\tdelete this._container;
  \t\tdelete this._rootGroup;
  \t\tdelete this._svgSize;
  \t},

  \t_update: function () {
  \t\tif (this._map._animatingZoom && this._bounds) { return; }

  \t\tRenderer.prototype._update.call(this);

  \t\tvar b = this._bounds,
  \t\t    size = b.getSize(),
  \t\t    container = this._container;

  \t\t// set size of svg-container if changed
  \t\tif (!this._svgSize || !this._svgSize.equals(size)) {
  \t\t\tthis._svgSize = size;
  \t\t\tcontainer.setAttribute('width', size.x);
  \t\t\tcontainer.setAttribute('height', size.y);
  \t\t}

  \t\t// movement: update container viewBox so that we don't have to change coordinates of individual layers
  \t\tsetPosition(container, b.min);
  \t\tcontainer.setAttribute('viewBox', [b.min.x, b.min.y, size.x, size.y].join(' '));

  \t\tthis.fire('update');
  \t},

  \t// methods below are called by vector layers implementations

  \t_initPath: function (layer) {
  \t\tvar path = layer._path = create('path');

  \t\t// @namespace Path
  \t\t// @option className: String = null
  \t\t// Custom class name set on an element. Only for SVG renderer.
  \t\tif (layer.options.className) {
  \t\t\taddClass(path, layer.options.className);
  \t\t}

  \t\tif (layer.options.interactive) {
  \t\t\taddClass(path, 'leaflet-interactive');
  \t\t}

  \t\tthis._updateStyle(layer);
  \t\tthis._layers[stamp(layer)] = layer;
  \t},

  \t_addPath: function (layer) {
  \t\tif (!this._rootGroup) { this._initContainer(); }
  \t\tthis._rootGroup.appendChild(layer._path);
  \t\tlayer.addInteractiveTarget(layer._path);
  \t},

  \t_removePath: function (layer) {
  \t\tremove(layer._path);
  \t\tlayer.removeInteractiveTarget(layer._path);
  \t\tdelete this._layers[stamp(layer)];
  \t},

  \t_updatePath: function (layer) {
  \t\tlayer._project();
  \t\tlayer._update();
  \t},

  \t_updateStyle: function (layer) {
  \t\tvar path = layer._path,
  \t\t    options = layer.options;

  \t\tif (!path) { return; }

  \t\tif (options.stroke) {
  \t\t\tpath.setAttribute('stroke', options.color);
  \t\t\tpath.setAttribute('stroke-opacity', options.opacity);
  \t\t\tpath.setAttribute('stroke-width', options.weight);
  \t\t\tpath.setAttribute('stroke-linecap', options.lineCap);
  \t\t\tpath.setAttribute('stroke-linejoin', options.lineJoin);

  \t\t\tif (options.dashArray) {
  \t\t\t\tpath.setAttribute('stroke-dasharray', options.dashArray);
  \t\t\t} else {
  \t\t\t\tpath.removeAttribute('stroke-dasharray');
  \t\t\t}

  \t\t\tif (options.dashOffset) {
  \t\t\t\tpath.setAttribute('stroke-dashoffset', options.dashOffset);
  \t\t\t} else {
  \t\t\t\tpath.removeAttribute('stroke-dashoffset');
  \t\t\t}
  \t\t} else {
  \t\t\tpath.setAttribute('stroke', 'none');
  \t\t}

  \t\tif (options.fill) {
  \t\t\tpath.setAttribute('fill', options.fillColor || options.color);
  \t\t\tpath.setAttribute('fill-opacity', options.fillOpacity);
  \t\t\tpath.setAttribute('fill-rule', options.fillRule || 'evenodd');
  \t\t} else {
  \t\t\tpath.setAttribute('fill', 'none');
  \t\t}
  \t},

  \t_updatePoly: function (layer, closed) {
  \t\tthis._setPath(layer, pointsToPath(layer._parts, closed));
  \t},

  \t_updateCircle: function (layer) {
  \t\tvar p = layer._point,
  \t\t    r = Math.max(Math.round(layer._radius), 1),
  \t\t    r2 = Math.max(Math.round(layer._radiusY), 1) || r,
  \t\t    arc = 'a' + r + ',' + r2 + ' 0 1,0 ';

  \t\t// drawing a circle with two half-arcs
  \t\tvar d = layer._empty() ? 'M0 0' :
  \t\t\t'M' + (p.x - r) + ',' + p.y +
  \t\t\tarc + (r * 2) + ',0 ' +
  \t\t\tarc + (-r * 2) + ',0 ';

  \t\tthis._setPath(layer, d);
  \t},

  \t_setPath: function (layer, path) {
  \t\tlayer._path.setAttribute('d', path);
  \t},

  \t// SVG does not have the concept of zIndex so we resort to changing the DOM order of elements
  \t_bringToFront: function (layer) {
  \t\ttoFront(layer._path);
  \t},

  \t_bringToBack: function (layer) {
  \t\ttoBack(layer._path);
  \t}
  });

  if (Browser.vml) {
  \tSVG.include(vmlMixin);
  }

  // @namespace SVG
  // @factory L.svg(options?: Renderer options)
  // Creates a SVG renderer with the given options.
  function svg(options) {
  \treturn Browser.svg || Browser.vml ? new SVG(options) : null;
  }

  Map.include({
  \t// @namespace Map; @method getRenderer(layer: Path): Renderer
  \t// Returns the instance of `Renderer` that should be used to render the given
  \t// `Path`. It will ensure that the `renderer` options of the map and paths
  \t// are respected, and that the renderers do exist on the map.
  \tgetRenderer: function (layer) {
  \t\t// @namespace Path; @option renderer: Renderer
  \t\t// Use this specific instance of `Renderer` for this path. Takes
  \t\t// precedence over the map's [default renderer](#map-renderer).
  \t\tvar renderer = layer.options.renderer || this._getPaneRenderer(layer.options.pane) || this.options.renderer || this._renderer;

  \t\tif (!renderer) {
  \t\t\trenderer = this._renderer = this._createRenderer();
  \t\t}

  \t\tif (!this.hasLayer(renderer)) {
  \t\t\tthis.addLayer(renderer);
  \t\t}
  \t\treturn renderer;
  \t},

  \t_getPaneRenderer: function (name) {
  \t\tif (name === 'overlayPane' || name === undefined) {
  \t\t\treturn false;
  \t\t}

  \t\tvar renderer = this._paneRenderers[name];
  \t\tif (renderer === undefined) {
  \t\t\trenderer = this._createRenderer({pane: name});
  \t\t\tthis._paneRenderers[name] = renderer;
  \t\t}
  \t\treturn renderer;
  \t},

  \t_createRenderer: function (options) {
  \t\t// @namespace Map; @option preferCanvas: Boolean = false
  \t\t// Whether `Path`s should be rendered on a `Canvas` renderer.
  \t\t// By default, all `Path`s are rendered in a `SVG` renderer.
  \t\treturn (this.options.preferCanvas && canvas(options)) || svg(options);
  \t}
  });

  /*
   * L.Rectangle extends Polygon and creates a rectangle when passed a LatLngBounds object.
   */

  /*
   * @class Rectangle
   * @aka L.Rectangle
   * @inherits Polygon
   *
   * A class for drawing rectangle overlays on a map. Extends `Polygon`.
   *
   * @example
   *
   * ```js
   * // define rectangle geographical bounds
   * var bounds = [[54.559322, -5.767822], [56.1210604, -3.021240]];
   *
   * // create an orange rectangle
   * L.rectangle(bounds, {color: \"#ff7800\", weight: 1}).addTo(map);
   *
   * // zoom the map to the rectangle bounds
   * map.fitBounds(bounds);
   * ```
   *
   */


  var Rectangle = Polygon.extend({
  \tinitialize: function (latLngBounds, options) {
  \t\tPolygon.prototype.initialize.call(this, this._boundsToLatLngs(latLngBounds), options);
  \t},

  \t// @method setBounds(latLngBounds: LatLngBounds): this
  \t// Redraws the rectangle with the passed bounds.
  \tsetBounds: function (latLngBounds) {
  \t\treturn this.setLatLngs(this._boundsToLatLngs(latLngBounds));
  \t},

  \t_boundsToLatLngs: function (latLngBounds) {
  \t\tlatLngBounds = toLatLngBounds(latLngBounds);
  \t\treturn [
  \t\t\tlatLngBounds.getSouthWest(),
  \t\t\tlatLngBounds.getNorthWest(),
  \t\t\tlatLngBounds.getNorthEast(),
  \t\t\tlatLngBounds.getSouthEast()
  \t\t];
  \t}
  });


  // @factory L.rectangle(latLngBounds: LatLngBounds, options?: Polyline options)
  function rectangle(latLngBounds, options) {
  \treturn new Rectangle(latLngBounds, options);
  }

  SVG.create = create;
  SVG.pointsToPath = pointsToPath;

  GeoJSON.geometryToLayer = geometryToLayer;
  GeoJSON.coordsToLatLng = coordsToLatLng;
  GeoJSON.coordsToLatLngs = coordsToLatLngs;
  GeoJSON.latLngToCoords = latLngToCoords;
  GeoJSON.latLngsToCoords = latLngsToCoords;
  GeoJSON.getFeature = getFeature;
  GeoJSON.asFeature = asFeature;

  /*
   * L.Handler.BoxZoom is used to add shift-drag zoom interaction to the map
   * (zoom to a selected bounding box), enabled by default.
   */

  // @namespace Map
  // @section Interaction Options
  Map.mergeOptions({
  \t// @option boxZoom: Boolean = true
  \t// Whether the map can be zoomed to a rectangular area specified by
  \t// dragging the mouse while pressing the shift key.
  \tboxZoom: true
  });

  var BoxZoom = Handler.extend({
  \tinitialize: function (map) {
  \t\tthis._map = map;
  \t\tthis._container = map._container;
  \t\tthis._pane = map._panes.overlayPane;
  \t\tthis._resetStateTimeout = 0;
  \t\tmap.on('unload', this._destroy, this);
  \t},

  \taddHooks: function () {
  \t\ton(this._container, 'mousedown', this._onMouseDown, this);
  \t},

  \tremoveHooks: function () {
  \t\toff(this._container, 'mousedown', this._onMouseDown, this);
  \t},

  \tmoved: function () {
  \t\treturn this._moved;
  \t},

  \t_destroy: function () {
  \t\tremove(this._pane);
  \t\tdelete this._pane;
  \t},

  \t_resetState: function () {
  \t\tthis._resetStateTimeout = 0;
  \t\tthis._moved = false;
  \t},

  \t_clearDeferredResetState: function () {
  \t\tif (this._resetStateTimeout !== 0) {
  \t\t\tclearTimeout(this._resetStateTimeout);
  \t\t\tthis._resetStateTimeout = 0;
  \t\t}
  \t},

  \t_onMouseDown: function (e) {
  \t\tif (!e.shiftKey || ((e.which !== 1) && (e.button !== 1))) { return false; }

  \t\t// Clear the deferred resetState if it hasn't executed yet, otherwise it
  \t\t// will interrupt the interaction and orphan a box element in the container.
  \t\tthis._clearDeferredResetState();
  \t\tthis._resetState();

  \t\tdisableTextSelection();
  \t\tdisableImageDrag();

  \t\tthis._startPoint = this._map.mouseEventToContainerPoint(e);

  \t\ton(document, {
  \t\t\tcontextmenu: stop,
  \t\t\tmousemove: this._onMouseMove,
  \t\t\tmouseup: this._onMouseUp,
  \t\t\tkeydown: this._onKeyDown
  \t\t}, this);
  \t},

  \t_onMouseMove: function (e) {
  \t\tif (!this._moved) {
  \t\t\tthis._moved = true;

  \t\t\tthis._box = create\$1('div', 'leaflet-zoom-box', this._container);
  \t\t\taddClass(this._container, 'leaflet-crosshair');

  \t\t\tthis._map.fire('boxzoomstart');
  \t\t}

  \t\tthis._point = this._map.mouseEventToContainerPoint(e);

  \t\tvar bounds = new Bounds(this._point, this._startPoint),
  \t\t    size = bounds.getSize();

  \t\tsetPosition(this._box, bounds.min);

  \t\tthis._box.style.width  = size.x + 'px';
  \t\tthis._box.style.height = size.y + 'px';
  \t},

  \t_finish: function () {
  \t\tif (this._moved) {
  \t\t\tremove(this._box);
  \t\t\tremoveClass(this._container, 'leaflet-crosshair');
  \t\t}

  \t\tenableTextSelection();
  \t\tenableImageDrag();

  \t\toff(document, {
  \t\t\tcontextmenu: stop,
  \t\t\tmousemove: this._onMouseMove,
  \t\t\tmouseup: this._onMouseUp,
  \t\t\tkeydown: this._onKeyDown
  \t\t}, this);
  \t},

  \t_onMouseUp: function (e) {
  \t\tif ((e.which !== 1) && (e.button !== 1)) { return; }

  \t\tthis._finish();

  \t\tif (!this._moved) { return; }
  \t\t// Postpone to next JS tick so internal click event handling
  \t\t// still see it as \"moved\".
  \t\tthis._clearDeferredResetState();
  \t\tthis._resetStateTimeout = setTimeout(bind(this._resetState, this), 0);

  \t\tvar bounds = new LatLngBounds(
  \t\t        this._map.containerPointToLatLng(this._startPoint),
  \t\t        this._map.containerPointToLatLng(this._point));

  \t\tthis._map
  \t\t\t.fitBounds(bounds)
  \t\t\t.fire('boxzoomend', {boxZoomBounds: bounds});
  \t},

  \t_onKeyDown: function (e) {
  \t\tif (e.keyCode === 27) {
  \t\t\tthis._finish();
  \t\t\tthis._clearDeferredResetState();
  \t\t\tthis._resetState();
  \t\t}
  \t}
  });

  // @section Handlers
  // @property boxZoom: Handler
  // Box (shift-drag with mouse) zoom handler.
  Map.addInitHook('addHandler', 'boxZoom', BoxZoom);

  /*
   * L.Handler.DoubleClickZoom is used to handle double-click zoom on the map, enabled by default.
   */

  // @namespace Map
  // @section Interaction Options

  Map.mergeOptions({
  \t// @option doubleClickZoom: Boolean|String = true
  \t// Whether the map can be zoomed in by double clicking on it and
  \t// zoomed out by double clicking while holding shift. If passed
  \t// `'center'`, double-click zoom will zoom to the center of the
  \t//  view regardless of where the mouse was.
  \tdoubleClickZoom: true
  });

  var DoubleClickZoom = Handler.extend({
  \taddHooks: function () {
  \t\tthis._map.on('dblclick', this._onDoubleClick, this);
  \t},

  \tremoveHooks: function () {
  \t\tthis._map.off('dblclick', this._onDoubleClick, this);
  \t},

  \t_onDoubleClick: function (e) {
  \t\tvar map = this._map,
  \t\t    oldZoom = map.getZoom(),
  \t\t    delta = map.options.zoomDelta,
  \t\t    zoom = e.originalEvent.shiftKey ? oldZoom - delta : oldZoom + delta;

  \t\tif (map.options.doubleClickZoom === 'center') {
  \t\t\tmap.setZoom(zoom);
  \t\t} else {
  \t\t\tmap.setZoomAround(e.containerPoint, zoom);
  \t\t}
  \t}
  });

  // @section Handlers
  //
  // Map properties include interaction handlers that allow you to control
  // interaction behavior in runtime, enabling or disabling certain features such
  // as dragging or touch zoom (see `Handler` methods). For example:
  //
  // ```js
  // map.doubleClickZoom.disable();
  // ```
  //
  // @property doubleClickZoom: Handler
  // Double click zoom handler.
  Map.addInitHook('addHandler', 'doubleClickZoom', DoubleClickZoom);

  /*
   * L.Handler.MapDrag is used to make the map draggable (with panning inertia), enabled by default.
   */

  // @namespace Map
  // @section Interaction Options
  Map.mergeOptions({
  \t// @option dragging: Boolean = true
  \t// Whether the map is draggable with mouse/touch or not.
  \tdragging: true,

  \t// @section Panning Inertia Options
  \t// @option inertia: Boolean = *
  \t// If enabled, panning of the map will have an inertia effect where
  \t// the map builds momentum while dragging and continues moving in
  \t// the same direction for some time. Feels especially nice on touch
  \t// devices. Enabled by default.
  \tinertia: true,

  \t// @option inertiaDeceleration: Number = 3000
  \t// The rate with which the inertial movement slows down, in pixels/second².
  \tinertiaDeceleration: 3400, // px/s^2

  \t// @option inertiaMaxSpeed: Number = Infinity
  \t// Max speed of the inertial movement, in pixels/second.
  \tinertiaMaxSpeed: Infinity, // px/s

  \t// @option easeLinearity: Number = 0.2
  \teaseLinearity: 0.2,

  \t// TODO refactor, move to CRS
  \t// @option worldCopyJump: Boolean = false
  \t// With this option enabled, the map tracks when you pan to another \"copy\"
  \t// of the world and seamlessly jumps to the original one so that all overlays
  \t// like markers and vector layers are still visible.
  \tworldCopyJump: false,

  \t// @option maxBoundsViscosity: Number = 0.0
  \t// If `maxBounds` is set, this option will control how solid the bounds
  \t// are when dragging the map around. The default value of `0.0` allows the
  \t// user to drag outside the bounds at normal speed, higher values will
  \t// slow down map dragging outside bounds, and `1.0` makes the bounds fully
  \t// solid, preventing the user from dragging outside the bounds.
  \tmaxBoundsViscosity: 0.0
  });

  var Drag = Handler.extend({
  \taddHooks: function () {
  \t\tif (!this._draggable) {
  \t\t\tvar map = this._map;

  \t\t\tthis._draggable = new Draggable(map._mapPane, map._container);

  \t\t\tthis._draggable.on({
  \t\t\t\tdragstart: this._onDragStart,
  \t\t\t\tdrag: this._onDrag,
  \t\t\t\tdragend: this._onDragEnd
  \t\t\t}, this);

  \t\t\tthis._draggable.on('predrag', this._onPreDragLimit, this);
  \t\t\tif (map.options.worldCopyJump) {
  \t\t\t\tthis._draggable.on('predrag', this._onPreDragWrap, this);
  \t\t\t\tmap.on('zoomend', this._onZoomEnd, this);

  \t\t\t\tmap.whenReady(this._onZoomEnd, this);
  \t\t\t}
  \t\t}
  \t\taddClass(this._map._container, 'leaflet-grab leaflet-touch-drag');
  \t\tthis._draggable.enable();
  \t\tthis._positions = [];
  \t\tthis._times = [];
  \t},

  \tremoveHooks: function () {
  \t\tremoveClass(this._map._container, 'leaflet-grab');
  \t\tremoveClass(this._map._container, 'leaflet-touch-drag');
  \t\tthis._draggable.disable();
  \t},

  \tmoved: function () {
  \t\treturn this._draggable && this._draggable._moved;
  \t},

  \tmoving: function () {
  \t\treturn this._draggable && this._draggable._moving;
  \t},

  \t_onDragStart: function () {
  \t\tvar map = this._map;

  \t\tmap._stop();
  \t\tif (this._map.options.maxBounds && this._map.options.maxBoundsViscosity) {
  \t\t\tvar bounds = toLatLngBounds(this._map.options.maxBounds);

  \t\t\tthis._offsetLimit = toBounds(
  \t\t\t\tthis._map.latLngToContainerPoint(bounds.getNorthWest()).multiplyBy(-1),
  \t\t\t\tthis._map.latLngToContainerPoint(bounds.getSouthEast()).multiplyBy(-1)
  \t\t\t\t\t.add(this._map.getSize()));

  \t\t\tthis._viscosity = Math.min(1.0, Math.max(0.0, this._map.options.maxBoundsViscosity));
  \t\t} else {
  \t\t\tthis._offsetLimit = null;
  \t\t}

  \t\tmap
  \t\t    .fire('movestart')
  \t\t    .fire('dragstart');

  \t\tif (map.options.inertia) {
  \t\t\tthis._positions = [];
  \t\t\tthis._times = [];
  \t\t}
  \t},

  \t_onDrag: function (e) {
  \t\tif (this._map.options.inertia) {
  \t\t\tvar time = this._lastTime = +new Date(),
  \t\t\t    pos = this._lastPos = this._draggable._absPos || this._draggable._newPos;

  \t\t\tthis._positions.push(pos);
  \t\t\tthis._times.push(time);

  \t\t\tthis._prunePositions(time);
  \t\t}

  \t\tthis._map
  \t\t    .fire('move', e)
  \t\t    .fire('drag', e);
  \t},

  \t_prunePositions: function (time) {
  \t\twhile (this._positions.length > 1 && time - this._times[0] > 50) {
  \t\t\tthis._positions.shift();
  \t\t\tthis._times.shift();
  \t\t}
  \t},

  \t_onZoomEnd: function () {
  \t\tvar pxCenter = this._map.getSize().divideBy(2),
  \t\t    pxWorldCenter = this._map.latLngToLayerPoint([0, 0]);

  \t\tthis._initialWorldOffset = pxWorldCenter.subtract(pxCenter).x;
  \t\tthis._worldWidth = this._map.getPixelWorldBounds().getSize().x;
  \t},

  \t_viscousLimit: function (value, threshold) {
  \t\treturn value - (value - threshold) * this._viscosity;
  \t},

  \t_onPreDragLimit: function () {
  \t\tif (!this._viscosity || !this._offsetLimit) { return; }

  \t\tvar offset = this._draggable._newPos.subtract(this._draggable._startPos);

  \t\tvar limit = this._offsetLimit;
  \t\tif (offset.x < limit.min.x) { offset.x = this._viscousLimit(offset.x, limit.min.x); }
  \t\tif (offset.y < limit.min.y) { offset.y = this._viscousLimit(offset.y, limit.min.y); }
  \t\tif (offset.x > limit.max.x) { offset.x = this._viscousLimit(offset.x, limit.max.x); }
  \t\tif (offset.y > limit.max.y) { offset.y = this._viscousLimit(offset.y, limit.max.y); }

  \t\tthis._draggable._newPos = this._draggable._startPos.add(offset);
  \t},

  \t_onPreDragWrap: function () {
  \t\t// TODO refactor to be able to adjust map pane position after zoom
  \t\tvar worldWidth = this._worldWidth,
  \t\t    halfWidth = Math.round(worldWidth / 2),
  \t\t    dx = this._initialWorldOffset,
  \t\t    x = this._draggable._newPos.x,
  \t\t    newX1 = (x - halfWidth + dx) % worldWidth + halfWidth - dx,
  \t\t    newX2 = (x + halfWidth + dx) % worldWidth - halfWidth - dx,
  \t\t    newX = Math.abs(newX1 + dx) < Math.abs(newX2 + dx) ? newX1 : newX2;

  \t\tthis._draggable._absPos = this._draggable._newPos.clone();
  \t\tthis._draggable._newPos.x = newX;
  \t},

  \t_onDragEnd: function (e) {
  \t\tvar map = this._map,
  \t\t    options = map.options,

  \t\t    noInertia = !options.inertia || e.noInertia || this._times.length < 2;

  \t\tmap.fire('dragend', e);

  \t\tif (noInertia) {
  \t\t\tmap.fire('moveend');

  \t\t} else {
  \t\t\tthis._prunePositions(+new Date());

  \t\t\tvar direction = this._lastPos.subtract(this._positions[0]),
  \t\t\t    duration = (this._lastTime - this._times[0]) / 1000,
  \t\t\t    ease = options.easeLinearity,

  \t\t\t    speedVector = direction.multiplyBy(ease / duration),
  \t\t\t    speed = speedVector.distanceTo([0, 0]),

  \t\t\t    limitedSpeed = Math.min(options.inertiaMaxSpeed, speed),
  \t\t\t    limitedSpeedVector = speedVector.multiplyBy(limitedSpeed / speed),

  \t\t\t    decelerationDuration = limitedSpeed / (options.inertiaDeceleration * ease),
  \t\t\t    offset = limitedSpeedVector.multiplyBy(-decelerationDuration / 2).round();

  \t\t\tif (!offset.x && !offset.y) {
  \t\t\t\tmap.fire('moveend');

  \t\t\t} else {
  \t\t\t\toffset = map._limitOffset(offset, map.options.maxBounds);

  \t\t\t\trequestAnimFrame(function () {
  \t\t\t\t\tmap.panBy(offset, {
  \t\t\t\t\t\tduration: decelerationDuration,
  \t\t\t\t\t\teaseLinearity: ease,
  \t\t\t\t\t\tnoMoveStart: true,
  \t\t\t\t\t\tanimate: true
  \t\t\t\t\t});
  \t\t\t\t});
  \t\t\t}
  \t\t}
  \t}
  });

  // @section Handlers
  // @property dragging: Handler
  // Map dragging handler (by both mouse and touch).
  Map.addInitHook('addHandler', 'dragging', Drag);

  /*
   * L.Map.Keyboard is handling keyboard interaction with the map, enabled by default.
   */

  // @namespace Map
  // @section Keyboard Navigation Options
  Map.mergeOptions({
  \t// @option keyboard: Boolean = true
  \t// Makes the map focusable and allows users to navigate the map with keyboard
  \t// arrows and `+`/`-` keys.
  \tkeyboard: true,

  \t// @option keyboardPanDelta: Number = 80
  \t// Amount of pixels to pan when pressing an arrow key.
  \tkeyboardPanDelta: 80
  });

  var Keyboard = Handler.extend({

  \tkeyCodes: {
  \t\tleft:    [37],
  \t\tright:   [39],
  \t\tdown:    [40],
  \t\tup:      [38],
  \t\tzoomIn:  [187, 107, 61, 171],
  \t\tzoomOut: [189, 109, 54, 173]
  \t},

  \tinitialize: function (map) {
  \t\tthis._map = map;

  \t\tthis._setPanDelta(map.options.keyboardPanDelta);
  \t\tthis._setZoomDelta(map.options.zoomDelta);
  \t},

  \taddHooks: function () {
  \t\tvar container = this._map._container;

  \t\t// make the container focusable by tabbing
  \t\tif (container.tabIndex <= 0) {
  \t\t\tcontainer.tabIndex = '0';
  \t\t}

  \t\ton(container, {
  \t\t\tfocus: this._onFocus,
  \t\t\tblur: this._onBlur,
  \t\t\tmousedown: this._onMouseDown
  \t\t}, this);

  \t\tthis._map.on({
  \t\t\tfocus: this._addHooks,
  \t\t\tblur: this._removeHooks
  \t\t}, this);
  \t},

  \tremoveHooks: function () {
  \t\tthis._removeHooks();

  \t\toff(this._map._container, {
  \t\t\tfocus: this._onFocus,
  \t\t\tblur: this._onBlur,
  \t\t\tmousedown: this._onMouseDown
  \t\t}, this);

  \t\tthis._map.off({
  \t\t\tfocus: this._addHooks,
  \t\t\tblur: this._removeHooks
  \t\t}, this);
  \t},

  \t_onMouseDown: function () {
  \t\tif (this._focused) { return; }

  \t\tvar body = document.body,
  \t\t    docEl = document.documentElement,
  \t\t    top = body.scrollTop || docEl.scrollTop,
  \t\t    left = body.scrollLeft || docEl.scrollLeft;

  \t\tthis._map._container.focus();

  \t\twindow.scrollTo(left, top);
  \t},

  \t_onFocus: function () {
  \t\tthis._focused = true;
  \t\tthis._map.fire('focus');
  \t},

  \t_onBlur: function () {
  \t\tthis._focused = false;
  \t\tthis._map.fire('blur');
  \t},

  \t_setPanDelta: function (panDelta) {
  \t\tvar keys = this._panKeys = {},
  \t\t    codes = this.keyCodes,
  \t\t    i, len;

  \t\tfor (i = 0, len = codes.left.length; i < len; i++) {
  \t\t\tkeys[codes.left[i]] = [-1 * panDelta, 0];
  \t\t}
  \t\tfor (i = 0, len = codes.right.length; i < len; i++) {
  \t\t\tkeys[codes.right[i]] = [panDelta, 0];
  \t\t}
  \t\tfor (i = 0, len = codes.down.length; i < len; i++) {
  \t\t\tkeys[codes.down[i]] = [0, panDelta];
  \t\t}
  \t\tfor (i = 0, len = codes.up.length; i < len; i++) {
  \t\t\tkeys[codes.up[i]] = [0, -1 * panDelta];
  \t\t}
  \t},

  \t_setZoomDelta: function (zoomDelta) {
  \t\tvar keys = this._zoomKeys = {},
  \t\t    codes = this.keyCodes,
  \t\t    i, len;

  \t\tfor (i = 0, len = codes.zoomIn.length; i < len; i++) {
  \t\t\tkeys[codes.zoomIn[i]] = zoomDelta;
  \t\t}
  \t\tfor (i = 0, len = codes.zoomOut.length; i < len; i++) {
  \t\t\tkeys[codes.zoomOut[i]] = -zoomDelta;
  \t\t}
  \t},

  \t_addHooks: function () {
  \t\ton(document, 'keydown', this._onKeyDown, this);
  \t},

  \t_removeHooks: function () {
  \t\toff(document, 'keydown', this._onKeyDown, this);
  \t},

  \t_onKeyDown: function (e) {
  \t\tif (e.altKey || e.ctrlKey || e.metaKey) { return; }

  \t\tvar key = e.keyCode,
  \t\t    map = this._map,
  \t\t    offset;

  \t\tif (key in this._panKeys) {
  \t\t\tif (!map._panAnim || !map._panAnim._inProgress) {
  \t\t\t\toffset = this._panKeys[key];
  \t\t\t\tif (e.shiftKey) {
  \t\t\t\t\toffset = toPoint(offset).multiplyBy(3);
  \t\t\t\t}

  \t\t\t\tif (map.options.maxBounds) {
  \t\t\t\t\toffset = map._limitOffset(toPoint(offset), map.options.maxBounds);
  \t\t\t\t}

  \t\t\t\tif (map.options.worldCopyJump) {
  \t\t\t\t\tvar newLatLng = map.wrapLatLng(map.unproject(map.project(map.getCenter()).add(offset)));
  \t\t\t\t\tmap.panTo(newLatLng);
  \t\t\t\t} else {
  \t\t\t\t\tmap.panBy(offset);
  \t\t\t\t}
  \t\t\t}
  \t\t} else if (key in this._zoomKeys) {
  \t\t\tmap.setZoom(map.getZoom() + (e.shiftKey ? 3 : 1) * this._zoomKeys[key]);

  \t\t} else if (key === 27 && map._popup && map._popup.options.closeOnEscapeKey) {
  \t\t\tmap.closePopup();

  \t\t} else {
  \t\t\treturn;
  \t\t}

  \t\tstop(e);
  \t}
  });

  // @section Handlers
  // @section Handlers
  // @property keyboard: Handler
  // Keyboard navigation handler.
  Map.addInitHook('addHandler', 'keyboard', Keyboard);

  /*
   * L.Handler.ScrollWheelZoom is used by L.Map to enable mouse scroll wheel zoom on the map.
   */

  // @namespace Map
  // @section Interaction Options
  Map.mergeOptions({
  \t// @section Mouse wheel options
  \t// @option scrollWheelZoom: Boolean|String = true
  \t// Whether the map can be zoomed by using the mouse wheel. If passed `'center'`,
  \t// it will zoom to the center of the view regardless of where the mouse was.
  \tscrollWheelZoom: true,

  \t// @option wheelDebounceTime: Number = 40
  \t// Limits the rate at which a wheel can fire (in milliseconds). By default
  \t// user can't zoom via wheel more often than once per 40 ms.
  \twheelDebounceTime: 40,

  \t// @option wheelPxPerZoomLevel: Number = 60
  \t// How many scroll pixels (as reported by [L.DomEvent.getWheelDelta](#domevent-getwheeldelta))
  \t// mean a change of one full zoom level. Smaller values will make wheel-zooming
  \t// faster (and vice versa).
  \twheelPxPerZoomLevel: 60
  });

  var ScrollWheelZoom = Handler.extend({
  \taddHooks: function () {
  \t\ton(this._map._container, 'wheel', this._onWheelScroll, this);

  \t\tthis._delta = 0;
  \t},

  \tremoveHooks: function () {
  \t\toff(this._map._container, 'wheel', this._onWheelScroll, this);
  \t},

  \t_onWheelScroll: function (e) {
  \t\tvar delta = getWheelDelta(e);

  \t\tvar debounce = this._map.options.wheelDebounceTime;

  \t\tthis._delta += delta;
  \t\tthis._lastMousePos = this._map.mouseEventToContainerPoint(e);

  \t\tif (!this._startTime) {
  \t\t\tthis._startTime = +new Date();
  \t\t}

  \t\tvar left = Math.max(debounce - (+new Date() - this._startTime), 0);

  \t\tclearTimeout(this._timer);
  \t\tthis._timer = setTimeout(bind(this._performZoom, this), left);

  \t\tstop(e);
  \t},

  \t_performZoom: function () {
  \t\tvar map = this._map,
  \t\t    zoom = map.getZoom(),
  \t\t    snap = this._map.options.zoomSnap || 0;

  \t\tmap._stop(); // stop panning and fly animations if any

  \t\t// map the delta with a sigmoid function to -4..4 range leaning on -1..1
  \t\tvar d2 = this._delta / (this._map.options.wheelPxPerZoomLevel * 4),
  \t\t    d3 = 4 * Math.log(2 / (1 + Math.exp(-Math.abs(d2)))) / Math.LN2,
  \t\t    d4 = snap ? Math.ceil(d3 / snap) * snap : d3,
  \t\t    delta = map._limitZoom(zoom + (this._delta > 0 ? d4 : -d4)) - zoom;

  \t\tthis._delta = 0;
  \t\tthis._startTime = null;

  \t\tif (!delta) { return; }

  \t\tif (map.options.scrollWheelZoom === 'center') {
  \t\t\tmap.setZoom(zoom + delta);
  \t\t} else {
  \t\t\tmap.setZoomAround(this._lastMousePos, zoom + delta);
  \t\t}
  \t}
  });

  // @section Handlers
  // @property scrollWheelZoom: Handler
  // Scroll wheel zoom handler.
  Map.addInitHook('addHandler', 'scrollWheelZoom', ScrollWheelZoom);

  /*
   * L.Map.TapHold is used to simulate `contextmenu` event on long hold,
   * which otherwise is not fired by mobile Safari.
   */

  var tapHoldDelay = 600;

  // @namespace Map
  // @section Interaction Options
  Map.mergeOptions({
  \t// @section Touch interaction options
  \t// @option tapHold: Boolean
  \t// Enables simulation of `contextmenu` event, default is `true` for mobile Safari.
  \ttapHold: Browser.touchNative && Browser.safari && Browser.mobile,

  \t// @option tapTolerance: Number = 15
  \t// The max number of pixels a user can shift his finger during touch
  \t// for it to be considered a valid tap.
  \ttapTolerance: 15
  });

  var TapHold = Handler.extend({
  \taddHooks: function () {
  \t\ton(this._map._container, 'touchstart', this._onDown, this);
  \t},

  \tremoveHooks: function () {
  \t\toff(this._map._container, 'touchstart', this._onDown, this);
  \t},

  \t_onDown: function (e) {
  \t\tclearTimeout(this._holdTimeout);
  \t\tif (e.touches.length !== 1) { return; }

  \t\tvar first = e.touches[0];
  \t\tthis._startPos = this._newPos = new Point(first.clientX, first.clientY);

  \t\tthis._holdTimeout = setTimeout(bind(function () {
  \t\t\tthis._cancel();
  \t\t\tif (!this._isTapValid()) { return; }

  \t\t\t// prevent simulated mouse events https://w3c.github.io/touch-events/#mouse-events
  \t\t\ton(document, 'touchend', preventDefault);
  \t\t\ton(document, 'touchend touchcancel', this._cancelClickPrevent);
  \t\t\tthis._simulateEvent('contextmenu', first);
  \t\t}, this), tapHoldDelay);

  \t\ton(document, 'touchend touchcancel contextmenu', this._cancel, this);
  \t\ton(document, 'touchmove', this._onMove, this);
  \t},

  \t_cancelClickPrevent: function cancelClickPrevent() {
  \t\toff(document, 'touchend', preventDefault);
  \t\toff(document, 'touchend touchcancel', cancelClickPrevent);
  \t},

  \t_cancel: function () {
  \t\tclearTimeout(this._holdTimeout);
  \t\toff(document, 'touchend touchcancel contextmenu', this._cancel, this);
  \t\toff(document, 'touchmove', this._onMove, this);
  \t},

  \t_onMove: function (e) {
  \t\tvar first = e.touches[0];
  \t\tthis._newPos = new Point(first.clientX, first.clientY);
  \t},

  \t_isTapValid: function () {
  \t\treturn this._newPos.distanceTo(this._startPos) <= this._map.options.tapTolerance;
  \t},

  \t_simulateEvent: function (type, e) {
  \t\tvar simulatedEvent = new MouseEvent(type, {
  \t\t\tbubbles: true,
  \t\t\tcancelable: true,
  \t\t\tview: window,
  \t\t\t// detail: 1,
  \t\t\tscreenX: e.screenX,
  \t\t\tscreenY: e.screenY,
  \t\t\tclientX: e.clientX,
  \t\t\tclientY: e.clientY,
  \t\t\t// button: 2,
  \t\t\t// buttons: 2
  \t\t});

  \t\tsimulatedEvent._simulated = true;

  \t\te.target.dispatchEvent(simulatedEvent);
  \t}
  });

  // @section Handlers
  // @property tapHold: Handler
  // Long tap handler to simulate `contextmenu` event (useful in mobile Safari).
  Map.addInitHook('addHandler', 'tapHold', TapHold);

  /*
   * L.Handler.TouchZoom is used by L.Map to add pinch zoom on supported mobile browsers.
   */

  // @namespace Map
  // @section Interaction Options
  Map.mergeOptions({
  \t// @section Touch interaction options
  \t// @option touchZoom: Boolean|String = *
  \t// Whether the map can be zoomed by touch-dragging with two fingers. If
  \t// passed `'center'`, it will zoom to the center of the view regardless of
  \t// where the touch events (fingers) were. Enabled for touch-capable web
  \t// browsers.
  \ttouchZoom: Browser.touch,

  \t// @option bounceAtZoomLimits: Boolean = true
  \t// Set it to false if you don't want the map to zoom beyond min/max zoom
  \t// and then bounce back when pinch-zooming.
  \tbounceAtZoomLimits: true
  });

  var TouchZoom = Handler.extend({
  \taddHooks: function () {
  \t\taddClass(this._map._container, 'leaflet-touch-zoom');
  \t\ton(this._map._container, 'touchstart', this._onTouchStart, this);
  \t},

  \tremoveHooks: function () {
  \t\tremoveClass(this._map._container, 'leaflet-touch-zoom');
  \t\toff(this._map._container, 'touchstart', this._onTouchStart, this);
  \t},

  \t_onTouchStart: function (e) {
  \t\tvar map = this._map;
  \t\tif (!e.touches || e.touches.length !== 2 || map._animatingZoom || this._zooming) { return; }

  \t\tvar p1 = map.mouseEventToContainerPoint(e.touches[0]),
  \t\t    p2 = map.mouseEventToContainerPoint(e.touches[1]);

  \t\tthis._centerPoint = map.getSize()._divideBy(2);
  \t\tthis._startLatLng = map.containerPointToLatLng(this._centerPoint);
  \t\tif (map.options.touchZoom !== 'center') {
  \t\t\tthis._pinchStartLatLng = map.containerPointToLatLng(p1.add(p2)._divideBy(2));
  \t\t}

  \t\tthis._startDist = p1.distanceTo(p2);
  \t\tthis._startZoom = map.getZoom();

  \t\tthis._moved = false;
  \t\tthis._zooming = true;

  \t\tmap._stop();

  \t\ton(document, 'touchmove', this._onTouchMove, this);
  \t\ton(document, 'touchend touchcancel', this._onTouchEnd, this);

  \t\tpreventDefault(e);
  \t},

  \t_onTouchMove: function (e) {
  \t\tif (!e.touches || e.touches.length !== 2 || !this._zooming) { return; }

  \t\tvar map = this._map,
  \t\t    p1 = map.mouseEventToContainerPoint(e.touches[0]),
  \t\t    p2 = map.mouseEventToContainerPoint(e.touches[1]),
  \t\t    scale = p1.distanceTo(p2) / this._startDist;

  \t\tthis._zoom = map.getScaleZoom(scale, this._startZoom);

  \t\tif (!map.options.bounceAtZoomLimits && (
  \t\t\t(this._zoom < map.getMinZoom() && scale < 1) ||
  \t\t\t(this._zoom > map.getMaxZoom() && scale > 1))) {
  \t\t\tthis._zoom = map._limitZoom(this._zoom);
  \t\t}

  \t\tif (map.options.touchZoom === 'center') {
  \t\t\tthis._center = this._startLatLng;
  \t\t\tif (scale === 1) { return; }
  \t\t} else {
  \t\t\t// Get delta from pinch to center, so centerLatLng is delta applied to initial pinchLatLng
  \t\t\tvar delta = p1._add(p2)._divideBy(2)._subtract(this._centerPoint);
  \t\t\tif (scale === 1 && delta.x === 0 && delta.y === 0) { return; }
  \t\t\tthis._center = map.unproject(map.project(this._pinchStartLatLng, this._zoom).subtract(delta), this._zoom);
  \t\t}

  \t\tif (!this._moved) {
  \t\t\tmap._moveStart(true, false);
  \t\t\tthis._moved = true;
  \t\t}

  \t\tcancelAnimFrame(this._animRequest);

  \t\tvar moveFn = bind(map._move, map, this._center, this._zoom, {pinch: true, round: false}, undefined);
  \t\tthis._animRequest = requestAnimFrame(moveFn, this, true);

  \t\tpreventDefault(e);
  \t},

  \t_onTouchEnd: function () {
  \t\tif (!this._moved || !this._zooming) {
  \t\t\tthis._zooming = false;
  \t\t\treturn;
  \t\t}

  \t\tthis._zooming = false;
  \t\tcancelAnimFrame(this._animRequest);

  \t\toff(document, 'touchmove', this._onTouchMove, this);
  \t\toff(document, 'touchend touchcancel', this._onTouchEnd, this);

  \t\t// Pinch updates GridLayers' levels only when zoomSnap is off, so zoomSnap becomes noUpdate.
  \t\tif (this._map.options.zoomAnimation) {
  \t\t\tthis._map._animateZoom(this._center, this._map._limitZoom(this._zoom), true, this._map.options.zoomSnap);
  \t\t} else {
  \t\t\tthis._map._resetView(this._center, this._map._limitZoom(this._zoom));
  \t\t}
  \t}
  });

  // @section Handlers
  // @property touchZoom: Handler
  // Touch zoom handler.
  Map.addInitHook('addHandler', 'touchZoom', TouchZoom);

  Map.BoxZoom = BoxZoom;
  Map.DoubleClickZoom = DoubleClickZoom;
  Map.Drag = Drag;
  Map.Keyboard = Keyboard;
  Map.ScrollWheelZoom = ScrollWheelZoom;
  Map.TapHold = TapHold;
  Map.TouchZoom = TouchZoom;

  exports.Bounds = Bounds;
  exports.Browser = Browser;
  exports.CRS = CRS;
  exports.Canvas = Canvas;
  exports.Circle = Circle;
  exports.CircleMarker = CircleMarker;
  exports.Class = Class;
  exports.Control = Control;
  exports.DivIcon = DivIcon;
  exports.DivOverlay = DivOverlay;
  exports.DomEvent = DomEvent;
  exports.DomUtil = DomUtil;
  exports.Draggable = Draggable;
  exports.Evented = Evented;
  exports.FeatureGroup = FeatureGroup;
  exports.GeoJSON = GeoJSON;
  exports.GridLayer = GridLayer;
  exports.Handler = Handler;
  exports.Icon = Icon;
  exports.ImageOverlay = ImageOverlay;
  exports.LatLng = LatLng;
  exports.LatLngBounds = LatLngBounds;
  exports.Layer = Layer;
  exports.LayerGroup = LayerGroup;
  exports.LineUtil = LineUtil;
  exports.Map = Map;
  exports.Marker = Marker;
  exports.Mixin = Mixin;
  exports.Path = Path;
  exports.Point = Point;
  exports.PolyUtil = PolyUtil;
  exports.Polygon = Polygon;
  exports.Polyline = Polyline;
  exports.Popup = Popup;
  exports.PosAnimation = PosAnimation;
  exports.Projection = index;
  exports.Rectangle = Rectangle;
  exports.Renderer = Renderer;
  exports.SVG = SVG;
  exports.SVGOverlay = SVGOverlay;
  exports.TileLayer = TileLayer;
  exports.Tooltip = Tooltip;
  exports.Transformation = Transformation;
  exports.Util = Util;
  exports.VideoOverlay = VideoOverlay;
  exports.bind = bind;
  exports.bounds = toBounds;
  exports.canvas = canvas;
  exports.circle = circle;
  exports.circleMarker = circleMarker;
  exports.control = control;
  exports.divIcon = divIcon;
  exports.extend = extend;
  exports.featureGroup = featureGroup;
  exports.geoJSON = geoJSON;
  exports.geoJson = geoJson;
  exports.gridLayer = gridLayer;
  exports.icon = icon;
  exports.imageOverlay = imageOverlay;
  exports.latLng = toLatLng;
  exports.latLngBounds = toLatLngBounds;
  exports.layerGroup = layerGroup;
  exports.map = createMap;
  exports.marker = marker;
  exports.point = toPoint;
  exports.polygon = polygon;
  exports.polyline = polyline;
  exports.popup = popup;
  exports.rectangle = rectangle;
  exports.setOptions = setOptions;
  exports.stamp = stamp;
  exports.svg = svg;
  exports.svgOverlay = svgOverlay;
  exports.tileLayer = tileLayer;
  exports.tooltip = tooltip;
  exports.transformation = toTransformation;
  exports.version = version;
  exports.videoOverlay = videoOverlay;

  var oldL = window.L;
  exports.noConflict = function() {
  \twindow.L = oldL;
  \treturn this;
  }
  // Always export us to window global (see #2364)
  window.L = exports;

}));
//# sourceMappingURL=leaflet-src.js.map


/***/ }),

/***/ \"./node_modules/bootstrap-table/dist/bootstrap-table.min.css\":
/*!*******************************************************************!*\\
  !*** ./node_modules/bootstrap-table/dist/bootstrap-table.min.css ***!
  \\*******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

\"use strict\";
__webpack_require__.r(__webpack_exports__);
// extracted by mini-css-extract-plugin


/***/ }),

/***/ \"./node_modules/leaflet/dist/leaflet.css\":
/*!***********************************************!*\\
  !*** ./node_modules/leaflet/dist/leaflet.css ***!
  \\***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

\"use strict\";
__webpack_require__.r(__webpack_exports__);
// extracted by mini-css-extract-plugin


/***/ })

}]);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwLXRhYmxlL2Rpc3QvYm9vdHN0cmFwLXRhYmxlLWxvY2FsZS1hbGwubWluLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9ib290c3RyYXAtdGFibGUvZGlzdC9ib290c3RyYXAtdGFibGUuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2FycmF5LWZpbGwuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2FycmF5LXJlZHVjZS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvZW5naW5lLWlzLW5vZGUuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2luaGVyaXQtaWYtcmVxdWlyZWQuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL251bWJlci1wYXJzZS1mbG9hdC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvc2FtZS12YWx1ZS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvc2V0LXNwZWNpZXMuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL3N0cmluZy1yZXBlYXQuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL3RoaXMtbnVtYmVyLXZhbHVlLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMuYXJyYXkuZmlsbC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLmFycmF5LmZpbmQuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lcy5hcnJheS5pbmNsdWRlcy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLmFycmF5LmluZGV4LW9mLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMuYXJyYXkuaXMtYXJyYXkuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lcy5hcnJheS5yZWR1Y2UuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lcy5hcnJheS5zb21lLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMuYXJyYXkuc3BsaWNlLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMuZnVuY3Rpb24uYmluZC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLm51bWJlci5jb25zdHJ1Y3Rvci5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLm51bWJlci50by1maXhlZC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLnBhcnNlLWZsb2F0LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMucmVnZXhwLmNvbnN0cnVjdG9yLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMucmVnZXhwLnRvLXN0cmluZy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLnN0cmluZy5zZWFyY2guanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy93ZWIudGltZXJzLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9sZWFmbGV0L2Rpc3QvbGVhZmxldC1zcmMuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC10YWJsZS9kaXN0L2Jvb3RzdHJhcC10YWJsZS5taW4uY3NzP2E1ZTMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2xlYWZsZXQvZGlzdC9sZWFmbGV0LmNzcz8wNDJmIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxlQUFlLEtBQW9ELEdBQUcsbUJBQU8sQ0FBQyxvREFBUSxHQUFHLENBQTBILENBQUMsbUJBQW1CLGFBQWEsY0FBYywrQ0FBK0MsV0FBVyw2R0FBNkcscUJBQU0sQ0FBQyxxQkFBTSxrQ0FBa0MsZ0JBQWdCLFlBQVksV0FBVyxzQkFBc0Isa0JBQWtCLDBCQUEwQix3SkFBd0osWUFBWSw0Q0FBNEMsSUFBSSxZQUFZLFNBQVMsVUFBVSxrQkFBa0Isa0NBQWtDLElBQUksZUFBZSxVQUFVLEtBQUssT0FBTywyREFBMkQsY0FBYyxJQUFJLGdCQUFnQixnQkFBZ0Isd0JBQXdCLEdBQUcsaUJBQWlCLE9BQU8sK0RBQStELEtBQUssd0JBQXdCLDZCQUE2Qiw0QkFBNEIsMkNBQTJDLGVBQWUsNENBQTRDLHNCQUFzQixzREFBc0QsU0FBUyxlQUFlLGVBQWUsZUFBZSx1REFBdUQsaUJBQWlCLGtCQUFrQixRQUFRLGlFQUFpRSw2REFBNkQsa0VBQWtFLDJEQUEyRCxLQUFLLGdDQUFnQyxtQkFBbUIsOERBQThELGdFQUFnRSxPQUFPLGVBQWUsVUFBVSxJQUFJLE1BQU0sd0NBQXdDLG9CQUFvQiwwQkFBMEIsY0FBYyxVQUFVLHlDQUF5QyxlQUFlLHdEQUF3RCxTQUFTLDRCQUE0QixzQkFBc0IsNkJBQTZCLGdCQUFnQixVQUFVLG1FQUFtRSxxQ0FBcUMscUJBQXFCLHVCQUF1QixpQkFBaUIsZ0JBQWdCLGlCQUFpQixJQUFJLFNBQVMsU0FBUyxPQUFPLFNBQVMsc0NBQXNDLHNCQUFzQixpRUFB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O0FBQzVELEtBQUs7QUFDTDs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLHdFQUF3RTtBQUNuRjtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLDBCQUEwQjtBQUMvQztBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxpRUFBaUU7QUFDNUU7QUFDQSxHQUFHOztBQUVIOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7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QTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHNDQUFzQzs7QUFFdEM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkI7QUFDM0I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUssZ0JBQWdCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7O0FBR0E7QUFDQTtBQUNBLFdBQVcsK0JBQStCO0FBQzFDO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7O0FBRUE7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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQjtBQUNuQjtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdDQUFnQztBQUNoQyxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwrQ0FBK0MsZUFBZSxFQUFFOztBQUVoRTtBQUNBO0FBQ0EsV0FBVyw0REFBNEQ7QUFDdkU7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDs7Ozs7OztBQU9BO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLFdBQVcsMkZBQTJGO0FBQ3RHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7Ozs7Ozs7QUFPQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxXQUFXLHVGQUF1RjtBQUNsRztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSw0RkFBNEYsYUFBYTtBQUN6RztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLE9BQU87O0FBRVA7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwyQkFBMkIsK0JBQStCO0FBQzFEOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0EsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSw0QkFBNEIsaUNBQWlDO0FBQzdEO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLE9BQU87QUFDUDtBQUNBOztBQUVBLHFCQUFxQixvQkFBb0I7QUFDekM7O0FBRUEsdUJBQXVCLGNBQWM7QUFDckM7QUFDQTtBQUNBOztBQUVBLHNCQUFzQixxQkFBcUI7QUFDM0M7QUFDQTs7QUFFQTtBQUNBLDhCQUE4QixpQ0FBaUM7QUFDL0Q7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0EsbUNBQW1DOztBQUVuQztBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTs7QUFFQSw0QkFBNEIsY0FBYztBQUMxQyw2QkFBNkIsYUFBYTtBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsNEJBQTRCLGlDQUFpQztBQUM3RDs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsZ0NBQWdDLGlDQUFpQztBQUNqRTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQjs7QUFFbkI7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsNENBQTRDLHFDQUFxQztBQUNqRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLGdDQUFnQyxpQ0FBaUM7QUFDakU7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsdUNBQXVDLHFCQUFxQjtBQUM1RDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0Esd0NBQXdDLHNCQUFzQixzQkFBc0Isd0JBQXdCLHdCQUF3Qix3QkFBd0I7QUFDNUo7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLGtDQUFrQyxzQkFBc0Isc0JBQXNCLHdCQUF3Qix3QkFBd0IseUJBQXlCO0FBQ3ZKOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsbUVBQW1FLDhCQUE4QjtBQUNqRztBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsNEJBQTRCLGlDQUFpQztBQUM3RDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDRCQUE0QixpQ0FBaUM7QUFDN0Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCOztBQUVyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCOztBQUVyQixnQkFBZ0IsaUJBQWlCLE9BQU87QUFDeEMsV0FBVzs7O0FBR1gsMEJBQTBCLGdCQUFnQjtBQUMxQyw0QkFBNEIsZ0JBQWdCO0FBQzVDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHlDQUF5Qzs7QUFFekM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxPQUFPO0FBQ1A7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87OztBQUdQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTzs7O0FBR1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0EsNEJBQTRCLGlDQUFpQztBQUM3RDs7QUFFQSw0REFBNEQsMkJBQTJCO0FBQ3ZGOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw0RUFBNEU7QUFDNUU7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSwyQkFBMkIsU0FBUztBQUNwQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRFQUE0RTs7QUFFNUU7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbURBQW1EOztBQUVuRDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0RBQWdEOztBQUVoRDtBQUNBO0FBQ0E7O0FBRUEsdURBQXVEO0FBQ3ZEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsV0FBVztBQUNYOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3REFBd0Q7O0FBRXhEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsV0FBVztBQUNYLFNBQVMsRUFBRTs7QUFFWDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdURBQXVEO0FBQ3ZELHNEQUFzRDtBQUN0RCwwREFBMEQ7QUFDMUQsOENBQThDOztBQUU5QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaUZBQWlGLDZCQUE2QjtBQUM5RztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSx5UUFBeVE7QUFDelE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7O0FBRVg7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSx3RUFBd0U7O0FBRXhFO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7O0FBRUE7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLGFBQWE7QUFDYjtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0EsV0FBVztBQUNYO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztB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Q0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsV0FBVzs7QUFFWDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLHVCQUF1QixVQUFVO0FBQ2pDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx3QkFBd0IsU0FBUztBQUNqQztBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtB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QTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7O0FBRUE7QUFDQTtBQUNBLHVFQUF1RSxpQ0FBaUM7QUFDeEc7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVztBQUNYOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EseUJBQXlCOztBQUV6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUEsa0RBQWtELFFBQVE7QUFDMUQ7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsOEJBQThCLGlDQUFpQztBQUMvRDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx5QkFBeUIsUUFBUTtBQUNqQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsOEJBQThCLGlDQUFpQztBQUMvRDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLDhCQUE4QixpQ0FBaUM7QUFDL0Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSw4QkFBOEIsaUNBQWlDO0FBQy9EOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLHFCQUFxQixtQkFBbUI7QUFDeEMsdUJBQXVCLG1CQUFtQjtBQUMxQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxpQ0FBaUMsbUNBQW1DO0FBQ3BFO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBLFdBQVc7QUFDWDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHVDQUF1QyxhQUFhO0FBQ3BEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEdBQTRHO0FBQzVHO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsOERBQThEO0FBQzlEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSx1QkFBdUIsZ0JBQWdCO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUEsdUJBQXVCLGdCQUFnQjtBQUN2QztBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMEJBQTBCO0FBQzFCO0FBQ0EsMEJBQTBCO0FBQzFCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7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QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsY0FBYzs7QUFFN0I7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOzs7O0FBSUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDJDQUEyQyx5QkFBeUIsT0FBTyxzQ0FBc0M7O0FBRWpIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IsYUFBYTs7QUFFckM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx1QkFBdUI7QUFDdkI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQ0FBMEM7QUFDMUM7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUM7QUFDdkM7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwwQkFBMEI7QUFDMUI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0osR0FBRzs7QUFFSCw0QkFBNEI7QUFDNUI7QUFDQSxHQUFHOztBQUVILG9CQUFvQjtBQUNwQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0NBQWtDLFNBQVM7QUFDM0M7O0FBRUEscUNBQXFDLFVBQVU7QUFDL0M7QUFDQTtBQUNBOztBQUVBLG9DQUFvQztBQUNwQztBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLDJCQUEyQjtBQUMzQjs7QUFFQSw4QkFBOEI7QUFDOUI7O0FBRUEsNkJBQTZCO0FBQzdCOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsa0NBQWtDO0FBQ2xDOztBQUVBO0FBQ0Esa0ZBQWtGO0FBQ2xGLHFDQUFxQztBQUNyQzs7QUFFQSw4QkFBOEI7QUFDOUI7O0FBRUEsK0JBQStCO0FBQy9COztBQUVBLDhCQUE4QjtBQUM5Qjs7QUFFQSwrQkFBK0I7QUFDL0I7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBLDRCQUE0QjtBQUM1Qjs7QUFFQSw2QkFBNkI7QUFDN0I7O0FBRUEsaUNBQWlDO0FBQ2pDOztBQUVBLGdDQUFnQztBQUNoQzs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsK0JBQStCO0FBQy9COztBQUVBLHFDQUFxQztBQUNyQzs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsb0NBQW9DO0FBQ3BDOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QztBQUN2Qyx1QkFBdUI7QUFDdkI7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUEsSUFBSTtBQUNKO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSCw0QkFBNEI7QUFDNUI7O0FBRUEsNEJBQTRCO0FBQzVCOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwrREFBK0QsUUFBUTs7QUFFdkU7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOEJBQThCO0FBQzlCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUI7QUFDdkI7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlDQUF5QyxTQUFTO0FBQ2xEO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLHNCQUFzQixRQUFRO0FBQzlCOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGtCQUFrQixrQkFBa0I7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EseUNBQXlDOztBQUV6QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQSxrQkFBa0IsYUFBYTs7QUFFL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCLFFBQVE7O0FBRXBDO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtEQUErRDtBQUMvRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUosdUNBQXVDO0FBQ3ZDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDJEQUEyRCxZQUFZO0FBQ3ZFOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOzs7QUFHSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQSw2QkFBNkIseUJBQXlCO0FBQ3RELDRCQUE0QixxREFBcUQ7QUFDakY7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaURBQWlELGNBQWM7QUFDL0QsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLDBDQUEwQyxjQUFjO0FBQ3hELElBQUk7O0FBRUo7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0Esc0NBQXNDO0FBQ3RDLDZDQUE2QyxhQUFhO0FBQzFELElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEs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LCtDQUErQzs7QUFFaEY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzREFBc0Q7QUFDdEQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsMkRBQTJEO0FBQzNEO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7OztBQUdKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBLGlEQUFpRDtBQUNqRDtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0EsaURBQWlEO0FBQ2pEO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQztBQUNyQztBQUNBLElBQUk7OztBQUdKOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7O0FBR0o7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtDQUErQztBQUMvQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSywrQkFBK0I7QUFDcEM7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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Q0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0EsMkNBQTJDO0FBQzNDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsbUJBQW1CLHlCQUF5QjtBQUM1QztBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQSxtQkFBbUIseUJBQXlCO0FBQzVDO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQSxtQkFBbUIseUJBQXlCOztBQUU1QztBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQSwyQkFBMkIsYUFBYTs7QUFFeEM7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGVBQWUseUJBQXlCO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxtQ0FBbUMsUUFBUTtBQUMzQztBQUNBOztBQUVBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBOztBQUVBO0FBQ0EsZUFBZSwwQkFBMEI7QUFDekM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLHdCQUF3QjtBQUN2QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxtQ0FBbUMsUUFBUTtBQUMzQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLHVFQUF1RTtBQUN2RTtBQUNBLG1EQUFtRDs7QUFFbkQ7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FB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QUFDQTs7QUFFQTs7QUFFQTtBQUNBLCtCQUErQixhQUFhO0FBQzVDO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBOztBQUVBLHdDQUF3QyxTQUFTO0FBQ2pEO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBLHFDQUFxQyxTQUFTO0FBQzlDO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQkFBK0IsNENBQTRDLEVBQUU7QUFDN0U7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxrQ0FBa0MsYUFBYTtBQUMvQyxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxxQ0FBcUMsYUFBYTtBQUNsRCxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBLGdDQUFnQyxhQUFhO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBLG9EQUFvRDtBQUNwRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKLCtCQUErQjtBQUMvQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBLCtDQUErQzs7QUFFL0M7QUFDQTtBQUNBLGVBQWUsYUFBYTtBQUM1QjtBQUNBLGdCQUFnQixXQUFXO0FBQzNCO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLDBCQUEwQixlQUFlOztBQUV6QztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSw4QkFBOEIsMkNBQTJDO0FBQ3pFLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQSxJQUFJOztBQUVKOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjs7QUFFQSxvQ0FBb0MsUUFBUTs7QUFFNUM7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsZUFBZSxRQUFROztBQUV2QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsOEJBQThCLDJDQUEyQztBQUN6RSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCLFlBQVk7QUFDekM7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0Isa0JBQWtCLGdCQUFnQjtBQUMxRDtBQUNBO0FBQ0E7O0FBRUEscUNBQXFDLGdEQUFnRDs7QUFFckY7QUFDQTtBQUNBLDhCQUE4QjtBQUM5QjtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0Esa0RBQWtEO0FBQ2xEOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5Q0FBeUMsYUFBYTtBQUN0RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsOENBQThDLFVBQVU7QUFDeEQ7O0FBRUEseUNBQXlDLFNBQVM7QUFDbEQ7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQSxJQUFJOztBQUVKLHFFQUFxRTtBQUNyRTtBQUNBO0FBQ0E7O0FBRUEseUNBQXlDLFNBQVM7QUFDbEQ7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGdCQUFnQixTQUFTO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdCQUFnQixTQUFTO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsZ0RBQWdELFNBQVM7QUFDekQ7O0FBRUEsc0NBQXNDLGNBQWM7QUFDcEQ7O0FBRUEscUJBQXFCLFVBQVU7O0FBRS9CO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHVDQUF1QyxTQUFTO0FBQ2hEO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0EscUJBQXFCLFFBQVE7O0FBRTdCO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUEseURBQXlELGNBQWM7O0FBRXZFO0FBQ0EseUNBQXlDLFNBQVM7QUFDbEQ7O0FBRUEsa0RBQWtELFVBQVU7QUFDNUQsaUNBQWlDLFVBQVU7O0FBRTNDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsYUFBYTtBQUNwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzREFBc0QsU0FBUztBQUMvRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx5REFBeUQsY0FBYzs7QUFFdkU7QUFDQSx5Q0FBeUMsU0FBUztBQUNsRDs7QUFFQSxrREFBa0QsVUFBVTtBQUM1RDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0EsTUFBTTtBQUNOO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx1Q0FBdUMsU0FBUztBQUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLHFEQUFxRCxhQUFhOztBQUVsRTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLG9DQUFvQyxTQUFTO0FBQzdDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaURBQWlELFNBQVM7QUFDMUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNOztBQUVOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwrQ0FBK0MsU0FBUztBQUN4RDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwrQ0FBK0MsU0FBUztBQUN4RDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsd0NBQXdDLFNBQVM7QUFDakQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYSxrQkFBa0Isc0JBQXNCO0FBQ3JEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxrQkFBa0I7QUFDbEI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUosZ0RBQWdEO0FBQ2hEO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw2QkFBNkIsd0NBQXdDO0FBQ3JFLGlDQUFpQyx1Q0FBdUM7O0FBRXhFO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBOztBQUVBO0FBQ0EsNkJBQTZCLHdDQUF3QztBQUNyRSxpQ0FBaUMsdUNBQXVDOztBQUV4RTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0IsMkJBQTJCO0FBQy9DO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLDhCQUE4Qix5QkFBeUI7O0FBRXZEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLHNCQUFzQjtBQUN6QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw2QkFBNkIsdUNBQXVDO0FBQ3BFLGlDQUFpQyxzQ0FBc0M7O0FBRXZFO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFEQUFxRDtBQUNyRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFD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QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQyxxREFBcUQ7QUFDM0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkIsY0FBYzs7QUFFM0M7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxjQUFjO0FBQ3JEO0FBQ0EsSUFBSTs7QUFFSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOEJBQThCLGNBQWM7O0FBRTVDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3Q0FBd0MsY0FBYztBQUN0RDtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSixnQ0FBZ0M7O0FBRWhDLDZCQUE2Qjs7QUFFN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBLGdEQUFnRCxRQUFRO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOzs7QUFHSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBOztBQUVBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCLHlCQUF5QjtBQUN0RDtBQUNBO0FBQ0EsZ0NBQWdDLGFBQWE7QUFDN0M7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsc0JBQXNCO0FBQ3RCLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7O0FBRUE7QUFDQSxtREFBbUQ7O0FBRW5ELGdEQUFnRCxTQUFTOztBQUV6RDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQSxxQkFBcUIsUUFBUTs7QUFFN0I7QUFDQSx3QkFBd0IsUUFBUTs7QUFFaEM7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSx5Q0FBeUMsVUFBVTs7QUFFbkQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzQ0FBc0Msb0JBQW9COztBQUUxRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7O0FBRUE7QUFDQSwwQkFBMEIsUUFBUTs7QUFFbEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKOztBQUVBO0FBQ0E7O0FBRUEsNkJBQTZCLGtCQUFrQjs7QUFFL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxJQUFJOztBQUVKOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7O0FBRUEsdUJBQXVCLGVBQWU7QUFDdEMsd0JBQXdCLGVBQWU7O0FBRXZDO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FB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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLGdCQUFnQixRQUFROztBQUV4QjtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKOztBQUVBOztBQUVBLDZCQUE2Qjs7QUFFN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLDJCQUEyQjs7QUFFM0I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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Q0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCLDRCQUE0QjtBQUN0RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQSwrREFBK0QsY0FBYzs7QUFFN0U7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLElBQUk7O0FBRUo7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLElBQUk7O0FBRUo7QUFDQSw4Q0FBOEMsUUFBUTs7QUFFdEQ7O0FBRUEsdUJBQXVCLFFBQVE7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwwQkFBMEIsc0JBQXNCO0FBQ2hELElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNOztBQUVOO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7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YXAtdGFibGUtbG9jYWxlLWFsbF9taW5fanMtbm9kZV9tb2R1bGVzX2Jvb3QtM2YwZmQwLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gICogYm9vdHN0cmFwLXRhYmxlIC0gQW4gZXh0ZW5kZWQgdGFibGUgdG8gaW50ZWdyYXRpb24gd2l0aCBzb21lIG9mIHRoZSBtb3N0IHdpZGVseSB1c2VkIENTUyBmcmFtZXdvcmtzLiAoU3VwcG9ydHMgQm9vdHN0cmFwLCBTZW1hbnRpYyBVSSwgQnVsbWEsIE1hdGVyaWFsIERlc2lnbiwgRm91bmRhdGlvbilcbiAgKlxuICAqIEB2ZXJzaW9uIHYxLjE4LjNcbiAgKiBAaG9tZXBhZ2UgaHR0cHM6Ly9ib290c3RyYXAtdGFibGUuY29tXG4gICogQGF1dGhvciB3ZW56aGl4aW4gPHdlbnpoaXhpbjIwMTBAZ21haWwuY29tPiAoaHR0cDovL3dlbnpoaXhpbi5uZXQuY24vKVxuICAqIEBsaWNlbnNlIE1JVFxuICAqL1xuXG4hZnVuY3Rpb24odCxuKXtcIm9iamVjdFwiPT10eXBlb2YgZXhwb3J0cyYmXCJ1bmRlZmluZWRcIiE9dHlwZW9mIG1vZHVsZT9uKHJlcXVpcmUoXCJqcXVlcnlcIikpOlwiZnVuY3Rpb25cIj09dHlwZW9mIGRlZmluZSYmZGVmaW5lLmFtZD9kZWZpbmUoW1wianF1ZXJ5XCJdLG4pOm4oKHQ9XCJ1bmRlZmluZWRcIiE9dHlwZW9mIGdsb2JhbFRoaXM/Z2xvYmFsVGhpczp0fHxzZWxmKS5qUXVlcnkpfSh0aGlzLChmdW5jdGlvbih0KXtcInVzZSBzdHJpY3RcIjtmdW5jdGlvbiBuKHQpe3JldHVybiB0JiZcIm9iamVjdFwiPT10eXBlb2YgdCYmXCJkZWZhdWx0XCJpbiB0P3Q6e2RlZmF1bHQ6dH19dmFyIG89bih0KSxyPVwidW5kZWZpbmVkXCIhPXR5cGVvZiBnbG9iYWxUaGlzP2dsb2JhbFRoaXM6XCJ1bmRlZmluZWRcIiE9dHlwZW9mIHdpbmRvdz93aW5kb3c6XCJ1bmRlZmluZWRcIiE9dHlwZW9mIGdsb2JhbD9nbG9iYWw6XCJ1bmRlZmluZWRcIiE9dHlwZW9mIHNlbGY/c2VsZjp7fTtmdW5jdGlvbiBlKHQsbil7cmV0dXJuIHQobj17ZXhwb3J0czp7fX0sbi5leHBvcnRzKSxuLmV4cG9ydHN9dmFyIGE9ZnVuY3Rpb24odCl7cmV0dXJuIHQmJnQuTWF0aD09TWF0aCYmdH0saT1hKFwib2JqZWN0XCI9PXR5cGVvZiBnbG9iYWxUaGlzJiZnbG9iYWxUaGlzKXx8YShcIm9iamVjdFwiPT10eXBlb2Ygd2luZG93JiZ3aW5kb3cpfHxhKFwib2JqZWN0XCI9PXR5cGVvZiBzZWxmJiZzZWxmKXx8YShcIm9iamVjdFwiPT10eXBlb2YgciYmcil8fGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXN9KCl8fEZ1bmN0aW9uKFwicmV0dXJuIHRoaXNcIikoKSx1PWZ1bmN0aW9uKHQpe3RyeXtyZXR1cm4hIXQoKX1jYXRjaCh0KXtyZXR1cm4hMH19LGY9IXUoKGZ1bmN0aW9uKCl7cmV0dXJuIDchPU9iamVjdC5kZWZpbmVQcm9wZXJ0eSh7fSwxLHtnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gN319KVsxXX0pKSxjPXt9LnByb3BlcnR5SXNFbnVtZXJhYmxlLGw9T2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcixzPXtmOmwmJiFjLmNhbGwoezE6Mn0sMSk/ZnVuY3Rpb24odCl7dmFyIG49bCh0aGlzLHQpO3JldHVybiEhbiYmbi5lbnVtZXJhYmxlfTpjfSxtPWZ1bmN0aW9uKHQsbil7cmV0dXJue2VudW1lcmFibGU6ISgxJnQpLGNvbmZpZ3VyYWJsZTohKDImdCksd3JpdGFibGU6ISg0JnQpLHZhbHVlOm59fSxnPXt9LnRvU3RyaW5nLGQ9ZnVuY3Rpb24odCl7cmV0dXJuIGcuY2FsbCh0KS5zbGljZSg4LC0xKX0saD1cIlwiLnNwbGl0LHA9dSgoZnVuY3Rpb24oKXtyZXR1cm4hT2JqZWN0KFwielwiKS5wcm9wZXJ0eUlzRW51bWVyYWJsZSgwKX0pKT9mdW5jdGlvbih0KXtyZXR1cm5cIlN0cmluZ1wiPT1kKHQpP2guY2FsbCh0LFwiXCIpOk9iamVjdCh0KX06T2JqZWN0LHc9ZnVuY3Rpb24odCl7aWYobnVsbD09dCl0aHJvdyBUeXBlRXJyb3IoXCJDYW4ndCBjYWxsIG1ldGhvZCBvbiBcIit0KTtyZXR1cm4gdH0sUz1mdW5jdGlvbih0KXtyZXR1cm4gcCh3KHQpKX0sUD1mdW5jdGlvbih0KXtyZXR1cm5cIm9iamVjdFwiPT10eXBlb2YgdD9udWxsIT09dDpcImZ1bmN0aW9uXCI9PXR5cGVvZiB0fSxUPWZ1bmN0aW9uKHQsbil7aWYoIVAodCkpcmV0dXJuIHQ7dmFyIG8scjtpZihuJiZcImZ1bmN0aW9uXCI9PXR5cGVvZihvPXQudG9TdHJpbmcpJiYhUChyPW8uY2FsbCh0KSkpcmV0dXJuIHI7aWYoXCJmdW5jdGlvblwiPT10eXBlb2Yobz10LnZhbHVlT2YpJiYhUChyPW8uY2FsbCh0KSkpcmV0dXJuIHI7aWYoIW4mJlwiZnVuY3Rpb25cIj09dHlwZW9mKG89dC50b1N0cmluZykmJiFQKHI9by5jYWxsKHQpKSlyZXR1cm4gcjt0aHJvdyBUeXBlRXJyb3IoXCJDYW4ndCBjb252ZXJ0IG9iamVjdCB0byBwcmltaXRpdmUgdmFsdWVcIil9LFI9e30uaGFzT3duUHJvcGVydHksQz1mdW5jdGlvbih0LG4pe3JldHVybiBSLmNhbGwodCxuKX0sYj1pLmRvY3VtZW50LHY9UChiKSYmUChiLmNyZWF0ZUVsZW1lbnQpLEE9IWYmJiF1KChmdW5jdGlvbigpe3JldHVybiA3IT1PYmplY3QuZGVmaW5lUHJvcGVydHkoKHQ9XCJkaXZcIix2P2IuY3JlYXRlRWxlbWVudCh0KTp7fSksXCJhXCIse2dldDpmdW5jdGlvbigpe3JldHVybiA3fX0pLmE7dmFyIHR9KSkseD1PYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yLEY9e2Y6Zj94OmZ1bmN0aW9uKHQsbil7aWYodD1TKHQpLG49VChuLCEwKSxBKXRyeXtyZXR1cm4geCh0LG4pfWNhdGNoKHQpe31pZihDKHQsbikpcmV0dXJuIG0oIXMuZi5jYWxsKHQsbiksdFtuXSl9fSx5PWZ1bmN0aW9uKHQpe2lmKCFQKHQpKXRocm93IFR5cGVFcnJvcihTdHJpbmcodCkrXCIgaXMgbm90IGFuIG9iamVjdFwiKTtyZXR1cm4gdH0saz1PYmplY3QuZGVmaW5lUHJvcGVydHksSD17ZjpmP2s6ZnVuY3Rpb24odCxuLG8pe2lmKHkodCksbj1UKG4sITApLHkobyksQSl0cnl7cmV0dXJuIGsodCxuLG8pfWNhdGNoKHQpe31pZihcImdldFwiaW4gb3x8XCJzZXRcImluIG8pdGhyb3cgVHlwZUVycm9yKFwiQWNjZXNzb3JzIG5vdCBzdXBwb3J0ZWRcIik7cmV0dXJuXCJ2YWx1ZVwiaW4gbyYmKHRbbl09by52YWx1ZSksdH19LE89Zj9mdW5jdGlvbih0LG4sbyl7cmV0dXJuIEguZih0LG4sbSgxLG8pKX06ZnVuY3Rpb24odCxuLG8pe3JldHVybiB0W25dPW8sdH0sTT1mdW5jdGlvbih0LG4pe3RyeXtPKGksdCxuKX1jYXRjaChvKXtpW3RdPW59cmV0dXJuIG59LEU9XCJfX2NvcmUtanNfc2hhcmVkX19cIixOPWlbRV18fE0oRSx7fSksRD1GdW5jdGlvbi50b1N0cmluZztcImZ1bmN0aW9uXCIhPXR5cGVvZiBOLmluc3BlY3RTb3VyY2UmJihOLmluc3BlY3RTb3VyY2U9ZnVuY3Rpb24odCl7cmV0dXJuIEQuY2FsbCh0KX0pO3ZhciB6LEwsaixCLFU9Ti5pbnNwZWN0U291cmNlLEo9aS5XZWFrTWFwLEc9XCJmdW5jdGlvblwiPT10eXBlb2YgSiYmL25hdGl2ZSBjb2RlLy50ZXN0KFUoSikpLFY9ZSgoZnVuY3Rpb24odCl7KHQuZXhwb3J0cz1mdW5jdGlvbih0LG4pe3JldHVybiBOW3RdfHwoTlt0XT12b2lkIDAhPT1uP246e30pfSkoXCJ2ZXJzaW9uc1wiLFtdKS5wdXNoKHt2ZXJzaW9uOlwiMy45LjFcIixtb2RlOlwiZ2xvYmFsXCIsY29weXJpZ2h0OlwiwqkgMjAyMSBEZW5pcyBQdXNoa2FyZXYgKHpsb2lyb2NrLnJ1KVwifSl9KSksWj0wLEk9TWF0aC5yYW5kb20oKSxxPWZ1bmN0aW9uKHQpe3JldHVyblwiU3ltYm9sKFwiK1N0cmluZyh2b2lkIDA9PT10P1wiXCI6dCkrXCIpX1wiKygrK1orSSkudG9TdHJpbmcoMzYpfSxLPVYoXCJrZXlzXCIpLFc9e30sWT1pLldlYWtNYXA7aWYoRyl7dmFyIF89Ti5zdGF0ZXx8KE4uc3RhdGU9bmV3IFkpLFE9Xy5nZXQsWD1fLmhhcywkPV8uc2V0O3o9ZnVuY3Rpb24odCxuKXtyZXR1cm4gbi5mYWNhZGU9dCwkLmNhbGwoXyx0LG4pLG59LEw9ZnVuY3Rpb24odCl7cmV0dXJuIFEuY2FsbChfLHQpfHx7fX0saj1mdW5jdGlvbih0KXtyZXR1cm4gWC5jYWxsKF8sdCl9fWVsc2V7dmFyIHR0PUtbQj1cInN0YXRlXCJdfHwoS1tCXT1xKEIpKTtXW3R0XT0hMCx6PWZ1bmN0aW9uKHQsbil7cmV0dXJuIG4uZmFjYWRlPXQsTyh0LHR0LG4pLG59LEw9ZnVuY3Rpb24odCl7cmV0dXJuIEModCx0dCk/dFt0dF06e319LGo9ZnVuY3Rpb24odCl7cmV0dXJuIEModCx0dCl9fXZhciBudCxvdCxydD17c2V0OnosZ2V0OkwsaGFzOmosZW5mb3JjZTpmdW5jdGlvbih0KXtyZXR1cm4gaih0KT9MKHQpOnoodCx7fSl9LGdldHRlckZvcjpmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24obil7dmFyIG87aWYoIVAobil8fChvPUwobikpLnR5cGUhPT10KXRocm93IFR5cGVFcnJvcihcIkluY29tcGF0aWJsZSByZWNlaXZlciwgXCIrdCtcIiByZXF1aXJlZFwiKTtyZXR1cm4gb319fSxldD1lKChmdW5jdGlvbih0KXt2YXIgbj1ydC5nZXQsbz1ydC5lbmZvcmNlLHI9U3RyaW5nKFN0cmluZykuc3BsaXQoXCJTdHJpbmdcIik7KHQuZXhwb3J0cz1mdW5jdGlvbih0LG4sZSxhKXt2YXIgdSxmPSEhYSYmISFhLnVuc2FmZSxjPSEhYSYmISFhLmVudW1lcmFibGUsbD0hIWEmJiEhYS5ub1RhcmdldEdldDtcImZ1bmN0aW9uXCI9PXR5cGVvZiBlJiYoXCJzdHJpbmdcIiE9dHlwZW9mIG58fEMoZSxcIm5hbWVcIil8fE8oZSxcIm5hbWVcIixuKSwodT1vKGUpKS5zb3VyY2V8fCh1LnNvdXJjZT1yLmpvaW4oXCJzdHJpbmdcIj09dHlwZW9mIG4/bjpcIlwiKSkpLHQhPT1pPyhmPyFsJiZ0W25dJiYoYz0hMCk6ZGVsZXRlIHRbbl0sYz90W25dPWU6Tyh0LG4sZSkpOmM/dFtuXT1lOk0obixlKX0pKEZ1bmN0aW9uLnByb3RvdHlwZSxcInRvU3RyaW5nXCIsKGZ1bmN0aW9uKCl7cmV0dXJuXCJmdW5jdGlvblwiPT10eXBlb2YgdGhpcyYmbih0aGlzKS5zb3VyY2V8fFUodGhpcyl9KSl9KSksYXQ9aSxpdD1mdW5jdGlvbih0KXtyZXR1cm5cImZ1bmN0aW9uXCI9PXR5cGVvZiB0P3Q6dm9pZCAwfSx1dD1mdW5jdGlvbih0LG4pe3JldHVybiBhcmd1bWVudHMubGVuZ3RoPDI/aXQoYXRbdF0pfHxpdChpW3RdKTphdFt0XSYmYXRbdF1bbl18fGlbdF0mJmlbdF1bbl19LGZ0PU1hdGguY2VpbCxjdD1NYXRoLmZsb29yLGx0PWZ1bmN0aW9uKHQpe3JldHVybiBpc05hTih0PSt0KT8wOih0PjA/Y3Q6ZnQpKHQpfSxzdD1NYXRoLm1pbixtdD1mdW5jdGlvbih0KXtyZXR1cm4gdD4wP3N0KGx0KHQpLDkwMDcxOTkyNTQ3NDA5OTEpOjB9LGd0PU1hdGgubWF4LGR0PU1hdGgubWluLGh0PWZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbihuLG8scil7dmFyIGUsYT1TKG4pLGk9bXQoYS5sZW5ndGgpLHU9ZnVuY3Rpb24odCxuKXt2YXIgbz1sdCh0KTtyZXR1cm4gbzwwP2d0KG8rbiwwKTpkdChvLG4pfShyLGkpO2lmKHQmJm8hPW8pe2Zvcig7aT51OylpZigoZT1hW3UrK10pIT1lKXJldHVybiEwfWVsc2UgZm9yKDtpPnU7dSsrKWlmKCh0fHx1IGluIGEpJiZhW3VdPT09bylyZXR1cm4gdHx8dXx8MDtyZXR1cm4hdCYmLTF9fSxwdD17aW5jbHVkZXM6aHQoITApLGluZGV4T2Y6aHQoITEpfS5pbmRleE9mLHd0PVtcImNvbnN0cnVjdG9yXCIsXCJoYXNPd25Qcm9wZXJ0eVwiLFwiaXNQcm90b3R5cGVPZlwiLFwicHJvcGVydHlJc0VudW1lcmFibGVcIixcInRvTG9jYWxlU3RyaW5nXCIsXCJ0b1N0cmluZ1wiLFwidmFsdWVPZlwiXS5jb25jYXQoXCJsZW5ndGhcIixcInByb3RvdHlwZVwiKSxTdD17ZjpPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lc3x8ZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKHQsbil7dmFyIG8scj1TKHQpLGU9MCxhPVtdO2ZvcihvIGluIHIpIUMoVyxvKSYmQyhyLG8pJiZhLnB1c2gobyk7Zm9yKDtuLmxlbmd0aD5lOylDKHIsbz1uW2UrK10pJiYofnB0KGEsbyl8fGEucHVzaChvKSk7cmV0dXJuIGF9KHQsd3QpfX0sUHQ9e2Y6T2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9sc30sVHQ9dXQoXCJSZWZsZWN0XCIsXCJvd25LZXlzXCIpfHxmdW5jdGlvbih0KXt2YXIgbj1TdC5mKHkodCkpLG89UHQuZjtyZXR1cm4gbz9uLmNvbmNhdChvKHQpKTpufSxSdD1mdW5jdGlvbih0LG4pe2Zvcih2YXIgbz1UdChuKSxyPUguZixlPUYuZixhPTA7YTxvLmxlbmd0aDthKyspe3ZhciBpPW9bYV07Qyh0LGkpfHxyKHQsaSxlKG4saSkpfX0sQ3Q9LyN8XFwucHJvdG90eXBlXFwuLyxidD1mdW5jdGlvbih0LG4pe3ZhciBvPUF0W3Z0KHQpXTtyZXR1cm4gbz09RnR8fG8hPXh0JiYoXCJmdW5jdGlvblwiPT10eXBlb2Ygbj91KG4pOiEhbil9LHZ0PWJ0Lm5vcm1hbGl6ZT1mdW5jdGlvbih0KXtyZXR1cm4gU3RyaW5nKHQpLnJlcGxhY2UoQ3QsXCIuXCIpLnRvTG93ZXJDYXNlKCl9LEF0PWJ0LmRhdGE9e30seHQ9YnQuTkFUSVZFPVwiTlwiLEZ0PWJ0LlBPTFlGSUxMPVwiUFwiLHl0PWJ0LGt0PUYuZixIdD1BcnJheS5pc0FycmF5fHxmdW5jdGlvbih0KXtyZXR1cm5cIkFycmF5XCI9PWQodCl9LE90PWZ1bmN0aW9uKHQpe3JldHVybiBPYmplY3Qodyh0KSl9LE10PWZ1bmN0aW9uKHQsbixvKXt2YXIgcj1UKG4pO3IgaW4gdD9ILmYodCxyLG0oMCxvKSk6dFtyXT1vfSxFdD1cInByb2Nlc3NcIj09ZChpLnByb2Nlc3MpLE50PXV0KFwibmF2aWdhdG9yXCIsXCJ1c2VyQWdlbnRcIil8fFwiXCIsRHQ9aS5wcm9jZXNzLHp0PUR0JiZEdC52ZXJzaW9ucyxMdD16dCYmenQudjg7THQ/b3Q9KG50PUx0LnNwbGl0KFwiLlwiKSlbMF0rbnRbMV06TnQmJighKG50PU50Lm1hdGNoKC9FZGdlXFwvKFxcZCspLykpfHxudFsxXT49NzQpJiYobnQ9TnQubWF0Y2goL0Nocm9tZVxcLyhcXGQrKS8pKSYmKG90PW50WzFdKTt2YXIganQsQnQ9b3QmJitvdCxVdD0hIU9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMmJiF1KChmdW5jdGlvbigpe3JldHVybiFTeW1ib2wuc2hhbSYmKEV0PzM4PT09QnQ6QnQ+MzcmJkJ0PDQxKX0pKSxKdD1VdCYmIVN5bWJvbC5zaGFtJiZcInN5bWJvbFwiPT10eXBlb2YgU3ltYm9sLml0ZXJhdG9yLEd0PVYoXCJ3a3NcIiksVnQ9aS5TeW1ib2wsWnQ9SnQ/VnQ6VnQmJlZ0LndpdGhvdXRTZXR0ZXJ8fHEsSXQ9ZnVuY3Rpb24odCl7cmV0dXJuIEMoR3QsdCkmJihVdHx8XCJzdHJpbmdcIj09dHlwZW9mIEd0W3RdKXx8KFV0JiZDKFZ0LHQpP0d0W3RdPVZ0W3RdOkd0W3RdPVp0KFwiU3ltYm9sLlwiK3QpKSxHdFt0XX0scXQ9SXQoXCJzcGVjaWVzXCIpLEt0PWZ1bmN0aW9uKHQsbil7dmFyIG87cmV0dXJuIEh0KHQpJiYoXCJmdW5jdGlvblwiIT10eXBlb2Yobz10LmNvbnN0cnVjdG9yKXx8byE9PUFycmF5JiYhSHQoby5wcm90b3R5cGUpP1AobykmJm51bGw9PT0obz1vW3F0XSkmJihvPXZvaWQgMCk6bz12b2lkIDApLG5ldyh2b2lkIDA9PT1vP0FycmF5Om8pKDA9PT1uPzA6bil9LFd0PUl0KFwic3BlY2llc1wiKSxZdD1JdChcImlzQ29uY2F0U3ByZWFkYWJsZVwiKSxfdD05MDA3MTk5MjU0NzQwOTkxLFF0PVwiTWF4aW11bSBhbGxvd2VkIGluZGV4IGV4Y2VlZGVkXCIsWHQ9QnQ+PTUxfHwhdSgoZnVuY3Rpb24oKXt2YXIgdD1bXTtyZXR1cm4gdFtZdF09ITEsdC5jb25jYXQoKVswXSE9PXR9KSksJHQ9KGp0PVwiY29uY2F0XCIsQnQ+PTUxfHwhdSgoZnVuY3Rpb24oKXt2YXIgdD1bXTtyZXR1cm4odC5jb25zdHJ1Y3Rvcj17fSlbV3RdPWZ1bmN0aW9uKCl7cmV0dXJue2ZvbzoxfX0sMSE9PXRbanRdKEJvb2xlYW4pLmZvb30pKSksdG49ZnVuY3Rpb24odCl7aWYoIVAodCkpcmV0dXJuITE7dmFyIG49dFtZdF07cmV0dXJuIHZvaWQgMCE9PW4/ISFuOkh0KHQpfTshZnVuY3Rpb24odCxuKXt2YXIgbyxyLGUsYSx1LGY9dC50YXJnZXQsYz10Lmdsb2JhbCxsPXQuc3RhdDtpZihvPWM/aTpsP2lbZl18fE0oZix7fSk6KGlbZl18fHt9KS5wcm90b3R5cGUpZm9yKHIgaW4gbil7aWYoYT1uW3JdLGU9dC5ub1RhcmdldEdldD8odT1rdChvLHIpKSYmdS52YWx1ZTpvW3JdLCF5dChjP3I6ZisobD9cIi5cIjpcIiNcIikrcix0LmZvcmNlZCkmJnZvaWQgMCE9PWUpe2lmKHR5cGVvZiBhPT10eXBlb2YgZSljb250aW51ZTtSdChhLGUpfSh0LnNoYW18fGUmJmUuc2hhbSkmJk8oYSxcInNoYW1cIiwhMCksZXQobyxyLGEsdCl9fSh7dGFyZ2V0OlwiQXJyYXlcIixwcm90bzohMCxmb3JjZWQ6IVh0fHwhJHR9LHtjb25jYXQ6ZnVuY3Rpb24odCl7dmFyIG4sbyxyLGUsYSxpPU90KHRoaXMpLHU9S3QoaSwwKSxmPTA7Zm9yKG49LTEscj1hcmd1bWVudHMubGVuZ3RoO248cjtuKyspaWYodG4oYT0tMT09PW4/aTphcmd1bWVudHNbbl0pKXtpZihmKyhlPW10KGEubGVuZ3RoKSk+X3QpdGhyb3cgVHlwZUVycm9yKFF0KTtmb3Iobz0wO288ZTtvKyssZisrKW8gaW4gYSYmTXQodSxmLGFbb10pfWVsc2V7aWYoZj49X3QpdGhyb3cgVHlwZUVycm9yKFF0KTtNdCh1LGYrKyxhKX1yZXR1cm4gdS5sZW5ndGg9Zix1fX0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiYWYtWkFcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMuYWY9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJCZXNpZyBvbSB0ZSBsYWFpLCB3YWcgYXNzZWJsaWVmXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcmVrb3JkcyBwZXIgYmxhZHN5XCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJSZXN1bHRhdGUgXCIuY29uY2F0KHQsXCIgdG90IFwiKS5jb25jYXQobixcIiB2YW4gXCIpLmNvbmNhdChvLFwiIHJ5ZSAoZmlsdGVyZWQgZnJvbSBcIikuY29uY2F0KHIsXCIgdG90YWwgcm93cylcIik6XCJSZXN1bHRhdGUgXCIuY29uY2F0KHQsXCIgdG90IFwiKS5jb25jYXQobixcIiB2YW4gXCIpLmNvbmNhdChvLFwiIHJ5ZVwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwicHJldmlvdXMgcGFnZVwifSxmb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dDpmdW5jdGlvbih0KXtyZXR1cm5cInRvIHBhZ2UgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwibmV4dCBwYWdlXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCJTaG93aW5nIFwiLmNvbmNhdCh0LFwiIHJvd3NcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbGVhciBTZWFyY2hcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJTb2VrXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiR2VlbiByZWtvcmRzIGdldmluZCBuaWVcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiV3lzL3ZlcmJlcmcgYmxhZHN5IG51bW1lcmluZ1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBwYWdpbmF0aW9uXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhlcmxhYWlcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCJXaXNzZWxcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiS29sb21tZVwifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb2dnbGUgYWxsXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIkZ1bGxzY3JlZW5cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiQWxsXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnQgZGF0YVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImFmLVpBXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImFyLVNBXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLmFyPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwi2KzYp9ix2Yog2KfZhNiq2K3ZhdmK2YQsINmK2LHYrNmJINin2YTYpdmG2KrYuNin2LFcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiDYs9is2YQg2YTZg9mEINi12YHYrdipXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCLYp9mE2LjYp9mH2LEgXCIuY29uY2F0KHQsXCIg2KXZhNmJIFwiKS5jb25jYXQobixcIiDZhdmGIFwiKS5jb25jYXQobyxcIiDYs9is2YQgXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwi2KfZhNi42KfZh9ixIFwiLmNvbmNhdCh0LFwiINil2YTZiSBcIikuY29uY2F0KG4sXCIg2YXZhiBcIikuY29uY2F0KG8sXCIg2LPYrNmEXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNsZWFyIFNlYXJjaFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cItio2K3Yq1wifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cItmE2Kcg2KrZiNis2K8g2YbYqtin2KbYrCDZhdi32KfYqNmC2Kkg2YTZhNio2K3Yq1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLYpdiu2YHYp9ih2KXYuNmH2KfYsSDYqtix2YLZitmFINin2YTYtdmB2K3Yp9iqXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwi2KrYrdiv2YrYq1wifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cItiq2LrZitmK2LFcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwi2KPYudmF2K/YqVwifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb2dnbGUgYWxsXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIkZ1bGxzY3JlZW5cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiQWxsXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnQgZGF0YVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImFyLVNBXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImJnLUJHXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLmJnPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwi0JfQsNGA0LXQttC00LDQvdC1LCDQvNC+0LvRjyDQuNC30YfQsNC60LDQudGC0LVcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiDRgNC10LTQsCDQvdCwINGB0YLRgNCw0L3QuNGG0LBcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cItCf0L7QutCw0LfQsNC90Lgg0YDQtdC00L7QstC1INC+0YIgXCIuY29uY2F0KHQsXCIg0LTQviBcIikuY29uY2F0KG4sXCIg0L7RgiBcIikuY29uY2F0KG8sXCIg0YDQtdC00LAgKNGE0LjQu9GC0YDQuNGA0LDQvdC4INC+0YIg0L7QsdGJ0L4gXCIpLmNvbmNhdChyLFwiINGA0LXQtNCwKVwiKTpcItCf0L7QutCw0LfQsNC90Lgg0YDQtdC00L7QstC1INC+0YIgXCIuY29uY2F0KHQsXCIg0LTQviBcIikuY29uY2F0KG4sXCIg0L7RgiDQvtCx0YnQviBcIikuY29uY2F0KG8sXCIg0YDQtdC00LBcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cItC/0YDQtdC00LjRiNC90LAg0YHRgtGA0LDQvdC40YbQsFwifSxmb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dDpmdW5jdGlvbih0KXtyZXR1cm5cItC00L4g0YHRgtGA0LDQvdC40YbQsCBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCLRgdC70LXQtNCy0LDRidCwINGB0YLRgNCw0L3QuNGG0LBcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cItCf0L7QutCw0LfQsNC90LggXCIuY29uY2F0KHQsXCIg0YDQtdC00LBcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLQmNC30YfQuNGB0YLQstCw0L3QtSDQvdCwINGC0YrRgNGB0LXQvdC10YLQvlwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cItCi0YrRgNGB0LXQvdC1XCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwi0J3QtSDRgdCwINC90LDQvNC10YDQtdC90Lgg0YHRitCy0L/QsNC00LDRidC4INC30LDQv9C40YHQuFwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLQodC60YDQuNCy0LDQvdC1L9Cf0L7QutCw0LfQstCw0L3QtSDQvdCwINGB0YLRgNCw0L3QuNGG0LjRgNCw0L3QtVwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwi0J/QvtC60LDQt9Cy0LDQvdC1INC90LAg0YHRgtGA0LDQvdC40YbQuNGA0LDQvdC1XCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwi0KHQutGA0LjQstCw0L3QtSDQvdCwINGB0YLRgNCw0L3QuNGG0LjRgNCw0L3QtVwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLQntCx0L3QvtCy0Y/QstCw0L3QtVwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cItCf0YDQtdCy0LrQu9GO0YfQstCw0L3QtVwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwi0J/QvtC60LDQt9Cy0LDQvdC1INC90LAg0LjQt9Cz0LvQtdC0INC60LDRgNGC0LBcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCLQodC60YDQuNCy0LDQvdC1INC90LAg0LjQt9Cz0LvQtdC0INC60LDRgNGC0LBcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwi0JrQvtC70L7QvdC4XCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cItCf0YDQtdCy0LrQu9GO0YfQstCw0L3QtSDQvdCwINCy0YHQuNGH0LrQuFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCLQptGP0Lsg0LXQutGA0LDQvVwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCLQktGB0LjRh9C60LhcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cItCQ0LLRgtC+0LzQsNGC0LjRh9C90L4g0L7QsdC90L7QstGP0LLQsNC90LVcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCLQldC60YHQv9C+0YDRgiDQvdCwINC00LDQvdC90LhcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCLQntCi0JjQlNCYXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLQoNCw0LfRiNC40YDQtdC90L4g0YLRitGA0YHQtdC90LVcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwi0JfQsNGC0LLQsNGA0Y/QvdC1XCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJiZy1CR1wiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJjYS1FU1wiXT1vLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcy5jYT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIkVzcGVyZXUsIHNpIHVzIHBsYXVcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiByZXN1bHRhdHMgcGVyIHDDoGdpbmFcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIk1vc3RyYW50IGRlIFwiLmNvbmNhdCh0LFwiIGZpbnMgXCIpLmNvbmNhdChuLFwiIC0gdG90YWwgXCIpLmNvbmNhdChvLFwiIHJlc3VsdGF0cyAoZmlsdGVyZWQgZnJvbSBcIikuY29uY2F0KHIsXCIgdG90YWwgcm93cylcIik6XCJNb3N0cmFudCBkZSBcIi5jb25jYXQodCxcIiBmaW5zIFwiKS5jb25jYXQobixcIiAtIHRvdGFsIFwiKS5jb25jYXQobyxcIiByZXN1bHRhdHNcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQ2xlYXIgU2VhcmNoXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQ2VyY2FcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCJObyBzJ2hhbiB0cm9iYXQgcmVzdWx0YXRzXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFtYWdhL01vc3RyYSBwYWdpbmFjacOzXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiUmVmcmVzY2FcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCJBbHRlcm5hIGZvcm1hdGFjacOzXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNhcmQgdmlld1wifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY2FyZCB2aWV3XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvbHVtbmVzXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZ2dsZSBhbGxcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiRnVsbHNjcmVlblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb3RzXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnQgZGF0YVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImNhLUVTXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImNzLUNaXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLmNzPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwixIxla2VqdGUsIHByb3PDrW1cIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiBwb2xvxb5layBuYSBzdHLDoW5rdVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiWm9icmF6ZW5hIFwiLmNvbmNhdCh0LFwiLiAtIFwiKS5jb25jYXQobixcIiAuIHBvbG/FvmthIHogY2Vsa292w71jaCBcIikuY29uY2F0KG8sXCIgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiWm9icmF6ZW5hIFwiLmNvbmNhdCh0LFwiLiAtIFwiKS5jb25jYXQobixcIiAuIHBvbG/FvmthIHogY2Vsa292w71jaCBcIikuY29uY2F0KG8pfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNsZWFyIFNlYXJjaFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlZ5aGxlZMOhdsOhbsOtXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiTmVuYWxlemVuYSDFvsOhZG7DoSB2eWhvdnVqw61jw60gcG9sb8W+a2FcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiU2tyw710L1pvYnJheml0IHN0csOhbmtvdsOhbsOtXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQWt0dWFsaXpvdmF0XCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiUMWZZXBuaVwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjYXJkIHZpZXdcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNhcmQgdmlld1wifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJTbG91cGNlXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZ2dsZSBhbGxcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiRnVsbHNjcmVlblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJWxaFlXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnQgZGF0YVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImNzLUNaXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImRhLURLXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLmRhPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiSW5kbMOmc2VyLCB2ZW50IHZlbmxpZ3N0XCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcG9zdGVyIHByIHNpZGVcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIlZpc2VyIFwiLmNvbmNhdCh0LFwiIHRpbCBcIikuY29uY2F0KG4sXCIgYWYgXCIpLmNvbmNhdChvLFwiIHLDpmtrZVwiKS5jb25jYXQobz4xP1wiclwiOlwiXCIsXCIgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiVmlzZXIgXCIuY29uY2F0KHQsXCIgdGlsIFwiKS5jb25jYXQobixcIiBhZiBcIikuY29uY2F0KG8sXCIgcsOma2tlXCIpLmNvbmNhdChvPjE/XCJyXCI6XCJcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiVmlzZXIgXCIuY29uY2F0KHQsXCIgcsOma2tlXCIpLmNvbmNhdCh0PjE/XCJyXCI6XCJcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJSeWQgZmlsdHJlXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiU8O4Z1wifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIkluZ2VuIHBvc3RlciBmdW5kZXRcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiU2tqdWwvdmlzIG51bW1lcmVyaW5nXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiT3BkYXRlclwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIlNraWZ0XCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNhcmQgdmlld1wifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY2FyZCB2aWV3XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cIktvbG9ubmVyXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZ2dsZSBhbGxcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiRnVsbHNjcmVlblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJBbGxlXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFa3Nwb3J0ZXJcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJkYS1ES1wiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJkZS1ERVwiXT1vLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcy5kZT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIlplaWxlbiBrb3BpZXJlblwifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiRHJ1Y2tlblwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiTGFkZSwgYml0dGUgd2FydGVuXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgWmVpbGVuIHBybyBTZWl0ZS5cIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIlplaWdlIFplaWxlIFwiLmNvbmNhdCh0LFwiIGJpcyBcIikuY29uY2F0KG4sXCIgdm9uIFwiKS5jb25jYXQobyxcIiBaZWlsZVwiKS5jb25jYXQobz4xP1wiblwiOlwiXCIsXCIgKEdlZmlsdGVydCB2b24gXCIpLmNvbmNhdChyLFwiIFplaWxlXCIpLmNvbmNhdChyPjE/XCJuXCI6XCJcIixcIilcIik6XCJaZWlnZSBaZWlsZSBcIi5jb25jYXQodCxcIiBiaXMgXCIpLmNvbmNhdChuLFwiIHZvbiBcIikuY29uY2F0KG8sXCIgWmVpbGVcIikuY29uY2F0KG8+MT9cIm5cIjpcIlwiLFwiLlwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwiVm9yaGVyaWdlIFNlaXRlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwiWnUgU2VpdGUgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwiTsOkY2hzdGUgU2VpdGVcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlplaWdlIFwiLmNvbmNhdCh0LFwiIFplaWxlXCIpLmNvbmNhdCh0PjE/XCJuXCI6XCJcIixcIi5cIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJMw7ZzY2hlIEZpbHRlclwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlN1Y2hlblwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIktlaW5lIHBhc3NlbmRlbiBFcmdlYm5pc3NlIGdlZnVuZGVuXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlZlcnN0ZWNrZS9aZWlnZSBOdW1tZXJpZXJ1bmdcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlplaWdlIE51bW1lcmllcnVuZ1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIlZlcnN0ZWNrZSBOdW1tZXJpZXJ1bmdcIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiTmV1IGxhZGVuXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiVW1zY2hhbHRlblwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiTm9ybWFsZSBBbnNpY2h0XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiS2FydGVuYW5zaWNodFwifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJTcGFsdGVuXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIkFsbGUgdW1zY2hhbHRlblwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJWb2xsYmlsZFwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJBbGxlXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvbWF0aXNjaGVzIE5ldWxhZGVuXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRGF0ZW5leHBvcnRcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJTcHJpbmdlblwifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiRXJ3ZWl0ZXJ0ZSBTdWNoZVwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTY2hsaWXDn2VuXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlZlcnN0ZWNrZS9aZWlnZSBGaWx0ZXJcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIlZlcnN0ZWNrZSBGaWx0ZXJcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlplaWdlIEZpbHRlclwifSxmb3JtYXRBZGRMZXZlbDpmdW5jdGlvbigpe3JldHVyblwiRWJlbmUgaGluenVmw7xnZW5cIn0sZm9ybWF0Q2FuY2VsOmZ1bmN0aW9uKCl7cmV0dXJuXCJBYmJyZWNoZW5cIn0sZm9ybWF0Q29sdW1uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTcGFsdGVcIn0sZm9ybWF0RGVsZXRlTGV2ZWw6ZnVuY3Rpb24oKXtyZXR1cm5cIkViZW5lIGVudGZlcm5lblwifSxmb3JtYXREdXBsaWNhdGVBbGVydFRpdGxlOmZ1bmN0aW9uKCl7cmV0dXJuXCJEb3BwZWx0ZSBFaW50csOkZ2UgZ2VmdW5kZW4hXCJ9LGZvcm1hdER1cGxpY2F0ZUFsZXJ0RGVzY3JpcHRpb246ZnVuY3Rpb24oKXtyZXR1cm5cIkJpdHRlIGRvcHBlbHRlIFNwYWx0ZW4gZW50ZmVuZW4gb2RlciDDpG5kZXJuXCJ9LGZvcm1hdE11bHRpcGxlU29ydDpmdW5jdGlvbigpe3JldHVyblwiTWVocmZhY2hzb3J0aWVydW5nXCJ9LGZvcm1hdE9yZGVyOmZ1bmN0aW9uKCl7cmV0dXJuXCJSZWloZW5mb2xnZVwifSxmb3JtYXRTb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJTb3J0aWVyZW5cIn0sZm9ybWF0U29ydEJ5OmZ1bmN0aW9uKCl7cmV0dXJuXCJTb3J0aWVyZW4gbmFjaFwifSxmb3JtYXRUaGVuQnk6ZnVuY3Rpb24oKXtyZXR1cm5cImFuc2NobGllw59lbmRcIn0sZm9ybWF0U29ydE9yZGVyczpmdW5jdGlvbigpe3JldHVybnthc2M6XCJBdWZzdGVpZ2VuZFwiLGRlc2M6XCJBYnN0ZWlnZW5kXCJ9fX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJkZS1ERVwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJlbC1HUlwiXT1vLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcy5lbD17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIs6mzr/Pgc+Ez47Ovc61zrksIM+AzrHPgc6xzrrOsc67z44gz4DOtc+BzrnOvM6tzr3Otc+EzrVcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiDOsc+Azr/PhM61zrvOrc+DzrzOsc+EzrEgzrHOvc6sIM+DzrXOu86vzrTOsVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wizpXOvM+GzrHOvc6vzrbOv869z4TOsc65IM6xz4DPjCDPhM63zr0gXCIuY29uY2F0KHQsXCIgz4nPgiDPhM63zr0gXCIpLmNvbmNhdChuLFwiIM6xz4DPjCDPg8+Nzr3Ov867zr8gXCIpLmNvbmNhdChvLFwiIM+DzrXOuc+Bz47OvSAoZmlsdGVyZWQgZnJvbSBcIikuY29uY2F0KHIsXCIgdG90YWwgcm93cylcIik6XCLOlc68z4bOsc69zq/Ots6/zr3PhM6xzrkgzrHPgM+MIM+EzrfOvSBcIi5jb25jYXQodCxcIiDPic+CIM+EzrfOvSBcIikuY29uY2F0KG4sXCIgzrHPgM+MIM+Dz43Ovc6/zrvOvyBcIikuY29uY2F0KG8sXCIgz4POtc65z4HPjs69XCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNsZWFyIFNlYXJjaFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIs6Rzr3Osc62zrfPhM6uz4PPhM61XCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwizpTOtc69IM6yz4HOrc64zrfOus6xzr0gzrHPgM6/z4TOtc67zq3Pg868zrHPhM6xXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiUmVmcmVzaFwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZ2dsZVwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjYXJkIHZpZXdcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNhcmQgdmlld1wifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb2x1bW5zXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZ2dsZSBhbGxcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiRnVsbHNjcmVlblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJBbGxcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVmcmVzaFwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4cG9ydCBkYXRhXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiR09cIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFkdmFuY2VkIHNlYXJjaFwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbG9zZVwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY29udHJvbHNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiZWwtR1JcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiZW4tVVNcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMuZW49e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJMb2FkaW5nLCBwbGVhc2Ugd2FpdFwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIHJvd3MgcGVyIHBhZ2VcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgdG8gXCIpLmNvbmNhdChuLFwiIG9mIFwiKS5jb25jYXQobyxcIiByb3dzIChmaWx0ZXJlZCBmcm9tIFwiKS5jb25jYXQocixcIiB0b3RhbCByb3dzKVwiKTpcIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgdG8gXCIpLmNvbmNhdChuLFwiIG9mIFwiKS5jb25jYXQobyxcIiByb3dzXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNsZWFyIFNlYXJjaFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlNlYXJjaFwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIk5vIG1hdGNoaW5nIHJlY29yZHMgZm91bmRcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJSZWZyZXNoXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNhcmQgdmlld1wifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY2FyZCB2aWV3XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvbHVtbnNcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkFsbFwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0IGRhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJlbi1VU1wiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJlcy1BUlwiXT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcGlhciBGaWxhc1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiSW1wcmltaXJcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhcmdhbmRvLCBlc3BlcmUgcG9yIGZhdm9yXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcmVnaXN0cm9zIHBvciBww6FnaW5hXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJNb3N0cmFuZG8gZGVzZGUgXCIuY29uY2F0KHQsXCIgYSBcIikuY29uY2F0KG4sXCIgZGUgXCIpLmNvbmNhdChvLFwiIGZpbGFzIChmaWx0cmFkbyBkZSBcIikuY29uY2F0KHIsXCIgY29sdW1uYXMgdG90YWxlcylcIik6XCJNb3N0cmFuZG8gZGVzZGUgXCIuY29uY2F0KHQsXCIgYSBcIikuY29uY2F0KG4sXCIgZGUgXCIpLmNvbmNhdChvLFwiIGZpbGFzXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJww6FnaW5hIGFudGVyaW9yXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwiYSBsYSBww6FnaW5hIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInNpZ3VpZW50ZSBww6FnaW5hXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCJNb3N0cmFuZG8gXCIuY29uY2F0KHQsXCIgY29sdW1uYXNcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJMaW1waWFyIGLDunNxdWVkYVwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkJ1c2NhclwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIk5vIHNlIGVuY29udHJhcm9uIHJlZ2lzdHJvc1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJPY3VsdGFyL01vc3RyYXIgcGFnaW5hY2nDs25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIk1vc3RyYXIgcGFnaW5hY2nDs25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJPY3VsdGFyIHBhZ2luYWNpw7NuXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlJlY2FyZ2FyXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiQ2FtYmlhclwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiTW9zdHJhciB2aXN0YSBkZSBjYXJ0YVwifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIgdmlzdGEgZGUgY2FydGFcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiQ29sdW1uYXNcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiQ2FtYmlhciB0b2RvXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIlBhbnRhbGxhIGNvbXBsZXRhXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZG9cIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVjYXJnYXJcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnRhciBkYXRvc1wifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIklyXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJCw7pzcXVlZGEgYXZhbnphZGFcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2VycmFyXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIvTW9zdHJhciBjb250cm9sZXNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIgY29udHJvbGVzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJNb3N0cmFyIGNvbnRyb2xlc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJlcy1BUlwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJlcy1DTFwiXT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcGlhciBGaWxhc1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiSW1wcmltaXJcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhcmdhbmRvLCBlc3BlcmUgcG9yIGZhdm9yXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgZmlsYXMgcG9yIHDDoWdpbmFcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIk1vc3RyYW5kbyBcIi5jb25jYXQodCxcIiBhIFwiKS5jb25jYXQobixcIiBkZSBcIikuY29uY2F0KG8sXCIgZmlsYXMgKGZpbHRyYWRvIGRlIFwiKS5jb25jYXQocixcIiBmaWxhcyB0b3RhbGVzKVwiKTpcIk1vc3RyYW5kbyBcIi5jb25jYXQodCxcIiBhIFwiKS5jb25jYXQobixcIiBkZSBcIikuY29uY2F0KG8sXCIgZmlsYXNcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInDDoWdpbmEgYW50ZXJpb3JcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJhIGxhIHDDoWdpbmEgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwic2lndWllbnRlIHDDoWdpbmFcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIk1vc3RyYW5kbyBcIi5jb25jYXQodCxcIiBmaWxhc1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkxpbXBpYXIgYsO6c3F1ZWRhXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQnVzY2FyXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiTm8gc2UgZW5jb250cmFyb24gcmVnaXN0cm9zXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIvTW9zdHJhciBwYWdpbmFjacOzblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwiTW9zdHJhciBwYWdpbmFjacOzblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIgcGFnaW5hY2nDs25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiUmVmcmVzY2FyXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiQ2FtYmlhclwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiTW9zdHJhciB2aXN0YSBkZSBjYXJ0YVwifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIgdmlzdGEgZGUgY2FydGFcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiQ29sdW1uYXNcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiQ2FtYmlhciB0b2RvXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIlBhbnRhbGxhIGNvbXBsZXRhXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZG9cIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVjYXJnYXJcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnRhciBkYXRvc1wifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIklSXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJCw7pzcXVlZGEgYXZhbnphZGFcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2VycmFyXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIvTW9zdHJhciBjb250cm9sZXNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIgY29udHJvbGVzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJNb3N0cmFyIGNvbnRyb2xlc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJlcy1DTFwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJlcy1DUlwiXT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhcmdhbmRvLCBwb3IgZmF2b3IgZXNwZXJlXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcmVnaXN0cm9zIHBvciBww6FnaW5hXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJNb3N0cmFuZG8gZGUgXCIuY29uY2F0KHQsXCIgYSBcIikuY29uY2F0KG4sXCIgcmVnaXN0cm9zIGRlIFwiKS5jb25jYXQobyxcIiByZWdpc3Ryb3MgZW4gdG90YWwgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiTW9zdHJhbmRvIGRlIFwiLmNvbmNhdCh0LFwiIGEgXCIpLmNvbmNhdChuLFwiIHJlZ2lzdHJvcyBkZSBcIikuY29uY2F0KG8sXCIgcmVnaXN0cm9zIGVuIHRvdGFsXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkxpbXBpYXIgYsO6c3F1ZWRhXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQnVzY2FyXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiTm8gc2UgZW5jb250cmFyb24gcmVnaXN0cm9zXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiUmVmcmVzY2FyXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiQWx0ZXJuYXJcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiQ29sdW1uYXNcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZG9cIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVmcmVzaFwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4cG9ydCBkYXRhXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiR09cIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFkdmFuY2VkIHNlYXJjaFwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbG9zZVwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJPY3VsdGFyL01vc3RyYXIgY29udHJvbGVzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJPY3VsdGFyIGNvbnRyb2xlc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiTW9zdHJhciBjb250cm9sZXNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiZXMtQ1JcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiZXMtRVNcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMuZXM9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3BpYXIgZmlsYXNcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkltcHJpbWlyXCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJQb3IgZmF2b3IgZXNwZXJlXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcmVzdWx0YWRvcyBwb3IgcMOhZ2luYVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiTW9zdHJhbmRvIGRlc2RlIFwiLmNvbmNhdCh0LFwiIGhhc3RhIFwiKS5jb25jYXQobixcIiAtIEVuIHRvdGFsIFwiKS5jb25jYXQobyxcIiByZXN1bHRhZG9zIChmaWx0cmFkbyBkZSBcIikuY29uY2F0KHIsXCIgZmlsYXMgdG90YWxlcylcIik6XCJNb3N0cmFuZG8gZGVzZGUgXCIuY29uY2F0KHQsXCIgaGFzdGEgXCIpLmNvbmNhdChuLFwiIC0gRW4gdG90YWwgXCIpLmNvbmNhdChvLFwiIHJlc3VsdGFkb3NcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInDDoWdpbmEgYW50ZXJpb3JcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJhIGxhIHDDoWdpbmEgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwic2lndWllbnRlIHDDoWdpbmFcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIk1vc3RyYW5kbyBcIi5jb25jYXQodCxcIiBmaWxhc1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkxpbXBpYXIgYsO6c3F1ZWRhXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQnVzY2FyXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiTm8gc2UgZW5jb250cmFyb24gcmVzdWx0YWRvc1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJPY3VsdGFyL01vc3RyYXIgcGFnaW5hY2nDs25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIk1vc3RyYXIgcGFnaW5hY2nDs25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJPY3VsdGFyIHBhZ2luYWNpw7NuXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlJlY2FyZ2FyXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiT2N1bHRhci9Nb3N0cmFyXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJNb3N0cmFyIHZpc3RhIGRlIGNhcnRhXCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiT2N1bHRhciB2aXN0YSBkZSBjYXJ0YVwifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb2x1bW5hc1wifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJDYW1iaWFyIHRvZG9cIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiUGFudGFsbGEgY29tcGxldGFcIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiVG9kb3NcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVjYXJnYXJcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnRhciBsb3MgZGF0b3NcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJJUlwifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQsO6c3F1ZWRhIGF2YW56YWRhXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNlcnJhclwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJPY3VsdGFyL01vc3RyYXIgY29udHJvbGVzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJPY3VsdGFyIGNvbnRyb2xlc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiTW9zdHJhciBjb250cm9sZXNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiZXMtRVNcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiZXMtTVhcIl09e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJDYXJnYW5kbywgZXNwZXJlIHBvciBmYXZvclwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIHJlZ2lzdHJvcyBwb3IgcMOhZ2luYVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiTW9zdHJhbmRvIFwiLmNvbmNhdCh0LFwiIGEgXCIpLmNvbmNhdChuLFwiIGRlIFwiKS5jb25jYXQobyxcIiBmaWxhcyAoZmlsdGVyZWQgZnJvbSBcIikuY29uY2F0KHIsXCIgdG90YWwgcm93cylcIik6XCJNb3N0cmFuZG8gXCIuY29uY2F0KHQsXCIgYSBcIikuY29uY2F0KG4sXCIgZGUgXCIpLmNvbmNhdChvLFwiIGZpbGFzXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIk1vc3RyYW5kbyBcIi5jb25jYXQodCxcIiBmaWxhc1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkxpbXBpYXIgYsO6c3F1ZWRhXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQnVzY2FyXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiTm8gc2UgZW5jb250cmFyb24gcmVnaXN0cm9zIHF1ZSBjb2luY2lkYW5cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiTW9zdHJhci9vY3VsdGFyIHBhZ2luYWNpw7NuXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQWN0dWFsaXphclwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhbWJpYXIgdmlzdGFcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiQ29sdW1uYXNcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJQYW50YWxsYSBjb21wbGV0YVwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb2RvXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnQgZGF0YVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiT2N1bHRhci9Nb3N0cmFyIGNvbnRyb2xlc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiT2N1bHRhciBjb250cm9sZXNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIk1vc3RyYXIgY29udHJvbGVzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImVzLU1YXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImVzLU5JXCJdPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiQ2FyZ2FuZG8sIHBvciBmYXZvciBlc3BlcmVcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiByZWdpc3Ryb3MgcG9yIHDDoWdpbmFcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIk1vc3RyYW5kbyBkZSBcIi5jb25jYXQodCxcIiBhIFwiKS5jb25jYXQobixcIiByZWdpc3Ryb3MgZGUgXCIpLmNvbmNhdChvLFwiIHJlZ2lzdHJvcyBlbiB0b3RhbCAoZmlsdGVyZWQgZnJvbSBcIikuY29uY2F0KHIsXCIgdG90YWwgcm93cylcIik6XCJNb3N0cmFuZG8gZGUgXCIuY29uY2F0KHQsXCIgYSBcIikuY29uY2F0KG4sXCIgcmVnaXN0cm9zIGRlIFwiKS5jb25jYXQobyxcIiByZWdpc3Ryb3MgZW4gdG90YWxcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiTGltcGlhciBiw7pzcXVlZGFcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJCdXNjYXJcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCJObyBzZSBlbmNvbnRyYXJvbiByZWdpc3Ryb3NcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJSZWZyZXNjYXJcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCJBbHRlcm5hclwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjYXJkIHZpZXdcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNhcmQgdmlld1wifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb2x1bW5hc1wifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb2dnbGUgYWxsXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIkZ1bGxzY3JlZW5cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiVG9kb1wifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0IGRhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIvTW9zdHJhciBjb250cm9sZXNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIgY29udHJvbGVzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJNb3N0cmFyIGNvbnRyb2xlc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJlcy1OSVwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJlcy1TUFwiXT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhcmdhbmRvLCBwb3IgZmF2b3IgZXNwZXJhXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcmVnaXN0cm9zIHBvciBwJiMyMjU7Z2luYS5cIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIlwiLmNvbmNhdCh0LFwiIC0gXCIpLmNvbmNhdChuLFwiIGRlIFwiKS5jb25jYXQobyxcIiByZWdpc3Ryb3MgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiXCIuY29uY2F0KHQsXCIgLSBcIikuY29uY2F0KG4sXCIgZGUgXCIpLmNvbmNhdChvLFwiIHJlZ2lzdHJvcy5cIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiTGltcGlhciBiw7pzcXVlZGFcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJCdXNjYXJcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCJObyBzZSBoYW4gZW5jb250cmFkbyByZWdpc3Ryb3MuXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQWN0dWFsaXphclwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkFsdGVybmFyXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNhcmQgdmlld1wifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY2FyZCB2aWV3XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvbHVtbmFzXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZ2dsZSBhbGxcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiRnVsbHNjcmVlblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb2RvXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnQgZGF0YVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiT2N1bHRhci9Nb3N0cmFyIGNvbnRyb2xlc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiT2N1bHRhciBjb250cm9sZXNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIk1vc3RyYXIgY29udHJvbGVzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImVzLVNQXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImV0LUVFXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLmV0PXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiUMOkcmluZyBrw6RpYiwgcGFsdW4gb290YVwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIHJpZGEgbGVoZSBrb2h0YVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiTsOkaXRhbiB0dWxlbXVzaSBcIi5jb25jYXQodCxcIiBrdW5pIFwiKS5jb25jYXQobixcIiAtIGtva2t1IFwiKS5jb25jYXQobyxcIiB0dWxlbXVzdCAoZmlsdGVyZWQgZnJvbSBcIikuY29uY2F0KHIsXCIgdG90YWwgcm93cylcIik6XCJOw6RpdGFuIHR1bGVtdXNpIFwiLmNvbmNhdCh0LFwiIGt1bmkgXCIpLmNvbmNhdChuLFwiIC0ga29ra3UgXCIpLmNvbmNhdChvLFwiIHR1bGVtdXN0XCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNsZWFyIFNlYXJjaFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk90c2lcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCJQw6RyaW5ndSB0aW5naW11c3RlbGUgZWkgdmFzdGFudWQgw7xodGVnaSB0dWxlbXVzdFwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJOw6RpdGEvUGVpZGEgbGVodGVkZWtzIGphZ2FtaW5lXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiVsOkcnNrZW5kYVwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkzDvGxpdGFcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiVmVlcnVkXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZ2dsZSBhbGxcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiRnVsbHNjcmVlblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJLw7Vpa1wifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0IGRhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJldC1FRVwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJldS1FVVwiXT1vLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcy5ldT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIkl0eGFyb24gbWVzZWRlelwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIGVtYWl0emEgb3JyaWtvLlwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiXCIuY29uY2F0KG8sXCIgZXJyZWdpc3Ryb2V0YXRpayBcIikuY29uY2F0KHQsXCJldGlrIFwiKS5jb25jYXQobixcImVyYWtvYWsgZXJha3VzdGVuIChmaWx0ZXJlZCBmcm9tIFwiKS5jb25jYXQocixcIiB0b3RhbCByb3dzKVwiKTpcIlwiLmNvbmNhdChvLFwiIGVycmVnaXN0cm9ldGF0aWsgXCIpLmNvbmNhdCh0LFwiZXRpayBcIikuY29uY2F0KG4sXCJlcmFrb2FrIGVyYWt1c3Rlbi5cIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQ2xlYXIgU2VhcmNoXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQmlsYXR1XCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiRXogZGEgZW1haXR6YXJpayBhdXJraXR1XCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkV6a3V0YXR1L0VyYWt1dHNpIG9ycmlrYXR6ZWFcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJFZ3VuZXJhdHVcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCJFemt1dGF0dS9FcmFrdXRzaVwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjYXJkIHZpZXdcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNhcmQgdmlld1wifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJadXRhYmVha1wifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb2dnbGUgYWxsXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIkZ1bGxzY3JlZW5cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiR3V6dGlha1wifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0IGRhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJldS1FVVwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJmYS1JUlwiXT1vLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcy5mYT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cItqp2b7bjCDYsdiv24zZgSDZh9inXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCLZvtix24zZhtiqXCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCLYr9ixINit2KfZhCDYqNin2LHar9iw2KfYsduMLCDZhNi32YHYpyDYtdio2LEg2qnZhtuM2K9cIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiDYsdqp2YjYsdivINiv2LEg2LXZgdit2YdcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cItmG2YXYp9uM2LQgXCIuY29uY2F0KHQsXCIg2KrYpyBcIikuY29uY2F0KG4sXCIg2KfYsiBcIikuY29uY2F0KG8sXCIg2LHYr9uM2YEgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwi2YbZhdin24zYtCBcIi5jb25jYXQodCxcIiDYqtinIFwiKS5jb25jYXQobixcIiDYp9iyIFwiKS5jb25jYXQobyxcIiDYsdiv24zZgVwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwi2LXZgdit2Ycg2YLYqNmE24xcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCLYqNmHINi12YHYrdmHIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIti12YHYrdmHINio2LnYr9uMXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCLZhtmF2KfbjNi0IFwiLmNvbmNhdCh0LFwiINiz2LfYsdmH2KdcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLZvtin2qkg2qnYsdiv2YYg2KzYs9iq2KzZiFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cItis2LPYqtis2YhcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCLYsdqp2YjYsdiv24wg24zYp9mB2Kog2YbYtNivLlwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLZhtmF2KfbjNi0L9mF2K7ZgduMINi12YHYrdmHINio2YbYr9uMXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCLZhtmF2KfbjNi0INi12YHYrdmHINio2YbYr9uMXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwi2b7ZhtmH2KfZhiDaqdix2K/ZhiDYtdmB2K3ZhyDYqNmG2K/bjFwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLYqNmHINix2YjYsiDYsdiz2KfZhtuMXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwi2KrYutuM24zYsSDZhtmF2KfbjNi0XCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNhcmQgdmlld1wifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY2FyZCB2aWV3XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cItiz2LfYsSDZh9inXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cItiq2LrbjNuM2LEg2YjYtti524zYqiDZh9mF2YdcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwi2KrZhdin2YUg2LXZgdit2YdcIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwi2YfZhdmHXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLYsdmB2LHYtCDYp9iq2YjZhdin2KrbjNqpXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwi2K7YsdmI2KzbjCDYr9uM2KrYp1wifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cItio2LHZiFwifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwi2KzYs9iq2KzZiNuMINm+24zYtNix2YHYqtmHXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cItio2LPYqtmGXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cItm+2YbZh9in2YYv2YbZhdin24zYtCDYr9in2K/ZhiDaqdmG2KrYsdmEINmH2KdcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cItm+2YbZh9in2YYg2qnYsdiv2YYg2qnZhtiq2LHZhCDZh9inXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCLZhtmF2KfbjNi0INqp2YbYqtix2YQg2YfYp1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJmYS1JUlwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJmaS1GSVwiXT1vLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcy5maT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIkxhZGF0YWFuLCBvbGUgaHl2w6QgamEgb2RvdGFcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiByaXZpw6Qgc2l2dWxsYVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiTsOkeXRldMOkw6RuIHJpdml0IFwiLmNvbmNhdCh0LFwiIC0gXCIpLmNvbmNhdChuLFwiIC8gXCIpLmNvbmNhdChvLFwiIChmaWx0ZXJlZCBmcm9tIFwiKS5jb25jYXQocixcIiB0b3RhbCByb3dzKVwiKTpcIk7DpHl0ZXTDpMOkbiByaXZpdCBcIi5jb25jYXQodCxcIiAtIFwiKS5jb25jYXQobixcIiAvIFwiKS5jb25jYXQobyl9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiUG9pc3RhIHN1b2RhdHRpbWV0XCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiSGFlXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiSGFrdWVodG9qYSB2YXN0YWF2aWEgdHVsb2tzaWEgZWkgbMO2eXR5bnl0XCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk7DpHl0w6QvUGlpbG90YSBzaXZ1dHVzXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiUMOkaXZpdMOkXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiVmFsaXRzZVwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjYXJkIHZpZXdcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNhcmQgdmlld1wifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJTYXJha2tlZXRcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkthaWtraVwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiVmllIHRpZWRvdFwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImZpLUZJXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImZyLUJFXCJdPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiQ2hhcmdlbWVudCBlbiBjb3Vyc1wifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIGxpZ25lcyBwYXIgcGFnZVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiQWZmaWNoZSBkZSBcIi5jb25jYXQodCxcIiDDoCBcIikuY29uY2F0KG4sXCIgc3VyIFwiKS5jb25jYXQobyxcIiBsaWduZXMgKGZpbHRyw6lzIMOgIHBhcnRpciBkZSBcIikuY29uY2F0KHIsXCIgbGlnbmVzKVwiKTpcIkFmZmljaGUgZGUgXCIuY29uY2F0KHQsXCIgw6AgXCIpLmNvbmNhdChuLFwiIHN1ciBcIikuY29uY2F0KG8sXCIgbGlnbmVzXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwYWdlIHByw6ljw6lkZW50ZVwifSxmb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dDpmdW5jdGlvbih0KXtyZXR1cm5cInZlcnMgbGEgcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwYWdlIHN1aXZhbnRlXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCJBZmZpY2hlIFwiLmNvbmNhdCh0LFwiIGxpZ25lc1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkVmZmFjZXIgbGEgcmVjaGVyY2hlXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiUmVjaGVyY2hlXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiUGFzIGRlIGxpZ25lcyB0cm91dsOpc1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJDYWNoZXIvQWZmaWNoZXIgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwiQWZmaWNoZXIgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhY2hlciBwYWdpbmF0aW9uXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlJhZnJhaWNoaXJcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCJCYXNjdWxlclwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiQWZmaWNoZXIgdnVlIGNhcnRlXCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiQ2FjaGVyIHZ1ZSBjYXJ0ZVwifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb2xvbm5lc1wifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb3V0IGJhc2N1bGVyXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIlBsZWluIMOpY3JhblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb3V0XCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJSYWZyYcOuY2hpc3NlbWVudCBhdXRvbWF0aXF1ZVwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4cG9ydGVyIGxlcyBkb25uw6llc1wifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkFsbGVyIMOgXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJSZWNoZXJjaGUgYXZhbmPDqWVcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiRmVybWVyXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhY2hlci9BZmZpY2hlciBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiQ2FjaGVyIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJBZmZpY2hlciBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJmci1CRVwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJmci1DSFwiXT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIkNoYXJnZW1lbnQgZW4gY291cnNcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiBsaWduZXMgcGFyIHBhZ2VcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIkFmZmljaGUgZGUgXCIuY29uY2F0KHQsXCIgw6AgXCIpLmNvbmNhdChuLFwiIHN1ciBcIikuY29uY2F0KG8sXCIgbGlnbmVzIChmaWx0csOpcyDDoCBwYXJ0aXIgZGUgXCIpLmNvbmNhdChyLFwiIGxpZ25lcylcIik6XCJBZmZpY2hlIGRlIFwiLmNvbmNhdCh0LFwiIMOgIFwiKS5jb25jYXQobixcIiBzdXIgXCIpLmNvbmNhdChvLFwiIGxpZ25lc1wiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwicGFnZSBwcsOpY8OpZGVudGVcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ2ZXJzIGxhIHBhZ2UgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwicGFnZSBzdWl2YW50ZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiQWZmaWNoZSBcIi5jb25jYXQodCxcIiBsaWduZXNcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJFZmZhY2VyIGxhIHJlY2hlcmNoZVwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlJlY2hlcmNoZVwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIlBhcyBkZSBsaWduZXMgdHJvdXbDqXNcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiQ2FjaGVyL0FmZmljaGVyIHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIkFmZmljaGVyIHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJDYWNoZXIgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJSYWZyYWljaGlyXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiQmFzY3VsZXJcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIkFmZmljaGVyIHZ1ZSBjYXJ0ZVwifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhY2hlciB2dWUgY2FydGVcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiQ29sb25uZXNcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG91dCBiYXNjdWxlclwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJQbGVpbiDDqWNyYW5cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiVG91dFwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiUmFmcmHDrmNoaXNzZW1lbnQgYXV0b21hdGlxdWVcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnRlciBsZXMgZG9ubsOpZXNcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJBbGxlciDDoFwifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiUmVjaGVyY2hlIGF2YW5jw6llXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkZlcm1lclwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJDYWNoZXIvQWZmaWNoZXIgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhY2hlciBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiQWZmaWNoZXIgY29udHJvbHNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiZnItQ0hcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiZnItRlJcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMuZnI9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3BpZXIgbGVzIGxpZ25lc1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiSW1wcmltZXJcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIkNoYXJnZW1lbnQgZW4gY291cnNcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiBsaWduZXMgcGFyIHBhZ2VcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIkFmZmljaGUgZGUgXCIuY29uY2F0KHQsXCIgw6AgXCIpLmNvbmNhdChuLFwiIHN1ciBcIikuY29uY2F0KG8sXCIgbGlnbmVzIChmaWx0csOpcyDDoCBwYXJ0aXIgZGUgXCIpLmNvbmNhdChyLFwiIGxpZ25lcylcIik6XCJBZmZpY2hlIGRlIFwiLmNvbmNhdCh0LFwiIMOgIFwiKS5jb25jYXQobixcIiBzdXIgXCIpLmNvbmNhdChvLFwiIGxpZ25lc1wiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwicGFnZSBwcsOpY8OpZGVudGVcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ2ZXJzIGxhIHBhZ2UgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwicGFnZSBzdWl2YW50ZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiQWZmaWNoZSBcIi5jb25jYXQodCxcIiBsaWduZXNcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJFZmZhY2VyIGxhIHJlY2hlcmNoZVwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlJlY2hlcmNoZVwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1Y3VuIHLDqXN1bHRhdFwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJNYXNxdWVyL0FmZmljaGVyIGxhIHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIkFmZmljaGVyIGxhIHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJNYXNxdWVyIGxhIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQWN0dWFsaXNlclwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkJhc2N1bGVyXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZmZpY2hlciBsYSB2dWUgY2FydGVcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJNYXNxdWVyIGxhIHZ1ZSBjYXJ0ZVwifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb2xvbm5lc1wifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb3V0IGJhc2N1bGVyXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIlBsZWluIMOpY3JhblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb3V0XCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBY3R1YWxpc2F0aW9uIGF1dG9tYXRpcXVlXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0ZXIgbGVzIGRvbm7DqWVzXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiQUxMRVJcIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlJlY2hlcmNoZSBhdmFuY8OpZVwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJGZXJtZXJcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiTWFzcXVlci9BZmZpY2hlciBsZXMgY29udHLDtGxlc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiTWFzcXVlciBsZXMgY29udHLDtGxlc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiQWZmaWNoZXIgbGVzIGNvbnRyw7RsZXNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiZnItRlJcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiZnItTFVcIl09e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJDaGFyZ2VtZW50IGVuIGNvdXJzXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgbGlnbmVzIHBhciBwYWdlXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJBZmZpY2hlIGRlIFwiLmNvbmNhdCh0LFwiIMOgIFwiKS5jb25jYXQobixcIiBzdXIgXCIpLmNvbmNhdChvLFwiIGxpZ25lcyAoZmlsdHLDqXMgw6AgcGFydGlyIGRlIFwiKS5jb25jYXQocixcIiBsaWduZXMpXCIpOlwiQWZmaWNoZSBkZSBcIi5jb25jYXQodCxcIiDDoCBcIikuY29uY2F0KG4sXCIgc3VyIFwiKS5jb25jYXQobyxcIiBsaWduZXNcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInBhZ2UgcHLDqWPDqWRlbnRlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidmVycyBsYSBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInBhZ2Ugc3VpdmFudGVcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIkFmZmljaGUgXCIuY29uY2F0KHQsXCIgbGlnbmVzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiRWZmYWNlciBsYSByZWNoZXJjaGVcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJSZWNoZXJjaGVcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCJQYXMgZGUgbGlnbmVzIHRyb3V2w6lzXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhY2hlci9BZmZpY2hlciBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZmZpY2hlciBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwiQ2FjaGVyIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiUmFmcmFpY2hpclwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkJhc2N1bGVyXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZmZpY2hlciB2dWUgY2FydGVcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJDYWNoZXIgdnVlIGNhcnRlXCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvbG9ubmVzXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvdXQgYmFzY3VsZXJcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiUGxlaW4gw6ljcmFuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvdXRcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlJhZnJhw65jaGlzc2VtZW50IGF1dG9tYXRpcXVlXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0ZXIgbGVzIGRvbm7DqWVzXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiQWxsZXIgw6BcIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlJlY2hlcmNoZSBhdmFuY8OpZVwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJGZXJtZXJcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiQ2FjaGVyL0FmZmljaGVyIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJDYWNoZXIgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIkFmZmljaGVyIGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImZyLUxVXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImhlLUlMXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLmhlPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwi15jXldei158sINeg15Ag15zXlNee16rXmdefXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIg16nXldeo15XXqiDXkdei157XldeTXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCLXntem15nXkiBcIi5jb25jYXQodCxcIiDXoteTIFwiKS5jb25jYXQobixcIiDXni1cIikuY29uY2F0KG8sXCLXqdeV16jXldeqXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwi157XpteZ15IgXCIuY29uY2F0KHQsXCIg16LXkyBcIikuY29uY2F0KG4sXCIg154tXCIpLmNvbmNhdChvLFwiINep15XXqNeV16pcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQ2xlYXIgU2VhcmNoXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwi15fXmdek15XXqVwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cItec15Ag16DXntem15DXlSDXqNep15XXnteV16og16rXldeQ157XldeqXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIteU16HXqteoL9eU16bXkiDXnteh16TXldeoINeT16TXmdedXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwi16jXoteg159cIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCLXlNeX15zXoyDXqtem15XXkteUXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNhcmQgdmlld1wifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY2FyZCB2aWV3XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cItei157XldeT15XXqlwifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb2dnbGUgYWxsXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIkZ1bGxzY3JlZW5cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwi15TXm9ecXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnQgZGF0YVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImhlLUlMXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImhyLUhSXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLmhyPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiTW9saW1vIHByacSNZWthanRlXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgYnJvaiB6YXBpc2EgcG8gc3RyYW5pY2lcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIlByaWthenVqZW0gXCIuY29uY2F0KHQsXCIuIC0gXCIpLmNvbmNhdChuLFwiLiBvZCB1a3Vwbm9nIGJyb2phIHphcGlzYSBcIikuY29uY2F0KG8sXCIgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiUHJpa2F6dWplbSBcIi5jb25jYXQodCxcIi4gLSBcIikuY29uY2F0KG4sXCIuIG9kIHVrdXBub2cgYnJvamEgemFwaXNhIFwiKS5jb25jYXQobyl9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQ2xlYXIgU2VhcmNoXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiUHJldHJhxb5pXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiTmlqZSBwcm9uYcSRZW4gbml0aSBqZWRhbiB6YXBpc1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmlrYcW+aS9zYWtyaWogc3RyYW5pY2VcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJPc3ZqZcW+aVwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIlByb21pamVuaSBwcmlrYXpcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiS29sb25lXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZ2dsZSBhbGxcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiRnVsbHNjcmVlblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJTdmVcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVmcmVzaFwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4cG9ydCBkYXRhXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiR09cIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFkdmFuY2VkIHNlYXJjaFwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbG9zZVwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY29udHJvbHNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiaHItSFJcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiaHUtSFVcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMuaHU9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJCZXTDtmx0w6lzLCBrw6lyZW0gdsOhcmpvblwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIHJla29yZCBwZXIgb2xkYWxcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIk1lZ2plbGVuw610dmUgXCIuY29uY2F0KHQsXCIgLSBcIikuY29uY2F0KG4sXCIgLyBcIikuY29uY2F0KG8sXCIgw7Zzc3plc2VuIChmaWx0ZXJlZCBmcm9tIFwiKS5jb25jYXQocixcIiB0b3RhbCByb3dzKVwiKTpcIk1lZ2plbGVuw610dmUgXCIuY29uY2F0KHQsXCIgLSBcIikuY29uY2F0KG4sXCIgLyBcIikuY29uY2F0KG8sXCIgw7Zzc3plc2VuXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNsZWFyIFNlYXJjaFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIktlcmVzw6lzXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiTmluY3MgdGFsw6FsYXRcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiTGFwb3rDsyBlbHJlanTDqXNlL21lZ2plbGVuw610w6lzZVwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBwYWdpbmF0aW9uXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkZyaXNzw610w6lzXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiw5Zzc3plY3N1ay9LaW55aXRcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiT3N6bG9wb2tcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIsOWc3N6ZXNcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVmcmVzaFwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4cG9ydCBkYXRhXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiR09cIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFkdmFuY2VkIHNlYXJjaFwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbG9zZVwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY29udHJvbHNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiaHUtSFVcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiaWQtSURcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMuaWQ9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJNZW11YXQsIG1vaG9uIHR1bmdndVwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIGJhcmlzIHBlciBoYWxhbWFuXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJNZW5hbXBpbGthbiBcIi5jb25jYXQodCxcIiBzYW1wYWkgXCIpLmNvbmNhdChuLFwiIGRhcmkgXCIpLmNvbmNhdChvLFwiIGJhcmlzIChmaWx0ZXJlZCBmcm9tIFwiKS5jb25jYXQocixcIiB0b3RhbCByb3dzKVwiKTpcIk1lbmFtcGlsa2FuIFwiLmNvbmNhdCh0LFwiIHNhbXBhaSBcIikuY29uY2F0KG4sXCIgZGFyaSBcIikuY29uY2F0KG8sXCIgYmFyaXNcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQmVyc2loa2FuIGZpbHRlclwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlBlbmNhcmlhblwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIlRpZGFrIGRpdGVtdWthbiBkYXRhIHlhbmcgY29jb2tcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiU2VtYnVueWlrYW4vVGFtcGlsa2FuIGhhbGFtYW5cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJNdWF0IHVsYW5nXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiQmVyYWxpaFwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjYXJkIHZpZXdcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNhcmQgdmlld1wifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJrb2xvbVwifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb2dnbGUgYWxsXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIkZ1bGxzY3JlZW5cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiU2VtdWFcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVmcmVzaFwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkVrc3BvciBkYXRhXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiR09cIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFkdmFuY2VkIHNlYXJjaFwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbG9zZVwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY29udHJvbHNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiaWQtSURcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiaXQtSVRcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMuaXQ9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJDYXJpY2FtZW50byBpbiBjb3Jzb1wifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIGVsZW1lbnRpIHBlciBwYWdpbmFcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIlZpc3VhbGl6emF6aW9uZSBkYSBcIi5jb25jYXQodCxcIiBhIFwiKS5jb25jYXQobixcIiBkaSBcIikuY29uY2F0KG8sXCIgZWxlbWVudGkgKGZpbHRyYXRpIGRhIFwiKS5jb25jYXQocixcIiBlbGVtZW50aSB0b3RhbGkpXCIpOlwiVmlzdWFsaXp6YXppb25lIGRhIFwiLmNvbmNhdCh0LFwiIGEgXCIpLmNvbmNhdChuLFwiIGRpIFwiKS5jb25jYXQobyxcIiBlbGVtZW50aVwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwicGFnaW5hIHByZWNlZGVudGVcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJhbGxhIHBhZ2luYSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwYWdpbmEgc3VjY2Vzc2l2YVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiTW9zdHJhbmRvIFwiLmNvbmNhdCh0LFwiIGVsZW1lbnRpXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiUHVsaXNjaSBmaWx0cmlcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJDZXJjYVwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIk5lc3N1biBlbGVtZW50byB0cm92YXRvXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk5hc2NvbmRpL01vc3RyYSBwYWdpbmF6aW9uZVwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwiTW9zdHJhIHBhZ2luYXppb25lXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwiTmFzY29uZGkgcGFnaW5hemlvbmVcIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQWdnaW9ybmFcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdHRpdmEvRGlzYXR0aXZhXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJNb3N0cmEgdmlzdWFsZSBhIHNjaGVkYVwifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIk5hc2NvbmRpIHZpc3VhbGUgYSBzY2hlZGFcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiQ29sb25uZVwifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJNb3N0cmEgdHV0dGVcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiU2NoZXJtbyBpbnRlcm9cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiVHV0dG9cIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gQWdnaW9ybmFtZW50b1wifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkVzcG9ydGEgZGF0aVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIlZBSVwifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiRmlsdHJpIGF2YW56YXRpXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNoaXVkaVwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY29udHJvbHNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiaXQtSVRcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiamEtSlBcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMuamE9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCLoqq3jgb/ovrzjgb/kuK3jgafjgZnjgILlsJHjgIXjgYrlvoXjgaHjgY/jgaDjgZXjgYTjgIJcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCLjg5rjg7zjgrjlvZPjgZ/jgormnIDlpKdcIi5jb25jYXQodCxcIuS7tlwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wi5YWoXCIuY29uY2F0KG8sXCLku7bjgYvjgonjgIFcIikuY29uY2F0KHQsXCLjgYvjgolcIikuY29uY2F0KG4sXCLku7bnm67jgb7jgafooajnpLrjgZfjgabjgYTjgb7jgZkgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwi5YWoXCIuY29uY2F0KG8sXCLku7bjgYvjgonjgIFcIikuY29uY2F0KHQsXCLjgYvjgolcIikuY29uY2F0KG4sXCLku7bnm67jgb7jgafooajnpLrjgZfjgabjgYTjgb7jgZlcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQ2xlYXIgU2VhcmNoXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwi5qSc57SiXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwi6Kmy5b2T44GZ44KL44Os44Kz44O844OJ44GM6KaL44Gk44GL44KK44G+44Gb44KTXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIuODmuODvOOCuOaVsOOCkuihqOekuuODu+mdnuihqOekulwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBwYWdpbmF0aW9uXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIuabtOaWsFwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIuODiOOCsOODq1wifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjYXJkIHZpZXdcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNhcmQgdmlld1wifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCLliJdcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIuOBmeOBueOBplwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0IGRhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJqYS1KUFwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJrYS1HRVwiXT1vLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcy5rYT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIuGDmOGDouGDleGDmOGDoOGDl+GDlOGDkeGDkCwg4YOS4YOX4YOu4YOd4YOV4YOXIOGDm+GDneGDmOGDquGDkOGDk+GDneGDl1wifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIOGDqeGDkOGDnOGDkOGDrOGDlOGDoOGDmCDhg5fhg5jhg5fhg50g4YOS4YOV4YOU4YOg4YOT4YOW4YOUXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCLhg5zhg5Dhg6nhg5Xhg5Thg5zhg5Thg5Hhg5jhg5AgXCIuY29uY2F0KHQsXCIt4YOT4YOQ4YOcIFwiKS5jb25jYXQobixcIi3hg5vhg5Phg5Qg4YOp4YOQ4YOc4YOQ4YOs4YOU4YOg4YOYIOGDr+GDkOGDm+GDo+GDoOGDmCBcIikuY29uY2F0KG8sXCIt4YOT4YOQ4YOcIChmaWx0ZXJlZCBmcm9tIFwiKS5jb25jYXQocixcIiB0b3RhbCByb3dzKVwiKTpcIuGDnOGDkOGDqeGDleGDlOGDnOGDlOGDkeGDmOGDkCBcIi5jb25jYXQodCxcIi3hg5Phg5Dhg5wgXCIpLmNvbmNhdChuLFwiLeGDm+GDk+GDlCDhg6nhg5Dhg5zhg5Dhg6zhg5Thg6Dhg5gg4YOv4YOQ4YOb4YOj4YOg4YOYIFwiKS5jb25jYXQobyxcIi3hg5Phg5Dhg5xcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQ2xlYXIgU2VhcmNoXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwi4YOr4YOU4YOR4YOc4YOQXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwi4YOb4YOd4YOc4YOQ4YOq4YOU4YOb4YOU4YOR4YOYIOGDkOGDoCDhg5Dhg6Dhg5jhg6FcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwi4YOS4YOV4YOU4YOg4YOT4YOU4YOR4YOY4YOhIOGDkuGDkOGDk+GDkOGDm+GDoOGDl+GDleGDlOGDmuGDmOGDoSDhg5Phg5Dhg5vhg5Dhg5rhg5Xhg5Av4YOS4YOQ4YOb4YOd4YOp4YOU4YOc4YOQXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwi4YOS4YOQ4YOc4YOQ4YOu4YOa4YOU4YOR4YOQXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwi4YOp4YOQ4YOg4YOX4YOV4YOQL+GDkuGDkOGDm+GDneGDoOGDl+GDleGDkFwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjYXJkIHZpZXdcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNhcmQgdmlld1wifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCLhg6Hhg5Xhg5Thg6Lhg5Thg5Hhg5hcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkFsbFwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0IGRhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJrYS1HRVwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJrby1LUlwiXT1vLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcy5rbz17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIuuNsOydtO2EsOulvCDrtojrn6zsmKTripQg7KSR7J6F64uI64ukXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwi7Y6Y7J207KeAIOuLuSBcIi5jb25jYXQodCxcIuqwnCDrjbDsnbTthLAg7Lac66ClXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCLsoITssrQgXCIuY29uY2F0KG8sXCLqsJwg7KSRIFwiKS5jb25jYXQodCxcIn5cIikuY29uY2F0KG4sXCLrsojsp7gg642w7J207YSwIOy2nOugpSwgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwi7KCE7LK0IFwiLmNvbmNhdChvLFwi6rCcIOykkSBcIikuY29uY2F0KHQsXCJ+XCIpLmNvbmNhdChuLFwi67KI7Ke4IOuNsOydtO2EsCDstpzroKUsXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNsZWFyIFNlYXJjaFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIuqygOyDiVwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIuyhsO2ajOuQnCDrjbDsnbTthLDqsIAg7JeG7Iq164uI64ukLlwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBwYWdpbmF0aW9uXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIuyDiOuhnCDqs6DsuahcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCLsoITtmZhcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwi7Lus65+8IO2VhO2EsOungVwifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb2dnbGUgYWxsXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIkZ1bGxzY3JlZW5cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiQWxsXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnQgZGF0YVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImtvLUtSXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcIm1zLU1ZXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLm1zPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiUGVybWludGFhbiBzZWRhbmcgZGltdWF0a2FuLiBTaWxhIHR1bmdndSBzZWJlbnRhclwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIHJla29kIHNldGlhcCBtdWthIHN1cmF0XCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJTZWRhbmcgbWVtYXBhcmthbiByZWtvZCBcIi5jb25jYXQodCxcIiBoaW5nZ2EgXCIpLmNvbmNhdChuLFwiIGRhcmlwYWRhIGp1bWxhaCBcIikuY29uY2F0KG8sXCIgcmVrb2QgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiU2VkYW5nIG1lbWFwYXJrYW4gcmVrb2QgXCIuY29uY2F0KHQsXCIgaGluZ2dhIFwiKS5jb25jYXQobixcIiBkYXJpcGFkYSBqdW1sYWggXCIpLmNvbmNhdChvLFwiIHJla29kXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNsZWFyIFNlYXJjaFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhcmlcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCJUaWFkYSByZWtvZCB5YW5nIG1lbnlhbWFpIHBlcm1pbnRhYW5cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiVHVuanVrL3NlbWJ1bnlpIG11a2Egc3VyYXRcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJNdWF0c2VtdWxhXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiVHVrYXJcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiTGFqdXJcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIlNlbXVhXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnQgZGF0YVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcIm1zLU1ZXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcIm5iLU5PXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLm5iPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiT3BwZGF0ZXJlciwgdmVubmxpZ3N0IHZlbnRcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiBwb3N0ZXIgcHIgc2lkZVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiVmlzZXIgXCIuY29uY2F0KHQsXCIgdGlsIFwiKS5jb25jYXQobixcIiBhdiBcIikuY29uY2F0KG8sXCIgcmVra2VyIChmaWx0ZXJlZCBmcm9tIFwiKS5jb25jYXQocixcIiB0b3RhbCByb3dzKVwiKTpcIlZpc2VyIFwiLmNvbmNhdCh0LFwiIHRpbCBcIikuY29uY2F0KG4sXCIgYXYgXCIpLmNvbmNhdChvLFwiIHJla2tlclwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwicHJldmlvdXMgcGFnZVwifSxmb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dDpmdW5jdGlvbih0KXtyZXR1cm5cInRvIHBhZ2UgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwibmV4dCBwYWdlXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCJTaG93aW5nIFwiLmNvbmNhdCh0LFwiIHJvd3NcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbGVhciBTZWFyY2hcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJTw7hrXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiSW5nZW4gcG9zdGVyIGZ1bm5ldFwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBwYWdpbmF0aW9uXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk9wcGRhdGVyXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiRW5kcmVcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiS29sb25uZXJcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkFsbFwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0IGRhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJuYi1OT1wiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJubC1CRVwiXT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIkxhZGVuLCBldmVuIGdlZHVsZFwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIHJlY29yZHMgcGVyIHBhZ2luYVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiVG9vbiBcIi5jb25jYXQodCxcIiB0b3QgXCIpLmNvbmNhdChuLFwiIHZhbiBcIikuY29uY2F0KG8sXCIgcmVjb3JkXCIpLmNvbmNhdChvPjE/XCJzXCI6XCJcIixcIiAoZ2VmaWx0ZXJkIHZhbiBcIikuY29uY2F0KHIsXCIgcmVjb3JkcyBpbiB0b3RhYWwpXCIpOlwiVG9vbiBcIi5jb25jYXQodCxcIiB0b3QgXCIpLmNvbmNhdChuLFwiIHZhbiBcIikuY29uY2F0KG8sXCIgcmVjb3JkXCIpLmNvbmNhdChvPjE/XCJzXCI6XCJcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInZvcmlnZSBwYWdpbmFcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0b3QgcGFnaW5hIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInZvbGdlbmRlIHBhZ2luYVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiVG9vbiBcIi5jb25jYXQodCxcIiByZWNvcmRcIikuY29uY2F0KHQ+MT9cInNcIjpcIlwiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlZlcndpamRlciBmaWx0ZXJzXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiWm9la2VuXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiR2VlbiByZXN1bHRhdGVuIGdldm9uZGVuXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlZlcmJlcmcvVG9vbiBwYWdpbmVyaW5nXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb29uIHBhZ2luZXJpbmdcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJWZXJiZXJnIHBhZ2luZXJpbmdcIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiVmVybmlldXdlblwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIk9tc2NoYWtlbGVuXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb29uIGthYXJ0d2VlcmdhdmVcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJWZXJiZXJnIGthYXJ0d2VlcmdhdmVcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiS29sb21tZW5cIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiQWxsZW4gb21zY2hha2VsZW5cIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiVm9sbGVkaWcgc2NoZXJtXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkFsbGVcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG9tYXRpc2NoIHZlcm5pZXV3ZW5cIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnRlZXIgZ2VnZXZlbnNcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHQVwifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiR2VhdmFuY2VlcmQgem9la2VuXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIlNsdWl0ZW5cIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiVmVyYmVyZy9Ub29uIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJWZXJiZXJnIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJUb29uIGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcIm5sLUJFXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcIm5sLU5MXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLm5sPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiTGFkZW4sIGV2ZW4gZ2VkdWxkXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcmVjb3JkcyBwZXIgcGFnaW5hXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJUb29uIFwiLmNvbmNhdCh0LFwiIHRvdCBcIikuY29uY2F0KG4sXCIgdmFuIFwiKS5jb25jYXQobyxcIiByZWNvcmRcIikuY29uY2F0KG8+MT9cInNcIjpcIlwiLFwiIChnZWZpbHRlcmQgdmFuIFwiKS5jb25jYXQocixcIiByZWNvcmRzIGluIHRvdGFhbClcIik6XCJUb29uIFwiLmNvbmNhdCh0LFwiIHRvdCBcIikuY29uY2F0KG4sXCIgdmFuIFwiKS5jb25jYXQobyxcIiByZWNvcmRcIikuY29uY2F0KG8+MT9cInNcIjpcIlwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwidm9yaWdlIHBhZ2luYVwifSxmb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dDpmdW5jdGlvbih0KXtyZXR1cm5cInRvdCBwYWdpbmEgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwidm9sZ2VuZGUgcGFnaW5hXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCJUb29uIFwiLmNvbmNhdCh0LFwiIHJlY29yZFwiKS5jb25jYXQodD4xP1wic1wiOlwiXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiVmVyd2lqZGVyIGZpbHRlcnNcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJab2VrZW5cIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCJHZWVuIHJlc3VsdGF0ZW4gZ2V2b25kZW5cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiVmVyYmVyZy9Ub29uIHBhZ2luZXJpbmdcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlRvb24gcGFnaW5lcmluZ1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIlZlcmJlcmcgcGFnaW5lcmluZ1wifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJWZXJuaWV1d2VuXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiT21zY2hha2VsZW5cIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlRvb24ga2FhcnR3ZWVyZ2F2ZVwifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIlZlcmJlcmcga2FhcnR3ZWVyZ2F2ZVwifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJLb2xvbW1lblwifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJBbGxlbiBvbXNjaGFrZWxlblwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJWb2xsZWRpZyBzY2hlcm1cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiQWxsZVwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0b21hdGlzY2ggdmVybmlldXdlblwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4cG9ydGVlciBnZWdldmVuc1wifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdBXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJHZWF2YW5jZWVyZCB6b2VrZW5cIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiU2x1aXRlblwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJWZXJiZXJnL1Rvb24gY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIlZlcmJlcmcgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvb24gY29udHJvbHNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wibmwtTkxcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wicGwtUExcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMucGw9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJLb3BpdWogd2llcnN6ZVwifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIsWBYWRvd2FuaWUsIHByb3N6xJkgY3pla2HEh1wifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIHJla29yZMOzdyBuYSBzdHJvbsSZXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJXecWbd2lldGxhbmllIHJla29yZMOzdyBvZCBcIi5jb25jYXQodCxcIiBkbyBcIikuY29uY2F0KG4sXCIgeiBcIikuY29uY2F0KG8sXCIgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiV3nFm3dpZXRsYW5pZSByZWtvcmTDs3cgb2QgXCIuY29uY2F0KHQsXCIgZG8gXCIpLmNvbmNhdChuLFwiIHogXCIpLmNvbmNhdChvKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwicG9wcnplZG5pYSBzdHJvbmFcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ6IFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5hc3TEmXBuYSBzdHJvbmFcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIld5xZt3aWV0bGEgXCIuY29uY2F0KHQsXCIgd2llcnN6eVwiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIld5Y3p5xZvEhyB3eXN6dWtpd2FuaWVcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJTenVrYWpcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCJOaWVzdGV0eSwgbmljIG5pZSB6bmFsZXppb25vXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlBva2HFvC91a3J5aiBzdHJvbmljb3dhbmllXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJQb2thxbwgc3Ryb25pY293YW5pZVwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIlVrcnlqIHN0cm9uaWNvd2FuaWVcIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiT2TFm3dpZcW8XCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiUHJ6ZcWCxIVjelwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiUG9rYcW8IHVrxYJhZCBrYXJ0eVwifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIlVrcnlqIHVrxYJhZCBrYXJ0eVwifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJLb2x1bW55XCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlphem5hY3ogd3N6eXN0a29cIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiRnVsbHNjcmVlblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJXc3p5c3RraWVcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gb2TFm3dpZcW8YW5pZVwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkVrc3BvcnQgZGFueWNoXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiUHJ6ZWpkxbpcIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIld5c3p1a2l3YW5pZSB6YWF3YW5zb3dhbmVcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiWmFta25palwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJQb2thxbwvVWtyeWpcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIlBva2HFvFwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiVWtyeWpcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wicGwtUExcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wicHQtQlJcIl09e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJDYXJyZWdhbmRvLCBhZ3VhcmRlXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcmVnaXN0cm9zIHBvciBww6FnaW5hXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJFeGliaW5kbyBcIi5jb25jYXQodCxcIiBhdMOpIFwiKS5jb25jYXQobixcIiBkZSBcIikuY29uY2F0KG8sXCIgbGluaGFzIChmaWx0cmFkYXMgZGUgdW0gdG90YWwgZGUgXCIpLmNvbmNhdChyLFwiIGxpbmhhcylcIik6XCJFeGliaW5kbyBcIi5jb25jYXQodCxcIiBhdMOpIFwiKS5jb25jYXQobixcIiBkZSBcIikuY29uY2F0KG8sXCIgbGluaGFzXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJww6FnaW5hIGFudGVyaW9yXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwiUGFyYSBhIHDDoWdpbmEgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwicHLDs3hpbWEgcMOhZ2luYVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiTW9zdHJhbmRvIFwiLmNvbmNhdCh0LFwiIGxpbmhhc1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkxpbXBhciBQZXNxdWlzYVwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlBlc3F1aXNhclwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIk5lbmh1bSByZWdpc3RybyBlbmNvbnRyYWRvXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIvRXhpYmlyIHBhZ2luYcOnw6NvXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJNb3N0cmFyIFBhZ2luYcOnw6NvXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwiRXNjb25kZXIgUGFnaW5hw6fDo29cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiUmVjYXJyZWdhclwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkFsdGVybmFyXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNhcmQgdmlld1wifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY2FyZCB2aWV3XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvbHVuYXNcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiQWx0ZXJuYXIgdHVkb1wifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJUZWxhIGNoZWlhXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIlR1ZG9cIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF0dWFsaXphw6fDo28gQXV0b23DoXRpY2FcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnRhciBkYWRvc1wifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIklSXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJQZXNxdWlzYSBBdmFuw6dhZGFcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiRmVjaGFyXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIvRXhpYmlyIGNvbnRyb2xlc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiT2N1bHRhciBjb250cm9sZXNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4aWJpciBjb250cm9sZXNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wicHQtQlJcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wicHQtUFRcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMucHQ9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3BpYXIgTGluaGFzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJJbXByaW1pclwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiQSBjYXJyZWdhciwgcG9yIGZhdm9yIGFndWFyZGVcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiByZWdpc3RvcyBwb3IgcMOhZ2luYVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiQSBtb3N0cmFyIFwiLmNvbmNhdCh0LFwiIGF0JmVhY3V0ZTsgXCIpLmNvbmNhdChuLFwiIGRlIFwiKS5jb25jYXQobyxcIiBsaW5oYXMgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiQSBtb3N0cmFyIFwiLmNvbmNhdCh0LFwiIGF0w6kgXCIpLmNvbmNhdChuLFwiIGRlIFwiKS5jb25jYXQobyxcIiBsaW5oYXNcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInDDoWdpbmEgYW50ZXJpb3JcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJpciBwYXJhIHDDoWdpbmEgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwicHLDs3hpbWEgcMOhZ2luYVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiTW9zdHJhbmRvIFwiLmNvbmNhdCh0LFwiIGxpbmhhc1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkxpbXBhciBQZXNxdWlzYVwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlBlc3F1aXNhXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiTmVuaHVtIHJlZ2lzdG8gZW5jb250cmFkb1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJFc2NvbmRlci9Nb3N0cmFyIHBhZ2luYcOnw6NvXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJNb3N0cmFyIHDDoWdpbmFcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJFc2NvbmRlciBww6FnaW5hXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFjdHVhbGl6YXJcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCJBbHRlcm5hclwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjYXJkIHZpZXdcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNhcmQgdmlld1wifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb2x1bmFzXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIkFjdGl2YXIgdHVkb1wifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJFY3LDoyBjb21wbGV0b1wifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJUdWRvXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBY3R1YWxpemHDp8OjbyBhdXRtw6F0aWNhXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0YXIgZGFkb3NcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdmFuw6dhclwifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiUGVzcXVpc2EgYXZhbsOnYWRhXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkZlY2hhclwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJFc2NvbmRlci9FeGliaXIgY29udHJvbG9zXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJFc2NvbmRlciBjb250cm9sb3NcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4aWJpciBjb250cm9sb3NcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wicHQtUFRcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wicm8tUk9cIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMucm89e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJTZSBpbmNhcmNhLCB2YSBydWdhbSBhc3RlcHRhdGlcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiBpbnJlZ2lzdHJhcmkgcGUgcGFnaW5hXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJBcmF0YSBkZSBsYSBcIi5jb25jYXQodCxcIiBwYW5hIGxhIFwiKS5jb25jYXQobixcIiBkaW4gXCIpLmNvbmNhdChvLFwiIHJhbmR1cmkgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiQXJhdGEgZGUgbGEgXCIuY29uY2F0KHQsXCIgcGFuYSBsYSBcIikuY29uY2F0KG4sXCIgZGluIFwiKS5jb25jYXQobyxcIiByYW5kdXJpXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNsZWFyIFNlYXJjaFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhdXRhXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiTnUgYXUgZm9zdCBnYXNpdGUgaW5yZWdpc3RyYXJpXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFzY3VuZGUvQXJhdGEgcGFnaW5hdGlhXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiUmVpbmNhcmNhXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiQ29tdXRhXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNhcmQgdmlld1wifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY2FyZCB2aWV3XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvbG9hbmVcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvYXRlXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnQgZGF0YVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcInJvLVJPXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcInJ1LVJVXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLnJ1PXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwi0KHQutC+0L/QuNGA0L7QstCw0YLRjCDRgdGC0YDQvtC60LhcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cItCf0LXRh9Cw0YLRjFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwi0J/QvtC20LDQu9GD0LnRgdGC0LAsINC/0L7QtNC+0LbQtNC40YLQtSwg0LjQtNGR0YIg0LfQsNCz0YDRg9C30LrQsFwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiINC30LDQv9C40YHQtdC5INC90LAg0YHRgtGA0LDQvdC40YbRg1wiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wi0JfQsNC/0LjRgdC4INGBIFwiLmNvbmNhdCh0LFwiINC/0L4gXCIpLmNvbmNhdChuLFwiINC40LcgXCIpLmNvbmNhdChvLFwiICjQvtGC0YTQuNC70YzRgtGA0L7QstCw0L3Qviwg0LLRgdC10LPQviDQvdCwINGB0LXRgNCy0LXRgNC1IFwiKS5jb25jYXQocixcIiDQt9Cw0L/QuNGB0LXQuSlcIik6XCLQl9Cw0L/QuNGB0Lgg0YEgXCIuY29uY2F0KHQsXCIg0L/QviBcIikuY29uY2F0KG4sXCIg0LjQtyBcIikuY29uY2F0KG8pfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCLQv9GA0LXQtNGL0LTRg9GJ0LDRjyDRgdGC0YDQsNC90LjRhtCwXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwi0L/QtdGA0LXQudGC0Lgg0Log0YHRgtGA0LDQvdC40YbQtSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCLRgdC70LXQtNGD0Y7RidCw0Y8g0YHRgtGA0LDQvdC40YbQsFwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwi0JfQsNCz0YDRg9C20LXQvdC+IFwiLmNvbmNhdCh0LFwiINGB0YLRgNC+0LpcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLQntGH0LjRgdGC0LjRgtGMINGE0LjQu9GM0YLRgNGLXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwi0J/QvtC40YHQulwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cItCd0LjRh9C10LPQviDQvdC1INC90LDQudC00LXQvdC+XCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cItCh0LrRgNGL0YLRjC/Qn9C+0LrQsNC30LDRgtGMINC/0L7RgdGC0YDQsNC90LjRh9C90YPRjiDQvdCw0LLQuNCz0LDRhtC40Y5cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cItCf0L7QutCw0LfQsNGC0Ywg0L/QvtGB0YLRgNCw0L3QuNGH0L3Rg9GOINC90LDQstC40LPQsNGG0LjRjlwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cItCh0LrRgNGL0YLRjCDQv9C+0YHRgtGA0LDQvdC40YfQvdGD0Y4g0L3QsNCy0LjQs9Cw0YbQuNGOXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cItCe0LHQvdC+0LLQuNGC0YxcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCLQn9C10YDQtdC60LvRjtGH0LjRgtGMXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCLQn9C+0LrQsNC30LDRgtGMINC30LDQv9C40YHQuCDQsiDQstC40LTQtSDQutCw0YDRgtC+0YfQtdC6XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwi0KLQsNCx0LvQuNGH0L3Ri9C5INGA0LXQttC40Lwg0L/RgNC+0YHQvNC+0YLRgNCwXCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cItCa0L7Qu9C+0L3QutC4XCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cItCS0YvQsdGA0LDRgtGMINCy0YHQtVwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCLQn9C+0LvQvdC+0Y3QutGA0LDQvdC90YvQuSDRgNC10LbQuNC8XCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cItCS0YHQtVwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwi0JDQstGC0L7QvNCw0YLQuNGH0LXRgdC60L7QtSDQvtCx0L3QvtCy0LvQtdC90LjQtVwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cItCt0LrRgdC/0L7RgNGC0LjRgNC+0LLQsNGC0Ywg0LTQsNC90L3Ri9C1XCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwi0KHRgtGALlwifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwi0KDQsNGB0YjQuNGA0LXQvdC90YvQuSDQv9C+0LjRgdC6XCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cItCX0LDQutGA0YvRgtGMXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cItCh0LrRgNGL0YLRjC/Qn9C+0LrQsNC30LDRgtGMINC/0LDQvdC10LvRjCDQuNC90YHRgtGA0YPQvNC10L3RgtC+0LJcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cItCh0LrRgNGL0YLRjCDQv9Cw0L3QtdC70Ywg0LjQvdGB0YLRgNGD0LzQtdC90YLQvtCyXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCLQn9C+0LrQsNC30LDRgtGMINC/0LDQvdC10LvRjCDQuNC90YHRgtGA0YPQvNC10L3RgtC+0LJcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wicnUtUlVcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wic2stU0tcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMuc2s9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJTa29ww61yb3ZhxaUgcmlhZGt5XCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJWeXRsYcSNacWlXCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJQcm9zw61tIMSNYWthanRlXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgesOhem5hbW92IG5hIHN0cmFudVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiWm9icmF6ZW7DoSBcIi5jb25jYXQodCxcIi4gLSBcIikuY29uY2F0KG4sXCIuIHBvbG/FvmthIHogY2Vsa292w71jaCBcIikuY29uY2F0KG8sXCIgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiWm9icmF6ZW7DoSBcIi5jb25jYXQodCxcIi4gLSBcIikuY29uY2F0KG4sXCIuIHBvbG/FvmthIHogY2Vsa292w71jaCBcIikuY29uY2F0KG8pfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmVkY2jDoWR6YWrDumNhIHN0cmFuYVwifSxmb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dDpmdW5jdGlvbih0KXtyZXR1cm5cIm5hIHN0cmFudSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJOYXNsZWR1asO6Y2Egc3RyYW5hXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCJab2JyYXp1amUgc2EgXCIuY29uY2F0KHQsXCIgcmlhZGtvdlwiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk9kc3Ryw6HFiCBmaWx0cmVcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJWeWjEvmFkw6F2YW5pZVwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIk5lbsOhamRlbsOhIMW+aWFkbmEgdnlob3Z1asO6Y2EgcG9sb8W+a2FcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiU2tyeS9ab2JyYXogc3Ryw6Fua292YW5pZVwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwiWm9icmF6acWlIHN0csOhbmtvdmFuaWVcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJTa3J5xaUgc3Ryw6Fua292YW5pZVwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJPYm5vdmnFpVwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIlByZXBuaVwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiWm9icmF6acWlIGthcnRvdsOpIHpvYnJhemVuaWVcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJza3J5xaUga2FydG92w6kgem9icmF6ZW5pZVwifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJTdMS6cGNlXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlByZXBuw7rFpSB2xaFldGt5XCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIkNlbMOhIG9icmF6b3ZrYVwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJWxaFldGt5XCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvbWF0aWNrw6kgb2Jub3ZlbmllXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0dWogZMOhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCLDjXPFpVwifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiUG9rcm/EjWlsw6kgdnloxL5hZMOhdmFuaWVcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiWmF0dm9yacWlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlpvYnJhemnFpS9Ta3J5xaUgdGxhxI1pZGzDoVwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiU2tyecWlIHRsYcSNaWRsw6FcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlpvYnJhemnFpSB0bGHEjWlkbMOhXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcInNrLVNLXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcInNyLUN5cmwtUlNcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMuc3I9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCLQnNC+0LvQuNC8INGB0LDRh9C10LrQsNGYXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIg0YDQtdC00L7QstCwINC/0L4g0YHRgtGA0LDQvdC4XCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCLQn9GA0LjQutCw0LfQsNC90L4gXCIuY29uY2F0KHQsXCIuIC0gXCIpLmNvbmNhdChuLFwiLiDQvtC0INGD0LrRg9C/0L3QvtCzINCx0YDQvtGY0LAg0YDQtdC00L7QstCwIFwiKS5jb25jYXQobyxcIiAo0YTQuNC70YLRgNC40YDQsNC90L4g0L7QtCBcIikuY29uY2F0KHIsXCIpXCIpOlwi0J/RgNC40LrQsNC30LDQvdC+IFwiLmNvbmNhdCh0LFwiLiAtIFwiKS5jb25jYXQobixcIi4g0L7QtCDRg9C60YPQv9C90L7QsyDQsdGA0L7RmNCwINGA0LXQtNC+0LLQsCBcIikuY29uY2F0KG8pfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCLQv9GA0LXRgtGF0L7QtNC90LAg0YHRgtGA0LDQvdCwXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwi0L3QsCDRgdGC0YDQsNC90YMgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwi0YHQu9C10LTQtdGb0LAg0YHRgtGA0LDQvdCwXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCLQn9GA0LjQutCw0LfQsNC90L4gXCIuY29uY2F0KHQsXCIg0YDQtdC00L7QstCwXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwi0J7QsdGA0LjRiNC4INC/0YDQtdGC0YDQsNCz0YNcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLQn9GA0L7QvdCw0ZLQuFwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cItCd0LjRmNC1INC/0YDQvtC90LDRktC10L0g0L3QuCDRmNC10LTQsNC9INC/0L7QtNCw0YLQsNC6XCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cItCf0YDQuNC60LDQttC4L9GB0LDQutGA0LjRmCDQv9Cw0LPQuNC90LDRhtC40ZjRg1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwi0J/RgNC40LrQsNC20Lgg0L/QsNCz0LjQvdCw0YbQuNGY0YNcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCLQodCw0LrRgNC40Zgg0L/QsNCz0LjQvdCw0YbQuNGY0YNcIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwi0J7RgdCy0LXQttC4XCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwi0J/RgNC+0LzQtdC90Lgg0L/RgNC40LrQsNC3XCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCLQn9GA0LjQutCw0LbQuCDQutCw0YDRgtC40YbQtVwifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cItCh0LDQutGA0LjRmCDQutCw0YDRgtC40YbQtVwifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCLQmtC+0LvQvtC90LVcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwi0J/RgNC40LrQsNC20Lgv0YHQsNC60YDQuNGYINGB0LLQtVwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCLQptC10L4g0LXQutGA0LDQvVwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCLQodCy0LVcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cItCQ0YPRgtC+0LzQsNGC0YHQutC+INC+0YHQstC10LbQsNCy0LDRmtC1XCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwi0JjQt9Cy0LXQt9C4INC/0L7QtNCw0YLQutC1XCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwi0JjQtNC4XCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLQndCw0L/RgNC10LTQvdCwINC/0YDQtdGC0YDQsNCz0LBcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwi0JfQsNGC0LLQvtGA0LhcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcInNyLUN5cmwtUlNcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wic3ItTGF0bi1SU1wiXT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIk1vbGltIHNhxI1la2FqXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcmVkb3ZhIHBvIHN0cmFuaVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiUHJpa2F6YW5vIFwiLmNvbmNhdCh0LFwiLiAtIFwiKS5jb25jYXQobixcIi4gb2QgdWt1cG5vZyBicm9qYSByZWRvdmEgXCIpLmNvbmNhdChvLFwiIChmaWx0cmlyYW5vIG9kIFwiKS5jb25jYXQocixcIilcIik6XCJQcmlrYXphbm8gXCIuY29uY2F0KHQsXCIuIC0gXCIpLmNvbmNhdChuLFwiLiBvZCB1a3Vwbm9nIGJyb2phIHJlZG92YSBcIikuY29uY2F0KG8pfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV0aG9kbmEgc3RyYW5hXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwibmEgc3RyYW51IFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInNsZWRlxIdhIHN0cmFuYVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiUHJpa2F6YW5vIFwiLmNvbmNhdCh0LFwiIHJlZG92YVwiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk9icmnFoWkgcHJldHJhZ3VcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJQcm9uYcSRaVwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIk5pamUgcHJvbmHEkWVuIG5pIGplZGFuIHBvZGF0YWtcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiUHJpa2HFvmkvc2FrcmlqIHBhZ2luYWNpanVcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlByaWthxb5pIHBhZ2luYWNpanVcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJTYWtyaWogcGFnaW5hY2lqdVwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJPc3Zlxb5pXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiUHJvbWVuaSBwcmlrYXpcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlByaWthxb5pIGthcnRpY2VcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJTYWtyaWoga2FydGljZVwifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJLb2xvbmVcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiUHJpa2HFvmkvc2FrcmlqIHN2ZVwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJDZW8gZWtyYW5cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiU3ZlXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvbWF0c2tvIG9zdmXFvmF2YW5qZVwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkl6dmV6aSBwb2RhdGtlXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiSWRpXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJOYXByZWRuYSBwcmV0cmFnYVwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJaYXR2b3JpXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJzci1MYXRuLVJTXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcInN2LVNFXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLnN2PXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiTGFkZGFyLCB2w6RubGlnZW4gdsOkbnRhXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcmFkZXIgcGVyIHNpZGFcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIlZpc2EgXCIuY29uY2F0KHQsXCIgdGlsbCBcIikuY29uY2F0KG4sXCIgYXYgXCIpLmNvbmNhdChvLFwiIHJhZGVyIChmaWx0ZXJlZCBmcm9tIFwiKS5jb25jYXQocixcIiB0b3RhbCByb3dzKVwiKTpcIlZpc2EgXCIuY29uY2F0KHQsXCIgdGlsbCBcIikuY29uY2F0KG4sXCIgYXYgXCIpLmNvbmNhdChvLFwiIHJhZGVyXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNsZWFyIFNlYXJjaFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlPDtmtcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCJJbmdhIG1hdGNoYW5kZSByZXN1bHRhdCBmdW5uYS5cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJVcHBkYXRlcmFcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCJTa2lmdGFcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwia29sdW1uXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZ2dsZSBhbGxcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiRnVsbHNjcmVlblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJBbGxcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVmcmVzaFwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4cG9ydCBkYXRhXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiR09cIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFkdmFuY2VkIHNlYXJjaFwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbG9zZVwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY29udHJvbHNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wic3YtU0VcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1widGgtVEhcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMudGg9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCLguIHguLPguKXguLHguIfguYLguKvguKXguJTguILguYnguK3guKHguLnguKUsIOC4geC4o+C4uOC4k+C4suC4o+C4reC4quC4seC4geC4hOC4o+C4ueC5iFwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIOC4o+C4suC4ouC4geC4suC4o+C4leC5iOC4reC4q+C4meC5ieC4slwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wi4Lij4Liy4Lii4LiB4Liy4Lij4LiX4Li14LmIIFwiLmNvbmNhdCh0LFwiIOC4luC4tuC4hyBcIikuY29uY2F0KG4sXCIg4LiI4Liy4LiB4LiX4Lix4LmJ4LiH4Lir4Lih4LiUIFwiKS5jb25jYXQobyxcIiDguKPguLLguKLguIHguLLguKMgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwi4Lij4Liy4Lii4LiB4Liy4Lij4LiX4Li14LmIIFwiLmNvbmNhdCh0LFwiIOC4luC4tuC4hyBcIikuY29uY2F0KG4sXCIg4LiI4Liy4LiB4LiX4Lix4LmJ4LiH4Lir4Lih4LiUIFwiKS5jb25jYXQobyxcIiDguKPguLLguKLguIHguLLguKNcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQ2xlYXIgU2VhcmNoXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwi4LiE4LmJ4LiZ4Lir4LiyXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwi4LmE4Lih4LmI4Lie4Lia4Lij4Liy4Lii4LiB4Liy4Lij4LiX4Li14LmI4LiE4LmJ4LiZ4Lir4LiyICFcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLguKPguLXguYDguJ/guKPguKpcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCLguKrguKXguLHguJrguKHguLjguKHguKHguK3guIdcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwi4LiE4Lit4Lil4Lix4Lih4LiZ4LmMXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZ2dsZSBhbGxcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiRnVsbHNjcmVlblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJBbGxcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVmcmVzaFwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4cG9ydCBkYXRhXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiR09cIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFkdmFuY2VkIHNlYXJjaFwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbG9zZVwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY29udHJvbHNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1widGgtVEhcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1widHItVFJcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMudHI9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJZw7xrbGVuaXlvciwgbMO8dGZlbiBiZWtsZXlpblwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlNheWZhIGJhxZ/EsW5hIFwiLmNvbmNhdCh0LFwiIGthecSxdC5cIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIlwiLmNvbmNhdChvLFwiIGthecSxdHRhbiBcIikuY29uY2F0KHQsXCItXCIpLmNvbmNhdChuLFwiIGFyYXPEsSBnw7ZzdGVyaWxpeW9yIChmaWx0ZXJlZCBmcm9tIFwiKS5jb25jYXQocixcIiB0b3RhbCByb3dzKS5cIik6XCJcIi5jb25jYXQobyxcIiBrYXnEsXR0YW4gXCIpLmNvbmNhdCh0LFwiLVwiKS5jb25jYXQobixcIiBhcmFzxLEgZ8O2c3RlcmlsaXlvci5cIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQ2xlYXIgU2VhcmNoXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQXJhXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiRcWfbGXFn2VuIGthecSxdCBidWx1bmFtYWTEsS5cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJZZW5pbGVcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCJEZcSfacWfdGlyXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNhcmQgdmlld1wifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY2FyZCB2aWV3XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cIlPDvHR1bmxhclwifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb2dnbGUgYWxsXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIkZ1bGxzY3JlZW5cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiVMO8bSBTYXTEsXJsYXJcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVmcmVzaFwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4cG9ydCBkYXRhXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiR09cIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFkdmFuY2VkIHNlYXJjaFwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbG9zZVwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY29udHJvbHNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1widHItVFJcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1widWstVUFcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMudWs9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCLQl9Cw0LLQsNC90YLQsNC20LXQvdC90Y8sINCx0YPQtNGMINC70LDRgdC60LAsINC30LDRh9C10LrQsNC50YLQtVwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiINC30LDQv9C40YHRltCyINC90LAg0YHRgtC+0YDRltC90LrRg1wiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wi0J/QvtC60LDQt9Cw0L3QviDQtyBcIi5jb25jYXQodCxcIiDQv9C+IFwiKS5jb25jYXQobixcIi4g0JLRgdGM0L7Qs9C+OiBcIikuY29uY2F0KG8sXCIgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwi0J/QvtC60LDQt9Cw0L3QviDQtyBcIi5jb25jYXQodCxcIiDQv9C+IFwiKS5jb25jYXQobixcIi4g0JLRgdGM0L7Qs9C+OiBcIikuY29uY2F0KG8pfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cItCe0YfQuNGB0YLQuNGC0Lgg0YTRltC70YzRgtGA0LhcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLQn9C+0YjRg9C6XCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwi0J3QtSDQt9C90LDQudC00LXQvdC+INC20L7QtNC90L7Qs9C+INC30LDQv9C40YHRg1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBwYWdpbmF0aW9uXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cItCe0L3QvtCy0LjRgtC4XCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwi0JfQvNGW0L3QuNGC0LhcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwi0KHRgtC+0LLQv9GG0ZZcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkFsbFwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0IGRhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJ1ay1VQVwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJ1ci1QS1wiXT1vLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcy51cj17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cItio2LHYp9uTINmF24HYsdio2KfZhtuMINin2YbYqti42KfYsSDaqduM2KzYptuSXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIg2LHbjNqp2KfYsdqI2LIg2YHbjCDYtdmB24EgXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCLYr9uM2qnavtuM2rogXCIuY29uY2F0KHQsXCIg2LPbkiBcIikuY29uY2F0KG4sXCIg2qnbkiBcIikuY29uY2F0KG8sXCLYsduM2qnYp9ix2ojYsiAoZmlsdGVyZWQgZnJvbSBcIikuY29uY2F0KHIsXCIgdG90YWwgcm93cylcIik6XCLYr9uM2qnavtuM2rogXCIuY29uY2F0KHQsXCIg2LPbkiBcIikuY29uY2F0KG4sXCIg2qnbkiBcIikuY29uY2F0KG8sXCLYsduM2qnYp9ix2ojYslwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwicHJldmlvdXMgcGFnZVwifSxmb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dDpmdW5jdGlvbih0KXtyZXR1cm5cInRvIHBhZ2UgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwibmV4dCBwYWdlXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCJTaG93aW5nIFwiLmNvbmNhdCh0LFwiIHJvd3NcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbGVhciBTZWFyY2hcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLYqtmE2KfYtFwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cItqp2YjYptuMINix24zaqdin2LHaiCDZhtuB24zauiDZhdmE2KdcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLYqtin2LLbgSDaqdix24zaulwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cItiq2KjYr9uM2YQg2qnYsduM2rpcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwi2qnYp9mE2YVcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkFsbFwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0IGRhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJ1ci1QS1wiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJ1ei1MYXRuLVVaXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLnV6PXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiWXVrbGFueWFwdGksIGlsdGltb3Mga3V0aW5nXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcWF0b3IgaGFyIHNhaGlmYWRhXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJLbydyc2F0eXBhdGkgXCIuY29uY2F0KHQsXCIgZGFuIFwiKS5jb25jYXQobixcIiBnYWNoYSBcIikuY29uY2F0KG8sXCIgcWF0b3JsYXJuaSAoZmlsdGVyZWQgZnJvbSBcIikuY29uY2F0KHIsXCIgdG90YWwgcm93cylcIik6XCJLbydyc2F0eXBhdGkgXCIuY29uY2F0KHQsXCIgZGFuIFwiKS5jb25jYXQobixcIiBnYWNoYSBcIikuY29uY2F0KG8sXCIgcWF0b3JsYXJuaVwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwicHJldmlvdXMgcGFnZVwifSxmb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dDpmdW5jdGlvbih0KXtyZXR1cm5cInRvIHBhZ2UgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwibmV4dCBwYWdlXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCJTaG93aW5nIFwiLmNvbmNhdCh0LFwiIHJvd3NcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJGaWx0cmxhcm5pIHRvemFsYXNoXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiUWlkaXJpc2hcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCJIZWNoIG5hcnNhIHRvcGlsbWFkaVwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJTYWhpZmFsYXNobmkgeWFzaGlyaXNoL2tvJ3JzYXRpc2hcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJZYW5naWxhc2hcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCJLbydyaW5pc2hcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiVXN0dW5sYXJcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkhhbW1hc2lcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVmcmVzaFwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkVrc3BvcnRcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJ1ei1MYXRuLVVaXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcInZpLVZOXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLnZpPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwixJBhbmcgdOG6o2lcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiBi4bqjbiBnaGkgbeG7l2kgdHJhbmdcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIkhp4buDbiB0aOG7iyB04burIHRyYW5nIFwiLmNvbmNhdCh0LFwiIMSR4bq/biBcIikuY29uY2F0KG4sXCIgY+G7p2EgXCIpLmNvbmNhdChvLFwiIGLhuqNuZyBnaGkgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiSGnhu4NuIHRo4buLIHThu6sgdHJhbmcgXCIuY29uY2F0KHQsXCIgxJHhur9uIFwiKS5jb25jYXQobixcIiBj4bunYSBcIikuY29uY2F0KG8sXCIgYuG6o25nIGdoaVwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwicHJldmlvdXMgcGFnZVwifSxmb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dDpmdW5jdGlvbih0KXtyZXR1cm5cInRvIHBhZ2UgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwibmV4dCBwYWdlXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCJTaG93aW5nIFwiLmNvbmNhdCh0LFwiIHJvd3NcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbGVhciBTZWFyY2hcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJUw6xtIGtp4bq/bVwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIktow7RuZyBjw7MgZOG7ryBsaeG7h3VcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJSZWZyZXNoXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNhcmQgdmlld1wifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY2FyZCB2aWV3XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvbHVtbnNcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkFsbFwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0IGRhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJ2aS1WTlwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJ6aC1DTlwiXT1vLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcy56aD17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIuato+WcqOWKquWKm+WcsOWKoOi9veaVsOaNruS4re+8jOivt+eojeWAmVwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIuavj+mhteaYvuekuiBcIi5jb25jYXQodCxcIiDmnaHorrDlvZVcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIuaYvuekuuesrCBcIi5jb25jYXQodCxcIiDliLDnrKwgXCIpLmNvbmNhdChuLFwiIOadoeiusOW9le+8jOaAu+WFsSBcIikuY29uY2F0KG8sXCIg5p2h6K6w5b2V77yI5LuOIFwiKS5jb25jYXQocixcIiDmgLvorrDlvZXkuK3ov4fmu6TvvIlcIik6XCLmmL7npLrnrKwgXCIuY29uY2F0KHQsXCIg5Yiw56ysIFwiKS5jb25jYXQobixcIiDmnaHorrDlvZXvvIzmgLvlhbEgXCIpLmNvbmNhdChvLFwiIOadoeiusOW9lVwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwi5LiK5LiA6aG1XCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwi56ysXCIuY29uY2F0KHQsXCLpobVcIil9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCLkuIvkuIDpobVcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIuaAu+WFsSBcIi5jb25jYXQodCxcIiDmnaHorrDlvZVcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLmuIXnqbrov4fmu6RcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLmkJzntKJcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCLmsqHmnInmib7liLDljLnphY3nmoTorrDlvZVcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwi6ZqQ6JePL+aYvuekuuWIhumhtVwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwi5pi+56S65YiG6aG1XCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwi6ZqQ6JeP5YiG6aG1XCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIuWIt+aWsFwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIuWIh+aNolwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwi5pi+56S65Y2h54mH6KeG5Zu+XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwi6ZqQ6JeP5Y2h54mH6KeG5Zu+XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cIuWIl1wifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCLliIfmjaLmiYDmnIlcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwi5YWo5bGPXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIuaJgOaciVwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwi6Ieq5Yqo5Yi35pawXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwi5a+85Ye65pWw5o2uXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwi6Lez6L2sXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLpq5jnuqfmkJzntKJcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwi5YWz6ZetXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIumakOiXjy/mmL7npLrov4fmu6TmjqfliLZcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIumakOiXj+i/h+a7pOaOp+WItlwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwi5pi+56S66L+H5ruk5o6n5Yi2XCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcInpoLUNOXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcInpoLVRXXCJdPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwi5q2j5Zyo5Yqq5Yqb5Zyw6LyJ5YWl6LOH5paZ77yM6KuL56iN5YCZXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwi5q+P6aCB6aGv56S6IFwiLmNvbmNhdCh0LFwiIOmgheiomOmMhFwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wi6aGv56S656ysIFwiLmNvbmNhdCh0LFwiIOWIsOesrCBcIikuY29uY2F0KG4sXCIg6aCF6KiY6YyE77yM57i95YWxIFwiKS5jb25jYXQobyxcIiDpoIXoqJjpjITvvIjlvp4gXCIpLmNvbmNhdChyLFwiIOe4veiomOmMhOS4remBjua/vu+8iVwiKTpcIumhr+ekuuesrCBcIi5jb25jYXQodCxcIiDliLDnrKwgXCIpLmNvbmNhdChuLFwiIOmgheiomOmMhO+8jOe4veWFsSBcIikuY29uY2F0KG8sXCIg6aCF6KiY6YyEXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCLkuIrkuIDpoIFcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCLnrKxcIi5jb25jYXQodCxcIumggVwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIuS4i+S4gOmggVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwi57i95YWxIFwiLmNvbmNhdCh0LFwiIOmgheiomOmMhFwiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIua4heepuumBjua/vlwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIuaQnOWwi1wifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIuaykuacieaJvuWIsOespuWQiOeahOe1kOaenFwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLpmrHol48v6aGv56S65YiG6aCBXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCLpoa/npLrliIbpoIFcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCLpmrHol4/liIbpoIFcIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwi6YeN5paw5pW055CGXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwi5YiH5o+bXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCLpoa/npLrljaHniYfoppblnJZcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCLpmrHol4/ljaHniYfoppblnJZcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwi5YiXXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIuWIh+aPm+aJgOaciVwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCLlhajlsY9cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwi5omA5pyJXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLoh6rli5XliLfmlrBcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCLlsI7lh7rmlbjmk5pcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCLot7PovYlcIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIumrmOe0muaQnOWwi1wifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCLpl5zplolcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwi6Zqx6JePL+mhr+ekuumBjua/vuaOp+WItlwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwi6Zqx6JeP6YGO5r++5o6n5Yi2XCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCLpoa/npLrpgY7mv77mjqfliLZcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiemgtVFdcIl0pfSkpO1xuIiwiKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KHJlcXVpcmUoJ2pxdWVyeScpKSA6XG4gIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2pxdWVyeSddLCBmYWN0b3J5KSA6XG4gIChnbG9iYWwgPSB0eXBlb2YgZ2xvYmFsVGhpcyAhPT0gJ3VuZGVmaW5lZCcgPyBnbG9iYWxUaGlzIDogZ2xvYmFsIHx8IHNlbGYsIGdsb2JhbC5Cb290c3RyYXBUYWJsZSA9IGZhY3RvcnkoZ2xvYmFsLmpRdWVyeSkpO1xufSh0aGlzLCAoZnVuY3Rpb24gKCQpIHsgJ3VzZSBzdHJpY3QnO1xuXG4gIGZ1bmN0aW9uIF9pbnRlcm9wRGVmYXVsdExlZ2FjeSAoZSkgeyByZXR1cm4gZSAmJiB0eXBlb2YgZSA9PT0gJ29iamVjdCcgJiYgJ2RlZmF1bHQnIGluIGUgPyBlIDogeyAnZGVmYXVsdCc6IGUgfTsgfVxuXG4gIHZhciAkX19kZWZhdWx0ID0gLyojX19QVVJFX18qL19pbnRlcm9wRGVmYXVsdExlZ2FjeSgkKTtcblxuICBmdW5jdGlvbiBfdHlwZW9mKG9iaikge1xuICAgIFwiQGJhYmVsL2hlbHBlcnMgLSB0eXBlb2ZcIjtcblxuICAgIGlmICh0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIFN5bWJvbC5pdGVyYXRvciA9PT0gXCJzeW1ib2xcIikge1xuICAgICAgX3R5cGVvZiA9IGZ1bmN0aW9uIChvYmopIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBvYmo7XG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBfdHlwZW9mID0gZnVuY3Rpb24gKG9iaikge1xuICAgICAgICByZXR1cm4gb2JqICYmIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvYmouY29uc3RydWN0b3IgPT09IFN5bWJvbCAmJiBvYmogIT09IFN5bWJvbC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogdHlwZW9mIG9iajtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIF90eXBlb2Yob2JqKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHtcbiAgICBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBfZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTtcbiAgICAgIGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTtcbiAgICAgIGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTtcbiAgICAgIGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gX2NyZWF0ZUNsYXNzKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykge1xuICAgIGlmIChwcm90b1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpO1xuICAgIGlmIChzdGF0aWNQcm9wcykgX2RlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTtcbiAgICByZXR1cm4gQ29uc3RydWN0b3I7XG4gIH1cblxuICBmdW5jdGlvbiBfc2xpY2VkVG9BcnJheShhcnIsIGkpIHtcbiAgICByZXR1cm4gX2FycmF5V2l0aEhvbGVzKGFycikgfHwgX2l0ZXJhYmxlVG9BcnJheUxpbWl0KGFyciwgaSkgfHwgX3Vuc3VwcG9ydGVkSXRlcmFibGVUb0FycmF5KGFyciwgaSkgfHwgX25vbkl0ZXJhYmxlUmVzdCgpO1xuICB9XG5cbiAgZnVuY3Rpb24gX3RvQ29uc3VtYWJsZUFycmF5KGFycikge1xuICAgIHJldHVybiBfYXJyYXlXaXRob3V0SG9sZXMoYXJyKSB8fCBfaXRlcmFibGVUb0FycmF5KGFycikgfHwgX3Vuc3VwcG9ydGVkSXRlcmFibGVUb0FycmF5KGFycikgfHwgX25vbkl0ZXJhYmxlU3ByZWFkKCk7XG4gIH1cblxuICBmdW5jdGlvbiBfYXJyYXlXaXRob3V0SG9sZXMoYXJyKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoYXJyKSkgcmV0dXJuIF9hcnJheUxpa2VUb0FycmF5KGFycik7XG4gIH1cblxuICBmdW5jdGlvbiBfYXJyYXlXaXRoSG9sZXMoYXJyKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoYXJyKSkgcmV0dXJuIGFycjtcbiAgfVxuXG4gIGZ1bmN0aW9uIF9pdGVyYWJsZVRvQXJyYXkoaXRlcikge1xuICAgIGlmICh0eXBlb2YgU3ltYm9sICE9PSBcInVuZGVmaW5lZFwiICYmIFN5bWJvbC5pdGVyYXRvciBpbiBPYmplY3QoaXRlcikpIHJldHVybiBBcnJheS5mcm9tKGl0ZXIpO1xuICB9XG5cbiAgZnVuY3Rpb24gX2l0ZXJhYmxlVG9BcnJheUxpbWl0KGFyciwgaSkge1xuICAgIGlmICh0eXBlb2YgU3ltYm9sID09PSBcInVuZGVmaW5lZFwiIHx8ICEoU3ltYm9sLml0ZXJhdG9yIGluIE9iamVjdChhcnIpKSkgcmV0dXJuO1xuICAgIHZhciBfYXJyID0gW107XG4gICAgdmFyIF9uID0gdHJ1ZTtcbiAgICB2YXIgX2QgPSBmYWxzZTtcbiAgICB2YXIgX2UgPSB1bmRlZmluZWQ7XG5cbiAgICB0cnkge1xuICAgICAgZm9yICh2YXIgX2kgPSBhcnJbU3ltYm9sLml0ZXJhdG9yXSgpLCBfczsgIShfbiA9IChfcyA9IF9pLm5leHQoKSkuZG9uZSk7IF9uID0gdHJ1ZSkge1xuICAgICAgICBfYXJyLnB1c2goX3MudmFsdWUpO1xuXG4gICAgICAgIGlmIChpICYmIF9hcnIubGVuZ3RoID09PSBpKSBicmVhaztcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIF9kID0gdHJ1ZTtcbiAgICAgIF9lID0gZXJyO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoIV9uICYmIF9pW1wicmV0dXJuXCJdICE9IG51bGwpIF9pW1wicmV0dXJuXCJdKCk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBpZiAoX2QpIHRocm93IF9lO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBfYXJyO1xuICB9XG5cbiAgZnVuY3Rpb24gX3Vuc3VwcG9ydGVkSXRlcmFibGVUb0FycmF5KG8sIG1pbkxlbikge1xuICAgIGlmICghbykgcmV0dXJuO1xuICAgIGlmICh0eXBlb2YgbyA9PT0gXCJzdHJpbmdcIikgcmV0dXJuIF9hcnJheUxpa2VUb0FycmF5KG8sIG1pbkxlbik7XG4gICAgdmFyIG4gPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobykuc2xpY2UoOCwgLTEpO1xuICAgIGlmIChuID09PSBcIk9iamVjdFwiICYmIG8uY29uc3RydWN0b3IpIG4gPSBvLmNvbnN0cnVjdG9yLm5hbWU7XG4gICAgaWYgKG4gPT09IFwiTWFwXCIgfHwgbiA9PT0gXCJTZXRcIikgcmV0dXJuIEFycmF5LmZyb20obyk7XG4gICAgaWYgKG4gPT09IFwiQXJndW1lbnRzXCIgfHwgL14oPzpVaXxJKW50KD86OHwxNnwzMikoPzpDbGFtcGVkKT9BcnJheSQvLnRlc3QobikpIHJldHVybiBfYXJyYXlMaWtlVG9BcnJheShvLCBtaW5MZW4pO1xuICB9XG5cbiAgZnVuY3Rpb24gX2FycmF5TGlrZVRvQXJyYXkoYXJyLCBsZW4pIHtcbiAgICBpZiAobGVuID09IG51bGwgfHwgbGVuID4gYXJyLmxlbmd0aCkgbGVuID0gYXJyLmxlbmd0aDtcblxuICAgIGZvciAodmFyIGkgPSAwLCBhcnIyID0gbmV3IEFycmF5KGxlbik7IGkgPCBsZW47IGkrKykgYXJyMltpXSA9IGFycltpXTtcblxuICAgIHJldHVybiBhcnIyO1xuICB9XG5cbiAgZnVuY3Rpb24gX25vbkl0ZXJhYmxlU3ByZWFkKCkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIGF0dGVtcHQgdG8gc3ByZWFkIG5vbi1pdGVyYWJsZSBpbnN0YW5jZS5cXG5JbiBvcmRlciB0byBiZSBpdGVyYWJsZSwgbm9uLWFycmF5IG9iamVjdHMgbXVzdCBoYXZlIGEgW1N5bWJvbC5pdGVyYXRvcl0oKSBtZXRob2QuXCIpO1xuICB9XG5cbiAgZnVuY3Rpb24gX25vbkl0ZXJhYmxlUmVzdCgpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiSW52YWxpZCBhdHRlbXB0IHRvIGRlc3RydWN0dXJlIG5vbi1pdGVyYWJsZSBpbnN0YW5jZS5cXG5JbiBvcmRlciB0byBiZSBpdGVyYWJsZSwgbm9uLWFycmF5IG9iamVjdHMgbXVzdCBoYXZlIGEgW1N5bWJvbC5pdGVyYXRvcl0oKSBtZXRob2QuXCIpO1xuICB9XG5cbiAgZnVuY3Rpb24gX2NyZWF0ZUZvck9mSXRlcmF0b3JIZWxwZXIobywgYWxsb3dBcnJheUxpa2UpIHtcbiAgICB2YXIgaXQ7XG5cbiAgICBpZiAodHlwZW9mIFN5bWJvbCA9PT0gXCJ1bmRlZmluZWRcIiB8fCBvW1N5bWJvbC5pdGVyYXRvcl0gPT0gbnVsbCkge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkobykgfHwgKGl0ID0gX3Vuc3VwcG9ydGVkSXRlcmFibGVUb0FycmF5KG8pKSB8fCBhbGxvd0FycmF5TGlrZSAmJiBvICYmIHR5cGVvZiBvLmxlbmd0aCA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICBpZiAoaXQpIG8gPSBpdDtcbiAgICAgICAgdmFyIGkgPSAwO1xuXG4gICAgICAgIHZhciBGID0gZnVuY3Rpb24gKCkge307XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzOiBGLFxuICAgICAgICAgIG46IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChpID49IG8ubGVuZ3RoKSByZXR1cm4ge1xuICAgICAgICAgICAgICBkb25lOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgZG9uZTogZmFsc2UsXG4gICAgICAgICAgICAgIHZhbHVlOiBvW2krK11cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfSxcbiAgICAgICAgICBlOiBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIGY6IEZcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgYXR0ZW1wdCB0byBpdGVyYXRlIG5vbi1pdGVyYWJsZSBpbnN0YW5jZS5cXG5JbiBvcmRlciB0byBiZSBpdGVyYWJsZSwgbm9uLWFycmF5IG9iamVjdHMgbXVzdCBoYXZlIGEgW1N5bWJvbC5pdGVyYXRvcl0oKSBtZXRob2QuXCIpO1xuICAgIH1cblxuICAgIHZhciBub3JtYWxDb21wbGV0aW9uID0gdHJ1ZSxcbiAgICAgICAgZGlkRXJyID0gZmFsc2UsXG4gICAgICAgIGVycjtcbiAgICByZXR1cm4ge1xuICAgICAgczogZnVuY3Rpb24gKCkge1xuICAgICAgICBpdCA9IG9bU3ltYm9sLml0ZXJhdG9yXSgpO1xuICAgICAgfSxcbiAgICAgIG46IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHN0ZXAgPSBpdC5uZXh0KCk7XG4gICAgICAgIG5vcm1hbENvbXBsZXRpb24gPSBzdGVwLmRvbmU7XG4gICAgICAgIHJldHVybiBzdGVwO1xuICAgICAgfSxcbiAgICAgIGU6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGRpZEVyciA9IHRydWU7XG4gICAgICAgIGVyciA9IGU7XG4gICAgICB9LFxuICAgICAgZjogZnVuY3Rpb24gKCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGlmICghbm9ybWFsQ29tcGxldGlvbiAmJiBpdC5yZXR1cm4gIT0gbnVsbCkgaXQucmV0dXJuKCk7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgaWYgKGRpZEVycikgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIHZhciBjb21tb25qc0dsb2JhbCA9IHR5cGVvZiBnbG9iYWxUaGlzICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbFRoaXMgOiB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnID8gc2VsZiA6IHt9O1xuXG4gIGZ1bmN0aW9uIGNyZWF0ZUNvbW1vbmpzTW9kdWxlKGZuLCBtb2R1bGUpIHtcbiAgXHRyZXR1cm4gbW9kdWxlID0geyBleHBvcnRzOiB7fSB9LCBmbihtb2R1bGUsIG1vZHVsZS5leHBvcnRzKSwgbW9kdWxlLmV4cG9ydHM7XG4gIH1cblxuICB2YXIgY2hlY2sgPSBmdW5jdGlvbiAoaXQpIHtcbiAgICByZXR1cm4gaXQgJiYgaXQuTWF0aCA9PSBNYXRoICYmIGl0O1xuICB9O1xuXG4gIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS96bG9pcm9jay9jb3JlLWpzL2lzc3Vlcy84NiNpc3N1ZWNvbW1lbnQtMTE1NzU5MDI4XG4gIHZhciBnbG9iYWxfMSA9XG4gICAgLyogZ2xvYmFsIGdsb2JhbFRoaXMgLS0gc2FmZSAqL1xuICAgIGNoZWNrKHR5cGVvZiBnbG9iYWxUaGlzID09ICdvYmplY3QnICYmIGdsb2JhbFRoaXMpIHx8XG4gICAgY2hlY2sodHlwZW9mIHdpbmRvdyA9PSAnb2JqZWN0JyAmJiB3aW5kb3cpIHx8XG4gICAgY2hlY2sodHlwZW9mIHNlbGYgPT0gJ29iamVjdCcgJiYgc2VsZikgfHxcbiAgICBjaGVjayh0eXBlb2YgY29tbW9uanNHbG9iYWwgPT0gJ29iamVjdCcgJiYgY29tbW9uanNHbG9iYWwpIHx8XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLW5ldy1mdW5jIC0tIGZhbGxiYWNrXG4gICAgKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0pKCkgfHwgRnVuY3Rpb24oJ3JldHVybiB0aGlzJykoKTtcblxuICB2YXIgZmFpbHMgPSBmdW5jdGlvbiAoZXhlYykge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gISFleGVjKCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfTtcblxuICAvLyBEZXRlY3QgSUU4J3MgaW5jb21wbGV0ZSBkZWZpbmVQcm9wZXJ0eSBpbXBsZW1lbnRhdGlvblxuICB2YXIgZGVzY3JpcHRvcnMgPSAhZmFpbHMoZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkoe30sIDEsIHsgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiA3OyB9IH0pWzFdICE9IDc7XG4gIH0pO1xuXG4gIHZhciBuYXRpdmVQcm9wZXJ0eUlzRW51bWVyYWJsZSA9IHt9LnByb3BlcnR5SXNFbnVtZXJhYmxlO1xuICB2YXIgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yJDQgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yO1xuXG4gIC8vIE5hc2hvcm4gfiBKREs4IGJ1Z1xuICB2YXIgTkFTSE9STl9CVUcgPSBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IkNCAmJiAhbmF0aXZlUHJvcGVydHlJc0VudW1lcmFibGUuY2FsbCh7IDE6IDIgfSwgMSk7XG5cbiAgLy8gYE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGVgIG1ldGhvZCBpbXBsZW1lbnRhdGlvblxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9iamVjdC5wcm90b3R5cGUucHJvcGVydHlpc2VudW1lcmFibGVcbiAgdmFyIGYkNCA9IE5BU0hPUk5fQlVHID8gZnVuY3Rpb24gcHJvcGVydHlJc0VudW1lcmFibGUoVikge1xuICAgIHZhciBkZXNjcmlwdG9yID0gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yJDQodGhpcywgVik7XG4gICAgcmV0dXJuICEhZGVzY3JpcHRvciAmJiBkZXNjcmlwdG9yLmVudW1lcmFibGU7XG4gIH0gOiBuYXRpdmVQcm9wZXJ0eUlzRW51bWVyYWJsZTtcblxuICB2YXIgb2JqZWN0UHJvcGVydHlJc0VudW1lcmFibGUgPSB7XG4gIFx0ZjogZiQ0XG4gIH07XG5cbiAgdmFyIGNyZWF0ZVByb3BlcnR5RGVzY3JpcHRvciA9IGZ1bmN0aW9uIChiaXRtYXAsIHZhbHVlKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGVudW1lcmFibGU6ICEoYml0bWFwICYgMSksXG4gICAgICBjb25maWd1cmFibGU6ICEoYml0bWFwICYgMiksXG4gICAgICB3cml0YWJsZTogIShiaXRtYXAgJiA0KSxcbiAgICAgIHZhbHVlOiB2YWx1ZVxuICAgIH07XG4gIH07XG5cbiAgdmFyIHRvU3RyaW5nID0ge30udG9TdHJpbmc7XG5cbiAgdmFyIGNsYXNzb2ZSYXcgPSBmdW5jdGlvbiAoaXQpIHtcbiAgICByZXR1cm4gdG9TdHJpbmcuY2FsbChpdCkuc2xpY2UoOCwgLTEpO1xuICB9O1xuXG4gIHZhciBzcGxpdCA9ICcnLnNwbGl0O1xuXG4gIC8vIGZhbGxiYWNrIGZvciBub24tYXJyYXktbGlrZSBFUzMgYW5kIG5vbi1lbnVtZXJhYmxlIG9sZCBWOCBzdHJpbmdzXG4gIHZhciBpbmRleGVkT2JqZWN0ID0gZmFpbHMoZnVuY3Rpb24gKCkge1xuICAgIC8vIHRocm93cyBhbiBlcnJvciBpbiByaGlubywgc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9tb3ppbGxhL3JoaW5vL2lzc3Vlcy8zNDZcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcHJvdG90eXBlLWJ1aWx0aW5zIC0tIHNhZmVcbiAgICByZXR1cm4gIU9iamVjdCgneicpLnByb3BlcnR5SXNFbnVtZXJhYmxlKDApO1xuICB9KSA/IGZ1bmN0aW9uIChpdCkge1xuICAgIHJldHVybiBjbGFzc29mUmF3KGl0KSA9PSAnU3RyaW5nJyA/IHNwbGl0LmNhbGwoaXQsICcnKSA6IE9iamVjdChpdCk7XG4gIH0gOiBPYmplY3Q7XG5cbiAgLy8gYFJlcXVpcmVPYmplY3RDb2VyY2libGVgIGFic3RyYWN0IG9wZXJhdGlvblxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXJlcXVpcmVvYmplY3Rjb2VyY2libGVcbiAgdmFyIHJlcXVpcmVPYmplY3RDb2VyY2libGUgPSBmdW5jdGlvbiAoaXQpIHtcbiAgICBpZiAoaXQgPT0gdW5kZWZpbmVkKSB0aHJvdyBUeXBlRXJyb3IoXCJDYW4ndCBjYWxsIG1ldGhvZCBvbiBcIiArIGl0KTtcbiAgICByZXR1cm4gaXQ7XG4gIH07XG5cbiAgLy8gdG9PYmplY3Qgd2l0aCBmYWxsYmFjayBmb3Igbm9uLWFycmF5LWxpa2UgRVMzIHN0cmluZ3NcblxuXG5cbiAgdmFyIHRvSW5kZXhlZE9iamVjdCA9IGZ1bmN0aW9uIChpdCkge1xuICAgIHJldHVybiBpbmRleGVkT2JqZWN0KHJlcXVpcmVPYmplY3RDb2VyY2libGUoaXQpKTtcbiAgfTtcblxuICB2YXIgaXNPYmplY3QgPSBmdW5jdGlvbiAoaXQpIHtcbiAgICByZXR1cm4gdHlwZW9mIGl0ID09PSAnb2JqZWN0JyA/IGl0ICE9PSBudWxsIDogdHlwZW9mIGl0ID09PSAnZnVuY3Rpb24nO1xuICB9O1xuXG4gIC8vIGBUb1ByaW1pdGl2ZWAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtdG9wcmltaXRpdmVcbiAgLy8gaW5zdGVhZCBvZiB0aGUgRVM2IHNwZWMgdmVyc2lvbiwgd2UgZGlkbid0IGltcGxlbWVudCBAQHRvUHJpbWl0aXZlIGNhc2VcbiAgLy8gYW5kIHRoZSBzZWNvbmQgYXJndW1lbnQgLSBmbGFnIC0gcHJlZmVycmVkIHR5cGUgaXMgYSBzdHJpbmdcbiAgdmFyIHRvUHJpbWl0aXZlID0gZnVuY3Rpb24gKGlucHV0LCBQUkVGRVJSRURfU1RSSU5HKSB7XG4gICAgaWYgKCFpc09iamVjdChpbnB1dCkpIHJldHVybiBpbnB1dDtcbiAgICB2YXIgZm4sIHZhbDtcbiAgICBpZiAoUFJFRkVSUkVEX1NUUklORyAmJiB0eXBlb2YgKGZuID0gaW5wdXQudG9TdHJpbmcpID09ICdmdW5jdGlvbicgJiYgIWlzT2JqZWN0KHZhbCA9IGZuLmNhbGwoaW5wdXQpKSkgcmV0dXJuIHZhbDtcbiAgICBpZiAodHlwZW9mIChmbiA9IGlucHV0LnZhbHVlT2YpID09ICdmdW5jdGlvbicgJiYgIWlzT2JqZWN0KHZhbCA9IGZuLmNhbGwoaW5wdXQpKSkgcmV0dXJuIHZhbDtcbiAgICBpZiAoIVBSRUZFUlJFRF9TVFJJTkcgJiYgdHlwZW9mIChmbiA9IGlucHV0LnRvU3RyaW5nKSA9PSAnZnVuY3Rpb24nICYmICFpc09iamVjdCh2YWwgPSBmbi5jYWxsKGlucHV0KSkpIHJldHVybiB2YWw7XG4gICAgdGhyb3cgVHlwZUVycm9yKFwiQ2FuJ3QgY29udmVydCBvYmplY3QgdG8gcHJpbWl0aXZlIHZhbHVlXCIpO1xuICB9O1xuXG4gIHZhciBoYXNPd25Qcm9wZXJ0eSA9IHt9Lmhhc093blByb3BlcnR5O1xuXG4gIHZhciBoYXMkMSA9IGZ1bmN0aW9uIChpdCwga2V5KSB7XG4gICAgcmV0dXJuIGhhc093blByb3BlcnR5LmNhbGwoaXQsIGtleSk7XG4gIH07XG5cbiAgdmFyIGRvY3VtZW50JDEgPSBnbG9iYWxfMS5kb2N1bWVudDtcbiAgLy8gdHlwZW9mIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQgaXMgJ29iamVjdCcgaW4gb2xkIElFXG4gIHZhciBFWElTVFMgPSBpc09iamVjdChkb2N1bWVudCQxKSAmJiBpc09iamVjdChkb2N1bWVudCQxLmNyZWF0ZUVsZW1lbnQpO1xuXG4gIHZhciBkb2N1bWVudENyZWF0ZUVsZW1lbnQgPSBmdW5jdGlvbiAoaXQpIHtcbiAgICByZXR1cm4gRVhJU1RTID8gZG9jdW1lbnQkMS5jcmVhdGVFbGVtZW50KGl0KSA6IHt9O1xuICB9O1xuXG4gIC8vIFRoYW5rJ3MgSUU4IGZvciBoaXMgZnVubnkgZGVmaW5lUHJvcGVydHlcbiAgdmFyIGllOERvbURlZmluZSA9ICFkZXNjcmlwdG9ycyAmJiAhZmFpbHMoZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkoZG9jdW1lbnRDcmVhdGVFbGVtZW50KCdkaXYnKSwgJ2EnLCB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIDc7IH1cbiAgICB9KS5hICE9IDc7XG4gIH0pO1xuXG4gIHZhciBuYXRpdmVHZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yO1xuXG4gIC8vIGBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yYCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1vYmplY3QuZ2V0b3ducHJvcGVydHlkZXNjcmlwdG9yXG4gIHZhciBmJDMgPSBkZXNjcmlwdG9ycyA/IG5hdGl2ZUdldE93blByb3BlcnR5RGVzY3JpcHRvciA6IGZ1bmN0aW9uIGdldE93blByb3BlcnR5RGVzY3JpcHRvcihPLCBQKSB7XG4gICAgTyA9IHRvSW5kZXhlZE9iamVjdChPKTtcbiAgICBQID0gdG9QcmltaXRpdmUoUCwgdHJ1ZSk7XG4gICAgaWYgKGllOERvbURlZmluZSkgdHJ5IHtcbiAgICAgIHJldHVybiBuYXRpdmVHZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoTywgUCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHsgLyogZW1wdHkgKi8gfVxuICAgIGlmIChoYXMkMShPLCBQKSkgcmV0dXJuIGNyZWF0ZVByb3BlcnR5RGVzY3JpcHRvcighb2JqZWN0UHJvcGVydHlJc0VudW1lcmFibGUuZi5jYWxsKE8sIFApLCBPW1BdKTtcbiAgfTtcblxuICB2YXIgb2JqZWN0R2V0T3duUHJvcGVydHlEZXNjcmlwdG9yID0ge1xuICBcdGY6IGYkM1xuICB9O1xuXG4gIHZhciBhbk9iamVjdCA9IGZ1bmN0aW9uIChpdCkge1xuICAgIGlmICghaXNPYmplY3QoaXQpKSB7XG4gICAgICB0aHJvdyBUeXBlRXJyb3IoU3RyaW5nKGl0KSArICcgaXMgbm90IGFuIG9iamVjdCcpO1xuICAgIH0gcmV0dXJuIGl0O1xuICB9O1xuXG4gIHZhciBuYXRpdmVEZWZpbmVQcm9wZXJ0eSA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eTtcblxuICAvLyBgT2JqZWN0LmRlZmluZVByb3BlcnR5YCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1vYmplY3QuZGVmaW5lcHJvcGVydHlcbiAgdmFyIGYkMiA9IGRlc2NyaXB0b3JzID8gbmF0aXZlRGVmaW5lUHJvcGVydHkgOiBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0eShPLCBQLCBBdHRyaWJ1dGVzKSB7XG4gICAgYW5PYmplY3QoTyk7XG4gICAgUCA9IHRvUHJpbWl0aXZlKFAsIHRydWUpO1xuICAgIGFuT2JqZWN0KEF0dHJpYnV0ZXMpO1xuICAgIGlmIChpZThEb21EZWZpbmUpIHRyeSB7XG4gICAgICByZXR1cm4gbmF0aXZlRGVmaW5lUHJvcGVydHkoTywgUCwgQXR0cmlidXRlcyk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHsgLyogZW1wdHkgKi8gfVxuICAgIGlmICgnZ2V0JyBpbiBBdHRyaWJ1dGVzIHx8ICdzZXQnIGluIEF0dHJpYnV0ZXMpIHRocm93IFR5cGVFcnJvcignQWNjZXNzb3JzIG5vdCBzdXBwb3J0ZWQnKTtcbiAgICBpZiAoJ3ZhbHVlJyBpbiBBdHRyaWJ1dGVzKSBPW1BdID0gQXR0cmlidXRlcy52YWx1ZTtcbiAgICByZXR1cm4gTztcbiAgfTtcblxuICB2YXIgb2JqZWN0RGVmaW5lUHJvcGVydHkgPSB7XG4gIFx0ZjogZiQyXG4gIH07XG5cbiAgdmFyIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eSA9IGRlc2NyaXB0b3JzID8gZnVuY3Rpb24gKG9iamVjdCwga2V5LCB2YWx1ZSkge1xuICAgIHJldHVybiBvYmplY3REZWZpbmVQcm9wZXJ0eS5mKG9iamVjdCwga2V5LCBjcmVhdGVQcm9wZXJ0eURlc2NyaXB0b3IoMSwgdmFsdWUpKTtcbiAgfSA6IGZ1bmN0aW9uIChvYmplY3QsIGtleSwgdmFsdWUpIHtcbiAgICBvYmplY3Rba2V5XSA9IHZhbHVlO1xuICAgIHJldHVybiBvYmplY3Q7XG4gIH07XG5cbiAgdmFyIHNldEdsb2JhbCA9IGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eShnbG9iYWxfMSwga2V5LCB2YWx1ZSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGdsb2JhbF8xW2tleV0gPSB2YWx1ZTtcbiAgICB9IHJldHVybiB2YWx1ZTtcbiAgfTtcblxuICB2YXIgU0hBUkVEID0gJ19fY29yZS1qc19zaGFyZWRfXyc7XG4gIHZhciBzdG9yZSQxID0gZ2xvYmFsXzFbU0hBUkVEXSB8fCBzZXRHbG9iYWwoU0hBUkVELCB7fSk7XG5cbiAgdmFyIHNoYXJlZFN0b3JlID0gc3RvcmUkMTtcblxuICB2YXIgZnVuY3Rpb25Ub1N0cmluZyA9IEZ1bmN0aW9uLnRvU3RyaW5nO1xuXG4gIC8vIHRoaXMgaGVscGVyIGJyb2tlbiBpbiBgMy40LjEtMy40LjRgLCBzbyB3ZSBjYW4ndCB1c2UgYHNoYXJlZGAgaGVscGVyXG4gIGlmICh0eXBlb2Ygc2hhcmVkU3RvcmUuaW5zcGVjdFNvdXJjZSAhPSAnZnVuY3Rpb24nKSB7XG4gICAgc2hhcmVkU3RvcmUuaW5zcGVjdFNvdXJjZSA9IGZ1bmN0aW9uIChpdCkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uVG9TdHJpbmcuY2FsbChpdCk7XG4gICAgfTtcbiAgfVxuXG4gIHZhciBpbnNwZWN0U291cmNlID0gc2hhcmVkU3RvcmUuaW5zcGVjdFNvdXJjZTtcblxuICB2YXIgV2Vha01hcCQxID0gZ2xvYmFsXzEuV2Vha01hcDtcblxuICB2YXIgbmF0aXZlV2Vha01hcCA9IHR5cGVvZiBXZWFrTWFwJDEgPT09ICdmdW5jdGlvbicgJiYgL25hdGl2ZSBjb2RlLy50ZXN0KGluc3BlY3RTb3VyY2UoV2Vha01hcCQxKSk7XG5cbiAgdmFyIHNoYXJlZCA9IGNyZWF0ZUNvbW1vbmpzTW9kdWxlKGZ1bmN0aW9uIChtb2R1bGUpIHtcbiAgKG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICByZXR1cm4gc2hhcmVkU3RvcmVba2V5XSB8fCAoc2hhcmVkU3RvcmVba2V5XSA9IHZhbHVlICE9PSB1bmRlZmluZWQgPyB2YWx1ZSA6IHt9KTtcbiAgfSkoJ3ZlcnNpb25zJywgW10pLnB1c2goe1xuICAgIHZlcnNpb246ICczLjkuMScsXG4gICAgbW9kZTogJ2dsb2JhbCcsXG4gICAgY29weXJpZ2h0OiAnwqkgMjAyMSBEZW5pcyBQdXNoa2FyZXYgKHpsb2lyb2NrLnJ1KSdcbiAgfSk7XG4gIH0pO1xuXG4gIHZhciBpZCA9IDA7XG4gIHZhciBwb3N0Zml4ID0gTWF0aC5yYW5kb20oKTtcblxuICB2YXIgdWlkID0gZnVuY3Rpb24gKGtleSkge1xuICAgIHJldHVybiAnU3ltYm9sKCcgKyBTdHJpbmcoa2V5ID09PSB1bmRlZmluZWQgPyAnJyA6IGtleSkgKyAnKV8nICsgKCsraWQgKyBwb3N0Zml4KS50b1N0cmluZygzNik7XG4gIH07XG5cbiAgdmFyIGtleXMkMiA9IHNoYXJlZCgna2V5cycpO1xuXG4gIHZhciBzaGFyZWRLZXkgPSBmdW5jdGlvbiAoa2V5KSB7XG4gICAgcmV0dXJuIGtleXMkMltrZXldIHx8IChrZXlzJDJba2V5XSA9IHVpZChrZXkpKTtcbiAgfTtcblxuICB2YXIgaGlkZGVuS2V5cyQxID0ge307XG5cbiAgdmFyIFdlYWtNYXAgPSBnbG9iYWxfMS5XZWFrTWFwO1xuICB2YXIgc2V0LCBnZXQsIGhhcztcblxuICB2YXIgZW5mb3JjZSA9IGZ1bmN0aW9uIChpdCkge1xuICAgIHJldHVybiBoYXMoaXQpID8gZ2V0KGl0KSA6IHNldChpdCwge30pO1xuICB9O1xuXG4gIHZhciBnZXR0ZXJGb3IgPSBmdW5jdGlvbiAoVFlQRSkge1xuICAgIHJldHVybiBmdW5jdGlvbiAoaXQpIHtcbiAgICAgIHZhciBzdGF0ZTtcbiAgICAgIGlmICghaXNPYmplY3QoaXQpIHx8IChzdGF0ZSA9IGdldChpdCkpLnR5cGUgIT09IFRZUEUpIHtcbiAgICAgICAgdGhyb3cgVHlwZUVycm9yKCdJbmNvbXBhdGlibGUgcmVjZWl2ZXIsICcgKyBUWVBFICsgJyByZXF1aXJlZCcpO1xuICAgICAgfSByZXR1cm4gc3RhdGU7XG4gICAgfTtcbiAgfTtcblxuICBpZiAobmF0aXZlV2Vha01hcCkge1xuICAgIHZhciBzdG9yZSA9IHNoYXJlZFN0b3JlLnN0YXRlIHx8IChzaGFyZWRTdG9yZS5zdGF0ZSA9IG5ldyBXZWFrTWFwKCkpO1xuICAgIHZhciB3bWdldCA9IHN0b3JlLmdldDtcbiAgICB2YXIgd21oYXMgPSBzdG9yZS5oYXM7XG4gICAgdmFyIHdtc2V0ID0gc3RvcmUuc2V0O1xuICAgIHNldCA9IGZ1bmN0aW9uIChpdCwgbWV0YWRhdGEpIHtcbiAgICAgIG1ldGFkYXRhLmZhY2FkZSA9IGl0O1xuICAgICAgd21zZXQuY2FsbChzdG9yZSwgaXQsIG1ldGFkYXRhKTtcbiAgICAgIHJldHVybiBtZXRhZGF0YTtcbiAgICB9O1xuICAgIGdldCA9IGZ1bmN0aW9uIChpdCkge1xuICAgICAgcmV0dXJuIHdtZ2V0LmNhbGwoc3RvcmUsIGl0KSB8fCB7fTtcbiAgICB9O1xuICAgIGhhcyA9IGZ1bmN0aW9uIChpdCkge1xuICAgICAgcmV0dXJuIHdtaGFzLmNhbGwoc3RvcmUsIGl0KTtcbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIHZhciBTVEFURSA9IHNoYXJlZEtleSgnc3RhdGUnKTtcbiAgICBoaWRkZW5LZXlzJDFbU1RBVEVdID0gdHJ1ZTtcbiAgICBzZXQgPSBmdW5jdGlvbiAoaXQsIG1ldGFkYXRhKSB7XG4gICAgICBtZXRhZGF0YS5mYWNhZGUgPSBpdDtcbiAgICAgIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eShpdCwgU1RBVEUsIG1ldGFkYXRhKTtcbiAgICAgIHJldHVybiBtZXRhZGF0YTtcbiAgICB9O1xuICAgIGdldCA9IGZ1bmN0aW9uIChpdCkge1xuICAgICAgcmV0dXJuIGhhcyQxKGl0LCBTVEFURSkgPyBpdFtTVEFURV0gOiB7fTtcbiAgICB9O1xuICAgIGhhcyA9IGZ1bmN0aW9uIChpdCkge1xuICAgICAgcmV0dXJuIGhhcyQxKGl0LCBTVEFURSk7XG4gICAgfTtcbiAgfVxuXG4gIHZhciBpbnRlcm5hbFN0YXRlID0ge1xuICAgIHNldDogc2V0LFxuICAgIGdldDogZ2V0LFxuICAgIGhhczogaGFzLFxuICAgIGVuZm9yY2U6IGVuZm9yY2UsXG4gICAgZ2V0dGVyRm9yOiBnZXR0ZXJGb3JcbiAgfTtcblxuICB2YXIgcmVkZWZpbmUgPSBjcmVhdGVDb21tb25qc01vZHVsZShmdW5jdGlvbiAobW9kdWxlKSB7XG4gIHZhciBnZXRJbnRlcm5hbFN0YXRlID0gaW50ZXJuYWxTdGF0ZS5nZXQ7XG4gIHZhciBlbmZvcmNlSW50ZXJuYWxTdGF0ZSA9IGludGVybmFsU3RhdGUuZW5mb3JjZTtcbiAgdmFyIFRFTVBMQVRFID0gU3RyaW5nKFN0cmluZykuc3BsaXQoJ1N0cmluZycpO1xuXG4gIChtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChPLCBrZXksIHZhbHVlLCBvcHRpb25zKSB7XG4gICAgdmFyIHVuc2FmZSA9IG9wdGlvbnMgPyAhIW9wdGlvbnMudW5zYWZlIDogZmFsc2U7XG4gICAgdmFyIHNpbXBsZSA9IG9wdGlvbnMgPyAhIW9wdGlvbnMuZW51bWVyYWJsZSA6IGZhbHNlO1xuICAgIHZhciBub1RhcmdldEdldCA9IG9wdGlvbnMgPyAhIW9wdGlvbnMubm9UYXJnZXRHZXQgOiBmYWxzZTtcbiAgICB2YXIgc3RhdGU7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICBpZiAodHlwZW9mIGtleSA9PSAnc3RyaW5nJyAmJiAhaGFzJDEodmFsdWUsICduYW1lJykpIHtcbiAgICAgICAgY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5KHZhbHVlLCAnbmFtZScsIGtleSk7XG4gICAgICB9XG4gICAgICBzdGF0ZSA9IGVuZm9yY2VJbnRlcm5hbFN0YXRlKHZhbHVlKTtcbiAgICAgIGlmICghc3RhdGUuc291cmNlKSB7XG4gICAgICAgIHN0YXRlLnNvdXJjZSA9IFRFTVBMQVRFLmpvaW4odHlwZW9mIGtleSA9PSAnc3RyaW5nJyA/IGtleSA6ICcnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKE8gPT09IGdsb2JhbF8xKSB7XG4gICAgICBpZiAoc2ltcGxlKSBPW2tleV0gPSB2YWx1ZTtcbiAgICAgIGVsc2Ugc2V0R2xvYmFsKGtleSwgdmFsdWUpO1xuICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSBpZiAoIXVuc2FmZSkge1xuICAgICAgZGVsZXRlIE9ba2V5XTtcbiAgICB9IGVsc2UgaWYgKCFub1RhcmdldEdldCAmJiBPW2tleV0pIHtcbiAgICAgIHNpbXBsZSA9IHRydWU7XG4gICAgfVxuICAgIGlmIChzaW1wbGUpIE9ba2V5XSA9IHZhbHVlO1xuICAgIGVsc2UgY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5KE8sIGtleSwgdmFsdWUpO1xuICAvLyBhZGQgZmFrZSBGdW5jdGlvbiN0b1N0cmluZyBmb3IgY29ycmVjdCB3b3JrIHdyYXBwZWQgbWV0aG9kcyAvIGNvbnN0cnVjdG9ycyB3aXRoIG1ldGhvZHMgbGlrZSBMb0Rhc2ggaXNOYXRpdmVcbiAgfSkoRnVuY3Rpb24ucHJvdG90eXBlLCAndG9TdHJpbmcnLCBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gdHlwZW9mIHRoaXMgPT0gJ2Z1bmN0aW9uJyAmJiBnZXRJbnRlcm5hbFN0YXRlKHRoaXMpLnNvdXJjZSB8fCBpbnNwZWN0U291cmNlKHRoaXMpO1xuICB9KTtcbiAgfSk7XG5cbiAgdmFyIHBhdGggPSBnbG9iYWxfMTtcblxuICB2YXIgYUZ1bmN0aW9uJDEgPSBmdW5jdGlvbiAodmFyaWFibGUpIHtcbiAgICByZXR1cm4gdHlwZW9mIHZhcmlhYmxlID09ICdmdW5jdGlvbicgPyB2YXJpYWJsZSA6IHVuZGVmaW5lZDtcbiAgfTtcblxuICB2YXIgZ2V0QnVpbHRJbiA9IGZ1bmN0aW9uIChuYW1lc3BhY2UsIG1ldGhvZCkge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoIDwgMiA/IGFGdW5jdGlvbiQxKHBhdGhbbmFtZXNwYWNlXSkgfHwgYUZ1bmN0aW9uJDEoZ2xvYmFsXzFbbmFtZXNwYWNlXSlcbiAgICAgIDogcGF0aFtuYW1lc3BhY2VdICYmIHBhdGhbbmFtZXNwYWNlXVttZXRob2RdIHx8IGdsb2JhbF8xW25hbWVzcGFjZV0gJiYgZ2xvYmFsXzFbbmFtZXNwYWNlXVttZXRob2RdO1xuICB9O1xuXG4gIHZhciBjZWlsID0gTWF0aC5jZWlsO1xuICB2YXIgZmxvb3IkMSA9IE1hdGguZmxvb3I7XG5cbiAgLy8gYFRvSW50ZWdlcmAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtdG9pbnRlZ2VyXG4gIHZhciB0b0ludGVnZXIgPSBmdW5jdGlvbiAoYXJndW1lbnQpIHtcbiAgICByZXR1cm4gaXNOYU4oYXJndW1lbnQgPSArYXJndW1lbnQpID8gMCA6IChhcmd1bWVudCA+IDAgPyBmbG9vciQxIDogY2VpbCkoYXJndW1lbnQpO1xuICB9O1xuXG4gIHZhciBtaW4kNiA9IE1hdGgubWluO1xuXG4gIC8vIGBUb0xlbmd0aGAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtdG9sZW5ndGhcbiAgdmFyIHRvTGVuZ3RoID0gZnVuY3Rpb24gKGFyZ3VtZW50KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50ID4gMCA/IG1pbiQ2KHRvSW50ZWdlcihhcmd1bWVudCksIDB4MUZGRkZGRkZGRkZGRkYpIDogMDsgLy8gMiAqKiA1MyAtIDEgPT0gOTAwNzE5OTI1NDc0MDk5MVxuICB9O1xuXG4gIHZhciBtYXgkMyA9IE1hdGgubWF4O1xuICB2YXIgbWluJDUgPSBNYXRoLm1pbjtcblxuICAvLyBIZWxwZXIgZm9yIGEgcG9wdWxhciByZXBlYXRpbmcgY2FzZSBvZiB0aGUgc3BlYzpcbiAgLy8gTGV0IGludGVnZXIgYmUgPyBUb0ludGVnZXIoaW5kZXgpLlxuICAvLyBJZiBpbnRlZ2VyIDwgMCwgbGV0IHJlc3VsdCBiZSBtYXgoKGxlbmd0aCArIGludGVnZXIpLCAwKTsgZWxzZSBsZXQgcmVzdWx0IGJlIG1pbihpbnRlZ2VyLCBsZW5ndGgpLlxuICB2YXIgdG9BYnNvbHV0ZUluZGV4ID0gZnVuY3Rpb24gKGluZGV4LCBsZW5ndGgpIHtcbiAgICB2YXIgaW50ZWdlciA9IHRvSW50ZWdlcihpbmRleCk7XG4gICAgcmV0dXJuIGludGVnZXIgPCAwID8gbWF4JDMoaW50ZWdlciArIGxlbmd0aCwgMCkgOiBtaW4kNShpbnRlZ2VyLCBsZW5ndGgpO1xuICB9O1xuXG4gIC8vIGBBcnJheS5wcm90b3R5cGUueyBpbmRleE9mLCBpbmNsdWRlcyB9YCBtZXRob2RzIGltcGxlbWVudGF0aW9uXG4gIHZhciBjcmVhdGVNZXRob2QkNCA9IGZ1bmN0aW9uIChJU19JTkNMVURFUykge1xuICAgIHJldHVybiBmdW5jdGlvbiAoJHRoaXMsIGVsLCBmcm9tSW5kZXgpIHtcbiAgICAgIHZhciBPID0gdG9JbmRleGVkT2JqZWN0KCR0aGlzKTtcbiAgICAgIHZhciBsZW5ndGggPSB0b0xlbmd0aChPLmxlbmd0aCk7XG4gICAgICB2YXIgaW5kZXggPSB0b0Fic29sdXRlSW5kZXgoZnJvbUluZGV4LCBsZW5ndGgpO1xuICAgICAgdmFyIHZhbHVlO1xuICAgICAgLy8gQXJyYXkjaW5jbHVkZXMgdXNlcyBTYW1lVmFsdWVaZXJvIGVxdWFsaXR5IGFsZ29yaXRobVxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXNlbGYtY29tcGFyZSAtLSBOYU4gY2hlY2tcbiAgICAgIGlmIChJU19JTkNMVURFUyAmJiBlbCAhPSBlbCkgd2hpbGUgKGxlbmd0aCA+IGluZGV4KSB7XG4gICAgICAgIHZhbHVlID0gT1tpbmRleCsrXTtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXNlbGYtY29tcGFyZSAtLSBOYU4gY2hlY2tcbiAgICAgICAgaWYgKHZhbHVlICE9IHZhbHVlKSByZXR1cm4gdHJ1ZTtcbiAgICAgIC8vIEFycmF5I2luZGV4T2YgaWdub3JlcyBob2xlcywgQXJyYXkjaW5jbHVkZXMgLSBub3RcbiAgICAgIH0gZWxzZSBmb3IgKDtsZW5ndGggPiBpbmRleDsgaW5kZXgrKykge1xuICAgICAgICBpZiAoKElTX0lOQ0xVREVTIHx8IGluZGV4IGluIE8pICYmIE9baW5kZXhdID09PSBlbCkgcmV0dXJuIElTX0lOQ0xVREVTIHx8IGluZGV4IHx8IDA7XG4gICAgICB9IHJldHVybiAhSVNfSU5DTFVERVMgJiYgLTE7XG4gICAgfTtcbiAgfTtcblxuICB2YXIgYXJyYXlJbmNsdWRlcyA9IHtcbiAgICAvLyBgQXJyYXkucHJvdG90eXBlLmluY2x1ZGVzYCBtZXRob2RcbiAgICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS5pbmNsdWRlc1xuICAgIGluY2x1ZGVzOiBjcmVhdGVNZXRob2QkNCh0cnVlKSxcbiAgICAvLyBgQXJyYXkucHJvdG90eXBlLmluZGV4T2ZgIG1ldGhvZFxuICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLmluZGV4b2ZcbiAgICBpbmRleE9mOiBjcmVhdGVNZXRob2QkNChmYWxzZSlcbiAgfTtcblxuICB2YXIgaW5kZXhPZiA9IGFycmF5SW5jbHVkZXMuaW5kZXhPZjtcblxuXG4gIHZhciBvYmplY3RLZXlzSW50ZXJuYWwgPSBmdW5jdGlvbiAob2JqZWN0LCBuYW1lcykge1xuICAgIHZhciBPID0gdG9JbmRleGVkT2JqZWN0KG9iamVjdCk7XG4gICAgdmFyIGkgPSAwO1xuICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICB2YXIga2V5O1xuICAgIGZvciAoa2V5IGluIE8pICFoYXMkMShoaWRkZW5LZXlzJDEsIGtleSkgJiYgaGFzJDEoTywga2V5KSAmJiByZXN1bHQucHVzaChrZXkpO1xuICAgIC8vIERvbid0IGVudW0gYnVnICYgaGlkZGVuIGtleXNcbiAgICB3aGlsZSAobmFtZXMubGVuZ3RoID4gaSkgaWYgKGhhcyQxKE8sIGtleSA9IG5hbWVzW2krK10pKSB7XG4gICAgICB+aW5kZXhPZihyZXN1bHQsIGtleSkgfHwgcmVzdWx0LnB1c2goa2V5KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICAvLyBJRTgtIGRvbid0IGVudW0gYnVnIGtleXNcbiAgdmFyIGVudW1CdWdLZXlzID0gW1xuICAgICdjb25zdHJ1Y3RvcicsXG4gICAgJ2hhc093blByb3BlcnR5JyxcbiAgICAnaXNQcm90b3R5cGVPZicsXG4gICAgJ3Byb3BlcnR5SXNFbnVtZXJhYmxlJyxcbiAgICAndG9Mb2NhbGVTdHJpbmcnLFxuICAgICd0b1N0cmluZycsXG4gICAgJ3ZhbHVlT2YnXG4gIF07XG5cbiAgdmFyIGhpZGRlbktleXMgPSBlbnVtQnVnS2V5cy5jb25jYXQoJ2xlbmd0aCcsICdwcm90b3R5cGUnKTtcblxuICAvLyBgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXNgIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9iamVjdC5nZXRvd25wcm9wZXJ0eW5hbWVzXG4gIHZhciBmJDEgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyB8fCBmdW5jdGlvbiBnZXRPd25Qcm9wZXJ0eU5hbWVzKE8pIHtcbiAgICByZXR1cm4gb2JqZWN0S2V5c0ludGVybmFsKE8sIGhpZGRlbktleXMpO1xuICB9O1xuXG4gIHZhciBvYmplY3RHZXRPd25Qcm9wZXJ0eU5hbWVzID0ge1xuICBcdGY6IGYkMVxuICB9O1xuXG4gIHZhciBmID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scztcblxuICB2YXIgb2JqZWN0R2V0T3duUHJvcGVydHlTeW1ib2xzID0ge1xuICBcdGY6IGZcbiAgfTtcblxuICAvLyBhbGwgb2JqZWN0IGtleXMsIGluY2x1ZGVzIG5vbi1lbnVtZXJhYmxlIGFuZCBzeW1ib2xzXG4gIHZhciBvd25LZXlzID0gZ2V0QnVpbHRJbignUmVmbGVjdCcsICdvd25LZXlzJykgfHwgZnVuY3Rpb24gb3duS2V5cyhpdCkge1xuICAgIHZhciBrZXlzID0gb2JqZWN0R2V0T3duUHJvcGVydHlOYW1lcy5mKGFuT2JqZWN0KGl0KSk7XG4gICAgdmFyIGdldE93blByb3BlcnR5U3ltYm9scyA9IG9iamVjdEdldE93blByb3BlcnR5U3ltYm9scy5mO1xuICAgIHJldHVybiBnZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPyBrZXlzLmNvbmNhdChnZXRPd25Qcm9wZXJ0eVN5bWJvbHMoaXQpKSA6IGtleXM7XG4gIH07XG5cbiAgdmFyIGNvcHlDb25zdHJ1Y3RvclByb3BlcnRpZXMgPSBmdW5jdGlvbiAodGFyZ2V0LCBzb3VyY2UpIHtcbiAgICB2YXIga2V5cyA9IG93bktleXMoc291cmNlKTtcbiAgICB2YXIgZGVmaW5lUHJvcGVydHkgPSBvYmplY3REZWZpbmVQcm9wZXJ0eS5mO1xuICAgIHZhciBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgPSBvYmplY3RHZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IuZjtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBrZXkgPSBrZXlzW2ldO1xuICAgICAgaWYgKCFoYXMkMSh0YXJnZXQsIGtleSkpIGRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Ioc291cmNlLCBrZXkpKTtcbiAgICB9XG4gIH07XG5cbiAgdmFyIHJlcGxhY2VtZW50ID0gLyN8XFwucHJvdG90eXBlXFwuLztcblxuICB2YXIgaXNGb3JjZWQgPSBmdW5jdGlvbiAoZmVhdHVyZSwgZGV0ZWN0aW9uKSB7XG4gICAgdmFyIHZhbHVlID0gZGF0YVtub3JtYWxpemUoZmVhdHVyZSldO1xuICAgIHJldHVybiB2YWx1ZSA9PSBQT0xZRklMTCA/IHRydWVcbiAgICAgIDogdmFsdWUgPT0gTkFUSVZFID8gZmFsc2VcbiAgICAgIDogdHlwZW9mIGRldGVjdGlvbiA9PSAnZnVuY3Rpb24nID8gZmFpbHMoZGV0ZWN0aW9uKVxuICAgICAgOiAhIWRldGVjdGlvbjtcbiAgfTtcblxuICB2YXIgbm9ybWFsaXplID0gaXNGb3JjZWQubm9ybWFsaXplID0gZnVuY3Rpb24gKHN0cmluZykge1xuICAgIHJldHVybiBTdHJpbmcoc3RyaW5nKS5yZXBsYWNlKHJlcGxhY2VtZW50LCAnLicpLnRvTG93ZXJDYXNlKCk7XG4gIH07XG5cbiAgdmFyIGRhdGEgPSBpc0ZvcmNlZC5kYXRhID0ge307XG4gIHZhciBOQVRJVkUgPSBpc0ZvcmNlZC5OQVRJVkUgPSAnTic7XG4gIHZhciBQT0xZRklMTCA9IGlzRm9yY2VkLlBPTFlGSUxMID0gJ1AnO1xuXG4gIHZhciBpc0ZvcmNlZF8xID0gaXNGb3JjZWQ7XG5cbiAgdmFyIGdldE93blByb3BlcnR5RGVzY3JpcHRvciQzID0gb2JqZWN0R2V0T3duUHJvcGVydHlEZXNjcmlwdG9yLmY7XG5cblxuXG5cblxuXG4gIC8qXG4gICAgb3B0aW9ucy50YXJnZXQgICAgICAtIG5hbWUgb2YgdGhlIHRhcmdldCBvYmplY3RcbiAgICBvcHRpb25zLmdsb2JhbCAgICAgIC0gdGFyZ2V0IGlzIHRoZSBnbG9iYWwgb2JqZWN0XG4gICAgb3B0aW9ucy5zdGF0ICAgICAgICAtIGV4cG9ydCBhcyBzdGF0aWMgbWV0aG9kcyBvZiB0YXJnZXRcbiAgICBvcHRpb25zLnByb3RvICAgICAgIC0gZXhwb3J0IGFzIHByb3RvdHlwZSBtZXRob2RzIG9mIHRhcmdldFxuICAgIG9wdGlvbnMucmVhbCAgICAgICAgLSByZWFsIHByb3RvdHlwZSBtZXRob2QgZm9yIHRoZSBgcHVyZWAgdmVyc2lvblxuICAgIG9wdGlvbnMuZm9yY2VkICAgICAgLSBleHBvcnQgZXZlbiBpZiB0aGUgbmF0aXZlIGZlYXR1cmUgaXMgYXZhaWxhYmxlXG4gICAgb3B0aW9ucy5iaW5kICAgICAgICAtIGJpbmQgbWV0aG9kcyB0byB0aGUgdGFyZ2V0LCByZXF1aXJlZCBmb3IgdGhlIGBwdXJlYCB2ZXJzaW9uXG4gICAgb3B0aW9ucy53cmFwICAgICAgICAtIHdyYXAgY29uc3RydWN0b3JzIHRvIHByZXZlbnRpbmcgZ2xvYmFsIHBvbGx1dGlvbiwgcmVxdWlyZWQgZm9yIHRoZSBgcHVyZWAgdmVyc2lvblxuICAgIG9wdGlvbnMudW5zYWZlICAgICAgLSB1c2UgdGhlIHNpbXBsZSBhc3NpZ25tZW50IG9mIHByb3BlcnR5IGluc3RlYWQgb2YgZGVsZXRlICsgZGVmaW5lUHJvcGVydHlcbiAgICBvcHRpb25zLnNoYW0gICAgICAgIC0gYWRkIGEgZmxhZyB0byBub3QgY29tcGxldGVseSBmdWxsIHBvbHlmaWxsc1xuICAgIG9wdGlvbnMuZW51bWVyYWJsZSAgLSBleHBvcnQgYXMgZW51bWVyYWJsZSBwcm9wZXJ0eVxuICAgIG9wdGlvbnMubm9UYXJnZXRHZXQgLSBwcmV2ZW50IGNhbGxpbmcgYSBnZXR0ZXIgb24gdGFyZ2V0XG4gICovXG4gIHZhciBfZXhwb3J0ID0gZnVuY3Rpb24gKG9wdGlvbnMsIHNvdXJjZSkge1xuICAgIHZhciBUQVJHRVQgPSBvcHRpb25zLnRhcmdldDtcbiAgICB2YXIgR0xPQkFMID0gb3B0aW9ucy5nbG9iYWw7XG4gICAgdmFyIFNUQVRJQyA9IG9wdGlvbnMuc3RhdDtcbiAgICB2YXIgRk9SQ0VELCB0YXJnZXQsIGtleSwgdGFyZ2V0UHJvcGVydHksIHNvdXJjZVByb3BlcnR5LCBkZXNjcmlwdG9yO1xuICAgIGlmIChHTE9CQUwpIHtcbiAgICAgIHRhcmdldCA9IGdsb2JhbF8xO1xuICAgIH0gZWxzZSBpZiAoU1RBVElDKSB7XG4gICAgICB0YXJnZXQgPSBnbG9iYWxfMVtUQVJHRVRdIHx8IHNldEdsb2JhbChUQVJHRVQsIHt9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGFyZ2V0ID0gKGdsb2JhbF8xW1RBUkdFVF0gfHwge30pLnByb3RvdHlwZTtcbiAgICB9XG4gICAgaWYgKHRhcmdldCkgZm9yIChrZXkgaW4gc291cmNlKSB7XG4gICAgICBzb3VyY2VQcm9wZXJ0eSA9IHNvdXJjZVtrZXldO1xuICAgICAgaWYgKG9wdGlvbnMubm9UYXJnZXRHZXQpIHtcbiAgICAgICAgZGVzY3JpcHRvciA9IGdldE93blByb3BlcnR5RGVzY3JpcHRvciQzKHRhcmdldCwga2V5KTtcbiAgICAgICAgdGFyZ2V0UHJvcGVydHkgPSBkZXNjcmlwdG9yICYmIGRlc2NyaXB0b3IudmFsdWU7XG4gICAgICB9IGVsc2UgdGFyZ2V0UHJvcGVydHkgPSB0YXJnZXRba2V5XTtcbiAgICAgIEZPUkNFRCA9IGlzRm9yY2VkXzEoR0xPQkFMID8ga2V5IDogVEFSR0VUICsgKFNUQVRJQyA/ICcuJyA6ICcjJykgKyBrZXksIG9wdGlvbnMuZm9yY2VkKTtcbiAgICAgIC8vIGNvbnRhaW5lZCBpbiB0YXJnZXRcbiAgICAgIGlmICghRk9SQ0VEICYmIHRhcmdldFByb3BlcnR5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBzb3VyY2VQcm9wZXJ0eSA9PT0gdHlwZW9mIHRhcmdldFByb3BlcnR5KSBjb250aW51ZTtcbiAgICAgICAgY29weUNvbnN0cnVjdG9yUHJvcGVydGllcyhzb3VyY2VQcm9wZXJ0eSwgdGFyZ2V0UHJvcGVydHkpO1xuICAgICAgfVxuICAgICAgLy8gYWRkIGEgZmxhZyB0byBub3QgY29tcGxldGVseSBmdWxsIHBvbHlmaWxsc1xuICAgICAgaWYgKG9wdGlvbnMuc2hhbSB8fCAodGFyZ2V0UHJvcGVydHkgJiYgdGFyZ2V0UHJvcGVydHkuc2hhbSkpIHtcbiAgICAgICAgY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5KHNvdXJjZVByb3BlcnR5LCAnc2hhbScsIHRydWUpO1xuICAgICAgfVxuICAgICAgLy8gZXh0ZW5kIGdsb2JhbFxuICAgICAgcmVkZWZpbmUodGFyZ2V0LCBrZXksIHNvdXJjZVByb3BlcnR5LCBvcHRpb25zKTtcbiAgICB9XG4gIH07XG5cbiAgLy8gYSBzdHJpbmcgb2YgYWxsIHZhbGlkIHVuaWNvZGUgd2hpdGVzcGFjZXNcbiAgdmFyIHdoaXRlc3BhY2VzID0gJ1xcdTAwMDlcXHUwMDBBXFx1MDAwQlxcdTAwMENcXHUwMDBEXFx1MDAyMFxcdTAwQTBcXHUxNjgwXFx1MjAwMFxcdTIwMDFcXHUyMDAyJyArXG4gICAgJ1xcdTIwMDNcXHUyMDA0XFx1MjAwNVxcdTIwMDZcXHUyMDA3XFx1MjAwOFxcdTIwMDlcXHUyMDBBXFx1MjAyRlxcdTIwNUZcXHUzMDAwXFx1MjAyOFxcdTIwMjlcXHVGRUZGJztcblxuICB2YXIgd2hpdGVzcGFjZSA9ICdbJyArIHdoaXRlc3BhY2VzICsgJ10nO1xuICB2YXIgbHRyaW0gPSBSZWdFeHAoJ14nICsgd2hpdGVzcGFjZSArIHdoaXRlc3BhY2UgKyAnKicpO1xuICB2YXIgcnRyaW0gPSBSZWdFeHAod2hpdGVzcGFjZSArIHdoaXRlc3BhY2UgKyAnKiQnKTtcblxuICAvLyBgU3RyaW5nLnByb3RvdHlwZS57IHRyaW0sIHRyaW1TdGFydCwgdHJpbUVuZCwgdHJpbUxlZnQsIHRyaW1SaWdodCB9YCBtZXRob2RzIGltcGxlbWVudGF0aW9uXG4gIHZhciBjcmVhdGVNZXRob2QkMyA9IGZ1bmN0aW9uIChUWVBFKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgkdGhpcykge1xuICAgICAgdmFyIHN0cmluZyA9IFN0cmluZyhyZXF1aXJlT2JqZWN0Q29lcmNpYmxlKCR0aGlzKSk7XG4gICAgICBpZiAoVFlQRSAmIDEpIHN0cmluZyA9IHN0cmluZy5yZXBsYWNlKGx0cmltLCAnJyk7XG4gICAgICBpZiAoVFlQRSAmIDIpIHN0cmluZyA9IHN0cmluZy5yZXBsYWNlKHJ0cmltLCAnJyk7XG4gICAgICByZXR1cm4gc3RyaW5nO1xuICAgIH07XG4gIH07XG5cbiAgdmFyIHN0cmluZ1RyaW0gPSB7XG4gICAgLy8gYFN0cmluZy5wcm90b3R5cGUueyB0cmltTGVmdCwgdHJpbVN0YXJ0IH1gIG1ldGhvZHNcbiAgICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXN0cmluZy5wcm90b3R5cGUudHJpbXN0YXJ0XG4gICAgc3RhcnQ6IGNyZWF0ZU1ldGhvZCQzKDEpLFxuICAgIC8vIGBTdHJpbmcucHJvdG90eXBlLnsgdHJpbVJpZ2h0LCB0cmltRW5kIH1gIG1ldGhvZHNcbiAgICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXN0cmluZy5wcm90b3R5cGUudHJpbWVuZFxuICAgIGVuZDogY3JlYXRlTWV0aG9kJDMoMiksXG4gICAgLy8gYFN0cmluZy5wcm90b3R5cGUudHJpbWAgbWV0aG9kXG4gICAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1zdHJpbmcucHJvdG90eXBlLnRyaW1cbiAgICB0cmltOiBjcmVhdGVNZXRob2QkMygzKVxuICB9O1xuXG4gIHZhciBub24gPSAnXFx1MjAwQlxcdTAwODVcXHUxODBFJztcblxuICAvLyBjaGVjayB0aGF0IGEgbWV0aG9kIHdvcmtzIHdpdGggdGhlIGNvcnJlY3QgbGlzdFxuICAvLyBvZiB3aGl0ZXNwYWNlcyBhbmQgaGFzIGEgY29ycmVjdCBuYW1lXG4gIHZhciBzdHJpbmdUcmltRm9yY2VkID0gZnVuY3Rpb24gKE1FVEhPRF9OQU1FKSB7XG4gICAgcmV0dXJuIGZhaWxzKGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAhIXdoaXRlc3BhY2VzW01FVEhPRF9OQU1FXSgpIHx8IG5vbltNRVRIT0RfTkFNRV0oKSAhPSBub24gfHwgd2hpdGVzcGFjZXNbTUVUSE9EX05BTUVdLm5hbWUgIT09IE1FVEhPRF9OQU1FO1xuICAgIH0pO1xuICB9O1xuXG4gIHZhciAkdHJpbSA9IHN0cmluZ1RyaW0udHJpbTtcblxuXG4gIC8vIGBTdHJpbmcucHJvdG90eXBlLnRyaW1gIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXN0cmluZy5wcm90b3R5cGUudHJpbVxuICBfZXhwb3J0KHsgdGFyZ2V0OiAnU3RyaW5nJywgcHJvdG86IHRydWUsIGZvcmNlZDogc3RyaW5nVHJpbUZvcmNlZCgndHJpbScpIH0sIHtcbiAgICB0cmltOiBmdW5jdGlvbiB0cmltKCkge1xuICAgICAgcmV0dXJuICR0cmltKHRoaXMpO1xuICAgIH1cbiAgfSk7XG5cbiAgdmFyIGFycmF5TWV0aG9kSXNTdHJpY3QgPSBmdW5jdGlvbiAoTUVUSE9EX05BTUUsIGFyZ3VtZW50KSB7XG4gICAgdmFyIG1ldGhvZCA9IFtdW01FVEhPRF9OQU1FXTtcbiAgICByZXR1cm4gISFtZXRob2QgJiYgZmFpbHMoZnVuY3Rpb24gKCkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVzZWxlc3MtY2FsbCxuby10aHJvdy1saXRlcmFsIC0tIHJlcXVpcmVkIGZvciB0ZXN0aW5nXG4gICAgICBtZXRob2QuY2FsbChudWxsLCBhcmd1bWVudCB8fCBmdW5jdGlvbiAoKSB7IHRocm93IDE7IH0sIDEpO1xuICAgIH0pO1xuICB9O1xuXG4gIHZhciBuYXRpdmVKb2luID0gW10uam9pbjtcblxuICB2YXIgRVMzX1NUUklOR1MgPSBpbmRleGVkT2JqZWN0ICE9IE9iamVjdDtcbiAgdmFyIFNUUklDVF9NRVRIT0QkMyA9IGFycmF5TWV0aG9kSXNTdHJpY3QoJ2pvaW4nLCAnLCcpO1xuXG4gIC8vIGBBcnJheS5wcm90b3R5cGUuam9pbmAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLmpvaW5cbiAgX2V4cG9ydCh7IHRhcmdldDogJ0FycmF5JywgcHJvdG86IHRydWUsIGZvcmNlZDogRVMzX1NUUklOR1MgfHwgIVNUUklDVF9NRVRIT0QkMyB9LCB7XG4gICAgam9pbjogZnVuY3Rpb24gam9pbihzZXBhcmF0b3IpIHtcbiAgICAgIHJldHVybiBuYXRpdmVKb2luLmNhbGwodG9JbmRleGVkT2JqZWN0KHRoaXMpLCBzZXBhcmF0b3IgPT09IHVuZGVmaW5lZCA/ICcsJyA6IHNlcGFyYXRvcik7XG4gICAgfVxuICB9KTtcblxuICAvLyBgUmVnRXhwLnByb3RvdHlwZS5mbGFnc2AgZ2V0dGVyIGltcGxlbWVudGF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtZ2V0LXJlZ2V4cC5wcm90b3R5cGUuZmxhZ3NcbiAgdmFyIHJlZ2V4cEZsYWdzID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciB0aGF0ID0gYW5PYmplY3QodGhpcyk7XG4gICAgdmFyIHJlc3VsdCA9ICcnO1xuICAgIGlmICh0aGF0Lmdsb2JhbCkgcmVzdWx0ICs9ICdnJztcbiAgICBpZiAodGhhdC5pZ25vcmVDYXNlKSByZXN1bHQgKz0gJ2knO1xuICAgIGlmICh0aGF0Lm11bHRpbGluZSkgcmVzdWx0ICs9ICdtJztcbiAgICBpZiAodGhhdC5kb3RBbGwpIHJlc3VsdCArPSAncyc7XG4gICAgaWYgKHRoYXQudW5pY29kZSkgcmVzdWx0ICs9ICd1JztcbiAgICBpZiAodGhhdC5zdGlja3kpIHJlc3VsdCArPSAneSc7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICAvLyBiYWJlbC1taW5pZnkgdHJhbnNwaWxlcyBSZWdFeHAoJ2EnLCAneScpIC0+IC9hL3kgYW5kIGl0IGNhdXNlcyBTeW50YXhFcnJvcixcbiAgLy8gc28gd2UgdXNlIGFuIGludGVybWVkaWF0ZSBmdW5jdGlvbi5cbiAgZnVuY3Rpb24gUkUocywgZikge1xuICAgIHJldHVybiBSZWdFeHAocywgZik7XG4gIH1cblxuICB2YXIgVU5TVVBQT1JURURfWSQyID0gZmFpbHMoZnVuY3Rpb24gKCkge1xuICAgIC8vIGJhYmVsLW1pbmlmeSB0cmFuc3BpbGVzIFJlZ0V4cCgnYScsICd5JykgLT4gL2EveSBhbmQgaXQgY2F1c2VzIFN5bnRheEVycm9yXG4gICAgdmFyIHJlID0gUkUoJ2EnLCAneScpO1xuICAgIHJlLmxhc3RJbmRleCA9IDI7XG4gICAgcmV0dXJuIHJlLmV4ZWMoJ2FiY2QnKSAhPSBudWxsO1xuICB9KTtcblxuICB2YXIgQlJPS0VOX0NBUkVUID0gZmFpbHMoZnVuY3Rpb24gKCkge1xuICAgIC8vIGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTc3MzY4N1xuICAgIHZhciByZSA9IFJFKCdecicsICdneScpO1xuICAgIHJlLmxhc3RJbmRleCA9IDI7XG4gICAgcmV0dXJuIHJlLmV4ZWMoJ3N0cicpICE9IG51bGw7XG4gIH0pO1xuXG4gIHZhciByZWdleHBTdGlja3lIZWxwZXJzID0ge1xuICBcdFVOU1VQUE9SVEVEX1k6IFVOU1VQUE9SVEVEX1kkMixcbiAgXHRCUk9LRU5fQ0FSRVQ6IEJST0tFTl9DQVJFVFxuICB9O1xuXG4gIHZhciBuYXRpdmVFeGVjID0gUmVnRXhwLnByb3RvdHlwZS5leGVjO1xuICAvLyBUaGlzIGFsd2F5cyByZWZlcnMgdG8gdGhlIG5hdGl2ZSBpbXBsZW1lbnRhdGlvbiwgYmVjYXVzZSB0aGVcbiAgLy8gU3RyaW5nI3JlcGxhY2UgcG9seWZpbGwgdXNlcyAuL2ZpeC1yZWdleHAtd2VsbC1rbm93bi1zeW1ib2wtbG9naWMuanMsXG4gIC8vIHdoaWNoIGxvYWRzIHRoaXMgZmlsZSBiZWZvcmUgcGF0Y2hpbmcgdGhlIG1ldGhvZC5cbiAgdmFyIG5hdGl2ZVJlcGxhY2UgPSBTdHJpbmcucHJvdG90eXBlLnJlcGxhY2U7XG5cbiAgdmFyIHBhdGNoZWRFeGVjID0gbmF0aXZlRXhlYztcblxuICB2YXIgVVBEQVRFU19MQVNUX0lOREVYX1dST05HID0gKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcmUxID0gL2EvO1xuICAgIHZhciByZTIgPSAvYiovZztcbiAgICBuYXRpdmVFeGVjLmNhbGwocmUxLCAnYScpO1xuICAgIG5hdGl2ZUV4ZWMuY2FsbChyZTIsICdhJyk7XG4gICAgcmV0dXJuIHJlMS5sYXN0SW5kZXggIT09IDAgfHwgcmUyLmxhc3RJbmRleCAhPT0gMDtcbiAgfSkoKTtcblxuICB2YXIgVU5TVVBQT1JURURfWSQxID0gcmVnZXhwU3RpY2t5SGVscGVycy5VTlNVUFBPUlRFRF9ZIHx8IHJlZ2V4cFN0aWNreUhlbHBlcnMuQlJPS0VOX0NBUkVUO1xuXG4gIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwLCBjb3BpZWQgZnJvbSBlczUtc2hpbSdzIFN0cmluZyNzcGxpdCBwYXRjaC5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHJlZ2V4cC9uby1hc3NlcnRpb24tY2FwdHVyaW5nLWdyb3VwLCByZWdleHAvbm8tZW1wdHktZ3JvdXAgLS0gcmVxdWlyZWQgZm9yIHRlc3RpbmdcbiAgdmFyIE5QQ0dfSU5DTFVERUQgPSAvKCk/Py8uZXhlYygnJylbMV0gIT09IHVuZGVmaW5lZDtcblxuICB2YXIgUEFUQ0ggPSBVUERBVEVTX0xBU1RfSU5ERVhfV1JPTkcgfHwgTlBDR19JTkNMVURFRCB8fCBVTlNVUFBPUlRFRF9ZJDE7XG5cbiAgaWYgKFBBVENIKSB7XG4gICAgcGF0Y2hlZEV4ZWMgPSBmdW5jdGlvbiBleGVjKHN0cikge1xuICAgICAgdmFyIHJlID0gdGhpcztcbiAgICAgIHZhciBsYXN0SW5kZXgsIHJlQ29weSwgbWF0Y2gsIGk7XG4gICAgICB2YXIgc3RpY2t5ID0gVU5TVVBQT1JURURfWSQxICYmIHJlLnN0aWNreTtcbiAgICAgIHZhciBmbGFncyA9IHJlZ2V4cEZsYWdzLmNhbGwocmUpO1xuICAgICAgdmFyIHNvdXJjZSA9IHJlLnNvdXJjZTtcbiAgICAgIHZhciBjaGFyc0FkZGVkID0gMDtcbiAgICAgIHZhciBzdHJDb3B5ID0gc3RyO1xuXG4gICAgICBpZiAoc3RpY2t5KSB7XG4gICAgICAgIGZsYWdzID0gZmxhZ3MucmVwbGFjZSgneScsICcnKTtcbiAgICAgICAgaWYgKGZsYWdzLmluZGV4T2YoJ2cnKSA9PT0gLTEpIHtcbiAgICAgICAgICBmbGFncyArPSAnZyc7XG4gICAgICAgIH1cblxuICAgICAgICBzdHJDb3B5ID0gU3RyaW5nKHN0cikuc2xpY2UocmUubGFzdEluZGV4KTtcbiAgICAgICAgLy8gU3VwcG9ydCBhbmNob3JlZCBzdGlja3kgYmVoYXZpb3IuXG4gICAgICAgIGlmIChyZS5sYXN0SW5kZXggPiAwICYmICghcmUubXVsdGlsaW5lIHx8IHJlLm11bHRpbGluZSAmJiBzdHJbcmUubGFzdEluZGV4IC0gMV0gIT09ICdcXG4nKSkge1xuICAgICAgICAgIHNvdXJjZSA9ICcoPzogJyArIHNvdXJjZSArICcpJztcbiAgICAgICAgICBzdHJDb3B5ID0gJyAnICsgc3RyQ29weTtcbiAgICAgICAgICBjaGFyc0FkZGVkKys7XG4gICAgICAgIH1cbiAgICAgICAgLy8gXig/ICsgcnggKyApIGlzIG5lZWRlZCwgaW4gY29tYmluYXRpb24gd2l0aCBzb21lIHN0ciBzbGljaW5nLCB0b1xuICAgICAgICAvLyBzaW11bGF0ZSB0aGUgJ3knIGZsYWcuXG4gICAgICAgIHJlQ29weSA9IG5ldyBSZWdFeHAoJ14oPzonICsgc291cmNlICsgJyknLCBmbGFncyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChOUENHX0lOQ0xVREVEKSB7XG4gICAgICAgIHJlQ29weSA9IG5ldyBSZWdFeHAoJ14nICsgc291cmNlICsgJyQoPyFcXFxccyknLCBmbGFncyk7XG4gICAgICB9XG4gICAgICBpZiAoVVBEQVRFU19MQVNUX0lOREVYX1dST05HKSBsYXN0SW5kZXggPSByZS5sYXN0SW5kZXg7XG5cbiAgICAgIG1hdGNoID0gbmF0aXZlRXhlYy5jYWxsKHN0aWNreSA/IHJlQ29weSA6IHJlLCBzdHJDb3B5KTtcblxuICAgICAgaWYgKHN0aWNreSkge1xuICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICBtYXRjaC5pbnB1dCA9IG1hdGNoLmlucHV0LnNsaWNlKGNoYXJzQWRkZWQpO1xuICAgICAgICAgIG1hdGNoWzBdID0gbWF0Y2hbMF0uc2xpY2UoY2hhcnNBZGRlZCk7XG4gICAgICAgICAgbWF0Y2guaW5kZXggPSByZS5sYXN0SW5kZXg7XG4gICAgICAgICAgcmUubGFzdEluZGV4ICs9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgfSBlbHNlIHJlLmxhc3RJbmRleCA9IDA7XG4gICAgICB9IGVsc2UgaWYgKFVQREFURVNfTEFTVF9JTkRFWF9XUk9ORyAmJiBtYXRjaCkge1xuICAgICAgICByZS5sYXN0SW5kZXggPSByZS5nbG9iYWwgPyBtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aCA6IGxhc3RJbmRleDtcbiAgICAgIH1cbiAgICAgIGlmIChOUENHX0lOQ0xVREVEICYmIG1hdGNoICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgLy8gRml4IGJyb3dzZXJzIHdob3NlIGBleGVjYCBtZXRob2RzIGRvbid0IGNvbnNpc3RlbnRseSByZXR1cm4gYHVuZGVmaW5lZGBcbiAgICAgICAgLy8gZm9yIE5QQ0csIGxpa2UgSUU4LiBOT1RFOiBUaGlzIGRvZXNuJyB3b3JrIGZvciAvKC4/KT8vXG4gICAgICAgIG5hdGl2ZVJlcGxhY2UuY2FsbChtYXRjaFswXSwgcmVDb3B5LCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgZm9yIChpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmaW5lZCkgbWF0Y2hbaV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG1hdGNoO1xuICAgIH07XG4gIH1cblxuICB2YXIgcmVnZXhwRXhlYyA9IHBhdGNoZWRFeGVjO1xuXG4gIC8vIGBSZWdFeHAucHJvdG90eXBlLmV4ZWNgIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXJlZ2V4cC5wcm90b3R5cGUuZXhlY1xuICBfZXhwb3J0KHsgdGFyZ2V0OiAnUmVnRXhwJywgcHJvdG86IHRydWUsIGZvcmNlZDogLy4vLmV4ZWMgIT09IHJlZ2V4cEV4ZWMgfSwge1xuICAgIGV4ZWM6IHJlZ2V4cEV4ZWNcbiAgfSk7XG5cbiAgdmFyIGVuZ2luZUlzTm9kZSA9IGNsYXNzb2ZSYXcoZ2xvYmFsXzEucHJvY2VzcykgPT0gJ3Byb2Nlc3MnO1xuXG4gIHZhciBlbmdpbmVVc2VyQWdlbnQgPSBnZXRCdWlsdEluKCduYXZpZ2F0b3InLCAndXNlckFnZW50JykgfHwgJyc7XG5cbiAgdmFyIHByb2Nlc3MgPSBnbG9iYWxfMS5wcm9jZXNzO1xuICB2YXIgdmVyc2lvbnMgPSBwcm9jZXNzICYmIHByb2Nlc3MudmVyc2lvbnM7XG4gIHZhciB2OCA9IHZlcnNpb25zICYmIHZlcnNpb25zLnY4O1xuICB2YXIgbWF0Y2gsIHZlcnNpb247XG5cbiAgaWYgKHY4KSB7XG4gICAgbWF0Y2ggPSB2OC5zcGxpdCgnLicpO1xuICAgIHZlcnNpb24gPSBtYXRjaFswXSArIG1hdGNoWzFdO1xuICB9IGVsc2UgaWYgKGVuZ2luZVVzZXJBZ2VudCkge1xuICAgIG1hdGNoID0gZW5naW5lVXNlckFnZW50Lm1hdGNoKC9FZGdlXFwvKFxcZCspLyk7XG4gICAgaWYgKCFtYXRjaCB8fCBtYXRjaFsxXSA+PSA3NCkge1xuICAgICAgbWF0Y2ggPSBlbmdpbmVVc2VyQWdlbnQubWF0Y2goL0Nocm9tZVxcLyhcXGQrKS8pO1xuICAgICAgaWYgKG1hdGNoKSB2ZXJzaW9uID0gbWF0Y2hbMV07XG4gICAgfVxuICB9XG5cbiAgdmFyIGVuZ2luZVY4VmVyc2lvbiA9IHZlcnNpb24gJiYgK3ZlcnNpb247XG5cbiAgdmFyIG5hdGl2ZVN5bWJvbCA9ICEhT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyAmJiAhZmFpbHMoZnVuY3Rpb24gKCkge1xuICAgIC8qIGdsb2JhbCBTeW1ib2wgLS0gcmVxdWlyZWQgZm9yIHRlc3RpbmcgKi9cbiAgICByZXR1cm4gIVN5bWJvbC5zaGFtICYmXG4gICAgICAvLyBDaHJvbWUgMzggU3ltYm9sIGhhcyBpbmNvcnJlY3QgdG9TdHJpbmcgY29udmVyc2lvblxuICAgICAgLy8gQ2hyb21lIDM4LTQwIHN5bWJvbHMgYXJlIG5vdCBpbmhlcml0ZWQgZnJvbSBET00gY29sbGVjdGlvbnMgcHJvdG90eXBlcyB0byBpbnN0YW5jZXNcbiAgICAgIChlbmdpbmVJc05vZGUgPyBlbmdpbmVWOFZlcnNpb24gPT09IDM4IDogZW5naW5lVjhWZXJzaW9uID4gMzcgJiYgZW5naW5lVjhWZXJzaW9uIDwgNDEpO1xuICB9KTtcblxuICB2YXIgdXNlU3ltYm9sQXNVaWQgPSBuYXRpdmVTeW1ib2xcbiAgICAvKiBnbG9iYWwgU3ltYm9sIC0tIHNhZmUgKi9cbiAgICAmJiAhU3ltYm9sLnNoYW1cbiAgICAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09ICdzeW1ib2wnO1xuXG4gIHZhciBXZWxsS25vd25TeW1ib2xzU3RvcmUgPSBzaGFyZWQoJ3drcycpO1xuICB2YXIgU3ltYm9sJDEgPSBnbG9iYWxfMS5TeW1ib2w7XG4gIHZhciBjcmVhdGVXZWxsS25vd25TeW1ib2wgPSB1c2VTeW1ib2xBc1VpZCA/IFN5bWJvbCQxIDogU3ltYm9sJDEgJiYgU3ltYm9sJDEud2l0aG91dFNldHRlciB8fCB1aWQ7XG5cbiAgdmFyIHdlbGxLbm93blN5bWJvbCA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgaWYgKCFoYXMkMShXZWxsS25vd25TeW1ib2xzU3RvcmUsIG5hbWUpIHx8ICEobmF0aXZlU3ltYm9sIHx8IHR5cGVvZiBXZWxsS25vd25TeW1ib2xzU3RvcmVbbmFtZV0gPT0gJ3N0cmluZycpKSB7XG4gICAgICBpZiAobmF0aXZlU3ltYm9sICYmIGhhcyQxKFN5bWJvbCQxLCBuYW1lKSkge1xuICAgICAgICBXZWxsS25vd25TeW1ib2xzU3RvcmVbbmFtZV0gPSBTeW1ib2wkMVtuYW1lXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIFdlbGxLbm93blN5bWJvbHNTdG9yZVtuYW1lXSA9IGNyZWF0ZVdlbGxLbm93blN5bWJvbCgnU3ltYm9sLicgKyBuYW1lKTtcbiAgICAgIH1cbiAgICB9IHJldHVybiBXZWxsS25vd25TeW1ib2xzU3RvcmVbbmFtZV07XG4gIH07XG5cbiAgLy8gVE9ETzogUmVtb3ZlIGZyb20gYGNvcmUtanNANGAgc2luY2UgaXQncyBtb3ZlZCB0byBlbnRyeSBwb2ludHNcblxuXG5cblxuXG5cblxuICB2YXIgU1BFQ0lFUyQ1ID0gd2VsbEtub3duU3ltYm9sKCdzcGVjaWVzJyk7XG5cbiAgdmFyIFJFUExBQ0VfU1VQUE9SVFNfTkFNRURfR1JPVVBTID0gIWZhaWxzKGZ1bmN0aW9uICgpIHtcbiAgICAvLyAjcmVwbGFjZSBuZWVkcyBidWlsdC1pbiBzdXBwb3J0IGZvciBuYW1lZCBncm91cHMuXG4gICAgLy8gI21hdGNoIHdvcmtzIGZpbmUgYmVjYXVzZSBpdCBqdXN0IHJldHVybiB0aGUgZXhlYyByZXN1bHRzLCBldmVuIGlmIGl0IGhhc1xuICAgIC8vIGEgXCJncm9wc1wiIHByb3BlcnR5LlxuICAgIHZhciByZSA9IC8uLztcbiAgICByZS5leGVjID0gZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgcmVzdWx0Lmdyb3VwcyA9IHsgYTogJzcnIH07XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gICAgcmV0dXJuICcnLnJlcGxhY2UocmUsICckPGE+JykgIT09ICc3JztcbiAgfSk7XG5cbiAgLy8gSUUgPD0gMTEgcmVwbGFjZXMgJDAgd2l0aCB0aGUgd2hvbGUgbWF0Y2gsIGFzIGlmIGl0IHdhcyAkJlxuICAvLyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82MDI0NjY2L2dldHRpbmctaWUtdG8tcmVwbGFjZS1hLXJlZ2V4LXdpdGgtdGhlLWxpdGVyYWwtc3RyaW5nLTBcbiAgdmFyIFJFUExBQ0VfS0VFUFNfJDAgPSAoZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAnYScucmVwbGFjZSgvLi8sICckMCcpID09PSAnJDAnO1xuICB9KSgpO1xuXG4gIHZhciBSRVBMQUNFID0gd2VsbEtub3duU3ltYm9sKCdyZXBsYWNlJyk7XG4gIC8vIFNhZmFyaSA8PSAxMy4wLjMoPykgc3Vic3RpdHV0ZXMgbnRoIGNhcHR1cmUgd2hlcmUgbj5tIHdpdGggYW4gZW1wdHkgc3RyaW5nXG4gIHZhciBSRUdFWFBfUkVQTEFDRV9TVUJTVElUVVRFU19VTkRFRklORURfQ0FQVFVSRSA9IChmdW5jdGlvbiAoKSB7XG4gICAgaWYgKC8uL1tSRVBMQUNFXSkge1xuICAgICAgcmV0dXJuIC8uL1tSRVBMQUNFXSgnYScsICckMCcpID09PSAnJztcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9KSgpO1xuXG4gIC8vIENocm9tZSA1MSBoYXMgYSBidWdneSBcInNwbGl0XCIgaW1wbGVtZW50YXRpb24gd2hlbiBSZWdFeHAjZXhlYyAhPT0gbmF0aXZlRXhlY1xuICAvLyBXZWV4IEpTIGhhcyBmcm96ZW4gYnVpbHQtaW4gcHJvdG90eXBlcywgc28gdXNlIHRyeSAvIGNhdGNoIHdyYXBwZXJcbiAgdmFyIFNQTElUX1dPUktTX1dJVEhfT1ZFUldSSVRURU5fRVhFQyA9ICFmYWlscyhmdW5jdGlvbiAoKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHJlZ2V4cC9uby1lbXB0eS1ncm91cCAtLSByZXF1aXJlZCBmb3IgdGVzdGluZ1xuICAgIHZhciByZSA9IC8oPzopLztcbiAgICB2YXIgb3JpZ2luYWxFeGVjID0gcmUuZXhlYztcbiAgICByZS5leGVjID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gb3JpZ2luYWxFeGVjLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7IH07XG4gICAgdmFyIHJlc3VsdCA9ICdhYicuc3BsaXQocmUpO1xuICAgIHJldHVybiByZXN1bHQubGVuZ3RoICE9PSAyIHx8IHJlc3VsdFswXSAhPT0gJ2EnIHx8IHJlc3VsdFsxXSAhPT0gJ2InO1xuICB9KTtcblxuICB2YXIgZml4UmVnZXhwV2VsbEtub3duU3ltYm9sTG9naWMgPSBmdW5jdGlvbiAoS0VZLCBsZW5ndGgsIGV4ZWMsIHNoYW0pIHtcbiAgICB2YXIgU1lNQk9MID0gd2VsbEtub3duU3ltYm9sKEtFWSk7XG5cbiAgICB2YXIgREVMRUdBVEVTX1RPX1NZTUJPTCA9ICFmYWlscyhmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBTdHJpbmcgbWV0aG9kcyBjYWxsIHN5bWJvbC1uYW1lZCBSZWdFcCBtZXRob2RzXG4gICAgICB2YXIgTyA9IHt9O1xuICAgICAgT1tTWU1CT0xdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gNzsgfTtcbiAgICAgIHJldHVybiAnJ1tLRVldKE8pICE9IDc7XG4gICAgfSk7XG5cbiAgICB2YXIgREVMRUdBVEVTX1RPX0VYRUMgPSBERUxFR0FURVNfVE9fU1lNQk9MICYmICFmYWlscyhmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBTeW1ib2wtbmFtZWQgUmVnRXhwIG1ldGhvZHMgY2FsbCAuZXhlY1xuICAgICAgdmFyIGV4ZWNDYWxsZWQgPSBmYWxzZTtcbiAgICAgIHZhciByZSA9IC9hLztcblxuICAgICAgaWYgKEtFWSA9PT0gJ3NwbGl0Jykge1xuICAgICAgICAvLyBXZSBjYW4ndCB1c2UgcmVhbCByZWdleCBoZXJlIHNpbmNlIGl0IGNhdXNlcyBkZW9wdGltaXphdGlvblxuICAgICAgICAvLyBhbmQgc2VyaW91cyBwZXJmb3JtYW5jZSBkZWdyYWRhdGlvbiBpbiBWOFxuICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vemxvaXJvY2svY29yZS1qcy9pc3N1ZXMvMzA2XG4gICAgICAgIHJlID0ge307XG4gICAgICAgIC8vIFJlZ0V4cFtAQHNwbGl0XSBkb2Vzbid0IGNhbGwgdGhlIHJlZ2V4J3MgZXhlYyBtZXRob2QsIGJ1dCBmaXJzdCBjcmVhdGVzXG4gICAgICAgIC8vIGEgbmV3IG9uZS4gV2UgbmVlZCB0byByZXR1cm4gdGhlIHBhdGNoZWQgcmVnZXggd2hlbiBjcmVhdGluZyB0aGUgbmV3IG9uZS5cbiAgICAgICAgcmUuY29uc3RydWN0b3IgPSB7fTtcbiAgICAgICAgcmUuY29uc3RydWN0b3JbU1BFQ0lFUyQ1XSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHJlOyB9O1xuICAgICAgICByZS5mbGFncyA9ICcnO1xuICAgICAgICByZVtTWU1CT0xdID0gLy4vW1NZTUJPTF07XG4gICAgICB9XG5cbiAgICAgIHJlLmV4ZWMgPSBmdW5jdGlvbiAoKSB7IGV4ZWNDYWxsZWQgPSB0cnVlOyByZXR1cm4gbnVsbDsgfTtcblxuICAgICAgcmVbU1lNQk9MXSgnJyk7XG4gICAgICByZXR1cm4gIWV4ZWNDYWxsZWQ7XG4gICAgfSk7XG5cbiAgICBpZiAoXG4gICAgICAhREVMRUdBVEVTX1RPX1NZTUJPTCB8fFxuICAgICAgIURFTEVHQVRFU19UT19FWEVDIHx8XG4gICAgICAoS0VZID09PSAncmVwbGFjZScgJiYgIShcbiAgICAgICAgUkVQTEFDRV9TVVBQT1JUU19OQU1FRF9HUk9VUFMgJiZcbiAgICAgICAgUkVQTEFDRV9LRUVQU18kMCAmJlxuICAgICAgICAhUkVHRVhQX1JFUExBQ0VfU1VCU1RJVFVURVNfVU5ERUZJTkVEX0NBUFRVUkVcbiAgICAgICkpIHx8XG4gICAgICAoS0VZID09PSAnc3BsaXQnICYmICFTUExJVF9XT1JLU19XSVRIX09WRVJXUklUVEVOX0VYRUMpXG4gICAgKSB7XG4gICAgICB2YXIgbmF0aXZlUmVnRXhwTWV0aG9kID0gLy4vW1NZTUJPTF07XG4gICAgICB2YXIgbWV0aG9kcyA9IGV4ZWMoU1lNQk9MLCAnJ1tLRVldLCBmdW5jdGlvbiAobmF0aXZlTWV0aG9kLCByZWdleHAsIHN0ciwgYXJnMiwgZm9yY2VTdHJpbmdNZXRob2QpIHtcbiAgICAgICAgaWYgKHJlZ2V4cC5leGVjID09PSByZWdleHBFeGVjKSB7XG4gICAgICAgICAgaWYgKERFTEVHQVRFU19UT19TWU1CT0wgJiYgIWZvcmNlU3RyaW5nTWV0aG9kKSB7XG4gICAgICAgICAgICAvLyBUaGUgbmF0aXZlIFN0cmluZyBtZXRob2QgYWxyZWFkeSBkZWxlZ2F0ZXMgdG8gQEBtZXRob2QgKHRoaXNcbiAgICAgICAgICAgIC8vIHBvbHlmaWxsZWQgZnVuY3Rpb24pLCBsZWFzaW5nIHRvIGluZmluaXRlIHJlY3Vyc2lvbi5cbiAgICAgICAgICAgIC8vIFdlIGF2b2lkIGl0IGJ5IGRpcmVjdGx5IGNhbGxpbmcgdGhlIG5hdGl2ZSBAQG1ldGhvZCBtZXRob2QuXG4gICAgICAgICAgICByZXR1cm4geyBkb25lOiB0cnVlLCB2YWx1ZTogbmF0aXZlUmVnRXhwTWV0aG9kLmNhbGwocmVnZXhwLCBzdHIsIGFyZzIpIH07XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB7IGRvbmU6IHRydWUsIHZhbHVlOiBuYXRpdmVNZXRob2QuY2FsbChzdHIsIHJlZ2V4cCwgYXJnMikgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyBkb25lOiBmYWxzZSB9O1xuICAgICAgfSwge1xuICAgICAgICBSRVBMQUNFX0tFRVBTXyQwOiBSRVBMQUNFX0tFRVBTXyQwLFxuICAgICAgICBSRUdFWFBfUkVQTEFDRV9TVUJTVElUVVRFU19VTkRFRklORURfQ0FQVFVSRTogUkVHRVhQX1JFUExBQ0VfU1VCU1RJVFVURVNfVU5ERUZJTkVEX0NBUFRVUkVcbiAgICAgIH0pO1xuICAgICAgdmFyIHN0cmluZ01ldGhvZCA9IG1ldGhvZHNbMF07XG4gICAgICB2YXIgcmVnZXhNZXRob2QgPSBtZXRob2RzWzFdO1xuXG4gICAgICByZWRlZmluZShTdHJpbmcucHJvdG90eXBlLCBLRVksIHN0cmluZ01ldGhvZCk7XG4gICAgICByZWRlZmluZShSZWdFeHAucHJvdG90eXBlLCBTWU1CT0wsIGxlbmd0aCA9PSAyXG4gICAgICAgIC8vIDIxLjIuNS44IFJlZ0V4cC5wcm90b3R5cGVbQEByZXBsYWNlXShzdHJpbmcsIHJlcGxhY2VWYWx1ZSlcbiAgICAgICAgLy8gMjEuMi41LjExIFJlZ0V4cC5wcm90b3R5cGVbQEBzcGxpdF0oc3RyaW5nLCBsaW1pdClcbiAgICAgICAgPyBmdW5jdGlvbiAoc3RyaW5nLCBhcmcpIHsgcmV0dXJuIHJlZ2V4TWV0aG9kLmNhbGwoc3RyaW5nLCB0aGlzLCBhcmcpOyB9XG4gICAgICAgIC8vIDIxLjIuNS42IFJlZ0V4cC5wcm90b3R5cGVbQEBtYXRjaF0oc3RyaW5nKVxuICAgICAgICAvLyAyMS4yLjUuOSBSZWdFeHAucHJvdG90eXBlW0BAc2VhcmNoXShzdHJpbmcpXG4gICAgICAgIDogZnVuY3Rpb24gKHN0cmluZykgeyByZXR1cm4gcmVnZXhNZXRob2QuY2FsbChzdHJpbmcsIHRoaXMpOyB9XG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChzaGFtKSBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkoUmVnRXhwLnByb3RvdHlwZVtTWU1CT0xdLCAnc2hhbScsIHRydWUpO1xuICB9O1xuXG4gIHZhciBNQVRDSCQyID0gd2VsbEtub3duU3ltYm9sKCdtYXRjaCcpO1xuXG4gIC8vIGBJc1JlZ0V4cGAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtaXNyZWdleHBcbiAgdmFyIGlzUmVnZXhwID0gZnVuY3Rpb24gKGl0KSB7XG4gICAgdmFyIGlzUmVnRXhwO1xuICAgIHJldHVybiBpc09iamVjdChpdCkgJiYgKChpc1JlZ0V4cCA9IGl0W01BVENIJDJdKSAhPT0gdW5kZWZpbmVkID8gISFpc1JlZ0V4cCA6IGNsYXNzb2ZSYXcoaXQpID09ICdSZWdFeHAnKTtcbiAgfTtcblxuICB2YXIgYUZ1bmN0aW9uID0gZnVuY3Rpb24gKGl0KSB7XG4gICAgaWYgKHR5cGVvZiBpdCAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICB0aHJvdyBUeXBlRXJyb3IoU3RyaW5nKGl0KSArICcgaXMgbm90IGEgZnVuY3Rpb24nKTtcbiAgICB9IHJldHVybiBpdDtcbiAgfTtcblxuICB2YXIgU1BFQ0lFUyQ0ID0gd2VsbEtub3duU3ltYm9sKCdzcGVjaWVzJyk7XG5cbiAgLy8gYFNwZWNpZXNDb25zdHJ1Y3RvcmAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtc3BlY2llc2NvbnN0cnVjdG9yXG4gIHZhciBzcGVjaWVzQ29uc3RydWN0b3IgPSBmdW5jdGlvbiAoTywgZGVmYXVsdENvbnN0cnVjdG9yKSB7XG4gICAgdmFyIEMgPSBhbk9iamVjdChPKS5jb25zdHJ1Y3RvcjtcbiAgICB2YXIgUztcbiAgICByZXR1cm4gQyA9PT0gdW5kZWZpbmVkIHx8IChTID0gYW5PYmplY3QoQylbU1BFQ0lFUyQ0XSkgPT0gdW5kZWZpbmVkID8gZGVmYXVsdENvbnN0cnVjdG9yIDogYUZ1bmN0aW9uKFMpO1xuICB9O1xuXG4gIC8vIGBTdHJpbmcucHJvdG90eXBlLnsgY29kZVBvaW50QXQsIGF0IH1gIG1ldGhvZHMgaW1wbGVtZW50YXRpb25cbiAgdmFyIGNyZWF0ZU1ldGhvZCQyID0gZnVuY3Rpb24gKENPTlZFUlRfVE9fU1RSSU5HKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgkdGhpcywgcG9zKSB7XG4gICAgICB2YXIgUyA9IFN0cmluZyhyZXF1aXJlT2JqZWN0Q29lcmNpYmxlKCR0aGlzKSk7XG4gICAgICB2YXIgcG9zaXRpb24gPSB0b0ludGVnZXIocG9zKTtcbiAgICAgIHZhciBzaXplID0gUy5sZW5ndGg7XG4gICAgICB2YXIgZmlyc3QsIHNlY29uZDtcbiAgICAgIGlmIChwb3NpdGlvbiA8IDAgfHwgcG9zaXRpb24gPj0gc2l6ZSkgcmV0dXJuIENPTlZFUlRfVE9fU1RSSU5HID8gJycgOiB1bmRlZmluZWQ7XG4gICAgICBmaXJzdCA9IFMuY2hhckNvZGVBdChwb3NpdGlvbik7XG4gICAgICByZXR1cm4gZmlyc3QgPCAweEQ4MDAgfHwgZmlyc3QgPiAweERCRkYgfHwgcG9zaXRpb24gKyAxID09PSBzaXplXG4gICAgICAgIHx8IChzZWNvbmQgPSBTLmNoYXJDb2RlQXQocG9zaXRpb24gKyAxKSkgPCAweERDMDAgfHwgc2Vjb25kID4gMHhERkZGXG4gICAgICAgICAgPyBDT05WRVJUX1RPX1NUUklORyA/IFMuY2hhckF0KHBvc2l0aW9uKSA6IGZpcnN0XG4gICAgICAgICAgOiBDT05WRVJUX1RPX1NUUklORyA/IFMuc2xpY2UocG9zaXRpb24sIHBvc2l0aW9uICsgMikgOiAoZmlyc3QgLSAweEQ4MDAgPDwgMTApICsgKHNlY29uZCAtIDB4REMwMCkgKyAweDEwMDAwO1xuICAgIH07XG4gIH07XG5cbiAgdmFyIHN0cmluZ011bHRpYnl0ZSA9IHtcbiAgICAvLyBgU3RyaW5nLnByb3RvdHlwZS5jb2RlUG9pbnRBdGAgbWV0aG9kXG4gICAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1zdHJpbmcucHJvdG90eXBlLmNvZGVwb2ludGF0XG4gICAgY29kZUF0OiBjcmVhdGVNZXRob2QkMihmYWxzZSksXG4gICAgLy8gYFN0cmluZy5wcm90b3R5cGUuYXRgIG1ldGhvZFxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9tYXRoaWFzYnluZW5zL1N0cmluZy5wcm90b3R5cGUuYXRcbiAgICBjaGFyQXQ6IGNyZWF0ZU1ldGhvZCQyKHRydWUpXG4gIH07XG5cbiAgdmFyIGNoYXJBdCA9IHN0cmluZ011bHRpYnl0ZS5jaGFyQXQ7XG5cbiAgLy8gYEFkdmFuY2VTdHJpbmdJbmRleGAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYWR2YW5jZXN0cmluZ2luZGV4XG4gIHZhciBhZHZhbmNlU3RyaW5nSW5kZXggPSBmdW5jdGlvbiAoUywgaW5kZXgsIHVuaWNvZGUpIHtcbiAgICByZXR1cm4gaW5kZXggKyAodW5pY29kZSA/IGNoYXJBdChTLCBpbmRleCkubGVuZ3RoIDogMSk7XG4gIH07XG5cbiAgLy8gYFJlZ0V4cEV4ZWNgIGFic3RyYWN0IG9wZXJhdGlvblxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXJlZ2V4cGV4ZWNcbiAgdmFyIHJlZ2V4cEV4ZWNBYnN0cmFjdCA9IGZ1bmN0aW9uIChSLCBTKSB7XG4gICAgdmFyIGV4ZWMgPSBSLmV4ZWM7XG4gICAgaWYgKHR5cGVvZiBleGVjID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gZXhlYy5jYWxsKFIsIFMpO1xuICAgICAgaWYgKHR5cGVvZiByZXN1bHQgIT09ICdvYmplY3QnKSB7XG4gICAgICAgIHRocm93IFR5cGVFcnJvcignUmVnRXhwIGV4ZWMgbWV0aG9kIHJldHVybmVkIHNvbWV0aGluZyBvdGhlciB0aGFuIGFuIE9iamVjdCBvciBudWxsJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGlmIChjbGFzc29mUmF3KFIpICE9PSAnUmVnRXhwJykge1xuICAgICAgdGhyb3cgVHlwZUVycm9yKCdSZWdFeHAjZXhlYyBjYWxsZWQgb24gaW5jb21wYXRpYmxlIHJlY2VpdmVyJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlZ2V4cEV4ZWMuY2FsbChSLCBTKTtcbiAgfTtcblxuICB2YXIgYXJyYXlQdXNoID0gW10ucHVzaDtcbiAgdmFyIG1pbiQ0ID0gTWF0aC5taW47XG4gIHZhciBNQVhfVUlOVDMyID0gMHhGRkZGRkZGRjtcblxuICAvLyBiYWJlbC1taW5pZnkgdHJhbnNwaWxlcyBSZWdFeHAoJ3gnLCAneScpIC0+IC94L3kgYW5kIGl0IGNhdXNlcyBTeW50YXhFcnJvclxuICB2YXIgU1VQUE9SVFNfWSA9ICFmYWlscyhmdW5jdGlvbiAoKSB7IHJldHVybiAhUmVnRXhwKE1BWF9VSU5UMzIsICd5Jyk7IH0pO1xuXG4gIC8vIEBAc3BsaXQgbG9naWNcbiAgZml4UmVnZXhwV2VsbEtub3duU3ltYm9sTG9naWMoJ3NwbGl0JywgMiwgZnVuY3Rpb24gKFNQTElULCBuYXRpdmVTcGxpdCwgbWF5YmVDYWxsTmF0aXZlKSB7XG4gICAgdmFyIGludGVybmFsU3BsaXQ7XG4gICAgaWYgKFxuICAgICAgJ2FiYmMnLnNwbGl0KC8oYikqLylbMV0gPT0gJ2MnIHx8XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVnZXhwL25vLWVtcHR5LWdyb3VwIC0tIHJlcXVpcmVkIGZvciB0ZXN0aW5nXG4gICAgICAndGVzdCcuc3BsaXQoLyg/OikvLCAtMSkubGVuZ3RoICE9IDQgfHxcbiAgICAgICdhYicuc3BsaXQoLyg/OmFiKSovKS5sZW5ndGggIT0gMiB8fFxuICAgICAgJy4nLnNwbGl0KC8oLj8pKC4/KS8pLmxlbmd0aCAhPSA0IHx8XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVnZXhwL25vLWFzc2VydGlvbi1jYXB0dXJpbmctZ3JvdXAsIHJlZ2V4cC9uby1lbXB0eS1ncm91cCAtLSByZXF1aXJlZCBmb3IgdGVzdGluZ1xuICAgICAgJy4nLnNwbGl0KC8oKSgpLykubGVuZ3RoID4gMSB8fFxuICAgICAgJycuc3BsaXQoLy4/LykubGVuZ3RoXG4gICAgKSB7XG4gICAgICAvLyBiYXNlZCBvbiBlczUtc2hpbSBpbXBsZW1lbnRhdGlvbiwgbmVlZCB0byByZXdvcmsgaXRcbiAgICAgIGludGVybmFsU3BsaXQgPSBmdW5jdGlvbiAoc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICB2YXIgc3RyaW5nID0gU3RyaW5nKHJlcXVpcmVPYmplY3RDb2VyY2libGUodGhpcykpO1xuICAgICAgICB2YXIgbGltID0gbGltaXQgPT09IHVuZGVmaW5lZCA/IE1BWF9VSU5UMzIgOiBsaW1pdCA+Pj4gMDtcbiAgICAgICAgaWYgKGxpbSA9PT0gMCkgcmV0dXJuIFtdO1xuICAgICAgICBpZiAoc2VwYXJhdG9yID09PSB1bmRlZmluZWQpIHJldHVybiBbc3RyaW5nXTtcbiAgICAgICAgLy8gSWYgYHNlcGFyYXRvcmAgaXMgbm90IGEgcmVnZXgsIHVzZSBuYXRpdmUgc3BsaXRcbiAgICAgICAgaWYgKCFpc1JlZ2V4cChzZXBhcmF0b3IpKSB7XG4gICAgICAgICAgcmV0dXJuIG5hdGl2ZVNwbGl0LmNhbGwoc3RyaW5nLCBzZXBhcmF0b3IsIGxpbSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG91dHB1dCA9IFtdO1xuICAgICAgICB2YXIgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyAnaScgOiAnJykgK1xuICAgICAgICAgICAgICAgICAgICAoc2VwYXJhdG9yLm11bHRpbGluZSA/ICdtJyA6ICcnKSArXG4gICAgICAgICAgICAgICAgICAgIChzZXBhcmF0b3IudW5pY29kZSA/ICd1JyA6ICcnKSArXG4gICAgICAgICAgICAgICAgICAgIChzZXBhcmF0b3Iuc3RpY2t5ID8gJ3knIDogJycpO1xuICAgICAgICB2YXIgbGFzdExhc3RJbmRleCA9IDA7XG4gICAgICAgIC8vIE1ha2UgYGdsb2JhbGAgYW5kIGF2b2lkIGBsYXN0SW5kZXhgIGlzc3VlcyBieSB3b3JraW5nIHdpdGggYSBjb3B5XG4gICAgICAgIHZhciBzZXBhcmF0b3JDb3B5ID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArICdnJyk7XG4gICAgICAgIHZhciBtYXRjaCwgbGFzdEluZGV4LCBsYXN0TGVuZ3RoO1xuICAgICAgICB3aGlsZSAobWF0Y2ggPSByZWdleHBFeGVjLmNhbGwoc2VwYXJhdG9yQ29weSwgc3RyaW5nKSkge1xuICAgICAgICAgIGxhc3RJbmRleCA9IHNlcGFyYXRvckNvcHkubGFzdEluZGV4O1xuICAgICAgICAgIGlmIChsYXN0SW5kZXggPiBsYXN0TGFzdEluZGV4KSB7XG4gICAgICAgICAgICBvdXRwdXQucHVzaChzdHJpbmcuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyaW5nLmxlbmd0aCkgYXJyYXlQdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICBpZiAob3V0cHV0Lmxlbmd0aCA+PSBsaW0pIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoc2VwYXJhdG9yQ29weS5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSBzZXBhcmF0b3JDb3B5Lmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgIH1cbiAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0cmluZy5sZW5ndGgpIHtcbiAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yQ29weS50ZXN0KCcnKSkgb3V0cHV0LnB1c2goJycpO1xuICAgICAgICB9IGVsc2Ugb3V0cHV0LnB1c2goc3RyaW5nLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW0gPyBvdXRwdXQuc2xpY2UoMCwgbGltKSA6IG91dHB1dDtcbiAgICAgIH07XG4gICAgLy8gQ2hha3JhLCBWOFxuICAgIH0gZWxzZSBpZiAoJzAnLnNwbGl0KHVuZGVmaW5lZCwgMCkubGVuZ3RoKSB7XG4gICAgICBpbnRlcm5hbFNwbGl0ID0gZnVuY3Rpb24gKHNlcGFyYXRvciwgbGltaXQpIHtcbiAgICAgICAgcmV0dXJuIHNlcGFyYXRvciA9PT0gdW5kZWZpbmVkICYmIGxpbWl0ID09PSAwID8gW10gOiBuYXRpdmVTcGxpdC5jYWxsKHRoaXMsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgfTtcbiAgICB9IGVsc2UgaW50ZXJuYWxTcGxpdCA9IG5hdGl2ZVNwbGl0O1xuXG4gICAgcmV0dXJuIFtcbiAgICAgIC8vIGBTdHJpbmcucHJvdG90eXBlLnNwbGl0YCBtZXRob2RcbiAgICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtc3RyaW5nLnByb3RvdHlwZS5zcGxpdFxuICAgICAgZnVuY3Rpb24gc3BsaXQoc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICB2YXIgTyA9IHJlcXVpcmVPYmplY3RDb2VyY2libGUodGhpcyk7XG4gICAgICAgIHZhciBzcGxpdHRlciA9IHNlcGFyYXRvciA9PSB1bmRlZmluZWQgPyB1bmRlZmluZWQgOiBzZXBhcmF0b3JbU1BMSVRdO1xuICAgICAgICByZXR1cm4gc3BsaXR0ZXIgIT09IHVuZGVmaW5lZFxuICAgICAgICAgID8gc3BsaXR0ZXIuY2FsbChzZXBhcmF0b3IsIE8sIGxpbWl0KVxuICAgICAgICAgIDogaW50ZXJuYWxTcGxpdC5jYWxsKFN0cmluZyhPKSwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICB9LFxuICAgICAgLy8gYFJlZ0V4cC5wcm90b3R5cGVbQEBzcGxpdF1gIG1ldGhvZFxuICAgICAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1yZWdleHAucHJvdG90eXBlLUBAc3BsaXRcbiAgICAgIC8vXG4gICAgICAvLyBOT1RFOiBUaGlzIGNhbm5vdCBiZSBwcm9wZXJseSBwb2x5ZmlsbGVkIGluIGVuZ2luZXMgdGhhdCBkb24ndCBzdXBwb3J0XG4gICAgICAvLyB0aGUgJ3knIGZsYWcuXG4gICAgICBmdW5jdGlvbiAocmVnZXhwLCBsaW1pdCkge1xuICAgICAgICB2YXIgcmVzID0gbWF5YmVDYWxsTmF0aXZlKGludGVybmFsU3BsaXQsIHJlZ2V4cCwgdGhpcywgbGltaXQsIGludGVybmFsU3BsaXQgIT09IG5hdGl2ZVNwbGl0KTtcbiAgICAgICAgaWYgKHJlcy5kb25lKSByZXR1cm4gcmVzLnZhbHVlO1xuXG4gICAgICAgIHZhciByeCA9IGFuT2JqZWN0KHJlZ2V4cCk7XG4gICAgICAgIHZhciBTID0gU3RyaW5nKHRoaXMpO1xuICAgICAgICB2YXIgQyA9IHNwZWNpZXNDb25zdHJ1Y3RvcihyeCwgUmVnRXhwKTtcblxuICAgICAgICB2YXIgdW5pY29kZU1hdGNoaW5nID0gcngudW5pY29kZTtcbiAgICAgICAgdmFyIGZsYWdzID0gKHJ4Lmlnbm9yZUNhc2UgPyAnaScgOiAnJykgK1xuICAgICAgICAgICAgICAgICAgICAocngubXVsdGlsaW5lID8gJ20nIDogJycpICtcbiAgICAgICAgICAgICAgICAgICAgKHJ4LnVuaWNvZGUgPyAndScgOiAnJykgK1xuICAgICAgICAgICAgICAgICAgICAoU1VQUE9SVFNfWSA/ICd5JyA6ICdnJyk7XG5cbiAgICAgICAgLy8gXig/ICsgcnggKyApIGlzIG5lZWRlZCwgaW4gY29tYmluYXRpb24gd2l0aCBzb21lIFMgc2xpY2luZywgdG9cbiAgICAgICAgLy8gc2ltdWxhdGUgdGhlICd5JyBmbGFnLlxuICAgICAgICB2YXIgc3BsaXR0ZXIgPSBuZXcgQyhTVVBQT1JUU19ZID8gcnggOiAnXig/OicgKyByeC5zb3VyY2UgKyAnKScsIGZsYWdzKTtcbiAgICAgICAgdmFyIGxpbSA9IGxpbWl0ID09PSB1bmRlZmluZWQgPyBNQVhfVUlOVDMyIDogbGltaXQgPj4+IDA7XG4gICAgICAgIGlmIChsaW0gPT09IDApIHJldHVybiBbXTtcbiAgICAgICAgaWYgKFMubGVuZ3RoID09PSAwKSByZXR1cm4gcmVnZXhwRXhlY0Fic3RyYWN0KHNwbGl0dGVyLCBTKSA9PT0gbnVsbCA/IFtTXSA6IFtdO1xuICAgICAgICB2YXIgcCA9IDA7XG4gICAgICAgIHZhciBxID0gMDtcbiAgICAgICAgdmFyIEEgPSBbXTtcbiAgICAgICAgd2hpbGUgKHEgPCBTLmxlbmd0aCkge1xuICAgICAgICAgIHNwbGl0dGVyLmxhc3RJbmRleCA9IFNVUFBPUlRTX1kgPyBxIDogMDtcbiAgICAgICAgICB2YXIgeiA9IHJlZ2V4cEV4ZWNBYnN0cmFjdChzcGxpdHRlciwgU1VQUE9SVFNfWSA/IFMgOiBTLnNsaWNlKHEpKTtcbiAgICAgICAgICB2YXIgZTtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICB6ID09PSBudWxsIHx8XG4gICAgICAgICAgICAoZSA9IG1pbiQ0KHRvTGVuZ3RoKHNwbGl0dGVyLmxhc3RJbmRleCArIChTVVBQT1JUU19ZID8gMCA6IHEpKSwgUy5sZW5ndGgpKSA9PT0gcFxuICAgICAgICAgICkge1xuICAgICAgICAgICAgcSA9IGFkdmFuY2VTdHJpbmdJbmRleChTLCBxLCB1bmljb2RlTWF0Y2hpbmcpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBBLnB1c2goUy5zbGljZShwLCBxKSk7XG4gICAgICAgICAgICBpZiAoQS5sZW5ndGggPT09IGxpbSkgcmV0dXJuIEE7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8PSB6Lmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgICAgICAgICBBLnB1c2goeltpXSk7XG4gICAgICAgICAgICAgIGlmIChBLmxlbmd0aCA9PT0gbGltKSByZXR1cm4gQTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHEgPSBwID0gZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgQS5wdXNoKFMuc2xpY2UocCkpO1xuICAgICAgICByZXR1cm4gQTtcbiAgICAgIH1cbiAgICBdO1xuICB9LCAhU1VQUE9SVFNfWSk7XG5cbiAgLy8gYE9iamVjdC5rZXlzYCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1vYmplY3Qua2V5c1xuICB2YXIgb2JqZWN0S2V5cyA9IE9iamVjdC5rZXlzIHx8IGZ1bmN0aW9uIGtleXMoTykge1xuICAgIHJldHVybiBvYmplY3RLZXlzSW50ZXJuYWwoTywgZW51bUJ1Z0tleXMpO1xuICB9O1xuXG4gIC8vIGBPYmplY3QuZGVmaW5lUHJvcGVydGllc2AgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtb2JqZWN0LmRlZmluZXByb3BlcnRpZXNcbiAgdmFyIG9iamVjdERlZmluZVByb3BlcnRpZXMgPSBkZXNjcmlwdG9ycyA/IE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzIDogZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyhPLCBQcm9wZXJ0aWVzKSB7XG4gICAgYW5PYmplY3QoTyk7XG4gICAgdmFyIGtleXMgPSBvYmplY3RLZXlzKFByb3BlcnRpZXMpO1xuICAgIHZhciBsZW5ndGggPSBrZXlzLmxlbmd0aDtcbiAgICB2YXIgaW5kZXggPSAwO1xuICAgIHZhciBrZXk7XG4gICAgd2hpbGUgKGxlbmd0aCA+IGluZGV4KSBvYmplY3REZWZpbmVQcm9wZXJ0eS5mKE8sIGtleSA9IGtleXNbaW5kZXgrK10sIFByb3BlcnRpZXNba2V5XSk7XG4gICAgcmV0dXJuIE87XG4gIH07XG5cbiAgdmFyIGh0bWwgPSBnZXRCdWlsdEluKCdkb2N1bWVudCcsICdkb2N1bWVudEVsZW1lbnQnKTtcblxuICB2YXIgR1QgPSAnPic7XG4gIHZhciBMVCA9ICc8JztcbiAgdmFyIFBST1RPVFlQRSA9ICdwcm90b3R5cGUnO1xuICB2YXIgU0NSSVBUID0gJ3NjcmlwdCc7XG4gIHZhciBJRV9QUk9UTyQxID0gc2hhcmVkS2V5KCdJRV9QUk9UTycpO1xuXG4gIHZhciBFbXB0eUNvbnN0cnVjdG9yID0gZnVuY3Rpb24gKCkgeyAvKiBlbXB0eSAqLyB9O1xuXG4gIHZhciBzY3JpcHRUYWcgPSBmdW5jdGlvbiAoY29udGVudCkge1xuICAgIHJldHVybiBMVCArIFNDUklQVCArIEdUICsgY29udGVudCArIExUICsgJy8nICsgU0NSSVBUICsgR1Q7XG4gIH07XG5cbiAgLy8gQ3JlYXRlIG9iamVjdCB3aXRoIGZha2UgYG51bGxgIHByb3RvdHlwZTogdXNlIEFjdGl2ZVggT2JqZWN0IHdpdGggY2xlYXJlZCBwcm90b3R5cGVcbiAgdmFyIE51bGxQcm90b09iamVjdFZpYUFjdGl2ZVggPSBmdW5jdGlvbiAoYWN0aXZlWERvY3VtZW50KSB7XG4gICAgYWN0aXZlWERvY3VtZW50LndyaXRlKHNjcmlwdFRhZygnJykpO1xuICAgIGFjdGl2ZVhEb2N1bWVudC5jbG9zZSgpO1xuICAgIHZhciB0ZW1wID0gYWN0aXZlWERvY3VtZW50LnBhcmVudFdpbmRvdy5PYmplY3Q7XG4gICAgYWN0aXZlWERvY3VtZW50ID0gbnVsbDsgLy8gYXZvaWQgbWVtb3J5IGxlYWtcbiAgICByZXR1cm4gdGVtcDtcbiAgfTtcblxuICAvLyBDcmVhdGUgb2JqZWN0IHdpdGggZmFrZSBgbnVsbGAgcHJvdG90eXBlOiB1c2UgaWZyYW1lIE9iamVjdCB3aXRoIGNsZWFyZWQgcHJvdG90eXBlXG4gIHZhciBOdWxsUHJvdG9PYmplY3RWaWFJRnJhbWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgLy8gVGhyYXNoLCB3YXN0ZSBhbmQgc29kb215OiBJRSBHQyBidWdcbiAgICB2YXIgaWZyYW1lID0gZG9jdW1lbnRDcmVhdGVFbGVtZW50KCdpZnJhbWUnKTtcbiAgICB2YXIgSlMgPSAnamF2YScgKyBTQ1JJUFQgKyAnOic7XG4gICAgdmFyIGlmcmFtZURvY3VtZW50O1xuICAgIGlmcmFtZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIGh0bWwuYXBwZW5kQ2hpbGQoaWZyYW1lKTtcbiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vemxvaXJvY2svY29yZS1qcy9pc3N1ZXMvNDc1XG4gICAgaWZyYW1lLnNyYyA9IFN0cmluZyhKUyk7XG4gICAgaWZyYW1lRG9jdW1lbnQgPSBpZnJhbWUuY29udGVudFdpbmRvdy5kb2N1bWVudDtcbiAgICBpZnJhbWVEb2N1bWVudC5vcGVuKCk7XG4gICAgaWZyYW1lRG9jdW1lbnQud3JpdGUoc2NyaXB0VGFnKCdkb2N1bWVudC5GPU9iamVjdCcpKTtcbiAgICBpZnJhbWVEb2N1bWVudC5jbG9zZSgpO1xuICAgIHJldHVybiBpZnJhbWVEb2N1bWVudC5GO1xuICB9O1xuXG4gIC8vIENoZWNrIGZvciBkb2N1bWVudC5kb21haW4gYW5kIGFjdGl2ZSB4IHN1cHBvcnRcbiAgLy8gTm8gbmVlZCB0byB1c2UgYWN0aXZlIHggYXBwcm9hY2ggd2hlbiBkb2N1bWVudC5kb21haW4gaXMgbm90IHNldFxuICAvLyBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2VzLXNoaW1zL2VzNS1zaGltL2lzc3Vlcy8xNTBcbiAgLy8gdmFyaWF0aW9uIG9mIGh0dHBzOi8vZ2l0aHViLmNvbS9raXRjYW1icmlkZ2UvZXM1LXNoaW0vY29tbWl0LzRmNzM4YWMwNjYzNDZcbiAgLy8gYXZvaWQgSUUgR0MgYnVnXG4gIHZhciBhY3RpdmVYRG9jdW1lbnQ7XG4gIHZhciBOdWxsUHJvdG9PYmplY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgdHJ5IHtcbiAgICAgIC8qIGdsb2JhbCBBY3RpdmVYT2JqZWN0IC0tIG9sZCBJRSAqL1xuICAgICAgYWN0aXZlWERvY3VtZW50ID0gZG9jdW1lbnQuZG9tYWluICYmIG5ldyBBY3RpdmVYT2JqZWN0KCdodG1sZmlsZScpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7IC8qIGlnbm9yZSAqLyB9XG4gICAgTnVsbFByb3RvT2JqZWN0ID0gYWN0aXZlWERvY3VtZW50ID8gTnVsbFByb3RvT2JqZWN0VmlhQWN0aXZlWChhY3RpdmVYRG9jdW1lbnQpIDogTnVsbFByb3RvT2JqZWN0VmlhSUZyYW1lKCk7XG4gICAgdmFyIGxlbmd0aCA9IGVudW1CdWdLZXlzLmxlbmd0aDtcbiAgICB3aGlsZSAobGVuZ3RoLS0pIGRlbGV0ZSBOdWxsUHJvdG9PYmplY3RbUFJPVE9UWVBFXVtlbnVtQnVnS2V5c1tsZW5ndGhdXTtcbiAgICByZXR1cm4gTnVsbFByb3RvT2JqZWN0KCk7XG4gIH07XG5cbiAgaGlkZGVuS2V5cyQxW0lFX1BST1RPJDFdID0gdHJ1ZTtcblxuICAvLyBgT2JqZWN0LmNyZWF0ZWAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtb2JqZWN0LmNyZWF0ZVxuICB2YXIgb2JqZWN0Q3JlYXRlID0gT2JqZWN0LmNyZWF0ZSB8fCBmdW5jdGlvbiBjcmVhdGUoTywgUHJvcGVydGllcykge1xuICAgIHZhciByZXN1bHQ7XG4gICAgaWYgKE8gIT09IG51bGwpIHtcbiAgICAgIEVtcHR5Q29uc3RydWN0b3JbUFJPVE9UWVBFXSA9IGFuT2JqZWN0KE8pO1xuICAgICAgcmVzdWx0ID0gbmV3IEVtcHR5Q29uc3RydWN0b3IoKTtcbiAgICAgIEVtcHR5Q29uc3RydWN0b3JbUFJPVE9UWVBFXSA9IG51bGw7XG4gICAgICAvLyBhZGQgXCJfX3Byb3RvX19cIiBmb3IgT2JqZWN0LmdldFByb3RvdHlwZU9mIHBvbHlmaWxsXG4gICAgICByZXN1bHRbSUVfUFJPVE8kMV0gPSBPO1xuICAgIH0gZWxzZSByZXN1bHQgPSBOdWxsUHJvdG9PYmplY3QoKTtcbiAgICByZXR1cm4gUHJvcGVydGllcyA9PT0gdW5kZWZpbmVkID8gcmVzdWx0IDogb2JqZWN0RGVmaW5lUHJvcGVydGllcyhyZXN1bHQsIFByb3BlcnRpZXMpO1xuICB9O1xuXG4gIHZhciBVTlNDT1BBQkxFUyA9IHdlbGxLbm93blN5bWJvbCgndW5zY29wYWJsZXMnKTtcbiAgdmFyIEFycmF5UHJvdG90eXBlID0gQXJyYXkucHJvdG90eXBlO1xuXG4gIC8vIEFycmF5LnByb3RvdHlwZVtAQHVuc2NvcGFibGVzXVxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS1AQHVuc2NvcGFibGVzXG4gIGlmIChBcnJheVByb3RvdHlwZVtVTlNDT1BBQkxFU10gPT0gdW5kZWZpbmVkKSB7XG4gICAgb2JqZWN0RGVmaW5lUHJvcGVydHkuZihBcnJheVByb3RvdHlwZSwgVU5TQ09QQUJMRVMsIHtcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgIHZhbHVlOiBvYmplY3RDcmVhdGUobnVsbClcbiAgICB9KTtcbiAgfVxuXG4gIC8vIGFkZCBhIGtleSB0byBBcnJheS5wcm90b3R5cGVbQEB1bnNjb3BhYmxlc11cbiAgdmFyIGFkZFRvVW5zY29wYWJsZXMgPSBmdW5jdGlvbiAoa2V5KSB7XG4gICAgQXJyYXlQcm90b3R5cGVbVU5TQ09QQUJMRVNdW2tleV0gPSB0cnVlO1xuICB9O1xuXG4gIHZhciAkaW5jbHVkZXMgPSBhcnJheUluY2x1ZGVzLmluY2x1ZGVzO1xuXG5cbiAgLy8gYEFycmF5LnByb3RvdHlwZS5pbmNsdWRlc2AgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLmluY2x1ZGVzXG4gIF9leHBvcnQoeyB0YXJnZXQ6ICdBcnJheScsIHByb3RvOiB0cnVlIH0sIHtcbiAgICBpbmNsdWRlczogZnVuY3Rpb24gaW5jbHVkZXMoZWwgLyogLCBmcm9tSW5kZXggPSAwICovKSB7XG4gICAgICByZXR1cm4gJGluY2x1ZGVzKHRoaXMsIGVsLCBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCk7XG4gICAgfVxuICB9KTtcblxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS1AQHVuc2NvcGFibGVzXG4gIGFkZFRvVW5zY29wYWJsZXMoJ2luY2x1ZGVzJyk7XG5cbiAgLy8gYElzQXJyYXlgIGFic3RyYWN0IG9wZXJhdGlvblxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWlzYXJyYXlcbiAgdmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5IHx8IGZ1bmN0aW9uIGlzQXJyYXkoYXJnKSB7XG4gICAgcmV0dXJuIGNsYXNzb2ZSYXcoYXJnKSA9PSAnQXJyYXknO1xuICB9O1xuXG4gIC8vIGBUb09iamVjdGAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtdG9vYmplY3RcbiAgdmFyIHRvT2JqZWN0ID0gZnVuY3Rpb24gKGFyZ3VtZW50KSB7XG4gICAgcmV0dXJuIE9iamVjdChyZXF1aXJlT2JqZWN0Q29lcmNpYmxlKGFyZ3VtZW50KSk7XG4gIH07XG5cbiAgdmFyIGNyZWF0ZVByb3BlcnR5ID0gZnVuY3Rpb24gKG9iamVjdCwga2V5LCB2YWx1ZSkge1xuICAgIHZhciBwcm9wZXJ0eUtleSA9IHRvUHJpbWl0aXZlKGtleSk7XG4gICAgaWYgKHByb3BlcnR5S2V5IGluIG9iamVjdCkgb2JqZWN0RGVmaW5lUHJvcGVydHkuZihvYmplY3QsIHByb3BlcnR5S2V5LCBjcmVhdGVQcm9wZXJ0eURlc2NyaXB0b3IoMCwgdmFsdWUpKTtcbiAgICBlbHNlIG9iamVjdFtwcm9wZXJ0eUtleV0gPSB2YWx1ZTtcbiAgfTtcblxuICB2YXIgU1BFQ0lFUyQzID0gd2VsbEtub3duU3ltYm9sKCdzcGVjaWVzJyk7XG5cbiAgLy8gYEFycmF5U3BlY2llc0NyZWF0ZWAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXlzcGVjaWVzY3JlYXRlXG4gIHZhciBhcnJheVNwZWNpZXNDcmVhdGUgPSBmdW5jdGlvbiAob3JpZ2luYWxBcnJheSwgbGVuZ3RoKSB7XG4gICAgdmFyIEM7XG4gICAgaWYgKGlzQXJyYXkob3JpZ2luYWxBcnJheSkpIHtcbiAgICAgIEMgPSBvcmlnaW5hbEFycmF5LmNvbnN0cnVjdG9yO1xuICAgICAgLy8gY3Jvc3MtcmVhbG0gZmFsbGJhY2tcbiAgICAgIGlmICh0eXBlb2YgQyA9PSAnZnVuY3Rpb24nICYmIChDID09PSBBcnJheSB8fCBpc0FycmF5KEMucHJvdG90eXBlKSkpIEMgPSB1bmRlZmluZWQ7XG4gICAgICBlbHNlIGlmIChpc09iamVjdChDKSkge1xuICAgICAgICBDID0gQ1tTUEVDSUVTJDNdO1xuICAgICAgICBpZiAoQyA9PT0gbnVsbCkgQyA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICB9IHJldHVybiBuZXcgKEMgPT09IHVuZGVmaW5lZCA/IEFycmF5IDogQykobGVuZ3RoID09PSAwID8gMCA6IGxlbmd0aCk7XG4gIH07XG5cbiAgdmFyIFNQRUNJRVMkMiA9IHdlbGxLbm93blN5bWJvbCgnc3BlY2llcycpO1xuXG4gIHZhciBhcnJheU1ldGhvZEhhc1NwZWNpZXNTdXBwb3J0ID0gZnVuY3Rpb24gKE1FVEhPRF9OQU1FKSB7XG4gICAgLy8gV2UgY2FuJ3QgdXNlIHRoaXMgZmVhdHVyZSBkZXRlY3Rpb24gaW4gVjggc2luY2UgaXQgY2F1c2VzXG4gICAgLy8gZGVvcHRpbWl6YXRpb24gYW5kIHNlcmlvdXMgcGVyZm9ybWFuY2UgZGVncmFkYXRpb25cbiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vemxvaXJvY2svY29yZS1qcy9pc3N1ZXMvNjc3XG4gICAgcmV0dXJuIGVuZ2luZVY4VmVyc2lvbiA+PSA1MSB8fCAhZmFpbHMoZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIGFycmF5ID0gW107XG4gICAgICB2YXIgY29uc3RydWN0b3IgPSBhcnJheS5jb25zdHJ1Y3RvciA9IHt9O1xuICAgICAgY29uc3RydWN0b3JbU1BFQ0lFUyQyXSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHsgZm9vOiAxIH07XG4gICAgICB9O1xuICAgICAgcmV0dXJuIGFycmF5W01FVEhPRF9OQU1FXShCb29sZWFuKS5mb28gIT09IDE7XG4gICAgfSk7XG4gIH07XG5cbiAgdmFyIElTX0NPTkNBVF9TUFJFQURBQkxFID0gd2VsbEtub3duU3ltYm9sKCdpc0NvbmNhdFNwcmVhZGFibGUnKTtcbiAgdmFyIE1BWF9TQUZFX0lOVEVHRVIkMSA9IDB4MUZGRkZGRkZGRkZGRkY7XG4gIHZhciBNQVhJTVVNX0FMTE9XRURfSU5ERVhfRVhDRUVERUQgPSAnTWF4aW11bSBhbGxvd2VkIGluZGV4IGV4Y2VlZGVkJztcblxuICAvLyBXZSBjYW4ndCB1c2UgdGhpcyBmZWF0dXJlIGRldGVjdGlvbiBpbiBWOCBzaW5jZSBpdCBjYXVzZXNcbiAgLy8gZGVvcHRpbWl6YXRpb24gYW5kIHNlcmlvdXMgcGVyZm9ybWFuY2UgZGVncmFkYXRpb25cbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMvaXNzdWVzLzY3OVxuICB2YXIgSVNfQ09OQ0FUX1NQUkVBREFCTEVfU1VQUE9SVCA9IGVuZ2luZVY4VmVyc2lvbiA+PSA1MSB8fCAhZmFpbHMoZnVuY3Rpb24gKCkge1xuICAgIHZhciBhcnJheSA9IFtdO1xuICAgIGFycmF5W0lTX0NPTkNBVF9TUFJFQURBQkxFXSA9IGZhbHNlO1xuICAgIHJldHVybiBhcnJheS5jb25jYXQoKVswXSAhPT0gYXJyYXk7XG4gIH0pO1xuXG4gIHZhciBTUEVDSUVTX1NVUFBPUlQgPSBhcnJheU1ldGhvZEhhc1NwZWNpZXNTdXBwb3J0KCdjb25jYXQnKTtcblxuICB2YXIgaXNDb25jYXRTcHJlYWRhYmxlID0gZnVuY3Rpb24gKE8pIHtcbiAgICBpZiAoIWlzT2JqZWN0KE8pKSByZXR1cm4gZmFsc2U7XG4gICAgdmFyIHNwcmVhZGFibGUgPSBPW0lTX0NPTkNBVF9TUFJFQURBQkxFXTtcbiAgICByZXR1cm4gc3ByZWFkYWJsZSAhPT0gdW5kZWZpbmVkID8gISFzcHJlYWRhYmxlIDogaXNBcnJheShPKTtcbiAgfTtcblxuICB2YXIgRk9SQ0VEJDQgPSAhSVNfQ09OQ0FUX1NQUkVBREFCTEVfU1VQUE9SVCB8fCAhU1BFQ0lFU19TVVBQT1JUO1xuXG4gIC8vIGBBcnJheS5wcm90b3R5cGUuY29uY2F0YCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUuY29uY2F0XG4gIC8vIHdpdGggYWRkaW5nIHN1cHBvcnQgb2YgQEBpc0NvbmNhdFNwcmVhZGFibGUgYW5kIEBAc3BlY2llc1xuICBfZXhwb3J0KHsgdGFyZ2V0OiAnQXJyYXknLCBwcm90bzogdHJ1ZSwgZm9yY2VkOiBGT1JDRUQkNCB9LCB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVudXNlZC12YXJzIC0tIHJlcXVpcmVkIGZvciBgLmxlbmd0aGBcbiAgICBjb25jYXQ6IGZ1bmN0aW9uIGNvbmNhdChhcmcpIHtcbiAgICAgIHZhciBPID0gdG9PYmplY3QodGhpcyk7XG4gICAgICB2YXIgQSA9IGFycmF5U3BlY2llc0NyZWF0ZShPLCAwKTtcbiAgICAgIHZhciBuID0gMDtcbiAgICAgIHZhciBpLCBrLCBsZW5ndGgsIGxlbiwgRTtcbiAgICAgIGZvciAoaSA9IC0xLCBsZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgRSA9IGkgPT09IC0xID8gTyA6IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgaWYgKGlzQ29uY2F0U3ByZWFkYWJsZShFKSkge1xuICAgICAgICAgIGxlbiA9IHRvTGVuZ3RoKEUubGVuZ3RoKTtcbiAgICAgICAgICBpZiAobiArIGxlbiA+IE1BWF9TQUZFX0lOVEVHRVIkMSkgdGhyb3cgVHlwZUVycm9yKE1BWElNVU1fQUxMT1dFRF9JTkRFWF9FWENFRURFRCk7XG4gICAgICAgICAgZm9yIChrID0gMDsgayA8IGxlbjsgaysrLCBuKyspIGlmIChrIGluIEUpIGNyZWF0ZVByb3BlcnR5KEEsIG4sIEVba10pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmIChuID49IE1BWF9TQUZFX0lOVEVHRVIkMSkgdGhyb3cgVHlwZUVycm9yKE1BWElNVU1fQUxMT1dFRF9JTkRFWF9FWENFRURFRCk7XG4gICAgICAgICAgY3JlYXRlUHJvcGVydHkoQSwgbisrLCBFKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgQS5sZW5ndGggPSBuO1xuICAgICAgcmV0dXJuIEE7XG4gICAgfVxuICB9KTtcblxuICAvLyBvcHRpb25hbCAvIHNpbXBsZSBjb250ZXh0IGJpbmRpbmdcbiAgdmFyIGZ1bmN0aW9uQmluZENvbnRleHQgPSBmdW5jdGlvbiAoZm4sIHRoYXQsIGxlbmd0aCkge1xuICAgIGFGdW5jdGlvbihmbik7XG4gICAgaWYgKHRoYXQgPT09IHVuZGVmaW5lZCkgcmV0dXJuIGZuO1xuICAgIHN3aXRjaCAobGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6IHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBmbi5jYWxsKHRoYXQpO1xuICAgICAgfTtcbiAgICAgIGNhc2UgMTogcmV0dXJuIGZ1bmN0aW9uIChhKSB7XG4gICAgICAgIHJldHVybiBmbi5jYWxsKHRoYXQsIGEpO1xuICAgICAgfTtcbiAgICAgIGNhc2UgMjogcmV0dXJuIGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgIHJldHVybiBmbi5jYWxsKHRoYXQsIGEsIGIpO1xuICAgICAgfTtcbiAgICAgIGNhc2UgMzogcmV0dXJuIGZ1bmN0aW9uIChhLCBiLCBjKSB7XG4gICAgICAgIHJldHVybiBmbi5jYWxsKHRoYXQsIGEsIGIsIGMpO1xuICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgvKiAuLi5hcmdzICovKSB7XG4gICAgICByZXR1cm4gZm4uYXBwbHkodGhhdCwgYXJndW1lbnRzKTtcbiAgICB9O1xuICB9O1xuXG4gIHZhciBwdXNoID0gW10ucHVzaDtcblxuICAvLyBgQXJyYXkucHJvdG90eXBlLnsgZm9yRWFjaCwgbWFwLCBmaWx0ZXIsIHNvbWUsIGV2ZXJ5LCBmaW5kLCBmaW5kSW5kZXgsIGZpbHRlck91dCB9YCBtZXRob2RzIGltcGxlbWVudGF0aW9uXG4gIHZhciBjcmVhdGVNZXRob2QkMSA9IGZ1bmN0aW9uIChUWVBFKSB7XG4gICAgdmFyIElTX01BUCA9IFRZUEUgPT0gMTtcbiAgICB2YXIgSVNfRklMVEVSID0gVFlQRSA9PSAyO1xuICAgIHZhciBJU19TT01FID0gVFlQRSA9PSAzO1xuICAgIHZhciBJU19FVkVSWSA9IFRZUEUgPT0gNDtcbiAgICB2YXIgSVNfRklORF9JTkRFWCA9IFRZUEUgPT0gNjtcbiAgICB2YXIgSVNfRklMVEVSX09VVCA9IFRZUEUgPT0gNztcbiAgICB2YXIgTk9fSE9MRVMgPSBUWVBFID09IDUgfHwgSVNfRklORF9JTkRFWDtcbiAgICByZXR1cm4gZnVuY3Rpb24gKCR0aGlzLCBjYWxsYmFja2ZuLCB0aGF0LCBzcGVjaWZpY0NyZWF0ZSkge1xuICAgICAgdmFyIE8gPSB0b09iamVjdCgkdGhpcyk7XG4gICAgICB2YXIgc2VsZiA9IGluZGV4ZWRPYmplY3QoTyk7XG4gICAgICB2YXIgYm91bmRGdW5jdGlvbiA9IGZ1bmN0aW9uQmluZENvbnRleHQoY2FsbGJhY2tmbiwgdGhhdCwgMyk7XG4gICAgICB2YXIgbGVuZ3RoID0gdG9MZW5ndGgoc2VsZi5sZW5ndGgpO1xuICAgICAgdmFyIGluZGV4ID0gMDtcbiAgICAgIHZhciBjcmVhdGUgPSBzcGVjaWZpY0NyZWF0ZSB8fCBhcnJheVNwZWNpZXNDcmVhdGU7XG4gICAgICB2YXIgdGFyZ2V0ID0gSVNfTUFQID8gY3JlYXRlKCR0aGlzLCBsZW5ndGgpIDogSVNfRklMVEVSIHx8IElTX0ZJTFRFUl9PVVQgPyBjcmVhdGUoJHRoaXMsIDApIDogdW5kZWZpbmVkO1xuICAgICAgdmFyIHZhbHVlLCByZXN1bHQ7XG4gICAgICBmb3IgKDtsZW5ndGggPiBpbmRleDsgaW5kZXgrKykgaWYgKE5PX0hPTEVTIHx8IGluZGV4IGluIHNlbGYpIHtcbiAgICAgICAgdmFsdWUgPSBzZWxmW2luZGV4XTtcbiAgICAgICAgcmVzdWx0ID0gYm91bmRGdW5jdGlvbih2YWx1ZSwgaW5kZXgsIE8pO1xuICAgICAgICBpZiAoVFlQRSkge1xuICAgICAgICAgIGlmIChJU19NQVApIHRhcmdldFtpbmRleF0gPSByZXN1bHQ7IC8vIG1hcFxuICAgICAgICAgIGVsc2UgaWYgKHJlc3VsdCkgc3dpdGNoIChUWVBFKSB7XG4gICAgICAgICAgICBjYXNlIDM6IHJldHVybiB0cnVlOyAgICAgICAgICAgICAgLy8gc29tZVxuICAgICAgICAgICAgY2FzZSA1OiByZXR1cm4gdmFsdWU7ICAgICAgICAgICAgIC8vIGZpbmRcbiAgICAgICAgICAgIGNhc2UgNjogcmV0dXJuIGluZGV4OyAgICAgICAgICAgICAvLyBmaW5kSW5kZXhcbiAgICAgICAgICAgIGNhc2UgMjogcHVzaC5jYWxsKHRhcmdldCwgdmFsdWUpOyAvLyBmaWx0ZXJcbiAgICAgICAgICB9IGVsc2Ugc3dpdGNoIChUWVBFKSB7XG4gICAgICAgICAgICBjYXNlIDQ6IHJldHVybiBmYWxzZTsgICAgICAgICAgICAgLy8gZXZlcnlcbiAgICAgICAgICAgIGNhc2UgNzogcHVzaC5jYWxsKHRhcmdldCwgdmFsdWUpOyAvLyBmaWx0ZXJPdXRcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBJU19GSU5EX0lOREVYID8gLTEgOiBJU19TT01FIHx8IElTX0VWRVJZID8gSVNfRVZFUlkgOiB0YXJnZXQ7XG4gICAgfTtcbiAgfTtcblxuICB2YXIgYXJyYXlJdGVyYXRpb24gPSB7XG4gICAgLy8gYEFycmF5LnByb3RvdHlwZS5mb3JFYWNoYCBtZXRob2RcbiAgICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS5mb3JlYWNoXG4gICAgZm9yRWFjaDogY3JlYXRlTWV0aG9kJDEoMCksXG4gICAgLy8gYEFycmF5LnByb3RvdHlwZS5tYXBgIG1ldGhvZFxuICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLm1hcFxuICAgIG1hcDogY3JlYXRlTWV0aG9kJDEoMSksXG4gICAgLy8gYEFycmF5LnByb3RvdHlwZS5maWx0ZXJgIG1ldGhvZFxuICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLmZpbHRlclxuICAgIGZpbHRlcjogY3JlYXRlTWV0aG9kJDEoMiksXG4gICAgLy8gYEFycmF5LnByb3RvdHlwZS5zb21lYCBtZXRob2RcbiAgICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS5zb21lXG4gICAgc29tZTogY3JlYXRlTWV0aG9kJDEoMyksXG4gICAgLy8gYEFycmF5LnByb3RvdHlwZS5ldmVyeWAgbWV0aG9kXG4gICAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUuZXZlcnlcbiAgICBldmVyeTogY3JlYXRlTWV0aG9kJDEoNCksXG4gICAgLy8gYEFycmF5LnByb3RvdHlwZS5maW5kYCBtZXRob2RcbiAgICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS5maW5kXG4gICAgZmluZDogY3JlYXRlTWV0aG9kJDEoNSksXG4gICAgLy8gYEFycmF5LnByb3RvdHlwZS5maW5kSW5kZXhgIG1ldGhvZFxuICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLmZpbmRJbmRleFxuICAgIGZpbmRJbmRleDogY3JlYXRlTWV0aG9kJDEoNiksXG4gICAgLy8gYEFycmF5LnByb3RvdHlwZS5maWx0ZXJPdXRgIG1ldGhvZFxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS90YzM5L3Byb3Bvc2FsLWFycmF5LWZpbHRlcmluZ1xuICAgIGZpbHRlck91dDogY3JlYXRlTWV0aG9kJDEoNylcbiAgfTtcblxuICB2YXIgJGZpbmQgPSBhcnJheUl0ZXJhdGlvbi5maW5kO1xuXG5cbiAgdmFyIEZJTkQgPSAnZmluZCc7XG4gIHZhciBTS0lQU19IT0xFUyQxID0gdHJ1ZTtcblxuICAvLyBTaG91bGRuJ3Qgc2tpcCBob2xlc1xuICBpZiAoRklORCBpbiBbXSkgQXJyYXkoMSlbRklORF0oZnVuY3Rpb24gKCkgeyBTS0lQU19IT0xFUyQxID0gZmFsc2U7IH0pO1xuXG4gIC8vIGBBcnJheS5wcm90b3R5cGUuZmluZGAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLmZpbmRcbiAgX2V4cG9ydCh7IHRhcmdldDogJ0FycmF5JywgcHJvdG86IHRydWUsIGZvcmNlZDogU0tJUFNfSE9MRVMkMSB9LCB7XG4gICAgZmluZDogZnVuY3Rpb24gZmluZChjYWxsYmFja2ZuIC8qICwgdGhhdCA9IHVuZGVmaW5lZCAqLykge1xuICAgICAgcmV0dXJuICRmaW5kKHRoaXMsIGNhbGxiYWNrZm4sIGFyZ3VtZW50cy5sZW5ndGggPiAxID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkKTtcbiAgICB9XG4gIH0pO1xuXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLUBAdW5zY29wYWJsZXNcbiAgYWRkVG9VbnNjb3BhYmxlcyhGSU5EKTtcblxuICB2YXIgbm90QVJlZ2V4cCA9IGZ1bmN0aW9uIChpdCkge1xuICAgIGlmIChpc1JlZ2V4cChpdCkpIHtcbiAgICAgIHRocm93IFR5cGVFcnJvcihcIlRoZSBtZXRob2QgZG9lc24ndCBhY2NlcHQgcmVndWxhciBleHByZXNzaW9uc1wiKTtcbiAgICB9IHJldHVybiBpdDtcbiAgfTtcblxuICB2YXIgTUFUQ0gkMSA9IHdlbGxLbm93blN5bWJvbCgnbWF0Y2gnKTtcblxuICB2YXIgY29ycmVjdElzUmVnZXhwTG9naWMgPSBmdW5jdGlvbiAoTUVUSE9EX05BTUUpIHtcbiAgICB2YXIgcmVnZXhwID0gLy4vO1xuICAgIHRyeSB7XG4gICAgICAnLy4vJ1tNRVRIT0RfTkFNRV0ocmVnZXhwKTtcbiAgICB9IGNhdGNoIChlcnJvcjEpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJlZ2V4cFtNQVRDSCQxXSA9IGZhbHNlO1xuICAgICAgICByZXR1cm4gJy8uLydbTUVUSE9EX05BTUVdKHJlZ2V4cCk7XG4gICAgICB9IGNhdGNoIChlcnJvcjIpIHsgLyogZW1wdHkgKi8gfVxuICAgIH0gcmV0dXJuIGZhbHNlO1xuICB9O1xuXG4gIC8vIGBTdHJpbmcucHJvdG90eXBlLmluY2x1ZGVzYCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1zdHJpbmcucHJvdG90eXBlLmluY2x1ZGVzXG4gIF9leHBvcnQoeyB0YXJnZXQ6ICdTdHJpbmcnLCBwcm90bzogdHJ1ZSwgZm9yY2VkOiAhY29ycmVjdElzUmVnZXhwTG9naWMoJ2luY2x1ZGVzJykgfSwge1xuICAgIGluY2x1ZGVzOiBmdW5jdGlvbiBpbmNsdWRlcyhzZWFyY2hTdHJpbmcgLyogLCBwb3NpdGlvbiA9IDAgKi8pIHtcbiAgICAgIHJldHVybiAhIX5TdHJpbmcocmVxdWlyZU9iamVjdENvZXJjaWJsZSh0aGlzKSlcbiAgICAgICAgLmluZGV4T2Yobm90QVJlZ2V4cChzZWFyY2hTdHJpbmcpLCBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCk7XG4gICAgfVxuICB9KTtcblxuICAvLyBpdGVyYWJsZSBET00gY29sbGVjdGlvbnNcbiAgLy8gZmxhZyAtIGBpdGVyYWJsZWAgaW50ZXJmYWNlIC0gJ2VudHJpZXMnLCAna2V5cycsICd2YWx1ZXMnLCAnZm9yRWFjaCcgbWV0aG9kc1xuICB2YXIgZG9tSXRlcmFibGVzID0ge1xuICAgIENTU1J1bGVMaXN0OiAwLFxuICAgIENTU1N0eWxlRGVjbGFyYXRpb246IDAsXG4gICAgQ1NTVmFsdWVMaXN0OiAwLFxuICAgIENsaWVudFJlY3RMaXN0OiAwLFxuICAgIERPTVJlY3RMaXN0OiAwLFxuICAgIERPTVN0cmluZ0xpc3Q6IDAsXG4gICAgRE9NVG9rZW5MaXN0OiAxLFxuICAgIERhdGFUcmFuc2Zlckl0ZW1MaXN0OiAwLFxuICAgIEZpbGVMaXN0OiAwLFxuICAgIEhUTUxBbGxDb2xsZWN0aW9uOiAwLFxuICAgIEhUTUxDb2xsZWN0aW9uOiAwLFxuICAgIEhUTUxGb3JtRWxlbWVudDogMCxcbiAgICBIVE1MU2VsZWN0RWxlbWVudDogMCxcbiAgICBNZWRpYUxpc3Q6IDAsXG4gICAgTWltZVR5cGVBcnJheTogMCxcbiAgICBOYW1lZE5vZGVNYXA6IDAsXG4gICAgTm9kZUxpc3Q6IDEsXG4gICAgUGFpbnRSZXF1ZXN0TGlzdDogMCxcbiAgICBQbHVnaW46IDAsXG4gICAgUGx1Z2luQXJyYXk6IDAsXG4gICAgU1ZHTGVuZ3RoTGlzdDogMCxcbiAgICBTVkdOdW1iZXJMaXN0OiAwLFxuICAgIFNWR1BhdGhTZWdMaXN0OiAwLFxuICAgIFNWR1BvaW50TGlzdDogMCxcbiAgICBTVkdTdHJpbmdMaXN0OiAwLFxuICAgIFNWR1RyYW5zZm9ybUxpc3Q6IDAsXG4gICAgU291cmNlQnVmZmVyTGlzdDogMCxcbiAgICBTdHlsZVNoZWV0TGlzdDogMCxcbiAgICBUZXh0VHJhY2tDdWVMaXN0OiAwLFxuICAgIFRleHRUcmFja0xpc3Q6IDAsXG4gICAgVG91Y2hMaXN0OiAwXG4gIH07XG5cbiAgdmFyICRmb3JFYWNoID0gYXJyYXlJdGVyYXRpb24uZm9yRWFjaDtcblxuXG4gIHZhciBTVFJJQ1RfTUVUSE9EJDIgPSBhcnJheU1ldGhvZElzU3RyaWN0KCdmb3JFYWNoJyk7XG5cbiAgLy8gYEFycmF5LnByb3RvdHlwZS5mb3JFYWNoYCBtZXRob2QgaW1wbGVtZW50YXRpb25cbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUuZm9yZWFjaFxuICB2YXIgYXJyYXlGb3JFYWNoID0gIVNUUklDVF9NRVRIT0QkMiA/IGZ1bmN0aW9uIGZvckVhY2goY2FsbGJhY2tmbiAvKiAsIHRoaXNBcmcgKi8pIHtcbiAgICByZXR1cm4gJGZvckVhY2godGhpcywgY2FsbGJhY2tmbiwgYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQpO1xuICB9IDogW10uZm9yRWFjaDtcblxuICBmb3IgKHZhciBDT0xMRUNUSU9OX05BTUUkMSBpbiBkb21JdGVyYWJsZXMpIHtcbiAgICB2YXIgQ29sbGVjdGlvbiQxID0gZ2xvYmFsXzFbQ09MTEVDVElPTl9OQU1FJDFdO1xuICAgIHZhciBDb2xsZWN0aW9uUHJvdG90eXBlJDEgPSBDb2xsZWN0aW9uJDEgJiYgQ29sbGVjdGlvbiQxLnByb3RvdHlwZTtcbiAgICAvLyBzb21lIENocm9tZSB2ZXJzaW9ucyBoYXZlIG5vbi1jb25maWd1cmFibGUgbWV0aG9kcyBvbiBET01Ub2tlbkxpc3RcbiAgICBpZiAoQ29sbGVjdGlvblByb3RvdHlwZSQxICYmIENvbGxlY3Rpb25Qcm90b3R5cGUkMS5mb3JFYWNoICE9PSBhcnJheUZvckVhY2gpIHRyeSB7XG4gICAgICBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkoQ29sbGVjdGlvblByb3RvdHlwZSQxLCAnZm9yRWFjaCcsIGFycmF5Rm9yRWFjaCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIENvbGxlY3Rpb25Qcm90b3R5cGUkMS5mb3JFYWNoID0gYXJyYXlGb3JFYWNoO1xuICAgIH1cbiAgfVxuXG4gIHZhciB0cmltJDIgPSBzdHJpbmdUcmltLnRyaW07XG5cblxuICB2YXIgJHBhcnNlRmxvYXQgPSBnbG9iYWxfMS5wYXJzZUZsb2F0O1xuICB2YXIgRk9SQ0VEJDMgPSAxIC8gJHBhcnNlRmxvYXQod2hpdGVzcGFjZXMgKyAnLTAnKSAhPT0gLUluZmluaXR5O1xuXG4gIC8vIGBwYXJzZUZsb2F0YCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1wYXJzZWZsb2F0LXN0cmluZ1xuICB2YXIgbnVtYmVyUGFyc2VGbG9hdCA9IEZPUkNFRCQzID8gZnVuY3Rpb24gcGFyc2VGbG9hdChzdHJpbmcpIHtcbiAgICB2YXIgdHJpbW1lZFN0cmluZyA9IHRyaW0kMihTdHJpbmcoc3RyaW5nKSk7XG4gICAgdmFyIHJlc3VsdCA9ICRwYXJzZUZsb2F0KHRyaW1tZWRTdHJpbmcpO1xuICAgIHJldHVybiByZXN1bHQgPT09IDAgJiYgdHJpbW1lZFN0cmluZy5jaGFyQXQoMCkgPT0gJy0nID8gLTAgOiByZXN1bHQ7XG4gIH0gOiAkcGFyc2VGbG9hdDtcblxuICAvLyBgcGFyc2VGbG9hdGAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtcGFyc2VmbG9hdC1zdHJpbmdcbiAgX2V4cG9ydCh7IGdsb2JhbDogdHJ1ZSwgZm9yY2VkOiBwYXJzZUZsb2F0ICE9IG51bWJlclBhcnNlRmxvYXQgfSwge1xuICAgIHBhcnNlRmxvYXQ6IG51bWJlclBhcnNlRmxvYXRcbiAgfSk7XG5cbiAgdmFyIHByb3BlcnR5SXNFbnVtZXJhYmxlID0gb2JqZWN0UHJvcGVydHlJc0VudW1lcmFibGUuZjtcblxuICAvLyBgT2JqZWN0LnsgZW50cmllcywgdmFsdWVzIH1gIG1ldGhvZHMgaW1wbGVtZW50YXRpb25cbiAgdmFyIGNyZWF0ZU1ldGhvZCA9IGZ1bmN0aW9uIChUT19FTlRSSUVTKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChpdCkge1xuICAgICAgdmFyIE8gPSB0b0luZGV4ZWRPYmplY3QoaXQpO1xuICAgICAgdmFyIGtleXMgPSBvYmplY3RLZXlzKE8pO1xuICAgICAgdmFyIGxlbmd0aCA9IGtleXMubGVuZ3RoO1xuICAgICAgdmFyIGkgPSAwO1xuICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgdmFyIGtleTtcbiAgICAgIHdoaWxlIChsZW5ndGggPiBpKSB7XG4gICAgICAgIGtleSA9IGtleXNbaSsrXTtcbiAgICAgICAgaWYgKCFkZXNjcmlwdG9ycyB8fCBwcm9wZXJ0eUlzRW51bWVyYWJsZS5jYWxsKE8sIGtleSkpIHtcbiAgICAgICAgICByZXN1bHQucHVzaChUT19FTlRSSUVTID8gW2tleSwgT1trZXldXSA6IE9ba2V5XSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgfTtcblxuICB2YXIgb2JqZWN0VG9BcnJheSA9IHtcbiAgICAvLyBgT2JqZWN0LmVudHJpZXNgIG1ldGhvZFxuICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtb2JqZWN0LmVudHJpZXNcbiAgICBlbnRyaWVzOiBjcmVhdGVNZXRob2QodHJ1ZSksXG4gICAgLy8gYE9iamVjdC52YWx1ZXNgIG1ldGhvZFxuICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtb2JqZWN0LnZhbHVlc1xuICAgIHZhbHVlczogY3JlYXRlTWV0aG9kKGZhbHNlKVxuICB9O1xuXG4gIHZhciAkZW50cmllcyA9IG9iamVjdFRvQXJyYXkuZW50cmllcztcblxuICAvLyBgT2JqZWN0LmVudHJpZXNgIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9iamVjdC5lbnRyaWVzXG4gIF9leHBvcnQoeyB0YXJnZXQ6ICdPYmplY3QnLCBzdGF0OiB0cnVlIH0sIHtcbiAgICBlbnRyaWVzOiBmdW5jdGlvbiBlbnRyaWVzKE8pIHtcbiAgICAgIHJldHVybiAkZW50cmllcyhPKTtcbiAgICB9XG4gIH0pO1xuXG4gIHZhciAkaW5kZXhPZiA9IGFycmF5SW5jbHVkZXMuaW5kZXhPZjtcblxuXG4gIHZhciBuYXRpdmVJbmRleE9mID0gW10uaW5kZXhPZjtcblxuICB2YXIgTkVHQVRJVkVfWkVSTyA9ICEhbmF0aXZlSW5kZXhPZiAmJiAxIC8gWzFdLmluZGV4T2YoMSwgLTApIDwgMDtcbiAgdmFyIFNUUklDVF9NRVRIT0QkMSA9IGFycmF5TWV0aG9kSXNTdHJpY3QoJ2luZGV4T2YnKTtcblxuICAvLyBgQXJyYXkucHJvdG90eXBlLmluZGV4T2ZgIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS5pbmRleG9mXG4gIF9leHBvcnQoeyB0YXJnZXQ6ICdBcnJheScsIHByb3RvOiB0cnVlLCBmb3JjZWQ6IE5FR0FUSVZFX1pFUk8gfHwgIVNUUklDVF9NRVRIT0QkMSB9LCB7XG4gICAgaW5kZXhPZjogZnVuY3Rpb24gaW5kZXhPZihzZWFyY2hFbGVtZW50IC8qICwgZnJvbUluZGV4ID0gMCAqLykge1xuICAgICAgcmV0dXJuIE5FR0FUSVZFX1pFUk9cbiAgICAgICAgLy8gY29udmVydCAtMCB0byArMFxuICAgICAgICA/IG5hdGl2ZUluZGV4T2YuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCAwXG4gICAgICAgIDogJGluZGV4T2YodGhpcywgc2VhcmNoRWxlbWVudCwgYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQpO1xuICAgIH1cbiAgfSk7XG5cbiAgdmFyIHRlc3QkMiA9IFtdO1xuICB2YXIgbmF0aXZlU29ydCA9IHRlc3QkMi5zb3J0O1xuXG4gIC8vIElFOC1cbiAgdmFyIEZBSUxTX09OX1VOREVGSU5FRCA9IGZhaWxzKGZ1bmN0aW9uICgpIHtcbiAgICB0ZXN0JDIuc29ydCh1bmRlZmluZWQpO1xuICB9KTtcbiAgLy8gVjggYnVnXG4gIHZhciBGQUlMU19PTl9OVUxMID0gZmFpbHMoZnVuY3Rpb24gKCkge1xuICAgIHRlc3QkMi5zb3J0KG51bGwpO1xuICB9KTtcbiAgLy8gT2xkIFdlYktpdFxuICB2YXIgU1RSSUNUX01FVEhPRCA9IGFycmF5TWV0aG9kSXNTdHJpY3QoJ3NvcnQnKTtcblxuICB2YXIgRk9SQ0VEJDIgPSBGQUlMU19PTl9VTkRFRklORUQgfHwgIUZBSUxTX09OX05VTEwgfHwgIVNUUklDVF9NRVRIT0Q7XG5cbiAgLy8gYEFycmF5LnByb3RvdHlwZS5zb3J0YCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUuc29ydFxuICBfZXhwb3J0KHsgdGFyZ2V0OiAnQXJyYXknLCBwcm90bzogdHJ1ZSwgZm9yY2VkOiBGT1JDRUQkMiB9LCB7XG4gICAgc29ydDogZnVuY3Rpb24gc29ydChjb21wYXJlZm4pIHtcbiAgICAgIHJldHVybiBjb21wYXJlZm4gPT09IHVuZGVmaW5lZFxuICAgICAgICA/IG5hdGl2ZVNvcnQuY2FsbCh0b09iamVjdCh0aGlzKSlcbiAgICAgICAgOiBuYXRpdmVTb3J0LmNhbGwodG9PYmplY3QodGhpcyksIGFGdW5jdGlvbihjb21wYXJlZm4pKTtcbiAgICB9XG4gIH0pO1xuXG4gIHZhciBmbG9vciA9IE1hdGguZmxvb3I7XG4gIHZhciByZXBsYWNlID0gJycucmVwbGFjZTtcbiAgdmFyIFNVQlNUSVRVVElPTl9TWU1CT0xTID0gL1xcJChbJCYnYF18XFxkezEsMn18PFtePl0qPikvZztcbiAgdmFyIFNVQlNUSVRVVElPTl9TWU1CT0xTX05PX05BTUVEID0gL1xcJChbJCYnYF18XFxkezEsMn0pL2c7XG5cbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1nZXRzdWJzdGl0dXRpb25cbiAgdmFyIGdldFN1YnN0aXR1dGlvbiA9IGZ1bmN0aW9uIChtYXRjaGVkLCBzdHIsIHBvc2l0aW9uLCBjYXB0dXJlcywgbmFtZWRDYXB0dXJlcywgcmVwbGFjZW1lbnQpIHtcbiAgICB2YXIgdGFpbFBvcyA9IHBvc2l0aW9uICsgbWF0Y2hlZC5sZW5ndGg7XG4gICAgdmFyIG0gPSBjYXB0dXJlcy5sZW5ndGg7XG4gICAgdmFyIHN5bWJvbHMgPSBTVUJTVElUVVRJT05fU1lNQk9MU19OT19OQU1FRDtcbiAgICBpZiAobmFtZWRDYXB0dXJlcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBuYW1lZENhcHR1cmVzID0gdG9PYmplY3QobmFtZWRDYXB0dXJlcyk7XG4gICAgICBzeW1ib2xzID0gU1VCU1RJVFVUSU9OX1NZTUJPTFM7XG4gICAgfVxuICAgIHJldHVybiByZXBsYWNlLmNhbGwocmVwbGFjZW1lbnQsIHN5bWJvbHMsIGZ1bmN0aW9uIChtYXRjaCwgY2gpIHtcbiAgICAgIHZhciBjYXB0dXJlO1xuICAgICAgc3dpdGNoIChjaC5jaGFyQXQoMCkpIHtcbiAgICAgICAgY2FzZSAnJCc6IHJldHVybiAnJCc7XG4gICAgICAgIGNhc2UgJyYnOiByZXR1cm4gbWF0Y2hlZDtcbiAgICAgICAgY2FzZSAnYCc6IHJldHVybiBzdHIuc2xpY2UoMCwgcG9zaXRpb24pO1xuICAgICAgICBjYXNlIFwiJ1wiOiByZXR1cm4gc3RyLnNsaWNlKHRhaWxQb3MpO1xuICAgICAgICBjYXNlICc8JzpcbiAgICAgICAgICBjYXB0dXJlID0gbmFtZWRDYXB0dXJlc1tjaC5zbGljZSgxLCAtMSldO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OiAvLyBcXGRcXGQ/XG4gICAgICAgICAgdmFyIG4gPSArY2g7XG4gICAgICAgICAgaWYgKG4gPT09IDApIHJldHVybiBtYXRjaDtcbiAgICAgICAgICBpZiAobiA+IG0pIHtcbiAgICAgICAgICAgIHZhciBmID0gZmxvb3IobiAvIDEwKTtcbiAgICAgICAgICAgIGlmIChmID09PSAwKSByZXR1cm4gbWF0Y2g7XG4gICAgICAgICAgICBpZiAoZiA8PSBtKSByZXR1cm4gY2FwdHVyZXNbZiAtIDFdID09PSB1bmRlZmluZWQgPyBjaC5jaGFyQXQoMSkgOiBjYXB0dXJlc1tmIC0gMV0gKyBjaC5jaGFyQXQoMSk7XG4gICAgICAgICAgICByZXR1cm4gbWF0Y2g7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNhcHR1cmUgPSBjYXB0dXJlc1tuIC0gMV07XG4gICAgICB9XG4gICAgICByZXR1cm4gY2FwdHVyZSA9PT0gdW5kZWZpbmVkID8gJycgOiBjYXB0dXJlO1xuICAgIH0pO1xuICB9O1xuXG4gIHZhciBtYXgkMiA9IE1hdGgubWF4O1xuICB2YXIgbWluJDMgPSBNYXRoLm1pbjtcblxuICB2YXIgbWF5YmVUb1N0cmluZyA9IGZ1bmN0aW9uIChpdCkge1xuICAgIHJldHVybiBpdCA9PT0gdW5kZWZpbmVkID8gaXQgOiBTdHJpbmcoaXQpO1xuICB9O1xuXG4gIC8vIEBAcmVwbGFjZSBsb2dpY1xuICBmaXhSZWdleHBXZWxsS25vd25TeW1ib2xMb2dpYygncmVwbGFjZScsIDIsIGZ1bmN0aW9uIChSRVBMQUNFLCBuYXRpdmVSZXBsYWNlLCBtYXliZUNhbGxOYXRpdmUsIHJlYXNvbikge1xuICAgIHZhciBSRUdFWFBfUkVQTEFDRV9TVUJTVElUVVRFU19VTkRFRklORURfQ0FQVFVSRSA9IHJlYXNvbi5SRUdFWFBfUkVQTEFDRV9TVUJTVElUVVRFU19VTkRFRklORURfQ0FQVFVSRTtcbiAgICB2YXIgUkVQTEFDRV9LRUVQU18kMCA9IHJlYXNvbi5SRVBMQUNFX0tFRVBTXyQwO1xuICAgIHZhciBVTlNBRkVfU1VCU1RJVFVURSA9IFJFR0VYUF9SRVBMQUNFX1NVQlNUSVRVVEVTX1VOREVGSU5FRF9DQVBUVVJFID8gJyQnIDogJyQwJztcblxuICAgIHJldHVybiBbXG4gICAgICAvLyBgU3RyaW5nLnByb3RvdHlwZS5yZXBsYWNlYCBtZXRob2RcbiAgICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtc3RyaW5nLnByb3RvdHlwZS5yZXBsYWNlXG4gICAgICBmdW5jdGlvbiByZXBsYWNlKHNlYXJjaFZhbHVlLCByZXBsYWNlVmFsdWUpIHtcbiAgICAgICAgdmFyIE8gPSByZXF1aXJlT2JqZWN0Q29lcmNpYmxlKHRoaXMpO1xuICAgICAgICB2YXIgcmVwbGFjZXIgPSBzZWFyY2hWYWx1ZSA9PSB1bmRlZmluZWQgPyB1bmRlZmluZWQgOiBzZWFyY2hWYWx1ZVtSRVBMQUNFXTtcbiAgICAgICAgcmV0dXJuIHJlcGxhY2VyICE9PSB1bmRlZmluZWRcbiAgICAgICAgICA/IHJlcGxhY2VyLmNhbGwoc2VhcmNoVmFsdWUsIE8sIHJlcGxhY2VWYWx1ZSlcbiAgICAgICAgICA6IG5hdGl2ZVJlcGxhY2UuY2FsbChTdHJpbmcoTyksIHNlYXJjaFZhbHVlLCByZXBsYWNlVmFsdWUpO1xuICAgICAgfSxcbiAgICAgIC8vIGBSZWdFeHAucHJvdG90eXBlW0BAcmVwbGFjZV1gIG1ldGhvZFxuICAgICAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1yZWdleHAucHJvdG90eXBlLUBAcmVwbGFjZVxuICAgICAgZnVuY3Rpb24gKHJlZ2V4cCwgcmVwbGFjZVZhbHVlKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAoIVJFR0VYUF9SRVBMQUNFX1NVQlNUSVRVVEVTX1VOREVGSU5FRF9DQVBUVVJFICYmIFJFUExBQ0VfS0VFUFNfJDApIHx8XG4gICAgICAgICAgKHR5cGVvZiByZXBsYWNlVmFsdWUgPT09ICdzdHJpbmcnICYmIHJlcGxhY2VWYWx1ZS5pbmRleE9mKFVOU0FGRV9TVUJTVElUVVRFKSA9PT0gLTEpXG4gICAgICAgICkge1xuICAgICAgICAgIHZhciByZXMgPSBtYXliZUNhbGxOYXRpdmUobmF0aXZlUmVwbGFjZSwgcmVnZXhwLCB0aGlzLCByZXBsYWNlVmFsdWUpO1xuICAgICAgICAgIGlmIChyZXMuZG9uZSkgcmV0dXJuIHJlcy52YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciByeCA9IGFuT2JqZWN0KHJlZ2V4cCk7XG4gICAgICAgIHZhciBTID0gU3RyaW5nKHRoaXMpO1xuXG4gICAgICAgIHZhciBmdW5jdGlvbmFsUmVwbGFjZSA9IHR5cGVvZiByZXBsYWNlVmFsdWUgPT09ICdmdW5jdGlvbic7XG4gICAgICAgIGlmICghZnVuY3Rpb25hbFJlcGxhY2UpIHJlcGxhY2VWYWx1ZSA9IFN0cmluZyhyZXBsYWNlVmFsdWUpO1xuXG4gICAgICAgIHZhciBnbG9iYWwgPSByeC5nbG9iYWw7XG4gICAgICAgIGlmIChnbG9iYWwpIHtcbiAgICAgICAgICB2YXIgZnVsbFVuaWNvZGUgPSByeC51bmljb2RlO1xuICAgICAgICAgIHJ4Lmxhc3RJbmRleCA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlc3VsdHMgPSBbXTtcbiAgICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICB2YXIgcmVzdWx0ID0gcmVnZXhwRXhlY0Fic3RyYWN0KHJ4LCBTKTtcbiAgICAgICAgICBpZiAocmVzdWx0ID09PSBudWxsKSBicmVhaztcblxuICAgICAgICAgIHJlc3VsdHMucHVzaChyZXN1bHQpO1xuICAgICAgICAgIGlmICghZ2xvYmFsKSBicmVhaztcblxuICAgICAgICAgIHZhciBtYXRjaFN0ciA9IFN0cmluZyhyZXN1bHRbMF0pO1xuICAgICAgICAgIGlmIChtYXRjaFN0ciA9PT0gJycpIHJ4Lmxhc3RJbmRleCA9IGFkdmFuY2VTdHJpbmdJbmRleChTLCB0b0xlbmd0aChyeC5sYXN0SW5kZXgpLCBmdWxsVW5pY29kZSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgYWNjdW11bGF0ZWRSZXN1bHQgPSAnJztcbiAgICAgICAgdmFyIG5leHRTb3VyY2VQb3NpdGlvbiA9IDA7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVzdWx0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdHNbaV07XG5cbiAgICAgICAgICB2YXIgbWF0Y2hlZCA9IFN0cmluZyhyZXN1bHRbMF0pO1xuICAgICAgICAgIHZhciBwb3NpdGlvbiA9IG1heCQyKG1pbiQzKHRvSW50ZWdlcihyZXN1bHQuaW5kZXgpLCBTLmxlbmd0aCksIDApO1xuICAgICAgICAgIHZhciBjYXB0dXJlcyA9IFtdO1xuICAgICAgICAgIC8vIE5PVEU6IFRoaXMgaXMgZXF1aXZhbGVudCB0b1xuICAgICAgICAgIC8vICAgY2FwdHVyZXMgPSByZXN1bHQuc2xpY2UoMSkubWFwKG1heWJlVG9TdHJpbmcpXG4gICAgICAgICAgLy8gYnV0IGZvciBzb21lIHJlYXNvbiBgbmF0aXZlU2xpY2UuY2FsbChyZXN1bHQsIDEsIHJlc3VsdC5sZW5ndGgpYCAoY2FsbGVkIGluXG4gICAgICAgICAgLy8gdGhlIHNsaWNlIHBvbHlmaWxsIHdoZW4gc2xpY2luZyBuYXRpdmUgYXJyYXlzKSBcImRvZXNuJ3Qgd29ya1wiIGluIHNhZmFyaSA5IGFuZFxuICAgICAgICAgIC8vIGNhdXNlcyBhIGNyYXNoIChodHRwczovL3Bhc3RlYmluLmNvbS9OMjFRemVRQSkgd2hlbiB0cnlpbmcgdG8gZGVidWcgaXQuXG4gICAgICAgICAgZm9yICh2YXIgaiA9IDE7IGogPCByZXN1bHQubGVuZ3RoOyBqKyspIGNhcHR1cmVzLnB1c2gobWF5YmVUb1N0cmluZyhyZXN1bHRbal0pKTtcbiAgICAgICAgICB2YXIgbmFtZWRDYXB0dXJlcyA9IHJlc3VsdC5ncm91cHM7XG4gICAgICAgICAgaWYgKGZ1bmN0aW9uYWxSZXBsYWNlKSB7XG4gICAgICAgICAgICB2YXIgcmVwbGFjZXJBcmdzID0gW21hdGNoZWRdLmNvbmNhdChjYXB0dXJlcywgcG9zaXRpb24sIFMpO1xuICAgICAgICAgICAgaWYgKG5hbWVkQ2FwdHVyZXMgIT09IHVuZGVmaW5lZCkgcmVwbGFjZXJBcmdzLnB1c2gobmFtZWRDYXB0dXJlcyk7XG4gICAgICAgICAgICB2YXIgcmVwbGFjZW1lbnQgPSBTdHJpbmcocmVwbGFjZVZhbHVlLmFwcGx5KHVuZGVmaW5lZCwgcmVwbGFjZXJBcmdzKSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcGxhY2VtZW50ID0gZ2V0U3Vic3RpdHV0aW9uKG1hdGNoZWQsIFMsIHBvc2l0aW9uLCBjYXB0dXJlcywgbmFtZWRDYXB0dXJlcywgcmVwbGFjZVZhbHVlKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHBvc2l0aW9uID49IG5leHRTb3VyY2VQb3NpdGlvbikge1xuICAgICAgICAgICAgYWNjdW11bGF0ZWRSZXN1bHQgKz0gUy5zbGljZShuZXh0U291cmNlUG9zaXRpb24sIHBvc2l0aW9uKSArIHJlcGxhY2VtZW50O1xuICAgICAgICAgICAgbmV4dFNvdXJjZVBvc2l0aW9uID0gcG9zaXRpb24gKyBtYXRjaGVkLmxlbmd0aDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFjY3VtdWxhdGVkUmVzdWx0ICsgUy5zbGljZShuZXh0U291cmNlUG9zaXRpb24pO1xuICAgICAgfVxuICAgIF07XG4gIH0pO1xuXG4gIHZhciBuYXRpdmVBc3NpZ24gPSBPYmplY3QuYXNzaWduO1xuICB2YXIgZGVmaW5lUHJvcGVydHkkMyA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eTtcblxuICAvLyBgT2JqZWN0LmFzc2lnbmAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtb2JqZWN0LmFzc2lnblxuICB2YXIgb2JqZWN0QXNzaWduID0gIW5hdGl2ZUFzc2lnbiB8fCBmYWlscyhmdW5jdGlvbiAoKSB7XG4gICAgLy8gc2hvdWxkIGhhdmUgY29ycmVjdCBvcmRlciBvZiBvcGVyYXRpb25zIChFZGdlIGJ1ZylcbiAgICBpZiAoZGVzY3JpcHRvcnMgJiYgbmF0aXZlQXNzaWduKHsgYjogMSB9LCBuYXRpdmVBc3NpZ24oZGVmaW5lUHJvcGVydHkkMyh7fSwgJ2EnLCB7XG4gICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGRlZmluZVByb3BlcnR5JDModGhpcywgJ2InLCB7XG4gICAgICAgICAgdmFsdWU6IDMsXG4gICAgICAgICAgZW51bWVyYWJsZTogZmFsc2VcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSksIHsgYjogMiB9KSkuYiAhPT0gMSkgcmV0dXJuIHRydWU7XG4gICAgLy8gc2hvdWxkIHdvcmsgd2l0aCBzeW1ib2xzIGFuZCBzaG91bGQgaGF2ZSBkZXRlcm1pbmlzdGljIHByb3BlcnR5IG9yZGVyIChWOCBidWcpXG4gICAgdmFyIEEgPSB7fTtcbiAgICB2YXIgQiA9IHt9O1xuICAgIC8qIGdsb2JhbCBTeW1ib2wgLS0gcmVxdWlyZWQgZm9yIHRlc3RpbmcgKi9cbiAgICB2YXIgc3ltYm9sID0gU3ltYm9sKCk7XG4gICAgdmFyIGFscGhhYmV0ID0gJ2FiY2RlZmdoaWprbG1ub3BxcnN0JztcbiAgICBBW3N5bWJvbF0gPSA3O1xuICAgIGFscGhhYmV0LnNwbGl0KCcnKS5mb3JFYWNoKGZ1bmN0aW9uIChjaHIpIHsgQltjaHJdID0gY2hyOyB9KTtcbiAgICByZXR1cm4gbmF0aXZlQXNzaWduKHt9LCBBKVtzeW1ib2xdICE9IDcgfHwgb2JqZWN0S2V5cyhuYXRpdmVBc3NpZ24oe30sIEIpKS5qb2luKCcnKSAhPSBhbHBoYWJldDtcbiAgfSkgPyBmdW5jdGlvbiBhc3NpZ24odGFyZ2V0LCBzb3VyY2UpIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFycyAtLSByZXF1aXJlZCBmb3IgYC5sZW5ndGhgXG4gICAgdmFyIFQgPSB0b09iamVjdCh0YXJnZXQpO1xuICAgIHZhciBhcmd1bWVudHNMZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgIHZhciBpbmRleCA9IDE7XG4gICAgdmFyIGdldE93blByb3BlcnR5U3ltYm9scyA9IG9iamVjdEdldE93blByb3BlcnR5U3ltYm9scy5mO1xuICAgIHZhciBwcm9wZXJ0eUlzRW51bWVyYWJsZSA9IG9iamVjdFByb3BlcnR5SXNFbnVtZXJhYmxlLmY7XG4gICAgd2hpbGUgKGFyZ3VtZW50c0xlbmd0aCA+IGluZGV4KSB7XG4gICAgICB2YXIgUyA9IGluZGV4ZWRPYmplY3QoYXJndW1lbnRzW2luZGV4KytdKTtcbiAgICAgIHZhciBrZXlzID0gZ2V0T3duUHJvcGVydHlTeW1ib2xzID8gb2JqZWN0S2V5cyhTKS5jb25jYXQoZ2V0T3duUHJvcGVydHlTeW1ib2xzKFMpKSA6IG9iamVjdEtleXMoUyk7XG4gICAgICB2YXIgbGVuZ3RoID0ga2V5cy5sZW5ndGg7XG4gICAgICB2YXIgaiA9IDA7XG4gICAgICB2YXIga2V5O1xuICAgICAgd2hpbGUgKGxlbmd0aCA+IGopIHtcbiAgICAgICAga2V5ID0ga2V5c1tqKytdO1xuICAgICAgICBpZiAoIWRlc2NyaXB0b3JzIHx8IHByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwoUywga2V5KSkgVFtrZXldID0gU1trZXldO1xuICAgICAgfVxuICAgIH0gcmV0dXJuIFQ7XG4gIH0gOiBuYXRpdmVBc3NpZ247XG5cbiAgLy8gYE9iamVjdC5hc3NpZ25gIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9iamVjdC5hc3NpZ25cbiAgX2V4cG9ydCh7IHRhcmdldDogJ09iamVjdCcsIHN0YXQ6IHRydWUsIGZvcmNlZDogT2JqZWN0LmFzc2lnbiAhPT0gb2JqZWN0QXNzaWduIH0sIHtcbiAgICBhc3NpZ246IG9iamVjdEFzc2lnblxuICB9KTtcblxuICB2YXIgJGZpbHRlciA9IGFycmF5SXRlcmF0aW9uLmZpbHRlcjtcblxuXG4gIHZhciBIQVNfU1BFQ0lFU19TVVBQT1JUJDMgPSBhcnJheU1ldGhvZEhhc1NwZWNpZXNTdXBwb3J0KCdmaWx0ZXInKTtcblxuICAvLyBgQXJyYXkucHJvdG90eXBlLmZpbHRlcmAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLmZpbHRlclxuICAvLyB3aXRoIGFkZGluZyBzdXBwb3J0IG9mIEBAc3BlY2llc1xuICBfZXhwb3J0KHsgdGFyZ2V0OiAnQXJyYXknLCBwcm90bzogdHJ1ZSwgZm9yY2VkOiAhSEFTX1NQRUNJRVNfU1VQUE9SVCQzIH0sIHtcbiAgICBmaWx0ZXI6IGZ1bmN0aW9uIGZpbHRlcihjYWxsYmFja2ZuIC8qICwgdGhpc0FyZyAqLykge1xuICAgICAgcmV0dXJuICRmaWx0ZXIodGhpcywgY2FsbGJhY2tmbiwgYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQpO1xuICAgIH1cbiAgfSk7XG5cbiAgLy8gYFNhbWVWYWx1ZWAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtc2FtZXZhbHVlXG4gIHZhciBzYW1lVmFsdWUgPSBPYmplY3QuaXMgfHwgZnVuY3Rpb24gaXMoeCwgeSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1zZWxmLWNvbXBhcmUgLS0gTmFOIGNoZWNrXG4gICAgcmV0dXJuIHggPT09IHkgPyB4ICE9PSAwIHx8IDEgLyB4ID09PSAxIC8geSA6IHggIT0geCAmJiB5ICE9IHk7XG4gIH07XG5cbiAgLy8gQEBzZWFyY2ggbG9naWNcbiAgZml4UmVnZXhwV2VsbEtub3duU3ltYm9sTG9naWMoJ3NlYXJjaCcsIDEsIGZ1bmN0aW9uIChTRUFSQ0gsIG5hdGl2ZVNlYXJjaCwgbWF5YmVDYWxsTmF0aXZlKSB7XG4gICAgcmV0dXJuIFtcbiAgICAgIC8vIGBTdHJpbmcucHJvdG90eXBlLnNlYXJjaGAgbWV0aG9kXG4gICAgICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXN0cmluZy5wcm90b3R5cGUuc2VhcmNoXG4gICAgICBmdW5jdGlvbiBzZWFyY2gocmVnZXhwKSB7XG4gICAgICAgIHZhciBPID0gcmVxdWlyZU9iamVjdENvZXJjaWJsZSh0aGlzKTtcbiAgICAgICAgdmFyIHNlYXJjaGVyID0gcmVnZXhwID09IHVuZGVmaW5lZCA/IHVuZGVmaW5lZCA6IHJlZ2V4cFtTRUFSQ0hdO1xuICAgICAgICByZXR1cm4gc2VhcmNoZXIgIT09IHVuZGVmaW5lZCA/IHNlYXJjaGVyLmNhbGwocmVnZXhwLCBPKSA6IG5ldyBSZWdFeHAocmVnZXhwKVtTRUFSQ0hdKFN0cmluZyhPKSk7XG4gICAgICB9LFxuICAgICAgLy8gYFJlZ0V4cC5wcm90b3R5cGVbQEBzZWFyY2hdYCBtZXRob2RcbiAgICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtcmVnZXhwLnByb3RvdHlwZS1AQHNlYXJjaFxuICAgICAgZnVuY3Rpb24gKHJlZ2V4cCkge1xuICAgICAgICB2YXIgcmVzID0gbWF5YmVDYWxsTmF0aXZlKG5hdGl2ZVNlYXJjaCwgcmVnZXhwLCB0aGlzKTtcbiAgICAgICAgaWYgKHJlcy5kb25lKSByZXR1cm4gcmVzLnZhbHVlO1xuXG4gICAgICAgIHZhciByeCA9IGFuT2JqZWN0KHJlZ2V4cCk7XG4gICAgICAgIHZhciBTID0gU3RyaW5nKHRoaXMpO1xuXG4gICAgICAgIHZhciBwcmV2aW91c0xhc3RJbmRleCA9IHJ4Lmxhc3RJbmRleDtcbiAgICAgICAgaWYgKCFzYW1lVmFsdWUocHJldmlvdXNMYXN0SW5kZXgsIDApKSByeC5sYXN0SW5kZXggPSAwO1xuICAgICAgICB2YXIgcmVzdWx0ID0gcmVnZXhwRXhlY0Fic3RyYWN0KHJ4LCBTKTtcbiAgICAgICAgaWYgKCFzYW1lVmFsdWUocngubGFzdEluZGV4LCBwcmV2aW91c0xhc3RJbmRleCkpIHJ4Lmxhc3RJbmRleCA9IHByZXZpb3VzTGFzdEluZGV4O1xuICAgICAgICByZXR1cm4gcmVzdWx0ID09PSBudWxsID8gLTEgOiByZXN1bHQuaW5kZXg7XG4gICAgICB9XG4gICAgXTtcbiAgfSk7XG5cbiAgdmFyIHRyaW0kMSA9IHN0cmluZ1RyaW0udHJpbTtcblxuXG4gIHZhciAkcGFyc2VJbnQgPSBnbG9iYWxfMS5wYXJzZUludDtcbiAgdmFyIGhleCA9IC9eWystXT8wW1h4XS87XG4gIHZhciBGT1JDRUQkMSA9ICRwYXJzZUludCh3aGl0ZXNwYWNlcyArICcwOCcpICE9PSA4IHx8ICRwYXJzZUludCh3aGl0ZXNwYWNlcyArICcweDE2JykgIT09IDIyO1xuXG4gIC8vIGBwYXJzZUludGAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtcGFyc2VpbnQtc3RyaW5nLXJhZGl4XG4gIHZhciBudW1iZXJQYXJzZUludCA9IEZPUkNFRCQxID8gZnVuY3Rpb24gcGFyc2VJbnQoc3RyaW5nLCByYWRpeCkge1xuICAgIHZhciBTID0gdHJpbSQxKFN0cmluZyhzdHJpbmcpKTtcbiAgICByZXR1cm4gJHBhcnNlSW50KFMsIChyYWRpeCA+Pj4gMCkgfHwgKGhleC50ZXN0KFMpID8gMTYgOiAxMCkpO1xuICB9IDogJHBhcnNlSW50O1xuXG4gIC8vIGBwYXJzZUludGAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtcGFyc2VpbnQtc3RyaW5nLXJhZGl4XG4gIF9leHBvcnQoeyBnbG9iYWw6IHRydWUsIGZvcmNlZDogcGFyc2VJbnQgIT0gbnVtYmVyUGFyc2VJbnQgfSwge1xuICAgIHBhcnNlSW50OiBudW1iZXJQYXJzZUludFxuICB9KTtcblxuICB2YXIgJG1hcCA9IGFycmF5SXRlcmF0aW9uLm1hcDtcblxuXG4gIHZhciBIQVNfU1BFQ0lFU19TVVBQT1JUJDIgPSBhcnJheU1ldGhvZEhhc1NwZWNpZXNTdXBwb3J0KCdtYXAnKTtcblxuICAvLyBgQXJyYXkucHJvdG90eXBlLm1hcGAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLm1hcFxuICAvLyB3aXRoIGFkZGluZyBzdXBwb3J0IG9mIEBAc3BlY2llc1xuICBfZXhwb3J0KHsgdGFyZ2V0OiAnQXJyYXknLCBwcm90bzogdHJ1ZSwgZm9yY2VkOiAhSEFTX1NQRUNJRVNfU1VQUE9SVCQyIH0sIHtcbiAgICBtYXA6IGZ1bmN0aW9uIG1hcChjYWxsYmFja2ZuIC8qICwgdGhpc0FyZyAqLykge1xuICAgICAgcmV0dXJuICRtYXAodGhpcywgY2FsbGJhY2tmbiwgYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQpO1xuICAgIH1cbiAgfSk7XG5cbiAgdmFyICRmaW5kSW5kZXggPSBhcnJheUl0ZXJhdGlvbi5maW5kSW5kZXg7XG5cblxuICB2YXIgRklORF9JTkRFWCA9ICdmaW5kSW5kZXgnO1xuICB2YXIgU0tJUFNfSE9MRVMgPSB0cnVlO1xuXG4gIC8vIFNob3VsZG4ndCBza2lwIGhvbGVzXG4gIGlmIChGSU5EX0lOREVYIGluIFtdKSBBcnJheSgxKVtGSU5EX0lOREVYXShmdW5jdGlvbiAoKSB7IFNLSVBTX0hPTEVTID0gZmFsc2U7IH0pO1xuXG4gIC8vIGBBcnJheS5wcm90b3R5cGUuZmluZEluZGV4YCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUuZmluZGluZGV4XG4gIF9leHBvcnQoeyB0YXJnZXQ6ICdBcnJheScsIHByb3RvOiB0cnVlLCBmb3JjZWQ6IFNLSVBTX0hPTEVTIH0sIHtcbiAgICBmaW5kSW5kZXg6IGZ1bmN0aW9uIGZpbmRJbmRleChjYWxsYmFja2ZuIC8qICwgdGhhdCA9IHVuZGVmaW5lZCAqLykge1xuICAgICAgcmV0dXJuICRmaW5kSW5kZXgodGhpcywgY2FsbGJhY2tmbiwgYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQpO1xuICAgIH1cbiAgfSk7XG5cbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUtQEB1bnNjb3BhYmxlc1xuICBhZGRUb1Vuc2NvcGFibGVzKEZJTkRfSU5ERVgpO1xuXG4gIHZhciBhUG9zc2libGVQcm90b3R5cGUgPSBmdW5jdGlvbiAoaXQpIHtcbiAgICBpZiAoIWlzT2JqZWN0KGl0KSAmJiBpdCAhPT0gbnVsbCkge1xuICAgICAgdGhyb3cgVHlwZUVycm9yKFwiQ2FuJ3Qgc2V0IFwiICsgU3RyaW5nKGl0KSArICcgYXMgYSBwcm90b3R5cGUnKTtcbiAgICB9IHJldHVybiBpdDtcbiAgfTtcblxuICAvKiBlc2xpbnQtZGlzYWJsZSBuby1wcm90byAtLSBzYWZlICovXG5cblxuXG4gIC8vIGBPYmplY3Quc2V0UHJvdG90eXBlT2ZgIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9iamVjdC5zZXRwcm90b3R5cGVvZlxuICAvLyBXb3JrcyB3aXRoIF9fcHJvdG9fXyBvbmx5LiBPbGQgdjggY2FuJ3Qgd29yayB3aXRoIG51bGwgcHJvdG8gb2JqZWN0cy5cbiAgdmFyIG9iamVjdFNldFByb3RvdHlwZU9mID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8ICgnX19wcm90b19fJyBpbiB7fSA/IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgQ09SUkVDVF9TRVRURVIgPSBmYWxzZTtcbiAgICB2YXIgdGVzdCA9IHt9O1xuICAgIHZhciBzZXR0ZXI7XG4gICAgdHJ5IHtcbiAgICAgIHNldHRlciA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoT2JqZWN0LnByb3RvdHlwZSwgJ19fcHJvdG9fXycpLnNldDtcbiAgICAgIHNldHRlci5jYWxsKHRlc3QsIFtdKTtcbiAgICAgIENPUlJFQ1RfU0VUVEVSID0gdGVzdCBpbnN0YW5jZW9mIEFycmF5O1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7IC8qIGVtcHR5ICovIH1cbiAgICByZXR1cm4gZnVuY3Rpb24gc2V0UHJvdG90eXBlT2YoTywgcHJvdG8pIHtcbiAgICAgIGFuT2JqZWN0KE8pO1xuICAgICAgYVBvc3NpYmxlUHJvdG90eXBlKHByb3RvKTtcbiAgICAgIGlmIChDT1JSRUNUX1NFVFRFUikgc2V0dGVyLmNhbGwoTywgcHJvdG8pO1xuICAgICAgZWxzZSBPLl9fcHJvdG9fXyA9IHByb3RvO1xuICAgICAgcmV0dXJuIE87XG4gICAgfTtcbiAgfSgpIDogdW5kZWZpbmVkKTtcblxuICAvLyBtYWtlcyBzdWJjbGFzc2luZyB3b3JrIGNvcnJlY3QgZm9yIHdyYXBwZWQgYnVpbHQtaW5zXG4gIHZhciBpbmhlcml0SWZSZXF1aXJlZCA9IGZ1bmN0aW9uICgkdGhpcywgZHVtbXksIFdyYXBwZXIpIHtcbiAgICB2YXIgTmV3VGFyZ2V0LCBOZXdUYXJnZXRQcm90b3R5cGU7XG4gICAgaWYgKFxuICAgICAgLy8gaXQgY2FuIHdvcmsgb25seSB3aXRoIG5hdGl2ZSBgc2V0UHJvdG90eXBlT2ZgXG4gICAgICBvYmplY3RTZXRQcm90b3R5cGVPZiAmJlxuICAgICAgLy8gd2UgaGF2ZW4ndCBjb21wbGV0ZWx5IGNvcnJlY3QgcHJlLUVTNiB3YXkgZm9yIGdldHRpbmcgYG5ldy50YXJnZXRgLCBzbyB1c2UgdGhpc1xuICAgICAgdHlwZW9mIChOZXdUYXJnZXQgPSBkdW1teS5jb25zdHJ1Y3RvcikgPT0gJ2Z1bmN0aW9uJyAmJlxuICAgICAgTmV3VGFyZ2V0ICE9PSBXcmFwcGVyICYmXG4gICAgICBpc09iamVjdChOZXdUYXJnZXRQcm90b3R5cGUgPSBOZXdUYXJnZXQucHJvdG90eXBlKSAmJlxuICAgICAgTmV3VGFyZ2V0UHJvdG90eXBlICE9PSBXcmFwcGVyLnByb3RvdHlwZVxuICAgICkgb2JqZWN0U2V0UHJvdG90eXBlT2YoJHRoaXMsIE5ld1RhcmdldFByb3RvdHlwZSk7XG4gICAgcmV0dXJuICR0aGlzO1xuICB9O1xuXG4gIHZhciBTUEVDSUVTJDEgPSB3ZWxsS25vd25TeW1ib2woJ3NwZWNpZXMnKTtcblxuICB2YXIgc2V0U3BlY2llcyA9IGZ1bmN0aW9uIChDT05TVFJVQ1RPUl9OQU1FKSB7XG4gICAgdmFyIENvbnN0cnVjdG9yID0gZ2V0QnVpbHRJbihDT05TVFJVQ1RPUl9OQU1FKTtcbiAgICB2YXIgZGVmaW5lUHJvcGVydHkgPSBvYmplY3REZWZpbmVQcm9wZXJ0eS5mO1xuXG4gICAgaWYgKGRlc2NyaXB0b3JzICYmIENvbnN0cnVjdG9yICYmICFDb25zdHJ1Y3RvcltTUEVDSUVTJDFdKSB7XG4gICAgICBkZWZpbmVQcm9wZXJ0eShDb25zdHJ1Y3RvciwgU1BFQ0lFUyQxLCB7XG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9XG4gICAgICB9KTtcbiAgICB9XG4gIH07XG5cbiAgdmFyIGRlZmluZVByb3BlcnR5JDIgPSBvYmplY3REZWZpbmVQcm9wZXJ0eS5mO1xuICB2YXIgZ2V0T3duUHJvcGVydHlOYW1lcyQxID0gb2JqZWN0R2V0T3duUHJvcGVydHlOYW1lcy5mO1xuXG5cblxuXG5cbiAgdmFyIHNldEludGVybmFsU3RhdGUkMSA9IGludGVybmFsU3RhdGUuc2V0O1xuXG5cblxuICB2YXIgTUFUQ0ggPSB3ZWxsS25vd25TeW1ib2woJ21hdGNoJyk7XG4gIHZhciBOYXRpdmVSZWdFeHAgPSBnbG9iYWxfMS5SZWdFeHA7XG4gIHZhciBSZWdFeHBQcm90b3R5cGUkMSA9IE5hdGl2ZVJlZ0V4cC5wcm90b3R5cGU7XG4gIHZhciByZTEgPSAvYS9nO1xuICB2YXIgcmUyID0gL2EvZztcblxuICAvLyBcIm5ld1wiIHNob3VsZCBjcmVhdGUgYSBuZXcgb2JqZWN0LCBvbGQgd2Via2l0IGJ1Z1xuICB2YXIgQ09SUkVDVF9ORVcgPSBuZXcgTmF0aXZlUmVnRXhwKHJlMSkgIT09IHJlMTtcblxuICB2YXIgVU5TVVBQT1JURURfWSA9IHJlZ2V4cFN0aWNreUhlbHBlcnMuVU5TVVBQT1JURURfWTtcblxuICB2YXIgRk9SQ0VEID0gZGVzY3JpcHRvcnMgJiYgaXNGb3JjZWRfMSgnUmVnRXhwJywgKCFDT1JSRUNUX05FVyB8fCBVTlNVUFBPUlRFRF9ZIHx8IGZhaWxzKGZ1bmN0aW9uICgpIHtcbiAgICByZTJbTUFUQ0hdID0gZmFsc2U7XG4gICAgLy8gUmVnRXhwIGNvbnN0cnVjdG9yIGNhbiBhbHRlciBmbGFncyBhbmQgSXNSZWdFeHAgd29ya3MgY29ycmVjdCB3aXRoIEBAbWF0Y2hcbiAgICByZXR1cm4gTmF0aXZlUmVnRXhwKHJlMSkgIT0gcmUxIHx8IE5hdGl2ZVJlZ0V4cChyZTIpID09IHJlMiB8fCBOYXRpdmVSZWdFeHAocmUxLCAnaScpICE9ICcvYS9pJztcbiAgfSkpKTtcblxuICAvLyBgUmVnRXhwYCBjb25zdHJ1Y3RvclxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXJlZ2V4cC1jb25zdHJ1Y3RvclxuICBpZiAoRk9SQ0VEKSB7XG4gICAgdmFyIFJlZ0V4cFdyYXBwZXIgPSBmdW5jdGlvbiBSZWdFeHAocGF0dGVybiwgZmxhZ3MpIHtcbiAgICAgIHZhciB0aGlzSXNSZWdFeHAgPSB0aGlzIGluc3RhbmNlb2YgUmVnRXhwV3JhcHBlcjtcbiAgICAgIHZhciBwYXR0ZXJuSXNSZWdFeHAgPSBpc1JlZ2V4cChwYXR0ZXJuKTtcbiAgICAgIHZhciBmbGFnc0FyZVVuZGVmaW5lZCA9IGZsYWdzID09PSB1bmRlZmluZWQ7XG4gICAgICB2YXIgc3RpY2t5O1xuXG4gICAgICBpZiAoIXRoaXNJc1JlZ0V4cCAmJiBwYXR0ZXJuSXNSZWdFeHAgJiYgcGF0dGVybi5jb25zdHJ1Y3RvciA9PT0gUmVnRXhwV3JhcHBlciAmJiBmbGFnc0FyZVVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gcGF0dGVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKENPUlJFQ1RfTkVXKSB7XG4gICAgICAgIGlmIChwYXR0ZXJuSXNSZWdFeHAgJiYgIWZsYWdzQXJlVW5kZWZpbmVkKSBwYXR0ZXJuID0gcGF0dGVybi5zb3VyY2U7XG4gICAgICB9IGVsc2UgaWYgKHBhdHRlcm4gaW5zdGFuY2VvZiBSZWdFeHBXcmFwcGVyKSB7XG4gICAgICAgIGlmIChmbGFnc0FyZVVuZGVmaW5lZCkgZmxhZ3MgPSByZWdleHBGbGFncy5jYWxsKHBhdHRlcm4pO1xuICAgICAgICBwYXR0ZXJuID0gcGF0dGVybi5zb3VyY2U7XG4gICAgICB9XG5cbiAgICAgIGlmIChVTlNVUFBPUlRFRF9ZKSB7XG4gICAgICAgIHN0aWNreSA9ICEhZmxhZ3MgJiYgZmxhZ3MuaW5kZXhPZigneScpID4gLTE7XG4gICAgICAgIGlmIChzdGlja3kpIGZsYWdzID0gZmxhZ3MucmVwbGFjZSgveS9nLCAnJyk7XG4gICAgICB9XG5cbiAgICAgIHZhciByZXN1bHQgPSBpbmhlcml0SWZSZXF1aXJlZChcbiAgICAgICAgQ09SUkVDVF9ORVcgPyBuZXcgTmF0aXZlUmVnRXhwKHBhdHRlcm4sIGZsYWdzKSA6IE5hdGl2ZVJlZ0V4cChwYXR0ZXJuLCBmbGFncyksXG4gICAgICAgIHRoaXNJc1JlZ0V4cCA/IHRoaXMgOiBSZWdFeHBQcm90b3R5cGUkMSxcbiAgICAgICAgUmVnRXhwV3JhcHBlclxuICAgICAgKTtcblxuICAgICAgaWYgKFVOU1VQUE9SVEVEX1kgJiYgc3RpY2t5KSBzZXRJbnRlcm5hbFN0YXRlJDEocmVzdWx0LCB7IHN0aWNreTogc3RpY2t5IH0pO1xuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gICAgdmFyIHByb3h5ID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAga2V5IGluIFJlZ0V4cFdyYXBwZXIgfHwgZGVmaW5lUHJvcGVydHkkMihSZWdFeHBXcmFwcGVyLCBrZXksIHtcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIE5hdGl2ZVJlZ0V4cFtrZXldOyB9LFxuICAgICAgICBzZXQ6IGZ1bmN0aW9uIChpdCkgeyBOYXRpdmVSZWdFeHBba2V5XSA9IGl0OyB9XG4gICAgICB9KTtcbiAgICB9O1xuICAgIHZhciBrZXlzJDEgPSBnZXRPd25Qcm9wZXJ0eU5hbWVzJDEoTmF0aXZlUmVnRXhwKTtcbiAgICB2YXIgaW5kZXggPSAwO1xuICAgIHdoaWxlIChrZXlzJDEubGVuZ3RoID4gaW5kZXgpIHByb3h5KGtleXMkMVtpbmRleCsrXSk7XG4gICAgUmVnRXhwUHJvdG90eXBlJDEuY29uc3RydWN0b3IgPSBSZWdFeHBXcmFwcGVyO1xuICAgIFJlZ0V4cFdyYXBwZXIucHJvdG90eXBlID0gUmVnRXhwUHJvdG90eXBlJDE7XG4gICAgcmVkZWZpbmUoZ2xvYmFsXzEsICdSZWdFeHAnLCBSZWdFeHBXcmFwcGVyKTtcbiAgfVxuXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtZ2V0LXJlZ2V4cC1AQHNwZWNpZXNcbiAgc2V0U3BlY2llcygnUmVnRXhwJyk7XG5cbiAgdmFyIFRPX1NUUklORyA9ICd0b1N0cmluZyc7XG4gIHZhciBSZWdFeHBQcm90b3R5cGUgPSBSZWdFeHAucHJvdG90eXBlO1xuICB2YXIgbmF0aXZlVG9TdHJpbmcgPSBSZWdFeHBQcm90b3R5cGVbVE9fU1RSSU5HXTtcblxuICB2YXIgTk9UX0dFTkVSSUMgPSBmYWlscyhmdW5jdGlvbiAoKSB7IHJldHVybiBuYXRpdmVUb1N0cmluZy5jYWxsKHsgc291cmNlOiAnYScsIGZsYWdzOiAnYicgfSkgIT0gJy9hL2InOyB9KTtcbiAgLy8gRkY0NC0gUmVnRXhwI3RvU3RyaW5nIGhhcyBhIHdyb25nIG5hbWVcbiAgdmFyIElOQ09SUkVDVF9OQU1FID0gbmF0aXZlVG9TdHJpbmcubmFtZSAhPSBUT19TVFJJTkc7XG5cbiAgLy8gYFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmdgIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXJlZ2V4cC5wcm90b3R5cGUudG9zdHJpbmdcbiAgaWYgKE5PVF9HRU5FUklDIHx8IElOQ09SUkVDVF9OQU1FKSB7XG4gICAgcmVkZWZpbmUoUmVnRXhwLnByb3RvdHlwZSwgVE9fU1RSSU5HLCBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgICAgIHZhciBSID0gYW5PYmplY3QodGhpcyk7XG4gICAgICB2YXIgcCA9IFN0cmluZyhSLnNvdXJjZSk7XG4gICAgICB2YXIgcmYgPSBSLmZsYWdzO1xuICAgICAgdmFyIGYgPSBTdHJpbmcocmYgPT09IHVuZGVmaW5lZCAmJiBSIGluc3RhbmNlb2YgUmVnRXhwICYmICEoJ2ZsYWdzJyBpbiBSZWdFeHBQcm90b3R5cGUpID8gcmVnZXhwRmxhZ3MuY2FsbChSKSA6IHJmKTtcbiAgICAgIHJldHVybiAnLycgKyBwICsgJy8nICsgZjtcbiAgICB9LCB7IHVuc2FmZTogdHJ1ZSB9KTtcbiAgfVxuXG4gIHZhciBUT19TVFJJTkdfVEFHJDMgPSB3ZWxsS25vd25TeW1ib2woJ3RvU3RyaW5nVGFnJyk7XG4gIHZhciB0ZXN0JDEgPSB7fTtcblxuICB0ZXN0JDFbVE9fU1RSSU5HX1RBRyQzXSA9ICd6JztcblxuICB2YXIgdG9TdHJpbmdUYWdTdXBwb3J0ID0gU3RyaW5nKHRlc3QkMSkgPT09ICdbb2JqZWN0IHpdJztcblxuICB2YXIgVE9fU1RSSU5HX1RBRyQyID0gd2VsbEtub3duU3ltYm9sKCd0b1N0cmluZ1RhZycpO1xuICAvLyBFUzMgd3JvbmcgaGVyZVxuICB2YXIgQ09SUkVDVF9BUkdVTUVOVFMgPSBjbGFzc29mUmF3KGZ1bmN0aW9uICgpIHsgcmV0dXJuIGFyZ3VtZW50czsgfSgpKSA9PSAnQXJndW1lbnRzJztcblxuICAvLyBmYWxsYmFjayBmb3IgSUUxMSBTY3JpcHQgQWNjZXNzIERlbmllZCBlcnJvclxuICB2YXIgdHJ5R2V0ID0gZnVuY3Rpb24gKGl0LCBrZXkpIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGl0W2tleV07XG4gICAgfSBjYXRjaCAoZXJyb3IpIHsgLyogZW1wdHkgKi8gfVxuICB9O1xuXG4gIC8vIGdldHRpbmcgdGFnIGZyb20gRVM2KyBgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ2BcbiAgdmFyIGNsYXNzb2YgPSB0b1N0cmluZ1RhZ1N1cHBvcnQgPyBjbGFzc29mUmF3IDogZnVuY3Rpb24gKGl0KSB7XG4gICAgdmFyIE8sIHRhZywgcmVzdWx0O1xuICAgIHJldHVybiBpdCA9PT0gdW5kZWZpbmVkID8gJ1VuZGVmaW5lZCcgOiBpdCA9PT0gbnVsbCA/ICdOdWxsJ1xuICAgICAgLy8gQEB0b1N0cmluZ1RhZyBjYXNlXG4gICAgICA6IHR5cGVvZiAodGFnID0gdHJ5R2V0KE8gPSBPYmplY3QoaXQpLCBUT19TVFJJTkdfVEFHJDIpKSA9PSAnc3RyaW5nJyA/IHRhZ1xuICAgICAgLy8gYnVpbHRpblRhZyBjYXNlXG4gICAgICA6IENPUlJFQ1RfQVJHVU1FTlRTID8gY2xhc3NvZlJhdyhPKVxuICAgICAgLy8gRVMzIGFyZ3VtZW50cyBmYWxsYmFja1xuICAgICAgOiAocmVzdWx0ID0gY2xhc3NvZlJhdyhPKSkgPT0gJ09iamVjdCcgJiYgdHlwZW9mIE8uY2FsbGVlID09ICdmdW5jdGlvbicgPyAnQXJndW1lbnRzJyA6IHJlc3VsdDtcbiAgfTtcblxuICAvLyBgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ2AgbWV0aG9kIGltcGxlbWVudGF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtb2JqZWN0LnByb3RvdHlwZS50b3N0cmluZ1xuICB2YXIgb2JqZWN0VG9TdHJpbmcgPSB0b1N0cmluZ1RhZ1N1cHBvcnQgPyB7fS50b1N0cmluZyA6IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiAnW29iamVjdCAnICsgY2xhc3NvZih0aGlzKSArICddJztcbiAgfTtcblxuICAvLyBgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ2AgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtb2JqZWN0LnByb3RvdHlwZS50b3N0cmluZ1xuICBpZiAoIXRvU3RyaW5nVGFnU3VwcG9ydCkge1xuICAgIHJlZGVmaW5lKE9iamVjdC5wcm90b3R5cGUsICd0b1N0cmluZycsIG9iamVjdFRvU3RyaW5nLCB7IHVuc2FmZTogdHJ1ZSB9KTtcbiAgfVxuXG4gIHZhciBIQVNfU1BFQ0lFU19TVVBQT1JUJDEgPSBhcnJheU1ldGhvZEhhc1NwZWNpZXNTdXBwb3J0KCdzbGljZScpO1xuXG4gIHZhciBTUEVDSUVTID0gd2VsbEtub3duU3ltYm9sKCdzcGVjaWVzJyk7XG4gIHZhciBuYXRpdmVTbGljZSA9IFtdLnNsaWNlO1xuICB2YXIgbWF4JDEgPSBNYXRoLm1heDtcblxuICAvLyBgQXJyYXkucHJvdG90eXBlLnNsaWNlYCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUuc2xpY2VcbiAgLy8gZmFsbGJhY2sgZm9yIG5vdCBhcnJheS1saWtlIEVTMyBzdHJpbmdzIGFuZCBET00gb2JqZWN0c1xuICBfZXhwb3J0KHsgdGFyZ2V0OiAnQXJyYXknLCBwcm90bzogdHJ1ZSwgZm9yY2VkOiAhSEFTX1NQRUNJRVNfU1VQUE9SVCQxIH0sIHtcbiAgICBzbGljZTogZnVuY3Rpb24gc2xpY2Uoc3RhcnQsIGVuZCkge1xuICAgICAgdmFyIE8gPSB0b0luZGV4ZWRPYmplY3QodGhpcyk7XG4gICAgICB2YXIgbGVuZ3RoID0gdG9MZW5ndGgoTy5sZW5ndGgpO1xuICAgICAgdmFyIGsgPSB0b0Fic29sdXRlSW5kZXgoc3RhcnQsIGxlbmd0aCk7XG4gICAgICB2YXIgZmluID0gdG9BYnNvbHV0ZUluZGV4KGVuZCA9PT0gdW5kZWZpbmVkID8gbGVuZ3RoIDogZW5kLCBsZW5ndGgpO1xuICAgICAgLy8gaW5saW5lIGBBcnJheVNwZWNpZXNDcmVhdGVgIGZvciB1c2FnZSBuYXRpdmUgYEFycmF5I3NsaWNlYCB3aGVyZSBpdCdzIHBvc3NpYmxlXG4gICAgICB2YXIgQ29uc3RydWN0b3IsIHJlc3VsdCwgbjtcbiAgICAgIGlmIChpc0FycmF5KE8pKSB7XG4gICAgICAgIENvbnN0cnVjdG9yID0gTy5jb25zdHJ1Y3RvcjtcbiAgICAgICAgLy8gY3Jvc3MtcmVhbG0gZmFsbGJhY2tcbiAgICAgICAgaWYgKHR5cGVvZiBDb25zdHJ1Y3RvciA9PSAnZnVuY3Rpb24nICYmIChDb25zdHJ1Y3RvciA9PT0gQXJyYXkgfHwgaXNBcnJheShDb25zdHJ1Y3Rvci5wcm90b3R5cGUpKSkge1xuICAgICAgICAgIENvbnN0cnVjdG9yID0gdW5kZWZpbmVkO1xuICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KENvbnN0cnVjdG9yKSkge1xuICAgICAgICAgIENvbnN0cnVjdG9yID0gQ29uc3RydWN0b3JbU1BFQ0lFU107XG4gICAgICAgICAgaWYgKENvbnN0cnVjdG9yID09PSBudWxsKSBDb25zdHJ1Y3RvciA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoQ29uc3RydWN0b3IgPT09IEFycmF5IHx8IENvbnN0cnVjdG9yID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICByZXR1cm4gbmF0aXZlU2xpY2UuY2FsbChPLCBrLCBmaW4pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXN1bHQgPSBuZXcgKENvbnN0cnVjdG9yID09PSB1bmRlZmluZWQgPyBBcnJheSA6IENvbnN0cnVjdG9yKShtYXgkMShmaW4gLSBrLCAwKSk7XG4gICAgICBmb3IgKG4gPSAwOyBrIDwgZmluOyBrKyssIG4rKykgaWYgKGsgaW4gTykgY3JlYXRlUHJvcGVydHkocmVzdWx0LCBuLCBPW2tdKTtcbiAgICAgIHJlc3VsdC5sZW5ndGggPSBuO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH0pO1xuXG4gIHZhciBjb3JyZWN0UHJvdG90eXBlR2V0dGVyID0gIWZhaWxzKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBGKCkgeyAvKiBlbXB0eSAqLyB9XG4gICAgRi5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBudWxsO1xuICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YobmV3IEYoKSkgIT09IEYucHJvdG90eXBlO1xuICB9KTtcblxuICB2YXIgSUVfUFJPVE8gPSBzaGFyZWRLZXkoJ0lFX1BST1RPJyk7XG4gIHZhciBPYmplY3RQcm90b3R5cGUgPSBPYmplY3QucHJvdG90eXBlO1xuXG4gIC8vIGBPYmplY3QuZ2V0UHJvdG90eXBlT2ZgIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9iamVjdC5nZXRwcm90b3R5cGVvZlxuICB2YXIgb2JqZWN0R2V0UHJvdG90eXBlT2YgPSBjb3JyZWN0UHJvdG90eXBlR2V0dGVyID8gT2JqZWN0LmdldFByb3RvdHlwZU9mIDogZnVuY3Rpb24gKE8pIHtcbiAgICBPID0gdG9PYmplY3QoTyk7XG4gICAgaWYgKGhhcyQxKE8sIElFX1BST1RPKSkgcmV0dXJuIE9bSUVfUFJPVE9dO1xuICAgIGlmICh0eXBlb2YgTy5jb25zdHJ1Y3RvciA9PSAnZnVuY3Rpb24nICYmIE8gaW5zdGFuY2VvZiBPLmNvbnN0cnVjdG9yKSB7XG4gICAgICByZXR1cm4gTy5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgfSByZXR1cm4gTyBpbnN0YW5jZW9mIE9iamVjdCA/IE9iamVjdFByb3RvdHlwZSA6IG51bGw7XG4gIH07XG5cbiAgdmFyIElURVJBVE9SJDIgPSB3ZWxsS25vd25TeW1ib2woJ2l0ZXJhdG9yJyk7XG4gIHZhciBCVUdHWV9TQUZBUklfSVRFUkFUT1JTJDEgPSBmYWxzZTtcblxuICB2YXIgcmV0dXJuVGhpcyQxID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfTtcblxuICAvLyBgJUl0ZXJhdG9yUHJvdG90eXBlJWAgb2JqZWN0XG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtJWl0ZXJhdG9ycHJvdG90eXBlJS1vYmplY3RcbiAgdmFyIEl0ZXJhdG9yUHJvdG90eXBlJDIsIFByb3RvdHlwZU9mQXJyYXlJdGVyYXRvclByb3RvdHlwZSwgYXJyYXlJdGVyYXRvcjtcblxuICBpZiAoW10ua2V5cykge1xuICAgIGFycmF5SXRlcmF0b3IgPSBbXS5rZXlzKCk7XG4gICAgLy8gU2FmYXJpIDggaGFzIGJ1Z2d5IGl0ZXJhdG9ycyB3L28gYG5leHRgXG4gICAgaWYgKCEoJ25leHQnIGluIGFycmF5SXRlcmF0b3IpKSBCVUdHWV9TQUZBUklfSVRFUkFUT1JTJDEgPSB0cnVlO1xuICAgIGVsc2Uge1xuICAgICAgUHJvdG90eXBlT2ZBcnJheUl0ZXJhdG9yUHJvdG90eXBlID0gb2JqZWN0R2V0UHJvdG90eXBlT2Yob2JqZWN0R2V0UHJvdG90eXBlT2YoYXJyYXlJdGVyYXRvcikpO1xuICAgICAgaWYgKFByb3RvdHlwZU9mQXJyYXlJdGVyYXRvclByb3RvdHlwZSAhPT0gT2JqZWN0LnByb3RvdHlwZSkgSXRlcmF0b3JQcm90b3R5cGUkMiA9IFByb3RvdHlwZU9mQXJyYXlJdGVyYXRvclByb3RvdHlwZTtcbiAgICB9XG4gIH1cblxuICB2YXIgTkVXX0lURVJBVE9SX1BST1RPVFlQRSA9IEl0ZXJhdG9yUHJvdG90eXBlJDIgPT0gdW5kZWZpbmVkIHx8IGZhaWxzKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgdGVzdCA9IHt9O1xuICAgIC8vIEZGNDQtIGxlZ2FjeSBpdGVyYXRvcnMgY2FzZVxuICAgIHJldHVybiBJdGVyYXRvclByb3RvdHlwZSQyW0lURVJBVE9SJDJdLmNhbGwodGVzdCkgIT09IHRlc3Q7XG4gIH0pO1xuXG4gIGlmIChORVdfSVRFUkFUT1JfUFJPVE9UWVBFKSBJdGVyYXRvclByb3RvdHlwZSQyID0ge307XG5cbiAgLy8gMjUuMS4yLjEuMSAlSXRlcmF0b3JQcm90b3R5cGUlW0BAaXRlcmF0b3JdKClcbiAgaWYgKCFoYXMkMShJdGVyYXRvclByb3RvdHlwZSQyLCBJVEVSQVRPUiQyKSkge1xuICAgIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eShJdGVyYXRvclByb3RvdHlwZSQyLCBJVEVSQVRPUiQyLCByZXR1cm5UaGlzJDEpO1xuICB9XG5cbiAgdmFyIGl0ZXJhdG9yc0NvcmUgPSB7XG4gICAgSXRlcmF0b3JQcm90b3R5cGU6IEl0ZXJhdG9yUHJvdG90eXBlJDIsXG4gICAgQlVHR1lfU0FGQVJJX0lURVJBVE9SUzogQlVHR1lfU0FGQVJJX0lURVJBVE9SUyQxXG4gIH07XG5cbiAgdmFyIGRlZmluZVByb3BlcnR5JDEgPSBvYmplY3REZWZpbmVQcm9wZXJ0eS5mO1xuXG5cblxuICB2YXIgVE9fU1RSSU5HX1RBRyQxID0gd2VsbEtub3duU3ltYm9sKCd0b1N0cmluZ1RhZycpO1xuXG4gIHZhciBzZXRUb1N0cmluZ1RhZyA9IGZ1bmN0aW9uIChpdCwgVEFHLCBTVEFUSUMpIHtcbiAgICBpZiAoaXQgJiYgIWhhcyQxKGl0ID0gU1RBVElDID8gaXQgOiBpdC5wcm90b3R5cGUsIFRPX1NUUklOR19UQUckMSkpIHtcbiAgICAgIGRlZmluZVByb3BlcnR5JDEoaXQsIFRPX1NUUklOR19UQUckMSwgeyBjb25maWd1cmFibGU6IHRydWUsIHZhbHVlOiBUQUcgfSk7XG4gICAgfVxuICB9O1xuXG4gIHZhciBJdGVyYXRvclByb3RvdHlwZSQxID0gaXRlcmF0b3JzQ29yZS5JdGVyYXRvclByb3RvdHlwZTtcblxuICB2YXIgY3JlYXRlSXRlcmF0b3JDb25zdHJ1Y3RvciA9IGZ1bmN0aW9uIChJdGVyYXRvckNvbnN0cnVjdG9yLCBOQU1FLCBuZXh0KSB7XG4gICAgdmFyIFRPX1NUUklOR19UQUcgPSBOQU1FICsgJyBJdGVyYXRvcic7XG4gICAgSXRlcmF0b3JDb25zdHJ1Y3Rvci5wcm90b3R5cGUgPSBvYmplY3RDcmVhdGUoSXRlcmF0b3JQcm90b3R5cGUkMSwgeyBuZXh0OiBjcmVhdGVQcm9wZXJ0eURlc2NyaXB0b3IoMSwgbmV4dCkgfSk7XG4gICAgc2V0VG9TdHJpbmdUYWcoSXRlcmF0b3JDb25zdHJ1Y3RvciwgVE9fU1RSSU5HX1RBRywgZmFsc2UpO1xuICAgIHJldHVybiBJdGVyYXRvckNvbnN0cnVjdG9yO1xuICB9O1xuXG4gIHZhciBJdGVyYXRvclByb3RvdHlwZSA9IGl0ZXJhdG9yc0NvcmUuSXRlcmF0b3JQcm90b3R5cGU7XG4gIHZhciBCVUdHWV9TQUZBUklfSVRFUkFUT1JTID0gaXRlcmF0b3JzQ29yZS5CVUdHWV9TQUZBUklfSVRFUkFUT1JTO1xuICB2YXIgSVRFUkFUT1IkMSA9IHdlbGxLbm93blN5bWJvbCgnaXRlcmF0b3InKTtcbiAgdmFyIEtFWVMgPSAna2V5cyc7XG4gIHZhciBWQUxVRVMgPSAndmFsdWVzJztcbiAgdmFyIEVOVFJJRVMgPSAnZW50cmllcyc7XG5cbiAgdmFyIHJldHVyblRoaXMgPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9O1xuXG4gIHZhciBkZWZpbmVJdGVyYXRvciA9IGZ1bmN0aW9uIChJdGVyYWJsZSwgTkFNRSwgSXRlcmF0b3JDb25zdHJ1Y3RvciwgbmV4dCwgREVGQVVMVCwgSVNfU0VULCBGT1JDRUQpIHtcbiAgICBjcmVhdGVJdGVyYXRvckNvbnN0cnVjdG9yKEl0ZXJhdG9yQ29uc3RydWN0b3IsIE5BTUUsIG5leHQpO1xuXG4gICAgdmFyIGdldEl0ZXJhdGlvbk1ldGhvZCA9IGZ1bmN0aW9uIChLSU5EKSB7XG4gICAgICBpZiAoS0lORCA9PT0gREVGQVVMVCAmJiBkZWZhdWx0SXRlcmF0b3IpIHJldHVybiBkZWZhdWx0SXRlcmF0b3I7XG4gICAgICBpZiAoIUJVR0dZX1NBRkFSSV9JVEVSQVRPUlMgJiYgS0lORCBpbiBJdGVyYWJsZVByb3RvdHlwZSkgcmV0dXJuIEl0ZXJhYmxlUHJvdG90eXBlW0tJTkRdO1xuICAgICAgc3dpdGNoIChLSU5EKSB7XG4gICAgICAgIGNhc2UgS0VZUzogcmV0dXJuIGZ1bmN0aW9uIGtleXMoKSB7IHJldHVybiBuZXcgSXRlcmF0b3JDb25zdHJ1Y3Rvcih0aGlzLCBLSU5EKTsgfTtcbiAgICAgICAgY2FzZSBWQUxVRVM6IHJldHVybiBmdW5jdGlvbiB2YWx1ZXMoKSB7IHJldHVybiBuZXcgSXRlcmF0b3JDb25zdHJ1Y3Rvcih0aGlzLCBLSU5EKTsgfTtcbiAgICAgICAgY2FzZSBFTlRSSUVTOiByZXR1cm4gZnVuY3Rpb24gZW50cmllcygpIHsgcmV0dXJuIG5ldyBJdGVyYXRvckNvbnN0cnVjdG9yKHRoaXMsIEtJTkQpOyB9O1xuICAgICAgfSByZXR1cm4gZnVuY3Rpb24gKCkgeyByZXR1cm4gbmV3IEl0ZXJhdG9yQ29uc3RydWN0b3IodGhpcyk7IH07XG4gICAgfTtcblxuICAgIHZhciBUT19TVFJJTkdfVEFHID0gTkFNRSArICcgSXRlcmF0b3InO1xuICAgIHZhciBJTkNPUlJFQ1RfVkFMVUVTX05BTUUgPSBmYWxzZTtcbiAgICB2YXIgSXRlcmFibGVQcm90b3R5cGUgPSBJdGVyYWJsZS5wcm90b3R5cGU7XG4gICAgdmFyIG5hdGl2ZUl0ZXJhdG9yID0gSXRlcmFibGVQcm90b3R5cGVbSVRFUkFUT1IkMV1cbiAgICAgIHx8IEl0ZXJhYmxlUHJvdG90eXBlWydAQGl0ZXJhdG9yJ11cbiAgICAgIHx8IERFRkFVTFQgJiYgSXRlcmFibGVQcm90b3R5cGVbREVGQVVMVF07XG4gICAgdmFyIGRlZmF1bHRJdGVyYXRvciA9ICFCVUdHWV9TQUZBUklfSVRFUkFUT1JTICYmIG5hdGl2ZUl0ZXJhdG9yIHx8IGdldEl0ZXJhdGlvbk1ldGhvZChERUZBVUxUKTtcbiAgICB2YXIgYW55TmF0aXZlSXRlcmF0b3IgPSBOQU1FID09ICdBcnJheScgPyBJdGVyYWJsZVByb3RvdHlwZS5lbnRyaWVzIHx8IG5hdGl2ZUl0ZXJhdG9yIDogbmF0aXZlSXRlcmF0b3I7XG4gICAgdmFyIEN1cnJlbnRJdGVyYXRvclByb3RvdHlwZSwgbWV0aG9kcywgS0VZO1xuXG4gICAgLy8gZml4IG5hdGl2ZVxuICAgIGlmIChhbnlOYXRpdmVJdGVyYXRvcikge1xuICAgICAgQ3VycmVudEl0ZXJhdG9yUHJvdG90eXBlID0gb2JqZWN0R2V0UHJvdG90eXBlT2YoYW55TmF0aXZlSXRlcmF0b3IuY2FsbChuZXcgSXRlcmFibGUoKSkpO1xuICAgICAgaWYgKEl0ZXJhdG9yUHJvdG90eXBlICE9PSBPYmplY3QucHJvdG90eXBlICYmIEN1cnJlbnRJdGVyYXRvclByb3RvdHlwZS5uZXh0KSB7XG4gICAgICAgIGlmIChvYmplY3RHZXRQcm90b3R5cGVPZihDdXJyZW50SXRlcmF0b3JQcm90b3R5cGUpICE9PSBJdGVyYXRvclByb3RvdHlwZSkge1xuICAgICAgICAgIGlmIChvYmplY3RTZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgb2JqZWN0U2V0UHJvdG90eXBlT2YoQ3VycmVudEl0ZXJhdG9yUHJvdG90eXBlLCBJdGVyYXRvclByb3RvdHlwZSk7XG4gICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgQ3VycmVudEl0ZXJhdG9yUHJvdG90eXBlW0lURVJBVE9SJDFdICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eShDdXJyZW50SXRlcmF0b3JQcm90b3R5cGUsIElURVJBVE9SJDEsIHJldHVyblRoaXMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBTZXQgQEB0b1N0cmluZ1RhZyB0byBuYXRpdmUgaXRlcmF0b3JzXG4gICAgICAgIHNldFRvU3RyaW5nVGFnKEN1cnJlbnRJdGVyYXRvclByb3RvdHlwZSwgVE9fU1RSSU5HX1RBRywgdHJ1ZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gZml4IEFycmF5I3t2YWx1ZXMsIEBAaXRlcmF0b3J9Lm5hbWUgaW4gVjggLyBGRlxuICAgIGlmIChERUZBVUxUID09IFZBTFVFUyAmJiBuYXRpdmVJdGVyYXRvciAmJiBuYXRpdmVJdGVyYXRvci5uYW1lICE9PSBWQUxVRVMpIHtcbiAgICAgIElOQ09SUkVDVF9WQUxVRVNfTkFNRSA9IHRydWU7XG4gICAgICBkZWZhdWx0SXRlcmF0b3IgPSBmdW5jdGlvbiB2YWx1ZXMoKSB7IHJldHVybiBuYXRpdmVJdGVyYXRvci5jYWxsKHRoaXMpOyB9O1xuICAgIH1cblxuICAgIC8vIGRlZmluZSBpdGVyYXRvclxuICAgIGlmIChJdGVyYWJsZVByb3RvdHlwZVtJVEVSQVRPUiQxXSAhPT0gZGVmYXVsdEl0ZXJhdG9yKSB7XG4gICAgICBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkoSXRlcmFibGVQcm90b3R5cGUsIElURVJBVE9SJDEsIGRlZmF1bHRJdGVyYXRvcik7XG4gICAgfVxuXG4gICAgLy8gZXhwb3J0IGFkZGl0aW9uYWwgbWV0aG9kc1xuICAgIGlmIChERUZBVUxUKSB7XG4gICAgICBtZXRob2RzID0ge1xuICAgICAgICB2YWx1ZXM6IGdldEl0ZXJhdGlvbk1ldGhvZChWQUxVRVMpLFxuICAgICAgICBrZXlzOiBJU19TRVQgPyBkZWZhdWx0SXRlcmF0b3IgOiBnZXRJdGVyYXRpb25NZXRob2QoS0VZUyksXG4gICAgICAgIGVudHJpZXM6IGdldEl0ZXJhdGlvbk1ldGhvZChFTlRSSUVTKVxuICAgICAgfTtcbiAgICAgIGlmIChGT1JDRUQpIGZvciAoS0VZIGluIG1ldGhvZHMpIHtcbiAgICAgICAgaWYgKEJVR0dZX1NBRkFSSV9JVEVSQVRPUlMgfHwgSU5DT1JSRUNUX1ZBTFVFU19OQU1FIHx8ICEoS0VZIGluIEl0ZXJhYmxlUHJvdG90eXBlKSkge1xuICAgICAgICAgIHJlZGVmaW5lKEl0ZXJhYmxlUHJvdG90eXBlLCBLRVksIG1ldGhvZHNbS0VZXSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBfZXhwb3J0KHsgdGFyZ2V0OiBOQU1FLCBwcm90bzogdHJ1ZSwgZm9yY2VkOiBCVUdHWV9TQUZBUklfSVRFUkFUT1JTIHx8IElOQ09SUkVDVF9WQUxVRVNfTkFNRSB9LCBtZXRob2RzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbWV0aG9kcztcbiAgfTtcblxuICB2YXIgQVJSQVlfSVRFUkFUT1IgPSAnQXJyYXkgSXRlcmF0b3InO1xuICB2YXIgc2V0SW50ZXJuYWxTdGF0ZSA9IGludGVybmFsU3RhdGUuc2V0O1xuICB2YXIgZ2V0SW50ZXJuYWxTdGF0ZSA9IGludGVybmFsU3RhdGUuZ2V0dGVyRm9yKEFSUkFZX0lURVJBVE9SKTtcblxuICAvLyBgQXJyYXkucHJvdG90eXBlLmVudHJpZXNgIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS5lbnRyaWVzXG4gIC8vIGBBcnJheS5wcm90b3R5cGUua2V5c2AgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLmtleXNcbiAgLy8gYEFycmF5LnByb3RvdHlwZS52YWx1ZXNgIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS52YWx1ZXNcbiAgLy8gYEFycmF5LnByb3RvdHlwZVtAQGl0ZXJhdG9yXWAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLUBAaXRlcmF0b3JcbiAgLy8gYENyZWF0ZUFycmF5SXRlcmF0b3JgIGludGVybmFsIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWNyZWF0ZWFycmF5aXRlcmF0b3JcbiAgdmFyIGVzX2FycmF5X2l0ZXJhdG9yID0gZGVmaW5lSXRlcmF0b3IoQXJyYXksICdBcnJheScsIGZ1bmN0aW9uIChpdGVyYXRlZCwga2luZCkge1xuICAgIHNldEludGVybmFsU3RhdGUodGhpcywge1xuICAgICAgdHlwZTogQVJSQVlfSVRFUkFUT1IsXG4gICAgICB0YXJnZXQ6IHRvSW5kZXhlZE9iamVjdChpdGVyYXRlZCksIC8vIHRhcmdldFxuICAgICAgaW5kZXg6IDAsICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBuZXh0IGluZGV4XG4gICAgICBraW5kOiBraW5kICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGtpbmRcbiAgICB9KTtcbiAgLy8gYCVBcnJheUl0ZXJhdG9yUHJvdG90eXBlJS5uZXh0YCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy0lYXJyYXlpdGVyYXRvcnByb3RvdHlwZSUubmV4dFxuICB9LCBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHN0YXRlID0gZ2V0SW50ZXJuYWxTdGF0ZSh0aGlzKTtcbiAgICB2YXIgdGFyZ2V0ID0gc3RhdGUudGFyZ2V0O1xuICAgIHZhciBraW5kID0gc3RhdGUua2luZDtcbiAgICB2YXIgaW5kZXggPSBzdGF0ZS5pbmRleCsrO1xuICAgIGlmICghdGFyZ2V0IHx8IGluZGV4ID49IHRhcmdldC5sZW5ndGgpIHtcbiAgICAgIHN0YXRlLnRhcmdldCA9IHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiB7IHZhbHVlOiB1bmRlZmluZWQsIGRvbmU6IHRydWUgfTtcbiAgICB9XG4gICAgaWYgKGtpbmQgPT0gJ2tleXMnKSByZXR1cm4geyB2YWx1ZTogaW5kZXgsIGRvbmU6IGZhbHNlIH07XG4gICAgaWYgKGtpbmQgPT0gJ3ZhbHVlcycpIHJldHVybiB7IHZhbHVlOiB0YXJnZXRbaW5kZXhdLCBkb25lOiBmYWxzZSB9O1xuICAgIHJldHVybiB7IHZhbHVlOiBbaW5kZXgsIHRhcmdldFtpbmRleF1dLCBkb25lOiBmYWxzZSB9O1xuICB9LCAndmFsdWVzJyk7XG5cbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUtQEB1bnNjb3BhYmxlc1xuICBhZGRUb1Vuc2NvcGFibGVzKCdrZXlzJyk7XG4gIGFkZFRvVW5zY29wYWJsZXMoJ3ZhbHVlcycpO1xuICBhZGRUb1Vuc2NvcGFibGVzKCdlbnRyaWVzJyk7XG5cbiAgdmFyIElURVJBVE9SID0gd2VsbEtub3duU3ltYm9sKCdpdGVyYXRvcicpO1xuICB2YXIgVE9fU1RSSU5HX1RBRyA9IHdlbGxLbm93blN5bWJvbCgndG9TdHJpbmdUYWcnKTtcbiAgdmFyIEFycmF5VmFsdWVzID0gZXNfYXJyYXlfaXRlcmF0b3IudmFsdWVzO1xuXG4gIGZvciAodmFyIENPTExFQ1RJT05fTkFNRSBpbiBkb21JdGVyYWJsZXMpIHtcbiAgICB2YXIgQ29sbGVjdGlvbiA9IGdsb2JhbF8xW0NPTExFQ1RJT05fTkFNRV07XG4gICAgdmFyIENvbGxlY3Rpb25Qcm90b3R5cGUgPSBDb2xsZWN0aW9uICYmIENvbGxlY3Rpb24ucHJvdG90eXBlO1xuICAgIGlmIChDb2xsZWN0aW9uUHJvdG90eXBlKSB7XG4gICAgICAvLyBzb21lIENocm9tZSB2ZXJzaW9ucyBoYXZlIG5vbi1jb25maWd1cmFibGUgbWV0aG9kcyBvbiBET01Ub2tlbkxpc3RcbiAgICAgIGlmIChDb2xsZWN0aW9uUHJvdG90eXBlW0lURVJBVE9SXSAhPT0gQXJyYXlWYWx1ZXMpIHRyeSB7XG4gICAgICAgIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eShDb2xsZWN0aW9uUHJvdG90eXBlLCBJVEVSQVRPUiwgQXJyYXlWYWx1ZXMpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgQ29sbGVjdGlvblByb3RvdHlwZVtJVEVSQVRPUl0gPSBBcnJheVZhbHVlcztcbiAgICAgIH1cbiAgICAgIGlmICghQ29sbGVjdGlvblByb3RvdHlwZVtUT19TVFJJTkdfVEFHXSkge1xuICAgICAgICBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkoQ29sbGVjdGlvblByb3RvdHlwZSwgVE9fU1RSSU5HX1RBRywgQ09MTEVDVElPTl9OQU1FKTtcbiAgICAgIH1cbiAgICAgIGlmIChkb21JdGVyYWJsZXNbQ09MTEVDVElPTl9OQU1FXSkgZm9yICh2YXIgTUVUSE9EX05BTUUgaW4gZXNfYXJyYXlfaXRlcmF0b3IpIHtcbiAgICAgICAgLy8gc29tZSBDaHJvbWUgdmVyc2lvbnMgaGF2ZSBub24tY29uZmlndXJhYmxlIG1ldGhvZHMgb24gRE9NVG9rZW5MaXN0XG4gICAgICAgIGlmIChDb2xsZWN0aW9uUHJvdG90eXBlW01FVEhPRF9OQU1FXSAhPT0gZXNfYXJyYXlfaXRlcmF0b3JbTUVUSE9EX05BTUVdKSB0cnkge1xuICAgICAgICAgIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eShDb2xsZWN0aW9uUHJvdG90eXBlLCBNRVRIT0RfTkFNRSwgZXNfYXJyYXlfaXRlcmF0b3JbTUVUSE9EX05BTUVdKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBDb2xsZWN0aW9uUHJvdG90eXBlW01FVEhPRF9OQU1FXSA9IGVzX2FycmF5X2l0ZXJhdG9yW01FVEhPRF9OQU1FXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHZhciBIQVNfU1BFQ0lFU19TVVBQT1JUID0gYXJyYXlNZXRob2RIYXNTcGVjaWVzU3VwcG9ydCgnc3BsaWNlJyk7XG5cbiAgdmFyIG1heCA9IE1hdGgubWF4O1xuICB2YXIgbWluJDIgPSBNYXRoLm1pbjtcbiAgdmFyIE1BWF9TQUZFX0lOVEVHRVIgPSAweDFGRkZGRkZGRkZGRkZGO1xuICB2YXIgTUFYSU1VTV9BTExPV0VEX0xFTkdUSF9FWENFRURFRCA9ICdNYXhpbXVtIGFsbG93ZWQgbGVuZ3RoIGV4Y2VlZGVkJztcblxuICAvLyBgQXJyYXkucHJvdG90eXBlLnNwbGljZWAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLnNwbGljZVxuICAvLyB3aXRoIGFkZGluZyBzdXBwb3J0IG9mIEBAc3BlY2llc1xuICBfZXhwb3J0KHsgdGFyZ2V0OiAnQXJyYXknLCBwcm90bzogdHJ1ZSwgZm9yY2VkOiAhSEFTX1NQRUNJRVNfU1VQUE9SVCB9LCB7XG4gICAgc3BsaWNlOiBmdW5jdGlvbiBzcGxpY2Uoc3RhcnQsIGRlbGV0ZUNvdW50IC8qICwgLi4uaXRlbXMgKi8pIHtcbiAgICAgIHZhciBPID0gdG9PYmplY3QodGhpcyk7XG4gICAgICB2YXIgbGVuID0gdG9MZW5ndGgoTy5sZW5ndGgpO1xuICAgICAgdmFyIGFjdHVhbFN0YXJ0ID0gdG9BYnNvbHV0ZUluZGV4KHN0YXJ0LCBsZW4pO1xuICAgICAgdmFyIGFyZ3VtZW50c0xlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgICB2YXIgaW5zZXJ0Q291bnQsIGFjdHVhbERlbGV0ZUNvdW50LCBBLCBrLCBmcm9tLCB0bztcbiAgICAgIGlmIChhcmd1bWVudHNMZW5ndGggPT09IDApIHtcbiAgICAgICAgaW5zZXJ0Q291bnQgPSBhY3R1YWxEZWxldGVDb3VudCA9IDA7XG4gICAgICB9IGVsc2UgaWYgKGFyZ3VtZW50c0xlbmd0aCA9PT0gMSkge1xuICAgICAgICBpbnNlcnRDb3VudCA9IDA7XG4gICAgICAgIGFjdHVhbERlbGV0ZUNvdW50ID0gbGVuIC0gYWN0dWFsU3RhcnQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpbnNlcnRDb3VudCA9IGFyZ3VtZW50c0xlbmd0aCAtIDI7XG4gICAgICAgIGFjdHVhbERlbGV0ZUNvdW50ID0gbWluJDIobWF4KHRvSW50ZWdlcihkZWxldGVDb3VudCksIDApLCBsZW4gLSBhY3R1YWxTdGFydCk7XG4gICAgICB9XG4gICAgICBpZiAobGVuICsgaW5zZXJ0Q291bnQgLSBhY3R1YWxEZWxldGVDb3VudCA+IE1BWF9TQUZFX0lOVEVHRVIpIHtcbiAgICAgICAgdGhyb3cgVHlwZUVycm9yKE1BWElNVU1fQUxMT1dFRF9MRU5HVEhfRVhDRUVERUQpO1xuICAgICAgfVxuICAgICAgQSA9IGFycmF5U3BlY2llc0NyZWF0ZShPLCBhY3R1YWxEZWxldGVDb3VudCk7XG4gICAgICBmb3IgKGsgPSAwOyBrIDwgYWN0dWFsRGVsZXRlQ291bnQ7IGsrKykge1xuICAgICAgICBmcm9tID0gYWN0dWFsU3RhcnQgKyBrO1xuICAgICAgICBpZiAoZnJvbSBpbiBPKSBjcmVhdGVQcm9wZXJ0eShBLCBrLCBPW2Zyb21dKTtcbiAgICAgIH1cbiAgICAgIEEubGVuZ3RoID0gYWN0dWFsRGVsZXRlQ291bnQ7XG4gICAgICBpZiAoaW5zZXJ0Q291bnQgPCBhY3R1YWxEZWxldGVDb3VudCkge1xuICAgICAgICBmb3IgKGsgPSBhY3R1YWxTdGFydDsgayA8IGxlbiAtIGFjdHVhbERlbGV0ZUNvdW50OyBrKyspIHtcbiAgICAgICAgICBmcm9tID0gayArIGFjdHVhbERlbGV0ZUNvdW50O1xuICAgICAgICAgIHRvID0gayArIGluc2VydENvdW50O1xuICAgICAgICAgIGlmIChmcm9tIGluIE8pIE9bdG9dID0gT1tmcm9tXTtcbiAgICAgICAgICBlbHNlIGRlbGV0ZSBPW3RvXTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGsgPSBsZW47IGsgPiBsZW4gLSBhY3R1YWxEZWxldGVDb3VudCArIGluc2VydENvdW50OyBrLS0pIGRlbGV0ZSBPW2sgLSAxXTtcbiAgICAgIH0gZWxzZSBpZiAoaW5zZXJ0Q291bnQgPiBhY3R1YWxEZWxldGVDb3VudCkge1xuICAgICAgICBmb3IgKGsgPSBsZW4gLSBhY3R1YWxEZWxldGVDb3VudDsgayA+IGFjdHVhbFN0YXJ0OyBrLS0pIHtcbiAgICAgICAgICBmcm9tID0gayArIGFjdHVhbERlbGV0ZUNvdW50IC0gMTtcbiAgICAgICAgICB0byA9IGsgKyBpbnNlcnRDb3VudCAtIDE7XG4gICAgICAgICAgaWYgKGZyb20gaW4gTykgT1t0b10gPSBPW2Zyb21dO1xuICAgICAgICAgIGVsc2UgZGVsZXRlIE9bdG9dO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmb3IgKGsgPSAwOyBrIDwgaW5zZXJ0Q291bnQ7IGsrKykge1xuICAgICAgICBPW2sgKyBhY3R1YWxTdGFydF0gPSBhcmd1bWVudHNbayArIDJdO1xuICAgICAgfVxuICAgICAgTy5sZW5ndGggPSBsZW4gLSBhY3R1YWxEZWxldGVDb3VudCArIGluc2VydENvdW50O1xuICAgICAgcmV0dXJuIEE7XG4gICAgfVxuICB9KTtcblxuICB2YXIgZ2V0T3duUHJvcGVydHlOYW1lcyA9IG9iamVjdEdldE93blByb3BlcnR5TmFtZXMuZjtcbiAgdmFyIGdldE93blByb3BlcnR5RGVzY3JpcHRvciQyID0gb2JqZWN0R2V0T3duUHJvcGVydHlEZXNjcmlwdG9yLmY7XG4gIHZhciBkZWZpbmVQcm9wZXJ0eSA9IG9iamVjdERlZmluZVByb3BlcnR5LmY7XG4gIHZhciB0cmltID0gc3RyaW5nVHJpbS50cmltO1xuXG4gIHZhciBOVU1CRVIgPSAnTnVtYmVyJztcbiAgdmFyIE5hdGl2ZU51bWJlciA9IGdsb2JhbF8xW05VTUJFUl07XG4gIHZhciBOdW1iZXJQcm90b3R5cGUgPSBOYXRpdmVOdW1iZXIucHJvdG90eXBlO1xuXG4gIC8vIE9wZXJhIH4xMiBoYXMgYnJva2VuIE9iamVjdCN0b1N0cmluZ1xuICB2YXIgQlJPS0VOX0NMQVNTT0YgPSBjbGFzc29mUmF3KG9iamVjdENyZWF0ZShOdW1iZXJQcm90b3R5cGUpKSA9PSBOVU1CRVI7XG5cbiAgLy8gYFRvTnVtYmVyYCBhYnN0cmFjdCBvcGVyYXRpb25cbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy10b251bWJlclxuICB2YXIgdG9OdW1iZXIgPSBmdW5jdGlvbiAoYXJndW1lbnQpIHtcbiAgICB2YXIgaXQgPSB0b1ByaW1pdGl2ZShhcmd1bWVudCwgZmFsc2UpO1xuICAgIHZhciBmaXJzdCwgdGhpcmQsIHJhZGl4LCBtYXhDb2RlLCBkaWdpdHMsIGxlbmd0aCwgaW5kZXgsIGNvZGU7XG4gICAgaWYgKHR5cGVvZiBpdCA9PSAnc3RyaW5nJyAmJiBpdC5sZW5ndGggPiAyKSB7XG4gICAgICBpdCA9IHRyaW0oaXQpO1xuICAgICAgZmlyc3QgPSBpdC5jaGFyQ29kZUF0KDApO1xuICAgICAgaWYgKGZpcnN0ID09PSA0MyB8fCBmaXJzdCA9PT0gNDUpIHtcbiAgICAgICAgdGhpcmQgPSBpdC5jaGFyQ29kZUF0KDIpO1xuICAgICAgICBpZiAodGhpcmQgPT09IDg4IHx8IHRoaXJkID09PSAxMjApIHJldHVybiBOYU47IC8vIE51bWJlcignKzB4MScpIHNob3VsZCBiZSBOYU4sIG9sZCBWOCBmaXhcbiAgICAgIH0gZWxzZSBpZiAoZmlyc3QgPT09IDQ4KSB7XG4gICAgICAgIHN3aXRjaCAoaXQuY2hhckNvZGVBdCgxKSkge1xuICAgICAgICAgIGNhc2UgNjY6IGNhc2UgOTg6IHJhZGl4ID0gMjsgbWF4Q29kZSA9IDQ5OyBicmVhazsgLy8gZmFzdCBlcXVhbCBvZiAvXjBiWzAxXSskL2lcbiAgICAgICAgICBjYXNlIDc5OiBjYXNlIDExMTogcmFkaXggPSA4OyBtYXhDb2RlID0gNTU7IGJyZWFrOyAvLyBmYXN0IGVxdWFsIG9mIC9eMG9bMC03XSskL2lcbiAgICAgICAgICBkZWZhdWx0OiByZXR1cm4gK2l0O1xuICAgICAgICB9XG4gICAgICAgIGRpZ2l0cyA9IGl0LnNsaWNlKDIpO1xuICAgICAgICBsZW5ndGggPSBkaWdpdHMubGVuZ3RoO1xuICAgICAgICBmb3IgKGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHtcbiAgICAgICAgICBjb2RlID0gZGlnaXRzLmNoYXJDb2RlQXQoaW5kZXgpO1xuICAgICAgICAgIC8vIHBhcnNlSW50IHBhcnNlcyBhIHN0cmluZyB0byBhIGZpcnN0IHVuYXZhaWxhYmxlIHN5bWJvbFxuICAgICAgICAgIC8vIGJ1dCBUb051bWJlciBzaG91bGQgcmV0dXJuIE5hTiBpZiBhIHN0cmluZyBjb250YWlucyB1bmF2YWlsYWJsZSBzeW1ib2xzXG4gICAgICAgICAgaWYgKGNvZGUgPCA0OCB8fCBjb2RlID4gbWF4Q29kZSkgcmV0dXJuIE5hTjtcbiAgICAgICAgfSByZXR1cm4gcGFyc2VJbnQoZGlnaXRzLCByYWRpeCk7XG4gICAgICB9XG4gICAgfSByZXR1cm4gK2l0O1xuICB9O1xuXG4gIC8vIGBOdW1iZXJgIGNvbnN0cnVjdG9yXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtbnVtYmVyLWNvbnN0cnVjdG9yXG4gIGlmIChpc0ZvcmNlZF8xKE5VTUJFUiwgIU5hdGl2ZU51bWJlcignIDBvMScpIHx8ICFOYXRpdmVOdW1iZXIoJzBiMScpIHx8IE5hdGl2ZU51bWJlcignKzB4MScpKSkge1xuICAgIHZhciBOdW1iZXJXcmFwcGVyID0gZnVuY3Rpb24gTnVtYmVyKHZhbHVlKSB7XG4gICAgICB2YXIgaXQgPSBhcmd1bWVudHMubGVuZ3RoIDwgMSA/IDAgOiB2YWx1ZTtcbiAgICAgIHZhciBkdW1teSA9IHRoaXM7XG4gICAgICByZXR1cm4gZHVtbXkgaW5zdGFuY2VvZiBOdW1iZXJXcmFwcGVyXG4gICAgICAgIC8vIGNoZWNrIG9uIDEuLmNvbnN0cnVjdG9yKGZvbykgY2FzZVxuICAgICAgICAmJiAoQlJPS0VOX0NMQVNTT0YgPyBmYWlscyhmdW5jdGlvbiAoKSB7IE51bWJlclByb3RvdHlwZS52YWx1ZU9mLmNhbGwoZHVtbXkpOyB9KSA6IGNsYXNzb2ZSYXcoZHVtbXkpICE9IE5VTUJFUilcbiAgICAgICAgICA/IGluaGVyaXRJZlJlcXVpcmVkKG5ldyBOYXRpdmVOdW1iZXIodG9OdW1iZXIoaXQpKSwgZHVtbXksIE51bWJlcldyYXBwZXIpIDogdG9OdW1iZXIoaXQpO1xuICAgIH07XG4gICAgZm9yICh2YXIga2V5cyA9IGRlc2NyaXB0b3JzID8gZ2V0T3duUHJvcGVydHlOYW1lcyhOYXRpdmVOdW1iZXIpIDogKFxuICAgICAgLy8gRVMzOlxuICAgICAgJ01BWF9WQUxVRSxNSU5fVkFMVUUsTmFOLE5FR0FUSVZFX0lORklOSVRZLFBPU0lUSVZFX0lORklOSVRZLCcgK1xuICAgICAgLy8gRVMyMDE1IChpbiBjYXNlLCBpZiBtb2R1bGVzIHdpdGggRVMyMDE1IE51bWJlciBzdGF0aWNzIHJlcXVpcmVkIGJlZm9yZSk6XG4gICAgICAnRVBTSUxPTixpc0Zpbml0ZSxpc0ludGVnZXIsaXNOYU4saXNTYWZlSW50ZWdlcixNQVhfU0FGRV9JTlRFR0VSLCcgK1xuICAgICAgJ01JTl9TQUZFX0lOVEVHRVIscGFyc2VGbG9hdCxwYXJzZUludCxpc0ludGVnZXIsJyArXG4gICAgICAvLyBFU05leHRcbiAgICAgICdmcm9tU3RyaW5nLHJhbmdlJ1xuICAgICkuc3BsaXQoJywnKSwgaiA9IDAsIGtleTsga2V5cy5sZW5ndGggPiBqOyBqKyspIHtcbiAgICAgIGlmIChoYXMkMShOYXRpdmVOdW1iZXIsIGtleSA9IGtleXNbal0pICYmICFoYXMkMShOdW1iZXJXcmFwcGVyLCBrZXkpKSB7XG4gICAgICAgIGRlZmluZVByb3BlcnR5KE51bWJlcldyYXBwZXIsIGtleSwgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yJDIoTmF0aXZlTnVtYmVyLCBrZXkpKTtcbiAgICAgIH1cbiAgICB9XG4gICAgTnVtYmVyV3JhcHBlci5wcm90b3R5cGUgPSBOdW1iZXJQcm90b3R5cGU7XG4gICAgTnVtYmVyUHJvdG90eXBlLmNvbnN0cnVjdG9yID0gTnVtYmVyV3JhcHBlcjtcbiAgICByZWRlZmluZShnbG9iYWxfMSwgTlVNQkVSLCBOdW1iZXJXcmFwcGVyKTtcbiAgfVxuXG4gIHZhciBuYXRpdmVSZXZlcnNlID0gW10ucmV2ZXJzZTtcbiAgdmFyIHRlc3QgPSBbMSwgMl07XG5cbiAgLy8gYEFycmF5LnByb3RvdHlwZS5yZXZlcnNlYCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUucmV2ZXJzZVxuICAvLyBmaXggZm9yIFNhZmFyaSAxMi4wIGJ1Z1xuICAvLyBodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTg4Nzk0XG4gIF9leHBvcnQoeyB0YXJnZXQ6ICdBcnJheScsIHByb3RvOiB0cnVlLCBmb3JjZWQ6IFN0cmluZyh0ZXN0KSA9PT0gU3RyaW5nKHRlc3QucmV2ZXJzZSgpKSB9LCB7XG4gICAgcmV2ZXJzZTogZnVuY3Rpb24gcmV2ZXJzZSgpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1zZWxmLWFzc2lnbiAtLSBkaXJ0eSBoYWNrXG4gICAgICBpZiAoaXNBcnJheSh0aGlzKSkgdGhpcy5sZW5ndGggPSB0aGlzLmxlbmd0aDtcbiAgICAgIHJldHVybiBuYXRpdmVSZXZlcnNlLmNhbGwodGhpcyk7XG4gICAgfVxuICB9KTtcblxuICAvKiBlc2xpbnQtZGlzYWJsZSBuby11bnVzZWQtdmFycyAqL1xuXG4gIHZhciBWRVJTSU9OID0gJzEuMTguMyc7XG4gIHZhciBib290c3RyYXBWZXJzaW9uID0gNDtcblxuICB0cnkge1xuICAgIHZhciByYXdWZXJzaW9uID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddLmZuLmRyb3Bkb3duLkNvbnN0cnVjdG9yLlZFUlNJT047IC8vIE9ubHkgdHJ5IHRvIHBhcnNlIFZFUlNJT04gaWYgaXQgaXMgZGVmaW5lZC5cbiAgICAvLyBJdCBpcyB1bmRlZmluZWQgaW4gb2xkZXIgdmVyc2lvbnMgb2YgQm9vdHN0cmFwICh0ZXN0ZWQgd2l0aCAzLjEuMSkuXG5cbiAgICBpZiAocmF3VmVyc2lvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBib290c3RyYXBWZXJzaW9uID0gcGFyc2VJbnQocmF3VmVyc2lvbiwgMTApO1xuICAgIH1cbiAgfSBjYXRjaCAoZSkgey8vIGlnbm9yZVxuICB9XG5cbiAgdHJ5IHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW5kZWZcbiAgICB2YXIgX3Jhd1ZlcnNpb24gPSBib290c3RyYXAuVG9vbHRpcC5WRVJTSU9OO1xuXG4gICAgaWYgKF9yYXdWZXJzaW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGJvb3RzdHJhcFZlcnNpb24gPSBwYXJzZUludChfcmF3VmVyc2lvbiwgMTApO1xuICAgIH1cbiAgfSBjYXRjaCAoZSkgey8vIGlnbm9yZVxuICB9XG5cbiAgdmFyIENPTlNUQU5UUyA9IHtcbiAgICAzOiB7XG4gICAgICBpY29uc1ByZWZpeDogJ2dseXBoaWNvbicsXG4gICAgICBpY29uczoge1xuICAgICAgICBwYWdpbmF0aW9uU3dpdGNoRG93bjogJ2dseXBoaWNvbi1jb2xsYXBzZS1kb3duIGljb24tY2hldnJvbi1kb3duJyxcbiAgICAgICAgcGFnaW5hdGlvblN3aXRjaFVwOiAnZ2x5cGhpY29uLWNvbGxhcHNlLXVwIGljb24tY2hldnJvbi11cCcsXG4gICAgICAgIHJlZnJlc2g6ICdnbHlwaGljb24tcmVmcmVzaCBpY29uLXJlZnJlc2gnLFxuICAgICAgICB0b2dnbGVPZmY6ICdnbHlwaGljb24tbGlzdC1hbHQgaWNvbi1saXN0LWFsdCcsXG4gICAgICAgIHRvZ2dsZU9uOiAnZ2x5cGhpY29uLWxpc3QtYWx0IGljb24tbGlzdC1hbHQnLFxuICAgICAgICBjb2x1bW5zOiAnZ2x5cGhpY29uLXRoIGljb24tdGgnLFxuICAgICAgICBkZXRhaWxPcGVuOiAnZ2x5cGhpY29uLXBsdXMgaWNvbi1wbHVzJyxcbiAgICAgICAgZGV0YWlsQ2xvc2U6ICdnbHlwaGljb24tbWludXMgaWNvbi1taW51cycsXG4gICAgICAgIGZ1bGxzY3JlZW46ICdnbHlwaGljb24tZnVsbHNjcmVlbicsXG4gICAgICAgIHNlYXJjaDogJ2dseXBoaWNvbi1zZWFyY2gnLFxuICAgICAgICBjbGVhclNlYXJjaDogJ2dseXBoaWNvbi10cmFzaCdcbiAgICAgIH0sXG4gICAgICBjbGFzc2VzOiB7XG4gICAgICAgIGJ1dHRvbnNQcmVmaXg6ICdidG4nLFxuICAgICAgICBidXR0b25zOiAnZGVmYXVsdCcsXG4gICAgICAgIGJ1dHRvbnNHcm91cDogJ2J0bi1ncm91cCcsXG4gICAgICAgIGJ1dHRvbnNEcm9wZG93bjogJ2J0bi1ncm91cCcsXG4gICAgICAgIHB1bGw6ICdwdWxsJyxcbiAgICAgICAgaW5wdXRHcm91cDogJ2lucHV0LWdyb3VwJyxcbiAgICAgICAgaW5wdXRQcmVmaXg6ICdpbnB1dC0nLFxuICAgICAgICBpbnB1dDogJ2Zvcm0tY29udHJvbCcsXG4gICAgICAgIHBhZ2luYXRpb25Ecm9wZG93bjogJ2J0bi1ncm91cCBkcm9wZG93bicsXG4gICAgICAgIGRyb3B1cDogJ2Ryb3B1cCcsXG4gICAgICAgIGRyb3Bkb3duQWN0aXZlOiAnYWN0aXZlJyxcbiAgICAgICAgcGFnaW5hdGlvbkFjdGl2ZTogJ2FjdGl2ZScsXG4gICAgICAgIGJ1dHRvbkFjdGl2ZTogJ2FjdGl2ZSdcbiAgICAgIH0sXG4gICAgICBodG1sOiB7XG4gICAgICAgIHRvb2xiYXJEcm9wZG93bjogWyc8dWwgY2xhc3M9XCJkcm9wZG93bi1tZW51XCIgcm9sZT1cIm1lbnVcIj4nLCAnPC91bD4nXSxcbiAgICAgICAgdG9vbGJhckRyb3Bkb3duSXRlbTogJzxsaSBjbGFzcz1cImRyb3Bkb3duLWl0ZW0tbWFya2VyXCIgcm9sZT1cIm1lbnVpdGVtXCI+PGxhYmVsPiVzPC9sYWJlbD48L2xpPicsXG4gICAgICAgIHRvb2xiYXJEcm9wZG93blNlcGFyYXRvcjogJzxsaSBjbGFzcz1cImRpdmlkZXJcIj48L2xpPicsXG4gICAgICAgIHBhZ2VEcm9wZG93bjogWyc8dWwgY2xhc3M9XCJkcm9wZG93bi1tZW51XCIgcm9sZT1cIm1lbnVcIj4nLCAnPC91bD4nXSxcbiAgICAgICAgcGFnZURyb3Bkb3duSXRlbTogJzxsaSByb2xlPVwibWVudWl0ZW1cIiBjbGFzcz1cIiVzXCI+PGEgaHJlZj1cIiNcIj4lczwvYT48L2xpPicsXG4gICAgICAgIGRyb3Bkb3duQ2FyZXQ6ICc8c3BhbiBjbGFzcz1cImNhcmV0XCI+PC9zcGFuPicsXG4gICAgICAgIHBhZ2luYXRpb246IFsnPHVsIGNsYXNzPVwicGFnaW5hdGlvbiVzXCI+JywgJzwvdWw+J10sXG4gICAgICAgIHBhZ2luYXRpb25JdGVtOiAnPGxpIGNsYXNzPVwicGFnZS1pdGVtJXNcIj48YSBjbGFzcz1cInBhZ2UtbGlua1wiIGFyaWEtbGFiZWw9XCIlc1wiIGhyZWY9XCJqYXZhc2NyaXB0OnZvaWQoMClcIj4lczwvYT48L2xpPicsXG4gICAgICAgIGljb246ICc8aSBjbGFzcz1cIiVzICVzXCI+PC9pPicsXG4gICAgICAgIGlucHV0R3JvdXA6ICc8ZGl2IGNsYXNzPVwiaW5wdXQtZ3JvdXBcIj4lczxzcGFuIGNsYXNzPVwiaW5wdXQtZ3JvdXAtYnRuXCI+JXM8L3NwYW4+PC9kaXY+JyxcbiAgICAgICAgc2VhcmNoSW5wdXQ6ICc8aW5wdXQgY2xhc3M9XCIlcyVzXCIgdHlwZT1cInRleHRcIiBwbGFjZWhvbGRlcj1cIiVzXCI+JyxcbiAgICAgICAgc2VhcmNoQnV0dG9uOiAnPGJ1dHRvbiBjbGFzcz1cIiVzXCIgdHlwZT1cImJ1dHRvblwiIG5hbWU9XCJzZWFyY2hcIiB0aXRsZT1cIiVzXCI+JXMgJXM8L2J1dHRvbj4nLFxuICAgICAgICBzZWFyY2hDbGVhckJ1dHRvbjogJzxidXR0b24gY2xhc3M9XCIlc1wiIHR5cGU9XCJidXR0b25cIiBuYW1lPVwiY2xlYXJTZWFyY2hcIiB0aXRsZT1cIiVzXCI+JXMgJXM8L2J1dHRvbj4nXG4gICAgICB9XG4gICAgfSxcbiAgICA0OiB7XG4gICAgICBpY29uc1ByZWZpeDogJ2ZhJyxcbiAgICAgIGljb25zOiB7XG4gICAgICAgIHBhZ2luYXRpb25Td2l0Y2hEb3duOiAnZmEtY2FyZXQtc3F1YXJlLWRvd24nLFxuICAgICAgICBwYWdpbmF0aW9uU3dpdGNoVXA6ICdmYS1jYXJldC1zcXVhcmUtdXAnLFxuICAgICAgICByZWZyZXNoOiAnZmEtc3luYycsXG4gICAgICAgIHRvZ2dsZU9mZjogJ2ZhLXRvZ2dsZS1vZmYnLFxuICAgICAgICB0b2dnbGVPbjogJ2ZhLXRvZ2dsZS1vbicsXG4gICAgICAgIGNvbHVtbnM6ICdmYS10aC1saXN0JyxcbiAgICAgICAgZGV0YWlsT3BlbjogJ2ZhLXBsdXMnLFxuICAgICAgICBkZXRhaWxDbG9zZTogJ2ZhLW1pbnVzJyxcbiAgICAgICAgZnVsbHNjcmVlbjogJ2ZhLWFycm93cy1hbHQnLFxuICAgICAgICBzZWFyY2g6ICdmYS1zZWFyY2gnLFxuICAgICAgICBjbGVhclNlYXJjaDogJ2ZhLXRyYXNoJ1xuICAgICAgfSxcbiAgICAgIGNsYXNzZXM6IHtcbiAgICAgICAgYnV0dG9uc1ByZWZpeDogJ2J0bicsXG4gICAgICAgIGJ1dHRvbnM6ICdzZWNvbmRhcnknLFxuICAgICAgICBidXR0b25zR3JvdXA6ICdidG4tZ3JvdXAnLFxuICAgICAgICBidXR0b25zRHJvcGRvd246ICdidG4tZ3JvdXAnLFxuICAgICAgICBwdWxsOiAnZmxvYXQnLFxuICAgICAgICBpbnB1dEdyb3VwOiAnYnRuLWdyb3VwJyxcbiAgICAgICAgaW5wdXRQcmVmaXg6ICdmb3JtLWNvbnRyb2wtJyxcbiAgICAgICAgaW5wdXQ6ICdmb3JtLWNvbnRyb2wnLFxuICAgICAgICBwYWdpbmF0aW9uRHJvcGRvd246ICdidG4tZ3JvdXAgZHJvcGRvd24nLFxuICAgICAgICBkcm9wdXA6ICdkcm9wdXAnLFxuICAgICAgICBkcm9wZG93bkFjdGl2ZTogJ2FjdGl2ZScsXG4gICAgICAgIHBhZ2luYXRpb25BY3RpdmU6ICdhY3RpdmUnLFxuICAgICAgICBidXR0b25BY3RpdmU6ICdhY3RpdmUnXG4gICAgICB9LFxuICAgICAgaHRtbDoge1xuICAgICAgICB0b29sYmFyRHJvcGRvd246IFsnPGRpdiBjbGFzcz1cImRyb3Bkb3duLW1lbnUgZHJvcGRvd24tbWVudS1yaWdodFwiPicsICc8L2Rpdj4nXSxcbiAgICAgICAgdG9vbGJhckRyb3Bkb3duSXRlbTogJzxsYWJlbCBjbGFzcz1cImRyb3Bkb3duLWl0ZW0gZHJvcGRvd24taXRlbS1tYXJrZXJcIj4lczwvbGFiZWw+JyxcbiAgICAgICAgcGFnZURyb3Bkb3duOiBbJzxkaXYgY2xhc3M9XCJkcm9wZG93bi1tZW51XCI+JywgJzwvZGl2PiddLFxuICAgICAgICBwYWdlRHJvcGRvd25JdGVtOiAnPGEgY2xhc3M9XCJkcm9wZG93bi1pdGVtICVzXCIgaHJlZj1cIiNcIj4lczwvYT4nLFxuICAgICAgICB0b29sYmFyRHJvcGRvd25TZXBhcmF0b3I6ICc8ZGl2IGNsYXNzPVwiZHJvcGRvd24tZGl2aWRlclwiPjwvZGl2PicsXG4gICAgICAgIGRyb3Bkb3duQ2FyZXQ6ICc8c3BhbiBjbGFzcz1cImNhcmV0XCI+PC9zcGFuPicsXG4gICAgICAgIHBhZ2luYXRpb246IFsnPHVsIGNsYXNzPVwicGFnaW5hdGlvbiVzXCI+JywgJzwvdWw+J10sXG4gICAgICAgIHBhZ2luYXRpb25JdGVtOiAnPGxpIGNsYXNzPVwicGFnZS1pdGVtJXNcIj48YSBjbGFzcz1cInBhZ2UtbGlua1wiIGFyaWEtbGFiZWw9XCIlc1wiIGhyZWY9XCJqYXZhc2NyaXB0OnZvaWQoMClcIj4lczwvYT48L2xpPicsXG4gICAgICAgIGljb246ICc8aSBjbGFzcz1cIiVzICVzXCI+PC9pPicsXG4gICAgICAgIGlucHV0R3JvdXA6ICc8ZGl2IGNsYXNzPVwiaW5wdXQtZ3JvdXBcIj4lczxkaXYgY2xhc3M9XCJpbnB1dC1ncm91cC1hcHBlbmRcIj4lczwvZGl2PjwvZGl2PicsXG4gICAgICAgIHNlYXJjaElucHV0OiAnPGlucHV0IGNsYXNzPVwiJXMlc1wiIHR5cGU9XCJ0ZXh0XCIgcGxhY2Vob2xkZXI9XCIlc1wiPicsXG4gICAgICAgIHNlYXJjaEJ1dHRvbjogJzxidXR0b24gY2xhc3M9XCIlc1wiIHR5cGU9XCJidXR0b25cIiBuYW1lPVwic2VhcmNoXCIgdGl0bGU9XCIlc1wiPiVzICVzPC9idXR0b24+JyxcbiAgICAgICAgc2VhcmNoQ2xlYXJCdXR0b246ICc8YnV0dG9uIGNsYXNzPVwiJXNcIiB0eXBlPVwiYnV0dG9uXCIgbmFtZT1cImNsZWFyU2VhcmNoXCIgdGl0bGU9XCIlc1wiPiVzICVzPC9idXR0b24+J1xuICAgICAgfVxuICAgIH0sXG4gICAgNToge1xuICAgICAgaWNvbnNQcmVmaXg6ICdmYScsXG4gICAgICBpY29uczoge1xuICAgICAgICBwYWdpbmF0aW9uU3dpdGNoRG93bjogJ2ZhLWNhcmV0LXNxdWFyZS1kb3duJyxcbiAgICAgICAgcGFnaW5hdGlvblN3aXRjaFVwOiAnZmEtY2FyZXQtc3F1YXJlLXVwJyxcbiAgICAgICAgcmVmcmVzaDogJ2ZhLXN5bmMnLFxuICAgICAgICB0b2dnbGVPZmY6ICdmYS10b2dnbGUtb2ZmJyxcbiAgICAgICAgdG9nZ2xlT246ICdmYS10b2dnbGUtb24nLFxuICAgICAgICBjb2x1bW5zOiAnZmEtdGgtbGlzdCcsXG4gICAgICAgIGRldGFpbE9wZW46ICdmYS1wbHVzJyxcbiAgICAgICAgZGV0YWlsQ2xvc2U6ICdmYS1taW51cycsXG4gICAgICAgIGZ1bGxzY3JlZW46ICdmYS1hcnJvd3MtYWx0JyxcbiAgICAgICAgc2VhcmNoOiAnZmEtc2VhcmNoJyxcbiAgICAgICAgY2xlYXJTZWFyY2g6ICdmYS10cmFzaCdcbiAgICAgIH0sXG4gICAgICBjbGFzc2VzOiB7XG4gICAgICAgIGJ1dHRvbnNQcmVmaXg6ICdidG4nLFxuICAgICAgICBidXR0b25zOiAnc2Vjb25kYXJ5JyxcbiAgICAgICAgYnV0dG9uc0dyb3VwOiAnYnRuLWdyb3VwJyxcbiAgICAgICAgYnV0dG9uc0Ryb3Bkb3duOiAnYnRuLWdyb3VwJyxcbiAgICAgICAgcHVsbDogJ2Zsb2F0JyxcbiAgICAgICAgaW5wdXRHcm91cDogJ2J0bi1ncm91cCcsXG4gICAgICAgIGlucHV0UHJlZml4OiAnZm9ybS1jb250cm9sLScsXG4gICAgICAgIGlucHV0OiAnZm9ybS1jb250cm9sJyxcbiAgICAgICAgcGFnaW5hdGlvbkRyb3Bkb3duOiAnYnRuLWdyb3VwIGRyb3Bkb3duJyxcbiAgICAgICAgZHJvcHVwOiAnZHJvcHVwJyxcbiAgICAgICAgZHJvcGRvd25BY3RpdmU6ICdhY3RpdmUnLFxuICAgICAgICBwYWdpbmF0aW9uQWN0aXZlOiAnYWN0aXZlJyxcbiAgICAgICAgYnV0dG9uQWN0aXZlOiAnYWN0aXZlJ1xuICAgICAgfSxcbiAgICAgIGh0bWw6IHtcbiAgICAgICAgZGF0YVRvZ2dsZTogJ2RhdGEtYnMtdG9nZ2xlJyxcbiAgICAgICAgdG9vbGJhckRyb3Bkb3duOiBbJzxkaXYgY2xhc3M9XCJkcm9wZG93bi1tZW51IGRyb3Bkb3duLW1lbnUtcmlnaHRcIj4nLCAnPC9kaXY+J10sXG4gICAgICAgIHRvb2xiYXJEcm9wZG93bkl0ZW06ICc8bGFiZWwgY2xhc3M9XCJkcm9wZG93bi1pdGVtIGRyb3Bkb3duLWl0ZW0tbWFya2VyXCI+JXM8L2xhYmVsPicsXG4gICAgICAgIHBhZ2VEcm9wZG93bjogWyc8ZGl2IGNsYXNzPVwiZHJvcGRvd24tbWVudVwiPicsICc8L2Rpdj4nXSxcbiAgICAgICAgcGFnZURyb3Bkb3duSXRlbTogJzxhIGNsYXNzPVwiZHJvcGRvd24taXRlbSAlc1wiIGhyZWY9XCIjXCI+JXM8L2E+JyxcbiAgICAgICAgdG9vbGJhckRyb3Bkb3duU2VwYXJhdG9yOiAnPGRpdiBjbGFzcz1cImRyb3Bkb3duLWRpdmlkZXJcIj48L2Rpdj4nLFxuICAgICAgICBkcm9wZG93bkNhcmV0OiAnPHNwYW4gY2xhc3M9XCJjYXJldFwiPjwvc3Bhbj4nLFxuICAgICAgICBwYWdpbmF0aW9uOiBbJzx1bCBjbGFzcz1cInBhZ2luYXRpb24lc1wiPicsICc8L3VsPiddLFxuICAgICAgICBwYWdpbmF0aW9uSXRlbTogJzxsaSBjbGFzcz1cInBhZ2UtaXRlbSVzXCI+PGEgY2xhc3M9XCJwYWdlLWxpbmtcIiBhcmlhLWxhYmVsPVwiJXNcIiBocmVmPVwiamF2YXNjcmlwdDp2b2lkKDApXCI+JXM8L2E+PC9saT4nLFxuICAgICAgICBpY29uOiAnPGkgY2xhc3M9XCIlcyAlc1wiPjwvaT4nLFxuICAgICAgICBpbnB1dEdyb3VwOiAnPGRpdiBjbGFzcz1cImlucHV0LWdyb3VwXCI+JXM8ZGl2IGNsYXNzPVwiaW5wdXQtZ3JvdXAtYXBwZW5kXCI+JXM8L2Rpdj48L2Rpdj4nLFxuICAgICAgICBzZWFyY2hJbnB1dDogJzxpbnB1dCBjbGFzcz1cIiVzJXNcIiB0eXBlPVwidGV4dFwiIHBsYWNlaG9sZGVyPVwiJXNcIj4nLFxuICAgICAgICBzZWFyY2hCdXR0b246ICc8YnV0dG9uIGNsYXNzPVwiJXNcIiB0eXBlPVwiYnV0dG9uXCIgbmFtZT1cInNlYXJjaFwiIHRpdGxlPVwiJXNcIj4lcyAlczwvYnV0dG9uPicsXG4gICAgICAgIHNlYXJjaENsZWFyQnV0dG9uOiAnPGJ1dHRvbiBjbGFzcz1cIiVzXCIgdHlwZT1cImJ1dHRvblwiIG5hbWU9XCJjbGVhclNlYXJjaFwiIHRpdGxlPVwiJXNcIj4lcyAlczwvYnV0dG9uPidcbiAgICAgIH1cbiAgICB9XG4gIH1bYm9vdHN0cmFwVmVyc2lvbl07XG4gIHZhciBERUZBVUxUUyA9IHtcbiAgICBoZWlnaHQ6IHVuZGVmaW5lZCxcbiAgICBjbGFzc2VzOiAndGFibGUgdGFibGUtYm9yZGVyZWQgdGFibGUtaG92ZXInLFxuICAgIGJ1dHRvbnM6IHt9LFxuICAgIHRoZWFkQ2xhc3NlczogJycsXG4gICAgaGVhZGVyU3R5bGU6IGZ1bmN0aW9uIGhlYWRlclN0eWxlKGNvbHVtbikge1xuICAgICAgcmV0dXJuIHt9O1xuICAgIH0sXG4gICAgcm93U3R5bGU6IGZ1bmN0aW9uIHJvd1N0eWxlKHJvdywgaW5kZXgpIHtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9LFxuICAgIHJvd0F0dHJpYnV0ZXM6IGZ1bmN0aW9uIHJvd0F0dHJpYnV0ZXMocm93LCBpbmRleCkge1xuICAgICAgcmV0dXJuIHt9O1xuICAgIH0sXG4gICAgdW5kZWZpbmVkVGV4dDogJy0nLFxuICAgIGxvY2FsZTogdW5kZWZpbmVkLFxuICAgIHZpcnR1YWxTY3JvbGw6IGZhbHNlLFxuICAgIHZpcnR1YWxTY3JvbGxJdGVtSGVpZ2h0OiB1bmRlZmluZWQsXG4gICAgc29ydGFibGU6IHRydWUsXG4gICAgc29ydENsYXNzOiB1bmRlZmluZWQsXG4gICAgc2lsZW50U29ydDogdHJ1ZSxcbiAgICBzb3J0TmFtZTogdW5kZWZpbmVkLFxuICAgIHNvcnRPcmRlcjogdW5kZWZpbmVkLFxuICAgIHNvcnRSZXNldDogZmFsc2UsXG4gICAgc29ydFN0YWJsZTogZmFsc2UsXG4gICAgcmVtZW1iZXJPcmRlcjogZmFsc2UsXG4gICAgc2VydmVyU29ydDogdHJ1ZSxcbiAgICBjdXN0b21Tb3J0OiB1bmRlZmluZWQsXG4gICAgY29sdW1uczogW1tdXSxcbiAgICBkYXRhOiBbXSxcbiAgICB1cmw6IHVuZGVmaW5lZCxcbiAgICBtZXRob2Q6ICdnZXQnLFxuICAgIGNhY2hlOiB0cnVlLFxuICAgIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgZGF0YVR5cGU6ICdqc29uJyxcbiAgICBhamF4OiB1bmRlZmluZWQsXG4gICAgYWpheE9wdGlvbnM6IHt9LFxuICAgIHF1ZXJ5UGFyYW1zOiBmdW5jdGlvbiBxdWVyeVBhcmFtcyhwYXJhbXMpIHtcbiAgICAgIHJldHVybiBwYXJhbXM7XG4gICAgfSxcbiAgICBxdWVyeVBhcmFtc1R5cGU6ICdsaW1pdCcsXG4gICAgLy8gJ2xpbWl0JywgdW5kZWZpbmVkXG4gICAgcmVzcG9uc2VIYW5kbGVyOiBmdW5jdGlvbiByZXNwb25zZUhhbmRsZXIocmVzKSB7XG4gICAgICByZXR1cm4gcmVzO1xuICAgIH0sXG4gICAgdG90YWxGaWVsZDogJ3RvdGFsJyxcbiAgICB0b3RhbE5vdEZpbHRlcmVkRmllbGQ6ICd0b3RhbE5vdEZpbHRlcmVkJyxcbiAgICBkYXRhRmllbGQ6ICdyb3dzJyxcbiAgICBmb290ZXJGaWVsZDogJ2Zvb3RlcicsXG4gICAgcGFnaW5hdGlvbjogZmFsc2UsXG4gICAgcGFnaW5hdGlvblBhcnRzOiBbJ3BhZ2VJbmZvJywgJ3BhZ2VTaXplJywgJ3BhZ2VMaXN0J10sXG4gICAgc2hvd0V4dGVuZGVkUGFnaW5hdGlvbjogZmFsc2UsXG4gICAgcGFnaW5hdGlvbkxvb3A6IHRydWUsXG4gICAgc2lkZVBhZ2luYXRpb246ICdjbGllbnQnLFxuICAgIC8vIGNsaWVudCBvciBzZXJ2ZXJcbiAgICB0b3RhbFJvd3M6IDAsXG4gICAgdG90YWxOb3RGaWx0ZXJlZDogMCxcbiAgICBwYWdlTnVtYmVyOiAxLFxuICAgIHBhZ2VTaXplOiAxMCxcbiAgICBwYWdlTGlzdDogWzEwLCAyNSwgNTAsIDEwMF0sXG4gICAgcGFnaW5hdGlvbkhBbGlnbjogJ3JpZ2h0JyxcbiAgICAvLyByaWdodCwgbGVmdFxuICAgIHBhZ2luYXRpb25WQWxpZ246ICdib3R0b20nLFxuICAgIC8vIGJvdHRvbSwgdG9wLCBib3RoXG4gICAgcGFnaW5hdGlvbkRldGFpbEhBbGlnbjogJ2xlZnQnLFxuICAgIC8vIHJpZ2h0LCBsZWZ0XG4gICAgcGFnaW5hdGlvblByZVRleHQ6ICcmbHNhcXVvOycsXG4gICAgcGFnaW5hdGlvbk5leHRUZXh0OiAnJnJzYXF1bzsnLFxuICAgIHBhZ2luYXRpb25TdWNjZXNzaXZlbHlTaXplOiA1LFxuICAgIC8vIE1heGltdW0gc3VjY2Vzc2l2ZWx5IG51bWJlciBvZiBwYWdlcyBpbiBhIHJvd1xuICAgIHBhZ2luYXRpb25QYWdlc0J5U2lkZTogMSxcbiAgICAvLyBOdW1iZXIgb2YgcGFnZXMgb24gZWFjaCBzaWRlIChyaWdodCwgbGVmdCkgb2YgdGhlIGN1cnJlbnQgcGFnZS5cbiAgICBwYWdpbmF0aW9uVXNlSW50ZXJtZWRpYXRlOiBmYWxzZSxcbiAgICAvLyBDYWxjdWxhdGUgaW50ZXJtZWRpYXRlIHBhZ2VzIGZvciBxdWljayBhY2Nlc3NcbiAgICBzZWFyY2g6IGZhbHNlLFxuICAgIHNlYXJjaEhpZ2hsaWdodDogZmFsc2UsXG4gICAgc2VhcmNoT25FbnRlcktleTogZmFsc2UsXG4gICAgc3RyaWN0U2VhcmNoOiBmYWxzZSxcbiAgICBzZWFyY2hTZWxlY3RvcjogZmFsc2UsXG4gICAgdmlzaWJsZVNlYXJjaDogZmFsc2UsXG4gICAgc2hvd0J1dHRvbkljb25zOiB0cnVlLFxuICAgIHNob3dCdXR0b25UZXh0OiBmYWxzZSxcbiAgICBzaG93U2VhcmNoQnV0dG9uOiBmYWxzZSxcbiAgICBzaG93U2VhcmNoQ2xlYXJCdXR0b246IGZhbHNlLFxuICAgIHRyaW1PblNlYXJjaDogdHJ1ZSxcbiAgICBzZWFyY2hBbGlnbjogJ3JpZ2h0JyxcbiAgICBzZWFyY2hUaW1lT3V0OiA1MDAsXG4gICAgc2VhcmNoVGV4dDogJycsXG4gICAgY3VzdG9tU2VhcmNoOiB1bmRlZmluZWQsXG4gICAgc2hvd0hlYWRlcjogdHJ1ZSxcbiAgICBzaG93Rm9vdGVyOiBmYWxzZSxcbiAgICBmb290ZXJTdHlsZTogZnVuY3Rpb24gZm9vdGVyU3R5bGUoY29sdW1uKSB7XG4gICAgICByZXR1cm4ge307XG4gICAgfSxcbiAgICBzZWFyY2hBY2NlbnROZXV0cmFsaXNlOiBmYWxzZSxcbiAgICBzaG93Q29sdW1uczogZmFsc2UsXG4gICAgc2hvd0NvbHVtbnNUb2dnbGVBbGw6IGZhbHNlLFxuICAgIHNob3dDb2x1bW5zU2VhcmNoOiBmYWxzZSxcbiAgICBtaW5pbXVtQ291bnRDb2x1bW5zOiAxLFxuICAgIHNob3dQYWdpbmF0aW9uU3dpdGNoOiBmYWxzZSxcbiAgICBzaG93UmVmcmVzaDogZmFsc2UsXG4gICAgc2hvd1RvZ2dsZTogZmFsc2UsXG4gICAgc2hvd0Z1bGxzY3JlZW46IGZhbHNlLFxuICAgIHNtYXJ0RGlzcGxheTogdHJ1ZSxcbiAgICBlc2NhcGU6IGZhbHNlLFxuICAgIGZpbHRlck9wdGlvbnM6IHtcbiAgICAgIGZpbHRlckFsZ29yaXRobTogJ2FuZCdcbiAgICB9LFxuICAgIGlkRmllbGQ6IHVuZGVmaW5lZCxcbiAgICBzZWxlY3RJdGVtTmFtZTogJ2J0U2VsZWN0SXRlbScsXG4gICAgY2xpY2tUb1NlbGVjdDogZmFsc2UsXG4gICAgaWdub3JlQ2xpY2tUb1NlbGVjdE9uOiBmdW5jdGlvbiBpZ25vcmVDbGlja1RvU2VsZWN0T24oX3JlZikge1xuICAgICAgdmFyIHRhZ05hbWUgPSBfcmVmLnRhZ05hbWU7XG4gICAgICByZXR1cm4gWydBJywgJ0JVVFRPTiddLmluY2x1ZGVzKHRhZ05hbWUpO1xuICAgIH0sXG4gICAgc2luZ2xlU2VsZWN0OiBmYWxzZSxcbiAgICBjaGVja2JveEhlYWRlcjogdHJ1ZSxcbiAgICBtYWludGFpbk1ldGFEYXRhOiBmYWxzZSxcbiAgICBtdWx0aXBsZVNlbGVjdFJvdzogZmFsc2UsXG4gICAgdW5pcXVlSWQ6IHVuZGVmaW5lZCxcbiAgICBjYXJkVmlldzogZmFsc2UsXG4gICAgZGV0YWlsVmlldzogZmFsc2UsXG4gICAgZGV0YWlsVmlld0ljb246IHRydWUsXG4gICAgZGV0YWlsVmlld0J5Q2xpY2s6IGZhbHNlLFxuICAgIGRldGFpbFZpZXdBbGlnbjogJ2xlZnQnLFxuICAgIGRldGFpbEZvcm1hdHRlcjogZnVuY3Rpb24gZGV0YWlsRm9ybWF0dGVyKGluZGV4LCByb3cpIHtcbiAgICAgIHJldHVybiAnJztcbiAgICB9LFxuICAgIGRldGFpbEZpbHRlcjogZnVuY3Rpb24gZGV0YWlsRmlsdGVyKGluZGV4LCByb3cpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG4gICAgdG9vbGJhcjogdW5kZWZpbmVkLFxuICAgIHRvb2xiYXJBbGlnbjogJ2xlZnQnLFxuICAgIGJ1dHRvbnNUb29sYmFyOiB1bmRlZmluZWQsXG4gICAgYnV0dG9uc0FsaWduOiAncmlnaHQnLFxuICAgIGJ1dHRvbnNPcmRlcjogWydwYWdpbmF0aW9uU3dpdGNoJywgJ3JlZnJlc2gnLCAndG9nZ2xlJywgJ2Z1bGxzY3JlZW4nLCAnY29sdW1ucyddLFxuICAgIGJ1dHRvbnNQcmVmaXg6IENPTlNUQU5UUy5jbGFzc2VzLmJ1dHRvbnNQcmVmaXgsXG4gICAgYnV0dG9uc0NsYXNzOiBDT05TVEFOVFMuY2xhc3Nlcy5idXR0b25zLFxuICAgIGljb25zOiBDT05TVEFOVFMuaWNvbnMsXG4gICAgaWNvblNpemU6IHVuZGVmaW5lZCxcbiAgICBpY29uc1ByZWZpeDogQ09OU1RBTlRTLmljb25zUHJlZml4LFxuICAgIC8vIGdseXBoaWNvbiBvciBmYShmb250LWF3ZXNvbWUpXG4gICAgbG9hZGluZ0ZvbnRTaXplOiAnYXV0bycsXG4gICAgbG9hZGluZ1RlbXBsYXRlOiBmdW5jdGlvbiBsb2FkaW5nVGVtcGxhdGUobG9hZGluZ01lc3NhZ2UpIHtcbiAgICAgIHJldHVybiBcIjxzcGFuIGNsYXNzPVxcXCJsb2FkaW5nLXdyYXBcXFwiPlxcbiAgICAgIDxzcGFuIGNsYXNzPVxcXCJsb2FkaW5nLXRleHRcXFwiPlwiLmNvbmNhdChsb2FkaW5nTWVzc2FnZSwgXCI8L3NwYW4+XFxuICAgICAgPHNwYW4gY2xhc3M9XFxcImFuaW1hdGlvbi13cmFwXFxcIj48c3BhbiBjbGFzcz1cXFwiYW5pbWF0aW9uLWRvdFxcXCI+PC9zcGFuPjwvc3Bhbj5cXG4gICAgICA8L3NwYW4+XFxuICAgIFwiKTtcbiAgICB9LFxuICAgIG9uQWxsOiBmdW5jdGlvbiBvbkFsbChuYW1lLCBhcmdzKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvbkNsaWNrQ2VsbDogZnVuY3Rpb24gb25DbGlja0NlbGwoZmllbGQsIHZhbHVlLCByb3csICRlbGVtZW50KSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvbkRibENsaWNrQ2VsbDogZnVuY3Rpb24gb25EYmxDbGlja0NlbGwoZmllbGQsIHZhbHVlLCByb3csICRlbGVtZW50KSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvbkNsaWNrUm93OiBmdW5jdGlvbiBvbkNsaWNrUm93KGl0ZW0sICRlbGVtZW50KSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvbkRibENsaWNrUm93OiBmdW5jdGlvbiBvbkRibENsaWNrUm93KGl0ZW0sICRlbGVtZW50KSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvblNvcnQ6IGZ1bmN0aW9uIG9uU29ydChuYW1lLCBvcmRlcikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG4gICAgb25DaGVjazogZnVuY3Rpb24gb25DaGVjayhyb3cpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LFxuICAgIG9uVW5jaGVjazogZnVuY3Rpb24gb25VbmNoZWNrKHJvdykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG4gICAgb25DaGVja0FsbDogZnVuY3Rpb24gb25DaGVja0FsbChyb3dzKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvblVuY2hlY2tBbGw6IGZ1bmN0aW9uIG9uVW5jaGVja0FsbChyb3dzKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvbkNoZWNrU29tZTogZnVuY3Rpb24gb25DaGVja1NvbWUocm93cykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG4gICAgb25VbmNoZWNrU29tZTogZnVuY3Rpb24gb25VbmNoZWNrU29tZShyb3dzKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvbkxvYWRTdWNjZXNzOiBmdW5jdGlvbiBvbkxvYWRTdWNjZXNzKGRhdGEpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LFxuICAgIG9uTG9hZEVycm9yOiBmdW5jdGlvbiBvbkxvYWRFcnJvcihzdGF0dXMpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LFxuICAgIG9uQ29sdW1uU3dpdGNoOiBmdW5jdGlvbiBvbkNvbHVtblN3aXRjaChmaWVsZCwgY2hlY2tlZCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG4gICAgb25QYWdlQ2hhbmdlOiBmdW5jdGlvbiBvblBhZ2VDaGFuZ2UobnVtYmVyLCBzaXplKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvblNlYXJjaDogZnVuY3Rpb24gb25TZWFyY2godGV4dCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG4gICAgb25Ub2dnbGU6IGZ1bmN0aW9uIG9uVG9nZ2xlKGNhcmRWaWV3KSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvblByZUJvZHk6IGZ1bmN0aW9uIG9uUHJlQm9keShkYXRhKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvblBvc3RCb2R5OiBmdW5jdGlvbiBvblBvc3RCb2R5KCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG4gICAgb25Qb3N0SGVhZGVyOiBmdW5jdGlvbiBvblBvc3RIZWFkZXIoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvblBvc3RGb290ZXI6IGZ1bmN0aW9uIG9uUG9zdEZvb3RlcigpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LFxuICAgIG9uRXhwYW5kUm93OiBmdW5jdGlvbiBvbkV4cGFuZFJvdyhpbmRleCwgcm93LCAkZGV0YWlsKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvbkNvbGxhcHNlUm93OiBmdW5jdGlvbiBvbkNvbGxhcHNlUm93KGluZGV4LCByb3cpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LFxuICAgIG9uUmVmcmVzaE9wdGlvbnM6IGZ1bmN0aW9uIG9uUmVmcmVzaE9wdGlvbnMob3B0aW9ucykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG4gICAgb25SZWZyZXNoOiBmdW5jdGlvbiBvblJlZnJlc2gocGFyYW1zKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvblJlc2V0VmlldzogZnVuY3Rpb24gb25SZXNldFZpZXcoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvblNjcm9sbEJvZHk6IGZ1bmN0aW9uIG9uU2Nyb2xsQm9keSgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH07XG4gIHZhciBFTiA9IHtcbiAgICBmb3JtYXRMb2FkaW5nTWVzc2FnZTogZnVuY3Rpb24gZm9ybWF0TG9hZGluZ01lc3NhZ2UoKSB7XG4gICAgICByZXR1cm4gJ0xvYWRpbmcsIHBsZWFzZSB3YWl0JztcbiAgICB9LFxuICAgIGZvcm1hdFJlY29yZHNQZXJQYWdlOiBmdW5jdGlvbiBmb3JtYXRSZWNvcmRzUGVyUGFnZShwYWdlTnVtYmVyKSB7XG4gICAgICByZXR1cm4gXCJcIi5jb25jYXQocGFnZU51bWJlciwgXCIgcm93cyBwZXIgcGFnZVwiKTtcbiAgICB9LFxuICAgIGZvcm1hdFNob3dpbmdSb3dzOiBmdW5jdGlvbiBmb3JtYXRTaG93aW5nUm93cyhwYWdlRnJvbSwgcGFnZVRvLCB0b3RhbFJvd3MsIHRvdGFsTm90RmlsdGVyZWQpIHtcbiAgICAgIGlmICh0b3RhbE5vdEZpbHRlcmVkICE9PSB1bmRlZmluZWQgJiYgdG90YWxOb3RGaWx0ZXJlZCA+IDAgJiYgdG90YWxOb3RGaWx0ZXJlZCA+IHRvdGFsUm93cykge1xuICAgICAgICByZXR1cm4gXCJTaG93aW5nIFwiLmNvbmNhdChwYWdlRnJvbSwgXCIgdG8gXCIpLmNvbmNhdChwYWdlVG8sIFwiIG9mIFwiKS5jb25jYXQodG90YWxSb3dzLCBcIiByb3dzIChmaWx0ZXJlZCBmcm9tIFwiKS5jb25jYXQodG90YWxOb3RGaWx0ZXJlZCwgXCIgdG90YWwgcm93cylcIik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBcIlNob3dpbmcgXCIuY29uY2F0KHBhZ2VGcm9tLCBcIiB0byBcIikuY29uY2F0KHBhZ2VUbywgXCIgb2YgXCIpLmNvbmNhdCh0b3RhbFJvd3MsIFwiIHJvd3NcIik7XG4gICAgfSxcbiAgICBmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OiBmdW5jdGlvbiBmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0KCkge1xuICAgICAgcmV0dXJuICdwcmV2aW91cyBwYWdlJztcbiAgICB9LFxuICAgIGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OiBmdW5jdGlvbiBmb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dChwYWdlKSB7XG4gICAgICByZXR1cm4gXCJ0byBwYWdlIFwiLmNvbmNhdChwYWdlKTtcbiAgICB9LFxuICAgIGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OiBmdW5jdGlvbiBmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dCgpIHtcbiAgICAgIHJldHVybiAnbmV4dCBwYWdlJztcbiAgICB9LFxuICAgIGZvcm1hdERldGFpbFBhZ2luYXRpb246IGZ1bmN0aW9uIGZvcm1hdERldGFpbFBhZ2luYXRpb24odG90YWxSb3dzKSB7XG4gICAgICByZXR1cm4gXCJTaG93aW5nIFwiLmNvbmNhdCh0b3RhbFJvd3MsIFwiIHJvd3NcIik7XG4gICAgfSxcbiAgICBmb3JtYXRTZWFyY2g6IGZ1bmN0aW9uIGZvcm1hdFNlYXJjaCgpIHtcbiAgICAgIHJldHVybiAnU2VhcmNoJztcbiAgICB9LFxuICAgIGZvcm1hdENsZWFyU2VhcmNoOiBmdW5jdGlvbiBmb3JtYXRDbGVhclNlYXJjaCgpIHtcbiAgICAgIHJldHVybiAnQ2xlYXIgU2VhcmNoJztcbiAgICB9LFxuICAgIGZvcm1hdE5vTWF0Y2hlczogZnVuY3Rpb24gZm9ybWF0Tm9NYXRjaGVzKCkge1xuICAgICAgcmV0dXJuICdObyBtYXRjaGluZyByZWNvcmRzIGZvdW5kJztcbiAgICB9LFxuICAgIGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6IGZ1bmN0aW9uIGZvcm1hdFBhZ2luYXRpb25Td2l0Y2goKSB7XG4gICAgICByZXR1cm4gJ0hpZGUvU2hvdyBwYWdpbmF0aW9uJztcbiAgICB9LFxuICAgIGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOiBmdW5jdGlvbiBmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bigpIHtcbiAgICAgIHJldHVybiAnU2hvdyBwYWdpbmF0aW9uJztcbiAgICB9LFxuICAgIGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDogZnVuY3Rpb24gZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwKCkge1xuICAgICAgcmV0dXJuICdIaWRlIHBhZ2luYXRpb24nO1xuICAgIH0sXG4gICAgZm9ybWF0UmVmcmVzaDogZnVuY3Rpb24gZm9ybWF0UmVmcmVzaCgpIHtcbiAgICAgIHJldHVybiAnUmVmcmVzaCc7XG4gICAgfSxcbiAgICBmb3JtYXRUb2dnbGU6IGZ1bmN0aW9uIGZvcm1hdFRvZ2dsZSgpIHtcbiAgICAgIHJldHVybiAnVG9nZ2xlJztcbiAgICB9LFxuICAgIGZvcm1hdFRvZ2dsZU9uOiBmdW5jdGlvbiBmb3JtYXRUb2dnbGVPbigpIHtcbiAgICAgIHJldHVybiAnU2hvdyBjYXJkIHZpZXcnO1xuICAgIH0sXG4gICAgZm9ybWF0VG9nZ2xlT2ZmOiBmdW5jdGlvbiBmb3JtYXRUb2dnbGVPZmYoKSB7XG4gICAgICByZXR1cm4gJ0hpZGUgY2FyZCB2aWV3JztcbiAgICB9LFxuICAgIGZvcm1hdENvbHVtbnM6IGZ1bmN0aW9uIGZvcm1hdENvbHVtbnMoKSB7XG4gICAgICByZXR1cm4gJ0NvbHVtbnMnO1xuICAgIH0sXG4gICAgZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDogZnVuY3Rpb24gZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbCgpIHtcbiAgICAgIHJldHVybiAnVG9nZ2xlIGFsbCc7XG4gICAgfSxcbiAgICBmb3JtYXRGdWxsc2NyZWVuOiBmdW5jdGlvbiBmb3JtYXRGdWxsc2NyZWVuKCkge1xuICAgICAgcmV0dXJuICdGdWxsc2NyZWVuJztcbiAgICB9LFxuICAgIGZvcm1hdEFsbFJvd3M6IGZ1bmN0aW9uIGZvcm1hdEFsbFJvd3MoKSB7XG4gICAgICByZXR1cm4gJ0FsbCc7XG4gICAgfVxuICB9O1xuICB2YXIgQ09MVU1OX0RFRkFVTFRTID0ge1xuICAgIGZpZWxkOiB1bmRlZmluZWQsXG4gICAgdGl0bGU6IHVuZGVmaW5lZCxcbiAgICB0aXRsZVRvb2x0aXA6IHVuZGVmaW5lZCxcbiAgICBjbGFzczogdW5kZWZpbmVkLFxuICAgIHdpZHRoOiB1bmRlZmluZWQsXG4gICAgd2lkdGhVbml0OiAncHgnLFxuICAgIHJvd3NwYW46IHVuZGVmaW5lZCxcbiAgICBjb2xzcGFuOiB1bmRlZmluZWQsXG4gICAgYWxpZ246IHVuZGVmaW5lZCxcbiAgICAvLyBsZWZ0LCByaWdodCwgY2VudGVyXG4gICAgaGFsaWduOiB1bmRlZmluZWQsXG4gICAgLy8gbGVmdCwgcmlnaHQsIGNlbnRlclxuICAgIGZhbGlnbjogdW5kZWZpbmVkLFxuICAgIC8vIGxlZnQsIHJpZ2h0LCBjZW50ZXJcbiAgICB2YWxpZ246IHVuZGVmaW5lZCxcbiAgICAvLyB0b3AsIG1pZGRsZSwgYm90dG9tXG4gICAgY2VsbFN0eWxlOiB1bmRlZmluZWQsXG4gICAgcmFkaW86IGZhbHNlLFxuICAgIGNoZWNrYm94OiBmYWxzZSxcbiAgICBjaGVja2JveEVuYWJsZWQ6IHRydWUsXG4gICAgY2xpY2tUb1NlbGVjdDogdHJ1ZSxcbiAgICBzaG93U2VsZWN0VGl0bGU6IGZhbHNlLFxuICAgIHNvcnRhYmxlOiBmYWxzZSxcbiAgICBzb3J0TmFtZTogdW5kZWZpbmVkLFxuICAgIG9yZGVyOiAnYXNjJyxcbiAgICAvLyBhc2MsIGRlc2NcbiAgICBzb3J0ZXI6IHVuZGVmaW5lZCxcbiAgICB2aXNpYmxlOiB0cnVlLFxuICAgIHN3aXRjaGFibGU6IHRydWUsXG4gICAgY2FyZFZpc2libGU6IHRydWUsXG4gICAgc2VhcmNoYWJsZTogdHJ1ZSxcbiAgICBmb3JtYXR0ZXI6IHVuZGVmaW5lZCxcbiAgICBmb290ZXJGb3JtYXR0ZXI6IHVuZGVmaW5lZCxcbiAgICBkZXRhaWxGb3JtYXR0ZXI6IHVuZGVmaW5lZCxcbiAgICBzZWFyY2hGb3JtYXR0ZXI6IHRydWUsXG4gICAgc2VhcmNoSGlnaGxpZ2h0Rm9ybWF0dGVyOiBmYWxzZSxcbiAgICBlc2NhcGU6IGZhbHNlLFxuICAgIGV2ZW50czogdW5kZWZpbmVkXG4gIH07XG4gIHZhciBNRVRIT0RTID0gWydnZXRPcHRpb25zJywgJ3JlZnJlc2hPcHRpb25zJywgJ2dldERhdGEnLCAnZ2V0U2VsZWN0aW9ucycsICdsb2FkJywgJ2FwcGVuZCcsICdwcmVwZW5kJywgJ3JlbW92ZScsICdyZW1vdmVBbGwnLCAnaW5zZXJ0Um93JywgJ3VwZGF0ZVJvdycsICdnZXRSb3dCeVVuaXF1ZUlkJywgJ3VwZGF0ZUJ5VW5pcXVlSWQnLCAncmVtb3ZlQnlVbmlxdWVJZCcsICd1cGRhdGVDZWxsJywgJ3VwZGF0ZUNlbGxCeVVuaXF1ZUlkJywgJ3Nob3dSb3cnLCAnaGlkZVJvdycsICdnZXRIaWRkZW5Sb3dzJywgJ3Nob3dDb2x1bW4nLCAnaGlkZUNvbHVtbicsICdnZXRWaXNpYmxlQ29sdW1ucycsICdnZXRIaWRkZW5Db2x1bW5zJywgJ3Nob3dBbGxDb2x1bW5zJywgJ2hpZGVBbGxDb2x1bW5zJywgJ21lcmdlQ2VsbHMnLCAnY2hlY2tBbGwnLCAndW5jaGVja0FsbCcsICdjaGVja0ludmVydCcsICdjaGVjaycsICd1bmNoZWNrJywgJ2NoZWNrQnknLCAndW5jaGVja0J5JywgJ3JlZnJlc2gnLCAnZGVzdHJveScsICdyZXNldFZpZXcnLCAnc2hvd0xvYWRpbmcnLCAnaGlkZUxvYWRpbmcnLCAndG9nZ2xlUGFnaW5hdGlvbicsICd0b2dnbGVGdWxsc2NyZWVuJywgJ3RvZ2dsZVZpZXcnLCAncmVzZXRTZWFyY2gnLCAnZmlsdGVyQnknLCAnc2Nyb2xsVG8nLCAnZ2V0U2Nyb2xsUG9zaXRpb24nLCAnc2VsZWN0UGFnZScsICdwcmV2UGFnZScsICduZXh0UGFnZScsICd0b2dnbGVEZXRhaWxWaWV3JywgJ2V4cGFuZFJvdycsICdjb2xsYXBzZVJvdycsICdleHBhbmRSb3dCeVVuaXF1ZUlkJywgJ2NvbGxhcHNlUm93QnlVbmlxdWVJZCcsICdleHBhbmRBbGxSb3dzJywgJ2NvbGxhcHNlQWxsUm93cycsICd1cGRhdGVDb2x1bW5UaXRsZScsICd1cGRhdGVGb3JtYXRUZXh0J107XG4gIHZhciBFVkVOVFMgPSB7XG4gICAgJ2FsbC5icy50YWJsZSc6ICdvbkFsbCcsXG4gICAgJ2NsaWNrLXJvdy5icy50YWJsZSc6ICdvbkNsaWNrUm93JyxcbiAgICAnZGJsLWNsaWNrLXJvdy5icy50YWJsZSc6ICdvbkRibENsaWNrUm93JyxcbiAgICAnY2xpY2stY2VsbC5icy50YWJsZSc6ICdvbkNsaWNrQ2VsbCcsXG4gICAgJ2RibC1jbGljay1jZWxsLmJzLnRhYmxlJzogJ29uRGJsQ2xpY2tDZWxsJyxcbiAgICAnc29ydC5icy50YWJsZSc6ICdvblNvcnQnLFxuICAgICdjaGVjay5icy50YWJsZSc6ICdvbkNoZWNrJyxcbiAgICAndW5jaGVjay5icy50YWJsZSc6ICdvblVuY2hlY2snLFxuICAgICdjaGVjay1hbGwuYnMudGFibGUnOiAnb25DaGVja0FsbCcsXG4gICAgJ3VuY2hlY2stYWxsLmJzLnRhYmxlJzogJ29uVW5jaGVja0FsbCcsXG4gICAgJ2NoZWNrLXNvbWUuYnMudGFibGUnOiAnb25DaGVja1NvbWUnLFxuICAgICd1bmNoZWNrLXNvbWUuYnMudGFibGUnOiAnb25VbmNoZWNrU29tZScsXG4gICAgJ2xvYWQtc3VjY2Vzcy5icy50YWJsZSc6ICdvbkxvYWRTdWNjZXNzJyxcbiAgICAnbG9hZC1lcnJvci5icy50YWJsZSc6ICdvbkxvYWRFcnJvcicsXG4gICAgJ2NvbHVtbi1zd2l0Y2guYnMudGFibGUnOiAnb25Db2x1bW5Td2l0Y2gnLFxuICAgICdwYWdlLWNoYW5nZS5icy50YWJsZSc6ICdvblBhZ2VDaGFuZ2UnLFxuICAgICdzZWFyY2guYnMudGFibGUnOiAnb25TZWFyY2gnLFxuICAgICd0b2dnbGUuYnMudGFibGUnOiAnb25Ub2dnbGUnLFxuICAgICdwcmUtYm9keS5icy50YWJsZSc6ICdvblByZUJvZHknLFxuICAgICdwb3N0LWJvZHkuYnMudGFibGUnOiAnb25Qb3N0Qm9keScsXG4gICAgJ3Bvc3QtaGVhZGVyLmJzLnRhYmxlJzogJ29uUG9zdEhlYWRlcicsXG4gICAgJ3Bvc3QtZm9vdGVyLmJzLnRhYmxlJzogJ29uUG9zdEZvb3RlcicsXG4gICAgJ2V4cGFuZC1yb3cuYnMudGFibGUnOiAnb25FeHBhbmRSb3cnLFxuICAgICdjb2xsYXBzZS1yb3cuYnMudGFibGUnOiAnb25Db2xsYXBzZVJvdycsXG4gICAgJ3JlZnJlc2gtb3B0aW9ucy5icy50YWJsZSc6ICdvblJlZnJlc2hPcHRpb25zJyxcbiAgICAncmVzZXQtdmlldy5icy50YWJsZSc6ICdvblJlc2V0VmlldycsXG4gICAgJ3JlZnJlc2guYnMudGFibGUnOiAnb25SZWZyZXNoJyxcbiAgICAnc2Nyb2xsLWJvZHkuYnMudGFibGUnOiAnb25TY3JvbGxCb2R5J1xuICB9O1xuICBPYmplY3QuYXNzaWduKERFRkFVTFRTLCBFTik7XG4gIHZhciBDb25zdGFudHMgPSB7XG4gICAgVkVSU0lPTjogVkVSU0lPTixcbiAgICBUSEVNRTogXCJib290c3RyYXBcIi5jb25jYXQoYm9vdHN0cmFwVmVyc2lvbiksXG4gICAgQ09OU1RBTlRTOiBDT05TVEFOVFMsXG4gICAgREVGQVVMVFM6IERFRkFVTFRTLFxuICAgIENPTFVNTl9ERUZBVUxUUzogQ09MVU1OX0RFRkFVTFRTLFxuICAgIE1FVEhPRFM6IE1FVEhPRFMsXG4gICAgRVZFTlRTOiBFVkVOVFMsXG4gICAgTE9DQUxFUzoge1xuICAgICAgZW46IEVOLFxuICAgICAgJ2VuLVVTJzogRU5cbiAgICB9XG4gIH07XG5cbiAgdmFyIEZBSUxTX09OX1BSSU1JVElWRVMgPSBmYWlscyhmdW5jdGlvbiAoKSB7IG9iamVjdEtleXMoMSk7IH0pO1xuXG4gIC8vIGBPYmplY3Qua2V5c2AgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtb2JqZWN0LmtleXNcbiAgX2V4cG9ydCh7IHRhcmdldDogJ09iamVjdCcsIHN0YXQ6IHRydWUsIGZvcmNlZDogRkFJTFNfT05fUFJJTUlUSVZFUyB9LCB7XG4gICAga2V5czogZnVuY3Rpb24ga2V5cyhpdCkge1xuICAgICAgcmV0dXJuIG9iamVjdEtleXModG9PYmplY3QoaXQpKTtcbiAgICB9XG4gIH0pO1xuXG4gIHZhciBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IkMSA9IG9iamVjdEdldE93blByb3BlcnR5RGVzY3JpcHRvci5mO1xuXG5cblxuXG5cblxuICB2YXIgbmF0aXZlU3RhcnRzV2l0aCA9ICcnLnN0YXJ0c1dpdGg7XG4gIHZhciBtaW4kMSA9IE1hdGgubWluO1xuXG4gIHZhciBDT1JSRUNUX0lTX1JFR0VYUF9MT0dJQyQxID0gY29ycmVjdElzUmVnZXhwTG9naWMoJ3N0YXJ0c1dpdGgnKTtcbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMvcHVsbC83MDJcbiAgdmFyIE1ETl9QT0xZRklMTF9CVUckMSA9ICFDT1JSRUNUX0lTX1JFR0VYUF9MT0dJQyQxICYmICEhZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZXNjcmlwdG9yID0gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yJDEoU3RyaW5nLnByb3RvdHlwZSwgJ3N0YXJ0c1dpdGgnKTtcbiAgICByZXR1cm4gZGVzY3JpcHRvciAmJiAhZGVzY3JpcHRvci53cml0YWJsZTtcbiAgfSgpO1xuXG4gIC8vIGBTdHJpbmcucHJvdG90eXBlLnN0YXJ0c1dpdGhgIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXN0cmluZy5wcm90b3R5cGUuc3RhcnRzd2l0aFxuICBfZXhwb3J0KHsgdGFyZ2V0OiAnU3RyaW5nJywgcHJvdG86IHRydWUsIGZvcmNlZDogIU1ETl9QT0xZRklMTF9CVUckMSAmJiAhQ09SUkVDVF9JU19SRUdFWFBfTE9HSUMkMSB9LCB7XG4gICAgc3RhcnRzV2l0aDogZnVuY3Rpb24gc3RhcnRzV2l0aChzZWFyY2hTdHJpbmcgLyogLCBwb3NpdGlvbiA9IDAgKi8pIHtcbiAgICAgIHZhciB0aGF0ID0gU3RyaW5nKHJlcXVpcmVPYmplY3RDb2VyY2libGUodGhpcykpO1xuICAgICAgbm90QVJlZ2V4cChzZWFyY2hTdHJpbmcpO1xuICAgICAgdmFyIGluZGV4ID0gdG9MZW5ndGgobWluJDEoYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQsIHRoYXQubGVuZ3RoKSk7XG4gICAgICB2YXIgc2VhcmNoID0gU3RyaW5nKHNlYXJjaFN0cmluZyk7XG4gICAgICByZXR1cm4gbmF0aXZlU3RhcnRzV2l0aFxuICAgICAgICA/IG5hdGl2ZVN0YXJ0c1dpdGguY2FsbCh0aGF0LCBzZWFyY2gsIGluZGV4KVxuICAgICAgICA6IHRoYXQuc2xpY2UoaW5kZXgsIGluZGV4ICsgc2VhcmNoLmxlbmd0aCkgPT09IHNlYXJjaDtcbiAgICB9XG4gIH0pO1xuXG4gIHZhciBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgPSBvYmplY3RHZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IuZjtcblxuXG5cblxuXG5cbiAgdmFyIG5hdGl2ZUVuZHNXaXRoID0gJycuZW5kc1dpdGg7XG4gIHZhciBtaW4gPSBNYXRoLm1pbjtcblxuICB2YXIgQ09SUkVDVF9JU19SRUdFWFBfTE9HSUMgPSBjb3JyZWN0SXNSZWdleHBMb2dpYygnZW5kc1dpdGgnKTtcbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMvcHVsbC83MDJcbiAgdmFyIE1ETl9QT0xZRklMTF9CVUcgPSAhQ09SUkVDVF9JU19SRUdFWFBfTE9HSUMgJiYgISFmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlc2NyaXB0b3IgPSBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoU3RyaW5nLnByb3RvdHlwZSwgJ2VuZHNXaXRoJyk7XG4gICAgcmV0dXJuIGRlc2NyaXB0b3IgJiYgIWRlc2NyaXB0b3Iud3JpdGFibGU7XG4gIH0oKTtcblxuICAvLyBgU3RyaW5nLnByb3RvdHlwZS5lbmRzV2l0aGAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtc3RyaW5nLnByb3RvdHlwZS5lbmRzd2l0aFxuICBfZXhwb3J0KHsgdGFyZ2V0OiAnU3RyaW5nJywgcHJvdG86IHRydWUsIGZvcmNlZDogIU1ETl9QT0xZRklMTF9CVUcgJiYgIUNPUlJFQ1RfSVNfUkVHRVhQX0xPR0lDIH0sIHtcbiAgICBlbmRzV2l0aDogZnVuY3Rpb24gZW5kc1dpdGgoc2VhcmNoU3RyaW5nIC8qICwgZW5kUG9zaXRpb24gPSBAbGVuZ3RoICovKSB7XG4gICAgICB2YXIgdGhhdCA9IFN0cmluZyhyZXF1aXJlT2JqZWN0Q29lcmNpYmxlKHRoaXMpKTtcbiAgICAgIG5vdEFSZWdleHAoc2VhcmNoU3RyaW5nKTtcbiAgICAgIHZhciBlbmRQb3NpdGlvbiA9IGFyZ3VtZW50cy5sZW5ndGggPiAxID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkO1xuICAgICAgdmFyIGxlbiA9IHRvTGVuZ3RoKHRoYXQubGVuZ3RoKTtcbiAgICAgIHZhciBlbmQgPSBlbmRQb3NpdGlvbiA9PT0gdW5kZWZpbmVkID8gbGVuIDogbWluKHRvTGVuZ3RoKGVuZFBvc2l0aW9uKSwgbGVuKTtcbiAgICAgIHZhciBzZWFyY2ggPSBTdHJpbmcoc2VhcmNoU3RyaW5nKTtcbiAgICAgIHJldHVybiBuYXRpdmVFbmRzV2l0aFxuICAgICAgICA/IG5hdGl2ZUVuZHNXaXRoLmNhbGwodGhhdCwgc2VhcmNoLCBlbmQpXG4gICAgICAgIDogdGhhdC5zbGljZShlbmQgLSBzZWFyY2gubGVuZ3RoLCBlbmQpID09PSBzZWFyY2g7XG4gICAgfVxuICB9KTtcblxuICB2YXIgVXRpbHMgPSB7XG4gICAgZ2V0U2VhcmNoSW5wdXQ6IGZ1bmN0aW9uIGdldFNlYXJjaElucHV0KHRoYXQpIHtcbiAgICAgIGlmICh0eXBlb2YgdGhhdC5vcHRpb25zLnNlYXJjaFNlbGVjdG9yID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gJF9fZGVmYXVsdFsnZGVmYXVsdCddKHRoYXQub3B0aW9ucy5zZWFyY2hTZWxlY3Rvcik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGF0LiR0b29sYmFyLmZpbmQoJy5zZWFyY2ggaW5wdXQnKTtcbiAgICB9LFxuICAgIC8vIGl0IG9ubHkgZG9lcyAnJXMnLCBhbmQgcmV0dXJuICcnIHdoZW4gYXJndW1lbnRzIGFyZSB1bmRlZmluZWRcbiAgICBzcHJpbnRmOiBmdW5jdGlvbiBzcHJpbnRmKF9zdHIpIHtcbiAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4gPiAxID8gX2xlbiAtIDEgOiAwKSwgX2tleSA9IDE7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHtcbiAgICAgICAgYXJnc1tfa2V5IC0gMV0gPSBhcmd1bWVudHNbX2tleV07XG4gICAgICB9XG5cbiAgICAgIHZhciBmbGFnID0gdHJ1ZTtcbiAgICAgIHZhciBpID0gMDtcblxuICAgICAgdmFyIHN0ciA9IF9zdHIucmVwbGFjZSgvJXMvZywgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgYXJnID0gYXJnc1tpKytdO1xuXG4gICAgICAgIGlmICh0eXBlb2YgYXJnID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIGZsYWcgPSBmYWxzZTtcbiAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYXJnO1xuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiBmbGFnID8gc3RyIDogJyc7XG4gICAgfSxcbiAgICBpc09iamVjdDogZnVuY3Rpb24gaXNPYmplY3QodmFsKSB7XG4gICAgICByZXR1cm4gdmFsIGluc3RhbmNlb2YgT2JqZWN0ICYmICFBcnJheS5pc0FycmF5KHZhbCk7XG4gICAgfSxcbiAgICBpc0VtcHR5T2JqZWN0OiBmdW5jdGlvbiBpc0VtcHR5T2JqZWN0KCkge1xuICAgICAgdmFyIG9iaiA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDoge307XG4gICAgICByZXR1cm4gT2JqZWN0LmVudHJpZXMob2JqKS5sZW5ndGggPT09IDAgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBPYmplY3Q7XG4gICAgfSxcbiAgICBpc051bWVyaWM6IGZ1bmN0aW9uIGlzTnVtZXJpYyhuKSB7XG4gICAgICByZXR1cm4gIWlzTmFOKHBhcnNlRmxvYXQobikpICYmIGlzRmluaXRlKG4pO1xuICAgIH0sXG4gICAgZ2V0RmllbGRUaXRsZTogZnVuY3Rpb24gZ2V0RmllbGRUaXRsZShsaXN0LCB2YWx1ZSkge1xuICAgICAgdmFyIF9pdGVyYXRvciA9IF9jcmVhdGVGb3JPZkl0ZXJhdG9ySGVscGVyKGxpc3QpLFxuICAgICAgICAgIF9zdGVwO1xuXG4gICAgICB0cnkge1xuICAgICAgICBmb3IgKF9pdGVyYXRvci5zKCk7ICEoX3N0ZXAgPSBfaXRlcmF0b3IubigpKS5kb25lOykge1xuICAgICAgICAgIHZhciBpdGVtID0gX3N0ZXAudmFsdWU7XG5cbiAgICAgICAgICBpZiAoaXRlbS5maWVsZCA9PT0gdmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybiBpdGVtLnRpdGxlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIF9pdGVyYXRvci5lKGVycik7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBfaXRlcmF0b3IuZigpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gJyc7XG4gICAgfSxcbiAgICBzZXRGaWVsZEluZGV4OiBmdW5jdGlvbiBzZXRGaWVsZEluZGV4KGNvbHVtbnMpIHtcbiAgICAgIHZhciB0b3RhbENvbCA9IDA7XG4gICAgICB2YXIgZmxhZyA9IFtdO1xuXG4gICAgICB2YXIgX2l0ZXJhdG9yMiA9IF9jcmVhdGVGb3JPZkl0ZXJhdG9ySGVscGVyKGNvbHVtbnNbMF0pLFxuICAgICAgICAgIF9zdGVwMjtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgZm9yIChfaXRlcmF0b3IyLnMoKTsgIShfc3RlcDIgPSBfaXRlcmF0b3IyLm4oKSkuZG9uZTspIHtcbiAgICAgICAgICB2YXIgY29sdW1uID0gX3N0ZXAyLnZhbHVlO1xuICAgICAgICAgIHRvdGFsQ29sICs9IGNvbHVtbi5jb2xzcGFuIHx8IDE7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBfaXRlcmF0b3IyLmUoZXJyKTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIF9pdGVyYXRvcjIuZigpO1xuICAgICAgfVxuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvbHVtbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZmxhZ1tpXSA9IFtdO1xuXG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgdG90YWxDb2w7IGorKykge1xuICAgICAgICAgIGZsYWdbaV1bal0gPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgY29sdW1ucy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIF9pdGVyYXRvcjMgPSBfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlcihjb2x1bW5zW19pXSksXG4gICAgICAgICAgICBfc3RlcDM7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBmb3IgKF9pdGVyYXRvcjMucygpOyAhKF9zdGVwMyA9IF9pdGVyYXRvcjMubigpKS5kb25lOykge1xuICAgICAgICAgICAgdmFyIHIgPSBfc3RlcDMudmFsdWU7XG4gICAgICAgICAgICB2YXIgcm93c3BhbiA9IHIucm93c3BhbiB8fCAxO1xuICAgICAgICAgICAgdmFyIGNvbHNwYW4gPSByLmNvbHNwYW4gfHwgMTtcblxuICAgICAgICAgICAgdmFyIGluZGV4ID0gZmxhZ1tfaV0uaW5kZXhPZihmYWxzZSk7XG5cbiAgICAgICAgICAgIHIuY29sc3BhbkluZGV4ID0gaW5kZXg7XG5cbiAgICAgICAgICAgIGlmIChjb2xzcGFuID09PSAxKSB7XG4gICAgICAgICAgICAgIHIuZmllbGRJbmRleCA9IGluZGV4OyAvLyB3aGVuIGZpZWxkIGlzIHVuZGVmaW5lZCwgdXNlIGluZGV4IGluc3RlYWRcblxuICAgICAgICAgICAgICBpZiAodHlwZW9mIHIuZmllbGQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgci5maWVsZCA9IGluZGV4O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByLmNvbHNwYW5Hcm91cCA9IHIuY29sc3BhbjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yICh2YXIgX2ogPSAwOyBfaiA8IHJvd3NwYW47IF9qKyspIHtcbiAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBjb2xzcGFuOyBrKyspIHtcbiAgICAgICAgICAgICAgICBmbGFnW19pICsgX2pdW2luZGV4ICsga10gPSB0cnVlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBfaXRlcmF0b3IzLmUoZXJyKTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICBfaXRlcmF0b3IzLmYoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG4gICAgbm9ybWFsaXplQWNjZW50OiBmdW5jdGlvbiBub3JtYWxpemVBY2NlbnQodmFsdWUpIHtcbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHZhbHVlLm5vcm1hbGl6ZSgnTkZEJykucmVwbGFjZSgvW1xcdTAzMDAtXFx1MDM2Zl0vZywgJycpO1xuICAgIH0sXG4gICAgdXBkYXRlRmllbGRHcm91cDogZnVuY3Rpb24gdXBkYXRlRmllbGRHcm91cChjb2x1bW5zKSB7XG4gICAgICB2YXIgX3JlZjtcblxuICAgICAgdmFyIGFsbENvbHVtbnMgPSAoX3JlZiA9IFtdKS5jb25jYXQuYXBwbHkoX3JlZiwgX3RvQ29uc3VtYWJsZUFycmF5KGNvbHVtbnMpKTtcblxuICAgICAgdmFyIF9pdGVyYXRvcjQgPSBfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlcihjb2x1bW5zKSxcbiAgICAgICAgICBfc3RlcDQ7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGZvciAoX2l0ZXJhdG9yNC5zKCk7ICEoX3N0ZXA0ID0gX2l0ZXJhdG9yNC5uKCkpLmRvbmU7KSB7XG4gICAgICAgICAgdmFyIGMgPSBfc3RlcDQudmFsdWU7XG5cbiAgICAgICAgICB2YXIgX2l0ZXJhdG9yNSA9IF9jcmVhdGVGb3JPZkl0ZXJhdG9ySGVscGVyKGMpLFxuICAgICAgICAgICAgICBfc3RlcDU7XG5cbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgZm9yIChfaXRlcmF0b3I1LnMoKTsgIShfc3RlcDUgPSBfaXRlcmF0b3I1Lm4oKSkuZG9uZTspIHtcbiAgICAgICAgICAgICAgdmFyIHIgPSBfc3RlcDUudmFsdWU7XG5cbiAgICAgICAgICAgICAgaWYgKHIuY29sc3Bhbkdyb3VwID4gMSkge1xuICAgICAgICAgICAgICAgIHZhciBjb2xzcGFuID0gMDtcblxuICAgICAgICAgICAgICAgIHZhciBfbG9vcCA9IGZ1bmN0aW9uIF9sb29wKGkpIHtcbiAgICAgICAgICAgICAgICAgIHZhciBjb2x1bW4gPSBhbGxDb2x1bW5zLmZpbmQoZnVuY3Rpb24gKGNvbCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29sLmZpZWxkSW5kZXggPT09IGk7XG4gICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgaWYgKGNvbHVtbi52aXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbHNwYW4rKztcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IHIuY29sc3BhbkluZGV4OyBpIDwgci5jb2xzcGFuSW5kZXggKyByLmNvbHNwYW5Hcm91cDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICBfbG9vcChpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByLmNvbHNwYW4gPSBjb2xzcGFuO1xuICAgICAgICAgICAgICAgIHIudmlzaWJsZSA9IGNvbHNwYW4gPiAwO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBfaXRlcmF0b3I1LmUoZXJyKTtcbiAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgX2l0ZXJhdG9yNS5mKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgX2l0ZXJhdG9yNC5lKGVycik7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBfaXRlcmF0b3I0LmYoKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIGdldFNjcm9sbEJhcldpZHRoOiBmdW5jdGlvbiBnZXRTY3JvbGxCYXJXaWR0aCgpIHtcbiAgICAgIGlmICh0aGlzLmNhY2hlZFdpZHRoID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdmFyICRpbm5lciA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXSgnPGRpdi8+JykuYWRkQ2xhc3MoJ2ZpeGVkLXRhYmxlLXNjcm9sbC1pbm5lcicpO1xuICAgICAgICB2YXIgJG91dGVyID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKCc8ZGl2Lz4nKS5hZGRDbGFzcygnZml4ZWQtdGFibGUtc2Nyb2xsLW91dGVyJyk7XG4gICAgICAgICRvdXRlci5hcHBlbmQoJGlubmVyKTtcbiAgICAgICAgJF9fZGVmYXVsdFsnZGVmYXVsdCddKCdib2R5JykuYXBwZW5kKCRvdXRlcik7XG4gICAgICAgIHZhciB3MSA9ICRpbm5lclswXS5vZmZzZXRXaWR0aDtcbiAgICAgICAgJG91dGVyLmNzcygnb3ZlcmZsb3cnLCAnc2Nyb2xsJyk7XG4gICAgICAgIHZhciB3MiA9ICRpbm5lclswXS5vZmZzZXRXaWR0aDtcblxuICAgICAgICBpZiAodzEgPT09IHcyKSB7XG4gICAgICAgICAgdzIgPSAkb3V0ZXJbMF0uY2xpZW50V2lkdGg7XG4gICAgICAgIH1cblxuICAgICAgICAkb3V0ZXIucmVtb3ZlKCk7XG4gICAgICAgIHRoaXMuY2FjaGVkV2lkdGggPSB3MSAtIHcyO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5jYWNoZWRXaWR0aDtcbiAgICB9LFxuICAgIGNhbGN1bGF0ZU9iamVjdFZhbHVlOiBmdW5jdGlvbiBjYWxjdWxhdGVPYmplY3RWYWx1ZShzZWxmLCBuYW1lLCBhcmdzLCBkZWZhdWx0VmFsdWUpIHtcbiAgICAgIHZhciBmdW5jID0gbmFtZTtcblxuICAgICAgaWYgKHR5cGVvZiBuYW1lID09PSAnc3RyaW5nJykge1xuICAgICAgICAvLyBzdXBwb3J0IG9iai5mdW5jMS5mdW5jMlxuICAgICAgICB2YXIgbmFtZXMgPSBuYW1lLnNwbGl0KCcuJyk7XG5cbiAgICAgICAgaWYgKG5hbWVzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICBmdW5jID0gd2luZG93O1xuXG4gICAgICAgICAgdmFyIF9pdGVyYXRvcjYgPSBfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlcihuYW1lcyksXG4gICAgICAgICAgICAgIF9zdGVwNjtcblxuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBmb3IgKF9pdGVyYXRvcjYucygpOyAhKF9zdGVwNiA9IF9pdGVyYXRvcjYubigpKS5kb25lOykge1xuICAgICAgICAgICAgICB2YXIgZiA9IF9zdGVwNi52YWx1ZTtcbiAgICAgICAgICAgICAgZnVuYyA9IGZ1bmNbZl07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBfaXRlcmF0b3I2LmUoZXJyKTtcbiAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgX2l0ZXJhdG9yNi5mKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGZ1bmMgPSB3aW5kb3dbbmFtZV07XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGZ1bmMgIT09IG51bGwgJiYgX3R5cGVvZihmdW5jKSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmM7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgZnVuYyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gZnVuYy5hcHBseShzZWxmLCBhcmdzIHx8IFtdKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFmdW5jICYmIHR5cGVvZiBuYW1lID09PSAnc3RyaW5nJyAmJiB0aGlzLnNwcmludGYuYXBwbHkodGhpcywgW25hbWVdLmNvbmNhdChfdG9Db25zdW1hYmxlQXJyYXkoYXJncykpKSkge1xuICAgICAgICByZXR1cm4gdGhpcy5zcHJpbnRmLmFwcGx5KHRoaXMsIFtuYW1lXS5jb25jYXQoX3RvQ29uc3VtYWJsZUFycmF5KGFyZ3MpKSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBkZWZhdWx0VmFsdWU7XG4gICAgfSxcbiAgICBjb21wYXJlT2JqZWN0czogZnVuY3Rpb24gY29tcGFyZU9iamVjdHMob2JqZWN0QSwgb2JqZWN0QiwgY29tcGFyZUxlbmd0aCkge1xuICAgICAgdmFyIGFLZXlzID0gT2JqZWN0LmtleXMob2JqZWN0QSk7XG4gICAgICB2YXIgYktleXMgPSBPYmplY3Qua2V5cyhvYmplY3RCKTtcblxuICAgICAgaWYgKGNvbXBhcmVMZW5ndGggJiYgYUtleXMubGVuZ3RoICE9PSBiS2V5cy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBmb3IgKHZhciBfaTIgPSAwLCBfYUtleXMgPSBhS2V5czsgX2kyIDwgX2FLZXlzLmxlbmd0aDsgX2kyKyspIHtcbiAgICAgICAgdmFyIGtleSA9IF9hS2V5c1tfaTJdO1xuXG4gICAgICAgIGlmIChiS2V5cy5pbmNsdWRlcyhrZXkpICYmIG9iamVjdEFba2V5XSAhPT0gb2JqZWN0QltrZXldKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG4gICAgZXNjYXBlSFRNTDogZnVuY3Rpb24gZXNjYXBlSFRNTCh0ZXh0KSB7XG4gICAgICBpZiAodHlwZW9mIHRleHQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiB0ZXh0LnJlcGxhY2UoLyYvZywgJyZhbXA7JykucmVwbGFjZSgvPC9nLCAnJmx0OycpLnJlcGxhY2UoLz4vZywgJyZndDsnKS5yZXBsYWNlKC9cIi9nLCAnJnF1b3Q7JykucmVwbGFjZSgvJy9nLCAnJiMwMzk7JykucmVwbGFjZSgvYC9nLCAnJiN4NjA7Jyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0ZXh0O1xuICAgIH0sXG4gICAgdW5lc2NhcGVIVE1MOiBmdW5jdGlvbiB1bmVzY2FwZUhUTUwodGV4dCkge1xuICAgICAgaWYgKHR5cGVvZiB0ZXh0ID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gdGV4dC5yZXBsYWNlKC8mYW1wOy9nLCAnJicpLnJlcGxhY2UoLyZsdDsvZywgJzwnKS5yZXBsYWNlKC8mZ3Q7L2csICc+JykucmVwbGFjZSgvJnF1b3Q7L2csICdcIicpLnJlcGxhY2UoLyYjMDM5Oy9nLCAnXFwnJykucmVwbGFjZSgvJiN4NjA7L2csICdgJyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0ZXh0O1xuICAgIH0sXG4gICAgZ2V0UmVhbERhdGFBdHRyOiBmdW5jdGlvbiBnZXRSZWFsRGF0YUF0dHIoZGF0YUF0dHIpIHtcbiAgICAgIGZvciAodmFyIF9pMyA9IDAsIF9PYmplY3QkZW50cmllcyA9IE9iamVjdC5lbnRyaWVzKGRhdGFBdHRyKTsgX2kzIDwgX09iamVjdCRlbnRyaWVzLmxlbmd0aDsgX2kzKyspIHtcbiAgICAgICAgdmFyIF9PYmplY3QkZW50cmllcyRfaSA9IF9zbGljZWRUb0FycmF5KF9PYmplY3QkZW50cmllc1tfaTNdLCAyKSxcbiAgICAgICAgICAgIGF0dHIgPSBfT2JqZWN0JGVudHJpZXMkX2lbMF0sXG4gICAgICAgICAgICB2YWx1ZSA9IF9PYmplY3QkZW50cmllcyRfaVsxXTtcblxuICAgICAgICB2YXIgYXV4QXR0ciA9IGF0dHIuc3BsaXQoLyg/PVtBLVpdKS8pLmpvaW4oJy0nKS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICAgIGlmIChhdXhBdHRyICE9PSBhdHRyKSB7XG4gICAgICAgICAgZGF0YUF0dHJbYXV4QXR0cl0gPSB2YWx1ZTtcbiAgICAgICAgICBkZWxldGUgZGF0YUF0dHJbYXR0cl07XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGRhdGFBdHRyO1xuICAgIH0sXG4gICAgZ2V0SXRlbUZpZWxkOiBmdW5jdGlvbiBnZXRJdGVtRmllbGQoaXRlbSwgZmllbGQsIGVzY2FwZSkge1xuICAgICAgdmFyIHZhbHVlID0gaXRlbTtcblxuICAgICAgaWYgKHR5cGVvZiBmaWVsZCAhPT0gJ3N0cmluZycgfHwgaXRlbS5oYXNPd25Qcm9wZXJ0eShmaWVsZCkpIHtcbiAgICAgICAgcmV0dXJuIGVzY2FwZSA/IHRoaXMuZXNjYXBlSFRNTChpdGVtW2ZpZWxkXSkgOiBpdGVtW2ZpZWxkXTtcbiAgICAgIH1cblxuICAgICAgdmFyIHByb3BzID0gZmllbGQuc3BsaXQoJy4nKTtcblxuICAgICAgdmFyIF9pdGVyYXRvcjcgPSBfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlcihwcm9wcyksXG4gICAgICAgICAgX3N0ZXA3O1xuXG4gICAgICB0cnkge1xuICAgICAgICBmb3IgKF9pdGVyYXRvcjcucygpOyAhKF9zdGVwNyA9IF9pdGVyYXRvcjcubigpKS5kb25lOykge1xuICAgICAgICAgIHZhciBwID0gX3N0ZXA3LnZhbHVlO1xuICAgICAgICAgIHZhbHVlID0gdmFsdWUgJiYgdmFsdWVbcF07XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBfaXRlcmF0b3I3LmUoZXJyKTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIF9pdGVyYXRvcjcuZigpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZXNjYXBlID8gdGhpcy5lc2NhcGVIVE1MKHZhbHVlKSA6IHZhbHVlO1xuICAgIH0sXG4gICAgaXNJRUJyb3dzZXI6IGZ1bmN0aW9uIGlzSUVCcm93c2VyKCkge1xuICAgICAgcmV0dXJuIG5hdmlnYXRvci51c2VyQWdlbnQuaW5jbHVkZXMoJ01TSUUgJykgfHwgL1RyaWRlbnQuKnJ2OjExXFwuLy50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICAgIH0sXG4gICAgZmluZEluZGV4OiBmdW5jdGlvbiBmaW5kSW5kZXgoaXRlbXMsIGl0ZW0pIHtcbiAgICAgIHZhciBfaXRlcmF0b3I4ID0gX2NyZWF0ZUZvck9mSXRlcmF0b3JIZWxwZXIoaXRlbXMpLFxuICAgICAgICAgIF9zdGVwODtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgZm9yIChfaXRlcmF0b3I4LnMoKTsgIShfc3RlcDggPSBfaXRlcmF0b3I4Lm4oKSkuZG9uZTspIHtcbiAgICAgICAgICB2YXIgaXQgPSBfc3RlcDgudmFsdWU7XG5cbiAgICAgICAgICBpZiAoSlNPTi5zdHJpbmdpZnkoaXQpID09PSBKU09OLnN0cmluZ2lmeShpdGVtKSkge1xuICAgICAgICAgICAgcmV0dXJuIGl0ZW1zLmluZGV4T2YoaXQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIF9pdGVyYXRvcjguZShlcnIpO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgX2l0ZXJhdG9yOC5mKCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAtMTtcbiAgICB9LFxuICAgIHRyVG9EYXRhOiBmdW5jdGlvbiB0clRvRGF0YShjb2x1bW5zLCAkZWxzKSB7XG4gICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICB2YXIgZGF0YSA9IFtdO1xuICAgICAgdmFyIG0gPSBbXTtcbiAgICAgICRlbHMuZWFjaChmdW5jdGlvbiAoeSwgZWwpIHtcbiAgICAgICAgdmFyICRlbCA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlbCk7XG4gICAgICAgIHZhciByb3cgPSB7fTsgLy8gc2F2ZSB0cidzIGlkLCBjbGFzcyBhbmQgZGF0YS0qIGF0dHJpYnV0ZXNcblxuICAgICAgICByb3cuX2lkID0gJGVsLmF0dHIoJ2lkJyk7XG4gICAgICAgIHJvdy5fY2xhc3MgPSAkZWwuYXR0cignY2xhc3MnKTtcbiAgICAgICAgcm93Ll9kYXRhID0gX3RoaXMuZ2V0UmVhbERhdGFBdHRyKCRlbC5kYXRhKCkpO1xuICAgICAgICByb3cuX3N0eWxlID0gJGVsLmF0dHIoJ3N0eWxlJyk7XG4gICAgICAgICRlbC5maW5kKCc+dGQsPnRoJykuZWFjaChmdW5jdGlvbiAoX3gsIGVsKSB7XG4gICAgICAgICAgdmFyICRlbCA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlbCk7XG4gICAgICAgICAgdmFyIGNzcGFuID0gKyRlbC5hdHRyKCdjb2xzcGFuJykgfHwgMTtcbiAgICAgICAgICB2YXIgcnNwYW4gPSArJGVsLmF0dHIoJ3Jvd3NwYW4nKSB8fCAxO1xuICAgICAgICAgIHZhciB4ID0gX3g7IC8vIHNraXAgYWxyZWFkeSBvY2N1cGllZCBjZWxscyBpbiBjdXJyZW50IHJvd1xuXG4gICAgICAgICAgZm9yICg7IG1beV0gJiYgbVt5XVt4XTsgeCsrKSB7Ly8gaWdub3JlXG4gICAgICAgICAgfSAvLyBtYXJrIG1hdHJpeCBlbGVtZW50cyBvY2N1cGllZCBieSBjdXJyZW50IGNlbGwgd2l0aCB0cnVlXG5cblxuICAgICAgICAgIGZvciAodmFyIHR4ID0geDsgdHggPCB4ICsgY3NwYW47IHR4KyspIHtcbiAgICAgICAgICAgIGZvciAodmFyIHR5ID0geTsgdHkgPCB5ICsgcnNwYW47IHR5KyspIHtcbiAgICAgICAgICAgICAgaWYgKCFtW3R5XSkge1xuICAgICAgICAgICAgICAgIC8vIGZpbGwgbWlzc2luZyByb3dzXG4gICAgICAgICAgICAgICAgbVt0eV0gPSBbXTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIG1bdHldW3R4XSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIGZpZWxkID0gY29sdW1uc1t4XS5maWVsZDtcbiAgICAgICAgICByb3dbZmllbGRdID0gJGVsLmh0bWwoKS50cmltKCk7IC8vIHNhdmUgdGQncyBpZCwgY2xhc3MgYW5kIGRhdGEtKiBhdHRyaWJ1dGVzXG5cbiAgICAgICAgICByb3dbXCJfXCIuY29uY2F0KGZpZWxkLCBcIl9pZFwiKV0gPSAkZWwuYXR0cignaWQnKTtcbiAgICAgICAgICByb3dbXCJfXCIuY29uY2F0KGZpZWxkLCBcIl9jbGFzc1wiKV0gPSAkZWwuYXR0cignY2xhc3MnKTtcbiAgICAgICAgICByb3dbXCJfXCIuY29uY2F0KGZpZWxkLCBcIl9yb3dzcGFuXCIpXSA9ICRlbC5hdHRyKCdyb3dzcGFuJyk7XG4gICAgICAgICAgcm93W1wiX1wiLmNvbmNhdChmaWVsZCwgXCJfY29sc3BhblwiKV0gPSAkZWwuYXR0cignY29sc3BhbicpO1xuICAgICAgICAgIHJvd1tcIl9cIi5jb25jYXQoZmllbGQsIFwiX3RpdGxlXCIpXSA9ICRlbC5hdHRyKCd0aXRsZScpO1xuICAgICAgICAgIHJvd1tcIl9cIi5jb25jYXQoZmllbGQsIFwiX2RhdGFcIildID0gX3RoaXMuZ2V0UmVhbERhdGFBdHRyKCRlbC5kYXRhKCkpO1xuICAgICAgICAgIHJvd1tcIl9cIi5jb25jYXQoZmllbGQsIFwiX3N0eWxlXCIpXSA9ICRlbC5hdHRyKCdzdHlsZScpO1xuICAgICAgICB9KTtcbiAgICAgICAgZGF0YS5wdXNoKHJvdyk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH0sXG4gICAgc29ydDogZnVuY3Rpb24gc29ydChhLCBiLCBvcmRlciwgc29ydFN0YWJsZSwgYVBvc2l0aW9uLCBiUG9zaXRpb24pIHtcbiAgICAgIGlmIChhID09PSB1bmRlZmluZWQgfHwgYSA9PT0gbnVsbCkge1xuICAgICAgICBhID0gJyc7XG4gICAgICB9XG5cbiAgICAgIGlmIChiID09PSB1bmRlZmluZWQgfHwgYiA9PT0gbnVsbCkge1xuICAgICAgICBiID0gJyc7XG4gICAgICB9XG5cbiAgICAgIGlmIChzb3J0U3RhYmxlICYmIGEgPT09IGIpIHtcbiAgICAgICAgYSA9IGFQb3NpdGlvbjtcbiAgICAgICAgYiA9IGJQb3NpdGlvbjtcbiAgICAgIH0gLy8gSWYgYm90aCB2YWx1ZXMgYXJlIG51bWVyaWMsIGRvIGEgbnVtZXJpYyBjb21wYXJpc29uXG5cblxuICAgICAgaWYgKHRoaXMuaXNOdW1lcmljKGEpICYmIHRoaXMuaXNOdW1lcmljKGIpKSB7XG4gICAgICAgIC8vIENvbnZlcnQgbnVtZXJpY2FsIHZhbHVlcyBmb3JtIHN0cmluZyB0byBmbG9hdC5cbiAgICAgICAgYSA9IHBhcnNlRmxvYXQoYSk7XG4gICAgICAgIGIgPSBwYXJzZUZsb2F0KGIpO1xuXG4gICAgICAgIGlmIChhIDwgYikge1xuICAgICAgICAgIHJldHVybiBvcmRlciAqIC0xO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGEgPiBiKSB7XG4gICAgICAgICAgcmV0dXJuIG9yZGVyO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgICB9XG5cbiAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfSAvLyBJZiB2YWx1ZSBpcyBub3QgYSBzdHJpbmcsIGNvbnZlcnQgdG8gc3RyaW5nXG5cblxuICAgICAgaWYgKHR5cGVvZiBhICE9PSAnc3RyaW5nJykge1xuICAgICAgICBhID0gYS50b1N0cmluZygpO1xuICAgICAgfVxuXG4gICAgICBpZiAoYS5sb2NhbGVDb21wYXJlKGIpID09PSAtMSkge1xuICAgICAgICByZXR1cm4gb3JkZXIgKiAtMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG9yZGVyO1xuICAgIH0sXG4gICAgZ2V0RXZlbnROYW1lOiBmdW5jdGlvbiBnZXRFdmVudE5hbWUoZXZlbnRQcmVmaXgpIHtcbiAgICAgIHZhciBpZCA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogJyc7XG4gICAgICBpZCA9IGlkIHx8IFwiXCIuY29uY2F0KCtuZXcgRGF0ZSgpKS5jb25jYXQofn4oTWF0aC5yYW5kb20oKSAqIDEwMDAwMDApKTtcbiAgICAgIHJldHVybiBcIlwiLmNvbmNhdChldmVudFByZWZpeCwgXCItXCIpLmNvbmNhdChpZCk7XG4gICAgfSxcbiAgICBoYXNEZXRhaWxWaWV3SWNvbjogZnVuY3Rpb24gaGFzRGV0YWlsVmlld0ljb24ob3B0aW9ucykge1xuICAgICAgcmV0dXJuIG9wdGlvbnMuZGV0YWlsVmlldyAmJiBvcHRpb25zLmRldGFpbFZpZXdJY29uICYmICFvcHRpb25zLmNhcmRWaWV3O1xuICAgIH0sXG4gICAgZ2V0RGV0YWlsVmlld0luZGV4T2Zmc2V0OiBmdW5jdGlvbiBnZXREZXRhaWxWaWV3SW5kZXhPZmZzZXQob3B0aW9ucykge1xuICAgICAgcmV0dXJuIHRoaXMuaGFzRGV0YWlsVmlld0ljb24ob3B0aW9ucykgJiYgb3B0aW9ucy5kZXRhaWxWaWV3QWxpZ24gIT09ICdyaWdodCcgPyAxIDogMDtcbiAgICB9LFxuICAgIGNoZWNrQXV0b01lcmdlQ2VsbHM6IGZ1bmN0aW9uIGNoZWNrQXV0b01lcmdlQ2VsbHMoZGF0YSkge1xuICAgICAgdmFyIF9pdGVyYXRvcjkgPSBfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlcihkYXRhKSxcbiAgICAgICAgICBfc3RlcDk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGZvciAoX2l0ZXJhdG9yOS5zKCk7ICEoX3N0ZXA5ID0gX2l0ZXJhdG9yOS5uKCkpLmRvbmU7KSB7XG4gICAgICAgICAgdmFyIHJvdyA9IF9zdGVwOS52YWx1ZTtcblxuICAgICAgICAgIGZvciAodmFyIF9pNCA9IDAsIF9PYmplY3Qka2V5cyA9IE9iamVjdC5rZXlzKHJvdyk7IF9pNCA8IF9PYmplY3Qka2V5cy5sZW5ndGg7IF9pNCsrKSB7XG4gICAgICAgICAgICB2YXIga2V5ID0gX09iamVjdCRrZXlzW19pNF07XG5cbiAgICAgICAgICAgIGlmIChrZXkuc3RhcnRzV2l0aCgnXycpICYmIChrZXkuZW5kc1dpdGgoJ19yb3dzcGFuJykgfHwga2V5LmVuZHNXaXRoKCdfY29sc3BhbicpKSkge1xuICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBfaXRlcmF0b3I5LmUoZXJyKTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIF9pdGVyYXRvcjkuZigpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBkZWVwQ29weTogZnVuY3Rpb24gZGVlcENvcHkoYXJnKSB7XG4gICAgICBpZiAoYXJnID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIGFyZztcbiAgICAgIH1cblxuICAgICAgcmV0dXJuICRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5leHRlbmQodHJ1ZSwgQXJyYXkuaXNBcnJheShhcmcpID8gW10gOiB7fSwgYXJnKTtcbiAgICB9XG4gIH07XG5cbiAgdmFyIEJMT0NLX1JPV1MgPSA1MDtcbiAgdmFyIENMVVNURVJfQkxPQ0tTID0gNDtcblxuICB2YXIgVmlydHVhbFNjcm9sbCA9IC8qI19fUFVSRV9fKi9mdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gVmlydHVhbFNjcm9sbChvcHRpb25zKSB7XG4gICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgVmlydHVhbFNjcm9sbCk7XG5cbiAgICAgIHRoaXMucm93cyA9IG9wdGlvbnMucm93cztcbiAgICAgIHRoaXMuc2Nyb2xsRWwgPSBvcHRpb25zLnNjcm9sbEVsO1xuICAgICAgdGhpcy5jb250ZW50RWwgPSBvcHRpb25zLmNvbnRlbnRFbDtcbiAgICAgIHRoaXMuY2FsbGJhY2sgPSBvcHRpb25zLmNhbGxiYWNrO1xuICAgICAgdGhpcy5pdGVtSGVpZ2h0ID0gb3B0aW9ucy5pdGVtSGVpZ2h0O1xuICAgICAgdGhpcy5jYWNoZSA9IHt9O1xuICAgICAgdGhpcy5zY3JvbGxUb3AgPSB0aGlzLnNjcm9sbEVsLnNjcm9sbFRvcDtcbiAgICAgIHRoaXMuaW5pdERPTSh0aGlzLnJvd3MsIG9wdGlvbnMuZml4ZWRTY3JvbGwpO1xuICAgICAgdGhpcy5zY3JvbGxFbC5zY3JvbGxUb3AgPSB0aGlzLnNjcm9sbFRvcDtcbiAgICAgIHRoaXMubGFzdENsdXN0ZXIgPSAwO1xuXG4gICAgICB2YXIgb25TY3JvbGwgPSBmdW5jdGlvbiBvblNjcm9sbCgpIHtcbiAgICAgICAgaWYgKF90aGlzLmxhc3RDbHVzdGVyICE9PSAoX3RoaXMubGFzdENsdXN0ZXIgPSBfdGhpcy5nZXROdW0oKSkpIHtcbiAgICAgICAgICBfdGhpcy5pbml0RE9NKF90aGlzLnJvd3MpO1xuXG4gICAgICAgICAgX3RoaXMuY2FsbGJhY2soKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgdGhpcy5zY3JvbGxFbC5hZGRFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBvblNjcm9sbCwgZmFsc2UpO1xuXG4gICAgICB0aGlzLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIF90aGlzLmNvbnRlbnRFbC5pbm5lckh0bWwgPSAnJztcblxuICAgICAgICBfdGhpcy5zY3JvbGxFbC5yZW1vdmVFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBvblNjcm9sbCwgZmFsc2UpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBfY3JlYXRlQ2xhc3MoVmlydHVhbFNjcm9sbCwgW3tcbiAgICAgIGtleTogXCJpbml0RE9NXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaW5pdERPTShyb3dzLCBmaXhlZFNjcm9sbCkge1xuICAgICAgICBpZiAodHlwZW9mIHRoaXMuY2x1c3RlckhlaWdodCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICB0aGlzLmNhY2hlLnNjcm9sbFRvcCA9IHRoaXMuc2Nyb2xsRWwuc2Nyb2xsVG9wO1xuICAgICAgICAgIHRoaXMuY2FjaGUuZGF0YSA9IHRoaXMuY29udGVudEVsLmlubmVySFRNTCA9IHJvd3NbMF0gKyByb3dzWzBdICsgcm93c1swXTtcbiAgICAgICAgICB0aGlzLmdldFJvd3NIZWlnaHQocm93cyk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZGF0YSA9IHRoaXMuaW5pdERhdGEocm93cywgdGhpcy5nZXROdW0oZml4ZWRTY3JvbGwpKTtcbiAgICAgICAgdmFyIHRoaXNSb3dzID0gZGF0YS5yb3dzLmpvaW4oJycpO1xuICAgICAgICB2YXIgZGF0YUNoYW5nZWQgPSB0aGlzLmNoZWNrQ2hhbmdlcygnZGF0YScsIHRoaXNSb3dzKTtcbiAgICAgICAgdmFyIHRvcE9mZnNldENoYW5nZWQgPSB0aGlzLmNoZWNrQ2hhbmdlcygndG9wJywgZGF0YS50b3BPZmZzZXQpO1xuICAgICAgICB2YXIgYm90dG9tT2Zmc2V0Q2hhbmdlZCA9IHRoaXMuY2hlY2tDaGFuZ2VzKCdib3R0b20nLCBkYXRhLmJvdHRvbU9mZnNldCk7XG4gICAgICAgIHZhciBodG1sID0gW107XG5cbiAgICAgICAgaWYgKGRhdGFDaGFuZ2VkICYmIHRvcE9mZnNldENoYW5nZWQpIHtcbiAgICAgICAgICBpZiAoZGF0YS50b3BPZmZzZXQpIHtcbiAgICAgICAgICAgIGh0bWwucHVzaCh0aGlzLmdldEV4dHJhKCd0b3AnLCBkYXRhLnRvcE9mZnNldCkpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGh0bWwucHVzaCh0aGlzUm93cyk7XG5cbiAgICAgICAgICBpZiAoZGF0YS5ib3R0b21PZmZzZXQpIHtcbiAgICAgICAgICAgIGh0bWwucHVzaCh0aGlzLmdldEV4dHJhKCdib3R0b20nLCBkYXRhLmJvdHRvbU9mZnNldCkpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuY29udGVudEVsLmlubmVySFRNTCA9IGh0bWwuam9pbignJyk7XG5cbiAgICAgICAgICBpZiAoZml4ZWRTY3JvbGwpIHtcbiAgICAgICAgICAgIHRoaXMuY29udGVudEVsLnNjcm9sbFRvcCA9IHRoaXMuY2FjaGUuc2Nyb2xsVG9wO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChib3R0b21PZmZzZXRDaGFuZ2VkKSB7XG4gICAgICAgICAgdGhpcy5jb250ZW50RWwubGFzdENoaWxkLnN0eWxlLmhlaWdodCA9IFwiXCIuY29uY2F0KGRhdGEuYm90dG9tT2Zmc2V0LCBcInB4XCIpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImdldFJvd3NIZWlnaHRcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRSb3dzSGVpZ2h0KCkge1xuICAgICAgICBpZiAodHlwZW9mIHRoaXMuaXRlbUhlaWdodCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICB2YXIgbm9kZXMgPSB0aGlzLmNvbnRlbnRFbC5jaGlsZHJlbjtcbiAgICAgICAgICB2YXIgbm9kZSA9IG5vZGVzW01hdGguZmxvb3Iobm9kZXMubGVuZ3RoIC8gMildO1xuICAgICAgICAgIHRoaXMuaXRlbUhlaWdodCA9IG5vZGUub2Zmc2V0SGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5ibG9ja0hlaWdodCA9IHRoaXMuaXRlbUhlaWdodCAqIEJMT0NLX1JPV1M7XG4gICAgICAgIHRoaXMuY2x1c3RlclJvd3MgPSBCTE9DS19ST1dTICogQ0xVU1RFUl9CTE9DS1M7XG4gICAgICAgIHRoaXMuY2x1c3RlckhlaWdodCA9IHRoaXMuYmxvY2tIZWlnaHQgKiBDTFVTVEVSX0JMT0NLUztcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiZ2V0TnVtXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0TnVtKGZpeGVkU2Nyb2xsKSB7XG4gICAgICAgIHRoaXMuc2Nyb2xsVG9wID0gZml4ZWRTY3JvbGwgPyB0aGlzLmNhY2hlLnNjcm9sbFRvcCA6IHRoaXMuc2Nyb2xsRWwuc2Nyb2xsVG9wO1xuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcih0aGlzLnNjcm9sbFRvcCAvICh0aGlzLmNsdXN0ZXJIZWlnaHQgLSB0aGlzLmJsb2NrSGVpZ2h0KSkgfHwgMDtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiaW5pdERhdGFcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0RGF0YShyb3dzLCBudW0pIHtcbiAgICAgICAgaWYgKHJvd3MubGVuZ3RoIDwgQkxPQ0tfUk9XUykge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB0b3BPZmZzZXQ6IDAsXG4gICAgICAgICAgICBib3R0b21PZmZzZXQ6IDAsXG4gICAgICAgICAgICByb3dzQWJvdmU6IDAsXG4gICAgICAgICAgICByb3dzOiByb3dzXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzdGFydCA9IE1hdGgubWF4KCh0aGlzLmNsdXN0ZXJSb3dzIC0gQkxPQ0tfUk9XUykgKiBudW0sIDApO1xuICAgICAgICB2YXIgZW5kID0gc3RhcnQgKyB0aGlzLmNsdXN0ZXJSb3dzO1xuICAgICAgICB2YXIgdG9wT2Zmc2V0ID0gTWF0aC5tYXgoc3RhcnQgKiB0aGlzLml0ZW1IZWlnaHQsIDApO1xuICAgICAgICB2YXIgYm90dG9tT2Zmc2V0ID0gTWF0aC5tYXgoKHJvd3MubGVuZ3RoIC0gZW5kKSAqIHRoaXMuaXRlbUhlaWdodCwgMCk7XG4gICAgICAgIHZhciB0aGlzUm93cyA9IFtdO1xuICAgICAgICB2YXIgcm93c0Fib3ZlID0gc3RhcnQ7XG5cbiAgICAgICAgaWYgKHRvcE9mZnNldCA8IDEpIHtcbiAgICAgICAgICByb3dzQWJvdmUrKztcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgICAgICAgcm93c1tpXSAmJiB0aGlzUm93cy5wdXNoKHJvd3NbaV0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0b3BPZmZzZXQ6IHRvcE9mZnNldCxcbiAgICAgICAgICBib3R0b21PZmZzZXQ6IGJvdHRvbU9mZnNldCxcbiAgICAgICAgICByb3dzQWJvdmU6IHJvd3NBYm92ZSxcbiAgICAgICAgICByb3dzOiB0aGlzUm93c1xuICAgICAgICB9O1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJjaGVja0NoYW5nZXNcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBjaGVja0NoYW5nZXModHlwZSwgdmFsdWUpIHtcbiAgICAgICAgdmFyIGNoYW5nZWQgPSB2YWx1ZSAhPT0gdGhpcy5jYWNoZVt0eXBlXTtcbiAgICAgICAgdGhpcy5jYWNoZVt0eXBlXSA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gY2hhbmdlZDtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiZ2V0RXh0cmFcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRFeHRyYShjbGFzc05hbWUsIGhlaWdodCkge1xuICAgICAgICB2YXIgdGFnID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndHInKTtcbiAgICAgICAgdGFnLmNsYXNzTmFtZSA9IFwidmlydHVhbC1zY3JvbGwtXCIuY29uY2F0KGNsYXNzTmFtZSk7XG5cbiAgICAgICAgaWYgKGhlaWdodCkge1xuICAgICAgICAgIHRhZy5zdHlsZS5oZWlnaHQgPSBcIlwiLmNvbmNhdChoZWlnaHQsIFwicHhcIik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGFnLm91dGVySFRNTDtcbiAgICAgIH1cbiAgICB9XSk7XG5cbiAgICByZXR1cm4gVmlydHVhbFNjcm9sbDtcbiAgfSgpO1xuXG4gIHZhciBCb290c3RyYXBUYWJsZSA9IC8qI19fUFVSRV9fKi9mdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQm9vdHN0cmFwVGFibGUoZWwsIG9wdGlvbnMpIHtcbiAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBCb290c3RyYXBUYWJsZSk7XG5cbiAgICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgICB0aGlzLiRlbCA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlbCk7XG4gICAgICB0aGlzLiRlbF8gPSB0aGlzLiRlbC5jbG9uZSgpO1xuICAgICAgdGhpcy50aW1lb3V0SWRfID0gMDtcbiAgICAgIHRoaXMudGltZW91dEZvb3Rlcl8gPSAwO1xuICAgIH1cblxuICAgIF9jcmVhdGVDbGFzcyhCb290c3RyYXBUYWJsZSwgW3tcbiAgICAgIGtleTogXCJpbml0XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaW5pdCgpIHtcbiAgICAgICAgdGhpcy5pbml0Q29uc3RhbnRzKCk7XG4gICAgICAgIHRoaXMuaW5pdExvY2FsZSgpO1xuICAgICAgICB0aGlzLmluaXRDb250YWluZXIoKTtcbiAgICAgICAgdGhpcy5pbml0VGFibGUoKTtcbiAgICAgICAgdGhpcy5pbml0SGVhZGVyKCk7XG4gICAgICAgIHRoaXMuaW5pdERhdGEoKTtcbiAgICAgICAgdGhpcy5pbml0SGlkZGVuUm93cygpO1xuICAgICAgICB0aGlzLmluaXRUb29sYmFyKCk7XG4gICAgICAgIHRoaXMuaW5pdFBhZ2luYXRpb24oKTtcbiAgICAgICAgdGhpcy5pbml0Qm9keSgpO1xuICAgICAgICB0aGlzLmluaXRTZWFyY2hUZXh0KCk7XG4gICAgICAgIHRoaXMuaW5pdFNlcnZlcigpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJpbml0Q29uc3RhbnRzXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaW5pdENvbnN0YW50cygpIHtcbiAgICAgICAgdmFyIG9wdHMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIHRoaXMuY29uc3RhbnRzID0gQ29uc3RhbnRzLkNPTlNUQU5UUztcbiAgICAgICAgdGhpcy5jb25zdGFudHMudGhlbWUgPSAkX19kZWZhdWx0WydkZWZhdWx0J10uZm4uYm9vdHN0cmFwVGFibGUudGhlbWU7XG4gICAgICAgIHRoaXMuY29uc3RhbnRzLmRhdGFUb2dnbGUgPSB0aGlzLmNvbnN0YW50cy5odG1sLmRhdGFUb2dnbGUgfHwgJ2RhdGEtdG9nZ2xlJztcbiAgICAgICAgdmFyIGJ1dHRvbnNQcmVmaXggPSBvcHRzLmJ1dHRvbnNQcmVmaXggPyBcIlwiLmNvbmNhdChvcHRzLmJ1dHRvbnNQcmVmaXgsIFwiLVwiKSA6ICcnO1xuICAgICAgICB0aGlzLmNvbnN0YW50cy5idXR0b25zQ2xhc3MgPSBbb3B0cy5idXR0b25zUHJlZml4LCBidXR0b25zUHJlZml4ICsgb3B0cy5idXR0b25zQ2xhc3MsIFV0aWxzLnNwcmludGYoXCJcIi5jb25jYXQoYnV0dG9uc1ByZWZpeCwgXCIlc1wiKSwgb3B0cy5pY29uU2l6ZSldLmpvaW4oJyAnKS50cmltKCk7XG4gICAgICAgIHRoaXMuYnV0dG9ucyA9IFV0aWxzLmNhbGN1bGF0ZU9iamVjdFZhbHVlKHRoaXMsIG9wdHMuYnV0dG9ucywgW10sIHt9KTtcblxuICAgICAgICBpZiAoX3R5cGVvZih0aGlzLmJ1dHRvbnMpICE9PSAnb2JqZWN0Jykge1xuICAgICAgICAgIHRoaXMuYnV0dG9ucyA9IHt9O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBvcHRzLmljb25zID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIG9wdHMuaWNvbnMgPSBVdGlscy5jYWxjdWxhdGVPYmplY3RWYWx1ZShudWxsLCBvcHRzLmljb25zKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJpbml0TG9jYWxlXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaW5pdExvY2FsZSgpIHtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5sb2NhbGUpIHtcbiAgICAgICAgICB2YXIgbG9jYWxlcyA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzO1xuICAgICAgICAgIHZhciBwYXJ0cyA9IHRoaXMub3B0aW9ucy5sb2NhbGUuc3BsaXQoLy18Xy8pO1xuICAgICAgICAgIHBhcnRzWzBdID0gcGFydHNbMF0udG9Mb3dlckNhc2UoKTtcblxuICAgICAgICAgIGlmIChwYXJ0c1sxXSkge1xuICAgICAgICAgICAgcGFydHNbMV0gPSBwYXJ0c1sxXS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChsb2NhbGVzW3RoaXMub3B0aW9ucy5sb2NhbGVdKSB7XG4gICAgICAgICAgICAkX19kZWZhdWx0WydkZWZhdWx0J10uZXh0ZW5kKHRoaXMub3B0aW9ucywgbG9jYWxlc1t0aGlzLm9wdGlvbnMubG9jYWxlXSk7XG4gICAgICAgICAgfSBlbHNlIGlmIChsb2NhbGVzW3BhcnRzLmpvaW4oJy0nKV0pIHtcbiAgICAgICAgICAgICRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5leHRlbmQodGhpcy5vcHRpb25zLCBsb2NhbGVzW3BhcnRzLmpvaW4oJy0nKV0pO1xuICAgICAgICAgIH0gZWxzZSBpZiAobG9jYWxlc1twYXJ0c1swXV0pIHtcbiAgICAgICAgICAgICRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5leHRlbmQodGhpcy5vcHRpb25zLCBsb2NhbGVzW3BhcnRzWzBdXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImluaXRDb250YWluZXJcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0Q29udGFpbmVyKCkge1xuICAgICAgICB2YXIgdG9wUGFnaW5hdGlvbiA9IFsndG9wJywgJ2JvdGgnXS5pbmNsdWRlcyh0aGlzLm9wdGlvbnMucGFnaW5hdGlvblZBbGlnbikgPyAnPGRpdiBjbGFzcz1cImZpeGVkLXRhYmxlLXBhZ2luYXRpb24gY2xlYXJmaXhcIj48L2Rpdj4nIDogJyc7XG4gICAgICAgIHZhciBib3R0b21QYWdpbmF0aW9uID0gWydib3R0b20nLCAnYm90aCddLmluY2x1ZGVzKHRoaXMub3B0aW9ucy5wYWdpbmF0aW9uVkFsaWduKSA/ICc8ZGl2IGNsYXNzPVwiZml4ZWQtdGFibGUtcGFnaW5hdGlvblwiPjwvZGl2PicgOiAnJztcbiAgICAgICAgdmFyIGxvYWRpbmdUZW1wbGF0ZSA9IFV0aWxzLmNhbGN1bGF0ZU9iamVjdFZhbHVlKHRoaXMub3B0aW9ucywgdGhpcy5vcHRpb25zLmxvYWRpbmdUZW1wbGF0ZSwgW3RoaXMub3B0aW9ucy5mb3JtYXRMb2FkaW5nTWVzc2FnZSgpXSk7XG4gICAgICAgIHRoaXMuJGNvbnRhaW5lciA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShcIlxcbiAgICAgIDxkaXYgY2xhc3M9XFxcImJvb3RzdHJhcC10YWJsZSBcIi5jb25jYXQodGhpcy5jb25zdGFudHMudGhlbWUsIFwiXFxcIj5cXG4gICAgICA8ZGl2IGNsYXNzPVxcXCJmaXhlZC10YWJsZS10b29sYmFyXFxcIj48L2Rpdj5cXG4gICAgICBcIikuY29uY2F0KHRvcFBhZ2luYXRpb24sIFwiXFxuICAgICAgPGRpdiBjbGFzcz1cXFwiZml4ZWQtdGFibGUtY29udGFpbmVyXFxcIj5cXG4gICAgICA8ZGl2IGNsYXNzPVxcXCJmaXhlZC10YWJsZS1oZWFkZXJcXFwiPjx0YWJsZT48L3RhYmxlPjwvZGl2PlxcbiAgICAgIDxkaXYgY2xhc3M9XFxcImZpeGVkLXRhYmxlLWJvZHlcXFwiPlxcbiAgICAgIDxkaXYgY2xhc3M9XFxcImZpeGVkLXRhYmxlLWxvYWRpbmdcXFwiPlxcbiAgICAgIFwiKS5jb25jYXQobG9hZGluZ1RlbXBsYXRlLCBcIlxcbiAgICAgIDwvZGl2PlxcbiAgICAgIDwvZGl2PlxcbiAgICAgIDxkaXYgY2xhc3M9XFxcImZpeGVkLXRhYmxlLWZvb3RlclxcXCI+PC9kaXY+XFxuICAgICAgPC9kaXY+XFxuICAgICAgXCIpLmNvbmNhdChib3R0b21QYWdpbmF0aW9uLCBcIlxcbiAgICAgIDwvZGl2PlxcbiAgICBcIikpO1xuICAgICAgICB0aGlzLiRjb250YWluZXIuaW5zZXJ0QWZ0ZXIodGhpcy4kZWwpO1xuICAgICAgICB0aGlzLiR0YWJsZUNvbnRhaW5lciA9IHRoaXMuJGNvbnRhaW5lci5maW5kKCcuZml4ZWQtdGFibGUtY29udGFpbmVyJyk7XG4gICAgICAgIHRoaXMuJHRhYmxlSGVhZGVyID0gdGhpcy4kY29udGFpbmVyLmZpbmQoJy5maXhlZC10YWJsZS1oZWFkZXInKTtcbiAgICAgICAgdGhpcy4kdGFibGVCb2R5ID0gdGhpcy4kY29udGFpbmVyLmZpbmQoJy5maXhlZC10YWJsZS1ib2R5Jyk7XG4gICAgICAgIHRoaXMuJHRhYmxlTG9hZGluZyA9IHRoaXMuJGNvbnRhaW5lci5maW5kKCcuZml4ZWQtdGFibGUtbG9hZGluZycpO1xuICAgICAgICB0aGlzLiR0YWJsZUZvb3RlciA9IHRoaXMuJGVsLmZpbmQoJ3Rmb290Jyk7IC8vIGNoZWNraW5nIGlmIGN1c3RvbSB0YWJsZS10b29sYmFyIGV4aXN0cyBvciBub3RcblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLmJ1dHRvbnNUb29sYmFyKSB7XG4gICAgICAgICAgdGhpcy4kdG9vbGJhciA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXSgnYm9keScpLmZpbmQodGhpcy5vcHRpb25zLmJ1dHRvbnNUb29sYmFyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLiR0b29sYmFyID0gdGhpcy4kY29udGFpbmVyLmZpbmQoJy5maXhlZC10YWJsZS10b29sYmFyJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLiRwYWdpbmF0aW9uID0gdGhpcy4kY29udGFpbmVyLmZpbmQoJy5maXhlZC10YWJsZS1wYWdpbmF0aW9uJyk7XG4gICAgICAgIHRoaXMuJHRhYmxlQm9keS5hcHBlbmQodGhpcy4kZWwpO1xuICAgICAgICB0aGlzLiRjb250YWluZXIuYWZ0ZXIoJzxkaXYgY2xhc3M9XCJjbGVhcmZpeFwiPjwvZGl2PicpO1xuICAgICAgICB0aGlzLiRlbC5hZGRDbGFzcyh0aGlzLm9wdGlvbnMuY2xhc3Nlcyk7XG4gICAgICAgIHRoaXMuJHRhYmxlTG9hZGluZy5hZGRDbGFzcyh0aGlzLm9wdGlvbnMuY2xhc3Nlcyk7XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5oZWlnaHQpIHtcbiAgICAgICAgICB0aGlzLiR0YWJsZUNvbnRhaW5lci5hZGRDbGFzcygnZml4ZWQtaGVpZ2h0Jyk7XG5cbiAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNob3dGb290ZXIpIHtcbiAgICAgICAgICAgIHRoaXMuJHRhYmxlQ29udGFpbmVyLmFkZENsYXNzKCdoYXMtZm9vdGVyJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5jbGFzc2VzLnNwbGl0KCcgJykuaW5jbHVkZXMoJ3RhYmxlLWJvcmRlcmVkJykpIHtcbiAgICAgICAgICAgIHRoaXMuJHRhYmxlQm9keS5hcHBlbmQoJzxkaXYgY2xhc3M9XCJmaXhlZC10YWJsZS1ib3JkZXJcIj48L2Rpdj4nKTtcbiAgICAgICAgICAgIHRoaXMuJHRhYmxlQm9yZGVyID0gdGhpcy4kdGFibGVCb2R5LmZpbmQoJy5maXhlZC10YWJsZS1ib3JkZXInKTtcbiAgICAgICAgICAgIHRoaXMuJHRhYmxlTG9hZGluZy5hZGRDbGFzcygnZml4ZWQtdGFibGUtYm9yZGVyJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy4kdGFibGVGb290ZXIgPSB0aGlzLiRjb250YWluZXIuZmluZCgnLmZpeGVkLXRhYmxlLWZvb3RlcicpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImluaXRUYWJsZVwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGluaXRUYWJsZSgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgICB2YXIgY29sdW1ucyA9IFtdO1xuICAgICAgICB0aGlzLiRoZWFkZXIgPSB0aGlzLiRlbC5maW5kKCc+dGhlYWQnKTtcblxuICAgICAgICBpZiAoIXRoaXMuJGhlYWRlci5sZW5ndGgpIHtcbiAgICAgICAgICB0aGlzLiRoZWFkZXIgPSAkX19kZWZhdWx0WydkZWZhdWx0J10oXCI8dGhlYWQgY2xhc3M9XFxcIlwiLmNvbmNhdCh0aGlzLm9wdGlvbnMudGhlYWRDbGFzc2VzLCBcIlxcXCI+PC90aGVhZD5cIikpLmFwcGVuZFRvKHRoaXMuJGVsKTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLm9wdGlvbnMudGhlYWRDbGFzc2VzKSB7XG4gICAgICAgICAgdGhpcy4kaGVhZGVyLmFkZENsYXNzKHRoaXMub3B0aW9ucy50aGVhZENsYXNzZXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5faGVhZGVyVHJDbGFzc2VzID0gW107XG4gICAgICAgIHRoaXMuX2hlYWRlclRyU3R5bGVzID0gW107XG4gICAgICAgIHRoaXMuJGhlYWRlci5maW5kKCd0cicpLmVhY2goZnVuY3Rpb24gKGksIGVsKSB7XG4gICAgICAgICAgdmFyICR0ciA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlbCk7XG4gICAgICAgICAgdmFyIGNvbHVtbiA9IFtdO1xuICAgICAgICAgICR0ci5maW5kKCd0aCcpLmVhY2goZnVuY3Rpb24gKGksIGVsKSB7XG4gICAgICAgICAgICB2YXIgJHRoID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKTsgLy8gIzIwMTQ6IGdldEZpZWxkSW5kZXggYW5kIGVsc2V3aGVyZSBhc3N1bWUgdGhpcyBpcyBzdHJpbmcsIGNhdXNlcyBpc3N1ZXMgaWYgbm90XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgJHRoLmRhdGEoJ2ZpZWxkJykgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICR0aC5kYXRhKCdmaWVsZCcsIFwiXCIuY29uY2F0KCR0aC5kYXRhKCdmaWVsZCcpKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbHVtbi5wdXNoKCRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5leHRlbmQoe30sIHtcbiAgICAgICAgICAgICAgdGl0bGU6ICR0aC5odG1sKCksXG4gICAgICAgICAgICAgIGNsYXNzOiAkdGguYXR0cignY2xhc3MnKSxcbiAgICAgICAgICAgICAgdGl0bGVUb29sdGlwOiAkdGguYXR0cigndGl0bGUnKSxcbiAgICAgICAgICAgICAgcm93c3BhbjogJHRoLmF0dHIoJ3Jvd3NwYW4nKSA/ICskdGguYXR0cigncm93c3BhbicpIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICBjb2xzcGFuOiAkdGguYXR0cignY29sc3BhbicpID8gKyR0aC5hdHRyKCdjb2xzcGFuJykgOiB1bmRlZmluZWRcbiAgICAgICAgICAgIH0sICR0aC5kYXRhKCkpKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBjb2x1bW5zLnB1c2goY29sdW1uKTtcblxuICAgICAgICAgIGlmICgkdHIuYXR0cignY2xhc3MnKSkge1xuICAgICAgICAgICAgX3RoaXMuX2hlYWRlclRyQ2xhc3Nlcy5wdXNoKCR0ci5hdHRyKCdjbGFzcycpKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoJHRyLmF0dHIoJ3N0eWxlJykpIHtcbiAgICAgICAgICAgIF90aGlzLl9oZWFkZXJUclN0eWxlcy5wdXNoKCR0ci5hdHRyKCdzdHlsZScpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICghQXJyYXkuaXNBcnJheSh0aGlzLm9wdGlvbnMuY29sdW1uc1swXSkpIHtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMuY29sdW1ucyA9IFt0aGlzLm9wdGlvbnMuY29sdW1uc107XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm9wdGlvbnMuY29sdW1ucyA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5leHRlbmQodHJ1ZSwgW10sIGNvbHVtbnMsIHRoaXMub3B0aW9ucy5jb2x1bW5zKTtcbiAgICAgICAgdGhpcy5jb2x1bW5zID0gW107XG4gICAgICAgIHRoaXMuZmllbGRzQ29sdW1uc0luZGV4ID0gW107XG4gICAgICAgIFV0aWxzLnNldEZpZWxkSW5kZXgodGhpcy5vcHRpb25zLmNvbHVtbnMpO1xuICAgICAgICB0aGlzLm9wdGlvbnMuY29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW5zLCBpKSB7XG4gICAgICAgICAgY29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChfY29sdW1uLCBqKSB7XG4gICAgICAgICAgICB2YXIgY29sdW1uID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddLmV4dGVuZCh7fSwgQm9vdHN0cmFwVGFibGUuQ09MVU1OX0RFRkFVTFRTLCBfY29sdW1uKTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBjb2x1bW4uZmllbGRJbmRleCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgX3RoaXMuY29sdW1uc1tjb2x1bW4uZmllbGRJbmRleF0gPSBjb2x1bW47XG4gICAgICAgICAgICAgIF90aGlzLmZpZWxkc0NvbHVtbnNJbmRleFtjb2x1bW4uZmllbGRdID0gY29sdW1uLmZpZWxkSW5kZXg7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIF90aGlzLm9wdGlvbnMuY29sdW1uc1tpXVtqXSA9IGNvbHVtbjtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7IC8vIGlmIG9wdGlvbnMuZGF0YSBpcyBzZXR0aW5nLCBkbyBub3QgcHJvY2VzcyB0Ym9keSBhbmQgdGZvb3QgZGF0YVxuXG4gICAgICAgIGlmICghdGhpcy5vcHRpb25zLmRhdGEubGVuZ3RoKSB7XG4gICAgICAgICAgdmFyIGh0bWxEYXRhID0gVXRpbHMudHJUb0RhdGEodGhpcy5jb2x1bW5zLCB0aGlzLiRlbC5maW5kKCc+dGJvZHk+dHInKSk7XG5cbiAgICAgICAgICBpZiAoaHRtbERhdGEubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aGlzLm9wdGlvbnMuZGF0YSA9IGh0bWxEYXRhO1xuICAgICAgICAgICAgdGhpcy5mcm9tSHRtbCA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEodGhpcy5vcHRpb25zLnBhZ2luYXRpb24gJiYgdGhpcy5vcHRpb25zLnNpZGVQYWdpbmF0aW9uICE9PSAnc2VydmVyJykpIHtcbiAgICAgICAgICB0aGlzLmZvb3RlckRhdGEgPSBVdGlscy50clRvRGF0YSh0aGlzLmNvbHVtbnMsIHRoaXMuJGVsLmZpbmQoJz50Zm9vdD50cicpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmZvb3RlckRhdGEpIHtcbiAgICAgICAgICB0aGlzLiRlbC5maW5kKCd0Zm9vdCcpLmh0bWwoJzx0cj48L3RyPicpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0aGlzLm9wdGlvbnMuc2hvd0Zvb3RlciB8fCB0aGlzLm9wdGlvbnMuY2FyZFZpZXcpIHtcbiAgICAgICAgICB0aGlzLiR0YWJsZUZvb3Rlci5oaWRlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy4kdGFibGVGb290ZXIuc2hvdygpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImluaXRIZWFkZXJcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0SGVhZGVyKCkge1xuICAgICAgICB2YXIgX3RoaXMyID0gdGhpcztcblxuICAgICAgICB2YXIgdmlzaWJsZUNvbHVtbnMgPSB7fTtcbiAgICAgICAgdmFyIGhlYWRlckh0bWwgPSBbXTtcbiAgICAgICAgdGhpcy5oZWFkZXIgPSB7XG4gICAgICAgICAgZmllbGRzOiBbXSxcbiAgICAgICAgICBzdHlsZXM6IFtdLFxuICAgICAgICAgIGNsYXNzZXM6IFtdLFxuICAgICAgICAgIGZvcm1hdHRlcnM6IFtdLFxuICAgICAgICAgIGRldGFpbEZvcm1hdHRlcnM6IFtdLFxuICAgICAgICAgIGV2ZW50czogW10sXG4gICAgICAgICAgc29ydGVyczogW10sXG4gICAgICAgICAgc29ydE5hbWVzOiBbXSxcbiAgICAgICAgICBjZWxsU3R5bGVzOiBbXSxcbiAgICAgICAgICBzZWFyY2hhYmxlczogW11cbiAgICAgICAgfTtcbiAgICAgICAgVXRpbHMudXBkYXRlRmllbGRHcm91cCh0aGlzLm9wdGlvbnMuY29sdW1ucyk7XG4gICAgICAgIHRoaXMub3B0aW9ucy5jb2x1bW5zLmZvckVhY2goZnVuY3Rpb24gKGNvbHVtbnMsIGkpIHtcbiAgICAgICAgICB2YXIgaHRtbCA9IFtdO1xuICAgICAgICAgIGh0bWwucHVzaChcIjx0clwiLmNvbmNhdChVdGlscy5zcHJpbnRmKCcgY2xhc3M9XCIlc1wiJywgX3RoaXMyLl9oZWFkZXJUckNsYXNzZXNbaV0pLCBcIiBcIikuY29uY2F0KFV0aWxzLnNwcmludGYoJyBzdHlsZT1cIiVzXCInLCBfdGhpczIuX2hlYWRlclRyU3R5bGVzW2ldKSwgXCI+XCIpKTtcbiAgICAgICAgICB2YXIgZGV0YWlsVmlld1RlbXBsYXRlID0gJyc7XG5cbiAgICAgICAgICBpZiAoaSA9PT0gMCAmJiBVdGlscy5oYXNEZXRhaWxWaWV3SWNvbihfdGhpczIub3B0aW9ucykpIHtcbiAgICAgICAgICAgIHZhciByb3dzcGFuID0gX3RoaXMyLm9wdGlvbnMuY29sdW1ucy5sZW5ndGggPiAxID8gXCIgcm93c3Bhbj1cXFwiXCIuY29uY2F0KF90aGlzMi5vcHRpb25zLmNvbHVtbnMubGVuZ3RoLCBcIlxcXCJcIikgOiAnJztcbiAgICAgICAgICAgIGRldGFpbFZpZXdUZW1wbGF0ZSA9IFwiPHRoIGNsYXNzPVxcXCJkZXRhaWxcXFwiXCIuY29uY2F0KHJvd3NwYW4sIFwiPlxcbiAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJmaHQtY2VsbFxcXCI+PC9kaXY+XFxuICAgICAgICAgIDwvdGg+XCIpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChkZXRhaWxWaWV3VGVtcGxhdGUgJiYgX3RoaXMyLm9wdGlvbnMuZGV0YWlsVmlld0FsaWduICE9PSAncmlnaHQnKSB7XG4gICAgICAgICAgICBodG1sLnB1c2goZGV0YWlsVmlld1RlbXBsYXRlKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb2x1bW5zLmZvckVhY2goZnVuY3Rpb24gKGNvbHVtbiwgaikge1xuICAgICAgICAgICAgdmFyIGNsYXNzXyA9IFV0aWxzLnNwcmludGYoJyBjbGFzcz1cIiVzXCInLCBjb2x1bW5bJ2NsYXNzJ10pO1xuICAgICAgICAgICAgdmFyIHVuaXRXaWR0aCA9IGNvbHVtbi53aWR0aFVuaXQ7XG4gICAgICAgICAgICB2YXIgd2lkdGggPSBwYXJzZUZsb2F0KGNvbHVtbi53aWR0aCk7XG4gICAgICAgICAgICB2YXIgaGFsaWduID0gVXRpbHMuc3ByaW50ZigndGV4dC1hbGlnbjogJXM7ICcsIGNvbHVtbi5oYWxpZ24gPyBjb2x1bW4uaGFsaWduIDogY29sdW1uLmFsaWduKTtcbiAgICAgICAgICAgIHZhciBhbGlnbiA9IFV0aWxzLnNwcmludGYoJ3RleHQtYWxpZ246ICVzOyAnLCBjb2x1bW4uYWxpZ24pO1xuICAgICAgICAgICAgdmFyIHN0eWxlID0gVXRpbHMuc3ByaW50ZigndmVydGljYWwtYWxpZ246ICVzOyAnLCBjb2x1bW4udmFsaWduKTtcbiAgICAgICAgICAgIHN0eWxlICs9IFV0aWxzLnNwcmludGYoJ3dpZHRoOiAlczsgJywgKGNvbHVtbi5jaGVja2JveCB8fCBjb2x1bW4ucmFkaW8pICYmICF3aWR0aCA/ICFjb2x1bW4uc2hvd1NlbGVjdFRpdGxlID8gJzM2cHgnIDogdW5kZWZpbmVkIDogd2lkdGggPyB3aWR0aCArIHVuaXRXaWR0aCA6IHVuZGVmaW5lZCk7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgY29sdW1uLmZpZWxkSW5kZXggPT09ICd1bmRlZmluZWQnICYmICFjb2x1bW4udmlzaWJsZSkge1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBoZWFkZXJTdHlsZSA9IFV0aWxzLmNhbGN1bGF0ZU9iamVjdFZhbHVlKG51bGwsIF90aGlzMi5vcHRpb25zLmhlYWRlclN0eWxlLCBbY29sdW1uXSk7XG4gICAgICAgICAgICB2YXIgY3NzZXMgPSBbXTtcbiAgICAgICAgICAgIHZhciBjbGFzc2VzID0gJyc7XG5cbiAgICAgICAgICAgIGlmIChoZWFkZXJTdHlsZSAmJiBoZWFkZXJTdHlsZS5jc3MpIHtcbiAgICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfT2JqZWN0JGVudHJpZXMgPSBPYmplY3QuZW50cmllcyhoZWFkZXJTdHlsZS5jc3MpOyBfaSA8IF9PYmplY3QkZW50cmllcy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgX09iamVjdCRlbnRyaWVzJF9pID0gX3NsaWNlZFRvQXJyYXkoX09iamVjdCRlbnRyaWVzW19pXSwgMiksXG4gICAgICAgICAgICAgICAgICAgIGtleSA9IF9PYmplY3QkZW50cmllcyRfaVswXSxcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBfT2JqZWN0JGVudHJpZXMkX2lbMV07XG5cbiAgICAgICAgICAgICAgICBjc3Nlcy5wdXNoKFwiXCIuY29uY2F0KGtleSwgXCI6IFwiKS5jb25jYXQodmFsdWUpKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoaGVhZGVyU3R5bGUgJiYgaGVhZGVyU3R5bGUuY2xhc3Nlcykge1xuICAgICAgICAgICAgICBjbGFzc2VzID0gVXRpbHMuc3ByaW50ZignIGNsYXNzPVwiJXNcIicsIGNvbHVtblsnY2xhc3MnXSA/IFtjb2x1bW5bJ2NsYXNzJ10sIGhlYWRlclN0eWxlLmNsYXNzZXNdLmpvaW4oJyAnKSA6IGhlYWRlclN0eWxlLmNsYXNzZXMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIGNvbHVtbi5maWVsZEluZGV4ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICBfdGhpczIuaGVhZGVyLmZpZWxkc1tjb2x1bW4uZmllbGRJbmRleF0gPSBjb2x1bW4uZmllbGQ7XG4gICAgICAgICAgICAgIF90aGlzMi5oZWFkZXIuc3R5bGVzW2NvbHVtbi5maWVsZEluZGV4XSA9IGFsaWduICsgc3R5bGU7XG4gICAgICAgICAgICAgIF90aGlzMi5oZWFkZXIuY2xhc3Nlc1tjb2x1bW4uZmllbGRJbmRleF0gPSBjbGFzc187XG4gICAgICAgICAgICAgIF90aGlzMi5oZWFkZXIuZm9ybWF0dGVyc1tjb2x1bW4uZmllbGRJbmRleF0gPSBjb2x1bW4uZm9ybWF0dGVyO1xuICAgICAgICAgICAgICBfdGhpczIuaGVhZGVyLmRldGFpbEZvcm1hdHRlcnNbY29sdW1uLmZpZWxkSW5kZXhdID0gY29sdW1uLmRldGFpbEZvcm1hdHRlcjtcbiAgICAgICAgICAgICAgX3RoaXMyLmhlYWRlci5ldmVudHNbY29sdW1uLmZpZWxkSW5kZXhdID0gY29sdW1uLmV2ZW50cztcbiAgICAgICAgICAgICAgX3RoaXMyLmhlYWRlci5zb3J0ZXJzW2NvbHVtbi5maWVsZEluZGV4XSA9IGNvbHVtbi5zb3J0ZXI7XG4gICAgICAgICAgICAgIF90aGlzMi5oZWFkZXIuc29ydE5hbWVzW2NvbHVtbi5maWVsZEluZGV4XSA9IGNvbHVtbi5zb3J0TmFtZTtcbiAgICAgICAgICAgICAgX3RoaXMyLmhlYWRlci5jZWxsU3R5bGVzW2NvbHVtbi5maWVsZEluZGV4XSA9IGNvbHVtbi5jZWxsU3R5bGU7XG4gICAgICAgICAgICAgIF90aGlzMi5oZWFkZXIuc2VhcmNoYWJsZXNbY29sdW1uLmZpZWxkSW5kZXhdID0gY29sdW1uLnNlYXJjaGFibGU7XG5cbiAgICAgICAgICAgICAgaWYgKCFjb2x1bW4udmlzaWJsZSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGlmIChfdGhpczIub3B0aW9ucy5jYXJkVmlldyAmJiAhY29sdW1uLmNhcmRWaXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgdmlzaWJsZUNvbHVtbnNbY29sdW1uLmZpZWxkXSA9IGNvbHVtbjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaHRtbC5wdXNoKFwiPHRoXCIuY29uY2F0KFV0aWxzLnNwcmludGYoJyB0aXRsZT1cIiVzXCInLCBjb2x1bW4udGl0bGVUb29sdGlwKSksIGNvbHVtbi5jaGVja2JveCB8fCBjb2x1bW4ucmFkaW8gPyBVdGlscy5zcHJpbnRmKCcgY2xhc3M9XCJicy1jaGVja2JveCAlc1wiJywgY29sdW1uWydjbGFzcyddIHx8ICcnKSA6IGNsYXNzZXMgfHwgY2xhc3NfLCBVdGlscy5zcHJpbnRmKCcgc3R5bGU9XCIlc1wiJywgaGFsaWduICsgc3R5bGUgKyBjc3Nlcy5qb2luKCc7ICcpKSwgVXRpbHMuc3ByaW50ZignIHJvd3NwYW49XCIlc1wiJywgY29sdW1uLnJvd3NwYW4pLCBVdGlscy5zcHJpbnRmKCcgY29sc3Bhbj1cIiVzXCInLCBjb2x1bW4uY29sc3BhbiksIFV0aWxzLnNwcmludGYoJyBkYXRhLWZpZWxkPVwiJXNcIicsIGNvbHVtbi5maWVsZCksIC8vIElmIGBjb2x1bW5gIGlzIG5vdCB0aGUgZmlyc3QgZWxlbWVudCBvZiBgdGhpcy5vcHRpb25zLmNvbHVtbnNbMF1gLCB0aGVuIGNsYXNzTmFtZSAnZGF0YS1ub3QtZmlyc3QtdGgnIHNob3VsZCBiZSBhZGRlZC5cbiAgICAgICAgICAgIGogPT09IDAgJiYgaSA+IDAgPyAnIGRhdGEtbm90LWZpcnN0LXRoJyA6ICcnLCAnPicpO1xuICAgICAgICAgICAgaHRtbC5wdXNoKFV0aWxzLnNwcmludGYoJzxkaXYgY2xhc3M9XCJ0aC1pbm5lciAlc1wiPicsIF90aGlzMi5vcHRpb25zLnNvcnRhYmxlICYmIGNvbHVtbi5zb3J0YWJsZSA/ICdzb3J0YWJsZSBib3RoJyA6ICcnKSk7XG4gICAgICAgICAgICB2YXIgdGV4dCA9IF90aGlzMi5vcHRpb25zLmVzY2FwZSA/IFV0aWxzLmVzY2FwZUhUTUwoY29sdW1uLnRpdGxlKSA6IGNvbHVtbi50aXRsZTtcbiAgICAgICAgICAgIHZhciB0aXRsZSA9IHRleHQ7XG5cbiAgICAgICAgICAgIGlmIChjb2x1bW4uY2hlY2tib3gpIHtcbiAgICAgICAgICAgICAgdGV4dCA9ICcnO1xuXG4gICAgICAgICAgICAgIGlmICghX3RoaXMyLm9wdGlvbnMuc2luZ2xlU2VsZWN0ICYmIF90aGlzMi5vcHRpb25zLmNoZWNrYm94SGVhZGVyKSB7XG4gICAgICAgICAgICAgICAgdGV4dCA9ICc8bGFiZWw+PGlucHV0IG5hbWU9XCJidFNlbGVjdEFsbFwiIHR5cGU9XCJjaGVja2JveFwiIC8+PHNwYW4+PC9zcGFuPjwvbGFiZWw+JztcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIF90aGlzMi5oZWFkZXIuc3RhdGVGaWVsZCA9IGNvbHVtbi5maWVsZDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNvbHVtbi5yYWRpbykge1xuICAgICAgICAgICAgICB0ZXh0ID0gJyc7XG4gICAgICAgICAgICAgIF90aGlzMi5oZWFkZXIuc3RhdGVGaWVsZCA9IGNvbHVtbi5maWVsZDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCF0ZXh0ICYmIGNvbHVtbi5zaG93U2VsZWN0VGl0bGUpIHtcbiAgICAgICAgICAgICAgdGV4dCArPSB0aXRsZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaHRtbC5wdXNoKHRleHQpO1xuICAgICAgICAgICAgaHRtbC5wdXNoKCc8L2Rpdj4nKTtcbiAgICAgICAgICAgIGh0bWwucHVzaCgnPGRpdiBjbGFzcz1cImZodC1jZWxsXCI+PC9kaXY+Jyk7XG4gICAgICAgICAgICBodG1sLnB1c2goJzwvZGl2PicpO1xuICAgICAgICAgICAgaHRtbC5wdXNoKCc8L3RoPicpO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaWYgKGRldGFpbFZpZXdUZW1wbGF0ZSAmJiBfdGhpczIub3B0aW9ucy5kZXRhaWxWaWV3QWxpZ24gPT09ICdyaWdodCcpIHtcbiAgICAgICAgICAgIGh0bWwucHVzaChkZXRhaWxWaWV3VGVtcGxhdGUpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGh0bWwucHVzaCgnPC90cj4nKTtcblxuICAgICAgICAgIGlmIChodG1sLmxlbmd0aCA+IDMpIHtcbiAgICAgICAgICAgIGhlYWRlckh0bWwucHVzaChodG1sLmpvaW4oJycpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLiRoZWFkZXIuaHRtbChoZWFkZXJIdG1sLmpvaW4oJycpKTtcbiAgICAgICAgdGhpcy4kaGVhZGVyLmZpbmQoJ3RoW2RhdGEtZmllbGRdJykuZWFjaChmdW5jdGlvbiAoaSwgZWwpIHtcbiAgICAgICAgICAkX19kZWZhdWx0WydkZWZhdWx0J10oZWwpLmRhdGEodmlzaWJsZUNvbHVtbnNbJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKS5kYXRhKCdmaWVsZCcpXSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLiRjb250YWluZXIub2ZmKCdjbGljaycsICcudGgtaW5uZXInKS5vbignY2xpY2snLCAnLnRoLWlubmVyJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICB2YXIgJHRoaXMgPSAkX19kZWZhdWx0WydkZWZhdWx0J10oZS5jdXJyZW50VGFyZ2V0KTtcblxuICAgICAgICAgIGlmIChfdGhpczIub3B0aW9ucy5kZXRhaWxWaWV3ICYmICEkdGhpcy5wYXJlbnQoKS5oYXNDbGFzcygnYnMtY2hlY2tib3gnKSkge1xuICAgICAgICAgICAgaWYgKCR0aGlzLmNsb3Nlc3QoJy5ib290c3RyYXAtdGFibGUnKVswXSAhPT0gX3RoaXMyLiRjb250YWluZXJbMF0pIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChfdGhpczIub3B0aW9ucy5zb3J0YWJsZSAmJiAkdGhpcy5wYXJlbnQoKS5kYXRhKCkuc29ydGFibGUpIHtcbiAgICAgICAgICAgIF90aGlzMi5vblNvcnQoZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy4kaGVhZGVyLmNoaWxkcmVuKCkuY2hpbGRyZW4oKS5vZmYoJ2tleXByZXNzJykub24oJ2tleXByZXNzJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICBpZiAoX3RoaXMyLm9wdGlvbnMuc29ydGFibGUgJiYgJF9fZGVmYXVsdFsnZGVmYXVsdCddKGUuY3VycmVudFRhcmdldCkuZGF0YSgpLnNvcnRhYmxlKSB7XG4gICAgICAgICAgICB2YXIgY29kZSA9IGUua2V5Q29kZSB8fCBlLndoaWNoO1xuXG4gICAgICAgICAgICBpZiAoY29kZSA9PT0gMTMpIHtcbiAgICAgICAgICAgICAgLy8gRW50ZXIga2V5Y29kZVxuICAgICAgICAgICAgICBfdGhpczIub25Tb3J0KGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHZhciByZXNpemVFdmVudCA9IFV0aWxzLmdldEV2ZW50TmFtZSgncmVzaXplLmJvb3RzdHJhcC10YWJsZScsIHRoaXMuJGVsLmF0dHIoJ2lkJykpO1xuICAgICAgICAkX19kZWZhdWx0WydkZWZhdWx0J10od2luZG93KS5vZmYocmVzaXplRXZlbnQpO1xuXG4gICAgICAgIGlmICghdGhpcy5vcHRpb25zLnNob3dIZWFkZXIgfHwgdGhpcy5vcHRpb25zLmNhcmRWaWV3KSB7XG4gICAgICAgICAgdGhpcy4kaGVhZGVyLmhpZGUoKTtcbiAgICAgICAgICB0aGlzLiR0YWJsZUhlYWRlci5oaWRlKCk7XG4gICAgICAgICAgdGhpcy4kdGFibGVMb2FkaW5nLmNzcygndG9wJywgMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy4kaGVhZGVyLnNob3coKTtcbiAgICAgICAgICB0aGlzLiR0YWJsZUhlYWRlci5zaG93KCk7XG4gICAgICAgICAgdGhpcy4kdGFibGVMb2FkaW5nLmNzcygndG9wJywgdGhpcy4kaGVhZGVyLm91dGVySGVpZ2h0KCkgKyAxKTsgLy8gQXNzaWduIHRoZSBjb3JyZWN0IHNvcnRhYmxlIGFycm93XG5cbiAgICAgICAgICB0aGlzLmdldENhcmV0KCk7XG4gICAgICAgICAgJF9fZGVmYXVsdFsnZGVmYXVsdCddKHdpbmRvdykub24ocmVzaXplRXZlbnQsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBfdGhpczIucmVzZXRWaWV3KCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLiRzZWxlY3RBbGwgPSB0aGlzLiRoZWFkZXIuZmluZCgnW25hbWU9XCJidFNlbGVjdEFsbFwiXScpO1xuICAgICAgICB0aGlzLiRzZWxlY3RBbGwub2ZmKCdjbGljaycpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICB2YXIgY2hlY2tlZCA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlLmN1cnJlbnRUYXJnZXQpLnByb3AoJ2NoZWNrZWQnKTtcblxuICAgICAgICAgIF90aGlzMltjaGVja2VkID8gJ2NoZWNrQWxsJyA6ICd1bmNoZWNrQWxsJ10oKTtcblxuICAgICAgICAgIF90aGlzMi51cGRhdGVTZWxlY3RlZCgpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiaW5pdERhdGFcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0RGF0YShkYXRhLCB0eXBlKSB7XG4gICAgICAgIGlmICh0eXBlID09PSAnYXBwZW5kJykge1xuICAgICAgICAgIHRoaXMub3B0aW9ucy5kYXRhID0gdGhpcy5vcHRpb25zLmRhdGEuY29uY2F0KGRhdGEpO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdwcmVwZW5kJykge1xuICAgICAgICAgIHRoaXMub3B0aW9ucy5kYXRhID0gW10uY29uY2F0KGRhdGEpLmNvbmNhdCh0aGlzLm9wdGlvbnMuZGF0YSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZGF0YSA9IGRhdGEgfHwgVXRpbHMuZGVlcENvcHkodGhpcy5vcHRpb25zLmRhdGEpO1xuICAgICAgICAgIHRoaXMub3B0aW9ucy5kYXRhID0gQXJyYXkuaXNBcnJheShkYXRhKSA/IGRhdGEgOiBkYXRhW3RoaXMub3B0aW9ucy5kYXRhRmllbGRdO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5kYXRhID0gX3RvQ29uc3VtYWJsZUFycmF5KHRoaXMub3B0aW9ucy5kYXRhKTtcblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNvcnRSZXNldCkge1xuICAgICAgICAgIHRoaXMudW5zb3J0ZWREYXRhID0gX3RvQ29uc3VtYWJsZUFycmF5KHRoaXMuZGF0YSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNpZGVQYWdpbmF0aW9uID09PSAnc2VydmVyJykge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaW5pdFNvcnQoKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiaW5pdFNvcnRcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0U29ydCgpIHtcbiAgICAgICAgdmFyIF90aGlzMyA9IHRoaXM7XG5cbiAgICAgICAgdmFyIG5hbWUgPSB0aGlzLm9wdGlvbnMuc29ydE5hbWU7XG4gICAgICAgIHZhciBvcmRlciA9IHRoaXMub3B0aW9ucy5zb3J0T3JkZXIgPT09ICdkZXNjJyA/IC0xIDogMTtcbiAgICAgICAgdmFyIGluZGV4ID0gdGhpcy5oZWFkZXIuZmllbGRzLmluZGV4T2YodGhpcy5vcHRpb25zLnNvcnROYW1lKTtcbiAgICAgICAgdmFyIHRpbWVvdXRJZCA9IDA7XG5cbiAgICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMuc29ydFN0YWJsZSkge1xuICAgICAgICAgICAgdGhpcy5kYXRhLmZvckVhY2goZnVuY3Rpb24gKHJvdywgaSkge1xuICAgICAgICAgICAgICBpZiAoIXJvdy5oYXNPd25Qcm9wZXJ0eSgnX3Bvc2l0aW9uJykpIHtcbiAgICAgICAgICAgICAgICByb3cuX3Bvc2l0aW9uID0gaTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5jdXN0b21Tb3J0KSB7XG4gICAgICAgICAgICBVdGlscy5jYWxjdWxhdGVPYmplY3RWYWx1ZSh0aGlzLm9wdGlvbnMsIHRoaXMub3B0aW9ucy5jdXN0b21Tb3J0LCBbdGhpcy5vcHRpb25zLnNvcnROYW1lLCB0aGlzLm9wdGlvbnMuc29ydE9yZGVyLCB0aGlzLmRhdGFdKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5kYXRhLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgICAgICAgaWYgKF90aGlzMy5oZWFkZXIuc29ydE5hbWVzW2luZGV4XSkge1xuICAgICAgICAgICAgICAgIG5hbWUgPSBfdGhpczMuaGVhZGVyLnNvcnROYW1lc1tpbmRleF07XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICB2YXIgYWEgPSBVdGlscy5nZXRJdGVtRmllbGQoYSwgbmFtZSwgX3RoaXMzLm9wdGlvbnMuZXNjYXBlKTtcbiAgICAgICAgICAgICAgdmFyIGJiID0gVXRpbHMuZ2V0SXRlbUZpZWxkKGIsIG5hbWUsIF90aGlzMy5vcHRpb25zLmVzY2FwZSk7XG4gICAgICAgICAgICAgIHZhciB2YWx1ZSA9IFV0aWxzLmNhbGN1bGF0ZU9iamVjdFZhbHVlKF90aGlzMy5oZWFkZXIsIF90aGlzMy5oZWFkZXIuc29ydGVyc1tpbmRleF0sIFthYSwgYmIsIGEsIGJdKTtcblxuICAgICAgICAgICAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpczMub3B0aW9ucy5zb3J0U3RhYmxlICYmIHZhbHVlID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gb3JkZXIgKiAoYS5fcG9zaXRpb24gLSBiLl9wb3NpdGlvbik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9yZGVyICogdmFsdWU7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICByZXR1cm4gVXRpbHMuc29ydChhYSwgYmIsIG9yZGVyLCBfdGhpczMub3B0aW9ucy5zb3J0U3RhYmxlLCBhLl9wb3NpdGlvbiwgYi5fcG9zaXRpb24pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5zb3J0Q2xhc3MgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXRJZCk7XG4gICAgICAgICAgICB0aW1lb3V0SWQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgX3RoaXMzLiRlbC5yZW1vdmVDbGFzcyhfdGhpczMub3B0aW9ucy5zb3J0Q2xhc3MpO1xuXG4gICAgICAgICAgICAgIHZhciBpbmRleCA9IF90aGlzMy4kaGVhZGVyLmZpbmQoXCJbZGF0YS1maWVsZD1cXFwiXCIuY29uY2F0KF90aGlzMy5vcHRpb25zLnNvcnROYW1lLCBcIlxcXCJdXCIpKS5pbmRleCgpO1xuXG4gICAgICAgICAgICAgIF90aGlzMy4kZWwuZmluZChcInRyIHRkOm50aC1jaGlsZChcIi5jb25jYXQoaW5kZXggKyAxLCBcIilcIikpLmFkZENsYXNzKF90aGlzMy5vcHRpb25zLnNvcnRDbGFzcyk7XG4gICAgICAgICAgICB9LCAyNTApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLm9wdGlvbnMuc29ydFJlc2V0KSB7XG4gICAgICAgICAgdGhpcy5kYXRhID0gX3RvQ29uc3VtYWJsZUFycmF5KHRoaXMudW5zb3J0ZWREYXRhKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJvblNvcnRcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBvblNvcnQoX3JlZikge1xuICAgICAgICB2YXIgdHlwZSA9IF9yZWYudHlwZSxcbiAgICAgICAgICAgIGN1cnJlbnRUYXJnZXQgPSBfcmVmLmN1cnJlbnRUYXJnZXQ7XG4gICAgICAgIHZhciAkdGhpcyA9IHR5cGUgPT09ICdrZXlwcmVzcycgPyAkX19kZWZhdWx0WydkZWZhdWx0J10oY3VycmVudFRhcmdldCkgOiAkX19kZWZhdWx0WydkZWZhdWx0J10oY3VycmVudFRhcmdldCkucGFyZW50KCk7XG4gICAgICAgIHZhciAkdGhpc18gPSB0aGlzLiRoZWFkZXIuZmluZCgndGgnKS5lcSgkdGhpcy5pbmRleCgpKTtcbiAgICAgICAgdGhpcy4kaGVhZGVyLmFkZCh0aGlzLiRoZWFkZXJfKS5maW5kKCdzcGFuLm9yZGVyJykucmVtb3ZlKCk7XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5zb3J0TmFtZSA9PT0gJHRoaXMuZGF0YSgnZmllbGQnKSkge1xuICAgICAgICAgIHZhciBjdXJyZW50U29ydE9yZGVyID0gdGhpcy5vcHRpb25zLnNvcnRPcmRlcjtcblxuICAgICAgICAgIGlmIChjdXJyZW50U29ydE9yZGVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMub3B0aW9ucy5zb3J0T3JkZXIgPSAnYXNjJztcbiAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRTb3J0T3JkZXIgPT09ICdhc2MnKSB7XG4gICAgICAgICAgICB0aGlzLm9wdGlvbnMuc29ydE9yZGVyID0gJ2Rlc2MnO1xuICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5vcHRpb25zLnNvcnRPcmRlciA9PT0gJ2Rlc2MnKSB7XG4gICAgICAgICAgICB0aGlzLm9wdGlvbnMuc29ydE9yZGVyID0gdGhpcy5vcHRpb25zLnNvcnRSZXNldCA/IHVuZGVmaW5lZCA6ICdhc2MnO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMuc29ydE9yZGVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMub3B0aW9ucy5zb3J0TmFtZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5vcHRpb25zLnNvcnROYW1lID0gJHRoaXMuZGF0YSgnZmllbGQnKTtcblxuICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMucmVtZW1iZXJPcmRlcikge1xuICAgICAgICAgICAgdGhpcy5vcHRpb25zLnNvcnRPcmRlciA9ICR0aGlzLmRhdGEoJ29yZGVyJykgPT09ICdhc2MnID8gJ2Rlc2MnIDogJ2FzYyc7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMub3B0aW9ucy5zb3J0T3JkZXIgPSB0aGlzLmNvbHVtbnNbdGhpcy5maWVsZHNDb2x1bW5zSW5kZXhbJHRoaXMuZGF0YSgnZmllbGQnKV1dLnNvcnRPcmRlciB8fCB0aGlzLmNvbHVtbnNbdGhpcy5maWVsZHNDb2x1bW5zSW5kZXhbJHRoaXMuZGF0YSgnZmllbGQnKV1dLm9yZGVyO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudHJpZ2dlcignc29ydCcsIHRoaXMub3B0aW9ucy5zb3J0TmFtZSwgdGhpcy5vcHRpb25zLnNvcnRPcmRlcik7XG4gICAgICAgICR0aGlzLmFkZCgkdGhpc18pLmRhdGEoJ29yZGVyJywgdGhpcy5vcHRpb25zLnNvcnRPcmRlcik7IC8vIEFzc2lnbiB0aGUgY29ycmVjdCBzb3J0YWJsZSBhcnJvd1xuXG4gICAgICAgIHRoaXMuZ2V0Q2FyZXQoKTtcblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNpZGVQYWdpbmF0aW9uID09PSAnc2VydmVyJyAmJiB0aGlzLm9wdGlvbnMuc2VydmVyU29ydCkge1xuICAgICAgICAgIHRoaXMub3B0aW9ucy5wYWdlTnVtYmVyID0gMTtcbiAgICAgICAgICB0aGlzLmluaXRTZXJ2ZXIodGhpcy5vcHRpb25zLnNpbGVudFNvcnQpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaW5pdFNvcnQoKTtcbiAgICAgICAgdGhpcy5pbml0Qm9keSgpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJpbml0VG9vbGJhclwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGluaXRUb29sYmFyKCkge1xuICAgICAgICB2YXIgX3RoaXM0ID0gdGhpcztcblxuICAgICAgICB2YXIgb3B0cyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgdmFyIGh0bWwgPSBbXTtcbiAgICAgICAgdmFyIHRpbWVvdXRJZCA9IDA7XG4gICAgICAgIHZhciAka2VlcE9wZW47XG4gICAgICAgIHZhciBzd2l0Y2hhYmxlQ291bnQgPSAwO1xuXG4gICAgICAgIGlmICh0aGlzLiR0b29sYmFyLmZpbmQoJy5icy1iYXJzJykuY2hpbGRyZW4oKS5sZW5ndGgpIHtcbiAgICAgICAgICAkX19kZWZhdWx0WydkZWZhdWx0J10oJ2JvZHknKS5hcHBlbmQoJF9fZGVmYXVsdFsnZGVmYXVsdCddKG9wdHMudG9vbGJhcikpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy4kdG9vbGJhci5odG1sKCcnKTtcblxuICAgICAgICBpZiAodHlwZW9mIG9wdHMudG9vbGJhciA9PT0gJ3N0cmluZycgfHwgX3R5cGVvZihvcHRzLnRvb2xiYXIpID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShVdGlscy5zcHJpbnRmKCc8ZGl2IGNsYXNzPVwiYnMtYmFycyAlcy0lc1wiPjwvZGl2PicsIHRoaXMuY29uc3RhbnRzLmNsYXNzZXMucHVsbCwgb3B0cy50b29sYmFyQWxpZ24pKS5hcHBlbmRUbyh0aGlzLiR0b29sYmFyKS5hcHBlbmQoJF9fZGVmYXVsdFsnZGVmYXVsdCddKG9wdHMudG9vbGJhcikpO1xuICAgICAgICB9IC8vIHNob3dDb2x1bW5zLCBzaG93VG9nZ2xlLCBzaG93UmVmcmVzaFxuXG5cbiAgICAgICAgaHRtbCA9IFtcIjxkaXYgY2xhc3M9XFxcIlwiLmNvbmNhdChbJ2NvbHVtbnMnLCBcImNvbHVtbnMtXCIuY29uY2F0KG9wdHMuYnV0dG9uc0FsaWduKSwgdGhpcy5jb25zdGFudHMuY2xhc3Nlcy5idXR0b25zR3JvdXAsIFwiXCIuY29uY2F0KHRoaXMuY29uc3RhbnRzLmNsYXNzZXMucHVsbCwgXCItXCIpLmNvbmNhdChvcHRzLmJ1dHRvbnNBbGlnbildLmpvaW4oJyAnKSwgXCJcXFwiPlwiKV07XG5cbiAgICAgICAgaWYgKHR5cGVvZiBvcHRzLmJ1dHRvbnNPcmRlciA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBvcHRzLmJ1dHRvbnNPcmRlciA9IG9wdHMuYnV0dG9uc09yZGVyLnJlcGxhY2UoL1xcW3xcXF18IHwnL2csICcnKS5zcGxpdCgnLCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5idXR0b25zID0gT2JqZWN0LmFzc2lnbih0aGlzLmJ1dHRvbnMsIHtcbiAgICAgICAgICBwYWdpbmF0aW9uU3dpdGNoOiB7XG4gICAgICAgICAgICB0ZXh0OiBvcHRzLnBhZ2luYXRpb24gPyBvcHRzLmZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcCgpIDogb3B0cy5mb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bigpLFxuICAgICAgICAgICAgaWNvbjogb3B0cy5wYWdpbmF0aW9uID8gb3B0cy5pY29ucy5wYWdpbmF0aW9uU3dpdGNoRG93biA6IG9wdHMuaWNvbnMucGFnaW5hdGlvblN3aXRjaFVwLFxuICAgICAgICAgICAgcmVuZGVyOiBmYWxzZSxcbiAgICAgICAgICAgIGV2ZW50OiB0aGlzLnRvZ2dsZVBhZ2luYXRpb24sXG4gICAgICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgICAgICdhcmlhLWxhYmVsJzogb3B0cy5mb3JtYXRQYWdpbmF0aW9uU3dpdGNoKCksXG4gICAgICAgICAgICAgIHRpdGxlOiBvcHRzLmZvcm1hdFBhZ2luYXRpb25Td2l0Y2goKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgcmVmcmVzaDoge1xuICAgICAgICAgICAgdGV4dDogb3B0cy5mb3JtYXRSZWZyZXNoKCksXG4gICAgICAgICAgICBpY29uOiBvcHRzLmljb25zLnJlZnJlc2gsXG4gICAgICAgICAgICByZW5kZXI6IGZhbHNlLFxuICAgICAgICAgICAgZXZlbnQ6IHRoaXMucmVmcmVzaCxcbiAgICAgICAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgICAgICAgJ2FyaWEtbGFiZWwnOiBvcHRzLmZvcm1hdFJlZnJlc2goKSxcbiAgICAgICAgICAgICAgdGl0bGU6IG9wdHMuZm9ybWF0UmVmcmVzaCgpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICB0b2dnbGU6IHtcbiAgICAgICAgICAgIHRleHQ6IG9wdHMuZm9ybWF0VG9nZ2xlKCksXG4gICAgICAgICAgICBpY29uOiBvcHRzLmljb25zLnRvZ2dsZU9mZixcbiAgICAgICAgICAgIHJlbmRlcjogZmFsc2UsXG4gICAgICAgICAgICBldmVudDogdGhpcy50b2dnbGVWaWV3LFxuICAgICAgICAgICAgYXR0cmlidXRlczoge1xuICAgICAgICAgICAgICAnYXJpYS1sYWJlbCc6IG9wdHMuZm9ybWF0VG9nZ2xlT24oKSxcbiAgICAgICAgICAgICAgdGl0bGU6IG9wdHMuZm9ybWF0VG9nZ2xlT24oKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgZnVsbHNjcmVlbjoge1xuICAgICAgICAgICAgdGV4dDogb3B0cy5mb3JtYXRGdWxsc2NyZWVuKCksXG4gICAgICAgICAgICBpY29uOiBvcHRzLmljb25zLmZ1bGxzY3JlZW4sXG4gICAgICAgICAgICByZW5kZXI6IGZhbHNlLFxuICAgICAgICAgICAgZXZlbnQ6IHRoaXMudG9nZ2xlRnVsbHNjcmVlbixcbiAgICAgICAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgICAgICAgJ2FyaWEtbGFiZWwnOiBvcHRzLmZvcm1hdEZ1bGxzY3JlZW4oKSxcbiAgICAgICAgICAgICAgdGl0bGU6IG9wdHMuZm9ybWF0RnVsbHNjcmVlbigpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBjb2x1bW5zOiB7XG4gICAgICAgICAgICByZW5kZXI6IGZhbHNlLFxuICAgICAgICAgICAgaHRtbDogZnVuY3Rpb24gaHRtbCgpIHtcbiAgICAgICAgICAgICAgdmFyIGh0bWwgPSBbXTtcbiAgICAgICAgICAgICAgaHRtbC5wdXNoKFwiPGRpdiBjbGFzcz1cXFwia2VlcC1vcGVuIFwiLmNvbmNhdChfdGhpczQuY29uc3RhbnRzLmNsYXNzZXMuYnV0dG9uc0Ryb3Bkb3duLCBcIlxcXCIgdGl0bGU9XFxcIlwiKS5jb25jYXQob3B0cy5mb3JtYXRDb2x1bW5zKCksIFwiXFxcIj5cXG4gICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVxcXCJcIikuY29uY2F0KF90aGlzNC5jb25zdGFudHMuYnV0dG9uc0NsYXNzLCBcIiBkcm9wZG93bi10b2dnbGVcXFwiIHR5cGU9XFxcImJ1dHRvblxcXCIgXCIpLmNvbmNhdChfdGhpczQuY29uc3RhbnRzLmRhdGFUb2dnbGUsIFwiPVxcXCJkcm9wZG93blxcXCJcXG4gICAgICAgICAgICBhcmlhLWxhYmVsPVxcXCJDb2x1bW5zXFxcIiB0aXRsZT1cXFwiXCIpLmNvbmNhdChvcHRzLmZvcm1hdENvbHVtbnMoKSwgXCJcXFwiPlxcbiAgICAgICAgICAgIFwiKS5jb25jYXQob3B0cy5zaG93QnV0dG9uSWNvbnMgPyBVdGlscy5zcHJpbnRmKF90aGlzNC5jb25zdGFudHMuaHRtbC5pY29uLCBvcHRzLmljb25zUHJlZml4LCBvcHRzLmljb25zLmNvbHVtbnMpIDogJycsIFwiXFxuICAgICAgICAgICAgXCIpLmNvbmNhdChvcHRzLnNob3dCdXR0b25UZXh0ID8gb3B0cy5mb3JtYXRDb2x1bW5zKCkgOiAnJywgXCJcXG4gICAgICAgICAgICBcIikuY29uY2F0KF90aGlzNC5jb25zdGFudHMuaHRtbC5kcm9wZG93bkNhcmV0LCBcIlxcbiAgICAgICAgICAgIDwvYnV0dG9uPlxcbiAgICAgICAgICAgIFwiKS5jb25jYXQoX3RoaXM0LmNvbnN0YW50cy5odG1sLnRvb2xiYXJEcm9wZG93blswXSkpO1xuXG4gICAgICAgICAgICAgIGlmIChvcHRzLnNob3dDb2x1bW5zU2VhcmNoKSB7XG4gICAgICAgICAgICAgICAgaHRtbC5wdXNoKFV0aWxzLnNwcmludGYoX3RoaXM0LmNvbnN0YW50cy5odG1sLnRvb2xiYXJEcm9wZG93bkl0ZW0sIFV0aWxzLnNwcmludGYoJzxpbnB1dCB0eXBlPVwidGV4dFwiIGNsYXNzPVwiJXNcIiBuYW1lPVwiY29sdW1uc1NlYXJjaFwiIHBsYWNlaG9sZGVyPVwiJXNcIiBhdXRvY29tcGxldGU9XCJvZmZcIj4nLCBfdGhpczQuY29uc3RhbnRzLmNsYXNzZXMuaW5wdXQsIG9wdHMuZm9ybWF0U2VhcmNoKCkpKSk7XG4gICAgICAgICAgICAgICAgaHRtbC5wdXNoKF90aGlzNC5jb25zdGFudHMuaHRtbC50b29sYmFyRHJvcGRvd25TZXBhcmF0b3IpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKG9wdHMuc2hvd0NvbHVtbnNUb2dnbGVBbGwpIHtcbiAgICAgICAgICAgICAgICB2YXIgYWxsRmllbGRzVmlzaWJsZSA9IF90aGlzNC5nZXRWaXNpYmxlQ29sdW1ucygpLmxlbmd0aCA9PT0gX3RoaXM0LmNvbHVtbnMuZmlsdGVyKGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiAhX3RoaXM0LmlzU2VsZWN0aW9uQ29sdW1uKGNvbHVtbik7XG4gICAgICAgICAgICAgICAgfSkubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgaHRtbC5wdXNoKFV0aWxzLnNwcmludGYoX3RoaXM0LmNvbnN0YW50cy5odG1sLnRvb2xiYXJEcm9wZG93bkl0ZW0sIFV0aWxzLnNwcmludGYoJzxpbnB1dCB0eXBlPVwiY2hlY2tib3hcIiBjbGFzcz1cInRvZ2dsZS1hbGxcIiAlcz4gPHNwYW4+JXM8L3NwYW4+JywgYWxsRmllbGRzVmlzaWJsZSA/ICdjaGVja2VkPVwiY2hlY2tlZFwiJyA6ICcnLCBvcHRzLmZvcm1hdENvbHVtbnNUb2dnbGVBbGwoKSkpKTtcbiAgICAgICAgICAgICAgICBodG1sLnB1c2goX3RoaXM0LmNvbnN0YW50cy5odG1sLnRvb2xiYXJEcm9wZG93blNlcGFyYXRvcik7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICB2YXIgdmlzaWJsZUNvbHVtbnMgPSAwO1xuXG4gICAgICAgICAgICAgIF90aGlzNC5jb2x1bW5zLmZvckVhY2goZnVuY3Rpb24gKGNvbHVtbikge1xuICAgICAgICAgICAgICAgIGlmIChjb2x1bW4udmlzaWJsZSkge1xuICAgICAgICAgICAgICAgICAgdmlzaWJsZUNvbHVtbnMrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgIF90aGlzNC5jb2x1bW5zLmZvckVhY2goZnVuY3Rpb24gKGNvbHVtbiwgaSkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpczQuaXNTZWxlY3Rpb25Db2x1bW4oY29sdW1uKSkge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChvcHRzLmNhcmRWaWV3ICYmICFjb2x1bW4uY2FyZFZpc2libGUpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgY2hlY2tlZCA9IGNvbHVtbi52aXNpYmxlID8gJyBjaGVja2VkPVwiY2hlY2tlZFwiJyA6ICcnO1xuICAgICAgICAgICAgICAgIHZhciBkaXNhYmxlZCA9IHZpc2libGVDb2x1bW5zIDw9IG9wdHMubWluaW11bUNvdW50Q29sdW1ucyAmJiBjaGVja2VkID8gJyBkaXNhYmxlZD1cImRpc2FibGVkXCInIDogJyc7XG5cbiAgICAgICAgICAgICAgICBpZiAoY29sdW1uLnN3aXRjaGFibGUpIHtcbiAgICAgICAgICAgICAgICAgIGh0bWwucHVzaChVdGlscy5zcHJpbnRmKF90aGlzNC5jb25zdGFudHMuaHRtbC50b29sYmFyRHJvcGRvd25JdGVtLCBVdGlscy5zcHJpbnRmKCc8aW5wdXQgdHlwZT1cImNoZWNrYm94XCIgZGF0YS1maWVsZD1cIiVzXCIgdmFsdWU9XCIlc1wiJXMlcz4gPHNwYW4+JXM8L3NwYW4+JywgY29sdW1uLmZpZWxkLCBpLCBjaGVja2VkLCBkaXNhYmxlZCwgY29sdW1uLnRpdGxlKSkpO1xuICAgICAgICAgICAgICAgICAgc3dpdGNoYWJsZUNvdW50Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICBodG1sLnB1c2goX3RoaXM0LmNvbnN0YW50cy5odG1sLnRvb2xiYXJEcm9wZG93blsxXSwgJzwvZGl2PicpO1xuICAgICAgICAgICAgICByZXR1cm4gaHRtbC5qb2luKCcnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgYnV0dG9uc0h0bWwgPSB7fTtcblxuICAgICAgICBmb3IgKHZhciBfaTIgPSAwLCBfT2JqZWN0JGVudHJpZXMyID0gT2JqZWN0LmVudHJpZXModGhpcy5idXR0b25zKTsgX2kyIDwgX09iamVjdCRlbnRyaWVzMi5sZW5ndGg7IF9pMisrKSB7XG4gICAgICAgICAgdmFyIF9PYmplY3QkZW50cmllczIkX2kgPSBfc2xpY2VkVG9BcnJheShfT2JqZWN0JGVudHJpZXMyW19pMl0sIDIpLFxuICAgICAgICAgICAgICBidXR0b25OYW1lID0gX09iamVjdCRlbnRyaWVzMiRfaVswXSxcbiAgICAgICAgICAgICAgYnV0dG9uQ29uZmlnID0gX09iamVjdCRlbnRyaWVzMiRfaVsxXTtcblxuICAgICAgICAgIHZhciBidXR0b25IdG1sID0gdm9pZCAwO1xuXG4gICAgICAgICAgaWYgKGJ1dHRvbkNvbmZpZy5oYXNPd25Qcm9wZXJ0eSgnaHRtbCcpKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGJ1dHRvbkNvbmZpZy5odG1sID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgIGJ1dHRvbkh0bWwgPSBidXR0b25Db25maWcuaHRtbCgpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYnV0dG9uQ29uZmlnLmh0bWwgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIGJ1dHRvbkh0bWwgPSBidXR0b25Db25maWcuaHRtbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYnV0dG9uSHRtbCA9IFwiPGJ1dHRvbiBjbGFzcz1cXFwiXCIuY29uY2F0KHRoaXMuY29uc3RhbnRzLmJ1dHRvbnNDbGFzcywgXCJcXFwiIHR5cGU9XFxcImJ1dHRvblxcXCIgbmFtZT1cXFwiXCIpLmNvbmNhdChidXR0b25OYW1lLCBcIlxcXCJcIik7XG5cbiAgICAgICAgICAgIGlmIChidXR0b25Db25maWcuaGFzT3duUHJvcGVydHkoJ2F0dHJpYnV0ZXMnKSkge1xuICAgICAgICAgICAgICBmb3IgKHZhciBfaTMgPSAwLCBfT2JqZWN0JGVudHJpZXMzID0gT2JqZWN0LmVudHJpZXMoYnV0dG9uQ29uZmlnLmF0dHJpYnV0ZXMpOyBfaTMgPCBfT2JqZWN0JGVudHJpZXMzLmxlbmd0aDsgX2kzKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgX09iamVjdCRlbnRyaWVzMyRfaSA9IF9zbGljZWRUb0FycmF5KF9PYmplY3QkZW50cmllczNbX2kzXSwgMiksXG4gICAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZU5hbWUgPSBfT2JqZWN0JGVudHJpZXMzJF9pWzBdLFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IF9PYmplY3QkZW50cmllczMkX2lbMV07XG5cbiAgICAgICAgICAgICAgICBidXR0b25IdG1sICs9IFwiIFwiLmNvbmNhdChhdHRyaWJ1dGVOYW1lLCBcIj1cXFwiXCIpLmNvbmNhdCh2YWx1ZSwgXCJcXFwiXCIpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGJ1dHRvbkh0bWwgKz0gJz4nO1xuXG4gICAgICAgICAgICBpZiAob3B0cy5zaG93QnV0dG9uSWNvbnMgJiYgYnV0dG9uQ29uZmlnLmhhc093blByb3BlcnR5KCdpY29uJykpIHtcbiAgICAgICAgICAgICAgYnV0dG9uSHRtbCArPSBcIlwiLmNvbmNhdChVdGlscy5zcHJpbnRmKHRoaXMuY29uc3RhbnRzLmh0bWwuaWNvbiwgb3B0cy5pY29uc1ByZWZpeCwgYnV0dG9uQ29uZmlnLmljb24pLCBcIiBcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChvcHRzLnNob3dCdXR0b25UZXh0ICYmIGJ1dHRvbkNvbmZpZy5oYXNPd25Qcm9wZXJ0eSgndGV4dCcpKSB7XG4gICAgICAgICAgICAgIGJ1dHRvbkh0bWwgKz0gYnV0dG9uQ29uZmlnLnRleHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGJ1dHRvbkh0bWwgKz0gJzwvYnV0dG9uPic7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYnV0dG9uc0h0bWxbYnV0dG9uTmFtZV0gPSBidXR0b25IdG1sO1xuICAgICAgICAgIHZhciBvcHRpb25OYW1lID0gXCJzaG93XCIuY29uY2F0KGJ1dHRvbk5hbWUuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkpLmNvbmNhdChidXR0b25OYW1lLnN1YnN0cmluZygxKSk7XG4gICAgICAgICAgdmFyIHNob3dPcHRpb24gPSBvcHRzW29wdGlvbk5hbWVdO1xuXG4gICAgICAgICAgaWYgKCghYnV0dG9uQ29uZmlnLmhhc093blByb3BlcnR5KCdyZW5kZXInKSB8fCBidXR0b25Db25maWcuaGFzT3duUHJvcGVydHkoJ3JlbmRlcicpICYmIGJ1dHRvbkNvbmZpZy5yZW5kZXIpICYmIChzaG93T3B0aW9uID09PSB1bmRlZmluZWQgfHwgc2hvd09wdGlvbiA9PT0gdHJ1ZSkpIHtcbiAgICAgICAgICAgIG9wdHNbb3B0aW9uTmFtZV0gPSB0cnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghb3B0cy5idXR0b25zT3JkZXIuaW5jbHVkZXMoYnV0dG9uTmFtZSkpIHtcbiAgICAgICAgICAgIG9wdHMuYnV0dG9uc09yZGVyLnB1c2goYnV0dG9uTmFtZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IC8vIEFkZGluZyB0aGUgYnV0dG9uIGh0bWwgdG8gdGhlIGZpbmFsIHRvb2xiYXIgaHRtbCB3aGVuIHRoZSBzaG93T3B0aW9uIGlzIHRydWVcblxuXG4gICAgICAgIHZhciBfaXRlcmF0b3IgPSBfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlcihvcHRzLmJ1dHRvbnNPcmRlciksXG4gICAgICAgICAgICBfc3RlcDtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGZvciAoX2l0ZXJhdG9yLnMoKTsgIShfc3RlcCA9IF9pdGVyYXRvci5uKCkpLmRvbmU7KSB7XG4gICAgICAgICAgICB2YXIgYnV0dG9uID0gX3N0ZXAudmFsdWU7XG4gICAgICAgICAgICB2YXIgX3Nob3dPcHRpb24gPSBvcHRzW1wic2hvd1wiLmNvbmNhdChidXR0b24uY2hhckF0KDApLnRvVXBwZXJDYXNlKCkpLmNvbmNhdChidXR0b24uc3Vic3RyaW5nKDEpKV07XG5cbiAgICAgICAgICAgIGlmIChfc2hvd09wdGlvbikge1xuICAgICAgICAgICAgICBodG1sLnB1c2goYnV0dG9uc0h0bWxbYnV0dG9uXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBfaXRlcmF0b3IuZShlcnIpO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIF9pdGVyYXRvci5mKCk7XG4gICAgICAgIH1cblxuICAgICAgICBodG1sLnB1c2goJzwvZGl2PicpOyAvLyBGaXggIzE4ODogdGhpcy5zaG93VG9vbGJhciBpcyBmb3IgZXh0ZW5zaW9uc1xuXG4gICAgICAgIGlmICh0aGlzLnNob3dUb29sYmFyIHx8IGh0bWwubGVuZ3RoID4gMikge1xuICAgICAgICAgIHRoaXMuJHRvb2xiYXIuYXBwZW5kKGh0bWwuam9pbignJykpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yICh2YXIgX2k0ID0gMCwgX09iamVjdCRlbnRyaWVzNCA9IE9iamVjdC5lbnRyaWVzKHRoaXMuYnV0dG9ucyk7IF9pNCA8IF9PYmplY3QkZW50cmllczQubGVuZ3RoOyBfaTQrKykge1xuICAgICAgICAgIHZhciBfT2JqZWN0JGVudHJpZXM0JF9pID0gX3NsaWNlZFRvQXJyYXkoX09iamVjdCRlbnRyaWVzNFtfaTRdLCAyKSxcbiAgICAgICAgICAgICAgX2J1dHRvbk5hbWUgPSBfT2JqZWN0JGVudHJpZXM0JF9pWzBdLFxuICAgICAgICAgICAgICBfYnV0dG9uQ29uZmlnID0gX09iamVjdCRlbnRyaWVzNCRfaVsxXTtcblxuICAgICAgICAgIGlmIChfYnV0dG9uQ29uZmlnLmhhc093blByb3BlcnR5KCdldmVudCcpKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIF9idXR0b25Db25maWcuZXZlbnQgPT09ICdmdW5jdGlvbicgfHwgdHlwZW9mIF9idXR0b25Db25maWcuZXZlbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIHZhciBfcmV0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBldmVudCA9IHR5cGVvZiBfYnV0dG9uQ29uZmlnLmV2ZW50ID09PSAnc3RyaW5nJyA/IHdpbmRvd1tfYnV0dG9uQ29uZmlnLmV2ZW50XSA6IF9idXR0b25Db25maWcuZXZlbnQ7XG5cbiAgICAgICAgICAgICAgICBfdGhpczQuJHRvb2xiYXIuZmluZChcImJ1dHRvbltuYW1lPVxcXCJcIi5jb25jYXQoX2J1dHRvbk5hbWUsIFwiXFxcIl1cIikpLm9mZignY2xpY2snKS5vbignY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gZXZlbnQuY2FsbChfdGhpczQpO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIFwiY29udGludWVcIjtcbiAgICAgICAgICAgICAgfSgpO1xuXG4gICAgICAgICAgICAgIGlmIChfcmV0ID09PSBcImNvbnRpbnVlXCIpIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgX2xvb3AgPSBmdW5jdGlvbiBfbG9vcCgpIHtcbiAgICAgICAgICAgICAgdmFyIF9PYmplY3QkZW50cmllczUkX2kgPSBfc2xpY2VkVG9BcnJheShfT2JqZWN0JGVudHJpZXM1W19pNV0sIDIpLFxuICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlID0gX09iamVjdCRlbnRyaWVzNSRfaVswXSxcbiAgICAgICAgICAgICAgICAgIGV2ZW50RnVuY3Rpb24gPSBfT2JqZWN0JGVudHJpZXM1JF9pWzFdO1xuXG4gICAgICAgICAgICAgIHZhciBldmVudCA9IHR5cGVvZiBldmVudEZ1bmN0aW9uID09PSAnc3RyaW5nJyA/IHdpbmRvd1tldmVudEZ1bmN0aW9uXSA6IGV2ZW50RnVuY3Rpb247XG5cbiAgICAgICAgICAgICAgX3RoaXM0LiR0b29sYmFyLmZpbmQoXCJidXR0b25bbmFtZT1cXFwiXCIuY29uY2F0KF9idXR0b25OYW1lLCBcIlxcXCJdXCIpKS5vZmYoZXZlbnRUeXBlKS5vbihldmVudFR5cGUsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXZlbnQuY2FsbChfdGhpczQpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGZvciAodmFyIF9pNSA9IDAsIF9PYmplY3QkZW50cmllczUgPSBPYmplY3QuZW50cmllcyhfYnV0dG9uQ29uZmlnLmV2ZW50KTsgX2k1IDwgX09iamVjdCRlbnRyaWVzNS5sZW5ndGg7IF9pNSsrKSB7XG4gICAgICAgICAgICAgIF9sb29wKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG9wdHMuc2hvd0NvbHVtbnMpIHtcbiAgICAgICAgICAka2VlcE9wZW4gPSB0aGlzLiR0b29sYmFyLmZpbmQoJy5rZWVwLW9wZW4nKTtcbiAgICAgICAgICB2YXIgJGNoZWNrYm94ZXMgPSAka2VlcE9wZW4uZmluZCgnaW5wdXRbdHlwZT1cImNoZWNrYm94XCJdOm5vdChcIi50b2dnbGUtYWxsXCIpJyk7XG4gICAgICAgICAgdmFyICR0b2dnbGVBbGwgPSAka2VlcE9wZW4uZmluZCgnaW5wdXRbdHlwZT1cImNoZWNrYm94XCJdLnRvZ2dsZS1hbGwnKTtcblxuICAgICAgICAgIGlmIChzd2l0Y2hhYmxlQ291bnQgPD0gb3B0cy5taW5pbXVtQ291bnRDb2x1bW5zKSB7XG4gICAgICAgICAgICAka2VlcE9wZW4uZmluZCgnaW5wdXQnKS5wcm9wKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgICRrZWVwT3Blbi5maW5kKCdsaSwgbGFiZWwnKS5vZmYoJ2NsaWNrJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgJGNoZWNrYm94ZXMub2ZmKCdjbGljaycpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChfcmVmMikge1xuICAgICAgICAgICAgdmFyIGN1cnJlbnRUYXJnZXQgPSBfcmVmMi5jdXJyZW50VGFyZ2V0O1xuICAgICAgICAgICAgdmFyICR0aGlzID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKGN1cnJlbnRUYXJnZXQpO1xuXG4gICAgICAgICAgICBfdGhpczQuX3RvZ2dsZUNvbHVtbigkdGhpcy52YWwoKSwgJHRoaXMucHJvcCgnY2hlY2tlZCcpLCBmYWxzZSk7XG5cbiAgICAgICAgICAgIF90aGlzNC50cmlnZ2VyKCdjb2x1bW4tc3dpdGNoJywgJHRoaXMuZGF0YSgnZmllbGQnKSwgJHRoaXMucHJvcCgnY2hlY2tlZCcpKTtcblxuICAgICAgICAgICAgJHRvZ2dsZUFsbC5wcm9wKCdjaGVja2VkJywgJGNoZWNrYm94ZXMuZmlsdGVyKCc6Y2hlY2tlZCcpLmxlbmd0aCA9PT0gX3RoaXM0LmNvbHVtbnMuZmlsdGVyKGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgICAgcmV0dXJuICFfdGhpczQuaXNTZWxlY3Rpb25Db2x1bW4oY29sdW1uKTtcbiAgICAgICAgICAgIH0pLmxlbmd0aCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgJHRvZ2dsZUFsbC5vZmYoJ2NsaWNrJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKF9yZWYzKSB7XG4gICAgICAgICAgICB2YXIgY3VycmVudFRhcmdldCA9IF9yZWYzLmN1cnJlbnRUYXJnZXQ7XG5cbiAgICAgICAgICAgIF90aGlzNC5fdG9nZ2xlQWxsQ29sdW1ucygkX19kZWZhdWx0WydkZWZhdWx0J10oY3VycmVudFRhcmdldCkucHJvcCgnY2hlY2tlZCcpKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGlmIChvcHRzLnNob3dDb2x1bW5zU2VhcmNoKSB7XG4gICAgICAgICAgICB2YXIgJGNvbHVtbnNTZWFyY2ggPSAka2VlcE9wZW4uZmluZCgnW25hbWU9XCJjb2x1bW5zU2VhcmNoXCJdJyk7XG4gICAgICAgICAgICB2YXIgJGxpc3RJdGVtcyA9ICRrZWVwT3Blbi5maW5kKCcuZHJvcGRvd24taXRlbS1tYXJrZXInKTtcbiAgICAgICAgICAgICRjb2x1bW5zU2VhcmNoLm9uKCdrZXl1cCBwYXN0ZSBjaGFuZ2UnLCBmdW5jdGlvbiAoX3JlZjQpIHtcbiAgICAgICAgICAgICAgdmFyIGN1cnJlbnRUYXJnZXQgPSBfcmVmNC5jdXJyZW50VGFyZ2V0O1xuICAgICAgICAgICAgICB2YXIgJHRoaXMgPSAkX19kZWZhdWx0WydkZWZhdWx0J10oY3VycmVudFRhcmdldCk7XG4gICAgICAgICAgICAgIHZhciBzZWFyY2hWYWx1ZSA9ICR0aGlzLnZhbCgpLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgICAgICAgICRsaXN0SXRlbXMuc2hvdygpO1xuICAgICAgICAgICAgICAkY2hlY2tib3hlcy5lYWNoKGZ1bmN0aW9uIChpLCBlbCkge1xuICAgICAgICAgICAgICAgIHZhciAkY2hlY2tib3ggPSAkX19kZWZhdWx0WydkZWZhdWx0J10oZWwpO1xuICAgICAgICAgICAgICAgIHZhciAkbGlzdEl0ZW0gPSAkY2hlY2tib3gucGFyZW50cygnLmRyb3Bkb3duLWl0ZW0tbWFya2VyJyk7XG4gICAgICAgICAgICAgICAgdmFyIHRleHQgPSAkbGlzdEl0ZW0udGV4dCgpLnRvTG93ZXJDYXNlKCk7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXRleHQuaW5jbHVkZXMoc2VhcmNoVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAkbGlzdEl0ZW0uaGlkZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgaGFuZGxlSW5wdXRFdmVudCA9IGZ1bmN0aW9uIGhhbmRsZUlucHV0RXZlbnQoJHNlYXJjaElucHV0KSB7XG4gICAgICAgICAgdmFyIGV2ZW50VHJpZ2dlcnMgPSAna2V5dXAgZHJvcCBibHVyIG1vdXNldXAnO1xuICAgICAgICAgICRzZWFyY2hJbnB1dC5vZmYoZXZlbnRUcmlnZ2Vycykub24oZXZlbnRUcmlnZ2VycywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICBpZiAob3B0cy5zZWFyY2hPbkVudGVyS2V5ICYmIGV2ZW50LmtleUNvZGUgIT09IDEzKSB7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKFszNywgMzgsIDM5LCA0MF0uaW5jbHVkZXMoZXZlbnQua2V5Q29kZSkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dElkKTsgLy8gZG9lc24ndCBtYXR0ZXIgaWYgaXQncyAwXG5cbiAgICAgICAgICAgIHRpbWVvdXRJZCA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICBfdGhpczQub25TZWFyY2goe1xuICAgICAgICAgICAgICAgIGN1cnJlbnRUYXJnZXQ6IGV2ZW50LmN1cnJlbnRUYXJnZXRcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LCBvcHRzLnNlYXJjaFRpbWVPdXQpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9OyAvLyBGaXggIzQ1MTY6IHRoaXMuc2hvd1NlYXJjaENsZWFyQnV0dG9uIGlzIGZvciBleHRlbnNpb25zXG5cblxuICAgICAgICBpZiAoKG9wdHMuc2VhcmNoIHx8IHRoaXMuc2hvd1NlYXJjaENsZWFyQnV0dG9uKSAmJiB0eXBlb2Ygb3B0cy5zZWFyY2hTZWxlY3RvciAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBodG1sID0gW107XG4gICAgICAgICAgdmFyIHNob3dTZWFyY2hCdXR0b24gPSBVdGlscy5zcHJpbnRmKHRoaXMuY29uc3RhbnRzLmh0bWwuc2VhcmNoQnV0dG9uLCB0aGlzLmNvbnN0YW50cy5idXR0b25zQ2xhc3MsIG9wdHMuZm9ybWF0U2VhcmNoKCksIG9wdHMuc2hvd0J1dHRvbkljb25zID8gVXRpbHMuc3ByaW50Zih0aGlzLmNvbnN0YW50cy5odG1sLmljb24sIG9wdHMuaWNvbnNQcmVmaXgsIG9wdHMuaWNvbnMuc2VhcmNoKSA6ICcnLCBvcHRzLnNob3dCdXR0b25UZXh0ID8gb3B0cy5mb3JtYXRTZWFyY2goKSA6ICcnKTtcbiAgICAgICAgICB2YXIgc2hvd1NlYXJjaENsZWFyQnV0dG9uID0gVXRpbHMuc3ByaW50Zih0aGlzLmNvbnN0YW50cy5odG1sLnNlYXJjaENsZWFyQnV0dG9uLCB0aGlzLmNvbnN0YW50cy5idXR0b25zQ2xhc3MsIG9wdHMuZm9ybWF0Q2xlYXJTZWFyY2goKSwgb3B0cy5zaG93QnV0dG9uSWNvbnMgPyBVdGlscy5zcHJpbnRmKHRoaXMuY29uc3RhbnRzLmh0bWwuaWNvbiwgb3B0cy5pY29uc1ByZWZpeCwgb3B0cy5pY29ucy5jbGVhclNlYXJjaCkgOiAnJywgb3B0cy5zaG93QnV0dG9uVGV4dCA/IG9wdHMuZm9ybWF0Q2xlYXJTZWFyY2goKSA6ICcnKTtcbiAgICAgICAgICB2YXIgc2VhcmNoSW5wdXRIdG1sID0gXCI8aW5wdXQgY2xhc3M9XFxcIlwiLmNvbmNhdCh0aGlzLmNvbnN0YW50cy5jbGFzc2VzLmlucHV0LCBcIlxcbiAgICAgICAgXCIpLmNvbmNhdChVdGlscy5zcHJpbnRmKCcgJXMlcycsIHRoaXMuY29uc3RhbnRzLmNsYXNzZXMuaW5wdXRQcmVmaXgsIG9wdHMuaWNvblNpemUpLCBcIlxcbiAgICAgICAgc2VhcmNoLWlucHV0XFxcIiB0eXBlPVxcXCJzZWFyY2hcXFwiIHBsYWNlaG9sZGVyPVxcXCJcIikuY29uY2F0KG9wdHMuZm9ybWF0U2VhcmNoKCksIFwiXFxcIiBhdXRvY29tcGxldGU9XFxcIm9mZlxcXCI+XCIpO1xuICAgICAgICAgIHZhciBzZWFyY2hJbnB1dEZpbmFsSHRtbCA9IHNlYXJjaElucHV0SHRtbDtcblxuICAgICAgICAgIGlmIChvcHRzLnNob3dTZWFyY2hCdXR0b24gfHwgb3B0cy5zaG93U2VhcmNoQ2xlYXJCdXR0b24pIHtcbiAgICAgICAgICAgIHZhciBfYnV0dG9uc0h0bWwgPSAob3B0cy5zaG93U2VhcmNoQnV0dG9uID8gc2hvd1NlYXJjaEJ1dHRvbiA6ICcnKSArIChvcHRzLnNob3dTZWFyY2hDbGVhckJ1dHRvbiA/IHNob3dTZWFyY2hDbGVhckJ1dHRvbiA6ICcnKTtcblxuICAgICAgICAgICAgc2VhcmNoSW5wdXRGaW5hbEh0bWwgPSBvcHRzLnNlYXJjaCA/IFV0aWxzLnNwcmludGYodGhpcy5jb25zdGFudHMuaHRtbC5pbnB1dEdyb3VwLCBzZWFyY2hJbnB1dEh0bWwsIF9idXR0b25zSHRtbCkgOiBfYnV0dG9uc0h0bWw7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaHRtbC5wdXNoKFV0aWxzLnNwcmludGYoXCJcXG4gICAgICAgIDxkaXYgY2xhc3M9XFxcIlwiLmNvbmNhdCh0aGlzLmNvbnN0YW50cy5jbGFzc2VzLnB1bGwsIFwiLVwiKS5jb25jYXQob3B0cy5zZWFyY2hBbGlnbiwgXCIgc2VhcmNoIFwiKS5jb25jYXQodGhpcy5jb25zdGFudHMuY2xhc3Nlcy5pbnB1dEdyb3VwLCBcIlxcXCI+XFxuICAgICAgICAgICVzXFxuICAgICAgICA8L2Rpdj5cXG4gICAgICBcIiksIHNlYXJjaElucHV0RmluYWxIdG1sKSk7XG4gICAgICAgICAgdGhpcy4kdG9vbGJhci5hcHBlbmQoaHRtbC5qb2luKCcnKSk7XG4gICAgICAgICAgdmFyICRzZWFyY2hJbnB1dCA9IFV0aWxzLmdldFNlYXJjaElucHV0KHRoaXMpO1xuXG4gICAgICAgICAgaWYgKG9wdHMuc2hvd1NlYXJjaEJ1dHRvbikge1xuICAgICAgICAgICAgdGhpcy4kdG9vbGJhci5maW5kKCcuc2VhcmNoIGJ1dHRvbltuYW1lPXNlYXJjaF0nKS5vZmYoJ2NsaWNrJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dElkKTsgLy8gZG9lc24ndCBtYXR0ZXIgaWYgaXQncyAwXG5cbiAgICAgICAgICAgICAgdGltZW91dElkID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXM0Lm9uU2VhcmNoKHtcbiAgICAgICAgICAgICAgICAgIGN1cnJlbnRUYXJnZXQ6ICRzZWFyY2hJbnB1dFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9LCBvcHRzLnNlYXJjaFRpbWVPdXQpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGlmIChvcHRzLnNlYXJjaE9uRW50ZXJLZXkpIHtcbiAgICAgICAgICAgICAgaGFuZGxlSW5wdXRFdmVudCgkc2VhcmNoSW5wdXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBoYW5kbGVJbnB1dEV2ZW50KCRzZWFyY2hJbnB1dCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKG9wdHMuc2hvd1NlYXJjaENsZWFyQnV0dG9uKSB7XG4gICAgICAgICAgICB0aGlzLiR0b29sYmFyLmZpbmQoJy5zZWFyY2ggYnV0dG9uW25hbWU9Y2xlYXJTZWFyY2hdJykuY2xpY2soZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICBfdGhpczQucmVzZXRTZWFyY2goKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygb3B0cy5zZWFyY2hTZWxlY3RvciA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICB2YXIgXyRzZWFyY2hJbnB1dCA9IFV0aWxzLmdldFNlYXJjaElucHV0KHRoaXMpO1xuXG4gICAgICAgICAgaGFuZGxlSW5wdXRFdmVudChfJHNlYXJjaElucHV0KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJvblNlYXJjaFwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIG9uU2VhcmNoKCkge1xuICAgICAgICB2YXIgX3JlZjUgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IHt9LFxuICAgICAgICAgICAgY3VycmVudFRhcmdldCA9IF9yZWY1LmN1cnJlbnRUYXJnZXQsXG4gICAgICAgICAgICBmaXJlZEJ5SW5pdFNlYXJjaFRleHQgPSBfcmVmNS5maXJlZEJ5SW5pdFNlYXJjaFRleHQ7XG5cbiAgICAgICAgdmFyIG92ZXJ3cml0ZVNlYXJjaFRleHQgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHRydWU7XG5cbiAgICAgICAgaWYgKGN1cnJlbnRUYXJnZXQgIT09IHVuZGVmaW5lZCAmJiAkX19kZWZhdWx0WydkZWZhdWx0J10oY3VycmVudFRhcmdldCkubGVuZ3RoICYmIG92ZXJ3cml0ZVNlYXJjaFRleHQpIHtcbiAgICAgICAgICB2YXIgdGV4dCA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShjdXJyZW50VGFyZ2V0KS52YWwoKS50cmltKCk7XG5cbiAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLnRyaW1PblNlYXJjaCAmJiAkX19kZWZhdWx0WydkZWZhdWx0J10oY3VycmVudFRhcmdldCkudmFsKCkgIT09IHRleHQpIHtcbiAgICAgICAgICAgICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShjdXJyZW50VGFyZ2V0KS52YWwodGV4dCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHRoaXMuc2VhcmNoVGV4dCA9PT0gdGV4dCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChjdXJyZW50VGFyZ2V0ID09PSBVdGlscy5nZXRTZWFyY2hJbnB1dCh0aGlzKVswXSB8fCAkX19kZWZhdWx0WydkZWZhdWx0J10oY3VycmVudFRhcmdldCkuaGFzQ2xhc3MoJ3NlYXJjaC1pbnB1dCcpKSB7XG4gICAgICAgICAgICB0aGlzLnNlYXJjaFRleHQgPSB0ZXh0O1xuICAgICAgICAgICAgdGhpcy5vcHRpb25zLnNlYXJjaFRleHQgPSB0ZXh0O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghZmlyZWRCeUluaXRTZWFyY2hUZXh0KSB7XG4gICAgICAgICAgdGhpcy5vcHRpb25zLnBhZ2VOdW1iZXIgPSAxO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5pbml0U2VhcmNoKCk7XG5cbiAgICAgICAgaWYgKGZpcmVkQnlJbml0U2VhcmNoVGV4dCkge1xuICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMuc2lkZVBhZ2luYXRpb24gPT09ICdjbGllbnQnKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVBhZ2luYXRpb24oKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy51cGRhdGVQYWdpbmF0aW9uKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnRyaWdnZXIoJ3NlYXJjaCcsIHRoaXMuc2VhcmNoVGV4dCk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImluaXRTZWFyY2hcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0U2VhcmNoKCkge1xuICAgICAgICB2YXIgX3RoaXM1ID0gdGhpcztcblxuICAgICAgICB0aGlzLmZpbHRlck9wdGlvbnMgPSB0aGlzLmZpbHRlck9wdGlvbnMgfHwgdGhpcy5vcHRpb25zLmZpbHRlck9wdGlvbnM7XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5zaWRlUGFnaW5hdGlvbiAhPT0gJ3NlcnZlcicpIHtcbiAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLmN1c3RvbVNlYXJjaCkge1xuICAgICAgICAgICAgdGhpcy5kYXRhID0gVXRpbHMuY2FsY3VsYXRlT2JqZWN0VmFsdWUodGhpcy5vcHRpb25zLCB0aGlzLm9wdGlvbnMuY3VzdG9tU2VhcmNoLCBbdGhpcy5vcHRpb25zLmRhdGEsIHRoaXMuc2VhcmNoVGV4dCwgdGhpcy5maWx0ZXJDb2x1bW5zXSk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMuc29ydFJlc2V0KSB7XG4gICAgICAgICAgICAgIHRoaXMudW5zb3J0ZWREYXRhID0gX3RvQ29uc3VtYWJsZUFycmF5KHRoaXMuZGF0YSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgcyA9IHRoaXMuc2VhcmNoVGV4dCAmJiAodGhpcy5mcm9tSHRtbCA/IFV0aWxzLmVzY2FwZUhUTUwodGhpcy5zZWFyY2hUZXh0KSA6IHRoaXMuc2VhcmNoVGV4dCkudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICB2YXIgZiA9IFV0aWxzLmlzRW1wdHlPYmplY3QodGhpcy5maWx0ZXJDb2x1bW5zKSA/IG51bGwgOiB0aGlzLmZpbHRlckNvbHVtbnM7XG5cbiAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNlYXJjaEFjY2VudE5ldXRyYWxpc2UpIHtcbiAgICAgICAgICAgIHMgPSBVdGlscy5ub3JtYWxpemVBY2NlbnQocyk7XG4gICAgICAgICAgfSAvLyBDaGVjayBmaWx0ZXJcblxuXG4gICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLmZpbHRlck9wdGlvbnMuZmlsdGVyQWxnb3JpdGhtID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICB0aGlzLmRhdGEgPSB0aGlzLm9wdGlvbnMuZGF0YS5maWx0ZXIoZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgICAgICAgcmV0dXJuIF90aGlzNS5maWx0ZXJPcHRpb25zLmZpbHRlckFsZ29yaXRobS5hcHBseShudWxsLCBbaXRlbSwgZl0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpcy5maWx0ZXJPcHRpb25zLmZpbHRlckFsZ29yaXRobSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRoaXMuZGF0YSA9IGYgPyB0aGlzLm9wdGlvbnMuZGF0YS5maWx0ZXIoZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgICAgICAgdmFyIGZpbHRlckFsZ29yaXRobSA9IF90aGlzNS5maWx0ZXJPcHRpb25zLmZpbHRlckFsZ29yaXRobTtcblxuICAgICAgICAgICAgICBpZiAoZmlsdGVyQWxnb3JpdGhtID09PSAnYW5kJykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBmKSB7XG4gICAgICAgICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShmW2tleV0pICYmICFmW2tleV0uaW5jbHVkZXMoaXRlbVtrZXldKSB8fCAhQXJyYXkuaXNBcnJheShmW2tleV0pICYmIGl0ZW1ba2V5XSAhPT0gZltrZXldKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAoZmlsdGVyQWxnb3JpdGhtID09PSAnb3InKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1hdGNoID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBfa2V5IGluIGYpIHtcbiAgICAgICAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGZbX2tleV0pICYmIGZbX2tleV0uaW5jbHVkZXMoaXRlbVtfa2V5XSkgfHwgIUFycmF5LmlzQXJyYXkoZltfa2V5XSkgJiYgaXRlbVtfa2V5XSA9PT0gZltfa2V5XSkge1xuICAgICAgICAgICAgICAgICAgICBtYXRjaCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG1hdGNoO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9KSA6IF90b0NvbnN1bWFibGVBcnJheSh0aGlzLm9wdGlvbnMuZGF0YSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIHZpc2libGVGaWVsZHMgPSB0aGlzLmdldFZpc2libGVGaWVsZHMoKTtcbiAgICAgICAgICB0aGlzLmRhdGEgPSBzID8gdGhpcy5kYXRhLmZpbHRlcihmdW5jdGlvbiAoaXRlbSwgaSkge1xuICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBfdGhpczUuaGVhZGVyLmZpZWxkcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICBpZiAoIV90aGlzNS5oZWFkZXIuc2VhcmNoYWJsZXNbal0gfHwgX3RoaXM1Lm9wdGlvbnMudmlzaWJsZVNlYXJjaCAmJiB2aXNpYmxlRmllbGRzLmluZGV4T2YoX3RoaXM1LmhlYWRlci5maWVsZHNbal0pID09PSAtMSkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgdmFyIGtleSA9IFV0aWxzLmlzTnVtZXJpYyhfdGhpczUuaGVhZGVyLmZpZWxkc1tqXSkgPyBwYXJzZUludChfdGhpczUuaGVhZGVyLmZpZWxkc1tqXSwgMTApIDogX3RoaXM1LmhlYWRlci5maWVsZHNbal07XG4gICAgICAgICAgICAgIHZhciBjb2x1bW4gPSBfdGhpczUuY29sdW1uc1tfdGhpczUuZmllbGRzQ29sdW1uc0luZGV4W2tleV1dO1xuICAgICAgICAgICAgICB2YXIgdmFsdWUgPSB2b2lkIDA7XG5cbiAgICAgICAgICAgICAgaWYgKHR5cGVvZiBrZXkgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSBpdGVtO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IGtleS5zcGxpdCgnLicpO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgX2k2ID0gMDsgX2k2IDwgcHJvcHMubGVuZ3RoOyBfaTYrKykge1xuICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlW3Byb3BzW19pNl1dICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWVbcHJvcHNbX2k2XV07XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gaXRlbVtrZXldO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKF90aGlzNS5vcHRpb25zLnNlYXJjaEFjY2VudE5ldXRyYWxpc2UpIHtcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IFV0aWxzLm5vcm1hbGl6ZUFjY2VudCh2YWx1ZSk7XG4gICAgICAgICAgICAgIH0gLy8gRml4ICMxNDI6IHJlc3BlY3Qgc2VhcmNoRm9ybWF0dGVyIGJvb2xlYW5cblxuXG4gICAgICAgICAgICAgIGlmIChjb2x1bW4gJiYgY29sdW1uLnNlYXJjaEZvcm1hdHRlcikge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gVXRpbHMuY2FsY3VsYXRlT2JqZWN0VmFsdWUoY29sdW1uLCBfdGhpczUuaGVhZGVyLmZvcm1hdHRlcnNbal0sIFt2YWx1ZSwgaXRlbSwgaSwgY29sdW1uLmZpZWxkXSwgdmFsdWUpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpczUub3B0aW9ucy5zdHJpY3RTZWFyY2gpIHtcbiAgICAgICAgICAgICAgICAgIGlmIChcIlwiLmNvbmNhdCh2YWx1ZSkudG9Mb3dlckNhc2UoKSA9PT0gcykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgdmFyIGxhcmdlclNtYWxsZXJFcXVhbHNSZWdleCA9IC8oPzooPD18PT58PTx8Pj18Pnw8KSg/OlxccyspPygtP1xcZCspP3woLT9cXGQrKT8oXFxzKyk/KDw9fD0+fD08fD49fD58PCkpL2dtO1xuICAgICAgICAgICAgICAgICAgdmFyIG1hdGNoZXMgPSBsYXJnZXJTbWFsbGVyRXF1YWxzUmVnZXguZXhlYyhfdGhpczUuc2VhcmNoVGV4dCk7XG4gICAgICAgICAgICAgICAgICB2YXIgY29tcGFyaXNvbkNoZWNrID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICAgIGlmIChtYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBvcGVyYXRvciA9IG1hdGNoZXNbMV0gfHwgXCJcIi5jb25jYXQobWF0Y2hlc1s1XSwgXCJsXCIpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgY29tcGFyaXNvblZhbHVlID0gbWF0Y2hlc1syXSB8fCBtYXRjaGVzWzNdO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaW50ID0gcGFyc2VJbnQodmFsdWUsIDEwKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNvbXBhcmlzb25JbnQgPSBwYXJzZUludChjb21wYXJpc29uVmFsdWUsIDEwKTtcblxuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKG9wZXJhdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSAnPic6XG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSAnPGwnOlxuICAgICAgICAgICAgICAgICAgICAgICAgY29tcGFyaXNvbkNoZWNrID0gaW50ID4gY29tcGFyaXNvbkludDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSAnPCc6XG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSAnPmwnOlxuICAgICAgICAgICAgICAgICAgICAgICAgY29tcGFyaXNvbkNoZWNrID0gaW50IDwgY29tcGFyaXNvbkludDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSAnPD0nOlxuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJz08JzpcbiAgICAgICAgICAgICAgICAgICAgICBjYXNlICc+PWwnOlxuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJz0+bCc6XG4gICAgICAgICAgICAgICAgICAgICAgICBjb21wYXJpc29uQ2hlY2sgPSBpbnQgPD0gY29tcGFyaXNvbkludDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSAnPj0nOlxuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJz0+JzpcbiAgICAgICAgICAgICAgICAgICAgICBjYXNlICc8PWwnOlxuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJz08bCc6XG4gICAgICAgICAgICAgICAgICAgICAgICBjb21wYXJpc29uQ2hlY2sgPSBpbnQgPj0gY29tcGFyaXNvbkludDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgIGlmIChjb21wYXJpc29uQ2hlY2sgfHwgXCJcIi5jb25jYXQodmFsdWUpLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMocykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9KSA6IHRoaXMuZGF0YTtcblxuICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMuc29ydFJlc2V0KSB7XG4gICAgICAgICAgICB0aGlzLnVuc29ydGVkRGF0YSA9IF90b0NvbnN1bWFibGVBcnJheSh0aGlzLmRhdGEpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuaW5pdFNvcnQoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJpbml0UGFnaW5hdGlvblwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGluaXRQYWdpbmF0aW9uKCkge1xuICAgICAgICB2YXIgX3RoaXM2ID0gdGhpcztcblxuICAgICAgICB2YXIgb3B0cyA9IHRoaXMub3B0aW9ucztcblxuICAgICAgICBpZiAoIW9wdHMucGFnaW5hdGlvbikge1xuICAgICAgICAgIHRoaXMuJHBhZ2luYXRpb24uaGlkZSgpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuJHBhZ2luYXRpb24uc2hvdygpO1xuICAgICAgICB2YXIgaHRtbCA9IFtdO1xuICAgICAgICB2YXIgYWxsU2VsZWN0ZWQgPSBmYWxzZTtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBmcm9tO1xuICAgICAgICB2YXIgdG87XG4gICAgICAgIHZhciAkcGFnZUxpc3Q7XG4gICAgICAgIHZhciAkcHJlO1xuICAgICAgICB2YXIgJG5leHQ7XG4gICAgICAgIHZhciAkbnVtYmVyO1xuICAgICAgICB2YXIgZGF0YSA9IHRoaXMuZ2V0RGF0YSh7XG4gICAgICAgICAgaW5jbHVkZUhpZGRlblJvd3M6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgcGFnZUxpc3QgPSBvcHRzLnBhZ2VMaXN0O1xuXG4gICAgICAgIGlmICh0eXBlb2YgcGFnZUxpc3QgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgcGFnZUxpc3QgPSBwYWdlTGlzdC5yZXBsYWNlKC9cXFt8XFxdfCAvZywgJycpLnRvTG93ZXJDYXNlKCkuc3BsaXQoJywnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHBhZ2VMaXN0ID0gcGFnZUxpc3QubWFwKGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWUudG9Mb3dlckNhc2UoKSA9PT0gb3B0cy5mb3JtYXRBbGxSb3dzKCkudG9Mb3dlckNhc2UoKSB8fCBbJ2FsbCcsICd1bmxpbWl0ZWQnXS5pbmNsdWRlcyh2YWx1ZS50b0xvd2VyQ2FzZSgpKSA/IG9wdHMuZm9ybWF0QWxsUm93cygpIDogK3ZhbHVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMucGFnaW5hdGlvblBhcnRzID0gb3B0cy5wYWdpbmF0aW9uUGFydHM7XG5cbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLnBhZ2luYXRpb25QYXJ0cyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICB0aGlzLnBhZ2luYXRpb25QYXJ0cyA9IHRoaXMucGFnaW5hdGlvblBhcnRzLnJlcGxhY2UoL1xcW3xcXF18IHwnL2csICcnKS5zcGxpdCgnLCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG9wdHMuc2lkZVBhZ2luYXRpb24gIT09ICdzZXJ2ZXInKSB7XG4gICAgICAgICAgb3B0cy50b3RhbFJvd3MgPSBkYXRhLmxlbmd0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudG90YWxQYWdlcyA9IDA7XG5cbiAgICAgICAgaWYgKG9wdHMudG90YWxSb3dzKSB7XG4gICAgICAgICAgaWYgKG9wdHMucGFnZVNpemUgPT09IG9wdHMuZm9ybWF0QWxsUm93cygpKSB7XG4gICAgICAgICAgICBvcHRzLnBhZ2VTaXplID0gb3B0cy50b3RhbFJvd3M7XG4gICAgICAgICAgICBhbGxTZWxlY3RlZCA9IHRydWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy50b3RhbFBhZ2VzID0gfn4oKG9wdHMudG90YWxSb3dzIC0gMSkgLyBvcHRzLnBhZ2VTaXplKSArIDE7XG4gICAgICAgICAgb3B0cy50b3RhbFBhZ2VzID0gdGhpcy50b3RhbFBhZ2VzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMudG90YWxQYWdlcyA+IDAgJiYgb3B0cy5wYWdlTnVtYmVyID4gdGhpcy50b3RhbFBhZ2VzKSB7XG4gICAgICAgICAgb3B0cy5wYWdlTnVtYmVyID0gdGhpcy50b3RhbFBhZ2VzO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5wYWdlRnJvbSA9IChvcHRzLnBhZ2VOdW1iZXIgLSAxKSAqIG9wdHMucGFnZVNpemUgKyAxO1xuICAgICAgICB0aGlzLnBhZ2VUbyA9IG9wdHMucGFnZU51bWJlciAqIG9wdHMucGFnZVNpemU7XG5cbiAgICAgICAgaWYgKHRoaXMucGFnZVRvID4gb3B0cy50b3RhbFJvd3MpIHtcbiAgICAgICAgICB0aGlzLnBhZ2VUbyA9IG9wdHMudG90YWxSb3dzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5wYWdpbmF0aW9uICYmIHRoaXMub3B0aW9ucy5zaWRlUGFnaW5hdGlvbiAhPT0gJ3NlcnZlcicpIHtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMudG90YWxOb3RGaWx0ZXJlZCA9IHRoaXMub3B0aW9ucy5kYXRhLmxlbmd0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5vcHRpb25zLnNob3dFeHRlbmRlZFBhZ2luYXRpb24pIHtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMudG90YWxOb3RGaWx0ZXJlZCA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnBhZ2luYXRpb25QYXJ0cy5pbmNsdWRlcygncGFnZUluZm8nKSB8fCB0aGlzLnBhZ2luYXRpb25QYXJ0cy5pbmNsdWRlcygncGFnZUluZm9TaG9ydCcpIHx8IHRoaXMucGFnaW5hdGlvblBhcnRzLmluY2x1ZGVzKCdwYWdlU2l6ZScpKSB7XG4gICAgICAgICAgaHRtbC5wdXNoKFwiPGRpdiBjbGFzcz1cXFwiXCIuY29uY2F0KHRoaXMuY29uc3RhbnRzLmNsYXNzZXMucHVsbCwgXCItXCIpLmNvbmNhdChvcHRzLnBhZ2luYXRpb25EZXRhaWxIQWxpZ24sIFwiIHBhZ2luYXRpb24tZGV0YWlsXFxcIj5cIikpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMucGFnaW5hdGlvblBhcnRzLmluY2x1ZGVzKCdwYWdlSW5mbycpIHx8IHRoaXMucGFnaW5hdGlvblBhcnRzLmluY2x1ZGVzKCdwYWdlSW5mb1Nob3J0JykpIHtcbiAgICAgICAgICB2YXIgcGFnaW5hdGlvbkluZm8gPSB0aGlzLnBhZ2luYXRpb25QYXJ0cy5pbmNsdWRlcygncGFnZUluZm9TaG9ydCcpID8gb3B0cy5mb3JtYXREZXRhaWxQYWdpbmF0aW9uKG9wdHMudG90YWxSb3dzKSA6IG9wdHMuZm9ybWF0U2hvd2luZ1Jvd3ModGhpcy5wYWdlRnJvbSwgdGhpcy5wYWdlVG8sIG9wdHMudG90YWxSb3dzLCBvcHRzLnRvdGFsTm90RmlsdGVyZWQpO1xuICAgICAgICAgIGh0bWwucHVzaChcIjxzcGFuIGNsYXNzPVxcXCJwYWdpbmF0aW9uLWluZm9cXFwiPlxcbiAgICAgIFwiLmNvbmNhdChwYWdpbmF0aW9uSW5mbywgXCJcXG4gICAgICA8L3NwYW4+XCIpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnBhZ2luYXRpb25QYXJ0cy5pbmNsdWRlcygncGFnZVNpemUnKSkge1xuICAgICAgICAgIGh0bWwucHVzaCgnPGRpdiBjbGFzcz1cInBhZ2UtbGlzdFwiPicpO1xuICAgICAgICAgIHZhciBwYWdlTnVtYmVyID0gW1wiPGRpdiBjbGFzcz1cXFwiXCIuY29uY2F0KHRoaXMuY29uc3RhbnRzLmNsYXNzZXMucGFnaW5hdGlvbkRyb3Bkb3duLCBcIlxcXCI+XFxuICAgICAgICA8YnV0dG9uIGNsYXNzPVxcXCJcIikuY29uY2F0KHRoaXMuY29uc3RhbnRzLmJ1dHRvbnNDbGFzcywgXCIgZHJvcGRvd24tdG9nZ2xlXFxcIiB0eXBlPVxcXCJidXR0b25cXFwiIFwiKS5jb25jYXQodGhpcy5jb25zdGFudHMuZGF0YVRvZ2dsZSwgXCI9XFxcImRyb3Bkb3duXFxcIj5cXG4gICAgICAgIDxzcGFuIGNsYXNzPVxcXCJwYWdlLXNpemVcXFwiPlxcbiAgICAgICAgXCIpLmNvbmNhdChhbGxTZWxlY3RlZCA/IG9wdHMuZm9ybWF0QWxsUm93cygpIDogb3B0cy5wYWdlU2l6ZSwgXCJcXG4gICAgICAgIDwvc3Bhbj5cXG4gICAgICAgIFwiKS5jb25jYXQodGhpcy5jb25zdGFudHMuaHRtbC5kcm9wZG93bkNhcmV0LCBcIlxcbiAgICAgICAgPC9idXR0b24+XFxuICAgICAgICBcIikuY29uY2F0KHRoaXMuY29uc3RhbnRzLmh0bWwucGFnZURyb3Bkb3duWzBdKV07XG4gICAgICAgICAgcGFnZUxpc3QuZm9yRWFjaChmdW5jdGlvbiAocGFnZSwgaSkge1xuICAgICAgICAgICAgaWYgKCFvcHRzLnNtYXJ0RGlzcGxheSB8fCBpID09PSAwIHx8IHBhZ2VMaXN0W2kgLSAxXSA8IG9wdHMudG90YWxSb3dzIHx8IHBhZ2UgPT09IG9wdHMuZm9ybWF0QWxsUm93cygpKSB7XG4gICAgICAgICAgICAgIHZhciBhY3RpdmU7XG5cbiAgICAgICAgICAgICAgaWYgKGFsbFNlbGVjdGVkKSB7XG4gICAgICAgICAgICAgICAgYWN0aXZlID0gcGFnZSA9PT0gb3B0cy5mb3JtYXRBbGxSb3dzKCkgPyBfdGhpczYuY29uc3RhbnRzLmNsYXNzZXMuZHJvcGRvd25BY3RpdmUgOiAnJztcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhY3RpdmUgPSBwYWdlID09PSBvcHRzLnBhZ2VTaXplID8gX3RoaXM2LmNvbnN0YW50cy5jbGFzc2VzLmRyb3Bkb3duQWN0aXZlIDogJyc7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBwYWdlTnVtYmVyLnB1c2goVXRpbHMuc3ByaW50ZihfdGhpczYuY29uc3RhbnRzLmh0bWwucGFnZURyb3Bkb3duSXRlbSwgYWN0aXZlLCBwYWdlKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcGFnZU51bWJlci5wdXNoKFwiXCIuY29uY2F0KHRoaXMuY29uc3RhbnRzLmh0bWwucGFnZURyb3Bkb3duWzFdLCBcIjwvZGl2PlwiKSk7XG4gICAgICAgICAgaHRtbC5wdXNoKG9wdHMuZm9ybWF0UmVjb3Jkc1BlclBhZ2UocGFnZU51bWJlci5qb2luKCcnKSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMucGFnaW5hdGlvblBhcnRzLmluY2x1ZGVzKCdwYWdlSW5mbycpIHx8IHRoaXMucGFnaW5hdGlvblBhcnRzLmluY2x1ZGVzKCdwYWdlSW5mb1Nob3J0JykgfHwgdGhpcy5wYWdpbmF0aW9uUGFydHMuaW5jbHVkZXMoJ3BhZ2VTaXplJykpIHtcbiAgICAgICAgICBodG1sLnB1c2goJzwvZGl2PjwvZGl2PicpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMucGFnaW5hdGlvblBhcnRzLmluY2x1ZGVzKCdwYWdlTGlzdCcpKSB7XG4gICAgICAgICAgaHRtbC5wdXNoKFwiPGRpdiBjbGFzcz1cXFwiXCIuY29uY2F0KHRoaXMuY29uc3RhbnRzLmNsYXNzZXMucHVsbCwgXCItXCIpLmNvbmNhdChvcHRzLnBhZ2luYXRpb25IQWxpZ24sIFwiIHBhZ2luYXRpb25cXFwiPlwiKSwgVXRpbHMuc3ByaW50Zih0aGlzLmNvbnN0YW50cy5odG1sLnBhZ2luYXRpb25bMF0sIFV0aWxzLnNwcmludGYoJyBwYWdpbmF0aW9uLSVzJywgb3B0cy5pY29uU2l6ZSkpLCBVdGlscy5zcHJpbnRmKHRoaXMuY29uc3RhbnRzLmh0bWwucGFnaW5hdGlvbkl0ZW0sICcgcGFnZS1wcmUnLCBvcHRzLmZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQoKSwgb3B0cy5wYWdpbmF0aW9uUHJlVGV4dCkpO1xuXG4gICAgICAgICAgaWYgKHRoaXMudG90YWxQYWdlcyA8IG9wdHMucGFnaW5hdGlvblN1Y2Nlc3NpdmVseVNpemUpIHtcbiAgICAgICAgICAgIGZyb20gPSAxO1xuICAgICAgICAgICAgdG8gPSB0aGlzLnRvdGFsUGFnZXM7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZyb20gPSBvcHRzLnBhZ2VOdW1iZXIgLSBvcHRzLnBhZ2luYXRpb25QYWdlc0J5U2lkZTtcbiAgICAgICAgICAgIHRvID0gZnJvbSArIG9wdHMucGFnaW5hdGlvblBhZ2VzQnlTaWRlICogMjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAob3B0cy5wYWdlTnVtYmVyIDwgb3B0cy5wYWdpbmF0aW9uU3VjY2Vzc2l2ZWx5U2l6ZSAtIDEpIHtcbiAgICAgICAgICAgIHRvID0gb3B0cy5wYWdpbmF0aW9uU3VjY2Vzc2l2ZWx5U2l6ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAob3B0cy5wYWdpbmF0aW9uU3VjY2Vzc2l2ZWx5U2l6ZSA+IHRoaXMudG90YWxQYWdlcyAtIGZyb20pIHtcbiAgICAgICAgICAgIGZyb20gPSBmcm9tIC0gKG9wdHMucGFnaW5hdGlvblN1Y2Nlc3NpdmVseVNpemUgLSAodGhpcy50b3RhbFBhZ2VzIC0gZnJvbSkpICsgMTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoZnJvbSA8IDEpIHtcbiAgICAgICAgICAgIGZyb20gPSAxO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0byA+IHRoaXMudG90YWxQYWdlcykge1xuICAgICAgICAgICAgdG8gPSB0aGlzLnRvdGFsUGFnZXM7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIG1pZGRsZVNpemUgPSBNYXRoLnJvdW5kKG9wdHMucGFnaW5hdGlvblBhZ2VzQnlTaWRlIC8gMik7XG5cbiAgICAgICAgICB2YXIgcGFnZUl0ZW0gPSBmdW5jdGlvbiBwYWdlSXRlbShpKSB7XG4gICAgICAgICAgICB2YXIgY2xhc3NlcyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogJyc7XG4gICAgICAgICAgICByZXR1cm4gVXRpbHMuc3ByaW50ZihfdGhpczYuY29uc3RhbnRzLmh0bWwucGFnaW5hdGlvbkl0ZW0sIGNsYXNzZXMgKyAoaSA9PT0gb3B0cy5wYWdlTnVtYmVyID8gXCIgXCIuY29uY2F0KF90aGlzNi5jb25zdGFudHMuY2xhc3Nlcy5wYWdpbmF0aW9uQWN0aXZlKSA6ICcnKSwgb3B0cy5mb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dChpKSwgaSk7XG4gICAgICAgICAgfTtcblxuICAgICAgICAgIGlmIChmcm9tID4gMSkge1xuICAgICAgICAgICAgdmFyIG1heCA9IG9wdHMucGFnaW5hdGlvblBhZ2VzQnlTaWRlO1xuICAgICAgICAgICAgaWYgKG1heCA+PSBmcm9tKSBtYXggPSBmcm9tIC0gMTtcblxuICAgICAgICAgICAgZm9yIChpID0gMTsgaSA8PSBtYXg7IGkrKykge1xuICAgICAgICAgICAgICBodG1sLnB1c2gocGFnZUl0ZW0oaSkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZnJvbSAtIDEgPT09IG1heCArIDEpIHtcbiAgICAgICAgICAgICAgaSA9IGZyb20gLSAxO1xuICAgICAgICAgICAgICBodG1sLnB1c2gocGFnZUl0ZW0oaSkpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChmcm9tIC0gMSA+IG1heCkge1xuICAgICAgICAgICAgICBpZiAoZnJvbSAtIG9wdHMucGFnaW5hdGlvblBhZ2VzQnlTaWRlICogMiA+IG9wdHMucGFnaW5hdGlvblBhZ2VzQnlTaWRlICYmIG9wdHMucGFnaW5hdGlvblVzZUludGVybWVkaWF0ZSkge1xuICAgICAgICAgICAgICAgIGkgPSBNYXRoLnJvdW5kKChmcm9tIC0gbWlkZGxlU2l6ZSkgLyAyICsgbWlkZGxlU2l6ZSk7XG4gICAgICAgICAgICAgICAgaHRtbC5wdXNoKHBhZ2VJdGVtKGksICcgcGFnZS1pbnRlcm1lZGlhdGUnKSk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaHRtbC5wdXNoKFV0aWxzLnNwcmludGYodGhpcy5jb25zdGFudHMuaHRtbC5wYWdpbmF0aW9uSXRlbSwgJyBwYWdlLWZpcnN0LXNlcGFyYXRvciBkaXNhYmxlZCcsICcnLCAnLi4uJykpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZm9yIChpID0gZnJvbTsgaSA8PSB0bzsgaSsrKSB7XG4gICAgICAgICAgICBodG1sLnB1c2gocGFnZUl0ZW0oaSkpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0aGlzLnRvdGFsUGFnZXMgPiB0bykge1xuICAgICAgICAgICAgdmFyIG1pbiA9IHRoaXMudG90YWxQYWdlcyAtIChvcHRzLnBhZ2luYXRpb25QYWdlc0J5U2lkZSAtIDEpO1xuICAgICAgICAgICAgaWYgKHRvID49IG1pbikgbWluID0gdG8gKyAxO1xuXG4gICAgICAgICAgICBpZiAodG8gKyAxID09PSBtaW4gLSAxKSB7XG4gICAgICAgICAgICAgIGkgPSB0byArIDE7XG4gICAgICAgICAgICAgIGh0bWwucHVzaChwYWdlSXRlbShpKSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1pbiA+IHRvICsgMSkge1xuICAgICAgICAgICAgICBpZiAodGhpcy50b3RhbFBhZ2VzIC0gdG8gPiBvcHRzLnBhZ2luYXRpb25QYWdlc0J5U2lkZSAqIDIgJiYgb3B0cy5wYWdpbmF0aW9uVXNlSW50ZXJtZWRpYXRlKSB7XG4gICAgICAgICAgICAgICAgaSA9IE1hdGgucm91bmQoKHRoaXMudG90YWxQYWdlcyAtIG1pZGRsZVNpemUgLSB0bykgLyAyICsgdG8pO1xuICAgICAgICAgICAgICAgIGh0bWwucHVzaChwYWdlSXRlbShpLCAnIHBhZ2UtaW50ZXJtZWRpYXRlJykpO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGh0bWwucHVzaChVdGlscy5zcHJpbnRmKHRoaXMuY29uc3RhbnRzLmh0bWwucGFnaW5hdGlvbkl0ZW0sICcgcGFnZS1sYXN0LXNlcGFyYXRvciBkaXNhYmxlZCcsICcnLCAnLi4uJykpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAoaSA9IG1pbjsgaSA8PSB0aGlzLnRvdGFsUGFnZXM7IGkrKykge1xuICAgICAgICAgICAgICBodG1sLnB1c2gocGFnZUl0ZW0oaSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGh0bWwucHVzaChVdGlscy5zcHJpbnRmKHRoaXMuY29uc3RhbnRzLmh0bWwucGFnaW5hdGlvbkl0ZW0sICcgcGFnZS1uZXh0Jywgb3B0cy5mb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dCgpLCBvcHRzLnBhZ2luYXRpb25OZXh0VGV4dCkpO1xuICAgICAgICAgIGh0bWwucHVzaCh0aGlzLmNvbnN0YW50cy5odG1sLnBhZ2luYXRpb25bMV0sICc8L2Rpdj4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuJHBhZ2luYXRpb24uaHRtbChodG1sLmpvaW4oJycpKTtcbiAgICAgICAgdmFyIGRyb3B1cENsYXNzID0gWydib3R0b20nLCAnYm90aCddLmluY2x1ZGVzKG9wdHMucGFnaW5hdGlvblZBbGlnbikgPyBcIiBcIi5jb25jYXQodGhpcy5jb25zdGFudHMuY2xhc3Nlcy5kcm9wdXApIDogJyc7XG4gICAgICAgIHRoaXMuJHBhZ2luYXRpb24ubGFzdCgpLmZpbmQoJy5wYWdlLWxpc3QgPiBkaXYnKS5hZGRDbGFzcyhkcm9wdXBDbGFzcyk7XG5cbiAgICAgICAgaWYgKCFvcHRzLm9ubHlJbmZvUGFnaW5hdGlvbikge1xuICAgICAgICAgICRwYWdlTGlzdCA9IHRoaXMuJHBhZ2luYXRpb24uZmluZCgnLnBhZ2UtbGlzdCBhJyk7XG4gICAgICAgICAgJHByZSA9IHRoaXMuJHBhZ2luYXRpb24uZmluZCgnLnBhZ2UtcHJlJyk7XG4gICAgICAgICAgJG5leHQgPSB0aGlzLiRwYWdpbmF0aW9uLmZpbmQoJy5wYWdlLW5leHQnKTtcbiAgICAgICAgICAkbnVtYmVyID0gdGhpcy4kcGFnaW5hdGlvbi5maW5kKCcucGFnZS1pdGVtJykubm90KCcucGFnZS1uZXh0LCAucGFnZS1wcmUsIC5wYWdlLWxhc3Qtc2VwYXJhdG9yLCAucGFnZS1maXJzdC1zZXBhcmF0b3InKTtcblxuICAgICAgICAgIGlmICh0aGlzLnRvdGFsUGFnZXMgPD0gMSkge1xuICAgICAgICAgICAgdGhpcy4kcGFnaW5hdGlvbi5maW5kKCdkaXYucGFnaW5hdGlvbicpLmhpZGUoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAob3B0cy5zbWFydERpc3BsYXkpIHtcbiAgICAgICAgICAgIGlmIChwYWdlTGlzdC5sZW5ndGggPCAyIHx8IG9wdHMudG90YWxSb3dzIDw9IHBhZ2VMaXN0WzBdKSB7XG4gICAgICAgICAgICAgIHRoaXMuJHBhZ2luYXRpb24uZmluZCgnc3Bhbi5wYWdlLWxpc3QnKS5oaWRlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSAvLyB3aGVuIGRhdGEgaXMgZW1wdHksIGhpZGUgdGhlIHBhZ2luYXRpb25cblxuXG4gICAgICAgICAgdGhpcy4kcGFnaW5hdGlvblt0aGlzLmdldERhdGEoKS5sZW5ndGggPyAnc2hvdycgOiAnaGlkZSddKCk7XG5cbiAgICAgICAgICBpZiAoIW9wdHMucGFnaW5hdGlvbkxvb3ApIHtcbiAgICAgICAgICAgIGlmIChvcHRzLnBhZ2VOdW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgJHByZS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG9wdHMucGFnZU51bWJlciA9PT0gdGhpcy50b3RhbFBhZ2VzKSB7XG4gICAgICAgICAgICAgICRuZXh0LmFkZENsYXNzKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChhbGxTZWxlY3RlZCkge1xuICAgICAgICAgICAgb3B0cy5wYWdlU2l6ZSA9IG9wdHMuZm9ybWF0QWxsUm93cygpO1xuICAgICAgICAgIH0gLy8gcmVtb3ZlZCB0aGUgZXZlbnRzIGZvciBsYXN0IGFuZCBmaXJzdCwgb25QYWdlTnVtYmVyIGV4ZWN1dGVkcyB0aGUgc2FtZSBsb2dpY1xuXG5cbiAgICAgICAgICAkcGFnZUxpc3Qub2ZmKCdjbGljaycpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICByZXR1cm4gX3RoaXM2Lm9uUGFnZUxpc3RDaGFuZ2UoZSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgJHByZS5vZmYoJ2NsaWNrJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIHJldHVybiBfdGhpczYub25QYWdlUHJlKGUpO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgICRuZXh0Lm9mZignY2xpY2snKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIF90aGlzNi5vblBhZ2VOZXh0KGUpO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgICRudW1iZXIub2ZmKCdjbGljaycpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICByZXR1cm4gX3RoaXM2Lm9uUGFnZU51bWJlcihlKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJ1cGRhdGVQYWdpbmF0aW9uXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdXBkYXRlUGFnaW5hdGlvbihldmVudCkge1xuICAgICAgICAvLyBGaXggIzE3MTogSUUgZGlzYWJsZWQgYnV0dG9uIGNhbiBiZSBjbGlja2VkIGJ1Zy5cbiAgICAgICAgaWYgKGV2ZW50ICYmICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShldmVudC5jdXJyZW50VGFyZ2V0KS5oYXNDbGFzcygnZGlzYWJsZWQnKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5vcHRpb25zLm1haW50YWluTWV0YURhdGEpIHtcbiAgICAgICAgICB0aGlzLnJlc2V0Um93cygpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5pbml0UGFnaW5hdGlvbigpO1xuICAgICAgICB0aGlzLnRyaWdnZXIoJ3BhZ2UtY2hhbmdlJywgdGhpcy5vcHRpb25zLnBhZ2VOdW1iZXIsIHRoaXMub3B0aW9ucy5wYWdlU2l6ZSk7XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5zaWRlUGFnaW5hdGlvbiA9PT0gJ3NlcnZlcicpIHtcbiAgICAgICAgICB0aGlzLmluaXRTZXJ2ZXIoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmluaXRCb2R5KCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwib25QYWdlTGlzdENoYW5nZVwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIG9uUGFnZUxpc3RDaGFuZ2UoZXZlbnQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdmFyICR0aGlzID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKGV2ZW50LmN1cnJlbnRUYXJnZXQpO1xuICAgICAgICAkdGhpcy5wYXJlbnQoKS5hZGRDbGFzcyh0aGlzLmNvbnN0YW50cy5jbGFzc2VzLmRyb3Bkb3duQWN0aXZlKS5zaWJsaW5ncygpLnJlbW92ZUNsYXNzKHRoaXMuY29uc3RhbnRzLmNsYXNzZXMuZHJvcGRvd25BY3RpdmUpO1xuICAgICAgICB0aGlzLm9wdGlvbnMucGFnZVNpemUgPSAkdGhpcy50ZXh0KCkudG9VcHBlckNhc2UoKSA9PT0gdGhpcy5vcHRpb25zLmZvcm1hdEFsbFJvd3MoKS50b1VwcGVyQ2FzZSgpID8gdGhpcy5vcHRpb25zLmZvcm1hdEFsbFJvd3MoKSA6ICskdGhpcy50ZXh0KCk7XG4gICAgICAgIHRoaXMuJHRvb2xiYXIuZmluZCgnLnBhZ2Utc2l6ZScpLnRleHQodGhpcy5vcHRpb25zLnBhZ2VTaXplKTtcbiAgICAgICAgdGhpcy51cGRhdGVQYWdpbmF0aW9uKGV2ZW50KTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJvblBhZ2VQcmVcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBvblBhZ2VQcmUoZXZlbnQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnBhZ2VOdW1iZXIgLSAxID09PSAwKSB7XG4gICAgICAgICAgdGhpcy5vcHRpb25zLnBhZ2VOdW1iZXIgPSB0aGlzLm9wdGlvbnMudG90YWxQYWdlcztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMucGFnZU51bWJlci0tO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy51cGRhdGVQYWdpbmF0aW9uKGV2ZW50KTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJvblBhZ2VOZXh0XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gb25QYWdlTmV4dChldmVudCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMucGFnZU51bWJlciArIDEgPiB0aGlzLm9wdGlvbnMudG90YWxQYWdlcykge1xuICAgICAgICAgIHRoaXMub3B0aW9ucy5wYWdlTnVtYmVyID0gMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMucGFnZU51bWJlcisrO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy51cGRhdGVQYWdpbmF0aW9uKGV2ZW50KTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJvblBhZ2VOdW1iZXJcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBvblBhZ2VOdW1iZXIoZXZlbnQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnBhZ2VOdW1iZXIgPT09ICskX19kZWZhdWx0WydkZWZhdWx0J10oZXZlbnQuY3VycmVudFRhcmdldCkudGV4dCgpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5vcHRpb25zLnBhZ2VOdW1iZXIgPSArJF9fZGVmYXVsdFsnZGVmYXVsdCddKGV2ZW50LmN1cnJlbnRUYXJnZXQpLnRleHQoKTtcbiAgICAgICAgdGhpcy51cGRhdGVQYWdpbmF0aW9uKGV2ZW50KTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfSAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW51c2VkLXZhcnNcblxuICAgIH0sIHtcbiAgICAgIGtleTogXCJpbml0Um93XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaW5pdFJvdyhpdGVtLCBpLCBkYXRhLCB0ckZyYWdtZW50cykge1xuICAgICAgICB2YXIgX3RoaXM3ID0gdGhpcztcblxuICAgICAgICB2YXIgaHRtbCA9IFtdO1xuICAgICAgICB2YXIgc3R5bGUgPSB7fTtcbiAgICAgICAgdmFyIGNzc2VzID0gW107XG4gICAgICAgIHZhciBkYXRhXyA9ICcnO1xuICAgICAgICB2YXIgYXR0cmlidXRlcyA9IHt9O1xuICAgICAgICB2YXIgaHRtbEF0dHJpYnV0ZXMgPSBbXTtcblxuICAgICAgICBpZiAoVXRpbHMuZmluZEluZGV4KHRoaXMuaGlkZGVuUm93cywgaXRlbSkgPiAtMSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHN0eWxlID0gVXRpbHMuY2FsY3VsYXRlT2JqZWN0VmFsdWUodGhpcy5vcHRpb25zLCB0aGlzLm9wdGlvbnMucm93U3R5bGUsIFtpdGVtLCBpXSwgc3R5bGUpO1xuXG4gICAgICAgIGlmIChzdHlsZSAmJiBzdHlsZS5jc3MpIHtcbiAgICAgICAgICBmb3IgKHZhciBfaTcgPSAwLCBfT2JqZWN0JGVudHJpZXM2ID0gT2JqZWN0LmVudHJpZXMoc3R5bGUuY3NzKTsgX2k3IDwgX09iamVjdCRlbnRyaWVzNi5sZW5ndGg7IF9pNysrKSB7XG4gICAgICAgICAgICB2YXIgX09iamVjdCRlbnRyaWVzNiRfaSA9IF9zbGljZWRUb0FycmF5KF9PYmplY3QkZW50cmllczZbX2k3XSwgMiksXG4gICAgICAgICAgICAgICAga2V5ID0gX09iamVjdCRlbnRyaWVzNiRfaVswXSxcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IF9PYmplY3QkZW50cmllczYkX2lbMV07XG5cbiAgICAgICAgICAgIGNzc2VzLnB1c2goXCJcIi5jb25jYXQoa2V5LCBcIjogXCIpLmNvbmNhdCh2YWx1ZSkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGF0dHJpYnV0ZXMgPSBVdGlscy5jYWxjdWxhdGVPYmplY3RWYWx1ZSh0aGlzLm9wdGlvbnMsIHRoaXMub3B0aW9ucy5yb3dBdHRyaWJ1dGVzLCBbaXRlbSwgaV0sIGF0dHJpYnV0ZXMpO1xuXG4gICAgICAgIGlmIChhdHRyaWJ1dGVzKSB7XG4gICAgICAgICAgZm9yICh2YXIgX2k4ID0gMCwgX09iamVjdCRlbnRyaWVzNyA9IE9iamVjdC5lbnRyaWVzKGF0dHJpYnV0ZXMpOyBfaTggPCBfT2JqZWN0JGVudHJpZXM3Lmxlbmd0aDsgX2k4KyspIHtcbiAgICAgICAgICAgIHZhciBfT2JqZWN0JGVudHJpZXM3JF9pID0gX3NsaWNlZFRvQXJyYXkoX09iamVjdCRlbnRyaWVzN1tfaThdLCAyKSxcbiAgICAgICAgICAgICAgICBfa2V5MiA9IF9PYmplY3QkZW50cmllczckX2lbMF0sXG4gICAgICAgICAgICAgICAgX3ZhbHVlID0gX09iamVjdCRlbnRyaWVzNyRfaVsxXTtcblxuICAgICAgICAgICAgaHRtbEF0dHJpYnV0ZXMucHVzaChcIlwiLmNvbmNhdChfa2V5MiwgXCI9XFxcIlwiKS5jb25jYXQoVXRpbHMuZXNjYXBlSFRNTChfdmFsdWUpLCBcIlxcXCJcIikpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpdGVtLl9kYXRhICYmICFVdGlscy5pc0VtcHR5T2JqZWN0KGl0ZW0uX2RhdGEpKSB7XG4gICAgICAgICAgZm9yICh2YXIgX2k5ID0gMCwgX09iamVjdCRlbnRyaWVzOCA9IE9iamVjdC5lbnRyaWVzKGl0ZW0uX2RhdGEpOyBfaTkgPCBfT2JqZWN0JGVudHJpZXM4Lmxlbmd0aDsgX2k5KyspIHtcbiAgICAgICAgICAgIHZhciBfT2JqZWN0JGVudHJpZXM4JF9pID0gX3NsaWNlZFRvQXJyYXkoX09iamVjdCRlbnRyaWVzOFtfaTldLCAyKSxcbiAgICAgICAgICAgICAgICBrID0gX09iamVjdCRlbnRyaWVzOCRfaVswXSxcbiAgICAgICAgICAgICAgICB2ID0gX09iamVjdCRlbnRyaWVzOCRfaVsxXTtcblxuICAgICAgICAgICAgLy8gaWdub3JlIGRhdGEtaW5kZXhcbiAgICAgICAgICAgIGlmIChrID09PSAnaW5kZXgnKSB7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZGF0YV8gKz0gXCIgZGF0YS1cIi5jb25jYXQoaywgXCI9J1wiKS5jb25jYXQoX3R5cGVvZih2KSA9PT0gJ29iamVjdCcgPyBKU09OLnN0cmluZ2lmeSh2KSA6IHYsIFwiJ1wiKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBodG1sLnB1c2goJzx0cicsIFV0aWxzLnNwcmludGYoJyAlcycsIGh0bWxBdHRyaWJ1dGVzLmxlbmd0aCA/IGh0bWxBdHRyaWJ1dGVzLmpvaW4oJyAnKSA6IHVuZGVmaW5lZCksIFV0aWxzLnNwcmludGYoJyBpZD1cIiVzXCInLCBBcnJheS5pc0FycmF5KGl0ZW0pID8gdW5kZWZpbmVkIDogaXRlbS5faWQpLCBVdGlscy5zcHJpbnRmKCcgY2xhc3M9XCIlc1wiJywgc3R5bGUuY2xhc3NlcyB8fCAoQXJyYXkuaXNBcnJheShpdGVtKSA/IHVuZGVmaW5lZCA6IGl0ZW0uX2NsYXNzKSksIFV0aWxzLnNwcmludGYoJyBzdHlsZT1cIiVzXCInLCBBcnJheS5pc0FycmF5KGl0ZW0pID8gdW5kZWZpbmVkIDogaXRlbS5fc3R5bGUpLCBcIiBkYXRhLWluZGV4PVxcXCJcIi5jb25jYXQoaSwgXCJcXFwiXCIpLCBVdGlscy5zcHJpbnRmKCcgZGF0YS11bmlxdWVpZD1cIiVzXCInLCBVdGlscy5nZXRJdGVtRmllbGQoaXRlbSwgdGhpcy5vcHRpb25zLnVuaXF1ZUlkLCBmYWxzZSkpLCBVdGlscy5zcHJpbnRmKCcgZGF0YS1oYXMtZGV0YWlsLXZpZXc9XCIlc1wiJywgdGhpcy5vcHRpb25zLmRldGFpbFZpZXcgJiYgVXRpbHMuY2FsY3VsYXRlT2JqZWN0VmFsdWUobnVsbCwgdGhpcy5vcHRpb25zLmRldGFpbEZpbHRlciwgW2ksIGl0ZW1dKSA/ICd0cnVlJyA6IHVuZGVmaW5lZCksIFV0aWxzLnNwcmludGYoJyVzJywgZGF0YV8pLCAnPicpO1xuXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuY2FyZFZpZXcpIHtcbiAgICAgICAgICBodG1sLnB1c2goXCI8dGQgY29sc3Bhbj1cXFwiXCIuY29uY2F0KHRoaXMuaGVhZGVyLmZpZWxkcy5sZW5ndGgsIFwiXFxcIj48ZGl2IGNsYXNzPVxcXCJjYXJkLXZpZXdzXFxcIj5cIikpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGRldGFpbFZpZXdUZW1wbGF0ZSA9ICcnO1xuXG4gICAgICAgIGlmIChVdGlscy5oYXNEZXRhaWxWaWV3SWNvbih0aGlzLm9wdGlvbnMpKSB7XG4gICAgICAgICAgZGV0YWlsVmlld1RlbXBsYXRlID0gJzx0ZD4nO1xuXG4gICAgICAgICAgaWYgKFV0aWxzLmNhbGN1bGF0ZU9iamVjdFZhbHVlKG51bGwsIHRoaXMub3B0aW9ucy5kZXRhaWxGaWx0ZXIsIFtpLCBpdGVtXSkpIHtcbiAgICAgICAgICAgIGRldGFpbFZpZXdUZW1wbGF0ZSArPSBcIlxcbiAgICAgICAgICA8YSBjbGFzcz1cXFwiZGV0YWlsLWljb25cXFwiIGhyZWY9XFxcIiNcXFwiPlxcbiAgICAgICAgICBcIi5jb25jYXQoVXRpbHMuc3ByaW50Zih0aGlzLmNvbnN0YW50cy5odG1sLmljb24sIHRoaXMub3B0aW9ucy5pY29uc1ByZWZpeCwgdGhpcy5vcHRpb25zLmljb25zLmRldGFpbE9wZW4pLCBcIlxcbiAgICAgICAgICA8L2E+XFxuICAgICAgICBcIik7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZGV0YWlsVmlld1RlbXBsYXRlICs9ICc8L3RkPic7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZGV0YWlsVmlld1RlbXBsYXRlICYmIHRoaXMub3B0aW9ucy5kZXRhaWxWaWV3QWxpZ24gIT09ICdyaWdodCcpIHtcbiAgICAgICAgICBodG1sLnB1c2goZGV0YWlsVmlld1RlbXBsYXRlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaGVhZGVyLmZpZWxkcy5mb3JFYWNoKGZ1bmN0aW9uIChmaWVsZCwgaikge1xuICAgICAgICAgIHZhciB0ZXh0ID0gJyc7XG4gICAgICAgICAgdmFyIHZhbHVlXyA9IFV0aWxzLmdldEl0ZW1GaWVsZChpdGVtLCBmaWVsZCwgX3RoaXM3Lm9wdGlvbnMuZXNjYXBlKTtcbiAgICAgICAgICB2YXIgdmFsdWUgPSAnJztcbiAgICAgICAgICB2YXIgdHlwZSA9ICcnO1xuICAgICAgICAgIHZhciBjZWxsU3R5bGUgPSB7fTtcbiAgICAgICAgICB2YXIgaWRfID0gJyc7XG4gICAgICAgICAgdmFyIGNsYXNzXyA9IF90aGlzNy5oZWFkZXIuY2xhc3Nlc1tqXTtcbiAgICAgICAgICB2YXIgc3R5bGVfID0gJyc7XG4gICAgICAgICAgdmFyIHN0eWxlVG9BZGRfID0gJyc7XG4gICAgICAgICAgdmFyIGRhdGFfID0gJyc7XG4gICAgICAgICAgdmFyIHJvd3NwYW5fID0gJyc7XG4gICAgICAgICAgdmFyIGNvbHNwYW5fID0gJyc7XG4gICAgICAgICAgdmFyIHRpdGxlXyA9ICcnO1xuICAgICAgICAgIHZhciBjb2x1bW4gPSBfdGhpczcuY29sdW1uc1tqXTtcblxuICAgICAgICAgIGlmICgoX3RoaXM3LmZyb21IdG1sIHx8IF90aGlzNy5hdXRvTWVyZ2VDZWxscykgJiYgdHlwZW9mIHZhbHVlXyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIGlmICghY29sdW1uLmNoZWNrYm94ICYmICFjb2x1bW4ucmFkaW8pIHtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghY29sdW1uLnZpc2libGUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoX3RoaXM3Lm9wdGlvbnMuY2FyZFZpZXcgJiYgIWNvbHVtbi5jYXJkVmlzaWJsZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChjb2x1bW4uZXNjYXBlKSB7XG4gICAgICAgICAgICB2YWx1ZV8gPSBVdGlscy5lc2NhcGVIVE1MKHZhbHVlXyk7XG4gICAgICAgICAgfSAvLyBTdHlsZSBjb25jYXRcblxuXG4gICAgICAgICAgaWYgKGNzc2VzLmNvbmNhdChbX3RoaXM3LmhlYWRlci5zdHlsZXNbal1dKS5sZW5ndGgpIHtcbiAgICAgICAgICAgIHN0eWxlVG9BZGRfICs9IFwiXCIuY29uY2F0KGNzc2VzLmNvbmNhdChbX3RoaXM3LmhlYWRlci5zdHlsZXNbal1dKS5qb2luKCc7ICcpKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoaXRlbVtcIl9cIi5jb25jYXQoZmllbGQsIFwiX3N0eWxlXCIpXSkge1xuICAgICAgICAgICAgc3R5bGVUb0FkZF8gKz0gXCJcIi5jb25jYXQoaXRlbVtcIl9cIi5jb25jYXQoZmllbGQsIFwiX3N0eWxlXCIpXSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHN0eWxlVG9BZGRfKSB7XG4gICAgICAgICAgICBzdHlsZV8gPSBcIiBzdHlsZT1cXFwiXCIuY29uY2F0KHN0eWxlVG9BZGRfLCBcIlxcXCJcIik7XG4gICAgICAgICAgfSAvLyBTdHlsZSBjb25jYXRcbiAgICAgICAgICAvLyBoYW5kbGUgaWQgYW5kIGNsYXNzIG9mIHRkXG5cblxuICAgICAgICAgIGlmIChpdGVtW1wiX1wiLmNvbmNhdChmaWVsZCwgXCJfaWRcIildKSB7XG4gICAgICAgICAgICBpZF8gPSBVdGlscy5zcHJpbnRmKCcgaWQ9XCIlc1wiJywgaXRlbVtcIl9cIi5jb25jYXQoZmllbGQsIFwiX2lkXCIpXSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGl0ZW1bXCJfXCIuY29uY2F0KGZpZWxkLCBcIl9jbGFzc1wiKV0pIHtcbiAgICAgICAgICAgIGNsYXNzXyA9IFV0aWxzLnNwcmludGYoJyBjbGFzcz1cIiVzXCInLCBpdGVtW1wiX1wiLmNvbmNhdChmaWVsZCwgXCJfY2xhc3NcIildKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoaXRlbVtcIl9cIi5jb25jYXQoZmllbGQsIFwiX3Jvd3NwYW5cIildKSB7XG4gICAgICAgICAgICByb3dzcGFuXyA9IFV0aWxzLnNwcmludGYoJyByb3dzcGFuPVwiJXNcIicsIGl0ZW1bXCJfXCIuY29uY2F0KGZpZWxkLCBcIl9yb3dzcGFuXCIpXSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGl0ZW1bXCJfXCIuY29uY2F0KGZpZWxkLCBcIl9jb2xzcGFuXCIpXSkge1xuICAgICAgICAgICAgY29sc3Bhbl8gPSBVdGlscy5zcHJpbnRmKCcgY29sc3Bhbj1cIiVzXCInLCBpdGVtW1wiX1wiLmNvbmNhdChmaWVsZCwgXCJfY29sc3BhblwiKV0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChpdGVtW1wiX1wiLmNvbmNhdChmaWVsZCwgXCJfdGl0bGVcIildKSB7XG4gICAgICAgICAgICB0aXRsZV8gPSBVdGlscy5zcHJpbnRmKCcgdGl0bGU9XCIlc1wiJywgaXRlbVtcIl9cIi5jb25jYXQoZmllbGQsIFwiX3RpdGxlXCIpXSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY2VsbFN0eWxlID0gVXRpbHMuY2FsY3VsYXRlT2JqZWN0VmFsdWUoX3RoaXM3LmhlYWRlciwgX3RoaXM3LmhlYWRlci5jZWxsU3R5bGVzW2pdLCBbdmFsdWVfLCBpdGVtLCBpLCBmaWVsZF0sIGNlbGxTdHlsZSk7XG5cbiAgICAgICAgICBpZiAoY2VsbFN0eWxlLmNsYXNzZXMpIHtcbiAgICAgICAgICAgIGNsYXNzXyA9IFwiIGNsYXNzPVxcXCJcIi5jb25jYXQoY2VsbFN0eWxlLmNsYXNzZXMsIFwiXFxcIlwiKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoY2VsbFN0eWxlLmNzcykge1xuICAgICAgICAgICAgdmFyIGNzc2VzXyA9IFtdO1xuXG4gICAgICAgICAgICBmb3IgKHZhciBfaTEwID0gMCwgX09iamVjdCRlbnRyaWVzOSA9IE9iamVjdC5lbnRyaWVzKGNlbGxTdHlsZS5jc3MpOyBfaTEwIDwgX09iamVjdCRlbnRyaWVzOS5sZW5ndGg7IF9pMTArKykge1xuICAgICAgICAgICAgICB2YXIgX09iamVjdCRlbnRyaWVzOSRfaSA9IF9zbGljZWRUb0FycmF5KF9PYmplY3QkZW50cmllczlbX2kxMF0sIDIpLFxuICAgICAgICAgICAgICAgICAgX2tleTMgPSBfT2JqZWN0JGVudHJpZXM5JF9pWzBdLFxuICAgICAgICAgICAgICAgICAgX3ZhbHVlMiA9IF9PYmplY3QkZW50cmllczkkX2lbMV07XG5cbiAgICAgICAgICAgICAgY3NzZXNfLnB1c2goXCJcIi5jb25jYXQoX2tleTMsIFwiOiBcIikuY29uY2F0KF92YWx1ZTIpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc3R5bGVfID0gXCIgc3R5bGU9XFxcIlwiLmNvbmNhdChjc3Nlc18uY29uY2F0KF90aGlzNy5oZWFkZXIuc3R5bGVzW2pdKS5qb2luKCc7ICcpLCBcIlxcXCJcIik7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFsdWUgPSBVdGlscy5jYWxjdWxhdGVPYmplY3RWYWx1ZShjb2x1bW4sIF90aGlzNy5oZWFkZXIuZm9ybWF0dGVyc1tqXSwgW3ZhbHVlXywgaXRlbSwgaSwgZmllbGRdLCB2YWx1ZV8pO1xuXG4gICAgICAgICAgaWYgKCEoY29sdW1uLmNoZWNrYm94IHx8IGNvbHVtbi5yYWRpbykpIHtcbiAgICAgICAgICAgIHZhbHVlID0gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJyB8fCB2YWx1ZSA9PT0gbnVsbCA/IF90aGlzNy5vcHRpb25zLnVuZGVmaW5lZFRleHQgOiB2YWx1ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoY29sdW1uLnNlYXJjaGFibGUgJiYgX3RoaXM3LnNlYXJjaFRleHQgJiYgX3RoaXM3Lm9wdGlvbnMuc2VhcmNoSGlnaGxpZ2h0KSB7XG4gICAgICAgICAgICB2YXIgZGVmVmFsdWUgPSAnJztcbiAgICAgICAgICAgIHZhciByZWdFeHAgPSBuZXcgUmVnRXhwKFwiKFwiLmNvbmNhdChfdGhpczcuc2VhcmNoVGV4dC5yZXBsYWNlKC9bLiorP14ke30oKXxbXFxdXFxcXF0vZywgJ1xcXFwkJicpLCBcIilcIiksICdnaW0nKTtcbiAgICAgICAgICAgIHZhciBtYXJrZXIgPSAnPG1hcms+JDE8L21hcms+JztcbiAgICAgICAgICAgIHZhciBpc0hUTUwgPSB2YWx1ZSAmJiAvPCg/PS4qPyAuKj9cXC8gPz58YnJ8aHJ8aW5wdXR8IS0tfHdicilbYS16XSsuKj8+fDwoW2Etel0rKS4qPzxcXC9cXDE+L2kudGVzdCh2YWx1ZSk7XG5cbiAgICAgICAgICAgIGlmIChpc0hUTUwpIHtcbiAgICAgICAgICAgICAgLy8gdmFsdWUgY2FuIGNvbnRhaW5zIGEgSFRNTCB0YWdzXG4gICAgICAgICAgICAgIHZhciB0ZXh0Q29udGVudCA9IG5ldyBET01QYXJzZXIoKS5wYXJzZUZyb21TdHJpbmcodmFsdWUudG9TdHJpbmcoKSwgJ3RleHQvaHRtbCcpLmRvY3VtZW50RWxlbWVudC50ZXh0Q29udGVudDtcbiAgICAgICAgICAgICAgdmFyIHRleHRSZXBsYWNlZCA9IHRleHRDb250ZW50LnJlcGxhY2UocmVnRXhwLCBtYXJrZXIpO1xuICAgICAgICAgICAgICBkZWZWYWx1ZSA9IHZhbHVlLnJlcGxhY2UobmV3IFJlZ0V4cChcIig+XFxcXHMqKShcIi5jb25jYXQodGV4dENvbnRlbnQsIFwiKShcXFxccyopXCIpLCAnZ20nKSwgXCIkMVwiLmNvbmNhdCh0ZXh0UmVwbGFjZWQsIFwiJDNcIikpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gYnV0IHVzdWFsbHkgbm90XG4gICAgICAgICAgICAgIGRlZlZhbHVlID0gdmFsdWUudG9TdHJpbmcoKS5yZXBsYWNlKHJlZ0V4cCwgbWFya2VyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFsdWUgPSBVdGlscy5jYWxjdWxhdGVPYmplY3RWYWx1ZShjb2x1bW4sIGNvbHVtbi5zZWFyY2hIaWdobGlnaHRGb3JtYXR0ZXIsIFt2YWx1ZSwgX3RoaXM3LnNlYXJjaFRleHRdLCBkZWZWYWx1ZSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGl0ZW1bXCJfXCIuY29uY2F0KGZpZWxkLCBcIl9kYXRhXCIpXSAmJiAhVXRpbHMuaXNFbXB0eU9iamVjdChpdGVtW1wiX1wiLmNvbmNhdChmaWVsZCwgXCJfZGF0YVwiKV0pKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBfaTExID0gMCwgX09iamVjdCRlbnRyaWVzMTAgPSBPYmplY3QuZW50cmllcyhpdGVtW1wiX1wiLmNvbmNhdChmaWVsZCwgXCJfZGF0YVwiKV0pOyBfaTExIDwgX09iamVjdCRlbnRyaWVzMTAubGVuZ3RoOyBfaTExKyspIHtcbiAgICAgICAgICAgICAgdmFyIF9PYmplY3QkZW50cmllczEwJF9pID0gX3NsaWNlZFRvQXJyYXkoX09iamVjdCRlbnRyaWVzMTBbX2kxMV0sIDIpLFxuICAgICAgICAgICAgICAgICAgX2sgPSBfT2JqZWN0JGVudHJpZXMxMCRfaVswXSxcbiAgICAgICAgICAgICAgICAgIF92ID0gX09iamVjdCRlbnRyaWVzMTAkX2lbMV07XG5cbiAgICAgICAgICAgICAgLy8gaWdub3JlIGRhdGEtaW5kZXhcbiAgICAgICAgICAgICAgaWYgKF9rID09PSAnaW5kZXgnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgZGF0YV8gKz0gXCIgZGF0YS1cIi5jb25jYXQoX2ssIFwiPVxcXCJcIikuY29uY2F0KF92LCBcIlxcXCJcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGNvbHVtbi5jaGVja2JveCB8fCBjb2x1bW4ucmFkaW8pIHtcbiAgICAgICAgICAgIHR5cGUgPSBjb2x1bW4uY2hlY2tib3ggPyAnY2hlY2tib3gnIDogdHlwZTtcbiAgICAgICAgICAgIHR5cGUgPSBjb2x1bW4ucmFkaW8gPyAncmFkaW8nIDogdHlwZTtcbiAgICAgICAgICAgIHZhciBjID0gY29sdW1uWydjbGFzcyddIHx8ICcnO1xuICAgICAgICAgICAgdmFyIGlzQ2hlY2tlZCA9IFV0aWxzLmlzT2JqZWN0KHZhbHVlKSAmJiB2YWx1ZS5oYXNPd25Qcm9wZXJ0eSgnY2hlY2tlZCcpID8gdmFsdWUuY2hlY2tlZCA6ICh2YWx1ZSA9PT0gdHJ1ZSB8fCB2YWx1ZV8pICYmIHZhbHVlICE9PSBmYWxzZTtcbiAgICAgICAgICAgIHZhciBpc0Rpc2FibGVkID0gIWNvbHVtbi5jaGVja2JveEVuYWJsZWQgfHwgdmFsdWUgJiYgdmFsdWUuZGlzYWJsZWQ7XG4gICAgICAgICAgICB0ZXh0ID0gW190aGlzNy5vcHRpb25zLmNhcmRWaWV3ID8gXCI8ZGl2IGNsYXNzPVxcXCJjYXJkLXZpZXcgXCIuY29uY2F0KGMsIFwiXFxcIj5cIikgOiBcIjx0ZCBjbGFzcz1cXFwiYnMtY2hlY2tib3ggXCIuY29uY2F0KGMsIFwiXFxcIlwiKS5jb25jYXQoY2xhc3NfKS5jb25jYXQoc3R5bGVfLCBcIj5cIiksIFwiPGxhYmVsPlxcbiAgICAgICAgICAgIDxpbnB1dFxcbiAgICAgICAgICAgIGRhdGEtaW5kZXg9XFxcIlwiLmNvbmNhdChpLCBcIlxcXCJcXG4gICAgICAgICAgICBuYW1lPVxcXCJcIikuY29uY2F0KF90aGlzNy5vcHRpb25zLnNlbGVjdEl0ZW1OYW1lLCBcIlxcXCJcXG4gICAgICAgICAgICB0eXBlPVxcXCJcIikuY29uY2F0KHR5cGUsIFwiXFxcIlxcbiAgICAgICAgICAgIFwiKS5jb25jYXQoVXRpbHMuc3ByaW50ZigndmFsdWU9XCIlc1wiJywgaXRlbVtfdGhpczcub3B0aW9ucy5pZEZpZWxkXSksIFwiXFxuICAgICAgICAgICAgXCIpLmNvbmNhdChVdGlscy5zcHJpbnRmKCdjaGVja2VkPVwiJXNcIicsIGlzQ2hlY2tlZCA/ICdjaGVja2VkJyA6IHVuZGVmaW5lZCksIFwiXFxuICAgICAgICAgICAgXCIpLmNvbmNhdChVdGlscy5zcHJpbnRmKCdkaXNhYmxlZD1cIiVzXCInLCBpc0Rpc2FibGVkID8gJ2Rpc2FibGVkJyA6IHVuZGVmaW5lZCksIFwiIC8+XFxuICAgICAgICAgICAgPHNwYW4+PC9zcGFuPlxcbiAgICAgICAgICAgIDwvbGFiZWw+XCIpLCBfdGhpczcuaGVhZGVyLmZvcm1hdHRlcnNbal0gJiYgdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyA/IHZhbHVlIDogJycsIF90aGlzNy5vcHRpb25zLmNhcmRWaWV3ID8gJzwvZGl2PicgOiAnPC90ZD4nXS5qb2luKCcnKTtcbiAgICAgICAgICAgIGl0ZW1bX3RoaXM3LmhlYWRlci5zdGF0ZUZpZWxkXSA9IHZhbHVlID09PSB0cnVlIHx8ICEhdmFsdWVfIHx8IHZhbHVlICYmIHZhbHVlLmNoZWNrZWQ7XG4gICAgICAgICAgfSBlbHNlIGlmIChfdGhpczcub3B0aW9ucy5jYXJkVmlldykge1xuICAgICAgICAgICAgdmFyIGNhcmRUaXRsZSA9IF90aGlzNy5vcHRpb25zLnNob3dIZWFkZXIgPyBcIjxzcGFuIGNsYXNzPVxcXCJjYXJkLXZpZXctdGl0bGUgXCIuY29uY2F0KGNlbGxTdHlsZS5jbGFzc2VzLCBcIlxcXCJcIikuY29uY2F0KHN0eWxlXywgXCI+XCIpLmNvbmNhdChVdGlscy5nZXRGaWVsZFRpdGxlKF90aGlzNy5jb2x1bW5zLCBmaWVsZCksIFwiPC9zcGFuPlwiKSA6ICcnO1xuICAgICAgICAgICAgdGV4dCA9IFwiPGRpdiBjbGFzcz1cXFwiY2FyZC12aWV3XFxcIj5cIi5jb25jYXQoY2FyZFRpdGxlLCBcIjxzcGFuIGNsYXNzPVxcXCJjYXJkLXZpZXctdmFsdWUgXCIpLmNvbmNhdChjZWxsU3R5bGUuY2xhc3NlcywgXCJcXFwiXCIpLmNvbmNhdChzdHlsZV8sIFwiPlwiKS5jb25jYXQodmFsdWUsIFwiPC9zcGFuPjwvZGl2PlwiKTtcblxuICAgICAgICAgICAgaWYgKF90aGlzNy5vcHRpb25zLnNtYXJ0RGlzcGxheSAmJiB2YWx1ZSA9PT0gJycpIHtcbiAgICAgICAgICAgICAgdGV4dCA9ICc8ZGl2IGNsYXNzPVwiY2FyZC12aWV3XCI+PC9kaXY+JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGV4dCA9IFwiPHRkXCIuY29uY2F0KGlkXykuY29uY2F0KGNsYXNzXykuY29uY2F0KHN0eWxlXykuY29uY2F0KGRhdGFfKS5jb25jYXQocm93c3Bhbl8pLmNvbmNhdChjb2xzcGFuXykuY29uY2F0KHRpdGxlXywgXCI+XCIpLmNvbmNhdCh2YWx1ZSwgXCI8L3RkPlwiKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBodG1sLnB1c2godGV4dCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChkZXRhaWxWaWV3VGVtcGxhdGUgJiYgdGhpcy5vcHRpb25zLmRldGFpbFZpZXdBbGlnbiA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICAgIGh0bWwucHVzaChkZXRhaWxWaWV3VGVtcGxhdGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5jYXJkVmlldykge1xuICAgICAgICAgIGh0bWwucHVzaCgnPC9kaXY+PC90ZD4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGh0bWwucHVzaCgnPC90cj4nKTtcbiAgICAgICAgcmV0dXJuIGh0bWwuam9pbignJyk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImluaXRCb2R5XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaW5pdEJvZHkoZml4ZWRTY3JvbGwpIHtcbiAgICAgICAgdmFyIF90aGlzOCA9IHRoaXM7XG5cbiAgICAgICAgdmFyIGRhdGEgPSB0aGlzLmdldERhdGEoKTtcbiAgICAgICAgdGhpcy50cmlnZ2VyKCdwcmUtYm9keScsIGRhdGEpO1xuICAgICAgICB0aGlzLiRib2R5ID0gdGhpcy4kZWwuZmluZCgnPnRib2R5Jyk7XG5cbiAgICAgICAgaWYgKCF0aGlzLiRib2R5Lmxlbmd0aCkge1xuICAgICAgICAgIHRoaXMuJGJvZHkgPSAkX19kZWZhdWx0WydkZWZhdWx0J10oJzx0Ym9keT48L3Rib2R5PicpLmFwcGVuZFRvKHRoaXMuJGVsKTtcbiAgICAgICAgfSAvLyBGaXggIzM4OSBCb290c3RyYXAtdGFibGUtZmxhdEpTT04gaXMgbm90IHdvcmtpbmdcblxuXG4gICAgICAgIGlmICghdGhpcy5vcHRpb25zLnBhZ2luYXRpb24gfHwgdGhpcy5vcHRpb25zLnNpZGVQYWdpbmF0aW9uID09PSAnc2VydmVyJykge1xuICAgICAgICAgIHRoaXMucGFnZUZyb20gPSAxO1xuICAgICAgICAgIHRoaXMucGFnZVRvID0gZGF0YS5sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcm93cyA9IFtdO1xuICAgICAgICB2YXIgdHJGcmFnbWVudHMgPSAkX19kZWZhdWx0WydkZWZhdWx0J10oZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpKTtcbiAgICAgICAgdmFyIGhhc1RyID0gZmFsc2U7XG4gICAgICAgIHRoaXMuYXV0b01lcmdlQ2VsbHMgPSBVdGlscy5jaGVja0F1dG9NZXJnZUNlbGxzKGRhdGEuc2xpY2UodGhpcy5wYWdlRnJvbSAtIDEsIHRoaXMucGFnZVRvKSk7XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IHRoaXMucGFnZUZyb20gLSAxOyBpIDwgdGhpcy5wYWdlVG87IGkrKykge1xuICAgICAgICAgIHZhciBpdGVtID0gZGF0YVtpXTtcbiAgICAgICAgICB2YXIgdHIgPSB0aGlzLmluaXRSb3coaXRlbSwgaSwgZGF0YSwgdHJGcmFnbWVudHMpO1xuICAgICAgICAgIGhhc1RyID0gaGFzVHIgfHwgISF0cjtcblxuICAgICAgICAgIGlmICh0ciAmJiB0eXBlb2YgdHIgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMub3B0aW9ucy52aXJ0dWFsU2Nyb2xsKSB7XG4gICAgICAgICAgICAgIHRyRnJhZ21lbnRzLmFwcGVuZCh0cik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByb3dzLnB1c2godHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSAvLyBzaG93IG5vIHJlY29yZHNcblxuXG4gICAgICAgIGlmICghaGFzVHIpIHtcbiAgICAgICAgICB0aGlzLiRib2R5Lmh0bWwoXCI8dHIgY2xhc3M9XFxcIm5vLXJlY29yZHMtZm91bmRcXFwiPlwiLmNvbmNhdChVdGlscy5zcHJpbnRmKCc8dGQgY29sc3Bhbj1cIiVzXCI+JXM8L3RkPicsIHRoaXMuZ2V0VmlzaWJsZUZpZWxkcygpLmxlbmd0aCArIFV0aWxzLmdldERldGFpbFZpZXdJbmRleE9mZnNldCh0aGlzLm9wdGlvbnMpLCB0aGlzLm9wdGlvbnMuZm9ybWF0Tm9NYXRjaGVzKCkpLCBcIjwvdHI+XCIpKTtcbiAgICAgICAgfSBlbHNlIGlmICghdGhpcy5vcHRpb25zLnZpcnR1YWxTY3JvbGwpIHtcbiAgICAgICAgICB0aGlzLiRib2R5Lmh0bWwodHJGcmFnbWVudHMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICh0aGlzLnZpcnR1YWxTY3JvbGwpIHtcbiAgICAgICAgICAgIHRoaXMudmlydHVhbFNjcm9sbC5kZXN0cm95KCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy52aXJ0dWFsU2Nyb2xsID0gbmV3IFZpcnR1YWxTY3JvbGwoe1xuICAgICAgICAgICAgcm93czogcm93cyxcbiAgICAgICAgICAgIGZpeGVkU2Nyb2xsOiBmaXhlZFNjcm9sbCxcbiAgICAgICAgICAgIHNjcm9sbEVsOiB0aGlzLiR0YWJsZUJvZHlbMF0sXG4gICAgICAgICAgICBjb250ZW50RWw6IHRoaXMuJGJvZHlbMF0sXG4gICAgICAgICAgICBpdGVtSGVpZ2h0OiB0aGlzLm9wdGlvbnMudmlydHVhbFNjcm9sbEl0ZW1IZWlnaHQsXG4gICAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24gY2FsbGJhY2soKSB7XG4gICAgICAgICAgICAgIF90aGlzOC5maXRIZWFkZXIoKTtcblxuICAgICAgICAgICAgICBfdGhpczguaW5pdEJvZHlFdmVudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFmaXhlZFNjcm9sbCkge1xuICAgICAgICAgIHRoaXMuc2Nyb2xsVG8oMCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmluaXRCb2R5RXZlbnQoKTtcbiAgICAgICAgdGhpcy51cGRhdGVTZWxlY3RlZCgpO1xuICAgICAgICB0aGlzLmluaXRGb290ZXIoKTtcbiAgICAgICAgdGhpcy5yZXNldFZpZXcoKTtcblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNpZGVQYWdpbmF0aW9uICE9PSAnc2VydmVyJykge1xuICAgICAgICAgIHRoaXMub3B0aW9ucy50b3RhbFJvd3MgPSBkYXRhLmxlbmd0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudHJpZ2dlcigncG9zdC1ib2R5JywgZGF0YSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImluaXRCb2R5RXZlbnRcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0Qm9keUV2ZW50KCkge1xuICAgICAgICB2YXIgX3RoaXM5ID0gdGhpcztcblxuICAgICAgICAvLyBjbGljayB0byBzZWxlY3QgYnkgY29sdW1uXG4gICAgICAgIHRoaXMuJGJvZHkuZmluZCgnPiB0cltkYXRhLWluZGV4XSA+IHRkJykub2ZmKCdjbGljayBkYmxjbGljaycpLm9uKCdjbGljayBkYmxjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgdmFyICR0ZCA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlLmN1cnJlbnRUYXJnZXQpO1xuICAgICAgICAgIHZhciAkdHIgPSAkdGQucGFyZW50KCk7XG4gICAgICAgICAgdmFyICRjYXJkVmlld0FyciA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlLnRhcmdldCkucGFyZW50cygnLmNhcmQtdmlld3MnKS5jaGlsZHJlbigpO1xuICAgICAgICAgIHZhciAkY2FyZFZpZXdUYXJnZXQgPSAkX19kZWZhdWx0WydkZWZhdWx0J10oZS50YXJnZXQpLnBhcmVudHMoJy5jYXJkLXZpZXcnKTtcbiAgICAgICAgICB2YXIgcm93SW5kZXggPSAkdHIuZGF0YSgnaW5kZXgnKTtcbiAgICAgICAgICB2YXIgaXRlbSA9IF90aGlzOS5kYXRhW3Jvd0luZGV4XTtcbiAgICAgICAgICB2YXIgaW5kZXggPSBfdGhpczkub3B0aW9ucy5jYXJkVmlldyA/ICRjYXJkVmlld0Fyci5pbmRleCgkY2FyZFZpZXdUYXJnZXQpIDogJHRkWzBdLmNlbGxJbmRleDtcblxuICAgICAgICAgIHZhciBmaWVsZHMgPSBfdGhpczkuZ2V0VmlzaWJsZUZpZWxkcygpO1xuXG4gICAgICAgICAgdmFyIGZpZWxkID0gZmllbGRzW2luZGV4IC0gVXRpbHMuZ2V0RGV0YWlsVmlld0luZGV4T2Zmc2V0KF90aGlzOS5vcHRpb25zKV07XG4gICAgICAgICAgdmFyIGNvbHVtbiA9IF90aGlzOS5jb2x1bW5zW190aGlzOS5maWVsZHNDb2x1bW5zSW5kZXhbZmllbGRdXTtcbiAgICAgICAgICB2YXIgdmFsdWUgPSBVdGlscy5nZXRJdGVtRmllbGQoaXRlbSwgZmllbGQsIF90aGlzOS5vcHRpb25zLmVzY2FwZSk7XG5cbiAgICAgICAgICBpZiAoJHRkLmZpbmQoJy5kZXRhaWwtaWNvbicpLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIF90aGlzOS50cmlnZ2VyKGUudHlwZSA9PT0gJ2NsaWNrJyA/ICdjbGljay1jZWxsJyA6ICdkYmwtY2xpY2stY2VsbCcsIGZpZWxkLCB2YWx1ZSwgaXRlbSwgJHRkKTtcblxuICAgICAgICAgIF90aGlzOS50cmlnZ2VyKGUudHlwZSA9PT0gJ2NsaWNrJyA/ICdjbGljay1yb3cnIDogJ2RibC1jbGljay1yb3cnLCBpdGVtLCAkdHIsIGZpZWxkKTsgLy8gaWYgY2xpY2sgdG8gc2VsZWN0IC0gdGhlbiB0cmlnZ2VyIHRoZSBjaGVja2JveC9yYWRpbyBjbGlja1xuXG5cbiAgICAgICAgICBpZiAoZS50eXBlID09PSAnY2xpY2snICYmIF90aGlzOS5vcHRpb25zLmNsaWNrVG9TZWxlY3QgJiYgY29sdW1uLmNsaWNrVG9TZWxlY3QgJiYgIVV0aWxzLmNhbGN1bGF0ZU9iamVjdFZhbHVlKF90aGlzOS5vcHRpb25zLCBfdGhpczkub3B0aW9ucy5pZ25vcmVDbGlja1RvU2VsZWN0T24sIFtlLnRhcmdldF0pKSB7XG4gICAgICAgICAgICB2YXIgJHNlbGVjdEl0ZW0gPSAkdHIuZmluZChVdGlscy5zcHJpbnRmKCdbbmFtZT1cIiVzXCJdJywgX3RoaXM5Lm9wdGlvbnMuc2VsZWN0SXRlbU5hbWUpKTtcblxuICAgICAgICAgICAgaWYgKCRzZWxlY3RJdGVtLmxlbmd0aCkge1xuICAgICAgICAgICAgICAkc2VsZWN0SXRlbVswXS5jbGljaygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChlLnR5cGUgPT09ICdjbGljaycgJiYgX3RoaXM5Lm9wdGlvbnMuZGV0YWlsVmlld0J5Q2xpY2spIHtcbiAgICAgICAgICAgIF90aGlzOS50b2dnbGVEZXRhaWxWaWV3KHJvd0luZGV4LCBfdGhpczkuaGVhZGVyLmRldGFpbEZvcm1hdHRlcnNbX3RoaXM5LmZpZWxkc0NvbHVtbnNJbmRleFtmaWVsZF1dKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pLm9mZignbW91c2Vkb3duJykub24oJ21vdXNlZG93bicsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2pxdWVyeS9qcXVlcnkvaXNzdWVzLzE3NDFcbiAgICAgICAgICBfdGhpczkubXVsdGlwbGVTZWxlY3RSb3dDdHJsS2V5ID0gZS5jdHJsS2V5IHx8IGUubWV0YUtleTtcbiAgICAgICAgICBfdGhpczkubXVsdGlwbGVTZWxlY3RSb3dTaGlmdEtleSA9IGUuc2hpZnRLZXk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLiRib2R5LmZpbmQoJz4gdHJbZGF0YS1pbmRleF0gPiB0ZCA+IC5kZXRhaWwtaWNvbicpLm9mZignY2xpY2snKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICAgIF90aGlzOS50b2dnbGVEZXRhaWxWaWV3KCRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlLmN1cnJlbnRUYXJnZXQpLnBhcmVudCgpLnBhcmVudCgpLmRhdGEoJ2luZGV4JykpO1xuXG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy4kc2VsZWN0SXRlbSA9IHRoaXMuJGJvZHkuZmluZChVdGlscy5zcHJpbnRmKCdbbmFtZT1cIiVzXCJdJywgdGhpcy5vcHRpb25zLnNlbGVjdEl0ZW1OYW1lKSk7XG4gICAgICAgIHRoaXMuJHNlbGVjdEl0ZW0ub2ZmKCdjbGljaycpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICB2YXIgJHRoaXMgPSAkX19kZWZhdWx0WydkZWZhdWx0J10oZS5jdXJyZW50VGFyZ2V0KTtcblxuICAgICAgICAgIF90aGlzOS5fdG9nZ2xlQ2hlY2soJHRoaXMucHJvcCgnY2hlY2tlZCcpLCAkdGhpcy5kYXRhKCdpbmRleCcpKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuaGVhZGVyLmV2ZW50cy5mb3JFYWNoKGZ1bmN0aW9uIChfZXZlbnRzLCBpKSB7XG4gICAgICAgICAgdmFyIGV2ZW50cyA9IF9ldmVudHM7XG5cbiAgICAgICAgICBpZiAoIWV2ZW50cykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH0gLy8gZml4IGJ1ZywgaWYgZXZlbnRzIGlzIGRlZmluZWQgd2l0aCBuYW1lc3BhY2VcblxuXG4gICAgICAgICAgaWYgKHR5cGVvZiBldmVudHMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBldmVudHMgPSBVdGlscy5jYWxjdWxhdGVPYmplY3RWYWx1ZShudWxsLCBldmVudHMpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciBmaWVsZCA9IF90aGlzOS5oZWFkZXIuZmllbGRzW2ldO1xuXG4gICAgICAgICAgdmFyIGZpZWxkSW5kZXggPSBfdGhpczkuZ2V0VmlzaWJsZUZpZWxkcygpLmluZGV4T2YoZmllbGQpO1xuXG4gICAgICAgICAgaWYgKGZpZWxkSW5kZXggPT09IC0xKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZmllbGRJbmRleCArPSBVdGlscy5nZXREZXRhaWxWaWV3SW5kZXhPZmZzZXQoX3RoaXM5Lm9wdGlvbnMpO1xuXG4gICAgICAgICAgdmFyIF9sb29wMiA9IGZ1bmN0aW9uIF9sb29wMihrZXkpIHtcbiAgICAgICAgICAgIGlmICghZXZlbnRzLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIFwiY29udGludWVcIjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGV2ZW50ID0gZXZlbnRzW2tleV07XG5cbiAgICAgICAgICAgIF90aGlzOS4kYm9keS5maW5kKCc+dHI6bm90KC5uby1yZWNvcmRzLWZvdW5kKScpLmVhY2goZnVuY3Rpb24gKGksIHRyKSB7XG4gICAgICAgICAgICAgIHZhciAkdHIgPSAkX19kZWZhdWx0WydkZWZhdWx0J10odHIpO1xuICAgICAgICAgICAgICB2YXIgJHRkID0gJHRyLmZpbmQoX3RoaXM5Lm9wdGlvbnMuY2FyZFZpZXcgPyAnLmNhcmQtdmlld3M+LmNhcmQtdmlldycgOiAnPnRkJykuZXEoZmllbGRJbmRleCk7XG4gICAgICAgICAgICAgIHZhciBpbmRleCA9IGtleS5pbmRleE9mKCcgJyk7XG4gICAgICAgICAgICAgIHZhciBuYW1lID0ga2V5LnN1YnN0cmluZygwLCBpbmRleCk7XG4gICAgICAgICAgICAgIHZhciBlbCA9IGtleS5zdWJzdHJpbmcoaW5kZXggKyAxKTtcbiAgICAgICAgICAgICAgJHRkLmZpbmQoZWwpLm9mZihuYW1lKS5vbihuYW1lLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIHZhciBpbmRleCA9ICR0ci5kYXRhKCdpbmRleCcpO1xuICAgICAgICAgICAgICAgIHZhciByb3cgPSBfdGhpczkuZGF0YVtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcm93W2ZpZWxkXTtcbiAgICAgICAgICAgICAgICBldmVudC5hcHBseShfdGhpczksIFtlLCB2YWx1ZSwgcm93LCBpbmRleF0pO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH07XG5cbiAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gZXZlbnRzKSB7XG4gICAgICAgICAgICB2YXIgX3JldDIgPSBfbG9vcDIoa2V5KTtcblxuICAgICAgICAgICAgaWYgKF9yZXQyID09PSBcImNvbnRpbnVlXCIpIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImluaXRTZXJ2ZXJcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0U2VydmVyKHNpbGVudCwgcXVlcnksIHVybCkge1xuICAgICAgICB2YXIgX3RoaXMxMCA9IHRoaXM7XG5cbiAgICAgICAgdmFyIGRhdGEgPSB7fTtcbiAgICAgICAgdmFyIGluZGV4ID0gdGhpcy5oZWFkZXIuZmllbGRzLmluZGV4T2YodGhpcy5vcHRpb25zLnNvcnROYW1lKTtcbiAgICAgICAgdmFyIHBhcmFtcyA9IHtcbiAgICAgICAgICBzZWFyY2hUZXh0OiB0aGlzLnNlYXJjaFRleHQsXG4gICAgICAgICAgc29ydE5hbWU6IHRoaXMub3B0aW9ucy5zb3J0TmFtZSxcbiAgICAgICAgICBzb3J0T3JkZXI6IHRoaXMub3B0aW9ucy5zb3J0T3JkZXJcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAodGhpcy5oZWFkZXIuc29ydE5hbWVzW2luZGV4XSkge1xuICAgICAgICAgIHBhcmFtcy5zb3J0TmFtZSA9IHRoaXMuaGVhZGVyLnNvcnROYW1lc1tpbmRleF07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnBhZ2luYXRpb24gJiYgdGhpcy5vcHRpb25zLnNpZGVQYWdpbmF0aW9uID09PSAnc2VydmVyJykge1xuICAgICAgICAgIHBhcmFtcy5wYWdlU2l6ZSA9IHRoaXMub3B0aW9ucy5wYWdlU2l6ZSA9PT0gdGhpcy5vcHRpb25zLmZvcm1hdEFsbFJvd3MoKSA/IHRoaXMub3B0aW9ucy50b3RhbFJvd3MgOiB0aGlzLm9wdGlvbnMucGFnZVNpemU7XG4gICAgICAgICAgcGFyYW1zLnBhZ2VOdW1iZXIgPSB0aGlzLm9wdGlvbnMucGFnZU51bWJlcjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghKHVybCB8fCB0aGlzLm9wdGlvbnMudXJsKSAmJiAhdGhpcy5vcHRpb25zLmFqYXgpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnF1ZXJ5UGFyYW1zVHlwZSA9PT0gJ2xpbWl0Jykge1xuICAgICAgICAgIHBhcmFtcyA9IHtcbiAgICAgICAgICAgIHNlYXJjaDogcGFyYW1zLnNlYXJjaFRleHQsXG4gICAgICAgICAgICBzb3J0OiBwYXJhbXMuc29ydE5hbWUsXG4gICAgICAgICAgICBvcmRlcjogcGFyYW1zLnNvcnRPcmRlclxuICAgICAgICAgIH07XG5cbiAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLnBhZ2luYXRpb24gJiYgdGhpcy5vcHRpb25zLnNpZGVQYWdpbmF0aW9uID09PSAnc2VydmVyJykge1xuICAgICAgICAgICAgcGFyYW1zLm9mZnNldCA9IHRoaXMub3B0aW9ucy5wYWdlU2l6ZSA9PT0gdGhpcy5vcHRpb25zLmZvcm1hdEFsbFJvd3MoKSA/IDAgOiB0aGlzLm9wdGlvbnMucGFnZVNpemUgKiAodGhpcy5vcHRpb25zLnBhZ2VOdW1iZXIgLSAxKTtcbiAgICAgICAgICAgIHBhcmFtcy5saW1pdCA9IHRoaXMub3B0aW9ucy5wYWdlU2l6ZSA9PT0gdGhpcy5vcHRpb25zLmZvcm1hdEFsbFJvd3MoKSA/IHRoaXMub3B0aW9ucy50b3RhbFJvd3MgOiB0aGlzLm9wdGlvbnMucGFnZVNpemU7XG5cbiAgICAgICAgICAgIGlmIChwYXJhbXMubGltaXQgPT09IDApIHtcbiAgICAgICAgICAgICAgZGVsZXRlIHBhcmFtcy5saW1pdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNlYXJjaCAmJiB0aGlzLm9wdGlvbnMuc2lkZVBhZ2luYXRpb24gPT09ICdzZXJ2ZXInICYmIHRoaXMuY29sdW1ucy5maWx0ZXIoZnVuY3Rpb24gKGNvbHVtbikge1xuICAgICAgICAgIHJldHVybiAhY29sdW1uLnNlYXJjaGFibGU7XG4gICAgICAgIH0pLmxlbmd0aCkge1xuICAgICAgICAgIHBhcmFtcy5zZWFyY2hhYmxlID0gW107XG5cbiAgICAgICAgICB2YXIgX2l0ZXJhdG9yMiA9IF9jcmVhdGVGb3JPZkl0ZXJhdG9ySGVscGVyKHRoaXMuY29sdW1ucyksXG4gICAgICAgICAgICAgIF9zdGVwMjtcblxuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBmb3IgKF9pdGVyYXRvcjIucygpOyAhKF9zdGVwMiA9IF9pdGVyYXRvcjIubigpKS5kb25lOykge1xuICAgICAgICAgICAgICB2YXIgY29sdW1uID0gX3N0ZXAyLnZhbHVlO1xuXG4gICAgICAgICAgICAgIGlmICghY29sdW1uLmNoZWNrYm94ICYmIGNvbHVtbi5zZWFyY2hhYmxlICYmICh0aGlzLm9wdGlvbnMudmlzaWJsZVNlYXJjaCAmJiBjb2x1bW4udmlzaWJsZSB8fCAhdGhpcy5vcHRpb25zLnZpc2libGVTZWFyY2gpKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zLnNlYXJjaGFibGUucHVzaChjb2x1bW4uZmllbGQpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBfaXRlcmF0b3IyLmUoZXJyKTtcbiAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgX2l0ZXJhdG9yMi5mKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFVdGlscy5pc0VtcHR5T2JqZWN0KHRoaXMuZmlsdGVyQ29sdW1uc1BhcnRpYWwpKSB7XG4gICAgICAgICAgcGFyYW1zLmZpbHRlciA9IEpTT04uc3RyaW5naWZ5KHRoaXMuZmlsdGVyQ29sdW1uc1BhcnRpYWwsIG51bGwpO1xuICAgICAgICB9XG5cbiAgICAgICAgJF9fZGVmYXVsdFsnZGVmYXVsdCddLmV4dGVuZChwYXJhbXMsIHF1ZXJ5IHx8IHt9KTtcbiAgICAgICAgZGF0YSA9IFV0aWxzLmNhbGN1bGF0ZU9iamVjdFZhbHVlKHRoaXMub3B0aW9ucywgdGhpcy5vcHRpb25zLnF1ZXJ5UGFyYW1zLCBbcGFyYW1zXSwgZGF0YSk7IC8vIGZhbHNlIHRvIHN0b3AgcmVxdWVzdFxuXG4gICAgICAgIGlmIChkYXRhID09PSBmYWxzZSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghc2lsZW50KSB7XG4gICAgICAgICAgdGhpcy5zaG93TG9hZGluZygpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHJlcXVlc3QgPSAkX19kZWZhdWx0WydkZWZhdWx0J10uZXh0ZW5kKHt9LCBVdGlscy5jYWxjdWxhdGVPYmplY3RWYWx1ZShudWxsLCB0aGlzLm9wdGlvbnMuYWpheE9wdGlvbnMpLCB7XG4gICAgICAgICAgdHlwZTogdGhpcy5vcHRpb25zLm1ldGhvZCxcbiAgICAgICAgICB1cmw6IHVybCB8fCB0aGlzLm9wdGlvbnMudXJsLFxuICAgICAgICAgIGRhdGE6IHRoaXMub3B0aW9ucy5jb250ZW50VHlwZSA9PT0gJ2FwcGxpY2F0aW9uL2pzb24nICYmIHRoaXMub3B0aW9ucy5tZXRob2QgPT09ICdwb3N0JyA/IEpTT04uc3RyaW5naWZ5KGRhdGEpIDogZGF0YSxcbiAgICAgICAgICBjYWNoZTogdGhpcy5vcHRpb25zLmNhY2hlLFxuICAgICAgICAgIGNvbnRlbnRUeXBlOiB0aGlzLm9wdGlvbnMuY29udGVudFR5cGUsXG4gICAgICAgICAgZGF0YVR5cGU6IHRoaXMub3B0aW9ucy5kYXRhVHlwZSxcbiAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbiBzdWNjZXNzKF9yZXMsIHRleHRTdGF0dXMsIGpxWEhSKSB7XG4gICAgICAgICAgICB2YXIgcmVzID0gVXRpbHMuY2FsY3VsYXRlT2JqZWN0VmFsdWUoX3RoaXMxMC5vcHRpb25zLCBfdGhpczEwLm9wdGlvbnMucmVzcG9uc2VIYW5kbGVyLCBbX3JlcywganFYSFJdLCBfcmVzKTtcblxuICAgICAgICAgICAgX3RoaXMxMC5sb2FkKHJlcyk7XG5cbiAgICAgICAgICAgIF90aGlzMTAudHJpZ2dlcignbG9hZC1zdWNjZXNzJywgcmVzLCBqcVhIUiAmJiBqcVhIUi5zdGF0dXMsIGpxWEhSKTtcblxuICAgICAgICAgICAgaWYgKCFzaWxlbnQpIHtcbiAgICAgICAgICAgICAgX3RoaXMxMC5oaWRlTG9hZGluZygpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoX3RoaXMxMC5vcHRpb25zLnNpZGVQYWdpbmF0aW9uID09PSAnc2VydmVyJyAmJiByZXNbX3RoaXMxMC5vcHRpb25zLnRvdGFsRmllbGRdID4gMCAmJiAhcmVzW190aGlzMTAub3B0aW9ucy5kYXRhRmllbGRdLmxlbmd0aCkge1xuICAgICAgICAgICAgICBfdGhpczEwLnVwZGF0ZVBhZ2luYXRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIGVycm9yOiBmdW5jdGlvbiBlcnJvcihqcVhIUikge1xuICAgICAgICAgICAgdmFyIGRhdGEgPSBbXTtcblxuICAgICAgICAgICAgaWYgKF90aGlzMTAub3B0aW9ucy5zaWRlUGFnaW5hdGlvbiA9PT0gJ3NlcnZlcicpIHtcbiAgICAgICAgICAgICAgZGF0YSA9IHt9O1xuICAgICAgICAgICAgICBkYXRhW190aGlzMTAub3B0aW9ucy50b3RhbEZpZWxkXSA9IDA7XG4gICAgICAgICAgICAgIGRhdGFbX3RoaXMxMC5vcHRpb25zLmRhdGFGaWVsZF0gPSBbXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgX3RoaXMxMC5sb2FkKGRhdGEpO1xuXG4gICAgICAgICAgICBfdGhpczEwLnRyaWdnZXIoJ2xvYWQtZXJyb3InLCBqcVhIUiAmJiBqcVhIUi5zdGF0dXMsIGpxWEhSKTtcblxuICAgICAgICAgICAgaWYgKCFzaWxlbnQpIF90aGlzMTAuJHRhYmxlTG9hZGluZy5oaWRlKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLmFqYXgpIHtcbiAgICAgICAgICBVdGlscy5jYWxjdWxhdGVPYmplY3RWYWx1ZSh0aGlzLCB0aGlzLm9wdGlvbnMuYWpheCwgW3JlcXVlc3RdLCBudWxsKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAodGhpcy5feGhyICYmIHRoaXMuX3hoci5yZWFkeVN0YXRlICE9PSA0KSB7XG4gICAgICAgICAgICB0aGlzLl94aHIuYWJvcnQoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aGlzLl94aHIgPSAkX19kZWZhdWx0WydkZWZhdWx0J10uYWpheChyZXF1ZXN0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJpbml0U2VhcmNoVGV4dFwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGluaXRTZWFyY2hUZXh0KCkge1xuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNlYXJjaCkge1xuICAgICAgICAgIHRoaXMuc2VhcmNoVGV4dCA9ICcnO1xuXG4gICAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5zZWFyY2hUZXh0ICE9PSAnJykge1xuICAgICAgICAgICAgdmFyICRzZWFyY2ggPSBVdGlscy5nZXRTZWFyY2hJbnB1dCh0aGlzKTtcbiAgICAgICAgICAgICRzZWFyY2gudmFsKHRoaXMub3B0aW9ucy5zZWFyY2hUZXh0KTtcbiAgICAgICAgICAgIHRoaXMub25TZWFyY2goe1xuICAgICAgICAgICAgICBjdXJyZW50VGFyZ2V0OiAkc2VhcmNoLFxuICAgICAgICAgICAgICBmaXJlZEJ5SW5pdFNlYXJjaFRleHQ6IHRydWVcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJnZXRDYXJldFwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGdldENhcmV0KCkge1xuICAgICAgICB2YXIgX3RoaXMxMSA9IHRoaXM7XG5cbiAgICAgICAgdGhpcy4kaGVhZGVyLmZpbmQoJ3RoJykuZWFjaChmdW5jdGlvbiAoaSwgdGgpIHtcbiAgICAgICAgICAkX19kZWZhdWx0WydkZWZhdWx0J10odGgpLmZpbmQoJy5zb3J0YWJsZScpLnJlbW92ZUNsYXNzKCdkZXNjIGFzYycpLmFkZENsYXNzKCRfX2RlZmF1bHRbJ2RlZmF1bHQnXSh0aCkuZGF0YSgnZmllbGQnKSA9PT0gX3RoaXMxMS5vcHRpb25zLnNvcnROYW1lID8gX3RoaXMxMS5vcHRpb25zLnNvcnRPcmRlciA6ICdib3RoJyk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJ1cGRhdGVTZWxlY3RlZFwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHVwZGF0ZVNlbGVjdGVkKCkge1xuICAgICAgICB2YXIgY2hlY2tBbGwgPSB0aGlzLiRzZWxlY3RJdGVtLmZpbHRlcignOmVuYWJsZWQnKS5sZW5ndGggJiYgdGhpcy4kc2VsZWN0SXRlbS5maWx0ZXIoJzplbmFibGVkJykubGVuZ3RoID09PSB0aGlzLiRzZWxlY3RJdGVtLmZpbHRlcignOmVuYWJsZWQnKS5maWx0ZXIoJzpjaGVja2VkJykubGVuZ3RoO1xuICAgICAgICB0aGlzLiRzZWxlY3RBbGwuYWRkKHRoaXMuJHNlbGVjdEFsbF8pLnByb3AoJ2NoZWNrZWQnLCBjaGVja0FsbCk7XG4gICAgICAgIHRoaXMuJHNlbGVjdEl0ZW0uZWFjaChmdW5jdGlvbiAoaSwgZWwpIHtcbiAgICAgICAgICAkX19kZWZhdWx0WydkZWZhdWx0J10oZWwpLmNsb3Nlc3QoJ3RyJylbJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKS5wcm9wKCdjaGVja2VkJykgPyAnYWRkQ2xhc3MnIDogJ3JlbW92ZUNsYXNzJ10oJ3NlbGVjdGVkJyk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJ1cGRhdGVSb3dzXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdXBkYXRlUm93cygpIHtcbiAgICAgICAgdmFyIF90aGlzMTIgPSB0aGlzO1xuXG4gICAgICAgIHRoaXMuJHNlbGVjdEl0ZW0uZWFjaChmdW5jdGlvbiAoaSwgZWwpIHtcbiAgICAgICAgICBfdGhpczEyLmRhdGFbJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKS5kYXRhKCdpbmRleCcpXVtfdGhpczEyLmhlYWRlci5zdGF0ZUZpZWxkXSA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlbCkucHJvcCgnY2hlY2tlZCcpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwicmVzZXRSb3dzXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gcmVzZXRSb3dzKCkge1xuICAgICAgICB2YXIgX2l0ZXJhdG9yMyA9IF9jcmVhdGVGb3JPZkl0ZXJhdG9ySGVscGVyKHRoaXMuZGF0YSksXG4gICAgICAgICAgICBfc3RlcDM7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBmb3IgKF9pdGVyYXRvcjMucygpOyAhKF9zdGVwMyA9IF9pdGVyYXRvcjMubigpKS5kb25lOykge1xuICAgICAgICAgICAgdmFyIHJvdyA9IF9zdGVwMy52YWx1ZTtcbiAgICAgICAgICAgIHRoaXMuJHNlbGVjdEFsbC5wcm9wKCdjaGVja2VkJywgZmFsc2UpO1xuICAgICAgICAgICAgdGhpcy4kc2VsZWN0SXRlbS5wcm9wKCdjaGVja2VkJywgZmFsc2UpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5oZWFkZXIuc3RhdGVGaWVsZCkge1xuICAgICAgICAgICAgICByb3dbdGhpcy5oZWFkZXIuc3RhdGVGaWVsZF0gPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIF9pdGVyYXRvcjMuZShlcnIpO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIF9pdGVyYXRvcjMuZigpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5pbml0SGlkZGVuUm93cygpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJ0cmlnZ2VyXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdHJpZ2dlcihfbmFtZSkge1xuICAgICAgICB2YXIgX3RoaXMkb3B0aW9ucywgX3RoaXMkb3B0aW9uczI7XG5cbiAgICAgICAgdmFyIG5hbWUgPSBcIlwiLmNvbmNhdChfbmFtZSwgXCIuYnMudGFibGVcIik7XG5cbiAgICAgICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiA+IDEgPyBfbGVuIC0gMSA6IDApLCBfa2V5NCA9IDE7IF9rZXk0IDwgX2xlbjsgX2tleTQrKykge1xuICAgICAgICAgIGFyZ3NbX2tleTQgLSAxXSA9IGFyZ3VtZW50c1tfa2V5NF07XG4gICAgICAgIH1cblxuICAgICAgICAoX3RoaXMkb3B0aW9ucyA9IHRoaXMub3B0aW9ucylbQm9vdHN0cmFwVGFibGUuRVZFTlRTW25hbWVdXS5hcHBseShfdGhpcyRvcHRpb25zLCBbXS5jb25jYXQoYXJncywgW3RoaXNdKSk7XG5cbiAgICAgICAgdGhpcy4kZWwudHJpZ2dlcigkX19kZWZhdWx0WydkZWZhdWx0J10uRXZlbnQobmFtZSwge1xuICAgICAgICAgIHNlbmRlcjogdGhpc1xuICAgICAgICB9KSwgYXJncyk7XG5cbiAgICAgICAgKF90aGlzJG9wdGlvbnMyID0gdGhpcy5vcHRpb25zKS5vbkFsbC5hcHBseShfdGhpcyRvcHRpb25zMiwgW25hbWVdLmNvbmNhdChbXS5jb25jYXQoYXJncywgW3RoaXNdKSkpO1xuXG4gICAgICAgIHRoaXMuJGVsLnRyaWdnZXIoJF9fZGVmYXVsdFsnZGVmYXVsdCddLkV2ZW50KCdhbGwuYnMudGFibGUnLCB7XG4gICAgICAgICAgc2VuZGVyOiB0aGlzXG4gICAgICAgIH0pLCBbbmFtZSwgYXJnc10pO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJyZXNldEhlYWRlclwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHJlc2V0SGVhZGVyKCkge1xuICAgICAgICB2YXIgX3RoaXMxMyA9IHRoaXM7XG5cbiAgICAgICAgLy8gZml4ICM2MTogdGhlIGhpZGRlbiB0YWJsZSByZXNldCBoZWFkZXIgYnVnLlxuICAgICAgICAvLyBmaXggYnVnOiBnZXQgJGVsLmNzcygnd2lkdGgnKSBlcnJvciBzb21ldGltZSAoaGVpZ2h0ID0gNTAwKVxuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy50aW1lb3V0SWRfKTtcbiAgICAgICAgdGhpcy50aW1lb3V0SWRfID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgcmV0dXJuIF90aGlzMTMuZml0SGVhZGVyKCk7XG4gICAgICAgIH0sIHRoaXMuJGVsLmlzKCc6aGlkZGVuJykgPyAxMDAgOiAwKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiZml0SGVhZGVyXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gZml0SGVhZGVyKCkge1xuICAgICAgICB2YXIgX3RoaXMxNCA9IHRoaXM7XG5cbiAgICAgICAgaWYgKHRoaXMuJGVsLmlzKCc6aGlkZGVuJykpIHtcbiAgICAgICAgICB0aGlzLnRpbWVvdXRJZF8gPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBfdGhpczE0LmZpdEhlYWRlcigpO1xuICAgICAgICAgIH0sIDEwMCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGZpeGVkQm9keSA9IHRoaXMuJHRhYmxlQm9keS5nZXQoMCk7XG4gICAgICAgIHZhciBzY3JvbGxXaWR0aCA9IGZpeGVkQm9keS5zY3JvbGxXaWR0aCA+IGZpeGVkQm9keS5jbGllbnRXaWR0aCAmJiBmaXhlZEJvZHkuc2Nyb2xsSGVpZ2h0ID4gZml4ZWRCb2R5LmNsaWVudEhlaWdodCArIHRoaXMuJGhlYWRlci5vdXRlckhlaWdodCgpID8gVXRpbHMuZ2V0U2Nyb2xsQmFyV2lkdGgoKSA6IDA7XG4gICAgICAgIHRoaXMuJGVsLmNzcygnbWFyZ2luLXRvcCcsIC10aGlzLiRoZWFkZXIub3V0ZXJIZWlnaHQoKSk7XG4gICAgICAgIHZhciBmb2N1c2VkID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKCc6Zm9jdXMnKTtcblxuICAgICAgICBpZiAoZm9jdXNlZC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgdmFyICR0aCA9IGZvY3VzZWQucGFyZW50cygndGgnKTtcblxuICAgICAgICAgIGlmICgkdGgubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdmFyIGRhdGFGaWVsZCA9ICR0aC5hdHRyKCdkYXRhLWZpZWxkJyk7XG5cbiAgICAgICAgICAgIGlmIChkYXRhRmllbGQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICB2YXIgJGhlYWRlclRoID0gdGhpcy4kaGVhZGVyLmZpbmQoXCJbZGF0YS1maWVsZD0nXCIuY29uY2F0KGRhdGFGaWVsZCwgXCInXVwiKSk7XG5cbiAgICAgICAgICAgICAgaWYgKCRoZWFkZXJUaC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgJGhlYWRlclRoLmZpbmQoJzppbnB1dCcpLmFkZENsYXNzKCdmb2N1cy10ZW1wJyk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLiRoZWFkZXJfID0gdGhpcy4kaGVhZGVyLmNsb25lKHRydWUsIHRydWUpO1xuICAgICAgICB0aGlzLiRzZWxlY3RBbGxfID0gdGhpcy4kaGVhZGVyXy5maW5kKCdbbmFtZT1cImJ0U2VsZWN0QWxsXCJdJyk7XG4gICAgICAgIHRoaXMuJHRhYmxlSGVhZGVyLmNzcygnbWFyZ2luLXJpZ2h0Jywgc2Nyb2xsV2lkdGgpLmZpbmQoJ3RhYmxlJykuY3NzKCd3aWR0aCcsIHRoaXMuJGVsLm91dGVyV2lkdGgoKSkuaHRtbCgnJykuYXR0cignY2xhc3MnLCB0aGlzLiRlbC5hdHRyKCdjbGFzcycpKS5hcHBlbmQodGhpcy4kaGVhZGVyXyk7XG4gICAgICAgIHRoaXMuJHRhYmxlTG9hZGluZy5jc3MoJ3dpZHRoJywgdGhpcy4kZWwub3V0ZXJXaWR0aCgpKTtcbiAgICAgICAgdmFyIGZvY3VzZWRUZW1wID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKCcuZm9jdXMtdGVtcDp2aXNpYmxlOmVxKDApJyk7XG5cbiAgICAgICAgaWYgKGZvY3VzZWRUZW1wLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBmb2N1c2VkVGVtcC5mb2N1cygpO1xuICAgICAgICAgIHRoaXMuJGhlYWRlci5maW5kKCcuZm9jdXMtdGVtcCcpLnJlbW92ZUNsYXNzKCdmb2N1cy10ZW1wJyk7XG4gICAgICAgIH0gLy8gZml4IGJ1ZzogJC5kYXRhKCkgaXMgbm90IHdvcmtpbmcgYXMgZXhwZWN0ZWQgYWZ0ZXIgJC5hcHBlbmQoKVxuXG5cbiAgICAgICAgdGhpcy4kaGVhZGVyLmZpbmQoJ3RoW2RhdGEtZmllbGRdJykuZWFjaChmdW5jdGlvbiAoaSwgZWwpIHtcbiAgICAgICAgICBfdGhpczE0LiRoZWFkZXJfLmZpbmQoVXRpbHMuc3ByaW50ZigndGhbZGF0YS1maWVsZD1cIiVzXCJdJywgJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKS5kYXRhKCdmaWVsZCcpKSkuZGF0YSgkX19kZWZhdWx0WydkZWZhdWx0J10oZWwpLmRhdGEoKSk7XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgdmlzaWJsZUZpZWxkcyA9IHRoaXMuZ2V0VmlzaWJsZUZpZWxkcygpO1xuICAgICAgICB2YXIgJHRocyA9IHRoaXMuJGhlYWRlcl8uZmluZCgndGgnKTtcbiAgICAgICAgdmFyICR0ciA9IHRoaXMuJGJvZHkuZmluZCgnPnRyOm5vdCgubm8tcmVjb3Jkcy1mb3VuZCwudmlydHVhbC1zY3JvbGwtdG9wKScpLmVxKDApO1xuXG4gICAgICAgIHdoaWxlICgkdHIubGVuZ3RoICYmICR0ci5maW5kKCc+dGRbY29sc3Bhbl06bm90KFtjb2xzcGFuPVwiMVwiXSknKS5sZW5ndGgpIHtcbiAgICAgICAgICAkdHIgPSAkdHIubmV4dCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHRyTGVuZ3RoID0gJHRyLmZpbmQoJz4gKicpLmxlbmd0aDtcbiAgICAgICAgJHRyLmZpbmQoJz4gKicpLmVhY2goZnVuY3Rpb24gKGksIGVsKSB7XG4gICAgICAgICAgdmFyICR0aGlzID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKTtcblxuICAgICAgICAgIGlmIChVdGlscy5oYXNEZXRhaWxWaWV3SWNvbihfdGhpczE0Lm9wdGlvbnMpKSB7XG4gICAgICAgICAgICBpZiAoaSA9PT0gMCAmJiBfdGhpczE0Lm9wdGlvbnMuZGV0YWlsVmlld0FsaWduICE9PSAncmlnaHQnIHx8IGkgPT09IHRyTGVuZ3RoIC0gMSAmJiBfdGhpczE0Lm9wdGlvbnMuZGV0YWlsVmlld0FsaWduID09PSAncmlnaHQnKSB7XG4gICAgICAgICAgICAgIHZhciAkdGhEZXRhaWwgPSAkdGhzLmZpbHRlcignLmRldGFpbCcpO1xuXG4gICAgICAgICAgICAgIHZhciBfem9vbVdpZHRoID0gJHRoRGV0YWlsLmlubmVyV2lkdGgoKSAtICR0aERldGFpbC5maW5kKCcuZmh0LWNlbGwnKS53aWR0aCgpO1xuXG4gICAgICAgICAgICAgICR0aERldGFpbC5maW5kKCcuZmh0LWNlbGwnKS53aWR0aCgkdGhpcy5pbm5lcldpZHRoKCkgLSBfem9vbVdpZHRoKTtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciBpbmRleCA9IGkgLSBVdGlscy5nZXREZXRhaWxWaWV3SW5kZXhPZmZzZXQoX3RoaXMxNC5vcHRpb25zKTtcblxuICAgICAgICAgIHZhciAkdGggPSBfdGhpczE0LiRoZWFkZXJfLmZpbmQoVXRpbHMuc3ByaW50ZigndGhbZGF0YS1maWVsZD1cIiVzXCJdJywgdmlzaWJsZUZpZWxkc1tpbmRleF0pKTtcblxuICAgICAgICAgIGlmICgkdGgubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgJHRoID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKCR0aHNbJHRoaXNbMF0uY2VsbEluZGV4XSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIHpvb21XaWR0aCA9ICR0aC5pbm5lcldpZHRoKCkgLSAkdGguZmluZCgnLmZodC1jZWxsJykud2lkdGgoKTtcbiAgICAgICAgICAkdGguZmluZCgnLmZodC1jZWxsJykud2lkdGgoJHRoaXMuaW5uZXJXaWR0aCgpIC0gem9vbVdpZHRoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuaG9yaXpvbnRhbFNjcm9sbCgpO1xuICAgICAgICB0aGlzLnRyaWdnZXIoJ3Bvc3QtaGVhZGVyJyk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImluaXRGb290ZXJcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0Rm9vdGVyKCkge1xuICAgICAgICBpZiAoIXRoaXMub3B0aW9ucy5zaG93Rm9vdGVyIHx8IHRoaXMub3B0aW9ucy5jYXJkVmlldykge1xuICAgICAgICAgIC8vIGRvIG5vdGhpbmdcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZGF0YSA9IHRoaXMuZ2V0RGF0YSgpO1xuICAgICAgICB2YXIgaHRtbCA9IFtdO1xuICAgICAgICB2YXIgZGV0YWlsVGVtcGxhdGUgPSAnJztcblxuICAgICAgICBpZiAoVXRpbHMuaGFzRGV0YWlsVmlld0ljb24odGhpcy5vcHRpb25zKSkge1xuICAgICAgICAgIGRldGFpbFRlbXBsYXRlID0gJzx0aCBjbGFzcz1cImRldGFpbFwiPjxkaXYgY2xhc3M9XCJ0aC1pbm5lclwiPjwvZGl2PjxkaXYgY2xhc3M9XCJmaHQtY2VsbFwiPjwvZGl2PjwvdGg+JztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkZXRhaWxUZW1wbGF0ZSAmJiB0aGlzLm9wdGlvbnMuZGV0YWlsVmlld0FsaWduICE9PSAncmlnaHQnKSB7XG4gICAgICAgICAgaHRtbC5wdXNoKGRldGFpbFRlbXBsYXRlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBfaXRlcmF0b3I0ID0gX2NyZWF0ZUZvck9mSXRlcmF0b3JIZWxwZXIodGhpcy5jb2x1bW5zKSxcbiAgICAgICAgICAgIF9zdGVwNDtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGZvciAoX2l0ZXJhdG9yNC5zKCk7ICEoX3N0ZXA0ID0gX2l0ZXJhdG9yNC5uKCkpLmRvbmU7KSB7XG4gICAgICAgICAgICB2YXIgY29sdW1uID0gX3N0ZXA0LnZhbHVlO1xuICAgICAgICAgICAgdmFyIGZhbGlnbiA9ICcnO1xuICAgICAgICAgICAgdmFyIHZhbGlnbiA9ICcnO1xuICAgICAgICAgICAgdmFyIGNzc2VzID0gW107XG4gICAgICAgICAgICB2YXIgc3R5bGUgPSB7fTtcbiAgICAgICAgICAgIHZhciBjbGFzc18gPSBVdGlscy5zcHJpbnRmKCcgY2xhc3M9XCIlc1wiJywgY29sdW1uWydjbGFzcyddKTtcblxuICAgICAgICAgICAgaWYgKCFjb2x1bW4udmlzaWJsZSB8fCB0aGlzLmZvb3RlckRhdGEgJiYgdGhpcy5mb290ZXJEYXRhLmxlbmd0aCA+IDAgJiYgIShjb2x1bW4uZmllbGQgaW4gdGhpcy5mb290ZXJEYXRhWzBdKSkge1xuICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5jYXJkVmlldyAmJiAhY29sdW1uLmNhcmRWaXNpYmxlKSB7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZmFsaWduID0gVXRpbHMuc3ByaW50ZigndGV4dC1hbGlnbjogJXM7ICcsIGNvbHVtbi5mYWxpZ24gPyBjb2x1bW4uZmFsaWduIDogY29sdW1uLmFsaWduKTtcbiAgICAgICAgICAgIHZhbGlnbiA9IFV0aWxzLnNwcmludGYoJ3ZlcnRpY2FsLWFsaWduOiAlczsgJywgY29sdW1uLnZhbGlnbik7XG4gICAgICAgICAgICBzdHlsZSA9IFV0aWxzLmNhbGN1bGF0ZU9iamVjdFZhbHVlKG51bGwsIHRoaXMub3B0aW9ucy5mb290ZXJTdHlsZSwgW2NvbHVtbl0pO1xuXG4gICAgICAgICAgICBpZiAoc3R5bGUgJiYgc3R5bGUuY3NzKSB7XG4gICAgICAgICAgICAgIGZvciAodmFyIF9pMTIgPSAwLCBfT2JqZWN0JGVudHJpZXMxMSA9IE9iamVjdC5lbnRyaWVzKHN0eWxlLmNzcyk7IF9pMTIgPCBfT2JqZWN0JGVudHJpZXMxMS5sZW5ndGg7IF9pMTIrKykge1xuICAgICAgICAgICAgICAgIHZhciBfT2JqZWN0JGVudHJpZXMxMSRfaSA9IF9zbGljZWRUb0FycmF5KF9PYmplY3QkZW50cmllczExW19pMTJdLCAyKSxcbiAgICAgICAgICAgICAgICAgICAga2V5ID0gX09iamVjdCRlbnRyaWVzMTEkX2lbMF0sXG4gICAgICAgICAgICAgICAgICAgIF92YWx1ZTMgPSBfT2JqZWN0JGVudHJpZXMxMSRfaVsxXTtcblxuICAgICAgICAgICAgICAgIGNzc2VzLnB1c2goXCJcIi5jb25jYXQoa2V5LCBcIjogXCIpLmNvbmNhdChfdmFsdWUzKSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHN0eWxlICYmIHN0eWxlLmNsYXNzZXMpIHtcbiAgICAgICAgICAgICAgY2xhc3NfID0gVXRpbHMuc3ByaW50ZignIGNsYXNzPVwiJXNcIicsIGNvbHVtblsnY2xhc3MnXSA/IFtjb2x1bW5bJ2NsYXNzJ10sIHN0eWxlLmNsYXNzZXNdLmpvaW4oJyAnKSA6IHN0eWxlLmNsYXNzZXMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBodG1sLnB1c2goJzx0aCcsIGNsYXNzXywgVXRpbHMuc3ByaW50ZignIHN0eWxlPVwiJXNcIicsIGZhbGlnbiArIHZhbGlnbiArIGNzc2VzLmNvbmNhdCgpLmpvaW4oJzsgJykpKTtcbiAgICAgICAgICAgIHZhciBjb2xzcGFuID0gMDtcblxuICAgICAgICAgICAgaWYgKHRoaXMuZm9vdGVyRGF0YSAmJiB0aGlzLmZvb3RlckRhdGEubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICBjb2xzcGFuID0gdGhpcy5mb290ZXJEYXRhWzBdW1wiX1wiLmNvbmNhdChjb2x1bW4uZmllbGQsIFwiX2NvbHNwYW5cIildIHx8IDA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb2xzcGFuKSB7XG4gICAgICAgICAgICAgIGh0bWwucHVzaChcIiBjb2xzcGFuPVxcXCJcIi5jb25jYXQoY29sc3BhbiwgXCJcXFwiIFwiKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGh0bWwucHVzaCgnPicpO1xuICAgICAgICAgICAgaHRtbC5wdXNoKCc8ZGl2IGNsYXNzPVwidGgtaW5uZXJcIj4nKTtcbiAgICAgICAgICAgIHZhciB2YWx1ZSA9ICcnO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5mb290ZXJEYXRhICYmIHRoaXMuZm9vdGVyRGF0YS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgIHZhbHVlID0gdGhpcy5mb290ZXJEYXRhWzBdW2NvbHVtbi5maWVsZF0gfHwgJyc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGh0bWwucHVzaChVdGlscy5jYWxjdWxhdGVPYmplY3RWYWx1ZShjb2x1bW4sIGNvbHVtbi5mb290ZXJGb3JtYXR0ZXIsIFtkYXRhLCB2YWx1ZV0sIHZhbHVlKSk7XG4gICAgICAgICAgICBodG1sLnB1c2goJzwvZGl2PicpO1xuICAgICAgICAgICAgaHRtbC5wdXNoKCc8ZGl2IGNsYXNzPVwiZmh0LWNlbGxcIj48L2Rpdj4nKTtcbiAgICAgICAgICAgIGh0bWwucHVzaCgnPC9kaXY+Jyk7XG4gICAgICAgICAgICBodG1sLnB1c2goJzwvdGg+Jyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBfaXRlcmF0b3I0LmUoZXJyKTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICBfaXRlcmF0b3I0LmYoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkZXRhaWxUZW1wbGF0ZSAmJiB0aGlzLm9wdGlvbnMuZGV0YWlsVmlld0FsaWduID09PSAncmlnaHQnKSB7XG4gICAgICAgICAgaHRtbC5wdXNoKGRldGFpbFRlbXBsYXRlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5vcHRpb25zLmhlaWdodCAmJiAhdGhpcy4kdGFibGVGb290ZXIubGVuZ3RoKSB7XG4gICAgICAgICAgdGhpcy4kZWwuYXBwZW5kKCc8dGZvb3Q+PHRyPjwvdHI+PC90Zm9vdD4nKTtcbiAgICAgICAgICB0aGlzLiR0YWJsZUZvb3RlciA9IHRoaXMuJGVsLmZpbmQoJ3Rmb290Jyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuJHRhYmxlRm9vdGVyLmZpbmQoJ3RyJykubGVuZ3RoKSB7XG4gICAgICAgICAgdGhpcy4kdGFibGVGb290ZXIuaHRtbCgnPHRhYmxlPjx0aGVhZD48dHI+PC90cj48L3RoZWFkPjwvdGFibGU+Jyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLiR0YWJsZUZvb3Rlci5maW5kKCd0cicpLmh0bWwoaHRtbC5qb2luKCcnKSk7XG4gICAgICAgIHRoaXMudHJpZ2dlcigncG9zdC1mb290ZXInLCB0aGlzLiR0YWJsZUZvb3Rlcik7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImZpdEZvb3RlclwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGZpdEZvb3RlcigpIHtcbiAgICAgICAgdmFyIF90aGlzMTUgPSB0aGlzO1xuXG4gICAgICAgIGlmICh0aGlzLiRlbC5pcygnOmhpZGRlbicpKSB7XG4gICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gX3RoaXMxNS5maXRGb290ZXIoKTtcbiAgICAgICAgICB9LCAxMDApO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBmaXhlZEJvZHkgPSB0aGlzLiR0YWJsZUJvZHkuZ2V0KDApO1xuICAgICAgICB2YXIgc2Nyb2xsV2lkdGggPSBmaXhlZEJvZHkuc2Nyb2xsV2lkdGggPiBmaXhlZEJvZHkuY2xpZW50V2lkdGggJiYgZml4ZWRCb2R5LnNjcm9sbEhlaWdodCA+IGZpeGVkQm9keS5jbGllbnRIZWlnaHQgKyB0aGlzLiRoZWFkZXIub3V0ZXJIZWlnaHQoKSA/IFV0aWxzLmdldFNjcm9sbEJhcldpZHRoKCkgOiAwO1xuICAgICAgICB0aGlzLiR0YWJsZUZvb3Rlci5jc3MoJ21hcmdpbi1yaWdodCcsIHNjcm9sbFdpZHRoKS5maW5kKCd0YWJsZScpLmNzcygnd2lkdGgnLCB0aGlzLiRlbC5vdXRlcldpZHRoKCkpLmF0dHIoJ2NsYXNzJywgdGhpcy4kZWwuYXR0cignY2xhc3MnKSk7XG4gICAgICAgIHZhciAkdGhzID0gdGhpcy4kdGFibGVGb290ZXIuZmluZCgndGgnKTtcbiAgICAgICAgdmFyICR0ciA9IHRoaXMuJGJvZHkuZmluZCgnPnRyOmZpcnN0LWNoaWxkOm5vdCgubm8tcmVjb3Jkcy1mb3VuZCknKTtcbiAgICAgICAgJHRocy5maW5kKCcuZmh0LWNlbGwnKS53aWR0aCgnYXV0bycpO1xuXG4gICAgICAgIHdoaWxlICgkdHIubGVuZ3RoICYmICR0ci5maW5kKCc+dGRbY29sc3Bhbl06bm90KFtjb2xzcGFuPVwiMVwiXSknKS5sZW5ndGgpIHtcbiAgICAgICAgICAkdHIgPSAkdHIubmV4dCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHRyTGVuZ3RoID0gJHRyLmZpbmQoJz4gKicpLmxlbmd0aDtcbiAgICAgICAgJHRyLmZpbmQoJz4gKicpLmVhY2goZnVuY3Rpb24gKGksIGVsKSB7XG4gICAgICAgICAgdmFyICR0aGlzID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKTtcblxuICAgICAgICAgIGlmIChVdGlscy5oYXNEZXRhaWxWaWV3SWNvbihfdGhpczE1Lm9wdGlvbnMpKSB7XG4gICAgICAgICAgICBpZiAoaSA9PT0gMCAmJiBfdGhpczE1Lm9wdGlvbnMuZGV0YWlsVmlld0FsaWduID09PSAnbGVmdCcgfHwgaSA9PT0gdHJMZW5ndGggLSAxICYmIF90aGlzMTUub3B0aW9ucy5kZXRhaWxWaWV3QWxpZ24gPT09ICdyaWdodCcpIHtcbiAgICAgICAgICAgICAgdmFyICR0aERldGFpbCA9ICR0aHMuZmlsdGVyKCcuZGV0YWlsJyk7XG5cbiAgICAgICAgICAgICAgdmFyIF96b29tV2lkdGgyID0gJHRoRGV0YWlsLmlubmVyV2lkdGgoKSAtICR0aERldGFpbC5maW5kKCcuZmh0LWNlbGwnKS53aWR0aCgpO1xuXG4gICAgICAgICAgICAgICR0aERldGFpbC5maW5kKCcuZmh0LWNlbGwnKS53aWR0aCgkdGhpcy5pbm5lcldpZHRoKCkgLSBfem9vbVdpZHRoMik7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgJHRoID0gJHRocy5lcShpKTtcbiAgICAgICAgICB2YXIgem9vbVdpZHRoID0gJHRoLmlubmVyV2lkdGgoKSAtICR0aC5maW5kKCcuZmh0LWNlbGwnKS53aWR0aCgpO1xuICAgICAgICAgICR0aC5maW5kKCcuZmh0LWNlbGwnKS53aWR0aCgkdGhpcy5pbm5lcldpZHRoKCkgLSB6b29tV2lkdGgpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5ob3Jpem9udGFsU2Nyb2xsKCk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImhvcml6b250YWxTY3JvbGxcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBob3Jpem9udGFsU2Nyb2xsKCkge1xuICAgICAgICB2YXIgX3RoaXMxNiA9IHRoaXM7XG5cbiAgICAgICAgLy8gaG9yaXpvbnRhbCBzY3JvbGwgZXZlbnRcbiAgICAgICAgLy8gVE9ETzogaXQncyBwcm9iYWJseSBiZXR0ZXIgaW1wcm92aW5nIHRoZSBsYXlvdXQgdGhhbiBiaW5kaW5nIHRvIHNjcm9sbCBldmVudFxuICAgICAgICB0aGlzLiR0YWJsZUJvZHkub2ZmKCdzY3JvbGwnKS5vbignc2Nyb2xsJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHZhciBzY3JvbGxMZWZ0ID0gX3RoaXMxNi4kdGFibGVCb2R5LnNjcm9sbExlZnQoKTtcblxuICAgICAgICAgIGlmIChfdGhpczE2Lm9wdGlvbnMuc2hvd0hlYWRlciAmJiBfdGhpczE2Lm9wdGlvbnMuaGVpZ2h0KSB7XG4gICAgICAgICAgICBfdGhpczE2LiR0YWJsZUhlYWRlci5zY3JvbGxMZWZ0KHNjcm9sbExlZnQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChfdGhpczE2Lm9wdGlvbnMuc2hvd0Zvb3RlciAmJiAhX3RoaXMxNi5vcHRpb25zLmNhcmRWaWV3KSB7XG4gICAgICAgICAgICBfdGhpczE2LiR0YWJsZUZvb3Rlci5zY3JvbGxMZWZ0KHNjcm9sbExlZnQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIF90aGlzMTYudHJpZ2dlcignc2Nyb2xsLWJvZHknLCBfdGhpczE2LiR0YWJsZUJvZHkpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiZ2V0VmlzaWJsZUZpZWxkc1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGdldFZpc2libGVGaWVsZHMoKSB7XG4gICAgICAgIHZhciB2aXNpYmxlRmllbGRzID0gW107XG5cbiAgICAgICAgdmFyIF9pdGVyYXRvcjUgPSBfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlcih0aGlzLmhlYWRlci5maWVsZHMpLFxuICAgICAgICAgICAgX3N0ZXA1O1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZm9yIChfaXRlcmF0b3I1LnMoKTsgIShfc3RlcDUgPSBfaXRlcmF0b3I1Lm4oKSkuZG9uZTspIHtcbiAgICAgICAgICAgIHZhciBmaWVsZCA9IF9zdGVwNS52YWx1ZTtcbiAgICAgICAgICAgIHZhciBjb2x1bW4gPSB0aGlzLmNvbHVtbnNbdGhpcy5maWVsZHNDb2x1bW5zSW5kZXhbZmllbGRdXTtcblxuICAgICAgICAgICAgaWYgKCFjb2x1bW4gfHwgIWNvbHVtbi52aXNpYmxlKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2aXNpYmxlRmllbGRzLnB1c2goZmllbGQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgX2l0ZXJhdG9yNS5lKGVycik7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgX2l0ZXJhdG9yNS5mKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdmlzaWJsZUZpZWxkcztcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiaW5pdEhpZGRlblJvd3NcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0SGlkZGVuUm93cygpIHtcbiAgICAgICAgdGhpcy5oaWRkZW5Sb3dzID0gW107XG4gICAgICB9IC8vIFBVQkxJQyBGVU5DVElPTiBERUZJTklUSU9OXG4gICAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PVxuXG4gICAgfSwge1xuICAgICAga2V5OiBcImdldE9wdGlvbnNcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRPcHRpb25zKCkge1xuICAgICAgICAvLyBkZWVwIGNvcHkgYW5kIHJlbW92ZSBkYXRhXG4gICAgICAgIHZhciBvcHRpb25zID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddLmV4dGVuZCh7fSwgdGhpcy5vcHRpb25zKTtcbiAgICAgICAgZGVsZXRlIG9wdGlvbnMuZGF0YTtcbiAgICAgICAgcmV0dXJuICRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5leHRlbmQodHJ1ZSwge30sIG9wdGlvbnMpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJyZWZyZXNoT3B0aW9uc1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHJlZnJlc2hPcHRpb25zKG9wdGlvbnMpIHtcbiAgICAgICAgLy8gSWYgdGhlIG9iamVjdHMgYXJlIGVxdWl2YWxlbnQgdGhlbiBhdm9pZCB0aGUgY2FsbCBvZiBkZXN0cm95IC8gaW5pdCBtZXRob2RzXG4gICAgICAgIGlmIChVdGlscy5jb21wYXJlT2JqZWN0cyh0aGlzLm9wdGlvbnMsIG9wdGlvbnMsIHRydWUpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5vcHRpb25zID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddLmV4dGVuZCh0aGlzLm9wdGlvbnMsIG9wdGlvbnMpO1xuICAgICAgICB0aGlzLnRyaWdnZXIoJ3JlZnJlc2gtb3B0aW9ucycsIHRoaXMub3B0aW9ucyk7XG4gICAgICAgIHRoaXMuZGVzdHJveSgpO1xuICAgICAgICB0aGlzLmluaXQoKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiZ2V0RGF0YVwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGdldERhdGEocGFyYW1zKSB7XG4gICAgICAgIHZhciBfdGhpczE3ID0gdGhpcztcblxuICAgICAgICB2YXIgZGF0YSA9IHRoaXMub3B0aW9ucy5kYXRhO1xuXG4gICAgICAgIGlmICgodGhpcy5zZWFyY2hUZXh0IHx8IHRoaXMub3B0aW9ucy5jdXN0b21TZWFyY2ggfHwgdGhpcy5vcHRpb25zLnNvcnROYW1lICE9PSB1bmRlZmluZWQgfHwgdGhpcy5lbmFibGVDdXN0b21Tb3J0IHx8IC8vIEZpeCAjNDYxNjogdGhpcy5lbmFibGVDdXN0b21Tb3J0IGlzIGZvciBleHRlbnNpb25zXG4gICAgICAgICFVdGlscy5pc0VtcHR5T2JqZWN0KHRoaXMuZmlsdGVyQ29sdW1ucykgfHwgIVV0aWxzLmlzRW1wdHlPYmplY3QodGhpcy5maWx0ZXJDb2x1bW5zUGFydGlhbCkpICYmICghcGFyYW1zIHx8ICFwYXJhbXMudW5maWx0ZXJlZCkpIHtcbiAgICAgICAgICBkYXRhID0gdGhpcy5kYXRhO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcmFtcyAmJiBwYXJhbXMudXNlQ3VycmVudFBhZ2UpIHtcbiAgICAgICAgICBkYXRhID0gZGF0YS5zbGljZSh0aGlzLnBhZ2VGcm9tIC0gMSwgdGhpcy5wYWdlVG8pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcmFtcyAmJiAhcGFyYW1zLmluY2x1ZGVIaWRkZW5Sb3dzKSB7XG4gICAgICAgICAgdmFyIGhpZGRlblJvd3MgPSB0aGlzLmdldEhpZGRlblJvd3MoKTtcbiAgICAgICAgICBkYXRhID0gZGF0YS5maWx0ZXIoZnVuY3Rpb24gKHJvdykge1xuICAgICAgICAgICAgcmV0dXJuIFV0aWxzLmZpbmRJbmRleChoaWRkZW5Sb3dzLCByb3cpID09PSAtMTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwYXJhbXMgJiYgcGFyYW1zLmZvcm1hdHRlZCkge1xuICAgICAgICAgIGRhdGEuZm9yRWFjaChmdW5jdGlvbiAocm93KSB7XG4gICAgICAgICAgICBmb3IgKHZhciBfaTEzID0gMCwgX09iamVjdCRlbnRyaWVzMTIgPSBPYmplY3QuZW50cmllcyhyb3cpOyBfaTEzIDwgX09iamVjdCRlbnRyaWVzMTIubGVuZ3RoOyBfaTEzKyspIHtcbiAgICAgICAgICAgICAgdmFyIF9PYmplY3QkZW50cmllczEyJF9pID0gX3NsaWNlZFRvQXJyYXkoX09iamVjdCRlbnRyaWVzMTJbX2kxM10sIDIpLFxuICAgICAgICAgICAgICAgICAga2V5ID0gX09iamVjdCRlbnRyaWVzMTIkX2lbMF0sXG4gICAgICAgICAgICAgICAgICB2YWx1ZSA9IF9PYmplY3QkZW50cmllczEyJF9pWzFdO1xuXG4gICAgICAgICAgICAgIHZhciBjb2x1bW4gPSBfdGhpczE3LmNvbHVtbnNbX3RoaXMxNy5maWVsZHNDb2x1bW5zSW5kZXhba2V5XV07XG5cbiAgICAgICAgICAgICAgaWYgKCFjb2x1bW4pIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICByb3dba2V5XSA9IFV0aWxzLmNhbGN1bGF0ZU9iamVjdFZhbHVlKGNvbHVtbiwgX3RoaXMxNy5oZWFkZXIuZm9ybWF0dGVyc1tjb2x1bW4uZmllbGRJbmRleF0sIFt2YWx1ZSwgcm93LCByb3cuaW5kZXgsIGNvbHVtbi5maWVsZF0sIHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJnZXRTZWxlY3Rpb25zXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0U2VsZWN0aW9ucygpIHtcbiAgICAgICAgdmFyIF90aGlzMTggPSB0aGlzO1xuXG4gICAgICAgIHJldHVybiAodGhpcy5vcHRpb25zLm1haW50YWluTWV0YURhdGEgPyB0aGlzLm9wdGlvbnMuZGF0YSA6IHRoaXMuZGF0YSkuZmlsdGVyKGZ1bmN0aW9uIChyb3cpIHtcbiAgICAgICAgICByZXR1cm4gcm93W190aGlzMTguaGVhZGVyLnN0YXRlRmllbGRdID09PSB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwibG9hZFwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGxvYWQoX2RhdGEpIHtcbiAgICAgICAgdmFyIGZpeGVkU2Nyb2xsID0gZmFsc2U7XG4gICAgICAgIHZhciBkYXRhID0gX2RhdGE7IC8vICM0MzE6IHN1cHBvcnQgcGFnaW5hdGlvblxuXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMucGFnaW5hdGlvbiAmJiB0aGlzLm9wdGlvbnMuc2lkZVBhZ2luYXRpb24gPT09ICdzZXJ2ZXInKSB7XG4gICAgICAgICAgdGhpcy5vcHRpb25zLnRvdGFsUm93cyA9IGRhdGFbdGhpcy5vcHRpb25zLnRvdGFsRmllbGRdO1xuICAgICAgICAgIHRoaXMub3B0aW9ucy50b3RhbE5vdEZpbHRlcmVkID0gZGF0YVt0aGlzLm9wdGlvbnMudG90YWxOb3RGaWx0ZXJlZEZpZWxkXTtcbiAgICAgICAgICB0aGlzLmZvb3RlckRhdGEgPSBkYXRhW3RoaXMub3B0aW9ucy5mb290ZXJGaWVsZF0gPyBbZGF0YVt0aGlzLm9wdGlvbnMuZm9vdGVyRmllbGRdXSA6IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGZpeGVkU2Nyb2xsID0gZGF0YS5maXhlZFNjcm9sbDtcbiAgICAgICAgZGF0YSA9IEFycmF5LmlzQXJyYXkoZGF0YSkgPyBkYXRhIDogZGF0YVt0aGlzLm9wdGlvbnMuZGF0YUZpZWxkXTtcbiAgICAgICAgdGhpcy5pbml0RGF0YShkYXRhKTtcbiAgICAgICAgdGhpcy5pbml0U2VhcmNoKCk7XG4gICAgICAgIHRoaXMuaW5pdFBhZ2luYXRpb24oKTtcbiAgICAgICAgdGhpcy5pbml0Qm9keShmaXhlZFNjcm9sbCk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImFwcGVuZFwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGFwcGVuZChkYXRhKSB7XG4gICAgICAgIHRoaXMuaW5pdERhdGEoZGF0YSwgJ2FwcGVuZCcpO1xuICAgICAgICB0aGlzLmluaXRTZWFyY2goKTtcbiAgICAgICAgdGhpcy5pbml0UGFnaW5hdGlvbigpO1xuICAgICAgICB0aGlzLmluaXRTb3J0KCk7XG4gICAgICAgIHRoaXMuaW5pdEJvZHkodHJ1ZSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInByZXBlbmRcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBwcmVwZW5kKGRhdGEpIHtcbiAgICAgICAgdGhpcy5pbml0RGF0YShkYXRhLCAncHJlcGVuZCcpO1xuICAgICAgICB0aGlzLmluaXRTZWFyY2goKTtcbiAgICAgICAgdGhpcy5pbml0UGFnaW5hdGlvbigpO1xuICAgICAgICB0aGlzLmluaXRTb3J0KCk7XG4gICAgICAgIHRoaXMuaW5pdEJvZHkodHJ1ZSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInJlbW92ZVwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHJlbW92ZShwYXJhbXMpIHtcbiAgICAgICAgdmFyIHJlbW92ZWQgPSAwO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSB0aGlzLm9wdGlvbnMuZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgIHZhciByb3cgPSB0aGlzLm9wdGlvbnMuZGF0YVtpXTtcblxuICAgICAgICAgIGlmICghcm93Lmhhc093blByb3BlcnR5KHBhcmFtcy5maWVsZCkgJiYgcGFyYW1zLmZpZWxkICE9PSAnJGluZGV4Jykge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCFyb3cuaGFzT3duUHJvcGVydHkocGFyYW1zLmZpZWxkKSAmJiBwYXJhbXMuZmllbGQgPT09ICckaW5kZXgnICYmIHBhcmFtcy52YWx1ZXMuaW5jbHVkZXMoaSkgfHwgcGFyYW1zLnZhbHVlcy5pbmNsdWRlcyhyb3dbcGFyYW1zLmZpZWxkXSkpIHtcbiAgICAgICAgICAgIHJlbW92ZWQrKztcbiAgICAgICAgICAgIHRoaXMub3B0aW9ucy5kYXRhLnNwbGljZShpLCAxKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXJlbW92ZWQpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNpZGVQYWdpbmF0aW9uID09PSAnc2VydmVyJykge1xuICAgICAgICAgIHRoaXMub3B0aW9ucy50b3RhbFJvd3MgLT0gcmVtb3ZlZDtcbiAgICAgICAgICB0aGlzLmRhdGEgPSBfdG9Db25zdW1hYmxlQXJyYXkodGhpcy5vcHRpb25zLmRhdGEpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5pbml0U2VhcmNoKCk7XG4gICAgICAgIHRoaXMuaW5pdFBhZ2luYXRpb24oKTtcbiAgICAgICAgdGhpcy5pbml0U29ydCgpO1xuICAgICAgICB0aGlzLmluaXRCb2R5KHRydWUpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJyZW1vdmVBbGxcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiByZW1vdmVBbGwoKSB7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuZGF0YS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgdGhpcy5vcHRpb25zLmRhdGEuc3BsaWNlKDAsIHRoaXMub3B0aW9ucy5kYXRhLmxlbmd0aCk7XG4gICAgICAgICAgdGhpcy5pbml0U2VhcmNoKCk7XG4gICAgICAgICAgdGhpcy5pbml0UGFnaW5hdGlvbigpO1xuICAgICAgICAgIHRoaXMuaW5pdEJvZHkodHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiaW5zZXJ0Um93XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaW5zZXJ0Um93KHBhcmFtcykge1xuICAgICAgICBpZiAoIXBhcmFtcy5oYXNPd25Qcm9wZXJ0eSgnaW5kZXgnKSB8fCAhcGFyYW1zLmhhc093blByb3BlcnR5KCdyb3cnKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMub3B0aW9ucy5kYXRhLnNwbGljZShwYXJhbXMuaW5kZXgsIDAsIHBhcmFtcy5yb3cpO1xuICAgICAgICB0aGlzLmluaXRTZWFyY2goKTtcbiAgICAgICAgdGhpcy5pbml0UGFnaW5hdGlvbigpO1xuICAgICAgICB0aGlzLmluaXRTb3J0KCk7XG4gICAgICAgIHRoaXMuaW5pdEJvZHkodHJ1ZSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInVwZGF0ZVJvd1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHVwZGF0ZVJvdyhwYXJhbXMpIHtcbiAgICAgICAgdmFyIGFsbFBhcmFtcyA9IEFycmF5LmlzQXJyYXkocGFyYW1zKSA/IHBhcmFtcyA6IFtwYXJhbXNdO1xuXG4gICAgICAgIHZhciBfaXRlcmF0b3I2ID0gX2NyZWF0ZUZvck9mSXRlcmF0b3JIZWxwZXIoYWxsUGFyYW1zKSxcbiAgICAgICAgICAgIF9zdGVwNjtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGZvciAoX2l0ZXJhdG9yNi5zKCk7ICEoX3N0ZXA2ID0gX2l0ZXJhdG9yNi5uKCkpLmRvbmU7KSB7XG4gICAgICAgICAgICB2YXIgX3BhcmFtcyA9IF9zdGVwNi52YWx1ZTtcblxuICAgICAgICAgICAgaWYgKCFfcGFyYW1zLmhhc093blByb3BlcnR5KCdpbmRleCcpIHx8ICFfcGFyYW1zLmhhc093blByb3BlcnR5KCdyb3cnKSkge1xuICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKF9wYXJhbXMuaGFzT3duUHJvcGVydHkoJ3JlcGxhY2UnKSAmJiBfcGFyYW1zLnJlcGxhY2UpIHtcbiAgICAgICAgICAgICAgdGhpcy5vcHRpb25zLmRhdGFbX3BhcmFtcy5pbmRleF0gPSBfcGFyYW1zLnJvdztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5leHRlbmQodGhpcy5vcHRpb25zLmRhdGFbX3BhcmFtcy5pbmRleF0sIF9wYXJhbXMucm93KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIF9pdGVyYXRvcjYuZShlcnIpO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIF9pdGVyYXRvcjYuZigpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5pbml0U2VhcmNoKCk7XG4gICAgICAgIHRoaXMuaW5pdFBhZ2luYXRpb24oKTtcbiAgICAgICAgdGhpcy5pbml0U29ydCgpO1xuICAgICAgICB0aGlzLmluaXRCb2R5KHRydWUpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJnZXRSb3dCeVVuaXF1ZUlkXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0Um93QnlVbmlxdWVJZChfaWQpIHtcbiAgICAgICAgdmFyIHVuaXF1ZUlkID0gdGhpcy5vcHRpb25zLnVuaXF1ZUlkO1xuICAgICAgICB2YXIgbGVuID0gdGhpcy5vcHRpb25zLmRhdGEubGVuZ3RoO1xuICAgICAgICB2YXIgaWQgPSBfaWQ7XG4gICAgICAgIHZhciBkYXRhUm93ID0gbnVsbDtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciByb3c7XG4gICAgICAgIHZhciByb3dVbmlxdWVJZDtcblxuICAgICAgICBmb3IgKGkgPSBsZW4gLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgIHJvdyA9IHRoaXMub3B0aW9ucy5kYXRhW2ldO1xuXG4gICAgICAgICAgaWYgKHJvdy5oYXNPd25Qcm9wZXJ0eSh1bmlxdWVJZCkpIHtcbiAgICAgICAgICAgIC8vIHVuaXF1ZUlkIGlzIGEgY29sdW1uXG4gICAgICAgICAgICByb3dVbmlxdWVJZCA9IHJvd1t1bmlxdWVJZF07XG4gICAgICAgICAgfSBlbHNlIGlmIChyb3cuX2RhdGEgJiYgcm93Ll9kYXRhLmhhc093blByb3BlcnR5KHVuaXF1ZUlkKSkge1xuICAgICAgICAgICAgLy8gdW5pcXVlSWQgaXMgYSByb3cgZGF0YSBwcm9wZXJ0eVxuICAgICAgICAgICAgcm93VW5pcXVlSWQgPSByb3cuX2RhdGFbdW5pcXVlSWRdO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAodHlwZW9mIHJvd1VuaXF1ZUlkID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgaWQgPSBpZC50b1N0cmluZygpO1xuICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHJvd1VuaXF1ZUlkID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgaWYgKE51bWJlcihyb3dVbmlxdWVJZCkgPT09IHJvd1VuaXF1ZUlkICYmIHJvd1VuaXF1ZUlkICUgMSA9PT0gMCkge1xuICAgICAgICAgICAgICBpZCA9IHBhcnNlSW50KGlkKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocm93VW5pcXVlSWQgPT09IE51bWJlcihyb3dVbmlxdWVJZCkgJiYgcm93VW5pcXVlSWQgIT09IDApIHtcbiAgICAgICAgICAgICAgaWQgPSBwYXJzZUZsb2F0KGlkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAocm93VW5pcXVlSWQgPT09IGlkKSB7XG4gICAgICAgICAgICBkYXRhUm93ID0gcm93O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGRhdGFSb3c7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInVwZGF0ZUJ5VW5pcXVlSWRcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiB1cGRhdGVCeVVuaXF1ZUlkKHBhcmFtcykge1xuICAgICAgICB2YXIgYWxsUGFyYW1zID0gQXJyYXkuaXNBcnJheShwYXJhbXMpID8gcGFyYW1zIDogW3BhcmFtc107XG5cbiAgICAgICAgdmFyIF9pdGVyYXRvcjcgPSBfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlcihhbGxQYXJhbXMpLFxuICAgICAgICAgICAgX3N0ZXA3O1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZm9yIChfaXRlcmF0b3I3LnMoKTsgIShfc3RlcDcgPSBfaXRlcmF0b3I3Lm4oKSkuZG9uZTspIHtcbiAgICAgICAgICAgIHZhciBfcGFyYW1zMiA9IF9zdGVwNy52YWx1ZTtcblxuICAgICAgICAgICAgaWYgKCFfcGFyYW1zMi5oYXNPd25Qcm9wZXJ0eSgnaWQnKSB8fCAhX3BhcmFtczIuaGFzT3duUHJvcGVydHkoJ3JvdycpKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgcm93SWQgPSB0aGlzLm9wdGlvbnMuZGF0YS5pbmRleE9mKHRoaXMuZ2V0Um93QnlVbmlxdWVJZChfcGFyYW1zMi5pZCkpO1xuXG4gICAgICAgICAgICBpZiAocm93SWQgPT09IC0xKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoX3BhcmFtczIuaGFzT3duUHJvcGVydHkoJ3JlcGxhY2UnKSAmJiBfcGFyYW1zMi5yZXBsYWNlKSB7XG4gICAgICAgICAgICAgIHRoaXMub3B0aW9ucy5kYXRhW3Jvd0lkXSA9IF9wYXJhbXMyLnJvdztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5leHRlbmQodGhpcy5vcHRpb25zLmRhdGFbcm93SWRdLCBfcGFyYW1zMi5yb3cpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgX2l0ZXJhdG9yNy5lKGVycik7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgX2l0ZXJhdG9yNy5mKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmluaXRTZWFyY2goKTtcbiAgICAgICAgdGhpcy5pbml0UGFnaW5hdGlvbigpO1xuICAgICAgICB0aGlzLmluaXRTb3J0KCk7XG4gICAgICAgIHRoaXMuaW5pdEJvZHkodHJ1ZSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInJlbW92ZUJ5VW5pcXVlSWRcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiByZW1vdmVCeVVuaXF1ZUlkKGlkKSB7XG4gICAgICAgIHZhciBsZW4gPSB0aGlzLm9wdGlvbnMuZGF0YS5sZW5ndGg7XG4gICAgICAgIHZhciByb3cgPSB0aGlzLmdldFJvd0J5VW5pcXVlSWQoaWQpO1xuXG4gICAgICAgIGlmIChyb3cpIHtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMuZGF0YS5zcGxpY2UodGhpcy5vcHRpb25zLmRhdGEuaW5kZXhPZihyb3cpLCAxKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChsZW4gPT09IHRoaXMub3B0aW9ucy5kYXRhLmxlbmd0aCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuc2lkZVBhZ2luYXRpb24gPT09ICdzZXJ2ZXInKSB7XG4gICAgICAgICAgdGhpcy5vcHRpb25zLnRvdGFsUm93cyAtPSAxO1xuICAgICAgICAgIHRoaXMuZGF0YSA9IF90b0NvbnN1bWFibGVBcnJheSh0aGlzLm9wdGlvbnMuZGF0YSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmluaXRTZWFyY2goKTtcbiAgICAgICAgdGhpcy5pbml0UGFnaW5hdGlvbigpO1xuICAgICAgICB0aGlzLmluaXRCb2R5KHRydWUpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJ1cGRhdGVDZWxsXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdXBkYXRlQ2VsbChwYXJhbXMpIHtcbiAgICAgICAgaWYgKCFwYXJhbXMuaGFzT3duUHJvcGVydHkoJ2luZGV4JykgfHwgIXBhcmFtcy5oYXNPd25Qcm9wZXJ0eSgnZmllbGQnKSB8fCAhcGFyYW1zLmhhc093blByb3BlcnR5KCd2YWx1ZScpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5kYXRhW3BhcmFtcy5pbmRleF1bcGFyYW1zLmZpZWxkXSA9IHBhcmFtcy52YWx1ZTtcblxuICAgICAgICBpZiAocGFyYW1zLnJlaW5pdCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmluaXRTb3J0KCk7XG4gICAgICAgIHRoaXMuaW5pdEJvZHkodHJ1ZSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInVwZGF0ZUNlbGxCeVVuaXF1ZUlkXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdXBkYXRlQ2VsbEJ5VW5pcXVlSWQocGFyYW1zKSB7XG4gICAgICAgIHZhciBfdGhpczE5ID0gdGhpcztcblxuICAgICAgICB2YXIgYWxsUGFyYW1zID0gQXJyYXkuaXNBcnJheShwYXJhbXMpID8gcGFyYW1zIDogW3BhcmFtc107XG4gICAgICAgIGFsbFBhcmFtcy5mb3JFYWNoKGZ1bmN0aW9uIChfcmVmNikge1xuICAgICAgICAgIHZhciBpZCA9IF9yZWY2LmlkLFxuICAgICAgICAgICAgICBmaWVsZCA9IF9yZWY2LmZpZWxkLFxuICAgICAgICAgICAgICB2YWx1ZSA9IF9yZWY2LnZhbHVlO1xuXG4gICAgICAgICAgdmFyIHJvd0lkID0gX3RoaXMxOS5vcHRpb25zLmRhdGEuaW5kZXhPZihfdGhpczE5LmdldFJvd0J5VW5pcXVlSWQoaWQpKTtcblxuICAgICAgICAgIGlmIChyb3dJZCA9PT0gLTEpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBfdGhpczE5Lm9wdGlvbnMuZGF0YVtyb3dJZF1bZmllbGRdID0gdmFsdWU7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChwYXJhbXMucmVpbml0ID09PSBmYWxzZSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaW5pdFNvcnQoKTtcbiAgICAgICAgdGhpcy5pbml0Qm9keSh0cnVlKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwic2hvd1Jvd1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHNob3dSb3cocGFyYW1zKSB7XG4gICAgICAgIHRoaXMuX3RvZ2dsZVJvdyhwYXJhbXMsIHRydWUpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJoaWRlUm93XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaGlkZVJvdyhwYXJhbXMpIHtcbiAgICAgICAgdGhpcy5fdG9nZ2xlUm93KHBhcmFtcywgZmFsc2UpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJfdG9nZ2xlUm93XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gX3RvZ2dsZVJvdyhwYXJhbXMsIHZpc2libGUpIHtcbiAgICAgICAgdmFyIHJvdztcblxuICAgICAgICBpZiAocGFyYW1zLmhhc093blByb3BlcnR5KCdpbmRleCcpKSB7XG4gICAgICAgICAgcm93ID0gdGhpcy5nZXREYXRhKClbcGFyYW1zLmluZGV4XTtcbiAgICAgICAgfSBlbHNlIGlmIChwYXJhbXMuaGFzT3duUHJvcGVydHkoJ3VuaXF1ZUlkJykpIHtcbiAgICAgICAgICByb3cgPSB0aGlzLmdldFJvd0J5VW5pcXVlSWQocGFyYW1zLnVuaXF1ZUlkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghcm93KSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGluZGV4ID0gVXRpbHMuZmluZEluZGV4KHRoaXMuaGlkZGVuUm93cywgcm93KTtcblxuICAgICAgICBpZiAoIXZpc2libGUgJiYgaW5kZXggPT09IC0xKSB7XG4gICAgICAgICAgdGhpcy5oaWRkZW5Sb3dzLnB1c2gocm93KTtcbiAgICAgICAgfSBlbHNlIGlmICh2aXNpYmxlICYmIGluZGV4ID4gLTEpIHtcbiAgICAgICAgICB0aGlzLmhpZGRlblJvd3Muc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaW5pdEJvZHkodHJ1ZSk7XG4gICAgICAgIHRoaXMuaW5pdFBhZ2luYXRpb24oKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiZ2V0SGlkZGVuUm93c1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGdldEhpZGRlblJvd3Moc2hvdykge1xuICAgICAgICBpZiAoc2hvdykge1xuICAgICAgICAgIHRoaXMuaW5pdEhpZGRlblJvd3MoKTtcbiAgICAgICAgICB0aGlzLmluaXRCb2R5KHRydWUpO1xuICAgICAgICAgIHRoaXMuaW5pdFBhZ2luYXRpb24oKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZGF0YSA9IHRoaXMuZ2V0RGF0YSgpO1xuICAgICAgICB2YXIgcm93cyA9IFtdO1xuXG4gICAgICAgIHZhciBfaXRlcmF0b3I4ID0gX2NyZWF0ZUZvck9mSXRlcmF0b3JIZWxwZXIoZGF0YSksXG4gICAgICAgICAgICBfc3RlcDg7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBmb3IgKF9pdGVyYXRvcjgucygpOyAhKF9zdGVwOCA9IF9pdGVyYXRvcjgubigpKS5kb25lOykge1xuICAgICAgICAgICAgdmFyIHJvdyA9IF9zdGVwOC52YWx1ZTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuaGlkZGVuUm93cy5pbmNsdWRlcyhyb3cpKSB7XG4gICAgICAgICAgICAgIHJvd3MucHVzaChyb3cpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgX2l0ZXJhdG9yOC5lKGVycik7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgX2l0ZXJhdG9yOC5mKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmhpZGRlblJvd3MgPSByb3dzO1xuICAgICAgICByZXR1cm4gcm93cztcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwic2hvd0NvbHVtblwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHNob3dDb2x1bW4oZmllbGQpIHtcbiAgICAgICAgdmFyIF90aGlzMjAgPSB0aGlzO1xuXG4gICAgICAgIHZhciBmaWVsZHMgPSBBcnJheS5pc0FycmF5KGZpZWxkKSA/IGZpZWxkIDogW2ZpZWxkXTtcbiAgICAgICAgZmllbGRzLmZvckVhY2goZnVuY3Rpb24gKGZpZWxkKSB7XG4gICAgICAgICAgX3RoaXMyMC5fdG9nZ2xlQ29sdW1uKF90aGlzMjAuZmllbGRzQ29sdW1uc0luZGV4W2ZpZWxkXSwgdHJ1ZSwgdHJ1ZSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJoaWRlQ29sdW1uXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaGlkZUNvbHVtbihmaWVsZCkge1xuICAgICAgICB2YXIgX3RoaXMyMSA9IHRoaXM7XG5cbiAgICAgICAgdmFyIGZpZWxkcyA9IEFycmF5LmlzQXJyYXkoZmllbGQpID8gZmllbGQgOiBbZmllbGRdO1xuICAgICAgICBmaWVsZHMuZm9yRWFjaChmdW5jdGlvbiAoZmllbGQpIHtcbiAgICAgICAgICBfdGhpczIxLl90b2dnbGVDb2x1bW4oX3RoaXMyMS5maWVsZHNDb2x1bW5zSW5kZXhbZmllbGRdLCBmYWxzZSwgdHJ1ZSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJfdG9nZ2xlQ29sdW1uXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gX3RvZ2dsZUNvbHVtbihpbmRleCwgY2hlY2tlZCwgbmVlZFVwZGF0ZSkge1xuICAgICAgICBpZiAoaW5kZXggPT09IC0xIHx8IHRoaXMuY29sdW1uc1tpbmRleF0udmlzaWJsZSA9PT0gY2hlY2tlZCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY29sdW1uc1tpbmRleF0udmlzaWJsZSA9IGNoZWNrZWQ7XG4gICAgICAgIHRoaXMuaW5pdEhlYWRlcigpO1xuICAgICAgICB0aGlzLmluaXRTZWFyY2goKTtcbiAgICAgICAgdGhpcy5pbml0UGFnaW5hdGlvbigpO1xuICAgICAgICB0aGlzLmluaXRCb2R5KCk7XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5zaG93Q29sdW1ucykge1xuICAgICAgICAgIHZhciAkaXRlbXMgPSB0aGlzLiR0b29sYmFyLmZpbmQoJy5rZWVwLW9wZW4gaW5wdXQ6bm90KFwiLnRvZ2dsZS1hbGxcIiknKS5wcm9wKCdkaXNhYmxlZCcsIGZhbHNlKTtcblxuICAgICAgICAgIGlmIChuZWVkVXBkYXRlKSB7XG4gICAgICAgICAgICAkaXRlbXMuZmlsdGVyKFV0aWxzLnNwcmludGYoJ1t2YWx1ZT1cIiVzXCJdJywgaW5kZXgpKS5wcm9wKCdjaGVja2VkJywgY2hlY2tlZCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCRpdGVtcy5maWx0ZXIoJzpjaGVja2VkJykubGVuZ3RoIDw9IHRoaXMub3B0aW9ucy5taW5pbXVtQ291bnRDb2x1bW5zKSB7XG4gICAgICAgICAgICAkaXRlbXMuZmlsdGVyKCc6Y2hlY2tlZCcpLnByb3AoJ2Rpc2FibGVkJywgdHJ1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImdldFZpc2libGVDb2x1bW5zXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0VmlzaWJsZUNvbHVtbnMoKSB7XG4gICAgICAgIHZhciBfdGhpczIyID0gdGhpcztcblxuICAgICAgICByZXR1cm4gdGhpcy5jb2x1bW5zLmZpbHRlcihmdW5jdGlvbiAoY29sdW1uKSB7XG4gICAgICAgICAgcmV0dXJuIGNvbHVtbi52aXNpYmxlICYmICFfdGhpczIyLmlzU2VsZWN0aW9uQ29sdW1uKGNvbHVtbik7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJnZXRIaWRkZW5Db2x1bW5zXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0SGlkZGVuQ29sdW1ucygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29sdW1ucy5maWx0ZXIoZnVuY3Rpb24gKF9yZWY3KSB7XG4gICAgICAgICAgdmFyIHZpc2libGUgPSBfcmVmNy52aXNpYmxlO1xuICAgICAgICAgIHJldHVybiAhdmlzaWJsZTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImlzU2VsZWN0aW9uQ29sdW1uXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaXNTZWxlY3Rpb25Db2x1bW4oY29sdW1uKSB7XG4gICAgICAgIHJldHVybiBjb2x1bW4ucmFkaW8gfHwgY29sdW1uLmNoZWNrYm94O1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJzaG93QWxsQ29sdW1uc1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHNob3dBbGxDb2x1bW5zKCkge1xuICAgICAgICB0aGlzLl90b2dnbGVBbGxDb2x1bW5zKHRydWUpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJoaWRlQWxsQ29sdW1uc1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGhpZGVBbGxDb2x1bW5zKCkge1xuICAgICAgICB0aGlzLl90b2dnbGVBbGxDb2x1bW5zKGZhbHNlKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiX3RvZ2dsZUFsbENvbHVtbnNcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBfdG9nZ2xlQWxsQ29sdW1ucyh2aXNpYmxlKSB7XG4gICAgICAgIHZhciBfdGhpczIzID0gdGhpcztcblxuICAgICAgICB2YXIgX2l0ZXJhdG9yOSA9IF9jcmVhdGVGb3JPZkl0ZXJhdG9ySGVscGVyKHRoaXMuY29sdW1ucy5zbGljZSgpLnJldmVyc2UoKSksXG4gICAgICAgICAgICBfc3RlcDk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBmb3IgKF9pdGVyYXRvcjkucygpOyAhKF9zdGVwOSA9IF9pdGVyYXRvcjkubigpKS5kb25lOykge1xuICAgICAgICAgICAgdmFyIGNvbHVtbiA9IF9zdGVwOS52YWx1ZTtcblxuICAgICAgICAgICAgaWYgKGNvbHVtbi5zd2l0Y2hhYmxlKSB7XG4gICAgICAgICAgICAgIGlmICghdmlzaWJsZSAmJiB0aGlzLm9wdGlvbnMuc2hvd0NvbHVtbnMgJiYgdGhpcy5nZXRWaXNpYmxlQ29sdW1ucygpLmxlbmd0aCA9PT0gdGhpcy5vcHRpb25zLm1pbmltdW1Db3VudENvbHVtbnMpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGNvbHVtbi52aXNpYmxlID0gdmlzaWJsZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIF9pdGVyYXRvcjkuZShlcnIpO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIF9pdGVyYXRvcjkuZigpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5pbml0SGVhZGVyKCk7XG4gICAgICAgIHRoaXMuaW5pdFNlYXJjaCgpO1xuICAgICAgICB0aGlzLmluaXRQYWdpbmF0aW9uKCk7XG4gICAgICAgIHRoaXMuaW5pdEJvZHkoKTtcblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNob3dDb2x1bW5zKSB7XG4gICAgICAgICAgdmFyICRpdGVtcyA9IHRoaXMuJHRvb2xiYXIuZmluZCgnLmtlZXAtb3BlbiBpbnB1dFt0eXBlPVwiY2hlY2tib3hcIl06bm90KFwiLnRvZ2dsZS1hbGxcIiknKS5wcm9wKCdkaXNhYmxlZCcsIGZhbHNlKTtcblxuICAgICAgICAgIGlmICh2aXNpYmxlKSB7XG4gICAgICAgICAgICAkaXRlbXMucHJvcCgnY2hlY2tlZCcsIHZpc2libGUpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAkaXRlbXMuZ2V0KCkucmV2ZXJzZSgpLmZvckVhY2goZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgICAgICAgaWYgKCRpdGVtcy5maWx0ZXIoJzpjaGVja2VkJykubGVuZ3RoID4gX3RoaXMyMy5vcHRpb25zLm1pbmltdW1Db3VudENvbHVtbnMpIHtcbiAgICAgICAgICAgICAgICAkX19kZWZhdWx0WydkZWZhdWx0J10oaXRlbSkucHJvcCgnY2hlY2tlZCcsIHZpc2libGUpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoJGl0ZW1zLmZpbHRlcignOmNoZWNrZWQnKS5sZW5ndGggPD0gdGhpcy5vcHRpb25zLm1pbmltdW1Db3VudENvbHVtbnMpIHtcbiAgICAgICAgICAgICRpdGVtcy5maWx0ZXIoJzpjaGVja2VkJykucHJvcCgnZGlzYWJsZWQnLCB0cnVlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwibWVyZ2VDZWxsc1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIG1lcmdlQ2VsbHMob3B0aW9ucykge1xuICAgICAgICB2YXIgcm93ID0gb3B0aW9ucy5pbmRleDtcbiAgICAgICAgdmFyIGNvbCA9IHRoaXMuZ2V0VmlzaWJsZUZpZWxkcygpLmluZGV4T2Yob3B0aW9ucy5maWVsZCk7XG4gICAgICAgIHZhciByb3dzcGFuID0gb3B0aW9ucy5yb3dzcGFuIHx8IDE7XG4gICAgICAgIHZhciBjb2xzcGFuID0gb3B0aW9ucy5jb2xzcGFuIHx8IDE7XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIgajtcbiAgICAgICAgdmFyICR0ciA9IHRoaXMuJGJvZHkuZmluZCgnPnRyJyk7XG4gICAgICAgIGNvbCArPSBVdGlscy5nZXREZXRhaWxWaWV3SW5kZXhPZmZzZXQodGhpcy5vcHRpb25zKTtcbiAgICAgICAgdmFyICR0ZCA9ICR0ci5lcShyb3cpLmZpbmQoJz50ZCcpLmVxKGNvbCk7XG5cbiAgICAgICAgaWYgKHJvdyA8IDAgfHwgY29sIDwgMCB8fCByb3cgPj0gdGhpcy5kYXRhLmxlbmd0aCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAoaSA9IHJvdzsgaSA8IHJvdyArIHJvd3NwYW47IGkrKykge1xuICAgICAgICAgIGZvciAoaiA9IGNvbDsgaiA8IGNvbCArIGNvbHNwYW47IGorKykge1xuICAgICAgICAgICAgJHRyLmVxKGkpLmZpbmQoJz50ZCcpLmVxKGopLmhpZGUoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAkdGQuYXR0cigncm93c3BhbicsIHJvd3NwYW4pLmF0dHIoJ2NvbHNwYW4nLCBjb2xzcGFuKS5zaG93KCk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImNoZWNrQWxsXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gY2hlY2tBbGwoKSB7XG4gICAgICAgIHRoaXMuX3RvZ2dsZUNoZWNrQWxsKHRydWUpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJ1bmNoZWNrQWxsXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdW5jaGVja0FsbCgpIHtcbiAgICAgICAgdGhpcy5fdG9nZ2xlQ2hlY2tBbGwoZmFsc2UpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJfdG9nZ2xlQ2hlY2tBbGxcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBfdG9nZ2xlQ2hlY2tBbGwoY2hlY2tlZCkge1xuICAgICAgICB2YXIgcm93c0JlZm9yZSA9IHRoaXMuZ2V0U2VsZWN0aW9ucygpO1xuICAgICAgICB0aGlzLiRzZWxlY3RBbGwuYWRkKHRoaXMuJHNlbGVjdEFsbF8pLnByb3AoJ2NoZWNrZWQnLCBjaGVja2VkKTtcbiAgICAgICAgdGhpcy4kc2VsZWN0SXRlbS5maWx0ZXIoJzplbmFibGVkJykucHJvcCgnY2hlY2tlZCcsIGNoZWNrZWQpO1xuICAgICAgICB0aGlzLnVwZGF0ZVJvd3MoKTtcbiAgICAgICAgdGhpcy51cGRhdGVTZWxlY3RlZCgpO1xuICAgICAgICB2YXIgcm93c0FmdGVyID0gdGhpcy5nZXRTZWxlY3Rpb25zKCk7XG5cbiAgICAgICAgaWYgKGNoZWNrZWQpIHtcbiAgICAgICAgICB0aGlzLnRyaWdnZXIoJ2NoZWNrLWFsbCcsIHJvd3NBZnRlciwgcm93c0JlZm9yZSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy50cmlnZ2VyKCd1bmNoZWNrLWFsbCcsIHJvd3NBZnRlciwgcm93c0JlZm9yZSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImNoZWNrSW52ZXJ0XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gY2hlY2tJbnZlcnQoKSB7XG4gICAgICAgIHZhciAkaXRlbXMgPSB0aGlzLiRzZWxlY3RJdGVtLmZpbHRlcignOmVuYWJsZWQnKTtcbiAgICAgICAgdmFyIGNoZWNrZWQgPSAkaXRlbXMuZmlsdGVyKCc6Y2hlY2tlZCcpO1xuICAgICAgICAkaXRlbXMuZWFjaChmdW5jdGlvbiAoaSwgZWwpIHtcbiAgICAgICAgICAkX19kZWZhdWx0WydkZWZhdWx0J10oZWwpLnByb3AoJ2NoZWNrZWQnLCAhJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKS5wcm9wKCdjaGVja2VkJykpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy51cGRhdGVSb3dzKCk7XG4gICAgICAgIHRoaXMudXBkYXRlU2VsZWN0ZWQoKTtcbiAgICAgICAgdGhpcy50cmlnZ2VyKCd1bmNoZWNrLXNvbWUnLCBjaGVja2VkKTtcbiAgICAgICAgY2hlY2tlZCA9IHRoaXMuZ2V0U2VsZWN0aW9ucygpO1xuICAgICAgICB0aGlzLnRyaWdnZXIoJ2NoZWNrLXNvbWUnLCBjaGVja2VkKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiY2hlY2tcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBjaGVjayhpbmRleCkge1xuICAgICAgICB0aGlzLl90b2dnbGVDaGVjayh0cnVlLCBpbmRleCk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInVuY2hlY2tcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiB1bmNoZWNrKGluZGV4KSB7XG4gICAgICAgIHRoaXMuX3RvZ2dsZUNoZWNrKGZhbHNlLCBpbmRleCk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcIl90b2dnbGVDaGVja1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIF90b2dnbGVDaGVjayhjaGVja2VkLCBpbmRleCkge1xuICAgICAgICB2YXIgJGVsID0gdGhpcy4kc2VsZWN0SXRlbS5maWx0ZXIoXCJbZGF0YS1pbmRleD1cXFwiXCIuY29uY2F0KGluZGV4LCBcIlxcXCJdXCIpKTtcbiAgICAgICAgdmFyIHJvdyA9IHRoaXMuZGF0YVtpbmRleF07XG5cbiAgICAgICAgaWYgKCRlbC5pcygnOnJhZGlvJykgfHwgdGhpcy5vcHRpb25zLnNpbmdsZVNlbGVjdCB8fCB0aGlzLm9wdGlvbnMubXVsdGlwbGVTZWxlY3RSb3cgJiYgIXRoaXMubXVsdGlwbGVTZWxlY3RSb3dDdHJsS2V5ICYmICF0aGlzLm11bHRpcGxlU2VsZWN0Um93U2hpZnRLZXkpIHtcbiAgICAgICAgICB2YXIgX2l0ZXJhdG9yMTAgPSBfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlcih0aGlzLm9wdGlvbnMuZGF0YSksXG4gICAgICAgICAgICAgIF9zdGVwMTA7XG5cbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgZm9yIChfaXRlcmF0b3IxMC5zKCk7ICEoX3N0ZXAxMCA9IF9pdGVyYXRvcjEwLm4oKSkuZG9uZTspIHtcbiAgICAgICAgICAgICAgdmFyIHIgPSBfc3RlcDEwLnZhbHVlO1xuICAgICAgICAgICAgICByW3RoaXMuaGVhZGVyLnN0YXRlRmllbGRdID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBfaXRlcmF0b3IxMC5lKGVycik7XG4gICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgIF9pdGVyYXRvcjEwLmYoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aGlzLiRzZWxlY3RJdGVtLmZpbHRlcignOmNoZWNrZWQnKS5ub3QoJGVsKS5wcm9wKCdjaGVja2VkJywgZmFsc2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgcm93W3RoaXMuaGVhZGVyLnN0YXRlRmllbGRdID0gY2hlY2tlZDtcblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLm11bHRpcGxlU2VsZWN0Um93KSB7XG4gICAgICAgICAgaWYgKHRoaXMubXVsdGlwbGVTZWxlY3RSb3dTaGlmdEtleSAmJiB0aGlzLm11bHRpcGxlU2VsZWN0Um93TGFzdFNlbGVjdGVkSW5kZXggPj0gMCkge1xuICAgICAgICAgICAgdmFyIF9yZWY4ID0gdGhpcy5tdWx0aXBsZVNlbGVjdFJvd0xhc3RTZWxlY3RlZEluZGV4IDwgaW5kZXggPyBbdGhpcy5tdWx0aXBsZVNlbGVjdFJvd0xhc3RTZWxlY3RlZEluZGV4LCBpbmRleF0gOiBbaW5kZXgsIHRoaXMubXVsdGlwbGVTZWxlY3RSb3dMYXN0U2VsZWN0ZWRJbmRleF0sXG4gICAgICAgICAgICAgICAgX3JlZjkgPSBfc2xpY2VkVG9BcnJheShfcmVmOCwgMiksXG4gICAgICAgICAgICAgICAgZnJvbUluZGV4ID0gX3JlZjlbMF0sXG4gICAgICAgICAgICAgICAgdG9JbmRleCA9IF9yZWY5WzFdO1xuXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gZnJvbUluZGV4ICsgMTsgaSA8IHRvSW5kZXg7IGkrKykge1xuICAgICAgICAgICAgICB0aGlzLmRhdGFbaV1bdGhpcy5oZWFkZXIuc3RhdGVGaWVsZF0gPSB0cnVlO1xuICAgICAgICAgICAgICB0aGlzLiRzZWxlY3RJdGVtLmZpbHRlcihcIltkYXRhLWluZGV4PVxcXCJcIi5jb25jYXQoaSwgXCJcXFwiXVwiKSkucHJvcCgnY2hlY2tlZCcsIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMubXVsdGlwbGVTZWxlY3RSb3dDdHJsS2V5ID0gZmFsc2U7XG4gICAgICAgICAgdGhpcy5tdWx0aXBsZVNlbGVjdFJvd1NoaWZ0S2V5ID0gZmFsc2U7XG4gICAgICAgICAgdGhpcy5tdWx0aXBsZVNlbGVjdFJvd0xhc3RTZWxlY3RlZEluZGV4ID0gY2hlY2tlZCA/IGluZGV4IDogLTE7XG4gICAgICAgIH1cblxuICAgICAgICAkZWwucHJvcCgnY2hlY2tlZCcsIGNoZWNrZWQpO1xuICAgICAgICB0aGlzLnVwZGF0ZVNlbGVjdGVkKCk7XG4gICAgICAgIHRoaXMudHJpZ2dlcihjaGVja2VkID8gJ2NoZWNrJyA6ICd1bmNoZWNrJywgdGhpcy5kYXRhW2luZGV4XSwgJGVsKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiY2hlY2tCeVwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGNoZWNrQnkob2JqKSB7XG4gICAgICAgIHRoaXMuX3RvZ2dsZUNoZWNrQnkodHJ1ZSwgb2JqKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwidW5jaGVja0J5XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdW5jaGVja0J5KG9iaikge1xuICAgICAgICB0aGlzLl90b2dnbGVDaGVja0J5KGZhbHNlLCBvYmopO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJfdG9nZ2xlQ2hlY2tCeVwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIF90b2dnbGVDaGVja0J5KGNoZWNrZWQsIG9iaikge1xuICAgICAgICB2YXIgX3RoaXMyNCA9IHRoaXM7XG5cbiAgICAgICAgaWYgKCFvYmouaGFzT3duUHJvcGVydHkoJ2ZpZWxkJykgfHwgIW9iai5oYXNPd25Qcm9wZXJ0eSgndmFsdWVzJykpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcm93cyA9IFtdO1xuICAgICAgICB0aGlzLmRhdGEuZm9yRWFjaChmdW5jdGlvbiAocm93LCBpKSB7XG4gICAgICAgICAgaWYgKCFyb3cuaGFzT3duUHJvcGVydHkob2JqLmZpZWxkKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChvYmoudmFsdWVzLmluY2x1ZGVzKHJvd1tvYmouZmllbGRdKSkge1xuICAgICAgICAgICAgdmFyICRlbCA9IF90aGlzMjQuJHNlbGVjdEl0ZW0uZmlsdGVyKCc6ZW5hYmxlZCcpLmZpbHRlcihVdGlscy5zcHJpbnRmKCdbZGF0YS1pbmRleD1cIiVzXCJdJywgaSkpO1xuXG4gICAgICAgICAgICAkZWwgPSBjaGVja2VkID8gJGVsLm5vdCgnOmNoZWNrZWQnKSA6ICRlbC5maWx0ZXIoJzpjaGVja2VkJyk7XG5cbiAgICAgICAgICAgIGlmICghJGVsLmxlbmd0aCkge1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICRlbC5wcm9wKCdjaGVja2VkJywgY2hlY2tlZCk7XG4gICAgICAgICAgICByb3dbX3RoaXMyNC5oZWFkZXIuc3RhdGVGaWVsZF0gPSBjaGVja2VkO1xuICAgICAgICAgICAgcm93cy5wdXNoKHJvdyk7XG5cbiAgICAgICAgICAgIF90aGlzMjQudHJpZ2dlcihjaGVja2VkID8gJ2NoZWNrJyA6ICd1bmNoZWNrJywgcm93LCAkZWwpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMudXBkYXRlU2VsZWN0ZWQoKTtcbiAgICAgICAgdGhpcy50cmlnZ2VyKGNoZWNrZWQgPyAnY2hlY2stc29tZScgOiAndW5jaGVjay1zb21lJywgcm93cyk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInJlZnJlc2hcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiByZWZyZXNoKHBhcmFtcykge1xuICAgICAgICBpZiAocGFyYW1zICYmIHBhcmFtcy51cmwpIHtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMudXJsID0gcGFyYW1zLnVybDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwYXJhbXMgJiYgcGFyYW1zLnBhZ2VOdW1iZXIpIHtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMucGFnZU51bWJlciA9IHBhcmFtcy5wYWdlTnVtYmVyO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcmFtcyAmJiBwYXJhbXMucGFnZVNpemUpIHtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMucGFnZVNpemUgPSBwYXJhbXMucGFnZVNpemU7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnRyaWdnZXIoJ3JlZnJlc2gnLCB0aGlzLmluaXRTZXJ2ZXIocGFyYW1zICYmIHBhcmFtcy5zaWxlbnQsIHBhcmFtcyAmJiBwYXJhbXMucXVlcnksIHBhcmFtcyAmJiBwYXJhbXMudXJsKSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImRlc3Ryb3lcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBkZXN0cm95KCkge1xuICAgICAgICB0aGlzLiRlbC5pbnNlcnRCZWZvcmUodGhpcy4kY29udGFpbmVyKTtcbiAgICAgICAgJF9fZGVmYXVsdFsnZGVmYXVsdCddKHRoaXMub3B0aW9ucy50b29sYmFyKS5pbnNlcnRCZWZvcmUodGhpcy4kZWwpO1xuICAgICAgICB0aGlzLiRjb250YWluZXIubmV4dCgpLnJlbW92ZSgpO1xuICAgICAgICB0aGlzLiRjb250YWluZXIucmVtb3ZlKCk7XG4gICAgICAgIHRoaXMuJGVsLmh0bWwodGhpcy4kZWxfLmh0bWwoKSkuY3NzKCdtYXJnaW4tdG9wJywgJzAnKS5hdHRyKCdjbGFzcycsIHRoaXMuJGVsXy5hdHRyKCdjbGFzcycpIHx8ICcnKTsgLy8gcmVzZXQgdGhlIGNsYXNzXG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInJlc2V0Vmlld1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHJlc2V0VmlldyhwYXJhbXMpIHtcbiAgICAgICAgdmFyIHBhZGRpbmcgPSAwO1xuXG4gICAgICAgIGlmIChwYXJhbXMgJiYgcGFyYW1zLmhlaWdodCkge1xuICAgICAgICAgIHRoaXMub3B0aW9ucy5oZWlnaHQgPSBwYXJhbXMuaGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy4kc2VsZWN0QWxsLnByb3AoJ2NoZWNrZWQnLCB0aGlzLiRzZWxlY3RJdGVtLmxlbmd0aCA+IDAgJiYgdGhpcy4kc2VsZWN0SXRlbS5sZW5ndGggPT09IHRoaXMuJHNlbGVjdEl0ZW0uZmlsdGVyKCc6Y2hlY2tlZCcpLmxlbmd0aCk7XG4gICAgICAgIHRoaXMuJHRhYmxlQ29udGFpbmVyLnRvZ2dsZUNsYXNzKCdoYXMtY2FyZC12aWV3JywgdGhpcy5vcHRpb25zLmNhcmRWaWV3KTtcblxuICAgICAgICBpZiAoIXRoaXMub3B0aW9ucy5jYXJkVmlldyAmJiB0aGlzLm9wdGlvbnMuc2hvd0hlYWRlciAmJiB0aGlzLm9wdGlvbnMuaGVpZ2h0KSB7XG4gICAgICAgICAgdGhpcy4kdGFibGVIZWFkZXIuc2hvdygpO1xuICAgICAgICAgIHRoaXMucmVzZXRIZWFkZXIoKTtcbiAgICAgICAgICBwYWRkaW5nICs9IHRoaXMuJGhlYWRlci5vdXRlckhlaWdodCh0cnVlKSArIDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy4kdGFibGVIZWFkZXIuaGlkZSgpO1xuICAgICAgICAgIHRoaXMudHJpZ2dlcigncG9zdC1oZWFkZXInKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5vcHRpb25zLmNhcmRWaWV3ICYmIHRoaXMub3B0aW9ucy5zaG93Rm9vdGVyKSB7XG4gICAgICAgICAgdGhpcy4kdGFibGVGb290ZXIuc2hvdygpO1xuICAgICAgICAgIHRoaXMuZml0Rm9vdGVyKCk7XG5cbiAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLmhlaWdodCkge1xuICAgICAgICAgICAgcGFkZGluZyArPSB0aGlzLiR0YWJsZUZvb3Rlci5vdXRlckhlaWdodCh0cnVlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy4kY29udGFpbmVyLmhhc0NsYXNzKCdmdWxsc2NyZWVuJykpIHtcbiAgICAgICAgICB0aGlzLiR0YWJsZUNvbnRhaW5lci5jc3MoJ2hlaWdodCcsICcnKTtcbiAgICAgICAgICB0aGlzLiR0YWJsZUNvbnRhaW5lci5jc3MoJ3dpZHRoJywgJycpO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMub3B0aW9ucy5oZWlnaHQpIHtcbiAgICAgICAgICBpZiAodGhpcy4kdGFibGVCb3JkZXIpIHtcbiAgICAgICAgICAgIHRoaXMuJHRhYmxlQm9yZGVyLmNzcygnd2lkdGgnLCAnJyk7XG4gICAgICAgICAgICB0aGlzLiR0YWJsZUJvcmRlci5jc3MoJ2hlaWdodCcsICcnKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgdG9vbGJhckhlaWdodCA9IHRoaXMuJHRvb2xiYXIub3V0ZXJIZWlnaHQodHJ1ZSk7XG4gICAgICAgICAgdmFyIHBhZ2luYXRpb25IZWlnaHQgPSB0aGlzLiRwYWdpbmF0aW9uLm91dGVySGVpZ2h0KHRydWUpO1xuICAgICAgICAgIHZhciBoZWlnaHQgPSB0aGlzLm9wdGlvbnMuaGVpZ2h0IC0gdG9vbGJhckhlaWdodCAtIHBhZ2luYXRpb25IZWlnaHQ7XG4gICAgICAgICAgdmFyICRib2R5VGFibGUgPSB0aGlzLiR0YWJsZUJvZHkuZmluZCgnPnRhYmxlJyk7XG4gICAgICAgICAgdmFyIHRhYmxlSGVpZ2h0ID0gJGJvZHlUYWJsZS5vdXRlckhlaWdodCgpO1xuICAgICAgICAgIHRoaXMuJHRhYmxlQ29udGFpbmVyLmNzcygnaGVpZ2h0JywgXCJcIi5jb25jYXQoaGVpZ2h0LCBcInB4XCIpKTtcblxuICAgICAgICAgIGlmICh0aGlzLiR0YWJsZUJvcmRlciAmJiAkYm9keVRhYmxlLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICB2YXIgdGFibGVCb3JkZXJIZWlnaHQgPSBoZWlnaHQgLSB0YWJsZUhlaWdodCAtIDI7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLiR0YWJsZUJvZHlbMF0uc2Nyb2xsV2lkdGggLSB0aGlzLiR0YWJsZUJvZHkuaW5uZXJXaWR0aCgpKSB7XG4gICAgICAgICAgICAgIHRhYmxlQm9yZGVySGVpZ2h0IC09IFV0aWxzLmdldFNjcm9sbEJhcldpZHRoKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuJHRhYmxlQm9yZGVyLmNzcygnd2lkdGgnLCBcIlwiLmNvbmNhdCgkYm9keVRhYmxlLm91dGVyV2lkdGgoKSwgXCJweFwiKSk7XG4gICAgICAgICAgICB0aGlzLiR0YWJsZUJvcmRlci5jc3MoJ2hlaWdodCcsIFwiXCIuY29uY2F0KHRhYmxlQm9yZGVySGVpZ2h0LCBcInB4XCIpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLmNhcmRWaWV3KSB7XG4gICAgICAgICAgLy8gcmVtb3ZlIHRoZSBlbGVtZW50IGNzc1xuICAgICAgICAgIHRoaXMuJGVsLmNzcygnbWFyZ2luLXRvcCcsICcwJyk7XG4gICAgICAgICAgdGhpcy4kdGFibGVDb250YWluZXIuY3NzKCdwYWRkaW5nLWJvdHRvbScsICcwJyk7XG4gICAgICAgICAgdGhpcy4kdGFibGVGb290ZXIuaGlkZSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIEFzc2lnbiB0aGUgY29ycmVjdCBzb3J0YWJsZSBhcnJvd1xuICAgICAgICAgIHRoaXMuZ2V0Q2FyZXQoKTtcbiAgICAgICAgICB0aGlzLiR0YWJsZUNvbnRhaW5lci5jc3MoJ3BhZGRpbmctYm90dG9tJywgXCJcIi5jb25jYXQocGFkZGluZywgXCJweFwiKSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnRyaWdnZXIoJ3Jlc2V0LXZpZXcnKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwic2hvd0xvYWRpbmdcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBzaG93TG9hZGluZygpIHtcbiAgICAgICAgdGhpcy4kdGFibGVMb2FkaW5nLnRvZ2dsZUNsYXNzKCdvcGVuJywgdHJ1ZSk7XG4gICAgICAgIHZhciBmb250U2l6ZSA9IHRoaXMub3B0aW9ucy5sb2FkaW5nRm9udFNpemU7XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5sb2FkaW5nRm9udFNpemUgPT09ICdhdXRvJykge1xuICAgICAgICAgIGZvbnRTaXplID0gdGhpcy4kdGFibGVMb2FkaW5nLndpZHRoKCkgKiAwLjA0O1xuICAgICAgICAgIGZvbnRTaXplID0gTWF0aC5tYXgoMTIsIGZvbnRTaXplKTtcbiAgICAgICAgICBmb250U2l6ZSA9IE1hdGgubWluKDMyLCBmb250U2l6ZSk7XG4gICAgICAgICAgZm9udFNpemUgPSBcIlwiLmNvbmNhdChmb250U2l6ZSwgXCJweFwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuJHRhYmxlTG9hZGluZy5maW5kKCcubG9hZGluZy10ZXh0JykuY3NzKCdmb250LXNpemUnLCBmb250U2l6ZSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImhpZGVMb2FkaW5nXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaGlkZUxvYWRpbmcoKSB7XG4gICAgICAgIHRoaXMuJHRhYmxlTG9hZGluZy50b2dnbGVDbGFzcygnb3BlbicsIGZhbHNlKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwidG9nZ2xlUGFnaW5hdGlvblwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHRvZ2dsZVBhZ2luYXRpb24oKSB7XG4gICAgICAgIHRoaXMub3B0aW9ucy5wYWdpbmF0aW9uID0gIXRoaXMub3B0aW9ucy5wYWdpbmF0aW9uO1xuICAgICAgICB2YXIgaWNvbiA9IHRoaXMub3B0aW9ucy5zaG93QnV0dG9uSWNvbnMgPyB0aGlzLm9wdGlvbnMucGFnaW5hdGlvbiA/IHRoaXMub3B0aW9ucy5pY29ucy5wYWdpbmF0aW9uU3dpdGNoRG93biA6IHRoaXMub3B0aW9ucy5pY29ucy5wYWdpbmF0aW9uU3dpdGNoVXAgOiAnJztcbiAgICAgICAgdmFyIHRleHQgPSB0aGlzLm9wdGlvbnMuc2hvd0J1dHRvblRleHQgPyB0aGlzLm9wdGlvbnMucGFnaW5hdGlvbiA/IHRoaXMub3B0aW9ucy5mb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXAoKSA6IHRoaXMub3B0aW9ucy5mb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bigpIDogJyc7XG4gICAgICAgIHRoaXMuJHRvb2xiYXIuZmluZCgnYnV0dG9uW25hbWU9XCJwYWdpbmF0aW9uU3dpdGNoXCJdJykuaHRtbChcIlwiLmNvbmNhdChVdGlscy5zcHJpbnRmKHRoaXMuY29uc3RhbnRzLmh0bWwuaWNvbiwgdGhpcy5vcHRpb25zLmljb25zUHJlZml4LCBpY29uKSwgXCIgXCIpLmNvbmNhdCh0ZXh0KSk7XG4gICAgICAgIHRoaXMudXBkYXRlUGFnaW5hdGlvbigpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJ0b2dnbGVGdWxsc2NyZWVuXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdG9nZ2xlRnVsbHNjcmVlbigpIHtcbiAgICAgICAgdGhpcy4kZWwuY2xvc2VzdCgnLmJvb3RzdHJhcC10YWJsZScpLnRvZ2dsZUNsYXNzKCdmdWxsc2NyZWVuJyk7XG4gICAgICAgIHRoaXMucmVzZXRWaWV3KCk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInRvZ2dsZVZpZXdcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiB0b2dnbGVWaWV3KCkge1xuICAgICAgICB0aGlzLm9wdGlvbnMuY2FyZFZpZXcgPSAhdGhpcy5vcHRpb25zLmNhcmRWaWV3O1xuICAgICAgICB0aGlzLmluaXRIZWFkZXIoKTtcbiAgICAgICAgdmFyIGljb24gPSB0aGlzLm9wdGlvbnMuc2hvd0J1dHRvbkljb25zID8gdGhpcy5vcHRpb25zLmNhcmRWaWV3ID8gdGhpcy5vcHRpb25zLmljb25zLnRvZ2dsZU9uIDogdGhpcy5vcHRpb25zLmljb25zLnRvZ2dsZU9mZiA6ICcnO1xuICAgICAgICB2YXIgdGV4dCA9IHRoaXMub3B0aW9ucy5zaG93QnV0dG9uVGV4dCA/IHRoaXMub3B0aW9ucy5jYXJkVmlldyA/IHRoaXMub3B0aW9ucy5mb3JtYXRUb2dnbGVPZmYoKSA6IHRoaXMub3B0aW9ucy5mb3JtYXRUb2dnbGVPbigpIDogJyc7XG4gICAgICAgIHRoaXMuJHRvb2xiYXIuZmluZCgnYnV0dG9uW25hbWU9XCJ0b2dnbGVcIl0nKS5odG1sKFwiXCIuY29uY2F0KFV0aWxzLnNwcmludGYodGhpcy5jb25zdGFudHMuaHRtbC5pY29uLCB0aGlzLm9wdGlvbnMuaWNvbnNQcmVmaXgsIGljb24pLCBcIiBcIikuY29uY2F0KHRleHQpKTtcbiAgICAgICAgdGhpcy5pbml0Qm9keSgpO1xuICAgICAgICB0aGlzLnRyaWdnZXIoJ3RvZ2dsZScsIHRoaXMub3B0aW9ucy5jYXJkVmlldyk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInJlc2V0U2VhcmNoXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gcmVzZXRTZWFyY2godGV4dCkge1xuICAgICAgICB2YXIgJHNlYXJjaCA9IFV0aWxzLmdldFNlYXJjaElucHV0KHRoaXMpO1xuICAgICAgICAkc2VhcmNoLnZhbCh0ZXh0IHx8ICcnKTtcbiAgICAgICAgdGhpcy5vblNlYXJjaCh7XG4gICAgICAgICAgY3VycmVudFRhcmdldDogJHNlYXJjaFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiZmlsdGVyQnlcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBmaWx0ZXJCeShjb2x1bW5zLCBvcHRpb25zKSB7XG4gICAgICAgIHRoaXMuZmlsdGVyT3B0aW9ucyA9IFV0aWxzLmlzRW1wdHlPYmplY3Qob3B0aW9ucykgPyB0aGlzLm9wdGlvbnMuZmlsdGVyT3B0aW9ucyA6ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5leHRlbmQodGhpcy5vcHRpb25zLmZpbHRlck9wdGlvbnMsIG9wdGlvbnMpO1xuICAgICAgICB0aGlzLmZpbHRlckNvbHVtbnMgPSBVdGlscy5pc0VtcHR5T2JqZWN0KGNvbHVtbnMpID8ge30gOiBjb2x1bW5zO1xuICAgICAgICB0aGlzLm9wdGlvbnMucGFnZU51bWJlciA9IDE7XG4gICAgICAgIHRoaXMuaW5pdFNlYXJjaCgpO1xuICAgICAgICB0aGlzLnVwZGF0ZVBhZ2luYXRpb24oKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwic2Nyb2xsVG9cIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBzY3JvbGxUbyhwYXJhbXMpIHtcbiAgICAgICAgdmFyIG9wdGlvbnMgPSB7XG4gICAgICAgICAgdW5pdDogJ3B4JyxcbiAgICAgICAgICB2YWx1ZTogMFxuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChfdHlwZW9mKHBhcmFtcykgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24ob3B0aW9ucywgcGFyYW1zKTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgcGFyYW1zID09PSAnc3RyaW5nJyAmJiBwYXJhbXMgPT09ICdib3R0b20nKSB7XG4gICAgICAgICAgb3B0aW9ucy52YWx1ZSA9IHRoaXMuJHRhYmxlQm9keVswXS5zY3JvbGxIZWlnaHQ7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHBhcmFtcyA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIHBhcmFtcyA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICBvcHRpb25zLnZhbHVlID0gcGFyYW1zO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHNjcm9sbFRvID0gb3B0aW9ucy52YWx1ZTtcblxuICAgICAgICBpZiAob3B0aW9ucy51bml0ID09PSAncm93cycpIHtcbiAgICAgICAgICBzY3JvbGxUbyA9IDA7XG4gICAgICAgICAgdGhpcy4kYm9keS5maW5kKFwiPiB0cjpsdChcIi5jb25jYXQob3B0aW9ucy52YWx1ZSwgXCIpXCIpKS5lYWNoKGZ1bmN0aW9uIChpLCBlbCkge1xuICAgICAgICAgICAgc2Nyb2xsVG8gKz0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKS5vdXRlckhlaWdodCh0cnVlKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuJHRhYmxlQm9keS5zY3JvbGxUb3Aoc2Nyb2xsVG8pO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJnZXRTY3JvbGxQb3NpdGlvblwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGdldFNjcm9sbFBvc2l0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy4kdGFibGVCb2R5LnNjcm9sbFRvcCgpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJzZWxlY3RQYWdlXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gc2VsZWN0UGFnZShwYWdlKSB7XG4gICAgICAgIGlmIChwYWdlID4gMCAmJiBwYWdlIDw9IHRoaXMub3B0aW9ucy50b3RhbFBhZ2VzKSB7XG4gICAgICAgICAgdGhpcy5vcHRpb25zLnBhZ2VOdW1iZXIgPSBwYWdlO1xuICAgICAgICAgIHRoaXMudXBkYXRlUGFnaW5hdGlvbigpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInByZXZQYWdlXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gcHJldlBhZ2UoKSB7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMucGFnZU51bWJlciA+IDEpIHtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMucGFnZU51bWJlci0tO1xuICAgICAgICAgIHRoaXMudXBkYXRlUGFnaW5hdGlvbigpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcIm5leHRQYWdlXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gbmV4dFBhZ2UoKSB7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMucGFnZU51bWJlciA8IHRoaXMub3B0aW9ucy50b3RhbFBhZ2VzKSB7XG4gICAgICAgICAgdGhpcy5vcHRpb25zLnBhZ2VOdW1iZXIrKztcbiAgICAgICAgICB0aGlzLnVwZGF0ZVBhZ2luYXRpb24oKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJ0b2dnbGVEZXRhaWxWaWV3XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdG9nZ2xlRGV0YWlsVmlldyhpbmRleCwgX2NvbHVtbkRldGFpbEZvcm1hdHRlcikge1xuICAgICAgICB2YXIgJHRyID0gdGhpcy4kYm9keS5maW5kKFV0aWxzLnNwcmludGYoJz4gdHJbZGF0YS1pbmRleD1cIiVzXCJdJywgaW5kZXgpKTtcblxuICAgICAgICBpZiAoJHRyLm5leHQoKS5pcygndHIuZGV0YWlsLXZpZXcnKSkge1xuICAgICAgICAgIHRoaXMuY29sbGFwc2VSb3coaW5kZXgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuZXhwYW5kUm93KGluZGV4LCBfY29sdW1uRGV0YWlsRm9ybWF0dGVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucmVzZXRWaWV3KCk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImV4cGFuZFJvd1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGV4cGFuZFJvdyhpbmRleCwgX2NvbHVtbkRldGFpbEZvcm1hdHRlcikge1xuICAgICAgICB2YXIgcm93ID0gdGhpcy5kYXRhW2luZGV4XTtcbiAgICAgICAgdmFyICR0ciA9IHRoaXMuJGJvZHkuZmluZChVdGlscy5zcHJpbnRmKCc+IHRyW2RhdGEtaW5kZXg9XCIlc1wiXVtkYXRhLWhhcy1kZXRhaWwtdmlld10nLCBpbmRleCkpO1xuXG4gICAgICAgIGlmICgkdHIubmV4dCgpLmlzKCd0ci5kZXRhaWwtdmlldycpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5kZXRhaWxWaWV3SWNvbikge1xuICAgICAgICAgICR0ci5maW5kKCdhLmRldGFpbC1pY29uJykuaHRtbChVdGlscy5zcHJpbnRmKHRoaXMuY29uc3RhbnRzLmh0bWwuaWNvbiwgdGhpcy5vcHRpb25zLmljb25zUHJlZml4LCB0aGlzLm9wdGlvbnMuaWNvbnMuZGV0YWlsQ2xvc2UpKTtcbiAgICAgICAgfVxuXG4gICAgICAgICR0ci5hZnRlcihVdGlscy5zcHJpbnRmKCc8dHIgY2xhc3M9XCJkZXRhaWwtdmlld1wiPjx0ZCBjb2xzcGFuPVwiJXNcIj48L3RkPjwvdHI+JywgJHRyLmNoaWxkcmVuKCd0ZCcpLmxlbmd0aCkpO1xuICAgICAgICB2YXIgJGVsZW1lbnQgPSAkdHIubmV4dCgpLmZpbmQoJ3RkJyk7XG4gICAgICAgIHZhciBkZXRhaWxGb3JtYXR0ZXIgPSBfY29sdW1uRGV0YWlsRm9ybWF0dGVyIHx8IHRoaXMub3B0aW9ucy5kZXRhaWxGb3JtYXR0ZXI7XG4gICAgICAgIHZhciBjb250ZW50ID0gVXRpbHMuY2FsY3VsYXRlT2JqZWN0VmFsdWUodGhpcy5vcHRpb25zLCBkZXRhaWxGb3JtYXR0ZXIsIFtpbmRleCwgcm93LCAkZWxlbWVudF0sICcnKTtcblxuICAgICAgICBpZiAoJGVsZW1lbnQubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgJGVsZW1lbnQuYXBwZW5kKGNvbnRlbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy50cmlnZ2VyKCdleHBhbmQtcm93JywgaW5kZXgsIHJvdywgJGVsZW1lbnQpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJleHBhbmRSb3dCeVVuaXF1ZUlkXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gZXhwYW5kUm93QnlVbmlxdWVJZCh1bmlxdWVJZCkge1xuICAgICAgICB2YXIgcm93ID0gdGhpcy5nZXRSb3dCeVVuaXF1ZUlkKHVuaXF1ZUlkKTtcblxuICAgICAgICBpZiAoIXJvdykge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZXhwYW5kUm93KHRoaXMuZGF0YS5pbmRleE9mKHJvdykpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJjb2xsYXBzZVJvd1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGNvbGxhcHNlUm93KGluZGV4KSB7XG4gICAgICAgIHZhciByb3cgPSB0aGlzLmRhdGFbaW5kZXhdO1xuICAgICAgICB2YXIgJHRyID0gdGhpcy4kYm9keS5maW5kKFV0aWxzLnNwcmludGYoJz4gdHJbZGF0YS1pbmRleD1cIiVzXCJdW2RhdGEtaGFzLWRldGFpbC12aWV3XScsIGluZGV4KSk7XG5cbiAgICAgICAgaWYgKCEkdHIubmV4dCgpLmlzKCd0ci5kZXRhaWwtdmlldycpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5kZXRhaWxWaWV3SWNvbikge1xuICAgICAgICAgICR0ci5maW5kKCdhLmRldGFpbC1pY29uJykuaHRtbChVdGlscy5zcHJpbnRmKHRoaXMuY29uc3RhbnRzLmh0bWwuaWNvbiwgdGhpcy5vcHRpb25zLmljb25zUHJlZml4LCB0aGlzLm9wdGlvbnMuaWNvbnMuZGV0YWlsT3BlbikpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy50cmlnZ2VyKCdjb2xsYXBzZS1yb3cnLCBpbmRleCwgcm93LCAkdHIubmV4dCgpKTtcbiAgICAgICAgJHRyLm5leHQoKS5yZW1vdmUoKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiY29sbGFwc2VSb3dCeVVuaXF1ZUlkXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gY29sbGFwc2VSb3dCeVVuaXF1ZUlkKHVuaXF1ZUlkKSB7XG4gICAgICAgIHZhciByb3cgPSB0aGlzLmdldFJvd0J5VW5pcXVlSWQodW5pcXVlSWQpO1xuXG4gICAgICAgIGlmICghcm93KSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5jb2xsYXBzZVJvdyh0aGlzLmRhdGEuaW5kZXhPZihyb3cpKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiZXhwYW5kQWxsUm93c1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGV4cGFuZEFsbFJvd3MoKSB7XG4gICAgICAgIHZhciB0cnMgPSB0aGlzLiRib2R5LmZpbmQoJz4gdHJbZGF0YS1pbmRleF1bZGF0YS1oYXMtZGV0YWlsLXZpZXddJyk7XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0cnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICB0aGlzLmV4cGFuZFJvdygkX19kZWZhdWx0WydkZWZhdWx0J10odHJzW2ldKS5kYXRhKCdpbmRleCcpKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJjb2xsYXBzZUFsbFJvd3NcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBjb2xsYXBzZUFsbFJvd3MoKSB7XG4gICAgICAgIHZhciB0cnMgPSB0aGlzLiRib2R5LmZpbmQoJz4gdHJbZGF0YS1pbmRleF1bZGF0YS1oYXMtZGV0YWlsLXZpZXddJyk7XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0cnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICB0aGlzLmNvbGxhcHNlUm93KCRfX2RlZmF1bHRbJ2RlZmF1bHQnXSh0cnNbaV0pLmRhdGEoJ2luZGV4JykpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInVwZGF0ZUNvbHVtblRpdGxlXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdXBkYXRlQ29sdW1uVGl0bGUocGFyYW1zKSB7XG4gICAgICAgIGlmICghcGFyYW1zLmhhc093blByb3BlcnR5KCdmaWVsZCcpIHx8ICFwYXJhbXMuaGFzT3duUHJvcGVydHkoJ3RpdGxlJykpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmNvbHVtbnNbdGhpcy5maWVsZHNDb2x1bW5zSW5kZXhbcGFyYW1zLmZpZWxkXV0udGl0bGUgPSB0aGlzLm9wdGlvbnMuZXNjYXBlID8gVXRpbHMuZXNjYXBlSFRNTChwYXJhbXMudGl0bGUpIDogcGFyYW1zLnRpdGxlO1xuXG4gICAgICAgIGlmICh0aGlzLmNvbHVtbnNbdGhpcy5maWVsZHNDb2x1bW5zSW5kZXhbcGFyYW1zLmZpZWxkXV0udmlzaWJsZSkge1xuICAgICAgICAgIHRoaXMuJGhlYWRlci5maW5kKCd0aFtkYXRhLWZpZWxkXScpLmVhY2goZnVuY3Rpb24gKGksIGVsKSB7XG4gICAgICAgICAgICBpZiAoJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKS5kYXRhKCdmaWVsZCcpID09PSBwYXJhbXMuZmllbGQpIHtcbiAgICAgICAgICAgICAgJF9fZGVmYXVsdFsnZGVmYXVsdCddKCRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlbCkuZmluZCgnLnRoLWlubmVyJylbMF0pLnRleHQocGFyYW1zLnRpdGxlKTtcbiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHRoaXMucmVzZXRWaWV3KCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwidXBkYXRlRm9ybWF0VGV4dFwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHVwZGF0ZUZvcm1hdFRleHQoZm9ybWF0TmFtZSwgdGV4dCkge1xuICAgICAgICBpZiAoIS9eZm9ybWF0Ly50ZXN0KGZvcm1hdE5hbWUpIHx8ICF0aGlzLm9wdGlvbnNbZm9ybWF0TmFtZV0pIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIHRleHQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgdGhpcy5vcHRpb25zW2Zvcm1hdE5hbWVdID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRleHQ7XG4gICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGV4dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgIHRoaXMub3B0aW9uc1tmb3JtYXROYW1lXSA9IHRleHQ7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmluaXRUb29sYmFyKCk7XG4gICAgICAgIHRoaXMuaW5pdFBhZ2luYXRpb24oKTtcbiAgICAgICAgdGhpcy5pbml0Qm9keSgpO1xuICAgICAgfVxuICAgIH1dKTtcblxuICAgIHJldHVybiBCb290c3RyYXBUYWJsZTtcbiAgfSgpO1xuXG4gIEJvb3RzdHJhcFRhYmxlLlZFUlNJT04gPSBDb25zdGFudHMuVkVSU0lPTjtcbiAgQm9vdHN0cmFwVGFibGUuREVGQVVMVFMgPSBDb25zdGFudHMuREVGQVVMVFM7XG4gIEJvb3RzdHJhcFRhYmxlLkxPQ0FMRVMgPSBDb25zdGFudHMuTE9DQUxFUztcbiAgQm9vdHN0cmFwVGFibGUuQ09MVU1OX0RFRkFVTFRTID0gQ29uc3RhbnRzLkNPTFVNTl9ERUZBVUxUUztcbiAgQm9vdHN0cmFwVGFibGUuTUVUSE9EUyA9IENvbnN0YW50cy5NRVRIT0RTO1xuICBCb290c3RyYXBUYWJsZS5FVkVOVFMgPSBDb25zdGFudHMuRVZFTlRTOyAvLyBCT09UU1RSQVAgVEFCTEUgUExVR0lOIERFRklOSVRJT05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT1cblxuICAkX19kZWZhdWx0WydkZWZhdWx0J10uQm9vdHN0cmFwVGFibGUgPSBCb290c3RyYXBUYWJsZTtcblxuICAkX19kZWZhdWx0WydkZWZhdWx0J10uZm4uYm9vdHN0cmFwVGFibGUgPSBmdW5jdGlvbiAob3B0aW9uKSB7XG4gICAgZm9yICh2YXIgX2xlbjIgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4yID4gMSA/IF9sZW4yIC0gMSA6IDApLCBfa2V5NSA9IDE7IF9rZXk1IDwgX2xlbjI7IF9rZXk1KyspIHtcbiAgICAgIGFyZ3NbX2tleTUgLSAxXSA9IGFyZ3VtZW50c1tfa2V5NV07XG4gICAgfVxuXG4gICAgdmFyIHZhbHVlO1xuICAgIHRoaXMuZWFjaChmdW5jdGlvbiAoaSwgZWwpIHtcbiAgICAgIHZhciBkYXRhID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKS5kYXRhKCdib290c3RyYXAudGFibGUnKTtcbiAgICAgIHZhciBvcHRpb25zID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddLmV4dGVuZCh7fSwgQm9vdHN0cmFwVGFibGUuREVGQVVMVFMsICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlbCkuZGF0YSgpLCBfdHlwZW9mKG9wdGlvbikgPT09ICdvYmplY3QnICYmIG9wdGlvbik7XG5cbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9uID09PSAnc3RyaW5nJykge1xuICAgICAgICB2YXIgX2RhdGEyO1xuXG4gICAgICAgIGlmICghQ29uc3RhbnRzLk1FVEhPRFMuaW5jbHVkZXMob3B0aW9uKSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVua25vd24gbWV0aG9kOiBcIi5jb25jYXQob3B0aW9uKSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YWx1ZSA9IChfZGF0YTIgPSBkYXRhKVtvcHRpb25dLmFwcGx5KF9kYXRhMiwgYXJncyk7XG5cbiAgICAgICAgaWYgKG9wdGlvbiA9PT0gJ2Rlc3Ryb3knKSB7XG4gICAgICAgICAgJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKS5yZW1vdmVEYXRhKCdib290c3RyYXAudGFibGUnKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgZGF0YSA9IG5ldyAkX19kZWZhdWx0WydkZWZhdWx0J10uQm9vdHN0cmFwVGFibGUoZWwsIG9wdGlvbnMpO1xuICAgICAgICAkX19kZWZhdWx0WydkZWZhdWx0J10oZWwpLmRhdGEoJ2Jvb3RzdHJhcC50YWJsZScsIGRhdGEpO1xuICAgICAgICBkYXRhLmluaXQoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJyA/IHRoaXMgOiB2YWx1ZTtcbiAgfTtcblxuICAkX19kZWZhdWx0WydkZWZhdWx0J10uZm4uYm9vdHN0cmFwVGFibGUuQ29uc3RydWN0b3IgPSBCb290c3RyYXBUYWJsZTtcbiAgJF9fZGVmYXVsdFsnZGVmYXVsdCddLmZuLmJvb3RzdHJhcFRhYmxlLnRoZW1lID0gQ29uc3RhbnRzLlRIRU1FO1xuICAkX19kZWZhdWx0WydkZWZhdWx0J10uZm4uYm9vdHN0cmFwVGFibGUuVkVSU0lPTiA9IENvbnN0YW50cy5WRVJTSU9OO1xuICAkX19kZWZhdWx0WydkZWZhdWx0J10uZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMgPSBCb290c3RyYXBUYWJsZS5ERUZBVUxUUztcbiAgJF9fZGVmYXVsdFsnZGVmYXVsdCddLmZuLmJvb3RzdHJhcFRhYmxlLmNvbHVtbkRlZmF1bHRzID0gQm9vdHN0cmFwVGFibGUuQ09MVU1OX0RFRkFVTFRTO1xuICAkX19kZWZhdWx0WydkZWZhdWx0J10uZm4uYm9vdHN0cmFwVGFibGUuZXZlbnRzID0gQm9vdHN0cmFwVGFibGUuRVZFTlRTO1xuICAkX19kZWZhdWx0WydkZWZhdWx0J10uZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcyA9IEJvb3RzdHJhcFRhYmxlLkxPQ0FMRVM7XG4gICRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5mbi5ib290c3RyYXBUYWJsZS5tZXRob2RzID0gQm9vdHN0cmFwVGFibGUuTUVUSE9EUztcbiAgJF9fZGVmYXVsdFsnZGVmYXVsdCddLmZuLmJvb3RzdHJhcFRhYmxlLnV0aWxzID0gVXRpbHM7IC8vIEJPT1RTVFJBUCBUQUJMRSBJTklUXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgJF9fZGVmYXVsdFsnZGVmYXVsdCddKGZ1bmN0aW9uICgpIHtcbiAgICAkX19kZWZhdWx0WydkZWZhdWx0J10oJ1tkYXRhLXRvZ2dsZT1cInRhYmxlXCJdJykuYm9vdHN0cmFwVGFibGUoKTtcbiAgfSk7XG5cbiAgcmV0dXJuIEJvb3RzdHJhcFRhYmxlO1xuXG59KSkpO1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIHRvT2JqZWN0ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3RvLW9iamVjdCcpO1xudmFyIHRvQWJzb2x1dGVJbmRleCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy90by1hYnNvbHV0ZS1pbmRleCcpO1xudmFyIHRvTGVuZ3RoID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3RvLWxlbmd0aCcpO1xuXG4vLyBgQXJyYXkucHJvdG90eXBlLmZpbGxgIG1ldGhvZCBpbXBsZW1lbnRhdGlvblxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUuZmlsbFxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBmaWxsKHZhbHVlIC8qICwgc3RhcnQgPSAwLCBlbmQgPSBAbGVuZ3RoICovKSB7XG4gIHZhciBPID0gdG9PYmplY3QodGhpcyk7XG4gIHZhciBsZW5ndGggPSB0b0xlbmd0aChPLmxlbmd0aCk7XG4gIHZhciBhcmd1bWVudHNMZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoO1xuICB2YXIgaW5kZXggPSB0b0Fic29sdXRlSW5kZXgoYXJndW1lbnRzTGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCwgbGVuZ3RoKTtcbiAgdmFyIGVuZCA9IGFyZ3VtZW50c0xlbmd0aCA+IDIgPyBhcmd1bWVudHNbMl0gOiB1bmRlZmluZWQ7XG4gIHZhciBlbmRQb3MgPSBlbmQgPT09IHVuZGVmaW5lZCA/IGxlbmd0aCA6IHRvQWJzb2x1dGVJbmRleChlbmQsIGxlbmd0aCk7XG4gIHdoaWxlIChlbmRQb3MgPiBpbmRleCkgT1tpbmRleCsrXSA9IHZhbHVlO1xuICByZXR1cm4gTztcbn07XG4iLCJ2YXIgYUZ1bmN0aW9uID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2EtZnVuY3Rpb24nKTtcbnZhciB0b09iamVjdCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy90by1vYmplY3QnKTtcbnZhciBJbmRleGVkT2JqZWN0ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2luZGV4ZWQtb2JqZWN0Jyk7XG52YXIgdG9MZW5ndGggPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvdG8tbGVuZ3RoJyk7XG5cbi8vIGBBcnJheS5wcm90b3R5cGUueyByZWR1Y2UsIHJlZHVjZVJpZ2h0IH1gIG1ldGhvZHMgaW1wbGVtZW50YXRpb25cbnZhciBjcmVhdGVNZXRob2QgPSBmdW5jdGlvbiAoSVNfUklHSFQpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh0aGF0LCBjYWxsYmFja2ZuLCBhcmd1bWVudHNMZW5ndGgsIG1lbW8pIHtcbiAgICBhRnVuY3Rpb24oY2FsbGJhY2tmbik7XG4gICAgdmFyIE8gPSB0b09iamVjdCh0aGF0KTtcbiAgICB2YXIgc2VsZiA9IEluZGV4ZWRPYmplY3QoTyk7XG4gICAgdmFyIGxlbmd0aCA9IHRvTGVuZ3RoKE8ubGVuZ3RoKTtcbiAgICB2YXIgaW5kZXggPSBJU19SSUdIVCA/IGxlbmd0aCAtIDEgOiAwO1xuICAgIHZhciBpID0gSVNfUklHSFQgPyAtMSA6IDE7XG4gICAgaWYgKGFyZ3VtZW50c0xlbmd0aCA8IDIpIHdoaWxlICh0cnVlKSB7XG4gICAgICBpZiAoaW5kZXggaW4gc2VsZikge1xuICAgICAgICBtZW1vID0gc2VsZltpbmRleF07XG4gICAgICAgIGluZGV4ICs9IGk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgaW5kZXggKz0gaTtcbiAgICAgIGlmIChJU19SSUdIVCA/IGluZGV4IDwgMCA6IGxlbmd0aCA8PSBpbmRleCkge1xuICAgICAgICB0aHJvdyBUeXBlRXJyb3IoJ1JlZHVjZSBvZiBlbXB0eSBhcnJheSB3aXRoIG5vIGluaXRpYWwgdmFsdWUnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZm9yICg7SVNfUklHSFQgPyBpbmRleCA+PSAwIDogbGVuZ3RoID4gaW5kZXg7IGluZGV4ICs9IGkpIGlmIChpbmRleCBpbiBzZWxmKSB7XG4gICAgICBtZW1vID0gY2FsbGJhY2tmbihtZW1vLCBzZWxmW2luZGV4XSwgaW5kZXgsIE8pO1xuICAgIH1cbiAgICByZXR1cm4gbWVtbztcbiAgfTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAvLyBgQXJyYXkucHJvdG90eXBlLnJlZHVjZWAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLnJlZHVjZVxuICBsZWZ0OiBjcmVhdGVNZXRob2QoZmFsc2UpLFxuICAvLyBgQXJyYXkucHJvdG90eXBlLnJlZHVjZVJpZ2h0YCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUucmVkdWNlcmlnaHRcbiAgcmlnaHQ6IGNyZWF0ZU1ldGhvZCh0cnVlKVxufTtcbiIsInZhciBjbGFzc29mID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2NsYXNzb2YtcmF3Jyk7XG52YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2dsb2JhbCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNsYXNzb2YoZ2xvYmFsLnByb2Nlc3MpID09ICdwcm9jZXNzJztcbiIsInZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1vYmplY3QnKTtcbnZhciBzZXRQcm90b3R5cGVPZiA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9vYmplY3Qtc2V0LXByb3RvdHlwZS1vZicpO1xuXG4vLyBtYWtlcyBzdWJjbGFzc2luZyB3b3JrIGNvcnJlY3QgZm9yIHdyYXBwZWQgYnVpbHQtaW5zXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgkdGhpcywgZHVtbXksIFdyYXBwZXIpIHtcbiAgdmFyIE5ld1RhcmdldCwgTmV3VGFyZ2V0UHJvdG90eXBlO1xuICBpZiAoXG4gICAgLy8gaXQgY2FuIHdvcmsgb25seSB3aXRoIG5hdGl2ZSBgc2V0UHJvdG90eXBlT2ZgXG4gICAgc2V0UHJvdG90eXBlT2YgJiZcbiAgICAvLyB3ZSBoYXZlbid0IGNvbXBsZXRlbHkgY29ycmVjdCBwcmUtRVM2IHdheSBmb3IgZ2V0dGluZyBgbmV3LnRhcmdldGAsIHNvIHVzZSB0aGlzXG4gICAgdHlwZW9mIChOZXdUYXJnZXQgPSBkdW1teS5jb25zdHJ1Y3RvcikgPT0gJ2Z1bmN0aW9uJyAmJlxuICAgIE5ld1RhcmdldCAhPT0gV3JhcHBlciAmJlxuICAgIGlzT2JqZWN0KE5ld1RhcmdldFByb3RvdHlwZSA9IE5ld1RhcmdldC5wcm90b3R5cGUpICYmXG4gICAgTmV3VGFyZ2V0UHJvdG90eXBlICE9PSBXcmFwcGVyLnByb3RvdHlwZVxuICApIHNldFByb3RvdHlwZU9mKCR0aGlzLCBOZXdUYXJnZXRQcm90b3R5cGUpO1xuICByZXR1cm4gJHRoaXM7XG59O1xuIiwidmFyIGdsb2JhbCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9nbG9iYWwnKTtcbnZhciB0cmltID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3N0cmluZy10cmltJykudHJpbTtcbnZhciB3aGl0ZXNwYWNlcyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy93aGl0ZXNwYWNlcycpO1xuXG52YXIgJHBhcnNlRmxvYXQgPSBnbG9iYWwucGFyc2VGbG9hdDtcbnZhciBGT1JDRUQgPSAxIC8gJHBhcnNlRmxvYXQod2hpdGVzcGFjZXMgKyAnLTAnKSAhPT0gLUluZmluaXR5O1xuXG4vLyBgcGFyc2VGbG9hdGAgbWV0aG9kXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXBhcnNlZmxvYXQtc3RyaW5nXG5tb2R1bGUuZXhwb3J0cyA9IEZPUkNFRCA/IGZ1bmN0aW9uIHBhcnNlRmxvYXQoc3RyaW5nKSB7XG4gIHZhciB0cmltbWVkU3RyaW5nID0gdHJpbShTdHJpbmcoc3RyaW5nKSk7XG4gIHZhciByZXN1bHQgPSAkcGFyc2VGbG9hdCh0cmltbWVkU3RyaW5nKTtcbiAgcmV0dXJuIHJlc3VsdCA9PT0gMCAmJiB0cmltbWVkU3RyaW5nLmNoYXJBdCgwKSA9PSAnLScgPyAtMCA6IHJlc3VsdDtcbn0gOiAkcGFyc2VGbG9hdDtcbiIsIi8vIGBTYW1lVmFsdWVgIGFic3RyYWN0IG9wZXJhdGlvblxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1zYW1ldmFsdWVcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3QtaXMgLS0gc2FmZVxubW9kdWxlLmV4cG9ydHMgPSBPYmplY3QuaXMgfHwgZnVuY3Rpb24gaXMoeCwgeSkge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tc2VsZi1jb21wYXJlIC0tIE5hTiBjaGVja1xuICByZXR1cm4geCA9PT0geSA/IHggIT09IDAgfHwgMSAvIHggPT09IDEgLyB5IDogeCAhPSB4ICYmIHkgIT0geTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgZ2V0QnVpbHRJbiA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9nZXQtYnVpbHQtaW4nKTtcbnZhciBkZWZpbmVQcm9wZXJ0eU1vZHVsZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9vYmplY3QtZGVmaW5lLXByb3BlcnR5Jyk7XG52YXIgd2VsbEtub3duU3ltYm9sID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3dlbGwta25vd24tc3ltYm9sJyk7XG52YXIgREVTQ1JJUFRPUlMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZGVzY3JpcHRvcnMnKTtcblxudmFyIFNQRUNJRVMgPSB3ZWxsS25vd25TeW1ib2woJ3NwZWNpZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoQ09OU1RSVUNUT1JfTkFNRSkge1xuICB2YXIgQ29uc3RydWN0b3IgPSBnZXRCdWlsdEluKENPTlNUUlVDVE9SX05BTUUpO1xuICB2YXIgZGVmaW5lUHJvcGVydHkgPSBkZWZpbmVQcm9wZXJ0eU1vZHVsZS5mO1xuXG4gIGlmIChERVNDUklQVE9SUyAmJiBDb25zdHJ1Y3RvciAmJiAhQ29uc3RydWN0b3JbU1BFQ0lFU10pIHtcbiAgICBkZWZpbmVQcm9wZXJ0eShDb25zdHJ1Y3RvciwgU1BFQ0lFUywge1xuICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9XG4gICAgfSk7XG4gIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgdG9JbnRlZ2VyID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3RvLWludGVnZXInKTtcbnZhciByZXF1aXJlT2JqZWN0Q29lcmNpYmxlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3JlcXVpcmUtb2JqZWN0LWNvZXJjaWJsZScpO1xuXG4vLyBgU3RyaW5nLnByb3RvdHlwZS5yZXBlYXRgIG1ldGhvZCBpbXBsZW1lbnRhdGlvblxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1zdHJpbmcucHJvdG90eXBlLnJlcGVhdFxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiByZXBlYXQoY291bnQpIHtcbiAgdmFyIHN0ciA9IFN0cmluZyhyZXF1aXJlT2JqZWN0Q29lcmNpYmxlKHRoaXMpKTtcbiAgdmFyIHJlc3VsdCA9ICcnO1xuICB2YXIgbiA9IHRvSW50ZWdlcihjb3VudCk7XG4gIGlmIChuIDwgMCB8fCBuID09IEluZmluaXR5KSB0aHJvdyBSYW5nZUVycm9yKCdXcm9uZyBudW1iZXIgb2YgcmVwZXRpdGlvbnMnKTtcbiAgZm9yICg7biA+IDA7IChuID4+Pj0gMSkgJiYgKHN0ciArPSBzdHIpKSBpZiAobiAmIDEpIHJlc3VsdCArPSBzdHI7XG4gIHJldHVybiByZXN1bHQ7XG59O1xuIiwidmFyIGNsYXNzb2YgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvY2xhc3NvZi1yYXcnKTtcblxuLy8gYHRoaXNOdW1iZXJWYWx1ZWAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXRoaXNudW1iZXJ2YWx1ZVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPSAnbnVtYmVyJyAmJiBjbGFzc29mKHZhbHVlKSAhPSAnTnVtYmVyJykge1xuICAgIHRocm93IFR5cGVFcnJvcignSW5jb3JyZWN0IGludm9jYXRpb24nKTtcbiAgfVxuICByZXR1cm4gK3ZhbHVlO1xufTtcbiIsInZhciAkID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2V4cG9ydCcpO1xudmFyIGZpbGwgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvYXJyYXktZmlsbCcpO1xudmFyIGFkZFRvVW5zY29wYWJsZXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvYWRkLXRvLXVuc2NvcGFibGVzJyk7XG5cbi8vIGBBcnJheS5wcm90b3R5cGUuZmlsbGAgbWV0aG9kXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS5maWxsXG4kKHsgdGFyZ2V0OiAnQXJyYXknLCBwcm90bzogdHJ1ZSB9LCB7XG4gIGZpbGw6IGZpbGxcbn0pO1xuXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS1AQHVuc2NvcGFibGVzXG5hZGRUb1Vuc2NvcGFibGVzKCdmaWxsJyk7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgJCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9leHBvcnQnKTtcbnZhciAkZmluZCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9hcnJheS1pdGVyYXRpb24nKS5maW5kO1xudmFyIGFkZFRvVW5zY29wYWJsZXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvYWRkLXRvLXVuc2NvcGFibGVzJyk7XG5cbnZhciBGSU5EID0gJ2ZpbmQnO1xudmFyIFNLSVBTX0hPTEVTID0gdHJ1ZTtcblxuLy8gU2hvdWxkbid0IHNraXAgaG9sZXNcbmlmIChGSU5EIGluIFtdKSBBcnJheSgxKVtGSU5EXShmdW5jdGlvbiAoKSB7IFNLSVBTX0hPTEVTID0gZmFsc2U7IH0pO1xuXG4vLyBgQXJyYXkucHJvdG90eXBlLmZpbmRgIG1ldGhvZFxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUuZmluZFxuJCh7IHRhcmdldDogJ0FycmF5JywgcHJvdG86IHRydWUsIGZvcmNlZDogU0tJUFNfSE9MRVMgfSwge1xuICBmaW5kOiBmdW5jdGlvbiBmaW5kKGNhbGxiYWNrZm4gLyogLCB0aGF0ID0gdW5kZWZpbmVkICovKSB7XG4gICAgcmV0dXJuICRmaW5kKHRoaXMsIGNhbGxiYWNrZm4sIGFyZ3VtZW50cy5sZW5ndGggPiAxID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkKTtcbiAgfVxufSk7XG5cbi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLUBAdW5zY29wYWJsZXNcbmFkZFRvVW5zY29wYWJsZXMoRklORCk7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgJCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9leHBvcnQnKTtcbnZhciAkaW5jbHVkZXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvYXJyYXktaW5jbHVkZXMnKS5pbmNsdWRlcztcbnZhciBhZGRUb1Vuc2NvcGFibGVzID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2FkZC10by11bnNjb3BhYmxlcycpO1xuXG4vLyBgQXJyYXkucHJvdG90eXBlLmluY2x1ZGVzYCBtZXRob2Rcbi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLmluY2x1ZGVzXG4kKHsgdGFyZ2V0OiAnQXJyYXknLCBwcm90bzogdHJ1ZSB9LCB7XG4gIGluY2x1ZGVzOiBmdW5jdGlvbiBpbmNsdWRlcyhlbCAvKiAsIGZyb21JbmRleCA9IDAgKi8pIHtcbiAgICByZXR1cm4gJGluY2x1ZGVzKHRoaXMsIGVsLCBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCk7XG4gIH1cbn0pO1xuXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS1AQHVuc2NvcGFibGVzXG5hZGRUb1Vuc2NvcGFibGVzKCdpbmNsdWRlcycpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuLyogZXNsaW50LWRpc2FibGUgZXMvbm8tYXJyYXktcHJvdG90eXBlLWluZGV4b2YgLS0gcmVxdWlyZWQgZm9yIHRlc3RpbmcgKi9cbnZhciAkID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2V4cG9ydCcpO1xudmFyICRpbmRleE9mID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2FycmF5LWluY2x1ZGVzJykuaW5kZXhPZjtcbnZhciBhcnJheU1ldGhvZElzU3RyaWN0ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2FycmF5LW1ldGhvZC1pcy1zdHJpY3QnKTtcblxudmFyIG5hdGl2ZUluZGV4T2YgPSBbXS5pbmRleE9mO1xuXG52YXIgTkVHQVRJVkVfWkVSTyA9ICEhbmF0aXZlSW5kZXhPZiAmJiAxIC8gWzFdLmluZGV4T2YoMSwgLTApIDwgMDtcbnZhciBTVFJJQ1RfTUVUSE9EID0gYXJyYXlNZXRob2RJc1N0cmljdCgnaW5kZXhPZicpO1xuXG4vLyBgQXJyYXkucHJvdG90eXBlLmluZGV4T2ZgIG1ldGhvZFxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUuaW5kZXhvZlxuJCh7IHRhcmdldDogJ0FycmF5JywgcHJvdG86IHRydWUsIGZvcmNlZDogTkVHQVRJVkVfWkVSTyB8fCAhU1RSSUNUX01FVEhPRCB9LCB7XG4gIGluZGV4T2Y6IGZ1bmN0aW9uIGluZGV4T2Yoc2VhcmNoRWxlbWVudCAvKiAsIGZyb21JbmRleCA9IDAgKi8pIHtcbiAgICByZXR1cm4gTkVHQVRJVkVfWkVST1xuICAgICAgLy8gY29udmVydCAtMCB0byArMFxuICAgICAgPyBuYXRpdmVJbmRleE9mLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgMFxuICAgICAgOiAkaW5kZXhPZih0aGlzLCBzZWFyY2hFbGVtZW50LCBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCk7XG4gIH1cbn0pO1xuIiwidmFyICQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZXhwb3J0Jyk7XG52YXIgaXNBcnJheSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1hcnJheScpO1xuXG4vLyBgQXJyYXkuaXNBcnJheWAgbWV0aG9kXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LmlzYXJyYXlcbiQoeyB0YXJnZXQ6ICdBcnJheScsIHN0YXQ6IHRydWUgfSwge1xuICBpc0FycmF5OiBpc0FycmF5XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciAkID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2V4cG9ydCcpO1xudmFyICRyZWR1Y2UgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvYXJyYXktcmVkdWNlJykubGVmdDtcbnZhciBhcnJheU1ldGhvZElzU3RyaWN0ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2FycmF5LW1ldGhvZC1pcy1zdHJpY3QnKTtcbnZhciBDSFJPTUVfVkVSU0lPTiA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9lbmdpbmUtdjgtdmVyc2lvbicpO1xudmFyIElTX05PREUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZW5naW5lLWlzLW5vZGUnKTtcblxudmFyIFNUUklDVF9NRVRIT0QgPSBhcnJheU1ldGhvZElzU3RyaWN0KCdyZWR1Y2UnKTtcbi8vIENocm9tZSA4MC04MiBoYXMgYSBjcml0aWNhbCBidWdcbi8vIGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC9jaHJvbWl1bS9pc3N1ZXMvZGV0YWlsP2lkPTEwNDk5ODJcbnZhciBDSFJPTUVfQlVHID0gIUlTX05PREUgJiYgQ0hST01FX1ZFUlNJT04gPiA3OSAmJiBDSFJPTUVfVkVSU0lPTiA8IDgzO1xuXG4vLyBgQXJyYXkucHJvdG90eXBlLnJlZHVjZWAgbWV0aG9kXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS5yZWR1Y2VcbiQoeyB0YXJnZXQ6ICdBcnJheScsIHByb3RvOiB0cnVlLCBmb3JjZWQ6ICFTVFJJQ1RfTUVUSE9EIHx8IENIUk9NRV9CVUcgfSwge1xuICByZWR1Y2U6IGZ1bmN0aW9uIHJlZHVjZShjYWxsYmFja2ZuIC8qICwgaW5pdGlhbFZhbHVlICovKSB7XG4gICAgcmV0dXJuICRyZWR1Y2UodGhpcywgY2FsbGJhY2tmbiwgYXJndW1lbnRzLmxlbmd0aCwgYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQpO1xuICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciAkID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2V4cG9ydCcpO1xudmFyICRzb21lID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2FycmF5LWl0ZXJhdGlvbicpLnNvbWU7XG52YXIgYXJyYXlNZXRob2RJc1N0cmljdCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9hcnJheS1tZXRob2QtaXMtc3RyaWN0Jyk7XG5cbnZhciBTVFJJQ1RfTUVUSE9EID0gYXJyYXlNZXRob2RJc1N0cmljdCgnc29tZScpO1xuXG4vLyBgQXJyYXkucHJvdG90eXBlLnNvbWVgIG1ldGhvZFxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUuc29tZVxuJCh7IHRhcmdldDogJ0FycmF5JywgcHJvdG86IHRydWUsIGZvcmNlZDogIVNUUklDVF9NRVRIT0QgfSwge1xuICBzb21lOiBmdW5jdGlvbiBzb21lKGNhbGxiYWNrZm4gLyogLCB0aGlzQXJnICovKSB7XG4gICAgcmV0dXJuICRzb21lKHRoaXMsIGNhbGxiYWNrZm4sIGFyZ3VtZW50cy5sZW5ndGggPiAxID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkKTtcbiAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgJCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9leHBvcnQnKTtcbnZhciB0b0Fic29sdXRlSW5kZXggPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvdG8tYWJzb2x1dGUtaW5kZXgnKTtcbnZhciB0b0ludGVnZXIgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvdG8taW50ZWdlcicpO1xudmFyIHRvTGVuZ3RoID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3RvLWxlbmd0aCcpO1xudmFyIHRvT2JqZWN0ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3RvLW9iamVjdCcpO1xudmFyIGFycmF5U3BlY2llc0NyZWF0ZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9hcnJheS1zcGVjaWVzLWNyZWF0ZScpO1xudmFyIGNyZWF0ZVByb3BlcnR5ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2NyZWF0ZS1wcm9wZXJ0eScpO1xudmFyIGFycmF5TWV0aG9kSGFzU3BlY2llc1N1cHBvcnQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvYXJyYXktbWV0aG9kLWhhcy1zcGVjaWVzLXN1cHBvcnQnKTtcblxudmFyIEhBU19TUEVDSUVTX1NVUFBPUlQgPSBhcnJheU1ldGhvZEhhc1NwZWNpZXNTdXBwb3J0KCdzcGxpY2UnKTtcblxudmFyIG1heCA9IE1hdGgubWF4O1xudmFyIG1pbiA9IE1hdGgubWluO1xudmFyIE1BWF9TQUZFX0lOVEVHRVIgPSAweDFGRkZGRkZGRkZGRkZGO1xudmFyIE1BWElNVU1fQUxMT1dFRF9MRU5HVEhfRVhDRUVERUQgPSAnTWF4aW11bSBhbGxvd2VkIGxlbmd0aCBleGNlZWRlZCc7XG5cbi8vIGBBcnJheS5wcm90b3R5cGUuc3BsaWNlYCBtZXRob2Rcbi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLnNwbGljZVxuLy8gd2l0aCBhZGRpbmcgc3VwcG9ydCBvZiBAQHNwZWNpZXNcbiQoeyB0YXJnZXQ6ICdBcnJheScsIHByb3RvOiB0cnVlLCBmb3JjZWQ6ICFIQVNfU1BFQ0lFU19TVVBQT1JUIH0sIHtcbiAgc3BsaWNlOiBmdW5jdGlvbiBzcGxpY2Uoc3RhcnQsIGRlbGV0ZUNvdW50IC8qICwgLi4uaXRlbXMgKi8pIHtcbiAgICB2YXIgTyA9IHRvT2JqZWN0KHRoaXMpO1xuICAgIHZhciBsZW4gPSB0b0xlbmd0aChPLmxlbmd0aCk7XG4gICAgdmFyIGFjdHVhbFN0YXJ0ID0gdG9BYnNvbHV0ZUluZGV4KHN0YXJ0LCBsZW4pO1xuICAgIHZhciBhcmd1bWVudHNMZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgIHZhciBpbnNlcnRDb3VudCwgYWN0dWFsRGVsZXRlQ291bnQsIEEsIGssIGZyb20sIHRvO1xuICAgIGlmIChhcmd1bWVudHNMZW5ndGggPT09IDApIHtcbiAgICAgIGluc2VydENvdW50ID0gYWN0dWFsRGVsZXRlQ291bnQgPSAwO1xuICAgIH0gZWxzZSBpZiAoYXJndW1lbnRzTGVuZ3RoID09PSAxKSB7XG4gICAgICBpbnNlcnRDb3VudCA9IDA7XG4gICAgICBhY3R1YWxEZWxldGVDb3VudCA9IGxlbiAtIGFjdHVhbFN0YXJ0O1xuICAgIH0gZWxzZSB7XG4gICAgICBpbnNlcnRDb3VudCA9IGFyZ3VtZW50c0xlbmd0aCAtIDI7XG4gICAgICBhY3R1YWxEZWxldGVDb3VudCA9IG1pbihtYXgodG9JbnRlZ2VyKGRlbGV0ZUNvdW50KSwgMCksIGxlbiAtIGFjdHVhbFN0YXJ0KTtcbiAgICB9XG4gICAgaWYgKGxlbiArIGluc2VydENvdW50IC0gYWN0dWFsRGVsZXRlQ291bnQgPiBNQVhfU0FGRV9JTlRFR0VSKSB7XG4gICAgICB0aHJvdyBUeXBlRXJyb3IoTUFYSU1VTV9BTExPV0VEX0xFTkdUSF9FWENFRURFRCk7XG4gICAgfVxuICAgIEEgPSBhcnJheVNwZWNpZXNDcmVhdGUoTywgYWN0dWFsRGVsZXRlQ291bnQpO1xuICAgIGZvciAoayA9IDA7IGsgPCBhY3R1YWxEZWxldGVDb3VudDsgaysrKSB7XG4gICAgICBmcm9tID0gYWN0dWFsU3RhcnQgKyBrO1xuICAgICAgaWYgKGZyb20gaW4gTykgY3JlYXRlUHJvcGVydHkoQSwgaywgT1tmcm9tXSk7XG4gICAgfVxuICAgIEEubGVuZ3RoID0gYWN0dWFsRGVsZXRlQ291bnQ7XG4gICAgaWYgKGluc2VydENvdW50IDwgYWN0dWFsRGVsZXRlQ291bnQpIHtcbiAgICAgIGZvciAoayA9IGFjdHVhbFN0YXJ0OyBrIDwgbGVuIC0gYWN0dWFsRGVsZXRlQ291bnQ7IGsrKykge1xuICAgICAgICBmcm9tID0gayArIGFjdHVhbERlbGV0ZUNvdW50O1xuICAgICAgICB0byA9IGsgKyBpbnNlcnRDb3VudDtcbiAgICAgICAgaWYgKGZyb20gaW4gTykgT1t0b10gPSBPW2Zyb21dO1xuICAgICAgICBlbHNlIGRlbGV0ZSBPW3RvXTtcbiAgICAgIH1cbiAgICAgIGZvciAoayA9IGxlbjsgayA+IGxlbiAtIGFjdHVhbERlbGV0ZUNvdW50ICsgaW5zZXJ0Q291bnQ7IGstLSkgZGVsZXRlIE9bayAtIDFdO1xuICAgIH0gZWxzZSBpZiAoaW5zZXJ0Q291bnQgPiBhY3R1YWxEZWxldGVDb3VudCkge1xuICAgICAgZm9yIChrID0gbGVuIC0gYWN0dWFsRGVsZXRlQ291bnQ7IGsgPiBhY3R1YWxTdGFydDsgay0tKSB7XG4gICAgICAgIGZyb20gPSBrICsgYWN0dWFsRGVsZXRlQ291bnQgLSAxO1xuICAgICAgICB0byA9IGsgKyBpbnNlcnRDb3VudCAtIDE7XG4gICAgICAgIGlmIChmcm9tIGluIE8pIE9bdG9dID0gT1tmcm9tXTtcbiAgICAgICAgZWxzZSBkZWxldGUgT1t0b107XG4gICAgICB9XG4gICAgfVxuICAgIGZvciAoayA9IDA7IGsgPCBpbnNlcnRDb3VudDsgaysrKSB7XG4gICAgICBPW2sgKyBhY3R1YWxTdGFydF0gPSBhcmd1bWVudHNbayArIDJdO1xuICAgIH1cbiAgICBPLmxlbmd0aCA9IGxlbiAtIGFjdHVhbERlbGV0ZUNvdW50ICsgaW5zZXJ0Q291bnQ7XG4gICAgcmV0dXJuIEE7XG4gIH1cbn0pO1xuIiwidmFyICQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZXhwb3J0Jyk7XG52YXIgYmluZCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9mdW5jdGlvbi1iaW5kJyk7XG5cbi8vIGBGdW5jdGlvbi5wcm90b3R5cGUuYmluZGAgbWV0aG9kXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kXG4kKHsgdGFyZ2V0OiAnRnVuY3Rpb24nLCBwcm90bzogdHJ1ZSB9LCB7XG4gIGJpbmQ6IGJpbmRcbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIERFU0NSSVBUT1JTID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2Rlc2NyaXB0b3JzJyk7XG52YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2dsb2JhbCcpO1xudmFyIGlzRm9yY2VkID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2lzLWZvcmNlZCcpO1xudmFyIHJlZGVmaW5lID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3JlZGVmaW5lJyk7XG52YXIgaGFzID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2hhcycpO1xudmFyIGNsYXNzb2YgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvY2xhc3NvZi1yYXcnKTtcbnZhciBpbmhlcml0SWZSZXF1aXJlZCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pbmhlcml0LWlmLXJlcXVpcmVkJyk7XG52YXIgdG9QcmltaXRpdmUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvdG8tcHJpbWl0aXZlJyk7XG52YXIgZmFpbHMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZmFpbHMnKTtcbnZhciBjcmVhdGUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvb2JqZWN0LWNyZWF0ZScpO1xudmFyIGdldE93blByb3BlcnR5TmFtZXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvb2JqZWN0LWdldC1vd24tcHJvcGVydHktbmFtZXMnKS5mO1xudmFyIGdldE93blByb3BlcnR5RGVzY3JpcHRvciA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9vYmplY3QtZ2V0LW93bi1wcm9wZXJ0eS1kZXNjcmlwdG9yJykuZjtcbnZhciBkZWZpbmVQcm9wZXJ0eSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9vYmplY3QtZGVmaW5lLXByb3BlcnR5JykuZjtcbnZhciB0cmltID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3N0cmluZy10cmltJykudHJpbTtcblxudmFyIE5VTUJFUiA9ICdOdW1iZXInO1xudmFyIE5hdGl2ZU51bWJlciA9IGdsb2JhbFtOVU1CRVJdO1xudmFyIE51bWJlclByb3RvdHlwZSA9IE5hdGl2ZU51bWJlci5wcm90b3R5cGU7XG5cbi8vIE9wZXJhIH4xMiBoYXMgYnJva2VuIE9iamVjdCN0b1N0cmluZ1xudmFyIEJST0tFTl9DTEFTU09GID0gY2xhc3NvZihjcmVhdGUoTnVtYmVyUHJvdG90eXBlKSkgPT0gTlVNQkVSO1xuXG4vLyBgVG9OdW1iZXJgIGFic3RyYWN0IG9wZXJhdGlvblxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy10b251bWJlclxudmFyIHRvTnVtYmVyID0gZnVuY3Rpb24gKGFyZ3VtZW50KSB7XG4gIHZhciBpdCA9IHRvUHJpbWl0aXZlKGFyZ3VtZW50LCBmYWxzZSk7XG4gIHZhciBmaXJzdCwgdGhpcmQsIHJhZGl4LCBtYXhDb2RlLCBkaWdpdHMsIGxlbmd0aCwgaW5kZXgsIGNvZGU7XG4gIGlmICh0eXBlb2YgaXQgPT0gJ3N0cmluZycgJiYgaXQubGVuZ3RoID4gMikge1xuICAgIGl0ID0gdHJpbShpdCk7XG4gICAgZmlyc3QgPSBpdC5jaGFyQ29kZUF0KDApO1xuICAgIGlmIChmaXJzdCA9PT0gNDMgfHwgZmlyc3QgPT09IDQ1KSB7XG4gICAgICB0aGlyZCA9IGl0LmNoYXJDb2RlQXQoMik7XG4gICAgICBpZiAodGhpcmQgPT09IDg4IHx8IHRoaXJkID09PSAxMjApIHJldHVybiBOYU47IC8vIE51bWJlcignKzB4MScpIHNob3VsZCBiZSBOYU4sIG9sZCBWOCBmaXhcbiAgICB9IGVsc2UgaWYgKGZpcnN0ID09PSA0OCkge1xuICAgICAgc3dpdGNoIChpdC5jaGFyQ29kZUF0KDEpKSB7XG4gICAgICAgIGNhc2UgNjY6IGNhc2UgOTg6IHJhZGl4ID0gMjsgbWF4Q29kZSA9IDQ5OyBicmVhazsgLy8gZmFzdCBlcXVhbCBvZiAvXjBiWzAxXSskL2lcbiAgICAgICAgY2FzZSA3OTogY2FzZSAxMTE6IHJhZGl4ID0gODsgbWF4Q29kZSA9IDU1OyBicmVhazsgLy8gZmFzdCBlcXVhbCBvZiAvXjBvWzAtN10rJC9pXG4gICAgICAgIGRlZmF1bHQ6IHJldHVybiAraXQ7XG4gICAgICB9XG4gICAgICBkaWdpdHMgPSBpdC5zbGljZSgyKTtcbiAgICAgIGxlbmd0aCA9IGRpZ2l0cy5sZW5ndGg7XG4gICAgICBmb3IgKGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHtcbiAgICAgICAgY29kZSA9IGRpZ2l0cy5jaGFyQ29kZUF0KGluZGV4KTtcbiAgICAgICAgLy8gcGFyc2VJbnQgcGFyc2VzIGEgc3RyaW5nIHRvIGEgZmlyc3QgdW5hdmFpbGFibGUgc3ltYm9sXG4gICAgICAgIC8vIGJ1dCBUb051bWJlciBzaG91bGQgcmV0dXJuIE5hTiBpZiBhIHN0cmluZyBjb250YWlucyB1bmF2YWlsYWJsZSBzeW1ib2xzXG4gICAgICAgIGlmIChjb2RlIDwgNDggfHwgY29kZSA+IG1heENvZGUpIHJldHVybiBOYU47XG4gICAgICB9IHJldHVybiBwYXJzZUludChkaWdpdHMsIHJhZGl4KTtcbiAgICB9XG4gIH0gcmV0dXJuICtpdDtcbn07XG5cbi8vIGBOdW1iZXJgIGNvbnN0cnVjdG9yXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW51bWJlci1jb25zdHJ1Y3RvclxuaWYgKGlzRm9yY2VkKE5VTUJFUiwgIU5hdGl2ZU51bWJlcignIDBvMScpIHx8ICFOYXRpdmVOdW1iZXIoJzBiMScpIHx8IE5hdGl2ZU51bWJlcignKzB4MScpKSkge1xuICB2YXIgTnVtYmVyV3JhcHBlciA9IGZ1bmN0aW9uIE51bWJlcih2YWx1ZSkge1xuICAgIHZhciBpdCA9IGFyZ3VtZW50cy5sZW5ndGggPCAxID8gMCA6IHZhbHVlO1xuICAgIHZhciBkdW1teSA9IHRoaXM7XG4gICAgcmV0dXJuIGR1bW15IGluc3RhbmNlb2YgTnVtYmVyV3JhcHBlclxuICAgICAgLy8gY2hlY2sgb24gMS4uY29uc3RydWN0b3IoZm9vKSBjYXNlXG4gICAgICAmJiAoQlJPS0VOX0NMQVNTT0YgPyBmYWlscyhmdW5jdGlvbiAoKSB7IE51bWJlclByb3RvdHlwZS52YWx1ZU9mLmNhbGwoZHVtbXkpOyB9KSA6IGNsYXNzb2YoZHVtbXkpICE9IE5VTUJFUilcbiAgICAgICAgPyBpbmhlcml0SWZSZXF1aXJlZChuZXcgTmF0aXZlTnVtYmVyKHRvTnVtYmVyKGl0KSksIGR1bW15LCBOdW1iZXJXcmFwcGVyKSA6IHRvTnVtYmVyKGl0KTtcbiAgfTtcbiAgZm9yICh2YXIga2V5cyA9IERFU0NSSVBUT1JTID8gZ2V0T3duUHJvcGVydHlOYW1lcyhOYXRpdmVOdW1iZXIpIDogKFxuICAgIC8vIEVTMzpcbiAgICAnTUFYX1ZBTFVFLE1JTl9WQUxVRSxOYU4sTkVHQVRJVkVfSU5GSU5JVFksUE9TSVRJVkVfSU5GSU5JVFksJyArXG4gICAgLy8gRVMyMDE1IChpbiBjYXNlLCBpZiBtb2R1bGVzIHdpdGggRVMyMDE1IE51bWJlciBzdGF0aWNzIHJlcXVpcmVkIGJlZm9yZSk6XG4gICAgJ0VQU0lMT04saXNGaW5pdGUsaXNJbnRlZ2VyLGlzTmFOLGlzU2FmZUludGVnZXIsTUFYX1NBRkVfSU5URUdFUiwnICtcbiAgICAnTUlOX1NBRkVfSU5URUdFUixwYXJzZUZsb2F0LHBhcnNlSW50LGlzSW50ZWdlciwnICtcbiAgICAvLyBFU05leHRcbiAgICAnZnJvbVN0cmluZyxyYW5nZSdcbiAgKS5zcGxpdCgnLCcpLCBqID0gMCwga2V5OyBrZXlzLmxlbmd0aCA+IGo7IGorKykge1xuICAgIGlmIChoYXMoTmF0aXZlTnVtYmVyLCBrZXkgPSBrZXlzW2pdKSAmJiAhaGFzKE51bWJlcldyYXBwZXIsIGtleSkpIHtcbiAgICAgIGRlZmluZVByb3BlcnR5KE51bWJlcldyYXBwZXIsIGtleSwgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKE5hdGl2ZU51bWJlciwga2V5KSk7XG4gICAgfVxuICB9XG4gIE51bWJlcldyYXBwZXIucHJvdG90eXBlID0gTnVtYmVyUHJvdG90eXBlO1xuICBOdW1iZXJQcm90b3R5cGUuY29uc3RydWN0b3IgPSBOdW1iZXJXcmFwcGVyO1xuICByZWRlZmluZShnbG9iYWwsIE5VTUJFUiwgTnVtYmVyV3JhcHBlcik7XG59XG4iLCIndXNlIHN0cmljdCc7XG52YXIgJCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9leHBvcnQnKTtcbnZhciB0b0ludGVnZXIgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvdG8taW50ZWdlcicpO1xudmFyIHRoaXNOdW1iZXJWYWx1ZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy90aGlzLW51bWJlci12YWx1ZScpO1xudmFyIHJlcGVhdCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9zdHJpbmctcmVwZWF0Jyk7XG52YXIgZmFpbHMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZmFpbHMnKTtcblxudmFyIG5hdGl2ZVRvRml4ZWQgPSAxLjAudG9GaXhlZDtcbnZhciBmbG9vciA9IE1hdGguZmxvb3I7XG5cbnZhciBwb3cgPSBmdW5jdGlvbiAoeCwgbiwgYWNjKSB7XG4gIHJldHVybiBuID09PSAwID8gYWNjIDogbiAlIDIgPT09IDEgPyBwb3coeCwgbiAtIDEsIGFjYyAqIHgpIDogcG93KHggKiB4LCBuIC8gMiwgYWNjKTtcbn07XG5cbnZhciBsb2cgPSBmdW5jdGlvbiAoeCkge1xuICB2YXIgbiA9IDA7XG4gIHZhciB4MiA9IHg7XG4gIHdoaWxlICh4MiA+PSA0MDk2KSB7XG4gICAgbiArPSAxMjtcbiAgICB4MiAvPSA0MDk2O1xuICB9XG4gIHdoaWxlICh4MiA+PSAyKSB7XG4gICAgbiArPSAxO1xuICAgIHgyIC89IDI7XG4gIH0gcmV0dXJuIG47XG59O1xuXG52YXIgbXVsdGlwbHkgPSBmdW5jdGlvbiAoZGF0YSwgbiwgYykge1xuICB2YXIgaW5kZXggPSAtMTtcbiAgdmFyIGMyID0gYztcbiAgd2hpbGUgKCsraW5kZXggPCA2KSB7XG4gICAgYzIgKz0gbiAqIGRhdGFbaW5kZXhdO1xuICAgIGRhdGFbaW5kZXhdID0gYzIgJSAxZTc7XG4gICAgYzIgPSBmbG9vcihjMiAvIDFlNyk7XG4gIH1cbn07XG5cbnZhciBkaXZpZGUgPSBmdW5jdGlvbiAoZGF0YSwgbikge1xuICB2YXIgaW5kZXggPSA2O1xuICB2YXIgYyA9IDA7XG4gIHdoaWxlICgtLWluZGV4ID49IDApIHtcbiAgICBjICs9IGRhdGFbaW5kZXhdO1xuICAgIGRhdGFbaW5kZXhdID0gZmxvb3IoYyAvIG4pO1xuICAgIGMgPSAoYyAlIG4pICogMWU3O1xuICB9XG59O1xuXG52YXIgZGF0YVRvU3RyaW5nID0gZnVuY3Rpb24gKGRhdGEpIHtcbiAgdmFyIGluZGV4ID0gNjtcbiAgdmFyIHMgPSAnJztcbiAgd2hpbGUgKC0taW5kZXggPj0gMCkge1xuICAgIGlmIChzICE9PSAnJyB8fCBpbmRleCA9PT0gMCB8fCBkYXRhW2luZGV4XSAhPT0gMCkge1xuICAgICAgdmFyIHQgPSBTdHJpbmcoZGF0YVtpbmRleF0pO1xuICAgICAgcyA9IHMgPT09ICcnID8gdCA6IHMgKyByZXBlYXQuY2FsbCgnMCcsIDcgLSB0Lmxlbmd0aCkgKyB0O1xuICAgIH1cbiAgfSByZXR1cm4gcztcbn07XG5cbnZhciBGT1JDRUQgPSBuYXRpdmVUb0ZpeGVkICYmIChcbiAgMC4wMDAwOC50b0ZpeGVkKDMpICE9PSAnMC4wMDAnIHx8XG4gIDAuOS50b0ZpeGVkKDApICE9PSAnMScgfHxcbiAgMS4yNTUudG9GaXhlZCgyKSAhPT0gJzEuMjUnIHx8XG4gIDEwMDAwMDAwMDAwMDAwMDAxMjguMC50b0ZpeGVkKDApICE9PSAnMTAwMDAwMDAwMDAwMDAwMDEyOCdcbikgfHwgIWZhaWxzKGZ1bmN0aW9uICgpIHtcbiAgLy8gVjggfiBBbmRyb2lkIDQuMy1cbiAgbmF0aXZlVG9GaXhlZC5jYWxsKHt9KTtcbn0pO1xuXG4vLyBgTnVtYmVyLnByb3RvdHlwZS50b0ZpeGVkYCBtZXRob2Rcbi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtbnVtYmVyLnByb3RvdHlwZS50b2ZpeGVkXG4kKHsgdGFyZ2V0OiAnTnVtYmVyJywgcHJvdG86IHRydWUsIGZvcmNlZDogRk9SQ0VEIH0sIHtcbiAgdG9GaXhlZDogZnVuY3Rpb24gdG9GaXhlZChmcmFjdGlvbkRpZ2l0cykge1xuICAgIHZhciBudW1iZXIgPSB0aGlzTnVtYmVyVmFsdWUodGhpcyk7XG4gICAgdmFyIGZyYWN0RGlnaXRzID0gdG9JbnRlZ2VyKGZyYWN0aW9uRGlnaXRzKTtcbiAgICB2YXIgZGF0YSA9IFswLCAwLCAwLCAwLCAwLCAwXTtcbiAgICB2YXIgc2lnbiA9ICcnO1xuICAgIHZhciByZXN1bHQgPSAnMCc7XG4gICAgdmFyIGUsIHosIGosIGs7XG5cbiAgICBpZiAoZnJhY3REaWdpdHMgPCAwIHx8IGZyYWN0RGlnaXRzID4gMjApIHRocm93IFJhbmdlRXJyb3IoJ0luY29ycmVjdCBmcmFjdGlvbiBkaWdpdHMnKTtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tc2VsZi1jb21wYXJlIC0tIE5hTiBjaGVja1xuICAgIGlmIChudW1iZXIgIT0gbnVtYmVyKSByZXR1cm4gJ05hTic7XG4gICAgaWYgKG51bWJlciA8PSAtMWUyMSB8fCBudW1iZXIgPj0gMWUyMSkgcmV0dXJuIFN0cmluZyhudW1iZXIpO1xuICAgIGlmIChudW1iZXIgPCAwKSB7XG4gICAgICBzaWduID0gJy0nO1xuICAgICAgbnVtYmVyID0gLW51bWJlcjtcbiAgICB9XG4gICAgaWYgKG51bWJlciA+IDFlLTIxKSB7XG4gICAgICBlID0gbG9nKG51bWJlciAqIHBvdygyLCA2OSwgMSkpIC0gNjk7XG4gICAgICB6ID0gZSA8IDAgPyBudW1iZXIgKiBwb3coMiwgLWUsIDEpIDogbnVtYmVyIC8gcG93KDIsIGUsIDEpO1xuICAgICAgeiAqPSAweDEwMDAwMDAwMDAwMDAwO1xuICAgICAgZSA9IDUyIC0gZTtcbiAgICAgIGlmIChlID4gMCkge1xuICAgICAgICBtdWx0aXBseShkYXRhLCAwLCB6KTtcbiAgICAgICAgaiA9IGZyYWN0RGlnaXRzO1xuICAgICAgICB3aGlsZSAoaiA+PSA3KSB7XG4gICAgICAgICAgbXVsdGlwbHkoZGF0YSwgMWU3LCAwKTtcbiAgICAgICAgICBqIC09IDc7XG4gICAgICAgIH1cbiAgICAgICAgbXVsdGlwbHkoZGF0YSwgcG93KDEwLCBqLCAxKSwgMCk7XG4gICAgICAgIGogPSBlIC0gMTtcbiAgICAgICAgd2hpbGUgKGogPj0gMjMpIHtcbiAgICAgICAgICBkaXZpZGUoZGF0YSwgMSA8PCAyMyk7XG4gICAgICAgICAgaiAtPSAyMztcbiAgICAgICAgfVxuICAgICAgICBkaXZpZGUoZGF0YSwgMSA8PCBqKTtcbiAgICAgICAgbXVsdGlwbHkoZGF0YSwgMSwgMSk7XG4gICAgICAgIGRpdmlkZShkYXRhLCAyKTtcbiAgICAgICAgcmVzdWx0ID0gZGF0YVRvU3RyaW5nKGRhdGEpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbXVsdGlwbHkoZGF0YSwgMCwgeik7XG4gICAgICAgIG11bHRpcGx5KGRhdGEsIDEgPDwgLWUsIDApO1xuICAgICAgICByZXN1bHQgPSBkYXRhVG9TdHJpbmcoZGF0YSkgKyByZXBlYXQuY2FsbCgnMCcsIGZyYWN0RGlnaXRzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGZyYWN0RGlnaXRzID4gMCkge1xuICAgICAgayA9IHJlc3VsdC5sZW5ndGg7XG4gICAgICByZXN1bHQgPSBzaWduICsgKGsgPD0gZnJhY3REaWdpdHNcbiAgICAgICAgPyAnMC4nICsgcmVwZWF0LmNhbGwoJzAnLCBmcmFjdERpZ2l0cyAtIGspICsgcmVzdWx0XG4gICAgICAgIDogcmVzdWx0LnNsaWNlKDAsIGsgLSBmcmFjdERpZ2l0cykgKyAnLicgKyByZXN1bHQuc2xpY2UoayAtIGZyYWN0RGlnaXRzKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3VsdCA9IHNpZ24gKyByZXN1bHQ7XG4gICAgfSByZXR1cm4gcmVzdWx0O1xuICB9XG59KTtcbiIsInZhciAkID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2V4cG9ydCcpO1xudmFyIHBhcnNlRmxvYXRJbXBsZW1lbnRhdGlvbiA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9udW1iZXItcGFyc2UtZmxvYXQnKTtcblxuLy8gYHBhcnNlRmxvYXRgIG1ldGhvZFxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1wYXJzZWZsb2F0LXN0cmluZ1xuJCh7IGdsb2JhbDogdHJ1ZSwgZm9yY2VkOiBwYXJzZUZsb2F0ICE9IHBhcnNlRmxvYXRJbXBsZW1lbnRhdGlvbiB9LCB7XG4gIHBhcnNlRmxvYXQ6IHBhcnNlRmxvYXRJbXBsZW1lbnRhdGlvblxufSk7XG4iLCJ2YXIgREVTQ1JJUFRPUlMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZGVzY3JpcHRvcnMnKTtcbnZhciBnbG9iYWwgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZ2xvYmFsJyk7XG52YXIgaXNGb3JjZWQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaXMtZm9yY2VkJyk7XG52YXIgaW5oZXJpdElmUmVxdWlyZWQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaW5oZXJpdC1pZi1yZXF1aXJlZCcpO1xudmFyIGRlZmluZVByb3BlcnR5ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL29iamVjdC1kZWZpbmUtcHJvcGVydHknKS5mO1xudmFyIGdldE93blByb3BlcnR5TmFtZXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvb2JqZWN0LWdldC1vd24tcHJvcGVydHktbmFtZXMnKS5mO1xudmFyIGlzUmVnRXhwID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2lzLXJlZ2V4cCcpO1xudmFyIGdldEZsYWdzID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3JlZ2V4cC1mbGFncycpO1xudmFyIHN0aWNreUhlbHBlcnMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvcmVnZXhwLXN0aWNreS1oZWxwZXJzJyk7XG52YXIgcmVkZWZpbmUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvcmVkZWZpbmUnKTtcbnZhciBmYWlscyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9mYWlscycpO1xudmFyIGVuZm9yY2VJbnRlcm5hbFN0YXRlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2ludGVybmFsLXN0YXRlJykuZW5mb3JjZTtcbnZhciBzZXRTcGVjaWVzID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3NldC1zcGVjaWVzJyk7XG52YXIgd2VsbEtub3duU3ltYm9sID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3dlbGwta25vd24tc3ltYm9sJyk7XG5cbnZhciBNQVRDSCA9IHdlbGxLbm93blN5bWJvbCgnbWF0Y2gnKTtcbnZhciBOYXRpdmVSZWdFeHAgPSBnbG9iYWwuUmVnRXhwO1xudmFyIFJlZ0V4cFByb3RvdHlwZSA9IE5hdGl2ZVJlZ0V4cC5wcm90b3R5cGU7XG52YXIgcmUxID0gL2EvZztcbnZhciByZTIgPSAvYS9nO1xuXG4vLyBcIm5ld1wiIHNob3VsZCBjcmVhdGUgYSBuZXcgb2JqZWN0LCBvbGQgd2Via2l0IGJ1Z1xudmFyIENPUlJFQ1RfTkVXID0gbmV3IE5hdGl2ZVJlZ0V4cChyZTEpICE9PSByZTE7XG5cbnZhciBVTlNVUFBPUlRFRF9ZID0gc3RpY2t5SGVscGVycy5VTlNVUFBPUlRFRF9ZO1xuXG52YXIgRk9SQ0VEID0gREVTQ1JJUFRPUlMgJiYgaXNGb3JjZWQoJ1JlZ0V4cCcsICghQ09SUkVDVF9ORVcgfHwgVU5TVVBQT1JURURfWSB8fCBmYWlscyhmdW5jdGlvbiAoKSB7XG4gIHJlMltNQVRDSF0gPSBmYWxzZTtcbiAgLy8gUmVnRXhwIGNvbnN0cnVjdG9yIGNhbiBhbHRlciBmbGFncyBhbmQgSXNSZWdFeHAgd29ya3MgY29ycmVjdCB3aXRoIEBAbWF0Y2hcbiAgcmV0dXJuIE5hdGl2ZVJlZ0V4cChyZTEpICE9IHJlMSB8fCBOYXRpdmVSZWdFeHAocmUyKSA9PSByZTIgfHwgTmF0aXZlUmVnRXhwKHJlMSwgJ2knKSAhPSAnL2EvaSc7XG59KSkpO1xuXG4vLyBgUmVnRXhwYCBjb25zdHJ1Y3RvclxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1yZWdleHAtY29uc3RydWN0b3JcbmlmIChGT1JDRUQpIHtcbiAgdmFyIFJlZ0V4cFdyYXBwZXIgPSBmdW5jdGlvbiBSZWdFeHAocGF0dGVybiwgZmxhZ3MpIHtcbiAgICB2YXIgdGhpc0lzUmVnRXhwID0gdGhpcyBpbnN0YW5jZW9mIFJlZ0V4cFdyYXBwZXI7XG4gICAgdmFyIHBhdHRlcm5Jc1JlZ0V4cCA9IGlzUmVnRXhwKHBhdHRlcm4pO1xuICAgIHZhciBmbGFnc0FyZVVuZGVmaW5lZCA9IGZsYWdzID09PSB1bmRlZmluZWQ7XG4gICAgdmFyIHN0aWNreTtcblxuICAgIGlmICghdGhpc0lzUmVnRXhwICYmIHBhdHRlcm5Jc1JlZ0V4cCAmJiBwYXR0ZXJuLmNvbnN0cnVjdG9yID09PSBSZWdFeHBXcmFwcGVyICYmIGZsYWdzQXJlVW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gcGF0dGVybjtcbiAgICB9XG5cbiAgICBpZiAoQ09SUkVDVF9ORVcpIHtcbiAgICAgIGlmIChwYXR0ZXJuSXNSZWdFeHAgJiYgIWZsYWdzQXJlVW5kZWZpbmVkKSBwYXR0ZXJuID0gcGF0dGVybi5zb3VyY2U7XG4gICAgfSBlbHNlIGlmIChwYXR0ZXJuIGluc3RhbmNlb2YgUmVnRXhwV3JhcHBlcikge1xuICAgICAgaWYgKGZsYWdzQXJlVW5kZWZpbmVkKSBmbGFncyA9IGdldEZsYWdzLmNhbGwocGF0dGVybik7XG4gICAgICBwYXR0ZXJuID0gcGF0dGVybi5zb3VyY2U7XG4gICAgfVxuXG4gICAgaWYgKFVOU1VQUE9SVEVEX1kpIHtcbiAgICAgIHN0aWNreSA9ICEhZmxhZ3MgJiYgZmxhZ3MuaW5kZXhPZigneScpID4gLTE7XG4gICAgICBpZiAoc3RpY2t5KSBmbGFncyA9IGZsYWdzLnJlcGxhY2UoL3kvZywgJycpO1xuICAgIH1cblxuICAgIHZhciByZXN1bHQgPSBpbmhlcml0SWZSZXF1aXJlZChcbiAgICAgIENPUlJFQ1RfTkVXID8gbmV3IE5hdGl2ZVJlZ0V4cChwYXR0ZXJuLCBmbGFncykgOiBOYXRpdmVSZWdFeHAocGF0dGVybiwgZmxhZ3MpLFxuICAgICAgdGhpc0lzUmVnRXhwID8gdGhpcyA6IFJlZ0V4cFByb3RvdHlwZSxcbiAgICAgIFJlZ0V4cFdyYXBwZXJcbiAgICApO1xuXG4gICAgaWYgKFVOU1VQUE9SVEVEX1kgJiYgc3RpY2t5KSB7XG4gICAgICB2YXIgc3RhdGUgPSBlbmZvcmNlSW50ZXJuYWxTdGF0ZShyZXN1bHQpO1xuICAgICAgc3RhdGUuc3RpY2t5ID0gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuICB2YXIgcHJveHkgPSBmdW5jdGlvbiAoa2V5KSB7XG4gICAga2V5IGluIFJlZ0V4cFdyYXBwZXIgfHwgZGVmaW5lUHJvcGVydHkoUmVnRXhwV3JhcHBlciwga2V5LCB7XG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIE5hdGl2ZVJlZ0V4cFtrZXldOyB9LFxuICAgICAgc2V0OiBmdW5jdGlvbiAoaXQpIHsgTmF0aXZlUmVnRXhwW2tleV0gPSBpdDsgfVxuICAgIH0pO1xuICB9O1xuICB2YXIga2V5cyA9IGdldE93blByb3BlcnR5TmFtZXMoTmF0aXZlUmVnRXhwKTtcbiAgdmFyIGluZGV4ID0gMDtcbiAgd2hpbGUgKGtleXMubGVuZ3RoID4gaW5kZXgpIHByb3h5KGtleXNbaW5kZXgrK10pO1xuICBSZWdFeHBQcm90b3R5cGUuY29uc3RydWN0b3IgPSBSZWdFeHBXcmFwcGVyO1xuICBSZWdFeHBXcmFwcGVyLnByb3RvdHlwZSA9IFJlZ0V4cFByb3RvdHlwZTtcbiAgcmVkZWZpbmUoZ2xvYmFsLCAnUmVnRXhwJywgUmVnRXhwV3JhcHBlcik7XG59XG5cbi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtZ2V0LXJlZ2V4cC1AQHNwZWNpZXNcbnNldFNwZWNpZXMoJ1JlZ0V4cCcpO1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIHJlZGVmaW5lID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3JlZGVmaW5lJyk7XG52YXIgYW5PYmplY3QgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvYW4tb2JqZWN0Jyk7XG52YXIgZmFpbHMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZmFpbHMnKTtcbnZhciBmbGFncyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9yZWdleHAtZmxhZ3MnKTtcblxudmFyIFRPX1NUUklORyA9ICd0b1N0cmluZyc7XG52YXIgUmVnRXhwUHJvdG90eXBlID0gUmVnRXhwLnByb3RvdHlwZTtcbnZhciBuYXRpdmVUb1N0cmluZyA9IFJlZ0V4cFByb3RvdHlwZVtUT19TVFJJTkddO1xuXG52YXIgTk9UX0dFTkVSSUMgPSBmYWlscyhmdW5jdGlvbiAoKSB7IHJldHVybiBuYXRpdmVUb1N0cmluZy5jYWxsKHsgc291cmNlOiAnYScsIGZsYWdzOiAnYicgfSkgIT0gJy9hL2InOyB9KTtcbi8vIEZGNDQtIFJlZ0V4cCN0b1N0cmluZyBoYXMgYSB3cm9uZyBuYW1lXG52YXIgSU5DT1JSRUNUX05BTUUgPSBuYXRpdmVUb1N0cmluZy5uYW1lICE9IFRPX1NUUklORztcblxuLy8gYFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmdgIG1ldGhvZFxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1yZWdleHAucHJvdG90eXBlLnRvc3RyaW5nXG5pZiAoTk9UX0dFTkVSSUMgfHwgSU5DT1JSRUNUX05BTUUpIHtcbiAgcmVkZWZpbmUoUmVnRXhwLnByb3RvdHlwZSwgVE9fU1RSSU5HLCBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgICB2YXIgUiA9IGFuT2JqZWN0KHRoaXMpO1xuICAgIHZhciBwID0gU3RyaW5nKFIuc291cmNlKTtcbiAgICB2YXIgcmYgPSBSLmZsYWdzO1xuICAgIHZhciBmID0gU3RyaW5nKHJmID09PSB1bmRlZmluZWQgJiYgUiBpbnN0YW5jZW9mIFJlZ0V4cCAmJiAhKCdmbGFncycgaW4gUmVnRXhwUHJvdG90eXBlKSA/IGZsYWdzLmNhbGwoUikgOiByZik7XG4gICAgcmV0dXJuICcvJyArIHAgKyAnLycgKyBmO1xuICB9LCB7IHVuc2FmZTogdHJ1ZSB9KTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcbnZhciBmaXhSZWdFeHBXZWxsS25vd25TeW1ib2xMb2dpYyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9maXgtcmVnZXhwLXdlbGwta25vd24tc3ltYm9sLWxvZ2ljJyk7XG52YXIgYW5PYmplY3QgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvYW4tb2JqZWN0Jyk7XG52YXIgcmVxdWlyZU9iamVjdENvZXJjaWJsZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9yZXF1aXJlLW9iamVjdC1jb2VyY2libGUnKTtcbnZhciBzYW1lVmFsdWUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvc2FtZS12YWx1ZScpO1xudmFyIHJlZ0V4cEV4ZWMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvcmVnZXhwLWV4ZWMtYWJzdHJhY3QnKTtcblxuLy8gQEBzZWFyY2ggbG9naWNcbmZpeFJlZ0V4cFdlbGxLbm93blN5bWJvbExvZ2ljKCdzZWFyY2gnLCAxLCBmdW5jdGlvbiAoU0VBUkNILCBuYXRpdmVTZWFyY2gsIG1heWJlQ2FsbE5hdGl2ZSkge1xuICByZXR1cm4gW1xuICAgIC8vIGBTdHJpbmcucHJvdG90eXBlLnNlYXJjaGAgbWV0aG9kXG4gICAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1zdHJpbmcucHJvdG90eXBlLnNlYXJjaFxuICAgIGZ1bmN0aW9uIHNlYXJjaChyZWdleHApIHtcbiAgICAgIHZhciBPID0gcmVxdWlyZU9iamVjdENvZXJjaWJsZSh0aGlzKTtcbiAgICAgIHZhciBzZWFyY2hlciA9IHJlZ2V4cCA9PSB1bmRlZmluZWQgPyB1bmRlZmluZWQgOiByZWdleHBbU0VBUkNIXTtcbiAgICAgIHJldHVybiBzZWFyY2hlciAhPT0gdW5kZWZpbmVkID8gc2VhcmNoZXIuY2FsbChyZWdleHAsIE8pIDogbmV3IFJlZ0V4cChyZWdleHApW1NFQVJDSF0oU3RyaW5nKE8pKTtcbiAgICB9LFxuICAgIC8vIGBSZWdFeHAucHJvdG90eXBlW0BAc2VhcmNoXWAgbWV0aG9kXG4gICAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1yZWdleHAucHJvdG90eXBlLUBAc2VhcmNoXG4gICAgZnVuY3Rpb24gKHJlZ2V4cCkge1xuICAgICAgdmFyIHJlcyA9IG1heWJlQ2FsbE5hdGl2ZShuYXRpdmVTZWFyY2gsIHJlZ2V4cCwgdGhpcyk7XG4gICAgICBpZiAocmVzLmRvbmUpIHJldHVybiByZXMudmFsdWU7XG5cbiAgICAgIHZhciByeCA9IGFuT2JqZWN0KHJlZ2V4cCk7XG4gICAgICB2YXIgUyA9IFN0cmluZyh0aGlzKTtcblxuICAgICAgdmFyIHByZXZpb3VzTGFzdEluZGV4ID0gcngubGFzdEluZGV4O1xuICAgICAgaWYgKCFzYW1lVmFsdWUocHJldmlvdXNMYXN0SW5kZXgsIDApKSByeC5sYXN0SW5kZXggPSAwO1xuICAgICAgdmFyIHJlc3VsdCA9IHJlZ0V4cEV4ZWMocngsIFMpO1xuICAgICAgaWYgKCFzYW1lVmFsdWUocngubGFzdEluZGV4LCBwcmV2aW91c0xhc3RJbmRleCkpIHJ4Lmxhc3RJbmRleCA9IHByZXZpb3VzTGFzdEluZGV4O1xuICAgICAgcmV0dXJuIHJlc3VsdCA9PT0gbnVsbCA/IC0xIDogcmVzdWx0LmluZGV4O1xuICAgIH1cbiAgXTtcbn0pO1xuIiwidmFyICQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZXhwb3J0Jyk7XG52YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2dsb2JhbCcpO1xudmFyIHVzZXJBZ2VudCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9lbmdpbmUtdXNlci1hZ2VudCcpO1xuXG52YXIgc2xpY2UgPSBbXS5zbGljZTtcbnZhciBNU0lFID0gL01TSUUgLlxcLi8udGVzdCh1c2VyQWdlbnQpOyAvLyA8LSBkaXJ0eSBpZTktIGNoZWNrXG5cbnZhciB3cmFwID0gZnVuY3Rpb24gKHNjaGVkdWxlcikge1xuICByZXR1cm4gZnVuY3Rpb24gKGhhbmRsZXIsIHRpbWVvdXQgLyogLCAuLi5hcmd1bWVudHMgKi8pIHtcbiAgICB2YXIgYm91bmRBcmdzID0gYXJndW1lbnRzLmxlbmd0aCA+IDI7XG4gICAgdmFyIGFyZ3MgPSBib3VuZEFyZ3MgPyBzbGljZS5jYWxsKGFyZ3VtZW50cywgMikgOiB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIHNjaGVkdWxlcihib3VuZEFyZ3MgPyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tbmV3LWZ1bmMgLS0gc3BlYyByZXF1aXJlbWVudFxuICAgICAgKHR5cGVvZiBoYW5kbGVyID09ICdmdW5jdGlvbicgPyBoYW5kbGVyIDogRnVuY3Rpb24oaGFuZGxlcikpLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgIH0gOiBoYW5kbGVyLCB0aW1lb3V0KTtcbiAgfTtcbn07XG5cbi8vIGllOS0gc2V0VGltZW91dCAmIHNldEludGVydmFsIGFkZGl0aW9uYWwgcGFyYW1ldGVycyBmaXhcbi8vIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvbXVsdGlwYWdlL3RpbWVycy1hbmQtdXNlci1wcm9tcHRzLmh0bWwjdGltZXJzXG4kKHsgZ2xvYmFsOiB0cnVlLCBiaW5kOiB0cnVlLCBmb3JjZWQ6IE1TSUUgfSwge1xuICAvLyBgc2V0VGltZW91dGAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvbXVsdGlwYWdlL3RpbWVycy1hbmQtdXNlci1wcm9tcHRzLmh0bWwjZG9tLXNldHRpbWVvdXRcbiAgc2V0VGltZW91dDogd3JhcChnbG9iYWwuc2V0VGltZW91dCksXG4gIC8vIGBzZXRJbnRlcnZhbGAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvbXVsdGlwYWdlL3RpbWVycy1hbmQtdXNlci1wcm9tcHRzLmh0bWwjZG9tLXNldGludGVydmFsXG4gIHNldEludGVydmFsOiB3cmFwKGdsb2JhbC5zZXRJbnRlcnZhbClcbn0pO1xuIiwiLyogQHByZXNlcnZlXG4gKiBMZWFmbGV0IDEuOS40LCBhIEpTIGxpYnJhcnkgZm9yIGludGVyYWN0aXZlIG1hcHMuIGh0dHBzOi8vbGVhZmxldGpzLmNvbVxuICogKGMpIDIwMTAtMjAyMyBWbGFkaW1pciBBZ2Fmb25raW4sIChjKSAyMDEwLTIwMTEgQ2xvdWRNYWRlXG4gKi9cblxuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzKSA6XG4gIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnXSwgZmFjdG9yeSkgOlxuICAoZ2xvYmFsID0gdHlwZW9mIGdsb2JhbFRoaXMgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsVGhpcyA6IGdsb2JhbCB8fCBzZWxmLCBmYWN0b3J5KGdsb2JhbC5sZWFmbGV0ID0ge30pKTtcbn0pKHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cykgeyAndXNlIHN0cmljdCc7XG5cbiAgdmFyIHZlcnNpb24gPSBcIjEuOS40XCI7XG5cbiAgLypcclxuICAgKiBAbmFtZXNwYWNlIFV0aWxcclxuICAgKlxyXG4gICAqIFZhcmlvdXMgdXRpbGl0eSBmdW5jdGlvbnMsIHVzZWQgYnkgTGVhZmxldCBpbnRlcm5hbGx5LlxyXG4gICAqL1xyXG5cclxuICAvLyBAZnVuY3Rpb24gZXh0ZW5kKGRlc3Q6IE9iamVjdCwgc3JjPzogT2JqZWN0KTogT2JqZWN0XHJcbiAgLy8gTWVyZ2VzIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBgc3JjYCBvYmplY3QgKG9yIG11bHRpcGxlIG9iamVjdHMpIGludG8gYGRlc3RgIG9iamVjdCBhbmQgcmV0dXJucyB0aGUgbGF0dGVyLiBIYXMgYW4gYEwuZXh0ZW5kYCBzaG9ydGN1dC5cclxuICBmdW5jdGlvbiBleHRlbmQoZGVzdCkge1xyXG4gIFx0dmFyIGksIGosIGxlbiwgc3JjO1xyXG5cclxuICBcdGZvciAoaiA9IDEsIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGogPCBsZW47IGorKykge1xyXG4gIFx0XHRzcmMgPSBhcmd1bWVudHNbal07XHJcbiAgXHRcdGZvciAoaSBpbiBzcmMpIHtcclxuICBcdFx0XHRkZXN0W2ldID0gc3JjW2ldO1xyXG4gIFx0XHR9XHJcbiAgXHR9XHJcbiAgXHRyZXR1cm4gZGVzdDtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBjcmVhdGUocHJvdG86IE9iamVjdCwgcHJvcGVydGllcz86IE9iamVjdCk6IE9iamVjdFxyXG4gIC8vIENvbXBhdGliaWxpdHkgcG9seWZpbGwgZm9yIFtPYmplY3QuY3JlYXRlXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9PYmplY3QvY3JlYXRlKVxyXG4gIHZhciBjcmVhdGUkMiA9IE9iamVjdC5jcmVhdGUgfHwgKGZ1bmN0aW9uICgpIHtcclxuICBcdGZ1bmN0aW9uIEYoKSB7fVxyXG4gIFx0cmV0dXJuIGZ1bmN0aW9uIChwcm90bykge1xyXG4gIFx0XHRGLnByb3RvdHlwZSA9IHByb3RvO1xyXG4gIFx0XHRyZXR1cm4gbmV3IEYoKTtcclxuICBcdH07XHJcbiAgfSkoKTtcclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGJpbmQoZm46IEZ1bmN0aW9uLCDigKYpOiBGdW5jdGlvblxyXG4gIC8vIFJldHVybnMgYSBuZXcgZnVuY3Rpb24gYm91bmQgdG8gdGhlIGFyZ3VtZW50cyBwYXNzZWQsIGxpa2UgW0Z1bmN0aW9uLnByb3RvdHlwZS5iaW5kXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9GdW5jdGlvbi9iaW5kKS5cclxuICAvLyBIYXMgYSBgTC5iaW5kKClgIHNob3J0Y3V0LlxyXG4gIGZ1bmN0aW9uIGJpbmQoZm4sIG9iaikge1xyXG4gIFx0dmFyIHNsaWNlID0gQXJyYXkucHJvdG90eXBlLnNsaWNlO1xyXG5cclxuICBcdGlmIChmbi5iaW5kKSB7XHJcbiAgXHRcdHJldHVybiBmbi5iaW5kLmFwcGx5KGZuLCBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xyXG4gIFx0fVxyXG5cclxuICBcdHZhciBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xyXG5cclxuICBcdHJldHVybiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiBmbi5hcHBseShvYmosIGFyZ3MubGVuZ3RoID8gYXJncy5jb25jYXQoc2xpY2UuY2FsbChhcmd1bWVudHMpKSA6IGFyZ3VtZW50cyk7XHJcbiAgXHR9O1xyXG4gIH1cclxuXHJcbiAgLy8gQHByb3BlcnR5IGxhc3RJZDogTnVtYmVyXHJcbiAgLy8gTGFzdCB1bmlxdWUgSUQgdXNlZCBieSBbYHN0YW1wKClgXSgjdXRpbC1zdGFtcClcclxuICB2YXIgbGFzdElkID0gMDtcclxuXHJcbiAgLy8gQGZ1bmN0aW9uIHN0YW1wKG9iajogT2JqZWN0KTogTnVtYmVyXHJcbiAgLy8gUmV0dXJucyB0aGUgdW5pcXVlIElEIG9mIGFuIG9iamVjdCwgYXNzaWduaW5nIGl0IG9uZSBpZiBpdCBkb2Vzbid0IGhhdmUgaXQuXHJcbiAgZnVuY3Rpb24gc3RhbXAob2JqKSB7XHJcbiAgXHRpZiAoISgnX2xlYWZsZXRfaWQnIGluIG9iaikpIHtcclxuICBcdFx0b2JqWydfbGVhZmxldF9pZCddID0gKytsYXN0SWQ7XHJcbiAgXHR9XHJcbiAgXHRyZXR1cm4gb2JqLl9sZWFmbGV0X2lkO1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIHRocm90dGxlKGZuOiBGdW5jdGlvbiwgdGltZTogTnVtYmVyLCBjb250ZXh0OiBPYmplY3QpOiBGdW5jdGlvblxyXG4gIC8vIFJldHVybnMgYSBmdW5jdGlvbiB3aGljaCBleGVjdXRlcyBmdW5jdGlvbiBgZm5gIHdpdGggdGhlIGdpdmVuIHNjb3BlIGBjb250ZXh0YFxyXG4gIC8vIChzbyB0aGF0IHRoZSBgdGhpc2Aga2V5d29yZCByZWZlcnMgdG8gYGNvbnRleHRgIGluc2lkZSBgZm5gJ3MgY29kZSkuIFRoZSBmdW5jdGlvblxyXG4gIC8vIGBmbmAgd2lsbCBiZSBjYWxsZWQgbm8gbW9yZSB0aGFuIG9uZSB0aW1lIHBlciBnaXZlbiBhbW91bnQgb2YgYHRpbWVgLiBUaGUgYXJndW1lbnRzXHJcbiAgLy8gcmVjZWl2ZWQgYnkgdGhlIGJvdW5kIGZ1bmN0aW9uIHdpbGwgYmUgYW55IGFyZ3VtZW50cyBwYXNzZWQgd2hlbiBiaW5kaW5nIHRoZVxyXG4gIC8vIGZ1bmN0aW9uLCBmb2xsb3dlZCBieSBhbnkgYXJndW1lbnRzIHBhc3NlZCB3aGVuIGludm9raW5nIHRoZSBib3VuZCBmdW5jdGlvbi5cclxuICAvLyBIYXMgYW4gYEwudGhyb3R0bGVgIHNob3J0Y3V0LlxyXG4gIGZ1bmN0aW9uIHRocm90dGxlKGZuLCB0aW1lLCBjb250ZXh0KSB7XHJcbiAgXHR2YXIgbG9jaywgYXJncywgd3JhcHBlckZuLCBsYXRlcjtcclxuXHJcbiAgXHRsYXRlciA9IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0Ly8gcmVzZXQgbG9jayBhbmQgY2FsbCBpZiBxdWV1ZWRcclxuICBcdFx0bG9jayA9IGZhbHNlO1xyXG4gIFx0XHRpZiAoYXJncykge1xyXG4gIFx0XHRcdHdyYXBwZXJGbi5hcHBseShjb250ZXh0LCBhcmdzKTtcclxuICBcdFx0XHRhcmdzID0gZmFsc2U7XHJcbiAgXHRcdH1cclxuICBcdH07XHJcblxyXG4gIFx0d3JhcHBlckZuID0gZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRpZiAobG9jaykge1xyXG4gIFx0XHRcdC8vIGNhbGxlZCB0b28gc29vbiwgcXVldWUgdG8gY2FsbCBsYXRlclxyXG4gIFx0XHRcdGFyZ3MgPSBhcmd1bWVudHM7XHJcblxyXG4gIFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdC8vIGNhbGwgYW5kIGxvY2sgdW50aWwgbGF0ZXJcclxuICBcdFx0XHRmbi5hcHBseShjb250ZXh0LCBhcmd1bWVudHMpO1xyXG4gIFx0XHRcdHNldFRpbWVvdXQobGF0ZXIsIHRpbWUpO1xyXG4gIFx0XHRcdGxvY2sgPSB0cnVlO1xyXG4gIFx0XHR9XHJcbiAgXHR9O1xyXG5cclxuICBcdHJldHVybiB3cmFwcGVyRm47XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gd3JhcE51bShudW06IE51bWJlciwgcmFuZ2U6IE51bWJlcltdLCBpbmNsdWRlTWF4PzogQm9vbGVhbik6IE51bWJlclxyXG4gIC8vIFJldHVybnMgdGhlIG51bWJlciBgbnVtYCBtb2R1bG8gYHJhbmdlYCBpbiBzdWNoIGEgd2F5IHNvIGl0IGxpZXMgd2l0aGluXHJcbiAgLy8gYHJhbmdlWzBdYCBhbmQgYHJhbmdlWzFdYC4gVGhlIHJldHVybmVkIHZhbHVlIHdpbGwgYmUgYWx3YXlzIHNtYWxsZXIgdGhhblxyXG4gIC8vIGByYW5nZVsxXWAgdW5sZXNzIGBpbmNsdWRlTWF4YCBpcyBzZXQgdG8gYHRydWVgLlxyXG4gIGZ1bmN0aW9uIHdyYXBOdW0oeCwgcmFuZ2UsIGluY2x1ZGVNYXgpIHtcclxuICBcdHZhciBtYXggPSByYW5nZVsxXSxcclxuICBcdCAgICBtaW4gPSByYW5nZVswXSxcclxuICBcdCAgICBkID0gbWF4IC0gbWluO1xyXG4gIFx0cmV0dXJuIHggPT09IG1heCAmJiBpbmNsdWRlTWF4ID8geCA6ICgoeCAtIG1pbikgJSBkICsgZCkgJSBkICsgbWluO1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGZhbHNlRm4oKTogRnVuY3Rpb25cclxuICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24gd2hpY2ggYWx3YXlzIHJldHVybnMgYGZhbHNlYC5cclxuICBmdW5jdGlvbiBmYWxzZUZuKCkgeyByZXR1cm4gZmFsc2U7IH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGZvcm1hdE51bShudW06IE51bWJlciwgcHJlY2lzaW9uPzogTnVtYmVyfGZhbHNlKTogTnVtYmVyXHJcbiAgLy8gUmV0dXJucyB0aGUgbnVtYmVyIGBudW1gIHJvdW5kZWQgd2l0aCBzcGVjaWZpZWQgYHByZWNpc2lvbmAuXHJcbiAgLy8gVGhlIGRlZmF1bHQgYHByZWNpc2lvbmAgdmFsdWUgaXMgNiBkZWNpbWFsIHBsYWNlcy5cclxuICAvLyBgZmFsc2VgIGNhbiBiZSBwYXNzZWQgdG8gc2tpcCBhbnkgcHJvY2Vzc2luZyAoY2FuIGJlIHVzZWZ1bCB0byBhdm9pZCByb3VuZC1vZmYgZXJyb3JzKS5cclxuICBmdW5jdGlvbiBmb3JtYXROdW0obnVtLCBwcmVjaXNpb24pIHtcclxuICBcdGlmIChwcmVjaXNpb24gPT09IGZhbHNlKSB7IHJldHVybiBudW07IH1cclxuICBcdHZhciBwb3cgPSBNYXRoLnBvdygxMCwgcHJlY2lzaW9uID09PSB1bmRlZmluZWQgPyA2IDogcHJlY2lzaW9uKTtcclxuICBcdHJldHVybiBNYXRoLnJvdW5kKG51bSAqIHBvdykgLyBwb3c7XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gdHJpbShzdHI6IFN0cmluZyk6IFN0cmluZ1xyXG4gIC8vIENvbXBhdGliaWxpdHkgcG9seWZpbGwgZm9yIFtTdHJpbmcucHJvdG90eXBlLnRyaW1dKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL1N0cmluZy9UcmltKVxyXG4gIGZ1bmN0aW9uIHRyaW0oc3RyKSB7XHJcbiAgXHRyZXR1cm4gc3RyLnRyaW0gPyBzdHIudHJpbSgpIDogc3RyLnJlcGxhY2UoL15cXHMrfFxccyskL2csICcnKTtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBzcGxpdFdvcmRzKHN0cjogU3RyaW5nKTogU3RyaW5nW11cclxuICAvLyBUcmltcyBhbmQgc3BsaXRzIHRoZSBzdHJpbmcgb24gd2hpdGVzcGFjZSBhbmQgcmV0dXJucyB0aGUgYXJyYXkgb2YgcGFydHMuXHJcbiAgZnVuY3Rpb24gc3BsaXRXb3JkcyhzdHIpIHtcclxuICBcdHJldHVybiB0cmltKHN0cikuc3BsaXQoL1xccysvKTtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBzZXRPcHRpb25zKG9iajogT2JqZWN0LCBvcHRpb25zOiBPYmplY3QpOiBPYmplY3RcclxuICAvLyBNZXJnZXMgdGhlIGdpdmVuIHByb3BlcnRpZXMgdG8gdGhlIGBvcHRpb25zYCBvZiB0aGUgYG9iamAgb2JqZWN0LCByZXR1cm5pbmcgdGhlIHJlc3VsdGluZyBvcHRpb25zLiBTZWUgYENsYXNzIG9wdGlvbnNgLiBIYXMgYW4gYEwuc2V0T3B0aW9uc2Agc2hvcnRjdXQuXHJcbiAgZnVuY3Rpb24gc2V0T3B0aW9ucyhvYmosIG9wdGlvbnMpIHtcclxuICBcdGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgJ29wdGlvbnMnKSkge1xyXG4gIFx0XHRvYmoub3B0aW9ucyA9IG9iai5vcHRpb25zID8gY3JlYXRlJDIob2JqLm9wdGlvbnMpIDoge307XHJcbiAgXHR9XHJcbiAgXHRmb3IgKHZhciBpIGluIG9wdGlvbnMpIHtcclxuICBcdFx0b2JqLm9wdGlvbnNbaV0gPSBvcHRpb25zW2ldO1xyXG4gIFx0fVxyXG4gIFx0cmV0dXJuIG9iai5vcHRpb25zO1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGdldFBhcmFtU3RyaW5nKG9iajogT2JqZWN0LCBleGlzdGluZ1VybD86IFN0cmluZywgdXBwZXJjYXNlPzogQm9vbGVhbik6IFN0cmluZ1xyXG4gIC8vIENvbnZlcnRzIGFuIG9iamVjdCBpbnRvIGEgcGFyYW1ldGVyIFVSTCBzdHJpbmcsIGUuZy4gYHthOiBcImZvb1wiLCBiOiBcImJhclwifWBcclxuICAvLyB0cmFuc2xhdGVzIHRvIGAnP2E9Zm9vJmI9YmFyJ2AuIElmIGBleGlzdGluZ1VybGAgaXMgc2V0LCB0aGUgcGFyYW1ldGVycyB3aWxsXHJcbiAgLy8gYmUgYXBwZW5kZWQgYXQgdGhlIGVuZC4gSWYgYHVwcGVyY2FzZWAgaXMgYHRydWVgLCB0aGUgcGFyYW1ldGVyIG5hbWVzIHdpbGxcclxuICAvLyBiZSB1cHBlcmNhc2VkIChlLmcuIGAnP0E9Zm9vJkI9YmFyJ2ApXHJcbiAgZnVuY3Rpb24gZ2V0UGFyYW1TdHJpbmcob2JqLCBleGlzdGluZ1VybCwgdXBwZXJjYXNlKSB7XHJcbiAgXHR2YXIgcGFyYW1zID0gW107XHJcbiAgXHRmb3IgKHZhciBpIGluIG9iaikge1xyXG4gIFx0XHRwYXJhbXMucHVzaChlbmNvZGVVUklDb21wb25lbnQodXBwZXJjYXNlID8gaS50b1VwcGVyQ2FzZSgpIDogaSkgKyAnPScgKyBlbmNvZGVVUklDb21wb25lbnQob2JqW2ldKSk7XHJcbiAgXHR9XHJcbiAgXHRyZXR1cm4gKCghZXhpc3RpbmdVcmwgfHwgZXhpc3RpbmdVcmwuaW5kZXhPZignPycpID09PSAtMSkgPyAnPycgOiAnJicpICsgcGFyYW1zLmpvaW4oJyYnKTtcclxuICB9XHJcblxyXG4gIHZhciB0ZW1wbGF0ZVJlID0gL1xceyAqKFtcXHdfIC1dKykgKlxcfS9nO1xyXG5cclxuICAvLyBAZnVuY3Rpb24gdGVtcGxhdGUoc3RyOiBTdHJpbmcsIGRhdGE6IE9iamVjdCk6IFN0cmluZ1xyXG4gIC8vIFNpbXBsZSB0ZW1wbGF0aW5nIGZhY2lsaXR5LCBhY2NlcHRzIGEgdGVtcGxhdGUgc3RyaW5nIG9mIHRoZSBmb3JtIGAnSGVsbG8ge2F9LCB7Yn0nYFxyXG4gIC8vIGFuZCBhIGRhdGEgb2JqZWN0IGxpa2UgYHthOiAnZm9vJywgYjogJ2Jhcid9YCwgcmV0dXJucyBldmFsdWF0ZWQgc3RyaW5nXHJcbiAgLy8gYCgnSGVsbG8gZm9vLCBiYXInKWAuIFlvdSBjYW4gYWxzbyBzcGVjaWZ5IGZ1bmN0aW9ucyBpbnN0ZWFkIG9mIHN0cmluZ3MgZm9yXHJcbiAgLy8gZGF0YSB2YWx1ZXMg4oCUIHRoZXkgd2lsbCBiZSBldmFsdWF0ZWQgcGFzc2luZyBgZGF0YWAgYXMgYW4gYXJndW1lbnQuXHJcbiAgZnVuY3Rpb24gdGVtcGxhdGUoc3RyLCBkYXRhKSB7XHJcbiAgXHRyZXR1cm4gc3RyLnJlcGxhY2UodGVtcGxhdGVSZSwgZnVuY3Rpb24gKHN0ciwga2V5KSB7XHJcbiAgXHRcdHZhciB2YWx1ZSA9IGRhdGFba2V5XTtcclxuXHJcbiAgXHRcdGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdObyB2YWx1ZSBwcm92aWRlZCBmb3IgdmFyaWFibGUgJyArIHN0cik7XHJcblxyXG4gIFx0XHR9IGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gIFx0XHRcdHZhbHVlID0gdmFsdWUoZGF0YSk7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHZhbHVlO1xyXG4gIFx0fSk7XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gaXNBcnJheShvYmopOiBCb29sZWFuXHJcbiAgLy8gQ29tcGF0aWJpbGl0eSBwb2x5ZmlsbCBmb3IgW0FycmF5LmlzQXJyYXldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0FycmF5L2lzQXJyYXkpXHJcbiAgdmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5IHx8IGZ1bmN0aW9uIChvYmopIHtcclxuICBcdHJldHVybiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG9iaikgPT09ICdbb2JqZWN0IEFycmF5XScpO1xyXG4gIH07XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBpbmRleE9mKGFycmF5OiBBcnJheSwgZWw6IE9iamVjdCk6IE51bWJlclxyXG4gIC8vIENvbXBhdGliaWxpdHkgcG9seWZpbGwgZm9yIFtBcnJheS5wcm90b3R5cGUuaW5kZXhPZl0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvQXJyYXkvaW5kZXhPZilcclxuICBmdW5jdGlvbiBpbmRleE9mKGFycmF5LCBlbCkge1xyXG4gIFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xyXG4gIFx0XHRpZiAoYXJyYXlbaV0gPT09IGVsKSB7IHJldHVybiBpOyB9XHJcbiAgXHR9XHJcbiAgXHRyZXR1cm4gLTE7XHJcbiAgfVxyXG5cclxuICAvLyBAcHJvcGVydHkgZW1wdHlJbWFnZVVybDogU3RyaW5nXHJcbiAgLy8gRGF0YSBVUkkgc3RyaW5nIGNvbnRhaW5pbmcgYSBiYXNlNjQtZW5jb2RlZCBlbXB0eSBHSUYgaW1hZ2UuXHJcbiAgLy8gVXNlZCBhcyBhIGhhY2sgdG8gZnJlZSBtZW1vcnkgZnJvbSB1bnVzZWQgaW1hZ2VzIG9uIFdlYktpdC1wb3dlcmVkXHJcbiAgLy8gbW9iaWxlIGRldmljZXMgKGJ5IHNldHRpbmcgaW1hZ2UgYHNyY2AgdG8gdGhpcyBzdHJpbmcpLlxyXG4gIHZhciBlbXB0eUltYWdlVXJsID0gJ2RhdGE6aW1hZ2UvZ2lmO2Jhc2U2NCxSMGxHT0RsaEFRQUJBQUQvQUN3QUFBQUFBUUFCQUFBQ0FEcz0nO1xyXG5cclxuICAvLyBpbnNwaXJlZCBieSBodHRwczovL3BhdWxpcmlzaC5jb20vMjAxMS9yZXF1ZXN0YW5pbWF0aW9uZnJhbWUtZm9yLXNtYXJ0LWFuaW1hdGluZy9cclxuXHJcbiAgZnVuY3Rpb24gZ2V0UHJlZml4ZWQobmFtZSkge1xyXG4gIFx0cmV0dXJuIHdpbmRvd1snd2Via2l0JyArIG5hbWVdIHx8IHdpbmRvd1snbW96JyArIG5hbWVdIHx8IHdpbmRvd1snbXMnICsgbmFtZV07XHJcbiAgfVxyXG5cclxuICB2YXIgbGFzdFRpbWUgPSAwO1xyXG5cclxuICAvLyBmYWxsYmFjayBmb3IgSUUgNy04XHJcbiAgZnVuY3Rpb24gdGltZW91dERlZmVyKGZuKSB7XHJcbiAgXHR2YXIgdGltZSA9ICtuZXcgRGF0ZSgpLFxyXG4gIFx0ICAgIHRpbWVUb0NhbGwgPSBNYXRoLm1heCgwLCAxNiAtICh0aW1lIC0gbGFzdFRpbWUpKTtcclxuXHJcbiAgXHRsYXN0VGltZSA9IHRpbWUgKyB0aW1lVG9DYWxsO1xyXG4gIFx0cmV0dXJuIHdpbmRvdy5zZXRUaW1lb3V0KGZuLCB0aW1lVG9DYWxsKTtcclxuICB9XHJcblxyXG4gIHZhciByZXF1ZXN0Rm4gPSB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lIHx8IGdldFByZWZpeGVkKCdSZXF1ZXN0QW5pbWF0aW9uRnJhbWUnKSB8fCB0aW1lb3V0RGVmZXI7XHJcbiAgdmFyIGNhbmNlbEZuID0gd2luZG93LmNhbmNlbEFuaW1hdGlvbkZyYW1lIHx8IGdldFByZWZpeGVkKCdDYW5jZWxBbmltYXRpb25GcmFtZScpIHx8XHJcbiAgXHRcdGdldFByZWZpeGVkKCdDYW5jZWxSZXF1ZXN0QW5pbWF0aW9uRnJhbWUnKSB8fCBmdW5jdGlvbiAoaWQpIHsgd2luZG93LmNsZWFyVGltZW91dChpZCk7IH07XHJcblxyXG4gIC8vIEBmdW5jdGlvbiByZXF1ZXN0QW5pbUZyYW1lKGZuOiBGdW5jdGlvbiwgY29udGV4dD86IE9iamVjdCwgaW1tZWRpYXRlPzogQm9vbGVhbik6IE51bWJlclxyXG4gIC8vIFNjaGVkdWxlcyBgZm5gIHRvIGJlIGV4ZWN1dGVkIHdoZW4gdGhlIGJyb3dzZXIgcmVwYWludHMuIGBmbmAgaXMgYm91bmQgdG9cclxuICAvLyBgY29udGV4dGAgaWYgZ2l2ZW4uIFdoZW4gYGltbWVkaWF0ZWAgaXMgc2V0LCBgZm5gIGlzIGNhbGxlZCBpbW1lZGlhdGVseSBpZlxyXG4gIC8vIHRoZSBicm93c2VyIGRvZXNuJ3QgaGF2ZSBuYXRpdmUgc3VwcG9ydCBmb3JcclxuICAvLyBbYHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWVgXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvd2luZG93L3JlcXVlc3RBbmltYXRpb25GcmFtZSksXHJcbiAgLy8gb3RoZXJ3aXNlIGl0J3MgZGVsYXllZC4gUmV0dXJucyBhIHJlcXVlc3QgSUQgdGhhdCBjYW4gYmUgdXNlZCB0byBjYW5jZWwgdGhlIHJlcXVlc3QuXHJcbiAgZnVuY3Rpb24gcmVxdWVzdEFuaW1GcmFtZShmbiwgY29udGV4dCwgaW1tZWRpYXRlKSB7XHJcbiAgXHRpZiAoaW1tZWRpYXRlICYmIHJlcXVlc3RGbiA9PT0gdGltZW91dERlZmVyKSB7XHJcbiAgXHRcdGZuLmNhbGwoY29udGV4dCk7XHJcbiAgXHR9IGVsc2Uge1xyXG4gIFx0XHRyZXR1cm4gcmVxdWVzdEZuLmNhbGwod2luZG93LCBiaW5kKGZuLCBjb250ZXh0KSk7XHJcbiAgXHR9XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gY2FuY2VsQW5pbUZyYW1lKGlkOiBOdW1iZXIpOiB1bmRlZmluZWRcclxuICAvLyBDYW5jZWxzIGEgcHJldmlvdXMgYHJlcXVlc3RBbmltRnJhbWVgLiBTZWUgYWxzbyBbd2luZG93LmNhbmNlbEFuaW1hdGlvbkZyYW1lXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvd2luZG93L2NhbmNlbEFuaW1hdGlvbkZyYW1lKS5cclxuICBmdW5jdGlvbiBjYW5jZWxBbmltRnJhbWUoaWQpIHtcclxuICBcdGlmIChpZCkge1xyXG4gIFx0XHRjYW5jZWxGbi5jYWxsKHdpbmRvdywgaWQpO1xyXG4gIFx0fVxyXG4gIH1cblxuICB2YXIgVXRpbCA9IHtcbiAgICBfX3Byb3RvX186IG51bGwsXG4gICAgZXh0ZW5kOiBleHRlbmQsXG4gICAgY3JlYXRlOiBjcmVhdGUkMixcbiAgICBiaW5kOiBiaW5kLFxuICAgIGdldCBsYXN0SWQgKCkgeyByZXR1cm4gbGFzdElkOyB9LFxuICAgIHN0YW1wOiBzdGFtcCxcbiAgICB0aHJvdHRsZTogdGhyb3R0bGUsXG4gICAgd3JhcE51bTogd3JhcE51bSxcbiAgICBmYWxzZUZuOiBmYWxzZUZuLFxuICAgIGZvcm1hdE51bTogZm9ybWF0TnVtLFxuICAgIHRyaW06IHRyaW0sXG4gICAgc3BsaXRXb3Jkczogc3BsaXRXb3JkcyxcbiAgICBzZXRPcHRpb25zOiBzZXRPcHRpb25zLFxuICAgIGdldFBhcmFtU3RyaW5nOiBnZXRQYXJhbVN0cmluZyxcbiAgICB0ZW1wbGF0ZTogdGVtcGxhdGUsXG4gICAgaXNBcnJheTogaXNBcnJheSxcbiAgICBpbmRleE9mOiBpbmRleE9mLFxuICAgIGVtcHR5SW1hZ2VVcmw6IGVtcHR5SW1hZ2VVcmwsXG4gICAgcmVxdWVzdEZuOiByZXF1ZXN0Rm4sXG4gICAgY2FuY2VsRm46IGNhbmNlbEZuLFxuICAgIHJlcXVlc3RBbmltRnJhbWU6IHJlcXVlc3RBbmltRnJhbWUsXG4gICAgY2FuY2VsQW5pbUZyYW1lOiBjYW5jZWxBbmltRnJhbWVcbiAgfTtcblxuICAvLyBAY2xhc3MgQ2xhc3NcclxuICAvLyBAYWthIEwuQ2xhc3NcclxuXHJcbiAgLy8gQHNlY3Rpb25cclxuICAvLyBAdW5pbmhlcml0YWJsZVxyXG5cclxuICAvLyBUaGFua3MgdG8gSm9obiBSZXNpZyBhbmQgRGVhbiBFZHdhcmRzIGZvciBpbnNwaXJhdGlvbiFcclxuXHJcbiAgZnVuY3Rpb24gQ2xhc3MoKSB7fVxyXG5cclxuICBDbGFzcy5leHRlbmQgPSBmdW5jdGlvbiAocHJvcHMpIHtcclxuXHJcbiAgXHQvLyBAZnVuY3Rpb24gZXh0ZW5kKHByb3BzOiBPYmplY3QpOiBGdW5jdGlvblxyXG4gIFx0Ly8gW0V4dGVuZHMgdGhlIGN1cnJlbnQgY2xhc3NdKCNjbGFzcy1pbmhlcml0YW5jZSkgZ2l2ZW4gdGhlIHByb3BlcnRpZXMgdG8gYmUgaW5jbHVkZWQuXHJcbiAgXHQvLyBSZXR1cm5zIGEgSmF2YXNjcmlwdCBmdW5jdGlvbiB0aGF0IGlzIGEgY2xhc3MgY29uc3RydWN0b3IgKHRvIGJlIGNhbGxlZCB3aXRoIGBuZXdgKS5cclxuICBcdHZhciBOZXdDbGFzcyA9IGZ1bmN0aW9uICgpIHtcclxuXHJcbiAgXHRcdHNldE9wdGlvbnModGhpcyk7XHJcblxyXG4gIFx0XHQvLyBjYWxsIHRoZSBjb25zdHJ1Y3RvclxyXG4gIFx0XHRpZiAodGhpcy5pbml0aWFsaXplKSB7XHJcbiAgXHRcdFx0dGhpcy5pbml0aWFsaXplLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdC8vIGNhbGwgYWxsIGNvbnN0cnVjdG9yIGhvb2tzXHJcbiAgXHRcdHRoaXMuY2FsbEluaXRIb29rcygpO1xyXG4gIFx0fTtcclxuXHJcbiAgXHR2YXIgcGFyZW50UHJvdG8gPSBOZXdDbGFzcy5fX3N1cGVyX18gPSB0aGlzLnByb3RvdHlwZTtcclxuXHJcbiAgXHR2YXIgcHJvdG8gPSBjcmVhdGUkMihwYXJlbnRQcm90byk7XHJcbiAgXHRwcm90by5jb25zdHJ1Y3RvciA9IE5ld0NsYXNzO1xyXG5cclxuICBcdE5ld0NsYXNzLnByb3RvdHlwZSA9IHByb3RvO1xyXG5cclxuICBcdC8vIGluaGVyaXQgcGFyZW50J3Mgc3RhdGljc1xyXG4gIFx0Zm9yICh2YXIgaSBpbiB0aGlzKSB7XHJcbiAgXHRcdGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodGhpcywgaSkgJiYgaSAhPT0gJ3Byb3RvdHlwZScgJiYgaSAhPT0gJ19fc3VwZXJfXycpIHtcclxuICBcdFx0XHROZXdDbGFzc1tpXSA9IHRoaXNbaV07XHJcbiAgXHRcdH1cclxuICBcdH1cclxuXHJcbiAgXHQvLyBtaXggc3RhdGljIHByb3BlcnRpZXMgaW50byB0aGUgY2xhc3NcclxuICBcdGlmIChwcm9wcy5zdGF0aWNzKSB7XHJcbiAgXHRcdGV4dGVuZChOZXdDbGFzcywgcHJvcHMuc3RhdGljcyk7XHJcbiAgXHR9XHJcblxyXG4gIFx0Ly8gbWl4IGluY2x1ZGVzIGludG8gdGhlIHByb3RvdHlwZVxyXG4gIFx0aWYgKHByb3BzLmluY2x1ZGVzKSB7XHJcbiAgXHRcdGNoZWNrRGVwcmVjYXRlZE1peGluRXZlbnRzKHByb3BzLmluY2x1ZGVzKTtcclxuICBcdFx0ZXh0ZW5kLmFwcGx5KG51bGwsIFtwcm90b10uY29uY2F0KHByb3BzLmluY2x1ZGVzKSk7XHJcbiAgXHR9XHJcblxyXG4gIFx0Ly8gbWl4IGdpdmVuIHByb3BlcnRpZXMgaW50byB0aGUgcHJvdG90eXBlXHJcbiAgXHRleHRlbmQocHJvdG8sIHByb3BzKTtcclxuICBcdGRlbGV0ZSBwcm90by5zdGF0aWNzO1xyXG4gIFx0ZGVsZXRlIHByb3RvLmluY2x1ZGVzO1xyXG5cclxuICBcdC8vIG1lcmdlIG9wdGlvbnNcclxuICBcdGlmIChwcm90by5vcHRpb25zKSB7XHJcbiAgXHRcdHByb3RvLm9wdGlvbnMgPSBwYXJlbnRQcm90by5vcHRpb25zID8gY3JlYXRlJDIocGFyZW50UHJvdG8ub3B0aW9ucykgOiB7fTtcclxuICBcdFx0ZXh0ZW5kKHByb3RvLm9wdGlvbnMsIHByb3BzLm9wdGlvbnMpO1xyXG4gIFx0fVxyXG5cclxuICBcdHByb3RvLl9pbml0SG9va3MgPSBbXTtcclxuXHJcbiAgXHQvLyBhZGQgbWV0aG9kIGZvciBjYWxsaW5nIGFsbCBob29rc1xyXG4gIFx0cHJvdG8uY2FsbEluaXRIb29rcyA9IGZ1bmN0aW9uICgpIHtcclxuXHJcbiAgXHRcdGlmICh0aGlzLl9pbml0SG9va3NDYWxsZWQpIHsgcmV0dXJuOyB9XHJcblxyXG4gIFx0XHRpZiAocGFyZW50UHJvdG8uY2FsbEluaXRIb29rcykge1xyXG4gIFx0XHRcdHBhcmVudFByb3RvLmNhbGxJbml0SG9va3MuY2FsbCh0aGlzKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5faW5pdEhvb2tzQ2FsbGVkID0gdHJ1ZTtcclxuXHJcbiAgXHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBwcm90by5faW5pdEhvb2tzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdFx0cHJvdG8uX2luaXRIb29rc1tpXS5jYWxsKHRoaXMpO1xyXG4gIFx0XHR9XHJcbiAgXHR9O1xyXG5cclxuICBcdHJldHVybiBOZXdDbGFzcztcclxuICB9O1xyXG5cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGluY2x1ZGUocHJvcGVydGllczogT2JqZWN0KTogdGhpc1xyXG4gIC8vIFtJbmNsdWRlcyBhIG1peGluXSgjY2xhc3MtaW5jbHVkZXMpIGludG8gdGhlIGN1cnJlbnQgY2xhc3MuXHJcbiAgQ2xhc3MuaW5jbHVkZSA9IGZ1bmN0aW9uIChwcm9wcykge1xyXG4gIFx0dmFyIHBhcmVudE9wdGlvbnMgPSB0aGlzLnByb3RvdHlwZS5vcHRpb25zO1xyXG4gIFx0ZXh0ZW5kKHRoaXMucHJvdG90eXBlLCBwcm9wcyk7XHJcbiAgXHRpZiAocHJvcHMub3B0aW9ucykge1xyXG4gIFx0XHR0aGlzLnByb3RvdHlwZS5vcHRpb25zID0gcGFyZW50T3B0aW9ucztcclxuICBcdFx0dGhpcy5tZXJnZU9wdGlvbnMocHJvcHMub3B0aW9ucyk7XHJcbiAgXHR9XHJcbiAgXHRyZXR1cm4gdGhpcztcclxuICB9O1xyXG5cclxuICAvLyBAZnVuY3Rpb24gbWVyZ2VPcHRpb25zKG9wdGlvbnM6IE9iamVjdCk6IHRoaXNcclxuICAvLyBbTWVyZ2VzIGBvcHRpb25zYF0oI2NsYXNzLW9wdGlvbnMpIGludG8gdGhlIGRlZmF1bHRzIG9mIHRoZSBjbGFzcy5cclxuICBDbGFzcy5tZXJnZU9wdGlvbnMgPSBmdW5jdGlvbiAob3B0aW9ucykge1xyXG4gIFx0ZXh0ZW5kKHRoaXMucHJvdG90eXBlLm9wdGlvbnMsIG9wdGlvbnMpO1xyXG4gIFx0cmV0dXJuIHRoaXM7XHJcbiAgfTtcclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGFkZEluaXRIb29rKGZuOiBGdW5jdGlvbik6IHRoaXNcclxuICAvLyBBZGRzIGEgW2NvbnN0cnVjdG9yIGhvb2tdKCNjbGFzcy1jb25zdHJ1Y3Rvci1ob29rcykgdG8gdGhlIGNsYXNzLlxyXG4gIENsYXNzLmFkZEluaXRIb29rID0gZnVuY3Rpb24gKGZuKSB7IC8vIChGdW5jdGlvbikgfHwgKFN0cmluZywgYXJncy4uLilcclxuICBcdHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcclxuXHJcbiAgXHR2YXIgaW5pdCA9IHR5cGVvZiBmbiA9PT0gJ2Z1bmN0aW9uJyA/IGZuIDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR0aGlzW2ZuXS5hcHBseSh0aGlzLCBhcmdzKTtcclxuICBcdH07XHJcblxyXG4gIFx0dGhpcy5wcm90b3R5cGUuX2luaXRIb29rcyA9IHRoaXMucHJvdG90eXBlLl9pbml0SG9va3MgfHwgW107XHJcbiAgXHR0aGlzLnByb3RvdHlwZS5faW5pdEhvb2tzLnB1c2goaW5pdCk7XHJcbiAgXHRyZXR1cm4gdGhpcztcclxuICB9O1xyXG5cclxuICBmdW5jdGlvbiBjaGVja0RlcHJlY2F0ZWRNaXhpbkV2ZW50cyhpbmNsdWRlcykge1xyXG4gIFx0LyogZ2xvYmFsIEw6IHRydWUgKi9cclxuICBcdGlmICh0eXBlb2YgTCA9PT0gJ3VuZGVmaW5lZCcgfHwgIUwgfHwgIUwuTWl4aW4pIHsgcmV0dXJuOyB9XHJcblxyXG4gIFx0aW5jbHVkZXMgPSBpc0FycmF5KGluY2x1ZGVzKSA/IGluY2x1ZGVzIDogW2luY2x1ZGVzXTtcclxuXHJcbiAgXHRmb3IgKHZhciBpID0gMDsgaSA8IGluY2x1ZGVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgXHRcdGlmIChpbmNsdWRlc1tpXSA9PT0gTC5NaXhpbi5FdmVudHMpIHtcclxuICBcdFx0XHRjb25zb2xlLndhcm4oJ0RlcHJlY2F0ZWQgaW5jbHVkZSBvZiBMLk1peGluLkV2ZW50czogJyArXHJcbiAgXHRcdFx0XHQndGhpcyBwcm9wZXJ0eSB3aWxsIGJlIHJlbW92ZWQgaW4gZnV0dXJlIHJlbGVhc2VzLCAnICtcclxuICBcdFx0XHRcdCdwbGVhc2UgaW5oZXJpdCBmcm9tIEwuRXZlbnRlZCBpbnN0ZWFkLicsIG5ldyBFcnJvcigpLnN0YWNrKTtcclxuICBcdFx0fVxyXG4gIFx0fVxyXG4gIH1cblxuICAvKlxyXG4gICAqIEBjbGFzcyBFdmVudGVkXHJcbiAgICogQGFrYSBMLkV2ZW50ZWRcclxuICAgKiBAaW5oZXJpdHMgQ2xhc3NcclxuICAgKlxyXG4gICAqIEEgc2V0IG9mIG1ldGhvZHMgc2hhcmVkIGJldHdlZW4gZXZlbnQtcG93ZXJlZCBjbGFzc2VzIChsaWtlIGBNYXBgIGFuZCBgTWFya2VyYCkuIEdlbmVyYWxseSwgZXZlbnRzIGFsbG93IHlvdSB0byBleGVjdXRlIHNvbWUgZnVuY3Rpb24gd2hlbiBzb21ldGhpbmcgaGFwcGVucyB3aXRoIGFuIG9iamVjdCAoZS5nLiB0aGUgdXNlciBjbGlja3Mgb24gdGhlIG1hcCwgY2F1c2luZyB0aGUgbWFwIHRvIGZpcmUgYCdjbGljaydgIGV2ZW50KS5cclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICpcclxuICAgKiBgYGBqc1xyXG4gICAqIG1hcC5vbignY2xpY2snLCBmdW5jdGlvbihlKSB7XHJcbiAgICogXHRhbGVydChlLmxhdGxuZyk7XHJcbiAgICogfSApO1xyXG4gICAqIGBgYFxyXG4gICAqXHJcbiAgICogTGVhZmxldCBkZWFscyB3aXRoIGV2ZW50IGxpc3RlbmVycyBieSByZWZlcmVuY2UsIHNvIGlmIHlvdSB3YW50IHRvIGFkZCBhIGxpc3RlbmVyIGFuZCB0aGVuIHJlbW92ZSBpdCwgZGVmaW5lIGl0IGFzIGEgZnVuY3Rpb246XHJcbiAgICpcclxuICAgKiBgYGBqc1xyXG4gICAqIGZ1bmN0aW9uIG9uQ2xpY2soZSkgeyAuLi4gfVxyXG4gICAqXHJcbiAgICogbWFwLm9uKCdjbGljaycsIG9uQ2xpY2spO1xyXG4gICAqIG1hcC5vZmYoJ2NsaWNrJywgb25DbGljayk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcblxyXG4gIHZhciBFdmVudHMgPSB7XHJcbiAgXHQvKiBAbWV0aG9kIG9uKHR5cGU6IFN0cmluZywgZm46IEZ1bmN0aW9uLCBjb250ZXh0PzogT2JqZWN0KTogdGhpc1xyXG4gIFx0ICogQWRkcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIChgZm5gKSB0byBhIHBhcnRpY3VsYXIgZXZlbnQgdHlwZSBvZiB0aGUgb2JqZWN0LiBZb3UgY2FuIG9wdGlvbmFsbHkgc3BlY2lmeSB0aGUgY29udGV4dCBvZiB0aGUgbGlzdGVuZXIgKG9iamVjdCB0aGUgdGhpcyBrZXl3b3JkIHdpbGwgcG9pbnQgdG8pLiBZb3UgY2FuIGFsc28gcGFzcyBzZXZlcmFsIHNwYWNlLXNlcGFyYXRlZCB0eXBlcyAoZS5nLiBgJ2NsaWNrIGRibGNsaWNrJ2ApLlxyXG4gIFx0ICpcclxuICBcdCAqIEBhbHRlcm5hdGl2ZVxyXG4gIFx0ICogQG1ldGhvZCBvbihldmVudE1hcDogT2JqZWN0KTogdGhpc1xyXG4gIFx0ICogQWRkcyBhIHNldCBvZiB0eXBlL2xpc3RlbmVyIHBhaXJzLCBlLmcuIGB7Y2xpY2s6IG9uQ2xpY2ssIG1vdXNlbW92ZTogb25Nb3VzZU1vdmV9YFxyXG4gIFx0ICovXHJcbiAgXHRvbjogZnVuY3Rpb24gKHR5cGVzLCBmbiwgY29udGV4dCkge1xyXG5cclxuICBcdFx0Ly8gdHlwZXMgY2FuIGJlIGEgbWFwIG9mIHR5cGVzL2hhbmRsZXJzXHJcbiAgXHRcdGlmICh0eXBlb2YgdHlwZXMgPT09ICdvYmplY3QnKSB7XHJcbiAgXHRcdFx0Zm9yICh2YXIgdHlwZSBpbiB0eXBlcykge1xyXG4gIFx0XHRcdFx0Ly8gd2UgZG9uJ3QgcHJvY2VzcyBzcGFjZS1zZXBhcmF0ZWQgZXZlbnRzIGhlcmUgZm9yIHBlcmZvcm1hbmNlO1xyXG4gIFx0XHRcdFx0Ly8gaXQncyBhIGhvdCBwYXRoIHNpbmNlIExheWVyIHVzZXMgdGhlIG9uKG9iaikgc3ludGF4XHJcbiAgXHRcdFx0XHR0aGlzLl9vbih0eXBlLCB0eXBlc1t0eXBlXSwgZm4pO1xyXG4gIFx0XHRcdH1cclxuXHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0Ly8gdHlwZXMgY2FuIGJlIGEgc3RyaW5nIG9mIHNwYWNlLXNlcGFyYXRlZCB3b3Jkc1xyXG4gIFx0XHRcdHR5cGVzID0gc3BsaXRXb3Jkcyh0eXBlcyk7XHJcblxyXG4gIFx0XHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSB0eXBlcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gIFx0XHRcdFx0dGhpcy5fb24odHlwZXNbaV0sIGZuLCBjb250ZXh0KTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvKiBAbWV0aG9kIG9mZih0eXBlOiBTdHJpbmcsIGZuPzogRnVuY3Rpb24sIGNvbnRleHQ/OiBPYmplY3QpOiB0aGlzXHJcbiAgXHQgKiBSZW1vdmVzIGEgcHJldmlvdXNseSBhZGRlZCBsaXN0ZW5lciBmdW5jdGlvbi4gSWYgbm8gZnVuY3Rpb24gaXMgc3BlY2lmaWVkLCBpdCB3aWxsIHJlbW92ZSBhbGwgdGhlIGxpc3RlbmVycyBvZiB0aGF0IHBhcnRpY3VsYXIgZXZlbnQgZnJvbSB0aGUgb2JqZWN0LiBOb3RlIHRoYXQgaWYgeW91IHBhc3NlZCBhIGN1c3RvbSBjb250ZXh0IHRvIGBvbmAsIHlvdSBtdXN0IHBhc3MgdGhlIHNhbWUgY29udGV4dCB0byBgb2ZmYCBpbiBvcmRlciB0byByZW1vdmUgdGhlIGxpc3RlbmVyLlxyXG4gIFx0ICpcclxuICBcdCAqIEBhbHRlcm5hdGl2ZVxyXG4gIFx0ICogQG1ldGhvZCBvZmYoZXZlbnRNYXA6IE9iamVjdCk6IHRoaXNcclxuICBcdCAqIFJlbW92ZXMgYSBzZXQgb2YgdHlwZS9saXN0ZW5lciBwYWlycy5cclxuICBcdCAqXHJcbiAgXHQgKiBAYWx0ZXJuYXRpdmVcclxuICBcdCAqIEBtZXRob2Qgb2ZmOiB0aGlzXHJcbiAgXHQgKiBSZW1vdmVzIGFsbCBsaXN0ZW5lcnMgdG8gYWxsIGV2ZW50cyBvbiB0aGUgb2JqZWN0LiBUaGlzIGluY2x1ZGVzIGltcGxpY2l0bHkgYXR0YWNoZWQgZXZlbnRzLlxyXG4gIFx0ICovXHJcbiAgXHRvZmY6IGZ1bmN0aW9uICh0eXBlcywgZm4sIGNvbnRleHQpIHtcclxuXHJcbiAgXHRcdGlmICghYXJndW1lbnRzLmxlbmd0aCkge1xyXG4gIFx0XHRcdC8vIGNsZWFyIGFsbCBsaXN0ZW5lcnMgaWYgY2FsbGVkIHdpdGhvdXQgYXJndW1lbnRzXHJcbiAgXHRcdFx0ZGVsZXRlIHRoaXMuX2V2ZW50cztcclxuXHJcbiAgXHRcdH0gZWxzZSBpZiAodHlwZW9mIHR5cGVzID09PSAnb2JqZWN0Jykge1xyXG4gIFx0XHRcdGZvciAodmFyIHR5cGUgaW4gdHlwZXMpIHtcclxuICBcdFx0XHRcdHRoaXMuX29mZih0eXBlLCB0eXBlc1t0eXBlXSwgZm4pO1xyXG4gIFx0XHRcdH1cclxuXHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0dHlwZXMgPSBzcGxpdFdvcmRzKHR5cGVzKTtcclxuXHJcbiAgXHRcdFx0dmFyIHJlbW92ZUFsbCA9IGFyZ3VtZW50cy5sZW5ndGggPT09IDE7XHJcbiAgXHRcdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IHR5cGVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdFx0XHRpZiAocmVtb3ZlQWxsKSB7XHJcbiAgXHRcdFx0XHRcdHRoaXMuX29mZih0eXBlc1tpXSk7XHJcbiAgXHRcdFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdFx0XHR0aGlzLl9vZmYodHlwZXNbaV0sIGZuLCBjb250ZXh0KTtcclxuICBcdFx0XHRcdH1cclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBhdHRhY2ggbGlzdGVuZXIgKHdpdGhvdXQgc3ludGFjdGljIHN1Z2FyIG5vdylcclxuICBcdF9vbjogZnVuY3Rpb24gKHR5cGUsIGZuLCBjb250ZXh0LCBfb25jZSkge1xyXG4gIFx0XHRpZiAodHlwZW9mIGZuICE9PSAnZnVuY3Rpb24nKSB7XHJcbiAgXHRcdFx0Y29uc29sZS53YXJuKCd3cm9uZyBsaXN0ZW5lciB0eXBlOiAnICsgdHlwZW9mIGZuKTtcclxuICBcdFx0XHRyZXR1cm47XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdC8vIGNoZWNrIGlmIGZuIGFscmVhZHkgdGhlcmVcclxuICBcdFx0aWYgKHRoaXMuX2xpc3RlbnModHlwZSwgZm4sIGNvbnRleHQpICE9PSBmYWxzZSkge1xyXG4gIFx0XHRcdHJldHVybjtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0aWYgKGNvbnRleHQgPT09IHRoaXMpIHtcclxuICBcdFx0XHQvLyBMZXNzIG1lbW9yeSBmb290cHJpbnQuXHJcbiAgXHRcdFx0Y29udGV4dCA9IHVuZGVmaW5lZDtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dmFyIG5ld0xpc3RlbmVyID0ge2ZuOiBmbiwgY3R4OiBjb250ZXh0fTtcclxuICBcdFx0aWYgKF9vbmNlKSB7XHJcbiAgXHRcdFx0bmV3TGlzdGVuZXIub25jZSA9IHRydWU7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX2V2ZW50cyA9IHRoaXMuX2V2ZW50cyB8fCB7fTtcclxuICBcdFx0dGhpcy5fZXZlbnRzW3R5cGVdID0gdGhpcy5fZXZlbnRzW3R5cGVdIHx8IFtdO1xyXG4gIFx0XHR0aGlzLl9ldmVudHNbdHlwZV0ucHVzaChuZXdMaXN0ZW5lcik7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9vZmY6IGZ1bmN0aW9uICh0eXBlLCBmbiwgY29udGV4dCkge1xyXG4gIFx0XHR2YXIgbGlzdGVuZXJzLFxyXG4gIFx0XHQgICAgaSxcclxuICBcdFx0ICAgIGxlbjtcclxuXHJcbiAgXHRcdGlmICghdGhpcy5fZXZlbnRzKSB7XHJcbiAgXHRcdFx0cmV0dXJuO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRsaXN0ZW5lcnMgPSB0aGlzLl9ldmVudHNbdHlwZV07XHJcbiAgXHRcdGlmICghbGlzdGVuZXJzKSB7XHJcbiAgXHRcdFx0cmV0dXJuO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkgeyAvLyByZW1vdmUgYWxsXHJcbiAgXHRcdFx0aWYgKHRoaXMuX2ZpcmluZ0NvdW50KSB7XHJcbiAgXHRcdFx0XHQvLyBTZXQgYWxsIHJlbW92ZWQgbGlzdGVuZXJzIHRvIG5vb3BcclxuICBcdFx0XHRcdC8vIHNvIHRoZXkgYXJlIG5vdCBjYWxsZWQgaWYgcmVtb3ZlIGhhcHBlbnMgaW4gZmlyZVxyXG4gIFx0XHRcdFx0Zm9yIChpID0gMCwgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdFx0XHRcdGxpc3RlbmVyc1tpXS5mbiA9IGZhbHNlRm47XHJcbiAgXHRcdFx0XHR9XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHRcdC8vIGNsZWFyIGFsbCBsaXN0ZW5lcnMgZm9yIGEgdHlwZSBpZiBmdW5jdGlvbiBpc24ndCBzcGVjaWZpZWRcclxuICBcdFx0XHRkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xyXG4gIFx0XHRcdHJldHVybjtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0aWYgKHR5cGVvZiBmbiAhPT0gJ2Z1bmN0aW9uJykge1xyXG4gIFx0XHRcdGNvbnNvbGUud2Fybignd3JvbmcgbGlzdGVuZXIgdHlwZTogJyArIHR5cGVvZiBmbik7XHJcbiAgXHRcdFx0cmV0dXJuO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHQvLyBmaW5kIGZuIGFuZCByZW1vdmUgaXRcclxuICBcdFx0dmFyIGluZGV4ID0gdGhpcy5fbGlzdGVucyh0eXBlLCBmbiwgY29udGV4dCk7XHJcbiAgXHRcdGlmIChpbmRleCAhPT0gZmFsc2UpIHtcclxuICBcdFx0XHR2YXIgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaW5kZXhdO1xyXG4gIFx0XHRcdGlmICh0aGlzLl9maXJpbmdDb3VudCkge1xyXG4gIFx0XHRcdFx0Ly8gc2V0IHRoZSByZW1vdmVkIGxpc3RlbmVyIHRvIG5vb3Agc28gdGhhdCdzIG5vdCBjYWxsZWQgaWYgcmVtb3ZlIGhhcHBlbnMgaW4gZmlyZVxyXG4gIFx0XHRcdFx0bGlzdGVuZXIuZm4gPSBmYWxzZUZuO1xyXG5cclxuICBcdFx0XHRcdC8qIGNvcHkgYXJyYXkgaW4gY2FzZSBldmVudHMgYXJlIGJlaW5nIGZpcmVkICovXHJcbiAgXHRcdFx0XHR0aGlzLl9ldmVudHNbdHlwZV0gPSBsaXN0ZW5lcnMgPSBsaXN0ZW5lcnMuc2xpY2UoKTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdFx0bGlzdGVuZXJzLnNwbGljZShpbmRleCwgMSk7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBmaXJlKHR5cGU6IFN0cmluZywgZGF0YT86IE9iamVjdCwgcHJvcGFnYXRlPzogQm9vbGVhbik6IHRoaXNcclxuICBcdC8vIEZpcmVzIGFuIGV2ZW50IG9mIHRoZSBzcGVjaWZpZWQgdHlwZS4gWW91IGNhbiBvcHRpb25hbGx5IHByb3ZpZGUgYSBkYXRhXHJcbiAgXHQvLyBvYmplY3Qg4oCUIHRoZSBmaXJzdCBhcmd1bWVudCBvZiB0aGUgbGlzdGVuZXIgZnVuY3Rpb24gd2lsbCBjb250YWluIGl0c1xyXG4gIFx0Ly8gcHJvcGVydGllcy4gVGhlIGV2ZW50IGNhbiBvcHRpb25hbGx5IGJlIHByb3BhZ2F0ZWQgdG8gZXZlbnQgcGFyZW50cy5cclxuICBcdGZpcmU6IGZ1bmN0aW9uICh0eXBlLCBkYXRhLCBwcm9wYWdhdGUpIHtcclxuICBcdFx0aWYgKCF0aGlzLmxpc3RlbnModHlwZSwgcHJvcGFnYXRlKSkgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuICBcdFx0dmFyIGV2ZW50ID0gZXh0ZW5kKHt9LCBkYXRhLCB7XHJcbiAgXHRcdFx0dHlwZTogdHlwZSxcclxuICBcdFx0XHR0YXJnZXQ6IHRoaXMsXHJcbiAgXHRcdFx0c291cmNlVGFyZ2V0OiBkYXRhICYmIGRhdGEuc291cmNlVGFyZ2V0IHx8IHRoaXNcclxuICBcdFx0fSk7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fZXZlbnRzKSB7XHJcbiAgXHRcdFx0dmFyIGxpc3RlbmVycyA9IHRoaXMuX2V2ZW50c1t0eXBlXTtcclxuICBcdFx0XHRpZiAobGlzdGVuZXJzKSB7XHJcbiAgXHRcdFx0XHR0aGlzLl9maXJpbmdDb3VudCA9ICh0aGlzLl9maXJpbmdDb3VudCArIDEpIHx8IDE7XHJcbiAgXHRcdFx0XHRmb3IgKHZhciBpID0gMCwgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdFx0XHRcdHZhciBsID0gbGlzdGVuZXJzW2ldO1xyXG4gIFx0XHRcdFx0XHQvLyBvZmYgb3ZlcndyaXRlcyBsLmZuLCBzbyB3ZSBuZWVkIHRvIGNvcHkgZm4gdG8gYSB2YXJcclxuICBcdFx0XHRcdFx0dmFyIGZuID0gbC5mbjtcclxuICBcdFx0XHRcdFx0aWYgKGwub25jZSkge1xyXG4gIFx0XHRcdFx0XHRcdHRoaXMub2ZmKHR5cGUsIGZuLCBsLmN0eCk7XHJcbiAgXHRcdFx0XHRcdH1cclxuICBcdFx0XHRcdFx0Zm4uY2FsbChsLmN0eCB8fCB0aGlzLCBldmVudCk7XHJcbiAgXHRcdFx0XHR9XHJcblxyXG4gIFx0XHRcdFx0dGhpcy5fZmlyaW5nQ291bnQtLTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmIChwcm9wYWdhdGUpIHtcclxuICBcdFx0XHQvLyBwcm9wYWdhdGUgdGhlIGV2ZW50IHRvIHBhcmVudHMgKHNldCB3aXRoIGFkZEV2ZW50UGFyZW50KVxyXG4gIFx0XHRcdHRoaXMuX3Byb3BhZ2F0ZUV2ZW50KGV2ZW50KTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgbGlzdGVucyh0eXBlOiBTdHJpbmcsIHByb3BhZ2F0ZT86IEJvb2xlYW4pOiBCb29sZWFuXHJcbiAgXHQvLyBAbWV0aG9kIGxpc3RlbnModHlwZTogU3RyaW5nLCBmbjogRnVuY3Rpb24sIGNvbnRleHQ/OiBPYmplY3QsIHByb3BhZ2F0ZT86IEJvb2xlYW4pOiBCb29sZWFuXHJcbiAgXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiBhIHBhcnRpY3VsYXIgZXZlbnQgdHlwZSBoYXMgYW55IGxpc3RlbmVycyBhdHRhY2hlZCB0byBpdC5cclxuICBcdC8vIFRoZSB2ZXJpZmljYXRpb24gY2FuIG9wdGlvbmFsbHkgYmUgcHJvcGFnYXRlZCwgaXQgd2lsbCByZXR1cm4gYHRydWVgIGlmIHBhcmVudHMgaGF2ZSB0aGUgbGlzdGVuZXIgYXR0YWNoZWQgdG8gaXQuXHJcbiAgXHRsaXN0ZW5zOiBmdW5jdGlvbiAodHlwZSwgZm4sIGNvbnRleHQsIHByb3BhZ2F0ZSkge1xyXG4gIFx0XHRpZiAodHlwZW9mIHR5cGUgIT09ICdzdHJpbmcnKSB7XHJcbiAgXHRcdFx0Y29uc29sZS53YXJuKCdcInN0cmluZ1wiIHR5cGUgYXJndW1lbnQgZXhwZWN0ZWQnKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gd2UgZG9uJ3Qgb3ZlcndyaXRlIHRoZSBpbnB1dCBgZm5gIHZhbHVlLCBiZWNhdXNlIHdlIG5lZWQgdG8gdXNlIGl0IGZvciBwcm9wYWdhdGlvblxyXG4gIFx0XHR2YXIgX2ZuID0gZm47XHJcbiAgXHRcdGlmICh0eXBlb2YgZm4gIT09ICdmdW5jdGlvbicpIHtcclxuICBcdFx0XHRwcm9wYWdhdGUgPSAhIWZuO1xyXG4gIFx0XHRcdF9mbiA9IHVuZGVmaW5lZDtcclxuICBcdFx0XHRjb250ZXh0ID0gdW5kZWZpbmVkO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgbGlzdGVuZXJzID0gdGhpcy5fZXZlbnRzICYmIHRoaXMuX2V2ZW50c1t0eXBlXTtcclxuICBcdFx0aWYgKGxpc3RlbmVycyAmJiBsaXN0ZW5lcnMubGVuZ3RoKSB7XHJcbiAgXHRcdFx0aWYgKHRoaXMuX2xpc3RlbnModHlwZSwgX2ZuLCBjb250ZXh0KSAhPT0gZmFsc2UpIHtcclxuICBcdFx0XHRcdHJldHVybiB0cnVlO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG5cclxuICBcdFx0aWYgKHByb3BhZ2F0ZSkge1xyXG4gIFx0XHRcdC8vIGFsc28gY2hlY2sgcGFyZW50cyBmb3IgbGlzdGVuZXJzIGlmIGV2ZW50IHByb3BhZ2F0ZXNcclxuICBcdFx0XHRmb3IgKHZhciBpZCBpbiB0aGlzLl9ldmVudFBhcmVudHMpIHtcclxuICBcdFx0XHRcdGlmICh0aGlzLl9ldmVudFBhcmVudHNbaWRdLmxpc3RlbnModHlwZSwgZm4sIGNvbnRleHQsIHByb3BhZ2F0ZSkpIHsgcmV0dXJuIHRydWU7IH1cclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIGZhbHNlO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyByZXR1cm5zIHRoZSBpbmRleCAobnVtYmVyKSBvciBmYWxzZVxyXG4gIFx0X2xpc3RlbnM6IGZ1bmN0aW9uICh0eXBlLCBmbiwgY29udGV4dCkge1xyXG4gIFx0XHRpZiAoIXRoaXMuX2V2ZW50cykge1xyXG4gIFx0XHRcdHJldHVybiBmYWxzZTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dmFyIGxpc3RlbmVycyA9IHRoaXMuX2V2ZW50c1t0eXBlXSB8fCBbXTtcclxuICBcdFx0aWYgKCFmbikge1xyXG4gIFx0XHRcdHJldHVybiAhIWxpc3RlbmVycy5sZW5ndGg7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmIChjb250ZXh0ID09PSB0aGlzKSB7XHJcbiAgXHRcdFx0Ly8gTGVzcyBtZW1vcnkgZm9vdHByaW50LlxyXG4gIFx0XHRcdGNvbnRleHQgPSB1bmRlZmluZWQ7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuICBcdFx0XHRpZiAobGlzdGVuZXJzW2ldLmZuID09PSBmbiAmJiBsaXN0ZW5lcnNbaV0uY3R4ID09PSBjb250ZXh0KSB7XHJcbiAgXHRcdFx0XHRyZXR1cm4gaTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIGZhbHNlO1xyXG5cclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBvbmNlKOKApik6IHRoaXNcclxuICBcdC8vIEJlaGF2ZXMgYXMgW2BvbijigKYpYF0oI2V2ZW50ZWQtb24pLCBleGNlcHQgdGhlIGxpc3RlbmVyIHdpbGwgb25seSBnZXQgZmlyZWQgb25jZSBhbmQgdGhlbiByZW1vdmVkLlxyXG4gIFx0b25jZTogZnVuY3Rpb24gKHR5cGVzLCBmbiwgY29udGV4dCkge1xyXG5cclxuICBcdFx0Ly8gdHlwZXMgY2FuIGJlIGEgbWFwIG9mIHR5cGVzL2hhbmRsZXJzXHJcbiAgXHRcdGlmICh0eXBlb2YgdHlwZXMgPT09ICdvYmplY3QnKSB7XHJcbiAgXHRcdFx0Zm9yICh2YXIgdHlwZSBpbiB0eXBlcykge1xyXG4gIFx0XHRcdFx0Ly8gd2UgZG9uJ3QgcHJvY2VzcyBzcGFjZS1zZXBhcmF0ZWQgZXZlbnRzIGhlcmUgZm9yIHBlcmZvcm1hbmNlO1xyXG4gIFx0XHRcdFx0Ly8gaXQncyBhIGhvdCBwYXRoIHNpbmNlIExheWVyIHVzZXMgdGhlIG9uKG9iaikgc3ludGF4XHJcbiAgXHRcdFx0XHR0aGlzLl9vbih0eXBlLCB0eXBlc1t0eXBlXSwgZm4sIHRydWUpO1xyXG4gIFx0XHRcdH1cclxuXHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0Ly8gdHlwZXMgY2FuIGJlIGEgc3RyaW5nIG9mIHNwYWNlLXNlcGFyYXRlZCB3b3Jkc1xyXG4gIFx0XHRcdHR5cGVzID0gc3BsaXRXb3Jkcyh0eXBlcyk7XHJcblxyXG4gIFx0XHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSB0eXBlcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gIFx0XHRcdFx0dGhpcy5fb24odHlwZXNbaV0sIGZuLCBjb250ZXh0LCB0cnVlKTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGFkZEV2ZW50UGFyZW50KG9iajogRXZlbnRlZCk6IHRoaXNcclxuICBcdC8vIEFkZHMgYW4gZXZlbnQgcGFyZW50IC0gYW4gYEV2ZW50ZWRgIHRoYXQgd2lsbCByZWNlaXZlIHByb3BhZ2F0ZWQgZXZlbnRzXHJcbiAgXHRhZGRFdmVudFBhcmVudDogZnVuY3Rpb24gKG9iaikge1xyXG4gIFx0XHR0aGlzLl9ldmVudFBhcmVudHMgPSB0aGlzLl9ldmVudFBhcmVudHMgfHwge307XHJcbiAgXHRcdHRoaXMuX2V2ZW50UGFyZW50c1tzdGFtcChvYmopXSA9IG9iajtcclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgcmVtb3ZlRXZlbnRQYXJlbnQob2JqOiBFdmVudGVkKTogdGhpc1xyXG4gIFx0Ly8gUmVtb3ZlcyBhbiBldmVudCBwYXJlbnQsIHNvIGl0IHdpbGwgc3RvcCByZWNlaXZpbmcgcHJvcGFnYXRlZCBldmVudHNcclxuICBcdHJlbW92ZUV2ZW50UGFyZW50OiBmdW5jdGlvbiAob2JqKSB7XHJcbiAgXHRcdGlmICh0aGlzLl9ldmVudFBhcmVudHMpIHtcclxuICBcdFx0XHRkZWxldGUgdGhpcy5fZXZlbnRQYXJlbnRzW3N0YW1wKG9iaildO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfcHJvcGFnYXRlRXZlbnQ6IGZ1bmN0aW9uIChlKSB7XHJcbiAgXHRcdGZvciAodmFyIGlkIGluIHRoaXMuX2V2ZW50UGFyZW50cykge1xyXG4gIFx0XHRcdHRoaXMuX2V2ZW50UGFyZW50c1tpZF0uZmlyZShlLnR5cGUsIGV4dGVuZCh7XHJcbiAgXHRcdFx0XHRsYXllcjogZS50YXJnZXQsXHJcbiAgXHRcdFx0XHRwcm9wYWdhdGVkRnJvbTogZS50YXJnZXRcclxuICBcdFx0XHR9LCBlKSwgdHJ1ZSk7XHJcbiAgXHRcdH1cclxuICBcdH1cclxuICB9O1xyXG5cclxuICAvLyBhbGlhc2VzOyB3ZSBzaG91bGQgZGl0Y2ggdGhvc2UgZXZlbnR1YWxseVxyXG5cclxuICAvLyBAbWV0aG9kIGFkZEV2ZW50TGlzdGVuZXIo4oCmKTogdGhpc1xyXG4gIC8vIEFsaWFzIHRvIFtgb24o4oCmKWBdKCNldmVudGVkLW9uKVxyXG4gIEV2ZW50cy5hZGRFdmVudExpc3RlbmVyID0gRXZlbnRzLm9uO1xyXG5cclxuICAvLyBAbWV0aG9kIHJlbW92ZUV2ZW50TGlzdGVuZXIo4oCmKTogdGhpc1xyXG4gIC8vIEFsaWFzIHRvIFtgb2ZmKOKApilgXSgjZXZlbnRlZC1vZmYpXHJcblxyXG4gIC8vIEBtZXRob2QgY2xlYXJBbGxFdmVudExpc3RlbmVycyjigKYpOiB0aGlzXHJcbiAgLy8gQWxpYXMgdG8gW2BvZmYoKWBdKCNldmVudGVkLW9mZilcclxuICBFdmVudHMucmVtb3ZlRXZlbnRMaXN0ZW5lciA9IEV2ZW50cy5jbGVhckFsbEV2ZW50TGlzdGVuZXJzID0gRXZlbnRzLm9mZjtcclxuXHJcbiAgLy8gQG1ldGhvZCBhZGRPbmVUaW1lRXZlbnRMaXN0ZW5lcijigKYpOiB0aGlzXHJcbiAgLy8gQWxpYXMgdG8gW2BvbmNlKOKApilgXSgjZXZlbnRlZC1vbmNlKVxyXG4gIEV2ZW50cy5hZGRPbmVUaW1lRXZlbnRMaXN0ZW5lciA9IEV2ZW50cy5vbmNlO1xyXG5cclxuICAvLyBAbWV0aG9kIGZpcmVFdmVudCjigKYpOiB0aGlzXHJcbiAgLy8gQWxpYXMgdG8gW2BmaXJlKOKApilgXSgjZXZlbnRlZC1maXJlKVxyXG4gIEV2ZW50cy5maXJlRXZlbnQgPSBFdmVudHMuZmlyZTtcclxuXHJcbiAgLy8gQG1ldGhvZCBoYXNFdmVudExpc3RlbmVycyjigKYpOiBCb29sZWFuXHJcbiAgLy8gQWxpYXMgdG8gW2BsaXN0ZW5zKOKApilgXSgjZXZlbnRlZC1saXN0ZW5zKVxyXG4gIEV2ZW50cy5oYXNFdmVudExpc3RlbmVycyA9IEV2ZW50cy5saXN0ZW5zO1xyXG5cclxuICB2YXIgRXZlbnRlZCA9IENsYXNzLmV4dGVuZChFdmVudHMpO1xuXG4gIC8qXHJcbiAgICogQGNsYXNzIFBvaW50XHJcbiAgICogQGFrYSBMLlBvaW50XHJcbiAgICpcclxuICAgKiBSZXByZXNlbnRzIGEgcG9pbnQgd2l0aCBgeGAgYW5kIGB5YCBjb29yZGluYXRlcyBpbiBwaXhlbHMuXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiB2YXIgcG9pbnQgPSBMLnBvaW50KDIwMCwgMzAwKTtcclxuICAgKiBgYGBcclxuICAgKlxyXG4gICAqIEFsbCBMZWFmbGV0IG1ldGhvZHMgYW5kIG9wdGlvbnMgdGhhdCBhY2NlcHQgYFBvaW50YCBvYmplY3RzIGFsc28gYWNjZXB0IHRoZW0gaW4gYSBzaW1wbGUgQXJyYXkgZm9ybSAodW5sZXNzIG5vdGVkIG90aGVyd2lzZSksIHNvIHRoZXNlIGxpbmVzIGFyZSBlcXVpdmFsZW50OlxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiBtYXAucGFuQnkoWzIwMCwgMzAwXSk7XHJcbiAgICogbWFwLnBhbkJ5KEwucG9pbnQoMjAwLCAzMDApKTtcclxuICAgKiBgYGBcclxuICAgKlxyXG4gICAqIE5vdGUgdGhhdCBgUG9pbnRgIGRvZXMgbm90IGluaGVyaXQgZnJvbSBMZWFmbGV0J3MgYENsYXNzYCBvYmplY3QsXHJcbiAgICogd2hpY2ggbWVhbnMgbmV3IGNsYXNzZXMgY2FuJ3QgaW5oZXJpdCBmcm9tIGl0LCBhbmQgbmV3IG1ldGhvZHNcclxuICAgKiBjYW4ndCBiZSBhZGRlZCB0byBpdCB3aXRoIHRoZSBgaW5jbHVkZWAgZnVuY3Rpb24uXHJcbiAgICovXHJcblxyXG4gIGZ1bmN0aW9uIFBvaW50KHgsIHksIHJvdW5kKSB7XHJcbiAgXHQvLyBAcHJvcGVydHkgeDogTnVtYmVyOyBUaGUgYHhgIGNvb3JkaW5hdGUgb2YgdGhlIHBvaW50XHJcbiAgXHR0aGlzLnggPSAocm91bmQgPyBNYXRoLnJvdW5kKHgpIDogeCk7XHJcbiAgXHQvLyBAcHJvcGVydHkgeTogTnVtYmVyOyBUaGUgYHlgIGNvb3JkaW5hdGUgb2YgdGhlIHBvaW50XHJcbiAgXHR0aGlzLnkgPSAocm91bmQgPyBNYXRoLnJvdW5kKHkpIDogeSk7XHJcbiAgfVxyXG5cclxuICB2YXIgdHJ1bmMgPSBNYXRoLnRydW5jIHx8IGZ1bmN0aW9uICh2KSB7XHJcbiAgXHRyZXR1cm4gdiA+IDAgPyBNYXRoLmZsb29yKHYpIDogTWF0aC5jZWlsKHYpO1xyXG4gIH07XHJcblxyXG4gIFBvaW50LnByb3RvdHlwZSA9IHtcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGNsb25lKCk6IFBvaW50XHJcbiAgXHQvLyBSZXR1cm5zIGEgY29weSBvZiB0aGUgY3VycmVudCBwb2ludC5cclxuICBcdGNsb25lOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiBuZXcgUG9pbnQodGhpcy54LCB0aGlzLnkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGFkZChvdGhlclBvaW50OiBQb2ludCk6IFBvaW50XHJcbiAgXHQvLyBSZXR1cm5zIHRoZSByZXN1bHQgb2YgYWRkaXRpb24gb2YgdGhlIGN1cnJlbnQgYW5kIHRoZSBnaXZlbiBwb2ludHMuXHJcbiAgXHRhZGQ6IGZ1bmN0aW9uIChwb2ludCkge1xyXG4gIFx0XHQvLyBub24tZGVzdHJ1Y3RpdmUsIHJldHVybnMgYSBuZXcgcG9pbnRcclxuICBcdFx0cmV0dXJuIHRoaXMuY2xvbmUoKS5fYWRkKHRvUG9pbnQocG9pbnQpKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X2FkZDogZnVuY3Rpb24gKHBvaW50KSB7XHJcbiAgXHRcdC8vIGRlc3RydWN0aXZlLCB1c2VkIGRpcmVjdGx5IGZvciBwZXJmb3JtYW5jZSBpbiBzaXR1YXRpb25zIHdoZXJlIGl0J3Mgc2FmZSB0byBtb2RpZnkgZXhpc3RpbmcgcG9pbnRcclxuICBcdFx0dGhpcy54ICs9IHBvaW50Lng7XHJcbiAgXHRcdHRoaXMueSArPSBwb2ludC55O1xyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBzdWJ0cmFjdChvdGhlclBvaW50OiBQb2ludCk6IFBvaW50XHJcbiAgXHQvLyBSZXR1cm5zIHRoZSByZXN1bHQgb2Ygc3VidHJhY3Rpb24gb2YgdGhlIGdpdmVuIHBvaW50IGZyb20gdGhlIGN1cnJlbnQuXHJcbiAgXHRzdWJ0cmFjdDogZnVuY3Rpb24gKHBvaW50KSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLmNsb25lKCkuX3N1YnRyYWN0KHRvUG9pbnQocG9pbnQpKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X3N1YnRyYWN0OiBmdW5jdGlvbiAocG9pbnQpIHtcclxuICBcdFx0dGhpcy54IC09IHBvaW50Lng7XHJcbiAgXHRcdHRoaXMueSAtPSBwb2ludC55O1xyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBkaXZpZGVCeShudW06IE51bWJlcik6IFBvaW50XHJcbiAgXHQvLyBSZXR1cm5zIHRoZSByZXN1bHQgb2YgZGl2aXNpb24gb2YgdGhlIGN1cnJlbnQgcG9pbnQgYnkgdGhlIGdpdmVuIG51bWJlci5cclxuICBcdGRpdmlkZUJ5OiBmdW5jdGlvbiAobnVtKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLmNsb25lKCkuX2RpdmlkZUJ5KG51bSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9kaXZpZGVCeTogZnVuY3Rpb24gKG51bSkge1xyXG4gIFx0XHR0aGlzLnggLz0gbnVtO1xyXG4gIFx0XHR0aGlzLnkgLz0gbnVtO1xyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBtdWx0aXBseUJ5KG51bTogTnVtYmVyKTogUG9pbnRcclxuICBcdC8vIFJldHVybnMgdGhlIHJlc3VsdCBvZiBtdWx0aXBsaWNhdGlvbiBvZiB0aGUgY3VycmVudCBwb2ludCBieSB0aGUgZ2l2ZW4gbnVtYmVyLlxyXG4gIFx0bXVsdGlwbHlCeTogZnVuY3Rpb24gKG51bSkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5jbG9uZSgpLl9tdWx0aXBseUJ5KG51bSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9tdWx0aXBseUJ5OiBmdW5jdGlvbiAobnVtKSB7XHJcbiAgXHRcdHRoaXMueCAqPSBudW07XHJcbiAgXHRcdHRoaXMueSAqPSBudW07XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNjYWxlQnkoc2NhbGU6IFBvaW50KTogUG9pbnRcclxuICBcdC8vIE11bHRpcGx5IGVhY2ggY29vcmRpbmF0ZSBvZiB0aGUgY3VycmVudCBwb2ludCBieSBlYWNoIGNvb3JkaW5hdGUgb2ZcclxuICBcdC8vIGBzY2FsZWAuIEluIGxpbmVhciBhbGdlYnJhIHRlcm1zLCBtdWx0aXBseSB0aGUgcG9pbnQgYnkgdGhlXHJcbiAgXHQvLyBbc2NhbGluZyBtYXRyaXhdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NjYWxpbmdfJTI4Z2VvbWV0cnklMjkjTWF0cml4X3JlcHJlc2VudGF0aW9uKVxyXG4gIFx0Ly8gZGVmaW5lZCBieSBgc2NhbGVgLlxyXG4gIFx0c2NhbGVCeTogZnVuY3Rpb24gKHBvaW50KSB7XHJcbiAgXHRcdHJldHVybiBuZXcgUG9pbnQodGhpcy54ICogcG9pbnQueCwgdGhpcy55ICogcG9pbnQueSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgdW5zY2FsZUJ5KHNjYWxlOiBQb2ludCk6IFBvaW50XHJcbiAgXHQvLyBJbnZlcnNlIG9mIGBzY2FsZUJ5YC4gRGl2aWRlIGVhY2ggY29vcmRpbmF0ZSBvZiB0aGUgY3VycmVudCBwb2ludCBieVxyXG4gIFx0Ly8gZWFjaCBjb29yZGluYXRlIG9mIGBzY2FsZWAuXHJcbiAgXHR1bnNjYWxlQnk6IGZ1bmN0aW9uIChwb2ludCkge1xyXG4gIFx0XHRyZXR1cm4gbmV3IFBvaW50KHRoaXMueCAvIHBvaW50LngsIHRoaXMueSAvIHBvaW50LnkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHJvdW5kKCk6IFBvaW50XHJcbiAgXHQvLyBSZXR1cm5zIGEgY29weSBvZiB0aGUgY3VycmVudCBwb2ludCB3aXRoIHJvdW5kZWQgY29vcmRpbmF0ZXMuXHJcbiAgXHRyb3VuZDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5jbG9uZSgpLl9yb3VuZCgpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfcm91bmQ6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dGhpcy54ID0gTWF0aC5yb3VuZCh0aGlzLngpO1xyXG4gIFx0XHR0aGlzLnkgPSBNYXRoLnJvdW5kKHRoaXMueSk7XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGZsb29yKCk6IFBvaW50XHJcbiAgXHQvLyBSZXR1cm5zIGEgY29weSBvZiB0aGUgY3VycmVudCBwb2ludCB3aXRoIGZsb29yZWQgY29vcmRpbmF0ZXMgKHJvdW5kZWQgZG93bikuXHJcbiAgXHRmbG9vcjogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5jbG9uZSgpLl9mbG9vcigpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfZmxvb3I6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dGhpcy54ID0gTWF0aC5mbG9vcih0aGlzLngpO1xyXG4gIFx0XHR0aGlzLnkgPSBNYXRoLmZsb29yKHRoaXMueSk7XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGNlaWwoKTogUG9pbnRcclxuICBcdC8vIFJldHVybnMgYSBjb3B5IG9mIHRoZSBjdXJyZW50IHBvaW50IHdpdGggY2VpbGVkIGNvb3JkaW5hdGVzIChyb3VuZGVkIHVwKS5cclxuICBcdGNlaWw6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuY2xvbmUoKS5fY2VpbCgpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfY2VpbDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR0aGlzLnggPSBNYXRoLmNlaWwodGhpcy54KTtcclxuICBcdFx0dGhpcy55ID0gTWF0aC5jZWlsKHRoaXMueSk7XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHRydW5jKCk6IFBvaW50XHJcbiAgXHQvLyBSZXR1cm5zIGEgY29weSBvZiB0aGUgY3VycmVudCBwb2ludCB3aXRoIHRydW5jYXRlZCBjb29yZGluYXRlcyAocm91bmRlZCB0b3dhcmRzIHplcm8pLlxyXG4gIFx0dHJ1bmM6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuY2xvbmUoKS5fdHJ1bmMoKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X3RydW5jOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHRoaXMueCA9IHRydW5jKHRoaXMueCk7XHJcbiAgXHRcdHRoaXMueSA9IHRydW5jKHRoaXMueSk7XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGRpc3RhbmNlVG8ob3RoZXJQb2ludDogUG9pbnQpOiBOdW1iZXJcclxuICBcdC8vIFJldHVybnMgdGhlIGNhcnRlc2lhbiBkaXN0YW5jZSBiZXR3ZWVuIHRoZSBjdXJyZW50IGFuZCB0aGUgZ2l2ZW4gcG9pbnRzLlxyXG4gIFx0ZGlzdGFuY2VUbzogZnVuY3Rpb24gKHBvaW50KSB7XHJcbiAgXHRcdHBvaW50ID0gdG9Qb2ludChwb2ludCk7XHJcblxyXG4gIFx0XHR2YXIgeCA9IHBvaW50LnggLSB0aGlzLngsXHJcbiAgXHRcdCAgICB5ID0gcG9pbnQueSAtIHRoaXMueTtcclxuXHJcbiAgXHRcdHJldHVybiBNYXRoLnNxcnQoeCAqIHggKyB5ICogeSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZXF1YWxzKG90aGVyUG9pbnQ6IFBvaW50KTogQm9vbGVhblxyXG4gIFx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGdpdmVuIHBvaW50IGhhcyB0aGUgc2FtZSBjb29yZGluYXRlcy5cclxuICBcdGVxdWFsczogZnVuY3Rpb24gKHBvaW50KSB7XHJcbiAgXHRcdHBvaW50ID0gdG9Qb2ludChwb2ludCk7XHJcblxyXG4gIFx0XHRyZXR1cm4gcG9pbnQueCA9PT0gdGhpcy54ICYmXHJcbiAgXHRcdCAgICAgICBwb2ludC55ID09PSB0aGlzLnk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgY29udGFpbnMob3RoZXJQb2ludDogUG9pbnQpOiBCb29sZWFuXHJcbiAgXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiBib3RoIGNvb3JkaW5hdGVzIG9mIHRoZSBnaXZlbiBwb2ludCBhcmUgbGVzcyB0aGFuIHRoZSBjb3JyZXNwb25kaW5nIGN1cnJlbnQgcG9pbnQgY29vcmRpbmF0ZXMgKGluIGFic29sdXRlIHZhbHVlcykuXHJcbiAgXHRjb250YWluczogZnVuY3Rpb24gKHBvaW50KSB7XHJcbiAgXHRcdHBvaW50ID0gdG9Qb2ludChwb2ludCk7XHJcblxyXG4gIFx0XHRyZXR1cm4gTWF0aC5hYnMocG9pbnQueCkgPD0gTWF0aC5hYnModGhpcy54KSAmJlxyXG4gIFx0XHQgICAgICAgTWF0aC5hYnMocG9pbnQueSkgPD0gTWF0aC5hYnModGhpcy55KTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCB0b1N0cmluZygpOiBTdHJpbmdcclxuICBcdC8vIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBvaW50IGZvciBkZWJ1Z2dpbmcgcHVycG9zZXMuXHJcbiAgXHR0b1N0cmluZzogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gJ1BvaW50KCcgK1xyXG4gIFx0XHQgICAgICAgIGZvcm1hdE51bSh0aGlzLngpICsgJywgJyArXHJcbiAgXHRcdCAgICAgICAgZm9ybWF0TnVtKHRoaXMueSkgKyAnKSc7XHJcbiAgXHR9XHJcbiAgfTtcclxuXHJcbiAgLy8gQGZhY3RvcnkgTC5wb2ludCh4OiBOdW1iZXIsIHk6IE51bWJlciwgcm91bmQ/OiBCb29sZWFuKVxyXG4gIC8vIENyZWF0ZXMgYSBQb2ludCBvYmplY3Qgd2l0aCB0aGUgZ2l2ZW4gYHhgIGFuZCBgeWAgY29vcmRpbmF0ZXMuIElmIG9wdGlvbmFsIGByb3VuZGAgaXMgc2V0IHRvIHRydWUsIHJvdW5kcyB0aGUgYHhgIGFuZCBgeWAgdmFsdWVzLlxyXG5cclxuICAvLyBAYWx0ZXJuYXRpdmVcclxuICAvLyBAZmFjdG9yeSBMLnBvaW50KGNvb3JkczogTnVtYmVyW10pXHJcbiAgLy8gRXhwZWN0cyBhbiBhcnJheSBvZiB0aGUgZm9ybSBgW3gsIHldYCBpbnN0ZWFkLlxyXG5cclxuICAvLyBAYWx0ZXJuYXRpdmVcclxuICAvLyBAZmFjdG9yeSBMLnBvaW50KGNvb3JkczogT2JqZWN0KVxyXG4gIC8vIEV4cGVjdHMgYSBwbGFpbiBvYmplY3Qgb2YgdGhlIGZvcm0gYHt4OiBOdW1iZXIsIHk6IE51bWJlcn1gIGluc3RlYWQuXHJcbiAgZnVuY3Rpb24gdG9Qb2ludCh4LCB5LCByb3VuZCkge1xyXG4gIFx0aWYgKHggaW5zdGFuY2VvZiBQb2ludCkge1xyXG4gIFx0XHRyZXR1cm4geDtcclxuICBcdH1cclxuICBcdGlmIChpc0FycmF5KHgpKSB7XHJcbiAgXHRcdHJldHVybiBuZXcgUG9pbnQoeFswXSwgeFsxXSk7XHJcbiAgXHR9XHJcbiAgXHRpZiAoeCA9PT0gdW5kZWZpbmVkIHx8IHggPT09IG51bGwpIHtcclxuICBcdFx0cmV0dXJuIHg7XHJcbiAgXHR9XHJcbiAgXHRpZiAodHlwZW9mIHggPT09ICdvYmplY3QnICYmICd4JyBpbiB4ICYmICd5JyBpbiB4KSB7XHJcbiAgXHRcdHJldHVybiBuZXcgUG9pbnQoeC54LCB4LnkpO1xyXG4gIFx0fVxyXG4gIFx0cmV0dXJuIG5ldyBQb2ludCh4LCB5LCByb3VuZCk7XHJcbiAgfVxuXG4gIC8qXHJcbiAgICogQGNsYXNzIEJvdW5kc1xyXG4gICAqIEBha2EgTC5Cb3VuZHNcclxuICAgKlxyXG4gICAqIFJlcHJlc2VudHMgYSByZWN0YW5ndWxhciBhcmVhIGluIHBpeGVsIGNvb3JkaW5hdGVzLlxyXG4gICAqXHJcbiAgICogQGV4YW1wbGVcclxuICAgKlxyXG4gICAqIGBgYGpzXHJcbiAgICogdmFyIHAxID0gTC5wb2ludCgxMCwgMTApLFxyXG4gICAqIHAyID0gTC5wb2ludCg0MCwgNjApLFxyXG4gICAqIGJvdW5kcyA9IEwuYm91bmRzKHAxLCBwMik7XHJcbiAgICogYGBgXHJcbiAgICpcclxuICAgKiBBbGwgTGVhZmxldCBtZXRob2RzIHRoYXQgYWNjZXB0IGBCb3VuZHNgIG9iamVjdHMgYWxzbyBhY2NlcHQgdGhlbSBpbiBhIHNpbXBsZSBBcnJheSBmb3JtICh1bmxlc3Mgbm90ZWQgb3RoZXJ3aXNlKSwgc28gdGhlIGJvdW5kcyBleGFtcGxlIGFib3ZlIGNhbiBiZSBwYXNzZWQgbGlrZSB0aGlzOlxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiBvdGhlckJvdW5kcy5pbnRlcnNlY3RzKFtbMTAsIDEwXSwgWzQwLCA2MF1dKTtcclxuICAgKiBgYGBcclxuICAgKlxyXG4gICAqIE5vdGUgdGhhdCBgQm91bmRzYCBkb2VzIG5vdCBpbmhlcml0IGZyb20gTGVhZmxldCdzIGBDbGFzc2Agb2JqZWN0LFxyXG4gICAqIHdoaWNoIG1lYW5zIG5ldyBjbGFzc2VzIGNhbid0IGluaGVyaXQgZnJvbSBpdCwgYW5kIG5ldyBtZXRob2RzXHJcbiAgICogY2FuJ3QgYmUgYWRkZWQgdG8gaXQgd2l0aCB0aGUgYGluY2x1ZGVgIGZ1bmN0aW9uLlxyXG4gICAqL1xyXG5cclxuICBmdW5jdGlvbiBCb3VuZHMoYSwgYikge1xyXG4gIFx0aWYgKCFhKSB7IHJldHVybjsgfVxyXG5cclxuICBcdHZhciBwb2ludHMgPSBiID8gW2EsIGJdIDogYTtcclxuXHJcbiAgXHRmb3IgKHZhciBpID0gMCwgbGVuID0gcG9pbnRzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdHRoaXMuZXh0ZW5kKHBvaW50c1tpXSk7XHJcbiAgXHR9XHJcbiAgfVxyXG5cclxuICBCb3VuZHMucHJvdG90eXBlID0ge1xyXG4gIFx0Ly8gQG1ldGhvZCBleHRlbmQocG9pbnQ6IFBvaW50KTogdGhpc1xyXG4gIFx0Ly8gRXh0ZW5kcyB0aGUgYm91bmRzIHRvIGNvbnRhaW4gdGhlIGdpdmVuIHBvaW50LlxyXG5cclxuICBcdC8vIEBhbHRlcm5hdGl2ZVxyXG4gIFx0Ly8gQG1ldGhvZCBleHRlbmQob3RoZXJCb3VuZHM6IEJvdW5kcyk6IHRoaXNcclxuICBcdC8vIEV4dGVuZCB0aGUgYm91bmRzIHRvIGNvbnRhaW4gdGhlIGdpdmVuIGJvdW5kc1xyXG4gIFx0ZXh0ZW5kOiBmdW5jdGlvbiAob2JqKSB7XHJcbiAgXHRcdHZhciBtaW4yLCBtYXgyO1xyXG4gIFx0XHRpZiAoIW9iaikgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuICBcdFx0aWYgKG9iaiBpbnN0YW5jZW9mIFBvaW50IHx8IHR5cGVvZiBvYmpbMF0gPT09ICdudW1iZXInIHx8ICd4JyBpbiBvYmopIHtcclxuICBcdFx0XHRtaW4yID0gbWF4MiA9IHRvUG9pbnQob2JqKTtcclxuICBcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRvYmogPSB0b0JvdW5kcyhvYmopO1xyXG4gIFx0XHRcdG1pbjIgPSBvYmoubWluO1xyXG4gIFx0XHRcdG1heDIgPSBvYmoubWF4O1xyXG5cclxuICBcdFx0XHRpZiAoIW1pbjIgfHwgIW1heDIpIHsgcmV0dXJuIHRoaXM7IH1cclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gQHByb3BlcnR5IG1pbjogUG9pbnRcclxuICBcdFx0Ly8gVGhlIHRvcCBsZWZ0IGNvcm5lciBvZiB0aGUgcmVjdGFuZ2xlLlxyXG4gIFx0XHQvLyBAcHJvcGVydHkgbWF4OiBQb2ludFxyXG4gIFx0XHQvLyBUaGUgYm90dG9tIHJpZ2h0IGNvcm5lciBvZiB0aGUgcmVjdGFuZ2xlLlxyXG4gIFx0XHRpZiAoIXRoaXMubWluICYmICF0aGlzLm1heCkge1xyXG4gIFx0XHRcdHRoaXMubWluID0gbWluMi5jbG9uZSgpO1xyXG4gIFx0XHRcdHRoaXMubWF4ID0gbWF4Mi5jbG9uZSgpO1xyXG4gIFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdHRoaXMubWluLnggPSBNYXRoLm1pbihtaW4yLngsIHRoaXMubWluLngpO1xyXG4gIFx0XHRcdHRoaXMubWF4LnggPSBNYXRoLm1heChtYXgyLngsIHRoaXMubWF4LngpO1xyXG4gIFx0XHRcdHRoaXMubWluLnkgPSBNYXRoLm1pbihtaW4yLnksIHRoaXMubWluLnkpO1xyXG4gIFx0XHRcdHRoaXMubWF4LnkgPSBNYXRoLm1heChtYXgyLnksIHRoaXMubWF4LnkpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldENlbnRlcihyb3VuZD86IEJvb2xlYW4pOiBQb2ludFxyXG4gIFx0Ly8gUmV0dXJucyB0aGUgY2VudGVyIHBvaW50IG9mIHRoZSBib3VuZHMuXHJcbiAgXHRnZXRDZW50ZXI6IGZ1bmN0aW9uIChyb3VuZCkge1xyXG4gIFx0XHRyZXR1cm4gdG9Qb2ludChcclxuICBcdFx0ICAgICAgICAodGhpcy5taW4ueCArIHRoaXMubWF4LngpIC8gMixcclxuICBcdFx0ICAgICAgICAodGhpcy5taW4ueSArIHRoaXMubWF4LnkpIC8gMiwgcm91bmQpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldEJvdHRvbUxlZnQoKTogUG9pbnRcclxuICBcdC8vIFJldHVybnMgdGhlIGJvdHRvbS1sZWZ0IHBvaW50IG9mIHRoZSBib3VuZHMuXHJcbiAgXHRnZXRCb3R0b21MZWZ0OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0b1BvaW50KHRoaXMubWluLngsIHRoaXMubWF4LnkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldFRvcFJpZ2h0KCk6IFBvaW50XHJcbiAgXHQvLyBSZXR1cm5zIHRoZSB0b3AtcmlnaHQgcG9pbnQgb2YgdGhlIGJvdW5kcy5cclxuICBcdGdldFRvcFJpZ2h0OiBmdW5jdGlvbiAoKSB7IC8vIC0+IFBvaW50XHJcbiAgXHRcdHJldHVybiB0b1BvaW50KHRoaXMubWF4LngsIHRoaXMubWluLnkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldFRvcExlZnQoKTogUG9pbnRcclxuICBcdC8vIFJldHVybnMgdGhlIHRvcC1sZWZ0IHBvaW50IG9mIHRoZSBib3VuZHMgKGkuZS4gW2B0aGlzLm1pbmBdKCNib3VuZHMtbWluKSkuXHJcbiAgXHRnZXRUb3BMZWZ0OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLm1pbjsgLy8gbGVmdCwgdG9wXHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0Qm90dG9tUmlnaHQoKTogUG9pbnRcclxuICBcdC8vIFJldHVybnMgdGhlIGJvdHRvbS1yaWdodCBwb2ludCBvZiB0aGUgYm91bmRzIChpLmUuIFtgdGhpcy5tYXhgXSgjYm91bmRzLW1heCkpLlxyXG4gIFx0Z2V0Qm90dG9tUmlnaHQ6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMubWF4OyAvLyByaWdodCwgYm90dG9tXHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0U2l6ZSgpOiBQb2ludFxyXG4gIFx0Ly8gUmV0dXJucyB0aGUgc2l6ZSBvZiB0aGUgZ2l2ZW4gYm91bmRzXHJcbiAgXHRnZXRTaXplOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLm1heC5zdWJ0cmFjdCh0aGlzLm1pbik7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgY29udGFpbnMob3RoZXJCb3VuZHM6IEJvdW5kcyk6IEJvb2xlYW5cclxuICBcdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSByZWN0YW5nbGUgY29udGFpbnMgdGhlIGdpdmVuIG9uZS5cclxuICBcdC8vIEBhbHRlcm5hdGl2ZVxyXG4gIFx0Ly8gQG1ldGhvZCBjb250YWlucyhwb2ludDogUG9pbnQpOiBCb29sZWFuXHJcbiAgXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcmVjdGFuZ2xlIGNvbnRhaW5zIHRoZSBnaXZlbiBwb2ludC5cclxuICBcdGNvbnRhaW5zOiBmdW5jdGlvbiAob2JqKSB7XHJcbiAgXHRcdHZhciBtaW4sIG1heDtcclxuXHJcbiAgXHRcdGlmICh0eXBlb2Ygb2JqWzBdID09PSAnbnVtYmVyJyB8fCBvYmogaW5zdGFuY2VvZiBQb2ludCkge1xyXG4gIFx0XHRcdG9iaiA9IHRvUG9pbnQob2JqKTtcclxuICBcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRvYmogPSB0b0JvdW5kcyhvYmopO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAob2JqIGluc3RhbmNlb2YgQm91bmRzKSB7XHJcbiAgXHRcdFx0bWluID0gb2JqLm1pbjtcclxuICBcdFx0XHRtYXggPSBvYmoubWF4O1xyXG4gIFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdG1pbiA9IG1heCA9IG9iajtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0cmV0dXJuIChtaW4ueCA+PSB0aGlzLm1pbi54KSAmJlxyXG4gIFx0XHQgICAgICAgKG1heC54IDw9IHRoaXMubWF4LngpICYmXHJcbiAgXHRcdCAgICAgICAobWluLnkgPj0gdGhpcy5taW4ueSkgJiZcclxuICBcdFx0ICAgICAgIChtYXgueSA8PSB0aGlzLm1heC55KTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBpbnRlcnNlY3RzKG90aGVyQm91bmRzOiBCb3VuZHMpOiBCb29sZWFuXHJcbiAgXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcmVjdGFuZ2xlIGludGVyc2VjdHMgdGhlIGdpdmVuIGJvdW5kcy4gVHdvIGJvdW5kc1xyXG4gIFx0Ly8gaW50ZXJzZWN0IGlmIHRoZXkgaGF2ZSBhdCBsZWFzdCBvbmUgcG9pbnQgaW4gY29tbW9uLlxyXG4gIFx0aW50ZXJzZWN0czogZnVuY3Rpb24gKGJvdW5kcykgeyAvLyAoQm91bmRzKSAtPiBCb29sZWFuXHJcbiAgXHRcdGJvdW5kcyA9IHRvQm91bmRzKGJvdW5kcyk7XHJcblxyXG4gIFx0XHR2YXIgbWluID0gdGhpcy5taW4sXHJcbiAgXHRcdCAgICBtYXggPSB0aGlzLm1heCxcclxuICBcdFx0ICAgIG1pbjIgPSBib3VuZHMubWluLFxyXG4gIFx0XHQgICAgbWF4MiA9IGJvdW5kcy5tYXgsXHJcbiAgXHRcdCAgICB4SW50ZXJzZWN0cyA9IChtYXgyLnggPj0gbWluLngpICYmIChtaW4yLnggPD0gbWF4LngpLFxyXG4gIFx0XHQgICAgeUludGVyc2VjdHMgPSAobWF4Mi55ID49IG1pbi55KSAmJiAobWluMi55IDw9IG1heC55KTtcclxuXHJcbiAgXHRcdHJldHVybiB4SW50ZXJzZWN0cyAmJiB5SW50ZXJzZWN0cztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBvdmVybGFwcyhvdGhlckJvdW5kczogQm91bmRzKTogQm9vbGVhblxyXG4gIFx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHJlY3RhbmdsZSBvdmVybGFwcyB0aGUgZ2l2ZW4gYm91bmRzLiBUd28gYm91bmRzXHJcbiAgXHQvLyBvdmVybGFwIGlmIHRoZWlyIGludGVyc2VjdGlvbiBpcyBhbiBhcmVhLlxyXG4gIFx0b3ZlcmxhcHM6IGZ1bmN0aW9uIChib3VuZHMpIHsgLy8gKEJvdW5kcykgLT4gQm9vbGVhblxyXG4gIFx0XHRib3VuZHMgPSB0b0JvdW5kcyhib3VuZHMpO1xyXG5cclxuICBcdFx0dmFyIG1pbiA9IHRoaXMubWluLFxyXG4gIFx0XHQgICAgbWF4ID0gdGhpcy5tYXgsXHJcbiAgXHRcdCAgICBtaW4yID0gYm91bmRzLm1pbixcclxuICBcdFx0ICAgIG1heDIgPSBib3VuZHMubWF4LFxyXG4gIFx0XHQgICAgeE92ZXJsYXBzID0gKG1heDIueCA+IG1pbi54KSAmJiAobWluMi54IDwgbWF4LngpLFxyXG4gIFx0XHQgICAgeU92ZXJsYXBzID0gKG1heDIueSA+IG1pbi55KSAmJiAobWluMi55IDwgbWF4LnkpO1xyXG5cclxuICBcdFx0cmV0dXJuIHhPdmVybGFwcyAmJiB5T3ZlcmxhcHM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgaXNWYWxpZCgpOiBCb29sZWFuXHJcbiAgXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgYm91bmRzIGFyZSBwcm9wZXJseSBpbml0aWFsaXplZC5cclxuICBcdGlzVmFsaWQ6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuICEhKHRoaXMubWluICYmIHRoaXMubWF4KTtcclxuICBcdH0sXHJcblxyXG5cclxuICBcdC8vIEBtZXRob2QgcGFkKGJ1ZmZlclJhdGlvOiBOdW1iZXIpOiBCb3VuZHNcclxuICBcdC8vIFJldHVybnMgYm91bmRzIGNyZWF0ZWQgYnkgZXh0ZW5kaW5nIG9yIHJldHJhY3RpbmcgdGhlIGN1cnJlbnQgYm91bmRzIGJ5IGEgZ2l2ZW4gcmF0aW8gaW4gZWFjaCBkaXJlY3Rpb24uXHJcbiAgXHQvLyBGb3IgZXhhbXBsZSwgYSByYXRpbyBvZiAwLjUgZXh0ZW5kcyB0aGUgYm91bmRzIGJ5IDUwJSBpbiBlYWNoIGRpcmVjdGlvbi5cclxuICBcdC8vIE5lZ2F0aXZlIHZhbHVlcyB3aWxsIHJldHJhY3QgdGhlIGJvdW5kcy5cclxuICBcdHBhZDogZnVuY3Rpb24gKGJ1ZmZlclJhdGlvKSB7XHJcbiAgXHRcdHZhciBtaW4gPSB0aGlzLm1pbixcclxuICBcdFx0bWF4ID0gdGhpcy5tYXgsXHJcbiAgXHRcdGhlaWdodEJ1ZmZlciA9IE1hdGguYWJzKG1pbi54IC0gbWF4LngpICogYnVmZmVyUmF0aW8sXHJcbiAgXHRcdHdpZHRoQnVmZmVyID0gTWF0aC5hYnMobWluLnkgLSBtYXgueSkgKiBidWZmZXJSYXRpbztcclxuXHJcblxyXG4gIFx0XHRyZXR1cm4gdG9Cb3VuZHMoXHJcbiAgXHRcdFx0dG9Qb2ludChtaW4ueCAtIGhlaWdodEJ1ZmZlciwgbWluLnkgLSB3aWR0aEJ1ZmZlciksXHJcbiAgXHRcdFx0dG9Qb2ludChtYXgueCArIGhlaWdodEJ1ZmZlciwgbWF4LnkgKyB3aWR0aEJ1ZmZlcikpO1xyXG4gIFx0fSxcclxuXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBlcXVhbHMob3RoZXJCb3VuZHM6IEJvdW5kcyk6IEJvb2xlYW5cclxuICBcdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSByZWN0YW5nbGUgaXMgZXF1aXZhbGVudCB0byB0aGUgZ2l2ZW4gYm91bmRzLlxyXG4gIFx0ZXF1YWxzOiBmdW5jdGlvbiAoYm91bmRzKSB7XHJcbiAgXHRcdGlmICghYm91bmRzKSB7IHJldHVybiBmYWxzZTsgfVxyXG5cclxuICBcdFx0Ym91bmRzID0gdG9Cb3VuZHMoYm91bmRzKTtcclxuXHJcbiAgXHRcdHJldHVybiB0aGlzLm1pbi5lcXVhbHMoYm91bmRzLmdldFRvcExlZnQoKSkgJiZcclxuICBcdFx0XHR0aGlzLm1heC5lcXVhbHMoYm91bmRzLmdldEJvdHRvbVJpZ2h0KCkpO1xyXG4gIFx0fSxcclxuICB9O1xyXG5cclxuXHJcbiAgLy8gQGZhY3RvcnkgTC5ib3VuZHMoY29ybmVyMTogUG9pbnQsIGNvcm5lcjI6IFBvaW50KVxyXG4gIC8vIENyZWF0ZXMgYSBCb3VuZHMgb2JqZWN0IGZyb20gdHdvIGNvcm5lcnMgY29vcmRpbmF0ZSBwYWlycy5cclxuICAvLyBAYWx0ZXJuYXRpdmVcclxuICAvLyBAZmFjdG9yeSBMLmJvdW5kcyhwb2ludHM6IFBvaW50W10pXHJcbiAgLy8gQ3JlYXRlcyBhIEJvdW5kcyBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gYXJyYXkgb2YgcG9pbnRzLlxyXG4gIGZ1bmN0aW9uIHRvQm91bmRzKGEsIGIpIHtcclxuICBcdGlmICghYSB8fCBhIGluc3RhbmNlb2YgQm91bmRzKSB7XHJcbiAgXHRcdHJldHVybiBhO1xyXG4gIFx0fVxyXG4gIFx0cmV0dXJuIG5ldyBCb3VuZHMoYSwgYik7XHJcbiAgfVxuXG4gIC8qXHJcbiAgICogQGNsYXNzIExhdExuZ0JvdW5kc1xyXG4gICAqIEBha2EgTC5MYXRMbmdCb3VuZHNcclxuICAgKlxyXG4gICAqIFJlcHJlc2VudHMgYSByZWN0YW5ndWxhciBnZW9ncmFwaGljYWwgYXJlYSBvbiBhIG1hcC5cclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICpcclxuICAgKiBgYGBqc1xyXG4gICAqIHZhciBjb3JuZXIxID0gTC5sYXRMbmcoNDAuNzEyLCAtNzQuMjI3KSxcclxuICAgKiBjb3JuZXIyID0gTC5sYXRMbmcoNDAuNzc0LCAtNzQuMTI1KSxcclxuICAgKiBib3VuZHMgPSBMLmxhdExuZ0JvdW5kcyhjb3JuZXIxLCBjb3JuZXIyKTtcclxuICAgKiBgYGBcclxuICAgKlxyXG4gICAqIEFsbCBMZWFmbGV0IG1ldGhvZHMgdGhhdCBhY2NlcHQgTGF0TG5nQm91bmRzIG9iamVjdHMgYWxzbyBhY2NlcHQgdGhlbSBpbiBhIHNpbXBsZSBBcnJheSBmb3JtICh1bmxlc3Mgbm90ZWQgb3RoZXJ3aXNlKSwgc28gdGhlIGJvdW5kcyBleGFtcGxlIGFib3ZlIGNhbiBiZSBwYXNzZWQgbGlrZSB0aGlzOlxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiBtYXAuZml0Qm91bmRzKFtcclxuICAgKiBcdFs0MC43MTIsIC03NC4yMjddLFxyXG4gICAqIFx0WzQwLjc3NCwgLTc0LjEyNV1cclxuICAgKiBdKTtcclxuICAgKiBgYGBcclxuICAgKlxyXG4gICAqIENhdXRpb246IGlmIHRoZSBhcmVhIGNyb3NzZXMgdGhlIGFudGltZXJpZGlhbiAob2Z0ZW4gY29uZnVzZWQgd2l0aCB0aGUgSW50ZXJuYXRpb25hbCBEYXRlIExpbmUpLCB5b3UgbXVzdCBzcGVjaWZ5IGNvcm5lcnMgX291dHNpZGVfIHRoZSBbLTE4MCwgMTgwXSBkZWdyZWVzIGxvbmdpdHVkZSByYW5nZS5cclxuICAgKlxyXG4gICAqIE5vdGUgdGhhdCBgTGF0TG5nQm91bmRzYCBkb2VzIG5vdCBpbmhlcml0IGZyb20gTGVhZmxldCdzIGBDbGFzc2Agb2JqZWN0LFxyXG4gICAqIHdoaWNoIG1lYW5zIG5ldyBjbGFzc2VzIGNhbid0IGluaGVyaXQgZnJvbSBpdCwgYW5kIG5ldyBtZXRob2RzXHJcbiAgICogY2FuJ3QgYmUgYWRkZWQgdG8gaXQgd2l0aCB0aGUgYGluY2x1ZGVgIGZ1bmN0aW9uLlxyXG4gICAqL1xyXG5cclxuICBmdW5jdGlvbiBMYXRMbmdCb3VuZHMoY29ybmVyMSwgY29ybmVyMikgeyAvLyAoTGF0TG5nLCBMYXRMbmcpIG9yIChMYXRMbmdbXSlcclxuICBcdGlmICghY29ybmVyMSkgeyByZXR1cm47IH1cclxuXHJcbiAgXHR2YXIgbGF0bG5ncyA9IGNvcm5lcjIgPyBbY29ybmVyMSwgY29ybmVyMl0gOiBjb3JuZXIxO1xyXG5cclxuICBcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBsYXRsbmdzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdHRoaXMuZXh0ZW5kKGxhdGxuZ3NbaV0pO1xyXG4gIFx0fVxyXG4gIH1cclxuXHJcbiAgTGF0TG5nQm91bmRzLnByb3RvdHlwZSA9IHtcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGV4dGVuZChsYXRsbmc6IExhdExuZyk6IHRoaXNcclxuICBcdC8vIEV4dGVuZCB0aGUgYm91bmRzIHRvIGNvbnRhaW4gdGhlIGdpdmVuIHBvaW50XHJcblxyXG4gIFx0Ly8gQGFsdGVybmF0aXZlXHJcbiAgXHQvLyBAbWV0aG9kIGV4dGVuZChvdGhlckJvdW5kczogTGF0TG5nQm91bmRzKTogdGhpc1xyXG4gIFx0Ly8gRXh0ZW5kIHRoZSBib3VuZHMgdG8gY29udGFpbiB0aGUgZ2l2ZW4gYm91bmRzXHJcbiAgXHRleHRlbmQ6IGZ1bmN0aW9uIChvYmopIHtcclxuICBcdFx0dmFyIHN3ID0gdGhpcy5fc291dGhXZXN0LFxyXG4gIFx0XHQgICAgbmUgPSB0aGlzLl9ub3J0aEVhc3QsXHJcbiAgXHRcdCAgICBzdzIsIG5lMjtcclxuXHJcbiAgXHRcdGlmIChvYmogaW5zdGFuY2VvZiBMYXRMbmcpIHtcclxuICBcdFx0XHRzdzIgPSBvYmo7XHJcbiAgXHRcdFx0bmUyID0gb2JqO1xyXG5cclxuICBcdFx0fSBlbHNlIGlmIChvYmogaW5zdGFuY2VvZiBMYXRMbmdCb3VuZHMpIHtcclxuICBcdFx0XHRzdzIgPSBvYmouX3NvdXRoV2VzdDtcclxuICBcdFx0XHRuZTIgPSBvYmouX25vcnRoRWFzdDtcclxuXHJcbiAgXHRcdFx0aWYgKCFzdzIgfHwgIW5lMikgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuICBcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRyZXR1cm4gb2JqID8gdGhpcy5leHRlbmQodG9MYXRMbmcob2JqKSB8fCB0b0xhdExuZ0JvdW5kcyhvYmopKSA6IHRoaXM7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmICghc3cgJiYgIW5lKSB7XHJcbiAgXHRcdFx0dGhpcy5fc291dGhXZXN0ID0gbmV3IExhdExuZyhzdzIubGF0LCBzdzIubG5nKTtcclxuICBcdFx0XHR0aGlzLl9ub3J0aEVhc3QgPSBuZXcgTGF0TG5nKG5lMi5sYXQsIG5lMi5sbmcpO1xyXG4gIFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdHN3LmxhdCA9IE1hdGgubWluKHN3Mi5sYXQsIHN3LmxhdCk7XHJcbiAgXHRcdFx0c3cubG5nID0gTWF0aC5taW4oc3cyLmxuZywgc3cubG5nKTtcclxuICBcdFx0XHRuZS5sYXQgPSBNYXRoLm1heChuZTIubGF0LCBuZS5sYXQpO1xyXG4gIFx0XHRcdG5lLmxuZyA9IE1hdGgubWF4KG5lMi5sbmcsIG5lLmxuZyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHBhZChidWZmZXJSYXRpbzogTnVtYmVyKTogTGF0TG5nQm91bmRzXHJcbiAgXHQvLyBSZXR1cm5zIGJvdW5kcyBjcmVhdGVkIGJ5IGV4dGVuZGluZyBvciByZXRyYWN0aW5nIHRoZSBjdXJyZW50IGJvdW5kcyBieSBhIGdpdmVuIHJhdGlvIGluIGVhY2ggZGlyZWN0aW9uLlxyXG4gIFx0Ly8gRm9yIGV4YW1wbGUsIGEgcmF0aW8gb2YgMC41IGV4dGVuZHMgdGhlIGJvdW5kcyBieSA1MCUgaW4gZWFjaCBkaXJlY3Rpb24uXHJcbiAgXHQvLyBOZWdhdGl2ZSB2YWx1ZXMgd2lsbCByZXRyYWN0IHRoZSBib3VuZHMuXHJcbiAgXHRwYWQ6IGZ1bmN0aW9uIChidWZmZXJSYXRpbykge1xyXG4gIFx0XHR2YXIgc3cgPSB0aGlzLl9zb3V0aFdlc3QsXHJcbiAgXHRcdCAgICBuZSA9IHRoaXMuX25vcnRoRWFzdCxcclxuICBcdFx0ICAgIGhlaWdodEJ1ZmZlciA9IE1hdGguYWJzKHN3LmxhdCAtIG5lLmxhdCkgKiBidWZmZXJSYXRpbyxcclxuICBcdFx0ICAgIHdpZHRoQnVmZmVyID0gTWF0aC5hYnMoc3cubG5nIC0gbmUubG5nKSAqIGJ1ZmZlclJhdGlvO1xyXG5cclxuICBcdFx0cmV0dXJuIG5ldyBMYXRMbmdCb3VuZHMoXHJcbiAgXHRcdCAgICAgICAgbmV3IExhdExuZyhzdy5sYXQgLSBoZWlnaHRCdWZmZXIsIHN3LmxuZyAtIHdpZHRoQnVmZmVyKSxcclxuICBcdFx0ICAgICAgICBuZXcgTGF0TG5nKG5lLmxhdCArIGhlaWdodEJ1ZmZlciwgbmUubG5nICsgd2lkdGhCdWZmZXIpKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRDZW50ZXIoKTogTGF0TG5nXHJcbiAgXHQvLyBSZXR1cm5zIHRoZSBjZW50ZXIgcG9pbnQgb2YgdGhlIGJvdW5kcy5cclxuICBcdGdldENlbnRlcjogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gbmV3IExhdExuZyhcclxuICBcdFx0ICAgICAgICAodGhpcy5fc291dGhXZXN0LmxhdCArIHRoaXMuX25vcnRoRWFzdC5sYXQpIC8gMixcclxuICBcdFx0ICAgICAgICAodGhpcy5fc291dGhXZXN0LmxuZyArIHRoaXMuX25vcnRoRWFzdC5sbmcpIC8gMik7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0U291dGhXZXN0KCk6IExhdExuZ1xyXG4gIFx0Ly8gUmV0dXJucyB0aGUgc291dGgtd2VzdCBwb2ludCBvZiB0aGUgYm91bmRzLlxyXG4gIFx0Z2V0U291dGhXZXN0OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLl9zb3V0aFdlc3Q7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0Tm9ydGhFYXN0KCk6IExhdExuZ1xyXG4gIFx0Ly8gUmV0dXJucyB0aGUgbm9ydGgtZWFzdCBwb2ludCBvZiB0aGUgYm91bmRzLlxyXG4gIFx0Z2V0Tm9ydGhFYXN0OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLl9ub3J0aEVhc3Q7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0Tm9ydGhXZXN0KCk6IExhdExuZ1xyXG4gIFx0Ly8gUmV0dXJucyB0aGUgbm9ydGgtd2VzdCBwb2ludCBvZiB0aGUgYm91bmRzLlxyXG4gIFx0Z2V0Tm9ydGhXZXN0OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiBuZXcgTGF0TG5nKHRoaXMuZ2V0Tm9ydGgoKSwgdGhpcy5nZXRXZXN0KCkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldFNvdXRoRWFzdCgpOiBMYXRMbmdcclxuICBcdC8vIFJldHVybnMgdGhlIHNvdXRoLWVhc3QgcG9pbnQgb2YgdGhlIGJvdW5kcy5cclxuICBcdGdldFNvdXRoRWFzdDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gbmV3IExhdExuZyh0aGlzLmdldFNvdXRoKCksIHRoaXMuZ2V0RWFzdCgpKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRXZXN0KCk6IE51bWJlclxyXG4gIFx0Ly8gUmV0dXJucyB0aGUgd2VzdCBsb25naXR1ZGUgb2YgdGhlIGJvdW5kc1xyXG4gIFx0Z2V0V2VzdDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5fc291dGhXZXN0LmxuZztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRTb3V0aCgpOiBOdW1iZXJcclxuICBcdC8vIFJldHVybnMgdGhlIHNvdXRoIGxhdGl0dWRlIG9mIHRoZSBib3VuZHNcclxuICBcdGdldFNvdXRoOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLl9zb3V0aFdlc3QubGF0O1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldEVhc3QoKTogTnVtYmVyXHJcbiAgXHQvLyBSZXR1cm5zIHRoZSBlYXN0IGxvbmdpdHVkZSBvZiB0aGUgYm91bmRzXHJcbiAgXHRnZXRFYXN0OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLl9ub3J0aEVhc3QubG5nO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldE5vcnRoKCk6IE51bWJlclxyXG4gIFx0Ly8gUmV0dXJucyB0aGUgbm9ydGggbGF0aXR1ZGUgb2YgdGhlIGJvdW5kc1xyXG4gIFx0Z2V0Tm9ydGg6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuX25vcnRoRWFzdC5sYXQ7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgY29udGFpbnMob3RoZXJCb3VuZHM6IExhdExuZ0JvdW5kcyk6IEJvb2xlYW5cclxuICBcdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSByZWN0YW5nbGUgY29udGFpbnMgdGhlIGdpdmVuIG9uZS5cclxuXHJcbiAgXHQvLyBAYWx0ZXJuYXRpdmVcclxuICBcdC8vIEBtZXRob2QgY29udGFpbnMgKGxhdGxuZzogTGF0TG5nKTogQm9vbGVhblxyXG4gIFx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHJlY3RhbmdsZSBjb250YWlucyB0aGUgZ2l2ZW4gcG9pbnQuXHJcbiAgXHRjb250YWluczogZnVuY3Rpb24gKG9iaikgeyAvLyAoTGF0TG5nQm91bmRzKSBvciAoTGF0TG5nKSAtPiBCb29sZWFuXHJcbiAgXHRcdGlmICh0eXBlb2Ygb2JqWzBdID09PSAnbnVtYmVyJyB8fCBvYmogaW5zdGFuY2VvZiBMYXRMbmcgfHwgJ2xhdCcgaW4gb2JqKSB7XHJcbiAgXHRcdFx0b2JqID0gdG9MYXRMbmcob2JqKTtcclxuICBcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRvYmogPSB0b0xhdExuZ0JvdW5kcyhvYmopO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgc3cgPSB0aGlzLl9zb3V0aFdlc3QsXHJcbiAgXHRcdCAgICBuZSA9IHRoaXMuX25vcnRoRWFzdCxcclxuICBcdFx0ICAgIHN3MiwgbmUyO1xyXG5cclxuICBcdFx0aWYgKG9iaiBpbnN0YW5jZW9mIExhdExuZ0JvdW5kcykge1xyXG4gIFx0XHRcdHN3MiA9IG9iai5nZXRTb3V0aFdlc3QoKTtcclxuICBcdFx0XHRuZTIgPSBvYmouZ2V0Tm9ydGhFYXN0KCk7XHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0c3cyID0gbmUyID0gb2JqO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gKHN3Mi5sYXQgPj0gc3cubGF0KSAmJiAobmUyLmxhdCA8PSBuZS5sYXQpICYmXHJcbiAgXHRcdCAgICAgICAoc3cyLmxuZyA+PSBzdy5sbmcpICYmIChuZTIubG5nIDw9IG5lLmxuZyk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgaW50ZXJzZWN0cyhvdGhlckJvdW5kczogTGF0TG5nQm91bmRzKTogQm9vbGVhblxyXG4gIFx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHJlY3RhbmdsZSBpbnRlcnNlY3RzIHRoZSBnaXZlbiBib3VuZHMuIFR3byBib3VuZHMgaW50ZXJzZWN0IGlmIHRoZXkgaGF2ZSBhdCBsZWFzdCBvbmUgcG9pbnQgaW4gY29tbW9uLlxyXG4gIFx0aW50ZXJzZWN0czogZnVuY3Rpb24gKGJvdW5kcykge1xyXG4gIFx0XHRib3VuZHMgPSB0b0xhdExuZ0JvdW5kcyhib3VuZHMpO1xyXG5cclxuICBcdFx0dmFyIHN3ID0gdGhpcy5fc291dGhXZXN0LFxyXG4gIFx0XHQgICAgbmUgPSB0aGlzLl9ub3J0aEVhc3QsXHJcbiAgXHRcdCAgICBzdzIgPSBib3VuZHMuZ2V0U291dGhXZXN0KCksXHJcbiAgXHRcdCAgICBuZTIgPSBib3VuZHMuZ2V0Tm9ydGhFYXN0KCksXHJcblxyXG4gIFx0XHQgICAgbGF0SW50ZXJzZWN0cyA9IChuZTIubGF0ID49IHN3LmxhdCkgJiYgKHN3Mi5sYXQgPD0gbmUubGF0KSxcclxuICBcdFx0ICAgIGxuZ0ludGVyc2VjdHMgPSAobmUyLmxuZyA+PSBzdy5sbmcpICYmIChzdzIubG5nIDw9IG5lLmxuZyk7XHJcblxyXG4gIFx0XHRyZXR1cm4gbGF0SW50ZXJzZWN0cyAmJiBsbmdJbnRlcnNlY3RzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIG92ZXJsYXBzKG90aGVyQm91bmRzOiBMYXRMbmdCb3VuZHMpOiBCb29sZWFuXHJcbiAgXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcmVjdGFuZ2xlIG92ZXJsYXBzIHRoZSBnaXZlbiBib3VuZHMuIFR3byBib3VuZHMgb3ZlcmxhcCBpZiB0aGVpciBpbnRlcnNlY3Rpb24gaXMgYW4gYXJlYS5cclxuICBcdG92ZXJsYXBzOiBmdW5jdGlvbiAoYm91bmRzKSB7XHJcbiAgXHRcdGJvdW5kcyA9IHRvTGF0TG5nQm91bmRzKGJvdW5kcyk7XHJcblxyXG4gIFx0XHR2YXIgc3cgPSB0aGlzLl9zb3V0aFdlc3QsXHJcbiAgXHRcdCAgICBuZSA9IHRoaXMuX25vcnRoRWFzdCxcclxuICBcdFx0ICAgIHN3MiA9IGJvdW5kcy5nZXRTb3V0aFdlc3QoKSxcclxuICBcdFx0ICAgIG5lMiA9IGJvdW5kcy5nZXROb3J0aEVhc3QoKSxcclxuXHJcbiAgXHRcdCAgICBsYXRPdmVybGFwcyA9IChuZTIubGF0ID4gc3cubGF0KSAmJiAoc3cyLmxhdCA8IG5lLmxhdCksXHJcbiAgXHRcdCAgICBsbmdPdmVybGFwcyA9IChuZTIubG5nID4gc3cubG5nKSAmJiAoc3cyLmxuZyA8IG5lLmxuZyk7XHJcblxyXG4gIFx0XHRyZXR1cm4gbGF0T3ZlcmxhcHMgJiYgbG5nT3ZlcmxhcHM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgdG9CQm94U3RyaW5nKCk6IFN0cmluZ1xyXG4gIFx0Ly8gUmV0dXJucyBhIHN0cmluZyB3aXRoIGJvdW5kaW5nIGJveCBjb29yZGluYXRlcyBpbiBhICdzb3V0aHdlc3RfbG5nLHNvdXRod2VzdF9sYXQsbm9ydGhlYXN0X2xuZyxub3J0aGVhc3RfbGF0JyBmb3JtYXQuIFVzZWZ1bCBmb3Igc2VuZGluZyByZXF1ZXN0cyB0byB3ZWIgc2VydmljZXMgdGhhdCByZXR1cm4gZ2VvIGRhdGEuXHJcbiAgXHR0b0JCb3hTdHJpbmc6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIFt0aGlzLmdldFdlc3QoKSwgdGhpcy5nZXRTb3V0aCgpLCB0aGlzLmdldEVhc3QoKSwgdGhpcy5nZXROb3J0aCgpXS5qb2luKCcsJyk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZXF1YWxzKG90aGVyQm91bmRzOiBMYXRMbmdCb3VuZHMsIG1heE1hcmdpbj86IE51bWJlcik6IEJvb2xlYW5cclxuICBcdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSByZWN0YW5nbGUgaXMgZXF1aXZhbGVudCAod2l0aGluIGEgc21hbGwgbWFyZ2luIG9mIGVycm9yKSB0byB0aGUgZ2l2ZW4gYm91bmRzLiBUaGUgbWFyZ2luIG9mIGVycm9yIGNhbiBiZSBvdmVycmlkZGVuIGJ5IHNldHRpbmcgYG1heE1hcmdpbmAgdG8gYSBzbWFsbCBudW1iZXIuXHJcbiAgXHRlcXVhbHM6IGZ1bmN0aW9uIChib3VuZHMsIG1heE1hcmdpbikge1xyXG4gIFx0XHRpZiAoIWJvdW5kcykgeyByZXR1cm4gZmFsc2U7IH1cclxuXHJcbiAgXHRcdGJvdW5kcyA9IHRvTGF0TG5nQm91bmRzKGJvdW5kcyk7XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcy5fc291dGhXZXN0LmVxdWFscyhib3VuZHMuZ2V0U291dGhXZXN0KCksIG1heE1hcmdpbikgJiZcclxuICBcdFx0ICAgICAgIHRoaXMuX25vcnRoRWFzdC5lcXVhbHMoYm91bmRzLmdldE5vcnRoRWFzdCgpLCBtYXhNYXJnaW4pO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGlzVmFsaWQoKTogQm9vbGVhblxyXG4gIFx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGJvdW5kcyBhcmUgcHJvcGVybHkgaW5pdGlhbGl6ZWQuXHJcbiAgXHRpc1ZhbGlkOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiAhISh0aGlzLl9zb3V0aFdlc3QgJiYgdGhpcy5fbm9ydGhFYXN0KTtcclxuICBcdH1cclxuICB9O1xyXG5cclxuICAvLyBUT0RPIEludGVybmF0aW9uYWwgZGF0ZSBsaW5lP1xyXG5cclxuICAvLyBAZmFjdG9yeSBMLmxhdExuZ0JvdW5kcyhjb3JuZXIxOiBMYXRMbmcsIGNvcm5lcjI6IExhdExuZylcclxuICAvLyBDcmVhdGVzIGEgYExhdExuZ0JvdW5kc2Agb2JqZWN0IGJ5IGRlZmluaW5nIHR3byBkaWFnb25hbGx5IG9wcG9zaXRlIGNvcm5lcnMgb2YgdGhlIHJlY3RhbmdsZS5cclxuXHJcbiAgLy8gQGFsdGVybmF0aXZlXHJcbiAgLy8gQGZhY3RvcnkgTC5sYXRMbmdCb3VuZHMobGF0bG5nczogTGF0TG5nW10pXHJcbiAgLy8gQ3JlYXRlcyBhIGBMYXRMbmdCb3VuZHNgIG9iamVjdCBkZWZpbmVkIGJ5IHRoZSBnZW9ncmFwaGljYWwgcG9pbnRzIGl0IGNvbnRhaW5zLiBWZXJ5IHVzZWZ1bCBmb3Igem9vbWluZyB0aGUgbWFwIHRvIGZpdCBhIHBhcnRpY3VsYXIgc2V0IG9mIGxvY2F0aW9ucyB3aXRoIFtgZml0Qm91bmRzYF0oI21hcC1maXRib3VuZHMpLlxyXG4gIGZ1bmN0aW9uIHRvTGF0TG5nQm91bmRzKGEsIGIpIHtcclxuICBcdGlmIChhIGluc3RhbmNlb2YgTGF0TG5nQm91bmRzKSB7XHJcbiAgXHRcdHJldHVybiBhO1xyXG4gIFx0fVxyXG4gIFx0cmV0dXJuIG5ldyBMYXRMbmdCb3VuZHMoYSwgYik7XHJcbiAgfVxuXG4gIC8qIEBjbGFzcyBMYXRMbmdcclxuICAgKiBAYWthIEwuTGF0TG5nXHJcbiAgICpcclxuICAgKiBSZXByZXNlbnRzIGEgZ2VvZ3JhcGhpY2FsIHBvaW50IHdpdGggYSBjZXJ0YWluIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUuXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqXHJcbiAgICogYGBgXHJcbiAgICogdmFyIGxhdGxuZyA9IEwubGF0TG5nKDUwLjUsIDMwLjUpO1xyXG4gICAqIGBgYFxyXG4gICAqXHJcbiAgICogQWxsIExlYWZsZXQgbWV0aG9kcyB0aGF0IGFjY2VwdCBMYXRMbmcgb2JqZWN0cyBhbHNvIGFjY2VwdCB0aGVtIGluIGEgc2ltcGxlIEFycmF5IGZvcm0gYW5kIHNpbXBsZSBvYmplY3QgZm9ybSAodW5sZXNzIG5vdGVkIG90aGVyd2lzZSksIHNvIHRoZXNlIGxpbmVzIGFyZSBlcXVpdmFsZW50OlxyXG4gICAqXHJcbiAgICogYGBgXHJcbiAgICogbWFwLnBhblRvKFs1MCwgMzBdKTtcclxuICAgKiBtYXAucGFuVG8oe2xvbjogMzAsIGxhdDogNTB9KTtcclxuICAgKiBtYXAucGFuVG8oe2xhdDogNTAsIGxuZzogMzB9KTtcclxuICAgKiBtYXAucGFuVG8oTC5sYXRMbmcoNTAsIDMwKSk7XHJcbiAgICogYGBgXHJcbiAgICpcclxuICAgKiBOb3RlIHRoYXQgYExhdExuZ2AgZG9lcyBub3QgaW5oZXJpdCBmcm9tIExlYWZsZXQncyBgQ2xhc3NgIG9iamVjdCxcclxuICAgKiB3aGljaCBtZWFucyBuZXcgY2xhc3NlcyBjYW4ndCBpbmhlcml0IGZyb20gaXQsIGFuZCBuZXcgbWV0aG9kc1xyXG4gICAqIGNhbid0IGJlIGFkZGVkIHRvIGl0IHdpdGggdGhlIGBpbmNsdWRlYCBmdW5jdGlvbi5cclxuICAgKi9cclxuXHJcbiAgZnVuY3Rpb24gTGF0TG5nKGxhdCwgbG5nLCBhbHQpIHtcclxuICBcdGlmIChpc05hTihsYXQpIHx8IGlzTmFOKGxuZykpIHtcclxuICBcdFx0dGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIExhdExuZyBvYmplY3Q6ICgnICsgbGF0ICsgJywgJyArIGxuZyArICcpJyk7XHJcbiAgXHR9XHJcblxyXG4gIFx0Ly8gQHByb3BlcnR5IGxhdDogTnVtYmVyXHJcbiAgXHQvLyBMYXRpdHVkZSBpbiBkZWdyZWVzXHJcbiAgXHR0aGlzLmxhdCA9ICtsYXQ7XHJcblxyXG4gIFx0Ly8gQHByb3BlcnR5IGxuZzogTnVtYmVyXHJcbiAgXHQvLyBMb25naXR1ZGUgaW4gZGVncmVlc1xyXG4gIFx0dGhpcy5sbmcgPSArbG5nO1xyXG5cclxuICBcdC8vIEBwcm9wZXJ0eSBhbHQ6IE51bWJlclxyXG4gIFx0Ly8gQWx0aXR1ZGUgaW4gbWV0ZXJzIChvcHRpb25hbClcclxuICBcdGlmIChhbHQgIT09IHVuZGVmaW5lZCkge1xyXG4gIFx0XHR0aGlzLmFsdCA9ICthbHQ7XHJcbiAgXHR9XHJcbiAgfVxyXG5cclxuICBMYXRMbmcucHJvdG90eXBlID0ge1xyXG4gIFx0Ly8gQG1ldGhvZCBlcXVhbHMob3RoZXJMYXRMbmc6IExhdExuZywgbWF4TWFyZ2luPzogTnVtYmVyKTogQm9vbGVhblxyXG4gIFx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGdpdmVuIGBMYXRMbmdgIHBvaW50IGlzIGF0IHRoZSBzYW1lIHBvc2l0aW9uICh3aXRoaW4gYSBzbWFsbCBtYXJnaW4gb2YgZXJyb3IpLiBUaGUgbWFyZ2luIG9mIGVycm9yIGNhbiBiZSBvdmVycmlkZGVuIGJ5IHNldHRpbmcgYG1heE1hcmdpbmAgdG8gYSBzbWFsbCBudW1iZXIuXHJcbiAgXHRlcXVhbHM6IGZ1bmN0aW9uIChvYmosIG1heE1hcmdpbikge1xyXG4gIFx0XHRpZiAoIW9iaikgeyByZXR1cm4gZmFsc2U7IH1cclxuXHJcbiAgXHRcdG9iaiA9IHRvTGF0TG5nKG9iaik7XHJcblxyXG4gIFx0XHR2YXIgbWFyZ2luID0gTWF0aC5tYXgoXHJcbiAgXHRcdCAgICAgICAgTWF0aC5hYnModGhpcy5sYXQgLSBvYmoubGF0KSxcclxuICBcdFx0ICAgICAgICBNYXRoLmFicyh0aGlzLmxuZyAtIG9iai5sbmcpKTtcclxuXHJcbiAgXHRcdHJldHVybiBtYXJnaW4gPD0gKG1heE1hcmdpbiA9PT0gdW5kZWZpbmVkID8gMS4wRS05IDogbWF4TWFyZ2luKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCB0b1N0cmluZygpOiBTdHJpbmdcclxuICBcdC8vIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBvaW50IChmb3IgZGVidWdnaW5nIHB1cnBvc2VzKS5cclxuICBcdHRvU3RyaW5nOiBmdW5jdGlvbiAocHJlY2lzaW9uKSB7XHJcbiAgXHRcdHJldHVybiAnTGF0TG5nKCcgK1xyXG4gIFx0XHQgICAgICAgIGZvcm1hdE51bSh0aGlzLmxhdCwgcHJlY2lzaW9uKSArICcsICcgK1xyXG4gIFx0XHQgICAgICAgIGZvcm1hdE51bSh0aGlzLmxuZywgcHJlY2lzaW9uKSArICcpJztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBkaXN0YW5jZVRvKG90aGVyTGF0TG5nOiBMYXRMbmcpOiBOdW1iZXJcclxuICBcdC8vIFJldHVybnMgdGhlIGRpc3RhbmNlIChpbiBtZXRlcnMpIHRvIHRoZSBnaXZlbiBgTGF0TG5nYCBjYWxjdWxhdGVkIHVzaW5nIHRoZSBbU3BoZXJpY2FsIExhdyBvZiBDb3NpbmVzXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TcGhlcmljYWxfbGF3X29mX2Nvc2luZXMpLlxyXG4gIFx0ZGlzdGFuY2VUbzogZnVuY3Rpb24gKG90aGVyKSB7XHJcbiAgXHRcdHJldHVybiBFYXJ0aC5kaXN0YW5jZSh0aGlzLCB0b0xhdExuZyhvdGhlcikpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHdyYXAoKTogTGF0TG5nXHJcbiAgXHQvLyBSZXR1cm5zIGEgbmV3IGBMYXRMbmdgIG9iamVjdCB3aXRoIHRoZSBsb25naXR1ZGUgd3JhcHBlZCBzbyBpdCdzIGFsd2F5cyBiZXR3ZWVuIC0xODAgYW5kICsxODAgZGVncmVlcy5cclxuICBcdHdyYXA6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIEVhcnRoLndyYXBMYXRMbmcodGhpcyk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgdG9Cb3VuZHMoc2l6ZUluTWV0ZXJzOiBOdW1iZXIpOiBMYXRMbmdCb3VuZHNcclxuICBcdC8vIFJldHVybnMgYSBuZXcgYExhdExuZ0JvdW5kc2Agb2JqZWN0IGluIHdoaWNoIGVhY2ggYm91bmRhcnkgaXMgYHNpemVJbk1ldGVycy8yYCBtZXRlcnMgYXBhcnQgZnJvbSB0aGUgYExhdExuZ2AuXHJcbiAgXHR0b0JvdW5kczogZnVuY3Rpb24gKHNpemVJbk1ldGVycykge1xyXG4gIFx0XHR2YXIgbGF0QWNjdXJhY3kgPSAxODAgKiBzaXplSW5NZXRlcnMgLyA0MDA3NTAxNyxcclxuICBcdFx0ICAgIGxuZ0FjY3VyYWN5ID0gbGF0QWNjdXJhY3kgLyBNYXRoLmNvcygoTWF0aC5QSSAvIDE4MCkgKiB0aGlzLmxhdCk7XHJcblxyXG4gIFx0XHRyZXR1cm4gdG9MYXRMbmdCb3VuZHMoXHJcbiAgXHRcdCAgICAgICAgW3RoaXMubGF0IC0gbGF0QWNjdXJhY3ksIHRoaXMubG5nIC0gbG5nQWNjdXJhY3ldLFxyXG4gIFx0XHQgICAgICAgIFt0aGlzLmxhdCArIGxhdEFjY3VyYWN5LCB0aGlzLmxuZyArIGxuZ0FjY3VyYWN5XSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdGNsb25lOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiBuZXcgTGF0TG5nKHRoaXMubGF0LCB0aGlzLmxuZywgdGhpcy5hbHQpO1xyXG4gIFx0fVxyXG4gIH07XHJcblxyXG5cclxuXHJcbiAgLy8gQGZhY3RvcnkgTC5sYXRMbmcobGF0aXR1ZGU6IE51bWJlciwgbG9uZ2l0dWRlOiBOdW1iZXIsIGFsdGl0dWRlPzogTnVtYmVyKTogTGF0TG5nXHJcbiAgLy8gQ3JlYXRlcyBhbiBvYmplY3QgcmVwcmVzZW50aW5nIGEgZ2VvZ3JhcGhpY2FsIHBvaW50IHdpdGggdGhlIGdpdmVuIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgKGFuZCBvcHRpb25hbGx5IGFsdGl0dWRlKS5cclxuXHJcbiAgLy8gQGFsdGVybmF0aXZlXHJcbiAgLy8gQGZhY3RvcnkgTC5sYXRMbmcoY29vcmRzOiBBcnJheSk6IExhdExuZ1xyXG4gIC8vIEV4cGVjdHMgYW4gYXJyYXkgb2YgdGhlIGZvcm0gYFtOdW1iZXIsIE51bWJlcl1gIG9yIGBbTnVtYmVyLCBOdW1iZXIsIE51bWJlcl1gIGluc3RlYWQuXHJcblxyXG4gIC8vIEBhbHRlcm5hdGl2ZVxyXG4gIC8vIEBmYWN0b3J5IEwubGF0TG5nKGNvb3JkczogT2JqZWN0KTogTGF0TG5nXHJcbiAgLy8gRXhwZWN0cyBhbiBwbGFpbiBvYmplY3Qgb2YgdGhlIGZvcm0gYHtsYXQ6IE51bWJlciwgbG5nOiBOdW1iZXJ9YCBvciBge2xhdDogTnVtYmVyLCBsbmc6IE51bWJlciwgYWx0OiBOdW1iZXJ9YCBpbnN0ZWFkLlxyXG5cclxuICBmdW5jdGlvbiB0b0xhdExuZyhhLCBiLCBjKSB7XHJcbiAgXHRpZiAoYSBpbnN0YW5jZW9mIExhdExuZykge1xyXG4gIFx0XHRyZXR1cm4gYTtcclxuICBcdH1cclxuICBcdGlmIChpc0FycmF5KGEpICYmIHR5cGVvZiBhWzBdICE9PSAnb2JqZWN0Jykge1xyXG4gIFx0XHRpZiAoYS5sZW5ndGggPT09IDMpIHtcclxuICBcdFx0XHRyZXR1cm4gbmV3IExhdExuZyhhWzBdLCBhWzFdLCBhWzJdKTtcclxuICBcdFx0fVxyXG4gIFx0XHRpZiAoYS5sZW5ndGggPT09IDIpIHtcclxuICBcdFx0XHRyZXR1cm4gbmV3IExhdExuZyhhWzBdLCBhWzFdKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gbnVsbDtcclxuICBcdH1cclxuICBcdGlmIChhID09PSB1bmRlZmluZWQgfHwgYSA9PT0gbnVsbCkge1xyXG4gIFx0XHRyZXR1cm4gYTtcclxuICBcdH1cclxuICBcdGlmICh0eXBlb2YgYSA9PT0gJ29iamVjdCcgJiYgJ2xhdCcgaW4gYSkge1xyXG4gIFx0XHRyZXR1cm4gbmV3IExhdExuZyhhLmxhdCwgJ2xuZycgaW4gYSA/IGEubG5nIDogYS5sb24sIGEuYWx0KTtcclxuICBcdH1cclxuICBcdGlmIChiID09PSB1bmRlZmluZWQpIHtcclxuICBcdFx0cmV0dXJuIG51bGw7XHJcbiAgXHR9XHJcbiAgXHRyZXR1cm4gbmV3IExhdExuZyhhLCBiLCBjKTtcclxuICB9XG5cbiAgLypcclxuICAgKiBAbmFtZXNwYWNlIENSU1xyXG4gICAqIEBjcnMgTC5DUlMuQmFzZVxyXG4gICAqIE9iamVjdCB0aGF0IGRlZmluZXMgY29vcmRpbmF0ZSByZWZlcmVuY2Ugc3lzdGVtcyBmb3IgcHJvamVjdGluZ1xyXG4gICAqIGdlb2dyYXBoaWNhbCBwb2ludHMgaW50byBwaXhlbCAoc2NyZWVuKSBjb29yZGluYXRlcyBhbmQgYmFjayAoYW5kIHRvXHJcbiAgICogY29vcmRpbmF0ZXMgaW4gb3RoZXIgdW5pdHMgZm9yIFtXTVNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1dlYl9NYXBfU2VydmljZSkgc2VydmljZXMpLiBTZWVcclxuICAgKiBbc3BhdGlhbCByZWZlcmVuY2Ugc3lzdGVtXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TcGF0aWFsX3JlZmVyZW5jZV9zeXN0ZW0pLlxyXG4gICAqXHJcbiAgICogTGVhZmxldCBkZWZpbmVzIHRoZSBtb3N0IHVzdWFsIENSU3MgYnkgZGVmYXVsdC4gSWYgeW91IHdhbnQgdG8gdXNlIGFcclxuICAgKiBDUlMgbm90IGRlZmluZWQgYnkgZGVmYXVsdCwgdGFrZSBhIGxvb2sgYXQgdGhlXHJcbiAgICogW1Byb2o0TGVhZmxldF0oaHR0cHM6Ly9naXRodWIuY29tL2thcnRlbmEvUHJvajRMZWFmbGV0KSBwbHVnaW4uXHJcbiAgICpcclxuICAgKiBOb3RlIHRoYXQgdGhlIENSUyBpbnN0YW5jZXMgZG8gbm90IGluaGVyaXQgZnJvbSBMZWFmbGV0J3MgYENsYXNzYCBvYmplY3QsXHJcbiAgICogYW5kIGNhbid0IGJlIGluc3RhbnRpYXRlZC4gQWxzbywgbmV3IGNsYXNzZXMgY2FuJ3QgaW5oZXJpdCBmcm9tIHRoZW0sXHJcbiAgICogYW5kIG1ldGhvZHMgY2FuJ3QgYmUgYWRkZWQgdG8gdGhlbSB3aXRoIHRoZSBgaW5jbHVkZWAgZnVuY3Rpb24uXHJcbiAgICovXHJcblxyXG4gIHZhciBDUlMgPSB7XHJcbiAgXHQvLyBAbWV0aG9kIGxhdExuZ1RvUG9pbnQobGF0bG5nOiBMYXRMbmcsIHpvb206IE51bWJlcik6IFBvaW50XHJcbiAgXHQvLyBQcm9qZWN0cyBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZXMgaW50byBwaXhlbCBjb29yZGluYXRlcyBmb3IgYSBnaXZlbiB6b29tLlxyXG4gIFx0bGF0TG5nVG9Qb2ludDogZnVuY3Rpb24gKGxhdGxuZywgem9vbSkge1xyXG4gIFx0XHR2YXIgcHJvamVjdGVkUG9pbnQgPSB0aGlzLnByb2plY3Rpb24ucHJvamVjdChsYXRsbmcpLFxyXG4gIFx0XHQgICAgc2NhbGUgPSB0aGlzLnNjYWxlKHpvb20pO1xyXG5cclxuICBcdFx0cmV0dXJuIHRoaXMudHJhbnNmb3JtYXRpb24uX3RyYW5zZm9ybShwcm9qZWN0ZWRQb2ludCwgc2NhbGUpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHBvaW50VG9MYXRMbmcocG9pbnQ6IFBvaW50LCB6b29tOiBOdW1iZXIpOiBMYXRMbmdcclxuICBcdC8vIFRoZSBpbnZlcnNlIG9mIGBsYXRMbmdUb1BvaW50YC4gUHJvamVjdHMgcGl4ZWwgY29vcmRpbmF0ZXMgb24gYSBnaXZlblxyXG4gIFx0Ly8gem9vbSBpbnRvIGdlb2dyYXBoaWNhbCBjb29yZGluYXRlcy5cclxuICBcdHBvaW50VG9MYXRMbmc6IGZ1bmN0aW9uIChwb2ludCwgem9vbSkge1xyXG4gIFx0XHR2YXIgc2NhbGUgPSB0aGlzLnNjYWxlKHpvb20pLFxyXG4gIFx0XHQgICAgdW50cmFuc2Zvcm1lZFBvaW50ID0gdGhpcy50cmFuc2Zvcm1hdGlvbi51bnRyYW5zZm9ybShwb2ludCwgc2NhbGUpO1xyXG5cclxuICBcdFx0cmV0dXJuIHRoaXMucHJvamVjdGlvbi51bnByb2plY3QodW50cmFuc2Zvcm1lZFBvaW50KTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBwcm9qZWN0KGxhdGxuZzogTGF0TG5nKTogUG9pbnRcclxuICBcdC8vIFByb2plY3RzIGdlb2dyYXBoaWNhbCBjb29yZGluYXRlcyBpbnRvIGNvb3JkaW5hdGVzIGluIHVuaXRzIGFjY2VwdGVkIGZvclxyXG4gIFx0Ly8gdGhpcyBDUlMgKGUuZy4gbWV0ZXJzIGZvciBFUFNHOjM4NTcsIGZvciBwYXNzaW5nIGl0IHRvIFdNUyBzZXJ2aWNlcykuXHJcbiAgXHRwcm9qZWN0OiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLnByb2plY3Rpb24ucHJvamVjdChsYXRsbmcpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHVucHJvamVjdChwb2ludDogUG9pbnQpOiBMYXRMbmdcclxuICBcdC8vIEdpdmVuIGEgcHJvamVjdGVkIGNvb3JkaW5hdGUgcmV0dXJucyB0aGUgY29ycmVzcG9uZGluZyBMYXRMbmcuXHJcbiAgXHQvLyBUaGUgaW52ZXJzZSBvZiBgcHJvamVjdGAuXHJcbiAgXHR1bnByb2plY3Q6IGZ1bmN0aW9uIChwb2ludCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5wcm9qZWN0aW9uLnVucHJvamVjdChwb2ludCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2NhbGUoem9vbTogTnVtYmVyKTogTnVtYmVyXHJcbiAgXHQvLyBSZXR1cm5zIHRoZSBzY2FsZSB1c2VkIHdoZW4gdHJhbnNmb3JtaW5nIHByb2plY3RlZCBjb29yZGluYXRlcyBpbnRvXHJcbiAgXHQvLyBwaXhlbCBjb29yZGluYXRlcyBmb3IgYSBwYXJ0aWN1bGFyIHpvb20uIEZvciBleGFtcGxlLCBpdCByZXR1cm5zXHJcbiAgXHQvLyBgMjU2ICogMl56b29tYCBmb3IgTWVyY2F0b3ItYmFzZWQgQ1JTLlxyXG4gIFx0c2NhbGU6IGZ1bmN0aW9uICh6b29tKSB7XHJcbiAgXHRcdHJldHVybiAyNTYgKiBNYXRoLnBvdygyLCB6b29tKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCB6b29tKHNjYWxlOiBOdW1iZXIpOiBOdW1iZXJcclxuICBcdC8vIEludmVyc2Ugb2YgYHNjYWxlKClgLCByZXR1cm5zIHRoZSB6b29tIGxldmVsIGNvcnJlc3BvbmRpbmcgdG8gYSBzY2FsZVxyXG4gIFx0Ly8gZmFjdG9yIG9mIGBzY2FsZWAuXHJcbiAgXHR6b29tOiBmdW5jdGlvbiAoc2NhbGUpIHtcclxuICBcdFx0cmV0dXJuIE1hdGgubG9nKHNjYWxlIC8gMjU2KSAvIE1hdGguTE4yO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldFByb2plY3RlZEJvdW5kcyh6b29tOiBOdW1iZXIpOiBCb3VuZHNcclxuICBcdC8vIFJldHVybnMgdGhlIHByb2plY3Rpb24ncyBib3VuZHMgc2NhbGVkIGFuZCB0cmFuc2Zvcm1lZCBmb3IgdGhlIHByb3ZpZGVkIGB6b29tYC5cclxuICBcdGdldFByb2plY3RlZEJvdW5kczogZnVuY3Rpb24gKHpvb20pIHtcclxuICBcdFx0aWYgKHRoaXMuaW5maW5pdGUpIHsgcmV0dXJuIG51bGw7IH1cclxuXHJcbiAgXHRcdHZhciBiID0gdGhpcy5wcm9qZWN0aW9uLmJvdW5kcyxcclxuICBcdFx0ICAgIHMgPSB0aGlzLnNjYWxlKHpvb20pLFxyXG4gIFx0XHQgICAgbWluID0gdGhpcy50cmFuc2Zvcm1hdGlvbi50cmFuc2Zvcm0oYi5taW4sIHMpLFxyXG4gIFx0XHQgICAgbWF4ID0gdGhpcy50cmFuc2Zvcm1hdGlvbi50cmFuc2Zvcm0oYi5tYXgsIHMpO1xyXG5cclxuICBcdFx0cmV0dXJuIG5ldyBCb3VuZHMobWluLCBtYXgpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGRpc3RhbmNlKGxhdGxuZzE6IExhdExuZywgbGF0bG5nMjogTGF0TG5nKTogTnVtYmVyXHJcbiAgXHQvLyBSZXR1cm5zIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHR3byBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZXMuXHJcblxyXG4gIFx0Ly8gQHByb3BlcnR5IGNvZGU6IFN0cmluZ1xyXG4gIFx0Ly8gU3RhbmRhcmQgY29kZSBuYW1lIG9mIHRoZSBDUlMgcGFzc2VkIGludG8gV01TIHNlcnZpY2VzIChlLmcuIGAnRVBTRzozODU3J2ApXHJcbiAgXHQvL1xyXG4gIFx0Ly8gQHByb3BlcnR5IHdyYXBMbmc6IE51bWJlcltdXHJcbiAgXHQvLyBBbiBhcnJheSBvZiB0d28gbnVtYmVycyBkZWZpbmluZyB3aGV0aGVyIHRoZSBsb25naXR1ZGUgKGhvcml6b250YWwpIGNvb3JkaW5hdGVcclxuICBcdC8vIGF4aXMgd3JhcHMgYXJvdW5kIGEgZ2l2ZW4gcmFuZ2UgYW5kIGhvdy4gRGVmYXVsdHMgdG8gYFstMTgwLCAxODBdYCBpbiBtb3N0XHJcbiAgXHQvLyBnZW9ncmFwaGljYWwgQ1JTcy4gSWYgYHVuZGVmaW5lZGAsIHRoZSBsb25naXR1ZGUgYXhpcyBkb2VzIG5vdCB3cmFwIGFyb3VuZC5cclxuICBcdC8vXHJcbiAgXHQvLyBAcHJvcGVydHkgd3JhcExhdDogTnVtYmVyW11cclxuICBcdC8vIExpa2UgYHdyYXBMbmdgLCBidXQgZm9yIHRoZSBsYXRpdHVkZSAodmVydGljYWwpIGF4aXMuXHJcblxyXG4gIFx0Ly8gd3JhcExuZzogW21pbiwgbWF4XSxcclxuICBcdC8vIHdyYXBMYXQ6IFttaW4sIG1heF0sXHJcblxyXG4gIFx0Ly8gQHByb3BlcnR5IGluZmluaXRlOiBCb29sZWFuXHJcbiAgXHQvLyBJZiB0cnVlLCB0aGUgY29vcmRpbmF0ZSBzcGFjZSB3aWxsIGJlIHVuYm91bmRlZCAoaW5maW5pdGUgaW4gYm90aCBheGVzKVxyXG4gIFx0aW5maW5pdGU6IGZhbHNlLFxyXG5cclxuICBcdC8vIEBtZXRob2Qgd3JhcExhdExuZyhsYXRsbmc6IExhdExuZyk6IExhdExuZ1xyXG4gIFx0Ly8gUmV0dXJucyBhIGBMYXRMbmdgIHdoZXJlIGxhdCBhbmQgbG5nIGhhcyBiZWVuIHdyYXBwZWQgYWNjb3JkaW5nIHRvIHRoZVxyXG4gIFx0Ly8gQ1JTJ3MgYHdyYXBMYXRgIGFuZCBgd3JhcExuZ2AgcHJvcGVydGllcywgaWYgdGhleSBhcmUgb3V0c2lkZSB0aGUgQ1JTJ3MgYm91bmRzLlxyXG4gIFx0d3JhcExhdExuZzogZnVuY3Rpb24gKGxhdGxuZykge1xyXG4gIFx0XHR2YXIgbG5nID0gdGhpcy53cmFwTG5nID8gd3JhcE51bShsYXRsbmcubG5nLCB0aGlzLndyYXBMbmcsIHRydWUpIDogbGF0bG5nLmxuZyxcclxuICBcdFx0ICAgIGxhdCA9IHRoaXMud3JhcExhdCA/IHdyYXBOdW0obGF0bG5nLmxhdCwgdGhpcy53cmFwTGF0LCB0cnVlKSA6IGxhdGxuZy5sYXQsXHJcbiAgXHRcdCAgICBhbHQgPSBsYXRsbmcuYWx0O1xyXG5cclxuICBcdFx0cmV0dXJuIG5ldyBMYXRMbmcobGF0LCBsbmcsIGFsdCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgd3JhcExhdExuZ0JvdW5kcyhib3VuZHM6IExhdExuZ0JvdW5kcyk6IExhdExuZ0JvdW5kc1xyXG4gIFx0Ly8gUmV0dXJucyBhIGBMYXRMbmdCb3VuZHNgIHdpdGggdGhlIHNhbWUgc2l6ZSBhcyB0aGUgZ2l2ZW4gb25lLCBlbnN1cmluZ1xyXG4gIFx0Ly8gdGhhdCBpdHMgY2VudGVyIGlzIHdpdGhpbiB0aGUgQ1JTJ3MgYm91bmRzLlxyXG4gIFx0Ly8gT25seSBhY2NlcHRzIGFjdHVhbCBgTC5MYXRMbmdCb3VuZHNgIGluc3RhbmNlcywgbm90IGFycmF5cy5cclxuICBcdHdyYXBMYXRMbmdCb3VuZHM6IGZ1bmN0aW9uIChib3VuZHMpIHtcclxuICBcdFx0dmFyIGNlbnRlciA9IGJvdW5kcy5nZXRDZW50ZXIoKSxcclxuICBcdFx0ICAgIG5ld0NlbnRlciA9IHRoaXMud3JhcExhdExuZyhjZW50ZXIpLFxyXG4gIFx0XHQgICAgbGF0U2hpZnQgPSBjZW50ZXIubGF0IC0gbmV3Q2VudGVyLmxhdCxcclxuICBcdFx0ICAgIGxuZ1NoaWZ0ID0gY2VudGVyLmxuZyAtIG5ld0NlbnRlci5sbmc7XHJcblxyXG4gIFx0XHRpZiAobGF0U2hpZnQgPT09IDAgJiYgbG5nU2hpZnQgPT09IDApIHtcclxuICBcdFx0XHRyZXR1cm4gYm91bmRzO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgc3cgPSBib3VuZHMuZ2V0U291dGhXZXN0KCksXHJcbiAgXHRcdCAgICBuZSA9IGJvdW5kcy5nZXROb3J0aEVhc3QoKSxcclxuICBcdFx0ICAgIG5ld1N3ID0gbmV3IExhdExuZyhzdy5sYXQgLSBsYXRTaGlmdCwgc3cubG5nIC0gbG5nU2hpZnQpLFxyXG4gIFx0XHQgICAgbmV3TmUgPSBuZXcgTGF0TG5nKG5lLmxhdCAtIGxhdFNoaWZ0LCBuZS5sbmcgLSBsbmdTaGlmdCk7XHJcblxyXG4gIFx0XHRyZXR1cm4gbmV3IExhdExuZ0JvdW5kcyhuZXdTdywgbmV3TmUpO1xyXG4gIFx0fVxyXG4gIH07XG5cbiAgLypcbiAgICogQG5hbWVzcGFjZSBDUlNcbiAgICogQGNycyBMLkNSUy5FYXJ0aFxuICAgKlxuICAgKiBTZXJ2ZXMgYXMgdGhlIGJhc2UgZm9yIENSUyB0aGF0IGFyZSBnbG9iYWwgc3VjaCB0aGF0IHRoZXkgY292ZXIgdGhlIGVhcnRoLlxuICAgKiBDYW4gb25seSBiZSB1c2VkIGFzIHRoZSBiYXNlIGZvciBvdGhlciBDUlMgYW5kIGNhbm5vdCBiZSB1c2VkIGRpcmVjdGx5LFxuICAgKiBzaW5jZSBpdCBkb2VzIG5vdCBoYXZlIGEgYGNvZGVgLCBgcHJvamVjdGlvbmAgb3IgYHRyYW5zZm9ybWF0aW9uYC4gYGRpc3RhbmNlKClgIHJldHVybnNcbiAgICogbWV0ZXJzLlxuICAgKi9cblxuICB2YXIgRWFydGggPSBleHRlbmQoe30sIENSUywge1xuICBcdHdyYXBMbmc6IFstMTgwLCAxODBdLFxuXG4gIFx0Ly8gTWVhbiBFYXJ0aCBSYWRpdXMsIGFzIHJlY29tbWVuZGVkIGZvciB1c2UgYnlcbiAgXHQvLyB0aGUgSW50ZXJuYXRpb25hbCBVbmlvbiBvZiBHZW9kZXN5IGFuZCBHZW9waHlzaWNzLFxuICBcdC8vIHNlZSBodHRwczovL3Jvc2V0dGFjb2RlLm9yZy93aWtpL0hhdmVyc2luZV9mb3JtdWxhXG4gIFx0UjogNjM3MTAwMCxcblxuICBcdC8vIGRpc3RhbmNlIGJldHdlZW4gdHdvIGdlb2dyYXBoaWNhbCBwb2ludHMgdXNpbmcgc3BoZXJpY2FsIGxhdyBvZiBjb3NpbmVzIGFwcHJveGltYXRpb25cbiAgXHRkaXN0YW5jZTogZnVuY3Rpb24gKGxhdGxuZzEsIGxhdGxuZzIpIHtcbiAgXHRcdHZhciByYWQgPSBNYXRoLlBJIC8gMTgwLFxuICBcdFx0ICAgIGxhdDEgPSBsYXRsbmcxLmxhdCAqIHJhZCxcbiAgXHRcdCAgICBsYXQyID0gbGF0bG5nMi5sYXQgKiByYWQsXG4gIFx0XHQgICAgc2luRExhdCA9IE1hdGguc2luKChsYXRsbmcyLmxhdCAtIGxhdGxuZzEubGF0KSAqIHJhZCAvIDIpLFxuICBcdFx0ICAgIHNpbkRMb24gPSBNYXRoLnNpbigobGF0bG5nMi5sbmcgLSBsYXRsbmcxLmxuZykgKiByYWQgLyAyKSxcbiAgXHRcdCAgICBhID0gc2luRExhdCAqIHNpbkRMYXQgKyBNYXRoLmNvcyhsYXQxKSAqIE1hdGguY29zKGxhdDIpICogc2luRExvbiAqIHNpbkRMb24sXG4gIFx0XHQgICAgYyA9IDIgKiBNYXRoLmF0YW4yKE1hdGguc3FydChhKSwgTWF0aC5zcXJ0KDEgLSBhKSk7XG4gIFx0XHRyZXR1cm4gdGhpcy5SICogYztcbiAgXHR9XG4gIH0pO1xuXG4gIC8qXHJcbiAgICogQG5hbWVzcGFjZSBQcm9qZWN0aW9uXHJcbiAgICogQHByb2plY3Rpb24gTC5Qcm9qZWN0aW9uLlNwaGVyaWNhbE1lcmNhdG9yXHJcbiAgICpcclxuICAgKiBTcGhlcmljYWwgTWVyY2F0b3IgcHJvamVjdGlvbiDigJQgdGhlIG1vc3QgY29tbW9uIHByb2plY3Rpb24gZm9yIG9ubGluZSBtYXBzLFxyXG4gICAqIHVzZWQgYnkgYWxtb3N0IGFsbCBmcmVlIGFuZCBjb21tZXJjaWFsIHRpbGUgcHJvdmlkZXJzLiBBc3N1bWVzIHRoYXQgRWFydGggaXNcclxuICAgKiBhIHNwaGVyZS4gVXNlZCBieSB0aGUgYEVQU0c6Mzg1N2AgQ1JTLlxyXG4gICAqL1xyXG5cclxuICB2YXIgZWFydGhSYWRpdXMgPSA2Mzc4MTM3O1xyXG5cclxuICB2YXIgU3BoZXJpY2FsTWVyY2F0b3IgPSB7XHJcblxyXG4gIFx0UjogZWFydGhSYWRpdXMsXHJcbiAgXHRNQVhfTEFUSVRVREU6IDg1LjA1MTEyODc3OTgsXHJcblxyXG4gIFx0cHJvamVjdDogZnVuY3Rpb24gKGxhdGxuZykge1xyXG4gIFx0XHR2YXIgZCA9IE1hdGguUEkgLyAxODAsXHJcbiAgXHRcdCAgICBtYXggPSB0aGlzLk1BWF9MQVRJVFVERSxcclxuICBcdFx0ICAgIGxhdCA9IE1hdGgubWF4KE1hdGgubWluKG1heCwgbGF0bG5nLmxhdCksIC1tYXgpLFxyXG4gIFx0XHQgICAgc2luID0gTWF0aC5zaW4obGF0ICogZCk7XHJcblxyXG4gIFx0XHRyZXR1cm4gbmV3IFBvaW50KFxyXG4gIFx0XHRcdHRoaXMuUiAqIGxhdGxuZy5sbmcgKiBkLFxyXG4gIFx0XHRcdHRoaXMuUiAqIE1hdGgubG9nKCgxICsgc2luKSAvICgxIC0gc2luKSkgLyAyKTtcclxuICBcdH0sXHJcblxyXG4gIFx0dW5wcm9qZWN0OiBmdW5jdGlvbiAocG9pbnQpIHtcclxuICBcdFx0dmFyIGQgPSAxODAgLyBNYXRoLlBJO1xyXG5cclxuICBcdFx0cmV0dXJuIG5ldyBMYXRMbmcoXHJcbiAgXHRcdFx0KDIgKiBNYXRoLmF0YW4oTWF0aC5leHAocG9pbnQueSAvIHRoaXMuUikpIC0gKE1hdGguUEkgLyAyKSkgKiBkLFxyXG4gIFx0XHRcdHBvaW50LnggKiBkIC8gdGhpcy5SKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ym91bmRzOiAoZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR2YXIgZCA9IGVhcnRoUmFkaXVzICogTWF0aC5QSTtcclxuICBcdFx0cmV0dXJuIG5ldyBCb3VuZHMoWy1kLCAtZF0sIFtkLCBkXSk7XHJcbiAgXHR9KSgpXHJcbiAgfTtcblxuICAvKlxyXG4gICAqIEBjbGFzcyBUcmFuc2Zvcm1hdGlvblxyXG4gICAqIEBha2EgTC5UcmFuc2Zvcm1hdGlvblxyXG4gICAqXHJcbiAgICogUmVwcmVzZW50cyBhbiBhZmZpbmUgdHJhbnNmb3JtYXRpb246IGEgc2V0IG9mIGNvZWZmaWNpZW50cyBgYWAsIGBiYCwgYGNgLCBgZGBcclxuICAgKiBmb3IgdHJhbnNmb3JtaW5nIGEgcG9pbnQgb2YgYSBmb3JtIGAoeCwgeSlgIGludG8gYChhKnggKyBiLCBjKnkgKyBkKWAgYW5kIGRvaW5nXHJcbiAgICogdGhlIHJldmVyc2UuIFVzZWQgYnkgTGVhZmxldCBpbiBpdHMgcHJvamVjdGlvbnMgY29kZS5cclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICpcclxuICAgKiBgYGBqc1xyXG4gICAqIHZhciB0cmFuc2Zvcm1hdGlvbiA9IEwudHJhbnNmb3JtYXRpb24oMiwgNSwgLTEsIDEwKSxcclxuICAgKiBcdHAgPSBMLnBvaW50KDEsIDIpLFxyXG4gICAqIFx0cDIgPSB0cmFuc2Zvcm1hdGlvbi50cmFuc2Zvcm0ocCksIC8vICBMLnBvaW50KDcsIDgpXHJcbiAgICogXHRwMyA9IHRyYW5zZm9ybWF0aW9uLnVudHJhbnNmb3JtKHAyKTsgLy8gIEwucG9pbnQoMSwgMilcclxuICAgKiBgYGBcclxuICAgKi9cclxuXHJcblxyXG4gIC8vIGZhY3RvcnkgbmV3IEwuVHJhbnNmb3JtYXRpb24oYTogTnVtYmVyLCBiOiBOdW1iZXIsIGM6IE51bWJlciwgZDogTnVtYmVyKVxyXG4gIC8vIENyZWF0ZXMgYSBgVHJhbnNmb3JtYXRpb25gIG9iamVjdCB3aXRoIHRoZSBnaXZlbiBjb2VmZmljaWVudHMuXHJcbiAgZnVuY3Rpb24gVHJhbnNmb3JtYXRpb24oYSwgYiwgYywgZCkge1xyXG4gIFx0aWYgKGlzQXJyYXkoYSkpIHtcclxuICBcdFx0Ly8gdXNlIGFycmF5IHByb3BlcnRpZXNcclxuICBcdFx0dGhpcy5fYSA9IGFbMF07XHJcbiAgXHRcdHRoaXMuX2IgPSBhWzFdO1xyXG4gIFx0XHR0aGlzLl9jID0gYVsyXTtcclxuICBcdFx0dGhpcy5fZCA9IGFbM107XHJcbiAgXHRcdHJldHVybjtcclxuICBcdH1cclxuICBcdHRoaXMuX2EgPSBhO1xyXG4gIFx0dGhpcy5fYiA9IGI7XHJcbiAgXHR0aGlzLl9jID0gYztcclxuICBcdHRoaXMuX2QgPSBkO1xyXG4gIH1cclxuXHJcbiAgVHJhbnNmb3JtYXRpb24ucHJvdG90eXBlID0ge1xyXG4gIFx0Ly8gQG1ldGhvZCB0cmFuc2Zvcm0ocG9pbnQ6IFBvaW50LCBzY2FsZT86IE51bWJlcik6IFBvaW50XHJcbiAgXHQvLyBSZXR1cm5zIGEgdHJhbnNmb3JtZWQgcG9pbnQsIG9wdGlvbmFsbHkgbXVsdGlwbGllZCBieSB0aGUgZ2l2ZW4gc2NhbGUuXHJcbiAgXHQvLyBPbmx5IGFjY2VwdHMgYWN0dWFsIGBMLlBvaW50YCBpbnN0YW5jZXMsIG5vdCBhcnJheXMuXHJcbiAgXHR0cmFuc2Zvcm06IGZ1bmN0aW9uIChwb2ludCwgc2NhbGUpIHsgLy8gKFBvaW50LCBOdW1iZXIpIC0+IFBvaW50XHJcbiAgXHRcdHJldHVybiB0aGlzLl90cmFuc2Zvcm0ocG9pbnQuY2xvbmUoKSwgc2NhbGUpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBkZXN0cnVjdGl2ZSB0cmFuc2Zvcm0gKGZhc3RlcilcclxuICBcdF90cmFuc2Zvcm06IGZ1bmN0aW9uIChwb2ludCwgc2NhbGUpIHtcclxuICBcdFx0c2NhbGUgPSBzY2FsZSB8fCAxO1xyXG4gIFx0XHRwb2ludC54ID0gc2NhbGUgKiAodGhpcy5fYSAqIHBvaW50LnggKyB0aGlzLl9iKTtcclxuICBcdFx0cG9pbnQueSA9IHNjYWxlICogKHRoaXMuX2MgKiBwb2ludC55ICsgdGhpcy5fZCk7XHJcbiAgXHRcdHJldHVybiBwb2ludDtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCB1bnRyYW5zZm9ybShwb2ludDogUG9pbnQsIHNjYWxlPzogTnVtYmVyKTogUG9pbnRcclxuICBcdC8vIFJldHVybnMgdGhlIHJldmVyc2UgdHJhbnNmb3JtYXRpb24gb2YgdGhlIGdpdmVuIHBvaW50LCBvcHRpb25hbGx5IGRpdmlkZWRcclxuICBcdC8vIGJ5IHRoZSBnaXZlbiBzY2FsZS4gT25seSBhY2NlcHRzIGFjdHVhbCBgTC5Qb2ludGAgaW5zdGFuY2VzLCBub3QgYXJyYXlzLlxyXG4gIFx0dW50cmFuc2Zvcm06IGZ1bmN0aW9uIChwb2ludCwgc2NhbGUpIHtcclxuICBcdFx0c2NhbGUgPSBzY2FsZSB8fCAxO1xyXG4gIFx0XHRyZXR1cm4gbmV3IFBvaW50KFxyXG4gIFx0XHQgICAgICAgIChwb2ludC54IC8gc2NhbGUgLSB0aGlzLl9iKSAvIHRoaXMuX2EsXHJcbiAgXHRcdCAgICAgICAgKHBvaW50LnkgLyBzY2FsZSAtIHRoaXMuX2QpIC8gdGhpcy5fYyk7XHJcbiAgXHR9XHJcbiAgfTtcclxuXHJcbiAgLy8gZmFjdG9yeSBMLnRyYW5zZm9ybWF0aW9uKGE6IE51bWJlciwgYjogTnVtYmVyLCBjOiBOdW1iZXIsIGQ6IE51bWJlcilcclxuXHJcbiAgLy8gQGZhY3RvcnkgTC50cmFuc2Zvcm1hdGlvbihhOiBOdW1iZXIsIGI6IE51bWJlciwgYzogTnVtYmVyLCBkOiBOdW1iZXIpXHJcbiAgLy8gSW5zdGFudGlhdGVzIGEgVHJhbnNmb3JtYXRpb24gb2JqZWN0IHdpdGggdGhlIGdpdmVuIGNvZWZmaWNpZW50cy5cclxuXHJcbiAgLy8gQGFsdGVybmF0aXZlXHJcbiAgLy8gQGZhY3RvcnkgTC50cmFuc2Zvcm1hdGlvbihjb2VmZmljaWVudHM6IEFycmF5KTogVHJhbnNmb3JtYXRpb25cclxuICAvLyBFeHBlY3RzIGFuIGNvZWZmaWNpZW50cyBhcnJheSBvZiB0aGUgZm9ybVxyXG4gIC8vIGBbYTogTnVtYmVyLCBiOiBOdW1iZXIsIGM6IE51bWJlciwgZDogTnVtYmVyXWAuXHJcblxyXG4gIGZ1bmN0aW9uIHRvVHJhbnNmb3JtYXRpb24oYSwgYiwgYywgZCkge1xyXG4gIFx0cmV0dXJuIG5ldyBUcmFuc2Zvcm1hdGlvbihhLCBiLCBjLCBkKTtcclxuICB9XG5cbiAgLypcclxuICAgKiBAbmFtZXNwYWNlIENSU1xyXG4gICAqIEBjcnMgTC5DUlMuRVBTRzM4NTdcclxuICAgKlxyXG4gICAqIFRoZSBtb3N0IGNvbW1vbiBDUlMgZm9yIG9ubGluZSBtYXBzLCB1c2VkIGJ5IGFsbW9zdCBhbGwgZnJlZSBhbmQgY29tbWVyY2lhbFxyXG4gICAqIHRpbGUgcHJvdmlkZXJzLiBVc2VzIFNwaGVyaWNhbCBNZXJjYXRvciBwcm9qZWN0aW9uLiBTZXQgaW4gYnkgZGVmYXVsdCBpblxyXG4gICAqIE1hcCdzIGBjcnNgIG9wdGlvbi5cclxuICAgKi9cclxuXHJcbiAgdmFyIEVQU0czODU3ID0gZXh0ZW5kKHt9LCBFYXJ0aCwge1xyXG4gIFx0Y29kZTogJ0VQU0c6Mzg1NycsXHJcbiAgXHRwcm9qZWN0aW9uOiBTcGhlcmljYWxNZXJjYXRvcixcclxuXHJcbiAgXHR0cmFuc2Zvcm1hdGlvbjogKGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dmFyIHNjYWxlID0gMC41IC8gKE1hdGguUEkgKiBTcGhlcmljYWxNZXJjYXRvci5SKTtcclxuICBcdFx0cmV0dXJuIHRvVHJhbnNmb3JtYXRpb24oc2NhbGUsIDAuNSwgLXNjYWxlLCAwLjUpO1xyXG4gIFx0fSgpKVxyXG4gIH0pO1xyXG5cclxuICB2YXIgRVBTRzkwMDkxMyA9IGV4dGVuZCh7fSwgRVBTRzM4NTcsIHtcclxuICBcdGNvZGU6ICdFUFNHOjkwMDkxMydcclxuICB9KTtcblxuICAvLyBAbmFtZXNwYWNlIFNWRzsgQHNlY3Rpb25cbiAgLy8gVGhlcmUgYXJlIHNldmVyYWwgc3RhdGljIGZ1bmN0aW9ucyB3aGljaCBjYW4gYmUgY2FsbGVkIHdpdGhvdXQgaW5zdGFudGlhdGluZyBMLlNWRzpcblxuICAvLyBAZnVuY3Rpb24gY3JlYXRlKG5hbWU6IFN0cmluZyk6IFNWR0VsZW1lbnRcbiAgLy8gUmV0dXJucyBhIGluc3RhbmNlIG9mIFtTVkdFbGVtZW50XShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvU1ZHRWxlbWVudCksXG4gIC8vIGNvcnJlc3BvbmRpbmcgdG8gdGhlIGNsYXNzIG5hbWUgcGFzc2VkLiBGb3IgZXhhbXBsZSwgdXNpbmcgJ2xpbmUnIHdpbGwgcmV0dXJuXG4gIC8vIGFuIGluc3RhbmNlIG9mIFtTVkdMaW5lRWxlbWVudF0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQVBJL1NWR0xpbmVFbGVtZW50KS5cbiAgZnVuY3Rpb24gc3ZnQ3JlYXRlKG5hbWUpIHtcbiAgXHRyZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKCdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZycsIG5hbWUpO1xuICB9XG5cbiAgLy8gQGZ1bmN0aW9uIHBvaW50c1RvUGF0aChyaW5nczogUG9pbnRbXSwgY2xvc2VkOiBCb29sZWFuKTogU3RyaW5nXG4gIC8vIEdlbmVyYXRlcyBhIFNWRyBwYXRoIHN0cmluZyBmb3IgbXVsdGlwbGUgcmluZ3MsIHdpdGggZWFjaCByaW5nIHR1cm5pbmdcbiAgLy8gaW50byBcIk0uLkwuLkwuLlwiIGluc3RydWN0aW9uc1xuICBmdW5jdGlvbiBwb2ludHNUb1BhdGgocmluZ3MsIGNsb3NlZCkge1xuICBcdHZhciBzdHIgPSAnJyxcbiAgXHRpLCBqLCBsZW4sIGxlbjIsIHBvaW50cywgcDtcblxuICBcdGZvciAoaSA9IDAsIGxlbiA9IHJpbmdzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gIFx0XHRwb2ludHMgPSByaW5nc1tpXTtcblxuICBcdFx0Zm9yIChqID0gMCwgbGVuMiA9IHBvaW50cy5sZW5ndGg7IGogPCBsZW4yOyBqKyspIHtcbiAgXHRcdFx0cCA9IHBvaW50c1tqXTtcbiAgXHRcdFx0c3RyICs9IChqID8gJ0wnIDogJ00nKSArIHAueCArICcgJyArIHAueTtcbiAgXHRcdH1cblxuICBcdFx0Ly8gY2xvc2VzIHRoZSByaW5nIGZvciBwb2x5Z29uczsgXCJ4XCIgaXMgVk1MIHN5bnRheFxuICBcdFx0c3RyICs9IGNsb3NlZCA/IChCcm93c2VyLnN2ZyA/ICd6JyA6ICd4JykgOiAnJztcbiAgXHR9XG5cbiAgXHQvLyBTVkcgY29tcGxhaW5zIGFib3V0IGVtcHR5IHBhdGggc3RyaW5nc1xuICBcdHJldHVybiBzdHIgfHwgJ00wIDAnO1xuICB9XG5cbiAgLypcclxuICAgKiBAbmFtZXNwYWNlIEJyb3dzZXJcclxuICAgKiBAYWthIEwuQnJvd3NlclxyXG4gICAqXHJcbiAgICogQSBuYW1lc3BhY2Ugd2l0aCBzdGF0aWMgcHJvcGVydGllcyBmb3IgYnJvd3Nlci9mZWF0dXJlIGRldGVjdGlvbiB1c2VkIGJ5IExlYWZsZXQgaW50ZXJuYWxseS5cclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICpcclxuICAgKiBgYGBqc1xyXG4gICAqIGlmIChMLkJyb3dzZXIuaWVsdDkpIHtcclxuICAgKiAgIGFsZXJ0KCdVcGdyYWRlIHlvdXIgYnJvd3NlciwgZHVkZSEnKTtcclxuICAgKiB9XHJcbiAgICogYGBgXHJcbiAgICovXHJcblxyXG4gIHZhciBzdHlsZSA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZTtcclxuXHJcbiAgLy8gQHByb3BlcnR5IGllOiBCb29sZWFuOyBgdHJ1ZWAgZm9yIGFsbCBJbnRlcm5ldCBFeHBsb3JlciB2ZXJzaW9ucyAobm90IEVkZ2UpLlxyXG4gIHZhciBpZSA9ICdBY3RpdmVYT2JqZWN0JyBpbiB3aW5kb3c7XHJcblxyXG4gIC8vIEBwcm9wZXJ0eSBpZWx0OTogQm9vbGVhbjsgYHRydWVgIGZvciBJbnRlcm5ldCBFeHBsb3JlciB2ZXJzaW9ucyBsZXNzIHRoYW4gOS5cclxuICB2YXIgaWVsdDkgPSBpZSAmJiAhZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcjtcclxuXHJcbiAgLy8gQHByb3BlcnR5IGVkZ2U6IEJvb2xlYW47IGB0cnVlYCBmb3IgdGhlIEVkZ2Ugd2ViIGJyb3dzZXIuXHJcbiAgdmFyIGVkZ2UgPSAnbXNMYXVuY2hVcmknIGluIG5hdmlnYXRvciAmJiAhKCdkb2N1bWVudE1vZGUnIGluIGRvY3VtZW50KTtcclxuXHJcbiAgLy8gQHByb3BlcnR5IHdlYmtpdDogQm9vbGVhbjtcclxuICAvLyBgdHJ1ZWAgZm9yIHdlYmtpdC1iYXNlZCBicm93c2VycyBsaWtlIENocm9tZSBhbmQgU2FmYXJpIChpbmNsdWRpbmcgbW9iaWxlIHZlcnNpb25zKS5cclxuICB2YXIgd2Via2l0ID0gdXNlckFnZW50Q29udGFpbnMoJ3dlYmtpdCcpO1xyXG5cclxuICAvLyBAcHJvcGVydHkgYW5kcm9pZDogQm9vbGVhblxyXG4gIC8vICoqRGVwcmVjYXRlZC4qKiBgdHJ1ZWAgZm9yIGFueSBicm93c2VyIHJ1bm5pbmcgb24gYW4gQW5kcm9pZCBwbGF0Zm9ybS5cclxuICB2YXIgYW5kcm9pZCA9IHVzZXJBZ2VudENvbnRhaW5zKCdhbmRyb2lkJyk7XHJcblxyXG4gIC8vIEBwcm9wZXJ0eSBhbmRyb2lkMjM6IEJvb2xlYW47ICoqRGVwcmVjYXRlZC4qKiBgdHJ1ZWAgZm9yIGJyb3dzZXJzIHJ1bm5pbmcgb24gQW5kcm9pZCAyIG9yIEFuZHJvaWQgMy5cclxuICB2YXIgYW5kcm9pZDIzID0gdXNlckFnZW50Q29udGFpbnMoJ2FuZHJvaWQgMicpIHx8IHVzZXJBZ2VudENvbnRhaW5zKCdhbmRyb2lkIDMnKTtcclxuXHJcbiAgLyogU2VlIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8xNzk2MTI2NiBmb3IgZGV0YWlscyBvbiBkZXRlY3Rpbmcgc3RvY2sgQW5kcm9pZCAqL1xyXG4gIHZhciB3ZWJraXRWZXIgPSBwYXJzZUludCgvV2ViS2l0XFwvKFswLTldKyl8JC8uZXhlYyhuYXZpZ2F0b3IudXNlckFnZW50KVsxXSwgMTApOyAvLyBhbHNvIG1hdGNoZXMgQXBwbGVXZWJLaXRcclxuICAvLyBAcHJvcGVydHkgYW5kcm9pZFN0b2NrOiBCb29sZWFuOyAqKkRlcHJlY2F0ZWQuKiogYHRydWVgIGZvciB0aGUgQW5kcm9pZCBzdG9jayBicm93c2VyIChpLmUuIG5vdCBDaHJvbWUpXHJcbiAgdmFyIGFuZHJvaWRTdG9jayA9IGFuZHJvaWQgJiYgdXNlckFnZW50Q29udGFpbnMoJ0dvb2dsZScpICYmIHdlYmtpdFZlciA8IDUzNyAmJiAhKCdBdWRpb05vZGUnIGluIHdpbmRvdyk7XHJcblxyXG4gIC8vIEBwcm9wZXJ0eSBvcGVyYTogQm9vbGVhbjsgYHRydWVgIGZvciB0aGUgT3BlcmEgYnJvd3NlclxyXG4gIHZhciBvcGVyYSA9ICEhd2luZG93Lm9wZXJhO1xyXG5cclxuICAvLyBAcHJvcGVydHkgY2hyb21lOiBCb29sZWFuOyBgdHJ1ZWAgZm9yIHRoZSBDaHJvbWUgYnJvd3Nlci5cclxuICB2YXIgY2hyb21lID0gIWVkZ2UgJiYgdXNlckFnZW50Q29udGFpbnMoJ2Nocm9tZScpO1xyXG5cclxuICAvLyBAcHJvcGVydHkgZ2Vja286IEJvb2xlYW47IGB0cnVlYCBmb3IgZ2Vja28tYmFzZWQgYnJvd3NlcnMgbGlrZSBGaXJlZm94LlxyXG4gIHZhciBnZWNrbyA9IHVzZXJBZ2VudENvbnRhaW5zKCdnZWNrbycpICYmICF3ZWJraXQgJiYgIW9wZXJhICYmICFpZTtcclxuXHJcbiAgLy8gQHByb3BlcnR5IHNhZmFyaTogQm9vbGVhbjsgYHRydWVgIGZvciB0aGUgU2FmYXJpIGJyb3dzZXIuXHJcbiAgdmFyIHNhZmFyaSA9ICFjaHJvbWUgJiYgdXNlckFnZW50Q29udGFpbnMoJ3NhZmFyaScpO1xyXG5cclxuICB2YXIgcGhhbnRvbSA9IHVzZXJBZ2VudENvbnRhaW5zKCdwaGFudG9tJyk7XHJcblxyXG4gIC8vIEBwcm9wZXJ0eSBvcGVyYTEyOiBCb29sZWFuXHJcbiAgLy8gYHRydWVgIGZvciB0aGUgT3BlcmEgYnJvd3NlciBzdXBwb3J0aW5nIENTUyB0cmFuc2Zvcm1zICh2ZXJzaW9uIDEyIG9yIGxhdGVyKS5cclxuICB2YXIgb3BlcmExMiA9ICdPVHJhbnNpdGlvbicgaW4gc3R5bGU7XHJcblxyXG4gIC8vIEBwcm9wZXJ0eSB3aW46IEJvb2xlYW47IGB0cnVlYCB3aGVuIHRoZSBicm93c2VyIGlzIHJ1bm5pbmcgaW4gYSBXaW5kb3dzIHBsYXRmb3JtXHJcbiAgdmFyIHdpbiA9IG5hdmlnYXRvci5wbGF0Zm9ybS5pbmRleE9mKCdXaW4nKSA9PT0gMDtcclxuXHJcbiAgLy8gQHByb3BlcnR5IGllM2Q6IEJvb2xlYW47IGB0cnVlYCBmb3IgYWxsIEludGVybmV0IEV4cGxvcmVyIHZlcnNpb25zIHN1cHBvcnRpbmcgQ1NTIHRyYW5zZm9ybXMuXHJcbiAgdmFyIGllM2QgPSBpZSAmJiAoJ3RyYW5zaXRpb24nIGluIHN0eWxlKTtcclxuXHJcbiAgLy8gQHByb3BlcnR5IHdlYmtpdDNkOiBCb29sZWFuOyBgdHJ1ZWAgZm9yIHdlYmtpdC1iYXNlZCBicm93c2VycyBzdXBwb3J0aW5nIENTUyB0cmFuc2Zvcm1zLlxyXG4gIHZhciB3ZWJraXQzZCA9ICgnV2ViS2l0Q1NTTWF0cml4JyBpbiB3aW5kb3cpICYmICgnbTExJyBpbiBuZXcgd2luZG93LldlYktpdENTU01hdHJpeCgpKSAmJiAhYW5kcm9pZDIzO1xyXG5cclxuICAvLyBAcHJvcGVydHkgZ2Vja28zZDogQm9vbGVhbjsgYHRydWVgIGZvciBnZWNrby1iYXNlZCBicm93c2VycyBzdXBwb3J0aW5nIENTUyB0cmFuc2Zvcm1zLlxyXG4gIHZhciBnZWNrbzNkID0gJ01velBlcnNwZWN0aXZlJyBpbiBzdHlsZTtcclxuXHJcbiAgLy8gQHByb3BlcnR5IGFueTNkOiBCb29sZWFuXHJcbiAgLy8gYHRydWVgIGZvciBhbGwgYnJvd3NlcnMgc3VwcG9ydGluZyBDU1MgdHJhbnNmb3Jtcy5cclxuICB2YXIgYW55M2QgPSAhd2luZG93LkxfRElTQUJMRV8zRCAmJiAoaWUzZCB8fCB3ZWJraXQzZCB8fCBnZWNrbzNkKSAmJiAhb3BlcmExMiAmJiAhcGhhbnRvbTtcclxuXHJcbiAgLy8gQHByb3BlcnR5IG1vYmlsZTogQm9vbGVhbjsgYHRydWVgIGZvciBhbGwgYnJvd3NlcnMgcnVubmluZyBpbiBhIG1vYmlsZSBkZXZpY2UuXHJcbiAgdmFyIG1vYmlsZSA9IHR5cGVvZiBvcmllbnRhdGlvbiAhPT0gJ3VuZGVmaW5lZCcgfHwgdXNlckFnZW50Q29udGFpbnMoJ21vYmlsZScpO1xyXG5cclxuICAvLyBAcHJvcGVydHkgbW9iaWxlV2Via2l0OiBCb29sZWFuOyBgdHJ1ZWAgZm9yIGFsbCB3ZWJraXQtYmFzZWQgYnJvd3NlcnMgaW4gYSBtb2JpbGUgZGV2aWNlLlxyXG4gIHZhciBtb2JpbGVXZWJraXQgPSBtb2JpbGUgJiYgd2Via2l0O1xyXG5cclxuICAvLyBAcHJvcGVydHkgbW9iaWxlV2Via2l0M2Q6IEJvb2xlYW5cclxuICAvLyBgdHJ1ZWAgZm9yIGFsbCB3ZWJraXQtYmFzZWQgYnJvd3NlcnMgaW4gYSBtb2JpbGUgZGV2aWNlIHN1cHBvcnRpbmcgQ1NTIHRyYW5zZm9ybXMuXHJcbiAgdmFyIG1vYmlsZVdlYmtpdDNkID0gbW9iaWxlICYmIHdlYmtpdDNkO1xyXG5cclxuICAvLyBAcHJvcGVydHkgbXNQb2ludGVyOiBCb29sZWFuXHJcbiAgLy8gYHRydWVgIGZvciBicm93c2VycyBpbXBsZW1lbnRpbmcgdGhlIE1pY3Jvc29mdCB0b3VjaCBldmVudHMgbW9kZWwgKG5vdGFibHkgSUUxMCkuXHJcbiAgdmFyIG1zUG9pbnRlciA9ICF3aW5kb3cuUG9pbnRlckV2ZW50ICYmIHdpbmRvdy5NU1BvaW50ZXJFdmVudDtcclxuXHJcbiAgLy8gQHByb3BlcnR5IHBvaW50ZXI6IEJvb2xlYW5cclxuICAvLyBgdHJ1ZWAgZm9yIGFsbCBicm93c2VycyBzdXBwb3J0aW5nIFtwb2ludGVyIGV2ZW50c10oaHR0cHM6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9kbjQzMzI0NCUyOHY9dnMuODUlMjkuYXNweCkuXHJcbiAgdmFyIHBvaW50ZXIgPSAhISh3aW5kb3cuUG9pbnRlckV2ZW50IHx8IG1zUG9pbnRlcik7XHJcblxyXG4gIC8vIEBwcm9wZXJ0eSB0b3VjaE5hdGl2ZTogQm9vbGVhblxyXG4gIC8vIGB0cnVlYCBmb3IgYWxsIGJyb3dzZXJzIHN1cHBvcnRpbmcgW3RvdWNoIGV2ZW50c10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQVBJL1RvdWNoX2V2ZW50cykuXHJcbiAgLy8gKipUaGlzIGRvZXMgbm90IG5lY2Vzc2FyaWx5IG1lYW4qKiB0aGF0IHRoZSBicm93c2VyIGlzIHJ1bm5pbmcgaW4gYSBjb21wdXRlciB3aXRoXHJcbiAgLy8gYSB0b3VjaHNjcmVlbiwgaXQgb25seSBtZWFucyB0aGF0IHRoZSBicm93c2VyIGlzIGNhcGFibGUgb2YgdW5kZXJzdGFuZGluZ1xyXG4gIC8vIHRvdWNoIGV2ZW50cy5cclxuICB2YXIgdG91Y2hOYXRpdmUgPSAnb250b3VjaHN0YXJ0JyBpbiB3aW5kb3cgfHwgISF3aW5kb3cuVG91Y2hFdmVudDtcclxuXHJcbiAgLy8gQHByb3BlcnR5IHRvdWNoOiBCb29sZWFuXHJcbiAgLy8gYHRydWVgIGZvciBhbGwgYnJvd3NlcnMgc3VwcG9ydGluZyBlaXRoZXIgW3RvdWNoXSgjYnJvd3Nlci10b3VjaCkgb3IgW3BvaW50ZXJdKCNicm93c2VyLXBvaW50ZXIpIGV2ZW50cy5cclxuICAvLyBOb3RlOiBwb2ludGVyIGV2ZW50cyB3aWxsIGJlIHByZWZlcnJlZCAoaWYgYXZhaWxhYmxlKSwgYW5kIHByb2Nlc3NlZCBmb3IgYWxsIGB0b3VjaCpgIGxpc3RlbmVycy5cclxuICB2YXIgdG91Y2ggPSAhd2luZG93LkxfTk9fVE9VQ0ggJiYgKHRvdWNoTmF0aXZlIHx8IHBvaW50ZXIpO1xyXG5cclxuICAvLyBAcHJvcGVydHkgbW9iaWxlT3BlcmE6IEJvb2xlYW47IGB0cnVlYCBmb3IgdGhlIE9wZXJhIGJyb3dzZXIgaW4gYSBtb2JpbGUgZGV2aWNlLlxyXG4gIHZhciBtb2JpbGVPcGVyYSA9IG1vYmlsZSAmJiBvcGVyYTtcclxuXHJcbiAgLy8gQHByb3BlcnR5IG1vYmlsZUdlY2tvOiBCb29sZWFuXHJcbiAgLy8gYHRydWVgIGZvciBnZWNrby1iYXNlZCBicm93c2VycyBydW5uaW5nIGluIGEgbW9iaWxlIGRldmljZS5cclxuICB2YXIgbW9iaWxlR2Vja28gPSBtb2JpbGUgJiYgZ2Vja287XHJcblxyXG4gIC8vIEBwcm9wZXJ0eSByZXRpbmE6IEJvb2xlYW5cclxuICAvLyBgdHJ1ZWAgZm9yIGJyb3dzZXJzIG9uIGEgaGlnaC1yZXNvbHV0aW9uIFwicmV0aW5hXCIgc2NyZWVuIG9yIG9uIGFueSBzY3JlZW4gd2hlbiBicm93c2VyJ3MgZGlzcGxheSB6b29tIGlzIG1vcmUgdGhhbiAxMDAlLlxyXG4gIHZhciByZXRpbmEgPSAod2luZG93LmRldmljZVBpeGVsUmF0aW8gfHwgKHdpbmRvdy5zY3JlZW4uZGV2aWNlWERQSSAvIHdpbmRvdy5zY3JlZW4ubG9naWNhbFhEUEkpKSA+IDE7XHJcblxyXG4gIC8vIEBwcm9wZXJ0eSBwYXNzaXZlRXZlbnRzOiBCb29sZWFuXHJcbiAgLy8gYHRydWVgIGZvciBicm93c2VycyB0aGF0IHN1cHBvcnQgcGFzc2l2ZSBldmVudHMuXHJcbiAgdmFyIHBhc3NpdmVFdmVudHMgPSAoZnVuY3Rpb24gKCkge1xyXG4gIFx0dmFyIHN1cHBvcnRzUGFzc2l2ZU9wdGlvbiA9IGZhbHNlO1xyXG4gIFx0dHJ5IHtcclxuICBcdFx0dmFyIG9wdHMgPSBPYmplY3QuZGVmaW5lUHJvcGVydHkoe30sICdwYXNzaXZlJywge1xyXG4gIFx0XHRcdGdldDogZnVuY3Rpb24gKCkgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGdldHRlci1yZXR1cm5cclxuICBcdFx0XHRcdHN1cHBvcnRzUGFzc2l2ZU9wdGlvbiA9IHRydWU7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9KTtcclxuICBcdFx0d2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Rlc3RQYXNzaXZlRXZlbnRTdXBwb3J0JywgZmFsc2VGbiwgb3B0cyk7XHJcbiAgXHRcdHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCd0ZXN0UGFzc2l2ZUV2ZW50U3VwcG9ydCcsIGZhbHNlRm4sIG9wdHMpO1xyXG4gIFx0fSBjYXRjaCAoZSkge1xyXG4gIFx0XHQvLyBFcnJvcnMgY2FuIHNhZmVseSBiZSBpZ25vcmVkIHNpbmNlIHRoaXMgaXMgb25seSBhIGJyb3dzZXIgc3VwcG9ydCB0ZXN0LlxyXG4gIFx0fVxyXG4gIFx0cmV0dXJuIHN1cHBvcnRzUGFzc2l2ZU9wdGlvbjtcclxuICB9KCkpO1xyXG5cclxuICAvLyBAcHJvcGVydHkgY2FudmFzOiBCb29sZWFuXHJcbiAgLy8gYHRydWVgIHdoZW4gdGhlIGJyb3dzZXIgc3VwcG9ydHMgW2A8Y2FudmFzPmBdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0FQSS9DYW52YXNfQVBJKS5cclxuICB2YXIgY2FudmFzJDEgPSAoZnVuY3Rpb24gKCkge1xyXG4gIFx0cmV0dXJuICEhZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJykuZ2V0Q29udGV4dDtcclxuICB9KCkpO1xyXG5cclxuICAvLyBAcHJvcGVydHkgc3ZnOiBCb29sZWFuXHJcbiAgLy8gYHRydWVgIHdoZW4gdGhlIGJyb3dzZXIgc3VwcG9ydHMgW1NWR10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvU1ZHKS5cclxuICB2YXIgc3ZnJDEgPSAhIShkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMgJiYgc3ZnQ3JlYXRlKCdzdmcnKS5jcmVhdGVTVkdSZWN0KTtcclxuXHJcbiAgdmFyIGlubGluZVN2ZyA9ICEhc3ZnJDEgJiYgKGZ1bmN0aW9uICgpIHtcclxuICBcdHZhciBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcclxuICBcdGRpdi5pbm5lckhUTUwgPSAnPHN2Zy8+JztcclxuICBcdHJldHVybiAoZGl2LmZpcnN0Q2hpbGQgJiYgZGl2LmZpcnN0Q2hpbGQubmFtZXNwYWNlVVJJKSA9PT0gJ2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJztcclxuICB9KSgpO1xyXG5cclxuICAvLyBAcHJvcGVydHkgdm1sOiBCb29sZWFuXHJcbiAgLy8gYHRydWVgIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIFtWTUxdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1ZlY3Rvcl9NYXJrdXBfTGFuZ3VhZ2UpLlxyXG4gIHZhciB2bWwgPSAhc3ZnJDEgJiYgKGZ1bmN0aW9uICgpIHtcclxuICBcdHRyeSB7XHJcbiAgXHRcdHZhciBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcclxuICBcdFx0ZGl2LmlubmVySFRNTCA9ICc8djpzaGFwZSBhZGo9XCIxXCIvPic7XHJcblxyXG4gIFx0XHR2YXIgc2hhcGUgPSBkaXYuZmlyc3RDaGlsZDtcclxuICBcdFx0c2hhcGUuc3R5bGUuYmVoYXZpb3IgPSAndXJsKCNkZWZhdWx0I1ZNTCknO1xyXG5cclxuICBcdFx0cmV0dXJuIHNoYXBlICYmICh0eXBlb2Ygc2hhcGUuYWRqID09PSAnb2JqZWN0Jyk7XHJcblxyXG4gIFx0fSBjYXRjaCAoZSkge1xyXG4gIFx0XHRyZXR1cm4gZmFsc2U7XHJcbiAgXHR9XHJcbiAgfSgpKTtcclxuXHJcblxyXG4gIC8vIEBwcm9wZXJ0eSBtYWM6IEJvb2xlYW47IGB0cnVlYCB3aGVuIHRoZSBicm93c2VyIGlzIHJ1bm5pbmcgaW4gYSBNYWMgcGxhdGZvcm1cclxuICB2YXIgbWFjID0gbmF2aWdhdG9yLnBsYXRmb3JtLmluZGV4T2YoJ01hYycpID09PSAwO1xyXG5cclxuICAvLyBAcHJvcGVydHkgbWFjOiBCb29sZWFuOyBgdHJ1ZWAgd2hlbiB0aGUgYnJvd3NlciBpcyBydW5uaW5nIGluIGEgTGludXggcGxhdGZvcm1cclxuICB2YXIgbGludXggPSBuYXZpZ2F0b3IucGxhdGZvcm0uaW5kZXhPZignTGludXgnKSA9PT0gMDtcclxuXHJcbiAgZnVuY3Rpb24gdXNlckFnZW50Q29udGFpbnMoc3RyKSB7XHJcbiAgXHRyZXR1cm4gbmF2aWdhdG9yLnVzZXJBZ2VudC50b0xvd2VyQ2FzZSgpLmluZGV4T2Yoc3RyKSA+PSAwO1xyXG4gIH1cclxuXHJcblxyXG4gIHZhciBCcm93c2VyID0ge1xyXG4gIFx0aWU6IGllLFxyXG4gIFx0aWVsdDk6IGllbHQ5LFxyXG4gIFx0ZWRnZTogZWRnZSxcclxuICBcdHdlYmtpdDogd2Via2l0LFxyXG4gIFx0YW5kcm9pZDogYW5kcm9pZCxcclxuICBcdGFuZHJvaWQyMzogYW5kcm9pZDIzLFxyXG4gIFx0YW5kcm9pZFN0b2NrOiBhbmRyb2lkU3RvY2ssXHJcbiAgXHRvcGVyYTogb3BlcmEsXHJcbiAgXHRjaHJvbWU6IGNocm9tZSxcclxuICBcdGdlY2tvOiBnZWNrbyxcclxuICBcdHNhZmFyaTogc2FmYXJpLFxyXG4gIFx0cGhhbnRvbTogcGhhbnRvbSxcclxuICBcdG9wZXJhMTI6IG9wZXJhMTIsXHJcbiAgXHR3aW46IHdpbixcclxuICBcdGllM2Q6IGllM2QsXHJcbiAgXHR3ZWJraXQzZDogd2Via2l0M2QsXHJcbiAgXHRnZWNrbzNkOiBnZWNrbzNkLFxyXG4gIFx0YW55M2Q6IGFueTNkLFxyXG4gIFx0bW9iaWxlOiBtb2JpbGUsXHJcbiAgXHRtb2JpbGVXZWJraXQ6IG1vYmlsZVdlYmtpdCxcclxuICBcdG1vYmlsZVdlYmtpdDNkOiBtb2JpbGVXZWJraXQzZCxcclxuICBcdG1zUG9pbnRlcjogbXNQb2ludGVyLFxyXG4gIFx0cG9pbnRlcjogcG9pbnRlcixcclxuICBcdHRvdWNoOiB0b3VjaCxcclxuICBcdHRvdWNoTmF0aXZlOiB0b3VjaE5hdGl2ZSxcclxuICBcdG1vYmlsZU9wZXJhOiBtb2JpbGVPcGVyYSxcclxuICBcdG1vYmlsZUdlY2tvOiBtb2JpbGVHZWNrbyxcclxuICBcdHJldGluYTogcmV0aW5hLFxyXG4gIFx0cGFzc2l2ZUV2ZW50czogcGFzc2l2ZUV2ZW50cyxcclxuICBcdGNhbnZhczogY2FudmFzJDEsXHJcbiAgXHRzdmc6IHN2ZyQxLFxyXG4gIFx0dm1sOiB2bWwsXHJcbiAgXHRpbmxpbmVTdmc6IGlubGluZVN2ZyxcclxuICBcdG1hYzogbWFjLFxyXG4gIFx0bGludXg6IGxpbnV4XHJcbiAgfTtcblxuICAvKlxuICAgKiBFeHRlbmRzIEwuRG9tRXZlbnQgdG8gcHJvdmlkZSB0b3VjaCBzdXBwb3J0IGZvciBJbnRlcm5ldCBFeHBsb3JlciBhbmQgV2luZG93cy1iYXNlZCBkZXZpY2VzLlxuICAgKi9cblxuICB2YXIgUE9JTlRFUl9ET1dOID0gICBCcm93c2VyLm1zUG9pbnRlciA/ICdNU1BvaW50ZXJEb3duJyAgIDogJ3BvaW50ZXJkb3duJztcbiAgdmFyIFBPSU5URVJfTU9WRSA9ICAgQnJvd3Nlci5tc1BvaW50ZXIgPyAnTVNQb2ludGVyTW92ZScgICA6ICdwb2ludGVybW92ZSc7XG4gIHZhciBQT0lOVEVSX1VQID0gICAgIEJyb3dzZXIubXNQb2ludGVyID8gJ01TUG9pbnRlclVwJyAgICAgOiAncG9pbnRlcnVwJztcbiAgdmFyIFBPSU5URVJfQ0FOQ0VMID0gQnJvd3Nlci5tc1BvaW50ZXIgPyAnTVNQb2ludGVyQ2FuY2VsJyA6ICdwb2ludGVyY2FuY2VsJztcbiAgdmFyIHBFdmVudCA9IHtcbiAgXHR0b3VjaHN0YXJ0ICA6IFBPSU5URVJfRE9XTixcbiAgXHR0b3VjaG1vdmUgICA6IFBPSU5URVJfTU9WRSxcbiAgXHR0b3VjaGVuZCAgICA6IFBPSU5URVJfVVAsXG4gIFx0dG91Y2hjYW5jZWwgOiBQT0lOVEVSX0NBTkNFTFxuICB9O1xuICB2YXIgaGFuZGxlID0ge1xuICBcdHRvdWNoc3RhcnQgIDogX29uUG9pbnRlclN0YXJ0LFxuICBcdHRvdWNobW92ZSAgIDogX2hhbmRsZVBvaW50ZXIsXG4gIFx0dG91Y2hlbmQgICAgOiBfaGFuZGxlUG9pbnRlcixcbiAgXHR0b3VjaGNhbmNlbCA6IF9oYW5kbGVQb2ludGVyXG4gIH07XG4gIHZhciBfcG9pbnRlcnMgPSB7fTtcbiAgdmFyIF9wb2ludGVyRG9jTGlzdGVuZXIgPSBmYWxzZTtcblxuICAvLyBQcm92aWRlcyBhIHRvdWNoIGV2ZW50cyB3cmFwcGVyIGZvciAobXMpcG9pbnRlciBldmVudHMuXG4gIC8vIHJlZiBodHRwczovL3d3dy53My5vcmcvVFIvcG9pbnRlcmV2ZW50cy8gaHR0cHM6Ly93d3cudzMub3JnL0J1Z3MvUHVibGljL3Nob3dfYnVnLmNnaT9pZD0yMjg5MFxuXG4gIGZ1bmN0aW9uIGFkZFBvaW50ZXJMaXN0ZW5lcihvYmosIHR5cGUsIGhhbmRsZXIpIHtcbiAgXHRpZiAodHlwZSA9PT0gJ3RvdWNoc3RhcnQnKSB7XG4gIFx0XHRfYWRkUG9pbnRlckRvY0xpc3RlbmVyKCk7XG4gIFx0fVxuICBcdGlmICghaGFuZGxlW3R5cGVdKSB7XG4gIFx0XHRjb25zb2xlLndhcm4oJ3dyb25nIGV2ZW50IHNwZWNpZmllZDonLCB0eXBlKTtcbiAgXHRcdHJldHVybiBmYWxzZUZuO1xuICBcdH1cbiAgXHRoYW5kbGVyID0gaGFuZGxlW3R5cGVdLmJpbmQodGhpcywgaGFuZGxlcik7XG4gIFx0b2JqLmFkZEV2ZW50TGlzdGVuZXIocEV2ZW50W3R5cGVdLCBoYW5kbGVyLCBmYWxzZSk7XG4gIFx0cmV0dXJuIGhhbmRsZXI7XG4gIH1cblxuICBmdW5jdGlvbiByZW1vdmVQb2ludGVyTGlzdGVuZXIob2JqLCB0eXBlLCBoYW5kbGVyKSB7XG4gIFx0aWYgKCFwRXZlbnRbdHlwZV0pIHtcbiAgXHRcdGNvbnNvbGUud2Fybignd3JvbmcgZXZlbnQgc3BlY2lmaWVkOicsIHR5cGUpO1xuICBcdFx0cmV0dXJuO1xuICBcdH1cbiAgXHRvYmoucmVtb3ZlRXZlbnRMaXN0ZW5lcihwRXZlbnRbdHlwZV0sIGhhbmRsZXIsIGZhbHNlKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIF9nbG9iYWxQb2ludGVyRG93bihlKSB7XG4gIFx0X3BvaW50ZXJzW2UucG9pbnRlcklkXSA9IGU7XG4gIH1cblxuICBmdW5jdGlvbiBfZ2xvYmFsUG9pbnRlck1vdmUoZSkge1xuICBcdGlmIChfcG9pbnRlcnNbZS5wb2ludGVySWRdKSB7XG4gIFx0XHRfcG9pbnRlcnNbZS5wb2ludGVySWRdID0gZTtcbiAgXHR9XG4gIH1cblxuICBmdW5jdGlvbiBfZ2xvYmFsUG9pbnRlclVwKGUpIHtcbiAgXHRkZWxldGUgX3BvaW50ZXJzW2UucG9pbnRlcklkXTtcbiAgfVxuXG4gIGZ1bmN0aW9uIF9hZGRQb2ludGVyRG9jTGlzdGVuZXIoKSB7XG4gIFx0Ly8gbmVlZCB0byBrZWVwIHRyYWNrIG9mIHdoYXQgcG9pbnRlcnMgYW5kIGhvdyBtYW55IGFyZSBhY3RpdmUgdG8gcHJvdmlkZSBlLnRvdWNoZXMgZW11bGF0aW9uXG4gIFx0aWYgKCFfcG9pbnRlckRvY0xpc3RlbmVyKSB7XG4gIFx0XHQvLyB3ZSBsaXN0ZW4gZG9jdW1lbnQgYXMgYW55IGRyYWdzIHRoYXQgZW5kIGJ5IG1vdmluZyB0aGUgdG91Y2ggb2ZmIHRoZSBzY3JlZW4gZ2V0IGZpcmVkIHRoZXJlXG4gIFx0XHRkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFBPSU5URVJfRE9XTiwgX2dsb2JhbFBvaW50ZXJEb3duLCB0cnVlKTtcbiAgXHRcdGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoUE9JTlRFUl9NT1ZFLCBfZ2xvYmFsUG9pbnRlck1vdmUsIHRydWUpO1xuICBcdFx0ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihQT0lOVEVSX1VQLCBfZ2xvYmFsUG9pbnRlclVwLCB0cnVlKTtcbiAgXHRcdGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoUE9JTlRFUl9DQU5DRUwsIF9nbG9iYWxQb2ludGVyVXAsIHRydWUpO1xuXG4gIFx0XHRfcG9pbnRlckRvY0xpc3RlbmVyID0gdHJ1ZTtcbiAgXHR9XG4gIH1cblxuICBmdW5jdGlvbiBfaGFuZGxlUG9pbnRlcihoYW5kbGVyLCBlKSB7XG4gIFx0aWYgKGUucG9pbnRlclR5cGUgPT09IChlLk1TUE9JTlRFUl9UWVBFX01PVVNFIHx8ICdtb3VzZScpKSB7IHJldHVybjsgfVxuXG4gIFx0ZS50b3VjaGVzID0gW107XG4gIFx0Zm9yICh2YXIgaSBpbiBfcG9pbnRlcnMpIHtcbiAgXHRcdGUudG91Y2hlcy5wdXNoKF9wb2ludGVyc1tpXSk7XG4gIFx0fVxuICBcdGUuY2hhbmdlZFRvdWNoZXMgPSBbZV07XG5cbiAgXHRoYW5kbGVyKGUpO1xuICB9XG5cbiAgZnVuY3Rpb24gX29uUG9pbnRlclN0YXJ0KGhhbmRsZXIsIGUpIHtcbiAgXHQvLyBJRTEwIHNwZWNpZmljOiBNc1RvdWNoIG5lZWRzIHByZXZlbnREZWZhdWx0LiBTZWUgIzIwMDBcbiAgXHRpZiAoZS5NU1BPSU5URVJfVFlQRV9UT1VDSCAmJiBlLnBvaW50ZXJUeXBlID09PSBlLk1TUE9JTlRFUl9UWVBFX1RPVUNIKSB7XG4gIFx0XHRwcmV2ZW50RGVmYXVsdChlKTtcbiAgXHR9XG4gIFx0X2hhbmRsZVBvaW50ZXIoaGFuZGxlciwgZSk7XG4gIH1cblxuICAvKlxyXG4gICAqIEV4dGVuZHMgdGhlIGV2ZW50IGhhbmRsaW5nIGNvZGUgd2l0aCBkb3VibGUgdGFwIHN1cHBvcnQgZm9yIG1vYmlsZSBicm93c2Vycy5cclxuICAgKlxyXG4gICAqIE5vdGU6IGN1cnJlbnRseSBtb3N0IGJyb3dzZXJzIGZpcmUgbmF0aXZlIGRibGNsaWNrLCB3aXRoIG9ubHkgYSBmZXcgZXhjZXB0aW9uc1xyXG4gICAqIChzZWUgaHR0cHM6Ly9naXRodWIuY29tL0xlYWZsZXQvTGVhZmxldC9pc3N1ZXMvNzAxMiNpc3N1ZWNvbW1lbnQtNTk1MDg3Mzg2KVxyXG4gICAqL1xyXG5cclxuICBmdW5jdGlvbiBtYWtlRGJsY2xpY2soZXZlbnQpIHtcclxuICBcdC8vIGluIG1vZGVybiBicm93c2VycyBgdHlwZWAgY2Fubm90IGJlIGp1c3Qgb3ZlcnJpZGRlbjpcclxuICBcdC8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0Vycm9ycy9HZXR0ZXJfb25seVxyXG4gIFx0dmFyIG5ld0V2ZW50ID0ge30sXHJcbiAgXHQgICAgcHJvcCwgaTtcclxuICBcdGZvciAoaSBpbiBldmVudCkge1xyXG4gIFx0XHRwcm9wID0gZXZlbnRbaV07XHJcbiAgXHRcdG5ld0V2ZW50W2ldID0gcHJvcCAmJiBwcm9wLmJpbmQgPyBwcm9wLmJpbmQoZXZlbnQpIDogcHJvcDtcclxuICBcdH1cclxuICBcdGV2ZW50ID0gbmV3RXZlbnQ7XHJcbiAgXHRuZXdFdmVudC50eXBlID0gJ2RibGNsaWNrJztcclxuICBcdG5ld0V2ZW50LmRldGFpbCA9IDI7XHJcbiAgXHRuZXdFdmVudC5pc1RydXN0ZWQgPSBmYWxzZTtcclxuICBcdG5ld0V2ZW50Ll9zaW11bGF0ZWQgPSB0cnVlOyAvLyBmb3IgZGVidWcgcHVycG9zZXNcclxuICBcdHJldHVybiBuZXdFdmVudDtcclxuICB9XHJcblxyXG4gIHZhciBkZWxheSA9IDIwMDtcclxuICBmdW5jdGlvbiBhZGREb3VibGVUYXBMaXN0ZW5lcihvYmosIGhhbmRsZXIpIHtcclxuICBcdC8vIE1vc3QgYnJvd3NlcnMgaGFuZGxlIGRvdWJsZSB0YXAgbmF0aXZlbHlcclxuICBcdG9iai5hZGRFdmVudExpc3RlbmVyKCdkYmxjbGljaycsIGhhbmRsZXIpO1xyXG5cclxuICBcdC8vIE9uIHNvbWUgcGxhdGZvcm1zIHRoZSBicm93c2VyIGRvZXNuJ3QgZmlyZSBuYXRpdmUgZGJsY2xpY2tzIGZvciB0b3VjaCBldmVudHMuXHJcbiAgXHQvLyBJdCBzZWVtcyB0aGF0IGluIGFsbCBzdWNoIGNhc2VzIGBkZXRhaWxgIHByb3BlcnR5IG9mIGBjbGlja2AgZXZlbnQgaXMgYWx3YXlzIGAxYC5cclxuICBcdC8vIFNvIGhlcmUgd2UgcmVseSBvbiB0aGF0IGZhY3QgdG8gYXZvaWQgZXhjZXNzaXZlICdkYmxjbGljaycgc2ltdWxhdGlvbiB3aGVuIG5vdCBuZWVkZWQuXHJcbiAgXHR2YXIgbGFzdCA9IDAsXHJcbiAgXHQgICAgZGV0YWlsO1xyXG4gIFx0ZnVuY3Rpb24gc2ltRGJsY2xpY2soZSkge1xyXG4gIFx0XHRpZiAoZS5kZXRhaWwgIT09IDEpIHtcclxuICBcdFx0XHRkZXRhaWwgPSBlLmRldGFpbDsgLy8ga2VlcCBpbiBzeW5jIHRvIGF2b2lkIGZhbHNlIGRibGNsaWNrIGluIHNvbWUgY2FzZXNcclxuICBcdFx0XHRyZXR1cm47XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmIChlLnBvaW50ZXJUeXBlID09PSAnbW91c2UnIHx8XHJcbiAgXHRcdFx0KGUuc291cmNlQ2FwYWJpbGl0aWVzICYmICFlLnNvdXJjZUNhcGFiaWxpdGllcy5maXJlc1RvdWNoRXZlbnRzKSkge1xyXG5cclxuICBcdFx0XHRyZXR1cm47XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdC8vIFdoZW4gY2xpY2tpbmcgb24gYW4gPGlucHV0PiwgdGhlIGJyb3dzZXIgZ2VuZXJhdGVzIGEgY2xpY2sgb24gaXRzXHJcbiAgXHRcdC8vIDxsYWJlbD4gKGFuZCB2aWNlIHZlcnNhKSB0cmlnZ2VyaW5nIHR3byBjbGlja3MgaW4gcXVpY2sgc3VjY2Vzc2lvbi5cclxuICBcdFx0Ly8gVGhpcyBpZ25vcmVzIGNsaWNrcyBvbiBlbGVtZW50cyB3aGljaCBhcmUgYSBsYWJlbCB3aXRoIGEgJ2ZvcidcclxuICBcdFx0Ly8gYXR0cmlidXRlIChvciBjaGlsZHJlbiBvZiBzdWNoIGEgbGFiZWwpLCBidXQgbm90IGNoaWxkcmVuIG9mXHJcbiAgXHRcdC8vIGEgPGlucHV0Pi5cclxuICBcdFx0dmFyIHBhdGggPSBnZXRQcm9wYWdhdGlvblBhdGgoZSk7XHJcbiAgXHRcdGlmIChwYXRoLnNvbWUoZnVuY3Rpb24gKGVsKSB7XHJcbiAgXHRcdFx0cmV0dXJuIGVsIGluc3RhbmNlb2YgSFRNTExhYmVsRWxlbWVudCAmJiBlbC5hdHRyaWJ1dGVzLmZvcjtcclxuICBcdFx0fSkgJiZcclxuICBcdFx0XHQhcGF0aC5zb21lKGZ1bmN0aW9uIChlbCkge1xyXG4gIFx0XHRcdFx0cmV0dXJuIChcclxuICBcdFx0XHRcdFx0ZWwgaW5zdGFuY2VvZiBIVE1MSW5wdXRFbGVtZW50IHx8XHJcbiAgXHRcdFx0XHRcdGVsIGluc3RhbmNlb2YgSFRNTFNlbGVjdEVsZW1lbnRcclxuICBcdFx0XHRcdCk7XHJcbiAgXHRcdFx0fSlcclxuICBcdFx0KSB7XHJcbiAgXHRcdFx0cmV0dXJuO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgbm93ID0gRGF0ZS5ub3coKTtcclxuICBcdFx0aWYgKG5vdyAtIGxhc3QgPD0gZGVsYXkpIHtcclxuICBcdFx0XHRkZXRhaWwrKztcclxuICBcdFx0XHRpZiAoZGV0YWlsID09PSAyKSB7XHJcbiAgXHRcdFx0XHRoYW5kbGVyKG1ha2VEYmxjbGljayhlKSk7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdGRldGFpbCA9IDE7XHJcbiAgXHRcdH1cclxuICBcdFx0bGFzdCA9IG5vdztcclxuICBcdH1cclxuXHJcbiAgXHRvYmouYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBzaW1EYmxjbGljayk7XHJcblxyXG4gIFx0cmV0dXJuIHtcclxuICBcdFx0ZGJsY2xpY2s6IGhhbmRsZXIsXHJcbiAgXHRcdHNpbURibGNsaWNrOiBzaW1EYmxjbGlja1xyXG4gIFx0fTtcclxuICB9XHJcblxyXG4gIGZ1bmN0aW9uIHJlbW92ZURvdWJsZVRhcExpc3RlbmVyKG9iaiwgaGFuZGxlcnMpIHtcclxuICBcdG9iai5yZW1vdmVFdmVudExpc3RlbmVyKCdkYmxjbGljaycsIGhhbmRsZXJzLmRibGNsaWNrKTtcclxuICBcdG9iai5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIGhhbmRsZXJzLnNpbURibGNsaWNrKTtcclxuICB9XG5cbiAgLypcclxuICAgKiBAbmFtZXNwYWNlIERvbVV0aWxcclxuICAgKlxyXG4gICAqIFV0aWxpdHkgZnVuY3Rpb25zIHRvIHdvcmsgd2l0aCB0aGUgW0RPTV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQVBJL0RvY3VtZW50X09iamVjdF9Nb2RlbClcclxuICAgKiB0cmVlLCB1c2VkIGJ5IExlYWZsZXQgaW50ZXJuYWxseS5cclxuICAgKlxyXG4gICAqIE1vc3QgZnVuY3Rpb25zIGV4cGVjdGluZyBvciByZXR1cm5pbmcgYSBgSFRNTEVsZW1lbnRgIGFsc28gd29yayBmb3JcclxuICAgKiBTVkcgZWxlbWVudHMuIFRoZSBvbmx5IGRpZmZlcmVuY2UgaXMgdGhhdCBjbGFzc2VzIHJlZmVyIHRvIENTUyBjbGFzc2VzXHJcbiAgICogaW4gSFRNTCBhbmQgU1ZHIGNsYXNzZXMgaW4gU1ZHLlxyXG4gICAqL1xyXG5cclxuXHJcbiAgLy8gQHByb3BlcnR5IFRSQU5TRk9STTogU3RyaW5nXHJcbiAgLy8gVmVuZG9yLXByZWZpeGVkIHRyYW5zZm9ybSBzdHlsZSBuYW1lIChlLmcuIGAnd2Via2l0VHJhbnNmb3JtJ2AgZm9yIFdlYktpdCkuXHJcbiAgdmFyIFRSQU5TRk9STSA9IHRlc3RQcm9wKFxyXG4gIFx0Wyd0cmFuc2Zvcm0nLCAnd2Via2l0VHJhbnNmb3JtJywgJ09UcmFuc2Zvcm0nLCAnTW96VHJhbnNmb3JtJywgJ21zVHJhbnNmb3JtJ10pO1xyXG5cclxuICAvLyB3ZWJraXRUcmFuc2l0aW9uIGNvbWVzIGZpcnN0IGJlY2F1c2Ugc29tZSBicm93c2VyIHZlcnNpb25zIHRoYXQgZHJvcCB2ZW5kb3IgcHJlZml4IGRvbid0IGRvXHJcbiAgLy8gdGhlIHNhbWUgZm9yIHRoZSB0cmFuc2l0aW9uZW5kIGV2ZW50LCBpbiBwYXJ0aWN1bGFyIHRoZSBBbmRyb2lkIDQuMSBzdG9jayBicm93c2VyXHJcblxyXG4gIC8vIEBwcm9wZXJ0eSBUUkFOU0lUSU9OOiBTdHJpbmdcclxuICAvLyBWZW5kb3ItcHJlZml4ZWQgdHJhbnNpdGlvbiBzdHlsZSBuYW1lLlxyXG4gIHZhciBUUkFOU0lUSU9OID0gdGVzdFByb3AoXHJcbiAgXHRbJ3dlYmtpdFRyYW5zaXRpb24nLCAndHJhbnNpdGlvbicsICdPVHJhbnNpdGlvbicsICdNb3pUcmFuc2l0aW9uJywgJ21zVHJhbnNpdGlvbiddKTtcclxuXHJcbiAgLy8gQHByb3BlcnR5IFRSQU5TSVRJT05fRU5EOiBTdHJpbmdcclxuICAvLyBWZW5kb3ItcHJlZml4ZWQgdHJhbnNpdGlvbmVuZCBldmVudCBuYW1lLlxyXG4gIHZhciBUUkFOU0lUSU9OX0VORCA9XHJcbiAgXHRUUkFOU0lUSU9OID09PSAnd2Via2l0VHJhbnNpdGlvbicgfHwgVFJBTlNJVElPTiA9PT0gJ09UcmFuc2l0aW9uJyA/IFRSQU5TSVRJT04gKyAnRW5kJyA6ICd0cmFuc2l0aW9uZW5kJztcclxuXHJcblxyXG4gIC8vIEBmdW5jdGlvbiBnZXQoaWQ6IFN0cmluZ3xIVE1MRWxlbWVudCk6IEhUTUxFbGVtZW50XHJcbiAgLy8gUmV0dXJucyBhbiBlbGVtZW50IGdpdmVuIGl0cyBET00gaWQsIG9yIHJldHVybnMgdGhlIGVsZW1lbnQgaXRzZWxmXHJcbiAgLy8gaWYgaXQgd2FzIHBhc3NlZCBkaXJlY3RseS5cclxuICBmdW5jdGlvbiBnZXQoaWQpIHtcclxuICBcdHJldHVybiB0eXBlb2YgaWQgPT09ICdzdHJpbmcnID8gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpIDogaWQ7XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gZ2V0U3R5bGUoZWw6IEhUTUxFbGVtZW50LCBzdHlsZUF0dHJpYjogU3RyaW5nKTogU3RyaW5nXHJcbiAgLy8gUmV0dXJucyB0aGUgdmFsdWUgZm9yIGEgY2VydGFpbiBzdHlsZSBhdHRyaWJ1dGUgb24gYW4gZWxlbWVudCxcclxuICAvLyBpbmNsdWRpbmcgY29tcHV0ZWQgdmFsdWVzIG9yIHZhbHVlcyBzZXQgdGhyb3VnaCBDU1MuXHJcbiAgZnVuY3Rpb24gZ2V0U3R5bGUoZWwsIHN0eWxlKSB7XHJcbiAgXHR2YXIgdmFsdWUgPSBlbC5zdHlsZVtzdHlsZV0gfHwgKGVsLmN1cnJlbnRTdHlsZSAmJiBlbC5jdXJyZW50U3R5bGVbc3R5bGVdKTtcclxuXHJcbiAgXHRpZiAoKCF2YWx1ZSB8fCB2YWx1ZSA9PT0gJ2F1dG8nKSAmJiBkb2N1bWVudC5kZWZhdWx0Vmlldykge1xyXG4gIFx0XHR2YXIgY3NzID0gZG9jdW1lbnQuZGVmYXVsdFZpZXcuZ2V0Q29tcHV0ZWRTdHlsZShlbCwgbnVsbCk7XHJcbiAgXHRcdHZhbHVlID0gY3NzID8gY3NzW3N0eWxlXSA6IG51bGw7XHJcbiAgXHR9XHJcbiAgXHRyZXR1cm4gdmFsdWUgPT09ICdhdXRvJyA/IG51bGwgOiB2YWx1ZTtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBjcmVhdGUodGFnTmFtZTogU3RyaW5nLCBjbGFzc05hbWU/OiBTdHJpbmcsIGNvbnRhaW5lcj86IEhUTUxFbGVtZW50KTogSFRNTEVsZW1lbnRcclxuICAvLyBDcmVhdGVzIGFuIEhUTUwgZWxlbWVudCB3aXRoIGB0YWdOYW1lYCwgc2V0cyBpdHMgY2xhc3MgdG8gYGNsYXNzTmFtZWAsIGFuZCBvcHRpb25hbGx5IGFwcGVuZHMgaXQgdG8gYGNvbnRhaW5lcmAgZWxlbWVudC5cclxuICBmdW5jdGlvbiBjcmVhdGUkMSh0YWdOYW1lLCBjbGFzc05hbWUsIGNvbnRhaW5lcikge1xyXG4gIFx0dmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWdOYW1lKTtcclxuICBcdGVsLmNsYXNzTmFtZSA9IGNsYXNzTmFtZSB8fCAnJztcclxuXHJcbiAgXHRpZiAoY29udGFpbmVyKSB7XHJcbiAgXHRcdGNvbnRhaW5lci5hcHBlbmRDaGlsZChlbCk7XHJcbiAgXHR9XHJcbiAgXHRyZXR1cm4gZWw7XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gcmVtb3ZlKGVsOiBIVE1MRWxlbWVudClcclxuICAvLyBSZW1vdmVzIGBlbGAgZnJvbSBpdHMgcGFyZW50IGVsZW1lbnRcclxuICBmdW5jdGlvbiByZW1vdmUoZWwpIHtcclxuICBcdHZhciBwYXJlbnQgPSBlbC5wYXJlbnROb2RlO1xyXG4gIFx0aWYgKHBhcmVudCkge1xyXG4gIFx0XHRwYXJlbnQucmVtb3ZlQ2hpbGQoZWwpO1xyXG4gIFx0fVxyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGVtcHR5KGVsOiBIVE1MRWxlbWVudClcclxuICAvLyBSZW1vdmVzIGFsbCBvZiBgZWxgJ3MgY2hpbGRyZW4gZWxlbWVudHMgZnJvbSBgZWxgXHJcbiAgZnVuY3Rpb24gZW1wdHkoZWwpIHtcclxuICBcdHdoaWxlIChlbC5maXJzdENoaWxkKSB7XHJcbiAgXHRcdGVsLnJlbW92ZUNoaWxkKGVsLmZpcnN0Q2hpbGQpO1xyXG4gIFx0fVxyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIHRvRnJvbnQoZWw6IEhUTUxFbGVtZW50KVxyXG4gIC8vIE1ha2VzIGBlbGAgdGhlIGxhc3QgY2hpbGQgb2YgaXRzIHBhcmVudCwgc28gaXQgcmVuZGVycyBpbiBmcm9udCBvZiB0aGUgb3RoZXIgY2hpbGRyZW4uXHJcbiAgZnVuY3Rpb24gdG9Gcm9udChlbCkge1xyXG4gIFx0dmFyIHBhcmVudCA9IGVsLnBhcmVudE5vZGU7XHJcbiAgXHRpZiAocGFyZW50ICYmIHBhcmVudC5sYXN0Q2hpbGQgIT09IGVsKSB7XHJcbiAgXHRcdHBhcmVudC5hcHBlbmRDaGlsZChlbCk7XHJcbiAgXHR9XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gdG9CYWNrKGVsOiBIVE1MRWxlbWVudClcclxuICAvLyBNYWtlcyBgZWxgIHRoZSBmaXJzdCBjaGlsZCBvZiBpdHMgcGFyZW50LCBzbyBpdCByZW5kZXJzIGJlaGluZCB0aGUgb3RoZXIgY2hpbGRyZW4uXHJcbiAgZnVuY3Rpb24gdG9CYWNrKGVsKSB7XHJcbiAgXHR2YXIgcGFyZW50ID0gZWwucGFyZW50Tm9kZTtcclxuICBcdGlmIChwYXJlbnQgJiYgcGFyZW50LmZpcnN0Q2hpbGQgIT09IGVsKSB7XHJcbiAgXHRcdHBhcmVudC5pbnNlcnRCZWZvcmUoZWwsIHBhcmVudC5maXJzdENoaWxkKTtcclxuICBcdH1cclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBoYXNDbGFzcyhlbDogSFRNTEVsZW1lbnQsIG5hbWU6IFN0cmluZyk6IEJvb2xlYW5cclxuICAvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZWxlbWVudCdzIGNsYXNzIGF0dHJpYnV0ZSBjb250YWlucyBgbmFtZWAuXHJcbiAgZnVuY3Rpb24gaGFzQ2xhc3MoZWwsIG5hbWUpIHtcclxuICBcdGlmIChlbC5jbGFzc0xpc3QgIT09IHVuZGVmaW5lZCkge1xyXG4gIFx0XHRyZXR1cm4gZWwuY2xhc3NMaXN0LmNvbnRhaW5zKG5hbWUpO1xyXG4gIFx0fVxyXG4gIFx0dmFyIGNsYXNzTmFtZSA9IGdldENsYXNzKGVsKTtcclxuICBcdHJldHVybiBjbGFzc05hbWUubGVuZ3RoID4gMCAmJiBuZXcgUmVnRXhwKCcoXnxcXFxccyknICsgbmFtZSArICcoXFxcXHN8JCknKS50ZXN0KGNsYXNzTmFtZSk7XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gYWRkQ2xhc3MoZWw6IEhUTUxFbGVtZW50LCBuYW1lOiBTdHJpbmcpXHJcbiAgLy8gQWRkcyBgbmFtZWAgdG8gdGhlIGVsZW1lbnQncyBjbGFzcyBhdHRyaWJ1dGUuXHJcbiAgZnVuY3Rpb24gYWRkQ2xhc3MoZWwsIG5hbWUpIHtcclxuICBcdGlmIChlbC5jbGFzc0xpc3QgIT09IHVuZGVmaW5lZCkge1xyXG4gIFx0XHR2YXIgY2xhc3NlcyA9IHNwbGl0V29yZHMobmFtZSk7XHJcbiAgXHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBjbGFzc2VzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdFx0ZWwuY2xhc3NMaXN0LmFkZChjbGFzc2VzW2ldKTtcclxuICBcdFx0fVxyXG4gIFx0fSBlbHNlIGlmICghaGFzQ2xhc3MoZWwsIG5hbWUpKSB7XHJcbiAgXHRcdHZhciBjbGFzc05hbWUgPSBnZXRDbGFzcyhlbCk7XHJcbiAgXHRcdHNldENsYXNzKGVsLCAoY2xhc3NOYW1lID8gY2xhc3NOYW1lICsgJyAnIDogJycpICsgbmFtZSk7XHJcbiAgXHR9XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gcmVtb3ZlQ2xhc3MoZWw6IEhUTUxFbGVtZW50LCBuYW1lOiBTdHJpbmcpXHJcbiAgLy8gUmVtb3ZlcyBgbmFtZWAgZnJvbSB0aGUgZWxlbWVudCdzIGNsYXNzIGF0dHJpYnV0ZS5cclxuICBmdW5jdGlvbiByZW1vdmVDbGFzcyhlbCwgbmFtZSkge1xyXG4gIFx0aWYgKGVsLmNsYXNzTGlzdCAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgXHRcdGVsLmNsYXNzTGlzdC5yZW1vdmUobmFtZSk7XHJcbiAgXHR9IGVsc2Uge1xyXG4gIFx0XHRzZXRDbGFzcyhlbCwgdHJpbSgoJyAnICsgZ2V0Q2xhc3MoZWwpICsgJyAnKS5yZXBsYWNlKCcgJyArIG5hbWUgKyAnICcsICcgJykpKTtcclxuICBcdH1cclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBzZXRDbGFzcyhlbDogSFRNTEVsZW1lbnQsIG5hbWU6IFN0cmluZylcclxuICAvLyBTZXRzIHRoZSBlbGVtZW50J3MgY2xhc3MuXHJcbiAgZnVuY3Rpb24gc2V0Q2xhc3MoZWwsIG5hbWUpIHtcclxuICBcdGlmIChlbC5jbGFzc05hbWUuYmFzZVZhbCA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgXHRcdGVsLmNsYXNzTmFtZSA9IG5hbWU7XHJcbiAgXHR9IGVsc2Uge1xyXG4gIFx0XHQvLyBpbiBjYXNlIG9mIFNWRyBlbGVtZW50XHJcbiAgXHRcdGVsLmNsYXNzTmFtZS5iYXNlVmFsID0gbmFtZTtcclxuICBcdH1cclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBnZXRDbGFzcyhlbDogSFRNTEVsZW1lbnQpOiBTdHJpbmdcclxuICAvLyBSZXR1cm5zIHRoZSBlbGVtZW50J3MgY2xhc3MuXHJcbiAgZnVuY3Rpb24gZ2V0Q2xhc3MoZWwpIHtcclxuICBcdC8vIENoZWNrIGlmIHRoZSBlbGVtZW50IGlzIGFuIFNWR0VsZW1lbnRJbnN0YW5jZSBhbmQgdXNlIHRoZSBjb3JyZXNwb25kaW5nRWxlbWVudCBpbnN0ZWFkXHJcbiAgXHQvLyAoUmVxdWlyZWQgZm9yIGxpbmtlZCBTVkcgZWxlbWVudHMgaW4gSUUxMS4pXHJcbiAgXHRpZiAoZWwuY29ycmVzcG9uZGluZ0VsZW1lbnQpIHtcclxuICBcdFx0ZWwgPSBlbC5jb3JyZXNwb25kaW5nRWxlbWVudDtcclxuICBcdH1cclxuICBcdHJldHVybiBlbC5jbGFzc05hbWUuYmFzZVZhbCA9PT0gdW5kZWZpbmVkID8gZWwuY2xhc3NOYW1lIDogZWwuY2xhc3NOYW1lLmJhc2VWYWw7XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gc2V0T3BhY2l0eShlbDogSFRNTEVsZW1lbnQsIG9wYWNpdHk6IE51bWJlcilcclxuICAvLyBTZXQgdGhlIG9wYWNpdHkgb2YgYW4gZWxlbWVudCAoaW5jbHVkaW5nIG9sZCBJRSBzdXBwb3J0KS5cclxuICAvLyBgb3BhY2l0eWAgbXVzdCBiZSBhIG51bWJlciBmcm9tIGAwYCB0byBgMWAuXHJcbiAgZnVuY3Rpb24gc2V0T3BhY2l0eShlbCwgdmFsdWUpIHtcclxuICBcdGlmICgnb3BhY2l0eScgaW4gZWwuc3R5bGUpIHtcclxuICBcdFx0ZWwuc3R5bGUub3BhY2l0eSA9IHZhbHVlO1xyXG4gIFx0fSBlbHNlIGlmICgnZmlsdGVyJyBpbiBlbC5zdHlsZSkge1xyXG4gIFx0XHRfc2V0T3BhY2l0eUlFKGVsLCB2YWx1ZSk7XHJcbiAgXHR9XHJcbiAgfVxyXG5cclxuICBmdW5jdGlvbiBfc2V0T3BhY2l0eUlFKGVsLCB2YWx1ZSkge1xyXG4gIFx0dmFyIGZpbHRlciA9IGZhbHNlLFxyXG4gIFx0ICAgIGZpbHRlck5hbWUgPSAnRFhJbWFnZVRyYW5zZm9ybS5NaWNyb3NvZnQuQWxwaGEnO1xyXG5cclxuICBcdC8vIGZpbHRlcnMgY29sbGVjdGlvbiB0aHJvd3MgYW4gZXJyb3IgaWYgd2UgdHJ5IHRvIHJldHJpZXZlIGEgZmlsdGVyIHRoYXQgZG9lc24ndCBleGlzdFxyXG4gIFx0dHJ5IHtcclxuICBcdFx0ZmlsdGVyID0gZWwuZmlsdGVycy5pdGVtKGZpbHRlck5hbWUpO1xyXG4gIFx0fSBjYXRjaCAoZSkge1xyXG4gIFx0XHQvLyBkb24ndCBzZXQgb3BhY2l0eSB0byAxIGlmIHdlIGhhdmVuJ3QgYWxyZWFkeSBzZXQgYW4gb3BhY2l0eSxcclxuICBcdFx0Ly8gaXQgaXNuJ3QgbmVlZGVkIGFuZCBicmVha3MgdHJhbnNwYXJlbnQgcG5ncy5cclxuICBcdFx0aWYgKHZhbHVlID09PSAxKSB7IHJldHVybjsgfVxyXG4gIFx0fVxyXG5cclxuICBcdHZhbHVlID0gTWF0aC5yb3VuZCh2YWx1ZSAqIDEwMCk7XHJcblxyXG4gIFx0aWYgKGZpbHRlcikge1xyXG4gIFx0XHRmaWx0ZXIuRW5hYmxlZCA9ICh2YWx1ZSAhPT0gMTAwKTtcclxuICBcdFx0ZmlsdGVyLk9wYWNpdHkgPSB2YWx1ZTtcclxuICBcdH0gZWxzZSB7XHJcbiAgXHRcdGVsLnN0eWxlLmZpbHRlciArPSAnIHByb2dpZDonICsgZmlsdGVyTmFtZSArICcob3BhY2l0eT0nICsgdmFsdWUgKyAnKSc7XHJcbiAgXHR9XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gdGVzdFByb3AocHJvcHM6IFN0cmluZ1tdKTogU3RyaW5nfGZhbHNlXHJcbiAgLy8gR29lcyB0aHJvdWdoIHRoZSBhcnJheSBvZiBzdHlsZSBuYW1lcyBhbmQgcmV0dXJucyB0aGUgZmlyc3QgbmFtZVxyXG4gIC8vIHRoYXQgaXMgYSB2YWxpZCBzdHlsZSBuYW1lIGZvciBhbiBlbGVtZW50LiBJZiBubyBzdWNoIG5hbWUgaXMgZm91bmQsXHJcbiAgLy8gaXQgcmV0dXJucyBmYWxzZS4gVXNlZnVsIGZvciB2ZW5kb3ItcHJlZml4ZWQgc3R5bGVzIGxpa2UgYHRyYW5zZm9ybWAuXHJcbiAgZnVuY3Rpb24gdGVzdFByb3AocHJvcHMpIHtcclxuICBcdHZhciBzdHlsZSA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZTtcclxuXHJcbiAgXHRmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7XHJcbiAgXHRcdGlmIChwcm9wc1tpXSBpbiBzdHlsZSkge1xyXG4gIFx0XHRcdHJldHVybiBwcm9wc1tpXTtcclxuICBcdFx0fVxyXG4gIFx0fVxyXG4gIFx0cmV0dXJuIGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIHNldFRyYW5zZm9ybShlbDogSFRNTEVsZW1lbnQsIG9mZnNldDogUG9pbnQsIHNjYWxlPzogTnVtYmVyKVxyXG4gIC8vIFJlc2V0cyB0aGUgM0QgQ1NTIHRyYW5zZm9ybSBvZiBgZWxgIHNvIGl0IGlzIHRyYW5zbGF0ZWQgYnkgYG9mZnNldGAgcGl4ZWxzXHJcbiAgLy8gYW5kIG9wdGlvbmFsbHkgc2NhbGVkIGJ5IGBzY2FsZWAuIERvZXMgbm90IGhhdmUgYW4gZWZmZWN0IGlmIHRoZVxyXG4gIC8vIGJyb3dzZXIgZG9lc24ndCBzdXBwb3J0IDNEIENTUyB0cmFuc2Zvcm1zLlxyXG4gIGZ1bmN0aW9uIHNldFRyYW5zZm9ybShlbCwgb2Zmc2V0LCBzY2FsZSkge1xyXG4gIFx0dmFyIHBvcyA9IG9mZnNldCB8fCBuZXcgUG9pbnQoMCwgMCk7XHJcblxyXG4gIFx0ZWwuc3R5bGVbVFJBTlNGT1JNXSA9XHJcbiAgXHRcdChCcm93c2VyLmllM2QgP1xyXG4gIFx0XHRcdCd0cmFuc2xhdGUoJyArIHBvcy54ICsgJ3B4LCcgKyBwb3MueSArICdweCknIDpcclxuICBcdFx0XHQndHJhbnNsYXRlM2QoJyArIHBvcy54ICsgJ3B4LCcgKyBwb3MueSArICdweCwwKScpICtcclxuICBcdFx0KHNjYWxlID8gJyBzY2FsZSgnICsgc2NhbGUgKyAnKScgOiAnJyk7XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gc2V0UG9zaXRpb24oZWw6IEhUTUxFbGVtZW50LCBwb3NpdGlvbjogUG9pbnQpXHJcbiAgLy8gU2V0cyB0aGUgcG9zaXRpb24gb2YgYGVsYCB0byBjb29yZGluYXRlcyBzcGVjaWZpZWQgYnkgYHBvc2l0aW9uYCxcclxuICAvLyB1c2luZyBDU1MgdHJhbnNsYXRlIG9yIHRvcC9sZWZ0IHBvc2l0aW9uaW5nIGRlcGVuZGluZyBvbiB0aGUgYnJvd3NlclxyXG4gIC8vICh1c2VkIGJ5IExlYWZsZXQgaW50ZXJuYWxseSB0byBwb3NpdGlvbiBpdHMgbGF5ZXJzKS5cclxuICBmdW5jdGlvbiBzZXRQb3NpdGlvbihlbCwgcG9pbnQpIHtcclxuXHJcbiAgXHQvKmVzbGludC1kaXNhYmxlICovXHJcbiAgXHRlbC5fbGVhZmxldF9wb3MgPSBwb2ludDtcclxuICBcdC8qIGVzbGludC1lbmFibGUgKi9cclxuXHJcbiAgXHRpZiAoQnJvd3Nlci5hbnkzZCkge1xyXG4gIFx0XHRzZXRUcmFuc2Zvcm0oZWwsIHBvaW50KTtcclxuICBcdH0gZWxzZSB7XHJcbiAgXHRcdGVsLnN0eWxlLmxlZnQgPSBwb2ludC54ICsgJ3B4JztcclxuICBcdFx0ZWwuc3R5bGUudG9wID0gcG9pbnQueSArICdweCc7XHJcbiAgXHR9XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gZ2V0UG9zaXRpb24oZWw6IEhUTUxFbGVtZW50KTogUG9pbnRcclxuICAvLyBSZXR1cm5zIHRoZSBjb29yZGluYXRlcyBvZiBhbiBlbGVtZW50IHByZXZpb3VzbHkgcG9zaXRpb25lZCB3aXRoIHNldFBvc2l0aW9uLlxyXG4gIGZ1bmN0aW9uIGdldFBvc2l0aW9uKGVsKSB7XHJcbiAgXHQvLyB0aGlzIG1ldGhvZCBpcyBvbmx5IHVzZWQgZm9yIGVsZW1lbnRzIHByZXZpb3VzbHkgcG9zaXRpb25lZCB1c2luZyBzZXRQb3NpdGlvbixcclxuICBcdC8vIHNvIGl0J3Mgc2FmZSB0byBjYWNoZSB0aGUgcG9zaXRpb24gZm9yIHBlcmZvcm1hbmNlXHJcblxyXG4gIFx0cmV0dXJuIGVsLl9sZWFmbGV0X3BvcyB8fCBuZXcgUG9pbnQoMCwgMCk7XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gZGlzYWJsZVRleHRTZWxlY3Rpb24oKVxyXG4gIC8vIFByZXZlbnRzIHRoZSB1c2VyIGZyb20gZ2VuZXJhdGluZyBgc2VsZWN0c3RhcnRgIERPTSBldmVudHMsIHVzdWFsbHkgZ2VuZXJhdGVkXHJcbiAgLy8gd2hlbiB0aGUgdXNlciBkcmFncyB0aGUgbW91c2UgdGhyb3VnaCBhIHBhZ2Ugd2l0aCB0ZXh0LiBVc2VkIGludGVybmFsbHlcclxuICAvLyBieSBMZWFmbGV0IHRvIG92ZXJyaWRlIHRoZSBiZWhhdmlvdXIgb2YgYW55IGNsaWNrLWFuZC1kcmFnIGludGVyYWN0aW9uIG9uXHJcbiAgLy8gdGhlIG1hcC4gQWZmZWN0cyBkcmFnIGludGVyYWN0aW9ucyBvbiB0aGUgd2hvbGUgZG9jdW1lbnQuXHJcblxyXG4gIC8vIEBmdW5jdGlvbiBlbmFibGVUZXh0U2VsZWN0aW9uKClcclxuICAvLyBDYW5jZWxzIHRoZSBlZmZlY3RzIG9mIGEgcHJldmlvdXMgW2BMLkRvbVV0aWwuZGlzYWJsZVRleHRTZWxlY3Rpb25gXSgjZG9tdXRpbC1kaXNhYmxldGV4dHNlbGVjdGlvbikuXHJcbiAgdmFyIGRpc2FibGVUZXh0U2VsZWN0aW9uO1xyXG4gIHZhciBlbmFibGVUZXh0U2VsZWN0aW9uO1xyXG4gIHZhciBfdXNlclNlbGVjdDtcclxuICBpZiAoJ29uc2VsZWN0c3RhcnQnIGluIGRvY3VtZW50KSB7XHJcbiAgXHRkaXNhYmxlVGV4dFNlbGVjdGlvbiA9IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0b24od2luZG93LCAnc2VsZWN0c3RhcnQnLCBwcmV2ZW50RGVmYXVsdCk7XHJcbiAgXHR9O1xyXG4gIFx0ZW5hYmxlVGV4dFNlbGVjdGlvbiA9IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0b2ZmKHdpbmRvdywgJ3NlbGVjdHN0YXJ0JywgcHJldmVudERlZmF1bHQpO1xyXG4gIFx0fTtcclxuICB9IGVsc2Uge1xyXG4gIFx0dmFyIHVzZXJTZWxlY3RQcm9wZXJ0eSA9IHRlc3RQcm9wKFxyXG4gIFx0XHRbJ3VzZXJTZWxlY3QnLCAnV2Via2l0VXNlclNlbGVjdCcsICdPVXNlclNlbGVjdCcsICdNb3pVc2VyU2VsZWN0JywgJ21zVXNlclNlbGVjdCddKTtcclxuXHJcbiAgXHRkaXNhYmxlVGV4dFNlbGVjdGlvbiA9IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKHVzZXJTZWxlY3RQcm9wZXJ0eSkge1xyXG4gIFx0XHRcdHZhciBzdHlsZSA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZTtcclxuICBcdFx0XHRfdXNlclNlbGVjdCA9IHN0eWxlW3VzZXJTZWxlY3RQcm9wZXJ0eV07XHJcbiAgXHRcdFx0c3R5bGVbdXNlclNlbGVjdFByb3BlcnR5XSA9ICdub25lJztcclxuICBcdFx0fVxyXG4gIFx0fTtcclxuICBcdGVuYWJsZVRleHRTZWxlY3Rpb24gPSBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICh1c2VyU2VsZWN0UHJvcGVydHkpIHtcclxuICBcdFx0XHRkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGVbdXNlclNlbGVjdFByb3BlcnR5XSA9IF91c2VyU2VsZWN0O1xyXG4gIFx0XHRcdF91c2VyU2VsZWN0ID0gdW5kZWZpbmVkO1xyXG4gIFx0XHR9XHJcbiAgXHR9O1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGRpc2FibGVJbWFnZURyYWcoKVxyXG4gIC8vIEFzIFtgTC5Eb21VdGlsLmRpc2FibGVUZXh0U2VsZWN0aW9uYF0oI2RvbXV0aWwtZGlzYWJsZXRleHRzZWxlY3Rpb24pLCBidXRcclxuICAvLyBmb3IgYGRyYWdzdGFydGAgRE9NIGV2ZW50cywgdXN1YWxseSBnZW5lcmF0ZWQgd2hlbiB0aGUgdXNlciBkcmFncyBhbiBpbWFnZS5cclxuICBmdW5jdGlvbiBkaXNhYmxlSW1hZ2VEcmFnKCkge1xyXG4gIFx0b24od2luZG93LCAnZHJhZ3N0YXJ0JywgcHJldmVudERlZmF1bHQpO1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGVuYWJsZUltYWdlRHJhZygpXHJcbiAgLy8gQ2FuY2VscyB0aGUgZWZmZWN0cyBvZiBhIHByZXZpb3VzIFtgTC5Eb21VdGlsLmRpc2FibGVJbWFnZURyYWdgXSgjZG9tdXRpbC1kaXNhYmxldGV4dHNlbGVjdGlvbikuXHJcbiAgZnVuY3Rpb24gZW5hYmxlSW1hZ2VEcmFnKCkge1xyXG4gIFx0b2ZmKHdpbmRvdywgJ2RyYWdzdGFydCcsIHByZXZlbnREZWZhdWx0KTtcclxuICB9XHJcblxyXG4gIHZhciBfb3V0bGluZUVsZW1lbnQsIF9vdXRsaW5lU3R5bGU7XHJcbiAgLy8gQGZ1bmN0aW9uIHByZXZlbnRPdXRsaW5lKGVsOiBIVE1MRWxlbWVudClcclxuICAvLyBNYWtlcyB0aGUgW291dGxpbmVdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0NTUy9vdXRsaW5lKVxyXG4gIC8vIG9mIHRoZSBlbGVtZW50IGBlbGAgaW52aXNpYmxlLiBVc2VkIGludGVybmFsbHkgYnkgTGVhZmxldCB0byBwcmV2ZW50XHJcbiAgLy8gZm9jdXNhYmxlIGVsZW1lbnRzIGZyb20gZGlzcGxheWluZyBhbiBvdXRsaW5lIHdoZW4gdGhlIHVzZXIgcGVyZm9ybXMgYVxyXG4gIC8vIGRyYWcgaW50ZXJhY3Rpb24gb24gdGhlbS5cclxuICBmdW5jdGlvbiBwcmV2ZW50T3V0bGluZShlbGVtZW50KSB7XHJcbiAgXHR3aGlsZSAoZWxlbWVudC50YWJJbmRleCA9PT0gLTEpIHtcclxuICBcdFx0ZWxlbWVudCA9IGVsZW1lbnQucGFyZW50Tm9kZTtcclxuICBcdH1cclxuICBcdGlmICghZWxlbWVudC5zdHlsZSkgeyByZXR1cm47IH1cclxuICBcdHJlc3RvcmVPdXRsaW5lKCk7XHJcbiAgXHRfb3V0bGluZUVsZW1lbnQgPSBlbGVtZW50O1xyXG4gIFx0X291dGxpbmVTdHlsZSA9IGVsZW1lbnQuc3R5bGUub3V0bGluZVN0eWxlO1xyXG4gIFx0ZWxlbWVudC5zdHlsZS5vdXRsaW5lU3R5bGUgPSAnbm9uZSc7XHJcbiAgXHRvbih3aW5kb3csICdrZXlkb3duJywgcmVzdG9yZU91dGxpbmUpO1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIHJlc3RvcmVPdXRsaW5lKClcclxuICAvLyBDYW5jZWxzIHRoZSBlZmZlY3RzIG9mIGEgcHJldmlvdXMgW2BMLkRvbVV0aWwucHJldmVudE91dGxpbmVgXSgpLlxyXG4gIGZ1bmN0aW9uIHJlc3RvcmVPdXRsaW5lKCkge1xyXG4gIFx0aWYgKCFfb3V0bGluZUVsZW1lbnQpIHsgcmV0dXJuOyB9XHJcbiAgXHRfb3V0bGluZUVsZW1lbnQuc3R5bGUub3V0bGluZVN0eWxlID0gX291dGxpbmVTdHlsZTtcclxuICBcdF9vdXRsaW5lRWxlbWVudCA9IHVuZGVmaW5lZDtcclxuICBcdF9vdXRsaW5lU3R5bGUgPSB1bmRlZmluZWQ7XHJcbiAgXHRvZmYod2luZG93LCAna2V5ZG93bicsIHJlc3RvcmVPdXRsaW5lKTtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBnZXRTaXplZFBhcmVudE5vZGUoZWw6IEhUTUxFbGVtZW50KTogSFRNTEVsZW1lbnRcclxuICAvLyBGaW5kcyB0aGUgY2xvc2VzdCBwYXJlbnQgbm9kZSB3aGljaCBzaXplICh3aWR0aCBhbmQgaGVpZ2h0KSBpcyBub3QgbnVsbC5cclxuICBmdW5jdGlvbiBnZXRTaXplZFBhcmVudE5vZGUoZWxlbWVudCkge1xyXG4gIFx0ZG8ge1xyXG4gIFx0XHRlbGVtZW50ID0gZWxlbWVudC5wYXJlbnROb2RlO1xyXG4gIFx0fSB3aGlsZSAoKCFlbGVtZW50Lm9mZnNldFdpZHRoIHx8ICFlbGVtZW50Lm9mZnNldEhlaWdodCkgJiYgZWxlbWVudCAhPT0gZG9jdW1lbnQuYm9keSk7XHJcbiAgXHRyZXR1cm4gZWxlbWVudDtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBnZXRTY2FsZShlbDogSFRNTEVsZW1lbnQpOiBPYmplY3RcclxuICAvLyBDb21wdXRlcyB0aGUgQ1NTIHNjYWxlIGN1cnJlbnRseSBhcHBsaWVkIG9uIHRoZSBlbGVtZW50LlxyXG4gIC8vIFJldHVybnMgYW4gb2JqZWN0IHdpdGggYHhgIGFuZCBgeWAgbWVtYmVycyBhcyBob3Jpem9udGFsIGFuZCB2ZXJ0aWNhbCBzY2FsZXMgcmVzcGVjdGl2ZWx5LFxyXG4gIC8vIGFuZCBgYm91bmRpbmdDbGllbnRSZWN0YCBhcyB0aGUgcmVzdWx0IG9mIFtgZ2V0Qm91bmRpbmdDbGllbnRSZWN0KClgXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvRWxlbWVudC9nZXRCb3VuZGluZ0NsaWVudFJlY3QpLlxyXG4gIGZ1bmN0aW9uIGdldFNjYWxlKGVsZW1lbnQpIHtcclxuICBcdHZhciByZWN0ID0gZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTsgLy8gUmVhZC1vbmx5IGluIG9sZCBicm93c2Vycy5cclxuXHJcbiAgXHRyZXR1cm4ge1xyXG4gIFx0XHR4OiByZWN0LndpZHRoIC8gZWxlbWVudC5vZmZzZXRXaWR0aCB8fCAxLFxyXG4gIFx0XHR5OiByZWN0LmhlaWdodCAvIGVsZW1lbnQub2Zmc2V0SGVpZ2h0IHx8IDEsXHJcbiAgXHRcdGJvdW5kaW5nQ2xpZW50UmVjdDogcmVjdFxyXG4gIFx0fTtcclxuICB9XG5cbiAgdmFyIERvbVV0aWwgPSB7XG4gICAgX19wcm90b19fOiBudWxsLFxuICAgIFRSQU5TRk9STTogVFJBTlNGT1JNLFxuICAgIFRSQU5TSVRJT046IFRSQU5TSVRJT04sXG4gICAgVFJBTlNJVElPTl9FTkQ6IFRSQU5TSVRJT05fRU5ELFxuICAgIGdldDogZ2V0LFxuICAgIGdldFN0eWxlOiBnZXRTdHlsZSxcbiAgICBjcmVhdGU6IGNyZWF0ZSQxLFxuICAgIHJlbW92ZTogcmVtb3ZlLFxuICAgIGVtcHR5OiBlbXB0eSxcbiAgICB0b0Zyb250OiB0b0Zyb250LFxuICAgIHRvQmFjazogdG9CYWNrLFxuICAgIGhhc0NsYXNzOiBoYXNDbGFzcyxcbiAgICBhZGRDbGFzczogYWRkQ2xhc3MsXG4gICAgcmVtb3ZlQ2xhc3M6IHJlbW92ZUNsYXNzLFxuICAgIHNldENsYXNzOiBzZXRDbGFzcyxcbiAgICBnZXRDbGFzczogZ2V0Q2xhc3MsXG4gICAgc2V0T3BhY2l0eTogc2V0T3BhY2l0eSxcbiAgICB0ZXN0UHJvcDogdGVzdFByb3AsXG4gICAgc2V0VHJhbnNmb3JtOiBzZXRUcmFuc2Zvcm0sXG4gICAgc2V0UG9zaXRpb246IHNldFBvc2l0aW9uLFxuICAgIGdldFBvc2l0aW9uOiBnZXRQb3NpdGlvbixcbiAgICBnZXQgZGlzYWJsZVRleHRTZWxlY3Rpb24gKCkgeyByZXR1cm4gZGlzYWJsZVRleHRTZWxlY3Rpb247IH0sXG4gICAgZ2V0IGVuYWJsZVRleHRTZWxlY3Rpb24gKCkgeyByZXR1cm4gZW5hYmxlVGV4dFNlbGVjdGlvbjsgfSxcbiAgICBkaXNhYmxlSW1hZ2VEcmFnOiBkaXNhYmxlSW1hZ2VEcmFnLFxuICAgIGVuYWJsZUltYWdlRHJhZzogZW5hYmxlSW1hZ2VEcmFnLFxuICAgIHByZXZlbnRPdXRsaW5lOiBwcmV2ZW50T3V0bGluZSxcbiAgICByZXN0b3JlT3V0bGluZTogcmVzdG9yZU91dGxpbmUsXG4gICAgZ2V0U2l6ZWRQYXJlbnROb2RlOiBnZXRTaXplZFBhcmVudE5vZGUsXG4gICAgZ2V0U2NhbGU6IGdldFNjYWxlXG4gIH07XG5cbiAgLypcclxuICAgKiBAbmFtZXNwYWNlIERvbUV2ZW50XHJcbiAgICogVXRpbGl0eSBmdW5jdGlvbnMgdG8gd29yayB3aXRoIHRoZSBbRE9NIGV2ZW50c10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQVBJL0V2ZW50KSwgdXNlZCBieSBMZWFmbGV0IGludGVybmFsbHkuXHJcbiAgICovXHJcblxyXG4gIC8vIEluc3BpcmVkIGJ5IEpvaG4gUmVzaWcsIERlYW4gRWR3YXJkcyBhbmQgWVVJIGFkZEV2ZW50IGltcGxlbWVudGF0aW9ucy5cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIG9uKGVsOiBIVE1MRWxlbWVudCwgdHlwZXM6IFN0cmluZywgZm46IEZ1bmN0aW9uLCBjb250ZXh0PzogT2JqZWN0KTogdGhpc1xyXG4gIC8vIEFkZHMgYSBsaXN0ZW5lciBmdW5jdGlvbiAoYGZuYCkgdG8gYSBwYXJ0aWN1bGFyIERPTSBldmVudCB0eXBlIG9mIHRoZVxyXG4gIC8vIGVsZW1lbnQgYGVsYC4gWW91IGNhbiBvcHRpb25hbGx5IHNwZWNpZnkgdGhlIGNvbnRleHQgb2YgdGhlIGxpc3RlbmVyXHJcbiAgLy8gKG9iamVjdCB0aGUgYHRoaXNgIGtleXdvcmQgd2lsbCBwb2ludCB0bykuIFlvdSBjYW4gYWxzbyBwYXNzIHNldmVyYWxcclxuICAvLyBzcGFjZS1zZXBhcmF0ZWQgdHlwZXMgKGUuZy4gYCdjbGljayBkYmxjbGljaydgKS5cclxuXHJcbiAgLy8gQGFsdGVybmF0aXZlXHJcbiAgLy8gQGZ1bmN0aW9uIG9uKGVsOiBIVE1MRWxlbWVudCwgZXZlbnRNYXA6IE9iamVjdCwgY29udGV4dD86IE9iamVjdCk6IHRoaXNcclxuICAvLyBBZGRzIGEgc2V0IG9mIHR5cGUvbGlzdGVuZXIgcGFpcnMsIGUuZy4gYHtjbGljazogb25DbGljaywgbW91c2Vtb3ZlOiBvbk1vdXNlTW92ZX1gXHJcbiAgZnVuY3Rpb24gb24ob2JqLCB0eXBlcywgZm4sIGNvbnRleHQpIHtcclxuXHJcbiAgXHRpZiAodHlwZXMgJiYgdHlwZW9mIHR5cGVzID09PSAnb2JqZWN0Jykge1xyXG4gIFx0XHRmb3IgKHZhciB0eXBlIGluIHR5cGVzKSB7XHJcbiAgXHRcdFx0YWRkT25lKG9iaiwgdHlwZSwgdHlwZXNbdHlwZV0sIGZuKTtcclxuICBcdFx0fVxyXG4gIFx0fSBlbHNlIHtcclxuICBcdFx0dHlwZXMgPSBzcGxpdFdvcmRzKHR5cGVzKTtcclxuXHJcbiAgXHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSB0eXBlcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gIFx0XHRcdGFkZE9uZShvYmosIHR5cGVzW2ldLCBmbiwgY29udGV4dCk7XHJcbiAgXHRcdH1cclxuICBcdH1cclxuXHJcbiAgXHRyZXR1cm4gdGhpcztcclxuICB9XHJcblxyXG4gIHZhciBldmVudHNLZXkgPSAnX2xlYWZsZXRfZXZlbnRzJztcclxuXHJcbiAgLy8gQGZ1bmN0aW9uIG9mZihlbDogSFRNTEVsZW1lbnQsIHR5cGVzOiBTdHJpbmcsIGZuOiBGdW5jdGlvbiwgY29udGV4dD86IE9iamVjdCk6IHRoaXNcclxuICAvLyBSZW1vdmVzIGEgcHJldmlvdXNseSBhZGRlZCBsaXN0ZW5lciBmdW5jdGlvbi5cclxuICAvLyBOb3RlIHRoYXQgaWYgeW91IHBhc3NlZCBhIGN1c3RvbSBjb250ZXh0IHRvIG9uLCB5b3UgbXVzdCBwYXNzIHRoZSBzYW1lXHJcbiAgLy8gY29udGV4dCB0byBgb2ZmYCBpbiBvcmRlciB0byByZW1vdmUgdGhlIGxpc3RlbmVyLlxyXG5cclxuICAvLyBAYWx0ZXJuYXRpdmVcclxuICAvLyBAZnVuY3Rpb24gb2ZmKGVsOiBIVE1MRWxlbWVudCwgZXZlbnRNYXA6IE9iamVjdCwgY29udGV4dD86IE9iamVjdCk6IHRoaXNcclxuICAvLyBSZW1vdmVzIGEgc2V0IG9mIHR5cGUvbGlzdGVuZXIgcGFpcnMsIGUuZy4gYHtjbGljazogb25DbGljaywgbW91c2Vtb3ZlOiBvbk1vdXNlTW92ZX1gXHJcblxyXG4gIC8vIEBhbHRlcm5hdGl2ZVxyXG4gIC8vIEBmdW5jdGlvbiBvZmYoZWw6IEhUTUxFbGVtZW50LCB0eXBlczogU3RyaW5nKTogdGhpc1xyXG4gIC8vIFJlbW92ZXMgYWxsIHByZXZpb3VzbHkgYWRkZWQgbGlzdGVuZXJzIG9mIGdpdmVuIHR5cGVzLlxyXG5cclxuICAvLyBAYWx0ZXJuYXRpdmVcclxuICAvLyBAZnVuY3Rpb24gb2ZmKGVsOiBIVE1MRWxlbWVudCk6IHRoaXNcclxuICAvLyBSZW1vdmVzIGFsbCBwcmV2aW91c2x5IGFkZGVkIGxpc3RlbmVycyBmcm9tIGdpdmVuIEhUTUxFbGVtZW50XHJcbiAgZnVuY3Rpb24gb2ZmKG9iaiwgdHlwZXMsIGZuLCBjb250ZXh0KSB7XHJcblxyXG4gIFx0aWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcclxuICBcdFx0YmF0Y2hSZW1vdmUob2JqKTtcclxuICBcdFx0ZGVsZXRlIG9ialtldmVudHNLZXldO1xyXG5cclxuICBcdH0gZWxzZSBpZiAodHlwZXMgJiYgdHlwZW9mIHR5cGVzID09PSAnb2JqZWN0Jykge1xyXG4gIFx0XHRmb3IgKHZhciB0eXBlIGluIHR5cGVzKSB7XHJcbiAgXHRcdFx0cmVtb3ZlT25lKG9iaiwgdHlwZSwgdHlwZXNbdHlwZV0sIGZuKTtcclxuICBcdFx0fVxyXG5cclxuICBcdH0gZWxzZSB7XHJcbiAgXHRcdHR5cGVzID0gc3BsaXRXb3Jkcyh0eXBlcyk7XHJcblxyXG4gIFx0XHRpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMikge1xyXG4gIFx0XHRcdGJhdGNoUmVtb3ZlKG9iaiwgZnVuY3Rpb24gKHR5cGUpIHtcclxuICBcdFx0XHRcdHJldHVybiBpbmRleE9mKHR5cGVzLCB0eXBlKSAhPT0gLTE7XHJcbiAgXHRcdFx0fSk7XHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IHR5cGVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdFx0XHRyZW1vdmVPbmUob2JqLCB0eXBlc1tpXSwgZm4sIGNvbnRleHQpO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG4gIFx0fVxyXG5cclxuICBcdHJldHVybiB0aGlzO1xyXG4gIH1cclxuXHJcbiAgZnVuY3Rpb24gYmF0Y2hSZW1vdmUob2JqLCBmaWx0ZXJGbikge1xyXG4gIFx0Zm9yICh2YXIgaWQgaW4gb2JqW2V2ZW50c0tleV0pIHtcclxuICBcdFx0dmFyIHR5cGUgPSBpZC5zcGxpdCgvXFxkLylbMF07XHJcbiAgXHRcdGlmICghZmlsdGVyRm4gfHwgZmlsdGVyRm4odHlwZSkpIHtcclxuICBcdFx0XHRyZW1vdmVPbmUob2JqLCB0eXBlLCBudWxsLCBudWxsLCBpZCk7XHJcbiAgXHRcdH1cclxuICBcdH1cclxuICB9XHJcblxyXG4gIHZhciBtb3VzZVN1YnN0ID0ge1xyXG4gIFx0bW91c2VlbnRlcjogJ21vdXNlb3ZlcicsXHJcbiAgXHRtb3VzZWxlYXZlOiAnbW91c2VvdXQnLFxyXG4gIFx0d2hlZWw6ICEoJ29ud2hlZWwnIGluIHdpbmRvdykgJiYgJ21vdXNld2hlZWwnXHJcbiAgfTtcclxuXHJcbiAgZnVuY3Rpb24gYWRkT25lKG9iaiwgdHlwZSwgZm4sIGNvbnRleHQpIHtcclxuICBcdHZhciBpZCA9IHR5cGUgKyBzdGFtcChmbikgKyAoY29udGV4dCA/ICdfJyArIHN0YW1wKGNvbnRleHQpIDogJycpO1xyXG5cclxuICBcdGlmIChvYmpbZXZlbnRzS2V5XSAmJiBvYmpbZXZlbnRzS2V5XVtpZF0pIHsgcmV0dXJuIHRoaXM7IH1cclxuXHJcbiAgXHR2YXIgaGFuZGxlciA9IGZ1bmN0aW9uIChlKSB7XHJcbiAgXHRcdHJldHVybiBmbi5jYWxsKGNvbnRleHQgfHwgb2JqLCBlIHx8IHdpbmRvdy5ldmVudCk7XHJcbiAgXHR9O1xyXG5cclxuICBcdHZhciBvcmlnaW5hbEhhbmRsZXIgPSBoYW5kbGVyO1xyXG5cclxuICBcdGlmICghQnJvd3Nlci50b3VjaE5hdGl2ZSAmJiBCcm93c2VyLnBvaW50ZXIgJiYgdHlwZS5pbmRleE9mKCd0b3VjaCcpID09PSAwKSB7XHJcbiAgXHRcdC8vIE5lZWRzIERvbUV2ZW50LlBvaW50ZXIuanNcclxuICBcdFx0aGFuZGxlciA9IGFkZFBvaW50ZXJMaXN0ZW5lcihvYmosIHR5cGUsIGhhbmRsZXIpO1xyXG5cclxuICBcdH0gZWxzZSBpZiAoQnJvd3Nlci50b3VjaCAmJiAodHlwZSA9PT0gJ2RibGNsaWNrJykpIHtcclxuICBcdFx0aGFuZGxlciA9IGFkZERvdWJsZVRhcExpc3RlbmVyKG9iaiwgaGFuZGxlcik7XHJcblxyXG4gIFx0fSBlbHNlIGlmICgnYWRkRXZlbnRMaXN0ZW5lcicgaW4gb2JqKSB7XHJcblxyXG4gIFx0XHRpZiAodHlwZSA9PT0gJ3RvdWNoc3RhcnQnIHx8IHR5cGUgPT09ICd0b3VjaG1vdmUnIHx8IHR5cGUgPT09ICd3aGVlbCcgfHwgIHR5cGUgPT09ICdtb3VzZXdoZWVsJykge1xyXG4gIFx0XHRcdG9iai5hZGRFdmVudExpc3RlbmVyKG1vdXNlU3Vic3RbdHlwZV0gfHwgdHlwZSwgaGFuZGxlciwgQnJvd3Nlci5wYXNzaXZlRXZlbnRzID8ge3Bhc3NpdmU6IGZhbHNlfSA6IGZhbHNlKTtcclxuXHJcbiAgXHRcdH0gZWxzZSBpZiAodHlwZSA9PT0gJ21vdXNlZW50ZXInIHx8IHR5cGUgPT09ICdtb3VzZWxlYXZlJykge1xyXG4gIFx0XHRcdGhhbmRsZXIgPSBmdW5jdGlvbiAoZSkge1xyXG4gIFx0XHRcdFx0ZSA9IGUgfHwgd2luZG93LmV2ZW50O1xyXG4gIFx0XHRcdFx0aWYgKGlzRXh0ZXJuYWxUYXJnZXQob2JqLCBlKSkge1xyXG4gIFx0XHRcdFx0XHRvcmlnaW5hbEhhbmRsZXIoZSk7XHJcbiAgXHRcdFx0XHR9XHJcbiAgXHRcdFx0fTtcclxuICBcdFx0XHRvYmouYWRkRXZlbnRMaXN0ZW5lcihtb3VzZVN1YnN0W3R5cGVdLCBoYW5kbGVyLCBmYWxzZSk7XHJcblxyXG4gIFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdG9iai5hZGRFdmVudExpc3RlbmVyKHR5cGUsIG9yaWdpbmFsSGFuZGxlciwgZmFsc2UpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0fSBlbHNlIHtcclxuICBcdFx0b2JqLmF0dGFjaEV2ZW50KCdvbicgKyB0eXBlLCBoYW5kbGVyKTtcclxuICBcdH1cclxuXHJcbiAgXHRvYmpbZXZlbnRzS2V5XSA9IG9ialtldmVudHNLZXldIHx8IHt9O1xyXG4gIFx0b2JqW2V2ZW50c0tleV1baWRdID0gaGFuZGxlcjtcclxuICB9XHJcblxyXG4gIGZ1bmN0aW9uIHJlbW92ZU9uZShvYmosIHR5cGUsIGZuLCBjb250ZXh0LCBpZCkge1xyXG4gIFx0aWQgPSBpZCB8fCB0eXBlICsgc3RhbXAoZm4pICsgKGNvbnRleHQgPyAnXycgKyBzdGFtcChjb250ZXh0KSA6ICcnKTtcclxuICBcdHZhciBoYW5kbGVyID0gb2JqW2V2ZW50c0tleV0gJiYgb2JqW2V2ZW50c0tleV1baWRdO1xyXG5cclxuICBcdGlmICghaGFuZGxlcikgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuICBcdGlmICghQnJvd3Nlci50b3VjaE5hdGl2ZSAmJiBCcm93c2VyLnBvaW50ZXIgJiYgdHlwZS5pbmRleE9mKCd0b3VjaCcpID09PSAwKSB7XHJcbiAgXHRcdHJlbW92ZVBvaW50ZXJMaXN0ZW5lcihvYmosIHR5cGUsIGhhbmRsZXIpO1xyXG5cclxuICBcdH0gZWxzZSBpZiAoQnJvd3Nlci50b3VjaCAmJiAodHlwZSA9PT0gJ2RibGNsaWNrJykpIHtcclxuICBcdFx0cmVtb3ZlRG91YmxlVGFwTGlzdGVuZXIob2JqLCBoYW5kbGVyKTtcclxuXHJcbiAgXHR9IGVsc2UgaWYgKCdyZW1vdmVFdmVudExpc3RlbmVyJyBpbiBvYmopIHtcclxuXHJcbiAgXHRcdG9iai5yZW1vdmVFdmVudExpc3RlbmVyKG1vdXNlU3Vic3RbdHlwZV0gfHwgdHlwZSwgaGFuZGxlciwgZmFsc2UpO1xyXG5cclxuICBcdH0gZWxzZSB7XHJcbiAgXHRcdG9iai5kZXRhY2hFdmVudCgnb24nICsgdHlwZSwgaGFuZGxlcik7XHJcbiAgXHR9XHJcblxyXG4gIFx0b2JqW2V2ZW50c0tleV1baWRdID0gbnVsbDtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBzdG9wUHJvcGFnYXRpb24oZXY6IERPTUV2ZW50KTogdGhpc1xyXG4gIC8vIFN0b3AgdGhlIGdpdmVuIGV2ZW50IGZyb20gcHJvcGFnYXRpb24gdG8gcGFyZW50IGVsZW1lbnRzLiBVc2VkIGluc2lkZSB0aGUgbGlzdGVuZXIgZnVuY3Rpb25zOlxyXG4gIC8vIGBgYGpzXHJcbiAgLy8gTC5Eb21FdmVudC5vbihkaXYsICdjbGljaycsIGZ1bmN0aW9uIChldikge1xyXG4gIC8vIFx0TC5Eb21FdmVudC5zdG9wUHJvcGFnYXRpb24oZXYpO1xyXG4gIC8vIH0pO1xyXG4gIC8vIGBgYFxyXG4gIGZ1bmN0aW9uIHN0b3BQcm9wYWdhdGlvbihlKSB7XHJcblxyXG4gIFx0aWYgKGUuc3RvcFByb3BhZ2F0aW9uKSB7XHJcbiAgXHRcdGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgXHR9IGVsc2UgaWYgKGUub3JpZ2luYWxFdmVudCkgeyAgLy8gSW4gY2FzZSBvZiBMZWFmbGV0IGV2ZW50LlxyXG4gIFx0XHRlLm9yaWdpbmFsRXZlbnQuX3N0b3BwZWQgPSB0cnVlO1xyXG4gIFx0fSBlbHNlIHtcclxuICBcdFx0ZS5jYW5jZWxCdWJibGUgPSB0cnVlO1xyXG4gIFx0fVxyXG5cclxuICBcdHJldHVybiB0aGlzO1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGRpc2FibGVTY3JvbGxQcm9wYWdhdGlvbihlbDogSFRNTEVsZW1lbnQpOiB0aGlzXHJcbiAgLy8gQWRkcyBgc3RvcFByb3BhZ2F0aW9uYCB0byB0aGUgZWxlbWVudCdzIGAnd2hlZWwnYCBldmVudHMgKHBsdXMgYnJvd3NlciB2YXJpYW50cykuXHJcbiAgZnVuY3Rpb24gZGlzYWJsZVNjcm9sbFByb3BhZ2F0aW9uKGVsKSB7XHJcbiAgXHRhZGRPbmUoZWwsICd3aGVlbCcsIHN0b3BQcm9wYWdhdGlvbik7XHJcbiAgXHRyZXR1cm4gdGhpcztcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBkaXNhYmxlQ2xpY2tQcm9wYWdhdGlvbihlbDogSFRNTEVsZW1lbnQpOiB0aGlzXHJcbiAgLy8gQWRkcyBgc3RvcFByb3BhZ2F0aW9uYCB0byB0aGUgZWxlbWVudCdzIGAnY2xpY2snYCwgYCdkYmxjbGljaydgLCBgJ2NvbnRleHRtZW51J2AsXHJcbiAgLy8gYCdtb3VzZWRvd24nYCBhbmQgYCd0b3VjaHN0YXJ0J2AgZXZlbnRzIChwbHVzIGJyb3dzZXIgdmFyaWFudHMpLlxyXG4gIGZ1bmN0aW9uIGRpc2FibGVDbGlja1Byb3BhZ2F0aW9uKGVsKSB7XHJcbiAgXHRvbihlbCwgJ21vdXNlZG93biB0b3VjaHN0YXJ0IGRibGNsaWNrIGNvbnRleHRtZW51Jywgc3RvcFByb3BhZ2F0aW9uKTtcclxuICBcdGVsWydfbGVhZmxldF9kaXNhYmxlX2NsaWNrJ10gPSB0cnVlO1xyXG4gIFx0cmV0dXJuIHRoaXM7XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gcHJldmVudERlZmF1bHQoZXY6IERPTUV2ZW50KTogdGhpc1xyXG4gIC8vIFByZXZlbnRzIHRoZSBkZWZhdWx0IGFjdGlvbiBvZiB0aGUgRE9NIEV2ZW50IGBldmAgZnJvbSBoYXBwZW5pbmcgKHN1Y2ggYXNcclxuICAvLyBmb2xsb3dpbmcgYSBsaW5rIGluIHRoZSBocmVmIG9mIHRoZSBhIGVsZW1lbnQsIG9yIGRvaW5nIGEgUE9TVCByZXF1ZXN0XHJcbiAgLy8gd2l0aCBwYWdlIHJlbG9hZCB3aGVuIGEgYDxmb3JtPmAgaXMgc3VibWl0dGVkKS5cclxuICAvLyBVc2UgaXQgaW5zaWRlIGxpc3RlbmVyIGZ1bmN0aW9ucy5cclxuICBmdW5jdGlvbiBwcmV2ZW50RGVmYXVsdChlKSB7XHJcbiAgXHRpZiAoZS5wcmV2ZW50RGVmYXVsdCkge1xyXG4gIFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgXHR9IGVsc2Uge1xyXG4gIFx0XHRlLnJldHVyblZhbHVlID0gZmFsc2U7XHJcbiAgXHR9XHJcbiAgXHRyZXR1cm4gdGhpcztcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBzdG9wKGV2OiBET01FdmVudCk6IHRoaXNcclxuICAvLyBEb2VzIGBzdG9wUHJvcGFnYXRpb25gIGFuZCBgcHJldmVudERlZmF1bHRgIGF0IHRoZSBzYW1lIHRpbWUuXHJcbiAgZnVuY3Rpb24gc3RvcChlKSB7XHJcbiAgXHRwcmV2ZW50RGVmYXVsdChlKTtcclxuICBcdHN0b3BQcm9wYWdhdGlvbihlKTtcclxuICBcdHJldHVybiB0aGlzO1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGdldFByb3BhZ2F0aW9uUGF0aChldjogRE9NRXZlbnQpOiBBcnJheVxyXG4gIC8vIENvbXBhdGliaWxpdHkgcG9seWZpbGwgZm9yIFtgRXZlbnQuY29tcG9zZWRQYXRoKClgXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvRXZlbnQvY29tcG9zZWRQYXRoKS5cclxuICAvLyBSZXR1cm5zIGFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIGBIVE1MRWxlbWVudGBzIHRoYXQgdGhlIGdpdmVuIERPTSBldmVudFxyXG4gIC8vIHNob3VsZCBwcm9wYWdhdGUgdG8gKGlmIG5vdCBzdG9wcGVkKS5cclxuICBmdW5jdGlvbiBnZXRQcm9wYWdhdGlvblBhdGgoZXYpIHtcclxuICBcdGlmIChldi5jb21wb3NlZFBhdGgpIHtcclxuICBcdFx0cmV0dXJuIGV2LmNvbXBvc2VkUGF0aCgpO1xyXG4gIFx0fVxyXG5cclxuICBcdHZhciBwYXRoID0gW107XHJcbiAgXHR2YXIgZWwgPSBldi50YXJnZXQ7XHJcblxyXG4gIFx0d2hpbGUgKGVsKSB7XHJcbiAgXHRcdHBhdGgucHVzaChlbCk7XHJcbiAgXHRcdGVsID0gZWwucGFyZW50Tm9kZTtcclxuICBcdH1cclxuICBcdHJldHVybiBwYXRoO1xyXG4gIH1cclxuXHJcblxyXG4gIC8vIEBmdW5jdGlvbiBnZXRNb3VzZVBvc2l0aW9uKGV2OiBET01FdmVudCwgY29udGFpbmVyPzogSFRNTEVsZW1lbnQpOiBQb2ludFxyXG4gIC8vIEdldHMgbm9ybWFsaXplZCBtb3VzZSBwb3NpdGlvbiBmcm9tIGEgRE9NIGV2ZW50IHJlbGF0aXZlIHRvIHRoZVxyXG4gIC8vIGBjb250YWluZXJgIChib3JkZXIgZXhjbHVkZWQpIG9yIHRvIHRoZSB3aG9sZSBwYWdlIGlmIG5vdCBzcGVjaWZpZWQuXHJcbiAgZnVuY3Rpb24gZ2V0TW91c2VQb3NpdGlvbihlLCBjb250YWluZXIpIHtcclxuICBcdGlmICghY29udGFpbmVyKSB7XHJcbiAgXHRcdHJldHVybiBuZXcgUG9pbnQoZS5jbGllbnRYLCBlLmNsaWVudFkpO1xyXG4gIFx0fVxyXG5cclxuICBcdHZhciBzY2FsZSA9IGdldFNjYWxlKGNvbnRhaW5lciksXHJcbiAgXHQgICAgb2Zmc2V0ID0gc2NhbGUuYm91bmRpbmdDbGllbnRSZWN0OyAvLyBsZWZ0IGFuZCB0b3AgIHZhbHVlcyBhcmUgaW4gcGFnZSBzY2FsZSAobGlrZSB0aGUgZXZlbnQgY2xpZW50WC9ZKVxyXG5cclxuICBcdHJldHVybiBuZXcgUG9pbnQoXHJcbiAgXHRcdC8vIG9mZnNldC5sZWZ0L3RvcCB2YWx1ZXMgYXJlIGluIHBhZ2Ugc2NhbGUgKGxpa2UgY2xpZW50WC9ZKSxcclxuICBcdFx0Ly8gd2hlcmVhcyBjbGllbnRMZWZ0L1RvcCAoYm9yZGVyIHdpZHRoKSB2YWx1ZXMgYXJlIHRoZSBvcmlnaW5hbCB2YWx1ZXMgKGJlZm9yZSBDU1Mgc2NhbGUgYXBwbGllcykuXHJcbiAgXHRcdChlLmNsaWVudFggLSBvZmZzZXQubGVmdCkgLyBzY2FsZS54IC0gY29udGFpbmVyLmNsaWVudExlZnQsXHJcbiAgXHRcdChlLmNsaWVudFkgLSBvZmZzZXQudG9wKSAvIHNjYWxlLnkgLSBjb250YWluZXIuY2xpZW50VG9wXHJcbiAgXHQpO1xyXG4gIH1cclxuXHJcblxyXG4gIC8vICBleGNlcHQgLCBTYWZhcmkgYW5kXHJcbiAgLy8gV2UgbmVlZCBkb3VibGUgdGhlIHNjcm9sbCBwaXhlbHMgKHNlZSAjNzQwMyBhbmQgIzQ1MzgpIGZvciBhbGwgQnJvd3NlcnNcclxuICAvLyBleGNlcHQgT1NYIChNYWMpIC0+IDN4LCBDaHJvbWUgcnVubmluZyBvbiBMaW51eCAxeFxyXG5cclxuICB2YXIgd2hlZWxQeEZhY3RvciA9XHJcbiAgXHQoQnJvd3Nlci5saW51eCAmJiBCcm93c2VyLmNocm9tZSkgPyB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyA6XHJcbiAgXHRCcm93c2VyLm1hYyA/IHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvICogMyA6XHJcbiAgXHR3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyA+IDAgPyAyICogd2luZG93LmRldmljZVBpeGVsUmF0aW8gOiAxO1xyXG4gIC8vIEBmdW5jdGlvbiBnZXRXaGVlbERlbHRhKGV2OiBET01FdmVudCk6IE51bWJlclxyXG4gIC8vIEdldHMgbm9ybWFsaXplZCB3aGVlbCBkZWx0YSBmcm9tIGEgd2hlZWwgRE9NIGV2ZW50LCBpbiB2ZXJ0aWNhbFxyXG4gIC8vIHBpeGVscyBzY3JvbGxlZCAobmVnYXRpdmUgaWYgc2Nyb2xsaW5nIGRvd24pLlxyXG4gIC8vIEV2ZW50cyBmcm9tIHBvaW50aW5nIGRldmljZXMgd2l0aG91dCBwcmVjaXNlIHNjcm9sbGluZyBhcmUgbWFwcGVkIHRvXHJcbiAgLy8gYSBiZXN0IGd1ZXNzIG9mIDYwIHBpeGVscy5cclxuICBmdW5jdGlvbiBnZXRXaGVlbERlbHRhKGUpIHtcclxuICBcdHJldHVybiAoQnJvd3Nlci5lZGdlKSA/IGUud2hlZWxEZWx0YVkgLyAyIDogLy8gRG9uJ3QgdHJ1c3Qgd2luZG93LWdlb21ldHJ5LWJhc2VkIGRlbHRhXHJcbiAgXHQgICAgICAgKGUuZGVsdGFZICYmIGUuZGVsdGFNb2RlID09PSAwKSA/IC1lLmRlbHRhWSAvIHdoZWVsUHhGYWN0b3IgOiAvLyBQaXhlbHNcclxuICBcdCAgICAgICAoZS5kZWx0YVkgJiYgZS5kZWx0YU1vZGUgPT09IDEpID8gLWUuZGVsdGFZICogMjAgOiAvLyBMaW5lc1xyXG4gIFx0ICAgICAgIChlLmRlbHRhWSAmJiBlLmRlbHRhTW9kZSA9PT0gMikgPyAtZS5kZWx0YVkgKiA2MCA6IC8vIFBhZ2VzXHJcbiAgXHQgICAgICAgKGUuZGVsdGFYIHx8IGUuZGVsdGFaKSA/IDAgOlx0Ly8gU2tpcCBob3Jpem9udGFsL2RlcHRoIHdoZWVsIGV2ZW50c1xyXG4gIFx0ICAgICAgIGUud2hlZWxEZWx0YSA/IChlLndoZWVsRGVsdGFZIHx8IGUud2hlZWxEZWx0YSkgLyAyIDogLy8gTGVnYWN5IElFIHBpeGVsc1xyXG4gIFx0ICAgICAgIChlLmRldGFpbCAmJiBNYXRoLmFicyhlLmRldGFpbCkgPCAzMjc2NSkgPyAtZS5kZXRhaWwgKiAyMCA6IC8vIExlZ2FjeSBNb3ogbGluZXNcclxuICBcdCAgICAgICBlLmRldGFpbCA/IGUuZGV0YWlsIC8gLTMyNzY1ICogNjAgOiAvLyBMZWdhY3kgTW96IHBhZ2VzXHJcbiAgXHQgICAgICAgMDtcclxuICB9XHJcblxyXG4gIC8vIGNoZWNrIGlmIGVsZW1lbnQgcmVhbGx5IGxlZnQvZW50ZXJlZCB0aGUgZXZlbnQgdGFyZ2V0IChmb3IgbW91c2VlbnRlci9tb3VzZWxlYXZlKVxyXG4gIGZ1bmN0aW9uIGlzRXh0ZXJuYWxUYXJnZXQoZWwsIGUpIHtcclxuXHJcbiAgXHR2YXIgcmVsYXRlZCA9IGUucmVsYXRlZFRhcmdldDtcclxuXHJcbiAgXHRpZiAoIXJlbGF0ZWQpIHsgcmV0dXJuIHRydWU7IH1cclxuXHJcbiAgXHR0cnkge1xyXG4gIFx0XHR3aGlsZSAocmVsYXRlZCAmJiAocmVsYXRlZCAhPT0gZWwpKSB7XHJcbiAgXHRcdFx0cmVsYXRlZCA9IHJlbGF0ZWQucGFyZW50Tm9kZTtcclxuICBcdFx0fVxyXG4gIFx0fSBjYXRjaCAoZXJyKSB7XHJcbiAgXHRcdHJldHVybiBmYWxzZTtcclxuICBcdH1cclxuICBcdHJldHVybiAocmVsYXRlZCAhPT0gZWwpO1xyXG4gIH1cblxuICB2YXIgRG9tRXZlbnQgPSB7XG4gICAgX19wcm90b19fOiBudWxsLFxuICAgIG9uOiBvbixcbiAgICBvZmY6IG9mZixcbiAgICBzdG9wUHJvcGFnYXRpb246IHN0b3BQcm9wYWdhdGlvbixcbiAgICBkaXNhYmxlU2Nyb2xsUHJvcGFnYXRpb246IGRpc2FibGVTY3JvbGxQcm9wYWdhdGlvbixcbiAgICBkaXNhYmxlQ2xpY2tQcm9wYWdhdGlvbjogZGlzYWJsZUNsaWNrUHJvcGFnYXRpb24sXG4gICAgcHJldmVudERlZmF1bHQ6IHByZXZlbnREZWZhdWx0LFxuICAgIHN0b3A6IHN0b3AsXG4gICAgZ2V0UHJvcGFnYXRpb25QYXRoOiBnZXRQcm9wYWdhdGlvblBhdGgsXG4gICAgZ2V0TW91c2VQb3NpdGlvbjogZ2V0TW91c2VQb3NpdGlvbixcbiAgICBnZXRXaGVlbERlbHRhOiBnZXRXaGVlbERlbHRhLFxuICAgIGlzRXh0ZXJuYWxUYXJnZXQ6IGlzRXh0ZXJuYWxUYXJnZXQsXG4gICAgYWRkTGlzdGVuZXI6IG9uLFxuICAgIHJlbW92ZUxpc3RlbmVyOiBvZmZcbiAgfTtcblxuICAvKlxuICAgKiBAY2xhc3MgUG9zQW5pbWF0aW9uXG4gICAqIEBha2EgTC5Qb3NBbmltYXRpb25cbiAgICogQGluaGVyaXRzIEV2ZW50ZWRcbiAgICogVXNlZCBpbnRlcm5hbGx5IGZvciBwYW5uaW5nIGFuaW1hdGlvbnMsIHV0aWxpemluZyBDU1MzIFRyYW5zaXRpb25zIGZvciBtb2Rlcm4gYnJvd3NlcnMgYW5kIGEgdGltZXIgZmFsbGJhY2sgZm9yIElFNi05LlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGBqc1xuICAgKiB2YXIgbXlQb3NpdGlvbk1hcmtlciA9IEwubWFya2VyKFs0OC44NjQ3MTYsIDIuMjk0Njk0XSkuYWRkVG8obWFwKTtcbiAgICpcbiAgICogbXlQb3NpdGlvbk1hcmtlci5vbihcImNsaWNrXCIsIGZ1bmN0aW9uKCkge1xuICAgKiBcdHZhciBwb3MgPSBtYXAubGF0TG5nVG9MYXllclBvaW50KG15UG9zaXRpb25NYXJrZXIuZ2V0TGF0TG5nKCkpO1xuICAgKiBcdHBvcy55IC09IDI1O1xuICAgKiBcdHZhciBmeCA9IG5ldyBMLlBvc0FuaW1hdGlvbigpO1xuICAgKlxuICAgKiBcdGZ4Lm9uY2UoJ2VuZCcsZnVuY3Rpb24oKSB7XG4gICAqIFx0XHRwb3MueSArPSAyNTtcbiAgICogXHRcdGZ4LnJ1bihteVBvc2l0aW9uTWFya2VyLl9pY29uLCBwb3MsIDAuOCk7XG4gICAqIFx0fSk7XG4gICAqXG4gICAqIFx0ZngucnVuKG15UG9zaXRpb25NYXJrZXIuX2ljb24sIHBvcywgMC4zKTtcbiAgICogfSk7XG4gICAqXG4gICAqIGBgYFxuICAgKlxuICAgKiBAY29uc3RydWN0b3IgTC5Qb3NBbmltYXRpb24oKVxuICAgKiBDcmVhdGVzIGEgYFBvc0FuaW1hdGlvbmAgb2JqZWN0LlxuICAgKlxuICAgKi9cblxuICB2YXIgUG9zQW5pbWF0aW9uID0gRXZlbnRlZC5leHRlbmQoe1xuXG4gIFx0Ly8gQG1ldGhvZCBydW4oZWw6IEhUTUxFbGVtZW50LCBuZXdQb3M6IFBvaW50LCBkdXJhdGlvbj86IE51bWJlciwgZWFzZUxpbmVhcml0eT86IE51bWJlcilcbiAgXHQvLyBSdW4gYW4gYW5pbWF0aW9uIG9mIGEgZ2l2ZW4gZWxlbWVudCB0byBhIG5ldyBwb3NpdGlvbiwgb3B0aW9uYWxseSBzZXR0aW5nXG4gIFx0Ly8gZHVyYXRpb24gaW4gc2Vjb25kcyAoYDAuMjVgIGJ5IGRlZmF1bHQpIGFuZCBlYXNpbmcgbGluZWFyaXR5IGZhY3RvciAoM3JkXG4gIFx0Ly8gYXJndW1lbnQgb2YgdGhlIFtjdWJpYyBiZXppZXIgY3VydmVdKGh0dHBzOi8vY3ViaWMtYmV6aWVyLmNvbS8jMCwwLC41LDEpLFxuICBcdC8vIGAwLjVgIGJ5IGRlZmF1bHQpLlxuICBcdHJ1bjogZnVuY3Rpb24gKGVsLCBuZXdQb3MsIGR1cmF0aW9uLCBlYXNlTGluZWFyaXR5KSB7XG4gIFx0XHR0aGlzLnN0b3AoKTtcblxuICBcdFx0dGhpcy5fZWwgPSBlbDtcbiAgXHRcdHRoaXMuX2luUHJvZ3Jlc3MgPSB0cnVlO1xuICBcdFx0dGhpcy5fZHVyYXRpb24gPSBkdXJhdGlvbiB8fCAwLjI1O1xuICBcdFx0dGhpcy5fZWFzZU91dFBvd2VyID0gMSAvIE1hdGgubWF4KGVhc2VMaW5lYXJpdHkgfHwgMC41LCAwLjIpO1xuXG4gIFx0XHR0aGlzLl9zdGFydFBvcyA9IGdldFBvc2l0aW9uKGVsKTtcbiAgXHRcdHRoaXMuX29mZnNldCA9IG5ld1Bvcy5zdWJ0cmFjdCh0aGlzLl9zdGFydFBvcyk7XG4gIFx0XHR0aGlzLl9zdGFydFRpbWUgPSArbmV3IERhdGUoKTtcblxuICBcdFx0Ly8gQGV2ZW50IHN0YXJ0OiBFdmVudFxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgYW5pbWF0aW9uIHN0YXJ0c1xuICBcdFx0dGhpcy5maXJlKCdzdGFydCcpO1xuXG4gIFx0XHR0aGlzLl9hbmltYXRlKCk7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2Qgc3RvcCgpXG4gIFx0Ly8gU3RvcHMgdGhlIGFuaW1hdGlvbiAoaWYgY3VycmVudGx5IHJ1bm5pbmcpLlxuICBcdHN0b3A6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICghdGhpcy5faW5Qcm9ncmVzcykgeyByZXR1cm47IH1cblxuICBcdFx0dGhpcy5fc3RlcCh0cnVlKTtcbiAgXHRcdHRoaXMuX2NvbXBsZXRlKCk7XG4gIFx0fSxcblxuICBcdF9hbmltYXRlOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHQvLyBhbmltYXRpb24gbG9vcFxuICBcdFx0dGhpcy5fYW5pbUlkID0gcmVxdWVzdEFuaW1GcmFtZSh0aGlzLl9hbmltYXRlLCB0aGlzKTtcbiAgXHRcdHRoaXMuX3N0ZXAoKTtcbiAgXHR9LFxuXG4gIFx0X3N0ZXA6IGZ1bmN0aW9uIChyb3VuZCkge1xuICBcdFx0dmFyIGVsYXBzZWQgPSAoK25ldyBEYXRlKCkpIC0gdGhpcy5fc3RhcnRUaW1lLFxuICBcdFx0ICAgIGR1cmF0aW9uID0gdGhpcy5fZHVyYXRpb24gKiAxMDAwO1xuXG4gIFx0XHRpZiAoZWxhcHNlZCA8IGR1cmF0aW9uKSB7XG4gIFx0XHRcdHRoaXMuX3J1bkZyYW1lKHRoaXMuX2Vhc2VPdXQoZWxhcHNlZCAvIGR1cmF0aW9uKSwgcm91bmQpO1xuICBcdFx0fSBlbHNlIHtcbiAgXHRcdFx0dGhpcy5fcnVuRnJhbWUoMSk7XG4gIFx0XHRcdHRoaXMuX2NvbXBsZXRlKCk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF9ydW5GcmFtZTogZnVuY3Rpb24gKHByb2dyZXNzLCByb3VuZCkge1xuICBcdFx0dmFyIHBvcyA9IHRoaXMuX3N0YXJ0UG9zLmFkZCh0aGlzLl9vZmZzZXQubXVsdGlwbHlCeShwcm9ncmVzcykpO1xuICBcdFx0aWYgKHJvdW5kKSB7XG4gIFx0XHRcdHBvcy5fcm91bmQoKTtcbiAgXHRcdH1cbiAgXHRcdHNldFBvc2l0aW9uKHRoaXMuX2VsLCBwb3MpO1xuXG4gIFx0XHQvLyBAZXZlbnQgc3RlcDogRXZlbnRcbiAgXHRcdC8vIEZpcmVkIGNvbnRpbnVvdXNseSBkdXJpbmcgdGhlIGFuaW1hdGlvbi5cbiAgXHRcdHRoaXMuZmlyZSgnc3RlcCcpO1xuICBcdH0sXG5cbiAgXHRfY29tcGxldGU6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGNhbmNlbEFuaW1GcmFtZSh0aGlzLl9hbmltSWQpO1xuXG4gIFx0XHR0aGlzLl9pblByb2dyZXNzID0gZmFsc2U7XG4gIFx0XHQvLyBAZXZlbnQgZW5kOiBFdmVudFxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgYW5pbWF0aW9uIGVuZHMuXG4gIFx0XHR0aGlzLmZpcmUoJ2VuZCcpO1xuICBcdH0sXG5cbiAgXHRfZWFzZU91dDogZnVuY3Rpb24gKHQpIHtcbiAgXHRcdHJldHVybiAxIC0gTWF0aC5wb3coMSAtIHQsIHRoaXMuX2Vhc2VPdXRQb3dlcik7XG4gIFx0fVxuICB9KTtcblxuICAvKlxyXG4gICAqIEBjbGFzcyBNYXBcclxuICAgKiBAYWthIEwuTWFwXHJcbiAgICogQGluaGVyaXRzIEV2ZW50ZWRcclxuICAgKlxyXG4gICAqIFRoZSBjZW50cmFsIGNsYXNzIG9mIHRoZSBBUEkg4oCUIGl0IGlzIHVzZWQgdG8gY3JlYXRlIGEgbWFwIG9uIGEgcGFnZSBhbmQgbWFuaXB1bGF0ZSBpdC5cclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICpcclxuICAgKiBgYGBqc1xyXG4gICAqIC8vIGluaXRpYWxpemUgdGhlIG1hcCBvbiB0aGUgXCJtYXBcIiBkaXYgd2l0aCBhIGdpdmVuIGNlbnRlciBhbmQgem9vbVxyXG4gICAqIHZhciBtYXAgPSBMLm1hcCgnbWFwJywge1xyXG4gICAqIFx0Y2VudGVyOiBbNTEuNTA1LCAtMC4wOV0sXHJcbiAgICogXHR6b29tOiAxM1xyXG4gICAqIH0pO1xyXG4gICAqIGBgYFxyXG4gICAqXHJcbiAgICovXHJcblxyXG4gIHZhciBNYXAgPSBFdmVudGVkLmV4dGVuZCh7XHJcblxyXG4gIFx0b3B0aW9uczoge1xyXG4gIFx0XHQvLyBAc2VjdGlvbiBNYXAgU3RhdGUgT3B0aW9uc1xyXG4gIFx0XHQvLyBAb3B0aW9uIGNyczogQ1JTID0gTC5DUlMuRVBTRzM4NTdcclxuICBcdFx0Ly8gVGhlIFtDb29yZGluYXRlIFJlZmVyZW5jZSBTeXN0ZW1dKCNjcnMpIHRvIHVzZS4gRG9uJ3QgY2hhbmdlIHRoaXMgaWYgeW91J3JlIG5vdFxyXG4gIFx0XHQvLyBzdXJlIHdoYXQgaXQgbWVhbnMuXHJcbiAgXHRcdGNyczogRVBTRzM4NTcsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIGNlbnRlcjogTGF0TG5nID0gdW5kZWZpbmVkXHJcbiAgXHRcdC8vIEluaXRpYWwgZ2VvZ3JhcGhpYyBjZW50ZXIgb2YgdGhlIG1hcFxyXG4gIFx0XHRjZW50ZXI6IHVuZGVmaW5lZCxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gem9vbTogTnVtYmVyID0gdW5kZWZpbmVkXHJcbiAgXHRcdC8vIEluaXRpYWwgbWFwIHpvb20gbGV2ZWxcclxuICBcdFx0em9vbTogdW5kZWZpbmVkLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBtaW5ab29tOiBOdW1iZXIgPSAqXHJcbiAgXHRcdC8vIE1pbmltdW0gem9vbSBsZXZlbCBvZiB0aGUgbWFwLlxyXG4gIFx0XHQvLyBJZiBub3Qgc3BlY2lmaWVkIGFuZCBhdCBsZWFzdCBvbmUgYEdyaWRMYXllcmAgb3IgYFRpbGVMYXllcmAgaXMgaW4gdGhlIG1hcCxcclxuICBcdFx0Ly8gdGhlIGxvd2VzdCBvZiB0aGVpciBgbWluWm9vbWAgb3B0aW9ucyB3aWxsIGJlIHVzZWQgaW5zdGVhZC5cclxuICBcdFx0bWluWm9vbTogdW5kZWZpbmVkLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBtYXhab29tOiBOdW1iZXIgPSAqXHJcbiAgXHRcdC8vIE1heGltdW0gem9vbSBsZXZlbCBvZiB0aGUgbWFwLlxyXG4gIFx0XHQvLyBJZiBub3Qgc3BlY2lmaWVkIGFuZCBhdCBsZWFzdCBvbmUgYEdyaWRMYXllcmAgb3IgYFRpbGVMYXllcmAgaXMgaW4gdGhlIG1hcCxcclxuICBcdFx0Ly8gdGhlIGhpZ2hlc3Qgb2YgdGhlaXIgYG1heFpvb21gIG9wdGlvbnMgd2lsbCBiZSB1c2VkIGluc3RlYWQuXHJcbiAgXHRcdG1heFpvb206IHVuZGVmaW5lZCxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gbGF5ZXJzOiBMYXllcltdID0gW11cclxuICBcdFx0Ly8gQXJyYXkgb2YgbGF5ZXJzIHRoYXQgd2lsbCBiZSBhZGRlZCB0byB0aGUgbWFwIGluaXRpYWxseVxyXG4gIFx0XHRsYXllcnM6IFtdLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBtYXhCb3VuZHM6IExhdExuZ0JvdW5kcyA9IG51bGxcclxuICBcdFx0Ly8gV2hlbiB0aGlzIG9wdGlvbiBpcyBzZXQsIHRoZSBtYXAgcmVzdHJpY3RzIHRoZSB2aWV3IHRvIHRoZSBnaXZlblxyXG4gIFx0XHQvLyBnZW9ncmFwaGljYWwgYm91bmRzLCBib3VuY2luZyB0aGUgdXNlciBiYWNrIGlmIHRoZSB1c2VyIHRyaWVzIHRvIHBhblxyXG4gIFx0XHQvLyBvdXRzaWRlIHRoZSB2aWV3LiBUbyBzZXQgdGhlIHJlc3RyaWN0aW9uIGR5bmFtaWNhbGx5LCB1c2VcclxuICBcdFx0Ly8gW2BzZXRNYXhCb3VuZHNgXSgjbWFwLXNldG1heGJvdW5kcykgbWV0aG9kLlxyXG4gIFx0XHRtYXhCb3VuZHM6IHVuZGVmaW5lZCxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gcmVuZGVyZXI6IFJlbmRlcmVyID0gKlxyXG4gIFx0XHQvLyBUaGUgZGVmYXVsdCBtZXRob2QgZm9yIGRyYXdpbmcgdmVjdG9yIGxheWVycyBvbiB0aGUgbWFwLiBgTC5TVkdgXHJcbiAgXHRcdC8vIG9yIGBMLkNhbnZhc2AgYnkgZGVmYXVsdCBkZXBlbmRpbmcgb24gYnJvd3NlciBzdXBwb3J0LlxyXG4gIFx0XHRyZW5kZXJlcjogdW5kZWZpbmVkLFxyXG5cclxuXHJcbiAgXHRcdC8vIEBzZWN0aW9uIEFuaW1hdGlvbiBPcHRpb25zXHJcbiAgXHRcdC8vIEBvcHRpb24gem9vbUFuaW1hdGlvbjogQm9vbGVhbiA9IHRydWVcclxuICBcdFx0Ly8gV2hldGhlciB0aGUgbWFwIHpvb20gYW5pbWF0aW9uIGlzIGVuYWJsZWQuIEJ5IGRlZmF1bHQgaXQncyBlbmFibGVkXHJcbiAgXHRcdC8vIGluIGFsbCBicm93c2VycyB0aGF0IHN1cHBvcnQgQ1NTMyBUcmFuc2l0aW9ucyBleGNlcHQgQW5kcm9pZC5cclxuICBcdFx0em9vbUFuaW1hdGlvbjogdHJ1ZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gem9vbUFuaW1hdGlvblRocmVzaG9sZDogTnVtYmVyID0gNFxyXG4gIFx0XHQvLyBXb24ndCBhbmltYXRlIHpvb20gaWYgdGhlIHpvb20gZGlmZmVyZW5jZSBleGNlZWRzIHRoaXMgdmFsdWUuXHJcbiAgXHRcdHpvb21BbmltYXRpb25UaHJlc2hvbGQ6IDQsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIGZhZGVBbmltYXRpb246IEJvb2xlYW4gPSB0cnVlXHJcbiAgXHRcdC8vIFdoZXRoZXIgdGhlIHRpbGUgZmFkZSBhbmltYXRpb24gaXMgZW5hYmxlZC4gQnkgZGVmYXVsdCBpdCdzIGVuYWJsZWRcclxuICBcdFx0Ly8gaW4gYWxsIGJyb3dzZXJzIHRoYXQgc3VwcG9ydCBDU1MzIFRyYW5zaXRpb25zIGV4Y2VwdCBBbmRyb2lkLlxyXG4gIFx0XHRmYWRlQW5pbWF0aW9uOiB0cnVlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBtYXJrZXJab29tQW5pbWF0aW9uOiBCb29sZWFuID0gdHJ1ZVxyXG4gIFx0XHQvLyBXaGV0aGVyIG1hcmtlcnMgYW5pbWF0ZSB0aGVpciB6b29tIHdpdGggdGhlIHpvb20gYW5pbWF0aW9uLCBpZiBkaXNhYmxlZFxyXG4gIFx0XHQvLyB0aGV5IHdpbGwgZGlzYXBwZWFyIGZvciB0aGUgbGVuZ3RoIG9mIHRoZSBhbmltYXRpb24uIEJ5IGRlZmF1bHQgaXQnc1xyXG4gIFx0XHQvLyBlbmFibGVkIGluIGFsbCBicm93c2VycyB0aGF0IHN1cHBvcnQgQ1NTMyBUcmFuc2l0aW9ucyBleGNlcHQgQW5kcm9pZC5cclxuICBcdFx0bWFya2VyWm9vbUFuaW1hdGlvbjogdHJ1ZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gdHJhbnNmb3JtM0RMaW1pdDogTnVtYmVyID0gMl4yM1xyXG4gIFx0XHQvLyBEZWZpbmVzIHRoZSBtYXhpbXVtIHNpemUgb2YgYSBDU1MgdHJhbnNsYXRpb24gdHJhbnNmb3JtLiBUaGUgZGVmYXVsdFxyXG4gIFx0XHQvLyB2YWx1ZSBzaG91bGQgbm90IGJlIGNoYW5nZWQgdW5sZXNzIGEgd2ViIGJyb3dzZXIgcG9zaXRpb25zIGxheWVycyBpblxyXG4gIFx0XHQvLyB0aGUgd3JvbmcgcGxhY2UgYWZ0ZXIgZG9pbmcgYSBsYXJnZSBgcGFuQnlgLlxyXG4gIFx0XHR0cmFuc2Zvcm0zRExpbWl0OiA4Mzg4NjA4LCAvLyBQcmVjaXNpb24gbGltaXQgb2YgYSAzMi1iaXQgZmxvYXRcclxuXHJcbiAgXHRcdC8vIEBzZWN0aW9uIEludGVyYWN0aW9uIE9wdGlvbnNcclxuICBcdFx0Ly8gQG9wdGlvbiB6b29tU25hcDogTnVtYmVyID0gMVxyXG4gIFx0XHQvLyBGb3JjZXMgdGhlIG1hcCdzIHpvb20gbGV2ZWwgdG8gYWx3YXlzIGJlIGEgbXVsdGlwbGUgb2YgdGhpcywgcGFydGljdWxhcmx5XHJcbiAgXHRcdC8vIHJpZ2h0IGFmdGVyIGEgW2BmaXRCb3VuZHMoKWBdKCNtYXAtZml0Ym91bmRzKSBvciBhIHBpbmNoLXpvb20uXHJcbiAgXHRcdC8vIEJ5IGRlZmF1bHQsIHRoZSB6b29tIGxldmVsIHNuYXBzIHRvIHRoZSBuZWFyZXN0IGludGVnZXI7IGxvd2VyIHZhbHVlc1xyXG4gIFx0XHQvLyAoZS5nLiBgMC41YCBvciBgMC4xYCkgYWxsb3cgZm9yIGdyZWF0ZXIgZ3JhbnVsYXJpdHkuIEEgdmFsdWUgb2YgYDBgXHJcbiAgXHRcdC8vIG1lYW5zIHRoZSB6b29tIGxldmVsIHdpbGwgbm90IGJlIHNuYXBwZWQgYWZ0ZXIgYGZpdEJvdW5kc2Agb3IgYSBwaW5jaC16b29tLlxyXG4gIFx0XHR6b29tU25hcDogMSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gem9vbURlbHRhOiBOdW1iZXIgPSAxXHJcbiAgXHRcdC8vIENvbnRyb2xzIGhvdyBtdWNoIHRoZSBtYXAncyB6b29tIGxldmVsIHdpbGwgY2hhbmdlIGFmdGVyIGFcclxuICBcdFx0Ly8gW2B6b29tSW4oKWBdKCNtYXAtem9vbWluKSwgW2B6b29tT3V0KClgXSgjbWFwLXpvb21vdXQpLCBwcmVzc2luZyBgK2BcclxuICBcdFx0Ly8gb3IgYC1gIG9uIHRoZSBrZXlib2FyZCwgb3IgdXNpbmcgdGhlIFt6b29tIGNvbnRyb2xzXSgjY29udHJvbC16b29tKS5cclxuICBcdFx0Ly8gVmFsdWVzIHNtYWxsZXIgdGhhbiBgMWAgKGUuZy4gYDAuNWApIGFsbG93IGZvciBncmVhdGVyIGdyYW51bGFyaXR5LlxyXG4gIFx0XHR6b29tRGVsdGE6IDEsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHRyYWNrUmVzaXplOiBCb29sZWFuID0gdHJ1ZVxyXG4gIFx0XHQvLyBXaGV0aGVyIHRoZSBtYXAgYXV0b21hdGljYWxseSBoYW5kbGVzIGJyb3dzZXIgd2luZG93IHJlc2l6ZSB0byB1cGRhdGUgaXRzZWxmLlxyXG4gIFx0XHR0cmFja1Jlc2l6ZTogdHJ1ZVxyXG4gIFx0fSxcclxuXHJcbiAgXHRpbml0aWFsaXplOiBmdW5jdGlvbiAoaWQsIG9wdGlvbnMpIHsgLy8gKEhUTUxFbGVtZW50IG9yIFN0cmluZywgT2JqZWN0KVxyXG4gIFx0XHRvcHRpb25zID0gc2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcclxuXHJcbiAgXHRcdC8vIE1ha2Ugc3VyZSB0byBhc3NpZ24gaW50ZXJuYWwgZmxhZ3MgYXQgdGhlIGJlZ2lubmluZyxcclxuICBcdFx0Ly8gdG8gYXZvaWQgaW5jb25zaXN0ZW50IHN0YXRlIGluIHNvbWUgZWRnZSBjYXNlcy5cclxuICBcdFx0dGhpcy5faGFuZGxlcnMgPSBbXTtcclxuICBcdFx0dGhpcy5fbGF5ZXJzID0ge307XHJcbiAgXHRcdHRoaXMuX3pvb21Cb3VuZExheWVycyA9IHt9O1xyXG4gIFx0XHR0aGlzLl9zaXplQ2hhbmdlZCA9IHRydWU7XHJcblxyXG4gIFx0XHR0aGlzLl9pbml0Q29udGFpbmVyKGlkKTtcclxuICBcdFx0dGhpcy5faW5pdExheW91dCgpO1xyXG5cclxuICBcdFx0Ly8gaGFjayBmb3IgaHR0cHM6Ly9naXRodWIuY29tL0xlYWZsZXQvTGVhZmxldC9pc3N1ZXMvMTk4MFxyXG4gIFx0XHR0aGlzLl9vblJlc2l6ZSA9IGJpbmQodGhpcy5fb25SZXNpemUsIHRoaXMpO1xyXG5cclxuICBcdFx0dGhpcy5faW5pdEV2ZW50cygpO1xyXG5cclxuICBcdFx0aWYgKG9wdGlvbnMubWF4Qm91bmRzKSB7XHJcbiAgXHRcdFx0dGhpcy5zZXRNYXhCb3VuZHMob3B0aW9ucy5tYXhCb3VuZHMpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAob3B0aW9ucy56b29tICE9PSB1bmRlZmluZWQpIHtcclxuICBcdFx0XHR0aGlzLl96b29tID0gdGhpcy5fbGltaXRab29tKG9wdGlvbnMuem9vbSk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmIChvcHRpb25zLmNlbnRlciAmJiBvcHRpb25zLnpvb20gIT09IHVuZGVmaW5lZCkge1xyXG4gIFx0XHRcdHRoaXMuc2V0Vmlldyh0b0xhdExuZyhvcHRpb25zLmNlbnRlciksIG9wdGlvbnMuem9vbSwge3Jlc2V0OiB0cnVlfSk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuY2FsbEluaXRIb29rcygpO1xyXG5cclxuICBcdFx0Ly8gZG9uJ3QgYW5pbWF0ZSBvbiBicm93c2VycyB3aXRob3V0IGhhcmR3YXJlLWFjY2VsZXJhdGVkIHRyYW5zaXRpb25zIG9yIG9sZCBBbmRyb2lkL09wZXJhXHJcbiAgXHRcdHRoaXMuX3pvb21BbmltYXRlZCA9IFRSQU5TSVRJT04gJiYgQnJvd3Nlci5hbnkzZCAmJiAhQnJvd3Nlci5tb2JpbGVPcGVyYSAmJlxyXG4gIFx0XHRcdFx0dGhpcy5vcHRpb25zLnpvb21BbmltYXRpb247XHJcblxyXG4gIFx0XHQvLyB6b29tIHRyYW5zaXRpb25zIHJ1biB3aXRoIHRoZSBzYW1lIGR1cmF0aW9uIGZvciBhbGwgbGF5ZXJzLCBzbyBpZiBvbmUgb2YgdHJhbnNpdGlvbmVuZCBldmVudHNcclxuICBcdFx0Ly8gaGFwcGVucyBhZnRlciBzdGFydGluZyB6b29tIGFuaW1hdGlvbiAocHJvcGFnYXRpbmcgdG8gdGhlIG1hcCBwYW5lKSwgd2Uga25vdyB0aGF0IGl0IGVuZGVkIGdsb2JhbGx5XHJcbiAgXHRcdGlmICh0aGlzLl96b29tQW5pbWF0ZWQpIHtcclxuICBcdFx0XHR0aGlzLl9jcmVhdGVBbmltUHJveHkoKTtcclxuICBcdFx0XHRvbih0aGlzLl9wcm94eSwgVFJBTlNJVElPTl9FTkQsIHRoaXMuX2NhdGNoVHJhbnNpdGlvbkVuZCwgdGhpcyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX2FkZExheWVycyh0aGlzLm9wdGlvbnMubGF5ZXJzKTtcclxuICBcdH0sXHJcblxyXG5cclxuICBcdC8vIEBzZWN0aW9uIE1ldGhvZHMgZm9yIG1vZGlmeWluZyBtYXAgc3RhdGVcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNldFZpZXcoY2VudGVyOiBMYXRMbmcsIHpvb206IE51bWJlciwgb3B0aW9ucz86IFpvb20vcGFuIG9wdGlvbnMpOiB0aGlzXHJcbiAgXHQvLyBTZXRzIHRoZSB2aWV3IG9mIHRoZSBtYXAgKGdlb2dyYXBoaWNhbCBjZW50ZXIgYW5kIHpvb20pIHdpdGggdGhlIGdpdmVuXHJcbiAgXHQvLyBhbmltYXRpb24gb3B0aW9ucy5cclxuICBcdHNldFZpZXc6IGZ1bmN0aW9uIChjZW50ZXIsIHpvb20sIG9wdGlvbnMpIHtcclxuXHJcbiAgXHRcdHpvb20gPSB6b29tID09PSB1bmRlZmluZWQgPyB0aGlzLl96b29tIDogdGhpcy5fbGltaXRab29tKHpvb20pO1xyXG4gIFx0XHRjZW50ZXIgPSB0aGlzLl9saW1pdENlbnRlcih0b0xhdExuZyhjZW50ZXIpLCB6b29tLCB0aGlzLm9wdGlvbnMubWF4Qm91bmRzKTtcclxuICBcdFx0b3B0aW9ucyA9IG9wdGlvbnMgfHwge307XHJcblxyXG4gIFx0XHR0aGlzLl9zdG9wKCk7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fbG9hZGVkICYmICFvcHRpb25zLnJlc2V0ICYmIG9wdGlvbnMgIT09IHRydWUpIHtcclxuXHJcbiAgXHRcdFx0aWYgKG9wdGlvbnMuYW5pbWF0ZSAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgXHRcdFx0XHRvcHRpb25zLnpvb20gPSBleHRlbmQoe2FuaW1hdGU6IG9wdGlvbnMuYW5pbWF0ZX0sIG9wdGlvbnMuem9vbSk7XHJcbiAgXHRcdFx0XHRvcHRpb25zLnBhbiA9IGV4dGVuZCh7YW5pbWF0ZTogb3B0aW9ucy5hbmltYXRlLCBkdXJhdGlvbjogb3B0aW9ucy5kdXJhdGlvbn0sIG9wdGlvbnMucGFuKTtcclxuICBcdFx0XHR9XHJcblxyXG4gIFx0XHRcdC8vIHRyeSBhbmltYXRpbmcgcGFuIG9yIHpvb21cclxuICBcdFx0XHR2YXIgbW92ZWQgPSAodGhpcy5fem9vbSAhPT0gem9vbSkgP1xyXG4gIFx0XHRcdFx0dGhpcy5fdHJ5QW5pbWF0ZWRab29tICYmIHRoaXMuX3RyeUFuaW1hdGVkWm9vbShjZW50ZXIsIHpvb20sIG9wdGlvbnMuem9vbSkgOlxyXG4gIFx0XHRcdFx0dGhpcy5fdHJ5QW5pbWF0ZWRQYW4oY2VudGVyLCBvcHRpb25zLnBhbik7XHJcblxyXG4gIFx0XHRcdGlmIChtb3ZlZCkge1xyXG4gIFx0XHRcdFx0Ly8gcHJldmVudCByZXNpemUgaGFuZGxlciBjYWxsLCB0aGUgdmlldyB3aWxsIHJlZnJlc2ggYWZ0ZXIgYW5pbWF0aW9uIGFueXdheVxyXG4gIFx0XHRcdFx0Y2xlYXJUaW1lb3V0KHRoaXMuX3NpemVUaW1lcik7XHJcbiAgXHRcdFx0XHRyZXR1cm4gdGhpcztcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdC8vIGFuaW1hdGlvbiBkaWRuJ3Qgc3RhcnQsIGp1c3QgcmVzZXQgdGhlIG1hcCB2aWV3XHJcbiAgXHRcdHRoaXMuX3Jlc2V0VmlldyhjZW50ZXIsIHpvb20sIG9wdGlvbnMucGFuICYmIG9wdGlvbnMucGFuLm5vTW92ZVN0YXJ0KTtcclxuXHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNldFpvb20oem9vbTogTnVtYmVyLCBvcHRpb25zPzogWm9vbS9wYW4gb3B0aW9ucyk6IHRoaXNcclxuICBcdC8vIFNldHMgdGhlIHpvb20gb2YgdGhlIG1hcC5cclxuICBcdHNldFpvb206IGZ1bmN0aW9uICh6b29tLCBvcHRpb25zKSB7XHJcbiAgXHRcdGlmICghdGhpcy5fbG9hZGVkKSB7XHJcbiAgXHRcdFx0dGhpcy5fem9vbSA9IHpvb207XHJcbiAgXHRcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXMuc2V0Vmlldyh0aGlzLmdldENlbnRlcigpLCB6b29tLCB7em9vbTogb3B0aW9uc30pO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHpvb21JbihkZWx0YT86IE51bWJlciwgb3B0aW9ucz86IFpvb20gb3B0aW9ucyk6IHRoaXNcclxuICBcdC8vIEluY3JlYXNlcyB0aGUgem9vbSBvZiB0aGUgbWFwIGJ5IGBkZWx0YWAgKFtgem9vbURlbHRhYF0oI21hcC16b29tZGVsdGEpIGJ5IGRlZmF1bHQpLlxyXG4gIFx0em9vbUluOiBmdW5jdGlvbiAoZGVsdGEsIG9wdGlvbnMpIHtcclxuICBcdFx0ZGVsdGEgPSBkZWx0YSB8fCAoQnJvd3Nlci5hbnkzZCA/IHRoaXMub3B0aW9ucy56b29tRGVsdGEgOiAxKTtcclxuICBcdFx0cmV0dXJuIHRoaXMuc2V0Wm9vbSh0aGlzLl96b29tICsgZGVsdGEsIG9wdGlvbnMpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHpvb21PdXQoZGVsdGE/OiBOdW1iZXIsIG9wdGlvbnM/OiBab29tIG9wdGlvbnMpOiB0aGlzXHJcbiAgXHQvLyBEZWNyZWFzZXMgdGhlIHpvb20gb2YgdGhlIG1hcCBieSBgZGVsdGFgIChbYHpvb21EZWx0YWBdKCNtYXAtem9vbWRlbHRhKSBieSBkZWZhdWx0KS5cclxuICBcdHpvb21PdXQ6IGZ1bmN0aW9uIChkZWx0YSwgb3B0aW9ucykge1xyXG4gIFx0XHRkZWx0YSA9IGRlbHRhIHx8IChCcm93c2VyLmFueTNkID8gdGhpcy5vcHRpb25zLnpvb21EZWx0YSA6IDEpO1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5zZXRab29tKHRoaXMuX3pvb20gLSBkZWx0YSwgb3B0aW9ucyk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2V0Wm9vbUFyb3VuZChsYXRsbmc6IExhdExuZywgem9vbTogTnVtYmVyLCBvcHRpb25zOiBab29tIG9wdGlvbnMpOiB0aGlzXHJcbiAgXHQvLyBab29tcyB0aGUgbWFwIHdoaWxlIGtlZXBpbmcgYSBzcGVjaWZpZWQgZ2VvZ3JhcGhpY2FsIHBvaW50IG9uIHRoZSBtYXBcclxuICBcdC8vIHN0YXRpb25hcnkgKGUuZy4gdXNlZCBpbnRlcm5hbGx5IGZvciBzY3JvbGwgem9vbSBhbmQgZG91YmxlLWNsaWNrIHpvb20pLlxyXG4gIFx0Ly8gQGFsdGVybmF0aXZlXHJcbiAgXHQvLyBAbWV0aG9kIHNldFpvb21Bcm91bmQob2Zmc2V0OiBQb2ludCwgem9vbTogTnVtYmVyLCBvcHRpb25zOiBab29tIG9wdGlvbnMpOiB0aGlzXHJcbiAgXHQvLyBab29tcyB0aGUgbWFwIHdoaWxlIGtlZXBpbmcgYSBzcGVjaWZpZWQgcGl4ZWwgb24gdGhlIG1hcCAocmVsYXRpdmUgdG8gdGhlIHRvcC1sZWZ0IGNvcm5lcikgc3RhdGlvbmFyeS5cclxuICBcdHNldFpvb21Bcm91bmQ6IGZ1bmN0aW9uIChsYXRsbmcsIHpvb20sIG9wdGlvbnMpIHtcclxuICBcdFx0dmFyIHNjYWxlID0gdGhpcy5nZXRab29tU2NhbGUoem9vbSksXHJcbiAgXHRcdCAgICB2aWV3SGFsZiA9IHRoaXMuZ2V0U2l6ZSgpLmRpdmlkZUJ5KDIpLFxyXG4gIFx0XHQgICAgY29udGFpbmVyUG9pbnQgPSBsYXRsbmcgaW5zdGFuY2VvZiBQb2ludCA/IGxhdGxuZyA6IHRoaXMubGF0TG5nVG9Db250YWluZXJQb2ludChsYXRsbmcpLFxyXG5cclxuICBcdFx0ICAgIGNlbnRlck9mZnNldCA9IGNvbnRhaW5lclBvaW50LnN1YnRyYWN0KHZpZXdIYWxmKS5tdWx0aXBseUJ5KDEgLSAxIC8gc2NhbGUpLFxyXG4gIFx0XHQgICAgbmV3Q2VudGVyID0gdGhpcy5jb250YWluZXJQb2ludFRvTGF0TG5nKHZpZXdIYWxmLmFkZChjZW50ZXJPZmZzZXQpKTtcclxuXHJcbiAgXHRcdHJldHVybiB0aGlzLnNldFZpZXcobmV3Q2VudGVyLCB6b29tLCB7em9vbTogb3B0aW9uc30pO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfZ2V0Qm91bmRzQ2VudGVyWm9vbTogZnVuY3Rpb24gKGJvdW5kcywgb3B0aW9ucykge1xyXG5cclxuICBcdFx0b3B0aW9ucyA9IG9wdGlvbnMgfHwge307XHJcbiAgXHRcdGJvdW5kcyA9IGJvdW5kcy5nZXRCb3VuZHMgPyBib3VuZHMuZ2V0Qm91bmRzKCkgOiB0b0xhdExuZ0JvdW5kcyhib3VuZHMpO1xyXG5cclxuICBcdFx0dmFyIHBhZGRpbmdUTCA9IHRvUG9pbnQob3B0aW9ucy5wYWRkaW5nVG9wTGVmdCB8fCBvcHRpb25zLnBhZGRpbmcgfHwgWzAsIDBdKSxcclxuICBcdFx0ICAgIHBhZGRpbmdCUiA9IHRvUG9pbnQob3B0aW9ucy5wYWRkaW5nQm90dG9tUmlnaHQgfHwgb3B0aW9ucy5wYWRkaW5nIHx8IFswLCAwXSksXHJcblxyXG4gIFx0XHQgICAgem9vbSA9IHRoaXMuZ2V0Qm91bmRzWm9vbShib3VuZHMsIGZhbHNlLCBwYWRkaW5nVEwuYWRkKHBhZGRpbmdCUikpO1xyXG5cclxuICBcdFx0em9vbSA9ICh0eXBlb2Ygb3B0aW9ucy5tYXhab29tID09PSAnbnVtYmVyJykgPyBNYXRoLm1pbihvcHRpb25zLm1heFpvb20sIHpvb20pIDogem9vbTtcclxuXHJcbiAgXHRcdGlmICh6b29tID09PSBJbmZpbml0eSkge1xyXG4gIFx0XHRcdHJldHVybiB7XHJcbiAgXHRcdFx0XHRjZW50ZXI6IGJvdW5kcy5nZXRDZW50ZXIoKSxcclxuICBcdFx0XHRcdHpvb206IHpvb21cclxuICBcdFx0XHR9O1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgcGFkZGluZ09mZnNldCA9IHBhZGRpbmdCUi5zdWJ0cmFjdChwYWRkaW5nVEwpLmRpdmlkZUJ5KDIpLFxyXG5cclxuICBcdFx0ICAgIHN3UG9pbnQgPSB0aGlzLnByb2plY3QoYm91bmRzLmdldFNvdXRoV2VzdCgpLCB6b29tKSxcclxuICBcdFx0ICAgIG5lUG9pbnQgPSB0aGlzLnByb2plY3QoYm91bmRzLmdldE5vcnRoRWFzdCgpLCB6b29tKSxcclxuICBcdFx0ICAgIGNlbnRlciA9IHRoaXMudW5wcm9qZWN0KHN3UG9pbnQuYWRkKG5lUG9pbnQpLmRpdmlkZUJ5KDIpLmFkZChwYWRkaW5nT2Zmc2V0KSwgem9vbSk7XHJcblxyXG4gIFx0XHRyZXR1cm4ge1xyXG4gIFx0XHRcdGNlbnRlcjogY2VudGVyLFxyXG4gIFx0XHRcdHpvb206IHpvb21cclxuICBcdFx0fTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBmaXRCb3VuZHMoYm91bmRzOiBMYXRMbmdCb3VuZHMsIG9wdGlvbnM/OiBmaXRCb3VuZHMgb3B0aW9ucyk6IHRoaXNcclxuICBcdC8vIFNldHMgYSBtYXAgdmlldyB0aGF0IGNvbnRhaW5zIHRoZSBnaXZlbiBnZW9ncmFwaGljYWwgYm91bmRzIHdpdGggdGhlXHJcbiAgXHQvLyBtYXhpbXVtIHpvb20gbGV2ZWwgcG9zc2libGUuXHJcbiAgXHRmaXRCb3VuZHM6IGZ1bmN0aW9uIChib3VuZHMsIG9wdGlvbnMpIHtcclxuXHJcbiAgXHRcdGJvdW5kcyA9IHRvTGF0TG5nQm91bmRzKGJvdW5kcyk7XHJcblxyXG4gIFx0XHRpZiAoIWJvdW5kcy5pc1ZhbGlkKCkpIHtcclxuICBcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0JvdW5kcyBhcmUgbm90IHZhbGlkLicpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgdGFyZ2V0ID0gdGhpcy5fZ2V0Qm91bmRzQ2VudGVyWm9vbShib3VuZHMsIG9wdGlvbnMpO1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5zZXRWaWV3KHRhcmdldC5jZW50ZXIsIHRhcmdldC56b29tLCBvcHRpb25zKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBmaXRXb3JsZChvcHRpb25zPzogZml0Qm91bmRzIG9wdGlvbnMpOiB0aGlzXHJcbiAgXHQvLyBTZXRzIGEgbWFwIHZpZXcgdGhhdCBtb3N0bHkgY29udGFpbnMgdGhlIHdob2xlIHdvcmxkIHdpdGggdGhlIG1heGltdW1cclxuICBcdC8vIHpvb20gbGV2ZWwgcG9zc2libGUuXHJcbiAgXHRmaXRXb3JsZDogZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuZml0Qm91bmRzKFtbLTkwLCAtMTgwXSwgWzkwLCAxODBdXSwgb3B0aW9ucyk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgcGFuVG8obGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/OiBQYW4gb3B0aW9ucyk6IHRoaXNcclxuICBcdC8vIFBhbnMgdGhlIG1hcCB0byBhIGdpdmVuIGNlbnRlci5cclxuICBcdHBhblRvOiBmdW5jdGlvbiAoY2VudGVyLCBvcHRpb25zKSB7IC8vIChMYXRMbmcpXHJcbiAgXHRcdHJldHVybiB0aGlzLnNldFZpZXcoY2VudGVyLCB0aGlzLl96b29tLCB7cGFuOiBvcHRpb25zfSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgcGFuQnkob2Zmc2V0OiBQb2ludCwgb3B0aW9ucz86IFBhbiBvcHRpb25zKTogdGhpc1xyXG4gIFx0Ly8gUGFucyB0aGUgbWFwIGJ5IGEgZ2l2ZW4gbnVtYmVyIG9mIHBpeGVscyAoYW5pbWF0ZWQpLlxyXG4gIFx0cGFuQnk6IGZ1bmN0aW9uIChvZmZzZXQsIG9wdGlvbnMpIHtcclxuICBcdFx0b2Zmc2V0ID0gdG9Qb2ludChvZmZzZXQpLnJvdW5kKCk7XHJcbiAgXHRcdG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xyXG5cclxuICBcdFx0aWYgKCFvZmZzZXQueCAmJiAhb2Zmc2V0LnkpIHtcclxuICBcdFx0XHRyZXR1cm4gdGhpcy5maXJlKCdtb3ZlZW5kJyk7XHJcbiAgXHRcdH1cclxuICBcdFx0Ly8gSWYgd2UgcGFuIHRvbyBmYXIsIENocm9tZSBnZXRzIGlzc3VlcyB3aXRoIHRpbGVzXHJcbiAgXHRcdC8vIGFuZCBtYWtlcyB0aGVtIGRpc2FwcGVhciBvciBhcHBlYXIgaW4gdGhlIHdyb25nIHBsYWNlIChzbGlnaHRseSBvZmZzZXQpICMyNjAyXHJcbiAgXHRcdGlmIChvcHRpb25zLmFuaW1hdGUgIT09IHRydWUgJiYgIXRoaXMuZ2V0U2l6ZSgpLmNvbnRhaW5zKG9mZnNldCkpIHtcclxuICBcdFx0XHR0aGlzLl9yZXNldFZpZXcodGhpcy51bnByb2plY3QodGhpcy5wcm9qZWN0KHRoaXMuZ2V0Q2VudGVyKCkpLmFkZChvZmZzZXQpKSwgdGhpcy5nZXRab29tKCkpO1xyXG4gIFx0XHRcdHJldHVybiB0aGlzO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAoIXRoaXMuX3BhbkFuaW0pIHtcclxuICBcdFx0XHR0aGlzLl9wYW5BbmltID0gbmV3IFBvc0FuaW1hdGlvbigpO1xyXG5cclxuICBcdFx0XHR0aGlzLl9wYW5BbmltLm9uKHtcclxuICBcdFx0XHRcdCdzdGVwJzogdGhpcy5fb25QYW5UcmFuc2l0aW9uU3RlcCxcclxuICBcdFx0XHRcdCdlbmQnOiB0aGlzLl9vblBhblRyYW5zaXRpb25FbmRcclxuICBcdFx0XHR9LCB0aGlzKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gZG9uJ3QgZmlyZSBtb3Zlc3RhcnQgaWYgYW5pbWF0aW5nIGluZXJ0aWFcclxuICBcdFx0aWYgKCFvcHRpb25zLm5vTW92ZVN0YXJ0KSB7XHJcbiAgXHRcdFx0dGhpcy5maXJlKCdtb3Zlc3RhcnQnKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gYW5pbWF0ZSBwYW4gdW5sZXNzIGFuaW1hdGU6IGZhbHNlIHNwZWNpZmllZFxyXG4gIFx0XHRpZiAob3B0aW9ucy5hbmltYXRlICE9PSBmYWxzZSkge1xyXG4gIFx0XHRcdGFkZENsYXNzKHRoaXMuX21hcFBhbmUsICdsZWFmbGV0LXBhbi1hbmltJyk7XHJcblxyXG4gIFx0XHRcdHZhciBuZXdQb3MgPSB0aGlzLl9nZXRNYXBQYW5lUG9zKCkuc3VidHJhY3Qob2Zmc2V0KS5yb3VuZCgpO1xyXG4gIFx0XHRcdHRoaXMuX3BhbkFuaW0ucnVuKHRoaXMuX21hcFBhbmUsIG5ld1Bvcywgb3B0aW9ucy5kdXJhdGlvbiB8fCAwLjI1LCBvcHRpb25zLmVhc2VMaW5lYXJpdHkpO1xyXG4gIFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdHRoaXMuX3Jhd1BhbkJ5KG9mZnNldCk7XHJcbiAgXHRcdFx0dGhpcy5maXJlKCdtb3ZlJykuZmlyZSgnbW92ZWVuZCcpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBmbHlUbyhsYXRsbmc6IExhdExuZywgem9vbT86IE51bWJlciwgb3B0aW9ucz86IFpvb20vcGFuIG9wdGlvbnMpOiB0aGlzXHJcbiAgXHQvLyBTZXRzIHRoZSB2aWV3IG9mIHRoZSBtYXAgKGdlb2dyYXBoaWNhbCBjZW50ZXIgYW5kIHpvb20pIHBlcmZvcm1pbmcgYSBzbW9vdGhcclxuICBcdC8vIHBhbi16b29tIGFuaW1hdGlvbi5cclxuICBcdGZseVRvOiBmdW5jdGlvbiAodGFyZ2V0Q2VudGVyLCB0YXJnZXRab29tLCBvcHRpb25zKSB7XHJcblxyXG4gIFx0XHRvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcclxuICBcdFx0aWYgKG9wdGlvbnMuYW5pbWF0ZSA9PT0gZmFsc2UgfHwgIUJyb3dzZXIuYW55M2QpIHtcclxuICBcdFx0XHRyZXR1cm4gdGhpcy5zZXRWaWV3KHRhcmdldENlbnRlciwgdGFyZ2V0Wm9vbSwgb3B0aW9ucyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX3N0b3AoKTtcclxuXHJcbiAgXHRcdHZhciBmcm9tID0gdGhpcy5wcm9qZWN0KHRoaXMuZ2V0Q2VudGVyKCkpLFxyXG4gIFx0XHQgICAgdG8gPSB0aGlzLnByb2plY3QodGFyZ2V0Q2VudGVyKSxcclxuICBcdFx0ICAgIHNpemUgPSB0aGlzLmdldFNpemUoKSxcclxuICBcdFx0ICAgIHN0YXJ0Wm9vbSA9IHRoaXMuX3pvb207XHJcblxyXG4gIFx0XHR0YXJnZXRDZW50ZXIgPSB0b0xhdExuZyh0YXJnZXRDZW50ZXIpO1xyXG4gIFx0XHR0YXJnZXRab29tID0gdGFyZ2V0Wm9vbSA9PT0gdW5kZWZpbmVkID8gc3RhcnRab29tIDogdGFyZ2V0Wm9vbTtcclxuXHJcbiAgXHRcdHZhciB3MCA9IE1hdGgubWF4KHNpemUueCwgc2l6ZS55KSxcclxuICBcdFx0ICAgIHcxID0gdzAgKiB0aGlzLmdldFpvb21TY2FsZShzdGFydFpvb20sIHRhcmdldFpvb20pLFxyXG4gIFx0XHQgICAgdTEgPSAodG8uZGlzdGFuY2VUbyhmcm9tKSkgfHwgMSxcclxuICBcdFx0ICAgIHJobyA9IDEuNDIsXHJcbiAgXHRcdCAgICByaG8yID0gcmhvICogcmhvO1xyXG5cclxuICBcdFx0ZnVuY3Rpb24gcihpKSB7XHJcbiAgXHRcdFx0dmFyIHMxID0gaSA/IC0xIDogMSxcclxuICBcdFx0XHQgICAgczIgPSBpID8gdzEgOiB3MCxcclxuICBcdFx0XHQgICAgdDEgPSB3MSAqIHcxIC0gdzAgKiB3MCArIHMxICogcmhvMiAqIHJobzIgKiB1MSAqIHUxLFxyXG4gIFx0XHRcdCAgICBiMSA9IDIgKiBzMiAqIHJobzIgKiB1MSxcclxuICBcdFx0XHQgICAgYiA9IHQxIC8gYjEsXHJcbiAgXHRcdFx0ICAgIHNxID0gTWF0aC5zcXJ0KGIgKiBiICsgMSkgLSBiO1xyXG5cclxuICBcdFx0XHQgICAgLy8gd29ya2Fyb3VuZCBmb3IgZmxvYXRpbmcgcG9pbnQgcHJlY2lzaW9uIGJ1ZyB3aGVuIHNxID0gMCwgbG9nID0gLUluZmluaXRlLFxyXG4gIFx0XHRcdCAgICAvLyB0aHVzIHRyaWdnZXJpbmcgYW4gaW5maW5pdGUgbG9vcCBpbiBmbHlUb1xyXG4gIFx0XHRcdCAgICB2YXIgbG9nID0gc3EgPCAwLjAwMDAwMDAwMSA/IC0xOCA6IE1hdGgubG9nKHNxKTtcclxuXHJcbiAgXHRcdFx0cmV0dXJuIGxvZztcclxuICBcdFx0fVxyXG5cclxuICBcdFx0ZnVuY3Rpb24gc2luaChuKSB7IHJldHVybiAoTWF0aC5leHAobikgLSBNYXRoLmV4cCgtbikpIC8gMjsgfVxyXG4gIFx0XHRmdW5jdGlvbiBjb3NoKG4pIHsgcmV0dXJuIChNYXRoLmV4cChuKSArIE1hdGguZXhwKC1uKSkgLyAyOyB9XHJcbiAgXHRcdGZ1bmN0aW9uIHRhbmgobikgeyByZXR1cm4gc2luaChuKSAvIGNvc2gobik7IH1cclxuXHJcbiAgXHRcdHZhciByMCA9IHIoMCk7XHJcblxyXG4gIFx0XHRmdW5jdGlvbiB3KHMpIHsgcmV0dXJuIHcwICogKGNvc2gocjApIC8gY29zaChyMCArIHJobyAqIHMpKTsgfVxyXG4gIFx0XHRmdW5jdGlvbiB1KHMpIHsgcmV0dXJuIHcwICogKGNvc2gocjApICogdGFuaChyMCArIHJobyAqIHMpIC0gc2luaChyMCkpIC8gcmhvMjsgfVxyXG5cclxuICBcdFx0ZnVuY3Rpb24gZWFzZU91dCh0KSB7IHJldHVybiAxIC0gTWF0aC5wb3coMSAtIHQsIDEuNSk7IH1cclxuXHJcbiAgXHRcdHZhciBzdGFydCA9IERhdGUubm93KCksXHJcbiAgXHRcdCAgICBTID0gKHIoMSkgLSByMCkgLyByaG8sXHJcbiAgXHRcdCAgICBkdXJhdGlvbiA9IG9wdGlvbnMuZHVyYXRpb24gPyAxMDAwICogb3B0aW9ucy5kdXJhdGlvbiA6IDEwMDAgKiBTICogMC44O1xyXG5cclxuICBcdFx0ZnVuY3Rpb24gZnJhbWUoKSB7XHJcbiAgXHRcdFx0dmFyIHQgPSAoRGF0ZS5ub3coKSAtIHN0YXJ0KSAvIGR1cmF0aW9uLFxyXG4gIFx0XHRcdCAgICBzID0gZWFzZU91dCh0KSAqIFM7XHJcblxyXG4gIFx0XHRcdGlmICh0IDw9IDEpIHtcclxuICBcdFx0XHRcdHRoaXMuX2ZseVRvRnJhbWUgPSByZXF1ZXN0QW5pbUZyYW1lKGZyYW1lLCB0aGlzKTtcclxuXHJcbiAgXHRcdFx0XHR0aGlzLl9tb3ZlKFxyXG4gIFx0XHRcdFx0XHR0aGlzLnVucHJvamVjdChmcm9tLmFkZCh0by5zdWJ0cmFjdChmcm9tKS5tdWx0aXBseUJ5KHUocykgLyB1MSkpLCBzdGFydFpvb20pLFxyXG4gIFx0XHRcdFx0XHR0aGlzLmdldFNjYWxlWm9vbSh3MCAvIHcocyksIHN0YXJ0Wm9vbSksXHJcbiAgXHRcdFx0XHRcdHtmbHlUbzogdHJ1ZX0pO1xyXG5cclxuICBcdFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdFx0dGhpc1xyXG4gIFx0XHRcdFx0XHQuX21vdmUodGFyZ2V0Q2VudGVyLCB0YXJnZXRab29tKVxyXG4gIFx0XHRcdFx0XHQuX21vdmVFbmQodHJ1ZSk7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR0aGlzLl9tb3ZlU3RhcnQodHJ1ZSwgb3B0aW9ucy5ub01vdmVTdGFydCk7XHJcblxyXG4gIFx0XHRmcmFtZS5jYWxsKHRoaXMpO1xyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBmbHlUb0JvdW5kcyhib3VuZHM6IExhdExuZ0JvdW5kcywgb3B0aW9ucz86IGZpdEJvdW5kcyBvcHRpb25zKTogdGhpc1xyXG4gIFx0Ly8gU2V0cyB0aGUgdmlldyBvZiB0aGUgbWFwIHdpdGggYSBzbW9vdGggYW5pbWF0aW9uIGxpa2UgW2BmbHlUb2BdKCNtYXAtZmx5dG8pLFxyXG4gIFx0Ly8gYnV0IHRha2VzIGEgYm91bmRzIHBhcmFtZXRlciBsaWtlIFtgZml0Qm91bmRzYF0oI21hcC1maXRib3VuZHMpLlxyXG4gIFx0Zmx5VG9Cb3VuZHM6IGZ1bmN0aW9uIChib3VuZHMsIG9wdGlvbnMpIHtcclxuICBcdFx0dmFyIHRhcmdldCA9IHRoaXMuX2dldEJvdW5kc0NlbnRlclpvb20oYm91bmRzLCBvcHRpb25zKTtcclxuICBcdFx0cmV0dXJuIHRoaXMuZmx5VG8odGFyZ2V0LmNlbnRlciwgdGFyZ2V0Lnpvb20sIG9wdGlvbnMpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNldE1heEJvdW5kcyhib3VuZHM6IExhdExuZ0JvdW5kcyk6IHRoaXNcclxuICBcdC8vIFJlc3RyaWN0cyB0aGUgbWFwIHZpZXcgdG8gdGhlIGdpdmVuIGJvdW5kcyAoc2VlIHRoZSBbbWF4Qm91bmRzXSgjbWFwLW1heGJvdW5kcykgb3B0aW9uKS5cclxuICBcdHNldE1heEJvdW5kczogZnVuY3Rpb24gKGJvdW5kcykge1xyXG4gIFx0XHRib3VuZHMgPSB0b0xhdExuZ0JvdW5kcyhib3VuZHMpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMubGlzdGVucygnbW92ZWVuZCcsIHRoaXMuX3Bhbkluc2lkZU1heEJvdW5kcykpIHtcclxuICBcdFx0XHR0aGlzLm9mZignbW92ZWVuZCcsIHRoaXMuX3Bhbkluc2lkZU1heEJvdW5kcyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmICghYm91bmRzLmlzVmFsaWQoKSkge1xyXG4gIFx0XHRcdHRoaXMub3B0aW9ucy5tYXhCb3VuZHMgPSBudWxsO1xyXG4gIFx0XHRcdHJldHVybiB0aGlzO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR0aGlzLm9wdGlvbnMubWF4Qm91bmRzID0gYm91bmRzO1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX2xvYWRlZCkge1xyXG4gIFx0XHRcdHRoaXMuX3Bhbkluc2lkZU1heEJvdW5kcygpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcy5vbignbW92ZWVuZCcsIHRoaXMuX3Bhbkluc2lkZU1heEJvdW5kcyk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2V0TWluWm9vbSh6b29tOiBOdW1iZXIpOiB0aGlzXHJcbiAgXHQvLyBTZXRzIHRoZSBsb3dlciBsaW1pdCBmb3IgdGhlIGF2YWlsYWJsZSB6b29tIGxldmVscyAoc2VlIHRoZSBbbWluWm9vbV0oI21hcC1taW56b29tKSBvcHRpb24pLlxyXG4gIFx0c2V0TWluWm9vbTogZnVuY3Rpb24gKHpvb20pIHtcclxuICBcdFx0dmFyIG9sZFpvb20gPSB0aGlzLm9wdGlvbnMubWluWm9vbTtcclxuICBcdFx0dGhpcy5vcHRpb25zLm1pblpvb20gPSB6b29tO1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX2xvYWRlZCAmJiBvbGRab29tICE9PSB6b29tKSB7XHJcbiAgXHRcdFx0dGhpcy5maXJlKCd6b29tbGV2ZWxzY2hhbmdlJyk7XHJcblxyXG4gIFx0XHRcdGlmICh0aGlzLmdldFpvb20oKSA8IHRoaXMub3B0aW9ucy5taW5ab29tKSB7XHJcbiAgXHRcdFx0XHRyZXR1cm4gdGhpcy5zZXRab29tKHpvb20pO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG5cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2V0TWF4Wm9vbSh6b29tOiBOdW1iZXIpOiB0aGlzXHJcbiAgXHQvLyBTZXRzIHRoZSB1cHBlciBsaW1pdCBmb3IgdGhlIGF2YWlsYWJsZSB6b29tIGxldmVscyAoc2VlIHRoZSBbbWF4Wm9vbV0oI21hcC1tYXh6b29tKSBvcHRpb24pLlxyXG4gIFx0c2V0TWF4Wm9vbTogZnVuY3Rpb24gKHpvb20pIHtcclxuICBcdFx0dmFyIG9sZFpvb20gPSB0aGlzLm9wdGlvbnMubWF4Wm9vbTtcclxuICBcdFx0dGhpcy5vcHRpb25zLm1heFpvb20gPSB6b29tO1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX2xvYWRlZCAmJiBvbGRab29tICE9PSB6b29tKSB7XHJcbiAgXHRcdFx0dGhpcy5maXJlKCd6b29tbGV2ZWxzY2hhbmdlJyk7XHJcblxyXG4gIFx0XHRcdGlmICh0aGlzLmdldFpvb20oKSA+IHRoaXMub3B0aW9ucy5tYXhab29tKSB7XHJcbiAgXHRcdFx0XHRyZXR1cm4gdGhpcy5zZXRab29tKHpvb20pO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG5cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgcGFuSW5zaWRlQm91bmRzKGJvdW5kczogTGF0TG5nQm91bmRzLCBvcHRpb25zPzogUGFuIG9wdGlvbnMpOiB0aGlzXHJcbiAgXHQvLyBQYW5zIHRoZSBtYXAgdG8gdGhlIGNsb3Nlc3QgdmlldyB0aGF0IHdvdWxkIGxpZSBpbnNpZGUgdGhlIGdpdmVuIGJvdW5kcyAoaWYgaXQncyBub3QgYWxyZWFkeSksIGNvbnRyb2xsaW5nIHRoZSBhbmltYXRpb24gdXNpbmcgdGhlIG9wdGlvbnMgc3BlY2lmaWMsIGlmIGFueS5cclxuICBcdHBhbkluc2lkZUJvdW5kczogZnVuY3Rpb24gKGJvdW5kcywgb3B0aW9ucykge1xyXG4gIFx0XHR0aGlzLl9lbmZvcmNpbmdCb3VuZHMgPSB0cnVlO1xyXG4gIFx0XHR2YXIgY2VudGVyID0gdGhpcy5nZXRDZW50ZXIoKSxcclxuICBcdFx0ICAgIG5ld0NlbnRlciA9IHRoaXMuX2xpbWl0Q2VudGVyKGNlbnRlciwgdGhpcy5fem9vbSwgdG9MYXRMbmdCb3VuZHMoYm91bmRzKSk7XHJcblxyXG4gIFx0XHRpZiAoIWNlbnRlci5lcXVhbHMobmV3Q2VudGVyKSkge1xyXG4gIFx0XHRcdHRoaXMucGFuVG8obmV3Q2VudGVyLCBvcHRpb25zKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5fZW5mb3JjaW5nQm91bmRzID0gZmFsc2U7XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHBhbkluc2lkZShsYXRsbmc6IExhdExuZywgb3B0aW9ucz86IHBhZGRpbmcgb3B0aW9ucyk6IHRoaXNcclxuICBcdC8vIFBhbnMgdGhlIG1hcCB0aGUgbWluaW11bSBhbW91bnQgdG8gbWFrZSB0aGUgYGxhdGxuZ2AgdmlzaWJsZS4gVXNlXHJcbiAgXHQvLyBwYWRkaW5nIG9wdGlvbnMgdG8gZml0IHRoZSBkaXNwbGF5IHRvIG1vcmUgcmVzdHJpY3RlZCBib3VuZHMuXHJcbiAgXHQvLyBJZiBgbGF0bG5nYCBpcyBhbHJlYWR5IHdpdGhpbiB0aGUgKG9wdGlvbmFsbHkgcGFkZGVkKSBkaXNwbGF5IGJvdW5kcyxcclxuICBcdC8vIHRoZSBtYXAgd2lsbCBub3QgYmUgcGFubmVkLlxyXG4gIFx0cGFuSW5zaWRlOiBmdW5jdGlvbiAobGF0bG5nLCBvcHRpb25zKSB7XHJcbiAgXHRcdG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xyXG5cclxuICBcdFx0dmFyIHBhZGRpbmdUTCA9IHRvUG9pbnQob3B0aW9ucy5wYWRkaW5nVG9wTGVmdCB8fCBvcHRpb25zLnBhZGRpbmcgfHwgWzAsIDBdKSxcclxuICBcdFx0ICAgIHBhZGRpbmdCUiA9IHRvUG9pbnQob3B0aW9ucy5wYWRkaW5nQm90dG9tUmlnaHQgfHwgb3B0aW9ucy5wYWRkaW5nIHx8IFswLCAwXSksXHJcbiAgXHRcdCAgICBwaXhlbENlbnRlciA9IHRoaXMucHJvamVjdCh0aGlzLmdldENlbnRlcigpKSxcclxuICBcdFx0ICAgIHBpeGVsUG9pbnQgPSB0aGlzLnByb2plY3QobGF0bG5nKSxcclxuICBcdFx0ICAgIHBpeGVsQm91bmRzID0gdGhpcy5nZXRQaXhlbEJvdW5kcygpLFxyXG4gIFx0XHQgICAgcGFkZGVkQm91bmRzID0gdG9Cb3VuZHMoW3BpeGVsQm91bmRzLm1pbi5hZGQocGFkZGluZ1RMKSwgcGl4ZWxCb3VuZHMubWF4LnN1YnRyYWN0KHBhZGRpbmdCUildKSxcclxuICBcdFx0ICAgIHBhZGRlZFNpemUgPSBwYWRkZWRCb3VuZHMuZ2V0U2l6ZSgpO1xyXG5cclxuICBcdFx0aWYgKCFwYWRkZWRCb3VuZHMuY29udGFpbnMocGl4ZWxQb2ludCkpIHtcclxuICBcdFx0XHR0aGlzLl9lbmZvcmNpbmdCb3VuZHMgPSB0cnVlO1xyXG4gIFx0XHRcdHZhciBjZW50ZXJPZmZzZXQgPSBwaXhlbFBvaW50LnN1YnRyYWN0KHBhZGRlZEJvdW5kcy5nZXRDZW50ZXIoKSk7XHJcbiAgXHRcdFx0dmFyIG9mZnNldCA9IHBhZGRlZEJvdW5kcy5leHRlbmQocGl4ZWxQb2ludCkuZ2V0U2l6ZSgpLnN1YnRyYWN0KHBhZGRlZFNpemUpO1xyXG4gIFx0XHRcdHBpeGVsQ2VudGVyLnggKz0gY2VudGVyT2Zmc2V0LnggPCAwID8gLW9mZnNldC54IDogb2Zmc2V0Lng7XHJcbiAgXHRcdFx0cGl4ZWxDZW50ZXIueSArPSBjZW50ZXJPZmZzZXQueSA8IDAgPyAtb2Zmc2V0LnkgOiBvZmZzZXQueTtcclxuICBcdFx0XHR0aGlzLnBhblRvKHRoaXMudW5wcm9qZWN0KHBpeGVsQ2VudGVyKSwgb3B0aW9ucyk7XHJcbiAgXHRcdFx0dGhpcy5fZW5mb3JjaW5nQm91bmRzID0gZmFsc2U7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgaW52YWxpZGF0ZVNpemUob3B0aW9uczogWm9vbS9wYW4gb3B0aW9ucyk6IHRoaXNcclxuICBcdC8vIENoZWNrcyBpZiB0aGUgbWFwIGNvbnRhaW5lciBzaXplIGNoYW5nZWQgYW5kIHVwZGF0ZXMgdGhlIG1hcCBpZiBzbyDigJRcclxuICBcdC8vIGNhbGwgaXQgYWZ0ZXIgeW91J3ZlIGNoYW5nZWQgdGhlIG1hcCBzaXplIGR5bmFtaWNhbGx5LCBhbHNvIGFuaW1hdGluZ1xyXG4gIFx0Ly8gcGFuIGJ5IGRlZmF1bHQuIElmIGBvcHRpb25zLnBhbmAgaXMgYGZhbHNlYCwgcGFubmluZyB3aWxsIG5vdCBvY2N1ci5cclxuICBcdC8vIElmIGBvcHRpb25zLmRlYm91bmNlTW92ZWVuZGAgaXMgYHRydWVgLCBpdCB3aWxsIGRlbGF5IGBtb3ZlZW5kYCBldmVudCBzb1xyXG4gIFx0Ly8gdGhhdCBpdCBkb2Vzbid0IGhhcHBlbiBvZnRlbiBldmVuIGlmIHRoZSBtZXRob2QgaXMgY2FsbGVkIG1hbnlcclxuICBcdC8vIHRpbWVzIGluIGEgcm93LlxyXG5cclxuICBcdC8vIEBhbHRlcm5hdGl2ZVxyXG4gIFx0Ly8gQG1ldGhvZCBpbnZhbGlkYXRlU2l6ZShhbmltYXRlOiBCb29sZWFuKTogdGhpc1xyXG4gIFx0Ly8gQ2hlY2tzIGlmIHRoZSBtYXAgY29udGFpbmVyIHNpemUgY2hhbmdlZCBhbmQgdXBkYXRlcyB0aGUgbWFwIGlmIHNvIOKAlFxyXG4gIFx0Ly8gY2FsbCBpdCBhZnRlciB5b3UndmUgY2hhbmdlZCB0aGUgbWFwIHNpemUgZHluYW1pY2FsbHksIGFsc28gYW5pbWF0aW5nXHJcbiAgXHQvLyBwYW4gYnkgZGVmYXVsdC5cclxuICBcdGludmFsaWRhdGVTaXplOiBmdW5jdGlvbiAob3B0aW9ucykge1xyXG4gIFx0XHRpZiAoIXRoaXMuX2xvYWRlZCkgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuICBcdFx0b3B0aW9ucyA9IGV4dGVuZCh7XHJcbiAgXHRcdFx0YW5pbWF0ZTogZmFsc2UsXHJcbiAgXHRcdFx0cGFuOiB0cnVlXHJcbiAgXHRcdH0sIG9wdGlvbnMgPT09IHRydWUgPyB7YW5pbWF0ZTogdHJ1ZX0gOiBvcHRpb25zKTtcclxuXHJcbiAgXHRcdHZhciBvbGRTaXplID0gdGhpcy5nZXRTaXplKCk7XHJcbiAgXHRcdHRoaXMuX3NpemVDaGFuZ2VkID0gdHJ1ZTtcclxuICBcdFx0dGhpcy5fbGFzdENlbnRlciA9IG51bGw7XHJcblxyXG4gIFx0XHR2YXIgbmV3U2l6ZSA9IHRoaXMuZ2V0U2l6ZSgpLFxyXG4gIFx0XHQgICAgb2xkQ2VudGVyID0gb2xkU2l6ZS5kaXZpZGVCeSgyKS5yb3VuZCgpLFxyXG4gIFx0XHQgICAgbmV3Q2VudGVyID0gbmV3U2l6ZS5kaXZpZGVCeSgyKS5yb3VuZCgpLFxyXG4gIFx0XHQgICAgb2Zmc2V0ID0gb2xkQ2VudGVyLnN1YnRyYWN0KG5ld0NlbnRlcik7XHJcblxyXG4gIFx0XHRpZiAoIW9mZnNldC54ICYmICFvZmZzZXQueSkgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuICBcdFx0aWYgKG9wdGlvbnMuYW5pbWF0ZSAmJiBvcHRpb25zLnBhbikge1xyXG4gIFx0XHRcdHRoaXMucGFuQnkob2Zmc2V0KTtcclxuXHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0aWYgKG9wdGlvbnMucGFuKSB7XHJcbiAgXHRcdFx0XHR0aGlzLl9yYXdQYW5CeShvZmZzZXQpO1xyXG4gIFx0XHRcdH1cclxuXHJcbiAgXHRcdFx0dGhpcy5maXJlKCdtb3ZlJyk7XHJcblxyXG4gIFx0XHRcdGlmIChvcHRpb25zLmRlYm91bmNlTW92ZWVuZCkge1xyXG4gIFx0XHRcdFx0Y2xlYXJUaW1lb3V0KHRoaXMuX3NpemVUaW1lcik7XHJcbiAgXHRcdFx0XHR0aGlzLl9zaXplVGltZXIgPSBzZXRUaW1lb3V0KGJpbmQodGhpcy5maXJlLCB0aGlzLCAnbW92ZWVuZCcpLCAyMDApO1xyXG4gIFx0XHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0XHR0aGlzLmZpcmUoJ21vdmVlbmQnKTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdC8vIEBzZWN0aW9uIE1hcCBzdGF0ZSBjaGFuZ2UgZXZlbnRzXHJcbiAgXHRcdC8vIEBldmVudCByZXNpemU6IFJlc2l6ZUV2ZW50XHJcbiAgXHRcdC8vIEZpcmVkIHdoZW4gdGhlIG1hcCBpcyByZXNpemVkLlxyXG4gIFx0XHRyZXR1cm4gdGhpcy5maXJlKCdyZXNpemUnLCB7XHJcbiAgXHRcdFx0b2xkU2l6ZTogb2xkU2l6ZSxcclxuICBcdFx0XHRuZXdTaXplOiBuZXdTaXplXHJcbiAgXHRcdH0pO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAc2VjdGlvbiBNZXRob2RzIGZvciBtb2RpZnlpbmcgbWFwIHN0YXRlXHJcbiAgXHQvLyBAbWV0aG9kIHN0b3AoKTogdGhpc1xyXG4gIFx0Ly8gU3RvcHMgdGhlIGN1cnJlbnRseSBydW5uaW5nIGBwYW5Ub2Agb3IgYGZseVRvYCBhbmltYXRpb24sIGlmIGFueS5cclxuICBcdHN0b3A6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dGhpcy5zZXRab29tKHRoaXMuX2xpbWl0Wm9vbSh0aGlzLl96b29tKSk7XHJcbiAgXHRcdGlmICghdGhpcy5vcHRpb25zLnpvb21TbmFwKSB7XHJcbiAgXHRcdFx0dGhpcy5maXJlKCd2aWV3cmVzZXQnKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcy5fc3RvcCgpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAc2VjdGlvbiBHZW9sb2NhdGlvbiBtZXRob2RzXHJcbiAgXHQvLyBAbWV0aG9kIGxvY2F0ZShvcHRpb25zPzogTG9jYXRlIG9wdGlvbnMpOiB0aGlzXHJcbiAgXHQvLyBUcmllcyB0byBsb2NhdGUgdGhlIHVzZXIgdXNpbmcgdGhlIEdlb2xvY2F0aW9uIEFQSSwgZmlyaW5nIGEgW2Bsb2NhdGlvbmZvdW5kYF0oI21hcC1sb2NhdGlvbmZvdW5kKVxyXG4gIFx0Ly8gZXZlbnQgd2l0aCBsb2NhdGlvbiBkYXRhIG9uIHN1Y2Nlc3Mgb3IgYSBbYGxvY2F0aW9uZXJyb3JgXSgjbWFwLWxvY2F0aW9uZXJyb3IpIGV2ZW50IG9uIGZhaWx1cmUsXHJcbiAgXHQvLyBhbmQgb3B0aW9uYWxseSBzZXRzIHRoZSBtYXAgdmlldyB0byB0aGUgdXNlcidzIGxvY2F0aW9uIHdpdGggcmVzcGVjdCB0b1xyXG4gIFx0Ly8gZGV0ZWN0aW9uIGFjY3VyYWN5IChvciB0byB0aGUgd29ybGQgdmlldyBpZiBnZW9sb2NhdGlvbiBmYWlsZWQpLlxyXG4gIFx0Ly8gTm90ZSB0aGF0LCBpZiB5b3VyIHBhZ2UgZG9lc24ndCB1c2UgSFRUUFMsIHRoaXMgbWV0aG9kIHdpbGwgZmFpbCBpblxyXG4gIFx0Ly8gbW9kZXJuIGJyb3dzZXJzIChbQ2hyb21lIDUwIGFuZCBuZXdlcl0oaHR0cHM6Ly9zaXRlcy5nb29nbGUuY29tL2EvY2hyb21pdW0ub3JnL2Rldi9Ib21lL2Nocm9taXVtLXNlY3VyaXR5L2RlcHJlY2F0aW5nLXBvd2VyZnVsLWZlYXR1cmVzLW9uLWluc2VjdXJlLW9yaWdpbnMpKVxyXG4gIFx0Ly8gU2VlIGBMb2NhdGUgb3B0aW9uc2AgZm9yIG1vcmUgZGV0YWlscy5cclxuICBcdGxvY2F0ZTogZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuXHJcbiAgXHRcdG9wdGlvbnMgPSB0aGlzLl9sb2NhdGVPcHRpb25zID0gZXh0ZW5kKHtcclxuICBcdFx0XHR0aW1lb3V0OiAxMDAwMCxcclxuICBcdFx0XHR3YXRjaDogZmFsc2VcclxuICBcdFx0XHQvLyBzZXRWaWV3OiBmYWxzZVxyXG4gIFx0XHRcdC8vIG1heFpvb206IDxOdW1iZXI+XHJcbiAgXHRcdFx0Ly8gbWF4aW11bUFnZTogMFxyXG4gIFx0XHRcdC8vIGVuYWJsZUhpZ2hBY2N1cmFjeTogZmFsc2VcclxuICBcdFx0fSwgb3B0aW9ucyk7XHJcblxyXG4gIFx0XHRpZiAoISgnZ2VvbG9jYXRpb24nIGluIG5hdmlnYXRvcikpIHtcclxuICBcdFx0XHR0aGlzLl9oYW5kbGVHZW9sb2NhdGlvbkVycm9yKHtcclxuICBcdFx0XHRcdGNvZGU6IDAsXHJcbiAgXHRcdFx0XHRtZXNzYWdlOiAnR2VvbG9jYXRpb24gbm90IHN1cHBvcnRlZC4nXHJcbiAgXHRcdFx0fSk7XHJcbiAgXHRcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHZhciBvblJlc3BvbnNlID0gYmluZCh0aGlzLl9oYW5kbGVHZW9sb2NhdGlvblJlc3BvbnNlLCB0aGlzKSxcclxuICBcdFx0ICAgIG9uRXJyb3IgPSBiaW5kKHRoaXMuX2hhbmRsZUdlb2xvY2F0aW9uRXJyb3IsIHRoaXMpO1xyXG5cclxuICBcdFx0aWYgKG9wdGlvbnMud2F0Y2gpIHtcclxuICBcdFx0XHR0aGlzLl9sb2NhdGlvbldhdGNoSWQgPVxyXG4gIFx0XHRcdCAgICAgICAgbmF2aWdhdG9yLmdlb2xvY2F0aW9uLndhdGNoUG9zaXRpb24ob25SZXNwb25zZSwgb25FcnJvciwgb3B0aW9ucyk7XHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0bmF2aWdhdG9yLmdlb2xvY2F0aW9uLmdldEN1cnJlbnRQb3NpdGlvbihvblJlc3BvbnNlLCBvbkVycm9yLCBvcHRpb25zKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBzdG9wTG9jYXRlKCk6IHRoaXNcclxuICBcdC8vIFN0b3BzIHdhdGNoaW5nIGxvY2F0aW9uIHByZXZpb3VzbHkgaW5pdGlhdGVkIGJ5IGBtYXAubG9jYXRlKHt3YXRjaDogdHJ1ZX0pYFxyXG4gIFx0Ly8gYW5kIGFib3J0cyByZXNldHRpbmcgdGhlIG1hcCB2aWV3IGlmIG1hcC5sb2NhdGUgd2FzIGNhbGxlZCB3aXRoXHJcbiAgXHQvLyBge3NldFZpZXc6IHRydWV9YC5cclxuICBcdHN0b3BMb2NhdGU6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKG5hdmlnYXRvci5nZW9sb2NhdGlvbiAmJiBuYXZpZ2F0b3IuZ2VvbG9jYXRpb24uY2xlYXJXYXRjaCkge1xyXG4gIFx0XHRcdG5hdmlnYXRvci5nZW9sb2NhdGlvbi5jbGVhcldhdGNoKHRoaXMuX2xvY2F0aW9uV2F0Y2hJZCk7XHJcbiAgXHRcdH1cclxuICBcdFx0aWYgKHRoaXMuX2xvY2F0ZU9wdGlvbnMpIHtcclxuICBcdFx0XHR0aGlzLl9sb2NhdGVPcHRpb25zLnNldFZpZXcgPSBmYWxzZTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0X2hhbmRsZUdlb2xvY2F0aW9uRXJyb3I6IGZ1bmN0aW9uIChlcnJvcikge1xyXG4gIFx0XHRpZiAoIXRoaXMuX2NvbnRhaW5lci5fbGVhZmxldF9pZCkgeyByZXR1cm47IH1cclxuXHJcbiAgXHRcdHZhciBjID0gZXJyb3IuY29kZSxcclxuICBcdFx0ICAgIG1lc3NhZ2UgPSBlcnJvci5tZXNzYWdlIHx8XHJcbiAgXHRcdCAgICAgICAgICAgIChjID09PSAxID8gJ3Blcm1pc3Npb24gZGVuaWVkJyA6XHJcbiAgXHRcdCAgICAgICAgICAgIChjID09PSAyID8gJ3Bvc2l0aW9uIHVuYXZhaWxhYmxlJyA6ICd0aW1lb3V0JykpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX2xvY2F0ZU9wdGlvbnMuc2V0VmlldyAmJiAhdGhpcy5fbG9hZGVkKSB7XHJcbiAgXHRcdFx0dGhpcy5maXRXb3JsZCgpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHQvLyBAc2VjdGlvbiBMb2NhdGlvbiBldmVudHNcclxuICBcdFx0Ly8gQGV2ZW50IGxvY2F0aW9uZXJyb3I6IEVycm9yRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiBnZW9sb2NhdGlvbiAodXNpbmcgdGhlIFtgbG9jYXRlYF0oI21hcC1sb2NhdGUpIG1ldGhvZCkgZmFpbGVkLlxyXG4gIFx0XHR0aGlzLmZpcmUoJ2xvY2F0aW9uZXJyb3InLCB7XHJcbiAgXHRcdFx0Y29kZTogYyxcclxuICBcdFx0XHRtZXNzYWdlOiAnR2VvbG9jYXRpb24gZXJyb3I6ICcgKyBtZXNzYWdlICsgJy4nXHJcbiAgXHRcdH0pO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfaGFuZGxlR2VvbG9jYXRpb25SZXNwb25zZTogZnVuY3Rpb24gKHBvcykge1xyXG4gIFx0XHRpZiAoIXRoaXMuX2NvbnRhaW5lci5fbGVhZmxldF9pZCkgeyByZXR1cm47IH1cclxuXHJcbiAgXHRcdHZhciBsYXQgPSBwb3MuY29vcmRzLmxhdGl0dWRlLFxyXG4gIFx0XHQgICAgbG5nID0gcG9zLmNvb3Jkcy5sb25naXR1ZGUsXHJcbiAgXHRcdCAgICBsYXRsbmcgPSBuZXcgTGF0TG5nKGxhdCwgbG5nKSxcclxuICBcdFx0ICAgIGJvdW5kcyA9IGxhdGxuZy50b0JvdW5kcyhwb3MuY29vcmRzLmFjY3VyYWN5ICogMiksXHJcbiAgXHRcdCAgICBvcHRpb25zID0gdGhpcy5fbG9jYXRlT3B0aW9ucztcclxuXHJcbiAgXHRcdGlmIChvcHRpb25zLnNldFZpZXcpIHtcclxuICBcdFx0XHR2YXIgem9vbSA9IHRoaXMuZ2V0Qm91bmRzWm9vbShib3VuZHMpO1xyXG4gIFx0XHRcdHRoaXMuc2V0VmlldyhsYXRsbmcsIG9wdGlvbnMubWF4Wm9vbSA/IE1hdGgubWluKHpvb20sIG9wdGlvbnMubWF4Wm9vbSkgOiB6b29tKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dmFyIGRhdGEgPSB7XHJcbiAgXHRcdFx0bGF0bG5nOiBsYXRsbmcsXHJcbiAgXHRcdFx0Ym91bmRzOiBib3VuZHMsXHJcbiAgXHRcdFx0dGltZXN0YW1wOiBwb3MudGltZXN0YW1wXHJcbiAgXHRcdH07XHJcblxyXG4gIFx0XHRmb3IgKHZhciBpIGluIHBvcy5jb29yZHMpIHtcclxuICBcdFx0XHRpZiAodHlwZW9mIHBvcy5jb29yZHNbaV0gPT09ICdudW1iZXInKSB7XHJcbiAgXHRcdFx0XHRkYXRhW2ldID0gcG9zLmNvb3Jkc1tpXTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdC8vIEBldmVudCBsb2NhdGlvbmZvdW5kOiBMb2NhdGlvbkV2ZW50XHJcbiAgXHRcdC8vIEZpcmVkIHdoZW4gZ2VvbG9jYXRpb24gKHVzaW5nIHRoZSBbYGxvY2F0ZWBdKCNtYXAtbG9jYXRlKSBtZXRob2QpXHJcbiAgXHRcdC8vIHdlbnQgc3VjY2Vzc2Z1bGx5LlxyXG4gIFx0XHR0aGlzLmZpcmUoJ2xvY2F0aW9uZm91bmQnLCBkYXRhKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gVE9ETyBBcHByb3ByaWF0ZSBkb2NzIHNlY3Rpb24/XHJcbiAgXHQvLyBAc2VjdGlvbiBPdGhlciBNZXRob2RzXHJcbiAgXHQvLyBAbWV0aG9kIGFkZEhhbmRsZXIobmFtZTogU3RyaW5nLCBIYW5kbGVyQ2xhc3M6IEZ1bmN0aW9uKTogdGhpc1xyXG4gIFx0Ly8gQWRkcyBhIG5ldyBgSGFuZGxlcmAgdG8gdGhlIG1hcCwgZ2l2ZW4gaXRzIG5hbWUgYW5kIGNvbnN0cnVjdG9yIGZ1bmN0aW9uLlxyXG4gIFx0YWRkSGFuZGxlcjogZnVuY3Rpb24gKG5hbWUsIEhhbmRsZXJDbGFzcykge1xyXG4gIFx0XHRpZiAoIUhhbmRsZXJDbGFzcykgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuICBcdFx0dmFyIGhhbmRsZXIgPSB0aGlzW25hbWVdID0gbmV3IEhhbmRsZXJDbGFzcyh0aGlzKTtcclxuXHJcbiAgXHRcdHRoaXMuX2hhbmRsZXJzLnB1c2goaGFuZGxlcik7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5vcHRpb25zW25hbWVdKSB7XHJcbiAgXHRcdFx0aGFuZGxlci5lbmFibGUoKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgcmVtb3ZlKCk6IHRoaXNcclxuICBcdC8vIERlc3Ryb3lzIHRoZSBtYXAgYW5kIGNsZWFycyBhbGwgcmVsYXRlZCBldmVudCBsaXN0ZW5lcnMuXHJcbiAgXHRyZW1vdmU6IGZ1bmN0aW9uICgpIHtcclxuXHJcbiAgXHRcdHRoaXMuX2luaXRFdmVudHModHJ1ZSk7XHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMubWF4Qm91bmRzKSB7IHRoaXMub2ZmKCdtb3ZlZW5kJywgdGhpcy5fcGFuSW5zaWRlTWF4Qm91bmRzKTsgfVxyXG5cclxuICBcdFx0aWYgKHRoaXMuX2NvbnRhaW5lcklkICE9PSB0aGlzLl9jb250YWluZXIuX2xlYWZsZXRfaWQpIHtcclxuICBcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ01hcCBjb250YWluZXIgaXMgYmVpbmcgcmV1c2VkIGJ5IGFub3RoZXIgaW5zdGFuY2UnKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dHJ5IHtcclxuICBcdFx0XHQvLyB0aHJvd3MgZXJyb3IgaW4gSUU2LThcclxuICBcdFx0XHRkZWxldGUgdGhpcy5fY29udGFpbmVyLl9sZWFmbGV0X2lkO1xyXG4gIFx0XHRcdGRlbGV0ZSB0aGlzLl9jb250YWluZXJJZDtcclxuICBcdFx0fSBjYXRjaCAoZSkge1xyXG4gIFx0XHRcdC8qZXNsaW50LWRpc2FibGUgKi9cclxuICBcdFx0XHR0aGlzLl9jb250YWluZXIuX2xlYWZsZXRfaWQgPSB1bmRlZmluZWQ7XHJcbiAgXHRcdFx0LyogZXNsaW50LWVuYWJsZSAqL1xyXG4gIFx0XHRcdHRoaXMuX2NvbnRhaW5lcklkID0gdW5kZWZpbmVkO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fbG9jYXRpb25XYXRjaElkICE9PSB1bmRlZmluZWQpIHtcclxuICBcdFx0XHR0aGlzLnN0b3BMb2NhdGUoKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5fc3RvcCgpO1xyXG5cclxuICBcdFx0cmVtb3ZlKHRoaXMuX21hcFBhbmUpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX2NsZWFyQ29udHJvbFBvcykge1xyXG4gIFx0XHRcdHRoaXMuX2NsZWFyQ29udHJvbFBvcygpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdGlmICh0aGlzLl9yZXNpemVSZXF1ZXN0KSB7XHJcbiAgXHRcdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX3Jlc2l6ZVJlcXVlc3QpO1xyXG4gIFx0XHRcdHRoaXMuX3Jlc2l6ZVJlcXVlc3QgPSBudWxsO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR0aGlzLl9jbGVhckhhbmRsZXJzKCk7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fbG9hZGVkKSB7XHJcbiAgXHRcdFx0Ly8gQHNlY3Rpb24gTWFwIHN0YXRlIGNoYW5nZSBldmVudHNcclxuICBcdFx0XHQvLyBAZXZlbnQgdW5sb2FkOiBFdmVudFxyXG4gIFx0XHRcdC8vIEZpcmVkIHdoZW4gdGhlIG1hcCBpcyBkZXN0cm95ZWQgd2l0aCBbcmVtb3ZlXSgjbWFwLXJlbW92ZSkgbWV0aG9kLlxyXG4gIFx0XHRcdHRoaXMuZmlyZSgndW5sb2FkJyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHZhciBpO1xyXG4gIFx0XHRmb3IgKGkgaW4gdGhpcy5fbGF5ZXJzKSB7XHJcbiAgXHRcdFx0dGhpcy5fbGF5ZXJzW2ldLnJlbW92ZSgpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdGZvciAoaSBpbiB0aGlzLl9wYW5lcykge1xyXG4gIFx0XHRcdHJlbW92ZSh0aGlzLl9wYW5lc1tpXSk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX2xheWVycyA9IFtdO1xyXG4gIFx0XHR0aGlzLl9wYW5lcyA9IFtdO1xyXG4gIFx0XHRkZWxldGUgdGhpcy5fbWFwUGFuZTtcclxuICBcdFx0ZGVsZXRlIHRoaXMuX3JlbmRlcmVyO1xyXG5cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBzZWN0aW9uIE90aGVyIE1ldGhvZHNcclxuICBcdC8vIEBtZXRob2QgY3JlYXRlUGFuZShuYW1lOiBTdHJpbmcsIGNvbnRhaW5lcj86IEhUTUxFbGVtZW50KTogSFRNTEVsZW1lbnRcclxuICBcdC8vIENyZWF0ZXMgYSBuZXcgW21hcCBwYW5lXSgjbWFwLXBhbmUpIHdpdGggdGhlIGdpdmVuIG5hbWUgaWYgaXQgZG9lc24ndCBleGlzdCBhbHJlYWR5LFxyXG4gIFx0Ly8gdGhlbiByZXR1cm5zIGl0LiBUaGUgcGFuZSBpcyBjcmVhdGVkIGFzIGEgY2hpbGQgb2YgYGNvbnRhaW5lcmAsIG9yXHJcbiAgXHQvLyBhcyBhIGNoaWxkIG9mIHRoZSBtYWluIG1hcCBwYW5lIGlmIG5vdCBzZXQuXHJcbiAgXHRjcmVhdGVQYW5lOiBmdW5jdGlvbiAobmFtZSwgY29udGFpbmVyKSB7XHJcbiAgXHRcdHZhciBjbGFzc05hbWUgPSAnbGVhZmxldC1wYW5lJyArIChuYW1lID8gJyBsZWFmbGV0LScgKyBuYW1lLnJlcGxhY2UoJ1BhbmUnLCAnJykgKyAnLXBhbmUnIDogJycpLFxyXG4gIFx0XHQgICAgcGFuZSA9IGNyZWF0ZSQxKCdkaXYnLCBjbGFzc05hbWUsIGNvbnRhaW5lciB8fCB0aGlzLl9tYXBQYW5lKTtcclxuXHJcbiAgXHRcdGlmIChuYW1lKSB7XHJcbiAgXHRcdFx0dGhpcy5fcGFuZXNbbmFtZV0gPSBwYW5lO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiBwYW5lO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAc2VjdGlvbiBNZXRob2RzIGZvciBHZXR0aW5nIE1hcCBTdGF0ZVxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0Q2VudGVyKCk6IExhdExuZ1xyXG4gIFx0Ly8gUmV0dXJucyB0aGUgZ2VvZ3JhcGhpY2FsIGNlbnRlciBvZiB0aGUgbWFwIHZpZXdcclxuICBcdGdldENlbnRlcjogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR0aGlzLl9jaGVja0lmTG9hZGVkKCk7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fbGFzdENlbnRlciAmJiAhdGhpcy5fbW92ZWQoKSkge1xyXG4gIFx0XHRcdHJldHVybiB0aGlzLl9sYXN0Q2VudGVyLmNsb25lKCk7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXMubGF5ZXJQb2ludFRvTGF0TG5nKHRoaXMuX2dldENlbnRlckxheWVyUG9pbnQoKSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0Wm9vbSgpOiBOdW1iZXJcclxuICBcdC8vIFJldHVybnMgdGhlIGN1cnJlbnQgem9vbSBsZXZlbCBvZiB0aGUgbWFwIHZpZXdcclxuICBcdGdldFpvb206IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuX3pvb207XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0Qm91bmRzKCk6IExhdExuZ0JvdW5kc1xyXG4gIFx0Ly8gUmV0dXJucyB0aGUgZ2VvZ3JhcGhpY2FsIGJvdW5kcyB2aXNpYmxlIGluIHRoZSBjdXJyZW50IG1hcCB2aWV3XHJcbiAgXHRnZXRCb3VuZHM6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dmFyIGJvdW5kcyA9IHRoaXMuZ2V0UGl4ZWxCb3VuZHMoKSxcclxuICBcdFx0ICAgIHN3ID0gdGhpcy51bnByb2plY3QoYm91bmRzLmdldEJvdHRvbUxlZnQoKSksXHJcbiAgXHRcdCAgICBuZSA9IHRoaXMudW5wcm9qZWN0KGJvdW5kcy5nZXRUb3BSaWdodCgpKTtcclxuXHJcbiAgXHRcdHJldHVybiBuZXcgTGF0TG5nQm91bmRzKHN3LCBuZSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0TWluWm9vbSgpOiBOdW1iZXJcclxuICBcdC8vIFJldHVybnMgdGhlIG1pbmltdW0gem9vbSBsZXZlbCBvZiB0aGUgbWFwIChpZiBzZXQgaW4gdGhlIGBtaW5ab29tYCBvcHRpb24gb2YgdGhlIG1hcCBvciBvZiBhbnkgbGF5ZXJzKSwgb3IgYDBgIGJ5IGRlZmF1bHQuXHJcbiAgXHRnZXRNaW5ab29tOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLm9wdGlvbnMubWluWm9vbSA9PT0gdW5kZWZpbmVkID8gdGhpcy5fbGF5ZXJzTWluWm9vbSB8fCAwIDogdGhpcy5vcHRpb25zLm1pblpvb207XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0TWF4Wm9vbSgpOiBOdW1iZXJcclxuICBcdC8vIFJldHVybnMgdGhlIG1heGltdW0gem9vbSBsZXZlbCBvZiB0aGUgbWFwIChpZiBzZXQgaW4gdGhlIGBtYXhab29tYCBvcHRpb24gb2YgdGhlIG1hcCBvciBvZiBhbnkgbGF5ZXJzKS5cclxuICBcdGdldE1heFpvb206IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMub3B0aW9ucy5tYXhab29tID09PSB1bmRlZmluZWQgP1xyXG4gIFx0XHRcdCh0aGlzLl9sYXllcnNNYXhab29tID09PSB1bmRlZmluZWQgPyBJbmZpbml0eSA6IHRoaXMuX2xheWVyc01heFpvb20pIDpcclxuICBcdFx0XHR0aGlzLm9wdGlvbnMubWF4Wm9vbTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRCb3VuZHNab29tKGJvdW5kczogTGF0TG5nQm91bmRzLCBpbnNpZGU/OiBCb29sZWFuLCBwYWRkaW5nPzogUG9pbnQpOiBOdW1iZXJcclxuICBcdC8vIFJldHVybnMgdGhlIG1heGltdW0gem9vbSBsZXZlbCBvbiB3aGljaCB0aGUgZ2l2ZW4gYm91bmRzIGZpdCB0byB0aGUgbWFwXHJcbiAgXHQvLyB2aWV3IGluIGl0cyBlbnRpcmV0eS4gSWYgYGluc2lkZWAgKG9wdGlvbmFsKSBpcyBzZXQgdG8gYHRydWVgLCB0aGUgbWV0aG9kXHJcbiAgXHQvLyBpbnN0ZWFkIHJldHVybnMgdGhlIG1pbmltdW0gem9vbSBsZXZlbCBvbiB3aGljaCB0aGUgbWFwIHZpZXcgZml0cyBpbnRvXHJcbiAgXHQvLyB0aGUgZ2l2ZW4gYm91bmRzIGluIGl0cyBlbnRpcmV0eS5cclxuICBcdGdldEJvdW5kc1pvb206IGZ1bmN0aW9uIChib3VuZHMsIGluc2lkZSwgcGFkZGluZykgeyAvLyAoTGF0TG5nQm91bmRzWywgQm9vbGVhbiwgUG9pbnRdKSAtPiBOdW1iZXJcclxuICBcdFx0Ym91bmRzID0gdG9MYXRMbmdCb3VuZHMoYm91bmRzKTtcclxuICBcdFx0cGFkZGluZyA9IHRvUG9pbnQocGFkZGluZyB8fCBbMCwgMF0pO1xyXG5cclxuICBcdFx0dmFyIHpvb20gPSB0aGlzLmdldFpvb20oKSB8fCAwLFxyXG4gIFx0XHQgICAgbWluID0gdGhpcy5nZXRNaW5ab29tKCksXHJcbiAgXHRcdCAgICBtYXggPSB0aGlzLmdldE1heFpvb20oKSxcclxuICBcdFx0ICAgIG53ID0gYm91bmRzLmdldE5vcnRoV2VzdCgpLFxyXG4gIFx0XHQgICAgc2UgPSBib3VuZHMuZ2V0U291dGhFYXN0KCksXHJcbiAgXHRcdCAgICBzaXplID0gdGhpcy5nZXRTaXplKCkuc3VidHJhY3QocGFkZGluZyksXHJcbiAgXHRcdCAgICBib3VuZHNTaXplID0gdG9Cb3VuZHModGhpcy5wcm9qZWN0KHNlLCB6b29tKSwgdGhpcy5wcm9qZWN0KG53LCB6b29tKSkuZ2V0U2l6ZSgpLFxyXG4gIFx0XHQgICAgc25hcCA9IEJyb3dzZXIuYW55M2QgPyB0aGlzLm9wdGlvbnMuem9vbVNuYXAgOiAxLFxyXG4gIFx0XHQgICAgc2NhbGV4ID0gc2l6ZS54IC8gYm91bmRzU2l6ZS54LFxyXG4gIFx0XHQgICAgc2NhbGV5ID0gc2l6ZS55IC8gYm91bmRzU2l6ZS55LFxyXG4gIFx0XHQgICAgc2NhbGUgPSBpbnNpZGUgPyBNYXRoLm1heChzY2FsZXgsIHNjYWxleSkgOiBNYXRoLm1pbihzY2FsZXgsIHNjYWxleSk7XHJcblxyXG4gIFx0XHR6b29tID0gdGhpcy5nZXRTY2FsZVpvb20oc2NhbGUsIHpvb20pO1xyXG5cclxuICBcdFx0aWYgKHNuYXApIHtcclxuICBcdFx0XHR6b29tID0gTWF0aC5yb3VuZCh6b29tIC8gKHNuYXAgLyAxMDApKSAqIChzbmFwIC8gMTAwKTsgLy8gZG9uJ3QganVtcCBpZiB3aXRoaW4gMSUgb2YgYSBzbmFwIGxldmVsXHJcbiAgXHRcdFx0em9vbSA9IGluc2lkZSA/IE1hdGguY2VpbCh6b29tIC8gc25hcCkgKiBzbmFwIDogTWF0aC5mbG9vcih6b29tIC8gc25hcCkgKiBzbmFwO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gTWF0aC5tYXgobWluLCBNYXRoLm1pbihtYXgsIHpvb20pKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRTaXplKCk6IFBvaW50XHJcbiAgXHQvLyBSZXR1cm5zIHRoZSBjdXJyZW50IHNpemUgb2YgdGhlIG1hcCBjb250YWluZXIgKGluIHBpeGVscykuXHJcbiAgXHRnZXRTaXplOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICghdGhpcy5fc2l6ZSB8fCB0aGlzLl9zaXplQ2hhbmdlZCkge1xyXG4gIFx0XHRcdHRoaXMuX3NpemUgPSBuZXcgUG9pbnQoXHJcbiAgXHRcdFx0XHR0aGlzLl9jb250YWluZXIuY2xpZW50V2lkdGggfHwgMCxcclxuICBcdFx0XHRcdHRoaXMuX2NvbnRhaW5lci5jbGllbnRIZWlnaHQgfHwgMCk7XHJcblxyXG4gIFx0XHRcdHRoaXMuX3NpemVDaGFuZ2VkID0gZmFsc2U7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXMuX3NpemUuY2xvbmUoKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRQaXhlbEJvdW5kcygpOiBCb3VuZHNcclxuICBcdC8vIFJldHVybnMgdGhlIGJvdW5kcyBvZiB0aGUgY3VycmVudCBtYXAgdmlldyBpbiBwcm9qZWN0ZWQgcGl4ZWxcclxuICBcdC8vIGNvb3JkaW5hdGVzIChzb21ldGltZXMgdXNlZnVsIGluIGxheWVyIGFuZCBvdmVybGF5IGltcGxlbWVudGF0aW9ucykuXHJcbiAgXHRnZXRQaXhlbEJvdW5kczogZnVuY3Rpb24gKGNlbnRlciwgem9vbSkge1xyXG4gIFx0XHR2YXIgdG9wTGVmdFBvaW50ID0gdGhpcy5fZ2V0VG9wTGVmdFBvaW50KGNlbnRlciwgem9vbSk7XHJcbiAgXHRcdHJldHVybiBuZXcgQm91bmRzKHRvcExlZnRQb2ludCwgdG9wTGVmdFBvaW50LmFkZCh0aGlzLmdldFNpemUoKSkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBUT0RPOiBDaGVjayBzZW1hbnRpY3MgLSBpc24ndCB0aGUgcGl4ZWwgb3JpZ2luIHRoZSAwLDAgY29vcmQgcmVsYXRpdmUgdG9cclxuICBcdC8vIHRoZSBtYXAgcGFuZT8gXCJsZWZ0IHBvaW50IG9mIHRoZSBtYXAgbGF5ZXJcIiBjYW4gYmUgY29uZnVzaW5nLCBzcGVjaWFsbHlcclxuICBcdC8vIHNpbmNlIHRoZXJlIGNhbiBiZSBuZWdhdGl2ZSBvZmZzZXRzLlxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRQaXhlbE9yaWdpbigpOiBQb2ludFxyXG4gIFx0Ly8gUmV0dXJucyB0aGUgcHJvamVjdGVkIHBpeGVsIGNvb3JkaW5hdGVzIG9mIHRoZSB0b3AgbGVmdCBwb2ludCBvZlxyXG4gIFx0Ly8gdGhlIG1hcCBsYXllciAodXNlZnVsIGluIGN1c3RvbSBsYXllciBhbmQgb3ZlcmxheSBpbXBsZW1lbnRhdGlvbnMpLlxyXG4gIFx0Z2V0UGl4ZWxPcmlnaW46IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dGhpcy5fY2hlY2tJZkxvYWRlZCgpO1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5fcGl4ZWxPcmlnaW47XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0UGl4ZWxXb3JsZEJvdW5kcyh6b29tPzogTnVtYmVyKTogQm91bmRzXHJcbiAgXHQvLyBSZXR1cm5zIHRoZSB3b3JsZCdzIGJvdW5kcyBpbiBwaXhlbCBjb29yZGluYXRlcyBmb3Igem9vbSBsZXZlbCBgem9vbWAuXHJcbiAgXHQvLyBJZiBgem9vbWAgaXMgb21pdHRlZCwgdGhlIG1hcCdzIGN1cnJlbnQgem9vbSBsZXZlbCBpcyB1c2VkLlxyXG4gIFx0Z2V0UGl4ZWxXb3JsZEJvdW5kczogZnVuY3Rpb24gKHpvb20pIHtcclxuICBcdFx0cmV0dXJuIHRoaXMub3B0aW9ucy5jcnMuZ2V0UHJvamVjdGVkQm91bmRzKHpvb20gPT09IHVuZGVmaW5lZCA/IHRoaXMuZ2V0Wm9vbSgpIDogem9vbSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBzZWN0aW9uIE90aGVyIE1ldGhvZHNcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldFBhbmUocGFuZTogU3RyaW5nfEhUTUxFbGVtZW50KTogSFRNTEVsZW1lbnRcclxuICBcdC8vIFJldHVybnMgYSBbbWFwIHBhbmVdKCNtYXAtcGFuZSksIGdpdmVuIGl0cyBuYW1lIG9yIGl0cyBIVE1MIGVsZW1lbnQgKGl0cyBpZGVudGl0eSkuXHJcbiAgXHRnZXRQYW5lOiBmdW5jdGlvbiAocGFuZSkge1xyXG4gIFx0XHRyZXR1cm4gdHlwZW9mIHBhbmUgPT09ICdzdHJpbmcnID8gdGhpcy5fcGFuZXNbcGFuZV0gOiBwYW5lO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldFBhbmVzKCk6IE9iamVjdFxyXG4gIFx0Ly8gUmV0dXJucyBhIHBsYWluIG9iamVjdCBjb250YWluaW5nIHRoZSBuYW1lcyBvZiBhbGwgW3BhbmVzXSgjbWFwLXBhbmUpIGFzIGtleXMgYW5kXHJcbiAgXHQvLyB0aGUgcGFuZXMgYXMgdmFsdWVzLlxyXG4gIFx0Z2V0UGFuZXM6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuX3BhbmVzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldENvbnRhaW5lcjogSFRNTEVsZW1lbnRcclxuICBcdC8vIFJldHVybnMgdGhlIEhUTUwgZWxlbWVudCB0aGF0IGNvbnRhaW5zIHRoZSBtYXAuXHJcbiAgXHRnZXRDb250YWluZXI6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuX2NvbnRhaW5lcjtcclxuICBcdH0sXHJcblxyXG5cclxuICBcdC8vIEBzZWN0aW9uIENvbnZlcnNpb24gTWV0aG9kc1xyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0Wm9vbVNjYWxlKHRvWm9vbTogTnVtYmVyLCBmcm9tWm9vbTogTnVtYmVyKTogTnVtYmVyXHJcbiAgXHQvLyBSZXR1cm5zIHRoZSBzY2FsZSBmYWN0b3IgdG8gYmUgYXBwbGllZCB0byBhIG1hcCB0cmFuc2l0aW9uIGZyb20gem9vbSBsZXZlbFxyXG4gIFx0Ly8gYGZyb21ab29tYCB0byBgdG9ab29tYC4gVXNlZCBpbnRlcm5hbGx5IHRvIGhlbHAgd2l0aCB6b29tIGFuaW1hdGlvbnMuXHJcbiAgXHRnZXRab29tU2NhbGU6IGZ1bmN0aW9uICh0b1pvb20sIGZyb21ab29tKSB7XHJcbiAgXHRcdC8vIFRPRE8gcmVwbGFjZSB3aXRoIHVuaXZlcnNhbCBpbXBsZW1lbnRhdGlvbiBhZnRlciByZWZhY3RvcmluZyBwcm9qZWN0aW9uc1xyXG4gIFx0XHR2YXIgY3JzID0gdGhpcy5vcHRpb25zLmNycztcclxuICBcdFx0ZnJvbVpvb20gPSBmcm9tWm9vbSA9PT0gdW5kZWZpbmVkID8gdGhpcy5fem9vbSA6IGZyb21ab29tO1xyXG4gIFx0XHRyZXR1cm4gY3JzLnNjYWxlKHRvWm9vbSkgLyBjcnMuc2NhbGUoZnJvbVpvb20pO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldFNjYWxlWm9vbShzY2FsZTogTnVtYmVyLCBmcm9tWm9vbTogTnVtYmVyKTogTnVtYmVyXHJcbiAgXHQvLyBSZXR1cm5zIHRoZSB6b29tIGxldmVsIHRoYXQgdGhlIG1hcCB3b3VsZCBlbmQgdXAgYXQsIGlmIGl0IGlzIGF0IGBmcm9tWm9vbWBcclxuICBcdC8vIGxldmVsIGFuZCBldmVyeXRoaW5nIGlzIHNjYWxlZCBieSBhIGZhY3RvciBvZiBgc2NhbGVgLiBJbnZlcnNlIG9mXHJcbiAgXHQvLyBbYGdldFpvb21TY2FsZWBdKCNtYXAtZ2V0Wm9vbVNjYWxlKS5cclxuICBcdGdldFNjYWxlWm9vbTogZnVuY3Rpb24gKHNjYWxlLCBmcm9tWm9vbSkge1xyXG4gIFx0XHR2YXIgY3JzID0gdGhpcy5vcHRpb25zLmNycztcclxuICBcdFx0ZnJvbVpvb20gPSBmcm9tWm9vbSA9PT0gdW5kZWZpbmVkID8gdGhpcy5fem9vbSA6IGZyb21ab29tO1xyXG4gIFx0XHR2YXIgem9vbSA9IGNycy56b29tKHNjYWxlICogY3JzLnNjYWxlKGZyb21ab29tKSk7XHJcbiAgXHRcdHJldHVybiBpc05hTih6b29tKSA/IEluZmluaXR5IDogem9vbTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBwcm9qZWN0KGxhdGxuZzogTGF0TG5nLCB6b29tOiBOdW1iZXIpOiBQb2ludFxyXG4gIFx0Ly8gUHJvamVjdHMgYSBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZSBgTGF0TG5nYCBhY2NvcmRpbmcgdG8gdGhlIHByb2plY3Rpb25cclxuICBcdC8vIG9mIHRoZSBtYXAncyBDUlMsIHRoZW4gc2NhbGVzIGl0IGFjY29yZGluZyB0byBgem9vbWAgYW5kIHRoZSBDUlMnc1xyXG4gIFx0Ly8gYFRyYW5zZm9ybWF0aW9uYC4gVGhlIHJlc3VsdCBpcyBwaXhlbCBjb29yZGluYXRlIHJlbGF0aXZlIHRvXHJcbiAgXHQvLyB0aGUgQ1JTIG9yaWdpbi5cclxuICBcdHByb2plY3Q6IGZ1bmN0aW9uIChsYXRsbmcsIHpvb20pIHtcclxuICBcdFx0em9vbSA9IHpvb20gPT09IHVuZGVmaW5lZCA/IHRoaXMuX3pvb20gOiB6b29tO1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmNycy5sYXRMbmdUb1BvaW50KHRvTGF0TG5nKGxhdGxuZyksIHpvb20pO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHVucHJvamVjdChwb2ludDogUG9pbnQsIHpvb206IE51bWJlcik6IExhdExuZ1xyXG4gIFx0Ly8gSW52ZXJzZSBvZiBbYHByb2plY3RgXSgjbWFwLXByb2plY3QpLlxyXG4gIFx0dW5wcm9qZWN0OiBmdW5jdGlvbiAocG9pbnQsIHpvb20pIHtcclxuICBcdFx0em9vbSA9IHpvb20gPT09IHVuZGVmaW5lZCA/IHRoaXMuX3pvb20gOiB6b29tO1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmNycy5wb2ludFRvTGF0TG5nKHRvUG9pbnQocG9pbnQpLCB6b29tKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBsYXllclBvaW50VG9MYXRMbmcocG9pbnQ6IFBvaW50KTogTGF0TG5nXHJcbiAgXHQvLyBHaXZlbiBhIHBpeGVsIGNvb3JkaW5hdGUgcmVsYXRpdmUgdG8gdGhlIFtvcmlnaW4gcGl4ZWxdKCNtYXAtZ2V0cGl4ZWxvcmlnaW4pLFxyXG4gIFx0Ly8gcmV0dXJucyB0aGUgY29ycmVzcG9uZGluZyBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZSAoZm9yIHRoZSBjdXJyZW50IHpvb20gbGV2ZWwpLlxyXG4gIFx0bGF5ZXJQb2ludFRvTGF0TG5nOiBmdW5jdGlvbiAocG9pbnQpIHtcclxuICBcdFx0dmFyIHByb2plY3RlZFBvaW50ID0gdG9Qb2ludChwb2ludCkuYWRkKHRoaXMuZ2V0UGl4ZWxPcmlnaW4oKSk7XHJcbiAgXHRcdHJldHVybiB0aGlzLnVucHJvamVjdChwcm9qZWN0ZWRQb2ludCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgbGF0TG5nVG9MYXllclBvaW50KGxhdGxuZzogTGF0TG5nKTogUG9pbnRcclxuICBcdC8vIEdpdmVuIGEgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGUsIHJldHVybnMgdGhlIGNvcnJlc3BvbmRpbmcgcGl4ZWwgY29vcmRpbmF0ZVxyXG4gIFx0Ly8gcmVsYXRpdmUgdG8gdGhlIFtvcmlnaW4gcGl4ZWxdKCNtYXAtZ2V0cGl4ZWxvcmlnaW4pLlxyXG4gIFx0bGF0TG5nVG9MYXllclBvaW50OiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcbiAgXHRcdHZhciBwcm9qZWN0ZWRQb2ludCA9IHRoaXMucHJvamVjdCh0b0xhdExuZyhsYXRsbmcpKS5fcm91bmQoKTtcclxuICBcdFx0cmV0dXJuIHByb2plY3RlZFBvaW50Ll9zdWJ0cmFjdCh0aGlzLmdldFBpeGVsT3JpZ2luKCkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHdyYXBMYXRMbmcobGF0bG5nOiBMYXRMbmcpOiBMYXRMbmdcclxuICBcdC8vIFJldHVybnMgYSBgTGF0TG5nYCB3aGVyZSBgbGF0YCBhbmQgYGxuZ2AgaGFzIGJlZW4gd3JhcHBlZCBhY2NvcmRpbmcgdG8gdGhlXHJcbiAgXHQvLyBtYXAncyBDUlMncyBgd3JhcExhdGAgYW5kIGB3cmFwTG5nYCBwcm9wZXJ0aWVzLCBpZiB0aGV5IGFyZSBvdXRzaWRlIHRoZVxyXG4gIFx0Ly8gQ1JTJ3MgYm91bmRzLlxyXG4gIFx0Ly8gQnkgZGVmYXVsdCB0aGlzIG1lYW5zIGxvbmdpdHVkZSBpcyB3cmFwcGVkIGFyb3VuZCB0aGUgZGF0ZWxpbmUgc28gaXRzXHJcbiAgXHQvLyB2YWx1ZSBpcyBiZXR3ZWVuIC0xODAgYW5kICsxODAgZGVncmVlcy5cclxuICBcdHdyYXBMYXRMbmc6IGZ1bmN0aW9uIChsYXRsbmcpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMub3B0aW9ucy5jcnMud3JhcExhdExuZyh0b0xhdExuZyhsYXRsbmcpKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCB3cmFwTGF0TG5nQm91bmRzKGJvdW5kczogTGF0TG5nQm91bmRzKTogTGF0TG5nQm91bmRzXHJcbiAgXHQvLyBSZXR1cm5zIGEgYExhdExuZ0JvdW5kc2Agd2l0aCB0aGUgc2FtZSBzaXplIGFzIHRoZSBnaXZlbiBvbmUsIGVuc3VyaW5nIHRoYXRcclxuICBcdC8vIGl0cyBjZW50ZXIgaXMgd2l0aGluIHRoZSBDUlMncyBib3VuZHMuXHJcbiAgXHQvLyBCeSBkZWZhdWx0IHRoaXMgbWVhbnMgdGhlIGNlbnRlciBsb25naXR1ZGUgaXMgd3JhcHBlZCBhcm91bmQgdGhlIGRhdGVsaW5lIHNvIGl0c1xyXG4gIFx0Ly8gdmFsdWUgaXMgYmV0d2VlbiAtMTgwIGFuZCArMTgwIGRlZ3JlZXMsIGFuZCB0aGUgbWFqb3JpdHkgb2YgdGhlIGJvdW5kc1xyXG4gIFx0Ly8gb3ZlcmxhcHMgdGhlIENSUydzIGJvdW5kcy5cclxuICBcdHdyYXBMYXRMbmdCb3VuZHM6IGZ1bmN0aW9uIChsYXRsbmcpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMub3B0aW9ucy5jcnMud3JhcExhdExuZ0JvdW5kcyh0b0xhdExuZ0JvdW5kcyhsYXRsbmcpKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBkaXN0YW5jZShsYXRsbmcxOiBMYXRMbmcsIGxhdGxuZzI6IExhdExuZyk6IE51bWJlclxyXG4gIFx0Ly8gUmV0dXJucyB0aGUgZGlzdGFuY2UgYmV0d2VlbiB0d28gZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGVzIGFjY29yZGluZyB0b1xyXG4gIFx0Ly8gdGhlIG1hcCdzIENSUy4gQnkgZGVmYXVsdCB0aGlzIG1lYXN1cmVzIGRpc3RhbmNlIGluIG1ldGVycy5cclxuICBcdGRpc3RhbmNlOiBmdW5jdGlvbiAobGF0bG5nMSwgbGF0bG5nMikge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmNycy5kaXN0YW5jZSh0b0xhdExuZyhsYXRsbmcxKSwgdG9MYXRMbmcobGF0bG5nMikpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGNvbnRhaW5lclBvaW50VG9MYXllclBvaW50KHBvaW50OiBQb2ludCk6IFBvaW50XHJcbiAgXHQvLyBHaXZlbiBhIHBpeGVsIGNvb3JkaW5hdGUgcmVsYXRpdmUgdG8gdGhlIG1hcCBjb250YWluZXIsIHJldHVybnMgdGhlIGNvcnJlc3BvbmRpbmdcclxuICBcdC8vIHBpeGVsIGNvb3JkaW5hdGUgcmVsYXRpdmUgdG8gdGhlIFtvcmlnaW4gcGl4ZWxdKCNtYXAtZ2V0cGl4ZWxvcmlnaW4pLlxyXG4gIFx0Y29udGFpbmVyUG9pbnRUb0xheWVyUG9pbnQ6IGZ1bmN0aW9uIChwb2ludCkgeyAvLyAoUG9pbnQpXHJcbiAgXHRcdHJldHVybiB0b1BvaW50KHBvaW50KS5zdWJ0cmFjdCh0aGlzLl9nZXRNYXBQYW5lUG9zKCkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGxheWVyUG9pbnRUb0NvbnRhaW5lclBvaW50KHBvaW50OiBQb2ludCk6IFBvaW50XHJcbiAgXHQvLyBHaXZlbiBhIHBpeGVsIGNvb3JkaW5hdGUgcmVsYXRpdmUgdG8gdGhlIFtvcmlnaW4gcGl4ZWxdKCNtYXAtZ2V0cGl4ZWxvcmlnaW4pLFxyXG4gIFx0Ly8gcmV0dXJucyB0aGUgY29ycmVzcG9uZGluZyBwaXhlbCBjb29yZGluYXRlIHJlbGF0aXZlIHRvIHRoZSBtYXAgY29udGFpbmVyLlxyXG4gIFx0bGF5ZXJQb2ludFRvQ29udGFpbmVyUG9pbnQ6IGZ1bmN0aW9uIChwb2ludCkgeyAvLyAoUG9pbnQpXHJcbiAgXHRcdHJldHVybiB0b1BvaW50KHBvaW50KS5hZGQodGhpcy5fZ2V0TWFwUGFuZVBvcygpKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBjb250YWluZXJQb2ludFRvTGF0TG5nKHBvaW50OiBQb2ludCk6IExhdExuZ1xyXG4gIFx0Ly8gR2l2ZW4gYSBwaXhlbCBjb29yZGluYXRlIHJlbGF0aXZlIHRvIHRoZSBtYXAgY29udGFpbmVyLCByZXR1cm5zXHJcbiAgXHQvLyB0aGUgY29ycmVzcG9uZGluZyBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZSAoZm9yIHRoZSBjdXJyZW50IHpvb20gbGV2ZWwpLlxyXG4gIFx0Y29udGFpbmVyUG9pbnRUb0xhdExuZzogZnVuY3Rpb24gKHBvaW50KSB7XHJcbiAgXHRcdHZhciBsYXllclBvaW50ID0gdGhpcy5jb250YWluZXJQb2ludFRvTGF5ZXJQb2ludCh0b1BvaW50KHBvaW50KSk7XHJcbiAgXHRcdHJldHVybiB0aGlzLmxheWVyUG9pbnRUb0xhdExuZyhsYXllclBvaW50KTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBsYXRMbmdUb0NvbnRhaW5lclBvaW50KGxhdGxuZzogTGF0TG5nKTogUG9pbnRcclxuICBcdC8vIEdpdmVuIGEgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGUsIHJldHVybnMgdGhlIGNvcnJlc3BvbmRpbmcgcGl4ZWwgY29vcmRpbmF0ZVxyXG4gIFx0Ly8gcmVsYXRpdmUgdG8gdGhlIG1hcCBjb250YWluZXIuXHJcbiAgXHRsYXRMbmdUb0NvbnRhaW5lclBvaW50OiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLmxheWVyUG9pbnRUb0NvbnRhaW5lclBvaW50KHRoaXMubGF0TG5nVG9MYXllclBvaW50KHRvTGF0TG5nKGxhdGxuZykpKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBtb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChldjogTW91c2VFdmVudCk6IFBvaW50XHJcbiAgXHQvLyBHaXZlbiBhIE1vdXNlRXZlbnQgb2JqZWN0LCByZXR1cm5zIHRoZSBwaXhlbCBjb29yZGluYXRlIHJlbGF0aXZlIHRvIHRoZVxyXG4gIFx0Ly8gbWFwIGNvbnRhaW5lciB3aGVyZSB0aGUgZXZlbnQgdG9vayBwbGFjZS5cclxuICBcdG1vdXNlRXZlbnRUb0NvbnRhaW5lclBvaW50OiBmdW5jdGlvbiAoZSkge1xyXG4gIFx0XHRyZXR1cm4gZ2V0TW91c2VQb3NpdGlvbihlLCB0aGlzLl9jb250YWluZXIpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIG1vdXNlRXZlbnRUb0xheWVyUG9pbnQoZXY6IE1vdXNlRXZlbnQpOiBQb2ludFxyXG4gIFx0Ly8gR2l2ZW4gYSBNb3VzZUV2ZW50IG9iamVjdCwgcmV0dXJucyB0aGUgcGl4ZWwgY29vcmRpbmF0ZSByZWxhdGl2ZSB0b1xyXG4gIFx0Ly8gdGhlIFtvcmlnaW4gcGl4ZWxdKCNtYXAtZ2V0cGl4ZWxvcmlnaW4pIHdoZXJlIHRoZSBldmVudCB0b29rIHBsYWNlLlxyXG4gIFx0bW91c2VFdmVudFRvTGF5ZXJQb2ludDogZnVuY3Rpb24gKGUpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuY29udGFpbmVyUG9pbnRUb0xheWVyUG9pbnQodGhpcy5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlKSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgbW91c2VFdmVudFRvTGF0TG5nKGV2OiBNb3VzZUV2ZW50KTogTGF0TG5nXHJcbiAgXHQvLyBHaXZlbiBhIE1vdXNlRXZlbnQgb2JqZWN0LCByZXR1cm5zIGdlb2dyYXBoaWNhbCBjb29yZGluYXRlIHdoZXJlIHRoZVxyXG4gIFx0Ly8gZXZlbnQgdG9vayBwbGFjZS5cclxuICBcdG1vdXNlRXZlbnRUb0xhdExuZzogZnVuY3Rpb24gKGUpIHsgLy8gKE1vdXNlRXZlbnQpXHJcbiAgXHRcdHJldHVybiB0aGlzLmxheWVyUG9pbnRUb0xhdExuZyh0aGlzLm1vdXNlRXZlbnRUb0xheWVyUG9pbnQoZSkpO1xyXG4gIFx0fSxcclxuXHJcblxyXG4gIFx0Ly8gbWFwIGluaXRpYWxpemF0aW9uIG1ldGhvZHNcclxuXHJcbiAgXHRfaW5pdENvbnRhaW5lcjogZnVuY3Rpb24gKGlkKSB7XHJcbiAgXHRcdHZhciBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXIgPSBnZXQoaWQpO1xyXG5cclxuICBcdFx0aWYgKCFjb250YWluZXIpIHtcclxuICBcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ01hcCBjb250YWluZXIgbm90IGZvdW5kLicpO1xyXG4gIFx0XHR9IGVsc2UgaWYgKGNvbnRhaW5lci5fbGVhZmxldF9pZCkge1xyXG4gIFx0XHRcdHRocm93IG5ldyBFcnJvcignTWFwIGNvbnRhaW5lciBpcyBhbHJlYWR5IGluaXRpYWxpemVkLicpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRvbihjb250YWluZXIsICdzY3JvbGwnLCB0aGlzLl9vblNjcm9sbCwgdGhpcyk7XHJcbiAgXHRcdHRoaXMuX2NvbnRhaW5lcklkID0gc3RhbXAoY29udGFpbmVyKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X2luaXRMYXlvdXQ6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dmFyIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRhaW5lcjtcclxuXHJcbiAgXHRcdHRoaXMuX2ZhZGVBbmltYXRlZCA9IHRoaXMub3B0aW9ucy5mYWRlQW5pbWF0aW9uICYmIEJyb3dzZXIuYW55M2Q7XHJcblxyXG4gIFx0XHRhZGRDbGFzcyhjb250YWluZXIsICdsZWFmbGV0LWNvbnRhaW5lcicgK1xyXG4gIFx0XHRcdChCcm93c2VyLnRvdWNoID8gJyBsZWFmbGV0LXRvdWNoJyA6ICcnKSArXHJcbiAgXHRcdFx0KEJyb3dzZXIucmV0aW5hID8gJyBsZWFmbGV0LXJldGluYScgOiAnJykgK1xyXG4gIFx0XHRcdChCcm93c2VyLmllbHQ5ID8gJyBsZWFmbGV0LW9sZGllJyA6ICcnKSArXHJcbiAgXHRcdFx0KEJyb3dzZXIuc2FmYXJpID8gJyBsZWFmbGV0LXNhZmFyaScgOiAnJykgK1xyXG4gIFx0XHRcdCh0aGlzLl9mYWRlQW5pbWF0ZWQgPyAnIGxlYWZsZXQtZmFkZS1hbmltJyA6ICcnKSk7XHJcblxyXG4gIFx0XHR2YXIgcG9zaXRpb24gPSBnZXRTdHlsZShjb250YWluZXIsICdwb3NpdGlvbicpO1xyXG5cclxuICBcdFx0aWYgKHBvc2l0aW9uICE9PSAnYWJzb2x1dGUnICYmIHBvc2l0aW9uICE9PSAncmVsYXRpdmUnICYmIHBvc2l0aW9uICE9PSAnZml4ZWQnICYmIHBvc2l0aW9uICE9PSAnc3RpY2t5Jykge1xyXG4gIFx0XHRcdGNvbnRhaW5lci5zdHlsZS5wb3NpdGlvbiA9ICdyZWxhdGl2ZSc7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX2luaXRQYW5lcygpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX2luaXRDb250cm9sUG9zKSB7XHJcbiAgXHRcdFx0dGhpcy5faW5pdENvbnRyb2xQb3MoKTtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHRfaW5pdFBhbmVzOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHZhciBwYW5lcyA9IHRoaXMuX3BhbmVzID0ge307XHJcbiAgXHRcdHRoaXMuX3BhbmVSZW5kZXJlcnMgPSB7fTtcclxuXHJcbiAgXHRcdC8vIEBzZWN0aW9uXHJcbiAgXHRcdC8vXHJcbiAgXHRcdC8vIFBhbmVzIGFyZSBET00gZWxlbWVudHMgdXNlZCB0byBjb250cm9sIHRoZSBvcmRlcmluZyBvZiBsYXllcnMgb24gdGhlIG1hcC4gWW91XHJcbiAgXHRcdC8vIGNhbiBhY2Nlc3MgcGFuZXMgd2l0aCBbYG1hcC5nZXRQYW5lYF0oI21hcC1nZXRwYW5lKSBvclxyXG4gIFx0XHQvLyBbYG1hcC5nZXRQYW5lc2BdKCNtYXAtZ2V0cGFuZXMpIG1ldGhvZHMuIE5ldyBwYW5lcyBjYW4gYmUgY3JlYXRlZCB3aXRoIHRoZVxyXG4gIFx0XHQvLyBbYG1hcC5jcmVhdGVQYW5lYF0oI21hcC1jcmVhdGVwYW5lKSBtZXRob2QuXHJcbiAgXHRcdC8vXHJcbiAgXHRcdC8vIEV2ZXJ5IG1hcCBoYXMgdGhlIGZvbGxvd2luZyBkZWZhdWx0IHBhbmVzIHRoYXQgZGlmZmVyIG9ubHkgaW4gekluZGV4LlxyXG4gIFx0XHQvL1xyXG4gIFx0XHQvLyBAcGFuZSBtYXBQYW5lOiBIVE1MRWxlbWVudCA9ICdhdXRvJ1xyXG4gIFx0XHQvLyBQYW5lIHRoYXQgY29udGFpbnMgYWxsIG90aGVyIG1hcCBwYW5lc1xyXG5cclxuICBcdFx0dGhpcy5fbWFwUGFuZSA9IHRoaXMuY3JlYXRlUGFuZSgnbWFwUGFuZScsIHRoaXMuX2NvbnRhaW5lcik7XHJcbiAgXHRcdHNldFBvc2l0aW9uKHRoaXMuX21hcFBhbmUsIG5ldyBQb2ludCgwLCAwKSk7XHJcblxyXG4gIFx0XHQvLyBAcGFuZSB0aWxlUGFuZTogSFRNTEVsZW1lbnQgPSAyMDBcclxuICBcdFx0Ly8gUGFuZSBmb3IgYEdyaWRMYXllcmBzIGFuZCBgVGlsZUxheWVyYHNcclxuICBcdFx0dGhpcy5jcmVhdGVQYW5lKCd0aWxlUGFuZScpO1xyXG4gIFx0XHQvLyBAcGFuZSBvdmVybGF5UGFuZTogSFRNTEVsZW1lbnQgPSA0MDBcclxuICBcdFx0Ly8gUGFuZSBmb3IgdmVjdG9ycyAoYFBhdGhgcywgbGlrZSBgUG9seWxpbmVgcyBhbmQgYFBvbHlnb25gcyksIGBJbWFnZU92ZXJsYXlgcyBhbmQgYFZpZGVvT3ZlcmxheWBzXHJcbiAgXHRcdHRoaXMuY3JlYXRlUGFuZSgnb3ZlcmxheVBhbmUnKTtcclxuICBcdFx0Ly8gQHBhbmUgc2hhZG93UGFuZTogSFRNTEVsZW1lbnQgPSA1MDBcclxuICBcdFx0Ly8gUGFuZSBmb3Igb3ZlcmxheSBzaGFkb3dzIChlLmcuIGBNYXJrZXJgIHNoYWRvd3MpXHJcbiAgXHRcdHRoaXMuY3JlYXRlUGFuZSgnc2hhZG93UGFuZScpO1xyXG4gIFx0XHQvLyBAcGFuZSBtYXJrZXJQYW5lOiBIVE1MRWxlbWVudCA9IDYwMFxyXG4gIFx0XHQvLyBQYW5lIGZvciBgSWNvbmBzIG9mIGBNYXJrZXJgc1xyXG4gIFx0XHR0aGlzLmNyZWF0ZVBhbmUoJ21hcmtlclBhbmUnKTtcclxuICBcdFx0Ly8gQHBhbmUgdG9vbHRpcFBhbmU6IEhUTUxFbGVtZW50ID0gNjUwXHJcbiAgXHRcdC8vIFBhbmUgZm9yIGBUb29sdGlwYHMuXHJcbiAgXHRcdHRoaXMuY3JlYXRlUGFuZSgndG9vbHRpcFBhbmUnKTtcclxuICBcdFx0Ly8gQHBhbmUgcG9wdXBQYW5lOiBIVE1MRWxlbWVudCA9IDcwMFxyXG4gIFx0XHQvLyBQYW5lIGZvciBgUG9wdXBgcy5cclxuICBcdFx0dGhpcy5jcmVhdGVQYW5lKCdwb3B1cFBhbmUnKTtcclxuXHJcbiAgXHRcdGlmICghdGhpcy5vcHRpb25zLm1hcmtlclpvb21BbmltYXRpb24pIHtcclxuICBcdFx0XHRhZGRDbGFzcyhwYW5lcy5tYXJrZXJQYW5lLCAnbGVhZmxldC16b29tLWhpZGUnKTtcclxuICBcdFx0XHRhZGRDbGFzcyhwYW5lcy5zaGFkb3dQYW5lLCAnbGVhZmxldC16b29tLWhpZGUnKTtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcblxyXG4gIFx0Ly8gcHJpdmF0ZSBtZXRob2RzIHRoYXQgbW9kaWZ5IG1hcCBzdGF0ZVxyXG5cclxuICBcdC8vIEBzZWN0aW9uIE1hcCBzdGF0ZSBjaGFuZ2UgZXZlbnRzXHJcbiAgXHRfcmVzZXRWaWV3OiBmdW5jdGlvbiAoY2VudGVyLCB6b29tLCBub01vdmVTdGFydCkge1xyXG4gIFx0XHRzZXRQb3NpdGlvbih0aGlzLl9tYXBQYW5lLCBuZXcgUG9pbnQoMCwgMCkpO1xyXG5cclxuICBcdFx0dmFyIGxvYWRpbmcgPSAhdGhpcy5fbG9hZGVkO1xyXG4gIFx0XHR0aGlzLl9sb2FkZWQgPSB0cnVlO1xyXG4gIFx0XHR6b29tID0gdGhpcy5fbGltaXRab29tKHpvb20pO1xyXG5cclxuICBcdFx0dGhpcy5maXJlKCd2aWV3cHJlcmVzZXQnKTtcclxuXHJcbiAgXHRcdHZhciB6b29tQ2hhbmdlZCA9IHRoaXMuX3pvb20gIT09IHpvb207XHJcbiAgXHRcdHRoaXNcclxuICBcdFx0XHQuX21vdmVTdGFydCh6b29tQ2hhbmdlZCwgbm9Nb3ZlU3RhcnQpXHJcbiAgXHRcdFx0Ll9tb3ZlKGNlbnRlciwgem9vbSlcclxuICBcdFx0XHQuX21vdmVFbmQoem9vbUNoYW5nZWQpO1xyXG5cclxuICBcdFx0Ly8gQGV2ZW50IHZpZXdyZXNldDogRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbWFwIG5lZWRzIHRvIHJlZHJhdyBpdHMgY29udGVudCAodGhpcyB1c3VhbGx5IGhhcHBlbnNcclxuICBcdFx0Ly8gb24gbWFwIHpvb20gb3IgbG9hZCkuIFZlcnkgdXNlZnVsIGZvciBjcmVhdGluZyBjdXN0b20gb3ZlcmxheXMuXHJcbiAgXHRcdHRoaXMuZmlyZSgndmlld3Jlc2V0Jyk7XHJcblxyXG4gIFx0XHQvLyBAZXZlbnQgbG9hZDogRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbWFwIGlzIGluaXRpYWxpemVkICh3aGVuIGl0cyBjZW50ZXIgYW5kIHpvb20gYXJlIHNldFxyXG4gIFx0XHQvLyBmb3IgdGhlIGZpcnN0IHRpbWUpLlxyXG4gIFx0XHRpZiAobG9hZGluZykge1xyXG4gIFx0XHRcdHRoaXMuZmlyZSgnbG9hZCcpO1xyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdF9tb3ZlU3RhcnQ6IGZ1bmN0aW9uICh6b29tQ2hhbmdlZCwgbm9Nb3ZlU3RhcnQpIHtcclxuICBcdFx0Ly8gQGV2ZW50IHpvb21zdGFydDogRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbWFwIHpvb20gaXMgYWJvdXQgdG8gY2hhbmdlIChlLmcuIGJlZm9yZSB6b29tIGFuaW1hdGlvbikuXHJcbiAgXHRcdC8vIEBldmVudCBtb3Zlc3RhcnQ6IEV2ZW50XHJcbiAgXHRcdC8vIEZpcmVkIHdoZW4gdGhlIHZpZXcgb2YgdGhlIG1hcCBzdGFydHMgY2hhbmdpbmcgKGUuZy4gdXNlciBzdGFydHMgZHJhZ2dpbmcgdGhlIG1hcCkuXHJcbiAgXHRcdGlmICh6b29tQ2hhbmdlZCkge1xyXG4gIFx0XHRcdHRoaXMuZmlyZSgnem9vbXN0YXJ0Jyk7XHJcbiAgXHRcdH1cclxuICBcdFx0aWYgKCFub01vdmVTdGFydCkge1xyXG4gIFx0XHRcdHRoaXMuZmlyZSgnbW92ZXN0YXJ0Jyk7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9tb3ZlOiBmdW5jdGlvbiAoY2VudGVyLCB6b29tLCBkYXRhLCBzdXByZXNzRXZlbnQpIHtcclxuICBcdFx0aWYgKHpvb20gPT09IHVuZGVmaW5lZCkge1xyXG4gIFx0XHRcdHpvb20gPSB0aGlzLl96b29tO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHZhciB6b29tQ2hhbmdlZCA9IHRoaXMuX3pvb20gIT09IHpvb207XHJcblxyXG4gIFx0XHR0aGlzLl96b29tID0gem9vbTtcclxuICBcdFx0dGhpcy5fbGFzdENlbnRlciA9IGNlbnRlcjtcclxuICBcdFx0dGhpcy5fcGl4ZWxPcmlnaW4gPSB0aGlzLl9nZXROZXdQaXhlbE9yaWdpbihjZW50ZXIpO1xyXG5cclxuICBcdFx0aWYgKCFzdXByZXNzRXZlbnQpIHtcclxuICBcdFx0XHQvLyBAZXZlbnQgem9vbTogRXZlbnRcclxuICBcdFx0XHQvLyBGaXJlZCByZXBlYXRlZGx5IGR1cmluZyBhbnkgY2hhbmdlIGluIHpvb20gbGV2ZWwsXHJcbiAgXHRcdFx0Ly8gaW5jbHVkaW5nIHpvb20gYW5kIGZseSBhbmltYXRpb25zLlxyXG4gIFx0XHRcdGlmICh6b29tQ2hhbmdlZCB8fCAoZGF0YSAmJiBkYXRhLnBpbmNoKSkge1x0Ly8gQWx3YXlzIGZpcmUgJ3pvb20nIGlmIHBpbmNoaW5nIGJlY2F1c2UgIzM1MzBcclxuICBcdFx0XHRcdHRoaXMuZmlyZSgnem9vbScsIGRhdGEpO1xyXG4gIFx0XHRcdH1cclxuXHJcbiAgXHRcdFx0Ly8gQGV2ZW50IG1vdmU6IEV2ZW50XHJcbiAgXHRcdFx0Ly8gRmlyZWQgcmVwZWF0ZWRseSBkdXJpbmcgYW55IG1vdmVtZW50IG9mIHRoZSBtYXAsXHJcbiAgXHRcdFx0Ly8gaW5jbHVkaW5nIHBhbiBhbmQgZmx5IGFuaW1hdGlvbnMuXHJcbiAgXHRcdFx0dGhpcy5maXJlKCdtb3ZlJywgZGF0YSk7XHJcbiAgXHRcdH0gZWxzZSBpZiAoZGF0YSAmJiBkYXRhLnBpbmNoKSB7XHQvLyBBbHdheXMgZmlyZSAnem9vbScgaWYgcGluY2hpbmcgYmVjYXVzZSAjMzUzMFxyXG4gIFx0XHRcdHRoaXMuZmlyZSgnem9vbScsIGRhdGEpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfbW92ZUVuZDogZnVuY3Rpb24gKHpvb21DaGFuZ2VkKSB7XHJcbiAgXHRcdC8vIEBldmVudCB6b29tZW5kOiBFdmVudFxyXG4gIFx0XHQvLyBGaXJlZCB3aGVuIHRoZSBtYXAgem9vbSBjaGFuZ2VkLCBhZnRlciBhbnkgYW5pbWF0aW9ucy5cclxuICBcdFx0aWYgKHpvb21DaGFuZ2VkKSB7XHJcbiAgXHRcdFx0dGhpcy5maXJlKCd6b29tZW5kJyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdC8vIEBldmVudCBtb3ZlZW5kOiBFdmVudFxyXG4gIFx0XHQvLyBGaXJlZCB3aGVuIHRoZSBjZW50ZXIgb2YgdGhlIG1hcCBzdG9wcyBjaGFuZ2luZ1xyXG4gIFx0XHQvLyAoZS5nLiB1c2VyIHN0b3BwZWQgZHJhZ2dpbmcgdGhlIG1hcCBvciBhZnRlciBub24tY2VudGVyZWQgem9vbSkuXHJcbiAgXHRcdHJldHVybiB0aGlzLmZpcmUoJ21vdmVlbmQnKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X3N0b3A6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX2ZseVRvRnJhbWUpO1xyXG4gIFx0XHRpZiAodGhpcy5fcGFuQW5pbSkge1xyXG4gIFx0XHRcdHRoaXMuX3BhbkFuaW0uc3RvcCgpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfcmF3UGFuQnk6IGZ1bmN0aW9uIChvZmZzZXQpIHtcclxuICBcdFx0c2V0UG9zaXRpb24odGhpcy5fbWFwUGFuZSwgdGhpcy5fZ2V0TWFwUGFuZVBvcygpLnN1YnRyYWN0KG9mZnNldCkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfZ2V0Wm9vbVNwYW46IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuZ2V0TWF4Wm9vbSgpIC0gdGhpcy5nZXRNaW5ab29tKCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9wYW5JbnNpZGVNYXhCb3VuZHM6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKCF0aGlzLl9lbmZvcmNpbmdCb3VuZHMpIHtcclxuICBcdFx0XHR0aGlzLnBhbkluc2lkZUJvdW5kcyh0aGlzLm9wdGlvbnMubWF4Qm91bmRzKTtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHRfY2hlY2tJZkxvYWRlZDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRpZiAoIXRoaXMuX2xvYWRlZCkge1xyXG4gIFx0XHRcdHRocm93IG5ldyBFcnJvcignU2V0IG1hcCBjZW50ZXIgYW5kIHpvb20gZmlyc3QuJyk7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gRE9NIGV2ZW50IGhhbmRsaW5nXHJcblxyXG4gIFx0Ly8gQHNlY3Rpb24gSW50ZXJhY3Rpb24gZXZlbnRzXHJcbiAgXHRfaW5pdEV2ZW50czogZnVuY3Rpb24gKHJlbW92ZSkge1xyXG4gIFx0XHR0aGlzLl90YXJnZXRzID0ge307XHJcbiAgXHRcdHRoaXMuX3RhcmdldHNbc3RhbXAodGhpcy5fY29udGFpbmVyKV0gPSB0aGlzO1xyXG5cclxuICBcdFx0dmFyIG9uT2ZmID0gcmVtb3ZlID8gb2ZmIDogb247XHJcblxyXG4gIFx0XHQvLyBAZXZlbnQgY2xpY2s6IE1vdXNlRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgdXNlciBjbGlja3MgKG9yIHRhcHMpIHRoZSBtYXAuXHJcbiAgXHRcdC8vIEBldmVudCBkYmxjbGljazogTW91c2VFdmVudFxyXG4gIFx0XHQvLyBGaXJlZCB3aGVuIHRoZSB1c2VyIGRvdWJsZS1jbGlja3MgKG9yIGRvdWJsZS10YXBzKSB0aGUgbWFwLlxyXG4gIFx0XHQvLyBAZXZlbnQgbW91c2Vkb3duOiBNb3VzZUV2ZW50XHJcbiAgXHRcdC8vIEZpcmVkIHdoZW4gdGhlIHVzZXIgcHVzaGVzIHRoZSBtb3VzZSBidXR0b24gb24gdGhlIG1hcC5cclxuICBcdFx0Ly8gQGV2ZW50IG1vdXNldXA6IE1vdXNlRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgdXNlciByZWxlYXNlcyB0aGUgbW91c2UgYnV0dG9uIG9uIHRoZSBtYXAuXHJcbiAgXHRcdC8vIEBldmVudCBtb3VzZW92ZXI6IE1vdXNlRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbW91c2UgZW50ZXJzIHRoZSBtYXAuXHJcbiAgXHRcdC8vIEBldmVudCBtb3VzZW91dDogTW91c2VFdmVudFxyXG4gIFx0XHQvLyBGaXJlZCB3aGVuIHRoZSBtb3VzZSBsZWF2ZXMgdGhlIG1hcC5cclxuICBcdFx0Ly8gQGV2ZW50IG1vdXNlbW92ZTogTW91c2VFdmVudFxyXG4gIFx0XHQvLyBGaXJlZCB3aGlsZSB0aGUgbW91c2UgbW92ZXMgb3ZlciB0aGUgbWFwLlxyXG4gIFx0XHQvLyBAZXZlbnQgY29udGV4dG1lbnU6IE1vdXNlRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgdXNlciBwdXNoZXMgdGhlIHJpZ2h0IG1vdXNlIGJ1dHRvbiBvbiB0aGUgbWFwLCBwcmV2ZW50c1xyXG4gIFx0XHQvLyBkZWZhdWx0IGJyb3dzZXIgY29udGV4dCBtZW51IGZyb20gc2hvd2luZyBpZiB0aGVyZSBhcmUgbGlzdGVuZXJzIG9uXHJcbiAgXHRcdC8vIHRoaXMgZXZlbnQuIEFsc28gZmlyZWQgb24gbW9iaWxlIHdoZW4gdGhlIHVzZXIgaG9sZHMgYSBzaW5nbGUgdG91Y2hcclxuICBcdFx0Ly8gZm9yIGEgc2Vjb25kIChhbHNvIGNhbGxlZCBsb25nIHByZXNzKS5cclxuICBcdFx0Ly8gQGV2ZW50IGtleXByZXNzOiBLZXlib2FyZEV2ZW50XHJcbiAgXHRcdC8vIEZpcmVkIHdoZW4gdGhlIHVzZXIgcHJlc3NlcyBhIGtleSBmcm9tIHRoZSBrZXlib2FyZCB0aGF0IHByb2R1Y2VzIGEgY2hhcmFjdGVyIHZhbHVlIHdoaWxlIHRoZSBtYXAgaXMgZm9jdXNlZC5cclxuICBcdFx0Ly8gQGV2ZW50IGtleWRvd246IEtleWJvYXJkRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgdXNlciBwcmVzc2VzIGEga2V5IGZyb20gdGhlIGtleWJvYXJkIHdoaWxlIHRoZSBtYXAgaXMgZm9jdXNlZC4gVW5saWtlIHRoZSBga2V5cHJlc3NgIGV2ZW50LFxyXG4gIFx0XHQvLyB0aGUgYGtleWRvd25gIGV2ZW50IGlzIGZpcmVkIGZvciBrZXlzIHRoYXQgcHJvZHVjZSBhIGNoYXJhY3RlciB2YWx1ZSBhbmQgZm9yIGtleXNcclxuICBcdFx0Ly8gdGhhdCBkbyBub3QgcHJvZHVjZSBhIGNoYXJhY3RlciB2YWx1ZS5cclxuICBcdFx0Ly8gQGV2ZW50IGtleXVwOiBLZXlib2FyZEV2ZW50XHJcbiAgXHRcdC8vIEZpcmVkIHdoZW4gdGhlIHVzZXIgcmVsZWFzZXMgYSBrZXkgZnJvbSB0aGUga2V5Ym9hcmQgd2hpbGUgdGhlIG1hcCBpcyBmb2N1c2VkLlxyXG4gIFx0XHRvbk9mZih0aGlzLl9jb250YWluZXIsICdjbGljayBkYmxjbGljayBtb3VzZWRvd24gbW91c2V1cCAnICtcclxuICBcdFx0XHQnbW91c2VvdmVyIG1vdXNlb3V0IG1vdXNlbW92ZSBjb250ZXh0bWVudSBrZXlwcmVzcyBrZXlkb3duIGtleXVwJywgdGhpcy5faGFuZGxlRE9NRXZlbnQsIHRoaXMpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy50cmFja1Jlc2l6ZSkge1xyXG4gIFx0XHRcdG9uT2ZmKHdpbmRvdywgJ3Jlc2l6ZScsIHRoaXMuX29uUmVzaXplLCB0aGlzKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0aWYgKEJyb3dzZXIuYW55M2QgJiYgdGhpcy5vcHRpb25zLnRyYW5zZm9ybTNETGltaXQpIHtcclxuICBcdFx0XHQocmVtb3ZlID8gdGhpcy5vZmYgOiB0aGlzLm9uKS5jYWxsKHRoaXMsICdtb3ZlZW5kJywgdGhpcy5fb25Nb3ZlRW5kKTtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHRfb25SZXNpemU6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX3Jlc2l6ZVJlcXVlc3QpO1xyXG4gIFx0XHR0aGlzLl9yZXNpemVSZXF1ZXN0ID0gcmVxdWVzdEFuaW1GcmFtZShcclxuICBcdFx0ICAgICAgICBmdW5jdGlvbiAoKSB7IHRoaXMuaW52YWxpZGF0ZVNpemUoe2RlYm91bmNlTW92ZWVuZDogdHJ1ZX0pOyB9LCB0aGlzKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X29uU2Nyb2xsOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHRoaXMuX2NvbnRhaW5lci5zY3JvbGxUb3AgID0gMDtcclxuICBcdFx0dGhpcy5fY29udGFpbmVyLnNjcm9sbExlZnQgPSAwO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfb25Nb3ZlRW5kOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHZhciBwb3MgPSB0aGlzLl9nZXRNYXBQYW5lUG9zKCk7XHJcbiAgXHRcdGlmIChNYXRoLm1heChNYXRoLmFicyhwb3MueCksIE1hdGguYWJzKHBvcy55KSkgPj0gdGhpcy5vcHRpb25zLnRyYW5zZm9ybTNETGltaXQpIHtcclxuICBcdFx0XHQvLyBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD0xMjAzODczIGJ1dCBXZWJraXQgYWxzbyBoYXZlXHJcbiAgXHRcdFx0Ly8gYSBwaXhlbCBvZmZzZXQgb24gdmVyeSBoaWdoIHZhbHVlcywgc2VlOiBodHRwczovL2pzZmlkZGxlLm5ldC9kZzZyNWhoYi9cclxuICBcdFx0XHR0aGlzLl9yZXNldFZpZXcodGhpcy5nZXRDZW50ZXIoKSwgdGhpcy5nZXRab29tKCkpO1xyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdF9maW5kRXZlbnRUYXJnZXRzOiBmdW5jdGlvbiAoZSwgdHlwZSkge1xyXG4gIFx0XHR2YXIgdGFyZ2V0cyA9IFtdLFxyXG4gIFx0XHQgICAgdGFyZ2V0LFxyXG4gIFx0XHQgICAgaXNIb3ZlciA9IHR5cGUgPT09ICdtb3VzZW91dCcgfHwgdHlwZSA9PT0gJ21vdXNlb3ZlcicsXHJcbiAgXHRcdCAgICBzcmMgPSBlLnRhcmdldCB8fCBlLnNyY0VsZW1lbnQsXHJcbiAgXHRcdCAgICBkcmFnZ2luZyA9IGZhbHNlO1xyXG5cclxuICBcdFx0d2hpbGUgKHNyYykge1xyXG4gIFx0XHRcdHRhcmdldCA9IHRoaXMuX3RhcmdldHNbc3RhbXAoc3JjKV07XHJcbiAgXHRcdFx0aWYgKHRhcmdldCAmJiAodHlwZSA9PT0gJ2NsaWNrJyB8fCB0eXBlID09PSAncHJlY2xpY2snKSAmJiB0aGlzLl9kcmFnZ2FibGVNb3ZlZCh0YXJnZXQpKSB7XHJcbiAgXHRcdFx0XHQvLyBQcmV2ZW50IGZpcmluZyBjbGljayBhZnRlciB5b3UganVzdCBkcmFnZ2VkIGFuIG9iamVjdC5cclxuICBcdFx0XHRcdGRyYWdnaW5nID0gdHJ1ZTtcclxuICBcdFx0XHRcdGJyZWFrO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0XHRpZiAodGFyZ2V0ICYmIHRhcmdldC5saXN0ZW5zKHR5cGUsIHRydWUpKSB7XHJcbiAgXHRcdFx0XHRpZiAoaXNIb3ZlciAmJiAhaXNFeHRlcm5hbFRhcmdldChzcmMsIGUpKSB7IGJyZWFrOyB9XHJcbiAgXHRcdFx0XHR0YXJnZXRzLnB1c2godGFyZ2V0KTtcclxuICBcdFx0XHRcdGlmIChpc0hvdmVyKSB7IGJyZWFrOyB9XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHRcdGlmIChzcmMgPT09IHRoaXMuX2NvbnRhaW5lcikgeyBicmVhazsgfVxyXG4gIFx0XHRcdHNyYyA9IHNyYy5wYXJlbnROb2RlO1xyXG4gIFx0XHR9XHJcbiAgXHRcdGlmICghdGFyZ2V0cy5sZW5ndGggJiYgIWRyYWdnaW5nICYmICFpc0hvdmVyICYmIHRoaXMubGlzdGVucyh0eXBlLCB0cnVlKSkge1xyXG4gIFx0XHRcdHRhcmdldHMgPSBbdGhpc107XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRhcmdldHM7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9pc0NsaWNrRGlzYWJsZWQ6IGZ1bmN0aW9uIChlbCkge1xyXG4gIFx0XHR3aGlsZSAoZWwgJiYgZWwgIT09IHRoaXMuX2NvbnRhaW5lcikge1xyXG4gIFx0XHRcdGlmIChlbFsnX2xlYWZsZXRfZGlzYWJsZV9jbGljayddKSB7IHJldHVybiB0cnVlOyB9XHJcbiAgXHRcdFx0ZWwgPSBlbC5wYXJlbnROb2RlO1xyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdF9oYW5kbGVET01FdmVudDogZnVuY3Rpb24gKGUpIHtcclxuICBcdFx0dmFyIGVsID0gKGUudGFyZ2V0IHx8IGUuc3JjRWxlbWVudCk7XHJcbiAgXHRcdGlmICghdGhpcy5fbG9hZGVkIHx8IGVsWydfbGVhZmxldF9kaXNhYmxlX2V2ZW50cyddIHx8IGUudHlwZSA9PT0gJ2NsaWNrJyAmJiB0aGlzLl9pc0NsaWNrRGlzYWJsZWQoZWwpKSB7XHJcbiAgXHRcdFx0cmV0dXJuO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgdHlwZSA9IGUudHlwZTtcclxuXHJcbiAgXHRcdGlmICh0eXBlID09PSAnbW91c2Vkb3duJykge1xyXG4gIFx0XHRcdC8vIHByZXZlbnRzIG91dGxpbmUgd2hlbiBjbGlja2luZyBvbiBrZXlib2FyZC1mb2N1c2FibGUgZWxlbWVudFxyXG4gIFx0XHRcdHByZXZlbnRPdXRsaW5lKGVsKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5fZmlyZURPTUV2ZW50KGUsIHR5cGUpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfbW91c2VFdmVudHM6IFsnY2xpY2snLCAnZGJsY2xpY2snLCAnbW91c2VvdmVyJywgJ21vdXNlb3V0JywgJ2NvbnRleHRtZW51J10sXHJcblxyXG4gIFx0X2ZpcmVET01FdmVudDogZnVuY3Rpb24gKGUsIHR5cGUsIGNhbnZhc1RhcmdldHMpIHtcclxuXHJcbiAgXHRcdGlmIChlLnR5cGUgPT09ICdjbGljaycpIHtcclxuICBcdFx0XHQvLyBGaXJlIGEgc3ludGhldGljICdwcmVjbGljaycgZXZlbnQgd2hpY2ggcHJvcGFnYXRlcyB1cCAobWFpbmx5IGZvciBjbG9zaW5nIHBvcHVwcykuXHJcbiAgXHRcdFx0Ly8gQGV2ZW50IHByZWNsaWNrOiBNb3VzZUV2ZW50XHJcbiAgXHRcdFx0Ly8gRmlyZWQgYmVmb3JlIG1vdXNlIGNsaWNrIG9uIHRoZSBtYXAgKHNvbWV0aW1lcyB1c2VmdWwgd2hlbiB5b3VcclxuICBcdFx0XHQvLyB3YW50IHNvbWV0aGluZyB0byBoYXBwZW4gb24gY2xpY2sgYmVmb3JlIGFueSBleGlzdGluZyBjbGlja1xyXG4gIFx0XHRcdC8vIGhhbmRsZXJzIHN0YXJ0IHJ1bm5pbmcpLlxyXG4gIFx0XHRcdHZhciBzeW50aCA9IGV4dGVuZCh7fSwgZSk7XHJcbiAgXHRcdFx0c3ludGgudHlwZSA9ICdwcmVjbGljayc7XHJcbiAgXHRcdFx0dGhpcy5fZmlyZURPTUV2ZW50KHN5bnRoLCBzeW50aC50eXBlLCBjYW52YXNUYXJnZXRzKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gRmluZCB0aGUgbGF5ZXIgdGhlIGV2ZW50IGlzIHByb3BhZ2F0aW5nIGZyb20gYW5kIGl0cyBwYXJlbnRzLlxyXG4gIFx0XHR2YXIgdGFyZ2V0cyA9IHRoaXMuX2ZpbmRFdmVudFRhcmdldHMoZSwgdHlwZSk7XHJcblxyXG4gIFx0XHRpZiAoY2FudmFzVGFyZ2V0cykge1xyXG4gIFx0XHRcdHZhciBmaWx0ZXJlZCA9IFtdOyAvLyBwaWNrIG9ubHkgdGFyZ2V0cyB3aXRoIGxpc3RlbmVyc1xyXG4gIFx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgY2FudmFzVGFyZ2V0cy5sZW5ndGg7IGkrKykge1xyXG4gIFx0XHRcdFx0aWYgKGNhbnZhc1RhcmdldHNbaV0ubGlzdGVucyh0eXBlLCB0cnVlKSkge1xyXG4gIFx0XHRcdFx0XHRmaWx0ZXJlZC5wdXNoKGNhbnZhc1RhcmdldHNbaV0pO1xyXG4gIFx0XHRcdFx0fVxyXG4gIFx0XHRcdH1cclxuICBcdFx0XHR0YXJnZXRzID0gZmlsdGVyZWQuY29uY2F0KHRhcmdldHMpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAoIXRhcmdldHMubGVuZ3RoKSB7IHJldHVybjsgfVxyXG5cclxuICBcdFx0aWYgKHR5cGUgPT09ICdjb250ZXh0bWVudScpIHtcclxuICBcdFx0XHRwcmV2ZW50RGVmYXVsdChlKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dmFyIHRhcmdldCA9IHRhcmdldHNbMF07XHJcbiAgXHRcdHZhciBkYXRhID0ge1xyXG4gIFx0XHRcdG9yaWdpbmFsRXZlbnQ6IGVcclxuICBcdFx0fTtcclxuXHJcbiAgXHRcdGlmIChlLnR5cGUgIT09ICdrZXlwcmVzcycgJiYgZS50eXBlICE9PSAna2V5ZG93bicgJiYgZS50eXBlICE9PSAna2V5dXAnKSB7XHJcbiAgXHRcdFx0dmFyIGlzTWFya2VyID0gdGFyZ2V0LmdldExhdExuZyAmJiAoIXRhcmdldC5fcmFkaXVzIHx8IHRhcmdldC5fcmFkaXVzIDw9IDEwKTtcclxuICBcdFx0XHRkYXRhLmNvbnRhaW5lclBvaW50ID0gaXNNYXJrZXIgP1xyXG4gIFx0XHRcdFx0dGhpcy5sYXRMbmdUb0NvbnRhaW5lclBvaW50KHRhcmdldC5nZXRMYXRMbmcoKSkgOiB0aGlzLm1vdXNlRXZlbnRUb0NvbnRhaW5lclBvaW50KGUpO1xyXG4gIFx0XHRcdGRhdGEubGF5ZXJQb2ludCA9IHRoaXMuY29udGFpbmVyUG9pbnRUb0xheWVyUG9pbnQoZGF0YS5jb250YWluZXJQb2ludCk7XHJcbiAgXHRcdFx0ZGF0YS5sYXRsbmcgPSBpc01hcmtlciA/IHRhcmdldC5nZXRMYXRMbmcoKSA6IHRoaXMubGF5ZXJQb2ludFRvTGF0TG5nKGRhdGEubGF5ZXJQb2ludCk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGZvciAoaSA9IDA7IGkgPCB0YXJnZXRzLmxlbmd0aDsgaSsrKSB7XHJcbiAgXHRcdFx0dGFyZ2V0c1tpXS5maXJlKHR5cGUsIGRhdGEsIHRydWUpO1xyXG4gIFx0XHRcdGlmIChkYXRhLm9yaWdpbmFsRXZlbnQuX3N0b3BwZWQgfHxcclxuICBcdFx0XHRcdCh0YXJnZXRzW2ldLm9wdGlvbnMuYnViYmxpbmdNb3VzZUV2ZW50cyA9PT0gZmFsc2UgJiYgaW5kZXhPZih0aGlzLl9tb3VzZUV2ZW50cywgdHlwZSkgIT09IC0xKSkgeyByZXR1cm47IH1cclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHRfZHJhZ2dhYmxlTW92ZWQ6IGZ1bmN0aW9uIChvYmopIHtcclxuICBcdFx0b2JqID0gb2JqLmRyYWdnaW5nICYmIG9iai5kcmFnZ2luZy5lbmFibGVkKCkgPyBvYmogOiB0aGlzO1xyXG4gIFx0XHRyZXR1cm4gKG9iai5kcmFnZ2luZyAmJiBvYmouZHJhZ2dpbmcubW92ZWQoKSkgfHwgKHRoaXMuYm94Wm9vbSAmJiB0aGlzLmJveFpvb20ubW92ZWQoKSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9jbGVhckhhbmRsZXJzOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSB0aGlzLl9oYW5kbGVycy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gIFx0XHRcdHRoaXMuX2hhbmRsZXJzW2ldLmRpc2FibGUoKTtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAc2VjdGlvbiBPdGhlciBNZXRob2RzXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCB3aGVuUmVhZHkoZm46IEZ1bmN0aW9uLCBjb250ZXh0PzogT2JqZWN0KTogdGhpc1xyXG4gIFx0Ly8gUnVucyB0aGUgZ2l2ZW4gZnVuY3Rpb24gYGZuYCB3aGVuIHRoZSBtYXAgZ2V0cyBpbml0aWFsaXplZCB3aXRoXHJcbiAgXHQvLyBhIHZpZXcgKGNlbnRlciBhbmQgem9vbSkgYW5kIGF0IGxlYXN0IG9uZSBsYXllciwgb3IgaW1tZWRpYXRlbHlcclxuICBcdC8vIGlmIGl0J3MgYWxyZWFkeSBpbml0aWFsaXplZCwgb3B0aW9uYWxseSBwYXNzaW5nIGEgZnVuY3Rpb24gY29udGV4dC5cclxuICBcdHdoZW5SZWFkeTogZnVuY3Rpb24gKGNhbGxiYWNrLCBjb250ZXh0KSB7XHJcbiAgXHRcdGlmICh0aGlzLl9sb2FkZWQpIHtcclxuICBcdFx0XHRjYWxsYmFjay5jYWxsKGNvbnRleHQgfHwgdGhpcywge3RhcmdldDogdGhpc30pO1xyXG4gIFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdHRoaXMub24oJ2xvYWQnLCBjYWxsYmFjaywgY29udGV4dCk7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuXHJcbiAgXHQvLyBwcml2YXRlIG1ldGhvZHMgZm9yIGdldHRpbmcgbWFwIHN0YXRlXHJcblxyXG4gIFx0X2dldE1hcFBhbmVQb3M6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIGdldFBvc2l0aW9uKHRoaXMuX21hcFBhbmUpIHx8IG5ldyBQb2ludCgwLCAwKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X21vdmVkOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHZhciBwb3MgPSB0aGlzLl9nZXRNYXBQYW5lUG9zKCk7XHJcbiAgXHRcdHJldHVybiBwb3MgJiYgIXBvcy5lcXVhbHMoWzAsIDBdKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X2dldFRvcExlZnRQb2ludDogZnVuY3Rpb24gKGNlbnRlciwgem9vbSkge1xyXG4gIFx0XHR2YXIgcGl4ZWxPcmlnaW4gPSBjZW50ZXIgJiYgem9vbSAhPT0gdW5kZWZpbmVkID9cclxuICBcdFx0XHR0aGlzLl9nZXROZXdQaXhlbE9yaWdpbihjZW50ZXIsIHpvb20pIDpcclxuICBcdFx0XHR0aGlzLmdldFBpeGVsT3JpZ2luKCk7XHJcbiAgXHRcdHJldHVybiBwaXhlbE9yaWdpbi5zdWJ0cmFjdCh0aGlzLl9nZXRNYXBQYW5lUG9zKCkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfZ2V0TmV3UGl4ZWxPcmlnaW46IGZ1bmN0aW9uIChjZW50ZXIsIHpvb20pIHtcclxuICBcdFx0dmFyIHZpZXdIYWxmID0gdGhpcy5nZXRTaXplKCkuX2RpdmlkZUJ5KDIpO1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5wcm9qZWN0KGNlbnRlciwgem9vbSkuX3N1YnRyYWN0KHZpZXdIYWxmKS5fYWRkKHRoaXMuX2dldE1hcFBhbmVQb3MoKSkuX3JvdW5kKCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9sYXRMbmdUb05ld0xheWVyUG9pbnQ6IGZ1bmN0aW9uIChsYXRsbmcsIHpvb20sIGNlbnRlcikge1xyXG4gIFx0XHR2YXIgdG9wTGVmdCA9IHRoaXMuX2dldE5ld1BpeGVsT3JpZ2luKGNlbnRlciwgem9vbSk7XHJcbiAgXHRcdHJldHVybiB0aGlzLnByb2plY3QobGF0bG5nLCB6b29tKS5fc3VidHJhY3QodG9wTGVmdCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9sYXRMbmdCb3VuZHNUb05ld0xheWVyQm91bmRzOiBmdW5jdGlvbiAobGF0TG5nQm91bmRzLCB6b29tLCBjZW50ZXIpIHtcclxuICBcdFx0dmFyIHRvcExlZnQgPSB0aGlzLl9nZXROZXdQaXhlbE9yaWdpbihjZW50ZXIsIHpvb20pO1xyXG4gIFx0XHRyZXR1cm4gdG9Cb3VuZHMoW1xyXG4gIFx0XHRcdHRoaXMucHJvamVjdChsYXRMbmdCb3VuZHMuZ2V0U291dGhXZXN0KCksIHpvb20pLl9zdWJ0cmFjdCh0b3BMZWZ0KSxcclxuICBcdFx0XHR0aGlzLnByb2plY3QobGF0TG5nQm91bmRzLmdldE5vcnRoV2VzdCgpLCB6b29tKS5fc3VidHJhY3QodG9wTGVmdCksXHJcbiAgXHRcdFx0dGhpcy5wcm9qZWN0KGxhdExuZ0JvdW5kcy5nZXRTb3V0aEVhc3QoKSwgem9vbSkuX3N1YnRyYWN0KHRvcExlZnQpLFxyXG4gIFx0XHRcdHRoaXMucHJvamVjdChsYXRMbmdCb3VuZHMuZ2V0Tm9ydGhFYXN0KCksIHpvb20pLl9zdWJ0cmFjdCh0b3BMZWZ0KVxyXG4gIFx0XHRdKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gbGF5ZXIgcG9pbnQgb2YgdGhlIGN1cnJlbnQgY2VudGVyXHJcbiAgXHRfZ2V0Q2VudGVyTGF5ZXJQb2ludDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5jb250YWluZXJQb2ludFRvTGF5ZXJQb2ludCh0aGlzLmdldFNpemUoKS5fZGl2aWRlQnkoMikpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBvZmZzZXQgb2YgdGhlIHNwZWNpZmllZCBwbGFjZSB0byB0aGUgY3VycmVudCBjZW50ZXIgaW4gcGl4ZWxzXHJcbiAgXHRfZ2V0Q2VudGVyT2Zmc2V0OiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLmxhdExuZ1RvTGF5ZXJQb2ludChsYXRsbmcpLnN1YnRyYWN0KHRoaXMuX2dldENlbnRlckxheWVyUG9pbnQoKSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIGFkanVzdCBjZW50ZXIgZm9yIHZpZXcgdG8gZ2V0IGluc2lkZSBib3VuZHNcclxuICBcdF9saW1pdENlbnRlcjogZnVuY3Rpb24gKGNlbnRlciwgem9vbSwgYm91bmRzKSB7XHJcblxyXG4gIFx0XHRpZiAoIWJvdW5kcykgeyByZXR1cm4gY2VudGVyOyB9XHJcblxyXG4gIFx0XHR2YXIgY2VudGVyUG9pbnQgPSB0aGlzLnByb2plY3QoY2VudGVyLCB6b29tKSxcclxuICBcdFx0ICAgIHZpZXdIYWxmID0gdGhpcy5nZXRTaXplKCkuZGl2aWRlQnkoMiksXHJcbiAgXHRcdCAgICB2aWV3Qm91bmRzID0gbmV3IEJvdW5kcyhjZW50ZXJQb2ludC5zdWJ0cmFjdCh2aWV3SGFsZiksIGNlbnRlclBvaW50LmFkZCh2aWV3SGFsZikpLFxyXG4gIFx0XHQgICAgb2Zmc2V0ID0gdGhpcy5fZ2V0Qm91bmRzT2Zmc2V0KHZpZXdCb3VuZHMsIGJvdW5kcywgem9vbSk7XHJcblxyXG4gIFx0XHQvLyBJZiBvZmZzZXQgaXMgbGVzcyB0aGFuIGEgcGl4ZWwsIGlnbm9yZS5cclxuICBcdFx0Ly8gVGhpcyBwcmV2ZW50cyB1bnN0YWJsZSBwcm9qZWN0aW9ucyBmcm9tIGdldHRpbmcgaW50b1xyXG4gIFx0XHQvLyBhbiBpbmZpbml0ZSBsb29wIG9mIHRpbnkgb2Zmc2V0cy5cclxuICBcdFx0aWYgKE1hdGguYWJzKG9mZnNldC54KSA8PSAxICYmIE1hdGguYWJzKG9mZnNldC55KSA8PSAxKSB7XHJcbiAgXHRcdFx0cmV0dXJuIGNlbnRlcjtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0cmV0dXJuIHRoaXMudW5wcm9qZWN0KGNlbnRlclBvaW50LmFkZChvZmZzZXQpLCB6b29tKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gYWRqdXN0IG9mZnNldCBmb3IgdmlldyB0byBnZXQgaW5zaWRlIGJvdW5kc1xyXG4gIFx0X2xpbWl0T2Zmc2V0OiBmdW5jdGlvbiAob2Zmc2V0LCBib3VuZHMpIHtcclxuICBcdFx0aWYgKCFib3VuZHMpIHsgcmV0dXJuIG9mZnNldDsgfVxyXG5cclxuICBcdFx0dmFyIHZpZXdCb3VuZHMgPSB0aGlzLmdldFBpeGVsQm91bmRzKCksXHJcbiAgXHRcdCAgICBuZXdCb3VuZHMgPSBuZXcgQm91bmRzKHZpZXdCb3VuZHMubWluLmFkZChvZmZzZXQpLCB2aWV3Qm91bmRzLm1heC5hZGQob2Zmc2V0KSk7XHJcblxyXG4gIFx0XHRyZXR1cm4gb2Zmc2V0LmFkZCh0aGlzLl9nZXRCb3VuZHNPZmZzZXQobmV3Qm91bmRzLCBib3VuZHMpKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gcmV0dXJucyBvZmZzZXQgbmVlZGVkIGZvciBweEJvdW5kcyB0byBnZXQgaW5zaWRlIG1heEJvdW5kcyBhdCBhIHNwZWNpZmllZCB6b29tXHJcbiAgXHRfZ2V0Qm91bmRzT2Zmc2V0OiBmdW5jdGlvbiAocHhCb3VuZHMsIG1heEJvdW5kcywgem9vbSkge1xyXG4gIFx0XHR2YXIgcHJvamVjdGVkTWF4Qm91bmRzID0gdG9Cb3VuZHMoXHJcbiAgXHRcdCAgICAgICAgdGhpcy5wcm9qZWN0KG1heEJvdW5kcy5nZXROb3J0aEVhc3QoKSwgem9vbSksXHJcbiAgXHRcdCAgICAgICAgdGhpcy5wcm9qZWN0KG1heEJvdW5kcy5nZXRTb3V0aFdlc3QoKSwgem9vbSlcclxuICBcdFx0ICAgICksXHJcbiAgXHRcdCAgICBtaW5PZmZzZXQgPSBwcm9qZWN0ZWRNYXhCb3VuZHMubWluLnN1YnRyYWN0KHB4Qm91bmRzLm1pbiksXHJcbiAgXHRcdCAgICBtYXhPZmZzZXQgPSBwcm9qZWN0ZWRNYXhCb3VuZHMubWF4LnN1YnRyYWN0KHB4Qm91bmRzLm1heCksXHJcblxyXG4gIFx0XHQgICAgZHggPSB0aGlzLl9yZWJvdW5kKG1pbk9mZnNldC54LCAtbWF4T2Zmc2V0LngpLFxyXG4gIFx0XHQgICAgZHkgPSB0aGlzLl9yZWJvdW5kKG1pbk9mZnNldC55LCAtbWF4T2Zmc2V0LnkpO1xyXG5cclxuICBcdFx0cmV0dXJuIG5ldyBQb2ludChkeCwgZHkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfcmVib3VuZDogZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XHJcbiAgXHRcdHJldHVybiBsZWZ0ICsgcmlnaHQgPiAwID9cclxuICBcdFx0XHRNYXRoLnJvdW5kKGxlZnQgLSByaWdodCkgLyAyIDpcclxuICBcdFx0XHRNYXRoLm1heCgwLCBNYXRoLmNlaWwobGVmdCkpIC0gTWF0aC5tYXgoMCwgTWF0aC5mbG9vcihyaWdodCkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfbGltaXRab29tOiBmdW5jdGlvbiAoem9vbSkge1xyXG4gIFx0XHR2YXIgbWluID0gdGhpcy5nZXRNaW5ab29tKCksXHJcbiAgXHRcdCAgICBtYXggPSB0aGlzLmdldE1heFpvb20oKSxcclxuICBcdFx0ICAgIHNuYXAgPSBCcm93c2VyLmFueTNkID8gdGhpcy5vcHRpb25zLnpvb21TbmFwIDogMTtcclxuICBcdFx0aWYgKHNuYXApIHtcclxuICBcdFx0XHR6b29tID0gTWF0aC5yb3VuZCh6b29tIC8gc25hcCkgKiBzbmFwO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiBNYXRoLm1heChtaW4sIE1hdGgubWluKG1heCwgem9vbSkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfb25QYW5UcmFuc2l0aW9uU3RlcDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR0aGlzLmZpcmUoJ21vdmUnKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X29uUGFuVHJhbnNpdGlvbkVuZDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZW1vdmVDbGFzcyh0aGlzLl9tYXBQYW5lLCAnbGVhZmxldC1wYW4tYW5pbScpO1xyXG4gIFx0XHR0aGlzLmZpcmUoJ21vdmVlbmQnKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X3RyeUFuaW1hdGVkUGFuOiBmdW5jdGlvbiAoY2VudGVyLCBvcHRpb25zKSB7XHJcbiAgXHRcdC8vIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbmV3IGFuZCBjdXJyZW50IGNlbnRlcnMgaW4gcGl4ZWxzXHJcbiAgXHRcdHZhciBvZmZzZXQgPSB0aGlzLl9nZXRDZW50ZXJPZmZzZXQoY2VudGVyKS5fdHJ1bmMoKTtcclxuXHJcbiAgXHRcdC8vIGRvbid0IGFuaW1hdGUgdG9vIGZhciB1bmxlc3MgYW5pbWF0ZTogdHJ1ZSBzcGVjaWZpZWQgaW4gb3B0aW9uc1xyXG4gIFx0XHRpZiAoKG9wdGlvbnMgJiYgb3B0aW9ucy5hbmltYXRlKSAhPT0gdHJ1ZSAmJiAhdGhpcy5nZXRTaXplKCkuY29udGFpbnMob2Zmc2V0KSkgeyByZXR1cm4gZmFsc2U7IH1cclxuXHJcbiAgXHRcdHRoaXMucGFuQnkob2Zmc2V0LCBvcHRpb25zKTtcclxuXHJcbiAgXHRcdHJldHVybiB0cnVlO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfY3JlYXRlQW5pbVByb3h5OiBmdW5jdGlvbiAoKSB7XHJcblxyXG4gIFx0XHR2YXIgcHJveHkgPSB0aGlzLl9wcm94eSA9IGNyZWF0ZSQxKCdkaXYnLCAnbGVhZmxldC1wcm94eSBsZWFmbGV0LXpvb20tYW5pbWF0ZWQnKTtcclxuICBcdFx0dGhpcy5fcGFuZXMubWFwUGFuZS5hcHBlbmRDaGlsZChwcm94eSk7XHJcblxyXG4gIFx0XHR0aGlzLm9uKCd6b29tYW5pbScsIGZ1bmN0aW9uIChlKSB7XHJcbiAgXHRcdFx0dmFyIHByb3AgPSBUUkFOU0ZPUk0sXHJcbiAgXHRcdFx0ICAgIHRyYW5zZm9ybSA9IHRoaXMuX3Byb3h5LnN0eWxlW3Byb3BdO1xyXG5cclxuICBcdFx0XHRzZXRUcmFuc2Zvcm0odGhpcy5fcHJveHksIHRoaXMucHJvamVjdChlLmNlbnRlciwgZS56b29tKSwgdGhpcy5nZXRab29tU2NhbGUoZS56b29tLCAxKSk7XHJcblxyXG4gIFx0XHRcdC8vIHdvcmthcm91bmQgZm9yIGNhc2Ugd2hlbiB0cmFuc2Zvcm0gaXMgdGhlIHNhbWUgYW5kIHNvIHRyYW5zaXRpb25lbmQgZXZlbnQgaXMgbm90IGZpcmVkXHJcbiAgXHRcdFx0aWYgKHRyYW5zZm9ybSA9PT0gdGhpcy5fcHJveHkuc3R5bGVbcHJvcF0gJiYgdGhpcy5fYW5pbWF0aW5nWm9vbSkge1xyXG4gIFx0XHRcdFx0dGhpcy5fb25ab29tVHJhbnNpdGlvbkVuZCgpO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fSwgdGhpcyk7XHJcblxyXG4gIFx0XHR0aGlzLm9uKCdsb2FkIG1vdmVlbmQnLCB0aGlzLl9hbmltTW92ZUVuZCwgdGhpcyk7XHJcblxyXG4gIFx0XHR0aGlzLl9vbigndW5sb2FkJywgdGhpcy5fZGVzdHJveUFuaW1Qcm94eSwgdGhpcyk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9kZXN0cm95QW5pbVByb3h5OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJlbW92ZSh0aGlzLl9wcm94eSk7XHJcbiAgXHRcdHRoaXMub2ZmKCdsb2FkIG1vdmVlbmQnLCB0aGlzLl9hbmltTW92ZUVuZCwgdGhpcyk7XHJcbiAgXHRcdGRlbGV0ZSB0aGlzLl9wcm94eTtcclxuICBcdH0sXHJcblxyXG4gIFx0X2FuaW1Nb3ZlRW5kOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHZhciBjID0gdGhpcy5nZXRDZW50ZXIoKSxcclxuICBcdFx0ICAgIHogPSB0aGlzLmdldFpvb20oKTtcclxuICBcdFx0c2V0VHJhbnNmb3JtKHRoaXMuX3Byb3h5LCB0aGlzLnByb2plY3QoYywgeiksIHRoaXMuZ2V0Wm9vbVNjYWxlKHosIDEpKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X2NhdGNoVHJhbnNpdGlvbkVuZDogZnVuY3Rpb24gKGUpIHtcclxuICBcdFx0aWYgKHRoaXMuX2FuaW1hdGluZ1pvb20gJiYgZS5wcm9wZXJ0eU5hbWUuaW5kZXhPZigndHJhbnNmb3JtJykgPj0gMCkge1xyXG4gIFx0XHRcdHRoaXMuX29uWm9vbVRyYW5zaXRpb25FbmQoKTtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHRfbm90aGluZ1RvQW5pbWF0ZTogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gIXRoaXMuX2NvbnRhaW5lci5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCdsZWFmbGV0LXpvb20tYW5pbWF0ZWQnKS5sZW5ndGg7XHJcbiAgXHR9LFxyXG5cclxuICBcdF90cnlBbmltYXRlZFpvb206IGZ1bmN0aW9uIChjZW50ZXIsIHpvb20sIG9wdGlvbnMpIHtcclxuXHJcbiAgXHRcdGlmICh0aGlzLl9hbmltYXRpbmdab29tKSB7IHJldHVybiB0cnVlOyB9XHJcblxyXG4gIFx0XHRvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcclxuXHJcbiAgXHRcdC8vIGRvbid0IGFuaW1hdGUgaWYgZGlzYWJsZWQsIG5vdCBzdXBwb3J0ZWQgb3Igem9vbSBkaWZmZXJlbmNlIGlzIHRvbyBsYXJnZVxyXG4gIFx0XHRpZiAoIXRoaXMuX3pvb21BbmltYXRlZCB8fCBvcHRpb25zLmFuaW1hdGUgPT09IGZhbHNlIHx8IHRoaXMuX25vdGhpbmdUb0FuaW1hdGUoKSB8fFxyXG4gIFx0XHQgICAgICAgIE1hdGguYWJzKHpvb20gLSB0aGlzLl96b29tKSA+IHRoaXMub3B0aW9ucy56b29tQW5pbWF0aW9uVGhyZXNob2xkKSB7IHJldHVybiBmYWxzZTsgfVxyXG5cclxuICBcdFx0Ly8gb2Zmc2V0IGlzIHRoZSBwaXhlbCBjb29yZHMgb2YgdGhlIHpvb20gb3JpZ2luIHJlbGF0aXZlIHRvIHRoZSBjdXJyZW50IGNlbnRlclxyXG4gIFx0XHR2YXIgc2NhbGUgPSB0aGlzLmdldFpvb21TY2FsZSh6b29tKSxcclxuICBcdFx0ICAgIG9mZnNldCA9IHRoaXMuX2dldENlbnRlck9mZnNldChjZW50ZXIpLl9kaXZpZGVCeSgxIC0gMSAvIHNjYWxlKTtcclxuXHJcbiAgXHRcdC8vIGRvbid0IGFuaW1hdGUgaWYgdGhlIHpvb20gb3JpZ2luIGlzbid0IHdpdGhpbiBvbmUgc2NyZWVuIGZyb20gdGhlIGN1cnJlbnQgY2VudGVyLCB1bmxlc3MgZm9yY2VkXHJcbiAgXHRcdGlmIChvcHRpb25zLmFuaW1hdGUgIT09IHRydWUgJiYgIXRoaXMuZ2V0U2l6ZSgpLmNvbnRhaW5zKG9mZnNldCkpIHsgcmV0dXJuIGZhbHNlOyB9XHJcblxyXG4gIFx0XHRyZXF1ZXN0QW5pbUZyYW1lKGZ1bmN0aW9uICgpIHtcclxuICBcdFx0XHR0aGlzXHJcbiAgXHRcdFx0ICAgIC5fbW92ZVN0YXJ0KHRydWUsIG9wdGlvbnMubm9Nb3ZlU3RhcnQgfHwgZmFsc2UpXHJcbiAgXHRcdFx0ICAgIC5fYW5pbWF0ZVpvb20oY2VudGVyLCB6b29tLCB0cnVlKTtcclxuICBcdFx0fSwgdGhpcyk7XHJcblxyXG4gIFx0XHRyZXR1cm4gdHJ1ZTtcclxuICBcdH0sXHJcblxyXG4gIFx0X2FuaW1hdGVab29tOiBmdW5jdGlvbiAoY2VudGVyLCB6b29tLCBzdGFydEFuaW0sIG5vVXBkYXRlKSB7XHJcbiAgXHRcdGlmICghdGhpcy5fbWFwUGFuZSkgeyByZXR1cm47IH1cclxuXHJcbiAgXHRcdGlmIChzdGFydEFuaW0pIHtcclxuICBcdFx0XHR0aGlzLl9hbmltYXRpbmdab29tID0gdHJ1ZTtcclxuXHJcbiAgXHRcdFx0Ly8gcmVtZW1iZXIgd2hhdCBjZW50ZXIvem9vbSB0byBzZXQgYWZ0ZXIgYW5pbWF0aW9uXHJcbiAgXHRcdFx0dGhpcy5fYW5pbWF0ZVRvQ2VudGVyID0gY2VudGVyO1xyXG4gIFx0XHRcdHRoaXMuX2FuaW1hdGVUb1pvb20gPSB6b29tO1xyXG5cclxuICBcdFx0XHRhZGRDbGFzcyh0aGlzLl9tYXBQYW5lLCAnbGVhZmxldC16b29tLWFuaW0nKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gQHNlY3Rpb24gT3RoZXIgRXZlbnRzXHJcbiAgXHRcdC8vIEBldmVudCB6b29tYW5pbTogWm9vbUFuaW1FdmVudFxyXG4gIFx0XHQvLyBGaXJlZCBhdCBsZWFzdCBvbmNlIHBlciB6b29tIGFuaW1hdGlvbi4gRm9yIGNvbnRpbnVvdXMgem9vbSwgbGlrZSBwaW5jaCB6b29taW5nLCBmaXJlZCBvbmNlIHBlciBmcmFtZSBkdXJpbmcgem9vbS5cclxuICBcdFx0dGhpcy5maXJlKCd6b29tYW5pbScsIHtcclxuICBcdFx0XHRjZW50ZXI6IGNlbnRlcixcclxuICBcdFx0XHR6b29tOiB6b29tLFxyXG4gIFx0XHRcdG5vVXBkYXRlOiBub1VwZGF0ZVxyXG4gIFx0XHR9KTtcclxuXHJcbiAgXHRcdGlmICghdGhpcy5fdGVtcEZpcmVab29tRXZlbnQpIHtcclxuICBcdFx0XHR0aGlzLl90ZW1wRmlyZVpvb21FdmVudCA9IHRoaXMuX3pvb20gIT09IHRoaXMuX2FuaW1hdGVUb1pvb207XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX21vdmUodGhpcy5fYW5pbWF0ZVRvQ2VudGVyLCB0aGlzLl9hbmltYXRlVG9ab29tLCB1bmRlZmluZWQsIHRydWUpO1xyXG5cclxuICBcdFx0Ly8gV29yayBhcm91bmQgd2Via2l0IG5vdCBmaXJpbmcgJ3RyYW5zaXRpb25lbmQnLCBzZWUgaHR0cHM6Ly9naXRodWIuY29tL0xlYWZsZXQvTGVhZmxldC9pc3N1ZXMvMzY4OSwgMjY5M1xyXG4gIFx0XHRzZXRUaW1lb3V0KGJpbmQodGhpcy5fb25ab29tVHJhbnNpdGlvbkVuZCwgdGhpcyksIDI1MCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9vblpvb21UcmFuc2l0aW9uRW5kOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICghdGhpcy5fYW5pbWF0aW5nWm9vbSkgeyByZXR1cm47IH1cclxuXHJcbiAgXHRcdGlmICh0aGlzLl9tYXBQYW5lKSB7XHJcbiAgXHRcdFx0cmVtb3ZlQ2xhc3ModGhpcy5fbWFwUGFuZSwgJ2xlYWZsZXQtem9vbS1hbmltJyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX2FuaW1hdGluZ1pvb20gPSBmYWxzZTtcclxuXHJcbiAgXHRcdHRoaXMuX21vdmUodGhpcy5fYW5pbWF0ZVRvQ2VudGVyLCB0aGlzLl9hbmltYXRlVG9ab29tLCB1bmRlZmluZWQsIHRydWUpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX3RlbXBGaXJlWm9vbUV2ZW50KSB7XHJcbiAgXHRcdFx0dGhpcy5maXJlKCd6b29tJyk7XHJcbiAgXHRcdH1cclxuICBcdFx0ZGVsZXRlIHRoaXMuX3RlbXBGaXJlWm9vbUV2ZW50O1xyXG5cclxuICBcdFx0dGhpcy5maXJlKCdtb3ZlJyk7XHJcblxyXG4gIFx0XHR0aGlzLl9tb3ZlRW5kKHRydWUpO1xyXG4gIFx0fVxyXG4gIH0pO1xyXG5cclxuICAvLyBAc2VjdGlvblxyXG5cclxuICAvLyBAZmFjdG9yeSBMLm1hcChpZDogU3RyaW5nLCBvcHRpb25zPzogTWFwIG9wdGlvbnMpXHJcbiAgLy8gSW5zdGFudGlhdGVzIGEgbWFwIG9iamVjdCBnaXZlbiB0aGUgRE9NIElEIG9mIGEgYDxkaXY+YCBlbGVtZW50XHJcbiAgLy8gYW5kIG9wdGlvbmFsbHkgYW4gb2JqZWN0IGxpdGVyYWwgd2l0aCBgTWFwIG9wdGlvbnNgLlxyXG4gIC8vXHJcbiAgLy8gQGFsdGVybmF0aXZlXHJcbiAgLy8gQGZhY3RvcnkgTC5tYXAoZWw6IEhUTUxFbGVtZW50LCBvcHRpb25zPzogTWFwIG9wdGlvbnMpXHJcbiAgLy8gSW5zdGFudGlhdGVzIGEgbWFwIG9iamVjdCBnaXZlbiBhbiBpbnN0YW5jZSBvZiBhIGA8ZGl2PmAgSFRNTCBlbGVtZW50XHJcbiAgLy8gYW5kIG9wdGlvbmFsbHkgYW4gb2JqZWN0IGxpdGVyYWwgd2l0aCBgTWFwIG9wdGlvbnNgLlxyXG4gIGZ1bmN0aW9uIGNyZWF0ZU1hcChpZCwgb3B0aW9ucykge1xyXG4gIFx0cmV0dXJuIG5ldyBNYXAoaWQsIG9wdGlvbnMpO1xyXG4gIH1cblxuICAvKlxyXG4gICAqIEBjbGFzcyBDb250cm9sXHJcbiAgICogQGFrYSBMLkNvbnRyb2xcclxuICAgKiBAaW5oZXJpdHMgQ2xhc3NcclxuICAgKlxyXG4gICAqIEwuQ29udHJvbCBpcyBhIGJhc2UgY2xhc3MgZm9yIGltcGxlbWVudGluZyBtYXAgY29udHJvbHMuIEhhbmRsZXMgcG9zaXRpb25pbmcuXHJcbiAgICogQWxsIG90aGVyIGNvbnRyb2xzIGV4dGVuZCBmcm9tIHRoaXMgY2xhc3MuXHJcbiAgICovXHJcblxyXG4gIHZhciBDb250cm9sID0gQ2xhc3MuZXh0ZW5kKHtcclxuICBcdC8vIEBzZWN0aW9uXHJcbiAgXHQvLyBAYWthIENvbnRyb2wgT3B0aW9uc1xyXG4gIFx0b3B0aW9uczoge1xyXG4gIFx0XHQvLyBAb3B0aW9uIHBvc2l0aW9uOiBTdHJpbmcgPSAndG9wcmlnaHQnXHJcbiAgXHRcdC8vIFRoZSBwb3NpdGlvbiBvZiB0aGUgY29udHJvbCAob25lIG9mIHRoZSBtYXAgY29ybmVycykuIFBvc3NpYmxlIHZhbHVlcyBhcmUgYCd0b3BsZWZ0J2AsXHJcbiAgXHRcdC8vIGAndG9wcmlnaHQnYCwgYCdib3R0b21sZWZ0J2Agb3IgYCdib3R0b21yaWdodCdgXHJcbiAgXHRcdHBvc2l0aW9uOiAndG9wcmlnaHQnXHJcbiAgXHR9LFxyXG5cclxuICBcdGluaXRpYWxpemU6IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcbiAgXHRcdHNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8qIEBzZWN0aW9uXHJcbiAgXHQgKiBDbGFzc2VzIGV4dGVuZGluZyBMLkNvbnRyb2wgd2lsbCBpbmhlcml0IHRoZSBmb2xsb3dpbmcgbWV0aG9kczpcclxuICBcdCAqXHJcbiAgXHQgKiBAbWV0aG9kIGdldFBvc2l0aW9uOiBzdHJpbmdcclxuICBcdCAqIFJldHVybnMgdGhlIHBvc2l0aW9uIG9mIHRoZSBjb250cm9sLlxyXG4gIFx0ICovXHJcbiAgXHRnZXRQb3NpdGlvbjogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLnBvc2l0aW9uO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNldFBvc2l0aW9uKHBvc2l0aW9uOiBzdHJpbmcpOiB0aGlzXHJcbiAgXHQvLyBTZXRzIHRoZSBwb3NpdGlvbiBvZiB0aGUgY29udHJvbC5cclxuICBcdHNldFBvc2l0aW9uOiBmdW5jdGlvbiAocG9zaXRpb24pIHtcclxuICBcdFx0dmFyIG1hcCA9IHRoaXMuX21hcDtcclxuXHJcbiAgXHRcdGlmIChtYXApIHtcclxuICBcdFx0XHRtYXAucmVtb3ZlQ29udHJvbCh0aGlzKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5vcHRpb25zLnBvc2l0aW9uID0gcG9zaXRpb247XHJcblxyXG4gIFx0XHRpZiAobWFwKSB7XHJcbiAgXHRcdFx0bWFwLmFkZENvbnRyb2wodGhpcyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldENvbnRhaW5lcjogSFRNTEVsZW1lbnRcclxuICBcdC8vIFJldHVybnMgdGhlIEhUTUxFbGVtZW50IHRoYXQgY29udGFpbnMgdGhlIGNvbnRyb2wuXHJcbiAgXHRnZXRDb250YWluZXI6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuX2NvbnRhaW5lcjtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBhZGRUbyhtYXA6IE1hcCk6IHRoaXNcclxuICBcdC8vIEFkZHMgdGhlIGNvbnRyb2wgdG8gdGhlIGdpdmVuIG1hcC5cclxuICBcdGFkZFRvOiBmdW5jdGlvbiAobWFwKSB7XHJcbiAgXHRcdHRoaXMucmVtb3ZlKCk7XHJcbiAgXHRcdHRoaXMuX21hcCA9IG1hcDtcclxuXHJcbiAgXHRcdHZhciBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXIgPSB0aGlzLm9uQWRkKG1hcCksXHJcbiAgXHRcdCAgICBwb3MgPSB0aGlzLmdldFBvc2l0aW9uKCksXHJcbiAgXHRcdCAgICBjb3JuZXIgPSBtYXAuX2NvbnRyb2xDb3JuZXJzW3Bvc107XHJcblxyXG4gIFx0XHRhZGRDbGFzcyhjb250YWluZXIsICdsZWFmbGV0LWNvbnRyb2wnKTtcclxuXHJcbiAgXHRcdGlmIChwb3MuaW5kZXhPZignYm90dG9tJykgIT09IC0xKSB7XHJcbiAgXHRcdFx0Y29ybmVyLmluc2VydEJlZm9yZShjb250YWluZXIsIGNvcm5lci5maXJzdENoaWxkKTtcclxuICBcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRjb3JuZXIuYXBwZW5kQ2hpbGQoY29udGFpbmVyKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5fbWFwLm9uKCd1bmxvYWQnLCB0aGlzLnJlbW92ZSwgdGhpcyk7XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCByZW1vdmU6IHRoaXNcclxuICBcdC8vIFJlbW92ZXMgdGhlIGNvbnRyb2wgZnJvbSB0aGUgbWFwIGl0IGlzIGN1cnJlbnRseSBhY3RpdmUgb24uXHJcbiAgXHRyZW1vdmU6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKCF0aGlzLl9tYXApIHtcclxuICBcdFx0XHRyZXR1cm4gdGhpcztcclxuICBcdFx0fVxyXG5cclxuICBcdFx0cmVtb3ZlKHRoaXMuX2NvbnRhaW5lcik7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5vblJlbW92ZSkge1xyXG4gIFx0XHRcdHRoaXMub25SZW1vdmUodGhpcy5fbWFwKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5fbWFwLm9mZigndW5sb2FkJywgdGhpcy5yZW1vdmUsIHRoaXMpO1xyXG4gIFx0XHR0aGlzLl9tYXAgPSBudWxsO1xyXG5cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9yZWZvY3VzT25NYXA6IGZ1bmN0aW9uIChlKSB7XHJcbiAgXHRcdC8vIGlmIG1hcCBleGlzdHMgYW5kIGV2ZW50IGlzIG5vdCBhIGtleWJvYXJkIGV2ZW50XHJcbiAgXHRcdGlmICh0aGlzLl9tYXAgJiYgZSAmJiBlLnNjcmVlblggPiAwICYmIGUuc2NyZWVuWSA+IDApIHtcclxuICBcdFx0XHR0aGlzLl9tYXAuZ2V0Q29udGFpbmVyKCkuZm9jdXMoKTtcclxuICBcdFx0fVxyXG4gIFx0fVxyXG4gIH0pO1xyXG5cclxuICB2YXIgY29udHJvbCA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcbiAgXHRyZXR1cm4gbmV3IENvbnRyb2wob3B0aW9ucyk7XHJcbiAgfTtcclxuXHJcbiAgLyogQHNlY3Rpb24gRXh0ZW5zaW9uIG1ldGhvZHNcclxuICAgKiBAdW5pbmhlcml0YWJsZVxyXG4gICAqXHJcbiAgICogRXZlcnkgY29udHJvbCBzaG91bGQgZXh0ZW5kIGZyb20gYEwuQ29udHJvbGAgYW5kIChyZS0paW1wbGVtZW50IHRoZSBmb2xsb3dpbmcgbWV0aG9kcy5cclxuICAgKlxyXG4gICAqIEBtZXRob2Qgb25BZGQobWFwOiBNYXApOiBIVE1MRWxlbWVudFxyXG4gICAqIFNob3VsZCByZXR1cm4gdGhlIGNvbnRhaW5lciBET00gZWxlbWVudCBmb3IgdGhlIGNvbnRyb2wgYW5kIGFkZCBsaXN0ZW5lcnMgb24gcmVsZXZhbnQgbWFwIGV2ZW50cy4gQ2FsbGVkIG9uIFtgY29udHJvbC5hZGRUbyhtYXApYF0oI2NvbnRyb2wtYWRkVG8pLlxyXG4gICAqXHJcbiAgICogQG1ldGhvZCBvblJlbW92ZShtYXA6IE1hcClcclxuICAgKiBPcHRpb25hbCBtZXRob2QuIFNob3VsZCBjb250YWluIGFsbCBjbGVhbiB1cCBjb2RlIHRoYXQgcmVtb3ZlcyB0aGUgbGlzdGVuZXJzIHByZXZpb3VzbHkgYWRkZWQgaW4gW2BvbkFkZGBdKCNjb250cm9sLW9uYWRkKS4gQ2FsbGVkIG9uIFtgY29udHJvbC5yZW1vdmUoKWBdKCNjb250cm9sLXJlbW92ZSkuXHJcbiAgICovXHJcblxyXG4gIC8qIEBuYW1lc3BhY2UgTWFwXHJcbiAgICogQHNlY3Rpb24gTWV0aG9kcyBmb3IgTGF5ZXJzIGFuZCBDb250cm9sc1xyXG4gICAqL1xyXG4gIE1hcC5pbmNsdWRlKHtcclxuICBcdC8vIEBtZXRob2QgYWRkQ29udHJvbChjb250cm9sOiBDb250cm9sKTogdGhpc1xyXG4gIFx0Ly8gQWRkcyB0aGUgZ2l2ZW4gY29udHJvbCB0byB0aGUgbWFwXHJcbiAgXHRhZGRDb250cm9sOiBmdW5jdGlvbiAoY29udHJvbCkge1xyXG4gIFx0XHRjb250cm9sLmFkZFRvKHRoaXMpO1xyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCByZW1vdmVDb250cm9sKGNvbnRyb2w6IENvbnRyb2wpOiB0aGlzXHJcbiAgXHQvLyBSZW1vdmVzIHRoZSBnaXZlbiBjb250cm9sIGZyb20gdGhlIG1hcFxyXG4gIFx0cmVtb3ZlQ29udHJvbDogZnVuY3Rpb24gKGNvbnRyb2wpIHtcclxuICBcdFx0Y29udHJvbC5yZW1vdmUoKTtcclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9pbml0Q29udHJvbFBvczogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR2YXIgY29ybmVycyA9IHRoaXMuX2NvbnRyb2xDb3JuZXJzID0ge30sXHJcbiAgXHRcdCAgICBsID0gJ2xlYWZsZXQtJyxcclxuICBcdFx0ICAgIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRyb2xDb250YWluZXIgPVxyXG4gIFx0XHQgICAgICAgICAgICBjcmVhdGUkMSgnZGl2JywgbCArICdjb250cm9sLWNvbnRhaW5lcicsIHRoaXMuX2NvbnRhaW5lcik7XHJcblxyXG4gIFx0XHRmdW5jdGlvbiBjcmVhdGVDb3JuZXIodlNpZGUsIGhTaWRlKSB7XHJcbiAgXHRcdFx0dmFyIGNsYXNzTmFtZSA9IGwgKyB2U2lkZSArICcgJyArIGwgKyBoU2lkZTtcclxuXHJcbiAgXHRcdFx0Y29ybmVyc1t2U2lkZSArIGhTaWRlXSA9IGNyZWF0ZSQxKCdkaXYnLCBjbGFzc05hbWUsIGNvbnRhaW5lcik7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGNyZWF0ZUNvcm5lcigndG9wJywgJ2xlZnQnKTtcclxuICBcdFx0Y3JlYXRlQ29ybmVyKCd0b3AnLCAncmlnaHQnKTtcclxuICBcdFx0Y3JlYXRlQ29ybmVyKCdib3R0b20nLCAnbGVmdCcpO1xyXG4gIFx0XHRjcmVhdGVDb3JuZXIoJ2JvdHRvbScsICdyaWdodCcpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfY2xlYXJDb250cm9sUG9zOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGZvciAodmFyIGkgaW4gdGhpcy5fY29udHJvbENvcm5lcnMpIHtcclxuICBcdFx0XHRyZW1vdmUodGhpcy5fY29udHJvbENvcm5lcnNbaV0pO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJlbW92ZSh0aGlzLl9jb250cm9sQ29udGFpbmVyKTtcclxuICBcdFx0ZGVsZXRlIHRoaXMuX2NvbnRyb2xDb3JuZXJzO1xyXG4gIFx0XHRkZWxldGUgdGhpcy5fY29udHJvbENvbnRhaW5lcjtcclxuICBcdH1cclxuICB9KTtcblxuICAvKlxyXG4gICAqIEBjbGFzcyBDb250cm9sLkxheWVyc1xyXG4gICAqIEBha2EgTC5Db250cm9sLkxheWVyc1xyXG4gICAqIEBpbmhlcml0cyBDb250cm9sXHJcbiAgICpcclxuICAgKiBUaGUgbGF5ZXJzIGNvbnRyb2wgZ2l2ZXMgdXNlcnMgdGhlIGFiaWxpdHkgdG8gc3dpdGNoIGJldHdlZW4gZGlmZmVyZW50IGJhc2UgbGF5ZXJzIGFuZCBzd2l0Y2ggb3ZlcmxheXMgb24vb2ZmIChjaGVjayBvdXQgdGhlIFtkZXRhaWxlZCBleGFtcGxlXShodHRwczovL2xlYWZsZXRqcy5jb20vZXhhbXBsZXMvbGF5ZXJzLWNvbnRyb2wvKSkuIEV4dGVuZHMgYENvbnRyb2xgLlxyXG4gICAqXHJcbiAgICogQGV4YW1wbGVcclxuICAgKlxyXG4gICAqIGBgYGpzXHJcbiAgICogdmFyIGJhc2VMYXllcnMgPSB7XHJcbiAgICogXHRcIk1hcGJveFwiOiBtYXBib3gsXHJcbiAgICogXHRcIk9wZW5TdHJlZXRNYXBcIjogb3NtXHJcbiAgICogfTtcclxuICAgKlxyXG4gICAqIHZhciBvdmVybGF5cyA9IHtcclxuICAgKiBcdFwiTWFya2VyXCI6IG1hcmtlcixcclxuICAgKiBcdFwiUm9hZHNcIjogcm9hZHNMYXllclxyXG4gICAqIH07XHJcbiAgICpcclxuICAgKiBMLmNvbnRyb2wubGF5ZXJzKGJhc2VMYXllcnMsIG92ZXJsYXlzKS5hZGRUbyhtYXApO1xyXG4gICAqIGBgYFxyXG4gICAqXHJcbiAgICogVGhlIGBiYXNlTGF5ZXJzYCBhbmQgYG92ZXJsYXlzYCBwYXJhbWV0ZXJzIGFyZSBvYmplY3QgbGl0ZXJhbHMgd2l0aCBsYXllciBuYW1lcyBhcyBrZXlzIGFuZCBgTGF5ZXJgIG9iamVjdHMgYXMgdmFsdWVzOlxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiB7XHJcbiAgICogICAgIFwiPHNvbWVOYW1lMT5cIjogbGF5ZXIxLFxyXG4gICAqICAgICBcIjxzb21lTmFtZTI+XCI6IGxheWVyMlxyXG4gICAqIH1cclxuICAgKiBgYGBcclxuICAgKlxyXG4gICAqIFRoZSBsYXllciBuYW1lcyBjYW4gY29udGFpbiBIVE1MLCB3aGljaCBhbGxvd3MgeW91IHRvIGFkZCBhZGRpdGlvbmFsIHN0eWxpbmcgdG8gdGhlIGl0ZW1zOlxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiB7XCI8aW1nIHNyYz0nbXktbGF5ZXItaWNvbicgLz4gPHNwYW4gY2xhc3M9J215LWxheWVyLWl0ZW0nPk15IExheWVyPC9zcGFuPlwiOiBteUxheWVyfVxyXG4gICAqIGBgYFxyXG4gICAqL1xyXG5cclxuICB2YXIgTGF5ZXJzID0gQ29udHJvbC5leHRlbmQoe1xyXG4gIFx0Ly8gQHNlY3Rpb25cclxuICBcdC8vIEBha2EgQ29udHJvbC5MYXllcnMgb3B0aW9uc1xyXG4gIFx0b3B0aW9uczoge1xyXG4gIFx0XHQvLyBAb3B0aW9uIGNvbGxhcHNlZDogQm9vbGVhbiA9IHRydWVcclxuICBcdFx0Ly8gSWYgYHRydWVgLCB0aGUgY29udHJvbCB3aWxsIGJlIGNvbGxhcHNlZCBpbnRvIGFuIGljb24gYW5kIGV4cGFuZGVkIG9uIG1vdXNlIGhvdmVyLCB0b3VjaCwgb3Iga2V5Ym9hcmQgYWN0aXZhdGlvbi5cclxuICBcdFx0Y29sbGFwc2VkOiB0cnVlLFxyXG4gIFx0XHRwb3NpdGlvbjogJ3RvcHJpZ2h0JyxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gYXV0b1pJbmRleDogQm9vbGVhbiA9IHRydWVcclxuICBcdFx0Ly8gSWYgYHRydWVgLCB0aGUgY29udHJvbCB3aWxsIGFzc2lnbiB6SW5kZXhlcyBpbiBpbmNyZWFzaW5nIG9yZGVyIHRvIGFsbCBvZiBpdHMgbGF5ZXJzIHNvIHRoYXQgdGhlIG9yZGVyIGlzIHByZXNlcnZlZCB3aGVuIHN3aXRjaGluZyB0aGVtIG9uL29mZi5cclxuICBcdFx0YXV0b1pJbmRleDogdHJ1ZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gaGlkZVNpbmdsZUJhc2U6IEJvb2xlYW4gPSBmYWxzZVxyXG4gIFx0XHQvLyBJZiBgdHJ1ZWAsIHRoZSBiYXNlIGxheWVycyBpbiB0aGUgY29udHJvbCB3aWxsIGJlIGhpZGRlbiB3aGVuIHRoZXJlIGlzIG9ubHkgb25lLlxyXG4gIFx0XHRoaWRlU2luZ2xlQmFzZTogZmFsc2UsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHNvcnRMYXllcnM6IEJvb2xlYW4gPSBmYWxzZVxyXG4gIFx0XHQvLyBXaGV0aGVyIHRvIHNvcnQgdGhlIGxheWVycy4gV2hlbiBgZmFsc2VgLCBsYXllcnMgd2lsbCBrZWVwIHRoZSBvcmRlclxyXG4gIFx0XHQvLyBpbiB3aGljaCB0aGV5IHdlcmUgYWRkZWQgdG8gdGhlIGNvbnRyb2wuXHJcbiAgXHRcdHNvcnRMYXllcnM6IGZhbHNlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBzb3J0RnVuY3Rpb246IEZ1bmN0aW9uID0gKlxyXG4gIFx0XHQvLyBBIFtjb21wYXJlIGZ1bmN0aW9uXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9BcnJheS9zb3J0KVxyXG4gIFx0XHQvLyB0aGF0IHdpbGwgYmUgdXNlZCBmb3Igc29ydGluZyB0aGUgbGF5ZXJzLCB3aGVuIGBzb3J0TGF5ZXJzYCBpcyBgdHJ1ZWAuXHJcbiAgXHRcdC8vIFRoZSBmdW5jdGlvbiByZWNlaXZlcyBib3RoIHRoZSBgTC5MYXllcmAgaW5zdGFuY2VzIGFuZCB0aGVpciBuYW1lcywgYXMgaW5cclxuICBcdFx0Ly8gYHNvcnRGdW5jdGlvbihsYXllckEsIGxheWVyQiwgbmFtZUEsIG5hbWVCKWAuXHJcbiAgXHRcdC8vIEJ5IGRlZmF1bHQsIGl0IHNvcnRzIGxheWVycyBhbHBoYWJldGljYWxseSBieSB0aGVpciBuYW1lLlxyXG4gIFx0XHRzb3J0RnVuY3Rpb246IGZ1bmN0aW9uIChsYXllckEsIGxheWVyQiwgbmFtZUEsIG5hbWVCKSB7XHJcbiAgXHRcdFx0cmV0dXJuIG5hbWVBIDwgbmFtZUIgPyAtMSA6IChuYW1lQiA8IG5hbWVBID8gMSA6IDApO1xyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdGluaXRpYWxpemU6IGZ1bmN0aW9uIChiYXNlTGF5ZXJzLCBvdmVybGF5cywgb3B0aW9ucykge1xyXG4gIFx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xyXG5cclxuICBcdFx0dGhpcy5fbGF5ZXJDb250cm9sSW5wdXRzID0gW107XHJcbiAgXHRcdHRoaXMuX2xheWVycyA9IFtdO1xyXG4gIFx0XHR0aGlzLl9sYXN0WkluZGV4ID0gMDtcclxuICBcdFx0dGhpcy5faGFuZGxpbmdDbGljayA9IGZhbHNlO1xyXG4gIFx0XHR0aGlzLl9wcmV2ZW50Q2xpY2sgPSBmYWxzZTtcclxuXHJcbiAgXHRcdGZvciAodmFyIGkgaW4gYmFzZUxheWVycykge1xyXG4gIFx0XHRcdHRoaXMuX2FkZExheWVyKGJhc2VMYXllcnNbaV0sIGkpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRmb3IgKGkgaW4gb3ZlcmxheXMpIHtcclxuICBcdFx0XHR0aGlzLl9hZGRMYXllcihvdmVybGF5c1tpXSwgaSwgdHJ1ZSk7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0b25BZGQ6IGZ1bmN0aW9uIChtYXApIHtcclxuICBcdFx0dGhpcy5faW5pdExheW91dCgpO1xyXG4gIFx0XHR0aGlzLl91cGRhdGUoKTtcclxuXHJcbiAgXHRcdHRoaXMuX21hcCA9IG1hcDtcclxuICBcdFx0bWFwLm9uKCd6b29tZW5kJywgdGhpcy5fY2hlY2tEaXNhYmxlZExheWVycywgdGhpcyk7XHJcblxyXG4gIFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2xheWVycy5sZW5ndGg7IGkrKykge1xyXG4gIFx0XHRcdHRoaXMuX2xheWVyc1tpXS5sYXllci5vbignYWRkIHJlbW92ZScsIHRoaXMuX29uTGF5ZXJDaGFuZ2UsIHRoaXMpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcy5fY29udGFpbmVyO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRhZGRUbzogZnVuY3Rpb24gKG1hcCkge1xyXG4gIFx0XHRDb250cm9sLnByb3RvdHlwZS5hZGRUby5jYWxsKHRoaXMsIG1hcCk7XHJcbiAgXHRcdC8vIFRyaWdnZXIgZXhwYW5kIGFmdGVyIExheWVycyBDb250cm9sIGhhcyBiZWVuIGluc2VydGVkIGludG8gRE9NIHNvIHRoYXQgaXMgbm93IGhhcyBhbiBhY3R1YWwgaGVpZ2h0LlxyXG4gIFx0XHRyZXR1cm4gdGhpcy5fZXhwYW5kSWZOb3RDb2xsYXBzZWQoKTtcclxuICBcdH0sXHJcblxyXG4gIFx0b25SZW1vdmU6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dGhpcy5fbWFwLm9mZignem9vbWVuZCcsIHRoaXMuX2NoZWNrRGlzYWJsZWRMYXllcnMsIHRoaXMpO1xyXG5cclxuICBcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9sYXllcnMubGVuZ3RoOyBpKyspIHtcclxuICBcdFx0XHR0aGlzLl9sYXllcnNbaV0ubGF5ZXIub2ZmKCdhZGQgcmVtb3ZlJywgdGhpcy5fb25MYXllckNoYW5nZSwgdGhpcyk7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBhZGRCYXNlTGF5ZXIobGF5ZXI6IExheWVyLCBuYW1lOiBTdHJpbmcpOiB0aGlzXHJcbiAgXHQvLyBBZGRzIGEgYmFzZSBsYXllciAocmFkaW8gYnV0dG9uIGVudHJ5KSB3aXRoIHRoZSBnaXZlbiBuYW1lIHRvIHRoZSBjb250cm9sLlxyXG4gIFx0YWRkQmFzZUxheWVyOiBmdW5jdGlvbiAobGF5ZXIsIG5hbWUpIHtcclxuICBcdFx0dGhpcy5fYWRkTGF5ZXIobGF5ZXIsIG5hbWUpO1xyXG4gIFx0XHRyZXR1cm4gKHRoaXMuX21hcCkgPyB0aGlzLl91cGRhdGUoKSA6IHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgYWRkT3ZlcmxheShsYXllcjogTGF5ZXIsIG5hbWU6IFN0cmluZyk6IHRoaXNcclxuICBcdC8vIEFkZHMgYW4gb3ZlcmxheSAoY2hlY2tib3ggZW50cnkpIHdpdGggdGhlIGdpdmVuIG5hbWUgdG8gdGhlIGNvbnRyb2wuXHJcbiAgXHRhZGRPdmVybGF5OiBmdW5jdGlvbiAobGF5ZXIsIG5hbWUpIHtcclxuICBcdFx0dGhpcy5fYWRkTGF5ZXIobGF5ZXIsIG5hbWUsIHRydWUpO1xyXG4gIFx0XHRyZXR1cm4gKHRoaXMuX21hcCkgPyB0aGlzLl91cGRhdGUoKSA6IHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgcmVtb3ZlTGF5ZXIobGF5ZXI6IExheWVyKTogdGhpc1xyXG4gIFx0Ly8gUmVtb3ZlIHRoZSBnaXZlbiBsYXllciBmcm9tIHRoZSBjb250cm9sLlxyXG4gIFx0cmVtb3ZlTGF5ZXI6IGZ1bmN0aW9uIChsYXllcikge1xyXG4gIFx0XHRsYXllci5vZmYoJ2FkZCByZW1vdmUnLCB0aGlzLl9vbkxheWVyQ2hhbmdlLCB0aGlzKTtcclxuXHJcbiAgXHRcdHZhciBvYmogPSB0aGlzLl9nZXRMYXllcihzdGFtcChsYXllcikpO1xyXG4gIFx0XHRpZiAob2JqKSB7XHJcbiAgXHRcdFx0dGhpcy5fbGF5ZXJzLnNwbGljZSh0aGlzLl9sYXllcnMuaW5kZXhPZihvYmopLCAxKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gKHRoaXMuX21hcCkgPyB0aGlzLl91cGRhdGUoKSA6IHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZXhwYW5kKCk6IHRoaXNcclxuICBcdC8vIEV4cGFuZCB0aGUgY29udHJvbCBjb250YWluZXIgaWYgY29sbGFwc2VkLlxyXG4gIFx0ZXhwYW5kOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGFkZENsYXNzKHRoaXMuX2NvbnRhaW5lciwgJ2xlYWZsZXQtY29udHJvbC1sYXllcnMtZXhwYW5kZWQnKTtcclxuICBcdFx0dGhpcy5fc2VjdGlvbi5zdHlsZS5oZWlnaHQgPSBudWxsO1xyXG4gIFx0XHR2YXIgYWNjZXB0YWJsZUhlaWdodCA9IHRoaXMuX21hcC5nZXRTaXplKCkueSAtICh0aGlzLl9jb250YWluZXIub2Zmc2V0VG9wICsgNTApO1xyXG4gIFx0XHRpZiAoYWNjZXB0YWJsZUhlaWdodCA8IHRoaXMuX3NlY3Rpb24uY2xpZW50SGVpZ2h0KSB7XHJcbiAgXHRcdFx0YWRkQ2xhc3ModGhpcy5fc2VjdGlvbiwgJ2xlYWZsZXQtY29udHJvbC1sYXllcnMtc2Nyb2xsYmFyJyk7XHJcbiAgXHRcdFx0dGhpcy5fc2VjdGlvbi5zdHlsZS5oZWlnaHQgPSBhY2NlcHRhYmxlSGVpZ2h0ICsgJ3B4JztcclxuICBcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRyZW1vdmVDbGFzcyh0aGlzLl9zZWN0aW9uLCAnbGVhZmxldC1jb250cm9sLWxheWVycy1zY3JvbGxiYXInKTtcclxuICBcdFx0fVxyXG4gIFx0XHR0aGlzLl9jaGVja0Rpc2FibGVkTGF5ZXJzKCk7XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGNvbGxhcHNlKCk6IHRoaXNcclxuICBcdC8vIENvbGxhcHNlIHRoZSBjb250cm9sIGNvbnRhaW5lciBpZiBleHBhbmRlZC5cclxuICBcdGNvbGxhcHNlOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJlbW92ZUNsYXNzKHRoaXMuX2NvbnRhaW5lciwgJ2xlYWZsZXQtY29udHJvbC1sYXllcnMtZXhwYW5kZWQnKTtcclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9pbml0TGF5b3V0OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHZhciBjbGFzc05hbWUgPSAnbGVhZmxldC1jb250cm9sLWxheWVycycsXHJcbiAgXHRcdCAgICBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXIgPSBjcmVhdGUkMSgnZGl2JywgY2xhc3NOYW1lKSxcclxuICBcdFx0ICAgIGNvbGxhcHNlZCA9IHRoaXMub3B0aW9ucy5jb2xsYXBzZWQ7XHJcblxyXG4gIFx0XHQvLyBtYWtlcyB0aGlzIHdvcmsgb24gSUUgdG91Y2ggZGV2aWNlcyBieSBzdG9wcGluZyBpdCBmcm9tIGZpcmluZyBhIG1vdXNlb3V0IGV2ZW50IHdoZW4gdGhlIHRvdWNoIGlzIHJlbGVhc2VkXHJcbiAgXHRcdGNvbnRhaW5lci5zZXRBdHRyaWJ1dGUoJ2FyaWEtaGFzcG9wdXAnLCB0cnVlKTtcclxuXHJcbiAgXHRcdGRpc2FibGVDbGlja1Byb3BhZ2F0aW9uKGNvbnRhaW5lcik7XHJcbiAgXHRcdGRpc2FibGVTY3JvbGxQcm9wYWdhdGlvbihjb250YWluZXIpO1xyXG5cclxuICBcdFx0dmFyIHNlY3Rpb24gPSB0aGlzLl9zZWN0aW9uID0gY3JlYXRlJDEoJ3NlY3Rpb24nLCBjbGFzc05hbWUgKyAnLWxpc3QnKTtcclxuXHJcbiAgXHRcdGlmIChjb2xsYXBzZWQpIHtcclxuICBcdFx0XHR0aGlzLl9tYXAub24oJ2NsaWNrJywgdGhpcy5jb2xsYXBzZSwgdGhpcyk7XHJcblxyXG4gIFx0XHRcdG9uKGNvbnRhaW5lciwge1xyXG4gIFx0XHRcdFx0bW91c2VlbnRlcjogdGhpcy5fZXhwYW5kU2FmZWx5LFxyXG4gIFx0XHRcdFx0bW91c2VsZWF2ZTogdGhpcy5jb2xsYXBzZVxyXG4gIFx0XHRcdH0sIHRoaXMpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgbGluayA9IHRoaXMuX2xheWVyc0xpbmsgPSBjcmVhdGUkMSgnYScsIGNsYXNzTmFtZSArICctdG9nZ2xlJywgY29udGFpbmVyKTtcclxuICBcdFx0bGluay5ocmVmID0gJyMnO1xyXG4gIFx0XHRsaW5rLnRpdGxlID0gJ0xheWVycyc7XHJcbiAgXHRcdGxpbmsuc2V0QXR0cmlidXRlKCdyb2xlJywgJ2J1dHRvbicpO1xyXG5cclxuICBcdFx0b24obGluaywge1xyXG4gIFx0XHRcdGtleWRvd246IGZ1bmN0aW9uIChlKSB7XHJcbiAgXHRcdFx0XHRpZiAoZS5rZXlDb2RlID09PSAxMykge1xyXG4gIFx0XHRcdFx0XHR0aGlzLl9leHBhbmRTYWZlbHkoKTtcclxuICBcdFx0XHRcdH1cclxuICBcdFx0XHR9LFxyXG4gIFx0XHRcdC8vIENlcnRhaW4gc2NyZWVuIHJlYWRlcnMgaW50ZXJjZXB0IHRoZSBrZXkgZXZlbnQgYW5kIGluc3RlYWQgc2VuZCBhIGNsaWNrIGV2ZW50XHJcbiAgXHRcdFx0Y2xpY2s6IGZ1bmN0aW9uIChlKSB7XHJcbiAgXHRcdFx0XHRwcmV2ZW50RGVmYXVsdChlKTtcclxuICBcdFx0XHRcdHRoaXMuX2V4cGFuZFNhZmVseSgpO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fSwgdGhpcyk7XHJcblxyXG4gIFx0XHRpZiAoIWNvbGxhcHNlZCkge1xyXG4gIFx0XHRcdHRoaXMuZXhwYW5kKCk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX2Jhc2VMYXllcnNMaXN0ID0gY3JlYXRlJDEoJ2RpdicsIGNsYXNzTmFtZSArICctYmFzZScsIHNlY3Rpb24pO1xyXG4gIFx0XHR0aGlzLl9zZXBhcmF0b3IgPSBjcmVhdGUkMSgnZGl2JywgY2xhc3NOYW1lICsgJy1zZXBhcmF0b3InLCBzZWN0aW9uKTtcclxuICBcdFx0dGhpcy5fb3ZlcmxheXNMaXN0ID0gY3JlYXRlJDEoJ2RpdicsIGNsYXNzTmFtZSArICctb3ZlcmxheXMnLCBzZWN0aW9uKTtcclxuXHJcbiAgXHRcdGNvbnRhaW5lci5hcHBlbmRDaGlsZChzZWN0aW9uKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X2dldExheWVyOiBmdW5jdGlvbiAoaWQpIHtcclxuICBcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9sYXllcnMubGVuZ3RoOyBpKyspIHtcclxuXHJcbiAgXHRcdFx0aWYgKHRoaXMuX2xheWVyc1tpXSAmJiBzdGFtcCh0aGlzLl9sYXllcnNbaV0ubGF5ZXIpID09PSBpZCkge1xyXG4gIFx0XHRcdFx0cmV0dXJuIHRoaXMuX2xheWVyc1tpXTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0X2FkZExheWVyOiBmdW5jdGlvbiAobGF5ZXIsIG5hbWUsIG92ZXJsYXkpIHtcclxuICBcdFx0aWYgKHRoaXMuX21hcCkge1xyXG4gIFx0XHRcdGxheWVyLm9uKCdhZGQgcmVtb3ZlJywgdGhpcy5fb25MYXllckNoYW5nZSwgdGhpcyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX2xheWVycy5wdXNoKHtcclxuICBcdFx0XHRsYXllcjogbGF5ZXIsXHJcbiAgXHRcdFx0bmFtZTogbmFtZSxcclxuICBcdFx0XHRvdmVybGF5OiBvdmVybGF5XHJcbiAgXHRcdH0pO1xyXG5cclxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5zb3J0TGF5ZXJzKSB7XHJcbiAgXHRcdFx0dGhpcy5fbGF5ZXJzLnNvcnQoYmluZChmdW5jdGlvbiAoYSwgYikge1xyXG4gIFx0XHRcdFx0cmV0dXJuIHRoaXMub3B0aW9ucy5zb3J0RnVuY3Rpb24oYS5sYXllciwgYi5sYXllciwgYS5uYW1lLCBiLm5hbWUpO1xyXG4gIFx0XHRcdH0sIHRoaXMpKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5hdXRvWkluZGV4ICYmIGxheWVyLnNldFpJbmRleCkge1xyXG4gIFx0XHRcdHRoaXMuX2xhc3RaSW5kZXgrKztcclxuICBcdFx0XHRsYXllci5zZXRaSW5kZXgodGhpcy5fbGFzdFpJbmRleCk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX2V4cGFuZElmTm90Q29sbGFwc2VkKCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF91cGRhdGU6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKCF0aGlzLl9jb250YWluZXIpIHsgcmV0dXJuIHRoaXM7IH1cclxuXHJcbiAgXHRcdGVtcHR5KHRoaXMuX2Jhc2VMYXllcnNMaXN0KTtcclxuICBcdFx0ZW1wdHkodGhpcy5fb3ZlcmxheXNMaXN0KTtcclxuXHJcbiAgXHRcdHRoaXMuX2xheWVyQ29udHJvbElucHV0cyA9IFtdO1xyXG4gIFx0XHR2YXIgYmFzZUxheWVyc1ByZXNlbnQsIG92ZXJsYXlzUHJlc2VudCwgaSwgb2JqLCBiYXNlTGF5ZXJzQ291bnQgPSAwO1xyXG5cclxuICBcdFx0Zm9yIChpID0gMDsgaSA8IHRoaXMuX2xheWVycy5sZW5ndGg7IGkrKykge1xyXG4gIFx0XHRcdG9iaiA9IHRoaXMuX2xheWVyc1tpXTtcclxuICBcdFx0XHR0aGlzLl9hZGRJdGVtKG9iaik7XHJcbiAgXHRcdFx0b3ZlcmxheXNQcmVzZW50ID0gb3ZlcmxheXNQcmVzZW50IHx8IG9iai5vdmVybGF5O1xyXG4gIFx0XHRcdGJhc2VMYXllcnNQcmVzZW50ID0gYmFzZUxheWVyc1ByZXNlbnQgfHwgIW9iai5vdmVybGF5O1xyXG4gIFx0XHRcdGJhc2VMYXllcnNDb3VudCArPSAhb2JqLm92ZXJsYXkgPyAxIDogMDtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gSGlkZSBiYXNlIGxheWVycyBzZWN0aW9uIGlmIHRoZXJlJ3Mgb25seSBvbmUgbGF5ZXIuXHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMuaGlkZVNpbmdsZUJhc2UpIHtcclxuICBcdFx0XHRiYXNlTGF5ZXJzUHJlc2VudCA9IGJhc2VMYXllcnNQcmVzZW50ICYmIGJhc2VMYXllcnNDb3VudCA+IDE7XHJcbiAgXHRcdFx0dGhpcy5fYmFzZUxheWVyc0xpc3Quc3R5bGUuZGlzcGxheSA9IGJhc2VMYXllcnNQcmVzZW50ID8gJycgOiAnbm9uZSc7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX3NlcGFyYXRvci5zdHlsZS5kaXNwbGF5ID0gb3ZlcmxheXNQcmVzZW50ICYmIGJhc2VMYXllcnNQcmVzZW50ID8gJycgOiAnbm9uZSc7XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0X29uTGF5ZXJDaGFuZ2U6IGZ1bmN0aW9uIChlKSB7XHJcbiAgXHRcdGlmICghdGhpcy5faGFuZGxpbmdDbGljaykge1xyXG4gIFx0XHRcdHRoaXMuX3VwZGF0ZSgpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgb2JqID0gdGhpcy5fZ2V0TGF5ZXIoc3RhbXAoZS50YXJnZXQpKTtcclxuXHJcbiAgXHRcdC8vIEBuYW1lc3BhY2UgTWFwXHJcbiAgXHRcdC8vIEBzZWN0aW9uIExheWVyIGV2ZW50c1xyXG4gIFx0XHQvLyBAZXZlbnQgYmFzZWxheWVyY2hhbmdlOiBMYXllcnNDb250cm9sRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgYmFzZSBsYXllciBpcyBjaGFuZ2VkIHRocm91Z2ggdGhlIFtsYXllcnMgY29udHJvbF0oI2NvbnRyb2wtbGF5ZXJzKS5cclxuICBcdFx0Ly8gQGV2ZW50IG92ZXJsYXlhZGQ6IExheWVyc0NvbnRyb2xFdmVudFxyXG4gIFx0XHQvLyBGaXJlZCB3aGVuIGFuIG92ZXJsYXkgaXMgc2VsZWN0ZWQgdGhyb3VnaCB0aGUgW2xheWVycyBjb250cm9sXSgjY29udHJvbC1sYXllcnMpLlxyXG4gIFx0XHQvLyBAZXZlbnQgb3ZlcmxheXJlbW92ZTogTGF5ZXJzQ29udHJvbEV2ZW50XHJcbiAgXHRcdC8vIEZpcmVkIHdoZW4gYW4gb3ZlcmxheSBpcyBkZXNlbGVjdGVkIHRocm91Z2ggdGhlIFtsYXllcnMgY29udHJvbF0oI2NvbnRyb2wtbGF5ZXJzKS5cclxuICBcdFx0Ly8gQG5hbWVzcGFjZSBDb250cm9sLkxheWVyc1xyXG4gIFx0XHR2YXIgdHlwZSA9IG9iai5vdmVybGF5ID9cclxuICBcdFx0XHQoZS50eXBlID09PSAnYWRkJyA/ICdvdmVybGF5YWRkJyA6ICdvdmVybGF5cmVtb3ZlJykgOlxyXG4gIFx0XHRcdChlLnR5cGUgPT09ICdhZGQnID8gJ2Jhc2VsYXllcmNoYW5nZScgOiBudWxsKTtcclxuXHJcbiAgXHRcdGlmICh0eXBlKSB7XHJcbiAgXHRcdFx0dGhpcy5fbWFwLmZpcmUodHlwZSwgb2JqKTtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBJRTcgYnVncyBvdXQgaWYgeW91IGNyZWF0ZSBhIHJhZGlvIGR5bmFtaWNhbGx5LCBzbyB5b3UgaGF2ZSB0byBkbyBpdCB0aGlzIGhhY2t5IHdheSAoc2VlIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8xMTkwNzkpXHJcbiAgXHRfY3JlYXRlUmFkaW9FbGVtZW50OiBmdW5jdGlvbiAobmFtZSwgY2hlY2tlZCkge1xyXG5cclxuICBcdFx0dmFyIHJhZGlvSHRtbCA9ICc8aW5wdXQgdHlwZT1cInJhZGlvXCIgY2xhc3M9XCJsZWFmbGV0LWNvbnRyb2wtbGF5ZXJzLXNlbGVjdG9yXCIgbmFtZT1cIicgK1xyXG4gIFx0XHRcdFx0bmFtZSArICdcIicgKyAoY2hlY2tlZCA/ICcgY2hlY2tlZD1cImNoZWNrZWRcIicgOiAnJykgKyAnLz4nO1xyXG5cclxuICBcdFx0dmFyIHJhZGlvRnJhZ21lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcclxuICBcdFx0cmFkaW9GcmFnbWVudC5pbm5lckhUTUwgPSByYWRpb0h0bWw7XHJcblxyXG4gIFx0XHRyZXR1cm4gcmFkaW9GcmFnbWVudC5maXJzdENoaWxkO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfYWRkSXRlbTogZnVuY3Rpb24gKG9iaikge1xyXG4gIFx0XHR2YXIgbGFiZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdsYWJlbCcpLFxyXG4gIFx0XHQgICAgY2hlY2tlZCA9IHRoaXMuX21hcC5oYXNMYXllcihvYmoubGF5ZXIpLFxyXG4gIFx0XHQgICAgaW5wdXQ7XHJcblxyXG4gIFx0XHRpZiAob2JqLm92ZXJsYXkpIHtcclxuICBcdFx0XHRpbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0Jyk7XHJcbiAgXHRcdFx0aW5wdXQudHlwZSA9ICdjaGVja2JveCc7XHJcbiAgXHRcdFx0aW5wdXQuY2xhc3NOYW1lID0gJ2xlYWZsZXQtY29udHJvbC1sYXllcnMtc2VsZWN0b3InO1xyXG4gIFx0XHRcdGlucHV0LmRlZmF1bHRDaGVja2VkID0gY2hlY2tlZDtcclxuICBcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRpbnB1dCA9IHRoaXMuX2NyZWF0ZVJhZGlvRWxlbWVudCgnbGVhZmxldC1iYXNlLWxheWVyc18nICsgc3RhbXAodGhpcyksIGNoZWNrZWQpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR0aGlzLl9sYXllckNvbnRyb2xJbnB1dHMucHVzaChpbnB1dCk7XHJcbiAgXHRcdGlucHV0LmxheWVySWQgPSBzdGFtcChvYmoubGF5ZXIpO1xyXG5cclxuICBcdFx0b24oaW5wdXQsICdjbGljaycsIHRoaXMuX29uSW5wdXRDbGljaywgdGhpcyk7XHJcblxyXG4gIFx0XHR2YXIgbmFtZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKTtcclxuICBcdFx0bmFtZS5pbm5lckhUTUwgPSAnICcgKyBvYmoubmFtZTtcclxuXHJcbiAgXHRcdC8vIEhlbHBzIGZyb20gcHJldmVudGluZyBsYXllciBjb250cm9sIGZsaWNrZXIgd2hlbiBjaGVja2JveGVzIGFyZSBkaXNhYmxlZFxyXG4gIFx0XHQvLyBodHRwczovL2dpdGh1Yi5jb20vTGVhZmxldC9MZWFmbGV0L2lzc3Vlcy8yNzcxXHJcbiAgXHRcdHZhciBob2xkZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyk7XHJcblxyXG4gIFx0XHRsYWJlbC5hcHBlbmRDaGlsZChob2xkZXIpO1xyXG4gIFx0XHRob2xkZXIuYXBwZW5kQ2hpbGQoaW5wdXQpO1xyXG4gIFx0XHRob2xkZXIuYXBwZW5kQ2hpbGQobmFtZSk7XHJcblxyXG4gIFx0XHR2YXIgY29udGFpbmVyID0gb2JqLm92ZXJsYXkgPyB0aGlzLl9vdmVybGF5c0xpc3QgOiB0aGlzLl9iYXNlTGF5ZXJzTGlzdDtcclxuICBcdFx0Y29udGFpbmVyLmFwcGVuZENoaWxkKGxhYmVsKTtcclxuXHJcbiAgXHRcdHRoaXMuX2NoZWNrRGlzYWJsZWRMYXllcnMoKTtcclxuICBcdFx0cmV0dXJuIGxhYmVsO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfb25JbnB1dENsaWNrOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdC8vIGV4cGFuZGluZyB0aGUgY29udHJvbCBvbiBtb2JpbGUgd2l0aCBhIGNsaWNrIGNhbiBjYXVzZSBhZGRpbmcgYSBsYXllciAtIHdlIGRvbid0IHdhbnQgdGhpc1xyXG4gIFx0XHRpZiAodGhpcy5fcHJldmVudENsaWNrKSB7XHJcbiAgXHRcdFx0cmV0dXJuO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgaW5wdXRzID0gdGhpcy5fbGF5ZXJDb250cm9sSW5wdXRzLFxyXG4gIFx0XHQgICAgaW5wdXQsIGxheWVyO1xyXG4gIFx0XHR2YXIgYWRkZWRMYXllcnMgPSBbXSxcclxuICBcdFx0ICAgIHJlbW92ZWRMYXllcnMgPSBbXTtcclxuXHJcbiAgXHRcdHRoaXMuX2hhbmRsaW5nQ2xpY2sgPSB0cnVlO1xyXG5cclxuICBcdFx0Zm9yICh2YXIgaSA9IGlucHV0cy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xyXG4gIFx0XHRcdGlucHV0ID0gaW5wdXRzW2ldO1xyXG4gIFx0XHRcdGxheWVyID0gdGhpcy5fZ2V0TGF5ZXIoaW5wdXQubGF5ZXJJZCkubGF5ZXI7XHJcblxyXG4gIFx0XHRcdGlmIChpbnB1dC5jaGVja2VkKSB7XHJcbiAgXHRcdFx0XHRhZGRlZExheWVycy5wdXNoKGxheWVyKTtcclxuICBcdFx0XHR9IGVsc2UgaWYgKCFpbnB1dC5jaGVja2VkKSB7XHJcbiAgXHRcdFx0XHRyZW1vdmVkTGF5ZXJzLnB1c2gobGF5ZXIpO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gQnVnZml4IGlzc3VlIDIzMTg6IFNob3VsZCByZW1vdmUgYWxsIG9sZCBsYXllcnMgYmVmb3JlIHJlYWRkaW5nIG5ldyBvbmVzXHJcbiAgXHRcdGZvciAoaSA9IDA7IGkgPCByZW1vdmVkTGF5ZXJzLmxlbmd0aDsgaSsrKSB7XHJcbiAgXHRcdFx0aWYgKHRoaXMuX21hcC5oYXNMYXllcihyZW1vdmVkTGF5ZXJzW2ldKSkge1xyXG4gIFx0XHRcdFx0dGhpcy5fbWFwLnJlbW92ZUxheWVyKHJlbW92ZWRMYXllcnNbaV0pO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG4gIFx0XHRmb3IgKGkgPSAwOyBpIDwgYWRkZWRMYXllcnMubGVuZ3RoOyBpKyspIHtcclxuICBcdFx0XHRpZiAoIXRoaXMuX21hcC5oYXNMYXllcihhZGRlZExheWVyc1tpXSkpIHtcclxuICBcdFx0XHRcdHRoaXMuX21hcC5hZGRMYXllcihhZGRlZExheWVyc1tpXSk7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR0aGlzLl9oYW5kbGluZ0NsaWNrID0gZmFsc2U7XHJcblxyXG4gIFx0XHR0aGlzLl9yZWZvY3VzT25NYXAoKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X2NoZWNrRGlzYWJsZWRMYXllcnM6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dmFyIGlucHV0cyA9IHRoaXMuX2xheWVyQ29udHJvbElucHV0cyxcclxuICBcdFx0ICAgIGlucHV0LFxyXG4gIFx0XHQgICAgbGF5ZXIsXHJcbiAgXHRcdCAgICB6b29tID0gdGhpcy5fbWFwLmdldFpvb20oKTtcclxuXHJcbiAgXHRcdGZvciAodmFyIGkgPSBpbnB1dHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcclxuICBcdFx0XHRpbnB1dCA9IGlucHV0c1tpXTtcclxuICBcdFx0XHRsYXllciA9IHRoaXMuX2dldExheWVyKGlucHV0LmxheWVySWQpLmxheWVyO1xyXG4gIFx0XHRcdGlucHV0LmRpc2FibGVkID0gKGxheWVyLm9wdGlvbnMubWluWm9vbSAhPT0gdW5kZWZpbmVkICYmIHpvb20gPCBsYXllci5vcHRpb25zLm1pblpvb20pIHx8XHJcbiAgXHRcdFx0ICAgICAgICAgICAgICAgICAobGF5ZXIub3B0aW9ucy5tYXhab29tICE9PSB1bmRlZmluZWQgJiYgem9vbSA+IGxheWVyLm9wdGlvbnMubWF4Wm9vbSk7XHJcblxyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdF9leHBhbmRJZk5vdENvbGxhcHNlZDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRpZiAodGhpcy5fbWFwICYmICF0aGlzLm9wdGlvbnMuY29sbGFwc2VkKSB7XHJcbiAgXHRcdFx0dGhpcy5leHBhbmQoKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0X2V4cGFuZFNhZmVseTogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR2YXIgc2VjdGlvbiA9IHRoaXMuX3NlY3Rpb247XHJcbiAgXHRcdHRoaXMuX3ByZXZlbnRDbGljayA9IHRydWU7XHJcbiAgXHRcdG9uKHNlY3Rpb24sICdjbGljaycsIHByZXZlbnREZWZhdWx0KTtcclxuICBcdFx0dGhpcy5leHBhbmQoKTtcclxuICBcdFx0dmFyIHRoYXQgPSB0aGlzO1xyXG4gIFx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcclxuICBcdFx0XHRvZmYoc2VjdGlvbiwgJ2NsaWNrJywgcHJldmVudERlZmF1bHQpO1xyXG4gIFx0XHRcdHRoYXQuX3ByZXZlbnRDbGljayA9IGZhbHNlO1xyXG4gIFx0XHR9KTtcclxuICBcdH1cclxuXHJcbiAgfSk7XHJcblxyXG5cclxuICAvLyBAZmFjdG9yeSBMLmNvbnRyb2wubGF5ZXJzKGJhc2VsYXllcnM/OiBPYmplY3QsIG92ZXJsYXlzPzogT2JqZWN0LCBvcHRpb25zPzogQ29udHJvbC5MYXllcnMgb3B0aW9ucylcclxuICAvLyBDcmVhdGVzIGEgbGF5ZXJzIGNvbnRyb2wgd2l0aCB0aGUgZ2l2ZW4gbGF5ZXJzLiBCYXNlIGxheWVycyB3aWxsIGJlIHN3aXRjaGVkIHdpdGggcmFkaW8gYnV0dG9ucywgd2hpbGUgb3ZlcmxheXMgd2lsbCBiZSBzd2l0Y2hlZCB3aXRoIGNoZWNrYm94ZXMuIE5vdGUgdGhhdCBhbGwgYmFzZSBsYXllcnMgc2hvdWxkIGJlIHBhc3NlZCBpbiB0aGUgYmFzZSBsYXllcnMgb2JqZWN0LCBidXQgb25seSBvbmUgc2hvdWxkIGJlIGFkZGVkIHRvIHRoZSBtYXAgZHVyaW5nIG1hcCBpbnN0YW50aWF0aW9uLlxyXG4gIHZhciBsYXllcnMgPSBmdW5jdGlvbiAoYmFzZUxheWVycywgb3ZlcmxheXMsIG9wdGlvbnMpIHtcclxuICBcdHJldHVybiBuZXcgTGF5ZXJzKGJhc2VMYXllcnMsIG92ZXJsYXlzLCBvcHRpb25zKTtcclxuICB9O1xuXG4gIC8qXHJcbiAgICogQGNsYXNzIENvbnRyb2wuWm9vbVxyXG4gICAqIEBha2EgTC5Db250cm9sLlpvb21cclxuICAgKiBAaW5oZXJpdHMgQ29udHJvbFxyXG4gICAqXHJcbiAgICogQSBiYXNpYyB6b29tIGNvbnRyb2wgd2l0aCB0d28gYnV0dG9ucyAoem9vbSBpbiBhbmQgem9vbSBvdXQpLiBJdCBpcyBwdXQgb24gdGhlIG1hcCBieSBkZWZhdWx0IHVubGVzcyB5b3Ugc2V0IGl0cyBbYHpvb21Db250cm9sYCBvcHRpb25dKCNtYXAtem9vbWNvbnRyb2wpIHRvIGBmYWxzZWAuIEV4dGVuZHMgYENvbnRyb2xgLlxyXG4gICAqL1xyXG5cclxuICB2YXIgWm9vbSA9IENvbnRyb2wuZXh0ZW5kKHtcclxuICBcdC8vIEBzZWN0aW9uXHJcbiAgXHQvLyBAYWthIENvbnRyb2wuWm9vbSBvcHRpb25zXHJcbiAgXHRvcHRpb25zOiB7XHJcbiAgXHRcdHBvc2l0aW9uOiAndG9wbGVmdCcsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHpvb21JblRleHQ6IFN0cmluZyA9ICc8c3BhbiBhcmlhLWhpZGRlbj1cInRydWVcIj4rPC9zcGFuPidcclxuICBcdFx0Ly8gVGhlIHRleHQgc2V0IG9uIHRoZSAnem9vbSBpbicgYnV0dG9uLlxyXG4gIFx0XHR6b29tSW5UZXh0OiAnPHNwYW4gYXJpYS1oaWRkZW49XCJ0cnVlXCI+Kzwvc3Bhbj4nLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiB6b29tSW5UaXRsZTogU3RyaW5nID0gJ1pvb20gaW4nXHJcbiAgXHRcdC8vIFRoZSB0aXRsZSBzZXQgb24gdGhlICd6b29tIGluJyBidXR0b24uXHJcbiAgXHRcdHpvb21JblRpdGxlOiAnWm9vbSBpbicsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHpvb21PdXRUZXh0OiBTdHJpbmcgPSAnPHNwYW4gYXJpYS1oaWRkZW49XCJ0cnVlXCI+JiN4MjIxMjs8L3NwYW4+J1xyXG4gIFx0XHQvLyBUaGUgdGV4dCBzZXQgb24gdGhlICd6b29tIG91dCcgYnV0dG9uLlxyXG4gIFx0XHR6b29tT3V0VGV4dDogJzxzcGFuIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPiYjeDIyMTI7PC9zcGFuPicsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHpvb21PdXRUaXRsZTogU3RyaW5nID0gJ1pvb20gb3V0J1xyXG4gIFx0XHQvLyBUaGUgdGl0bGUgc2V0IG9uIHRoZSAnem9vbSBvdXQnIGJ1dHRvbi5cclxuICBcdFx0em9vbU91dFRpdGxlOiAnWm9vbSBvdXQnXHJcbiAgXHR9LFxyXG5cclxuICBcdG9uQWRkOiBmdW5jdGlvbiAobWFwKSB7XHJcbiAgXHRcdHZhciB6b29tTmFtZSA9ICdsZWFmbGV0LWNvbnRyb2wtem9vbScsXHJcbiAgXHRcdCAgICBjb250YWluZXIgPSBjcmVhdGUkMSgnZGl2Jywgem9vbU5hbWUgKyAnIGxlYWZsZXQtYmFyJyksXHJcbiAgXHRcdCAgICBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xyXG5cclxuICBcdFx0dGhpcy5fem9vbUluQnV0dG9uICA9IHRoaXMuX2NyZWF0ZUJ1dHRvbihvcHRpb25zLnpvb21JblRleHQsIG9wdGlvbnMuem9vbUluVGl0bGUsXHJcbiAgXHRcdCAgICAgICAgem9vbU5hbWUgKyAnLWluJywgIGNvbnRhaW5lciwgdGhpcy5fem9vbUluKTtcclxuICBcdFx0dGhpcy5fem9vbU91dEJ1dHRvbiA9IHRoaXMuX2NyZWF0ZUJ1dHRvbihvcHRpb25zLnpvb21PdXRUZXh0LCBvcHRpb25zLnpvb21PdXRUaXRsZSxcclxuICBcdFx0ICAgICAgICB6b29tTmFtZSArICctb3V0JywgY29udGFpbmVyLCB0aGlzLl96b29tT3V0KTtcclxuXHJcbiAgXHRcdHRoaXMuX3VwZGF0ZURpc2FibGVkKCk7XHJcbiAgXHRcdG1hcC5vbignem9vbWVuZCB6b29tbGV2ZWxzY2hhbmdlJywgdGhpcy5fdXBkYXRlRGlzYWJsZWQsIHRoaXMpO1xyXG5cclxuICBcdFx0cmV0dXJuIGNvbnRhaW5lcjtcclxuICBcdH0sXHJcblxyXG4gIFx0b25SZW1vdmU6IGZ1bmN0aW9uIChtYXApIHtcclxuICBcdFx0bWFwLm9mZignem9vbWVuZCB6b29tbGV2ZWxzY2hhbmdlJywgdGhpcy5fdXBkYXRlRGlzYWJsZWQsIHRoaXMpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRkaXNhYmxlOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHRoaXMuX2Rpc2FibGVkID0gdHJ1ZTtcclxuICBcdFx0dGhpcy5fdXBkYXRlRGlzYWJsZWQoKTtcclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdGVuYWJsZTogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR0aGlzLl9kaXNhYmxlZCA9IGZhbHNlO1xyXG4gIFx0XHR0aGlzLl91cGRhdGVEaXNhYmxlZCgpO1xyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0X3pvb21JbjogZnVuY3Rpb24gKGUpIHtcclxuICBcdFx0aWYgKCF0aGlzLl9kaXNhYmxlZCAmJiB0aGlzLl9tYXAuX3pvb20gPCB0aGlzLl9tYXAuZ2V0TWF4Wm9vbSgpKSB7XHJcbiAgXHRcdFx0dGhpcy5fbWFwLnpvb21Jbih0aGlzLl9tYXAub3B0aW9ucy56b29tRGVsdGEgKiAoZS5zaGlmdEtleSA/IDMgOiAxKSk7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0X3pvb21PdXQ6IGZ1bmN0aW9uIChlKSB7XHJcbiAgXHRcdGlmICghdGhpcy5fZGlzYWJsZWQgJiYgdGhpcy5fbWFwLl96b29tID4gdGhpcy5fbWFwLmdldE1pblpvb20oKSkge1xyXG4gIFx0XHRcdHRoaXMuX21hcC56b29tT3V0KHRoaXMuX21hcC5vcHRpb25zLnpvb21EZWx0YSAqIChlLnNoaWZ0S2V5ID8gMyA6IDEpKTtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHRfY3JlYXRlQnV0dG9uOiBmdW5jdGlvbiAoaHRtbCwgdGl0bGUsIGNsYXNzTmFtZSwgY29udGFpbmVyLCBmbikge1xyXG4gIFx0XHR2YXIgbGluayA9IGNyZWF0ZSQxKCdhJywgY2xhc3NOYW1lLCBjb250YWluZXIpO1xyXG4gIFx0XHRsaW5rLmlubmVySFRNTCA9IGh0bWw7XHJcbiAgXHRcdGxpbmsuaHJlZiA9ICcjJztcclxuICBcdFx0bGluay50aXRsZSA9IHRpdGxlO1xyXG5cclxuICBcdFx0LypcclxuICBcdFx0ICogV2lsbCBmb3JjZSBzY3JlZW4gcmVhZGVycyBsaWtlIFZvaWNlT3ZlciB0byByZWFkIHRoaXMgYXMgXCJab29tIGluIC0gYnV0dG9uXCJcclxuICBcdFx0ICovXHJcbiAgXHRcdGxpbmsuc2V0QXR0cmlidXRlKCdyb2xlJywgJ2J1dHRvbicpO1xyXG4gIFx0XHRsaW5rLnNldEF0dHJpYnV0ZSgnYXJpYS1sYWJlbCcsIHRpdGxlKTtcclxuXHJcbiAgXHRcdGRpc2FibGVDbGlja1Byb3BhZ2F0aW9uKGxpbmspO1xyXG4gIFx0XHRvbihsaW5rLCAnY2xpY2snLCBzdG9wKTtcclxuICBcdFx0b24obGluaywgJ2NsaWNrJywgZm4sIHRoaXMpO1xyXG4gIFx0XHRvbihsaW5rLCAnY2xpY2snLCB0aGlzLl9yZWZvY3VzT25NYXAsIHRoaXMpO1xyXG5cclxuICBcdFx0cmV0dXJuIGxpbms7XHJcbiAgXHR9LFxyXG5cclxuICBcdF91cGRhdGVEaXNhYmxlZDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR2YXIgbWFwID0gdGhpcy5fbWFwLFxyXG4gIFx0XHQgICAgY2xhc3NOYW1lID0gJ2xlYWZsZXQtZGlzYWJsZWQnO1xyXG5cclxuICBcdFx0cmVtb3ZlQ2xhc3ModGhpcy5fem9vbUluQnV0dG9uLCBjbGFzc05hbWUpO1xyXG4gIFx0XHRyZW1vdmVDbGFzcyh0aGlzLl96b29tT3V0QnV0dG9uLCBjbGFzc05hbWUpO1xyXG4gIFx0XHR0aGlzLl96b29tSW5CdXR0b24uc2V0QXR0cmlidXRlKCdhcmlhLWRpc2FibGVkJywgJ2ZhbHNlJyk7XHJcbiAgXHRcdHRoaXMuX3pvb21PdXRCdXR0b24uc2V0QXR0cmlidXRlKCdhcmlhLWRpc2FibGVkJywgJ2ZhbHNlJyk7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fZGlzYWJsZWQgfHwgbWFwLl96b29tID09PSBtYXAuZ2V0TWluWm9vbSgpKSB7XHJcbiAgXHRcdFx0YWRkQ2xhc3ModGhpcy5fem9vbU91dEJ1dHRvbiwgY2xhc3NOYW1lKTtcclxuICBcdFx0XHR0aGlzLl96b29tT3V0QnV0dG9uLnNldEF0dHJpYnV0ZSgnYXJpYS1kaXNhYmxlZCcsICd0cnVlJyk7XHJcbiAgXHRcdH1cclxuICBcdFx0aWYgKHRoaXMuX2Rpc2FibGVkIHx8IG1hcC5fem9vbSA9PT0gbWFwLmdldE1heFpvb20oKSkge1xyXG4gIFx0XHRcdGFkZENsYXNzKHRoaXMuX3pvb21JbkJ1dHRvbiwgY2xhc3NOYW1lKTtcclxuICBcdFx0XHR0aGlzLl96b29tSW5CdXR0b24uc2V0QXR0cmlidXRlKCdhcmlhLWRpc2FibGVkJywgJ3RydWUnKTtcclxuICBcdFx0fVxyXG4gIFx0fVxyXG4gIH0pO1xyXG5cclxuICAvLyBAbmFtZXNwYWNlIE1hcFxyXG4gIC8vIEBzZWN0aW9uIENvbnRyb2wgb3B0aW9uc1xyXG4gIC8vIEBvcHRpb24gem9vbUNvbnRyb2w6IEJvb2xlYW4gPSB0cnVlXHJcbiAgLy8gV2hldGhlciBhIFt6b29tIGNvbnRyb2xdKCNjb250cm9sLXpvb20pIGlzIGFkZGVkIHRvIHRoZSBtYXAgYnkgZGVmYXVsdC5cclxuICBNYXAubWVyZ2VPcHRpb25zKHtcclxuICBcdHpvb21Db250cm9sOiB0cnVlXHJcbiAgfSk7XHJcblxyXG4gIE1hcC5hZGRJbml0SG9vayhmdW5jdGlvbiAoKSB7XHJcbiAgXHRpZiAodGhpcy5vcHRpb25zLnpvb21Db250cm9sKSB7XHJcbiAgXHRcdC8vIEBzZWN0aW9uIENvbnRyb2xzXHJcbiAgXHRcdC8vIEBwcm9wZXJ0eSB6b29tQ29udHJvbDogQ29udHJvbC5ab29tXHJcbiAgXHRcdC8vIFRoZSBkZWZhdWx0IHpvb20gY29udHJvbCAob25seSBhdmFpbGFibGUgaWYgdGhlXHJcbiAgXHRcdC8vIFtgem9vbUNvbnRyb2xgIG9wdGlvbl0oI21hcC16b29tY29udHJvbCkgd2FzIGB0cnVlYCB3aGVuIGNyZWF0aW5nIHRoZSBtYXApLlxyXG4gIFx0XHR0aGlzLnpvb21Db250cm9sID0gbmV3IFpvb20oKTtcclxuICBcdFx0dGhpcy5hZGRDb250cm9sKHRoaXMuem9vbUNvbnRyb2wpO1xyXG4gIFx0fVxyXG4gIH0pO1xyXG5cclxuICAvLyBAbmFtZXNwYWNlIENvbnRyb2wuWm9vbVxyXG4gIC8vIEBmYWN0b3J5IEwuY29udHJvbC56b29tKG9wdGlvbnM6IENvbnRyb2wuWm9vbSBvcHRpb25zKVxyXG4gIC8vIENyZWF0ZXMgYSB6b29tIGNvbnRyb2xcclxuICB2YXIgem9vbSA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcbiAgXHRyZXR1cm4gbmV3IFpvb20ob3B0aW9ucyk7XHJcbiAgfTtcblxuICAvKlxuICAgKiBAY2xhc3MgQ29udHJvbC5TY2FsZVxuICAgKiBAYWthIEwuQ29udHJvbC5TY2FsZVxuICAgKiBAaW5oZXJpdHMgQ29udHJvbFxuICAgKlxuICAgKiBBIHNpbXBsZSBzY2FsZSBjb250cm9sIHRoYXQgc2hvd3MgdGhlIHNjYWxlIG9mIHRoZSBjdXJyZW50IGNlbnRlciBvZiBzY3JlZW4gaW4gbWV0cmljIChtL2ttKSBhbmQgaW1wZXJpYWwgKG1pL2Z0KSBzeXN0ZW1zLiBFeHRlbmRzIGBDb250cm9sYC5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICpcbiAgICogYGBganNcbiAgICogTC5jb250cm9sLnNjYWxlKCkuYWRkVG8obWFwKTtcbiAgICogYGBgXG4gICAqL1xuXG4gIHZhciBTY2FsZSA9IENvbnRyb2wuZXh0ZW5kKHtcbiAgXHQvLyBAc2VjdGlvblxuICBcdC8vIEBha2EgQ29udHJvbC5TY2FsZSBvcHRpb25zXG4gIFx0b3B0aW9uczoge1xuICBcdFx0cG9zaXRpb246ICdib3R0b21sZWZ0JyxcblxuICBcdFx0Ly8gQG9wdGlvbiBtYXhXaWR0aDogTnVtYmVyID0gMTAwXG4gIFx0XHQvLyBNYXhpbXVtIHdpZHRoIG9mIHRoZSBjb250cm9sIGluIHBpeGVscy4gVGhlIHdpZHRoIGlzIHNldCBkeW5hbWljYWxseSB0byBzaG93IHJvdW5kIHZhbHVlcyAoZS5nLiAxMDAsIDIwMCwgNTAwKS5cbiAgXHRcdG1heFdpZHRoOiAxMDAsXG5cbiAgXHRcdC8vIEBvcHRpb24gbWV0cmljOiBCb29sZWFuID0gVHJ1ZVxuICBcdFx0Ly8gV2hldGhlciB0byBzaG93IHRoZSBtZXRyaWMgc2NhbGUgbGluZSAobS9rbSkuXG4gIFx0XHRtZXRyaWM6IHRydWUsXG5cbiAgXHRcdC8vIEBvcHRpb24gaW1wZXJpYWw6IEJvb2xlYW4gPSBUcnVlXG4gIFx0XHQvLyBXaGV0aGVyIHRvIHNob3cgdGhlIGltcGVyaWFsIHNjYWxlIGxpbmUgKG1pL2Z0KS5cbiAgXHRcdGltcGVyaWFsOiB0cnVlXG5cbiAgXHRcdC8vIEBvcHRpb24gdXBkYXRlV2hlbklkbGU6IEJvb2xlYW4gPSBmYWxzZVxuICBcdFx0Ly8gSWYgYHRydWVgLCB0aGUgY29udHJvbCBpcyB1cGRhdGVkIG9uIFtgbW92ZWVuZGBdKCNtYXAtbW92ZWVuZCksIG90aGVyd2lzZSBpdCdzIGFsd2F5cyB1cC10by1kYXRlICh1cGRhdGVkIG9uIFtgbW92ZWBdKCNtYXAtbW92ZSkpLlxuICBcdH0sXG5cbiAgXHRvbkFkZDogZnVuY3Rpb24gKG1hcCkge1xuICBcdFx0dmFyIGNsYXNzTmFtZSA9ICdsZWFmbGV0LWNvbnRyb2wtc2NhbGUnLFxuICBcdFx0ICAgIGNvbnRhaW5lciA9IGNyZWF0ZSQxKCdkaXYnLCBjbGFzc05hbWUpLFxuICBcdFx0ICAgIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG5cbiAgXHRcdHRoaXMuX2FkZFNjYWxlcyhvcHRpb25zLCBjbGFzc05hbWUgKyAnLWxpbmUnLCBjb250YWluZXIpO1xuXG4gIFx0XHRtYXAub24ob3B0aW9ucy51cGRhdGVXaGVuSWRsZSA/ICdtb3ZlZW5kJyA6ICdtb3ZlJywgdGhpcy5fdXBkYXRlLCB0aGlzKTtcbiAgXHRcdG1hcC53aGVuUmVhZHkodGhpcy5fdXBkYXRlLCB0aGlzKTtcblxuICBcdFx0cmV0dXJuIGNvbnRhaW5lcjtcbiAgXHR9LFxuXG4gIFx0b25SZW1vdmU6IGZ1bmN0aW9uIChtYXApIHtcbiAgXHRcdG1hcC5vZmYodGhpcy5vcHRpb25zLnVwZGF0ZVdoZW5JZGxlID8gJ21vdmVlbmQnIDogJ21vdmUnLCB0aGlzLl91cGRhdGUsIHRoaXMpO1xuICBcdH0sXG5cbiAgXHRfYWRkU2NhbGVzOiBmdW5jdGlvbiAob3B0aW9ucywgY2xhc3NOYW1lLCBjb250YWluZXIpIHtcbiAgXHRcdGlmIChvcHRpb25zLm1ldHJpYykge1xuICBcdFx0XHR0aGlzLl9tU2NhbGUgPSBjcmVhdGUkMSgnZGl2JywgY2xhc3NOYW1lLCBjb250YWluZXIpO1xuICBcdFx0fVxuICBcdFx0aWYgKG9wdGlvbnMuaW1wZXJpYWwpIHtcbiAgXHRcdFx0dGhpcy5faVNjYWxlID0gY3JlYXRlJDEoJ2RpdicsIGNsYXNzTmFtZSwgY29udGFpbmVyKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZTogZnVuY3Rpb24gKCkge1xuICBcdFx0dmFyIG1hcCA9IHRoaXMuX21hcCxcbiAgXHRcdCAgICB5ID0gbWFwLmdldFNpemUoKS55IC8gMjtcblxuICBcdFx0dmFyIG1heE1ldGVycyA9IG1hcC5kaXN0YW5jZShcbiAgXHRcdFx0bWFwLmNvbnRhaW5lclBvaW50VG9MYXRMbmcoWzAsIHldKSxcbiAgXHRcdFx0bWFwLmNvbnRhaW5lclBvaW50VG9MYXRMbmcoW3RoaXMub3B0aW9ucy5tYXhXaWR0aCwgeV0pKTtcblxuICBcdFx0dGhpcy5fdXBkYXRlU2NhbGVzKG1heE1ldGVycyk7XG4gIFx0fSxcblxuICBcdF91cGRhdGVTY2FsZXM6IGZ1bmN0aW9uIChtYXhNZXRlcnMpIHtcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMubWV0cmljICYmIG1heE1ldGVycykge1xuICBcdFx0XHR0aGlzLl91cGRhdGVNZXRyaWMobWF4TWV0ZXJzKTtcbiAgXHRcdH1cbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMuaW1wZXJpYWwgJiYgbWF4TWV0ZXJzKSB7XG4gIFx0XHRcdHRoaXMuX3VwZGF0ZUltcGVyaWFsKG1heE1ldGVycyk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF91cGRhdGVNZXRyaWM6IGZ1bmN0aW9uIChtYXhNZXRlcnMpIHtcbiAgXHRcdHZhciBtZXRlcnMgPSB0aGlzLl9nZXRSb3VuZE51bShtYXhNZXRlcnMpLFxuICBcdFx0ICAgIGxhYmVsID0gbWV0ZXJzIDwgMTAwMCA/IG1ldGVycyArICcgbScgOiAobWV0ZXJzIC8gMTAwMCkgKyAnIGttJztcblxuICBcdFx0dGhpcy5fdXBkYXRlU2NhbGUodGhpcy5fbVNjYWxlLCBsYWJlbCwgbWV0ZXJzIC8gbWF4TWV0ZXJzKTtcbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZUltcGVyaWFsOiBmdW5jdGlvbiAobWF4TWV0ZXJzKSB7XG4gIFx0XHR2YXIgbWF4RmVldCA9IG1heE1ldGVycyAqIDMuMjgwODM5OSxcbiAgXHRcdCAgICBtYXhNaWxlcywgbWlsZXMsIGZlZXQ7XG5cbiAgXHRcdGlmIChtYXhGZWV0ID4gNTI4MCkge1xuICBcdFx0XHRtYXhNaWxlcyA9IG1heEZlZXQgLyA1MjgwO1xuICBcdFx0XHRtaWxlcyA9IHRoaXMuX2dldFJvdW5kTnVtKG1heE1pbGVzKTtcbiAgXHRcdFx0dGhpcy5fdXBkYXRlU2NhbGUodGhpcy5faVNjYWxlLCBtaWxlcyArICcgbWknLCBtaWxlcyAvIG1heE1pbGVzKTtcblxuICBcdFx0fSBlbHNlIHtcbiAgXHRcdFx0ZmVldCA9IHRoaXMuX2dldFJvdW5kTnVtKG1heEZlZXQpO1xuICBcdFx0XHR0aGlzLl91cGRhdGVTY2FsZSh0aGlzLl9pU2NhbGUsIGZlZXQgKyAnIGZ0JywgZmVldCAvIG1heEZlZXQpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfdXBkYXRlU2NhbGU6IGZ1bmN0aW9uIChzY2FsZSwgdGV4dCwgcmF0aW8pIHtcbiAgXHRcdHNjYWxlLnN0eWxlLndpZHRoID0gTWF0aC5yb3VuZCh0aGlzLm9wdGlvbnMubWF4V2lkdGggKiByYXRpbykgKyAncHgnO1xuICBcdFx0c2NhbGUuaW5uZXJIVE1MID0gdGV4dDtcbiAgXHR9LFxuXG4gIFx0X2dldFJvdW5kTnVtOiBmdW5jdGlvbiAobnVtKSB7XG4gIFx0XHR2YXIgcG93MTAgPSBNYXRoLnBvdygxMCwgKE1hdGguZmxvb3IobnVtKSArICcnKS5sZW5ndGggLSAxKSxcbiAgXHRcdCAgICBkID0gbnVtIC8gcG93MTA7XG5cbiAgXHRcdGQgPSBkID49IDEwID8gMTAgOlxuICBcdFx0ICAgIGQgPj0gNSA/IDUgOlxuICBcdFx0ICAgIGQgPj0gMyA/IDMgOlxuICBcdFx0ICAgIGQgPj0gMiA/IDIgOiAxO1xuXG4gIFx0XHRyZXR1cm4gcG93MTAgKiBkO1xuICBcdH1cbiAgfSk7XG5cblxuICAvLyBAZmFjdG9yeSBMLmNvbnRyb2wuc2NhbGUob3B0aW9ucz86IENvbnRyb2wuU2NhbGUgb3B0aW9ucylcbiAgLy8gQ3JlYXRlcyBhbiBzY2FsZSBjb250cm9sIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuXG4gIHZhciBzY2FsZSA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gIFx0cmV0dXJuIG5ldyBTY2FsZShvcHRpb25zKTtcbiAgfTtcblxuICB2YXIgdWtyYWluaWFuRmxhZyA9ICc8c3ZnIGFyaWEtaGlkZGVuPVwidHJ1ZVwiIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB3aWR0aD1cIjEyXCIgaGVpZ2h0PVwiOFwiIHZpZXdCb3g9XCIwIDAgMTIgOFwiIGNsYXNzPVwibGVhZmxldC1hdHRyaWJ1dGlvbi1mbGFnXCI+PHBhdGggZmlsbD1cIiM0QzdCRTFcIiBkPVwiTTAgMGgxMnY0SDB6XCIvPjxwYXRoIGZpbGw9XCIjRkZENTAwXCIgZD1cIk0wIDRoMTJ2M0gwelwiLz48cGF0aCBmaWxsPVwiI0UwQkMwMFwiIGQ9XCJNMCA3aDEydjFIMHpcIi8+PC9zdmc+JztcclxuXHJcblxyXG4gIC8qXHJcbiAgICogQGNsYXNzIENvbnRyb2wuQXR0cmlidXRpb25cclxuICAgKiBAYWthIEwuQ29udHJvbC5BdHRyaWJ1dGlvblxyXG4gICAqIEBpbmhlcml0cyBDb250cm9sXHJcbiAgICpcclxuICAgKiBUaGUgYXR0cmlidXRpb24gY29udHJvbCBhbGxvd3MgeW91IHRvIGRpc3BsYXkgYXR0cmlidXRpb24gZGF0YSBpbiBhIHNtYWxsIHRleHQgYm94IG9uIGEgbWFwLiBJdCBpcyBwdXQgb24gdGhlIG1hcCBieSBkZWZhdWx0IHVubGVzcyB5b3Ugc2V0IGl0cyBbYGF0dHJpYnV0aW9uQ29udHJvbGAgb3B0aW9uXSgjbWFwLWF0dHJpYnV0aW9uY29udHJvbCkgdG8gYGZhbHNlYCwgYW5kIGl0IGZldGNoZXMgYXR0cmlidXRpb24gdGV4dHMgZnJvbSBsYXllcnMgd2l0aCB0aGUgW2BnZXRBdHRyaWJ1dGlvbmAgbWV0aG9kXSgjbGF5ZXItZ2V0YXR0cmlidXRpb24pIGF1dG9tYXRpY2FsbHkuIEV4dGVuZHMgQ29udHJvbC5cclxuICAgKi9cclxuXHJcbiAgdmFyIEF0dHJpYnV0aW9uID0gQ29udHJvbC5leHRlbmQoe1xyXG4gIFx0Ly8gQHNlY3Rpb25cclxuICBcdC8vIEBha2EgQ29udHJvbC5BdHRyaWJ1dGlvbiBvcHRpb25zXHJcbiAgXHRvcHRpb25zOiB7XHJcbiAgXHRcdHBvc2l0aW9uOiAnYm90dG9tcmlnaHQnLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBwcmVmaXg6IFN0cmluZ3xmYWxzZSA9ICdMZWFmbGV0J1xyXG4gIFx0XHQvLyBUaGUgSFRNTCB0ZXh0IHNob3duIGJlZm9yZSB0aGUgYXR0cmlidXRpb25zLiBQYXNzIGBmYWxzZWAgdG8gZGlzYWJsZS5cclxuICBcdFx0cHJlZml4OiAnPGEgaHJlZj1cImh0dHBzOi8vbGVhZmxldGpzLmNvbVwiIHRpdGxlPVwiQSBKYXZhU2NyaXB0IGxpYnJhcnkgZm9yIGludGVyYWN0aXZlIG1hcHNcIj4nICsgKEJyb3dzZXIuaW5saW5lU3ZnID8gdWtyYWluaWFuRmxhZyArICcgJyA6ICcnKSArICdMZWFmbGV0PC9hPidcclxuICBcdH0sXHJcblxyXG4gIFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuICBcdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcclxuXHJcbiAgXHRcdHRoaXMuX2F0dHJpYnV0aW9ucyA9IHt9O1xyXG4gIFx0fSxcclxuXHJcbiAgXHRvbkFkZDogZnVuY3Rpb24gKG1hcCkge1xyXG4gIFx0XHRtYXAuYXR0cmlidXRpb25Db250cm9sID0gdGhpcztcclxuICBcdFx0dGhpcy5fY29udGFpbmVyID0gY3JlYXRlJDEoJ2RpdicsICdsZWFmbGV0LWNvbnRyb2wtYXR0cmlidXRpb24nKTtcclxuICBcdFx0ZGlzYWJsZUNsaWNrUHJvcGFnYXRpb24odGhpcy5fY29udGFpbmVyKTtcclxuXHJcbiAgXHRcdC8vIFRPRE8gdWdseSwgcmVmYWN0b3JcclxuICBcdFx0Zm9yICh2YXIgaSBpbiBtYXAuX2xheWVycykge1xyXG4gIFx0XHRcdGlmIChtYXAuX2xheWVyc1tpXS5nZXRBdHRyaWJ1dGlvbikge1xyXG4gIFx0XHRcdFx0dGhpcy5hZGRBdHRyaWJ1dGlvbihtYXAuX2xheWVyc1tpXS5nZXRBdHRyaWJ1dGlvbigpKTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX3VwZGF0ZSgpO1xyXG5cclxuICBcdFx0bWFwLm9uKCdsYXllcmFkZCcsIHRoaXMuX2FkZEF0dHJpYnV0aW9uLCB0aGlzKTtcclxuXHJcbiAgXHRcdHJldHVybiB0aGlzLl9jb250YWluZXI7XHJcbiAgXHR9LFxyXG5cclxuICBcdG9uUmVtb3ZlOiBmdW5jdGlvbiAobWFwKSB7XHJcbiAgXHRcdG1hcC5vZmYoJ2xheWVyYWRkJywgdGhpcy5fYWRkQXR0cmlidXRpb24sIHRoaXMpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfYWRkQXR0cmlidXRpb246IGZ1bmN0aW9uIChldikge1xyXG4gIFx0XHRpZiAoZXYubGF5ZXIuZ2V0QXR0cmlidXRpb24pIHtcclxuICBcdFx0XHR0aGlzLmFkZEF0dHJpYnV0aW9uKGV2LmxheWVyLmdldEF0dHJpYnV0aW9uKCkpO1xyXG4gIFx0XHRcdGV2LmxheWVyLm9uY2UoJ3JlbW92ZScsIGZ1bmN0aW9uICgpIHtcclxuICBcdFx0XHRcdHRoaXMucmVtb3ZlQXR0cmlidXRpb24oZXYubGF5ZXIuZ2V0QXR0cmlidXRpb24oKSk7XHJcbiAgXHRcdFx0fSwgdGhpcyk7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBzZXRQcmVmaXgocHJlZml4OiBTdHJpbmd8ZmFsc2UpOiB0aGlzXHJcbiAgXHQvLyBUaGUgSFRNTCB0ZXh0IHNob3duIGJlZm9yZSB0aGUgYXR0cmlidXRpb25zLiBQYXNzIGBmYWxzZWAgdG8gZGlzYWJsZS5cclxuICBcdHNldFByZWZpeDogZnVuY3Rpb24gKHByZWZpeCkge1xyXG4gIFx0XHR0aGlzLm9wdGlvbnMucHJlZml4ID0gcHJlZml4O1xyXG4gIFx0XHR0aGlzLl91cGRhdGUoKTtcclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgYWRkQXR0cmlidXRpb24odGV4dDogU3RyaW5nKTogdGhpc1xyXG4gIFx0Ly8gQWRkcyBhbiBhdHRyaWJ1dGlvbiB0ZXh0IChlLmcuIGAnJmNvcHk7IE9wZW5TdHJlZXRNYXAgY29udHJpYnV0b3JzJ2ApLlxyXG4gIFx0YWRkQXR0cmlidXRpb246IGZ1bmN0aW9uICh0ZXh0KSB7XHJcbiAgXHRcdGlmICghdGV4dCkgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuICBcdFx0aWYgKCF0aGlzLl9hdHRyaWJ1dGlvbnNbdGV4dF0pIHtcclxuICBcdFx0XHR0aGlzLl9hdHRyaWJ1dGlvbnNbdGV4dF0gPSAwO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHRoaXMuX2F0dHJpYnV0aW9uc1t0ZXh0XSsrO1xyXG5cclxuICBcdFx0dGhpcy5fdXBkYXRlKCk7XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCByZW1vdmVBdHRyaWJ1dGlvbih0ZXh0OiBTdHJpbmcpOiB0aGlzXHJcbiAgXHQvLyBSZW1vdmVzIGFuIGF0dHJpYnV0aW9uIHRleHQuXHJcbiAgXHRyZW1vdmVBdHRyaWJ1dGlvbjogZnVuY3Rpb24gKHRleHQpIHtcclxuICBcdFx0aWYgKCF0ZXh0KSB7IHJldHVybiB0aGlzOyB9XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fYXR0cmlidXRpb25zW3RleHRdKSB7XHJcbiAgXHRcdFx0dGhpcy5fYXR0cmlidXRpb25zW3RleHRdLS07XHJcbiAgXHRcdFx0dGhpcy5fdXBkYXRlKCk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfdXBkYXRlOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICghdGhpcy5fbWFwKSB7IHJldHVybjsgfVxyXG5cclxuICBcdFx0dmFyIGF0dHJpYnMgPSBbXTtcclxuXHJcbiAgXHRcdGZvciAodmFyIGkgaW4gdGhpcy5fYXR0cmlidXRpb25zKSB7XHJcbiAgXHRcdFx0aWYgKHRoaXMuX2F0dHJpYnV0aW9uc1tpXSkge1xyXG4gIFx0XHRcdFx0YXR0cmlicy5wdXNoKGkpO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG5cclxuICBcdFx0dmFyIHByZWZpeEFuZEF0dHJpYnMgPSBbXTtcclxuXHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMucHJlZml4KSB7XHJcbiAgXHRcdFx0cHJlZml4QW5kQXR0cmlicy5wdXNoKHRoaXMub3B0aW9ucy5wcmVmaXgpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdGlmIChhdHRyaWJzLmxlbmd0aCkge1xyXG4gIFx0XHRcdHByZWZpeEFuZEF0dHJpYnMucHVzaChhdHRyaWJzLmpvaW4oJywgJykpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR0aGlzLl9jb250YWluZXIuaW5uZXJIVE1MID0gcHJlZml4QW5kQXR0cmlicy5qb2luKCcgPHNwYW4gYXJpYS1oaWRkZW49XCJ0cnVlXCI+fDwvc3Bhbj4gJyk7XHJcbiAgXHR9XHJcbiAgfSk7XHJcblxyXG4gIC8vIEBuYW1lc3BhY2UgTWFwXHJcbiAgLy8gQHNlY3Rpb24gQ29udHJvbCBvcHRpb25zXHJcbiAgLy8gQG9wdGlvbiBhdHRyaWJ1dGlvbkNvbnRyb2w6IEJvb2xlYW4gPSB0cnVlXHJcbiAgLy8gV2hldGhlciBhIFthdHRyaWJ1dGlvbiBjb250cm9sXSgjY29udHJvbC1hdHRyaWJ1dGlvbikgaXMgYWRkZWQgdG8gdGhlIG1hcCBieSBkZWZhdWx0LlxyXG4gIE1hcC5tZXJnZU9wdGlvbnMoe1xyXG4gIFx0YXR0cmlidXRpb25Db250cm9sOiB0cnVlXHJcbiAgfSk7XHJcblxyXG4gIE1hcC5hZGRJbml0SG9vayhmdW5jdGlvbiAoKSB7XHJcbiAgXHRpZiAodGhpcy5vcHRpb25zLmF0dHJpYnV0aW9uQ29udHJvbCkge1xyXG4gIFx0XHRuZXcgQXR0cmlidXRpb24oKS5hZGRUbyh0aGlzKTtcclxuICBcdH1cclxuICB9KTtcclxuXHJcbiAgLy8gQG5hbWVzcGFjZSBDb250cm9sLkF0dHJpYnV0aW9uXHJcbiAgLy8gQGZhY3RvcnkgTC5jb250cm9sLmF0dHJpYnV0aW9uKG9wdGlvbnM6IENvbnRyb2wuQXR0cmlidXRpb24gb3B0aW9ucylcclxuICAvLyBDcmVhdGVzIGFuIGF0dHJpYnV0aW9uIGNvbnRyb2wuXHJcbiAgdmFyIGF0dHJpYnV0aW9uID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuICBcdHJldHVybiBuZXcgQXR0cmlidXRpb24ob3B0aW9ucyk7XHJcbiAgfTtcblxuICBDb250cm9sLkxheWVycyA9IExheWVycztcbiAgQ29udHJvbC5ab29tID0gWm9vbTtcbiAgQ29udHJvbC5TY2FsZSA9IFNjYWxlO1xuICBDb250cm9sLkF0dHJpYnV0aW9uID0gQXR0cmlidXRpb247XG5cbiAgY29udHJvbC5sYXllcnMgPSBsYXllcnM7XG4gIGNvbnRyb2wuem9vbSA9IHpvb207XG4gIGNvbnRyb2wuc2NhbGUgPSBzY2FsZTtcbiAgY29udHJvbC5hdHRyaWJ1dGlvbiA9IGF0dHJpYnV0aW9uO1xuXG4gIC8qXG4gIFx0TC5IYW5kbGVyIGlzIGEgYmFzZSBjbGFzcyBmb3IgaGFuZGxlciBjbGFzc2VzIHRoYXQgYXJlIHVzZWQgaW50ZXJuYWxseSB0byBpbmplY3RcbiAgXHRpbnRlcmFjdGlvbiBmZWF0dXJlcyBsaWtlIGRyYWdnaW5nIHRvIGNsYXNzZXMgbGlrZSBNYXAgYW5kIE1hcmtlci5cbiAgKi9cblxuICAvLyBAY2xhc3MgSGFuZGxlclxuICAvLyBAYWthIEwuSGFuZGxlclxuICAvLyBBYnN0cmFjdCBjbGFzcyBmb3IgbWFwIGludGVyYWN0aW9uIGhhbmRsZXJzXG5cbiAgdmFyIEhhbmRsZXIgPSBDbGFzcy5leHRlbmQoe1xuICBcdGluaXRpYWxpemU6IGZ1bmN0aW9uIChtYXApIHtcbiAgXHRcdHRoaXMuX21hcCA9IG1hcDtcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBlbmFibGUoKTogdGhpc1xuICBcdC8vIEVuYWJsZXMgdGhlIGhhbmRsZXJcbiAgXHRlbmFibGU6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICh0aGlzLl9lbmFibGVkKSB7IHJldHVybiB0aGlzOyB9XG5cbiAgXHRcdHRoaXMuX2VuYWJsZWQgPSB0cnVlO1xuICBcdFx0dGhpcy5hZGRIb29rcygpO1xuICBcdFx0cmV0dXJuIHRoaXM7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgZGlzYWJsZSgpOiB0aGlzXG4gIFx0Ly8gRGlzYWJsZXMgdGhlIGhhbmRsZXJcbiAgXHRkaXNhYmxlOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRpZiAoIXRoaXMuX2VuYWJsZWQpIHsgcmV0dXJuIHRoaXM7IH1cblxuICBcdFx0dGhpcy5fZW5hYmxlZCA9IGZhbHNlO1xuICBcdFx0dGhpcy5yZW1vdmVIb29rcygpO1xuICBcdFx0cmV0dXJuIHRoaXM7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgZW5hYmxlZCgpOiBCb29sZWFuXG4gIFx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGhhbmRsZXIgaXMgZW5hYmxlZFxuICBcdGVuYWJsZWQ6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHJldHVybiAhIXRoaXMuX2VuYWJsZWQ7XG4gIFx0fVxuXG4gIFx0Ly8gQHNlY3Rpb24gRXh0ZW5zaW9uIG1ldGhvZHNcbiAgXHQvLyBDbGFzc2VzIGluaGVyaXRpbmcgZnJvbSBgSGFuZGxlcmAgbXVzdCBpbXBsZW1lbnQgdGhlIHR3byBmb2xsb3dpbmcgbWV0aG9kczpcbiAgXHQvLyBAbWV0aG9kIGFkZEhvb2tzKClcbiAgXHQvLyBDYWxsZWQgd2hlbiB0aGUgaGFuZGxlciBpcyBlbmFibGVkLCBzaG91bGQgYWRkIGV2ZW50IGhvb2tzLlxuICBcdC8vIEBtZXRob2QgcmVtb3ZlSG9va3MoKVxuICBcdC8vIENhbGxlZCB3aGVuIHRoZSBoYW5kbGVyIGlzIGRpc2FibGVkLCBzaG91bGQgcmVtb3ZlIHRoZSBldmVudCBob29rcyBhZGRlZCBwcmV2aW91c2x5LlxuICB9KTtcblxuICAvLyBAc2VjdGlvbiBUaGVyZSBpcyBzdGF0aWMgZnVuY3Rpb24gd2hpY2ggY2FuIGJlIGNhbGxlZCB3aXRob3V0IGluc3RhbnRpYXRpbmcgTC5IYW5kbGVyOlxuICAvLyBAZnVuY3Rpb24gYWRkVG8obWFwOiBNYXAsIG5hbWU6IFN0cmluZyk6IHRoaXNcbiAgLy8gQWRkcyBhIG5ldyBIYW5kbGVyIHRvIHRoZSBnaXZlbiBtYXAgd2l0aCB0aGUgZ2l2ZW4gbmFtZS5cbiAgSGFuZGxlci5hZGRUbyA9IGZ1bmN0aW9uIChtYXAsIG5hbWUpIHtcbiAgXHRtYXAuYWRkSGFuZGxlcihuYW1lLCB0aGlzKTtcbiAgXHRyZXR1cm4gdGhpcztcbiAgfTtcblxuICB2YXIgTWl4aW4gPSB7RXZlbnRzOiBFdmVudHN9O1xuXG4gIC8qXHJcbiAgICogQGNsYXNzIERyYWdnYWJsZVxyXG4gICAqIEBha2EgTC5EcmFnZ2FibGVcclxuICAgKiBAaW5oZXJpdHMgRXZlbnRlZFxyXG4gICAqXHJcbiAgICogQSBjbGFzcyBmb3IgbWFraW5nIERPTSBlbGVtZW50cyBkcmFnZ2FibGUgKGluY2x1ZGluZyB0b3VjaCBzdXBwb3J0KS5cclxuICAgKiBVc2VkIGludGVybmFsbHkgZm9yIG1hcCBhbmQgbWFya2VyIGRyYWdnaW5nLiBPbmx5IHdvcmtzIGZvciBlbGVtZW50c1xyXG4gICAqIHRoYXQgd2VyZSBwb3NpdGlvbmVkIHdpdGggW2BMLkRvbVV0aWwuc2V0UG9zaXRpb25gXSgjZG9tdXRpbC1zZXRwb3NpdGlvbikuXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqIGBgYGpzXHJcbiAgICogdmFyIGRyYWdnYWJsZSA9IG5ldyBMLkRyYWdnYWJsZShlbGVtZW50VG9EcmFnKTtcclxuICAgKiBkcmFnZ2FibGUuZW5hYmxlKCk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcblxyXG4gIHZhciBTVEFSVCA9IEJyb3dzZXIudG91Y2ggPyAndG91Y2hzdGFydCBtb3VzZWRvd24nIDogJ21vdXNlZG93bic7XHJcblxyXG4gIHZhciBEcmFnZ2FibGUgPSBFdmVudGVkLmV4dGVuZCh7XHJcblxyXG4gIFx0b3B0aW9uczoge1xyXG4gIFx0XHQvLyBAc2VjdGlvblxyXG4gIFx0XHQvLyBAYWthIERyYWdnYWJsZSBvcHRpb25zXHJcbiAgXHRcdC8vIEBvcHRpb24gY2xpY2tUb2xlcmFuY2U6IE51bWJlciA9IDNcclxuICBcdFx0Ly8gVGhlIG1heCBudW1iZXIgb2YgcGl4ZWxzIGEgdXNlciBjYW4gc2hpZnQgdGhlIG1vdXNlIHBvaW50ZXIgZHVyaW5nIGEgY2xpY2tcclxuICBcdFx0Ly8gZm9yIGl0IHRvIGJlIGNvbnNpZGVyZWQgYSB2YWxpZCBjbGljayAoYXMgb3Bwb3NlZCB0byBhIG1vdXNlIGRyYWcpLlxyXG4gIFx0XHRjbGlja1RvbGVyYW5jZTogM1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAY29uc3RydWN0b3IgTC5EcmFnZ2FibGUoZWw6IEhUTUxFbGVtZW50LCBkcmFnSGFuZGxlPzogSFRNTEVsZW1lbnQsIHByZXZlbnRPdXRsaW5lPzogQm9vbGVhbiwgb3B0aW9ucz86IERyYWdnYWJsZSBvcHRpb25zKVxyXG4gIFx0Ly8gQ3JlYXRlcyBhIGBEcmFnZ2FibGVgIG9iamVjdCBmb3IgbW92aW5nIGBlbGAgd2hlbiB5b3Ugc3RhcnQgZHJhZ2dpbmcgdGhlIGBkcmFnSGFuZGxlYCBlbGVtZW50IChlcXVhbHMgYGVsYCBpdHNlbGYgYnkgZGVmYXVsdCkuXHJcbiAgXHRpbml0aWFsaXplOiBmdW5jdGlvbiAoZWxlbWVudCwgZHJhZ1N0YXJ0VGFyZ2V0LCBwcmV2ZW50T3V0bGluZSwgb3B0aW9ucykge1xyXG4gIFx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xyXG5cclxuICBcdFx0dGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XHJcbiAgXHRcdHRoaXMuX2RyYWdTdGFydFRhcmdldCA9IGRyYWdTdGFydFRhcmdldCB8fCBlbGVtZW50O1xyXG4gIFx0XHR0aGlzLl9wcmV2ZW50T3V0bGluZSA9IHByZXZlbnRPdXRsaW5lO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGVuYWJsZSgpXHJcbiAgXHQvLyBFbmFibGVzIHRoZSBkcmFnZ2luZyBhYmlsaXR5XHJcbiAgXHRlbmFibGU6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKHRoaXMuX2VuYWJsZWQpIHsgcmV0dXJuOyB9XHJcblxyXG4gIFx0XHRvbih0aGlzLl9kcmFnU3RhcnRUYXJnZXQsIFNUQVJULCB0aGlzLl9vbkRvd24sIHRoaXMpO1xyXG5cclxuICBcdFx0dGhpcy5fZW5hYmxlZCA9IHRydWU7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZGlzYWJsZSgpXHJcbiAgXHQvLyBEaXNhYmxlcyB0aGUgZHJhZ2dpbmcgYWJpbGl0eVxyXG4gIFx0ZGlzYWJsZTogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRpZiAoIXRoaXMuX2VuYWJsZWQpIHsgcmV0dXJuOyB9XHJcblxyXG4gIFx0XHQvLyBJZiB3ZSdyZSBjdXJyZW50bHkgZHJhZ2dpbmcgdGhpcyBkcmFnZ2FibGUsXHJcbiAgXHRcdC8vIGRpc2FibGluZyBpdCBjb3VudHMgYXMgZmlyc3QgZW5kaW5nIHRoZSBkcmFnLlxyXG4gIFx0XHRpZiAoRHJhZ2dhYmxlLl9kcmFnZ2luZyA9PT0gdGhpcykge1xyXG4gIFx0XHRcdHRoaXMuZmluaXNoRHJhZyh0cnVlKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0b2ZmKHRoaXMuX2RyYWdTdGFydFRhcmdldCwgU1RBUlQsIHRoaXMuX29uRG93biwgdGhpcyk7XHJcblxyXG4gIFx0XHR0aGlzLl9lbmFibGVkID0gZmFsc2U7XHJcbiAgXHRcdHRoaXMuX21vdmVkID0gZmFsc2U7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9vbkRvd246IGZ1bmN0aW9uIChlKSB7XHJcbiAgXHRcdC8vIElnbm9yZSB0aGUgZXZlbnQgaWYgZGlzYWJsZWQ7IHRoaXMgaGFwcGVucyBpbiBJRTExXHJcbiAgXHRcdC8vIHVuZGVyIHNvbWUgY2lyY3Vtc3RhbmNlcywgc2VlICMzNjY2LlxyXG4gIFx0XHRpZiAoIXRoaXMuX2VuYWJsZWQpIHsgcmV0dXJuOyB9XHJcblxyXG4gIFx0XHR0aGlzLl9tb3ZlZCA9IGZhbHNlO1xyXG5cclxuICBcdFx0aWYgKGhhc0NsYXNzKHRoaXMuX2VsZW1lbnQsICdsZWFmbGV0LXpvb20tYW5pbScpKSB7IHJldHVybjsgfVxyXG5cclxuICBcdFx0aWYgKGUudG91Y2hlcyAmJiBlLnRvdWNoZXMubGVuZ3RoICE9PSAxKSB7XHJcbiAgXHRcdFx0Ly8gRmluaXNoIGRyYWdnaW5nIHRvIGF2b2lkIGNvbmZsaWN0IHdpdGggdG91Y2hab29tXHJcbiAgXHRcdFx0aWYgKERyYWdnYWJsZS5fZHJhZ2dpbmcgPT09IHRoaXMpIHtcclxuICBcdFx0XHRcdHRoaXMuZmluaXNoRHJhZygpO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0XHRyZXR1cm47XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmIChEcmFnZ2FibGUuX2RyYWdnaW5nIHx8IGUuc2hpZnRLZXkgfHwgKChlLndoaWNoICE9PSAxKSAmJiAoZS5idXR0b24gIT09IDEpICYmICFlLnRvdWNoZXMpKSB7IHJldHVybjsgfVxyXG4gIFx0XHREcmFnZ2FibGUuX2RyYWdnaW5nID0gdGhpczsgIC8vIFByZXZlbnQgZHJhZ2dpbmcgbXVsdGlwbGUgb2JqZWN0cyBhdCBvbmNlLlxyXG5cclxuICBcdFx0aWYgKHRoaXMuX3ByZXZlbnRPdXRsaW5lKSB7XHJcbiAgXHRcdFx0cHJldmVudE91dGxpbmUodGhpcy5fZWxlbWVudCk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGRpc2FibGVJbWFnZURyYWcoKTtcclxuICBcdFx0ZGlzYWJsZVRleHRTZWxlY3Rpb24oKTtcclxuXHJcbiAgXHRcdGlmICh0aGlzLl9tb3ZpbmcpIHsgcmV0dXJuOyB9XHJcblxyXG4gIFx0XHQvLyBAZXZlbnQgZG93bjogRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiBhIGRyYWcgaXMgYWJvdXQgdG8gc3RhcnQuXHJcbiAgXHRcdHRoaXMuZmlyZSgnZG93bicpO1xyXG5cclxuICBcdFx0dmFyIGZpcnN0ID0gZS50b3VjaGVzID8gZS50b3VjaGVzWzBdIDogZSxcclxuICBcdFx0ICAgIHNpemVkUGFyZW50ID0gZ2V0U2l6ZWRQYXJlbnROb2RlKHRoaXMuX2VsZW1lbnQpO1xyXG5cclxuICBcdFx0dGhpcy5fc3RhcnRQb2ludCA9IG5ldyBQb2ludChmaXJzdC5jbGllbnRYLCBmaXJzdC5jbGllbnRZKTtcclxuICBcdFx0dGhpcy5fc3RhcnRQb3MgPSBnZXRQb3NpdGlvbih0aGlzLl9lbGVtZW50KTtcclxuXHJcbiAgXHRcdC8vIENhY2hlIHRoZSBzY2FsZSwgc28gdGhhdCB3ZSBjYW4gY29udGludW91c2x5IGNvbXBlbnNhdGUgZm9yIGl0IGR1cmluZyBkcmFnIChfb25Nb3ZlKS5cclxuICBcdFx0dGhpcy5fcGFyZW50U2NhbGUgPSBnZXRTY2FsZShzaXplZFBhcmVudCk7XHJcblxyXG4gIFx0XHR2YXIgbW91c2VldmVudCA9IGUudHlwZSA9PT0gJ21vdXNlZG93bic7XHJcbiAgXHRcdG9uKGRvY3VtZW50LCBtb3VzZWV2ZW50ID8gJ21vdXNlbW92ZScgOiAndG91Y2htb3ZlJywgdGhpcy5fb25Nb3ZlLCB0aGlzKTtcclxuICBcdFx0b24oZG9jdW1lbnQsIG1vdXNlZXZlbnQgPyAnbW91c2V1cCcgOiAndG91Y2hlbmQgdG91Y2hjYW5jZWwnLCB0aGlzLl9vblVwLCB0aGlzKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X29uTW92ZTogZnVuY3Rpb24gKGUpIHtcclxuICBcdFx0Ly8gSWdub3JlIHRoZSBldmVudCBpZiBkaXNhYmxlZDsgdGhpcyBoYXBwZW5zIGluIElFMTFcclxuICBcdFx0Ly8gdW5kZXIgc29tZSBjaXJjdW1zdGFuY2VzLCBzZWUgIzM2NjYuXHJcbiAgXHRcdGlmICghdGhpcy5fZW5hYmxlZCkgeyByZXR1cm47IH1cclxuXHJcbiAgXHRcdGlmIChlLnRvdWNoZXMgJiYgZS50b3VjaGVzLmxlbmd0aCA+IDEpIHtcclxuICBcdFx0XHR0aGlzLl9tb3ZlZCA9IHRydWU7XHJcbiAgXHRcdFx0cmV0dXJuO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgZmlyc3QgPSAoZS50b3VjaGVzICYmIGUudG91Y2hlcy5sZW5ndGggPT09IDEgPyBlLnRvdWNoZXNbMF0gOiBlKSxcclxuICBcdFx0ICAgIG9mZnNldCA9IG5ldyBQb2ludChmaXJzdC5jbGllbnRYLCBmaXJzdC5jbGllbnRZKS5fc3VidHJhY3QodGhpcy5fc3RhcnRQb2ludCk7XHJcblxyXG4gIFx0XHRpZiAoIW9mZnNldC54ICYmICFvZmZzZXQueSkgeyByZXR1cm47IH1cclxuICBcdFx0aWYgKE1hdGguYWJzKG9mZnNldC54KSArIE1hdGguYWJzKG9mZnNldC55KSA8IHRoaXMub3B0aW9ucy5jbGlja1RvbGVyYW5jZSkgeyByZXR1cm47IH1cclxuXHJcbiAgXHRcdC8vIFdlIGFzc3VtZSB0aGF0IHRoZSBwYXJlbnQgY29udGFpbmVyJ3MgcG9zaXRpb24sIGJvcmRlciBhbmQgc2NhbGUgZG8gbm90IGNoYW5nZSBmb3IgdGhlIGR1cmF0aW9uIG9mIHRoZSBkcmFnLlxyXG4gIFx0XHQvLyBUaGVyZWZvcmUgdGhlcmUgaXMgbm8gbmVlZCB0byBhY2NvdW50IGZvciB0aGUgcG9zaXRpb24gYW5kIGJvcmRlciAodGhleSBhcmUgZWxpbWluYXRlZCBieSB0aGUgc3VidHJhY3Rpb24pXHJcbiAgXHRcdC8vIGFuZCB3ZSBjYW4gdXNlIHRoZSBjYWNoZWQgdmFsdWUgZm9yIHRoZSBzY2FsZS5cclxuICBcdFx0b2Zmc2V0LnggLz0gdGhpcy5fcGFyZW50U2NhbGUueDtcclxuICBcdFx0b2Zmc2V0LnkgLz0gdGhpcy5fcGFyZW50U2NhbGUueTtcclxuXHJcbiAgXHRcdHByZXZlbnREZWZhdWx0KGUpO1xyXG5cclxuICBcdFx0aWYgKCF0aGlzLl9tb3ZlZCkge1xyXG4gIFx0XHRcdC8vIEBldmVudCBkcmFnc3RhcnQ6IEV2ZW50XHJcbiAgXHRcdFx0Ly8gRmlyZWQgd2hlbiBhIGRyYWcgc3RhcnRzXHJcbiAgXHRcdFx0dGhpcy5maXJlKCdkcmFnc3RhcnQnKTtcclxuXHJcbiAgXHRcdFx0dGhpcy5fbW92ZWQgPSB0cnVlO1xyXG5cclxuICBcdFx0XHRhZGRDbGFzcyhkb2N1bWVudC5ib2R5LCAnbGVhZmxldC1kcmFnZ2luZycpO1xyXG5cclxuICBcdFx0XHR0aGlzLl9sYXN0VGFyZ2V0ID0gZS50YXJnZXQgfHwgZS5zcmNFbGVtZW50O1xyXG4gIFx0XHRcdC8vIElFIGFuZCBFZGdlIGRvIG5vdCBnaXZlIHRoZSA8dXNlPiBlbGVtZW50LCBzbyBmZXRjaCBpdFxyXG4gIFx0XHRcdC8vIGlmIG5lY2Vzc2FyeVxyXG4gIFx0XHRcdGlmICh3aW5kb3cuU1ZHRWxlbWVudEluc3RhbmNlICYmIHRoaXMuX2xhc3RUYXJnZXQgaW5zdGFuY2VvZiB3aW5kb3cuU1ZHRWxlbWVudEluc3RhbmNlKSB7XHJcbiAgXHRcdFx0XHR0aGlzLl9sYXN0VGFyZ2V0ID0gdGhpcy5fbGFzdFRhcmdldC5jb3JyZXNwb25kaW5nVXNlRWxlbWVudDtcclxuICBcdFx0XHR9XHJcbiAgXHRcdFx0YWRkQ2xhc3ModGhpcy5fbGFzdFRhcmdldCwgJ2xlYWZsZXQtZHJhZy10YXJnZXQnKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5fbmV3UG9zID0gdGhpcy5fc3RhcnRQb3MuYWRkKG9mZnNldCk7XHJcbiAgXHRcdHRoaXMuX21vdmluZyA9IHRydWU7XHJcblxyXG4gIFx0XHR0aGlzLl9sYXN0RXZlbnQgPSBlO1xyXG4gIFx0XHR0aGlzLl91cGRhdGVQb3NpdGlvbigpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfdXBkYXRlUG9zaXRpb246IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dmFyIGUgPSB7b3JpZ2luYWxFdmVudDogdGhpcy5fbGFzdEV2ZW50fTtcclxuXHJcbiAgXHRcdC8vIEBldmVudCBwcmVkcmFnOiBFdmVudFxyXG4gIFx0XHQvLyBGaXJlZCBjb250aW51b3VzbHkgZHVyaW5nIGRyYWdnaW5nICpiZWZvcmUqIGVhY2ggY29ycmVzcG9uZGluZ1xyXG4gIFx0XHQvLyB1cGRhdGUgb2YgdGhlIGVsZW1lbnQncyBwb3NpdGlvbi5cclxuICBcdFx0dGhpcy5maXJlKCdwcmVkcmFnJywgZSk7XHJcbiAgXHRcdHNldFBvc2l0aW9uKHRoaXMuX2VsZW1lbnQsIHRoaXMuX25ld1Bvcyk7XHJcblxyXG4gIFx0XHQvLyBAZXZlbnQgZHJhZzogRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgY29udGludW91c2x5IGR1cmluZyBkcmFnZ2luZy5cclxuICBcdFx0dGhpcy5maXJlKCdkcmFnJywgZSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9vblVwOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdC8vIElnbm9yZSB0aGUgZXZlbnQgaWYgZGlzYWJsZWQ7IHRoaXMgaGFwcGVucyBpbiBJRTExXHJcbiAgXHRcdC8vIHVuZGVyIHNvbWUgY2lyY3Vtc3RhbmNlcywgc2VlICMzNjY2LlxyXG4gIFx0XHRpZiAoIXRoaXMuX2VuYWJsZWQpIHsgcmV0dXJuOyB9XHJcbiAgXHRcdHRoaXMuZmluaXNoRHJhZygpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRmaW5pc2hEcmFnOiBmdW5jdGlvbiAobm9JbmVydGlhKSB7XHJcbiAgXHRcdHJlbW92ZUNsYXNzKGRvY3VtZW50LmJvZHksICdsZWFmbGV0LWRyYWdnaW5nJyk7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fbGFzdFRhcmdldCkge1xyXG4gIFx0XHRcdHJlbW92ZUNsYXNzKHRoaXMuX2xhc3RUYXJnZXQsICdsZWFmbGV0LWRyYWctdGFyZ2V0Jyk7XHJcbiAgXHRcdFx0dGhpcy5fbGFzdFRhcmdldCA9IG51bGw7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdG9mZihkb2N1bWVudCwgJ21vdXNlbW92ZSB0b3VjaG1vdmUnLCB0aGlzLl9vbk1vdmUsIHRoaXMpO1xyXG4gIFx0XHRvZmYoZG9jdW1lbnQsICdtb3VzZXVwIHRvdWNoZW5kIHRvdWNoY2FuY2VsJywgdGhpcy5fb25VcCwgdGhpcyk7XHJcblxyXG4gIFx0XHRlbmFibGVJbWFnZURyYWcoKTtcclxuICBcdFx0ZW5hYmxlVGV4dFNlbGVjdGlvbigpO1xyXG5cclxuICBcdFx0dmFyIGZpcmVEcmFnZW5kID0gdGhpcy5fbW92ZWQgJiYgdGhpcy5fbW92aW5nO1xyXG5cclxuICBcdFx0dGhpcy5fbW92aW5nID0gZmFsc2U7XHJcbiAgXHRcdERyYWdnYWJsZS5fZHJhZ2dpbmcgPSBmYWxzZTtcclxuXHJcbiAgXHRcdGlmIChmaXJlRHJhZ2VuZCkge1xyXG4gIFx0XHRcdC8vIEBldmVudCBkcmFnZW5kOiBEcmFnRW5kRXZlbnRcclxuICBcdFx0XHQvLyBGaXJlZCB3aGVuIHRoZSBkcmFnIGVuZHMuXHJcbiAgXHRcdFx0dGhpcy5maXJlKCdkcmFnZW5kJywge1xyXG4gIFx0XHRcdFx0bm9JbmVydGlhOiBub0luZXJ0aWEsXHJcbiAgXHRcdFx0XHRkaXN0YW5jZTogdGhpcy5fbmV3UG9zLmRpc3RhbmNlVG8odGhpcy5fc3RhcnRQb3MpXHJcbiAgXHRcdFx0fSk7XHJcbiAgXHRcdH1cclxuICBcdH1cclxuXHJcbiAgfSk7XG5cbiAgLypcclxuICAgKiBAbmFtZXNwYWNlIFBvbHlVdGlsXHJcbiAgICogVmFyaW91cyB1dGlsaXR5IGZ1bmN0aW9ucyBmb3IgcG9seWdvbiBnZW9tZXRyaWVzLlxyXG4gICAqL1xyXG5cclxuICAvKiBAZnVuY3Rpb24gY2xpcFBvbHlnb24ocG9pbnRzOiBQb2ludFtdLCBib3VuZHM6IEJvdW5kcywgcm91bmQ/OiBCb29sZWFuKTogUG9pbnRbXVxyXG4gICAqIENsaXBzIHRoZSBwb2x5Z29uIGdlb21ldHJ5IGRlZmluZWQgYnkgdGhlIGdpdmVuIGBwb2ludHNgIGJ5IHRoZSBnaXZlbiBib3VuZHMgKHVzaW5nIHRoZSBbU3V0aGVybGFuZC1Ib2RnbWFuIGFsZ29yaXRobV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU3V0aGVybGFuZCVFMiU4MCU5M0hvZGdtYW5fYWxnb3JpdGhtKSkuXHJcbiAgICogVXNlZCBieSBMZWFmbGV0IHRvIG9ubHkgc2hvdyBwb2x5Z29uIHBvaW50cyB0aGF0IGFyZSBvbiB0aGUgc2NyZWVuIG9yIG5lYXIsIGluY3JlYXNpbmdcclxuICAgKiBwZXJmb3JtYW5jZS4gTm90ZSB0aGF0IHBvbHlnb24gcG9pbnRzIG5lZWRzIGRpZmZlcmVudCBhbGdvcml0aG0gZm9yIGNsaXBwaW5nXHJcbiAgICogdGhhbiBwb2x5bGluZSwgc28gdGhlcmUncyBhIHNlcGFyYXRlIG1ldGhvZCBmb3IgaXQuXHJcbiAgICovXHJcbiAgZnVuY3Rpb24gY2xpcFBvbHlnb24ocG9pbnRzLCBib3VuZHMsIHJvdW5kKSB7XHJcbiAgXHR2YXIgY2xpcHBlZFBvaW50cyxcclxuICBcdCAgICBlZGdlcyA9IFsxLCA0LCAyLCA4XSxcclxuICBcdCAgICBpLCBqLCBrLFxyXG4gIFx0ICAgIGEsIGIsXHJcbiAgXHQgICAgbGVuLCBlZGdlLCBwO1xyXG5cclxuICBcdGZvciAoaSA9IDAsIGxlbiA9IHBvaW50cy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gIFx0XHRwb2ludHNbaV0uX2NvZGUgPSBfZ2V0Qml0Q29kZShwb2ludHNbaV0sIGJvdW5kcyk7XHJcbiAgXHR9XHJcblxyXG4gIFx0Ly8gZm9yIGVhY2ggZWRnZSAobGVmdCwgYm90dG9tLCByaWdodCwgdG9wKVxyXG4gIFx0Zm9yIChrID0gMDsgayA8IDQ7IGsrKykge1xyXG4gIFx0XHRlZGdlID0gZWRnZXNba107XHJcbiAgXHRcdGNsaXBwZWRQb2ludHMgPSBbXTtcclxuXHJcbiAgXHRcdGZvciAoaSA9IDAsIGxlbiA9IHBvaW50cy5sZW5ndGgsIGogPSBsZW4gLSAxOyBpIDwgbGVuOyBqID0gaSsrKSB7XHJcbiAgXHRcdFx0YSA9IHBvaW50c1tpXTtcclxuICBcdFx0XHRiID0gcG9pbnRzW2pdO1xyXG5cclxuICBcdFx0XHQvLyBpZiBhIGlzIGluc2lkZSB0aGUgY2xpcCB3aW5kb3dcclxuICBcdFx0XHRpZiAoIShhLl9jb2RlICYgZWRnZSkpIHtcclxuICBcdFx0XHRcdC8vIGlmIGIgaXMgb3V0c2lkZSB0aGUgY2xpcCB3aW5kb3cgKGEtPmIgZ29lcyBvdXQgb2Ygc2NyZWVuKVxyXG4gIFx0XHRcdFx0aWYgKGIuX2NvZGUgJiBlZGdlKSB7XHJcbiAgXHRcdFx0XHRcdHAgPSBfZ2V0RWRnZUludGVyc2VjdGlvbihiLCBhLCBlZGdlLCBib3VuZHMsIHJvdW5kKTtcclxuICBcdFx0XHRcdFx0cC5fY29kZSA9IF9nZXRCaXRDb2RlKHAsIGJvdW5kcyk7XHJcbiAgXHRcdFx0XHRcdGNsaXBwZWRQb2ludHMucHVzaChwKTtcclxuICBcdFx0XHRcdH1cclxuICBcdFx0XHRcdGNsaXBwZWRQb2ludHMucHVzaChhKTtcclxuXHJcbiAgXHRcdFx0Ly8gZWxzZSBpZiBiIGlzIGluc2lkZSB0aGUgY2xpcCB3aW5kb3cgKGEtPmIgZW50ZXJzIHRoZSBzY3JlZW4pXHJcbiAgXHRcdFx0fSBlbHNlIGlmICghKGIuX2NvZGUgJiBlZGdlKSkge1xyXG4gIFx0XHRcdFx0cCA9IF9nZXRFZGdlSW50ZXJzZWN0aW9uKGIsIGEsIGVkZ2UsIGJvdW5kcywgcm91bmQpO1xyXG4gIFx0XHRcdFx0cC5fY29kZSA9IF9nZXRCaXRDb2RlKHAsIGJvdW5kcyk7XHJcbiAgXHRcdFx0XHRjbGlwcGVkUG9pbnRzLnB1c2gocCk7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcbiAgXHRcdHBvaW50cyA9IGNsaXBwZWRQb2ludHM7XHJcbiAgXHR9XHJcblxyXG4gIFx0cmV0dXJuIHBvaW50cztcclxuICB9XHJcblxyXG4gIC8qIEBmdW5jdGlvbiBwb2x5Z29uQ2VudGVyKGxhdGxuZ3M6IExhdExuZ1tdLCBjcnM6IENSUyk6IExhdExuZ1xyXG4gICAqIFJldHVybnMgdGhlIGNlbnRlciAoW2NlbnRyb2lkXShodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NlbnRyb2lkKSkgb2YgdGhlIHBhc3NlZCBMYXRMbmdzIChmaXJzdCByaW5nKSBmcm9tIGEgcG9seWdvbi5cclxuICAgKi9cclxuICBmdW5jdGlvbiBwb2x5Z29uQ2VudGVyKGxhdGxuZ3MsIGNycykge1xyXG4gIFx0dmFyIGksIGosIHAxLCBwMiwgZiwgYXJlYSwgeCwgeSwgY2VudGVyO1xyXG5cclxuICBcdGlmICghbGF0bG5ncyB8fCBsYXRsbmdzLmxlbmd0aCA9PT0gMCkge1xyXG4gIFx0XHR0aHJvdyBuZXcgRXJyb3IoJ2xhdGxuZ3Mgbm90IHBhc3NlZCcpO1xyXG4gIFx0fVxyXG5cclxuICBcdGlmICghaXNGbGF0KGxhdGxuZ3MpKSB7XHJcbiAgXHRcdGNvbnNvbGUud2FybignbGF0bG5ncyBhcmUgbm90IGZsYXQhIE9ubHkgdGhlIGZpcnN0IHJpbmcgd2lsbCBiZSB1c2VkJyk7XHJcbiAgXHRcdGxhdGxuZ3MgPSBsYXRsbmdzWzBdO1xyXG4gIFx0fVxyXG5cclxuICBcdHZhciBjZW50cm9pZExhdExuZyA9IHRvTGF0TG5nKFswLCAwXSk7XHJcblxyXG4gIFx0dmFyIGJvdW5kcyA9IHRvTGF0TG5nQm91bmRzKGxhdGxuZ3MpO1xyXG4gIFx0dmFyIGFyZWFCb3VuZHMgPSBib3VuZHMuZ2V0Tm9ydGhXZXN0KCkuZGlzdGFuY2VUbyhib3VuZHMuZ2V0U291dGhXZXN0KCkpICogYm91bmRzLmdldE5vcnRoRWFzdCgpLmRpc3RhbmNlVG8oYm91bmRzLmdldE5vcnRoV2VzdCgpKTtcclxuICBcdC8vIHRlc3RzIHNob3dlZCB0aGF0IGJlbG93IDE3MDAgcm91bmRpbmcgZXJyb3JzIGFyZSBoYXBwZW5pbmdcclxuICBcdGlmIChhcmVhQm91bmRzIDwgMTcwMCkge1xyXG4gIFx0XHQvLyBnZXR0aW5nIGEgaW5leGFjdCBjZW50ZXIsIHRvIG1vdmUgdGhlIGxhdGxuZ3MgbmVhciB0byBbMCwgMF0gdG8gcHJldmVudCByb3VuZGluZyBlcnJvcnNcclxuICBcdFx0Y2VudHJvaWRMYXRMbmcgPSBjZW50cm9pZChsYXRsbmdzKTtcclxuICBcdH1cclxuXHJcbiAgXHR2YXIgbGVuID0gbGF0bG5ncy5sZW5ndGg7XHJcbiAgXHR2YXIgcG9pbnRzID0gW107XHJcbiAgXHRmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcclxuICBcdFx0dmFyIGxhdGxuZyA9IHRvTGF0TG5nKGxhdGxuZ3NbaV0pO1xyXG4gIFx0XHRwb2ludHMucHVzaChjcnMucHJvamVjdCh0b0xhdExuZyhbbGF0bG5nLmxhdCAtIGNlbnRyb2lkTGF0TG5nLmxhdCwgbGF0bG5nLmxuZyAtIGNlbnRyb2lkTGF0TG5nLmxuZ10pKSk7XHJcbiAgXHR9XHJcblxyXG4gIFx0YXJlYSA9IHggPSB5ID0gMDtcclxuXHJcbiAgXHQvLyBwb2x5Z29uIGNlbnRyb2lkIGFsZ29yaXRobTtcclxuICBcdGZvciAoaSA9IDAsIGogPSBsZW4gLSAxOyBpIDwgbGVuOyBqID0gaSsrKSB7XHJcbiAgXHRcdHAxID0gcG9pbnRzW2ldO1xyXG4gIFx0XHRwMiA9IHBvaW50c1tqXTtcclxuXHJcbiAgXHRcdGYgPSBwMS55ICogcDIueCAtIHAyLnkgKiBwMS54O1xyXG4gIFx0XHR4ICs9IChwMS54ICsgcDIueCkgKiBmO1xyXG4gIFx0XHR5ICs9IChwMS55ICsgcDIueSkgKiBmO1xyXG4gIFx0XHRhcmVhICs9IGYgKiAzO1xyXG4gIFx0fVxyXG5cclxuICBcdGlmIChhcmVhID09PSAwKSB7XHJcbiAgXHRcdC8vIFBvbHlnb24gaXMgc28gc21hbGwgdGhhdCBhbGwgcG9pbnRzIGFyZSBvbiBzYW1lIHBpeGVsLlxyXG4gIFx0XHRjZW50ZXIgPSBwb2ludHNbMF07XHJcbiAgXHR9IGVsc2Uge1xyXG4gIFx0XHRjZW50ZXIgPSBbeCAvIGFyZWEsIHkgLyBhcmVhXTtcclxuICBcdH1cclxuXHJcbiAgXHR2YXIgbGF0bG5nQ2VudGVyID0gY3JzLnVucHJvamVjdCh0b1BvaW50KGNlbnRlcikpO1xyXG4gIFx0cmV0dXJuIHRvTGF0TG5nKFtsYXRsbmdDZW50ZXIubGF0ICsgY2VudHJvaWRMYXRMbmcubGF0LCBsYXRsbmdDZW50ZXIubG5nICsgY2VudHJvaWRMYXRMbmcubG5nXSk7XHJcbiAgfVxyXG5cclxuICAvKiBAZnVuY3Rpb24gY2VudHJvaWQobGF0bG5nczogTGF0TG5nW10pOiBMYXRMbmdcclxuICAgKiBSZXR1cm5zIHRoZSAnY2VudGVyIG9mIG1hc3MnIG9mIHRoZSBwYXNzZWQgTGF0TG5ncy5cclxuICAgKi9cclxuICBmdW5jdGlvbiBjZW50cm9pZChjb29yZHMpIHtcclxuICBcdHZhciBsYXRTdW0gPSAwO1xyXG4gIFx0dmFyIGxuZ1N1bSA9IDA7XHJcbiAgXHR2YXIgbGVuID0gMDtcclxuICBcdGZvciAodmFyIGkgPSAwOyBpIDwgY29vcmRzLmxlbmd0aDsgaSsrKSB7XHJcbiAgXHRcdHZhciBsYXRsbmcgPSB0b0xhdExuZyhjb29yZHNbaV0pO1xyXG4gIFx0XHRsYXRTdW0gKz0gbGF0bG5nLmxhdDtcclxuICBcdFx0bG5nU3VtICs9IGxhdGxuZy5sbmc7XHJcbiAgXHRcdGxlbisrO1xyXG4gIFx0fVxyXG4gIFx0cmV0dXJuIHRvTGF0TG5nKFtsYXRTdW0gLyBsZW4sIGxuZ1N1bSAvIGxlbl0pO1xyXG4gIH1cblxuICB2YXIgUG9seVV0aWwgPSB7XG4gICAgX19wcm90b19fOiBudWxsLFxuICAgIGNsaXBQb2x5Z29uOiBjbGlwUG9seWdvbixcbiAgICBwb2x5Z29uQ2VudGVyOiBwb2x5Z29uQ2VudGVyLFxuICAgIGNlbnRyb2lkOiBjZW50cm9pZFxuICB9O1xuXG4gIC8qXHJcbiAgICogQG5hbWVzcGFjZSBMaW5lVXRpbFxyXG4gICAqXHJcbiAgICogVmFyaW91cyB1dGlsaXR5IGZ1bmN0aW9ucyBmb3IgcG9seWxpbmUgcG9pbnRzIHByb2Nlc3NpbmcsIHVzZWQgYnkgTGVhZmxldCBpbnRlcm5hbGx5IHRvIG1ha2UgcG9seWxpbmVzIGxpZ2h0bmluZy1mYXN0LlxyXG4gICAqL1xyXG5cclxuICAvLyBTaW1wbGlmeSBwb2x5bGluZSB3aXRoIHZlcnRleCByZWR1Y3Rpb24gYW5kIERvdWdsYXMtUGV1Y2tlciBzaW1wbGlmaWNhdGlvbi5cclxuICAvLyBJbXByb3ZlcyByZW5kZXJpbmcgcGVyZm9ybWFuY2UgZHJhbWF0aWNhbGx5IGJ5IGxlc3NlbmluZyB0aGUgbnVtYmVyIG9mIHBvaW50cyB0byBkcmF3LlxyXG5cclxuICAvLyBAZnVuY3Rpb24gc2ltcGxpZnkocG9pbnRzOiBQb2ludFtdLCB0b2xlcmFuY2U6IE51bWJlcik6IFBvaW50W11cclxuICAvLyBEcmFtYXRpY2FsbHkgcmVkdWNlcyB0aGUgbnVtYmVyIG9mIHBvaW50cyBpbiBhIHBvbHlsaW5lIHdoaWxlIHJldGFpbmluZ1xyXG4gIC8vIGl0cyBzaGFwZSBhbmQgcmV0dXJucyBhIG5ldyBhcnJheSBvZiBzaW1wbGlmaWVkIHBvaW50cywgdXNpbmcgdGhlXHJcbiAgLy8gW1JhbWVyLURvdWdsYXMtUGV1Y2tlciBhbGdvcml0aG1dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1JhbWVyLURvdWdsYXMtUGV1Y2tlcl9hbGdvcml0aG0pLlxyXG4gIC8vIFVzZWQgZm9yIGEgaHVnZSBwZXJmb3JtYW5jZSBib29zdCB3aGVuIHByb2Nlc3NpbmcvZGlzcGxheWluZyBMZWFmbGV0IHBvbHlsaW5lcyBmb3JcclxuICAvLyBlYWNoIHpvb20gbGV2ZWwgYW5kIGFsc28gcmVkdWNpbmcgdmlzdWFsIG5vaXNlLiB0b2xlcmFuY2UgYWZmZWN0cyB0aGUgYW1vdW50IG9mXHJcbiAgLy8gc2ltcGxpZmljYXRpb24gKGxlc3NlciB2YWx1ZSBtZWFucyBoaWdoZXIgcXVhbGl0eSBidXQgc2xvd2VyIGFuZCB3aXRoIG1vcmUgcG9pbnRzKS5cclxuICAvLyBBbHNvIHJlbGVhc2VkIGFzIGEgc2VwYXJhdGVkIG1pY3JvLWxpYnJhcnkgW1NpbXBsaWZ5LmpzXShodHRwczovL21vdXJuZXIuZ2l0aHViLmlvL3NpbXBsaWZ5LWpzLykuXHJcbiAgZnVuY3Rpb24gc2ltcGxpZnkocG9pbnRzLCB0b2xlcmFuY2UpIHtcclxuICBcdGlmICghdG9sZXJhbmNlIHx8ICFwb2ludHMubGVuZ3RoKSB7XHJcbiAgXHRcdHJldHVybiBwb2ludHMuc2xpY2UoKTtcclxuICBcdH1cclxuXHJcbiAgXHR2YXIgc3FUb2xlcmFuY2UgPSB0b2xlcmFuY2UgKiB0b2xlcmFuY2U7XHJcblxyXG4gIFx0ICAgIC8vIHN0YWdlIDE6IHZlcnRleCByZWR1Y3Rpb25cclxuICBcdCAgICBwb2ludHMgPSBfcmVkdWNlUG9pbnRzKHBvaW50cywgc3FUb2xlcmFuY2UpO1xyXG5cclxuICBcdCAgICAvLyBzdGFnZSAyOiBEb3VnbGFzLVBldWNrZXIgc2ltcGxpZmljYXRpb25cclxuICBcdCAgICBwb2ludHMgPSBfc2ltcGxpZnlEUChwb2ludHMsIHNxVG9sZXJhbmNlKTtcclxuXHJcbiAgXHRyZXR1cm4gcG9pbnRzO1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIHBvaW50VG9TZWdtZW50RGlzdGFuY2UocDogUG9pbnQsIHAxOiBQb2ludCwgcDI6IFBvaW50KTogTnVtYmVyXHJcbiAgLy8gUmV0dXJucyB0aGUgZGlzdGFuY2UgYmV0d2VlbiBwb2ludCBgcGAgYW5kIHNlZ21lbnQgYHAxYCB0byBgcDJgLlxyXG4gIGZ1bmN0aW9uIHBvaW50VG9TZWdtZW50RGlzdGFuY2UocCwgcDEsIHAyKSB7XHJcbiAgXHRyZXR1cm4gTWF0aC5zcXJ0KF9zcUNsb3Nlc3RQb2ludE9uU2VnbWVudChwLCBwMSwgcDIsIHRydWUpKTtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBjbG9zZXN0UG9pbnRPblNlZ21lbnQocDogUG9pbnQsIHAxOiBQb2ludCwgcDI6IFBvaW50KTogTnVtYmVyXHJcbiAgLy8gUmV0dXJucyB0aGUgY2xvc2VzdCBwb2ludCBmcm9tIGEgcG9pbnQgYHBgIG9uIGEgc2VnbWVudCBgcDFgIHRvIGBwMmAuXHJcbiAgZnVuY3Rpb24gY2xvc2VzdFBvaW50T25TZWdtZW50KHAsIHAxLCBwMikge1xyXG4gIFx0cmV0dXJuIF9zcUNsb3Nlc3RQb2ludE9uU2VnbWVudChwLCBwMSwgcDIpO1xyXG4gIH1cclxuXHJcbiAgLy8gUmFtZXItRG91Z2xhcy1QZXVja2VyIHNpbXBsaWZpY2F0aW9uLCBzZWUgaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUmFtZXItRG91Z2xhcy1QZXVja2VyX2FsZ29yaXRobVxyXG4gIGZ1bmN0aW9uIF9zaW1wbGlmeURQKHBvaW50cywgc3FUb2xlcmFuY2UpIHtcclxuXHJcbiAgXHR2YXIgbGVuID0gcG9pbnRzLmxlbmd0aCxcclxuICBcdCAgICBBcnJheUNvbnN0cnVjdG9yID0gdHlwZW9mIFVpbnQ4QXJyYXkgIT09IHVuZGVmaW5lZCArICcnID8gVWludDhBcnJheSA6IEFycmF5LFxyXG4gIFx0ICAgIG1hcmtlcnMgPSBuZXcgQXJyYXlDb25zdHJ1Y3RvcihsZW4pO1xyXG5cclxuICBcdCAgICBtYXJrZXJzWzBdID0gbWFya2Vyc1tsZW4gLSAxXSA9IDE7XHJcblxyXG4gIFx0X3NpbXBsaWZ5RFBTdGVwKHBvaW50cywgbWFya2Vycywgc3FUb2xlcmFuY2UsIDAsIGxlbiAtIDEpO1xyXG5cclxuICBcdHZhciBpLFxyXG4gIFx0ICAgIG5ld1BvaW50cyA9IFtdO1xyXG5cclxuICBcdGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xyXG4gIFx0XHRpZiAobWFya2Vyc1tpXSkge1xyXG4gIFx0XHRcdG5ld1BvaW50cy5wdXNoKHBvaW50c1tpXSk7XHJcbiAgXHRcdH1cclxuICBcdH1cclxuXHJcbiAgXHRyZXR1cm4gbmV3UG9pbnRzO1xyXG4gIH1cclxuXHJcbiAgZnVuY3Rpb24gX3NpbXBsaWZ5RFBTdGVwKHBvaW50cywgbWFya2Vycywgc3FUb2xlcmFuY2UsIGZpcnN0LCBsYXN0KSB7XHJcblxyXG4gIFx0dmFyIG1heFNxRGlzdCA9IDAsXHJcbiAgXHRpbmRleCwgaSwgc3FEaXN0O1xyXG5cclxuICBcdGZvciAoaSA9IGZpcnN0ICsgMTsgaSA8PSBsYXN0IC0gMTsgaSsrKSB7XHJcbiAgXHRcdHNxRGlzdCA9IF9zcUNsb3Nlc3RQb2ludE9uU2VnbWVudChwb2ludHNbaV0sIHBvaW50c1tmaXJzdF0sIHBvaW50c1tsYXN0XSwgdHJ1ZSk7XHJcblxyXG4gIFx0XHRpZiAoc3FEaXN0ID4gbWF4U3FEaXN0KSB7XHJcbiAgXHRcdFx0aW5kZXggPSBpO1xyXG4gIFx0XHRcdG1heFNxRGlzdCA9IHNxRGlzdDtcclxuICBcdFx0fVxyXG4gIFx0fVxyXG5cclxuICBcdGlmIChtYXhTcURpc3QgPiBzcVRvbGVyYW5jZSkge1xyXG4gIFx0XHRtYXJrZXJzW2luZGV4XSA9IDE7XHJcblxyXG4gIFx0XHRfc2ltcGxpZnlEUFN0ZXAocG9pbnRzLCBtYXJrZXJzLCBzcVRvbGVyYW5jZSwgZmlyc3QsIGluZGV4KTtcclxuICBcdFx0X3NpbXBsaWZ5RFBTdGVwKHBvaW50cywgbWFya2Vycywgc3FUb2xlcmFuY2UsIGluZGV4LCBsYXN0KTtcclxuICBcdH1cclxuICB9XHJcblxyXG4gIC8vIHJlZHVjZSBwb2ludHMgdGhhdCBhcmUgdG9vIGNsb3NlIHRvIGVhY2ggb3RoZXIgdG8gYSBzaW5nbGUgcG9pbnRcclxuICBmdW5jdGlvbiBfcmVkdWNlUG9pbnRzKHBvaW50cywgc3FUb2xlcmFuY2UpIHtcclxuICBcdHZhciByZWR1Y2VkUG9pbnRzID0gW3BvaW50c1swXV07XHJcblxyXG4gIFx0Zm9yICh2YXIgaSA9IDEsIHByZXYgPSAwLCBsZW4gPSBwb2ludHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuICBcdFx0aWYgKF9zcURpc3QocG9pbnRzW2ldLCBwb2ludHNbcHJldl0pID4gc3FUb2xlcmFuY2UpIHtcclxuICBcdFx0XHRyZWR1Y2VkUG9pbnRzLnB1c2gocG9pbnRzW2ldKTtcclxuICBcdFx0XHRwcmV2ID0gaTtcclxuICBcdFx0fVxyXG4gIFx0fVxyXG4gIFx0aWYgKHByZXYgPCBsZW4gLSAxKSB7XHJcbiAgXHRcdHJlZHVjZWRQb2ludHMucHVzaChwb2ludHNbbGVuIC0gMV0pO1xyXG4gIFx0fVxyXG4gIFx0cmV0dXJuIHJlZHVjZWRQb2ludHM7XHJcbiAgfVxyXG5cclxuICB2YXIgX2xhc3RDb2RlO1xyXG5cclxuICAvLyBAZnVuY3Rpb24gY2xpcFNlZ21lbnQoYTogUG9pbnQsIGI6IFBvaW50LCBib3VuZHM6IEJvdW5kcywgdXNlTGFzdENvZGU/OiBCb29sZWFuLCByb3VuZD86IEJvb2xlYW4pOiBQb2ludFtdfEJvb2xlYW5cclxuICAvLyBDbGlwcyB0aGUgc2VnbWVudCBhIHRvIGIgYnkgcmVjdGFuZ3VsYXIgYm91bmRzIHdpdGggdGhlXHJcbiAgLy8gW0NvaGVuLVN1dGhlcmxhbmQgYWxnb3JpdGhtXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Db2hlbiVFMiU4MCU5M1N1dGhlcmxhbmRfYWxnb3JpdGhtKVxyXG4gIC8vIChtb2RpZnlpbmcgdGhlIHNlZ21lbnQgcG9pbnRzIGRpcmVjdGx5ISkuIFVzZWQgYnkgTGVhZmxldCB0byBvbmx5IHNob3cgcG9seWxpbmVcclxuICAvLyBwb2ludHMgdGhhdCBhcmUgb24gdGhlIHNjcmVlbiBvciBuZWFyLCBpbmNyZWFzaW5nIHBlcmZvcm1hbmNlLlxyXG4gIGZ1bmN0aW9uIGNsaXBTZWdtZW50KGEsIGIsIGJvdW5kcywgdXNlTGFzdENvZGUsIHJvdW5kKSB7XHJcbiAgXHR2YXIgY29kZUEgPSB1c2VMYXN0Q29kZSA/IF9sYXN0Q29kZSA6IF9nZXRCaXRDb2RlKGEsIGJvdW5kcyksXHJcbiAgXHQgICAgY29kZUIgPSBfZ2V0Qml0Q29kZShiLCBib3VuZHMpLFxyXG5cclxuICBcdCAgICBjb2RlT3V0LCBwLCBuZXdDb2RlO1xyXG5cclxuICBcdCAgICAvLyBzYXZlIDJuZCBjb2RlIHRvIGF2b2lkIGNhbGN1bGF0aW5nIGl0IG9uIHRoZSBuZXh0IHNlZ21lbnRcclxuICBcdCAgICBfbGFzdENvZGUgPSBjb2RlQjtcclxuXHJcbiAgXHR3aGlsZSAodHJ1ZSkge1xyXG4gIFx0XHQvLyBpZiBhLGIgaXMgaW5zaWRlIHRoZSBjbGlwIHdpbmRvdyAodHJpdmlhbCBhY2NlcHQpXHJcbiAgXHRcdGlmICghKGNvZGVBIHwgY29kZUIpKSB7XHJcbiAgXHRcdFx0cmV0dXJuIFthLCBiXTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gaWYgYSxiIGlzIG91dHNpZGUgdGhlIGNsaXAgd2luZG93ICh0cml2aWFsIHJlamVjdClcclxuICBcdFx0aWYgKGNvZGVBICYgY29kZUIpIHtcclxuICBcdFx0XHRyZXR1cm4gZmFsc2U7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdC8vIG90aGVyIGNhc2VzXHJcbiAgXHRcdGNvZGVPdXQgPSBjb2RlQSB8fCBjb2RlQjtcclxuICBcdFx0cCA9IF9nZXRFZGdlSW50ZXJzZWN0aW9uKGEsIGIsIGNvZGVPdXQsIGJvdW5kcywgcm91bmQpO1xyXG4gIFx0XHRuZXdDb2RlID0gX2dldEJpdENvZGUocCwgYm91bmRzKTtcclxuXHJcbiAgXHRcdGlmIChjb2RlT3V0ID09PSBjb2RlQSkge1xyXG4gIFx0XHRcdGEgPSBwO1xyXG4gIFx0XHRcdGNvZGVBID0gbmV3Q29kZTtcclxuICBcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRiID0gcDtcclxuICBcdFx0XHRjb2RlQiA9IG5ld0NvZGU7XHJcbiAgXHRcdH1cclxuICBcdH1cclxuICB9XHJcblxyXG4gIGZ1bmN0aW9uIF9nZXRFZGdlSW50ZXJzZWN0aW9uKGEsIGIsIGNvZGUsIGJvdW5kcywgcm91bmQpIHtcclxuICBcdHZhciBkeCA9IGIueCAtIGEueCxcclxuICBcdCAgICBkeSA9IGIueSAtIGEueSxcclxuICBcdCAgICBtaW4gPSBib3VuZHMubWluLFxyXG4gIFx0ICAgIG1heCA9IGJvdW5kcy5tYXgsXHJcbiAgXHQgICAgeCwgeTtcclxuXHJcbiAgXHRpZiAoY29kZSAmIDgpIHsgLy8gdG9wXHJcbiAgXHRcdHggPSBhLnggKyBkeCAqIChtYXgueSAtIGEueSkgLyBkeTtcclxuICBcdFx0eSA9IG1heC55O1xyXG5cclxuICBcdH0gZWxzZSBpZiAoY29kZSAmIDQpIHsgLy8gYm90dG9tXHJcbiAgXHRcdHggPSBhLnggKyBkeCAqIChtaW4ueSAtIGEueSkgLyBkeTtcclxuICBcdFx0eSA9IG1pbi55O1xyXG5cclxuICBcdH0gZWxzZSBpZiAoY29kZSAmIDIpIHsgLy8gcmlnaHRcclxuICBcdFx0eCA9IG1heC54O1xyXG4gIFx0XHR5ID0gYS55ICsgZHkgKiAobWF4LnggLSBhLngpIC8gZHg7XHJcblxyXG4gIFx0fSBlbHNlIGlmIChjb2RlICYgMSkgeyAvLyBsZWZ0XHJcbiAgXHRcdHggPSBtaW4ueDtcclxuICBcdFx0eSA9IGEueSArIGR5ICogKG1pbi54IC0gYS54KSAvIGR4O1xyXG4gIFx0fVxyXG5cclxuICBcdHJldHVybiBuZXcgUG9pbnQoeCwgeSwgcm91bmQpO1xyXG4gIH1cclxuXHJcbiAgZnVuY3Rpb24gX2dldEJpdENvZGUocCwgYm91bmRzKSB7XHJcbiAgXHR2YXIgY29kZSA9IDA7XHJcblxyXG4gIFx0aWYgKHAueCA8IGJvdW5kcy5taW4ueCkgeyAvLyBsZWZ0XHJcbiAgXHRcdGNvZGUgfD0gMTtcclxuICBcdH0gZWxzZSBpZiAocC54ID4gYm91bmRzLm1heC54KSB7IC8vIHJpZ2h0XHJcbiAgXHRcdGNvZGUgfD0gMjtcclxuICBcdH1cclxuXHJcbiAgXHRpZiAocC55IDwgYm91bmRzLm1pbi55KSB7IC8vIGJvdHRvbVxyXG4gIFx0XHRjb2RlIHw9IDQ7XHJcbiAgXHR9IGVsc2UgaWYgKHAueSA+IGJvdW5kcy5tYXgueSkgeyAvLyB0b3BcclxuICBcdFx0Y29kZSB8PSA4O1xyXG4gIFx0fVxyXG5cclxuICBcdHJldHVybiBjb2RlO1xyXG4gIH1cclxuXHJcbiAgLy8gc3F1YXJlIGRpc3RhbmNlICh0byBhdm9pZCB1bm5lY2Vzc2FyeSBNYXRoLnNxcnQgY2FsbHMpXHJcbiAgZnVuY3Rpb24gX3NxRGlzdChwMSwgcDIpIHtcclxuICBcdHZhciBkeCA9IHAyLnggLSBwMS54LFxyXG4gIFx0ICAgIGR5ID0gcDIueSAtIHAxLnk7XHJcbiAgXHRyZXR1cm4gZHggKiBkeCArIGR5ICogZHk7XHJcbiAgfVxyXG5cclxuICAvLyByZXR1cm4gY2xvc2VzdCBwb2ludCBvbiBzZWdtZW50IG9yIGRpc3RhbmNlIHRvIHRoYXQgcG9pbnRcclxuICBmdW5jdGlvbiBfc3FDbG9zZXN0UG9pbnRPblNlZ21lbnQocCwgcDEsIHAyLCBzcURpc3QpIHtcclxuICBcdHZhciB4ID0gcDEueCxcclxuICBcdCAgICB5ID0gcDEueSxcclxuICBcdCAgICBkeCA9IHAyLnggLSB4LFxyXG4gIFx0ICAgIGR5ID0gcDIueSAtIHksXHJcbiAgXHQgICAgZG90ID0gZHggKiBkeCArIGR5ICogZHksXHJcbiAgXHQgICAgdDtcclxuXHJcbiAgXHRpZiAoZG90ID4gMCkge1xyXG4gIFx0XHR0ID0gKChwLnggLSB4KSAqIGR4ICsgKHAueSAtIHkpICogZHkpIC8gZG90O1xyXG5cclxuICBcdFx0aWYgKHQgPiAxKSB7XHJcbiAgXHRcdFx0eCA9IHAyLng7XHJcbiAgXHRcdFx0eSA9IHAyLnk7XHJcbiAgXHRcdH0gZWxzZSBpZiAodCA+IDApIHtcclxuICBcdFx0XHR4ICs9IGR4ICogdDtcclxuICBcdFx0XHR5ICs9IGR5ICogdDtcclxuICBcdFx0fVxyXG4gIFx0fVxyXG5cclxuICBcdGR4ID0gcC54IC0geDtcclxuICBcdGR5ID0gcC55IC0geTtcclxuXHJcbiAgXHRyZXR1cm4gc3FEaXN0ID8gZHggKiBkeCArIGR5ICogZHkgOiBuZXcgUG9pbnQoeCwgeSk7XHJcbiAgfVxyXG5cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGlzRmxhdChsYXRsbmdzOiBMYXRMbmdbXSk6IEJvb2xlYW5cclxuICAvLyBSZXR1cm5zIHRydWUgaWYgYGxhdGxuZ3NgIGlzIGEgZmxhdCBhcnJheSwgZmFsc2UgaXMgbmVzdGVkLlxyXG4gIGZ1bmN0aW9uIGlzRmxhdChsYXRsbmdzKSB7XHJcbiAgXHRyZXR1cm4gIWlzQXJyYXkobGF0bG5nc1swXSkgfHwgKHR5cGVvZiBsYXRsbmdzWzBdWzBdICE9PSAnb2JqZWN0JyAmJiB0eXBlb2YgbGF0bG5nc1swXVswXSAhPT0gJ3VuZGVmaW5lZCcpO1xyXG4gIH1cclxuXHJcbiAgZnVuY3Rpb24gX2ZsYXQobGF0bG5ncykge1xyXG4gIFx0Y29uc29sZS53YXJuKCdEZXByZWNhdGVkIHVzZSBvZiBfZmxhdCwgcGxlYXNlIHVzZSBMLkxpbmVVdGlsLmlzRmxhdCBpbnN0ZWFkLicpO1xyXG4gIFx0cmV0dXJuIGlzRmxhdChsYXRsbmdzKTtcclxuICB9XHJcblxyXG4gIC8qIEBmdW5jdGlvbiBwb2x5bGluZUNlbnRlcihsYXRsbmdzOiBMYXRMbmdbXSwgY3JzOiBDUlMpOiBMYXRMbmdcclxuICAgKiBSZXR1cm5zIHRoZSBjZW50ZXIgKFtjZW50cm9pZF0oaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9DZW50cm9pZCkpIG9mIHRoZSBwYXNzZWQgTGF0TG5ncyAoZmlyc3QgcmluZykgZnJvbSBhIHBvbHlsaW5lLlxyXG4gICAqL1xyXG4gIGZ1bmN0aW9uIHBvbHlsaW5lQ2VudGVyKGxhdGxuZ3MsIGNycykge1xyXG4gIFx0dmFyIGksIGhhbGZEaXN0LCBzZWdEaXN0LCBkaXN0LCBwMSwgcDIsIHJhdGlvLCBjZW50ZXI7XHJcblxyXG4gIFx0aWYgKCFsYXRsbmdzIHx8IGxhdGxuZ3MubGVuZ3RoID09PSAwKSB7XHJcbiAgXHRcdHRocm93IG5ldyBFcnJvcignbGF0bG5ncyBub3QgcGFzc2VkJyk7XHJcbiAgXHR9XHJcblxyXG4gIFx0aWYgKCFpc0ZsYXQobGF0bG5ncykpIHtcclxuICBcdFx0Y29uc29sZS53YXJuKCdsYXRsbmdzIGFyZSBub3QgZmxhdCEgT25seSB0aGUgZmlyc3QgcmluZyB3aWxsIGJlIHVzZWQnKTtcclxuICBcdFx0bGF0bG5ncyA9IGxhdGxuZ3NbMF07XHJcbiAgXHR9XHJcblxyXG4gIFx0dmFyIGNlbnRyb2lkTGF0TG5nID0gdG9MYXRMbmcoWzAsIDBdKTtcclxuXHJcbiAgXHR2YXIgYm91bmRzID0gdG9MYXRMbmdCb3VuZHMobGF0bG5ncyk7XHJcbiAgXHR2YXIgYXJlYUJvdW5kcyA9IGJvdW5kcy5nZXROb3J0aFdlc3QoKS5kaXN0YW5jZVRvKGJvdW5kcy5nZXRTb3V0aFdlc3QoKSkgKiBib3VuZHMuZ2V0Tm9ydGhFYXN0KCkuZGlzdGFuY2VUbyhib3VuZHMuZ2V0Tm9ydGhXZXN0KCkpO1xyXG4gIFx0Ly8gdGVzdHMgc2hvd2VkIHRoYXQgYmVsb3cgMTcwMCByb3VuZGluZyBlcnJvcnMgYXJlIGhhcHBlbmluZ1xyXG4gIFx0aWYgKGFyZWFCb3VuZHMgPCAxNzAwKSB7XHJcbiAgXHRcdC8vIGdldHRpbmcgYSBpbmV4YWN0IGNlbnRlciwgdG8gbW92ZSB0aGUgbGF0bG5ncyBuZWFyIHRvIFswLCAwXSB0byBwcmV2ZW50IHJvdW5kaW5nIGVycm9yc1xyXG4gIFx0XHRjZW50cm9pZExhdExuZyA9IGNlbnRyb2lkKGxhdGxuZ3MpO1xyXG4gIFx0fVxyXG5cclxuICBcdHZhciBsZW4gPSBsYXRsbmdzLmxlbmd0aDtcclxuICBcdHZhciBwb2ludHMgPSBbXTtcclxuICBcdGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xyXG4gIFx0XHR2YXIgbGF0bG5nID0gdG9MYXRMbmcobGF0bG5nc1tpXSk7XHJcbiAgXHRcdHBvaW50cy5wdXNoKGNycy5wcm9qZWN0KHRvTGF0TG5nKFtsYXRsbmcubGF0IC0gY2VudHJvaWRMYXRMbmcubGF0LCBsYXRsbmcubG5nIC0gY2VudHJvaWRMYXRMbmcubG5nXSkpKTtcclxuICBcdH1cclxuXHJcbiAgXHRmb3IgKGkgPSAwLCBoYWxmRGlzdCA9IDA7IGkgPCBsZW4gLSAxOyBpKyspIHtcclxuICBcdFx0aGFsZkRpc3QgKz0gcG9pbnRzW2ldLmRpc3RhbmNlVG8ocG9pbnRzW2kgKyAxXSkgLyAyO1xyXG4gIFx0fVxyXG5cclxuICBcdC8vIFRoZSBsaW5lIGlzIHNvIHNtYWxsIGluIHRoZSBjdXJyZW50IHZpZXcgdGhhdCBhbGwgcG9pbnRzIGFyZSBvbiB0aGUgc2FtZSBwaXhlbC5cclxuICBcdGlmIChoYWxmRGlzdCA9PT0gMCkge1xyXG4gIFx0XHRjZW50ZXIgPSBwb2ludHNbMF07XHJcbiAgXHR9IGVsc2Uge1xyXG4gIFx0XHRmb3IgKGkgPSAwLCBkaXN0ID0gMDsgaSA8IGxlbiAtIDE7IGkrKykge1xyXG4gIFx0XHRcdHAxID0gcG9pbnRzW2ldO1xyXG4gIFx0XHRcdHAyID0gcG9pbnRzW2kgKyAxXTtcclxuICBcdFx0XHRzZWdEaXN0ID0gcDEuZGlzdGFuY2VUbyhwMik7XHJcbiAgXHRcdFx0ZGlzdCArPSBzZWdEaXN0O1xyXG5cclxuICBcdFx0XHRpZiAoZGlzdCA+IGhhbGZEaXN0KSB7XHJcbiAgXHRcdFx0XHRyYXRpbyA9IChkaXN0IC0gaGFsZkRpc3QpIC8gc2VnRGlzdDtcclxuICBcdFx0XHRcdGNlbnRlciA9IFtcclxuICBcdFx0XHRcdFx0cDIueCAtIHJhdGlvICogKHAyLnggLSBwMS54KSxcclxuICBcdFx0XHRcdFx0cDIueSAtIHJhdGlvICogKHAyLnkgLSBwMS55KVxyXG4gIFx0XHRcdFx0XTtcclxuICBcdFx0XHRcdGJyZWFrO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG4gIFx0fVxyXG5cclxuICBcdHZhciBsYXRsbmdDZW50ZXIgPSBjcnMudW5wcm9qZWN0KHRvUG9pbnQoY2VudGVyKSk7XHJcbiAgXHRyZXR1cm4gdG9MYXRMbmcoW2xhdGxuZ0NlbnRlci5sYXQgKyBjZW50cm9pZExhdExuZy5sYXQsIGxhdGxuZ0NlbnRlci5sbmcgKyBjZW50cm9pZExhdExuZy5sbmddKTtcclxuICB9XG5cbiAgdmFyIExpbmVVdGlsID0ge1xuICAgIF9fcHJvdG9fXzogbnVsbCxcbiAgICBzaW1wbGlmeTogc2ltcGxpZnksXG4gICAgcG9pbnRUb1NlZ21lbnREaXN0YW5jZTogcG9pbnRUb1NlZ21lbnREaXN0YW5jZSxcbiAgICBjbG9zZXN0UG9pbnRPblNlZ21lbnQ6IGNsb3Nlc3RQb2ludE9uU2VnbWVudCxcbiAgICBjbGlwU2VnbWVudDogY2xpcFNlZ21lbnQsXG4gICAgX2dldEVkZ2VJbnRlcnNlY3Rpb246IF9nZXRFZGdlSW50ZXJzZWN0aW9uLFxuICAgIF9nZXRCaXRDb2RlOiBfZ2V0Qml0Q29kZSxcbiAgICBfc3FDbG9zZXN0UG9pbnRPblNlZ21lbnQ6IF9zcUNsb3Nlc3RQb2ludE9uU2VnbWVudCxcbiAgICBpc0ZsYXQ6IGlzRmxhdCxcbiAgICBfZmxhdDogX2ZsYXQsXG4gICAgcG9seWxpbmVDZW50ZXI6IHBvbHlsaW5lQ2VudGVyXG4gIH07XG5cbiAgLypcclxuICAgKiBAbmFtZXNwYWNlIFByb2plY3Rpb25cclxuICAgKiBAc2VjdGlvblxyXG4gICAqIExlYWZsZXQgY29tZXMgd2l0aCBhIHNldCBvZiBhbHJlYWR5IGRlZmluZWQgUHJvamVjdGlvbnMgb3V0IG9mIHRoZSBib3g6XHJcbiAgICpcclxuICAgKiBAcHJvamVjdGlvbiBMLlByb2plY3Rpb24uTG9uTGF0XHJcbiAgICpcclxuICAgKiBFcXVpcmVjdGFuZ3VsYXIsIG9yIFBsYXRlIENhcnJlZSBwcm9qZWN0aW9uIOKAlCB0aGUgbW9zdCBzaW1wbGUgcHJvamVjdGlvbixcclxuICAgKiBtb3N0bHkgdXNlZCBieSBHSVMgZW50aHVzaWFzdHMuIERpcmVjdGx5IG1hcHMgYHhgIGFzIGxvbmdpdHVkZSwgYW5kIGB5YCBhc1xyXG4gICAqIGxhdGl0dWRlLiBBbHNvIHN1aXRhYmxlIGZvciBmbGF0IHdvcmxkcywgZS5nLiBnYW1lIG1hcHMuIFVzZWQgYnkgdGhlXHJcbiAgICogYEVQU0c6NDMyNmAgYW5kIGBTaW1wbGVgIENSUy5cclxuICAgKi9cclxuXHJcbiAgdmFyIExvbkxhdCA9IHtcclxuICBcdHByb2plY3Q6IGZ1bmN0aW9uIChsYXRsbmcpIHtcclxuICBcdFx0cmV0dXJuIG5ldyBQb2ludChsYXRsbmcubG5nLCBsYXRsbmcubGF0KTtcclxuICBcdH0sXHJcblxyXG4gIFx0dW5wcm9qZWN0OiBmdW5jdGlvbiAocG9pbnQpIHtcclxuICBcdFx0cmV0dXJuIG5ldyBMYXRMbmcocG9pbnQueSwgcG9pbnQueCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdGJvdW5kczogbmV3IEJvdW5kcyhbLTE4MCwgLTkwXSwgWzE4MCwgOTBdKVxyXG4gIH07XG5cbiAgLypcclxuICAgKiBAbmFtZXNwYWNlIFByb2plY3Rpb25cclxuICAgKiBAcHJvamVjdGlvbiBMLlByb2plY3Rpb24uTWVyY2F0b3JcclxuICAgKlxyXG4gICAqIEVsbGlwdGljYWwgTWVyY2F0b3IgcHJvamVjdGlvbiDigJQgbW9yZSBjb21wbGV4IHRoYW4gU3BoZXJpY2FsIE1lcmNhdG9yLiBBc3N1bWVzIHRoYXQgRWFydGggaXMgYW4gZWxsaXBzb2lkLiBVc2VkIGJ5IHRoZSBFUFNHOjMzOTUgQ1JTLlxyXG4gICAqL1xyXG5cclxuICB2YXIgTWVyY2F0b3IgPSB7XHJcbiAgXHRSOiA2Mzc4MTM3LFxyXG4gIFx0Ul9NSU5PUjogNjM1Njc1Mi4zMTQyNDUxNzksXHJcblxyXG4gIFx0Ym91bmRzOiBuZXcgQm91bmRzKFstMjAwMzc1MDguMzQyNzksIC0xNTQ5NjU3MC43Mzk3Ml0sIFsyMDAzNzUwOC4zNDI3OSwgMTg3NjQ2NTYuMjMxMzhdKSxcclxuXHJcbiAgXHRwcm9qZWN0OiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcbiAgXHRcdHZhciBkID0gTWF0aC5QSSAvIDE4MCxcclxuICBcdFx0ICAgIHIgPSB0aGlzLlIsXHJcbiAgXHRcdCAgICB5ID0gbGF0bG5nLmxhdCAqIGQsXHJcbiAgXHRcdCAgICB0bXAgPSB0aGlzLlJfTUlOT1IgLyByLFxyXG4gIFx0XHQgICAgZSA9IE1hdGguc3FydCgxIC0gdG1wICogdG1wKSxcclxuICBcdFx0ICAgIGNvbiA9IGUgKiBNYXRoLnNpbih5KTtcclxuXHJcbiAgXHRcdHZhciB0cyA9IE1hdGgudGFuKE1hdGguUEkgLyA0IC0geSAvIDIpIC8gTWF0aC5wb3coKDEgLSBjb24pIC8gKDEgKyBjb24pLCBlIC8gMik7XHJcbiAgXHRcdHkgPSAtciAqIE1hdGgubG9nKE1hdGgubWF4KHRzLCAxRS0xMCkpO1xyXG5cclxuICBcdFx0cmV0dXJuIG5ldyBQb2ludChsYXRsbmcubG5nICogZCAqIHIsIHkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHR1bnByb2plY3Q6IGZ1bmN0aW9uIChwb2ludCkge1xyXG4gIFx0XHR2YXIgZCA9IDE4MCAvIE1hdGguUEksXHJcbiAgXHRcdCAgICByID0gdGhpcy5SLFxyXG4gIFx0XHQgICAgdG1wID0gdGhpcy5SX01JTk9SIC8gcixcclxuICBcdFx0ICAgIGUgPSBNYXRoLnNxcnQoMSAtIHRtcCAqIHRtcCksXHJcbiAgXHRcdCAgICB0cyA9IE1hdGguZXhwKC1wb2ludC55IC8gciksXHJcbiAgXHRcdCAgICBwaGkgPSBNYXRoLlBJIC8gMiAtIDIgKiBNYXRoLmF0YW4odHMpO1xyXG5cclxuICBcdFx0Zm9yICh2YXIgaSA9IDAsIGRwaGkgPSAwLjEsIGNvbjsgaSA8IDE1ICYmIE1hdGguYWJzKGRwaGkpID4gMWUtNzsgaSsrKSB7XHJcbiAgXHRcdFx0Y29uID0gZSAqIE1hdGguc2luKHBoaSk7XHJcbiAgXHRcdFx0Y29uID0gTWF0aC5wb3coKDEgLSBjb24pIC8gKDEgKyBjb24pLCBlIC8gMik7XHJcbiAgXHRcdFx0ZHBoaSA9IE1hdGguUEkgLyAyIC0gMiAqIE1hdGguYXRhbih0cyAqIGNvbikgLSBwaGk7XHJcbiAgXHRcdFx0cGhpICs9IGRwaGk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiBuZXcgTGF0TG5nKHBoaSAqIGQsIHBvaW50LnggKiBkIC8gcik7XHJcbiAgXHR9XHJcbiAgfTtcblxuICAvKlxuICAgKiBAY2xhc3MgUHJvamVjdGlvblxuXG4gICAqIEFuIG9iamVjdCB3aXRoIG1ldGhvZHMgZm9yIHByb2plY3RpbmcgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGVzIG9mIHRoZSB3b3JsZCBvbnRvXG4gICAqIGEgZmxhdCBzdXJmYWNlIChhbmQgYmFjaykuIFNlZSBbTWFwIHByb2plY3Rpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL01hcF9wcm9qZWN0aW9uKS5cblxuICAgKiBAcHJvcGVydHkgYm91bmRzOiBCb3VuZHNcbiAgICogVGhlIGJvdW5kcyAoc3BlY2lmaWVkIGluIENSUyB1bml0cykgd2hlcmUgdGhlIHByb2plY3Rpb24gaXMgdmFsaWRcblxuICAgKiBAbWV0aG9kIHByb2plY3QobGF0bG5nOiBMYXRMbmcpOiBQb2ludFxuICAgKiBQcm9qZWN0cyBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZXMgaW50byBhIDJEIHBvaW50LlxuICAgKiBPbmx5IGFjY2VwdHMgYWN0dWFsIGBMLkxhdExuZ2AgaW5zdGFuY2VzLCBub3QgYXJyYXlzLlxuXG4gICAqIEBtZXRob2QgdW5wcm9qZWN0KHBvaW50OiBQb2ludCk6IExhdExuZ1xuICAgKiBUaGUgaW52ZXJzZSBvZiBgcHJvamVjdGAuIFByb2plY3RzIGEgMkQgcG9pbnQgaW50byBhIGdlb2dyYXBoaWNhbCBsb2NhdGlvbi5cbiAgICogT25seSBhY2NlcHRzIGFjdHVhbCBgTC5Qb2ludGAgaW5zdGFuY2VzLCBub3QgYXJyYXlzLlxuXG4gICAqIE5vdGUgdGhhdCB0aGUgcHJvamVjdGlvbiBpbnN0YW5jZXMgZG8gbm90IGluaGVyaXQgZnJvbSBMZWFmbGV0J3MgYENsYXNzYCBvYmplY3QsXG4gICAqIGFuZCBjYW4ndCBiZSBpbnN0YW50aWF0ZWQuIEFsc28sIG5ldyBjbGFzc2VzIGNhbid0IGluaGVyaXQgZnJvbSB0aGVtLFxuICAgKiBhbmQgbWV0aG9kcyBjYW4ndCBiZSBhZGRlZCB0byB0aGVtIHdpdGggdGhlIGBpbmNsdWRlYCBmdW5jdGlvbi5cblxuICAgKi9cblxuICB2YXIgaW5kZXggPSB7XG4gICAgX19wcm90b19fOiBudWxsLFxuICAgIExvbkxhdDogTG9uTGF0LFxuICAgIE1lcmNhdG9yOiBNZXJjYXRvcixcbiAgICBTcGhlcmljYWxNZXJjYXRvcjogU3BoZXJpY2FsTWVyY2F0b3JcbiAgfTtcblxuICAvKlxyXG4gICAqIEBuYW1lc3BhY2UgQ1JTXHJcbiAgICogQGNycyBMLkNSUy5FUFNHMzM5NVxyXG4gICAqXHJcbiAgICogUmFyZWx5IHVzZWQgYnkgc29tZSBjb21tZXJjaWFsIHRpbGUgcHJvdmlkZXJzLiBVc2VzIEVsbGlwdGljYWwgTWVyY2F0b3IgcHJvamVjdGlvbi5cclxuICAgKi9cclxuICB2YXIgRVBTRzMzOTUgPSBleHRlbmQoe30sIEVhcnRoLCB7XHJcbiAgXHRjb2RlOiAnRVBTRzozMzk1JyxcclxuICBcdHByb2plY3Rpb246IE1lcmNhdG9yLFxyXG5cclxuICBcdHRyYW5zZm9ybWF0aW9uOiAoZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR2YXIgc2NhbGUgPSAwLjUgLyAoTWF0aC5QSSAqIE1lcmNhdG9yLlIpO1xyXG4gIFx0XHRyZXR1cm4gdG9UcmFuc2Zvcm1hdGlvbihzY2FsZSwgMC41LCAtc2NhbGUsIDAuNSk7XHJcbiAgXHR9KCkpXHJcbiAgfSk7XG5cbiAgLypcclxuICAgKiBAbmFtZXNwYWNlIENSU1xyXG4gICAqIEBjcnMgTC5DUlMuRVBTRzQzMjZcclxuICAgKlxyXG4gICAqIEEgY29tbW9uIENSUyBhbW9uZyBHSVMgZW50aHVzaWFzdHMuIFVzZXMgc2ltcGxlIEVxdWlyZWN0YW5ndWxhciBwcm9qZWN0aW9uLlxyXG4gICAqXHJcbiAgICogTGVhZmxldCAxLjAueCBjb21wbGllcyB3aXRoIHRoZSBbVE1TIGNvb3JkaW5hdGUgc2NoZW1lIGZvciBFUFNHOjQzMjZdKGh0dHBzOi8vd2lraS5vc2dlby5vcmcvd2lraS9UaWxlX01hcF9TZXJ2aWNlX1NwZWNpZmljYXRpb24jZ2xvYmFsLWdlb2RldGljKSxcclxuICAgKiB3aGljaCBpcyBhIGJyZWFraW5nIGNoYW5nZSBmcm9tIDAuNy54IGJlaGF2aW91ci4gIElmIHlvdSBhcmUgdXNpbmcgYSBgVGlsZUxheWVyYFxyXG4gICAqIHdpdGggdGhpcyBDUlMsIGVuc3VyZSB0aGF0IHRoZXJlIGFyZSB0d28gMjU2eDI1NiBwaXhlbCB0aWxlcyBjb3ZlcmluZyB0aGVcclxuICAgKiB3aG9sZSBlYXJ0aCBhdCB6b29tIGxldmVsIHplcm8sIGFuZCB0aGF0IHRoZSB0aWxlIGNvb3JkaW5hdGUgb3JpZ2luIGlzICgtMTgwLCs5MCksXHJcbiAgICogb3IgKC0xODAsLTkwKSBmb3IgYFRpbGVMYXllcmBzIHdpdGggW3RoZSBgdG1zYCBvcHRpb25dKCN0aWxlbGF5ZXItdG1zKSBzZXQuXHJcbiAgICovXHJcblxyXG4gIHZhciBFUFNHNDMyNiA9IGV4dGVuZCh7fSwgRWFydGgsIHtcclxuICBcdGNvZGU6ICdFUFNHOjQzMjYnLFxyXG4gIFx0cHJvamVjdGlvbjogTG9uTGF0LFxyXG4gIFx0dHJhbnNmb3JtYXRpb246IHRvVHJhbnNmb3JtYXRpb24oMSAvIDE4MCwgMSwgLTEgLyAxODAsIDAuNSlcclxuICB9KTtcblxuICAvKlxuICAgKiBAbmFtZXNwYWNlIENSU1xuICAgKiBAY3JzIEwuQ1JTLlNpbXBsZVxuICAgKlxuICAgKiBBIHNpbXBsZSBDUlMgdGhhdCBtYXBzIGxvbmdpdHVkZSBhbmQgbGF0aXR1ZGUgaW50byBgeGAgYW5kIGB5YCBkaXJlY3RseS5cbiAgICogTWF5IGJlIHVzZWQgZm9yIG1hcHMgb2YgZmxhdCBzdXJmYWNlcyAoZS5nLiBnYW1lIG1hcHMpLiBOb3RlIHRoYXQgdGhlIGB5YFxuICAgKiBheGlzIHNob3VsZCBzdGlsbCBiZSBpbnZlcnRlZCAoZ29pbmcgZnJvbSBib3R0b20gdG8gdG9wKS4gYGRpc3RhbmNlKClgIHJldHVybnNcbiAgICogc2ltcGxlIGV1Y2xpZGVhbiBkaXN0YW5jZS5cbiAgICovXG5cbiAgdmFyIFNpbXBsZSA9IGV4dGVuZCh7fSwgQ1JTLCB7XG4gIFx0cHJvamVjdGlvbjogTG9uTGF0LFxuICBcdHRyYW5zZm9ybWF0aW9uOiB0b1RyYW5zZm9ybWF0aW9uKDEsIDAsIC0xLCAwKSxcblxuICBcdHNjYWxlOiBmdW5jdGlvbiAoem9vbSkge1xuICBcdFx0cmV0dXJuIE1hdGgucG93KDIsIHpvb20pO1xuICBcdH0sXG5cbiAgXHR6b29tOiBmdW5jdGlvbiAoc2NhbGUpIHtcbiAgXHRcdHJldHVybiBNYXRoLmxvZyhzY2FsZSkgLyBNYXRoLkxOMjtcbiAgXHR9LFxuXG4gIFx0ZGlzdGFuY2U6IGZ1bmN0aW9uIChsYXRsbmcxLCBsYXRsbmcyKSB7XG4gIFx0XHR2YXIgZHggPSBsYXRsbmcyLmxuZyAtIGxhdGxuZzEubG5nLFxuICBcdFx0ICAgIGR5ID0gbGF0bG5nMi5sYXQgLSBsYXRsbmcxLmxhdDtcblxuICBcdFx0cmV0dXJuIE1hdGguc3FydChkeCAqIGR4ICsgZHkgKiBkeSk7XG4gIFx0fSxcblxuICBcdGluZmluaXRlOiB0cnVlXG4gIH0pO1xuXG4gIENSUy5FYXJ0aCA9IEVhcnRoO1xuICBDUlMuRVBTRzMzOTUgPSBFUFNHMzM5NTtcbiAgQ1JTLkVQU0czODU3ID0gRVBTRzM4NTc7XG4gIENSUy5FUFNHOTAwOTEzID0gRVBTRzkwMDkxMztcbiAgQ1JTLkVQU0c0MzI2ID0gRVBTRzQzMjY7XG4gIENSUy5TaW1wbGUgPSBTaW1wbGU7XG5cbiAgLypcbiAgICogQGNsYXNzIExheWVyXG4gICAqIEBpbmhlcml0cyBFdmVudGVkXG4gICAqIEBha2EgTC5MYXllclxuICAgKiBAYWthIElMYXllclxuICAgKlxuICAgKiBBIHNldCBvZiBtZXRob2RzIGZyb20gdGhlIExheWVyIGJhc2UgY2xhc3MgdGhhdCBhbGwgTGVhZmxldCBsYXllcnMgdXNlLlxuICAgKiBJbmhlcml0cyBhbGwgbWV0aG9kcywgb3B0aW9ucyBhbmQgZXZlbnRzIGZyb20gYEwuRXZlbnRlZGAuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqIGBgYGpzXG4gICAqIHZhciBsYXllciA9IEwubWFya2VyKGxhdGxuZykuYWRkVG8obWFwKTtcbiAgICogbGF5ZXIuYWRkVG8obWFwKTtcbiAgICogbGF5ZXIucmVtb3ZlKCk7XG4gICAqIGBgYFxuICAgKlxuICAgKiBAZXZlbnQgYWRkOiBFdmVudFxuICAgKiBGaXJlZCBhZnRlciB0aGUgbGF5ZXIgaXMgYWRkZWQgdG8gYSBtYXBcbiAgICpcbiAgICogQGV2ZW50IHJlbW92ZTogRXZlbnRcbiAgICogRmlyZWQgYWZ0ZXIgdGhlIGxheWVyIGlzIHJlbW92ZWQgZnJvbSBhIG1hcFxuICAgKi9cblxuXG4gIHZhciBMYXllciA9IEV2ZW50ZWQuZXh0ZW5kKHtcblxuICBcdC8vIENsYXNzZXMgZXh0ZW5kaW5nIGBMLkxheWVyYCB3aWxsIGluaGVyaXQgdGhlIGZvbGxvd2luZyBvcHRpb25zOlxuICBcdG9wdGlvbnM6IHtcbiAgXHRcdC8vIEBvcHRpb24gcGFuZTogU3RyaW5nID0gJ292ZXJsYXlQYW5lJ1xuICBcdFx0Ly8gQnkgZGVmYXVsdCB0aGUgbGF5ZXIgd2lsbCBiZSBhZGRlZCB0byB0aGUgbWFwJ3MgW292ZXJsYXkgcGFuZV0oI21hcC1vdmVybGF5cGFuZSkuIE92ZXJyaWRpbmcgdGhpcyBvcHRpb24gd2lsbCBjYXVzZSB0aGUgbGF5ZXIgdG8gYmUgcGxhY2VkIG9uIGFub3RoZXIgcGFuZSBieSBkZWZhdWx0LlxuICBcdFx0cGFuZTogJ292ZXJsYXlQYW5lJyxcblxuICBcdFx0Ly8gQG9wdGlvbiBhdHRyaWJ1dGlvbjogU3RyaW5nID0gbnVsbFxuICBcdFx0Ly8gU3RyaW5nIHRvIGJlIHNob3duIGluIHRoZSBhdHRyaWJ1dGlvbiBjb250cm9sLCBlLmcuIFwiwqkgT3BlblN0cmVldE1hcCBjb250cmlidXRvcnNcIi4gSXQgZGVzY3JpYmVzIHRoZSBsYXllciBkYXRhIGFuZCBpcyBvZnRlbiBhIGxlZ2FsIG9ibGlnYXRpb24gdG93YXJkcyBjb3B5cmlnaHQgaG9sZGVycyBhbmQgdGlsZSBwcm92aWRlcnMuXG4gIFx0XHRhdHRyaWJ1dGlvbjogbnVsbCxcblxuICBcdFx0YnViYmxpbmdNb3VzZUV2ZW50czogdHJ1ZVxuICBcdH0sXG5cbiAgXHQvKiBAc2VjdGlvblxuICBcdCAqIENsYXNzZXMgZXh0ZW5kaW5nIGBMLkxheWVyYCB3aWxsIGluaGVyaXQgdGhlIGZvbGxvd2luZyBtZXRob2RzOlxuICBcdCAqXG4gIFx0ICogQG1ldGhvZCBhZGRUbyhtYXA6IE1hcHxMYXllckdyb3VwKTogdGhpc1xuICBcdCAqIEFkZHMgdGhlIGxheWVyIHRvIHRoZSBnaXZlbiBtYXAgb3IgbGF5ZXIgZ3JvdXAuXG4gIFx0ICovXG4gIFx0YWRkVG86IGZ1bmN0aW9uIChtYXApIHtcbiAgXHRcdG1hcC5hZGRMYXllcih0aGlzKTtcbiAgXHRcdHJldHVybiB0aGlzO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIHJlbW92ZTogdGhpc1xuICBcdC8vIFJlbW92ZXMgdGhlIGxheWVyIGZyb20gdGhlIG1hcCBpdCBpcyBjdXJyZW50bHkgYWN0aXZlIG9uLlxuICBcdHJlbW92ZTogZnVuY3Rpb24gKCkge1xuICBcdFx0cmV0dXJuIHRoaXMucmVtb3ZlRnJvbSh0aGlzLl9tYXAgfHwgdGhpcy5fbWFwVG9BZGQpO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIHJlbW92ZUZyb20obWFwOiBNYXApOiB0aGlzXG4gIFx0Ly8gUmVtb3ZlcyB0aGUgbGF5ZXIgZnJvbSB0aGUgZ2l2ZW4gbWFwXG4gIFx0Ly9cbiAgXHQvLyBAYWx0ZXJuYXRpdmVcbiAgXHQvLyBAbWV0aG9kIHJlbW92ZUZyb20oZ3JvdXA6IExheWVyR3JvdXApOiB0aGlzXG4gIFx0Ly8gUmVtb3ZlcyB0aGUgbGF5ZXIgZnJvbSB0aGUgZ2l2ZW4gYExheWVyR3JvdXBgXG4gIFx0cmVtb3ZlRnJvbTogZnVuY3Rpb24gKG9iaikge1xuICBcdFx0aWYgKG9iaikge1xuICBcdFx0XHRvYmoucmVtb3ZlTGF5ZXIodGhpcyk7XG4gIFx0XHR9XG4gIFx0XHRyZXR1cm4gdGhpcztcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBnZXRQYW5lKG5hbWU/IDogU3RyaW5nKTogSFRNTEVsZW1lbnRcbiAgXHQvLyBSZXR1cm5zIHRoZSBgSFRNTEVsZW1lbnRgIHJlcHJlc2VudGluZyB0aGUgbmFtZWQgcGFuZSBvbiB0aGUgbWFwLiBJZiBgbmFtZWAgaXMgb21pdHRlZCwgcmV0dXJucyB0aGUgcGFuZSBmb3IgdGhpcyBsYXllci5cbiAgXHRnZXRQYW5lOiBmdW5jdGlvbiAobmFtZSkge1xuICBcdFx0cmV0dXJuIHRoaXMuX21hcC5nZXRQYW5lKG5hbWUgPyAodGhpcy5vcHRpb25zW25hbWVdIHx8IG5hbWUpIDogdGhpcy5vcHRpb25zLnBhbmUpO1xuICBcdH0sXG5cbiAgXHRhZGRJbnRlcmFjdGl2ZVRhcmdldDogZnVuY3Rpb24gKHRhcmdldEVsKSB7XG4gIFx0XHR0aGlzLl9tYXAuX3RhcmdldHNbc3RhbXAodGFyZ2V0RWwpXSA9IHRoaXM7XG4gIFx0XHRyZXR1cm4gdGhpcztcbiAgXHR9LFxuXG4gIFx0cmVtb3ZlSW50ZXJhY3RpdmVUYXJnZXQ6IGZ1bmN0aW9uICh0YXJnZXRFbCkge1xuICBcdFx0ZGVsZXRlIHRoaXMuX21hcC5fdGFyZ2V0c1tzdGFtcCh0YXJnZXRFbCldO1xuICBcdFx0cmV0dXJuIHRoaXM7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgZ2V0QXR0cmlidXRpb246IFN0cmluZ1xuICBcdC8vIFVzZWQgYnkgdGhlIGBhdHRyaWJ1dGlvbiBjb250cm9sYCwgcmV0dXJucyB0aGUgW2F0dHJpYnV0aW9uIG9wdGlvbl0oI2dyaWRsYXllci1hdHRyaWJ1dGlvbikuXG4gIFx0Z2V0QXR0cmlidXRpb246IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHJldHVybiB0aGlzLm9wdGlvbnMuYXR0cmlidXRpb247XG4gIFx0fSxcblxuICBcdF9sYXllckFkZDogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdHZhciBtYXAgPSBlLnRhcmdldDtcblxuICBcdFx0Ly8gY2hlY2sgaW4gY2FzZSBsYXllciBnZXRzIGFkZGVkIGFuZCB0aGVuIHJlbW92ZWQgYmVmb3JlIHRoZSBtYXAgaXMgcmVhZHlcbiAgXHRcdGlmICghbWFwLmhhc0xheWVyKHRoaXMpKSB7IHJldHVybjsgfVxuXG4gIFx0XHR0aGlzLl9tYXAgPSBtYXA7XG4gIFx0XHR0aGlzLl96b29tQW5pbWF0ZWQgPSBtYXAuX3pvb21BbmltYXRlZDtcblxuICBcdFx0aWYgKHRoaXMuZ2V0RXZlbnRzKSB7XG4gIFx0XHRcdHZhciBldmVudHMgPSB0aGlzLmdldEV2ZW50cygpO1xuICBcdFx0XHRtYXAub24oZXZlbnRzLCB0aGlzKTtcbiAgXHRcdFx0dGhpcy5vbmNlKCdyZW1vdmUnLCBmdW5jdGlvbiAoKSB7XG4gIFx0XHRcdFx0bWFwLm9mZihldmVudHMsIHRoaXMpO1xuICBcdFx0XHR9LCB0aGlzKTtcbiAgXHRcdH1cblxuICBcdFx0dGhpcy5vbkFkZChtYXApO1xuXG4gIFx0XHR0aGlzLmZpcmUoJ2FkZCcpO1xuICBcdFx0bWFwLmZpcmUoJ2xheWVyYWRkJywge2xheWVyOiB0aGlzfSk7XG4gIFx0fVxuICB9KTtcblxuICAvKiBAc2VjdGlvbiBFeHRlbnNpb24gbWV0aG9kc1xuICAgKiBAdW5pbmhlcml0YWJsZVxuICAgKlxuICAgKiBFdmVyeSBsYXllciBzaG91bGQgZXh0ZW5kIGZyb20gYEwuTGF5ZXJgIGFuZCAocmUtKWltcGxlbWVudCB0aGUgZm9sbG93aW5nIG1ldGhvZHMuXG4gICAqXG4gICAqIEBtZXRob2Qgb25BZGQobWFwOiBNYXApOiB0aGlzXG4gICAqIFNob3VsZCBjb250YWluIGNvZGUgdGhhdCBjcmVhdGVzIERPTSBlbGVtZW50cyBmb3IgdGhlIGxheWVyLCBhZGRzIHRoZW0gdG8gYG1hcCBwYW5lc2Agd2hlcmUgdGhleSBzaG91bGQgYmVsb25nIGFuZCBwdXRzIGxpc3RlbmVycyBvbiByZWxldmFudCBtYXAgZXZlbnRzLiBDYWxsZWQgb24gW2BtYXAuYWRkTGF5ZXIobGF5ZXIpYF0oI21hcC1hZGRsYXllcikuXG4gICAqXG4gICAqIEBtZXRob2Qgb25SZW1vdmUobWFwOiBNYXApOiB0aGlzXG4gICAqIFNob3VsZCBjb250YWluIGFsbCBjbGVhbiB1cCBjb2RlIHRoYXQgcmVtb3ZlcyB0aGUgbGF5ZXIncyBlbGVtZW50cyBmcm9tIHRoZSBET00gYW5kIHJlbW92ZXMgbGlzdGVuZXJzIHByZXZpb3VzbHkgYWRkZWQgaW4gW2BvbkFkZGBdKCNsYXllci1vbmFkZCkuIENhbGxlZCBvbiBbYG1hcC5yZW1vdmVMYXllcihsYXllcilgXSgjbWFwLXJlbW92ZWxheWVyKS5cbiAgICpcbiAgICogQG1ldGhvZCBnZXRFdmVudHMoKTogT2JqZWN0XG4gICAqIFRoaXMgb3B0aW9uYWwgbWV0aG9kIHNob3VsZCByZXR1cm4gYW4gb2JqZWN0IGxpa2UgYHsgdmlld3Jlc2V0OiB0aGlzLl9yZXNldCB9YCBmb3IgW2BhZGRFdmVudExpc3RlbmVyYF0oI2V2ZW50ZWQtYWRkZXZlbnRsaXN0ZW5lcikuIFRoZSBldmVudCBoYW5kbGVycyBpbiB0aGlzIG9iamVjdCB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgYWRkZWQgYW5kIHJlbW92ZWQgZnJvbSB0aGUgbWFwIHdpdGggeW91ciBsYXllci5cbiAgICpcbiAgICogQG1ldGhvZCBnZXRBdHRyaWJ1dGlvbigpOiBTdHJpbmdcbiAgICogVGhpcyBvcHRpb25hbCBtZXRob2Qgc2hvdWxkIHJldHVybiBhIHN0cmluZyBjb250YWluaW5nIEhUTUwgdG8gYmUgc2hvd24gb24gdGhlIGBBdHRyaWJ1dGlvbiBjb250cm9sYCB3aGVuZXZlciB0aGUgbGF5ZXIgaXMgdmlzaWJsZS5cbiAgICpcbiAgICogQG1ldGhvZCBiZWZvcmVBZGQobWFwOiBNYXApOiB0aGlzXG4gICAqIE9wdGlvbmFsIG1ldGhvZC4gQ2FsbGVkIG9uIFtgbWFwLmFkZExheWVyKGxheWVyKWBdKCNtYXAtYWRkbGF5ZXIpLCBiZWZvcmUgdGhlIGxheWVyIGlzIGFkZGVkIHRvIHRoZSBtYXAsIGJlZm9yZSBldmVudHMgYXJlIGluaXRpYWxpemVkLCB3aXRob3V0IHdhaXRpbmcgdW50aWwgdGhlIG1hcCBpcyBpbiBhIHVzYWJsZSBzdGF0ZS4gVXNlIGZvciBlYXJseSBpbml0aWFsaXphdGlvbiBvbmx5LlxuICAgKi9cblxuXG4gIC8qIEBuYW1lc3BhY2UgTWFwXG4gICAqIEBzZWN0aW9uIExheWVyIGV2ZW50c1xuICAgKlxuICAgKiBAZXZlbnQgbGF5ZXJhZGQ6IExheWVyRXZlbnRcbiAgICogRmlyZWQgd2hlbiBhIG5ldyBsYXllciBpcyBhZGRlZCB0byB0aGUgbWFwLlxuICAgKlxuICAgKiBAZXZlbnQgbGF5ZXJyZW1vdmU6IExheWVyRXZlbnRcbiAgICogRmlyZWQgd2hlbiBzb21lIGxheWVyIGlzIHJlbW92ZWQgZnJvbSB0aGUgbWFwXG4gICAqXG4gICAqIEBzZWN0aW9uIE1ldGhvZHMgZm9yIExheWVycyBhbmQgQ29udHJvbHNcbiAgICovXG4gIE1hcC5pbmNsdWRlKHtcbiAgXHQvLyBAbWV0aG9kIGFkZExheWVyKGxheWVyOiBMYXllcik6IHRoaXNcbiAgXHQvLyBBZGRzIHRoZSBnaXZlbiBsYXllciB0byB0aGUgbWFwXG4gIFx0YWRkTGF5ZXI6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0aWYgKCFsYXllci5fbGF5ZXJBZGQpIHtcbiAgXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdUaGUgcHJvdmlkZWQgb2JqZWN0IGlzIG5vdCBhIExheWVyLicpO1xuICBcdFx0fVxuXG4gIFx0XHR2YXIgaWQgPSBzdGFtcChsYXllcik7XG4gIFx0XHRpZiAodGhpcy5fbGF5ZXJzW2lkXSkgeyByZXR1cm4gdGhpczsgfVxuICBcdFx0dGhpcy5fbGF5ZXJzW2lkXSA9IGxheWVyO1xuXG4gIFx0XHRsYXllci5fbWFwVG9BZGQgPSB0aGlzO1xuXG4gIFx0XHRpZiAobGF5ZXIuYmVmb3JlQWRkKSB7XG4gIFx0XHRcdGxheWVyLmJlZm9yZUFkZCh0aGlzKTtcbiAgXHRcdH1cblxuICBcdFx0dGhpcy53aGVuUmVhZHkobGF5ZXIuX2xheWVyQWRkLCBsYXllcik7XG5cbiAgXHRcdHJldHVybiB0aGlzO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIHJlbW92ZUxheWVyKGxheWVyOiBMYXllcik6IHRoaXNcbiAgXHQvLyBSZW1vdmVzIHRoZSBnaXZlbiBsYXllciBmcm9tIHRoZSBtYXAuXG4gIFx0cmVtb3ZlTGF5ZXI6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0dmFyIGlkID0gc3RhbXAobGF5ZXIpO1xuXG4gIFx0XHRpZiAoIXRoaXMuX2xheWVyc1tpZF0pIHsgcmV0dXJuIHRoaXM7IH1cblxuICBcdFx0aWYgKHRoaXMuX2xvYWRlZCkge1xuICBcdFx0XHRsYXllci5vblJlbW92ZSh0aGlzKTtcbiAgXHRcdH1cblxuICBcdFx0ZGVsZXRlIHRoaXMuX2xheWVyc1tpZF07XG5cbiAgXHRcdGlmICh0aGlzLl9sb2FkZWQpIHtcbiAgXHRcdFx0dGhpcy5maXJlKCdsYXllcnJlbW92ZScsIHtsYXllcjogbGF5ZXJ9KTtcbiAgXHRcdFx0bGF5ZXIuZmlyZSgncmVtb3ZlJyk7XG4gIFx0XHR9XG5cbiAgXHRcdGxheWVyLl9tYXAgPSBsYXllci5fbWFwVG9BZGQgPSBudWxsO1xuXG4gIFx0XHRyZXR1cm4gdGhpcztcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBoYXNMYXllcihsYXllcjogTGF5ZXIpOiBCb29sZWFuXG4gIFx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGdpdmVuIGxheWVyIGlzIGN1cnJlbnRseSBhZGRlZCB0byB0aGUgbWFwXG4gIFx0aGFzTGF5ZXI6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0cmV0dXJuIHN0YW1wKGxheWVyKSBpbiB0aGlzLl9sYXllcnM7XG4gIFx0fSxcblxuICBcdC8qIEBtZXRob2QgZWFjaExheWVyKGZuOiBGdW5jdGlvbiwgY29udGV4dD86IE9iamVjdCk6IHRoaXNcbiAgXHQgKiBJdGVyYXRlcyBvdmVyIHRoZSBsYXllcnMgb2YgdGhlIG1hcCwgb3B0aW9uYWxseSBzcGVjaWZ5aW5nIGNvbnRleHQgb2YgdGhlIGl0ZXJhdG9yIGZ1bmN0aW9uLlxuICBcdCAqIGBgYFxuICBcdCAqIG1hcC5lYWNoTGF5ZXIoZnVuY3Rpb24obGF5ZXIpe1xuICBcdCAqICAgICBsYXllci5iaW5kUG9wdXAoJ0hlbGxvJyk7XG4gIFx0ICogfSk7XG4gIFx0ICogYGBgXG4gIFx0ICovXG4gIFx0ZWFjaExheWVyOiBmdW5jdGlvbiAobWV0aG9kLCBjb250ZXh0KSB7XG4gIFx0XHRmb3IgKHZhciBpIGluIHRoaXMuX2xheWVycykge1xuICBcdFx0XHRtZXRob2QuY2FsbChjb250ZXh0LCB0aGlzLl9sYXllcnNbaV0pO1xuICBcdFx0fVxuICBcdFx0cmV0dXJuIHRoaXM7XG4gIFx0fSxcblxuICBcdF9hZGRMYXllcnM6IGZ1bmN0aW9uIChsYXllcnMpIHtcbiAgXHRcdGxheWVycyA9IGxheWVycyA/IChpc0FycmF5KGxheWVycykgPyBsYXllcnMgOiBbbGF5ZXJzXSkgOiBbXTtcblxuICBcdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IGxheWVycy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICBcdFx0XHR0aGlzLmFkZExheWVyKGxheWVyc1tpXSk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF9hZGRab29tTGltaXQ6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0aWYgKCFpc05hTihsYXllci5vcHRpb25zLm1heFpvb20pIHx8ICFpc05hTihsYXllci5vcHRpb25zLm1pblpvb20pKSB7XG4gIFx0XHRcdHRoaXMuX3pvb21Cb3VuZExheWVyc1tzdGFtcChsYXllcildID0gbGF5ZXI7XG4gIFx0XHRcdHRoaXMuX3VwZGF0ZVpvb21MZXZlbHMoKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3JlbW92ZVpvb21MaW1pdDogZnVuY3Rpb24gKGxheWVyKSB7XG4gIFx0XHR2YXIgaWQgPSBzdGFtcChsYXllcik7XG5cbiAgXHRcdGlmICh0aGlzLl96b29tQm91bmRMYXllcnNbaWRdKSB7XG4gIFx0XHRcdGRlbGV0ZSB0aGlzLl96b29tQm91bmRMYXllcnNbaWRdO1xuICBcdFx0XHR0aGlzLl91cGRhdGVab29tTGV2ZWxzKCk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF91cGRhdGVab29tTGV2ZWxzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR2YXIgbWluWm9vbSA9IEluZmluaXR5LFxuICBcdFx0ICAgIG1heFpvb20gPSAtSW5maW5pdHksXG4gIFx0XHQgICAgb2xkWm9vbVNwYW4gPSB0aGlzLl9nZXRab29tU3BhbigpO1xuXG4gIFx0XHRmb3IgKHZhciBpIGluIHRoaXMuX3pvb21Cb3VuZExheWVycykge1xuICBcdFx0XHR2YXIgb3B0aW9ucyA9IHRoaXMuX3pvb21Cb3VuZExheWVyc1tpXS5vcHRpb25zO1xuXG4gIFx0XHRcdG1pblpvb20gPSBvcHRpb25zLm1pblpvb20gPT09IHVuZGVmaW5lZCA/IG1pblpvb20gOiBNYXRoLm1pbihtaW5ab29tLCBvcHRpb25zLm1pblpvb20pO1xuICBcdFx0XHRtYXhab29tID0gb3B0aW9ucy5tYXhab29tID09PSB1bmRlZmluZWQgPyBtYXhab29tIDogTWF0aC5tYXgobWF4Wm9vbSwgb3B0aW9ucy5tYXhab29tKTtcbiAgXHRcdH1cblxuICBcdFx0dGhpcy5fbGF5ZXJzTWF4Wm9vbSA9IG1heFpvb20gPT09IC1JbmZpbml0eSA/IHVuZGVmaW5lZCA6IG1heFpvb207XG4gIFx0XHR0aGlzLl9sYXllcnNNaW5ab29tID0gbWluWm9vbSA9PT0gSW5maW5pdHkgPyB1bmRlZmluZWQgOiBtaW5ab29tO1xuXG4gIFx0XHQvLyBAc2VjdGlvbiBNYXAgc3RhdGUgY2hhbmdlIGV2ZW50c1xuICBcdFx0Ly8gQGV2ZW50IHpvb21sZXZlbHNjaGFuZ2U6IEV2ZW50XG4gIFx0XHQvLyBGaXJlZCB3aGVuIHRoZSBudW1iZXIgb2Ygem9vbWxldmVscyBvbiB0aGUgbWFwIGlzIGNoYW5nZWQgZHVlXG4gIFx0XHQvLyB0byBhZGRpbmcgb3IgcmVtb3ZpbmcgYSBsYXllci5cbiAgXHRcdGlmIChvbGRab29tU3BhbiAhPT0gdGhpcy5fZ2V0Wm9vbVNwYW4oKSkge1xuICBcdFx0XHR0aGlzLmZpcmUoJ3pvb21sZXZlbHNjaGFuZ2UnKTtcbiAgXHRcdH1cblxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5tYXhab29tID09PSB1bmRlZmluZWQgJiYgdGhpcy5fbGF5ZXJzTWF4Wm9vbSAmJiB0aGlzLmdldFpvb20oKSA+IHRoaXMuX2xheWVyc01heFpvb20pIHtcbiAgXHRcdFx0dGhpcy5zZXRab29tKHRoaXMuX2xheWVyc01heFpvb20pO1xuICBcdFx0fVxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5taW5ab29tID09PSB1bmRlZmluZWQgJiYgdGhpcy5fbGF5ZXJzTWluWm9vbSAmJiB0aGlzLmdldFpvb20oKSA8IHRoaXMuX2xheWVyc01pblpvb20pIHtcbiAgXHRcdFx0dGhpcy5zZXRab29tKHRoaXMuX2xheWVyc01pblpvb20pO1xuICBcdFx0fVxuICBcdH1cbiAgfSk7XG5cbiAgLypcclxuICAgKiBAY2xhc3MgTGF5ZXJHcm91cFxyXG4gICAqIEBha2EgTC5MYXllckdyb3VwXHJcbiAgICogQGluaGVyaXRzIEludGVyYWN0aXZlIGxheWVyXHJcbiAgICpcclxuICAgKiBVc2VkIHRvIGdyb3VwIHNldmVyYWwgbGF5ZXJzIGFuZCBoYW5kbGUgdGhlbSBhcyBvbmUuIElmIHlvdSBhZGQgaXQgdG8gdGhlIG1hcCxcclxuICAgKiBhbnkgbGF5ZXJzIGFkZGVkIG9yIHJlbW92ZWQgZnJvbSB0aGUgZ3JvdXAgd2lsbCBiZSBhZGRlZC9yZW1vdmVkIG9uIHRoZSBtYXAgYXNcclxuICAgKiB3ZWxsLiBFeHRlbmRzIGBMYXllcmAuXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiBMLmxheWVyR3JvdXAoW21hcmtlcjEsIG1hcmtlcjJdKVxyXG4gICAqIFx0LmFkZExheWVyKHBvbHlsaW5lKVxyXG4gICAqIFx0LmFkZFRvKG1hcCk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcblxyXG4gIHZhciBMYXllckdyb3VwID0gTGF5ZXIuZXh0ZW5kKHtcclxuXHJcbiAgXHRpbml0aWFsaXplOiBmdW5jdGlvbiAobGF5ZXJzLCBvcHRpb25zKSB7XHJcbiAgXHRcdHNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XHJcblxyXG4gIFx0XHR0aGlzLl9sYXllcnMgPSB7fTtcclxuXHJcbiAgXHRcdHZhciBpLCBsZW47XHJcblxyXG4gIFx0XHRpZiAobGF5ZXJzKSB7XHJcbiAgXHRcdFx0Zm9yIChpID0gMCwgbGVuID0gbGF5ZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdFx0XHR0aGlzLmFkZExheWVyKGxheWVyc1tpXSk7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgYWRkTGF5ZXIobGF5ZXI6IExheWVyKTogdGhpc1xyXG4gIFx0Ly8gQWRkcyB0aGUgZ2l2ZW4gbGF5ZXIgdG8gdGhlIGdyb3VwLlxyXG4gIFx0YWRkTGF5ZXI6IGZ1bmN0aW9uIChsYXllcikge1xyXG4gIFx0XHR2YXIgaWQgPSB0aGlzLmdldExheWVySWQobGF5ZXIpO1xyXG5cclxuICBcdFx0dGhpcy5fbGF5ZXJzW2lkXSA9IGxheWVyO1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX21hcCkge1xyXG4gIFx0XHRcdHRoaXMuX21hcC5hZGRMYXllcihsYXllcik7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHJlbW92ZUxheWVyKGxheWVyOiBMYXllcik6IHRoaXNcclxuICBcdC8vIFJlbW92ZXMgdGhlIGdpdmVuIGxheWVyIGZyb20gdGhlIGdyb3VwLlxyXG4gIFx0Ly8gQGFsdGVybmF0aXZlXHJcbiAgXHQvLyBAbWV0aG9kIHJlbW92ZUxheWVyKGlkOiBOdW1iZXIpOiB0aGlzXHJcbiAgXHQvLyBSZW1vdmVzIHRoZSBsYXllciB3aXRoIHRoZSBnaXZlbiBpbnRlcm5hbCBJRCBmcm9tIHRoZSBncm91cC5cclxuICBcdHJlbW92ZUxheWVyOiBmdW5jdGlvbiAobGF5ZXIpIHtcclxuICBcdFx0dmFyIGlkID0gbGF5ZXIgaW4gdGhpcy5fbGF5ZXJzID8gbGF5ZXIgOiB0aGlzLmdldExheWVySWQobGF5ZXIpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX21hcCAmJiB0aGlzLl9sYXllcnNbaWRdKSB7XHJcbiAgXHRcdFx0dGhpcy5fbWFwLnJlbW92ZUxheWVyKHRoaXMuX2xheWVyc1tpZF0pO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRkZWxldGUgdGhpcy5fbGF5ZXJzW2lkXTtcclxuXHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGhhc0xheWVyKGxheWVyOiBMYXllcik6IEJvb2xlYW5cclxuICBcdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSBnaXZlbiBsYXllciBpcyBjdXJyZW50bHkgYWRkZWQgdG8gdGhlIGdyb3VwLlxyXG4gIFx0Ly8gQGFsdGVybmF0aXZlXHJcbiAgXHQvLyBAbWV0aG9kIGhhc0xheWVyKGlkOiBOdW1iZXIpOiBCb29sZWFuXHJcbiAgXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZ2l2ZW4gaW50ZXJuYWwgSUQgaXMgY3VycmVudGx5IGFkZGVkIHRvIHRoZSBncm91cC5cclxuICBcdGhhc0xheWVyOiBmdW5jdGlvbiAobGF5ZXIpIHtcclxuICBcdFx0dmFyIGxheWVySWQgPSB0eXBlb2YgbGF5ZXIgPT09ICdudW1iZXInID8gbGF5ZXIgOiB0aGlzLmdldExheWVySWQobGF5ZXIpO1xyXG4gIFx0XHRyZXR1cm4gbGF5ZXJJZCBpbiB0aGlzLl9sYXllcnM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgY2xlYXJMYXllcnMoKTogdGhpc1xyXG4gIFx0Ly8gUmVtb3ZlcyBhbGwgdGhlIGxheWVycyBmcm9tIHRoZSBncm91cC5cclxuICBcdGNsZWFyTGF5ZXJzOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLmVhY2hMYXllcih0aGlzLnJlbW92ZUxheWVyLCB0aGlzKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBpbnZva2UobWV0aG9kTmFtZTogU3RyaW5nLCDigKYpOiB0aGlzXHJcbiAgXHQvLyBDYWxscyBgbWV0aG9kTmFtZWAgb24gZXZlcnkgbGF5ZXIgY29udGFpbmVkIGluIHRoaXMgZ3JvdXAsIHBhc3NpbmcgYW55XHJcbiAgXHQvLyBhZGRpdGlvbmFsIHBhcmFtZXRlcnMuIEhhcyBubyBlZmZlY3QgaWYgdGhlIGxheWVycyBjb250YWluZWQgZG8gbm90XHJcbiAgXHQvLyBpbXBsZW1lbnQgYG1ldGhvZE5hbWVgLlxyXG4gIFx0aW52b2tlOiBmdW5jdGlvbiAobWV0aG9kTmFtZSkge1xyXG4gIFx0XHR2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSksXHJcbiAgXHRcdCAgICBpLCBsYXllcjtcclxuXHJcbiAgXHRcdGZvciAoaSBpbiB0aGlzLl9sYXllcnMpIHtcclxuICBcdFx0XHRsYXllciA9IHRoaXMuX2xheWVyc1tpXTtcclxuXHJcbiAgXHRcdFx0aWYgKGxheWVyW21ldGhvZE5hbWVdKSB7XHJcbiAgXHRcdFx0XHRsYXllclttZXRob2ROYW1lXS5hcHBseShsYXllciwgYXJncyk7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0b25BZGQ6IGZ1bmN0aW9uIChtYXApIHtcclxuICBcdFx0dGhpcy5lYWNoTGF5ZXIobWFwLmFkZExheWVyLCBtYXApO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRvblJlbW92ZTogZnVuY3Rpb24gKG1hcCkge1xyXG4gIFx0XHR0aGlzLmVhY2hMYXllcihtYXAucmVtb3ZlTGF5ZXIsIG1hcCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZWFjaExheWVyKGZuOiBGdW5jdGlvbiwgY29udGV4dD86IE9iamVjdCk6IHRoaXNcclxuICBcdC8vIEl0ZXJhdGVzIG92ZXIgdGhlIGxheWVycyBvZiB0aGUgZ3JvdXAsIG9wdGlvbmFsbHkgc3BlY2lmeWluZyBjb250ZXh0IG9mIHRoZSBpdGVyYXRvciBmdW5jdGlvbi5cclxuICBcdC8vIGBgYGpzXHJcbiAgXHQvLyBncm91cC5lYWNoTGF5ZXIoZnVuY3Rpb24gKGxheWVyKSB7XHJcbiAgXHQvLyBcdGxheWVyLmJpbmRQb3B1cCgnSGVsbG8nKTtcclxuICBcdC8vIH0pO1xyXG4gIFx0Ly8gYGBgXHJcbiAgXHRlYWNoTGF5ZXI6IGZ1bmN0aW9uIChtZXRob2QsIGNvbnRleHQpIHtcclxuICBcdFx0Zm9yICh2YXIgaSBpbiB0aGlzLl9sYXllcnMpIHtcclxuICBcdFx0XHRtZXRob2QuY2FsbChjb250ZXh0LCB0aGlzLl9sYXllcnNbaV0pO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldExheWVyKGlkOiBOdW1iZXIpOiBMYXllclxyXG4gIFx0Ly8gUmV0dXJucyB0aGUgbGF5ZXIgd2l0aCB0aGUgZ2l2ZW4gaW50ZXJuYWwgSUQuXHJcbiAgXHRnZXRMYXllcjogZnVuY3Rpb24gKGlkKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLl9sYXllcnNbaWRdO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldExheWVycygpOiBMYXllcltdXHJcbiAgXHQvLyBSZXR1cm5zIGFuIGFycmF5IG9mIGFsbCB0aGUgbGF5ZXJzIGFkZGVkIHRvIHRoZSBncm91cC5cclxuICBcdGdldExheWVyczogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR2YXIgbGF5ZXJzID0gW107XHJcbiAgXHRcdHRoaXMuZWFjaExheWVyKGxheWVycy5wdXNoLCBsYXllcnMpO1xyXG4gIFx0XHRyZXR1cm4gbGF5ZXJzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNldFpJbmRleCh6SW5kZXg6IE51bWJlcik6IHRoaXNcclxuICBcdC8vIENhbGxzIGBzZXRaSW5kZXhgIG9uIGV2ZXJ5IGxheWVyIGNvbnRhaW5lZCBpbiB0aGlzIGdyb3VwLCBwYXNzaW5nIHRoZSB6LWluZGV4LlxyXG4gIFx0c2V0WkluZGV4OiBmdW5jdGlvbiAoekluZGV4KSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLmludm9rZSgnc2V0WkluZGV4JywgekluZGV4KTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRMYXllcklkKGxheWVyOiBMYXllcik6IE51bWJlclxyXG4gIFx0Ly8gUmV0dXJucyB0aGUgaW50ZXJuYWwgSUQgZm9yIGEgbGF5ZXJcclxuICBcdGdldExheWVySWQ6IGZ1bmN0aW9uIChsYXllcikge1xyXG4gIFx0XHRyZXR1cm4gc3RhbXAobGF5ZXIpO1xyXG4gIFx0fVxyXG4gIH0pO1xyXG5cclxuXHJcbiAgLy8gQGZhY3RvcnkgTC5sYXllckdyb3VwKGxheWVycz86IExheWVyW10sIG9wdGlvbnM/OiBPYmplY3QpXHJcbiAgLy8gQ3JlYXRlIGEgbGF5ZXIgZ3JvdXAsIG9wdGlvbmFsbHkgZ2l2ZW4gYW4gaW5pdGlhbCBzZXQgb2YgbGF5ZXJzIGFuZCBhbiBgb3B0aW9uc2Agb2JqZWN0LlxyXG4gIHZhciBsYXllckdyb3VwID0gZnVuY3Rpb24gKGxheWVycywgb3B0aW9ucykge1xyXG4gIFx0cmV0dXJuIG5ldyBMYXllckdyb3VwKGxheWVycywgb3B0aW9ucyk7XHJcbiAgfTtcblxuICAvKlxyXG4gICAqIEBjbGFzcyBGZWF0dXJlR3JvdXBcclxuICAgKiBAYWthIEwuRmVhdHVyZUdyb3VwXHJcbiAgICogQGluaGVyaXRzIExheWVyR3JvdXBcclxuICAgKlxyXG4gICAqIEV4dGVuZGVkIGBMYXllckdyb3VwYCB0aGF0IG1ha2VzIGl0IGVhc2llciB0byBkbyB0aGUgc2FtZSB0aGluZyB0byBhbGwgaXRzIG1lbWJlciBsYXllcnM6XHJcbiAgICogICogW2BiaW5kUG9wdXBgXSgjbGF5ZXItYmluZHBvcHVwKSBiaW5kcyBhIHBvcHVwIHRvIGFsbCBvZiB0aGUgbGF5ZXJzIGF0IG9uY2UgKGxpa2V3aXNlIHdpdGggW2BiaW5kVG9vbHRpcGBdKCNsYXllci1iaW5kdG9vbHRpcCkpXHJcbiAgICogICogRXZlbnRzIGFyZSBwcm9wYWdhdGVkIHRvIHRoZSBgRmVhdHVyZUdyb3VwYCwgc28gaWYgdGhlIGdyb3VwIGhhcyBhbiBldmVudFxyXG4gICAqIGhhbmRsZXIsIGl0IHdpbGwgaGFuZGxlIGV2ZW50cyBmcm9tIGFueSBvZiB0aGUgbGF5ZXJzLiBUaGlzIGluY2x1ZGVzIG1vdXNlIGV2ZW50c1xyXG4gICAqIGFuZCBjdXN0b20gZXZlbnRzLlxyXG4gICAqICAqIEhhcyBgbGF5ZXJhZGRgIGFuZCBgbGF5ZXJyZW1vdmVgIGV2ZW50c1xyXG4gICAqXHJcbiAgICogQGV4YW1wbGVcclxuICAgKlxyXG4gICAqIGBgYGpzXHJcbiAgICogTC5mZWF0dXJlR3JvdXAoW21hcmtlcjEsIG1hcmtlcjIsIHBvbHlsaW5lXSlcclxuICAgKiBcdC5iaW5kUG9wdXAoJ0hlbGxvIHdvcmxkIScpXHJcbiAgICogXHQub24oJ2NsaWNrJywgZnVuY3Rpb24oKSB7IGFsZXJ0KCdDbGlja2VkIG9uIGEgbWVtYmVyIG9mIHRoZSBncm91cCEnKTsgfSlcclxuICAgKiBcdC5hZGRUbyhtYXApO1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG5cclxuICB2YXIgRmVhdHVyZUdyb3VwID0gTGF5ZXJHcm91cC5leHRlbmQoe1xyXG5cclxuICBcdGFkZExheWVyOiBmdW5jdGlvbiAobGF5ZXIpIHtcclxuICBcdFx0aWYgKHRoaXMuaGFzTGF5ZXIobGF5ZXIpKSB7XHJcbiAgXHRcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGxheWVyLmFkZEV2ZW50UGFyZW50KHRoaXMpO1xyXG5cclxuICBcdFx0TGF5ZXJHcm91cC5wcm90b3R5cGUuYWRkTGF5ZXIuY2FsbCh0aGlzLCBsYXllcik7XHJcblxyXG4gIFx0XHQvLyBAZXZlbnQgbGF5ZXJhZGQ6IExheWVyRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiBhIGxheWVyIGlzIGFkZGVkIHRvIHRoaXMgYEZlYXR1cmVHcm91cGBcclxuICBcdFx0cmV0dXJuIHRoaXMuZmlyZSgnbGF5ZXJhZGQnLCB7bGF5ZXI6IGxheWVyfSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdHJlbW92ZUxheWVyOiBmdW5jdGlvbiAobGF5ZXIpIHtcclxuICBcdFx0aWYgKCF0aGlzLmhhc0xheWVyKGxheWVyKSkge1xyXG4gIFx0XHRcdHJldHVybiB0aGlzO1xyXG4gIFx0XHR9XHJcbiAgXHRcdGlmIChsYXllciBpbiB0aGlzLl9sYXllcnMpIHtcclxuICBcdFx0XHRsYXllciA9IHRoaXMuX2xheWVyc1tsYXllcl07XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGxheWVyLnJlbW92ZUV2ZW50UGFyZW50KHRoaXMpO1xyXG5cclxuICBcdFx0TGF5ZXJHcm91cC5wcm90b3R5cGUucmVtb3ZlTGF5ZXIuY2FsbCh0aGlzLCBsYXllcik7XHJcblxyXG4gIFx0XHQvLyBAZXZlbnQgbGF5ZXJyZW1vdmU6IExheWVyRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiBhIGxheWVyIGlzIHJlbW92ZWQgZnJvbSB0aGlzIGBGZWF0dXJlR3JvdXBgXHJcbiAgXHRcdHJldHVybiB0aGlzLmZpcmUoJ2xheWVycmVtb3ZlJywge2xheWVyOiBsYXllcn0pO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNldFN0eWxlKHN0eWxlOiBQYXRoIG9wdGlvbnMpOiB0aGlzXHJcbiAgXHQvLyBTZXRzIHRoZSBnaXZlbiBwYXRoIG9wdGlvbnMgdG8gZWFjaCBsYXllciBvZiB0aGUgZ3JvdXAgdGhhdCBoYXMgYSBgc2V0U3R5bGVgIG1ldGhvZC5cclxuICBcdHNldFN0eWxlOiBmdW5jdGlvbiAoc3R5bGUpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuaW52b2tlKCdzZXRTdHlsZScsIHN0eWxlKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBicmluZ1RvRnJvbnQoKTogdGhpc1xyXG4gIFx0Ly8gQnJpbmdzIHRoZSBsYXllciBncm91cCB0byB0aGUgdG9wIG9mIGFsbCBvdGhlciBsYXllcnNcclxuICBcdGJyaW5nVG9Gcm9udDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5pbnZva2UoJ2JyaW5nVG9Gcm9udCcpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGJyaW5nVG9CYWNrKCk6IHRoaXNcclxuICBcdC8vIEJyaW5ncyB0aGUgbGF5ZXIgZ3JvdXAgdG8gdGhlIGJhY2sgb2YgYWxsIG90aGVyIGxheWVyc1xyXG4gIFx0YnJpbmdUb0JhY2s6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuaW52b2tlKCdicmluZ1RvQmFjaycpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldEJvdW5kcygpOiBMYXRMbmdCb3VuZHNcclxuICBcdC8vIFJldHVybnMgdGhlIExhdExuZ0JvdW5kcyBvZiB0aGUgRmVhdHVyZSBHcm91cCAoY3JlYXRlZCBmcm9tIGJvdW5kcyBhbmQgY29vcmRpbmF0ZXMgb2YgaXRzIGNoaWxkcmVuKS5cclxuICBcdGdldEJvdW5kczogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR2YXIgYm91bmRzID0gbmV3IExhdExuZ0JvdW5kcygpO1xyXG5cclxuICBcdFx0Zm9yICh2YXIgaWQgaW4gdGhpcy5fbGF5ZXJzKSB7XHJcbiAgXHRcdFx0dmFyIGxheWVyID0gdGhpcy5fbGF5ZXJzW2lkXTtcclxuICBcdFx0XHRib3VuZHMuZXh0ZW5kKGxheWVyLmdldEJvdW5kcyA/IGxheWVyLmdldEJvdW5kcygpIDogbGF5ZXIuZ2V0TGF0TG5nKCkpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiBib3VuZHM7XHJcbiAgXHR9XHJcbiAgfSk7XHJcblxyXG4gIC8vIEBmYWN0b3J5IEwuZmVhdHVyZUdyb3VwKGxheWVycz86IExheWVyW10sIG9wdGlvbnM/OiBPYmplY3QpXHJcbiAgLy8gQ3JlYXRlIGEgZmVhdHVyZSBncm91cCwgb3B0aW9uYWxseSBnaXZlbiBhbiBpbml0aWFsIHNldCBvZiBsYXllcnMgYW5kIGFuIGBvcHRpb25zYCBvYmplY3QuXHJcbiAgdmFyIGZlYXR1cmVHcm91cCA9IGZ1bmN0aW9uIChsYXllcnMsIG9wdGlvbnMpIHtcclxuICBcdHJldHVybiBuZXcgRmVhdHVyZUdyb3VwKGxheWVycywgb3B0aW9ucyk7XHJcbiAgfTtcblxuICAvKlxyXG4gICAqIEBjbGFzcyBJY29uXHJcbiAgICogQGFrYSBMLkljb25cclxuICAgKlxyXG4gICAqIFJlcHJlc2VudHMgYW4gaWNvbiB0byBwcm92aWRlIHdoZW4gY3JlYXRpbmcgYSBtYXJrZXIuXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiB2YXIgbXlJY29uID0gTC5pY29uKHtcclxuICAgKiAgICAgaWNvblVybDogJ215LWljb24ucG5nJyxcclxuICAgKiAgICAgaWNvblJldGluYVVybDogJ215LWljb25AMngucG5nJyxcclxuICAgKiAgICAgaWNvblNpemU6IFszOCwgOTVdLFxyXG4gICAqICAgICBpY29uQW5jaG9yOiBbMjIsIDk0XSxcclxuICAgKiAgICAgcG9wdXBBbmNob3I6IFstMywgLTc2XSxcclxuICAgKiAgICAgc2hhZG93VXJsOiAnbXktaWNvbi1zaGFkb3cucG5nJyxcclxuICAgKiAgICAgc2hhZG93UmV0aW5hVXJsOiAnbXktaWNvbi1zaGFkb3dAMngucG5nJyxcclxuICAgKiAgICAgc2hhZG93U2l6ZTogWzY4LCA5NV0sXHJcbiAgICogICAgIHNoYWRvd0FuY2hvcjogWzIyLCA5NF1cclxuICAgKiB9KTtcclxuICAgKlxyXG4gICAqIEwubWFya2VyKFs1MC41MDUsIDMwLjU3XSwge2ljb246IG15SWNvbn0pLmFkZFRvKG1hcCk7XHJcbiAgICogYGBgXHJcbiAgICpcclxuICAgKiBgTC5JY29uLkRlZmF1bHRgIGV4dGVuZHMgYEwuSWNvbmAgYW5kIGlzIHRoZSBibHVlIGljb24gTGVhZmxldCB1c2VzIGZvciBtYXJrZXJzIGJ5IGRlZmF1bHQuXHJcbiAgICpcclxuICAgKi9cclxuXHJcbiAgdmFyIEljb24gPSBDbGFzcy5leHRlbmQoe1xyXG5cclxuICBcdC8qIEBzZWN0aW9uXHJcbiAgXHQgKiBAYWthIEljb24gb3B0aW9uc1xyXG4gIFx0ICpcclxuICBcdCAqIEBvcHRpb24gaWNvblVybDogU3RyaW5nID0gbnVsbFxyXG4gIFx0ICogKioocmVxdWlyZWQpKiogVGhlIFVSTCB0byB0aGUgaWNvbiBpbWFnZSAoYWJzb2x1dGUgb3IgcmVsYXRpdmUgdG8geW91ciBzY3JpcHQgcGF0aCkuXHJcbiAgXHQgKlxyXG4gIFx0ICogQG9wdGlvbiBpY29uUmV0aW5hVXJsOiBTdHJpbmcgPSBudWxsXHJcbiAgXHQgKiBUaGUgVVJMIHRvIGEgcmV0aW5hIHNpemVkIHZlcnNpb24gb2YgdGhlIGljb24gaW1hZ2UgKGFic29sdXRlIG9yIHJlbGF0aXZlIHRvIHlvdXJcclxuICBcdCAqIHNjcmlwdCBwYXRoKS4gVXNlZCBmb3IgUmV0aW5hIHNjcmVlbiBkZXZpY2VzLlxyXG4gIFx0ICpcclxuICBcdCAqIEBvcHRpb24gaWNvblNpemU6IFBvaW50ID0gbnVsbFxyXG4gIFx0ICogU2l6ZSBvZiB0aGUgaWNvbiBpbWFnZSBpbiBwaXhlbHMuXHJcbiAgXHQgKlxyXG4gIFx0ICogQG9wdGlvbiBpY29uQW5jaG9yOiBQb2ludCA9IG51bGxcclxuICBcdCAqIFRoZSBjb29yZGluYXRlcyBvZiB0aGUgXCJ0aXBcIiBvZiB0aGUgaWNvbiAocmVsYXRpdmUgdG8gaXRzIHRvcCBsZWZ0IGNvcm5lcikuIFRoZSBpY29uXHJcbiAgXHQgKiB3aWxsIGJlIGFsaWduZWQgc28gdGhhdCB0aGlzIHBvaW50IGlzIGF0IHRoZSBtYXJrZXIncyBnZW9ncmFwaGljYWwgbG9jYXRpb24uIENlbnRlcmVkXHJcbiAgXHQgKiBieSBkZWZhdWx0IGlmIHNpemUgaXMgc3BlY2lmaWVkLCBhbHNvIGNhbiBiZSBzZXQgaW4gQ1NTIHdpdGggbmVnYXRpdmUgbWFyZ2lucy5cclxuICBcdCAqXHJcbiAgXHQgKiBAb3B0aW9uIHBvcHVwQW5jaG9yOiBQb2ludCA9IFswLCAwXVxyXG4gIFx0ICogVGhlIGNvb3JkaW5hdGVzIG9mIHRoZSBwb2ludCBmcm9tIHdoaWNoIHBvcHVwcyB3aWxsIFwib3BlblwiLCByZWxhdGl2ZSB0byB0aGUgaWNvbiBhbmNob3IuXHJcbiAgXHQgKlxyXG4gIFx0ICogQG9wdGlvbiB0b29sdGlwQW5jaG9yOiBQb2ludCA9IFswLCAwXVxyXG4gIFx0ICogVGhlIGNvb3JkaW5hdGVzIG9mIHRoZSBwb2ludCBmcm9tIHdoaWNoIHRvb2x0aXBzIHdpbGwgXCJvcGVuXCIsIHJlbGF0aXZlIHRvIHRoZSBpY29uIGFuY2hvci5cclxuICBcdCAqXHJcbiAgXHQgKiBAb3B0aW9uIHNoYWRvd1VybDogU3RyaW5nID0gbnVsbFxyXG4gIFx0ICogVGhlIFVSTCB0byB0aGUgaWNvbiBzaGFkb3cgaW1hZ2UuIElmIG5vdCBzcGVjaWZpZWQsIG5vIHNoYWRvdyBpbWFnZSB3aWxsIGJlIGNyZWF0ZWQuXHJcbiAgXHQgKlxyXG4gIFx0ICogQG9wdGlvbiBzaGFkb3dSZXRpbmFVcmw6IFN0cmluZyA9IG51bGxcclxuICBcdCAqXHJcbiAgXHQgKiBAb3B0aW9uIHNoYWRvd1NpemU6IFBvaW50ID0gbnVsbFxyXG4gIFx0ICogU2l6ZSBvZiB0aGUgc2hhZG93IGltYWdlIGluIHBpeGVscy5cclxuICBcdCAqXHJcbiAgXHQgKiBAb3B0aW9uIHNoYWRvd0FuY2hvcjogUG9pbnQgPSBudWxsXHJcbiAgXHQgKiBUaGUgY29vcmRpbmF0ZXMgb2YgdGhlIFwidGlwXCIgb2YgdGhlIHNoYWRvdyAocmVsYXRpdmUgdG8gaXRzIHRvcCBsZWZ0IGNvcm5lcikgKHRoZSBzYW1lXHJcbiAgXHQgKiBhcyBpY29uQW5jaG9yIGlmIG5vdCBzcGVjaWZpZWQpLlxyXG4gIFx0ICpcclxuICBcdCAqIEBvcHRpb24gY2xhc3NOYW1lOiBTdHJpbmcgPSAnJ1xyXG4gIFx0ICogQSBjdXN0b20gY2xhc3MgbmFtZSB0byBhc3NpZ24gdG8gYm90aCBpY29uIGFuZCBzaGFkb3cgaW1hZ2VzLiBFbXB0eSBieSBkZWZhdWx0LlxyXG4gIFx0ICovXHJcblxyXG4gIFx0b3B0aW9uczoge1xyXG4gIFx0XHRwb3B1cEFuY2hvcjogWzAsIDBdLFxyXG4gIFx0XHR0b29sdGlwQW5jaG9yOiBbMCwgMF0sXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIGNyb3NzT3JpZ2luOiBCb29sZWFufFN0cmluZyA9IGZhbHNlXHJcbiAgXHRcdC8vIFdoZXRoZXIgdGhlIGNyb3NzT3JpZ2luIGF0dHJpYnV0ZSB3aWxsIGJlIGFkZGVkIHRvIHRoZSB0aWxlcy5cclxuICBcdFx0Ly8gSWYgYSBTdHJpbmcgaXMgcHJvdmlkZWQsIGFsbCB0aWxlcyB3aWxsIGhhdmUgdGhlaXIgY3Jvc3NPcmlnaW4gYXR0cmlidXRlIHNldCB0byB0aGUgU3RyaW5nIHByb3ZpZGVkLiBUaGlzIGlzIG5lZWRlZCBpZiB5b3Ugd2FudCB0byBhY2Nlc3MgdGlsZSBwaXhlbCBkYXRhLlxyXG4gIFx0XHQvLyBSZWZlciB0byBbQ09SUyBTZXR0aW5nc10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSFRNTC9DT1JTX3NldHRpbmdzX2F0dHJpYnV0ZXMpIGZvciB2YWxpZCBTdHJpbmcgdmFsdWVzLlxyXG4gIFx0XHRjcm9zc09yaWdpbjogZmFsc2VcclxuICBcdH0sXHJcblxyXG4gIFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuICBcdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBjcmVhdGVJY29uKG9sZEljb24/OiBIVE1MRWxlbWVudCk6IEhUTUxFbGVtZW50XHJcbiAgXHQvLyBDYWxsZWQgaW50ZXJuYWxseSB3aGVuIHRoZSBpY29uIGhhcyB0byBiZSBzaG93biwgcmV0dXJucyBhIGA8aW1nPmAgSFRNTCBlbGVtZW50XHJcbiAgXHQvLyBzdHlsZWQgYWNjb3JkaW5nIHRvIHRoZSBvcHRpb25zLlxyXG4gIFx0Y3JlYXRlSWNvbjogZnVuY3Rpb24gKG9sZEljb24pIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuX2NyZWF0ZUljb24oJ2ljb24nLCBvbGRJY29uKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBjcmVhdGVTaGFkb3cob2xkSWNvbj86IEhUTUxFbGVtZW50KTogSFRNTEVsZW1lbnRcclxuICBcdC8vIEFzIGBjcmVhdGVJY29uYCwgYnV0IGZvciB0aGUgc2hhZG93IGJlbmVhdGggaXQuXHJcbiAgXHRjcmVhdGVTaGFkb3c6IGZ1bmN0aW9uIChvbGRJY29uKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLl9jcmVhdGVJY29uKCdzaGFkb3cnLCBvbGRJY29uKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X2NyZWF0ZUljb246IGZ1bmN0aW9uIChuYW1lLCBvbGRJY29uKSB7XHJcbiAgXHRcdHZhciBzcmMgPSB0aGlzLl9nZXRJY29uVXJsKG5hbWUpO1xyXG5cclxuICBcdFx0aWYgKCFzcmMpIHtcclxuICBcdFx0XHRpZiAobmFtZSA9PT0gJ2ljb24nKSB7XHJcbiAgXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ2ljb25Vcmwgbm90IHNldCBpbiBJY29uIG9wdGlvbnMgKHNlZSB0aGUgZG9jcykuJyk7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHRcdHJldHVybiBudWxsO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgaW1nID0gdGhpcy5fY3JlYXRlSW1nKHNyYywgb2xkSWNvbiAmJiBvbGRJY29uLnRhZ05hbWUgPT09ICdJTUcnID8gb2xkSWNvbiA6IG51bGwpO1xyXG4gIFx0XHR0aGlzLl9zZXRJY29uU3R5bGVzKGltZywgbmFtZSk7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5vcHRpb25zLmNyb3NzT3JpZ2luIHx8IHRoaXMub3B0aW9ucy5jcm9zc09yaWdpbiA9PT0gJycpIHtcclxuICBcdFx0XHRpbWcuY3Jvc3NPcmlnaW4gPSB0aGlzLm9wdGlvbnMuY3Jvc3NPcmlnaW4gPT09IHRydWUgPyAnJyA6IHRoaXMub3B0aW9ucy5jcm9zc09yaWdpbjtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0cmV0dXJuIGltZztcclxuICBcdH0sXHJcblxyXG4gIFx0X3NldEljb25TdHlsZXM6IGZ1bmN0aW9uIChpbWcsIG5hbWUpIHtcclxuICBcdFx0dmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XHJcbiAgXHRcdHZhciBzaXplT3B0aW9uID0gb3B0aW9uc1tuYW1lICsgJ1NpemUnXTtcclxuXHJcbiAgXHRcdGlmICh0eXBlb2Ygc2l6ZU9wdGlvbiA9PT0gJ251bWJlcicpIHtcclxuICBcdFx0XHRzaXplT3B0aW9uID0gW3NpemVPcHRpb24sIHNpemVPcHRpb25dO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgc2l6ZSA9IHRvUG9pbnQoc2l6ZU9wdGlvbiksXHJcbiAgXHRcdCAgICBhbmNob3IgPSB0b1BvaW50KG5hbWUgPT09ICdzaGFkb3cnICYmIG9wdGlvbnMuc2hhZG93QW5jaG9yIHx8IG9wdGlvbnMuaWNvbkFuY2hvciB8fFxyXG4gIFx0XHQgICAgICAgICAgICBzaXplICYmIHNpemUuZGl2aWRlQnkoMiwgdHJ1ZSkpO1xyXG5cclxuICBcdFx0aW1nLmNsYXNzTmFtZSA9ICdsZWFmbGV0LW1hcmtlci0nICsgbmFtZSArICcgJyArIChvcHRpb25zLmNsYXNzTmFtZSB8fCAnJyk7XHJcblxyXG4gIFx0XHRpZiAoYW5jaG9yKSB7XHJcbiAgXHRcdFx0aW1nLnN0eWxlLm1hcmdpbkxlZnQgPSAoLWFuY2hvci54KSArICdweCc7XHJcbiAgXHRcdFx0aW1nLnN0eWxlLm1hcmdpblRvcCAgPSAoLWFuY2hvci55KSArICdweCc7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmIChzaXplKSB7XHJcbiAgXHRcdFx0aW1nLnN0eWxlLndpZHRoICA9IHNpemUueCArICdweCc7XHJcbiAgXHRcdFx0aW1nLnN0eWxlLmhlaWdodCA9IHNpemUueSArICdweCc7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0X2NyZWF0ZUltZzogZnVuY3Rpb24gKHNyYywgZWwpIHtcclxuICBcdFx0ZWwgPSBlbCB8fCBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTtcclxuICBcdFx0ZWwuc3JjID0gc3JjO1xyXG4gIFx0XHRyZXR1cm4gZWw7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9nZXRJY29uVXJsOiBmdW5jdGlvbiAobmFtZSkge1xyXG4gIFx0XHRyZXR1cm4gQnJvd3Nlci5yZXRpbmEgJiYgdGhpcy5vcHRpb25zW25hbWUgKyAnUmV0aW5hVXJsJ10gfHwgdGhpcy5vcHRpb25zW25hbWUgKyAnVXJsJ107XHJcbiAgXHR9XHJcbiAgfSk7XHJcblxyXG5cclxuICAvLyBAZmFjdG9yeSBMLmljb24ob3B0aW9uczogSWNvbiBvcHRpb25zKVxyXG4gIC8vIENyZWF0ZXMgYW4gaWNvbiBpbnN0YW5jZSB3aXRoIHRoZSBnaXZlbiBvcHRpb25zLlxyXG4gIGZ1bmN0aW9uIGljb24ob3B0aW9ucykge1xyXG4gIFx0cmV0dXJuIG5ldyBJY29uKG9wdGlvbnMpO1xyXG4gIH1cblxuICAvKlxuICAgKiBAbWluaWNsYXNzIEljb24uRGVmYXVsdCAoSWNvbilcbiAgICogQGFrYSBMLkljb24uRGVmYXVsdFxuICAgKiBAc2VjdGlvblxuICAgKlxuICAgKiBBIHRyaXZpYWwgc3ViY2xhc3Mgb2YgYEljb25gLCByZXByZXNlbnRzIHRoZSBpY29uIHRvIHVzZSBpbiBgTWFya2VyYHMgd2hlblxuICAgKiBubyBpY29uIGlzIHNwZWNpZmllZC4gUG9pbnRzIHRvIHRoZSBibHVlIG1hcmtlciBpbWFnZSBkaXN0cmlidXRlZCB3aXRoIExlYWZsZXRcbiAgICogcmVsZWFzZXMuXG4gICAqXG4gICAqIEluIG9yZGVyIHRvIGN1c3RvbWl6ZSB0aGUgZGVmYXVsdCBpY29uLCBqdXN0IGNoYW5nZSB0aGUgcHJvcGVydGllcyBvZiBgTC5JY29uLkRlZmF1bHQucHJvdG90eXBlLm9wdGlvbnNgXG4gICAqICh3aGljaCBpcyBhIHNldCBvZiBgSWNvbiBvcHRpb25zYCkuXG4gICAqXG4gICAqIElmIHlvdSB3YW50IHRvIF9jb21wbGV0ZWx5XyByZXBsYWNlIHRoZSBkZWZhdWx0IGljb24sIG92ZXJyaWRlIHRoZVxuICAgKiBgTC5NYXJrZXIucHJvdG90eXBlLm9wdGlvbnMuaWNvbmAgd2l0aCB5b3VyIG93biBpY29uIGluc3RlYWQuXG4gICAqL1xuXG4gIHZhciBJY29uRGVmYXVsdCA9IEljb24uZXh0ZW5kKHtcblxuICBcdG9wdGlvbnM6IHtcbiAgXHRcdGljb25Vcmw6ICAgICAgICdtYXJrZXItaWNvbi5wbmcnLFxuICBcdFx0aWNvblJldGluYVVybDogJ21hcmtlci1pY29uLTJ4LnBuZycsXG4gIFx0XHRzaGFkb3dVcmw6ICAgICAnbWFya2VyLXNoYWRvdy5wbmcnLFxuICBcdFx0aWNvblNpemU6ICAgIFsyNSwgNDFdLFxuICBcdFx0aWNvbkFuY2hvcjogIFsxMiwgNDFdLFxuICBcdFx0cG9wdXBBbmNob3I6IFsxLCAtMzRdLFxuICBcdFx0dG9vbHRpcEFuY2hvcjogWzE2LCAtMjhdLFxuICBcdFx0c2hhZG93U2l6ZTogIFs0MSwgNDFdXG4gIFx0fSxcblxuICBcdF9nZXRJY29uVXJsOiBmdW5jdGlvbiAobmFtZSkge1xuICBcdFx0aWYgKHR5cGVvZiBJY29uRGVmYXVsdC5pbWFnZVBhdGggIT09ICdzdHJpbmcnKSB7XHQvLyBEZXByZWNhdGVkLCBiYWNrd2FyZHMtY29tcGF0aWJpbGl0eSBvbmx5XG4gIFx0XHRcdEljb25EZWZhdWx0LmltYWdlUGF0aCA9IHRoaXMuX2RldGVjdEljb25QYXRoKCk7XG4gIFx0XHR9XG5cbiAgXHRcdC8vIEBvcHRpb24gaW1hZ2VQYXRoOiBTdHJpbmdcbiAgXHRcdC8vIGBJY29uLkRlZmF1bHRgIHdpbGwgdHJ5IHRvIGF1dG8tZGV0ZWN0IHRoZSBsb2NhdGlvbiBvZiB0aGVcbiAgXHRcdC8vIGJsdWUgaWNvbiBpbWFnZXMuIElmIHlvdSBhcmUgcGxhY2luZyB0aGVzZSBpbWFnZXMgaW4gYSBub24tc3RhbmRhcmRcbiAgXHRcdC8vIHdheSwgc2V0IHRoaXMgb3B0aW9uIHRvIHBvaW50IHRvIHRoZSByaWdodCBwYXRoLlxuICBcdFx0cmV0dXJuICh0aGlzLm9wdGlvbnMuaW1hZ2VQYXRoIHx8IEljb25EZWZhdWx0LmltYWdlUGF0aCkgKyBJY29uLnByb3RvdHlwZS5fZ2V0SWNvblVybC5jYWxsKHRoaXMsIG5hbWUpO1xuICBcdH0sXG5cbiAgXHRfc3RyaXBVcmw6IGZ1bmN0aW9uIChwYXRoKSB7XHQvLyBzZXBhcmF0ZSBmdW5jdGlvbiB0byB1c2UgaW4gdGVzdHNcbiAgXHRcdHZhciBzdHJpcCA9IGZ1bmN0aW9uIChzdHIsIHJlLCBpZHgpIHtcbiAgXHRcdFx0dmFyIG1hdGNoID0gcmUuZXhlYyhzdHIpO1xuICBcdFx0XHRyZXR1cm4gbWF0Y2ggJiYgbWF0Y2hbaWR4XTtcbiAgXHRcdH07XG4gIFx0XHRwYXRoID0gc3RyaXAocGF0aCwgL151cmxcXCgoWydcIl0pPyguKylcXDFcXCkkLywgMik7XG4gIFx0XHRyZXR1cm4gcGF0aCAmJiBzdHJpcChwYXRoLCAvXiguKiltYXJrZXItaWNvblxcLnBuZyQvLCAxKTtcbiAgXHR9LFxuXG4gIFx0X2RldGVjdEljb25QYXRoOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR2YXIgZWwgPSBjcmVhdGUkMSgnZGl2JywgICdsZWFmbGV0LWRlZmF1bHQtaWNvbi1wYXRoJywgZG9jdW1lbnQuYm9keSk7XG4gIFx0XHR2YXIgcGF0aCA9IGdldFN0eWxlKGVsLCAnYmFja2dyb3VuZC1pbWFnZScpIHx8XG4gIFx0XHQgICAgICAgICAgIGdldFN0eWxlKGVsLCAnYmFja2dyb3VuZEltYWdlJyk7XHQvLyBJRThcblxuICBcdFx0ZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChlbCk7XG4gIFx0XHRwYXRoID0gdGhpcy5fc3RyaXBVcmwocGF0aCk7XG4gIFx0XHRpZiAocGF0aCkgeyByZXR1cm4gcGF0aDsgfVxuICBcdFx0dmFyIGxpbmsgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdsaW5rW2hyZWYkPVwibGVhZmxldC5jc3NcIl0nKTtcbiAgXHRcdGlmICghbGluaykgeyByZXR1cm4gJyc7IH1cbiAgXHRcdHJldHVybiBsaW5rLmhyZWYuc3Vic3RyaW5nKDAsIGxpbmsuaHJlZi5sZW5ndGggLSAnbGVhZmxldC5jc3MnLmxlbmd0aCAtIDEpO1xuICBcdH1cbiAgfSk7XG5cbiAgLypcbiAgICogTC5IYW5kbGVyLk1hcmtlckRyYWcgaXMgdXNlZCBpbnRlcm5hbGx5IGJ5IEwuTWFya2VyIHRvIG1ha2UgdGhlIG1hcmtlcnMgZHJhZ2dhYmxlLlxuICAgKi9cblxuXG4gIC8qIEBuYW1lc3BhY2UgTWFya2VyXG4gICAqIEBzZWN0aW9uIEludGVyYWN0aW9uIGhhbmRsZXJzXG4gICAqXG4gICAqIEludGVyYWN0aW9uIGhhbmRsZXJzIGFyZSBwcm9wZXJ0aWVzIG9mIGEgbWFya2VyIGluc3RhbmNlIHRoYXQgYWxsb3cgeW91IHRvIGNvbnRyb2wgaW50ZXJhY3Rpb24gYmVoYXZpb3IgaW4gcnVudGltZSwgZW5hYmxpbmcgb3IgZGlzYWJsaW5nIGNlcnRhaW4gZmVhdHVyZXMgc3VjaCBhcyBkcmFnZ2luZyAoc2VlIGBIYW5kbGVyYCBtZXRob2RzKS4gRXhhbXBsZTpcbiAgICpcbiAgICogYGBganNcbiAgICogbWFya2VyLmRyYWdnaW5nLmRpc2FibGUoKTtcbiAgICogYGBgXG4gICAqXG4gICAqIEBwcm9wZXJ0eSBkcmFnZ2luZzogSGFuZGxlclxuICAgKiBNYXJrZXIgZHJhZ2dpbmcgaGFuZGxlciAoYnkgYm90aCBtb3VzZSBhbmQgdG91Y2gpLiBPbmx5IHZhbGlkIHdoZW4gdGhlIG1hcmtlciBpcyBvbiB0aGUgbWFwIChPdGhlcndpc2Ugc2V0IFtgbWFya2VyLm9wdGlvbnMuZHJhZ2dhYmxlYF0oI21hcmtlci1kcmFnZ2FibGUpKS5cbiAgICovXG5cbiAgdmFyIE1hcmtlckRyYWcgPSBIYW5kbGVyLmV4dGVuZCh7XG4gIFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKG1hcmtlcikge1xuICBcdFx0dGhpcy5fbWFya2VyID0gbWFya2VyO1xuICBcdH0sXG5cbiAgXHRhZGRIb29rczogZnVuY3Rpb24gKCkge1xuICBcdFx0dmFyIGljb24gPSB0aGlzLl9tYXJrZXIuX2ljb247XG5cbiAgXHRcdGlmICghdGhpcy5fZHJhZ2dhYmxlKSB7XG4gIFx0XHRcdHRoaXMuX2RyYWdnYWJsZSA9IG5ldyBEcmFnZ2FibGUoaWNvbiwgaWNvbiwgdHJ1ZSk7XG4gIFx0XHR9XG5cbiAgXHRcdHRoaXMuX2RyYWdnYWJsZS5vbih7XG4gIFx0XHRcdGRyYWdzdGFydDogdGhpcy5fb25EcmFnU3RhcnQsXG4gIFx0XHRcdHByZWRyYWc6IHRoaXMuX29uUHJlRHJhZyxcbiAgXHRcdFx0ZHJhZzogdGhpcy5fb25EcmFnLFxuICBcdFx0XHRkcmFnZW5kOiB0aGlzLl9vbkRyYWdFbmRcbiAgXHRcdH0sIHRoaXMpLmVuYWJsZSgpO1xuXG4gIFx0XHRhZGRDbGFzcyhpY29uLCAnbGVhZmxldC1tYXJrZXItZHJhZ2dhYmxlJyk7XG4gIFx0fSxcblxuICBcdHJlbW92ZUhvb2tzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR0aGlzLl9kcmFnZ2FibGUub2ZmKHtcbiAgXHRcdFx0ZHJhZ3N0YXJ0OiB0aGlzLl9vbkRyYWdTdGFydCxcbiAgXHRcdFx0cHJlZHJhZzogdGhpcy5fb25QcmVEcmFnLFxuICBcdFx0XHRkcmFnOiB0aGlzLl9vbkRyYWcsXG4gIFx0XHRcdGRyYWdlbmQ6IHRoaXMuX29uRHJhZ0VuZFxuICBcdFx0fSwgdGhpcykuZGlzYWJsZSgpO1xuXG4gIFx0XHRpZiAodGhpcy5fbWFya2VyLl9pY29uKSB7XG4gIFx0XHRcdHJlbW92ZUNsYXNzKHRoaXMuX21hcmtlci5faWNvbiwgJ2xlYWZsZXQtbWFya2VyLWRyYWdnYWJsZScpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRtb3ZlZDogZnVuY3Rpb24gKCkge1xuICBcdFx0cmV0dXJuIHRoaXMuX2RyYWdnYWJsZSAmJiB0aGlzLl9kcmFnZ2FibGUuX21vdmVkO1xuICBcdH0sXG5cbiAgXHRfYWRqdXN0UGFuOiBmdW5jdGlvbiAoZSkge1xuICBcdFx0dmFyIG1hcmtlciA9IHRoaXMuX21hcmtlcixcbiAgXHRcdCAgICBtYXAgPSBtYXJrZXIuX21hcCxcbiAgXHRcdCAgICBzcGVlZCA9IHRoaXMuX21hcmtlci5vcHRpb25zLmF1dG9QYW5TcGVlZCxcbiAgXHRcdCAgICBwYWRkaW5nID0gdGhpcy5fbWFya2VyLm9wdGlvbnMuYXV0b1BhblBhZGRpbmcsXG4gIFx0XHQgICAgaWNvblBvcyA9IGdldFBvc2l0aW9uKG1hcmtlci5faWNvbiksXG4gIFx0XHQgICAgYm91bmRzID0gbWFwLmdldFBpeGVsQm91bmRzKCksXG4gIFx0XHQgICAgb3JpZ2luID0gbWFwLmdldFBpeGVsT3JpZ2luKCk7XG5cbiAgXHRcdHZhciBwYW5Cb3VuZHMgPSB0b0JvdW5kcyhcbiAgXHRcdFx0Ym91bmRzLm1pbi5fc3VidHJhY3Qob3JpZ2luKS5hZGQocGFkZGluZyksXG4gIFx0XHRcdGJvdW5kcy5tYXguX3N1YnRyYWN0KG9yaWdpbikuc3VidHJhY3QocGFkZGluZylcbiAgXHRcdCk7XG5cbiAgXHRcdGlmICghcGFuQm91bmRzLmNvbnRhaW5zKGljb25Qb3MpKSB7XG4gIFx0XHRcdC8vIENvbXB1dGUgaW5jcmVtZW50YWwgbW92ZW1lbnRcbiAgXHRcdFx0dmFyIG1vdmVtZW50ID0gdG9Qb2ludChcbiAgXHRcdFx0XHQoTWF0aC5tYXgocGFuQm91bmRzLm1heC54LCBpY29uUG9zLngpIC0gcGFuQm91bmRzLm1heC54KSAvIChib3VuZHMubWF4LnggLSBwYW5Cb3VuZHMubWF4LngpIC1cbiAgXHRcdFx0XHQoTWF0aC5taW4ocGFuQm91bmRzLm1pbi54LCBpY29uUG9zLngpIC0gcGFuQm91bmRzLm1pbi54KSAvIChib3VuZHMubWluLnggLSBwYW5Cb3VuZHMubWluLngpLFxuXG4gIFx0XHRcdFx0KE1hdGgubWF4KHBhbkJvdW5kcy5tYXgueSwgaWNvblBvcy55KSAtIHBhbkJvdW5kcy5tYXgueSkgLyAoYm91bmRzLm1heC55IC0gcGFuQm91bmRzLm1heC55KSAtXG4gIFx0XHRcdFx0KE1hdGgubWluKHBhbkJvdW5kcy5taW4ueSwgaWNvblBvcy55KSAtIHBhbkJvdW5kcy5taW4ueSkgLyAoYm91bmRzLm1pbi55IC0gcGFuQm91bmRzLm1pbi55KVxuICBcdFx0XHQpLm11bHRpcGx5Qnkoc3BlZWQpO1xuXG4gIFx0XHRcdG1hcC5wYW5CeShtb3ZlbWVudCwge2FuaW1hdGU6IGZhbHNlfSk7XG5cbiAgXHRcdFx0dGhpcy5fZHJhZ2dhYmxlLl9uZXdQb3MuX2FkZChtb3ZlbWVudCk7XG4gIFx0XHRcdHRoaXMuX2RyYWdnYWJsZS5fc3RhcnRQb3MuX2FkZChtb3ZlbWVudCk7XG5cbiAgXHRcdFx0c2V0UG9zaXRpb24obWFya2VyLl9pY29uLCB0aGlzLl9kcmFnZ2FibGUuX25ld1Bvcyk7XG4gIFx0XHRcdHRoaXMuX29uRHJhZyhlKTtcblxuICBcdFx0XHR0aGlzLl9wYW5SZXF1ZXN0ID0gcmVxdWVzdEFuaW1GcmFtZSh0aGlzLl9hZGp1c3RQYW4uYmluZCh0aGlzLCBlKSk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF9vbkRyYWdTdGFydDogZnVuY3Rpb24gKCkge1xuICBcdFx0Ly8gQHNlY3Rpb24gRHJhZ2dpbmcgZXZlbnRzXG4gIFx0XHQvLyBAZXZlbnQgZHJhZ3N0YXJ0OiBFdmVudFxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgdXNlciBzdGFydHMgZHJhZ2dpbmcgdGhlIG1hcmtlci5cblxuICBcdFx0Ly8gQGV2ZW50IG1vdmVzdGFydDogRXZlbnRcbiAgXHRcdC8vIEZpcmVkIHdoZW4gdGhlIG1hcmtlciBzdGFydHMgbW92aW5nIChiZWNhdXNlIG9mIGRyYWdnaW5nKS5cblxuICBcdFx0dGhpcy5fb2xkTGF0TG5nID0gdGhpcy5fbWFya2VyLmdldExhdExuZygpO1xuXG4gIFx0XHQvLyBXaGVuIHVzaW5nIEVTNiBpbXBvcnRzIGl0IGNvdWxkIG5vdCBiZSBzZXQgd2hlbiBgUG9wdXBgIHdhcyBub3QgaW1wb3J0ZWQgYXMgd2VsbFxuICBcdFx0dGhpcy5fbWFya2VyLmNsb3NlUG9wdXAgJiYgdGhpcy5fbWFya2VyLmNsb3NlUG9wdXAoKTtcblxuICBcdFx0dGhpcy5fbWFya2VyXG4gIFx0XHRcdC5maXJlKCdtb3Zlc3RhcnQnKVxuICBcdFx0XHQuZmlyZSgnZHJhZ3N0YXJ0Jyk7XG4gIFx0fSxcblxuICBcdF9vblByZURyYWc6IGZ1bmN0aW9uIChlKSB7XG4gIFx0XHRpZiAodGhpcy5fbWFya2VyLm9wdGlvbnMuYXV0b1Bhbikge1xuICBcdFx0XHRjYW5jZWxBbmltRnJhbWUodGhpcy5fcGFuUmVxdWVzdCk7XG4gIFx0XHRcdHRoaXMuX3BhblJlcXVlc3QgPSByZXF1ZXN0QW5pbUZyYW1lKHRoaXMuX2FkanVzdFBhbi5iaW5kKHRoaXMsIGUpKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X29uRHJhZzogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdHZhciBtYXJrZXIgPSB0aGlzLl9tYXJrZXIsXG4gIFx0XHQgICAgc2hhZG93ID0gbWFya2VyLl9zaGFkb3csXG4gIFx0XHQgICAgaWNvblBvcyA9IGdldFBvc2l0aW9uKG1hcmtlci5faWNvbiksXG4gIFx0XHQgICAgbGF0bG5nID0gbWFya2VyLl9tYXAubGF5ZXJQb2ludFRvTGF0TG5nKGljb25Qb3MpO1xuXG4gIFx0XHQvLyB1cGRhdGUgc2hhZG93IHBvc2l0aW9uXG4gIFx0XHRpZiAoc2hhZG93KSB7XG4gIFx0XHRcdHNldFBvc2l0aW9uKHNoYWRvdywgaWNvblBvcyk7XG4gIFx0XHR9XG5cbiAgXHRcdG1hcmtlci5fbGF0bG5nID0gbGF0bG5nO1xuICBcdFx0ZS5sYXRsbmcgPSBsYXRsbmc7XG4gIFx0XHRlLm9sZExhdExuZyA9IHRoaXMuX29sZExhdExuZztcblxuICBcdFx0Ly8gQGV2ZW50IGRyYWc6IEV2ZW50XG4gIFx0XHQvLyBGaXJlZCByZXBlYXRlZGx5IHdoaWxlIHRoZSB1c2VyIGRyYWdzIHRoZSBtYXJrZXIuXG4gIFx0XHRtYXJrZXJcbiAgXHRcdCAgICAuZmlyZSgnbW92ZScsIGUpXG4gIFx0XHQgICAgLmZpcmUoJ2RyYWcnLCBlKTtcbiAgXHR9LFxuXG4gIFx0X29uRHJhZ0VuZDogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdC8vIEBldmVudCBkcmFnZW5kOiBEcmFnRW5kRXZlbnRcbiAgXHRcdC8vIEZpcmVkIHdoZW4gdGhlIHVzZXIgc3RvcHMgZHJhZ2dpbmcgdGhlIG1hcmtlci5cblxuICBcdFx0IGNhbmNlbEFuaW1GcmFtZSh0aGlzLl9wYW5SZXF1ZXN0KTtcblxuICBcdFx0Ly8gQGV2ZW50IG1vdmVlbmQ6IEV2ZW50XG4gIFx0XHQvLyBGaXJlZCB3aGVuIHRoZSBtYXJrZXIgc3RvcHMgbW92aW5nIChiZWNhdXNlIG9mIGRyYWdnaW5nKS5cbiAgXHRcdGRlbGV0ZSB0aGlzLl9vbGRMYXRMbmc7XG4gIFx0XHR0aGlzLl9tYXJrZXJcbiAgXHRcdCAgICAuZmlyZSgnbW92ZWVuZCcpXG4gIFx0XHQgICAgLmZpcmUoJ2RyYWdlbmQnLCBlKTtcbiAgXHR9XG4gIH0pO1xuXG4gIC8qXHJcbiAgICogQGNsYXNzIE1hcmtlclxyXG4gICAqIEBpbmhlcml0cyBJbnRlcmFjdGl2ZSBsYXllclxyXG4gICAqIEBha2EgTC5NYXJrZXJcclxuICAgKiBMLk1hcmtlciBpcyB1c2VkIHRvIGRpc3BsYXkgY2xpY2thYmxlL2RyYWdnYWJsZSBpY29ucyBvbiB0aGUgbWFwLiBFeHRlbmRzIGBMYXllcmAuXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiBMLm1hcmtlcihbNTAuNSwgMzAuNV0pLmFkZFRvKG1hcCk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcblxyXG4gIHZhciBNYXJrZXIgPSBMYXllci5leHRlbmQoe1xyXG5cclxuICBcdC8vIEBzZWN0aW9uXHJcbiAgXHQvLyBAYWthIE1hcmtlciBvcHRpb25zXHJcbiAgXHRvcHRpb25zOiB7XHJcbiAgXHRcdC8vIEBvcHRpb24gaWNvbjogSWNvbiA9ICpcclxuICBcdFx0Ly8gSWNvbiBpbnN0YW5jZSB0byB1c2UgZm9yIHJlbmRlcmluZyB0aGUgbWFya2VyLlxyXG4gIFx0XHQvLyBTZWUgW0ljb24gZG9jdW1lbnRhdGlvbl0oI0wuSWNvbikgZm9yIGRldGFpbHMgb24gaG93IHRvIGN1c3RvbWl6ZSB0aGUgbWFya2VyIGljb24uXHJcbiAgXHRcdC8vIElmIG5vdCBzcGVjaWZpZWQsIGEgY29tbW9uIGluc3RhbmNlIG9mIGBMLkljb24uRGVmYXVsdGAgaXMgdXNlZC5cclxuICBcdFx0aWNvbjogbmV3IEljb25EZWZhdWx0KCksXHJcblxyXG4gIFx0XHQvLyBPcHRpb24gaW5oZXJpdGVkIGZyb20gXCJJbnRlcmFjdGl2ZSBsYXllclwiIGFic3RyYWN0IGNsYXNzXHJcbiAgXHRcdGludGVyYWN0aXZlOiB0cnVlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBrZXlib2FyZDogQm9vbGVhbiA9IHRydWVcclxuICBcdFx0Ly8gV2hldGhlciB0aGUgbWFya2VyIGNhbiBiZSB0YWJiZWQgdG8gd2l0aCBhIGtleWJvYXJkIGFuZCBjbGlja2VkIGJ5IHByZXNzaW5nIGVudGVyLlxyXG4gIFx0XHRrZXlib2FyZDogdHJ1ZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gdGl0bGU6IFN0cmluZyA9ICcnXHJcbiAgXHRcdC8vIFRleHQgZm9yIHRoZSBicm93c2VyIHRvb2x0aXAgdGhhdCBhcHBlYXIgb24gbWFya2VyIGhvdmVyIChubyB0b29sdGlwIGJ5IGRlZmF1bHQpLlxyXG4gIFx0XHQvLyBbVXNlZnVsIGZvciBhY2Nlc3NpYmlsaXR5XShodHRwczovL2xlYWZsZXRqcy5jb20vZXhhbXBsZXMvYWNjZXNzaWJpbGl0eS8jbWFya2Vycy1tdXN0LWJlLWxhYmVsbGVkKS5cclxuICBcdFx0dGl0bGU6ICcnLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBhbHQ6IFN0cmluZyA9ICdNYXJrZXInXHJcbiAgXHRcdC8vIFRleHQgZm9yIHRoZSBgYWx0YCBhdHRyaWJ1dGUgb2YgdGhlIGljb24gaW1hZ2UuXHJcbiAgXHRcdC8vIFtVc2VmdWwgZm9yIGFjY2Vzc2liaWxpdHldKGh0dHBzOi8vbGVhZmxldGpzLmNvbS9leGFtcGxlcy9hY2Nlc3NpYmlsaXR5LyNtYXJrZXJzLW11c3QtYmUtbGFiZWxsZWQpLlxyXG4gIFx0XHRhbHQ6ICdNYXJrZXInLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiB6SW5kZXhPZmZzZXQ6IE51bWJlciA9IDBcclxuICBcdFx0Ly8gQnkgZGVmYXVsdCwgbWFya2VyIGltYWdlcyB6SW5kZXggaXMgc2V0IGF1dG9tYXRpY2FsbHkgYmFzZWQgb24gaXRzIGxhdGl0dWRlLiBVc2UgdGhpcyBvcHRpb24gaWYgeW91IHdhbnQgdG8gcHV0IHRoZSBtYXJrZXIgb24gdG9wIG9mIGFsbCBvdGhlcnMgKG9yIGJlbG93KSwgc3BlY2lmeWluZyBhIGhpZ2ggdmFsdWUgbGlrZSBgMTAwMGAgKG9yIGhpZ2ggbmVnYXRpdmUgdmFsdWUsIHJlc3BlY3RpdmVseSkuXHJcbiAgXHRcdHpJbmRleE9mZnNldDogMCxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gb3BhY2l0eTogTnVtYmVyID0gMS4wXHJcbiAgXHRcdC8vIFRoZSBvcGFjaXR5IG9mIHRoZSBtYXJrZXIuXHJcbiAgXHRcdG9wYWNpdHk6IDEsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHJpc2VPbkhvdmVyOiBCb29sZWFuID0gZmFsc2VcclxuICBcdFx0Ly8gSWYgYHRydWVgLCB0aGUgbWFya2VyIHdpbGwgZ2V0IG9uIHRvcCBvZiBvdGhlcnMgd2hlbiB5b3UgaG92ZXIgdGhlIG1vdXNlIG92ZXIgaXQuXHJcbiAgXHRcdHJpc2VPbkhvdmVyOiBmYWxzZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gcmlzZU9mZnNldDogTnVtYmVyID0gMjUwXHJcbiAgXHRcdC8vIFRoZSB6LWluZGV4IG9mZnNldCB1c2VkIGZvciB0aGUgYHJpc2VPbkhvdmVyYCBmZWF0dXJlLlxyXG4gIFx0XHRyaXNlT2Zmc2V0OiAyNTAsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHBhbmU6IFN0cmluZyA9ICdtYXJrZXJQYW5lJ1xyXG4gIFx0XHQvLyBgTWFwIHBhbmVgIHdoZXJlIHRoZSBtYXJrZXJzIGljb24gd2lsbCBiZSBhZGRlZC5cclxuICBcdFx0cGFuZTogJ21hcmtlclBhbmUnLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBzaGFkb3dQYW5lOiBTdHJpbmcgPSAnc2hhZG93UGFuZSdcclxuICBcdFx0Ly8gYE1hcCBwYW5lYCB3aGVyZSB0aGUgbWFya2VycyBzaGFkb3cgd2lsbCBiZSBhZGRlZC5cclxuICBcdFx0c2hhZG93UGFuZTogJ3NoYWRvd1BhbmUnLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBidWJibGluZ01vdXNlRXZlbnRzOiBCb29sZWFuID0gZmFsc2VcclxuICBcdFx0Ly8gV2hlbiBgdHJ1ZWAsIGEgbW91c2UgZXZlbnQgb24gdGhpcyBtYXJrZXIgd2lsbCB0cmlnZ2VyIHRoZSBzYW1lIGV2ZW50IG9uIHRoZSBtYXBcclxuICBcdFx0Ly8gKHVubGVzcyBbYEwuRG9tRXZlbnQuc3RvcFByb3BhZ2F0aW9uYF0oI2RvbWV2ZW50LXN0b3Bwcm9wYWdhdGlvbikgaXMgdXNlZCkuXHJcbiAgXHRcdGJ1YmJsaW5nTW91c2VFdmVudHM6IGZhbHNlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBhdXRvUGFuT25Gb2N1czogQm9vbGVhbiA9IHRydWVcclxuICBcdFx0Ly8gV2hlbiBgdHJ1ZWAsIHRoZSBtYXAgd2lsbCBwYW4gd2hlbmV2ZXIgdGhlIG1hcmtlciBpcyBmb2N1c2VkICh2aWFcclxuICBcdFx0Ly8gZS5nLiBwcmVzc2luZyBgdGFiYCBvbiB0aGUga2V5Ym9hcmQpIHRvIGVuc3VyZSB0aGUgbWFya2VyIGlzXHJcbiAgXHRcdC8vIHZpc2libGUgd2l0aGluIHRoZSBtYXAncyBib3VuZHNcclxuICBcdFx0YXV0b1Bhbk9uRm9jdXM6IHRydWUsXHJcblxyXG4gIFx0XHQvLyBAc2VjdGlvbiBEcmFnZ2FibGUgbWFya2VyIG9wdGlvbnNcclxuICBcdFx0Ly8gQG9wdGlvbiBkcmFnZ2FibGU6IEJvb2xlYW4gPSBmYWxzZVxyXG4gIFx0XHQvLyBXaGV0aGVyIHRoZSBtYXJrZXIgaXMgZHJhZ2dhYmxlIHdpdGggbW91c2UvdG91Y2ggb3Igbm90LlxyXG4gIFx0XHRkcmFnZ2FibGU6IGZhbHNlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBhdXRvUGFuOiBCb29sZWFuID0gZmFsc2VcclxuICBcdFx0Ly8gV2hldGhlciB0byBwYW4gdGhlIG1hcCB3aGVuIGRyYWdnaW5nIHRoaXMgbWFya2VyIG5lYXIgaXRzIGVkZ2Ugb3Igbm90LlxyXG4gIFx0XHRhdXRvUGFuOiBmYWxzZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gYXV0b1BhblBhZGRpbmc6IFBvaW50ID0gUG9pbnQoNTAsIDUwKVxyXG4gIFx0XHQvLyBEaXN0YW5jZSAoaW4gcGl4ZWxzIHRvIHRoZSBsZWZ0L3JpZ2h0IGFuZCB0byB0aGUgdG9wL2JvdHRvbSkgb2YgdGhlXHJcbiAgXHRcdC8vIG1hcCBlZGdlIHRvIHN0YXJ0IHBhbm5pbmcgdGhlIG1hcC5cclxuICBcdFx0YXV0b1BhblBhZGRpbmc6IFs1MCwgNTBdLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBhdXRvUGFuU3BlZWQ6IE51bWJlciA9IDEwXHJcbiAgXHRcdC8vIE51bWJlciBvZiBwaXhlbHMgdGhlIG1hcCBzaG91bGQgcGFuIGJ5LlxyXG4gIFx0XHRhdXRvUGFuU3BlZWQ6IDEwXHJcbiAgXHR9LFxyXG5cclxuICBcdC8qIEBzZWN0aW9uXHJcbiAgXHQgKlxyXG4gIFx0ICogSW4gYWRkaXRpb24gdG8gW3NoYXJlZCBsYXllciBtZXRob2RzXSgjTGF5ZXIpIGxpa2UgYGFkZFRvKClgIGFuZCBgcmVtb3ZlKClgIGFuZCBbcG9wdXAgbWV0aG9kc10oI1BvcHVwKSBsaWtlIGJpbmRQb3B1cCgpIHlvdSBjYW4gYWxzbyB1c2UgdGhlIGZvbGxvd2luZyBtZXRob2RzOlxyXG4gIFx0ICovXHJcblxyXG4gIFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKGxhdGxuZywgb3B0aW9ucykge1xyXG4gIFx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xyXG4gIFx0XHR0aGlzLl9sYXRsbmcgPSB0b0xhdExuZyhsYXRsbmcpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRvbkFkZDogZnVuY3Rpb24gKG1hcCkge1xyXG4gIFx0XHR0aGlzLl96b29tQW5pbWF0ZWQgPSB0aGlzLl96b29tQW5pbWF0ZWQgJiYgbWFwLm9wdGlvbnMubWFya2VyWm9vbUFuaW1hdGlvbjtcclxuXHJcbiAgXHRcdGlmICh0aGlzLl96b29tQW5pbWF0ZWQpIHtcclxuICBcdFx0XHRtYXAub24oJ3pvb21hbmltJywgdGhpcy5fYW5pbWF0ZVpvb20sIHRoaXMpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR0aGlzLl9pbml0SWNvbigpO1xyXG4gIFx0XHR0aGlzLnVwZGF0ZSgpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRvblJlbW92ZTogZnVuY3Rpb24gKG1hcCkge1xyXG4gIFx0XHRpZiAodGhpcy5kcmFnZ2luZyAmJiB0aGlzLmRyYWdnaW5nLmVuYWJsZWQoKSkge1xyXG4gIFx0XHRcdHRoaXMub3B0aW9ucy5kcmFnZ2FibGUgPSB0cnVlO1xyXG4gIFx0XHRcdHRoaXMuZHJhZ2dpbmcucmVtb3ZlSG9va3MoKTtcclxuICBcdFx0fVxyXG4gIFx0XHRkZWxldGUgdGhpcy5kcmFnZ2luZztcclxuXHJcbiAgXHRcdGlmICh0aGlzLl96b29tQW5pbWF0ZWQpIHtcclxuICBcdFx0XHRtYXAub2ZmKCd6b29tYW5pbScsIHRoaXMuX2FuaW1hdGVab29tLCB0aGlzKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5fcmVtb3ZlSWNvbigpO1xyXG4gIFx0XHR0aGlzLl9yZW1vdmVTaGFkb3coKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Z2V0RXZlbnRzOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB7XHJcbiAgXHRcdFx0em9vbTogdGhpcy51cGRhdGUsXHJcbiAgXHRcdFx0dmlld3Jlc2V0OiB0aGlzLnVwZGF0ZVxyXG4gIFx0XHR9O1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldExhdExuZzogTGF0TG5nXHJcbiAgXHQvLyBSZXR1cm5zIHRoZSBjdXJyZW50IGdlb2dyYXBoaWNhbCBwb3NpdGlvbiBvZiB0aGUgbWFya2VyLlxyXG4gIFx0Z2V0TGF0TG5nOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLl9sYXRsbmc7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2V0TGF0TG5nKGxhdGxuZzogTGF0TG5nKTogdGhpc1xyXG4gIFx0Ly8gQ2hhbmdlcyB0aGUgbWFya2VyIHBvc2l0aW9uIHRvIHRoZSBnaXZlbiBwb2ludC5cclxuICBcdHNldExhdExuZzogZnVuY3Rpb24gKGxhdGxuZykge1xyXG4gIFx0XHR2YXIgb2xkTGF0TG5nID0gdGhpcy5fbGF0bG5nO1xyXG4gIFx0XHR0aGlzLl9sYXRsbmcgPSB0b0xhdExuZyhsYXRsbmcpO1xyXG4gIFx0XHR0aGlzLnVwZGF0ZSgpO1xyXG5cclxuICBcdFx0Ly8gQGV2ZW50IG1vdmU6IEV2ZW50XHJcbiAgXHRcdC8vIEZpcmVkIHdoZW4gdGhlIG1hcmtlciBpcyBtb3ZlZCB2aWEgW2BzZXRMYXRMbmdgXSgjbWFya2VyLXNldGxhdGxuZykgb3IgYnkgW2RyYWdnaW5nXSgjbWFya2VyLWRyYWdnaW5nKS4gT2xkIGFuZCBuZXcgY29vcmRpbmF0ZXMgYXJlIGluY2x1ZGVkIGluIGV2ZW50IGFyZ3VtZW50cyBhcyBgb2xkTGF0TG5nYCwgYGxhdGxuZ2AuXHJcbiAgXHRcdHJldHVybiB0aGlzLmZpcmUoJ21vdmUnLCB7b2xkTGF0TG5nOiBvbGRMYXRMbmcsIGxhdGxuZzogdGhpcy5fbGF0bG5nfSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2V0WkluZGV4T2Zmc2V0KG9mZnNldDogTnVtYmVyKTogdGhpc1xyXG4gIFx0Ly8gQ2hhbmdlcyB0aGUgW3pJbmRleCBvZmZzZXRdKCNtYXJrZXItemluZGV4b2Zmc2V0KSBvZiB0aGUgbWFya2VyLlxyXG4gIFx0c2V0WkluZGV4T2Zmc2V0OiBmdW5jdGlvbiAob2Zmc2V0KSB7XHJcbiAgXHRcdHRoaXMub3B0aW9ucy56SW5kZXhPZmZzZXQgPSBvZmZzZXQ7XHJcbiAgXHRcdHJldHVybiB0aGlzLnVwZGF0ZSgpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldEljb246IEljb25cclxuICBcdC8vIFJldHVybnMgdGhlIGN1cnJlbnQgaWNvbiB1c2VkIGJ5IHRoZSBtYXJrZXJcclxuICBcdGdldEljb246IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMub3B0aW9ucy5pY29uO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNldEljb24oaWNvbjogSWNvbik6IHRoaXNcclxuICBcdC8vIENoYW5nZXMgdGhlIG1hcmtlciBpY29uLlxyXG4gIFx0c2V0SWNvbjogZnVuY3Rpb24gKGljb24pIHtcclxuXHJcbiAgXHRcdHRoaXMub3B0aW9ucy5pY29uID0gaWNvbjtcclxuXHJcbiAgXHRcdGlmICh0aGlzLl9tYXApIHtcclxuICBcdFx0XHR0aGlzLl9pbml0SWNvbigpO1xyXG4gIFx0XHRcdHRoaXMudXBkYXRlKCk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmICh0aGlzLl9wb3B1cCkge1xyXG4gIFx0XHRcdHRoaXMuYmluZFBvcHVwKHRoaXMuX3BvcHVwLCB0aGlzLl9wb3B1cC5vcHRpb25zKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdGdldEVsZW1lbnQ6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuX2ljb247XHJcbiAgXHR9LFxyXG5cclxuICBcdHVwZGF0ZTogZnVuY3Rpb24gKCkge1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX2ljb24gJiYgdGhpcy5fbWFwKSB7XHJcbiAgXHRcdFx0dmFyIHBvcyA9IHRoaXMuX21hcC5sYXRMbmdUb0xheWVyUG9pbnQodGhpcy5fbGF0bG5nKS5yb3VuZCgpO1xyXG4gIFx0XHRcdHRoaXMuX3NldFBvcyhwb3MpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0X2luaXRJY29uOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHZhciBvcHRpb25zID0gdGhpcy5vcHRpb25zLFxyXG4gIFx0XHQgICAgY2xhc3NUb0FkZCA9ICdsZWFmbGV0LXpvb20tJyArICh0aGlzLl96b29tQW5pbWF0ZWQgPyAnYW5pbWF0ZWQnIDogJ2hpZGUnKTtcclxuXHJcbiAgXHRcdHZhciBpY29uID0gb3B0aW9ucy5pY29uLmNyZWF0ZUljb24odGhpcy5faWNvbiksXHJcbiAgXHRcdCAgICBhZGRJY29uID0gZmFsc2U7XHJcblxyXG4gIFx0XHQvLyBpZiB3ZSdyZSBub3QgcmV1c2luZyB0aGUgaWNvbiwgcmVtb3ZlIHRoZSBvbGQgb25lIGFuZCBpbml0IG5ldyBvbmVcclxuICBcdFx0aWYgKGljb24gIT09IHRoaXMuX2ljb24pIHtcclxuICBcdFx0XHRpZiAodGhpcy5faWNvbikge1xyXG4gIFx0XHRcdFx0dGhpcy5fcmVtb3ZlSWNvbigpO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0XHRhZGRJY29uID0gdHJ1ZTtcclxuXHJcbiAgXHRcdFx0aWYgKG9wdGlvbnMudGl0bGUpIHtcclxuICBcdFx0XHRcdGljb24udGl0bGUgPSBvcHRpb25zLnRpdGxlO1xyXG4gIFx0XHRcdH1cclxuXHJcbiAgXHRcdFx0aWYgKGljb24udGFnTmFtZSA9PT0gJ0lNRycpIHtcclxuICBcdFx0XHRcdGljb24uYWx0ID0gb3B0aW9ucy5hbHQgfHwgJyc7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRhZGRDbGFzcyhpY29uLCBjbGFzc1RvQWRkKTtcclxuXHJcbiAgXHRcdGlmIChvcHRpb25zLmtleWJvYXJkKSB7XHJcbiAgXHRcdFx0aWNvbi50YWJJbmRleCA9ICcwJztcclxuICBcdFx0XHRpY29uLnNldEF0dHJpYnV0ZSgncm9sZScsICdidXR0b24nKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5faWNvbiA9IGljb247XHJcblxyXG4gIFx0XHRpZiAob3B0aW9ucy5yaXNlT25Ib3Zlcikge1xyXG4gIFx0XHRcdHRoaXMub24oe1xyXG4gIFx0XHRcdFx0bW91c2VvdmVyOiB0aGlzLl9icmluZ1RvRnJvbnQsXHJcbiAgXHRcdFx0XHRtb3VzZW91dDogdGhpcy5fcmVzZXRaSW5kZXhcclxuICBcdFx0XHR9KTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5hdXRvUGFuT25Gb2N1cykge1xyXG4gIFx0XHRcdG9uKGljb24sICdmb2N1cycsIHRoaXMuX3Bhbk9uRm9jdXMsIHRoaXMpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgbmV3U2hhZG93ID0gb3B0aW9ucy5pY29uLmNyZWF0ZVNoYWRvdyh0aGlzLl9zaGFkb3cpLFxyXG4gIFx0XHQgICAgYWRkU2hhZG93ID0gZmFsc2U7XHJcblxyXG4gIFx0XHRpZiAobmV3U2hhZG93ICE9PSB0aGlzLl9zaGFkb3cpIHtcclxuICBcdFx0XHR0aGlzLl9yZW1vdmVTaGFkb3coKTtcclxuICBcdFx0XHRhZGRTaGFkb3cgPSB0cnVlO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAobmV3U2hhZG93KSB7XHJcbiAgXHRcdFx0YWRkQ2xhc3MobmV3U2hhZG93LCBjbGFzc1RvQWRkKTtcclxuICBcdFx0XHRuZXdTaGFkb3cuYWx0ID0gJyc7XHJcbiAgXHRcdH1cclxuICBcdFx0dGhpcy5fc2hhZG93ID0gbmV3U2hhZG93O1xyXG5cclxuXHJcbiAgXHRcdGlmIChvcHRpb25zLm9wYWNpdHkgPCAxKSB7XHJcbiAgXHRcdFx0dGhpcy5fdXBkYXRlT3BhY2l0eSgpO1xyXG4gIFx0XHR9XHJcblxyXG5cclxuICBcdFx0aWYgKGFkZEljb24pIHtcclxuICBcdFx0XHR0aGlzLmdldFBhbmUoKS5hcHBlbmRDaGlsZCh0aGlzLl9pY29uKTtcclxuICBcdFx0fVxyXG4gIFx0XHR0aGlzLl9pbml0SW50ZXJhY3Rpb24oKTtcclxuICBcdFx0aWYgKG5ld1NoYWRvdyAmJiBhZGRTaGFkb3cpIHtcclxuICBcdFx0XHR0aGlzLmdldFBhbmUob3B0aW9ucy5zaGFkb3dQYW5lKS5hcHBlbmRDaGlsZCh0aGlzLl9zaGFkb3cpO1xyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdF9yZW1vdmVJY29uOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMucmlzZU9uSG92ZXIpIHtcclxuICBcdFx0XHR0aGlzLm9mZih7XHJcbiAgXHRcdFx0XHRtb3VzZW92ZXI6IHRoaXMuX2JyaW5nVG9Gcm9udCxcclxuICBcdFx0XHRcdG1vdXNlb3V0OiB0aGlzLl9yZXNldFpJbmRleFxyXG4gIFx0XHRcdH0pO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAodGhpcy5vcHRpb25zLmF1dG9QYW5PbkZvY3VzKSB7XHJcbiAgXHRcdFx0b2ZmKHRoaXMuX2ljb24sICdmb2N1cycsIHRoaXMuX3Bhbk9uRm9jdXMsIHRoaXMpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZW1vdmUodGhpcy5faWNvbik7XHJcbiAgXHRcdHRoaXMucmVtb3ZlSW50ZXJhY3RpdmVUYXJnZXQodGhpcy5faWNvbik7XHJcblxyXG4gIFx0XHR0aGlzLl9pY29uID0gbnVsbDtcclxuICBcdH0sXHJcblxyXG4gIFx0X3JlbW92ZVNoYWRvdzogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRpZiAodGhpcy5fc2hhZG93KSB7XHJcbiAgXHRcdFx0cmVtb3ZlKHRoaXMuX3NoYWRvdyk7XHJcbiAgXHRcdH1cclxuICBcdFx0dGhpcy5fc2hhZG93ID0gbnVsbDtcclxuICBcdH0sXHJcblxyXG4gIFx0X3NldFBvczogZnVuY3Rpb24gKHBvcykge1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX2ljb24pIHtcclxuICBcdFx0XHRzZXRQb3NpdGlvbih0aGlzLl9pY29uLCBwb3MpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fc2hhZG93KSB7XHJcbiAgXHRcdFx0c2V0UG9zaXRpb24odGhpcy5fc2hhZG93LCBwb3MpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR0aGlzLl96SW5kZXggPSBwb3MueSArIHRoaXMub3B0aW9ucy56SW5kZXhPZmZzZXQ7XHJcblxyXG4gIFx0XHR0aGlzLl9yZXNldFpJbmRleCgpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfdXBkYXRlWkluZGV4OiBmdW5jdGlvbiAob2Zmc2V0KSB7XHJcbiAgXHRcdGlmICh0aGlzLl9pY29uKSB7XHJcbiAgXHRcdFx0dGhpcy5faWNvbi5zdHlsZS56SW5kZXggPSB0aGlzLl96SW5kZXggKyBvZmZzZXQ7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0X2FuaW1hdGVab29tOiBmdW5jdGlvbiAob3B0KSB7XHJcbiAgXHRcdHZhciBwb3MgPSB0aGlzLl9tYXAuX2xhdExuZ1RvTmV3TGF5ZXJQb2ludCh0aGlzLl9sYXRsbmcsIG9wdC56b29tLCBvcHQuY2VudGVyKS5yb3VuZCgpO1xyXG5cclxuICBcdFx0dGhpcy5fc2V0UG9zKHBvcyk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9pbml0SW50ZXJhY3Rpb246IGZ1bmN0aW9uICgpIHtcclxuXHJcbiAgXHRcdGlmICghdGhpcy5vcHRpb25zLmludGVyYWN0aXZlKSB7IHJldHVybjsgfVxyXG5cclxuICBcdFx0YWRkQ2xhc3ModGhpcy5faWNvbiwgJ2xlYWZsZXQtaW50ZXJhY3RpdmUnKTtcclxuXHJcbiAgXHRcdHRoaXMuYWRkSW50ZXJhY3RpdmVUYXJnZXQodGhpcy5faWNvbik7XHJcblxyXG4gIFx0XHRpZiAoTWFya2VyRHJhZykge1xyXG4gIFx0XHRcdHZhciBkcmFnZ2FibGUgPSB0aGlzLm9wdGlvbnMuZHJhZ2dhYmxlO1xyXG4gIFx0XHRcdGlmICh0aGlzLmRyYWdnaW5nKSB7XHJcbiAgXHRcdFx0XHRkcmFnZ2FibGUgPSB0aGlzLmRyYWdnaW5nLmVuYWJsZWQoKTtcclxuICBcdFx0XHRcdHRoaXMuZHJhZ2dpbmcuZGlzYWJsZSgpO1xyXG4gIFx0XHRcdH1cclxuXHJcbiAgXHRcdFx0dGhpcy5kcmFnZ2luZyA9IG5ldyBNYXJrZXJEcmFnKHRoaXMpO1xyXG5cclxuICBcdFx0XHRpZiAoZHJhZ2dhYmxlKSB7XHJcbiAgXHRcdFx0XHR0aGlzLmRyYWdnaW5nLmVuYWJsZSgpO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNldE9wYWNpdHkob3BhY2l0eTogTnVtYmVyKTogdGhpc1xyXG4gIFx0Ly8gQ2hhbmdlcyB0aGUgb3BhY2l0eSBvZiB0aGUgbWFya2VyLlxyXG4gIFx0c2V0T3BhY2l0eTogZnVuY3Rpb24gKG9wYWNpdHkpIHtcclxuICBcdFx0dGhpcy5vcHRpb25zLm9wYWNpdHkgPSBvcGFjaXR5O1xyXG4gIFx0XHRpZiAodGhpcy5fbWFwKSB7XHJcbiAgXHRcdFx0dGhpcy5fdXBkYXRlT3BhY2l0eSgpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0X3VwZGF0ZU9wYWNpdHk6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dmFyIG9wYWNpdHkgPSB0aGlzLm9wdGlvbnMub3BhY2l0eTtcclxuXHJcbiAgXHRcdGlmICh0aGlzLl9pY29uKSB7XHJcbiAgXHRcdFx0c2V0T3BhY2l0eSh0aGlzLl9pY29uLCBvcGFjaXR5KTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0aWYgKHRoaXMuX3NoYWRvdykge1xyXG4gIFx0XHRcdHNldE9wYWNpdHkodGhpcy5fc2hhZG93LCBvcGFjaXR5KTtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHRfYnJpbmdUb0Zyb250OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHRoaXMuX3VwZGF0ZVpJbmRleCh0aGlzLm9wdGlvbnMucmlzZU9mZnNldCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9yZXNldFpJbmRleDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR0aGlzLl91cGRhdGVaSW5kZXgoMCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9wYW5PbkZvY3VzOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHZhciBtYXAgPSB0aGlzLl9tYXA7XHJcbiAgXHRcdGlmICghbWFwKSB7IHJldHVybjsgfVxyXG5cclxuICBcdFx0dmFyIGljb25PcHRzID0gdGhpcy5vcHRpb25zLmljb24ub3B0aW9ucztcclxuICBcdFx0dmFyIHNpemUgPSBpY29uT3B0cy5pY29uU2l6ZSA/IHRvUG9pbnQoaWNvbk9wdHMuaWNvblNpemUpIDogdG9Qb2ludCgwLCAwKTtcclxuICBcdFx0dmFyIGFuY2hvciA9IGljb25PcHRzLmljb25BbmNob3IgPyB0b1BvaW50KGljb25PcHRzLmljb25BbmNob3IpIDogdG9Qb2ludCgwLCAwKTtcclxuXHJcbiAgXHRcdG1hcC5wYW5JbnNpZGUodGhpcy5fbGF0bG5nLCB7XHJcbiAgXHRcdFx0cGFkZGluZ1RvcExlZnQ6IGFuY2hvcixcclxuICBcdFx0XHRwYWRkaW5nQm90dG9tUmlnaHQ6IHNpemUuc3VidHJhY3QoYW5jaG9yKVxyXG4gIFx0XHR9KTtcclxuICBcdH0sXHJcblxyXG4gIFx0X2dldFBvcHVwQW5jaG9yOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLm9wdGlvbnMuaWNvbi5vcHRpb25zLnBvcHVwQW5jaG9yO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfZ2V0VG9vbHRpcEFuY2hvcjogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmljb24ub3B0aW9ucy50b29sdGlwQW5jaG9yO1xyXG4gIFx0fVxyXG4gIH0pO1xyXG5cclxuXHJcbiAgLy8gZmFjdG9yeSBMLm1hcmtlcihsYXRsbmc6IExhdExuZywgb3B0aW9ucz8gOiBNYXJrZXIgb3B0aW9ucylcclxuXHJcbiAgLy8gQGZhY3RvcnkgTC5tYXJrZXIobGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/IDogTWFya2VyIG9wdGlvbnMpXHJcbiAgLy8gSW5zdGFudGlhdGVzIGEgTWFya2VyIG9iamVjdCBnaXZlbiBhIGdlb2dyYXBoaWNhbCBwb2ludCBhbmQgb3B0aW9uYWxseSBhbiBvcHRpb25zIG9iamVjdC5cclxuICBmdW5jdGlvbiBtYXJrZXIobGF0bG5nLCBvcHRpb25zKSB7XHJcbiAgXHRyZXR1cm4gbmV3IE1hcmtlcihsYXRsbmcsIG9wdGlvbnMpO1xyXG4gIH1cblxuICAvKlxuICAgKiBAY2xhc3MgUGF0aFxuICAgKiBAYWthIEwuUGF0aFxuICAgKiBAaW5oZXJpdHMgSW50ZXJhY3RpdmUgbGF5ZXJcbiAgICpcbiAgICogQW4gYWJzdHJhY3QgY2xhc3MgdGhhdCBjb250YWlucyBvcHRpb25zIGFuZCBjb25zdGFudHMgc2hhcmVkIGJldHdlZW4gdmVjdG9yXG4gICAqIG92ZXJsYXlzIChQb2x5Z29uLCBQb2x5bGluZSwgQ2lyY2xlKS4gRG8gbm90IHVzZSBpdCBkaXJlY3RseS4gRXh0ZW5kcyBgTGF5ZXJgLlxuICAgKi9cblxuICB2YXIgUGF0aCA9IExheWVyLmV4dGVuZCh7XG5cbiAgXHQvLyBAc2VjdGlvblxuICBcdC8vIEBha2EgUGF0aCBvcHRpb25zXG4gIFx0b3B0aW9uczoge1xuICBcdFx0Ly8gQG9wdGlvbiBzdHJva2U6IEJvb2xlYW4gPSB0cnVlXG4gIFx0XHQvLyBXaGV0aGVyIHRvIGRyYXcgc3Ryb2tlIGFsb25nIHRoZSBwYXRoLiBTZXQgaXQgdG8gYGZhbHNlYCB0byBkaXNhYmxlIGJvcmRlcnMgb24gcG9seWdvbnMgb3IgY2lyY2xlcy5cbiAgXHRcdHN0cm9rZTogdHJ1ZSxcblxuICBcdFx0Ly8gQG9wdGlvbiBjb2xvcjogU3RyaW5nID0gJyMzMzg4ZmYnXG4gIFx0XHQvLyBTdHJva2UgY29sb3JcbiAgXHRcdGNvbG9yOiAnIzMzODhmZicsXG5cbiAgXHRcdC8vIEBvcHRpb24gd2VpZ2h0OiBOdW1iZXIgPSAzXG4gIFx0XHQvLyBTdHJva2Ugd2lkdGggaW4gcGl4ZWxzXG4gIFx0XHR3ZWlnaHQ6IDMsXG5cbiAgXHRcdC8vIEBvcHRpb24gb3BhY2l0eTogTnVtYmVyID0gMS4wXG4gIFx0XHQvLyBTdHJva2Ugb3BhY2l0eVxuICBcdFx0b3BhY2l0eTogMSxcblxuICBcdFx0Ly8gQG9wdGlvbiBsaW5lQ2FwOiBTdHJpbmc9ICdyb3VuZCdcbiAgXHRcdC8vIEEgc3RyaW5nIHRoYXQgZGVmaW5lcyBbc2hhcGUgdG8gYmUgdXNlZCBhdCB0aGUgZW5kXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9TVkcvQXR0cmlidXRlL3N0cm9rZS1saW5lY2FwKSBvZiB0aGUgc3Ryb2tlLlxuICBcdFx0bGluZUNhcDogJ3JvdW5kJyxcblxuICBcdFx0Ly8gQG9wdGlvbiBsaW5lSm9pbjogU3RyaW5nID0gJ3JvdW5kJ1xuICBcdFx0Ly8gQSBzdHJpbmcgdGhhdCBkZWZpbmVzIFtzaGFwZSB0byBiZSB1c2VkIGF0IHRoZSBjb3JuZXJzXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9TVkcvQXR0cmlidXRlL3N0cm9rZS1saW5lam9pbikgb2YgdGhlIHN0cm9rZS5cbiAgXHRcdGxpbmVKb2luOiAncm91bmQnLFxuXG4gIFx0XHQvLyBAb3B0aW9uIGRhc2hBcnJheTogU3RyaW5nID0gbnVsbFxuICBcdFx0Ly8gQSBzdHJpbmcgdGhhdCBkZWZpbmVzIHRoZSBzdHJva2UgW2Rhc2ggcGF0dGVybl0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvU1ZHL0F0dHJpYnV0ZS9zdHJva2UtZGFzaGFycmF5KS4gRG9lc24ndCB3b3JrIG9uIGBDYW52YXNgLXBvd2VyZWQgbGF5ZXJzIGluIFtzb21lIG9sZCBicm93c2Vyc10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQVBJL0NhbnZhc1JlbmRlcmluZ0NvbnRleHQyRC9zZXRMaW5lRGFzaCNCcm93c2VyX2NvbXBhdGliaWxpdHkpLlxuICBcdFx0ZGFzaEFycmF5OiBudWxsLFxuXG4gIFx0XHQvLyBAb3B0aW9uIGRhc2hPZmZzZXQ6IFN0cmluZyA9IG51bGxcbiAgXHRcdC8vIEEgc3RyaW5nIHRoYXQgZGVmaW5lcyB0aGUgW2Rpc3RhbmNlIGludG8gdGhlIGRhc2ggcGF0dGVybiB0byBzdGFydCB0aGUgZGFzaF0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvU1ZHL0F0dHJpYnV0ZS9zdHJva2UtZGFzaG9mZnNldCkuIERvZXNuJ3Qgd29yayBvbiBgQ2FudmFzYC1wb3dlcmVkIGxheWVycyBpbiBbc29tZSBvbGQgYnJvd3NlcnNdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0FQSS9DYW52YXNSZW5kZXJpbmdDb250ZXh0MkQvc2V0TGluZURhc2gjQnJvd3Nlcl9jb21wYXRpYmlsaXR5KS5cbiAgXHRcdGRhc2hPZmZzZXQ6IG51bGwsXG5cbiAgXHRcdC8vIEBvcHRpb24gZmlsbDogQm9vbGVhbiA9IGRlcGVuZHNcbiAgXHRcdC8vIFdoZXRoZXIgdG8gZmlsbCB0aGUgcGF0aCB3aXRoIGNvbG9yLiBTZXQgaXQgdG8gYGZhbHNlYCB0byBkaXNhYmxlIGZpbGxpbmcgb24gcG9seWdvbnMgb3IgY2lyY2xlcy5cbiAgXHRcdGZpbGw6IGZhbHNlLFxuXG4gIFx0XHQvLyBAb3B0aW9uIGZpbGxDb2xvcjogU3RyaW5nID0gKlxuICBcdFx0Ly8gRmlsbCBjb2xvci4gRGVmYXVsdHMgdG8gdGhlIHZhbHVlIG9mIHRoZSBbYGNvbG9yYF0oI3BhdGgtY29sb3IpIG9wdGlvblxuICBcdFx0ZmlsbENvbG9yOiBudWxsLFxuXG4gIFx0XHQvLyBAb3B0aW9uIGZpbGxPcGFjaXR5OiBOdW1iZXIgPSAwLjJcbiAgXHRcdC8vIEZpbGwgb3BhY2l0eS5cbiAgXHRcdGZpbGxPcGFjaXR5OiAwLjIsXG5cbiAgXHRcdC8vIEBvcHRpb24gZmlsbFJ1bGU6IFN0cmluZyA9ICdldmVub2RkJ1xuICBcdFx0Ly8gQSBzdHJpbmcgdGhhdCBkZWZpbmVzIFtob3cgdGhlIGluc2lkZSBvZiBhIHNoYXBlXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9TVkcvQXR0cmlidXRlL2ZpbGwtcnVsZSkgaXMgZGV0ZXJtaW5lZC5cbiAgXHRcdGZpbGxSdWxlOiAnZXZlbm9kZCcsXG5cbiAgXHRcdC8vIGNsYXNzTmFtZTogJycsXG5cbiAgXHRcdC8vIE9wdGlvbiBpbmhlcml0ZWQgZnJvbSBcIkludGVyYWN0aXZlIGxheWVyXCIgYWJzdHJhY3QgY2xhc3NcbiAgXHRcdGludGVyYWN0aXZlOiB0cnVlLFxuXG4gIFx0XHQvLyBAb3B0aW9uIGJ1YmJsaW5nTW91c2VFdmVudHM6IEJvb2xlYW4gPSB0cnVlXG4gIFx0XHQvLyBXaGVuIGB0cnVlYCwgYSBtb3VzZSBldmVudCBvbiB0aGlzIHBhdGggd2lsbCB0cmlnZ2VyIHRoZSBzYW1lIGV2ZW50IG9uIHRoZSBtYXBcbiAgXHRcdC8vICh1bmxlc3MgW2BMLkRvbUV2ZW50LnN0b3BQcm9wYWdhdGlvbmBdKCNkb21ldmVudC1zdG9wcHJvcGFnYXRpb24pIGlzIHVzZWQpLlxuICBcdFx0YnViYmxpbmdNb3VzZUV2ZW50czogdHJ1ZVxuICBcdH0sXG5cbiAgXHRiZWZvcmVBZGQ6IGZ1bmN0aW9uIChtYXApIHtcbiAgXHRcdC8vIFJlbmRlcmVyIGlzIHNldCBoZXJlIGJlY2F1c2Ugd2UgbmVlZCB0byBjYWxsIHJlbmRlcmVyLmdldEV2ZW50c1xuICBcdFx0Ly8gYmVmb3JlIHRoaXMuZ2V0RXZlbnRzLlxuICBcdFx0dGhpcy5fcmVuZGVyZXIgPSBtYXAuZ2V0UmVuZGVyZXIodGhpcyk7XG4gIFx0fSxcblxuICBcdG9uQWRkOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR0aGlzLl9yZW5kZXJlci5faW5pdFBhdGgodGhpcyk7XG4gIFx0XHR0aGlzLl9yZXNldCgpO1xuICBcdFx0dGhpcy5fcmVuZGVyZXIuX2FkZFBhdGgodGhpcyk7XG4gIFx0fSxcblxuICBcdG9uUmVtb3ZlOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR0aGlzLl9yZW5kZXJlci5fcmVtb3ZlUGF0aCh0aGlzKTtcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCByZWRyYXcoKTogdGhpc1xuICBcdC8vIFJlZHJhd3MgdGhlIGxheWVyLiBTb21ldGltZXMgdXNlZnVsIGFmdGVyIHlvdSBjaGFuZ2VkIHRoZSBjb29yZGluYXRlcyB0aGF0IHRoZSBwYXRoIHVzZXMuXG4gIFx0cmVkcmF3OiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRpZiAodGhpcy5fbWFwKSB7XG4gIFx0XHRcdHRoaXMuX3JlbmRlcmVyLl91cGRhdGVQYXRoKHRoaXMpO1xuICBcdFx0fVxuICBcdFx0cmV0dXJuIHRoaXM7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2Qgc2V0U3R5bGUoc3R5bGU6IFBhdGggb3B0aW9ucyk6IHRoaXNcbiAgXHQvLyBDaGFuZ2VzIHRoZSBhcHBlYXJhbmNlIG9mIGEgUGF0aCBiYXNlZCBvbiB0aGUgb3B0aW9ucyBpbiB0aGUgYFBhdGggb3B0aW9uc2Agb2JqZWN0LlxuICBcdHNldFN0eWxlOiBmdW5jdGlvbiAoc3R5bGUpIHtcbiAgXHRcdHNldE9wdGlvbnModGhpcywgc3R5bGUpO1xuICBcdFx0aWYgKHRoaXMuX3JlbmRlcmVyKSB7XG4gIFx0XHRcdHRoaXMuX3JlbmRlcmVyLl91cGRhdGVTdHlsZSh0aGlzKTtcbiAgXHRcdFx0aWYgKHRoaXMub3B0aW9ucy5zdHJva2UgJiYgc3R5bGUgJiYgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHN0eWxlLCAnd2VpZ2h0JykpIHtcbiAgXHRcdFx0XHR0aGlzLl91cGRhdGVCb3VuZHMoKTtcbiAgXHRcdFx0fVxuICBcdFx0fVxuICBcdFx0cmV0dXJuIHRoaXM7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgYnJpbmdUb0Zyb250KCk6IHRoaXNcbiAgXHQvLyBCcmluZ3MgdGhlIGxheWVyIHRvIHRoZSB0b3Agb2YgYWxsIHBhdGggbGF5ZXJzLlxuICBcdGJyaW5nVG9Gcm9udDogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKHRoaXMuX3JlbmRlcmVyKSB7XG4gIFx0XHRcdHRoaXMuX3JlbmRlcmVyLl9icmluZ1RvRnJvbnQodGhpcyk7XG4gIFx0XHR9XG4gIFx0XHRyZXR1cm4gdGhpcztcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBicmluZ1RvQmFjaygpOiB0aGlzXG4gIFx0Ly8gQnJpbmdzIHRoZSBsYXllciB0byB0aGUgYm90dG9tIG9mIGFsbCBwYXRoIGxheWVycy5cbiAgXHRicmluZ1RvQmFjazogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKHRoaXMuX3JlbmRlcmVyKSB7XG4gIFx0XHRcdHRoaXMuX3JlbmRlcmVyLl9icmluZ1RvQmFjayh0aGlzKTtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiB0aGlzO1xuICBcdH0sXG5cbiAgXHRnZXRFbGVtZW50OiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZXR1cm4gdGhpcy5fcGF0aDtcbiAgXHR9LFxuXG4gIFx0X3Jlc2V0OiBmdW5jdGlvbiAoKSB7XG4gIFx0XHQvLyBkZWZpbmVkIGluIGNoaWxkIGNsYXNzZXNcbiAgXHRcdHRoaXMuX3Byb2plY3QoKTtcbiAgXHRcdHRoaXMuX3VwZGF0ZSgpO1xuICBcdH0sXG5cbiAgXHRfY2xpY2tUb2xlcmFuY2U6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdC8vIHVzZWQgd2hlbiBkb2luZyBoaXQgZGV0ZWN0aW9uIGZvciBDYW52YXMgbGF5ZXJzXG4gIFx0XHRyZXR1cm4gKHRoaXMub3B0aW9ucy5zdHJva2UgPyB0aGlzLm9wdGlvbnMud2VpZ2h0IC8gMiA6IDApICtcbiAgXHRcdCAgKHRoaXMuX3JlbmRlcmVyLm9wdGlvbnMudG9sZXJhbmNlIHx8IDApO1xuICBcdH1cbiAgfSk7XG5cbiAgLypcbiAgICogQGNsYXNzIENpcmNsZU1hcmtlclxuICAgKiBAYWthIEwuQ2lyY2xlTWFya2VyXG4gICAqIEBpbmhlcml0cyBQYXRoXG4gICAqXG4gICAqIEEgY2lyY2xlIG9mIGEgZml4ZWQgc2l6ZSB3aXRoIHJhZGl1cyBzcGVjaWZpZWQgaW4gcGl4ZWxzLiBFeHRlbmRzIGBQYXRoYC5cbiAgICovXG5cbiAgdmFyIENpcmNsZU1hcmtlciA9IFBhdGguZXh0ZW5kKHtcblxuICBcdC8vIEBzZWN0aW9uXG4gIFx0Ly8gQGFrYSBDaXJjbGVNYXJrZXIgb3B0aW9uc1xuICBcdG9wdGlvbnM6IHtcbiAgXHRcdGZpbGw6IHRydWUsXG5cbiAgXHRcdC8vIEBvcHRpb24gcmFkaXVzOiBOdW1iZXIgPSAxMFxuICBcdFx0Ly8gUmFkaXVzIG9mIHRoZSBjaXJjbGUgbWFya2VyLCBpbiBwaXhlbHNcbiAgXHRcdHJhZGl1czogMTBcbiAgXHR9LFxuXG4gIFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKGxhdGxuZywgb3B0aW9ucykge1xuICBcdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcbiAgXHRcdHRoaXMuX2xhdGxuZyA9IHRvTGF0TG5nKGxhdGxuZyk7XG4gIFx0XHR0aGlzLl9yYWRpdXMgPSB0aGlzLm9wdGlvbnMucmFkaXVzO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIHNldExhdExuZyhsYXRMbmc6IExhdExuZyk6IHRoaXNcbiAgXHQvLyBTZXRzIHRoZSBwb3NpdGlvbiBvZiBhIGNpcmNsZSBtYXJrZXIgdG8gYSBuZXcgbG9jYXRpb24uXG4gIFx0c2V0TGF0TG5nOiBmdW5jdGlvbiAobGF0bG5nKSB7XG4gIFx0XHR2YXIgb2xkTGF0TG5nID0gdGhpcy5fbGF0bG5nO1xuICBcdFx0dGhpcy5fbGF0bG5nID0gdG9MYXRMbmcobGF0bG5nKTtcbiAgXHRcdHRoaXMucmVkcmF3KCk7XG5cbiAgXHRcdC8vIEBldmVudCBtb3ZlOiBFdmVudFxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbWFya2VyIGlzIG1vdmVkIHZpYSBbYHNldExhdExuZ2BdKCNjaXJjbGVtYXJrZXItc2V0bGF0bG5nKS4gT2xkIGFuZCBuZXcgY29vcmRpbmF0ZXMgYXJlIGluY2x1ZGVkIGluIGV2ZW50IGFyZ3VtZW50cyBhcyBgb2xkTGF0TG5nYCwgYGxhdGxuZ2AuXG4gIFx0XHRyZXR1cm4gdGhpcy5maXJlKCdtb3ZlJywge29sZExhdExuZzogb2xkTGF0TG5nLCBsYXRsbmc6IHRoaXMuX2xhdGxuZ30pO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIGdldExhdExuZygpOiBMYXRMbmdcbiAgXHQvLyBSZXR1cm5zIHRoZSBjdXJyZW50IGdlb2dyYXBoaWNhbCBwb3NpdGlvbiBvZiB0aGUgY2lyY2xlIG1hcmtlclxuICBcdGdldExhdExuZzogZnVuY3Rpb24gKCkge1xuICBcdFx0cmV0dXJuIHRoaXMuX2xhdGxuZztcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBzZXRSYWRpdXMocmFkaXVzOiBOdW1iZXIpOiB0aGlzXG4gIFx0Ly8gU2V0cyB0aGUgcmFkaXVzIG9mIGEgY2lyY2xlIG1hcmtlci4gVW5pdHMgYXJlIGluIHBpeGVscy5cbiAgXHRzZXRSYWRpdXM6IGZ1bmN0aW9uIChyYWRpdXMpIHtcbiAgXHRcdHRoaXMub3B0aW9ucy5yYWRpdXMgPSB0aGlzLl9yYWRpdXMgPSByYWRpdXM7XG4gIFx0XHRyZXR1cm4gdGhpcy5yZWRyYXcoKTtcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBnZXRSYWRpdXMoKTogTnVtYmVyXG4gIFx0Ly8gUmV0dXJucyB0aGUgY3VycmVudCByYWRpdXMgb2YgdGhlIGNpcmNsZVxuICBcdGdldFJhZGl1czogZnVuY3Rpb24gKCkge1xuICBcdFx0cmV0dXJuIHRoaXMuX3JhZGl1cztcbiAgXHR9LFxuXG4gIFx0c2V0U3R5bGUgOiBmdW5jdGlvbiAob3B0aW9ucykge1xuICBcdFx0dmFyIHJhZGl1cyA9IG9wdGlvbnMgJiYgb3B0aW9ucy5yYWRpdXMgfHwgdGhpcy5fcmFkaXVzO1xuICBcdFx0UGF0aC5wcm90b3R5cGUuc2V0U3R5bGUuY2FsbCh0aGlzLCBvcHRpb25zKTtcbiAgXHRcdHRoaXMuc2V0UmFkaXVzKHJhZGl1cyk7XG4gIFx0XHRyZXR1cm4gdGhpcztcbiAgXHR9LFxuXG4gIFx0X3Byb2plY3Q6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHRoaXMuX3BvaW50ID0gdGhpcy5fbWFwLmxhdExuZ1RvTGF5ZXJQb2ludCh0aGlzLl9sYXRsbmcpO1xuICBcdFx0dGhpcy5fdXBkYXRlQm91bmRzKCk7XG4gIFx0fSxcblxuICBcdF91cGRhdGVCb3VuZHM6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHZhciByID0gdGhpcy5fcmFkaXVzLFxuICBcdFx0ICAgIHIyID0gdGhpcy5fcmFkaXVzWSB8fCByLFxuICBcdFx0ICAgIHcgPSB0aGlzLl9jbGlja1RvbGVyYW5jZSgpLFxuICBcdFx0ICAgIHAgPSBbciArIHcsIHIyICsgd107XG4gIFx0XHR0aGlzLl9weEJvdW5kcyA9IG5ldyBCb3VuZHModGhpcy5fcG9pbnQuc3VidHJhY3QocCksIHRoaXMuX3BvaW50LmFkZChwKSk7XG4gIFx0fSxcblxuICBcdF91cGRhdGU6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICh0aGlzLl9tYXApIHtcbiAgXHRcdFx0dGhpcy5fdXBkYXRlUGF0aCgpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfdXBkYXRlUGF0aDogZnVuY3Rpb24gKCkge1xuICBcdFx0dGhpcy5fcmVuZGVyZXIuX3VwZGF0ZUNpcmNsZSh0aGlzKTtcbiAgXHR9LFxuXG4gIFx0X2VtcHR5OiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZXR1cm4gdGhpcy5fcmFkaXVzICYmICF0aGlzLl9yZW5kZXJlci5fYm91bmRzLmludGVyc2VjdHModGhpcy5fcHhCb3VuZHMpO1xuICBcdH0sXG5cbiAgXHQvLyBOZWVkZWQgYnkgdGhlIGBDYW52YXNgIHJlbmRlcmVyIGZvciBpbnRlcmFjdGl2aXR5XG4gIFx0X2NvbnRhaW5zUG9pbnQ6IGZ1bmN0aW9uIChwKSB7XG4gIFx0XHRyZXR1cm4gcC5kaXN0YW5jZVRvKHRoaXMuX3BvaW50KSA8PSB0aGlzLl9yYWRpdXMgKyB0aGlzLl9jbGlja1RvbGVyYW5jZSgpO1xuICBcdH1cbiAgfSk7XG5cblxuICAvLyBAZmFjdG9yeSBMLmNpcmNsZU1hcmtlcihsYXRsbmc6IExhdExuZywgb3B0aW9ucz86IENpcmNsZU1hcmtlciBvcHRpb25zKVxuICAvLyBJbnN0YW50aWF0ZXMgYSBjaXJjbGUgbWFya2VyIG9iamVjdCBnaXZlbiBhIGdlb2dyYXBoaWNhbCBwb2ludCwgYW5kIGFuIG9wdGlvbmFsIG9wdGlvbnMgb2JqZWN0LlxuICBmdW5jdGlvbiBjaXJjbGVNYXJrZXIobGF0bG5nLCBvcHRpb25zKSB7XG4gIFx0cmV0dXJuIG5ldyBDaXJjbGVNYXJrZXIobGF0bG5nLCBvcHRpb25zKTtcbiAgfVxuXG4gIC8qXG4gICAqIEBjbGFzcyBDaXJjbGVcbiAgICogQGFrYSBMLkNpcmNsZVxuICAgKiBAaW5oZXJpdHMgQ2lyY2xlTWFya2VyXG4gICAqXG4gICAqIEEgY2xhc3MgZm9yIGRyYXdpbmcgY2lyY2xlIG92ZXJsYXlzIG9uIGEgbWFwLiBFeHRlbmRzIGBDaXJjbGVNYXJrZXJgLlxuICAgKlxuICAgKiBJdCdzIGFuIGFwcHJveGltYXRpb24gYW5kIHN0YXJ0cyB0byBkaXZlcmdlIGZyb20gYSByZWFsIGNpcmNsZSBjbG9zZXIgdG8gcG9sZXMgKGR1ZSB0byBwcm9qZWN0aW9uIGRpc3RvcnRpb24pLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKlxuICAgKiBgYGBqc1xuICAgKiBMLmNpcmNsZShbNTAuNSwgMzAuNV0sIHtyYWRpdXM6IDIwMH0pLmFkZFRvKG1hcCk7XG4gICAqIGBgYFxuICAgKi9cblxuICB2YXIgQ2lyY2xlID0gQ2lyY2xlTWFya2VyLmV4dGVuZCh7XG5cbiAgXHRpbml0aWFsaXplOiBmdW5jdGlvbiAobGF0bG5nLCBvcHRpb25zLCBsZWdhY3lPcHRpb25zKSB7XG4gIFx0XHRpZiAodHlwZW9mIG9wdGlvbnMgPT09ICdudW1iZXInKSB7XG4gIFx0XHRcdC8vIEJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IHdpdGggMC43LnggZmFjdG9yeSAobGF0bG5nLCByYWRpdXMsIG9wdGlvbnM/KVxuICBcdFx0XHRvcHRpb25zID0gZXh0ZW5kKHt9LCBsZWdhY3lPcHRpb25zLCB7cmFkaXVzOiBvcHRpb25zfSk7XG4gIFx0XHR9XG4gIFx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xuICBcdFx0dGhpcy5fbGF0bG5nID0gdG9MYXRMbmcobGF0bG5nKTtcblxuICBcdFx0aWYgKGlzTmFOKHRoaXMub3B0aW9ucy5yYWRpdXMpKSB7IHRocm93IG5ldyBFcnJvcignQ2lyY2xlIHJhZGl1cyBjYW5ub3QgYmUgTmFOJyk7IH1cblxuICBcdFx0Ly8gQHNlY3Rpb25cbiAgXHRcdC8vIEBha2EgQ2lyY2xlIG9wdGlvbnNcbiAgXHRcdC8vIEBvcHRpb24gcmFkaXVzOiBOdW1iZXI7IFJhZGl1cyBvZiB0aGUgY2lyY2xlLCBpbiBtZXRlcnMuXG4gIFx0XHR0aGlzLl9tUmFkaXVzID0gdGhpcy5vcHRpb25zLnJhZGl1cztcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBzZXRSYWRpdXMocmFkaXVzOiBOdW1iZXIpOiB0aGlzXG4gIFx0Ly8gU2V0cyB0aGUgcmFkaXVzIG9mIGEgY2lyY2xlLiBVbml0cyBhcmUgaW4gbWV0ZXJzLlxuICBcdHNldFJhZGl1czogZnVuY3Rpb24gKHJhZGl1cykge1xuICBcdFx0dGhpcy5fbVJhZGl1cyA9IHJhZGl1cztcbiAgXHRcdHJldHVybiB0aGlzLnJlZHJhdygpO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIGdldFJhZGl1cygpOiBOdW1iZXJcbiAgXHQvLyBSZXR1cm5zIHRoZSBjdXJyZW50IHJhZGl1cyBvZiBhIGNpcmNsZS4gVW5pdHMgYXJlIGluIG1ldGVycy5cbiAgXHRnZXRSYWRpdXM6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHJldHVybiB0aGlzLl9tUmFkaXVzO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIGdldEJvdW5kcygpOiBMYXRMbmdCb3VuZHNcbiAgXHQvLyBSZXR1cm5zIHRoZSBgTGF0TG5nQm91bmRzYCBvZiB0aGUgcGF0aC5cbiAgXHRnZXRCb3VuZHM6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHZhciBoYWxmID0gW3RoaXMuX3JhZGl1cywgdGhpcy5fcmFkaXVzWSB8fCB0aGlzLl9yYWRpdXNdO1xuXG4gIFx0XHRyZXR1cm4gbmV3IExhdExuZ0JvdW5kcyhcbiAgXHRcdFx0dGhpcy5fbWFwLmxheWVyUG9pbnRUb0xhdExuZyh0aGlzLl9wb2ludC5zdWJ0cmFjdChoYWxmKSksXG4gIFx0XHRcdHRoaXMuX21hcC5sYXllclBvaW50VG9MYXRMbmcodGhpcy5fcG9pbnQuYWRkKGhhbGYpKSk7XG4gIFx0fSxcblxuICBcdHNldFN0eWxlOiBQYXRoLnByb3RvdHlwZS5zZXRTdHlsZSxcblxuICBcdF9wcm9qZWN0OiBmdW5jdGlvbiAoKSB7XG5cbiAgXHRcdHZhciBsbmcgPSB0aGlzLl9sYXRsbmcubG5nLFxuICBcdFx0ICAgIGxhdCA9IHRoaXMuX2xhdGxuZy5sYXQsXG4gIFx0XHQgICAgbWFwID0gdGhpcy5fbWFwLFxuICBcdFx0ICAgIGNycyA9IG1hcC5vcHRpb25zLmNycztcblxuICBcdFx0aWYgKGNycy5kaXN0YW5jZSA9PT0gRWFydGguZGlzdGFuY2UpIHtcbiAgXHRcdFx0dmFyIGQgPSBNYXRoLlBJIC8gMTgwLFxuICBcdFx0XHQgICAgbGF0UiA9ICh0aGlzLl9tUmFkaXVzIC8gRWFydGguUikgLyBkLFxuICBcdFx0XHQgICAgdG9wID0gbWFwLnByb2plY3QoW2xhdCArIGxhdFIsIGxuZ10pLFxuICBcdFx0XHQgICAgYm90dG9tID0gbWFwLnByb2plY3QoW2xhdCAtIGxhdFIsIGxuZ10pLFxuICBcdFx0XHQgICAgcCA9IHRvcC5hZGQoYm90dG9tKS5kaXZpZGVCeSgyKSxcbiAgXHRcdFx0ICAgIGxhdDIgPSBtYXAudW5wcm9qZWN0KHApLmxhdCxcbiAgXHRcdFx0ICAgIGxuZ1IgPSBNYXRoLmFjb3MoKE1hdGguY29zKGxhdFIgKiBkKSAtIE1hdGguc2luKGxhdCAqIGQpICogTWF0aC5zaW4obGF0MiAqIGQpKSAvXG4gIFx0XHRcdCAgICAgICAgICAgIChNYXRoLmNvcyhsYXQgKiBkKSAqIE1hdGguY29zKGxhdDIgKiBkKSkpIC8gZDtcblxuICBcdFx0XHRpZiAoaXNOYU4obG5nUikgfHwgbG5nUiA9PT0gMCkge1xuICBcdFx0XHRcdGxuZ1IgPSBsYXRSIC8gTWF0aC5jb3MoTWF0aC5QSSAvIDE4MCAqIGxhdCk7IC8vIEZhbGxiYWNrIGZvciBlZGdlIGNhc2UsICMyNDI1XG4gIFx0XHRcdH1cblxuICBcdFx0XHR0aGlzLl9wb2ludCA9IHAuc3VidHJhY3QobWFwLmdldFBpeGVsT3JpZ2luKCkpO1xuICBcdFx0XHR0aGlzLl9yYWRpdXMgPSBpc05hTihsbmdSKSA/IDAgOiBwLnggLSBtYXAucHJvamVjdChbbGF0MiwgbG5nIC0gbG5nUl0pLng7XG4gIFx0XHRcdHRoaXMuX3JhZGl1c1kgPSBwLnkgLSB0b3AueTtcblxuICBcdFx0fSBlbHNlIHtcbiAgXHRcdFx0dmFyIGxhdGxuZzIgPSBjcnMudW5wcm9qZWN0KGNycy5wcm9qZWN0KHRoaXMuX2xhdGxuZykuc3VidHJhY3QoW3RoaXMuX21SYWRpdXMsIDBdKSk7XG5cbiAgXHRcdFx0dGhpcy5fcG9pbnQgPSBtYXAubGF0TG5nVG9MYXllclBvaW50KHRoaXMuX2xhdGxuZyk7XG4gIFx0XHRcdHRoaXMuX3JhZGl1cyA9IHRoaXMuX3BvaW50LnggLSBtYXAubGF0TG5nVG9MYXllclBvaW50KGxhdGxuZzIpLng7XG4gIFx0XHR9XG5cbiAgXHRcdHRoaXMuX3VwZGF0ZUJvdW5kcygpO1xuICBcdH1cbiAgfSk7XG5cbiAgLy8gQGZhY3RvcnkgTC5jaXJjbGUobGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/OiBDaXJjbGUgb3B0aW9ucylcbiAgLy8gSW5zdGFudGlhdGVzIGEgY2lyY2xlIG9iamVjdCBnaXZlbiBhIGdlb2dyYXBoaWNhbCBwb2ludCwgYW5kIGFuIG9wdGlvbnMgb2JqZWN0XG4gIC8vIHdoaWNoIGNvbnRhaW5zIHRoZSBjaXJjbGUgcmFkaXVzLlxuICAvLyBAYWx0ZXJuYXRpdmVcbiAgLy8gQGZhY3RvcnkgTC5jaXJjbGUobGF0bG5nOiBMYXRMbmcsIHJhZGl1czogTnVtYmVyLCBvcHRpb25zPzogQ2lyY2xlIG9wdGlvbnMpXG4gIC8vIE9ic29sZXRlIHdheSBvZiBpbnN0YW50aWF0aW5nIGEgY2lyY2xlLCBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIDAuNy54IGNvZGUuXG4gIC8vIERvIG5vdCB1c2UgaW4gbmV3IGFwcGxpY2F0aW9ucyBvciBwbHVnaW5zLlxuICBmdW5jdGlvbiBjaXJjbGUobGF0bG5nLCBvcHRpb25zLCBsZWdhY3lPcHRpb25zKSB7XG4gIFx0cmV0dXJuIG5ldyBDaXJjbGUobGF0bG5nLCBvcHRpb25zLCBsZWdhY3lPcHRpb25zKTtcbiAgfVxuXG4gIC8qXG4gICAqIEBjbGFzcyBQb2x5bGluZVxuICAgKiBAYWthIEwuUG9seWxpbmVcbiAgICogQGluaGVyaXRzIFBhdGhcbiAgICpcbiAgICogQSBjbGFzcyBmb3IgZHJhd2luZyBwb2x5bGluZSBvdmVybGF5cyBvbiBhIG1hcC4gRXh0ZW5kcyBgUGF0aGAuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqIGBgYGpzXG4gICAqIC8vIGNyZWF0ZSBhIHJlZCBwb2x5bGluZSBmcm9tIGFuIGFycmF5IG9mIExhdExuZyBwb2ludHNcbiAgICogdmFyIGxhdGxuZ3MgPSBbXG4gICAqIFx0WzQ1LjUxLCAtMTIyLjY4XSxcbiAgICogXHRbMzcuNzcsIC0xMjIuNDNdLFxuICAgKiBcdFszNC4wNCwgLTExOC4yXVxuICAgKiBdO1xuICAgKlxuICAgKiB2YXIgcG9seWxpbmUgPSBMLnBvbHlsaW5lKGxhdGxuZ3MsIHtjb2xvcjogJ3JlZCd9KS5hZGRUbyhtYXApO1xuICAgKlxuICAgKiAvLyB6b29tIHRoZSBtYXAgdG8gdGhlIHBvbHlsaW5lXG4gICAqIG1hcC5maXRCb3VuZHMocG9seWxpbmUuZ2V0Qm91bmRzKCkpO1xuICAgKiBgYGBcbiAgICpcbiAgICogWW91IGNhbiBhbHNvIHBhc3MgYSBtdWx0aS1kaW1lbnNpb25hbCBhcnJheSB0byByZXByZXNlbnQgYSBgTXVsdGlQb2x5bGluZWAgc2hhcGU6XG4gICAqXG4gICAqIGBgYGpzXG4gICAqIC8vIGNyZWF0ZSBhIHJlZCBwb2x5bGluZSBmcm9tIGFuIGFycmF5IG9mIGFycmF5cyBvZiBMYXRMbmcgcG9pbnRzXG4gICAqIHZhciBsYXRsbmdzID0gW1xuICAgKiBcdFtbNDUuNTEsIC0xMjIuNjhdLFxuICAgKiBcdCBbMzcuNzcsIC0xMjIuNDNdLFxuICAgKiBcdCBbMzQuMDQsIC0xMTguMl1dLFxuICAgKiBcdFtbNDAuNzgsIC03My45MV0sXG4gICAqIFx0IFs0MS44MywgLTg3LjYyXSxcbiAgICogXHQgWzMyLjc2LCAtOTYuNzJdXVxuICAgKiBdO1xuICAgKiBgYGBcbiAgICovXG5cblxuICB2YXIgUG9seWxpbmUgPSBQYXRoLmV4dGVuZCh7XG5cbiAgXHQvLyBAc2VjdGlvblxuICBcdC8vIEBha2EgUG9seWxpbmUgb3B0aW9uc1xuICBcdG9wdGlvbnM6IHtcbiAgXHRcdC8vIEBvcHRpb24gc21vb3RoRmFjdG9yOiBOdW1iZXIgPSAxLjBcbiAgXHRcdC8vIEhvdyBtdWNoIHRvIHNpbXBsaWZ5IHRoZSBwb2x5bGluZSBvbiBlYWNoIHpvb20gbGV2ZWwuIE1vcmUgbWVhbnNcbiAgXHRcdC8vIGJldHRlciBwZXJmb3JtYW5jZSBhbmQgc21vb3RoZXIgbG9vaywgYW5kIGxlc3MgbWVhbnMgbW9yZSBhY2N1cmF0ZSByZXByZXNlbnRhdGlvbi5cbiAgXHRcdHNtb290aEZhY3RvcjogMS4wLFxuXG4gIFx0XHQvLyBAb3B0aW9uIG5vQ2xpcDogQm9vbGVhbiA9IGZhbHNlXG4gIFx0XHQvLyBEaXNhYmxlIHBvbHlsaW5lIGNsaXBwaW5nLlxuICBcdFx0bm9DbGlwOiBmYWxzZVxuICBcdH0sXG5cbiAgXHRpbml0aWFsaXplOiBmdW5jdGlvbiAobGF0bG5ncywgb3B0aW9ucykge1xuICBcdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcbiAgXHRcdHRoaXMuX3NldExhdExuZ3MobGF0bG5ncyk7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgZ2V0TGF0TG5ncygpOiBMYXRMbmdbXVxuICBcdC8vIFJldHVybnMgYW4gYXJyYXkgb2YgdGhlIHBvaW50cyBpbiB0aGUgcGF0aCwgb3IgbmVzdGVkIGFycmF5cyBvZiBwb2ludHMgaW4gY2FzZSBvZiBtdWx0aS1wb2x5bGluZS5cbiAgXHRnZXRMYXRMbmdzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZXR1cm4gdGhpcy5fbGF0bG5ncztcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBzZXRMYXRMbmdzKGxhdGxuZ3M6IExhdExuZ1tdKTogdGhpc1xuICBcdC8vIFJlcGxhY2VzIGFsbCB0aGUgcG9pbnRzIGluIHRoZSBwb2x5bGluZSB3aXRoIHRoZSBnaXZlbiBhcnJheSBvZiBnZW9ncmFwaGljYWwgcG9pbnRzLlxuICBcdHNldExhdExuZ3M6IGZ1bmN0aW9uIChsYXRsbmdzKSB7XG4gIFx0XHR0aGlzLl9zZXRMYXRMbmdzKGxhdGxuZ3MpO1xuICBcdFx0cmV0dXJuIHRoaXMucmVkcmF3KCk7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgaXNFbXB0eSgpOiBCb29sZWFuXG4gIFx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIFBvbHlsaW5lIGhhcyBubyBMYXRMbmdzLlxuICBcdGlzRW1wdHk6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHJldHVybiAhdGhpcy5fbGF0bG5ncy5sZW5ndGg7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgY2xvc2VzdExheWVyUG9pbnQocDogUG9pbnQpOiBQb2ludFxuICBcdC8vIFJldHVybnMgdGhlIHBvaW50IGNsb3Nlc3QgdG8gYHBgIG9uIHRoZSBQb2x5bGluZS5cbiAgXHRjbG9zZXN0TGF5ZXJQb2ludDogZnVuY3Rpb24gKHApIHtcbiAgXHRcdHZhciBtaW5EaXN0YW5jZSA9IEluZmluaXR5LFxuICBcdFx0ICAgIG1pblBvaW50ID0gbnVsbCxcbiAgXHRcdCAgICBjbG9zZXN0ID0gX3NxQ2xvc2VzdFBvaW50T25TZWdtZW50LFxuICBcdFx0ICAgIHAxLCBwMjtcblxuICBcdFx0Zm9yICh2YXIgaiA9IDAsIGpMZW4gPSB0aGlzLl9wYXJ0cy5sZW5ndGg7IGogPCBqTGVuOyBqKyspIHtcbiAgXHRcdFx0dmFyIHBvaW50cyA9IHRoaXMuX3BhcnRzW2pdO1xuXG4gIFx0XHRcdGZvciAodmFyIGkgPSAxLCBsZW4gPSBwb2ludHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgXHRcdFx0XHRwMSA9IHBvaW50c1tpIC0gMV07XG4gIFx0XHRcdFx0cDIgPSBwb2ludHNbaV07XG5cbiAgXHRcdFx0XHR2YXIgc3FEaXN0ID0gY2xvc2VzdChwLCBwMSwgcDIsIHRydWUpO1xuXG4gIFx0XHRcdFx0aWYgKHNxRGlzdCA8IG1pbkRpc3RhbmNlKSB7XG4gIFx0XHRcdFx0XHRtaW5EaXN0YW5jZSA9IHNxRGlzdDtcbiAgXHRcdFx0XHRcdG1pblBvaW50ID0gY2xvc2VzdChwLCBwMSwgcDIpO1xuICBcdFx0XHRcdH1cbiAgXHRcdFx0fVxuICBcdFx0fVxuICBcdFx0aWYgKG1pblBvaW50KSB7XG4gIFx0XHRcdG1pblBvaW50LmRpc3RhbmNlID0gTWF0aC5zcXJ0KG1pbkRpc3RhbmNlKTtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiBtaW5Qb2ludDtcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBnZXRDZW50ZXIoKTogTGF0TG5nXG4gIFx0Ly8gUmV0dXJucyB0aGUgY2VudGVyIChbY2VudHJvaWRdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NlbnRyb2lkKSkgb2YgdGhlIHBvbHlsaW5lLlxuICBcdGdldENlbnRlcjogZnVuY3Rpb24gKCkge1xuICBcdFx0Ly8gdGhyb3dzIGVycm9yIHdoZW4gbm90IHlldCBhZGRlZCB0byBtYXAgYXMgdGhpcyBjZW50ZXIgY2FsY3VsYXRpb24gcmVxdWlyZXMgcHJvamVjdGVkIGNvb3JkaW5hdGVzXG4gIFx0XHRpZiAoIXRoaXMuX21hcCkge1xuICBcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ011c3QgYWRkIGxheWVyIHRvIG1hcCBiZWZvcmUgdXNpbmcgZ2V0Q2VudGVyKCknKTtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiBwb2x5bGluZUNlbnRlcih0aGlzLl9kZWZhdWx0U2hhcGUoKSwgdGhpcy5fbWFwLm9wdGlvbnMuY3JzKTtcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBnZXRCb3VuZHMoKTogTGF0TG5nQm91bmRzXG4gIFx0Ly8gUmV0dXJucyB0aGUgYExhdExuZ0JvdW5kc2Agb2YgdGhlIHBhdGguXG4gIFx0Z2V0Qm91bmRzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZXR1cm4gdGhpcy5fYm91bmRzO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIGFkZExhdExuZyhsYXRsbmc6IExhdExuZywgbGF0bG5ncz86IExhdExuZ1tdKTogdGhpc1xuICBcdC8vIEFkZHMgYSBnaXZlbiBwb2ludCB0byB0aGUgcG9seWxpbmUuIEJ5IGRlZmF1bHQsIGFkZHMgdG8gdGhlIGZpcnN0IHJpbmcgb2ZcbiAgXHQvLyB0aGUgcG9seWxpbmUgaW4gY2FzZSBvZiBhIG11bHRpLXBvbHlsaW5lLCBidXQgY2FuIGJlIG92ZXJyaWRkZW4gYnkgcGFzc2luZ1xuICBcdC8vIGEgc3BlY2lmaWMgcmluZyBhcyBhIExhdExuZyBhcnJheSAodGhhdCB5b3UgY2FuIGVhcmxpZXIgYWNjZXNzIHdpdGggW2BnZXRMYXRMbmdzYF0oI3BvbHlsaW5lLWdldGxhdGxuZ3MpKS5cbiAgXHRhZGRMYXRMbmc6IGZ1bmN0aW9uIChsYXRsbmcsIGxhdGxuZ3MpIHtcbiAgXHRcdGxhdGxuZ3MgPSBsYXRsbmdzIHx8IHRoaXMuX2RlZmF1bHRTaGFwZSgpO1xuICBcdFx0bGF0bG5nID0gdG9MYXRMbmcobGF0bG5nKTtcbiAgXHRcdGxhdGxuZ3MucHVzaChsYXRsbmcpO1xuICBcdFx0dGhpcy5fYm91bmRzLmV4dGVuZChsYXRsbmcpO1xuICBcdFx0cmV0dXJuIHRoaXMucmVkcmF3KCk7XG4gIFx0fSxcblxuICBcdF9zZXRMYXRMbmdzOiBmdW5jdGlvbiAobGF0bG5ncykge1xuICBcdFx0dGhpcy5fYm91bmRzID0gbmV3IExhdExuZ0JvdW5kcygpO1xuICBcdFx0dGhpcy5fbGF0bG5ncyA9IHRoaXMuX2NvbnZlcnRMYXRMbmdzKGxhdGxuZ3MpO1xuICBcdH0sXG5cbiAgXHRfZGVmYXVsdFNoYXBlOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZXR1cm4gaXNGbGF0KHRoaXMuX2xhdGxuZ3MpID8gdGhpcy5fbGF0bG5ncyA6IHRoaXMuX2xhdGxuZ3NbMF07XG4gIFx0fSxcblxuICBcdC8vIHJlY3Vyc2l2ZWx5IGNvbnZlcnQgbGF0bG5ncyBpbnB1dCBpbnRvIGFjdHVhbCBMYXRMbmcgaW5zdGFuY2VzOyBjYWxjdWxhdGUgYm91bmRzIGFsb25nIHRoZSB3YXlcbiAgXHRfY29udmVydExhdExuZ3M6IGZ1bmN0aW9uIChsYXRsbmdzKSB7XG4gIFx0XHR2YXIgcmVzdWx0ID0gW10sXG4gIFx0XHQgICAgZmxhdCA9IGlzRmxhdChsYXRsbmdzKTtcblxuICBcdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IGxhdGxuZ3MubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgXHRcdFx0aWYgKGZsYXQpIHtcbiAgXHRcdFx0XHRyZXN1bHRbaV0gPSB0b0xhdExuZyhsYXRsbmdzW2ldKTtcbiAgXHRcdFx0XHR0aGlzLl9ib3VuZHMuZXh0ZW5kKHJlc3VsdFtpXSk7XG4gIFx0XHRcdH0gZWxzZSB7XG4gIFx0XHRcdFx0cmVzdWx0W2ldID0gdGhpcy5fY29udmVydExhdExuZ3MobGF0bG5nc1tpXSk7XG4gIFx0XHRcdH1cbiAgXHRcdH1cblxuICBcdFx0cmV0dXJuIHJlc3VsdDtcbiAgXHR9LFxuXG4gIFx0X3Byb2plY3Q6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHZhciBweEJvdW5kcyA9IG5ldyBCb3VuZHMoKTtcbiAgXHRcdHRoaXMuX3JpbmdzID0gW107XG4gIFx0XHR0aGlzLl9wcm9qZWN0TGF0bG5ncyh0aGlzLl9sYXRsbmdzLCB0aGlzLl9yaW5ncywgcHhCb3VuZHMpO1xuXG4gIFx0XHRpZiAodGhpcy5fYm91bmRzLmlzVmFsaWQoKSAmJiBweEJvdW5kcy5pc1ZhbGlkKCkpIHtcbiAgXHRcdFx0dGhpcy5fcmF3UHhCb3VuZHMgPSBweEJvdW5kcztcbiAgXHRcdFx0dGhpcy5fdXBkYXRlQm91bmRzKCk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF91cGRhdGVCb3VuZHM6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHZhciB3ID0gdGhpcy5fY2xpY2tUb2xlcmFuY2UoKSxcbiAgXHRcdCAgICBwID0gbmV3IFBvaW50KHcsIHcpO1xuXG4gIFx0XHRpZiAoIXRoaXMuX3Jhd1B4Qm91bmRzKSB7XG4gIFx0XHRcdHJldHVybjtcbiAgXHRcdH1cblxuICBcdFx0dGhpcy5fcHhCb3VuZHMgPSBuZXcgQm91bmRzKFtcbiAgXHRcdFx0dGhpcy5fcmF3UHhCb3VuZHMubWluLnN1YnRyYWN0KHApLFxuICBcdFx0XHR0aGlzLl9yYXdQeEJvdW5kcy5tYXguYWRkKHApXG4gIFx0XHRdKTtcbiAgXHR9LFxuXG4gIFx0Ly8gcmVjdXJzaXZlbHkgdHVybnMgbGF0bG5ncyBpbnRvIGEgc2V0IG9mIHJpbmdzIHdpdGggcHJvamVjdGVkIGNvb3JkaW5hdGVzXG4gIFx0X3Byb2plY3RMYXRsbmdzOiBmdW5jdGlvbiAobGF0bG5ncywgcmVzdWx0LCBwcm9qZWN0ZWRCb3VuZHMpIHtcbiAgXHRcdHZhciBmbGF0ID0gbGF0bG5nc1swXSBpbnN0YW5jZW9mIExhdExuZyxcbiAgXHRcdCAgICBsZW4gPSBsYXRsbmdzLmxlbmd0aCxcbiAgXHRcdCAgICBpLCByaW5nO1xuXG4gIFx0XHRpZiAoZmxhdCkge1xuICBcdFx0XHRyaW5nID0gW107XG4gIFx0XHRcdGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICBcdFx0XHRcdHJpbmdbaV0gPSB0aGlzLl9tYXAubGF0TG5nVG9MYXllclBvaW50KGxhdGxuZ3NbaV0pO1xuICBcdFx0XHRcdHByb2plY3RlZEJvdW5kcy5leHRlbmQocmluZ1tpXSk7XG4gIFx0XHRcdH1cbiAgXHRcdFx0cmVzdWx0LnB1c2gocmluZyk7XG4gIFx0XHR9IGVsc2Uge1xuICBcdFx0XHRmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgXHRcdFx0XHR0aGlzLl9wcm9qZWN0TGF0bG5ncyhsYXRsbmdzW2ldLCByZXN1bHQsIHByb2plY3RlZEJvdW5kcyk7XG4gIFx0XHRcdH1cbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0Ly8gY2xpcCBwb2x5bGluZSBieSByZW5kZXJlciBib3VuZHMgc28gdGhhdCB3ZSBoYXZlIGxlc3MgdG8gcmVuZGVyIGZvciBwZXJmb3JtYW5jZVxuICBcdF9jbGlwUG9pbnRzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR2YXIgYm91bmRzID0gdGhpcy5fcmVuZGVyZXIuX2JvdW5kcztcblxuICBcdFx0dGhpcy5fcGFydHMgPSBbXTtcbiAgXHRcdGlmICghdGhpcy5fcHhCb3VuZHMgfHwgIXRoaXMuX3B4Qm91bmRzLmludGVyc2VjdHMoYm91bmRzKSkge1xuICBcdFx0XHRyZXR1cm47XG4gIFx0XHR9XG5cbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMubm9DbGlwKSB7XG4gIFx0XHRcdHRoaXMuX3BhcnRzID0gdGhpcy5fcmluZ3M7XG4gIFx0XHRcdHJldHVybjtcbiAgXHRcdH1cblxuICBcdFx0dmFyIHBhcnRzID0gdGhpcy5fcGFydHMsXG4gIFx0XHQgICAgaSwgaiwgaywgbGVuLCBsZW4yLCBzZWdtZW50LCBwb2ludHM7XG5cbiAgXHRcdGZvciAoaSA9IDAsIGsgPSAwLCBsZW4gPSB0aGlzLl9yaW5ncy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICBcdFx0XHRwb2ludHMgPSB0aGlzLl9yaW5nc1tpXTtcblxuICBcdFx0XHRmb3IgKGogPSAwLCBsZW4yID0gcG9pbnRzLmxlbmd0aDsgaiA8IGxlbjIgLSAxOyBqKyspIHtcbiAgXHRcdFx0XHRzZWdtZW50ID0gY2xpcFNlZ21lbnQocG9pbnRzW2pdLCBwb2ludHNbaiArIDFdLCBib3VuZHMsIGosIHRydWUpO1xuXG4gIFx0XHRcdFx0aWYgKCFzZWdtZW50KSB7IGNvbnRpbnVlOyB9XG5cbiAgXHRcdFx0XHRwYXJ0c1trXSA9IHBhcnRzW2tdIHx8IFtdO1xuICBcdFx0XHRcdHBhcnRzW2tdLnB1c2goc2VnbWVudFswXSk7XG5cbiAgXHRcdFx0XHQvLyBpZiBzZWdtZW50IGdvZXMgb3V0IG9mIHNjcmVlbiwgb3IgaXQncyB0aGUgbGFzdCBvbmUsIGl0J3MgdGhlIGVuZCBvZiB0aGUgbGluZSBwYXJ0XG4gIFx0XHRcdFx0aWYgKChzZWdtZW50WzFdICE9PSBwb2ludHNbaiArIDFdKSB8fCAoaiA9PT0gbGVuMiAtIDIpKSB7XG4gIFx0XHRcdFx0XHRwYXJ0c1trXS5wdXNoKHNlZ21lbnRbMV0pO1xuICBcdFx0XHRcdFx0aysrO1xuICBcdFx0XHRcdH1cbiAgXHRcdFx0fVxuICBcdFx0fVxuICBcdH0sXG5cbiAgXHQvLyBzaW1wbGlmeSBlYWNoIGNsaXBwZWQgcGFydCBvZiB0aGUgcG9seWxpbmUgZm9yIHBlcmZvcm1hbmNlXG4gIFx0X3NpbXBsaWZ5UG9pbnRzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR2YXIgcGFydHMgPSB0aGlzLl9wYXJ0cyxcbiAgXHRcdCAgICB0b2xlcmFuY2UgPSB0aGlzLm9wdGlvbnMuc21vb3RoRmFjdG9yO1xuXG4gIFx0XHRmb3IgKHZhciBpID0gMCwgbGVuID0gcGFydHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgXHRcdFx0cGFydHNbaV0gPSBzaW1wbGlmeShwYXJ0c1tpXSwgdG9sZXJhbmNlKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZTogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKCF0aGlzLl9tYXApIHsgcmV0dXJuOyB9XG5cbiAgXHRcdHRoaXMuX2NsaXBQb2ludHMoKTtcbiAgXHRcdHRoaXMuX3NpbXBsaWZ5UG9pbnRzKCk7XG4gIFx0XHR0aGlzLl91cGRhdGVQYXRoKCk7XG4gIFx0fSxcblxuICBcdF91cGRhdGVQYXRoOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR0aGlzLl9yZW5kZXJlci5fdXBkYXRlUG9seSh0aGlzKTtcbiAgXHR9LFxuXG4gIFx0Ly8gTmVlZGVkIGJ5IHRoZSBgQ2FudmFzYCByZW5kZXJlciBmb3IgaW50ZXJhY3Rpdml0eVxuICBcdF9jb250YWluc1BvaW50OiBmdW5jdGlvbiAocCwgY2xvc2VkKSB7XG4gIFx0XHR2YXIgaSwgaiwgaywgbGVuLCBsZW4yLCBwYXJ0LFxuICBcdFx0ICAgIHcgPSB0aGlzLl9jbGlja1RvbGVyYW5jZSgpO1xuXG4gIFx0XHRpZiAoIXRoaXMuX3B4Qm91bmRzIHx8ICF0aGlzLl9weEJvdW5kcy5jb250YWlucyhwKSkgeyByZXR1cm4gZmFsc2U7IH1cblxuICBcdFx0Ly8gaGl0IGRldGVjdGlvbiBmb3IgcG9seWxpbmVzXG4gIFx0XHRmb3IgKGkgPSAwLCBsZW4gPSB0aGlzLl9wYXJ0cy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICBcdFx0XHRwYXJ0ID0gdGhpcy5fcGFydHNbaV07XG5cbiAgXHRcdFx0Zm9yIChqID0gMCwgbGVuMiA9IHBhcnQubGVuZ3RoLCBrID0gbGVuMiAtIDE7IGogPCBsZW4yOyBrID0gaisrKSB7XG4gIFx0XHRcdFx0aWYgKCFjbG9zZWQgJiYgKGogPT09IDApKSB7IGNvbnRpbnVlOyB9XG5cbiAgXHRcdFx0XHRpZiAocG9pbnRUb1NlZ21lbnREaXN0YW5jZShwLCBwYXJ0W2tdLCBwYXJ0W2pdKSA8PSB3KSB7XG4gIFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcbiAgXHRcdFx0XHR9XG4gIFx0XHRcdH1cbiAgXHRcdH1cbiAgXHRcdHJldHVybiBmYWxzZTtcbiAgXHR9XG4gIH0pO1xuXG4gIC8vIEBmYWN0b3J5IEwucG9seWxpbmUobGF0bG5nczogTGF0TG5nW10sIG9wdGlvbnM/OiBQb2x5bGluZSBvcHRpb25zKVxuICAvLyBJbnN0YW50aWF0ZXMgYSBwb2x5bGluZSBvYmplY3QgZ2l2ZW4gYW4gYXJyYXkgb2YgZ2VvZ3JhcGhpY2FsIHBvaW50cyBhbmRcbiAgLy8gb3B0aW9uYWxseSBhbiBvcHRpb25zIG9iamVjdC4gWW91IGNhbiBjcmVhdGUgYSBgUG9seWxpbmVgIG9iamVjdCB3aXRoXG4gIC8vIG11bHRpcGxlIHNlcGFyYXRlIGxpbmVzIChgTXVsdGlQb2x5bGluZWApIGJ5IHBhc3NpbmcgYW4gYXJyYXkgb2YgYXJyYXlzXG4gIC8vIG9mIGdlb2dyYXBoaWMgcG9pbnRzLlxuICBmdW5jdGlvbiBwb2x5bGluZShsYXRsbmdzLCBvcHRpb25zKSB7XG4gIFx0cmV0dXJuIG5ldyBQb2x5bGluZShsYXRsbmdzLCBvcHRpb25zKTtcbiAgfVxuXG4gIC8vIFJldHJvY29tcGF0LiBBbGxvdyBwbHVnaW5zIHRvIHN1cHBvcnQgTGVhZmxldCB2ZXJzaW9ucyBiZWZvcmUgYW5kIGFmdGVyIDEuMS5cbiAgUG9seWxpbmUuX2ZsYXQgPSBfZmxhdDtcblxuICAvKlxuICAgKiBAY2xhc3MgUG9seWdvblxuICAgKiBAYWthIEwuUG9seWdvblxuICAgKiBAaW5oZXJpdHMgUG9seWxpbmVcbiAgICpcbiAgICogQSBjbGFzcyBmb3IgZHJhd2luZyBwb2x5Z29uIG92ZXJsYXlzIG9uIGEgbWFwLiBFeHRlbmRzIGBQb2x5bGluZWAuXG4gICAqXG4gICAqIE5vdGUgdGhhdCBwb2ludHMgeW91IHBhc3Mgd2hlbiBjcmVhdGluZyBhIHBvbHlnb24gc2hvdWxkbid0IGhhdmUgYW4gYWRkaXRpb25hbCBsYXN0IHBvaW50IGVxdWFsIHRvIHRoZSBmaXJzdCBvbmUg4oCUIGl0J3MgYmV0dGVyIHRvIGZpbHRlciBvdXQgc3VjaCBwb2ludHMuXG4gICAqXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqIGBgYGpzXG4gICAqIC8vIGNyZWF0ZSBhIHJlZCBwb2x5Z29uIGZyb20gYW4gYXJyYXkgb2YgTGF0TG5nIHBvaW50c1xuICAgKiB2YXIgbGF0bG5ncyA9IFtbMzcsIC0xMDkuMDVdLFs0MSwgLTEwOS4wM10sWzQxLCAtMTAyLjA1XSxbMzcsIC0xMDIuMDRdXTtcbiAgICpcbiAgICogdmFyIHBvbHlnb24gPSBMLnBvbHlnb24obGF0bG5ncywge2NvbG9yOiAncmVkJ30pLmFkZFRvKG1hcCk7XG4gICAqXG4gICAqIC8vIHpvb20gdGhlIG1hcCB0byB0aGUgcG9seWdvblxuICAgKiBtYXAuZml0Qm91bmRzKHBvbHlnb24uZ2V0Qm91bmRzKCkpO1xuICAgKiBgYGBcbiAgICpcbiAgICogWW91IGNhbiBhbHNvIHBhc3MgYW4gYXJyYXkgb2YgYXJyYXlzIG9mIGxhdGxuZ3MsIHdpdGggdGhlIGZpcnN0IGFycmF5IHJlcHJlc2VudGluZyB0aGUgb3V0ZXIgc2hhcGUgYW5kIHRoZSBvdGhlciBhcnJheXMgcmVwcmVzZW50aW5nIGhvbGVzIGluIHRoZSBvdXRlciBzaGFwZTpcbiAgICpcbiAgICogYGBganNcbiAgICogdmFyIGxhdGxuZ3MgPSBbXG4gICAqICAgW1szNywgLTEwOS4wNV0sWzQxLCAtMTA5LjAzXSxbNDEsIC0xMDIuMDVdLFszNywgLTEwMi4wNF1dLCAvLyBvdXRlciByaW5nXG4gICAqICAgW1szNy4yOSwgLTEwOC41OF0sWzQwLjcxLCAtMTA4LjU4XSxbNDAuNzEsIC0xMDIuNTBdLFszNy4yOSwgLTEwMi41MF1dIC8vIGhvbGVcbiAgICogXTtcbiAgICogYGBgXG4gICAqXG4gICAqIEFkZGl0aW9uYWxseSwgeW91IGNhbiBwYXNzIGEgbXVsdGktZGltZW5zaW9uYWwgYXJyYXkgdG8gcmVwcmVzZW50IGEgTXVsdGlQb2x5Z29uIHNoYXBlLlxuICAgKlxuICAgKiBgYGBqc1xuICAgKiB2YXIgbGF0bG5ncyA9IFtcbiAgICogICBbIC8vIGZpcnN0IHBvbHlnb25cbiAgICogICAgIFtbMzcsIC0xMDkuMDVdLFs0MSwgLTEwOS4wM10sWzQxLCAtMTAyLjA1XSxbMzcsIC0xMDIuMDRdXSwgLy8gb3V0ZXIgcmluZ1xuICAgKiAgICAgW1szNy4yOSwgLTEwOC41OF0sWzQwLjcxLCAtMTA4LjU4XSxbNDAuNzEsIC0xMDIuNTBdLFszNy4yOSwgLTEwMi41MF1dIC8vIGhvbGVcbiAgICogICBdLFxuICAgKiAgIFsgLy8gc2Vjb25kIHBvbHlnb25cbiAgICogICAgIFtbNDEsIC0xMTEuMDNdLFs0NSwgLTExMS4wNF0sWzQ1LCAtMTA0LjA1XSxbNDEsIC0xMDQuMDVdXVxuICAgKiAgIF1cbiAgICogXTtcbiAgICogYGBgXG4gICAqL1xuXG4gIHZhciBQb2x5Z29uID0gUG9seWxpbmUuZXh0ZW5kKHtcblxuICBcdG9wdGlvbnM6IHtcbiAgXHRcdGZpbGw6IHRydWVcbiAgXHR9LFxuXG4gIFx0aXNFbXB0eTogZnVuY3Rpb24gKCkge1xuICBcdFx0cmV0dXJuICF0aGlzLl9sYXRsbmdzLmxlbmd0aCB8fCAhdGhpcy5fbGF0bG5nc1swXS5sZW5ndGg7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgZ2V0Q2VudGVyKCk6IExhdExuZ1xuICBcdC8vIFJldHVybnMgdGhlIGNlbnRlciAoW2NlbnRyb2lkXShodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NlbnRyb2lkKSkgb2YgdGhlIFBvbHlnb24uXG4gIFx0Z2V0Q2VudGVyOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHQvLyB0aHJvd3MgZXJyb3Igd2hlbiBub3QgeWV0IGFkZGVkIHRvIG1hcCBhcyB0aGlzIGNlbnRlciBjYWxjdWxhdGlvbiByZXF1aXJlcyBwcm9qZWN0ZWQgY29vcmRpbmF0ZXNcbiAgXHRcdGlmICghdGhpcy5fbWFwKSB7XG4gIFx0XHRcdHRocm93IG5ldyBFcnJvcignTXVzdCBhZGQgbGF5ZXIgdG8gbWFwIGJlZm9yZSB1c2luZyBnZXRDZW50ZXIoKScpO1xuICBcdFx0fVxuICBcdFx0cmV0dXJuIHBvbHlnb25DZW50ZXIodGhpcy5fZGVmYXVsdFNoYXBlKCksIHRoaXMuX21hcC5vcHRpb25zLmNycyk7XG4gIFx0fSxcblxuICBcdF9jb252ZXJ0TGF0TG5nczogZnVuY3Rpb24gKGxhdGxuZ3MpIHtcbiAgXHRcdHZhciByZXN1bHQgPSBQb2x5bGluZS5wcm90b3R5cGUuX2NvbnZlcnRMYXRMbmdzLmNhbGwodGhpcywgbGF0bG5ncyksXG4gIFx0XHQgICAgbGVuID0gcmVzdWx0Lmxlbmd0aDtcblxuICBcdFx0Ly8gcmVtb3ZlIGxhc3QgcG9pbnQgaWYgaXQgZXF1YWxzIGZpcnN0IG9uZVxuICBcdFx0aWYgKGxlbiA+PSAyICYmIHJlc3VsdFswXSBpbnN0YW5jZW9mIExhdExuZyAmJiByZXN1bHRbMF0uZXF1YWxzKHJlc3VsdFtsZW4gLSAxXSkpIHtcbiAgXHRcdFx0cmVzdWx0LnBvcCgpO1xuICBcdFx0fVxuICBcdFx0cmV0dXJuIHJlc3VsdDtcbiAgXHR9LFxuXG4gIFx0X3NldExhdExuZ3M6IGZ1bmN0aW9uIChsYXRsbmdzKSB7XG4gIFx0XHRQb2x5bGluZS5wcm90b3R5cGUuX3NldExhdExuZ3MuY2FsbCh0aGlzLCBsYXRsbmdzKTtcbiAgXHRcdGlmIChpc0ZsYXQodGhpcy5fbGF0bG5ncykpIHtcbiAgXHRcdFx0dGhpcy5fbGF0bG5ncyA9IFt0aGlzLl9sYXRsbmdzXTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X2RlZmF1bHRTaGFwZTogZnVuY3Rpb24gKCkge1xuICBcdFx0cmV0dXJuIGlzRmxhdCh0aGlzLl9sYXRsbmdzWzBdKSA/IHRoaXMuX2xhdGxuZ3NbMF0gOiB0aGlzLl9sYXRsbmdzWzBdWzBdO1xuICBcdH0sXG5cbiAgXHRfY2xpcFBvaW50czogZnVuY3Rpb24gKCkge1xuICBcdFx0Ly8gcG9seWdvbnMgbmVlZCBhIGRpZmZlcmVudCBjbGlwcGluZyBhbGdvcml0aG0gc28gd2UgcmVkZWZpbmUgdGhhdFxuXG4gIFx0XHR2YXIgYm91bmRzID0gdGhpcy5fcmVuZGVyZXIuX2JvdW5kcyxcbiAgXHRcdCAgICB3ID0gdGhpcy5vcHRpb25zLndlaWdodCxcbiAgXHRcdCAgICBwID0gbmV3IFBvaW50KHcsIHcpO1xuXG4gIFx0XHQvLyBpbmNyZWFzZSBjbGlwIHBhZGRpbmcgYnkgc3Ryb2tlIHdpZHRoIHRvIGF2b2lkIHN0cm9rZSBvbiBjbGlwIGVkZ2VzXG4gIFx0XHRib3VuZHMgPSBuZXcgQm91bmRzKGJvdW5kcy5taW4uc3VidHJhY3QocCksIGJvdW5kcy5tYXguYWRkKHApKTtcblxuICBcdFx0dGhpcy5fcGFydHMgPSBbXTtcbiAgXHRcdGlmICghdGhpcy5fcHhCb3VuZHMgfHwgIXRoaXMuX3B4Qm91bmRzLmludGVyc2VjdHMoYm91bmRzKSkge1xuICBcdFx0XHRyZXR1cm47XG4gIFx0XHR9XG5cbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMubm9DbGlwKSB7XG4gIFx0XHRcdHRoaXMuX3BhcnRzID0gdGhpcy5fcmluZ3M7XG4gIFx0XHRcdHJldHVybjtcbiAgXHRcdH1cblxuICBcdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IHRoaXMuX3JpbmdzLmxlbmd0aCwgY2xpcHBlZDsgaSA8IGxlbjsgaSsrKSB7XG4gIFx0XHRcdGNsaXBwZWQgPSBjbGlwUG9seWdvbih0aGlzLl9yaW5nc1tpXSwgYm91bmRzLCB0cnVlKTtcbiAgXHRcdFx0aWYgKGNsaXBwZWQubGVuZ3RoKSB7XG4gIFx0XHRcdFx0dGhpcy5fcGFydHMucHVzaChjbGlwcGVkKTtcbiAgXHRcdFx0fVxuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfdXBkYXRlUGF0aDogZnVuY3Rpb24gKCkge1xuICBcdFx0dGhpcy5fcmVuZGVyZXIuX3VwZGF0ZVBvbHkodGhpcywgdHJ1ZSk7XG4gIFx0fSxcblxuICBcdC8vIE5lZWRlZCBieSB0aGUgYENhbnZhc2AgcmVuZGVyZXIgZm9yIGludGVyYWN0aXZpdHlcbiAgXHRfY29udGFpbnNQb2ludDogZnVuY3Rpb24gKHApIHtcbiAgXHRcdHZhciBpbnNpZGUgPSBmYWxzZSxcbiAgXHRcdCAgICBwYXJ0LCBwMSwgcDIsIGksIGosIGssIGxlbiwgbGVuMjtcblxuICBcdFx0aWYgKCF0aGlzLl9weEJvdW5kcyB8fCAhdGhpcy5fcHhCb3VuZHMuY29udGFpbnMocCkpIHsgcmV0dXJuIGZhbHNlOyB9XG5cbiAgXHRcdC8vIHJheSBjYXN0aW5nIGFsZ29yaXRobSBmb3IgZGV0ZWN0aW5nIGlmIHBvaW50IGlzIGluIHBvbHlnb25cbiAgXHRcdGZvciAoaSA9IDAsIGxlbiA9IHRoaXMuX3BhcnRzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gIFx0XHRcdHBhcnQgPSB0aGlzLl9wYXJ0c1tpXTtcblxuICBcdFx0XHRmb3IgKGogPSAwLCBsZW4yID0gcGFydC5sZW5ndGgsIGsgPSBsZW4yIC0gMTsgaiA8IGxlbjI7IGsgPSBqKyspIHtcbiAgXHRcdFx0XHRwMSA9IHBhcnRbal07XG4gIFx0XHRcdFx0cDIgPSBwYXJ0W2tdO1xuXG4gIFx0XHRcdFx0aWYgKCgocDEueSA+IHAueSkgIT09IChwMi55ID4gcC55KSkgJiYgKHAueCA8IChwMi54IC0gcDEueCkgKiAocC55IC0gcDEueSkgLyAocDIueSAtIHAxLnkpICsgcDEueCkpIHtcbiAgXHRcdFx0XHRcdGluc2lkZSA9ICFpbnNpZGU7XG4gIFx0XHRcdFx0fVxuICBcdFx0XHR9XG4gIFx0XHR9XG5cbiAgXHRcdC8vIGFsc28gY2hlY2sgaWYgaXQncyBvbiBwb2x5Z29uIHN0cm9rZVxuICBcdFx0cmV0dXJuIGluc2lkZSB8fCBQb2x5bGluZS5wcm90b3R5cGUuX2NvbnRhaW5zUG9pbnQuY2FsbCh0aGlzLCBwLCB0cnVlKTtcbiAgXHR9XG5cbiAgfSk7XG5cblxuICAvLyBAZmFjdG9yeSBMLnBvbHlnb24obGF0bG5nczogTGF0TG5nW10sIG9wdGlvbnM/OiBQb2x5bGluZSBvcHRpb25zKVxuICBmdW5jdGlvbiBwb2x5Z29uKGxhdGxuZ3MsIG9wdGlvbnMpIHtcbiAgXHRyZXR1cm4gbmV3IFBvbHlnb24obGF0bG5ncywgb3B0aW9ucyk7XG4gIH1cblxuICAvKlxyXG4gICAqIEBjbGFzcyBHZW9KU09OXHJcbiAgICogQGFrYSBMLkdlb0pTT05cclxuICAgKiBAaW5oZXJpdHMgRmVhdHVyZUdyb3VwXHJcbiAgICpcclxuICAgKiBSZXByZXNlbnRzIGEgR2VvSlNPTiBvYmplY3Qgb3IgYW4gYXJyYXkgb2YgR2VvSlNPTiBvYmplY3RzLiBBbGxvd3MgeW91IHRvIHBhcnNlXHJcbiAgICogR2VvSlNPTiBkYXRhIGFuZCBkaXNwbGF5IGl0IG9uIHRoZSBtYXAuIEV4dGVuZHMgYEZlYXR1cmVHcm91cGAuXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiBMLmdlb0pTT04oZGF0YSwge1xyXG4gICAqIFx0c3R5bGU6IGZ1bmN0aW9uIChmZWF0dXJlKSB7XHJcbiAgICogXHRcdHJldHVybiB7Y29sb3I6IGZlYXR1cmUucHJvcGVydGllcy5jb2xvcn07XHJcbiAgICogXHR9XHJcbiAgICogfSkuYmluZFBvcHVwKGZ1bmN0aW9uIChsYXllcikge1xyXG4gICAqIFx0cmV0dXJuIGxheWVyLmZlYXR1cmUucHJvcGVydGllcy5kZXNjcmlwdGlvbjtcclxuICAgKiB9KS5hZGRUbyhtYXApO1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG5cclxuICB2YXIgR2VvSlNPTiA9IEZlYXR1cmVHcm91cC5leHRlbmQoe1xyXG5cclxuICBcdC8qIEBzZWN0aW9uXHJcbiAgXHQgKiBAYWthIEdlb0pTT04gb3B0aW9uc1xyXG4gIFx0ICpcclxuICBcdCAqIEBvcHRpb24gcG9pbnRUb0xheWVyOiBGdW5jdGlvbiA9ICpcclxuICBcdCAqIEEgYEZ1bmN0aW9uYCBkZWZpbmluZyBob3cgR2VvSlNPTiBwb2ludHMgc3Bhd24gTGVhZmxldCBsYXllcnMuIEl0IGlzIGludGVybmFsbHlcclxuICBcdCAqIGNhbGxlZCB3aGVuIGRhdGEgaXMgYWRkZWQsIHBhc3NpbmcgdGhlIEdlb0pTT04gcG9pbnQgZmVhdHVyZSBhbmQgaXRzIGBMYXRMbmdgLlxyXG4gIFx0ICogVGhlIGRlZmF1bHQgaXMgdG8gc3Bhd24gYSBkZWZhdWx0IGBNYXJrZXJgOlxyXG4gIFx0ICogYGBganNcclxuICBcdCAqIGZ1bmN0aW9uKGdlb0pzb25Qb2ludCwgbGF0bG5nKSB7XHJcbiAgXHQgKiBcdHJldHVybiBMLm1hcmtlcihsYXRsbmcpO1xyXG4gIFx0ICogfVxyXG4gIFx0ICogYGBgXHJcbiAgXHQgKlxyXG4gIFx0ICogQG9wdGlvbiBzdHlsZTogRnVuY3Rpb24gPSAqXHJcbiAgXHQgKiBBIGBGdW5jdGlvbmAgZGVmaW5pbmcgdGhlIGBQYXRoIG9wdGlvbnNgIGZvciBzdHlsaW5nIEdlb0pTT04gbGluZXMgYW5kIHBvbHlnb25zLFxyXG4gIFx0ICogY2FsbGVkIGludGVybmFsbHkgd2hlbiBkYXRhIGlzIGFkZGVkLlxyXG4gIFx0ICogVGhlIGRlZmF1bHQgdmFsdWUgaXMgdG8gbm90IG92ZXJyaWRlIGFueSBkZWZhdWx0czpcclxuICBcdCAqIGBgYGpzXHJcbiAgXHQgKiBmdW5jdGlvbiAoZ2VvSnNvbkZlYXR1cmUpIHtcclxuICBcdCAqIFx0cmV0dXJuIHt9XHJcbiAgXHQgKiB9XHJcbiAgXHQgKiBgYGBcclxuICBcdCAqXHJcbiAgXHQgKiBAb3B0aW9uIG9uRWFjaEZlYXR1cmU6IEZ1bmN0aW9uID0gKlxyXG4gIFx0ICogQSBgRnVuY3Rpb25gIHRoYXQgd2lsbCBiZSBjYWxsZWQgb25jZSBmb3IgZWFjaCBjcmVhdGVkIGBGZWF0dXJlYCwgYWZ0ZXIgaXQgaGFzXHJcbiAgXHQgKiBiZWVuIGNyZWF0ZWQgYW5kIHN0eWxlZC4gVXNlZnVsIGZvciBhdHRhY2hpbmcgZXZlbnRzIGFuZCBwb3B1cHMgdG8gZmVhdHVyZXMuXHJcbiAgXHQgKiBUaGUgZGVmYXVsdCBpcyB0byBkbyBub3RoaW5nIHdpdGggdGhlIG5ld2x5IGNyZWF0ZWQgbGF5ZXJzOlxyXG4gIFx0ICogYGBganNcclxuICBcdCAqIGZ1bmN0aW9uIChmZWF0dXJlLCBsYXllcikge31cclxuICBcdCAqIGBgYFxyXG4gIFx0ICpcclxuICBcdCAqIEBvcHRpb24gZmlsdGVyOiBGdW5jdGlvbiA9ICpcclxuICBcdCAqIEEgYEZ1bmN0aW9uYCB0aGF0IHdpbGwgYmUgdXNlZCB0byBkZWNpZGUgd2hldGhlciB0byBpbmNsdWRlIGEgZmVhdHVyZSBvciBub3QuXHJcbiAgXHQgKiBUaGUgZGVmYXVsdCBpcyB0byBpbmNsdWRlIGFsbCBmZWF0dXJlczpcclxuICBcdCAqIGBgYGpzXHJcbiAgXHQgKiBmdW5jdGlvbiAoZ2VvSnNvbkZlYXR1cmUpIHtcclxuICBcdCAqIFx0cmV0dXJuIHRydWU7XHJcbiAgXHQgKiB9XHJcbiAgXHQgKiBgYGBcclxuICBcdCAqIE5vdGU6IGR5bmFtaWNhbGx5IGNoYW5naW5nIHRoZSBgZmlsdGVyYCBvcHRpb24gd2lsbCBoYXZlIGVmZmVjdCBvbmx5IG9uIG5ld2x5XHJcbiAgXHQgKiBhZGRlZCBkYXRhLiBJdCB3aWxsIF9ub3RfIHJlLWV2YWx1YXRlIGFscmVhZHkgaW5jbHVkZWQgZmVhdHVyZXMuXHJcbiAgXHQgKlxyXG4gIFx0ICogQG9wdGlvbiBjb29yZHNUb0xhdExuZzogRnVuY3Rpb24gPSAqXHJcbiAgXHQgKiBBIGBGdW5jdGlvbmAgdGhhdCB3aWxsIGJlIHVzZWQgZm9yIGNvbnZlcnRpbmcgR2VvSlNPTiBjb29yZGluYXRlcyB0byBgTGF0TG5nYHMuXHJcbiAgXHQgKiBUaGUgZGVmYXVsdCBpcyB0aGUgYGNvb3Jkc1RvTGF0TG5nYCBzdGF0aWMgbWV0aG9kLlxyXG4gIFx0ICpcclxuICBcdCAqIEBvcHRpb24gbWFya2Vyc0luaGVyaXRPcHRpb25zOiBCb29sZWFuID0gZmFsc2VcclxuICBcdCAqIFdoZXRoZXIgZGVmYXVsdCBNYXJrZXJzIGZvciBcIlBvaW50XCIgdHlwZSBGZWF0dXJlcyBpbmhlcml0IGZyb20gZ3JvdXAgb3B0aW9ucy5cclxuICBcdCAqL1xyXG5cclxuICBcdGluaXRpYWxpemU6IGZ1bmN0aW9uIChnZW9qc29uLCBvcHRpb25zKSB7XHJcbiAgXHRcdHNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XHJcblxyXG4gIFx0XHR0aGlzLl9sYXllcnMgPSB7fTtcclxuXHJcbiAgXHRcdGlmIChnZW9qc29uKSB7XHJcbiAgXHRcdFx0dGhpcy5hZGREYXRhKGdlb2pzb24pO1xyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgYWRkRGF0YSggPEdlb0pTT04+IGRhdGEgKTogdGhpc1xyXG4gIFx0Ly8gQWRkcyBhIEdlb0pTT04gb2JqZWN0IHRvIHRoZSBsYXllci5cclxuICBcdGFkZERhdGE6IGZ1bmN0aW9uIChnZW9qc29uKSB7XHJcbiAgXHRcdHZhciBmZWF0dXJlcyA9IGlzQXJyYXkoZ2VvanNvbikgPyBnZW9qc29uIDogZ2VvanNvbi5mZWF0dXJlcyxcclxuICBcdFx0ICAgIGksIGxlbiwgZmVhdHVyZTtcclxuXHJcbiAgXHRcdGlmIChmZWF0dXJlcykge1xyXG4gIFx0XHRcdGZvciAoaSA9IDAsIGxlbiA9IGZlYXR1cmVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdFx0XHQvLyBvbmx5IGFkZCB0aGlzIGlmIGdlb21ldHJ5IG9yIGdlb21ldHJpZXMgYXJlIHNldCBhbmQgbm90IG51bGxcclxuICBcdFx0XHRcdGZlYXR1cmUgPSBmZWF0dXJlc1tpXTtcclxuICBcdFx0XHRcdGlmIChmZWF0dXJlLmdlb21ldHJpZXMgfHwgZmVhdHVyZS5nZW9tZXRyeSB8fCBmZWF0dXJlLmZlYXR1cmVzIHx8IGZlYXR1cmUuY29vcmRpbmF0ZXMpIHtcclxuICBcdFx0XHRcdFx0dGhpcy5hZGREYXRhKGZlYXR1cmUpO1xyXG4gIFx0XHRcdFx0fVxyXG4gIFx0XHRcdH1cclxuICBcdFx0XHRyZXR1cm4gdGhpcztcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XHJcblxyXG4gIFx0XHRpZiAob3B0aW9ucy5maWx0ZXIgJiYgIW9wdGlvbnMuZmlsdGVyKGdlb2pzb24pKSB7IHJldHVybiB0aGlzOyB9XHJcblxyXG4gIFx0XHR2YXIgbGF5ZXIgPSBnZW9tZXRyeVRvTGF5ZXIoZ2VvanNvbiwgb3B0aW9ucyk7XHJcbiAgXHRcdGlmICghbGF5ZXIpIHtcclxuICBcdFx0XHRyZXR1cm4gdGhpcztcclxuICBcdFx0fVxyXG4gIFx0XHRsYXllci5mZWF0dXJlID0gYXNGZWF0dXJlKGdlb2pzb24pO1xyXG5cclxuICBcdFx0bGF5ZXIuZGVmYXVsdE9wdGlvbnMgPSBsYXllci5vcHRpb25zO1xyXG4gIFx0XHR0aGlzLnJlc2V0U3R5bGUobGF5ZXIpO1xyXG5cclxuICBcdFx0aWYgKG9wdGlvbnMub25FYWNoRmVhdHVyZSkge1xyXG4gIFx0XHRcdG9wdGlvbnMub25FYWNoRmVhdHVyZShnZW9qc29uLCBsYXllcik7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiB0aGlzLmFkZExheWVyKGxheWVyKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCByZXNldFN0eWxlKCA8UGF0aD4gbGF5ZXI/ICk6IHRoaXNcclxuICBcdC8vIFJlc2V0cyB0aGUgZ2l2ZW4gdmVjdG9yIGxheWVyJ3Mgc3R5bGUgdG8gdGhlIG9yaWdpbmFsIEdlb0pTT04gc3R5bGUsIHVzZWZ1bCBmb3IgcmVzZXR0aW5nIHN0eWxlIGFmdGVyIGhvdmVyIGV2ZW50cy5cclxuICBcdC8vIElmIGBsYXllcmAgaXMgb21pdHRlZCwgdGhlIHN0eWxlIG9mIGFsbCBmZWF0dXJlcyBpbiB0aGUgY3VycmVudCBsYXllciBpcyByZXNldC5cclxuICBcdHJlc2V0U3R5bGU6IGZ1bmN0aW9uIChsYXllcikge1xyXG4gIFx0XHRpZiAobGF5ZXIgPT09IHVuZGVmaW5lZCkge1xyXG4gIFx0XHRcdHJldHVybiB0aGlzLmVhY2hMYXllcih0aGlzLnJlc2V0U3R5bGUsIHRoaXMpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdC8vIHJlc2V0IGFueSBjdXN0b20gc3R5bGVzXHJcbiAgXHRcdGxheWVyLm9wdGlvbnMgPSBleHRlbmQoe30sIGxheWVyLmRlZmF1bHRPcHRpb25zKTtcclxuICBcdFx0dGhpcy5fc2V0TGF5ZXJTdHlsZShsYXllciwgdGhpcy5vcHRpb25zLnN0eWxlKTtcclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2V0U3R5bGUoIDxGdW5jdGlvbj4gc3R5bGUgKTogdGhpc1xyXG4gIFx0Ly8gQ2hhbmdlcyBzdHlsZXMgb2YgR2VvSlNPTiB2ZWN0b3IgbGF5ZXJzIHdpdGggdGhlIGdpdmVuIHN0eWxlIGZ1bmN0aW9uLlxyXG4gIFx0c2V0U3R5bGU6IGZ1bmN0aW9uIChzdHlsZSkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5lYWNoTGF5ZXIoZnVuY3Rpb24gKGxheWVyKSB7XHJcbiAgXHRcdFx0dGhpcy5fc2V0TGF5ZXJTdHlsZShsYXllciwgc3R5bGUpO1xyXG4gIFx0XHR9LCB0aGlzKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X3NldExheWVyU3R5bGU6IGZ1bmN0aW9uIChsYXllciwgc3R5bGUpIHtcclxuICBcdFx0aWYgKGxheWVyLnNldFN0eWxlKSB7XHJcbiAgXHRcdFx0aWYgKHR5cGVvZiBzdHlsZSA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gIFx0XHRcdFx0c3R5bGUgPSBzdHlsZShsYXllci5mZWF0dXJlKTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdFx0bGF5ZXIuc2V0U3R5bGUoc3R5bGUpO1xyXG4gIFx0XHR9XHJcbiAgXHR9XHJcbiAgfSk7XHJcblxyXG4gIC8vIEBzZWN0aW9uXHJcbiAgLy8gVGhlcmUgYXJlIHNldmVyYWwgc3RhdGljIGZ1bmN0aW9ucyB3aGljaCBjYW4gYmUgY2FsbGVkIHdpdGhvdXQgaW5zdGFudGlhdGluZyBMLkdlb0pTT046XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBnZW9tZXRyeVRvTGF5ZXIoZmVhdHVyZURhdGE6IE9iamVjdCwgb3B0aW9ucz86IEdlb0pTT04gb3B0aW9ucyk6IExheWVyXHJcbiAgLy8gQ3JlYXRlcyBhIGBMYXllcmAgZnJvbSBhIGdpdmVuIEdlb0pTT04gZmVhdHVyZS4gQ2FuIHVzZSBhIGN1c3RvbVxyXG4gIC8vIFtgcG9pbnRUb0xheWVyYF0oI2dlb2pzb24tcG9pbnR0b2xheWVyKSBhbmQvb3IgW2Bjb29yZHNUb0xhdExuZ2BdKCNnZW9qc29uLWNvb3Jkc3RvbGF0bG5nKVxyXG4gIC8vIGZ1bmN0aW9ucyBpZiBwcm92aWRlZCBhcyBvcHRpb25zLlxyXG4gIGZ1bmN0aW9uIGdlb21ldHJ5VG9MYXllcihnZW9qc29uLCBvcHRpb25zKSB7XHJcblxyXG4gIFx0dmFyIGdlb21ldHJ5ID0gZ2VvanNvbi50eXBlID09PSAnRmVhdHVyZScgPyBnZW9qc29uLmdlb21ldHJ5IDogZ2VvanNvbixcclxuICBcdCAgICBjb29yZHMgPSBnZW9tZXRyeSA/IGdlb21ldHJ5LmNvb3JkaW5hdGVzIDogbnVsbCxcclxuICBcdCAgICBsYXllcnMgPSBbXSxcclxuICBcdCAgICBwb2ludFRvTGF5ZXIgPSBvcHRpb25zICYmIG9wdGlvbnMucG9pbnRUb0xheWVyLFxyXG4gIFx0ICAgIF9jb29yZHNUb0xhdExuZyA9IG9wdGlvbnMgJiYgb3B0aW9ucy5jb29yZHNUb0xhdExuZyB8fCBjb29yZHNUb0xhdExuZyxcclxuICBcdCAgICBsYXRsbmcsIGxhdGxuZ3MsIGksIGxlbjtcclxuXHJcbiAgXHRpZiAoIWNvb3JkcyAmJiAhZ2VvbWV0cnkpIHtcclxuICBcdFx0cmV0dXJuIG51bGw7XHJcbiAgXHR9XHJcblxyXG4gIFx0c3dpdGNoIChnZW9tZXRyeS50eXBlKSB7XHJcbiAgXHRjYXNlICdQb2ludCc6XHJcbiAgXHRcdGxhdGxuZyA9IF9jb29yZHNUb0xhdExuZyhjb29yZHMpO1xyXG4gIFx0XHRyZXR1cm4gX3BvaW50VG9MYXllcihwb2ludFRvTGF5ZXIsIGdlb2pzb24sIGxhdGxuZywgb3B0aW9ucyk7XHJcblxyXG4gIFx0Y2FzZSAnTXVsdGlQb2ludCc6XHJcbiAgXHRcdGZvciAoaSA9IDAsIGxlbiA9IGNvb3Jkcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gIFx0XHRcdGxhdGxuZyA9IF9jb29yZHNUb0xhdExuZyhjb29yZHNbaV0pO1xyXG4gIFx0XHRcdGxheWVycy5wdXNoKF9wb2ludFRvTGF5ZXIocG9pbnRUb0xheWVyLCBnZW9qc29uLCBsYXRsbmcsIG9wdGlvbnMpKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gbmV3IEZlYXR1cmVHcm91cChsYXllcnMpO1xyXG5cclxuICBcdGNhc2UgJ0xpbmVTdHJpbmcnOlxyXG4gIFx0Y2FzZSAnTXVsdGlMaW5lU3RyaW5nJzpcclxuICBcdFx0bGF0bG5ncyA9IGNvb3Jkc1RvTGF0TG5ncyhjb29yZHMsIGdlb21ldHJ5LnR5cGUgPT09ICdMaW5lU3RyaW5nJyA/IDAgOiAxLCBfY29vcmRzVG9MYXRMbmcpO1xyXG4gIFx0XHRyZXR1cm4gbmV3IFBvbHlsaW5lKGxhdGxuZ3MsIG9wdGlvbnMpO1xyXG5cclxuICBcdGNhc2UgJ1BvbHlnb24nOlxyXG4gIFx0Y2FzZSAnTXVsdGlQb2x5Z29uJzpcclxuICBcdFx0bGF0bG5ncyA9IGNvb3Jkc1RvTGF0TG5ncyhjb29yZHMsIGdlb21ldHJ5LnR5cGUgPT09ICdQb2x5Z29uJyA/IDEgOiAyLCBfY29vcmRzVG9MYXRMbmcpO1xyXG4gIFx0XHRyZXR1cm4gbmV3IFBvbHlnb24obGF0bG5ncywgb3B0aW9ucyk7XHJcblxyXG4gIFx0Y2FzZSAnR2VvbWV0cnlDb2xsZWN0aW9uJzpcclxuICBcdFx0Zm9yIChpID0gMCwgbGVuID0gZ2VvbWV0cnkuZ2VvbWV0cmllcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gIFx0XHRcdHZhciBnZW9MYXllciA9IGdlb21ldHJ5VG9MYXllcih7XHJcbiAgXHRcdFx0XHRnZW9tZXRyeTogZ2VvbWV0cnkuZ2VvbWV0cmllc1tpXSxcclxuICBcdFx0XHRcdHR5cGU6ICdGZWF0dXJlJyxcclxuICBcdFx0XHRcdHByb3BlcnRpZXM6IGdlb2pzb24ucHJvcGVydGllc1xyXG4gIFx0XHRcdH0sIG9wdGlvbnMpO1xyXG5cclxuICBcdFx0XHRpZiAoZ2VvTGF5ZXIpIHtcclxuICBcdFx0XHRcdGxheWVycy5wdXNoKGdlb0xheWVyKTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIG5ldyBGZWF0dXJlR3JvdXAobGF5ZXJzKTtcclxuXHJcbiAgXHRjYXNlICdGZWF0dXJlQ29sbGVjdGlvbic6XHJcbiAgXHRcdGZvciAoaSA9IDAsIGxlbiA9IGdlb21ldHJ5LmZlYXR1cmVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdFx0dmFyIGZlYXR1cmVMYXllciA9IGdlb21ldHJ5VG9MYXllcihnZW9tZXRyeS5mZWF0dXJlc1tpXSwgb3B0aW9ucyk7XHJcblxyXG4gIFx0XHRcdGlmIChmZWF0dXJlTGF5ZXIpIHtcclxuICBcdFx0XHRcdGxheWVycy5wdXNoKGZlYXR1cmVMYXllcik7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiBuZXcgRmVhdHVyZUdyb3VwKGxheWVycyk7XHJcblxyXG4gIFx0ZGVmYXVsdDpcclxuICBcdFx0dGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIEdlb0pTT04gb2JqZWN0LicpO1xyXG4gIFx0fVxyXG4gIH1cclxuXHJcbiAgZnVuY3Rpb24gX3BvaW50VG9MYXllcihwb2ludFRvTGF5ZXJGbiwgZ2VvanNvbiwgbGF0bG5nLCBvcHRpb25zKSB7XHJcbiAgXHRyZXR1cm4gcG9pbnRUb0xheWVyRm4gP1xyXG4gIFx0XHRwb2ludFRvTGF5ZXJGbihnZW9qc29uLCBsYXRsbmcpIDpcclxuICBcdFx0bmV3IE1hcmtlcihsYXRsbmcsIG9wdGlvbnMgJiYgb3B0aW9ucy5tYXJrZXJzSW5oZXJpdE9wdGlvbnMgJiYgb3B0aW9ucyk7XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gY29vcmRzVG9MYXRMbmcoY29vcmRzOiBBcnJheSk6IExhdExuZ1xyXG4gIC8vIENyZWF0ZXMgYSBgTGF0TG5nYCBvYmplY3QgZnJvbSBhbiBhcnJheSBvZiAyIG51bWJlcnMgKGxvbmdpdHVkZSwgbGF0aXR1ZGUpXHJcbiAgLy8gb3IgMyBudW1iZXJzIChsb25naXR1ZGUsIGxhdGl0dWRlLCBhbHRpdHVkZSkgdXNlZCBpbiBHZW9KU09OIGZvciBwb2ludHMuXHJcbiAgZnVuY3Rpb24gY29vcmRzVG9MYXRMbmcoY29vcmRzKSB7XHJcbiAgXHRyZXR1cm4gbmV3IExhdExuZyhjb29yZHNbMV0sIGNvb3Jkc1swXSwgY29vcmRzWzJdKTtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBjb29yZHNUb0xhdExuZ3MoY29vcmRzOiBBcnJheSwgbGV2ZWxzRGVlcD86IE51bWJlciwgY29vcmRzVG9MYXRMbmc/OiBGdW5jdGlvbik6IEFycmF5XHJcbiAgLy8gQ3JlYXRlcyBhIG11bHRpZGltZW5zaW9uYWwgYXJyYXkgb2YgYExhdExuZ2BzIGZyb20gYSBHZW9KU09OIGNvb3JkaW5hdGVzIGFycmF5LlxyXG4gIC8vIGBsZXZlbHNEZWVwYCBzcGVjaWZpZXMgdGhlIG5lc3RpbmcgbGV2ZWwgKDAgaXMgZm9yIGFuIGFycmF5IG9mIHBvaW50cywgMSBmb3IgYW4gYXJyYXkgb2YgYXJyYXlzIG9mIHBvaW50cywgZXRjLiwgMCBieSBkZWZhdWx0KS5cclxuICAvLyBDYW4gdXNlIGEgY3VzdG9tIFtgY29vcmRzVG9MYXRMbmdgXSgjZ2VvanNvbi1jb29yZHN0b2xhdGxuZykgZnVuY3Rpb24uXHJcbiAgZnVuY3Rpb24gY29vcmRzVG9MYXRMbmdzKGNvb3JkcywgbGV2ZWxzRGVlcCwgX2Nvb3Jkc1RvTGF0TG5nKSB7XHJcbiAgXHR2YXIgbGF0bG5ncyA9IFtdO1xyXG5cclxuICBcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBjb29yZHMubGVuZ3RoLCBsYXRsbmc7IGkgPCBsZW47IGkrKykge1xyXG4gIFx0XHRsYXRsbmcgPSBsZXZlbHNEZWVwID9cclxuICBcdFx0XHRjb29yZHNUb0xhdExuZ3MoY29vcmRzW2ldLCBsZXZlbHNEZWVwIC0gMSwgX2Nvb3Jkc1RvTGF0TG5nKSA6XHJcbiAgXHRcdFx0KF9jb29yZHNUb0xhdExuZyB8fCBjb29yZHNUb0xhdExuZykoY29vcmRzW2ldKTtcclxuXHJcbiAgXHRcdGxhdGxuZ3MucHVzaChsYXRsbmcpO1xyXG4gIFx0fVxyXG5cclxuICBcdHJldHVybiBsYXRsbmdzO1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGxhdExuZ1RvQ29vcmRzKGxhdGxuZzogTGF0TG5nLCBwcmVjaXNpb24/OiBOdW1iZXJ8ZmFsc2UpOiBBcnJheVxyXG4gIC8vIFJldmVyc2Ugb2YgW2Bjb29yZHNUb0xhdExuZ2BdKCNnZW9qc29uLWNvb3Jkc3RvbGF0bG5nKVxyXG4gIC8vIENvb3JkaW5hdGVzIHZhbHVlcyBhcmUgcm91bmRlZCB3aXRoIFtgZm9ybWF0TnVtYF0oI3V0aWwtZm9ybWF0bnVtKSBmdW5jdGlvbi5cclxuICBmdW5jdGlvbiBsYXRMbmdUb0Nvb3JkcyhsYXRsbmcsIHByZWNpc2lvbikge1xyXG4gIFx0bGF0bG5nID0gdG9MYXRMbmcobGF0bG5nKTtcclxuICBcdHJldHVybiBsYXRsbmcuYWx0ICE9PSB1bmRlZmluZWQgP1xyXG4gIFx0XHRbZm9ybWF0TnVtKGxhdGxuZy5sbmcsIHByZWNpc2lvbiksIGZvcm1hdE51bShsYXRsbmcubGF0LCBwcmVjaXNpb24pLCBmb3JtYXROdW0obGF0bG5nLmFsdCwgcHJlY2lzaW9uKV0gOlxyXG4gIFx0XHRbZm9ybWF0TnVtKGxhdGxuZy5sbmcsIHByZWNpc2lvbiksIGZvcm1hdE51bShsYXRsbmcubGF0LCBwcmVjaXNpb24pXTtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBsYXRMbmdzVG9Db29yZHMobGF0bG5nczogQXJyYXksIGxldmVsc0RlZXA/OiBOdW1iZXIsIGNsb3NlZD86IEJvb2xlYW4sIHByZWNpc2lvbj86IE51bWJlcnxmYWxzZSk6IEFycmF5XHJcbiAgLy8gUmV2ZXJzZSBvZiBbYGNvb3Jkc1RvTGF0TG5nc2BdKCNnZW9qc29uLWNvb3Jkc3RvbGF0bG5ncylcclxuICAvLyBgY2xvc2VkYCBkZXRlcm1pbmVzIHdoZXRoZXIgdGhlIGZpcnN0IHBvaW50IHNob3VsZCBiZSBhcHBlbmRlZCB0byB0aGUgZW5kIG9mIHRoZSBhcnJheSB0byBjbG9zZSB0aGUgZmVhdHVyZSwgb25seSB1c2VkIHdoZW4gYGxldmVsc0RlZXBgIGlzIDAuIEZhbHNlIGJ5IGRlZmF1bHQuXHJcbiAgLy8gQ29vcmRpbmF0ZXMgdmFsdWVzIGFyZSByb3VuZGVkIHdpdGggW2Bmb3JtYXROdW1gXSgjdXRpbC1mb3JtYXRudW0pIGZ1bmN0aW9uLlxyXG4gIGZ1bmN0aW9uIGxhdExuZ3NUb0Nvb3JkcyhsYXRsbmdzLCBsZXZlbHNEZWVwLCBjbG9zZWQsIHByZWNpc2lvbikge1xyXG4gIFx0dmFyIGNvb3JkcyA9IFtdO1xyXG5cclxuICBcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBsYXRsbmdzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdC8vIENoZWNrIGZvciBmbGF0IGFycmF5cyByZXF1aXJlZCB0byBlbnN1cmUgdW5iYWxhbmNlZCBhcnJheXMgYXJlIGNvcnJlY3RseSBjb252ZXJ0ZWQgaW4gcmVjdXJzaW9uXHJcbiAgXHRcdGNvb3Jkcy5wdXNoKGxldmVsc0RlZXAgP1xyXG4gIFx0XHRcdGxhdExuZ3NUb0Nvb3JkcyhsYXRsbmdzW2ldLCBpc0ZsYXQobGF0bG5nc1tpXSkgPyAwIDogbGV2ZWxzRGVlcCAtIDEsIGNsb3NlZCwgcHJlY2lzaW9uKSA6XHJcbiAgXHRcdFx0bGF0TG5nVG9Db29yZHMobGF0bG5nc1tpXSwgcHJlY2lzaW9uKSk7XHJcbiAgXHR9XHJcblxyXG4gIFx0aWYgKCFsZXZlbHNEZWVwICYmIGNsb3NlZCAmJiBjb29yZHMubGVuZ3RoID4gMCkge1xyXG4gIFx0XHRjb29yZHMucHVzaChjb29yZHNbMF0uc2xpY2UoKSk7XHJcbiAgXHR9XHJcblxyXG4gIFx0cmV0dXJuIGNvb3JkcztcclxuICB9XHJcblxyXG4gIGZ1bmN0aW9uIGdldEZlYXR1cmUobGF5ZXIsIG5ld0dlb21ldHJ5KSB7XHJcbiAgXHRyZXR1cm4gbGF5ZXIuZmVhdHVyZSA/XHJcbiAgXHRcdGV4dGVuZCh7fSwgbGF5ZXIuZmVhdHVyZSwge2dlb21ldHJ5OiBuZXdHZW9tZXRyeX0pIDpcclxuICBcdFx0YXNGZWF0dXJlKG5ld0dlb21ldHJ5KTtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBhc0ZlYXR1cmUoZ2VvanNvbjogT2JqZWN0KTogT2JqZWN0XHJcbiAgLy8gTm9ybWFsaXplIEdlb0pTT04gZ2VvbWV0cmllcy9mZWF0dXJlcyBpbnRvIEdlb0pTT04gZmVhdHVyZXMuXHJcbiAgZnVuY3Rpb24gYXNGZWF0dXJlKGdlb2pzb24pIHtcclxuICBcdGlmIChnZW9qc29uLnR5cGUgPT09ICdGZWF0dXJlJyB8fCBnZW9qc29uLnR5cGUgPT09ICdGZWF0dXJlQ29sbGVjdGlvbicpIHtcclxuICBcdFx0cmV0dXJuIGdlb2pzb247XHJcbiAgXHR9XHJcblxyXG4gIFx0cmV0dXJuIHtcclxuICBcdFx0dHlwZTogJ0ZlYXR1cmUnLFxyXG4gIFx0XHRwcm9wZXJ0aWVzOiB7fSxcclxuICBcdFx0Z2VvbWV0cnk6IGdlb2pzb25cclxuICBcdH07XHJcbiAgfVxyXG5cclxuICB2YXIgUG9pbnRUb0dlb0pTT04gPSB7XHJcbiAgXHR0b0dlb0pTT046IGZ1bmN0aW9uIChwcmVjaXNpb24pIHtcclxuICBcdFx0cmV0dXJuIGdldEZlYXR1cmUodGhpcywge1xyXG4gIFx0XHRcdHR5cGU6ICdQb2ludCcsXHJcbiAgXHRcdFx0Y29vcmRpbmF0ZXM6IGxhdExuZ1RvQ29vcmRzKHRoaXMuZ2V0TGF0TG5nKCksIHByZWNpc2lvbilcclxuICBcdFx0fSk7XHJcbiAgXHR9XHJcbiAgfTtcclxuXHJcbiAgLy8gQG5hbWVzcGFjZSBNYXJrZXJcclxuICAvLyBAc2VjdGlvbiBPdGhlciBtZXRob2RzXHJcbiAgLy8gQG1ldGhvZCB0b0dlb0pTT04ocHJlY2lzaW9uPzogTnVtYmVyfGZhbHNlKTogT2JqZWN0XHJcbiAgLy8gQ29vcmRpbmF0ZXMgdmFsdWVzIGFyZSByb3VuZGVkIHdpdGggW2Bmb3JtYXROdW1gXSgjdXRpbC1mb3JtYXRudW0pIGZ1bmN0aW9uIHdpdGggZ2l2ZW4gYHByZWNpc2lvbmAuXHJcbiAgLy8gUmV0dXJucyBhIFtgR2VvSlNPTmBdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0dlb0pTT04pIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBtYXJrZXIgKGFzIGEgR2VvSlNPTiBgUG9pbnRgIEZlYXR1cmUpLlxyXG4gIE1hcmtlci5pbmNsdWRlKFBvaW50VG9HZW9KU09OKTtcclxuXHJcbiAgLy8gQG5hbWVzcGFjZSBDaXJjbGVNYXJrZXJcclxuICAvLyBAbWV0aG9kIHRvR2VvSlNPTihwcmVjaXNpb24/OiBOdW1iZXJ8ZmFsc2UpOiBPYmplY3RcclxuICAvLyBDb29yZGluYXRlcyB2YWx1ZXMgYXJlIHJvdW5kZWQgd2l0aCBbYGZvcm1hdE51bWBdKCN1dGlsLWZvcm1hdG51bSkgZnVuY3Rpb24gd2l0aCBnaXZlbiBgcHJlY2lzaW9uYC5cclxuICAvLyBSZXR1cm5zIGEgW2BHZW9KU09OYF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvR2VvSlNPTikgcmVwcmVzZW50YXRpb24gb2YgdGhlIGNpcmNsZSBtYXJrZXIgKGFzIGEgR2VvSlNPTiBgUG9pbnRgIEZlYXR1cmUpLlxyXG4gIENpcmNsZS5pbmNsdWRlKFBvaW50VG9HZW9KU09OKTtcclxuICBDaXJjbGVNYXJrZXIuaW5jbHVkZShQb2ludFRvR2VvSlNPTik7XHJcblxyXG5cclxuICAvLyBAbmFtZXNwYWNlIFBvbHlsaW5lXHJcbiAgLy8gQG1ldGhvZCB0b0dlb0pTT04ocHJlY2lzaW9uPzogTnVtYmVyfGZhbHNlKTogT2JqZWN0XHJcbiAgLy8gQ29vcmRpbmF0ZXMgdmFsdWVzIGFyZSByb3VuZGVkIHdpdGggW2Bmb3JtYXROdW1gXSgjdXRpbC1mb3JtYXRudW0pIGZ1bmN0aW9uIHdpdGggZ2l2ZW4gYHByZWNpc2lvbmAuXHJcbiAgLy8gUmV0dXJucyBhIFtgR2VvSlNPTmBdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0dlb0pTT04pIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBwb2x5bGluZSAoYXMgYSBHZW9KU09OIGBMaW5lU3RyaW5nYCBvciBgTXVsdGlMaW5lU3RyaW5nYCBGZWF0dXJlKS5cclxuICBQb2x5bGluZS5pbmNsdWRlKHtcclxuICBcdHRvR2VvSlNPTjogZnVuY3Rpb24gKHByZWNpc2lvbikge1xyXG4gIFx0XHR2YXIgbXVsdGkgPSAhaXNGbGF0KHRoaXMuX2xhdGxuZ3MpO1xyXG5cclxuICBcdFx0dmFyIGNvb3JkcyA9IGxhdExuZ3NUb0Nvb3Jkcyh0aGlzLl9sYXRsbmdzLCBtdWx0aSA/IDEgOiAwLCBmYWxzZSwgcHJlY2lzaW9uKTtcclxuXHJcbiAgXHRcdHJldHVybiBnZXRGZWF0dXJlKHRoaXMsIHtcclxuICBcdFx0XHR0eXBlOiAobXVsdGkgPyAnTXVsdGknIDogJycpICsgJ0xpbmVTdHJpbmcnLFxyXG4gIFx0XHRcdGNvb3JkaW5hdGVzOiBjb29yZHNcclxuICBcdFx0fSk7XHJcbiAgXHR9XHJcbiAgfSk7XHJcblxyXG4gIC8vIEBuYW1lc3BhY2UgUG9seWdvblxyXG4gIC8vIEBtZXRob2QgdG9HZW9KU09OKHByZWNpc2lvbj86IE51bWJlcnxmYWxzZSk6IE9iamVjdFxyXG4gIC8vIENvb3JkaW5hdGVzIHZhbHVlcyBhcmUgcm91bmRlZCB3aXRoIFtgZm9ybWF0TnVtYF0oI3V0aWwtZm9ybWF0bnVtKSBmdW5jdGlvbiB3aXRoIGdpdmVuIGBwcmVjaXNpb25gLlxyXG4gIC8vIFJldHVybnMgYSBbYEdlb0pTT05gXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9HZW9KU09OKSByZXByZXNlbnRhdGlvbiBvZiB0aGUgcG9seWdvbiAoYXMgYSBHZW9KU09OIGBQb2x5Z29uYCBvciBgTXVsdGlQb2x5Z29uYCBGZWF0dXJlKS5cclxuICBQb2x5Z29uLmluY2x1ZGUoe1xyXG4gIFx0dG9HZW9KU09OOiBmdW5jdGlvbiAocHJlY2lzaW9uKSB7XHJcbiAgXHRcdHZhciBob2xlcyA9ICFpc0ZsYXQodGhpcy5fbGF0bG5ncyksXHJcbiAgXHRcdCAgICBtdWx0aSA9IGhvbGVzICYmICFpc0ZsYXQodGhpcy5fbGF0bG5nc1swXSk7XHJcblxyXG4gIFx0XHR2YXIgY29vcmRzID0gbGF0TG5nc1RvQ29vcmRzKHRoaXMuX2xhdGxuZ3MsIG11bHRpID8gMiA6IGhvbGVzID8gMSA6IDAsIHRydWUsIHByZWNpc2lvbik7XHJcblxyXG4gIFx0XHRpZiAoIWhvbGVzKSB7XHJcbiAgXHRcdFx0Y29vcmRzID0gW2Nvb3Jkc107XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiBnZXRGZWF0dXJlKHRoaXMsIHtcclxuICBcdFx0XHR0eXBlOiAobXVsdGkgPyAnTXVsdGknIDogJycpICsgJ1BvbHlnb24nLFxyXG4gIFx0XHRcdGNvb3JkaW5hdGVzOiBjb29yZHNcclxuICBcdFx0fSk7XHJcbiAgXHR9XHJcbiAgfSk7XHJcblxyXG5cclxuICAvLyBAbmFtZXNwYWNlIExheWVyR3JvdXBcclxuICBMYXllckdyb3VwLmluY2x1ZGUoe1xyXG4gIFx0dG9NdWx0aVBvaW50OiBmdW5jdGlvbiAocHJlY2lzaW9uKSB7XHJcbiAgXHRcdHZhciBjb29yZHMgPSBbXTtcclxuXHJcbiAgXHRcdHRoaXMuZWFjaExheWVyKGZ1bmN0aW9uIChsYXllcikge1xyXG4gIFx0XHRcdGNvb3Jkcy5wdXNoKGxheWVyLnRvR2VvSlNPTihwcmVjaXNpb24pLmdlb21ldHJ5LmNvb3JkaW5hdGVzKTtcclxuICBcdFx0fSk7XHJcblxyXG4gIFx0XHRyZXR1cm4gZ2V0RmVhdHVyZSh0aGlzLCB7XHJcbiAgXHRcdFx0dHlwZTogJ011bHRpUG9pbnQnLFxyXG4gIFx0XHRcdGNvb3JkaW5hdGVzOiBjb29yZHNcclxuICBcdFx0fSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgdG9HZW9KU09OKHByZWNpc2lvbj86IE51bWJlcnxmYWxzZSk6IE9iamVjdFxyXG4gIFx0Ly8gQ29vcmRpbmF0ZXMgdmFsdWVzIGFyZSByb3VuZGVkIHdpdGggW2Bmb3JtYXROdW1gXSgjdXRpbC1mb3JtYXRudW0pIGZ1bmN0aW9uIHdpdGggZ2l2ZW4gYHByZWNpc2lvbmAuXHJcbiAgXHQvLyBSZXR1cm5zIGEgW2BHZW9KU09OYF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvR2VvSlNPTikgcmVwcmVzZW50YXRpb24gb2YgdGhlIGxheWVyIGdyb3VwIChhcyBhIEdlb0pTT04gYEZlYXR1cmVDb2xsZWN0aW9uYCwgYEdlb21ldHJ5Q29sbGVjdGlvbmAsIG9yIGBNdWx0aVBvaW50YCkuXHJcbiAgXHR0b0dlb0pTT046IGZ1bmN0aW9uIChwcmVjaXNpb24pIHtcclxuXHJcbiAgXHRcdHZhciB0eXBlID0gdGhpcy5mZWF0dXJlICYmIHRoaXMuZmVhdHVyZS5nZW9tZXRyeSAmJiB0aGlzLmZlYXR1cmUuZ2VvbWV0cnkudHlwZTtcclxuXHJcbiAgXHRcdGlmICh0eXBlID09PSAnTXVsdGlQb2ludCcpIHtcclxuICBcdFx0XHRyZXR1cm4gdGhpcy50b011bHRpUG9pbnQocHJlY2lzaW9uKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dmFyIGlzR2VvbWV0cnlDb2xsZWN0aW9uID0gdHlwZSA9PT0gJ0dlb21ldHJ5Q29sbGVjdGlvbicsXHJcbiAgXHRcdCAgICBqc29ucyA9IFtdO1xyXG5cclxuICBcdFx0dGhpcy5lYWNoTGF5ZXIoZnVuY3Rpb24gKGxheWVyKSB7XHJcbiAgXHRcdFx0aWYgKGxheWVyLnRvR2VvSlNPTikge1xyXG4gIFx0XHRcdFx0dmFyIGpzb24gPSBsYXllci50b0dlb0pTT04ocHJlY2lzaW9uKTtcclxuICBcdFx0XHRcdGlmIChpc0dlb21ldHJ5Q29sbGVjdGlvbikge1xyXG4gIFx0XHRcdFx0XHRqc29ucy5wdXNoKGpzb24uZ2VvbWV0cnkpO1xyXG4gIFx0XHRcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRcdFx0dmFyIGZlYXR1cmUgPSBhc0ZlYXR1cmUoanNvbik7XHJcbiAgXHRcdFx0XHRcdC8vIFNxdWFzaCBuZXN0ZWQgZmVhdHVyZSBjb2xsZWN0aW9uc1xyXG4gIFx0XHRcdFx0XHRpZiAoZmVhdHVyZS50eXBlID09PSAnRmVhdHVyZUNvbGxlY3Rpb24nKSB7XHJcbiAgXHRcdFx0XHRcdFx0anNvbnMucHVzaC5hcHBseShqc29ucywgZmVhdHVyZS5mZWF0dXJlcyk7XHJcbiAgXHRcdFx0XHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0XHRcdFx0anNvbnMucHVzaChmZWF0dXJlKTtcclxuICBcdFx0XHRcdFx0fVxyXG4gIFx0XHRcdFx0fVxyXG4gIFx0XHRcdH1cclxuICBcdFx0fSk7XHJcblxyXG4gIFx0XHRpZiAoaXNHZW9tZXRyeUNvbGxlY3Rpb24pIHtcclxuICBcdFx0XHRyZXR1cm4gZ2V0RmVhdHVyZSh0aGlzLCB7XHJcbiAgXHRcdFx0XHRnZW9tZXRyaWVzOiBqc29ucyxcclxuICBcdFx0XHRcdHR5cGU6ICdHZW9tZXRyeUNvbGxlY3Rpb24nXHJcbiAgXHRcdFx0fSk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiB7XHJcbiAgXHRcdFx0dHlwZTogJ0ZlYXR1cmVDb2xsZWN0aW9uJyxcclxuICBcdFx0XHRmZWF0dXJlczoganNvbnNcclxuICBcdFx0fTtcclxuICBcdH1cclxuICB9KTtcclxuXHJcbiAgLy8gQG5hbWVzcGFjZSBHZW9KU09OXHJcbiAgLy8gQGZhY3RvcnkgTC5nZW9KU09OKGdlb2pzb24/OiBPYmplY3QsIG9wdGlvbnM/OiBHZW9KU09OIG9wdGlvbnMpXHJcbiAgLy8gQ3JlYXRlcyBhIEdlb0pTT04gbGF5ZXIuIE9wdGlvbmFsbHkgYWNjZXB0cyBhbiBvYmplY3QgaW5cclxuICAvLyBbR2VvSlNPTiBmb3JtYXRdKGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmM3OTQ2KSB0byBkaXNwbGF5IG9uIHRoZSBtYXBcclxuICAvLyAoeW91IGNhbiBhbHRlcm5hdGl2ZWx5IGFkZCBpdCBsYXRlciB3aXRoIGBhZGREYXRhYCBtZXRob2QpIGFuZCBhbiBgb3B0aW9uc2Agb2JqZWN0LlxyXG4gIGZ1bmN0aW9uIGdlb0pTT04oZ2VvanNvbiwgb3B0aW9ucykge1xyXG4gIFx0cmV0dXJuIG5ldyBHZW9KU09OKGdlb2pzb24sIG9wdGlvbnMpO1xyXG4gIH1cclxuXHJcbiAgLy8gQmFja3dhcmQgY29tcGF0aWJpbGl0eS5cclxuICB2YXIgZ2VvSnNvbiA9IGdlb0pTT047XG5cbiAgLypcclxuICAgKiBAY2xhc3MgSW1hZ2VPdmVybGF5XHJcbiAgICogQGFrYSBMLkltYWdlT3ZlcmxheVxyXG4gICAqIEBpbmhlcml0cyBJbnRlcmFjdGl2ZSBsYXllclxyXG4gICAqXHJcbiAgICogVXNlZCB0byBsb2FkIGFuZCBkaXNwbGF5IGEgc2luZ2xlIGltYWdlIG92ZXIgc3BlY2lmaWMgYm91bmRzIG9mIHRoZSBtYXAuIEV4dGVuZHMgYExheWVyYC5cclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICpcclxuICAgKiBgYGBqc1xyXG4gICAqIHZhciBpbWFnZVVybCA9ICdodHRwczovL21hcHMubGliLnV0ZXhhcy5lZHUvbWFwcy9oaXN0b3JpY2FsL25ld2Fya19ual8xOTIyLmpwZycsXHJcbiAgICogXHRpbWFnZUJvdW5kcyA9IFtbNDAuNzEyMjE2LCAtNzQuMjI2NTVdLCBbNDAuNzczOTQxLCAtNzQuMTI1NDRdXTtcclxuICAgKiBMLmltYWdlT3ZlcmxheShpbWFnZVVybCwgaW1hZ2VCb3VuZHMpLmFkZFRvKG1hcCk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcblxyXG4gIHZhciBJbWFnZU92ZXJsYXkgPSBMYXllci5leHRlbmQoe1xyXG5cclxuICBcdC8vIEBzZWN0aW9uXHJcbiAgXHQvLyBAYWthIEltYWdlT3ZlcmxheSBvcHRpb25zXHJcbiAgXHRvcHRpb25zOiB7XHJcbiAgXHRcdC8vIEBvcHRpb24gb3BhY2l0eTogTnVtYmVyID0gMS4wXHJcbiAgXHRcdC8vIFRoZSBvcGFjaXR5IG9mIHRoZSBpbWFnZSBvdmVybGF5LlxyXG4gIFx0XHRvcGFjaXR5OiAxLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBhbHQ6IFN0cmluZyA9ICcnXHJcbiAgXHRcdC8vIFRleHQgZm9yIHRoZSBgYWx0YCBhdHRyaWJ1dGUgb2YgdGhlIGltYWdlICh1c2VmdWwgZm9yIGFjY2Vzc2liaWxpdHkpLlxyXG4gIFx0XHRhbHQ6ICcnLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBpbnRlcmFjdGl2ZTogQm9vbGVhbiA9IGZhbHNlXHJcbiAgXHRcdC8vIElmIGB0cnVlYCwgdGhlIGltYWdlIG92ZXJsYXkgd2lsbCBlbWl0IFttb3VzZSBldmVudHNdKCNpbnRlcmFjdGl2ZS1sYXllcikgd2hlbiBjbGlja2VkIG9yIGhvdmVyZWQuXHJcbiAgXHRcdGludGVyYWN0aXZlOiBmYWxzZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gY3Jvc3NPcmlnaW46IEJvb2xlYW58U3RyaW5nID0gZmFsc2VcclxuICBcdFx0Ly8gV2hldGhlciB0aGUgY3Jvc3NPcmlnaW4gYXR0cmlidXRlIHdpbGwgYmUgYWRkZWQgdG8gdGhlIGltYWdlLlxyXG4gIFx0XHQvLyBJZiBhIFN0cmluZyBpcyBwcm92aWRlZCwgdGhlIGltYWdlIHdpbGwgaGF2ZSBpdHMgY3Jvc3NPcmlnaW4gYXR0cmlidXRlIHNldCB0byB0aGUgU3RyaW5nIHByb3ZpZGVkLiBUaGlzIGlzIG5lZWRlZCBpZiB5b3Ugd2FudCB0byBhY2Nlc3MgaW1hZ2UgcGl4ZWwgZGF0YS5cclxuICBcdFx0Ly8gUmVmZXIgdG8gW0NPUlMgU2V0dGluZ3NdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0hUTUwvQ09SU19zZXR0aW5nc19hdHRyaWJ1dGVzKSBmb3IgdmFsaWQgU3RyaW5nIHZhbHVlcy5cclxuICBcdFx0Y3Jvc3NPcmlnaW46IGZhbHNlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBlcnJvck92ZXJsYXlVcmw6IFN0cmluZyA9ICcnXHJcbiAgXHRcdC8vIFVSTCB0byB0aGUgb3ZlcmxheSBpbWFnZSB0byBzaG93IGluIHBsYWNlIG9mIHRoZSBvdmVybGF5IHRoYXQgZmFpbGVkIHRvIGxvYWQuXHJcbiAgXHRcdGVycm9yT3ZlcmxheVVybDogJycsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHpJbmRleDogTnVtYmVyID0gMVxyXG4gIFx0XHQvLyBUaGUgZXhwbGljaXQgW3pJbmRleF0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQ1NTL0NTU19Qb3NpdGlvbmluZy9VbmRlcnN0YW5kaW5nX3pfaW5kZXgpIG9mIHRoZSBvdmVybGF5IGxheWVyLlxyXG4gIFx0XHR6SW5kZXg6IDEsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIGNsYXNzTmFtZTogU3RyaW5nID0gJydcclxuICBcdFx0Ly8gQSBjdXN0b20gY2xhc3MgbmFtZSB0byBhc3NpZ24gdG8gdGhlIGltYWdlLiBFbXB0eSBieSBkZWZhdWx0LlxyXG4gIFx0XHRjbGFzc05hbWU6ICcnXHJcbiAgXHR9LFxyXG5cclxuICBcdGluaXRpYWxpemU6IGZ1bmN0aW9uICh1cmwsIGJvdW5kcywgb3B0aW9ucykgeyAvLyAoU3RyaW5nLCBMYXRMbmdCb3VuZHMsIE9iamVjdClcclxuICBcdFx0dGhpcy5fdXJsID0gdXJsO1xyXG4gIFx0XHR0aGlzLl9ib3VuZHMgPSB0b0xhdExuZ0JvdW5kcyhib3VuZHMpO1xyXG5cclxuICBcdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcclxuICBcdH0sXHJcblxyXG4gIFx0b25BZGQ6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKCF0aGlzLl9pbWFnZSkge1xyXG4gIFx0XHRcdHRoaXMuX2luaXRJbWFnZSgpO1xyXG5cclxuICBcdFx0XHRpZiAodGhpcy5vcHRpb25zLm9wYWNpdHkgPCAxKSB7XHJcbiAgXHRcdFx0XHR0aGlzLl91cGRhdGVPcGFjaXR5KCk7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAodGhpcy5vcHRpb25zLmludGVyYWN0aXZlKSB7XHJcbiAgXHRcdFx0YWRkQ2xhc3ModGhpcy5faW1hZ2UsICdsZWFmbGV0LWludGVyYWN0aXZlJyk7XHJcbiAgXHRcdFx0dGhpcy5hZGRJbnRlcmFjdGl2ZVRhcmdldCh0aGlzLl9pbWFnZSk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuZ2V0UGFuZSgpLmFwcGVuZENoaWxkKHRoaXMuX2ltYWdlKTtcclxuICBcdFx0dGhpcy5fcmVzZXQoKTtcclxuICBcdH0sXHJcblxyXG4gIFx0b25SZW1vdmU6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmVtb3ZlKHRoaXMuX2ltYWdlKTtcclxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5pbnRlcmFjdGl2ZSkge1xyXG4gIFx0XHRcdHRoaXMucmVtb3ZlSW50ZXJhY3RpdmVUYXJnZXQodGhpcy5faW1hZ2UpO1xyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2V0T3BhY2l0eShvcGFjaXR5OiBOdW1iZXIpOiB0aGlzXHJcbiAgXHQvLyBTZXRzIHRoZSBvcGFjaXR5IG9mIHRoZSBvdmVybGF5LlxyXG4gIFx0c2V0T3BhY2l0eTogZnVuY3Rpb24gKG9wYWNpdHkpIHtcclxuICBcdFx0dGhpcy5vcHRpb25zLm9wYWNpdHkgPSBvcGFjaXR5O1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX2ltYWdlKSB7XHJcbiAgXHRcdFx0dGhpcy5fdXBkYXRlT3BhY2l0eSgpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRzZXRTdHlsZTogZnVuY3Rpb24gKHN0eWxlT3B0cykge1xyXG4gIFx0XHRpZiAoc3R5bGVPcHRzLm9wYWNpdHkpIHtcclxuICBcdFx0XHR0aGlzLnNldE9wYWNpdHkoc3R5bGVPcHRzLm9wYWNpdHkpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGJyaW5nVG9Gcm9udCgpOiB0aGlzXHJcbiAgXHQvLyBCcmluZ3MgdGhlIGxheWVyIHRvIHRoZSB0b3Agb2YgYWxsIG92ZXJsYXlzLlxyXG4gIFx0YnJpbmdUb0Zyb250OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICh0aGlzLl9tYXApIHtcclxuICBcdFx0XHR0b0Zyb250KHRoaXMuX2ltYWdlKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBicmluZ1RvQmFjaygpOiB0aGlzXHJcbiAgXHQvLyBCcmluZ3MgdGhlIGxheWVyIHRvIHRoZSBib3R0b20gb2YgYWxsIG92ZXJsYXlzLlxyXG4gIFx0YnJpbmdUb0JhY2s6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKHRoaXMuX21hcCkge1xyXG4gIFx0XHRcdHRvQmFjayh0aGlzLl9pbWFnZSk7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2V0VXJsKHVybDogU3RyaW5nKTogdGhpc1xyXG4gIFx0Ly8gQ2hhbmdlcyB0aGUgVVJMIG9mIHRoZSBpbWFnZS5cclxuICBcdHNldFVybDogZnVuY3Rpb24gKHVybCkge1xyXG4gIFx0XHR0aGlzLl91cmwgPSB1cmw7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5faW1hZ2UpIHtcclxuICBcdFx0XHR0aGlzLl9pbWFnZS5zcmMgPSB1cmw7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2V0Qm91bmRzKGJvdW5kczogTGF0TG5nQm91bmRzKTogdGhpc1xyXG4gIFx0Ly8gVXBkYXRlIHRoZSBib3VuZHMgdGhhdCB0aGlzIEltYWdlT3ZlcmxheSBjb3ZlcnNcclxuICBcdHNldEJvdW5kczogZnVuY3Rpb24gKGJvdW5kcykge1xyXG4gIFx0XHR0aGlzLl9ib3VuZHMgPSB0b0xhdExuZ0JvdW5kcyhib3VuZHMpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX21hcCkge1xyXG4gIFx0XHRcdHRoaXMuX3Jlc2V0KCk7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdGdldEV2ZW50czogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR2YXIgZXZlbnRzID0ge1xyXG4gIFx0XHRcdHpvb206IHRoaXMuX3Jlc2V0LFxyXG4gIFx0XHRcdHZpZXdyZXNldDogdGhpcy5fcmVzZXRcclxuICBcdFx0fTtcclxuXHJcbiAgXHRcdGlmICh0aGlzLl96b29tQW5pbWF0ZWQpIHtcclxuICBcdFx0XHRldmVudHMuem9vbWFuaW0gPSB0aGlzLl9hbmltYXRlWm9vbTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0cmV0dXJuIGV2ZW50cztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBzZXRaSW5kZXgodmFsdWU6IE51bWJlcik6IHRoaXNcclxuICBcdC8vIENoYW5nZXMgdGhlIFt6SW5kZXhdKCNpbWFnZW92ZXJsYXktemluZGV4KSBvZiB0aGUgaW1hZ2Ugb3ZlcmxheS5cclxuICBcdHNldFpJbmRleDogZnVuY3Rpb24gKHZhbHVlKSB7XHJcbiAgXHRcdHRoaXMub3B0aW9ucy56SW5kZXggPSB2YWx1ZTtcclxuICBcdFx0dGhpcy5fdXBkYXRlWkluZGV4KCk7XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldEJvdW5kcygpOiBMYXRMbmdCb3VuZHNcclxuICBcdC8vIEdldCB0aGUgYm91bmRzIHRoYXQgdGhpcyBJbWFnZU92ZXJsYXkgY292ZXJzXHJcbiAgXHRnZXRCb3VuZHM6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuX2JvdW5kcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRFbGVtZW50KCk6IEhUTUxFbGVtZW50XHJcbiAgXHQvLyBSZXR1cm5zIHRoZSBpbnN0YW5jZSBvZiBbYEhUTUxJbWFnZUVsZW1lbnRgXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvSFRNTEltYWdlRWxlbWVudClcclxuICBcdC8vIHVzZWQgYnkgdGhpcyBvdmVybGF5LlxyXG4gIFx0Z2V0RWxlbWVudDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5faW1hZ2U7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9pbml0SW1hZ2U6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dmFyIHdhc0VsZW1lbnRTdXBwbGllZCA9IHRoaXMuX3VybC50YWdOYW1lID09PSAnSU1HJztcclxuICBcdFx0dmFyIGltZyA9IHRoaXMuX2ltYWdlID0gd2FzRWxlbWVudFN1cHBsaWVkID8gdGhpcy5fdXJsIDogY3JlYXRlJDEoJ2ltZycpO1xyXG5cclxuICBcdFx0YWRkQ2xhc3MoaW1nLCAnbGVhZmxldC1pbWFnZS1sYXllcicpO1xyXG4gIFx0XHRpZiAodGhpcy5fem9vbUFuaW1hdGVkKSB7IGFkZENsYXNzKGltZywgJ2xlYWZsZXQtem9vbS1hbmltYXRlZCcpOyB9XHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMuY2xhc3NOYW1lKSB7IGFkZENsYXNzKGltZywgdGhpcy5vcHRpb25zLmNsYXNzTmFtZSk7IH1cclxuXHJcbiAgXHRcdGltZy5vbnNlbGVjdHN0YXJ0ID0gZmFsc2VGbjtcclxuICBcdFx0aW1nLm9ubW91c2Vtb3ZlID0gZmFsc2VGbjtcclxuXHJcbiAgXHRcdC8vIEBldmVudCBsb2FkOiBFdmVudFxyXG4gIFx0XHQvLyBGaXJlZCB3aGVuIHRoZSBJbWFnZU92ZXJsYXkgbGF5ZXIgaGFzIGxvYWRlZCBpdHMgaW1hZ2VcclxuICBcdFx0aW1nLm9ubG9hZCA9IGJpbmQodGhpcy5maXJlLCB0aGlzLCAnbG9hZCcpO1xyXG4gIFx0XHRpbWcub25lcnJvciA9IGJpbmQodGhpcy5fb3ZlcmxheU9uRXJyb3IsIHRoaXMsICdlcnJvcicpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5jcm9zc09yaWdpbiB8fCB0aGlzLm9wdGlvbnMuY3Jvc3NPcmlnaW4gPT09ICcnKSB7XHJcbiAgXHRcdFx0aW1nLmNyb3NzT3JpZ2luID0gdGhpcy5vcHRpb25zLmNyb3NzT3JpZ2luID09PSB0cnVlID8gJycgOiB0aGlzLm9wdGlvbnMuY3Jvc3NPcmlnaW47XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMuekluZGV4KSB7XHJcbiAgXHRcdFx0dGhpcy5fdXBkYXRlWkluZGV4KCk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmICh3YXNFbGVtZW50U3VwcGxpZWQpIHtcclxuICBcdFx0XHR0aGlzLl91cmwgPSBpbWcuc3JjO1xyXG4gIFx0XHRcdHJldHVybjtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0aW1nLnNyYyA9IHRoaXMuX3VybDtcclxuICBcdFx0aW1nLmFsdCA9IHRoaXMub3B0aW9ucy5hbHQ7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9hbmltYXRlWm9vbTogZnVuY3Rpb24gKGUpIHtcclxuICBcdFx0dmFyIHNjYWxlID0gdGhpcy5fbWFwLmdldFpvb21TY2FsZShlLnpvb20pLFxyXG4gIFx0XHQgICAgb2Zmc2V0ID0gdGhpcy5fbWFwLl9sYXRMbmdCb3VuZHNUb05ld0xheWVyQm91bmRzKHRoaXMuX2JvdW5kcywgZS56b29tLCBlLmNlbnRlcikubWluO1xyXG5cclxuICBcdFx0c2V0VHJhbnNmb3JtKHRoaXMuX2ltYWdlLCBvZmZzZXQsIHNjYWxlKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X3Jlc2V0OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHZhciBpbWFnZSA9IHRoaXMuX2ltYWdlLFxyXG4gIFx0XHQgICAgYm91bmRzID0gbmV3IEJvdW5kcyhcclxuICBcdFx0ICAgICAgICB0aGlzLl9tYXAubGF0TG5nVG9MYXllclBvaW50KHRoaXMuX2JvdW5kcy5nZXROb3J0aFdlc3QoKSksXHJcbiAgXHRcdCAgICAgICAgdGhpcy5fbWFwLmxhdExuZ1RvTGF5ZXJQb2ludCh0aGlzLl9ib3VuZHMuZ2V0U291dGhFYXN0KCkpKSxcclxuICBcdFx0ICAgIHNpemUgPSBib3VuZHMuZ2V0U2l6ZSgpO1xyXG5cclxuICBcdFx0c2V0UG9zaXRpb24oaW1hZ2UsIGJvdW5kcy5taW4pO1xyXG5cclxuICBcdFx0aW1hZ2Uuc3R5bGUud2lkdGggID0gc2l6ZS54ICsgJ3B4JztcclxuICBcdFx0aW1hZ2Uuc3R5bGUuaGVpZ2h0ID0gc2l6ZS55ICsgJ3B4JztcclxuICBcdH0sXHJcblxyXG4gIFx0X3VwZGF0ZU9wYWNpdHk6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0c2V0T3BhY2l0eSh0aGlzLl9pbWFnZSwgdGhpcy5vcHRpb25zLm9wYWNpdHkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfdXBkYXRlWkluZGV4OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICh0aGlzLl9pbWFnZSAmJiB0aGlzLm9wdGlvbnMuekluZGV4ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5vcHRpb25zLnpJbmRleCAhPT0gbnVsbCkge1xyXG4gIFx0XHRcdHRoaXMuX2ltYWdlLnN0eWxlLnpJbmRleCA9IHRoaXMub3B0aW9ucy56SW5kZXg7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0X292ZXJsYXlPbkVycm9yOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdC8vIEBldmVudCBlcnJvcjogRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgSW1hZ2VPdmVybGF5IGxheWVyIGZhaWxzIHRvIGxvYWQgaXRzIGltYWdlXHJcbiAgXHRcdHRoaXMuZmlyZSgnZXJyb3InKTtcclxuXHJcbiAgXHRcdHZhciBlcnJvclVybCA9IHRoaXMub3B0aW9ucy5lcnJvck92ZXJsYXlVcmw7XHJcbiAgXHRcdGlmIChlcnJvclVybCAmJiB0aGlzLl91cmwgIT09IGVycm9yVXJsKSB7XHJcbiAgXHRcdFx0dGhpcy5fdXJsID0gZXJyb3JVcmw7XHJcbiAgXHRcdFx0dGhpcy5faW1hZ2Uuc3JjID0gZXJyb3JVcmw7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRDZW50ZXIoKTogTGF0TG5nXHJcbiAgXHQvLyBSZXR1cm5zIHRoZSBjZW50ZXIgb2YgdGhlIEltYWdlT3ZlcmxheS5cclxuICBcdGdldENlbnRlcjogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5fYm91bmRzLmdldENlbnRlcigpO1xyXG4gIFx0fVxyXG4gIH0pO1xyXG5cclxuICAvLyBAZmFjdG9yeSBMLmltYWdlT3ZlcmxheShpbWFnZVVybDogU3RyaW5nLCBib3VuZHM6IExhdExuZ0JvdW5kcywgb3B0aW9ucz86IEltYWdlT3ZlcmxheSBvcHRpb25zKVxyXG4gIC8vIEluc3RhbnRpYXRlcyBhbiBpbWFnZSBvdmVybGF5IG9iamVjdCBnaXZlbiB0aGUgVVJMIG9mIHRoZSBpbWFnZSBhbmQgdGhlXHJcbiAgLy8gZ2VvZ3JhcGhpY2FsIGJvdW5kcyBpdCBpcyB0aWVkIHRvLlxyXG4gIHZhciBpbWFnZU92ZXJsYXkgPSBmdW5jdGlvbiAodXJsLCBib3VuZHMsIG9wdGlvbnMpIHtcclxuICBcdHJldHVybiBuZXcgSW1hZ2VPdmVybGF5KHVybCwgYm91bmRzLCBvcHRpb25zKTtcclxuICB9O1xuXG4gIC8qXHJcbiAgICogQGNsYXNzIFZpZGVvT3ZlcmxheVxyXG4gICAqIEBha2EgTC5WaWRlb092ZXJsYXlcclxuICAgKiBAaW5oZXJpdHMgSW1hZ2VPdmVybGF5XHJcbiAgICpcclxuICAgKiBVc2VkIHRvIGxvYWQgYW5kIGRpc3BsYXkgYSB2aWRlbyBwbGF5ZXIgb3ZlciBzcGVjaWZpYyBib3VuZHMgb2YgdGhlIG1hcC4gRXh0ZW5kcyBgSW1hZ2VPdmVybGF5YC5cclxuICAgKlxyXG4gICAqIEEgdmlkZW8gb3ZlcmxheSB1c2VzIHRoZSBbYDx2aWRlbz5gXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9IVE1ML0VsZW1lbnQvdmlkZW8pXHJcbiAgICogSFRNTDUgZWxlbWVudC5cclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICpcclxuICAgKiBgYGBqc1xyXG4gICAqIHZhciB2aWRlb1VybCA9ICdodHRwczovL3d3dy5tYXBib3guY29tL2JpdGVzLzAwMTg4L3BhdHJpY2lhX25hc2Eud2VibScsXHJcbiAgICogXHR2aWRlb0JvdW5kcyA9IFtbIDMyLCAtMTMwXSwgWyAxMywgLTEwMF1dO1xyXG4gICAqIEwudmlkZW9PdmVybGF5KHZpZGVvVXJsLCB2aWRlb0JvdW5kcyApLmFkZFRvKG1hcCk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcblxyXG4gIHZhciBWaWRlb092ZXJsYXkgPSBJbWFnZU92ZXJsYXkuZXh0ZW5kKHtcclxuXHJcbiAgXHQvLyBAc2VjdGlvblxyXG4gIFx0Ly8gQGFrYSBWaWRlb092ZXJsYXkgb3B0aW9uc1xyXG4gIFx0b3B0aW9uczoge1xyXG4gIFx0XHQvLyBAb3B0aW9uIGF1dG9wbGF5OiBCb29sZWFuID0gdHJ1ZVxyXG4gIFx0XHQvLyBXaGV0aGVyIHRoZSB2aWRlbyBzdGFydHMgcGxheWluZyBhdXRvbWF0aWNhbGx5IHdoZW4gbG9hZGVkLlxyXG4gIFx0XHQvLyBPbiBzb21lIGJyb3dzZXJzIGF1dG9wbGF5IHdpbGwgb25seSB3b3JrIHdpdGggYG11dGVkOiB0cnVlYFxyXG4gIFx0XHRhdXRvcGxheTogdHJ1ZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gbG9vcDogQm9vbGVhbiA9IHRydWVcclxuICBcdFx0Ly8gV2hldGhlciB0aGUgdmlkZW8gd2lsbCBsb29wIGJhY2sgdG8gdGhlIGJlZ2lubmluZyB3aGVuIHBsYXllZC5cclxuICBcdFx0bG9vcDogdHJ1ZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24ga2VlcEFzcGVjdFJhdGlvOiBCb29sZWFuID0gdHJ1ZVxyXG4gIFx0XHQvLyBXaGV0aGVyIHRoZSB2aWRlbyB3aWxsIHNhdmUgYXNwZWN0IHJhdGlvIGFmdGVyIHRoZSBwcm9qZWN0aW9uLlxyXG4gIFx0XHQvLyBSZWxldmFudCBmb3Igc3VwcG9ydGVkIGJyb3dzZXJzLiBTZWUgW2Jyb3dzZXIgY29tcGF0aWJpbGl0eV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQ1NTL29iamVjdC1maXQpXHJcbiAgXHRcdGtlZXBBc3BlY3RSYXRpbzogdHJ1ZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gbXV0ZWQ6IEJvb2xlYW4gPSBmYWxzZVxyXG4gIFx0XHQvLyBXaGV0aGVyIHRoZSB2aWRlbyBzdGFydHMgb24gbXV0ZSB3aGVuIGxvYWRlZC5cclxuICBcdFx0bXV0ZWQ6IGZhbHNlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBwbGF5c0lubGluZTogQm9vbGVhbiA9IHRydWVcclxuICBcdFx0Ly8gTW9iaWxlIGJyb3dzZXJzIHdpbGwgcGxheSB0aGUgdmlkZW8gcmlnaHQgd2hlcmUgaXQgaXMgaW5zdGVhZCBvZiBvcGVuIGl0IHVwIGluIGZ1bGxzY3JlZW4gbW9kZS5cclxuICBcdFx0cGxheXNJbmxpbmU6IHRydWVcclxuICBcdH0sXHJcblxyXG4gIFx0X2luaXRJbWFnZTogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR2YXIgd2FzRWxlbWVudFN1cHBsaWVkID0gdGhpcy5fdXJsLnRhZ05hbWUgPT09ICdWSURFTyc7XHJcbiAgXHRcdHZhciB2aWQgPSB0aGlzLl9pbWFnZSA9IHdhc0VsZW1lbnRTdXBwbGllZCA/IHRoaXMuX3VybCA6IGNyZWF0ZSQxKCd2aWRlbycpO1xyXG5cclxuICBcdFx0YWRkQ2xhc3ModmlkLCAnbGVhZmxldC1pbWFnZS1sYXllcicpO1xyXG4gIFx0XHRpZiAodGhpcy5fem9vbUFuaW1hdGVkKSB7IGFkZENsYXNzKHZpZCwgJ2xlYWZsZXQtem9vbS1hbmltYXRlZCcpOyB9XHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMuY2xhc3NOYW1lKSB7IGFkZENsYXNzKHZpZCwgdGhpcy5vcHRpb25zLmNsYXNzTmFtZSk7IH1cclxuXHJcbiAgXHRcdHZpZC5vbnNlbGVjdHN0YXJ0ID0gZmFsc2VGbjtcclxuICBcdFx0dmlkLm9ubW91c2Vtb3ZlID0gZmFsc2VGbjtcclxuXHJcbiAgXHRcdC8vIEBldmVudCBsb2FkOiBFdmVudFxyXG4gIFx0XHQvLyBGaXJlZCB3aGVuIHRoZSB2aWRlbyBoYXMgZmluaXNoZWQgbG9hZGluZyB0aGUgZmlyc3QgZnJhbWVcclxuICBcdFx0dmlkLm9ubG9hZGVkZGF0YSA9IGJpbmQodGhpcy5maXJlLCB0aGlzLCAnbG9hZCcpO1xyXG5cclxuICBcdFx0aWYgKHdhc0VsZW1lbnRTdXBwbGllZCkge1xyXG4gIFx0XHRcdHZhciBzb3VyY2VFbGVtZW50cyA9IHZpZC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnc291cmNlJyk7XHJcbiAgXHRcdFx0dmFyIHNvdXJjZXMgPSBbXTtcclxuICBcdFx0XHRmb3IgKHZhciBqID0gMDsgaiA8IHNvdXJjZUVsZW1lbnRzLmxlbmd0aDsgaisrKSB7XHJcbiAgXHRcdFx0XHRzb3VyY2VzLnB1c2goc291cmNlRWxlbWVudHNbal0uc3JjKTtcclxuICBcdFx0XHR9XHJcblxyXG4gIFx0XHRcdHRoaXMuX3VybCA9IChzb3VyY2VFbGVtZW50cy5sZW5ndGggPiAwKSA/IHNvdXJjZXMgOiBbdmlkLnNyY107XHJcbiAgXHRcdFx0cmV0dXJuO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAoIWlzQXJyYXkodGhpcy5fdXJsKSkgeyB0aGlzLl91cmwgPSBbdGhpcy5fdXJsXTsgfVxyXG5cclxuICBcdFx0aWYgKCF0aGlzLm9wdGlvbnMua2VlcEFzcGVjdFJhdGlvICYmIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh2aWQuc3R5bGUsICdvYmplY3RGaXQnKSkge1xyXG4gIFx0XHRcdHZpZC5zdHlsZVsnb2JqZWN0Rml0J10gPSAnZmlsbCc7XHJcbiAgXHRcdH1cclxuICBcdFx0dmlkLmF1dG9wbGF5ID0gISF0aGlzLm9wdGlvbnMuYXV0b3BsYXk7XHJcbiAgXHRcdHZpZC5sb29wID0gISF0aGlzLm9wdGlvbnMubG9vcDtcclxuICBcdFx0dmlkLm11dGVkID0gISF0aGlzLm9wdGlvbnMubXV0ZWQ7XHJcbiAgXHRcdHZpZC5wbGF5c0lubGluZSA9ICEhdGhpcy5vcHRpb25zLnBsYXlzSW5saW5lO1xyXG4gIFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX3VybC5sZW5ndGg7IGkrKykge1xyXG4gIFx0XHRcdHZhciBzb3VyY2UgPSBjcmVhdGUkMSgnc291cmNlJyk7XHJcbiAgXHRcdFx0c291cmNlLnNyYyA9IHRoaXMuX3VybFtpXTtcclxuICBcdFx0XHR2aWQuYXBwZW5kQ2hpbGQoc291cmNlKTtcclxuICBcdFx0fVxyXG4gIFx0fVxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0RWxlbWVudCgpOiBIVE1MVmlkZW9FbGVtZW50XHJcbiAgXHQvLyBSZXR1cm5zIHRoZSBpbnN0YW5jZSBvZiBbYEhUTUxWaWRlb0VsZW1lbnRgXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvSFRNTFZpZGVvRWxlbWVudClcclxuICBcdC8vIHVzZWQgYnkgdGhpcyBvdmVybGF5LlxyXG4gIH0pO1xyXG5cclxuXHJcbiAgLy8gQGZhY3RvcnkgTC52aWRlb092ZXJsYXkodmlkZW86IFN0cmluZ3xBcnJheXxIVE1MVmlkZW9FbGVtZW50LCBib3VuZHM6IExhdExuZ0JvdW5kcywgb3B0aW9ucz86IFZpZGVvT3ZlcmxheSBvcHRpb25zKVxyXG4gIC8vIEluc3RhbnRpYXRlcyBhbiBpbWFnZSBvdmVybGF5IG9iamVjdCBnaXZlbiB0aGUgVVJMIG9mIHRoZSB2aWRlbyAob3IgYXJyYXkgb2YgVVJMcywgb3IgZXZlbiBhIHZpZGVvIGVsZW1lbnQpIGFuZCB0aGVcclxuICAvLyBnZW9ncmFwaGljYWwgYm91bmRzIGl0IGlzIHRpZWQgdG8uXHJcblxyXG4gIGZ1bmN0aW9uIHZpZGVvT3ZlcmxheSh2aWRlbywgYm91bmRzLCBvcHRpb25zKSB7XHJcbiAgXHRyZXR1cm4gbmV3IFZpZGVvT3ZlcmxheSh2aWRlbywgYm91bmRzLCBvcHRpb25zKTtcclxuICB9XG5cbiAgLypcbiAgICogQGNsYXNzIFNWR092ZXJsYXlcbiAgICogQGFrYSBMLlNWR092ZXJsYXlcbiAgICogQGluaGVyaXRzIEltYWdlT3ZlcmxheVxuICAgKlxuICAgKiBVc2VkIHRvIGxvYWQsIGRpc3BsYXkgYW5kIHByb3ZpZGUgRE9NIGFjY2VzcyB0byBhbiBTVkcgZmlsZSBvdmVyIHNwZWNpZmljIGJvdW5kcyBvZiB0aGUgbWFwLiBFeHRlbmRzIGBJbWFnZU92ZXJsYXlgLlxuICAgKlxuICAgKiBBbiBTVkcgb3ZlcmxheSB1c2VzIHRoZSBbYDxzdmc+YF0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvU1ZHL0VsZW1lbnQvc3ZnKSBlbGVtZW50LlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKlxuICAgKiBgYGBqc1xuICAgKiB2YXIgc3ZnRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsIFwic3ZnXCIpO1xuICAgKiBzdmdFbGVtZW50LnNldEF0dHJpYnV0ZSgneG1sbnMnLCBcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIpO1xuICAgKiBzdmdFbGVtZW50LnNldEF0dHJpYnV0ZSgndmlld0JveCcsIFwiMCAwIDIwMCAyMDBcIik7XG4gICAqIHN2Z0VsZW1lbnQuaW5uZXJIVE1MID0gJzxyZWN0IHdpZHRoPVwiMjAwXCIgaGVpZ2h0PVwiMjAwXCIvPjxyZWN0IHg9XCI3NVwiIHk9XCIyM1wiIHdpZHRoPVwiNTBcIiBoZWlnaHQ9XCI1MFwiIHN0eWxlPVwiZmlsbDpyZWRcIi8+PHJlY3QgeD1cIjc1XCIgeT1cIjEyM1wiIHdpZHRoPVwiNTBcIiBoZWlnaHQ9XCI1MFwiIHN0eWxlPVwiZmlsbDojMDAxM2ZmXCIvPic7XG4gICAqIHZhciBzdmdFbGVtZW50Qm91bmRzID0gWyBbIDMyLCAtMTMwIF0sIFsgMTMsIC0xMDAgXSBdO1xuICAgKiBMLnN2Z092ZXJsYXkoc3ZnRWxlbWVudCwgc3ZnRWxlbWVudEJvdW5kcykuYWRkVG8obWFwKTtcbiAgICogYGBgXG4gICAqL1xuXG4gIHZhciBTVkdPdmVybGF5ID0gSW1hZ2VPdmVybGF5LmV4dGVuZCh7XG4gIFx0X2luaXRJbWFnZTogZnVuY3Rpb24gKCkge1xuICBcdFx0dmFyIGVsID0gdGhpcy5faW1hZ2UgPSB0aGlzLl91cmw7XG5cbiAgXHRcdGFkZENsYXNzKGVsLCAnbGVhZmxldC1pbWFnZS1sYXllcicpO1xuICBcdFx0aWYgKHRoaXMuX3pvb21BbmltYXRlZCkgeyBhZGRDbGFzcyhlbCwgJ2xlYWZsZXQtem9vbS1hbmltYXRlZCcpOyB9XG4gIFx0XHRpZiAodGhpcy5vcHRpb25zLmNsYXNzTmFtZSkgeyBhZGRDbGFzcyhlbCwgdGhpcy5vcHRpb25zLmNsYXNzTmFtZSk7IH1cblxuICBcdFx0ZWwub25zZWxlY3RzdGFydCA9IGZhbHNlRm47XG4gIFx0XHRlbC5vbm1vdXNlbW92ZSA9IGZhbHNlRm47XG4gIFx0fVxuXG4gIFx0Ly8gQG1ldGhvZCBnZXRFbGVtZW50KCk6IFNWR0VsZW1lbnRcbiAgXHQvLyBSZXR1cm5zIHRoZSBpbnN0YW5jZSBvZiBbYFNWR0VsZW1lbnRgXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvU1ZHRWxlbWVudClcbiAgXHQvLyB1c2VkIGJ5IHRoaXMgb3ZlcmxheS5cbiAgfSk7XG5cblxuICAvLyBAZmFjdG9yeSBMLnN2Z092ZXJsYXkoc3ZnOiBTdHJpbmd8U1ZHRWxlbWVudCwgYm91bmRzOiBMYXRMbmdCb3VuZHMsIG9wdGlvbnM/OiBTVkdPdmVybGF5IG9wdGlvbnMpXG4gIC8vIEluc3RhbnRpYXRlcyBhbiBpbWFnZSBvdmVybGF5IG9iamVjdCBnaXZlbiBhbiBTVkcgZWxlbWVudCBhbmQgdGhlIGdlb2dyYXBoaWNhbCBib3VuZHMgaXQgaXMgdGllZCB0by5cbiAgLy8gQSB2aWV3Qm94IGF0dHJpYnV0ZSBpcyByZXF1aXJlZCBvbiB0aGUgU1ZHIGVsZW1lbnQgdG8gem9vbSBpbiBhbmQgb3V0IHByb3Blcmx5LlxuXG4gIGZ1bmN0aW9uIHN2Z092ZXJsYXkoZWwsIGJvdW5kcywgb3B0aW9ucykge1xuICBcdHJldHVybiBuZXcgU1ZHT3ZlcmxheShlbCwgYm91bmRzLCBvcHRpb25zKTtcbiAgfVxuXG4gIC8qXHJcbiAgICogQGNsYXNzIERpdk92ZXJsYXlcclxuICAgKiBAaW5oZXJpdHMgSW50ZXJhY3RpdmUgbGF5ZXJcclxuICAgKiBAYWthIEwuRGl2T3ZlcmxheVxyXG4gICAqIEJhc2UgbW9kZWwgZm9yIEwuUG9wdXAgYW5kIEwuVG9vbHRpcC4gSW5oZXJpdCBmcm9tIGl0IGZvciBjdXN0b20gb3ZlcmxheXMgbGlrZSBwbHVnaW5zLlxyXG4gICAqL1xyXG5cclxuICAvLyBAbmFtZXNwYWNlIERpdk92ZXJsYXlcclxuICB2YXIgRGl2T3ZlcmxheSA9IExheWVyLmV4dGVuZCh7XHJcblxyXG4gIFx0Ly8gQHNlY3Rpb25cclxuICBcdC8vIEBha2EgRGl2T3ZlcmxheSBvcHRpb25zXHJcbiAgXHRvcHRpb25zOiB7XHJcbiAgXHRcdC8vIEBvcHRpb24gaW50ZXJhY3RpdmU6IEJvb2xlYW4gPSBmYWxzZVxyXG4gIFx0XHQvLyBJZiB0cnVlLCB0aGUgcG9wdXAvdG9vbHRpcCB3aWxsIGxpc3RlbiB0byB0aGUgbW91c2UgZXZlbnRzLlxyXG4gIFx0XHRpbnRlcmFjdGl2ZTogZmFsc2UsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIG9mZnNldDogUG9pbnQgPSBQb2ludCgwLCAwKVxyXG4gIFx0XHQvLyBUaGUgb2Zmc2V0IG9mIHRoZSBvdmVybGF5IHBvc2l0aW9uLlxyXG4gIFx0XHRvZmZzZXQ6IFswLCAwXSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gY2xhc3NOYW1lOiBTdHJpbmcgPSAnJ1xyXG4gIFx0XHQvLyBBIGN1c3RvbSBDU1MgY2xhc3MgbmFtZSB0byBhc3NpZ24gdG8gdGhlIG92ZXJsYXkuXHJcbiAgXHRcdGNsYXNzTmFtZTogJycsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHBhbmU6IFN0cmluZyA9IHVuZGVmaW5lZFxyXG4gIFx0XHQvLyBgTWFwIHBhbmVgIHdoZXJlIHRoZSBvdmVybGF5IHdpbGwgYmUgYWRkZWQuXHJcbiAgXHRcdHBhbmU6IHVuZGVmaW5lZCxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gY29udGVudDogU3RyaW5nfEhUTUxFbGVtZW50fEZ1bmN0aW9uID0gJydcclxuICBcdFx0Ly8gU2V0cyB0aGUgSFRNTCBjb250ZW50IG9mIHRoZSBvdmVybGF5IHdoaWxlIGluaXRpYWxpemluZy4gSWYgYSBmdW5jdGlvbiBpcyBwYXNzZWQgdGhlIHNvdXJjZSBsYXllciB3aWxsIGJlXHJcbiAgXHRcdC8vIHBhc3NlZCB0byB0aGUgZnVuY3Rpb24uIFRoZSBmdW5jdGlvbiBzaG91bGQgcmV0dXJuIGEgYFN0cmluZ2Agb3IgYEhUTUxFbGVtZW50YCB0byBiZSB1c2VkIGluIHRoZSBvdmVybGF5LlxyXG4gIFx0XHRjb250ZW50OiAnJ1xyXG4gIFx0fSxcclxuXHJcbiAgXHRpbml0aWFsaXplOiBmdW5jdGlvbiAob3B0aW9ucywgc291cmNlKSB7XHJcbiAgXHRcdGlmIChvcHRpb25zICYmIChvcHRpb25zIGluc3RhbmNlb2YgTGF0TG5nIHx8IGlzQXJyYXkob3B0aW9ucykpKSB7XHJcbiAgXHRcdFx0dGhpcy5fbGF0bG5nID0gdG9MYXRMbmcob3B0aW9ucyk7XHJcbiAgXHRcdFx0c2V0T3B0aW9ucyh0aGlzLCBzb3VyY2UpO1xyXG4gIFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdHNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XHJcbiAgXHRcdFx0dGhpcy5fc291cmNlID0gc291cmNlO1xyXG4gIFx0XHR9XHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMuY29udGVudCkge1xyXG4gIFx0XHRcdHRoaXMuX2NvbnRlbnQgPSB0aGlzLm9wdGlvbnMuY29udGVudDtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIG9wZW5PbihtYXA6IE1hcCk6IHRoaXNcclxuICBcdC8vIEFkZHMgdGhlIG92ZXJsYXkgdG8gdGhlIG1hcC5cclxuICBcdC8vIEFsdGVybmF0aXZlIHRvIGBtYXAub3BlblBvcHVwKHBvcHVwKWAvYC5vcGVuVG9vbHRpcCh0b29sdGlwKWAuXHJcbiAgXHRvcGVuT246IGZ1bmN0aW9uIChtYXApIHtcclxuICBcdFx0bWFwID0gYXJndW1lbnRzLmxlbmd0aCA/IG1hcCA6IHRoaXMuX3NvdXJjZS5fbWFwOyAvLyBleHBlcmltZW50YWwsIG5vdCB0aGUgcGFydCBvZiBwdWJsaWMgYXBpXHJcbiAgXHRcdGlmICghbWFwLmhhc0xheWVyKHRoaXMpKSB7XHJcbiAgXHRcdFx0bWFwLmFkZExheWVyKHRoaXMpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGNsb3NlKCk6IHRoaXNcclxuICBcdC8vIENsb3NlcyB0aGUgb3ZlcmxheS5cclxuICBcdC8vIEFsdGVybmF0aXZlIHRvIGBtYXAuY2xvc2VQb3B1cChwb3B1cClgL2AuY2xvc2VUb29sdGlwKHRvb2x0aXApYFxyXG4gIFx0Ly8gYW5kIGBsYXllci5jbG9zZVBvcHVwKClgL2AuY2xvc2VUb29sdGlwKClgLlxyXG4gIFx0Y2xvc2U6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKHRoaXMuX21hcCkge1xyXG4gIFx0XHRcdHRoaXMuX21hcC5yZW1vdmVMYXllcih0aGlzKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCB0b2dnbGUobGF5ZXI/OiBMYXllcik6IHRoaXNcclxuICBcdC8vIE9wZW5zIG9yIGNsb3NlcyB0aGUgb3ZlcmxheSBib3VuZCB0byBsYXllciBkZXBlbmRpbmcgb24gaXRzIGN1cnJlbnQgc3RhdGUuXHJcbiAgXHQvLyBBcmd1bWVudCBtYXkgYmUgb21pdHRlZCBvbmx5IGZvciBvdmVybGF5IGJvdW5kIHRvIGxheWVyLlxyXG4gIFx0Ly8gQWx0ZXJuYXRpdmUgdG8gYGxheWVyLnRvZ2dsZVBvcHVwKClgL2AudG9nZ2xlVG9vbHRpcCgpYC5cclxuICBcdHRvZ2dsZTogZnVuY3Rpb24gKGxheWVyKSB7XHJcbiAgXHRcdGlmICh0aGlzLl9tYXApIHtcclxuICBcdFx0XHR0aGlzLmNsb3NlKCk7XHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0aWYgKGFyZ3VtZW50cy5sZW5ndGgpIHtcclxuICBcdFx0XHRcdHRoaXMuX3NvdXJjZSA9IGxheWVyO1xyXG4gIFx0XHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0XHRsYXllciA9IHRoaXMuX3NvdXJjZTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdFx0dGhpcy5fcHJlcGFyZU9wZW4oKTtcclxuXHJcbiAgXHRcdFx0Ly8gb3BlbiB0aGUgb3ZlcmxheSBvbiB0aGUgbWFwXHJcbiAgXHRcdFx0dGhpcy5vcGVuT24obGF5ZXIuX21hcCk7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdG9uQWRkOiBmdW5jdGlvbiAobWFwKSB7XHJcbiAgXHRcdHRoaXMuX3pvb21BbmltYXRlZCA9IG1hcC5fem9vbUFuaW1hdGVkO1xyXG5cclxuICBcdFx0aWYgKCF0aGlzLl9jb250YWluZXIpIHtcclxuICBcdFx0XHR0aGlzLl9pbml0TGF5b3V0KCk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmIChtYXAuX2ZhZGVBbmltYXRlZCkge1xyXG4gIFx0XHRcdHNldE9wYWNpdHkodGhpcy5fY29udGFpbmVyLCAwKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0Y2xlYXJUaW1lb3V0KHRoaXMuX3JlbW92ZVRpbWVvdXQpO1xyXG4gIFx0XHR0aGlzLmdldFBhbmUoKS5hcHBlbmRDaGlsZCh0aGlzLl9jb250YWluZXIpO1xyXG4gIFx0XHR0aGlzLnVwZGF0ZSgpO1xyXG5cclxuICBcdFx0aWYgKG1hcC5fZmFkZUFuaW1hdGVkKSB7XHJcbiAgXHRcdFx0c2V0T3BhY2l0eSh0aGlzLl9jb250YWluZXIsIDEpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR0aGlzLmJyaW5nVG9Gcm9udCgpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5pbnRlcmFjdGl2ZSkge1xyXG4gIFx0XHRcdGFkZENsYXNzKHRoaXMuX2NvbnRhaW5lciwgJ2xlYWZsZXQtaW50ZXJhY3RpdmUnKTtcclxuICBcdFx0XHR0aGlzLmFkZEludGVyYWN0aXZlVGFyZ2V0KHRoaXMuX2NvbnRhaW5lcik7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0b25SZW1vdmU6IGZ1bmN0aW9uIChtYXApIHtcclxuICBcdFx0aWYgKG1hcC5fZmFkZUFuaW1hdGVkKSB7XHJcbiAgXHRcdFx0c2V0T3BhY2l0eSh0aGlzLl9jb250YWluZXIsIDApO1xyXG4gIFx0XHRcdHRoaXMuX3JlbW92ZVRpbWVvdXQgPSBzZXRUaW1lb3V0KGJpbmQocmVtb3ZlLCB1bmRlZmluZWQsIHRoaXMuX2NvbnRhaW5lciksIDIwMCk7XHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0cmVtb3ZlKHRoaXMuX2NvbnRhaW5lcik7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMuaW50ZXJhY3RpdmUpIHtcclxuICBcdFx0XHRyZW1vdmVDbGFzcyh0aGlzLl9jb250YWluZXIsICdsZWFmbGV0LWludGVyYWN0aXZlJyk7XHJcbiAgXHRcdFx0dGhpcy5yZW1vdmVJbnRlcmFjdGl2ZVRhcmdldCh0aGlzLl9jb250YWluZXIpO1xyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBuYW1lc3BhY2UgRGl2T3ZlcmxheVxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRMYXRMbmc6IExhdExuZ1xyXG4gIFx0Ly8gUmV0dXJucyB0aGUgZ2VvZ3JhcGhpY2FsIHBvaW50IG9mIHRoZSBvdmVybGF5LlxyXG4gIFx0Z2V0TGF0TG5nOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLl9sYXRsbmc7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2V0TGF0TG5nKGxhdGxuZzogTGF0TG5nKTogdGhpc1xyXG4gIFx0Ly8gU2V0cyB0aGUgZ2VvZ3JhcGhpY2FsIHBvaW50IHdoZXJlIHRoZSBvdmVybGF5IHdpbGwgb3Blbi5cclxuICBcdHNldExhdExuZzogZnVuY3Rpb24gKGxhdGxuZykge1xyXG4gIFx0XHR0aGlzLl9sYXRsbmcgPSB0b0xhdExuZyhsYXRsbmcpO1xyXG4gIFx0XHRpZiAodGhpcy5fbWFwKSB7XHJcbiAgXHRcdFx0dGhpcy5fdXBkYXRlUG9zaXRpb24oKTtcclxuICBcdFx0XHR0aGlzLl9hZGp1c3RQYW4oKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRDb250ZW50OiBTdHJpbmd8SFRNTEVsZW1lbnRcclxuICBcdC8vIFJldHVybnMgdGhlIGNvbnRlbnQgb2YgdGhlIG92ZXJsYXkuXHJcbiAgXHRnZXRDb250ZW50OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLl9jb250ZW50O1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNldENvbnRlbnQoaHRtbENvbnRlbnQ6IFN0cmluZ3xIVE1MRWxlbWVudHxGdW5jdGlvbik6IHRoaXNcclxuICBcdC8vIFNldHMgdGhlIEhUTUwgY29udGVudCBvZiB0aGUgb3ZlcmxheS4gSWYgYSBmdW5jdGlvbiBpcyBwYXNzZWQgdGhlIHNvdXJjZSBsYXllciB3aWxsIGJlIHBhc3NlZCB0byB0aGUgZnVuY3Rpb24uXHJcbiAgXHQvLyBUaGUgZnVuY3Rpb24gc2hvdWxkIHJldHVybiBhIGBTdHJpbmdgIG9yIGBIVE1MRWxlbWVudGAgdG8gYmUgdXNlZCBpbiB0aGUgb3ZlcmxheS5cclxuICBcdHNldENvbnRlbnQ6IGZ1bmN0aW9uIChjb250ZW50KSB7XHJcbiAgXHRcdHRoaXMuX2NvbnRlbnQgPSBjb250ZW50O1xyXG4gIFx0XHR0aGlzLnVwZGF0ZSgpO1xyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRFbGVtZW50OiBTdHJpbmd8SFRNTEVsZW1lbnRcclxuICBcdC8vIFJldHVybnMgdGhlIEhUTUwgY29udGFpbmVyIG9mIHRoZSBvdmVybGF5LlxyXG4gIFx0Z2V0RWxlbWVudDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5fY29udGFpbmVyO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHVwZGF0ZTogbnVsbFxyXG4gIFx0Ly8gVXBkYXRlcyB0aGUgb3ZlcmxheSBjb250ZW50LCBsYXlvdXQgYW5kIHBvc2l0aW9uLiBVc2VmdWwgZm9yIHVwZGF0aW5nIHRoZSBvdmVybGF5IGFmdGVyIHNvbWV0aGluZyBpbnNpZGUgY2hhbmdlZCwgZS5nLiBpbWFnZSBsb2FkZWQuXHJcbiAgXHR1cGRhdGU6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKCF0aGlzLl9tYXApIHsgcmV0dXJuOyB9XHJcblxyXG4gIFx0XHR0aGlzLl9jb250YWluZXIuc3R5bGUudmlzaWJpbGl0eSA9ICdoaWRkZW4nO1xyXG5cclxuICBcdFx0dGhpcy5fdXBkYXRlQ29udGVudCgpO1xyXG4gIFx0XHR0aGlzLl91cGRhdGVMYXlvdXQoKTtcclxuICBcdFx0dGhpcy5fdXBkYXRlUG9zaXRpb24oKTtcclxuXHJcbiAgXHRcdHRoaXMuX2NvbnRhaW5lci5zdHlsZS52aXNpYmlsaXR5ID0gJyc7XHJcblxyXG4gIFx0XHR0aGlzLl9hZGp1c3RQYW4oKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Z2V0RXZlbnRzOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHZhciBldmVudHMgPSB7XHJcbiAgXHRcdFx0em9vbTogdGhpcy5fdXBkYXRlUG9zaXRpb24sXHJcbiAgXHRcdFx0dmlld3Jlc2V0OiB0aGlzLl91cGRhdGVQb3NpdGlvblxyXG4gIFx0XHR9O1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX3pvb21BbmltYXRlZCkge1xyXG4gIFx0XHRcdGV2ZW50cy56b29tYW5pbSA9IHRoaXMuX2FuaW1hdGVab29tO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiBldmVudHM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgaXNPcGVuOiBCb29sZWFuXHJcbiAgXHQvLyBSZXR1cm5zIGB0cnVlYCB3aGVuIHRoZSBvdmVybGF5IGlzIHZpc2libGUgb24gdGhlIG1hcC5cclxuICBcdGlzT3BlbjogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gISF0aGlzLl9tYXAgJiYgdGhpcy5fbWFwLmhhc0xheWVyKHRoaXMpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGJyaW5nVG9Gcm9udDogdGhpc1xyXG4gIFx0Ly8gQnJpbmdzIHRoaXMgb3ZlcmxheSBpbiBmcm9udCBvZiBvdGhlciBvdmVybGF5cyAoaW4gdGhlIHNhbWUgbWFwIHBhbmUpLlxyXG4gIFx0YnJpbmdUb0Zyb250OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICh0aGlzLl9tYXApIHtcclxuICBcdFx0XHR0b0Zyb250KHRoaXMuX2NvbnRhaW5lcik7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgYnJpbmdUb0JhY2s6IHRoaXNcclxuICBcdC8vIEJyaW5ncyB0aGlzIG92ZXJsYXkgdG8gdGhlIGJhY2sgb2Ygb3RoZXIgb3ZlcmxheXMgKGluIHRoZSBzYW1lIG1hcCBwYW5lKS5cclxuICBcdGJyaW5nVG9CYWNrOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICh0aGlzLl9tYXApIHtcclxuICBcdFx0XHR0b0JhY2sodGhpcy5fY29udGFpbmVyKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gcHJlcGFyZSBib3VuZCBvdmVybGF5IHRvIG9wZW46IHVwZGF0ZSBsYXRsbmcgcG9zIC8gY29udGVudCBzb3VyY2UgKGZvciBGZWF0dXJlR3JvdXApXHJcbiAgXHRfcHJlcGFyZU9wZW46IGZ1bmN0aW9uIChsYXRsbmcpIHtcclxuICBcdFx0dmFyIHNvdXJjZSA9IHRoaXMuX3NvdXJjZTtcclxuICBcdFx0aWYgKCFzb3VyY2UuX21hcCkgeyByZXR1cm4gZmFsc2U7IH1cclxuXHJcbiAgXHRcdGlmIChzb3VyY2UgaW5zdGFuY2VvZiBGZWF0dXJlR3JvdXApIHtcclxuICBcdFx0XHRzb3VyY2UgPSBudWxsO1xyXG4gIFx0XHRcdHZhciBsYXllcnMgPSB0aGlzLl9zb3VyY2UuX2xheWVycztcclxuICBcdFx0XHRmb3IgKHZhciBpZCBpbiBsYXllcnMpIHtcclxuICBcdFx0XHRcdGlmIChsYXllcnNbaWRdLl9tYXApIHtcclxuICBcdFx0XHRcdFx0c291cmNlID0gbGF5ZXJzW2lkXTtcclxuICBcdFx0XHRcdFx0YnJlYWs7XHJcbiAgXHRcdFx0XHR9XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHRcdGlmICghc291cmNlKSB7IHJldHVybiBmYWxzZTsgfSAvLyBVbmFibGUgdG8gZ2V0IHNvdXJjZSBsYXllci5cclxuXHJcbiAgXHRcdFx0Ly8gc2V0IG92ZXJsYXkgc291cmNlIHRvIHRoaXMgbGF5ZXJcclxuICBcdFx0XHR0aGlzLl9zb3VyY2UgPSBzb3VyY2U7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmICghbGF0bG5nKSB7XHJcbiAgXHRcdFx0aWYgKHNvdXJjZS5nZXRDZW50ZXIpIHtcclxuICBcdFx0XHRcdGxhdGxuZyA9IHNvdXJjZS5nZXRDZW50ZXIoKTtcclxuICBcdFx0XHR9IGVsc2UgaWYgKHNvdXJjZS5nZXRMYXRMbmcpIHtcclxuICBcdFx0XHRcdGxhdGxuZyA9IHNvdXJjZS5nZXRMYXRMbmcoKTtcclxuICBcdFx0XHR9IGVsc2UgaWYgKHNvdXJjZS5nZXRCb3VuZHMpIHtcclxuICBcdFx0XHRcdGxhdGxuZyA9IHNvdXJjZS5nZXRCb3VuZHMoKS5nZXRDZW50ZXIoKTtcclxuICBcdFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCdVbmFibGUgdG8gZ2V0IHNvdXJjZSBsYXllciBMYXRMbmcuJyk7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcbiAgXHRcdHRoaXMuc2V0TGF0TG5nKGxhdGxuZyk7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fbWFwKSB7XHJcbiAgXHRcdFx0Ly8gdXBkYXRlIHRoZSBvdmVybGF5IChjb250ZW50LCBsYXlvdXQsIGV0Yy4uLilcclxuICBcdFx0XHR0aGlzLnVwZGF0ZSgpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gdHJ1ZTtcclxuICBcdH0sXHJcblxyXG4gIFx0X3VwZGF0ZUNvbnRlbnQ6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKCF0aGlzLl9jb250ZW50KSB7IHJldHVybjsgfVxyXG5cclxuICBcdFx0dmFyIG5vZGUgPSB0aGlzLl9jb250ZW50Tm9kZTtcclxuICBcdFx0dmFyIGNvbnRlbnQgPSAodHlwZW9mIHRoaXMuX2NvbnRlbnQgPT09ICdmdW5jdGlvbicpID8gdGhpcy5fY29udGVudCh0aGlzLl9zb3VyY2UgfHwgdGhpcykgOiB0aGlzLl9jb250ZW50O1xyXG5cclxuICBcdFx0aWYgKHR5cGVvZiBjb250ZW50ID09PSAnc3RyaW5nJykge1xyXG4gIFx0XHRcdG5vZGUuaW5uZXJIVE1MID0gY29udGVudDtcclxuICBcdFx0fSBlbHNlIHtcclxuICBcdFx0XHR3aGlsZSAobm9kZS5oYXNDaGlsZE5vZGVzKCkpIHtcclxuICBcdFx0XHRcdG5vZGUucmVtb3ZlQ2hpbGQobm9kZS5maXJzdENoaWxkKTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdFx0bm9kZS5hcHBlbmRDaGlsZChjb250ZW50KTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gQG5hbWVzcGFjZSBEaXZPdmVybGF5XHJcbiAgXHRcdC8vIEBzZWN0aW9uIERpdk92ZXJsYXkgZXZlbnRzXHJcbiAgXHRcdC8vIEBldmVudCBjb250ZW50dXBkYXRlOiBFdmVudFxyXG4gIFx0XHQvLyBGaXJlZCB3aGVuIHRoZSBjb250ZW50IG9mIHRoZSBvdmVybGF5IGlzIHVwZGF0ZWRcclxuICBcdFx0dGhpcy5maXJlKCdjb250ZW50dXBkYXRlJyk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF91cGRhdGVQb3NpdGlvbjogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRpZiAoIXRoaXMuX21hcCkgeyByZXR1cm47IH1cclxuXHJcbiAgXHRcdHZhciBwb3MgPSB0aGlzLl9tYXAubGF0TG5nVG9MYXllclBvaW50KHRoaXMuX2xhdGxuZyksXHJcbiAgXHRcdCAgICBvZmZzZXQgPSB0b1BvaW50KHRoaXMub3B0aW9ucy5vZmZzZXQpLFxyXG4gIFx0XHQgICAgYW5jaG9yID0gdGhpcy5fZ2V0QW5jaG9yKCk7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fem9vbUFuaW1hdGVkKSB7XHJcbiAgXHRcdFx0c2V0UG9zaXRpb24odGhpcy5fY29udGFpbmVyLCBwb3MuYWRkKGFuY2hvcikpO1xyXG4gIFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdG9mZnNldCA9IG9mZnNldC5hZGQocG9zKS5hZGQoYW5jaG9yKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dmFyIGJvdHRvbSA9IHRoaXMuX2NvbnRhaW5lckJvdHRvbSA9IC1vZmZzZXQueSxcclxuICBcdFx0ICAgIGxlZnQgPSB0aGlzLl9jb250YWluZXJMZWZ0ID0gLU1hdGgucm91bmQodGhpcy5fY29udGFpbmVyV2lkdGggLyAyKSArIG9mZnNldC54O1xyXG5cclxuICBcdFx0Ly8gYm90dG9tIHBvc2l0aW9uIHRoZSBvdmVybGF5IGluIGNhc2UgdGhlIGhlaWdodCBvZiB0aGUgb3ZlcmxheSBjaGFuZ2VzIChpbWFnZXMgbG9hZGluZyBldGMpXHJcbiAgXHRcdHRoaXMuX2NvbnRhaW5lci5zdHlsZS5ib3R0b20gPSBib3R0b20gKyAncHgnO1xyXG4gIFx0XHR0aGlzLl9jb250YWluZXIuc3R5bGUubGVmdCA9IGxlZnQgKyAncHgnO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfZ2V0QW5jaG9yOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiBbMCwgMF07XHJcbiAgXHR9XHJcblxyXG4gIH0pO1xyXG5cclxuICBNYXAuaW5jbHVkZSh7XHJcbiAgXHRfaW5pdE92ZXJsYXk6IGZ1bmN0aW9uIChPdmVybGF5Q2xhc3MsIGNvbnRlbnQsIGxhdGxuZywgb3B0aW9ucykge1xyXG4gIFx0XHR2YXIgb3ZlcmxheSA9IGNvbnRlbnQ7XHJcbiAgXHRcdGlmICghKG92ZXJsYXkgaW5zdGFuY2VvZiBPdmVybGF5Q2xhc3MpKSB7XHJcbiAgXHRcdFx0b3ZlcmxheSA9IG5ldyBPdmVybGF5Q2xhc3Mob3B0aW9ucykuc2V0Q29udGVudChjb250ZW50KTtcclxuICBcdFx0fVxyXG4gIFx0XHRpZiAobGF0bG5nKSB7XHJcbiAgXHRcdFx0b3ZlcmxheS5zZXRMYXRMbmcobGF0bG5nKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gb3ZlcmxheTtcclxuICBcdH1cclxuICB9KTtcclxuXHJcblxyXG4gIExheWVyLmluY2x1ZGUoe1xyXG4gIFx0X2luaXRPdmVybGF5OiBmdW5jdGlvbiAoT3ZlcmxheUNsYXNzLCBvbGQsIGNvbnRlbnQsIG9wdGlvbnMpIHtcclxuICBcdFx0dmFyIG92ZXJsYXkgPSBjb250ZW50O1xyXG4gIFx0XHRpZiAob3ZlcmxheSBpbnN0YW5jZW9mIE92ZXJsYXlDbGFzcykge1xyXG4gIFx0XHRcdHNldE9wdGlvbnMob3ZlcmxheSwgb3B0aW9ucyk7XHJcbiAgXHRcdFx0b3ZlcmxheS5fc291cmNlID0gdGhpcztcclxuICBcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRvdmVybGF5ID0gKG9sZCAmJiAhb3B0aW9ucykgPyBvbGQgOiBuZXcgT3ZlcmxheUNsYXNzKG9wdGlvbnMsIHRoaXMpO1xyXG4gIFx0XHRcdG92ZXJsYXkuc2V0Q29udGVudChjb250ZW50KTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gb3ZlcmxheTtcclxuICBcdH1cclxuICB9KTtcblxuICAvKlxyXG4gICAqIEBjbGFzcyBQb3B1cFxyXG4gICAqIEBpbmhlcml0cyBEaXZPdmVybGF5XHJcbiAgICogQGFrYSBMLlBvcHVwXHJcbiAgICogVXNlZCB0byBvcGVuIHBvcHVwcyBpbiBjZXJ0YWluIHBsYWNlcyBvZiB0aGUgbWFwLiBVc2UgW01hcC5vcGVuUG9wdXBdKCNtYXAtb3BlbnBvcHVwKSB0b1xyXG4gICAqIG9wZW4gcG9wdXBzIHdoaWxlIG1ha2luZyBzdXJlIHRoYXQgb25seSBvbmUgcG9wdXAgaXMgb3BlbiBhdCBvbmUgdGltZVxyXG4gICAqIChyZWNvbW1lbmRlZCBmb3IgdXNhYmlsaXR5KSwgb3IgdXNlIFtNYXAuYWRkTGF5ZXJdKCNtYXAtYWRkbGF5ZXIpIHRvIG9wZW4gYXMgbWFueSBhcyB5b3Ugd2FudC5cclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICpcclxuICAgKiBJZiB5b3Ugd2FudCB0byBqdXN0IGJpbmQgYSBwb3B1cCB0byBtYXJrZXIgY2xpY2sgYW5kIHRoZW4gb3BlbiBpdCwgaXQncyByZWFsbHkgZWFzeTpcclxuICAgKlxyXG4gICAqIGBgYGpzXHJcbiAgICogbWFya2VyLmJpbmRQb3B1cChwb3B1cENvbnRlbnQpLm9wZW5Qb3B1cCgpO1xyXG4gICAqIGBgYFxyXG4gICAqIFBhdGggb3ZlcmxheXMgbGlrZSBwb2x5bGluZXMgYWxzbyBoYXZlIGEgYGJpbmRQb3B1cGAgbWV0aG9kLlxyXG4gICAqXHJcbiAgICogQSBwb3B1cCBjYW4gYmUgYWxzbyBzdGFuZGFsb25lOlxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiB2YXIgcG9wdXAgPSBMLnBvcHVwKClcclxuICAgKiBcdC5zZXRMYXRMbmcobGF0bG5nKVxyXG4gICAqIFx0LnNldENvbnRlbnQoJzxwPkhlbGxvIHdvcmxkITxiciAvPlRoaXMgaXMgYSBuaWNlIHBvcHVwLjwvcD4nKVxyXG4gICAqIFx0Lm9wZW5PbihtYXApO1xyXG4gICAqIGBgYFxyXG4gICAqIG9yXHJcbiAgICogYGBganNcclxuICAgKiB2YXIgcG9wdXAgPSBMLnBvcHVwKGxhdGxuZywge2NvbnRlbnQ6ICc8cD5IZWxsbyB3b3JsZCE8YnIgLz5UaGlzIGlzIGEgbmljZSBwb3B1cC48L3A+JylcclxuICAgKiBcdC5vcGVuT24obWFwKTtcclxuICAgKiBgYGBcclxuICAgKi9cclxuXHJcblxyXG4gIC8vIEBuYW1lc3BhY2UgUG9wdXBcclxuICB2YXIgUG9wdXAgPSBEaXZPdmVybGF5LmV4dGVuZCh7XHJcblxyXG4gIFx0Ly8gQHNlY3Rpb25cclxuICBcdC8vIEBha2EgUG9wdXAgb3B0aW9uc1xyXG4gIFx0b3B0aW9uczoge1xyXG4gIFx0XHQvLyBAb3B0aW9uIHBhbmU6IFN0cmluZyA9ICdwb3B1cFBhbmUnXHJcbiAgXHRcdC8vIGBNYXAgcGFuZWAgd2hlcmUgdGhlIHBvcHVwIHdpbGwgYmUgYWRkZWQuXHJcbiAgXHRcdHBhbmU6ICdwb3B1cFBhbmUnLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBvZmZzZXQ6IFBvaW50ID0gUG9pbnQoMCwgNylcclxuICBcdFx0Ly8gVGhlIG9mZnNldCBvZiB0aGUgcG9wdXAgcG9zaXRpb24uXHJcbiAgXHRcdG9mZnNldDogWzAsIDddLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBtYXhXaWR0aDogTnVtYmVyID0gMzAwXHJcbiAgXHRcdC8vIE1heCB3aWR0aCBvZiB0aGUgcG9wdXAsIGluIHBpeGVscy5cclxuICBcdFx0bWF4V2lkdGg6IDMwMCxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gbWluV2lkdGg6IE51bWJlciA9IDUwXHJcbiAgXHRcdC8vIE1pbiB3aWR0aCBvZiB0aGUgcG9wdXAsIGluIHBpeGVscy5cclxuICBcdFx0bWluV2lkdGg6IDUwLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBtYXhIZWlnaHQ6IE51bWJlciA9IG51bGxcclxuICBcdFx0Ly8gSWYgc2V0LCBjcmVhdGVzIGEgc2Nyb2xsYWJsZSBjb250YWluZXIgb2YgdGhlIGdpdmVuIGhlaWdodFxyXG4gIFx0XHQvLyBpbnNpZGUgYSBwb3B1cCBpZiBpdHMgY29udGVudCBleGNlZWRzIGl0LlxyXG4gIFx0XHQvLyBUaGUgc2Nyb2xsYWJsZSBjb250YWluZXIgY2FuIGJlIHN0eWxlZCB1c2luZyB0aGVcclxuICBcdFx0Ly8gYGxlYWZsZXQtcG9wdXAtc2Nyb2xsZWRgIENTUyBjbGFzcyBzZWxlY3Rvci5cclxuICBcdFx0bWF4SGVpZ2h0OiBudWxsLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBhdXRvUGFuOiBCb29sZWFuID0gdHJ1ZVxyXG4gIFx0XHQvLyBTZXQgaXQgdG8gYGZhbHNlYCBpZiB5b3UgZG9uJ3Qgd2FudCB0aGUgbWFwIHRvIGRvIHBhbm5pbmcgYW5pbWF0aW9uXHJcbiAgXHRcdC8vIHRvIGZpdCB0aGUgb3BlbmVkIHBvcHVwLlxyXG4gIFx0XHRhdXRvUGFuOiB0cnVlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBhdXRvUGFuUGFkZGluZ1RvcExlZnQ6IFBvaW50ID0gbnVsbFxyXG4gIFx0XHQvLyBUaGUgbWFyZ2luIGJldHdlZW4gdGhlIHBvcHVwIGFuZCB0aGUgdG9wIGxlZnQgY29ybmVyIG9mIHRoZSBtYXBcclxuICBcdFx0Ly8gdmlldyBhZnRlciBhdXRvcGFubmluZyB3YXMgcGVyZm9ybWVkLlxyXG4gIFx0XHRhdXRvUGFuUGFkZGluZ1RvcExlZnQ6IG51bGwsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIGF1dG9QYW5QYWRkaW5nQm90dG9tUmlnaHQ6IFBvaW50ID0gbnVsbFxyXG4gIFx0XHQvLyBUaGUgbWFyZ2luIGJldHdlZW4gdGhlIHBvcHVwIGFuZCB0aGUgYm90dG9tIHJpZ2h0IGNvcm5lciBvZiB0aGUgbWFwXHJcbiAgXHRcdC8vIHZpZXcgYWZ0ZXIgYXV0b3Bhbm5pbmcgd2FzIHBlcmZvcm1lZC5cclxuICBcdFx0YXV0b1BhblBhZGRpbmdCb3R0b21SaWdodDogbnVsbCxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gYXV0b1BhblBhZGRpbmc6IFBvaW50ID0gUG9pbnQoNSwgNSlcclxuICBcdFx0Ly8gRXF1aXZhbGVudCBvZiBzZXR0aW5nIGJvdGggdG9wIGxlZnQgYW5kIGJvdHRvbSByaWdodCBhdXRvcGFuIHBhZGRpbmcgdG8gdGhlIHNhbWUgdmFsdWUuXHJcbiAgXHRcdGF1dG9QYW5QYWRkaW5nOiBbNSwgNV0sXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIGtlZXBJblZpZXc6IEJvb2xlYW4gPSBmYWxzZVxyXG4gIFx0XHQvLyBTZXQgaXQgdG8gYHRydWVgIGlmIHlvdSB3YW50IHRvIHByZXZlbnQgdXNlcnMgZnJvbSBwYW5uaW5nIHRoZSBwb3B1cFxyXG4gIFx0XHQvLyBvZmYgb2YgdGhlIHNjcmVlbiB3aGlsZSBpdCBpcyBvcGVuLlxyXG4gIFx0XHRrZWVwSW5WaWV3OiBmYWxzZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gY2xvc2VCdXR0b246IEJvb2xlYW4gPSB0cnVlXHJcbiAgXHRcdC8vIENvbnRyb2xzIHRoZSBwcmVzZW5jZSBvZiBhIGNsb3NlIGJ1dHRvbiBpbiB0aGUgcG9wdXAuXHJcbiAgXHRcdGNsb3NlQnV0dG9uOiB0cnVlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBhdXRvQ2xvc2U6IEJvb2xlYW4gPSB0cnVlXHJcbiAgXHRcdC8vIFNldCBpdCB0byBgZmFsc2VgIGlmIHlvdSB3YW50IHRvIG92ZXJyaWRlIHRoZSBkZWZhdWx0IGJlaGF2aW9yIG9mXHJcbiAgXHRcdC8vIHRoZSBwb3B1cCBjbG9zaW5nIHdoZW4gYW5vdGhlciBwb3B1cCBpcyBvcGVuZWQuXHJcbiAgXHRcdGF1dG9DbG9zZTogdHJ1ZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gY2xvc2VPbkVzY2FwZUtleTogQm9vbGVhbiA9IHRydWVcclxuICBcdFx0Ly8gU2V0IGl0IHRvIGBmYWxzZWAgaWYgeW91IHdhbnQgdG8gb3ZlcnJpZGUgdGhlIGRlZmF1bHQgYmVoYXZpb3Igb2ZcclxuICBcdFx0Ly8gdGhlIEVTQyBrZXkgZm9yIGNsb3Npbmcgb2YgdGhlIHBvcHVwLlxyXG4gIFx0XHRjbG9zZU9uRXNjYXBlS2V5OiB0cnVlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBjbG9zZU9uQ2xpY2s6IEJvb2xlYW4gPSAqXHJcbiAgXHRcdC8vIFNldCBpdCBpZiB5b3Ugd2FudCB0byBvdmVycmlkZSB0aGUgZGVmYXVsdCBiZWhhdmlvciBvZiB0aGUgcG9wdXAgY2xvc2luZyB3aGVuIHVzZXIgY2xpY2tzXHJcbiAgXHRcdC8vIG9uIHRoZSBtYXAuIERlZmF1bHRzIHRvIHRoZSBtYXAncyBbYGNsb3NlUG9wdXBPbkNsaWNrYF0oI21hcC1jbG9zZXBvcHVwb25jbGljaykgb3B0aW9uLlxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBjbGFzc05hbWU6IFN0cmluZyA9ICcnXHJcbiAgXHRcdC8vIEEgY3VzdG9tIENTUyBjbGFzcyBuYW1lIHRvIGFzc2lnbiB0byB0aGUgcG9wdXAuXHJcbiAgXHRcdGNsYXNzTmFtZTogJydcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG5hbWVzcGFjZSBQb3B1cFxyXG4gIFx0Ly8gQG1ldGhvZCBvcGVuT24obWFwOiBNYXApOiB0aGlzXHJcbiAgXHQvLyBBbHRlcm5hdGl2ZSB0byBgbWFwLm9wZW5Qb3B1cChwb3B1cClgLlxyXG4gIFx0Ly8gQWRkcyB0aGUgcG9wdXAgdG8gdGhlIG1hcCBhbmQgY2xvc2VzIHRoZSBwcmV2aW91cyBvbmUuXHJcbiAgXHRvcGVuT246IGZ1bmN0aW9uIChtYXApIHtcclxuICBcdFx0bWFwID0gYXJndW1lbnRzLmxlbmd0aCA/IG1hcCA6IHRoaXMuX3NvdXJjZS5fbWFwOyAvLyBleHBlcmltZW50YWwsIG5vdCB0aGUgcGFydCBvZiBwdWJsaWMgYXBpXHJcblxyXG4gIFx0XHRpZiAoIW1hcC5oYXNMYXllcih0aGlzKSAmJiBtYXAuX3BvcHVwICYmIG1hcC5fcG9wdXAub3B0aW9ucy5hdXRvQ2xvc2UpIHtcclxuICBcdFx0XHRtYXAucmVtb3ZlTGF5ZXIobWFwLl9wb3B1cCk7XHJcbiAgXHRcdH1cclxuICBcdFx0bWFwLl9wb3B1cCA9IHRoaXM7XHJcblxyXG4gIFx0XHRyZXR1cm4gRGl2T3ZlcmxheS5wcm90b3R5cGUub3Blbk9uLmNhbGwodGhpcywgbWFwKTtcclxuICBcdH0sXHJcblxyXG4gIFx0b25BZGQ6IGZ1bmN0aW9uIChtYXApIHtcclxuICBcdFx0RGl2T3ZlcmxheS5wcm90b3R5cGUub25BZGQuY2FsbCh0aGlzLCBtYXApO1xyXG5cclxuICBcdFx0Ly8gQG5hbWVzcGFjZSBNYXBcclxuICBcdFx0Ly8gQHNlY3Rpb24gUG9wdXAgZXZlbnRzXHJcbiAgXHRcdC8vIEBldmVudCBwb3B1cG9wZW46IFBvcHVwRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiBhIHBvcHVwIGlzIG9wZW5lZCBpbiB0aGUgbWFwXHJcbiAgXHRcdG1hcC5maXJlKCdwb3B1cG9wZW4nLCB7cG9wdXA6IHRoaXN9KTtcclxuXHJcbiAgXHRcdGlmICh0aGlzLl9zb3VyY2UpIHtcclxuICBcdFx0XHQvLyBAbmFtZXNwYWNlIExheWVyXHJcbiAgXHRcdFx0Ly8gQHNlY3Rpb24gUG9wdXAgZXZlbnRzXHJcbiAgXHRcdFx0Ly8gQGV2ZW50IHBvcHVwb3BlbjogUG9wdXBFdmVudFxyXG4gIFx0XHRcdC8vIEZpcmVkIHdoZW4gYSBwb3B1cCBib3VuZCB0byB0aGlzIGxheWVyIGlzIG9wZW5lZFxyXG4gIFx0XHRcdHRoaXMuX3NvdXJjZS5maXJlKCdwb3B1cG9wZW4nLCB7cG9wdXA6IHRoaXN9LCB0cnVlKTtcclxuICBcdFx0XHQvLyBGb3Igbm9uLXBhdGggbGF5ZXJzLCB3ZSB0b2dnbGUgdGhlIHBvcHVwIHdoZW4gY2xpY2tpbmdcclxuICBcdFx0XHQvLyBhZ2FpbiB0aGUgbGF5ZXIsIHNvIHByZXZlbnQgdGhlIG1hcCB0byByZW9wZW4gaXQuXHJcbiAgXHRcdFx0aWYgKCEodGhpcy5fc291cmNlIGluc3RhbmNlb2YgUGF0aCkpIHtcclxuICBcdFx0XHRcdHRoaXMuX3NvdXJjZS5vbigncHJlY2xpY2snLCBzdG9wUHJvcGFnYXRpb24pO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHRvblJlbW92ZTogZnVuY3Rpb24gKG1hcCkge1xyXG4gIFx0XHREaXZPdmVybGF5LnByb3RvdHlwZS5vblJlbW92ZS5jYWxsKHRoaXMsIG1hcCk7XHJcblxyXG4gIFx0XHQvLyBAbmFtZXNwYWNlIE1hcFxyXG4gIFx0XHQvLyBAc2VjdGlvbiBQb3B1cCBldmVudHNcclxuICBcdFx0Ly8gQGV2ZW50IHBvcHVwY2xvc2U6IFBvcHVwRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiBhIHBvcHVwIGluIHRoZSBtYXAgaXMgY2xvc2VkXHJcbiAgXHRcdG1hcC5maXJlKCdwb3B1cGNsb3NlJywge3BvcHVwOiB0aGlzfSk7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fc291cmNlKSB7XHJcbiAgXHRcdFx0Ly8gQG5hbWVzcGFjZSBMYXllclxyXG4gIFx0XHRcdC8vIEBzZWN0aW9uIFBvcHVwIGV2ZW50c1xyXG4gIFx0XHRcdC8vIEBldmVudCBwb3B1cGNsb3NlOiBQb3B1cEV2ZW50XHJcbiAgXHRcdFx0Ly8gRmlyZWQgd2hlbiBhIHBvcHVwIGJvdW5kIHRvIHRoaXMgbGF5ZXIgaXMgY2xvc2VkXHJcbiAgXHRcdFx0dGhpcy5fc291cmNlLmZpcmUoJ3BvcHVwY2xvc2UnLCB7cG9wdXA6IHRoaXN9LCB0cnVlKTtcclxuICBcdFx0XHRpZiAoISh0aGlzLl9zb3VyY2UgaW5zdGFuY2VvZiBQYXRoKSkge1xyXG4gIFx0XHRcdFx0dGhpcy5fc291cmNlLm9mZigncHJlY2xpY2snLCBzdG9wUHJvcGFnYXRpb24pO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHRnZXRFdmVudHM6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dmFyIGV2ZW50cyA9IERpdk92ZXJsYXkucHJvdG90eXBlLmdldEV2ZW50cy5jYWxsKHRoaXMpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5jbG9zZU9uQ2xpY2sgIT09IHVuZGVmaW5lZCA/IHRoaXMub3B0aW9ucy5jbG9zZU9uQ2xpY2sgOiB0aGlzLl9tYXAub3B0aW9ucy5jbG9zZVBvcHVwT25DbGljaykge1xyXG4gIFx0XHRcdGV2ZW50cy5wcmVjbGljayA9IHRoaXMuY2xvc2U7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMua2VlcEluVmlldykge1xyXG4gIFx0XHRcdGV2ZW50cy5tb3ZlZW5kID0gdGhpcy5fYWRqdXN0UGFuO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gZXZlbnRzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfaW5pdExheW91dDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR2YXIgcHJlZml4ID0gJ2xlYWZsZXQtcG9wdXAnLFxyXG4gIFx0XHQgICAgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyID0gY3JlYXRlJDEoJ2RpdicsXHJcbiAgXHRcdFx0cHJlZml4ICsgJyAnICsgKHRoaXMub3B0aW9ucy5jbGFzc05hbWUgfHwgJycpICtcclxuICBcdFx0XHQnIGxlYWZsZXQtem9vbS1hbmltYXRlZCcpO1xyXG5cclxuICBcdFx0dmFyIHdyYXBwZXIgPSB0aGlzLl93cmFwcGVyID0gY3JlYXRlJDEoJ2RpdicsIHByZWZpeCArICctY29udGVudC13cmFwcGVyJywgY29udGFpbmVyKTtcclxuICBcdFx0dGhpcy5fY29udGVudE5vZGUgPSBjcmVhdGUkMSgnZGl2JywgcHJlZml4ICsgJy1jb250ZW50Jywgd3JhcHBlcik7XHJcblxyXG4gIFx0XHRkaXNhYmxlQ2xpY2tQcm9wYWdhdGlvbihjb250YWluZXIpO1xyXG4gIFx0XHRkaXNhYmxlU2Nyb2xsUHJvcGFnYXRpb24odGhpcy5fY29udGVudE5vZGUpO1xyXG4gIFx0XHRvbihjb250YWluZXIsICdjb250ZXh0bWVudScsIHN0b3BQcm9wYWdhdGlvbik7XHJcblxyXG4gIFx0XHR0aGlzLl90aXBDb250YWluZXIgPSBjcmVhdGUkMSgnZGl2JywgcHJlZml4ICsgJy10aXAtY29udGFpbmVyJywgY29udGFpbmVyKTtcclxuICBcdFx0dGhpcy5fdGlwID0gY3JlYXRlJDEoJ2RpdicsIHByZWZpeCArICctdGlwJywgdGhpcy5fdGlwQ29udGFpbmVyKTtcclxuXHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMuY2xvc2VCdXR0b24pIHtcclxuICBcdFx0XHR2YXIgY2xvc2VCdXR0b24gPSB0aGlzLl9jbG9zZUJ1dHRvbiA9IGNyZWF0ZSQxKCdhJywgcHJlZml4ICsgJy1jbG9zZS1idXR0b24nLCBjb250YWluZXIpO1xyXG4gIFx0XHRcdGNsb3NlQnV0dG9uLnNldEF0dHJpYnV0ZSgncm9sZScsICdidXR0b24nKTsgLy8gb3ZlcnJpZGVzIHRoZSBpbXBsaWNpdCByb2xlPWxpbmsgb2YgPGE+IGVsZW1lbnRzICM3Mzk5XHJcbiAgXHRcdFx0Y2xvc2VCdXR0b24uc2V0QXR0cmlidXRlKCdhcmlhLWxhYmVsJywgJ0Nsb3NlIHBvcHVwJyk7XHJcbiAgXHRcdFx0Y2xvc2VCdXR0b24uaHJlZiA9ICcjY2xvc2UnO1xyXG4gIFx0XHRcdGNsb3NlQnV0dG9uLmlubmVySFRNTCA9ICc8c3BhbiBhcmlhLWhpZGRlbj1cInRydWVcIj4mIzIxNTs8L3NwYW4+JztcclxuXHJcbiAgXHRcdFx0b24oY2xvc2VCdXR0b24sICdjbGljaycsIGZ1bmN0aW9uIChldikge1xyXG4gIFx0XHRcdFx0cHJldmVudERlZmF1bHQoZXYpO1xyXG4gIFx0XHRcdFx0dGhpcy5jbG9zZSgpO1xyXG4gIFx0XHRcdH0sIHRoaXMpO1xyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdF91cGRhdGVMYXlvdXQ6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dmFyIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRlbnROb2RlLFxyXG4gIFx0XHQgICAgc3R5bGUgPSBjb250YWluZXIuc3R5bGU7XHJcblxyXG4gIFx0XHRzdHlsZS53aWR0aCA9ICcnO1xyXG4gIFx0XHRzdHlsZS53aGl0ZVNwYWNlID0gJ25vd3JhcCc7XHJcblxyXG4gIFx0XHR2YXIgd2lkdGggPSBjb250YWluZXIub2Zmc2V0V2lkdGg7XHJcbiAgXHRcdHdpZHRoID0gTWF0aC5taW4od2lkdGgsIHRoaXMub3B0aW9ucy5tYXhXaWR0aCk7XHJcbiAgXHRcdHdpZHRoID0gTWF0aC5tYXgod2lkdGgsIHRoaXMub3B0aW9ucy5taW5XaWR0aCk7XHJcblxyXG4gIFx0XHRzdHlsZS53aWR0aCA9ICh3aWR0aCArIDEpICsgJ3B4JztcclxuICBcdFx0c3R5bGUud2hpdGVTcGFjZSA9ICcnO1xyXG5cclxuICBcdFx0c3R5bGUuaGVpZ2h0ID0gJyc7XHJcblxyXG4gIFx0XHR2YXIgaGVpZ2h0ID0gY29udGFpbmVyLm9mZnNldEhlaWdodCxcclxuICBcdFx0ICAgIG1heEhlaWdodCA9IHRoaXMub3B0aW9ucy5tYXhIZWlnaHQsXHJcbiAgXHRcdCAgICBzY3JvbGxlZENsYXNzID0gJ2xlYWZsZXQtcG9wdXAtc2Nyb2xsZWQnO1xyXG5cclxuICBcdFx0aWYgKG1heEhlaWdodCAmJiBoZWlnaHQgPiBtYXhIZWlnaHQpIHtcclxuICBcdFx0XHRzdHlsZS5oZWlnaHQgPSBtYXhIZWlnaHQgKyAncHgnO1xyXG4gIFx0XHRcdGFkZENsYXNzKGNvbnRhaW5lciwgc2Nyb2xsZWRDbGFzcyk7XHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0cmVtb3ZlQ2xhc3MoY29udGFpbmVyLCBzY3JvbGxlZENsYXNzKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5fY29udGFpbmVyV2lkdGggPSB0aGlzLl9jb250YWluZXIub2Zmc2V0V2lkdGg7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9hbmltYXRlWm9vbTogZnVuY3Rpb24gKGUpIHtcclxuICBcdFx0dmFyIHBvcyA9IHRoaXMuX21hcC5fbGF0TG5nVG9OZXdMYXllclBvaW50KHRoaXMuX2xhdGxuZywgZS56b29tLCBlLmNlbnRlciksXHJcbiAgXHRcdCAgICBhbmNob3IgPSB0aGlzLl9nZXRBbmNob3IoKTtcclxuICBcdFx0c2V0UG9zaXRpb24odGhpcy5fY29udGFpbmVyLCBwb3MuYWRkKGFuY2hvcikpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfYWRqdXN0UGFuOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICghdGhpcy5vcHRpb25zLmF1dG9QYW4pIHsgcmV0dXJuOyB9XHJcbiAgXHRcdGlmICh0aGlzLl9tYXAuX3BhbkFuaW0pIHsgdGhpcy5fbWFwLl9wYW5BbmltLnN0b3AoKTsgfVxyXG5cclxuICBcdFx0Ly8gV2UgY2FuIGVuZGxlc3NseSByZWN1cnNlIGlmIGtlZXBJblZpZXcgaXMgc2V0IGFuZCB0aGUgdmlldyByZXNldHMuXHJcbiAgXHRcdC8vIExldCdzIGd1YXJkIGFnYWluc3QgdGhhdCBieSBleGl0aW5nIGVhcmx5IGlmIHdlJ3JlIHJlc3BvbmRpbmcgdG8gb3VyIG93biBhdXRvcGFuLlxyXG4gIFx0XHRpZiAodGhpcy5fYXV0b3Bhbm5pbmcpIHtcclxuICBcdFx0XHR0aGlzLl9hdXRvcGFubmluZyA9IGZhbHNlO1xyXG4gIFx0XHRcdHJldHVybjtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dmFyIG1hcCA9IHRoaXMuX21hcCxcclxuICBcdFx0ICAgIG1hcmdpbkJvdHRvbSA9IHBhcnNlSW50KGdldFN0eWxlKHRoaXMuX2NvbnRhaW5lciwgJ21hcmdpbkJvdHRvbScpLCAxMCkgfHwgMCxcclxuICBcdFx0ICAgIGNvbnRhaW5lckhlaWdodCA9IHRoaXMuX2NvbnRhaW5lci5vZmZzZXRIZWlnaHQgKyBtYXJnaW5Cb3R0b20sXHJcbiAgXHRcdCAgICBjb250YWluZXJXaWR0aCA9IHRoaXMuX2NvbnRhaW5lcldpZHRoLFxyXG4gIFx0XHQgICAgbGF5ZXJQb3MgPSBuZXcgUG9pbnQodGhpcy5fY29udGFpbmVyTGVmdCwgLWNvbnRhaW5lckhlaWdodCAtIHRoaXMuX2NvbnRhaW5lckJvdHRvbSk7XHJcblxyXG4gIFx0XHRsYXllclBvcy5fYWRkKGdldFBvc2l0aW9uKHRoaXMuX2NvbnRhaW5lcikpO1xyXG5cclxuICBcdFx0dmFyIGNvbnRhaW5lclBvcyA9IG1hcC5sYXllclBvaW50VG9Db250YWluZXJQb2ludChsYXllclBvcyksXHJcbiAgXHRcdCAgICBwYWRkaW5nID0gdG9Qb2ludCh0aGlzLm9wdGlvbnMuYXV0b1BhblBhZGRpbmcpLFxyXG4gIFx0XHQgICAgcGFkZGluZ1RMID0gdG9Qb2ludCh0aGlzLm9wdGlvbnMuYXV0b1BhblBhZGRpbmdUb3BMZWZ0IHx8IHBhZGRpbmcpLFxyXG4gIFx0XHQgICAgcGFkZGluZ0JSID0gdG9Qb2ludCh0aGlzLm9wdGlvbnMuYXV0b1BhblBhZGRpbmdCb3R0b21SaWdodCB8fCBwYWRkaW5nKSxcclxuICBcdFx0ICAgIHNpemUgPSBtYXAuZ2V0U2l6ZSgpLFxyXG4gIFx0XHQgICAgZHggPSAwLFxyXG4gIFx0XHQgICAgZHkgPSAwO1xyXG5cclxuICBcdFx0aWYgKGNvbnRhaW5lclBvcy54ICsgY29udGFpbmVyV2lkdGggKyBwYWRkaW5nQlIueCA+IHNpemUueCkgeyAvLyByaWdodFxyXG4gIFx0XHRcdGR4ID0gY29udGFpbmVyUG9zLnggKyBjb250YWluZXJXaWR0aCAtIHNpemUueCArIHBhZGRpbmdCUi54O1xyXG4gIFx0XHR9XHJcbiAgXHRcdGlmIChjb250YWluZXJQb3MueCAtIGR4IC0gcGFkZGluZ1RMLnggPCAwKSB7IC8vIGxlZnRcclxuICBcdFx0XHRkeCA9IGNvbnRhaW5lclBvcy54IC0gcGFkZGluZ1RMLng7XHJcbiAgXHRcdH1cclxuICBcdFx0aWYgKGNvbnRhaW5lclBvcy55ICsgY29udGFpbmVySGVpZ2h0ICsgcGFkZGluZ0JSLnkgPiBzaXplLnkpIHsgLy8gYm90dG9tXHJcbiAgXHRcdFx0ZHkgPSBjb250YWluZXJQb3MueSArIGNvbnRhaW5lckhlaWdodCAtIHNpemUueSArIHBhZGRpbmdCUi55O1xyXG4gIFx0XHR9XHJcbiAgXHRcdGlmIChjb250YWluZXJQb3MueSAtIGR5IC0gcGFkZGluZ1RMLnkgPCAwKSB7IC8vIHRvcFxyXG4gIFx0XHRcdGR5ID0gY29udGFpbmVyUG9zLnkgLSBwYWRkaW5nVEwueTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gQG5hbWVzcGFjZSBNYXBcclxuICBcdFx0Ly8gQHNlY3Rpb24gUG9wdXAgZXZlbnRzXHJcbiAgXHRcdC8vIEBldmVudCBhdXRvcGFuc3RhcnQ6IEV2ZW50XHJcbiAgXHRcdC8vIEZpcmVkIHdoZW4gdGhlIG1hcCBzdGFydHMgYXV0b3Bhbm5pbmcgd2hlbiBvcGVuaW5nIGEgcG9wdXAuXHJcbiAgXHRcdGlmIChkeCB8fCBkeSkge1xyXG4gIFx0XHRcdC8vIFRyYWNrIHRoYXQgd2UncmUgYXV0b3Bhbm5pbmcsIGFzIHRoaXMgZnVuY3Rpb24gd2lsbCBiZSByZS1yYW4gb24gbW92ZWVuZFxyXG4gIFx0XHRcdGlmICh0aGlzLm9wdGlvbnMua2VlcEluVmlldykge1xyXG4gIFx0XHRcdFx0dGhpcy5fYXV0b3Bhbm5pbmcgPSB0cnVlO1xyXG4gIFx0XHRcdH1cclxuXHJcbiAgXHRcdFx0bWFwXHJcbiAgXHRcdFx0ICAgIC5maXJlKCdhdXRvcGFuc3RhcnQnKVxyXG4gIFx0XHRcdCAgICAucGFuQnkoW2R4LCBkeV0pO1xyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdF9nZXRBbmNob3I6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0Ly8gV2hlcmUgc2hvdWxkIHdlIGFuY2hvciB0aGUgcG9wdXAgb24gdGhlIHNvdXJjZSBsYXllcj9cclxuICBcdFx0cmV0dXJuIHRvUG9pbnQodGhpcy5fc291cmNlICYmIHRoaXMuX3NvdXJjZS5fZ2V0UG9wdXBBbmNob3IgPyB0aGlzLl9zb3VyY2UuX2dldFBvcHVwQW5jaG9yKCkgOiBbMCwgMF0pO1xyXG4gIFx0fVxyXG5cclxuICB9KTtcclxuXHJcbiAgLy8gQG5hbWVzcGFjZSBQb3B1cFxyXG4gIC8vIEBmYWN0b3J5IEwucG9wdXAob3B0aW9ucz86IFBvcHVwIG9wdGlvbnMsIHNvdXJjZT86IExheWVyKVxyXG4gIC8vIEluc3RhbnRpYXRlcyBhIGBQb3B1cGAgb2JqZWN0IGdpdmVuIGFuIG9wdGlvbmFsIGBvcHRpb25zYCBvYmplY3QgdGhhdCBkZXNjcmliZXMgaXRzIGFwcGVhcmFuY2UgYW5kIGxvY2F0aW9uIGFuZCBhbiBvcHRpb25hbCBgc291cmNlYCBvYmplY3QgdGhhdCBpcyB1c2VkIHRvIHRhZyB0aGUgcG9wdXAgd2l0aCBhIHJlZmVyZW5jZSB0byB0aGUgTGF5ZXIgdG8gd2hpY2ggaXQgcmVmZXJzLlxyXG4gIC8vIEBhbHRlcm5hdGl2ZVxyXG4gIC8vIEBmYWN0b3J5IEwucG9wdXAobGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/OiBQb3B1cCBvcHRpb25zKVxyXG4gIC8vIEluc3RhbnRpYXRlcyBhIGBQb3B1cGAgb2JqZWN0IGdpdmVuIGBsYXRsbmdgIHdoZXJlIHRoZSBwb3B1cCB3aWxsIG9wZW4gYW5kIGFuIG9wdGlvbmFsIGBvcHRpb25zYCBvYmplY3QgdGhhdCBkZXNjcmliZXMgaXRzIGFwcGVhcmFuY2UgYW5kIGxvY2F0aW9uLlxyXG4gIHZhciBwb3B1cCA9IGZ1bmN0aW9uIChvcHRpb25zLCBzb3VyY2UpIHtcclxuICBcdHJldHVybiBuZXcgUG9wdXAob3B0aW9ucywgc291cmNlKTtcclxuICB9O1xyXG5cclxuXHJcbiAgLyogQG5hbWVzcGFjZSBNYXBcclxuICAgKiBAc2VjdGlvbiBJbnRlcmFjdGlvbiBPcHRpb25zXHJcbiAgICogQG9wdGlvbiBjbG9zZVBvcHVwT25DbGljazogQm9vbGVhbiA9IHRydWVcclxuICAgKiBTZXQgaXQgdG8gYGZhbHNlYCBpZiB5b3UgZG9uJ3Qgd2FudCBwb3B1cHMgdG8gY2xvc2Ugd2hlbiB1c2VyIGNsaWNrcyB0aGUgbWFwLlxyXG4gICAqL1xyXG4gIE1hcC5tZXJnZU9wdGlvbnMoe1xyXG4gIFx0Y2xvc2VQb3B1cE9uQ2xpY2s6IHRydWVcclxuICB9KTtcclxuXHJcblxyXG4gIC8vIEBuYW1lc3BhY2UgTWFwXHJcbiAgLy8gQHNlY3Rpb24gTWV0aG9kcyBmb3IgTGF5ZXJzIGFuZCBDb250cm9sc1xyXG4gIE1hcC5pbmNsdWRlKHtcclxuICBcdC8vIEBtZXRob2Qgb3BlblBvcHVwKHBvcHVwOiBQb3B1cCk6IHRoaXNcclxuICBcdC8vIE9wZW5zIHRoZSBzcGVjaWZpZWQgcG9wdXAgd2hpbGUgY2xvc2luZyB0aGUgcHJldmlvdXNseSBvcGVuZWQgKHRvIG1ha2Ugc3VyZSBvbmx5IG9uZSBpcyBvcGVuZWQgYXQgb25lIHRpbWUgZm9yIHVzYWJpbGl0eSkuXHJcbiAgXHQvLyBAYWx0ZXJuYXRpdmVcclxuICBcdC8vIEBtZXRob2Qgb3BlblBvcHVwKGNvbnRlbnQ6IFN0cmluZ3xIVE1MRWxlbWVudCwgbGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/OiBQb3B1cCBvcHRpb25zKTogdGhpc1xyXG4gIFx0Ly8gQ3JlYXRlcyBhIHBvcHVwIHdpdGggdGhlIHNwZWNpZmllZCBjb250ZW50IGFuZCBvcHRpb25zIGFuZCBvcGVucyBpdCBpbiB0aGUgZ2l2ZW4gcG9pbnQgb24gYSBtYXAuXHJcbiAgXHRvcGVuUG9wdXA6IGZ1bmN0aW9uIChwb3B1cCwgbGF0bG5nLCBvcHRpb25zKSB7XHJcbiAgXHRcdHRoaXMuX2luaXRPdmVybGF5KFBvcHVwLCBwb3B1cCwgbGF0bG5nLCBvcHRpb25zKVxyXG4gIFx0XHQgIC5vcGVuT24odGhpcyk7XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBjbG9zZVBvcHVwKHBvcHVwPzogUG9wdXApOiB0aGlzXHJcbiAgXHQvLyBDbG9zZXMgdGhlIHBvcHVwIHByZXZpb3VzbHkgb3BlbmVkIHdpdGggW29wZW5Qb3B1cF0oI21hcC1vcGVucG9wdXApIChvciB0aGUgZ2l2ZW4gb25lKS5cclxuICBcdGNsb3NlUG9wdXA6IGZ1bmN0aW9uIChwb3B1cCkge1xyXG4gIFx0XHRwb3B1cCA9IGFyZ3VtZW50cy5sZW5ndGggPyBwb3B1cCA6IHRoaXMuX3BvcHVwO1xyXG4gIFx0XHRpZiAocG9wdXApIHtcclxuICBcdFx0XHRwb3B1cC5jbG9zZSgpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fVxyXG4gIH0pO1xyXG5cclxuICAvKlxyXG4gICAqIEBuYW1lc3BhY2UgTGF5ZXJcclxuICAgKiBAc2VjdGlvbiBQb3B1cCBtZXRob2RzIGV4YW1wbGVcclxuICAgKlxyXG4gICAqIEFsbCBsYXllcnMgc2hhcmUgYSBzZXQgb2YgbWV0aG9kcyBjb252ZW5pZW50IGZvciBiaW5kaW5nIHBvcHVwcyB0byBpdC5cclxuICAgKlxyXG4gICAqIGBgYGpzXHJcbiAgICogdmFyIGxheWVyID0gTC5Qb2x5Z29uKGxhdGxuZ3MpLmJpbmRQb3B1cCgnSGkgVGhlcmUhJykuYWRkVG8obWFwKTtcclxuICAgKiBsYXllci5vcGVuUG9wdXAoKTtcclxuICAgKiBsYXllci5jbG9zZVBvcHVwKCk7XHJcbiAgICogYGBgXHJcbiAgICpcclxuICAgKiBQb3B1cHMgd2lsbCBhbHNvIGJlIGF1dG9tYXRpY2FsbHkgb3BlbmVkIHdoZW4gdGhlIGxheWVyIGlzIGNsaWNrZWQgb24gYW5kIGNsb3NlZCB3aGVuIHRoZSBsYXllciBpcyByZW1vdmVkIGZyb20gdGhlIG1hcCBvciBhbm90aGVyIHBvcHVwIGlzIG9wZW5lZC5cclxuICAgKi9cclxuXHJcbiAgLy8gQHNlY3Rpb24gUG9wdXAgbWV0aG9kc1xyXG4gIExheWVyLmluY2x1ZGUoe1xyXG5cclxuICBcdC8vIEBtZXRob2QgYmluZFBvcHVwKGNvbnRlbnQ6IFN0cmluZ3xIVE1MRWxlbWVudHxGdW5jdGlvbnxQb3B1cCwgb3B0aW9ucz86IFBvcHVwIG9wdGlvbnMpOiB0aGlzXHJcbiAgXHQvLyBCaW5kcyBhIHBvcHVwIHRvIHRoZSBsYXllciB3aXRoIHRoZSBwYXNzZWQgYGNvbnRlbnRgIGFuZCBzZXRzIHVwIHRoZVxyXG4gIFx0Ly8gbmVjZXNzYXJ5IGV2ZW50IGxpc3RlbmVycy4gSWYgYSBgRnVuY3Rpb25gIGlzIHBhc3NlZCBpdCB3aWxsIHJlY2VpdmVcclxuICBcdC8vIHRoZSBsYXllciBhcyB0aGUgZmlyc3QgYXJndW1lbnQgYW5kIHNob3VsZCByZXR1cm4gYSBgU3RyaW5nYCBvciBgSFRNTEVsZW1lbnRgLlxyXG4gIFx0YmluZFBvcHVwOiBmdW5jdGlvbiAoY29udGVudCwgb3B0aW9ucykge1xyXG4gIFx0XHR0aGlzLl9wb3B1cCA9IHRoaXMuX2luaXRPdmVybGF5KFBvcHVwLCB0aGlzLl9wb3B1cCwgY29udGVudCwgb3B0aW9ucyk7XHJcbiAgXHRcdGlmICghdGhpcy5fcG9wdXBIYW5kbGVyc0FkZGVkKSB7XHJcbiAgXHRcdFx0dGhpcy5vbih7XHJcbiAgXHRcdFx0XHRjbGljazogdGhpcy5fb3BlblBvcHVwLFxyXG4gIFx0XHRcdFx0a2V5cHJlc3M6IHRoaXMuX29uS2V5UHJlc3MsXHJcbiAgXHRcdFx0XHRyZW1vdmU6IHRoaXMuY2xvc2VQb3B1cCxcclxuICBcdFx0XHRcdG1vdmU6IHRoaXMuX21vdmVQb3B1cFxyXG4gIFx0XHRcdH0pO1xyXG4gIFx0XHRcdHRoaXMuX3BvcHVwSGFuZGxlcnNBZGRlZCA9IHRydWU7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHVuYmluZFBvcHVwKCk6IHRoaXNcclxuICBcdC8vIFJlbW92ZXMgdGhlIHBvcHVwIHByZXZpb3VzbHkgYm91bmQgd2l0aCBgYmluZFBvcHVwYC5cclxuICBcdHVuYmluZFBvcHVwOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICh0aGlzLl9wb3B1cCkge1xyXG4gIFx0XHRcdHRoaXMub2ZmKHtcclxuICBcdFx0XHRcdGNsaWNrOiB0aGlzLl9vcGVuUG9wdXAsXHJcbiAgXHRcdFx0XHRrZXlwcmVzczogdGhpcy5fb25LZXlQcmVzcyxcclxuICBcdFx0XHRcdHJlbW92ZTogdGhpcy5jbG9zZVBvcHVwLFxyXG4gIFx0XHRcdFx0bW92ZTogdGhpcy5fbW92ZVBvcHVwXHJcbiAgXHRcdFx0fSk7XHJcbiAgXHRcdFx0dGhpcy5fcG9wdXBIYW5kbGVyc0FkZGVkID0gZmFsc2U7XHJcbiAgXHRcdFx0dGhpcy5fcG9wdXAgPSBudWxsO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIG9wZW5Qb3B1cChsYXRsbmc/OiBMYXRMbmcpOiB0aGlzXHJcbiAgXHQvLyBPcGVucyB0aGUgYm91bmQgcG9wdXAgYXQgdGhlIHNwZWNpZmllZCBgbGF0bG5nYCBvciBhdCB0aGUgZGVmYXVsdCBwb3B1cCBhbmNob3IgaWYgbm8gYGxhdGxuZ2AgaXMgcGFzc2VkLlxyXG4gIFx0b3BlblBvcHVwOiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcbiAgXHRcdGlmICh0aGlzLl9wb3B1cCkge1xyXG4gIFx0XHRcdGlmICghKHRoaXMgaW5zdGFuY2VvZiBGZWF0dXJlR3JvdXApKSB7XHJcbiAgXHRcdFx0XHR0aGlzLl9wb3B1cC5fc291cmNlID0gdGhpcztcclxuICBcdFx0XHR9XHJcbiAgXHRcdFx0aWYgKHRoaXMuX3BvcHVwLl9wcmVwYXJlT3BlbihsYXRsbmcgfHwgdGhpcy5fbGF0bG5nKSkge1xyXG4gIFx0XHRcdFx0Ly8gb3BlbiB0aGUgcG9wdXAgb24gdGhlIG1hcFxyXG4gIFx0XHRcdFx0dGhpcy5fcG9wdXAub3Blbk9uKHRoaXMuX21hcCk7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGNsb3NlUG9wdXAoKTogdGhpc1xyXG4gIFx0Ly8gQ2xvc2VzIHRoZSBwb3B1cCBib3VuZCB0byB0aGlzIGxheWVyIGlmIGl0IGlzIG9wZW4uXHJcbiAgXHRjbG9zZVBvcHVwOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICh0aGlzLl9wb3B1cCkge1xyXG4gIFx0XHRcdHRoaXMuX3BvcHVwLmNsb3NlKCk7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgdG9nZ2xlUG9wdXAoKTogdGhpc1xyXG4gIFx0Ly8gT3BlbnMgb3IgY2xvc2VzIHRoZSBwb3B1cCBib3VuZCB0byB0aGlzIGxheWVyIGRlcGVuZGluZyBvbiBpdHMgY3VycmVudCBzdGF0ZS5cclxuICBcdHRvZ2dsZVBvcHVwOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICh0aGlzLl9wb3B1cCkge1xyXG4gIFx0XHRcdHRoaXMuX3BvcHVwLnRvZ2dsZSh0aGlzKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBpc1BvcHVwT3BlbigpOiBib29sZWFuXHJcbiAgXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcG9wdXAgYm91bmQgdG8gdGhpcyBsYXllciBpcyBjdXJyZW50bHkgb3Blbi5cclxuICBcdGlzUG9wdXBPcGVuOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiAodGhpcy5fcG9wdXAgPyB0aGlzLl9wb3B1cC5pc09wZW4oKSA6IGZhbHNlKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBzZXRQb3B1cENvbnRlbnQoY29udGVudDogU3RyaW5nfEhUTUxFbGVtZW50fFBvcHVwKTogdGhpc1xyXG4gIFx0Ly8gU2V0cyB0aGUgY29udGVudCBvZiB0aGUgcG9wdXAgYm91bmQgdG8gdGhpcyBsYXllci5cclxuICBcdHNldFBvcHVwQ29udGVudDogZnVuY3Rpb24gKGNvbnRlbnQpIHtcclxuICBcdFx0aWYgKHRoaXMuX3BvcHVwKSB7XHJcbiAgXHRcdFx0dGhpcy5fcG9wdXAuc2V0Q29udGVudChjb250ZW50KTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRQb3B1cCgpOiBQb3B1cFxyXG4gIFx0Ly8gUmV0dXJucyB0aGUgcG9wdXAgYm91bmQgdG8gdGhpcyBsYXllci5cclxuICBcdGdldFBvcHVwOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLl9wb3B1cDtcclxuICBcdH0sXHJcblxyXG4gIFx0X29wZW5Qb3B1cDogZnVuY3Rpb24gKGUpIHtcclxuICBcdFx0aWYgKCF0aGlzLl9wb3B1cCB8fCAhdGhpcy5fbWFwKSB7XHJcbiAgXHRcdFx0cmV0dXJuO1xyXG4gIFx0XHR9XHJcbiAgXHRcdC8vIHByZXZlbnQgbWFwIGNsaWNrXHJcbiAgXHRcdHN0b3AoZSk7XHJcblxyXG4gIFx0XHR2YXIgdGFyZ2V0ID0gZS5sYXllciB8fCBlLnRhcmdldDtcclxuICBcdFx0aWYgKHRoaXMuX3BvcHVwLl9zb3VyY2UgPT09IHRhcmdldCAmJiAhKHRhcmdldCBpbnN0YW5jZW9mIFBhdGgpKSB7XHJcbiAgXHRcdFx0Ly8gdHJlYXQgaXQgbGlrZSBhIG1hcmtlciBhbmQgZmlndXJlIG91dFxyXG4gIFx0XHRcdC8vIGlmIHdlIHNob3VsZCB0b2dnbGUgaXQgb3Blbi9jbG9zZWRcclxuICBcdFx0XHRpZiAodGhpcy5fbWFwLmhhc0xheWVyKHRoaXMuX3BvcHVwKSkge1xyXG4gIFx0XHRcdFx0dGhpcy5jbG9zZVBvcHVwKCk7XHJcbiAgXHRcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRcdHRoaXMub3BlblBvcHVwKGUubGF0bG5nKTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdFx0cmV0dXJuO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHRoaXMuX3BvcHVwLl9zb3VyY2UgPSB0YXJnZXQ7XHJcbiAgXHRcdHRoaXMub3BlblBvcHVwKGUubGF0bG5nKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X21vdmVQb3B1cDogZnVuY3Rpb24gKGUpIHtcclxuICBcdFx0dGhpcy5fcG9wdXAuc2V0TGF0TG5nKGUubGF0bG5nKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X29uS2V5UHJlc3M6IGZ1bmN0aW9uIChlKSB7XHJcbiAgXHRcdGlmIChlLm9yaWdpbmFsRXZlbnQua2V5Q29kZSA9PT0gMTMpIHtcclxuICBcdFx0XHR0aGlzLl9vcGVuUG9wdXAoZSk7XHJcbiAgXHRcdH1cclxuICBcdH1cclxuICB9KTtcblxuICAvKlxuICAgKiBAY2xhc3MgVG9vbHRpcFxuICAgKiBAaW5oZXJpdHMgRGl2T3ZlcmxheVxuICAgKiBAYWthIEwuVG9vbHRpcFxuICAgKiBVc2VkIHRvIGRpc3BsYXkgc21hbGwgdGV4dHMgb24gdG9wIG9mIG1hcCBsYXllcnMuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIElmIHlvdSB3YW50IHRvIGp1c3QgYmluZCBhIHRvb2x0aXAgdG8gbWFya2VyOlxuICAgKlxuICAgKiBgYGBqc1xuICAgKiBtYXJrZXIuYmluZFRvb2x0aXAoXCJteSB0b29sdGlwIHRleHRcIikub3BlblRvb2x0aXAoKTtcbiAgICogYGBgXG4gICAqIFBhdGggb3ZlcmxheXMgbGlrZSBwb2x5bGluZXMgYWxzbyBoYXZlIGEgYGJpbmRUb29sdGlwYCBtZXRob2QuXG4gICAqXG4gICAqIEEgdG9vbHRpcCBjYW4gYmUgYWxzbyBzdGFuZGFsb25lOlxuICAgKlxuICAgKiBgYGBqc1xuICAgKiB2YXIgdG9vbHRpcCA9IEwudG9vbHRpcCgpXG4gICAqIFx0LnNldExhdExuZyhsYXRsbmcpXG4gICAqIFx0LnNldENvbnRlbnQoJ0hlbGxvIHdvcmxkITxiciAvPlRoaXMgaXMgYSBuaWNlIHRvb2x0aXAuJylcbiAgICogXHQuYWRkVG8obWFwKTtcbiAgICogYGBgXG4gICAqIG9yXG4gICAqIGBgYGpzXG4gICAqIHZhciB0b29sdGlwID0gTC50b29sdGlwKGxhdGxuZywge2NvbnRlbnQ6ICdIZWxsbyB3b3JsZCE8YnIgLz5UaGlzIGlzIGEgbmljZSB0b29sdGlwLid9KVxuICAgKiBcdC5hZGRUbyhtYXApO1xuICAgKiBgYGBcbiAgICpcbiAgICpcbiAgICogTm90ZSBhYm91dCB0b29sdGlwIG9mZnNldC4gTGVhZmxldCB0YWtlcyB0d28gb3B0aW9ucyBpbiBjb25zaWRlcmF0aW9uXG4gICAqIGZvciBjb21wdXRpbmcgdG9vbHRpcCBvZmZzZXR0aW5nOlxuICAgKiAtIHRoZSBgb2Zmc2V0YCBUb29sdGlwIG9wdGlvbjogaXQgZGVmYXVsdHMgdG8gWzAsIDBdLCBhbmQgaXQncyBzcGVjaWZpYyB0byBvbmUgdG9vbHRpcC5cbiAgICogICBBZGQgYSBwb3NpdGl2ZSB4IG9mZnNldCB0byBtb3ZlIHRoZSB0b29sdGlwIHRvIHRoZSByaWdodCwgYW5kIGEgcG9zaXRpdmUgeSBvZmZzZXQgdG9cbiAgICogICBtb3ZlIGl0IHRvIHRoZSBib3R0b20uIE5lZ2F0aXZlcyB3aWxsIG1vdmUgdG8gdGhlIGxlZnQgYW5kIHRvcC5cbiAgICogLSB0aGUgYHRvb2x0aXBBbmNob3JgIEljb24gb3B0aW9uOiB0aGlzIHdpbGwgb25seSBiZSBjb25zaWRlcmVkIGZvciBNYXJrZXIuIFlvdVxuICAgKiAgIHNob3VsZCBhZGFwdCB0aGlzIHZhbHVlIGlmIHlvdSB1c2UgYSBjdXN0b20gaWNvbi5cbiAgICovXG5cblxuICAvLyBAbmFtZXNwYWNlIFRvb2x0aXBcbiAgdmFyIFRvb2x0aXAgPSBEaXZPdmVybGF5LmV4dGVuZCh7XG5cbiAgXHQvLyBAc2VjdGlvblxuICBcdC8vIEBha2EgVG9vbHRpcCBvcHRpb25zXG4gIFx0b3B0aW9uczoge1xuICBcdFx0Ly8gQG9wdGlvbiBwYW5lOiBTdHJpbmcgPSAndG9vbHRpcFBhbmUnXG4gIFx0XHQvLyBgTWFwIHBhbmVgIHdoZXJlIHRoZSB0b29sdGlwIHdpbGwgYmUgYWRkZWQuXG4gIFx0XHRwYW5lOiAndG9vbHRpcFBhbmUnLFxuXG4gIFx0XHQvLyBAb3B0aW9uIG9mZnNldDogUG9pbnQgPSBQb2ludCgwLCAwKVxuICBcdFx0Ly8gT3B0aW9uYWwgb2Zmc2V0IG9mIHRoZSB0b29sdGlwIHBvc2l0aW9uLlxuICBcdFx0b2Zmc2V0OiBbMCwgMF0sXG5cbiAgXHRcdC8vIEBvcHRpb24gZGlyZWN0aW9uOiBTdHJpbmcgPSAnYXV0bydcbiAgXHRcdC8vIERpcmVjdGlvbiB3aGVyZSB0byBvcGVuIHRoZSB0b29sdGlwLiBQb3NzaWJsZSB2YWx1ZXMgYXJlOiBgcmlnaHRgLCBgbGVmdGAsXG4gIFx0XHQvLyBgdG9wYCwgYGJvdHRvbWAsIGBjZW50ZXJgLCBgYXV0b2AuXG4gIFx0XHQvLyBgYXV0b2Agd2lsbCBkeW5hbWljYWxseSBzd2l0Y2ggYmV0d2VlbiBgcmlnaHRgIGFuZCBgbGVmdGAgYWNjb3JkaW5nIHRvIHRoZSB0b29sdGlwXG4gIFx0XHQvLyBwb3NpdGlvbiBvbiB0aGUgbWFwLlxuICBcdFx0ZGlyZWN0aW9uOiAnYXV0bycsXG5cbiAgXHRcdC8vIEBvcHRpb24gcGVybWFuZW50OiBCb29sZWFuID0gZmFsc2VcbiAgXHRcdC8vIFdoZXRoZXIgdG8gb3BlbiB0aGUgdG9vbHRpcCBwZXJtYW5lbnRseSBvciBvbmx5IG9uIG1vdXNlb3Zlci5cbiAgXHRcdHBlcm1hbmVudDogZmFsc2UsXG5cbiAgXHRcdC8vIEBvcHRpb24gc3RpY2t5OiBCb29sZWFuID0gZmFsc2VcbiAgXHRcdC8vIElmIHRydWUsIHRoZSB0b29sdGlwIHdpbGwgZm9sbG93IHRoZSBtb3VzZSBpbnN0ZWFkIG9mIGJlaW5nIGZpeGVkIGF0IHRoZSBmZWF0dXJlIGNlbnRlci5cbiAgXHRcdHN0aWNreTogZmFsc2UsXG5cbiAgXHRcdC8vIEBvcHRpb24gb3BhY2l0eTogTnVtYmVyID0gMC45XG4gIFx0XHQvLyBUb29sdGlwIGNvbnRhaW5lciBvcGFjaXR5LlxuICBcdFx0b3BhY2l0eTogMC45XG4gIFx0fSxcblxuICBcdG9uQWRkOiBmdW5jdGlvbiAobWFwKSB7XG4gIFx0XHREaXZPdmVybGF5LnByb3RvdHlwZS5vbkFkZC5jYWxsKHRoaXMsIG1hcCk7XG4gIFx0XHR0aGlzLnNldE9wYWNpdHkodGhpcy5vcHRpb25zLm9wYWNpdHkpO1xuXG4gIFx0XHQvLyBAbmFtZXNwYWNlIE1hcFxuICBcdFx0Ly8gQHNlY3Rpb24gVG9vbHRpcCBldmVudHNcbiAgXHRcdC8vIEBldmVudCB0b29sdGlwb3BlbjogVG9vbHRpcEV2ZW50XG4gIFx0XHQvLyBGaXJlZCB3aGVuIGEgdG9vbHRpcCBpcyBvcGVuZWQgaW4gdGhlIG1hcC5cbiAgXHRcdG1hcC5maXJlKCd0b29sdGlwb3BlbicsIHt0b29sdGlwOiB0aGlzfSk7XG5cbiAgXHRcdGlmICh0aGlzLl9zb3VyY2UpIHtcbiAgXHRcdFx0dGhpcy5hZGRFdmVudFBhcmVudCh0aGlzLl9zb3VyY2UpO1xuXG4gIFx0XHRcdC8vIEBuYW1lc3BhY2UgTGF5ZXJcbiAgXHRcdFx0Ly8gQHNlY3Rpb24gVG9vbHRpcCBldmVudHNcbiAgXHRcdFx0Ly8gQGV2ZW50IHRvb2x0aXBvcGVuOiBUb29sdGlwRXZlbnRcbiAgXHRcdFx0Ly8gRmlyZWQgd2hlbiBhIHRvb2x0aXAgYm91bmQgdG8gdGhpcyBsYXllciBpcyBvcGVuZWQuXG4gIFx0XHRcdHRoaXMuX3NvdXJjZS5maXJlKCd0b29sdGlwb3BlbicsIHt0b29sdGlwOiB0aGlzfSwgdHJ1ZSk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdG9uUmVtb3ZlOiBmdW5jdGlvbiAobWFwKSB7XG4gIFx0XHREaXZPdmVybGF5LnByb3RvdHlwZS5vblJlbW92ZS5jYWxsKHRoaXMsIG1hcCk7XG5cbiAgXHRcdC8vIEBuYW1lc3BhY2UgTWFwXG4gIFx0XHQvLyBAc2VjdGlvbiBUb29sdGlwIGV2ZW50c1xuICBcdFx0Ly8gQGV2ZW50IHRvb2x0aXBjbG9zZTogVG9vbHRpcEV2ZW50XG4gIFx0XHQvLyBGaXJlZCB3aGVuIGEgdG9vbHRpcCBpbiB0aGUgbWFwIGlzIGNsb3NlZC5cbiAgXHRcdG1hcC5maXJlKCd0b29sdGlwY2xvc2UnLCB7dG9vbHRpcDogdGhpc30pO1xuXG4gIFx0XHRpZiAodGhpcy5fc291cmNlKSB7XG4gIFx0XHRcdHRoaXMucmVtb3ZlRXZlbnRQYXJlbnQodGhpcy5fc291cmNlKTtcblxuICBcdFx0XHQvLyBAbmFtZXNwYWNlIExheWVyXG4gIFx0XHRcdC8vIEBzZWN0aW9uIFRvb2x0aXAgZXZlbnRzXG4gIFx0XHRcdC8vIEBldmVudCB0b29sdGlwY2xvc2U6IFRvb2x0aXBFdmVudFxuICBcdFx0XHQvLyBGaXJlZCB3aGVuIGEgdG9vbHRpcCBib3VuZCB0byB0aGlzIGxheWVyIGlzIGNsb3NlZC5cbiAgXHRcdFx0dGhpcy5fc291cmNlLmZpcmUoJ3Rvb2x0aXBjbG9zZScsIHt0b29sdGlwOiB0aGlzfSwgdHJ1ZSk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdGdldEV2ZW50czogZnVuY3Rpb24gKCkge1xuICBcdFx0dmFyIGV2ZW50cyA9IERpdk92ZXJsYXkucHJvdG90eXBlLmdldEV2ZW50cy5jYWxsKHRoaXMpO1xuXG4gIFx0XHRpZiAoIXRoaXMub3B0aW9ucy5wZXJtYW5lbnQpIHtcbiAgXHRcdFx0ZXZlbnRzLnByZWNsaWNrID0gdGhpcy5jbG9zZTtcbiAgXHRcdH1cblxuICBcdFx0cmV0dXJuIGV2ZW50cztcbiAgXHR9LFxuXG4gIFx0X2luaXRMYXlvdXQ6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHZhciBwcmVmaXggPSAnbGVhZmxldC10b29sdGlwJyxcbiAgXHRcdCAgICBjbGFzc05hbWUgPSBwcmVmaXggKyAnICcgKyAodGhpcy5vcHRpb25zLmNsYXNzTmFtZSB8fCAnJykgKyAnIGxlYWZsZXQtem9vbS0nICsgKHRoaXMuX3pvb21BbmltYXRlZCA/ICdhbmltYXRlZCcgOiAnaGlkZScpO1xuXG4gIFx0XHR0aGlzLl9jb250ZW50Tm9kZSA9IHRoaXMuX2NvbnRhaW5lciA9IGNyZWF0ZSQxKCdkaXYnLCBjbGFzc05hbWUpO1xuXG4gIFx0XHR0aGlzLl9jb250YWluZXIuc2V0QXR0cmlidXRlKCdyb2xlJywgJ3Rvb2x0aXAnKTtcbiAgXHRcdHRoaXMuX2NvbnRhaW5lci5zZXRBdHRyaWJ1dGUoJ2lkJywgJ2xlYWZsZXQtdG9vbHRpcC0nICsgc3RhbXAodGhpcykpO1xuICBcdH0sXG5cbiAgXHRfdXBkYXRlTGF5b3V0OiBmdW5jdGlvbiAoKSB7fSxcblxuICBcdF9hZGp1c3RQYW46IGZ1bmN0aW9uICgpIHt9LFxuXG4gIFx0X3NldFBvc2l0aW9uOiBmdW5jdGlvbiAocG9zKSB7XG4gIFx0XHR2YXIgc3ViWCwgc3ViWSxcbiAgXHRcdCAgICBtYXAgPSB0aGlzLl9tYXAsXG4gIFx0XHQgICAgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyLFxuICBcdFx0ICAgIGNlbnRlclBvaW50ID0gbWFwLmxhdExuZ1RvQ29udGFpbmVyUG9pbnQobWFwLmdldENlbnRlcigpKSxcbiAgXHRcdCAgICB0b29sdGlwUG9pbnQgPSBtYXAubGF5ZXJQb2ludFRvQ29udGFpbmVyUG9pbnQocG9zKSxcbiAgXHRcdCAgICBkaXJlY3Rpb24gPSB0aGlzLm9wdGlvbnMuZGlyZWN0aW9uLFxuICBcdFx0ICAgIHRvb2x0aXBXaWR0aCA9IGNvbnRhaW5lci5vZmZzZXRXaWR0aCxcbiAgXHRcdCAgICB0b29sdGlwSGVpZ2h0ID0gY29udGFpbmVyLm9mZnNldEhlaWdodCxcbiAgXHRcdCAgICBvZmZzZXQgPSB0b1BvaW50KHRoaXMub3B0aW9ucy5vZmZzZXQpLFxuICBcdFx0ICAgIGFuY2hvciA9IHRoaXMuX2dldEFuY2hvcigpO1xuXG4gIFx0XHRpZiAoZGlyZWN0aW9uID09PSAndG9wJykge1xuICBcdFx0XHRzdWJYID0gdG9vbHRpcFdpZHRoIC8gMjtcbiAgXHRcdFx0c3ViWSA9IHRvb2x0aXBIZWlnaHQ7XG4gIFx0XHR9IGVsc2UgaWYgKGRpcmVjdGlvbiA9PT0gJ2JvdHRvbScpIHtcbiAgXHRcdFx0c3ViWCA9IHRvb2x0aXBXaWR0aCAvIDI7XG4gIFx0XHRcdHN1YlkgPSAwO1xuICBcdFx0fSBlbHNlIGlmIChkaXJlY3Rpb24gPT09ICdjZW50ZXInKSB7XG4gIFx0XHRcdHN1YlggPSB0b29sdGlwV2lkdGggLyAyO1xuICBcdFx0XHRzdWJZID0gdG9vbHRpcEhlaWdodCAvIDI7XG4gIFx0XHR9IGVsc2UgaWYgKGRpcmVjdGlvbiA9PT0gJ3JpZ2h0Jykge1xuICBcdFx0XHRzdWJYID0gMDtcbiAgXHRcdFx0c3ViWSA9IHRvb2x0aXBIZWlnaHQgLyAyO1xuICBcdFx0fSBlbHNlIGlmIChkaXJlY3Rpb24gPT09ICdsZWZ0Jykge1xuICBcdFx0XHRzdWJYID0gdG9vbHRpcFdpZHRoO1xuICBcdFx0XHRzdWJZID0gdG9vbHRpcEhlaWdodCAvIDI7XG4gIFx0XHR9IGVsc2UgaWYgKHRvb2x0aXBQb2ludC54IDwgY2VudGVyUG9pbnQueCkge1xuICBcdFx0XHRkaXJlY3Rpb24gPSAncmlnaHQnO1xuICBcdFx0XHRzdWJYID0gMDtcbiAgXHRcdFx0c3ViWSA9IHRvb2x0aXBIZWlnaHQgLyAyO1xuICBcdFx0fSBlbHNlIHtcbiAgXHRcdFx0ZGlyZWN0aW9uID0gJ2xlZnQnO1xuICBcdFx0XHRzdWJYID0gdG9vbHRpcFdpZHRoICsgKG9mZnNldC54ICsgYW5jaG9yLngpICogMjtcbiAgXHRcdFx0c3ViWSA9IHRvb2x0aXBIZWlnaHQgLyAyO1xuICBcdFx0fVxuXG4gIFx0XHRwb3MgPSBwb3Muc3VidHJhY3QodG9Qb2ludChzdWJYLCBzdWJZLCB0cnVlKSkuYWRkKG9mZnNldCkuYWRkKGFuY2hvcik7XG5cbiAgXHRcdHJlbW92ZUNsYXNzKGNvbnRhaW5lciwgJ2xlYWZsZXQtdG9vbHRpcC1yaWdodCcpO1xuICBcdFx0cmVtb3ZlQ2xhc3MoY29udGFpbmVyLCAnbGVhZmxldC10b29sdGlwLWxlZnQnKTtcbiAgXHRcdHJlbW92ZUNsYXNzKGNvbnRhaW5lciwgJ2xlYWZsZXQtdG9vbHRpcC10b3AnKTtcbiAgXHRcdHJlbW92ZUNsYXNzKGNvbnRhaW5lciwgJ2xlYWZsZXQtdG9vbHRpcC1ib3R0b20nKTtcbiAgXHRcdGFkZENsYXNzKGNvbnRhaW5lciwgJ2xlYWZsZXQtdG9vbHRpcC0nICsgZGlyZWN0aW9uKTtcbiAgXHRcdHNldFBvc2l0aW9uKGNvbnRhaW5lciwgcG9zKTtcbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZVBvc2l0aW9uOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR2YXIgcG9zID0gdGhpcy5fbWFwLmxhdExuZ1RvTGF5ZXJQb2ludCh0aGlzLl9sYXRsbmcpO1xuICBcdFx0dGhpcy5fc2V0UG9zaXRpb24ocG9zKTtcbiAgXHR9LFxuXG4gIFx0c2V0T3BhY2l0eTogZnVuY3Rpb24gKG9wYWNpdHkpIHtcbiAgXHRcdHRoaXMub3B0aW9ucy5vcGFjaXR5ID0gb3BhY2l0eTtcblxuICBcdFx0aWYgKHRoaXMuX2NvbnRhaW5lcikge1xuICBcdFx0XHRzZXRPcGFjaXR5KHRoaXMuX2NvbnRhaW5lciwgb3BhY2l0eSk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF9hbmltYXRlWm9vbTogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdHZhciBwb3MgPSB0aGlzLl9tYXAuX2xhdExuZ1RvTmV3TGF5ZXJQb2ludCh0aGlzLl9sYXRsbmcsIGUuem9vbSwgZS5jZW50ZXIpO1xuICBcdFx0dGhpcy5fc2V0UG9zaXRpb24ocG9zKTtcbiAgXHR9LFxuXG4gIFx0X2dldEFuY2hvcjogZnVuY3Rpb24gKCkge1xuICBcdFx0Ly8gV2hlcmUgc2hvdWxkIHdlIGFuY2hvciB0aGUgdG9vbHRpcCBvbiB0aGUgc291cmNlIGxheWVyP1xuICBcdFx0cmV0dXJuIHRvUG9pbnQodGhpcy5fc291cmNlICYmIHRoaXMuX3NvdXJjZS5fZ2V0VG9vbHRpcEFuY2hvciAmJiAhdGhpcy5vcHRpb25zLnN0aWNreSA/IHRoaXMuX3NvdXJjZS5fZ2V0VG9vbHRpcEFuY2hvcigpIDogWzAsIDBdKTtcbiAgXHR9XG5cbiAgfSk7XG5cbiAgLy8gQG5hbWVzcGFjZSBUb29sdGlwXG4gIC8vIEBmYWN0b3J5IEwudG9vbHRpcChvcHRpb25zPzogVG9vbHRpcCBvcHRpb25zLCBzb3VyY2U/OiBMYXllcilcbiAgLy8gSW5zdGFudGlhdGVzIGEgYFRvb2x0aXBgIG9iamVjdCBnaXZlbiBhbiBvcHRpb25hbCBgb3B0aW9uc2Agb2JqZWN0IHRoYXQgZGVzY3JpYmVzIGl0cyBhcHBlYXJhbmNlIGFuZCBsb2NhdGlvbiBhbmQgYW4gb3B0aW9uYWwgYHNvdXJjZWAgb2JqZWN0IHRoYXQgaXMgdXNlZCB0byB0YWcgdGhlIHRvb2x0aXAgd2l0aCBhIHJlZmVyZW5jZSB0byB0aGUgTGF5ZXIgdG8gd2hpY2ggaXQgcmVmZXJzLlxuICAvLyBAYWx0ZXJuYXRpdmVcbiAgLy8gQGZhY3RvcnkgTC50b29sdGlwKGxhdGxuZzogTGF0TG5nLCBvcHRpb25zPzogVG9vbHRpcCBvcHRpb25zKVxuICAvLyBJbnN0YW50aWF0ZXMgYSBgVG9vbHRpcGAgb2JqZWN0IGdpdmVuIGBsYXRsbmdgIHdoZXJlIHRoZSB0b29sdGlwIHdpbGwgb3BlbiBhbmQgYW4gb3B0aW9uYWwgYG9wdGlvbnNgIG9iamVjdCB0aGF0IGRlc2NyaWJlcyBpdHMgYXBwZWFyYW5jZSBhbmQgbG9jYXRpb24uXG4gIHZhciB0b29sdGlwID0gZnVuY3Rpb24gKG9wdGlvbnMsIHNvdXJjZSkge1xuICBcdHJldHVybiBuZXcgVG9vbHRpcChvcHRpb25zLCBzb3VyY2UpO1xuICB9O1xuXG4gIC8vIEBuYW1lc3BhY2UgTWFwXG4gIC8vIEBzZWN0aW9uIE1ldGhvZHMgZm9yIExheWVycyBhbmQgQ29udHJvbHNcbiAgTWFwLmluY2x1ZGUoe1xuXG4gIFx0Ly8gQG1ldGhvZCBvcGVuVG9vbHRpcCh0b29sdGlwOiBUb29sdGlwKTogdGhpc1xuICBcdC8vIE9wZW5zIHRoZSBzcGVjaWZpZWQgdG9vbHRpcC5cbiAgXHQvLyBAYWx0ZXJuYXRpdmVcbiAgXHQvLyBAbWV0aG9kIG9wZW5Ub29sdGlwKGNvbnRlbnQ6IFN0cmluZ3xIVE1MRWxlbWVudCwgbGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/OiBUb29sdGlwIG9wdGlvbnMpOiB0aGlzXG4gIFx0Ly8gQ3JlYXRlcyBhIHRvb2x0aXAgd2l0aCB0aGUgc3BlY2lmaWVkIGNvbnRlbnQgYW5kIG9wdGlvbnMgYW5kIG9wZW4gaXQuXG4gIFx0b3BlblRvb2x0aXA6IGZ1bmN0aW9uICh0b29sdGlwLCBsYXRsbmcsIG9wdGlvbnMpIHtcbiAgXHRcdHRoaXMuX2luaXRPdmVybGF5KFRvb2x0aXAsIHRvb2x0aXAsIGxhdGxuZywgb3B0aW9ucylcbiAgXHRcdCAgLm9wZW5Pbih0aGlzKTtcblxuICBcdFx0cmV0dXJuIHRoaXM7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgY2xvc2VUb29sdGlwKHRvb2x0aXA6IFRvb2x0aXApOiB0aGlzXG4gIFx0Ly8gQ2xvc2VzIHRoZSB0b29sdGlwIGdpdmVuIGFzIHBhcmFtZXRlci5cbiAgXHRjbG9zZVRvb2x0aXA6IGZ1bmN0aW9uICh0b29sdGlwKSB7XG4gIFx0XHR0b29sdGlwLmNsb3NlKCk7XG4gIFx0XHRyZXR1cm4gdGhpcztcbiAgXHR9XG5cbiAgfSk7XG5cbiAgLypcbiAgICogQG5hbWVzcGFjZSBMYXllclxuICAgKiBAc2VjdGlvbiBUb29sdGlwIG1ldGhvZHMgZXhhbXBsZVxuICAgKlxuICAgKiBBbGwgbGF5ZXJzIHNoYXJlIGEgc2V0IG9mIG1ldGhvZHMgY29udmVuaWVudCBmb3IgYmluZGluZyB0b29sdGlwcyB0byBpdC5cbiAgICpcbiAgICogYGBganNcbiAgICogdmFyIGxheWVyID0gTC5Qb2x5Z29uKGxhdGxuZ3MpLmJpbmRUb29sdGlwKCdIaSBUaGVyZSEnKS5hZGRUbyhtYXApO1xuICAgKiBsYXllci5vcGVuVG9vbHRpcCgpO1xuICAgKiBsYXllci5jbG9zZVRvb2x0aXAoKTtcbiAgICogYGBgXG4gICAqL1xuXG4gIC8vIEBzZWN0aW9uIFRvb2x0aXAgbWV0aG9kc1xuICBMYXllci5pbmNsdWRlKHtcblxuICBcdC8vIEBtZXRob2QgYmluZFRvb2x0aXAoY29udGVudDogU3RyaW5nfEhUTUxFbGVtZW50fEZ1bmN0aW9ufFRvb2x0aXAsIG9wdGlvbnM/OiBUb29sdGlwIG9wdGlvbnMpOiB0aGlzXG4gIFx0Ly8gQmluZHMgYSB0b29sdGlwIHRvIHRoZSBsYXllciB3aXRoIHRoZSBwYXNzZWQgYGNvbnRlbnRgIGFuZCBzZXRzIHVwIHRoZVxuICBcdC8vIG5lY2Vzc2FyeSBldmVudCBsaXN0ZW5lcnMuIElmIGEgYEZ1bmN0aW9uYCBpcyBwYXNzZWQgaXQgd2lsbCByZWNlaXZlXG4gIFx0Ly8gdGhlIGxheWVyIGFzIHRoZSBmaXJzdCBhcmd1bWVudCBhbmQgc2hvdWxkIHJldHVybiBhIGBTdHJpbmdgIG9yIGBIVE1MRWxlbWVudGAuXG4gIFx0YmluZFRvb2x0aXA6IGZ1bmN0aW9uIChjb250ZW50LCBvcHRpb25zKSB7XG5cbiAgXHRcdGlmICh0aGlzLl90b29sdGlwICYmIHRoaXMuaXNUb29sdGlwT3BlbigpKSB7XG4gIFx0XHRcdHRoaXMudW5iaW5kVG9vbHRpcCgpO1xuICBcdFx0fVxuXG4gIFx0XHR0aGlzLl90b29sdGlwID0gdGhpcy5faW5pdE92ZXJsYXkoVG9vbHRpcCwgdGhpcy5fdG9vbHRpcCwgY29udGVudCwgb3B0aW9ucyk7XG4gIFx0XHR0aGlzLl9pbml0VG9vbHRpcEludGVyYWN0aW9ucygpO1xuXG4gIFx0XHRpZiAodGhpcy5fdG9vbHRpcC5vcHRpb25zLnBlcm1hbmVudCAmJiB0aGlzLl9tYXAgJiYgdGhpcy5fbWFwLmhhc0xheWVyKHRoaXMpKSB7XG4gIFx0XHRcdHRoaXMub3BlblRvb2x0aXAoKTtcbiAgXHRcdH1cblxuICBcdFx0cmV0dXJuIHRoaXM7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgdW5iaW5kVG9vbHRpcCgpOiB0aGlzXG4gIFx0Ly8gUmVtb3ZlcyB0aGUgdG9vbHRpcCBwcmV2aW91c2x5IGJvdW5kIHdpdGggYGJpbmRUb29sdGlwYC5cbiAgXHR1bmJpbmRUb29sdGlwOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRpZiAodGhpcy5fdG9vbHRpcCkge1xuICBcdFx0XHR0aGlzLl9pbml0VG9vbHRpcEludGVyYWN0aW9ucyh0cnVlKTtcbiAgXHRcdFx0dGhpcy5jbG9zZVRvb2x0aXAoKTtcbiAgXHRcdFx0dGhpcy5fdG9vbHRpcCA9IG51bGw7XG4gIFx0XHR9XG4gIFx0XHRyZXR1cm4gdGhpcztcbiAgXHR9LFxuXG4gIFx0X2luaXRUb29sdGlwSW50ZXJhY3Rpb25zOiBmdW5jdGlvbiAocmVtb3ZlKSB7XG4gIFx0XHRpZiAoIXJlbW92ZSAmJiB0aGlzLl90b29sdGlwSGFuZGxlcnNBZGRlZCkgeyByZXR1cm47IH1cbiAgXHRcdHZhciBvbk9mZiA9IHJlbW92ZSA/ICdvZmYnIDogJ29uJyxcbiAgXHRcdCAgICBldmVudHMgPSB7XG4gIFx0XHRcdHJlbW92ZTogdGhpcy5jbG9zZVRvb2x0aXAsXG4gIFx0XHRcdG1vdmU6IHRoaXMuX21vdmVUb29sdGlwXG4gIFx0XHQgICAgfTtcbiAgXHRcdGlmICghdGhpcy5fdG9vbHRpcC5vcHRpb25zLnBlcm1hbmVudCkge1xuICBcdFx0XHRldmVudHMubW91c2VvdmVyID0gdGhpcy5fb3BlblRvb2x0aXA7XG4gIFx0XHRcdGV2ZW50cy5tb3VzZW91dCA9IHRoaXMuY2xvc2VUb29sdGlwO1xuICBcdFx0XHRldmVudHMuY2xpY2sgPSB0aGlzLl9vcGVuVG9vbHRpcDtcbiAgXHRcdFx0aWYgKHRoaXMuX21hcCkge1xuICBcdFx0XHRcdHRoaXMuX2FkZEZvY3VzTGlzdGVuZXJzKCk7XG4gIFx0XHRcdH0gZWxzZSB7XG4gIFx0XHRcdFx0ZXZlbnRzLmFkZCA9IHRoaXMuX2FkZEZvY3VzTGlzdGVuZXJzO1xuICBcdFx0XHR9XG4gIFx0XHR9IGVsc2Uge1xuICBcdFx0XHRldmVudHMuYWRkID0gdGhpcy5fb3BlblRvb2x0aXA7XG4gIFx0XHR9XG4gIFx0XHRpZiAodGhpcy5fdG9vbHRpcC5vcHRpb25zLnN0aWNreSkge1xuICBcdFx0XHRldmVudHMubW91c2Vtb3ZlID0gdGhpcy5fbW92ZVRvb2x0aXA7XG4gIFx0XHR9XG4gIFx0XHR0aGlzW29uT2ZmXShldmVudHMpO1xuICBcdFx0dGhpcy5fdG9vbHRpcEhhbmRsZXJzQWRkZWQgPSAhcmVtb3ZlO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIG9wZW5Ub29sdGlwKGxhdGxuZz86IExhdExuZyk6IHRoaXNcbiAgXHQvLyBPcGVucyB0aGUgYm91bmQgdG9vbHRpcCBhdCB0aGUgc3BlY2lmaWVkIGBsYXRsbmdgIG9yIGF0IHRoZSBkZWZhdWx0IHRvb2x0aXAgYW5jaG9yIGlmIG5vIGBsYXRsbmdgIGlzIHBhc3NlZC5cbiAgXHRvcGVuVG9vbHRpcDogZnVuY3Rpb24gKGxhdGxuZykge1xuICBcdFx0aWYgKHRoaXMuX3Rvb2x0aXApIHtcbiAgXHRcdFx0aWYgKCEodGhpcyBpbnN0YW5jZW9mIEZlYXR1cmVHcm91cCkpIHtcbiAgXHRcdFx0XHR0aGlzLl90b29sdGlwLl9zb3VyY2UgPSB0aGlzO1xuICBcdFx0XHR9XG4gIFx0XHRcdGlmICh0aGlzLl90b29sdGlwLl9wcmVwYXJlT3BlbihsYXRsbmcpKSB7XG4gIFx0XHRcdFx0Ly8gb3BlbiB0aGUgdG9vbHRpcCBvbiB0aGUgbWFwXG4gIFx0XHRcdFx0dGhpcy5fdG9vbHRpcC5vcGVuT24odGhpcy5fbWFwKTtcblxuICBcdFx0XHRcdGlmICh0aGlzLmdldEVsZW1lbnQpIHtcbiAgXHRcdFx0XHRcdHRoaXMuX3NldEFyaWFEZXNjcmliZWRCeU9uTGF5ZXIodGhpcyk7XG4gIFx0XHRcdFx0fSBlbHNlIGlmICh0aGlzLmVhY2hMYXllcikge1xuICBcdFx0XHRcdFx0dGhpcy5lYWNoTGF5ZXIodGhpcy5fc2V0QXJpYURlc2NyaWJlZEJ5T25MYXllciwgdGhpcyk7XG4gIFx0XHRcdFx0fVxuICBcdFx0XHR9XG4gIFx0XHR9XG4gIFx0XHRyZXR1cm4gdGhpcztcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBjbG9zZVRvb2x0aXAoKTogdGhpc1xuICBcdC8vIENsb3NlcyB0aGUgdG9vbHRpcCBib3VuZCB0byB0aGlzIGxheWVyIGlmIGl0IGlzIG9wZW4uXG4gIFx0Y2xvc2VUb29sdGlwOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRpZiAodGhpcy5fdG9vbHRpcCkge1xuICBcdFx0XHRyZXR1cm4gdGhpcy5fdG9vbHRpcC5jbG9zZSgpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIHRvZ2dsZVRvb2x0aXAoKTogdGhpc1xuICBcdC8vIE9wZW5zIG9yIGNsb3NlcyB0aGUgdG9vbHRpcCBib3VuZCB0byB0aGlzIGxheWVyIGRlcGVuZGluZyBvbiBpdHMgY3VycmVudCBzdGF0ZS5cbiAgXHR0b2dnbGVUb29sdGlwOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRpZiAodGhpcy5fdG9vbHRpcCkge1xuICBcdFx0XHR0aGlzLl90b29sdGlwLnRvZ2dsZSh0aGlzKTtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiB0aGlzO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIGlzVG9vbHRpcE9wZW4oKTogYm9vbGVhblxuICBcdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSB0b29sdGlwIGJvdW5kIHRvIHRoaXMgbGF5ZXIgaXMgY3VycmVudGx5IG9wZW4uXG4gIFx0aXNUb29sdGlwT3BlbjogZnVuY3Rpb24gKCkge1xuICBcdFx0cmV0dXJuIHRoaXMuX3Rvb2x0aXAuaXNPcGVuKCk7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2Qgc2V0VG9vbHRpcENvbnRlbnQoY29udGVudDogU3RyaW5nfEhUTUxFbGVtZW50fFRvb2x0aXApOiB0aGlzXG4gIFx0Ly8gU2V0cyB0aGUgY29udGVudCBvZiB0aGUgdG9vbHRpcCBib3VuZCB0byB0aGlzIGxheWVyLlxuICBcdHNldFRvb2x0aXBDb250ZW50OiBmdW5jdGlvbiAoY29udGVudCkge1xuICBcdFx0aWYgKHRoaXMuX3Rvb2x0aXApIHtcbiAgXHRcdFx0dGhpcy5fdG9vbHRpcC5zZXRDb250ZW50KGNvbnRlbnQpO1xuICBcdFx0fVxuICBcdFx0cmV0dXJuIHRoaXM7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgZ2V0VG9vbHRpcCgpOiBUb29sdGlwXG4gIFx0Ly8gUmV0dXJucyB0aGUgdG9vbHRpcCBib3VuZCB0byB0aGlzIGxheWVyLlxuICBcdGdldFRvb2x0aXA6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHJldHVybiB0aGlzLl90b29sdGlwO1xuICBcdH0sXG5cbiAgXHRfYWRkRm9jdXNMaXN0ZW5lcnM6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICh0aGlzLmdldEVsZW1lbnQpIHtcbiAgXHRcdFx0dGhpcy5fYWRkRm9jdXNMaXN0ZW5lcnNPbkxheWVyKHRoaXMpO1xuICBcdFx0fSBlbHNlIGlmICh0aGlzLmVhY2hMYXllcikge1xuICBcdFx0XHR0aGlzLmVhY2hMYXllcih0aGlzLl9hZGRGb2N1c0xpc3RlbmVyc09uTGF5ZXIsIHRoaXMpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfYWRkRm9jdXNMaXN0ZW5lcnNPbkxheWVyOiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdHZhciBlbCA9IHR5cGVvZiBsYXllci5nZXRFbGVtZW50ID09PSAnZnVuY3Rpb24nICYmIGxheWVyLmdldEVsZW1lbnQoKTtcbiAgXHRcdGlmIChlbCkge1xuICBcdFx0XHRvbihlbCwgJ2ZvY3VzJywgZnVuY3Rpb24gKCkge1xuICBcdFx0XHRcdHRoaXMuX3Rvb2x0aXAuX3NvdXJjZSA9IGxheWVyO1xuICBcdFx0XHRcdHRoaXMub3BlblRvb2x0aXAoKTtcbiAgXHRcdFx0fSwgdGhpcyk7XG4gIFx0XHRcdG9uKGVsLCAnYmx1cicsIHRoaXMuY2xvc2VUb29sdGlwLCB0aGlzKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3NldEFyaWFEZXNjcmliZWRCeU9uTGF5ZXI6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0dmFyIGVsID0gdHlwZW9mIGxheWVyLmdldEVsZW1lbnQgPT09ICdmdW5jdGlvbicgJiYgbGF5ZXIuZ2V0RWxlbWVudCgpO1xuICBcdFx0aWYgKGVsKSB7XG4gIFx0XHRcdGVsLnNldEF0dHJpYnV0ZSgnYXJpYS1kZXNjcmliZWRieScsIHRoaXMuX3Rvb2x0aXAuX2NvbnRhaW5lci5pZCk7XG4gIFx0XHR9XG4gIFx0fSxcblxuXG4gIFx0X29wZW5Ub29sdGlwOiBmdW5jdGlvbiAoZSkge1xuICBcdFx0aWYgKCF0aGlzLl90b29sdGlwIHx8ICF0aGlzLl9tYXApIHtcbiAgXHRcdFx0cmV0dXJuO1xuICBcdFx0fVxuXG4gIFx0XHQvLyBJZiB0aGUgbWFwIGlzIG1vdmluZywgd2Ugd2lsbCBzaG93IHRoZSB0b29sdGlwIGFmdGVyIGl0J3MgZG9uZS5cbiAgXHRcdGlmICh0aGlzLl9tYXAuZHJhZ2dpbmcgJiYgdGhpcy5fbWFwLmRyYWdnaW5nLm1vdmluZygpICYmICF0aGlzLl9vcGVuT25jZUZsYWcpIHtcbiAgXHRcdFx0dGhpcy5fb3Blbk9uY2VGbGFnID0gdHJ1ZTtcbiAgXHRcdFx0dmFyIHRoYXQgPSB0aGlzO1xuICBcdFx0XHR0aGlzLl9tYXAub25jZSgnbW92ZWVuZCcsIGZ1bmN0aW9uICgpIHtcbiAgXHRcdFx0XHR0aGF0Ll9vcGVuT25jZUZsYWcgPSBmYWxzZTtcbiAgXHRcdFx0XHR0aGF0Ll9vcGVuVG9vbHRpcChlKTtcbiAgXHRcdFx0fSk7XG4gIFx0XHRcdHJldHVybjtcbiAgXHRcdH1cblxuICBcdFx0dGhpcy5fdG9vbHRpcC5fc291cmNlID0gZS5sYXllciB8fCBlLnRhcmdldDtcblxuICBcdFx0dGhpcy5vcGVuVG9vbHRpcCh0aGlzLl90b29sdGlwLm9wdGlvbnMuc3RpY2t5ID8gZS5sYXRsbmcgOiB1bmRlZmluZWQpO1xuICBcdH0sXG5cbiAgXHRfbW92ZVRvb2x0aXA6IGZ1bmN0aW9uIChlKSB7XG4gIFx0XHR2YXIgbGF0bG5nID0gZS5sYXRsbmcsIGNvbnRhaW5lclBvaW50LCBsYXllclBvaW50O1xuICBcdFx0aWYgKHRoaXMuX3Rvb2x0aXAub3B0aW9ucy5zdGlja3kgJiYgZS5vcmlnaW5hbEV2ZW50KSB7XG4gIFx0XHRcdGNvbnRhaW5lclBvaW50ID0gdGhpcy5fbWFwLm1vdXNlRXZlbnRUb0NvbnRhaW5lclBvaW50KGUub3JpZ2luYWxFdmVudCk7XG4gIFx0XHRcdGxheWVyUG9pbnQgPSB0aGlzLl9tYXAuY29udGFpbmVyUG9pbnRUb0xheWVyUG9pbnQoY29udGFpbmVyUG9pbnQpO1xuICBcdFx0XHRsYXRsbmcgPSB0aGlzLl9tYXAubGF5ZXJQb2ludFRvTGF0TG5nKGxheWVyUG9pbnQpO1xuICBcdFx0fVxuICBcdFx0dGhpcy5fdG9vbHRpcC5zZXRMYXRMbmcobGF0bG5nKTtcbiAgXHR9XG4gIH0pO1xuXG4gIC8qXG4gICAqIEBjbGFzcyBEaXZJY29uXG4gICAqIEBha2EgTC5EaXZJY29uXG4gICAqIEBpbmhlcml0cyBJY29uXG4gICAqXG4gICAqIFJlcHJlc2VudHMgYSBsaWdodHdlaWdodCBpY29uIGZvciBtYXJrZXJzIHRoYXQgdXNlcyBhIHNpbXBsZSBgPGRpdj5gXG4gICAqIGVsZW1lbnQgaW5zdGVhZCBvZiBhbiBpbWFnZS4gSW5oZXJpdHMgZnJvbSBgSWNvbmAgYnV0IGlnbm9yZXMgdGhlIGBpY29uVXJsYCBhbmQgc2hhZG93IG9wdGlvbnMuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYGpzXG4gICAqIHZhciBteUljb24gPSBMLmRpdkljb24oe2NsYXNzTmFtZTogJ215LWRpdi1pY29uJ30pO1xuICAgKiAvLyB5b3UgY2FuIHNldCAubXktZGl2LWljb24gc3R5bGVzIGluIENTU1xuICAgKlxuICAgKiBMLm1hcmtlcihbNTAuNTA1LCAzMC41N10sIHtpY29uOiBteUljb259KS5hZGRUbyhtYXApO1xuICAgKiBgYGBcbiAgICpcbiAgICogQnkgZGVmYXVsdCwgaXQgaGFzIGEgJ2xlYWZsZXQtZGl2LWljb24nIENTUyBjbGFzcyBhbmQgaXMgc3R5bGVkIGFzIGEgbGl0dGxlIHdoaXRlIHNxdWFyZSB3aXRoIGEgc2hhZG93LlxuICAgKi9cblxuICB2YXIgRGl2SWNvbiA9IEljb24uZXh0ZW5kKHtcbiAgXHRvcHRpb25zOiB7XG4gIFx0XHQvLyBAc2VjdGlvblxuICBcdFx0Ly8gQGFrYSBEaXZJY29uIG9wdGlvbnNcbiAgXHRcdGljb25TaXplOiBbMTIsIDEyXSwgLy8gYWxzbyBjYW4gYmUgc2V0IHRocm91Z2ggQ1NTXG5cbiAgXHRcdC8vIGljb25BbmNob3I6IChQb2ludCksXG4gIFx0XHQvLyBwb3B1cEFuY2hvcjogKFBvaW50KSxcblxuICBcdFx0Ly8gQG9wdGlvbiBodG1sOiBTdHJpbmd8SFRNTEVsZW1lbnQgPSAnJ1xuICBcdFx0Ly8gQ3VzdG9tIEhUTUwgY29kZSB0byBwdXQgaW5zaWRlIHRoZSBkaXYgZWxlbWVudCwgZW1wdHkgYnkgZGVmYXVsdC4gQWx0ZXJuYXRpdmVseSxcbiAgXHRcdC8vIGFuIGluc3RhbmNlIG9mIGBIVE1MRWxlbWVudGAuXG4gIFx0XHRodG1sOiBmYWxzZSxcblxuICBcdFx0Ly8gQG9wdGlvbiBiZ1BvczogUG9pbnQgPSBbMCwgMF1cbiAgXHRcdC8vIE9wdGlvbmFsIHJlbGF0aXZlIHBvc2l0aW9uIG9mIHRoZSBiYWNrZ3JvdW5kLCBpbiBwaXhlbHNcbiAgXHRcdGJnUG9zOiBudWxsLFxuXG4gIFx0XHRjbGFzc05hbWU6ICdsZWFmbGV0LWRpdi1pY29uJ1xuICBcdH0sXG5cbiAgXHRjcmVhdGVJY29uOiBmdW5jdGlvbiAob2xkSWNvbikge1xuICBcdFx0dmFyIGRpdiA9IChvbGRJY29uICYmIG9sZEljb24udGFnTmFtZSA9PT0gJ0RJVicpID8gb2xkSWNvbiA6IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpLFxuICBcdFx0ICAgIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG5cbiAgXHRcdGlmIChvcHRpb25zLmh0bWwgaW5zdGFuY2VvZiBFbGVtZW50KSB7XG4gIFx0XHRcdGVtcHR5KGRpdik7XG4gIFx0XHRcdGRpdi5hcHBlbmRDaGlsZChvcHRpb25zLmh0bWwpO1xuICBcdFx0fSBlbHNlIHtcbiAgXHRcdFx0ZGl2LmlubmVySFRNTCA9IG9wdGlvbnMuaHRtbCAhPT0gZmFsc2UgPyBvcHRpb25zLmh0bWwgOiAnJztcbiAgXHRcdH1cblxuICBcdFx0aWYgKG9wdGlvbnMuYmdQb3MpIHtcbiAgXHRcdFx0dmFyIGJnUG9zID0gdG9Qb2ludChvcHRpb25zLmJnUG9zKTtcbiAgXHRcdFx0ZGl2LnN0eWxlLmJhY2tncm91bmRQb3NpdGlvbiA9ICgtYmdQb3MueCkgKyAncHggJyArICgtYmdQb3MueSkgKyAncHgnO1xuICBcdFx0fVxuICBcdFx0dGhpcy5fc2V0SWNvblN0eWxlcyhkaXYsICdpY29uJyk7XG5cbiAgXHRcdHJldHVybiBkaXY7XG4gIFx0fSxcblxuICBcdGNyZWF0ZVNoYWRvdzogZnVuY3Rpb24gKCkge1xuICBcdFx0cmV0dXJuIG51bGw7XG4gIFx0fVxuICB9KTtcblxuICAvLyBAZmFjdG9yeSBMLmRpdkljb24ob3B0aW9uczogRGl2SWNvbiBvcHRpb25zKVxuICAvLyBDcmVhdGVzIGEgYERpdkljb25gIGluc3RhbmNlIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuXG4gIGZ1bmN0aW9uIGRpdkljb24ob3B0aW9ucykge1xuICBcdHJldHVybiBuZXcgRGl2SWNvbihvcHRpb25zKTtcbiAgfVxuXG4gIEljb24uRGVmYXVsdCA9IEljb25EZWZhdWx0O1xuXG4gIC8qXG4gICAqIEBjbGFzcyBHcmlkTGF5ZXJcbiAgICogQGluaGVyaXRzIExheWVyXG4gICAqIEBha2EgTC5HcmlkTGF5ZXJcbiAgICpcbiAgICogR2VuZXJpYyBjbGFzcyBmb3IgaGFuZGxpbmcgYSB0aWxlZCBncmlkIG9mIEhUTUwgZWxlbWVudHMuIFRoaXMgaXMgdGhlIGJhc2UgY2xhc3MgZm9yIGFsbCB0aWxlIGxheWVycyBhbmQgcmVwbGFjZXMgYFRpbGVMYXllci5DYW52YXNgLlxuICAgKiBHcmlkTGF5ZXIgY2FuIGJlIGV4dGVuZGVkIHRvIGNyZWF0ZSBhIHRpbGVkIGdyaWQgb2YgSFRNTCBlbGVtZW50cyBsaWtlIGA8Y2FudmFzPmAsIGA8aW1nPmAgb3IgYDxkaXY+YC4gR3JpZExheWVyIHdpbGwgaGFuZGxlIGNyZWF0aW5nIGFuZCBhbmltYXRpbmcgdGhlc2UgRE9NIGVsZW1lbnRzIGZvciB5b3UuXG4gICAqXG4gICAqXG4gICAqIEBzZWN0aW9uIFN5bmNocm9ub3VzIHVzYWdlXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqIFRvIGNyZWF0ZSBhIGN1c3RvbSBsYXllciwgZXh0ZW5kIEdyaWRMYXllciBhbmQgaW1wbGVtZW50IHRoZSBgY3JlYXRlVGlsZSgpYCBtZXRob2QsIHdoaWNoIHdpbGwgYmUgcGFzc2VkIGEgYFBvaW50YCBvYmplY3Qgd2l0aCB0aGUgYHhgLCBgeWAsIGFuZCBgemAgKHpvb20gbGV2ZWwpIGNvb3JkaW5hdGVzIHRvIGRyYXcgeW91ciB0aWxlLlxuICAgKlxuICAgKiBgYGBqc1xuICAgKiB2YXIgQ2FudmFzTGF5ZXIgPSBMLkdyaWRMYXllci5leHRlbmQoe1xuICAgKiAgICAgY3JlYXRlVGlsZTogZnVuY3Rpb24oY29vcmRzKXtcbiAgICogICAgICAgICAvLyBjcmVhdGUgYSA8Y2FudmFzPiBlbGVtZW50IGZvciBkcmF3aW5nXG4gICAqICAgICAgICAgdmFyIHRpbGUgPSBMLkRvbVV0aWwuY3JlYXRlKCdjYW52YXMnLCAnbGVhZmxldC10aWxlJyk7XG4gICAqXG4gICAqICAgICAgICAgLy8gc2V0dXAgdGlsZSB3aWR0aCBhbmQgaGVpZ2h0IGFjY29yZGluZyB0byB0aGUgb3B0aW9uc1xuICAgKiAgICAgICAgIHZhciBzaXplID0gdGhpcy5nZXRUaWxlU2l6ZSgpO1xuICAgKiAgICAgICAgIHRpbGUud2lkdGggPSBzaXplLng7XG4gICAqICAgICAgICAgdGlsZS5oZWlnaHQgPSBzaXplLnk7XG4gICAqXG4gICAqICAgICAgICAgLy8gZ2V0IGEgY2FudmFzIGNvbnRleHQgYW5kIGRyYXcgc29tZXRoaW5nIG9uIGl0IHVzaW5nIGNvb3Jkcy54LCBjb29yZHMueSBhbmQgY29vcmRzLnpcbiAgICogICAgICAgICB2YXIgY3R4ID0gdGlsZS5nZXRDb250ZXh0KCcyZCcpO1xuICAgKlxuICAgKiAgICAgICAgIC8vIHJldHVybiB0aGUgdGlsZSBzbyBpdCBjYW4gYmUgcmVuZGVyZWQgb24gc2NyZWVuXG4gICAqICAgICAgICAgcmV0dXJuIHRpbGU7XG4gICAqICAgICB9XG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICpcbiAgICogQHNlY3Rpb24gQXN5bmNocm9ub3VzIHVzYWdlXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqIFRpbGUgY3JlYXRpb24gY2FuIGFsc28gYmUgYXN5bmNocm9ub3VzLCB0aGlzIGlzIHVzZWZ1bCB3aGVuIHVzaW5nIGEgdGhpcmQtcGFydHkgZHJhd2luZyBsaWJyYXJ5LiBPbmNlIHRoZSB0aWxlIGlzIGZpbmlzaGVkIGRyYXdpbmcgaXQgY2FuIGJlIHBhc3NlZCB0byB0aGUgYGRvbmUoKWAgY2FsbGJhY2suXG4gICAqXG4gICAqIGBgYGpzXG4gICAqIHZhciBDYW52YXNMYXllciA9IEwuR3JpZExheWVyLmV4dGVuZCh7XG4gICAqICAgICBjcmVhdGVUaWxlOiBmdW5jdGlvbihjb29yZHMsIGRvbmUpe1xuICAgKiAgICAgICAgIHZhciBlcnJvcjtcbiAgICpcbiAgICogICAgICAgICAvLyBjcmVhdGUgYSA8Y2FudmFzPiBlbGVtZW50IGZvciBkcmF3aW5nXG4gICAqICAgICAgICAgdmFyIHRpbGUgPSBMLkRvbVV0aWwuY3JlYXRlKCdjYW52YXMnLCAnbGVhZmxldC10aWxlJyk7XG4gICAqXG4gICAqICAgICAgICAgLy8gc2V0dXAgdGlsZSB3aWR0aCBhbmQgaGVpZ2h0IGFjY29yZGluZyB0byB0aGUgb3B0aW9uc1xuICAgKiAgICAgICAgIHZhciBzaXplID0gdGhpcy5nZXRUaWxlU2l6ZSgpO1xuICAgKiAgICAgICAgIHRpbGUud2lkdGggPSBzaXplLng7XG4gICAqICAgICAgICAgdGlsZS5oZWlnaHQgPSBzaXplLnk7XG4gICAqXG4gICAqICAgICAgICAgLy8gZHJhdyBzb21ldGhpbmcgYXN5bmNocm9ub3VzbHkgYW5kIHBhc3MgdGhlIHRpbGUgdG8gdGhlIGRvbmUoKSBjYWxsYmFja1xuICAgKiAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAqICAgICAgICAgICAgIGRvbmUoZXJyb3IsIHRpbGUpO1xuICAgKiAgICAgICAgIH0sIDEwMDApO1xuICAgKlxuICAgKiAgICAgICAgIHJldHVybiB0aWxlO1xuICAgKiAgICAgfVxuICAgKiB9KTtcbiAgICogYGBgXG4gICAqXG4gICAqIEBzZWN0aW9uXG4gICAqL1xuXG5cbiAgdmFyIEdyaWRMYXllciA9IExheWVyLmV4dGVuZCh7XG5cbiAgXHQvLyBAc2VjdGlvblxuICBcdC8vIEBha2EgR3JpZExheWVyIG9wdGlvbnNcbiAgXHRvcHRpb25zOiB7XG4gIFx0XHQvLyBAb3B0aW9uIHRpbGVTaXplOiBOdW1iZXJ8UG9pbnQgPSAyNTZcbiAgXHRcdC8vIFdpZHRoIGFuZCBoZWlnaHQgb2YgdGlsZXMgaW4gdGhlIGdyaWQuIFVzZSBhIG51bWJlciBpZiB3aWR0aCBhbmQgaGVpZ2h0IGFyZSBlcXVhbCwgb3IgYEwucG9pbnQod2lkdGgsIGhlaWdodClgIG90aGVyd2lzZS5cbiAgXHRcdHRpbGVTaXplOiAyNTYsXG5cbiAgXHRcdC8vIEBvcHRpb24gb3BhY2l0eTogTnVtYmVyID0gMS4wXG4gIFx0XHQvLyBPcGFjaXR5IG9mIHRoZSB0aWxlcy4gQ2FuIGJlIHVzZWQgaW4gdGhlIGBjcmVhdGVUaWxlKClgIGZ1bmN0aW9uLlxuICBcdFx0b3BhY2l0eTogMSxcblxuICBcdFx0Ly8gQG9wdGlvbiB1cGRhdGVXaGVuSWRsZTogQm9vbGVhbiA9IChkZXBlbmRzKVxuICBcdFx0Ly8gTG9hZCBuZXcgdGlsZXMgb25seSB3aGVuIHBhbm5pbmcgZW5kcy5cbiAgXHRcdC8vIGB0cnVlYCBieSBkZWZhdWx0IG9uIG1vYmlsZSBicm93c2VycywgaW4gb3JkZXIgdG8gYXZvaWQgdG9vIG1hbnkgcmVxdWVzdHMgYW5kIGtlZXAgc21vb3RoIG5hdmlnYXRpb24uXG4gIFx0XHQvLyBgZmFsc2VgIG90aGVyd2lzZSBpbiBvcmRlciB0byBkaXNwbGF5IG5ldyB0aWxlcyBfZHVyaW5nXyBwYW5uaW5nLCBzaW5jZSBpdCBpcyBlYXN5IHRvIHBhbiBvdXRzaWRlIHRoZVxuICBcdFx0Ly8gW2BrZWVwQnVmZmVyYF0oI2dyaWRsYXllci1rZWVwYnVmZmVyKSBvcHRpb24gaW4gZGVza3RvcCBicm93c2Vycy5cbiAgXHRcdHVwZGF0ZVdoZW5JZGxlOiBCcm93c2VyLm1vYmlsZSxcblxuICBcdFx0Ly8gQG9wdGlvbiB1cGRhdGVXaGVuWm9vbWluZzogQm9vbGVhbiA9IHRydWVcbiAgXHRcdC8vIEJ5IGRlZmF1bHQsIGEgc21vb3RoIHpvb20gYW5pbWF0aW9uIChkdXJpbmcgYSBbdG91Y2ggem9vbV0oI21hcC10b3VjaHpvb20pIG9yIGEgW2BmbHlUbygpYF0oI21hcC1mbHl0bykpIHdpbGwgdXBkYXRlIGdyaWQgbGF5ZXJzIGV2ZXJ5IGludGVnZXIgem9vbSBsZXZlbC4gU2V0dGluZyB0aGlzIG9wdGlvbiB0byBgZmFsc2VgIHdpbGwgdXBkYXRlIHRoZSBncmlkIGxheWVyIG9ubHkgd2hlbiB0aGUgc21vb3RoIGFuaW1hdGlvbiBlbmRzLlxuICBcdFx0dXBkYXRlV2hlblpvb21pbmc6IHRydWUsXG5cbiAgXHRcdC8vIEBvcHRpb24gdXBkYXRlSW50ZXJ2YWw6IE51bWJlciA9IDIwMFxuICBcdFx0Ly8gVGlsZXMgd2lsbCBub3QgdXBkYXRlIG1vcmUgdGhhbiBvbmNlIGV2ZXJ5IGB1cGRhdGVJbnRlcnZhbGAgbWlsbGlzZWNvbmRzIHdoZW4gcGFubmluZy5cbiAgXHRcdHVwZGF0ZUludGVydmFsOiAyMDAsXG5cbiAgXHRcdC8vIEBvcHRpb24gekluZGV4OiBOdW1iZXIgPSAxXG4gIFx0XHQvLyBUaGUgZXhwbGljaXQgekluZGV4IG9mIHRoZSB0aWxlIGxheWVyLlxuICBcdFx0ekluZGV4OiAxLFxuXG4gIFx0XHQvLyBAb3B0aW9uIGJvdW5kczogTGF0TG5nQm91bmRzID0gdW5kZWZpbmVkXG4gIFx0XHQvLyBJZiBzZXQsIHRpbGVzIHdpbGwgb25seSBiZSBsb2FkZWQgaW5zaWRlIHRoZSBzZXQgYExhdExuZ0JvdW5kc2AuXG4gIFx0XHRib3VuZHM6IG51bGwsXG5cbiAgXHRcdC8vIEBvcHRpb24gbWluWm9vbTogTnVtYmVyID0gMFxuICBcdFx0Ly8gVGhlIG1pbmltdW0gem9vbSBsZXZlbCBkb3duIHRvIHdoaWNoIHRoaXMgbGF5ZXIgd2lsbCBiZSBkaXNwbGF5ZWQgKGluY2x1c2l2ZSkuXG4gIFx0XHRtaW5ab29tOiAwLFxuXG4gIFx0XHQvLyBAb3B0aW9uIG1heFpvb206IE51bWJlciA9IHVuZGVmaW5lZFxuICBcdFx0Ly8gVGhlIG1heGltdW0gem9vbSBsZXZlbCB1cCB0byB3aGljaCB0aGlzIGxheWVyIHdpbGwgYmUgZGlzcGxheWVkIChpbmNsdXNpdmUpLlxuICBcdFx0bWF4Wm9vbTogdW5kZWZpbmVkLFxuXG4gIFx0XHQvLyBAb3B0aW9uIG1heE5hdGl2ZVpvb206IE51bWJlciA9IHVuZGVmaW5lZFxuICBcdFx0Ly8gTWF4aW11bSB6b29tIG51bWJlciB0aGUgdGlsZSBzb3VyY2UgaGFzIGF2YWlsYWJsZS4gSWYgaXQgaXMgc3BlY2lmaWVkLFxuICBcdFx0Ly8gdGhlIHRpbGVzIG9uIGFsbCB6b29tIGxldmVscyBoaWdoZXIgdGhhbiBgbWF4TmF0aXZlWm9vbWAgd2lsbCBiZSBsb2FkZWRcbiAgXHRcdC8vIGZyb20gYG1heE5hdGl2ZVpvb21gIGxldmVsIGFuZCBhdXRvLXNjYWxlZC5cbiAgXHRcdG1heE5hdGl2ZVpvb206IHVuZGVmaW5lZCxcblxuICBcdFx0Ly8gQG9wdGlvbiBtaW5OYXRpdmVab29tOiBOdW1iZXIgPSB1bmRlZmluZWRcbiAgXHRcdC8vIE1pbmltdW0gem9vbSBudW1iZXIgdGhlIHRpbGUgc291cmNlIGhhcyBhdmFpbGFibGUuIElmIGl0IGlzIHNwZWNpZmllZCxcbiAgXHRcdC8vIHRoZSB0aWxlcyBvbiBhbGwgem9vbSBsZXZlbHMgbG93ZXIgdGhhbiBgbWluTmF0aXZlWm9vbWAgd2lsbCBiZSBsb2FkZWRcbiAgXHRcdC8vIGZyb20gYG1pbk5hdGl2ZVpvb21gIGxldmVsIGFuZCBhdXRvLXNjYWxlZC5cbiAgXHRcdG1pbk5hdGl2ZVpvb206IHVuZGVmaW5lZCxcblxuICBcdFx0Ly8gQG9wdGlvbiBub1dyYXA6IEJvb2xlYW4gPSBmYWxzZVxuICBcdFx0Ly8gV2hldGhlciB0aGUgbGF5ZXIgaXMgd3JhcHBlZCBhcm91bmQgdGhlIGFudGltZXJpZGlhbi4gSWYgYHRydWVgLCB0aGVcbiAgXHRcdC8vIEdyaWRMYXllciB3aWxsIG9ubHkgYmUgZGlzcGxheWVkIG9uY2UgYXQgbG93IHpvb20gbGV2ZWxzLiBIYXMgbm9cbiAgXHRcdC8vIGVmZmVjdCB3aGVuIHRoZSBbbWFwIENSU10oI21hcC1jcnMpIGRvZXNuJ3Qgd3JhcCBhcm91bmQuIENhbiBiZSB1c2VkXG4gIFx0XHQvLyBpbiBjb21iaW5hdGlvbiB3aXRoIFtgYm91bmRzYF0oI2dyaWRsYXllci1ib3VuZHMpIHRvIHByZXZlbnQgcmVxdWVzdGluZ1xuICBcdFx0Ly8gdGlsZXMgb3V0c2lkZSB0aGUgQ1JTIGxpbWl0cy5cbiAgXHRcdG5vV3JhcDogZmFsc2UsXG5cbiAgXHRcdC8vIEBvcHRpb24gcGFuZTogU3RyaW5nID0gJ3RpbGVQYW5lJ1xuICBcdFx0Ly8gYE1hcCBwYW5lYCB3aGVyZSB0aGUgZ3JpZCBsYXllciB3aWxsIGJlIGFkZGVkLlxuICBcdFx0cGFuZTogJ3RpbGVQYW5lJyxcblxuICBcdFx0Ly8gQG9wdGlvbiBjbGFzc05hbWU6IFN0cmluZyA9ICcnXG4gIFx0XHQvLyBBIGN1c3RvbSBjbGFzcyBuYW1lIHRvIGFzc2lnbiB0byB0aGUgdGlsZSBsYXllci4gRW1wdHkgYnkgZGVmYXVsdC5cbiAgXHRcdGNsYXNzTmFtZTogJycsXG5cbiAgXHRcdC8vIEBvcHRpb24ga2VlcEJ1ZmZlcjogTnVtYmVyID0gMlxuICBcdFx0Ly8gV2hlbiBwYW5uaW5nIHRoZSBtYXAsIGtlZXAgdGhpcyBtYW55IHJvd3MgYW5kIGNvbHVtbnMgb2YgdGlsZXMgYmVmb3JlIHVubG9hZGluZyB0aGVtLlxuICBcdFx0a2VlcEJ1ZmZlcjogMlxuICBcdH0sXG5cbiAgXHRpbml0aWFsaXplOiBmdW5jdGlvbiAob3B0aW9ucykge1xuICBcdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcbiAgXHR9LFxuXG4gIFx0b25BZGQ6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHRoaXMuX2luaXRDb250YWluZXIoKTtcblxuICBcdFx0dGhpcy5fbGV2ZWxzID0ge307XG4gIFx0XHR0aGlzLl90aWxlcyA9IHt9O1xuXG4gIFx0XHR0aGlzLl9yZXNldFZpZXcoKTsgLy8gaW1wbGljaXQgX3VwZGF0ZSgpIGNhbGxcbiAgXHR9LFxuXG4gIFx0YmVmb3JlQWRkOiBmdW5jdGlvbiAobWFwKSB7XG4gIFx0XHRtYXAuX2FkZFpvb21MaW1pdCh0aGlzKTtcbiAgXHR9LFxuXG4gIFx0b25SZW1vdmU6IGZ1bmN0aW9uIChtYXApIHtcbiAgXHRcdHRoaXMuX3JlbW92ZUFsbFRpbGVzKCk7XG4gIFx0XHRyZW1vdmUodGhpcy5fY29udGFpbmVyKTtcbiAgXHRcdG1hcC5fcmVtb3ZlWm9vbUxpbWl0KHRoaXMpO1xuICBcdFx0dGhpcy5fY29udGFpbmVyID0gbnVsbDtcbiAgXHRcdHRoaXMuX3RpbGVab29tID0gdW5kZWZpbmVkO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIGJyaW5nVG9Gcm9udDogdGhpc1xuICBcdC8vIEJyaW5ncyB0aGUgdGlsZSBsYXllciB0byB0aGUgdG9wIG9mIGFsbCB0aWxlIGxheWVycy5cbiAgXHRicmluZ1RvRnJvbnQ6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICh0aGlzLl9tYXApIHtcbiAgXHRcdFx0dG9Gcm9udCh0aGlzLl9jb250YWluZXIpO1xuICBcdFx0XHR0aGlzLl9zZXRBdXRvWkluZGV4KE1hdGgubWF4KTtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiB0aGlzO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIGJyaW5nVG9CYWNrOiB0aGlzXG4gIFx0Ly8gQnJpbmdzIHRoZSB0aWxlIGxheWVyIHRvIHRoZSBib3R0b20gb2YgYWxsIHRpbGUgbGF5ZXJzLlxuICBcdGJyaW5nVG9CYWNrOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRpZiAodGhpcy5fbWFwKSB7XG4gIFx0XHRcdHRvQmFjayh0aGlzLl9jb250YWluZXIpO1xuICBcdFx0XHR0aGlzLl9zZXRBdXRvWkluZGV4KE1hdGgubWluKTtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiB0aGlzO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIGdldENvbnRhaW5lcjogSFRNTEVsZW1lbnRcbiAgXHQvLyBSZXR1cm5zIHRoZSBIVE1MIGVsZW1lbnQgdGhhdCBjb250YWlucyB0aGUgdGlsZXMgZm9yIHRoaXMgbGF5ZXIuXG4gIFx0Z2V0Q29udGFpbmVyOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZXR1cm4gdGhpcy5fY29udGFpbmVyO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIHNldE9wYWNpdHkob3BhY2l0eTogTnVtYmVyKTogdGhpc1xuICBcdC8vIENoYW5nZXMgdGhlIFtvcGFjaXR5XSgjZ3JpZGxheWVyLW9wYWNpdHkpIG9mIHRoZSBncmlkIGxheWVyLlxuICBcdHNldE9wYWNpdHk6IGZ1bmN0aW9uIChvcGFjaXR5KSB7XG4gIFx0XHR0aGlzLm9wdGlvbnMub3BhY2l0eSA9IG9wYWNpdHk7XG4gIFx0XHR0aGlzLl91cGRhdGVPcGFjaXR5KCk7XG4gIFx0XHRyZXR1cm4gdGhpcztcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBzZXRaSW5kZXgoekluZGV4OiBOdW1iZXIpOiB0aGlzXG4gIFx0Ly8gQ2hhbmdlcyB0aGUgW3pJbmRleF0oI2dyaWRsYXllci16aW5kZXgpIG9mIHRoZSBncmlkIGxheWVyLlxuICBcdHNldFpJbmRleDogZnVuY3Rpb24gKHpJbmRleCkge1xuICBcdFx0dGhpcy5vcHRpb25zLnpJbmRleCA9IHpJbmRleDtcbiAgXHRcdHRoaXMuX3VwZGF0ZVpJbmRleCgpO1xuXG4gIFx0XHRyZXR1cm4gdGhpcztcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBpc0xvYWRpbmc6IEJvb2xlYW5cbiAgXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiBhbnkgdGlsZSBpbiB0aGUgZ3JpZCBsYXllciBoYXMgbm90IGZpbmlzaGVkIGxvYWRpbmcuXG4gIFx0aXNMb2FkaW5nOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZXR1cm4gdGhpcy5fbG9hZGluZztcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCByZWRyYXc6IHRoaXNcbiAgXHQvLyBDYXVzZXMgdGhlIGxheWVyIHRvIGNsZWFyIGFsbCB0aGUgdGlsZXMgYW5kIHJlcXVlc3QgdGhlbSBhZ2Fpbi5cbiAgXHRyZWRyYXc6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICh0aGlzLl9tYXApIHtcbiAgXHRcdFx0dGhpcy5fcmVtb3ZlQWxsVGlsZXMoKTtcbiAgXHRcdFx0dmFyIHRpbGVab29tID0gdGhpcy5fY2xhbXBab29tKHRoaXMuX21hcC5nZXRab29tKCkpO1xuICBcdFx0XHRpZiAodGlsZVpvb20gIT09IHRoaXMuX3RpbGVab29tKSB7XG4gIFx0XHRcdFx0dGhpcy5fdGlsZVpvb20gPSB0aWxlWm9vbTtcbiAgXHRcdFx0XHR0aGlzLl91cGRhdGVMZXZlbHMoKTtcbiAgXHRcdFx0fVxuICBcdFx0XHR0aGlzLl91cGRhdGUoKTtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiB0aGlzO1xuICBcdH0sXG5cbiAgXHRnZXRFdmVudHM6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHZhciBldmVudHMgPSB7XG4gIFx0XHRcdHZpZXdwcmVyZXNldDogdGhpcy5faW52YWxpZGF0ZUFsbCxcbiAgXHRcdFx0dmlld3Jlc2V0OiB0aGlzLl9yZXNldFZpZXcsXG4gIFx0XHRcdHpvb206IHRoaXMuX3Jlc2V0VmlldyxcbiAgXHRcdFx0bW92ZWVuZDogdGhpcy5fb25Nb3ZlRW5kXG4gIFx0XHR9O1xuXG4gIFx0XHRpZiAoIXRoaXMub3B0aW9ucy51cGRhdGVXaGVuSWRsZSkge1xuICBcdFx0XHQvLyB1cGRhdGUgdGlsZXMgb24gbW92ZSwgYnV0IG5vdCBtb3JlIG9mdGVuIHRoYW4gb25jZSBwZXIgZ2l2ZW4gaW50ZXJ2YWxcbiAgXHRcdFx0aWYgKCF0aGlzLl9vbk1vdmUpIHtcbiAgXHRcdFx0XHR0aGlzLl9vbk1vdmUgPSB0aHJvdHRsZSh0aGlzLl9vbk1vdmVFbmQsIHRoaXMub3B0aW9ucy51cGRhdGVJbnRlcnZhbCwgdGhpcyk7XG4gIFx0XHRcdH1cblxuICBcdFx0XHRldmVudHMubW92ZSA9IHRoaXMuX29uTW92ZTtcbiAgXHRcdH1cblxuICBcdFx0aWYgKHRoaXMuX3pvb21BbmltYXRlZCkge1xuICBcdFx0XHRldmVudHMuem9vbWFuaW0gPSB0aGlzLl9hbmltYXRlWm9vbTtcbiAgXHRcdH1cblxuICBcdFx0cmV0dXJuIGV2ZW50cztcbiAgXHR9LFxuXG4gIFx0Ly8gQHNlY3Rpb24gRXh0ZW5zaW9uIG1ldGhvZHNcbiAgXHQvLyBMYXllcnMgZXh0ZW5kaW5nIGBHcmlkTGF5ZXJgIHNoYWxsIHJlaW1wbGVtZW50IHRoZSBmb2xsb3dpbmcgbWV0aG9kLlxuICBcdC8vIEBtZXRob2QgY3JlYXRlVGlsZShjb29yZHM6IE9iamVjdCwgZG9uZT86IEZ1bmN0aW9uKTogSFRNTEVsZW1lbnRcbiAgXHQvLyBDYWxsZWQgb25seSBpbnRlcm5hbGx5LCBtdXN0IGJlIG92ZXJyaWRkZW4gYnkgY2xhc3NlcyBleHRlbmRpbmcgYEdyaWRMYXllcmAuXG4gIFx0Ly8gUmV0dXJucyB0aGUgYEhUTUxFbGVtZW50YCBjb3JyZXNwb25kaW5nIHRvIHRoZSBnaXZlbiBgY29vcmRzYC4gSWYgdGhlIGBkb25lYCBjYWxsYmFja1xuICBcdC8vIGlzIHNwZWNpZmllZCwgaXQgbXVzdCBiZSBjYWxsZWQgd2hlbiB0aGUgdGlsZSBoYXMgZmluaXNoZWQgbG9hZGluZyBhbmQgZHJhd2luZy5cbiAgXHRjcmVhdGVUaWxlOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gIFx0fSxcblxuICBcdC8vIEBzZWN0aW9uXG4gIFx0Ly8gQG1ldGhvZCBnZXRUaWxlU2l6ZTogUG9pbnRcbiAgXHQvLyBOb3JtYWxpemVzIHRoZSBbdGlsZVNpemUgb3B0aW9uXSgjZ3JpZGxheWVyLXRpbGVzaXplKSBpbnRvIGEgcG9pbnQuIFVzZWQgYnkgdGhlIGBjcmVhdGVUaWxlKClgIG1ldGhvZC5cbiAgXHRnZXRUaWxlU2l6ZTogZnVuY3Rpb24gKCkge1xuICBcdFx0dmFyIHMgPSB0aGlzLm9wdGlvbnMudGlsZVNpemU7XG4gIFx0XHRyZXR1cm4gcyBpbnN0YW5jZW9mIFBvaW50ID8gcyA6IG5ldyBQb2ludChzLCBzKTtcbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZVpJbmRleDogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKHRoaXMuX2NvbnRhaW5lciAmJiB0aGlzLm9wdGlvbnMuekluZGV4ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5vcHRpb25zLnpJbmRleCAhPT0gbnVsbCkge1xuICBcdFx0XHR0aGlzLl9jb250YWluZXIuc3R5bGUuekluZGV4ID0gdGhpcy5vcHRpb25zLnpJbmRleDtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3NldEF1dG9aSW5kZXg6IGZ1bmN0aW9uIChjb21wYXJlKSB7XG4gIFx0XHQvLyBnbyB0aHJvdWdoIGFsbCBvdGhlciBsYXllcnMgb2YgdGhlIHNhbWUgcGFuZSwgc2V0IHpJbmRleCB0byBtYXggKyAxIChmcm9udCkgb3IgbWluIC0gMSAoYmFjaylcblxuICBcdFx0dmFyIGxheWVycyA9IHRoaXMuZ2V0UGFuZSgpLmNoaWxkcmVuLFxuICBcdFx0ICAgIGVkZ2VaSW5kZXggPSAtY29tcGFyZSgtSW5maW5pdHksIEluZmluaXR5KTsgLy8gLUluZmluaXR5IGZvciBtYXgsIEluZmluaXR5IGZvciBtaW5cblxuICBcdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IGxheWVycy5sZW5ndGgsIHpJbmRleDsgaSA8IGxlbjsgaSsrKSB7XG5cbiAgXHRcdFx0ekluZGV4ID0gbGF5ZXJzW2ldLnN0eWxlLnpJbmRleDtcblxuICBcdFx0XHRpZiAobGF5ZXJzW2ldICE9PSB0aGlzLl9jb250YWluZXIgJiYgekluZGV4KSB7XG4gIFx0XHRcdFx0ZWRnZVpJbmRleCA9IGNvbXBhcmUoZWRnZVpJbmRleCwgK3pJbmRleCk7XG4gIFx0XHRcdH1cbiAgXHRcdH1cblxuICBcdFx0aWYgKGlzRmluaXRlKGVkZ2VaSW5kZXgpKSB7XG4gIFx0XHRcdHRoaXMub3B0aW9ucy56SW5kZXggPSBlZGdlWkluZGV4ICsgY29tcGFyZSgtMSwgMSk7XG4gIFx0XHRcdHRoaXMuX3VwZGF0ZVpJbmRleCgpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfdXBkYXRlT3BhY2l0eTogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKCF0aGlzLl9tYXApIHsgcmV0dXJuOyB9XG5cbiAgXHRcdC8vIElFIGRvZXNuJ3QgaW5oZXJpdCBmaWx0ZXIgb3BhY2l0eSBwcm9wZXJseSwgc28gd2UncmUgZm9yY2VkIHRvIHNldCBpdCBvbiB0aWxlc1xuICBcdFx0aWYgKEJyb3dzZXIuaWVsdDkpIHsgcmV0dXJuOyB9XG5cbiAgXHRcdHNldE9wYWNpdHkodGhpcy5fY29udGFpbmVyLCB0aGlzLm9wdGlvbnMub3BhY2l0eSk7XG5cbiAgXHRcdHZhciBub3cgPSArbmV3IERhdGUoKSxcbiAgXHRcdCAgICBuZXh0RnJhbWUgPSBmYWxzZSxcbiAgXHRcdCAgICB3aWxsUHJ1bmUgPSBmYWxzZTtcblxuICBcdFx0Zm9yICh2YXIga2V5IGluIHRoaXMuX3RpbGVzKSB7XG4gIFx0XHRcdHZhciB0aWxlID0gdGhpcy5fdGlsZXNba2V5XTtcbiAgXHRcdFx0aWYgKCF0aWxlLmN1cnJlbnQgfHwgIXRpbGUubG9hZGVkKSB7IGNvbnRpbnVlOyB9XG5cbiAgXHRcdFx0dmFyIGZhZGUgPSBNYXRoLm1pbigxLCAobm93IC0gdGlsZS5sb2FkZWQpIC8gMjAwKTtcblxuICBcdFx0XHRzZXRPcGFjaXR5KHRpbGUuZWwsIGZhZGUpO1xuICBcdFx0XHRpZiAoZmFkZSA8IDEpIHtcbiAgXHRcdFx0XHRuZXh0RnJhbWUgPSB0cnVlO1xuICBcdFx0XHR9IGVsc2Uge1xuICBcdFx0XHRcdGlmICh0aWxlLmFjdGl2ZSkge1xuICBcdFx0XHRcdFx0d2lsbFBydW5lID0gdHJ1ZTtcbiAgXHRcdFx0XHR9IGVsc2Uge1xuICBcdFx0XHRcdFx0dGhpcy5fb25PcGFxdWVUaWxlKHRpbGUpO1xuICBcdFx0XHRcdH1cbiAgXHRcdFx0XHR0aWxlLmFjdGl2ZSA9IHRydWU7XG4gIFx0XHRcdH1cbiAgXHRcdH1cblxuICBcdFx0aWYgKHdpbGxQcnVuZSAmJiAhdGhpcy5fbm9QcnVuZSkgeyB0aGlzLl9wcnVuZVRpbGVzKCk7IH1cblxuICBcdFx0aWYgKG5leHRGcmFtZSkge1xuICBcdFx0XHRjYW5jZWxBbmltRnJhbWUodGhpcy5fZmFkZUZyYW1lKTtcbiAgXHRcdFx0dGhpcy5fZmFkZUZyYW1lID0gcmVxdWVzdEFuaW1GcmFtZSh0aGlzLl91cGRhdGVPcGFjaXR5LCB0aGlzKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X29uT3BhcXVlVGlsZTogZmFsc2VGbixcblxuICBcdF9pbml0Q29udGFpbmVyOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRpZiAodGhpcy5fY29udGFpbmVyKSB7IHJldHVybjsgfVxuXG4gIFx0XHR0aGlzLl9jb250YWluZXIgPSBjcmVhdGUkMSgnZGl2JywgJ2xlYWZsZXQtbGF5ZXIgJyArICh0aGlzLm9wdGlvbnMuY2xhc3NOYW1lIHx8ICcnKSk7XG4gIFx0XHR0aGlzLl91cGRhdGVaSW5kZXgoKTtcblxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5vcGFjaXR5IDwgMSkge1xuICBcdFx0XHR0aGlzLl91cGRhdGVPcGFjaXR5KCk7XG4gIFx0XHR9XG5cbiAgXHRcdHRoaXMuZ2V0UGFuZSgpLmFwcGVuZENoaWxkKHRoaXMuX2NvbnRhaW5lcik7XG4gIFx0fSxcblxuICBcdF91cGRhdGVMZXZlbHM6IGZ1bmN0aW9uICgpIHtcblxuICBcdFx0dmFyIHpvb20gPSB0aGlzLl90aWxlWm9vbSxcbiAgXHRcdCAgICBtYXhab29tID0gdGhpcy5vcHRpb25zLm1heFpvb207XG5cbiAgXHRcdGlmICh6b29tID09PSB1bmRlZmluZWQpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfVxuXG4gIFx0XHRmb3IgKHZhciB6IGluIHRoaXMuX2xldmVscykge1xuICBcdFx0XHR6ID0gTnVtYmVyKHopO1xuICBcdFx0XHRpZiAodGhpcy5fbGV2ZWxzW3pdLmVsLmNoaWxkcmVuLmxlbmd0aCB8fCB6ID09PSB6b29tKSB7XG4gIFx0XHRcdFx0dGhpcy5fbGV2ZWxzW3pdLmVsLnN0eWxlLnpJbmRleCA9IG1heFpvb20gLSBNYXRoLmFicyh6b29tIC0geik7XG4gIFx0XHRcdFx0dGhpcy5fb25VcGRhdGVMZXZlbCh6KTtcbiAgXHRcdFx0fSBlbHNlIHtcbiAgXHRcdFx0XHRyZW1vdmUodGhpcy5fbGV2ZWxzW3pdLmVsKTtcbiAgXHRcdFx0XHR0aGlzLl9yZW1vdmVUaWxlc0F0Wm9vbSh6KTtcbiAgXHRcdFx0XHR0aGlzLl9vblJlbW92ZUxldmVsKHopO1xuICBcdFx0XHRcdGRlbGV0ZSB0aGlzLl9sZXZlbHNbel07XG4gIFx0XHRcdH1cbiAgXHRcdH1cblxuICBcdFx0dmFyIGxldmVsID0gdGhpcy5fbGV2ZWxzW3pvb21dLFxuICBcdFx0ICAgIG1hcCA9IHRoaXMuX21hcDtcblxuICBcdFx0aWYgKCFsZXZlbCkge1xuICBcdFx0XHRsZXZlbCA9IHRoaXMuX2xldmVsc1t6b29tXSA9IHt9O1xuXG4gIFx0XHRcdGxldmVsLmVsID0gY3JlYXRlJDEoJ2RpdicsICdsZWFmbGV0LXRpbGUtY29udGFpbmVyIGxlYWZsZXQtem9vbS1hbmltYXRlZCcsIHRoaXMuX2NvbnRhaW5lcik7XG4gIFx0XHRcdGxldmVsLmVsLnN0eWxlLnpJbmRleCA9IG1heFpvb207XG5cbiAgXHRcdFx0bGV2ZWwub3JpZ2luID0gbWFwLnByb2plY3QobWFwLnVucHJvamVjdChtYXAuZ2V0UGl4ZWxPcmlnaW4oKSksIHpvb20pLnJvdW5kKCk7XG4gIFx0XHRcdGxldmVsLnpvb20gPSB6b29tO1xuXG4gIFx0XHRcdHRoaXMuX3NldFpvb21UcmFuc2Zvcm0obGV2ZWwsIG1hcC5nZXRDZW50ZXIoKSwgbWFwLmdldFpvb20oKSk7XG5cbiAgXHRcdFx0Ly8gZm9yY2UgdGhlIGJyb3dzZXIgdG8gY29uc2lkZXIgdGhlIG5ld2x5IGFkZGVkIGVsZW1lbnQgZm9yIHRyYW5zaXRpb25cbiAgXHRcdFx0ZmFsc2VGbihsZXZlbC5lbC5vZmZzZXRXaWR0aCk7XG5cbiAgXHRcdFx0dGhpcy5fb25DcmVhdGVMZXZlbChsZXZlbCk7XG4gIFx0XHR9XG5cbiAgXHRcdHRoaXMuX2xldmVsID0gbGV2ZWw7XG5cbiAgXHRcdHJldHVybiBsZXZlbDtcbiAgXHR9LFxuXG4gIFx0X29uVXBkYXRlTGV2ZWw6IGZhbHNlRm4sXG5cbiAgXHRfb25SZW1vdmVMZXZlbDogZmFsc2VGbixcblxuICBcdF9vbkNyZWF0ZUxldmVsOiBmYWxzZUZuLFxuXG4gIFx0X3BydW5lVGlsZXM6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICghdGhpcy5fbWFwKSB7XG4gIFx0XHRcdHJldHVybjtcbiAgXHRcdH1cblxuICBcdFx0dmFyIGtleSwgdGlsZTtcblxuICBcdFx0dmFyIHpvb20gPSB0aGlzLl9tYXAuZ2V0Wm9vbSgpO1xuICBcdFx0aWYgKHpvb20gPiB0aGlzLm9wdGlvbnMubWF4Wm9vbSB8fFxuICBcdFx0XHR6b29tIDwgdGhpcy5vcHRpb25zLm1pblpvb20pIHtcbiAgXHRcdFx0dGhpcy5fcmVtb3ZlQWxsVGlsZXMoKTtcbiAgXHRcdFx0cmV0dXJuO1xuICBcdFx0fVxuXG4gIFx0XHRmb3IgKGtleSBpbiB0aGlzLl90aWxlcykge1xuICBcdFx0XHR0aWxlID0gdGhpcy5fdGlsZXNba2V5XTtcbiAgXHRcdFx0dGlsZS5yZXRhaW4gPSB0aWxlLmN1cnJlbnQ7XG4gIFx0XHR9XG5cbiAgXHRcdGZvciAoa2V5IGluIHRoaXMuX3RpbGVzKSB7XG4gIFx0XHRcdHRpbGUgPSB0aGlzLl90aWxlc1trZXldO1xuICBcdFx0XHRpZiAodGlsZS5jdXJyZW50ICYmICF0aWxlLmFjdGl2ZSkge1xuICBcdFx0XHRcdHZhciBjb29yZHMgPSB0aWxlLmNvb3JkcztcbiAgXHRcdFx0XHRpZiAoIXRoaXMuX3JldGFpblBhcmVudChjb29yZHMueCwgY29vcmRzLnksIGNvb3Jkcy56LCBjb29yZHMueiAtIDUpKSB7XG4gIFx0XHRcdFx0XHR0aGlzLl9yZXRhaW5DaGlsZHJlbihjb29yZHMueCwgY29vcmRzLnksIGNvb3Jkcy56LCBjb29yZHMueiArIDIpO1xuICBcdFx0XHRcdH1cbiAgXHRcdFx0fVxuICBcdFx0fVxuXG4gIFx0XHRmb3IgKGtleSBpbiB0aGlzLl90aWxlcykge1xuICBcdFx0XHRpZiAoIXRoaXMuX3RpbGVzW2tleV0ucmV0YWluKSB7XG4gIFx0XHRcdFx0dGhpcy5fcmVtb3ZlVGlsZShrZXkpO1xuICBcdFx0XHR9XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF9yZW1vdmVUaWxlc0F0Wm9vbTogZnVuY3Rpb24gKHpvb20pIHtcbiAgXHRcdGZvciAodmFyIGtleSBpbiB0aGlzLl90aWxlcykge1xuICBcdFx0XHRpZiAodGhpcy5fdGlsZXNba2V5XS5jb29yZHMueiAhPT0gem9vbSkge1xuICBcdFx0XHRcdGNvbnRpbnVlO1xuICBcdFx0XHR9XG4gIFx0XHRcdHRoaXMuX3JlbW92ZVRpbGUoa2V5KTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3JlbW92ZUFsbFRpbGVzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRmb3IgKHZhciBrZXkgaW4gdGhpcy5fdGlsZXMpIHtcbiAgXHRcdFx0dGhpcy5fcmVtb3ZlVGlsZShrZXkpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfaW52YWxpZGF0ZUFsbDogZnVuY3Rpb24gKCkge1xuICBcdFx0Zm9yICh2YXIgeiBpbiB0aGlzLl9sZXZlbHMpIHtcbiAgXHRcdFx0cmVtb3ZlKHRoaXMuX2xldmVsc1t6XS5lbCk7XG4gIFx0XHRcdHRoaXMuX29uUmVtb3ZlTGV2ZWwoTnVtYmVyKHopKTtcbiAgXHRcdFx0ZGVsZXRlIHRoaXMuX2xldmVsc1t6XTtcbiAgXHRcdH1cbiAgXHRcdHRoaXMuX3JlbW92ZUFsbFRpbGVzKCk7XG5cbiAgXHRcdHRoaXMuX3RpbGVab29tID0gdW5kZWZpbmVkO1xuICBcdH0sXG5cbiAgXHRfcmV0YWluUGFyZW50OiBmdW5jdGlvbiAoeCwgeSwgeiwgbWluWm9vbSkge1xuICBcdFx0dmFyIHgyID0gTWF0aC5mbG9vcih4IC8gMiksXG4gIFx0XHQgICAgeTIgPSBNYXRoLmZsb29yKHkgLyAyKSxcbiAgXHRcdCAgICB6MiA9IHogLSAxLFxuICBcdFx0ICAgIGNvb3JkczIgPSBuZXcgUG9pbnQoK3gyLCAreTIpO1xuICBcdFx0Y29vcmRzMi56ID0gK3oyO1xuXG4gIFx0XHR2YXIga2V5ID0gdGhpcy5fdGlsZUNvb3Jkc1RvS2V5KGNvb3JkczIpLFxuICBcdFx0ICAgIHRpbGUgPSB0aGlzLl90aWxlc1trZXldO1xuXG4gIFx0XHRpZiAodGlsZSAmJiB0aWxlLmFjdGl2ZSkge1xuICBcdFx0XHR0aWxlLnJldGFpbiA9IHRydWU7XG4gIFx0XHRcdHJldHVybiB0cnVlO1xuXG4gIFx0XHR9IGVsc2UgaWYgKHRpbGUgJiYgdGlsZS5sb2FkZWQpIHtcbiAgXHRcdFx0dGlsZS5yZXRhaW4gPSB0cnVlO1xuICBcdFx0fVxuXG4gIFx0XHRpZiAoejIgPiBtaW5ab29tKSB7XG4gIFx0XHRcdHJldHVybiB0aGlzLl9yZXRhaW5QYXJlbnQoeDIsIHkyLCB6MiwgbWluWm9vbSk7XG4gIFx0XHR9XG5cbiAgXHRcdHJldHVybiBmYWxzZTtcbiAgXHR9LFxuXG4gIFx0X3JldGFpbkNoaWxkcmVuOiBmdW5jdGlvbiAoeCwgeSwgeiwgbWF4Wm9vbSkge1xuXG4gIFx0XHRmb3IgKHZhciBpID0gMiAqIHg7IGkgPCAyICogeCArIDI7IGkrKykge1xuICBcdFx0XHRmb3IgKHZhciBqID0gMiAqIHk7IGogPCAyICogeSArIDI7IGorKykge1xuXG4gIFx0XHRcdFx0dmFyIGNvb3JkcyA9IG5ldyBQb2ludChpLCBqKTtcbiAgXHRcdFx0XHRjb29yZHMueiA9IHogKyAxO1xuXG4gIFx0XHRcdFx0dmFyIGtleSA9IHRoaXMuX3RpbGVDb29yZHNUb0tleShjb29yZHMpLFxuICBcdFx0XHRcdCAgICB0aWxlID0gdGhpcy5fdGlsZXNba2V5XTtcblxuICBcdFx0XHRcdGlmICh0aWxlICYmIHRpbGUuYWN0aXZlKSB7XG4gIFx0XHRcdFx0XHR0aWxlLnJldGFpbiA9IHRydWU7XG4gIFx0XHRcdFx0XHRjb250aW51ZTtcblxuICBcdFx0XHRcdH0gZWxzZSBpZiAodGlsZSAmJiB0aWxlLmxvYWRlZCkge1xuICBcdFx0XHRcdFx0dGlsZS5yZXRhaW4gPSB0cnVlO1xuICBcdFx0XHRcdH1cblxuICBcdFx0XHRcdGlmICh6ICsgMSA8IG1heFpvb20pIHtcbiAgXHRcdFx0XHRcdHRoaXMuX3JldGFpbkNoaWxkcmVuKGksIGosIHogKyAxLCBtYXhab29tKTtcbiAgXHRcdFx0XHR9XG4gIFx0XHRcdH1cbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3Jlc2V0VmlldzogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdHZhciBhbmltYXRpbmcgPSBlICYmIChlLnBpbmNoIHx8IGUuZmx5VG8pO1xuICBcdFx0dGhpcy5fc2V0Vmlldyh0aGlzLl9tYXAuZ2V0Q2VudGVyKCksIHRoaXMuX21hcC5nZXRab29tKCksIGFuaW1hdGluZywgYW5pbWF0aW5nKTtcbiAgXHR9LFxuXG4gIFx0X2FuaW1hdGVab29tOiBmdW5jdGlvbiAoZSkge1xuICBcdFx0dGhpcy5fc2V0VmlldyhlLmNlbnRlciwgZS56b29tLCB0cnVlLCBlLm5vVXBkYXRlKTtcbiAgXHR9LFxuXG4gIFx0X2NsYW1wWm9vbTogZnVuY3Rpb24gKHpvb20pIHtcbiAgXHRcdHZhciBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuXG4gIFx0XHRpZiAodW5kZWZpbmVkICE9PSBvcHRpb25zLm1pbk5hdGl2ZVpvb20gJiYgem9vbSA8IG9wdGlvbnMubWluTmF0aXZlWm9vbSkge1xuICBcdFx0XHRyZXR1cm4gb3B0aW9ucy5taW5OYXRpdmVab29tO1xuICBcdFx0fVxuXG4gIFx0XHRpZiAodW5kZWZpbmVkICE9PSBvcHRpb25zLm1heE5hdGl2ZVpvb20gJiYgb3B0aW9ucy5tYXhOYXRpdmVab29tIDwgem9vbSkge1xuICBcdFx0XHRyZXR1cm4gb3B0aW9ucy5tYXhOYXRpdmVab29tO1xuICBcdFx0fVxuXG4gIFx0XHRyZXR1cm4gem9vbTtcbiAgXHR9LFxuXG4gIFx0X3NldFZpZXc6IGZ1bmN0aW9uIChjZW50ZXIsIHpvb20sIG5vUHJ1bmUsIG5vVXBkYXRlKSB7XG4gIFx0XHR2YXIgdGlsZVpvb20gPSBNYXRoLnJvdW5kKHpvb20pO1xuICBcdFx0aWYgKCh0aGlzLm9wdGlvbnMubWF4Wm9vbSAhPT0gdW5kZWZpbmVkICYmIHRpbGVab29tID4gdGhpcy5vcHRpb25zLm1heFpvb20pIHx8XG4gIFx0XHQgICAgKHRoaXMub3B0aW9ucy5taW5ab29tICE9PSB1bmRlZmluZWQgJiYgdGlsZVpvb20gPCB0aGlzLm9wdGlvbnMubWluWm9vbSkpIHtcbiAgXHRcdFx0dGlsZVpvb20gPSB1bmRlZmluZWQ7XG4gIFx0XHR9IGVsc2Uge1xuICBcdFx0XHR0aWxlWm9vbSA9IHRoaXMuX2NsYW1wWm9vbSh0aWxlWm9vbSk7XG4gIFx0XHR9XG5cbiAgXHRcdHZhciB0aWxlWm9vbUNoYW5nZWQgPSB0aGlzLm9wdGlvbnMudXBkYXRlV2hlblpvb21pbmcgJiYgKHRpbGVab29tICE9PSB0aGlzLl90aWxlWm9vbSk7XG5cbiAgXHRcdGlmICghbm9VcGRhdGUgfHwgdGlsZVpvb21DaGFuZ2VkKSB7XG5cbiAgXHRcdFx0dGhpcy5fdGlsZVpvb20gPSB0aWxlWm9vbTtcblxuICBcdFx0XHRpZiAodGhpcy5fYWJvcnRMb2FkaW5nKSB7XG4gIFx0XHRcdFx0dGhpcy5fYWJvcnRMb2FkaW5nKCk7XG4gIFx0XHRcdH1cblxuICBcdFx0XHR0aGlzLl91cGRhdGVMZXZlbHMoKTtcbiAgXHRcdFx0dGhpcy5fcmVzZXRHcmlkKCk7XG5cbiAgXHRcdFx0aWYgKHRpbGVab29tICE9PSB1bmRlZmluZWQpIHtcbiAgXHRcdFx0XHR0aGlzLl91cGRhdGUoY2VudGVyKTtcbiAgXHRcdFx0fVxuXG4gIFx0XHRcdGlmICghbm9QcnVuZSkge1xuICBcdFx0XHRcdHRoaXMuX3BydW5lVGlsZXMoKTtcbiAgXHRcdFx0fVxuXG4gIFx0XHRcdC8vIEZsYWcgdG8gcHJldmVudCBfdXBkYXRlT3BhY2l0eSBmcm9tIHBydW5pbmcgdGlsZXMgZHVyaW5nXG4gIFx0XHRcdC8vIGEgem9vbSBhbmltIG9yIGEgcGluY2ggZ2VzdHVyZVxuICBcdFx0XHR0aGlzLl9ub1BydW5lID0gISFub1BydW5lO1xuICBcdFx0fVxuXG4gIFx0XHR0aGlzLl9zZXRab29tVHJhbnNmb3JtcyhjZW50ZXIsIHpvb20pO1xuICBcdH0sXG5cbiAgXHRfc2V0Wm9vbVRyYW5zZm9ybXM6IGZ1bmN0aW9uIChjZW50ZXIsIHpvb20pIHtcbiAgXHRcdGZvciAodmFyIGkgaW4gdGhpcy5fbGV2ZWxzKSB7XG4gIFx0XHRcdHRoaXMuX3NldFpvb21UcmFuc2Zvcm0odGhpcy5fbGV2ZWxzW2ldLCBjZW50ZXIsIHpvb20pO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfc2V0Wm9vbVRyYW5zZm9ybTogZnVuY3Rpb24gKGxldmVsLCBjZW50ZXIsIHpvb20pIHtcbiAgXHRcdHZhciBzY2FsZSA9IHRoaXMuX21hcC5nZXRab29tU2NhbGUoem9vbSwgbGV2ZWwuem9vbSksXG4gIFx0XHQgICAgdHJhbnNsYXRlID0gbGV2ZWwub3JpZ2luLm11bHRpcGx5Qnkoc2NhbGUpXG4gIFx0XHQgICAgICAgIC5zdWJ0cmFjdCh0aGlzLl9tYXAuX2dldE5ld1BpeGVsT3JpZ2luKGNlbnRlciwgem9vbSkpLnJvdW5kKCk7XG5cbiAgXHRcdGlmIChCcm93c2VyLmFueTNkKSB7XG4gIFx0XHRcdHNldFRyYW5zZm9ybShsZXZlbC5lbCwgdHJhbnNsYXRlLCBzY2FsZSk7XG4gIFx0XHR9IGVsc2Uge1xuICBcdFx0XHRzZXRQb3NpdGlvbihsZXZlbC5lbCwgdHJhbnNsYXRlKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3Jlc2V0R3JpZDogZnVuY3Rpb24gKCkge1xuICBcdFx0dmFyIG1hcCA9IHRoaXMuX21hcCxcbiAgXHRcdCAgICBjcnMgPSBtYXAub3B0aW9ucy5jcnMsXG4gIFx0XHQgICAgdGlsZVNpemUgPSB0aGlzLl90aWxlU2l6ZSA9IHRoaXMuZ2V0VGlsZVNpemUoKSxcbiAgXHRcdCAgICB0aWxlWm9vbSA9IHRoaXMuX3RpbGVab29tO1xuXG4gIFx0XHR2YXIgYm91bmRzID0gdGhpcy5fbWFwLmdldFBpeGVsV29ybGRCb3VuZHModGhpcy5fdGlsZVpvb20pO1xuICBcdFx0aWYgKGJvdW5kcykge1xuICBcdFx0XHR0aGlzLl9nbG9iYWxUaWxlUmFuZ2UgPSB0aGlzLl9weEJvdW5kc1RvVGlsZVJhbmdlKGJvdW5kcyk7XG4gIFx0XHR9XG5cbiAgXHRcdHRoaXMuX3dyYXBYID0gY3JzLndyYXBMbmcgJiYgIXRoaXMub3B0aW9ucy5ub1dyYXAgJiYgW1xuICBcdFx0XHRNYXRoLmZsb29yKG1hcC5wcm9qZWN0KFswLCBjcnMud3JhcExuZ1swXV0sIHRpbGVab29tKS54IC8gdGlsZVNpemUueCksXG4gIFx0XHRcdE1hdGguY2VpbChtYXAucHJvamVjdChbMCwgY3JzLndyYXBMbmdbMV1dLCB0aWxlWm9vbSkueCAvIHRpbGVTaXplLnkpXG4gIFx0XHRdO1xuICBcdFx0dGhpcy5fd3JhcFkgPSBjcnMud3JhcExhdCAmJiAhdGhpcy5vcHRpb25zLm5vV3JhcCAmJiBbXG4gIFx0XHRcdE1hdGguZmxvb3IobWFwLnByb2plY3QoW2Nycy53cmFwTGF0WzBdLCAwXSwgdGlsZVpvb20pLnkgLyB0aWxlU2l6ZS54KSxcbiAgXHRcdFx0TWF0aC5jZWlsKG1hcC5wcm9qZWN0KFtjcnMud3JhcExhdFsxXSwgMF0sIHRpbGVab29tKS55IC8gdGlsZVNpemUueSlcbiAgXHRcdF07XG4gIFx0fSxcblxuICBcdF9vbk1vdmVFbmQ6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICghdGhpcy5fbWFwIHx8IHRoaXMuX21hcC5fYW5pbWF0aW5nWm9vbSkgeyByZXR1cm47IH1cblxuICBcdFx0dGhpcy5fdXBkYXRlKCk7XG4gIFx0fSxcblxuICBcdF9nZXRUaWxlZFBpeGVsQm91bmRzOiBmdW5jdGlvbiAoY2VudGVyKSB7XG4gIFx0XHR2YXIgbWFwID0gdGhpcy5fbWFwLFxuICBcdFx0ICAgIG1hcFpvb20gPSBtYXAuX2FuaW1hdGluZ1pvb20gPyBNYXRoLm1heChtYXAuX2FuaW1hdGVUb1pvb20sIG1hcC5nZXRab29tKCkpIDogbWFwLmdldFpvb20oKSxcbiAgXHRcdCAgICBzY2FsZSA9IG1hcC5nZXRab29tU2NhbGUobWFwWm9vbSwgdGhpcy5fdGlsZVpvb20pLFxuICBcdFx0ICAgIHBpeGVsQ2VudGVyID0gbWFwLnByb2plY3QoY2VudGVyLCB0aGlzLl90aWxlWm9vbSkuZmxvb3IoKSxcbiAgXHRcdCAgICBoYWxmU2l6ZSA9IG1hcC5nZXRTaXplKCkuZGl2aWRlQnkoc2NhbGUgKiAyKTtcblxuICBcdFx0cmV0dXJuIG5ldyBCb3VuZHMocGl4ZWxDZW50ZXIuc3VidHJhY3QoaGFsZlNpemUpLCBwaXhlbENlbnRlci5hZGQoaGFsZlNpemUpKTtcbiAgXHR9LFxuXG4gIFx0Ly8gUHJpdmF0ZSBtZXRob2QgdG8gbG9hZCB0aWxlcyBpbiB0aGUgZ3JpZCdzIGFjdGl2ZSB6b29tIGxldmVsIGFjY29yZGluZyB0byBtYXAgYm91bmRzXG4gIFx0X3VwZGF0ZTogZnVuY3Rpb24gKGNlbnRlcikge1xuICBcdFx0dmFyIG1hcCA9IHRoaXMuX21hcDtcbiAgXHRcdGlmICghbWFwKSB7IHJldHVybjsgfVxuICBcdFx0dmFyIHpvb20gPSB0aGlzLl9jbGFtcFpvb20obWFwLmdldFpvb20oKSk7XG5cbiAgXHRcdGlmIChjZW50ZXIgPT09IHVuZGVmaW5lZCkgeyBjZW50ZXIgPSBtYXAuZ2V0Q2VudGVyKCk7IH1cbiAgXHRcdGlmICh0aGlzLl90aWxlWm9vbSA9PT0gdW5kZWZpbmVkKSB7IHJldHVybjsgfVx0Ly8gaWYgb3V0IG9mIG1pbnpvb20vbWF4em9vbVxuXG4gIFx0XHR2YXIgcGl4ZWxCb3VuZHMgPSB0aGlzLl9nZXRUaWxlZFBpeGVsQm91bmRzKGNlbnRlciksXG4gIFx0XHQgICAgdGlsZVJhbmdlID0gdGhpcy5fcHhCb3VuZHNUb1RpbGVSYW5nZShwaXhlbEJvdW5kcyksXG4gIFx0XHQgICAgdGlsZUNlbnRlciA9IHRpbGVSYW5nZS5nZXRDZW50ZXIoKSxcbiAgXHRcdCAgICBxdWV1ZSA9IFtdLFxuICBcdFx0ICAgIG1hcmdpbiA9IHRoaXMub3B0aW9ucy5rZWVwQnVmZmVyLFxuICBcdFx0ICAgIG5vUHJ1bmVSYW5nZSA9IG5ldyBCb3VuZHModGlsZVJhbmdlLmdldEJvdHRvbUxlZnQoKS5zdWJ0cmFjdChbbWFyZ2luLCAtbWFyZ2luXSksXG4gIFx0XHQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWxlUmFuZ2UuZ2V0VG9wUmlnaHQoKS5hZGQoW21hcmdpbiwgLW1hcmdpbl0pKTtcblxuICBcdFx0Ly8gU2FuaXR5IGNoZWNrOiBwYW5pYyBpZiB0aGUgdGlsZSByYW5nZSBjb250YWlucyBJbmZpbml0eSBzb21ld2hlcmUuXG4gIFx0XHRpZiAoIShpc0Zpbml0ZSh0aWxlUmFuZ2UubWluLngpICYmXG4gIFx0XHQgICAgICBpc0Zpbml0ZSh0aWxlUmFuZ2UubWluLnkpICYmXG4gIFx0XHQgICAgICBpc0Zpbml0ZSh0aWxlUmFuZ2UubWF4LngpICYmXG4gIFx0XHQgICAgICBpc0Zpbml0ZSh0aWxlUmFuZ2UubWF4LnkpKSkgeyB0aHJvdyBuZXcgRXJyb3IoJ0F0dGVtcHRlZCB0byBsb2FkIGFuIGluZmluaXRlIG51bWJlciBvZiB0aWxlcycpOyB9XG5cbiAgXHRcdGZvciAodmFyIGtleSBpbiB0aGlzLl90aWxlcykge1xuICBcdFx0XHR2YXIgYyA9IHRoaXMuX3RpbGVzW2tleV0uY29vcmRzO1xuICBcdFx0XHRpZiAoYy56ICE9PSB0aGlzLl90aWxlWm9vbSB8fCAhbm9QcnVuZVJhbmdlLmNvbnRhaW5zKG5ldyBQb2ludChjLngsIGMueSkpKSB7XG4gIFx0XHRcdFx0dGhpcy5fdGlsZXNba2V5XS5jdXJyZW50ID0gZmFsc2U7XG4gIFx0XHRcdH1cbiAgXHRcdH1cblxuICBcdFx0Ly8gX3VwZGF0ZSBqdXN0IGxvYWRzIG1vcmUgdGlsZXMuIElmIHRoZSB0aWxlIHpvb20gbGV2ZWwgZGlmZmVycyB0b28gbXVjaFxuICBcdFx0Ly8gZnJvbSB0aGUgbWFwJ3MsIGxldCBfc2V0VmlldyByZXNldCBsZXZlbHMgYW5kIHBydW5lIG9sZCB0aWxlcy5cbiAgXHRcdGlmIChNYXRoLmFicyh6b29tIC0gdGhpcy5fdGlsZVpvb20pID4gMSkgeyB0aGlzLl9zZXRWaWV3KGNlbnRlciwgem9vbSk7IHJldHVybjsgfVxuXG4gIFx0XHQvLyBjcmVhdGUgYSBxdWV1ZSBvZiBjb29yZGluYXRlcyB0byBsb2FkIHRpbGVzIGZyb21cbiAgXHRcdGZvciAodmFyIGogPSB0aWxlUmFuZ2UubWluLnk7IGogPD0gdGlsZVJhbmdlLm1heC55OyBqKyspIHtcbiAgXHRcdFx0Zm9yICh2YXIgaSA9IHRpbGVSYW5nZS5taW4ueDsgaSA8PSB0aWxlUmFuZ2UubWF4Lng7IGkrKykge1xuICBcdFx0XHRcdHZhciBjb29yZHMgPSBuZXcgUG9pbnQoaSwgaik7XG4gIFx0XHRcdFx0Y29vcmRzLnogPSB0aGlzLl90aWxlWm9vbTtcblxuICBcdFx0XHRcdGlmICghdGhpcy5faXNWYWxpZFRpbGUoY29vcmRzKSkgeyBjb250aW51ZTsgfVxuXG4gIFx0XHRcdFx0dmFyIHRpbGUgPSB0aGlzLl90aWxlc1t0aGlzLl90aWxlQ29vcmRzVG9LZXkoY29vcmRzKV07XG4gIFx0XHRcdFx0aWYgKHRpbGUpIHtcbiAgXHRcdFx0XHRcdHRpbGUuY3VycmVudCA9IHRydWU7XG4gIFx0XHRcdFx0fSBlbHNlIHtcbiAgXHRcdFx0XHRcdHF1ZXVlLnB1c2goY29vcmRzKTtcbiAgXHRcdFx0XHR9XG4gIFx0XHRcdH1cbiAgXHRcdH1cblxuICBcdFx0Ly8gc29ydCB0aWxlIHF1ZXVlIHRvIGxvYWQgdGlsZXMgaW4gb3JkZXIgb2YgdGhlaXIgZGlzdGFuY2UgdG8gY2VudGVyXG4gIFx0XHRxdWV1ZS5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gIFx0XHRcdHJldHVybiBhLmRpc3RhbmNlVG8odGlsZUNlbnRlcikgLSBiLmRpc3RhbmNlVG8odGlsZUNlbnRlcik7XG4gIFx0XHR9KTtcblxuICBcdFx0aWYgKHF1ZXVlLmxlbmd0aCAhPT0gMCkge1xuICBcdFx0XHQvLyBpZiBpdCdzIHRoZSBmaXJzdCBiYXRjaCBvZiB0aWxlcyB0byBsb2FkXG4gIFx0XHRcdGlmICghdGhpcy5fbG9hZGluZykge1xuICBcdFx0XHRcdHRoaXMuX2xvYWRpbmcgPSB0cnVlO1xuICBcdFx0XHRcdC8vIEBldmVudCBsb2FkaW5nOiBFdmVudFxuICBcdFx0XHRcdC8vIEZpcmVkIHdoZW4gdGhlIGdyaWQgbGF5ZXIgc3RhcnRzIGxvYWRpbmcgdGlsZXMuXG4gIFx0XHRcdFx0dGhpcy5maXJlKCdsb2FkaW5nJyk7XG4gIFx0XHRcdH1cblxuICBcdFx0XHQvLyBjcmVhdGUgRE9NIGZyYWdtZW50IHRvIGFwcGVuZCB0aWxlcyBpbiBvbmUgYmF0Y2hcbiAgXHRcdFx0dmFyIGZyYWdtZW50ID0gZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpO1xuXG4gIFx0XHRcdGZvciAoaSA9IDA7IGkgPCBxdWV1ZS5sZW5ndGg7IGkrKykge1xuICBcdFx0XHRcdHRoaXMuX2FkZFRpbGUocXVldWVbaV0sIGZyYWdtZW50KTtcbiAgXHRcdFx0fVxuXG4gIFx0XHRcdHRoaXMuX2xldmVsLmVsLmFwcGVuZENoaWxkKGZyYWdtZW50KTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X2lzVmFsaWRUaWxlOiBmdW5jdGlvbiAoY29vcmRzKSB7XG4gIFx0XHR2YXIgY3JzID0gdGhpcy5fbWFwLm9wdGlvbnMuY3JzO1xuXG4gIFx0XHRpZiAoIWNycy5pbmZpbml0ZSkge1xuICBcdFx0XHQvLyBkb24ndCBsb2FkIHRpbGUgaWYgaXQncyBvdXQgb2YgYm91bmRzIGFuZCBub3Qgd3JhcHBlZFxuICBcdFx0XHR2YXIgYm91bmRzID0gdGhpcy5fZ2xvYmFsVGlsZVJhbmdlO1xuICBcdFx0XHRpZiAoKCFjcnMud3JhcExuZyAmJiAoY29vcmRzLnggPCBib3VuZHMubWluLnggfHwgY29vcmRzLnggPiBib3VuZHMubWF4LngpKSB8fFxuICBcdFx0XHQgICAgKCFjcnMud3JhcExhdCAmJiAoY29vcmRzLnkgPCBib3VuZHMubWluLnkgfHwgY29vcmRzLnkgPiBib3VuZHMubWF4LnkpKSkgeyByZXR1cm4gZmFsc2U7IH1cbiAgXHRcdH1cblxuICBcdFx0aWYgKCF0aGlzLm9wdGlvbnMuYm91bmRzKSB7IHJldHVybiB0cnVlOyB9XG5cbiAgXHRcdC8vIGRvbid0IGxvYWQgdGlsZSBpZiBpdCBkb2Vzbid0IGludGVyc2VjdCB0aGUgYm91bmRzIGluIG9wdGlvbnNcbiAgXHRcdHZhciB0aWxlQm91bmRzID0gdGhpcy5fdGlsZUNvb3Jkc1RvQm91bmRzKGNvb3Jkcyk7XG4gIFx0XHRyZXR1cm4gdG9MYXRMbmdCb3VuZHModGhpcy5vcHRpb25zLmJvdW5kcykub3ZlcmxhcHModGlsZUJvdW5kcyk7XG4gIFx0fSxcblxuICBcdF9rZXlUb0JvdW5kczogZnVuY3Rpb24gKGtleSkge1xuICBcdFx0cmV0dXJuIHRoaXMuX3RpbGVDb29yZHNUb0JvdW5kcyh0aGlzLl9rZXlUb1RpbGVDb29yZHMoa2V5KSk7XG4gIFx0fSxcblxuICBcdF90aWxlQ29vcmRzVG9Od1NlOiBmdW5jdGlvbiAoY29vcmRzKSB7XG4gIFx0XHR2YXIgbWFwID0gdGhpcy5fbWFwLFxuICBcdFx0ICAgIHRpbGVTaXplID0gdGhpcy5nZXRUaWxlU2l6ZSgpLFxuICBcdFx0ICAgIG53UG9pbnQgPSBjb29yZHMuc2NhbGVCeSh0aWxlU2l6ZSksXG4gIFx0XHQgICAgc2VQb2ludCA9IG53UG9pbnQuYWRkKHRpbGVTaXplKSxcbiAgXHRcdCAgICBudyA9IG1hcC51bnByb2plY3QobndQb2ludCwgY29vcmRzLnopLFxuICBcdFx0ICAgIHNlID0gbWFwLnVucHJvamVjdChzZVBvaW50LCBjb29yZHMueik7XG4gIFx0XHRyZXR1cm4gW253LCBzZV07XG4gIFx0fSxcblxuICBcdC8vIGNvbnZlcnRzIHRpbGUgY29vcmRpbmF0ZXMgdG8gaXRzIGdlb2dyYXBoaWNhbCBib3VuZHNcbiAgXHRfdGlsZUNvb3Jkc1RvQm91bmRzOiBmdW5jdGlvbiAoY29vcmRzKSB7XG4gIFx0XHR2YXIgYnAgPSB0aGlzLl90aWxlQ29vcmRzVG9Od1NlKGNvb3JkcyksXG4gIFx0XHQgICAgYm91bmRzID0gbmV3IExhdExuZ0JvdW5kcyhicFswXSwgYnBbMV0pO1xuXG4gIFx0XHRpZiAoIXRoaXMub3B0aW9ucy5ub1dyYXApIHtcbiAgXHRcdFx0Ym91bmRzID0gdGhpcy5fbWFwLndyYXBMYXRMbmdCb3VuZHMoYm91bmRzKTtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiBib3VuZHM7XG4gIFx0fSxcbiAgXHQvLyBjb252ZXJ0cyB0aWxlIGNvb3JkaW5hdGVzIHRvIGtleSBmb3IgdGhlIHRpbGUgY2FjaGVcbiAgXHRfdGlsZUNvb3Jkc1RvS2V5OiBmdW5jdGlvbiAoY29vcmRzKSB7XG4gIFx0XHRyZXR1cm4gY29vcmRzLnggKyAnOicgKyBjb29yZHMueSArICc6JyArIGNvb3Jkcy56O1xuICBcdH0sXG5cbiAgXHQvLyBjb252ZXJ0cyB0aWxlIGNhY2hlIGtleSB0byBjb29yZGluYXRlc1xuICBcdF9rZXlUb1RpbGVDb29yZHM6IGZ1bmN0aW9uIChrZXkpIHtcbiAgXHRcdHZhciBrID0ga2V5LnNwbGl0KCc6JyksXG4gIFx0XHQgICAgY29vcmRzID0gbmV3IFBvaW50KCtrWzBdLCAra1sxXSk7XG4gIFx0XHRjb29yZHMueiA9ICtrWzJdO1xuICBcdFx0cmV0dXJuIGNvb3JkcztcbiAgXHR9LFxuXG4gIFx0X3JlbW92ZVRpbGU6IGZ1bmN0aW9uIChrZXkpIHtcbiAgXHRcdHZhciB0aWxlID0gdGhpcy5fdGlsZXNba2V5XTtcbiAgXHRcdGlmICghdGlsZSkgeyByZXR1cm47IH1cblxuICBcdFx0cmVtb3ZlKHRpbGUuZWwpO1xuXG4gIFx0XHRkZWxldGUgdGhpcy5fdGlsZXNba2V5XTtcblxuICBcdFx0Ly8gQGV2ZW50IHRpbGV1bmxvYWQ6IFRpbGVFdmVudFxuICBcdFx0Ly8gRmlyZWQgd2hlbiBhIHRpbGUgaXMgcmVtb3ZlZCAoZS5nLiB3aGVuIGEgdGlsZSBnb2VzIG9mZiB0aGUgc2NyZWVuKS5cbiAgXHRcdHRoaXMuZmlyZSgndGlsZXVubG9hZCcsIHtcbiAgXHRcdFx0dGlsZTogdGlsZS5lbCxcbiAgXHRcdFx0Y29vcmRzOiB0aGlzLl9rZXlUb1RpbGVDb29yZHMoa2V5KVxuICBcdFx0fSk7XG4gIFx0fSxcblxuICBcdF9pbml0VGlsZTogZnVuY3Rpb24gKHRpbGUpIHtcbiAgXHRcdGFkZENsYXNzKHRpbGUsICdsZWFmbGV0LXRpbGUnKTtcblxuICBcdFx0dmFyIHRpbGVTaXplID0gdGhpcy5nZXRUaWxlU2l6ZSgpO1xuICBcdFx0dGlsZS5zdHlsZS53aWR0aCA9IHRpbGVTaXplLnggKyAncHgnO1xuICBcdFx0dGlsZS5zdHlsZS5oZWlnaHQgPSB0aWxlU2l6ZS55ICsgJ3B4JztcblxuICBcdFx0dGlsZS5vbnNlbGVjdHN0YXJ0ID0gZmFsc2VGbjtcbiAgXHRcdHRpbGUub25tb3VzZW1vdmUgPSBmYWxzZUZuO1xuXG4gIFx0XHQvLyB1cGRhdGUgb3BhY2l0eSBvbiB0aWxlcyBpbiBJRTctOCBiZWNhdXNlIG9mIGZpbHRlciBpbmhlcml0YW5jZSBwcm9ibGVtc1xuICBcdFx0aWYgKEJyb3dzZXIuaWVsdDkgJiYgdGhpcy5vcHRpb25zLm9wYWNpdHkgPCAxKSB7XG4gIFx0XHRcdHNldE9wYWNpdHkodGlsZSwgdGhpcy5vcHRpb25zLm9wYWNpdHkpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfYWRkVGlsZTogZnVuY3Rpb24gKGNvb3JkcywgY29udGFpbmVyKSB7XG4gIFx0XHR2YXIgdGlsZVBvcyA9IHRoaXMuX2dldFRpbGVQb3MoY29vcmRzKSxcbiAgXHRcdCAgICBrZXkgPSB0aGlzLl90aWxlQ29vcmRzVG9LZXkoY29vcmRzKTtcblxuICBcdFx0dmFyIHRpbGUgPSB0aGlzLmNyZWF0ZVRpbGUodGhpcy5fd3JhcENvb3Jkcyhjb29yZHMpLCBiaW5kKHRoaXMuX3RpbGVSZWFkeSwgdGhpcywgY29vcmRzKSk7XG5cbiAgXHRcdHRoaXMuX2luaXRUaWxlKHRpbGUpO1xuXG4gIFx0XHQvLyBpZiBjcmVhdGVUaWxlIGlzIGRlZmluZWQgd2l0aCBhIHNlY29uZCBhcmd1bWVudCAoXCJkb25lXCIgY2FsbGJhY2spLFxuICBcdFx0Ly8gd2Uga25vdyB0aGF0IHRpbGUgaXMgYXN5bmMgYW5kIHdpbGwgYmUgcmVhZHkgbGF0ZXI7IG90aGVyd2lzZVxuICBcdFx0aWYgKHRoaXMuY3JlYXRlVGlsZS5sZW5ndGggPCAyKSB7XG4gIFx0XHRcdC8vIG1hcmsgdGlsZSBhcyByZWFkeSwgYnV0IGRlbGF5IG9uZSBmcmFtZSBmb3Igb3BhY2l0eSBhbmltYXRpb24gdG8gaGFwcGVuXG4gIFx0XHRcdHJlcXVlc3RBbmltRnJhbWUoYmluZCh0aGlzLl90aWxlUmVhZHksIHRoaXMsIGNvb3JkcywgbnVsbCwgdGlsZSkpO1xuICBcdFx0fVxuXG4gIFx0XHRzZXRQb3NpdGlvbih0aWxlLCB0aWxlUG9zKTtcblxuICBcdFx0Ly8gc2F2ZSB0aWxlIGluIGNhY2hlXG4gIFx0XHR0aGlzLl90aWxlc1trZXldID0ge1xuICBcdFx0XHRlbDogdGlsZSxcbiAgXHRcdFx0Y29vcmRzOiBjb29yZHMsXG4gIFx0XHRcdGN1cnJlbnQ6IHRydWVcbiAgXHRcdH07XG5cbiAgXHRcdGNvbnRhaW5lci5hcHBlbmRDaGlsZCh0aWxlKTtcbiAgXHRcdC8vIEBldmVudCB0aWxlbG9hZHN0YXJ0OiBUaWxlRXZlbnRcbiAgXHRcdC8vIEZpcmVkIHdoZW4gYSB0aWxlIGlzIHJlcXVlc3RlZCBhbmQgc3RhcnRzIGxvYWRpbmcuXG4gIFx0XHR0aGlzLmZpcmUoJ3RpbGVsb2Fkc3RhcnQnLCB7XG4gIFx0XHRcdHRpbGU6IHRpbGUsXG4gIFx0XHRcdGNvb3JkczogY29vcmRzXG4gIFx0XHR9KTtcbiAgXHR9LFxuXG4gIFx0X3RpbGVSZWFkeTogZnVuY3Rpb24gKGNvb3JkcywgZXJyLCB0aWxlKSB7XG4gIFx0XHRpZiAoZXJyKSB7XG4gIFx0XHRcdC8vIEBldmVudCB0aWxlZXJyb3I6IFRpbGVFcnJvckV2ZW50XG4gIFx0XHRcdC8vIEZpcmVkIHdoZW4gdGhlcmUgaXMgYW4gZXJyb3IgbG9hZGluZyBhIHRpbGUuXG4gIFx0XHRcdHRoaXMuZmlyZSgndGlsZWVycm9yJywge1xuICBcdFx0XHRcdGVycm9yOiBlcnIsXG4gIFx0XHRcdFx0dGlsZTogdGlsZSxcbiAgXHRcdFx0XHRjb29yZHM6IGNvb3Jkc1xuICBcdFx0XHR9KTtcbiAgXHRcdH1cblxuICBcdFx0dmFyIGtleSA9IHRoaXMuX3RpbGVDb29yZHNUb0tleShjb29yZHMpO1xuXG4gIFx0XHR0aWxlID0gdGhpcy5fdGlsZXNba2V5XTtcbiAgXHRcdGlmICghdGlsZSkgeyByZXR1cm47IH1cblxuICBcdFx0dGlsZS5sb2FkZWQgPSArbmV3IERhdGUoKTtcbiAgXHRcdGlmICh0aGlzLl9tYXAuX2ZhZGVBbmltYXRlZCkge1xuICBcdFx0XHRzZXRPcGFjaXR5KHRpbGUuZWwsIDApO1xuICBcdFx0XHRjYW5jZWxBbmltRnJhbWUodGhpcy5fZmFkZUZyYW1lKTtcbiAgXHRcdFx0dGhpcy5fZmFkZUZyYW1lID0gcmVxdWVzdEFuaW1GcmFtZSh0aGlzLl91cGRhdGVPcGFjaXR5LCB0aGlzKTtcbiAgXHRcdH0gZWxzZSB7XG4gIFx0XHRcdHRpbGUuYWN0aXZlID0gdHJ1ZTtcbiAgXHRcdFx0dGhpcy5fcHJ1bmVUaWxlcygpO1xuICBcdFx0fVxuXG4gIFx0XHRpZiAoIWVycikge1xuICBcdFx0XHRhZGRDbGFzcyh0aWxlLmVsLCAnbGVhZmxldC10aWxlLWxvYWRlZCcpO1xuXG4gIFx0XHRcdC8vIEBldmVudCB0aWxlbG9hZDogVGlsZUV2ZW50XG4gIFx0XHRcdC8vIEZpcmVkIHdoZW4gYSB0aWxlIGxvYWRzLlxuICBcdFx0XHR0aGlzLmZpcmUoJ3RpbGVsb2FkJywge1xuICBcdFx0XHRcdHRpbGU6IHRpbGUuZWwsXG4gIFx0XHRcdFx0Y29vcmRzOiBjb29yZHNcbiAgXHRcdFx0fSk7XG4gIFx0XHR9XG5cbiAgXHRcdGlmICh0aGlzLl9ub1RpbGVzVG9Mb2FkKCkpIHtcbiAgXHRcdFx0dGhpcy5fbG9hZGluZyA9IGZhbHNlO1xuICBcdFx0XHQvLyBAZXZlbnQgbG9hZDogRXZlbnRcbiAgXHRcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgZ3JpZCBsYXllciBsb2FkZWQgYWxsIHZpc2libGUgdGlsZXMuXG4gIFx0XHRcdHRoaXMuZmlyZSgnbG9hZCcpO1xuXG4gIFx0XHRcdGlmIChCcm93c2VyLmllbHQ5IHx8ICF0aGlzLl9tYXAuX2ZhZGVBbmltYXRlZCkge1xuICBcdFx0XHRcdHJlcXVlc3RBbmltRnJhbWUodGhpcy5fcHJ1bmVUaWxlcywgdGhpcyk7XG4gIFx0XHRcdH0gZWxzZSB7XG4gIFx0XHRcdFx0Ly8gV2FpdCBhIGJpdCBtb3JlIHRoYW4gMC4yIHNlY3MgKHRoZSBkdXJhdGlvbiBvZiB0aGUgdGlsZSBmYWRlLWluKVxuICBcdFx0XHRcdC8vIHRvIHRyaWdnZXIgYSBwcnVuaW5nLlxuICBcdFx0XHRcdHNldFRpbWVvdXQoYmluZCh0aGlzLl9wcnVuZVRpbGVzLCB0aGlzKSwgMjUwKTtcbiAgXHRcdFx0fVxuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfZ2V0VGlsZVBvczogZnVuY3Rpb24gKGNvb3Jkcykge1xuICBcdFx0cmV0dXJuIGNvb3Jkcy5zY2FsZUJ5KHRoaXMuZ2V0VGlsZVNpemUoKSkuc3VidHJhY3QodGhpcy5fbGV2ZWwub3JpZ2luKTtcbiAgXHR9LFxuXG4gIFx0X3dyYXBDb29yZHM6IGZ1bmN0aW9uIChjb29yZHMpIHtcbiAgXHRcdHZhciBuZXdDb29yZHMgPSBuZXcgUG9pbnQoXG4gIFx0XHRcdHRoaXMuX3dyYXBYID8gd3JhcE51bShjb29yZHMueCwgdGhpcy5fd3JhcFgpIDogY29vcmRzLngsXG4gIFx0XHRcdHRoaXMuX3dyYXBZID8gd3JhcE51bShjb29yZHMueSwgdGhpcy5fd3JhcFkpIDogY29vcmRzLnkpO1xuICBcdFx0bmV3Q29vcmRzLnogPSBjb29yZHMuejtcbiAgXHRcdHJldHVybiBuZXdDb29yZHM7XG4gIFx0fSxcblxuICBcdF9weEJvdW5kc1RvVGlsZVJhbmdlOiBmdW5jdGlvbiAoYm91bmRzKSB7XG4gIFx0XHR2YXIgdGlsZVNpemUgPSB0aGlzLmdldFRpbGVTaXplKCk7XG4gIFx0XHRyZXR1cm4gbmV3IEJvdW5kcyhcbiAgXHRcdFx0Ym91bmRzLm1pbi51bnNjYWxlQnkodGlsZVNpemUpLmZsb29yKCksXG4gIFx0XHRcdGJvdW5kcy5tYXgudW5zY2FsZUJ5KHRpbGVTaXplKS5jZWlsKCkuc3VidHJhY3QoWzEsIDFdKSk7XG4gIFx0fSxcblxuICBcdF9ub1RpbGVzVG9Mb2FkOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRmb3IgKHZhciBrZXkgaW4gdGhpcy5fdGlsZXMpIHtcbiAgXHRcdFx0aWYgKCF0aGlzLl90aWxlc1trZXldLmxvYWRlZCkgeyByZXR1cm4gZmFsc2U7IH1cbiAgXHRcdH1cbiAgXHRcdHJldHVybiB0cnVlO1xuICBcdH1cbiAgfSk7XG5cbiAgLy8gQGZhY3RvcnkgTC5ncmlkTGF5ZXIob3B0aW9ucz86IEdyaWRMYXllciBvcHRpb25zKVxuICAvLyBDcmVhdGVzIGEgbmV3IGluc3RhbmNlIG9mIEdyaWRMYXllciB3aXRoIHRoZSBzdXBwbGllZCBvcHRpb25zLlxuICBmdW5jdGlvbiBncmlkTGF5ZXIob3B0aW9ucykge1xuICBcdHJldHVybiBuZXcgR3JpZExheWVyKG9wdGlvbnMpO1xuICB9XG5cbiAgLypcclxuICAgKiBAY2xhc3MgVGlsZUxheWVyXHJcbiAgICogQGluaGVyaXRzIEdyaWRMYXllclxyXG4gICAqIEBha2EgTC5UaWxlTGF5ZXJcclxuICAgKiBVc2VkIHRvIGxvYWQgYW5kIGRpc3BsYXkgdGlsZSBsYXllcnMgb24gdGhlIG1hcC4gTm90ZSB0aGF0IG1vc3QgdGlsZSBzZXJ2ZXJzIHJlcXVpcmUgYXR0cmlidXRpb24sIHdoaWNoIHlvdSBjYW4gc2V0IHVuZGVyIGBMYXllcmAuIEV4dGVuZHMgYEdyaWRMYXllcmAuXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiBMLnRpbGVMYXllcignaHR0cHM6Ly90aWxlLm9wZW5zdHJlZXRtYXAub3JnL3t6fS97eH0ve3l9LnBuZz97Zm9vfScsIHtmb286ICdiYXInLCBhdHRyaWJ1dGlvbjogJyZjb3B5OyA8YSBocmVmPVwiaHR0cHM6Ly93d3cub3BlbnN0cmVldG1hcC5vcmcvY29weXJpZ2h0XCI+T3BlblN0cmVldE1hcDwvYT4gY29udHJpYnV0b3JzJ30pLmFkZFRvKG1hcCk7XG4gICAqIGBgYFxyXG4gICAqXHJcbiAgICogQHNlY3Rpb24gVVJMIHRlbXBsYXRlXHJcbiAgICogQGV4YW1wbGVcclxuICAgKlxyXG4gICAqIEEgc3RyaW5nIG9mIHRoZSBmb2xsb3dpbmcgZm9ybTpcclxuICAgKlxyXG4gICAqIGBgYFxyXG4gICAqICdodHRwczovL3tzfS5zb21lZG9tYWluLmNvbS9ibGFibGEve3p9L3t4fS97eX17cn0ucG5nJ1xyXG4gICAqIGBgYFxyXG4gICAqXHJcbiAgICogYHtzfWAgbWVhbnMgb25lIG9mIHRoZSBhdmFpbGFibGUgc3ViZG9tYWlucyAodXNlZCBzZXF1ZW50aWFsbHkgdG8gaGVscCB3aXRoIGJyb3dzZXIgcGFyYWxsZWwgcmVxdWVzdHMgcGVyIGRvbWFpbiBsaW1pdGF0aW9uOyBzdWJkb21haW4gdmFsdWVzIGFyZSBzcGVjaWZpZWQgaW4gb3B0aW9uczsgYGFgLCBgYmAgb3IgYGNgIGJ5IGRlZmF1bHQsIGNhbiBiZSBvbWl0dGVkKSwgYHt6fWAg4oCUIHpvb20gbGV2ZWwsIGB7eH1gIGFuZCBge3l9YCDigJQgdGlsZSBjb29yZGluYXRlcy4gYHtyfWAgY2FuIGJlIHVzZWQgdG8gYWRkIFwiJmNvbW1hdDsyeFwiIHRvIHRoZSBVUkwgdG8gbG9hZCByZXRpbmEgdGlsZXMuXHJcbiAgICpcclxuICAgKiBZb3UgY2FuIHVzZSBjdXN0b20ga2V5cyBpbiB0aGUgdGVtcGxhdGUsIHdoaWNoIHdpbGwgYmUgW2V2YWx1YXRlZF0oI3V0aWwtdGVtcGxhdGUpIGZyb20gVGlsZUxheWVyIG9wdGlvbnMsIGxpa2UgdGhpczpcclxuICAgKlxyXG4gICAqIGBgYFxyXG4gICAqIEwudGlsZUxheWVyKCdodHRwczovL3tzfS5zb21lZG9tYWluLmNvbS97Zm9vfS97en0ve3h9L3t5fS5wbmcnLCB7Zm9vOiAnYmFyJ30pO1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG5cclxuXHJcbiAgdmFyIFRpbGVMYXllciA9IEdyaWRMYXllci5leHRlbmQoe1xyXG5cclxuICBcdC8vIEBzZWN0aW9uXHJcbiAgXHQvLyBAYWthIFRpbGVMYXllciBvcHRpb25zXHJcbiAgXHRvcHRpb25zOiB7XHJcbiAgXHRcdC8vIEBvcHRpb24gbWluWm9vbTogTnVtYmVyID0gMFxyXG4gIFx0XHQvLyBUaGUgbWluaW11bSB6b29tIGxldmVsIGRvd24gdG8gd2hpY2ggdGhpcyBsYXllciB3aWxsIGJlIGRpc3BsYXllZCAoaW5jbHVzaXZlKS5cclxuICBcdFx0bWluWm9vbTogMCxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gbWF4Wm9vbTogTnVtYmVyID0gMThcclxuICBcdFx0Ly8gVGhlIG1heGltdW0gem9vbSBsZXZlbCB1cCB0byB3aGljaCB0aGlzIGxheWVyIHdpbGwgYmUgZGlzcGxheWVkIChpbmNsdXNpdmUpLlxyXG4gIFx0XHRtYXhab29tOiAxOCxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gc3ViZG9tYWluczogU3RyaW5nfFN0cmluZ1tdID0gJ2FiYydcclxuICBcdFx0Ly8gU3ViZG9tYWlucyBvZiB0aGUgdGlsZSBzZXJ2aWNlLiBDYW4gYmUgcGFzc2VkIGluIHRoZSBmb3JtIG9mIG9uZSBzdHJpbmcgKHdoZXJlIGVhY2ggbGV0dGVyIGlzIGEgc3ViZG9tYWluIG5hbWUpIG9yIGFuIGFycmF5IG9mIHN0cmluZ3MuXHJcbiAgXHRcdHN1YmRvbWFpbnM6ICdhYmMnLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBlcnJvclRpbGVVcmw6IFN0cmluZyA9ICcnXHJcbiAgXHRcdC8vIFVSTCB0byB0aGUgdGlsZSBpbWFnZSB0byBzaG93IGluIHBsYWNlIG9mIHRoZSB0aWxlIHRoYXQgZmFpbGVkIHRvIGxvYWQuXHJcbiAgXHRcdGVycm9yVGlsZVVybDogJycsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHpvb21PZmZzZXQ6IE51bWJlciA9IDBcclxuICBcdFx0Ly8gVGhlIHpvb20gbnVtYmVyIHVzZWQgaW4gdGlsZSBVUkxzIHdpbGwgYmUgb2Zmc2V0IHdpdGggdGhpcyB2YWx1ZS5cclxuICBcdFx0em9vbU9mZnNldDogMCxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gdG1zOiBCb29sZWFuID0gZmFsc2VcclxuICBcdFx0Ly8gSWYgYHRydWVgLCBpbnZlcnNlcyBZIGF4aXMgbnVtYmVyaW5nIGZvciB0aWxlcyAodHVybiB0aGlzIG9uIGZvciBbVE1TXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9UaWxlX01hcF9TZXJ2aWNlKSBzZXJ2aWNlcykuXHJcbiAgXHRcdHRtczogZmFsc2UsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHpvb21SZXZlcnNlOiBCb29sZWFuID0gZmFsc2VcclxuICBcdFx0Ly8gSWYgc2V0IHRvIHRydWUsIHRoZSB6b29tIG51bWJlciB1c2VkIGluIHRpbGUgVVJMcyB3aWxsIGJlIHJldmVyc2VkIChgbWF4Wm9vbSAtIHpvb21gIGluc3RlYWQgb2YgYHpvb21gKVxyXG4gIFx0XHR6b29tUmV2ZXJzZTogZmFsc2UsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIGRldGVjdFJldGluYTogQm9vbGVhbiA9IGZhbHNlXHJcbiAgXHRcdC8vIElmIGB0cnVlYCBhbmQgdXNlciBpcyBvbiBhIHJldGluYSBkaXNwbGF5LCBpdCB3aWxsIHJlcXVlc3QgZm91ciB0aWxlcyBvZiBoYWxmIHRoZSBzcGVjaWZpZWQgc2l6ZSBhbmQgYSBiaWdnZXIgem9vbSBsZXZlbCBpbiBwbGFjZSBvZiBvbmUgdG8gdXRpbGl6ZSB0aGUgaGlnaCByZXNvbHV0aW9uLlxyXG4gIFx0XHRkZXRlY3RSZXRpbmE6IGZhbHNlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBjcm9zc09yaWdpbjogQm9vbGVhbnxTdHJpbmcgPSBmYWxzZVxyXG4gIFx0XHQvLyBXaGV0aGVyIHRoZSBjcm9zc09yaWdpbiBhdHRyaWJ1dGUgd2lsbCBiZSBhZGRlZCB0byB0aGUgdGlsZXMuXHJcbiAgXHRcdC8vIElmIGEgU3RyaW5nIGlzIHByb3ZpZGVkLCBhbGwgdGlsZXMgd2lsbCBoYXZlIHRoZWlyIGNyb3NzT3JpZ2luIGF0dHJpYnV0ZSBzZXQgdG8gdGhlIFN0cmluZyBwcm92aWRlZC4gVGhpcyBpcyBuZWVkZWQgaWYgeW91IHdhbnQgdG8gYWNjZXNzIHRpbGUgcGl4ZWwgZGF0YS5cclxuICBcdFx0Ly8gUmVmZXIgdG8gW0NPUlMgU2V0dGluZ3NdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0hUTUwvQ09SU19zZXR0aW5nc19hdHRyaWJ1dGVzKSBmb3IgdmFsaWQgU3RyaW5nIHZhbHVlcy5cclxuICBcdFx0Y3Jvc3NPcmlnaW46IGZhbHNlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiByZWZlcnJlclBvbGljeTogQm9vbGVhbnxTdHJpbmcgPSBmYWxzZVxyXG4gIFx0XHQvLyBXaGV0aGVyIHRoZSByZWZlcnJlclBvbGljeSBhdHRyaWJ1dGUgd2lsbCBiZSBhZGRlZCB0byB0aGUgdGlsZXMuXHJcbiAgXHRcdC8vIElmIGEgU3RyaW5nIGlzIHByb3ZpZGVkLCBhbGwgdGlsZXMgd2lsbCBoYXZlIHRoZWlyIHJlZmVycmVyUG9saWN5IGF0dHJpYnV0ZSBzZXQgdG8gdGhlIFN0cmluZyBwcm92aWRlZC5cclxuICBcdFx0Ly8gVGhpcyBtYXkgYmUgbmVlZGVkIGlmIHlvdXIgbWFwJ3MgcmVuZGVyaW5nIGNvbnRleHQgaGFzIGEgc3RyaWN0IGRlZmF1bHQgYnV0IHlvdXIgdGlsZSBwcm92aWRlciBleHBlY3RzIGEgdmFsaWQgcmVmZXJyZXJcclxuICBcdFx0Ly8gKGUuZy4gdG8gdmFsaWRhdGUgYW4gQVBJIHRva2VuKS5cclxuICBcdFx0Ly8gUmVmZXIgdG8gW0hUTUxJbWFnZUVsZW1lbnQucmVmZXJyZXJQb2xpY3ldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9IVE1MSW1hZ2VFbGVtZW50L3JlZmVycmVyUG9saWN5KSBmb3IgdmFsaWQgU3RyaW5nIHZhbHVlcy5cclxuICBcdFx0cmVmZXJyZXJQb2xpY3k6IGZhbHNlXHJcbiAgXHR9LFxyXG5cclxuICBcdGluaXRpYWxpemU6IGZ1bmN0aW9uICh1cmwsIG9wdGlvbnMpIHtcclxuXHJcbiAgXHRcdHRoaXMuX3VybCA9IHVybDtcclxuXHJcbiAgXHRcdG9wdGlvbnMgPSBzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xyXG5cclxuICBcdFx0Ly8gZGV0ZWN0aW5nIHJldGluYSBkaXNwbGF5cywgYWRqdXN0aW5nIHRpbGVTaXplIGFuZCB6b29tIGxldmVsc1xyXG4gIFx0XHRpZiAob3B0aW9ucy5kZXRlY3RSZXRpbmEgJiYgQnJvd3Nlci5yZXRpbmEgJiYgb3B0aW9ucy5tYXhab29tID4gMCkge1xyXG5cclxuICBcdFx0XHRvcHRpb25zLnRpbGVTaXplID0gTWF0aC5mbG9vcihvcHRpb25zLnRpbGVTaXplIC8gMik7XHJcblxyXG4gIFx0XHRcdGlmICghb3B0aW9ucy56b29tUmV2ZXJzZSkge1xyXG4gIFx0XHRcdFx0b3B0aW9ucy56b29tT2Zmc2V0Kys7XHJcbiAgXHRcdFx0XHRvcHRpb25zLm1heFpvb20gPSBNYXRoLm1heChvcHRpb25zLm1pblpvb20sIG9wdGlvbnMubWF4Wm9vbSAtIDEpO1xyXG4gIFx0XHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0XHRvcHRpb25zLnpvb21PZmZzZXQtLTtcclxuICBcdFx0XHRcdG9wdGlvbnMubWluWm9vbSA9IE1hdGgubWluKG9wdGlvbnMubWF4Wm9vbSwgb3B0aW9ucy5taW5ab29tICsgMSk7XHJcbiAgXHRcdFx0fVxyXG5cclxuICBcdFx0XHRvcHRpb25zLm1pblpvb20gPSBNYXRoLm1heCgwLCBvcHRpb25zLm1pblpvb20pO1xyXG4gIFx0XHR9IGVsc2UgaWYgKCFvcHRpb25zLnpvb21SZXZlcnNlKSB7XHJcbiAgXHRcdFx0Ly8gbWFrZSBzdXJlIG1heFpvb20gaXMgZ3RlIG1pblpvb21cclxuICBcdFx0XHRvcHRpb25zLm1heFpvb20gPSBNYXRoLm1heChvcHRpb25zLm1pblpvb20sIG9wdGlvbnMubWF4Wm9vbSk7XHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0Ly8gbWFrZSBzdXJlIG1pblpvb20gaXMgbHRlIG1heFpvb21cclxuICBcdFx0XHRvcHRpb25zLm1pblpvb20gPSBNYXRoLm1pbihvcHRpb25zLm1heFpvb20sIG9wdGlvbnMubWluWm9vbSk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmICh0eXBlb2Ygb3B0aW9ucy5zdWJkb21haW5zID09PSAnc3RyaW5nJykge1xyXG4gIFx0XHRcdG9wdGlvbnMuc3ViZG9tYWlucyA9IG9wdGlvbnMuc3ViZG9tYWlucy5zcGxpdCgnJyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMub24oJ3RpbGV1bmxvYWQnLCB0aGlzLl9vblRpbGVSZW1vdmUpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNldFVybCh1cmw6IFN0cmluZywgbm9SZWRyYXc/OiBCb29sZWFuKTogdGhpc1xyXG4gIFx0Ly8gVXBkYXRlcyB0aGUgbGF5ZXIncyBVUkwgdGVtcGxhdGUgYW5kIHJlZHJhd3MgaXQgKHVubGVzcyBgbm9SZWRyYXdgIGlzIHNldCB0byBgdHJ1ZWApLlxyXG4gIFx0Ly8gSWYgdGhlIFVSTCBkb2VzIG5vdCBjaGFuZ2UsIHRoZSBsYXllciB3aWxsIG5vdCBiZSByZWRyYXduIHVubGVzc1xyXG4gIFx0Ly8gdGhlIG5vUmVkcmF3IHBhcmFtZXRlciBpcyBzZXQgdG8gZmFsc2UuXHJcbiAgXHRzZXRVcmw6IGZ1bmN0aW9uICh1cmwsIG5vUmVkcmF3KSB7XHJcbiAgXHRcdGlmICh0aGlzLl91cmwgPT09IHVybCAmJiBub1JlZHJhdyA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgXHRcdFx0bm9SZWRyYXcgPSB0cnVlO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR0aGlzLl91cmwgPSB1cmw7XHJcblxyXG4gIFx0XHRpZiAoIW5vUmVkcmF3KSB7XHJcbiAgXHRcdFx0dGhpcy5yZWRyYXcoKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBjcmVhdGVUaWxlKGNvb3JkczogT2JqZWN0LCBkb25lPzogRnVuY3Rpb24pOiBIVE1MRWxlbWVudFxyXG4gIFx0Ly8gQ2FsbGVkIG9ubHkgaW50ZXJuYWxseSwgb3ZlcnJpZGVzIEdyaWRMYXllcidzIFtgY3JlYXRlVGlsZSgpYF0oI2dyaWRsYXllci1jcmVhdGV0aWxlKVxyXG4gIFx0Ly8gdG8gcmV0dXJuIGFuIGA8aW1nPmAgSFRNTCBlbGVtZW50IHdpdGggdGhlIGFwcHJvcHJpYXRlIGltYWdlIFVSTCBnaXZlbiBgY29vcmRzYC4gVGhlIGBkb25lYFxyXG4gIFx0Ly8gY2FsbGJhY2sgaXMgY2FsbGVkIHdoZW4gdGhlIHRpbGUgaGFzIGJlZW4gbG9hZGVkLlxyXG4gIFx0Y3JlYXRlVGlsZTogZnVuY3Rpb24gKGNvb3JkcywgZG9uZSkge1xyXG4gIFx0XHR2YXIgdGlsZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ltZycpO1xyXG5cclxuICBcdFx0b24odGlsZSwgJ2xvYWQnLCBiaW5kKHRoaXMuX3RpbGVPbkxvYWQsIHRoaXMsIGRvbmUsIHRpbGUpKTtcclxuICBcdFx0b24odGlsZSwgJ2Vycm9yJywgYmluZCh0aGlzLl90aWxlT25FcnJvciwgdGhpcywgZG9uZSwgdGlsZSkpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5jcm9zc09yaWdpbiB8fCB0aGlzLm9wdGlvbnMuY3Jvc3NPcmlnaW4gPT09ICcnKSB7XHJcbiAgXHRcdFx0dGlsZS5jcm9zc09yaWdpbiA9IHRoaXMub3B0aW9ucy5jcm9zc09yaWdpbiA9PT0gdHJ1ZSA/ICcnIDogdGhpcy5vcHRpb25zLmNyb3NzT3JpZ2luO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHQvLyBmb3IgdGhpcyBuZXcgb3B0aW9uIHdlIGZvbGxvdyB0aGUgZG9jdW1lbnRlZCBiZWhhdmlvclxyXG4gIFx0XHQvLyBtb3JlIGNsb3NlbHkgYnkgb25seSBzZXR0aW5nIHRoZSBwcm9wZXJ0eSB3aGVuIHN0cmluZ1xyXG4gIFx0XHRpZiAodHlwZW9mIHRoaXMub3B0aW9ucy5yZWZlcnJlclBvbGljeSA9PT0gJ3N0cmluZycpIHtcclxuICBcdFx0XHR0aWxlLnJlZmVycmVyUG9saWN5ID0gdGhpcy5vcHRpb25zLnJlZmVycmVyUG9saWN5O1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHQvLyBUaGUgYWx0IGF0dHJpYnV0ZSBpcyBzZXQgdG8gdGhlIGVtcHR5IHN0cmluZyxcclxuICBcdFx0Ly8gYWxsb3dpbmcgc2NyZWVuIHJlYWRlcnMgdG8gaWdub3JlIHRoZSBkZWNvcmF0aXZlIGltYWdlIHRpbGVzLlxyXG4gIFx0XHQvLyBodHRwczovL3d3dy53My5vcmcvV0FJL3R1dG9yaWFscy9pbWFnZXMvZGVjb3JhdGl2ZS9cclxuICBcdFx0Ly8gaHR0cHM6Ly93d3cudzMub3JnL1RSL2h0bWwtYXJpYS8jZWwtaW1nLWVtcHR5LWFsdFxyXG4gIFx0XHR0aWxlLmFsdCA9ICcnO1xyXG5cclxuICBcdFx0dGlsZS5zcmMgPSB0aGlzLmdldFRpbGVVcmwoY29vcmRzKTtcclxuXHJcbiAgXHRcdHJldHVybiB0aWxlO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAc2VjdGlvbiBFeHRlbnNpb24gbWV0aG9kc1xyXG4gIFx0Ly8gQHVuaW5oZXJpdGFibGVcclxuICBcdC8vIExheWVycyBleHRlbmRpbmcgYFRpbGVMYXllcmAgbWlnaHQgcmVpbXBsZW1lbnQgdGhlIGZvbGxvd2luZyBtZXRob2QuXHJcbiAgXHQvLyBAbWV0aG9kIGdldFRpbGVVcmwoY29vcmRzOiBPYmplY3QpOiBTdHJpbmdcclxuICBcdC8vIENhbGxlZCBvbmx5IGludGVybmFsbHksIHJldHVybnMgdGhlIFVSTCBmb3IgYSB0aWxlIGdpdmVuIGl0cyBjb29yZGluYXRlcy5cclxuICBcdC8vIENsYXNzZXMgZXh0ZW5kaW5nIGBUaWxlTGF5ZXJgIGNhbiBvdmVycmlkZSB0aGlzIGZ1bmN0aW9uIHRvIHByb3ZpZGUgY3VzdG9tIHRpbGUgVVJMIG5hbWluZyBzY2hlbWVzLlxyXG4gIFx0Z2V0VGlsZVVybDogZnVuY3Rpb24gKGNvb3Jkcykge1xyXG4gIFx0XHR2YXIgZGF0YSA9IHtcclxuICBcdFx0XHRyOiBCcm93c2VyLnJldGluYSA/ICdAMngnIDogJycsXHJcbiAgXHRcdFx0czogdGhpcy5fZ2V0U3ViZG9tYWluKGNvb3JkcyksXHJcbiAgXHRcdFx0eDogY29vcmRzLngsXHJcbiAgXHRcdFx0eTogY29vcmRzLnksXHJcbiAgXHRcdFx0ejogdGhpcy5fZ2V0Wm9vbUZvclVybCgpXHJcbiAgXHRcdH07XHJcbiAgXHRcdGlmICh0aGlzLl9tYXAgJiYgIXRoaXMuX21hcC5vcHRpb25zLmNycy5pbmZpbml0ZSkge1xyXG4gIFx0XHRcdHZhciBpbnZlcnRlZFkgPSB0aGlzLl9nbG9iYWxUaWxlUmFuZ2UubWF4LnkgLSBjb29yZHMueTtcclxuICBcdFx0XHRpZiAodGhpcy5vcHRpb25zLnRtcykge1xyXG4gIFx0XHRcdFx0ZGF0YVsneSddID0gaW52ZXJ0ZWRZO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0XHRkYXRhWycteSddID0gaW52ZXJ0ZWRZO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gdGVtcGxhdGUodGhpcy5fdXJsLCBleHRlbmQoZGF0YSwgdGhpcy5vcHRpb25zKSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF90aWxlT25Mb2FkOiBmdW5jdGlvbiAoZG9uZSwgdGlsZSkge1xyXG4gIFx0XHQvLyBGb3IgaHR0cHM6Ly9naXRodWIuY29tL0xlYWZsZXQvTGVhZmxldC9pc3N1ZXMvMzMzMlxyXG4gIFx0XHRpZiAoQnJvd3Nlci5pZWx0OSkge1xyXG4gIFx0XHRcdHNldFRpbWVvdXQoYmluZChkb25lLCB0aGlzLCBudWxsLCB0aWxlKSwgMCk7XHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0ZG9uZShudWxsLCB0aWxlKTtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHRfdGlsZU9uRXJyb3I6IGZ1bmN0aW9uIChkb25lLCB0aWxlLCBlKSB7XHJcbiAgXHRcdHZhciBlcnJvclVybCA9IHRoaXMub3B0aW9ucy5lcnJvclRpbGVVcmw7XHJcbiAgXHRcdGlmIChlcnJvclVybCAmJiB0aWxlLmdldEF0dHJpYnV0ZSgnc3JjJykgIT09IGVycm9yVXJsKSB7XHJcbiAgXHRcdFx0dGlsZS5zcmMgPSBlcnJvclVybDtcclxuICBcdFx0fVxyXG4gIFx0XHRkb25lKGUsIHRpbGUpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfb25UaWxlUmVtb3ZlOiBmdW5jdGlvbiAoZSkge1xyXG4gIFx0XHRlLnRpbGUub25sb2FkID0gbnVsbDtcclxuICBcdH0sXHJcblxyXG4gIFx0X2dldFpvb21Gb3JVcmw6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dmFyIHpvb20gPSB0aGlzLl90aWxlWm9vbSxcclxuICBcdFx0bWF4Wm9vbSA9IHRoaXMub3B0aW9ucy5tYXhab29tLFxyXG4gIFx0XHR6b29tUmV2ZXJzZSA9IHRoaXMub3B0aW9ucy56b29tUmV2ZXJzZSxcclxuICBcdFx0em9vbU9mZnNldCA9IHRoaXMub3B0aW9ucy56b29tT2Zmc2V0O1xyXG5cclxuICBcdFx0aWYgKHpvb21SZXZlcnNlKSB7XHJcbiAgXHRcdFx0em9vbSA9IG1heFpvb20gLSB6b29tO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gem9vbSArIHpvb21PZmZzZXQ7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9nZXRTdWJkb21haW46IGZ1bmN0aW9uICh0aWxlUG9pbnQpIHtcclxuICBcdFx0dmFyIGluZGV4ID0gTWF0aC5hYnModGlsZVBvaW50LnggKyB0aWxlUG9pbnQueSkgJSB0aGlzLm9wdGlvbnMuc3ViZG9tYWlucy5sZW5ndGg7XHJcbiAgXHRcdHJldHVybiB0aGlzLm9wdGlvbnMuc3ViZG9tYWluc1tpbmRleF07XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIHN0b3BzIGxvYWRpbmcgYWxsIHRpbGVzIGluIHRoZSBiYWNrZ3JvdW5kIGxheWVyXHJcbiAgXHRfYWJvcnRMb2FkaW5nOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHZhciBpLCB0aWxlO1xyXG4gIFx0XHRmb3IgKGkgaW4gdGhpcy5fdGlsZXMpIHtcclxuICBcdFx0XHRpZiAodGhpcy5fdGlsZXNbaV0uY29vcmRzLnogIT09IHRoaXMuX3RpbGVab29tKSB7XHJcbiAgXHRcdFx0XHR0aWxlID0gdGhpcy5fdGlsZXNbaV0uZWw7XHJcblxyXG4gIFx0XHRcdFx0dGlsZS5vbmxvYWQgPSBmYWxzZUZuO1xyXG4gIFx0XHRcdFx0dGlsZS5vbmVycm9yID0gZmFsc2VGbjtcclxuXHJcbiAgXHRcdFx0XHRpZiAoIXRpbGUuY29tcGxldGUpIHtcclxuICBcdFx0XHRcdFx0dGlsZS5zcmMgPSBlbXB0eUltYWdlVXJsO1xyXG4gIFx0XHRcdFx0XHR2YXIgY29vcmRzID0gdGhpcy5fdGlsZXNbaV0uY29vcmRzO1xyXG4gIFx0XHRcdFx0XHRyZW1vdmUodGlsZSk7XHJcbiAgXHRcdFx0XHRcdGRlbGV0ZSB0aGlzLl90aWxlc1tpXTtcclxuICBcdFx0XHRcdFx0Ly8gQGV2ZW50IHRpbGVhYm9ydDogVGlsZUV2ZW50XHJcbiAgXHRcdFx0XHRcdC8vIEZpcmVkIHdoZW4gYSB0aWxlIHdhcyBsb2FkaW5nIGJ1dCBpcyBub3cgbm90IHdhbnRlZC5cclxuICBcdFx0XHRcdFx0dGhpcy5maXJlKCd0aWxlYWJvcnQnLCB7XHJcbiAgXHRcdFx0XHRcdFx0dGlsZTogdGlsZSxcclxuICBcdFx0XHRcdFx0XHRjb29yZHM6IGNvb3Jkc1xyXG4gIFx0XHRcdFx0XHR9KTtcclxuICBcdFx0XHRcdH1cclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0X3JlbW92ZVRpbGU6IGZ1bmN0aW9uIChrZXkpIHtcclxuICBcdFx0dmFyIHRpbGUgPSB0aGlzLl90aWxlc1trZXldO1xyXG4gIFx0XHRpZiAoIXRpbGUpIHsgcmV0dXJuOyB9XHJcblxyXG4gIFx0XHQvLyBDYW5jZWxzIGFueSBwZW5kaW5nIGh0dHAgcmVxdWVzdHMgYXNzb2NpYXRlZCB3aXRoIHRoZSB0aWxlXHJcbiAgXHRcdHRpbGUuZWwuc2V0QXR0cmlidXRlKCdzcmMnLCBlbXB0eUltYWdlVXJsKTtcclxuXHJcbiAgXHRcdHJldHVybiBHcmlkTGF5ZXIucHJvdG90eXBlLl9yZW1vdmVUaWxlLmNhbGwodGhpcywga2V5KTtcclxuICBcdH0sXHJcblxyXG4gIFx0X3RpbGVSZWFkeTogZnVuY3Rpb24gKGNvb3JkcywgZXJyLCB0aWxlKSB7XHJcbiAgXHRcdGlmICghdGhpcy5fbWFwIHx8ICh0aWxlICYmIHRpbGUuZ2V0QXR0cmlidXRlKCdzcmMnKSA9PT0gZW1wdHlJbWFnZVVybCkpIHtcclxuICBcdFx0XHRyZXR1cm47XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiBHcmlkTGF5ZXIucHJvdG90eXBlLl90aWxlUmVhZHkuY2FsbCh0aGlzLCBjb29yZHMsIGVyciwgdGlsZSk7XHJcbiAgXHR9XHJcbiAgfSk7XHJcblxyXG5cclxuICAvLyBAZmFjdG9yeSBMLnRpbGVsYXllcih1cmxUZW1wbGF0ZTogU3RyaW5nLCBvcHRpb25zPzogVGlsZUxheWVyIG9wdGlvbnMpXHJcbiAgLy8gSW5zdGFudGlhdGVzIGEgdGlsZSBsYXllciBvYmplY3QgZ2l2ZW4gYSBgVVJMIHRlbXBsYXRlYCBhbmQgb3B0aW9uYWxseSBhbiBvcHRpb25zIG9iamVjdC5cclxuXHJcbiAgZnVuY3Rpb24gdGlsZUxheWVyKHVybCwgb3B0aW9ucykge1xyXG4gIFx0cmV0dXJuIG5ldyBUaWxlTGF5ZXIodXJsLCBvcHRpb25zKTtcclxuICB9XG5cbiAgLypcclxuICAgKiBAY2xhc3MgVGlsZUxheWVyLldNU1xyXG4gICAqIEBpbmhlcml0cyBUaWxlTGF5ZXJcclxuICAgKiBAYWthIEwuVGlsZUxheWVyLldNU1xyXG4gICAqIFVzZWQgdG8gZGlzcGxheSBbV01TXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9XZWJfTWFwX1NlcnZpY2UpIHNlcnZpY2VzIGFzIHRpbGUgbGF5ZXJzIG9uIHRoZSBtYXAuIEV4dGVuZHMgYFRpbGVMYXllcmAuXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiB2YXIgbmV4cmFkID0gTC50aWxlTGF5ZXIud21zKFwiaHR0cDovL21lc29uZXQuYWdyb24uaWFzdGF0ZS5lZHUvY2dpLWJpbi93bXMvbmV4cmFkL24wci5jZ2lcIiwge1xyXG4gICAqIFx0bGF5ZXJzOiAnbmV4cmFkLW4wci05MDA5MTMnLFxyXG4gICAqIFx0Zm9ybWF0OiAnaW1hZ2UvcG5nJyxcclxuICAgKiBcdHRyYW5zcGFyZW50OiB0cnVlLFxyXG4gICAqIFx0YXR0cmlidXRpb246IFwiV2VhdGhlciBkYXRhIMKpIDIwMTIgSUVNIE5leHJhZFwiXHJcbiAgICogfSk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcblxyXG4gIHZhciBUaWxlTGF5ZXJXTVMgPSBUaWxlTGF5ZXIuZXh0ZW5kKHtcclxuXHJcbiAgXHQvLyBAc2VjdGlvblxyXG4gIFx0Ly8gQGFrYSBUaWxlTGF5ZXIuV01TIG9wdGlvbnNcclxuICBcdC8vIElmIGFueSBjdXN0b20gb3B0aW9ucyBub3QgZG9jdW1lbnRlZCBoZXJlIGFyZSB1c2VkLCB0aGV5IHdpbGwgYmUgc2VudCB0byB0aGVcclxuICBcdC8vIFdNUyBzZXJ2ZXIgYXMgZXh0cmEgcGFyYW1ldGVycyBpbiBlYWNoIHJlcXVlc3QgVVJMLiBUaGlzIGNhbiBiZSB1c2VmdWwgZm9yXHJcbiAgXHQvLyBbbm9uLXN0YW5kYXJkIHZlbmRvciBXTVMgcGFyYW1ldGVyc10oaHR0cHM6Ly9kb2NzLmdlb3NlcnZlci5vcmcvc3RhYmxlL2VuL3VzZXIvc2VydmljZXMvd21zL3ZlbmRvci5odG1sKS5cclxuICBcdGRlZmF1bHRXbXNQYXJhbXM6IHtcclxuICBcdFx0c2VydmljZTogJ1dNUycsXHJcbiAgXHRcdHJlcXVlc3Q6ICdHZXRNYXAnLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBsYXllcnM6IFN0cmluZyA9ICcnXHJcbiAgXHRcdC8vICoqKHJlcXVpcmVkKSoqIENvbW1hLXNlcGFyYXRlZCBsaXN0IG9mIFdNUyBsYXllcnMgdG8gc2hvdy5cclxuICBcdFx0bGF5ZXJzOiAnJyxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gc3R5bGVzOiBTdHJpbmcgPSAnJ1xyXG4gIFx0XHQvLyBDb21tYS1zZXBhcmF0ZWQgbGlzdCBvZiBXTVMgc3R5bGVzLlxyXG4gIFx0XHRzdHlsZXM6ICcnLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBmb3JtYXQ6IFN0cmluZyA9ICdpbWFnZS9qcGVnJ1xyXG4gIFx0XHQvLyBXTVMgaW1hZ2UgZm9ybWF0ICh1c2UgYCdpbWFnZS9wbmcnYCBmb3IgbGF5ZXJzIHdpdGggdHJhbnNwYXJlbmN5KS5cclxuICBcdFx0Zm9ybWF0OiAnaW1hZ2UvanBlZycsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHRyYW5zcGFyZW50OiBCb29sZWFuID0gZmFsc2VcclxuICBcdFx0Ly8gSWYgYHRydWVgLCB0aGUgV01TIHNlcnZpY2Ugd2lsbCByZXR1cm4gaW1hZ2VzIHdpdGggdHJhbnNwYXJlbmN5LlxyXG4gIFx0XHR0cmFuc3BhcmVudDogZmFsc2UsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHZlcnNpb246IFN0cmluZyA9ICcxLjEuMSdcclxuICBcdFx0Ly8gVmVyc2lvbiBvZiB0aGUgV01TIHNlcnZpY2UgdG8gdXNlXHJcbiAgXHRcdHZlcnNpb246ICcxLjEuMSdcclxuICBcdH0sXHJcblxyXG4gIFx0b3B0aW9uczoge1xyXG4gIFx0XHQvLyBAb3B0aW9uIGNyczogQ1JTID0gbnVsbFxyXG4gIFx0XHQvLyBDb29yZGluYXRlIFJlZmVyZW5jZSBTeXN0ZW0gdG8gdXNlIGZvciB0aGUgV01TIHJlcXVlc3RzLCBkZWZhdWx0cyB0b1xyXG4gIFx0XHQvLyBtYXAgQ1JTLiBEb24ndCBjaGFuZ2UgdGhpcyBpZiB5b3UncmUgbm90IHN1cmUgd2hhdCBpdCBtZWFucy5cclxuICBcdFx0Y3JzOiBudWxsLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiB1cHBlcmNhc2U6IEJvb2xlYW4gPSBmYWxzZVxyXG4gIFx0XHQvLyBJZiBgdHJ1ZWAsIFdNUyByZXF1ZXN0IHBhcmFtZXRlciBrZXlzIHdpbGwgYmUgdXBwZXJjYXNlLlxyXG4gIFx0XHR1cHBlcmNhc2U6IGZhbHNlXHJcbiAgXHR9LFxyXG5cclxuICBcdGluaXRpYWxpemU6IGZ1bmN0aW9uICh1cmwsIG9wdGlvbnMpIHtcclxuXHJcbiAgXHRcdHRoaXMuX3VybCA9IHVybDtcclxuXHJcbiAgXHRcdHZhciB3bXNQYXJhbXMgPSBleHRlbmQoe30sIHRoaXMuZGVmYXVsdFdtc1BhcmFtcyk7XHJcblxyXG4gIFx0XHQvLyBhbGwga2V5cyB0aGF0IGFyZSBub3QgVGlsZUxheWVyIG9wdGlvbnMgZ28gdG8gV01TIHBhcmFtc1xyXG4gIFx0XHRmb3IgKHZhciBpIGluIG9wdGlvbnMpIHtcclxuICBcdFx0XHRpZiAoIShpIGluIHRoaXMub3B0aW9ucykpIHtcclxuICBcdFx0XHRcdHdtc1BhcmFtc1tpXSA9IG9wdGlvbnNbaV07XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRvcHRpb25zID0gc2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcclxuXHJcbiAgXHRcdHZhciByZWFsUmV0aW5hID0gb3B0aW9ucy5kZXRlY3RSZXRpbmEgJiYgQnJvd3Nlci5yZXRpbmEgPyAyIDogMTtcclxuICBcdFx0dmFyIHRpbGVTaXplID0gdGhpcy5nZXRUaWxlU2l6ZSgpO1xyXG4gIFx0XHR3bXNQYXJhbXMud2lkdGggPSB0aWxlU2l6ZS54ICogcmVhbFJldGluYTtcclxuICBcdFx0d21zUGFyYW1zLmhlaWdodCA9IHRpbGVTaXplLnkgKiByZWFsUmV0aW5hO1xyXG5cclxuICBcdFx0dGhpcy53bXNQYXJhbXMgPSB3bXNQYXJhbXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdG9uQWRkOiBmdW5jdGlvbiAobWFwKSB7XHJcblxyXG4gIFx0XHR0aGlzLl9jcnMgPSB0aGlzLm9wdGlvbnMuY3JzIHx8IG1hcC5vcHRpb25zLmNycztcclxuICBcdFx0dGhpcy5fd21zVmVyc2lvbiA9IHBhcnNlRmxvYXQodGhpcy53bXNQYXJhbXMudmVyc2lvbik7XHJcblxyXG4gIFx0XHR2YXIgcHJvamVjdGlvbktleSA9IHRoaXMuX3dtc1ZlcnNpb24gPj0gMS4zID8gJ2NycycgOiAnc3JzJztcclxuICBcdFx0dGhpcy53bXNQYXJhbXNbcHJvamVjdGlvbktleV0gPSB0aGlzLl9jcnMuY29kZTtcclxuXHJcbiAgXHRcdFRpbGVMYXllci5wcm90b3R5cGUub25BZGQuY2FsbCh0aGlzLCBtYXApO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRnZXRUaWxlVXJsOiBmdW5jdGlvbiAoY29vcmRzKSB7XHJcblxyXG4gIFx0XHR2YXIgdGlsZUJvdW5kcyA9IHRoaXMuX3RpbGVDb29yZHNUb053U2UoY29vcmRzKSxcclxuICBcdFx0ICAgIGNycyA9IHRoaXMuX2NycyxcclxuICBcdFx0ICAgIGJvdW5kcyA9IHRvQm91bmRzKGNycy5wcm9qZWN0KHRpbGVCb3VuZHNbMF0pLCBjcnMucHJvamVjdCh0aWxlQm91bmRzWzFdKSksXHJcbiAgXHRcdCAgICBtaW4gPSBib3VuZHMubWluLFxyXG4gIFx0XHQgICAgbWF4ID0gYm91bmRzLm1heCxcclxuICBcdFx0ICAgIGJib3ggPSAodGhpcy5fd21zVmVyc2lvbiA+PSAxLjMgJiYgdGhpcy5fY3JzID09PSBFUFNHNDMyNiA/XHJcbiAgXHRcdCAgICBbbWluLnksIG1pbi54LCBtYXgueSwgbWF4LnhdIDpcclxuICBcdFx0ICAgIFttaW4ueCwgbWluLnksIG1heC54LCBtYXgueV0pLmpvaW4oJywnKSxcclxuICBcdFx0ICAgIHVybCA9IFRpbGVMYXllci5wcm90b3R5cGUuZ2V0VGlsZVVybC5jYWxsKHRoaXMsIGNvb3Jkcyk7XHJcbiAgXHRcdHJldHVybiB1cmwgK1xyXG4gIFx0XHRcdGdldFBhcmFtU3RyaW5nKHRoaXMud21zUGFyYW1zLCB1cmwsIHRoaXMub3B0aW9ucy51cHBlcmNhc2UpICtcclxuICBcdFx0XHQodGhpcy5vcHRpb25zLnVwcGVyY2FzZSA/ICcmQkJPWD0nIDogJyZiYm94PScpICsgYmJveDtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBzZXRQYXJhbXMocGFyYW1zOiBPYmplY3QsIG5vUmVkcmF3PzogQm9vbGVhbik6IHRoaXNcclxuICBcdC8vIE1lcmdlcyBhbiBvYmplY3Qgd2l0aCB0aGUgbmV3IHBhcmFtZXRlcnMgYW5kIHJlLXJlcXVlc3RzIHRpbGVzIG9uIHRoZSBjdXJyZW50IHNjcmVlbiAodW5sZXNzIGBub1JlZHJhd2Agd2FzIHNldCB0byB0cnVlKS5cclxuICBcdHNldFBhcmFtczogZnVuY3Rpb24gKHBhcmFtcywgbm9SZWRyYXcpIHtcclxuXHJcbiAgXHRcdGV4dGVuZCh0aGlzLndtc1BhcmFtcywgcGFyYW1zKTtcclxuXHJcbiAgXHRcdGlmICghbm9SZWRyYXcpIHtcclxuICBcdFx0XHR0aGlzLnJlZHJhdygpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH1cclxuICB9KTtcclxuXHJcblxyXG4gIC8vIEBmYWN0b3J5IEwudGlsZUxheWVyLndtcyhiYXNlVXJsOiBTdHJpbmcsIG9wdGlvbnM6IFRpbGVMYXllci5XTVMgb3B0aW9ucylcclxuICAvLyBJbnN0YW50aWF0ZXMgYSBXTVMgdGlsZSBsYXllciBvYmplY3QgZ2l2ZW4gYSBiYXNlIFVSTCBvZiB0aGUgV01TIHNlcnZpY2UgYW5kIGEgV01TIHBhcmFtZXRlcnMvb3B0aW9ucyBvYmplY3QuXHJcbiAgZnVuY3Rpb24gdGlsZUxheWVyV01TKHVybCwgb3B0aW9ucykge1xyXG4gIFx0cmV0dXJuIG5ldyBUaWxlTGF5ZXJXTVModXJsLCBvcHRpb25zKTtcclxuICB9XG5cbiAgVGlsZUxheWVyLldNUyA9IFRpbGVMYXllcldNUztcbiAgdGlsZUxheWVyLndtcyA9IHRpbGVMYXllcldNUztcblxuICAvKlxuICAgKiBAY2xhc3MgUmVuZGVyZXJcbiAgICogQGluaGVyaXRzIExheWVyXG4gICAqIEBha2EgTC5SZW5kZXJlclxuICAgKlxuICAgKiBCYXNlIGNsYXNzIGZvciB2ZWN0b3IgcmVuZGVyZXIgaW1wbGVtZW50YXRpb25zIChgU1ZHYCwgYENhbnZhc2ApLiBIYW5kbGVzIHRoZVxuICAgKiBET00gY29udGFpbmVyIG9mIHRoZSByZW5kZXJlciwgaXRzIGJvdW5kcywgYW5kIGl0cyB6b29tIGFuaW1hdGlvbi5cbiAgICpcbiAgICogQSBgUmVuZGVyZXJgIHdvcmtzIGFzIGFuIGltcGxpY2l0IGxheWVyIGdyb3VwIGZvciBhbGwgYFBhdGhgcyAtIHRoZSByZW5kZXJlclxuICAgKiBpdHNlbGYgY2FuIGJlIGFkZGVkIG9yIHJlbW92ZWQgdG8gdGhlIG1hcC4gQWxsIHBhdGhzIHVzZSBhIHJlbmRlcmVyLCB3aGljaCBjYW5cbiAgICogYmUgaW1wbGljaXQgKHRoZSBtYXAgd2lsbCBkZWNpZGUgdGhlIHR5cGUgb2YgcmVuZGVyZXIgYW5kIHVzZSBpdCBhdXRvbWF0aWNhbGx5KVxuICAgKiBvciBleHBsaWNpdCAodXNpbmcgdGhlIFtgcmVuZGVyZXJgXSgjcGF0aC1yZW5kZXJlcikgb3B0aW9uIG9mIHRoZSBwYXRoKS5cbiAgICpcbiAgICogRG8gbm90IHVzZSB0aGlzIGNsYXNzIGRpcmVjdGx5LCB1c2UgYFNWR2AgYW5kIGBDYW52YXNgIGluc3RlYWQuXG4gICAqXG4gICAqIEBldmVudCB1cGRhdGU6IEV2ZW50XG4gICAqIEZpcmVkIHdoZW4gdGhlIHJlbmRlcmVyIHVwZGF0ZXMgaXRzIGJvdW5kcywgY2VudGVyIGFuZCB6b29tLCBmb3IgZXhhbXBsZSB3aGVuXG4gICAqIGl0cyBtYXAgaGFzIG1vdmVkXG4gICAqL1xuXG4gIHZhciBSZW5kZXJlciA9IExheWVyLmV4dGVuZCh7XG5cbiAgXHQvLyBAc2VjdGlvblxuICBcdC8vIEBha2EgUmVuZGVyZXIgb3B0aW9uc1xuICBcdG9wdGlvbnM6IHtcbiAgXHRcdC8vIEBvcHRpb24gcGFkZGluZzogTnVtYmVyID0gMC4xXG4gIFx0XHQvLyBIb3cgbXVjaCB0byBleHRlbmQgdGhlIGNsaXAgYXJlYSBhcm91bmQgdGhlIG1hcCB2aWV3IChyZWxhdGl2ZSB0byBpdHMgc2l6ZSlcbiAgXHRcdC8vIGUuZy4gMC4xIHdvdWxkIGJlIDEwJSBvZiBtYXAgdmlldyBpbiBlYWNoIGRpcmVjdGlvblxuICBcdFx0cGFkZGluZzogMC4xXG4gIFx0fSxcblxuICBcdGluaXRpYWxpemU6IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gIFx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xuICBcdFx0c3RhbXAodGhpcyk7XG4gIFx0XHR0aGlzLl9sYXllcnMgPSB0aGlzLl9sYXllcnMgfHwge307XG4gIFx0fSxcblxuICBcdG9uQWRkOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRpZiAoIXRoaXMuX2NvbnRhaW5lcikge1xuICBcdFx0XHR0aGlzLl9pbml0Q29udGFpbmVyKCk7IC8vIGRlZmluZWQgYnkgcmVuZGVyZXIgaW1wbGVtZW50YXRpb25zXG5cbiAgXHRcdFx0Ly8gYWx3YXlzIGtlZXAgdHJhbnNmb3JtLW9yaWdpbiBhcyAwIDBcbiAgXHRcdFx0YWRkQ2xhc3ModGhpcy5fY29udGFpbmVyLCAnbGVhZmxldC16b29tLWFuaW1hdGVkJyk7XG4gIFx0XHR9XG5cbiAgXHRcdHRoaXMuZ2V0UGFuZSgpLmFwcGVuZENoaWxkKHRoaXMuX2NvbnRhaW5lcik7XG4gIFx0XHR0aGlzLl91cGRhdGUoKTtcbiAgXHRcdHRoaXMub24oJ3VwZGF0ZScsIHRoaXMuX3VwZGF0ZVBhdGhzLCB0aGlzKTtcbiAgXHR9LFxuXG4gIFx0b25SZW1vdmU6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHRoaXMub2ZmKCd1cGRhdGUnLCB0aGlzLl91cGRhdGVQYXRocywgdGhpcyk7XG4gIFx0XHR0aGlzLl9kZXN0cm95Q29udGFpbmVyKCk7XG4gIFx0fSxcblxuICBcdGdldEV2ZW50czogZnVuY3Rpb24gKCkge1xuICBcdFx0dmFyIGV2ZW50cyA9IHtcbiAgXHRcdFx0dmlld3Jlc2V0OiB0aGlzLl9yZXNldCxcbiAgXHRcdFx0em9vbTogdGhpcy5fb25ab29tLFxuICBcdFx0XHRtb3ZlZW5kOiB0aGlzLl91cGRhdGUsXG4gIFx0XHRcdHpvb21lbmQ6IHRoaXMuX29uWm9vbUVuZFxuICBcdFx0fTtcbiAgXHRcdGlmICh0aGlzLl96b29tQW5pbWF0ZWQpIHtcbiAgXHRcdFx0ZXZlbnRzLnpvb21hbmltID0gdGhpcy5fb25BbmltWm9vbTtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiBldmVudHM7XG4gIFx0fSxcblxuICBcdF9vbkFuaW1ab29tOiBmdW5jdGlvbiAoZXYpIHtcbiAgXHRcdHRoaXMuX3VwZGF0ZVRyYW5zZm9ybShldi5jZW50ZXIsIGV2Lnpvb20pO1xuICBcdH0sXG5cbiAgXHRfb25ab29tOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR0aGlzLl91cGRhdGVUcmFuc2Zvcm0odGhpcy5fbWFwLmdldENlbnRlcigpLCB0aGlzLl9tYXAuZ2V0Wm9vbSgpKTtcbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZVRyYW5zZm9ybTogZnVuY3Rpb24gKGNlbnRlciwgem9vbSkge1xuICBcdFx0dmFyIHNjYWxlID0gdGhpcy5fbWFwLmdldFpvb21TY2FsZSh6b29tLCB0aGlzLl96b29tKSxcbiAgXHRcdCAgICB2aWV3SGFsZiA9IHRoaXMuX21hcC5nZXRTaXplKCkubXVsdGlwbHlCeSgwLjUgKyB0aGlzLm9wdGlvbnMucGFkZGluZyksXG4gIFx0XHQgICAgY3VycmVudENlbnRlclBvaW50ID0gdGhpcy5fbWFwLnByb2plY3QodGhpcy5fY2VudGVyLCB6b29tKSxcblxuICBcdFx0ICAgIHRvcExlZnRPZmZzZXQgPSB2aWV3SGFsZi5tdWx0aXBseUJ5KC1zY2FsZSkuYWRkKGN1cnJlbnRDZW50ZXJQb2ludClcbiAgXHRcdFx0XHQgIC5zdWJ0cmFjdCh0aGlzLl9tYXAuX2dldE5ld1BpeGVsT3JpZ2luKGNlbnRlciwgem9vbSkpO1xuXG4gIFx0XHRpZiAoQnJvd3Nlci5hbnkzZCkge1xuICBcdFx0XHRzZXRUcmFuc2Zvcm0odGhpcy5fY29udGFpbmVyLCB0b3BMZWZ0T2Zmc2V0LCBzY2FsZSk7XG4gIFx0XHR9IGVsc2Uge1xuICBcdFx0XHRzZXRQb3NpdGlvbih0aGlzLl9jb250YWluZXIsIHRvcExlZnRPZmZzZXQpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfcmVzZXQ6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHRoaXMuX3VwZGF0ZSgpO1xuICBcdFx0dGhpcy5fdXBkYXRlVHJhbnNmb3JtKHRoaXMuX2NlbnRlciwgdGhpcy5fem9vbSk7XG5cbiAgXHRcdGZvciAodmFyIGlkIGluIHRoaXMuX2xheWVycykge1xuICBcdFx0XHR0aGlzLl9sYXllcnNbaWRdLl9yZXNldCgpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfb25ab29tRW5kOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRmb3IgKHZhciBpZCBpbiB0aGlzLl9sYXllcnMpIHtcbiAgXHRcdFx0dGhpcy5fbGF5ZXJzW2lkXS5fcHJvamVjdCgpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfdXBkYXRlUGF0aHM6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGZvciAodmFyIGlkIGluIHRoaXMuX2xheWVycykge1xuICBcdFx0XHR0aGlzLl9sYXllcnNbaWRdLl91cGRhdGUoKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZTogZnVuY3Rpb24gKCkge1xuICBcdFx0Ly8gVXBkYXRlIHBpeGVsIGJvdW5kcyBvZiByZW5kZXJlciBjb250YWluZXIgKGZvciBwb3NpdGlvbmluZy9zaXppbmcvY2xpcHBpbmcgbGF0ZXIpXG4gIFx0XHQvLyBTdWJjbGFzc2VzIGFyZSByZXNwb25zaWJsZSBvZiBmaXJpbmcgdGhlICd1cGRhdGUnIGV2ZW50LlxuICBcdFx0dmFyIHAgPSB0aGlzLm9wdGlvbnMucGFkZGluZyxcbiAgXHRcdCAgICBzaXplID0gdGhpcy5fbWFwLmdldFNpemUoKSxcbiAgXHRcdCAgICBtaW4gPSB0aGlzLl9tYXAuY29udGFpbmVyUG9pbnRUb0xheWVyUG9pbnQoc2l6ZS5tdWx0aXBseUJ5KC1wKSkucm91bmQoKTtcblxuICBcdFx0dGhpcy5fYm91bmRzID0gbmV3IEJvdW5kcyhtaW4sIG1pbi5hZGQoc2l6ZS5tdWx0aXBseUJ5KDEgKyBwICogMikpLnJvdW5kKCkpO1xuXG4gIFx0XHR0aGlzLl9jZW50ZXIgPSB0aGlzLl9tYXAuZ2V0Q2VudGVyKCk7XG4gIFx0XHR0aGlzLl96b29tID0gdGhpcy5fbWFwLmdldFpvb20oKTtcbiAgXHR9XG4gIH0pO1xuXG4gIC8qXG4gICAqIEBjbGFzcyBDYW52YXNcbiAgICogQGluaGVyaXRzIFJlbmRlcmVyXG4gICAqIEBha2EgTC5DYW52YXNcbiAgICpcbiAgICogQWxsb3dzIHZlY3RvciBsYXllcnMgdG8gYmUgZGlzcGxheWVkIHdpdGggW2A8Y2FudmFzPmBdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0FQSS9DYW52YXNfQVBJKS5cbiAgICogSW5oZXJpdHMgYFJlbmRlcmVyYC5cbiAgICpcbiAgICogRHVlIHRvIFt0ZWNobmljYWwgbGltaXRhdGlvbnNdKGh0dHBzOi8vY2FuaXVzZS5jb20vY2FudmFzKSwgQ2FudmFzIGlzIG5vdFxuICAgKiBhdmFpbGFibGUgaW4gYWxsIHdlYiBicm93c2Vycywgbm90YWJseSBJRTgsIGFuZCBvdmVybGFwcGluZyBnZW9tZXRyaWVzIG1pZ2h0XG4gICAqIG5vdCBkaXNwbGF5IHByb3Blcmx5IGluIHNvbWUgZWRnZSBjYXNlcy5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICpcbiAgICogVXNlIENhbnZhcyBieSBkZWZhdWx0IGZvciBhbGwgcGF0aHMgaW4gdGhlIG1hcDpcbiAgICpcbiAgICogYGBganNcbiAgICogdmFyIG1hcCA9IEwubWFwKCdtYXAnLCB7XG4gICAqIFx0cmVuZGVyZXI6IEwuY2FudmFzKClcbiAgICogfSk7XG4gICAqIGBgYFxuICAgKlxuICAgKiBVc2UgYSBDYW52YXMgcmVuZGVyZXIgd2l0aCBleHRyYSBwYWRkaW5nIGZvciBzcGVjaWZpYyB2ZWN0b3IgZ2VvbWV0cmllczpcbiAgICpcbiAgICogYGBganNcbiAgICogdmFyIG1hcCA9IEwubWFwKCdtYXAnKTtcbiAgICogdmFyIG15UmVuZGVyZXIgPSBMLmNhbnZhcyh7IHBhZGRpbmc6IDAuNSB9KTtcbiAgICogdmFyIGxpbmUgPSBMLnBvbHlsaW5lKCBjb29yZGluYXRlcywgeyByZW5kZXJlcjogbXlSZW5kZXJlciB9ICk7XG4gICAqIHZhciBjaXJjbGUgPSBMLmNpcmNsZSggY2VudGVyLCB7IHJlbmRlcmVyOiBteVJlbmRlcmVyIH0gKTtcbiAgICogYGBgXG4gICAqL1xuXG4gIHZhciBDYW52YXMgPSBSZW5kZXJlci5leHRlbmQoe1xuXG4gIFx0Ly8gQHNlY3Rpb25cbiAgXHQvLyBAYWthIENhbnZhcyBvcHRpb25zXG4gIFx0b3B0aW9uczoge1xuICBcdFx0Ly8gQG9wdGlvbiB0b2xlcmFuY2U6IE51bWJlciA9IDBcbiAgXHRcdC8vIEhvdyBtdWNoIHRvIGV4dGVuZCB0aGUgY2xpY2sgdG9sZXJhbmNlIGFyb3VuZCBhIHBhdGgvb2JqZWN0IG9uIHRoZSBtYXAuXG4gIFx0XHR0b2xlcmFuY2U6IDBcbiAgXHR9LFxuXG4gIFx0Z2V0RXZlbnRzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR2YXIgZXZlbnRzID0gUmVuZGVyZXIucHJvdG90eXBlLmdldEV2ZW50cy5jYWxsKHRoaXMpO1xuICBcdFx0ZXZlbnRzLnZpZXdwcmVyZXNldCA9IHRoaXMuX29uVmlld1ByZVJlc2V0O1xuICBcdFx0cmV0dXJuIGV2ZW50cztcbiAgXHR9LFxuXG4gIFx0X29uVmlld1ByZVJlc2V0OiBmdW5jdGlvbiAoKSB7XG4gIFx0XHQvLyBTZXQgYSBmbGFnIHNvIHRoYXQgYSB2aWV3cHJlcmVzZXQrbW92ZWVuZCt2aWV3cmVzZXQgb25seSB1cGRhdGVzJnJlZHJhd3Mgb25jZVxuICBcdFx0dGhpcy5fcG9zdHBvbmVVcGRhdGVQYXRocyA9IHRydWU7XG4gIFx0fSxcblxuICBcdG9uQWRkOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRSZW5kZXJlci5wcm90b3R5cGUub25BZGQuY2FsbCh0aGlzKTtcblxuICBcdFx0Ly8gUmVkcmF3IHZlY3RvcnMgc2luY2UgY2FudmFzIGlzIGNsZWFyZWQgdXBvbiByZW1vdmFsLFxuICBcdFx0Ly8gaW4gY2FzZSBvZiByZW1vdmluZyB0aGUgcmVuZGVyZXIgaXRzZWxmIGZyb20gdGhlIG1hcC5cbiAgXHRcdHRoaXMuX2RyYXcoKTtcbiAgXHR9LFxuXG4gIFx0X2luaXRDb250YWluZXI6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHZhciBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcblxuICBcdFx0b24oY29udGFpbmVyLCAnbW91c2Vtb3ZlJywgdGhpcy5fb25Nb3VzZU1vdmUsIHRoaXMpO1xuICBcdFx0b24oY29udGFpbmVyLCAnY2xpY2sgZGJsY2xpY2sgbW91c2Vkb3duIG1vdXNldXAgY29udGV4dG1lbnUnLCB0aGlzLl9vbkNsaWNrLCB0aGlzKTtcbiAgXHRcdG9uKGNvbnRhaW5lciwgJ21vdXNlb3V0JywgdGhpcy5faGFuZGxlTW91c2VPdXQsIHRoaXMpO1xuICBcdFx0Y29udGFpbmVyWydfbGVhZmxldF9kaXNhYmxlX2V2ZW50cyddID0gdHJ1ZTtcblxuICBcdFx0dGhpcy5fY3R4ID0gY29udGFpbmVyLmdldENvbnRleHQoJzJkJyk7XG4gIFx0fSxcblxuICBcdF9kZXN0cm95Q29udGFpbmVyOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRjYW5jZWxBbmltRnJhbWUodGhpcy5fcmVkcmF3UmVxdWVzdCk7XG4gIFx0XHRkZWxldGUgdGhpcy5fY3R4O1xuICBcdFx0cmVtb3ZlKHRoaXMuX2NvbnRhaW5lcik7XG4gIFx0XHRvZmYodGhpcy5fY29udGFpbmVyKTtcbiAgXHRcdGRlbGV0ZSB0aGlzLl9jb250YWluZXI7XG4gIFx0fSxcblxuICBcdF91cGRhdGVQYXRoczogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKHRoaXMuX3Bvc3Rwb25lVXBkYXRlUGF0aHMpIHsgcmV0dXJuOyB9XG5cbiAgXHRcdHZhciBsYXllcjtcbiAgXHRcdHRoaXMuX3JlZHJhd0JvdW5kcyA9IG51bGw7XG4gIFx0XHRmb3IgKHZhciBpZCBpbiB0aGlzLl9sYXllcnMpIHtcbiAgXHRcdFx0bGF5ZXIgPSB0aGlzLl9sYXllcnNbaWRdO1xuICBcdFx0XHRsYXllci5fdXBkYXRlKCk7XG4gIFx0XHR9XG4gIFx0XHR0aGlzLl9yZWRyYXcoKTtcbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZTogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKHRoaXMuX21hcC5fYW5pbWF0aW5nWm9vbSAmJiB0aGlzLl9ib3VuZHMpIHsgcmV0dXJuOyB9XG5cbiAgXHRcdFJlbmRlcmVyLnByb3RvdHlwZS5fdXBkYXRlLmNhbGwodGhpcyk7XG5cbiAgXHRcdHZhciBiID0gdGhpcy5fYm91bmRzLFxuICBcdFx0ICAgIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRhaW5lcixcbiAgXHRcdCAgICBzaXplID0gYi5nZXRTaXplKCksXG4gIFx0XHQgICAgbSA9IEJyb3dzZXIucmV0aW5hID8gMiA6IDE7XG5cbiAgXHRcdHNldFBvc2l0aW9uKGNvbnRhaW5lciwgYi5taW4pO1xuXG4gIFx0XHQvLyBzZXQgY2FudmFzIHNpemUgKGFsc28gY2xlYXJpbmcgaXQpOyB1c2UgZG91YmxlIHNpemUgb24gcmV0aW5hXG4gIFx0XHRjb250YWluZXIud2lkdGggPSBtICogc2l6ZS54O1xuICBcdFx0Y29udGFpbmVyLmhlaWdodCA9IG0gKiBzaXplLnk7XG4gIFx0XHRjb250YWluZXIuc3R5bGUud2lkdGggPSBzaXplLnggKyAncHgnO1xuICBcdFx0Y29udGFpbmVyLnN0eWxlLmhlaWdodCA9IHNpemUueSArICdweCc7XG5cbiAgXHRcdGlmIChCcm93c2VyLnJldGluYSkge1xuICBcdFx0XHR0aGlzLl9jdHguc2NhbGUoMiwgMik7XG4gIFx0XHR9XG5cbiAgXHRcdC8vIHRyYW5zbGF0ZSBzbyB3ZSB1c2UgdGhlIHNhbWUgcGF0aCBjb29yZGluYXRlcyBhZnRlciBjYW52YXMgZWxlbWVudCBtb3Zlc1xuICBcdFx0dGhpcy5fY3R4LnRyYW5zbGF0ZSgtYi5taW4ueCwgLWIubWluLnkpO1xuXG4gIFx0XHQvLyBUZWxsIHBhdGhzIHRvIHJlZHJhdyB0aGVtc2VsdmVzXG4gIFx0XHR0aGlzLmZpcmUoJ3VwZGF0ZScpO1xuICBcdH0sXG5cbiAgXHRfcmVzZXQ6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdFJlbmRlcmVyLnByb3RvdHlwZS5fcmVzZXQuY2FsbCh0aGlzKTtcblxuICBcdFx0aWYgKHRoaXMuX3Bvc3Rwb25lVXBkYXRlUGF0aHMpIHtcbiAgXHRcdFx0dGhpcy5fcG9zdHBvbmVVcGRhdGVQYXRocyA9IGZhbHNlO1xuICBcdFx0XHR0aGlzLl91cGRhdGVQYXRocygpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfaW5pdFBhdGg6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0dGhpcy5fdXBkYXRlRGFzaEFycmF5KGxheWVyKTtcbiAgXHRcdHRoaXMuX2xheWVyc1tzdGFtcChsYXllcildID0gbGF5ZXI7XG5cbiAgXHRcdHZhciBvcmRlciA9IGxheWVyLl9vcmRlciA9IHtcbiAgXHRcdFx0bGF5ZXI6IGxheWVyLFxuICBcdFx0XHRwcmV2OiB0aGlzLl9kcmF3TGFzdCxcbiAgXHRcdFx0bmV4dDogbnVsbFxuICBcdFx0fTtcbiAgXHRcdGlmICh0aGlzLl9kcmF3TGFzdCkgeyB0aGlzLl9kcmF3TGFzdC5uZXh0ID0gb3JkZXI7IH1cbiAgXHRcdHRoaXMuX2RyYXdMYXN0ID0gb3JkZXI7XG4gIFx0XHR0aGlzLl9kcmF3Rmlyc3QgPSB0aGlzLl9kcmF3Rmlyc3QgfHwgdGhpcy5fZHJhd0xhc3Q7XG4gIFx0fSxcblxuICBcdF9hZGRQYXRoOiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdHRoaXMuX3JlcXVlc3RSZWRyYXcobGF5ZXIpO1xuICBcdH0sXG5cbiAgXHRfcmVtb3ZlUGF0aDogZnVuY3Rpb24gKGxheWVyKSB7XG4gIFx0XHR2YXIgb3JkZXIgPSBsYXllci5fb3JkZXI7XG4gIFx0XHR2YXIgbmV4dCA9IG9yZGVyLm5leHQ7XG4gIFx0XHR2YXIgcHJldiA9IG9yZGVyLnByZXY7XG5cbiAgXHRcdGlmIChuZXh0KSB7XG4gIFx0XHRcdG5leHQucHJldiA9IHByZXY7XG4gIFx0XHR9IGVsc2Uge1xuICBcdFx0XHR0aGlzLl9kcmF3TGFzdCA9IHByZXY7XG4gIFx0XHR9XG4gIFx0XHRpZiAocHJldikge1xuICBcdFx0XHRwcmV2Lm5leHQgPSBuZXh0O1xuICBcdFx0fSBlbHNlIHtcbiAgXHRcdFx0dGhpcy5fZHJhd0ZpcnN0ID0gbmV4dDtcbiAgXHRcdH1cblxuICBcdFx0ZGVsZXRlIGxheWVyLl9vcmRlcjtcblxuICBcdFx0ZGVsZXRlIHRoaXMuX2xheWVyc1tzdGFtcChsYXllcildO1xuXG4gIFx0XHR0aGlzLl9yZXF1ZXN0UmVkcmF3KGxheWVyKTtcbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZVBhdGg6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0Ly8gUmVkcmF3IHRoZSB1bmlvbiBvZiB0aGUgbGF5ZXIncyBvbGQgcGl4ZWxcbiAgXHRcdC8vIGJvdW5kcyBhbmQgdGhlIG5ldyBwaXhlbCBib3VuZHMuXG4gIFx0XHR0aGlzLl9leHRlbmRSZWRyYXdCb3VuZHMobGF5ZXIpO1xuICBcdFx0bGF5ZXIuX3Byb2plY3QoKTtcbiAgXHRcdGxheWVyLl91cGRhdGUoKTtcbiAgXHRcdC8vIFRoZSByZWRyYXcgd2lsbCBleHRlbmQgdGhlIHJlZHJhdyBib3VuZHNcbiAgXHRcdC8vIHdpdGggdGhlIG5ldyBwaXhlbCBib3VuZHMuXG4gIFx0XHR0aGlzLl9yZXF1ZXN0UmVkcmF3KGxheWVyKTtcbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZVN0eWxlOiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdHRoaXMuX3VwZGF0ZURhc2hBcnJheShsYXllcik7XG4gIFx0XHR0aGlzLl9yZXF1ZXN0UmVkcmF3KGxheWVyKTtcbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZURhc2hBcnJheTogZnVuY3Rpb24gKGxheWVyKSB7XG4gIFx0XHRpZiAodHlwZW9mIGxheWVyLm9wdGlvbnMuZGFzaEFycmF5ID09PSAnc3RyaW5nJykge1xuICBcdFx0XHR2YXIgcGFydHMgPSBsYXllci5vcHRpb25zLmRhc2hBcnJheS5zcGxpdCgvWywgXSsvKSxcbiAgXHRcdFx0ICAgIGRhc2hBcnJheSA9IFtdLFxuICBcdFx0XHQgICAgZGFzaFZhbHVlLFxuICBcdFx0XHQgICAgaTtcbiAgXHRcdFx0Zm9yIChpID0gMDsgaSA8IHBhcnRzLmxlbmd0aDsgaSsrKSB7XG4gIFx0XHRcdFx0ZGFzaFZhbHVlID0gTnVtYmVyKHBhcnRzW2ldKTtcbiAgXHRcdFx0XHQvLyBJZ25vcmUgZGFzaCBhcnJheSBjb250YWluaW5nIGludmFsaWQgbGVuZ3Roc1xuICBcdFx0XHRcdGlmIChpc05hTihkYXNoVmFsdWUpKSB7IHJldHVybjsgfVxuICBcdFx0XHRcdGRhc2hBcnJheS5wdXNoKGRhc2hWYWx1ZSk7XG4gIFx0XHRcdH1cbiAgXHRcdFx0bGF5ZXIub3B0aW9ucy5fZGFzaEFycmF5ID0gZGFzaEFycmF5O1xuICBcdFx0fSBlbHNlIHtcbiAgXHRcdFx0bGF5ZXIub3B0aW9ucy5fZGFzaEFycmF5ID0gbGF5ZXIub3B0aW9ucy5kYXNoQXJyYXk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF9yZXF1ZXN0UmVkcmF3OiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdGlmICghdGhpcy5fbWFwKSB7IHJldHVybjsgfVxuXG4gIFx0XHR0aGlzLl9leHRlbmRSZWRyYXdCb3VuZHMobGF5ZXIpO1xuICBcdFx0dGhpcy5fcmVkcmF3UmVxdWVzdCA9IHRoaXMuX3JlZHJhd1JlcXVlc3QgfHwgcmVxdWVzdEFuaW1GcmFtZSh0aGlzLl9yZWRyYXcsIHRoaXMpO1xuICBcdH0sXG5cbiAgXHRfZXh0ZW5kUmVkcmF3Qm91bmRzOiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdGlmIChsYXllci5fcHhCb3VuZHMpIHtcbiAgXHRcdFx0dmFyIHBhZGRpbmcgPSAobGF5ZXIub3B0aW9ucy53ZWlnaHQgfHwgMCkgKyAxO1xuICBcdFx0XHR0aGlzLl9yZWRyYXdCb3VuZHMgPSB0aGlzLl9yZWRyYXdCb3VuZHMgfHwgbmV3IEJvdW5kcygpO1xuICBcdFx0XHR0aGlzLl9yZWRyYXdCb3VuZHMuZXh0ZW5kKGxheWVyLl9weEJvdW5kcy5taW4uc3VidHJhY3QoW3BhZGRpbmcsIHBhZGRpbmddKSk7XG4gIFx0XHRcdHRoaXMuX3JlZHJhd0JvdW5kcy5leHRlbmQobGF5ZXIuX3B4Qm91bmRzLm1heC5hZGQoW3BhZGRpbmcsIHBhZGRpbmddKSk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF9yZWRyYXc6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHRoaXMuX3JlZHJhd1JlcXVlc3QgPSBudWxsO1xuXG4gIFx0XHRpZiAodGhpcy5fcmVkcmF3Qm91bmRzKSB7XG4gIFx0XHRcdHRoaXMuX3JlZHJhd0JvdW5kcy5taW4uX2Zsb29yKCk7XG4gIFx0XHRcdHRoaXMuX3JlZHJhd0JvdW5kcy5tYXguX2NlaWwoKTtcbiAgXHRcdH1cblxuICBcdFx0dGhpcy5fY2xlYXIoKTsgLy8gY2xlYXIgbGF5ZXJzIGluIHJlZHJhdyBib3VuZHNcbiAgXHRcdHRoaXMuX2RyYXcoKTsgLy8gZHJhdyBsYXllcnNcblxuICBcdFx0dGhpcy5fcmVkcmF3Qm91bmRzID0gbnVsbDtcbiAgXHR9LFxuXG4gIFx0X2NsZWFyOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR2YXIgYm91bmRzID0gdGhpcy5fcmVkcmF3Qm91bmRzO1xuICBcdFx0aWYgKGJvdW5kcykge1xuICBcdFx0XHR2YXIgc2l6ZSA9IGJvdW5kcy5nZXRTaXplKCk7XG4gIFx0XHRcdHRoaXMuX2N0eC5jbGVhclJlY3QoYm91bmRzLm1pbi54LCBib3VuZHMubWluLnksIHNpemUueCwgc2l6ZS55KTtcbiAgXHRcdH0gZWxzZSB7XG4gIFx0XHRcdHRoaXMuX2N0eC5zYXZlKCk7XG4gIFx0XHRcdHRoaXMuX2N0eC5zZXRUcmFuc2Zvcm0oMSwgMCwgMCwgMSwgMCwgMCk7XG4gIFx0XHRcdHRoaXMuX2N0eC5jbGVhclJlY3QoMCwgMCwgdGhpcy5fY29udGFpbmVyLndpZHRoLCB0aGlzLl9jb250YWluZXIuaGVpZ2h0KTtcbiAgXHRcdFx0dGhpcy5fY3R4LnJlc3RvcmUoKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X2RyYXc6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHZhciBsYXllciwgYm91bmRzID0gdGhpcy5fcmVkcmF3Qm91bmRzO1xuICBcdFx0dGhpcy5fY3R4LnNhdmUoKTtcbiAgXHRcdGlmIChib3VuZHMpIHtcbiAgXHRcdFx0dmFyIHNpemUgPSBib3VuZHMuZ2V0U2l6ZSgpO1xuICBcdFx0XHR0aGlzLl9jdHguYmVnaW5QYXRoKCk7XG4gIFx0XHRcdHRoaXMuX2N0eC5yZWN0KGJvdW5kcy5taW4ueCwgYm91bmRzLm1pbi55LCBzaXplLngsIHNpemUueSk7XG4gIFx0XHRcdHRoaXMuX2N0eC5jbGlwKCk7XG4gIFx0XHR9XG5cbiAgXHRcdHRoaXMuX2RyYXdpbmcgPSB0cnVlO1xuXG4gIFx0XHRmb3IgKHZhciBvcmRlciA9IHRoaXMuX2RyYXdGaXJzdDsgb3JkZXI7IG9yZGVyID0gb3JkZXIubmV4dCkge1xuICBcdFx0XHRsYXllciA9IG9yZGVyLmxheWVyO1xuICBcdFx0XHRpZiAoIWJvdW5kcyB8fCAobGF5ZXIuX3B4Qm91bmRzICYmIGxheWVyLl9weEJvdW5kcy5pbnRlcnNlY3RzKGJvdW5kcykpKSB7XG4gIFx0XHRcdFx0bGF5ZXIuX3VwZGF0ZVBhdGgoKTtcbiAgXHRcdFx0fVxuICBcdFx0fVxuXG4gIFx0XHR0aGlzLl9kcmF3aW5nID0gZmFsc2U7XG5cbiAgXHRcdHRoaXMuX2N0eC5yZXN0b3JlKCk7ICAvLyBSZXN0b3JlIHN0YXRlIGJlZm9yZSBjbGlwcGluZy5cbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZVBvbHk6IGZ1bmN0aW9uIChsYXllciwgY2xvc2VkKSB7XG4gIFx0XHRpZiAoIXRoaXMuX2RyYXdpbmcpIHsgcmV0dXJuOyB9XG5cbiAgXHRcdHZhciBpLCBqLCBsZW4yLCBwLFxuICBcdFx0ICAgIHBhcnRzID0gbGF5ZXIuX3BhcnRzLFxuICBcdFx0ICAgIGxlbiA9IHBhcnRzLmxlbmd0aCxcbiAgXHRcdCAgICBjdHggPSB0aGlzLl9jdHg7XG5cbiAgXHRcdGlmICghbGVuKSB7IHJldHVybjsgfVxuXG4gIFx0XHRjdHguYmVnaW5QYXRoKCk7XG5cbiAgXHRcdGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICBcdFx0XHRmb3IgKGogPSAwLCBsZW4yID0gcGFydHNbaV0ubGVuZ3RoOyBqIDwgbGVuMjsgaisrKSB7XG4gIFx0XHRcdFx0cCA9IHBhcnRzW2ldW2pdO1xuICBcdFx0XHRcdGN0eFtqID8gJ2xpbmVUbycgOiAnbW92ZVRvJ10ocC54LCBwLnkpO1xuICBcdFx0XHR9XG4gIFx0XHRcdGlmIChjbG9zZWQpIHtcbiAgXHRcdFx0XHRjdHguY2xvc2VQYXRoKCk7XG4gIFx0XHRcdH1cbiAgXHRcdH1cblxuICBcdFx0dGhpcy5fZmlsbFN0cm9rZShjdHgsIGxheWVyKTtcblxuICBcdFx0Ly8gVE9ETyBvcHRpbWl6YXRpb246IDEgZmlsbC9zdHJva2UgZm9yIGFsbCBmZWF0dXJlcyB3aXRoIGVxdWFsIHN0eWxlIGluc3RlYWQgb2YgMSBmb3IgZWFjaCBmZWF0dXJlXG4gIFx0fSxcblxuICBcdF91cGRhdGVDaXJjbGU6IGZ1bmN0aW9uIChsYXllcikge1xuXG4gIFx0XHRpZiAoIXRoaXMuX2RyYXdpbmcgfHwgbGF5ZXIuX2VtcHR5KCkpIHsgcmV0dXJuOyB9XG5cbiAgXHRcdHZhciBwID0gbGF5ZXIuX3BvaW50LFxuICBcdFx0ICAgIGN0eCA9IHRoaXMuX2N0eCxcbiAgXHRcdCAgICByID0gTWF0aC5tYXgoTWF0aC5yb3VuZChsYXllci5fcmFkaXVzKSwgMSksXG4gIFx0XHQgICAgcyA9IChNYXRoLm1heChNYXRoLnJvdW5kKGxheWVyLl9yYWRpdXNZKSwgMSkgfHwgcikgLyByO1xuXG4gIFx0XHRpZiAocyAhPT0gMSkge1xuICBcdFx0XHRjdHguc2F2ZSgpO1xuICBcdFx0XHRjdHguc2NhbGUoMSwgcyk7XG4gIFx0XHR9XG5cbiAgXHRcdGN0eC5iZWdpblBhdGgoKTtcbiAgXHRcdGN0eC5hcmMocC54LCBwLnkgLyBzLCByLCAwLCBNYXRoLlBJICogMiwgZmFsc2UpO1xuXG4gIFx0XHRpZiAocyAhPT0gMSkge1xuICBcdFx0XHRjdHgucmVzdG9yZSgpO1xuICBcdFx0fVxuXG4gIFx0XHR0aGlzLl9maWxsU3Ryb2tlKGN0eCwgbGF5ZXIpO1xuICBcdH0sXG5cbiAgXHRfZmlsbFN0cm9rZTogZnVuY3Rpb24gKGN0eCwgbGF5ZXIpIHtcbiAgXHRcdHZhciBvcHRpb25zID0gbGF5ZXIub3B0aW9ucztcblxuICBcdFx0aWYgKG9wdGlvbnMuZmlsbCkge1xuICBcdFx0XHRjdHguZ2xvYmFsQWxwaGEgPSBvcHRpb25zLmZpbGxPcGFjaXR5O1xuICBcdFx0XHRjdHguZmlsbFN0eWxlID0gb3B0aW9ucy5maWxsQ29sb3IgfHwgb3B0aW9ucy5jb2xvcjtcbiAgXHRcdFx0Y3R4LmZpbGwob3B0aW9ucy5maWxsUnVsZSB8fCAnZXZlbm9kZCcpO1xuICBcdFx0fVxuXG4gIFx0XHRpZiAob3B0aW9ucy5zdHJva2UgJiYgb3B0aW9ucy53ZWlnaHQgIT09IDApIHtcbiAgXHRcdFx0aWYgKGN0eC5zZXRMaW5lRGFzaCkge1xuICBcdFx0XHRcdGN0eC5zZXRMaW5lRGFzaChsYXllci5vcHRpb25zICYmIGxheWVyLm9wdGlvbnMuX2Rhc2hBcnJheSB8fCBbXSk7XG4gIFx0XHRcdH1cbiAgXHRcdFx0Y3R4Lmdsb2JhbEFscGhhID0gb3B0aW9ucy5vcGFjaXR5O1xuICBcdFx0XHRjdHgubGluZVdpZHRoID0gb3B0aW9ucy53ZWlnaHQ7XG4gIFx0XHRcdGN0eC5zdHJva2VTdHlsZSA9IG9wdGlvbnMuY29sb3I7XG4gIFx0XHRcdGN0eC5saW5lQ2FwID0gb3B0aW9ucy5saW5lQ2FwO1xuICBcdFx0XHRjdHgubGluZUpvaW4gPSBvcHRpb25zLmxpbmVKb2luO1xuICBcdFx0XHRjdHguc3Ryb2tlKCk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdC8vIENhbnZhcyBvYnZpb3VzbHkgZG9lc24ndCBoYXZlIG1vdXNlIGV2ZW50cyBmb3IgaW5kaXZpZHVhbCBkcmF3biBvYmplY3RzLFxuICBcdC8vIHNvIHdlIGVtdWxhdGUgdGhhdCBieSBjYWxjdWxhdGluZyB3aGF0J3MgdW5kZXIgdGhlIG1vdXNlIG9uIG1vdXNlbW92ZS9jbGljayBtYW51YWxseVxuXG4gIFx0X29uQ2xpY2s6IGZ1bmN0aW9uIChlKSB7XG4gIFx0XHR2YXIgcG9pbnQgPSB0aGlzLl9tYXAubW91c2VFdmVudFRvTGF5ZXJQb2ludChlKSwgbGF5ZXIsIGNsaWNrZWRMYXllcjtcblxuICBcdFx0Zm9yICh2YXIgb3JkZXIgPSB0aGlzLl9kcmF3Rmlyc3Q7IG9yZGVyOyBvcmRlciA9IG9yZGVyLm5leHQpIHtcbiAgXHRcdFx0bGF5ZXIgPSBvcmRlci5sYXllcjtcbiAgXHRcdFx0aWYgKGxheWVyLm9wdGlvbnMuaW50ZXJhY3RpdmUgJiYgbGF5ZXIuX2NvbnRhaW5zUG9pbnQocG9pbnQpKSB7XG4gIFx0XHRcdFx0aWYgKCEoZS50eXBlID09PSAnY2xpY2snIHx8IGUudHlwZSA9PT0gJ3ByZWNsaWNrJykgfHwgIXRoaXMuX21hcC5fZHJhZ2dhYmxlTW92ZWQobGF5ZXIpKSB7XG4gIFx0XHRcdFx0XHRjbGlja2VkTGF5ZXIgPSBsYXllcjtcbiAgXHRcdFx0XHR9XG4gIFx0XHRcdH1cbiAgXHRcdH1cbiAgXHRcdHRoaXMuX2ZpcmVFdmVudChjbGlja2VkTGF5ZXIgPyBbY2xpY2tlZExheWVyXSA6IGZhbHNlLCBlKTtcbiAgXHR9LFxuXG4gIFx0X29uTW91c2VNb3ZlOiBmdW5jdGlvbiAoZSkge1xuICBcdFx0aWYgKCF0aGlzLl9tYXAgfHwgdGhpcy5fbWFwLmRyYWdnaW5nLm1vdmluZygpIHx8IHRoaXMuX21hcC5fYW5pbWF0aW5nWm9vbSkgeyByZXR1cm47IH1cblxuICBcdFx0dmFyIHBvaW50ID0gdGhpcy5fbWFwLm1vdXNlRXZlbnRUb0xheWVyUG9pbnQoZSk7XG4gIFx0XHR0aGlzLl9oYW5kbGVNb3VzZUhvdmVyKGUsIHBvaW50KTtcbiAgXHR9LFxuXG5cbiAgXHRfaGFuZGxlTW91c2VPdXQ6IGZ1bmN0aW9uIChlKSB7XG4gIFx0XHR2YXIgbGF5ZXIgPSB0aGlzLl9ob3ZlcmVkTGF5ZXI7XG4gIFx0XHRpZiAobGF5ZXIpIHtcbiAgXHRcdFx0Ly8gaWYgd2UncmUgbGVhdmluZyB0aGUgbGF5ZXIsIGZpcmUgbW91c2VvdXRcbiAgXHRcdFx0cmVtb3ZlQ2xhc3ModGhpcy5fY29udGFpbmVyLCAnbGVhZmxldC1pbnRlcmFjdGl2ZScpO1xuICBcdFx0XHR0aGlzLl9maXJlRXZlbnQoW2xheWVyXSwgZSwgJ21vdXNlb3V0Jyk7XG4gIFx0XHRcdHRoaXMuX2hvdmVyZWRMYXllciA9IG51bGw7XG4gIFx0XHRcdHRoaXMuX21vdXNlSG92ZXJUaHJvdHRsZWQgPSBmYWxzZTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X2hhbmRsZU1vdXNlSG92ZXI6IGZ1bmN0aW9uIChlLCBwb2ludCkge1xuICBcdFx0aWYgKHRoaXMuX21vdXNlSG92ZXJUaHJvdHRsZWQpIHtcbiAgXHRcdFx0cmV0dXJuO1xuICBcdFx0fVxuXG4gIFx0XHR2YXIgbGF5ZXIsIGNhbmRpZGF0ZUhvdmVyZWRMYXllcjtcblxuICBcdFx0Zm9yICh2YXIgb3JkZXIgPSB0aGlzLl9kcmF3Rmlyc3Q7IG9yZGVyOyBvcmRlciA9IG9yZGVyLm5leHQpIHtcbiAgXHRcdFx0bGF5ZXIgPSBvcmRlci5sYXllcjtcbiAgXHRcdFx0aWYgKGxheWVyLm9wdGlvbnMuaW50ZXJhY3RpdmUgJiYgbGF5ZXIuX2NvbnRhaW5zUG9pbnQocG9pbnQpKSB7XG4gIFx0XHRcdFx0Y2FuZGlkYXRlSG92ZXJlZExheWVyID0gbGF5ZXI7XG4gIFx0XHRcdH1cbiAgXHRcdH1cblxuICBcdFx0aWYgKGNhbmRpZGF0ZUhvdmVyZWRMYXllciAhPT0gdGhpcy5faG92ZXJlZExheWVyKSB7XG4gIFx0XHRcdHRoaXMuX2hhbmRsZU1vdXNlT3V0KGUpO1xuXG4gIFx0XHRcdGlmIChjYW5kaWRhdGVIb3ZlcmVkTGF5ZXIpIHtcbiAgXHRcdFx0XHRhZGRDbGFzcyh0aGlzLl9jb250YWluZXIsICdsZWFmbGV0LWludGVyYWN0aXZlJyk7IC8vIGNoYW5nZSBjdXJzb3JcbiAgXHRcdFx0XHR0aGlzLl9maXJlRXZlbnQoW2NhbmRpZGF0ZUhvdmVyZWRMYXllcl0sIGUsICdtb3VzZW92ZXInKTtcbiAgXHRcdFx0XHR0aGlzLl9ob3ZlcmVkTGF5ZXIgPSBjYW5kaWRhdGVIb3ZlcmVkTGF5ZXI7XG4gIFx0XHRcdH1cbiAgXHRcdH1cblxuICBcdFx0dGhpcy5fZmlyZUV2ZW50KHRoaXMuX2hvdmVyZWRMYXllciA/IFt0aGlzLl9ob3ZlcmVkTGF5ZXJdIDogZmFsc2UsIGUpO1xuXG4gIFx0XHR0aGlzLl9tb3VzZUhvdmVyVGhyb3R0bGVkID0gdHJ1ZTtcbiAgXHRcdHNldFRpbWVvdXQoYmluZChmdW5jdGlvbiAoKSB7XG4gIFx0XHRcdHRoaXMuX21vdXNlSG92ZXJUaHJvdHRsZWQgPSBmYWxzZTtcbiAgXHRcdH0sIHRoaXMpLCAzMik7XG4gIFx0fSxcblxuICBcdF9maXJlRXZlbnQ6IGZ1bmN0aW9uIChsYXllcnMsIGUsIHR5cGUpIHtcbiAgXHRcdHRoaXMuX21hcC5fZmlyZURPTUV2ZW50KGUsIHR5cGUgfHwgZS50eXBlLCBsYXllcnMpO1xuICBcdH0sXG5cbiAgXHRfYnJpbmdUb0Zyb250OiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdHZhciBvcmRlciA9IGxheWVyLl9vcmRlcjtcblxuICBcdFx0aWYgKCFvcmRlcikgeyByZXR1cm47IH1cblxuICBcdFx0dmFyIG5leHQgPSBvcmRlci5uZXh0O1xuICBcdFx0dmFyIHByZXYgPSBvcmRlci5wcmV2O1xuXG4gIFx0XHRpZiAobmV4dCkge1xuICBcdFx0XHRuZXh0LnByZXYgPSBwcmV2O1xuICBcdFx0fSBlbHNlIHtcbiAgXHRcdFx0Ly8gQWxyZWFkeSBsYXN0XG4gIFx0XHRcdHJldHVybjtcbiAgXHRcdH1cbiAgXHRcdGlmIChwcmV2KSB7XG4gIFx0XHRcdHByZXYubmV4dCA9IG5leHQ7XG4gIFx0XHR9IGVsc2UgaWYgKG5leHQpIHtcbiAgXHRcdFx0Ly8gVXBkYXRlIGZpcnN0IGVudHJ5IHVubGVzcyB0aGlzIGlzIHRoZVxuICBcdFx0XHQvLyBzaW5nbGUgZW50cnlcbiAgXHRcdFx0dGhpcy5fZHJhd0ZpcnN0ID0gbmV4dDtcbiAgXHRcdH1cblxuICBcdFx0b3JkZXIucHJldiA9IHRoaXMuX2RyYXdMYXN0O1xuICBcdFx0dGhpcy5fZHJhd0xhc3QubmV4dCA9IG9yZGVyO1xuXG4gIFx0XHRvcmRlci5uZXh0ID0gbnVsbDtcbiAgXHRcdHRoaXMuX2RyYXdMYXN0ID0gb3JkZXI7XG5cbiAgXHRcdHRoaXMuX3JlcXVlc3RSZWRyYXcobGF5ZXIpO1xuICBcdH0sXG5cbiAgXHRfYnJpbmdUb0JhY2s6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0dmFyIG9yZGVyID0gbGF5ZXIuX29yZGVyO1xuXG4gIFx0XHRpZiAoIW9yZGVyKSB7IHJldHVybjsgfVxuXG4gIFx0XHR2YXIgbmV4dCA9IG9yZGVyLm5leHQ7XG4gIFx0XHR2YXIgcHJldiA9IG9yZGVyLnByZXY7XG5cbiAgXHRcdGlmIChwcmV2KSB7XG4gIFx0XHRcdHByZXYubmV4dCA9IG5leHQ7XG4gIFx0XHR9IGVsc2Uge1xuICBcdFx0XHQvLyBBbHJlYWR5IGZpcnN0XG4gIFx0XHRcdHJldHVybjtcbiAgXHRcdH1cbiAgXHRcdGlmIChuZXh0KSB7XG4gIFx0XHRcdG5leHQucHJldiA9IHByZXY7XG4gIFx0XHR9IGVsc2UgaWYgKHByZXYpIHtcbiAgXHRcdFx0Ly8gVXBkYXRlIGxhc3QgZW50cnkgdW5sZXNzIHRoaXMgaXMgdGhlXG4gIFx0XHRcdC8vIHNpbmdsZSBlbnRyeVxuICBcdFx0XHR0aGlzLl9kcmF3TGFzdCA9IHByZXY7XG4gIFx0XHR9XG5cbiAgXHRcdG9yZGVyLnByZXYgPSBudWxsO1xuXG4gIFx0XHRvcmRlci5uZXh0ID0gdGhpcy5fZHJhd0ZpcnN0O1xuICBcdFx0dGhpcy5fZHJhd0ZpcnN0LnByZXYgPSBvcmRlcjtcbiAgXHRcdHRoaXMuX2RyYXdGaXJzdCA9IG9yZGVyO1xuXG4gIFx0XHR0aGlzLl9yZXF1ZXN0UmVkcmF3KGxheWVyKTtcbiAgXHR9XG4gIH0pO1xuXG4gIC8vIEBmYWN0b3J5IEwuY2FudmFzKG9wdGlvbnM/OiBSZW5kZXJlciBvcHRpb25zKVxuICAvLyBDcmVhdGVzIGEgQ2FudmFzIHJlbmRlcmVyIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuXG4gIGZ1bmN0aW9uIGNhbnZhcyhvcHRpb25zKSB7XG4gIFx0cmV0dXJuIEJyb3dzZXIuY2FudmFzID8gbmV3IENhbnZhcyhvcHRpb25zKSA6IG51bGw7XG4gIH1cblxuICAvKlxuICAgKiBUaGFua3MgdG8gRG1pdHJ5IEJhcmFub3Zza3kgYW5kIGhpcyBSYXBoYWVsIGxpYnJhcnkgZm9yIGluc3BpcmF0aW9uIVxuICAgKi9cblxuXG4gIHZhciB2bWxDcmVhdGUgPSAoZnVuY3Rpb24gKCkge1xuICBcdHRyeSB7XG4gIFx0XHRkb2N1bWVudC5uYW1lc3BhY2VzLmFkZCgnbHZtbCcsICd1cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOnZtbCcpO1xuICBcdFx0cmV0dXJuIGZ1bmN0aW9uIChuYW1lKSB7XG4gIFx0XHRcdHJldHVybiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCc8bHZtbDonICsgbmFtZSArICcgY2xhc3M9XCJsdm1sXCI+Jyk7XG4gIFx0XHR9O1xuICBcdH0gY2F0Y2ggKGUpIHtcbiAgXHRcdC8vIERvIG5vdCByZXR1cm4gZm4gZnJvbSBjYXRjaCBibG9jayBzbyBgZWAgY2FuIGJlIGdhcmJhZ2UgY29sbGVjdGVkXG4gIFx0XHQvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL0xlYWZsZXQvTGVhZmxldC9wdWxsLzcyNzlcbiAgXHR9XG4gIFx0cmV0dXJuIGZ1bmN0aW9uIChuYW1lKSB7XG4gIFx0XHRyZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnPCcgKyBuYW1lICsgJyB4bWxucz1cInVybjpzY2hlbWFzLW1pY3Jvc29mdC5jb206dm1sXCIgY2xhc3M9XCJsdm1sXCI+Jyk7XG4gIFx0fTtcbiAgfSkoKTtcblxuXG4gIC8qXG4gICAqIEBjbGFzcyBTVkdcbiAgICpcbiAgICpcbiAgICogVk1MIHdhcyBkZXByZWNhdGVkIGluIDIwMTIsIHdoaWNoIG1lYW5zIFZNTCBmdW5jdGlvbmFsaXR5IGV4aXN0cyBvbmx5IGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eVxuICAgKiB3aXRoIG9sZCB2ZXJzaW9ucyBvZiBJbnRlcm5ldCBFeHBsb3Jlci5cbiAgICovXG5cbiAgLy8gbWl4aW4gdG8gcmVkZWZpbmUgc29tZSBTVkcgbWV0aG9kcyB0byBoYW5kbGUgVk1MIHN5bnRheCB3aGljaCBpcyBzaW1pbGFyIGJ1dCB3aXRoIHNvbWUgZGlmZmVyZW5jZXNcbiAgdmFyIHZtbE1peGluID0ge1xuXG4gIFx0X2luaXRDb250YWluZXI6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHRoaXMuX2NvbnRhaW5lciA9IGNyZWF0ZSQxKCdkaXYnLCAnbGVhZmxldC12bWwtY29udGFpbmVyJyk7XG4gIFx0fSxcblxuICBcdF91cGRhdGU6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICh0aGlzLl9tYXAuX2FuaW1hdGluZ1pvb20pIHsgcmV0dXJuOyB9XG4gIFx0XHRSZW5kZXJlci5wcm90b3R5cGUuX3VwZGF0ZS5jYWxsKHRoaXMpO1xuICBcdFx0dGhpcy5maXJlKCd1cGRhdGUnKTtcbiAgXHR9LFxuXG4gIFx0X2luaXRQYXRoOiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdHZhciBjb250YWluZXIgPSBsYXllci5fY29udGFpbmVyID0gdm1sQ3JlYXRlKCdzaGFwZScpO1xuXG4gIFx0XHRhZGRDbGFzcyhjb250YWluZXIsICdsZWFmbGV0LXZtbC1zaGFwZSAnICsgKHRoaXMub3B0aW9ucy5jbGFzc05hbWUgfHwgJycpKTtcblxuICBcdFx0Y29udGFpbmVyLmNvb3Jkc2l6ZSA9ICcxIDEnO1xuXG4gIFx0XHRsYXllci5fcGF0aCA9IHZtbENyZWF0ZSgncGF0aCcpO1xuICBcdFx0Y29udGFpbmVyLmFwcGVuZENoaWxkKGxheWVyLl9wYXRoKTtcblxuICBcdFx0dGhpcy5fdXBkYXRlU3R5bGUobGF5ZXIpO1xuICBcdFx0dGhpcy5fbGF5ZXJzW3N0YW1wKGxheWVyKV0gPSBsYXllcjtcbiAgXHR9LFxuXG4gIFx0X2FkZFBhdGg6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0dmFyIGNvbnRhaW5lciA9IGxheWVyLl9jb250YWluZXI7XG4gIFx0XHR0aGlzLl9jb250YWluZXIuYXBwZW5kQ2hpbGQoY29udGFpbmVyKTtcblxuICBcdFx0aWYgKGxheWVyLm9wdGlvbnMuaW50ZXJhY3RpdmUpIHtcbiAgXHRcdFx0bGF5ZXIuYWRkSW50ZXJhY3RpdmVUYXJnZXQoY29udGFpbmVyKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3JlbW92ZVBhdGg6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0dmFyIGNvbnRhaW5lciA9IGxheWVyLl9jb250YWluZXI7XG4gIFx0XHRyZW1vdmUoY29udGFpbmVyKTtcbiAgXHRcdGxheWVyLnJlbW92ZUludGVyYWN0aXZlVGFyZ2V0KGNvbnRhaW5lcik7XG4gIFx0XHRkZWxldGUgdGhpcy5fbGF5ZXJzW3N0YW1wKGxheWVyKV07XG4gIFx0fSxcblxuICBcdF91cGRhdGVTdHlsZTogZnVuY3Rpb24gKGxheWVyKSB7XG4gIFx0XHR2YXIgc3Ryb2tlID0gbGF5ZXIuX3N0cm9rZSxcbiAgXHRcdCAgICBmaWxsID0gbGF5ZXIuX2ZpbGwsXG4gIFx0XHQgICAgb3B0aW9ucyA9IGxheWVyLm9wdGlvbnMsXG4gIFx0XHQgICAgY29udGFpbmVyID0gbGF5ZXIuX2NvbnRhaW5lcjtcblxuICBcdFx0Y29udGFpbmVyLnN0cm9rZWQgPSAhIW9wdGlvbnMuc3Ryb2tlO1xuICBcdFx0Y29udGFpbmVyLmZpbGxlZCA9ICEhb3B0aW9ucy5maWxsO1xuXG4gIFx0XHRpZiAob3B0aW9ucy5zdHJva2UpIHtcbiAgXHRcdFx0aWYgKCFzdHJva2UpIHtcbiAgXHRcdFx0XHRzdHJva2UgPSBsYXllci5fc3Ryb2tlID0gdm1sQ3JlYXRlKCdzdHJva2UnKTtcbiAgXHRcdFx0fVxuICBcdFx0XHRjb250YWluZXIuYXBwZW5kQ2hpbGQoc3Ryb2tlKTtcbiAgXHRcdFx0c3Ryb2tlLndlaWdodCA9IG9wdGlvbnMud2VpZ2h0ICsgJ3B4JztcbiAgXHRcdFx0c3Ryb2tlLmNvbG9yID0gb3B0aW9ucy5jb2xvcjtcbiAgXHRcdFx0c3Ryb2tlLm9wYWNpdHkgPSBvcHRpb25zLm9wYWNpdHk7XG5cbiAgXHRcdFx0aWYgKG9wdGlvbnMuZGFzaEFycmF5KSB7XG4gIFx0XHRcdFx0c3Ryb2tlLmRhc2hTdHlsZSA9IGlzQXJyYXkob3B0aW9ucy5kYXNoQXJyYXkpID9cbiAgXHRcdFx0XHQgICAgb3B0aW9ucy5kYXNoQXJyYXkuam9pbignICcpIDpcbiAgXHRcdFx0XHQgICAgb3B0aW9ucy5kYXNoQXJyYXkucmVwbGFjZSgvKCAqLCAqKS9nLCAnICcpO1xuICBcdFx0XHR9IGVsc2Uge1xuICBcdFx0XHRcdHN0cm9rZS5kYXNoU3R5bGUgPSAnJztcbiAgXHRcdFx0fVxuICBcdFx0XHRzdHJva2UuZW5kY2FwID0gb3B0aW9ucy5saW5lQ2FwLnJlcGxhY2UoJ2J1dHQnLCAnZmxhdCcpO1xuICBcdFx0XHRzdHJva2Uuam9pbnN0eWxlID0gb3B0aW9ucy5saW5lSm9pbjtcblxuICBcdFx0fSBlbHNlIGlmIChzdHJva2UpIHtcbiAgXHRcdFx0Y29udGFpbmVyLnJlbW92ZUNoaWxkKHN0cm9rZSk7XG4gIFx0XHRcdGxheWVyLl9zdHJva2UgPSBudWxsO1xuICBcdFx0fVxuXG4gIFx0XHRpZiAob3B0aW9ucy5maWxsKSB7XG4gIFx0XHRcdGlmICghZmlsbCkge1xuICBcdFx0XHRcdGZpbGwgPSBsYXllci5fZmlsbCA9IHZtbENyZWF0ZSgnZmlsbCcpO1xuICBcdFx0XHR9XG4gIFx0XHRcdGNvbnRhaW5lci5hcHBlbmRDaGlsZChmaWxsKTtcbiAgXHRcdFx0ZmlsbC5jb2xvciA9IG9wdGlvbnMuZmlsbENvbG9yIHx8IG9wdGlvbnMuY29sb3I7XG4gIFx0XHRcdGZpbGwub3BhY2l0eSA9IG9wdGlvbnMuZmlsbE9wYWNpdHk7XG5cbiAgXHRcdH0gZWxzZSBpZiAoZmlsbCkge1xuICBcdFx0XHRjb250YWluZXIucmVtb3ZlQ2hpbGQoZmlsbCk7XG4gIFx0XHRcdGxheWVyLl9maWxsID0gbnVsbDtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZUNpcmNsZTogZnVuY3Rpb24gKGxheWVyKSB7XG4gIFx0XHR2YXIgcCA9IGxheWVyLl9wb2ludC5yb3VuZCgpLFxuICBcdFx0ICAgIHIgPSBNYXRoLnJvdW5kKGxheWVyLl9yYWRpdXMpLFxuICBcdFx0ICAgIHIyID0gTWF0aC5yb3VuZChsYXllci5fcmFkaXVzWSB8fCByKTtcblxuICBcdFx0dGhpcy5fc2V0UGF0aChsYXllciwgbGF5ZXIuX2VtcHR5KCkgPyAnTTAgMCcgOlxuICBcdFx0XHQnQUwgJyArIHAueCArICcsJyArIHAueSArICcgJyArIHIgKyAnLCcgKyByMiArICcgMCwnICsgKDY1NTM1ICogMzYwKSk7XG4gIFx0fSxcblxuICBcdF9zZXRQYXRoOiBmdW5jdGlvbiAobGF5ZXIsIHBhdGgpIHtcbiAgXHRcdGxheWVyLl9wYXRoLnYgPSBwYXRoO1xuICBcdH0sXG5cbiAgXHRfYnJpbmdUb0Zyb250OiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdHRvRnJvbnQobGF5ZXIuX2NvbnRhaW5lcik7XG4gIFx0fSxcblxuICBcdF9icmluZ1RvQmFjazogZnVuY3Rpb24gKGxheWVyKSB7XG4gIFx0XHR0b0JhY2sobGF5ZXIuX2NvbnRhaW5lcik7XG4gIFx0fVxuICB9O1xuXG4gIHZhciBjcmVhdGUgPSBCcm93c2VyLnZtbCA/IHZtbENyZWF0ZSA6IHN2Z0NyZWF0ZTtcblxuICAvKlxuICAgKiBAY2xhc3MgU1ZHXG4gICAqIEBpbmhlcml0cyBSZW5kZXJlclxuICAgKiBAYWthIEwuU1ZHXG4gICAqXG4gICAqIEFsbG93cyB2ZWN0b3IgbGF5ZXJzIHRvIGJlIGRpc3BsYXllZCB3aXRoIFtTVkddKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL1NWRykuXG4gICAqIEluaGVyaXRzIGBSZW5kZXJlcmAuXG4gICAqXG4gICAqIER1ZSB0byBbdGVjaG5pY2FsIGxpbWl0YXRpb25zXShodHRwczovL2Nhbml1c2UuY29tL3N2ZyksIFNWRyBpcyBub3RcbiAgICogYXZhaWxhYmxlIGluIGFsbCB3ZWIgYnJvd3NlcnMsIG5vdGFibHkgQW5kcm9pZCAyLnggYW5kIDMueC5cbiAgICpcbiAgICogQWx0aG91Z2ggU1ZHIGlzIG5vdCBhdmFpbGFibGUgb24gSUU3IGFuZCBJRTgsIHRoZXNlIGJyb3dzZXJzIHN1cHBvcnRcbiAgICogW1ZNTF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvVmVjdG9yX01hcmt1cF9MYW5ndWFnZSlcbiAgICogKGEgbm93IGRlcHJlY2F0ZWQgdGVjaG5vbG9neSksIGFuZCB0aGUgU1ZHIHJlbmRlcmVyIHdpbGwgZmFsbCBiYWNrIHRvIFZNTCBpblxuICAgKiB0aGlzIGNhc2UuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqIFVzZSBTVkcgYnkgZGVmYXVsdCBmb3IgYWxsIHBhdGhzIGluIHRoZSBtYXA6XG4gICAqXG4gICAqIGBgYGpzXG4gICAqIHZhciBtYXAgPSBMLm1hcCgnbWFwJywge1xuICAgKiBcdHJlbmRlcmVyOiBMLnN2ZygpXG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICpcbiAgICogVXNlIGEgU1ZHIHJlbmRlcmVyIHdpdGggZXh0cmEgcGFkZGluZyBmb3Igc3BlY2lmaWMgdmVjdG9yIGdlb21ldHJpZXM6XG4gICAqXG4gICAqIGBgYGpzXG4gICAqIHZhciBtYXAgPSBMLm1hcCgnbWFwJyk7XG4gICAqIHZhciBteVJlbmRlcmVyID0gTC5zdmcoeyBwYWRkaW5nOiAwLjUgfSk7XG4gICAqIHZhciBsaW5lID0gTC5wb2x5bGluZSggY29vcmRpbmF0ZXMsIHsgcmVuZGVyZXI6IG15UmVuZGVyZXIgfSApO1xuICAgKiB2YXIgY2lyY2xlID0gTC5jaXJjbGUoIGNlbnRlciwgeyByZW5kZXJlcjogbXlSZW5kZXJlciB9ICk7XG4gICAqIGBgYFxuICAgKi9cblxuICB2YXIgU1ZHID0gUmVuZGVyZXIuZXh0ZW5kKHtcblxuICBcdF9pbml0Q29udGFpbmVyOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR0aGlzLl9jb250YWluZXIgPSBjcmVhdGUoJ3N2ZycpO1xuXG4gIFx0XHQvLyBtYWtlcyBpdCBwb3NzaWJsZSB0byBjbGljayB0aHJvdWdoIHN2ZyByb290OyB3ZSdsbCByZXNldCBpdCBiYWNrIGluIGluZGl2aWR1YWwgcGF0aHNcbiAgXHRcdHRoaXMuX2NvbnRhaW5lci5zZXRBdHRyaWJ1dGUoJ3BvaW50ZXItZXZlbnRzJywgJ25vbmUnKTtcblxuICBcdFx0dGhpcy5fcm9vdEdyb3VwID0gY3JlYXRlKCdnJyk7XG4gIFx0XHR0aGlzLl9jb250YWluZXIuYXBwZW5kQ2hpbGQodGhpcy5fcm9vdEdyb3VwKTtcbiAgXHR9LFxuXG4gIFx0X2Rlc3Ryb3lDb250YWluZXI6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHJlbW92ZSh0aGlzLl9jb250YWluZXIpO1xuICBcdFx0b2ZmKHRoaXMuX2NvbnRhaW5lcik7XG4gIFx0XHRkZWxldGUgdGhpcy5fY29udGFpbmVyO1xuICBcdFx0ZGVsZXRlIHRoaXMuX3Jvb3RHcm91cDtcbiAgXHRcdGRlbGV0ZSB0aGlzLl9zdmdTaXplO1xuICBcdH0sXG5cbiAgXHRfdXBkYXRlOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRpZiAodGhpcy5fbWFwLl9hbmltYXRpbmdab29tICYmIHRoaXMuX2JvdW5kcykgeyByZXR1cm47IH1cblxuICBcdFx0UmVuZGVyZXIucHJvdG90eXBlLl91cGRhdGUuY2FsbCh0aGlzKTtcblxuICBcdFx0dmFyIGIgPSB0aGlzLl9ib3VuZHMsXG4gIFx0XHQgICAgc2l6ZSA9IGIuZ2V0U2l6ZSgpLFxuICBcdFx0ICAgIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRhaW5lcjtcblxuICBcdFx0Ly8gc2V0IHNpemUgb2Ygc3ZnLWNvbnRhaW5lciBpZiBjaGFuZ2VkXG4gIFx0XHRpZiAoIXRoaXMuX3N2Z1NpemUgfHwgIXRoaXMuX3N2Z1NpemUuZXF1YWxzKHNpemUpKSB7XG4gIFx0XHRcdHRoaXMuX3N2Z1NpemUgPSBzaXplO1xuICBcdFx0XHRjb250YWluZXIuc2V0QXR0cmlidXRlKCd3aWR0aCcsIHNpemUueCk7XG4gIFx0XHRcdGNvbnRhaW5lci5zZXRBdHRyaWJ1dGUoJ2hlaWdodCcsIHNpemUueSk7XG4gIFx0XHR9XG5cbiAgXHRcdC8vIG1vdmVtZW50OiB1cGRhdGUgY29udGFpbmVyIHZpZXdCb3ggc28gdGhhdCB3ZSBkb24ndCBoYXZlIHRvIGNoYW5nZSBjb29yZGluYXRlcyBvZiBpbmRpdmlkdWFsIGxheWVyc1xuICBcdFx0c2V0UG9zaXRpb24oY29udGFpbmVyLCBiLm1pbik7XG4gIFx0XHRjb250YWluZXIuc2V0QXR0cmlidXRlKCd2aWV3Qm94JywgW2IubWluLngsIGIubWluLnksIHNpemUueCwgc2l6ZS55XS5qb2luKCcgJykpO1xuXG4gIFx0XHR0aGlzLmZpcmUoJ3VwZGF0ZScpO1xuICBcdH0sXG5cbiAgXHQvLyBtZXRob2RzIGJlbG93IGFyZSBjYWxsZWQgYnkgdmVjdG9yIGxheWVycyBpbXBsZW1lbnRhdGlvbnNcblxuICBcdF9pbml0UGF0aDogZnVuY3Rpb24gKGxheWVyKSB7XG4gIFx0XHR2YXIgcGF0aCA9IGxheWVyLl9wYXRoID0gY3JlYXRlKCdwYXRoJyk7XG5cbiAgXHRcdC8vIEBuYW1lc3BhY2UgUGF0aFxuICBcdFx0Ly8gQG9wdGlvbiBjbGFzc05hbWU6IFN0cmluZyA9IG51bGxcbiAgXHRcdC8vIEN1c3RvbSBjbGFzcyBuYW1lIHNldCBvbiBhbiBlbGVtZW50LiBPbmx5IGZvciBTVkcgcmVuZGVyZXIuXG4gIFx0XHRpZiAobGF5ZXIub3B0aW9ucy5jbGFzc05hbWUpIHtcbiAgXHRcdFx0YWRkQ2xhc3MocGF0aCwgbGF5ZXIub3B0aW9ucy5jbGFzc05hbWUpO1xuICBcdFx0fVxuXG4gIFx0XHRpZiAobGF5ZXIub3B0aW9ucy5pbnRlcmFjdGl2ZSkge1xuICBcdFx0XHRhZGRDbGFzcyhwYXRoLCAnbGVhZmxldC1pbnRlcmFjdGl2ZScpO1xuICBcdFx0fVxuXG4gIFx0XHR0aGlzLl91cGRhdGVTdHlsZShsYXllcik7XG4gIFx0XHR0aGlzLl9sYXllcnNbc3RhbXAobGF5ZXIpXSA9IGxheWVyO1xuICBcdH0sXG5cbiAgXHRfYWRkUGF0aDogZnVuY3Rpb24gKGxheWVyKSB7XG4gIFx0XHRpZiAoIXRoaXMuX3Jvb3RHcm91cCkgeyB0aGlzLl9pbml0Q29udGFpbmVyKCk7IH1cbiAgXHRcdHRoaXMuX3Jvb3RHcm91cC5hcHBlbmRDaGlsZChsYXllci5fcGF0aCk7XG4gIFx0XHRsYXllci5hZGRJbnRlcmFjdGl2ZVRhcmdldChsYXllci5fcGF0aCk7XG4gIFx0fSxcblxuICBcdF9yZW1vdmVQYXRoOiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdHJlbW92ZShsYXllci5fcGF0aCk7XG4gIFx0XHRsYXllci5yZW1vdmVJbnRlcmFjdGl2ZVRhcmdldChsYXllci5fcGF0aCk7XG4gIFx0XHRkZWxldGUgdGhpcy5fbGF5ZXJzW3N0YW1wKGxheWVyKV07XG4gIFx0fSxcblxuICBcdF91cGRhdGVQYXRoOiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdGxheWVyLl9wcm9qZWN0KCk7XG4gIFx0XHRsYXllci5fdXBkYXRlKCk7XG4gIFx0fSxcblxuICBcdF91cGRhdGVTdHlsZTogZnVuY3Rpb24gKGxheWVyKSB7XG4gIFx0XHR2YXIgcGF0aCA9IGxheWVyLl9wYXRoLFxuICBcdFx0ICAgIG9wdGlvbnMgPSBsYXllci5vcHRpb25zO1xuXG4gIFx0XHRpZiAoIXBhdGgpIHsgcmV0dXJuOyB9XG5cbiAgXHRcdGlmIChvcHRpb25zLnN0cm9rZSkge1xuICBcdFx0XHRwYXRoLnNldEF0dHJpYnV0ZSgnc3Ryb2tlJywgb3B0aW9ucy5jb2xvcik7XG4gIFx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2Utb3BhY2l0eScsIG9wdGlvbnMub3BhY2l0eSk7XG4gIFx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2Utd2lkdGgnLCBvcHRpb25zLndlaWdodCk7XG4gIFx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2UtbGluZWNhcCcsIG9wdGlvbnMubGluZUNhcCk7XG4gIFx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2UtbGluZWpvaW4nLCBvcHRpb25zLmxpbmVKb2luKTtcblxuICBcdFx0XHRpZiAob3B0aW9ucy5kYXNoQXJyYXkpIHtcbiAgXHRcdFx0XHRwYXRoLnNldEF0dHJpYnV0ZSgnc3Ryb2tlLWRhc2hhcnJheScsIG9wdGlvbnMuZGFzaEFycmF5KTtcbiAgXHRcdFx0fSBlbHNlIHtcbiAgXHRcdFx0XHRwYXRoLnJlbW92ZUF0dHJpYnV0ZSgnc3Ryb2tlLWRhc2hhcnJheScpO1xuICBcdFx0XHR9XG5cbiAgXHRcdFx0aWYgKG9wdGlvbnMuZGFzaE9mZnNldCkge1xuICBcdFx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2UtZGFzaG9mZnNldCcsIG9wdGlvbnMuZGFzaE9mZnNldCk7XG4gIFx0XHRcdH0gZWxzZSB7XG4gIFx0XHRcdFx0cGF0aC5yZW1vdmVBdHRyaWJ1dGUoJ3N0cm9rZS1kYXNob2Zmc2V0Jyk7XG4gIFx0XHRcdH1cbiAgXHRcdH0gZWxzZSB7XG4gIFx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2UnLCAnbm9uZScpO1xuICBcdFx0fVxuXG4gIFx0XHRpZiAob3B0aW9ucy5maWxsKSB7XG4gIFx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdmaWxsJywgb3B0aW9ucy5maWxsQ29sb3IgfHwgb3B0aW9ucy5jb2xvcik7XG4gIFx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdmaWxsLW9wYWNpdHknLCBvcHRpb25zLmZpbGxPcGFjaXR5KTtcbiAgXHRcdFx0cGF0aC5zZXRBdHRyaWJ1dGUoJ2ZpbGwtcnVsZScsIG9wdGlvbnMuZmlsbFJ1bGUgfHwgJ2V2ZW5vZGQnKTtcbiAgXHRcdH0gZWxzZSB7XG4gIFx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdmaWxsJywgJ25vbmUnKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZVBvbHk6IGZ1bmN0aW9uIChsYXllciwgY2xvc2VkKSB7XG4gIFx0XHR0aGlzLl9zZXRQYXRoKGxheWVyLCBwb2ludHNUb1BhdGgobGF5ZXIuX3BhcnRzLCBjbG9zZWQpKTtcbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZUNpcmNsZTogZnVuY3Rpb24gKGxheWVyKSB7XG4gIFx0XHR2YXIgcCA9IGxheWVyLl9wb2ludCxcbiAgXHRcdCAgICByID0gTWF0aC5tYXgoTWF0aC5yb3VuZChsYXllci5fcmFkaXVzKSwgMSksXG4gIFx0XHQgICAgcjIgPSBNYXRoLm1heChNYXRoLnJvdW5kKGxheWVyLl9yYWRpdXNZKSwgMSkgfHwgcixcbiAgXHRcdCAgICBhcmMgPSAnYScgKyByICsgJywnICsgcjIgKyAnIDAgMSwwICc7XG5cbiAgXHRcdC8vIGRyYXdpbmcgYSBjaXJjbGUgd2l0aCB0d28gaGFsZi1hcmNzXG4gIFx0XHR2YXIgZCA9IGxheWVyLl9lbXB0eSgpID8gJ00wIDAnIDpcbiAgXHRcdFx0J00nICsgKHAueCAtIHIpICsgJywnICsgcC55ICtcbiAgXHRcdFx0YXJjICsgKHIgKiAyKSArICcsMCAnICtcbiAgXHRcdFx0YXJjICsgKC1yICogMikgKyAnLDAgJztcblxuICBcdFx0dGhpcy5fc2V0UGF0aChsYXllciwgZCk7XG4gIFx0fSxcblxuICBcdF9zZXRQYXRoOiBmdW5jdGlvbiAobGF5ZXIsIHBhdGgpIHtcbiAgXHRcdGxheWVyLl9wYXRoLnNldEF0dHJpYnV0ZSgnZCcsIHBhdGgpO1xuICBcdH0sXG5cbiAgXHQvLyBTVkcgZG9lcyBub3QgaGF2ZSB0aGUgY29uY2VwdCBvZiB6SW5kZXggc28gd2UgcmVzb3J0IHRvIGNoYW5naW5nIHRoZSBET00gb3JkZXIgb2YgZWxlbWVudHNcbiAgXHRfYnJpbmdUb0Zyb250OiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdHRvRnJvbnQobGF5ZXIuX3BhdGgpO1xuICBcdH0sXG5cbiAgXHRfYnJpbmdUb0JhY2s6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0dG9CYWNrKGxheWVyLl9wYXRoKTtcbiAgXHR9XG4gIH0pO1xuXG4gIGlmIChCcm93c2VyLnZtbCkge1xuICBcdFNWRy5pbmNsdWRlKHZtbE1peGluKTtcbiAgfVxuXG4gIC8vIEBuYW1lc3BhY2UgU1ZHXG4gIC8vIEBmYWN0b3J5IEwuc3ZnKG9wdGlvbnM/OiBSZW5kZXJlciBvcHRpb25zKVxuICAvLyBDcmVhdGVzIGEgU1ZHIHJlbmRlcmVyIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuXG4gIGZ1bmN0aW9uIHN2ZyhvcHRpb25zKSB7XG4gIFx0cmV0dXJuIEJyb3dzZXIuc3ZnIHx8IEJyb3dzZXIudm1sID8gbmV3IFNWRyhvcHRpb25zKSA6IG51bGw7XG4gIH1cblxuICBNYXAuaW5jbHVkZSh7XG4gIFx0Ly8gQG5hbWVzcGFjZSBNYXA7IEBtZXRob2QgZ2V0UmVuZGVyZXIobGF5ZXI6IFBhdGgpOiBSZW5kZXJlclxuICBcdC8vIFJldHVybnMgdGhlIGluc3RhbmNlIG9mIGBSZW5kZXJlcmAgdGhhdCBzaG91bGQgYmUgdXNlZCB0byByZW5kZXIgdGhlIGdpdmVuXG4gIFx0Ly8gYFBhdGhgLiBJdCB3aWxsIGVuc3VyZSB0aGF0IHRoZSBgcmVuZGVyZXJgIG9wdGlvbnMgb2YgdGhlIG1hcCBhbmQgcGF0aHNcbiAgXHQvLyBhcmUgcmVzcGVjdGVkLCBhbmQgdGhhdCB0aGUgcmVuZGVyZXJzIGRvIGV4aXN0IG9uIHRoZSBtYXAuXG4gIFx0Z2V0UmVuZGVyZXI6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0Ly8gQG5hbWVzcGFjZSBQYXRoOyBAb3B0aW9uIHJlbmRlcmVyOiBSZW5kZXJlclxuICBcdFx0Ly8gVXNlIHRoaXMgc3BlY2lmaWMgaW5zdGFuY2Ugb2YgYFJlbmRlcmVyYCBmb3IgdGhpcyBwYXRoLiBUYWtlc1xuICBcdFx0Ly8gcHJlY2VkZW5jZSBvdmVyIHRoZSBtYXAncyBbZGVmYXVsdCByZW5kZXJlcl0oI21hcC1yZW5kZXJlcikuXG4gIFx0XHR2YXIgcmVuZGVyZXIgPSBsYXllci5vcHRpb25zLnJlbmRlcmVyIHx8IHRoaXMuX2dldFBhbmVSZW5kZXJlcihsYXllci5vcHRpb25zLnBhbmUpIHx8IHRoaXMub3B0aW9ucy5yZW5kZXJlciB8fCB0aGlzLl9yZW5kZXJlcjtcblxuICBcdFx0aWYgKCFyZW5kZXJlcikge1xuICBcdFx0XHRyZW5kZXJlciA9IHRoaXMuX3JlbmRlcmVyID0gdGhpcy5fY3JlYXRlUmVuZGVyZXIoKTtcbiAgXHRcdH1cblxuICBcdFx0aWYgKCF0aGlzLmhhc0xheWVyKHJlbmRlcmVyKSkge1xuICBcdFx0XHR0aGlzLmFkZExheWVyKHJlbmRlcmVyKTtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiByZW5kZXJlcjtcbiAgXHR9LFxuXG4gIFx0X2dldFBhbmVSZW5kZXJlcjogZnVuY3Rpb24gKG5hbWUpIHtcbiAgXHRcdGlmIChuYW1lID09PSAnb3ZlcmxheVBhbmUnIHx8IG5hbWUgPT09IHVuZGVmaW5lZCkge1xuICBcdFx0XHRyZXR1cm4gZmFsc2U7XG4gIFx0XHR9XG5cbiAgXHRcdHZhciByZW5kZXJlciA9IHRoaXMuX3BhbmVSZW5kZXJlcnNbbmFtZV07XG4gIFx0XHRpZiAocmVuZGVyZXIgPT09IHVuZGVmaW5lZCkge1xuICBcdFx0XHRyZW5kZXJlciA9IHRoaXMuX2NyZWF0ZVJlbmRlcmVyKHtwYW5lOiBuYW1lfSk7XG4gIFx0XHRcdHRoaXMuX3BhbmVSZW5kZXJlcnNbbmFtZV0gPSByZW5kZXJlcjtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiByZW5kZXJlcjtcbiAgXHR9LFxuXG4gIFx0X2NyZWF0ZVJlbmRlcmVyOiBmdW5jdGlvbiAob3B0aW9ucykge1xuICBcdFx0Ly8gQG5hbWVzcGFjZSBNYXA7IEBvcHRpb24gcHJlZmVyQ2FudmFzOiBCb29sZWFuID0gZmFsc2VcbiAgXHRcdC8vIFdoZXRoZXIgYFBhdGhgcyBzaG91bGQgYmUgcmVuZGVyZWQgb24gYSBgQ2FudmFzYCByZW5kZXJlci5cbiAgXHRcdC8vIEJ5IGRlZmF1bHQsIGFsbCBgUGF0aGBzIGFyZSByZW5kZXJlZCBpbiBhIGBTVkdgIHJlbmRlcmVyLlxuICBcdFx0cmV0dXJuICh0aGlzLm9wdGlvbnMucHJlZmVyQ2FudmFzICYmIGNhbnZhcyhvcHRpb25zKSkgfHwgc3ZnKG9wdGlvbnMpO1xuICBcdH1cbiAgfSk7XG5cbiAgLypcbiAgICogTC5SZWN0YW5nbGUgZXh0ZW5kcyBQb2x5Z29uIGFuZCBjcmVhdGVzIGEgcmVjdGFuZ2xlIHdoZW4gcGFzc2VkIGEgTGF0TG5nQm91bmRzIG9iamVjdC5cbiAgICovXG5cbiAgLypcbiAgICogQGNsYXNzIFJlY3RhbmdsZVxuICAgKiBAYWthIEwuUmVjdGFuZ2xlXG4gICAqIEBpbmhlcml0cyBQb2x5Z29uXG4gICAqXG4gICAqIEEgY2xhc3MgZm9yIGRyYXdpbmcgcmVjdGFuZ2xlIG92ZXJsYXlzIG9uIGEgbWFwLiBFeHRlbmRzIGBQb2x5Z29uYC5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICpcbiAgICogYGBganNcbiAgICogLy8gZGVmaW5lIHJlY3RhbmdsZSBnZW9ncmFwaGljYWwgYm91bmRzXG4gICAqIHZhciBib3VuZHMgPSBbWzU0LjU1OTMyMiwgLTUuNzY3ODIyXSwgWzU2LjEyMTA2MDQsIC0zLjAyMTI0MF1dO1xuICAgKlxuICAgKiAvLyBjcmVhdGUgYW4gb3JhbmdlIHJlY3RhbmdsZVxuICAgKiBMLnJlY3RhbmdsZShib3VuZHMsIHtjb2xvcjogXCIjZmY3ODAwXCIsIHdlaWdodDogMX0pLmFkZFRvKG1hcCk7XG4gICAqXG4gICAqIC8vIHpvb20gdGhlIG1hcCB0byB0aGUgcmVjdGFuZ2xlIGJvdW5kc1xuICAgKiBtYXAuZml0Qm91bmRzKGJvdW5kcyk7XG4gICAqIGBgYFxuICAgKlxuICAgKi9cblxuXG4gIHZhciBSZWN0YW5nbGUgPSBQb2x5Z29uLmV4dGVuZCh7XG4gIFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKGxhdExuZ0JvdW5kcywgb3B0aW9ucykge1xuICBcdFx0UG9seWdvbi5wcm90b3R5cGUuaW5pdGlhbGl6ZS5jYWxsKHRoaXMsIHRoaXMuX2JvdW5kc1RvTGF0TG5ncyhsYXRMbmdCb3VuZHMpLCBvcHRpb25zKTtcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBzZXRCb3VuZHMobGF0TG5nQm91bmRzOiBMYXRMbmdCb3VuZHMpOiB0aGlzXG4gIFx0Ly8gUmVkcmF3cyB0aGUgcmVjdGFuZ2xlIHdpdGggdGhlIHBhc3NlZCBib3VuZHMuXG4gIFx0c2V0Qm91bmRzOiBmdW5jdGlvbiAobGF0TG5nQm91bmRzKSB7XG4gIFx0XHRyZXR1cm4gdGhpcy5zZXRMYXRMbmdzKHRoaXMuX2JvdW5kc1RvTGF0TG5ncyhsYXRMbmdCb3VuZHMpKTtcbiAgXHR9LFxuXG4gIFx0X2JvdW5kc1RvTGF0TG5nczogZnVuY3Rpb24gKGxhdExuZ0JvdW5kcykge1xuICBcdFx0bGF0TG5nQm91bmRzID0gdG9MYXRMbmdCb3VuZHMobGF0TG5nQm91bmRzKTtcbiAgXHRcdHJldHVybiBbXG4gIFx0XHRcdGxhdExuZ0JvdW5kcy5nZXRTb3V0aFdlc3QoKSxcbiAgXHRcdFx0bGF0TG5nQm91bmRzLmdldE5vcnRoV2VzdCgpLFxuICBcdFx0XHRsYXRMbmdCb3VuZHMuZ2V0Tm9ydGhFYXN0KCksXG4gIFx0XHRcdGxhdExuZ0JvdW5kcy5nZXRTb3V0aEVhc3QoKVxuICBcdFx0XTtcbiAgXHR9XG4gIH0pO1xuXG5cbiAgLy8gQGZhY3RvcnkgTC5yZWN0YW5nbGUobGF0TG5nQm91bmRzOiBMYXRMbmdCb3VuZHMsIG9wdGlvbnM/OiBQb2x5bGluZSBvcHRpb25zKVxuICBmdW5jdGlvbiByZWN0YW5nbGUobGF0TG5nQm91bmRzLCBvcHRpb25zKSB7XG4gIFx0cmV0dXJuIG5ldyBSZWN0YW5nbGUobGF0TG5nQm91bmRzLCBvcHRpb25zKTtcbiAgfVxuXG4gIFNWRy5jcmVhdGUgPSBjcmVhdGU7XG4gIFNWRy5wb2ludHNUb1BhdGggPSBwb2ludHNUb1BhdGg7XG5cbiAgR2VvSlNPTi5nZW9tZXRyeVRvTGF5ZXIgPSBnZW9tZXRyeVRvTGF5ZXI7XG4gIEdlb0pTT04uY29vcmRzVG9MYXRMbmcgPSBjb29yZHNUb0xhdExuZztcbiAgR2VvSlNPTi5jb29yZHNUb0xhdExuZ3MgPSBjb29yZHNUb0xhdExuZ3M7XG4gIEdlb0pTT04ubGF0TG5nVG9Db29yZHMgPSBsYXRMbmdUb0Nvb3JkcztcbiAgR2VvSlNPTi5sYXRMbmdzVG9Db29yZHMgPSBsYXRMbmdzVG9Db29yZHM7XG4gIEdlb0pTT04uZ2V0RmVhdHVyZSA9IGdldEZlYXR1cmU7XG4gIEdlb0pTT04uYXNGZWF0dXJlID0gYXNGZWF0dXJlO1xuXG4gIC8qXG4gICAqIEwuSGFuZGxlci5Cb3hab29tIGlzIHVzZWQgdG8gYWRkIHNoaWZ0LWRyYWcgem9vbSBpbnRlcmFjdGlvbiB0byB0aGUgbWFwXG4gICAqICh6b29tIHRvIGEgc2VsZWN0ZWQgYm91bmRpbmcgYm94KSwgZW5hYmxlZCBieSBkZWZhdWx0LlxuICAgKi9cblxuICAvLyBAbmFtZXNwYWNlIE1hcFxuICAvLyBAc2VjdGlvbiBJbnRlcmFjdGlvbiBPcHRpb25zXG4gIE1hcC5tZXJnZU9wdGlvbnMoe1xuICBcdC8vIEBvcHRpb24gYm94Wm9vbTogQm9vbGVhbiA9IHRydWVcbiAgXHQvLyBXaGV0aGVyIHRoZSBtYXAgY2FuIGJlIHpvb21lZCB0byBhIHJlY3Rhbmd1bGFyIGFyZWEgc3BlY2lmaWVkIGJ5XG4gIFx0Ly8gZHJhZ2dpbmcgdGhlIG1vdXNlIHdoaWxlIHByZXNzaW5nIHRoZSBzaGlmdCBrZXkuXG4gIFx0Ym94Wm9vbTogdHJ1ZVxuICB9KTtcblxuICB2YXIgQm94Wm9vbSA9IEhhbmRsZXIuZXh0ZW5kKHtcbiAgXHRpbml0aWFsaXplOiBmdW5jdGlvbiAobWFwKSB7XG4gIFx0XHR0aGlzLl9tYXAgPSBtYXA7XG4gIFx0XHR0aGlzLl9jb250YWluZXIgPSBtYXAuX2NvbnRhaW5lcjtcbiAgXHRcdHRoaXMuX3BhbmUgPSBtYXAuX3BhbmVzLm92ZXJsYXlQYW5lO1xuICBcdFx0dGhpcy5fcmVzZXRTdGF0ZVRpbWVvdXQgPSAwO1xuICBcdFx0bWFwLm9uKCd1bmxvYWQnLCB0aGlzLl9kZXN0cm95LCB0aGlzKTtcbiAgXHR9LFxuXG4gIFx0YWRkSG9va3M6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdG9uKHRoaXMuX2NvbnRhaW5lciwgJ21vdXNlZG93bicsIHRoaXMuX29uTW91c2VEb3duLCB0aGlzKTtcbiAgXHR9LFxuXG4gIFx0cmVtb3ZlSG9va3M6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdG9mZih0aGlzLl9jb250YWluZXIsICdtb3VzZWRvd24nLCB0aGlzLl9vbk1vdXNlRG93biwgdGhpcyk7XG4gIFx0fSxcblxuICBcdG1vdmVkOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZXR1cm4gdGhpcy5fbW92ZWQ7XG4gIFx0fSxcblxuICBcdF9kZXN0cm95OiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZW1vdmUodGhpcy5fcGFuZSk7XG4gIFx0XHRkZWxldGUgdGhpcy5fcGFuZTtcbiAgXHR9LFxuXG4gIFx0X3Jlc2V0U3RhdGU6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHRoaXMuX3Jlc2V0U3RhdGVUaW1lb3V0ID0gMDtcbiAgXHRcdHRoaXMuX21vdmVkID0gZmFsc2U7XG4gIFx0fSxcblxuICBcdF9jbGVhckRlZmVycmVkUmVzZXRTdGF0ZTogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKHRoaXMuX3Jlc2V0U3RhdGVUaW1lb3V0ICE9PSAwKSB7XG4gIFx0XHRcdGNsZWFyVGltZW91dCh0aGlzLl9yZXNldFN0YXRlVGltZW91dCk7XG4gIFx0XHRcdHRoaXMuX3Jlc2V0U3RhdGVUaW1lb3V0ID0gMDtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X29uTW91c2VEb3duOiBmdW5jdGlvbiAoZSkge1xuICBcdFx0aWYgKCFlLnNoaWZ0S2V5IHx8ICgoZS53aGljaCAhPT0gMSkgJiYgKGUuYnV0dG9uICE9PSAxKSkpIHsgcmV0dXJuIGZhbHNlOyB9XG5cbiAgXHRcdC8vIENsZWFyIHRoZSBkZWZlcnJlZCByZXNldFN0YXRlIGlmIGl0IGhhc24ndCBleGVjdXRlZCB5ZXQsIG90aGVyd2lzZSBpdFxuICBcdFx0Ly8gd2lsbCBpbnRlcnJ1cHQgdGhlIGludGVyYWN0aW9uIGFuZCBvcnBoYW4gYSBib3ggZWxlbWVudCBpbiB0aGUgY29udGFpbmVyLlxuICBcdFx0dGhpcy5fY2xlYXJEZWZlcnJlZFJlc2V0U3RhdGUoKTtcbiAgXHRcdHRoaXMuX3Jlc2V0U3RhdGUoKTtcblxuICBcdFx0ZGlzYWJsZVRleHRTZWxlY3Rpb24oKTtcbiAgXHRcdGRpc2FibGVJbWFnZURyYWcoKTtcblxuICBcdFx0dGhpcy5fc3RhcnRQb2ludCA9IHRoaXMuX21hcC5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlKTtcblxuICBcdFx0b24oZG9jdW1lbnQsIHtcbiAgXHRcdFx0Y29udGV4dG1lbnU6IHN0b3AsXG4gIFx0XHRcdG1vdXNlbW92ZTogdGhpcy5fb25Nb3VzZU1vdmUsXG4gIFx0XHRcdG1vdXNldXA6IHRoaXMuX29uTW91c2VVcCxcbiAgXHRcdFx0a2V5ZG93bjogdGhpcy5fb25LZXlEb3duXG4gIFx0XHR9LCB0aGlzKTtcbiAgXHR9LFxuXG4gIFx0X29uTW91c2VNb3ZlOiBmdW5jdGlvbiAoZSkge1xuICBcdFx0aWYgKCF0aGlzLl9tb3ZlZCkge1xuICBcdFx0XHR0aGlzLl9tb3ZlZCA9IHRydWU7XG5cbiAgXHRcdFx0dGhpcy5fYm94ID0gY3JlYXRlJDEoJ2RpdicsICdsZWFmbGV0LXpvb20tYm94JywgdGhpcy5fY29udGFpbmVyKTtcbiAgXHRcdFx0YWRkQ2xhc3ModGhpcy5fY29udGFpbmVyLCAnbGVhZmxldC1jcm9zc2hhaXInKTtcblxuICBcdFx0XHR0aGlzLl9tYXAuZmlyZSgnYm94em9vbXN0YXJ0Jyk7XG4gIFx0XHR9XG5cbiAgXHRcdHRoaXMuX3BvaW50ID0gdGhpcy5fbWFwLm1vdXNlRXZlbnRUb0NvbnRhaW5lclBvaW50KGUpO1xuXG4gIFx0XHR2YXIgYm91bmRzID0gbmV3IEJvdW5kcyh0aGlzLl9wb2ludCwgdGhpcy5fc3RhcnRQb2ludCksXG4gIFx0XHQgICAgc2l6ZSA9IGJvdW5kcy5nZXRTaXplKCk7XG5cbiAgXHRcdHNldFBvc2l0aW9uKHRoaXMuX2JveCwgYm91bmRzLm1pbik7XG5cbiAgXHRcdHRoaXMuX2JveC5zdHlsZS53aWR0aCAgPSBzaXplLnggKyAncHgnO1xuICBcdFx0dGhpcy5fYm94LnN0eWxlLmhlaWdodCA9IHNpemUueSArICdweCc7XG4gIFx0fSxcblxuICBcdF9maW5pc2g6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICh0aGlzLl9tb3ZlZCkge1xuICBcdFx0XHRyZW1vdmUodGhpcy5fYm94KTtcbiAgXHRcdFx0cmVtb3ZlQ2xhc3ModGhpcy5fY29udGFpbmVyLCAnbGVhZmxldC1jcm9zc2hhaXInKTtcbiAgXHRcdH1cblxuICBcdFx0ZW5hYmxlVGV4dFNlbGVjdGlvbigpO1xuICBcdFx0ZW5hYmxlSW1hZ2VEcmFnKCk7XG5cbiAgXHRcdG9mZihkb2N1bWVudCwge1xuICBcdFx0XHRjb250ZXh0bWVudTogc3RvcCxcbiAgXHRcdFx0bW91c2Vtb3ZlOiB0aGlzLl9vbk1vdXNlTW92ZSxcbiAgXHRcdFx0bW91c2V1cDogdGhpcy5fb25Nb3VzZVVwLFxuICBcdFx0XHRrZXlkb3duOiB0aGlzLl9vbktleURvd25cbiAgXHRcdH0sIHRoaXMpO1xuICBcdH0sXG5cbiAgXHRfb25Nb3VzZVVwOiBmdW5jdGlvbiAoZSkge1xuICBcdFx0aWYgKChlLndoaWNoICE9PSAxKSAmJiAoZS5idXR0b24gIT09IDEpKSB7IHJldHVybjsgfVxuXG4gIFx0XHR0aGlzLl9maW5pc2goKTtcblxuICBcdFx0aWYgKCF0aGlzLl9tb3ZlZCkgeyByZXR1cm47IH1cbiAgXHRcdC8vIFBvc3Rwb25lIHRvIG5leHQgSlMgdGljayBzbyBpbnRlcm5hbCBjbGljayBldmVudCBoYW5kbGluZ1xuICBcdFx0Ly8gc3RpbGwgc2VlIGl0IGFzIFwibW92ZWRcIi5cbiAgXHRcdHRoaXMuX2NsZWFyRGVmZXJyZWRSZXNldFN0YXRlKCk7XG4gIFx0XHR0aGlzLl9yZXNldFN0YXRlVGltZW91dCA9IHNldFRpbWVvdXQoYmluZCh0aGlzLl9yZXNldFN0YXRlLCB0aGlzKSwgMCk7XG5cbiAgXHRcdHZhciBib3VuZHMgPSBuZXcgTGF0TG5nQm91bmRzKFxuICBcdFx0ICAgICAgICB0aGlzLl9tYXAuY29udGFpbmVyUG9pbnRUb0xhdExuZyh0aGlzLl9zdGFydFBvaW50KSxcbiAgXHRcdCAgICAgICAgdGhpcy5fbWFwLmNvbnRhaW5lclBvaW50VG9MYXRMbmcodGhpcy5fcG9pbnQpKTtcblxuICBcdFx0dGhpcy5fbWFwXG4gIFx0XHRcdC5maXRCb3VuZHMoYm91bmRzKVxuICBcdFx0XHQuZmlyZSgnYm94em9vbWVuZCcsIHtib3hab29tQm91bmRzOiBib3VuZHN9KTtcbiAgXHR9LFxuXG4gIFx0X29uS2V5RG93bjogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdGlmIChlLmtleUNvZGUgPT09IDI3KSB7XG4gIFx0XHRcdHRoaXMuX2ZpbmlzaCgpO1xuICBcdFx0XHR0aGlzLl9jbGVhckRlZmVycmVkUmVzZXRTdGF0ZSgpO1xuICBcdFx0XHR0aGlzLl9yZXNldFN0YXRlKCk7XG4gIFx0XHR9XG4gIFx0fVxuICB9KTtcblxuICAvLyBAc2VjdGlvbiBIYW5kbGVyc1xuICAvLyBAcHJvcGVydHkgYm94Wm9vbTogSGFuZGxlclxuICAvLyBCb3ggKHNoaWZ0LWRyYWcgd2l0aCBtb3VzZSkgem9vbSBoYW5kbGVyLlxuICBNYXAuYWRkSW5pdEhvb2soJ2FkZEhhbmRsZXInLCAnYm94Wm9vbScsIEJveFpvb20pO1xuXG4gIC8qXG4gICAqIEwuSGFuZGxlci5Eb3VibGVDbGlja1pvb20gaXMgdXNlZCB0byBoYW5kbGUgZG91YmxlLWNsaWNrIHpvb20gb24gdGhlIG1hcCwgZW5hYmxlZCBieSBkZWZhdWx0LlxuICAgKi9cblxuICAvLyBAbmFtZXNwYWNlIE1hcFxuICAvLyBAc2VjdGlvbiBJbnRlcmFjdGlvbiBPcHRpb25zXG5cbiAgTWFwLm1lcmdlT3B0aW9ucyh7XG4gIFx0Ly8gQG9wdGlvbiBkb3VibGVDbGlja1pvb206IEJvb2xlYW58U3RyaW5nID0gdHJ1ZVxuICBcdC8vIFdoZXRoZXIgdGhlIG1hcCBjYW4gYmUgem9vbWVkIGluIGJ5IGRvdWJsZSBjbGlja2luZyBvbiBpdCBhbmRcbiAgXHQvLyB6b29tZWQgb3V0IGJ5IGRvdWJsZSBjbGlja2luZyB3aGlsZSBob2xkaW5nIHNoaWZ0LiBJZiBwYXNzZWRcbiAgXHQvLyBgJ2NlbnRlcidgLCBkb3VibGUtY2xpY2sgem9vbSB3aWxsIHpvb20gdG8gdGhlIGNlbnRlciBvZiB0aGVcbiAgXHQvLyAgdmlldyByZWdhcmRsZXNzIG9mIHdoZXJlIHRoZSBtb3VzZSB3YXMuXG4gIFx0ZG91YmxlQ2xpY2tab29tOiB0cnVlXG4gIH0pO1xuXG4gIHZhciBEb3VibGVDbGlja1pvb20gPSBIYW5kbGVyLmV4dGVuZCh7XG4gIFx0YWRkSG9va3M6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHRoaXMuX21hcC5vbignZGJsY2xpY2snLCB0aGlzLl9vbkRvdWJsZUNsaWNrLCB0aGlzKTtcbiAgXHR9LFxuXG4gIFx0cmVtb3ZlSG9va3M6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHRoaXMuX21hcC5vZmYoJ2RibGNsaWNrJywgdGhpcy5fb25Eb3VibGVDbGljaywgdGhpcyk7XG4gIFx0fSxcblxuICBcdF9vbkRvdWJsZUNsaWNrOiBmdW5jdGlvbiAoZSkge1xuICBcdFx0dmFyIG1hcCA9IHRoaXMuX21hcCxcbiAgXHRcdCAgICBvbGRab29tID0gbWFwLmdldFpvb20oKSxcbiAgXHRcdCAgICBkZWx0YSA9IG1hcC5vcHRpb25zLnpvb21EZWx0YSxcbiAgXHRcdCAgICB6b29tID0gZS5vcmlnaW5hbEV2ZW50LnNoaWZ0S2V5ID8gb2xkWm9vbSAtIGRlbHRhIDogb2xkWm9vbSArIGRlbHRhO1xuXG4gIFx0XHRpZiAobWFwLm9wdGlvbnMuZG91YmxlQ2xpY2tab29tID09PSAnY2VudGVyJykge1xuICBcdFx0XHRtYXAuc2V0Wm9vbSh6b29tKTtcbiAgXHRcdH0gZWxzZSB7XG4gIFx0XHRcdG1hcC5zZXRab29tQXJvdW5kKGUuY29udGFpbmVyUG9pbnQsIHpvb20pO1xuICBcdFx0fVxuICBcdH1cbiAgfSk7XG5cbiAgLy8gQHNlY3Rpb24gSGFuZGxlcnNcbiAgLy9cbiAgLy8gTWFwIHByb3BlcnRpZXMgaW5jbHVkZSBpbnRlcmFjdGlvbiBoYW5kbGVycyB0aGF0IGFsbG93IHlvdSB0byBjb250cm9sXG4gIC8vIGludGVyYWN0aW9uIGJlaGF2aW9yIGluIHJ1bnRpbWUsIGVuYWJsaW5nIG9yIGRpc2FibGluZyBjZXJ0YWluIGZlYXR1cmVzIHN1Y2hcbiAgLy8gYXMgZHJhZ2dpbmcgb3IgdG91Y2ggem9vbSAoc2VlIGBIYW5kbGVyYCBtZXRob2RzKS4gRm9yIGV4YW1wbGU6XG4gIC8vXG4gIC8vIGBgYGpzXG4gIC8vIG1hcC5kb3VibGVDbGlja1pvb20uZGlzYWJsZSgpO1xuICAvLyBgYGBcbiAgLy9cbiAgLy8gQHByb3BlcnR5IGRvdWJsZUNsaWNrWm9vbTogSGFuZGxlclxuICAvLyBEb3VibGUgY2xpY2sgem9vbSBoYW5kbGVyLlxuICBNYXAuYWRkSW5pdEhvb2soJ2FkZEhhbmRsZXInLCAnZG91YmxlQ2xpY2tab29tJywgRG91YmxlQ2xpY2tab29tKTtcblxuICAvKlxuICAgKiBMLkhhbmRsZXIuTWFwRHJhZyBpcyB1c2VkIHRvIG1ha2UgdGhlIG1hcCBkcmFnZ2FibGUgKHdpdGggcGFubmluZyBpbmVydGlhKSwgZW5hYmxlZCBieSBkZWZhdWx0LlxuICAgKi9cblxuICAvLyBAbmFtZXNwYWNlIE1hcFxuICAvLyBAc2VjdGlvbiBJbnRlcmFjdGlvbiBPcHRpb25zXG4gIE1hcC5tZXJnZU9wdGlvbnMoe1xuICBcdC8vIEBvcHRpb24gZHJhZ2dpbmc6IEJvb2xlYW4gPSB0cnVlXG4gIFx0Ly8gV2hldGhlciB0aGUgbWFwIGlzIGRyYWdnYWJsZSB3aXRoIG1vdXNlL3RvdWNoIG9yIG5vdC5cbiAgXHRkcmFnZ2luZzogdHJ1ZSxcblxuICBcdC8vIEBzZWN0aW9uIFBhbm5pbmcgSW5lcnRpYSBPcHRpb25zXG4gIFx0Ly8gQG9wdGlvbiBpbmVydGlhOiBCb29sZWFuID0gKlxuICBcdC8vIElmIGVuYWJsZWQsIHBhbm5pbmcgb2YgdGhlIG1hcCB3aWxsIGhhdmUgYW4gaW5lcnRpYSBlZmZlY3Qgd2hlcmVcbiAgXHQvLyB0aGUgbWFwIGJ1aWxkcyBtb21lbnR1bSB3aGlsZSBkcmFnZ2luZyBhbmQgY29udGludWVzIG1vdmluZyBpblxuICBcdC8vIHRoZSBzYW1lIGRpcmVjdGlvbiBmb3Igc29tZSB0aW1lLiBGZWVscyBlc3BlY2lhbGx5IG5pY2Ugb24gdG91Y2hcbiAgXHQvLyBkZXZpY2VzLiBFbmFibGVkIGJ5IGRlZmF1bHQuXG4gIFx0aW5lcnRpYTogdHJ1ZSxcblxuICBcdC8vIEBvcHRpb24gaW5lcnRpYURlY2VsZXJhdGlvbjogTnVtYmVyID0gMzAwMFxuICBcdC8vIFRoZSByYXRlIHdpdGggd2hpY2ggdGhlIGluZXJ0aWFsIG1vdmVtZW50IHNsb3dzIGRvd24sIGluIHBpeGVscy9zZWNvbmTCsi5cbiAgXHRpbmVydGlhRGVjZWxlcmF0aW9uOiAzNDAwLCAvLyBweC9zXjJcblxuICBcdC8vIEBvcHRpb24gaW5lcnRpYU1heFNwZWVkOiBOdW1iZXIgPSBJbmZpbml0eVxuICBcdC8vIE1heCBzcGVlZCBvZiB0aGUgaW5lcnRpYWwgbW92ZW1lbnQsIGluIHBpeGVscy9zZWNvbmQuXG4gIFx0aW5lcnRpYU1heFNwZWVkOiBJbmZpbml0eSwgLy8gcHgvc1xuXG4gIFx0Ly8gQG9wdGlvbiBlYXNlTGluZWFyaXR5OiBOdW1iZXIgPSAwLjJcbiAgXHRlYXNlTGluZWFyaXR5OiAwLjIsXG5cbiAgXHQvLyBUT0RPIHJlZmFjdG9yLCBtb3ZlIHRvIENSU1xuICBcdC8vIEBvcHRpb24gd29ybGRDb3B5SnVtcDogQm9vbGVhbiA9IGZhbHNlXG4gIFx0Ly8gV2l0aCB0aGlzIG9wdGlvbiBlbmFibGVkLCB0aGUgbWFwIHRyYWNrcyB3aGVuIHlvdSBwYW4gdG8gYW5vdGhlciBcImNvcHlcIlxuICBcdC8vIG9mIHRoZSB3b3JsZCBhbmQgc2VhbWxlc3NseSBqdW1wcyB0byB0aGUgb3JpZ2luYWwgb25lIHNvIHRoYXQgYWxsIG92ZXJsYXlzXG4gIFx0Ly8gbGlrZSBtYXJrZXJzIGFuZCB2ZWN0b3IgbGF5ZXJzIGFyZSBzdGlsbCB2aXNpYmxlLlxuICBcdHdvcmxkQ29weUp1bXA6IGZhbHNlLFxuXG4gIFx0Ly8gQG9wdGlvbiBtYXhCb3VuZHNWaXNjb3NpdHk6IE51bWJlciA9IDAuMFxuICBcdC8vIElmIGBtYXhCb3VuZHNgIGlzIHNldCwgdGhpcyBvcHRpb24gd2lsbCBjb250cm9sIGhvdyBzb2xpZCB0aGUgYm91bmRzXG4gIFx0Ly8gYXJlIHdoZW4gZHJhZ2dpbmcgdGhlIG1hcCBhcm91bmQuIFRoZSBkZWZhdWx0IHZhbHVlIG9mIGAwLjBgIGFsbG93cyB0aGVcbiAgXHQvLyB1c2VyIHRvIGRyYWcgb3V0c2lkZSB0aGUgYm91bmRzIGF0IG5vcm1hbCBzcGVlZCwgaGlnaGVyIHZhbHVlcyB3aWxsXG4gIFx0Ly8gc2xvdyBkb3duIG1hcCBkcmFnZ2luZyBvdXRzaWRlIGJvdW5kcywgYW5kIGAxLjBgIG1ha2VzIHRoZSBib3VuZHMgZnVsbHlcbiAgXHQvLyBzb2xpZCwgcHJldmVudGluZyB0aGUgdXNlciBmcm9tIGRyYWdnaW5nIG91dHNpZGUgdGhlIGJvdW5kcy5cbiAgXHRtYXhCb3VuZHNWaXNjb3NpdHk6IDAuMFxuICB9KTtcblxuICB2YXIgRHJhZyA9IEhhbmRsZXIuZXh0ZW5kKHtcbiAgXHRhZGRIb29rczogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKCF0aGlzLl9kcmFnZ2FibGUpIHtcbiAgXHRcdFx0dmFyIG1hcCA9IHRoaXMuX21hcDtcblxuICBcdFx0XHR0aGlzLl9kcmFnZ2FibGUgPSBuZXcgRHJhZ2dhYmxlKG1hcC5fbWFwUGFuZSwgbWFwLl9jb250YWluZXIpO1xuXG4gIFx0XHRcdHRoaXMuX2RyYWdnYWJsZS5vbih7XG4gIFx0XHRcdFx0ZHJhZ3N0YXJ0OiB0aGlzLl9vbkRyYWdTdGFydCxcbiAgXHRcdFx0XHRkcmFnOiB0aGlzLl9vbkRyYWcsXG4gIFx0XHRcdFx0ZHJhZ2VuZDogdGhpcy5fb25EcmFnRW5kXG4gIFx0XHRcdH0sIHRoaXMpO1xuXG4gIFx0XHRcdHRoaXMuX2RyYWdnYWJsZS5vbigncHJlZHJhZycsIHRoaXMuX29uUHJlRHJhZ0xpbWl0LCB0aGlzKTtcbiAgXHRcdFx0aWYgKG1hcC5vcHRpb25zLndvcmxkQ29weUp1bXApIHtcbiAgXHRcdFx0XHR0aGlzLl9kcmFnZ2FibGUub24oJ3ByZWRyYWcnLCB0aGlzLl9vblByZURyYWdXcmFwLCB0aGlzKTtcbiAgXHRcdFx0XHRtYXAub24oJ3pvb21lbmQnLCB0aGlzLl9vblpvb21FbmQsIHRoaXMpO1xuXG4gIFx0XHRcdFx0bWFwLndoZW5SZWFkeSh0aGlzLl9vblpvb21FbmQsIHRoaXMpO1xuICBcdFx0XHR9XG4gIFx0XHR9XG4gIFx0XHRhZGRDbGFzcyh0aGlzLl9tYXAuX2NvbnRhaW5lciwgJ2xlYWZsZXQtZ3JhYiBsZWFmbGV0LXRvdWNoLWRyYWcnKTtcbiAgXHRcdHRoaXMuX2RyYWdnYWJsZS5lbmFibGUoKTtcbiAgXHRcdHRoaXMuX3Bvc2l0aW9ucyA9IFtdO1xuICBcdFx0dGhpcy5fdGltZXMgPSBbXTtcbiAgXHR9LFxuXG4gIFx0cmVtb3ZlSG9va3M6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHJlbW92ZUNsYXNzKHRoaXMuX21hcC5fY29udGFpbmVyLCAnbGVhZmxldC1ncmFiJyk7XG4gIFx0XHRyZW1vdmVDbGFzcyh0aGlzLl9tYXAuX2NvbnRhaW5lciwgJ2xlYWZsZXQtdG91Y2gtZHJhZycpO1xuICBcdFx0dGhpcy5fZHJhZ2dhYmxlLmRpc2FibGUoKTtcbiAgXHR9LFxuXG4gIFx0bW92ZWQ6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHJldHVybiB0aGlzLl9kcmFnZ2FibGUgJiYgdGhpcy5fZHJhZ2dhYmxlLl9tb3ZlZDtcbiAgXHR9LFxuXG4gIFx0bW92aW5nOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZXR1cm4gdGhpcy5fZHJhZ2dhYmxlICYmIHRoaXMuX2RyYWdnYWJsZS5fbW92aW5nO1xuICBcdH0sXG5cbiAgXHRfb25EcmFnU3RhcnQ6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHZhciBtYXAgPSB0aGlzLl9tYXA7XG5cbiAgXHRcdG1hcC5fc3RvcCgpO1xuICBcdFx0aWYgKHRoaXMuX21hcC5vcHRpb25zLm1heEJvdW5kcyAmJiB0aGlzLl9tYXAub3B0aW9ucy5tYXhCb3VuZHNWaXNjb3NpdHkpIHtcbiAgXHRcdFx0dmFyIGJvdW5kcyA9IHRvTGF0TG5nQm91bmRzKHRoaXMuX21hcC5vcHRpb25zLm1heEJvdW5kcyk7XG5cbiAgXHRcdFx0dGhpcy5fb2Zmc2V0TGltaXQgPSB0b0JvdW5kcyhcbiAgXHRcdFx0XHR0aGlzLl9tYXAubGF0TG5nVG9Db250YWluZXJQb2ludChib3VuZHMuZ2V0Tm9ydGhXZXN0KCkpLm11bHRpcGx5QnkoLTEpLFxuICBcdFx0XHRcdHRoaXMuX21hcC5sYXRMbmdUb0NvbnRhaW5lclBvaW50KGJvdW5kcy5nZXRTb3V0aEVhc3QoKSkubXVsdGlwbHlCeSgtMSlcbiAgXHRcdFx0XHRcdC5hZGQodGhpcy5fbWFwLmdldFNpemUoKSkpO1xuXG4gIFx0XHRcdHRoaXMuX3Zpc2Nvc2l0eSA9IE1hdGgubWluKDEuMCwgTWF0aC5tYXgoMC4wLCB0aGlzLl9tYXAub3B0aW9ucy5tYXhCb3VuZHNWaXNjb3NpdHkpKTtcbiAgXHRcdH0gZWxzZSB7XG4gIFx0XHRcdHRoaXMuX29mZnNldExpbWl0ID0gbnVsbDtcbiAgXHRcdH1cblxuICBcdFx0bWFwXG4gIFx0XHQgICAgLmZpcmUoJ21vdmVzdGFydCcpXG4gIFx0XHQgICAgLmZpcmUoJ2RyYWdzdGFydCcpO1xuXG4gIFx0XHRpZiAobWFwLm9wdGlvbnMuaW5lcnRpYSkge1xuICBcdFx0XHR0aGlzLl9wb3NpdGlvbnMgPSBbXTtcbiAgXHRcdFx0dGhpcy5fdGltZXMgPSBbXTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X29uRHJhZzogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdGlmICh0aGlzLl9tYXAub3B0aW9ucy5pbmVydGlhKSB7XG4gIFx0XHRcdHZhciB0aW1lID0gdGhpcy5fbGFzdFRpbWUgPSArbmV3IERhdGUoKSxcbiAgXHRcdFx0ICAgIHBvcyA9IHRoaXMuX2xhc3RQb3MgPSB0aGlzLl9kcmFnZ2FibGUuX2Fic1BvcyB8fCB0aGlzLl9kcmFnZ2FibGUuX25ld1BvcztcblxuICBcdFx0XHR0aGlzLl9wb3NpdGlvbnMucHVzaChwb3MpO1xuICBcdFx0XHR0aGlzLl90aW1lcy5wdXNoKHRpbWUpO1xuXG4gIFx0XHRcdHRoaXMuX3BydW5lUG9zaXRpb25zKHRpbWUpO1xuICBcdFx0fVxuXG4gIFx0XHR0aGlzLl9tYXBcbiAgXHRcdCAgICAuZmlyZSgnbW92ZScsIGUpXG4gIFx0XHQgICAgLmZpcmUoJ2RyYWcnLCBlKTtcbiAgXHR9LFxuXG4gIFx0X3BydW5lUG9zaXRpb25zOiBmdW5jdGlvbiAodGltZSkge1xuICBcdFx0d2hpbGUgKHRoaXMuX3Bvc2l0aW9ucy5sZW5ndGggPiAxICYmIHRpbWUgLSB0aGlzLl90aW1lc1swXSA+IDUwKSB7XG4gIFx0XHRcdHRoaXMuX3Bvc2l0aW9ucy5zaGlmdCgpO1xuICBcdFx0XHR0aGlzLl90aW1lcy5zaGlmdCgpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfb25ab29tRW5kOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR2YXIgcHhDZW50ZXIgPSB0aGlzLl9tYXAuZ2V0U2l6ZSgpLmRpdmlkZUJ5KDIpLFxuICBcdFx0ICAgIHB4V29ybGRDZW50ZXIgPSB0aGlzLl9tYXAubGF0TG5nVG9MYXllclBvaW50KFswLCAwXSk7XG5cbiAgXHRcdHRoaXMuX2luaXRpYWxXb3JsZE9mZnNldCA9IHB4V29ybGRDZW50ZXIuc3VidHJhY3QocHhDZW50ZXIpLng7XG4gIFx0XHR0aGlzLl93b3JsZFdpZHRoID0gdGhpcy5fbWFwLmdldFBpeGVsV29ybGRCb3VuZHMoKS5nZXRTaXplKCkueDtcbiAgXHR9LFxuXG4gIFx0X3Zpc2NvdXNMaW1pdDogZnVuY3Rpb24gKHZhbHVlLCB0aHJlc2hvbGQpIHtcbiAgXHRcdHJldHVybiB2YWx1ZSAtICh2YWx1ZSAtIHRocmVzaG9sZCkgKiB0aGlzLl92aXNjb3NpdHk7XG4gIFx0fSxcblxuICBcdF9vblByZURyYWdMaW1pdDogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKCF0aGlzLl92aXNjb3NpdHkgfHwgIXRoaXMuX29mZnNldExpbWl0KSB7IHJldHVybjsgfVxuXG4gIFx0XHR2YXIgb2Zmc2V0ID0gdGhpcy5fZHJhZ2dhYmxlLl9uZXdQb3Muc3VidHJhY3QodGhpcy5fZHJhZ2dhYmxlLl9zdGFydFBvcyk7XG5cbiAgXHRcdHZhciBsaW1pdCA9IHRoaXMuX29mZnNldExpbWl0O1xuICBcdFx0aWYgKG9mZnNldC54IDwgbGltaXQubWluLngpIHsgb2Zmc2V0LnggPSB0aGlzLl92aXNjb3VzTGltaXQob2Zmc2V0LngsIGxpbWl0Lm1pbi54KTsgfVxuICBcdFx0aWYgKG9mZnNldC55IDwgbGltaXQubWluLnkpIHsgb2Zmc2V0LnkgPSB0aGlzLl92aXNjb3VzTGltaXQob2Zmc2V0LnksIGxpbWl0Lm1pbi55KTsgfVxuICBcdFx0aWYgKG9mZnNldC54ID4gbGltaXQubWF4LngpIHsgb2Zmc2V0LnggPSB0aGlzLl92aXNjb3VzTGltaXQob2Zmc2V0LngsIGxpbWl0Lm1heC54KTsgfVxuICBcdFx0aWYgKG9mZnNldC55ID4gbGltaXQubWF4LnkpIHsgb2Zmc2V0LnkgPSB0aGlzLl92aXNjb3VzTGltaXQob2Zmc2V0LnksIGxpbWl0Lm1heC55KTsgfVxuXG4gIFx0XHR0aGlzLl9kcmFnZ2FibGUuX25ld1BvcyA9IHRoaXMuX2RyYWdnYWJsZS5fc3RhcnRQb3MuYWRkKG9mZnNldCk7XG4gIFx0fSxcblxuICBcdF9vblByZURyYWdXcmFwOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHQvLyBUT0RPIHJlZmFjdG9yIHRvIGJlIGFibGUgdG8gYWRqdXN0IG1hcCBwYW5lIHBvc2l0aW9uIGFmdGVyIHpvb21cbiAgXHRcdHZhciB3b3JsZFdpZHRoID0gdGhpcy5fd29ybGRXaWR0aCxcbiAgXHRcdCAgICBoYWxmV2lkdGggPSBNYXRoLnJvdW5kKHdvcmxkV2lkdGggLyAyKSxcbiAgXHRcdCAgICBkeCA9IHRoaXMuX2luaXRpYWxXb3JsZE9mZnNldCxcbiAgXHRcdCAgICB4ID0gdGhpcy5fZHJhZ2dhYmxlLl9uZXdQb3MueCxcbiAgXHRcdCAgICBuZXdYMSA9ICh4IC0gaGFsZldpZHRoICsgZHgpICUgd29ybGRXaWR0aCArIGhhbGZXaWR0aCAtIGR4LFxuICBcdFx0ICAgIG5ld1gyID0gKHggKyBoYWxmV2lkdGggKyBkeCkgJSB3b3JsZFdpZHRoIC0gaGFsZldpZHRoIC0gZHgsXG4gIFx0XHQgICAgbmV3WCA9IE1hdGguYWJzKG5ld1gxICsgZHgpIDwgTWF0aC5hYnMobmV3WDIgKyBkeCkgPyBuZXdYMSA6IG5ld1gyO1xuXG4gIFx0XHR0aGlzLl9kcmFnZ2FibGUuX2Fic1BvcyA9IHRoaXMuX2RyYWdnYWJsZS5fbmV3UG9zLmNsb25lKCk7XG4gIFx0XHR0aGlzLl9kcmFnZ2FibGUuX25ld1Bvcy54ID0gbmV3WDtcbiAgXHR9LFxuXG4gIFx0X29uRHJhZ0VuZDogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdHZhciBtYXAgPSB0aGlzLl9tYXAsXG4gIFx0XHQgICAgb3B0aW9ucyA9IG1hcC5vcHRpb25zLFxuXG4gIFx0XHQgICAgbm9JbmVydGlhID0gIW9wdGlvbnMuaW5lcnRpYSB8fCBlLm5vSW5lcnRpYSB8fCB0aGlzLl90aW1lcy5sZW5ndGggPCAyO1xuXG4gIFx0XHRtYXAuZmlyZSgnZHJhZ2VuZCcsIGUpO1xuXG4gIFx0XHRpZiAobm9JbmVydGlhKSB7XG4gIFx0XHRcdG1hcC5maXJlKCdtb3ZlZW5kJyk7XG5cbiAgXHRcdH0gZWxzZSB7XG4gIFx0XHRcdHRoaXMuX3BydW5lUG9zaXRpb25zKCtuZXcgRGF0ZSgpKTtcblxuICBcdFx0XHR2YXIgZGlyZWN0aW9uID0gdGhpcy5fbGFzdFBvcy5zdWJ0cmFjdCh0aGlzLl9wb3NpdGlvbnNbMF0pLFxuICBcdFx0XHQgICAgZHVyYXRpb24gPSAodGhpcy5fbGFzdFRpbWUgLSB0aGlzLl90aW1lc1swXSkgLyAxMDAwLFxuICBcdFx0XHQgICAgZWFzZSA9IG9wdGlvbnMuZWFzZUxpbmVhcml0eSxcblxuICBcdFx0XHQgICAgc3BlZWRWZWN0b3IgPSBkaXJlY3Rpb24ubXVsdGlwbHlCeShlYXNlIC8gZHVyYXRpb24pLFxuICBcdFx0XHQgICAgc3BlZWQgPSBzcGVlZFZlY3Rvci5kaXN0YW5jZVRvKFswLCAwXSksXG5cbiAgXHRcdFx0ICAgIGxpbWl0ZWRTcGVlZCA9IE1hdGgubWluKG9wdGlvbnMuaW5lcnRpYU1heFNwZWVkLCBzcGVlZCksXG4gIFx0XHRcdCAgICBsaW1pdGVkU3BlZWRWZWN0b3IgPSBzcGVlZFZlY3Rvci5tdWx0aXBseUJ5KGxpbWl0ZWRTcGVlZCAvIHNwZWVkKSxcblxuICBcdFx0XHQgICAgZGVjZWxlcmF0aW9uRHVyYXRpb24gPSBsaW1pdGVkU3BlZWQgLyAob3B0aW9ucy5pbmVydGlhRGVjZWxlcmF0aW9uICogZWFzZSksXG4gIFx0XHRcdCAgICBvZmZzZXQgPSBsaW1pdGVkU3BlZWRWZWN0b3IubXVsdGlwbHlCeSgtZGVjZWxlcmF0aW9uRHVyYXRpb24gLyAyKS5yb3VuZCgpO1xuXG4gIFx0XHRcdGlmICghb2Zmc2V0LnggJiYgIW9mZnNldC55KSB7XG4gIFx0XHRcdFx0bWFwLmZpcmUoJ21vdmVlbmQnKTtcblxuICBcdFx0XHR9IGVsc2Uge1xuICBcdFx0XHRcdG9mZnNldCA9IG1hcC5fbGltaXRPZmZzZXQob2Zmc2V0LCBtYXAub3B0aW9ucy5tYXhCb3VuZHMpO1xuXG4gIFx0XHRcdFx0cmVxdWVzdEFuaW1GcmFtZShmdW5jdGlvbiAoKSB7XG4gIFx0XHRcdFx0XHRtYXAucGFuQnkob2Zmc2V0LCB7XG4gIFx0XHRcdFx0XHRcdGR1cmF0aW9uOiBkZWNlbGVyYXRpb25EdXJhdGlvbixcbiAgXHRcdFx0XHRcdFx0ZWFzZUxpbmVhcml0eTogZWFzZSxcbiAgXHRcdFx0XHRcdFx0bm9Nb3ZlU3RhcnQ6IHRydWUsXG4gIFx0XHRcdFx0XHRcdGFuaW1hdGU6IHRydWVcbiAgXHRcdFx0XHRcdH0pO1xuICBcdFx0XHRcdH0pO1xuICBcdFx0XHR9XG4gIFx0XHR9XG4gIFx0fVxuICB9KTtcblxuICAvLyBAc2VjdGlvbiBIYW5kbGVyc1xuICAvLyBAcHJvcGVydHkgZHJhZ2dpbmc6IEhhbmRsZXJcbiAgLy8gTWFwIGRyYWdnaW5nIGhhbmRsZXIgKGJ5IGJvdGggbW91c2UgYW5kIHRvdWNoKS5cbiAgTWFwLmFkZEluaXRIb29rKCdhZGRIYW5kbGVyJywgJ2RyYWdnaW5nJywgRHJhZyk7XG5cbiAgLypcbiAgICogTC5NYXAuS2V5Ym9hcmQgaXMgaGFuZGxpbmcga2V5Ym9hcmQgaW50ZXJhY3Rpb24gd2l0aCB0aGUgbWFwLCBlbmFibGVkIGJ5IGRlZmF1bHQuXG4gICAqL1xuXG4gIC8vIEBuYW1lc3BhY2UgTWFwXG4gIC8vIEBzZWN0aW9uIEtleWJvYXJkIE5hdmlnYXRpb24gT3B0aW9uc1xuICBNYXAubWVyZ2VPcHRpb25zKHtcbiAgXHQvLyBAb3B0aW9uIGtleWJvYXJkOiBCb29sZWFuID0gdHJ1ZVxuICBcdC8vIE1ha2VzIHRoZSBtYXAgZm9jdXNhYmxlIGFuZCBhbGxvd3MgdXNlcnMgdG8gbmF2aWdhdGUgdGhlIG1hcCB3aXRoIGtleWJvYXJkXG4gIFx0Ly8gYXJyb3dzIGFuZCBgK2AvYC1gIGtleXMuXG4gIFx0a2V5Ym9hcmQ6IHRydWUsXG5cbiAgXHQvLyBAb3B0aW9uIGtleWJvYXJkUGFuRGVsdGE6IE51bWJlciA9IDgwXG4gIFx0Ly8gQW1vdW50IG9mIHBpeGVscyB0byBwYW4gd2hlbiBwcmVzc2luZyBhbiBhcnJvdyBrZXkuXG4gIFx0a2V5Ym9hcmRQYW5EZWx0YTogODBcbiAgfSk7XG5cbiAgdmFyIEtleWJvYXJkID0gSGFuZGxlci5leHRlbmQoe1xuXG4gIFx0a2V5Q29kZXM6IHtcbiAgXHRcdGxlZnQ6ICAgIFszN10sXG4gIFx0XHRyaWdodDogICBbMzldLFxuICBcdFx0ZG93bjogICAgWzQwXSxcbiAgXHRcdHVwOiAgICAgIFszOF0sXG4gIFx0XHR6b29tSW46ICBbMTg3LCAxMDcsIDYxLCAxNzFdLFxuICBcdFx0em9vbU91dDogWzE4OSwgMTA5LCA1NCwgMTczXVxuICBcdH0sXG5cbiAgXHRpbml0aWFsaXplOiBmdW5jdGlvbiAobWFwKSB7XG4gIFx0XHR0aGlzLl9tYXAgPSBtYXA7XG5cbiAgXHRcdHRoaXMuX3NldFBhbkRlbHRhKG1hcC5vcHRpb25zLmtleWJvYXJkUGFuRGVsdGEpO1xuICBcdFx0dGhpcy5fc2V0Wm9vbURlbHRhKG1hcC5vcHRpb25zLnpvb21EZWx0YSk7XG4gIFx0fSxcblxuICBcdGFkZEhvb2tzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR2YXIgY29udGFpbmVyID0gdGhpcy5fbWFwLl9jb250YWluZXI7XG5cbiAgXHRcdC8vIG1ha2UgdGhlIGNvbnRhaW5lciBmb2N1c2FibGUgYnkgdGFiYmluZ1xuICBcdFx0aWYgKGNvbnRhaW5lci50YWJJbmRleCA8PSAwKSB7XG4gIFx0XHRcdGNvbnRhaW5lci50YWJJbmRleCA9ICcwJztcbiAgXHRcdH1cblxuICBcdFx0b24oY29udGFpbmVyLCB7XG4gIFx0XHRcdGZvY3VzOiB0aGlzLl9vbkZvY3VzLFxuICBcdFx0XHRibHVyOiB0aGlzLl9vbkJsdXIsXG4gIFx0XHRcdG1vdXNlZG93bjogdGhpcy5fb25Nb3VzZURvd25cbiAgXHRcdH0sIHRoaXMpO1xuXG4gIFx0XHR0aGlzLl9tYXAub24oe1xuICBcdFx0XHRmb2N1czogdGhpcy5fYWRkSG9va3MsXG4gIFx0XHRcdGJsdXI6IHRoaXMuX3JlbW92ZUhvb2tzXG4gIFx0XHR9LCB0aGlzKTtcbiAgXHR9LFxuXG4gIFx0cmVtb3ZlSG9va3M6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHRoaXMuX3JlbW92ZUhvb2tzKCk7XG5cbiAgXHRcdG9mZih0aGlzLl9tYXAuX2NvbnRhaW5lciwge1xuICBcdFx0XHRmb2N1czogdGhpcy5fb25Gb2N1cyxcbiAgXHRcdFx0Ymx1cjogdGhpcy5fb25CbHVyLFxuICBcdFx0XHRtb3VzZWRvd246IHRoaXMuX29uTW91c2VEb3duXG4gIFx0XHR9LCB0aGlzKTtcblxuICBcdFx0dGhpcy5fbWFwLm9mZih7XG4gIFx0XHRcdGZvY3VzOiB0aGlzLl9hZGRIb29rcyxcbiAgXHRcdFx0Ymx1cjogdGhpcy5fcmVtb3ZlSG9va3NcbiAgXHRcdH0sIHRoaXMpO1xuICBcdH0sXG5cbiAgXHRfb25Nb3VzZURvd246IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICh0aGlzLl9mb2N1c2VkKSB7IHJldHVybjsgfVxuXG4gIFx0XHR2YXIgYm9keSA9IGRvY3VtZW50LmJvZHksXG4gIFx0XHQgICAgZG9jRWwgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsXG4gIFx0XHQgICAgdG9wID0gYm9keS5zY3JvbGxUb3AgfHwgZG9jRWwuc2Nyb2xsVG9wLFxuICBcdFx0ICAgIGxlZnQgPSBib2R5LnNjcm9sbExlZnQgfHwgZG9jRWwuc2Nyb2xsTGVmdDtcblxuICBcdFx0dGhpcy5fbWFwLl9jb250YWluZXIuZm9jdXMoKTtcblxuICBcdFx0d2luZG93LnNjcm9sbFRvKGxlZnQsIHRvcCk7XG4gIFx0fSxcblxuICBcdF9vbkZvY3VzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR0aGlzLl9mb2N1c2VkID0gdHJ1ZTtcbiAgXHRcdHRoaXMuX21hcC5maXJlKCdmb2N1cycpO1xuICBcdH0sXG5cbiAgXHRfb25CbHVyOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR0aGlzLl9mb2N1c2VkID0gZmFsc2U7XG4gIFx0XHR0aGlzLl9tYXAuZmlyZSgnYmx1cicpO1xuICBcdH0sXG5cbiAgXHRfc2V0UGFuRGVsdGE6IGZ1bmN0aW9uIChwYW5EZWx0YSkge1xuICBcdFx0dmFyIGtleXMgPSB0aGlzLl9wYW5LZXlzID0ge30sXG4gIFx0XHQgICAgY29kZXMgPSB0aGlzLmtleUNvZGVzLFxuICBcdFx0ICAgIGksIGxlbjtcblxuICBcdFx0Zm9yIChpID0gMCwgbGVuID0gY29kZXMubGVmdC5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICBcdFx0XHRrZXlzW2NvZGVzLmxlZnRbaV1dID0gWy0xICogcGFuRGVsdGEsIDBdO1xuICBcdFx0fVxuICBcdFx0Zm9yIChpID0gMCwgbGVuID0gY29kZXMucmlnaHQubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgXHRcdFx0a2V5c1tjb2Rlcy5yaWdodFtpXV0gPSBbcGFuRGVsdGEsIDBdO1xuICBcdFx0fVxuICBcdFx0Zm9yIChpID0gMCwgbGVuID0gY29kZXMuZG93bi5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICBcdFx0XHRrZXlzW2NvZGVzLmRvd25baV1dID0gWzAsIHBhbkRlbHRhXTtcbiAgXHRcdH1cbiAgXHRcdGZvciAoaSA9IDAsIGxlbiA9IGNvZGVzLnVwLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gIFx0XHRcdGtleXNbY29kZXMudXBbaV1dID0gWzAsIC0xICogcGFuRGVsdGFdO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfc2V0Wm9vbURlbHRhOiBmdW5jdGlvbiAoem9vbURlbHRhKSB7XG4gIFx0XHR2YXIga2V5cyA9IHRoaXMuX3pvb21LZXlzID0ge30sXG4gIFx0XHQgICAgY29kZXMgPSB0aGlzLmtleUNvZGVzLFxuICBcdFx0ICAgIGksIGxlbjtcblxuICBcdFx0Zm9yIChpID0gMCwgbGVuID0gY29kZXMuem9vbUluLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gIFx0XHRcdGtleXNbY29kZXMuem9vbUluW2ldXSA9IHpvb21EZWx0YTtcbiAgXHRcdH1cbiAgXHRcdGZvciAoaSA9IDAsIGxlbiA9IGNvZGVzLnpvb21PdXQubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgXHRcdFx0a2V5c1tjb2Rlcy56b29tT3V0W2ldXSA9IC16b29tRGVsdGE7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF9hZGRIb29rczogZnVuY3Rpb24gKCkge1xuICBcdFx0b24oZG9jdW1lbnQsICdrZXlkb3duJywgdGhpcy5fb25LZXlEb3duLCB0aGlzKTtcbiAgXHR9LFxuXG4gIFx0X3JlbW92ZUhvb2tzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRvZmYoZG9jdW1lbnQsICdrZXlkb3duJywgdGhpcy5fb25LZXlEb3duLCB0aGlzKTtcbiAgXHR9LFxuXG4gIFx0X29uS2V5RG93bjogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdGlmIChlLmFsdEtleSB8fCBlLmN0cmxLZXkgfHwgZS5tZXRhS2V5KSB7IHJldHVybjsgfVxuXG4gIFx0XHR2YXIga2V5ID0gZS5rZXlDb2RlLFxuICBcdFx0ICAgIG1hcCA9IHRoaXMuX21hcCxcbiAgXHRcdCAgICBvZmZzZXQ7XG5cbiAgXHRcdGlmIChrZXkgaW4gdGhpcy5fcGFuS2V5cykge1xuICBcdFx0XHRpZiAoIW1hcC5fcGFuQW5pbSB8fCAhbWFwLl9wYW5BbmltLl9pblByb2dyZXNzKSB7XG4gIFx0XHRcdFx0b2Zmc2V0ID0gdGhpcy5fcGFuS2V5c1trZXldO1xuICBcdFx0XHRcdGlmIChlLnNoaWZ0S2V5KSB7XG4gIFx0XHRcdFx0XHRvZmZzZXQgPSB0b1BvaW50KG9mZnNldCkubXVsdGlwbHlCeSgzKTtcbiAgXHRcdFx0XHR9XG5cbiAgXHRcdFx0XHRpZiAobWFwLm9wdGlvbnMubWF4Qm91bmRzKSB7XG4gIFx0XHRcdFx0XHRvZmZzZXQgPSBtYXAuX2xpbWl0T2Zmc2V0KHRvUG9pbnQob2Zmc2V0KSwgbWFwLm9wdGlvbnMubWF4Qm91bmRzKTtcbiAgXHRcdFx0XHR9XG5cbiAgXHRcdFx0XHRpZiAobWFwLm9wdGlvbnMud29ybGRDb3B5SnVtcCkge1xuICBcdFx0XHRcdFx0dmFyIG5ld0xhdExuZyA9IG1hcC53cmFwTGF0TG5nKG1hcC51bnByb2plY3QobWFwLnByb2plY3QobWFwLmdldENlbnRlcigpKS5hZGQob2Zmc2V0KSkpO1xuICBcdFx0XHRcdFx0bWFwLnBhblRvKG5ld0xhdExuZyk7XG4gIFx0XHRcdFx0fSBlbHNlIHtcbiAgXHRcdFx0XHRcdG1hcC5wYW5CeShvZmZzZXQpO1xuICBcdFx0XHRcdH1cbiAgXHRcdFx0fVxuICBcdFx0fSBlbHNlIGlmIChrZXkgaW4gdGhpcy5fem9vbUtleXMpIHtcbiAgXHRcdFx0bWFwLnNldFpvb20obWFwLmdldFpvb20oKSArIChlLnNoaWZ0S2V5ID8gMyA6IDEpICogdGhpcy5fem9vbUtleXNba2V5XSk7XG5cbiAgXHRcdH0gZWxzZSBpZiAoa2V5ID09PSAyNyAmJiBtYXAuX3BvcHVwICYmIG1hcC5fcG9wdXAub3B0aW9ucy5jbG9zZU9uRXNjYXBlS2V5KSB7XG4gIFx0XHRcdG1hcC5jbG9zZVBvcHVwKCk7XG5cbiAgXHRcdH0gZWxzZSB7XG4gIFx0XHRcdHJldHVybjtcbiAgXHRcdH1cblxuICBcdFx0c3RvcChlKTtcbiAgXHR9XG4gIH0pO1xuXG4gIC8vIEBzZWN0aW9uIEhhbmRsZXJzXG4gIC8vIEBzZWN0aW9uIEhhbmRsZXJzXG4gIC8vIEBwcm9wZXJ0eSBrZXlib2FyZDogSGFuZGxlclxuICAvLyBLZXlib2FyZCBuYXZpZ2F0aW9uIGhhbmRsZXIuXG4gIE1hcC5hZGRJbml0SG9vaygnYWRkSGFuZGxlcicsICdrZXlib2FyZCcsIEtleWJvYXJkKTtcblxuICAvKlxuICAgKiBMLkhhbmRsZXIuU2Nyb2xsV2hlZWxab29tIGlzIHVzZWQgYnkgTC5NYXAgdG8gZW5hYmxlIG1vdXNlIHNjcm9sbCB3aGVlbCB6b29tIG9uIHRoZSBtYXAuXG4gICAqL1xuXG4gIC8vIEBuYW1lc3BhY2UgTWFwXG4gIC8vIEBzZWN0aW9uIEludGVyYWN0aW9uIE9wdGlvbnNcbiAgTWFwLm1lcmdlT3B0aW9ucyh7XG4gIFx0Ly8gQHNlY3Rpb24gTW91c2Ugd2hlZWwgb3B0aW9uc1xuICBcdC8vIEBvcHRpb24gc2Nyb2xsV2hlZWxab29tOiBCb29sZWFufFN0cmluZyA9IHRydWVcbiAgXHQvLyBXaGV0aGVyIHRoZSBtYXAgY2FuIGJlIHpvb21lZCBieSB1c2luZyB0aGUgbW91c2Ugd2hlZWwuIElmIHBhc3NlZCBgJ2NlbnRlcidgLFxuICBcdC8vIGl0IHdpbGwgem9vbSB0byB0aGUgY2VudGVyIG9mIHRoZSB2aWV3IHJlZ2FyZGxlc3Mgb2Ygd2hlcmUgdGhlIG1vdXNlIHdhcy5cbiAgXHRzY3JvbGxXaGVlbFpvb206IHRydWUsXG5cbiAgXHQvLyBAb3B0aW9uIHdoZWVsRGVib3VuY2VUaW1lOiBOdW1iZXIgPSA0MFxuICBcdC8vIExpbWl0cyB0aGUgcmF0ZSBhdCB3aGljaCBhIHdoZWVsIGNhbiBmaXJlIChpbiBtaWxsaXNlY29uZHMpLiBCeSBkZWZhdWx0XG4gIFx0Ly8gdXNlciBjYW4ndCB6b29tIHZpYSB3aGVlbCBtb3JlIG9mdGVuIHRoYW4gb25jZSBwZXIgNDAgbXMuXG4gIFx0d2hlZWxEZWJvdW5jZVRpbWU6IDQwLFxuXG4gIFx0Ly8gQG9wdGlvbiB3aGVlbFB4UGVyWm9vbUxldmVsOiBOdW1iZXIgPSA2MFxuICBcdC8vIEhvdyBtYW55IHNjcm9sbCBwaXhlbHMgKGFzIHJlcG9ydGVkIGJ5IFtMLkRvbUV2ZW50LmdldFdoZWVsRGVsdGFdKCNkb21ldmVudC1nZXR3aGVlbGRlbHRhKSlcbiAgXHQvLyBtZWFuIGEgY2hhbmdlIG9mIG9uZSBmdWxsIHpvb20gbGV2ZWwuIFNtYWxsZXIgdmFsdWVzIHdpbGwgbWFrZSB3aGVlbC16b29taW5nXG4gIFx0Ly8gZmFzdGVyIChhbmQgdmljZSB2ZXJzYSkuXG4gIFx0d2hlZWxQeFBlclpvb21MZXZlbDogNjBcbiAgfSk7XG5cbiAgdmFyIFNjcm9sbFdoZWVsWm9vbSA9IEhhbmRsZXIuZXh0ZW5kKHtcbiAgXHRhZGRIb29rczogZnVuY3Rpb24gKCkge1xuICBcdFx0b24odGhpcy5fbWFwLl9jb250YWluZXIsICd3aGVlbCcsIHRoaXMuX29uV2hlZWxTY3JvbGwsIHRoaXMpO1xuXG4gIFx0XHR0aGlzLl9kZWx0YSA9IDA7XG4gIFx0fSxcblxuICBcdHJlbW92ZUhvb2tzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRvZmYodGhpcy5fbWFwLl9jb250YWluZXIsICd3aGVlbCcsIHRoaXMuX29uV2hlZWxTY3JvbGwsIHRoaXMpO1xuICBcdH0sXG5cbiAgXHRfb25XaGVlbFNjcm9sbDogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdHZhciBkZWx0YSA9IGdldFdoZWVsRGVsdGEoZSk7XG5cbiAgXHRcdHZhciBkZWJvdW5jZSA9IHRoaXMuX21hcC5vcHRpb25zLndoZWVsRGVib3VuY2VUaW1lO1xuXG4gIFx0XHR0aGlzLl9kZWx0YSArPSBkZWx0YTtcbiAgXHRcdHRoaXMuX2xhc3RNb3VzZVBvcyA9IHRoaXMuX21hcC5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlKTtcblxuICBcdFx0aWYgKCF0aGlzLl9zdGFydFRpbWUpIHtcbiAgXHRcdFx0dGhpcy5fc3RhcnRUaW1lID0gK25ldyBEYXRlKCk7XG4gIFx0XHR9XG5cbiAgXHRcdHZhciBsZWZ0ID0gTWF0aC5tYXgoZGVib3VuY2UgLSAoK25ldyBEYXRlKCkgLSB0aGlzLl9zdGFydFRpbWUpLCAwKTtcblxuICBcdFx0Y2xlYXJUaW1lb3V0KHRoaXMuX3RpbWVyKTtcbiAgXHRcdHRoaXMuX3RpbWVyID0gc2V0VGltZW91dChiaW5kKHRoaXMuX3BlcmZvcm1ab29tLCB0aGlzKSwgbGVmdCk7XG5cbiAgXHRcdHN0b3AoZSk7XG4gIFx0fSxcblxuICBcdF9wZXJmb3JtWm9vbTogZnVuY3Rpb24gKCkge1xuICBcdFx0dmFyIG1hcCA9IHRoaXMuX21hcCxcbiAgXHRcdCAgICB6b29tID0gbWFwLmdldFpvb20oKSxcbiAgXHRcdCAgICBzbmFwID0gdGhpcy5fbWFwLm9wdGlvbnMuem9vbVNuYXAgfHwgMDtcblxuICBcdFx0bWFwLl9zdG9wKCk7IC8vIHN0b3AgcGFubmluZyBhbmQgZmx5IGFuaW1hdGlvbnMgaWYgYW55XG5cbiAgXHRcdC8vIG1hcCB0aGUgZGVsdGEgd2l0aCBhIHNpZ21vaWQgZnVuY3Rpb24gdG8gLTQuLjQgcmFuZ2UgbGVhbmluZyBvbiAtMS4uMVxuICBcdFx0dmFyIGQyID0gdGhpcy5fZGVsdGEgLyAodGhpcy5fbWFwLm9wdGlvbnMud2hlZWxQeFBlclpvb21MZXZlbCAqIDQpLFxuICBcdFx0ICAgIGQzID0gNCAqIE1hdGgubG9nKDIgLyAoMSArIE1hdGguZXhwKC1NYXRoLmFicyhkMikpKSkgLyBNYXRoLkxOMixcbiAgXHRcdCAgICBkNCA9IHNuYXAgPyBNYXRoLmNlaWwoZDMgLyBzbmFwKSAqIHNuYXAgOiBkMyxcbiAgXHRcdCAgICBkZWx0YSA9IG1hcC5fbGltaXRab29tKHpvb20gKyAodGhpcy5fZGVsdGEgPiAwID8gZDQgOiAtZDQpKSAtIHpvb207XG5cbiAgXHRcdHRoaXMuX2RlbHRhID0gMDtcbiAgXHRcdHRoaXMuX3N0YXJ0VGltZSA9IG51bGw7XG5cbiAgXHRcdGlmICghZGVsdGEpIHsgcmV0dXJuOyB9XG5cbiAgXHRcdGlmIChtYXAub3B0aW9ucy5zY3JvbGxXaGVlbFpvb20gPT09ICdjZW50ZXInKSB7XG4gIFx0XHRcdG1hcC5zZXRab29tKHpvb20gKyBkZWx0YSk7XG4gIFx0XHR9IGVsc2Uge1xuICBcdFx0XHRtYXAuc2V0Wm9vbUFyb3VuZCh0aGlzLl9sYXN0TW91c2VQb3MsIHpvb20gKyBkZWx0YSk7XG4gIFx0XHR9XG4gIFx0fVxuICB9KTtcblxuICAvLyBAc2VjdGlvbiBIYW5kbGVyc1xuICAvLyBAcHJvcGVydHkgc2Nyb2xsV2hlZWxab29tOiBIYW5kbGVyXG4gIC8vIFNjcm9sbCB3aGVlbCB6b29tIGhhbmRsZXIuXG4gIE1hcC5hZGRJbml0SG9vaygnYWRkSGFuZGxlcicsICdzY3JvbGxXaGVlbFpvb20nLCBTY3JvbGxXaGVlbFpvb20pO1xuXG4gIC8qXG4gICAqIEwuTWFwLlRhcEhvbGQgaXMgdXNlZCB0byBzaW11bGF0ZSBgY29udGV4dG1lbnVgIGV2ZW50IG9uIGxvbmcgaG9sZCxcbiAgICogd2hpY2ggb3RoZXJ3aXNlIGlzIG5vdCBmaXJlZCBieSBtb2JpbGUgU2FmYXJpLlxuICAgKi9cblxuICB2YXIgdGFwSG9sZERlbGF5ID0gNjAwO1xuXG4gIC8vIEBuYW1lc3BhY2UgTWFwXG4gIC8vIEBzZWN0aW9uIEludGVyYWN0aW9uIE9wdGlvbnNcbiAgTWFwLm1lcmdlT3B0aW9ucyh7XG4gIFx0Ly8gQHNlY3Rpb24gVG91Y2ggaW50ZXJhY3Rpb24gb3B0aW9uc1xuICBcdC8vIEBvcHRpb24gdGFwSG9sZDogQm9vbGVhblxuICBcdC8vIEVuYWJsZXMgc2ltdWxhdGlvbiBvZiBgY29udGV4dG1lbnVgIGV2ZW50LCBkZWZhdWx0IGlzIGB0cnVlYCBmb3IgbW9iaWxlIFNhZmFyaS5cbiAgXHR0YXBIb2xkOiBCcm93c2VyLnRvdWNoTmF0aXZlICYmIEJyb3dzZXIuc2FmYXJpICYmIEJyb3dzZXIubW9iaWxlLFxuXG4gIFx0Ly8gQG9wdGlvbiB0YXBUb2xlcmFuY2U6IE51bWJlciA9IDE1XG4gIFx0Ly8gVGhlIG1heCBudW1iZXIgb2YgcGl4ZWxzIGEgdXNlciBjYW4gc2hpZnQgaGlzIGZpbmdlciBkdXJpbmcgdG91Y2hcbiAgXHQvLyBmb3IgaXQgdG8gYmUgY29uc2lkZXJlZCBhIHZhbGlkIHRhcC5cbiAgXHR0YXBUb2xlcmFuY2U6IDE1XG4gIH0pO1xuXG4gIHZhciBUYXBIb2xkID0gSGFuZGxlci5leHRlbmQoe1xuICBcdGFkZEhvb2tzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRvbih0aGlzLl9tYXAuX2NvbnRhaW5lciwgJ3RvdWNoc3RhcnQnLCB0aGlzLl9vbkRvd24sIHRoaXMpO1xuICBcdH0sXG5cbiAgXHRyZW1vdmVIb29rczogZnVuY3Rpb24gKCkge1xuICBcdFx0b2ZmKHRoaXMuX21hcC5fY29udGFpbmVyLCAndG91Y2hzdGFydCcsIHRoaXMuX29uRG93biwgdGhpcyk7XG4gIFx0fSxcblxuICBcdF9vbkRvd246IGZ1bmN0aW9uIChlKSB7XG4gIFx0XHRjbGVhclRpbWVvdXQodGhpcy5faG9sZFRpbWVvdXQpO1xuICBcdFx0aWYgKGUudG91Y2hlcy5sZW5ndGggIT09IDEpIHsgcmV0dXJuOyB9XG5cbiAgXHRcdHZhciBmaXJzdCA9IGUudG91Y2hlc1swXTtcbiAgXHRcdHRoaXMuX3N0YXJ0UG9zID0gdGhpcy5fbmV3UG9zID0gbmV3IFBvaW50KGZpcnN0LmNsaWVudFgsIGZpcnN0LmNsaWVudFkpO1xuXG4gIFx0XHR0aGlzLl9ob2xkVGltZW91dCA9IHNldFRpbWVvdXQoYmluZChmdW5jdGlvbiAoKSB7XG4gIFx0XHRcdHRoaXMuX2NhbmNlbCgpO1xuICBcdFx0XHRpZiAoIXRoaXMuX2lzVGFwVmFsaWQoKSkgeyByZXR1cm47IH1cblxuICBcdFx0XHQvLyBwcmV2ZW50IHNpbXVsYXRlZCBtb3VzZSBldmVudHMgaHR0cHM6Ly93M2MuZ2l0aHViLmlvL3RvdWNoLWV2ZW50cy8jbW91c2UtZXZlbnRzXG4gIFx0XHRcdG9uKGRvY3VtZW50LCAndG91Y2hlbmQnLCBwcmV2ZW50RGVmYXVsdCk7XG4gIFx0XHRcdG9uKGRvY3VtZW50LCAndG91Y2hlbmQgdG91Y2hjYW5jZWwnLCB0aGlzLl9jYW5jZWxDbGlja1ByZXZlbnQpO1xuICBcdFx0XHR0aGlzLl9zaW11bGF0ZUV2ZW50KCdjb250ZXh0bWVudScsIGZpcnN0KTtcbiAgXHRcdH0sIHRoaXMpLCB0YXBIb2xkRGVsYXkpO1xuXG4gIFx0XHRvbihkb2N1bWVudCwgJ3RvdWNoZW5kIHRvdWNoY2FuY2VsIGNvbnRleHRtZW51JywgdGhpcy5fY2FuY2VsLCB0aGlzKTtcbiAgXHRcdG9uKGRvY3VtZW50LCAndG91Y2htb3ZlJywgdGhpcy5fb25Nb3ZlLCB0aGlzKTtcbiAgXHR9LFxuXG4gIFx0X2NhbmNlbENsaWNrUHJldmVudDogZnVuY3Rpb24gY2FuY2VsQ2xpY2tQcmV2ZW50KCkge1xuICBcdFx0b2ZmKGRvY3VtZW50LCAndG91Y2hlbmQnLCBwcmV2ZW50RGVmYXVsdCk7XG4gIFx0XHRvZmYoZG9jdW1lbnQsICd0b3VjaGVuZCB0b3VjaGNhbmNlbCcsIGNhbmNlbENsaWNrUHJldmVudCk7XG4gIFx0fSxcblxuICBcdF9jYW5jZWw6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGNsZWFyVGltZW91dCh0aGlzLl9ob2xkVGltZW91dCk7XG4gIFx0XHRvZmYoZG9jdW1lbnQsICd0b3VjaGVuZCB0b3VjaGNhbmNlbCBjb250ZXh0bWVudScsIHRoaXMuX2NhbmNlbCwgdGhpcyk7XG4gIFx0XHRvZmYoZG9jdW1lbnQsICd0b3VjaG1vdmUnLCB0aGlzLl9vbk1vdmUsIHRoaXMpO1xuICBcdH0sXG5cbiAgXHRfb25Nb3ZlOiBmdW5jdGlvbiAoZSkge1xuICBcdFx0dmFyIGZpcnN0ID0gZS50b3VjaGVzWzBdO1xuICBcdFx0dGhpcy5fbmV3UG9zID0gbmV3IFBvaW50KGZpcnN0LmNsaWVudFgsIGZpcnN0LmNsaWVudFkpO1xuICBcdH0sXG5cbiAgXHRfaXNUYXBWYWxpZDogZnVuY3Rpb24gKCkge1xuICBcdFx0cmV0dXJuIHRoaXMuX25ld1Bvcy5kaXN0YW5jZVRvKHRoaXMuX3N0YXJ0UG9zKSA8PSB0aGlzLl9tYXAub3B0aW9ucy50YXBUb2xlcmFuY2U7XG4gIFx0fSxcblxuICBcdF9zaW11bGF0ZUV2ZW50OiBmdW5jdGlvbiAodHlwZSwgZSkge1xuICBcdFx0dmFyIHNpbXVsYXRlZEV2ZW50ID0gbmV3IE1vdXNlRXZlbnQodHlwZSwge1xuICBcdFx0XHRidWJibGVzOiB0cnVlLFxuICBcdFx0XHRjYW5jZWxhYmxlOiB0cnVlLFxuICBcdFx0XHR2aWV3OiB3aW5kb3csXG4gIFx0XHRcdC8vIGRldGFpbDogMSxcbiAgXHRcdFx0c2NyZWVuWDogZS5zY3JlZW5YLFxuICBcdFx0XHRzY3JlZW5ZOiBlLnNjcmVlblksXG4gIFx0XHRcdGNsaWVudFg6IGUuY2xpZW50WCxcbiAgXHRcdFx0Y2xpZW50WTogZS5jbGllbnRZLFxuICBcdFx0XHQvLyBidXR0b246IDIsXG4gIFx0XHRcdC8vIGJ1dHRvbnM6IDJcbiAgXHRcdH0pO1xuXG4gIFx0XHRzaW11bGF0ZWRFdmVudC5fc2ltdWxhdGVkID0gdHJ1ZTtcblxuICBcdFx0ZS50YXJnZXQuZGlzcGF0Y2hFdmVudChzaW11bGF0ZWRFdmVudCk7XG4gIFx0fVxuICB9KTtcblxuICAvLyBAc2VjdGlvbiBIYW5kbGVyc1xuICAvLyBAcHJvcGVydHkgdGFwSG9sZDogSGFuZGxlclxuICAvLyBMb25nIHRhcCBoYW5kbGVyIHRvIHNpbXVsYXRlIGBjb250ZXh0bWVudWAgZXZlbnQgKHVzZWZ1bCBpbiBtb2JpbGUgU2FmYXJpKS5cbiAgTWFwLmFkZEluaXRIb29rKCdhZGRIYW5kbGVyJywgJ3RhcEhvbGQnLCBUYXBIb2xkKTtcblxuICAvKlxuICAgKiBMLkhhbmRsZXIuVG91Y2hab29tIGlzIHVzZWQgYnkgTC5NYXAgdG8gYWRkIHBpbmNoIHpvb20gb24gc3VwcG9ydGVkIG1vYmlsZSBicm93c2Vycy5cbiAgICovXG5cbiAgLy8gQG5hbWVzcGFjZSBNYXBcbiAgLy8gQHNlY3Rpb24gSW50ZXJhY3Rpb24gT3B0aW9uc1xuICBNYXAubWVyZ2VPcHRpb25zKHtcbiAgXHQvLyBAc2VjdGlvbiBUb3VjaCBpbnRlcmFjdGlvbiBvcHRpb25zXG4gIFx0Ly8gQG9wdGlvbiB0b3VjaFpvb206IEJvb2xlYW58U3RyaW5nID0gKlxuICBcdC8vIFdoZXRoZXIgdGhlIG1hcCBjYW4gYmUgem9vbWVkIGJ5IHRvdWNoLWRyYWdnaW5nIHdpdGggdHdvIGZpbmdlcnMuIElmXG4gIFx0Ly8gcGFzc2VkIGAnY2VudGVyJ2AsIGl0IHdpbGwgem9vbSB0byB0aGUgY2VudGVyIG9mIHRoZSB2aWV3IHJlZ2FyZGxlc3Mgb2ZcbiAgXHQvLyB3aGVyZSB0aGUgdG91Y2ggZXZlbnRzIChmaW5nZXJzKSB3ZXJlLiBFbmFibGVkIGZvciB0b3VjaC1jYXBhYmxlIHdlYlxuICBcdC8vIGJyb3dzZXJzLlxuICBcdHRvdWNoWm9vbTogQnJvd3Nlci50b3VjaCxcblxuICBcdC8vIEBvcHRpb24gYm91bmNlQXRab29tTGltaXRzOiBCb29sZWFuID0gdHJ1ZVxuICBcdC8vIFNldCBpdCB0byBmYWxzZSBpZiB5b3UgZG9uJ3Qgd2FudCB0aGUgbWFwIHRvIHpvb20gYmV5b25kIG1pbi9tYXggem9vbVxuICBcdC8vIGFuZCB0aGVuIGJvdW5jZSBiYWNrIHdoZW4gcGluY2gtem9vbWluZy5cbiAgXHRib3VuY2VBdFpvb21MaW1pdHM6IHRydWVcbiAgfSk7XG5cbiAgdmFyIFRvdWNoWm9vbSA9IEhhbmRsZXIuZXh0ZW5kKHtcbiAgXHRhZGRIb29rczogZnVuY3Rpb24gKCkge1xuICBcdFx0YWRkQ2xhc3ModGhpcy5fbWFwLl9jb250YWluZXIsICdsZWFmbGV0LXRvdWNoLXpvb20nKTtcbiAgXHRcdG9uKHRoaXMuX21hcC5fY29udGFpbmVyLCAndG91Y2hzdGFydCcsIHRoaXMuX29uVG91Y2hTdGFydCwgdGhpcyk7XG4gIFx0fSxcblxuICBcdHJlbW92ZUhvb2tzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZW1vdmVDbGFzcyh0aGlzLl9tYXAuX2NvbnRhaW5lciwgJ2xlYWZsZXQtdG91Y2gtem9vbScpO1xuICBcdFx0b2ZmKHRoaXMuX21hcC5fY29udGFpbmVyLCAndG91Y2hzdGFydCcsIHRoaXMuX29uVG91Y2hTdGFydCwgdGhpcyk7XG4gIFx0fSxcblxuICBcdF9vblRvdWNoU3RhcnQ6IGZ1bmN0aW9uIChlKSB7XG4gIFx0XHR2YXIgbWFwID0gdGhpcy5fbWFwO1xuICBcdFx0aWYgKCFlLnRvdWNoZXMgfHwgZS50b3VjaGVzLmxlbmd0aCAhPT0gMiB8fCBtYXAuX2FuaW1hdGluZ1pvb20gfHwgdGhpcy5fem9vbWluZykgeyByZXR1cm47IH1cblxuICBcdFx0dmFyIHAxID0gbWFwLm1vdXNlRXZlbnRUb0NvbnRhaW5lclBvaW50KGUudG91Y2hlc1swXSksXG4gIFx0XHQgICAgcDIgPSBtYXAubW91c2VFdmVudFRvQ29udGFpbmVyUG9pbnQoZS50b3VjaGVzWzFdKTtcblxuICBcdFx0dGhpcy5fY2VudGVyUG9pbnQgPSBtYXAuZ2V0U2l6ZSgpLl9kaXZpZGVCeSgyKTtcbiAgXHRcdHRoaXMuX3N0YXJ0TGF0TG5nID0gbWFwLmNvbnRhaW5lclBvaW50VG9MYXRMbmcodGhpcy5fY2VudGVyUG9pbnQpO1xuICBcdFx0aWYgKG1hcC5vcHRpb25zLnRvdWNoWm9vbSAhPT0gJ2NlbnRlcicpIHtcbiAgXHRcdFx0dGhpcy5fcGluY2hTdGFydExhdExuZyA9IG1hcC5jb250YWluZXJQb2ludFRvTGF0TG5nKHAxLmFkZChwMikuX2RpdmlkZUJ5KDIpKTtcbiAgXHRcdH1cblxuICBcdFx0dGhpcy5fc3RhcnREaXN0ID0gcDEuZGlzdGFuY2VUbyhwMik7XG4gIFx0XHR0aGlzLl9zdGFydFpvb20gPSBtYXAuZ2V0Wm9vbSgpO1xuXG4gIFx0XHR0aGlzLl9tb3ZlZCA9IGZhbHNlO1xuICBcdFx0dGhpcy5fem9vbWluZyA9IHRydWU7XG5cbiAgXHRcdG1hcC5fc3RvcCgpO1xuXG4gIFx0XHRvbihkb2N1bWVudCwgJ3RvdWNobW92ZScsIHRoaXMuX29uVG91Y2hNb3ZlLCB0aGlzKTtcbiAgXHRcdG9uKGRvY3VtZW50LCAndG91Y2hlbmQgdG91Y2hjYW5jZWwnLCB0aGlzLl9vblRvdWNoRW5kLCB0aGlzKTtcblxuICBcdFx0cHJldmVudERlZmF1bHQoZSk7XG4gIFx0fSxcblxuICBcdF9vblRvdWNoTW92ZTogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdGlmICghZS50b3VjaGVzIHx8IGUudG91Y2hlcy5sZW5ndGggIT09IDIgfHwgIXRoaXMuX3pvb21pbmcpIHsgcmV0dXJuOyB9XG5cbiAgXHRcdHZhciBtYXAgPSB0aGlzLl9tYXAsXG4gIFx0XHQgICAgcDEgPSBtYXAubW91c2VFdmVudFRvQ29udGFpbmVyUG9pbnQoZS50b3VjaGVzWzBdKSxcbiAgXHRcdCAgICBwMiA9IG1hcC5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlLnRvdWNoZXNbMV0pLFxuICBcdFx0ICAgIHNjYWxlID0gcDEuZGlzdGFuY2VUbyhwMikgLyB0aGlzLl9zdGFydERpc3Q7XG5cbiAgXHRcdHRoaXMuX3pvb20gPSBtYXAuZ2V0U2NhbGVab29tKHNjYWxlLCB0aGlzLl9zdGFydFpvb20pO1xuXG4gIFx0XHRpZiAoIW1hcC5vcHRpb25zLmJvdW5jZUF0Wm9vbUxpbWl0cyAmJiAoXG4gIFx0XHRcdCh0aGlzLl96b29tIDwgbWFwLmdldE1pblpvb20oKSAmJiBzY2FsZSA8IDEpIHx8XG4gIFx0XHRcdCh0aGlzLl96b29tID4gbWFwLmdldE1heFpvb20oKSAmJiBzY2FsZSA+IDEpKSkge1xuICBcdFx0XHR0aGlzLl96b29tID0gbWFwLl9saW1pdFpvb20odGhpcy5fem9vbSk7XG4gIFx0XHR9XG5cbiAgXHRcdGlmIChtYXAub3B0aW9ucy50b3VjaFpvb20gPT09ICdjZW50ZXInKSB7XG4gIFx0XHRcdHRoaXMuX2NlbnRlciA9IHRoaXMuX3N0YXJ0TGF0TG5nO1xuICBcdFx0XHRpZiAoc2NhbGUgPT09IDEpIHsgcmV0dXJuOyB9XG4gIFx0XHR9IGVsc2Uge1xuICBcdFx0XHQvLyBHZXQgZGVsdGEgZnJvbSBwaW5jaCB0byBjZW50ZXIsIHNvIGNlbnRlckxhdExuZyBpcyBkZWx0YSBhcHBsaWVkIHRvIGluaXRpYWwgcGluY2hMYXRMbmdcbiAgXHRcdFx0dmFyIGRlbHRhID0gcDEuX2FkZChwMikuX2RpdmlkZUJ5KDIpLl9zdWJ0cmFjdCh0aGlzLl9jZW50ZXJQb2ludCk7XG4gIFx0XHRcdGlmIChzY2FsZSA9PT0gMSAmJiBkZWx0YS54ID09PSAwICYmIGRlbHRhLnkgPT09IDApIHsgcmV0dXJuOyB9XG4gIFx0XHRcdHRoaXMuX2NlbnRlciA9IG1hcC51bnByb2plY3QobWFwLnByb2plY3QodGhpcy5fcGluY2hTdGFydExhdExuZywgdGhpcy5fem9vbSkuc3VidHJhY3QoZGVsdGEpLCB0aGlzLl96b29tKTtcbiAgXHRcdH1cblxuICBcdFx0aWYgKCF0aGlzLl9tb3ZlZCkge1xuICBcdFx0XHRtYXAuX21vdmVTdGFydCh0cnVlLCBmYWxzZSk7XG4gIFx0XHRcdHRoaXMuX21vdmVkID0gdHJ1ZTtcbiAgXHRcdH1cblxuICBcdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX2FuaW1SZXF1ZXN0KTtcblxuICBcdFx0dmFyIG1vdmVGbiA9IGJpbmQobWFwLl9tb3ZlLCBtYXAsIHRoaXMuX2NlbnRlciwgdGhpcy5fem9vbSwge3BpbmNoOiB0cnVlLCByb3VuZDogZmFsc2V9LCB1bmRlZmluZWQpO1xuICBcdFx0dGhpcy5fYW5pbVJlcXVlc3QgPSByZXF1ZXN0QW5pbUZyYW1lKG1vdmVGbiwgdGhpcywgdHJ1ZSk7XG5cbiAgXHRcdHByZXZlbnREZWZhdWx0KGUpO1xuICBcdH0sXG5cbiAgXHRfb25Ub3VjaEVuZDogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKCF0aGlzLl9tb3ZlZCB8fCAhdGhpcy5fem9vbWluZykge1xuICBcdFx0XHR0aGlzLl96b29taW5nID0gZmFsc2U7XG4gIFx0XHRcdHJldHVybjtcbiAgXHRcdH1cblxuICBcdFx0dGhpcy5fem9vbWluZyA9IGZhbHNlO1xuICBcdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX2FuaW1SZXF1ZXN0KTtcblxuICBcdFx0b2ZmKGRvY3VtZW50LCAndG91Y2htb3ZlJywgdGhpcy5fb25Ub3VjaE1vdmUsIHRoaXMpO1xuICBcdFx0b2ZmKGRvY3VtZW50LCAndG91Y2hlbmQgdG91Y2hjYW5jZWwnLCB0aGlzLl9vblRvdWNoRW5kLCB0aGlzKTtcblxuICBcdFx0Ly8gUGluY2ggdXBkYXRlcyBHcmlkTGF5ZXJzJyBsZXZlbHMgb25seSB3aGVuIHpvb21TbmFwIGlzIG9mZiwgc28gem9vbVNuYXAgYmVjb21lcyBub1VwZGF0ZS5cbiAgXHRcdGlmICh0aGlzLl9tYXAub3B0aW9ucy56b29tQW5pbWF0aW9uKSB7XG4gIFx0XHRcdHRoaXMuX21hcC5fYW5pbWF0ZVpvb20odGhpcy5fY2VudGVyLCB0aGlzLl9tYXAuX2xpbWl0Wm9vbSh0aGlzLl96b29tKSwgdHJ1ZSwgdGhpcy5fbWFwLm9wdGlvbnMuem9vbVNuYXApO1xuICBcdFx0fSBlbHNlIHtcbiAgXHRcdFx0dGhpcy5fbWFwLl9yZXNldFZpZXcodGhpcy5fY2VudGVyLCB0aGlzLl9tYXAuX2xpbWl0Wm9vbSh0aGlzLl96b29tKSk7XG4gIFx0XHR9XG4gIFx0fVxuICB9KTtcblxuICAvLyBAc2VjdGlvbiBIYW5kbGVyc1xuICAvLyBAcHJvcGVydHkgdG91Y2hab29tOiBIYW5kbGVyXG4gIC8vIFRvdWNoIHpvb20gaGFuZGxlci5cbiAgTWFwLmFkZEluaXRIb29rKCdhZGRIYW5kbGVyJywgJ3RvdWNoWm9vbScsIFRvdWNoWm9vbSk7XG5cbiAgTWFwLkJveFpvb20gPSBCb3hab29tO1xuICBNYXAuRG91YmxlQ2xpY2tab29tID0gRG91YmxlQ2xpY2tab29tO1xuICBNYXAuRHJhZyA9IERyYWc7XG4gIE1hcC5LZXlib2FyZCA9IEtleWJvYXJkO1xuICBNYXAuU2Nyb2xsV2hlZWxab29tID0gU2Nyb2xsV2hlZWxab29tO1xuICBNYXAuVGFwSG9sZCA9IFRhcEhvbGQ7XG4gIE1hcC5Ub3VjaFpvb20gPSBUb3VjaFpvb207XG5cbiAgZXhwb3J0cy5Cb3VuZHMgPSBCb3VuZHM7XG4gIGV4cG9ydHMuQnJvd3NlciA9IEJyb3dzZXI7XG4gIGV4cG9ydHMuQ1JTID0gQ1JTO1xuICBleHBvcnRzLkNhbnZhcyA9IENhbnZhcztcbiAgZXhwb3J0cy5DaXJjbGUgPSBDaXJjbGU7XG4gIGV4cG9ydHMuQ2lyY2xlTWFya2VyID0gQ2lyY2xlTWFya2VyO1xuICBleHBvcnRzLkNsYXNzID0gQ2xhc3M7XG4gIGV4cG9ydHMuQ29udHJvbCA9IENvbnRyb2w7XG4gIGV4cG9ydHMuRGl2SWNvbiA9IERpdkljb247XG4gIGV4cG9ydHMuRGl2T3ZlcmxheSA9IERpdk92ZXJsYXk7XG4gIGV4cG9ydHMuRG9tRXZlbnQgPSBEb21FdmVudDtcbiAgZXhwb3J0cy5Eb21VdGlsID0gRG9tVXRpbDtcbiAgZXhwb3J0cy5EcmFnZ2FibGUgPSBEcmFnZ2FibGU7XG4gIGV4cG9ydHMuRXZlbnRlZCA9IEV2ZW50ZWQ7XG4gIGV4cG9ydHMuRmVhdHVyZUdyb3VwID0gRmVhdHVyZUdyb3VwO1xuICBleHBvcnRzLkdlb0pTT04gPSBHZW9KU09OO1xuICBleHBvcnRzLkdyaWRMYXllciA9IEdyaWRMYXllcjtcbiAgZXhwb3J0cy5IYW5kbGVyID0gSGFuZGxlcjtcbiAgZXhwb3J0cy5JY29uID0gSWNvbjtcbiAgZXhwb3J0cy5JbWFnZU92ZXJsYXkgPSBJbWFnZU92ZXJsYXk7XG4gIGV4cG9ydHMuTGF0TG5nID0gTGF0TG5nO1xuICBleHBvcnRzLkxhdExuZ0JvdW5kcyA9IExhdExuZ0JvdW5kcztcbiAgZXhwb3J0cy5MYXllciA9IExheWVyO1xuICBleHBvcnRzLkxheWVyR3JvdXAgPSBMYXllckdyb3VwO1xuICBleHBvcnRzLkxpbmVVdGlsID0gTGluZVV0aWw7XG4gIGV4cG9ydHMuTWFwID0gTWFwO1xuICBleHBvcnRzLk1hcmtlciA9IE1hcmtlcjtcbiAgZXhwb3J0cy5NaXhpbiA9IE1peGluO1xuICBleHBvcnRzLlBhdGggPSBQYXRoO1xuICBleHBvcnRzLlBvaW50ID0gUG9pbnQ7XG4gIGV4cG9ydHMuUG9seVV0aWwgPSBQb2x5VXRpbDtcbiAgZXhwb3J0cy5Qb2x5Z29uID0gUG9seWdvbjtcbiAgZXhwb3J0cy5Qb2x5bGluZSA9IFBvbHlsaW5lO1xuICBleHBvcnRzLlBvcHVwID0gUG9wdXA7XG4gIGV4cG9ydHMuUG9zQW5pbWF0aW9uID0gUG9zQW5pbWF0aW9uO1xuICBleHBvcnRzLlByb2plY3Rpb24gPSBpbmRleDtcbiAgZXhwb3J0cy5SZWN0YW5nbGUgPSBSZWN0YW5nbGU7XG4gIGV4cG9ydHMuUmVuZGVyZXIgPSBSZW5kZXJlcjtcbiAgZXhwb3J0cy5TVkcgPSBTVkc7XG4gIGV4cG9ydHMuU1ZHT3ZlcmxheSA9IFNWR092ZXJsYXk7XG4gIGV4cG9ydHMuVGlsZUxheWVyID0gVGlsZUxheWVyO1xuICBleHBvcnRzLlRvb2x0aXAgPSBUb29sdGlwO1xuICBleHBvcnRzLlRyYW5zZm9ybWF0aW9uID0gVHJhbnNmb3JtYXRpb247XG4gIGV4cG9ydHMuVXRpbCA9IFV0aWw7XG4gIGV4cG9ydHMuVmlkZW9PdmVybGF5ID0gVmlkZW9PdmVybGF5O1xuICBleHBvcnRzLmJpbmQgPSBiaW5kO1xuICBleHBvcnRzLmJvdW5kcyA9IHRvQm91bmRzO1xuICBleHBvcnRzLmNhbnZhcyA9IGNhbnZhcztcbiAgZXhwb3J0cy5jaXJjbGUgPSBjaXJjbGU7XG4gIGV4cG9ydHMuY2lyY2xlTWFya2VyID0gY2lyY2xlTWFya2VyO1xuICBleHBvcnRzLmNvbnRyb2wgPSBjb250cm9sO1xuICBleHBvcnRzLmRpdkljb24gPSBkaXZJY29uO1xuICBleHBvcnRzLmV4dGVuZCA9IGV4dGVuZDtcbiAgZXhwb3J0cy5mZWF0dXJlR3JvdXAgPSBmZWF0dXJlR3JvdXA7XG4gIGV4cG9ydHMuZ2VvSlNPTiA9IGdlb0pTT047XG4gIGV4cG9ydHMuZ2VvSnNvbiA9IGdlb0pzb247XG4gIGV4cG9ydHMuZ3JpZExheWVyID0gZ3JpZExheWVyO1xuICBleHBvcnRzLmljb24gPSBpY29uO1xuICBleHBvcnRzLmltYWdlT3ZlcmxheSA9IGltYWdlT3ZlcmxheTtcbiAgZXhwb3J0cy5sYXRMbmcgPSB0b0xhdExuZztcbiAgZXhwb3J0cy5sYXRMbmdCb3VuZHMgPSB0b0xhdExuZ0JvdW5kcztcbiAgZXhwb3J0cy5sYXllckdyb3VwID0gbGF5ZXJHcm91cDtcbiAgZXhwb3J0cy5tYXAgPSBjcmVhdGVNYXA7XG4gIGV4cG9ydHMubWFya2VyID0gbWFya2VyO1xuICBleHBvcnRzLnBvaW50ID0gdG9Qb2ludDtcbiAgZXhwb3J0cy5wb2x5Z29uID0gcG9seWdvbjtcbiAgZXhwb3J0cy5wb2x5bGluZSA9IHBvbHlsaW5lO1xuICBleHBvcnRzLnBvcHVwID0gcG9wdXA7XG4gIGV4cG9ydHMucmVjdGFuZ2xlID0gcmVjdGFuZ2xlO1xuICBleHBvcnRzLnNldE9wdGlvbnMgPSBzZXRPcHRpb25zO1xuICBleHBvcnRzLnN0YW1wID0gc3RhbXA7XG4gIGV4cG9ydHMuc3ZnID0gc3ZnO1xuICBleHBvcnRzLnN2Z092ZXJsYXkgPSBzdmdPdmVybGF5O1xuICBleHBvcnRzLnRpbGVMYXllciA9IHRpbGVMYXllcjtcbiAgZXhwb3J0cy50b29sdGlwID0gdG9vbHRpcDtcbiAgZXhwb3J0cy50cmFuc2Zvcm1hdGlvbiA9IHRvVHJhbnNmb3JtYXRpb247XG4gIGV4cG9ydHMudmVyc2lvbiA9IHZlcnNpb247XG4gIGV4cG9ydHMudmlkZW9PdmVybGF5ID0gdmlkZW9PdmVybGF5O1xuXG4gIHZhciBvbGRMID0gd2luZG93Lkw7XG4gIGV4cG9ydHMubm9Db25mbGljdCA9IGZ1bmN0aW9uKCkge1xuICBcdHdpbmRvdy5MID0gb2xkTDtcbiAgXHRyZXR1cm4gdGhpcztcbiAgfVxuICAvLyBBbHdheXMgZXhwb3J0IHVzIHRvIHdpbmRvdyBnbG9iYWwgKHNlZSAjMjM2NClcbiAgd2luZG93LkwgPSBleHBvcnRzO1xuXG59KSk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1sZWFmbGV0LXNyYy5qcy5tYXBcbiIsIi8vIGV4dHJhY3RlZCBieSBtaW5pLWNzcy1leHRyYWN0LXBsdWdpblxuZXhwb3J0IHt9OyIsIi8vIGV4dHJhY3RlZCBieSBtaW5pLWNzcy1leHRyYWN0LXBsdWdpblxuZXhwb3J0IHt9OyJdLCJzb3VyY2VSb290IjoiIn0=";
        
        $__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e->leave($__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e_prof);

        
        $__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02->leave($__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02_prof);

        return; yield '';
    }

    /**
     * @codeCoverageIgnore
     */
    public function getTemplateName()
    {
        return "@public_path/build/vendors-node_modules_bootstrap-table_dist_bootstrap-table-locale-all_min_js-node_modules_boot-3f0fd0.js";
    }

    /**
     * @codeCoverageIgnore
     */
    public function getDebugInfo()
    {
        return array ();
    }

    public function getSourceContext()
    {
        return new Source("(self[\"webpackChunk\"] = self[\"webpackChunk\"] || []).push([[\"vendors-node_modules_bootstrap-table_dist_bootstrap-table-locale-all_min_js-node_modules_boot-3f0fd0\"],{

/***/ \"./node_modules/bootstrap-table/dist/bootstrap-table-locale-all.min.js\":
/*!*****************************************************************************!*\\
  !*** ./node_modules/bootstrap-table/dist/bootstrap-table-locale-all.min.js ***!
  \\*****************************************************************************/
/***/ (function(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) {

/**
  * bootstrap-table - An extended table to integration with some of the most widely used CSS frameworks. (Supports Bootstrap, Semantic UI, Bulma, Material Design, Foundation)
  *
  * @version v1.18.3
  * @homepage https://bootstrap-table.com
  * @author wenzhixin <wenzhixin2010@gmail.com> (http://wenzhixin.net.cn/)
  * @license MIT
  */

!function(t,n){ true?n(__webpack_require__(/*! jquery */ \"./node_modules/jquery/dist/jquery.js\")):0}(this,(function(t){\"use strict\";function n(t){return t&&\"object\"==typeof t&&\"default\"in t?t:{default:t}}var o=n(t),r=\"undefined\"!=typeof globalThis?globalThis:\"undefined\"!=typeof window?window:\"undefined\"!=typeof __webpack_require__.g?__webpack_require__.g:\"undefined\"!=typeof self?self:{};function e(t,n){return t(n={exports:{}},n.exports),n.exports}var a=function(t){return t&&t.Math==Math&&t},i=a(\"object\"==typeof globalThis&&globalThis)||a(\"object\"==typeof window&&window)||a(\"object\"==typeof self&&self)||a(\"object\"==typeof r&&r)||function(){return this}()||Function(\"return this\")(),u=function(t){try{return!!t()}catch(t){return!0}},f=!u((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]})),c={}.propertyIsEnumerable,l=Object.getOwnPropertyDescriptor,s={f:l&&!c.call({1:2},1)?function(t){var n=l(this,t);return!!n&&n.enumerable}:c},m=function(t,n){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:n}},g={}.toString,d=function(t){return g.call(t).slice(8,-1)},h=\"\".split,p=u((function(){return!Object(\"z\").propertyIsEnumerable(0)}))?function(t){return\"String\"==d(t)?h.call(t,\"\"):Object(t)}:Object,w=function(t){if(null==t)throw TypeError(\"Can't call method on \"+t);return t},S=function(t){return p(w(t))},P=function(t){return\"object\"==typeof t?null!==t:\"function\"==typeof t},T=function(t,n){if(!P(t))return t;var o,r;if(n&&\"function\"==typeof(o=t.toString)&&!P(r=o.call(t)))return r;if(\"function\"==typeof(o=t.valueOf)&&!P(r=o.call(t)))return r;if(!n&&\"function\"==typeof(o=t.toString)&&!P(r=o.call(t)))return r;throw TypeError(\"Can't convert object to primitive value\")},R={}.hasOwnProperty,C=function(t,n){return R.call(t,n)},b=i.document,v=P(b)&&P(b.createElement),A=!f&&!u((function(){return 7!=Object.defineProperty((t=\"div\",v?b.createElement(t):{}),\"a\",{get:function(){return 7}}).a;var t})),x=Object.getOwnPropertyDescriptor,F={f:f?x:function(t,n){if(t=S(t),n=T(n,!0),A)try{return x(t,n)}catch(t){}if(C(t,n))return m(!s.f.call(t,n),t[n])}},y=function(t){if(!P(t))throw TypeError(String(t)+\" is not an object\");return t},k=Object.defineProperty,H={f:f?k:function(t,n,o){if(y(t),n=T(n,!0),y(o),A)try{return k(t,n,o)}catch(t){}if(\"get\"in o||\"set\"in o)throw TypeError(\"Accessors not supported\");return\"value\"in o&&(t[n]=o.value),t}},O=f?function(t,n,o){return H.f(t,n,m(1,o))}:function(t,n,o){return t[n]=o,t},M=function(t,n){try{O(i,t,n)}catch(o){i[t]=n}return n},E=\"__core-js_shared__\",N=i[E]||M(E,{}),D=Function.toString;\"function\"!=typeof N.inspectSource&&(N.inspectSource=function(t){return D.call(t)});var z,L,j,B,U=N.inspectSource,J=i.WeakMap,G=\"function\"==typeof J&&/native code/.test(U(J)),V=e((function(t){(t.exports=function(t,n){return N[t]||(N[t]=void 0!==n?n:{})})(\"versions\",[]).push({version:\"3.9.1\",mode:\"global\",copyright:\"© 2021 Denis Pushkarev (zloirock.ru)\"})})),Z=0,I=Math.random(),q=function(t){return\"Symbol(\"+String(void 0===t?\"\":t)+\")_\"+(++Z+I).toString(36)},K=V(\"keys\"),W={},Y=i.WeakMap;if(G){var _=N.state||(N.state=new Y),Q=_.get,X=_.has,\$=_.set;z=function(t,n){return n.facade=t,\$.call(_,t,n),n},L=function(t){return Q.call(_,t)||{}},j=function(t){return X.call(_,t)}}else{var tt=K[B=\"state\"]||(K[B]=q(B));W[tt]=!0,z=function(t,n){return n.facade=t,O(t,tt,n),n},L=function(t){return C(t,tt)?t[tt]:{}},j=function(t){return C(t,tt)}}var nt,ot,rt={set:z,get:L,has:j,enforce:function(t){return j(t)?L(t):z(t,{})},getterFor:function(t){return function(n){var o;if(!P(n)||(o=L(n)).type!==t)throw TypeError(\"Incompatible receiver, \"+t+\" required\");return o}}},et=e((function(t){var n=rt.get,o=rt.enforce,r=String(String).split(\"String\");(t.exports=function(t,n,e,a){var u,f=!!a&&!!a.unsafe,c=!!a&&!!a.enumerable,l=!!a&&!!a.noTargetGet;\"function\"==typeof e&&(\"string\"!=typeof n||C(e,\"name\")||O(e,\"name\",n),(u=o(e)).source||(u.source=r.join(\"string\"==typeof n?n:\"\"))),t!==i?(f?!l&&t[n]&&(c=!0):delete t[n],c?t[n]=e:O(t,n,e)):c?t[n]=e:M(n,e)})(Function.prototype,\"toString\",(function(){return\"function\"==typeof this&&n(this).source||U(this)}))})),at=i,it=function(t){return\"function\"==typeof t?t:void 0},ut=function(t,n){return arguments.length<2?it(at[t])||it(i[t]):at[t]&&at[t][n]||i[t]&&i[t][n]},ft=Math.ceil,ct=Math.floor,lt=function(t){return isNaN(t=+t)?0:(t>0?ct:ft)(t)},st=Math.min,mt=function(t){return t>0?st(lt(t),9007199254740991):0},gt=Math.max,dt=Math.min,ht=function(t){return function(n,o,r){var e,a=S(n),i=mt(a.length),u=function(t,n){var o=lt(t);return o<0?gt(o+n,0):dt(o,n)}(r,i);if(t&&o!=o){for(;i>u;)if((e=a[u++])!=e)return!0}else for(;i>u;u++)if((t||u in a)&&a[u]===o)return t||u||0;return!t&&-1}},pt={includes:ht(!0),indexOf:ht(!1)}.indexOf,wt=[\"constructor\",\"hasOwnProperty\",\"isPrototypeOf\",\"propertyIsEnumerable\",\"toLocaleString\",\"toString\",\"valueOf\"].concat(\"length\",\"prototype\"),St={f:Object.getOwnPropertyNames||function(t){return function(t,n){var o,r=S(t),e=0,a=[];for(o in r)!C(W,o)&&C(r,o)&&a.push(o);for(;n.length>e;)C(r,o=n[e++])&&(~pt(a,o)||a.push(o));return a}(t,wt)}},Pt={f:Object.getOwnPropertySymbols},Tt=ut(\"Reflect\",\"ownKeys\")||function(t){var n=St.f(y(t)),o=Pt.f;return o?n.concat(o(t)):n},Rt=function(t,n){for(var o=Tt(n),r=H.f,e=F.f,a=0;a<o.length;a++){var i=o[a];C(t,i)||r(t,i,e(n,i))}},Ct=/#|\\.prototype\\./,bt=function(t,n){var o=At[vt(t)];return o==Ft||o!=xt&&(\"function\"==typeof n?u(n):!!n)},vt=bt.normalize=function(t){return String(t).replace(Ct,\".\").toLowerCase()},At=bt.data={},xt=bt.NATIVE=\"N\",Ft=bt.POLYFILL=\"P\",yt=bt,kt=F.f,Ht=Array.isArray||function(t){return\"Array\"==d(t)},Ot=function(t){return Object(w(t))},Mt=function(t,n,o){var r=T(n);r in t?H.f(t,r,m(0,o)):t[r]=o},Et=\"process\"==d(i.process),Nt=ut(\"navigator\",\"userAgent\")||\"\",Dt=i.process,zt=Dt&&Dt.versions,Lt=zt&&zt.v8;Lt?ot=(nt=Lt.split(\".\"))[0]+nt[1]:Nt&&(!(nt=Nt.match(/Edge\\/(\\d+)/))||nt[1]>=74)&&(nt=Nt.match(/Chrome\\/(\\d+)/))&&(ot=nt[1]);var jt,Bt=ot&&+ot,Ut=!!Object.getOwnPropertySymbols&&!u((function(){return!Symbol.sham&&(Et?38===Bt:Bt>37&&Bt<41)})),Jt=Ut&&!Symbol.sham&&\"symbol\"==typeof Symbol.iterator,Gt=V(\"wks\"),Vt=i.Symbol,Zt=Jt?Vt:Vt&&Vt.withoutSetter||q,It=function(t){return C(Gt,t)&&(Ut||\"string\"==typeof Gt[t])||(Ut&&C(Vt,t)?Gt[t]=Vt[t]:Gt[t]=Zt(\"Symbol.\"+t)),Gt[t]},qt=It(\"species\"),Kt=function(t,n){var o;return Ht(t)&&(\"function\"!=typeof(o=t.constructor)||o!==Array&&!Ht(o.prototype)?P(o)&&null===(o=o[qt])&&(o=void 0):o=void 0),new(void 0===o?Array:o)(0===n?0:n)},Wt=It(\"species\"),Yt=It(\"isConcatSpreadable\"),_t=9007199254740991,Qt=\"Maximum allowed index exceeded\",Xt=Bt>=51||!u((function(){var t=[];return t[Yt]=!1,t.concat()[0]!==t})),\$t=(jt=\"concat\",Bt>=51||!u((function(){var t=[];return(t.constructor={})[Wt]=function(){return{foo:1}},1!==t[jt](Boolean).foo}))),tn=function(t){if(!P(t))return!1;var n=t[Yt];return void 0!==n?!!n:Ht(t)};!function(t,n){var o,r,e,a,u,f=t.target,c=t.global,l=t.stat;if(o=c?i:l?i[f]||M(f,{}):(i[f]||{}).prototype)for(r in n){if(a=n[r],e=t.noTargetGet?(u=kt(o,r))&&u.value:o[r],!yt(c?r:f+(l?\".\":\"#\")+r,t.forced)&&void 0!==e){if(typeof a==typeof e)continue;Rt(a,e)}(t.sham||e&&e.sham)&&O(a,\"sham\",!0),et(o,r,a,t)}}({target:\"Array\",proto:!0,forced:!Xt||!\$t},{concat:function(t){var n,o,r,e,a,i=Ot(this),u=Kt(i,0),f=0;for(n=-1,r=arguments.length;n<r;n++)if(tn(a=-1===n?i:arguments[n])){if(f+(e=mt(a.length))>_t)throw TypeError(Qt);for(o=0;o<e;o++,f++)o in a&&Mt(u,f,a[o])}else{if(f>=_t)throw TypeError(Qt);Mt(u,f++,a)}return u.length=f,u}}),o.default.fn.bootstrapTable.locales[\"af-ZA\"]=o.default.fn.bootstrapTable.locales.af={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Besig om te laai, wag asseblief\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" rekords per bladsy\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Resultate \".concat(t,\" tot \").concat(n,\" van \").concat(o,\" rye (filtered from \").concat(r,\" total rows)\"):\"Resultate \".concat(t,\" tot \").concat(n,\" van \").concat(o,\" rye\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Soek\"},formatNoMatches:function(){return\"Geen rekords gevind nie\"},formatPaginationSwitch:function(){return\"Wys/verberg bladsy nummering\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Herlaai\"},formatToggle:function(){return\"Wissel\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Kolomme\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"af-ZA\"]),o.default.fn.bootstrapTable.locales[\"ar-SA\"]=o.default.fn.bootstrapTable.locales.ar={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"جاري التحميل, يرجى الإنتظار\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" سجل لكل صفحة\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"الظاهر \".concat(t,\" إلى \").concat(n,\" من \").concat(o,\" سجل \").concat(r,\" total rows)\"):\"الظاهر \".concat(t,\" إلى \").concat(n,\" من \").concat(o,\" سجل\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"بحث\"},formatNoMatches:function(){return\"لا توجد نتائج مطابقة للبحث\"},formatPaginationSwitch:function(){return\"إخفاءإظهار ترقيم الصفحات\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"تحديث\"},formatToggle:function(){return\"تغيير\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"أعمدة\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"ar-SA\"]),o.default.fn.bootstrapTable.locales[\"bg-BG\"]=o.default.fn.bootstrapTable.locales.bg={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Зареждане, моля изчакайте\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" реда на страница\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Показани редове от \".concat(t,\" до \").concat(n,\" от \").concat(o,\" реда (филтрирани от общо \").concat(r,\" реда)\"):\"Показани редове от \".concat(t,\" до \").concat(n,\" от общо \").concat(o,\" реда\")},formatSRPaginationPreText:function(){return\"предишна страница\"},formatSRPaginationPageText:function(t){return\"до страница \".concat(t)},formatSRPaginationNextText:function(){return\"следваща страница\"},formatDetailPagination:function(t){return\"Показани \".concat(t,\" реда\")},formatClearSearch:function(){return\"Изчистване на търсенето\"},formatSearch:function(){return\"Търсене\"},formatNoMatches:function(){return\"Не са намерени съвпадащи записи\"},formatPaginationSwitch:function(){return\"Скриване/Показване на странициране\"},formatPaginationSwitchDown:function(){return\"Показване на странициране\"},formatPaginationSwitchUp:function(){return\"Скриване на странициране\"},formatRefresh:function(){return\"Обновяване\"},formatToggle:function(){return\"Превключване\"},formatToggleOn:function(){return\"Показване на изглед карта\"},formatToggleOff:function(){return\"Скриване на изглед карта\"},formatColumns:function(){return\"Колони\"},formatColumnsToggleAll:function(){return\"Превключване на всички\"},formatFullscreen:function(){return\"Цял екран\"},formatAllRows:function(){return\"Всички\"},formatAutoRefresh:function(){return\"Автоматично обновяване\"},formatExport:function(){return\"Експорт на данни\"},formatJumpTo:function(){return\"ОТИДИ\"},formatAdvancedSearch:function(){return\"Разширено търсене\"},formatAdvancedCloseButton:function(){return\"Затваряне\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"bg-BG\"]),o.default.fn.bootstrapTable.locales[\"ca-ES\"]=o.default.fn.bootstrapTable.locales.ca={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Espereu, si us plau\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" resultats per pàgina\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Mostrant de \".concat(t,\" fins \").concat(n,\" - total \").concat(o,\" resultats (filtered from \").concat(r,\" total rows)\"):\"Mostrant de \".concat(t,\" fins \").concat(n,\" - total \").concat(o,\" resultats\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Cerca\"},formatNoMatches:function(){return\"No s'han trobat resultats\"},formatPaginationSwitch:function(){return\"Amaga/Mostra paginació\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Refresca\"},formatToggle:function(){return\"Alterna formatació\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Columnes\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Tots\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"ca-ES\"]),o.default.fn.bootstrapTable.locales[\"cs-CZ\"]=o.default.fn.bootstrapTable.locales.cs={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Čekejte, prosím\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" položek na stránku\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Zobrazena \".concat(t,\". - \").concat(n,\" . položka z celkových \").concat(o,\" (filtered from \").concat(r,\" total rows)\"):\"Zobrazena \".concat(t,\". - \").concat(n,\" . položka z celkových \").concat(o)},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Vyhledávání\"},formatNoMatches:function(){return\"Nenalezena žádná vyhovující položka\"},formatPaginationSwitch:function(){return\"Skrýt/Zobrazit stránkování\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Aktualizovat\"},formatToggle:function(){return\"Přepni\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Sloupce\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Vše\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"cs-CZ\"]),o.default.fn.bootstrapTable.locales[\"da-DK\"]=o.default.fn.bootstrapTable.locales.da={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Indlæser, vent venligst\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" poster pr side\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Viser \".concat(t,\" til \").concat(n,\" af \").concat(o,\" række\").concat(o>1?\"r\":\"\",\" (filtered from \").concat(r,\" total rows)\"):\"Viser \".concat(t,\" til \").concat(n,\" af \").concat(o,\" række\").concat(o>1?\"r\":\"\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Viser \".concat(t,\" række\").concat(t>1?\"r\":\"\")},formatClearSearch:function(){return\"Ryd filtre\"},formatSearch:function(){return\"Søg\"},formatNoMatches:function(){return\"Ingen poster fundet\"},formatPaginationSwitch:function(){return\"Skjul/vis nummerering\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Opdater\"},formatToggle:function(){return\"Skift\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Kolonner\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Alle\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Eksporter\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"da-DK\"]),o.default.fn.bootstrapTable.locales[\"de-DE\"]=o.default.fn.bootstrapTable.locales.de={formatCopyRows:function(){return\"Zeilen kopieren\"},formatPrint:function(){return\"Drucken\"},formatLoadingMessage:function(){return\"Lade, bitte warten\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" Zeilen pro Seite.\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Zeige Zeile \".concat(t,\" bis \").concat(n,\" von \").concat(o,\" Zeile\").concat(o>1?\"n\":\"\",\" (Gefiltert von \").concat(r,\" Zeile\").concat(r>1?\"n\":\"\",\")\"):\"Zeige Zeile \".concat(t,\" bis \").concat(n,\" von \").concat(o,\" Zeile\").concat(o>1?\"n\":\"\",\".\")},formatSRPaginationPreText:function(){return\"Vorherige Seite\"},formatSRPaginationPageText:function(t){return\"Zu Seite \".concat(t)},formatSRPaginationNextText:function(){return\"Nächste Seite\"},formatDetailPagination:function(t){return\"Zeige \".concat(t,\" Zeile\").concat(t>1?\"n\":\"\",\".\")},formatClearSearch:function(){return\"Lösche Filter\"},formatSearch:function(){return\"Suchen\"},formatNoMatches:function(){return\"Keine passenden Ergebnisse gefunden\"},formatPaginationSwitch:function(){return\"Verstecke/Zeige Nummerierung\"},formatPaginationSwitchDown:function(){return\"Zeige Nummerierung\"},formatPaginationSwitchUp:function(){return\"Verstecke Nummerierung\"},formatRefresh:function(){return\"Neu laden\"},formatToggle:function(){return\"Umschalten\"},formatToggleOn:function(){return\"Normale Ansicht\"},formatToggleOff:function(){return\"Kartenansicht\"},formatColumns:function(){return\"Spalten\"},formatColumnsToggleAll:function(){return\"Alle umschalten\"},formatFullscreen:function(){return\"Vollbild\"},formatAllRows:function(){return\"Alle\"},formatAutoRefresh:function(){return\"Automatisches Neuladen\"},formatExport:function(){return\"Datenexport\"},formatJumpTo:function(){return\"Springen\"},formatAdvancedSearch:function(){return\"Erweiterte Suche\"},formatAdvancedCloseButton:function(){return\"Schließen\"},formatFilterControlSwitch:function(){return\"Verstecke/Zeige Filter\"},formatFilterControlSwitchHide:function(){return\"Verstecke Filter\"},formatFilterControlSwitchShow:function(){return\"Zeige Filter\"},formatAddLevel:function(){return\"Ebene hinzufügen\"},formatCancel:function(){return\"Abbrechen\"},formatColumn:function(){return\"Spalte\"},formatDeleteLevel:function(){return\"Ebene entfernen\"},formatDuplicateAlertTitle:function(){return\"Doppelte Einträge gefunden!\"},formatDuplicateAlertDescription:function(){return\"Bitte doppelte Spalten entfenen oder ändern\"},formatMultipleSort:function(){return\"Mehrfachsortierung\"},formatOrder:function(){return\"Reihenfolge\"},formatSort:function(){return\"Sortieren\"},formatSortBy:function(){return\"Sortieren nach\"},formatThenBy:function(){return\"anschließend\"},formatSortOrders:function(){return{asc:\"Aufsteigend\",desc:\"Absteigend\"}}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"de-DE\"]),o.default.fn.bootstrapTable.locales[\"el-GR\"]=o.default.fn.bootstrapTable.locales.el={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Φορτώνει, παρακαλώ περιμένετε\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" αποτελέσματα ανά σελίδα\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Εμφανίζονται από την \".concat(t,\" ως την \").concat(n,\" από σύνολο \").concat(o,\" σειρών (filtered from \").concat(r,\" total rows)\"):\"Εμφανίζονται από την \".concat(t,\" ως την \").concat(n,\" από σύνολο \").concat(o,\" σειρών\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Αναζητήστε\"},formatNoMatches:function(){return\"Δεν βρέθηκαν αποτελέσματα\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Refresh\"},formatToggle:function(){return\"Toggle\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Columns\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"el-GR\"]),o.default.fn.bootstrapTable.locales[\"en-US\"]=o.default.fn.bootstrapTable.locales.en={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Loading, please wait\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" rows per page\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Showing \".concat(t,\" to \").concat(n,\" of \").concat(o,\" rows (filtered from \").concat(r,\" total rows)\"):\"Showing \".concat(t,\" to \").concat(n,\" of \").concat(o,\" rows\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Search\"},formatNoMatches:function(){return\"No matching records found\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Refresh\"},formatToggle:function(){return\"Toggle\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Columns\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"en-US\"]),o.default.fn.bootstrapTable.locales[\"es-AR\"]={formatCopyRows:function(){return\"Copiar Filas\"},formatPrint:function(){return\"Imprimir\"},formatLoadingMessage:function(){return\"Cargando, espere por favor\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" registros por página\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Mostrando desde \".concat(t,\" a \").concat(n,\" de \").concat(o,\" filas (filtrado de \").concat(r,\" columnas totales)\"):\"Mostrando desde \".concat(t,\" a \").concat(n,\" de \").concat(o,\" filas\")},formatSRPaginationPreText:function(){return\"página anterior\"},formatSRPaginationPageText:function(t){return\"a la página \".concat(t)},formatSRPaginationNextText:function(){return\"siguiente página\"},formatDetailPagination:function(t){return\"Mostrando \".concat(t,\" columnas\")},formatClearSearch:function(){return\"Limpiar búsqueda\"},formatSearch:function(){return\"Buscar\"},formatNoMatches:function(){return\"No se encontraron registros\"},formatPaginationSwitch:function(){return\"Ocultar/Mostrar paginación\"},formatPaginationSwitchDown:function(){return\"Mostrar paginación\"},formatPaginationSwitchUp:function(){return\"Ocultar paginación\"},formatRefresh:function(){return\"Recargar\"},formatToggle:function(){return\"Cambiar\"},formatToggleOn:function(){return\"Mostrar vista de carta\"},formatToggleOff:function(){return\"Ocultar vista de carta\"},formatColumns:function(){return\"Columnas\"},formatColumnsToggleAll:function(){return\"Cambiar todo\"},formatFullscreen:function(){return\"Pantalla completa\"},formatAllRows:function(){return\"Todo\"},formatAutoRefresh:function(){return\"Auto Recargar\"},formatExport:function(){return\"Exportar datos\"},formatJumpTo:function(){return\"Ir\"},formatAdvancedSearch:function(){return\"Búsqueda avanzada\"},formatAdvancedCloseButton:function(){return\"Cerrar\"},formatFilterControlSwitch:function(){return\"Ocultar/Mostrar controles\"},formatFilterControlSwitchHide:function(){return\"Ocultar controles\"},formatFilterControlSwitchShow:function(){return\"Mostrar controles\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"es-AR\"]),o.default.fn.bootstrapTable.locales[\"es-CL\"]={formatCopyRows:function(){return\"Copiar Filas\"},formatPrint:function(){return\"Imprimir\"},formatLoadingMessage:function(){return\"Cargando, espere por favor\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" filas por página\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Mostrando \".concat(t,\" a \").concat(n,\" de \").concat(o,\" filas (filtrado de \").concat(r,\" filas totales)\"):\"Mostrando \".concat(t,\" a \").concat(n,\" de \").concat(o,\" filas\")},formatSRPaginationPreText:function(){return\"página anterior\"},formatSRPaginationPageText:function(t){return\"a la página \".concat(t)},formatSRPaginationNextText:function(){return\"siguiente página\"},formatDetailPagination:function(t){return\"Mostrando \".concat(t,\" filas\")},formatClearSearch:function(){return\"Limpiar búsqueda\"},formatSearch:function(){return\"Buscar\"},formatNoMatches:function(){return\"No se encontraron registros\"},formatPaginationSwitch:function(){return\"Ocultar/Mostrar paginación\"},formatPaginationSwitchDown:function(){return\"Mostrar paginación\"},formatPaginationSwitchUp:function(){return\"Ocultar paginación\"},formatRefresh:function(){return\"Refrescar\"},formatToggle:function(){return\"Cambiar\"},formatToggleOn:function(){return\"Mostrar vista de carta\"},formatToggleOff:function(){return\"Ocultar vista de carta\"},formatColumns:function(){return\"Columnas\"},formatColumnsToggleAll:function(){return\"Cambiar todo\"},formatFullscreen:function(){return\"Pantalla completa\"},formatAllRows:function(){return\"Todo\"},formatAutoRefresh:function(){return\"Auto Recargar\"},formatExport:function(){return\"Exportar datos\"},formatJumpTo:function(){return\"IR\"},formatAdvancedSearch:function(){return\"Búsqueda avanzada\"},formatAdvancedCloseButton:function(){return\"Cerrar\"},formatFilterControlSwitch:function(){return\"Ocultar/Mostrar controles\"},formatFilterControlSwitchHide:function(){return\"Ocultar controles\"},formatFilterControlSwitchShow:function(){return\"Mostrar controles\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"es-CL\"]),o.default.fn.bootstrapTable.locales[\"es-CR\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Cargando, por favor espere\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" registros por página\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Mostrando de \".concat(t,\" a \").concat(n,\" registros de \").concat(o,\" registros en total (filtered from \").concat(r,\" total rows)\"):\"Mostrando de \".concat(t,\" a \").concat(n,\" registros de \").concat(o,\" registros en total\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Limpiar búsqueda\"},formatSearch:function(){return\"Buscar\"},formatNoMatches:function(){return\"No se encontraron registros\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Refrescar\"},formatToggle:function(){return\"Alternar\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Columnas\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Todo\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Ocultar/Mostrar controles\"},formatFilterControlSwitchHide:function(){return\"Ocultar controles\"},formatFilterControlSwitchShow:function(){return\"Mostrar controles\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"es-CR\"]),o.default.fn.bootstrapTable.locales[\"es-ES\"]=o.default.fn.bootstrapTable.locales.es={formatCopyRows:function(){return\"Copiar filas\"},formatPrint:function(){return\"Imprimir\"},formatLoadingMessage:function(){return\"Por favor espere\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" resultados por página\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Mostrando desde \".concat(t,\" hasta \").concat(n,\" - En total \").concat(o,\" resultados (filtrado de \").concat(r,\" filas totales)\"):\"Mostrando desde \".concat(t,\" hasta \").concat(n,\" - En total \").concat(o,\" resultados\")},formatSRPaginationPreText:function(){return\"página anterior\"},formatSRPaginationPageText:function(t){return\"a la página \".concat(t)},formatSRPaginationNextText:function(){return\"siguiente página\"},formatDetailPagination:function(t){return\"Mostrando \".concat(t,\" filas\")},formatClearSearch:function(){return\"Limpiar búsqueda\"},formatSearch:function(){return\"Buscar\"},formatNoMatches:function(){return\"No se encontraron resultados\"},formatPaginationSwitch:function(){return\"Ocultar/Mostrar paginación\"},formatPaginationSwitchDown:function(){return\"Mostrar paginación\"},formatPaginationSwitchUp:function(){return\"Ocultar paginación\"},formatRefresh:function(){return\"Recargar\"},formatToggle:function(){return\"Ocultar/Mostrar\"},formatToggleOn:function(){return\"Mostrar vista de carta\"},formatToggleOff:function(){return\"Ocultar vista de carta\"},formatColumns:function(){return\"Columnas\"},formatColumnsToggleAll:function(){return\"Cambiar todo\"},formatFullscreen:function(){return\"Pantalla completa\"},formatAllRows:function(){return\"Todos\"},formatAutoRefresh:function(){return\"Auto Recargar\"},formatExport:function(){return\"Exportar los datos\"},formatJumpTo:function(){return\"IR\"},formatAdvancedSearch:function(){return\"Búsqueda avanzada\"},formatAdvancedCloseButton:function(){return\"Cerrar\"},formatFilterControlSwitch:function(){return\"Ocultar/Mostrar controles\"},formatFilterControlSwitchHide:function(){return\"Ocultar controles\"},formatFilterControlSwitchShow:function(){return\"Mostrar controles\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"es-ES\"]),o.default.fn.bootstrapTable.locales[\"es-MX\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Cargando, espere por favor\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" registros por página\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Mostrando \".concat(t,\" a \").concat(n,\" de \").concat(o,\" filas (filtered from \").concat(r,\" total rows)\"):\"Mostrando \".concat(t,\" a \").concat(n,\" de \").concat(o,\" filas\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Mostrando \".concat(t,\" filas\")},formatClearSearch:function(){return\"Limpiar búsqueda\"},formatSearch:function(){return\"Buscar\"},formatNoMatches:function(){return\"No se encontraron registros que coincidan\"},formatPaginationSwitch:function(){return\"Mostrar/ocultar paginación\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Actualizar\"},formatToggle:function(){return\"Cambiar vista\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Columnas\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Pantalla completa\"},formatAllRows:function(){return\"Todo\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Ocultar/Mostrar controles\"},formatFilterControlSwitchHide:function(){return\"Ocultar controles\"},formatFilterControlSwitchShow:function(){return\"Mostrar controles\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"es-MX\"]),o.default.fn.bootstrapTable.locales[\"es-NI\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Cargando, por favor espere\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" registros por página\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Mostrando de \".concat(t,\" a \").concat(n,\" registros de \").concat(o,\" registros en total (filtered from \").concat(r,\" total rows)\"):\"Mostrando de \".concat(t,\" a \").concat(n,\" registros de \").concat(o,\" registros en total\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Limpiar búsqueda\"},formatSearch:function(){return\"Buscar\"},formatNoMatches:function(){return\"No se encontraron registros\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Refrescar\"},formatToggle:function(){return\"Alternar\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Columnas\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Todo\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Ocultar/Mostrar controles\"},formatFilterControlSwitchHide:function(){return\"Ocultar controles\"},formatFilterControlSwitchShow:function(){return\"Mostrar controles\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"es-NI\"]),o.default.fn.bootstrapTable.locales[\"es-SP\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Cargando, por favor espera\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" registros por p&#225;gina.\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"\".concat(t,\" - \").concat(n,\" de \").concat(o,\" registros (filtered from \").concat(r,\" total rows)\"):\"\".concat(t,\" - \").concat(n,\" de \").concat(o,\" registros.\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Limpiar búsqueda\"},formatSearch:function(){return\"Buscar\"},formatNoMatches:function(){return\"No se han encontrado registros.\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Actualizar\"},formatToggle:function(){return\"Alternar\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Columnas\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Todo\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Ocultar/Mostrar controles\"},formatFilterControlSwitchHide:function(){return\"Ocultar controles\"},formatFilterControlSwitchShow:function(){return\"Mostrar controles\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"es-SP\"]),o.default.fn.bootstrapTable.locales[\"et-EE\"]=o.default.fn.bootstrapTable.locales.et={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Päring käib, palun oota\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" rida lehe kohta\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Näitan tulemusi \".concat(t,\" kuni \").concat(n,\" - kokku \").concat(o,\" tulemust (filtered from \").concat(r,\" total rows)\"):\"Näitan tulemusi \".concat(t,\" kuni \").concat(n,\" - kokku \").concat(o,\" tulemust\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Otsi\"},formatNoMatches:function(){return\"Päringu tingimustele ei vastanud ühtegi tulemust\"},formatPaginationSwitch:function(){return\"Näita/Peida lehtedeks jagamine\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Värskenda\"},formatToggle:function(){return\"Lülita\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Veerud\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Kõik\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"et-EE\"]),o.default.fn.bootstrapTable.locales[\"eu-EU\"]=o.default.fn.bootstrapTable.locales.eu={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Itxaron mesedez\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" emaitza orriko.\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"\".concat(o,\" erregistroetatik \").concat(t,\"etik \").concat(n,\"erakoak erakusten (filtered from \").concat(r,\" total rows)\"):\"\".concat(o,\" erregistroetatik \").concat(t,\"etik \").concat(n,\"erakoak erakusten.\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Bilatu\"},formatNoMatches:function(){return\"Ez da emaitzarik aurkitu\"},formatPaginationSwitch:function(){return\"Ezkutatu/Erakutsi orrikatzea\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Eguneratu\"},formatToggle:function(){return\"Ezkutatu/Erakutsi\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Zutabeak\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Guztiak\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"eu-EU\"]),o.default.fn.bootstrapTable.locales[\"fa-IR\"]=o.default.fn.bootstrapTable.locales.fa={formatCopyRows:function(){return\"کپی ردیف ها\"},formatPrint:function(){return\"پرینت\"},formatLoadingMessage:function(){return\"در حال بارگذاری, لطفا صبر کنید\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" رکورد در صفحه\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"نمایش \".concat(t,\" تا \").concat(n,\" از \").concat(o,\" ردیف (filtered from \").concat(r,\" total rows)\"):\"نمایش \".concat(t,\" تا \").concat(n,\" از \").concat(o,\" ردیف\")},formatSRPaginationPreText:function(){return\"صفحه قبلی\"},formatSRPaginationPageText:function(t){return\"به صفحه \".concat(t)},formatSRPaginationNextText:function(){return\"صفحه بعدی\"},formatDetailPagination:function(t){return\"نمایش \".concat(t,\" سطرها\")},formatClearSearch:function(){return\"پاک کردن جستجو\"},formatSearch:function(){return\"جستجو\"},formatNoMatches:function(){return\"رکوردی یافت نشد.\"},formatPaginationSwitch:function(){return\"نمایش/مخفی صفحه بندی\"},formatPaginationSwitchDown:function(){return\"نمایش صفحه بندی\"},formatPaginationSwitchUp:function(){return\"پنهان کردن صفحه بندی\"},formatRefresh:function(){return\"به روز رسانی\"},formatToggle:function(){return\"تغییر نمایش\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"سطر ها\"},formatColumnsToggleAll:function(){return\"تغییر وضعیت همه\"},formatFullscreen:function(){return\"تمام صفحه\"},formatAllRows:function(){return\"همه\"},formatAutoRefresh:function(){return\"رفرش اتوماتیک\"},formatExport:function(){return\"خروجی دیتا\"},formatJumpTo:function(){return\"برو\"},formatAdvancedSearch:function(){return\"جستجوی پیشرفته\"},formatAdvancedCloseButton:function(){return\"بستن\"},formatFilterControlSwitch:function(){return\"پنهان/نمایش دادن کنترل ها\"},formatFilterControlSwitchHide:function(){return\"پنهان کردن کنترل ها\"},formatFilterControlSwitchShow:function(){return\"نمایش کنترل ها\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"fa-IR\"]),o.default.fn.bootstrapTable.locales[\"fi-FI\"]=o.default.fn.bootstrapTable.locales.fi={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Ladataan, ole hyvä ja odota\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" riviä sivulla\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Näytetään rivit \".concat(t,\" - \").concat(n,\" / \").concat(o,\" (filtered from \").concat(r,\" total rows)\"):\"Näytetään rivit \".concat(t,\" - \").concat(n,\" / \").concat(o)},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Poista suodattimet\"},formatSearch:function(){return\"Hae\"},formatNoMatches:function(){return\"Hakuehtoja vastaavia tuloksia ei löytynyt\"},formatPaginationSwitch:function(){return\"Näytä/Piilota sivutus\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Päivitä\"},formatToggle:function(){return\"Valitse\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Sarakkeet\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Kaikki\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Vie tiedot\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"fi-FI\"]),o.default.fn.bootstrapTable.locales[\"fr-BE\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Chargement en cours\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" lignes par page\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Affiche de \".concat(t,\" à \").concat(n,\" sur \").concat(o,\" lignes (filtrés à partir de \").concat(r,\" lignes)\"):\"Affiche de \".concat(t,\" à \").concat(n,\" sur \").concat(o,\" lignes\")},formatSRPaginationPreText:function(){return\"page précédente\"},formatSRPaginationPageText:function(t){return\"vers la page \".concat(t)},formatSRPaginationNextText:function(){return\"page suivante\"},formatDetailPagination:function(t){return\"Affiche \".concat(t,\" lignes\")},formatClearSearch:function(){return\"Effacer la recherche\"},formatSearch:function(){return\"Recherche\"},formatNoMatches:function(){return\"Pas de lignes trouvés\"},formatPaginationSwitch:function(){return\"Cacher/Afficher pagination\"},formatPaginationSwitchDown:function(){return\"Afficher pagination\"},formatPaginationSwitchUp:function(){return\"Cacher pagination\"},formatRefresh:function(){return\"Rafraichir\"},formatToggle:function(){return\"Basculer\"},formatToggleOn:function(){return\"Afficher vue carte\"},formatToggleOff:function(){return\"Cacher vue carte\"},formatColumns:function(){return\"Colonnes\"},formatColumnsToggleAll:function(){return\"Tout basculer\"},formatFullscreen:function(){return\"Plein écran\"},formatAllRows:function(){return\"Tout\"},formatAutoRefresh:function(){return\"Rafraîchissement automatique\"},formatExport:function(){return\"Exporter les données\"},formatJumpTo:function(){return\"Aller à\"},formatAdvancedSearch:function(){return\"Recherche avancée\"},formatAdvancedCloseButton:function(){return\"Fermer\"},formatFilterControlSwitch:function(){return\"Cacher/Afficher controls\"},formatFilterControlSwitchHide:function(){return\"Cacher controls\"},formatFilterControlSwitchShow:function(){return\"Afficher controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"fr-BE\"]),o.default.fn.bootstrapTable.locales[\"fr-CH\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Chargement en cours\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" lignes par page\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Affiche de \".concat(t,\" à \").concat(n,\" sur \").concat(o,\" lignes (filtrés à partir de \").concat(r,\" lignes)\"):\"Affiche de \".concat(t,\" à \").concat(n,\" sur \").concat(o,\" lignes\")},formatSRPaginationPreText:function(){return\"page précédente\"},formatSRPaginationPageText:function(t){return\"vers la page \".concat(t)},formatSRPaginationNextText:function(){return\"page suivante\"},formatDetailPagination:function(t){return\"Affiche \".concat(t,\" lignes\")},formatClearSearch:function(){return\"Effacer la recherche\"},formatSearch:function(){return\"Recherche\"},formatNoMatches:function(){return\"Pas de lignes trouvés\"},formatPaginationSwitch:function(){return\"Cacher/Afficher pagination\"},formatPaginationSwitchDown:function(){return\"Afficher pagination\"},formatPaginationSwitchUp:function(){return\"Cacher pagination\"},formatRefresh:function(){return\"Rafraichir\"},formatToggle:function(){return\"Basculer\"},formatToggleOn:function(){return\"Afficher vue carte\"},formatToggleOff:function(){return\"Cacher vue carte\"},formatColumns:function(){return\"Colonnes\"},formatColumnsToggleAll:function(){return\"Tout basculer\"},formatFullscreen:function(){return\"Plein écran\"},formatAllRows:function(){return\"Tout\"},formatAutoRefresh:function(){return\"Rafraîchissement automatique\"},formatExport:function(){return\"Exporter les données\"},formatJumpTo:function(){return\"Aller à\"},formatAdvancedSearch:function(){return\"Recherche avancée\"},formatAdvancedCloseButton:function(){return\"Fermer\"},formatFilterControlSwitch:function(){return\"Cacher/Afficher controls\"},formatFilterControlSwitchHide:function(){return\"Cacher controls\"},formatFilterControlSwitchShow:function(){return\"Afficher controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"fr-CH\"]),o.default.fn.bootstrapTable.locales[\"fr-FR\"]=o.default.fn.bootstrapTable.locales.fr={formatCopyRows:function(){return\"Copier les lignes\"},formatPrint:function(){return\"Imprimer\"},formatLoadingMessage:function(){return\"Chargement en cours\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" lignes par page\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Affiche de \".concat(t,\" à \").concat(n,\" sur \").concat(o,\" lignes (filtrés à partir de \").concat(r,\" lignes)\"):\"Affiche de \".concat(t,\" à \").concat(n,\" sur \").concat(o,\" lignes\")},formatSRPaginationPreText:function(){return\"page précédente\"},formatSRPaginationPageText:function(t){return\"vers la page \".concat(t)},formatSRPaginationNextText:function(){return\"page suivante\"},formatDetailPagination:function(t){return\"Affiche \".concat(t,\" lignes\")},formatClearSearch:function(){return\"Effacer la recherche\"},formatSearch:function(){return\"Recherche\"},formatNoMatches:function(){return\"Aucun résultat\"},formatPaginationSwitch:function(){return\"Masquer/Afficher la pagination\"},formatPaginationSwitchDown:function(){return\"Afficher la pagination\"},formatPaginationSwitchUp:function(){return\"Masquer la pagination\"},formatRefresh:function(){return\"Actualiser\"},formatToggle:function(){return\"Basculer\"},formatToggleOn:function(){return\"Afficher la vue carte\"},formatToggleOff:function(){return\"Masquer la vue carte\"},formatColumns:function(){return\"Colonnes\"},formatColumnsToggleAll:function(){return\"Tout basculer\"},formatFullscreen:function(){return\"Plein écran\"},formatAllRows:function(){return\"Tout\"},formatAutoRefresh:function(){return\"Actualisation automatique\"},formatExport:function(){return\"Exporter les données\"},formatJumpTo:function(){return\"ALLER\"},formatAdvancedSearch:function(){return\"Recherche avancée\"},formatAdvancedCloseButton:function(){return\"Fermer\"},formatFilterControlSwitch:function(){return\"Masquer/Afficher les contrôles\"},formatFilterControlSwitchHide:function(){return\"Masquer les contrôles\"},formatFilterControlSwitchShow:function(){return\"Afficher les contrôles\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"fr-FR\"]),o.default.fn.bootstrapTable.locales[\"fr-LU\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Chargement en cours\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" lignes par page\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Affiche de \".concat(t,\" à \").concat(n,\" sur \").concat(o,\" lignes (filtrés à partir de \").concat(r,\" lignes)\"):\"Affiche de \".concat(t,\" à \").concat(n,\" sur \").concat(o,\" lignes\")},formatSRPaginationPreText:function(){return\"page précédente\"},formatSRPaginationPageText:function(t){return\"vers la page \".concat(t)},formatSRPaginationNextText:function(){return\"page suivante\"},formatDetailPagination:function(t){return\"Affiche \".concat(t,\" lignes\")},formatClearSearch:function(){return\"Effacer la recherche\"},formatSearch:function(){return\"Recherche\"},formatNoMatches:function(){return\"Pas de lignes trouvés\"},formatPaginationSwitch:function(){return\"Cacher/Afficher pagination\"},formatPaginationSwitchDown:function(){return\"Afficher pagination\"},formatPaginationSwitchUp:function(){return\"Cacher pagination\"},formatRefresh:function(){return\"Rafraichir\"},formatToggle:function(){return\"Basculer\"},formatToggleOn:function(){return\"Afficher vue carte\"},formatToggleOff:function(){return\"Cacher vue carte\"},formatColumns:function(){return\"Colonnes\"},formatColumnsToggleAll:function(){return\"Tout basculer\"},formatFullscreen:function(){return\"Plein écran\"},formatAllRows:function(){return\"Tout\"},formatAutoRefresh:function(){return\"Rafraîchissement automatique\"},formatExport:function(){return\"Exporter les données\"},formatJumpTo:function(){return\"Aller à\"},formatAdvancedSearch:function(){return\"Recherche avancée\"},formatAdvancedCloseButton:function(){return\"Fermer\"},formatFilterControlSwitch:function(){return\"Cacher/Afficher controls\"},formatFilterControlSwitchHide:function(){return\"Cacher controls\"},formatFilterControlSwitchShow:function(){return\"Afficher controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"fr-LU\"]),o.default.fn.bootstrapTable.locales[\"he-IL\"]=o.default.fn.bootstrapTable.locales.he={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"טוען, נא להמתין\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" שורות בעמוד\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"מציג \".concat(t,\" עד \").concat(n,\" מ-\").concat(o,\"שורות\").concat(r,\" total rows)\"):\"מציג \".concat(t,\" עד \").concat(n,\" מ-\").concat(o,\" שורות\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"חיפוש\"},formatNoMatches:function(){return\"לא נמצאו רשומות תואמות\"},formatPaginationSwitch:function(){return\"הסתר/הצג מספור דפים\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"רענן\"},formatToggle:function(){return\"החלף תצוגה\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"עמודות\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"הכל\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"he-IL\"]),o.default.fn.bootstrapTable.locales[\"hr-HR\"]=o.default.fn.bootstrapTable.locales.hr={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Molimo pričekajte\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" broj zapisa po stranici\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Prikazujem \".concat(t,\". - \").concat(n,\". od ukupnog broja zapisa \").concat(o,\" (filtered from \").concat(r,\" total rows)\"):\"Prikazujem \".concat(t,\". - \").concat(n,\". od ukupnog broja zapisa \").concat(o)},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Pretraži\"},formatNoMatches:function(){return\"Nije pronađen niti jedan zapis\"},formatPaginationSwitch:function(){return\"Prikaži/sakrij stranice\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Osvježi\"},formatToggle:function(){return\"Promijeni prikaz\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Kolone\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Sve\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"hr-HR\"]),o.default.fn.bootstrapTable.locales[\"hu-HU\"]=o.default.fn.bootstrapTable.locales.hu={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Betöltés, kérem várjon\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" rekord per oldal\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Megjelenítve \".concat(t,\" - \").concat(n,\" / \").concat(o,\" összesen (filtered from \").concat(r,\" total rows)\"):\"Megjelenítve \".concat(t,\" - \").concat(n,\" / \").concat(o,\" összesen\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Keresés\"},formatNoMatches:function(){return\"Nincs találat\"},formatPaginationSwitch:function(){return\"Lapozó elrejtése/megjelenítése\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Frissítés\"},formatToggle:function(){return\"Összecsuk/Kinyit\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Oszlopok\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Összes\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"hu-HU\"]),o.default.fn.bootstrapTable.locales[\"id-ID\"]=o.default.fn.bootstrapTable.locales.id={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Memuat, mohon tunggu\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" baris per halaman\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Menampilkan \".concat(t,\" sampai \").concat(n,\" dari \").concat(o,\" baris (filtered from \").concat(r,\" total rows)\"):\"Menampilkan \".concat(t,\" sampai \").concat(n,\" dari \").concat(o,\" baris\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Bersihkan filter\"},formatSearch:function(){return\"Pencarian\"},formatNoMatches:function(){return\"Tidak ditemukan data yang cocok\"},formatPaginationSwitch:function(){return\"Sembunyikan/Tampilkan halaman\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Muat ulang\"},formatToggle:function(){return\"Beralih\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"kolom\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Semua\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Ekspor data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"id-ID\"]),o.default.fn.bootstrapTable.locales[\"it-IT\"]=o.default.fn.bootstrapTable.locales.it={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Caricamento in corso\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" elementi per pagina\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Visualizzazione da \".concat(t,\" a \").concat(n,\" di \").concat(o,\" elementi (filtrati da \").concat(r,\" elementi totali)\"):\"Visualizzazione da \".concat(t,\" a \").concat(n,\" di \").concat(o,\" elementi\")},formatSRPaginationPreText:function(){return\"pagina precedente\"},formatSRPaginationPageText:function(t){return\"alla pagina \".concat(t)},formatSRPaginationNextText:function(){return\"pagina successiva\"},formatDetailPagination:function(t){return\"Mostrando \".concat(t,\" elementi\")},formatClearSearch:function(){return\"Pulisci filtri\"},formatSearch:function(){return\"Cerca\"},formatNoMatches:function(){return\"Nessun elemento trovato\"},formatPaginationSwitch:function(){return\"Nascondi/Mostra paginazione\"},formatPaginationSwitchDown:function(){return\"Mostra paginazione\"},formatPaginationSwitchUp:function(){return\"Nascondi paginazione\"},formatRefresh:function(){return\"Aggiorna\"},formatToggle:function(){return\"Attiva/Disattiva\"},formatToggleOn:function(){return\"Mostra visuale a scheda\"},formatToggleOff:function(){return\"Nascondi visuale a scheda\"},formatColumns:function(){return\"Colonne\"},formatColumnsToggleAll:function(){return\"Mostra tutte\"},formatFullscreen:function(){return\"Schermo intero\"},formatAllRows:function(){return\"Tutto\"},formatAutoRefresh:function(){return\"Auto Aggiornamento\"},formatExport:function(){return\"Esporta dati\"},formatJumpTo:function(){return\"VAI\"},formatAdvancedSearch:function(){return\"Filtri avanzati\"},formatAdvancedCloseButton:function(){return\"Chiudi\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"it-IT\"]),o.default.fn.bootstrapTable.locales[\"ja-JP\"]=o.default.fn.bootstrapTable.locales.ja={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"読み込み中です。少々お待ちください。\"},formatRecordsPerPage:function(t){return\"ページ当たり最大\".concat(t,\"件\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"全\".concat(o,\"件から、\").concat(t,\"から\").concat(n,\"件目まで表示しています (filtered from \").concat(r,\" total rows)\"):\"全\".concat(o,\"件から、\").concat(t,\"から\").concat(n,\"件目まで表示しています\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"検索\"},formatNoMatches:function(){return\"該当するレコードが見つかりません\"},formatPaginationSwitch:function(){return\"ページ数を表示・非表示\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"更新\"},formatToggle:function(){return\"トグル\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"列\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"すべて\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"ja-JP\"]),o.default.fn.bootstrapTable.locales[\"ka-GE\"]=o.default.fn.bootstrapTable.locales.ka={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"იტვირთება, გთხოვთ მოიცადოთ\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" ჩანაწერი თითო გვერდზე\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"ნაჩვენებია \".concat(t,\"-დან \").concat(n,\"-მდე ჩანაწერი ჯამური \").concat(o,\"-დან (filtered from \").concat(r,\" total rows)\"):\"ნაჩვენებია \".concat(t,\"-დან \").concat(n,\"-მდე ჩანაწერი ჯამური \").concat(o,\"-დან\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"ძებნა\"},formatNoMatches:function(){return\"მონაცემები არ არის\"},formatPaginationSwitch:function(){return\"გვერდების გადამრთველის დამალვა/გამოჩენა\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"განახლება\"},formatToggle:function(){return\"ჩართვა/გამორთვა\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"სვეტები\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"ka-GE\"]),o.default.fn.bootstrapTable.locales[\"ko-KR\"]=o.default.fn.bootstrapTable.locales.ko={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"데이터를 불러오는 중입니다\"},formatRecordsPerPage:function(t){return\"페이지 당 \".concat(t,\"개 데이터 출력\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"전체 \".concat(o,\"개 중 \").concat(t,\"~\").concat(n,\"번째 데이터 출력, (filtered from \").concat(r,\" total rows)\"):\"전체 \".concat(o,\"개 중 \").concat(t,\"~\").concat(n,\"번째 데이터 출력,\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"검색\"},formatNoMatches:function(){return\"조회된 데이터가 없습니다.\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"새로 고침\"},formatToggle:function(){return\"전환\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"컬럼 필터링\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"ko-KR\"]),o.default.fn.bootstrapTable.locales[\"ms-MY\"]=o.default.fn.bootstrapTable.locales.ms={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Permintaan sedang dimuatkan. Sila tunggu sebentar\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" rekod setiap muka surat\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Sedang memaparkan rekod \".concat(t,\" hingga \").concat(n,\" daripada jumlah \").concat(o,\" rekod (filtered from \").concat(r,\" total rows)\"):\"Sedang memaparkan rekod \".concat(t,\" hingga \").concat(n,\" daripada jumlah \").concat(o,\" rekod\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Cari\"},formatNoMatches:function(){return\"Tiada rekod yang menyamai permintaan\"},formatPaginationSwitch:function(){return\"Tunjuk/sembunyi muka surat\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Muatsemula\"},formatToggle:function(){return\"Tukar\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Lajur\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Semua\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"ms-MY\"]),o.default.fn.bootstrapTable.locales[\"nb-NO\"]=o.default.fn.bootstrapTable.locales.nb={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Oppdaterer, vennligst vent\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" poster pr side\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Viser \".concat(t,\" til \").concat(n,\" av \").concat(o,\" rekker (filtered from \").concat(r,\" total rows)\"):\"Viser \".concat(t,\" til \").concat(n,\" av \").concat(o,\" rekker\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Søk\"},formatNoMatches:function(){return\"Ingen poster funnet\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Oppdater\"},formatToggle:function(){return\"Endre\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Kolonner\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"nb-NO\"]),o.default.fn.bootstrapTable.locales[\"nl-BE\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Laden, even geduld\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" records per pagina\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Toon \".concat(t,\" tot \").concat(n,\" van \").concat(o,\" record\").concat(o>1?\"s\":\"\",\" (gefilterd van \").concat(r,\" records in totaal)\"):\"Toon \".concat(t,\" tot \").concat(n,\" van \").concat(o,\" record\").concat(o>1?\"s\":\"\")},formatSRPaginationPreText:function(){return\"vorige pagina\"},formatSRPaginationPageText:function(t){return\"tot pagina \".concat(t)},formatSRPaginationNextText:function(){return\"volgende pagina\"},formatDetailPagination:function(t){return\"Toon \".concat(t,\" record\").concat(t>1?\"s\":\"\")},formatClearSearch:function(){return\"Verwijder filters\"},formatSearch:function(){return\"Zoeken\"},formatNoMatches:function(){return\"Geen resultaten gevonden\"},formatPaginationSwitch:function(){return\"Verberg/Toon paginering\"},formatPaginationSwitchDown:function(){return\"Toon paginering\"},formatPaginationSwitchUp:function(){return\"Verberg paginering\"},formatRefresh:function(){return\"Vernieuwen\"},formatToggle:function(){return\"Omschakelen\"},formatToggleOn:function(){return\"Toon kaartweergave\"},formatToggleOff:function(){return\"Verberg kaartweergave\"},formatColumns:function(){return\"Kolommen\"},formatColumnsToggleAll:function(){return\"Allen omschakelen\"},formatFullscreen:function(){return\"Volledig scherm\"},formatAllRows:function(){return\"Alle\"},formatAutoRefresh:function(){return\"Automatisch vernieuwen\"},formatExport:function(){return\"Exporteer gegevens\"},formatJumpTo:function(){return\"GA\"},formatAdvancedSearch:function(){return\"Geavanceerd zoeken\"},formatAdvancedCloseButton:function(){return\"Sluiten\"},formatFilterControlSwitch:function(){return\"Verberg/Toon controls\"},formatFilterControlSwitchHide:function(){return\"Verberg controls\"},formatFilterControlSwitchShow:function(){return\"Toon controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"nl-BE\"]),o.default.fn.bootstrapTable.locales[\"nl-NL\"]=o.default.fn.bootstrapTable.locales.nl={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Laden, even geduld\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" records per pagina\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Toon \".concat(t,\" tot \").concat(n,\" van \").concat(o,\" record\").concat(o>1?\"s\":\"\",\" (gefilterd van \").concat(r,\" records in totaal)\"):\"Toon \".concat(t,\" tot \").concat(n,\" van \").concat(o,\" record\").concat(o>1?\"s\":\"\")},formatSRPaginationPreText:function(){return\"vorige pagina\"},formatSRPaginationPageText:function(t){return\"tot pagina \".concat(t)},formatSRPaginationNextText:function(){return\"volgende pagina\"},formatDetailPagination:function(t){return\"Toon \".concat(t,\" record\").concat(t>1?\"s\":\"\")},formatClearSearch:function(){return\"Verwijder filters\"},formatSearch:function(){return\"Zoeken\"},formatNoMatches:function(){return\"Geen resultaten gevonden\"},formatPaginationSwitch:function(){return\"Verberg/Toon paginering\"},formatPaginationSwitchDown:function(){return\"Toon paginering\"},formatPaginationSwitchUp:function(){return\"Verberg paginering\"},formatRefresh:function(){return\"Vernieuwen\"},formatToggle:function(){return\"Omschakelen\"},formatToggleOn:function(){return\"Toon kaartweergave\"},formatToggleOff:function(){return\"Verberg kaartweergave\"},formatColumns:function(){return\"Kolommen\"},formatColumnsToggleAll:function(){return\"Allen omschakelen\"},formatFullscreen:function(){return\"Volledig scherm\"},formatAllRows:function(){return\"Alle\"},formatAutoRefresh:function(){return\"Automatisch vernieuwen\"},formatExport:function(){return\"Exporteer gegevens\"},formatJumpTo:function(){return\"GA\"},formatAdvancedSearch:function(){return\"Geavanceerd zoeken\"},formatAdvancedCloseButton:function(){return\"Sluiten\"},formatFilterControlSwitch:function(){return\"Verberg/Toon controls\"},formatFilterControlSwitchHide:function(){return\"Verberg controls\"},formatFilterControlSwitchShow:function(){return\"Toon controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"nl-NL\"]),o.default.fn.bootstrapTable.locales[\"pl-PL\"]=o.default.fn.bootstrapTable.locales.pl={formatCopyRows:function(){return\"Kopiuj wiersze\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Ładowanie, proszę czekać\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" rekordów na stronę\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Wyświetlanie rekordów od \".concat(t,\" do \").concat(n,\" z \").concat(o,\" (filtered from \").concat(r,\" total rows)\"):\"Wyświetlanie rekordów od \".concat(t,\" do \").concat(n,\" z \").concat(o)},formatSRPaginationPreText:function(){return\"poprzednia strona\"},formatSRPaginationPageText:function(t){return\"z \".concat(t)},formatSRPaginationNextText:function(){return\"następna strona\"},formatDetailPagination:function(t){return\"Wyświetla \".concat(t,\" wierszy\")},formatClearSearch:function(){return\"Wyczyść wyszukiwanie\"},formatSearch:function(){return\"Szukaj\"},formatNoMatches:function(){return\"Niestety, nic nie znaleziono\"},formatPaginationSwitch:function(){return\"Pokaż/ukryj stronicowanie\"},formatPaginationSwitchDown:function(){return\"Pokaż stronicowanie\"},formatPaginationSwitchUp:function(){return\"Ukryj stronicowanie\"},formatRefresh:function(){return\"Odśwież\"},formatToggle:function(){return\"Przełącz\"},formatToggleOn:function(){return\"Pokaż układ karty\"},formatToggleOff:function(){return\"Ukryj układ karty\"},formatColumns:function(){return\"Kolumny\"},formatColumnsToggleAll:function(){return\"Zaznacz wszystko\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Wszystkie\"},formatAutoRefresh:function(){return\"Auto odświeżanie\"},formatExport:function(){return\"Eksport danych\"},formatJumpTo:function(){return\"Przejdź\"},formatAdvancedSearch:function(){return\"Wyszukiwanie zaawansowane\"},formatAdvancedCloseButton:function(){return\"Zamknij\"},formatFilterControlSwitch:function(){return\"Pokaż/Ukryj\"},formatFilterControlSwitchHide:function(){return\"Pokaż\"},formatFilterControlSwitchShow:function(){return\"Ukryj\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"pl-PL\"]),o.default.fn.bootstrapTable.locales[\"pt-BR\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Carregando, aguarde\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" registros por página\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Exibindo \".concat(t,\" até \").concat(n,\" de \").concat(o,\" linhas (filtradas de um total de \").concat(r,\" linhas)\"):\"Exibindo \".concat(t,\" até \").concat(n,\" de \").concat(o,\" linhas\")},formatSRPaginationPreText:function(){return\"página anterior\"},formatSRPaginationPageText:function(t){return\"Para a página \".concat(t)},formatSRPaginationNextText:function(){return\"próxima página\"},formatDetailPagination:function(t){return\"Mostrando \".concat(t,\" linhas\")},formatClearSearch:function(){return\"Limpar Pesquisa\"},formatSearch:function(){return\"Pesquisar\"},formatNoMatches:function(){return\"Nenhum registro encontrado\"},formatPaginationSwitch:function(){return\"Ocultar/Exibir paginação\"},formatPaginationSwitchDown:function(){return\"Mostrar Paginação\"},formatPaginationSwitchUp:function(){return\"Esconder Paginação\"},formatRefresh:function(){return\"Recarregar\"},formatToggle:function(){return\"Alternar\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Colunas\"},formatColumnsToggleAll:function(){return\"Alternar tudo\"},formatFullscreen:function(){return\"Tela cheia\"},formatAllRows:function(){return\"Tudo\"},formatAutoRefresh:function(){return\"Atualização Automática\"},formatExport:function(){return\"Exportar dados\"},formatJumpTo:function(){return\"IR\"},formatAdvancedSearch:function(){return\"Pesquisa Avançada\"},formatAdvancedCloseButton:function(){return\"Fechar\"},formatFilterControlSwitch:function(){return\"Ocultar/Exibir controles\"},formatFilterControlSwitchHide:function(){return\"Ocultar controles\"},formatFilterControlSwitchShow:function(){return\"Exibir controles\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"pt-BR\"]),o.default.fn.bootstrapTable.locales[\"pt-PT\"]=o.default.fn.bootstrapTable.locales.pt={formatCopyRows:function(){return\"Copiar Linhas\"},formatPrint:function(){return\"Imprimir\"},formatLoadingMessage:function(){return\"A carregar, por favor aguarde\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" registos por página\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"A mostrar \".concat(t,\" at&eacute; \").concat(n,\" de \").concat(o,\" linhas (filtered from \").concat(r,\" total rows)\"):\"A mostrar \".concat(t,\" até \").concat(n,\" de \").concat(o,\" linhas\")},formatSRPaginationPreText:function(){return\"página anterior\"},formatSRPaginationPageText:function(t){return\"ir para página \".concat(t)},formatSRPaginationNextText:function(){return\"próxima página\"},formatDetailPagination:function(t){return\"Mostrando \".concat(t,\" linhas\")},formatClearSearch:function(){return\"Limpar Pesquisa\"},formatSearch:function(){return\"Pesquisa\"},formatNoMatches:function(){return\"Nenhum registo encontrado\"},formatPaginationSwitch:function(){return\"Esconder/Mostrar paginação\"},formatPaginationSwitchDown:function(){return\"Mostrar página\"},formatPaginationSwitchUp:function(){return\"Esconder página\"},formatRefresh:function(){return\"Actualizar\"},formatToggle:function(){return\"Alternar\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Colunas\"},formatColumnsToggleAll:function(){return\"Activar tudo\"},formatFullscreen:function(){return\"Ecrã completo\"},formatAllRows:function(){return\"Tudo\"},formatAutoRefresh:function(){return\"Actualização autmática\"},formatExport:function(){return\"Exportar dados\"},formatJumpTo:function(){return\"Avançar\"},formatAdvancedSearch:function(){return\"Pesquisa avançada\"},formatAdvancedCloseButton:function(){return\"Fechar\"},formatFilterControlSwitch:function(){return\"Esconder/Exibir controlos\"},formatFilterControlSwitchHide:function(){return\"Esconder controlos\"},formatFilterControlSwitchShow:function(){return\"Exibir controlos\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"pt-PT\"]),o.default.fn.bootstrapTable.locales[\"ro-RO\"]=o.default.fn.bootstrapTable.locales.ro={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Se incarca, va rugam asteptati\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" inregistrari pe pagina\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Arata de la \".concat(t,\" pana la \").concat(n,\" din \").concat(o,\" randuri (filtered from \").concat(r,\" total rows)\"):\"Arata de la \".concat(t,\" pana la \").concat(n,\" din \").concat(o,\" randuri\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Cauta\"},formatNoMatches:function(){return\"Nu au fost gasite inregistrari\"},formatPaginationSwitch:function(){return\"Ascunde/Arata paginatia\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Reincarca\"},formatToggle:function(){return\"Comuta\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Coloane\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Toate\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"ro-RO\"]),o.default.fn.bootstrapTable.locales[\"ru-RU\"]=o.default.fn.bootstrapTable.locales.ru={formatCopyRows:function(){return\"Скопировать строки\"},formatPrint:function(){return\"Печать\"},formatLoadingMessage:function(){return\"Пожалуйста, подождите, идёт загрузка\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" записей на страницу\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Записи с \".concat(t,\" по \").concat(n,\" из \").concat(o,\" (отфильтровано, всего на сервере \").concat(r,\" записей)\"):\"Записи с \".concat(t,\" по \").concat(n,\" из \").concat(o)},formatSRPaginationPreText:function(){return\"предыдущая страница\"},formatSRPaginationPageText:function(t){return\"перейти к странице \".concat(t)},formatSRPaginationNextText:function(){return\"следующая страница\"},formatDetailPagination:function(t){return\"Загружено \".concat(t,\" строк\")},formatClearSearch:function(){return\"Очистить фильтры\"},formatSearch:function(){return\"Поиск\"},formatNoMatches:function(){return\"Ничего не найдено\"},formatPaginationSwitch:function(){return\"Скрыть/Показать постраничную навигацию\"},formatPaginationSwitchDown:function(){return\"Показать постраничную навигацию\"},formatPaginationSwitchUp:function(){return\"Скрыть постраничную навигацию\"},formatRefresh:function(){return\"Обновить\"},formatToggle:function(){return\"Переключить\"},formatToggleOn:function(){return\"Показать записи в виде карточек\"},formatToggleOff:function(){return\"Табличный режим просмотра\"},formatColumns:function(){return\"Колонки\"},formatColumnsToggleAll:function(){return\"Выбрать все\"},formatFullscreen:function(){return\"Полноэкранный режим\"},formatAllRows:function(){return\"Все\"},formatAutoRefresh:function(){return\"Автоматическое обновление\"},formatExport:function(){return\"Экспортировать данные\"},formatJumpTo:function(){return\"Стр.\"},formatAdvancedSearch:function(){return\"Расширенный поиск\"},formatAdvancedCloseButton:function(){return\"Закрыть\"},formatFilterControlSwitch:function(){return\"Скрыть/Показать панель инструментов\"},formatFilterControlSwitchHide:function(){return\"Скрыть панель инструментов\"},formatFilterControlSwitchShow:function(){return\"Показать панель инструментов\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"ru-RU\"]),o.default.fn.bootstrapTable.locales[\"sk-SK\"]=o.default.fn.bootstrapTable.locales.sk={formatCopyRows:function(){return\"Skopírovať riadky\"},formatPrint:function(){return\"Vytlačiť\"},formatLoadingMessage:function(){return\"Prosím čakajte\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" záznamov na stranu\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Zobrazená \".concat(t,\". - \").concat(n,\". položka z celkových \").concat(o,\" (filtered from \").concat(r,\" total rows)\"):\"Zobrazená \".concat(t,\". - \").concat(n,\". položka z celkových \").concat(o)},formatSRPaginationPreText:function(){return\"Predchádzajúca strana\"},formatSRPaginationPageText:function(t){return\"na stranu \".concat(t)},formatSRPaginationNextText:function(){return\"Nasledujúca strana\"},formatDetailPagination:function(t){return\"Zobrazuje sa \".concat(t,\" riadkov\")},formatClearSearch:function(){return\"Odstráň filtre\"},formatSearch:function(){return\"Vyhľadávanie\"},formatNoMatches:function(){return\"Nenájdená žiadna vyhovujúca položka\"},formatPaginationSwitch:function(){return\"Skry/Zobraz stránkovanie\"},formatPaginationSwitchDown:function(){return\"Zobraziť stránkovanie\"},formatPaginationSwitchUp:function(){return\"Skryť stránkovanie\"},formatRefresh:function(){return\"Obnoviť\"},formatToggle:function(){return\"Prepni\"},formatToggleOn:function(){return\"Zobraziť kartové zobrazenie\"},formatToggleOff:function(){return\"skryť kartové zobrazenie\"},formatColumns:function(){return\"Stĺpce\"},formatColumnsToggleAll:function(){return\"Prepnúť všetky\"},formatFullscreen:function(){return\"Celá obrazovka\"},formatAllRows:function(){return\"Všetky\"},formatAutoRefresh:function(){return\"Automatické obnovenie\"},formatExport:function(){return\"Exportuj dáta\"},formatJumpTo:function(){return\"Ísť\"},formatAdvancedSearch:function(){return\"Pokročilé vyhľadávanie\"},formatAdvancedCloseButton:function(){return\"Zatvoriť\"},formatFilterControlSwitch:function(){return\"Zobraziť/Skryť tlačidlá\"},formatFilterControlSwitchHide:function(){return\"Skryť tlačidlá\"},formatFilterControlSwitchShow:function(){return\"Zobraziť tlačidlá\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"sk-SK\"]),o.default.fn.bootstrapTable.locales[\"sr-Cyrl-RS\"]=o.default.fn.bootstrapTable.locales.sr={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Молим сачекај\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" редова по страни\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Приказано \".concat(t,\". - \").concat(n,\". од укупног броја редова \").concat(o,\" (филтрирано од \").concat(r,\")\"):\"Приказано \".concat(t,\". - \").concat(n,\". од укупног броја редова \").concat(o)},formatSRPaginationPreText:function(){return\"претходна страна\"},formatSRPaginationPageText:function(t){return\"на страну \".concat(t)},formatSRPaginationNextText:function(){return\"следећа страна\"},formatDetailPagination:function(t){return\"Приказано \".concat(t,\" редова\")},formatClearSearch:function(){return\"Обриши претрагу\"},formatSearch:function(){return\"Пронађи\"},formatNoMatches:function(){return\"Није пронађен ни један податак\"},formatPaginationSwitch:function(){return\"Прикажи/сакриј пагинацију\"},formatPaginationSwitchDown:function(){return\"Прикажи пагинацију\"},formatPaginationSwitchUp:function(){return\"Сакриј пагинацију\"},formatRefresh:function(){return\"Освежи\"},formatToggle:function(){return\"Промени приказ\"},formatToggleOn:function(){return\"Прикажи картице\"},formatToggleOff:function(){return\"Сакриј картице\"},formatColumns:function(){return\"Колоне\"},formatColumnsToggleAll:function(){return\"Прикажи/сакриј све\"},formatFullscreen:function(){return\"Цео екран\"},formatAllRows:function(){return\"Све\"},formatAutoRefresh:function(){return\"Аутоматско освежавање\"},formatExport:function(){return\"Извези податке\"},formatJumpTo:function(){return\"Иди\"},formatAdvancedSearch:function(){return\"Напредна претрага\"},formatAdvancedCloseButton:function(){return\"Затвори\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"sr-Cyrl-RS\"]),o.default.fn.bootstrapTable.locales[\"sr-Latn-RS\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Molim sačekaj\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" redova po strani\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Prikazano \".concat(t,\". - \").concat(n,\". od ukupnog broja redova \").concat(o,\" (filtrirano od \").concat(r,\")\"):\"Prikazano \".concat(t,\". - \").concat(n,\". od ukupnog broja redova \").concat(o)},formatSRPaginationPreText:function(){return\"prethodna strana\"},formatSRPaginationPageText:function(t){return\"na stranu \".concat(t)},formatSRPaginationNextText:function(){return\"sledeća strana\"},formatDetailPagination:function(t){return\"Prikazano \".concat(t,\" redova\")},formatClearSearch:function(){return\"Obriši pretragu\"},formatSearch:function(){return\"Pronađi\"},formatNoMatches:function(){return\"Nije pronađen ni jedan podatak\"},formatPaginationSwitch:function(){return\"Prikaži/sakrij paginaciju\"},formatPaginationSwitchDown:function(){return\"Prikaži paginaciju\"},formatPaginationSwitchUp:function(){return\"Sakrij paginaciju\"},formatRefresh:function(){return\"Osveži\"},formatToggle:function(){return\"Promeni prikaz\"},formatToggleOn:function(){return\"Prikaži kartice\"},formatToggleOff:function(){return\"Sakrij kartice\"},formatColumns:function(){return\"Kolone\"},formatColumnsToggleAll:function(){return\"Prikaži/sakrij sve\"},formatFullscreen:function(){return\"Ceo ekran\"},formatAllRows:function(){return\"Sve\"},formatAutoRefresh:function(){return\"Automatsko osvežavanje\"},formatExport:function(){return\"Izvezi podatke\"},formatJumpTo:function(){return\"Idi\"},formatAdvancedSearch:function(){return\"Napredna pretraga\"},formatAdvancedCloseButton:function(){return\"Zatvori\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"sr-Latn-RS\"]),o.default.fn.bootstrapTable.locales[\"sv-SE\"]=o.default.fn.bootstrapTable.locales.sv={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Laddar, vänligen vänta\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" rader per sida\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Visa \".concat(t,\" till \").concat(n,\" av \").concat(o,\" rader (filtered from \").concat(r,\" total rows)\"):\"Visa \".concat(t,\" till \").concat(n,\" av \").concat(o,\" rader\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Sök\"},formatNoMatches:function(){return\"Inga matchande resultat funna.\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Uppdatera\"},formatToggle:function(){return\"Skifta\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"kolumn\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"sv-SE\"]),o.default.fn.bootstrapTable.locales[\"th-TH\"]=o.default.fn.bootstrapTable.locales.th={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"กำลังโหลดข้อมูล, กรุณารอสักครู่\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" รายการต่อหน้า\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"รายการที่ \".concat(t,\" ถึง \").concat(n,\" จากทั้งหมด \").concat(o,\" รายการ (filtered from \").concat(r,\" total rows)\"):\"รายการที่ \".concat(t,\" ถึง \").concat(n,\" จากทั้งหมด \").concat(o,\" รายการ\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"ค้นหา\"},formatNoMatches:function(){return\"ไม่พบรายการที่ค้นหา !\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"รีเฟรส\"},formatToggle:function(){return\"สลับมุมมอง\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"คอลัมน์\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"th-TH\"]),o.default.fn.bootstrapTable.locales[\"tr-TR\"]=o.default.fn.bootstrapTable.locales.tr={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Yükleniyor, lütfen bekleyin\"},formatRecordsPerPage:function(t){return\"Sayfa başına \".concat(t,\" kayıt.\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"\".concat(o,\" kayıttan \").concat(t,\"-\").concat(n,\" arası gösteriliyor (filtered from \").concat(r,\" total rows).\"):\"\".concat(o,\" kayıttan \").concat(t,\"-\").concat(n,\" arası gösteriliyor.\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Ara\"},formatNoMatches:function(){return\"Eşleşen kayıt bulunamadı.\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Yenile\"},formatToggle:function(){return\"Değiştir\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Sütunlar\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Tüm Satırlar\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"tr-TR\"]),o.default.fn.bootstrapTable.locales[\"uk-UA\"]=o.default.fn.bootstrapTable.locales.uk={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Завантаження, будь ласка, зачекайте\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" записів на сторінку\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Показано з \".concat(t,\" по \").concat(n,\". Всього: \").concat(o,\" (filtered from \").concat(r,\" total rows)\"):\"Показано з \".concat(t,\" по \").concat(n,\". Всього: \").concat(o)},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Очистити фільтри\"},formatSearch:function(){return\"Пошук\"},formatNoMatches:function(){return\"Не знайдено жодного запису\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Оновити\"},formatToggle:function(){return\"Змінити\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Стовпці\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"uk-UA\"]),o.default.fn.bootstrapTable.locales[\"ur-PK\"]=o.default.fn.bootstrapTable.locales.ur={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"براۓ مہربانی انتظار کیجئے\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" ریکارڈز فی صفہ \")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"دیکھیں \".concat(t,\" سے \").concat(n,\" کے \").concat(o,\"ریکارڈز (filtered from \").concat(r,\" total rows)\"):\"دیکھیں \".concat(t,\" سے \").concat(n,\" کے \").concat(o,\"ریکارڈز\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"تلاش\"},formatNoMatches:function(){return\"کوئی ریکارڈ نہیں ملا\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"تازہ کریں\"},formatToggle:function(){return\"تبدیل کریں\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"کالم\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"ur-PK\"]),o.default.fn.bootstrapTable.locales[\"uz-Latn-UZ\"]=o.default.fn.bootstrapTable.locales.uz={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Yuklanyapti, iltimos kuting\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" qator har sahifada\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Ko'rsatypati \".concat(t,\" dan \").concat(n,\" gacha \").concat(o,\" qatorlarni (filtered from \").concat(r,\" total rows)\"):\"Ko'rsatypati \".concat(t,\" dan \").concat(n,\" gacha \").concat(o,\" qatorlarni\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Filtrlarni tozalash\"},formatSearch:function(){return\"Qidirish\"},formatNoMatches:function(){return\"Hech narsa topilmadi\"},formatPaginationSwitch:function(){return\"Sahifalashni yashirish/ko'rsatish\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Yangilash\"},formatToggle:function(){return\"Ko'rinish\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Ustunlar\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"Hammasi\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Eksport\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"uz-Latn-UZ\"]),o.default.fn.bootstrapTable.locales[\"vi-VN\"]=o.default.fn.bootstrapTable.locales.vi={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"Đang tải\"},formatRecordsPerPage:function(t){return\"\".concat(t,\" bản ghi mỗi trang\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"Hiển thị từ trang \".concat(t,\" đến \").concat(n,\" của \").concat(o,\" bảng ghi (filtered from \").concat(r,\" total rows)\"):\"Hiển thị từ trang \".concat(t,\" đến \").concat(n,\" của \").concat(o,\" bảng ghi\")},formatSRPaginationPreText:function(){return\"previous page\"},formatSRPaginationPageText:function(t){return\"to page \".concat(t)},formatSRPaginationNextText:function(){return\"next page\"},formatDetailPagination:function(t){return\"Showing \".concat(t,\" rows\")},formatClearSearch:function(){return\"Clear Search\"},formatSearch:function(){return\"Tìm kiếm\"},formatNoMatches:function(){return\"Không có dữ liệu\"},formatPaginationSwitch:function(){return\"Hide/Show pagination\"},formatPaginationSwitchDown:function(){return\"Show pagination\"},formatPaginationSwitchUp:function(){return\"Hide pagination\"},formatRefresh:function(){return\"Refresh\"},formatToggle:function(){return\"Toggle\"},formatToggleOn:function(){return\"Show card view\"},formatToggleOff:function(){return\"Hide card view\"},formatColumns:function(){return\"Columns\"},formatColumnsToggleAll:function(){return\"Toggle all\"},formatFullscreen:function(){return\"Fullscreen\"},formatAllRows:function(){return\"All\"},formatAutoRefresh:function(){return\"Auto Refresh\"},formatExport:function(){return\"Export data\"},formatJumpTo:function(){return\"GO\"},formatAdvancedSearch:function(){return\"Advanced search\"},formatAdvancedCloseButton:function(){return\"Close\"},formatFilterControlSwitch:function(){return\"Hide/Show controls\"},formatFilterControlSwitchHide:function(){return\"Hide controls\"},formatFilterControlSwitchShow:function(){return\"Show controls\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"vi-VN\"]),o.default.fn.bootstrapTable.locales[\"zh-CN\"]=o.default.fn.bootstrapTable.locales.zh={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"正在努力地加载数据中，请稍候\"},formatRecordsPerPage:function(t){return\"每页显示 \".concat(t,\" 条记录\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"显示第 \".concat(t,\" 到第 \").concat(n,\" 条记录，总共 \").concat(o,\" 条记录（从 \").concat(r,\" 总记录中过滤）\"):\"显示第 \".concat(t,\" 到第 \").concat(n,\" 条记录，总共 \").concat(o,\" 条记录\")},formatSRPaginationPreText:function(){return\"上一页\"},formatSRPaginationPageText:function(t){return\"第\".concat(t,\"页\")},formatSRPaginationNextText:function(){return\"下一页\"},formatDetailPagination:function(t){return\"总共 \".concat(t,\" 条记录\")},formatClearSearch:function(){return\"清空过滤\"},formatSearch:function(){return\"搜索\"},formatNoMatches:function(){return\"没有找到匹配的记录\"},formatPaginationSwitch:function(){return\"隐藏/显示分页\"},formatPaginationSwitchDown:function(){return\"显示分页\"},formatPaginationSwitchUp:function(){return\"隐藏分页\"},formatRefresh:function(){return\"刷新\"},formatToggle:function(){return\"切换\"},formatToggleOn:function(){return\"显示卡片视图\"},formatToggleOff:function(){return\"隐藏卡片视图\"},formatColumns:function(){return\"列\"},formatColumnsToggleAll:function(){return\"切换所有\"},formatFullscreen:function(){return\"全屏\"},formatAllRows:function(){return\"所有\"},formatAutoRefresh:function(){return\"自动刷新\"},formatExport:function(){return\"导出数据\"},formatJumpTo:function(){return\"跳转\"},formatAdvancedSearch:function(){return\"高级搜索\"},formatAdvancedCloseButton:function(){return\"关闭\"},formatFilterControlSwitch:function(){return\"隐藏/显示过滤控制\"},formatFilterControlSwitchHide:function(){return\"隐藏过滤控制\"},formatFilterControlSwitchShow:function(){return\"显示过滤控制\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"zh-CN\"]),o.default.fn.bootstrapTable.locales[\"zh-TW\"]={formatCopyRows:function(){return\"Copy Rows\"},formatPrint:function(){return\"Print\"},formatLoadingMessage:function(){return\"正在努力地載入資料，請稍候\"},formatRecordsPerPage:function(t){return\"每頁顯示 \".concat(t,\" 項記錄\")},formatShowingRows:function(t,n,o,r){return void 0!==r&&r>0&&r>o?\"顯示第 \".concat(t,\" 到第 \").concat(n,\" 項記錄，總共 \").concat(o,\" 項記錄（從 \").concat(r,\" 總記錄中過濾）\"):\"顯示第 \".concat(t,\" 到第 \").concat(n,\" 項記錄，總共 \").concat(o,\" 項記錄\")},formatSRPaginationPreText:function(){return\"上一頁\"},formatSRPaginationPageText:function(t){return\"第\".concat(t,\"頁\")},formatSRPaginationNextText:function(){return\"下一頁\"},formatDetailPagination:function(t){return\"總共 \".concat(t,\" 項記錄\")},formatClearSearch:function(){return\"清空過濾\"},formatSearch:function(){return\"搜尋\"},formatNoMatches:function(){return\"沒有找到符合的結果\"},formatPaginationSwitch:function(){return\"隱藏/顯示分頁\"},formatPaginationSwitchDown:function(){return\"顯示分頁\"},formatPaginationSwitchUp:function(){return\"隱藏分頁\"},formatRefresh:function(){return\"重新整理\"},formatToggle:function(){return\"切換\"},formatToggleOn:function(){return\"顯示卡片視圖\"},formatToggleOff:function(){return\"隱藏卡片視圖\"},formatColumns:function(){return\"列\"},formatColumnsToggleAll:function(){return\"切換所有\"},formatFullscreen:function(){return\"全屏\"},formatAllRows:function(){return\"所有\"},formatAutoRefresh:function(){return\"自動刷新\"},formatExport:function(){return\"導出數據\"},formatJumpTo:function(){return\"跳轉\"},formatAdvancedSearch:function(){return\"高級搜尋\"},formatAdvancedCloseButton:function(){return\"關閉\"},formatFilterControlSwitch:function(){return\"隱藏/顯示過濾控制\"},formatFilterControlSwitchHide:function(){return\"隱藏過濾控制\"},formatFilterControlSwitchShow:function(){return\"顯示過濾控制\"}},o.default.extend(o.default.fn.bootstrapTable.defaults,o.default.fn.bootstrapTable.locales[\"zh-TW\"])}));


/***/ }),

/***/ \"./node_modules/bootstrap-table/dist/bootstrap-table.js\":
/*!**************************************************************!*\\
  !*** ./node_modules/bootstrap-table/dist/bootstrap-table.js ***!
  \\**************************************************************/
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {

(function (global, factory) {
   true ? module.exports = factory(__webpack_require__(/*! jquery */ \"./node_modules/jquery/dist/jquery.js\")) :
  0;
}(this, (function (\$) { 'use strict';

  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

  var \$__default = /*#__PURE__*/_interopDefaultLegacy(\$);

  function _typeof(obj) {
    \"@babel/helpers - typeof\";

    if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") {
      _typeof = function (obj) {
        return typeof obj;
      };
    } else {
      _typeof = function (obj) {
        return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;
      };
    }

    return _typeof(obj);
  }

  function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError(\"Cannot call a class as a 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);
    }
  }

  function _createClass(Constructor, protoProps, staticProps) {
    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
    if (staticProps) _defineProperties(Constructor, staticProps);
    return Constructor;
  }

  function _slicedToArray(arr, i) {
    return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
  }

  function _toConsumableArray(arr) {
    return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
  }

  function _arrayWithoutHoles(arr) {
    if (Array.isArray(arr)) return _arrayLikeToArray(arr);
  }

  function _arrayWithHoles(arr) {
    if (Array.isArray(arr)) return arr;
  }

  function _iterableToArray(iter) {
    if (typeof Symbol !== \"undefined\" && Symbol.iterator in Object(iter)) return Array.from(iter);
  }

  function _iterableToArrayLimit(arr, i) {
    if (typeof Symbol === \"undefined\" || !(Symbol.iterator in Object(arr))) return;
    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\"] != null) _i[\"return\"]();
      } finally {
        if (_d) throw _e;
      }
    }

    return _arr;
  }

  function _unsupportedIterableToArray(o, minLen) {
    if (!o) return;
    if (typeof o === \"string\") return _arrayLikeToArray(o, minLen);
    var n = Object.prototype.toString.call(o).slice(8, -1);
    if (n === \"Object\" && o.constructor) n = o.constructor.name;
    if (n === \"Map\" || n === \"Set\") return Array.from(o);
    if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array\$/.test(n)) return _arrayLikeToArray(o, minLen);
  }

  function _arrayLikeToArray(arr, len) {
    if (len == null || len > arr.length) len = arr.length;

    for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];

    return arr2;
  }

  function _nonIterableSpread() {
    throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");
  }

  function _nonIterableRest() {
    throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");
  }

  function _createForOfIteratorHelper(o, allowArrayLike) {
    var it;

    if (typeof Symbol === \"undefined\" || o[Symbol.iterator] == null) {
      if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === \"number\") {
        if (it) o = it;
        var i = 0;

        var F = function () {};

        return {
          s: F,
          n: function () {
            if (i >= o.length) return {
              done: true
            };
            return {
              done: false,
              value: o[i++]
            };
          },
          e: function (e) {
            throw e;
          },
          f: F
        };
      }

      throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");
    }

    var normalCompletion = true,
        didErr = false,
        err;
    return {
      s: function () {
        it = o[Symbol.iterator]();
      },
      n: function () {
        var step = it.next();
        normalCompletion = step.done;
        return step;
      },
      e: function (e) {
        didErr = true;
        err = e;
      },
      f: function () {
        try {
          if (!normalCompletion && it.return != null) it.return();
        } finally {
          if (didErr) throw err;
        }
      }
    };
  }

  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof __webpack_require__.g !== 'undefined' ? __webpack_require__.g : typeof self !== 'undefined' ? self : {};

  function createCommonjsModule(fn, module) {
  \treturn module = { exports: {} }, fn(module, module.exports), module.exports;
  }

  var check = function (it) {
    return it && it.Math == Math && it;
  };

  // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
  var global_1 =
    /* global globalThis -- safe */
    check(typeof globalThis == 'object' && globalThis) ||
    check(typeof window == 'object' && window) ||
    check(typeof self == 'object' && self) ||
    check(typeof commonjsGlobal == 'object' && commonjsGlobal) ||
    // eslint-disable-next-line no-new-func -- fallback
    (function () { return this; })() || Function('return this')();

  var fails = function (exec) {
    try {
      return !!exec();
    } catch (error) {
      return true;
    }
  };

  // Detect IE8's incomplete defineProperty implementation
  var descriptors = !fails(function () {
    return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] != 7;
  });

  var nativePropertyIsEnumerable = {}.propertyIsEnumerable;
  var getOwnPropertyDescriptor\$4 = Object.getOwnPropertyDescriptor;

  // Nashorn ~ JDK8 bug
  var NASHORN_BUG = getOwnPropertyDescriptor\$4 && !nativePropertyIsEnumerable.call({ 1: 2 }, 1);

  // `Object.prototype.propertyIsEnumerable` method implementation
  // https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
  var f\$4 = NASHORN_BUG ? function propertyIsEnumerable(V) {
    var descriptor = getOwnPropertyDescriptor\$4(this, V);
    return !!descriptor && descriptor.enumerable;
  } : nativePropertyIsEnumerable;

  var objectPropertyIsEnumerable = {
  \tf: f\$4
  };

  var createPropertyDescriptor = function (bitmap, value) {
    return {
      enumerable: !(bitmap & 1),
      configurable: !(bitmap & 2),
      writable: !(bitmap & 4),
      value: value
    };
  };

  var toString = {}.toString;

  var classofRaw = function (it) {
    return toString.call(it).slice(8, -1);
  };

  var split = ''.split;

  // fallback for non-array-like ES3 and non-enumerable old V8 strings
  var indexedObject = fails(function () {
    // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
    // eslint-disable-next-line no-prototype-builtins -- safe
    return !Object('z').propertyIsEnumerable(0);
  }) ? function (it) {
    return classofRaw(it) == 'String' ? split.call(it, '') : Object(it);
  } : Object;

  // `RequireObjectCoercible` abstract operation
  // https://tc39.es/ecma262/#sec-requireobjectcoercible
  var requireObjectCoercible = function (it) {
    if (it == undefined) throw TypeError(\"Can't call method on \" + it);
    return it;
  };

  // toObject with fallback for non-array-like ES3 strings



  var toIndexedObject = function (it) {
    return indexedObject(requireObjectCoercible(it));
  };

  var isObject = function (it) {
    return typeof it === 'object' ? it !== null : typeof it === 'function';
  };

  // `ToPrimitive` abstract operation
  // https://tc39.es/ecma262/#sec-toprimitive
  // instead of the ES6 spec version, we didn't implement @@toPrimitive case
  // and the second argument - flag - preferred type is a string
  var toPrimitive = function (input, PREFERRED_STRING) {
    if (!isObject(input)) return input;
    var fn, val;
    if (PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val;
    if (typeof (fn = input.valueOf) == 'function' && !isObject(val = fn.call(input))) return val;
    if (!PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val;
    throw TypeError(\"Can't convert object to primitive value\");
  };

  var hasOwnProperty = {}.hasOwnProperty;

  var has\$1 = function (it, key) {
    return hasOwnProperty.call(it, key);
  };

  var document\$1 = global_1.document;
  // typeof document.createElement is 'object' in old IE
  var EXISTS = isObject(document\$1) && isObject(document\$1.createElement);

  var documentCreateElement = function (it) {
    return EXISTS ? document\$1.createElement(it) : {};
  };

  // Thank's IE8 for his funny defineProperty
  var ie8DomDefine = !descriptors && !fails(function () {
    return Object.defineProperty(documentCreateElement('div'), 'a', {
      get: function () { return 7; }
    }).a != 7;
  });

  var nativeGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;

  // `Object.getOwnPropertyDescriptor` method
  // https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
  var f\$3 = descriptors ? nativeGetOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) {
    O = toIndexedObject(O);
    P = toPrimitive(P, true);
    if (ie8DomDefine) try {
      return nativeGetOwnPropertyDescriptor(O, P);
    } catch (error) { /* empty */ }
    if (has\$1(O, P)) return createPropertyDescriptor(!objectPropertyIsEnumerable.f.call(O, P), O[P]);
  };

  var objectGetOwnPropertyDescriptor = {
  \tf: f\$3
  };

  var anObject = function (it) {
    if (!isObject(it)) {
      throw TypeError(String(it) + ' is not an object');
    } return it;
  };

  var nativeDefineProperty = Object.defineProperty;

  // `Object.defineProperty` method
  // https://tc39.es/ecma262/#sec-object.defineproperty
  var f\$2 = descriptors ? nativeDefineProperty : function defineProperty(O, P, Attributes) {
    anObject(O);
    P = toPrimitive(P, true);
    anObject(Attributes);
    if (ie8DomDefine) try {
      return nativeDefineProperty(O, P, Attributes);
    } catch (error) { /* empty */ }
    if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported');
    if ('value' in Attributes) O[P] = Attributes.value;
    return O;
  };

  var objectDefineProperty = {
  \tf: f\$2
  };

  var createNonEnumerableProperty = descriptors ? function (object, key, value) {
    return objectDefineProperty.f(object, key, createPropertyDescriptor(1, value));
  } : function (object, key, value) {
    object[key] = value;
    return object;
  };

  var setGlobal = function (key, value) {
    try {
      createNonEnumerableProperty(global_1, key, value);
    } catch (error) {
      global_1[key] = value;
    } return value;
  };

  var SHARED = '__core-js_shared__';
  var store\$1 = global_1[SHARED] || setGlobal(SHARED, {});

  var sharedStore = store\$1;

  var functionToString = Function.toString;

  // this helper broken in `3.4.1-3.4.4`, so we can't use `shared` helper
  if (typeof sharedStore.inspectSource != 'function') {
    sharedStore.inspectSource = function (it) {
      return functionToString.call(it);
    };
  }

  var inspectSource = sharedStore.inspectSource;

  var WeakMap\$1 = global_1.WeakMap;

  var nativeWeakMap = typeof WeakMap\$1 === 'function' && /native code/.test(inspectSource(WeakMap\$1));

  var shared = createCommonjsModule(function (module) {
  (module.exports = function (key, value) {
    return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {});
  })('versions', []).push({
    version: '3.9.1',
    mode: 'global',
    copyright: '© 2021 Denis Pushkarev (zloirock.ru)'
  });
  });

  var id = 0;
  var postfix = Math.random();

  var uid = function (key) {
    return 'Symbol(' + String(key === undefined ? '' : key) + ')_' + (++id + postfix).toString(36);
  };

  var keys\$2 = shared('keys');

  var sharedKey = function (key) {
    return keys\$2[key] || (keys\$2[key] = uid(key));
  };

  var hiddenKeys\$1 = {};

  var WeakMap = global_1.WeakMap;
  var set, get, has;

  var enforce = function (it) {
    return has(it) ? get(it) : set(it, {});
  };

  var getterFor = function (TYPE) {
    return function (it) {
      var state;
      if (!isObject(it) || (state = get(it)).type !== TYPE) {
        throw TypeError('Incompatible receiver, ' + TYPE + ' required');
      } return state;
    };
  };

  if (nativeWeakMap) {
    var store = sharedStore.state || (sharedStore.state = new WeakMap());
    var wmget = store.get;
    var wmhas = store.has;
    var wmset = store.set;
    set = function (it, metadata) {
      metadata.facade = it;
      wmset.call(store, it, metadata);
      return metadata;
    };
    get = function (it) {
      return wmget.call(store, it) || {};
    };
    has = function (it) {
      return wmhas.call(store, it);
    };
  } else {
    var STATE = sharedKey('state');
    hiddenKeys\$1[STATE] = true;
    set = function (it, metadata) {
      metadata.facade = it;
      createNonEnumerableProperty(it, STATE, metadata);
      return metadata;
    };
    get = function (it) {
      return has\$1(it, STATE) ? it[STATE] : {};
    };
    has = function (it) {
      return has\$1(it, STATE);
    };
  }

  var internalState = {
    set: set,
    get: get,
    has: has,
    enforce: enforce,
    getterFor: getterFor
  };

  var redefine = createCommonjsModule(function (module) {
  var getInternalState = internalState.get;
  var enforceInternalState = internalState.enforce;
  var TEMPLATE = String(String).split('String');

  (module.exports = function (O, key, value, options) {
    var unsafe = options ? !!options.unsafe : false;
    var simple = options ? !!options.enumerable : false;
    var noTargetGet = options ? !!options.noTargetGet : false;
    var state;
    if (typeof value == 'function') {
      if (typeof key == 'string' && !has\$1(value, 'name')) {
        createNonEnumerableProperty(value, 'name', key);
      }
      state = enforceInternalState(value);
      if (!state.source) {
        state.source = TEMPLATE.join(typeof key == 'string' ? key : '');
      }
    }
    if (O === global_1) {
      if (simple) O[key] = value;
      else setGlobal(key, value);
      return;
    } else if (!unsafe) {
      delete O[key];
    } else if (!noTargetGet && O[key]) {
      simple = true;
    }
    if (simple) O[key] = value;
    else createNonEnumerableProperty(O, key, value);
  // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
  })(Function.prototype, 'toString', function toString() {
    return typeof this == 'function' && getInternalState(this).source || inspectSource(this);
  });
  });

  var path = global_1;

  var aFunction\$1 = function (variable) {
    return typeof variable == 'function' ? variable : undefined;
  };

  var getBuiltIn = function (namespace, method) {
    return arguments.length < 2 ? aFunction\$1(path[namespace]) || aFunction\$1(global_1[namespace])
      : path[namespace] && path[namespace][method] || global_1[namespace] && global_1[namespace][method];
  };

  var ceil = Math.ceil;
  var floor\$1 = Math.floor;

  // `ToInteger` abstract operation
  // https://tc39.es/ecma262/#sec-tointeger
  var toInteger = function (argument) {
    return isNaN(argument = +argument) ? 0 : (argument > 0 ? floor\$1 : ceil)(argument);
  };

  var min\$6 = Math.min;

  // `ToLength` abstract operation
  // https://tc39.es/ecma262/#sec-tolength
  var toLength = function (argument) {
    return argument > 0 ? min\$6(toInteger(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991
  };

  var max\$3 = Math.max;
  var min\$5 = Math.min;

  // Helper for a popular repeating case of the spec:
  // Let integer be ? ToInteger(index).
  // If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length).
  var toAbsoluteIndex = function (index, length) {
    var integer = toInteger(index);
    return integer < 0 ? max\$3(integer + length, 0) : min\$5(integer, length);
  };

  // `Array.prototype.{ indexOf, includes }` methods implementation
  var createMethod\$4 = function (IS_INCLUDES) {
    return function (\$this, el, fromIndex) {
      var O = toIndexedObject(\$this);
      var length = toLength(O.length);
      var index = toAbsoluteIndex(fromIndex, length);
      var value;
      // Array#includes uses SameValueZero equality algorithm
      // eslint-disable-next-line no-self-compare -- NaN check
      if (IS_INCLUDES && el != el) while (length > index) {
        value = O[index++];
        // eslint-disable-next-line no-self-compare -- NaN check
        if (value != value) return true;
      // Array#indexOf ignores holes, Array#includes - not
      } else for (;length > index; index++) {
        if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
      } return !IS_INCLUDES && -1;
    };
  };

  var arrayIncludes = {
    // `Array.prototype.includes` method
    // https://tc39.es/ecma262/#sec-array.prototype.includes
    includes: createMethod\$4(true),
    // `Array.prototype.indexOf` method
    // https://tc39.es/ecma262/#sec-array.prototype.indexof
    indexOf: createMethod\$4(false)
  };

  var indexOf = arrayIncludes.indexOf;


  var objectKeysInternal = function (object, names) {
    var O = toIndexedObject(object);
    var i = 0;
    var result = [];
    var key;
    for (key in O) !has\$1(hiddenKeys\$1, key) && has\$1(O, key) && result.push(key);
    // Don't enum bug & hidden keys
    while (names.length > i) if (has\$1(O, key = names[i++])) {
      ~indexOf(result, key) || result.push(key);
    }
    return result;
  };

  // IE8- don't enum bug keys
  var enumBugKeys = [
    'constructor',
    'hasOwnProperty',
    'isPrototypeOf',
    'propertyIsEnumerable',
    'toLocaleString',
    'toString',
    'valueOf'
  ];

  var hiddenKeys = enumBugKeys.concat('length', 'prototype');

  // `Object.getOwnPropertyNames` method
  // https://tc39.es/ecma262/#sec-object.getownpropertynames
  var f\$1 = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
    return objectKeysInternal(O, hiddenKeys);
  };

  var objectGetOwnPropertyNames = {
  \tf: f\$1
  };

  var f = Object.getOwnPropertySymbols;

  var objectGetOwnPropertySymbols = {
  \tf: f
  };

  // all object keys, includes non-enumerable and symbols
  var ownKeys = getBuiltIn('Reflect', 'ownKeys') || function ownKeys(it) {
    var keys = objectGetOwnPropertyNames.f(anObject(it));
    var getOwnPropertySymbols = objectGetOwnPropertySymbols.f;
    return getOwnPropertySymbols ? keys.concat(getOwnPropertySymbols(it)) : keys;
  };

  var copyConstructorProperties = function (target, source) {
    var keys = ownKeys(source);
    var defineProperty = objectDefineProperty.f;
    var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f;
    for (var i = 0; i < keys.length; i++) {
      var key = keys[i];
      if (!has\$1(target, key)) defineProperty(target, key, getOwnPropertyDescriptor(source, key));
    }
  };

  var replacement = /#|\\.prototype\\./;

  var isForced = function (feature, detection) {
    var value = data[normalize(feature)];
    return value == POLYFILL ? true
      : value == NATIVE ? false
      : typeof detection == 'function' ? fails(detection)
      : !!detection;
  };

  var normalize = isForced.normalize = function (string) {
    return String(string).replace(replacement, '.').toLowerCase();
  };

  var data = isForced.data = {};
  var NATIVE = isForced.NATIVE = 'N';
  var POLYFILL = isForced.POLYFILL = 'P';

  var isForced_1 = isForced;

  var getOwnPropertyDescriptor\$3 = objectGetOwnPropertyDescriptor.f;






  /*
    options.target      - name of the target object
    options.global      - target is the global object
    options.stat        - export as static methods of target
    options.proto       - export as prototype methods of target
    options.real        - real prototype method for the `pure` version
    options.forced      - export even if the native feature is available
    options.bind        - bind methods to the target, required for the `pure` version
    options.wrap        - wrap constructors to preventing global pollution, required for the `pure` version
    options.unsafe      - use the simple assignment of property instead of delete + defineProperty
    options.sham        - add a flag to not completely full polyfills
    options.enumerable  - export as enumerable property
    options.noTargetGet - prevent calling a getter on target
  */
  var _export = function (options, source) {
    var TARGET = options.target;
    var GLOBAL = options.global;
    var STATIC = options.stat;
    var FORCED, target, key, targetProperty, sourceProperty, descriptor;
    if (GLOBAL) {
      target = global_1;
    } else if (STATIC) {
      target = global_1[TARGET] || setGlobal(TARGET, {});
    } else {
      target = (global_1[TARGET] || {}).prototype;
    }
    if (target) for (key in source) {
      sourceProperty = source[key];
      if (options.noTargetGet) {
        descriptor = getOwnPropertyDescriptor\$3(target, key);
        targetProperty = descriptor && descriptor.value;
      } else targetProperty = target[key];
      FORCED = isForced_1(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced);
      // contained in target
      if (!FORCED && targetProperty !== undefined) {
        if (typeof sourceProperty === typeof targetProperty) continue;
        copyConstructorProperties(sourceProperty, targetProperty);
      }
      // add a flag to not completely full polyfills
      if (options.sham || (targetProperty && targetProperty.sham)) {
        createNonEnumerableProperty(sourceProperty, 'sham', true);
      }
      // extend global
      redefine(target, key, sourceProperty, options);
    }
  };

  // a string of all valid unicode whitespaces
  var whitespaces = '\\u0009\\u000A\\u000B\\u000C\\u000D\\u0020\\u00A0\\u1680\\u2000\\u2001\\u2002' +
    '\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\u2028\\u2029\\uFEFF';

  var whitespace = '[' + whitespaces + ']';
  var ltrim = RegExp('^' + whitespace + whitespace + '*');
  var rtrim = RegExp(whitespace + whitespace + '*\$');

  // `String.prototype.{ trim, trimStart, trimEnd, trimLeft, trimRight }` methods implementation
  var createMethod\$3 = function (TYPE) {
    return function (\$this) {
      var string = String(requireObjectCoercible(\$this));
      if (TYPE & 1) string = string.replace(ltrim, '');
      if (TYPE & 2) string = string.replace(rtrim, '');
      return string;
    };
  };

  var stringTrim = {
    // `String.prototype.{ trimLeft, trimStart }` methods
    // https://tc39.es/ecma262/#sec-string.prototype.trimstart
    start: createMethod\$3(1),
    // `String.prototype.{ trimRight, trimEnd }` methods
    // https://tc39.es/ecma262/#sec-string.prototype.trimend
    end: createMethod\$3(2),
    // `String.prototype.trim` method
    // https://tc39.es/ecma262/#sec-string.prototype.trim
    trim: createMethod\$3(3)
  };

  var non = '\\u200B\\u0085\\u180E';

  // check that a method works with the correct list
  // of whitespaces and has a correct name
  var stringTrimForced = function (METHOD_NAME) {
    return fails(function () {
      return !!whitespaces[METHOD_NAME]() || non[METHOD_NAME]() != non || whitespaces[METHOD_NAME].name !== METHOD_NAME;
    });
  };

  var \$trim = stringTrim.trim;


  // `String.prototype.trim` method
  // https://tc39.es/ecma262/#sec-string.prototype.trim
  _export({ target: 'String', proto: true, forced: stringTrimForced('trim') }, {
    trim: function trim() {
      return \$trim(this);
    }
  });

  var arrayMethodIsStrict = function (METHOD_NAME, argument) {
    var method = [][METHOD_NAME];
    return !!method && fails(function () {
      // eslint-disable-next-line no-useless-call,no-throw-literal -- required for testing
      method.call(null, argument || function () { throw 1; }, 1);
    });
  };

  var nativeJoin = [].join;

  var ES3_STRINGS = indexedObject != Object;
  var STRICT_METHOD\$3 = arrayMethodIsStrict('join', ',');

  // `Array.prototype.join` method
  // https://tc39.es/ecma262/#sec-array.prototype.join
  _export({ target: 'Array', proto: true, forced: ES3_STRINGS || !STRICT_METHOD\$3 }, {
    join: function join(separator) {
      return nativeJoin.call(toIndexedObject(this), separator === undefined ? ',' : separator);
    }
  });

  // `RegExp.prototype.flags` getter implementation
  // https://tc39.es/ecma262/#sec-get-regexp.prototype.flags
  var regexpFlags = function () {
    var that = anObject(this);
    var result = '';
    if (that.global) result += 'g';
    if (that.ignoreCase) result += 'i';
    if (that.multiline) result += 'm';
    if (that.dotAll) result += 's';
    if (that.unicode) result += 'u';
    if (that.sticky) result += 'y';
    return result;
  };

  // babel-minify transpiles RegExp('a', 'y') -> /a/y and it causes SyntaxError,
  // so we use an intermediate function.
  function RE(s, f) {
    return RegExp(s, f);
  }

  var UNSUPPORTED_Y\$2 = fails(function () {
    // babel-minify transpiles RegExp('a', 'y') -> /a/y and it causes SyntaxError
    var re = RE('a', 'y');
    re.lastIndex = 2;
    return re.exec('abcd') != null;
  });

  var BROKEN_CARET = fails(function () {
    // https://bugzilla.mozilla.org/show_bug.cgi?id=773687
    var re = RE('^r', 'gy');
    re.lastIndex = 2;
    return re.exec('str') != null;
  });

  var regexpStickyHelpers = {
  \tUNSUPPORTED_Y: UNSUPPORTED_Y\$2,
  \tBROKEN_CARET: BROKEN_CARET
  };

  var nativeExec = RegExp.prototype.exec;
  // This always refers to the native implementation, because the
  // String#replace polyfill uses ./fix-regexp-well-known-symbol-logic.js,
  // which loads this file before patching the method.
  var nativeReplace = String.prototype.replace;

  var patchedExec = nativeExec;

  var UPDATES_LAST_INDEX_WRONG = (function () {
    var re1 = /a/;
    var re2 = /b*/g;
    nativeExec.call(re1, 'a');
    nativeExec.call(re2, 'a');
    return re1.lastIndex !== 0 || re2.lastIndex !== 0;
  })();

  var UNSUPPORTED_Y\$1 = regexpStickyHelpers.UNSUPPORTED_Y || regexpStickyHelpers.BROKEN_CARET;

  // nonparticipating capturing group, copied from es5-shim's String#split patch.
  // eslint-disable-next-line regexp/no-assertion-capturing-group, regexp/no-empty-group -- required for testing
  var NPCG_INCLUDED = /()??/.exec('')[1] !== undefined;

  var PATCH = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED || UNSUPPORTED_Y\$1;

  if (PATCH) {
    patchedExec = function exec(str) {
      var re = this;
      var lastIndex, reCopy, match, i;
      var sticky = UNSUPPORTED_Y\$1 && re.sticky;
      var flags = regexpFlags.call(re);
      var source = re.source;
      var charsAdded = 0;
      var strCopy = str;

      if (sticky) {
        flags = flags.replace('y', '');
        if (flags.indexOf('g') === -1) {
          flags += 'g';
        }

        strCopy = String(str).slice(re.lastIndex);
        // Support anchored sticky behavior.
        if (re.lastIndex > 0 && (!re.multiline || re.multiline && str[re.lastIndex - 1] !== '\\n')) {
          source = '(?: ' + source + ')';
          strCopy = ' ' + strCopy;
          charsAdded++;
        }
        // ^(? + rx + ) is needed, in combination with some str slicing, to
        // simulate the 'y' flag.
        reCopy = new RegExp('^(?:' + source + ')', flags);
      }

      if (NPCG_INCLUDED) {
        reCopy = new RegExp('^' + source + '\$(?!\\\\s)', flags);
      }
      if (UPDATES_LAST_INDEX_WRONG) lastIndex = re.lastIndex;

      match = nativeExec.call(sticky ? reCopy : re, strCopy);

      if (sticky) {
        if (match) {
          match.input = match.input.slice(charsAdded);
          match[0] = match[0].slice(charsAdded);
          match.index = re.lastIndex;
          re.lastIndex += match[0].length;
        } else re.lastIndex = 0;
      } else if (UPDATES_LAST_INDEX_WRONG && match) {
        re.lastIndex = re.global ? match.index + match[0].length : lastIndex;
      }
      if (NPCG_INCLUDED && match && match.length > 1) {
        // Fix browsers whose `exec` methods don't consistently return `undefined`
        // for NPCG, like IE8. NOTE: This doesn' work for /(.?)?/
        nativeReplace.call(match[0], reCopy, function () {
          for (i = 1; i < arguments.length - 2; i++) {
            if (arguments[i] === undefined) match[i] = undefined;
          }
        });
      }

      return match;
    };
  }

  var regexpExec = patchedExec;

  // `RegExp.prototype.exec` method
  // https://tc39.es/ecma262/#sec-regexp.prototype.exec
  _export({ target: 'RegExp', proto: true, forced: /./.exec !== regexpExec }, {
    exec: regexpExec
  });

  var engineIsNode = classofRaw(global_1.process) == 'process';

  var engineUserAgent = getBuiltIn('navigator', 'userAgent') || '';

  var process = global_1.process;
  var versions = process && process.versions;
  var v8 = versions && versions.v8;
  var match, version;

  if (v8) {
    match = v8.split('.');
    version = match[0] + match[1];
  } else if (engineUserAgent) {
    match = engineUserAgent.match(/Edge\\/(\\d+)/);
    if (!match || match[1] >= 74) {
      match = engineUserAgent.match(/Chrome\\/(\\d+)/);
      if (match) version = match[1];
    }
  }

  var engineV8Version = version && +version;

  var nativeSymbol = !!Object.getOwnPropertySymbols && !fails(function () {
    /* global Symbol -- required for testing */
    return !Symbol.sham &&
      // Chrome 38 Symbol has incorrect toString conversion
      // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
      (engineIsNode ? engineV8Version === 38 : engineV8Version > 37 && engineV8Version < 41);
  });

  var useSymbolAsUid = nativeSymbol
    /* global Symbol -- safe */
    && !Symbol.sham
    && typeof Symbol.iterator == 'symbol';

  var WellKnownSymbolsStore = shared('wks');
  var Symbol\$1 = global_1.Symbol;
  var createWellKnownSymbol = useSymbolAsUid ? Symbol\$1 : Symbol\$1 && Symbol\$1.withoutSetter || uid;

  var wellKnownSymbol = function (name) {
    if (!has\$1(WellKnownSymbolsStore, name) || !(nativeSymbol || typeof WellKnownSymbolsStore[name] == 'string')) {
      if (nativeSymbol && has\$1(Symbol\$1, name)) {
        WellKnownSymbolsStore[name] = Symbol\$1[name];
      } else {
        WellKnownSymbolsStore[name] = createWellKnownSymbol('Symbol.' + name);
      }
    } return WellKnownSymbolsStore[name];
  };

  // TODO: Remove from `core-js@4` since it's moved to entry points







  var SPECIES\$5 = wellKnownSymbol('species');

  var REPLACE_SUPPORTS_NAMED_GROUPS = !fails(function () {
    // #replace needs built-in support for named groups.
    // #match works fine because it just return the exec results, even if it has
    // a \"grops\" property.
    var re = /./;
    re.exec = function () {
      var result = [];
      result.groups = { a: '7' };
      return result;
    };
    return ''.replace(re, '\$<a>') !== '7';
  });

  // IE <= 11 replaces \$0 with the whole match, as if it was \$&
  // https://stackoverflow.com/questions/6024666/getting-ie-to-replace-a-regex-with-the-literal-string-0
  var REPLACE_KEEPS_\$0 = (function () {
    return 'a'.replace(/./, '\$0') === '\$0';
  })();

  var REPLACE = wellKnownSymbol('replace');
  // Safari <= 13.0.3(?) substitutes nth capture where n>m with an empty string
  var REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE = (function () {
    if (/./[REPLACE]) {
      return /./[REPLACE]('a', '\$0') === '';
    }
    return false;
  })();

  // Chrome 51 has a buggy \"split\" implementation when RegExp#exec !== nativeExec
  // Weex JS has frozen built-in prototypes, so use try / catch wrapper
  var SPLIT_WORKS_WITH_OVERWRITTEN_EXEC = !fails(function () {
    // eslint-disable-next-line regexp/no-empty-group -- required for testing
    var re = /(?:)/;
    var originalExec = re.exec;
    re.exec = function () { return originalExec.apply(this, arguments); };
    var result = 'ab'.split(re);
    return result.length !== 2 || result[0] !== 'a' || result[1] !== 'b';
  });

  var fixRegexpWellKnownSymbolLogic = function (KEY, length, exec, sham) {
    var SYMBOL = wellKnownSymbol(KEY);

    var DELEGATES_TO_SYMBOL = !fails(function () {
      // String methods call symbol-named RegEp methods
      var O = {};
      O[SYMBOL] = function () { return 7; };
      return ''[KEY](O) != 7;
    });

    var DELEGATES_TO_EXEC = DELEGATES_TO_SYMBOL && !fails(function () {
      // Symbol-named RegExp methods call .exec
      var execCalled = false;
      var re = /a/;

      if (KEY === 'split') {
        // We can't use real regex here since it causes deoptimization
        // and serious performance degradation in V8
        // https://github.com/zloirock/core-js/issues/306
        re = {};
        // RegExp[@@split] doesn't call the regex's exec method, but first creates
        // a new one. We need to return the patched regex when creating the new one.
        re.constructor = {};
        re.constructor[SPECIES\$5] = function () { return re; };
        re.flags = '';
        re[SYMBOL] = /./[SYMBOL];
      }

      re.exec = function () { execCalled = true; return null; };

      re[SYMBOL]('');
      return !execCalled;
    });

    if (
      !DELEGATES_TO_SYMBOL ||
      !DELEGATES_TO_EXEC ||
      (KEY === 'replace' && !(
        REPLACE_SUPPORTS_NAMED_GROUPS &&
        REPLACE_KEEPS_\$0 &&
        !REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE
      )) ||
      (KEY === 'split' && !SPLIT_WORKS_WITH_OVERWRITTEN_EXEC)
    ) {
      var nativeRegExpMethod = /./[SYMBOL];
      var methods = exec(SYMBOL, ''[KEY], function (nativeMethod, regexp, str, arg2, forceStringMethod) {
        if (regexp.exec === regexpExec) {
          if (DELEGATES_TO_SYMBOL && !forceStringMethod) {
            // The native String method already delegates to @@method (this
            // polyfilled function), leasing to infinite recursion.
            // We avoid it by directly calling the native @@method method.
            return { done: true, value: nativeRegExpMethod.call(regexp, str, arg2) };
          }
          return { done: true, value: nativeMethod.call(str, regexp, arg2) };
        }
        return { done: false };
      }, {
        REPLACE_KEEPS_\$0: REPLACE_KEEPS_\$0,
        REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE: REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE
      });
      var stringMethod = methods[0];
      var regexMethod = methods[1];

      redefine(String.prototype, KEY, stringMethod);
      redefine(RegExp.prototype, SYMBOL, length == 2
        // 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue)
        // 21.2.5.11 RegExp.prototype[@@split](string, limit)
        ? function (string, arg) { return regexMethod.call(string, this, arg); }
        // 21.2.5.6 RegExp.prototype[@@match](string)
        // 21.2.5.9 RegExp.prototype[@@search](string)
        : function (string) { return regexMethod.call(string, this); }
      );
    }

    if (sham) createNonEnumerableProperty(RegExp.prototype[SYMBOL], 'sham', true);
  };

  var MATCH\$2 = wellKnownSymbol('match');

  // `IsRegExp` abstract operation
  // https://tc39.es/ecma262/#sec-isregexp
  var isRegexp = function (it) {
    var isRegExp;
    return isObject(it) && ((isRegExp = it[MATCH\$2]) !== undefined ? !!isRegExp : classofRaw(it) == 'RegExp');
  };

  var aFunction = function (it) {
    if (typeof it != 'function') {
      throw TypeError(String(it) + ' is not a function');
    } return it;
  };

  var SPECIES\$4 = wellKnownSymbol('species');

  // `SpeciesConstructor` abstract operation
  // https://tc39.es/ecma262/#sec-speciesconstructor
  var speciesConstructor = function (O, defaultConstructor) {
    var C = anObject(O).constructor;
    var S;
    return C === undefined || (S = anObject(C)[SPECIES\$4]) == undefined ? defaultConstructor : aFunction(S);
  };

  // `String.prototype.{ codePointAt, at }` methods implementation
  var createMethod\$2 = function (CONVERT_TO_STRING) {
    return function (\$this, pos) {
      var S = String(requireObjectCoercible(\$this));
      var position = toInteger(pos);
      var size = S.length;
      var first, second;
      if (position < 0 || position >= size) return CONVERT_TO_STRING ? '' : undefined;
      first = S.charCodeAt(position);
      return first < 0xD800 || first > 0xDBFF || position + 1 === size
        || (second = S.charCodeAt(position + 1)) < 0xDC00 || second > 0xDFFF
          ? CONVERT_TO_STRING ? S.charAt(position) : first
          : CONVERT_TO_STRING ? S.slice(position, position + 2) : (first - 0xD800 << 10) + (second - 0xDC00) + 0x10000;
    };
  };

  var stringMultibyte = {
    // `String.prototype.codePointAt` method
    // https://tc39.es/ecma262/#sec-string.prototype.codepointat
    codeAt: createMethod\$2(false),
    // `String.prototype.at` method
    // https://github.com/mathiasbynens/String.prototype.at
    charAt: createMethod\$2(true)
  };

  var charAt = stringMultibyte.charAt;

  // `AdvanceStringIndex` abstract operation
  // https://tc39.es/ecma262/#sec-advancestringindex
  var advanceStringIndex = function (S, index, unicode) {
    return index + (unicode ? charAt(S, index).length : 1);
  };

  // `RegExpExec` abstract operation
  // https://tc39.es/ecma262/#sec-regexpexec
  var regexpExecAbstract = function (R, S) {
    var exec = R.exec;
    if (typeof exec === 'function') {
      var result = exec.call(R, S);
      if (typeof result !== 'object') {
        throw TypeError('RegExp exec method returned something other than an Object or null');
      }
      return result;
    }

    if (classofRaw(R) !== 'RegExp') {
      throw TypeError('RegExp#exec called on incompatible receiver');
    }

    return regexpExec.call(R, S);
  };

  var arrayPush = [].push;
  var min\$4 = Math.min;
  var MAX_UINT32 = 0xFFFFFFFF;

  // babel-minify transpiles RegExp('x', 'y') -> /x/y and it causes SyntaxError
  var SUPPORTS_Y = !fails(function () { return !RegExp(MAX_UINT32, 'y'); });

  // @@split logic
  fixRegexpWellKnownSymbolLogic('split', 2, function (SPLIT, nativeSplit, maybeCallNative) {
    var internalSplit;
    if (
      'abbc'.split(/(b)*/)[1] == 'c' ||
      // eslint-disable-next-line regexp/no-empty-group -- required for testing
      'test'.split(/(?:)/, -1).length != 4 ||
      'ab'.split(/(?:ab)*/).length != 2 ||
      '.'.split(/(.?)(.?)/).length != 4 ||
      // eslint-disable-next-line regexp/no-assertion-capturing-group, regexp/no-empty-group -- required for testing
      '.'.split(/()()/).length > 1 ||
      ''.split(/.?/).length
    ) {
      // based on es5-shim implementation, need to rework it
      internalSplit = function (separator, limit) {
        var string = String(requireObjectCoercible(this));
        var lim = limit === undefined ? MAX_UINT32 : limit >>> 0;
        if (lim === 0) return [];
        if (separator === undefined) return [string];
        // If `separator` is not a regex, use native split
        if (!isRegexp(separator)) {
          return nativeSplit.call(string, separator, lim);
        }
        var output = [];
        var flags = (separator.ignoreCase ? 'i' : '') +
                    (separator.multiline ? 'm' : '') +
                    (separator.unicode ? 'u' : '') +
                    (separator.sticky ? 'y' : '');
        var lastLastIndex = 0;
        // Make `global` and avoid `lastIndex` issues by working with a copy
        var separatorCopy = new RegExp(separator.source, flags + 'g');
        var match, lastIndex, lastLength;
        while (match = regexpExec.call(separatorCopy, string)) {
          lastIndex = separatorCopy.lastIndex;
          if (lastIndex > lastLastIndex) {
            output.push(string.slice(lastLastIndex, match.index));
            if (match.length > 1 && match.index < string.length) arrayPush.apply(output, match.slice(1));
            lastLength = match[0].length;
            lastLastIndex = lastIndex;
            if (output.length >= lim) break;
          }
          if (separatorCopy.lastIndex === match.index) separatorCopy.lastIndex++; // Avoid an infinite loop
        }
        if (lastLastIndex === string.length) {
          if (lastLength || !separatorCopy.test('')) output.push('');
        } else output.push(string.slice(lastLastIndex));
        return output.length > lim ? output.slice(0, lim) : output;
      };
    // Chakra, V8
    } else if ('0'.split(undefined, 0).length) {
      internalSplit = function (separator, limit) {
        return separator === undefined && limit === 0 ? [] : nativeSplit.call(this, separator, limit);
      };
    } else internalSplit = nativeSplit;

    return [
      // `String.prototype.split` method
      // https://tc39.es/ecma262/#sec-string.prototype.split
      function split(separator, limit) {
        var O = requireObjectCoercible(this);
        var splitter = separator == undefined ? undefined : separator[SPLIT];
        return splitter !== undefined
          ? splitter.call(separator, O, limit)
          : internalSplit.call(String(O), separator, limit);
      },
      // `RegExp.prototype[@@split]` method
      // https://tc39.es/ecma262/#sec-regexp.prototype-@@split
      //
      // NOTE: This cannot be properly polyfilled in engines that don't support
      // the 'y' flag.
      function (regexp, limit) {
        var res = maybeCallNative(internalSplit, regexp, this, limit, internalSplit !== nativeSplit);
        if (res.done) return res.value;

        var rx = anObject(regexp);
        var S = String(this);
        var C = speciesConstructor(rx, RegExp);

        var unicodeMatching = rx.unicode;
        var flags = (rx.ignoreCase ? 'i' : '') +
                    (rx.multiline ? 'm' : '') +
                    (rx.unicode ? 'u' : '') +
                    (SUPPORTS_Y ? 'y' : 'g');

        // ^(? + rx + ) is needed, in combination with some S slicing, to
        // simulate the 'y' flag.
        var splitter = new C(SUPPORTS_Y ? rx : '^(?:' + rx.source + ')', flags);
        var lim = limit === undefined ? MAX_UINT32 : limit >>> 0;
        if (lim === 0) return [];
        if (S.length === 0) return regexpExecAbstract(splitter, S) === null ? [S] : [];
        var p = 0;
        var q = 0;
        var A = [];
        while (q < S.length) {
          splitter.lastIndex = SUPPORTS_Y ? q : 0;
          var z = regexpExecAbstract(splitter, SUPPORTS_Y ? S : S.slice(q));
          var e;
          if (
            z === null ||
            (e = min\$4(toLength(splitter.lastIndex + (SUPPORTS_Y ? 0 : q)), S.length)) === p
          ) {
            q = advanceStringIndex(S, q, unicodeMatching);
          } else {
            A.push(S.slice(p, q));
            if (A.length === lim) return A;
            for (var i = 1; i <= z.length - 1; i++) {
              A.push(z[i]);
              if (A.length === lim) return A;
            }
            q = p = e;
          }
        }
        A.push(S.slice(p));
        return A;
      }
    ];
  }, !SUPPORTS_Y);

  // `Object.keys` method
  // https://tc39.es/ecma262/#sec-object.keys
  var objectKeys = Object.keys || function keys(O) {
    return objectKeysInternal(O, enumBugKeys);
  };

  // `Object.defineProperties` method
  // https://tc39.es/ecma262/#sec-object.defineproperties
  var objectDefineProperties = descriptors ? Object.defineProperties : function defineProperties(O, Properties) {
    anObject(O);
    var keys = objectKeys(Properties);
    var length = keys.length;
    var index = 0;
    var key;
    while (length > index) objectDefineProperty.f(O, key = keys[index++], Properties[key]);
    return O;
  };

  var html = getBuiltIn('document', 'documentElement');

  var GT = '>';
  var LT = '<';
  var PROTOTYPE = 'prototype';
  var SCRIPT = 'script';
  var IE_PROTO\$1 = sharedKey('IE_PROTO');

  var EmptyConstructor = function () { /* empty */ };

  var scriptTag = function (content) {
    return LT + SCRIPT + GT + content + LT + '/' + SCRIPT + GT;
  };

  // Create object with fake `null` prototype: use ActiveX Object with cleared prototype
  var NullProtoObjectViaActiveX = function (activeXDocument) {
    activeXDocument.write(scriptTag(''));
    activeXDocument.close();
    var temp = activeXDocument.parentWindow.Object;
    activeXDocument = null; // avoid memory leak
    return temp;
  };

  // Create object with fake `null` prototype: use iframe Object with cleared prototype
  var NullProtoObjectViaIFrame = function () {
    // Thrash, waste and sodomy: IE GC bug
    var iframe = documentCreateElement('iframe');
    var JS = 'java' + SCRIPT + ':';
    var iframeDocument;
    iframe.style.display = 'none';
    html.appendChild(iframe);
    // https://github.com/zloirock/core-js/issues/475
    iframe.src = String(JS);
    iframeDocument = iframe.contentWindow.document;
    iframeDocument.open();
    iframeDocument.write(scriptTag('document.F=Object'));
    iframeDocument.close();
    return iframeDocument.F;
  };

  // Check for document.domain and active x support
  // No need to use active x approach when document.domain is not set
  // see https://github.com/es-shims/es5-shim/issues/150
  // variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346
  // avoid IE GC bug
  var activeXDocument;
  var NullProtoObject = function () {
    try {
      /* global ActiveXObject -- old IE */
      activeXDocument = document.domain && new ActiveXObject('htmlfile');
    } catch (error) { /* ignore */ }
    NullProtoObject = activeXDocument ? NullProtoObjectViaActiveX(activeXDocument) : NullProtoObjectViaIFrame();
    var length = enumBugKeys.length;
    while (length--) delete NullProtoObject[PROTOTYPE][enumBugKeys[length]];
    return NullProtoObject();
  };

  hiddenKeys\$1[IE_PROTO\$1] = true;

  // `Object.create` method
  // https://tc39.es/ecma262/#sec-object.create
  var objectCreate = Object.create || function create(O, Properties) {
    var result;
    if (O !== null) {
      EmptyConstructor[PROTOTYPE] = anObject(O);
      result = new EmptyConstructor();
      EmptyConstructor[PROTOTYPE] = null;
      // add \"__proto__\" for Object.getPrototypeOf polyfill
      result[IE_PROTO\$1] = O;
    } else result = NullProtoObject();
    return Properties === undefined ? result : objectDefineProperties(result, Properties);
  };

  var UNSCOPABLES = wellKnownSymbol('unscopables');
  var ArrayPrototype = Array.prototype;

  // Array.prototype[@@unscopables]
  // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
  if (ArrayPrototype[UNSCOPABLES] == undefined) {
    objectDefineProperty.f(ArrayPrototype, UNSCOPABLES, {
      configurable: true,
      value: objectCreate(null)
    });
  }

  // add a key to Array.prototype[@@unscopables]
  var addToUnscopables = function (key) {
    ArrayPrototype[UNSCOPABLES][key] = true;
  };

  var \$includes = arrayIncludes.includes;


  // `Array.prototype.includes` method
  // https://tc39.es/ecma262/#sec-array.prototype.includes
  _export({ target: 'Array', proto: true }, {
    includes: function includes(el /* , fromIndex = 0 */) {
      return \$includes(this, el, arguments.length > 1 ? arguments[1] : undefined);
    }
  });

  // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
  addToUnscopables('includes');

  // `IsArray` abstract operation
  // https://tc39.es/ecma262/#sec-isarray
  var isArray = Array.isArray || function isArray(arg) {
    return classofRaw(arg) == 'Array';
  };

  // `ToObject` abstract operation
  // https://tc39.es/ecma262/#sec-toobject
  var toObject = function (argument) {
    return Object(requireObjectCoercible(argument));
  };

  var createProperty = function (object, key, value) {
    var propertyKey = toPrimitive(key);
    if (propertyKey in object) objectDefineProperty.f(object, propertyKey, createPropertyDescriptor(0, value));
    else object[propertyKey] = value;
  };

  var SPECIES\$3 = wellKnownSymbol('species');

  // `ArraySpeciesCreate` abstract operation
  // https://tc39.es/ecma262/#sec-arrayspeciescreate
  var arraySpeciesCreate = function (originalArray, length) {
    var C;
    if (isArray(originalArray)) {
      C = originalArray.constructor;
      // cross-realm fallback
      if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined;
      else if (isObject(C)) {
        C = C[SPECIES\$3];
        if (C === null) C = undefined;
      }
    } return new (C === undefined ? Array : C)(length === 0 ? 0 : length);
  };

  var SPECIES\$2 = wellKnownSymbol('species');

  var arrayMethodHasSpeciesSupport = function (METHOD_NAME) {
    // We can't use this feature detection in V8 since it causes
    // deoptimization and serious performance degradation
    // https://github.com/zloirock/core-js/issues/677
    return engineV8Version >= 51 || !fails(function () {
      var array = [];
      var constructor = array.constructor = {};
      constructor[SPECIES\$2] = function () {
        return { foo: 1 };
      };
      return array[METHOD_NAME](Boolean).foo !== 1;
    });
  };

  var IS_CONCAT_SPREADABLE = wellKnownSymbol('isConcatSpreadable');
  var MAX_SAFE_INTEGER\$1 = 0x1FFFFFFFFFFFFF;
  var MAXIMUM_ALLOWED_INDEX_EXCEEDED = 'Maximum allowed index exceeded';

  // We can't use this feature detection in V8 since it causes
  // deoptimization and serious performance degradation
  // https://github.com/zloirock/core-js/issues/679
  var IS_CONCAT_SPREADABLE_SUPPORT = engineV8Version >= 51 || !fails(function () {
    var array = [];
    array[IS_CONCAT_SPREADABLE] = false;
    return array.concat()[0] !== array;
  });

  var SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('concat');

  var isConcatSpreadable = function (O) {
    if (!isObject(O)) return false;
    var spreadable = O[IS_CONCAT_SPREADABLE];
    return spreadable !== undefined ? !!spreadable : isArray(O);
  };

  var FORCED\$4 = !IS_CONCAT_SPREADABLE_SUPPORT || !SPECIES_SUPPORT;

  // `Array.prototype.concat` method
  // https://tc39.es/ecma262/#sec-array.prototype.concat
  // with adding support of @@isConcatSpreadable and @@species
  _export({ target: 'Array', proto: true, forced: FORCED\$4 }, {
    // eslint-disable-next-line no-unused-vars -- required for `.length`
    concat: function concat(arg) {
      var O = toObject(this);
      var A = arraySpeciesCreate(O, 0);
      var n = 0;
      var i, k, length, len, E;
      for (i = -1, length = arguments.length; i < length; i++) {
        E = i === -1 ? O : arguments[i];
        if (isConcatSpreadable(E)) {
          len = toLength(E.length);
          if (n + len > MAX_SAFE_INTEGER\$1) throw TypeError(MAXIMUM_ALLOWED_INDEX_EXCEEDED);
          for (k = 0; k < len; k++, n++) if (k in E) createProperty(A, n, E[k]);
        } else {
          if (n >= MAX_SAFE_INTEGER\$1) throw TypeError(MAXIMUM_ALLOWED_INDEX_EXCEEDED);
          createProperty(A, n++, E);
        }
      }
      A.length = n;
      return A;
    }
  });

  // optional / simple context binding
  var functionBindContext = function (fn, that, length) {
    aFunction(fn);
    if (that === undefined) return fn;
    switch (length) {
      case 0: return function () {
        return fn.call(that);
      };
      case 1: return function (a) {
        return fn.call(that, a);
      };
      case 2: return function (a, b) {
        return fn.call(that, a, b);
      };
      case 3: return function (a, b, c) {
        return fn.call(that, a, b, c);
      };
    }
    return function (/* ...args */) {
      return fn.apply(that, arguments);
    };
  };

  var push = [].push;

  // `Array.prototype.{ forEach, map, filter, some, every, find, findIndex, filterOut }` methods implementation
  var createMethod\$1 = function (TYPE) {
    var IS_MAP = TYPE == 1;
    var IS_FILTER = TYPE == 2;
    var IS_SOME = TYPE == 3;
    var IS_EVERY = TYPE == 4;
    var IS_FIND_INDEX = TYPE == 6;
    var IS_FILTER_OUT = TYPE == 7;
    var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;
    return function (\$this, callbackfn, that, specificCreate) {
      var O = toObject(\$this);
      var self = indexedObject(O);
      var boundFunction = functionBindContext(callbackfn, that, 3);
      var length = toLength(self.length);
      var index = 0;
      var create = specificCreate || arraySpeciesCreate;
      var target = IS_MAP ? create(\$this, length) : IS_FILTER || IS_FILTER_OUT ? create(\$this, 0) : undefined;
      var value, result;
      for (;length > index; index++) if (NO_HOLES || index in self) {
        value = self[index];
        result = boundFunction(value, index, O);
        if (TYPE) {
          if (IS_MAP) target[index] = result; // map
          else if (result) switch (TYPE) {
            case 3: return true;              // some
            case 5: return value;             // find
            case 6: return index;             // findIndex
            case 2: push.call(target, value); // filter
          } else switch (TYPE) {
            case 4: return false;             // every
            case 7: push.call(target, value); // filterOut
          }
        }
      }
      return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : target;
    };
  };

  var arrayIteration = {
    // `Array.prototype.forEach` method
    // https://tc39.es/ecma262/#sec-array.prototype.foreach
    forEach: createMethod\$1(0),
    // `Array.prototype.map` method
    // https://tc39.es/ecma262/#sec-array.prototype.map
    map: createMethod\$1(1),
    // `Array.prototype.filter` method
    // https://tc39.es/ecma262/#sec-array.prototype.filter
    filter: createMethod\$1(2),
    // `Array.prototype.some` method
    // https://tc39.es/ecma262/#sec-array.prototype.some
    some: createMethod\$1(3),
    // `Array.prototype.every` method
    // https://tc39.es/ecma262/#sec-array.prototype.every
    every: createMethod\$1(4),
    // `Array.prototype.find` method
    // https://tc39.es/ecma262/#sec-array.prototype.find
    find: createMethod\$1(5),
    // `Array.prototype.findIndex` method
    // https://tc39.es/ecma262/#sec-array.prototype.findIndex
    findIndex: createMethod\$1(6),
    // `Array.prototype.filterOut` method
    // https://github.com/tc39/proposal-array-filtering
    filterOut: createMethod\$1(7)
  };

  var \$find = arrayIteration.find;


  var FIND = 'find';
  var SKIPS_HOLES\$1 = true;

  // Shouldn't skip holes
  if (FIND in []) Array(1)[FIND](function () { SKIPS_HOLES\$1 = false; });

  // `Array.prototype.find` method
  // https://tc39.es/ecma262/#sec-array.prototype.find
  _export({ target: 'Array', proto: true, forced: SKIPS_HOLES\$1 }, {
    find: function find(callbackfn /* , that = undefined */) {
      return \$find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
    }
  });

  // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
  addToUnscopables(FIND);

  var notARegexp = function (it) {
    if (isRegexp(it)) {
      throw TypeError(\"The method doesn't accept regular expressions\");
    } return it;
  };

  var MATCH\$1 = wellKnownSymbol('match');

  var correctIsRegexpLogic = function (METHOD_NAME) {
    var regexp = /./;
    try {
      '/./'[METHOD_NAME](regexp);
    } catch (error1) {
      try {
        regexp[MATCH\$1] = false;
        return '/./'[METHOD_NAME](regexp);
      } catch (error2) { /* empty */ }
    } return false;
  };

  // `String.prototype.includes` method
  // https://tc39.es/ecma262/#sec-string.prototype.includes
  _export({ target: 'String', proto: true, forced: !correctIsRegexpLogic('includes') }, {
    includes: function includes(searchString /* , position = 0 */) {
      return !!~String(requireObjectCoercible(this))
        .indexOf(notARegexp(searchString), arguments.length > 1 ? arguments[1] : undefined);
    }
  });

  // iterable DOM collections
  // flag - `iterable` interface - 'entries', 'keys', 'values', 'forEach' methods
  var domIterables = {
    CSSRuleList: 0,
    CSSStyleDeclaration: 0,
    CSSValueList: 0,
    ClientRectList: 0,
    DOMRectList: 0,
    DOMStringList: 0,
    DOMTokenList: 1,
    DataTransferItemList: 0,
    FileList: 0,
    HTMLAllCollection: 0,
    HTMLCollection: 0,
    HTMLFormElement: 0,
    HTMLSelectElement: 0,
    MediaList: 0,
    MimeTypeArray: 0,
    NamedNodeMap: 0,
    NodeList: 1,
    PaintRequestList: 0,
    Plugin: 0,
    PluginArray: 0,
    SVGLengthList: 0,
    SVGNumberList: 0,
    SVGPathSegList: 0,
    SVGPointList: 0,
    SVGStringList: 0,
    SVGTransformList: 0,
    SourceBufferList: 0,
    StyleSheetList: 0,
    TextTrackCueList: 0,
    TextTrackList: 0,
    TouchList: 0
  };

  var \$forEach = arrayIteration.forEach;


  var STRICT_METHOD\$2 = arrayMethodIsStrict('forEach');

  // `Array.prototype.forEach` method implementation
  // https://tc39.es/ecma262/#sec-array.prototype.foreach
  var arrayForEach = !STRICT_METHOD\$2 ? function forEach(callbackfn /* , thisArg */) {
    return \$forEach(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
  } : [].forEach;

  for (var COLLECTION_NAME\$1 in domIterables) {
    var Collection\$1 = global_1[COLLECTION_NAME\$1];
    var CollectionPrototype\$1 = Collection\$1 && Collection\$1.prototype;
    // some Chrome versions have non-configurable methods on DOMTokenList
    if (CollectionPrototype\$1 && CollectionPrototype\$1.forEach !== arrayForEach) try {
      createNonEnumerableProperty(CollectionPrototype\$1, 'forEach', arrayForEach);
    } catch (error) {
      CollectionPrototype\$1.forEach = arrayForEach;
    }
  }

  var trim\$2 = stringTrim.trim;


  var \$parseFloat = global_1.parseFloat;
  var FORCED\$3 = 1 / \$parseFloat(whitespaces + '-0') !== -Infinity;

  // `parseFloat` method
  // https://tc39.es/ecma262/#sec-parsefloat-string
  var numberParseFloat = FORCED\$3 ? function parseFloat(string) {
    var trimmedString = trim\$2(String(string));
    var result = \$parseFloat(trimmedString);
    return result === 0 && trimmedString.charAt(0) == '-' ? -0 : result;
  } : \$parseFloat;

  // `parseFloat` method
  // https://tc39.es/ecma262/#sec-parsefloat-string
  _export({ global: true, forced: parseFloat != numberParseFloat }, {
    parseFloat: numberParseFloat
  });

  var propertyIsEnumerable = objectPropertyIsEnumerable.f;

  // `Object.{ entries, values }` methods implementation
  var createMethod = function (TO_ENTRIES) {
    return function (it) {
      var O = toIndexedObject(it);
      var keys = objectKeys(O);
      var length = keys.length;
      var i = 0;
      var result = [];
      var key;
      while (length > i) {
        key = keys[i++];
        if (!descriptors || propertyIsEnumerable.call(O, key)) {
          result.push(TO_ENTRIES ? [key, O[key]] : O[key]);
        }
      }
      return result;
    };
  };

  var objectToArray = {
    // `Object.entries` method
    // https://tc39.es/ecma262/#sec-object.entries
    entries: createMethod(true),
    // `Object.values` method
    // https://tc39.es/ecma262/#sec-object.values
    values: createMethod(false)
  };

  var \$entries = objectToArray.entries;

  // `Object.entries` method
  // https://tc39.es/ecma262/#sec-object.entries
  _export({ target: 'Object', stat: true }, {
    entries: function entries(O) {
      return \$entries(O);
    }
  });

  var \$indexOf = arrayIncludes.indexOf;


  var nativeIndexOf = [].indexOf;

  var NEGATIVE_ZERO = !!nativeIndexOf && 1 / [1].indexOf(1, -0) < 0;
  var STRICT_METHOD\$1 = arrayMethodIsStrict('indexOf');

  // `Array.prototype.indexOf` method
  // https://tc39.es/ecma262/#sec-array.prototype.indexof
  _export({ target: 'Array', proto: true, forced: NEGATIVE_ZERO || !STRICT_METHOD\$1 }, {
    indexOf: function indexOf(searchElement /* , fromIndex = 0 */) {
      return NEGATIVE_ZERO
        // convert -0 to +0
        ? nativeIndexOf.apply(this, arguments) || 0
        : \$indexOf(this, searchElement, arguments.length > 1 ? arguments[1] : undefined);
    }
  });

  var test\$2 = [];
  var nativeSort = test\$2.sort;

  // IE8-
  var FAILS_ON_UNDEFINED = fails(function () {
    test\$2.sort(undefined);
  });
  // V8 bug
  var FAILS_ON_NULL = fails(function () {
    test\$2.sort(null);
  });
  // Old WebKit
  var STRICT_METHOD = arrayMethodIsStrict('sort');

  var FORCED\$2 = FAILS_ON_UNDEFINED || !FAILS_ON_NULL || !STRICT_METHOD;

  // `Array.prototype.sort` method
  // https://tc39.es/ecma262/#sec-array.prototype.sort
  _export({ target: 'Array', proto: true, forced: FORCED\$2 }, {
    sort: function sort(comparefn) {
      return comparefn === undefined
        ? nativeSort.call(toObject(this))
        : nativeSort.call(toObject(this), aFunction(comparefn));
    }
  });

  var floor = Math.floor;
  var replace = ''.replace;
  var SUBSTITUTION_SYMBOLS = /\\\$([\$&'`]|\\d{1,2}|<[^>]*>)/g;
  var SUBSTITUTION_SYMBOLS_NO_NAMED = /\\\$([\$&'`]|\\d{1,2})/g;

  // https://tc39.es/ecma262/#sec-getsubstitution
  var getSubstitution = function (matched, str, position, captures, namedCaptures, replacement) {
    var tailPos = position + matched.length;
    var m = captures.length;
    var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED;
    if (namedCaptures !== undefined) {
      namedCaptures = toObject(namedCaptures);
      symbols = SUBSTITUTION_SYMBOLS;
    }
    return replace.call(replacement, symbols, function (match, ch) {
      var capture;
      switch (ch.charAt(0)) {
        case '\$': return '\$';
        case '&': return matched;
        case '`': return str.slice(0, position);
        case \"'\": return str.slice(tailPos);
        case '<':
          capture = namedCaptures[ch.slice(1, -1)];
          break;
        default: // \\d\\d?
          var n = +ch;
          if (n === 0) return match;
          if (n > m) {
            var f = floor(n / 10);
            if (f === 0) return match;
            if (f <= m) return captures[f - 1] === undefined ? ch.charAt(1) : captures[f - 1] + ch.charAt(1);
            return match;
          }
          capture = captures[n - 1];
      }
      return capture === undefined ? '' : capture;
    });
  };

  var max\$2 = Math.max;
  var min\$3 = Math.min;

  var maybeToString = function (it) {
    return it === undefined ? it : String(it);
  };

  // @@replace logic
  fixRegexpWellKnownSymbolLogic('replace', 2, function (REPLACE, nativeReplace, maybeCallNative, reason) {
    var REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE = reason.REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE;
    var REPLACE_KEEPS_\$0 = reason.REPLACE_KEEPS_\$0;
    var UNSAFE_SUBSTITUTE = REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE ? '\$' : '\$0';

    return [
      // `String.prototype.replace` method
      // https://tc39.es/ecma262/#sec-string.prototype.replace
      function replace(searchValue, replaceValue) {
        var O = requireObjectCoercible(this);
        var replacer = searchValue == undefined ? undefined : searchValue[REPLACE];
        return replacer !== undefined
          ? replacer.call(searchValue, O, replaceValue)
          : nativeReplace.call(String(O), searchValue, replaceValue);
      },
      // `RegExp.prototype[@@replace]` method
      // https://tc39.es/ecma262/#sec-regexp.prototype-@@replace
      function (regexp, replaceValue) {
        if (
          (!REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE && REPLACE_KEEPS_\$0) ||
          (typeof replaceValue === 'string' && replaceValue.indexOf(UNSAFE_SUBSTITUTE) === -1)
        ) {
          var res = maybeCallNative(nativeReplace, regexp, this, replaceValue);
          if (res.done) return res.value;
        }

        var rx = anObject(regexp);
        var S = String(this);

        var functionalReplace = typeof replaceValue === 'function';
        if (!functionalReplace) replaceValue = String(replaceValue);

        var global = rx.global;
        if (global) {
          var fullUnicode = rx.unicode;
          rx.lastIndex = 0;
        }
        var results = [];
        while (true) {
          var result = regexpExecAbstract(rx, S);
          if (result === null) break;

          results.push(result);
          if (!global) break;

          var matchStr = String(result[0]);
          if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength(rx.lastIndex), fullUnicode);
        }

        var accumulatedResult = '';
        var nextSourcePosition = 0;
        for (var i = 0; i < results.length; i++) {
          result = results[i];

          var matched = String(result[0]);
          var position = max\$2(min\$3(toInteger(result.index), S.length), 0);
          var captures = [];
          // NOTE: This is equivalent to
          //   captures = result.slice(1).map(maybeToString)
          // but for some reason `nativeSlice.call(result, 1, result.length)` (called in
          // the slice polyfill when slicing native arrays) \"doesn't work\" in safari 9 and
          // causes a crash (https://pastebin.com/N21QzeQA) when trying to debug it.
          for (var j = 1; j < result.length; j++) captures.push(maybeToString(result[j]));
          var namedCaptures = result.groups;
          if (functionalReplace) {
            var replacerArgs = [matched].concat(captures, position, S);
            if (namedCaptures !== undefined) replacerArgs.push(namedCaptures);
            var replacement = String(replaceValue.apply(undefined, replacerArgs));
          } else {
            replacement = getSubstitution(matched, S, position, captures, namedCaptures, replaceValue);
          }
          if (position >= nextSourcePosition) {
            accumulatedResult += S.slice(nextSourcePosition, position) + replacement;
            nextSourcePosition = position + matched.length;
          }
        }
        return accumulatedResult + S.slice(nextSourcePosition);
      }
    ];
  });

  var nativeAssign = Object.assign;
  var defineProperty\$3 = Object.defineProperty;

  // `Object.assign` method
  // https://tc39.es/ecma262/#sec-object.assign
  var objectAssign = !nativeAssign || fails(function () {
    // should have correct order of operations (Edge bug)
    if (descriptors && nativeAssign({ b: 1 }, nativeAssign(defineProperty\$3({}, 'a', {
      enumerable: true,
      get: function () {
        defineProperty\$3(this, 'b', {
          value: 3,
          enumerable: false
        });
      }
    }), { b: 2 })).b !== 1) return true;
    // should work with symbols and should have deterministic property order (V8 bug)
    var A = {};
    var B = {};
    /* global Symbol -- required for testing */
    var symbol = Symbol();
    var alphabet = 'abcdefghijklmnopqrst';
    A[symbol] = 7;
    alphabet.split('').forEach(function (chr) { B[chr] = chr; });
    return nativeAssign({}, A)[symbol] != 7 || objectKeys(nativeAssign({}, B)).join('') != alphabet;
  }) ? function assign(target, source) { // eslint-disable-line no-unused-vars -- required for `.length`
    var T = toObject(target);
    var argumentsLength = arguments.length;
    var index = 1;
    var getOwnPropertySymbols = objectGetOwnPropertySymbols.f;
    var propertyIsEnumerable = objectPropertyIsEnumerable.f;
    while (argumentsLength > index) {
      var S = indexedObject(arguments[index++]);
      var keys = getOwnPropertySymbols ? objectKeys(S).concat(getOwnPropertySymbols(S)) : objectKeys(S);
      var length = keys.length;
      var j = 0;
      var key;
      while (length > j) {
        key = keys[j++];
        if (!descriptors || propertyIsEnumerable.call(S, key)) T[key] = S[key];
      }
    } return T;
  } : nativeAssign;

  // `Object.assign` method
  // https://tc39.es/ecma262/#sec-object.assign
  _export({ target: 'Object', stat: true, forced: Object.assign !== objectAssign }, {
    assign: objectAssign
  });

  var \$filter = arrayIteration.filter;


  var HAS_SPECIES_SUPPORT\$3 = arrayMethodHasSpeciesSupport('filter');

  // `Array.prototype.filter` method
  // https://tc39.es/ecma262/#sec-array.prototype.filter
  // with adding support of @@species
  _export({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT\$3 }, {
    filter: function filter(callbackfn /* , thisArg */) {
      return \$filter(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
    }
  });

  // `SameValue` abstract operation
  // https://tc39.es/ecma262/#sec-samevalue
  var sameValue = Object.is || function is(x, y) {
    // eslint-disable-next-line no-self-compare -- NaN check
    return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y;
  };

  // @@search logic
  fixRegexpWellKnownSymbolLogic('search', 1, function (SEARCH, nativeSearch, maybeCallNative) {
    return [
      // `String.prototype.search` method
      // https://tc39.es/ecma262/#sec-string.prototype.search
      function search(regexp) {
        var O = requireObjectCoercible(this);
        var searcher = regexp == undefined ? undefined : regexp[SEARCH];
        return searcher !== undefined ? searcher.call(regexp, O) : new RegExp(regexp)[SEARCH](String(O));
      },
      // `RegExp.prototype[@@search]` method
      // https://tc39.es/ecma262/#sec-regexp.prototype-@@search
      function (regexp) {
        var res = maybeCallNative(nativeSearch, regexp, this);
        if (res.done) return res.value;

        var rx = anObject(regexp);
        var S = String(this);

        var previousLastIndex = rx.lastIndex;
        if (!sameValue(previousLastIndex, 0)) rx.lastIndex = 0;
        var result = regexpExecAbstract(rx, S);
        if (!sameValue(rx.lastIndex, previousLastIndex)) rx.lastIndex = previousLastIndex;
        return result === null ? -1 : result.index;
      }
    ];
  });

  var trim\$1 = stringTrim.trim;


  var \$parseInt = global_1.parseInt;
  var hex = /^[+-]?0[Xx]/;
  var FORCED\$1 = \$parseInt(whitespaces + '08') !== 8 || \$parseInt(whitespaces + '0x16') !== 22;

  // `parseInt` method
  // https://tc39.es/ecma262/#sec-parseint-string-radix
  var numberParseInt = FORCED\$1 ? function parseInt(string, radix) {
    var S = trim\$1(String(string));
    return \$parseInt(S, (radix >>> 0) || (hex.test(S) ? 16 : 10));
  } : \$parseInt;

  // `parseInt` method
  // https://tc39.es/ecma262/#sec-parseint-string-radix
  _export({ global: true, forced: parseInt != numberParseInt }, {
    parseInt: numberParseInt
  });

  var \$map = arrayIteration.map;


  var HAS_SPECIES_SUPPORT\$2 = arrayMethodHasSpeciesSupport('map');

  // `Array.prototype.map` method
  // https://tc39.es/ecma262/#sec-array.prototype.map
  // with adding support of @@species
  _export({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT\$2 }, {
    map: function map(callbackfn /* , thisArg */) {
      return \$map(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
    }
  });

  var \$findIndex = arrayIteration.findIndex;


  var FIND_INDEX = 'findIndex';
  var SKIPS_HOLES = true;

  // Shouldn't skip holes
  if (FIND_INDEX in []) Array(1)[FIND_INDEX](function () { SKIPS_HOLES = false; });

  // `Array.prototype.findIndex` method
  // https://tc39.es/ecma262/#sec-array.prototype.findindex
  _export({ target: 'Array', proto: true, forced: SKIPS_HOLES }, {
    findIndex: function findIndex(callbackfn /* , that = undefined */) {
      return \$findIndex(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
    }
  });

  // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
  addToUnscopables(FIND_INDEX);

  var aPossiblePrototype = function (it) {
    if (!isObject(it) && it !== null) {
      throw TypeError(\"Can't set \" + String(it) + ' as a prototype');
    } return it;
  };

  /* eslint-disable no-proto -- safe */



  // `Object.setPrototypeOf` method
  // https://tc39.es/ecma262/#sec-object.setprototypeof
  // Works with __proto__ only. Old v8 can't work with null proto objects.
  var objectSetPrototypeOf = Object.setPrototypeOf || ('__proto__' in {} ? function () {
    var CORRECT_SETTER = false;
    var test = {};
    var setter;
    try {
      setter = Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').set;
      setter.call(test, []);
      CORRECT_SETTER = test instanceof Array;
    } catch (error) { /* empty */ }
    return function setPrototypeOf(O, proto) {
      anObject(O);
      aPossiblePrototype(proto);
      if (CORRECT_SETTER) setter.call(O, proto);
      else O.__proto__ = proto;
      return O;
    };
  }() : undefined);

  // makes subclassing work correct for wrapped built-ins
  var inheritIfRequired = function (\$this, dummy, Wrapper) {
    var NewTarget, NewTargetPrototype;
    if (
      // it can work only with native `setPrototypeOf`
      objectSetPrototypeOf &&
      // we haven't completely correct pre-ES6 way for getting `new.target`, so use this
      typeof (NewTarget = dummy.constructor) == 'function' &&
      NewTarget !== Wrapper &&
      isObject(NewTargetPrototype = NewTarget.prototype) &&
      NewTargetPrototype !== Wrapper.prototype
    ) objectSetPrototypeOf(\$this, NewTargetPrototype);
    return \$this;
  };

  var SPECIES\$1 = wellKnownSymbol('species');

  var setSpecies = function (CONSTRUCTOR_NAME) {
    var Constructor = getBuiltIn(CONSTRUCTOR_NAME);
    var defineProperty = objectDefineProperty.f;

    if (descriptors && Constructor && !Constructor[SPECIES\$1]) {
      defineProperty(Constructor, SPECIES\$1, {
        configurable: true,
        get: function () { return this; }
      });
    }
  };

  var defineProperty\$2 = objectDefineProperty.f;
  var getOwnPropertyNames\$1 = objectGetOwnPropertyNames.f;





  var setInternalState\$1 = internalState.set;



  var MATCH = wellKnownSymbol('match');
  var NativeRegExp = global_1.RegExp;
  var RegExpPrototype\$1 = NativeRegExp.prototype;
  var re1 = /a/g;
  var re2 = /a/g;

  // \"new\" should create a new object, old webkit bug
  var CORRECT_NEW = new NativeRegExp(re1) !== re1;

  var UNSUPPORTED_Y = regexpStickyHelpers.UNSUPPORTED_Y;

  var FORCED = descriptors && isForced_1('RegExp', (!CORRECT_NEW || UNSUPPORTED_Y || fails(function () {
    re2[MATCH] = false;
    // RegExp constructor can alter flags and IsRegExp works correct with @@match
    return NativeRegExp(re1) != re1 || NativeRegExp(re2) == re2 || NativeRegExp(re1, 'i') != '/a/i';
  })));

  // `RegExp` constructor
  // https://tc39.es/ecma262/#sec-regexp-constructor
  if (FORCED) {
    var RegExpWrapper = function RegExp(pattern, flags) {
      var thisIsRegExp = this instanceof RegExpWrapper;
      var patternIsRegExp = isRegexp(pattern);
      var flagsAreUndefined = flags === undefined;
      var sticky;

      if (!thisIsRegExp && patternIsRegExp && pattern.constructor === RegExpWrapper && flagsAreUndefined) {
        return pattern;
      }

      if (CORRECT_NEW) {
        if (patternIsRegExp && !flagsAreUndefined) pattern = pattern.source;
      } else if (pattern instanceof RegExpWrapper) {
        if (flagsAreUndefined) flags = regexpFlags.call(pattern);
        pattern = pattern.source;
      }

      if (UNSUPPORTED_Y) {
        sticky = !!flags && flags.indexOf('y') > -1;
        if (sticky) flags = flags.replace(/y/g, '');
      }

      var result = inheritIfRequired(
        CORRECT_NEW ? new NativeRegExp(pattern, flags) : NativeRegExp(pattern, flags),
        thisIsRegExp ? this : RegExpPrototype\$1,
        RegExpWrapper
      );

      if (UNSUPPORTED_Y && sticky) setInternalState\$1(result, { sticky: sticky });

      return result;
    };
    var proxy = function (key) {
      key in RegExpWrapper || defineProperty\$2(RegExpWrapper, key, {
        configurable: true,
        get: function () { return NativeRegExp[key]; },
        set: function (it) { NativeRegExp[key] = it; }
      });
    };
    var keys\$1 = getOwnPropertyNames\$1(NativeRegExp);
    var index = 0;
    while (keys\$1.length > index) proxy(keys\$1[index++]);
    RegExpPrototype\$1.constructor = RegExpWrapper;
    RegExpWrapper.prototype = RegExpPrototype\$1;
    redefine(global_1, 'RegExp', RegExpWrapper);
  }

  // https://tc39.es/ecma262/#sec-get-regexp-@@species
  setSpecies('RegExp');

  var TO_STRING = 'toString';
  var RegExpPrototype = RegExp.prototype;
  var nativeToString = RegExpPrototype[TO_STRING];

  var NOT_GENERIC = fails(function () { return nativeToString.call({ source: 'a', flags: 'b' }) != '/a/b'; });
  // FF44- RegExp#toString has a wrong name
  var INCORRECT_NAME = nativeToString.name != TO_STRING;

  // `RegExp.prototype.toString` method
  // https://tc39.es/ecma262/#sec-regexp.prototype.tostring
  if (NOT_GENERIC || INCORRECT_NAME) {
    redefine(RegExp.prototype, TO_STRING, function toString() {
      var R = anObject(this);
      var p = String(R.source);
      var rf = R.flags;
      var f = String(rf === undefined && R instanceof RegExp && !('flags' in RegExpPrototype) ? regexpFlags.call(R) : rf);
      return '/' + p + '/' + f;
    }, { unsafe: true });
  }

  var TO_STRING_TAG\$3 = wellKnownSymbol('toStringTag');
  var test\$1 = {};

  test\$1[TO_STRING_TAG\$3] = 'z';

  var toStringTagSupport = String(test\$1) === '[object z]';

  var TO_STRING_TAG\$2 = wellKnownSymbol('toStringTag');
  // ES3 wrong here
  var CORRECT_ARGUMENTS = classofRaw(function () { return arguments; }()) == 'Arguments';

  // fallback for IE11 Script Access Denied error
  var tryGet = function (it, key) {
    try {
      return it[key];
    } catch (error) { /* empty */ }
  };

  // getting tag from ES6+ `Object.prototype.toString`
  var classof = toStringTagSupport ? classofRaw : function (it) {
    var O, tag, result;
    return it === undefined ? 'Undefined' : it === null ? 'Null'
      // @@toStringTag case
      : typeof (tag = tryGet(O = Object(it), TO_STRING_TAG\$2)) == 'string' ? tag
      // builtinTag case
      : CORRECT_ARGUMENTS ? classofRaw(O)
      // ES3 arguments fallback
      : (result = classofRaw(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : result;
  };

  // `Object.prototype.toString` method implementation
  // https://tc39.es/ecma262/#sec-object.prototype.tostring
  var objectToString = toStringTagSupport ? {}.toString : function toString() {
    return '[object ' + classof(this) + ']';
  };

  // `Object.prototype.toString` method
  // https://tc39.es/ecma262/#sec-object.prototype.tostring
  if (!toStringTagSupport) {
    redefine(Object.prototype, 'toString', objectToString, { unsafe: true });
  }

  var HAS_SPECIES_SUPPORT\$1 = arrayMethodHasSpeciesSupport('slice');

  var SPECIES = wellKnownSymbol('species');
  var nativeSlice = [].slice;
  var max\$1 = Math.max;

  // `Array.prototype.slice` method
  // https://tc39.es/ecma262/#sec-array.prototype.slice
  // fallback for not array-like ES3 strings and DOM objects
  _export({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT\$1 }, {
    slice: function slice(start, end) {
      var O = toIndexedObject(this);
      var length = toLength(O.length);
      var k = toAbsoluteIndex(start, length);
      var fin = toAbsoluteIndex(end === undefined ? length : end, length);
      // inline `ArraySpeciesCreate` for usage native `Array#slice` where it's possible
      var Constructor, result, n;
      if (isArray(O)) {
        Constructor = O.constructor;
        // cross-realm fallback
        if (typeof Constructor == 'function' && (Constructor === Array || isArray(Constructor.prototype))) {
          Constructor = undefined;
        } else if (isObject(Constructor)) {
          Constructor = Constructor[SPECIES];
          if (Constructor === null) Constructor = undefined;
        }
        if (Constructor === Array || Constructor === undefined) {
          return nativeSlice.call(O, k, fin);
        }
      }
      result = new (Constructor === undefined ? Array : Constructor)(max\$1(fin - k, 0));
      for (n = 0; k < fin; k++, n++) if (k in O) createProperty(result, n, O[k]);
      result.length = n;
      return result;
    }
  });

  var correctPrototypeGetter = !fails(function () {
    function F() { /* empty */ }
    F.prototype.constructor = null;
    return Object.getPrototypeOf(new F()) !== F.prototype;
  });

  var IE_PROTO = sharedKey('IE_PROTO');
  var ObjectPrototype = Object.prototype;

  // `Object.getPrototypeOf` method
  // https://tc39.es/ecma262/#sec-object.getprototypeof
  var objectGetPrototypeOf = correctPrototypeGetter ? Object.getPrototypeOf : function (O) {
    O = toObject(O);
    if (has\$1(O, IE_PROTO)) return O[IE_PROTO];
    if (typeof O.constructor == 'function' && O instanceof O.constructor) {
      return O.constructor.prototype;
    } return O instanceof Object ? ObjectPrototype : null;
  };

  var ITERATOR\$2 = wellKnownSymbol('iterator');
  var BUGGY_SAFARI_ITERATORS\$1 = false;

  var returnThis\$1 = function () { return this; };

  // `%IteratorPrototype%` object
  // https://tc39.es/ecma262/#sec-%iteratorprototype%-object
  var IteratorPrototype\$2, PrototypeOfArrayIteratorPrototype, arrayIterator;

  if ([].keys) {
    arrayIterator = [].keys();
    // Safari 8 has buggy iterators w/o `next`
    if (!('next' in arrayIterator)) BUGGY_SAFARI_ITERATORS\$1 = true;
    else {
      PrototypeOfArrayIteratorPrototype = objectGetPrototypeOf(objectGetPrototypeOf(arrayIterator));
      if (PrototypeOfArrayIteratorPrototype !== Object.prototype) IteratorPrototype\$2 = PrototypeOfArrayIteratorPrototype;
    }
  }

  var NEW_ITERATOR_PROTOTYPE = IteratorPrototype\$2 == undefined || fails(function () {
    var test = {};
    // FF44- legacy iterators case
    return IteratorPrototype\$2[ITERATOR\$2].call(test) !== test;
  });

  if (NEW_ITERATOR_PROTOTYPE) IteratorPrototype\$2 = {};

  // 25.1.2.1.1 %IteratorPrototype%[@@iterator]()
  if (!has\$1(IteratorPrototype\$2, ITERATOR\$2)) {
    createNonEnumerableProperty(IteratorPrototype\$2, ITERATOR\$2, returnThis\$1);
  }

  var iteratorsCore = {
    IteratorPrototype: IteratorPrototype\$2,
    BUGGY_SAFARI_ITERATORS: BUGGY_SAFARI_ITERATORS\$1
  };

  var defineProperty\$1 = objectDefineProperty.f;



  var TO_STRING_TAG\$1 = wellKnownSymbol('toStringTag');

  var setToStringTag = function (it, TAG, STATIC) {
    if (it && !has\$1(it = STATIC ? it : it.prototype, TO_STRING_TAG\$1)) {
      defineProperty\$1(it, TO_STRING_TAG\$1, { configurable: true, value: TAG });
    }
  };

  var IteratorPrototype\$1 = iteratorsCore.IteratorPrototype;

  var createIteratorConstructor = function (IteratorConstructor, NAME, next) {
    var TO_STRING_TAG = NAME + ' Iterator';
    IteratorConstructor.prototype = objectCreate(IteratorPrototype\$1, { next: createPropertyDescriptor(1, next) });
    setToStringTag(IteratorConstructor, TO_STRING_TAG, false);
    return IteratorConstructor;
  };

  var IteratorPrototype = iteratorsCore.IteratorPrototype;
  var BUGGY_SAFARI_ITERATORS = iteratorsCore.BUGGY_SAFARI_ITERATORS;
  var ITERATOR\$1 = wellKnownSymbol('iterator');
  var KEYS = 'keys';
  var VALUES = 'values';
  var ENTRIES = 'entries';

  var returnThis = function () { return this; };

  var defineIterator = function (Iterable, NAME, IteratorConstructor, next, DEFAULT, IS_SET, FORCED) {
    createIteratorConstructor(IteratorConstructor, NAME, next);

    var getIterationMethod = function (KIND) {
      if (KIND === DEFAULT && defaultIterator) return defaultIterator;
      if (!BUGGY_SAFARI_ITERATORS && KIND in IterablePrototype) return IterablePrototype[KIND];
      switch (KIND) {
        case KEYS: return function keys() { return new IteratorConstructor(this, KIND); };
        case VALUES: return function values() { return new IteratorConstructor(this, KIND); };
        case ENTRIES: return function entries() { return new IteratorConstructor(this, KIND); };
      } return function () { return new IteratorConstructor(this); };
    };

    var TO_STRING_TAG = NAME + ' Iterator';
    var INCORRECT_VALUES_NAME = false;
    var IterablePrototype = Iterable.prototype;
    var nativeIterator = IterablePrototype[ITERATOR\$1]
      || IterablePrototype['@@iterator']
      || DEFAULT && IterablePrototype[DEFAULT];
    var defaultIterator = !BUGGY_SAFARI_ITERATORS && nativeIterator || getIterationMethod(DEFAULT);
    var anyNativeIterator = NAME == 'Array' ? IterablePrototype.entries || nativeIterator : nativeIterator;
    var CurrentIteratorPrototype, methods, KEY;

    // fix native
    if (anyNativeIterator) {
      CurrentIteratorPrototype = objectGetPrototypeOf(anyNativeIterator.call(new Iterable()));
      if (IteratorPrototype !== Object.prototype && CurrentIteratorPrototype.next) {
        if (objectGetPrototypeOf(CurrentIteratorPrototype) !== IteratorPrototype) {
          if (objectSetPrototypeOf) {
            objectSetPrototypeOf(CurrentIteratorPrototype, IteratorPrototype);
          } else if (typeof CurrentIteratorPrototype[ITERATOR\$1] != 'function') {
            createNonEnumerableProperty(CurrentIteratorPrototype, ITERATOR\$1, returnThis);
          }
        }
        // Set @@toStringTag to native iterators
        setToStringTag(CurrentIteratorPrototype, TO_STRING_TAG, true);
      }
    }

    // fix Array#{values, @@iterator}.name in V8 / FF
    if (DEFAULT == VALUES && nativeIterator && nativeIterator.name !== VALUES) {
      INCORRECT_VALUES_NAME = true;
      defaultIterator = function values() { return nativeIterator.call(this); };
    }

    // define iterator
    if (IterablePrototype[ITERATOR\$1] !== defaultIterator) {
      createNonEnumerableProperty(IterablePrototype, ITERATOR\$1, defaultIterator);
    }

    // export additional methods
    if (DEFAULT) {
      methods = {
        values: getIterationMethod(VALUES),
        keys: IS_SET ? defaultIterator : getIterationMethod(KEYS),
        entries: getIterationMethod(ENTRIES)
      };
      if (FORCED) for (KEY in methods) {
        if (BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME || !(KEY in IterablePrototype)) {
          redefine(IterablePrototype, KEY, methods[KEY]);
        }
      } else _export({ target: NAME, proto: true, forced: BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME }, methods);
    }

    return methods;
  };

  var ARRAY_ITERATOR = 'Array Iterator';
  var setInternalState = internalState.set;
  var getInternalState = internalState.getterFor(ARRAY_ITERATOR);

  // `Array.prototype.entries` method
  // https://tc39.es/ecma262/#sec-array.prototype.entries
  // `Array.prototype.keys` method
  // https://tc39.es/ecma262/#sec-array.prototype.keys
  // `Array.prototype.values` method
  // https://tc39.es/ecma262/#sec-array.prototype.values
  // `Array.prototype[@@iterator]` method
  // https://tc39.es/ecma262/#sec-array.prototype-@@iterator
  // `CreateArrayIterator` internal method
  // https://tc39.es/ecma262/#sec-createarrayiterator
  var es_array_iterator = defineIterator(Array, 'Array', function (iterated, kind) {
    setInternalState(this, {
      type: ARRAY_ITERATOR,
      target: toIndexedObject(iterated), // target
      index: 0,                          // next index
      kind: kind                         // kind
    });
  // `%ArrayIteratorPrototype%.next` method
  // https://tc39.es/ecma262/#sec-%arrayiteratorprototype%.next
  }, function () {
    var state = getInternalState(this);
    var target = state.target;
    var kind = state.kind;
    var index = state.index++;
    if (!target || index >= target.length) {
      state.target = undefined;
      return { value: undefined, done: true };
    }
    if (kind == 'keys') return { value: index, done: false };
    if (kind == 'values') return { value: target[index], done: false };
    return { value: [index, target[index]], done: false };
  }, 'values');

  // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
  addToUnscopables('keys');
  addToUnscopables('values');
  addToUnscopables('entries');

  var ITERATOR = wellKnownSymbol('iterator');
  var TO_STRING_TAG = wellKnownSymbol('toStringTag');
  var ArrayValues = es_array_iterator.values;

  for (var COLLECTION_NAME in domIterables) {
    var Collection = global_1[COLLECTION_NAME];
    var CollectionPrototype = Collection && Collection.prototype;
    if (CollectionPrototype) {
      // some Chrome versions have non-configurable methods on DOMTokenList
      if (CollectionPrototype[ITERATOR] !== ArrayValues) try {
        createNonEnumerableProperty(CollectionPrototype, ITERATOR, ArrayValues);
      } catch (error) {
        CollectionPrototype[ITERATOR] = ArrayValues;
      }
      if (!CollectionPrototype[TO_STRING_TAG]) {
        createNonEnumerableProperty(CollectionPrototype, TO_STRING_TAG, COLLECTION_NAME);
      }
      if (domIterables[COLLECTION_NAME]) for (var METHOD_NAME in es_array_iterator) {
        // some Chrome versions have non-configurable methods on DOMTokenList
        if (CollectionPrototype[METHOD_NAME] !== es_array_iterator[METHOD_NAME]) try {
          createNonEnumerableProperty(CollectionPrototype, METHOD_NAME, es_array_iterator[METHOD_NAME]);
        } catch (error) {
          CollectionPrototype[METHOD_NAME] = es_array_iterator[METHOD_NAME];
        }
      }
    }
  }

  var HAS_SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('splice');

  var max = Math.max;
  var min\$2 = Math.min;
  var MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF;
  var MAXIMUM_ALLOWED_LENGTH_EXCEEDED = 'Maximum allowed length exceeded';

  // `Array.prototype.splice` method
  // https://tc39.es/ecma262/#sec-array.prototype.splice
  // with adding support of @@species
  _export({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT }, {
    splice: function splice(start, deleteCount /* , ...items */) {
      var O = toObject(this);
      var len = toLength(O.length);
      var actualStart = toAbsoluteIndex(start, len);
      var argumentsLength = arguments.length;
      var insertCount, actualDeleteCount, A, k, from, to;
      if (argumentsLength === 0) {
        insertCount = actualDeleteCount = 0;
      } else if (argumentsLength === 1) {
        insertCount = 0;
        actualDeleteCount = len - actualStart;
      } else {
        insertCount = argumentsLength - 2;
        actualDeleteCount = min\$2(max(toInteger(deleteCount), 0), len - actualStart);
      }
      if (len + insertCount - actualDeleteCount > MAX_SAFE_INTEGER) {
        throw TypeError(MAXIMUM_ALLOWED_LENGTH_EXCEEDED);
      }
      A = arraySpeciesCreate(O, actualDeleteCount);
      for (k = 0; k < actualDeleteCount; k++) {
        from = actualStart + k;
        if (from in O) createProperty(A, k, O[from]);
      }
      A.length = actualDeleteCount;
      if (insertCount < actualDeleteCount) {
        for (k = actualStart; k < len - actualDeleteCount; k++) {
          from = k + actualDeleteCount;
          to = k + insertCount;
          if (from in O) O[to] = O[from];
          else delete O[to];
        }
        for (k = len; k > len - actualDeleteCount + insertCount; k--) delete O[k - 1];
      } else if (insertCount > actualDeleteCount) {
        for (k = len - actualDeleteCount; k > actualStart; k--) {
          from = k + actualDeleteCount - 1;
          to = k + insertCount - 1;
          if (from in O) O[to] = O[from];
          else delete O[to];
        }
      }
      for (k = 0; k < insertCount; k++) {
        O[k + actualStart] = arguments[k + 2];
      }
      O.length = len - actualDeleteCount + insertCount;
      return A;
    }
  });

  var getOwnPropertyNames = objectGetOwnPropertyNames.f;
  var getOwnPropertyDescriptor\$2 = objectGetOwnPropertyDescriptor.f;
  var defineProperty = objectDefineProperty.f;
  var trim = stringTrim.trim;

  var NUMBER = 'Number';
  var NativeNumber = global_1[NUMBER];
  var NumberPrototype = NativeNumber.prototype;

  // Opera ~12 has broken Object#toString
  var BROKEN_CLASSOF = classofRaw(objectCreate(NumberPrototype)) == NUMBER;

  // `ToNumber` abstract operation
  // https://tc39.es/ecma262/#sec-tonumber
  var toNumber = function (argument) {
    var it = toPrimitive(argument, false);
    var first, third, radix, maxCode, digits, length, index, code;
    if (typeof it == 'string' && it.length > 2) {
      it = trim(it);
      first = it.charCodeAt(0);
      if (first === 43 || first === 45) {
        third = it.charCodeAt(2);
        if (third === 88 || third === 120) return NaN; // Number('+0x1') should be NaN, old V8 fix
      } else if (first === 48) {
        switch (it.charCodeAt(1)) {
          case 66: case 98: radix = 2; maxCode = 49; break; // fast equal of /^0b[01]+\$/i
          case 79: case 111: radix = 8; maxCode = 55; break; // fast equal of /^0o[0-7]+\$/i
          default: return +it;
        }
        digits = it.slice(2);
        length = digits.length;
        for (index = 0; index < length; index++) {
          code = digits.charCodeAt(index);
          // parseInt parses a string to a first unavailable symbol
          // but ToNumber should return NaN if a string contains unavailable symbols
          if (code < 48 || code > maxCode) return NaN;
        } return parseInt(digits, radix);
      }
    } return +it;
  };

  // `Number` constructor
  // https://tc39.es/ecma262/#sec-number-constructor
  if (isForced_1(NUMBER, !NativeNumber(' 0o1') || !NativeNumber('0b1') || NativeNumber('+0x1'))) {
    var NumberWrapper = function Number(value) {
      var it = arguments.length < 1 ? 0 : value;
      var dummy = this;
      return dummy instanceof NumberWrapper
        // check on 1..constructor(foo) case
        && (BROKEN_CLASSOF ? fails(function () { NumberPrototype.valueOf.call(dummy); }) : classofRaw(dummy) != NUMBER)
          ? inheritIfRequired(new NativeNumber(toNumber(it)), dummy, NumberWrapper) : toNumber(it);
    };
    for (var keys = descriptors ? getOwnPropertyNames(NativeNumber) : (
      // ES3:
      'MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,' +
      // ES2015 (in case, if modules with ES2015 Number statics required before):
      'EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,' +
      'MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger,' +
      // ESNext
      'fromString,range'
    ).split(','), j = 0, key; keys.length > j; j++) {
      if (has\$1(NativeNumber, key = keys[j]) && !has\$1(NumberWrapper, key)) {
        defineProperty(NumberWrapper, key, getOwnPropertyDescriptor\$2(NativeNumber, key));
      }
    }
    NumberWrapper.prototype = NumberPrototype;
    NumberPrototype.constructor = NumberWrapper;
    redefine(global_1, NUMBER, NumberWrapper);
  }

  var nativeReverse = [].reverse;
  var test = [1, 2];

  // `Array.prototype.reverse` method
  // https://tc39.es/ecma262/#sec-array.prototype.reverse
  // fix for Safari 12.0 bug
  // https://bugs.webkit.org/show_bug.cgi?id=188794
  _export({ target: 'Array', proto: true, forced: String(test) === String(test.reverse()) }, {
    reverse: function reverse() {
      // eslint-disable-next-line no-self-assign -- dirty hack
      if (isArray(this)) this.length = this.length;
      return nativeReverse.call(this);
    }
  });

  /* eslint-disable no-unused-vars */

  var VERSION = '1.18.3';
  var bootstrapVersion = 4;

  try {
    var rawVersion = \$__default['default'].fn.dropdown.Constructor.VERSION; // Only try to parse VERSION if it is defined.
    // It is undefined in older versions of Bootstrap (tested with 3.1.1).

    if (rawVersion !== undefined) {
      bootstrapVersion = parseInt(rawVersion, 10);
    }
  } catch (e) {// ignore
  }

  try {
    // eslint-disable-next-line no-undef
    var _rawVersion = bootstrap.Tooltip.VERSION;

    if (_rawVersion !== undefined) {
      bootstrapVersion = parseInt(_rawVersion, 10);
    }
  } catch (e) {// ignore
  }

  var CONSTANTS = {
    3: {
      iconsPrefix: 'glyphicon',
      icons: {
        paginationSwitchDown: 'glyphicon-collapse-down icon-chevron-down',
        paginationSwitchUp: 'glyphicon-collapse-up icon-chevron-up',
        refresh: 'glyphicon-refresh icon-refresh',
        toggleOff: 'glyphicon-list-alt icon-list-alt',
        toggleOn: 'glyphicon-list-alt icon-list-alt',
        columns: 'glyphicon-th icon-th',
        detailOpen: 'glyphicon-plus icon-plus',
        detailClose: 'glyphicon-minus icon-minus',
        fullscreen: 'glyphicon-fullscreen',
        search: 'glyphicon-search',
        clearSearch: 'glyphicon-trash'
      },
      classes: {
        buttonsPrefix: 'btn',
        buttons: 'default',
        buttonsGroup: 'btn-group',
        buttonsDropdown: 'btn-group',
        pull: 'pull',
        inputGroup: 'input-group',
        inputPrefix: 'input-',
        input: 'form-control',
        paginationDropdown: 'btn-group dropdown',
        dropup: 'dropup',
        dropdownActive: 'active',
        paginationActive: 'active',
        buttonActive: 'active'
      },
      html: {
        toolbarDropdown: ['<ul class=\"dropdown-menu\" role=\"menu\">', '</ul>'],
        toolbarDropdownItem: '<li class=\"dropdown-item-marker\" role=\"menuitem\"><label>%s</label></li>',
        toolbarDropdownSeparator: '<li class=\"divider\"></li>',
        pageDropdown: ['<ul class=\"dropdown-menu\" role=\"menu\">', '</ul>'],
        pageDropdownItem: '<li role=\"menuitem\" class=\"%s\"><a href=\"#\">%s</a></li>',
        dropdownCaret: '<span class=\"caret\"></span>',
        pagination: ['<ul class=\"pagination%s\">', '</ul>'],
        paginationItem: '<li class=\"page-item%s\"><a class=\"page-link\" aria-label=\"%s\" href=\"javascript:void(0)\">%s</a></li>',
        icon: '<i class=\"%s %s\"></i>',
        inputGroup: '<div class=\"input-group\">%s<span class=\"input-group-btn\">%s</span></div>',
        searchInput: '<input class=\"%s%s\" type=\"text\" placeholder=\"%s\">',
        searchButton: '<button class=\"%s\" type=\"button\" name=\"search\" title=\"%s\">%s %s</button>',
        searchClearButton: '<button class=\"%s\" type=\"button\" name=\"clearSearch\" title=\"%s\">%s %s</button>'
      }
    },
    4: {
      iconsPrefix: 'fa',
      icons: {
        paginationSwitchDown: 'fa-caret-square-down',
        paginationSwitchUp: 'fa-caret-square-up',
        refresh: 'fa-sync',
        toggleOff: 'fa-toggle-off',
        toggleOn: 'fa-toggle-on',
        columns: 'fa-th-list',
        detailOpen: 'fa-plus',
        detailClose: 'fa-minus',
        fullscreen: 'fa-arrows-alt',
        search: 'fa-search',
        clearSearch: 'fa-trash'
      },
      classes: {
        buttonsPrefix: 'btn',
        buttons: 'secondary',
        buttonsGroup: 'btn-group',
        buttonsDropdown: 'btn-group',
        pull: 'float',
        inputGroup: 'btn-group',
        inputPrefix: 'form-control-',
        input: 'form-control',
        paginationDropdown: 'btn-group dropdown',
        dropup: 'dropup',
        dropdownActive: 'active',
        paginationActive: 'active',
        buttonActive: 'active'
      },
      html: {
        toolbarDropdown: ['<div class=\"dropdown-menu dropdown-menu-right\">', '</div>'],
        toolbarDropdownItem: '<label class=\"dropdown-item dropdown-item-marker\">%s</label>',
        pageDropdown: ['<div class=\"dropdown-menu\">', '</div>'],
        pageDropdownItem: '<a class=\"dropdown-item %s\" href=\"#\">%s</a>',
        toolbarDropdownSeparator: '<div class=\"dropdown-divider\"></div>',
        dropdownCaret: '<span class=\"caret\"></span>',
        pagination: ['<ul class=\"pagination%s\">', '</ul>'],
        paginationItem: '<li class=\"page-item%s\"><a class=\"page-link\" aria-label=\"%s\" href=\"javascript:void(0)\">%s</a></li>',
        icon: '<i class=\"%s %s\"></i>',
        inputGroup: '<div class=\"input-group\">%s<div class=\"input-group-append\">%s</div></div>',
        searchInput: '<input class=\"%s%s\" type=\"text\" placeholder=\"%s\">',
        searchButton: '<button class=\"%s\" type=\"button\" name=\"search\" title=\"%s\">%s %s</button>',
        searchClearButton: '<button class=\"%s\" type=\"button\" name=\"clearSearch\" title=\"%s\">%s %s</button>'
      }
    },
    5: {
      iconsPrefix: 'fa',
      icons: {
        paginationSwitchDown: 'fa-caret-square-down',
        paginationSwitchUp: 'fa-caret-square-up',
        refresh: 'fa-sync',
        toggleOff: 'fa-toggle-off',
        toggleOn: 'fa-toggle-on',
        columns: 'fa-th-list',
        detailOpen: 'fa-plus',
        detailClose: 'fa-minus',
        fullscreen: 'fa-arrows-alt',
        search: 'fa-search',
        clearSearch: 'fa-trash'
      },
      classes: {
        buttonsPrefix: 'btn',
        buttons: 'secondary',
        buttonsGroup: 'btn-group',
        buttonsDropdown: 'btn-group',
        pull: 'float',
        inputGroup: 'btn-group',
        inputPrefix: 'form-control-',
        input: 'form-control',
        paginationDropdown: 'btn-group dropdown',
        dropup: 'dropup',
        dropdownActive: 'active',
        paginationActive: 'active',
        buttonActive: 'active'
      },
      html: {
        dataToggle: 'data-bs-toggle',
        toolbarDropdown: ['<div class=\"dropdown-menu dropdown-menu-right\">', '</div>'],
        toolbarDropdownItem: '<label class=\"dropdown-item dropdown-item-marker\">%s</label>',
        pageDropdown: ['<div class=\"dropdown-menu\">', '</div>'],
        pageDropdownItem: '<a class=\"dropdown-item %s\" href=\"#\">%s</a>',
        toolbarDropdownSeparator: '<div class=\"dropdown-divider\"></div>',
        dropdownCaret: '<span class=\"caret\"></span>',
        pagination: ['<ul class=\"pagination%s\">', '</ul>'],
        paginationItem: '<li class=\"page-item%s\"><a class=\"page-link\" aria-label=\"%s\" href=\"javascript:void(0)\">%s</a></li>',
        icon: '<i class=\"%s %s\"></i>',
        inputGroup: '<div class=\"input-group\">%s<div class=\"input-group-append\">%s</div></div>',
        searchInput: '<input class=\"%s%s\" type=\"text\" placeholder=\"%s\">',
        searchButton: '<button class=\"%s\" type=\"button\" name=\"search\" title=\"%s\">%s %s</button>',
        searchClearButton: '<button class=\"%s\" type=\"button\" name=\"clearSearch\" title=\"%s\">%s %s</button>'
      }
    }
  }[bootstrapVersion];
  var DEFAULTS = {
    height: undefined,
    classes: 'table table-bordered table-hover',
    buttons: {},
    theadClasses: '',
    headerStyle: function headerStyle(column) {
      return {};
    },
    rowStyle: function rowStyle(row, index) {
      return {};
    },
    rowAttributes: function rowAttributes(row, index) {
      return {};
    },
    undefinedText: '-',
    locale: undefined,
    virtualScroll: false,
    virtualScrollItemHeight: undefined,
    sortable: true,
    sortClass: undefined,
    silentSort: true,
    sortName: undefined,
    sortOrder: undefined,
    sortReset: false,
    sortStable: false,
    rememberOrder: false,
    serverSort: true,
    customSort: undefined,
    columns: [[]],
    data: [],
    url: undefined,
    method: 'get',
    cache: true,
    contentType: 'application/json',
    dataType: 'json',
    ajax: undefined,
    ajaxOptions: {},
    queryParams: function queryParams(params) {
      return params;
    },
    queryParamsType: 'limit',
    // 'limit', undefined
    responseHandler: function responseHandler(res) {
      return res;
    },
    totalField: 'total',
    totalNotFilteredField: 'totalNotFiltered',
    dataField: 'rows',
    footerField: 'footer',
    pagination: false,
    paginationParts: ['pageInfo', 'pageSize', 'pageList'],
    showExtendedPagination: false,
    paginationLoop: true,
    sidePagination: 'client',
    // client or server
    totalRows: 0,
    totalNotFiltered: 0,
    pageNumber: 1,
    pageSize: 10,
    pageList: [10, 25, 50, 100],
    paginationHAlign: 'right',
    // right, left
    paginationVAlign: 'bottom',
    // bottom, top, both
    paginationDetailHAlign: 'left',
    // right, left
    paginationPreText: '&lsaquo;',
    paginationNextText: '&rsaquo;',
    paginationSuccessivelySize: 5,
    // Maximum successively number of pages in a row
    paginationPagesBySide: 1,
    // Number of pages on each side (right, left) of the current page.
    paginationUseIntermediate: false,
    // Calculate intermediate pages for quick access
    search: false,
    searchHighlight: false,
    searchOnEnterKey: false,
    strictSearch: false,
    searchSelector: false,
    visibleSearch: false,
    showButtonIcons: true,
    showButtonText: false,
    showSearchButton: false,
    showSearchClearButton: false,
    trimOnSearch: true,
    searchAlign: 'right',
    searchTimeOut: 500,
    searchText: '',
    customSearch: undefined,
    showHeader: true,
    showFooter: false,
    footerStyle: function footerStyle(column) {
      return {};
    },
    searchAccentNeutralise: false,
    showColumns: false,
    showColumnsToggleAll: false,
    showColumnsSearch: false,
    minimumCountColumns: 1,
    showPaginationSwitch: false,
    showRefresh: false,
    showToggle: false,
    showFullscreen: false,
    smartDisplay: true,
    escape: false,
    filterOptions: {
      filterAlgorithm: 'and'
    },
    idField: undefined,
    selectItemName: 'btSelectItem',
    clickToSelect: false,
    ignoreClickToSelectOn: function ignoreClickToSelectOn(_ref) {
      var tagName = _ref.tagName;
      return ['A', 'BUTTON'].includes(tagName);
    },
    singleSelect: false,
    checkboxHeader: true,
    maintainMetaData: false,
    multipleSelectRow: false,
    uniqueId: undefined,
    cardView: false,
    detailView: false,
    detailViewIcon: true,
    detailViewByClick: false,
    detailViewAlign: 'left',
    detailFormatter: function detailFormatter(index, row) {
      return '';
    },
    detailFilter: function detailFilter(index, row) {
      return true;
    },
    toolbar: undefined,
    toolbarAlign: 'left',
    buttonsToolbar: undefined,
    buttonsAlign: 'right',
    buttonsOrder: ['paginationSwitch', 'refresh', 'toggle', 'fullscreen', 'columns'],
    buttonsPrefix: CONSTANTS.classes.buttonsPrefix,
    buttonsClass: CONSTANTS.classes.buttons,
    icons: CONSTANTS.icons,
    iconSize: undefined,
    iconsPrefix: CONSTANTS.iconsPrefix,
    // glyphicon or fa(font-awesome)
    loadingFontSize: 'auto',
    loadingTemplate: function loadingTemplate(loadingMessage) {
      return \"<span class=\\\"loading-wrap\\\">\\n      <span class=\\\"loading-text\\\">\".concat(loadingMessage, \"</span>\\n      <span class=\\\"animation-wrap\\\"><span class=\\\"animation-dot\\\"></span></span>\\n      </span>\\n    \");
    },
    onAll: function onAll(name, args) {
      return false;
    },
    onClickCell: function onClickCell(field, value, row, \$element) {
      return false;
    },
    onDblClickCell: function onDblClickCell(field, value, row, \$element) {
      return false;
    },
    onClickRow: function onClickRow(item, \$element) {
      return false;
    },
    onDblClickRow: function onDblClickRow(item, \$element) {
      return false;
    },
    onSort: function onSort(name, order) {
      return false;
    },
    onCheck: function onCheck(row) {
      return false;
    },
    onUncheck: function onUncheck(row) {
      return false;
    },
    onCheckAll: function onCheckAll(rows) {
      return false;
    },
    onUncheckAll: function onUncheckAll(rows) {
      return false;
    },
    onCheckSome: function onCheckSome(rows) {
      return false;
    },
    onUncheckSome: function onUncheckSome(rows) {
      return false;
    },
    onLoadSuccess: function onLoadSuccess(data) {
      return false;
    },
    onLoadError: function onLoadError(status) {
      return false;
    },
    onColumnSwitch: function onColumnSwitch(field, checked) {
      return false;
    },
    onPageChange: function onPageChange(number, size) {
      return false;
    },
    onSearch: function onSearch(text) {
      return false;
    },
    onToggle: function onToggle(cardView) {
      return false;
    },
    onPreBody: function onPreBody(data) {
      return false;
    },
    onPostBody: function onPostBody() {
      return false;
    },
    onPostHeader: function onPostHeader() {
      return false;
    },
    onPostFooter: function onPostFooter() {
      return false;
    },
    onExpandRow: function onExpandRow(index, row, \$detail) {
      return false;
    },
    onCollapseRow: function onCollapseRow(index, row) {
      return false;
    },
    onRefreshOptions: function onRefreshOptions(options) {
      return false;
    },
    onRefresh: function onRefresh(params) {
      return false;
    },
    onResetView: function onResetView() {
      return false;
    },
    onScrollBody: function onScrollBody() {
      return false;
    }
  };
  var EN = {
    formatLoadingMessage: function formatLoadingMessage() {
      return 'Loading, please wait';
    },
    formatRecordsPerPage: function formatRecordsPerPage(pageNumber) {
      return \"\".concat(pageNumber, \" rows per page\");
    },
    formatShowingRows: function formatShowingRows(pageFrom, pageTo, totalRows, totalNotFiltered) {
      if (totalNotFiltered !== undefined && totalNotFiltered > 0 && totalNotFiltered > totalRows) {
        return \"Showing \".concat(pageFrom, \" to \").concat(pageTo, \" of \").concat(totalRows, \" rows (filtered from \").concat(totalNotFiltered, \" total rows)\");
      }

      return \"Showing \".concat(pageFrom, \" to \").concat(pageTo, \" of \").concat(totalRows, \" rows\");
    },
    formatSRPaginationPreText: function formatSRPaginationPreText() {
      return 'previous page';
    },
    formatSRPaginationPageText: function formatSRPaginationPageText(page) {
      return \"to page \".concat(page);
    },
    formatSRPaginationNextText: function formatSRPaginationNextText() {
      return 'next page';
    },
    formatDetailPagination: function formatDetailPagination(totalRows) {
      return \"Showing \".concat(totalRows, \" rows\");
    },
    formatSearch: function formatSearch() {
      return 'Search';
    },
    formatClearSearch: function formatClearSearch() {
      return 'Clear Search';
    },
    formatNoMatches: function formatNoMatches() {
      return 'No matching records found';
    },
    formatPaginationSwitch: function formatPaginationSwitch() {
      return 'Hide/Show pagination';
    },
    formatPaginationSwitchDown: function formatPaginationSwitchDown() {
      return 'Show pagination';
    },
    formatPaginationSwitchUp: function formatPaginationSwitchUp() {
      return 'Hide pagination';
    },
    formatRefresh: function formatRefresh() {
      return 'Refresh';
    },
    formatToggle: function formatToggle() {
      return 'Toggle';
    },
    formatToggleOn: function formatToggleOn() {
      return 'Show card view';
    },
    formatToggleOff: function formatToggleOff() {
      return 'Hide card view';
    },
    formatColumns: function formatColumns() {
      return 'Columns';
    },
    formatColumnsToggleAll: function formatColumnsToggleAll() {
      return 'Toggle all';
    },
    formatFullscreen: function formatFullscreen() {
      return 'Fullscreen';
    },
    formatAllRows: function formatAllRows() {
      return 'All';
    }
  };
  var COLUMN_DEFAULTS = {
    field: undefined,
    title: undefined,
    titleTooltip: undefined,
    class: undefined,
    width: undefined,
    widthUnit: 'px',
    rowspan: undefined,
    colspan: undefined,
    align: undefined,
    // left, right, center
    halign: undefined,
    // left, right, center
    falign: undefined,
    // left, right, center
    valign: undefined,
    // top, middle, bottom
    cellStyle: undefined,
    radio: false,
    checkbox: false,
    checkboxEnabled: true,
    clickToSelect: true,
    showSelectTitle: false,
    sortable: false,
    sortName: undefined,
    order: 'asc',
    // asc, desc
    sorter: undefined,
    visible: true,
    switchable: true,
    cardVisible: true,
    searchable: true,
    formatter: undefined,
    footerFormatter: undefined,
    detailFormatter: undefined,
    searchFormatter: true,
    searchHighlightFormatter: false,
    escape: false,
    events: undefined
  };
  var METHODS = ['getOptions', 'refreshOptions', 'getData', 'getSelections', 'load', 'append', 'prepend', 'remove', 'removeAll', 'insertRow', 'updateRow', 'getRowByUniqueId', 'updateByUniqueId', 'removeByUniqueId', 'updateCell', 'updateCellByUniqueId', 'showRow', 'hideRow', 'getHiddenRows', 'showColumn', 'hideColumn', 'getVisibleColumns', 'getHiddenColumns', 'showAllColumns', 'hideAllColumns', 'mergeCells', 'checkAll', 'uncheckAll', 'checkInvert', 'check', 'uncheck', 'checkBy', 'uncheckBy', 'refresh', 'destroy', 'resetView', 'showLoading', 'hideLoading', 'togglePagination', 'toggleFullscreen', 'toggleView', 'resetSearch', 'filterBy', 'scrollTo', 'getScrollPosition', 'selectPage', 'prevPage', 'nextPage', 'toggleDetailView', 'expandRow', 'collapseRow', 'expandRowByUniqueId', 'collapseRowByUniqueId', 'expandAllRows', 'collapseAllRows', 'updateColumnTitle', 'updateFormatText'];
  var EVENTS = {
    'all.bs.table': 'onAll',
    'click-row.bs.table': 'onClickRow',
    'dbl-click-row.bs.table': 'onDblClickRow',
    'click-cell.bs.table': 'onClickCell',
    'dbl-click-cell.bs.table': 'onDblClickCell',
    'sort.bs.table': 'onSort',
    'check.bs.table': 'onCheck',
    'uncheck.bs.table': 'onUncheck',
    'check-all.bs.table': 'onCheckAll',
    'uncheck-all.bs.table': 'onUncheckAll',
    'check-some.bs.table': 'onCheckSome',
    'uncheck-some.bs.table': 'onUncheckSome',
    'load-success.bs.table': 'onLoadSuccess',
    'load-error.bs.table': 'onLoadError',
    'column-switch.bs.table': 'onColumnSwitch',
    'page-change.bs.table': 'onPageChange',
    'search.bs.table': 'onSearch',
    'toggle.bs.table': 'onToggle',
    'pre-body.bs.table': 'onPreBody',
    'post-body.bs.table': 'onPostBody',
    'post-header.bs.table': 'onPostHeader',
    'post-footer.bs.table': 'onPostFooter',
    'expand-row.bs.table': 'onExpandRow',
    'collapse-row.bs.table': 'onCollapseRow',
    'refresh-options.bs.table': 'onRefreshOptions',
    'reset-view.bs.table': 'onResetView',
    'refresh.bs.table': 'onRefresh',
    'scroll-body.bs.table': 'onScrollBody'
  };
  Object.assign(DEFAULTS, EN);
  var Constants = {
    VERSION: VERSION,
    THEME: \"bootstrap\".concat(bootstrapVersion),
    CONSTANTS: CONSTANTS,
    DEFAULTS: DEFAULTS,
    COLUMN_DEFAULTS: COLUMN_DEFAULTS,
    METHODS: METHODS,
    EVENTS: EVENTS,
    LOCALES: {
      en: EN,
      'en-US': EN
    }
  };

  var FAILS_ON_PRIMITIVES = fails(function () { objectKeys(1); });

  // `Object.keys` method
  // https://tc39.es/ecma262/#sec-object.keys
  _export({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES }, {
    keys: function keys(it) {
      return objectKeys(toObject(it));
    }
  });

  var getOwnPropertyDescriptor\$1 = objectGetOwnPropertyDescriptor.f;






  var nativeStartsWith = ''.startsWith;
  var min\$1 = Math.min;

  var CORRECT_IS_REGEXP_LOGIC\$1 = correctIsRegexpLogic('startsWith');
  // https://github.com/zloirock/core-js/pull/702
  var MDN_POLYFILL_BUG\$1 = !CORRECT_IS_REGEXP_LOGIC\$1 && !!function () {
    var descriptor = getOwnPropertyDescriptor\$1(String.prototype, 'startsWith');
    return descriptor && !descriptor.writable;
  }();

  // `String.prototype.startsWith` method
  // https://tc39.es/ecma262/#sec-string.prototype.startswith
  _export({ target: 'String', proto: true, forced: !MDN_POLYFILL_BUG\$1 && !CORRECT_IS_REGEXP_LOGIC\$1 }, {
    startsWith: function startsWith(searchString /* , position = 0 */) {
      var that = String(requireObjectCoercible(this));
      notARegexp(searchString);
      var index = toLength(min\$1(arguments.length > 1 ? arguments[1] : undefined, that.length));
      var search = String(searchString);
      return nativeStartsWith
        ? nativeStartsWith.call(that, search, index)
        : that.slice(index, index + search.length) === search;
    }
  });

  var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f;






  var nativeEndsWith = ''.endsWith;
  var min = Math.min;

  var CORRECT_IS_REGEXP_LOGIC = correctIsRegexpLogic('endsWith');
  // https://github.com/zloirock/core-js/pull/702
  var MDN_POLYFILL_BUG = !CORRECT_IS_REGEXP_LOGIC && !!function () {
    var descriptor = getOwnPropertyDescriptor(String.prototype, 'endsWith');
    return descriptor && !descriptor.writable;
  }();

  // `String.prototype.endsWith` method
  // https://tc39.es/ecma262/#sec-string.prototype.endswith
  _export({ target: 'String', proto: true, forced: !MDN_POLYFILL_BUG && !CORRECT_IS_REGEXP_LOGIC }, {
    endsWith: function endsWith(searchString /* , endPosition = @length */) {
      var that = String(requireObjectCoercible(this));
      notARegexp(searchString);
      var endPosition = arguments.length > 1 ? arguments[1] : undefined;
      var len = toLength(that.length);
      var end = endPosition === undefined ? len : min(toLength(endPosition), len);
      var search = String(searchString);
      return nativeEndsWith
        ? nativeEndsWith.call(that, search, end)
        : that.slice(end - search.length, end) === search;
    }
  });

  var Utils = {
    getSearchInput: function getSearchInput(that) {
      if (typeof that.options.searchSelector === 'string') {
        return \$__default['default'](that.options.searchSelector);
      }

      return that.\$toolbar.find('.search input');
    },
    // it only does '%s', and return '' when arguments are undefined
    sprintf: function sprintf(_str) {
      for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
        args[_key - 1] = arguments[_key];
      }

      var flag = true;
      var i = 0;

      var str = _str.replace(/%s/g, function () {
        var arg = args[i++];

        if (typeof arg === 'undefined') {
          flag = false;
          return '';
        }

        return arg;
      });

      return flag ? str : '';
    },
    isObject: function isObject(val) {
      return val instanceof Object && !Array.isArray(val);
    },
    isEmptyObject: function isEmptyObject() {
      var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      return Object.entries(obj).length === 0 && obj.constructor === Object;
    },
    isNumeric: function isNumeric(n) {
      return !isNaN(parseFloat(n)) && isFinite(n);
    },
    getFieldTitle: function getFieldTitle(list, value) {
      var _iterator = _createForOfIteratorHelper(list),
          _step;

      try {
        for (_iterator.s(); !(_step = _iterator.n()).done;) {
          var item = _step.value;

          if (item.field === value) {
            return item.title;
          }
        }
      } catch (err) {
        _iterator.e(err);
      } finally {
        _iterator.f();
      }

      return '';
    },
    setFieldIndex: function setFieldIndex(columns) {
      var totalCol = 0;
      var flag = [];

      var _iterator2 = _createForOfIteratorHelper(columns[0]),
          _step2;

      try {
        for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
          var column = _step2.value;
          totalCol += column.colspan || 1;
        }
      } catch (err) {
        _iterator2.e(err);
      } finally {
        _iterator2.f();
      }

      for (var i = 0; i < columns.length; i++) {
        flag[i] = [];

        for (var j = 0; j < totalCol; j++) {
          flag[i][j] = false;
        }
      }

      for (var _i = 0; _i < columns.length; _i++) {
        var _iterator3 = _createForOfIteratorHelper(columns[_i]),
            _step3;

        try {
          for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
            var r = _step3.value;
            var rowspan = r.rowspan || 1;
            var colspan = r.colspan || 1;

            var index = flag[_i].indexOf(false);

            r.colspanIndex = index;

            if (colspan === 1) {
              r.fieldIndex = index; // when field is undefined, use index instead

              if (typeof r.field === 'undefined') {
                r.field = index;
              }
            } else {
              r.colspanGroup = r.colspan;
            }

            for (var _j = 0; _j < rowspan; _j++) {
              for (var k = 0; k < colspan; k++) {
                flag[_i + _j][index + k] = true;
              }
            }
          }
        } catch (err) {
          _iterator3.e(err);
        } finally {
          _iterator3.f();
        }
      }
    },
    normalizeAccent: function normalizeAccent(value) {
      if (typeof value !== 'string') {
        return value;
      }

      return value.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '');
    },
    updateFieldGroup: function updateFieldGroup(columns) {
      var _ref;

      var allColumns = (_ref = []).concat.apply(_ref, _toConsumableArray(columns));

      var _iterator4 = _createForOfIteratorHelper(columns),
          _step4;

      try {
        for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
          var c = _step4.value;

          var _iterator5 = _createForOfIteratorHelper(c),
              _step5;

          try {
            for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
              var r = _step5.value;

              if (r.colspanGroup > 1) {
                var colspan = 0;

                var _loop = function _loop(i) {
                  var column = allColumns.find(function (col) {
                    return col.fieldIndex === i;
                  });

                  if (column.visible) {
                    colspan++;
                  }
                };

                for (var i = r.colspanIndex; i < r.colspanIndex + r.colspanGroup; i++) {
                  _loop(i);
                }

                r.colspan = colspan;
                r.visible = colspan > 0;
              }
            }
          } catch (err) {
            _iterator5.e(err);
          } finally {
            _iterator5.f();
          }
        }
      } catch (err) {
        _iterator4.e(err);
      } finally {
        _iterator4.f();
      }
    },
    getScrollBarWidth: function getScrollBarWidth() {
      if (this.cachedWidth === undefined) {
        var \$inner = \$__default['default']('<div/>').addClass('fixed-table-scroll-inner');
        var \$outer = \$__default['default']('<div/>').addClass('fixed-table-scroll-outer');
        \$outer.append(\$inner);
        \$__default['default']('body').append(\$outer);
        var w1 = \$inner[0].offsetWidth;
        \$outer.css('overflow', 'scroll');
        var w2 = \$inner[0].offsetWidth;

        if (w1 === w2) {
          w2 = \$outer[0].clientWidth;
        }

        \$outer.remove();
        this.cachedWidth = w1 - w2;
      }

      return this.cachedWidth;
    },
    calculateObjectValue: function calculateObjectValue(self, name, args, defaultValue) {
      var func = name;

      if (typeof name === 'string') {
        // support obj.func1.func2
        var names = name.split('.');

        if (names.length > 1) {
          func = window;

          var _iterator6 = _createForOfIteratorHelper(names),
              _step6;

          try {
            for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
              var f = _step6.value;
              func = func[f];
            }
          } catch (err) {
            _iterator6.e(err);
          } finally {
            _iterator6.f();
          }
        } else {
          func = window[name];
        }
      }

      if (func !== null && _typeof(func) === 'object') {
        return func;
      }

      if (typeof func === 'function') {
        return func.apply(self, args || []);
      }

      if (!func && typeof name === 'string' && this.sprintf.apply(this, [name].concat(_toConsumableArray(args)))) {
        return this.sprintf.apply(this, [name].concat(_toConsumableArray(args)));
      }

      return defaultValue;
    },
    compareObjects: function compareObjects(objectA, objectB, compareLength) {
      var aKeys = Object.keys(objectA);
      var bKeys = Object.keys(objectB);

      if (compareLength && aKeys.length !== bKeys.length) {
        return false;
      }

      for (var _i2 = 0, _aKeys = aKeys; _i2 < _aKeys.length; _i2++) {
        var key = _aKeys[_i2];

        if (bKeys.includes(key) && objectA[key] !== objectB[key]) {
          return false;
        }
      }

      return true;
    },
    escapeHTML: function escapeHTML(text) {
      if (typeof text === 'string') {
        return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;').replace(/'/g, '&#039;').replace(/`/g, '&#x60;');
      }

      return text;
    },
    unescapeHTML: function unescapeHTML(text) {
      if (typeof text === 'string') {
        return text.replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '\"').replace(/&#039;/g, '\\'').replace(/&#x60;/g, '`');
      }

      return text;
    },
    getRealDataAttr: function getRealDataAttr(dataAttr) {
      for (var _i3 = 0, _Object\$entries = Object.entries(dataAttr); _i3 < _Object\$entries.length; _i3++) {
        var _Object\$entries\$_i = _slicedToArray(_Object\$entries[_i3], 2),
            attr = _Object\$entries\$_i[0],
            value = _Object\$entries\$_i[1];

        var auxAttr = attr.split(/(?=[A-Z])/).join('-').toLowerCase();

        if (auxAttr !== attr) {
          dataAttr[auxAttr] = value;
          delete dataAttr[attr];
        }
      }

      return dataAttr;
    },
    getItemField: function getItemField(item, field, escape) {
      var value = item;

      if (typeof field !== 'string' || item.hasOwnProperty(field)) {
        return escape ? this.escapeHTML(item[field]) : item[field];
      }

      var props = field.split('.');

      var _iterator7 = _createForOfIteratorHelper(props),
          _step7;

      try {
        for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
          var p = _step7.value;
          value = value && value[p];
        }
      } catch (err) {
        _iterator7.e(err);
      } finally {
        _iterator7.f();
      }

      return escape ? this.escapeHTML(value) : value;
    },
    isIEBrowser: function isIEBrowser() {
      return navigator.userAgent.includes('MSIE ') || /Trident.*rv:11\\./.test(navigator.userAgent);
    },
    findIndex: function findIndex(items, item) {
      var _iterator8 = _createForOfIteratorHelper(items),
          _step8;

      try {
        for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
          var it = _step8.value;

          if (JSON.stringify(it) === JSON.stringify(item)) {
            return items.indexOf(it);
          }
        }
      } catch (err) {
        _iterator8.e(err);
      } finally {
        _iterator8.f();
      }

      return -1;
    },
    trToData: function trToData(columns, \$els) {
      var _this = this;

      var data = [];
      var m = [];
      \$els.each(function (y, el) {
        var \$el = \$__default['default'](el);
        var row = {}; // save tr's id, class and data-* attributes

        row._id = \$el.attr('id');
        row._class = \$el.attr('class');
        row._data = _this.getRealDataAttr(\$el.data());
        row._style = \$el.attr('style');
        \$el.find('>td,>th').each(function (_x, el) {
          var \$el = \$__default['default'](el);
          var cspan = +\$el.attr('colspan') || 1;
          var rspan = +\$el.attr('rowspan') || 1;
          var x = _x; // skip already occupied cells in current row

          for (; m[y] && m[y][x]; x++) {// ignore
          } // mark matrix elements occupied by current cell with true


          for (var tx = x; tx < x + cspan; tx++) {
            for (var ty = y; ty < y + rspan; ty++) {
              if (!m[ty]) {
                // fill missing rows
                m[ty] = [];
              }

              m[ty][tx] = true;
            }
          }

          var field = columns[x].field;
          row[field] = \$el.html().trim(); // save td's id, class and data-* attributes

          row[\"_\".concat(field, \"_id\")] = \$el.attr('id');
          row[\"_\".concat(field, \"_class\")] = \$el.attr('class');
          row[\"_\".concat(field, \"_rowspan\")] = \$el.attr('rowspan');
          row[\"_\".concat(field, \"_colspan\")] = \$el.attr('colspan');
          row[\"_\".concat(field, \"_title\")] = \$el.attr('title');
          row[\"_\".concat(field, \"_data\")] = _this.getRealDataAttr(\$el.data());
          row[\"_\".concat(field, \"_style\")] = \$el.attr('style');
        });
        data.push(row);
      });
      return data;
    },
    sort: function sort(a, b, order, sortStable, aPosition, bPosition) {
      if (a === undefined || a === null) {
        a = '';
      }

      if (b === undefined || b === null) {
        b = '';
      }

      if (sortStable && a === b) {
        a = aPosition;
        b = bPosition;
      } // If both values are numeric, do a numeric comparison


      if (this.isNumeric(a) && this.isNumeric(b)) {
        // Convert numerical values form string to float.
        a = parseFloat(a);
        b = parseFloat(b);

        if (a < b) {
          return order * -1;
        }

        if (a > b) {
          return order;
        }

        return 0;
      }

      if (a === b) {
        return 0;
      } // If value is not a string, convert to string


      if (typeof a !== 'string') {
        a = a.toString();
      }

      if (a.localeCompare(b) === -1) {
        return order * -1;
      }

      return order;
    },
    getEventName: function getEventName(eventPrefix) {
      var id = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
      id = id || \"\".concat(+new Date()).concat(~~(Math.random() * 1000000));
      return \"\".concat(eventPrefix, \"-\").concat(id);
    },
    hasDetailViewIcon: function hasDetailViewIcon(options) {
      return options.detailView && options.detailViewIcon && !options.cardView;
    },
    getDetailViewIndexOffset: function getDetailViewIndexOffset(options) {
      return this.hasDetailViewIcon(options) && options.detailViewAlign !== 'right' ? 1 : 0;
    },
    checkAutoMergeCells: function checkAutoMergeCells(data) {
      var _iterator9 = _createForOfIteratorHelper(data),
          _step9;

      try {
        for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
          var row = _step9.value;

          for (var _i4 = 0, _Object\$keys = Object.keys(row); _i4 < _Object\$keys.length; _i4++) {
            var key = _Object\$keys[_i4];

            if (key.startsWith('_') && (key.endsWith('_rowspan') || key.endsWith('_colspan'))) {
              return true;
            }
          }
        }
      } catch (err) {
        _iterator9.e(err);
      } finally {
        _iterator9.f();
      }

      return false;
    },
    deepCopy: function deepCopy(arg) {
      if (arg === undefined) {
        return arg;
      }

      return \$__default['default'].extend(true, Array.isArray(arg) ? [] : {}, arg);
    }
  };

  var BLOCK_ROWS = 50;
  var CLUSTER_BLOCKS = 4;

  var VirtualScroll = /*#__PURE__*/function () {
    function VirtualScroll(options) {
      var _this = this;

      _classCallCheck(this, VirtualScroll);

      this.rows = options.rows;
      this.scrollEl = options.scrollEl;
      this.contentEl = options.contentEl;
      this.callback = options.callback;
      this.itemHeight = options.itemHeight;
      this.cache = {};
      this.scrollTop = this.scrollEl.scrollTop;
      this.initDOM(this.rows, options.fixedScroll);
      this.scrollEl.scrollTop = this.scrollTop;
      this.lastCluster = 0;

      var onScroll = function onScroll() {
        if (_this.lastCluster !== (_this.lastCluster = _this.getNum())) {
          _this.initDOM(_this.rows);

          _this.callback();
        }
      };

      this.scrollEl.addEventListener('scroll', onScroll, false);

      this.destroy = function () {
        _this.contentEl.innerHtml = '';

        _this.scrollEl.removeEventListener('scroll', onScroll, false);
      };
    }

    _createClass(VirtualScroll, [{
      key: \"initDOM\",
      value: function initDOM(rows, fixedScroll) {
        if (typeof this.clusterHeight === 'undefined') {
          this.cache.scrollTop = this.scrollEl.scrollTop;
          this.cache.data = this.contentEl.innerHTML = rows[0] + rows[0] + rows[0];
          this.getRowsHeight(rows);
        }

        var data = this.initData(rows, this.getNum(fixedScroll));
        var thisRows = data.rows.join('');
        var dataChanged = this.checkChanges('data', thisRows);
        var topOffsetChanged = this.checkChanges('top', data.topOffset);
        var bottomOffsetChanged = this.checkChanges('bottom', data.bottomOffset);
        var html = [];

        if (dataChanged && topOffsetChanged) {
          if (data.topOffset) {
            html.push(this.getExtra('top', data.topOffset));
          }

          html.push(thisRows);

          if (data.bottomOffset) {
            html.push(this.getExtra('bottom', data.bottomOffset));
          }

          this.contentEl.innerHTML = html.join('');

          if (fixedScroll) {
            this.contentEl.scrollTop = this.cache.scrollTop;
          }
        } else if (bottomOffsetChanged) {
          this.contentEl.lastChild.style.height = \"\".concat(data.bottomOffset, \"px\");
        }
      }
    }, {
      key: \"getRowsHeight\",
      value: function getRowsHeight() {
        if (typeof this.itemHeight === 'undefined') {
          var nodes = this.contentEl.children;
          var node = nodes[Math.floor(nodes.length / 2)];
          this.itemHeight = node.offsetHeight;
        }

        this.blockHeight = this.itemHeight * BLOCK_ROWS;
        this.clusterRows = BLOCK_ROWS * CLUSTER_BLOCKS;
        this.clusterHeight = this.blockHeight * CLUSTER_BLOCKS;
      }
    }, {
      key: \"getNum\",
      value: function getNum(fixedScroll) {
        this.scrollTop = fixedScroll ? this.cache.scrollTop : this.scrollEl.scrollTop;
        return Math.floor(this.scrollTop / (this.clusterHeight - this.blockHeight)) || 0;
      }
    }, {
      key: \"initData\",
      value: function initData(rows, num) {
        if (rows.length < BLOCK_ROWS) {
          return {
            topOffset: 0,
            bottomOffset: 0,
            rowsAbove: 0,
            rows: rows
          };
        }

        var start = Math.max((this.clusterRows - BLOCK_ROWS) * num, 0);
        var end = start + this.clusterRows;
        var topOffset = Math.max(start * this.itemHeight, 0);
        var bottomOffset = Math.max((rows.length - end) * this.itemHeight, 0);
        var thisRows = [];
        var rowsAbove = start;

        if (topOffset < 1) {
          rowsAbove++;
        }

        for (var i = start; i < end; i++) {
          rows[i] && thisRows.push(rows[i]);
        }

        return {
          topOffset: topOffset,
          bottomOffset: bottomOffset,
          rowsAbove: rowsAbove,
          rows: thisRows
        };
      }
    }, {
      key: \"checkChanges\",
      value: function checkChanges(type, value) {
        var changed = value !== this.cache[type];
        this.cache[type] = value;
        return changed;
      }
    }, {
      key: \"getExtra\",
      value: function getExtra(className, height) {
        var tag = document.createElement('tr');
        tag.className = \"virtual-scroll-\".concat(className);

        if (height) {
          tag.style.height = \"\".concat(height, \"px\");
        }

        return tag.outerHTML;
      }
    }]);

    return VirtualScroll;
  }();

  var BootstrapTable = /*#__PURE__*/function () {
    function BootstrapTable(el, options) {
      _classCallCheck(this, BootstrapTable);

      this.options = options;
      this.\$el = \$__default['default'](el);
      this.\$el_ = this.\$el.clone();
      this.timeoutId_ = 0;
      this.timeoutFooter_ = 0;
    }

    _createClass(BootstrapTable, [{
      key: \"init\",
      value: function init() {
        this.initConstants();
        this.initLocale();
        this.initContainer();
        this.initTable();
        this.initHeader();
        this.initData();
        this.initHiddenRows();
        this.initToolbar();
        this.initPagination();
        this.initBody();
        this.initSearchText();
        this.initServer();
      }
    }, {
      key: \"initConstants\",
      value: function initConstants() {
        var opts = this.options;
        this.constants = Constants.CONSTANTS;
        this.constants.theme = \$__default['default'].fn.bootstrapTable.theme;
        this.constants.dataToggle = this.constants.html.dataToggle || 'data-toggle';
        var buttonsPrefix = opts.buttonsPrefix ? \"\".concat(opts.buttonsPrefix, \"-\") : '';
        this.constants.buttonsClass = [opts.buttonsPrefix, buttonsPrefix + opts.buttonsClass, Utils.sprintf(\"\".concat(buttonsPrefix, \"%s\"), opts.iconSize)].join(' ').trim();
        this.buttons = Utils.calculateObjectValue(this, opts.buttons, [], {});

        if (_typeof(this.buttons) !== 'object') {
          this.buttons = {};
        }

        if (typeof opts.icons === 'string') {
          opts.icons = Utils.calculateObjectValue(null, opts.icons);
        }
      }
    }, {
      key: \"initLocale\",
      value: function initLocale() {
        if (this.options.locale) {
          var locales = \$__default['default'].fn.bootstrapTable.locales;
          var parts = this.options.locale.split(/-|_/);
          parts[0] = parts[0].toLowerCase();

          if (parts[1]) {
            parts[1] = parts[1].toUpperCase();
          }

          if (locales[this.options.locale]) {
            \$__default['default'].extend(this.options, locales[this.options.locale]);
          } else if (locales[parts.join('-')]) {
            \$__default['default'].extend(this.options, locales[parts.join('-')]);
          } else if (locales[parts[0]]) {
            \$__default['default'].extend(this.options, locales[parts[0]]);
          }
        }
      }
    }, {
      key: \"initContainer\",
      value: function initContainer() {
        var topPagination = ['top', 'both'].includes(this.options.paginationVAlign) ? '<div class=\"fixed-table-pagination clearfix\"></div>' : '';
        var bottomPagination = ['bottom', 'both'].includes(this.options.paginationVAlign) ? '<div class=\"fixed-table-pagination\"></div>' : '';
        var loadingTemplate = Utils.calculateObjectValue(this.options, this.options.loadingTemplate, [this.options.formatLoadingMessage()]);
        this.\$container = \$__default['default'](\"\\n      <div class=\\\"bootstrap-table \".concat(this.constants.theme, \"\\\">\\n      <div class=\\\"fixed-table-toolbar\\\"></div>\\n      \").concat(topPagination, \"\\n      <div class=\\\"fixed-table-container\\\">\\n      <div class=\\\"fixed-table-header\\\"><table></table></div>\\n      <div class=\\\"fixed-table-body\\\">\\n      <div class=\\\"fixed-table-loading\\\">\\n      \").concat(loadingTemplate, \"\\n      </div>\\n      </div>\\n      <div class=\\\"fixed-table-footer\\\"></div>\\n      </div>\\n      \").concat(bottomPagination, \"\\n      </div>\\n    \"));
        this.\$container.insertAfter(this.\$el);
        this.\$tableContainer = this.\$container.find('.fixed-table-container');
        this.\$tableHeader = this.\$container.find('.fixed-table-header');
        this.\$tableBody = this.\$container.find('.fixed-table-body');
        this.\$tableLoading = this.\$container.find('.fixed-table-loading');
        this.\$tableFooter = this.\$el.find('tfoot'); // checking if custom table-toolbar exists or not

        if (this.options.buttonsToolbar) {
          this.\$toolbar = \$__default['default']('body').find(this.options.buttonsToolbar);
        } else {
          this.\$toolbar = this.\$container.find('.fixed-table-toolbar');
        }

        this.\$pagination = this.\$container.find('.fixed-table-pagination');
        this.\$tableBody.append(this.\$el);
        this.\$container.after('<div class=\"clearfix\"></div>');
        this.\$el.addClass(this.options.classes);
        this.\$tableLoading.addClass(this.options.classes);

        if (this.options.height) {
          this.\$tableContainer.addClass('fixed-height');

          if (this.options.showFooter) {
            this.\$tableContainer.addClass('has-footer');
          }

          if (this.options.classes.split(' ').includes('table-bordered')) {
            this.\$tableBody.append('<div class=\"fixed-table-border\"></div>');
            this.\$tableBorder = this.\$tableBody.find('.fixed-table-border');
            this.\$tableLoading.addClass('fixed-table-border');
          }

          this.\$tableFooter = this.\$container.find('.fixed-table-footer');
        }
      }
    }, {
      key: \"initTable\",
      value: function initTable() {
        var _this = this;

        var columns = [];
        this.\$header = this.\$el.find('>thead');

        if (!this.\$header.length) {
          this.\$header = \$__default['default'](\"<thead class=\\\"\".concat(this.options.theadClasses, \"\\\"></thead>\")).appendTo(this.\$el);
        } else if (this.options.theadClasses) {
          this.\$header.addClass(this.options.theadClasses);
        }

        this._headerTrClasses = [];
        this._headerTrStyles = [];
        this.\$header.find('tr').each(function (i, el) {
          var \$tr = \$__default['default'](el);
          var column = [];
          \$tr.find('th').each(function (i, el) {
            var \$th = \$__default['default'](el); // #2014: getFieldIndex and elsewhere assume this is string, causes issues if not

            if (typeof \$th.data('field') !== 'undefined') {
              \$th.data('field', \"\".concat(\$th.data('field')));
            }

            column.push(\$__default['default'].extend({}, {
              title: \$th.html(),
              class: \$th.attr('class'),
              titleTooltip: \$th.attr('title'),
              rowspan: \$th.attr('rowspan') ? +\$th.attr('rowspan') : undefined,
              colspan: \$th.attr('colspan') ? +\$th.attr('colspan') : undefined
            }, \$th.data()));
          });
          columns.push(column);

          if (\$tr.attr('class')) {
            _this._headerTrClasses.push(\$tr.attr('class'));
          }

          if (\$tr.attr('style')) {
            _this._headerTrStyles.push(\$tr.attr('style'));
          }
        });

        if (!Array.isArray(this.options.columns[0])) {
          this.options.columns = [this.options.columns];
        }

        this.options.columns = \$__default['default'].extend(true, [], columns, this.options.columns);
        this.columns = [];
        this.fieldsColumnsIndex = [];
        Utils.setFieldIndex(this.options.columns);
        this.options.columns.forEach(function (columns, i) {
          columns.forEach(function (_column, j) {
            var column = \$__default['default'].extend({}, BootstrapTable.COLUMN_DEFAULTS, _column);

            if (typeof column.fieldIndex !== 'undefined') {
              _this.columns[column.fieldIndex] = column;
              _this.fieldsColumnsIndex[column.field] = column.fieldIndex;
            }

            _this.options.columns[i][j] = column;
          });
        }); // if options.data is setting, do not process tbody and tfoot data

        if (!this.options.data.length) {
          var htmlData = Utils.trToData(this.columns, this.\$el.find('>tbody>tr'));

          if (htmlData.length) {
            this.options.data = htmlData;
            this.fromHtml = true;
          }
        }

        if (!(this.options.pagination && this.options.sidePagination !== 'server')) {
          this.footerData = Utils.trToData(this.columns, this.\$el.find('>tfoot>tr'));
        }

        if (this.footerData) {
          this.\$el.find('tfoot').html('<tr></tr>');
        }

        if (!this.options.showFooter || this.options.cardView) {
          this.\$tableFooter.hide();
        } else {
          this.\$tableFooter.show();
        }
      }
    }, {
      key: \"initHeader\",
      value: function initHeader() {
        var _this2 = this;

        var visibleColumns = {};
        var headerHtml = [];
        this.header = {
          fields: [],
          styles: [],
          classes: [],
          formatters: [],
          detailFormatters: [],
          events: [],
          sorters: [],
          sortNames: [],
          cellStyles: [],
          searchables: []
        };
        Utils.updateFieldGroup(this.options.columns);
        this.options.columns.forEach(function (columns, i) {
          var html = [];
          html.push(\"<tr\".concat(Utils.sprintf(' class=\"%s\"', _this2._headerTrClasses[i]), \" \").concat(Utils.sprintf(' style=\"%s\"', _this2._headerTrStyles[i]), \">\"));
          var detailViewTemplate = '';

          if (i === 0 && Utils.hasDetailViewIcon(_this2.options)) {
            var rowspan = _this2.options.columns.length > 1 ? \" rowspan=\\\"\".concat(_this2.options.columns.length, \"\\\"\") : '';
            detailViewTemplate = \"<th class=\\\"detail\\\"\".concat(rowspan, \">\\n          <div class=\\\"fht-cell\\\"></div>\\n          </th>\");
          }

          if (detailViewTemplate && _this2.options.detailViewAlign !== 'right') {
            html.push(detailViewTemplate);
          }

          columns.forEach(function (column, j) {
            var class_ = Utils.sprintf(' class=\"%s\"', column['class']);
            var unitWidth = column.widthUnit;
            var width = parseFloat(column.width);
            var halign = Utils.sprintf('text-align: %s; ', column.halign ? column.halign : column.align);
            var align = Utils.sprintf('text-align: %s; ', column.align);
            var style = Utils.sprintf('vertical-align: %s; ', column.valign);
            style += Utils.sprintf('width: %s; ', (column.checkbox || column.radio) && !width ? !column.showSelectTitle ? '36px' : undefined : width ? width + unitWidth : undefined);

            if (typeof column.fieldIndex === 'undefined' && !column.visible) {
              return;
            }

            var headerStyle = Utils.calculateObjectValue(null, _this2.options.headerStyle, [column]);
            var csses = [];
            var classes = '';

            if (headerStyle && headerStyle.css) {
              for (var _i = 0, _Object\$entries = Object.entries(headerStyle.css); _i < _Object\$entries.length; _i++) {
                var _Object\$entries\$_i = _slicedToArray(_Object\$entries[_i], 2),
                    key = _Object\$entries\$_i[0],
                    value = _Object\$entries\$_i[1];

                csses.push(\"\".concat(key, \": \").concat(value));
              }
            }

            if (headerStyle && headerStyle.classes) {
              classes = Utils.sprintf(' class=\"%s\"', column['class'] ? [column['class'], headerStyle.classes].join(' ') : headerStyle.classes);
            }

            if (typeof column.fieldIndex !== 'undefined') {
              _this2.header.fields[column.fieldIndex] = column.field;
              _this2.header.styles[column.fieldIndex] = align + style;
              _this2.header.classes[column.fieldIndex] = class_;
              _this2.header.formatters[column.fieldIndex] = column.formatter;
              _this2.header.detailFormatters[column.fieldIndex] = column.detailFormatter;
              _this2.header.events[column.fieldIndex] = column.events;
              _this2.header.sorters[column.fieldIndex] = column.sorter;
              _this2.header.sortNames[column.fieldIndex] = column.sortName;
              _this2.header.cellStyles[column.fieldIndex] = column.cellStyle;
              _this2.header.searchables[column.fieldIndex] = column.searchable;

              if (!column.visible) {
                return;
              }

              if (_this2.options.cardView && !column.cardVisible) {
                return;
              }

              visibleColumns[column.field] = column;
            }

            html.push(\"<th\".concat(Utils.sprintf(' title=\"%s\"', column.titleTooltip)), column.checkbox || column.radio ? Utils.sprintf(' class=\"bs-checkbox %s\"', column['class'] || '') : classes || class_, Utils.sprintf(' style=\"%s\"', halign + style + csses.join('; ')), Utils.sprintf(' rowspan=\"%s\"', column.rowspan), Utils.sprintf(' colspan=\"%s\"', column.colspan), Utils.sprintf(' data-field=\"%s\"', column.field), // If `column` is not the first element of `this.options.columns[0]`, then className 'data-not-first-th' should be added.
            j === 0 && i > 0 ? ' data-not-first-th' : '', '>');
            html.push(Utils.sprintf('<div class=\"th-inner %s\">', _this2.options.sortable && column.sortable ? 'sortable both' : ''));
            var text = _this2.options.escape ? Utils.escapeHTML(column.title) : column.title;
            var title = text;

            if (column.checkbox) {
              text = '';

              if (!_this2.options.singleSelect && _this2.options.checkboxHeader) {
                text = '<label><input name=\"btSelectAll\" type=\"checkbox\" /><span></span></label>';
              }

              _this2.header.stateField = column.field;
            }

            if (column.radio) {
              text = '';
              _this2.header.stateField = column.field;
            }

            if (!text && column.showSelectTitle) {
              text += title;
            }

            html.push(text);
            html.push('</div>');
            html.push('<div class=\"fht-cell\"></div>');
            html.push('</div>');
            html.push('</th>');
          });

          if (detailViewTemplate && _this2.options.detailViewAlign === 'right') {
            html.push(detailViewTemplate);
          }

          html.push('</tr>');

          if (html.length > 3) {
            headerHtml.push(html.join(''));
          }
        });
        this.\$header.html(headerHtml.join(''));
        this.\$header.find('th[data-field]').each(function (i, el) {
          \$__default['default'](el).data(visibleColumns[\$__default['default'](el).data('field')]);
        });
        this.\$container.off('click', '.th-inner').on('click', '.th-inner', function (e) {
          var \$this = \$__default['default'](e.currentTarget);

          if (_this2.options.detailView && !\$this.parent().hasClass('bs-checkbox')) {
            if (\$this.closest('.bootstrap-table')[0] !== _this2.\$container[0]) {
              return false;
            }
          }

          if (_this2.options.sortable && \$this.parent().data().sortable) {
            _this2.onSort(e);
          }
        });
        this.\$header.children().children().off('keypress').on('keypress', function (e) {
          if (_this2.options.sortable && \$__default['default'](e.currentTarget).data().sortable) {
            var code = e.keyCode || e.which;

            if (code === 13) {
              // Enter keycode
              _this2.onSort(e);
            }
          }
        });
        var resizeEvent = Utils.getEventName('resize.bootstrap-table', this.\$el.attr('id'));
        \$__default['default'](window).off(resizeEvent);

        if (!this.options.showHeader || this.options.cardView) {
          this.\$header.hide();
          this.\$tableHeader.hide();
          this.\$tableLoading.css('top', 0);
        } else {
          this.\$header.show();
          this.\$tableHeader.show();
          this.\$tableLoading.css('top', this.\$header.outerHeight() + 1); // Assign the correct sortable arrow

          this.getCaret();
          \$__default['default'](window).on(resizeEvent, function () {
            return _this2.resetView();
          });
        }

        this.\$selectAll = this.\$header.find('[name=\"btSelectAll\"]');
        this.\$selectAll.off('click').on('click', function (e) {
          e.stopPropagation();
          var checked = \$__default['default'](e.currentTarget).prop('checked');

          _this2[checked ? 'checkAll' : 'uncheckAll']();

          _this2.updateSelected();
        });
      }
    }, {
      key: \"initData\",
      value: function initData(data, type) {
        if (type === 'append') {
          this.options.data = this.options.data.concat(data);
        } else if (type === 'prepend') {
          this.options.data = [].concat(data).concat(this.options.data);
        } else {
          data = data || Utils.deepCopy(this.options.data);
          this.options.data = Array.isArray(data) ? data : data[this.options.dataField];
        }

        this.data = _toConsumableArray(this.options.data);

        if (this.options.sortReset) {
          this.unsortedData = _toConsumableArray(this.data);
        }

        if (this.options.sidePagination === 'server') {
          return;
        }

        this.initSort();
      }
    }, {
      key: \"initSort\",
      value: function initSort() {
        var _this3 = this;

        var name = this.options.sortName;
        var order = this.options.sortOrder === 'desc' ? -1 : 1;
        var index = this.header.fields.indexOf(this.options.sortName);
        var timeoutId = 0;

        if (index !== -1) {
          if (this.options.sortStable) {
            this.data.forEach(function (row, i) {
              if (!row.hasOwnProperty('_position')) {
                row._position = i;
              }
            });
          }

          if (this.options.customSort) {
            Utils.calculateObjectValue(this.options, this.options.customSort, [this.options.sortName, this.options.sortOrder, this.data]);
          } else {
            this.data.sort(function (a, b) {
              if (_this3.header.sortNames[index]) {
                name = _this3.header.sortNames[index];
              }

              var aa = Utils.getItemField(a, name, _this3.options.escape);
              var bb = Utils.getItemField(b, name, _this3.options.escape);
              var value = Utils.calculateObjectValue(_this3.header, _this3.header.sorters[index], [aa, bb, a, b]);

              if (value !== undefined) {
                if (_this3.options.sortStable && value === 0) {
                  return order * (a._position - b._position);
                }

                return order * value;
              }

              return Utils.sort(aa, bb, order, _this3.options.sortStable, a._position, b._position);
            });
          }

          if (this.options.sortClass !== undefined) {
            clearTimeout(timeoutId);
            timeoutId = setTimeout(function () {
              _this3.\$el.removeClass(_this3.options.sortClass);

              var index = _this3.\$header.find(\"[data-field=\\\"\".concat(_this3.options.sortName, \"\\\"]\")).index();

              _this3.\$el.find(\"tr td:nth-child(\".concat(index + 1, \")\")).addClass(_this3.options.sortClass);
            }, 250);
          }
        } else if (this.options.sortReset) {
          this.data = _toConsumableArray(this.unsortedData);
        }
      }
    }, {
      key: \"onSort\",
      value: function onSort(_ref) {
        var type = _ref.type,
            currentTarget = _ref.currentTarget;
        var \$this = type === 'keypress' ? \$__default['default'](currentTarget) : \$__default['default'](currentTarget).parent();
        var \$this_ = this.\$header.find('th').eq(\$this.index());
        this.\$header.add(this.\$header_).find('span.order').remove();

        if (this.options.sortName === \$this.data('field')) {
          var currentSortOrder = this.options.sortOrder;

          if (currentSortOrder === undefined) {
            this.options.sortOrder = 'asc';
          } else if (currentSortOrder === 'asc') {
            this.options.sortOrder = 'desc';
          } else if (this.options.sortOrder === 'desc') {
            this.options.sortOrder = this.options.sortReset ? undefined : 'asc';
          }

          if (this.options.sortOrder === undefined) {
            this.options.sortName = undefined;
          }
        } else {
          this.options.sortName = \$this.data('field');

          if (this.options.rememberOrder) {
            this.options.sortOrder = \$this.data('order') === 'asc' ? 'desc' : 'asc';
          } else {
            this.options.sortOrder = this.columns[this.fieldsColumnsIndex[\$this.data('field')]].sortOrder || this.columns[this.fieldsColumnsIndex[\$this.data('field')]].order;
          }
        }

        this.trigger('sort', this.options.sortName, this.options.sortOrder);
        \$this.add(\$this_).data('order', this.options.sortOrder); // Assign the correct sortable arrow

        this.getCaret();

        if (this.options.sidePagination === 'server' && this.options.serverSort) {
          this.options.pageNumber = 1;
          this.initServer(this.options.silentSort);
          return;
        }

        this.initSort();
        this.initBody();
      }
    }, {
      key: \"initToolbar\",
      value: function initToolbar() {
        var _this4 = this;

        var opts = this.options;
        var html = [];
        var timeoutId = 0;
        var \$keepOpen;
        var switchableCount = 0;

        if (this.\$toolbar.find('.bs-bars').children().length) {
          \$__default['default']('body').append(\$__default['default'](opts.toolbar));
        }

        this.\$toolbar.html('');

        if (typeof opts.toolbar === 'string' || _typeof(opts.toolbar) === 'object') {
          \$__default['default'](Utils.sprintf('<div class=\"bs-bars %s-%s\"></div>', this.constants.classes.pull, opts.toolbarAlign)).appendTo(this.\$toolbar).append(\$__default['default'](opts.toolbar));
        } // showColumns, showToggle, showRefresh


        html = [\"<div class=\\\"\".concat(['columns', \"columns-\".concat(opts.buttonsAlign), this.constants.classes.buttonsGroup, \"\".concat(this.constants.classes.pull, \"-\").concat(opts.buttonsAlign)].join(' '), \"\\\">\")];

        if (typeof opts.buttonsOrder === 'string') {
          opts.buttonsOrder = opts.buttonsOrder.replace(/\\[|\\]| |'/g, '').split(',');
        }

        this.buttons = Object.assign(this.buttons, {
          paginationSwitch: {
            text: opts.pagination ? opts.formatPaginationSwitchUp() : opts.formatPaginationSwitchDown(),
            icon: opts.pagination ? opts.icons.paginationSwitchDown : opts.icons.paginationSwitchUp,
            render: false,
            event: this.togglePagination,
            attributes: {
              'aria-label': opts.formatPaginationSwitch(),
              title: opts.formatPaginationSwitch()
            }
          },
          refresh: {
            text: opts.formatRefresh(),
            icon: opts.icons.refresh,
            render: false,
            event: this.refresh,
            attributes: {
              'aria-label': opts.formatRefresh(),
              title: opts.formatRefresh()
            }
          },
          toggle: {
            text: opts.formatToggle(),
            icon: opts.icons.toggleOff,
            render: false,
            event: this.toggleView,
            attributes: {
              'aria-label': opts.formatToggleOn(),
              title: opts.formatToggleOn()
            }
          },
          fullscreen: {
            text: opts.formatFullscreen(),
            icon: opts.icons.fullscreen,
            render: false,
            event: this.toggleFullscreen,
            attributes: {
              'aria-label': opts.formatFullscreen(),
              title: opts.formatFullscreen()
            }
          },
          columns: {
            render: false,
            html: function html() {
              var html = [];
              html.push(\"<div class=\\\"keep-open \".concat(_this4.constants.classes.buttonsDropdown, \"\\\" title=\\\"\").concat(opts.formatColumns(), \"\\\">\\n            <button class=\\\"\").concat(_this4.constants.buttonsClass, \" dropdown-toggle\\\" type=\\\"button\\\" \").concat(_this4.constants.dataToggle, \"=\\\"dropdown\\\"\\n            aria-label=\\\"Columns\\\" title=\\\"\").concat(opts.formatColumns(), \"\\\">\\n            \").concat(opts.showButtonIcons ? Utils.sprintf(_this4.constants.html.icon, opts.iconsPrefix, opts.icons.columns) : '', \"\\n            \").concat(opts.showButtonText ? opts.formatColumns() : '', \"\\n            \").concat(_this4.constants.html.dropdownCaret, \"\\n            </button>\\n            \").concat(_this4.constants.html.toolbarDropdown[0]));

              if (opts.showColumnsSearch) {
                html.push(Utils.sprintf(_this4.constants.html.toolbarDropdownItem, Utils.sprintf('<input type=\"text\" class=\"%s\" name=\"columnsSearch\" placeholder=\"%s\" autocomplete=\"off\">', _this4.constants.classes.input, opts.formatSearch())));
                html.push(_this4.constants.html.toolbarDropdownSeparator);
              }

              if (opts.showColumnsToggleAll) {
                var allFieldsVisible = _this4.getVisibleColumns().length === _this4.columns.filter(function (column) {
                  return !_this4.isSelectionColumn(column);
                }).length;

                html.push(Utils.sprintf(_this4.constants.html.toolbarDropdownItem, Utils.sprintf('<input type=\"checkbox\" class=\"toggle-all\" %s> <span>%s</span>', allFieldsVisible ? 'checked=\"checked\"' : '', opts.formatColumnsToggleAll())));
                html.push(_this4.constants.html.toolbarDropdownSeparator);
              }

              var visibleColumns = 0;

              _this4.columns.forEach(function (column) {
                if (column.visible) {
                  visibleColumns++;
                }
              });

              _this4.columns.forEach(function (column, i) {
                if (_this4.isSelectionColumn(column)) {
                  return;
                }

                if (opts.cardView && !column.cardVisible) {
                  return;
                }

                var checked = column.visible ? ' checked=\"checked\"' : '';
                var disabled = visibleColumns <= opts.minimumCountColumns && checked ? ' disabled=\"disabled\"' : '';

                if (column.switchable) {
                  html.push(Utils.sprintf(_this4.constants.html.toolbarDropdownItem, Utils.sprintf('<input type=\"checkbox\" data-field=\"%s\" value=\"%s\"%s%s> <span>%s</span>', column.field, i, checked, disabled, column.title)));
                  switchableCount++;
                }
              });

              html.push(_this4.constants.html.toolbarDropdown[1], '</div>');
              return html.join('');
            }
          }
        });
        var buttonsHtml = {};

        for (var _i2 = 0, _Object\$entries2 = Object.entries(this.buttons); _i2 < _Object\$entries2.length; _i2++) {
          var _Object\$entries2\$_i = _slicedToArray(_Object\$entries2[_i2], 2),
              buttonName = _Object\$entries2\$_i[0],
              buttonConfig = _Object\$entries2\$_i[1];

          var buttonHtml = void 0;

          if (buttonConfig.hasOwnProperty('html')) {
            if (typeof buttonConfig.html === 'function') {
              buttonHtml = buttonConfig.html();
            } else if (typeof buttonConfig.html === 'string') {
              buttonHtml = buttonConfig.html;
            }
          } else {
            buttonHtml = \"<button class=\\\"\".concat(this.constants.buttonsClass, \"\\\" type=\\\"button\\\" name=\\\"\").concat(buttonName, \"\\\"\");

            if (buttonConfig.hasOwnProperty('attributes')) {
              for (var _i3 = 0, _Object\$entries3 = Object.entries(buttonConfig.attributes); _i3 < _Object\$entries3.length; _i3++) {
                var _Object\$entries3\$_i = _slicedToArray(_Object\$entries3[_i3], 2),
                    attributeName = _Object\$entries3\$_i[0],
                    value = _Object\$entries3\$_i[1];

                buttonHtml += \" \".concat(attributeName, \"=\\\"\").concat(value, \"\\\"\");
              }
            }

            buttonHtml += '>';

            if (opts.showButtonIcons && buttonConfig.hasOwnProperty('icon')) {
              buttonHtml += \"\".concat(Utils.sprintf(this.constants.html.icon, opts.iconsPrefix, buttonConfig.icon), \" \");
            }

            if (opts.showButtonText && buttonConfig.hasOwnProperty('text')) {
              buttonHtml += buttonConfig.text;
            }

            buttonHtml += '</button>';
          }

          buttonsHtml[buttonName] = buttonHtml;
          var optionName = \"show\".concat(buttonName.charAt(0).toUpperCase()).concat(buttonName.substring(1));
          var showOption = opts[optionName];

          if ((!buttonConfig.hasOwnProperty('render') || buttonConfig.hasOwnProperty('render') && buttonConfig.render) && (showOption === undefined || showOption === true)) {
            opts[optionName] = true;
          }

          if (!opts.buttonsOrder.includes(buttonName)) {
            opts.buttonsOrder.push(buttonName);
          }
        } // Adding the button html to the final toolbar html when the showOption is true


        var _iterator = _createForOfIteratorHelper(opts.buttonsOrder),
            _step;

        try {
          for (_iterator.s(); !(_step = _iterator.n()).done;) {
            var button = _step.value;
            var _showOption = opts[\"show\".concat(button.charAt(0).toUpperCase()).concat(button.substring(1))];

            if (_showOption) {
              html.push(buttonsHtml[button]);
            }
          }
        } catch (err) {
          _iterator.e(err);
        } finally {
          _iterator.f();
        }

        html.push('</div>'); // Fix #188: this.showToolbar is for extensions

        if (this.showToolbar || html.length > 2) {
          this.\$toolbar.append(html.join(''));
        }

        for (var _i4 = 0, _Object\$entries4 = Object.entries(this.buttons); _i4 < _Object\$entries4.length; _i4++) {
          var _Object\$entries4\$_i = _slicedToArray(_Object\$entries4[_i4], 2),
              _buttonName = _Object\$entries4\$_i[0],
              _buttonConfig = _Object\$entries4\$_i[1];

          if (_buttonConfig.hasOwnProperty('event')) {
            if (typeof _buttonConfig.event === 'function' || typeof _buttonConfig.event === 'string') {
              var _ret = function () {
                var event = typeof _buttonConfig.event === 'string' ? window[_buttonConfig.event] : _buttonConfig.event;

                _this4.\$toolbar.find(\"button[name=\\\"\".concat(_buttonName, \"\\\"]\")).off('click').on('click', function () {
                  return event.call(_this4);
                });

                return \"continue\";
              }();

              if (_ret === \"continue\") continue;
            }

            var _loop = function _loop() {
              var _Object\$entries5\$_i = _slicedToArray(_Object\$entries5[_i5], 2),
                  eventType = _Object\$entries5\$_i[0],
                  eventFunction = _Object\$entries5\$_i[1];

              var event = typeof eventFunction === 'string' ? window[eventFunction] : eventFunction;

              _this4.\$toolbar.find(\"button[name=\\\"\".concat(_buttonName, \"\\\"]\")).off(eventType).on(eventType, function () {
                return event.call(_this4);
              });
            };

            for (var _i5 = 0, _Object\$entries5 = Object.entries(_buttonConfig.event); _i5 < _Object\$entries5.length; _i5++) {
              _loop();
            }
          }
        }

        if (opts.showColumns) {
          \$keepOpen = this.\$toolbar.find('.keep-open');
          var \$checkboxes = \$keepOpen.find('input[type=\"checkbox\"]:not(\".toggle-all\")');
          var \$toggleAll = \$keepOpen.find('input[type=\"checkbox\"].toggle-all');

          if (switchableCount <= opts.minimumCountColumns) {
            \$keepOpen.find('input').prop('disabled', true);
          }

          \$keepOpen.find('li, label').off('click').on('click', function (e) {
            e.stopImmediatePropagation();
          });
          \$checkboxes.off('click').on('click', function (_ref2) {
            var currentTarget = _ref2.currentTarget;
            var \$this = \$__default['default'](currentTarget);

            _this4._toggleColumn(\$this.val(), \$this.prop('checked'), false);

            _this4.trigger('column-switch', \$this.data('field'), \$this.prop('checked'));

            \$toggleAll.prop('checked', \$checkboxes.filter(':checked').length === _this4.columns.filter(function (column) {
              return !_this4.isSelectionColumn(column);
            }).length);
          });
          \$toggleAll.off('click').on('click', function (_ref3) {
            var currentTarget = _ref3.currentTarget;

            _this4._toggleAllColumns(\$__default['default'](currentTarget).prop('checked'));
          });

          if (opts.showColumnsSearch) {
            var \$columnsSearch = \$keepOpen.find('[name=\"columnsSearch\"]');
            var \$listItems = \$keepOpen.find('.dropdown-item-marker');
            \$columnsSearch.on('keyup paste change', function (_ref4) {
              var currentTarget = _ref4.currentTarget;
              var \$this = \$__default['default'](currentTarget);
              var searchValue = \$this.val().toLowerCase();
              \$listItems.show();
              \$checkboxes.each(function (i, el) {
                var \$checkbox = \$__default['default'](el);
                var \$listItem = \$checkbox.parents('.dropdown-item-marker');
                var text = \$listItem.text().toLowerCase();

                if (!text.includes(searchValue)) {
                  \$listItem.hide();
                }
              });
            });
          }
        }

        var handleInputEvent = function handleInputEvent(\$searchInput) {
          var eventTriggers = 'keyup drop blur mouseup';
          \$searchInput.off(eventTriggers).on(eventTriggers, function (event) {
            if (opts.searchOnEnterKey && event.keyCode !== 13) {
              return;
            }

            if ([37, 38, 39, 40].includes(event.keyCode)) {
              return;
            }

            clearTimeout(timeoutId); // doesn't matter if it's 0

            timeoutId = setTimeout(function () {
              _this4.onSearch({
                currentTarget: event.currentTarget
              });
            }, opts.searchTimeOut);
          });
        }; // Fix #4516: this.showSearchClearButton is for extensions


        if ((opts.search || this.showSearchClearButton) && typeof opts.searchSelector !== 'string') {
          html = [];
          var showSearchButton = Utils.sprintf(this.constants.html.searchButton, this.constants.buttonsClass, opts.formatSearch(), opts.showButtonIcons ? Utils.sprintf(this.constants.html.icon, opts.iconsPrefix, opts.icons.search) : '', opts.showButtonText ? opts.formatSearch() : '');
          var showSearchClearButton = Utils.sprintf(this.constants.html.searchClearButton, this.constants.buttonsClass, opts.formatClearSearch(), opts.showButtonIcons ? Utils.sprintf(this.constants.html.icon, opts.iconsPrefix, opts.icons.clearSearch) : '', opts.showButtonText ? opts.formatClearSearch() : '');
          var searchInputHtml = \"<input class=\\\"\".concat(this.constants.classes.input, \"\\n        \").concat(Utils.sprintf(' %s%s', this.constants.classes.inputPrefix, opts.iconSize), \"\\n        search-input\\\" type=\\\"search\\\" placeholder=\\\"\").concat(opts.formatSearch(), \"\\\" autocomplete=\\\"off\\\">\");
          var searchInputFinalHtml = searchInputHtml;

          if (opts.showSearchButton || opts.showSearchClearButton) {
            var _buttonsHtml = (opts.showSearchButton ? showSearchButton : '') + (opts.showSearchClearButton ? showSearchClearButton : '');

            searchInputFinalHtml = opts.search ? Utils.sprintf(this.constants.html.inputGroup, searchInputHtml, _buttonsHtml) : _buttonsHtml;
          }

          html.push(Utils.sprintf(\"\\n        <div class=\\\"\".concat(this.constants.classes.pull, \"-\").concat(opts.searchAlign, \" search \").concat(this.constants.classes.inputGroup, \"\\\">\\n          %s\\n        </div>\\n      \"), searchInputFinalHtml));
          this.\$toolbar.append(html.join(''));
          var \$searchInput = Utils.getSearchInput(this);

          if (opts.showSearchButton) {
            this.\$toolbar.find('.search button[name=search]').off('click').on('click', function () {
              clearTimeout(timeoutId); // doesn't matter if it's 0

              timeoutId = setTimeout(function () {
                _this4.onSearch({
                  currentTarget: \$searchInput
                });
              }, opts.searchTimeOut);
            });

            if (opts.searchOnEnterKey) {
              handleInputEvent(\$searchInput);
            }
          } else {
            handleInputEvent(\$searchInput);
          }

          if (opts.showSearchClearButton) {
            this.\$toolbar.find('.search button[name=clearSearch]').click(function () {
              _this4.resetSearch();
            });
          }
        } else if (typeof opts.searchSelector === 'string') {
          var _\$searchInput = Utils.getSearchInput(this);

          handleInputEvent(_\$searchInput);
        }
      }
    }, {
      key: \"onSearch\",
      value: function onSearch() {
        var _ref5 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
            currentTarget = _ref5.currentTarget,
            firedByInitSearchText = _ref5.firedByInitSearchText;

        var overwriteSearchText = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;

        if (currentTarget !== undefined && \$__default['default'](currentTarget).length && overwriteSearchText) {
          var text = \$__default['default'](currentTarget).val().trim();

          if (this.options.trimOnSearch && \$__default['default'](currentTarget).val() !== text) {
            \$__default['default'](currentTarget).val(text);
          }

          if (this.searchText === text) {
            return;
          }

          if (currentTarget === Utils.getSearchInput(this)[0] || \$__default['default'](currentTarget).hasClass('search-input')) {
            this.searchText = text;
            this.options.searchText = text;
          }
        }

        if (!firedByInitSearchText) {
          this.options.pageNumber = 1;
        }

        this.initSearch();

        if (firedByInitSearchText) {
          if (this.options.sidePagination === 'client') {
            this.updatePagination();
          }
        } else {
          this.updatePagination();
        }

        this.trigger('search', this.searchText);
      }
    }, {
      key: \"initSearch\",
      value: function initSearch() {
        var _this5 = this;

        this.filterOptions = this.filterOptions || this.options.filterOptions;

        if (this.options.sidePagination !== 'server') {
          if (this.options.customSearch) {
            this.data = Utils.calculateObjectValue(this.options, this.options.customSearch, [this.options.data, this.searchText, this.filterColumns]);

            if (this.options.sortReset) {
              this.unsortedData = _toConsumableArray(this.data);
            }

            return;
          }

          var s = this.searchText && (this.fromHtml ? Utils.escapeHTML(this.searchText) : this.searchText).toLowerCase();
          var f = Utils.isEmptyObject(this.filterColumns) ? null : this.filterColumns;

          if (this.options.searchAccentNeutralise) {
            s = Utils.normalizeAccent(s);
          } // Check filter


          if (typeof this.filterOptions.filterAlgorithm === 'function') {
            this.data = this.options.data.filter(function (item) {
              return _this5.filterOptions.filterAlgorithm.apply(null, [item, f]);
            });
          } else if (typeof this.filterOptions.filterAlgorithm === 'string') {
            this.data = f ? this.options.data.filter(function (item) {
              var filterAlgorithm = _this5.filterOptions.filterAlgorithm;

              if (filterAlgorithm === 'and') {
                for (var key in f) {
                  if (Array.isArray(f[key]) && !f[key].includes(item[key]) || !Array.isArray(f[key]) && item[key] !== f[key]) {
                    return false;
                  }
                }
              } else if (filterAlgorithm === 'or') {
                var match = false;

                for (var _key in f) {
                  if (Array.isArray(f[_key]) && f[_key].includes(item[_key]) || !Array.isArray(f[_key]) && item[_key] === f[_key]) {
                    match = true;
                  }
                }

                return match;
              }

              return true;
            }) : _toConsumableArray(this.options.data);
          }

          var visibleFields = this.getVisibleFields();
          this.data = s ? this.data.filter(function (item, i) {
            for (var j = 0; j < _this5.header.fields.length; j++) {
              if (!_this5.header.searchables[j] || _this5.options.visibleSearch && visibleFields.indexOf(_this5.header.fields[j]) === -1) {
                continue;
              }

              var key = Utils.isNumeric(_this5.header.fields[j]) ? parseInt(_this5.header.fields[j], 10) : _this5.header.fields[j];
              var column = _this5.columns[_this5.fieldsColumnsIndex[key]];
              var value = void 0;

              if (typeof key === 'string') {
                value = item;
                var props = key.split('.');

                for (var _i6 = 0; _i6 < props.length; _i6++) {
                  if (value[props[_i6]] !== null) {
                    value = value[props[_i6]];
                  }
                }
              } else {
                value = item[key];
              }

              if (_this5.options.searchAccentNeutralise) {
                value = Utils.normalizeAccent(value);
              } // Fix #142: respect searchFormatter boolean


              if (column && column.searchFormatter) {
                value = Utils.calculateObjectValue(column, _this5.header.formatters[j], [value, item, i, column.field], value);
              }

              if (typeof value === 'string' || typeof value === 'number') {
                if (_this5.options.strictSearch) {
                  if (\"\".concat(value).toLowerCase() === s) {
                    return true;
                  }
                } else {
                  var largerSmallerEqualsRegex = /(?:(<=|=>|=<|>=|>|<)(?:\\s+)?(-?\\d+)?|(-?\\d+)?(\\s+)?(<=|=>|=<|>=|>|<))/gm;
                  var matches = largerSmallerEqualsRegex.exec(_this5.searchText);
                  var comparisonCheck = false;

                  if (matches) {
                    var operator = matches[1] || \"\".concat(matches[5], \"l\");
                    var comparisonValue = matches[2] || matches[3];
                    var int = parseInt(value, 10);
                    var comparisonInt = parseInt(comparisonValue, 10);

                    switch (operator) {
                      case '>':
                      case '<l':
                        comparisonCheck = int > comparisonInt;
                        break;

                      case '<':
                      case '>l':
                        comparisonCheck = int < comparisonInt;
                        break;

                      case '<=':
                      case '=<':
                      case '>=l':
                      case '=>l':
                        comparisonCheck = int <= comparisonInt;
                        break;

                      case '>=':
                      case '=>':
                      case '<=l':
                      case '=<l':
                        comparisonCheck = int >= comparisonInt;
                        break;
                    }
                  }

                  if (comparisonCheck || \"\".concat(value).toLowerCase().includes(s)) {
                    return true;
                  }
                }
              }
            }

            return false;
          }) : this.data;

          if (this.options.sortReset) {
            this.unsortedData = _toConsumableArray(this.data);
          }

          this.initSort();
        }
      }
    }, {
      key: \"initPagination\",
      value: function initPagination() {
        var _this6 = this;

        var opts = this.options;

        if (!opts.pagination) {
          this.\$pagination.hide();
          return;
        }

        this.\$pagination.show();
        var html = [];
        var allSelected = false;
        var i;
        var from;
        var to;
        var \$pageList;
        var \$pre;
        var \$next;
        var \$number;
        var data = this.getData({
          includeHiddenRows: false
        });
        var pageList = opts.pageList;

        if (typeof pageList === 'string') {
          pageList = pageList.replace(/\\[|\\]| /g, '').toLowerCase().split(',');
        }

        pageList = pageList.map(function (value) {
          if (typeof value === 'string') {
            return value.toLowerCase() === opts.formatAllRows().toLowerCase() || ['all', 'unlimited'].includes(value.toLowerCase()) ? opts.formatAllRows() : +value;
          }

          return value;
        });
        this.paginationParts = opts.paginationParts;

        if (typeof this.paginationParts === 'string') {
          this.paginationParts = this.paginationParts.replace(/\\[|\\]| |'/g, '').split(',');
        }

        if (opts.sidePagination !== 'server') {
          opts.totalRows = data.length;
        }

        this.totalPages = 0;

        if (opts.totalRows) {
          if (opts.pageSize === opts.formatAllRows()) {
            opts.pageSize = opts.totalRows;
            allSelected = true;
          }

          this.totalPages = ~~((opts.totalRows - 1) / opts.pageSize) + 1;
          opts.totalPages = this.totalPages;
        }

        if (this.totalPages > 0 && opts.pageNumber > this.totalPages) {
          opts.pageNumber = this.totalPages;
        }

        this.pageFrom = (opts.pageNumber - 1) * opts.pageSize + 1;
        this.pageTo = opts.pageNumber * opts.pageSize;

        if (this.pageTo > opts.totalRows) {
          this.pageTo = opts.totalRows;
        }

        if (this.options.pagination && this.options.sidePagination !== 'server') {
          this.options.totalNotFiltered = this.options.data.length;
        }

        if (!this.options.showExtendedPagination) {
          this.options.totalNotFiltered = undefined;
        }

        if (this.paginationParts.includes('pageInfo') || this.paginationParts.includes('pageInfoShort') || this.paginationParts.includes('pageSize')) {
          html.push(\"<div class=\\\"\".concat(this.constants.classes.pull, \"-\").concat(opts.paginationDetailHAlign, \" pagination-detail\\\">\"));
        }

        if (this.paginationParts.includes('pageInfo') || this.paginationParts.includes('pageInfoShort')) {
          var paginationInfo = this.paginationParts.includes('pageInfoShort') ? opts.formatDetailPagination(opts.totalRows) : opts.formatShowingRows(this.pageFrom, this.pageTo, opts.totalRows, opts.totalNotFiltered);
          html.push(\"<span class=\\\"pagination-info\\\">\\n      \".concat(paginationInfo, \"\\n      </span>\"));
        }

        if (this.paginationParts.includes('pageSize')) {
          html.push('<div class=\"page-list\">');
          var pageNumber = [\"<div class=\\\"\".concat(this.constants.classes.paginationDropdown, \"\\\">\\n        <button class=\\\"\").concat(this.constants.buttonsClass, \" dropdown-toggle\\\" type=\\\"button\\\" \").concat(this.constants.dataToggle, \"=\\\"dropdown\\\">\\n        <span class=\\\"page-size\\\">\\n        \").concat(allSelected ? opts.formatAllRows() : opts.pageSize, \"\\n        </span>\\n        \").concat(this.constants.html.dropdownCaret, \"\\n        </button>\\n        \").concat(this.constants.html.pageDropdown[0])];
          pageList.forEach(function (page, i) {
            if (!opts.smartDisplay || i === 0 || pageList[i - 1] < opts.totalRows || page === opts.formatAllRows()) {
              var active;

              if (allSelected) {
                active = page === opts.formatAllRows() ? _this6.constants.classes.dropdownActive : '';
              } else {
                active = page === opts.pageSize ? _this6.constants.classes.dropdownActive : '';
              }

              pageNumber.push(Utils.sprintf(_this6.constants.html.pageDropdownItem, active, page));
            }
          });
          pageNumber.push(\"\".concat(this.constants.html.pageDropdown[1], \"</div>\"));
          html.push(opts.formatRecordsPerPage(pageNumber.join('')));
        }

        if (this.paginationParts.includes('pageInfo') || this.paginationParts.includes('pageInfoShort') || this.paginationParts.includes('pageSize')) {
          html.push('</div></div>');
        }

        if (this.paginationParts.includes('pageList')) {
          html.push(\"<div class=\\\"\".concat(this.constants.classes.pull, \"-\").concat(opts.paginationHAlign, \" pagination\\\">\"), Utils.sprintf(this.constants.html.pagination[0], Utils.sprintf(' pagination-%s', opts.iconSize)), Utils.sprintf(this.constants.html.paginationItem, ' page-pre', opts.formatSRPaginationPreText(), opts.paginationPreText));

          if (this.totalPages < opts.paginationSuccessivelySize) {
            from = 1;
            to = this.totalPages;
          } else {
            from = opts.pageNumber - opts.paginationPagesBySide;
            to = from + opts.paginationPagesBySide * 2;
          }

          if (opts.pageNumber < opts.paginationSuccessivelySize - 1) {
            to = opts.paginationSuccessivelySize;
          }

          if (opts.paginationSuccessivelySize > this.totalPages - from) {
            from = from - (opts.paginationSuccessivelySize - (this.totalPages - from)) + 1;
          }

          if (from < 1) {
            from = 1;
          }

          if (to > this.totalPages) {
            to = this.totalPages;
          }

          var middleSize = Math.round(opts.paginationPagesBySide / 2);

          var pageItem = function pageItem(i) {
            var classes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
            return Utils.sprintf(_this6.constants.html.paginationItem, classes + (i === opts.pageNumber ? \" \".concat(_this6.constants.classes.paginationActive) : ''), opts.formatSRPaginationPageText(i), i);
          };

          if (from > 1) {
            var max = opts.paginationPagesBySide;
            if (max >= from) max = from - 1;

            for (i = 1; i <= max; i++) {
              html.push(pageItem(i));
            }

            if (from - 1 === max + 1) {
              i = from - 1;
              html.push(pageItem(i));
            } else if (from - 1 > max) {
              if (from - opts.paginationPagesBySide * 2 > opts.paginationPagesBySide && opts.paginationUseIntermediate) {
                i = Math.round((from - middleSize) / 2 + middleSize);
                html.push(pageItem(i, ' page-intermediate'));
              } else {
                html.push(Utils.sprintf(this.constants.html.paginationItem, ' page-first-separator disabled', '', '...'));
              }
            }
          }

          for (i = from; i <= to; i++) {
            html.push(pageItem(i));
          }

          if (this.totalPages > to) {
            var min = this.totalPages - (opts.paginationPagesBySide - 1);
            if (to >= min) min = to + 1;

            if (to + 1 === min - 1) {
              i = to + 1;
              html.push(pageItem(i));
            } else if (min > to + 1) {
              if (this.totalPages - to > opts.paginationPagesBySide * 2 && opts.paginationUseIntermediate) {
                i = Math.round((this.totalPages - middleSize - to) / 2 + to);
                html.push(pageItem(i, ' page-intermediate'));
              } else {
                html.push(Utils.sprintf(this.constants.html.paginationItem, ' page-last-separator disabled', '', '...'));
              }
            }

            for (i = min; i <= this.totalPages; i++) {
              html.push(pageItem(i));
            }
          }

          html.push(Utils.sprintf(this.constants.html.paginationItem, ' page-next', opts.formatSRPaginationNextText(), opts.paginationNextText));
          html.push(this.constants.html.pagination[1], '</div>');
        }

        this.\$pagination.html(html.join(''));
        var dropupClass = ['bottom', 'both'].includes(opts.paginationVAlign) ? \" \".concat(this.constants.classes.dropup) : '';
        this.\$pagination.last().find('.page-list > div').addClass(dropupClass);

        if (!opts.onlyInfoPagination) {
          \$pageList = this.\$pagination.find('.page-list a');
          \$pre = this.\$pagination.find('.page-pre');
          \$next = this.\$pagination.find('.page-next');
          \$number = this.\$pagination.find('.page-item').not('.page-next, .page-pre, .page-last-separator, .page-first-separator');

          if (this.totalPages <= 1) {
            this.\$pagination.find('div.pagination').hide();
          }

          if (opts.smartDisplay) {
            if (pageList.length < 2 || opts.totalRows <= pageList[0]) {
              this.\$pagination.find('span.page-list').hide();
            }
          } // when data is empty, hide the pagination


          this.\$pagination[this.getData().length ? 'show' : 'hide']();

          if (!opts.paginationLoop) {
            if (opts.pageNumber === 1) {
              \$pre.addClass('disabled');
            }

            if (opts.pageNumber === this.totalPages) {
              \$next.addClass('disabled');
            }
          }

          if (allSelected) {
            opts.pageSize = opts.formatAllRows();
          } // removed the events for last and first, onPageNumber executeds the same logic


          \$pageList.off('click').on('click', function (e) {
            return _this6.onPageListChange(e);
          });
          \$pre.off('click').on('click', function (e) {
            return _this6.onPagePre(e);
          });
          \$next.off('click').on('click', function (e) {
            return _this6.onPageNext(e);
          });
          \$number.off('click').on('click', function (e) {
            return _this6.onPageNumber(e);
          });
        }
      }
    }, {
      key: \"updatePagination\",
      value: function updatePagination(event) {
        // Fix #171: IE disabled button can be clicked bug.
        if (event && \$__default['default'](event.currentTarget).hasClass('disabled')) {
          return;
        }

        if (!this.options.maintainMetaData) {
          this.resetRows();
        }

        this.initPagination();
        this.trigger('page-change', this.options.pageNumber, this.options.pageSize);

        if (this.options.sidePagination === 'server') {
          this.initServer();
        } else {
          this.initBody();
        }
      }
    }, {
      key: \"onPageListChange\",
      value: function onPageListChange(event) {
        event.preventDefault();
        var \$this = \$__default['default'](event.currentTarget);
        \$this.parent().addClass(this.constants.classes.dropdownActive).siblings().removeClass(this.constants.classes.dropdownActive);
        this.options.pageSize = \$this.text().toUpperCase() === this.options.formatAllRows().toUpperCase() ? this.options.formatAllRows() : +\$this.text();
        this.\$toolbar.find('.page-size').text(this.options.pageSize);
        this.updatePagination(event);
        return false;
      }
    }, {
      key: \"onPagePre\",
      value: function onPagePre(event) {
        event.preventDefault();

        if (this.options.pageNumber - 1 === 0) {
          this.options.pageNumber = this.options.totalPages;
        } else {
          this.options.pageNumber--;
        }

        this.updatePagination(event);
        return false;
      }
    }, {
      key: \"onPageNext\",
      value: function onPageNext(event) {
        event.preventDefault();

        if (this.options.pageNumber + 1 > this.options.totalPages) {
          this.options.pageNumber = 1;
        } else {
          this.options.pageNumber++;
        }

        this.updatePagination(event);
        return false;
      }
    }, {
      key: \"onPageNumber\",
      value: function onPageNumber(event) {
        event.preventDefault();

        if (this.options.pageNumber === +\$__default['default'](event.currentTarget).text()) {
          return;
        }

        this.options.pageNumber = +\$__default['default'](event.currentTarget).text();
        this.updatePagination(event);
        return false;
      } // eslint-disable-next-line no-unused-vars

    }, {
      key: \"initRow\",
      value: function initRow(item, i, data, trFragments) {
        var _this7 = this;

        var html = [];
        var style = {};
        var csses = [];
        var data_ = '';
        var attributes = {};
        var htmlAttributes = [];

        if (Utils.findIndex(this.hiddenRows, item) > -1) {
          return;
        }

        style = Utils.calculateObjectValue(this.options, this.options.rowStyle, [item, i], style);

        if (style && style.css) {
          for (var _i7 = 0, _Object\$entries6 = Object.entries(style.css); _i7 < _Object\$entries6.length; _i7++) {
            var _Object\$entries6\$_i = _slicedToArray(_Object\$entries6[_i7], 2),
                key = _Object\$entries6\$_i[0],
                value = _Object\$entries6\$_i[1];

            csses.push(\"\".concat(key, \": \").concat(value));
          }
        }

        attributes = Utils.calculateObjectValue(this.options, this.options.rowAttributes, [item, i], attributes);

        if (attributes) {
          for (var _i8 = 0, _Object\$entries7 = Object.entries(attributes); _i8 < _Object\$entries7.length; _i8++) {
            var _Object\$entries7\$_i = _slicedToArray(_Object\$entries7[_i8], 2),
                _key2 = _Object\$entries7\$_i[0],
                _value = _Object\$entries7\$_i[1];

            htmlAttributes.push(\"\".concat(_key2, \"=\\\"\").concat(Utils.escapeHTML(_value), \"\\\"\"));
          }
        }

        if (item._data && !Utils.isEmptyObject(item._data)) {
          for (var _i9 = 0, _Object\$entries8 = Object.entries(item._data); _i9 < _Object\$entries8.length; _i9++) {
            var _Object\$entries8\$_i = _slicedToArray(_Object\$entries8[_i9], 2),
                k = _Object\$entries8\$_i[0],
                v = _Object\$entries8\$_i[1];

            // ignore data-index
            if (k === 'index') {
              return;
            }

            data_ += \" data-\".concat(k, \"='\").concat(_typeof(v) === 'object' ? JSON.stringify(v) : v, \"'\");
          }
        }

        html.push('<tr', Utils.sprintf(' %s', htmlAttributes.length ? htmlAttributes.join(' ') : undefined), Utils.sprintf(' id=\"%s\"', Array.isArray(item) ? undefined : item._id), Utils.sprintf(' class=\"%s\"', style.classes || (Array.isArray(item) ? undefined : item._class)), Utils.sprintf(' style=\"%s\"', Array.isArray(item) ? undefined : item._style), \" data-index=\\\"\".concat(i, \"\\\"\"), Utils.sprintf(' data-uniqueid=\"%s\"', Utils.getItemField(item, this.options.uniqueId, false)), Utils.sprintf(' data-has-detail-view=\"%s\"', this.options.detailView && Utils.calculateObjectValue(null, this.options.detailFilter, [i, item]) ? 'true' : undefined), Utils.sprintf('%s', data_), '>');

        if (this.options.cardView) {
          html.push(\"<td colspan=\\\"\".concat(this.header.fields.length, \"\\\"><div class=\\\"card-views\\\">\"));
        }

        var detailViewTemplate = '';

        if (Utils.hasDetailViewIcon(this.options)) {
          detailViewTemplate = '<td>';

          if (Utils.calculateObjectValue(null, this.options.detailFilter, [i, item])) {
            detailViewTemplate += \"\\n          <a class=\\\"detail-icon\\\" href=\\\"#\\\">\\n          \".concat(Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, this.options.icons.detailOpen), \"\\n          </a>\\n        \");
          }

          detailViewTemplate += '</td>';
        }

        if (detailViewTemplate && this.options.detailViewAlign !== 'right') {
          html.push(detailViewTemplate);
        }

        this.header.fields.forEach(function (field, j) {
          var text = '';
          var value_ = Utils.getItemField(item, field, _this7.options.escape);
          var value = '';
          var type = '';
          var cellStyle = {};
          var id_ = '';
          var class_ = _this7.header.classes[j];
          var style_ = '';
          var styleToAdd_ = '';
          var data_ = '';
          var rowspan_ = '';
          var colspan_ = '';
          var title_ = '';
          var column = _this7.columns[j];

          if ((_this7.fromHtml || _this7.autoMergeCells) && typeof value_ === 'undefined') {
            if (!column.checkbox && !column.radio) {
              return;
            }
          }

          if (!column.visible) {
            return;
          }

          if (_this7.options.cardView && !column.cardVisible) {
            return;
          }

          if (column.escape) {
            value_ = Utils.escapeHTML(value_);
          } // Style concat


          if (csses.concat([_this7.header.styles[j]]).length) {
            styleToAdd_ += \"\".concat(csses.concat([_this7.header.styles[j]]).join('; '));
          }

          if (item[\"_\".concat(field, \"_style\")]) {
            styleToAdd_ += \"\".concat(item[\"_\".concat(field, \"_style\")]);
          }

          if (styleToAdd_) {
            style_ = \" style=\\\"\".concat(styleToAdd_, \"\\\"\");
          } // Style concat
          // handle id and class of td


          if (item[\"_\".concat(field, \"_id\")]) {
            id_ = Utils.sprintf(' id=\"%s\"', item[\"_\".concat(field, \"_id\")]);
          }

          if (item[\"_\".concat(field, \"_class\")]) {
            class_ = Utils.sprintf(' class=\"%s\"', item[\"_\".concat(field, \"_class\")]);
          }

          if (item[\"_\".concat(field, \"_rowspan\")]) {
            rowspan_ = Utils.sprintf(' rowspan=\"%s\"', item[\"_\".concat(field, \"_rowspan\")]);
          }

          if (item[\"_\".concat(field, \"_colspan\")]) {
            colspan_ = Utils.sprintf(' colspan=\"%s\"', item[\"_\".concat(field, \"_colspan\")]);
          }

          if (item[\"_\".concat(field, \"_title\")]) {
            title_ = Utils.sprintf(' title=\"%s\"', item[\"_\".concat(field, \"_title\")]);
          }

          cellStyle = Utils.calculateObjectValue(_this7.header, _this7.header.cellStyles[j], [value_, item, i, field], cellStyle);

          if (cellStyle.classes) {
            class_ = \" class=\\\"\".concat(cellStyle.classes, \"\\\"\");
          }

          if (cellStyle.css) {
            var csses_ = [];

            for (var _i10 = 0, _Object\$entries9 = Object.entries(cellStyle.css); _i10 < _Object\$entries9.length; _i10++) {
              var _Object\$entries9\$_i = _slicedToArray(_Object\$entries9[_i10], 2),
                  _key3 = _Object\$entries9\$_i[0],
                  _value2 = _Object\$entries9\$_i[1];

              csses_.push(\"\".concat(_key3, \": \").concat(_value2));
            }

            style_ = \" style=\\\"\".concat(csses_.concat(_this7.header.styles[j]).join('; '), \"\\\"\");
          }

          value = Utils.calculateObjectValue(column, _this7.header.formatters[j], [value_, item, i, field], value_);

          if (!(column.checkbox || column.radio)) {
            value = typeof value === 'undefined' || value === null ? _this7.options.undefinedText : value;
          }

          if (column.searchable && _this7.searchText && _this7.options.searchHighlight) {
            var defValue = '';
            var regExp = new RegExp(\"(\".concat(_this7.searchText.replace(/[.*+?^\${}()|[\\]\\\\]/g, '\\\\\$&'), \")\"), 'gim');
            var marker = '<mark>\$1</mark>';
            var isHTML = value && /<(?=.*? .*?\\/ ?>|br|hr|input|!--|wbr)[a-z]+.*?>|<([a-z]+).*?<\\/\\1>/i.test(value);

            if (isHTML) {
              // value can contains a HTML tags
              var textContent = new DOMParser().parseFromString(value.toString(), 'text/html').documentElement.textContent;
              var textReplaced = textContent.replace(regExp, marker);
              defValue = value.replace(new RegExp(\"(>\\\\s*)(\".concat(textContent, \")(\\\\s*)\"), 'gm'), \"\$1\".concat(textReplaced, \"\$3\"));
            } else {
              // but usually not
              defValue = value.toString().replace(regExp, marker);
            }

            value = Utils.calculateObjectValue(column, column.searchHighlightFormatter, [value, _this7.searchText], defValue);
          }

          if (item[\"_\".concat(field, \"_data\")] && !Utils.isEmptyObject(item[\"_\".concat(field, \"_data\")])) {
            for (var _i11 = 0, _Object\$entries10 = Object.entries(item[\"_\".concat(field, \"_data\")]); _i11 < _Object\$entries10.length; _i11++) {
              var _Object\$entries10\$_i = _slicedToArray(_Object\$entries10[_i11], 2),
                  _k = _Object\$entries10\$_i[0],
                  _v = _Object\$entries10\$_i[1];

              // ignore data-index
              if (_k === 'index') {
                return;
              }

              data_ += \" data-\".concat(_k, \"=\\\"\").concat(_v, \"\\\"\");
            }
          }

          if (column.checkbox || column.radio) {
            type = column.checkbox ? 'checkbox' : type;
            type = column.radio ? 'radio' : type;
            var c = column['class'] || '';
            var isChecked = Utils.isObject(value) && value.hasOwnProperty('checked') ? value.checked : (value === true || value_) && value !== false;
            var isDisabled = !column.checkboxEnabled || value && value.disabled;
            text = [_this7.options.cardView ? \"<div class=\\\"card-view \".concat(c, \"\\\">\") : \"<td class=\\\"bs-checkbox \".concat(c, \"\\\"\").concat(class_).concat(style_, \">\"), \"<label>\\n            <input\\n            data-index=\\\"\".concat(i, \"\\\"\\n            name=\\\"\").concat(_this7.options.selectItemName, \"\\\"\\n            type=\\\"\").concat(type, \"\\\"\\n            \").concat(Utils.sprintf('value=\"%s\"', item[_this7.options.idField]), \"\\n            \").concat(Utils.sprintf('checked=\"%s\"', isChecked ? 'checked' : undefined), \"\\n            \").concat(Utils.sprintf('disabled=\"%s\"', isDisabled ? 'disabled' : undefined), \" />\\n            <span></span>\\n            </label>\"), _this7.header.formatters[j] && typeof value === 'string' ? value : '', _this7.options.cardView ? '</div>' : '</td>'].join('');
            item[_this7.header.stateField] = value === true || !!value_ || value && value.checked;
          } else if (_this7.options.cardView) {
            var cardTitle = _this7.options.showHeader ? \"<span class=\\\"card-view-title \".concat(cellStyle.classes, \"\\\"\").concat(style_, \">\").concat(Utils.getFieldTitle(_this7.columns, field), \"</span>\") : '';
            text = \"<div class=\\\"card-view\\\">\".concat(cardTitle, \"<span class=\\\"card-view-value \").concat(cellStyle.classes, \"\\\"\").concat(style_, \">\").concat(value, \"</span></div>\");

            if (_this7.options.smartDisplay && value === '') {
              text = '<div class=\"card-view\"></div>';
            }
          } else {
            text = \"<td\".concat(id_).concat(class_).concat(style_).concat(data_).concat(rowspan_).concat(colspan_).concat(title_, \">\").concat(value, \"</td>\");
          }

          html.push(text);
        });

        if (detailViewTemplate && this.options.detailViewAlign === 'right') {
          html.push(detailViewTemplate);
        }

        if (this.options.cardView) {
          html.push('</div></td>');
        }

        html.push('</tr>');
        return html.join('');
      }
    }, {
      key: \"initBody\",
      value: function initBody(fixedScroll) {
        var _this8 = this;

        var data = this.getData();
        this.trigger('pre-body', data);
        this.\$body = this.\$el.find('>tbody');

        if (!this.\$body.length) {
          this.\$body = \$__default['default']('<tbody></tbody>').appendTo(this.\$el);
        } // Fix #389 Bootstrap-table-flatJSON is not working


        if (!this.options.pagination || this.options.sidePagination === 'server') {
          this.pageFrom = 1;
          this.pageTo = data.length;
        }

        var rows = [];
        var trFragments = \$__default['default'](document.createDocumentFragment());
        var hasTr = false;
        this.autoMergeCells = Utils.checkAutoMergeCells(data.slice(this.pageFrom - 1, this.pageTo));

        for (var i = this.pageFrom - 1; i < this.pageTo; i++) {
          var item = data[i];
          var tr = this.initRow(item, i, data, trFragments);
          hasTr = hasTr || !!tr;

          if (tr && typeof tr === 'string') {
            if (!this.options.virtualScroll) {
              trFragments.append(tr);
            } else {
              rows.push(tr);
            }
          }
        } // show no records


        if (!hasTr) {
          this.\$body.html(\"<tr class=\\\"no-records-found\\\">\".concat(Utils.sprintf('<td colspan=\"%s\">%s</td>', this.getVisibleFields().length + Utils.getDetailViewIndexOffset(this.options), this.options.formatNoMatches()), \"</tr>\"));
        } else if (!this.options.virtualScroll) {
          this.\$body.html(trFragments);
        } else {
          if (this.virtualScroll) {
            this.virtualScroll.destroy();
          }

          this.virtualScroll = new VirtualScroll({
            rows: rows,
            fixedScroll: fixedScroll,
            scrollEl: this.\$tableBody[0],
            contentEl: this.\$body[0],
            itemHeight: this.options.virtualScrollItemHeight,
            callback: function callback() {
              _this8.fitHeader();

              _this8.initBodyEvent();
            }
          });
        }

        if (!fixedScroll) {
          this.scrollTo(0);
        }

        this.initBodyEvent();
        this.updateSelected();
        this.initFooter();
        this.resetView();

        if (this.options.sidePagination !== 'server') {
          this.options.totalRows = data.length;
        }

        this.trigger('post-body', data);
      }
    }, {
      key: \"initBodyEvent\",
      value: function initBodyEvent() {
        var _this9 = this;

        // click to select by column
        this.\$body.find('> tr[data-index] > td').off('click dblclick').on('click dblclick', function (e) {
          var \$td = \$__default['default'](e.currentTarget);
          var \$tr = \$td.parent();
          var \$cardViewArr = \$__default['default'](e.target).parents('.card-views').children();
          var \$cardViewTarget = \$__default['default'](e.target).parents('.card-view');
          var rowIndex = \$tr.data('index');
          var item = _this9.data[rowIndex];
          var index = _this9.options.cardView ? \$cardViewArr.index(\$cardViewTarget) : \$td[0].cellIndex;

          var fields = _this9.getVisibleFields();

          var field = fields[index - Utils.getDetailViewIndexOffset(_this9.options)];
          var column = _this9.columns[_this9.fieldsColumnsIndex[field]];
          var value = Utils.getItemField(item, field, _this9.options.escape);

          if (\$td.find('.detail-icon').length) {
            return;
          }

          _this9.trigger(e.type === 'click' ? 'click-cell' : 'dbl-click-cell', field, value, item, \$td);

          _this9.trigger(e.type === 'click' ? 'click-row' : 'dbl-click-row', item, \$tr, field); // if click to select - then trigger the checkbox/radio click


          if (e.type === 'click' && _this9.options.clickToSelect && column.clickToSelect && !Utils.calculateObjectValue(_this9.options, _this9.options.ignoreClickToSelectOn, [e.target])) {
            var \$selectItem = \$tr.find(Utils.sprintf('[name=\"%s\"]', _this9.options.selectItemName));

            if (\$selectItem.length) {
              \$selectItem[0].click();
            }
          }

          if (e.type === 'click' && _this9.options.detailViewByClick) {
            _this9.toggleDetailView(rowIndex, _this9.header.detailFormatters[_this9.fieldsColumnsIndex[field]]);
          }
        }).off('mousedown').on('mousedown', function (e) {
          // https://github.com/jquery/jquery/issues/1741
          _this9.multipleSelectRowCtrlKey = e.ctrlKey || e.metaKey;
          _this9.multipleSelectRowShiftKey = e.shiftKey;
        });
        this.\$body.find('> tr[data-index] > td > .detail-icon').off('click').on('click', function (e) {
          e.preventDefault();

          _this9.toggleDetailView(\$__default['default'](e.currentTarget).parent().parent().data('index'));

          return false;
        });
        this.\$selectItem = this.\$body.find(Utils.sprintf('[name=\"%s\"]', this.options.selectItemName));
        this.\$selectItem.off('click').on('click', function (e) {
          e.stopImmediatePropagation();
          var \$this = \$__default['default'](e.currentTarget);

          _this9._toggleCheck(\$this.prop('checked'), \$this.data('index'));
        });
        this.header.events.forEach(function (_events, i) {
          var events = _events;

          if (!events) {
            return;
          } // fix bug, if events is defined with namespace


          if (typeof events === 'string') {
            events = Utils.calculateObjectValue(null, events);
          }

          var field = _this9.header.fields[i];

          var fieldIndex = _this9.getVisibleFields().indexOf(field);

          if (fieldIndex === -1) {
            return;
          }

          fieldIndex += Utils.getDetailViewIndexOffset(_this9.options);

          var _loop2 = function _loop2(key) {
            if (!events.hasOwnProperty(key)) {
              return \"continue\";
            }

            var event = events[key];

            _this9.\$body.find('>tr:not(.no-records-found)').each(function (i, tr) {
              var \$tr = \$__default['default'](tr);
              var \$td = \$tr.find(_this9.options.cardView ? '.card-views>.card-view' : '>td').eq(fieldIndex);
              var index = key.indexOf(' ');
              var name = key.substring(0, index);
              var el = key.substring(index + 1);
              \$td.find(el).off(name).on(name, function (e) {
                var index = \$tr.data('index');
                var row = _this9.data[index];
                var value = row[field];
                event.apply(_this9, [e, value, row, index]);
              });
            });
          };

          for (var key in events) {
            var _ret2 = _loop2(key);

            if (_ret2 === \"continue\") continue;
          }
        });
      }
    }, {
      key: \"initServer\",
      value: function initServer(silent, query, url) {
        var _this10 = this;

        var data = {};
        var index = this.header.fields.indexOf(this.options.sortName);
        var params = {
          searchText: this.searchText,
          sortName: this.options.sortName,
          sortOrder: this.options.sortOrder
        };

        if (this.header.sortNames[index]) {
          params.sortName = this.header.sortNames[index];
        }

        if (this.options.pagination && this.options.sidePagination === 'server') {
          params.pageSize = this.options.pageSize === this.options.formatAllRows() ? this.options.totalRows : this.options.pageSize;
          params.pageNumber = this.options.pageNumber;
        }

        if (!(url || this.options.url) && !this.options.ajax) {
          return;
        }

        if (this.options.queryParamsType === 'limit') {
          params = {
            search: params.searchText,
            sort: params.sortName,
            order: params.sortOrder
          };

          if (this.options.pagination && this.options.sidePagination === 'server') {
            params.offset = this.options.pageSize === this.options.formatAllRows() ? 0 : this.options.pageSize * (this.options.pageNumber - 1);
            params.limit = this.options.pageSize === this.options.formatAllRows() ? this.options.totalRows : this.options.pageSize;

            if (params.limit === 0) {
              delete params.limit;
            }
          }
        }

        if (this.options.search && this.options.sidePagination === 'server' && this.columns.filter(function (column) {
          return !column.searchable;
        }).length) {
          params.searchable = [];

          var _iterator2 = _createForOfIteratorHelper(this.columns),
              _step2;

          try {
            for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
              var column = _step2.value;

              if (!column.checkbox && column.searchable && (this.options.visibleSearch && column.visible || !this.options.visibleSearch)) {
                params.searchable.push(column.field);
              }
            }
          } catch (err) {
            _iterator2.e(err);
          } finally {
            _iterator2.f();
          }
        }

        if (!Utils.isEmptyObject(this.filterColumnsPartial)) {
          params.filter = JSON.stringify(this.filterColumnsPartial, null);
        }

        \$__default['default'].extend(params, query || {});
        data = Utils.calculateObjectValue(this.options, this.options.queryParams, [params], data); // false to stop request

        if (data === false) {
          return;
        }

        if (!silent) {
          this.showLoading();
        }

        var request = \$__default['default'].extend({}, Utils.calculateObjectValue(null, this.options.ajaxOptions), {
          type: this.options.method,
          url: url || this.options.url,
          data: this.options.contentType === 'application/json' && this.options.method === 'post' ? JSON.stringify(data) : data,
          cache: this.options.cache,
          contentType: this.options.contentType,
          dataType: this.options.dataType,
          success: function success(_res, textStatus, jqXHR) {
            var res = Utils.calculateObjectValue(_this10.options, _this10.options.responseHandler, [_res, jqXHR], _res);

            _this10.load(res);

            _this10.trigger('load-success', res, jqXHR && jqXHR.status, jqXHR);

            if (!silent) {
              _this10.hideLoading();
            }

            if (_this10.options.sidePagination === 'server' && res[_this10.options.totalField] > 0 && !res[_this10.options.dataField].length) {
              _this10.updatePagination();
            }
          },
          error: function error(jqXHR) {
            var data = [];

            if (_this10.options.sidePagination === 'server') {
              data = {};
              data[_this10.options.totalField] = 0;
              data[_this10.options.dataField] = [];
            }

            _this10.load(data);

            _this10.trigger('load-error', jqXHR && jqXHR.status, jqXHR);

            if (!silent) _this10.\$tableLoading.hide();
          }
        });

        if (this.options.ajax) {
          Utils.calculateObjectValue(this, this.options.ajax, [request], null);
        } else {
          if (this._xhr && this._xhr.readyState !== 4) {
            this._xhr.abort();
          }

          this._xhr = \$__default['default'].ajax(request);
        }

        return data;
      }
    }, {
      key: \"initSearchText\",
      value: function initSearchText() {
        if (this.options.search) {
          this.searchText = '';

          if (this.options.searchText !== '') {
            var \$search = Utils.getSearchInput(this);
            \$search.val(this.options.searchText);
            this.onSearch({
              currentTarget: \$search,
              firedByInitSearchText: true
            });
          }
        }
      }
    }, {
      key: \"getCaret\",
      value: function getCaret() {
        var _this11 = this;

        this.\$header.find('th').each(function (i, th) {
          \$__default['default'](th).find('.sortable').removeClass('desc asc').addClass(\$__default['default'](th).data('field') === _this11.options.sortName ? _this11.options.sortOrder : 'both');
        });
      }
    }, {
      key: \"updateSelected\",
      value: function updateSelected() {
        var checkAll = this.\$selectItem.filter(':enabled').length && this.\$selectItem.filter(':enabled').length === this.\$selectItem.filter(':enabled').filter(':checked').length;
        this.\$selectAll.add(this.\$selectAll_).prop('checked', checkAll);
        this.\$selectItem.each(function (i, el) {
          \$__default['default'](el).closest('tr')[\$__default['default'](el).prop('checked') ? 'addClass' : 'removeClass']('selected');
        });
      }
    }, {
      key: \"updateRows\",
      value: function updateRows() {
        var _this12 = this;

        this.\$selectItem.each(function (i, el) {
          _this12.data[\$__default['default'](el).data('index')][_this12.header.stateField] = \$__default['default'](el).prop('checked');
        });
      }
    }, {
      key: \"resetRows\",
      value: function resetRows() {
        var _iterator3 = _createForOfIteratorHelper(this.data),
            _step3;

        try {
          for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
            var row = _step3.value;
            this.\$selectAll.prop('checked', false);
            this.\$selectItem.prop('checked', false);

            if (this.header.stateField) {
              row[this.header.stateField] = false;
            }
          }
        } catch (err) {
          _iterator3.e(err);
        } finally {
          _iterator3.f();
        }

        this.initHiddenRows();
      }
    }, {
      key: \"trigger\",
      value: function trigger(_name) {
        var _this\$options, _this\$options2;

        var name = \"\".concat(_name, \".bs.table\");

        for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key4 = 1; _key4 < _len; _key4++) {
          args[_key4 - 1] = arguments[_key4];
        }

        (_this\$options = this.options)[BootstrapTable.EVENTS[name]].apply(_this\$options, [].concat(args, [this]));

        this.\$el.trigger(\$__default['default'].Event(name, {
          sender: this
        }), args);

        (_this\$options2 = this.options).onAll.apply(_this\$options2, [name].concat([].concat(args, [this])));

        this.\$el.trigger(\$__default['default'].Event('all.bs.table', {
          sender: this
        }), [name, args]);
      }
    }, {
      key: \"resetHeader\",
      value: function resetHeader() {
        var _this13 = this;

        // fix #61: the hidden table reset header bug.
        // fix bug: get \$el.css('width') error sometime (height = 500)
        clearTimeout(this.timeoutId_);
        this.timeoutId_ = setTimeout(function () {
          return _this13.fitHeader();
        }, this.\$el.is(':hidden') ? 100 : 0);
      }
    }, {
      key: \"fitHeader\",
      value: function fitHeader() {
        var _this14 = this;

        if (this.\$el.is(':hidden')) {
          this.timeoutId_ = setTimeout(function () {
            return _this14.fitHeader();
          }, 100);
          return;
        }

        var fixedBody = this.\$tableBody.get(0);
        var scrollWidth = fixedBody.scrollWidth > fixedBody.clientWidth && fixedBody.scrollHeight > fixedBody.clientHeight + this.\$header.outerHeight() ? Utils.getScrollBarWidth() : 0;
        this.\$el.css('margin-top', -this.\$header.outerHeight());
        var focused = \$__default['default'](':focus');

        if (focused.length > 0) {
          var \$th = focused.parents('th');

          if (\$th.length > 0) {
            var dataField = \$th.attr('data-field');

            if (dataField !== undefined) {
              var \$headerTh = this.\$header.find(\"[data-field='\".concat(dataField, \"']\"));

              if (\$headerTh.length > 0) {
                \$headerTh.find(':input').addClass('focus-temp');
              }
            }
          }
        }

        this.\$header_ = this.\$header.clone(true, true);
        this.\$selectAll_ = this.\$header_.find('[name=\"btSelectAll\"]');
        this.\$tableHeader.css('margin-right', scrollWidth).find('table').css('width', this.\$el.outerWidth()).html('').attr('class', this.\$el.attr('class')).append(this.\$header_);
        this.\$tableLoading.css('width', this.\$el.outerWidth());
        var focusedTemp = \$__default['default']('.focus-temp:visible:eq(0)');

        if (focusedTemp.length > 0) {
          focusedTemp.focus();
          this.\$header.find('.focus-temp').removeClass('focus-temp');
        } // fix bug: \$.data() is not working as expected after \$.append()


        this.\$header.find('th[data-field]').each(function (i, el) {
          _this14.\$header_.find(Utils.sprintf('th[data-field=\"%s\"]', \$__default['default'](el).data('field'))).data(\$__default['default'](el).data());
        });
        var visibleFields = this.getVisibleFields();
        var \$ths = this.\$header_.find('th');
        var \$tr = this.\$body.find('>tr:not(.no-records-found,.virtual-scroll-top)').eq(0);

        while (\$tr.length && \$tr.find('>td[colspan]:not([colspan=\"1\"])').length) {
          \$tr = \$tr.next();
        }

        var trLength = \$tr.find('> *').length;
        \$tr.find('> *').each(function (i, el) {
          var \$this = \$__default['default'](el);

          if (Utils.hasDetailViewIcon(_this14.options)) {
            if (i === 0 && _this14.options.detailViewAlign !== 'right' || i === trLength - 1 && _this14.options.detailViewAlign === 'right') {
              var \$thDetail = \$ths.filter('.detail');

              var _zoomWidth = \$thDetail.innerWidth() - \$thDetail.find('.fht-cell').width();

              \$thDetail.find('.fht-cell').width(\$this.innerWidth() - _zoomWidth);
              return;
            }
          }

          var index = i - Utils.getDetailViewIndexOffset(_this14.options);

          var \$th = _this14.\$header_.find(Utils.sprintf('th[data-field=\"%s\"]', visibleFields[index]));

          if (\$th.length > 1) {
            \$th = \$__default['default'](\$ths[\$this[0].cellIndex]);
          }

          var zoomWidth = \$th.innerWidth() - \$th.find('.fht-cell').width();
          \$th.find('.fht-cell').width(\$this.innerWidth() - zoomWidth);
        });
        this.horizontalScroll();
        this.trigger('post-header');
      }
    }, {
      key: \"initFooter\",
      value: function initFooter() {
        if (!this.options.showFooter || this.options.cardView) {
          // do nothing
          return;
        }

        var data = this.getData();
        var html = [];
        var detailTemplate = '';

        if (Utils.hasDetailViewIcon(this.options)) {
          detailTemplate = '<th class=\"detail\"><div class=\"th-inner\"></div><div class=\"fht-cell\"></div></th>';
        }

        if (detailTemplate && this.options.detailViewAlign !== 'right') {
          html.push(detailTemplate);
        }

        var _iterator4 = _createForOfIteratorHelper(this.columns),
            _step4;

        try {
          for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
            var column = _step4.value;
            var falign = '';
            var valign = '';
            var csses = [];
            var style = {};
            var class_ = Utils.sprintf(' class=\"%s\"', column['class']);

            if (!column.visible || this.footerData && this.footerData.length > 0 && !(column.field in this.footerData[0])) {
              continue;
            }

            if (this.options.cardView && !column.cardVisible) {
              return;
            }

            falign = Utils.sprintf('text-align: %s; ', column.falign ? column.falign : column.align);
            valign = Utils.sprintf('vertical-align: %s; ', column.valign);
            style = Utils.calculateObjectValue(null, this.options.footerStyle, [column]);

            if (style && style.css) {
              for (var _i12 = 0, _Object\$entries11 = Object.entries(style.css); _i12 < _Object\$entries11.length; _i12++) {
                var _Object\$entries11\$_i = _slicedToArray(_Object\$entries11[_i12], 2),
                    key = _Object\$entries11\$_i[0],
                    _value3 = _Object\$entries11\$_i[1];

                csses.push(\"\".concat(key, \": \").concat(_value3));
              }
            }

            if (style && style.classes) {
              class_ = Utils.sprintf(' class=\"%s\"', column['class'] ? [column['class'], style.classes].join(' ') : style.classes);
            }

            html.push('<th', class_, Utils.sprintf(' style=\"%s\"', falign + valign + csses.concat().join('; ')));
            var colspan = 0;

            if (this.footerData && this.footerData.length > 0) {
              colspan = this.footerData[0][\"_\".concat(column.field, \"_colspan\")] || 0;
            }

            if (colspan) {
              html.push(\" colspan=\\\"\".concat(colspan, \"\\\" \"));
            }

            html.push('>');
            html.push('<div class=\"th-inner\">');
            var value = '';

            if (this.footerData && this.footerData.length > 0) {
              value = this.footerData[0][column.field] || '';
            }

            html.push(Utils.calculateObjectValue(column, column.footerFormatter, [data, value], value));
            html.push('</div>');
            html.push('<div class=\"fht-cell\"></div>');
            html.push('</div>');
            html.push('</th>');
          }
        } catch (err) {
          _iterator4.e(err);
        } finally {
          _iterator4.f();
        }

        if (detailTemplate && this.options.detailViewAlign === 'right') {
          html.push(detailTemplate);
        }

        if (!this.options.height && !this.\$tableFooter.length) {
          this.\$el.append('<tfoot><tr></tr></tfoot>');
          this.\$tableFooter = this.\$el.find('tfoot');
        }

        if (!this.\$tableFooter.find('tr').length) {
          this.\$tableFooter.html('<table><thead><tr></tr></thead></table>');
        }

        this.\$tableFooter.find('tr').html(html.join(''));
        this.trigger('post-footer', this.\$tableFooter);
      }
    }, {
      key: \"fitFooter\",
      value: function fitFooter() {
        var _this15 = this;

        if (this.\$el.is(':hidden')) {
          setTimeout(function () {
            return _this15.fitFooter();
          }, 100);
          return;
        }

        var fixedBody = this.\$tableBody.get(0);
        var scrollWidth = fixedBody.scrollWidth > fixedBody.clientWidth && fixedBody.scrollHeight > fixedBody.clientHeight + this.\$header.outerHeight() ? Utils.getScrollBarWidth() : 0;
        this.\$tableFooter.css('margin-right', scrollWidth).find('table').css('width', this.\$el.outerWidth()).attr('class', this.\$el.attr('class'));
        var \$ths = this.\$tableFooter.find('th');
        var \$tr = this.\$body.find('>tr:first-child:not(.no-records-found)');
        \$ths.find('.fht-cell').width('auto');

        while (\$tr.length && \$tr.find('>td[colspan]:not([colspan=\"1\"])').length) {
          \$tr = \$tr.next();
        }

        var trLength = \$tr.find('> *').length;
        \$tr.find('> *').each(function (i, el) {
          var \$this = \$__default['default'](el);

          if (Utils.hasDetailViewIcon(_this15.options)) {
            if (i === 0 && _this15.options.detailViewAlign === 'left' || i === trLength - 1 && _this15.options.detailViewAlign === 'right') {
              var \$thDetail = \$ths.filter('.detail');

              var _zoomWidth2 = \$thDetail.innerWidth() - \$thDetail.find('.fht-cell').width();

              \$thDetail.find('.fht-cell').width(\$this.innerWidth() - _zoomWidth2);
              return;
            }
          }

          var \$th = \$ths.eq(i);
          var zoomWidth = \$th.innerWidth() - \$th.find('.fht-cell').width();
          \$th.find('.fht-cell').width(\$this.innerWidth() - zoomWidth);
        });
        this.horizontalScroll();
      }
    }, {
      key: \"horizontalScroll\",
      value: function horizontalScroll() {
        var _this16 = this;

        // horizontal scroll event
        // TODO: it's probably better improving the layout than binding to scroll event
        this.\$tableBody.off('scroll').on('scroll', function () {
          var scrollLeft = _this16.\$tableBody.scrollLeft();

          if (_this16.options.showHeader && _this16.options.height) {
            _this16.\$tableHeader.scrollLeft(scrollLeft);
          }

          if (_this16.options.showFooter && !_this16.options.cardView) {
            _this16.\$tableFooter.scrollLeft(scrollLeft);
          }

          _this16.trigger('scroll-body', _this16.\$tableBody);
        });
      }
    }, {
      key: \"getVisibleFields\",
      value: function getVisibleFields() {
        var visibleFields = [];

        var _iterator5 = _createForOfIteratorHelper(this.header.fields),
            _step5;

        try {
          for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
            var field = _step5.value;
            var column = this.columns[this.fieldsColumnsIndex[field]];

            if (!column || !column.visible) {
              continue;
            }

            visibleFields.push(field);
          }
        } catch (err) {
          _iterator5.e(err);
        } finally {
          _iterator5.f();
        }

        return visibleFields;
      }
    }, {
      key: \"initHiddenRows\",
      value: function initHiddenRows() {
        this.hiddenRows = [];
      } // PUBLIC FUNCTION DEFINITION
      // =======================

    }, {
      key: \"getOptions\",
      value: function getOptions() {
        // deep copy and remove data
        var options = \$__default['default'].extend({}, this.options);
        delete options.data;
        return \$__default['default'].extend(true, {}, options);
      }
    }, {
      key: \"refreshOptions\",
      value: function refreshOptions(options) {
        // If the objects are equivalent then avoid the call of destroy / init methods
        if (Utils.compareObjects(this.options, options, true)) {
          return;
        }

        this.options = \$__default['default'].extend(this.options, options);
        this.trigger('refresh-options', this.options);
        this.destroy();
        this.init();
      }
    }, {
      key: \"getData\",
      value: function getData(params) {
        var _this17 = this;

        var data = this.options.data;

        if ((this.searchText || this.options.customSearch || this.options.sortName !== undefined || this.enableCustomSort || // Fix #4616: this.enableCustomSort is for extensions
        !Utils.isEmptyObject(this.filterColumns) || !Utils.isEmptyObject(this.filterColumnsPartial)) && (!params || !params.unfiltered)) {
          data = this.data;
        }

        if (params && params.useCurrentPage) {
          data = data.slice(this.pageFrom - 1, this.pageTo);
        }

        if (params && !params.includeHiddenRows) {
          var hiddenRows = this.getHiddenRows();
          data = data.filter(function (row) {
            return Utils.findIndex(hiddenRows, row) === -1;
          });
        }

        if (params && params.formatted) {
          data.forEach(function (row) {
            for (var _i13 = 0, _Object\$entries12 = Object.entries(row); _i13 < _Object\$entries12.length; _i13++) {
              var _Object\$entries12\$_i = _slicedToArray(_Object\$entries12[_i13], 2),
                  key = _Object\$entries12\$_i[0],
                  value = _Object\$entries12\$_i[1];

              var column = _this17.columns[_this17.fieldsColumnsIndex[key]];

              if (!column) {
                return;
              }

              row[key] = Utils.calculateObjectValue(column, _this17.header.formatters[column.fieldIndex], [value, row, row.index, column.field], value);
            }
          });
        }

        return data;
      }
    }, {
      key: \"getSelections\",
      value: function getSelections() {
        var _this18 = this;

        return (this.options.maintainMetaData ? this.options.data : this.data).filter(function (row) {
          return row[_this18.header.stateField] === true;
        });
      }
    }, {
      key: \"load\",
      value: function load(_data) {
        var fixedScroll = false;
        var data = _data; // #431: support pagination

        if (this.options.pagination && this.options.sidePagination === 'server') {
          this.options.totalRows = data[this.options.totalField];
          this.options.totalNotFiltered = data[this.options.totalNotFilteredField];
          this.footerData = data[this.options.footerField] ? [data[this.options.footerField]] : undefined;
        }

        fixedScroll = data.fixedScroll;
        data = Array.isArray(data) ? data : data[this.options.dataField];
        this.initData(data);
        this.initSearch();
        this.initPagination();
        this.initBody(fixedScroll);
      }
    }, {
      key: \"append\",
      value: function append(data) {
        this.initData(data, 'append');
        this.initSearch();
        this.initPagination();
        this.initSort();
        this.initBody(true);
      }
    }, {
      key: \"prepend\",
      value: function prepend(data) {
        this.initData(data, 'prepend');
        this.initSearch();
        this.initPagination();
        this.initSort();
        this.initBody(true);
      }
    }, {
      key: \"remove\",
      value: function remove(params) {
        var removed = 0;

        for (var i = this.options.data.length - 1; i >= 0; i--) {
          var row = this.options.data[i];

          if (!row.hasOwnProperty(params.field) && params.field !== '\$index') {
            continue;
          }

          if (!row.hasOwnProperty(params.field) && params.field === '\$index' && params.values.includes(i) || params.values.includes(row[params.field])) {
            removed++;
            this.options.data.splice(i, 1);
          }
        }

        if (!removed) {
          return;
        }

        if (this.options.sidePagination === 'server') {
          this.options.totalRows -= removed;
          this.data = _toConsumableArray(this.options.data);
        }

        this.initSearch();
        this.initPagination();
        this.initSort();
        this.initBody(true);
      }
    }, {
      key: \"removeAll\",
      value: function removeAll() {
        if (this.options.data.length > 0) {
          this.options.data.splice(0, this.options.data.length);
          this.initSearch();
          this.initPagination();
          this.initBody(true);
        }
      }
    }, {
      key: \"insertRow\",
      value: function insertRow(params) {
        if (!params.hasOwnProperty('index') || !params.hasOwnProperty('row')) {
          return;
        }

        this.options.data.splice(params.index, 0, params.row);
        this.initSearch();
        this.initPagination();
        this.initSort();
        this.initBody(true);
      }
    }, {
      key: \"updateRow\",
      value: function updateRow(params) {
        var allParams = Array.isArray(params) ? params : [params];

        var _iterator6 = _createForOfIteratorHelper(allParams),
            _step6;

        try {
          for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
            var _params = _step6.value;

            if (!_params.hasOwnProperty('index') || !_params.hasOwnProperty('row')) {
              continue;
            }

            if (_params.hasOwnProperty('replace') && _params.replace) {
              this.options.data[_params.index] = _params.row;
            } else {
              \$__default['default'].extend(this.options.data[_params.index], _params.row);
            }
          }
        } catch (err) {
          _iterator6.e(err);
        } finally {
          _iterator6.f();
        }

        this.initSearch();
        this.initPagination();
        this.initSort();
        this.initBody(true);
      }
    }, {
      key: \"getRowByUniqueId\",
      value: function getRowByUniqueId(_id) {
        var uniqueId = this.options.uniqueId;
        var len = this.options.data.length;
        var id = _id;
        var dataRow = null;
        var i;
        var row;
        var rowUniqueId;

        for (i = len - 1; i >= 0; i--) {
          row = this.options.data[i];

          if (row.hasOwnProperty(uniqueId)) {
            // uniqueId is a column
            rowUniqueId = row[uniqueId];
          } else if (row._data && row._data.hasOwnProperty(uniqueId)) {
            // uniqueId is a row data property
            rowUniqueId = row._data[uniqueId];
          } else {
            continue;
          }

          if (typeof rowUniqueId === 'string') {
            id = id.toString();
          } else if (typeof rowUniqueId === 'number') {
            if (Number(rowUniqueId) === rowUniqueId && rowUniqueId % 1 === 0) {
              id = parseInt(id);
            } else if (rowUniqueId === Number(rowUniqueId) && rowUniqueId !== 0) {
              id = parseFloat(id);
            }
          }

          if (rowUniqueId === id) {
            dataRow = row;
            break;
          }
        }

        return dataRow;
      }
    }, {
      key: \"updateByUniqueId\",
      value: function updateByUniqueId(params) {
        var allParams = Array.isArray(params) ? params : [params];

        var _iterator7 = _createForOfIteratorHelper(allParams),
            _step7;

        try {
          for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
            var _params2 = _step7.value;

            if (!_params2.hasOwnProperty('id') || !_params2.hasOwnProperty('row')) {
              continue;
            }

            var rowId = this.options.data.indexOf(this.getRowByUniqueId(_params2.id));

            if (rowId === -1) {
              continue;
            }

            if (_params2.hasOwnProperty('replace') && _params2.replace) {
              this.options.data[rowId] = _params2.row;
            } else {
              \$__default['default'].extend(this.options.data[rowId], _params2.row);
            }
          }
        } catch (err) {
          _iterator7.e(err);
        } finally {
          _iterator7.f();
        }

        this.initSearch();
        this.initPagination();
        this.initSort();
        this.initBody(true);
      }
    }, {
      key: \"removeByUniqueId\",
      value: function removeByUniqueId(id) {
        var len = this.options.data.length;
        var row = this.getRowByUniqueId(id);

        if (row) {
          this.options.data.splice(this.options.data.indexOf(row), 1);
        }

        if (len === this.options.data.length) {
          return;
        }

        if (this.options.sidePagination === 'server') {
          this.options.totalRows -= 1;
          this.data = _toConsumableArray(this.options.data);
        }

        this.initSearch();
        this.initPagination();
        this.initBody(true);
      }
    }, {
      key: \"updateCell\",
      value: function updateCell(params) {
        if (!params.hasOwnProperty('index') || !params.hasOwnProperty('field') || !params.hasOwnProperty('value')) {
          return;
        }

        this.data[params.index][params.field] = params.value;

        if (params.reinit === false) {
          return;
        }

        this.initSort();
        this.initBody(true);
      }
    }, {
      key: \"updateCellByUniqueId\",
      value: function updateCellByUniqueId(params) {
        var _this19 = this;

        var allParams = Array.isArray(params) ? params : [params];
        allParams.forEach(function (_ref6) {
          var id = _ref6.id,
              field = _ref6.field,
              value = _ref6.value;

          var rowId = _this19.options.data.indexOf(_this19.getRowByUniqueId(id));

          if (rowId === -1) {
            return;
          }

          _this19.options.data[rowId][field] = value;
        });

        if (params.reinit === false) {
          return;
        }

        this.initSort();
        this.initBody(true);
      }
    }, {
      key: \"showRow\",
      value: function showRow(params) {
        this._toggleRow(params, true);
      }
    }, {
      key: \"hideRow\",
      value: function hideRow(params) {
        this._toggleRow(params, false);
      }
    }, {
      key: \"_toggleRow\",
      value: function _toggleRow(params, visible) {
        var row;

        if (params.hasOwnProperty('index')) {
          row = this.getData()[params.index];
        } else if (params.hasOwnProperty('uniqueId')) {
          row = this.getRowByUniqueId(params.uniqueId);
        }

        if (!row) {
          return;
        }

        var index = Utils.findIndex(this.hiddenRows, row);

        if (!visible && index === -1) {
          this.hiddenRows.push(row);
        } else if (visible && index > -1) {
          this.hiddenRows.splice(index, 1);
        }

        this.initBody(true);
        this.initPagination();
      }
    }, {
      key: \"getHiddenRows\",
      value: function getHiddenRows(show) {
        if (show) {
          this.initHiddenRows();
          this.initBody(true);
          this.initPagination();
          return;
        }

        var data = this.getData();
        var rows = [];

        var _iterator8 = _createForOfIteratorHelper(data),
            _step8;

        try {
          for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
            var row = _step8.value;

            if (this.hiddenRows.includes(row)) {
              rows.push(row);
            }
          }
        } catch (err) {
          _iterator8.e(err);
        } finally {
          _iterator8.f();
        }

        this.hiddenRows = rows;
        return rows;
      }
    }, {
      key: \"showColumn\",
      value: function showColumn(field) {
        var _this20 = this;

        var fields = Array.isArray(field) ? field : [field];
        fields.forEach(function (field) {
          _this20._toggleColumn(_this20.fieldsColumnsIndex[field], true, true);
        });
      }
    }, {
      key: \"hideColumn\",
      value: function hideColumn(field) {
        var _this21 = this;

        var fields = Array.isArray(field) ? field : [field];
        fields.forEach(function (field) {
          _this21._toggleColumn(_this21.fieldsColumnsIndex[field], false, true);
        });
      }
    }, {
      key: \"_toggleColumn\",
      value: function _toggleColumn(index, checked, needUpdate) {
        if (index === -1 || this.columns[index].visible === checked) {
          return;
        }

        this.columns[index].visible = checked;
        this.initHeader();
        this.initSearch();
        this.initPagination();
        this.initBody();

        if (this.options.showColumns) {
          var \$items = this.\$toolbar.find('.keep-open input:not(\".toggle-all\")').prop('disabled', false);

          if (needUpdate) {
            \$items.filter(Utils.sprintf('[value=\"%s\"]', index)).prop('checked', checked);
          }

          if (\$items.filter(':checked').length <= this.options.minimumCountColumns) {
            \$items.filter(':checked').prop('disabled', true);
          }
        }
      }
    }, {
      key: \"getVisibleColumns\",
      value: function getVisibleColumns() {
        var _this22 = this;

        return this.columns.filter(function (column) {
          return column.visible && !_this22.isSelectionColumn(column);
        });
      }
    }, {
      key: \"getHiddenColumns\",
      value: function getHiddenColumns() {
        return this.columns.filter(function (_ref7) {
          var visible = _ref7.visible;
          return !visible;
        });
      }
    }, {
      key: \"isSelectionColumn\",
      value: function isSelectionColumn(column) {
        return column.radio || column.checkbox;
      }
    }, {
      key: \"showAllColumns\",
      value: function showAllColumns() {
        this._toggleAllColumns(true);
      }
    }, {
      key: \"hideAllColumns\",
      value: function hideAllColumns() {
        this._toggleAllColumns(false);
      }
    }, {
      key: \"_toggleAllColumns\",
      value: function _toggleAllColumns(visible) {
        var _this23 = this;

        var _iterator9 = _createForOfIteratorHelper(this.columns.slice().reverse()),
            _step9;

        try {
          for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
            var column = _step9.value;

            if (column.switchable) {
              if (!visible && this.options.showColumns && this.getVisibleColumns().length === this.options.minimumCountColumns) {
                continue;
              }

              column.visible = visible;
            }
          }
        } catch (err) {
          _iterator9.e(err);
        } finally {
          _iterator9.f();
        }

        this.initHeader();
        this.initSearch();
        this.initPagination();
        this.initBody();

        if (this.options.showColumns) {
          var \$items = this.\$toolbar.find('.keep-open input[type=\"checkbox\"]:not(\".toggle-all\")').prop('disabled', false);

          if (visible) {
            \$items.prop('checked', visible);
          } else {
            \$items.get().reverse().forEach(function (item) {
              if (\$items.filter(':checked').length > _this23.options.minimumCountColumns) {
                \$__default['default'](item).prop('checked', visible);
              }
            });
          }

          if (\$items.filter(':checked').length <= this.options.minimumCountColumns) {
            \$items.filter(':checked').prop('disabled', true);
          }
        }
      }
    }, {
      key: \"mergeCells\",
      value: function mergeCells(options) {
        var row = options.index;
        var col = this.getVisibleFields().indexOf(options.field);
        var rowspan = options.rowspan || 1;
        var colspan = options.colspan || 1;
        var i;
        var j;
        var \$tr = this.\$body.find('>tr');
        col += Utils.getDetailViewIndexOffset(this.options);
        var \$td = \$tr.eq(row).find('>td').eq(col);

        if (row < 0 || col < 0 || row >= this.data.length) {
          return;
        }

        for (i = row; i < row + rowspan; i++) {
          for (j = col; j < col + colspan; j++) {
            \$tr.eq(i).find('>td').eq(j).hide();
          }
        }

        \$td.attr('rowspan', rowspan).attr('colspan', colspan).show();
      }
    }, {
      key: \"checkAll\",
      value: function checkAll() {
        this._toggleCheckAll(true);
      }
    }, {
      key: \"uncheckAll\",
      value: function uncheckAll() {
        this._toggleCheckAll(false);
      }
    }, {
      key: \"_toggleCheckAll\",
      value: function _toggleCheckAll(checked) {
        var rowsBefore = this.getSelections();
        this.\$selectAll.add(this.\$selectAll_).prop('checked', checked);
        this.\$selectItem.filter(':enabled').prop('checked', checked);
        this.updateRows();
        this.updateSelected();
        var rowsAfter = this.getSelections();

        if (checked) {
          this.trigger('check-all', rowsAfter, rowsBefore);
          return;
        }

        this.trigger('uncheck-all', rowsAfter, rowsBefore);
      }
    }, {
      key: \"checkInvert\",
      value: function checkInvert() {
        var \$items = this.\$selectItem.filter(':enabled');
        var checked = \$items.filter(':checked');
        \$items.each(function (i, el) {
          \$__default['default'](el).prop('checked', !\$__default['default'](el).prop('checked'));
        });
        this.updateRows();
        this.updateSelected();
        this.trigger('uncheck-some', checked);
        checked = this.getSelections();
        this.trigger('check-some', checked);
      }
    }, {
      key: \"check\",
      value: function check(index) {
        this._toggleCheck(true, index);
      }
    }, {
      key: \"uncheck\",
      value: function uncheck(index) {
        this._toggleCheck(false, index);
      }
    }, {
      key: \"_toggleCheck\",
      value: function _toggleCheck(checked, index) {
        var \$el = this.\$selectItem.filter(\"[data-index=\\\"\".concat(index, \"\\\"]\"));
        var row = this.data[index];

        if (\$el.is(':radio') || this.options.singleSelect || this.options.multipleSelectRow && !this.multipleSelectRowCtrlKey && !this.multipleSelectRowShiftKey) {
          var _iterator10 = _createForOfIteratorHelper(this.options.data),
              _step10;

          try {
            for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) {
              var r = _step10.value;
              r[this.header.stateField] = false;
            }
          } catch (err) {
            _iterator10.e(err);
          } finally {
            _iterator10.f();
          }

          this.\$selectItem.filter(':checked').not(\$el).prop('checked', false);
        }

        row[this.header.stateField] = checked;

        if (this.options.multipleSelectRow) {
          if (this.multipleSelectRowShiftKey && this.multipleSelectRowLastSelectedIndex >= 0) {
            var _ref8 = this.multipleSelectRowLastSelectedIndex < index ? [this.multipleSelectRowLastSelectedIndex, index] : [index, this.multipleSelectRowLastSelectedIndex],
                _ref9 = _slicedToArray(_ref8, 2),
                fromIndex = _ref9[0],
                toIndex = _ref9[1];

            for (var i = fromIndex + 1; i < toIndex; i++) {
              this.data[i][this.header.stateField] = true;
              this.\$selectItem.filter(\"[data-index=\\\"\".concat(i, \"\\\"]\")).prop('checked', true);
            }
          }

          this.multipleSelectRowCtrlKey = false;
          this.multipleSelectRowShiftKey = false;
          this.multipleSelectRowLastSelectedIndex = checked ? index : -1;
        }

        \$el.prop('checked', checked);
        this.updateSelected();
        this.trigger(checked ? 'check' : 'uncheck', this.data[index], \$el);
      }
    }, {
      key: \"checkBy\",
      value: function checkBy(obj) {
        this._toggleCheckBy(true, obj);
      }
    }, {
      key: \"uncheckBy\",
      value: function uncheckBy(obj) {
        this._toggleCheckBy(false, obj);
      }
    }, {
      key: \"_toggleCheckBy\",
      value: function _toggleCheckBy(checked, obj) {
        var _this24 = this;

        if (!obj.hasOwnProperty('field') || !obj.hasOwnProperty('values')) {
          return;
        }

        var rows = [];
        this.data.forEach(function (row, i) {
          if (!row.hasOwnProperty(obj.field)) {
            return false;
          }

          if (obj.values.includes(row[obj.field])) {
            var \$el = _this24.\$selectItem.filter(':enabled').filter(Utils.sprintf('[data-index=\"%s\"]', i));

            \$el = checked ? \$el.not(':checked') : \$el.filter(':checked');

            if (!\$el.length) {
              return;
            }

            \$el.prop('checked', checked);
            row[_this24.header.stateField] = checked;
            rows.push(row);

            _this24.trigger(checked ? 'check' : 'uncheck', row, \$el);
          }
        });
        this.updateSelected();
        this.trigger(checked ? 'check-some' : 'uncheck-some', rows);
      }
    }, {
      key: \"refresh\",
      value: function refresh(params) {
        if (params && params.url) {
          this.options.url = params.url;
        }

        if (params && params.pageNumber) {
          this.options.pageNumber = params.pageNumber;
        }

        if (params && params.pageSize) {
          this.options.pageSize = params.pageSize;
        }

        this.trigger('refresh', this.initServer(params && params.silent, params && params.query, params && params.url));
      }
    }, {
      key: \"destroy\",
      value: function destroy() {
        this.\$el.insertBefore(this.\$container);
        \$__default['default'](this.options.toolbar).insertBefore(this.\$el);
        this.\$container.next().remove();
        this.\$container.remove();
        this.\$el.html(this.\$el_.html()).css('margin-top', '0').attr('class', this.\$el_.attr('class') || ''); // reset the class
      }
    }, {
      key: \"resetView\",
      value: function resetView(params) {
        var padding = 0;

        if (params && params.height) {
          this.options.height = params.height;
        }

        this.\$selectAll.prop('checked', this.\$selectItem.length > 0 && this.\$selectItem.length === this.\$selectItem.filter(':checked').length);
        this.\$tableContainer.toggleClass('has-card-view', this.options.cardView);

        if (!this.options.cardView && this.options.showHeader && this.options.height) {
          this.\$tableHeader.show();
          this.resetHeader();
          padding += this.\$header.outerHeight(true) + 1;
        } else {
          this.\$tableHeader.hide();
          this.trigger('post-header');
        }

        if (!this.options.cardView && this.options.showFooter) {
          this.\$tableFooter.show();
          this.fitFooter();

          if (this.options.height) {
            padding += this.\$tableFooter.outerHeight(true);
          }
        }

        if (this.\$container.hasClass('fullscreen')) {
          this.\$tableContainer.css('height', '');
          this.\$tableContainer.css('width', '');
        } else if (this.options.height) {
          if (this.\$tableBorder) {
            this.\$tableBorder.css('width', '');
            this.\$tableBorder.css('height', '');
          }

          var toolbarHeight = this.\$toolbar.outerHeight(true);
          var paginationHeight = this.\$pagination.outerHeight(true);
          var height = this.options.height - toolbarHeight - paginationHeight;
          var \$bodyTable = this.\$tableBody.find('>table');
          var tableHeight = \$bodyTable.outerHeight();
          this.\$tableContainer.css('height', \"\".concat(height, \"px\"));

          if (this.\$tableBorder && \$bodyTable.is(':visible')) {
            var tableBorderHeight = height - tableHeight - 2;

            if (this.\$tableBody[0].scrollWidth - this.\$tableBody.innerWidth()) {
              tableBorderHeight -= Utils.getScrollBarWidth();
            }

            this.\$tableBorder.css('width', \"\".concat(\$bodyTable.outerWidth(), \"px\"));
            this.\$tableBorder.css('height', \"\".concat(tableBorderHeight, \"px\"));
          }
        }

        if (this.options.cardView) {
          // remove the element css
          this.\$el.css('margin-top', '0');
          this.\$tableContainer.css('padding-bottom', '0');
          this.\$tableFooter.hide();
        } else {
          // Assign the correct sortable arrow
          this.getCaret();
          this.\$tableContainer.css('padding-bottom', \"\".concat(padding, \"px\"));
        }

        this.trigger('reset-view');
      }
    }, {
      key: \"showLoading\",
      value: function showLoading() {
        this.\$tableLoading.toggleClass('open', true);
        var fontSize = this.options.loadingFontSize;

        if (this.options.loadingFontSize === 'auto') {
          fontSize = this.\$tableLoading.width() * 0.04;
          fontSize = Math.max(12, fontSize);
          fontSize = Math.min(32, fontSize);
          fontSize = \"\".concat(fontSize, \"px\");
        }

        this.\$tableLoading.find('.loading-text').css('font-size', fontSize);
      }
    }, {
      key: \"hideLoading\",
      value: function hideLoading() {
        this.\$tableLoading.toggleClass('open', false);
      }
    }, {
      key: \"togglePagination\",
      value: function togglePagination() {
        this.options.pagination = !this.options.pagination;
        var icon = this.options.showButtonIcons ? this.options.pagination ? this.options.icons.paginationSwitchDown : this.options.icons.paginationSwitchUp : '';
        var text = this.options.showButtonText ? this.options.pagination ? this.options.formatPaginationSwitchUp() : this.options.formatPaginationSwitchDown() : '';
        this.\$toolbar.find('button[name=\"paginationSwitch\"]').html(\"\".concat(Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, icon), \" \").concat(text));
        this.updatePagination();
      }
    }, {
      key: \"toggleFullscreen\",
      value: function toggleFullscreen() {
        this.\$el.closest('.bootstrap-table').toggleClass('fullscreen');
        this.resetView();
      }
    }, {
      key: \"toggleView\",
      value: function toggleView() {
        this.options.cardView = !this.options.cardView;
        this.initHeader();
        var icon = this.options.showButtonIcons ? this.options.cardView ? this.options.icons.toggleOn : this.options.icons.toggleOff : '';
        var text = this.options.showButtonText ? this.options.cardView ? this.options.formatToggleOff() : this.options.formatToggleOn() : '';
        this.\$toolbar.find('button[name=\"toggle\"]').html(\"\".concat(Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, icon), \" \").concat(text));
        this.initBody();
        this.trigger('toggle', this.options.cardView);
      }
    }, {
      key: \"resetSearch\",
      value: function resetSearch(text) {
        var \$search = Utils.getSearchInput(this);
        \$search.val(text || '');
        this.onSearch({
          currentTarget: \$search
        });
      }
    }, {
      key: \"filterBy\",
      value: function filterBy(columns, options) {
        this.filterOptions = Utils.isEmptyObject(options) ? this.options.filterOptions : \$__default['default'].extend(this.options.filterOptions, options);
        this.filterColumns = Utils.isEmptyObject(columns) ? {} : columns;
        this.options.pageNumber = 1;
        this.initSearch();
        this.updatePagination();
      }
    }, {
      key: \"scrollTo\",
      value: function scrollTo(params) {
        var options = {
          unit: 'px',
          value: 0
        };

        if (_typeof(params) === 'object') {
          options = Object.assign(options, params);
        } else if (typeof params === 'string' && params === 'bottom') {
          options.value = this.\$tableBody[0].scrollHeight;
        } else if (typeof params === 'string' || typeof params === 'number') {
          options.value = params;
        }

        var scrollTo = options.value;

        if (options.unit === 'rows') {
          scrollTo = 0;
          this.\$body.find(\"> tr:lt(\".concat(options.value, \")\")).each(function (i, el) {
            scrollTo += \$__default['default'](el).outerHeight(true);
          });
        }

        this.\$tableBody.scrollTop(scrollTo);
      }
    }, {
      key: \"getScrollPosition\",
      value: function getScrollPosition() {
        return this.\$tableBody.scrollTop();
      }
    }, {
      key: \"selectPage\",
      value: function selectPage(page) {
        if (page > 0 && page <= this.options.totalPages) {
          this.options.pageNumber = page;
          this.updatePagination();
        }
      }
    }, {
      key: \"prevPage\",
      value: function prevPage() {
        if (this.options.pageNumber > 1) {
          this.options.pageNumber--;
          this.updatePagination();
        }
      }
    }, {
      key: \"nextPage\",
      value: function nextPage() {
        if (this.options.pageNumber < this.options.totalPages) {
          this.options.pageNumber++;
          this.updatePagination();
        }
      }
    }, {
      key: \"toggleDetailView\",
      value: function toggleDetailView(index, _columnDetailFormatter) {
        var \$tr = this.\$body.find(Utils.sprintf('> tr[data-index=\"%s\"]', index));

        if (\$tr.next().is('tr.detail-view')) {
          this.collapseRow(index);
        } else {
          this.expandRow(index, _columnDetailFormatter);
        }

        this.resetView();
      }
    }, {
      key: \"expandRow\",
      value: function expandRow(index, _columnDetailFormatter) {
        var row = this.data[index];
        var \$tr = this.\$body.find(Utils.sprintf('> tr[data-index=\"%s\"][data-has-detail-view]', index));

        if (\$tr.next().is('tr.detail-view')) {
          return;
        }

        if (this.options.detailViewIcon) {
          \$tr.find('a.detail-icon').html(Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, this.options.icons.detailClose));
        }

        \$tr.after(Utils.sprintf('<tr class=\"detail-view\"><td colspan=\"%s\"></td></tr>', \$tr.children('td').length));
        var \$element = \$tr.next().find('td');
        var detailFormatter = _columnDetailFormatter || this.options.detailFormatter;
        var content = Utils.calculateObjectValue(this.options, detailFormatter, [index, row, \$element], '');

        if (\$element.length === 1) {
          \$element.append(content);
        }

        this.trigger('expand-row', index, row, \$element);
      }
    }, {
      key: \"expandRowByUniqueId\",
      value: function expandRowByUniqueId(uniqueId) {
        var row = this.getRowByUniqueId(uniqueId);

        if (!row) {
          return;
        }

        this.expandRow(this.data.indexOf(row));
      }
    }, {
      key: \"collapseRow\",
      value: function collapseRow(index) {
        var row = this.data[index];
        var \$tr = this.\$body.find(Utils.sprintf('> tr[data-index=\"%s\"][data-has-detail-view]', index));

        if (!\$tr.next().is('tr.detail-view')) {
          return;
        }

        if (this.options.detailViewIcon) {
          \$tr.find('a.detail-icon').html(Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, this.options.icons.detailOpen));
        }

        this.trigger('collapse-row', index, row, \$tr.next());
        \$tr.next().remove();
      }
    }, {
      key: \"collapseRowByUniqueId\",
      value: function collapseRowByUniqueId(uniqueId) {
        var row = this.getRowByUniqueId(uniqueId);

        if (!row) {
          return;
        }

        this.collapseRow(this.data.indexOf(row));
      }
    }, {
      key: \"expandAllRows\",
      value: function expandAllRows() {
        var trs = this.\$body.find('> tr[data-index][data-has-detail-view]');

        for (var i = 0; i < trs.length; i++) {
          this.expandRow(\$__default['default'](trs[i]).data('index'));
        }
      }
    }, {
      key: \"collapseAllRows\",
      value: function collapseAllRows() {
        var trs = this.\$body.find('> tr[data-index][data-has-detail-view]');

        for (var i = 0; i < trs.length; i++) {
          this.collapseRow(\$__default['default'](trs[i]).data('index'));
        }
      }
    }, {
      key: \"updateColumnTitle\",
      value: function updateColumnTitle(params) {
        if (!params.hasOwnProperty('field') || !params.hasOwnProperty('title')) {
          return;
        }

        this.columns[this.fieldsColumnsIndex[params.field]].title = this.options.escape ? Utils.escapeHTML(params.title) : params.title;

        if (this.columns[this.fieldsColumnsIndex[params.field]].visible) {
          this.\$header.find('th[data-field]').each(function (i, el) {
            if (\$__default['default'](el).data('field') === params.field) {
              \$__default['default'](\$__default['default'](el).find('.th-inner')[0]).text(params.title);
              return false;
            }
          });
          this.resetView();
        }
      }
    }, {
      key: \"updateFormatText\",
      value: function updateFormatText(formatName, text) {
        if (!/^format/.test(formatName) || !this.options[formatName]) {
          return;
        }

        if (typeof text === 'string') {
          this.options[formatName] = function () {
            return text;
          };
        } else if (typeof text === 'function') {
          this.options[formatName] = text;
        }

        this.initToolbar();
        this.initPagination();
        this.initBody();
      }
    }]);

    return BootstrapTable;
  }();

  BootstrapTable.VERSION = Constants.VERSION;
  BootstrapTable.DEFAULTS = Constants.DEFAULTS;
  BootstrapTable.LOCALES = Constants.LOCALES;
  BootstrapTable.COLUMN_DEFAULTS = Constants.COLUMN_DEFAULTS;
  BootstrapTable.METHODS = Constants.METHODS;
  BootstrapTable.EVENTS = Constants.EVENTS; // BOOTSTRAP TABLE PLUGIN DEFINITION
  // =======================

  \$__default['default'].BootstrapTable = BootstrapTable;

  \$__default['default'].fn.bootstrapTable = function (option) {
    for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key5 = 1; _key5 < _len2; _key5++) {
      args[_key5 - 1] = arguments[_key5];
    }

    var value;
    this.each(function (i, el) {
      var data = \$__default['default'](el).data('bootstrap.table');
      var options = \$__default['default'].extend({}, BootstrapTable.DEFAULTS, \$__default['default'](el).data(), _typeof(option) === 'object' && option);

      if (typeof option === 'string') {
        var _data2;

        if (!Constants.METHODS.includes(option)) {
          throw new Error(\"Unknown method: \".concat(option));
        }

        if (!data) {
          return;
        }

        value = (_data2 = data)[option].apply(_data2, args);

        if (option === 'destroy') {
          \$__default['default'](el).removeData('bootstrap.table');
        }
      }

      if (!data) {
        data = new \$__default['default'].BootstrapTable(el, options);
        \$__default['default'](el).data('bootstrap.table', data);
        data.init();
      }
    });
    return typeof value === 'undefined' ? this : value;
  };

  \$__default['default'].fn.bootstrapTable.Constructor = BootstrapTable;
  \$__default['default'].fn.bootstrapTable.theme = Constants.THEME;
  \$__default['default'].fn.bootstrapTable.VERSION = Constants.VERSION;
  \$__default['default'].fn.bootstrapTable.defaults = BootstrapTable.DEFAULTS;
  \$__default['default'].fn.bootstrapTable.columnDefaults = BootstrapTable.COLUMN_DEFAULTS;
  \$__default['default'].fn.bootstrapTable.events = BootstrapTable.EVENTS;
  \$__default['default'].fn.bootstrapTable.locales = BootstrapTable.LOCALES;
  \$__default['default'].fn.bootstrapTable.methods = BootstrapTable.METHODS;
  \$__default['default'].fn.bootstrapTable.utils = Utils; // BOOTSTRAP TABLE INIT
  // =======================

  \$__default['default'](function () {
    \$__default['default']('[data-toggle=\"table\"]').bootstrapTable();
  });

  return BootstrapTable;

})));


/***/ }),

/***/ \"./node_modules/core-js/internals/array-fill.js\":
/*!******************************************************!*\\
  !*** ./node_modules/core-js/internals/array-fill.js ***!
  \\******************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var toObject = __webpack_require__(/*! ../internals/to-object */ \"./node_modules/core-js/internals/to-object.js\");
var toAbsoluteIndex = __webpack_require__(/*! ../internals/to-absolute-index */ \"./node_modules/core-js/internals/to-absolute-index.js\");
var toLength = __webpack_require__(/*! ../internals/to-length */ \"./node_modules/core-js/internals/to-length.js\");

// `Array.prototype.fill` method implementation
// https://tc39.es/ecma262/#sec-array.prototype.fill
module.exports = function fill(value /* , start = 0, end = @length */) {
  var O = toObject(this);
  var length = toLength(O.length);
  var argumentsLength = arguments.length;
  var index = toAbsoluteIndex(argumentsLength > 1 ? arguments[1] : undefined, length);
  var end = argumentsLength > 2 ? arguments[2] : undefined;
  var endPos = end === undefined ? length : toAbsoluteIndex(end, length);
  while (endPos > index) O[index++] = value;
  return O;
};


/***/ }),

/***/ \"./node_modules/core-js/internals/array-reduce.js\":
/*!********************************************************!*\\
  !*** ./node_modules/core-js/internals/array-reduce.js ***!
  \\********************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

var aFunction = __webpack_require__(/*! ../internals/a-function */ \"./node_modules/core-js/internals/a-function.js\");
var toObject = __webpack_require__(/*! ../internals/to-object */ \"./node_modules/core-js/internals/to-object.js\");
var IndexedObject = __webpack_require__(/*! ../internals/indexed-object */ \"./node_modules/core-js/internals/indexed-object.js\");
var toLength = __webpack_require__(/*! ../internals/to-length */ \"./node_modules/core-js/internals/to-length.js\");

// `Array.prototype.{ reduce, reduceRight }` methods implementation
var createMethod = function (IS_RIGHT) {
  return function (that, callbackfn, argumentsLength, memo) {
    aFunction(callbackfn);
    var O = toObject(that);
    var self = IndexedObject(O);
    var length = toLength(O.length);
    var index = IS_RIGHT ? length - 1 : 0;
    var i = IS_RIGHT ? -1 : 1;
    if (argumentsLength < 2) while (true) {
      if (index in self) {
        memo = self[index];
        index += i;
        break;
      }
      index += i;
      if (IS_RIGHT ? index < 0 : length <= index) {
        throw TypeError('Reduce of empty array with no initial value');
      }
    }
    for (;IS_RIGHT ? index >= 0 : length > index; index += i) if (index in self) {
      memo = callbackfn(memo, self[index], index, O);
    }
    return memo;
  };
};

module.exports = {
  // `Array.prototype.reduce` method
  // https://tc39.es/ecma262/#sec-array.prototype.reduce
  left: createMethod(false),
  // `Array.prototype.reduceRight` method
  // https://tc39.es/ecma262/#sec-array.prototype.reduceright
  right: createMethod(true)
};


/***/ }),

/***/ \"./node_modules/core-js/internals/engine-is-node.js\":
/*!**********************************************************!*\\
  !*** ./node_modules/core-js/internals/engine-is-node.js ***!
  \\**********************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

var classof = __webpack_require__(/*! ../internals/classof-raw */ \"./node_modules/core-js/internals/classof-raw.js\");
var global = __webpack_require__(/*! ../internals/global */ \"./node_modules/core-js/internals/global.js\");

module.exports = classof(global.process) == 'process';


/***/ }),

/***/ \"./node_modules/core-js/internals/inherit-if-required.js\":
/*!***************************************************************!*\\
  !*** ./node_modules/core-js/internals/inherit-if-required.js ***!
  \\***************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

var isObject = __webpack_require__(/*! ../internals/is-object */ \"./node_modules/core-js/internals/is-object.js\");
var setPrototypeOf = __webpack_require__(/*! ../internals/object-set-prototype-of */ \"./node_modules/core-js/internals/object-set-prototype-of.js\");

// makes subclassing work correct for wrapped built-ins
module.exports = function (\$this, dummy, Wrapper) {
  var NewTarget, NewTargetPrototype;
  if (
    // it can work only with native `setPrototypeOf`
    setPrototypeOf &&
    // we haven't completely correct pre-ES6 way for getting `new.target`, so use this
    typeof (NewTarget = dummy.constructor) == 'function' &&
    NewTarget !== Wrapper &&
    isObject(NewTargetPrototype = NewTarget.prototype) &&
    NewTargetPrototype !== Wrapper.prototype
  ) setPrototypeOf(\$this, NewTargetPrototype);
  return \$this;
};


/***/ }),

/***/ \"./node_modules/core-js/internals/number-parse-float.js\":
/*!**************************************************************!*\\
  !*** ./node_modules/core-js/internals/number-parse-float.js ***!
  \\**************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

var global = __webpack_require__(/*! ../internals/global */ \"./node_modules/core-js/internals/global.js\");
var trim = __webpack_require__(/*! ../internals/string-trim */ \"./node_modules/core-js/internals/string-trim.js\").trim;
var whitespaces = __webpack_require__(/*! ../internals/whitespaces */ \"./node_modules/core-js/internals/whitespaces.js\");

var \$parseFloat = global.parseFloat;
var FORCED = 1 / \$parseFloat(whitespaces + '-0') !== -Infinity;

// `parseFloat` method
// https://tc39.es/ecma262/#sec-parsefloat-string
module.exports = FORCED ? function parseFloat(string) {
  var trimmedString = trim(String(string));
  var result = \$parseFloat(trimmedString);
  return result === 0 && trimmedString.charAt(0) == '-' ? -0 : result;
} : \$parseFloat;


/***/ }),

/***/ \"./node_modules/core-js/internals/same-value.js\":
/*!******************************************************!*\\
  !*** ./node_modules/core-js/internals/same-value.js ***!
  \\******************************************************/
/***/ ((module) => {

// `SameValue` abstract operation
// https://tc39.es/ecma262/#sec-samevalue
// eslint-disable-next-line es/no-object-is -- safe
module.exports = Object.is || function is(x, y) {
  // eslint-disable-next-line no-self-compare -- NaN check
  return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y;
};


/***/ }),

/***/ \"./node_modules/core-js/internals/set-species.js\":
/*!*******************************************************!*\\
  !*** ./node_modules/core-js/internals/set-species.js ***!
  \\*******************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var getBuiltIn = __webpack_require__(/*! ../internals/get-built-in */ \"./node_modules/core-js/internals/get-built-in.js\");
var definePropertyModule = __webpack_require__(/*! ../internals/object-define-property */ \"./node_modules/core-js/internals/object-define-property.js\");
var wellKnownSymbol = __webpack_require__(/*! ../internals/well-known-symbol */ \"./node_modules/core-js/internals/well-known-symbol.js\");
var DESCRIPTORS = __webpack_require__(/*! ../internals/descriptors */ \"./node_modules/core-js/internals/descriptors.js\");

var SPECIES = wellKnownSymbol('species');

module.exports = function (CONSTRUCTOR_NAME) {
  var Constructor = getBuiltIn(CONSTRUCTOR_NAME);
  var defineProperty = definePropertyModule.f;

  if (DESCRIPTORS && Constructor && !Constructor[SPECIES]) {
    defineProperty(Constructor, SPECIES, {
      configurable: true,
      get: function () { return this; }
    });
  }
};


/***/ }),

/***/ \"./node_modules/core-js/internals/string-repeat.js\":
/*!*********************************************************!*\\
  !*** ./node_modules/core-js/internals/string-repeat.js ***!
  \\*********************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var toInteger = __webpack_require__(/*! ../internals/to-integer */ \"./node_modules/core-js/internals/to-integer.js\");
var requireObjectCoercible = __webpack_require__(/*! ../internals/require-object-coercible */ \"./node_modules/core-js/internals/require-object-coercible.js\");

// `String.prototype.repeat` method implementation
// https://tc39.es/ecma262/#sec-string.prototype.repeat
module.exports = function repeat(count) {
  var str = String(requireObjectCoercible(this));
  var result = '';
  var n = toInteger(count);
  if (n < 0 || n == Infinity) throw RangeError('Wrong number of repetitions');
  for (;n > 0; (n >>>= 1) && (str += str)) if (n & 1) result += str;
  return result;
};


/***/ }),

/***/ \"./node_modules/core-js/internals/this-number-value.js\":
/*!*************************************************************!*\\
  !*** ./node_modules/core-js/internals/this-number-value.js ***!
  \\*************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

var classof = __webpack_require__(/*! ../internals/classof-raw */ \"./node_modules/core-js/internals/classof-raw.js\");

// `thisNumberValue` abstract operation
// https://tc39.es/ecma262/#sec-thisnumbervalue
module.exports = function (value) {
  if (typeof value != 'number' && classof(value) != 'Number') {
    throw TypeError('Incorrect invocation');
  }
  return +value;
};


/***/ }),

/***/ \"./node_modules/core-js/modules/es.array.fill.js\":
/*!*******************************************************!*\\
  !*** ./node_modules/core-js/modules/es.array.fill.js ***!
  \\*******************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var fill = __webpack_require__(/*! ../internals/array-fill */ \"./node_modules/core-js/internals/array-fill.js\");
var addToUnscopables = __webpack_require__(/*! ../internals/add-to-unscopables */ \"./node_modules/core-js/internals/add-to-unscopables.js\");

// `Array.prototype.fill` method
// https://tc39.es/ecma262/#sec-array.prototype.fill
\$({ target: 'Array', proto: true }, {
  fill: fill
});

// https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
addToUnscopables('fill');


/***/ }),

/***/ \"./node_modules/core-js/modules/es.array.find.js\":
/*!*******************************************************!*\\
  !*** ./node_modules/core-js/modules/es.array.find.js ***!
  \\*******************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var \$find = __webpack_require__(/*! ../internals/array-iteration */ \"./node_modules/core-js/internals/array-iteration.js\").find;
var addToUnscopables = __webpack_require__(/*! ../internals/add-to-unscopables */ \"./node_modules/core-js/internals/add-to-unscopables.js\");

var FIND = 'find';
var SKIPS_HOLES = true;

// Shouldn't skip holes
if (FIND in []) Array(1)[FIND](function () { SKIPS_HOLES = false; });

// `Array.prototype.find` method
// https://tc39.es/ecma262/#sec-array.prototype.find
\$({ target: 'Array', proto: true, forced: SKIPS_HOLES }, {
  find: function find(callbackfn /* , that = undefined */) {
    return \$find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
  }
});

// https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
addToUnscopables(FIND);


/***/ }),

/***/ \"./node_modules/core-js/modules/es.array.includes.js\":
/*!***********************************************************!*\\
  !*** ./node_modules/core-js/modules/es.array.includes.js ***!
  \\***********************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var \$includes = __webpack_require__(/*! ../internals/array-includes */ \"./node_modules/core-js/internals/array-includes.js\").includes;
var addToUnscopables = __webpack_require__(/*! ../internals/add-to-unscopables */ \"./node_modules/core-js/internals/add-to-unscopables.js\");

// `Array.prototype.includes` method
// https://tc39.es/ecma262/#sec-array.prototype.includes
\$({ target: 'Array', proto: true }, {
  includes: function includes(el /* , fromIndex = 0 */) {
    return \$includes(this, el, arguments.length > 1 ? arguments[1] : undefined);
  }
});

// https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
addToUnscopables('includes');


/***/ }),

/***/ \"./node_modules/core-js/modules/es.array.index-of.js\":
/*!***********************************************************!*\\
  !*** ./node_modules/core-js/modules/es.array.index-of.js ***!
  \\***********************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

/* eslint-disable es/no-array-prototype-indexof -- required for testing */
var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var \$indexOf = __webpack_require__(/*! ../internals/array-includes */ \"./node_modules/core-js/internals/array-includes.js\").indexOf;
var arrayMethodIsStrict = __webpack_require__(/*! ../internals/array-method-is-strict */ \"./node_modules/core-js/internals/array-method-is-strict.js\");

var nativeIndexOf = [].indexOf;

var NEGATIVE_ZERO = !!nativeIndexOf && 1 / [1].indexOf(1, -0) < 0;
var STRICT_METHOD = arrayMethodIsStrict('indexOf');

// `Array.prototype.indexOf` method
// https://tc39.es/ecma262/#sec-array.prototype.indexof
\$({ target: 'Array', proto: true, forced: NEGATIVE_ZERO || !STRICT_METHOD }, {
  indexOf: function indexOf(searchElement /* , fromIndex = 0 */) {
    return NEGATIVE_ZERO
      // convert -0 to +0
      ? nativeIndexOf.apply(this, arguments) || 0
      : \$indexOf(this, searchElement, arguments.length > 1 ? arguments[1] : undefined);
  }
});


/***/ }),

/***/ \"./node_modules/core-js/modules/es.array.is-array.js\":
/*!***********************************************************!*\\
  !*** ./node_modules/core-js/modules/es.array.is-array.js ***!
  \\***********************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var isArray = __webpack_require__(/*! ../internals/is-array */ \"./node_modules/core-js/internals/is-array.js\");

// `Array.isArray` method
// https://tc39.es/ecma262/#sec-array.isarray
\$({ target: 'Array', stat: true }, {
  isArray: isArray
});


/***/ }),

/***/ \"./node_modules/core-js/modules/es.array.reduce.js\":
/*!*********************************************************!*\\
  !*** ./node_modules/core-js/modules/es.array.reduce.js ***!
  \\*********************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var \$reduce = __webpack_require__(/*! ../internals/array-reduce */ \"./node_modules/core-js/internals/array-reduce.js\").left;
var arrayMethodIsStrict = __webpack_require__(/*! ../internals/array-method-is-strict */ \"./node_modules/core-js/internals/array-method-is-strict.js\");
var CHROME_VERSION = __webpack_require__(/*! ../internals/engine-v8-version */ \"./node_modules/core-js/internals/engine-v8-version.js\");
var IS_NODE = __webpack_require__(/*! ../internals/engine-is-node */ \"./node_modules/core-js/internals/engine-is-node.js\");

var STRICT_METHOD = arrayMethodIsStrict('reduce');
// Chrome 80-82 has a critical bug
// https://bugs.chromium.org/p/chromium/issues/detail?id=1049982
var CHROME_BUG = !IS_NODE && CHROME_VERSION > 79 && CHROME_VERSION < 83;

// `Array.prototype.reduce` method
// https://tc39.es/ecma262/#sec-array.prototype.reduce
\$({ target: 'Array', proto: true, forced: !STRICT_METHOD || CHROME_BUG }, {
  reduce: function reduce(callbackfn /* , initialValue */) {
    return \$reduce(this, callbackfn, arguments.length, arguments.length > 1 ? arguments[1] : undefined);
  }
});


/***/ }),

/***/ \"./node_modules/core-js/modules/es.array.some.js\":
/*!*******************************************************!*\\
  !*** ./node_modules/core-js/modules/es.array.some.js ***!
  \\*******************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var \$some = __webpack_require__(/*! ../internals/array-iteration */ \"./node_modules/core-js/internals/array-iteration.js\").some;
var arrayMethodIsStrict = __webpack_require__(/*! ../internals/array-method-is-strict */ \"./node_modules/core-js/internals/array-method-is-strict.js\");

var STRICT_METHOD = arrayMethodIsStrict('some');

// `Array.prototype.some` method
// https://tc39.es/ecma262/#sec-array.prototype.some
\$({ target: 'Array', proto: true, forced: !STRICT_METHOD }, {
  some: function some(callbackfn /* , thisArg */) {
    return \$some(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
  }
});


/***/ }),

/***/ \"./node_modules/core-js/modules/es.array.splice.js\":
/*!*********************************************************!*\\
  !*** ./node_modules/core-js/modules/es.array.splice.js ***!
  \\*********************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var toAbsoluteIndex = __webpack_require__(/*! ../internals/to-absolute-index */ \"./node_modules/core-js/internals/to-absolute-index.js\");
var toInteger = __webpack_require__(/*! ../internals/to-integer */ \"./node_modules/core-js/internals/to-integer.js\");
var toLength = __webpack_require__(/*! ../internals/to-length */ \"./node_modules/core-js/internals/to-length.js\");
var toObject = __webpack_require__(/*! ../internals/to-object */ \"./node_modules/core-js/internals/to-object.js\");
var arraySpeciesCreate = __webpack_require__(/*! ../internals/array-species-create */ \"./node_modules/core-js/internals/array-species-create.js\");
var createProperty = __webpack_require__(/*! ../internals/create-property */ \"./node_modules/core-js/internals/create-property.js\");
var arrayMethodHasSpeciesSupport = __webpack_require__(/*! ../internals/array-method-has-species-support */ \"./node_modules/core-js/internals/array-method-has-species-support.js\");

var HAS_SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('splice');

var max = Math.max;
var min = Math.min;
var MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF;
var MAXIMUM_ALLOWED_LENGTH_EXCEEDED = 'Maximum allowed length exceeded';

// `Array.prototype.splice` method
// https://tc39.es/ecma262/#sec-array.prototype.splice
// with adding support of @@species
\$({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT }, {
  splice: function splice(start, deleteCount /* , ...items */) {
    var O = toObject(this);
    var len = toLength(O.length);
    var actualStart = toAbsoluteIndex(start, len);
    var argumentsLength = arguments.length;
    var insertCount, actualDeleteCount, A, k, from, to;
    if (argumentsLength === 0) {
      insertCount = actualDeleteCount = 0;
    } else if (argumentsLength === 1) {
      insertCount = 0;
      actualDeleteCount = len - actualStart;
    } else {
      insertCount = argumentsLength - 2;
      actualDeleteCount = min(max(toInteger(deleteCount), 0), len - actualStart);
    }
    if (len + insertCount - actualDeleteCount > MAX_SAFE_INTEGER) {
      throw TypeError(MAXIMUM_ALLOWED_LENGTH_EXCEEDED);
    }
    A = arraySpeciesCreate(O, actualDeleteCount);
    for (k = 0; k < actualDeleteCount; k++) {
      from = actualStart + k;
      if (from in O) createProperty(A, k, O[from]);
    }
    A.length = actualDeleteCount;
    if (insertCount < actualDeleteCount) {
      for (k = actualStart; k < len - actualDeleteCount; k++) {
        from = k + actualDeleteCount;
        to = k + insertCount;
        if (from in O) O[to] = O[from];
        else delete O[to];
      }
      for (k = len; k > len - actualDeleteCount + insertCount; k--) delete O[k - 1];
    } else if (insertCount > actualDeleteCount) {
      for (k = len - actualDeleteCount; k > actualStart; k--) {
        from = k + actualDeleteCount - 1;
        to = k + insertCount - 1;
        if (from in O) O[to] = O[from];
        else delete O[to];
      }
    }
    for (k = 0; k < insertCount; k++) {
      O[k + actualStart] = arguments[k + 2];
    }
    O.length = len - actualDeleteCount + insertCount;
    return A;
  }
});


/***/ }),

/***/ \"./node_modules/core-js/modules/es.function.bind.js\":
/*!**********************************************************!*\\
  !*** ./node_modules/core-js/modules/es.function.bind.js ***!
  \\**********************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var bind = __webpack_require__(/*! ../internals/function-bind */ \"./node_modules/core-js/internals/function-bind.js\");

// `Function.prototype.bind` method
// https://tc39.es/ecma262/#sec-function.prototype.bind
\$({ target: 'Function', proto: true }, {
  bind: bind
});


/***/ }),

/***/ \"./node_modules/core-js/modules/es.number.constructor.js\":
/*!***************************************************************!*\\
  !*** ./node_modules/core-js/modules/es.number.constructor.js ***!
  \\***************************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var DESCRIPTORS = __webpack_require__(/*! ../internals/descriptors */ \"./node_modules/core-js/internals/descriptors.js\");
var global = __webpack_require__(/*! ../internals/global */ \"./node_modules/core-js/internals/global.js\");
var isForced = __webpack_require__(/*! ../internals/is-forced */ \"./node_modules/core-js/internals/is-forced.js\");
var redefine = __webpack_require__(/*! ../internals/redefine */ \"./node_modules/core-js/internals/redefine.js\");
var has = __webpack_require__(/*! ../internals/has */ \"./node_modules/core-js/internals/has.js\");
var classof = __webpack_require__(/*! ../internals/classof-raw */ \"./node_modules/core-js/internals/classof-raw.js\");
var inheritIfRequired = __webpack_require__(/*! ../internals/inherit-if-required */ \"./node_modules/core-js/internals/inherit-if-required.js\");
var toPrimitive = __webpack_require__(/*! ../internals/to-primitive */ \"./node_modules/core-js/internals/to-primitive.js\");
var fails = __webpack_require__(/*! ../internals/fails */ \"./node_modules/core-js/internals/fails.js\");
var create = __webpack_require__(/*! ../internals/object-create */ \"./node_modules/core-js/internals/object-create.js\");
var getOwnPropertyNames = __webpack_require__(/*! ../internals/object-get-own-property-names */ \"./node_modules/core-js/internals/object-get-own-property-names.js\").f;
var getOwnPropertyDescriptor = __webpack_require__(/*! ../internals/object-get-own-property-descriptor */ \"./node_modules/core-js/internals/object-get-own-property-descriptor.js\").f;
var defineProperty = __webpack_require__(/*! ../internals/object-define-property */ \"./node_modules/core-js/internals/object-define-property.js\").f;
var trim = __webpack_require__(/*! ../internals/string-trim */ \"./node_modules/core-js/internals/string-trim.js\").trim;

var NUMBER = 'Number';
var NativeNumber = global[NUMBER];
var NumberPrototype = NativeNumber.prototype;

// Opera ~12 has broken Object#toString
var BROKEN_CLASSOF = classof(create(NumberPrototype)) == NUMBER;

// `ToNumber` abstract operation
// https://tc39.es/ecma262/#sec-tonumber
var toNumber = function (argument) {
  var it = toPrimitive(argument, false);
  var first, third, radix, maxCode, digits, length, index, code;
  if (typeof it == 'string' && it.length > 2) {
    it = trim(it);
    first = it.charCodeAt(0);
    if (first === 43 || first === 45) {
      third = it.charCodeAt(2);
      if (third === 88 || third === 120) return NaN; // Number('+0x1') should be NaN, old V8 fix
    } else if (first === 48) {
      switch (it.charCodeAt(1)) {
        case 66: case 98: radix = 2; maxCode = 49; break; // fast equal of /^0b[01]+\$/i
        case 79: case 111: radix = 8; maxCode = 55; break; // fast equal of /^0o[0-7]+\$/i
        default: return +it;
      }
      digits = it.slice(2);
      length = digits.length;
      for (index = 0; index < length; index++) {
        code = digits.charCodeAt(index);
        // parseInt parses a string to a first unavailable symbol
        // but ToNumber should return NaN if a string contains unavailable symbols
        if (code < 48 || code > maxCode) return NaN;
      } return parseInt(digits, radix);
    }
  } return +it;
};

// `Number` constructor
// https://tc39.es/ecma262/#sec-number-constructor
if (isForced(NUMBER, !NativeNumber(' 0o1') || !NativeNumber('0b1') || NativeNumber('+0x1'))) {
  var NumberWrapper = function Number(value) {
    var it = arguments.length < 1 ? 0 : value;
    var dummy = this;
    return dummy instanceof NumberWrapper
      // check on 1..constructor(foo) case
      && (BROKEN_CLASSOF ? fails(function () { NumberPrototype.valueOf.call(dummy); }) : classof(dummy) != NUMBER)
        ? inheritIfRequired(new NativeNumber(toNumber(it)), dummy, NumberWrapper) : toNumber(it);
  };
  for (var keys = DESCRIPTORS ? getOwnPropertyNames(NativeNumber) : (
    // ES3:
    'MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,' +
    // ES2015 (in case, if modules with ES2015 Number statics required before):
    'EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,' +
    'MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger,' +
    // ESNext
    'fromString,range'
  ).split(','), j = 0, key; keys.length > j; j++) {
    if (has(NativeNumber, key = keys[j]) && !has(NumberWrapper, key)) {
      defineProperty(NumberWrapper, key, getOwnPropertyDescriptor(NativeNumber, key));
    }
  }
  NumberWrapper.prototype = NumberPrototype;
  NumberPrototype.constructor = NumberWrapper;
  redefine(global, NUMBER, NumberWrapper);
}


/***/ }),

/***/ \"./node_modules/core-js/modules/es.number.to-fixed.js\":
/*!************************************************************!*\\
  !*** ./node_modules/core-js/modules/es.number.to-fixed.js ***!
  \\************************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var toInteger = __webpack_require__(/*! ../internals/to-integer */ \"./node_modules/core-js/internals/to-integer.js\");
var thisNumberValue = __webpack_require__(/*! ../internals/this-number-value */ \"./node_modules/core-js/internals/this-number-value.js\");
var repeat = __webpack_require__(/*! ../internals/string-repeat */ \"./node_modules/core-js/internals/string-repeat.js\");
var fails = __webpack_require__(/*! ../internals/fails */ \"./node_modules/core-js/internals/fails.js\");

var nativeToFixed = 1.0.toFixed;
var floor = Math.floor;

var pow = function (x, n, acc) {
  return n === 0 ? acc : n % 2 === 1 ? pow(x, n - 1, acc * x) : pow(x * x, n / 2, acc);
};

var log = function (x) {
  var n = 0;
  var x2 = x;
  while (x2 >= 4096) {
    n += 12;
    x2 /= 4096;
  }
  while (x2 >= 2) {
    n += 1;
    x2 /= 2;
  } return n;
};

var multiply = function (data, n, c) {
  var index = -1;
  var c2 = c;
  while (++index < 6) {
    c2 += n * data[index];
    data[index] = c2 % 1e7;
    c2 = floor(c2 / 1e7);
  }
};

var divide = function (data, n) {
  var index = 6;
  var c = 0;
  while (--index >= 0) {
    c += data[index];
    data[index] = floor(c / n);
    c = (c % n) * 1e7;
  }
};

var dataToString = function (data) {
  var index = 6;
  var s = '';
  while (--index >= 0) {
    if (s !== '' || index === 0 || data[index] !== 0) {
      var t = String(data[index]);
      s = s === '' ? t : s + repeat.call('0', 7 - t.length) + t;
    }
  } return s;
};

var FORCED = nativeToFixed && (
  0.00008.toFixed(3) !== '0.000' ||
  0.9.toFixed(0) !== '1' ||
  1.255.toFixed(2) !== '1.25' ||
  1000000000000000128.0.toFixed(0) !== '1000000000000000128'
) || !fails(function () {
  // V8 ~ Android 4.3-
  nativeToFixed.call({});
});

// `Number.prototype.toFixed` method
// https://tc39.es/ecma262/#sec-number.prototype.tofixed
\$({ target: 'Number', proto: true, forced: FORCED }, {
  toFixed: function toFixed(fractionDigits) {
    var number = thisNumberValue(this);
    var fractDigits = toInteger(fractionDigits);
    var data = [0, 0, 0, 0, 0, 0];
    var sign = '';
    var result = '0';
    var e, z, j, k;

    if (fractDigits < 0 || fractDigits > 20) throw RangeError('Incorrect fraction digits');
    // eslint-disable-next-line no-self-compare -- NaN check
    if (number != number) return 'NaN';
    if (number <= -1e21 || number >= 1e21) return String(number);
    if (number < 0) {
      sign = '-';
      number = -number;
    }
    if (number > 1e-21) {
      e = log(number * pow(2, 69, 1)) - 69;
      z = e < 0 ? number * pow(2, -e, 1) : number / pow(2, e, 1);
      z *= 0x10000000000000;
      e = 52 - e;
      if (e > 0) {
        multiply(data, 0, z);
        j = fractDigits;
        while (j >= 7) {
          multiply(data, 1e7, 0);
          j -= 7;
        }
        multiply(data, pow(10, j, 1), 0);
        j = e - 1;
        while (j >= 23) {
          divide(data, 1 << 23);
          j -= 23;
        }
        divide(data, 1 << j);
        multiply(data, 1, 1);
        divide(data, 2);
        result = dataToString(data);
      } else {
        multiply(data, 0, z);
        multiply(data, 1 << -e, 0);
        result = dataToString(data) + repeat.call('0', fractDigits);
      }
    }
    if (fractDigits > 0) {
      k = result.length;
      result = sign + (k <= fractDigits
        ? '0.' + repeat.call('0', fractDigits - k) + result
        : result.slice(0, k - fractDigits) + '.' + result.slice(k - fractDigits));
    } else {
      result = sign + result;
    } return result;
  }
});


/***/ }),

/***/ \"./node_modules/core-js/modules/es.parse-float.js\":
/*!********************************************************!*\\
  !*** ./node_modules/core-js/modules/es.parse-float.js ***!
  \\********************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var parseFloatImplementation = __webpack_require__(/*! ../internals/number-parse-float */ \"./node_modules/core-js/internals/number-parse-float.js\");

// `parseFloat` method
// https://tc39.es/ecma262/#sec-parsefloat-string
\$({ global: true, forced: parseFloat != parseFloatImplementation }, {
  parseFloat: parseFloatImplementation
});


/***/ }),

/***/ \"./node_modules/core-js/modules/es.regexp.constructor.js\":
/*!***************************************************************!*\\
  !*** ./node_modules/core-js/modules/es.regexp.constructor.js ***!
  \\***************************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

var DESCRIPTORS = __webpack_require__(/*! ../internals/descriptors */ \"./node_modules/core-js/internals/descriptors.js\");
var global = __webpack_require__(/*! ../internals/global */ \"./node_modules/core-js/internals/global.js\");
var isForced = __webpack_require__(/*! ../internals/is-forced */ \"./node_modules/core-js/internals/is-forced.js\");
var inheritIfRequired = __webpack_require__(/*! ../internals/inherit-if-required */ \"./node_modules/core-js/internals/inherit-if-required.js\");
var defineProperty = __webpack_require__(/*! ../internals/object-define-property */ \"./node_modules/core-js/internals/object-define-property.js\").f;
var getOwnPropertyNames = __webpack_require__(/*! ../internals/object-get-own-property-names */ \"./node_modules/core-js/internals/object-get-own-property-names.js\").f;
var isRegExp = __webpack_require__(/*! ../internals/is-regexp */ \"./node_modules/core-js/internals/is-regexp.js\");
var getFlags = __webpack_require__(/*! ../internals/regexp-flags */ \"./node_modules/core-js/internals/regexp-flags.js\");
var stickyHelpers = __webpack_require__(/*! ../internals/regexp-sticky-helpers */ \"./node_modules/core-js/internals/regexp-sticky-helpers.js\");
var redefine = __webpack_require__(/*! ../internals/redefine */ \"./node_modules/core-js/internals/redefine.js\");
var fails = __webpack_require__(/*! ../internals/fails */ \"./node_modules/core-js/internals/fails.js\");
var enforceInternalState = __webpack_require__(/*! ../internals/internal-state */ \"./node_modules/core-js/internals/internal-state.js\").enforce;
var setSpecies = __webpack_require__(/*! ../internals/set-species */ \"./node_modules/core-js/internals/set-species.js\");
var wellKnownSymbol = __webpack_require__(/*! ../internals/well-known-symbol */ \"./node_modules/core-js/internals/well-known-symbol.js\");

var MATCH = wellKnownSymbol('match');
var NativeRegExp = global.RegExp;
var RegExpPrototype = NativeRegExp.prototype;
var re1 = /a/g;
var re2 = /a/g;

// \"new\" should create a new object, old webkit bug
var CORRECT_NEW = new NativeRegExp(re1) !== re1;

var UNSUPPORTED_Y = stickyHelpers.UNSUPPORTED_Y;

var FORCED = DESCRIPTORS && isForced('RegExp', (!CORRECT_NEW || UNSUPPORTED_Y || fails(function () {
  re2[MATCH] = false;
  // RegExp constructor can alter flags and IsRegExp works correct with @@match
  return NativeRegExp(re1) != re1 || NativeRegExp(re2) == re2 || NativeRegExp(re1, 'i') != '/a/i';
})));

// `RegExp` constructor
// https://tc39.es/ecma262/#sec-regexp-constructor
if (FORCED) {
  var RegExpWrapper = function RegExp(pattern, flags) {
    var thisIsRegExp = this instanceof RegExpWrapper;
    var patternIsRegExp = isRegExp(pattern);
    var flagsAreUndefined = flags === undefined;
    var sticky;

    if (!thisIsRegExp && patternIsRegExp && pattern.constructor === RegExpWrapper && flagsAreUndefined) {
      return pattern;
    }

    if (CORRECT_NEW) {
      if (patternIsRegExp && !flagsAreUndefined) pattern = pattern.source;
    } else if (pattern instanceof RegExpWrapper) {
      if (flagsAreUndefined) flags = getFlags.call(pattern);
      pattern = pattern.source;
    }

    if (UNSUPPORTED_Y) {
      sticky = !!flags && flags.indexOf('y') > -1;
      if (sticky) flags = flags.replace(/y/g, '');
    }

    var result = inheritIfRequired(
      CORRECT_NEW ? new NativeRegExp(pattern, flags) : NativeRegExp(pattern, flags),
      thisIsRegExp ? this : RegExpPrototype,
      RegExpWrapper
    );

    if (UNSUPPORTED_Y && sticky) {
      var state = enforceInternalState(result);
      state.sticky = true;
    }

    return result;
  };
  var proxy = function (key) {
    key in RegExpWrapper || defineProperty(RegExpWrapper, key, {
      configurable: true,
      get: function () { return NativeRegExp[key]; },
      set: function (it) { NativeRegExp[key] = it; }
    });
  };
  var keys = getOwnPropertyNames(NativeRegExp);
  var index = 0;
  while (keys.length > index) proxy(keys[index++]);
  RegExpPrototype.constructor = RegExpWrapper;
  RegExpWrapper.prototype = RegExpPrototype;
  redefine(global, 'RegExp', RegExpWrapper);
}

// https://tc39.es/ecma262/#sec-get-regexp-@@species
setSpecies('RegExp');


/***/ }),

/***/ \"./node_modules/core-js/modules/es.regexp.to-string.js\":
/*!*************************************************************!*\\
  !*** ./node_modules/core-js/modules/es.regexp.to-string.js ***!
  \\*************************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var redefine = __webpack_require__(/*! ../internals/redefine */ \"./node_modules/core-js/internals/redefine.js\");
var anObject = __webpack_require__(/*! ../internals/an-object */ \"./node_modules/core-js/internals/an-object.js\");
var fails = __webpack_require__(/*! ../internals/fails */ \"./node_modules/core-js/internals/fails.js\");
var flags = __webpack_require__(/*! ../internals/regexp-flags */ \"./node_modules/core-js/internals/regexp-flags.js\");

var TO_STRING = 'toString';
var RegExpPrototype = RegExp.prototype;
var nativeToString = RegExpPrototype[TO_STRING];

var NOT_GENERIC = fails(function () { return nativeToString.call({ source: 'a', flags: 'b' }) != '/a/b'; });
// FF44- RegExp#toString has a wrong name
var INCORRECT_NAME = nativeToString.name != TO_STRING;

// `RegExp.prototype.toString` method
// https://tc39.es/ecma262/#sec-regexp.prototype.tostring
if (NOT_GENERIC || INCORRECT_NAME) {
  redefine(RegExp.prototype, TO_STRING, function toString() {
    var R = anObject(this);
    var p = String(R.source);
    var rf = R.flags;
    var f = String(rf === undefined && R instanceof RegExp && !('flags' in RegExpPrototype) ? flags.call(R) : rf);
    return '/' + p + '/' + f;
  }, { unsafe: true });
}


/***/ }),

/***/ \"./node_modules/core-js/modules/es.string.search.js\":
/*!**********************************************************!*\\
  !*** ./node_modules/core-js/modules/es.string.search.js ***!
  \\**********************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

\"use strict\";

var fixRegExpWellKnownSymbolLogic = __webpack_require__(/*! ../internals/fix-regexp-well-known-symbol-logic */ \"./node_modules/core-js/internals/fix-regexp-well-known-symbol-logic.js\");
var anObject = __webpack_require__(/*! ../internals/an-object */ \"./node_modules/core-js/internals/an-object.js\");
var requireObjectCoercible = __webpack_require__(/*! ../internals/require-object-coercible */ \"./node_modules/core-js/internals/require-object-coercible.js\");
var sameValue = __webpack_require__(/*! ../internals/same-value */ \"./node_modules/core-js/internals/same-value.js\");
var regExpExec = __webpack_require__(/*! ../internals/regexp-exec-abstract */ \"./node_modules/core-js/internals/regexp-exec-abstract.js\");

// @@search logic
fixRegExpWellKnownSymbolLogic('search', 1, function (SEARCH, nativeSearch, maybeCallNative) {
  return [
    // `String.prototype.search` method
    // https://tc39.es/ecma262/#sec-string.prototype.search
    function search(regexp) {
      var O = requireObjectCoercible(this);
      var searcher = regexp == undefined ? undefined : regexp[SEARCH];
      return searcher !== undefined ? searcher.call(regexp, O) : new RegExp(regexp)[SEARCH](String(O));
    },
    // `RegExp.prototype[@@search]` method
    // https://tc39.es/ecma262/#sec-regexp.prototype-@@search
    function (regexp) {
      var res = maybeCallNative(nativeSearch, regexp, this);
      if (res.done) return res.value;

      var rx = anObject(regexp);
      var S = String(this);

      var previousLastIndex = rx.lastIndex;
      if (!sameValue(previousLastIndex, 0)) rx.lastIndex = 0;
      var result = regExpExec(rx, S);
      if (!sameValue(rx.lastIndex, previousLastIndex)) rx.lastIndex = previousLastIndex;
      return result === null ? -1 : result.index;
    }
  ];
});


/***/ }),

/***/ \"./node_modules/core-js/modules/web.timers.js\":
/*!****************************************************!*\\
  !*** ./node_modules/core-js/modules/web.timers.js ***!
  \\****************************************************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

var \$ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");
var global = __webpack_require__(/*! ../internals/global */ \"./node_modules/core-js/internals/global.js\");
var userAgent = __webpack_require__(/*! ../internals/engine-user-agent */ \"./node_modules/core-js/internals/engine-user-agent.js\");

var slice = [].slice;
var MSIE = /MSIE .\\./.test(userAgent); // <- dirty ie9- check

var wrap = function (scheduler) {
  return function (handler, timeout /* , ...arguments */) {
    var boundArgs = arguments.length > 2;
    var args = boundArgs ? slice.call(arguments, 2) : undefined;
    return scheduler(boundArgs ? function () {
      // eslint-disable-next-line no-new-func -- spec requirement
      (typeof handler == 'function' ? handler : Function(handler)).apply(this, args);
    } : handler, timeout);
  };
};

// ie9- setTimeout & setInterval additional parameters fix
// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers
\$({ global: true, bind: true, forced: MSIE }, {
  // `setTimeout` method
  // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-settimeout
  setTimeout: wrap(global.setTimeout),
  // `setInterval` method
  // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-setinterval
  setInterval: wrap(global.setInterval)
});


/***/ }),

/***/ \"./node_modules/leaflet/dist/leaflet-src.js\":
/*!**************************************************!*\\
  !*** ./node_modules/leaflet/dist/leaflet-src.js ***!
  \\**************************************************/
/***/ (function(__unused_webpack_module, exports) {

/* @preserve
 * Leaflet 1.9.4, a JS library for interactive maps. https://leafletjs.com
 * (c) 2010-2023 Vladimir Agafonkin, (c) 2010-2011 CloudMade
 */

(function (global, factory) {
   true ? factory(exports) :
  0;
})(this, (function (exports) { 'use strict';

  var version = \"1.9.4\";

  /*
   * @namespace Util
   *
   * Various utility functions, used by Leaflet internally.
   */

  // @function extend(dest: Object, src?: Object): Object
  // Merges the properties of the `src` object (or multiple objects) into `dest` object and returns the latter. Has an `L.extend` shortcut.
  function extend(dest) {
  \tvar i, j, len, src;

  \tfor (j = 1, len = arguments.length; j < len; j++) {
  \t\tsrc = arguments[j];
  \t\tfor (i in src) {
  \t\t\tdest[i] = src[i];
  \t\t}
  \t}
  \treturn dest;
  }

  // @function create(proto: Object, properties?: Object): Object
  // Compatibility polyfill for [Object.create](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/create)
  var create\$2 = Object.create || (function () {
  \tfunction F() {}
  \treturn function (proto) {
  \t\tF.prototype = proto;
  \t\treturn new F();
  \t};
  })();

  // @function bind(fn: Function, …): Function
  // Returns a new function bound to the arguments passed, like [Function.prototype.bind](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Function/bind).
  // Has a `L.bind()` shortcut.
  function bind(fn, obj) {
  \tvar slice = Array.prototype.slice;

  \tif (fn.bind) {
  \t\treturn fn.bind.apply(fn, slice.call(arguments, 1));
  \t}

  \tvar args = slice.call(arguments, 2);

  \treturn function () {
  \t\treturn fn.apply(obj, args.length ? args.concat(slice.call(arguments)) : arguments);
  \t};
  }

  // @property lastId: Number
  // Last unique ID used by [`stamp()`](#util-stamp)
  var lastId = 0;

  // @function stamp(obj: Object): Number
  // Returns the unique ID of an object, assigning it one if it doesn't have it.
  function stamp(obj) {
  \tif (!('_leaflet_id' in obj)) {
  \t\tobj['_leaflet_id'] = ++lastId;
  \t}
  \treturn obj._leaflet_id;
  }

  // @function throttle(fn: Function, time: Number, context: Object): Function
  // Returns a function which executes function `fn` with the given scope `context`
  // (so that the `this` keyword refers to `context` inside `fn`'s code). The function
  // `fn` will be called no more than one time per given amount of `time`. The arguments
  // received by the bound function will be any arguments passed when binding the
  // function, followed by any arguments passed when invoking the bound function.
  // Has an `L.throttle` shortcut.
  function throttle(fn, time, context) {
  \tvar lock, args, wrapperFn, later;

  \tlater = function () {
  \t\t// reset lock and call if queued
  \t\tlock = false;
  \t\tif (args) {
  \t\t\twrapperFn.apply(context, args);
  \t\t\targs = false;
  \t\t}
  \t};

  \twrapperFn = function () {
  \t\tif (lock) {
  \t\t\t// called too soon, queue to call later
  \t\t\targs = arguments;

  \t\t} else {
  \t\t\t// call and lock until later
  \t\t\tfn.apply(context, arguments);
  \t\t\tsetTimeout(later, time);
  \t\t\tlock = true;
  \t\t}
  \t};

  \treturn wrapperFn;
  }

  // @function wrapNum(num: Number, range: Number[], includeMax?: Boolean): Number
  // Returns the number `num` modulo `range` in such a way so it lies within
  // `range[0]` and `range[1]`. The returned value will be always smaller than
  // `range[1]` unless `includeMax` is set to `true`.
  function wrapNum(x, range, includeMax) {
  \tvar max = range[1],
  \t    min = range[0],
  \t    d = max - min;
  \treturn x === max && includeMax ? x : ((x - min) % d + d) % d + min;
  }

  // @function falseFn(): Function
  // Returns a function which always returns `false`.
  function falseFn() { return false; }

  // @function formatNum(num: Number, precision?: Number|false): Number
  // Returns the number `num` rounded with specified `precision`.
  // The default `precision` value is 6 decimal places.
  // `false` can be passed to skip any processing (can be useful to avoid round-off errors).
  function formatNum(num, precision) {
  \tif (precision === false) { return num; }
  \tvar pow = Math.pow(10, precision === undefined ? 6 : precision);
  \treturn Math.round(num * pow) / pow;
  }

  // @function trim(str: String): String
  // Compatibility polyfill for [String.prototype.trim](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/Trim)
  function trim(str) {
  \treturn str.trim ? str.trim() : str.replace(/^\\s+|\\s+\$/g, '');
  }

  // @function splitWords(str: String): String[]
  // Trims and splits the string on whitespace and returns the array of parts.
  function splitWords(str) {
  \treturn trim(str).split(/\\s+/);
  }

  // @function setOptions(obj: Object, options: Object): Object
  // Merges the given properties to the `options` of the `obj` object, returning the resulting options. See `Class options`. Has an `L.setOptions` shortcut.
  function setOptions(obj, options) {
  \tif (!Object.prototype.hasOwnProperty.call(obj, 'options')) {
  \t\tobj.options = obj.options ? create\$2(obj.options) : {};
  \t}
  \tfor (var i in options) {
  \t\tobj.options[i] = options[i];
  \t}
  \treturn obj.options;
  }

  // @function getParamString(obj: Object, existingUrl?: String, uppercase?: Boolean): String
  // Converts an object into a parameter URL string, e.g. `{a: \"foo\", b: \"bar\"}`
  // translates to `'?a=foo&b=bar'`. If `existingUrl` is set, the parameters will
  // be appended at the end. If `uppercase` is `true`, the parameter names will
  // be uppercased (e.g. `'?A=foo&B=bar'`)
  function getParamString(obj, existingUrl, uppercase) {
  \tvar params = [];
  \tfor (var i in obj) {
  \t\tparams.push(encodeURIComponent(uppercase ? i.toUpperCase() : i) + '=' + encodeURIComponent(obj[i]));
  \t}
  \treturn ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&');
  }

  var templateRe = /\\{ *([\\w_ -]+) *\\}/g;

  // @function template(str: String, data: Object): String
  // Simple templating facility, accepts a template string of the form `'Hello {a}, {b}'`
  // and a data object like `{a: 'foo', b: 'bar'}`, returns evaluated string
  // `('Hello foo, bar')`. You can also specify functions instead of strings for
  // data values — they will be evaluated passing `data` as an argument.
  function template(str, data) {
  \treturn str.replace(templateRe, function (str, key) {
  \t\tvar value = data[key];

  \t\tif (value === undefined) {
  \t\t\tthrow new Error('No value provided for variable ' + str);

  \t\t} else if (typeof value === 'function') {
  \t\t\tvalue = value(data);
  \t\t}
  \t\treturn value;
  \t});
  }

  // @function isArray(obj): Boolean
  // Compatibility polyfill for [Array.isArray](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray)
  var isArray = Array.isArray || function (obj) {
  \treturn (Object.prototype.toString.call(obj) === '[object Array]');
  };

  // @function indexOf(array: Array, el: Object): Number
  // Compatibility polyfill for [Array.prototype.indexOf](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf)
  function indexOf(array, el) {
  \tfor (var i = 0; i < array.length; i++) {
  \t\tif (array[i] === el) { return i; }
  \t}
  \treturn -1;
  }

  // @property emptyImageUrl: String
  // Data URI string containing a base64-encoded empty GIF image.
  // Used as a hack to free memory from unused images on WebKit-powered
  // mobile devices (by setting image `src` to this string).
  var emptyImageUrl = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';

  // inspired by https://paulirish.com/2011/requestanimationframe-for-smart-animating/

  function getPrefixed(name) {
  \treturn window['webkit' + name] || window['moz' + name] || window['ms' + name];
  }

  var lastTime = 0;

  // fallback for IE 7-8
  function timeoutDefer(fn) {
  \tvar time = +new Date(),
  \t    timeToCall = Math.max(0, 16 - (time - lastTime));

  \tlastTime = time + timeToCall;
  \treturn window.setTimeout(fn, timeToCall);
  }

  var requestFn = window.requestAnimationFrame || getPrefixed('RequestAnimationFrame') || timeoutDefer;
  var cancelFn = window.cancelAnimationFrame || getPrefixed('CancelAnimationFrame') ||
  \t\tgetPrefixed('CancelRequestAnimationFrame') || function (id) { window.clearTimeout(id); };

  // @function requestAnimFrame(fn: Function, context?: Object, immediate?: Boolean): Number
  // Schedules `fn` to be executed when the browser repaints. `fn` is bound to
  // `context` if given. When `immediate` is set, `fn` is called immediately if
  // the browser doesn't have native support for
  // [`window.requestAnimationFrame`](https://developer.mozilla.org/docs/Web/API/window/requestAnimationFrame),
  // otherwise it's delayed. Returns a request ID that can be used to cancel the request.
  function requestAnimFrame(fn, context, immediate) {
  \tif (immediate && requestFn === timeoutDefer) {
  \t\tfn.call(context);
  \t} else {
  \t\treturn requestFn.call(window, bind(fn, context));
  \t}
  }

  // @function cancelAnimFrame(id: Number): undefined
  // Cancels a previous `requestAnimFrame`. See also [window.cancelAnimationFrame](https://developer.mozilla.org/docs/Web/API/window/cancelAnimationFrame).
  function cancelAnimFrame(id) {
  \tif (id) {
  \t\tcancelFn.call(window, id);
  \t}
  }

  var Util = {
    __proto__: null,
    extend: extend,
    create: create\$2,
    bind: bind,
    get lastId () { return lastId; },
    stamp: stamp,
    throttle: throttle,
    wrapNum: wrapNum,
    falseFn: falseFn,
    formatNum: formatNum,
    trim: trim,
    splitWords: splitWords,
    setOptions: setOptions,
    getParamString: getParamString,
    template: template,
    isArray: isArray,
    indexOf: indexOf,
    emptyImageUrl: emptyImageUrl,
    requestFn: requestFn,
    cancelFn: cancelFn,
    requestAnimFrame: requestAnimFrame,
    cancelAnimFrame: cancelAnimFrame
  };

  // @class Class
  // @aka L.Class

  // @section
  // @uninheritable

  // Thanks to John Resig and Dean Edwards for inspiration!

  function Class() {}

  Class.extend = function (props) {

  \t// @function extend(props: Object): Function
  \t// [Extends the current class](#class-inheritance) given the properties to be included.
  \t// Returns a Javascript function that is a class constructor (to be called with `new`).
  \tvar NewClass = function () {

  \t\tsetOptions(this);

  \t\t// call the constructor
  \t\tif (this.initialize) {
  \t\t\tthis.initialize.apply(this, arguments);
  \t\t}

  \t\t// call all constructor hooks
  \t\tthis.callInitHooks();
  \t};

  \tvar parentProto = NewClass.__super__ = this.prototype;

  \tvar proto = create\$2(parentProto);
  \tproto.constructor = NewClass;

  \tNewClass.prototype = proto;

  \t// inherit parent's statics
  \tfor (var i in this) {
  \t\tif (Object.prototype.hasOwnProperty.call(this, i) && i !== 'prototype' && i !== '__super__') {
  \t\t\tNewClass[i] = this[i];
  \t\t}
  \t}

  \t// mix static properties into the class
  \tif (props.statics) {
  \t\textend(NewClass, props.statics);
  \t}

  \t// mix includes into the prototype
  \tif (props.includes) {
  \t\tcheckDeprecatedMixinEvents(props.includes);
  \t\textend.apply(null, [proto].concat(props.includes));
  \t}

  \t// mix given properties into the prototype
  \textend(proto, props);
  \tdelete proto.statics;
  \tdelete proto.includes;

  \t// merge options
  \tif (proto.options) {
  \t\tproto.options = parentProto.options ? create\$2(parentProto.options) : {};
  \t\textend(proto.options, props.options);
  \t}

  \tproto._initHooks = [];

  \t// add method for calling all hooks
  \tproto.callInitHooks = function () {

  \t\tif (this._initHooksCalled) { return; }

  \t\tif (parentProto.callInitHooks) {
  \t\t\tparentProto.callInitHooks.call(this);
  \t\t}

  \t\tthis._initHooksCalled = true;

  \t\tfor (var i = 0, len = proto._initHooks.length; i < len; i++) {
  \t\t\tproto._initHooks[i].call(this);
  \t\t}
  \t};

  \treturn NewClass;
  };


  // @function include(properties: Object): this
  // [Includes a mixin](#class-includes) into the current class.
  Class.include = function (props) {
  \tvar parentOptions = this.prototype.options;
  \textend(this.prototype, props);
  \tif (props.options) {
  \t\tthis.prototype.options = parentOptions;
  \t\tthis.mergeOptions(props.options);
  \t}
  \treturn this;
  };

  // @function mergeOptions(options: Object): this
  // [Merges `options`](#class-options) into the defaults of the class.
  Class.mergeOptions = function (options) {
  \textend(this.prototype.options, options);
  \treturn this;
  };

  // @function addInitHook(fn: Function): this
  // Adds a [constructor hook](#class-constructor-hooks) to the class.
  Class.addInitHook = function (fn) { // (Function) || (String, args...)
  \tvar args = Array.prototype.slice.call(arguments, 1);

  \tvar init = typeof fn === 'function' ? fn : function () {
  \t\tthis[fn].apply(this, args);
  \t};

  \tthis.prototype._initHooks = this.prototype._initHooks || [];
  \tthis.prototype._initHooks.push(init);
  \treturn this;
  };

  function checkDeprecatedMixinEvents(includes) {
  \t/* global L: true */
  \tif (typeof L === 'undefined' || !L || !L.Mixin) { return; }

  \tincludes = isArray(includes) ? includes : [includes];

  \tfor (var i = 0; i < includes.length; i++) {
  \t\tif (includes[i] === L.Mixin.Events) {
  \t\t\tconsole.warn('Deprecated include of L.Mixin.Events: ' +
  \t\t\t\t'this property will be removed in future releases, ' +
  \t\t\t\t'please inherit from L.Evented instead.', new Error().stack);
  \t\t}
  \t}
  }

  /*
   * @class Evented
   * @aka L.Evented
   * @inherits Class
   *
   * A set of methods shared between event-powered classes (like `Map` and `Marker`). Generally, events allow you to execute some function when something happens with an object (e.g. the user clicks on the map, causing the map to fire `'click'` event).
   *
   * @example
   *
   * ```js
   * map.on('click', function(e) {
   * \talert(e.latlng);
   * } );
   * ```
   *
   * Leaflet deals with event listeners by reference, so if you want to add a listener and then remove it, define it as a function:
   *
   * ```js
   * function onClick(e) { ... }
   *
   * map.on('click', onClick);
   * map.off('click', onClick);
   * ```
   */

  var Events = {
  \t/* @method on(type: String, fn: Function, context?: Object): this
  \t * Adds a listener function (`fn`) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. `'click dblclick'`).
  \t *
  \t * @alternative
  \t * @method on(eventMap: Object): this
  \t * Adds a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}`
  \t */
  \ton: function (types, fn, context) {

  \t\t// types can be a map of types/handlers
  \t\tif (typeof types === 'object') {
  \t\t\tfor (var type in types) {
  \t\t\t\t// we don't process space-separated events here for performance;
  \t\t\t\t// it's a hot path since Layer uses the on(obj) syntax
  \t\t\t\tthis._on(type, types[type], fn);
  \t\t\t}

  \t\t} else {
  \t\t\t// types can be a string of space-separated words
  \t\t\ttypes = splitWords(types);

  \t\t\tfor (var i = 0, len = types.length; i < len; i++) {
  \t\t\t\tthis._on(types[i], fn, context);
  \t\t\t}
  \t\t}

  \t\treturn this;
  \t},

  \t/* @method off(type: String, fn?: Function, context?: Object): this
  \t * Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to `on`, you must pass the same context to `off` in order to remove the listener.
  \t *
  \t * @alternative
  \t * @method off(eventMap: Object): this
  \t * Removes a set of type/listener pairs.
  \t *
  \t * @alternative
  \t * @method off: this
  \t * Removes all listeners to all events on the object. This includes implicitly attached events.
  \t */
  \toff: function (types, fn, context) {

  \t\tif (!arguments.length) {
  \t\t\t// clear all listeners if called without arguments
  \t\t\tdelete this._events;

  \t\t} else if (typeof types === 'object') {
  \t\t\tfor (var type in types) {
  \t\t\t\tthis._off(type, types[type], fn);
  \t\t\t}

  \t\t} else {
  \t\t\ttypes = splitWords(types);

  \t\t\tvar removeAll = arguments.length === 1;
  \t\t\tfor (var i = 0, len = types.length; i < len; i++) {
  \t\t\t\tif (removeAll) {
  \t\t\t\t\tthis._off(types[i]);
  \t\t\t\t} else {
  \t\t\t\t\tthis._off(types[i], fn, context);
  \t\t\t\t}
  \t\t\t}
  \t\t}

  \t\treturn this;
  \t},

  \t// attach listener (without syntactic sugar now)
  \t_on: function (type, fn, context, _once) {
  \t\tif (typeof fn !== 'function') {
  \t\t\tconsole.warn('wrong listener type: ' + typeof fn);
  \t\t\treturn;
  \t\t}

  \t\t// check if fn already there
  \t\tif (this._listens(type, fn, context) !== false) {
  \t\t\treturn;
  \t\t}

  \t\tif (context === this) {
  \t\t\t// Less memory footprint.
  \t\t\tcontext = undefined;
  \t\t}

  \t\tvar newListener = {fn: fn, ctx: context};
  \t\tif (_once) {
  \t\t\tnewListener.once = true;
  \t\t}

  \t\tthis._events = this._events || {};
  \t\tthis._events[type] = this._events[type] || [];
  \t\tthis._events[type].push(newListener);
  \t},

  \t_off: function (type, fn, context) {
  \t\tvar listeners,
  \t\t    i,
  \t\t    len;

  \t\tif (!this._events) {
  \t\t\treturn;
  \t\t}

  \t\tlisteners = this._events[type];
  \t\tif (!listeners) {
  \t\t\treturn;
  \t\t}

  \t\tif (arguments.length === 1) { // remove all
  \t\t\tif (this._firingCount) {
  \t\t\t\t// Set all removed listeners to noop
  \t\t\t\t// so they are not called if remove happens in fire
  \t\t\t\tfor (i = 0, len = listeners.length; i < len; i++) {
  \t\t\t\t\tlisteners[i].fn = falseFn;
  \t\t\t\t}
  \t\t\t}
  \t\t\t// clear all listeners for a type if function isn't specified
  \t\t\tdelete this._events[type];
  \t\t\treturn;
  \t\t}

  \t\tif (typeof fn !== 'function') {
  \t\t\tconsole.warn('wrong listener type: ' + typeof fn);
  \t\t\treturn;
  \t\t}

  \t\t// find fn and remove it
  \t\tvar index = this._listens(type, fn, context);
  \t\tif (index !== false) {
  \t\t\tvar listener = listeners[index];
  \t\t\tif (this._firingCount) {
  \t\t\t\t// set the removed listener to noop so that's not called if remove happens in fire
  \t\t\t\tlistener.fn = falseFn;

  \t\t\t\t/* copy array in case events are being fired */
  \t\t\t\tthis._events[type] = listeners = listeners.slice();
  \t\t\t}
  \t\t\tlisteners.splice(index, 1);
  \t\t}
  \t},

  \t// @method fire(type: String, data?: Object, propagate?: Boolean): this
  \t// Fires an event of the specified type. You can optionally provide a data
  \t// object — the first argument of the listener function will contain its
  \t// properties. The event can optionally be propagated to event parents.
  \tfire: function (type, data, propagate) {
  \t\tif (!this.listens(type, propagate)) { return this; }

  \t\tvar event = extend({}, data, {
  \t\t\ttype: type,
  \t\t\ttarget: this,
  \t\t\tsourceTarget: data && data.sourceTarget || this
  \t\t});

  \t\tif (this._events) {
  \t\t\tvar listeners = this._events[type];
  \t\t\tif (listeners) {
  \t\t\t\tthis._firingCount = (this._firingCount + 1) || 1;
  \t\t\t\tfor (var i = 0, len = listeners.length; i < len; i++) {
  \t\t\t\t\tvar l = listeners[i];
  \t\t\t\t\t// off overwrites l.fn, so we need to copy fn to a var
  \t\t\t\t\tvar fn = l.fn;
  \t\t\t\t\tif (l.once) {
  \t\t\t\t\t\tthis.off(type, fn, l.ctx);
  \t\t\t\t\t}
  \t\t\t\t\tfn.call(l.ctx || this, event);
  \t\t\t\t}

  \t\t\t\tthis._firingCount--;
  \t\t\t}
  \t\t}

  \t\tif (propagate) {
  \t\t\t// propagate the event to parents (set with addEventParent)
  \t\t\tthis._propagateEvent(event);
  \t\t}

  \t\treturn this;
  \t},

  \t// @method listens(type: String, propagate?: Boolean): Boolean
  \t// @method listens(type: String, fn: Function, context?: Object, propagate?: Boolean): Boolean
  \t// Returns `true` if a particular event type has any listeners attached to it.
  \t// The verification can optionally be propagated, it will return `true` if parents have the listener attached to it.
  \tlistens: function (type, fn, context, propagate) {
  \t\tif (typeof type !== 'string') {
  \t\t\tconsole.warn('\"string\" type argument expected');
  \t\t}

  \t\t// we don't overwrite the input `fn` value, because we need to use it for propagation
  \t\tvar _fn = fn;
  \t\tif (typeof fn !== 'function') {
  \t\t\tpropagate = !!fn;
  \t\t\t_fn = undefined;
  \t\t\tcontext = undefined;
  \t\t}

  \t\tvar listeners = this._events && this._events[type];
  \t\tif (listeners && listeners.length) {
  \t\t\tif (this._listens(type, _fn, context) !== false) {
  \t\t\t\treturn true;
  \t\t\t}
  \t\t}

  \t\tif (propagate) {
  \t\t\t// also check parents for listeners if event propagates
  \t\t\tfor (var id in this._eventParents) {
  \t\t\t\tif (this._eventParents[id].listens(type, fn, context, propagate)) { return true; }
  \t\t\t}
  \t\t}
  \t\treturn false;
  \t},

  \t// returns the index (number) or false
  \t_listens: function (type, fn, context) {
  \t\tif (!this._events) {
  \t\t\treturn false;
  \t\t}

  \t\tvar listeners = this._events[type] || [];
  \t\tif (!fn) {
  \t\t\treturn !!listeners.length;
  \t\t}

  \t\tif (context === this) {
  \t\t\t// Less memory footprint.
  \t\t\tcontext = undefined;
  \t\t}

  \t\tfor (var i = 0, len = listeners.length; i < len; i++) {
  \t\t\tif (listeners[i].fn === fn && listeners[i].ctx === context) {
  \t\t\t\treturn i;
  \t\t\t}
  \t\t}
  \t\treturn false;

  \t},

  \t// @method once(…): this
  \t// Behaves as [`on(…)`](#evented-on), except the listener will only get fired once and then removed.
  \tonce: function (types, fn, context) {

  \t\t// types can be a map of types/handlers
  \t\tif (typeof types === 'object') {
  \t\t\tfor (var type in types) {
  \t\t\t\t// we don't process space-separated events here for performance;
  \t\t\t\t// it's a hot path since Layer uses the on(obj) syntax
  \t\t\t\tthis._on(type, types[type], fn, true);
  \t\t\t}

  \t\t} else {
  \t\t\t// types can be a string of space-separated words
  \t\t\ttypes = splitWords(types);

  \t\t\tfor (var i = 0, len = types.length; i < len; i++) {
  \t\t\t\tthis._on(types[i], fn, context, true);
  \t\t\t}
  \t\t}

  \t\treturn this;
  \t},

  \t// @method addEventParent(obj: Evented): this
  \t// Adds an event parent - an `Evented` that will receive propagated events
  \taddEventParent: function (obj) {
  \t\tthis._eventParents = this._eventParents || {};
  \t\tthis._eventParents[stamp(obj)] = obj;
  \t\treturn this;
  \t},

  \t// @method removeEventParent(obj: Evented): this
  \t// Removes an event parent, so it will stop receiving propagated events
  \tremoveEventParent: function (obj) {
  \t\tif (this._eventParents) {
  \t\t\tdelete this._eventParents[stamp(obj)];
  \t\t}
  \t\treturn this;
  \t},

  \t_propagateEvent: function (e) {
  \t\tfor (var id in this._eventParents) {
  \t\t\tthis._eventParents[id].fire(e.type, extend({
  \t\t\t\tlayer: e.target,
  \t\t\t\tpropagatedFrom: e.target
  \t\t\t}, e), true);
  \t\t}
  \t}
  };

  // aliases; we should ditch those eventually

  // @method addEventListener(…): this
  // Alias to [`on(…)`](#evented-on)
  Events.addEventListener = Events.on;

  // @method removeEventListener(…): this
  // Alias to [`off(…)`](#evented-off)

  // @method clearAllEventListeners(…): this
  // Alias to [`off()`](#evented-off)
  Events.removeEventListener = Events.clearAllEventListeners = Events.off;

  // @method addOneTimeEventListener(…): this
  // Alias to [`once(…)`](#evented-once)
  Events.addOneTimeEventListener = Events.once;

  // @method fireEvent(…): this
  // Alias to [`fire(…)`](#evented-fire)
  Events.fireEvent = Events.fire;

  // @method hasEventListeners(…): Boolean
  // Alias to [`listens(…)`](#evented-listens)
  Events.hasEventListeners = Events.listens;

  var Evented = Class.extend(Events);

  /*
   * @class Point
   * @aka L.Point
   *
   * Represents a point with `x` and `y` coordinates in pixels.
   *
   * @example
   *
   * ```js
   * var point = L.point(200, 300);
   * ```
   *
   * All Leaflet methods and options that accept `Point` objects also accept them in a simple Array form (unless noted otherwise), so these lines are equivalent:
   *
   * ```js
   * map.panBy([200, 300]);
   * map.panBy(L.point(200, 300));
   * ```
   *
   * Note that `Point` does not inherit from Leaflet's `Class` object,
   * which means new classes can't inherit from it, and new methods
   * can't be added to it with the `include` function.
   */

  function Point(x, y, round) {
  \t// @property x: Number; The `x` coordinate of the point
  \tthis.x = (round ? Math.round(x) : x);
  \t// @property y: Number; The `y` coordinate of the point
  \tthis.y = (round ? Math.round(y) : y);
  }

  var trunc = Math.trunc || function (v) {
  \treturn v > 0 ? Math.floor(v) : Math.ceil(v);
  };

  Point.prototype = {

  \t// @method clone(): Point
  \t// Returns a copy of the current point.
  \tclone: function () {
  \t\treturn new Point(this.x, this.y);
  \t},

  \t// @method add(otherPoint: Point): Point
  \t// Returns the result of addition of the current and the given points.
  \tadd: function (point) {
  \t\t// non-destructive, returns a new point
  \t\treturn this.clone()._add(toPoint(point));
  \t},

  \t_add: function (point) {
  \t\t// destructive, used directly for performance in situations where it's safe to modify existing point
  \t\tthis.x += point.x;
  \t\tthis.y += point.y;
  \t\treturn this;
  \t},

  \t// @method subtract(otherPoint: Point): Point
  \t// Returns the result of subtraction of the given point from the current.
  \tsubtract: function (point) {
  \t\treturn this.clone()._subtract(toPoint(point));
  \t},

  \t_subtract: function (point) {
  \t\tthis.x -= point.x;
  \t\tthis.y -= point.y;
  \t\treturn this;
  \t},

  \t// @method divideBy(num: Number): Point
  \t// Returns the result of division of the current point by the given number.
  \tdivideBy: function (num) {
  \t\treturn this.clone()._divideBy(num);
  \t},

  \t_divideBy: function (num) {
  \t\tthis.x /= num;
  \t\tthis.y /= num;
  \t\treturn this;
  \t},

  \t// @method multiplyBy(num: Number): Point
  \t// Returns the result of multiplication of the current point by the given number.
  \tmultiplyBy: function (num) {
  \t\treturn this.clone()._multiplyBy(num);
  \t},

  \t_multiplyBy: function (num) {
  \t\tthis.x *= num;
  \t\tthis.y *= num;
  \t\treturn this;
  \t},

  \t// @method scaleBy(scale: Point): Point
  \t// Multiply each coordinate of the current point by each coordinate of
  \t// `scale`. In linear algebra terms, multiply the point by the
  \t// [scaling matrix](https://en.wikipedia.org/wiki/Scaling_%28geometry%29#Matrix_representation)
  \t// defined by `scale`.
  \tscaleBy: function (point) {
  \t\treturn new Point(this.x * point.x, this.y * point.y);
  \t},

  \t// @method unscaleBy(scale: Point): Point
  \t// Inverse of `scaleBy`. Divide each coordinate of the current point by
  \t// each coordinate of `scale`.
  \tunscaleBy: function (point) {
  \t\treturn new Point(this.x / point.x, this.y / point.y);
  \t},

  \t// @method round(): Point
  \t// Returns a copy of the current point with rounded coordinates.
  \tround: function () {
  \t\treturn this.clone()._round();
  \t},

  \t_round: function () {
  \t\tthis.x = Math.round(this.x);
  \t\tthis.y = Math.round(this.y);
  \t\treturn this;
  \t},

  \t// @method floor(): Point
  \t// Returns a copy of the current point with floored coordinates (rounded down).
  \tfloor: function () {
  \t\treturn this.clone()._floor();
  \t},

  \t_floor: function () {
  \t\tthis.x = Math.floor(this.x);
  \t\tthis.y = Math.floor(this.y);
  \t\treturn this;
  \t},

  \t// @method ceil(): Point
  \t// Returns a copy of the current point with ceiled coordinates (rounded up).
  \tceil: function () {
  \t\treturn this.clone()._ceil();
  \t},

  \t_ceil: function () {
  \t\tthis.x = Math.ceil(this.x);
  \t\tthis.y = Math.ceil(this.y);
  \t\treturn this;
  \t},

  \t// @method trunc(): Point
  \t// Returns a copy of the current point with truncated coordinates (rounded towards zero).
  \ttrunc: function () {
  \t\treturn this.clone()._trunc();
  \t},

  \t_trunc: function () {
  \t\tthis.x = trunc(this.x);
  \t\tthis.y = trunc(this.y);
  \t\treturn this;
  \t},

  \t// @method distanceTo(otherPoint: Point): Number
  \t// Returns the cartesian distance between the current and the given points.
  \tdistanceTo: function (point) {
  \t\tpoint = toPoint(point);

  \t\tvar x = point.x - this.x,
  \t\t    y = point.y - this.y;

  \t\treturn Math.sqrt(x * x + y * y);
  \t},

  \t// @method equals(otherPoint: Point): Boolean
  \t// Returns `true` if the given point has the same coordinates.
  \tequals: function (point) {
  \t\tpoint = toPoint(point);

  \t\treturn point.x === this.x &&
  \t\t       point.y === this.y;
  \t},

  \t// @method contains(otherPoint: Point): Boolean
  \t// Returns `true` if both coordinates of the given point are less than the corresponding current point coordinates (in absolute values).
  \tcontains: function (point) {
  \t\tpoint = toPoint(point);

  \t\treturn Math.abs(point.x) <= Math.abs(this.x) &&
  \t\t       Math.abs(point.y) <= Math.abs(this.y);
  \t},

  \t// @method toString(): String
  \t// Returns a string representation of the point for debugging purposes.
  \ttoString: function () {
  \t\treturn 'Point(' +
  \t\t        formatNum(this.x) + ', ' +
  \t\t        formatNum(this.y) + ')';
  \t}
  };

  // @factory L.point(x: Number, y: Number, round?: Boolean)
  // Creates a Point object with the given `x` and `y` coordinates. If optional `round` is set to true, rounds the `x` and `y` values.

  // @alternative
  // @factory L.point(coords: Number[])
  // Expects an array of the form `[x, y]` instead.

  // @alternative
  // @factory L.point(coords: Object)
  // Expects a plain object of the form `{x: Number, y: Number}` instead.
  function toPoint(x, y, round) {
  \tif (x instanceof Point) {
  \t\treturn x;
  \t}
  \tif (isArray(x)) {
  \t\treturn new Point(x[0], x[1]);
  \t}
  \tif (x === undefined || x === null) {
  \t\treturn x;
  \t}
  \tif (typeof x === 'object' && 'x' in x && 'y' in x) {
  \t\treturn new Point(x.x, x.y);
  \t}
  \treturn new Point(x, y, round);
  }

  /*
   * @class Bounds
   * @aka L.Bounds
   *
   * Represents a rectangular area in pixel coordinates.
   *
   * @example
   *
   * ```js
   * var p1 = L.point(10, 10),
   * p2 = L.point(40, 60),
   * bounds = L.bounds(p1, p2);
   * ```
   *
   * All Leaflet methods that accept `Bounds` objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this:
   *
   * ```js
   * otherBounds.intersects([[10, 10], [40, 60]]);
   * ```
   *
   * Note that `Bounds` does not inherit from Leaflet's `Class` object,
   * which means new classes can't inherit from it, and new methods
   * can't be added to it with the `include` function.
   */

  function Bounds(a, b) {
  \tif (!a) { return; }

  \tvar points = b ? [a, b] : a;

  \tfor (var i = 0, len = points.length; i < len; i++) {
  \t\tthis.extend(points[i]);
  \t}
  }

  Bounds.prototype = {
  \t// @method extend(point: Point): this
  \t// Extends the bounds to contain the given point.

  \t// @alternative
  \t// @method extend(otherBounds: Bounds): this
  \t// Extend the bounds to contain the given bounds
  \textend: function (obj) {
  \t\tvar min2, max2;
  \t\tif (!obj) { return this; }

  \t\tif (obj instanceof Point || typeof obj[0] === 'number' || 'x' in obj) {
  \t\t\tmin2 = max2 = toPoint(obj);
  \t\t} else {
  \t\t\tobj = toBounds(obj);
  \t\t\tmin2 = obj.min;
  \t\t\tmax2 = obj.max;

  \t\t\tif (!min2 || !max2) { return this; }
  \t\t}

  \t\t// @property min: Point
  \t\t// The top left corner of the rectangle.
  \t\t// @property max: Point
  \t\t// The bottom right corner of the rectangle.
  \t\tif (!this.min && !this.max) {
  \t\t\tthis.min = min2.clone();
  \t\t\tthis.max = max2.clone();
  \t\t} else {
  \t\t\tthis.min.x = Math.min(min2.x, this.min.x);
  \t\t\tthis.max.x = Math.max(max2.x, this.max.x);
  \t\t\tthis.min.y = Math.min(min2.y, this.min.y);
  \t\t\tthis.max.y = Math.max(max2.y, this.max.y);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method getCenter(round?: Boolean): Point
  \t// Returns the center point of the bounds.
  \tgetCenter: function (round) {
  \t\treturn toPoint(
  \t\t        (this.min.x + this.max.x) / 2,
  \t\t        (this.min.y + this.max.y) / 2, round);
  \t},

  \t// @method getBottomLeft(): Point
  \t// Returns the bottom-left point of the bounds.
  \tgetBottomLeft: function () {
  \t\treturn toPoint(this.min.x, this.max.y);
  \t},

  \t// @method getTopRight(): Point
  \t// Returns the top-right point of the bounds.
  \tgetTopRight: function () { // -> Point
  \t\treturn toPoint(this.max.x, this.min.y);
  \t},

  \t// @method getTopLeft(): Point
  \t// Returns the top-left point of the bounds (i.e. [`this.min`](#bounds-min)).
  \tgetTopLeft: function () {
  \t\treturn this.min; // left, top
  \t},

  \t// @method getBottomRight(): Point
  \t// Returns the bottom-right point of the bounds (i.e. [`this.max`](#bounds-max)).
  \tgetBottomRight: function () {
  \t\treturn this.max; // right, bottom
  \t},

  \t// @method getSize(): Point
  \t// Returns the size of the given bounds
  \tgetSize: function () {
  \t\treturn this.max.subtract(this.min);
  \t},

  \t// @method contains(otherBounds: Bounds): Boolean
  \t// Returns `true` if the rectangle contains the given one.
  \t// @alternative
  \t// @method contains(point: Point): Boolean
  \t// Returns `true` if the rectangle contains the given point.
  \tcontains: function (obj) {
  \t\tvar min, max;

  \t\tif (typeof obj[0] === 'number' || obj instanceof Point) {
  \t\t\tobj = toPoint(obj);
  \t\t} else {
  \t\t\tobj = toBounds(obj);
  \t\t}

  \t\tif (obj instanceof Bounds) {
  \t\t\tmin = obj.min;
  \t\t\tmax = obj.max;
  \t\t} else {
  \t\t\tmin = max = obj;
  \t\t}

  \t\treturn (min.x >= this.min.x) &&
  \t\t       (max.x <= this.max.x) &&
  \t\t       (min.y >= this.min.y) &&
  \t\t       (max.y <= this.max.y);
  \t},

  \t// @method intersects(otherBounds: Bounds): Boolean
  \t// Returns `true` if the rectangle intersects the given bounds. Two bounds
  \t// intersect if they have at least one point in common.
  \tintersects: function (bounds) { // (Bounds) -> Boolean
  \t\tbounds = toBounds(bounds);

  \t\tvar min = this.min,
  \t\t    max = this.max,
  \t\t    min2 = bounds.min,
  \t\t    max2 = bounds.max,
  \t\t    xIntersects = (max2.x >= min.x) && (min2.x <= max.x),
  \t\t    yIntersects = (max2.y >= min.y) && (min2.y <= max.y);

  \t\treturn xIntersects && yIntersects;
  \t},

  \t// @method overlaps(otherBounds: Bounds): Boolean
  \t// Returns `true` if the rectangle overlaps the given bounds. Two bounds
  \t// overlap if their intersection is an area.
  \toverlaps: function (bounds) { // (Bounds) -> Boolean
  \t\tbounds = toBounds(bounds);

  \t\tvar min = this.min,
  \t\t    max = this.max,
  \t\t    min2 = bounds.min,
  \t\t    max2 = bounds.max,
  \t\t    xOverlaps = (max2.x > min.x) && (min2.x < max.x),
  \t\t    yOverlaps = (max2.y > min.y) && (min2.y < max.y);

  \t\treturn xOverlaps && yOverlaps;
  \t},

  \t// @method isValid(): Boolean
  \t// Returns `true` if the bounds are properly initialized.
  \tisValid: function () {
  \t\treturn !!(this.min && this.max);
  \t},


  \t// @method pad(bufferRatio: Number): Bounds
  \t// Returns bounds created by extending or retracting the current bounds by a given ratio in each direction.
  \t// For example, a ratio of 0.5 extends the bounds by 50% in each direction.
  \t// Negative values will retract the bounds.
  \tpad: function (bufferRatio) {
  \t\tvar min = this.min,
  \t\tmax = this.max,
  \t\theightBuffer = Math.abs(min.x - max.x) * bufferRatio,
  \t\twidthBuffer = Math.abs(min.y - max.y) * bufferRatio;


  \t\treturn toBounds(
  \t\t\ttoPoint(min.x - heightBuffer, min.y - widthBuffer),
  \t\t\ttoPoint(max.x + heightBuffer, max.y + widthBuffer));
  \t},


  \t// @method equals(otherBounds: Bounds): Boolean
  \t// Returns `true` if the rectangle is equivalent to the given bounds.
  \tequals: function (bounds) {
  \t\tif (!bounds) { return false; }

  \t\tbounds = toBounds(bounds);

  \t\treturn this.min.equals(bounds.getTopLeft()) &&
  \t\t\tthis.max.equals(bounds.getBottomRight());
  \t},
  };


  // @factory L.bounds(corner1: Point, corner2: Point)
  // Creates a Bounds object from two corners coordinate pairs.
  // @alternative
  // @factory L.bounds(points: Point[])
  // Creates a Bounds object from the given array of points.
  function toBounds(a, b) {
  \tif (!a || a instanceof Bounds) {
  \t\treturn a;
  \t}
  \treturn new Bounds(a, b);
  }

  /*
   * @class LatLngBounds
   * @aka L.LatLngBounds
   *
   * Represents a rectangular geographical area on a map.
   *
   * @example
   *
   * ```js
   * var corner1 = L.latLng(40.712, -74.227),
   * corner2 = L.latLng(40.774, -74.125),
   * bounds = L.latLngBounds(corner1, corner2);
   * ```
   *
   * All Leaflet methods that accept LatLngBounds objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this:
   *
   * ```js
   * map.fitBounds([
   * \t[40.712, -74.227],
   * \t[40.774, -74.125]
   * ]);
   * ```
   *
   * Caution: if the area crosses the antimeridian (often confused with the International Date Line), you must specify corners _outside_ the [-180, 180] degrees longitude range.
   *
   * Note that `LatLngBounds` does not inherit from Leaflet's `Class` object,
   * which means new classes can't inherit from it, and new methods
   * can't be added to it with the `include` function.
   */

  function LatLngBounds(corner1, corner2) { // (LatLng, LatLng) or (LatLng[])
  \tif (!corner1) { return; }

  \tvar latlngs = corner2 ? [corner1, corner2] : corner1;

  \tfor (var i = 0, len = latlngs.length; i < len; i++) {
  \t\tthis.extend(latlngs[i]);
  \t}
  }

  LatLngBounds.prototype = {

  \t// @method extend(latlng: LatLng): this
  \t// Extend the bounds to contain the given point

  \t// @alternative
  \t// @method extend(otherBounds: LatLngBounds): this
  \t// Extend the bounds to contain the given bounds
  \textend: function (obj) {
  \t\tvar sw = this._southWest,
  \t\t    ne = this._northEast,
  \t\t    sw2, ne2;

  \t\tif (obj instanceof LatLng) {
  \t\t\tsw2 = obj;
  \t\t\tne2 = obj;

  \t\t} else if (obj instanceof LatLngBounds) {
  \t\t\tsw2 = obj._southWest;
  \t\t\tne2 = obj._northEast;

  \t\t\tif (!sw2 || !ne2) { return this; }

  \t\t} else {
  \t\t\treturn obj ? this.extend(toLatLng(obj) || toLatLngBounds(obj)) : this;
  \t\t}

  \t\tif (!sw && !ne) {
  \t\t\tthis._southWest = new LatLng(sw2.lat, sw2.lng);
  \t\t\tthis._northEast = new LatLng(ne2.lat, ne2.lng);
  \t\t} else {
  \t\t\tsw.lat = Math.min(sw2.lat, sw.lat);
  \t\t\tsw.lng = Math.min(sw2.lng, sw.lng);
  \t\t\tne.lat = Math.max(ne2.lat, ne.lat);
  \t\t\tne.lng = Math.max(ne2.lng, ne.lng);
  \t\t}

  \t\treturn this;
  \t},

  \t// @method pad(bufferRatio: Number): LatLngBounds
  \t// Returns bounds created by extending or retracting the current bounds by a given ratio in each direction.
  \t// For example, a ratio of 0.5 extends the bounds by 50% in each direction.
  \t// Negative values will retract the bounds.
  \tpad: function (bufferRatio) {
  \t\tvar sw = this._southWest,
  \t\t    ne = this._northEast,
  \t\t    heightBuffer = Math.abs(sw.lat - ne.lat) * bufferRatio,
  \t\t    widthBuffer = Math.abs(sw.lng - ne.lng) * bufferRatio;

  \t\treturn new LatLngBounds(
  \t\t        new LatLng(sw.lat - heightBuffer, sw.lng - widthBuffer),
  \t\t        new LatLng(ne.lat + heightBuffer, ne.lng + widthBuffer));
  \t},

  \t// @method getCenter(): LatLng
  \t// Returns the center point of the bounds.
  \tgetCenter: function () {
  \t\treturn new LatLng(
  \t\t        (this._southWest.lat + this._northEast.lat) / 2,
  \t\t        (this._southWest.lng + this._northEast.lng) / 2);
  \t},

  \t// @method getSouthWest(): LatLng
  \t// Returns the south-west point of the bounds.
  \tgetSouthWest: function () {
  \t\treturn this._southWest;
  \t},

  \t// @method getNorthEast(): LatLng
  \t// Returns the north-east point of the bounds.
  \tgetNorthEast: function () {
  \t\treturn this._northEast;
  \t},

  \t// @method getNorthWest(): LatLng
  \t// Returns the north-west point of the bounds.
  \tgetNorthWest: function () {
  \t\treturn new LatLng(this.getNorth(), this.getWest());
  \t},

  \t// @method getSouthEast(): LatLng
  \t// Returns the south-east point of the bounds.
  \tgetSouthEast: function () {
  \t\treturn new LatLng(this.getSouth(), this.getEast());
  \t},

  \t// @method getWest(): Number
  \t// Returns the west longitude of the bounds
  \tgetWest: function () {
  \t\treturn this._southWest.lng;
  \t},

  \t// @method getSouth(): Number
  \t// Returns the south latitude of the bounds
  \tgetSouth: function () {
  \t\treturn this._southWest.lat;
  \t},

  \t// @method getEast(): Number
  \t// Returns the east longitude of the bounds
  \tgetEast: function () {
  \t\treturn this._northEast.lng;
  \t},

  \t// @method getNorth(): Number
  \t// Returns the north latitude of the bounds
  \tgetNorth: function () {
  \t\treturn this._northEast.lat;
  \t},

  \t// @method contains(otherBounds: LatLngBounds): Boolean
  \t// Returns `true` if the rectangle contains the given one.

  \t// @alternative
  \t// @method contains (latlng: LatLng): Boolean
  \t// Returns `true` if the rectangle contains the given point.
  \tcontains: function (obj) { // (LatLngBounds) or (LatLng) -> Boolean
  \t\tif (typeof obj[0] === 'number' || obj instanceof LatLng || 'lat' in obj) {
  \t\t\tobj = toLatLng(obj);
  \t\t} else {
  \t\t\tobj = toLatLngBounds(obj);
  \t\t}

  \t\tvar sw = this._southWest,
  \t\t    ne = this._northEast,
  \t\t    sw2, ne2;

  \t\tif (obj instanceof LatLngBounds) {
  \t\t\tsw2 = obj.getSouthWest();
  \t\t\tne2 = obj.getNorthEast();
  \t\t} else {
  \t\t\tsw2 = ne2 = obj;
  \t\t}

  \t\treturn (sw2.lat >= sw.lat) && (ne2.lat <= ne.lat) &&
  \t\t       (sw2.lng >= sw.lng) && (ne2.lng <= ne.lng);
  \t},

  \t// @method intersects(otherBounds: LatLngBounds): Boolean
  \t// Returns `true` if the rectangle intersects the given bounds. Two bounds intersect if they have at least one point in common.
  \tintersects: function (bounds) {
  \t\tbounds = toLatLngBounds(bounds);

  \t\tvar sw = this._southWest,
  \t\t    ne = this._northEast,
  \t\t    sw2 = bounds.getSouthWest(),
  \t\t    ne2 = bounds.getNorthEast(),

  \t\t    latIntersects = (ne2.lat >= sw.lat) && (sw2.lat <= ne.lat),
  \t\t    lngIntersects = (ne2.lng >= sw.lng) && (sw2.lng <= ne.lng);

  \t\treturn latIntersects && lngIntersects;
  \t},

  \t// @method overlaps(otherBounds: LatLngBounds): Boolean
  \t// Returns `true` if the rectangle overlaps the given bounds. Two bounds overlap if their intersection is an area.
  \toverlaps: function (bounds) {
  \t\tbounds = toLatLngBounds(bounds);

  \t\tvar sw = this._southWest,
  \t\t    ne = this._northEast,
  \t\t    sw2 = bounds.getSouthWest(),
  \t\t    ne2 = bounds.getNorthEast(),

  \t\t    latOverlaps = (ne2.lat > sw.lat) && (sw2.lat < ne.lat),
  \t\t    lngOverlaps = (ne2.lng > sw.lng) && (sw2.lng < ne.lng);

  \t\treturn latOverlaps && lngOverlaps;
  \t},

  \t// @method toBBoxString(): String
  \t// Returns a string with bounding box coordinates in a 'southwest_lng,southwest_lat,northeast_lng,northeast_lat' format. Useful for sending requests to web services that return geo data.
  \ttoBBoxString: function () {
  \t\treturn [this.getWest(), this.getSouth(), this.getEast(), this.getNorth()].join(',');
  \t},

  \t// @method equals(otherBounds: LatLngBounds, maxMargin?: Number): Boolean
  \t// Returns `true` if the rectangle is equivalent (within a small margin of error) to the given bounds. The margin of error can be overridden by setting `maxMargin` to a small number.
  \tequals: function (bounds, maxMargin) {
  \t\tif (!bounds) { return false; }

  \t\tbounds = toLatLngBounds(bounds);

  \t\treturn this._southWest.equals(bounds.getSouthWest(), maxMargin) &&
  \t\t       this._northEast.equals(bounds.getNorthEast(), maxMargin);
  \t},

  \t// @method isValid(): Boolean
  \t// Returns `true` if the bounds are properly initialized.
  \tisValid: function () {
  \t\treturn !!(this._southWest && this._northEast);
  \t}
  };

  // TODO International date line?

  // @factory L.latLngBounds(corner1: LatLng, corner2: LatLng)
  // Creates a `LatLngBounds` object by defining two diagonally opposite corners of the rectangle.

  // @alternative
  // @factory L.latLngBounds(latlngs: LatLng[])
  // Creates a `LatLngBounds` object defined by the geographical points it contains. Very useful for zooming the map to fit a particular set of locations with [`fitBounds`](#map-fitbounds).
  function toLatLngBounds(a, b) {
  \tif (a instanceof LatLngBounds) {
  \t\treturn a;
  \t}
  \treturn new LatLngBounds(a, b);
  }

  /* @class LatLng
   * @aka L.LatLng
   *
   * Represents a geographical point with a certain latitude and longitude.
   *
   * @example
   *
   * ```
   * var latlng = L.latLng(50.5, 30.5);
   * ```
   *
   * All Leaflet methods that accept LatLng objects also accept them in a simple Array form and simple object form (unless noted otherwise), so these lines are equivalent:
   *
   * ```
   * map.panTo([50, 30]);
   * map.panTo({lon: 30, lat: 50});
   * map.panTo({lat: 50, lng: 30});
   * map.panTo(L.latLng(50, 30));
   * ```
   *
   * Note that `LatLng` does not inherit from Leaflet's `Class` object,
   * which means new classes can't inherit from it, and new methods
   * can't be added to it with the `include` function.
   */

  function LatLng(lat, lng, alt) {
  \tif (isNaN(lat) || isNaN(lng)) {
  \t\tthrow new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')');
  \t}

  \t// @property lat: Number
  \t// Latitude in degrees
  \tthis.lat = +lat;

  \t// @property lng: Number
  \t// Longitude in degrees
  \tthis.lng = +lng;

  \t// @property alt: Number
  \t// Altitude in meters (optional)
  \tif (alt !== undefined) {
  \t\tthis.alt = +alt;
  \t}
  }

  LatLng.prototype = {
  \t// @method equals(otherLatLng: LatLng, maxMargin?: Number): Boolean
  \t// Returns `true` if the given `LatLng` point is at the same position (within a small margin of error). The margin of error can be overridden by setting `maxMargin` to a small number.
  \tequals: function (obj, maxMargin) {
  \t\tif (!obj) { return false; }

  \t\tobj = toLatLng(obj);

  \t\tvar margin = Math.max(
  \t\t        Math.abs(this.lat - obj.lat),
  \t\t        Math.abs(this.lng - obj.lng));

  \t\treturn margin <= (maxMargin === undefined ? 1.0E-9 : maxMargin);
  \t},

  \t// @method toString(): String
  \t// Returns a string representation of the point (for debugging purposes).
  \ttoString: function (precision) {
  \t\treturn 'LatLng(' +
  \t\t        formatNum(this.lat, precision) + ', ' +
  \t\t        formatNum(this.lng, precision) + ')';
  \t},

  \t// @method distanceTo(otherLatLng: LatLng): Number
  \t// Returns the distance (in meters) to the given `LatLng` calculated using the [Spherical Law of Cosines](https://en.wikipedia.org/wiki/Spherical_law_of_cosines).
  \tdistanceTo: function (other) {
  \t\treturn Earth.distance(this, toLatLng(other));
  \t},

  \t// @method wrap(): LatLng
  \t// Returns a new `LatLng` object with the longitude wrapped so it's always between -180 and +180 degrees.
  \twrap: function () {
  \t\treturn Earth.wrapLatLng(this);
  \t},

  \t// @method toBounds(sizeInMeters: Number): LatLngBounds
  \t// Returns a new `LatLngBounds` object in which each boundary is `sizeInMeters/2` meters apart from the `LatLng`.
  \ttoBounds: function (sizeInMeters) {
  \t\tvar latAccuracy = 180 * sizeInMeters / 40075017,
  \t\t    lngAccuracy = latAccuracy / Math.cos((Math.PI / 180) * this.lat);

  \t\treturn toLatLngBounds(
  \t\t        [this.lat - latAccuracy, this.lng - lngAccuracy],
  \t\t        [this.lat + latAccuracy, this.lng + lngAccuracy]);
  \t},

  \tclone: function () {
  \t\treturn new LatLng(this.lat, this.lng, this.alt);
  \t}
  };



  // @factory L.latLng(latitude: Number, longitude: Number, altitude?: Number): LatLng
  // Creates an object representing a geographical point with the given latitude and longitude (and optionally altitude).

  // @alternative
  // @factory L.latLng(coords: Array): LatLng
  // Expects an array of the form `[Number, Number]` or `[Number, Number, Number]` instead.

  // @alternative
  // @factory L.latLng(coords: Object): LatLng
  // Expects an plain object of the form `{lat: Number, lng: Number}` or `{lat: Number, lng: Number, alt: Number}` instead.

  function toLatLng(a, b, c) {
  \tif (a instanceof LatLng) {
  \t\treturn a;
  \t}
  \tif (isArray(a) && typeof a[0] !== 'object') {
  \t\tif (a.length === 3) {
  \t\t\treturn new LatLng(a[0], a[1], a[2]);
  \t\t}
  \t\tif (a.length === 2) {
  \t\t\treturn new LatLng(a[0], a[1]);
  \t\t}
  \t\treturn null;
  \t}
  \tif (a === undefined || a === null) {
  \t\treturn a;
  \t}
  \tif (typeof a === 'object' && 'lat' in a) {
  \t\treturn new LatLng(a.lat, 'lng' in a ? a.lng : a.lon, a.alt);
  \t}
  \tif (b === undefined) {
  \t\treturn null;
  \t}
  \treturn new LatLng(a, b, c);
  }

  /*
   * @namespace CRS
   * @crs L.CRS.Base
   * Object that defines coordinate reference systems for projecting
   * geographical points into pixel (screen) coordinates and back (and to
   * coordinates in other units for [WMS](https://en.wikipedia.org/wiki/Web_Map_Service) services). See
   * [spatial reference system](https://en.wikipedia.org/wiki/Spatial_reference_system).
   *
   * Leaflet defines the most usual CRSs by default. If you want to use a
   * CRS not defined by default, take a look at the
   * [Proj4Leaflet](https://github.com/kartena/Proj4Leaflet) plugin.
   *
   * Note that the CRS instances do not inherit from Leaflet's `Class` object,
   * and can't be instantiated. Also, new classes can't inherit from them,
   * and methods can't be added to them with the `include` function.
   */

  var CRS = {
  \t// @method latLngToPoint(latlng: LatLng, zoom: Number): Point
  \t// Projects geographical coordinates into pixel coordinates for a given zoom.
  \tlatLngToPoint: function (latlng, zoom) {
  \t\tvar projectedPoint = this.projection.project(latlng),
  \t\t    scale = this.scale(zoom);

  \t\treturn this.transformation._transform(projectedPoint, scale);
  \t},

  \t// @method pointToLatLng(point: Point, zoom: Number): LatLng
  \t// The inverse of `latLngToPoint`. Projects pixel coordinates on a given
  \t// zoom into geographical coordinates.
  \tpointToLatLng: function (point, zoom) {
  \t\tvar scale = this.scale(zoom),
  \t\t    untransformedPoint = this.transformation.untransform(point, scale);

  \t\treturn this.projection.unproject(untransformedPoint);
  \t},

  \t// @method project(latlng: LatLng): Point
  \t// Projects geographical coordinates into coordinates in units accepted for
  \t// this CRS (e.g. meters for EPSG:3857, for passing it to WMS services).
  \tproject: function (latlng) {
  \t\treturn this.projection.project(latlng);
  \t},

  \t// @method unproject(point: Point): LatLng
  \t// Given a projected coordinate returns the corresponding LatLng.
  \t// The inverse of `project`.
  \tunproject: function (point) {
  \t\treturn this.projection.unproject(point);
  \t},

  \t// @method scale(zoom: Number): Number
  \t// Returns the scale used when transforming projected coordinates into
  \t// pixel coordinates for a particular zoom. For example, it returns
  \t// `256 * 2^zoom` for Mercator-based CRS.
  \tscale: function (zoom) {
  \t\treturn 256 * Math.pow(2, zoom);
  \t},

  \t// @method zoom(scale: Number): Number
  \t// Inverse of `scale()`, returns the zoom level corresponding to a scale
  \t// factor of `scale`.
  \tzoom: function (scale) {
  \t\treturn Math.log(scale / 256) / Math.LN2;
  \t},

  \t// @method getProjectedBounds(zoom: Number): Bounds
  \t// Returns the projection's bounds scaled and transformed for the provided `zoom`.
  \tgetProjectedBounds: function (zoom) {
  \t\tif (this.infinite) { return null; }

  \t\tvar b = this.projection.bounds,
  \t\t    s = this.scale(zoom),
  \t\t    min = this.transformation.transform(b.min, s),
  \t\t    max = this.transformation.transform(b.max, s);

  \t\treturn new Bounds(min, max);
  \t},

  \t// @method distance(latlng1: LatLng, latlng2: LatLng): Number
  \t// Returns the distance between two geographical coordinates.

  \t// @property code: String
  \t// Standard code name of the CRS passed into WMS services (e.g. `'EPSG:3857'`)
  \t//
  \t// @property wrapLng: Number[]
  \t// An array of two numbers defining whether the longitude (horizontal) coordinate
  \t// axis wraps around a given range and how. Defaults to `[-180, 180]` in most
  \t// geographical CRSs. If `undefined`, the longitude axis does not wrap around.
  \t//
  \t// @property wrapLat: Number[]
  \t// Like `wrapLng`, but for the latitude (vertical) axis.

  \t// wrapLng: [min, max],
  \t// wrapLat: [min, max],

  \t// @property infinite: Boolean
  \t// If true, the coordinate space will be unbounded (infinite in both axes)
  \tinfinite: false,

  \t// @method wrapLatLng(latlng: LatLng): LatLng
  \t// Returns a `LatLng` where lat and lng has been wrapped according to the
  \t// CRS's `wrapLat` and `wrapLng` properties, if they are outside the CRS's bounds.
  \twrapLatLng: function (latlng) {
  \t\tvar lng = this.wrapLng ? wrapNum(latlng.lng, this.wrapLng, true) : latlng.lng,
  \t\t    lat = this.wrapLat ? wrapNum(latlng.lat, this.wrapLat, true) : latlng.lat,
  \t\t    alt = latlng.alt;

  \t\treturn new LatLng(lat, lng, alt);
  \t},

  \t// @method wrapLatLngBounds(bounds: LatLngBounds): LatLngBounds
  \t// Returns a `LatLngBounds` with the same size as the given one, ensuring
  \t// that its center is within the CRS's bounds.
  \t// Only accepts actual `L.LatLngBounds` instances, not arrays.
  \twrapLatLngBounds: function (bounds) {
  \t\tvar center = bounds.getCenter(),
  \t\t    newCenter = this.wrapLatLng(center),
  \t\t    latShift = center.lat - newCenter.lat,
  \t\t    lngShift = center.lng - newCenter.lng;

  \t\tif (latShift === 0 && lngShift === 0) {
  \t\t\treturn bounds;
  \t\t}

  \t\tvar sw = bounds.getSouthWest(),
  \t\t    ne = bounds.getNorthEast(),
  \t\t    newSw = new LatLng(sw.lat - latShift, sw.lng - lngShift),
  \t\t    newNe = new LatLng(ne.lat - latShift, ne.lng - lngShift);

  \t\treturn new LatLngBounds(newSw, newNe);
  \t}
  };

  /*
   * @namespace CRS
   * @crs L.CRS.Earth
   *
   * Serves as the base for CRS that are global such that they cover the earth.
   * Can only be used as the base for other CRS and cannot be used directly,
   * since it does not have a `code`, `projection` or `transformation`. `distance()` returns
   * meters.
   */

  var Earth = extend({}, CRS, {
  \twrapLng: [-180, 180],

  \t// Mean Earth Radius, as recommended for use by
  \t// the International Union of Geodesy and Geophysics,
  \t// see https://rosettacode.org/wiki/Haversine_formula
  \tR: 6371000,

  \t// distance between two geographical points using spherical law of cosines approximation
  \tdistance: function (latlng1, latlng2) {
  \t\tvar rad = Math.PI / 180,
  \t\t    lat1 = latlng1.lat * rad,
  \t\t    lat2 = latlng2.lat * rad,
  \t\t    sinDLat = Math.sin((latlng2.lat - latlng1.lat) * rad / 2),
  \t\t    sinDLon = Math.sin((latlng2.lng - latlng1.lng) * rad / 2),
  \t\t    a = sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon,
  \t\t    c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  \t\treturn this.R * c;
  \t}
  });

  /*
   * @namespace Projection
   * @projection L.Projection.SphericalMercator
   *
   * Spherical Mercator projection — the most common projection for online maps,
   * used by almost all free and commercial tile providers. Assumes that Earth is
   * a sphere. Used by the `EPSG:3857` CRS.
   */

  var earthRadius = 6378137;

  var SphericalMercator = {

  \tR: earthRadius,
  \tMAX_LATITUDE: 85.0511287798,

  \tproject: function (latlng) {
  \t\tvar d = Math.PI / 180,
  \t\t    max = this.MAX_LATITUDE,
  \t\t    lat = Math.max(Math.min(max, latlng.lat), -max),
  \t\t    sin = Math.sin(lat * d);

  \t\treturn new Point(
  \t\t\tthis.R * latlng.lng * d,
  \t\t\tthis.R * Math.log((1 + sin) / (1 - sin)) / 2);
  \t},

  \tunproject: function (point) {
  \t\tvar d = 180 / Math.PI;

  \t\treturn new LatLng(
  \t\t\t(2 * Math.atan(Math.exp(point.y / this.R)) - (Math.PI / 2)) * d,
  \t\t\tpoint.x * d / this.R);
  \t},

  \tbounds: (function () {
  \t\tvar d = earthRadius * Math.PI;
  \t\treturn new Bounds([-d, -d], [d, d]);
  \t})()
  };

  /*
   * @class Transformation
   * @aka L.Transformation
   *
   * Represents an affine transformation: a set of coefficients `a`, `b`, `c`, `d`
   * for transforming a point of a form `(x, y)` into `(a*x + b, c*y + d)` and doing
   * the reverse. Used by Leaflet in its projections code.
   *
   * @example
   *
   * ```js
   * var transformation = L.transformation(2, 5, -1, 10),
   * \tp = L.point(1, 2),
   * \tp2 = transformation.transform(p), //  L.point(7, 8)
   * \tp3 = transformation.untransform(p2); //  L.point(1, 2)
   * ```
   */


  // factory new L.Transformation(a: Number, b: Number, c: Number, d: Number)
  // Creates a `Transformation` object with the given coefficients.
  function Transformation(a, b, c, d) {
  \tif (isArray(a)) {
  \t\t// use array properties
  \t\tthis._a = a[0];
  \t\tthis._b = a[1];
  \t\tthis._c = a[2];
  \t\tthis._d = a[3];
  \t\treturn;
  \t}
  \tthis._a = a;
  \tthis._b = b;
  \tthis._c = c;
  \tthis._d = d;
  }

  Transformation.prototype = {
  \t// @method transform(point: Point, scale?: Number): Point
  \t// Returns a transformed point, optionally multiplied by the given scale.
  \t// Only accepts actual `L.Point` instances, not arrays.
  \ttransform: function (point, scale) { // (Point, Number) -> Point
  \t\treturn this._transform(point.clone(), scale);
  \t},

  \t// destructive transform (faster)
  \t_transform: function (point, scale) {
  \t\tscale = scale || 1;
  \t\tpoint.x = scale * (this._a * point.x + this._b);
  \t\tpoint.y = scale * (this._c * point.y + this._d);
  \t\treturn point;
  \t},

  \t// @method untransform(point: Point, scale?: Number): Point
  \t// Returns the reverse transformation of the given point, optionally divided
  \t// by the given scale. Only accepts actual `L.Point` instances, not arrays.
  \tuntransform: function (point, scale) {
  \t\tscale = scale || 1;
  \t\treturn new Point(
  \t\t        (point.x / scale - this._b) / this._a,
  \t\t        (point.y / scale - this._d) / this._c);
  \t}
  };

  // factory L.transformation(a: Number, b: Number, c: Number, d: Number)

  // @factory L.transformation(a: Number, b: Number, c: Number, d: Number)
  // Instantiates a Transformation object with the given coefficients.

  // @alternative
  // @factory L.transformation(coefficients: Array): Transformation
  // Expects an coefficients array of the form
  // `[a: Number, b: Number, c: Number, d: Number]`.

  function toTransformation(a, b, c, d) {
  \treturn new Transformation(a, b, c, d);
  }

  /*
   * @namespace CRS
   * @crs L.CRS.EPSG3857
   *
   * The most common CRS for online maps, used by almost all free and commercial
   * tile providers. Uses Spherical Mercator projection. Set in by default in
   * Map's `crs` option.
   */

  var EPSG3857 = extend({}, Earth, {
  \tcode: 'EPSG:3857',
  \tprojection: SphericalMercator,

  \ttransformation: (function () {
  \t\tvar scale = 0.5 / (Math.PI * SphericalMercator.R);
  \t\treturn toTransformation(scale, 0.5, -scale, 0.5);
  \t}())
  });

  var EPSG900913 = extend({}, EPSG3857, {
  \tcode: 'EPSG:900913'
  });

  // @namespace SVG; @section
  // There are several static functions which can be called without instantiating L.SVG:

  // @function create(name: String): SVGElement
  // Returns a instance of [SVGElement](https://developer.mozilla.org/docs/Web/API/SVGElement),
  // corresponding to the class name passed. For example, using 'line' will return
  // an instance of [SVGLineElement](https://developer.mozilla.org/docs/Web/API/SVGLineElement).
  function svgCreate(name) {
  \treturn document.createElementNS('http://www.w3.org/2000/svg', name);
  }

  // @function pointsToPath(rings: Point[], closed: Boolean): String
  // Generates a SVG path string for multiple rings, with each ring turning
  // into \"M..L..L..\" instructions
  function pointsToPath(rings, closed) {
  \tvar str = '',
  \ti, j, len, len2, points, p;

  \tfor (i = 0, len = rings.length; i < len; i++) {
  \t\tpoints = rings[i];

  \t\tfor (j = 0, len2 = points.length; j < len2; j++) {
  \t\t\tp = points[j];
  \t\t\tstr += (j ? 'L' : 'M') + p.x + ' ' + p.y;
  \t\t}

  \t\t// closes the ring for polygons; \"x\" is VML syntax
  \t\tstr += closed ? (Browser.svg ? 'z' : 'x') : '';
  \t}

  \t// SVG complains about empty path strings
  \treturn str || 'M0 0';
  }

  /*
   * @namespace Browser
   * @aka L.Browser
   *
   * A namespace with static properties for browser/feature detection used by Leaflet internally.
   *
   * @example
   *
   * ```js
   * if (L.Browser.ielt9) {
   *   alert('Upgrade your browser, dude!');
   * }
   * ```
   */

  var style = document.documentElement.style;

  // @property ie: Boolean; `true` for all Internet Explorer versions (not Edge).
  var ie = 'ActiveXObject' in window;

  // @property ielt9: Boolean; `true` for Internet Explorer versions less than 9.
  var ielt9 = ie && !document.addEventListener;

  // @property edge: Boolean; `true` for the Edge web browser.
  var edge = 'msLaunchUri' in navigator && !('documentMode' in document);

  // @property webkit: Boolean;
  // `true` for webkit-based browsers like Chrome and Safari (including mobile versions).
  var webkit = userAgentContains('webkit');

  // @property android: Boolean
  // **Deprecated.** `true` for any browser running on an Android platform.
  var android = userAgentContains('android');

  // @property android23: Boolean; **Deprecated.** `true` for browsers running on Android 2 or Android 3.
  var android23 = userAgentContains('android 2') || userAgentContains('android 3');

  /* See https://stackoverflow.com/a/17961266 for details on detecting stock Android */
  var webkitVer = parseInt(/WebKit\\/([0-9]+)|\$/.exec(navigator.userAgent)[1], 10); // also matches AppleWebKit
  // @property androidStock: Boolean; **Deprecated.** `true` for the Android stock browser (i.e. not Chrome)
  var androidStock = android && userAgentContains('Google') && webkitVer < 537 && !('AudioNode' in window);

  // @property opera: Boolean; `true` for the Opera browser
  var opera = !!window.opera;

  // @property chrome: Boolean; `true` for the Chrome browser.
  var chrome = !edge && userAgentContains('chrome');

  // @property gecko: Boolean; `true` for gecko-based browsers like Firefox.
  var gecko = userAgentContains('gecko') && !webkit && !opera && !ie;

  // @property safari: Boolean; `true` for the Safari browser.
  var safari = !chrome && userAgentContains('safari');

  var phantom = userAgentContains('phantom');

  // @property opera12: Boolean
  // `true` for the Opera browser supporting CSS transforms (version 12 or later).
  var opera12 = 'OTransition' in style;

  // @property win: Boolean; `true` when the browser is running in a Windows platform
  var win = navigator.platform.indexOf('Win') === 0;

  // @property ie3d: Boolean; `true` for all Internet Explorer versions supporting CSS transforms.
  var ie3d = ie && ('transition' in style);

  // @property webkit3d: Boolean; `true` for webkit-based browsers supporting CSS transforms.
  var webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()) && !android23;

  // @property gecko3d: Boolean; `true` for gecko-based browsers supporting CSS transforms.
  var gecko3d = 'MozPerspective' in style;

  // @property any3d: Boolean
  // `true` for all browsers supporting CSS transforms.
  var any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d) && !opera12 && !phantom;

  // @property mobile: Boolean; `true` for all browsers running in a mobile device.
  var mobile = typeof orientation !== 'undefined' || userAgentContains('mobile');

  // @property mobileWebkit: Boolean; `true` for all webkit-based browsers in a mobile device.
  var mobileWebkit = mobile && webkit;

  // @property mobileWebkit3d: Boolean
  // `true` for all webkit-based browsers in a mobile device supporting CSS transforms.
  var mobileWebkit3d = mobile && webkit3d;

  // @property msPointer: Boolean
  // `true` for browsers implementing the Microsoft touch events model (notably IE10).
  var msPointer = !window.PointerEvent && window.MSPointerEvent;

  // @property pointer: Boolean
  // `true` for all browsers supporting [pointer events](https://msdn.microsoft.com/en-us/library/dn433244%28v=vs.85%29.aspx).
  var pointer = !!(window.PointerEvent || msPointer);

  // @property touchNative: Boolean
  // `true` for all browsers supporting [touch events](https://developer.mozilla.org/docs/Web/API/Touch_events).
  // **This does not necessarily mean** that the browser is running in a computer with
  // a touchscreen, it only means that the browser is capable of understanding
  // touch events.
  var touchNative = 'ontouchstart' in window || !!window.TouchEvent;

  // @property touch: Boolean
  // `true` for all browsers supporting either [touch](#browser-touch) or [pointer](#browser-pointer) events.
  // Note: pointer events will be preferred (if available), and processed for all `touch*` listeners.
  var touch = !window.L_NO_TOUCH && (touchNative || pointer);

  // @property mobileOpera: Boolean; `true` for the Opera browser in a mobile device.
  var mobileOpera = mobile && opera;

  // @property mobileGecko: Boolean
  // `true` for gecko-based browsers running in a mobile device.
  var mobileGecko = mobile && gecko;

  // @property retina: Boolean
  // `true` for browsers on a high-resolution \"retina\" screen or on any screen when browser's display zoom is more than 100%.
  var retina = (window.devicePixelRatio || (window.screen.deviceXDPI / window.screen.logicalXDPI)) > 1;

  // @property passiveEvents: Boolean
  // `true` for browsers that support passive events.
  var passiveEvents = (function () {
  \tvar supportsPassiveOption = false;
  \ttry {
  \t\tvar opts = Object.defineProperty({}, 'passive', {
  \t\t\tget: function () { // eslint-disable-line getter-return
  \t\t\t\tsupportsPassiveOption = true;
  \t\t\t}
  \t\t});
  \t\twindow.addEventListener('testPassiveEventSupport', falseFn, opts);
  \t\twindow.removeEventListener('testPassiveEventSupport', falseFn, opts);
  \t} catch (e) {
  \t\t// Errors can safely be ignored since this is only a browser support test.
  \t}
  \treturn supportsPassiveOption;
  }());

  // @property canvas: Boolean
  // `true` when the browser supports [`<canvas>`](https://developer.mozilla.org/docs/Web/API/Canvas_API).
  var canvas\$1 = (function () {
  \treturn !!document.createElement('canvas').getContext;
  }());

  // @property svg: Boolean
  // `true` when the browser supports [SVG](https://developer.mozilla.org/docs/Web/SVG).
  var svg\$1 = !!(document.createElementNS && svgCreate('svg').createSVGRect);

  var inlineSvg = !!svg\$1 && (function () {
  \tvar div = document.createElement('div');
  \tdiv.innerHTML = '<svg/>';
  \treturn (div.firstChild && div.firstChild.namespaceURI) === 'http://www.w3.org/2000/svg';
  })();

  // @property vml: Boolean
  // `true` if the browser supports [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language).
  var vml = !svg\$1 && (function () {
  \ttry {
  \t\tvar div = document.createElement('div');
  \t\tdiv.innerHTML = '<v:shape adj=\"1\"/>';

  \t\tvar shape = div.firstChild;
  \t\tshape.style.behavior = 'url(#default#VML)';

  \t\treturn shape && (typeof shape.adj === 'object');

  \t} catch (e) {
  \t\treturn false;
  \t}
  }());


  // @property mac: Boolean; `true` when the browser is running in a Mac platform
  var mac = navigator.platform.indexOf('Mac') === 0;

  // @property mac: Boolean; `true` when the browser is running in a Linux platform
  var linux = navigator.platform.indexOf('Linux') === 0;

  function userAgentContains(str) {
  \treturn navigator.userAgent.toLowerCase().indexOf(str) >= 0;
  }


  var Browser = {
  \tie: ie,
  \tielt9: ielt9,
  \tedge: edge,
  \twebkit: webkit,
  \tandroid: android,
  \tandroid23: android23,
  \tandroidStock: androidStock,
  \topera: opera,
  \tchrome: chrome,
  \tgecko: gecko,
  \tsafari: safari,
  \tphantom: phantom,
  \topera12: opera12,
  \twin: win,
  \tie3d: ie3d,
  \twebkit3d: webkit3d,
  \tgecko3d: gecko3d,
  \tany3d: any3d,
  \tmobile: mobile,
  \tmobileWebkit: mobileWebkit,
  \tmobileWebkit3d: mobileWebkit3d,
  \tmsPointer: msPointer,
  \tpointer: pointer,
  \ttouch: touch,
  \ttouchNative: touchNative,
  \tmobileOpera: mobileOpera,
  \tmobileGecko: mobileGecko,
  \tretina: retina,
  \tpassiveEvents: passiveEvents,
  \tcanvas: canvas\$1,
  \tsvg: svg\$1,
  \tvml: vml,
  \tinlineSvg: inlineSvg,
  \tmac: mac,
  \tlinux: linux
  };

  /*
   * Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices.
   */

  var POINTER_DOWN =   Browser.msPointer ? 'MSPointerDown'   : 'pointerdown';
  var POINTER_MOVE =   Browser.msPointer ? 'MSPointerMove'   : 'pointermove';
  var POINTER_UP =     Browser.msPointer ? 'MSPointerUp'     : 'pointerup';
  var POINTER_CANCEL = Browser.msPointer ? 'MSPointerCancel' : 'pointercancel';
  var pEvent = {
  \ttouchstart  : POINTER_DOWN,
  \ttouchmove   : POINTER_MOVE,
  \ttouchend    : POINTER_UP,
  \ttouchcancel : POINTER_CANCEL
  };
  var handle = {
  \ttouchstart  : _onPointerStart,
  \ttouchmove   : _handlePointer,
  \ttouchend    : _handlePointer,
  \ttouchcancel : _handlePointer
  };
  var _pointers = {};
  var _pointerDocListener = false;

  // Provides a touch events wrapper for (ms)pointer events.
  // ref https://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890

  function addPointerListener(obj, type, handler) {
  \tif (type === 'touchstart') {
  \t\t_addPointerDocListener();
  \t}
  \tif (!handle[type]) {
  \t\tconsole.warn('wrong event specified:', type);
  \t\treturn falseFn;
  \t}
  \thandler = handle[type].bind(this, handler);
  \tobj.addEventListener(pEvent[type], handler, false);
  \treturn handler;
  }

  function removePointerListener(obj, type, handler) {
  \tif (!pEvent[type]) {
  \t\tconsole.warn('wrong event specified:', type);
  \t\treturn;
  \t}
  \tobj.removeEventListener(pEvent[type], handler, false);
  }

  function _globalPointerDown(e) {
  \t_pointers[e.pointerId] = e;
  }

  function _globalPointerMove(e) {
  \tif (_pointers[e.pointerId]) {
  \t\t_pointers[e.pointerId] = e;
  \t}
  }

  function _globalPointerUp(e) {
  \tdelete _pointers[e.pointerId];
  }

  function _addPointerDocListener() {
  \t// need to keep track of what pointers and how many are active to provide e.touches emulation
  \tif (!_pointerDocListener) {
  \t\t// we listen document as any drags that end by moving the touch off the screen get fired there
  \t\tdocument.addEventListener(POINTER_DOWN, _globalPointerDown, true);
  \t\tdocument.addEventListener(POINTER_MOVE, _globalPointerMove, true);
  \t\tdocument.addEventListener(POINTER_UP, _globalPointerUp, true);
  \t\tdocument.addEventListener(POINTER_CANCEL, _globalPointerUp, true);

  \t\t_pointerDocListener = true;
  \t}
  }

  function _handlePointer(handler, e) {
  \tif (e.pointerType === (e.MSPOINTER_TYPE_MOUSE || 'mouse')) { return; }

  \te.touches = [];
  \tfor (var i in _pointers) {
  \t\te.touches.push(_pointers[i]);
  \t}
  \te.changedTouches = [e];

  \thandler(e);
  }

  function _onPointerStart(handler, e) {
  \t// IE10 specific: MsTouch needs preventDefault. See #2000
  \tif (e.MSPOINTER_TYPE_TOUCH && e.pointerType === e.MSPOINTER_TYPE_TOUCH) {
  \t\tpreventDefault(e);
  \t}
  \t_handlePointer(handler, e);
  }

  /*
   * Extends the event handling code with double tap support for mobile browsers.
   *
   * Note: currently most browsers fire native dblclick, with only a few exceptions
   * (see https://github.com/Leaflet/Leaflet/issues/7012#issuecomment-595087386)
   */

  function makeDblclick(event) {
  \t// in modern browsers `type` cannot be just overridden:
  \t// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Getter_only
  \tvar newEvent = {},
  \t    prop, i;
  \tfor (i in event) {
  \t\tprop = event[i];
  \t\tnewEvent[i] = prop && prop.bind ? prop.bind(event) : prop;
  \t}
  \tevent = newEvent;
  \tnewEvent.type = 'dblclick';
  \tnewEvent.detail = 2;
  \tnewEvent.isTrusted = false;
  \tnewEvent._simulated = true; // for debug purposes
  \treturn newEvent;
  }

  var delay = 200;
  function addDoubleTapListener(obj, handler) {
  \t// Most browsers handle double tap natively
  \tobj.addEventListener('dblclick', handler);

  \t// On some platforms the browser doesn't fire native dblclicks for touch events.
  \t// It seems that in all such cases `detail` property of `click` event is always `1`.
  \t// So here we rely on that fact to avoid excessive 'dblclick' simulation when not needed.
  \tvar last = 0,
  \t    detail;
  \tfunction simDblclick(e) {
  \t\tif (e.detail !== 1) {
  \t\t\tdetail = e.detail; // keep in sync to avoid false dblclick in some cases
  \t\t\treturn;
  \t\t}

  \t\tif (e.pointerType === 'mouse' ||
  \t\t\t(e.sourceCapabilities && !e.sourceCapabilities.firesTouchEvents)) {

  \t\t\treturn;
  \t\t}

  \t\t// When clicking on an <input>, the browser generates a click on its
  \t\t// <label> (and vice versa) triggering two clicks in quick succession.
  \t\t// This ignores clicks on elements which are a label with a 'for'
  \t\t// attribute (or children of such a label), but not children of
  \t\t// a <input>.
  \t\tvar path = getPropagationPath(e);
  \t\tif (path.some(function (el) {
  \t\t\treturn el instanceof HTMLLabelElement && el.attributes.for;
  \t\t}) &&
  \t\t\t!path.some(function (el) {
  \t\t\t\treturn (
  \t\t\t\t\tel instanceof HTMLInputElement ||
  \t\t\t\t\tel instanceof HTMLSelectElement
  \t\t\t\t);
  \t\t\t})
  \t\t) {
  \t\t\treturn;
  \t\t}

  \t\tvar now = Date.now();
  \t\tif (now - last <= delay) {
  \t\t\tdetail++;
  \t\t\tif (detail === 2) {
  \t\t\t\thandler(makeDblclick(e));
  \t\t\t}
  \t\t} else {
  \t\t\tdetail = 1;
  \t\t}
  \t\tlast = now;
  \t}

  \tobj.addEventListener('click', simDblclick);

  \treturn {
  \t\tdblclick: handler,
  \t\tsimDblclick: simDblclick
  \t};
  }

  function removeDoubleTapListener(obj, handlers) {
  \tobj.removeEventListener('dblclick', handlers.dblclick);
  \tobj.removeEventListener('click', handlers.simDblclick);
  }

  /*
   * @namespace DomUtil
   *
   * Utility functions to work with the [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model)
   * tree, used by Leaflet internally.
   *
   * Most functions expecting or returning a `HTMLElement` also work for
   * SVG elements. The only difference is that classes refer to CSS classes
   * in HTML and SVG classes in SVG.
   */


  // @property TRANSFORM: String
  // Vendor-prefixed transform style name (e.g. `'webkitTransform'` for WebKit).
  var TRANSFORM = testProp(
  \t['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform']);

  // webkitTransition comes first because some browser versions that drop vendor prefix don't do
  // the same for the transitionend event, in particular the Android 4.1 stock browser

  // @property TRANSITION: String
  // Vendor-prefixed transition style name.
  var TRANSITION = testProp(
  \t['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']);

  // @property TRANSITION_END: String
  // Vendor-prefixed transitionend event name.
  var TRANSITION_END =
  \tTRANSITION === 'webkitTransition' || TRANSITION === 'OTransition' ? TRANSITION + 'End' : 'transitionend';


  // @function get(id: String|HTMLElement): HTMLElement
  // Returns an element given its DOM id, or returns the element itself
  // if it was passed directly.
  function get(id) {
  \treturn typeof id === 'string' ? document.getElementById(id) : id;
  }

  // @function getStyle(el: HTMLElement, styleAttrib: String): String
  // Returns the value for a certain style attribute on an element,
  // including computed values or values set through CSS.
  function getStyle(el, style) {
  \tvar value = el.style[style] || (el.currentStyle && el.currentStyle[style]);

  \tif ((!value || value === 'auto') && document.defaultView) {
  \t\tvar css = document.defaultView.getComputedStyle(el, null);
  \t\tvalue = css ? css[style] : null;
  \t}
  \treturn value === 'auto' ? null : value;
  }

  // @function create(tagName: String, className?: String, container?: HTMLElement): HTMLElement
  // Creates an HTML element with `tagName`, sets its class to `className`, and optionally appends it to `container` element.
  function create\$1(tagName, className, container) {
  \tvar el = document.createElement(tagName);
  \tel.className = className || '';

  \tif (container) {
  \t\tcontainer.appendChild(el);
  \t}
  \treturn el;
  }

  // @function remove(el: HTMLElement)
  // Removes `el` from its parent element
  function remove(el) {
  \tvar parent = el.parentNode;
  \tif (parent) {
  \t\tparent.removeChild(el);
  \t}
  }

  // @function empty(el: HTMLElement)
  // Removes all of `el`'s children elements from `el`
  function empty(el) {
  \twhile (el.firstChild) {
  \t\tel.removeChild(el.firstChild);
  \t}
  }

  // @function toFront(el: HTMLElement)
  // Makes `el` the last child of its parent, so it renders in front of the other children.
  function toFront(el) {
  \tvar parent = el.parentNode;
  \tif (parent && parent.lastChild !== el) {
  \t\tparent.appendChild(el);
  \t}
  }

  // @function toBack(el: HTMLElement)
  // Makes `el` the first child of its parent, so it renders behind the other children.
  function toBack(el) {
  \tvar parent = el.parentNode;
  \tif (parent && parent.firstChild !== el) {
  \t\tparent.insertBefore(el, parent.firstChild);
  \t}
  }

  // @function hasClass(el: HTMLElement, name: String): Boolean
  // Returns `true` if the element's class attribute contains `name`.
  function hasClass(el, name) {
  \tif (el.classList !== undefined) {
  \t\treturn el.classList.contains(name);
  \t}
  \tvar className = getClass(el);
  \treturn className.length > 0 && new RegExp('(^|\\\\s)' + name + '(\\\\s|\$)').test(className);
  }

  // @function addClass(el: HTMLElement, name: String)
  // Adds `name` to the element's class attribute.
  function addClass(el, name) {
  \tif (el.classList !== undefined) {
  \t\tvar classes = splitWords(name);
  \t\tfor (var i = 0, len = classes.length; i < len; i++) {
  \t\t\tel.classList.add(classes[i]);
  \t\t}
  \t} else if (!hasClass(el, name)) {
  \t\tvar className = getClass(el);
  \t\tsetClass(el, (className ? className + ' ' : '') + name);
  \t}
  }

  // @function removeClass(el: HTMLElement, name: String)
  // Removes `name` from the element's class attribute.
  function removeClass(el, name) {
  \tif (el.classList !== undefined) {
  \t\tel.classList.remove(name);
  \t} else {
  \t\tsetClass(el, trim((' ' + getClass(el) + ' ').replace(' ' + name + ' ', ' ')));
  \t}
  }

  // @function setClass(el: HTMLElement, name: String)
  // Sets the element's class.
  function setClass(el, name) {
  \tif (el.className.baseVal === undefined) {
  \t\tel.className = name;
  \t} else {
  \t\t// in case of SVG element
  \t\tel.className.baseVal = name;
  \t}
  }

  // @function getClass(el: HTMLElement): String
  // Returns the element's class.
  function getClass(el) {
  \t// Check if the element is an SVGElementInstance and use the correspondingElement instead
  \t// (Required for linked SVG elements in IE11.)
  \tif (el.correspondingElement) {
  \t\tel = el.correspondingElement;
  \t}
  \treturn el.className.baseVal === undefined ? el.className : el.className.baseVal;
  }

  // @function setOpacity(el: HTMLElement, opacity: Number)
  // Set the opacity of an element (including old IE support).
  // `opacity` must be a number from `0` to `1`.
  function setOpacity(el, value) {
  \tif ('opacity' in el.style) {
  \t\tel.style.opacity = value;
  \t} else if ('filter' in el.style) {
  \t\t_setOpacityIE(el, value);
  \t}
  }

  function _setOpacityIE(el, value) {
  \tvar filter = false,
  \t    filterName = 'DXImageTransform.Microsoft.Alpha';

  \t// filters collection throws an error if we try to retrieve a filter that doesn't exist
  \ttry {
  \t\tfilter = el.filters.item(filterName);
  \t} catch (e) {
  \t\t// don't set opacity to 1 if we haven't already set an opacity,
  \t\t// it isn't needed and breaks transparent pngs.
  \t\tif (value === 1) { return; }
  \t}

  \tvalue = Math.round(value * 100);

  \tif (filter) {
  \t\tfilter.Enabled = (value !== 100);
  \t\tfilter.Opacity = value;
  \t} else {
  \t\tel.style.filter += ' progid:' + filterName + '(opacity=' + value + ')';
  \t}
  }

  // @function testProp(props: String[]): String|false
  // Goes through the array of style names and returns the first name
  // that is a valid style name for an element. If no such name is found,
  // it returns false. Useful for vendor-prefixed styles like `transform`.
  function testProp(props) {
  \tvar style = document.documentElement.style;

  \tfor (var i = 0; i < props.length; i++) {
  \t\tif (props[i] in style) {
  \t\t\treturn props[i];
  \t\t}
  \t}
  \treturn false;
  }

  // @function setTransform(el: HTMLElement, offset: Point, scale?: Number)
  // Resets the 3D CSS transform of `el` so it is translated by `offset` pixels
  // and optionally scaled by `scale`. Does not have an effect if the
  // browser doesn't support 3D CSS transforms.
  function setTransform(el, offset, scale) {
  \tvar pos = offset || new Point(0, 0);

  \tel.style[TRANSFORM] =
  \t\t(Browser.ie3d ?
  \t\t\t'translate(' + pos.x + 'px,' + pos.y + 'px)' :
  \t\t\t'translate3d(' + pos.x + 'px,' + pos.y + 'px,0)') +
  \t\t(scale ? ' scale(' + scale + ')' : '');
  }

  // @function setPosition(el: HTMLElement, position: Point)
  // Sets the position of `el` to coordinates specified by `position`,
  // using CSS translate or top/left positioning depending on the browser
  // (used by Leaflet internally to position its layers).
  function setPosition(el, point) {

  \t/*eslint-disable */
  \tel._leaflet_pos = point;
  \t/* eslint-enable */

  \tif (Browser.any3d) {
  \t\tsetTransform(el, point);
  \t} else {
  \t\tel.style.left = point.x + 'px';
  \t\tel.style.top = point.y + 'px';
  \t}
  }

  // @function getPosition(el: HTMLElement): Point
  // Returns the coordinates of an element previously positioned with setPosition.
  function getPosition(el) {
  \t// this method is only used for elements previously positioned using setPosition,
  \t// so it's safe to cache the position for performance

  \treturn el._leaflet_pos || new Point(0, 0);
  }

  // @function disableTextSelection()
  // Prevents the user from generating `selectstart` DOM events, usually generated
  // when the user drags the mouse through a page with text. Used internally
  // by Leaflet to override the behaviour of any click-and-drag interaction on
  // the map. Affects drag interactions on the whole document.

  // @function enableTextSelection()
  // Cancels the effects of a previous [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection).
  var disableTextSelection;
  var enableTextSelection;
  var _userSelect;
  if ('onselectstart' in document) {
  \tdisableTextSelection = function () {
  \t\ton(window, 'selectstart', preventDefault);
  \t};
  \tenableTextSelection = function () {
  \t\toff(window, 'selectstart', preventDefault);
  \t};
  } else {
  \tvar userSelectProperty = testProp(
  \t\t['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']);

  \tdisableTextSelection = function () {
  \t\tif (userSelectProperty) {
  \t\t\tvar style = document.documentElement.style;
  \t\t\t_userSelect = style[userSelectProperty];
  \t\t\tstyle[userSelectProperty] = 'none';
  \t\t}
  \t};
  \tenableTextSelection = function () {
  \t\tif (userSelectProperty) {
  \t\t\tdocument.documentElement.style[userSelectProperty] = _userSelect;
  \t\t\t_userSelect = undefined;
  \t\t}
  \t};
  }

  // @function disableImageDrag()
  // As [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection), but
  // for `dragstart` DOM events, usually generated when the user drags an image.
  function disableImageDrag() {
  \ton(window, 'dragstart', preventDefault);
  }

  // @function enableImageDrag()
  // Cancels the effects of a previous [`L.DomUtil.disableImageDrag`](#domutil-disabletextselection).
  function enableImageDrag() {
  \toff(window, 'dragstart', preventDefault);
  }

  var _outlineElement, _outlineStyle;
  // @function preventOutline(el: HTMLElement)
  // Makes the [outline](https://developer.mozilla.org/docs/Web/CSS/outline)
  // of the element `el` invisible. Used internally by Leaflet to prevent
  // focusable elements from displaying an outline when the user performs a
  // drag interaction on them.
  function preventOutline(element) {
  \twhile (element.tabIndex === -1) {
  \t\telement = element.parentNode;
  \t}
  \tif (!element.style) { return; }
  \trestoreOutline();
  \t_outlineElement = element;
  \t_outlineStyle = element.style.outlineStyle;
  \telement.style.outlineStyle = 'none';
  \ton(window, 'keydown', restoreOutline);
  }

  // @function restoreOutline()
  // Cancels the effects of a previous [`L.DomUtil.preventOutline`]().
  function restoreOutline() {
  \tif (!_outlineElement) { return; }
  \t_outlineElement.style.outlineStyle = _outlineStyle;
  \t_outlineElement = undefined;
  \t_outlineStyle = undefined;
  \toff(window, 'keydown', restoreOutline);
  }

  // @function getSizedParentNode(el: HTMLElement): HTMLElement
  // Finds the closest parent node which size (width and height) is not null.
  function getSizedParentNode(element) {
  \tdo {
  \t\telement = element.parentNode;
  \t} while ((!element.offsetWidth || !element.offsetHeight) && element !== document.body);
  \treturn element;
  }

  // @function getScale(el: HTMLElement): Object
  // Computes the CSS scale currently applied on the element.
  // Returns an object with `x` and `y` members as horizontal and vertical scales respectively,
  // and `boundingClientRect` as the result of [`getBoundingClientRect()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect).
  function getScale(element) {
  \tvar rect = element.getBoundingClientRect(); // Read-only in old browsers.

  \treturn {
  \t\tx: rect.width / element.offsetWidth || 1,
  \t\ty: rect.height / element.offsetHeight || 1,
  \t\tboundingClientRect: rect
  \t};
  }

  var DomUtil = {
    __proto__: null,
    TRANSFORM: TRANSFORM,
    TRANSITION: TRANSITION,
    TRANSITION_END: TRANSITION_END,
    get: get,
    getStyle: getStyle,
    create: create\$1,
    remove: remove,
    empty: empty,
    toFront: toFront,
    toBack: toBack,
    hasClass: hasClass,
    addClass: addClass,
    removeClass: removeClass,
    setClass: setClass,
    getClass: getClass,
    setOpacity: setOpacity,
    testProp: testProp,
    setTransform: setTransform,
    setPosition: setPosition,
    getPosition: getPosition,
    get disableTextSelection () { return disableTextSelection; },
    get enableTextSelection () { return enableTextSelection; },
    disableImageDrag: disableImageDrag,
    enableImageDrag: enableImageDrag,
    preventOutline: preventOutline,
    restoreOutline: restoreOutline,
    getSizedParentNode: getSizedParentNode,
    getScale: getScale
  };

  /*
   * @namespace DomEvent
   * Utility functions to work with the [DOM events](https://developer.mozilla.org/docs/Web/API/Event), used by Leaflet internally.
   */

  // Inspired by John Resig, Dean Edwards and YUI addEvent implementations.

  // @function on(el: HTMLElement, types: String, fn: Function, context?: Object): this
  // Adds a listener function (`fn`) to a particular DOM event type of the
  // element `el`. You can optionally specify the context of the listener
  // (object the `this` keyword will point to). You can also pass several
  // space-separated types (e.g. `'click dblclick'`).

  // @alternative
  // @function on(el: HTMLElement, eventMap: Object, context?: Object): this
  // Adds a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}`
  function on(obj, types, fn, context) {

  \tif (types && typeof types === 'object') {
  \t\tfor (var type in types) {
  \t\t\taddOne(obj, type, types[type], fn);
  \t\t}
  \t} else {
  \t\ttypes = splitWords(types);

  \t\tfor (var i = 0, len = types.length; i < len; i++) {
  \t\t\taddOne(obj, types[i], fn, context);
  \t\t}
  \t}

  \treturn this;
  }

  var eventsKey = '_leaflet_events';

  // @function off(el: HTMLElement, types: String, fn: Function, context?: Object): this
  // Removes a previously added listener function.
  // Note that if you passed a custom context to on, you must pass the same
  // context to `off` in order to remove the listener.

  // @alternative
  // @function off(el: HTMLElement, eventMap: Object, context?: Object): this
  // Removes a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}`

  // @alternative
  // @function off(el: HTMLElement, types: String): this
  // Removes all previously added listeners of given types.

  // @alternative
  // @function off(el: HTMLElement): this
  // Removes all previously added listeners from given HTMLElement
  function off(obj, types, fn, context) {

  \tif (arguments.length === 1) {
  \t\tbatchRemove(obj);
  \t\tdelete obj[eventsKey];

  \t} else if (types && typeof types === 'object') {
  \t\tfor (var type in types) {
  \t\t\tremoveOne(obj, type, types[type], fn);
  \t\t}

  \t} else {
  \t\ttypes = splitWords(types);

  \t\tif (arguments.length === 2) {
  \t\t\tbatchRemove(obj, function (type) {
  \t\t\t\treturn indexOf(types, type) !== -1;
  \t\t\t});
  \t\t} else {
  \t\t\tfor (var i = 0, len = types.length; i < len; i++) {
  \t\t\t\tremoveOne(obj, types[i], fn, context);
  \t\t\t}
  \t\t}
  \t}

  \treturn this;
  }

  function batchRemove(obj, filterFn) {
  \tfor (var id in obj[eventsKey]) {
  \t\tvar type = id.split(/\\d/)[0];
  \t\tif (!filterFn || filterFn(type)) {
  \t\t\tremoveOne(obj, type, null, null, id);
  \t\t}
  \t}
  }

  var mouseSubst = {
  \tmouseenter: 'mouseover',
  \tmouseleave: 'mouseout',
  \twheel: !('onwheel' in window) && 'mousewheel'
  };

  function addOne(obj, type, fn, context) {
  \tvar id = type + stamp(fn) + (context ? '_' + stamp(context) : '');

  \tif (obj[eventsKey] && obj[eventsKey][id]) { return this; }

  \tvar handler = function (e) {
  \t\treturn fn.call(context || obj, e || window.event);
  \t};

  \tvar originalHandler = handler;

  \tif (!Browser.touchNative && Browser.pointer && type.indexOf('touch') === 0) {
  \t\t// Needs DomEvent.Pointer.js
  \t\thandler = addPointerListener(obj, type, handler);

  \t} else if (Browser.touch && (type === 'dblclick')) {
  \t\thandler = addDoubleTapListener(obj, handler);

  \t} else if ('addEventListener' in obj) {

  \t\tif (type === 'touchstart' || type === 'touchmove' || type === 'wheel' ||  type === 'mousewheel') {
  \t\t\tobj.addEventListener(mouseSubst[type] || type, handler, Browser.passiveEvents ? {passive: false} : false);

  \t\t} else if (type === 'mouseenter' || type === 'mouseleave') {
  \t\t\thandler = function (e) {
  \t\t\t\te = e || window.event;
  \t\t\t\tif (isExternalTarget(obj, e)) {
  \t\t\t\t\toriginalHandler(e);
  \t\t\t\t}
  \t\t\t};
  \t\t\tobj.addEventListener(mouseSubst[type], handler, false);

  \t\t} else {
  \t\t\tobj.addEventListener(type, originalHandler, false);
  \t\t}

  \t} else {
  \t\tobj.attachEvent('on' + type, handler);
  \t}

  \tobj[eventsKey] = obj[eventsKey] || {};
  \tobj[eventsKey][id] = handler;
  }

  function removeOne(obj, type, fn, context, id) {
  \tid = id || type + stamp(fn) + (context ? '_' + stamp(context) : '');
  \tvar handler = obj[eventsKey] && obj[eventsKey][id];

  \tif (!handler) { return this; }

  \tif (!Browser.touchNative && Browser.pointer && type.indexOf('touch') === 0) {
  \t\tremovePointerListener(obj, type, handler);

  \t} else if (Browser.touch && (type === 'dblclick')) {
  \t\tremoveDoubleTapListener(obj, handler);

  \t} else if ('removeEventListener' in obj) {

  \t\tobj.removeEventListener(mouseSubst[type] || type, handler, false);

  \t} else {
  \t\tobj.detachEvent('on' + type, handler);
  \t}

  \tobj[eventsKey][id] = null;
  }

  // @function stopPropagation(ev: DOMEvent): this
  // Stop the given event from propagation to parent elements. Used inside the listener functions:
  // ```js
  // L.DomEvent.on(div, 'click', function (ev) {
  // \tL.DomEvent.stopPropagation(ev);
  // });
  // ```
  function stopPropagation(e) {

  \tif (e.stopPropagation) {
  \t\te.stopPropagation();
  \t} else if (e.originalEvent) {  // In case of Leaflet event.
  \t\te.originalEvent._stopped = true;
  \t} else {
  \t\te.cancelBubble = true;
  \t}

  \treturn this;
  }

  // @function disableScrollPropagation(el: HTMLElement): this
  // Adds `stopPropagation` to the element's `'wheel'` events (plus browser variants).
  function disableScrollPropagation(el) {
  \taddOne(el, 'wheel', stopPropagation);
  \treturn this;
  }

  // @function disableClickPropagation(el: HTMLElement): this
  // Adds `stopPropagation` to the element's `'click'`, `'dblclick'`, `'contextmenu'`,
  // `'mousedown'` and `'touchstart'` events (plus browser variants).
  function disableClickPropagation(el) {
  \ton(el, 'mousedown touchstart dblclick contextmenu', stopPropagation);
  \tel['_leaflet_disable_click'] = true;
  \treturn this;
  }

  // @function preventDefault(ev: DOMEvent): this
  // Prevents the default action of the DOM Event `ev` from happening (such as
  // following a link in the href of the a element, or doing a POST request
  // with page reload when a `<form>` is submitted).
  // Use it inside listener functions.
  function preventDefault(e) {
  \tif (e.preventDefault) {
  \t\te.preventDefault();
  \t} else {
  \t\te.returnValue = false;
  \t}
  \treturn this;
  }

  // @function stop(ev: DOMEvent): this
  // Does `stopPropagation` and `preventDefault` at the same time.
  function stop(e) {
  \tpreventDefault(e);
  \tstopPropagation(e);
  \treturn this;
  }

  // @function getPropagationPath(ev: DOMEvent): Array
  // Compatibility polyfill for [`Event.composedPath()`](https://developer.mozilla.org/en-US/docs/Web/API/Event/composedPath).
  // Returns an array containing the `HTMLElement`s that the given DOM event
  // should propagate to (if not stopped).
  function getPropagationPath(ev) {
  \tif (ev.composedPath) {
  \t\treturn ev.composedPath();
  \t}

  \tvar path = [];
  \tvar el = ev.target;

  \twhile (el) {
  \t\tpath.push(el);
  \t\tel = el.parentNode;
  \t}
  \treturn path;
  }


  // @function getMousePosition(ev: DOMEvent, container?: HTMLElement): Point
  // Gets normalized mouse position from a DOM event relative to the
  // `container` (border excluded) or to the whole page if not specified.
  function getMousePosition(e, container) {
  \tif (!container) {
  \t\treturn new Point(e.clientX, e.clientY);
  \t}

  \tvar scale = getScale(container),
  \t    offset = scale.boundingClientRect; // left and top  values are in page scale (like the event clientX/Y)

  \treturn new Point(
  \t\t// offset.left/top values are in page scale (like clientX/Y),
  \t\t// whereas clientLeft/Top (border width) values are the original values (before CSS scale applies).
  \t\t(e.clientX - offset.left) / scale.x - container.clientLeft,
  \t\t(e.clientY - offset.top) / scale.y - container.clientTop
  \t);
  }


  //  except , Safari and
  // We need double the scroll pixels (see #7403 and #4538) for all Browsers
  // except OSX (Mac) -> 3x, Chrome running on Linux 1x

  var wheelPxFactor =
  \t(Browser.linux && Browser.chrome) ? window.devicePixelRatio :
  \tBrowser.mac ? window.devicePixelRatio * 3 :
  \twindow.devicePixelRatio > 0 ? 2 * window.devicePixelRatio : 1;
  // @function getWheelDelta(ev: DOMEvent): Number
  // Gets normalized wheel delta from a wheel DOM event, in vertical
  // pixels scrolled (negative if scrolling down).
  // Events from pointing devices without precise scrolling are mapped to
  // a best guess of 60 pixels.
  function getWheelDelta(e) {
  \treturn (Browser.edge) ? e.wheelDeltaY / 2 : // Don't trust window-geometry-based delta
  \t       (e.deltaY && e.deltaMode === 0) ? -e.deltaY / wheelPxFactor : // Pixels
  \t       (e.deltaY && e.deltaMode === 1) ? -e.deltaY * 20 : // Lines
  \t       (e.deltaY && e.deltaMode === 2) ? -e.deltaY * 60 : // Pages
  \t       (e.deltaX || e.deltaZ) ? 0 :\t// Skip horizontal/depth wheel events
  \t       e.wheelDelta ? (e.wheelDeltaY || e.wheelDelta) / 2 : // Legacy IE pixels
  \t       (e.detail && Math.abs(e.detail) < 32765) ? -e.detail * 20 : // Legacy Moz lines
  \t       e.detail ? e.detail / -32765 * 60 : // Legacy Moz pages
  \t       0;
  }

  // check if element really left/entered the event target (for mouseenter/mouseleave)
  function isExternalTarget(el, e) {

  \tvar related = e.relatedTarget;

  \tif (!related) { return true; }

  \ttry {
  \t\twhile (related && (related !== el)) {
  \t\t\trelated = related.parentNode;
  \t\t}
  \t} catch (err) {
  \t\treturn false;
  \t}
  \treturn (related !== el);
  }

  var DomEvent = {
    __proto__: null,
    on: on,
    off: off,
    stopPropagation: stopPropagation,
    disableScrollPropagation: disableScrollPropagation,
    disableClickPropagation: disableClickPropagation,
    preventDefault: preventDefault,
    stop: stop,
    getPropagationPath: getPropagationPath,
    getMousePosition: getMousePosition,
    getWheelDelta: getWheelDelta,
    isExternalTarget: isExternalTarget,
    addListener: on,
    removeListener: off
  };

  /*
   * @class PosAnimation
   * @aka L.PosAnimation
   * @inherits Evented
   * Used internally for panning animations, utilizing CSS3 Transitions for modern browsers and a timer fallback for IE6-9.
   *
   * @example
   * ```js
   * var myPositionMarker = L.marker([48.864716, 2.294694]).addTo(map);
   *
   * myPositionMarker.on(\"click\", function() {
   * \tvar pos = map.latLngToLayerPoint(myPositionMarker.getLatLng());
   * \tpos.y -= 25;
   * \tvar fx = new L.PosAnimation();
   *
   * \tfx.once('end',function() {
   * \t\tpos.y += 25;
   * \t\tfx.run(myPositionMarker._icon, pos, 0.8);
   * \t});
   *
   * \tfx.run(myPositionMarker._icon, pos, 0.3);
   * });
   *
   * ```
   *
   * @constructor L.PosAnimation()
   * Creates a `PosAnimation` object.
   *
   */

  var PosAnimation = Evented.extend({

  \t// @method run(el: HTMLElement, newPos: Point, duration?: Number, easeLinearity?: Number)
  \t// Run an animation of a given element to a new position, optionally setting
  \t// duration in seconds (`0.25` by default) and easing linearity factor (3rd
  \t// argument of the [cubic bezier curve](https://cubic-bezier.com/#0,0,.5,1),
  \t// `0.5` by default).
  \trun: function (el, newPos, duration, easeLinearity) {
  \t\tthis.stop();

  \t\tthis._el = el;
  \t\tthis._inProgress = true;
  \t\tthis._duration = duration || 0.25;
  \t\tthis._easeOutPower = 1 / Math.max(easeLinearity || 0.5, 0.2);

  \t\tthis._startPos = getPosition(el);
  \t\tthis._offset = newPos.subtract(this._startPos);
  \t\tthis._startTime = +new Date();

  \t\t// @event start: Event
  \t\t// Fired when the animation starts
  \t\tthis.fire('start');

  \t\tthis._animate();
  \t},

  \t// @method stop()
  \t// Stops the animation (if currently running).
  \tstop: function () {
  \t\tif (!this._inProgress) { return; }

  \t\tthis._step(true);
  \t\tthis._complete();
  \t},

  \t_animate: function () {
  \t\t// animation loop
  \t\tthis._animId = requestAnimFrame(this._animate, this);
  \t\tthis._step();
  \t},

  \t_step: function (round) {
  \t\tvar elapsed = (+new Date()) - this._startTime,
  \t\t    duration = this._duration * 1000;

  \t\tif (elapsed < duration) {
  \t\t\tthis._runFrame(this._easeOut(elapsed / duration), round);
  \t\t} else {
  \t\t\tthis._runFrame(1);
  \t\t\tthis._complete();
  \t\t}
  \t},

  \t_runFrame: function (progress, round) {
  \t\tvar pos = this._startPos.add(this._offset.multiplyBy(progress));
  \t\tif (round) {
  \t\t\tpos._round();
  \t\t}
  \t\tsetPosition(this._el, pos);

  \t\t// @event step: Event
  \t\t// Fired continuously during the animation.
  \t\tthis.fire('step');
  \t},

  \t_complete: function () {
  \t\tcancelAnimFrame(this._animId);

  \t\tthis._inProgress = false;
  \t\t// @event end: Event
  \t\t// Fired when the animation ends.
  \t\tthis.fire('end');
  \t},

  \t_easeOut: function (t) {
  \t\treturn 1 - Math.pow(1 - t, this._easeOutPower);
  \t}
  });

  /*
   * @class Map
   * @aka L.Map
   * @inherits Evented
   *
   * The central class of the API — it is used to create a map on a page and manipulate it.
   *
   * @example
   *
   * ```js
   * // initialize the map on the \"map\" div with a given center and zoom
   * var map = L.map('map', {
   * \tcenter: [51.505, -0.09],
   * \tzoom: 13
   * });
   * ```
   *
   */

  var Map = Evented.extend({

  \toptions: {
  \t\t// @section Map State Options
  \t\t// @option crs: CRS = L.CRS.EPSG3857
  \t\t// The [Coordinate Reference System](#crs) to use. Don't change this if you're not
  \t\t// sure what it means.
  \t\tcrs: EPSG3857,

  \t\t// @option center: LatLng = undefined
  \t\t// Initial geographic center of the map
  \t\tcenter: undefined,

  \t\t// @option zoom: Number = undefined
  \t\t// Initial map zoom level
  \t\tzoom: undefined,

  \t\t// @option minZoom: Number = *
  \t\t// Minimum zoom level of the map.
  \t\t// If not specified and at least one `GridLayer` or `TileLayer` is in the map,
  \t\t// the lowest of their `minZoom` options will be used instead.
  \t\tminZoom: undefined,

  \t\t// @option maxZoom: Number = *
  \t\t// Maximum zoom level of the map.
  \t\t// If not specified and at least one `GridLayer` or `TileLayer` is in the map,
  \t\t// the highest of their `maxZoom` options will be used instead.
  \t\tmaxZoom: undefined,

  \t\t// @option layers: Layer[] = []
  \t\t// Array of layers that will be added to the map initially
  \t\tlayers: [],

  \t\t// @option maxBounds: LatLngBounds = null
  \t\t// When this option is set, the map restricts the view to the given
  \t\t// geographical bounds, bouncing the user back if the user tries to pan
  \t\t// outside the view. To set the restriction dynamically, use
  \t\t// [`setMaxBounds`](#map-setmaxbounds) method.
  \t\tmaxBounds: undefined,

  \t\t// @option renderer: Renderer = *
  \t\t// The default method for drawing vector layers on the map. `L.SVG`
  \t\t// or `L.Canvas` by default depending on browser support.
  \t\trenderer: undefined,


  \t\t// @section Animation Options
  \t\t// @option zoomAnimation: Boolean = true
  \t\t// Whether the map zoom animation is enabled. By default it's enabled
  \t\t// in all browsers that support CSS3 Transitions except Android.
  \t\tzoomAnimation: true,

  \t\t// @option zoomAnimationThreshold: Number = 4
  \t\t// Won't animate zoom if the zoom difference exceeds this value.
  \t\tzoomAnimationThreshold: 4,

  \t\t// @option fadeAnimation: Boolean = true
  \t\t// Whether the tile fade animation is enabled. By default it's enabled
  \t\t// in all browsers that support CSS3 Transitions except Android.
  \t\tfadeAnimation: true,

  \t\t// @option markerZoomAnimation: Boolean = true
  \t\t// Whether markers animate their zoom with the zoom animation, if disabled
  \t\t// they will disappear for the length of the animation. By default it's
  \t\t// enabled in all browsers that support CSS3 Transitions except Android.
  \t\tmarkerZoomAnimation: true,

  \t\t// @option transform3DLimit: Number = 2^23
  \t\t// Defines the maximum size of a CSS translation transform. The default
  \t\t// value should not be changed unless a web browser positions layers in
  \t\t// the wrong place after doing a large `panBy`.
  \t\ttransform3DLimit: 8388608, // Precision limit of a 32-bit float

  \t\t// @section Interaction Options
  \t\t// @option zoomSnap: Number = 1
  \t\t// Forces the map's zoom level to always be a multiple of this, particularly
  \t\t// right after a [`fitBounds()`](#map-fitbounds) or a pinch-zoom.
  \t\t// By default, the zoom level snaps to the nearest integer; lower values
  \t\t// (e.g. `0.5` or `0.1`) allow for greater granularity. A value of `0`
  \t\t// means the zoom level will not be snapped after `fitBounds` or a pinch-zoom.
  \t\tzoomSnap: 1,

  \t\t// @option zoomDelta: Number = 1
  \t\t// Controls how much the map's zoom level will change after a
  \t\t// [`zoomIn()`](#map-zoomin), [`zoomOut()`](#map-zoomout), pressing `+`
  \t\t// or `-` on the keyboard, or using the [zoom controls](#control-zoom).
  \t\t// Values smaller than `1` (e.g. `0.5`) allow for greater granularity.
  \t\tzoomDelta: 1,

  \t\t// @option trackResize: Boolean = true
  \t\t// Whether the map automatically handles browser window resize to update itself.
  \t\ttrackResize: true
  \t},

  \tinitialize: function (id, options) { // (HTMLElement or String, Object)
  \t\toptions = setOptions(this, options);

  \t\t// Make sure to assign internal flags at the beginning,
  \t\t// to avoid inconsistent state in some edge cases.
  \t\tthis._handlers = [];
  \t\tthis._layers = {};
  \t\tthis._zoomBoundLayers = {};
  \t\tthis._sizeChanged = true;

  \t\tthis._initContainer(id);
  \t\tthis._initLayout();

  \t\t// hack for https://github.com/Leaflet/Leaflet/issues/1980
  \t\tthis._onResize = bind(this._onResize, this);

  \t\tthis._initEvents();

  \t\tif (options.maxBounds) {
  \t\t\tthis.setMaxBounds(options.maxBounds);
  \t\t}

  \t\tif (options.zoom !== undefined) {
  \t\t\tthis._zoom = this._limitZoom(options.zoom);
  \t\t}

  \t\tif (options.center && options.zoom !== undefined) {
  \t\t\tthis.setView(toLatLng(options.center), options.zoom, {reset: true});
  \t\t}

  \t\tthis.callInitHooks();

  \t\t// don't animate on browsers without hardware-accelerated transitions or old Android/Opera
  \t\tthis._zoomAnimated = TRANSITION && Browser.any3d && !Browser.mobileOpera &&
  \t\t\t\tthis.options.zoomAnimation;

  \t\t// zoom transitions run with the same duration for all layers, so if one of transitionend events
  \t\t// happens after starting zoom animation (propagating to the map pane), we know that it ended globally
  \t\tif (this._zoomAnimated) {
  \t\t\tthis._createAnimProxy();
  \t\t\ton(this._proxy, TRANSITION_END, this._catchTransitionEnd, this);
  \t\t}

  \t\tthis._addLayers(this.options.layers);
  \t},


  \t// @section Methods for modifying map state

  \t// @method setView(center: LatLng, zoom: Number, options?: Zoom/pan options): this
  \t// Sets the view of the map (geographical center and zoom) with the given
  \t// animation options.
  \tsetView: function (center, zoom, options) {

  \t\tzoom = zoom === undefined ? this._zoom : this._limitZoom(zoom);
  \t\tcenter = this._limitCenter(toLatLng(center), zoom, this.options.maxBounds);
  \t\toptions = options || {};

  \t\tthis._stop();

  \t\tif (this._loaded && !options.reset && options !== true) {

  \t\t\tif (options.animate !== undefined) {
  \t\t\t\toptions.zoom = extend({animate: options.animate}, options.zoom);
  \t\t\t\toptions.pan = extend({animate: options.animate, duration: options.duration}, options.pan);
  \t\t\t}

  \t\t\t// try animating pan or zoom
  \t\t\tvar moved = (this._zoom !== zoom) ?
  \t\t\t\tthis._tryAnimatedZoom && this._tryAnimatedZoom(center, zoom, options.zoom) :
  \t\t\t\tthis._tryAnimatedPan(center, options.pan);

  \t\t\tif (moved) {
  \t\t\t\t// prevent resize handler call, the view will refresh after animation anyway
  \t\t\t\tclearTimeout(this._sizeTimer);
  \t\t\t\treturn this;
  \t\t\t}
  \t\t}

  \t\t// animation didn't start, just reset the map view
  \t\tthis._resetView(center, zoom, options.pan && options.pan.noMoveStart);

  \t\treturn this;
  \t},

  \t// @method setZoom(zoom: Number, options?: Zoom/pan options): this
  \t// Sets the zoom of the map.
  \tsetZoom: function (zoom, options) {
  \t\tif (!this._loaded) {
  \t\t\tthis._zoom = zoom;
  \t\t\treturn this;
  \t\t}
  \t\treturn this.setView(this.getCenter(), zoom, {zoom: options});
  \t},

  \t// @method zoomIn(delta?: Number, options?: Zoom options): this
  \t// Increases the zoom of the map by `delta` ([`zoomDelta`](#map-zoomdelta) by default).
  \tzoomIn: function (delta, options) {
  \t\tdelta = delta || (Browser.any3d ? this.options.zoomDelta : 1);
  \t\treturn this.setZoom(this._zoom + delta, options);
  \t},

  \t// @method zoomOut(delta?: Number, options?: Zoom options): this
  \t// Decreases the zoom of the map by `delta` ([`zoomDelta`](#map-zoomdelta) by default).
  \tzoomOut: function (delta, options) {
  \t\tdelta = delta || (Browser.any3d ? this.options.zoomDelta : 1);
  \t\treturn this.setZoom(this._zoom - delta, options);
  \t},

  \t// @method setZoomAround(latlng: LatLng, zoom: Number, options: Zoom options): this
  \t// Zooms the map while keeping a specified geographical point on the map
  \t// stationary (e.g. used internally for scroll zoom and double-click zoom).
  \t// @alternative
  \t// @method setZoomAround(offset: Point, zoom: Number, options: Zoom options): this
  \t// Zooms the map while keeping a specified pixel on the map (relative to the top-left corner) stationary.
  \tsetZoomAround: function (latlng, zoom, options) {
  \t\tvar scale = this.getZoomScale(zoom),
  \t\t    viewHalf = this.getSize().divideBy(2),
  \t\t    containerPoint = latlng instanceof Point ? latlng : this.latLngToContainerPoint(latlng),

  \t\t    centerOffset = containerPoint.subtract(viewHalf).multiplyBy(1 - 1 / scale),
  \t\t    newCenter = this.containerPointToLatLng(viewHalf.add(centerOffset));

  \t\treturn this.setView(newCenter, zoom, {zoom: options});
  \t},

  \t_getBoundsCenterZoom: function (bounds, options) {

  \t\toptions = options || {};
  \t\tbounds = bounds.getBounds ? bounds.getBounds() : toLatLngBounds(bounds);

  \t\tvar paddingTL = toPoint(options.paddingTopLeft || options.padding || [0, 0]),
  \t\t    paddingBR = toPoint(options.paddingBottomRight || options.padding || [0, 0]),

  \t\t    zoom = this.getBoundsZoom(bounds, false, paddingTL.add(paddingBR));

  \t\tzoom = (typeof options.maxZoom === 'number') ? Math.min(options.maxZoom, zoom) : zoom;

  \t\tif (zoom === Infinity) {
  \t\t\treturn {
  \t\t\t\tcenter: bounds.getCenter(),
  \t\t\t\tzoom: zoom
  \t\t\t};
  \t\t}

  \t\tvar paddingOffset = paddingBR.subtract(paddingTL).divideBy(2),

  \t\t    swPoint = this.project(bounds.getSouthWest(), zoom),
  \t\t    nePoint = this.project(bounds.getNorthEast(), zoom),
  \t\t    center = this.unproject(swPoint.add(nePoint).divideBy(2).add(paddingOffset), zoom);

  \t\treturn {
  \t\t\tcenter: center,
  \t\t\tzoom: zoom
  \t\t};
  \t},

  \t// @method fitBounds(bounds: LatLngBounds, options?: fitBounds options): this
  \t// Sets a map view that contains the given geographical bounds with the
  \t// maximum zoom level possible.
  \tfitBounds: function (bounds, options) {

  \t\tbounds = toLatLngBounds(bounds);

  \t\tif (!bounds.isValid()) {
  \t\t\tthrow new Error('Bounds are not valid.');
  \t\t}

  \t\tvar target = this._getBoundsCenterZoom(bounds, options);
  \t\treturn this.setView(target.center, target.zoom, options);
  \t},

  \t// @method fitWorld(options?: fitBounds options): this
  \t// Sets a map view that mostly contains the whole world with the maximum
  \t// zoom level possible.
  \tfitWorld: function (options) {
  \t\treturn this.fitBounds([[-90, -180], [90, 180]], options);
  \t},

  \t// @method panTo(latlng: LatLng, options?: Pan options): this
  \t// Pans the map to a given center.
  \tpanTo: function (center, options) { // (LatLng)
  \t\treturn this.setView(center, this._zoom, {pan: options});
  \t},

  \t// @method panBy(offset: Point, options?: Pan options): this
  \t// Pans the map by a given number of pixels (animated).
  \tpanBy: function (offset, options) {
  \t\toffset = toPoint(offset).round();
  \t\toptions = options || {};

  \t\tif (!offset.x && !offset.y) {
  \t\t\treturn this.fire('moveend');
  \t\t}
  \t\t// If we pan too far, Chrome gets issues with tiles
  \t\t// and makes them disappear or appear in the wrong place (slightly offset) #2602
  \t\tif (options.animate !== true && !this.getSize().contains(offset)) {
  \t\t\tthis._resetView(this.unproject(this.project(this.getCenter()).add(offset)), this.getZoom());
  \t\t\treturn this;
  \t\t}

  \t\tif (!this._panAnim) {
  \t\t\tthis._panAnim = new PosAnimation();

  \t\t\tthis._panAnim.on({
  \t\t\t\t'step': this._onPanTransitionStep,
  \t\t\t\t'end': this._onPanTransitionEnd
  \t\t\t}, this);
  \t\t}

  \t\t// don't fire movestart if animating inertia
  \t\tif (!options.noMoveStart) {
  \t\t\tthis.fire('movestart');
  \t\t}

  \t\t// animate pan unless animate: false specified
  \t\tif (options.animate !== false) {
  \t\t\taddClass(this._mapPane, 'leaflet-pan-anim');

  \t\t\tvar newPos = this._getMapPanePos().subtract(offset).round();
  \t\t\tthis._panAnim.run(this._mapPane, newPos, options.duration || 0.25, options.easeLinearity);
  \t\t} else {
  \t\t\tthis._rawPanBy(offset);
  \t\t\tthis.fire('move').fire('moveend');
  \t\t}

  \t\treturn this;
  \t},

  \t// @method flyTo(latlng: LatLng, zoom?: Number, options?: Zoom/pan options): this
  \t// Sets the view of the map (geographical center and zoom) performing a smooth
  \t// pan-zoom animation.
  \tflyTo: function (targetCenter, targetZoom, options) {

  \t\toptions = options || {};
  \t\tif (options.animate === false || !Browser.any3d) {
  \t\t\treturn this.setView(targetCenter, targetZoom, options);
  \t\t}

  \t\tthis._stop();

  \t\tvar from = this.project(this.getCenter()),
  \t\t    to = this.project(targetCenter),
  \t\t    size = this.getSize(),
  \t\t    startZoom = this._zoom;

  \t\ttargetCenter = toLatLng(targetCenter);
  \t\ttargetZoom = targetZoom === undefined ? startZoom : targetZoom;

  \t\tvar w0 = Math.max(size.x, size.y),
  \t\t    w1 = w0 * this.getZoomScale(startZoom, targetZoom),
  \t\t    u1 = (to.distanceTo(from)) || 1,
  \t\t    rho = 1.42,
  \t\t    rho2 = rho * rho;

  \t\tfunction r(i) {
  \t\t\tvar s1 = i ? -1 : 1,
  \t\t\t    s2 = i ? w1 : w0,
  \t\t\t    t1 = w1 * w1 - w0 * w0 + s1 * rho2 * rho2 * u1 * u1,
  \t\t\t    b1 = 2 * s2 * rho2 * u1,
  \t\t\t    b = t1 / b1,
  \t\t\t    sq = Math.sqrt(b * b + 1) - b;

  \t\t\t    // workaround for floating point precision bug when sq = 0, log = -Infinite,
  \t\t\t    // thus triggering an infinite loop in flyTo
  \t\t\t    var log = sq < 0.000000001 ? -18 : Math.log(sq);

  \t\t\treturn log;
  \t\t}

  \t\tfunction sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; }
  \t\tfunction cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; }
  \t\tfunction tanh(n) { return sinh(n) / cosh(n); }

  \t\tvar r0 = r(0);

  \t\tfunction w(s) { return w0 * (cosh(r0) / cosh(r0 + rho * s)); }
  \t\tfunction u(s) { return w0 * (cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2; }

  \t\tfunction easeOut(t) { return 1 - Math.pow(1 - t, 1.5); }

  \t\tvar start = Date.now(),
  \t\t    S = (r(1) - r0) / rho,
  \t\t    duration = options.duration ? 1000 * options.duration : 1000 * S * 0.8;

  \t\tfunction frame() {
  \t\t\tvar t = (Date.now() - start) / duration,
  \t\t\t    s = easeOut(t) * S;

  \t\t\tif (t <= 1) {
  \t\t\t\tthis._flyToFrame = requestAnimFrame(frame, this);

  \t\t\t\tthis._move(
  \t\t\t\t\tthis.unproject(from.add(to.subtract(from).multiplyBy(u(s) / u1)), startZoom),
  \t\t\t\t\tthis.getScaleZoom(w0 / w(s), startZoom),
  \t\t\t\t\t{flyTo: true});

  \t\t\t} else {
  \t\t\t\tthis
  \t\t\t\t\t._move(targetCenter, targetZoom)
  \t\t\t\t\t._moveEnd(true);
  \t\t\t}
  \t\t}

  \t\tthis._moveStart(true, options.noMoveStart);

  \t\tframe.call(this);
  \t\treturn this;
  \t},

  \t// @method flyToBounds(bounds: LatLngBounds, options?: fitBounds options): this
  \t// Sets the view of the map with a smooth animation like [`flyTo`](#map-flyto),
  \t// but takes a bounds parameter like [`fitBounds`](#map-fitbounds).
  \tflyToBounds: function (bounds, options) {
  \t\tvar target = this._getBoundsCenterZoom(bounds, options);
  \t\treturn this.flyTo(target.center, target.zoom, options);
  \t},

  \t// @method setMaxBounds(bounds: LatLngBounds): this
  \t// Restricts the map view to the given bounds (see the [maxBounds](#map-maxbounds) option).
  \tsetMaxBounds: function (bounds) {
  \t\tbounds = toLatLngBounds(bounds);

  \t\tif (this.listens('moveend', this._panInsideMaxBounds)) {
  \t\t\tthis.off('moveend', this._panInsideMaxBounds);
  \t\t}

  \t\tif (!bounds.isValid()) {
  \t\t\tthis.options.maxBounds = null;
  \t\t\treturn this;
  \t\t}

  \t\tthis.options.maxBounds = bounds;

  \t\tif (this._loaded) {
  \t\t\tthis._panInsideMaxBounds();
  \t\t}

  \t\treturn this.on('moveend', this._panInsideMaxBounds);
  \t},

  \t// @method setMinZoom(zoom: Number): this
  \t// Sets the lower limit for the available zoom levels (see the [minZoom](#map-minzoom) option).
  \tsetMinZoom: function (zoom) {
  \t\tvar oldZoom = this.options.minZoom;
  \t\tthis.options.minZoom = zoom;

  \t\tif (this._loaded && oldZoom !== zoom) {
  \t\t\tthis.fire('zoomlevelschange');

  \t\t\tif (this.getZoom() < this.options.minZoom) {
  \t\t\t\treturn this.setZoom(zoom);
  \t\t\t}
  \t\t}

  \t\treturn this;
  \t},

  \t// @method setMaxZoom(zoom: Number): this
  \t// Sets the upper limit for the available zoom levels (see the [maxZoom](#map-maxzoom) option).
  \tsetMaxZoom: function (zoom) {
  \t\tvar oldZoom = this.options.maxZoom;
  \t\tthis.options.maxZoom = zoom;

  \t\tif (this._loaded && oldZoom !== zoom) {
  \t\t\tthis.fire('zoomlevelschange');

  \t\t\tif (this.getZoom() > this.options.maxZoom) {
  \t\t\t\treturn this.setZoom(zoom);
  \t\t\t}
  \t\t}

  \t\treturn this;
  \t},

  \t// @method panInsideBounds(bounds: LatLngBounds, options?: Pan options): this
  \t// Pans the map to the closest view that would lie inside the given bounds (if it's not already), controlling the animation using the options specific, if any.
  \tpanInsideBounds: function (bounds, options) {
  \t\tthis._enforcingBounds = true;
  \t\tvar center = this.getCenter(),
  \t\t    newCenter = this._limitCenter(center, this._zoom, toLatLngBounds(bounds));

  \t\tif (!center.equals(newCenter)) {
  \t\t\tthis.panTo(newCenter, options);
  \t\t}

  \t\tthis._enforcingBounds = false;
  \t\treturn this;
  \t},

  \t// @method panInside(latlng: LatLng, options?: padding options): this
  \t// Pans the map the minimum amount to make the `latlng` visible. Use
  \t// padding options to fit the display to more restricted bounds.
  \t// If `latlng` is already within the (optionally padded) display bounds,
  \t// the map will not be panned.
  \tpanInside: function (latlng, options) {
  \t\toptions = options || {};

  \t\tvar paddingTL = toPoint(options.paddingTopLeft || options.padding || [0, 0]),
  \t\t    paddingBR = toPoint(options.paddingBottomRight || options.padding || [0, 0]),
  \t\t    pixelCenter = this.project(this.getCenter()),
  \t\t    pixelPoint = this.project(latlng),
  \t\t    pixelBounds = this.getPixelBounds(),
  \t\t    paddedBounds = toBounds([pixelBounds.min.add(paddingTL), pixelBounds.max.subtract(paddingBR)]),
  \t\t    paddedSize = paddedBounds.getSize();

  \t\tif (!paddedBounds.contains(pixelPoint)) {
  \t\t\tthis._enforcingBounds = true;
  \t\t\tvar centerOffset = pixelPoint.subtract(paddedBounds.getCenter());
  \t\t\tvar offset = paddedBounds.extend(pixelPoint).getSize().subtract(paddedSize);
  \t\t\tpixelCenter.x += centerOffset.x < 0 ? -offset.x : offset.x;
  \t\t\tpixelCenter.y += centerOffset.y < 0 ? -offset.y : offset.y;
  \t\t\tthis.panTo(this.unproject(pixelCenter), options);
  \t\t\tthis._enforcingBounds = false;
  \t\t}
  \t\treturn this;
  \t},

  \t// @method invalidateSize(options: Zoom/pan options): this
  \t// Checks if the map container size changed and updates the map if so —
  \t// call it after you've changed the map size dynamically, also animating
  \t// pan by default. If `options.pan` is `false`, panning will not occur.
  \t// If `options.debounceMoveend` is `true`, it will delay `moveend` event so
  \t// that it doesn't happen often even if the method is called many
  \t// times in a row.

  \t// @alternative
  \t// @method invalidateSize(animate: Boolean): this
  \t// Checks if the map container size changed and updates the map if so —
  \t// call it after you've changed the map size dynamically, also animating
  \t// pan by default.
  \tinvalidateSize: function (options) {
  \t\tif (!this._loaded) { return this; }

  \t\toptions = extend({
  \t\t\tanimate: false,
  \t\t\tpan: true
  \t\t}, options === true ? {animate: true} : options);

  \t\tvar oldSize = this.getSize();
  \t\tthis._sizeChanged = true;
  \t\tthis._lastCenter = null;

  \t\tvar newSize = this.getSize(),
  \t\t    oldCenter = oldSize.divideBy(2).round(),
  \t\t    newCenter = newSize.divideBy(2).round(),
  \t\t    offset = oldCenter.subtract(newCenter);

  \t\tif (!offset.x && !offset.y) { return this; }

  \t\tif (options.animate && options.pan) {
  \t\t\tthis.panBy(offset);

  \t\t} else {
  \t\t\tif (options.pan) {
  \t\t\t\tthis._rawPanBy(offset);
  \t\t\t}

  \t\t\tthis.fire('move');

  \t\t\tif (options.debounceMoveend) {
  \t\t\t\tclearTimeout(this._sizeTimer);
  \t\t\t\tthis._sizeTimer = setTimeout(bind(this.fire, this, 'moveend'), 200);
  \t\t\t} else {
  \t\t\t\tthis.fire('moveend');
  \t\t\t}
  \t\t}

  \t\t// @section Map state change events
  \t\t// @event resize: ResizeEvent
  \t\t// Fired when the map is resized.
  \t\treturn this.fire('resize', {
  \t\t\toldSize: oldSize,
  \t\t\tnewSize: newSize
  \t\t});
  \t},

  \t// @section Methods for modifying map state
  \t// @method stop(): this
  \t// Stops the currently running `panTo` or `flyTo` animation, if any.
  \tstop: function () {
  \t\tthis.setZoom(this._limitZoom(this._zoom));
  \t\tif (!this.options.zoomSnap) {
  \t\t\tthis.fire('viewreset');
  \t\t}
  \t\treturn this._stop();
  \t},

  \t// @section Geolocation methods
  \t// @method locate(options?: Locate options): this
  \t// Tries to locate the user using the Geolocation API, firing a [`locationfound`](#map-locationfound)
  \t// event with location data on success or a [`locationerror`](#map-locationerror) event on failure,
  \t// and optionally sets the map view to the user's location with respect to
  \t// detection accuracy (or to the world view if geolocation failed).
  \t// Note that, if your page doesn't use HTTPS, this method will fail in
  \t// modern browsers ([Chrome 50 and newer](https://sites.google.com/a/chromium.org/dev/Home/chromium-security/deprecating-powerful-features-on-insecure-origins))
  \t// See `Locate options` for more details.
  \tlocate: function (options) {

  \t\toptions = this._locateOptions = extend({
  \t\t\ttimeout: 10000,
  \t\t\twatch: false
  \t\t\t// setView: false
  \t\t\t// maxZoom: <Number>
  \t\t\t// maximumAge: 0
  \t\t\t// enableHighAccuracy: false
  \t\t}, options);

  \t\tif (!('geolocation' in navigator)) {
  \t\t\tthis._handleGeolocationError({
  \t\t\t\tcode: 0,
  \t\t\t\tmessage: 'Geolocation not supported.'
  \t\t\t});
  \t\t\treturn this;
  \t\t}

  \t\tvar onResponse = bind(this._handleGeolocationResponse, this),
  \t\t    onError = bind(this._handleGeolocationError, this);

  \t\tif (options.watch) {
  \t\t\tthis._locationWatchId =
  \t\t\t        navigator.geolocation.watchPosition(onResponse, onError, options);
  \t\t} else {
  \t\t\tnavigator.geolocation.getCurrentPosition(onResponse, onError, options);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method stopLocate(): this
  \t// Stops watching location previously initiated by `map.locate({watch: true})`
  \t// and aborts resetting the map view if map.locate was called with
  \t// `{setView: true}`.
  \tstopLocate: function () {
  \t\tif (navigator.geolocation && navigator.geolocation.clearWatch) {
  \t\t\tnavigator.geolocation.clearWatch(this._locationWatchId);
  \t\t}
  \t\tif (this._locateOptions) {
  \t\t\tthis._locateOptions.setView = false;
  \t\t}
  \t\treturn this;
  \t},

  \t_handleGeolocationError: function (error) {
  \t\tif (!this._container._leaflet_id) { return; }

  \t\tvar c = error.code,
  \t\t    message = error.message ||
  \t\t            (c === 1 ? 'permission denied' :
  \t\t            (c === 2 ? 'position unavailable' : 'timeout'));

  \t\tif (this._locateOptions.setView && !this._loaded) {
  \t\t\tthis.fitWorld();
  \t\t}

  \t\t// @section Location events
  \t\t// @event locationerror: ErrorEvent
  \t\t// Fired when geolocation (using the [`locate`](#map-locate) method) failed.
  \t\tthis.fire('locationerror', {
  \t\t\tcode: c,
  \t\t\tmessage: 'Geolocation error: ' + message + '.'
  \t\t});
  \t},

  \t_handleGeolocationResponse: function (pos) {
  \t\tif (!this._container._leaflet_id) { return; }

  \t\tvar lat = pos.coords.latitude,
  \t\t    lng = pos.coords.longitude,
  \t\t    latlng = new LatLng(lat, lng),
  \t\t    bounds = latlng.toBounds(pos.coords.accuracy * 2),
  \t\t    options = this._locateOptions;

  \t\tif (options.setView) {
  \t\t\tvar zoom = this.getBoundsZoom(bounds);
  \t\t\tthis.setView(latlng, options.maxZoom ? Math.min(zoom, options.maxZoom) : zoom);
  \t\t}

  \t\tvar data = {
  \t\t\tlatlng: latlng,
  \t\t\tbounds: bounds,
  \t\t\ttimestamp: pos.timestamp
  \t\t};

  \t\tfor (var i in pos.coords) {
  \t\t\tif (typeof pos.coords[i] === 'number') {
  \t\t\t\tdata[i] = pos.coords[i];
  \t\t\t}
  \t\t}

  \t\t// @event locationfound: LocationEvent
  \t\t// Fired when geolocation (using the [`locate`](#map-locate) method)
  \t\t// went successfully.
  \t\tthis.fire('locationfound', data);
  \t},

  \t// TODO Appropriate docs section?
  \t// @section Other Methods
  \t// @method addHandler(name: String, HandlerClass: Function): this
  \t// Adds a new `Handler` to the map, given its name and constructor function.
  \taddHandler: function (name, HandlerClass) {
  \t\tif (!HandlerClass) { return this; }

  \t\tvar handler = this[name] = new HandlerClass(this);

  \t\tthis._handlers.push(handler);

  \t\tif (this.options[name]) {
  \t\t\thandler.enable();
  \t\t}

  \t\treturn this;
  \t},

  \t// @method remove(): this
  \t// Destroys the map and clears all related event listeners.
  \tremove: function () {

  \t\tthis._initEvents(true);
  \t\tif (this.options.maxBounds) { this.off('moveend', this._panInsideMaxBounds); }

  \t\tif (this._containerId !== this._container._leaflet_id) {
  \t\t\tthrow new Error('Map container is being reused by another instance');
  \t\t}

  \t\ttry {
  \t\t\t// throws error in IE6-8
  \t\t\tdelete this._container._leaflet_id;
  \t\t\tdelete this._containerId;
  \t\t} catch (e) {
  \t\t\t/*eslint-disable */
  \t\t\tthis._container._leaflet_id = undefined;
  \t\t\t/* eslint-enable */
  \t\t\tthis._containerId = undefined;
  \t\t}

  \t\tif (this._locationWatchId !== undefined) {
  \t\t\tthis.stopLocate();
  \t\t}

  \t\tthis._stop();

  \t\tremove(this._mapPane);

  \t\tif (this._clearControlPos) {
  \t\t\tthis._clearControlPos();
  \t\t}
  \t\tif (this._resizeRequest) {
  \t\t\tcancelAnimFrame(this._resizeRequest);
  \t\t\tthis._resizeRequest = null;
  \t\t}

  \t\tthis._clearHandlers();

  \t\tif (this._loaded) {
  \t\t\t// @section Map state change events
  \t\t\t// @event unload: Event
  \t\t\t// Fired when the map is destroyed with [remove](#map-remove) method.
  \t\t\tthis.fire('unload');
  \t\t}

  \t\tvar i;
  \t\tfor (i in this._layers) {
  \t\t\tthis._layers[i].remove();
  \t\t}
  \t\tfor (i in this._panes) {
  \t\t\tremove(this._panes[i]);
  \t\t}

  \t\tthis._layers = [];
  \t\tthis._panes = [];
  \t\tdelete this._mapPane;
  \t\tdelete this._renderer;

  \t\treturn this;
  \t},

  \t// @section Other Methods
  \t// @method createPane(name: String, container?: HTMLElement): HTMLElement
  \t// Creates a new [map pane](#map-pane) with the given name if it doesn't exist already,
  \t// then returns it. The pane is created as a child of `container`, or
  \t// as a child of the main map pane if not set.
  \tcreatePane: function (name, container) {
  \t\tvar className = 'leaflet-pane' + (name ? ' leaflet-' + name.replace('Pane', '') + '-pane' : ''),
  \t\t    pane = create\$1('div', className, container || this._mapPane);

  \t\tif (name) {
  \t\t\tthis._panes[name] = pane;
  \t\t}
  \t\treturn pane;
  \t},

  \t// @section Methods for Getting Map State

  \t// @method getCenter(): LatLng
  \t// Returns the geographical center of the map view
  \tgetCenter: function () {
  \t\tthis._checkIfLoaded();

  \t\tif (this._lastCenter && !this._moved()) {
  \t\t\treturn this._lastCenter.clone();
  \t\t}
  \t\treturn this.layerPointToLatLng(this._getCenterLayerPoint());
  \t},

  \t// @method getZoom(): Number
  \t// Returns the current zoom level of the map view
  \tgetZoom: function () {
  \t\treturn this._zoom;
  \t},

  \t// @method getBounds(): LatLngBounds
  \t// Returns the geographical bounds visible in the current map view
  \tgetBounds: function () {
  \t\tvar bounds = this.getPixelBounds(),
  \t\t    sw = this.unproject(bounds.getBottomLeft()),
  \t\t    ne = this.unproject(bounds.getTopRight());

  \t\treturn new LatLngBounds(sw, ne);
  \t},

  \t// @method getMinZoom(): Number
  \t// Returns the minimum zoom level of the map (if set in the `minZoom` option of the map or of any layers), or `0` by default.
  \tgetMinZoom: function () {
  \t\treturn this.options.minZoom === undefined ? this._layersMinZoom || 0 : this.options.minZoom;
  \t},

  \t// @method getMaxZoom(): Number
  \t// Returns the maximum zoom level of the map (if set in the `maxZoom` option of the map or of any layers).
  \tgetMaxZoom: function () {
  \t\treturn this.options.maxZoom === undefined ?
  \t\t\t(this._layersMaxZoom === undefined ? Infinity : this._layersMaxZoom) :
  \t\t\tthis.options.maxZoom;
  \t},

  \t// @method getBoundsZoom(bounds: LatLngBounds, inside?: Boolean, padding?: Point): Number
  \t// Returns the maximum zoom level on which the given bounds fit to the map
  \t// view in its entirety. If `inside` (optional) is set to `true`, the method
  \t// instead returns the minimum zoom level on which the map view fits into
  \t// the given bounds in its entirety.
  \tgetBoundsZoom: function (bounds, inside, padding) { // (LatLngBounds[, Boolean, Point]) -> Number
  \t\tbounds = toLatLngBounds(bounds);
  \t\tpadding = toPoint(padding || [0, 0]);

  \t\tvar zoom = this.getZoom() || 0,
  \t\t    min = this.getMinZoom(),
  \t\t    max = this.getMaxZoom(),
  \t\t    nw = bounds.getNorthWest(),
  \t\t    se = bounds.getSouthEast(),
  \t\t    size = this.getSize().subtract(padding),
  \t\t    boundsSize = toBounds(this.project(se, zoom), this.project(nw, zoom)).getSize(),
  \t\t    snap = Browser.any3d ? this.options.zoomSnap : 1,
  \t\t    scalex = size.x / boundsSize.x,
  \t\t    scaley = size.y / boundsSize.y,
  \t\t    scale = inside ? Math.max(scalex, scaley) : Math.min(scalex, scaley);

  \t\tzoom = this.getScaleZoom(scale, zoom);

  \t\tif (snap) {
  \t\t\tzoom = Math.round(zoom / (snap / 100)) * (snap / 100); // don't jump if within 1% of a snap level
  \t\t\tzoom = inside ? Math.ceil(zoom / snap) * snap : Math.floor(zoom / snap) * snap;
  \t\t}

  \t\treturn Math.max(min, Math.min(max, zoom));
  \t},

  \t// @method getSize(): Point
  \t// Returns the current size of the map container (in pixels).
  \tgetSize: function () {
  \t\tif (!this._size || this._sizeChanged) {
  \t\t\tthis._size = new Point(
  \t\t\t\tthis._container.clientWidth || 0,
  \t\t\t\tthis._container.clientHeight || 0);

  \t\t\tthis._sizeChanged = false;
  \t\t}
  \t\treturn this._size.clone();
  \t},

  \t// @method getPixelBounds(): Bounds
  \t// Returns the bounds of the current map view in projected pixel
  \t// coordinates (sometimes useful in layer and overlay implementations).
  \tgetPixelBounds: function (center, zoom) {
  \t\tvar topLeftPoint = this._getTopLeftPoint(center, zoom);
  \t\treturn new Bounds(topLeftPoint, topLeftPoint.add(this.getSize()));
  \t},

  \t// TODO: Check semantics - isn't the pixel origin the 0,0 coord relative to
  \t// the map pane? \"left point of the map layer\" can be confusing, specially
  \t// since there can be negative offsets.
  \t// @method getPixelOrigin(): Point
  \t// Returns the projected pixel coordinates of the top left point of
  \t// the map layer (useful in custom layer and overlay implementations).
  \tgetPixelOrigin: function () {
  \t\tthis._checkIfLoaded();
  \t\treturn this._pixelOrigin;
  \t},

  \t// @method getPixelWorldBounds(zoom?: Number): Bounds
  \t// Returns the world's bounds in pixel coordinates for zoom level `zoom`.
  \t// If `zoom` is omitted, the map's current zoom level is used.
  \tgetPixelWorldBounds: function (zoom) {
  \t\treturn this.options.crs.getProjectedBounds(zoom === undefined ? this.getZoom() : zoom);
  \t},

  \t// @section Other Methods

  \t// @method getPane(pane: String|HTMLElement): HTMLElement
  \t// Returns a [map pane](#map-pane), given its name or its HTML element (its identity).
  \tgetPane: function (pane) {
  \t\treturn typeof pane === 'string' ? this._panes[pane] : pane;
  \t},

  \t// @method getPanes(): Object
  \t// Returns a plain object containing the names of all [panes](#map-pane) as keys and
  \t// the panes as values.
  \tgetPanes: function () {
  \t\treturn this._panes;
  \t},

  \t// @method getContainer: HTMLElement
  \t// Returns the HTML element that contains the map.
  \tgetContainer: function () {
  \t\treturn this._container;
  \t},


  \t// @section Conversion Methods

  \t// @method getZoomScale(toZoom: Number, fromZoom: Number): Number
  \t// Returns the scale factor to be applied to a map transition from zoom level
  \t// `fromZoom` to `toZoom`. Used internally to help with zoom animations.
  \tgetZoomScale: function (toZoom, fromZoom) {
  \t\t// TODO replace with universal implementation after refactoring projections
  \t\tvar crs = this.options.crs;
  \t\tfromZoom = fromZoom === undefined ? this._zoom : fromZoom;
  \t\treturn crs.scale(toZoom) / crs.scale(fromZoom);
  \t},

  \t// @method getScaleZoom(scale: Number, fromZoom: Number): Number
  \t// Returns the zoom level that the map would end up at, if it is at `fromZoom`
  \t// level and everything is scaled by a factor of `scale`. Inverse of
  \t// [`getZoomScale`](#map-getZoomScale).
  \tgetScaleZoom: function (scale, fromZoom) {
  \t\tvar crs = this.options.crs;
  \t\tfromZoom = fromZoom === undefined ? this._zoom : fromZoom;
  \t\tvar zoom = crs.zoom(scale * crs.scale(fromZoom));
  \t\treturn isNaN(zoom) ? Infinity : zoom;
  \t},

  \t// @method project(latlng: LatLng, zoom: Number): Point
  \t// Projects a geographical coordinate `LatLng` according to the projection
  \t// of the map's CRS, then scales it according to `zoom` and the CRS's
  \t// `Transformation`. The result is pixel coordinate relative to
  \t// the CRS origin.
  \tproject: function (latlng, zoom) {
  \t\tzoom = zoom === undefined ? this._zoom : zoom;
  \t\treturn this.options.crs.latLngToPoint(toLatLng(latlng), zoom);
  \t},

  \t// @method unproject(point: Point, zoom: Number): LatLng
  \t// Inverse of [`project`](#map-project).
  \tunproject: function (point, zoom) {
  \t\tzoom = zoom === undefined ? this._zoom : zoom;
  \t\treturn this.options.crs.pointToLatLng(toPoint(point), zoom);
  \t},

  \t// @method layerPointToLatLng(point: Point): LatLng
  \t// Given a pixel coordinate relative to the [origin pixel](#map-getpixelorigin),
  \t// returns the corresponding geographical coordinate (for the current zoom level).
  \tlayerPointToLatLng: function (point) {
  \t\tvar projectedPoint = toPoint(point).add(this.getPixelOrigin());
  \t\treturn this.unproject(projectedPoint);
  \t},

  \t// @method latLngToLayerPoint(latlng: LatLng): Point
  \t// Given a geographical coordinate, returns the corresponding pixel coordinate
  \t// relative to the [origin pixel](#map-getpixelorigin).
  \tlatLngToLayerPoint: function (latlng) {
  \t\tvar projectedPoint = this.project(toLatLng(latlng))._round();
  \t\treturn projectedPoint._subtract(this.getPixelOrigin());
  \t},

  \t// @method wrapLatLng(latlng: LatLng): LatLng
  \t// Returns a `LatLng` where `lat` and `lng` has been wrapped according to the
  \t// map's CRS's `wrapLat` and `wrapLng` properties, if they are outside the
  \t// CRS's bounds.
  \t// By default this means longitude is wrapped around the dateline so its
  \t// value is between -180 and +180 degrees.
  \twrapLatLng: function (latlng) {
  \t\treturn this.options.crs.wrapLatLng(toLatLng(latlng));
  \t},

  \t// @method wrapLatLngBounds(bounds: LatLngBounds): LatLngBounds
  \t// Returns a `LatLngBounds` with the same size as the given one, ensuring that
  \t// its center is within the CRS's bounds.
  \t// By default this means the center longitude is wrapped around the dateline so its
  \t// value is between -180 and +180 degrees, and the majority of the bounds
  \t// overlaps the CRS's bounds.
  \twrapLatLngBounds: function (latlng) {
  \t\treturn this.options.crs.wrapLatLngBounds(toLatLngBounds(latlng));
  \t},

  \t// @method distance(latlng1: LatLng, latlng2: LatLng): Number
  \t// Returns the distance between two geographical coordinates according to
  \t// the map's CRS. By default this measures distance in meters.
  \tdistance: function (latlng1, latlng2) {
  \t\treturn this.options.crs.distance(toLatLng(latlng1), toLatLng(latlng2));
  \t},

  \t// @method containerPointToLayerPoint(point: Point): Point
  \t// Given a pixel coordinate relative to the map container, returns the corresponding
  \t// pixel coordinate relative to the [origin pixel](#map-getpixelorigin).
  \tcontainerPointToLayerPoint: function (point) { // (Point)
  \t\treturn toPoint(point).subtract(this._getMapPanePos());
  \t},

  \t// @method layerPointToContainerPoint(point: Point): Point
  \t// Given a pixel coordinate relative to the [origin pixel](#map-getpixelorigin),
  \t// returns the corresponding pixel coordinate relative to the map container.
  \tlayerPointToContainerPoint: function (point) { // (Point)
  \t\treturn toPoint(point).add(this._getMapPanePos());
  \t},

  \t// @method containerPointToLatLng(point: Point): LatLng
  \t// Given a pixel coordinate relative to the map container, returns
  \t// the corresponding geographical coordinate (for the current zoom level).
  \tcontainerPointToLatLng: function (point) {
  \t\tvar layerPoint = this.containerPointToLayerPoint(toPoint(point));
  \t\treturn this.layerPointToLatLng(layerPoint);
  \t},

  \t// @method latLngToContainerPoint(latlng: LatLng): Point
  \t// Given a geographical coordinate, returns the corresponding pixel coordinate
  \t// relative to the map container.
  \tlatLngToContainerPoint: function (latlng) {
  \t\treturn this.layerPointToContainerPoint(this.latLngToLayerPoint(toLatLng(latlng)));
  \t},

  \t// @method mouseEventToContainerPoint(ev: MouseEvent): Point
  \t// Given a MouseEvent object, returns the pixel coordinate relative to the
  \t// map container where the event took place.
  \tmouseEventToContainerPoint: function (e) {
  \t\treturn getMousePosition(e, this._container);
  \t},

  \t// @method mouseEventToLayerPoint(ev: MouseEvent): Point
  \t// Given a MouseEvent object, returns the pixel coordinate relative to
  \t// the [origin pixel](#map-getpixelorigin) where the event took place.
  \tmouseEventToLayerPoint: function (e) {
  \t\treturn this.containerPointToLayerPoint(this.mouseEventToContainerPoint(e));
  \t},

  \t// @method mouseEventToLatLng(ev: MouseEvent): LatLng
  \t// Given a MouseEvent object, returns geographical coordinate where the
  \t// event took place.
  \tmouseEventToLatLng: function (e) { // (MouseEvent)
  \t\treturn this.layerPointToLatLng(this.mouseEventToLayerPoint(e));
  \t},


  \t// map initialization methods

  \t_initContainer: function (id) {
  \t\tvar container = this._container = get(id);

  \t\tif (!container) {
  \t\t\tthrow new Error('Map container not found.');
  \t\t} else if (container._leaflet_id) {
  \t\t\tthrow new Error('Map container is already initialized.');
  \t\t}

  \t\ton(container, 'scroll', this._onScroll, this);
  \t\tthis._containerId = stamp(container);
  \t},

  \t_initLayout: function () {
  \t\tvar container = this._container;

  \t\tthis._fadeAnimated = this.options.fadeAnimation && Browser.any3d;

  \t\taddClass(container, 'leaflet-container' +
  \t\t\t(Browser.touch ? ' leaflet-touch' : '') +
  \t\t\t(Browser.retina ? ' leaflet-retina' : '') +
  \t\t\t(Browser.ielt9 ? ' leaflet-oldie' : '') +
  \t\t\t(Browser.safari ? ' leaflet-safari' : '') +
  \t\t\t(this._fadeAnimated ? ' leaflet-fade-anim' : ''));

  \t\tvar position = getStyle(container, 'position');

  \t\tif (position !== 'absolute' && position !== 'relative' && position !== 'fixed' && position !== 'sticky') {
  \t\t\tcontainer.style.position = 'relative';
  \t\t}

  \t\tthis._initPanes();

  \t\tif (this._initControlPos) {
  \t\t\tthis._initControlPos();
  \t\t}
  \t},

  \t_initPanes: function () {
  \t\tvar panes = this._panes = {};
  \t\tthis._paneRenderers = {};

  \t\t// @section
  \t\t//
  \t\t// Panes are DOM elements used to control the ordering of layers on the map. You
  \t\t// can access panes with [`map.getPane`](#map-getpane) or
  \t\t// [`map.getPanes`](#map-getpanes) methods. New panes can be created with the
  \t\t// [`map.createPane`](#map-createpane) method.
  \t\t//
  \t\t// Every map has the following default panes that differ only in zIndex.
  \t\t//
  \t\t// @pane mapPane: HTMLElement = 'auto'
  \t\t// Pane that contains all other map panes

  \t\tthis._mapPane = this.createPane('mapPane', this._container);
  \t\tsetPosition(this._mapPane, new Point(0, 0));

  \t\t// @pane tilePane: HTMLElement = 200
  \t\t// Pane for `GridLayer`s and `TileLayer`s
  \t\tthis.createPane('tilePane');
  \t\t// @pane overlayPane: HTMLElement = 400
  \t\t// Pane for vectors (`Path`s, like `Polyline`s and `Polygon`s), `ImageOverlay`s and `VideoOverlay`s
  \t\tthis.createPane('overlayPane');
  \t\t// @pane shadowPane: HTMLElement = 500
  \t\t// Pane for overlay shadows (e.g. `Marker` shadows)
  \t\tthis.createPane('shadowPane');
  \t\t// @pane markerPane: HTMLElement = 600
  \t\t// Pane for `Icon`s of `Marker`s
  \t\tthis.createPane('markerPane');
  \t\t// @pane tooltipPane: HTMLElement = 650
  \t\t// Pane for `Tooltip`s.
  \t\tthis.createPane('tooltipPane');
  \t\t// @pane popupPane: HTMLElement = 700
  \t\t// Pane for `Popup`s.
  \t\tthis.createPane('popupPane');

  \t\tif (!this.options.markerZoomAnimation) {
  \t\t\taddClass(panes.markerPane, 'leaflet-zoom-hide');
  \t\t\taddClass(panes.shadowPane, 'leaflet-zoom-hide');
  \t\t}
  \t},


  \t// private methods that modify map state

  \t// @section Map state change events
  \t_resetView: function (center, zoom, noMoveStart) {
  \t\tsetPosition(this._mapPane, new Point(0, 0));

  \t\tvar loading = !this._loaded;
  \t\tthis._loaded = true;
  \t\tzoom = this._limitZoom(zoom);

  \t\tthis.fire('viewprereset');

  \t\tvar zoomChanged = this._zoom !== zoom;
  \t\tthis
  \t\t\t._moveStart(zoomChanged, noMoveStart)
  \t\t\t._move(center, zoom)
  \t\t\t._moveEnd(zoomChanged);

  \t\t// @event viewreset: Event
  \t\t// Fired when the map needs to redraw its content (this usually happens
  \t\t// on map zoom or load). Very useful for creating custom overlays.
  \t\tthis.fire('viewreset');

  \t\t// @event load: Event
  \t\t// Fired when the map is initialized (when its center and zoom are set
  \t\t// for the first time).
  \t\tif (loading) {
  \t\t\tthis.fire('load');
  \t\t}
  \t},

  \t_moveStart: function (zoomChanged, noMoveStart) {
  \t\t// @event zoomstart: Event
  \t\t// Fired when the map zoom is about to change (e.g. before zoom animation).
  \t\t// @event movestart: Event
  \t\t// Fired when the view of the map starts changing (e.g. user starts dragging the map).
  \t\tif (zoomChanged) {
  \t\t\tthis.fire('zoomstart');
  \t\t}
  \t\tif (!noMoveStart) {
  \t\t\tthis.fire('movestart');
  \t\t}
  \t\treturn this;
  \t},

  \t_move: function (center, zoom, data, supressEvent) {
  \t\tif (zoom === undefined) {
  \t\t\tzoom = this._zoom;
  \t\t}
  \t\tvar zoomChanged = this._zoom !== zoom;

  \t\tthis._zoom = zoom;
  \t\tthis._lastCenter = center;
  \t\tthis._pixelOrigin = this._getNewPixelOrigin(center);

  \t\tif (!supressEvent) {
  \t\t\t// @event zoom: Event
  \t\t\t// Fired repeatedly during any change in zoom level,
  \t\t\t// including zoom and fly animations.
  \t\t\tif (zoomChanged || (data && data.pinch)) {\t// Always fire 'zoom' if pinching because #3530
  \t\t\t\tthis.fire('zoom', data);
  \t\t\t}

  \t\t\t// @event move: Event
  \t\t\t// Fired repeatedly during any movement of the map,
  \t\t\t// including pan and fly animations.
  \t\t\tthis.fire('move', data);
  \t\t} else if (data && data.pinch) {\t// Always fire 'zoom' if pinching because #3530
  \t\t\tthis.fire('zoom', data);
  \t\t}
  \t\treturn this;
  \t},

  \t_moveEnd: function (zoomChanged) {
  \t\t// @event zoomend: Event
  \t\t// Fired when the map zoom changed, after any animations.
  \t\tif (zoomChanged) {
  \t\t\tthis.fire('zoomend');
  \t\t}

  \t\t// @event moveend: Event
  \t\t// Fired when the center of the map stops changing
  \t\t// (e.g. user stopped dragging the map or after non-centered zoom).
  \t\treturn this.fire('moveend');
  \t},

  \t_stop: function () {
  \t\tcancelAnimFrame(this._flyToFrame);
  \t\tif (this._panAnim) {
  \t\t\tthis._panAnim.stop();
  \t\t}
  \t\treturn this;
  \t},

  \t_rawPanBy: function (offset) {
  \t\tsetPosition(this._mapPane, this._getMapPanePos().subtract(offset));
  \t},

  \t_getZoomSpan: function () {
  \t\treturn this.getMaxZoom() - this.getMinZoom();
  \t},

  \t_panInsideMaxBounds: function () {
  \t\tif (!this._enforcingBounds) {
  \t\t\tthis.panInsideBounds(this.options.maxBounds);
  \t\t}
  \t},

  \t_checkIfLoaded: function () {
  \t\tif (!this._loaded) {
  \t\t\tthrow new Error('Set map center and zoom first.');
  \t\t}
  \t},

  \t// DOM event handling

  \t// @section Interaction events
  \t_initEvents: function (remove) {
  \t\tthis._targets = {};
  \t\tthis._targets[stamp(this._container)] = this;

  \t\tvar onOff = remove ? off : on;

  \t\t// @event click: MouseEvent
  \t\t// Fired when the user clicks (or taps) the map.
  \t\t// @event dblclick: MouseEvent
  \t\t// Fired when the user double-clicks (or double-taps) the map.
  \t\t// @event mousedown: MouseEvent
  \t\t// Fired when the user pushes the mouse button on the map.
  \t\t// @event mouseup: MouseEvent
  \t\t// Fired when the user releases the mouse button on the map.
  \t\t// @event mouseover: MouseEvent
  \t\t// Fired when the mouse enters the map.
  \t\t// @event mouseout: MouseEvent
  \t\t// Fired when the mouse leaves the map.
  \t\t// @event mousemove: MouseEvent
  \t\t// Fired while the mouse moves over the map.
  \t\t// @event contextmenu: MouseEvent
  \t\t// Fired when the user pushes the right mouse button on the map, prevents
  \t\t// default browser context menu from showing if there are listeners on
  \t\t// this event. Also fired on mobile when the user holds a single touch
  \t\t// for a second (also called long press).
  \t\t// @event keypress: KeyboardEvent
  \t\t// Fired when the user presses a key from the keyboard that produces a character value while the map is focused.
  \t\t// @event keydown: KeyboardEvent
  \t\t// Fired when the user presses a key from the keyboard while the map is focused. Unlike the `keypress` event,
  \t\t// the `keydown` event is fired for keys that produce a character value and for keys
  \t\t// that do not produce a character value.
  \t\t// @event keyup: KeyboardEvent
  \t\t// Fired when the user releases a key from the keyboard while the map is focused.
  \t\tonOff(this._container, 'click dblclick mousedown mouseup ' +
  \t\t\t'mouseover mouseout mousemove contextmenu keypress keydown keyup', this._handleDOMEvent, this);

  \t\tif (this.options.trackResize) {
  \t\t\tonOff(window, 'resize', this._onResize, this);
  \t\t}

  \t\tif (Browser.any3d && this.options.transform3DLimit) {
  \t\t\t(remove ? this.off : this.on).call(this, 'moveend', this._onMoveEnd);
  \t\t}
  \t},

  \t_onResize: function () {
  \t\tcancelAnimFrame(this._resizeRequest);
  \t\tthis._resizeRequest = requestAnimFrame(
  \t\t        function () { this.invalidateSize({debounceMoveend: true}); }, this);
  \t},

  \t_onScroll: function () {
  \t\tthis._container.scrollTop  = 0;
  \t\tthis._container.scrollLeft = 0;
  \t},

  \t_onMoveEnd: function () {
  \t\tvar pos = this._getMapPanePos();
  \t\tif (Math.max(Math.abs(pos.x), Math.abs(pos.y)) >= this.options.transform3DLimit) {
  \t\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=1203873 but Webkit also have
  \t\t\t// a pixel offset on very high values, see: https://jsfiddle.net/dg6r5hhb/
  \t\t\tthis._resetView(this.getCenter(), this.getZoom());
  \t\t}
  \t},

  \t_findEventTargets: function (e, type) {
  \t\tvar targets = [],
  \t\t    target,
  \t\t    isHover = type === 'mouseout' || type === 'mouseover',
  \t\t    src = e.target || e.srcElement,
  \t\t    dragging = false;

  \t\twhile (src) {
  \t\t\ttarget = this._targets[stamp(src)];
  \t\t\tif (target && (type === 'click' || type === 'preclick') && this._draggableMoved(target)) {
  \t\t\t\t// Prevent firing click after you just dragged an object.
  \t\t\t\tdragging = true;
  \t\t\t\tbreak;
  \t\t\t}
  \t\t\tif (target && target.listens(type, true)) {
  \t\t\t\tif (isHover && !isExternalTarget(src, e)) { break; }
  \t\t\t\ttargets.push(target);
  \t\t\t\tif (isHover) { break; }
  \t\t\t}
  \t\t\tif (src === this._container) { break; }
  \t\t\tsrc = src.parentNode;
  \t\t}
  \t\tif (!targets.length && !dragging && !isHover && this.listens(type, true)) {
  \t\t\ttargets = [this];
  \t\t}
  \t\treturn targets;
  \t},

  \t_isClickDisabled: function (el) {
  \t\twhile (el && el !== this._container) {
  \t\t\tif (el['_leaflet_disable_click']) { return true; }
  \t\t\tel = el.parentNode;
  \t\t}
  \t},

  \t_handleDOMEvent: function (e) {
  \t\tvar el = (e.target || e.srcElement);
  \t\tif (!this._loaded || el['_leaflet_disable_events'] || e.type === 'click' && this._isClickDisabled(el)) {
  \t\t\treturn;
  \t\t}

  \t\tvar type = e.type;

  \t\tif (type === 'mousedown') {
  \t\t\t// prevents outline when clicking on keyboard-focusable element
  \t\t\tpreventOutline(el);
  \t\t}

  \t\tthis._fireDOMEvent(e, type);
  \t},

  \t_mouseEvents: ['click', 'dblclick', 'mouseover', 'mouseout', 'contextmenu'],

  \t_fireDOMEvent: function (e, type, canvasTargets) {

  \t\tif (e.type === 'click') {
  \t\t\t// Fire a synthetic 'preclick' event which propagates up (mainly for closing popups).
  \t\t\t// @event preclick: MouseEvent
  \t\t\t// Fired before mouse click on the map (sometimes useful when you
  \t\t\t// want something to happen on click before any existing click
  \t\t\t// handlers start running).
  \t\t\tvar synth = extend({}, e);
  \t\t\tsynth.type = 'preclick';
  \t\t\tthis._fireDOMEvent(synth, synth.type, canvasTargets);
  \t\t}

  \t\t// Find the layer the event is propagating from and its parents.
  \t\tvar targets = this._findEventTargets(e, type);

  \t\tif (canvasTargets) {
  \t\t\tvar filtered = []; // pick only targets with listeners
  \t\t\tfor (var i = 0; i < canvasTargets.length; i++) {
  \t\t\t\tif (canvasTargets[i].listens(type, true)) {
  \t\t\t\t\tfiltered.push(canvasTargets[i]);
  \t\t\t\t}
  \t\t\t}
  \t\t\ttargets = filtered.concat(targets);
  \t\t}

  \t\tif (!targets.length) { return; }

  \t\tif (type === 'contextmenu') {
  \t\t\tpreventDefault(e);
  \t\t}

  \t\tvar target = targets[0];
  \t\tvar data = {
  \t\t\toriginalEvent: e
  \t\t};

  \t\tif (e.type !== 'keypress' && e.type !== 'keydown' && e.type !== 'keyup') {
  \t\t\tvar isMarker = target.getLatLng && (!target._radius || target._radius <= 10);
  \t\t\tdata.containerPoint = isMarker ?
  \t\t\t\tthis.latLngToContainerPoint(target.getLatLng()) : this.mouseEventToContainerPoint(e);
  \t\t\tdata.layerPoint = this.containerPointToLayerPoint(data.containerPoint);
  \t\t\tdata.latlng = isMarker ? target.getLatLng() : this.layerPointToLatLng(data.layerPoint);
  \t\t}

  \t\tfor (i = 0; i < targets.length; i++) {
  \t\t\ttargets[i].fire(type, data, true);
  \t\t\tif (data.originalEvent._stopped ||
  \t\t\t\t(targets[i].options.bubblingMouseEvents === false && indexOf(this._mouseEvents, type) !== -1)) { return; }
  \t\t}
  \t},

  \t_draggableMoved: function (obj) {
  \t\tobj = obj.dragging && obj.dragging.enabled() ? obj : this;
  \t\treturn (obj.dragging && obj.dragging.moved()) || (this.boxZoom && this.boxZoom.moved());
  \t},

  \t_clearHandlers: function () {
  \t\tfor (var i = 0, len = this._handlers.length; i < len; i++) {
  \t\t\tthis._handlers[i].disable();
  \t\t}
  \t},

  \t// @section Other Methods

  \t// @method whenReady(fn: Function, context?: Object): this
  \t// Runs the given function `fn` when the map gets initialized with
  \t// a view (center and zoom) and at least one layer, or immediately
  \t// if it's already initialized, optionally passing a function context.
  \twhenReady: function (callback, context) {
  \t\tif (this._loaded) {
  \t\t\tcallback.call(context || this, {target: this});
  \t\t} else {
  \t\t\tthis.on('load', callback, context);
  \t\t}
  \t\treturn this;
  \t},


  \t// private methods for getting map state

  \t_getMapPanePos: function () {
  \t\treturn getPosition(this._mapPane) || new Point(0, 0);
  \t},

  \t_moved: function () {
  \t\tvar pos = this._getMapPanePos();
  \t\treturn pos && !pos.equals([0, 0]);
  \t},

  \t_getTopLeftPoint: function (center, zoom) {
  \t\tvar pixelOrigin = center && zoom !== undefined ?
  \t\t\tthis._getNewPixelOrigin(center, zoom) :
  \t\t\tthis.getPixelOrigin();
  \t\treturn pixelOrigin.subtract(this._getMapPanePos());
  \t},

  \t_getNewPixelOrigin: function (center, zoom) {
  \t\tvar viewHalf = this.getSize()._divideBy(2);
  \t\treturn this.project(center, zoom)._subtract(viewHalf)._add(this._getMapPanePos())._round();
  \t},

  \t_latLngToNewLayerPoint: function (latlng, zoom, center) {
  \t\tvar topLeft = this._getNewPixelOrigin(center, zoom);
  \t\treturn this.project(latlng, zoom)._subtract(topLeft);
  \t},

  \t_latLngBoundsToNewLayerBounds: function (latLngBounds, zoom, center) {
  \t\tvar topLeft = this._getNewPixelOrigin(center, zoom);
  \t\treturn toBounds([
  \t\t\tthis.project(latLngBounds.getSouthWest(), zoom)._subtract(topLeft),
  \t\t\tthis.project(latLngBounds.getNorthWest(), zoom)._subtract(topLeft),
  \t\t\tthis.project(latLngBounds.getSouthEast(), zoom)._subtract(topLeft),
  \t\t\tthis.project(latLngBounds.getNorthEast(), zoom)._subtract(topLeft)
  \t\t]);
  \t},

  \t// layer point of the current center
  \t_getCenterLayerPoint: function () {
  \t\treturn this.containerPointToLayerPoint(this.getSize()._divideBy(2));
  \t},

  \t// offset of the specified place to the current center in pixels
  \t_getCenterOffset: function (latlng) {
  \t\treturn this.latLngToLayerPoint(latlng).subtract(this._getCenterLayerPoint());
  \t},

  \t// adjust center for view to get inside bounds
  \t_limitCenter: function (center, zoom, bounds) {

  \t\tif (!bounds) { return center; }

  \t\tvar centerPoint = this.project(center, zoom),
  \t\t    viewHalf = this.getSize().divideBy(2),
  \t\t    viewBounds = new Bounds(centerPoint.subtract(viewHalf), centerPoint.add(viewHalf)),
  \t\t    offset = this._getBoundsOffset(viewBounds, bounds, zoom);

  \t\t// If offset is less than a pixel, ignore.
  \t\t// This prevents unstable projections from getting into
  \t\t// an infinite loop of tiny offsets.
  \t\tif (Math.abs(offset.x) <= 1 && Math.abs(offset.y) <= 1) {
  \t\t\treturn center;
  \t\t}

  \t\treturn this.unproject(centerPoint.add(offset), zoom);
  \t},

  \t// adjust offset for view to get inside bounds
  \t_limitOffset: function (offset, bounds) {
  \t\tif (!bounds) { return offset; }

  \t\tvar viewBounds = this.getPixelBounds(),
  \t\t    newBounds = new Bounds(viewBounds.min.add(offset), viewBounds.max.add(offset));

  \t\treturn offset.add(this._getBoundsOffset(newBounds, bounds));
  \t},

  \t// returns offset needed for pxBounds to get inside maxBounds at a specified zoom
  \t_getBoundsOffset: function (pxBounds, maxBounds, zoom) {
  \t\tvar projectedMaxBounds = toBounds(
  \t\t        this.project(maxBounds.getNorthEast(), zoom),
  \t\t        this.project(maxBounds.getSouthWest(), zoom)
  \t\t    ),
  \t\t    minOffset = projectedMaxBounds.min.subtract(pxBounds.min),
  \t\t    maxOffset = projectedMaxBounds.max.subtract(pxBounds.max),

  \t\t    dx = this._rebound(minOffset.x, -maxOffset.x),
  \t\t    dy = this._rebound(minOffset.y, -maxOffset.y);

  \t\treturn new Point(dx, dy);
  \t},

  \t_rebound: function (left, right) {
  \t\treturn left + right > 0 ?
  \t\t\tMath.round(left - right) / 2 :
  \t\t\tMath.max(0, Math.ceil(left)) - Math.max(0, Math.floor(right));
  \t},

  \t_limitZoom: function (zoom) {
  \t\tvar min = this.getMinZoom(),
  \t\t    max = this.getMaxZoom(),
  \t\t    snap = Browser.any3d ? this.options.zoomSnap : 1;
  \t\tif (snap) {
  \t\t\tzoom = Math.round(zoom / snap) * snap;
  \t\t}
  \t\treturn Math.max(min, Math.min(max, zoom));
  \t},

  \t_onPanTransitionStep: function () {
  \t\tthis.fire('move');
  \t},

  \t_onPanTransitionEnd: function () {
  \t\tremoveClass(this._mapPane, 'leaflet-pan-anim');
  \t\tthis.fire('moveend');
  \t},

  \t_tryAnimatedPan: function (center, options) {
  \t\t// difference between the new and current centers in pixels
  \t\tvar offset = this._getCenterOffset(center)._trunc();

  \t\t// don't animate too far unless animate: true specified in options
  \t\tif ((options && options.animate) !== true && !this.getSize().contains(offset)) { return false; }

  \t\tthis.panBy(offset, options);

  \t\treturn true;
  \t},

  \t_createAnimProxy: function () {

  \t\tvar proxy = this._proxy = create\$1('div', 'leaflet-proxy leaflet-zoom-animated');
  \t\tthis._panes.mapPane.appendChild(proxy);

  \t\tthis.on('zoomanim', function (e) {
  \t\t\tvar prop = TRANSFORM,
  \t\t\t    transform = this._proxy.style[prop];

  \t\t\tsetTransform(this._proxy, this.project(e.center, e.zoom), this.getZoomScale(e.zoom, 1));

  \t\t\t// workaround for case when transform is the same and so transitionend event is not fired
  \t\t\tif (transform === this._proxy.style[prop] && this._animatingZoom) {
  \t\t\t\tthis._onZoomTransitionEnd();
  \t\t\t}
  \t\t}, this);

  \t\tthis.on('load moveend', this._animMoveEnd, this);

  \t\tthis._on('unload', this._destroyAnimProxy, this);
  \t},

  \t_destroyAnimProxy: function () {
  \t\tremove(this._proxy);
  \t\tthis.off('load moveend', this._animMoveEnd, this);
  \t\tdelete this._proxy;
  \t},

  \t_animMoveEnd: function () {
  \t\tvar c = this.getCenter(),
  \t\t    z = this.getZoom();
  \t\tsetTransform(this._proxy, this.project(c, z), this.getZoomScale(z, 1));
  \t},

  \t_catchTransitionEnd: function (e) {
  \t\tif (this._animatingZoom && e.propertyName.indexOf('transform') >= 0) {
  \t\t\tthis._onZoomTransitionEnd();
  \t\t}
  \t},

  \t_nothingToAnimate: function () {
  \t\treturn !this._container.getElementsByClassName('leaflet-zoom-animated').length;
  \t},

  \t_tryAnimatedZoom: function (center, zoom, options) {

  \t\tif (this._animatingZoom) { return true; }

  \t\toptions = options || {};

  \t\t// don't animate if disabled, not supported or zoom difference is too large
  \t\tif (!this._zoomAnimated || options.animate === false || this._nothingToAnimate() ||
  \t\t        Math.abs(zoom - this._zoom) > this.options.zoomAnimationThreshold) { return false; }

  \t\t// offset is the pixel coords of the zoom origin relative to the current center
  \t\tvar scale = this.getZoomScale(zoom),
  \t\t    offset = this._getCenterOffset(center)._divideBy(1 - 1 / scale);

  \t\t// don't animate if the zoom origin isn't within one screen from the current center, unless forced
  \t\tif (options.animate !== true && !this.getSize().contains(offset)) { return false; }

  \t\trequestAnimFrame(function () {
  \t\t\tthis
  \t\t\t    ._moveStart(true, options.noMoveStart || false)
  \t\t\t    ._animateZoom(center, zoom, true);
  \t\t}, this);

  \t\treturn true;
  \t},

  \t_animateZoom: function (center, zoom, startAnim, noUpdate) {
  \t\tif (!this._mapPane) { return; }

  \t\tif (startAnim) {
  \t\t\tthis._animatingZoom = true;

  \t\t\t// remember what center/zoom to set after animation
  \t\t\tthis._animateToCenter = center;
  \t\t\tthis._animateToZoom = zoom;

  \t\t\taddClass(this._mapPane, 'leaflet-zoom-anim');
  \t\t}

  \t\t// @section Other Events
  \t\t// @event zoomanim: ZoomAnimEvent
  \t\t// Fired at least once per zoom animation. For continuous zoom, like pinch zooming, fired once per frame during zoom.
  \t\tthis.fire('zoomanim', {
  \t\t\tcenter: center,
  \t\t\tzoom: zoom,
  \t\t\tnoUpdate: noUpdate
  \t\t});

  \t\tif (!this._tempFireZoomEvent) {
  \t\t\tthis._tempFireZoomEvent = this._zoom !== this._animateToZoom;
  \t\t}

  \t\tthis._move(this._animateToCenter, this._animateToZoom, undefined, true);

  \t\t// Work around webkit not firing 'transitionend', see https://github.com/Leaflet/Leaflet/issues/3689, 2693
  \t\tsetTimeout(bind(this._onZoomTransitionEnd, this), 250);
  \t},

  \t_onZoomTransitionEnd: function () {
  \t\tif (!this._animatingZoom) { return; }

  \t\tif (this._mapPane) {
  \t\t\tremoveClass(this._mapPane, 'leaflet-zoom-anim');
  \t\t}

  \t\tthis._animatingZoom = false;

  \t\tthis._move(this._animateToCenter, this._animateToZoom, undefined, true);

  \t\tif (this._tempFireZoomEvent) {
  \t\t\tthis.fire('zoom');
  \t\t}
  \t\tdelete this._tempFireZoomEvent;

  \t\tthis.fire('move');

  \t\tthis._moveEnd(true);
  \t}
  });

  // @section

  // @factory L.map(id: String, options?: Map options)
  // Instantiates a map object given the DOM ID of a `<div>` element
  // and optionally an object literal with `Map options`.
  //
  // @alternative
  // @factory L.map(el: HTMLElement, options?: Map options)
  // Instantiates a map object given an instance of a `<div>` HTML element
  // and optionally an object literal with `Map options`.
  function createMap(id, options) {
  \treturn new Map(id, options);
  }

  /*
   * @class Control
   * @aka L.Control
   * @inherits Class
   *
   * L.Control is a base class for implementing map controls. Handles positioning.
   * All other controls extend from this class.
   */

  var Control = Class.extend({
  \t// @section
  \t// @aka Control Options
  \toptions: {
  \t\t// @option position: String = 'topright'
  \t\t// The position of the control (one of the map corners). Possible values are `'topleft'`,
  \t\t// `'topright'`, `'bottomleft'` or `'bottomright'`
  \t\tposition: 'topright'
  \t},

  \tinitialize: function (options) {
  \t\tsetOptions(this, options);
  \t},

  \t/* @section
  \t * Classes extending L.Control will inherit the following methods:
  \t *
  \t * @method getPosition: string
  \t * Returns the position of the control.
  \t */
  \tgetPosition: function () {
  \t\treturn this.options.position;
  \t},

  \t// @method setPosition(position: string): this
  \t// Sets the position of the control.
  \tsetPosition: function (position) {
  \t\tvar map = this._map;

  \t\tif (map) {
  \t\t\tmap.removeControl(this);
  \t\t}

  \t\tthis.options.position = position;

  \t\tif (map) {
  \t\t\tmap.addControl(this);
  \t\t}

  \t\treturn this;
  \t},

  \t// @method getContainer: HTMLElement
  \t// Returns the HTMLElement that contains the control.
  \tgetContainer: function () {
  \t\treturn this._container;
  \t},

  \t// @method addTo(map: Map): this
  \t// Adds the control to the given map.
  \taddTo: function (map) {
  \t\tthis.remove();
  \t\tthis._map = map;

  \t\tvar container = this._container = this.onAdd(map),
  \t\t    pos = this.getPosition(),
  \t\t    corner = map._controlCorners[pos];

  \t\taddClass(container, 'leaflet-control');

  \t\tif (pos.indexOf('bottom') !== -1) {
  \t\t\tcorner.insertBefore(container, corner.firstChild);
  \t\t} else {
  \t\t\tcorner.appendChild(container);
  \t\t}

  \t\tthis._map.on('unload', this.remove, this);

  \t\treturn this;
  \t},

  \t// @method remove: this
  \t// Removes the control from the map it is currently active on.
  \tremove: function () {
  \t\tif (!this._map) {
  \t\t\treturn this;
  \t\t}

  \t\tremove(this._container);

  \t\tif (this.onRemove) {
  \t\t\tthis.onRemove(this._map);
  \t\t}

  \t\tthis._map.off('unload', this.remove, this);
  \t\tthis._map = null;

  \t\treturn this;
  \t},

  \t_refocusOnMap: function (e) {
  \t\t// if map exists and event is not a keyboard event
  \t\tif (this._map && e && e.screenX > 0 && e.screenY > 0) {
  \t\t\tthis._map.getContainer().focus();
  \t\t}
  \t}
  });

  var control = function (options) {
  \treturn new Control(options);
  };

  /* @section Extension methods
   * @uninheritable
   *
   * Every control should extend from `L.Control` and (re-)implement the following methods.
   *
   * @method onAdd(map: Map): HTMLElement
   * Should return the container DOM element for the control and add listeners on relevant map events. Called on [`control.addTo(map)`](#control-addTo).
   *
   * @method onRemove(map: Map)
   * Optional method. Should contain all clean up code that removes the listeners previously added in [`onAdd`](#control-onadd). Called on [`control.remove()`](#control-remove).
   */

  /* @namespace Map
   * @section Methods for Layers and Controls
   */
  Map.include({
  \t// @method addControl(control: Control): this
  \t// Adds the given control to the map
  \taddControl: function (control) {
  \t\tcontrol.addTo(this);
  \t\treturn this;
  \t},

  \t// @method removeControl(control: Control): this
  \t// Removes the given control from the map
  \tremoveControl: function (control) {
  \t\tcontrol.remove();
  \t\treturn this;
  \t},

  \t_initControlPos: function () {
  \t\tvar corners = this._controlCorners = {},
  \t\t    l = 'leaflet-',
  \t\t    container = this._controlContainer =
  \t\t            create\$1('div', l + 'control-container', this._container);

  \t\tfunction createCorner(vSide, hSide) {
  \t\t\tvar className = l + vSide + ' ' + l + hSide;

  \t\t\tcorners[vSide + hSide] = create\$1('div', className, container);
  \t\t}

  \t\tcreateCorner('top', 'left');
  \t\tcreateCorner('top', 'right');
  \t\tcreateCorner('bottom', 'left');
  \t\tcreateCorner('bottom', 'right');
  \t},

  \t_clearControlPos: function () {
  \t\tfor (var i in this._controlCorners) {
  \t\t\tremove(this._controlCorners[i]);
  \t\t}
  \t\tremove(this._controlContainer);
  \t\tdelete this._controlCorners;
  \t\tdelete this._controlContainer;
  \t}
  });

  /*
   * @class Control.Layers
   * @aka L.Control.Layers
   * @inherits Control
   *
   * The layers control gives users the ability to switch between different base layers and switch overlays on/off (check out the [detailed example](https://leafletjs.com/examples/layers-control/)). Extends `Control`.
   *
   * @example
   *
   * ```js
   * var baseLayers = {
   * \t\"Mapbox\": mapbox,
   * \t\"OpenStreetMap\": osm
   * };
   *
   * var overlays = {
   * \t\"Marker\": marker,
   * \t\"Roads\": roadsLayer
   * };
   *
   * L.control.layers(baseLayers, overlays).addTo(map);
   * ```
   *
   * The `baseLayers` and `overlays` parameters are object literals with layer names as keys and `Layer` objects as values:
   *
   * ```js
   * {
   *     \"<someName1>\": layer1,
   *     \"<someName2>\": layer2
   * }
   * ```
   *
   * The layer names can contain HTML, which allows you to add additional styling to the items:
   *
   * ```js
   * {\"<img src='my-layer-icon' /> <span class='my-layer-item'>My Layer</span>\": myLayer}
   * ```
   */

  var Layers = Control.extend({
  \t// @section
  \t// @aka Control.Layers options
  \toptions: {
  \t\t// @option collapsed: Boolean = true
  \t\t// If `true`, the control will be collapsed into an icon and expanded on mouse hover, touch, or keyboard activation.
  \t\tcollapsed: true,
  \t\tposition: 'topright',

  \t\t// @option autoZIndex: Boolean = true
  \t\t// If `true`, the control will assign zIndexes in increasing order to all of its layers so that the order is preserved when switching them on/off.
  \t\tautoZIndex: true,

  \t\t// @option hideSingleBase: Boolean = false
  \t\t// If `true`, the base layers in the control will be hidden when there is only one.
  \t\thideSingleBase: false,

  \t\t// @option sortLayers: Boolean = false
  \t\t// Whether to sort the layers. When `false`, layers will keep the order
  \t\t// in which they were added to the control.
  \t\tsortLayers: false,

  \t\t// @option sortFunction: Function = *
  \t\t// A [compare function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)
  \t\t// that will be used for sorting the layers, when `sortLayers` is `true`.
  \t\t// The function receives both the `L.Layer` instances and their names, as in
  \t\t// `sortFunction(layerA, layerB, nameA, nameB)`.
  \t\t// By default, it sorts layers alphabetically by their name.
  \t\tsortFunction: function (layerA, layerB, nameA, nameB) {
  \t\t\treturn nameA < nameB ? -1 : (nameB < nameA ? 1 : 0);
  \t\t}
  \t},

  \tinitialize: function (baseLayers, overlays, options) {
  \t\tsetOptions(this, options);

  \t\tthis._layerControlInputs = [];
  \t\tthis._layers = [];
  \t\tthis._lastZIndex = 0;
  \t\tthis._handlingClick = false;
  \t\tthis._preventClick = false;

  \t\tfor (var i in baseLayers) {
  \t\t\tthis._addLayer(baseLayers[i], i);
  \t\t}

  \t\tfor (i in overlays) {
  \t\t\tthis._addLayer(overlays[i], i, true);
  \t\t}
  \t},

  \tonAdd: function (map) {
  \t\tthis._initLayout();
  \t\tthis._update();

  \t\tthis._map = map;
  \t\tmap.on('zoomend', this._checkDisabledLayers, this);

  \t\tfor (var i = 0; i < this._layers.length; i++) {
  \t\t\tthis._layers[i].layer.on('add remove', this._onLayerChange, this);
  \t\t}

  \t\treturn this._container;
  \t},

  \taddTo: function (map) {
  \t\tControl.prototype.addTo.call(this, map);
  \t\t// Trigger expand after Layers Control has been inserted into DOM so that is now has an actual height.
  \t\treturn this._expandIfNotCollapsed();
  \t},

  \tonRemove: function () {
  \t\tthis._map.off('zoomend', this._checkDisabledLayers, this);

  \t\tfor (var i = 0; i < this._layers.length; i++) {
  \t\t\tthis._layers[i].layer.off('add remove', this._onLayerChange, this);
  \t\t}
  \t},

  \t// @method addBaseLayer(layer: Layer, name: String): this
  \t// Adds a base layer (radio button entry) with the given name to the control.
  \taddBaseLayer: function (layer, name) {
  \t\tthis._addLayer(layer, name);
  \t\treturn (this._map) ? this._update() : this;
  \t},

  \t// @method addOverlay(layer: Layer, name: String): this
  \t// Adds an overlay (checkbox entry) with the given name to the control.
  \taddOverlay: function (layer, name) {
  \t\tthis._addLayer(layer, name, true);
  \t\treturn (this._map) ? this._update() : this;
  \t},

  \t// @method removeLayer(layer: Layer): this
  \t// Remove the given layer from the control.
  \tremoveLayer: function (layer) {
  \t\tlayer.off('add remove', this._onLayerChange, this);

  \t\tvar obj = this._getLayer(stamp(layer));
  \t\tif (obj) {
  \t\t\tthis._layers.splice(this._layers.indexOf(obj), 1);
  \t\t}
  \t\treturn (this._map) ? this._update() : this;
  \t},

  \t// @method expand(): this
  \t// Expand the control container if collapsed.
  \texpand: function () {
  \t\taddClass(this._container, 'leaflet-control-layers-expanded');
  \t\tthis._section.style.height = null;
  \t\tvar acceptableHeight = this._map.getSize().y - (this._container.offsetTop + 50);
  \t\tif (acceptableHeight < this._section.clientHeight) {
  \t\t\taddClass(this._section, 'leaflet-control-layers-scrollbar');
  \t\t\tthis._section.style.height = acceptableHeight + 'px';
  \t\t} else {
  \t\t\tremoveClass(this._section, 'leaflet-control-layers-scrollbar');
  \t\t}
  \t\tthis._checkDisabledLayers();
  \t\treturn this;
  \t},

  \t// @method collapse(): this
  \t// Collapse the control container if expanded.
  \tcollapse: function () {
  \t\tremoveClass(this._container, 'leaflet-control-layers-expanded');
  \t\treturn this;
  \t},

  \t_initLayout: function () {
  \t\tvar className = 'leaflet-control-layers',
  \t\t    container = this._container = create\$1('div', className),
  \t\t    collapsed = this.options.collapsed;

  \t\t// makes this work on IE touch devices by stopping it from firing a mouseout event when the touch is released
  \t\tcontainer.setAttribute('aria-haspopup', true);

  \t\tdisableClickPropagation(container);
  \t\tdisableScrollPropagation(container);

  \t\tvar section = this._section = create\$1('section', className + '-list');

  \t\tif (collapsed) {
  \t\t\tthis._map.on('click', this.collapse, this);

  \t\t\ton(container, {
  \t\t\t\tmouseenter: this._expandSafely,
  \t\t\t\tmouseleave: this.collapse
  \t\t\t}, this);
  \t\t}

  \t\tvar link = this._layersLink = create\$1('a', className + '-toggle', container);
  \t\tlink.href = '#';
  \t\tlink.title = 'Layers';
  \t\tlink.setAttribute('role', 'button');

  \t\ton(link, {
  \t\t\tkeydown: function (e) {
  \t\t\t\tif (e.keyCode === 13) {
  \t\t\t\t\tthis._expandSafely();
  \t\t\t\t}
  \t\t\t},
  \t\t\t// Certain screen readers intercept the key event and instead send a click event
  \t\t\tclick: function (e) {
  \t\t\t\tpreventDefault(e);
  \t\t\t\tthis._expandSafely();
  \t\t\t}
  \t\t}, this);

  \t\tif (!collapsed) {
  \t\t\tthis.expand();
  \t\t}

  \t\tthis._baseLayersList = create\$1('div', className + '-base', section);
  \t\tthis._separator = create\$1('div', className + '-separator', section);
  \t\tthis._overlaysList = create\$1('div', className + '-overlays', section);

  \t\tcontainer.appendChild(section);
  \t},

  \t_getLayer: function (id) {
  \t\tfor (var i = 0; i < this._layers.length; i++) {

  \t\t\tif (this._layers[i] && stamp(this._layers[i].layer) === id) {
  \t\t\t\treturn this._layers[i];
  \t\t\t}
  \t\t}
  \t},

  \t_addLayer: function (layer, name, overlay) {
  \t\tif (this._map) {
  \t\t\tlayer.on('add remove', this._onLayerChange, this);
  \t\t}

  \t\tthis._layers.push({
  \t\t\tlayer: layer,
  \t\t\tname: name,
  \t\t\toverlay: overlay
  \t\t});

  \t\tif (this.options.sortLayers) {
  \t\t\tthis._layers.sort(bind(function (a, b) {
  \t\t\t\treturn this.options.sortFunction(a.layer, b.layer, a.name, b.name);
  \t\t\t}, this));
  \t\t}

  \t\tif (this.options.autoZIndex && layer.setZIndex) {
  \t\t\tthis._lastZIndex++;
  \t\t\tlayer.setZIndex(this._lastZIndex);
  \t\t}

  \t\tthis._expandIfNotCollapsed();
  \t},

  \t_update: function () {
  \t\tif (!this._container) { return this; }

  \t\tempty(this._baseLayersList);
  \t\tempty(this._overlaysList);

  \t\tthis._layerControlInputs = [];
  \t\tvar baseLayersPresent, overlaysPresent, i, obj, baseLayersCount = 0;

  \t\tfor (i = 0; i < this._layers.length; i++) {
  \t\t\tobj = this._layers[i];
  \t\t\tthis._addItem(obj);
  \t\t\toverlaysPresent = overlaysPresent || obj.overlay;
  \t\t\tbaseLayersPresent = baseLayersPresent || !obj.overlay;
  \t\t\tbaseLayersCount += !obj.overlay ? 1 : 0;
  \t\t}

  \t\t// Hide base layers section if there's only one layer.
  \t\tif (this.options.hideSingleBase) {
  \t\t\tbaseLayersPresent = baseLayersPresent && baseLayersCount > 1;
  \t\t\tthis._baseLayersList.style.display = baseLayersPresent ? '' : 'none';
  \t\t}

  \t\tthis._separator.style.display = overlaysPresent && baseLayersPresent ? '' : 'none';

  \t\treturn this;
  \t},

  \t_onLayerChange: function (e) {
  \t\tif (!this._handlingClick) {
  \t\t\tthis._update();
  \t\t}

  \t\tvar obj = this._getLayer(stamp(e.target));

  \t\t// @namespace Map
  \t\t// @section Layer events
  \t\t// @event baselayerchange: LayersControlEvent
  \t\t// Fired when the base layer is changed through the [layers control](#control-layers).
  \t\t// @event overlayadd: LayersControlEvent
  \t\t// Fired when an overlay is selected through the [layers control](#control-layers).
  \t\t// @event overlayremove: LayersControlEvent
  \t\t// Fired when an overlay is deselected through the [layers control](#control-layers).
  \t\t// @namespace Control.Layers
  \t\tvar type = obj.overlay ?
  \t\t\t(e.type === 'add' ? 'overlayadd' : 'overlayremove') :
  \t\t\t(e.type === 'add' ? 'baselayerchange' : null);

  \t\tif (type) {
  \t\t\tthis._map.fire(type, obj);
  \t\t}
  \t},

  \t// IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see https://stackoverflow.com/a/119079)
  \t_createRadioElement: function (name, checked) {

  \t\tvar radioHtml = '<input type=\"radio\" class=\"leaflet-control-layers-selector\" name=\"' +
  \t\t\t\tname + '\"' + (checked ? ' checked=\"checked\"' : '') + '/>';

  \t\tvar radioFragment = document.createElement('div');
  \t\tradioFragment.innerHTML = radioHtml;

  \t\treturn radioFragment.firstChild;
  \t},

  \t_addItem: function (obj) {
  \t\tvar label = document.createElement('label'),
  \t\t    checked = this._map.hasLayer(obj.layer),
  \t\t    input;

  \t\tif (obj.overlay) {
  \t\t\tinput = document.createElement('input');
  \t\t\tinput.type = 'checkbox';
  \t\t\tinput.className = 'leaflet-control-layers-selector';
  \t\t\tinput.defaultChecked = checked;
  \t\t} else {
  \t\t\tinput = this._createRadioElement('leaflet-base-layers_' + stamp(this), checked);
  \t\t}

  \t\tthis._layerControlInputs.push(input);
  \t\tinput.layerId = stamp(obj.layer);

  \t\ton(input, 'click', this._onInputClick, this);

  \t\tvar name = document.createElement('span');
  \t\tname.innerHTML = ' ' + obj.name;

  \t\t// Helps from preventing layer control flicker when checkboxes are disabled
  \t\t// https://github.com/Leaflet/Leaflet/issues/2771
  \t\tvar holder = document.createElement('span');

  \t\tlabel.appendChild(holder);
  \t\tholder.appendChild(input);
  \t\tholder.appendChild(name);

  \t\tvar container = obj.overlay ? this._overlaysList : this._baseLayersList;
  \t\tcontainer.appendChild(label);

  \t\tthis._checkDisabledLayers();
  \t\treturn label;
  \t},

  \t_onInputClick: function () {
  \t\t// expanding the control on mobile with a click can cause adding a layer - we don't want this
  \t\tif (this._preventClick) {
  \t\t\treturn;
  \t\t}

  \t\tvar inputs = this._layerControlInputs,
  \t\t    input, layer;
  \t\tvar addedLayers = [],
  \t\t    removedLayers = [];

  \t\tthis._handlingClick = true;

  \t\tfor (var i = inputs.length - 1; i >= 0; i--) {
  \t\t\tinput = inputs[i];
  \t\t\tlayer = this._getLayer(input.layerId).layer;

  \t\t\tif (input.checked) {
  \t\t\t\taddedLayers.push(layer);
  \t\t\t} else if (!input.checked) {
  \t\t\t\tremovedLayers.push(layer);
  \t\t\t}
  \t\t}

  \t\t// Bugfix issue 2318: Should remove all old layers before readding new ones
  \t\tfor (i = 0; i < removedLayers.length; i++) {
  \t\t\tif (this._map.hasLayer(removedLayers[i])) {
  \t\t\t\tthis._map.removeLayer(removedLayers[i]);
  \t\t\t}
  \t\t}
  \t\tfor (i = 0; i < addedLayers.length; i++) {
  \t\t\tif (!this._map.hasLayer(addedLayers[i])) {
  \t\t\t\tthis._map.addLayer(addedLayers[i]);
  \t\t\t}
  \t\t}

  \t\tthis._handlingClick = false;

  \t\tthis._refocusOnMap();
  \t},

  \t_checkDisabledLayers: function () {
  \t\tvar inputs = this._layerControlInputs,
  \t\t    input,
  \t\t    layer,
  \t\t    zoom = this._map.getZoom();

  \t\tfor (var i = inputs.length - 1; i >= 0; i--) {
  \t\t\tinput = inputs[i];
  \t\t\tlayer = this._getLayer(input.layerId).layer;
  \t\t\tinput.disabled = (layer.options.minZoom !== undefined && zoom < layer.options.minZoom) ||
  \t\t\t                 (layer.options.maxZoom !== undefined && zoom > layer.options.maxZoom);

  \t\t}
  \t},

  \t_expandIfNotCollapsed: function () {
  \t\tif (this._map && !this.options.collapsed) {
  \t\t\tthis.expand();
  \t\t}
  \t\treturn this;
  \t},

  \t_expandSafely: function () {
  \t\tvar section = this._section;
  \t\tthis._preventClick = true;
  \t\ton(section, 'click', preventDefault);
  \t\tthis.expand();
  \t\tvar that = this;
  \t\tsetTimeout(function () {
  \t\t\toff(section, 'click', preventDefault);
  \t\t\tthat._preventClick = false;
  \t\t});
  \t}

  });


  // @factory L.control.layers(baselayers?: Object, overlays?: Object, options?: Control.Layers options)
  // Creates a layers control with the given layers. Base layers will be switched with radio buttons, while overlays will be switched with checkboxes. Note that all base layers should be passed in the base layers object, but only one should be added to the map during map instantiation.
  var layers = function (baseLayers, overlays, options) {
  \treturn new Layers(baseLayers, overlays, options);
  };

  /*
   * @class Control.Zoom
   * @aka L.Control.Zoom
   * @inherits Control
   *
   * A basic zoom control with two buttons (zoom in and zoom out). It is put on the map by default unless you set its [`zoomControl` option](#map-zoomcontrol) to `false`. Extends `Control`.
   */

  var Zoom = Control.extend({
  \t// @section
  \t// @aka Control.Zoom options
  \toptions: {
  \t\tposition: 'topleft',

  \t\t// @option zoomInText: String = '<span aria-hidden=\"true\">+</span>'
  \t\t// The text set on the 'zoom in' button.
  \t\tzoomInText: '<span aria-hidden=\"true\">+</span>',

  \t\t// @option zoomInTitle: String = 'Zoom in'
  \t\t// The title set on the 'zoom in' button.
  \t\tzoomInTitle: 'Zoom in',

  \t\t// @option zoomOutText: String = '<span aria-hidden=\"true\">&#x2212;</span>'
  \t\t// The text set on the 'zoom out' button.
  \t\tzoomOutText: '<span aria-hidden=\"true\">&#x2212;</span>',

  \t\t// @option zoomOutTitle: String = 'Zoom out'
  \t\t// The title set on the 'zoom out' button.
  \t\tzoomOutTitle: 'Zoom out'
  \t},

  \tonAdd: function (map) {
  \t\tvar zoomName = 'leaflet-control-zoom',
  \t\t    container = create\$1('div', zoomName + ' leaflet-bar'),
  \t\t    options = this.options;

  \t\tthis._zoomInButton  = this._createButton(options.zoomInText, options.zoomInTitle,
  \t\t        zoomName + '-in',  container, this._zoomIn);
  \t\tthis._zoomOutButton = this._createButton(options.zoomOutText, options.zoomOutTitle,
  \t\t        zoomName + '-out', container, this._zoomOut);

  \t\tthis._updateDisabled();
  \t\tmap.on('zoomend zoomlevelschange', this._updateDisabled, this);

  \t\treturn container;
  \t},

  \tonRemove: function (map) {
  \t\tmap.off('zoomend zoomlevelschange', this._updateDisabled, this);
  \t},

  \tdisable: function () {
  \t\tthis._disabled = true;
  \t\tthis._updateDisabled();
  \t\treturn this;
  \t},

  \tenable: function () {
  \t\tthis._disabled = false;
  \t\tthis._updateDisabled();
  \t\treturn this;
  \t},

  \t_zoomIn: function (e) {
  \t\tif (!this._disabled && this._map._zoom < this._map.getMaxZoom()) {
  \t\t\tthis._map.zoomIn(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1));
  \t\t}
  \t},

  \t_zoomOut: function (e) {
  \t\tif (!this._disabled && this._map._zoom > this._map.getMinZoom()) {
  \t\t\tthis._map.zoomOut(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1));
  \t\t}
  \t},

  \t_createButton: function (html, title, className, container, fn) {
  \t\tvar link = create\$1('a', className, container);
  \t\tlink.innerHTML = html;
  \t\tlink.href = '#';
  \t\tlink.title = title;

  \t\t/*
  \t\t * Will force screen readers like VoiceOver to read this as \"Zoom in - button\"
  \t\t */
  \t\tlink.setAttribute('role', 'button');
  \t\tlink.setAttribute('aria-label', title);

  \t\tdisableClickPropagation(link);
  \t\ton(link, 'click', stop);
  \t\ton(link, 'click', fn, this);
  \t\ton(link, 'click', this._refocusOnMap, this);

  \t\treturn link;
  \t},

  \t_updateDisabled: function () {
  \t\tvar map = this._map,
  \t\t    className = 'leaflet-disabled';

  \t\tremoveClass(this._zoomInButton, className);
  \t\tremoveClass(this._zoomOutButton, className);
  \t\tthis._zoomInButton.setAttribute('aria-disabled', 'false');
  \t\tthis._zoomOutButton.setAttribute('aria-disabled', 'false');

  \t\tif (this._disabled || map._zoom === map.getMinZoom()) {
  \t\t\taddClass(this._zoomOutButton, className);
  \t\t\tthis._zoomOutButton.setAttribute('aria-disabled', 'true');
  \t\t}
  \t\tif (this._disabled || map._zoom === map.getMaxZoom()) {
  \t\t\taddClass(this._zoomInButton, className);
  \t\t\tthis._zoomInButton.setAttribute('aria-disabled', 'true');
  \t\t}
  \t}
  });

  // @namespace Map
  // @section Control options
  // @option zoomControl: Boolean = true
  // Whether a [zoom control](#control-zoom) is added to the map by default.
  Map.mergeOptions({
  \tzoomControl: true
  });

  Map.addInitHook(function () {
  \tif (this.options.zoomControl) {
  \t\t// @section Controls
  \t\t// @property zoomControl: Control.Zoom
  \t\t// The default zoom control (only available if the
  \t\t// [`zoomControl` option](#map-zoomcontrol) was `true` when creating the map).
  \t\tthis.zoomControl = new Zoom();
  \t\tthis.addControl(this.zoomControl);
  \t}
  });

  // @namespace Control.Zoom
  // @factory L.control.zoom(options: Control.Zoom options)
  // Creates a zoom control
  var zoom = function (options) {
  \treturn new Zoom(options);
  };

  /*
   * @class Control.Scale
   * @aka L.Control.Scale
   * @inherits Control
   *
   * A simple scale control that shows the scale of the current center of screen in metric (m/km) and imperial (mi/ft) systems. Extends `Control`.
   *
   * @example
   *
   * ```js
   * L.control.scale().addTo(map);
   * ```
   */

  var Scale = Control.extend({
  \t// @section
  \t// @aka Control.Scale options
  \toptions: {
  \t\tposition: 'bottomleft',

  \t\t// @option maxWidth: Number = 100
  \t\t// Maximum width of the control in pixels. The width is set dynamically to show round values (e.g. 100, 200, 500).
  \t\tmaxWidth: 100,

  \t\t// @option metric: Boolean = True
  \t\t// Whether to show the metric scale line (m/km).
  \t\tmetric: true,

  \t\t// @option imperial: Boolean = True
  \t\t// Whether to show the imperial scale line (mi/ft).
  \t\timperial: true

  \t\t// @option updateWhenIdle: Boolean = false
  \t\t// If `true`, the control is updated on [`moveend`](#map-moveend), otherwise it's always up-to-date (updated on [`move`](#map-move)).
  \t},

  \tonAdd: function (map) {
  \t\tvar className = 'leaflet-control-scale',
  \t\t    container = create\$1('div', className),
  \t\t    options = this.options;

  \t\tthis._addScales(options, className + '-line', container);

  \t\tmap.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this);
  \t\tmap.whenReady(this._update, this);

  \t\treturn container;
  \t},

  \tonRemove: function (map) {
  \t\tmap.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this);
  \t},

  \t_addScales: function (options, className, container) {
  \t\tif (options.metric) {
  \t\t\tthis._mScale = create\$1('div', className, container);
  \t\t}
  \t\tif (options.imperial) {
  \t\t\tthis._iScale = create\$1('div', className, container);
  \t\t}
  \t},

  \t_update: function () {
  \t\tvar map = this._map,
  \t\t    y = map.getSize().y / 2;

  \t\tvar maxMeters = map.distance(
  \t\t\tmap.containerPointToLatLng([0, y]),
  \t\t\tmap.containerPointToLatLng([this.options.maxWidth, y]));

  \t\tthis._updateScales(maxMeters);
  \t},

  \t_updateScales: function (maxMeters) {
  \t\tif (this.options.metric && maxMeters) {
  \t\t\tthis._updateMetric(maxMeters);
  \t\t}
  \t\tif (this.options.imperial && maxMeters) {
  \t\t\tthis._updateImperial(maxMeters);
  \t\t}
  \t},

  \t_updateMetric: function (maxMeters) {
  \t\tvar meters = this._getRoundNum(maxMeters),
  \t\t    label = meters < 1000 ? meters + ' m' : (meters / 1000) + ' km';

  \t\tthis._updateScale(this._mScale, label, meters / maxMeters);
  \t},

  \t_updateImperial: function (maxMeters) {
  \t\tvar maxFeet = maxMeters * 3.2808399,
  \t\t    maxMiles, miles, feet;

  \t\tif (maxFeet > 5280) {
  \t\t\tmaxMiles = maxFeet / 5280;
  \t\t\tmiles = this._getRoundNum(maxMiles);
  \t\t\tthis._updateScale(this._iScale, miles + ' mi', miles / maxMiles);

  \t\t} else {
  \t\t\tfeet = this._getRoundNum(maxFeet);
  \t\t\tthis._updateScale(this._iScale, feet + ' ft', feet / maxFeet);
  \t\t}
  \t},

  \t_updateScale: function (scale, text, ratio) {
  \t\tscale.style.width = Math.round(this.options.maxWidth * ratio) + 'px';
  \t\tscale.innerHTML = text;
  \t},

  \t_getRoundNum: function (num) {
  \t\tvar pow10 = Math.pow(10, (Math.floor(num) + '').length - 1),
  \t\t    d = num / pow10;

  \t\td = d >= 10 ? 10 :
  \t\t    d >= 5 ? 5 :
  \t\t    d >= 3 ? 3 :
  \t\t    d >= 2 ? 2 : 1;

  \t\treturn pow10 * d;
  \t}
  });


  // @factory L.control.scale(options?: Control.Scale options)
  // Creates an scale control with the given options.
  var scale = function (options) {
  \treturn new Scale(options);
  };

  var ukrainianFlag = '<svg aria-hidden=\"true\" xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"8\" viewBox=\"0 0 12 8\" class=\"leaflet-attribution-flag\"><path fill=\"#4C7BE1\" d=\"M0 0h12v4H0z\"/><path fill=\"#FFD500\" d=\"M0 4h12v3H0z\"/><path fill=\"#E0BC00\" d=\"M0 7h12v1H0z\"/></svg>';


  /*
   * @class Control.Attribution
   * @aka L.Control.Attribution
   * @inherits Control
   *
   * The attribution control allows you to display attribution data in a small text box on a map. It is put on the map by default unless you set its [`attributionControl` option](#map-attributioncontrol) to `false`, and it fetches attribution texts from layers with the [`getAttribution` method](#layer-getattribution) automatically. Extends Control.
   */

  var Attribution = Control.extend({
  \t// @section
  \t// @aka Control.Attribution options
  \toptions: {
  \t\tposition: 'bottomright',

  \t\t// @option prefix: String|false = 'Leaflet'
  \t\t// The HTML text shown before the attributions. Pass `false` to disable.
  \t\tprefix: '<a href=\"https://leafletjs.com\" title=\"A JavaScript library for interactive maps\">' + (Browser.inlineSvg ? ukrainianFlag + ' ' : '') + 'Leaflet</a>'
  \t},

  \tinitialize: function (options) {
  \t\tsetOptions(this, options);

  \t\tthis._attributions = {};
  \t},

  \tonAdd: function (map) {
  \t\tmap.attributionControl = this;
  \t\tthis._container = create\$1('div', 'leaflet-control-attribution');
  \t\tdisableClickPropagation(this._container);

  \t\t// TODO ugly, refactor
  \t\tfor (var i in map._layers) {
  \t\t\tif (map._layers[i].getAttribution) {
  \t\t\t\tthis.addAttribution(map._layers[i].getAttribution());
  \t\t\t}
  \t\t}

  \t\tthis._update();

  \t\tmap.on('layeradd', this._addAttribution, this);

  \t\treturn this._container;
  \t},

  \tonRemove: function (map) {
  \t\tmap.off('layeradd', this._addAttribution, this);
  \t},

  \t_addAttribution: function (ev) {
  \t\tif (ev.layer.getAttribution) {
  \t\t\tthis.addAttribution(ev.layer.getAttribution());
  \t\t\tev.layer.once('remove', function () {
  \t\t\t\tthis.removeAttribution(ev.layer.getAttribution());
  \t\t\t}, this);
  \t\t}
  \t},

  \t// @method setPrefix(prefix: String|false): this
  \t// The HTML text shown before the attributions. Pass `false` to disable.
  \tsetPrefix: function (prefix) {
  \t\tthis.options.prefix = prefix;
  \t\tthis._update();
  \t\treturn this;
  \t},

  \t// @method addAttribution(text: String): this
  \t// Adds an attribution text (e.g. `'&copy; OpenStreetMap contributors'`).
  \taddAttribution: function (text) {
  \t\tif (!text) { return this; }

  \t\tif (!this._attributions[text]) {
  \t\t\tthis._attributions[text] = 0;
  \t\t}
  \t\tthis._attributions[text]++;

  \t\tthis._update();

  \t\treturn this;
  \t},

  \t// @method removeAttribution(text: String): this
  \t// Removes an attribution text.
  \tremoveAttribution: function (text) {
  \t\tif (!text) { return this; }

  \t\tif (this._attributions[text]) {
  \t\t\tthis._attributions[text]--;
  \t\t\tthis._update();
  \t\t}

  \t\treturn this;
  \t},

  \t_update: function () {
  \t\tif (!this._map) { return; }

  \t\tvar attribs = [];

  \t\tfor (var i in this._attributions) {
  \t\t\tif (this._attributions[i]) {
  \t\t\t\tattribs.push(i);
  \t\t\t}
  \t\t}

  \t\tvar prefixAndAttribs = [];

  \t\tif (this.options.prefix) {
  \t\t\tprefixAndAttribs.push(this.options.prefix);
  \t\t}
  \t\tif (attribs.length) {
  \t\t\tprefixAndAttribs.push(attribs.join(', '));
  \t\t}

  \t\tthis._container.innerHTML = prefixAndAttribs.join(' <span aria-hidden=\"true\">|</span> ');
  \t}
  });

  // @namespace Map
  // @section Control options
  // @option attributionControl: Boolean = true
  // Whether a [attribution control](#control-attribution) is added to the map by default.
  Map.mergeOptions({
  \tattributionControl: true
  });

  Map.addInitHook(function () {
  \tif (this.options.attributionControl) {
  \t\tnew Attribution().addTo(this);
  \t}
  });

  // @namespace Control.Attribution
  // @factory L.control.attribution(options: Control.Attribution options)
  // Creates an attribution control.
  var attribution = function (options) {
  \treturn new Attribution(options);
  };

  Control.Layers = Layers;
  Control.Zoom = Zoom;
  Control.Scale = Scale;
  Control.Attribution = Attribution;

  control.layers = layers;
  control.zoom = zoom;
  control.scale = scale;
  control.attribution = attribution;

  /*
  \tL.Handler is a base class for handler classes that are used internally to inject
  \tinteraction features like dragging to classes like Map and Marker.
  */

  // @class Handler
  // @aka L.Handler
  // Abstract class for map interaction handlers

  var Handler = Class.extend({
  \tinitialize: function (map) {
  \t\tthis._map = map;
  \t},

  \t// @method enable(): this
  \t// Enables the handler
  \tenable: function () {
  \t\tif (this._enabled) { return this; }

  \t\tthis._enabled = true;
  \t\tthis.addHooks();
  \t\treturn this;
  \t},

  \t// @method disable(): this
  \t// Disables the handler
  \tdisable: function () {
  \t\tif (!this._enabled) { return this; }

  \t\tthis._enabled = false;
  \t\tthis.removeHooks();
  \t\treturn this;
  \t},

  \t// @method enabled(): Boolean
  \t// Returns `true` if the handler is enabled
  \tenabled: function () {
  \t\treturn !!this._enabled;
  \t}

  \t// @section Extension methods
  \t// Classes inheriting from `Handler` must implement the two following methods:
  \t// @method addHooks()
  \t// Called when the handler is enabled, should add event hooks.
  \t// @method removeHooks()
  \t// Called when the handler is disabled, should remove the event hooks added previously.
  });

  // @section There is static function which can be called without instantiating L.Handler:
  // @function addTo(map: Map, name: String): this
  // Adds a new Handler to the given map with the given name.
  Handler.addTo = function (map, name) {
  \tmap.addHandler(name, this);
  \treturn this;
  };

  var Mixin = {Events: Events};

  /*
   * @class Draggable
   * @aka L.Draggable
   * @inherits Evented
   *
   * A class for making DOM elements draggable (including touch support).
   * Used internally for map and marker dragging. Only works for elements
   * that were positioned with [`L.DomUtil.setPosition`](#domutil-setposition).
   *
   * @example
   * ```js
   * var draggable = new L.Draggable(elementToDrag);
   * draggable.enable();
   * ```
   */

  var START = Browser.touch ? 'touchstart mousedown' : 'mousedown';

  var Draggable = Evented.extend({

  \toptions: {
  \t\t// @section
  \t\t// @aka Draggable options
  \t\t// @option clickTolerance: Number = 3
  \t\t// The max number of pixels a user can shift the mouse pointer during a click
  \t\t// for it to be considered a valid click (as opposed to a mouse drag).
  \t\tclickTolerance: 3
  \t},

  \t// @constructor L.Draggable(el: HTMLElement, dragHandle?: HTMLElement, preventOutline?: Boolean, options?: Draggable options)
  \t// Creates a `Draggable` object for moving `el` when you start dragging the `dragHandle` element (equals `el` itself by default).
  \tinitialize: function (element, dragStartTarget, preventOutline, options) {
  \t\tsetOptions(this, options);

  \t\tthis._element = element;
  \t\tthis._dragStartTarget = dragStartTarget || element;
  \t\tthis._preventOutline = preventOutline;
  \t},

  \t// @method enable()
  \t// Enables the dragging ability
  \tenable: function () {
  \t\tif (this._enabled) { return; }

  \t\ton(this._dragStartTarget, START, this._onDown, this);

  \t\tthis._enabled = true;
  \t},

  \t// @method disable()
  \t// Disables the dragging ability
  \tdisable: function () {
  \t\tif (!this._enabled) { return; }

  \t\t// If we're currently dragging this draggable,
  \t\t// disabling it counts as first ending the drag.
  \t\tif (Draggable._dragging === this) {
  \t\t\tthis.finishDrag(true);
  \t\t}

  \t\toff(this._dragStartTarget, START, this._onDown, this);

  \t\tthis._enabled = false;
  \t\tthis._moved = false;
  \t},

  \t_onDown: function (e) {
  \t\t// Ignore the event if disabled; this happens in IE11
  \t\t// under some circumstances, see #3666.
  \t\tif (!this._enabled) { return; }

  \t\tthis._moved = false;

  \t\tif (hasClass(this._element, 'leaflet-zoom-anim')) { return; }

  \t\tif (e.touches && e.touches.length !== 1) {
  \t\t\t// Finish dragging to avoid conflict with touchZoom
  \t\t\tif (Draggable._dragging === this) {
  \t\t\t\tthis.finishDrag();
  \t\t\t}
  \t\t\treturn;
  \t\t}

  \t\tif (Draggable._dragging || e.shiftKey || ((e.which !== 1) && (e.button !== 1) && !e.touches)) { return; }
  \t\tDraggable._dragging = this;  // Prevent dragging multiple objects at once.

  \t\tif (this._preventOutline) {
  \t\t\tpreventOutline(this._element);
  \t\t}

  \t\tdisableImageDrag();
  \t\tdisableTextSelection();

  \t\tif (this._moving) { return; }

  \t\t// @event down: Event
  \t\t// Fired when a drag is about to start.
  \t\tthis.fire('down');

  \t\tvar first = e.touches ? e.touches[0] : e,
  \t\t    sizedParent = getSizedParentNode(this._element);

  \t\tthis._startPoint = new Point(first.clientX, first.clientY);
  \t\tthis._startPos = getPosition(this._element);

  \t\t// Cache the scale, so that we can continuously compensate for it during drag (_onMove).
  \t\tthis._parentScale = getScale(sizedParent);

  \t\tvar mouseevent = e.type === 'mousedown';
  \t\ton(document, mouseevent ? 'mousemove' : 'touchmove', this._onMove, this);
  \t\ton(document, mouseevent ? 'mouseup' : 'touchend touchcancel', this._onUp, this);
  \t},

  \t_onMove: function (e) {
  \t\t// Ignore the event if disabled; this happens in IE11
  \t\t// under some circumstances, see #3666.
  \t\tif (!this._enabled) { return; }

  \t\tif (e.touches && e.touches.length > 1) {
  \t\t\tthis._moved = true;
  \t\t\treturn;
  \t\t}

  \t\tvar first = (e.touches && e.touches.length === 1 ? e.touches[0] : e),
  \t\t    offset = new Point(first.clientX, first.clientY)._subtract(this._startPoint);

  \t\tif (!offset.x && !offset.y) { return; }
  \t\tif (Math.abs(offset.x) + Math.abs(offset.y) < this.options.clickTolerance) { return; }

  \t\t// We assume that the parent container's position, border and scale do not change for the duration of the drag.
  \t\t// Therefore there is no need to account for the position and border (they are eliminated by the subtraction)
  \t\t// and we can use the cached value for the scale.
  \t\toffset.x /= this._parentScale.x;
  \t\toffset.y /= this._parentScale.y;

  \t\tpreventDefault(e);

  \t\tif (!this._moved) {
  \t\t\t// @event dragstart: Event
  \t\t\t// Fired when a drag starts
  \t\t\tthis.fire('dragstart');

  \t\t\tthis._moved = true;

  \t\t\taddClass(document.body, 'leaflet-dragging');

  \t\t\tthis._lastTarget = e.target || e.srcElement;
  \t\t\t// IE and Edge do not give the <use> element, so fetch it
  \t\t\t// if necessary
  \t\t\tif (window.SVGElementInstance && this._lastTarget instanceof window.SVGElementInstance) {
  \t\t\t\tthis._lastTarget = this._lastTarget.correspondingUseElement;
  \t\t\t}
  \t\t\taddClass(this._lastTarget, 'leaflet-drag-target');
  \t\t}

  \t\tthis._newPos = this._startPos.add(offset);
  \t\tthis._moving = true;

  \t\tthis._lastEvent = e;
  \t\tthis._updatePosition();
  \t},

  \t_updatePosition: function () {
  \t\tvar e = {originalEvent: this._lastEvent};

  \t\t// @event predrag: Event
  \t\t// Fired continuously during dragging *before* each corresponding
  \t\t// update of the element's position.
  \t\tthis.fire('predrag', e);
  \t\tsetPosition(this._element, this._newPos);

  \t\t// @event drag: Event
  \t\t// Fired continuously during dragging.
  \t\tthis.fire('drag', e);
  \t},

  \t_onUp: function () {
  \t\t// Ignore the event if disabled; this happens in IE11
  \t\t// under some circumstances, see #3666.
  \t\tif (!this._enabled) { return; }
  \t\tthis.finishDrag();
  \t},

  \tfinishDrag: function (noInertia) {
  \t\tremoveClass(document.body, 'leaflet-dragging');

  \t\tif (this._lastTarget) {
  \t\t\tremoveClass(this._lastTarget, 'leaflet-drag-target');
  \t\t\tthis._lastTarget = null;
  \t\t}

  \t\toff(document, 'mousemove touchmove', this._onMove, this);
  \t\toff(document, 'mouseup touchend touchcancel', this._onUp, this);

  \t\tenableImageDrag();
  \t\tenableTextSelection();

  \t\tvar fireDragend = this._moved && this._moving;

  \t\tthis._moving = false;
  \t\tDraggable._dragging = false;

  \t\tif (fireDragend) {
  \t\t\t// @event dragend: DragEndEvent
  \t\t\t// Fired when the drag ends.
  \t\t\tthis.fire('dragend', {
  \t\t\t\tnoInertia: noInertia,
  \t\t\t\tdistance: this._newPos.distanceTo(this._startPos)
  \t\t\t});
  \t\t}
  \t}

  });

  /*
   * @namespace PolyUtil
   * Various utility functions for polygon geometries.
   */

  /* @function clipPolygon(points: Point[], bounds: Bounds, round?: Boolean): Point[]
   * Clips the polygon geometry defined by the given `points` by the given bounds (using the [Sutherland-Hodgman algorithm](https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm)).
   * Used by Leaflet to only show polygon points that are on the screen or near, increasing
   * performance. Note that polygon points needs different algorithm for clipping
   * than polyline, so there's a separate method for it.
   */
  function clipPolygon(points, bounds, round) {
  \tvar clippedPoints,
  \t    edges = [1, 4, 2, 8],
  \t    i, j, k,
  \t    a, b,
  \t    len, edge, p;

  \tfor (i = 0, len = points.length; i < len; i++) {
  \t\tpoints[i]._code = _getBitCode(points[i], bounds);
  \t}

  \t// for each edge (left, bottom, right, top)
  \tfor (k = 0; k < 4; k++) {
  \t\tedge = edges[k];
  \t\tclippedPoints = [];

  \t\tfor (i = 0, len = points.length, j = len - 1; i < len; j = i++) {
  \t\t\ta = points[i];
  \t\t\tb = points[j];

  \t\t\t// if a is inside the clip window
  \t\t\tif (!(a._code & edge)) {
  \t\t\t\t// if b is outside the clip window (a->b goes out of screen)
  \t\t\t\tif (b._code & edge) {
  \t\t\t\t\tp = _getEdgeIntersection(b, a, edge, bounds, round);
  \t\t\t\t\tp._code = _getBitCode(p, bounds);
  \t\t\t\t\tclippedPoints.push(p);
  \t\t\t\t}
  \t\t\t\tclippedPoints.push(a);

  \t\t\t// else if b is inside the clip window (a->b enters the screen)
  \t\t\t} else if (!(b._code & edge)) {
  \t\t\t\tp = _getEdgeIntersection(b, a, edge, bounds, round);
  \t\t\t\tp._code = _getBitCode(p, bounds);
  \t\t\t\tclippedPoints.push(p);
  \t\t\t}
  \t\t}
  \t\tpoints = clippedPoints;
  \t}

  \treturn points;
  }

  /* @function polygonCenter(latlngs: LatLng[], crs: CRS): LatLng
   * Returns the center ([centroid](http://en.wikipedia.org/wiki/Centroid)) of the passed LatLngs (first ring) from a polygon.
   */
  function polygonCenter(latlngs, crs) {
  \tvar i, j, p1, p2, f, area, x, y, center;

  \tif (!latlngs || latlngs.length === 0) {
  \t\tthrow new Error('latlngs not passed');
  \t}

  \tif (!isFlat(latlngs)) {
  \t\tconsole.warn('latlngs are not flat! Only the first ring will be used');
  \t\tlatlngs = latlngs[0];
  \t}

  \tvar centroidLatLng = toLatLng([0, 0]);

  \tvar bounds = toLatLngBounds(latlngs);
  \tvar areaBounds = bounds.getNorthWest().distanceTo(bounds.getSouthWest()) * bounds.getNorthEast().distanceTo(bounds.getNorthWest());
  \t// tests showed that below 1700 rounding errors are happening
  \tif (areaBounds < 1700) {
  \t\t// getting a inexact center, to move the latlngs near to [0, 0] to prevent rounding errors
  \t\tcentroidLatLng = centroid(latlngs);
  \t}

  \tvar len = latlngs.length;
  \tvar points = [];
  \tfor (i = 0; i < len; i++) {
  \t\tvar latlng = toLatLng(latlngs[i]);
  \t\tpoints.push(crs.project(toLatLng([latlng.lat - centroidLatLng.lat, latlng.lng - centroidLatLng.lng])));
  \t}

  \tarea = x = y = 0;

  \t// polygon centroid algorithm;
  \tfor (i = 0, j = len - 1; i < len; j = i++) {
  \t\tp1 = points[i];
  \t\tp2 = points[j];

  \t\tf = p1.y * p2.x - p2.y * p1.x;
  \t\tx += (p1.x + p2.x) * f;
  \t\ty += (p1.y + p2.y) * f;
  \t\tarea += f * 3;
  \t}

  \tif (area === 0) {
  \t\t// Polygon is so small that all points are on same pixel.
  \t\tcenter = points[0];
  \t} else {
  \t\tcenter = [x / area, y / area];
  \t}

  \tvar latlngCenter = crs.unproject(toPoint(center));
  \treturn toLatLng([latlngCenter.lat + centroidLatLng.lat, latlngCenter.lng + centroidLatLng.lng]);
  }

  /* @function centroid(latlngs: LatLng[]): LatLng
   * Returns the 'center of mass' of the passed LatLngs.
   */
  function centroid(coords) {
  \tvar latSum = 0;
  \tvar lngSum = 0;
  \tvar len = 0;
  \tfor (var i = 0; i < coords.length; i++) {
  \t\tvar latlng = toLatLng(coords[i]);
  \t\tlatSum += latlng.lat;
  \t\tlngSum += latlng.lng;
  \t\tlen++;
  \t}
  \treturn toLatLng([latSum / len, lngSum / len]);
  }

  var PolyUtil = {
    __proto__: null,
    clipPolygon: clipPolygon,
    polygonCenter: polygonCenter,
    centroid: centroid
  };

  /*
   * @namespace LineUtil
   *
   * Various utility functions for polyline points processing, used by Leaflet internally to make polylines lightning-fast.
   */

  // Simplify polyline with vertex reduction and Douglas-Peucker simplification.
  // Improves rendering performance dramatically by lessening the number of points to draw.

  // @function simplify(points: Point[], tolerance: Number): Point[]
  // Dramatically reduces the number of points in a polyline while retaining
  // its shape and returns a new array of simplified points, using the
  // [Ramer-Douglas-Peucker algorithm](https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm).
  // Used for a huge performance boost when processing/displaying Leaflet polylines for
  // each zoom level and also reducing visual noise. tolerance affects the amount of
  // simplification (lesser value means higher quality but slower and with more points).
  // Also released as a separated micro-library [Simplify.js](https://mourner.github.io/simplify-js/).
  function simplify(points, tolerance) {
  \tif (!tolerance || !points.length) {
  \t\treturn points.slice();
  \t}

  \tvar sqTolerance = tolerance * tolerance;

  \t    // stage 1: vertex reduction
  \t    points = _reducePoints(points, sqTolerance);

  \t    // stage 2: Douglas-Peucker simplification
  \t    points = _simplifyDP(points, sqTolerance);

  \treturn points;
  }

  // @function pointToSegmentDistance(p: Point, p1: Point, p2: Point): Number
  // Returns the distance between point `p` and segment `p1` to `p2`.
  function pointToSegmentDistance(p, p1, p2) {
  \treturn Math.sqrt(_sqClosestPointOnSegment(p, p1, p2, true));
  }

  // @function closestPointOnSegment(p: Point, p1: Point, p2: Point): Number
  // Returns the closest point from a point `p` on a segment `p1` to `p2`.
  function closestPointOnSegment(p, p1, p2) {
  \treturn _sqClosestPointOnSegment(p, p1, p2);
  }

  // Ramer-Douglas-Peucker simplification, see https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
  function _simplifyDP(points, sqTolerance) {

  \tvar len = points.length,
  \t    ArrayConstructor = typeof Uint8Array !== undefined + '' ? Uint8Array : Array,
  \t    markers = new ArrayConstructor(len);

  \t    markers[0] = markers[len - 1] = 1;

  \t_simplifyDPStep(points, markers, sqTolerance, 0, len - 1);

  \tvar i,
  \t    newPoints = [];

  \tfor (i = 0; i < len; i++) {
  \t\tif (markers[i]) {
  \t\t\tnewPoints.push(points[i]);
  \t\t}
  \t}

  \treturn newPoints;
  }

  function _simplifyDPStep(points, markers, sqTolerance, first, last) {

  \tvar maxSqDist = 0,
  \tindex, i, sqDist;

  \tfor (i = first + 1; i <= last - 1; i++) {
  \t\tsqDist = _sqClosestPointOnSegment(points[i], points[first], points[last], true);

  \t\tif (sqDist > maxSqDist) {
  \t\t\tindex = i;
  \t\t\tmaxSqDist = sqDist;
  \t\t}
  \t}

  \tif (maxSqDist > sqTolerance) {
  \t\tmarkers[index] = 1;

  \t\t_simplifyDPStep(points, markers, sqTolerance, first, index);
  \t\t_simplifyDPStep(points, markers, sqTolerance, index, last);
  \t}
  }

  // reduce points that are too close to each other to a single point
  function _reducePoints(points, sqTolerance) {
  \tvar reducedPoints = [points[0]];

  \tfor (var i = 1, prev = 0, len = points.length; i < len; i++) {
  \t\tif (_sqDist(points[i], points[prev]) > sqTolerance) {
  \t\t\treducedPoints.push(points[i]);
  \t\t\tprev = i;
  \t\t}
  \t}
  \tif (prev < len - 1) {
  \t\treducedPoints.push(points[len - 1]);
  \t}
  \treturn reducedPoints;
  }

  var _lastCode;

  // @function clipSegment(a: Point, b: Point, bounds: Bounds, useLastCode?: Boolean, round?: Boolean): Point[]|Boolean
  // Clips the segment a to b by rectangular bounds with the
  // [Cohen-Sutherland algorithm](https://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland_algorithm)
  // (modifying the segment points directly!). Used by Leaflet to only show polyline
  // points that are on the screen or near, increasing performance.
  function clipSegment(a, b, bounds, useLastCode, round) {
  \tvar codeA = useLastCode ? _lastCode : _getBitCode(a, bounds),
  \t    codeB = _getBitCode(b, bounds),

  \t    codeOut, p, newCode;

  \t    // save 2nd code to avoid calculating it on the next segment
  \t    _lastCode = codeB;

  \twhile (true) {
  \t\t// if a,b is inside the clip window (trivial accept)
  \t\tif (!(codeA | codeB)) {
  \t\t\treturn [a, b];
  \t\t}

  \t\t// if a,b is outside the clip window (trivial reject)
  \t\tif (codeA & codeB) {
  \t\t\treturn false;
  \t\t}

  \t\t// other cases
  \t\tcodeOut = codeA || codeB;
  \t\tp = _getEdgeIntersection(a, b, codeOut, bounds, round);
  \t\tnewCode = _getBitCode(p, bounds);

  \t\tif (codeOut === codeA) {
  \t\t\ta = p;
  \t\t\tcodeA = newCode;
  \t\t} else {
  \t\t\tb = p;
  \t\t\tcodeB = newCode;
  \t\t}
  \t}
  }

  function _getEdgeIntersection(a, b, code, bounds, round) {
  \tvar dx = b.x - a.x,
  \t    dy = b.y - a.y,
  \t    min = bounds.min,
  \t    max = bounds.max,
  \t    x, y;

  \tif (code & 8) { // top
  \t\tx = a.x + dx * (max.y - a.y) / dy;
  \t\ty = max.y;

  \t} else if (code & 4) { // bottom
  \t\tx = a.x + dx * (min.y - a.y) / dy;
  \t\ty = min.y;

  \t} else if (code & 2) { // right
  \t\tx = max.x;
  \t\ty = a.y + dy * (max.x - a.x) / dx;

  \t} else if (code & 1) { // left
  \t\tx = min.x;
  \t\ty = a.y + dy * (min.x - a.x) / dx;
  \t}

  \treturn new Point(x, y, round);
  }

  function _getBitCode(p, bounds) {
  \tvar code = 0;

  \tif (p.x < bounds.min.x) { // left
  \t\tcode |= 1;
  \t} else if (p.x > bounds.max.x) { // right
  \t\tcode |= 2;
  \t}

  \tif (p.y < bounds.min.y) { // bottom
  \t\tcode |= 4;
  \t} else if (p.y > bounds.max.y) { // top
  \t\tcode |= 8;
  \t}

  \treturn code;
  }

  // square distance (to avoid unnecessary Math.sqrt calls)
  function _sqDist(p1, p2) {
  \tvar dx = p2.x - p1.x,
  \t    dy = p2.y - p1.y;
  \treturn dx * dx + dy * dy;
  }

  // return closest point on segment or distance to that point
  function _sqClosestPointOnSegment(p, p1, p2, sqDist) {
  \tvar x = p1.x,
  \t    y = p1.y,
  \t    dx = p2.x - x,
  \t    dy = p2.y - y,
  \t    dot = dx * dx + dy * dy,
  \t    t;

  \tif (dot > 0) {
  \t\tt = ((p.x - x) * dx + (p.y - y) * dy) / dot;

  \t\tif (t > 1) {
  \t\t\tx = p2.x;
  \t\t\ty = p2.y;
  \t\t} else if (t > 0) {
  \t\t\tx += dx * t;
  \t\t\ty += dy * t;
  \t\t}
  \t}

  \tdx = p.x - x;
  \tdy = p.y - y;

  \treturn sqDist ? dx * dx + dy * dy : new Point(x, y);
  }


  // @function isFlat(latlngs: LatLng[]): Boolean
  // Returns true if `latlngs` is a flat array, false is nested.
  function isFlat(latlngs) {
  \treturn !isArray(latlngs[0]) || (typeof latlngs[0][0] !== 'object' && typeof latlngs[0][0] !== 'undefined');
  }

  function _flat(latlngs) {
  \tconsole.warn('Deprecated use of _flat, please use L.LineUtil.isFlat instead.');
  \treturn isFlat(latlngs);
  }

  /* @function polylineCenter(latlngs: LatLng[], crs: CRS): LatLng
   * Returns the center ([centroid](http://en.wikipedia.org/wiki/Centroid)) of the passed LatLngs (first ring) from a polyline.
   */
  function polylineCenter(latlngs, crs) {
  \tvar i, halfDist, segDist, dist, p1, p2, ratio, center;

  \tif (!latlngs || latlngs.length === 0) {
  \t\tthrow new Error('latlngs not passed');
  \t}

  \tif (!isFlat(latlngs)) {
  \t\tconsole.warn('latlngs are not flat! Only the first ring will be used');
  \t\tlatlngs = latlngs[0];
  \t}

  \tvar centroidLatLng = toLatLng([0, 0]);

  \tvar bounds = toLatLngBounds(latlngs);
  \tvar areaBounds = bounds.getNorthWest().distanceTo(bounds.getSouthWest()) * bounds.getNorthEast().distanceTo(bounds.getNorthWest());
  \t// tests showed that below 1700 rounding errors are happening
  \tif (areaBounds < 1700) {
  \t\t// getting a inexact center, to move the latlngs near to [0, 0] to prevent rounding errors
  \t\tcentroidLatLng = centroid(latlngs);
  \t}

  \tvar len = latlngs.length;
  \tvar points = [];
  \tfor (i = 0; i < len; i++) {
  \t\tvar latlng = toLatLng(latlngs[i]);
  \t\tpoints.push(crs.project(toLatLng([latlng.lat - centroidLatLng.lat, latlng.lng - centroidLatLng.lng])));
  \t}

  \tfor (i = 0, halfDist = 0; i < len - 1; i++) {
  \t\thalfDist += points[i].distanceTo(points[i + 1]) / 2;
  \t}

  \t// The line is so small in the current view that all points are on the same pixel.
  \tif (halfDist === 0) {
  \t\tcenter = points[0];
  \t} else {
  \t\tfor (i = 0, dist = 0; i < len - 1; i++) {
  \t\t\tp1 = points[i];
  \t\t\tp2 = points[i + 1];
  \t\t\tsegDist = p1.distanceTo(p2);
  \t\t\tdist += segDist;

  \t\t\tif (dist > halfDist) {
  \t\t\t\tratio = (dist - halfDist) / segDist;
  \t\t\t\tcenter = [
  \t\t\t\t\tp2.x - ratio * (p2.x - p1.x),
  \t\t\t\t\tp2.y - ratio * (p2.y - p1.y)
  \t\t\t\t];
  \t\t\t\tbreak;
  \t\t\t}
  \t\t}
  \t}

  \tvar latlngCenter = crs.unproject(toPoint(center));
  \treturn toLatLng([latlngCenter.lat + centroidLatLng.lat, latlngCenter.lng + centroidLatLng.lng]);
  }

  var LineUtil = {
    __proto__: null,
    simplify: simplify,
    pointToSegmentDistance: pointToSegmentDistance,
    closestPointOnSegment: closestPointOnSegment,
    clipSegment: clipSegment,
    _getEdgeIntersection: _getEdgeIntersection,
    _getBitCode: _getBitCode,
    _sqClosestPointOnSegment: _sqClosestPointOnSegment,
    isFlat: isFlat,
    _flat: _flat,
    polylineCenter: polylineCenter
  };

  /*
   * @namespace Projection
   * @section
   * Leaflet comes with a set of already defined Projections out of the box:
   *
   * @projection L.Projection.LonLat
   *
   * Equirectangular, or Plate Carree projection — the most simple projection,
   * mostly used by GIS enthusiasts. Directly maps `x` as longitude, and `y` as
   * latitude. Also suitable for flat worlds, e.g. game maps. Used by the
   * `EPSG:4326` and `Simple` CRS.
   */

  var LonLat = {
  \tproject: function (latlng) {
  \t\treturn new Point(latlng.lng, latlng.lat);
  \t},

  \tunproject: function (point) {
  \t\treturn new LatLng(point.y, point.x);
  \t},

  \tbounds: new Bounds([-180, -90], [180, 90])
  };

  /*
   * @namespace Projection
   * @projection L.Projection.Mercator
   *
   * Elliptical Mercator projection — more complex than Spherical Mercator. Assumes that Earth is an ellipsoid. Used by the EPSG:3395 CRS.
   */

  var Mercator = {
  \tR: 6378137,
  \tR_MINOR: 6356752.314245179,

  \tbounds: new Bounds([-20037508.34279, -15496570.73972], [20037508.34279, 18764656.23138]),

  \tproject: function (latlng) {
  \t\tvar d = Math.PI / 180,
  \t\t    r = this.R,
  \t\t    y = latlng.lat * d,
  \t\t    tmp = this.R_MINOR / r,
  \t\t    e = Math.sqrt(1 - tmp * tmp),
  \t\t    con = e * Math.sin(y);

  \t\tvar ts = Math.tan(Math.PI / 4 - y / 2) / Math.pow((1 - con) / (1 + con), e / 2);
  \t\ty = -r * Math.log(Math.max(ts, 1E-10));

  \t\treturn new Point(latlng.lng * d * r, y);
  \t},

  \tunproject: function (point) {
  \t\tvar d = 180 / Math.PI,
  \t\t    r = this.R,
  \t\t    tmp = this.R_MINOR / r,
  \t\t    e = Math.sqrt(1 - tmp * tmp),
  \t\t    ts = Math.exp(-point.y / r),
  \t\t    phi = Math.PI / 2 - 2 * Math.atan(ts);

  \t\tfor (var i = 0, dphi = 0.1, con; i < 15 && Math.abs(dphi) > 1e-7; i++) {
  \t\t\tcon = e * Math.sin(phi);
  \t\t\tcon = Math.pow((1 - con) / (1 + con), e / 2);
  \t\t\tdphi = Math.PI / 2 - 2 * Math.atan(ts * con) - phi;
  \t\t\tphi += dphi;
  \t\t}

  \t\treturn new LatLng(phi * d, point.x * d / r);
  \t}
  };

  /*
   * @class Projection

   * An object with methods for projecting geographical coordinates of the world onto
   * a flat surface (and back). See [Map projection](https://en.wikipedia.org/wiki/Map_projection).

   * @property bounds: Bounds
   * The bounds (specified in CRS units) where the projection is valid

   * @method project(latlng: LatLng): Point
   * Projects geographical coordinates into a 2D point.
   * Only accepts actual `L.LatLng` instances, not arrays.

   * @method unproject(point: Point): LatLng
   * The inverse of `project`. Projects a 2D point into a geographical location.
   * Only accepts actual `L.Point` instances, not arrays.

   * Note that the projection instances do not inherit from Leaflet's `Class` object,
   * and can't be instantiated. Also, new classes can't inherit from them,
   * and methods can't be added to them with the `include` function.

   */

  var index = {
    __proto__: null,
    LonLat: LonLat,
    Mercator: Mercator,
    SphericalMercator: SphericalMercator
  };

  /*
   * @namespace CRS
   * @crs L.CRS.EPSG3395
   *
   * Rarely used by some commercial tile providers. Uses Elliptical Mercator projection.
   */
  var EPSG3395 = extend({}, Earth, {
  \tcode: 'EPSG:3395',
  \tprojection: Mercator,

  \ttransformation: (function () {
  \t\tvar scale = 0.5 / (Math.PI * Mercator.R);
  \t\treturn toTransformation(scale, 0.5, -scale, 0.5);
  \t}())
  });

  /*
   * @namespace CRS
   * @crs L.CRS.EPSG4326
   *
   * A common CRS among GIS enthusiasts. Uses simple Equirectangular projection.
   *
   * Leaflet 1.0.x complies with the [TMS coordinate scheme for EPSG:4326](https://wiki.osgeo.org/wiki/Tile_Map_Service_Specification#global-geodetic),
   * which is a breaking change from 0.7.x behaviour.  If you are using a `TileLayer`
   * with this CRS, ensure that there are two 256x256 pixel tiles covering the
   * whole earth at zoom level zero, and that the tile coordinate origin is (-180,+90),
   * or (-180,-90) for `TileLayer`s with [the `tms` option](#tilelayer-tms) set.
   */

  var EPSG4326 = extend({}, Earth, {
  \tcode: 'EPSG:4326',
  \tprojection: LonLat,
  \ttransformation: toTransformation(1 / 180, 1, -1 / 180, 0.5)
  });

  /*
   * @namespace CRS
   * @crs L.CRS.Simple
   *
   * A simple CRS that maps longitude and latitude into `x` and `y` directly.
   * May be used for maps of flat surfaces (e.g. game maps). Note that the `y`
   * axis should still be inverted (going from bottom to top). `distance()` returns
   * simple euclidean distance.
   */

  var Simple = extend({}, CRS, {
  \tprojection: LonLat,
  \ttransformation: toTransformation(1, 0, -1, 0),

  \tscale: function (zoom) {
  \t\treturn Math.pow(2, zoom);
  \t},

  \tzoom: function (scale) {
  \t\treturn Math.log(scale) / Math.LN2;
  \t},

  \tdistance: function (latlng1, latlng2) {
  \t\tvar dx = latlng2.lng - latlng1.lng,
  \t\t    dy = latlng2.lat - latlng1.lat;

  \t\treturn Math.sqrt(dx * dx + dy * dy);
  \t},

  \tinfinite: true
  });

  CRS.Earth = Earth;
  CRS.EPSG3395 = EPSG3395;
  CRS.EPSG3857 = EPSG3857;
  CRS.EPSG900913 = EPSG900913;
  CRS.EPSG4326 = EPSG4326;
  CRS.Simple = Simple;

  /*
   * @class Layer
   * @inherits Evented
   * @aka L.Layer
   * @aka ILayer
   *
   * A set of methods from the Layer base class that all Leaflet layers use.
   * Inherits all methods, options and events from `L.Evented`.
   *
   * @example
   *
   * ```js
   * var layer = L.marker(latlng).addTo(map);
   * layer.addTo(map);
   * layer.remove();
   * ```
   *
   * @event add: Event
   * Fired after the layer is added to a map
   *
   * @event remove: Event
   * Fired after the layer is removed from a map
   */


  var Layer = Evented.extend({

  \t// Classes extending `L.Layer` will inherit the following options:
  \toptions: {
  \t\t// @option pane: String = 'overlayPane'
  \t\t// By default the layer will be added to the map's [overlay pane](#map-overlaypane). Overriding this option will cause the layer to be placed on another pane by default.
  \t\tpane: 'overlayPane',

  \t\t// @option attribution: String = null
  \t\t// String to be shown in the attribution control, e.g. \"© OpenStreetMap contributors\". It describes the layer data and is often a legal obligation towards copyright holders and tile providers.
  \t\tattribution: null,

  \t\tbubblingMouseEvents: true
  \t},

  \t/* @section
  \t * Classes extending `L.Layer` will inherit the following methods:
  \t *
  \t * @method addTo(map: Map|LayerGroup): this
  \t * Adds the layer to the given map or layer group.
  \t */
  \taddTo: function (map) {
  \t\tmap.addLayer(this);
  \t\treturn this;
  \t},

  \t// @method remove: this
  \t// Removes the layer from the map it is currently active on.
  \tremove: function () {
  \t\treturn this.removeFrom(this._map || this._mapToAdd);
  \t},

  \t// @method removeFrom(map: Map): this
  \t// Removes the layer from the given map
  \t//
  \t// @alternative
  \t// @method removeFrom(group: LayerGroup): this
  \t// Removes the layer from the given `LayerGroup`
  \tremoveFrom: function (obj) {
  \t\tif (obj) {
  \t\t\tobj.removeLayer(this);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method getPane(name? : String): HTMLElement
  \t// Returns the `HTMLElement` representing the named pane on the map. If `name` is omitted, returns the pane for this layer.
  \tgetPane: function (name) {
  \t\treturn this._map.getPane(name ? (this.options[name] || name) : this.options.pane);
  \t},

  \taddInteractiveTarget: function (targetEl) {
  \t\tthis._map._targets[stamp(targetEl)] = this;
  \t\treturn this;
  \t},

  \tremoveInteractiveTarget: function (targetEl) {
  \t\tdelete this._map._targets[stamp(targetEl)];
  \t\treturn this;
  \t},

  \t// @method getAttribution: String
  \t// Used by the `attribution control`, returns the [attribution option](#gridlayer-attribution).
  \tgetAttribution: function () {
  \t\treturn this.options.attribution;
  \t},

  \t_layerAdd: function (e) {
  \t\tvar map = e.target;

  \t\t// check in case layer gets added and then removed before the map is ready
  \t\tif (!map.hasLayer(this)) { return; }

  \t\tthis._map = map;
  \t\tthis._zoomAnimated = map._zoomAnimated;

  \t\tif (this.getEvents) {
  \t\t\tvar events = this.getEvents();
  \t\t\tmap.on(events, this);
  \t\t\tthis.once('remove', function () {
  \t\t\t\tmap.off(events, this);
  \t\t\t}, this);
  \t\t}

  \t\tthis.onAdd(map);

  \t\tthis.fire('add');
  \t\tmap.fire('layeradd', {layer: this});
  \t}
  });

  /* @section Extension methods
   * @uninheritable
   *
   * Every layer should extend from `L.Layer` and (re-)implement the following methods.
   *
   * @method onAdd(map: Map): this
   * Should contain code that creates DOM elements for the layer, adds them to `map panes` where they should belong and puts listeners on relevant map events. Called on [`map.addLayer(layer)`](#map-addlayer).
   *
   * @method onRemove(map: Map): this
   * Should contain all clean up code that removes the layer's elements from the DOM and removes listeners previously added in [`onAdd`](#layer-onadd). Called on [`map.removeLayer(layer)`](#map-removelayer).
   *
   * @method getEvents(): Object
   * This optional method should return an object like `{ viewreset: this._reset }` for [`addEventListener`](#evented-addeventlistener). The event handlers in this object will be automatically added and removed from the map with your layer.
   *
   * @method getAttribution(): String
   * This optional method should return a string containing HTML to be shown on the `Attribution control` whenever the layer is visible.
   *
   * @method beforeAdd(map: Map): this
   * Optional method. Called on [`map.addLayer(layer)`](#map-addlayer), before the layer is added to the map, before events are initialized, without waiting until the map is in a usable state. Use for early initialization only.
   */


  /* @namespace Map
   * @section Layer events
   *
   * @event layeradd: LayerEvent
   * Fired when a new layer is added to the map.
   *
   * @event layerremove: LayerEvent
   * Fired when some layer is removed from the map
   *
   * @section Methods for Layers and Controls
   */
  Map.include({
  \t// @method addLayer(layer: Layer): this
  \t// Adds the given layer to the map
  \taddLayer: function (layer) {
  \t\tif (!layer._layerAdd) {
  \t\t\tthrow new Error('The provided object is not a Layer.');
  \t\t}

  \t\tvar id = stamp(layer);
  \t\tif (this._layers[id]) { return this; }
  \t\tthis._layers[id] = layer;

  \t\tlayer._mapToAdd = this;

  \t\tif (layer.beforeAdd) {
  \t\t\tlayer.beforeAdd(this);
  \t\t}

  \t\tthis.whenReady(layer._layerAdd, layer);

  \t\treturn this;
  \t},

  \t// @method removeLayer(layer: Layer): this
  \t// Removes the given layer from the map.
  \tremoveLayer: function (layer) {
  \t\tvar id = stamp(layer);

  \t\tif (!this._layers[id]) { return this; }

  \t\tif (this._loaded) {
  \t\t\tlayer.onRemove(this);
  \t\t}

  \t\tdelete this._layers[id];

  \t\tif (this._loaded) {
  \t\t\tthis.fire('layerremove', {layer: layer});
  \t\t\tlayer.fire('remove');
  \t\t}

  \t\tlayer._map = layer._mapToAdd = null;

  \t\treturn this;
  \t},

  \t// @method hasLayer(layer: Layer): Boolean
  \t// Returns `true` if the given layer is currently added to the map
  \thasLayer: function (layer) {
  \t\treturn stamp(layer) in this._layers;
  \t},

  \t/* @method eachLayer(fn: Function, context?: Object): this
  \t * Iterates over the layers of the map, optionally specifying context of the iterator function.
  \t * ```
  \t * map.eachLayer(function(layer){
  \t *     layer.bindPopup('Hello');
  \t * });
  \t * ```
  \t */
  \teachLayer: function (method, context) {
  \t\tfor (var i in this._layers) {
  \t\t\tmethod.call(context, this._layers[i]);
  \t\t}
  \t\treturn this;
  \t},

  \t_addLayers: function (layers) {
  \t\tlayers = layers ? (isArray(layers) ? layers : [layers]) : [];

  \t\tfor (var i = 0, len = layers.length; i < len; i++) {
  \t\t\tthis.addLayer(layers[i]);
  \t\t}
  \t},

  \t_addZoomLimit: function (layer) {
  \t\tif (!isNaN(layer.options.maxZoom) || !isNaN(layer.options.minZoom)) {
  \t\t\tthis._zoomBoundLayers[stamp(layer)] = layer;
  \t\t\tthis._updateZoomLevels();
  \t\t}
  \t},

  \t_removeZoomLimit: function (layer) {
  \t\tvar id = stamp(layer);

  \t\tif (this._zoomBoundLayers[id]) {
  \t\t\tdelete this._zoomBoundLayers[id];
  \t\t\tthis._updateZoomLevels();
  \t\t}
  \t},

  \t_updateZoomLevels: function () {
  \t\tvar minZoom = Infinity,
  \t\t    maxZoom = -Infinity,
  \t\t    oldZoomSpan = this._getZoomSpan();

  \t\tfor (var i in this._zoomBoundLayers) {
  \t\t\tvar options = this._zoomBoundLayers[i].options;

  \t\t\tminZoom = options.minZoom === undefined ? minZoom : Math.min(minZoom, options.minZoom);
  \t\t\tmaxZoom = options.maxZoom === undefined ? maxZoom : Math.max(maxZoom, options.maxZoom);
  \t\t}

  \t\tthis._layersMaxZoom = maxZoom === -Infinity ? undefined : maxZoom;
  \t\tthis._layersMinZoom = minZoom === Infinity ? undefined : minZoom;

  \t\t// @section Map state change events
  \t\t// @event zoomlevelschange: Event
  \t\t// Fired when the number of zoomlevels on the map is changed due
  \t\t// to adding or removing a layer.
  \t\tif (oldZoomSpan !== this._getZoomSpan()) {
  \t\t\tthis.fire('zoomlevelschange');
  \t\t}

  \t\tif (this.options.maxZoom === undefined && this._layersMaxZoom && this.getZoom() > this._layersMaxZoom) {
  \t\t\tthis.setZoom(this._layersMaxZoom);
  \t\t}
  \t\tif (this.options.minZoom === undefined && this._layersMinZoom && this.getZoom() < this._layersMinZoom) {
  \t\t\tthis.setZoom(this._layersMinZoom);
  \t\t}
  \t}
  });

  /*
   * @class LayerGroup
   * @aka L.LayerGroup
   * @inherits Interactive layer
   *
   * Used to group several layers and handle them as one. If you add it to the map,
   * any layers added or removed from the group will be added/removed on the map as
   * well. Extends `Layer`.
   *
   * @example
   *
   * ```js
   * L.layerGroup([marker1, marker2])
   * \t.addLayer(polyline)
   * \t.addTo(map);
   * ```
   */

  var LayerGroup = Layer.extend({

  \tinitialize: function (layers, options) {
  \t\tsetOptions(this, options);

  \t\tthis._layers = {};

  \t\tvar i, len;

  \t\tif (layers) {
  \t\t\tfor (i = 0, len = layers.length; i < len; i++) {
  \t\t\t\tthis.addLayer(layers[i]);
  \t\t\t}
  \t\t}
  \t},

  \t// @method addLayer(layer: Layer): this
  \t// Adds the given layer to the group.
  \taddLayer: function (layer) {
  \t\tvar id = this.getLayerId(layer);

  \t\tthis._layers[id] = layer;

  \t\tif (this._map) {
  \t\t\tthis._map.addLayer(layer);
  \t\t}

  \t\treturn this;
  \t},

  \t// @method removeLayer(layer: Layer): this
  \t// Removes the given layer from the group.
  \t// @alternative
  \t// @method removeLayer(id: Number): this
  \t// Removes the layer with the given internal ID from the group.
  \tremoveLayer: function (layer) {
  \t\tvar id = layer in this._layers ? layer : this.getLayerId(layer);

  \t\tif (this._map && this._layers[id]) {
  \t\t\tthis._map.removeLayer(this._layers[id]);
  \t\t}

  \t\tdelete this._layers[id];

  \t\treturn this;
  \t},

  \t// @method hasLayer(layer: Layer): Boolean
  \t// Returns `true` if the given layer is currently added to the group.
  \t// @alternative
  \t// @method hasLayer(id: Number): Boolean
  \t// Returns `true` if the given internal ID is currently added to the group.
  \thasLayer: function (layer) {
  \t\tvar layerId = typeof layer === 'number' ? layer : this.getLayerId(layer);
  \t\treturn layerId in this._layers;
  \t},

  \t// @method clearLayers(): this
  \t// Removes all the layers from the group.
  \tclearLayers: function () {
  \t\treturn this.eachLayer(this.removeLayer, this);
  \t},

  \t// @method invoke(methodName: String, …): this
  \t// Calls `methodName` on every layer contained in this group, passing any
  \t// additional parameters. Has no effect if the layers contained do not
  \t// implement `methodName`.
  \tinvoke: function (methodName) {
  \t\tvar args = Array.prototype.slice.call(arguments, 1),
  \t\t    i, layer;

  \t\tfor (i in this._layers) {
  \t\t\tlayer = this._layers[i];

  \t\t\tif (layer[methodName]) {
  \t\t\t\tlayer[methodName].apply(layer, args);
  \t\t\t}
  \t\t}

  \t\treturn this;
  \t},

  \tonAdd: function (map) {
  \t\tthis.eachLayer(map.addLayer, map);
  \t},

  \tonRemove: function (map) {
  \t\tthis.eachLayer(map.removeLayer, map);
  \t},

  \t// @method eachLayer(fn: Function, context?: Object): this
  \t// Iterates over the layers of the group, optionally specifying context of the iterator function.
  \t// ```js
  \t// group.eachLayer(function (layer) {
  \t// \tlayer.bindPopup('Hello');
  \t// });
  \t// ```
  \teachLayer: function (method, context) {
  \t\tfor (var i in this._layers) {
  \t\t\tmethod.call(context, this._layers[i]);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method getLayer(id: Number): Layer
  \t// Returns the layer with the given internal ID.
  \tgetLayer: function (id) {
  \t\treturn this._layers[id];
  \t},

  \t// @method getLayers(): Layer[]
  \t// Returns an array of all the layers added to the group.
  \tgetLayers: function () {
  \t\tvar layers = [];
  \t\tthis.eachLayer(layers.push, layers);
  \t\treturn layers;
  \t},

  \t// @method setZIndex(zIndex: Number): this
  \t// Calls `setZIndex` on every layer contained in this group, passing the z-index.
  \tsetZIndex: function (zIndex) {
  \t\treturn this.invoke('setZIndex', zIndex);
  \t},

  \t// @method getLayerId(layer: Layer): Number
  \t// Returns the internal ID for a layer
  \tgetLayerId: function (layer) {
  \t\treturn stamp(layer);
  \t}
  });


  // @factory L.layerGroup(layers?: Layer[], options?: Object)
  // Create a layer group, optionally given an initial set of layers and an `options` object.
  var layerGroup = function (layers, options) {
  \treturn new LayerGroup(layers, options);
  };

  /*
   * @class FeatureGroup
   * @aka L.FeatureGroup
   * @inherits LayerGroup
   *
   * Extended `LayerGroup` that makes it easier to do the same thing to all its member layers:
   *  * [`bindPopup`](#layer-bindpopup) binds a popup to all of the layers at once (likewise with [`bindTooltip`](#layer-bindtooltip))
   *  * Events are propagated to the `FeatureGroup`, so if the group has an event
   * handler, it will handle events from any of the layers. This includes mouse events
   * and custom events.
   *  * Has `layeradd` and `layerremove` events
   *
   * @example
   *
   * ```js
   * L.featureGroup([marker1, marker2, polyline])
   * \t.bindPopup('Hello world!')
   * \t.on('click', function() { alert('Clicked on a member of the group!'); })
   * \t.addTo(map);
   * ```
   */

  var FeatureGroup = LayerGroup.extend({

  \taddLayer: function (layer) {
  \t\tif (this.hasLayer(layer)) {
  \t\t\treturn this;
  \t\t}

  \t\tlayer.addEventParent(this);

  \t\tLayerGroup.prototype.addLayer.call(this, layer);

  \t\t// @event layeradd: LayerEvent
  \t\t// Fired when a layer is added to this `FeatureGroup`
  \t\treturn this.fire('layeradd', {layer: layer});
  \t},

  \tremoveLayer: function (layer) {
  \t\tif (!this.hasLayer(layer)) {
  \t\t\treturn this;
  \t\t}
  \t\tif (layer in this._layers) {
  \t\t\tlayer = this._layers[layer];
  \t\t}

  \t\tlayer.removeEventParent(this);

  \t\tLayerGroup.prototype.removeLayer.call(this, layer);

  \t\t// @event layerremove: LayerEvent
  \t\t// Fired when a layer is removed from this `FeatureGroup`
  \t\treturn this.fire('layerremove', {layer: layer});
  \t},

  \t// @method setStyle(style: Path options): this
  \t// Sets the given path options to each layer of the group that has a `setStyle` method.
  \tsetStyle: function (style) {
  \t\treturn this.invoke('setStyle', style);
  \t},

  \t// @method bringToFront(): this
  \t// Brings the layer group to the top of all other layers
  \tbringToFront: function () {
  \t\treturn this.invoke('bringToFront');
  \t},

  \t// @method bringToBack(): this
  \t// Brings the layer group to the back of all other layers
  \tbringToBack: function () {
  \t\treturn this.invoke('bringToBack');
  \t},

  \t// @method getBounds(): LatLngBounds
  \t// Returns the LatLngBounds of the Feature Group (created from bounds and coordinates of its children).
  \tgetBounds: function () {
  \t\tvar bounds = new LatLngBounds();

  \t\tfor (var id in this._layers) {
  \t\t\tvar layer = this._layers[id];
  \t\t\tbounds.extend(layer.getBounds ? layer.getBounds() : layer.getLatLng());
  \t\t}
  \t\treturn bounds;
  \t}
  });

  // @factory L.featureGroup(layers?: Layer[], options?: Object)
  // Create a feature group, optionally given an initial set of layers and an `options` object.
  var featureGroup = function (layers, options) {
  \treturn new FeatureGroup(layers, options);
  };

  /*
   * @class Icon
   * @aka L.Icon
   *
   * Represents an icon to provide when creating a marker.
   *
   * @example
   *
   * ```js
   * var myIcon = L.icon({
   *     iconUrl: 'my-icon.png',
   *     iconRetinaUrl: 'my-icon@2x.png',
   *     iconSize: [38, 95],
   *     iconAnchor: [22, 94],
   *     popupAnchor: [-3, -76],
   *     shadowUrl: 'my-icon-shadow.png',
   *     shadowRetinaUrl: 'my-icon-shadow@2x.png',
   *     shadowSize: [68, 95],
   *     shadowAnchor: [22, 94]
   * });
   *
   * L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
   * ```
   *
   * `L.Icon.Default` extends `L.Icon` and is the blue icon Leaflet uses for markers by default.
   *
   */

  var Icon = Class.extend({

  \t/* @section
  \t * @aka Icon options
  \t *
  \t * @option iconUrl: String = null
  \t * **(required)** The URL to the icon image (absolute or relative to your script path).
  \t *
  \t * @option iconRetinaUrl: String = null
  \t * The URL to a retina sized version of the icon image (absolute or relative to your
  \t * script path). Used for Retina screen devices.
  \t *
  \t * @option iconSize: Point = null
  \t * Size of the icon image in pixels.
  \t *
  \t * @option iconAnchor: Point = null
  \t * The coordinates of the \"tip\" of the icon (relative to its top left corner). The icon
  \t * will be aligned so that this point is at the marker's geographical location. Centered
  \t * by default if size is specified, also can be set in CSS with negative margins.
  \t *
  \t * @option popupAnchor: Point = [0, 0]
  \t * The coordinates of the point from which popups will \"open\", relative to the icon anchor.
  \t *
  \t * @option tooltipAnchor: Point = [0, 0]
  \t * The coordinates of the point from which tooltips will \"open\", relative to the icon anchor.
  \t *
  \t * @option shadowUrl: String = null
  \t * The URL to the icon shadow image. If not specified, no shadow image will be created.
  \t *
  \t * @option shadowRetinaUrl: String = null
  \t *
  \t * @option shadowSize: Point = null
  \t * Size of the shadow image in pixels.
  \t *
  \t * @option shadowAnchor: Point = null
  \t * The coordinates of the \"tip\" of the shadow (relative to its top left corner) (the same
  \t * as iconAnchor if not specified).
  \t *
  \t * @option className: String = ''
  \t * A custom class name to assign to both icon and shadow images. Empty by default.
  \t */

  \toptions: {
  \t\tpopupAnchor: [0, 0],
  \t\ttooltipAnchor: [0, 0],

  \t\t// @option crossOrigin: Boolean|String = false
  \t\t// Whether the crossOrigin attribute will be added to the tiles.
  \t\t// If a String is provided, all tiles will have their crossOrigin attribute set to the String provided. This is needed if you want to access tile pixel data.
  \t\t// Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values.
  \t\tcrossOrigin: false
  \t},

  \tinitialize: function (options) {
  \t\tsetOptions(this, options);
  \t},

  \t// @method createIcon(oldIcon?: HTMLElement): HTMLElement
  \t// Called internally when the icon has to be shown, returns a `<img>` HTML element
  \t// styled according to the options.
  \tcreateIcon: function (oldIcon) {
  \t\treturn this._createIcon('icon', oldIcon);
  \t},

  \t// @method createShadow(oldIcon?: HTMLElement): HTMLElement
  \t// As `createIcon`, but for the shadow beneath it.
  \tcreateShadow: function (oldIcon) {
  \t\treturn this._createIcon('shadow', oldIcon);
  \t},

  \t_createIcon: function (name, oldIcon) {
  \t\tvar src = this._getIconUrl(name);

  \t\tif (!src) {
  \t\t\tif (name === 'icon') {
  \t\t\t\tthrow new Error('iconUrl not set in Icon options (see the docs).');
  \t\t\t}
  \t\t\treturn null;
  \t\t}

  \t\tvar img = this._createImg(src, oldIcon && oldIcon.tagName === 'IMG' ? oldIcon : null);
  \t\tthis._setIconStyles(img, name);

  \t\tif (this.options.crossOrigin || this.options.crossOrigin === '') {
  \t\t\timg.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin;
  \t\t}

  \t\treturn img;
  \t},

  \t_setIconStyles: function (img, name) {
  \t\tvar options = this.options;
  \t\tvar sizeOption = options[name + 'Size'];

  \t\tif (typeof sizeOption === 'number') {
  \t\t\tsizeOption = [sizeOption, sizeOption];
  \t\t}

  \t\tvar size = toPoint(sizeOption),
  \t\t    anchor = toPoint(name === 'shadow' && options.shadowAnchor || options.iconAnchor ||
  \t\t            size && size.divideBy(2, true));

  \t\timg.className = 'leaflet-marker-' + name + ' ' + (options.className || '');

  \t\tif (anchor) {
  \t\t\timg.style.marginLeft = (-anchor.x) + 'px';
  \t\t\timg.style.marginTop  = (-anchor.y) + 'px';
  \t\t}

  \t\tif (size) {
  \t\t\timg.style.width  = size.x + 'px';
  \t\t\timg.style.height = size.y + 'px';
  \t\t}
  \t},

  \t_createImg: function (src, el) {
  \t\tel = el || document.createElement('img');
  \t\tel.src = src;
  \t\treturn el;
  \t},

  \t_getIconUrl: function (name) {
  \t\treturn Browser.retina && this.options[name + 'RetinaUrl'] || this.options[name + 'Url'];
  \t}
  });


  // @factory L.icon(options: Icon options)
  // Creates an icon instance with the given options.
  function icon(options) {
  \treturn new Icon(options);
  }

  /*
   * @miniclass Icon.Default (Icon)
   * @aka L.Icon.Default
   * @section
   *
   * A trivial subclass of `Icon`, represents the icon to use in `Marker`s when
   * no icon is specified. Points to the blue marker image distributed with Leaflet
   * releases.
   *
   * In order to customize the default icon, just change the properties of `L.Icon.Default.prototype.options`
   * (which is a set of `Icon options`).
   *
   * If you want to _completely_ replace the default icon, override the
   * `L.Marker.prototype.options.icon` with your own icon instead.
   */

  var IconDefault = Icon.extend({

  \toptions: {
  \t\ticonUrl:       'marker-icon.png',
  \t\ticonRetinaUrl: 'marker-icon-2x.png',
  \t\tshadowUrl:     'marker-shadow.png',
  \t\ticonSize:    [25, 41],
  \t\ticonAnchor:  [12, 41],
  \t\tpopupAnchor: [1, -34],
  \t\ttooltipAnchor: [16, -28],
  \t\tshadowSize:  [41, 41]
  \t},

  \t_getIconUrl: function (name) {
  \t\tif (typeof IconDefault.imagePath !== 'string') {\t// Deprecated, backwards-compatibility only
  \t\t\tIconDefault.imagePath = this._detectIconPath();
  \t\t}

  \t\t// @option imagePath: String
  \t\t// `Icon.Default` will try to auto-detect the location of the
  \t\t// blue icon images. If you are placing these images in a non-standard
  \t\t// way, set this option to point to the right path.
  \t\treturn (this.options.imagePath || IconDefault.imagePath) + Icon.prototype._getIconUrl.call(this, name);
  \t},

  \t_stripUrl: function (path) {\t// separate function to use in tests
  \t\tvar strip = function (str, re, idx) {
  \t\t\tvar match = re.exec(str);
  \t\t\treturn match && match[idx];
  \t\t};
  \t\tpath = strip(path, /^url\\((['\"])?(.+)\\1\\)\$/, 2);
  \t\treturn path && strip(path, /^(.*)marker-icon\\.png\$/, 1);
  \t},

  \t_detectIconPath: function () {
  \t\tvar el = create\$1('div',  'leaflet-default-icon-path', document.body);
  \t\tvar path = getStyle(el, 'background-image') ||
  \t\t           getStyle(el, 'backgroundImage');\t// IE8

  \t\tdocument.body.removeChild(el);
  \t\tpath = this._stripUrl(path);
  \t\tif (path) { return path; }
  \t\tvar link = document.querySelector('link[href\$=\"leaflet.css\"]');
  \t\tif (!link) { return ''; }
  \t\treturn link.href.substring(0, link.href.length - 'leaflet.css'.length - 1);
  \t}
  });

  /*
   * L.Handler.MarkerDrag is used internally by L.Marker to make the markers draggable.
   */


  /* @namespace Marker
   * @section Interaction handlers
   *
   * Interaction handlers are properties of a marker instance that allow you to control interaction behavior in runtime, enabling or disabling certain features such as dragging (see `Handler` methods). Example:
   *
   * ```js
   * marker.dragging.disable();
   * ```
   *
   * @property dragging: Handler
   * Marker dragging handler (by both mouse and touch). Only valid when the marker is on the map (Otherwise set [`marker.options.draggable`](#marker-draggable)).
   */

  var MarkerDrag = Handler.extend({
  \tinitialize: function (marker) {
  \t\tthis._marker = marker;
  \t},

  \taddHooks: function () {
  \t\tvar icon = this._marker._icon;

  \t\tif (!this._draggable) {
  \t\t\tthis._draggable = new Draggable(icon, icon, true);
  \t\t}

  \t\tthis._draggable.on({
  \t\t\tdragstart: this._onDragStart,
  \t\t\tpredrag: this._onPreDrag,
  \t\t\tdrag: this._onDrag,
  \t\t\tdragend: this._onDragEnd
  \t\t}, this).enable();

  \t\taddClass(icon, 'leaflet-marker-draggable');
  \t},

  \tremoveHooks: function () {
  \t\tthis._draggable.off({
  \t\t\tdragstart: this._onDragStart,
  \t\t\tpredrag: this._onPreDrag,
  \t\t\tdrag: this._onDrag,
  \t\t\tdragend: this._onDragEnd
  \t\t}, this).disable();

  \t\tif (this._marker._icon) {
  \t\t\tremoveClass(this._marker._icon, 'leaflet-marker-draggable');
  \t\t}
  \t},

  \tmoved: function () {
  \t\treturn this._draggable && this._draggable._moved;
  \t},

  \t_adjustPan: function (e) {
  \t\tvar marker = this._marker,
  \t\t    map = marker._map,
  \t\t    speed = this._marker.options.autoPanSpeed,
  \t\t    padding = this._marker.options.autoPanPadding,
  \t\t    iconPos = getPosition(marker._icon),
  \t\t    bounds = map.getPixelBounds(),
  \t\t    origin = map.getPixelOrigin();

  \t\tvar panBounds = toBounds(
  \t\t\tbounds.min._subtract(origin).add(padding),
  \t\t\tbounds.max._subtract(origin).subtract(padding)
  \t\t);

  \t\tif (!panBounds.contains(iconPos)) {
  \t\t\t// Compute incremental movement
  \t\t\tvar movement = toPoint(
  \t\t\t\t(Math.max(panBounds.max.x, iconPos.x) - panBounds.max.x) / (bounds.max.x - panBounds.max.x) -
  \t\t\t\t(Math.min(panBounds.min.x, iconPos.x) - panBounds.min.x) / (bounds.min.x - panBounds.min.x),

  \t\t\t\t(Math.max(panBounds.max.y, iconPos.y) - panBounds.max.y) / (bounds.max.y - panBounds.max.y) -
  \t\t\t\t(Math.min(panBounds.min.y, iconPos.y) - panBounds.min.y) / (bounds.min.y - panBounds.min.y)
  \t\t\t).multiplyBy(speed);

  \t\t\tmap.panBy(movement, {animate: false});

  \t\t\tthis._draggable._newPos._add(movement);
  \t\t\tthis._draggable._startPos._add(movement);

  \t\t\tsetPosition(marker._icon, this._draggable._newPos);
  \t\t\tthis._onDrag(e);

  \t\t\tthis._panRequest = requestAnimFrame(this._adjustPan.bind(this, e));
  \t\t}
  \t},

  \t_onDragStart: function () {
  \t\t// @section Dragging events
  \t\t// @event dragstart: Event
  \t\t// Fired when the user starts dragging the marker.

  \t\t// @event movestart: Event
  \t\t// Fired when the marker starts moving (because of dragging).

  \t\tthis._oldLatLng = this._marker.getLatLng();

  \t\t// When using ES6 imports it could not be set when `Popup` was not imported as well
  \t\tthis._marker.closePopup && this._marker.closePopup();

  \t\tthis._marker
  \t\t\t.fire('movestart')
  \t\t\t.fire('dragstart');
  \t},

  \t_onPreDrag: function (e) {
  \t\tif (this._marker.options.autoPan) {
  \t\t\tcancelAnimFrame(this._panRequest);
  \t\t\tthis._panRequest = requestAnimFrame(this._adjustPan.bind(this, e));
  \t\t}
  \t},

  \t_onDrag: function (e) {
  \t\tvar marker = this._marker,
  \t\t    shadow = marker._shadow,
  \t\t    iconPos = getPosition(marker._icon),
  \t\t    latlng = marker._map.layerPointToLatLng(iconPos);

  \t\t// update shadow position
  \t\tif (shadow) {
  \t\t\tsetPosition(shadow, iconPos);
  \t\t}

  \t\tmarker._latlng = latlng;
  \t\te.latlng = latlng;
  \t\te.oldLatLng = this._oldLatLng;

  \t\t// @event drag: Event
  \t\t// Fired repeatedly while the user drags the marker.
  \t\tmarker
  \t\t    .fire('move', e)
  \t\t    .fire('drag', e);
  \t},

  \t_onDragEnd: function (e) {
  \t\t// @event dragend: DragEndEvent
  \t\t// Fired when the user stops dragging the marker.

  \t\t cancelAnimFrame(this._panRequest);

  \t\t// @event moveend: Event
  \t\t// Fired when the marker stops moving (because of dragging).
  \t\tdelete this._oldLatLng;
  \t\tthis._marker
  \t\t    .fire('moveend')
  \t\t    .fire('dragend', e);
  \t}
  });

  /*
   * @class Marker
   * @inherits Interactive layer
   * @aka L.Marker
   * L.Marker is used to display clickable/draggable icons on the map. Extends `Layer`.
   *
   * @example
   *
   * ```js
   * L.marker([50.5, 30.5]).addTo(map);
   * ```
   */

  var Marker = Layer.extend({

  \t// @section
  \t// @aka Marker options
  \toptions: {
  \t\t// @option icon: Icon = *
  \t\t// Icon instance to use for rendering the marker.
  \t\t// See [Icon documentation](#L.Icon) for details on how to customize the marker icon.
  \t\t// If not specified, a common instance of `L.Icon.Default` is used.
  \t\ticon: new IconDefault(),

  \t\t// Option inherited from \"Interactive layer\" abstract class
  \t\tinteractive: true,

  \t\t// @option keyboard: Boolean = true
  \t\t// Whether the marker can be tabbed to with a keyboard and clicked by pressing enter.
  \t\tkeyboard: true,

  \t\t// @option title: String = ''
  \t\t// Text for the browser tooltip that appear on marker hover (no tooltip by default).
  \t\t// [Useful for accessibility](https://leafletjs.com/examples/accessibility/#markers-must-be-labelled).
  \t\ttitle: '',

  \t\t// @option alt: String = 'Marker'
  \t\t// Text for the `alt` attribute of the icon image.
  \t\t// [Useful for accessibility](https://leafletjs.com/examples/accessibility/#markers-must-be-labelled).
  \t\talt: 'Marker',

  \t\t// @option zIndexOffset: Number = 0
  \t\t// By default, marker images zIndex is set automatically based on its latitude. Use this option if you want to put the marker on top of all others (or below), specifying a high value like `1000` (or high negative value, respectively).
  \t\tzIndexOffset: 0,

  \t\t// @option opacity: Number = 1.0
  \t\t// The opacity of the marker.
  \t\topacity: 1,

  \t\t// @option riseOnHover: Boolean = false
  \t\t// If `true`, the marker will get on top of others when you hover the mouse over it.
  \t\triseOnHover: false,

  \t\t// @option riseOffset: Number = 250
  \t\t// The z-index offset used for the `riseOnHover` feature.
  \t\triseOffset: 250,

  \t\t// @option pane: String = 'markerPane'
  \t\t// `Map pane` where the markers icon will be added.
  \t\tpane: 'markerPane',

  \t\t// @option shadowPane: String = 'shadowPane'
  \t\t// `Map pane` where the markers shadow will be added.
  \t\tshadowPane: 'shadowPane',

  \t\t// @option bubblingMouseEvents: Boolean = false
  \t\t// When `true`, a mouse event on this marker will trigger the same event on the map
  \t\t// (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used).
  \t\tbubblingMouseEvents: false,

  \t\t// @option autoPanOnFocus: Boolean = true
  \t\t// When `true`, the map will pan whenever the marker is focused (via
  \t\t// e.g. pressing `tab` on the keyboard) to ensure the marker is
  \t\t// visible within the map's bounds
  \t\tautoPanOnFocus: true,

  \t\t// @section Draggable marker options
  \t\t// @option draggable: Boolean = false
  \t\t// Whether the marker is draggable with mouse/touch or not.
  \t\tdraggable: false,

  \t\t// @option autoPan: Boolean = false
  \t\t// Whether to pan the map when dragging this marker near its edge or not.
  \t\tautoPan: false,

  \t\t// @option autoPanPadding: Point = Point(50, 50)
  \t\t// Distance (in pixels to the left/right and to the top/bottom) of the
  \t\t// map edge to start panning the map.
  \t\tautoPanPadding: [50, 50],

  \t\t// @option autoPanSpeed: Number = 10
  \t\t// Number of pixels the map should pan by.
  \t\tautoPanSpeed: 10
  \t},

  \t/* @section
  \t *
  \t * In addition to [shared layer methods](#Layer) like `addTo()` and `remove()` and [popup methods](#Popup) like bindPopup() you can also use the following methods:
  \t */

  \tinitialize: function (latlng, options) {
  \t\tsetOptions(this, options);
  \t\tthis._latlng = toLatLng(latlng);
  \t},

  \tonAdd: function (map) {
  \t\tthis._zoomAnimated = this._zoomAnimated && map.options.markerZoomAnimation;

  \t\tif (this._zoomAnimated) {
  \t\t\tmap.on('zoomanim', this._animateZoom, this);
  \t\t}

  \t\tthis._initIcon();
  \t\tthis.update();
  \t},

  \tonRemove: function (map) {
  \t\tif (this.dragging && this.dragging.enabled()) {
  \t\t\tthis.options.draggable = true;
  \t\t\tthis.dragging.removeHooks();
  \t\t}
  \t\tdelete this.dragging;

  \t\tif (this._zoomAnimated) {
  \t\t\tmap.off('zoomanim', this._animateZoom, this);
  \t\t}

  \t\tthis._removeIcon();
  \t\tthis._removeShadow();
  \t},

  \tgetEvents: function () {
  \t\treturn {
  \t\t\tzoom: this.update,
  \t\t\tviewreset: this.update
  \t\t};
  \t},

  \t// @method getLatLng: LatLng
  \t// Returns the current geographical position of the marker.
  \tgetLatLng: function () {
  \t\treturn this._latlng;
  \t},

  \t// @method setLatLng(latlng: LatLng): this
  \t// Changes the marker position to the given point.
  \tsetLatLng: function (latlng) {
  \t\tvar oldLatLng = this._latlng;
  \t\tthis._latlng = toLatLng(latlng);
  \t\tthis.update();

  \t\t// @event move: Event
  \t\t// Fired when the marker is moved via [`setLatLng`](#marker-setlatlng) or by [dragging](#marker-dragging). Old and new coordinates are included in event arguments as `oldLatLng`, `latlng`.
  \t\treturn this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng});
  \t},

  \t// @method setZIndexOffset(offset: Number): this
  \t// Changes the [zIndex offset](#marker-zindexoffset) of the marker.
  \tsetZIndexOffset: function (offset) {
  \t\tthis.options.zIndexOffset = offset;
  \t\treturn this.update();
  \t},

  \t// @method getIcon: Icon
  \t// Returns the current icon used by the marker
  \tgetIcon: function () {
  \t\treturn this.options.icon;
  \t},

  \t// @method setIcon(icon: Icon): this
  \t// Changes the marker icon.
  \tsetIcon: function (icon) {

  \t\tthis.options.icon = icon;

  \t\tif (this._map) {
  \t\t\tthis._initIcon();
  \t\t\tthis.update();
  \t\t}

  \t\tif (this._popup) {
  \t\t\tthis.bindPopup(this._popup, this._popup.options);
  \t\t}

  \t\treturn this;
  \t},

  \tgetElement: function () {
  \t\treturn this._icon;
  \t},

  \tupdate: function () {

  \t\tif (this._icon && this._map) {
  \t\t\tvar pos = this._map.latLngToLayerPoint(this._latlng).round();
  \t\t\tthis._setPos(pos);
  \t\t}

  \t\treturn this;
  \t},

  \t_initIcon: function () {
  \t\tvar options = this.options,
  \t\t    classToAdd = 'leaflet-zoom-' + (this._zoomAnimated ? 'animated' : 'hide');

  \t\tvar icon = options.icon.createIcon(this._icon),
  \t\t    addIcon = false;

  \t\t// if we're not reusing the icon, remove the old one and init new one
  \t\tif (icon !== this._icon) {
  \t\t\tif (this._icon) {
  \t\t\t\tthis._removeIcon();
  \t\t\t}
  \t\t\taddIcon = true;

  \t\t\tif (options.title) {
  \t\t\t\ticon.title = options.title;
  \t\t\t}

  \t\t\tif (icon.tagName === 'IMG') {
  \t\t\t\ticon.alt = options.alt || '';
  \t\t\t}
  \t\t}

  \t\taddClass(icon, classToAdd);

  \t\tif (options.keyboard) {
  \t\t\ticon.tabIndex = '0';
  \t\t\ticon.setAttribute('role', 'button');
  \t\t}

  \t\tthis._icon = icon;

  \t\tif (options.riseOnHover) {
  \t\t\tthis.on({
  \t\t\t\tmouseover: this._bringToFront,
  \t\t\t\tmouseout: this._resetZIndex
  \t\t\t});
  \t\t}

  \t\tif (this.options.autoPanOnFocus) {
  \t\t\ton(icon, 'focus', this._panOnFocus, this);
  \t\t}

  \t\tvar newShadow = options.icon.createShadow(this._shadow),
  \t\t    addShadow = false;

  \t\tif (newShadow !== this._shadow) {
  \t\t\tthis._removeShadow();
  \t\t\taddShadow = true;
  \t\t}

  \t\tif (newShadow) {
  \t\t\taddClass(newShadow, classToAdd);
  \t\t\tnewShadow.alt = '';
  \t\t}
  \t\tthis._shadow = newShadow;


  \t\tif (options.opacity < 1) {
  \t\t\tthis._updateOpacity();
  \t\t}


  \t\tif (addIcon) {
  \t\t\tthis.getPane().appendChild(this._icon);
  \t\t}
  \t\tthis._initInteraction();
  \t\tif (newShadow && addShadow) {
  \t\t\tthis.getPane(options.shadowPane).appendChild(this._shadow);
  \t\t}
  \t},

  \t_removeIcon: function () {
  \t\tif (this.options.riseOnHover) {
  \t\t\tthis.off({
  \t\t\t\tmouseover: this._bringToFront,
  \t\t\t\tmouseout: this._resetZIndex
  \t\t\t});
  \t\t}

  \t\tif (this.options.autoPanOnFocus) {
  \t\t\toff(this._icon, 'focus', this._panOnFocus, this);
  \t\t}

  \t\tremove(this._icon);
  \t\tthis.removeInteractiveTarget(this._icon);

  \t\tthis._icon = null;
  \t},

  \t_removeShadow: function () {
  \t\tif (this._shadow) {
  \t\t\tremove(this._shadow);
  \t\t}
  \t\tthis._shadow = null;
  \t},

  \t_setPos: function (pos) {

  \t\tif (this._icon) {
  \t\t\tsetPosition(this._icon, pos);
  \t\t}

  \t\tif (this._shadow) {
  \t\t\tsetPosition(this._shadow, pos);
  \t\t}

  \t\tthis._zIndex = pos.y + this.options.zIndexOffset;

  \t\tthis._resetZIndex();
  \t},

  \t_updateZIndex: function (offset) {
  \t\tif (this._icon) {
  \t\t\tthis._icon.style.zIndex = this._zIndex + offset;
  \t\t}
  \t},

  \t_animateZoom: function (opt) {
  \t\tvar pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round();

  \t\tthis._setPos(pos);
  \t},

  \t_initInteraction: function () {

  \t\tif (!this.options.interactive) { return; }

  \t\taddClass(this._icon, 'leaflet-interactive');

  \t\tthis.addInteractiveTarget(this._icon);

  \t\tif (MarkerDrag) {
  \t\t\tvar draggable = this.options.draggable;
  \t\t\tif (this.dragging) {
  \t\t\t\tdraggable = this.dragging.enabled();
  \t\t\t\tthis.dragging.disable();
  \t\t\t}

  \t\t\tthis.dragging = new MarkerDrag(this);

  \t\t\tif (draggable) {
  \t\t\t\tthis.dragging.enable();
  \t\t\t}
  \t\t}
  \t},

  \t// @method setOpacity(opacity: Number): this
  \t// Changes the opacity of the marker.
  \tsetOpacity: function (opacity) {
  \t\tthis.options.opacity = opacity;
  \t\tif (this._map) {
  \t\t\tthis._updateOpacity();
  \t\t}

  \t\treturn this;
  \t},

  \t_updateOpacity: function () {
  \t\tvar opacity = this.options.opacity;

  \t\tif (this._icon) {
  \t\t\tsetOpacity(this._icon, opacity);
  \t\t}

  \t\tif (this._shadow) {
  \t\t\tsetOpacity(this._shadow, opacity);
  \t\t}
  \t},

  \t_bringToFront: function () {
  \t\tthis._updateZIndex(this.options.riseOffset);
  \t},

  \t_resetZIndex: function () {
  \t\tthis._updateZIndex(0);
  \t},

  \t_panOnFocus: function () {
  \t\tvar map = this._map;
  \t\tif (!map) { return; }

  \t\tvar iconOpts = this.options.icon.options;
  \t\tvar size = iconOpts.iconSize ? toPoint(iconOpts.iconSize) : toPoint(0, 0);
  \t\tvar anchor = iconOpts.iconAnchor ? toPoint(iconOpts.iconAnchor) : toPoint(0, 0);

  \t\tmap.panInside(this._latlng, {
  \t\t\tpaddingTopLeft: anchor,
  \t\t\tpaddingBottomRight: size.subtract(anchor)
  \t\t});
  \t},

  \t_getPopupAnchor: function () {
  \t\treturn this.options.icon.options.popupAnchor;
  \t},

  \t_getTooltipAnchor: function () {
  \t\treturn this.options.icon.options.tooltipAnchor;
  \t}
  });


  // factory L.marker(latlng: LatLng, options? : Marker options)

  // @factory L.marker(latlng: LatLng, options? : Marker options)
  // Instantiates a Marker object given a geographical point and optionally an options object.
  function marker(latlng, options) {
  \treturn new Marker(latlng, options);
  }

  /*
   * @class Path
   * @aka L.Path
   * @inherits Interactive layer
   *
   * An abstract class that contains options and constants shared between vector
   * overlays (Polygon, Polyline, Circle). Do not use it directly. Extends `Layer`.
   */

  var Path = Layer.extend({

  \t// @section
  \t// @aka Path options
  \toptions: {
  \t\t// @option stroke: Boolean = true
  \t\t// Whether to draw stroke along the path. Set it to `false` to disable borders on polygons or circles.
  \t\tstroke: true,

  \t\t// @option color: String = '#3388ff'
  \t\t// Stroke color
  \t\tcolor: '#3388ff',

  \t\t// @option weight: Number = 3
  \t\t// Stroke width in pixels
  \t\tweight: 3,

  \t\t// @option opacity: Number = 1.0
  \t\t// Stroke opacity
  \t\topacity: 1,

  \t\t// @option lineCap: String= 'round'
  \t\t// A string that defines [shape to be used at the end](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linecap) of the stroke.
  \t\tlineCap: 'round',

  \t\t// @option lineJoin: String = 'round'
  \t\t// A string that defines [shape to be used at the corners](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linejoin) of the stroke.
  \t\tlineJoin: 'round',

  \t\t// @option dashArray: String = null
  \t\t// A string that defines the stroke [dash pattern](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dasharray). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility).
  \t\tdashArray: null,

  \t\t// @option dashOffset: String = null
  \t\t// A string that defines the [distance into the dash pattern to start the dash](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dashoffset). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility).
  \t\tdashOffset: null,

  \t\t// @option fill: Boolean = depends
  \t\t// Whether to fill the path with color. Set it to `false` to disable filling on polygons or circles.
  \t\tfill: false,

  \t\t// @option fillColor: String = *
  \t\t// Fill color. Defaults to the value of the [`color`](#path-color) option
  \t\tfillColor: null,

  \t\t// @option fillOpacity: Number = 0.2
  \t\t// Fill opacity.
  \t\tfillOpacity: 0.2,

  \t\t// @option fillRule: String = 'evenodd'
  \t\t// A string that defines [how the inside of a shape](https://developer.mozilla.org/docs/Web/SVG/Attribute/fill-rule) is determined.
  \t\tfillRule: 'evenodd',

  \t\t// className: '',

  \t\t// Option inherited from \"Interactive layer\" abstract class
  \t\tinteractive: true,

  \t\t// @option bubblingMouseEvents: Boolean = true
  \t\t// When `true`, a mouse event on this path will trigger the same event on the map
  \t\t// (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used).
  \t\tbubblingMouseEvents: true
  \t},

  \tbeforeAdd: function (map) {
  \t\t// Renderer is set here because we need to call renderer.getEvents
  \t\t// before this.getEvents.
  \t\tthis._renderer = map.getRenderer(this);
  \t},

  \tonAdd: function () {
  \t\tthis._renderer._initPath(this);
  \t\tthis._reset();
  \t\tthis._renderer._addPath(this);
  \t},

  \tonRemove: function () {
  \t\tthis._renderer._removePath(this);
  \t},

  \t// @method redraw(): this
  \t// Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.
  \tredraw: function () {
  \t\tif (this._map) {
  \t\t\tthis._renderer._updatePath(this);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method setStyle(style: Path options): this
  \t// Changes the appearance of a Path based on the options in the `Path options` object.
  \tsetStyle: function (style) {
  \t\tsetOptions(this, style);
  \t\tif (this._renderer) {
  \t\t\tthis._renderer._updateStyle(this);
  \t\t\tif (this.options.stroke && style && Object.prototype.hasOwnProperty.call(style, 'weight')) {
  \t\t\t\tthis._updateBounds();
  \t\t\t}
  \t\t}
  \t\treturn this;
  \t},

  \t// @method bringToFront(): this
  \t// Brings the layer to the top of all path layers.
  \tbringToFront: function () {
  \t\tif (this._renderer) {
  \t\t\tthis._renderer._bringToFront(this);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method bringToBack(): this
  \t// Brings the layer to the bottom of all path layers.
  \tbringToBack: function () {
  \t\tif (this._renderer) {
  \t\t\tthis._renderer._bringToBack(this);
  \t\t}
  \t\treturn this;
  \t},

  \tgetElement: function () {
  \t\treturn this._path;
  \t},

  \t_reset: function () {
  \t\t// defined in child classes
  \t\tthis._project();
  \t\tthis._update();
  \t},

  \t_clickTolerance: function () {
  \t\t// used when doing hit detection for Canvas layers
  \t\treturn (this.options.stroke ? this.options.weight / 2 : 0) +
  \t\t  (this._renderer.options.tolerance || 0);
  \t}
  });

  /*
   * @class CircleMarker
   * @aka L.CircleMarker
   * @inherits Path
   *
   * A circle of a fixed size with radius specified in pixels. Extends `Path`.
   */

  var CircleMarker = Path.extend({

  \t// @section
  \t// @aka CircleMarker options
  \toptions: {
  \t\tfill: true,

  \t\t// @option radius: Number = 10
  \t\t// Radius of the circle marker, in pixels
  \t\tradius: 10
  \t},

  \tinitialize: function (latlng, options) {
  \t\tsetOptions(this, options);
  \t\tthis._latlng = toLatLng(latlng);
  \t\tthis._radius = this.options.radius;
  \t},

  \t// @method setLatLng(latLng: LatLng): this
  \t// Sets the position of a circle marker to a new location.
  \tsetLatLng: function (latlng) {
  \t\tvar oldLatLng = this._latlng;
  \t\tthis._latlng = toLatLng(latlng);
  \t\tthis.redraw();

  \t\t// @event move: Event
  \t\t// Fired when the marker is moved via [`setLatLng`](#circlemarker-setlatlng). Old and new coordinates are included in event arguments as `oldLatLng`, `latlng`.
  \t\treturn this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng});
  \t},

  \t// @method getLatLng(): LatLng
  \t// Returns the current geographical position of the circle marker
  \tgetLatLng: function () {
  \t\treturn this._latlng;
  \t},

  \t// @method setRadius(radius: Number): this
  \t// Sets the radius of a circle marker. Units are in pixels.
  \tsetRadius: function (radius) {
  \t\tthis.options.radius = this._radius = radius;
  \t\treturn this.redraw();
  \t},

  \t// @method getRadius(): Number
  \t// Returns the current radius of the circle
  \tgetRadius: function () {
  \t\treturn this._radius;
  \t},

  \tsetStyle : function (options) {
  \t\tvar radius = options && options.radius || this._radius;
  \t\tPath.prototype.setStyle.call(this, options);
  \t\tthis.setRadius(radius);
  \t\treturn this;
  \t},

  \t_project: function () {
  \t\tthis._point = this._map.latLngToLayerPoint(this._latlng);
  \t\tthis._updateBounds();
  \t},

  \t_updateBounds: function () {
  \t\tvar r = this._radius,
  \t\t    r2 = this._radiusY || r,
  \t\t    w = this._clickTolerance(),
  \t\t    p = [r + w, r2 + w];
  \t\tthis._pxBounds = new Bounds(this._point.subtract(p), this._point.add(p));
  \t},

  \t_update: function () {
  \t\tif (this._map) {
  \t\t\tthis._updatePath();
  \t\t}
  \t},

  \t_updatePath: function () {
  \t\tthis._renderer._updateCircle(this);
  \t},

  \t_empty: function () {
  \t\treturn this._radius && !this._renderer._bounds.intersects(this._pxBounds);
  \t},

  \t// Needed by the `Canvas` renderer for interactivity
  \t_containsPoint: function (p) {
  \t\treturn p.distanceTo(this._point) <= this._radius + this._clickTolerance();
  \t}
  });


  // @factory L.circleMarker(latlng: LatLng, options?: CircleMarker options)
  // Instantiates a circle marker object given a geographical point, and an optional options object.
  function circleMarker(latlng, options) {
  \treturn new CircleMarker(latlng, options);
  }

  /*
   * @class Circle
   * @aka L.Circle
   * @inherits CircleMarker
   *
   * A class for drawing circle overlays on a map. Extends `CircleMarker`.
   *
   * It's an approximation and starts to diverge from a real circle closer to poles (due to projection distortion).
   *
   * @example
   *
   * ```js
   * L.circle([50.5, 30.5], {radius: 200}).addTo(map);
   * ```
   */

  var Circle = CircleMarker.extend({

  \tinitialize: function (latlng, options, legacyOptions) {
  \t\tif (typeof options === 'number') {
  \t\t\t// Backwards compatibility with 0.7.x factory (latlng, radius, options?)
  \t\t\toptions = extend({}, legacyOptions, {radius: options});
  \t\t}
  \t\tsetOptions(this, options);
  \t\tthis._latlng = toLatLng(latlng);

  \t\tif (isNaN(this.options.radius)) { throw new Error('Circle radius cannot be NaN'); }

  \t\t// @section
  \t\t// @aka Circle options
  \t\t// @option radius: Number; Radius of the circle, in meters.
  \t\tthis._mRadius = this.options.radius;
  \t},

  \t// @method setRadius(radius: Number): this
  \t// Sets the radius of a circle. Units are in meters.
  \tsetRadius: function (radius) {
  \t\tthis._mRadius = radius;
  \t\treturn this.redraw();
  \t},

  \t// @method getRadius(): Number
  \t// Returns the current radius of a circle. Units are in meters.
  \tgetRadius: function () {
  \t\treturn this._mRadius;
  \t},

  \t// @method getBounds(): LatLngBounds
  \t// Returns the `LatLngBounds` of the path.
  \tgetBounds: function () {
  \t\tvar half = [this._radius, this._radiusY || this._radius];

  \t\treturn new LatLngBounds(
  \t\t\tthis._map.layerPointToLatLng(this._point.subtract(half)),
  \t\t\tthis._map.layerPointToLatLng(this._point.add(half)));
  \t},

  \tsetStyle: Path.prototype.setStyle,

  \t_project: function () {

  \t\tvar lng = this._latlng.lng,
  \t\t    lat = this._latlng.lat,
  \t\t    map = this._map,
  \t\t    crs = map.options.crs;

  \t\tif (crs.distance === Earth.distance) {
  \t\t\tvar d = Math.PI / 180,
  \t\t\t    latR = (this._mRadius / Earth.R) / d,
  \t\t\t    top = map.project([lat + latR, lng]),
  \t\t\t    bottom = map.project([lat - latR, lng]),
  \t\t\t    p = top.add(bottom).divideBy(2),
  \t\t\t    lat2 = map.unproject(p).lat,
  \t\t\t    lngR = Math.acos((Math.cos(latR * d) - Math.sin(lat * d) * Math.sin(lat2 * d)) /
  \t\t\t            (Math.cos(lat * d) * Math.cos(lat2 * d))) / d;

  \t\t\tif (isNaN(lngR) || lngR === 0) {
  \t\t\t\tlngR = latR / Math.cos(Math.PI / 180 * lat); // Fallback for edge case, #2425
  \t\t\t}

  \t\t\tthis._point = p.subtract(map.getPixelOrigin());
  \t\t\tthis._radius = isNaN(lngR) ? 0 : p.x - map.project([lat2, lng - lngR]).x;
  \t\t\tthis._radiusY = p.y - top.y;

  \t\t} else {
  \t\t\tvar latlng2 = crs.unproject(crs.project(this._latlng).subtract([this._mRadius, 0]));

  \t\t\tthis._point = map.latLngToLayerPoint(this._latlng);
  \t\t\tthis._radius = this._point.x - map.latLngToLayerPoint(latlng2).x;
  \t\t}

  \t\tthis._updateBounds();
  \t}
  });

  // @factory L.circle(latlng: LatLng, options?: Circle options)
  // Instantiates a circle object given a geographical point, and an options object
  // which contains the circle radius.
  // @alternative
  // @factory L.circle(latlng: LatLng, radius: Number, options?: Circle options)
  // Obsolete way of instantiating a circle, for compatibility with 0.7.x code.
  // Do not use in new applications or plugins.
  function circle(latlng, options, legacyOptions) {
  \treturn new Circle(latlng, options, legacyOptions);
  }

  /*
   * @class Polyline
   * @aka L.Polyline
   * @inherits Path
   *
   * A class for drawing polyline overlays on a map. Extends `Path`.
   *
   * @example
   *
   * ```js
   * // create a red polyline from an array of LatLng points
   * var latlngs = [
   * \t[45.51, -122.68],
   * \t[37.77, -122.43],
   * \t[34.04, -118.2]
   * ];
   *
   * var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map);
   *
   * // zoom the map to the polyline
   * map.fitBounds(polyline.getBounds());
   * ```
   *
   * You can also pass a multi-dimensional array to represent a `MultiPolyline` shape:
   *
   * ```js
   * // create a red polyline from an array of arrays of LatLng points
   * var latlngs = [
   * \t[[45.51, -122.68],
   * \t [37.77, -122.43],
   * \t [34.04, -118.2]],
   * \t[[40.78, -73.91],
   * \t [41.83, -87.62],
   * \t [32.76, -96.72]]
   * ];
   * ```
   */


  var Polyline = Path.extend({

  \t// @section
  \t// @aka Polyline options
  \toptions: {
  \t\t// @option smoothFactor: Number = 1.0
  \t\t// How much to simplify the polyline on each zoom level. More means
  \t\t// better performance and smoother look, and less means more accurate representation.
  \t\tsmoothFactor: 1.0,

  \t\t// @option noClip: Boolean = false
  \t\t// Disable polyline clipping.
  \t\tnoClip: false
  \t},

  \tinitialize: function (latlngs, options) {
  \t\tsetOptions(this, options);
  \t\tthis._setLatLngs(latlngs);
  \t},

  \t// @method getLatLngs(): LatLng[]
  \t// Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.
  \tgetLatLngs: function () {
  \t\treturn this._latlngs;
  \t},

  \t// @method setLatLngs(latlngs: LatLng[]): this
  \t// Replaces all the points in the polyline with the given array of geographical points.
  \tsetLatLngs: function (latlngs) {
  \t\tthis._setLatLngs(latlngs);
  \t\treturn this.redraw();
  \t},

  \t// @method isEmpty(): Boolean
  \t// Returns `true` if the Polyline has no LatLngs.
  \tisEmpty: function () {
  \t\treturn !this._latlngs.length;
  \t},

  \t// @method closestLayerPoint(p: Point): Point
  \t// Returns the point closest to `p` on the Polyline.
  \tclosestLayerPoint: function (p) {
  \t\tvar minDistance = Infinity,
  \t\t    minPoint = null,
  \t\t    closest = _sqClosestPointOnSegment,
  \t\t    p1, p2;

  \t\tfor (var j = 0, jLen = this._parts.length; j < jLen; j++) {
  \t\t\tvar points = this._parts[j];

  \t\t\tfor (var i = 1, len = points.length; i < len; i++) {
  \t\t\t\tp1 = points[i - 1];
  \t\t\t\tp2 = points[i];

  \t\t\t\tvar sqDist = closest(p, p1, p2, true);

  \t\t\t\tif (sqDist < minDistance) {
  \t\t\t\t\tminDistance = sqDist;
  \t\t\t\t\tminPoint = closest(p, p1, p2);
  \t\t\t\t}
  \t\t\t}
  \t\t}
  \t\tif (minPoint) {
  \t\t\tminPoint.distance = Math.sqrt(minDistance);
  \t\t}
  \t\treturn minPoint;
  \t},

  \t// @method getCenter(): LatLng
  \t// Returns the center ([centroid](https://en.wikipedia.org/wiki/Centroid)) of the polyline.
  \tgetCenter: function () {
  \t\t// throws error when not yet added to map as this center calculation requires projected coordinates
  \t\tif (!this._map) {
  \t\t\tthrow new Error('Must add layer to map before using getCenter()');
  \t\t}
  \t\treturn polylineCenter(this._defaultShape(), this._map.options.crs);
  \t},

  \t// @method getBounds(): LatLngBounds
  \t// Returns the `LatLngBounds` of the path.
  \tgetBounds: function () {
  \t\treturn this._bounds;
  \t},

  \t// @method addLatLng(latlng: LatLng, latlngs?: LatLng[]): this
  \t// Adds a given point to the polyline. By default, adds to the first ring of
  \t// the polyline in case of a multi-polyline, but can be overridden by passing
  \t// a specific ring as a LatLng array (that you can earlier access with [`getLatLngs`](#polyline-getlatlngs)).
  \taddLatLng: function (latlng, latlngs) {
  \t\tlatlngs = latlngs || this._defaultShape();
  \t\tlatlng = toLatLng(latlng);
  \t\tlatlngs.push(latlng);
  \t\tthis._bounds.extend(latlng);
  \t\treturn this.redraw();
  \t},

  \t_setLatLngs: function (latlngs) {
  \t\tthis._bounds = new LatLngBounds();
  \t\tthis._latlngs = this._convertLatLngs(latlngs);
  \t},

  \t_defaultShape: function () {
  \t\treturn isFlat(this._latlngs) ? this._latlngs : this._latlngs[0];
  \t},

  \t// recursively convert latlngs input into actual LatLng instances; calculate bounds along the way
  \t_convertLatLngs: function (latlngs) {
  \t\tvar result = [],
  \t\t    flat = isFlat(latlngs);

  \t\tfor (var i = 0, len = latlngs.length; i < len; i++) {
  \t\t\tif (flat) {
  \t\t\t\tresult[i] = toLatLng(latlngs[i]);
  \t\t\t\tthis._bounds.extend(result[i]);
  \t\t\t} else {
  \t\t\t\tresult[i] = this._convertLatLngs(latlngs[i]);
  \t\t\t}
  \t\t}

  \t\treturn result;
  \t},

  \t_project: function () {
  \t\tvar pxBounds = new Bounds();
  \t\tthis._rings = [];
  \t\tthis._projectLatlngs(this._latlngs, this._rings, pxBounds);

  \t\tif (this._bounds.isValid() && pxBounds.isValid()) {
  \t\t\tthis._rawPxBounds = pxBounds;
  \t\t\tthis._updateBounds();
  \t\t}
  \t},

  \t_updateBounds: function () {
  \t\tvar w = this._clickTolerance(),
  \t\t    p = new Point(w, w);

  \t\tif (!this._rawPxBounds) {
  \t\t\treturn;
  \t\t}

  \t\tthis._pxBounds = new Bounds([
  \t\t\tthis._rawPxBounds.min.subtract(p),
  \t\t\tthis._rawPxBounds.max.add(p)
  \t\t]);
  \t},

  \t// recursively turns latlngs into a set of rings with projected coordinates
  \t_projectLatlngs: function (latlngs, result, projectedBounds) {
  \t\tvar flat = latlngs[0] instanceof LatLng,
  \t\t    len = latlngs.length,
  \t\t    i, ring;

  \t\tif (flat) {
  \t\t\tring = [];
  \t\t\tfor (i = 0; i < len; i++) {
  \t\t\t\tring[i] = this._map.latLngToLayerPoint(latlngs[i]);
  \t\t\t\tprojectedBounds.extend(ring[i]);
  \t\t\t}
  \t\t\tresult.push(ring);
  \t\t} else {
  \t\t\tfor (i = 0; i < len; i++) {
  \t\t\t\tthis._projectLatlngs(latlngs[i], result, projectedBounds);
  \t\t\t}
  \t\t}
  \t},

  \t// clip polyline by renderer bounds so that we have less to render for performance
  \t_clipPoints: function () {
  \t\tvar bounds = this._renderer._bounds;

  \t\tthis._parts = [];
  \t\tif (!this._pxBounds || !this._pxBounds.intersects(bounds)) {
  \t\t\treturn;
  \t\t}

  \t\tif (this.options.noClip) {
  \t\t\tthis._parts = this._rings;
  \t\t\treturn;
  \t\t}

  \t\tvar parts = this._parts,
  \t\t    i, j, k, len, len2, segment, points;

  \t\tfor (i = 0, k = 0, len = this._rings.length; i < len; i++) {
  \t\t\tpoints = this._rings[i];

  \t\t\tfor (j = 0, len2 = points.length; j < len2 - 1; j++) {
  \t\t\t\tsegment = clipSegment(points[j], points[j + 1], bounds, j, true);

  \t\t\t\tif (!segment) { continue; }

  \t\t\t\tparts[k] = parts[k] || [];
  \t\t\t\tparts[k].push(segment[0]);

  \t\t\t\t// if segment goes out of screen, or it's the last one, it's the end of the line part
  \t\t\t\tif ((segment[1] !== points[j + 1]) || (j === len2 - 2)) {
  \t\t\t\t\tparts[k].push(segment[1]);
  \t\t\t\t\tk++;
  \t\t\t\t}
  \t\t\t}
  \t\t}
  \t},

  \t// simplify each clipped part of the polyline for performance
  \t_simplifyPoints: function () {
  \t\tvar parts = this._parts,
  \t\t    tolerance = this.options.smoothFactor;

  \t\tfor (var i = 0, len = parts.length; i < len; i++) {
  \t\t\tparts[i] = simplify(parts[i], tolerance);
  \t\t}
  \t},

  \t_update: function () {
  \t\tif (!this._map) { return; }

  \t\tthis._clipPoints();
  \t\tthis._simplifyPoints();
  \t\tthis._updatePath();
  \t},

  \t_updatePath: function () {
  \t\tthis._renderer._updatePoly(this);
  \t},

  \t// Needed by the `Canvas` renderer for interactivity
  \t_containsPoint: function (p, closed) {
  \t\tvar i, j, k, len, len2, part,
  \t\t    w = this._clickTolerance();

  \t\tif (!this._pxBounds || !this._pxBounds.contains(p)) { return false; }

  \t\t// hit detection for polylines
  \t\tfor (i = 0, len = this._parts.length; i < len; i++) {
  \t\t\tpart = this._parts[i];

  \t\t\tfor (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {
  \t\t\t\tif (!closed && (j === 0)) { continue; }

  \t\t\t\tif (pointToSegmentDistance(p, part[k], part[j]) <= w) {
  \t\t\t\t\treturn true;
  \t\t\t\t}
  \t\t\t}
  \t\t}
  \t\treturn false;
  \t}
  });

  // @factory L.polyline(latlngs: LatLng[], options?: Polyline options)
  // Instantiates a polyline object given an array of geographical points and
  // optionally an options object. You can create a `Polyline` object with
  // multiple separate lines (`MultiPolyline`) by passing an array of arrays
  // of geographic points.
  function polyline(latlngs, options) {
  \treturn new Polyline(latlngs, options);
  }

  // Retrocompat. Allow plugins to support Leaflet versions before and after 1.1.
  Polyline._flat = _flat;

  /*
   * @class Polygon
   * @aka L.Polygon
   * @inherits Polyline
   *
   * A class for drawing polygon overlays on a map. Extends `Polyline`.
   *
   * Note that points you pass when creating a polygon shouldn't have an additional last point equal to the first one — it's better to filter out such points.
   *
   *
   * @example
   *
   * ```js
   * // create a red polygon from an array of LatLng points
   * var latlngs = [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]];
   *
   * var polygon = L.polygon(latlngs, {color: 'red'}).addTo(map);
   *
   * // zoom the map to the polygon
   * map.fitBounds(polygon.getBounds());
   * ```
   *
   * You can also pass an array of arrays of latlngs, with the first array representing the outer shape and the other arrays representing holes in the outer shape:
   *
   * ```js
   * var latlngs = [
   *   [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring
   *   [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole
   * ];
   * ```
   *
   * Additionally, you can pass a multi-dimensional array to represent a MultiPolygon shape.
   *
   * ```js
   * var latlngs = [
   *   [ // first polygon
   *     [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring
   *     [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole
   *   ],
   *   [ // second polygon
   *     [[41, -111.03],[45, -111.04],[45, -104.05],[41, -104.05]]
   *   ]
   * ];
   * ```
   */

  var Polygon = Polyline.extend({

  \toptions: {
  \t\tfill: true
  \t},

  \tisEmpty: function () {
  \t\treturn !this._latlngs.length || !this._latlngs[0].length;
  \t},

  \t// @method getCenter(): LatLng
  \t// Returns the center ([centroid](http://en.wikipedia.org/wiki/Centroid)) of the Polygon.
  \tgetCenter: function () {
  \t\t// throws error when not yet added to map as this center calculation requires projected coordinates
  \t\tif (!this._map) {
  \t\t\tthrow new Error('Must add layer to map before using getCenter()');
  \t\t}
  \t\treturn polygonCenter(this._defaultShape(), this._map.options.crs);
  \t},

  \t_convertLatLngs: function (latlngs) {
  \t\tvar result = Polyline.prototype._convertLatLngs.call(this, latlngs),
  \t\t    len = result.length;

  \t\t// remove last point if it equals first one
  \t\tif (len >= 2 && result[0] instanceof LatLng && result[0].equals(result[len - 1])) {
  \t\t\tresult.pop();
  \t\t}
  \t\treturn result;
  \t},

  \t_setLatLngs: function (latlngs) {
  \t\tPolyline.prototype._setLatLngs.call(this, latlngs);
  \t\tif (isFlat(this._latlngs)) {
  \t\t\tthis._latlngs = [this._latlngs];
  \t\t}
  \t},

  \t_defaultShape: function () {
  \t\treturn isFlat(this._latlngs[0]) ? this._latlngs[0] : this._latlngs[0][0];
  \t},

  \t_clipPoints: function () {
  \t\t// polygons need a different clipping algorithm so we redefine that

  \t\tvar bounds = this._renderer._bounds,
  \t\t    w = this.options.weight,
  \t\t    p = new Point(w, w);

  \t\t// increase clip padding by stroke width to avoid stroke on clip edges
  \t\tbounds = new Bounds(bounds.min.subtract(p), bounds.max.add(p));

  \t\tthis._parts = [];
  \t\tif (!this._pxBounds || !this._pxBounds.intersects(bounds)) {
  \t\t\treturn;
  \t\t}

  \t\tif (this.options.noClip) {
  \t\t\tthis._parts = this._rings;
  \t\t\treturn;
  \t\t}

  \t\tfor (var i = 0, len = this._rings.length, clipped; i < len; i++) {
  \t\t\tclipped = clipPolygon(this._rings[i], bounds, true);
  \t\t\tif (clipped.length) {
  \t\t\t\tthis._parts.push(clipped);
  \t\t\t}
  \t\t}
  \t},

  \t_updatePath: function () {
  \t\tthis._renderer._updatePoly(this, true);
  \t},

  \t// Needed by the `Canvas` renderer for interactivity
  \t_containsPoint: function (p) {
  \t\tvar inside = false,
  \t\t    part, p1, p2, i, j, k, len, len2;

  \t\tif (!this._pxBounds || !this._pxBounds.contains(p)) { return false; }

  \t\t// ray casting algorithm for detecting if point is in polygon
  \t\tfor (i = 0, len = this._parts.length; i < len; i++) {
  \t\t\tpart = this._parts[i];

  \t\t\tfor (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {
  \t\t\t\tp1 = part[j];
  \t\t\t\tp2 = part[k];

  \t\t\t\tif (((p1.y > p.y) !== (p2.y > p.y)) && (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x)) {
  \t\t\t\t\tinside = !inside;
  \t\t\t\t}
  \t\t\t}
  \t\t}

  \t\t// also check if it's on polygon stroke
  \t\treturn inside || Polyline.prototype._containsPoint.call(this, p, true);
  \t}

  });


  // @factory L.polygon(latlngs: LatLng[], options?: Polyline options)
  function polygon(latlngs, options) {
  \treturn new Polygon(latlngs, options);
  }

  /*
   * @class GeoJSON
   * @aka L.GeoJSON
   * @inherits FeatureGroup
   *
   * Represents a GeoJSON object or an array of GeoJSON objects. Allows you to parse
   * GeoJSON data and display it on the map. Extends `FeatureGroup`.
   *
   * @example
   *
   * ```js
   * L.geoJSON(data, {
   * \tstyle: function (feature) {
   * \t\treturn {color: feature.properties.color};
   * \t}
   * }).bindPopup(function (layer) {
   * \treturn layer.feature.properties.description;
   * }).addTo(map);
   * ```
   */

  var GeoJSON = FeatureGroup.extend({

  \t/* @section
  \t * @aka GeoJSON options
  \t *
  \t * @option pointToLayer: Function = *
  \t * A `Function` defining how GeoJSON points spawn Leaflet layers. It is internally
  \t * called when data is added, passing the GeoJSON point feature and its `LatLng`.
  \t * The default is to spawn a default `Marker`:
  \t * ```js
  \t * function(geoJsonPoint, latlng) {
  \t * \treturn L.marker(latlng);
  \t * }
  \t * ```
  \t *
  \t * @option style: Function = *
  \t * A `Function` defining the `Path options` for styling GeoJSON lines and polygons,
  \t * called internally when data is added.
  \t * The default value is to not override any defaults:
  \t * ```js
  \t * function (geoJsonFeature) {
  \t * \treturn {}
  \t * }
  \t * ```
  \t *
  \t * @option onEachFeature: Function = *
  \t * A `Function` that will be called once for each created `Feature`, after it has
  \t * been created and styled. Useful for attaching events and popups to features.
  \t * The default is to do nothing with the newly created layers:
  \t * ```js
  \t * function (feature, layer) {}
  \t * ```
  \t *
  \t * @option filter: Function = *
  \t * A `Function` that will be used to decide whether to include a feature or not.
  \t * The default is to include all features:
  \t * ```js
  \t * function (geoJsonFeature) {
  \t * \treturn true;
  \t * }
  \t * ```
  \t * Note: dynamically changing the `filter` option will have effect only on newly
  \t * added data. It will _not_ re-evaluate already included features.
  \t *
  \t * @option coordsToLatLng: Function = *
  \t * A `Function` that will be used for converting GeoJSON coordinates to `LatLng`s.
  \t * The default is the `coordsToLatLng` static method.
  \t *
  \t * @option markersInheritOptions: Boolean = false
  \t * Whether default Markers for \"Point\" type Features inherit from group options.
  \t */

  \tinitialize: function (geojson, options) {
  \t\tsetOptions(this, options);

  \t\tthis._layers = {};

  \t\tif (geojson) {
  \t\t\tthis.addData(geojson);
  \t\t}
  \t},

  \t// @method addData( <GeoJSON> data ): this
  \t// Adds a GeoJSON object to the layer.
  \taddData: function (geojson) {
  \t\tvar features = isArray(geojson) ? geojson : geojson.features,
  \t\t    i, len, feature;

  \t\tif (features) {
  \t\t\tfor (i = 0, len = features.length; i < len; i++) {
  \t\t\t\t// only add this if geometry or geometries are set and not null
  \t\t\t\tfeature = features[i];
  \t\t\t\tif (feature.geometries || feature.geometry || feature.features || feature.coordinates) {
  \t\t\t\t\tthis.addData(feature);
  \t\t\t\t}
  \t\t\t}
  \t\t\treturn this;
  \t\t}

  \t\tvar options = this.options;

  \t\tif (options.filter && !options.filter(geojson)) { return this; }

  \t\tvar layer = geometryToLayer(geojson, options);
  \t\tif (!layer) {
  \t\t\treturn this;
  \t\t}
  \t\tlayer.feature = asFeature(geojson);

  \t\tlayer.defaultOptions = layer.options;
  \t\tthis.resetStyle(layer);

  \t\tif (options.onEachFeature) {
  \t\t\toptions.onEachFeature(geojson, layer);
  \t\t}

  \t\treturn this.addLayer(layer);
  \t},

  \t// @method resetStyle( <Path> layer? ): this
  \t// Resets the given vector layer's style to the original GeoJSON style, useful for resetting style after hover events.
  \t// If `layer` is omitted, the style of all features in the current layer is reset.
  \tresetStyle: function (layer) {
  \t\tif (layer === undefined) {
  \t\t\treturn this.eachLayer(this.resetStyle, this);
  \t\t}
  \t\t// reset any custom styles
  \t\tlayer.options = extend({}, layer.defaultOptions);
  \t\tthis._setLayerStyle(layer, this.options.style);
  \t\treturn this;
  \t},

  \t// @method setStyle( <Function> style ): this
  \t// Changes styles of GeoJSON vector layers with the given style function.
  \tsetStyle: function (style) {
  \t\treturn this.eachLayer(function (layer) {
  \t\t\tthis._setLayerStyle(layer, style);
  \t\t}, this);
  \t},

  \t_setLayerStyle: function (layer, style) {
  \t\tif (layer.setStyle) {
  \t\t\tif (typeof style === 'function') {
  \t\t\t\tstyle = style(layer.feature);
  \t\t\t}
  \t\t\tlayer.setStyle(style);
  \t\t}
  \t}
  });

  // @section
  // There are several static functions which can be called without instantiating L.GeoJSON:

  // @function geometryToLayer(featureData: Object, options?: GeoJSON options): Layer
  // Creates a `Layer` from a given GeoJSON feature. Can use a custom
  // [`pointToLayer`](#geojson-pointtolayer) and/or [`coordsToLatLng`](#geojson-coordstolatlng)
  // functions if provided as options.
  function geometryToLayer(geojson, options) {

  \tvar geometry = geojson.type === 'Feature' ? geojson.geometry : geojson,
  \t    coords = geometry ? geometry.coordinates : null,
  \t    layers = [],
  \t    pointToLayer = options && options.pointToLayer,
  \t    _coordsToLatLng = options && options.coordsToLatLng || coordsToLatLng,
  \t    latlng, latlngs, i, len;

  \tif (!coords && !geometry) {
  \t\treturn null;
  \t}

  \tswitch (geometry.type) {
  \tcase 'Point':
  \t\tlatlng = _coordsToLatLng(coords);
  \t\treturn _pointToLayer(pointToLayer, geojson, latlng, options);

  \tcase 'MultiPoint':
  \t\tfor (i = 0, len = coords.length; i < len; i++) {
  \t\t\tlatlng = _coordsToLatLng(coords[i]);
  \t\t\tlayers.push(_pointToLayer(pointToLayer, geojson, latlng, options));
  \t\t}
  \t\treturn new FeatureGroup(layers);

  \tcase 'LineString':
  \tcase 'MultiLineString':
  \t\tlatlngs = coordsToLatLngs(coords, geometry.type === 'LineString' ? 0 : 1, _coordsToLatLng);
  \t\treturn new Polyline(latlngs, options);

  \tcase 'Polygon':
  \tcase 'MultiPolygon':
  \t\tlatlngs = coordsToLatLngs(coords, geometry.type === 'Polygon' ? 1 : 2, _coordsToLatLng);
  \t\treturn new Polygon(latlngs, options);

  \tcase 'GeometryCollection':
  \t\tfor (i = 0, len = geometry.geometries.length; i < len; i++) {
  \t\t\tvar geoLayer = geometryToLayer({
  \t\t\t\tgeometry: geometry.geometries[i],
  \t\t\t\ttype: 'Feature',
  \t\t\t\tproperties: geojson.properties
  \t\t\t}, options);

  \t\t\tif (geoLayer) {
  \t\t\t\tlayers.push(geoLayer);
  \t\t\t}
  \t\t}
  \t\treturn new FeatureGroup(layers);

  \tcase 'FeatureCollection':
  \t\tfor (i = 0, len = geometry.features.length; i < len; i++) {
  \t\t\tvar featureLayer = geometryToLayer(geometry.features[i], options);

  \t\t\tif (featureLayer) {
  \t\t\t\tlayers.push(featureLayer);
  \t\t\t}
  \t\t}
  \t\treturn new FeatureGroup(layers);

  \tdefault:
  \t\tthrow new Error('Invalid GeoJSON object.');
  \t}
  }

  function _pointToLayer(pointToLayerFn, geojson, latlng, options) {
  \treturn pointToLayerFn ?
  \t\tpointToLayerFn(geojson, latlng) :
  \t\tnew Marker(latlng, options && options.markersInheritOptions && options);
  }

  // @function coordsToLatLng(coords: Array): LatLng
  // Creates a `LatLng` object from an array of 2 numbers (longitude, latitude)
  // or 3 numbers (longitude, latitude, altitude) used in GeoJSON for points.
  function coordsToLatLng(coords) {
  \treturn new LatLng(coords[1], coords[0], coords[2]);
  }

  // @function coordsToLatLngs(coords: Array, levelsDeep?: Number, coordsToLatLng?: Function): Array
  // Creates a multidimensional array of `LatLng`s from a GeoJSON coordinates array.
  // `levelsDeep` specifies the nesting level (0 is for an array of points, 1 for an array of arrays of points, etc., 0 by default).
  // Can use a custom [`coordsToLatLng`](#geojson-coordstolatlng) function.
  function coordsToLatLngs(coords, levelsDeep, _coordsToLatLng) {
  \tvar latlngs = [];

  \tfor (var i = 0, len = coords.length, latlng; i < len; i++) {
  \t\tlatlng = levelsDeep ?
  \t\t\tcoordsToLatLngs(coords[i], levelsDeep - 1, _coordsToLatLng) :
  \t\t\t(_coordsToLatLng || coordsToLatLng)(coords[i]);

  \t\tlatlngs.push(latlng);
  \t}

  \treturn latlngs;
  }

  // @function latLngToCoords(latlng: LatLng, precision?: Number|false): Array
  // Reverse of [`coordsToLatLng`](#geojson-coordstolatlng)
  // Coordinates values are rounded with [`formatNum`](#util-formatnum) function.
  function latLngToCoords(latlng, precision) {
  \tlatlng = toLatLng(latlng);
  \treturn latlng.alt !== undefined ?
  \t\t[formatNum(latlng.lng, precision), formatNum(latlng.lat, precision), formatNum(latlng.alt, precision)] :
  \t\t[formatNum(latlng.lng, precision), formatNum(latlng.lat, precision)];
  }

  // @function latLngsToCoords(latlngs: Array, levelsDeep?: Number, closed?: Boolean, precision?: Number|false): Array
  // Reverse of [`coordsToLatLngs`](#geojson-coordstolatlngs)
  // `closed` determines whether the first point should be appended to the end of the array to close the feature, only used when `levelsDeep` is 0. False by default.
  // Coordinates values are rounded with [`formatNum`](#util-formatnum) function.
  function latLngsToCoords(latlngs, levelsDeep, closed, precision) {
  \tvar coords = [];

  \tfor (var i = 0, len = latlngs.length; i < len; i++) {
  \t\t// Check for flat arrays required to ensure unbalanced arrays are correctly converted in recursion
  \t\tcoords.push(levelsDeep ?
  \t\t\tlatLngsToCoords(latlngs[i], isFlat(latlngs[i]) ? 0 : levelsDeep - 1, closed, precision) :
  \t\t\tlatLngToCoords(latlngs[i], precision));
  \t}

  \tif (!levelsDeep && closed && coords.length > 0) {
  \t\tcoords.push(coords[0].slice());
  \t}

  \treturn coords;
  }

  function getFeature(layer, newGeometry) {
  \treturn layer.feature ?
  \t\textend({}, layer.feature, {geometry: newGeometry}) :
  \t\tasFeature(newGeometry);
  }

  // @function asFeature(geojson: Object): Object
  // Normalize GeoJSON geometries/features into GeoJSON features.
  function asFeature(geojson) {
  \tif (geojson.type === 'Feature' || geojson.type === 'FeatureCollection') {
  \t\treturn geojson;
  \t}

  \treturn {
  \t\ttype: 'Feature',
  \t\tproperties: {},
  \t\tgeometry: geojson
  \t};
  }

  var PointToGeoJSON = {
  \ttoGeoJSON: function (precision) {
  \t\treturn getFeature(this, {
  \t\t\ttype: 'Point',
  \t\t\tcoordinates: latLngToCoords(this.getLatLng(), precision)
  \t\t});
  \t}
  };

  // @namespace Marker
  // @section Other methods
  // @method toGeoJSON(precision?: Number|false): Object
  // Coordinates values are rounded with [`formatNum`](#util-formatnum) function with given `precision`.
  // Returns a [`GeoJSON`](https://en.wikipedia.org/wiki/GeoJSON) representation of the marker (as a GeoJSON `Point` Feature).
  Marker.include(PointToGeoJSON);

  // @namespace CircleMarker
  // @method toGeoJSON(precision?: Number|false): Object
  // Coordinates values are rounded with [`formatNum`](#util-formatnum) function with given `precision`.
  // Returns a [`GeoJSON`](https://en.wikipedia.org/wiki/GeoJSON) representation of the circle marker (as a GeoJSON `Point` Feature).
  Circle.include(PointToGeoJSON);
  CircleMarker.include(PointToGeoJSON);


  // @namespace Polyline
  // @method toGeoJSON(precision?: Number|false): Object
  // Coordinates values are rounded with [`formatNum`](#util-formatnum) function with given `precision`.
  // Returns a [`GeoJSON`](https://en.wikipedia.org/wiki/GeoJSON) representation of the polyline (as a GeoJSON `LineString` or `MultiLineString` Feature).
  Polyline.include({
  \ttoGeoJSON: function (precision) {
  \t\tvar multi = !isFlat(this._latlngs);

  \t\tvar coords = latLngsToCoords(this._latlngs, multi ? 1 : 0, false, precision);

  \t\treturn getFeature(this, {
  \t\t\ttype: (multi ? 'Multi' : '') + 'LineString',
  \t\t\tcoordinates: coords
  \t\t});
  \t}
  });

  // @namespace Polygon
  // @method toGeoJSON(precision?: Number|false): Object
  // Coordinates values are rounded with [`formatNum`](#util-formatnum) function with given `precision`.
  // Returns a [`GeoJSON`](https://en.wikipedia.org/wiki/GeoJSON) representation of the polygon (as a GeoJSON `Polygon` or `MultiPolygon` Feature).
  Polygon.include({
  \ttoGeoJSON: function (precision) {
  \t\tvar holes = !isFlat(this._latlngs),
  \t\t    multi = holes && !isFlat(this._latlngs[0]);

  \t\tvar coords = latLngsToCoords(this._latlngs, multi ? 2 : holes ? 1 : 0, true, precision);

  \t\tif (!holes) {
  \t\t\tcoords = [coords];
  \t\t}

  \t\treturn getFeature(this, {
  \t\t\ttype: (multi ? 'Multi' : '') + 'Polygon',
  \t\t\tcoordinates: coords
  \t\t});
  \t}
  });


  // @namespace LayerGroup
  LayerGroup.include({
  \ttoMultiPoint: function (precision) {
  \t\tvar coords = [];

  \t\tthis.eachLayer(function (layer) {
  \t\t\tcoords.push(layer.toGeoJSON(precision).geometry.coordinates);
  \t\t});

  \t\treturn getFeature(this, {
  \t\t\ttype: 'MultiPoint',
  \t\t\tcoordinates: coords
  \t\t});
  \t},

  \t// @method toGeoJSON(precision?: Number|false): Object
  \t// Coordinates values are rounded with [`formatNum`](#util-formatnum) function with given `precision`.
  \t// Returns a [`GeoJSON`](https://en.wikipedia.org/wiki/GeoJSON) representation of the layer group (as a GeoJSON `FeatureCollection`, `GeometryCollection`, or `MultiPoint`).
  \ttoGeoJSON: function (precision) {

  \t\tvar type = this.feature && this.feature.geometry && this.feature.geometry.type;

  \t\tif (type === 'MultiPoint') {
  \t\t\treturn this.toMultiPoint(precision);
  \t\t}

  \t\tvar isGeometryCollection = type === 'GeometryCollection',
  \t\t    jsons = [];

  \t\tthis.eachLayer(function (layer) {
  \t\t\tif (layer.toGeoJSON) {
  \t\t\t\tvar json = layer.toGeoJSON(precision);
  \t\t\t\tif (isGeometryCollection) {
  \t\t\t\t\tjsons.push(json.geometry);
  \t\t\t\t} else {
  \t\t\t\t\tvar feature = asFeature(json);
  \t\t\t\t\t// Squash nested feature collections
  \t\t\t\t\tif (feature.type === 'FeatureCollection') {
  \t\t\t\t\t\tjsons.push.apply(jsons, feature.features);
  \t\t\t\t\t} else {
  \t\t\t\t\t\tjsons.push(feature);
  \t\t\t\t\t}
  \t\t\t\t}
  \t\t\t}
  \t\t});

  \t\tif (isGeometryCollection) {
  \t\t\treturn getFeature(this, {
  \t\t\t\tgeometries: jsons,
  \t\t\t\ttype: 'GeometryCollection'
  \t\t\t});
  \t\t}

  \t\treturn {
  \t\t\ttype: 'FeatureCollection',
  \t\t\tfeatures: jsons
  \t\t};
  \t}
  });

  // @namespace GeoJSON
  // @factory L.geoJSON(geojson?: Object, options?: GeoJSON options)
  // Creates a GeoJSON layer. Optionally accepts an object in
  // [GeoJSON format](https://tools.ietf.org/html/rfc7946) to display on the map
  // (you can alternatively add it later with `addData` method) and an `options` object.
  function geoJSON(geojson, options) {
  \treturn new GeoJSON(geojson, options);
  }

  // Backward compatibility.
  var geoJson = geoJSON;

  /*
   * @class ImageOverlay
   * @aka L.ImageOverlay
   * @inherits Interactive layer
   *
   * Used to load and display a single image over specific bounds of the map. Extends `Layer`.
   *
   * @example
   *
   * ```js
   * var imageUrl = 'https://maps.lib.utexas.edu/maps/historical/newark_nj_1922.jpg',
   * \timageBounds = [[40.712216, -74.22655], [40.773941, -74.12544]];
   * L.imageOverlay(imageUrl, imageBounds).addTo(map);
   * ```
   */

  var ImageOverlay = Layer.extend({

  \t// @section
  \t// @aka ImageOverlay options
  \toptions: {
  \t\t// @option opacity: Number = 1.0
  \t\t// The opacity of the image overlay.
  \t\topacity: 1,

  \t\t// @option alt: String = ''
  \t\t// Text for the `alt` attribute of the image (useful for accessibility).
  \t\talt: '',

  \t\t// @option interactive: Boolean = false
  \t\t// If `true`, the image overlay will emit [mouse events](#interactive-layer) when clicked or hovered.
  \t\tinteractive: false,

  \t\t// @option crossOrigin: Boolean|String = false
  \t\t// Whether the crossOrigin attribute will be added to the image.
  \t\t// If a String is provided, the image will have its crossOrigin attribute set to the String provided. This is needed if you want to access image pixel data.
  \t\t// Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values.
  \t\tcrossOrigin: false,

  \t\t// @option errorOverlayUrl: String = ''
  \t\t// URL to the overlay image to show in place of the overlay that failed to load.
  \t\terrorOverlayUrl: '',

  \t\t// @option zIndex: Number = 1
  \t\t// The explicit [zIndex](https://developer.mozilla.org/docs/Web/CSS/CSS_Positioning/Understanding_z_index) of the overlay layer.
  \t\tzIndex: 1,

  \t\t// @option className: String = ''
  \t\t// A custom class name to assign to the image. Empty by default.
  \t\tclassName: ''
  \t},

  \tinitialize: function (url, bounds, options) { // (String, LatLngBounds, Object)
  \t\tthis._url = url;
  \t\tthis._bounds = toLatLngBounds(bounds);

  \t\tsetOptions(this, options);
  \t},

  \tonAdd: function () {
  \t\tif (!this._image) {
  \t\t\tthis._initImage();

  \t\t\tif (this.options.opacity < 1) {
  \t\t\t\tthis._updateOpacity();
  \t\t\t}
  \t\t}

  \t\tif (this.options.interactive) {
  \t\t\taddClass(this._image, 'leaflet-interactive');
  \t\t\tthis.addInteractiveTarget(this._image);
  \t\t}

  \t\tthis.getPane().appendChild(this._image);
  \t\tthis._reset();
  \t},

  \tonRemove: function () {
  \t\tremove(this._image);
  \t\tif (this.options.interactive) {
  \t\t\tthis.removeInteractiveTarget(this._image);
  \t\t}
  \t},

  \t// @method setOpacity(opacity: Number): this
  \t// Sets the opacity of the overlay.
  \tsetOpacity: function (opacity) {
  \t\tthis.options.opacity = opacity;

  \t\tif (this._image) {
  \t\t\tthis._updateOpacity();
  \t\t}
  \t\treturn this;
  \t},

  \tsetStyle: function (styleOpts) {
  \t\tif (styleOpts.opacity) {
  \t\t\tthis.setOpacity(styleOpts.opacity);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method bringToFront(): this
  \t// Brings the layer to the top of all overlays.
  \tbringToFront: function () {
  \t\tif (this._map) {
  \t\t\ttoFront(this._image);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method bringToBack(): this
  \t// Brings the layer to the bottom of all overlays.
  \tbringToBack: function () {
  \t\tif (this._map) {
  \t\t\ttoBack(this._image);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method setUrl(url: String): this
  \t// Changes the URL of the image.
  \tsetUrl: function (url) {
  \t\tthis._url = url;

  \t\tif (this._image) {
  \t\t\tthis._image.src = url;
  \t\t}
  \t\treturn this;
  \t},

  \t// @method setBounds(bounds: LatLngBounds): this
  \t// Update the bounds that this ImageOverlay covers
  \tsetBounds: function (bounds) {
  \t\tthis._bounds = toLatLngBounds(bounds);

  \t\tif (this._map) {
  \t\t\tthis._reset();
  \t\t}
  \t\treturn this;
  \t},

  \tgetEvents: function () {
  \t\tvar events = {
  \t\t\tzoom: this._reset,
  \t\t\tviewreset: this._reset
  \t\t};

  \t\tif (this._zoomAnimated) {
  \t\t\tevents.zoomanim = this._animateZoom;
  \t\t}

  \t\treturn events;
  \t},

  \t// @method setZIndex(value: Number): this
  \t// Changes the [zIndex](#imageoverlay-zindex) of the image overlay.
  \tsetZIndex: function (value) {
  \t\tthis.options.zIndex = value;
  \t\tthis._updateZIndex();
  \t\treturn this;
  \t},

  \t// @method getBounds(): LatLngBounds
  \t// Get the bounds that this ImageOverlay covers
  \tgetBounds: function () {
  \t\treturn this._bounds;
  \t},

  \t// @method getElement(): HTMLElement
  \t// Returns the instance of [`HTMLImageElement`](https://developer.mozilla.org/docs/Web/API/HTMLImageElement)
  \t// used by this overlay.
  \tgetElement: function () {
  \t\treturn this._image;
  \t},

  \t_initImage: function () {
  \t\tvar wasElementSupplied = this._url.tagName === 'IMG';
  \t\tvar img = this._image = wasElementSupplied ? this._url : create\$1('img');

  \t\taddClass(img, 'leaflet-image-layer');
  \t\tif (this._zoomAnimated) { addClass(img, 'leaflet-zoom-animated'); }
  \t\tif (this.options.className) { addClass(img, this.options.className); }

  \t\timg.onselectstart = falseFn;
  \t\timg.onmousemove = falseFn;

  \t\t// @event load: Event
  \t\t// Fired when the ImageOverlay layer has loaded its image
  \t\timg.onload = bind(this.fire, this, 'load');
  \t\timg.onerror = bind(this._overlayOnError, this, 'error');

  \t\tif (this.options.crossOrigin || this.options.crossOrigin === '') {
  \t\t\timg.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin;
  \t\t}

  \t\tif (this.options.zIndex) {
  \t\t\tthis._updateZIndex();
  \t\t}

  \t\tif (wasElementSupplied) {
  \t\t\tthis._url = img.src;
  \t\t\treturn;
  \t\t}

  \t\timg.src = this._url;
  \t\timg.alt = this.options.alt;
  \t},

  \t_animateZoom: function (e) {
  \t\tvar scale = this._map.getZoomScale(e.zoom),
  \t\t    offset = this._map._latLngBoundsToNewLayerBounds(this._bounds, e.zoom, e.center).min;

  \t\tsetTransform(this._image, offset, scale);
  \t},

  \t_reset: function () {
  \t\tvar image = this._image,
  \t\t    bounds = new Bounds(
  \t\t        this._map.latLngToLayerPoint(this._bounds.getNorthWest()),
  \t\t        this._map.latLngToLayerPoint(this._bounds.getSouthEast())),
  \t\t    size = bounds.getSize();

  \t\tsetPosition(image, bounds.min);

  \t\timage.style.width  = size.x + 'px';
  \t\timage.style.height = size.y + 'px';
  \t},

  \t_updateOpacity: function () {
  \t\tsetOpacity(this._image, this.options.opacity);
  \t},

  \t_updateZIndex: function () {
  \t\tif (this._image && this.options.zIndex !== undefined && this.options.zIndex !== null) {
  \t\t\tthis._image.style.zIndex = this.options.zIndex;
  \t\t}
  \t},

  \t_overlayOnError: function () {
  \t\t// @event error: Event
  \t\t// Fired when the ImageOverlay layer fails to load its image
  \t\tthis.fire('error');

  \t\tvar errorUrl = this.options.errorOverlayUrl;
  \t\tif (errorUrl && this._url !== errorUrl) {
  \t\t\tthis._url = errorUrl;
  \t\t\tthis._image.src = errorUrl;
  \t\t}
  \t},

  \t// @method getCenter(): LatLng
  \t// Returns the center of the ImageOverlay.
  \tgetCenter: function () {
  \t\treturn this._bounds.getCenter();
  \t}
  });

  // @factory L.imageOverlay(imageUrl: String, bounds: LatLngBounds, options?: ImageOverlay options)
  // Instantiates an image overlay object given the URL of the image and the
  // geographical bounds it is tied to.
  var imageOverlay = function (url, bounds, options) {
  \treturn new ImageOverlay(url, bounds, options);
  };

  /*
   * @class VideoOverlay
   * @aka L.VideoOverlay
   * @inherits ImageOverlay
   *
   * Used to load and display a video player over specific bounds of the map. Extends `ImageOverlay`.
   *
   * A video overlay uses the [`<video>`](https://developer.mozilla.org/docs/Web/HTML/Element/video)
   * HTML5 element.
   *
   * @example
   *
   * ```js
   * var videoUrl = 'https://www.mapbox.com/bites/00188/patricia_nasa.webm',
   * \tvideoBounds = [[ 32, -130], [ 13, -100]];
   * L.videoOverlay(videoUrl, videoBounds ).addTo(map);
   * ```
   */

  var VideoOverlay = ImageOverlay.extend({

  \t// @section
  \t// @aka VideoOverlay options
  \toptions: {
  \t\t// @option autoplay: Boolean = true
  \t\t// Whether the video starts playing automatically when loaded.
  \t\t// On some browsers autoplay will only work with `muted: true`
  \t\tautoplay: true,

  \t\t// @option loop: Boolean = true
  \t\t// Whether the video will loop back to the beginning when played.
  \t\tloop: true,

  \t\t// @option keepAspectRatio: Boolean = true
  \t\t// Whether the video will save aspect ratio after the projection.
  \t\t// Relevant for supported browsers. See [browser compatibility](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit)
  \t\tkeepAspectRatio: true,

  \t\t// @option muted: Boolean = false
  \t\t// Whether the video starts on mute when loaded.
  \t\tmuted: false,

  \t\t// @option playsInline: Boolean = true
  \t\t// Mobile browsers will play the video right where it is instead of open it up in fullscreen mode.
  \t\tplaysInline: true
  \t},

  \t_initImage: function () {
  \t\tvar wasElementSupplied = this._url.tagName === 'VIDEO';
  \t\tvar vid = this._image = wasElementSupplied ? this._url : create\$1('video');

  \t\taddClass(vid, 'leaflet-image-layer');
  \t\tif (this._zoomAnimated) { addClass(vid, 'leaflet-zoom-animated'); }
  \t\tif (this.options.className) { addClass(vid, this.options.className); }

  \t\tvid.onselectstart = falseFn;
  \t\tvid.onmousemove = falseFn;

  \t\t// @event load: Event
  \t\t// Fired when the video has finished loading the first frame
  \t\tvid.onloadeddata = bind(this.fire, this, 'load');

  \t\tif (wasElementSupplied) {
  \t\t\tvar sourceElements = vid.getElementsByTagName('source');
  \t\t\tvar sources = [];
  \t\t\tfor (var j = 0; j < sourceElements.length; j++) {
  \t\t\t\tsources.push(sourceElements[j].src);
  \t\t\t}

  \t\t\tthis._url = (sourceElements.length > 0) ? sources : [vid.src];
  \t\t\treturn;
  \t\t}

  \t\tif (!isArray(this._url)) { this._url = [this._url]; }

  \t\tif (!this.options.keepAspectRatio && Object.prototype.hasOwnProperty.call(vid.style, 'objectFit')) {
  \t\t\tvid.style['objectFit'] = 'fill';
  \t\t}
  \t\tvid.autoplay = !!this.options.autoplay;
  \t\tvid.loop = !!this.options.loop;
  \t\tvid.muted = !!this.options.muted;
  \t\tvid.playsInline = !!this.options.playsInline;
  \t\tfor (var i = 0; i < this._url.length; i++) {
  \t\t\tvar source = create\$1('source');
  \t\t\tsource.src = this._url[i];
  \t\t\tvid.appendChild(source);
  \t\t}
  \t}

  \t// @method getElement(): HTMLVideoElement
  \t// Returns the instance of [`HTMLVideoElement`](https://developer.mozilla.org/docs/Web/API/HTMLVideoElement)
  \t// used by this overlay.
  });


  // @factory L.videoOverlay(video: String|Array|HTMLVideoElement, bounds: LatLngBounds, options?: VideoOverlay options)
  // Instantiates an image overlay object given the URL of the video (or array of URLs, or even a video element) and the
  // geographical bounds it is tied to.

  function videoOverlay(video, bounds, options) {
  \treturn new VideoOverlay(video, bounds, options);
  }

  /*
   * @class SVGOverlay
   * @aka L.SVGOverlay
   * @inherits ImageOverlay
   *
   * Used to load, display and provide DOM access to an SVG file over specific bounds of the map. Extends `ImageOverlay`.
   *
   * An SVG overlay uses the [`<svg>`](https://developer.mozilla.org/docs/Web/SVG/Element/svg) element.
   *
   * @example
   *
   * ```js
   * var svgElement = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");
   * svgElement.setAttribute('xmlns', \"http://www.w3.org/2000/svg\");
   * svgElement.setAttribute('viewBox', \"0 0 200 200\");
   * svgElement.innerHTML = '<rect width=\"200\" height=\"200\"/><rect x=\"75\" y=\"23\" width=\"50\" height=\"50\" style=\"fill:red\"/><rect x=\"75\" y=\"123\" width=\"50\" height=\"50\" style=\"fill:#0013ff\"/>';
   * var svgElementBounds = [ [ 32, -130 ], [ 13, -100 ] ];
   * L.svgOverlay(svgElement, svgElementBounds).addTo(map);
   * ```
   */

  var SVGOverlay = ImageOverlay.extend({
  \t_initImage: function () {
  \t\tvar el = this._image = this._url;

  \t\taddClass(el, 'leaflet-image-layer');
  \t\tif (this._zoomAnimated) { addClass(el, 'leaflet-zoom-animated'); }
  \t\tif (this.options.className) { addClass(el, this.options.className); }

  \t\tel.onselectstart = falseFn;
  \t\tel.onmousemove = falseFn;
  \t}

  \t// @method getElement(): SVGElement
  \t// Returns the instance of [`SVGElement`](https://developer.mozilla.org/docs/Web/API/SVGElement)
  \t// used by this overlay.
  });


  // @factory L.svgOverlay(svg: String|SVGElement, bounds: LatLngBounds, options?: SVGOverlay options)
  // Instantiates an image overlay object given an SVG element and the geographical bounds it is tied to.
  // A viewBox attribute is required on the SVG element to zoom in and out properly.

  function svgOverlay(el, bounds, options) {
  \treturn new SVGOverlay(el, bounds, options);
  }

  /*
   * @class DivOverlay
   * @inherits Interactive layer
   * @aka L.DivOverlay
   * Base model for L.Popup and L.Tooltip. Inherit from it for custom overlays like plugins.
   */

  // @namespace DivOverlay
  var DivOverlay = Layer.extend({

  \t// @section
  \t// @aka DivOverlay options
  \toptions: {
  \t\t// @option interactive: Boolean = false
  \t\t// If true, the popup/tooltip will listen to the mouse events.
  \t\tinteractive: false,

  \t\t// @option offset: Point = Point(0, 0)
  \t\t// The offset of the overlay position.
  \t\toffset: [0, 0],

  \t\t// @option className: String = ''
  \t\t// A custom CSS class name to assign to the overlay.
  \t\tclassName: '',

  \t\t// @option pane: String = undefined
  \t\t// `Map pane` where the overlay will be added.
  \t\tpane: undefined,

  \t\t// @option content: String|HTMLElement|Function = ''
  \t\t// Sets the HTML content of the overlay while initializing. If a function is passed the source layer will be
  \t\t// passed to the function. The function should return a `String` or `HTMLElement` to be used in the overlay.
  \t\tcontent: ''
  \t},

  \tinitialize: function (options, source) {
  \t\tif (options && (options instanceof LatLng || isArray(options))) {
  \t\t\tthis._latlng = toLatLng(options);
  \t\t\tsetOptions(this, source);
  \t\t} else {
  \t\t\tsetOptions(this, options);
  \t\t\tthis._source = source;
  \t\t}
  \t\tif (this.options.content) {
  \t\t\tthis._content = this.options.content;
  \t\t}
  \t},

  \t// @method openOn(map: Map): this
  \t// Adds the overlay to the map.
  \t// Alternative to `map.openPopup(popup)`/`.openTooltip(tooltip)`.
  \topenOn: function (map) {
  \t\tmap = arguments.length ? map : this._source._map; // experimental, not the part of public api
  \t\tif (!map.hasLayer(this)) {
  \t\t\tmap.addLayer(this);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method close(): this
  \t// Closes the overlay.
  \t// Alternative to `map.closePopup(popup)`/`.closeTooltip(tooltip)`
  \t// and `layer.closePopup()`/`.closeTooltip()`.
  \tclose: function () {
  \t\tif (this._map) {
  \t\t\tthis._map.removeLayer(this);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method toggle(layer?: Layer): this
  \t// Opens or closes the overlay bound to layer depending on its current state.
  \t// Argument may be omitted only for overlay bound to layer.
  \t// Alternative to `layer.togglePopup()`/`.toggleTooltip()`.
  \ttoggle: function (layer) {
  \t\tif (this._map) {
  \t\t\tthis.close();
  \t\t} else {
  \t\t\tif (arguments.length) {
  \t\t\t\tthis._source = layer;
  \t\t\t} else {
  \t\t\t\tlayer = this._source;
  \t\t\t}
  \t\t\tthis._prepareOpen();

  \t\t\t// open the overlay on the map
  \t\t\tthis.openOn(layer._map);
  \t\t}
  \t\treturn this;
  \t},

  \tonAdd: function (map) {
  \t\tthis._zoomAnimated = map._zoomAnimated;

  \t\tif (!this._container) {
  \t\t\tthis._initLayout();
  \t\t}

  \t\tif (map._fadeAnimated) {
  \t\t\tsetOpacity(this._container, 0);
  \t\t}

  \t\tclearTimeout(this._removeTimeout);
  \t\tthis.getPane().appendChild(this._container);
  \t\tthis.update();

  \t\tif (map._fadeAnimated) {
  \t\t\tsetOpacity(this._container, 1);
  \t\t}

  \t\tthis.bringToFront();

  \t\tif (this.options.interactive) {
  \t\t\taddClass(this._container, 'leaflet-interactive');
  \t\t\tthis.addInteractiveTarget(this._container);
  \t\t}
  \t},

  \tonRemove: function (map) {
  \t\tif (map._fadeAnimated) {
  \t\t\tsetOpacity(this._container, 0);
  \t\t\tthis._removeTimeout = setTimeout(bind(remove, undefined, this._container), 200);
  \t\t} else {
  \t\t\tremove(this._container);
  \t\t}

  \t\tif (this.options.interactive) {
  \t\t\tremoveClass(this._container, 'leaflet-interactive');
  \t\t\tthis.removeInteractiveTarget(this._container);
  \t\t}
  \t},

  \t// @namespace DivOverlay
  \t// @method getLatLng: LatLng
  \t// Returns the geographical point of the overlay.
  \tgetLatLng: function () {
  \t\treturn this._latlng;
  \t},

  \t// @method setLatLng(latlng: LatLng): this
  \t// Sets the geographical point where the overlay will open.
  \tsetLatLng: function (latlng) {
  \t\tthis._latlng = toLatLng(latlng);
  \t\tif (this._map) {
  \t\t\tthis._updatePosition();
  \t\t\tthis._adjustPan();
  \t\t}
  \t\treturn this;
  \t},

  \t// @method getContent: String|HTMLElement
  \t// Returns the content of the overlay.
  \tgetContent: function () {
  \t\treturn this._content;
  \t},

  \t// @method setContent(htmlContent: String|HTMLElement|Function): this
  \t// Sets the HTML content of the overlay. If a function is passed the source layer will be passed to the function.
  \t// The function should return a `String` or `HTMLElement` to be used in the overlay.
  \tsetContent: function (content) {
  \t\tthis._content = content;
  \t\tthis.update();
  \t\treturn this;
  \t},

  \t// @method getElement: String|HTMLElement
  \t// Returns the HTML container of the overlay.
  \tgetElement: function () {
  \t\treturn this._container;
  \t},

  \t// @method update: null
  \t// Updates the overlay content, layout and position. Useful for updating the overlay after something inside changed, e.g. image loaded.
  \tupdate: function () {
  \t\tif (!this._map) { return; }

  \t\tthis._container.style.visibility = 'hidden';

  \t\tthis._updateContent();
  \t\tthis._updateLayout();
  \t\tthis._updatePosition();

  \t\tthis._container.style.visibility = '';

  \t\tthis._adjustPan();
  \t},

  \tgetEvents: function () {
  \t\tvar events = {
  \t\t\tzoom: this._updatePosition,
  \t\t\tviewreset: this._updatePosition
  \t\t};

  \t\tif (this._zoomAnimated) {
  \t\t\tevents.zoomanim = this._animateZoom;
  \t\t}
  \t\treturn events;
  \t},

  \t// @method isOpen: Boolean
  \t// Returns `true` when the overlay is visible on the map.
  \tisOpen: function () {
  \t\treturn !!this._map && this._map.hasLayer(this);
  \t},

  \t// @method bringToFront: this
  \t// Brings this overlay in front of other overlays (in the same map pane).
  \tbringToFront: function () {
  \t\tif (this._map) {
  \t\t\ttoFront(this._container);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method bringToBack: this
  \t// Brings this overlay to the back of other overlays (in the same map pane).
  \tbringToBack: function () {
  \t\tif (this._map) {
  \t\t\ttoBack(this._container);
  \t\t}
  \t\treturn this;
  \t},

  \t// prepare bound overlay to open: update latlng pos / content source (for FeatureGroup)
  \t_prepareOpen: function (latlng) {
  \t\tvar source = this._source;
  \t\tif (!source._map) { return false; }

  \t\tif (source instanceof FeatureGroup) {
  \t\t\tsource = null;
  \t\t\tvar layers = this._source._layers;
  \t\t\tfor (var id in layers) {
  \t\t\t\tif (layers[id]._map) {
  \t\t\t\t\tsource = layers[id];
  \t\t\t\t\tbreak;
  \t\t\t\t}
  \t\t\t}
  \t\t\tif (!source) { return false; } // Unable to get source layer.

  \t\t\t// set overlay source to this layer
  \t\t\tthis._source = source;
  \t\t}

  \t\tif (!latlng) {
  \t\t\tif (source.getCenter) {
  \t\t\t\tlatlng = source.getCenter();
  \t\t\t} else if (source.getLatLng) {
  \t\t\t\tlatlng = source.getLatLng();
  \t\t\t} else if (source.getBounds) {
  \t\t\t\tlatlng = source.getBounds().getCenter();
  \t\t\t} else {
  \t\t\t\tthrow new Error('Unable to get source layer LatLng.');
  \t\t\t}
  \t\t}
  \t\tthis.setLatLng(latlng);

  \t\tif (this._map) {
  \t\t\t// update the overlay (content, layout, etc...)
  \t\t\tthis.update();
  \t\t}

  \t\treturn true;
  \t},

  \t_updateContent: function () {
  \t\tif (!this._content) { return; }

  \t\tvar node = this._contentNode;
  \t\tvar content = (typeof this._content === 'function') ? this._content(this._source || this) : this._content;

  \t\tif (typeof content === 'string') {
  \t\t\tnode.innerHTML = content;
  \t\t} else {
  \t\t\twhile (node.hasChildNodes()) {
  \t\t\t\tnode.removeChild(node.firstChild);
  \t\t\t}
  \t\t\tnode.appendChild(content);
  \t\t}

  \t\t// @namespace DivOverlay
  \t\t// @section DivOverlay events
  \t\t// @event contentupdate: Event
  \t\t// Fired when the content of the overlay is updated
  \t\tthis.fire('contentupdate');
  \t},

  \t_updatePosition: function () {
  \t\tif (!this._map) { return; }

  \t\tvar pos = this._map.latLngToLayerPoint(this._latlng),
  \t\t    offset = toPoint(this.options.offset),
  \t\t    anchor = this._getAnchor();

  \t\tif (this._zoomAnimated) {
  \t\t\tsetPosition(this._container, pos.add(anchor));
  \t\t} else {
  \t\t\toffset = offset.add(pos).add(anchor);
  \t\t}

  \t\tvar bottom = this._containerBottom = -offset.y,
  \t\t    left = this._containerLeft = -Math.round(this._containerWidth / 2) + offset.x;

  \t\t// bottom position the overlay in case the height of the overlay changes (images loading etc)
  \t\tthis._container.style.bottom = bottom + 'px';
  \t\tthis._container.style.left = left + 'px';
  \t},

  \t_getAnchor: function () {
  \t\treturn [0, 0];
  \t}

  });

  Map.include({
  \t_initOverlay: function (OverlayClass, content, latlng, options) {
  \t\tvar overlay = content;
  \t\tif (!(overlay instanceof OverlayClass)) {
  \t\t\toverlay = new OverlayClass(options).setContent(content);
  \t\t}
  \t\tif (latlng) {
  \t\t\toverlay.setLatLng(latlng);
  \t\t}
  \t\treturn overlay;
  \t}
  });


  Layer.include({
  \t_initOverlay: function (OverlayClass, old, content, options) {
  \t\tvar overlay = content;
  \t\tif (overlay instanceof OverlayClass) {
  \t\t\tsetOptions(overlay, options);
  \t\t\toverlay._source = this;
  \t\t} else {
  \t\t\toverlay = (old && !options) ? old : new OverlayClass(options, this);
  \t\t\toverlay.setContent(content);
  \t\t}
  \t\treturn overlay;
  \t}
  });

  /*
   * @class Popup
   * @inherits DivOverlay
   * @aka L.Popup
   * Used to open popups in certain places of the map. Use [Map.openPopup](#map-openpopup) to
   * open popups while making sure that only one popup is open at one time
   * (recommended for usability), or use [Map.addLayer](#map-addlayer) to open as many as you want.
   *
   * @example
   *
   * If you want to just bind a popup to marker click and then open it, it's really easy:
   *
   * ```js
   * marker.bindPopup(popupContent).openPopup();
   * ```
   * Path overlays like polylines also have a `bindPopup` method.
   *
   * A popup can be also standalone:
   *
   * ```js
   * var popup = L.popup()
   * \t.setLatLng(latlng)
   * \t.setContent('<p>Hello world!<br />This is a nice popup.</p>')
   * \t.openOn(map);
   * ```
   * or
   * ```js
   * var popup = L.popup(latlng, {content: '<p>Hello world!<br />This is a nice popup.</p>')
   * \t.openOn(map);
   * ```
   */


  // @namespace Popup
  var Popup = DivOverlay.extend({

  \t// @section
  \t// @aka Popup options
  \toptions: {
  \t\t// @option pane: String = 'popupPane'
  \t\t// `Map pane` where the popup will be added.
  \t\tpane: 'popupPane',

  \t\t// @option offset: Point = Point(0, 7)
  \t\t// The offset of the popup position.
  \t\toffset: [0, 7],

  \t\t// @option maxWidth: Number = 300
  \t\t// Max width of the popup, in pixels.
  \t\tmaxWidth: 300,

  \t\t// @option minWidth: Number = 50
  \t\t// Min width of the popup, in pixels.
  \t\tminWidth: 50,

  \t\t// @option maxHeight: Number = null
  \t\t// If set, creates a scrollable container of the given height
  \t\t// inside a popup if its content exceeds it.
  \t\t// The scrollable container can be styled using the
  \t\t// `leaflet-popup-scrolled` CSS class selector.
  \t\tmaxHeight: null,

  \t\t// @option autoPan: Boolean = true
  \t\t// Set it to `false` if you don't want the map to do panning animation
  \t\t// to fit the opened popup.
  \t\tautoPan: true,

  \t\t// @option autoPanPaddingTopLeft: Point = null
  \t\t// The margin between the popup and the top left corner of the map
  \t\t// view after autopanning was performed.
  \t\tautoPanPaddingTopLeft: null,

  \t\t// @option autoPanPaddingBottomRight: Point = null
  \t\t// The margin between the popup and the bottom right corner of the map
  \t\t// view after autopanning was performed.
  \t\tautoPanPaddingBottomRight: null,

  \t\t// @option autoPanPadding: Point = Point(5, 5)
  \t\t// Equivalent of setting both top left and bottom right autopan padding to the same value.
  \t\tautoPanPadding: [5, 5],

  \t\t// @option keepInView: Boolean = false
  \t\t// Set it to `true` if you want to prevent users from panning the popup
  \t\t// off of the screen while it is open.
  \t\tkeepInView: false,

  \t\t// @option closeButton: Boolean = true
  \t\t// Controls the presence of a close button in the popup.
  \t\tcloseButton: true,

  \t\t// @option autoClose: Boolean = true
  \t\t// Set it to `false` if you want to override the default behavior of
  \t\t// the popup closing when another popup is opened.
  \t\tautoClose: true,

  \t\t// @option closeOnEscapeKey: Boolean = true
  \t\t// Set it to `false` if you want to override the default behavior of
  \t\t// the ESC key for closing of the popup.
  \t\tcloseOnEscapeKey: true,

  \t\t// @option closeOnClick: Boolean = *
  \t\t// Set it if you want to override the default behavior of the popup closing when user clicks
  \t\t// on the map. Defaults to the map's [`closePopupOnClick`](#map-closepopuponclick) option.

  \t\t// @option className: String = ''
  \t\t// A custom CSS class name to assign to the popup.
  \t\tclassName: ''
  \t},

  \t// @namespace Popup
  \t// @method openOn(map: Map): this
  \t// Alternative to `map.openPopup(popup)`.
  \t// Adds the popup to the map and closes the previous one.
  \topenOn: function (map) {
  \t\tmap = arguments.length ? map : this._source._map; // experimental, not the part of public api

  \t\tif (!map.hasLayer(this) && map._popup && map._popup.options.autoClose) {
  \t\t\tmap.removeLayer(map._popup);
  \t\t}
  \t\tmap._popup = this;

  \t\treturn DivOverlay.prototype.openOn.call(this, map);
  \t},

  \tonAdd: function (map) {
  \t\tDivOverlay.prototype.onAdd.call(this, map);

  \t\t// @namespace Map
  \t\t// @section Popup events
  \t\t// @event popupopen: PopupEvent
  \t\t// Fired when a popup is opened in the map
  \t\tmap.fire('popupopen', {popup: this});

  \t\tif (this._source) {
  \t\t\t// @namespace Layer
  \t\t\t// @section Popup events
  \t\t\t// @event popupopen: PopupEvent
  \t\t\t// Fired when a popup bound to this layer is opened
  \t\t\tthis._source.fire('popupopen', {popup: this}, true);
  \t\t\t// For non-path layers, we toggle the popup when clicking
  \t\t\t// again the layer, so prevent the map to reopen it.
  \t\t\tif (!(this._source instanceof Path)) {
  \t\t\t\tthis._source.on('preclick', stopPropagation);
  \t\t\t}
  \t\t}
  \t},

  \tonRemove: function (map) {
  \t\tDivOverlay.prototype.onRemove.call(this, map);

  \t\t// @namespace Map
  \t\t// @section Popup events
  \t\t// @event popupclose: PopupEvent
  \t\t// Fired when a popup in the map is closed
  \t\tmap.fire('popupclose', {popup: this});

  \t\tif (this._source) {
  \t\t\t// @namespace Layer
  \t\t\t// @section Popup events
  \t\t\t// @event popupclose: PopupEvent
  \t\t\t// Fired when a popup bound to this layer is closed
  \t\t\tthis._source.fire('popupclose', {popup: this}, true);
  \t\t\tif (!(this._source instanceof Path)) {
  \t\t\t\tthis._source.off('preclick', stopPropagation);
  \t\t\t}
  \t\t}
  \t},

  \tgetEvents: function () {
  \t\tvar events = DivOverlay.prototype.getEvents.call(this);

  \t\tif (this.options.closeOnClick !== undefined ? this.options.closeOnClick : this._map.options.closePopupOnClick) {
  \t\t\tevents.preclick = this.close;
  \t\t}

  \t\tif (this.options.keepInView) {
  \t\t\tevents.moveend = this._adjustPan;
  \t\t}

  \t\treturn events;
  \t},

  \t_initLayout: function () {
  \t\tvar prefix = 'leaflet-popup',
  \t\t    container = this._container = create\$1('div',
  \t\t\tprefix + ' ' + (this.options.className || '') +
  \t\t\t' leaflet-zoom-animated');

  \t\tvar wrapper = this._wrapper = create\$1('div', prefix + '-content-wrapper', container);
  \t\tthis._contentNode = create\$1('div', prefix + '-content', wrapper);

  \t\tdisableClickPropagation(container);
  \t\tdisableScrollPropagation(this._contentNode);
  \t\ton(container, 'contextmenu', stopPropagation);

  \t\tthis._tipContainer = create\$1('div', prefix + '-tip-container', container);
  \t\tthis._tip = create\$1('div', prefix + '-tip', this._tipContainer);

  \t\tif (this.options.closeButton) {
  \t\t\tvar closeButton = this._closeButton = create\$1('a', prefix + '-close-button', container);
  \t\t\tcloseButton.setAttribute('role', 'button'); // overrides the implicit role=link of <a> elements #7399
  \t\t\tcloseButton.setAttribute('aria-label', 'Close popup');
  \t\t\tcloseButton.href = '#close';
  \t\t\tcloseButton.innerHTML = '<span aria-hidden=\"true\">&#215;</span>';

  \t\t\ton(closeButton, 'click', function (ev) {
  \t\t\t\tpreventDefault(ev);
  \t\t\t\tthis.close();
  \t\t\t}, this);
  \t\t}
  \t},

  \t_updateLayout: function () {
  \t\tvar container = this._contentNode,
  \t\t    style = container.style;

  \t\tstyle.width = '';
  \t\tstyle.whiteSpace = 'nowrap';

  \t\tvar width = container.offsetWidth;
  \t\twidth = Math.min(width, this.options.maxWidth);
  \t\twidth = Math.max(width, this.options.minWidth);

  \t\tstyle.width = (width + 1) + 'px';
  \t\tstyle.whiteSpace = '';

  \t\tstyle.height = '';

  \t\tvar height = container.offsetHeight,
  \t\t    maxHeight = this.options.maxHeight,
  \t\t    scrolledClass = 'leaflet-popup-scrolled';

  \t\tif (maxHeight && height > maxHeight) {
  \t\t\tstyle.height = maxHeight + 'px';
  \t\t\taddClass(container, scrolledClass);
  \t\t} else {
  \t\t\tremoveClass(container, scrolledClass);
  \t\t}

  \t\tthis._containerWidth = this._container.offsetWidth;
  \t},

  \t_animateZoom: function (e) {
  \t\tvar pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center),
  \t\t    anchor = this._getAnchor();
  \t\tsetPosition(this._container, pos.add(anchor));
  \t},

  \t_adjustPan: function () {
  \t\tif (!this.options.autoPan) { return; }
  \t\tif (this._map._panAnim) { this._map._panAnim.stop(); }

  \t\t// We can endlessly recurse if keepInView is set and the view resets.
  \t\t// Let's guard against that by exiting early if we're responding to our own autopan.
  \t\tif (this._autopanning) {
  \t\t\tthis._autopanning = false;
  \t\t\treturn;
  \t\t}

  \t\tvar map = this._map,
  \t\t    marginBottom = parseInt(getStyle(this._container, 'marginBottom'), 10) || 0,
  \t\t    containerHeight = this._container.offsetHeight + marginBottom,
  \t\t    containerWidth = this._containerWidth,
  \t\t    layerPos = new Point(this._containerLeft, -containerHeight - this._containerBottom);

  \t\tlayerPos._add(getPosition(this._container));

  \t\tvar containerPos = map.layerPointToContainerPoint(layerPos),
  \t\t    padding = toPoint(this.options.autoPanPadding),
  \t\t    paddingTL = toPoint(this.options.autoPanPaddingTopLeft || padding),
  \t\t    paddingBR = toPoint(this.options.autoPanPaddingBottomRight || padding),
  \t\t    size = map.getSize(),
  \t\t    dx = 0,
  \t\t    dy = 0;

  \t\tif (containerPos.x + containerWidth + paddingBR.x > size.x) { // right
  \t\t\tdx = containerPos.x + containerWidth - size.x + paddingBR.x;
  \t\t}
  \t\tif (containerPos.x - dx - paddingTL.x < 0) { // left
  \t\t\tdx = containerPos.x - paddingTL.x;
  \t\t}
  \t\tif (containerPos.y + containerHeight + paddingBR.y > size.y) { // bottom
  \t\t\tdy = containerPos.y + containerHeight - size.y + paddingBR.y;
  \t\t}
  \t\tif (containerPos.y - dy - paddingTL.y < 0) { // top
  \t\t\tdy = containerPos.y - paddingTL.y;
  \t\t}

  \t\t// @namespace Map
  \t\t// @section Popup events
  \t\t// @event autopanstart: Event
  \t\t// Fired when the map starts autopanning when opening a popup.
  \t\tif (dx || dy) {
  \t\t\t// Track that we're autopanning, as this function will be re-ran on moveend
  \t\t\tif (this.options.keepInView) {
  \t\t\t\tthis._autopanning = true;
  \t\t\t}

  \t\t\tmap
  \t\t\t    .fire('autopanstart')
  \t\t\t    .panBy([dx, dy]);
  \t\t}
  \t},

  \t_getAnchor: function () {
  \t\t// Where should we anchor the popup on the source layer?
  \t\treturn toPoint(this._source && this._source._getPopupAnchor ? this._source._getPopupAnchor() : [0, 0]);
  \t}

  });

  // @namespace Popup
  // @factory L.popup(options?: Popup options, source?: Layer)
  // Instantiates a `Popup` object given an optional `options` object that describes its appearance and location and an optional `source` object that is used to tag the popup with a reference to the Layer to which it refers.
  // @alternative
  // @factory L.popup(latlng: LatLng, options?: Popup options)
  // Instantiates a `Popup` object given `latlng` where the popup will open and an optional `options` object that describes its appearance and location.
  var popup = function (options, source) {
  \treturn new Popup(options, source);
  };


  /* @namespace Map
   * @section Interaction Options
   * @option closePopupOnClick: Boolean = true
   * Set it to `false` if you don't want popups to close when user clicks the map.
   */
  Map.mergeOptions({
  \tclosePopupOnClick: true
  });


  // @namespace Map
  // @section Methods for Layers and Controls
  Map.include({
  \t// @method openPopup(popup: Popup): this
  \t// Opens the specified popup while closing the previously opened (to make sure only one is opened at one time for usability).
  \t// @alternative
  \t// @method openPopup(content: String|HTMLElement, latlng: LatLng, options?: Popup options): this
  \t// Creates a popup with the specified content and options and opens it in the given point on a map.
  \topenPopup: function (popup, latlng, options) {
  \t\tthis._initOverlay(Popup, popup, latlng, options)
  \t\t  .openOn(this);

  \t\treturn this;
  \t},

  \t// @method closePopup(popup?: Popup): this
  \t// Closes the popup previously opened with [openPopup](#map-openpopup) (or the given one).
  \tclosePopup: function (popup) {
  \t\tpopup = arguments.length ? popup : this._popup;
  \t\tif (popup) {
  \t\t\tpopup.close();
  \t\t}
  \t\treturn this;
  \t}
  });

  /*
   * @namespace Layer
   * @section Popup methods example
   *
   * All layers share a set of methods convenient for binding popups to it.
   *
   * ```js
   * var layer = L.Polygon(latlngs).bindPopup('Hi There!').addTo(map);
   * layer.openPopup();
   * layer.closePopup();
   * ```
   *
   * Popups will also be automatically opened when the layer is clicked on and closed when the layer is removed from the map or another popup is opened.
   */

  // @section Popup methods
  Layer.include({

  \t// @method bindPopup(content: String|HTMLElement|Function|Popup, options?: Popup options): this
  \t// Binds a popup to the layer with the passed `content` and sets up the
  \t// necessary event listeners. If a `Function` is passed it will receive
  \t// the layer as the first argument and should return a `String` or `HTMLElement`.
  \tbindPopup: function (content, options) {
  \t\tthis._popup = this._initOverlay(Popup, this._popup, content, options);
  \t\tif (!this._popupHandlersAdded) {
  \t\t\tthis.on({
  \t\t\t\tclick: this._openPopup,
  \t\t\t\tkeypress: this._onKeyPress,
  \t\t\t\tremove: this.closePopup,
  \t\t\t\tmove: this._movePopup
  \t\t\t});
  \t\t\tthis._popupHandlersAdded = true;
  \t\t}

  \t\treturn this;
  \t},

  \t// @method unbindPopup(): this
  \t// Removes the popup previously bound with `bindPopup`.
  \tunbindPopup: function () {
  \t\tif (this._popup) {
  \t\t\tthis.off({
  \t\t\t\tclick: this._openPopup,
  \t\t\t\tkeypress: this._onKeyPress,
  \t\t\t\tremove: this.closePopup,
  \t\t\t\tmove: this._movePopup
  \t\t\t});
  \t\t\tthis._popupHandlersAdded = false;
  \t\t\tthis._popup = null;
  \t\t}
  \t\treturn this;
  \t},

  \t// @method openPopup(latlng?: LatLng): this
  \t// Opens the bound popup at the specified `latlng` or at the default popup anchor if no `latlng` is passed.
  \topenPopup: function (latlng) {
  \t\tif (this._popup) {
  \t\t\tif (!(this instanceof FeatureGroup)) {
  \t\t\t\tthis._popup._source = this;
  \t\t\t}
  \t\t\tif (this._popup._prepareOpen(latlng || this._latlng)) {
  \t\t\t\t// open the popup on the map
  \t\t\t\tthis._popup.openOn(this._map);
  \t\t\t}
  \t\t}
  \t\treturn this;
  \t},

  \t// @method closePopup(): this
  \t// Closes the popup bound to this layer if it is open.
  \tclosePopup: function () {
  \t\tif (this._popup) {
  \t\t\tthis._popup.close();
  \t\t}
  \t\treturn this;
  \t},

  \t// @method togglePopup(): this
  \t// Opens or closes the popup bound to this layer depending on its current state.
  \ttogglePopup: function () {
  \t\tif (this._popup) {
  \t\t\tthis._popup.toggle(this);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method isPopupOpen(): boolean
  \t// Returns `true` if the popup bound to this layer is currently open.
  \tisPopupOpen: function () {
  \t\treturn (this._popup ? this._popup.isOpen() : false);
  \t},

  \t// @method setPopupContent(content: String|HTMLElement|Popup): this
  \t// Sets the content of the popup bound to this layer.
  \tsetPopupContent: function (content) {
  \t\tif (this._popup) {
  \t\t\tthis._popup.setContent(content);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method getPopup(): Popup
  \t// Returns the popup bound to this layer.
  \tgetPopup: function () {
  \t\treturn this._popup;
  \t},

  \t_openPopup: function (e) {
  \t\tif (!this._popup || !this._map) {
  \t\t\treturn;
  \t\t}
  \t\t// prevent map click
  \t\tstop(e);

  \t\tvar target = e.layer || e.target;
  \t\tif (this._popup._source === target && !(target instanceof Path)) {
  \t\t\t// treat it like a marker and figure out
  \t\t\t// if we should toggle it open/closed
  \t\t\tif (this._map.hasLayer(this._popup)) {
  \t\t\t\tthis.closePopup();
  \t\t\t} else {
  \t\t\t\tthis.openPopup(e.latlng);
  \t\t\t}
  \t\t\treturn;
  \t\t}
  \t\tthis._popup._source = target;
  \t\tthis.openPopup(e.latlng);
  \t},

  \t_movePopup: function (e) {
  \t\tthis._popup.setLatLng(e.latlng);
  \t},

  \t_onKeyPress: function (e) {
  \t\tif (e.originalEvent.keyCode === 13) {
  \t\t\tthis._openPopup(e);
  \t\t}
  \t}
  });

  /*
   * @class Tooltip
   * @inherits DivOverlay
   * @aka L.Tooltip
   * Used to display small texts on top of map layers.
   *
   * @example
   * If you want to just bind a tooltip to marker:
   *
   * ```js
   * marker.bindTooltip(\"my tooltip text\").openTooltip();
   * ```
   * Path overlays like polylines also have a `bindTooltip` method.
   *
   * A tooltip can be also standalone:
   *
   * ```js
   * var tooltip = L.tooltip()
   * \t.setLatLng(latlng)
   * \t.setContent('Hello world!<br />This is a nice tooltip.')
   * \t.addTo(map);
   * ```
   * or
   * ```js
   * var tooltip = L.tooltip(latlng, {content: 'Hello world!<br />This is a nice tooltip.'})
   * \t.addTo(map);
   * ```
   *
   *
   * Note about tooltip offset. Leaflet takes two options in consideration
   * for computing tooltip offsetting:
   * - the `offset` Tooltip option: it defaults to [0, 0], and it's specific to one tooltip.
   *   Add a positive x offset to move the tooltip to the right, and a positive y offset to
   *   move it to the bottom. Negatives will move to the left and top.
   * - the `tooltipAnchor` Icon option: this will only be considered for Marker. You
   *   should adapt this value if you use a custom icon.
   */


  // @namespace Tooltip
  var Tooltip = DivOverlay.extend({

  \t// @section
  \t// @aka Tooltip options
  \toptions: {
  \t\t// @option pane: String = 'tooltipPane'
  \t\t// `Map pane` where the tooltip will be added.
  \t\tpane: 'tooltipPane',

  \t\t// @option offset: Point = Point(0, 0)
  \t\t// Optional offset of the tooltip position.
  \t\toffset: [0, 0],

  \t\t// @option direction: String = 'auto'
  \t\t// Direction where to open the tooltip. Possible values are: `right`, `left`,
  \t\t// `top`, `bottom`, `center`, `auto`.
  \t\t// `auto` will dynamically switch between `right` and `left` according to the tooltip
  \t\t// position on the map.
  \t\tdirection: 'auto',

  \t\t// @option permanent: Boolean = false
  \t\t// Whether to open the tooltip permanently or only on mouseover.
  \t\tpermanent: false,

  \t\t// @option sticky: Boolean = false
  \t\t// If true, the tooltip will follow the mouse instead of being fixed at the feature center.
  \t\tsticky: false,

  \t\t// @option opacity: Number = 0.9
  \t\t// Tooltip container opacity.
  \t\topacity: 0.9
  \t},

  \tonAdd: function (map) {
  \t\tDivOverlay.prototype.onAdd.call(this, map);
  \t\tthis.setOpacity(this.options.opacity);

  \t\t// @namespace Map
  \t\t// @section Tooltip events
  \t\t// @event tooltipopen: TooltipEvent
  \t\t// Fired when a tooltip is opened in the map.
  \t\tmap.fire('tooltipopen', {tooltip: this});

  \t\tif (this._source) {
  \t\t\tthis.addEventParent(this._source);

  \t\t\t// @namespace Layer
  \t\t\t// @section Tooltip events
  \t\t\t// @event tooltipopen: TooltipEvent
  \t\t\t// Fired when a tooltip bound to this layer is opened.
  \t\t\tthis._source.fire('tooltipopen', {tooltip: this}, true);
  \t\t}
  \t},

  \tonRemove: function (map) {
  \t\tDivOverlay.prototype.onRemove.call(this, map);

  \t\t// @namespace Map
  \t\t// @section Tooltip events
  \t\t// @event tooltipclose: TooltipEvent
  \t\t// Fired when a tooltip in the map is closed.
  \t\tmap.fire('tooltipclose', {tooltip: this});

  \t\tif (this._source) {
  \t\t\tthis.removeEventParent(this._source);

  \t\t\t// @namespace Layer
  \t\t\t// @section Tooltip events
  \t\t\t// @event tooltipclose: TooltipEvent
  \t\t\t// Fired when a tooltip bound to this layer is closed.
  \t\t\tthis._source.fire('tooltipclose', {tooltip: this}, true);
  \t\t}
  \t},

  \tgetEvents: function () {
  \t\tvar events = DivOverlay.prototype.getEvents.call(this);

  \t\tif (!this.options.permanent) {
  \t\t\tevents.preclick = this.close;
  \t\t}

  \t\treturn events;
  \t},

  \t_initLayout: function () {
  \t\tvar prefix = 'leaflet-tooltip',
  \t\t    className = prefix + ' ' + (this.options.className || '') + ' leaflet-zoom-' + (this._zoomAnimated ? 'animated' : 'hide');

  \t\tthis._contentNode = this._container = create\$1('div', className);

  \t\tthis._container.setAttribute('role', 'tooltip');
  \t\tthis._container.setAttribute('id', 'leaflet-tooltip-' + stamp(this));
  \t},

  \t_updateLayout: function () {},

  \t_adjustPan: function () {},

  \t_setPosition: function (pos) {
  \t\tvar subX, subY,
  \t\t    map = this._map,
  \t\t    container = this._container,
  \t\t    centerPoint = map.latLngToContainerPoint(map.getCenter()),
  \t\t    tooltipPoint = map.layerPointToContainerPoint(pos),
  \t\t    direction = this.options.direction,
  \t\t    tooltipWidth = container.offsetWidth,
  \t\t    tooltipHeight = container.offsetHeight,
  \t\t    offset = toPoint(this.options.offset),
  \t\t    anchor = this._getAnchor();

  \t\tif (direction === 'top') {
  \t\t\tsubX = tooltipWidth / 2;
  \t\t\tsubY = tooltipHeight;
  \t\t} else if (direction === 'bottom') {
  \t\t\tsubX = tooltipWidth / 2;
  \t\t\tsubY = 0;
  \t\t} else if (direction === 'center') {
  \t\t\tsubX = tooltipWidth / 2;
  \t\t\tsubY = tooltipHeight / 2;
  \t\t} else if (direction === 'right') {
  \t\t\tsubX = 0;
  \t\t\tsubY = tooltipHeight / 2;
  \t\t} else if (direction === 'left') {
  \t\t\tsubX = tooltipWidth;
  \t\t\tsubY = tooltipHeight / 2;
  \t\t} else if (tooltipPoint.x < centerPoint.x) {
  \t\t\tdirection = 'right';
  \t\t\tsubX = 0;
  \t\t\tsubY = tooltipHeight / 2;
  \t\t} else {
  \t\t\tdirection = 'left';
  \t\t\tsubX = tooltipWidth + (offset.x + anchor.x) * 2;
  \t\t\tsubY = tooltipHeight / 2;
  \t\t}

  \t\tpos = pos.subtract(toPoint(subX, subY, true)).add(offset).add(anchor);

  \t\tremoveClass(container, 'leaflet-tooltip-right');
  \t\tremoveClass(container, 'leaflet-tooltip-left');
  \t\tremoveClass(container, 'leaflet-tooltip-top');
  \t\tremoveClass(container, 'leaflet-tooltip-bottom');
  \t\taddClass(container, 'leaflet-tooltip-' + direction);
  \t\tsetPosition(container, pos);
  \t},

  \t_updatePosition: function () {
  \t\tvar pos = this._map.latLngToLayerPoint(this._latlng);
  \t\tthis._setPosition(pos);
  \t},

  \tsetOpacity: function (opacity) {
  \t\tthis.options.opacity = opacity;

  \t\tif (this._container) {
  \t\t\tsetOpacity(this._container, opacity);
  \t\t}
  \t},

  \t_animateZoom: function (e) {
  \t\tvar pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center);
  \t\tthis._setPosition(pos);
  \t},

  \t_getAnchor: function () {
  \t\t// Where should we anchor the tooltip on the source layer?
  \t\treturn toPoint(this._source && this._source._getTooltipAnchor && !this.options.sticky ? this._source._getTooltipAnchor() : [0, 0]);
  \t}

  });

  // @namespace Tooltip
  // @factory L.tooltip(options?: Tooltip options, source?: Layer)
  // Instantiates a `Tooltip` object given an optional `options` object that describes its appearance and location and an optional `source` object that is used to tag the tooltip with a reference to the Layer to which it refers.
  // @alternative
  // @factory L.tooltip(latlng: LatLng, options?: Tooltip options)
  // Instantiates a `Tooltip` object given `latlng` where the tooltip will open and an optional `options` object that describes its appearance and location.
  var tooltip = function (options, source) {
  \treturn new Tooltip(options, source);
  };

  // @namespace Map
  // @section Methods for Layers and Controls
  Map.include({

  \t// @method openTooltip(tooltip: Tooltip): this
  \t// Opens the specified tooltip.
  \t// @alternative
  \t// @method openTooltip(content: String|HTMLElement, latlng: LatLng, options?: Tooltip options): this
  \t// Creates a tooltip with the specified content and options and open it.
  \topenTooltip: function (tooltip, latlng, options) {
  \t\tthis._initOverlay(Tooltip, tooltip, latlng, options)
  \t\t  .openOn(this);

  \t\treturn this;
  \t},

  \t// @method closeTooltip(tooltip: Tooltip): this
  \t// Closes the tooltip given as parameter.
  \tcloseTooltip: function (tooltip) {
  \t\ttooltip.close();
  \t\treturn this;
  \t}

  });

  /*
   * @namespace Layer
   * @section Tooltip methods example
   *
   * All layers share a set of methods convenient for binding tooltips to it.
   *
   * ```js
   * var layer = L.Polygon(latlngs).bindTooltip('Hi There!').addTo(map);
   * layer.openTooltip();
   * layer.closeTooltip();
   * ```
   */

  // @section Tooltip methods
  Layer.include({

  \t// @method bindTooltip(content: String|HTMLElement|Function|Tooltip, options?: Tooltip options): this
  \t// Binds a tooltip to the layer with the passed `content` and sets up the
  \t// necessary event listeners. If a `Function` is passed it will receive
  \t// the layer as the first argument and should return a `String` or `HTMLElement`.
  \tbindTooltip: function (content, options) {

  \t\tif (this._tooltip && this.isTooltipOpen()) {
  \t\t\tthis.unbindTooltip();
  \t\t}

  \t\tthis._tooltip = this._initOverlay(Tooltip, this._tooltip, content, options);
  \t\tthis._initTooltipInteractions();

  \t\tif (this._tooltip.options.permanent && this._map && this._map.hasLayer(this)) {
  \t\t\tthis.openTooltip();
  \t\t}

  \t\treturn this;
  \t},

  \t// @method unbindTooltip(): this
  \t// Removes the tooltip previously bound with `bindTooltip`.
  \tunbindTooltip: function () {
  \t\tif (this._tooltip) {
  \t\t\tthis._initTooltipInteractions(true);
  \t\t\tthis.closeTooltip();
  \t\t\tthis._tooltip = null;
  \t\t}
  \t\treturn this;
  \t},

  \t_initTooltipInteractions: function (remove) {
  \t\tif (!remove && this._tooltipHandlersAdded) { return; }
  \t\tvar onOff = remove ? 'off' : 'on',
  \t\t    events = {
  \t\t\tremove: this.closeTooltip,
  \t\t\tmove: this._moveTooltip
  \t\t    };
  \t\tif (!this._tooltip.options.permanent) {
  \t\t\tevents.mouseover = this._openTooltip;
  \t\t\tevents.mouseout = this.closeTooltip;
  \t\t\tevents.click = this._openTooltip;
  \t\t\tif (this._map) {
  \t\t\t\tthis._addFocusListeners();
  \t\t\t} else {
  \t\t\t\tevents.add = this._addFocusListeners;
  \t\t\t}
  \t\t} else {
  \t\t\tevents.add = this._openTooltip;
  \t\t}
  \t\tif (this._tooltip.options.sticky) {
  \t\t\tevents.mousemove = this._moveTooltip;
  \t\t}
  \t\tthis[onOff](events);
  \t\tthis._tooltipHandlersAdded = !remove;
  \t},

  \t// @method openTooltip(latlng?: LatLng): this
  \t// Opens the bound tooltip at the specified `latlng` or at the default tooltip anchor if no `latlng` is passed.
  \topenTooltip: function (latlng) {
  \t\tif (this._tooltip) {
  \t\t\tif (!(this instanceof FeatureGroup)) {
  \t\t\t\tthis._tooltip._source = this;
  \t\t\t}
  \t\t\tif (this._tooltip._prepareOpen(latlng)) {
  \t\t\t\t// open the tooltip on the map
  \t\t\t\tthis._tooltip.openOn(this._map);

  \t\t\t\tif (this.getElement) {
  \t\t\t\t\tthis._setAriaDescribedByOnLayer(this);
  \t\t\t\t} else if (this.eachLayer) {
  \t\t\t\t\tthis.eachLayer(this._setAriaDescribedByOnLayer, this);
  \t\t\t\t}
  \t\t\t}
  \t\t}
  \t\treturn this;
  \t},

  \t// @method closeTooltip(): this
  \t// Closes the tooltip bound to this layer if it is open.
  \tcloseTooltip: function () {
  \t\tif (this._tooltip) {
  \t\t\treturn this._tooltip.close();
  \t\t}
  \t},

  \t// @method toggleTooltip(): this
  \t// Opens or closes the tooltip bound to this layer depending on its current state.
  \ttoggleTooltip: function () {
  \t\tif (this._tooltip) {
  \t\t\tthis._tooltip.toggle(this);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method isTooltipOpen(): boolean
  \t// Returns `true` if the tooltip bound to this layer is currently open.
  \tisTooltipOpen: function () {
  \t\treturn this._tooltip.isOpen();
  \t},

  \t// @method setTooltipContent(content: String|HTMLElement|Tooltip): this
  \t// Sets the content of the tooltip bound to this layer.
  \tsetTooltipContent: function (content) {
  \t\tif (this._tooltip) {
  \t\t\tthis._tooltip.setContent(content);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method getTooltip(): Tooltip
  \t// Returns the tooltip bound to this layer.
  \tgetTooltip: function () {
  \t\treturn this._tooltip;
  \t},

  \t_addFocusListeners: function () {
  \t\tif (this.getElement) {
  \t\t\tthis._addFocusListenersOnLayer(this);
  \t\t} else if (this.eachLayer) {
  \t\t\tthis.eachLayer(this._addFocusListenersOnLayer, this);
  \t\t}
  \t},

  \t_addFocusListenersOnLayer: function (layer) {
  \t\tvar el = typeof layer.getElement === 'function' && layer.getElement();
  \t\tif (el) {
  \t\t\ton(el, 'focus', function () {
  \t\t\t\tthis._tooltip._source = layer;
  \t\t\t\tthis.openTooltip();
  \t\t\t}, this);
  \t\t\ton(el, 'blur', this.closeTooltip, this);
  \t\t}
  \t},

  \t_setAriaDescribedByOnLayer: function (layer) {
  \t\tvar el = typeof layer.getElement === 'function' && layer.getElement();
  \t\tif (el) {
  \t\t\tel.setAttribute('aria-describedby', this._tooltip._container.id);
  \t\t}
  \t},


  \t_openTooltip: function (e) {
  \t\tif (!this._tooltip || !this._map) {
  \t\t\treturn;
  \t\t}

  \t\t// If the map is moving, we will show the tooltip after it's done.
  \t\tif (this._map.dragging && this._map.dragging.moving() && !this._openOnceFlag) {
  \t\t\tthis._openOnceFlag = true;
  \t\t\tvar that = this;
  \t\t\tthis._map.once('moveend', function () {
  \t\t\t\tthat._openOnceFlag = false;
  \t\t\t\tthat._openTooltip(e);
  \t\t\t});
  \t\t\treturn;
  \t\t}

  \t\tthis._tooltip._source = e.layer || e.target;

  \t\tthis.openTooltip(this._tooltip.options.sticky ? e.latlng : undefined);
  \t},

  \t_moveTooltip: function (e) {
  \t\tvar latlng = e.latlng, containerPoint, layerPoint;
  \t\tif (this._tooltip.options.sticky && e.originalEvent) {
  \t\t\tcontainerPoint = this._map.mouseEventToContainerPoint(e.originalEvent);
  \t\t\tlayerPoint = this._map.containerPointToLayerPoint(containerPoint);
  \t\t\tlatlng = this._map.layerPointToLatLng(layerPoint);
  \t\t}
  \t\tthis._tooltip.setLatLng(latlng);
  \t}
  });

  /*
   * @class DivIcon
   * @aka L.DivIcon
   * @inherits Icon
   *
   * Represents a lightweight icon for markers that uses a simple `<div>`
   * element instead of an image. Inherits from `Icon` but ignores the `iconUrl` and shadow options.
   *
   * @example
   * ```js
   * var myIcon = L.divIcon({className: 'my-div-icon'});
   * // you can set .my-div-icon styles in CSS
   *
   * L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
   * ```
   *
   * By default, it has a 'leaflet-div-icon' CSS class and is styled as a little white square with a shadow.
   */

  var DivIcon = Icon.extend({
  \toptions: {
  \t\t// @section
  \t\t// @aka DivIcon options
  \t\ticonSize: [12, 12], // also can be set through CSS

  \t\t// iconAnchor: (Point),
  \t\t// popupAnchor: (Point),

  \t\t// @option html: String|HTMLElement = ''
  \t\t// Custom HTML code to put inside the div element, empty by default. Alternatively,
  \t\t// an instance of `HTMLElement`.
  \t\thtml: false,

  \t\t// @option bgPos: Point = [0, 0]
  \t\t// Optional relative position of the background, in pixels
  \t\tbgPos: null,

  \t\tclassName: 'leaflet-div-icon'
  \t},

  \tcreateIcon: function (oldIcon) {
  \t\tvar div = (oldIcon && oldIcon.tagName === 'DIV') ? oldIcon : document.createElement('div'),
  \t\t    options = this.options;

  \t\tif (options.html instanceof Element) {
  \t\t\tempty(div);
  \t\t\tdiv.appendChild(options.html);
  \t\t} else {
  \t\t\tdiv.innerHTML = options.html !== false ? options.html : '';
  \t\t}

  \t\tif (options.bgPos) {
  \t\t\tvar bgPos = toPoint(options.bgPos);
  \t\t\tdiv.style.backgroundPosition = (-bgPos.x) + 'px ' + (-bgPos.y) + 'px';
  \t\t}
  \t\tthis._setIconStyles(div, 'icon');

  \t\treturn div;
  \t},

  \tcreateShadow: function () {
  \t\treturn null;
  \t}
  });

  // @factory L.divIcon(options: DivIcon options)
  // Creates a `DivIcon` instance with the given options.
  function divIcon(options) {
  \treturn new DivIcon(options);
  }

  Icon.Default = IconDefault;

  /*
   * @class GridLayer
   * @inherits Layer
   * @aka L.GridLayer
   *
   * Generic class for handling a tiled grid of HTML elements. This is the base class for all tile layers and replaces `TileLayer.Canvas`.
   * GridLayer can be extended to create a tiled grid of HTML elements like `<canvas>`, `<img>` or `<div>`. GridLayer will handle creating and animating these DOM elements for you.
   *
   *
   * @section Synchronous usage
   * @example
   *
   * To create a custom layer, extend GridLayer and implement the `createTile()` method, which will be passed a `Point` object with the `x`, `y`, and `z` (zoom level) coordinates to draw your tile.
   *
   * ```js
   * var CanvasLayer = L.GridLayer.extend({
   *     createTile: function(coords){
   *         // create a <canvas> element for drawing
   *         var tile = L.DomUtil.create('canvas', 'leaflet-tile');
   *
   *         // setup tile width and height according to the options
   *         var size = this.getTileSize();
   *         tile.width = size.x;
   *         tile.height = size.y;
   *
   *         // get a canvas context and draw something on it using coords.x, coords.y and coords.z
   *         var ctx = tile.getContext('2d');
   *
   *         // return the tile so it can be rendered on screen
   *         return tile;
   *     }
   * });
   * ```
   *
   * @section Asynchronous usage
   * @example
   *
   * Tile creation can also be asynchronous, this is useful when using a third-party drawing library. Once the tile is finished drawing it can be passed to the `done()` callback.
   *
   * ```js
   * var CanvasLayer = L.GridLayer.extend({
   *     createTile: function(coords, done){
   *         var error;
   *
   *         // create a <canvas> element for drawing
   *         var tile = L.DomUtil.create('canvas', 'leaflet-tile');
   *
   *         // setup tile width and height according to the options
   *         var size = this.getTileSize();
   *         tile.width = size.x;
   *         tile.height = size.y;
   *
   *         // draw something asynchronously and pass the tile to the done() callback
   *         setTimeout(function() {
   *             done(error, tile);
   *         }, 1000);
   *
   *         return tile;
   *     }
   * });
   * ```
   *
   * @section
   */


  var GridLayer = Layer.extend({

  \t// @section
  \t// @aka GridLayer options
  \toptions: {
  \t\t// @option tileSize: Number|Point = 256
  \t\t// Width and height of tiles in the grid. Use a number if width and height are equal, or `L.point(width, height)` otherwise.
  \t\ttileSize: 256,

  \t\t// @option opacity: Number = 1.0
  \t\t// Opacity of the tiles. Can be used in the `createTile()` function.
  \t\topacity: 1,

  \t\t// @option updateWhenIdle: Boolean = (depends)
  \t\t// Load new tiles only when panning ends.
  \t\t// `true` by default on mobile browsers, in order to avoid too many requests and keep smooth navigation.
  \t\t// `false` otherwise in order to display new tiles _during_ panning, since it is easy to pan outside the
  \t\t// [`keepBuffer`](#gridlayer-keepbuffer) option in desktop browsers.
  \t\tupdateWhenIdle: Browser.mobile,

  \t\t// @option updateWhenZooming: Boolean = true
  \t\t// By default, a smooth zoom animation (during a [touch zoom](#map-touchzoom) or a [`flyTo()`](#map-flyto)) will update grid layers every integer zoom level. Setting this option to `false` will update the grid layer only when the smooth animation ends.
  \t\tupdateWhenZooming: true,

  \t\t// @option updateInterval: Number = 200
  \t\t// Tiles will not update more than once every `updateInterval` milliseconds when panning.
  \t\tupdateInterval: 200,

  \t\t// @option zIndex: Number = 1
  \t\t// The explicit zIndex of the tile layer.
  \t\tzIndex: 1,

  \t\t// @option bounds: LatLngBounds = undefined
  \t\t// If set, tiles will only be loaded inside the set `LatLngBounds`.
  \t\tbounds: null,

  \t\t// @option minZoom: Number = 0
  \t\t// The minimum zoom level down to which this layer will be displayed (inclusive).
  \t\tminZoom: 0,

  \t\t// @option maxZoom: Number = undefined
  \t\t// The maximum zoom level up to which this layer will be displayed (inclusive).
  \t\tmaxZoom: undefined,

  \t\t// @option maxNativeZoom: Number = undefined
  \t\t// Maximum zoom number the tile source has available. If it is specified,
  \t\t// the tiles on all zoom levels higher than `maxNativeZoom` will be loaded
  \t\t// from `maxNativeZoom` level and auto-scaled.
  \t\tmaxNativeZoom: undefined,

  \t\t// @option minNativeZoom: Number = undefined
  \t\t// Minimum zoom number the tile source has available. If it is specified,
  \t\t// the tiles on all zoom levels lower than `minNativeZoom` will be loaded
  \t\t// from `minNativeZoom` level and auto-scaled.
  \t\tminNativeZoom: undefined,

  \t\t// @option noWrap: Boolean = false
  \t\t// Whether the layer is wrapped around the antimeridian. If `true`, the
  \t\t// GridLayer will only be displayed once at low zoom levels. Has no
  \t\t// effect when the [map CRS](#map-crs) doesn't wrap around. Can be used
  \t\t// in combination with [`bounds`](#gridlayer-bounds) to prevent requesting
  \t\t// tiles outside the CRS limits.
  \t\tnoWrap: false,

  \t\t// @option pane: String = 'tilePane'
  \t\t// `Map pane` where the grid layer will be added.
  \t\tpane: 'tilePane',

  \t\t// @option className: String = ''
  \t\t// A custom class name to assign to the tile layer. Empty by default.
  \t\tclassName: '',

  \t\t// @option keepBuffer: Number = 2
  \t\t// When panning the map, keep this many rows and columns of tiles before unloading them.
  \t\tkeepBuffer: 2
  \t},

  \tinitialize: function (options) {
  \t\tsetOptions(this, options);
  \t},

  \tonAdd: function () {
  \t\tthis._initContainer();

  \t\tthis._levels = {};
  \t\tthis._tiles = {};

  \t\tthis._resetView(); // implicit _update() call
  \t},

  \tbeforeAdd: function (map) {
  \t\tmap._addZoomLimit(this);
  \t},

  \tonRemove: function (map) {
  \t\tthis._removeAllTiles();
  \t\tremove(this._container);
  \t\tmap._removeZoomLimit(this);
  \t\tthis._container = null;
  \t\tthis._tileZoom = undefined;
  \t},

  \t// @method bringToFront: this
  \t// Brings the tile layer to the top of all tile layers.
  \tbringToFront: function () {
  \t\tif (this._map) {
  \t\t\ttoFront(this._container);
  \t\t\tthis._setAutoZIndex(Math.max);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method bringToBack: this
  \t// Brings the tile layer to the bottom of all tile layers.
  \tbringToBack: function () {
  \t\tif (this._map) {
  \t\t\ttoBack(this._container);
  \t\t\tthis._setAutoZIndex(Math.min);
  \t\t}
  \t\treturn this;
  \t},

  \t// @method getContainer: HTMLElement
  \t// Returns the HTML element that contains the tiles for this layer.
  \tgetContainer: function () {
  \t\treturn this._container;
  \t},

  \t// @method setOpacity(opacity: Number): this
  \t// Changes the [opacity](#gridlayer-opacity) of the grid layer.
  \tsetOpacity: function (opacity) {
  \t\tthis.options.opacity = opacity;
  \t\tthis._updateOpacity();
  \t\treturn this;
  \t},

  \t// @method setZIndex(zIndex: Number): this
  \t// Changes the [zIndex](#gridlayer-zindex) of the grid layer.
  \tsetZIndex: function (zIndex) {
  \t\tthis.options.zIndex = zIndex;
  \t\tthis._updateZIndex();

  \t\treturn this;
  \t},

  \t// @method isLoading: Boolean
  \t// Returns `true` if any tile in the grid layer has not finished loading.
  \tisLoading: function () {
  \t\treturn this._loading;
  \t},

  \t// @method redraw: this
  \t// Causes the layer to clear all the tiles and request them again.
  \tredraw: function () {
  \t\tif (this._map) {
  \t\t\tthis._removeAllTiles();
  \t\t\tvar tileZoom = this._clampZoom(this._map.getZoom());
  \t\t\tif (tileZoom !== this._tileZoom) {
  \t\t\t\tthis._tileZoom = tileZoom;
  \t\t\t\tthis._updateLevels();
  \t\t\t}
  \t\t\tthis._update();
  \t\t}
  \t\treturn this;
  \t},

  \tgetEvents: function () {
  \t\tvar events = {
  \t\t\tviewprereset: this._invalidateAll,
  \t\t\tviewreset: this._resetView,
  \t\t\tzoom: this._resetView,
  \t\t\tmoveend: this._onMoveEnd
  \t\t};

  \t\tif (!this.options.updateWhenIdle) {
  \t\t\t// update tiles on move, but not more often than once per given interval
  \t\t\tif (!this._onMove) {
  \t\t\t\tthis._onMove = throttle(this._onMoveEnd, this.options.updateInterval, this);
  \t\t\t}

  \t\t\tevents.move = this._onMove;
  \t\t}

  \t\tif (this._zoomAnimated) {
  \t\t\tevents.zoomanim = this._animateZoom;
  \t\t}

  \t\treturn events;
  \t},

  \t// @section Extension methods
  \t// Layers extending `GridLayer` shall reimplement the following method.
  \t// @method createTile(coords: Object, done?: Function): HTMLElement
  \t// Called only internally, must be overridden by classes extending `GridLayer`.
  \t// Returns the `HTMLElement` corresponding to the given `coords`. If the `done` callback
  \t// is specified, it must be called when the tile has finished loading and drawing.
  \tcreateTile: function () {
  \t\treturn document.createElement('div');
  \t},

  \t// @section
  \t// @method getTileSize: Point
  \t// Normalizes the [tileSize option](#gridlayer-tilesize) into a point. Used by the `createTile()` method.
  \tgetTileSize: function () {
  \t\tvar s = this.options.tileSize;
  \t\treturn s instanceof Point ? s : new Point(s, s);
  \t},

  \t_updateZIndex: function () {
  \t\tif (this._container && this.options.zIndex !== undefined && this.options.zIndex !== null) {
  \t\t\tthis._container.style.zIndex = this.options.zIndex;
  \t\t}
  \t},

  \t_setAutoZIndex: function (compare) {
  \t\t// go through all other layers of the same pane, set zIndex to max + 1 (front) or min - 1 (back)

  \t\tvar layers = this.getPane().children,
  \t\t    edgeZIndex = -compare(-Infinity, Infinity); // -Infinity for max, Infinity for min

  \t\tfor (var i = 0, len = layers.length, zIndex; i < len; i++) {

  \t\t\tzIndex = layers[i].style.zIndex;

  \t\t\tif (layers[i] !== this._container && zIndex) {
  \t\t\t\tedgeZIndex = compare(edgeZIndex, +zIndex);
  \t\t\t}
  \t\t}

  \t\tif (isFinite(edgeZIndex)) {
  \t\t\tthis.options.zIndex = edgeZIndex + compare(-1, 1);
  \t\t\tthis._updateZIndex();
  \t\t}
  \t},

  \t_updateOpacity: function () {
  \t\tif (!this._map) { return; }

  \t\t// IE doesn't inherit filter opacity properly, so we're forced to set it on tiles
  \t\tif (Browser.ielt9) { return; }

  \t\tsetOpacity(this._container, this.options.opacity);

  \t\tvar now = +new Date(),
  \t\t    nextFrame = false,
  \t\t    willPrune = false;

  \t\tfor (var key in this._tiles) {
  \t\t\tvar tile = this._tiles[key];
  \t\t\tif (!tile.current || !tile.loaded) { continue; }

  \t\t\tvar fade = Math.min(1, (now - tile.loaded) / 200);

  \t\t\tsetOpacity(tile.el, fade);
  \t\t\tif (fade < 1) {
  \t\t\t\tnextFrame = true;
  \t\t\t} else {
  \t\t\t\tif (tile.active) {
  \t\t\t\t\twillPrune = true;
  \t\t\t\t} else {
  \t\t\t\t\tthis._onOpaqueTile(tile);
  \t\t\t\t}
  \t\t\t\ttile.active = true;
  \t\t\t}
  \t\t}

  \t\tif (willPrune && !this._noPrune) { this._pruneTiles(); }

  \t\tif (nextFrame) {
  \t\t\tcancelAnimFrame(this._fadeFrame);
  \t\t\tthis._fadeFrame = requestAnimFrame(this._updateOpacity, this);
  \t\t}
  \t},

  \t_onOpaqueTile: falseFn,

  \t_initContainer: function () {
  \t\tif (this._container) { return; }

  \t\tthis._container = create\$1('div', 'leaflet-layer ' + (this.options.className || ''));
  \t\tthis._updateZIndex();

  \t\tif (this.options.opacity < 1) {
  \t\t\tthis._updateOpacity();
  \t\t}

  \t\tthis.getPane().appendChild(this._container);
  \t},

  \t_updateLevels: function () {

  \t\tvar zoom = this._tileZoom,
  \t\t    maxZoom = this.options.maxZoom;

  \t\tif (zoom === undefined) { return undefined; }

  \t\tfor (var z in this._levels) {
  \t\t\tz = Number(z);
  \t\t\tif (this._levels[z].el.children.length || z === zoom) {
  \t\t\t\tthis._levels[z].el.style.zIndex = maxZoom - Math.abs(zoom - z);
  \t\t\t\tthis._onUpdateLevel(z);
  \t\t\t} else {
  \t\t\t\tremove(this._levels[z].el);
  \t\t\t\tthis._removeTilesAtZoom(z);
  \t\t\t\tthis._onRemoveLevel(z);
  \t\t\t\tdelete this._levels[z];
  \t\t\t}
  \t\t}

  \t\tvar level = this._levels[zoom],
  \t\t    map = this._map;

  \t\tif (!level) {
  \t\t\tlevel = this._levels[zoom] = {};

  \t\t\tlevel.el = create\$1('div', 'leaflet-tile-container leaflet-zoom-animated', this._container);
  \t\t\tlevel.el.style.zIndex = maxZoom;

  \t\t\tlevel.origin = map.project(map.unproject(map.getPixelOrigin()), zoom).round();
  \t\t\tlevel.zoom = zoom;

  \t\t\tthis._setZoomTransform(level, map.getCenter(), map.getZoom());

  \t\t\t// force the browser to consider the newly added element for transition
  \t\t\tfalseFn(level.el.offsetWidth);

  \t\t\tthis._onCreateLevel(level);
  \t\t}

  \t\tthis._level = level;

  \t\treturn level;
  \t},

  \t_onUpdateLevel: falseFn,

  \t_onRemoveLevel: falseFn,

  \t_onCreateLevel: falseFn,

  \t_pruneTiles: function () {
  \t\tif (!this._map) {
  \t\t\treturn;
  \t\t}

  \t\tvar key, tile;

  \t\tvar zoom = this._map.getZoom();
  \t\tif (zoom > this.options.maxZoom ||
  \t\t\tzoom < this.options.minZoom) {
  \t\t\tthis._removeAllTiles();
  \t\t\treturn;
  \t\t}

  \t\tfor (key in this._tiles) {
  \t\t\ttile = this._tiles[key];
  \t\t\ttile.retain = tile.current;
  \t\t}

  \t\tfor (key in this._tiles) {
  \t\t\ttile = this._tiles[key];
  \t\t\tif (tile.current && !tile.active) {
  \t\t\t\tvar coords = tile.coords;
  \t\t\t\tif (!this._retainParent(coords.x, coords.y, coords.z, coords.z - 5)) {
  \t\t\t\t\tthis._retainChildren(coords.x, coords.y, coords.z, coords.z + 2);
  \t\t\t\t}
  \t\t\t}
  \t\t}

  \t\tfor (key in this._tiles) {
  \t\t\tif (!this._tiles[key].retain) {
  \t\t\t\tthis._removeTile(key);
  \t\t\t}
  \t\t}
  \t},

  \t_removeTilesAtZoom: function (zoom) {
  \t\tfor (var key in this._tiles) {
  \t\t\tif (this._tiles[key].coords.z !== zoom) {
  \t\t\t\tcontinue;
  \t\t\t}
  \t\t\tthis._removeTile(key);
  \t\t}
  \t},

  \t_removeAllTiles: function () {
  \t\tfor (var key in this._tiles) {
  \t\t\tthis._removeTile(key);
  \t\t}
  \t},

  \t_invalidateAll: function () {
  \t\tfor (var z in this._levels) {
  \t\t\tremove(this._levels[z].el);
  \t\t\tthis._onRemoveLevel(Number(z));
  \t\t\tdelete this._levels[z];
  \t\t}
  \t\tthis._removeAllTiles();

  \t\tthis._tileZoom = undefined;
  \t},

  \t_retainParent: function (x, y, z, minZoom) {
  \t\tvar x2 = Math.floor(x / 2),
  \t\t    y2 = Math.floor(y / 2),
  \t\t    z2 = z - 1,
  \t\t    coords2 = new Point(+x2, +y2);
  \t\tcoords2.z = +z2;

  \t\tvar key = this._tileCoordsToKey(coords2),
  \t\t    tile = this._tiles[key];

  \t\tif (tile && tile.active) {
  \t\t\ttile.retain = true;
  \t\t\treturn true;

  \t\t} else if (tile && tile.loaded) {
  \t\t\ttile.retain = true;
  \t\t}

  \t\tif (z2 > minZoom) {
  \t\t\treturn this._retainParent(x2, y2, z2, minZoom);
  \t\t}

  \t\treturn false;
  \t},

  \t_retainChildren: function (x, y, z, maxZoom) {

  \t\tfor (var i = 2 * x; i < 2 * x + 2; i++) {
  \t\t\tfor (var j = 2 * y; j < 2 * y + 2; j++) {

  \t\t\t\tvar coords = new Point(i, j);
  \t\t\t\tcoords.z = z + 1;

  \t\t\t\tvar key = this._tileCoordsToKey(coords),
  \t\t\t\t    tile = this._tiles[key];

  \t\t\t\tif (tile && tile.active) {
  \t\t\t\t\ttile.retain = true;
  \t\t\t\t\tcontinue;

  \t\t\t\t} else if (tile && tile.loaded) {
  \t\t\t\t\ttile.retain = true;
  \t\t\t\t}

  \t\t\t\tif (z + 1 < maxZoom) {
  \t\t\t\t\tthis._retainChildren(i, j, z + 1, maxZoom);
  \t\t\t\t}
  \t\t\t}
  \t\t}
  \t},

  \t_resetView: function (e) {
  \t\tvar animating = e && (e.pinch || e.flyTo);
  \t\tthis._setView(this._map.getCenter(), this._map.getZoom(), animating, animating);
  \t},

  \t_animateZoom: function (e) {
  \t\tthis._setView(e.center, e.zoom, true, e.noUpdate);
  \t},

  \t_clampZoom: function (zoom) {
  \t\tvar options = this.options;

  \t\tif (undefined !== options.minNativeZoom && zoom < options.minNativeZoom) {
  \t\t\treturn options.minNativeZoom;
  \t\t}

  \t\tif (undefined !== options.maxNativeZoom && options.maxNativeZoom < zoom) {
  \t\t\treturn options.maxNativeZoom;
  \t\t}

  \t\treturn zoom;
  \t},

  \t_setView: function (center, zoom, noPrune, noUpdate) {
  \t\tvar tileZoom = Math.round(zoom);
  \t\tif ((this.options.maxZoom !== undefined && tileZoom > this.options.maxZoom) ||
  \t\t    (this.options.minZoom !== undefined && tileZoom < this.options.minZoom)) {
  \t\t\ttileZoom = undefined;
  \t\t} else {
  \t\t\ttileZoom = this._clampZoom(tileZoom);
  \t\t}

  \t\tvar tileZoomChanged = this.options.updateWhenZooming && (tileZoom !== this._tileZoom);

  \t\tif (!noUpdate || tileZoomChanged) {

  \t\t\tthis._tileZoom = tileZoom;

  \t\t\tif (this._abortLoading) {
  \t\t\t\tthis._abortLoading();
  \t\t\t}

  \t\t\tthis._updateLevels();
  \t\t\tthis._resetGrid();

  \t\t\tif (tileZoom !== undefined) {
  \t\t\t\tthis._update(center);
  \t\t\t}

  \t\t\tif (!noPrune) {
  \t\t\t\tthis._pruneTiles();
  \t\t\t}

  \t\t\t// Flag to prevent _updateOpacity from pruning tiles during
  \t\t\t// a zoom anim or a pinch gesture
  \t\t\tthis._noPrune = !!noPrune;
  \t\t}

  \t\tthis._setZoomTransforms(center, zoom);
  \t},

  \t_setZoomTransforms: function (center, zoom) {
  \t\tfor (var i in this._levels) {
  \t\t\tthis._setZoomTransform(this._levels[i], center, zoom);
  \t\t}
  \t},

  \t_setZoomTransform: function (level, center, zoom) {
  \t\tvar scale = this._map.getZoomScale(zoom, level.zoom),
  \t\t    translate = level.origin.multiplyBy(scale)
  \t\t        .subtract(this._map._getNewPixelOrigin(center, zoom)).round();

  \t\tif (Browser.any3d) {
  \t\t\tsetTransform(level.el, translate, scale);
  \t\t} else {
  \t\t\tsetPosition(level.el, translate);
  \t\t}
  \t},

  \t_resetGrid: function () {
  \t\tvar map = this._map,
  \t\t    crs = map.options.crs,
  \t\t    tileSize = this._tileSize = this.getTileSize(),
  \t\t    tileZoom = this._tileZoom;

  \t\tvar bounds = this._map.getPixelWorldBounds(this._tileZoom);
  \t\tif (bounds) {
  \t\t\tthis._globalTileRange = this._pxBoundsToTileRange(bounds);
  \t\t}

  \t\tthis._wrapX = crs.wrapLng && !this.options.noWrap && [
  \t\t\tMath.floor(map.project([0, crs.wrapLng[0]], tileZoom).x / tileSize.x),
  \t\t\tMath.ceil(map.project([0, crs.wrapLng[1]], tileZoom).x / tileSize.y)
  \t\t];
  \t\tthis._wrapY = crs.wrapLat && !this.options.noWrap && [
  \t\t\tMath.floor(map.project([crs.wrapLat[0], 0], tileZoom).y / tileSize.x),
  \t\t\tMath.ceil(map.project([crs.wrapLat[1], 0], tileZoom).y / tileSize.y)
  \t\t];
  \t},

  \t_onMoveEnd: function () {
  \t\tif (!this._map || this._map._animatingZoom) { return; }

  \t\tthis._update();
  \t},

  \t_getTiledPixelBounds: function (center) {
  \t\tvar map = this._map,
  \t\t    mapZoom = map._animatingZoom ? Math.max(map._animateToZoom, map.getZoom()) : map.getZoom(),
  \t\t    scale = map.getZoomScale(mapZoom, this._tileZoom),
  \t\t    pixelCenter = map.project(center, this._tileZoom).floor(),
  \t\t    halfSize = map.getSize().divideBy(scale * 2);

  \t\treturn new Bounds(pixelCenter.subtract(halfSize), pixelCenter.add(halfSize));
  \t},

  \t// Private method to load tiles in the grid's active zoom level according to map bounds
  \t_update: function (center) {
  \t\tvar map = this._map;
  \t\tif (!map) { return; }
  \t\tvar zoom = this._clampZoom(map.getZoom());

  \t\tif (center === undefined) { center = map.getCenter(); }
  \t\tif (this._tileZoom === undefined) { return; }\t// if out of minzoom/maxzoom

  \t\tvar pixelBounds = this._getTiledPixelBounds(center),
  \t\t    tileRange = this._pxBoundsToTileRange(pixelBounds),
  \t\t    tileCenter = tileRange.getCenter(),
  \t\t    queue = [],
  \t\t    margin = this.options.keepBuffer,
  \t\t    noPruneRange = new Bounds(tileRange.getBottomLeft().subtract([margin, -margin]),
  \t\t                              tileRange.getTopRight().add([margin, -margin]));

  \t\t// Sanity check: panic if the tile range contains Infinity somewhere.
  \t\tif (!(isFinite(tileRange.min.x) &&
  \t\t      isFinite(tileRange.min.y) &&
  \t\t      isFinite(tileRange.max.x) &&
  \t\t      isFinite(tileRange.max.y))) { throw new Error('Attempted to load an infinite number of tiles'); }

  \t\tfor (var key in this._tiles) {
  \t\t\tvar c = this._tiles[key].coords;
  \t\t\tif (c.z !== this._tileZoom || !noPruneRange.contains(new Point(c.x, c.y))) {
  \t\t\t\tthis._tiles[key].current = false;
  \t\t\t}
  \t\t}

  \t\t// _update just loads more tiles. If the tile zoom level differs too much
  \t\t// from the map's, let _setView reset levels and prune old tiles.
  \t\tif (Math.abs(zoom - this._tileZoom) > 1) { this._setView(center, zoom); return; }

  \t\t// create a queue of coordinates to load tiles from
  \t\tfor (var j = tileRange.min.y; j <= tileRange.max.y; j++) {
  \t\t\tfor (var i = tileRange.min.x; i <= tileRange.max.x; i++) {
  \t\t\t\tvar coords = new Point(i, j);
  \t\t\t\tcoords.z = this._tileZoom;

  \t\t\t\tif (!this._isValidTile(coords)) { continue; }

  \t\t\t\tvar tile = this._tiles[this._tileCoordsToKey(coords)];
  \t\t\t\tif (tile) {
  \t\t\t\t\ttile.current = true;
  \t\t\t\t} else {
  \t\t\t\t\tqueue.push(coords);
  \t\t\t\t}
  \t\t\t}
  \t\t}

  \t\t// sort tile queue to load tiles in order of their distance to center
  \t\tqueue.sort(function (a, b) {
  \t\t\treturn a.distanceTo(tileCenter) - b.distanceTo(tileCenter);
  \t\t});

  \t\tif (queue.length !== 0) {
  \t\t\t// if it's the first batch of tiles to load
  \t\t\tif (!this._loading) {
  \t\t\t\tthis._loading = true;
  \t\t\t\t// @event loading: Event
  \t\t\t\t// Fired when the grid layer starts loading tiles.
  \t\t\t\tthis.fire('loading');
  \t\t\t}

  \t\t\t// create DOM fragment to append tiles in one batch
  \t\t\tvar fragment = document.createDocumentFragment();

  \t\t\tfor (i = 0; i < queue.length; i++) {
  \t\t\t\tthis._addTile(queue[i], fragment);
  \t\t\t}

  \t\t\tthis._level.el.appendChild(fragment);
  \t\t}
  \t},

  \t_isValidTile: function (coords) {
  \t\tvar crs = this._map.options.crs;

  \t\tif (!crs.infinite) {
  \t\t\t// don't load tile if it's out of bounds and not wrapped
  \t\t\tvar bounds = this._globalTileRange;
  \t\t\tif ((!crs.wrapLng && (coords.x < bounds.min.x || coords.x > bounds.max.x)) ||
  \t\t\t    (!crs.wrapLat && (coords.y < bounds.min.y || coords.y > bounds.max.y))) { return false; }
  \t\t}

  \t\tif (!this.options.bounds) { return true; }

  \t\t// don't load tile if it doesn't intersect the bounds in options
  \t\tvar tileBounds = this._tileCoordsToBounds(coords);
  \t\treturn toLatLngBounds(this.options.bounds).overlaps(tileBounds);
  \t},

  \t_keyToBounds: function (key) {
  \t\treturn this._tileCoordsToBounds(this._keyToTileCoords(key));
  \t},

  \t_tileCoordsToNwSe: function (coords) {
  \t\tvar map = this._map,
  \t\t    tileSize = this.getTileSize(),
  \t\t    nwPoint = coords.scaleBy(tileSize),
  \t\t    sePoint = nwPoint.add(tileSize),
  \t\t    nw = map.unproject(nwPoint, coords.z),
  \t\t    se = map.unproject(sePoint, coords.z);
  \t\treturn [nw, se];
  \t},

  \t// converts tile coordinates to its geographical bounds
  \t_tileCoordsToBounds: function (coords) {
  \t\tvar bp = this._tileCoordsToNwSe(coords),
  \t\t    bounds = new LatLngBounds(bp[0], bp[1]);

  \t\tif (!this.options.noWrap) {
  \t\t\tbounds = this._map.wrapLatLngBounds(bounds);
  \t\t}
  \t\treturn bounds;
  \t},
  \t// converts tile coordinates to key for the tile cache
  \t_tileCoordsToKey: function (coords) {
  \t\treturn coords.x + ':' + coords.y + ':' + coords.z;
  \t},

  \t// converts tile cache key to coordinates
  \t_keyToTileCoords: function (key) {
  \t\tvar k = key.split(':'),
  \t\t    coords = new Point(+k[0], +k[1]);
  \t\tcoords.z = +k[2];
  \t\treturn coords;
  \t},

  \t_removeTile: function (key) {
  \t\tvar tile = this._tiles[key];
  \t\tif (!tile) { return; }

  \t\tremove(tile.el);

  \t\tdelete this._tiles[key];

  \t\t// @event tileunload: TileEvent
  \t\t// Fired when a tile is removed (e.g. when a tile goes off the screen).
  \t\tthis.fire('tileunload', {
  \t\t\ttile: tile.el,
  \t\t\tcoords: this._keyToTileCoords(key)
  \t\t});
  \t},

  \t_initTile: function (tile) {
  \t\taddClass(tile, 'leaflet-tile');

  \t\tvar tileSize = this.getTileSize();
  \t\ttile.style.width = tileSize.x + 'px';
  \t\ttile.style.height = tileSize.y + 'px';

  \t\ttile.onselectstart = falseFn;
  \t\ttile.onmousemove = falseFn;

  \t\t// update opacity on tiles in IE7-8 because of filter inheritance problems
  \t\tif (Browser.ielt9 && this.options.opacity < 1) {
  \t\t\tsetOpacity(tile, this.options.opacity);
  \t\t}
  \t},

  \t_addTile: function (coords, container) {
  \t\tvar tilePos = this._getTilePos(coords),
  \t\t    key = this._tileCoordsToKey(coords);

  \t\tvar tile = this.createTile(this._wrapCoords(coords), bind(this._tileReady, this, coords));

  \t\tthis._initTile(tile);

  \t\t// if createTile is defined with a second argument (\"done\" callback),
  \t\t// we know that tile is async and will be ready later; otherwise
  \t\tif (this.createTile.length < 2) {
  \t\t\t// mark tile as ready, but delay one frame for opacity animation to happen
  \t\t\trequestAnimFrame(bind(this._tileReady, this, coords, null, tile));
  \t\t}

  \t\tsetPosition(tile, tilePos);

  \t\t// save tile in cache
  \t\tthis._tiles[key] = {
  \t\t\tel: tile,
  \t\t\tcoords: coords,
  \t\t\tcurrent: true
  \t\t};

  \t\tcontainer.appendChild(tile);
  \t\t// @event tileloadstart: TileEvent
  \t\t// Fired when a tile is requested and starts loading.
  \t\tthis.fire('tileloadstart', {
  \t\t\ttile: tile,
  \t\t\tcoords: coords
  \t\t});
  \t},

  \t_tileReady: function (coords, err, tile) {
  \t\tif (err) {
  \t\t\t// @event tileerror: TileErrorEvent
  \t\t\t// Fired when there is an error loading a tile.
  \t\t\tthis.fire('tileerror', {
  \t\t\t\terror: err,
  \t\t\t\ttile: tile,
  \t\t\t\tcoords: coords
  \t\t\t});
  \t\t}

  \t\tvar key = this._tileCoordsToKey(coords);

  \t\ttile = this._tiles[key];
  \t\tif (!tile) { return; }

  \t\ttile.loaded = +new Date();
  \t\tif (this._map._fadeAnimated) {
  \t\t\tsetOpacity(tile.el, 0);
  \t\t\tcancelAnimFrame(this._fadeFrame);
  \t\t\tthis._fadeFrame = requestAnimFrame(this._updateOpacity, this);
  \t\t} else {
  \t\t\ttile.active = true;
  \t\t\tthis._pruneTiles();
  \t\t}

  \t\tif (!err) {
  \t\t\taddClass(tile.el, 'leaflet-tile-loaded');

  \t\t\t// @event tileload: TileEvent
  \t\t\t// Fired when a tile loads.
  \t\t\tthis.fire('tileload', {
  \t\t\t\ttile: tile.el,
  \t\t\t\tcoords: coords
  \t\t\t});
  \t\t}

  \t\tif (this._noTilesToLoad()) {
  \t\t\tthis._loading = false;
  \t\t\t// @event load: Event
  \t\t\t// Fired when the grid layer loaded all visible tiles.
  \t\t\tthis.fire('load');

  \t\t\tif (Browser.ielt9 || !this._map._fadeAnimated) {
  \t\t\t\trequestAnimFrame(this._pruneTiles, this);
  \t\t\t} else {
  \t\t\t\t// Wait a bit more than 0.2 secs (the duration of the tile fade-in)
  \t\t\t\t// to trigger a pruning.
  \t\t\t\tsetTimeout(bind(this._pruneTiles, this), 250);
  \t\t\t}
  \t\t}
  \t},

  \t_getTilePos: function (coords) {
  \t\treturn coords.scaleBy(this.getTileSize()).subtract(this._level.origin);
  \t},

  \t_wrapCoords: function (coords) {
  \t\tvar newCoords = new Point(
  \t\t\tthis._wrapX ? wrapNum(coords.x, this._wrapX) : coords.x,
  \t\t\tthis._wrapY ? wrapNum(coords.y, this._wrapY) : coords.y);
  \t\tnewCoords.z = coords.z;
  \t\treturn newCoords;
  \t},

  \t_pxBoundsToTileRange: function (bounds) {
  \t\tvar tileSize = this.getTileSize();
  \t\treturn new Bounds(
  \t\t\tbounds.min.unscaleBy(tileSize).floor(),
  \t\t\tbounds.max.unscaleBy(tileSize).ceil().subtract([1, 1]));
  \t},

  \t_noTilesToLoad: function () {
  \t\tfor (var key in this._tiles) {
  \t\t\tif (!this._tiles[key].loaded) { return false; }
  \t\t}
  \t\treturn true;
  \t}
  });

  // @factory L.gridLayer(options?: GridLayer options)
  // Creates a new instance of GridLayer with the supplied options.
  function gridLayer(options) {
  \treturn new GridLayer(options);
  }

  /*
   * @class TileLayer
   * @inherits GridLayer
   * @aka L.TileLayer
   * Used to load and display tile layers on the map. Note that most tile servers require attribution, which you can set under `Layer`. Extends `GridLayer`.
   *
   * @example
   *
   * ```js
   * L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar', attribution: '&copy; <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors'}).addTo(map);
   * ```
   *
   * @section URL template
   * @example
   *
   * A string of the following form:
   *
   * ```
   * 'https://{s}.somedomain.com/blabla/{z}/{x}/{y}{r}.png'
   * ```
   *
   * `{s}` means one of the available subdomains (used sequentially to help with browser parallel requests per domain limitation; subdomain values are specified in options; `a`, `b` or `c` by default, can be omitted), `{z}` — zoom level, `{x}` and `{y}` — tile coordinates. `{r}` can be used to add \"&commat;2x\" to the URL to load retina tiles.
   *
   * You can use custom keys in the template, which will be [evaluated](#util-template) from TileLayer options, like this:
   *
   * ```
   * L.tileLayer('https://{s}.somedomain.com/{foo}/{z}/{x}/{y}.png', {foo: 'bar'});
   * ```
   */


  var TileLayer = GridLayer.extend({

  \t// @section
  \t// @aka TileLayer options
  \toptions: {
  \t\t// @option minZoom: Number = 0
  \t\t// The minimum zoom level down to which this layer will be displayed (inclusive).
  \t\tminZoom: 0,

  \t\t// @option maxZoom: Number = 18
  \t\t// The maximum zoom level up to which this layer will be displayed (inclusive).
  \t\tmaxZoom: 18,

  \t\t// @option subdomains: String|String[] = 'abc'
  \t\t// Subdomains of the tile service. Can be passed in the form of one string (where each letter is a subdomain name) or an array of strings.
  \t\tsubdomains: 'abc',

  \t\t// @option errorTileUrl: String = ''
  \t\t// URL to the tile image to show in place of the tile that failed to load.
  \t\terrorTileUrl: '',

  \t\t// @option zoomOffset: Number = 0
  \t\t// The zoom number used in tile URLs will be offset with this value.
  \t\tzoomOffset: 0,

  \t\t// @option tms: Boolean = false
  \t\t// If `true`, inverses Y axis numbering for tiles (turn this on for [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) services).
  \t\ttms: false,

  \t\t// @option zoomReverse: Boolean = false
  \t\t// If set to true, the zoom number used in tile URLs will be reversed (`maxZoom - zoom` instead of `zoom`)
  \t\tzoomReverse: false,

  \t\t// @option detectRetina: Boolean = false
  \t\t// If `true` and user is on a retina display, it will request four tiles of half the specified size and a bigger zoom level in place of one to utilize the high resolution.
  \t\tdetectRetina: false,

  \t\t// @option crossOrigin: Boolean|String = false
  \t\t// Whether the crossOrigin attribute will be added to the tiles.
  \t\t// If a String is provided, all tiles will have their crossOrigin attribute set to the String provided. This is needed if you want to access tile pixel data.
  \t\t// Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values.
  \t\tcrossOrigin: false,

  \t\t// @option referrerPolicy: Boolean|String = false
  \t\t// Whether the referrerPolicy attribute will be added to the tiles.
  \t\t// If a String is provided, all tiles will have their referrerPolicy attribute set to the String provided.
  \t\t// This may be needed if your map's rendering context has a strict default but your tile provider expects a valid referrer
  \t\t// (e.g. to validate an API token).
  \t\t// Refer to [HTMLImageElement.referrerPolicy](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/referrerPolicy) for valid String values.
  \t\treferrerPolicy: false
  \t},

  \tinitialize: function (url, options) {

  \t\tthis._url = url;

  \t\toptions = setOptions(this, options);

  \t\t// detecting retina displays, adjusting tileSize and zoom levels
  \t\tif (options.detectRetina && Browser.retina && options.maxZoom > 0) {

  \t\t\toptions.tileSize = Math.floor(options.tileSize / 2);

  \t\t\tif (!options.zoomReverse) {
  \t\t\t\toptions.zoomOffset++;
  \t\t\t\toptions.maxZoom = Math.max(options.minZoom, options.maxZoom - 1);
  \t\t\t} else {
  \t\t\t\toptions.zoomOffset--;
  \t\t\t\toptions.minZoom = Math.min(options.maxZoom, options.minZoom + 1);
  \t\t\t}

  \t\t\toptions.minZoom = Math.max(0, options.minZoom);
  \t\t} else if (!options.zoomReverse) {
  \t\t\t// make sure maxZoom is gte minZoom
  \t\t\toptions.maxZoom = Math.max(options.minZoom, options.maxZoom);
  \t\t} else {
  \t\t\t// make sure minZoom is lte maxZoom
  \t\t\toptions.minZoom = Math.min(options.maxZoom, options.minZoom);
  \t\t}

  \t\tif (typeof options.subdomains === 'string') {
  \t\t\toptions.subdomains = options.subdomains.split('');
  \t\t}

  \t\tthis.on('tileunload', this._onTileRemove);
  \t},

  \t// @method setUrl(url: String, noRedraw?: Boolean): this
  \t// Updates the layer's URL template and redraws it (unless `noRedraw` is set to `true`).
  \t// If the URL does not change, the layer will not be redrawn unless
  \t// the noRedraw parameter is set to false.
  \tsetUrl: function (url, noRedraw) {
  \t\tif (this._url === url && noRedraw === undefined) {
  \t\t\tnoRedraw = true;
  \t\t}

  \t\tthis._url = url;

  \t\tif (!noRedraw) {
  \t\t\tthis.redraw();
  \t\t}
  \t\treturn this;
  \t},

  \t// @method createTile(coords: Object, done?: Function): HTMLElement
  \t// Called only internally, overrides GridLayer's [`createTile()`](#gridlayer-createtile)
  \t// to return an `<img>` HTML element with the appropriate image URL given `coords`. The `done`
  \t// callback is called when the tile has been loaded.
  \tcreateTile: function (coords, done) {
  \t\tvar tile = document.createElement('img');

  \t\ton(tile, 'load', bind(this._tileOnLoad, this, done, tile));
  \t\ton(tile, 'error', bind(this._tileOnError, this, done, tile));

  \t\tif (this.options.crossOrigin || this.options.crossOrigin === '') {
  \t\t\ttile.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin;
  \t\t}

  \t\t// for this new option we follow the documented behavior
  \t\t// more closely by only setting the property when string
  \t\tif (typeof this.options.referrerPolicy === 'string') {
  \t\t\ttile.referrerPolicy = this.options.referrerPolicy;
  \t\t}

  \t\t// The alt attribute is set to the empty string,
  \t\t// allowing screen readers to ignore the decorative image tiles.
  \t\t// https://www.w3.org/WAI/tutorials/images/decorative/
  \t\t// https://www.w3.org/TR/html-aria/#el-img-empty-alt
  \t\ttile.alt = '';

  \t\ttile.src = this.getTileUrl(coords);

  \t\treturn tile;
  \t},

  \t// @section Extension methods
  \t// @uninheritable
  \t// Layers extending `TileLayer` might reimplement the following method.
  \t// @method getTileUrl(coords: Object): String
  \t// Called only internally, returns the URL for a tile given its coordinates.
  \t// Classes extending `TileLayer` can override this function to provide custom tile URL naming schemes.
  \tgetTileUrl: function (coords) {
  \t\tvar data = {
  \t\t\tr: Browser.retina ? '@2x' : '',
  \t\t\ts: this._getSubdomain(coords),
  \t\t\tx: coords.x,
  \t\t\ty: coords.y,
  \t\t\tz: this._getZoomForUrl()
  \t\t};
  \t\tif (this._map && !this._map.options.crs.infinite) {
  \t\t\tvar invertedY = this._globalTileRange.max.y - coords.y;
  \t\t\tif (this.options.tms) {
  \t\t\t\tdata['y'] = invertedY;
  \t\t\t}
  \t\t\tdata['-y'] = invertedY;
  \t\t}

  \t\treturn template(this._url, extend(data, this.options));
  \t},

  \t_tileOnLoad: function (done, tile) {
  \t\t// For https://github.com/Leaflet/Leaflet/issues/3332
  \t\tif (Browser.ielt9) {
  \t\t\tsetTimeout(bind(done, this, null, tile), 0);
  \t\t} else {
  \t\t\tdone(null, tile);
  \t\t}
  \t},

  \t_tileOnError: function (done, tile, e) {
  \t\tvar errorUrl = this.options.errorTileUrl;
  \t\tif (errorUrl && tile.getAttribute('src') !== errorUrl) {
  \t\t\ttile.src = errorUrl;
  \t\t}
  \t\tdone(e, tile);
  \t},

  \t_onTileRemove: function (e) {
  \t\te.tile.onload = null;
  \t},

  \t_getZoomForUrl: function () {
  \t\tvar zoom = this._tileZoom,
  \t\tmaxZoom = this.options.maxZoom,
  \t\tzoomReverse = this.options.zoomReverse,
  \t\tzoomOffset = this.options.zoomOffset;

  \t\tif (zoomReverse) {
  \t\t\tzoom = maxZoom - zoom;
  \t\t}

  \t\treturn zoom + zoomOffset;
  \t},

  \t_getSubdomain: function (tilePoint) {
  \t\tvar index = Math.abs(tilePoint.x + tilePoint.y) % this.options.subdomains.length;
  \t\treturn this.options.subdomains[index];
  \t},

  \t// stops loading all tiles in the background layer
  \t_abortLoading: function () {
  \t\tvar i, tile;
  \t\tfor (i in this._tiles) {
  \t\t\tif (this._tiles[i].coords.z !== this._tileZoom) {
  \t\t\t\ttile = this._tiles[i].el;

  \t\t\t\ttile.onload = falseFn;
  \t\t\t\ttile.onerror = falseFn;

  \t\t\t\tif (!tile.complete) {
  \t\t\t\t\ttile.src = emptyImageUrl;
  \t\t\t\t\tvar coords = this._tiles[i].coords;
  \t\t\t\t\tremove(tile);
  \t\t\t\t\tdelete this._tiles[i];
  \t\t\t\t\t// @event tileabort: TileEvent
  \t\t\t\t\t// Fired when a tile was loading but is now not wanted.
  \t\t\t\t\tthis.fire('tileabort', {
  \t\t\t\t\t\ttile: tile,
  \t\t\t\t\t\tcoords: coords
  \t\t\t\t\t});
  \t\t\t\t}
  \t\t\t}
  \t\t}
  \t},

  \t_removeTile: function (key) {
  \t\tvar tile = this._tiles[key];
  \t\tif (!tile) { return; }

  \t\t// Cancels any pending http requests associated with the tile
  \t\ttile.el.setAttribute('src', emptyImageUrl);

  \t\treturn GridLayer.prototype._removeTile.call(this, key);
  \t},

  \t_tileReady: function (coords, err, tile) {
  \t\tif (!this._map || (tile && tile.getAttribute('src') === emptyImageUrl)) {
  \t\t\treturn;
  \t\t}

  \t\treturn GridLayer.prototype._tileReady.call(this, coords, err, tile);
  \t}
  });


  // @factory L.tilelayer(urlTemplate: String, options?: TileLayer options)
  // Instantiates a tile layer object given a `URL template` and optionally an options object.

  function tileLayer(url, options) {
  \treturn new TileLayer(url, options);
  }

  /*
   * @class TileLayer.WMS
   * @inherits TileLayer
   * @aka L.TileLayer.WMS
   * Used to display [WMS](https://en.wikipedia.org/wiki/Web_Map_Service) services as tile layers on the map. Extends `TileLayer`.
   *
   * @example
   *
   * ```js
   * var nexrad = L.tileLayer.wms(\"http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi\", {
   * \tlayers: 'nexrad-n0r-900913',
   * \tformat: 'image/png',
   * \ttransparent: true,
   * \tattribution: \"Weather data © 2012 IEM Nexrad\"
   * });
   * ```
   */

  var TileLayerWMS = TileLayer.extend({

  \t// @section
  \t// @aka TileLayer.WMS options
  \t// If any custom options not documented here are used, they will be sent to the
  \t// WMS server as extra parameters in each request URL. This can be useful for
  \t// [non-standard vendor WMS parameters](https://docs.geoserver.org/stable/en/user/services/wms/vendor.html).
  \tdefaultWmsParams: {
  \t\tservice: 'WMS',
  \t\trequest: 'GetMap',

  \t\t// @option layers: String = ''
  \t\t// **(required)** Comma-separated list of WMS layers to show.
  \t\tlayers: '',

  \t\t// @option styles: String = ''
  \t\t// Comma-separated list of WMS styles.
  \t\tstyles: '',

  \t\t// @option format: String = 'image/jpeg'
  \t\t// WMS image format (use `'image/png'` for layers with transparency).
  \t\tformat: 'image/jpeg',

  \t\t// @option transparent: Boolean = false
  \t\t// If `true`, the WMS service will return images with transparency.
  \t\ttransparent: false,

  \t\t// @option version: String = '1.1.1'
  \t\t// Version of the WMS service to use
  \t\tversion: '1.1.1'
  \t},

  \toptions: {
  \t\t// @option crs: CRS = null
  \t\t// Coordinate Reference System to use for the WMS requests, defaults to
  \t\t// map CRS. Don't change this if you're not sure what it means.
  \t\tcrs: null,

  \t\t// @option uppercase: Boolean = false
  \t\t// If `true`, WMS request parameter keys will be uppercase.
  \t\tuppercase: false
  \t},

  \tinitialize: function (url, options) {

  \t\tthis._url = url;

  \t\tvar wmsParams = extend({}, this.defaultWmsParams);

  \t\t// all keys that are not TileLayer options go to WMS params
  \t\tfor (var i in options) {
  \t\t\tif (!(i in this.options)) {
  \t\t\t\twmsParams[i] = options[i];
  \t\t\t}
  \t\t}

  \t\toptions = setOptions(this, options);

  \t\tvar realRetina = options.detectRetina && Browser.retina ? 2 : 1;
  \t\tvar tileSize = this.getTileSize();
  \t\twmsParams.width = tileSize.x * realRetina;
  \t\twmsParams.height = tileSize.y * realRetina;

  \t\tthis.wmsParams = wmsParams;
  \t},

  \tonAdd: function (map) {

  \t\tthis._crs = this.options.crs || map.options.crs;
  \t\tthis._wmsVersion = parseFloat(this.wmsParams.version);

  \t\tvar projectionKey = this._wmsVersion >= 1.3 ? 'crs' : 'srs';
  \t\tthis.wmsParams[projectionKey] = this._crs.code;

  \t\tTileLayer.prototype.onAdd.call(this, map);
  \t},

  \tgetTileUrl: function (coords) {

  \t\tvar tileBounds = this._tileCoordsToNwSe(coords),
  \t\t    crs = this._crs,
  \t\t    bounds = toBounds(crs.project(tileBounds[0]), crs.project(tileBounds[1])),
  \t\t    min = bounds.min,
  \t\t    max = bounds.max,
  \t\t    bbox = (this._wmsVersion >= 1.3 && this._crs === EPSG4326 ?
  \t\t    [min.y, min.x, max.y, max.x] :
  \t\t    [min.x, min.y, max.x, max.y]).join(','),
  \t\t    url = TileLayer.prototype.getTileUrl.call(this, coords);
  \t\treturn url +
  \t\t\tgetParamString(this.wmsParams, url, this.options.uppercase) +
  \t\t\t(this.options.uppercase ? '&BBOX=' : '&bbox=') + bbox;
  \t},

  \t// @method setParams(params: Object, noRedraw?: Boolean): this
  \t// Merges an object with the new parameters and re-requests tiles on the current screen (unless `noRedraw` was set to true).
  \tsetParams: function (params, noRedraw) {

  \t\textend(this.wmsParams, params);

  \t\tif (!noRedraw) {
  \t\t\tthis.redraw();
  \t\t}

  \t\treturn this;
  \t}
  });


  // @factory L.tileLayer.wms(baseUrl: String, options: TileLayer.WMS options)
  // Instantiates a WMS tile layer object given a base URL of the WMS service and a WMS parameters/options object.
  function tileLayerWMS(url, options) {
  \treturn new TileLayerWMS(url, options);
  }

  TileLayer.WMS = TileLayerWMS;
  tileLayer.wms = tileLayerWMS;

  /*
   * @class Renderer
   * @inherits Layer
   * @aka L.Renderer
   *
   * Base class for vector renderer implementations (`SVG`, `Canvas`). Handles the
   * DOM container of the renderer, its bounds, and its zoom animation.
   *
   * A `Renderer` works as an implicit layer group for all `Path`s - the renderer
   * itself can be added or removed to the map. All paths use a renderer, which can
   * be implicit (the map will decide the type of renderer and use it automatically)
   * or explicit (using the [`renderer`](#path-renderer) option of the path).
   *
   * Do not use this class directly, use `SVG` and `Canvas` instead.
   *
   * @event update: Event
   * Fired when the renderer updates its bounds, center and zoom, for example when
   * its map has moved
   */

  var Renderer = Layer.extend({

  \t// @section
  \t// @aka Renderer options
  \toptions: {
  \t\t// @option padding: Number = 0.1
  \t\t// How much to extend the clip area around the map view (relative to its size)
  \t\t// e.g. 0.1 would be 10% of map view in each direction
  \t\tpadding: 0.1
  \t},

  \tinitialize: function (options) {
  \t\tsetOptions(this, options);
  \t\tstamp(this);
  \t\tthis._layers = this._layers || {};
  \t},

  \tonAdd: function () {
  \t\tif (!this._container) {
  \t\t\tthis._initContainer(); // defined by renderer implementations

  \t\t\t// always keep transform-origin as 0 0
  \t\t\taddClass(this._container, 'leaflet-zoom-animated');
  \t\t}

  \t\tthis.getPane().appendChild(this._container);
  \t\tthis._update();
  \t\tthis.on('update', this._updatePaths, this);
  \t},

  \tonRemove: function () {
  \t\tthis.off('update', this._updatePaths, this);
  \t\tthis._destroyContainer();
  \t},

  \tgetEvents: function () {
  \t\tvar events = {
  \t\t\tviewreset: this._reset,
  \t\t\tzoom: this._onZoom,
  \t\t\tmoveend: this._update,
  \t\t\tzoomend: this._onZoomEnd
  \t\t};
  \t\tif (this._zoomAnimated) {
  \t\t\tevents.zoomanim = this._onAnimZoom;
  \t\t}
  \t\treturn events;
  \t},

  \t_onAnimZoom: function (ev) {
  \t\tthis._updateTransform(ev.center, ev.zoom);
  \t},

  \t_onZoom: function () {
  \t\tthis._updateTransform(this._map.getCenter(), this._map.getZoom());
  \t},

  \t_updateTransform: function (center, zoom) {
  \t\tvar scale = this._map.getZoomScale(zoom, this._zoom),
  \t\t    viewHalf = this._map.getSize().multiplyBy(0.5 + this.options.padding),
  \t\t    currentCenterPoint = this._map.project(this._center, zoom),

  \t\t    topLeftOffset = viewHalf.multiplyBy(-scale).add(currentCenterPoint)
  \t\t\t\t  .subtract(this._map._getNewPixelOrigin(center, zoom));

  \t\tif (Browser.any3d) {
  \t\t\tsetTransform(this._container, topLeftOffset, scale);
  \t\t} else {
  \t\t\tsetPosition(this._container, topLeftOffset);
  \t\t}
  \t},

  \t_reset: function () {
  \t\tthis._update();
  \t\tthis._updateTransform(this._center, this._zoom);

  \t\tfor (var id in this._layers) {
  \t\t\tthis._layers[id]._reset();
  \t\t}
  \t},

  \t_onZoomEnd: function () {
  \t\tfor (var id in this._layers) {
  \t\t\tthis._layers[id]._project();
  \t\t}
  \t},

  \t_updatePaths: function () {
  \t\tfor (var id in this._layers) {
  \t\t\tthis._layers[id]._update();
  \t\t}
  \t},

  \t_update: function () {
  \t\t// Update pixel bounds of renderer container (for positioning/sizing/clipping later)
  \t\t// Subclasses are responsible of firing the 'update' event.
  \t\tvar p = this.options.padding,
  \t\t    size = this._map.getSize(),
  \t\t    min = this._map.containerPointToLayerPoint(size.multiplyBy(-p)).round();

  \t\tthis._bounds = new Bounds(min, min.add(size.multiplyBy(1 + p * 2)).round());

  \t\tthis._center = this._map.getCenter();
  \t\tthis._zoom = this._map.getZoom();
  \t}
  });

  /*
   * @class Canvas
   * @inherits Renderer
   * @aka L.Canvas
   *
   * Allows vector layers to be displayed with [`<canvas>`](https://developer.mozilla.org/docs/Web/API/Canvas_API).
   * Inherits `Renderer`.
   *
   * Due to [technical limitations](https://caniuse.com/canvas), Canvas is not
   * available in all web browsers, notably IE8, and overlapping geometries might
   * not display properly in some edge cases.
   *
   * @example
   *
   * Use Canvas by default for all paths in the map:
   *
   * ```js
   * var map = L.map('map', {
   * \trenderer: L.canvas()
   * });
   * ```
   *
   * Use a Canvas renderer with extra padding for specific vector geometries:
   *
   * ```js
   * var map = L.map('map');
   * var myRenderer = L.canvas({ padding: 0.5 });
   * var line = L.polyline( coordinates, { renderer: myRenderer } );
   * var circle = L.circle( center, { renderer: myRenderer } );
   * ```
   */

  var Canvas = Renderer.extend({

  \t// @section
  \t// @aka Canvas options
  \toptions: {
  \t\t// @option tolerance: Number = 0
  \t\t// How much to extend the click tolerance around a path/object on the map.
  \t\ttolerance: 0
  \t},

  \tgetEvents: function () {
  \t\tvar events = Renderer.prototype.getEvents.call(this);
  \t\tevents.viewprereset = this._onViewPreReset;
  \t\treturn events;
  \t},

  \t_onViewPreReset: function () {
  \t\t// Set a flag so that a viewprereset+moveend+viewreset only updates&redraws once
  \t\tthis._postponeUpdatePaths = true;
  \t},

  \tonAdd: function () {
  \t\tRenderer.prototype.onAdd.call(this);

  \t\t// Redraw vectors since canvas is cleared upon removal,
  \t\t// in case of removing the renderer itself from the map.
  \t\tthis._draw();
  \t},

  \t_initContainer: function () {
  \t\tvar container = this._container = document.createElement('canvas');

  \t\ton(container, 'mousemove', this._onMouseMove, this);
  \t\ton(container, 'click dblclick mousedown mouseup contextmenu', this._onClick, this);
  \t\ton(container, 'mouseout', this._handleMouseOut, this);
  \t\tcontainer['_leaflet_disable_events'] = true;

  \t\tthis._ctx = container.getContext('2d');
  \t},

  \t_destroyContainer: function () {
  \t\tcancelAnimFrame(this._redrawRequest);
  \t\tdelete this._ctx;
  \t\tremove(this._container);
  \t\toff(this._container);
  \t\tdelete this._container;
  \t},

  \t_updatePaths: function () {
  \t\tif (this._postponeUpdatePaths) { return; }

  \t\tvar layer;
  \t\tthis._redrawBounds = null;
  \t\tfor (var id in this._layers) {
  \t\t\tlayer = this._layers[id];
  \t\t\tlayer._update();
  \t\t}
  \t\tthis._redraw();
  \t},

  \t_update: function () {
  \t\tif (this._map._animatingZoom && this._bounds) { return; }

  \t\tRenderer.prototype._update.call(this);

  \t\tvar b = this._bounds,
  \t\t    container = this._container,
  \t\t    size = b.getSize(),
  \t\t    m = Browser.retina ? 2 : 1;

  \t\tsetPosition(container, b.min);

  \t\t// set canvas size (also clearing it); use double size on retina
  \t\tcontainer.width = m * size.x;
  \t\tcontainer.height = m * size.y;
  \t\tcontainer.style.width = size.x + 'px';
  \t\tcontainer.style.height = size.y + 'px';

  \t\tif (Browser.retina) {
  \t\t\tthis._ctx.scale(2, 2);
  \t\t}

  \t\t// translate so we use the same path coordinates after canvas element moves
  \t\tthis._ctx.translate(-b.min.x, -b.min.y);

  \t\t// Tell paths to redraw themselves
  \t\tthis.fire('update');
  \t},

  \t_reset: function () {
  \t\tRenderer.prototype._reset.call(this);

  \t\tif (this._postponeUpdatePaths) {
  \t\t\tthis._postponeUpdatePaths = false;
  \t\t\tthis._updatePaths();
  \t\t}
  \t},

  \t_initPath: function (layer) {
  \t\tthis._updateDashArray(layer);
  \t\tthis._layers[stamp(layer)] = layer;

  \t\tvar order = layer._order = {
  \t\t\tlayer: layer,
  \t\t\tprev: this._drawLast,
  \t\t\tnext: null
  \t\t};
  \t\tif (this._drawLast) { this._drawLast.next = order; }
  \t\tthis._drawLast = order;
  \t\tthis._drawFirst = this._drawFirst || this._drawLast;
  \t},

  \t_addPath: function (layer) {
  \t\tthis._requestRedraw(layer);
  \t},

  \t_removePath: function (layer) {
  \t\tvar order = layer._order;
  \t\tvar next = order.next;
  \t\tvar prev = order.prev;

  \t\tif (next) {
  \t\t\tnext.prev = prev;
  \t\t} else {
  \t\t\tthis._drawLast = prev;
  \t\t}
  \t\tif (prev) {
  \t\t\tprev.next = next;
  \t\t} else {
  \t\t\tthis._drawFirst = next;
  \t\t}

  \t\tdelete layer._order;

  \t\tdelete this._layers[stamp(layer)];

  \t\tthis._requestRedraw(layer);
  \t},

  \t_updatePath: function (layer) {
  \t\t// Redraw the union of the layer's old pixel
  \t\t// bounds and the new pixel bounds.
  \t\tthis._extendRedrawBounds(layer);
  \t\tlayer._project();
  \t\tlayer._update();
  \t\t// The redraw will extend the redraw bounds
  \t\t// with the new pixel bounds.
  \t\tthis._requestRedraw(layer);
  \t},

  \t_updateStyle: function (layer) {
  \t\tthis._updateDashArray(layer);
  \t\tthis._requestRedraw(layer);
  \t},

  \t_updateDashArray: function (layer) {
  \t\tif (typeof layer.options.dashArray === 'string') {
  \t\t\tvar parts = layer.options.dashArray.split(/[, ]+/),
  \t\t\t    dashArray = [],
  \t\t\t    dashValue,
  \t\t\t    i;
  \t\t\tfor (i = 0; i < parts.length; i++) {
  \t\t\t\tdashValue = Number(parts[i]);
  \t\t\t\t// Ignore dash array containing invalid lengths
  \t\t\t\tif (isNaN(dashValue)) { return; }
  \t\t\t\tdashArray.push(dashValue);
  \t\t\t}
  \t\t\tlayer.options._dashArray = dashArray;
  \t\t} else {
  \t\t\tlayer.options._dashArray = layer.options.dashArray;
  \t\t}
  \t},

  \t_requestRedraw: function (layer) {
  \t\tif (!this._map) { return; }

  \t\tthis._extendRedrawBounds(layer);
  \t\tthis._redrawRequest = this._redrawRequest || requestAnimFrame(this._redraw, this);
  \t},

  \t_extendRedrawBounds: function (layer) {
  \t\tif (layer._pxBounds) {
  \t\t\tvar padding = (layer.options.weight || 0) + 1;
  \t\t\tthis._redrawBounds = this._redrawBounds || new Bounds();
  \t\t\tthis._redrawBounds.extend(layer._pxBounds.min.subtract([padding, padding]));
  \t\t\tthis._redrawBounds.extend(layer._pxBounds.max.add([padding, padding]));
  \t\t}
  \t},

  \t_redraw: function () {
  \t\tthis._redrawRequest = null;

  \t\tif (this._redrawBounds) {
  \t\t\tthis._redrawBounds.min._floor();
  \t\t\tthis._redrawBounds.max._ceil();
  \t\t}

  \t\tthis._clear(); // clear layers in redraw bounds
  \t\tthis._draw(); // draw layers

  \t\tthis._redrawBounds = null;
  \t},

  \t_clear: function () {
  \t\tvar bounds = this._redrawBounds;
  \t\tif (bounds) {
  \t\t\tvar size = bounds.getSize();
  \t\t\tthis._ctx.clearRect(bounds.min.x, bounds.min.y, size.x, size.y);
  \t\t} else {
  \t\t\tthis._ctx.save();
  \t\t\tthis._ctx.setTransform(1, 0, 0, 1, 0, 0);
  \t\t\tthis._ctx.clearRect(0, 0, this._container.width, this._container.height);
  \t\t\tthis._ctx.restore();
  \t\t}
  \t},

  \t_draw: function () {
  \t\tvar layer, bounds = this._redrawBounds;
  \t\tthis._ctx.save();
  \t\tif (bounds) {
  \t\t\tvar size = bounds.getSize();
  \t\t\tthis._ctx.beginPath();
  \t\t\tthis._ctx.rect(bounds.min.x, bounds.min.y, size.x, size.y);
  \t\t\tthis._ctx.clip();
  \t\t}

  \t\tthis._drawing = true;

  \t\tfor (var order = this._drawFirst; order; order = order.next) {
  \t\t\tlayer = order.layer;
  \t\t\tif (!bounds || (layer._pxBounds && layer._pxBounds.intersects(bounds))) {
  \t\t\t\tlayer._updatePath();
  \t\t\t}
  \t\t}

  \t\tthis._drawing = false;

  \t\tthis._ctx.restore();  // Restore state before clipping.
  \t},

  \t_updatePoly: function (layer, closed) {
  \t\tif (!this._drawing) { return; }

  \t\tvar i, j, len2, p,
  \t\t    parts = layer._parts,
  \t\t    len = parts.length,
  \t\t    ctx = this._ctx;

  \t\tif (!len) { return; }

  \t\tctx.beginPath();

  \t\tfor (i = 0; i < len; i++) {
  \t\t\tfor (j = 0, len2 = parts[i].length; j < len2; j++) {
  \t\t\t\tp = parts[i][j];
  \t\t\t\tctx[j ? 'lineTo' : 'moveTo'](p.x, p.y);
  \t\t\t}
  \t\t\tif (closed) {
  \t\t\t\tctx.closePath();
  \t\t\t}
  \t\t}

  \t\tthis._fillStroke(ctx, layer);

  \t\t// TODO optimization: 1 fill/stroke for all features with equal style instead of 1 for each feature
  \t},

  \t_updateCircle: function (layer) {

  \t\tif (!this._drawing || layer._empty()) { return; }

  \t\tvar p = layer._point,
  \t\t    ctx = this._ctx,
  \t\t    r = Math.max(Math.round(layer._radius), 1),
  \t\t    s = (Math.max(Math.round(layer._radiusY), 1) || r) / r;

  \t\tif (s !== 1) {
  \t\t\tctx.save();
  \t\t\tctx.scale(1, s);
  \t\t}

  \t\tctx.beginPath();
  \t\tctx.arc(p.x, p.y / s, r, 0, Math.PI * 2, false);

  \t\tif (s !== 1) {
  \t\t\tctx.restore();
  \t\t}

  \t\tthis._fillStroke(ctx, layer);
  \t},

  \t_fillStroke: function (ctx, layer) {
  \t\tvar options = layer.options;

  \t\tif (options.fill) {
  \t\t\tctx.globalAlpha = options.fillOpacity;
  \t\t\tctx.fillStyle = options.fillColor || options.color;
  \t\t\tctx.fill(options.fillRule || 'evenodd');
  \t\t}

  \t\tif (options.stroke && options.weight !== 0) {
  \t\t\tif (ctx.setLineDash) {
  \t\t\t\tctx.setLineDash(layer.options && layer.options._dashArray || []);
  \t\t\t}
  \t\t\tctx.globalAlpha = options.opacity;
  \t\t\tctx.lineWidth = options.weight;
  \t\t\tctx.strokeStyle = options.color;
  \t\t\tctx.lineCap = options.lineCap;
  \t\t\tctx.lineJoin = options.lineJoin;
  \t\t\tctx.stroke();
  \t\t}
  \t},

  \t// Canvas obviously doesn't have mouse events for individual drawn objects,
  \t// so we emulate that by calculating what's under the mouse on mousemove/click manually

  \t_onClick: function (e) {
  \t\tvar point = this._map.mouseEventToLayerPoint(e), layer, clickedLayer;

  \t\tfor (var order = this._drawFirst; order; order = order.next) {
  \t\t\tlayer = order.layer;
  \t\t\tif (layer.options.interactive && layer._containsPoint(point)) {
  \t\t\t\tif (!(e.type === 'click' || e.type === 'preclick') || !this._map._draggableMoved(layer)) {
  \t\t\t\t\tclickedLayer = layer;
  \t\t\t\t}
  \t\t\t}
  \t\t}
  \t\tthis._fireEvent(clickedLayer ? [clickedLayer] : false, e);
  \t},

  \t_onMouseMove: function (e) {
  \t\tif (!this._map || this._map.dragging.moving() || this._map._animatingZoom) { return; }

  \t\tvar point = this._map.mouseEventToLayerPoint(e);
  \t\tthis._handleMouseHover(e, point);
  \t},


  \t_handleMouseOut: function (e) {
  \t\tvar layer = this._hoveredLayer;
  \t\tif (layer) {
  \t\t\t// if we're leaving the layer, fire mouseout
  \t\t\tremoveClass(this._container, 'leaflet-interactive');
  \t\t\tthis._fireEvent([layer], e, 'mouseout');
  \t\t\tthis._hoveredLayer = null;
  \t\t\tthis._mouseHoverThrottled = false;
  \t\t}
  \t},

  \t_handleMouseHover: function (e, point) {
  \t\tif (this._mouseHoverThrottled) {
  \t\t\treturn;
  \t\t}

  \t\tvar layer, candidateHoveredLayer;

  \t\tfor (var order = this._drawFirst; order; order = order.next) {
  \t\t\tlayer = order.layer;
  \t\t\tif (layer.options.interactive && layer._containsPoint(point)) {
  \t\t\t\tcandidateHoveredLayer = layer;
  \t\t\t}
  \t\t}

  \t\tif (candidateHoveredLayer !== this._hoveredLayer) {
  \t\t\tthis._handleMouseOut(e);

  \t\t\tif (candidateHoveredLayer) {
  \t\t\t\taddClass(this._container, 'leaflet-interactive'); // change cursor
  \t\t\t\tthis._fireEvent([candidateHoveredLayer], e, 'mouseover');
  \t\t\t\tthis._hoveredLayer = candidateHoveredLayer;
  \t\t\t}
  \t\t}

  \t\tthis._fireEvent(this._hoveredLayer ? [this._hoveredLayer] : false, e);

  \t\tthis._mouseHoverThrottled = true;
  \t\tsetTimeout(bind(function () {
  \t\t\tthis._mouseHoverThrottled = false;
  \t\t}, this), 32);
  \t},

  \t_fireEvent: function (layers, e, type) {
  \t\tthis._map._fireDOMEvent(e, type || e.type, layers);
  \t},

  \t_bringToFront: function (layer) {
  \t\tvar order = layer._order;

  \t\tif (!order) { return; }

  \t\tvar next = order.next;
  \t\tvar prev = order.prev;

  \t\tif (next) {
  \t\t\tnext.prev = prev;
  \t\t} else {
  \t\t\t// Already last
  \t\t\treturn;
  \t\t}
  \t\tif (prev) {
  \t\t\tprev.next = next;
  \t\t} else if (next) {
  \t\t\t// Update first entry unless this is the
  \t\t\t// single entry
  \t\t\tthis._drawFirst = next;
  \t\t}

  \t\torder.prev = this._drawLast;
  \t\tthis._drawLast.next = order;

  \t\torder.next = null;
  \t\tthis._drawLast = order;

  \t\tthis._requestRedraw(layer);
  \t},

  \t_bringToBack: function (layer) {
  \t\tvar order = layer._order;

  \t\tif (!order) { return; }

  \t\tvar next = order.next;
  \t\tvar prev = order.prev;

  \t\tif (prev) {
  \t\t\tprev.next = next;
  \t\t} else {
  \t\t\t// Already first
  \t\t\treturn;
  \t\t}
  \t\tif (next) {
  \t\t\tnext.prev = prev;
  \t\t} else if (prev) {
  \t\t\t// Update last entry unless this is the
  \t\t\t// single entry
  \t\t\tthis._drawLast = prev;
  \t\t}

  \t\torder.prev = null;

  \t\torder.next = this._drawFirst;
  \t\tthis._drawFirst.prev = order;
  \t\tthis._drawFirst = order;

  \t\tthis._requestRedraw(layer);
  \t}
  });

  // @factory L.canvas(options?: Renderer options)
  // Creates a Canvas renderer with the given options.
  function canvas(options) {
  \treturn Browser.canvas ? new Canvas(options) : null;
  }

  /*
   * Thanks to Dmitry Baranovsky and his Raphael library for inspiration!
   */


  var vmlCreate = (function () {
  \ttry {
  \t\tdocument.namespaces.add('lvml', 'urn:schemas-microsoft-com:vml');
  \t\treturn function (name) {
  \t\t\treturn document.createElement('<lvml:' + name + ' class=\"lvml\">');
  \t\t};
  \t} catch (e) {
  \t\t// Do not return fn from catch block so `e` can be garbage collected
  \t\t// See https://github.com/Leaflet/Leaflet/pull/7279
  \t}
  \treturn function (name) {
  \t\treturn document.createElement('<' + name + ' xmlns=\"urn:schemas-microsoft.com:vml\" class=\"lvml\">');
  \t};
  })();


  /*
   * @class SVG
   *
   *
   * VML was deprecated in 2012, which means VML functionality exists only for backwards compatibility
   * with old versions of Internet Explorer.
   */

  // mixin to redefine some SVG methods to handle VML syntax which is similar but with some differences
  var vmlMixin = {

  \t_initContainer: function () {
  \t\tthis._container = create\$1('div', 'leaflet-vml-container');
  \t},

  \t_update: function () {
  \t\tif (this._map._animatingZoom) { return; }
  \t\tRenderer.prototype._update.call(this);
  \t\tthis.fire('update');
  \t},

  \t_initPath: function (layer) {
  \t\tvar container = layer._container = vmlCreate('shape');

  \t\taddClass(container, 'leaflet-vml-shape ' + (this.options.className || ''));

  \t\tcontainer.coordsize = '1 1';

  \t\tlayer._path = vmlCreate('path');
  \t\tcontainer.appendChild(layer._path);

  \t\tthis._updateStyle(layer);
  \t\tthis._layers[stamp(layer)] = layer;
  \t},

  \t_addPath: function (layer) {
  \t\tvar container = layer._container;
  \t\tthis._container.appendChild(container);

  \t\tif (layer.options.interactive) {
  \t\t\tlayer.addInteractiveTarget(container);
  \t\t}
  \t},

  \t_removePath: function (layer) {
  \t\tvar container = layer._container;
  \t\tremove(container);
  \t\tlayer.removeInteractiveTarget(container);
  \t\tdelete this._layers[stamp(layer)];
  \t},

  \t_updateStyle: function (layer) {
  \t\tvar stroke = layer._stroke,
  \t\t    fill = layer._fill,
  \t\t    options = layer.options,
  \t\t    container = layer._container;

  \t\tcontainer.stroked = !!options.stroke;
  \t\tcontainer.filled = !!options.fill;

  \t\tif (options.stroke) {
  \t\t\tif (!stroke) {
  \t\t\t\tstroke = layer._stroke = vmlCreate('stroke');
  \t\t\t}
  \t\t\tcontainer.appendChild(stroke);
  \t\t\tstroke.weight = options.weight + 'px';
  \t\t\tstroke.color = options.color;
  \t\t\tstroke.opacity = options.opacity;

  \t\t\tif (options.dashArray) {
  \t\t\t\tstroke.dashStyle = isArray(options.dashArray) ?
  \t\t\t\t    options.dashArray.join(' ') :
  \t\t\t\t    options.dashArray.replace(/( *, *)/g, ' ');
  \t\t\t} else {
  \t\t\t\tstroke.dashStyle = '';
  \t\t\t}
  \t\t\tstroke.endcap = options.lineCap.replace('butt', 'flat');
  \t\t\tstroke.joinstyle = options.lineJoin;

  \t\t} else if (stroke) {
  \t\t\tcontainer.removeChild(stroke);
  \t\t\tlayer._stroke = null;
  \t\t}

  \t\tif (options.fill) {
  \t\t\tif (!fill) {
  \t\t\t\tfill = layer._fill = vmlCreate('fill');
  \t\t\t}
  \t\t\tcontainer.appendChild(fill);
  \t\t\tfill.color = options.fillColor || options.color;
  \t\t\tfill.opacity = options.fillOpacity;

  \t\t} else if (fill) {
  \t\t\tcontainer.removeChild(fill);
  \t\t\tlayer._fill = null;
  \t\t}
  \t},

  \t_updateCircle: function (layer) {
  \t\tvar p = layer._point.round(),
  \t\t    r = Math.round(layer._radius),
  \t\t    r2 = Math.round(layer._radiusY || r);

  \t\tthis._setPath(layer, layer._empty() ? 'M0 0' :
  \t\t\t'AL ' + p.x + ',' + p.y + ' ' + r + ',' + r2 + ' 0,' + (65535 * 360));
  \t},

  \t_setPath: function (layer, path) {
  \t\tlayer._path.v = path;
  \t},

  \t_bringToFront: function (layer) {
  \t\ttoFront(layer._container);
  \t},

  \t_bringToBack: function (layer) {
  \t\ttoBack(layer._container);
  \t}
  };

  var create = Browser.vml ? vmlCreate : svgCreate;

  /*
   * @class SVG
   * @inherits Renderer
   * @aka L.SVG
   *
   * Allows vector layers to be displayed with [SVG](https://developer.mozilla.org/docs/Web/SVG).
   * Inherits `Renderer`.
   *
   * Due to [technical limitations](https://caniuse.com/svg), SVG is not
   * available in all web browsers, notably Android 2.x and 3.x.
   *
   * Although SVG is not available on IE7 and IE8, these browsers support
   * [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language)
   * (a now deprecated technology), and the SVG renderer will fall back to VML in
   * this case.
   *
   * @example
   *
   * Use SVG by default for all paths in the map:
   *
   * ```js
   * var map = L.map('map', {
   * \trenderer: L.svg()
   * });
   * ```
   *
   * Use a SVG renderer with extra padding for specific vector geometries:
   *
   * ```js
   * var map = L.map('map');
   * var myRenderer = L.svg({ padding: 0.5 });
   * var line = L.polyline( coordinates, { renderer: myRenderer } );
   * var circle = L.circle( center, { renderer: myRenderer } );
   * ```
   */

  var SVG = Renderer.extend({

  \t_initContainer: function () {
  \t\tthis._container = create('svg');

  \t\t// makes it possible to click through svg root; we'll reset it back in individual paths
  \t\tthis._container.setAttribute('pointer-events', 'none');

  \t\tthis._rootGroup = create('g');
  \t\tthis._container.appendChild(this._rootGroup);
  \t},

  \t_destroyContainer: function () {
  \t\tremove(this._container);
  \t\toff(this._container);
  \t\tdelete this._container;
  \t\tdelete this._rootGroup;
  \t\tdelete this._svgSize;
  \t},

  \t_update: function () {
  \t\tif (this._map._animatingZoom && this._bounds) { return; }

  \t\tRenderer.prototype._update.call(this);

  \t\tvar b = this._bounds,
  \t\t    size = b.getSize(),
  \t\t    container = this._container;

  \t\t// set size of svg-container if changed
  \t\tif (!this._svgSize || !this._svgSize.equals(size)) {
  \t\t\tthis._svgSize = size;
  \t\t\tcontainer.setAttribute('width', size.x);
  \t\t\tcontainer.setAttribute('height', size.y);
  \t\t}

  \t\t// movement: update container viewBox so that we don't have to change coordinates of individual layers
  \t\tsetPosition(container, b.min);
  \t\tcontainer.setAttribute('viewBox', [b.min.x, b.min.y, size.x, size.y].join(' '));

  \t\tthis.fire('update');
  \t},

  \t// methods below are called by vector layers implementations

  \t_initPath: function (layer) {
  \t\tvar path = layer._path = create('path');

  \t\t// @namespace Path
  \t\t// @option className: String = null
  \t\t// Custom class name set on an element. Only for SVG renderer.
  \t\tif (layer.options.className) {
  \t\t\taddClass(path, layer.options.className);
  \t\t}

  \t\tif (layer.options.interactive) {
  \t\t\taddClass(path, 'leaflet-interactive');
  \t\t}

  \t\tthis._updateStyle(layer);
  \t\tthis._layers[stamp(layer)] = layer;
  \t},

  \t_addPath: function (layer) {
  \t\tif (!this._rootGroup) { this._initContainer(); }
  \t\tthis._rootGroup.appendChild(layer._path);
  \t\tlayer.addInteractiveTarget(layer._path);
  \t},

  \t_removePath: function (layer) {
  \t\tremove(layer._path);
  \t\tlayer.removeInteractiveTarget(layer._path);
  \t\tdelete this._layers[stamp(layer)];
  \t},

  \t_updatePath: function (layer) {
  \t\tlayer._project();
  \t\tlayer._update();
  \t},

  \t_updateStyle: function (layer) {
  \t\tvar path = layer._path,
  \t\t    options = layer.options;

  \t\tif (!path) { return; }

  \t\tif (options.stroke) {
  \t\t\tpath.setAttribute('stroke', options.color);
  \t\t\tpath.setAttribute('stroke-opacity', options.opacity);
  \t\t\tpath.setAttribute('stroke-width', options.weight);
  \t\t\tpath.setAttribute('stroke-linecap', options.lineCap);
  \t\t\tpath.setAttribute('stroke-linejoin', options.lineJoin);

  \t\t\tif (options.dashArray) {
  \t\t\t\tpath.setAttribute('stroke-dasharray', options.dashArray);
  \t\t\t} else {
  \t\t\t\tpath.removeAttribute('stroke-dasharray');
  \t\t\t}

  \t\t\tif (options.dashOffset) {
  \t\t\t\tpath.setAttribute('stroke-dashoffset', options.dashOffset);
  \t\t\t} else {
  \t\t\t\tpath.removeAttribute('stroke-dashoffset');
  \t\t\t}
  \t\t} else {
  \t\t\tpath.setAttribute('stroke', 'none');
  \t\t}

  \t\tif (options.fill) {
  \t\t\tpath.setAttribute('fill', options.fillColor || options.color);
  \t\t\tpath.setAttribute('fill-opacity', options.fillOpacity);
  \t\t\tpath.setAttribute('fill-rule', options.fillRule || 'evenodd');
  \t\t} else {
  \t\t\tpath.setAttribute('fill', 'none');
  \t\t}
  \t},

  \t_updatePoly: function (layer, closed) {
  \t\tthis._setPath(layer, pointsToPath(layer._parts, closed));
  \t},

  \t_updateCircle: function (layer) {
  \t\tvar p = layer._point,
  \t\t    r = Math.max(Math.round(layer._radius), 1),
  \t\t    r2 = Math.max(Math.round(layer._radiusY), 1) || r,
  \t\t    arc = 'a' + r + ',' + r2 + ' 0 1,0 ';

  \t\t// drawing a circle with two half-arcs
  \t\tvar d = layer._empty() ? 'M0 0' :
  \t\t\t'M' + (p.x - r) + ',' + p.y +
  \t\t\tarc + (r * 2) + ',0 ' +
  \t\t\tarc + (-r * 2) + ',0 ';

  \t\tthis._setPath(layer, d);
  \t},

  \t_setPath: function (layer, path) {
  \t\tlayer._path.setAttribute('d', path);
  \t},

  \t// SVG does not have the concept of zIndex so we resort to changing the DOM order of elements
  \t_bringToFront: function (layer) {
  \t\ttoFront(layer._path);
  \t},

  \t_bringToBack: function (layer) {
  \t\ttoBack(layer._path);
  \t}
  });

  if (Browser.vml) {
  \tSVG.include(vmlMixin);
  }

  // @namespace SVG
  // @factory L.svg(options?: Renderer options)
  // Creates a SVG renderer with the given options.
  function svg(options) {
  \treturn Browser.svg || Browser.vml ? new SVG(options) : null;
  }

  Map.include({
  \t// @namespace Map; @method getRenderer(layer: Path): Renderer
  \t// Returns the instance of `Renderer` that should be used to render the given
  \t// `Path`. It will ensure that the `renderer` options of the map and paths
  \t// are respected, and that the renderers do exist on the map.
  \tgetRenderer: function (layer) {
  \t\t// @namespace Path; @option renderer: Renderer
  \t\t// Use this specific instance of `Renderer` for this path. Takes
  \t\t// precedence over the map's [default renderer](#map-renderer).
  \t\tvar renderer = layer.options.renderer || this._getPaneRenderer(layer.options.pane) || this.options.renderer || this._renderer;

  \t\tif (!renderer) {
  \t\t\trenderer = this._renderer = this._createRenderer();
  \t\t}

  \t\tif (!this.hasLayer(renderer)) {
  \t\t\tthis.addLayer(renderer);
  \t\t}
  \t\treturn renderer;
  \t},

  \t_getPaneRenderer: function (name) {
  \t\tif (name === 'overlayPane' || name === undefined) {
  \t\t\treturn false;
  \t\t}

  \t\tvar renderer = this._paneRenderers[name];
  \t\tif (renderer === undefined) {
  \t\t\trenderer = this._createRenderer({pane: name});
  \t\t\tthis._paneRenderers[name] = renderer;
  \t\t}
  \t\treturn renderer;
  \t},

  \t_createRenderer: function (options) {
  \t\t// @namespace Map; @option preferCanvas: Boolean = false
  \t\t// Whether `Path`s should be rendered on a `Canvas` renderer.
  \t\t// By default, all `Path`s are rendered in a `SVG` renderer.
  \t\treturn (this.options.preferCanvas && canvas(options)) || svg(options);
  \t}
  });

  /*
   * L.Rectangle extends Polygon and creates a rectangle when passed a LatLngBounds object.
   */

  /*
   * @class Rectangle
   * @aka L.Rectangle
   * @inherits Polygon
   *
   * A class for drawing rectangle overlays on a map. Extends `Polygon`.
   *
   * @example
   *
   * ```js
   * // define rectangle geographical bounds
   * var bounds = [[54.559322, -5.767822], [56.1210604, -3.021240]];
   *
   * // create an orange rectangle
   * L.rectangle(bounds, {color: \"#ff7800\", weight: 1}).addTo(map);
   *
   * // zoom the map to the rectangle bounds
   * map.fitBounds(bounds);
   * ```
   *
   */


  var Rectangle = Polygon.extend({
  \tinitialize: function (latLngBounds, options) {
  \t\tPolygon.prototype.initialize.call(this, this._boundsToLatLngs(latLngBounds), options);
  \t},

  \t// @method setBounds(latLngBounds: LatLngBounds): this
  \t// Redraws the rectangle with the passed bounds.
  \tsetBounds: function (latLngBounds) {
  \t\treturn this.setLatLngs(this._boundsToLatLngs(latLngBounds));
  \t},

  \t_boundsToLatLngs: function (latLngBounds) {
  \t\tlatLngBounds = toLatLngBounds(latLngBounds);
  \t\treturn [
  \t\t\tlatLngBounds.getSouthWest(),
  \t\t\tlatLngBounds.getNorthWest(),
  \t\t\tlatLngBounds.getNorthEast(),
  \t\t\tlatLngBounds.getSouthEast()
  \t\t];
  \t}
  });


  // @factory L.rectangle(latLngBounds: LatLngBounds, options?: Polyline options)
  function rectangle(latLngBounds, options) {
  \treturn new Rectangle(latLngBounds, options);
  }

  SVG.create = create;
  SVG.pointsToPath = pointsToPath;

  GeoJSON.geometryToLayer = geometryToLayer;
  GeoJSON.coordsToLatLng = coordsToLatLng;
  GeoJSON.coordsToLatLngs = coordsToLatLngs;
  GeoJSON.latLngToCoords = latLngToCoords;
  GeoJSON.latLngsToCoords = latLngsToCoords;
  GeoJSON.getFeature = getFeature;
  GeoJSON.asFeature = asFeature;

  /*
   * L.Handler.BoxZoom is used to add shift-drag zoom interaction to the map
   * (zoom to a selected bounding box), enabled by default.
   */

  // @namespace Map
  // @section Interaction Options
  Map.mergeOptions({
  \t// @option boxZoom: Boolean = true
  \t// Whether the map can be zoomed to a rectangular area specified by
  \t// dragging the mouse while pressing the shift key.
  \tboxZoom: true
  });

  var BoxZoom = Handler.extend({
  \tinitialize: function (map) {
  \t\tthis._map = map;
  \t\tthis._container = map._container;
  \t\tthis._pane = map._panes.overlayPane;
  \t\tthis._resetStateTimeout = 0;
  \t\tmap.on('unload', this._destroy, this);
  \t},

  \taddHooks: function () {
  \t\ton(this._container, 'mousedown', this._onMouseDown, this);
  \t},

  \tremoveHooks: function () {
  \t\toff(this._container, 'mousedown', this._onMouseDown, this);
  \t},

  \tmoved: function () {
  \t\treturn this._moved;
  \t},

  \t_destroy: function () {
  \t\tremove(this._pane);
  \t\tdelete this._pane;
  \t},

  \t_resetState: function () {
  \t\tthis._resetStateTimeout = 0;
  \t\tthis._moved = false;
  \t},

  \t_clearDeferredResetState: function () {
  \t\tif (this._resetStateTimeout !== 0) {
  \t\t\tclearTimeout(this._resetStateTimeout);
  \t\t\tthis._resetStateTimeout = 0;
  \t\t}
  \t},

  \t_onMouseDown: function (e) {
  \t\tif (!e.shiftKey || ((e.which !== 1) && (e.button !== 1))) { return false; }

  \t\t// Clear the deferred resetState if it hasn't executed yet, otherwise it
  \t\t// will interrupt the interaction and orphan a box element in the container.
  \t\tthis._clearDeferredResetState();
  \t\tthis._resetState();

  \t\tdisableTextSelection();
  \t\tdisableImageDrag();

  \t\tthis._startPoint = this._map.mouseEventToContainerPoint(e);

  \t\ton(document, {
  \t\t\tcontextmenu: stop,
  \t\t\tmousemove: this._onMouseMove,
  \t\t\tmouseup: this._onMouseUp,
  \t\t\tkeydown: this._onKeyDown
  \t\t}, this);
  \t},

  \t_onMouseMove: function (e) {
  \t\tif (!this._moved) {
  \t\t\tthis._moved = true;

  \t\t\tthis._box = create\$1('div', 'leaflet-zoom-box', this._container);
  \t\t\taddClass(this._container, 'leaflet-crosshair');

  \t\t\tthis._map.fire('boxzoomstart');
  \t\t}

  \t\tthis._point = this._map.mouseEventToContainerPoint(e);

  \t\tvar bounds = new Bounds(this._point, this._startPoint),
  \t\t    size = bounds.getSize();

  \t\tsetPosition(this._box, bounds.min);

  \t\tthis._box.style.width  = size.x + 'px';
  \t\tthis._box.style.height = size.y + 'px';
  \t},

  \t_finish: function () {
  \t\tif (this._moved) {
  \t\t\tremove(this._box);
  \t\t\tremoveClass(this._container, 'leaflet-crosshair');
  \t\t}

  \t\tenableTextSelection();
  \t\tenableImageDrag();

  \t\toff(document, {
  \t\t\tcontextmenu: stop,
  \t\t\tmousemove: this._onMouseMove,
  \t\t\tmouseup: this._onMouseUp,
  \t\t\tkeydown: this._onKeyDown
  \t\t}, this);
  \t},

  \t_onMouseUp: function (e) {
  \t\tif ((e.which !== 1) && (e.button !== 1)) { return; }

  \t\tthis._finish();

  \t\tif (!this._moved) { return; }
  \t\t// Postpone to next JS tick so internal click event handling
  \t\t// still see it as \"moved\".
  \t\tthis._clearDeferredResetState();
  \t\tthis._resetStateTimeout = setTimeout(bind(this._resetState, this), 0);

  \t\tvar bounds = new LatLngBounds(
  \t\t        this._map.containerPointToLatLng(this._startPoint),
  \t\t        this._map.containerPointToLatLng(this._point));

  \t\tthis._map
  \t\t\t.fitBounds(bounds)
  \t\t\t.fire('boxzoomend', {boxZoomBounds: bounds});
  \t},

  \t_onKeyDown: function (e) {
  \t\tif (e.keyCode === 27) {
  \t\t\tthis._finish();
  \t\t\tthis._clearDeferredResetState();
  \t\t\tthis._resetState();
  \t\t}
  \t}
  });

  // @section Handlers
  // @property boxZoom: Handler
  // Box (shift-drag with mouse) zoom handler.
  Map.addInitHook('addHandler', 'boxZoom', BoxZoom);

  /*
   * L.Handler.DoubleClickZoom is used to handle double-click zoom on the map, enabled by default.
   */

  // @namespace Map
  // @section Interaction Options

  Map.mergeOptions({
  \t// @option doubleClickZoom: Boolean|String = true
  \t// Whether the map can be zoomed in by double clicking on it and
  \t// zoomed out by double clicking while holding shift. If passed
  \t// `'center'`, double-click zoom will zoom to the center of the
  \t//  view regardless of where the mouse was.
  \tdoubleClickZoom: true
  });

  var DoubleClickZoom = Handler.extend({
  \taddHooks: function () {
  \t\tthis._map.on('dblclick', this._onDoubleClick, this);
  \t},

  \tremoveHooks: function () {
  \t\tthis._map.off('dblclick', this._onDoubleClick, this);
  \t},

  \t_onDoubleClick: function (e) {
  \t\tvar map = this._map,
  \t\t    oldZoom = map.getZoom(),
  \t\t    delta = map.options.zoomDelta,
  \t\t    zoom = e.originalEvent.shiftKey ? oldZoom - delta : oldZoom + delta;

  \t\tif (map.options.doubleClickZoom === 'center') {
  \t\t\tmap.setZoom(zoom);
  \t\t} else {
  \t\t\tmap.setZoomAround(e.containerPoint, zoom);
  \t\t}
  \t}
  });

  // @section Handlers
  //
  // Map properties include interaction handlers that allow you to control
  // interaction behavior in runtime, enabling or disabling certain features such
  // as dragging or touch zoom (see `Handler` methods). For example:
  //
  // ```js
  // map.doubleClickZoom.disable();
  // ```
  //
  // @property doubleClickZoom: Handler
  // Double click zoom handler.
  Map.addInitHook('addHandler', 'doubleClickZoom', DoubleClickZoom);

  /*
   * L.Handler.MapDrag is used to make the map draggable (with panning inertia), enabled by default.
   */

  // @namespace Map
  // @section Interaction Options
  Map.mergeOptions({
  \t// @option dragging: Boolean = true
  \t// Whether the map is draggable with mouse/touch or not.
  \tdragging: true,

  \t// @section Panning Inertia Options
  \t// @option inertia: Boolean = *
  \t// If enabled, panning of the map will have an inertia effect where
  \t// the map builds momentum while dragging and continues moving in
  \t// the same direction for some time. Feels especially nice on touch
  \t// devices. Enabled by default.
  \tinertia: true,

  \t// @option inertiaDeceleration: Number = 3000
  \t// The rate with which the inertial movement slows down, in pixels/second².
  \tinertiaDeceleration: 3400, // px/s^2

  \t// @option inertiaMaxSpeed: Number = Infinity
  \t// Max speed of the inertial movement, in pixels/second.
  \tinertiaMaxSpeed: Infinity, // px/s

  \t// @option easeLinearity: Number = 0.2
  \teaseLinearity: 0.2,

  \t// TODO refactor, move to CRS
  \t// @option worldCopyJump: Boolean = false
  \t// With this option enabled, the map tracks when you pan to another \"copy\"
  \t// of the world and seamlessly jumps to the original one so that all overlays
  \t// like markers and vector layers are still visible.
  \tworldCopyJump: false,

  \t// @option maxBoundsViscosity: Number = 0.0
  \t// If `maxBounds` is set, this option will control how solid the bounds
  \t// are when dragging the map around. The default value of `0.0` allows the
  \t// user to drag outside the bounds at normal speed, higher values will
  \t// slow down map dragging outside bounds, and `1.0` makes the bounds fully
  \t// solid, preventing the user from dragging outside the bounds.
  \tmaxBoundsViscosity: 0.0
  });

  var Drag = Handler.extend({
  \taddHooks: function () {
  \t\tif (!this._draggable) {
  \t\t\tvar map = this._map;

  \t\t\tthis._draggable = new Draggable(map._mapPane, map._container);

  \t\t\tthis._draggable.on({
  \t\t\t\tdragstart: this._onDragStart,
  \t\t\t\tdrag: this._onDrag,
  \t\t\t\tdragend: this._onDragEnd
  \t\t\t}, this);

  \t\t\tthis._draggable.on('predrag', this._onPreDragLimit, this);
  \t\t\tif (map.options.worldCopyJump) {
  \t\t\t\tthis._draggable.on('predrag', this._onPreDragWrap, this);
  \t\t\t\tmap.on('zoomend', this._onZoomEnd, this);

  \t\t\t\tmap.whenReady(this._onZoomEnd, this);
  \t\t\t}
  \t\t}
  \t\taddClass(this._map._container, 'leaflet-grab leaflet-touch-drag');
  \t\tthis._draggable.enable();
  \t\tthis._positions = [];
  \t\tthis._times = [];
  \t},

  \tremoveHooks: function () {
  \t\tremoveClass(this._map._container, 'leaflet-grab');
  \t\tremoveClass(this._map._container, 'leaflet-touch-drag');
  \t\tthis._draggable.disable();
  \t},

  \tmoved: function () {
  \t\treturn this._draggable && this._draggable._moved;
  \t},

  \tmoving: function () {
  \t\treturn this._draggable && this._draggable._moving;
  \t},

  \t_onDragStart: function () {
  \t\tvar map = this._map;

  \t\tmap._stop();
  \t\tif (this._map.options.maxBounds && this._map.options.maxBoundsViscosity) {
  \t\t\tvar bounds = toLatLngBounds(this._map.options.maxBounds);

  \t\t\tthis._offsetLimit = toBounds(
  \t\t\t\tthis._map.latLngToContainerPoint(bounds.getNorthWest()).multiplyBy(-1),
  \t\t\t\tthis._map.latLngToContainerPoint(bounds.getSouthEast()).multiplyBy(-1)
  \t\t\t\t\t.add(this._map.getSize()));

  \t\t\tthis._viscosity = Math.min(1.0, Math.max(0.0, this._map.options.maxBoundsViscosity));
  \t\t} else {
  \t\t\tthis._offsetLimit = null;
  \t\t}

  \t\tmap
  \t\t    .fire('movestart')
  \t\t    .fire('dragstart');

  \t\tif (map.options.inertia) {
  \t\t\tthis._positions = [];
  \t\t\tthis._times = [];
  \t\t}
  \t},

  \t_onDrag: function (e) {
  \t\tif (this._map.options.inertia) {
  \t\t\tvar time = this._lastTime = +new Date(),
  \t\t\t    pos = this._lastPos = this._draggable._absPos || this._draggable._newPos;

  \t\t\tthis._positions.push(pos);
  \t\t\tthis._times.push(time);

  \t\t\tthis._prunePositions(time);
  \t\t}

  \t\tthis._map
  \t\t    .fire('move', e)
  \t\t    .fire('drag', e);
  \t},

  \t_prunePositions: function (time) {
  \t\twhile (this._positions.length > 1 && time - this._times[0] > 50) {
  \t\t\tthis._positions.shift();
  \t\t\tthis._times.shift();
  \t\t}
  \t},

  \t_onZoomEnd: function () {
  \t\tvar pxCenter = this._map.getSize().divideBy(2),
  \t\t    pxWorldCenter = this._map.latLngToLayerPoint([0, 0]);

  \t\tthis._initialWorldOffset = pxWorldCenter.subtract(pxCenter).x;
  \t\tthis._worldWidth = this._map.getPixelWorldBounds().getSize().x;
  \t},

  \t_viscousLimit: function (value, threshold) {
  \t\treturn value - (value - threshold) * this._viscosity;
  \t},

  \t_onPreDragLimit: function () {
  \t\tif (!this._viscosity || !this._offsetLimit) { return; }

  \t\tvar offset = this._draggable._newPos.subtract(this._draggable._startPos);

  \t\tvar limit = this._offsetLimit;
  \t\tif (offset.x < limit.min.x) { offset.x = this._viscousLimit(offset.x, limit.min.x); }
  \t\tif (offset.y < limit.min.y) { offset.y = this._viscousLimit(offset.y, limit.min.y); }
  \t\tif (offset.x > limit.max.x) { offset.x = this._viscousLimit(offset.x, limit.max.x); }
  \t\tif (offset.y > limit.max.y) { offset.y = this._viscousLimit(offset.y, limit.max.y); }

  \t\tthis._draggable._newPos = this._draggable._startPos.add(offset);
  \t},

  \t_onPreDragWrap: function () {
  \t\t// TODO refactor to be able to adjust map pane position after zoom
  \t\tvar worldWidth = this._worldWidth,
  \t\t    halfWidth = Math.round(worldWidth / 2),
  \t\t    dx = this._initialWorldOffset,
  \t\t    x = this._draggable._newPos.x,
  \t\t    newX1 = (x - halfWidth + dx) % worldWidth + halfWidth - dx,
  \t\t    newX2 = (x + halfWidth + dx) % worldWidth - halfWidth - dx,
  \t\t    newX = Math.abs(newX1 + dx) < Math.abs(newX2 + dx) ? newX1 : newX2;

  \t\tthis._draggable._absPos = this._draggable._newPos.clone();
  \t\tthis._draggable._newPos.x = newX;
  \t},

  \t_onDragEnd: function (e) {
  \t\tvar map = this._map,
  \t\t    options = map.options,

  \t\t    noInertia = !options.inertia || e.noInertia || this._times.length < 2;

  \t\tmap.fire('dragend', e);

  \t\tif (noInertia) {
  \t\t\tmap.fire('moveend');

  \t\t} else {
  \t\t\tthis._prunePositions(+new Date());

  \t\t\tvar direction = this._lastPos.subtract(this._positions[0]),
  \t\t\t    duration = (this._lastTime - this._times[0]) / 1000,
  \t\t\t    ease = options.easeLinearity,

  \t\t\t    speedVector = direction.multiplyBy(ease / duration),
  \t\t\t    speed = speedVector.distanceTo([0, 0]),

  \t\t\t    limitedSpeed = Math.min(options.inertiaMaxSpeed, speed),
  \t\t\t    limitedSpeedVector = speedVector.multiplyBy(limitedSpeed / speed),

  \t\t\t    decelerationDuration = limitedSpeed / (options.inertiaDeceleration * ease),
  \t\t\t    offset = limitedSpeedVector.multiplyBy(-decelerationDuration / 2).round();

  \t\t\tif (!offset.x && !offset.y) {
  \t\t\t\tmap.fire('moveend');

  \t\t\t} else {
  \t\t\t\toffset = map._limitOffset(offset, map.options.maxBounds);

  \t\t\t\trequestAnimFrame(function () {
  \t\t\t\t\tmap.panBy(offset, {
  \t\t\t\t\t\tduration: decelerationDuration,
  \t\t\t\t\t\teaseLinearity: ease,
  \t\t\t\t\t\tnoMoveStart: true,
  \t\t\t\t\t\tanimate: true
  \t\t\t\t\t});
  \t\t\t\t});
  \t\t\t}
  \t\t}
  \t}
  });

  // @section Handlers
  // @property dragging: Handler
  // Map dragging handler (by both mouse and touch).
  Map.addInitHook('addHandler', 'dragging', Drag);

  /*
   * L.Map.Keyboard is handling keyboard interaction with the map, enabled by default.
   */

  // @namespace Map
  // @section Keyboard Navigation Options
  Map.mergeOptions({
  \t// @option keyboard: Boolean = true
  \t// Makes the map focusable and allows users to navigate the map with keyboard
  \t// arrows and `+`/`-` keys.
  \tkeyboard: true,

  \t// @option keyboardPanDelta: Number = 80
  \t// Amount of pixels to pan when pressing an arrow key.
  \tkeyboardPanDelta: 80
  });

  var Keyboard = Handler.extend({

  \tkeyCodes: {
  \t\tleft:    [37],
  \t\tright:   [39],
  \t\tdown:    [40],
  \t\tup:      [38],
  \t\tzoomIn:  [187, 107, 61, 171],
  \t\tzoomOut: [189, 109, 54, 173]
  \t},

  \tinitialize: function (map) {
  \t\tthis._map = map;

  \t\tthis._setPanDelta(map.options.keyboardPanDelta);
  \t\tthis._setZoomDelta(map.options.zoomDelta);
  \t},

  \taddHooks: function () {
  \t\tvar container = this._map._container;

  \t\t// make the container focusable by tabbing
  \t\tif (container.tabIndex <= 0) {
  \t\t\tcontainer.tabIndex = '0';
  \t\t}

  \t\ton(container, {
  \t\t\tfocus: this._onFocus,
  \t\t\tblur: this._onBlur,
  \t\t\tmousedown: this._onMouseDown
  \t\t}, this);

  \t\tthis._map.on({
  \t\t\tfocus: this._addHooks,
  \t\t\tblur: this._removeHooks
  \t\t}, this);
  \t},

  \tremoveHooks: function () {
  \t\tthis._removeHooks();

  \t\toff(this._map._container, {
  \t\t\tfocus: this._onFocus,
  \t\t\tblur: this._onBlur,
  \t\t\tmousedown: this._onMouseDown
  \t\t}, this);

  \t\tthis._map.off({
  \t\t\tfocus: this._addHooks,
  \t\t\tblur: this._removeHooks
  \t\t}, this);
  \t},

  \t_onMouseDown: function () {
  \t\tif (this._focused) { return; }

  \t\tvar body = document.body,
  \t\t    docEl = document.documentElement,
  \t\t    top = body.scrollTop || docEl.scrollTop,
  \t\t    left = body.scrollLeft || docEl.scrollLeft;

  \t\tthis._map._container.focus();

  \t\twindow.scrollTo(left, top);
  \t},

  \t_onFocus: function () {
  \t\tthis._focused = true;
  \t\tthis._map.fire('focus');
  \t},

  \t_onBlur: function () {
  \t\tthis._focused = false;
  \t\tthis._map.fire('blur');
  \t},

  \t_setPanDelta: function (panDelta) {
  \t\tvar keys = this._panKeys = {},
  \t\t    codes = this.keyCodes,
  \t\t    i, len;

  \t\tfor (i = 0, len = codes.left.length; i < len; i++) {
  \t\t\tkeys[codes.left[i]] = [-1 * panDelta, 0];
  \t\t}
  \t\tfor (i = 0, len = codes.right.length; i < len; i++) {
  \t\t\tkeys[codes.right[i]] = [panDelta, 0];
  \t\t}
  \t\tfor (i = 0, len = codes.down.length; i < len; i++) {
  \t\t\tkeys[codes.down[i]] = [0, panDelta];
  \t\t}
  \t\tfor (i = 0, len = codes.up.length; i < len; i++) {
  \t\t\tkeys[codes.up[i]] = [0, -1 * panDelta];
  \t\t}
  \t},

  \t_setZoomDelta: function (zoomDelta) {
  \t\tvar keys = this._zoomKeys = {},
  \t\t    codes = this.keyCodes,
  \t\t    i, len;

  \t\tfor (i = 0, len = codes.zoomIn.length; i < len; i++) {
  \t\t\tkeys[codes.zoomIn[i]] = zoomDelta;
  \t\t}
  \t\tfor (i = 0, len = codes.zoomOut.length; i < len; i++) {
  \t\t\tkeys[codes.zoomOut[i]] = -zoomDelta;
  \t\t}
  \t},

  \t_addHooks: function () {
  \t\ton(document, 'keydown', this._onKeyDown, this);
  \t},

  \t_removeHooks: function () {
  \t\toff(document, 'keydown', this._onKeyDown, this);
  \t},

  \t_onKeyDown: function (e) {
  \t\tif (e.altKey || e.ctrlKey || e.metaKey) { return; }

  \t\tvar key = e.keyCode,
  \t\t    map = this._map,
  \t\t    offset;

  \t\tif (key in this._panKeys) {
  \t\t\tif (!map._panAnim || !map._panAnim._inProgress) {
  \t\t\t\toffset = this._panKeys[key];
  \t\t\t\tif (e.shiftKey) {
  \t\t\t\t\toffset = toPoint(offset).multiplyBy(3);
  \t\t\t\t}

  \t\t\t\tif (map.options.maxBounds) {
  \t\t\t\t\toffset = map._limitOffset(toPoint(offset), map.options.maxBounds);
  \t\t\t\t}

  \t\t\t\tif (map.options.worldCopyJump) {
  \t\t\t\t\tvar newLatLng = map.wrapLatLng(map.unproject(map.project(map.getCenter()).add(offset)));
  \t\t\t\t\tmap.panTo(newLatLng);
  \t\t\t\t} else {
  \t\t\t\t\tmap.panBy(offset);
  \t\t\t\t}
  \t\t\t}
  \t\t} else if (key in this._zoomKeys) {
  \t\t\tmap.setZoom(map.getZoom() + (e.shiftKey ? 3 : 1) * this._zoomKeys[key]);

  \t\t} else if (key === 27 && map._popup && map._popup.options.closeOnEscapeKey) {
  \t\t\tmap.closePopup();

  \t\t} else {
  \t\t\treturn;
  \t\t}

  \t\tstop(e);
  \t}
  });

  // @section Handlers
  // @section Handlers
  // @property keyboard: Handler
  // Keyboard navigation handler.
  Map.addInitHook('addHandler', 'keyboard', Keyboard);

  /*
   * L.Handler.ScrollWheelZoom is used by L.Map to enable mouse scroll wheel zoom on the map.
   */

  // @namespace Map
  // @section Interaction Options
  Map.mergeOptions({
  \t// @section Mouse wheel options
  \t// @option scrollWheelZoom: Boolean|String = true
  \t// Whether the map can be zoomed by using the mouse wheel. If passed `'center'`,
  \t// it will zoom to the center of the view regardless of where the mouse was.
  \tscrollWheelZoom: true,

  \t// @option wheelDebounceTime: Number = 40
  \t// Limits the rate at which a wheel can fire (in milliseconds). By default
  \t// user can't zoom via wheel more often than once per 40 ms.
  \twheelDebounceTime: 40,

  \t// @option wheelPxPerZoomLevel: Number = 60
  \t// How many scroll pixels (as reported by [L.DomEvent.getWheelDelta](#domevent-getwheeldelta))
  \t// mean a change of one full zoom level. Smaller values will make wheel-zooming
  \t// faster (and vice versa).
  \twheelPxPerZoomLevel: 60
  });

  var ScrollWheelZoom = Handler.extend({
  \taddHooks: function () {
  \t\ton(this._map._container, 'wheel', this._onWheelScroll, this);

  \t\tthis._delta = 0;
  \t},

  \tremoveHooks: function () {
  \t\toff(this._map._container, 'wheel', this._onWheelScroll, this);
  \t},

  \t_onWheelScroll: function (e) {
  \t\tvar delta = getWheelDelta(e);

  \t\tvar debounce = this._map.options.wheelDebounceTime;

  \t\tthis._delta += delta;
  \t\tthis._lastMousePos = this._map.mouseEventToContainerPoint(e);

  \t\tif (!this._startTime) {
  \t\t\tthis._startTime = +new Date();
  \t\t}

  \t\tvar left = Math.max(debounce - (+new Date() - this._startTime), 0);

  \t\tclearTimeout(this._timer);
  \t\tthis._timer = setTimeout(bind(this._performZoom, this), left);

  \t\tstop(e);
  \t},

  \t_performZoom: function () {
  \t\tvar map = this._map,
  \t\t    zoom = map.getZoom(),
  \t\t    snap = this._map.options.zoomSnap || 0;

  \t\tmap._stop(); // stop panning and fly animations if any

  \t\t// map the delta with a sigmoid function to -4..4 range leaning on -1..1
  \t\tvar d2 = this._delta / (this._map.options.wheelPxPerZoomLevel * 4),
  \t\t    d3 = 4 * Math.log(2 / (1 + Math.exp(-Math.abs(d2)))) / Math.LN2,
  \t\t    d4 = snap ? Math.ceil(d3 / snap) * snap : d3,
  \t\t    delta = map._limitZoom(zoom + (this._delta > 0 ? d4 : -d4)) - zoom;

  \t\tthis._delta = 0;
  \t\tthis._startTime = null;

  \t\tif (!delta) { return; }

  \t\tif (map.options.scrollWheelZoom === 'center') {
  \t\t\tmap.setZoom(zoom + delta);
  \t\t} else {
  \t\t\tmap.setZoomAround(this._lastMousePos, zoom + delta);
  \t\t}
  \t}
  });

  // @section Handlers
  // @property scrollWheelZoom: Handler
  // Scroll wheel zoom handler.
  Map.addInitHook('addHandler', 'scrollWheelZoom', ScrollWheelZoom);

  /*
   * L.Map.TapHold is used to simulate `contextmenu` event on long hold,
   * which otherwise is not fired by mobile Safari.
   */

  var tapHoldDelay = 600;

  // @namespace Map
  // @section Interaction Options
  Map.mergeOptions({
  \t// @section Touch interaction options
  \t// @option tapHold: Boolean
  \t// Enables simulation of `contextmenu` event, default is `true` for mobile Safari.
  \ttapHold: Browser.touchNative && Browser.safari && Browser.mobile,

  \t// @option tapTolerance: Number = 15
  \t// The max number of pixels a user can shift his finger during touch
  \t// for it to be considered a valid tap.
  \ttapTolerance: 15
  });

  var TapHold = Handler.extend({
  \taddHooks: function () {
  \t\ton(this._map._container, 'touchstart', this._onDown, this);
  \t},

  \tremoveHooks: function () {
  \t\toff(this._map._container, 'touchstart', this._onDown, this);
  \t},

  \t_onDown: function (e) {
  \t\tclearTimeout(this._holdTimeout);
  \t\tif (e.touches.length !== 1) { return; }

  \t\tvar first = e.touches[0];
  \t\tthis._startPos = this._newPos = new Point(first.clientX, first.clientY);

  \t\tthis._holdTimeout = setTimeout(bind(function () {
  \t\t\tthis._cancel();
  \t\t\tif (!this._isTapValid()) { return; }

  \t\t\t// prevent simulated mouse events https://w3c.github.io/touch-events/#mouse-events
  \t\t\ton(document, 'touchend', preventDefault);
  \t\t\ton(document, 'touchend touchcancel', this._cancelClickPrevent);
  \t\t\tthis._simulateEvent('contextmenu', first);
  \t\t}, this), tapHoldDelay);

  \t\ton(document, 'touchend touchcancel contextmenu', this._cancel, this);
  \t\ton(document, 'touchmove', this._onMove, this);
  \t},

  \t_cancelClickPrevent: function cancelClickPrevent() {
  \t\toff(document, 'touchend', preventDefault);
  \t\toff(document, 'touchend touchcancel', cancelClickPrevent);
  \t},

  \t_cancel: function () {
  \t\tclearTimeout(this._holdTimeout);
  \t\toff(document, 'touchend touchcancel contextmenu', this._cancel, this);
  \t\toff(document, 'touchmove', this._onMove, this);
  \t},

  \t_onMove: function (e) {
  \t\tvar first = e.touches[0];
  \t\tthis._newPos = new Point(first.clientX, first.clientY);
  \t},

  \t_isTapValid: function () {
  \t\treturn this._newPos.distanceTo(this._startPos) <= this._map.options.tapTolerance;
  \t},

  \t_simulateEvent: function (type, e) {
  \t\tvar simulatedEvent = new MouseEvent(type, {
  \t\t\tbubbles: true,
  \t\t\tcancelable: true,
  \t\t\tview: window,
  \t\t\t// detail: 1,
  \t\t\tscreenX: e.screenX,
  \t\t\tscreenY: e.screenY,
  \t\t\tclientX: e.clientX,
  \t\t\tclientY: e.clientY,
  \t\t\t// button: 2,
  \t\t\t// buttons: 2
  \t\t});

  \t\tsimulatedEvent._simulated = true;

  \t\te.target.dispatchEvent(simulatedEvent);
  \t}
  });

  // @section Handlers
  // @property tapHold: Handler
  // Long tap handler to simulate `contextmenu` event (useful in mobile Safari).
  Map.addInitHook('addHandler', 'tapHold', TapHold);

  /*
   * L.Handler.TouchZoom is used by L.Map to add pinch zoom on supported mobile browsers.
   */

  // @namespace Map
  // @section Interaction Options
  Map.mergeOptions({
  \t// @section Touch interaction options
  \t// @option touchZoom: Boolean|String = *
  \t// Whether the map can be zoomed by touch-dragging with two fingers. If
  \t// passed `'center'`, it will zoom to the center of the view regardless of
  \t// where the touch events (fingers) were. Enabled for touch-capable web
  \t// browsers.
  \ttouchZoom: Browser.touch,

  \t// @option bounceAtZoomLimits: Boolean = true
  \t// Set it to false if you don't want the map to zoom beyond min/max zoom
  \t// and then bounce back when pinch-zooming.
  \tbounceAtZoomLimits: true
  });

  var TouchZoom = Handler.extend({
  \taddHooks: function () {
  \t\taddClass(this._map._container, 'leaflet-touch-zoom');
  \t\ton(this._map._container, 'touchstart', this._onTouchStart, this);
  \t},

  \tremoveHooks: function () {
  \t\tremoveClass(this._map._container, 'leaflet-touch-zoom');
  \t\toff(this._map._container, 'touchstart', this._onTouchStart, this);
  \t},

  \t_onTouchStart: function (e) {
  \t\tvar map = this._map;
  \t\tif (!e.touches || e.touches.length !== 2 || map._animatingZoom || this._zooming) { return; }

  \t\tvar p1 = map.mouseEventToContainerPoint(e.touches[0]),
  \t\t    p2 = map.mouseEventToContainerPoint(e.touches[1]);

  \t\tthis._centerPoint = map.getSize()._divideBy(2);
  \t\tthis._startLatLng = map.containerPointToLatLng(this._centerPoint);
  \t\tif (map.options.touchZoom !== 'center') {
  \t\t\tthis._pinchStartLatLng = map.containerPointToLatLng(p1.add(p2)._divideBy(2));
  \t\t}

  \t\tthis._startDist = p1.distanceTo(p2);
  \t\tthis._startZoom = map.getZoom();

  \t\tthis._moved = false;
  \t\tthis._zooming = true;

  \t\tmap._stop();

  \t\ton(document, 'touchmove', this._onTouchMove, this);
  \t\ton(document, 'touchend touchcancel', this._onTouchEnd, this);

  \t\tpreventDefault(e);
  \t},

  \t_onTouchMove: function (e) {
  \t\tif (!e.touches || e.touches.length !== 2 || !this._zooming) { return; }

  \t\tvar map = this._map,
  \t\t    p1 = map.mouseEventToContainerPoint(e.touches[0]),
  \t\t    p2 = map.mouseEventToContainerPoint(e.touches[1]),
  \t\t    scale = p1.distanceTo(p2) / this._startDist;

  \t\tthis._zoom = map.getScaleZoom(scale, this._startZoom);

  \t\tif (!map.options.bounceAtZoomLimits && (
  \t\t\t(this._zoom < map.getMinZoom() && scale < 1) ||
  \t\t\t(this._zoom > map.getMaxZoom() && scale > 1))) {
  \t\t\tthis._zoom = map._limitZoom(this._zoom);
  \t\t}

  \t\tif (map.options.touchZoom === 'center') {
  \t\t\tthis._center = this._startLatLng;
  \t\t\tif (scale === 1) { return; }
  \t\t} else {
  \t\t\t// Get delta from pinch to center, so centerLatLng is delta applied to initial pinchLatLng
  \t\t\tvar delta = p1._add(p2)._divideBy(2)._subtract(this._centerPoint);
  \t\t\tif (scale === 1 && delta.x === 0 && delta.y === 0) { return; }
  \t\t\tthis._center = map.unproject(map.project(this._pinchStartLatLng, this._zoom).subtract(delta), this._zoom);
  \t\t}

  \t\tif (!this._moved) {
  \t\t\tmap._moveStart(true, false);
  \t\t\tthis._moved = true;
  \t\t}

  \t\tcancelAnimFrame(this._animRequest);

  \t\tvar moveFn = bind(map._move, map, this._center, this._zoom, {pinch: true, round: false}, undefined);
  \t\tthis._animRequest = requestAnimFrame(moveFn, this, true);

  \t\tpreventDefault(e);
  \t},

  \t_onTouchEnd: function () {
  \t\tif (!this._moved || !this._zooming) {
  \t\t\tthis._zooming = false;
  \t\t\treturn;
  \t\t}

  \t\tthis._zooming = false;
  \t\tcancelAnimFrame(this._animRequest);

  \t\toff(document, 'touchmove', this._onTouchMove, this);
  \t\toff(document, 'touchend touchcancel', this._onTouchEnd, this);

  \t\t// Pinch updates GridLayers' levels only when zoomSnap is off, so zoomSnap becomes noUpdate.
  \t\tif (this._map.options.zoomAnimation) {
  \t\t\tthis._map._animateZoom(this._center, this._map._limitZoom(this._zoom), true, this._map.options.zoomSnap);
  \t\t} else {
  \t\t\tthis._map._resetView(this._center, this._map._limitZoom(this._zoom));
  \t\t}
  \t}
  });

  // @section Handlers
  // @property touchZoom: Handler
  // Touch zoom handler.
  Map.addInitHook('addHandler', 'touchZoom', TouchZoom);

  Map.BoxZoom = BoxZoom;
  Map.DoubleClickZoom = DoubleClickZoom;
  Map.Drag = Drag;
  Map.Keyboard = Keyboard;
  Map.ScrollWheelZoom = ScrollWheelZoom;
  Map.TapHold = TapHold;
  Map.TouchZoom = TouchZoom;

  exports.Bounds = Bounds;
  exports.Browser = Browser;
  exports.CRS = CRS;
  exports.Canvas = Canvas;
  exports.Circle = Circle;
  exports.CircleMarker = CircleMarker;
  exports.Class = Class;
  exports.Control = Control;
  exports.DivIcon = DivIcon;
  exports.DivOverlay = DivOverlay;
  exports.DomEvent = DomEvent;
  exports.DomUtil = DomUtil;
  exports.Draggable = Draggable;
  exports.Evented = Evented;
  exports.FeatureGroup = FeatureGroup;
  exports.GeoJSON = GeoJSON;
  exports.GridLayer = GridLayer;
  exports.Handler = Handler;
  exports.Icon = Icon;
  exports.ImageOverlay = ImageOverlay;
  exports.LatLng = LatLng;
  exports.LatLngBounds = LatLngBounds;
  exports.Layer = Layer;
  exports.LayerGroup = LayerGroup;
  exports.LineUtil = LineUtil;
  exports.Map = Map;
  exports.Marker = Marker;
  exports.Mixin = Mixin;
  exports.Path = Path;
  exports.Point = Point;
  exports.PolyUtil = PolyUtil;
  exports.Polygon = Polygon;
  exports.Polyline = Polyline;
  exports.Popup = Popup;
  exports.PosAnimation = PosAnimation;
  exports.Projection = index;
  exports.Rectangle = Rectangle;
  exports.Renderer = Renderer;
  exports.SVG = SVG;
  exports.SVGOverlay = SVGOverlay;
  exports.TileLayer = TileLayer;
  exports.Tooltip = Tooltip;
  exports.Transformation = Transformation;
  exports.Util = Util;
  exports.VideoOverlay = VideoOverlay;
  exports.bind = bind;
  exports.bounds = toBounds;
  exports.canvas = canvas;
  exports.circle = circle;
  exports.circleMarker = circleMarker;
  exports.control = control;
  exports.divIcon = divIcon;
  exports.extend = extend;
  exports.featureGroup = featureGroup;
  exports.geoJSON = geoJSON;
  exports.geoJson = geoJson;
  exports.gridLayer = gridLayer;
  exports.icon = icon;
  exports.imageOverlay = imageOverlay;
  exports.latLng = toLatLng;
  exports.latLngBounds = toLatLngBounds;
  exports.layerGroup = layerGroup;
  exports.map = createMap;
  exports.marker = marker;
  exports.point = toPoint;
  exports.polygon = polygon;
  exports.polyline = polyline;
  exports.popup = popup;
  exports.rectangle = rectangle;
  exports.setOptions = setOptions;
  exports.stamp = stamp;
  exports.svg = svg;
  exports.svgOverlay = svgOverlay;
  exports.tileLayer = tileLayer;
  exports.tooltip = tooltip;
  exports.transformation = toTransformation;
  exports.version = version;
  exports.videoOverlay = videoOverlay;

  var oldL = window.L;
  exports.noConflict = function() {
  \twindow.L = oldL;
  \treturn this;
  }
  // Always export us to window global (see #2364)
  window.L = exports;

}));
//# sourceMappingURL=leaflet-src.js.map


/***/ }),

/***/ \"./node_modules/bootstrap-table/dist/bootstrap-table.min.css\":
/*!*******************************************************************!*\\
  !*** ./node_modules/bootstrap-table/dist/bootstrap-table.min.css ***!
  \\*******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

\"use strict\";
__webpack_require__.r(__webpack_exports__);
// extracted by mini-css-extract-plugin


/***/ }),

/***/ \"./node_modules/leaflet/dist/leaflet.css\":
/*!***********************************************!*\\
  !*** ./node_modules/leaflet/dist/leaflet.css ***!
  \\***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

\"use strict\";
__webpack_require__.r(__webpack_exports__);
// extracted by mini-css-extract-plugin


/***/ })

}]);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwLXRhYmxlL2Rpc3QvYm9vdHN0cmFwLXRhYmxlLWxvY2FsZS1hbGwubWluLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9ib290c3RyYXAtdGFibGUvZGlzdC9ib290c3RyYXAtdGFibGUuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2FycmF5LWZpbGwuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2FycmF5LXJlZHVjZS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvZW5naW5lLWlzLW5vZGUuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2luaGVyaXQtaWYtcmVxdWlyZWQuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL251bWJlci1wYXJzZS1mbG9hdC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvc2FtZS12YWx1ZS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvc2V0LXNwZWNpZXMuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL3N0cmluZy1yZXBlYXQuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL3RoaXMtbnVtYmVyLXZhbHVlLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMuYXJyYXkuZmlsbC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLmFycmF5LmZpbmQuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lcy5hcnJheS5pbmNsdWRlcy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLmFycmF5LmluZGV4LW9mLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMuYXJyYXkuaXMtYXJyYXkuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lcy5hcnJheS5yZWR1Y2UuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lcy5hcnJheS5zb21lLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMuYXJyYXkuc3BsaWNlLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMuZnVuY3Rpb24uYmluZC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLm51bWJlci5jb25zdHJ1Y3Rvci5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLm51bWJlci50by1maXhlZC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLnBhcnNlLWZsb2F0LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMucmVnZXhwLmNvbnN0cnVjdG9yLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMucmVnZXhwLnRvLXN0cmluZy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLnN0cmluZy5zZWFyY2guanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy93ZWIudGltZXJzLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9sZWFmbGV0L2Rpc3QvbGVhZmxldC1zcmMuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC10YWJsZS9kaXN0L2Jvb3RzdHJhcC10YWJsZS5taW4uY3NzP2E1ZTMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2xlYWZsZXQvZGlzdC9sZWFmbGV0LmNzcz8wNDJmIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxlQUFlLEtBQW9ELEdBQUcsbUJBQU8sQ0FBQyxvREFBUSxHQUFHLENBQTBILENBQUMsbUJBQW1CLGFBQWEsY0FBYywrQ0FBK0MsV0FBVyw2R0FBNkcscUJBQU0sQ0FBQyxxQkFBTSxrQ0FBa0MsZ0JBQWdCLFlBQVksV0FBVyxzQkFBc0Isa0JBQWtCLDBCQUEwQix3SkFBd0osWUFBWSw0Q0FBNEMsSUFBSSxZQUFZLFNBQVMsVUFBVSxrQkFBa0Isa0NBQWtDLElBQUksZUFBZSxVQUFVLEtBQUssT0FBTywyREFBMkQsY0FBYyxJQUFJLGdCQUFnQixnQkFBZ0Isd0JBQXdCLEdBQUcsaUJBQWlCLE9BQU8sK0RBQStELEtBQUssd0JBQXdCLDZCQUE2Qiw0QkFBNEIsMkNBQTJDLGVBQWUsNENBQTRDLHNCQUFzQixzREFBc0QsU0FBUyxlQUFlLGVBQWUsZUFBZSx1REFBdUQsaUJBQWlCLGtCQUFrQixRQUFRLGlFQUFpRSw2REFBNkQsa0VBQWtFLDJEQUEyRCxLQUFLLGdDQUFnQyxtQkFBbUIsOERBQThELGdFQUFnRSxPQUFPLGVBQWUsVUFBVSxJQUFJLE1BQU0sd0NBQXdDLG9CQUFvQiwwQkFBMEIsY0FBYyxVQUFVLHlDQUF5QyxlQUFlLHdEQUF3RCxTQUFTLDRCQUE0QixzQkFBc0IsNkJBQTZCLGdCQUFnQixVQUFVLG1FQUFtRSxxQ0FBcUMscUJBQXFCLHVCQUF1QixpQkFBaUIsZ0JBQWdCLGlCQUFpQixJQUFJLFNBQVMsU0FBUyxPQUFPLFNBQVMsc0NBQXNDLHNCQUFzQixpRUFB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O0FBQzVELEtBQUs7QUFDTDs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLHdFQUF3RTtBQUNuRjtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLDBCQUEwQjtBQUMvQztBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxpRUFBaUU7QUFDNUU7QUFDQSxHQUFHOztBQUVIOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7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QTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHNDQUFzQzs7QUFFdEM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkI7QUFDM0I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUssZ0JBQWdCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7O0FBR0E7QUFDQTtBQUNBLFdBQVcsK0JBQStCO0FBQzFDO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7O0FBRUE7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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQjtBQUNuQjtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdDQUFnQztBQUNoQyxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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QSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87OztBQUdQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTzs7O0FBR1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0EsNEJBQTRCLGlDQUFpQztBQUM3RDs7QUFFQSw0REFBNEQsMkJBQTJCO0FBQ3ZGOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw0RUFBNEU7QUFDNUU7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSwyQkFBMkIsU0FBUztBQUNwQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRFQUE0RTs7QUFFNUU7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbURBQW1EOztBQUVuRDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0RBQWdEOztBQUVoRDtBQUNBO0FBQ0E7O0FBRUEsdURBQXVEO0FBQ3ZEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsV0FBVztBQUNYOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3REFBd0Q7O0FBRXhEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsV0FBVztBQUNYLFNBQVMsRUFBRTs7QUFFWDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdURBQXVEO0FBQ3ZELHNEQUFzRDtBQUN0RCwwREFBMEQ7QUFDMUQsOENBQThDOztBQUU5QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaUZBQWlGLDZCQUE2QjtBQUM5RztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSx5UUFBeVE7QUFDelE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7O0FBRVg7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSx3RUFBd0U7O0FBRXhFO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7O0FBRUE7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLGFBQWE7QUFDYjtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0EsV0FBVztBQUNYO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztB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Q0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsV0FBVzs7QUFFWDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLHVCQUF1QixVQUFVO0FBQ2pDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx3QkFBd0IsU0FBUztBQUNqQztBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtB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QTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7O0FBRUE7QUFDQTtBQUNBLHVFQUF1RSxpQ0FBaUM7QUFDeEc7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVztBQUNYOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EseUJBQXlCOztBQUV6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUEsa0RBQWtELFFBQVE7QUFDMUQ7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsOEJBQThCLGlDQUFpQztBQUMvRDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx5QkFBeUIsUUFBUTtBQUNqQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsOEJBQThCLGlDQUFpQztBQUMvRDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLDhCQUE4QixpQ0FBaUM7QUFDL0Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSw4QkFBOEIsaUNBQWlDO0FBQy9EOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLHFCQUFxQixtQkFBbUI7QUFDeEMsdUJBQXVCLG1CQUFtQjtBQUMxQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxpQ0FBaUMsbUNBQW1DO0FBQ3BFO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBLFdBQVc7QUFDWDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHVDQUF1QyxhQUFhO0FBQ3BEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEdBQTRHO0FBQzVHO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsOERBQThEO0FBQzlEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSx1QkFBdUIsZ0JBQWdCO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUEsdUJBQXVCLGdCQUFnQjtBQUN2QztBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQ0FBMkM7QUFDM0M7O0FBRUE7O0FBRUE7QUFDQSw4RkFBOEYsZUFBZTtBQUM3RztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLG1EQUFtRDs7QUFFbkQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0RBQXdEO0FBQ3hEOztBQUVBO0FBQ0E7QUFDQSxHQUFHOztBQUVIOztBQUVBLENBQUM7Ozs7Ozs7Ozs7OztBQ2h2T1k7QUFDYixlQUFlLG1CQUFPLENBQUMsNkVBQXdCO0FBQy9DLHNCQUFzQixtQkFBTyxDQUFDLDZGQUFnQztBQUM5RCxlQUFlLG1CQUFPLENBQUMsNkVBQXdCOztBQUUvQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FDaEJBLGdCQUFnQixtQkFBTyxDQUFDLCtFQUF5QjtBQUNqRCxlQUFlLG1CQUFPLENBQUMsNkVBQXdCO0FBQy9DLG9CQUFvQixtQkFBTyxDQUFDLHVGQUE2QjtBQUN6RCxlQUFlLG1CQUFPLENBQUMsNkVBQXdCOztBQUUvQyxxQkFBcUIsc0JBQXNCO0FBQzNDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVSx1Q0FBdUM7QUFDakQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQ3ZDQSxjQUFjLG1CQUFPLENBQUMsaUZBQTBCO0FBQ2hELGFBQWEsbUJBQU8sQ0FBQyx1RUFBcUI7O0FBRTFDOzs7Ozs7Ozs7OztBQ0hBLGVBQWUsbUJBQU8sQ0FBQyw2RUFBd0I7QUFDL0MscUJBQXFCLG1CQUFPLENBQUMseUdBQXNDOztBQUVuRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQ2hCQSxhQUFhLG1CQUFPLENBQUMsdUVBQXFCO0FBQzFDLFdBQVcsMkdBQXdDO0FBQ25ELGtCQUFrQixtQkFBTyxDQUFDLGlGQUEwQjs7QUFFcEQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7Ozs7Ozs7OztBQ2JEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUNOYTtBQUNiLGlCQUFpQixtQkFBTyxDQUFDLG1GQUEyQjtBQUNwRCwyQkFBMkIsbUJBQU8sQ0FBQyx1R0FBcUM7QUFDeEUsc0JBQXNCLG1CQUFPLENBQUMsNkZBQWdDO0FBQzlELGtCQUFrQixtQkFBTyxDQUFDLGlGQUEwQjs7QUFFcEQ7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QixhQUFhO0FBQ3JDLEtBQUs7QUFDTDtBQUNBOzs7Ozs7Ozs7Ozs7QUNsQmE7QUFDYixnQkFBZ0IsbUJBQU8sQ0FBQywrRUFBeUI7QUFDakQsNkJBQTZCLG1CQUFPLENBQUMsMkdBQXVDOztBQUU1RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVEsTUFBTTtBQUNkO0FBQ0E7Ozs7Ozs7Ozs7O0FDYkEsY0FBYyxtQkFBTyxDQUFDLGlGQUEwQjs7QUFFaEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUNUQSxRQUFRLG1CQUFPLENBQUMsdUVBQXFCO0FBQ3JDLFdBQVcsbUJBQU8sQ0FBQywrRUFBeUI7QUFDNUMsdUJBQXVCLG1CQUFPLENBQUMsK0ZBQWlDOztBQUVoRTtBQUNBO0FBQ0EsR0FBRywrQkFBK0I7QUFDbEM7QUFDQSxDQUFDOztBQUVEO0FBQ0E7Ozs7Ozs7Ozs7OztBQ1hhO0FBQ2IsUUFBUSxtQkFBTyxDQUFDLHVFQUFxQjtBQUNyQyxZQUFZLG1IQUE0QztBQUN4RCx1QkFBdUIsbUJBQU8sQ0FBQywrRkFBaUM7O0FBRWhFO0FBQ0E7O0FBRUE7QUFDQSw0Q0FBNEMscUJBQXFCLEVBQUU7O0FBRW5FO0FBQ0E7QUFDQSxHQUFHLG9EQUFvRDtBQUN2RDtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7Ozs7Ozs7Ozs7OztBQ3BCYTtBQUNiLFFBQVEsbUJBQU8sQ0FBQyx1RUFBcUI7QUFDckMsZ0JBQWdCLHFIQUErQztBQUMvRCx1QkFBdUIsbUJBQU8sQ0FBQywrRkFBaUM7O0FBRWhFO0FBQ0E7QUFDQSxHQUFHLCtCQUErQjtBQUNsQztBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7Ozs7Ozs7Ozs7OztBQ2RhO0FBQ2I7QUFDQSxRQUFRLG1CQUFPLENBQUMsdUVBQXFCO0FBQ3JDLGVBQWUsb0hBQThDO0FBQzdELDBCQUEwQixtQkFBTyxDQUFDLHVHQUFxQzs7QUFFdkU7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRyx3RUFBd0U7QUFDM0U7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7Ozs7Ozs7QUNwQkQsUUFBUSxtQkFBTyxDQUFDLHVFQUFxQjtBQUNyQyxjQUFjLG1CQUFPLENBQUMsMkVBQXVCOztBQUU3QztBQUNBO0FBQ0EsR0FBRyw4QkFBOEI7QUFDakM7QUFDQSxDQUFDOzs7Ozs7Ozs7Ozs7QUNQWTtBQUNiLFFBQVEsbUJBQU8sQ0FBQyx1RUFBcUI7QUFDckMsY0FBYyw2R0FBeUM7QUFDdkQsMEJBQTBCLG1CQUFPLENBQUMsdUdBQXFDO0FBQ3ZFLHFCQUFxQixtQkFBTyxDQUFDLDZGQUFnQztBQUM3RCxjQUFjLG1CQUFPLENBQUMsdUZBQTZCOztBQUVuRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRyxxRUFBcUU7QUFDeEU7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7Ozs7Ozs7O0FDbEJZO0FBQ2IsUUFBUSxtQkFBTyxDQUFDLHVFQUFxQjtBQUNyQyxZQUFZLG1IQUE0QztBQUN4RCwwQkFBMEIsbUJBQU8sQ0FBQyx1R0FBcUM7O0FBRXZFOztBQUVBO0FBQ0E7QUFDQSxHQUFHLHVEQUF1RDtBQUMxRDtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7Ozs7Ozs7Ozs7QUNiWTtBQUNiLFFBQVEsbUJBQU8sQ0FBQyx1RUFBcUI7QUFDckMsc0JBQXNCLG1CQUFPLENBQUMsNkZBQWdDO0FBQzlELGdCQUFnQixtQkFBTyxDQUFDLCtFQUF5QjtBQUNqRCxlQUFlLG1CQUFPLENBQUMsNkVBQXdCO0FBQy9DLGVBQWUsbUJBQU8sQ0FBQyw2RUFBd0I7QUFDL0MseUJBQXlCLG1CQUFPLENBQUMsbUdBQW1DO0FBQ3BFLHFCQUFxQixtQkFBTyxDQUFDLHlGQUE4QjtBQUMzRCxtQ0FBbUMsbUJBQU8sQ0FBQywySEFBK0M7O0FBRTFGOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUcsNkRBQTZEO0FBQ2hFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsdUJBQXVCO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkIsNkJBQTZCO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUIsMkNBQTJDO0FBQzlELEtBQUs7QUFDTCx1Q0FBdUMsaUJBQWlCO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsaUJBQWlCO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7Ozs7Ozs7OztBQ25FRCxRQUFRLG1CQUFPLENBQUMsdUVBQXFCO0FBQ3JDLFdBQVcsbUJBQU8sQ0FBQyxxRkFBNEI7O0FBRS9DO0FBQ0E7QUFDQSxHQUFHLGtDQUFrQztBQUNyQztBQUNBLENBQUM7Ozs7Ozs7Ozs7OztBQ1BZO0FBQ2Isa0JBQWtCLG1CQUFPLENBQUMsaUZBQTBCO0FBQ3BELGFBQWEsbUJBQU8sQ0FBQyx1RUFBcUI7QUFDMUMsZUFBZSxtQkFBTyxDQUFDLDZFQUF3QjtBQUMvQyxlQUFlLG1CQUFPLENBQUMsMkVBQXVCO0FBQzlDLFVBQVUsbUJBQU8sQ0FBQyxpRUFBa0I7QUFDcEMsY0FBYyxtQkFBTyxDQUFDLGlGQUEwQjtBQUNoRCx3QkFBd0IsbUJBQU8sQ0FBQyxpR0FBa0M7QUFDbEUsa0JBQWtCLG1CQUFPLENBQUMsbUZBQTJCO0FBQ3JELFlBQVksbUJBQU8sQ0FBQyxxRUFBb0I7QUFDeEMsYUFBYSxtQkFBTyxDQUFDLHFGQUE0QjtBQUNqRCwwQkFBMEIsNElBQXVEO0FBQ2pGLCtCQUErQixzSkFBNEQ7QUFDM0YscUJBQXFCLDhIQUFnRDtBQUNyRSxXQUFXLDJHQUF3Qzs7QUFFbkQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvREFBb0Q7QUFDcEQsS0FBSztBQUNMO0FBQ0Esb0NBQW9DLGNBQWMsT0FBTztBQUN6RCxxQ0FBcUMsY0FBYyxPQUFPO0FBQzFEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLGdCQUFnQjtBQUNyQztBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLHFDQUFxQyxFQUFFO0FBQ3JGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCLGlCQUFpQjtBQUM1QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUMvRWE7QUFDYixRQUFRLG1CQUFPLENBQUMsdUVBQXFCO0FBQ3JDLGdCQUFnQixtQkFBTyxDQUFDLCtFQUF5QjtBQUNqRCxzQkFBc0IsbUJBQU8sQ0FBQyw2RkFBZ0M7QUFDOUQsYUFBYSxtQkFBTyxDQUFDLHFGQUE0QjtBQUNqRCxZQUFZLG1CQUFPLENBQUMscUVBQW9COztBQUV4QztBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUI7QUFDdkIsQ0FBQzs7QUFFRDtBQUNBO0FBQ0EsR0FBRyxnREFBZ0Q7QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0EsQ0FBQzs7Ozs7Ozs7Ozs7QUM1SEQsUUFBUSxtQkFBTyxDQUFDLHVFQUFxQjtBQUNyQywrQkFBK0IsbUJBQU8sQ0FBQywrRkFBaUM7O0FBRXhFO0FBQ0E7QUFDQSxHQUFHLCtEQUErRDtBQUNsRTtBQUNBLENBQUM7Ozs7Ozs7Ozs7O0FDUEQsa0JBQWtCLG1CQUFPLENBQUMsaUZBQTBCO0FBQ3BELGFBQWEsbUJBQU8sQ0FBQyx1RUFBcUI7QUFDMUMsZUFBZSxtQkFBTyxDQUFDLDZFQUF3QjtBQUMvQyx3QkFBd0IsbUJBQU8sQ0FBQyxpR0FBa0M7QUFDbEUscUJBQXFCLDhIQUFnRDtBQUNyRSwwQkFBMEIsNElBQXVEO0FBQ2pGLGVBQWUsbUJBQU8sQ0FBQyw2RUFBd0I7QUFDL0MsZUFBZSxtQkFBTyxDQUFDLG1GQUEyQjtBQUNsRCxvQkFBb0IsbUJBQU8sQ0FBQyxxR0FBb0M7QUFDaEUsZUFBZSxtQkFBTyxDQUFDLDJFQUF1QjtBQUM5QyxZQUFZLG1CQUFPLENBQUMscUVBQW9CO0FBQ3hDLDJCQUEyQixvSEFBOEM7QUFDekUsaUJBQWlCLG1CQUFPLENBQUMsaUZBQTBCO0FBQ25ELHNCQUFzQixtQkFBTyxDQUFDLDZGQUFnQzs7QUFFOUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IsMEJBQTBCLEVBQUU7QUFDcEQsMEJBQTBCLHdCQUF3QjtBQUNsRCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7Ozs7Ozs7Ozs7QUN0RmE7QUFDYixlQUFlLG1CQUFPLENBQUMsMkVBQXVCO0FBQzlDLGVBQWUsbUJBQU8sQ0FBQyw2RUFBd0I7QUFDL0MsWUFBWSxtQkFBTyxDQUFDLHFFQUFvQjtBQUN4QyxZQUFZLG1CQUFPLENBQUMsbUZBQTJCOztBQUUvQztBQUNBO0FBQ0E7O0FBRUEscUNBQXFDLDZCQUE2QiwwQkFBMEIsWUFBWSxFQUFFO0FBQzFHO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRyxHQUFHLGVBQWU7QUFDckI7Ozs7Ozs7Ozs7OztBQ3hCYTtBQUNiLG9DQUFvQyxtQkFBTyxDQUFDLCtIQUFpRDtBQUM3RixlQUFlLG1CQUFPLENBQUMsNkVBQXdCO0FBQy9DLDZCQUE2QixtQkFBTyxDQUFDLDJHQUF1QztBQUM1RSxnQkFBZ0IsbUJBQU8sQ0FBQywrRUFBeUI7QUFDakQsaUJBQWlCLG1CQUFPLENBQUMsbUdBQW1DOztBQUU1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7Ozs7Ozs7QUNqQ0QsUUFBUSxtQkFBTyxDQUFDLHVFQUFxQjtBQUNyQyxhQUFhLG1CQUFPLENBQUMsdUVBQXFCO0FBQzFDLGdCQUFnQixtQkFBTyxDQUFDLDZGQUFnQzs7QUFFeEQ7QUFDQSxzQ0FBc0M7O0FBRXRDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUcseUNBQXlDO0FBQzVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7Ozs7Ozs7Ozs7O0FDM0JEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRSxLQUE0RDtBQUM5RCxFQUFFLENBQ3dHO0FBQzFHLENBQUMsNkJBQTZCOztBQUU5Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHNDQUFzQyxTQUFTO0FBQy9DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esc0JBQXNCLGNBQWM7O0FBRXBDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkIsWUFBWTtBQUN6QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw0REFBNEQsbUJBQW1CO0FBQy9FO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHNCQUFzQixnQkFBZ0I7O0FBRXRDO0FBQ0EsZ0ZBQWdGLEVBQUUsR0FBRyxFQUFFO0FBQ3ZGLDhCQUE4QixtQkFBbUI7QUFDakQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0Isa0JBQWtCO0FBQ3BDLDBCQUEwQixVQUFVO0FBQ3BDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQzs7QUFFdEM7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsaUVBQWlFLHlCQUF5Qjs7QUFFMUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLGVBQWUsRUFBRTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQSxnQ0FBZ0MsUUFBUTs7QUFFeEM7QUFDQTtBQUNBOztBQUVBOztBQUVBLGtEQUFrRCxTQUFTO0FBQzNEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EscUNBQXFDO0FBQ3JDOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esb0RBQW9ELFFBQVE7O0FBRTVEOztBQUVBLGtCQUFrQixxQkFBcUI7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEI7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnREFBZ0QsdUNBQXVDO0FBQ3ZGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUEsd0NBQXdDLFNBQVM7QUFDakQ7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMOztBQUVBO0FBQ0Esd0NBQXdDLFNBQVM7QUFDakQ7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHVCQUF1QjtBQUN2QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBLHlDQUF5QyxTQUFTO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5Q0FBeUMsYUFBYTs7QUFFdEQseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2Q0FBNkMsU0FBUztBQUN0RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EseUVBQXlFLGFBQWE7QUFDdEY7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDJDQUEyQyxTQUFTO0FBQ3BEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUEsd0NBQXdDLFNBQVM7QUFDakQ7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQSxhQUFhOztBQUViO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMEJBQTBCO0FBQzFCO0FBQ0EsMEJBQTBCO0FBQzFCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7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QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsY0FBYzs7QUFFN0I7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOzs7O0FBSUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDJDQUEyQyx5QkFBeUIsT0FBTyxzQ0FBc0M7O0FBRWpIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IsYUFBYTs7QUFFckM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx1QkFBdUI7QUFDdkI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQ0FBMEM7QUFDMUM7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUM7QUFDdkM7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwwQkFBMEI7QUFDMUI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0osR0FBRzs7QUFFSCw0QkFBNEI7QUFDNUI7QUFDQSxHQUFHOztBQUVILG9CQUFvQjtBQUNwQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0NBQWtDLFNBQVM7QUFDM0M7O0FBRUEscUNBQXFDLFVBQVU7QUFDL0M7QUFDQTtBQUNBOztBQUVBLG9DQUFvQztBQUNwQztBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLDJCQUEyQjtBQUMzQjs7QUFFQSw4QkFBOEI7QUFDOUI7O0FBRUEsNkJBQTZCO0FBQzdCOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsa0NBQWtDO0FBQ2xDOztBQUVBO0FBQ0Esa0ZBQWtGO0FBQ2xGLHFDQUFxQztBQUNyQzs7QUFFQSw4QkFBOEI7QUFDOUI7O0FBRUEsK0JBQStCO0FBQy9COztBQUVBLDhCQUE4QjtBQUM5Qjs7QUFFQSwrQkFBK0I7QUFDL0I7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBLDRCQUE0QjtBQUM1Qjs7QUFFQSw2QkFBNkI7QUFDN0I7O0FBRUEsaUNBQWlDO0FBQ2pDOztBQUVBLGdDQUFnQztBQUNoQzs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsK0JBQStCO0FBQy9COztBQUVBLHFDQUFxQztBQUNyQzs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsb0NBQW9DO0FBQ3BDOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QztBQUN2Qyx1QkFBdUI7QUFDdkI7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUEsSUFBSTtBQUNKO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSCw0QkFBNEI7QUFDNUI7O0FBRUEsNEJBQTRCO0FBQzVCOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwrREFBK0QsUUFBUTs7QUFFdkU7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOEJBQThCO0FBQzlCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUI7QUFDdkI7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlDQUF5QyxTQUFTO0FBQ2xEO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLHNCQUFzQixRQUFRO0FBQzlCOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGtCQUFrQixrQkFBa0I7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLFFBQVE7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQixRQUFRO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEM7O0FBRTlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlDQUFpQyw2QkFBNkIsRUFBRTtBQUNoRSxnQ0FBZ0MsNEJBQTRCLEVBQUU7QUFDOUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsK0NBQStDLHVDQUF1QztBQUN0Rjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQSx1Q0FBdUMsU0FBUztBQUNoRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esa0RBQWtELHVDQUF1Qzs7QUFFekY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ04sS0FBSztBQUNMLHdDQUF3QyxTQUFTO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsOENBQThDLGFBQWE7O0FBRTNEO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsSUFBSTtBQUNKOztBQUVBLElBQUk7O0FBRUo7QUFDQSxzRkFBc0YsZUFBZTs7QUFFckcsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCLGFBQWE7O0FBRS9CO0FBQ0E7O0FBRUEsSUFBSTtBQUNKOztBQUVBLElBQUk7O0FBRUo7O0FBRUEsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUksNEJBQTRCO0FBQ2hDO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EseUNBQXlDOztBQUV6QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQSxrQkFBa0IsYUFBYTs7QUFFL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCLFFBQVE7O0FBRXBDO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtEQUErRDtBQUMvRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUosdUNBQXVDO0FBQ3ZDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDJEQUEyRCxZQUFZO0FBQ3ZFOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOzs7QUFHSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQSw2QkFBNkIseUJBQXlCO0FBQ3RELDRCQUE0QixxREFBcUQ7QUFDakY7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaURBQWlELGNBQWM7QUFDL0QsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLDBDQUEwQyxjQUFjO0FBQ3hELElBQUk7O0FBRUo7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0Esc0NBQXNDO0FBQ3RDLDZDQUE2QyxhQUFhO0FBQzFELElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEs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LCtDQUErQzs7QUFFaEY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzREFBc0Q7QUFDdEQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsMkRBQTJEO0FBQzNEO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7OztBQUdKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBLGlEQUFpRDtBQUNqRDtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0EsaURBQWlEO0FBQ2pEO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQztBQUNyQztBQUNBLElBQUk7OztBQUdKOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7O0FBR0o7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtDQUErQztBQUMvQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSywrQkFBK0I7QUFDcEM7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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Q0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0EsMkNBQTJDO0FBQzNDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsbUJBQW1CLHlCQUF5QjtBQUM1QztBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQSxtQkFBbUIseUJBQXlCO0FBQzVDO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQSxtQkFBbUIseUJBQXlCOztBQUU1QztBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQSwyQkFBMkIsYUFBYTs7QUFFeEM7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGVBQWUseUJBQXlCO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxtQ0FBbUMsUUFBUTtBQUMzQztBQUNBOztBQUVBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBOztBQUVBO0FBQ0EsZUFBZSwwQkFBMEI7QUFDekM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLHdCQUF3QjtBQUN2QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxtQ0FBbUMsUUFBUTtBQUMzQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLHVFQUF1RTtBQUN2RTtBQUNBLG1EQUFtRDs7QUFFbkQ7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FB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QUFDQTs7QUFFQTs7QUFFQTtBQUNBLCtCQUErQixhQUFhO0FBQzVDO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBOztBQUVBLHdDQUF3QyxTQUFTO0FBQ2pEO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBLHFDQUFxQyxTQUFTO0FBQzlDO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQkFBK0IsNENBQTRDLEVBQUU7QUFDN0U7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxrQ0FBa0MsYUFBYTtBQUMvQyxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxxQ0FBcUMsYUFBYTtBQUNsRCxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBLGdDQUFnQyxhQUFhO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBLG9EQUFvRDtBQUNwRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKLCtCQUErQjtBQUMvQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBLCtDQUErQzs7QUFFL0M7QUFDQTtBQUNBLGVBQWUsYUFBYTtBQUM1QjtBQUNBLGdCQUFnQixXQUFXO0FBQzNCO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLDBCQUEwQixlQUFlOztBQUV6QztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSw4QkFBOEIsMkNBQTJDO0FBQ3pFLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQSxJQUFJOztBQUVKOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjs7QUFFQSxvQ0FBb0MsUUFBUTs7QUFFNUM7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsZUFBZSxRQUFROztBQUV2QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsOEJBQThCLDJDQUEyQztBQUN6RSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCLFlBQVk7QUFDekM7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0Isa0JBQWtCLGdCQUFnQjtBQUMxRDtBQUNBO0FBQ0E7O0FBRUEscUNBQXFDLGdEQUFnRDs7QUFFckY7QUFDQTtBQUNBLDhCQUE4QjtBQUM5QjtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0Esa0RBQWtEO0FBQ2xEOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5Q0FBeUMsYUFBYTtBQUN0RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsOENBQThDLFVBQVU7QUFDeEQ7O0FBRUEseUNBQXlDLFNBQVM7QUFDbEQ7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQSxJQUFJOztBQUVKLHFFQUFxRTtBQUNyRTtBQUNBO0FBQ0E7O0FBRUEseUNBQXlDLFNBQVM7QUFDbEQ7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGdCQUFnQixTQUFTO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdCQUFnQixTQUFTO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsZ0RBQWdELFNBQVM7QUFDekQ7O0FBRUEsc0NBQXNDLGNBQWM7QUFDcEQ7O0FBRUEscUJBQXFCLFVBQVU7O0FBRS9CO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHVDQUF1QyxTQUFTO0FBQ2hEO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0EscUJBQXFCLFFBQVE7O0FBRTdCO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUEseURBQXlELGNBQWM7O0FBRXZFO0FBQ0EseUNBQXlDLFNBQVM7QUFDbEQ7O0FBRUEsa0RBQWtELFVBQVU7QUFDNUQsaUNBQWlDLFVBQVU7O0FBRTNDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsYUFBYTtBQUNwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzREFBc0QsU0FBUztBQUMvRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx5REFBeUQsY0FBYzs7QUFFdkU7QUFDQSx5Q0FBeUMsU0FBUztBQUNsRDs7QUFFQSxrREFBa0QsVUFBVTtBQUM1RDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0EsTUFBTTtBQUNOO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx1Q0FBdUMsU0FBUztBQUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLHFEQUFxRCxhQUFhOztBQUVsRTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLG9DQUFvQyxTQUFTO0FBQzdDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaURBQWlELFNBQVM7QUFDMUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNOztBQUVOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwrQ0FBK0MsU0FBUztBQUN4RDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwrQ0FBK0MsU0FBUztBQUN4RDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsd0NBQXdDLFNBQVM7QUFDakQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYSxrQkFBa0Isc0JBQXNCO0FBQ3JEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxrQkFBa0I7QUFDbEI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUosZ0RBQWdEO0FBQ2hEO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw2QkFBNkIsd0NBQXdDO0FBQ3JFLGlDQUFpQyx1Q0FBdUM7O0FBRXhFO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBOztBQUVBO0FBQ0EsNkJBQTZCLHdDQUF3QztBQUNyRSxpQ0FBaUMsdUNBQXVDOztBQUV4RTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0IsMkJBQTJCO0FBQy9DO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLDhCQUE4Qix5QkFBeUI7O0FBRXZEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLHNCQUFzQjtBQUN6QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw2QkFBNkIsdUNBQXVDO0FBQ3BFLGlDQUFpQyxzQ0FBc0M7O0FBRXZFO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFEQUFxRDtBQUNyRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFD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QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQyxxREFBcUQ7QUFDM0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkIsY0FBYzs7QUFFM0M7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxjQUFjO0FBQ3JEO0FBQ0EsSUFBSTs7QUFFSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOEJBQThCLGNBQWM7O0FBRTVDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3Q0FBd0MsY0FBYztBQUN0RDtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSixnQ0FBZ0M7O0FBRWhDLDZCQUE2Qjs7QUFFN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBLGdEQUFnRCxRQUFRO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOzs7QUFHSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBOztBQUVBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCLHlCQUF5QjtBQUN0RDtBQUNBO0FBQ0EsZ0NBQWdDLGFBQWE7QUFDN0M7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsc0JBQXNCO0FBQ3RCLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7O0FBRUE7QUFDQSxtREFBbUQ7O0FBRW5ELGdEQUFnRCxTQUFTOztBQUV6RDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQSxxQkFBcUIsUUFBUTs7QUFFN0I7QUFDQSx3QkFBd0IsUUFBUTs7QUFFaEM7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSx5Q0FBeUMsVUFBVTs7QUFFbkQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzQ0FBc0Msb0JBQW9COztBQUUxRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7O0FBRUE7QUFDQSwwQkFBMEIsUUFBUTs7QUFFbEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKOztBQUVBO0FBQ0E7O0FBRUEsNkJBQTZCLGtCQUFrQjs7QUFFL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxJQUFJOztBQUVKOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7O0FBRUEsdUJBQXVCLGVBQWU7QUFDdEMsd0JBQXdCLGVBQWU7O0FBRXZDO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0EsaURBQWlELFFBQVE7O0FBRXpEO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBLGVBQWUsUUFBUTtBQUN2Qjs7QUFFQSwrQkFBK0IsMEJBQTBCO0FBQ3pELHVDQUF1QyxRQUFRLEVBQUU7O0FBRWpEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUNBQXVDLGtFQUFrRTs7QUFFekc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSw4Q0FBOEMsNkJBQTZCLFFBQVE7O0FBRW5GO0FBQ0EsaUNBQWlDLHNCQUFzQjtBQUN2RCxrQ0FBa0Msc0JBQXNCO0FBQ3hEO0FBQ0E7O0FBRUEsdUNBQXVDLFVBQVU7O0FBRWpEO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxnQkFBZ0Isa0JBQWtCO0FBQ2xDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtGQUFrRixjQUFjO0FBQ2hHOztBQUVBLCtCQUErQixhQUFhOztBQUU1QztBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsZ0JBQWdCLFFBQVE7O0FBRXhCOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsSUFBSTs7QUFFSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQSwwREFBMEQ7QUFDMUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047O0FBRUE7O0FBRUE7QUFDQSxnQkFBZ0IsUUFBUTs7QUFFeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQSxvQ0FBb0MsY0FBYztBQUNsRDtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0RBQWtELEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxNQUFNLElBQUksSUFBSSxnQ0FBZ0MsbUZBQW1GO0FBQzdMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLEVBQUUsd0JBQXdCLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFO0FBQ3REO0FBQ0E7QUFDQSxPQUFPLEVBQUUsd0hBQXdILDJDQUEyQyxnREFBZ0QsRUFBRSxrQkFBa0IsRUFBRSxRQUFRLEVBQUUsd0JBQXdCLEVBQUUsOEJBQThCO0FBQ3BUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCLEVBQUUsaUJBQWlCLElBQUksRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsUUFBUSxXQUFXO0FBQ2pGO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLGdCQUFnQixRQUFROztBQUV4QjtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKOztBQUVBOztBQUVBLDZCQUE2Qjs7QUFFN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLDJCQUEyQjs7QUFFM0I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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Q0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCLDRCQUE0QjtBQUN0RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQSwrREFBK0QsY0FBYzs7QUFFN0U7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLElBQUk7O0FBRUo7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLElBQUk7O0FBRUo7QUFDQSw4Q0FBOEMsUUFBUTs7QUFFdEQ7O0FBRUEsdUJBQXVCLFFBQVE7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwwQkFBMEIsc0JBQXNCO0FBQ2hELElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNOztBQUVOO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7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YXAtdGFibGUtbG9jYWxlLWFsbF9taW5fanMtbm9kZV9tb2R1bGVzX2Jvb3QtM2YwZmQwLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gICogYm9vdHN0cmFwLXRhYmxlIC0gQW4gZXh0ZW5kZWQgdGFibGUgdG8gaW50ZWdyYXRpb24gd2l0aCBzb21lIG9mIHRoZSBtb3N0IHdpZGVseSB1c2VkIENTUyBmcmFtZXdvcmtzLiAoU3VwcG9ydHMgQm9vdHN0cmFwLCBTZW1hbnRpYyBVSSwgQnVsbWEsIE1hdGVyaWFsIERlc2lnbiwgRm91bmRhdGlvbilcbiAgKlxuICAqIEB2ZXJzaW9uIHYxLjE4LjNcbiAgKiBAaG9tZXBhZ2UgaHR0cHM6Ly9ib290c3RyYXAtdGFibGUuY29tXG4gICogQGF1dGhvciB3ZW56aGl4aW4gPHdlbnpoaXhpbjIwMTBAZ21haWwuY29tPiAoaHR0cDovL3dlbnpoaXhpbi5uZXQuY24vKVxuICAqIEBsaWNlbnNlIE1JVFxuICAqL1xuXG4hZnVuY3Rpb24odCxuKXtcIm9iamVjdFwiPT10eXBlb2YgZXhwb3J0cyYmXCJ1bmRlZmluZWRcIiE9dHlwZW9mIG1vZHVsZT9uKHJlcXVpcmUoXCJqcXVlcnlcIikpOlwiZnVuY3Rpb25cIj09dHlwZW9mIGRlZmluZSYmZGVmaW5lLmFtZD9kZWZpbmUoW1wianF1ZXJ5XCJdLG4pOm4oKHQ9XCJ1bmRlZmluZWRcIiE9dHlwZW9mIGdsb2JhbFRoaXM/Z2xvYmFsVGhpczp0fHxzZWxmKS5qUXVlcnkpfSh0aGlzLChmdW5jdGlvbih0KXtcInVzZSBzdHJpY3RcIjtmdW5jdGlvbiBuKHQpe3JldHVybiB0JiZcIm9iamVjdFwiPT10eXBlb2YgdCYmXCJkZWZhdWx0XCJpbiB0P3Q6e2RlZmF1bHQ6dH19dmFyIG89bih0KSxyPVwidW5kZWZpbmVkXCIhPXR5cGVvZiBnbG9iYWxUaGlzP2dsb2JhbFRoaXM6XCJ1bmRlZmluZWRcIiE9dHlwZW9mIHdpbmRvdz93aW5kb3c6XCJ1bmRlZmluZWRcIiE9dHlwZW9mIGdsb2JhbD9nbG9iYWw6XCJ1bmRlZmluZWRcIiE9dHlwZW9mIHNlbGY/c2VsZjp7fTtmdW5jdGlvbiBlKHQsbil7cmV0dXJuIHQobj17ZXhwb3J0czp7fX0sbi5leHBvcnRzKSxuLmV4cG9ydHN9dmFyIGE9ZnVuY3Rpb24odCl7cmV0dXJuIHQmJnQuTWF0aD09TWF0aCYmdH0saT1hKFwib2JqZWN0XCI9PXR5cGVvZiBnbG9iYWxUaGlzJiZnbG9iYWxUaGlzKXx8YShcIm9iamVjdFwiPT10eXBlb2Ygd2luZG93JiZ3aW5kb3cpfHxhKFwib2JqZWN0XCI9PXR5cGVvZiBzZWxmJiZzZWxmKXx8YShcIm9iamVjdFwiPT10eXBlb2YgciYmcil8fGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXN9KCl8fEZ1bmN0aW9uKFwicmV0dXJuIHRoaXNcIikoKSx1PWZ1bmN0aW9uKHQpe3RyeXtyZXR1cm4hIXQoKX1jYXRjaCh0KXtyZXR1cm4hMH19LGY9IXUoKGZ1bmN0aW9uKCl7cmV0dXJuIDchPU9iamVjdC5kZWZpbmVQcm9wZXJ0eSh7fSwxLHtnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gN319KVsxXX0pKSxjPXt9LnByb3BlcnR5SXNFbnVtZXJhYmxlLGw9T2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcixzPXtmOmwmJiFjLmNhbGwoezE6Mn0sMSk/ZnVuY3Rpb24odCl7dmFyIG49bCh0aGlzLHQpO3JldHVybiEhbiYmbi5lbnVtZXJhYmxlfTpjfSxtPWZ1bmN0aW9uKHQsbil7cmV0dXJue2VudW1lcmFibGU6ISgxJnQpLGNvbmZpZ3VyYWJsZTohKDImdCksd3JpdGFibGU6ISg0JnQpLHZhbHVlOm59fSxnPXt9LnRvU3RyaW5nLGQ9ZnVuY3Rpb24odCl7cmV0dXJuIGcuY2FsbCh0KS5zbGljZSg4LC0xKX0saD1cIlwiLnNwbGl0LHA9dSgoZnVuY3Rpb24oKXtyZXR1cm4hT2JqZWN0KFwielwiKS5wcm9wZXJ0eUlzRW51bWVyYWJsZSgwKX0pKT9mdW5jdGlvbih0KXtyZXR1cm5cIlN0cmluZ1wiPT1kKHQpP2guY2FsbCh0LFwiXCIpOk9iamVjdCh0KX06T2JqZWN0LHc9ZnVuY3Rpb24odCl7aWYobnVsbD09dCl0aHJvdyBUeXBlRXJyb3IoXCJDYW4ndCBjYWxsIG1ldGhvZCBvbiBcIit0KTtyZXR1cm4gdH0sUz1mdW5jdGlvbih0KXtyZXR1cm4gcCh3KHQpKX0sUD1mdW5jdGlvbih0KXtyZXR1cm5cIm9iamVjdFwiPT10eXBlb2YgdD9udWxsIT09dDpcImZ1bmN0aW9uXCI9PXR5cGVvZiB0fSxUPWZ1bmN0aW9uKHQsbil7aWYoIVAodCkpcmV0dXJuIHQ7dmFyIG8scjtpZihuJiZcImZ1bmN0aW9uXCI9PXR5cGVvZihvPXQudG9TdHJpbmcpJiYhUChyPW8uY2FsbCh0KSkpcmV0dXJuIHI7aWYoXCJmdW5jdGlvblwiPT10eXBlb2Yobz10LnZhbHVlT2YpJiYhUChyPW8uY2FsbCh0KSkpcmV0dXJuIHI7aWYoIW4mJlwiZnVuY3Rpb25cIj09dHlwZW9mKG89dC50b1N0cmluZykmJiFQKHI9by5jYWxsKHQpKSlyZXR1cm4gcjt0aHJvdyBUeXBlRXJyb3IoXCJDYW4ndCBjb252ZXJ0IG9iamVjdCB0byBwcmltaXRpdmUgdmFsdWVcIil9LFI9e30uaGFzT3duUHJvcGVydHksQz1mdW5jdGlvbih0LG4pe3JldHVybiBSLmNhbGwodCxuKX0sYj1pLmRvY3VtZW50LHY9UChiKSYmUChiLmNyZWF0ZUVsZW1lbnQpLEE9IWYmJiF1KChmdW5jdGlvbigpe3JldHVybiA3IT1PYmplY3QuZGVmaW5lUHJvcGVydHkoKHQ9XCJkaXZcIix2P2IuY3JlYXRlRWxlbWVudCh0KTp7fSksXCJhXCIse2dldDpmdW5jdGlvbigpe3JldHVybiA3fX0pLmE7dmFyIHR9KSkseD1PYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yLEY9e2Y6Zj94OmZ1bmN0aW9uKHQsbil7aWYodD1TKHQpLG49VChuLCEwKSxBKXRyeXtyZXR1cm4geCh0LG4pfWNhdGNoKHQpe31pZihDKHQsbikpcmV0dXJuIG0oIXMuZi5jYWxsKHQsbiksdFtuXSl9fSx5PWZ1bmN0aW9uKHQpe2lmKCFQKHQpKXRocm93IFR5cGVFcnJvcihTdHJpbmcodCkrXCIgaXMgbm90IGFuIG9iamVjdFwiKTtyZXR1cm4gdH0saz1PYmplY3QuZGVmaW5lUHJvcGVydHksSD17ZjpmP2s6ZnVuY3Rpb24odCxuLG8pe2lmKHkodCksbj1UKG4sITApLHkobyksQSl0cnl7cmV0dXJuIGsodCxuLG8pfWNhdGNoKHQpe31pZihcImdldFwiaW4gb3x8XCJzZXRcImluIG8pdGhyb3cgVHlwZUVycm9yKFwiQWNjZXNzb3JzIG5vdCBzdXBwb3J0ZWRcIik7cmV0dXJuXCJ2YWx1ZVwiaW4gbyYmKHRbbl09by52YWx1ZSksdH19LE89Zj9mdW5jdGlvbih0LG4sbyl7cmV0dXJuIEguZih0LG4sbSgxLG8pKX06ZnVuY3Rpb24odCxuLG8pe3JldHVybiB0W25dPW8sdH0sTT1mdW5jdGlvbih0LG4pe3RyeXtPKGksdCxuKX1jYXRjaChvKXtpW3RdPW59cmV0dXJuIG59LEU9XCJfX2NvcmUtanNfc2hhcmVkX19cIixOPWlbRV18fE0oRSx7fSksRD1GdW5jdGlvbi50b1N0cmluZztcImZ1bmN0aW9uXCIhPXR5cGVvZiBOLmluc3BlY3RTb3VyY2UmJihOLmluc3BlY3RTb3VyY2U9ZnVuY3Rpb24odCl7cmV0dXJuIEQuY2FsbCh0KX0pO3ZhciB6LEwsaixCLFU9Ti5pbnNwZWN0U291cmNlLEo9aS5XZWFrTWFwLEc9XCJmdW5jdGlvblwiPT10eXBlb2YgSiYmL25hdGl2ZSBjb2RlLy50ZXN0KFUoSikpLFY9ZSgoZnVuY3Rpb24odCl7KHQuZXhwb3J0cz1mdW5jdGlvbih0LG4pe3JldHVybiBOW3RdfHwoTlt0XT12b2lkIDAhPT1uP246e30pfSkoXCJ2ZXJzaW9uc1wiLFtdKS5wdXNoKHt2ZXJzaW9uOlwiMy45LjFcIixtb2RlOlwiZ2xvYmFsXCIsY29weXJpZ2h0OlwiwqkgMjAyMSBEZW5pcyBQdXNoa2FyZXYgKHpsb2lyb2NrLnJ1KVwifSl9KSksWj0wLEk9TWF0aC5yYW5kb20oKSxxPWZ1bmN0aW9uKHQpe3JldHVyblwiU3ltYm9sKFwiK1N0cmluZyh2b2lkIDA9PT10P1wiXCI6dCkrXCIpX1wiKygrK1orSSkudG9TdHJpbmcoMzYpfSxLPVYoXCJrZXlzXCIpLFc9e30sWT1pLldlYWtNYXA7aWYoRyl7dmFyIF89Ti5zdGF0ZXx8KE4uc3RhdGU9bmV3IFkpLFE9Xy5nZXQsWD1fLmhhcywkPV8uc2V0O3o9ZnVuY3Rpb24odCxuKXtyZXR1cm4gbi5mYWNhZGU9dCwkLmNhbGwoXyx0LG4pLG59LEw9ZnVuY3Rpb24odCl7cmV0dXJuIFEuY2FsbChfLHQpfHx7fX0saj1mdW5jdGlvbih0KXtyZXR1cm4gWC5jYWxsKF8sdCl9fWVsc2V7dmFyIHR0PUtbQj1cInN0YXRlXCJdfHwoS1tCXT1xKEIpKTtXW3R0XT0hMCx6PWZ1bmN0aW9uKHQsbil7cmV0dXJuIG4uZmFjYWRlPXQsTyh0LHR0LG4pLG59LEw9ZnVuY3Rpb24odCl7cmV0dXJuIEModCx0dCk/dFt0dF06e319LGo9ZnVuY3Rpb24odCl7cmV0dXJuIEModCx0dCl9fXZhciBudCxvdCxydD17c2V0OnosZ2V0OkwsaGFzOmosZW5mb3JjZTpmdW5jdGlvbih0KXtyZXR1cm4gaih0KT9MKHQpOnoodCx7fSl9LGdldHRlckZvcjpmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24obil7dmFyIG87aWYoIVAobil8fChvPUwobikpLnR5cGUhPT10KXRocm93IFR5cGVFcnJvcihcIkluY29tcGF0aWJsZSByZWNlaXZlciwgXCIrdCtcIiByZXF1aXJlZFwiKTtyZXR1cm4gb319fSxldD1lKChmdW5jdGlvbih0KXt2YXIgbj1ydC5nZXQsbz1ydC5lbmZvcmNlLHI9U3RyaW5nKFN0cmluZykuc3BsaXQoXCJTdHJpbmdcIik7KHQuZXhwb3J0cz1mdW5jdGlvbih0LG4sZSxhKXt2YXIgdSxmPSEhYSYmISFhLnVuc2FmZSxjPSEhYSYmISFhLmVudW1lcmFibGUsbD0hIWEmJiEhYS5ub1RhcmdldEdldDtcImZ1bmN0aW9uXCI9PXR5cGVvZiBlJiYoXCJzdHJpbmdcIiE9dHlwZW9mIG58fEMoZSxcIm5hbWVcIil8fE8oZSxcIm5hbWVcIixuKSwodT1vKGUpKS5zb3VyY2V8fCh1LnNvdXJjZT1yLmpvaW4oXCJzdHJpbmdcIj09dHlwZW9mIG4/bjpcIlwiKSkpLHQhPT1pPyhmPyFsJiZ0W25dJiYoYz0hMCk6ZGVsZXRlIHRbbl0sYz90W25dPWU6Tyh0LG4sZSkpOmM/dFtuXT1lOk0obixlKX0pKEZ1bmN0aW9uLnByb3RvdHlwZSxcInRvU3RyaW5nXCIsKGZ1bmN0aW9uKCl7cmV0dXJuXCJmdW5jdGlvblwiPT10eXBlb2YgdGhpcyYmbih0aGlzKS5zb3VyY2V8fFUodGhpcyl9KSl9KSksYXQ9aSxpdD1mdW5jdGlvbih0KXtyZXR1cm5cImZ1bmN0aW9uXCI9PXR5cGVvZiB0P3Q6dm9pZCAwfSx1dD1mdW5jdGlvbih0LG4pe3JldHVybiBhcmd1bWVudHMubGVuZ3RoPDI/aXQoYXRbdF0pfHxpdChpW3RdKTphdFt0XSYmYXRbdF1bbl18fGlbdF0mJmlbdF1bbl19LGZ0PU1hdGguY2VpbCxjdD1NYXRoLmZsb29yLGx0PWZ1bmN0aW9uKHQpe3JldHVybiBpc05hTih0PSt0KT8wOih0PjA/Y3Q6ZnQpKHQpfSxzdD1NYXRoLm1pbixtdD1mdW5jdGlvbih0KXtyZXR1cm4gdD4wP3N0KGx0KHQpLDkwMDcxOTkyNTQ3NDA5OTEpOjB9LGd0PU1hdGgubWF4LGR0PU1hdGgubWluLGh0PWZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbihuLG8scil7dmFyIGUsYT1TKG4pLGk9bXQoYS5sZW5ndGgpLHU9ZnVuY3Rpb24odCxuKXt2YXIgbz1sdCh0KTtyZXR1cm4gbzwwP2d0KG8rbiwwKTpkdChvLG4pfShyLGkpO2lmKHQmJm8hPW8pe2Zvcig7aT51OylpZigoZT1hW3UrK10pIT1lKXJldHVybiEwfWVsc2UgZm9yKDtpPnU7dSsrKWlmKCh0fHx1IGluIGEpJiZhW3VdPT09bylyZXR1cm4gdHx8dXx8MDtyZXR1cm4hdCYmLTF9fSxwdD17aW5jbHVkZXM6aHQoITApLGluZGV4T2Y6aHQoITEpfS5pbmRleE9mLHd0PVtcImNvbnN0cnVjdG9yXCIsXCJoYXNPd25Qcm9wZXJ0eVwiLFwiaXNQcm90b3R5cGVPZlwiLFwicHJvcGVydHlJc0VudW1lcmFibGVcIixcInRvTG9jYWxlU3RyaW5nXCIsXCJ0b1N0cmluZ1wiLFwidmFsdWVPZlwiXS5jb25jYXQoXCJsZW5ndGhcIixcInByb3RvdHlwZVwiKSxTdD17ZjpPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lc3x8ZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKHQsbil7dmFyIG8scj1TKHQpLGU9MCxhPVtdO2ZvcihvIGluIHIpIUMoVyxvKSYmQyhyLG8pJiZhLnB1c2gobyk7Zm9yKDtuLmxlbmd0aD5lOylDKHIsbz1uW2UrK10pJiYofnB0KGEsbyl8fGEucHVzaChvKSk7cmV0dXJuIGF9KHQsd3QpfX0sUHQ9e2Y6T2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9sc30sVHQ9dXQoXCJSZWZsZWN0XCIsXCJvd25LZXlzXCIpfHxmdW5jdGlvbih0KXt2YXIgbj1TdC5mKHkodCkpLG89UHQuZjtyZXR1cm4gbz9uLmNvbmNhdChvKHQpKTpufSxSdD1mdW5jdGlvbih0LG4pe2Zvcih2YXIgbz1UdChuKSxyPUguZixlPUYuZixhPTA7YTxvLmxlbmd0aDthKyspe3ZhciBpPW9bYV07Qyh0LGkpfHxyKHQsaSxlKG4saSkpfX0sQ3Q9LyN8XFwucHJvdG90eXBlXFwuLyxidD1mdW5jdGlvbih0LG4pe3ZhciBvPUF0W3Z0KHQpXTtyZXR1cm4gbz09RnR8fG8hPXh0JiYoXCJmdW5jdGlvblwiPT10eXBlb2Ygbj91KG4pOiEhbil9LHZ0PWJ0Lm5vcm1hbGl6ZT1mdW5jdGlvbih0KXtyZXR1cm4gU3RyaW5nKHQpLnJlcGxhY2UoQ3QsXCIuXCIpLnRvTG93ZXJDYXNlKCl9LEF0PWJ0LmRhdGE9e30seHQ9YnQuTkFUSVZFPVwiTlwiLEZ0PWJ0LlBPTFlGSUxMPVwiUFwiLHl0PWJ0LGt0PUYuZixIdD1BcnJheS5pc0FycmF5fHxmdW5jdGlvbih0KXtyZXR1cm5cIkFycmF5XCI9PWQodCl9LE90PWZ1bmN0aW9uKHQpe3JldHVybiBPYmplY3Qodyh0KSl9LE10PWZ1bmN0aW9uKHQsbixvKXt2YXIgcj1UKG4pO3IgaW4gdD9ILmYodCxyLG0oMCxvKSk6dFtyXT1vfSxFdD1cInByb2Nlc3NcIj09ZChpLnByb2Nlc3MpLE50PXV0KFwibmF2aWdhdG9yXCIsXCJ1c2VyQWdlbnRcIil8fFwiXCIsRHQ9aS5wcm9jZXNzLHp0PUR0JiZEdC52ZXJzaW9ucyxMdD16dCYmenQudjg7THQ/b3Q9KG50PUx0LnNwbGl0KFwiLlwiKSlbMF0rbnRbMV06TnQmJighKG50PU50Lm1hdGNoKC9FZGdlXFwvKFxcZCspLykpfHxudFsxXT49NzQpJiYobnQ9TnQubWF0Y2goL0Nocm9tZVxcLyhcXGQrKS8pKSYmKG90PW50WzFdKTt2YXIganQsQnQ9b3QmJitvdCxVdD0hIU9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMmJiF1KChmdW5jdGlvbigpe3JldHVybiFTeW1ib2wuc2hhbSYmKEV0PzM4PT09QnQ6QnQ+MzcmJkJ0PDQxKX0pKSxKdD1VdCYmIVN5bWJvbC5zaGFtJiZcInN5bWJvbFwiPT10eXBlb2YgU3ltYm9sLml0ZXJhdG9yLEd0PVYoXCJ3a3NcIiksVnQ9aS5TeW1ib2wsWnQ9SnQ/VnQ6VnQmJlZ0LndpdGhvdXRTZXR0ZXJ8fHEsSXQ9ZnVuY3Rpb24odCl7cmV0dXJuIEMoR3QsdCkmJihVdHx8XCJzdHJpbmdcIj09dHlwZW9mIEd0W3RdKXx8KFV0JiZDKFZ0LHQpP0d0W3RdPVZ0W3RdOkd0W3RdPVp0KFwiU3ltYm9sLlwiK3QpKSxHdFt0XX0scXQ9SXQoXCJzcGVjaWVzXCIpLEt0PWZ1bmN0aW9uKHQsbil7dmFyIG87cmV0dXJuIEh0KHQpJiYoXCJmdW5jdGlvblwiIT10eXBlb2Yobz10LmNvbnN0cnVjdG9yKXx8byE9PUFycmF5JiYhSHQoby5wcm90b3R5cGUpP1AobykmJm51bGw9PT0obz1vW3F0XSkmJihvPXZvaWQgMCk6bz12b2lkIDApLG5ldyh2b2lkIDA9PT1vP0FycmF5Om8pKDA9PT1uPzA6bil9LFd0PUl0KFwic3BlY2llc1wiKSxZdD1JdChcImlzQ29uY2F0U3ByZWFkYWJsZVwiKSxfdD05MDA3MTk5MjU0NzQwOTkxLFF0PVwiTWF4aW11bSBhbGxvd2VkIGluZGV4IGV4Y2VlZGVkXCIsWHQ9QnQ+PTUxfHwhdSgoZnVuY3Rpb24oKXt2YXIgdD1bXTtyZXR1cm4gdFtZdF09ITEsdC5jb25jYXQoKVswXSE9PXR9KSksJHQ9KGp0PVwiY29uY2F0XCIsQnQ+PTUxfHwhdSgoZnVuY3Rpb24oKXt2YXIgdD1bXTtyZXR1cm4odC5jb25zdHJ1Y3Rvcj17fSlbV3RdPWZ1bmN0aW9uKCl7cmV0dXJue2ZvbzoxfX0sMSE9PXRbanRdKEJvb2xlYW4pLmZvb30pKSksdG49ZnVuY3Rpb24odCl7aWYoIVAodCkpcmV0dXJuITE7dmFyIG49dFtZdF07cmV0dXJuIHZvaWQgMCE9PW4/ISFuOkh0KHQpfTshZnVuY3Rpb24odCxuKXt2YXIgbyxyLGUsYSx1LGY9dC50YXJnZXQsYz10Lmdsb2JhbCxsPXQuc3RhdDtpZihvPWM/aTpsP2lbZl18fE0oZix7fSk6KGlbZl18fHt9KS5wcm90b3R5cGUpZm9yKHIgaW4gbil7aWYoYT1uW3JdLGU9dC5ub1RhcmdldEdldD8odT1rdChvLHIpKSYmdS52YWx1ZTpvW3JdLCF5dChjP3I6ZisobD9cIi5cIjpcIiNcIikrcix0LmZvcmNlZCkmJnZvaWQgMCE9PWUpe2lmKHR5cGVvZiBhPT10eXBlb2YgZSljb250aW51ZTtSdChhLGUpfSh0LnNoYW18fGUmJmUuc2hhbSkmJk8oYSxcInNoYW1cIiwhMCksZXQobyxyLGEsdCl9fSh7dGFyZ2V0OlwiQXJyYXlcIixwcm90bzohMCxmb3JjZWQ6IVh0fHwhJHR9LHtjb25jYXQ6ZnVuY3Rpb24odCl7dmFyIG4sbyxyLGUsYSxpPU90KHRoaXMpLHU9S3QoaSwwKSxmPTA7Zm9yKG49LTEscj1hcmd1bWVudHMubGVuZ3RoO248cjtuKyspaWYodG4oYT0tMT09PW4/aTphcmd1bWVudHNbbl0pKXtpZihmKyhlPW10KGEubGVuZ3RoKSk+X3QpdGhyb3cgVHlwZUVycm9yKFF0KTtmb3Iobz0wO288ZTtvKyssZisrKW8gaW4gYSYmTXQodSxmLGFbb10pfWVsc2V7aWYoZj49X3QpdGhyb3cgVHlwZUVycm9yKFF0KTtNdCh1LGYrKyxhKX1yZXR1cm4gdS5sZW5ndGg9Zix1fX0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiYWYtWkFcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMuYWY9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJCZXNpZyBvbSB0ZSBsYWFpLCB3YWcgYXNzZWJsaWVmXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcmVrb3JkcyBwZXIgYmxhZHN5XCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJSZXN1bHRhdGUgXCIuY29uY2F0KHQsXCIgdG90IFwiKS5jb25jYXQobixcIiB2YW4gXCIpLmNvbmNhdChvLFwiIHJ5ZSAoZmlsdGVyZWQgZnJvbSBcIikuY29uY2F0KHIsXCIgdG90YWwgcm93cylcIik6XCJSZXN1bHRhdGUgXCIuY29uY2F0KHQsXCIgdG90IFwiKS5jb25jYXQobixcIiB2YW4gXCIpLmNvbmNhdChvLFwiIHJ5ZVwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwicHJldmlvdXMgcGFnZVwifSxmb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dDpmdW5jdGlvbih0KXtyZXR1cm5cInRvIHBhZ2UgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwibmV4dCBwYWdlXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCJTaG93aW5nIFwiLmNvbmNhdCh0LFwiIHJvd3NcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbGVhciBTZWFyY2hcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJTb2VrXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiR2VlbiByZWtvcmRzIGdldmluZCBuaWVcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiV3lzL3ZlcmJlcmcgYmxhZHN5IG51bW1lcmluZ1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBwYWdpbmF0aW9uXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhlcmxhYWlcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCJXaXNzZWxcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiS29sb21tZVwifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb2dnbGUgYWxsXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIkZ1bGxzY3JlZW5cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiQWxsXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnQgZGF0YVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImFmLVpBXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImFyLVNBXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLmFyPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwi2KzYp9ix2Yog2KfZhNiq2K3ZhdmK2YQsINmK2LHYrNmJINin2YTYpdmG2KrYuNin2LFcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiDYs9is2YQg2YTZg9mEINi12YHYrdipXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCLYp9mE2LjYp9mH2LEgXCIuY29uY2F0KHQsXCIg2KXZhNmJIFwiKS5jb25jYXQobixcIiDZhdmGIFwiKS5jb25jYXQobyxcIiDYs9is2YQgXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwi2KfZhNi42KfZh9ixIFwiLmNvbmNhdCh0LFwiINil2YTZiSBcIikuY29uY2F0KG4sXCIg2YXZhiBcIikuY29uY2F0KG8sXCIg2LPYrNmEXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNsZWFyIFNlYXJjaFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cItio2K3Yq1wifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cItmE2Kcg2KrZiNis2K8g2YbYqtin2KbYrCDZhdi32KfYqNmC2Kkg2YTZhNio2K3Yq1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLYpdiu2YHYp9ih2KXYuNmH2KfYsSDYqtix2YLZitmFINin2YTYtdmB2K3Yp9iqXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwi2KrYrdiv2YrYq1wifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cItiq2LrZitmK2LFcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwi2KPYudmF2K/YqVwifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb2dnbGUgYWxsXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIkZ1bGxzY3JlZW5cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiQWxsXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnQgZGF0YVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImFyLVNBXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImJnLUJHXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLmJnPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwi0JfQsNGA0LXQttC00LDQvdC1LCDQvNC+0LvRjyDQuNC30YfQsNC60LDQudGC0LVcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiDRgNC10LTQsCDQvdCwINGB0YLRgNCw0L3QuNGG0LBcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cItCf0L7QutCw0LfQsNC90Lgg0YDQtdC00L7QstC1INC+0YIgXCIuY29uY2F0KHQsXCIg0LTQviBcIikuY29uY2F0KG4sXCIg0L7RgiBcIikuY29uY2F0KG8sXCIg0YDQtdC00LAgKNGE0LjQu9GC0YDQuNGA0LDQvdC4INC+0YIg0L7QsdGJ0L4gXCIpLmNvbmNhdChyLFwiINGA0LXQtNCwKVwiKTpcItCf0L7QutCw0LfQsNC90Lgg0YDQtdC00L7QstC1INC+0YIgXCIuY29uY2F0KHQsXCIg0LTQviBcIikuY29uY2F0KG4sXCIg0L7RgiDQvtCx0YnQviBcIikuY29uY2F0KG8sXCIg0YDQtdC00LBcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cItC/0YDQtdC00LjRiNC90LAg0YHRgtGA0LDQvdC40YbQsFwifSxmb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dDpmdW5jdGlvbih0KXtyZXR1cm5cItC00L4g0YHRgtGA0LDQvdC40YbQsCBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCLRgdC70LXQtNCy0LDRidCwINGB0YLRgNCw0L3QuNGG0LBcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cItCf0L7QutCw0LfQsNC90LggXCIuY29uY2F0KHQsXCIg0YDQtdC00LBcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLQmNC30YfQuNGB0YLQstCw0L3QtSDQvdCwINGC0YrRgNGB0LXQvdC10YLQvlwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cItCi0YrRgNGB0LXQvdC1XCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwi0J3QtSDRgdCwINC90LDQvNC10YDQtdC90Lgg0YHRitCy0L/QsNC00LDRidC4INC30LDQv9C40YHQuFwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLQodC60YDQuNCy0LDQvdC1L9Cf0L7QutCw0LfQstCw0L3QtSDQvdCwINGB0YLRgNCw0L3QuNGG0LjRgNCw0L3QtVwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwi0J/QvtC60LDQt9Cy0LDQvdC1INC90LAg0YHRgtGA0LDQvdC40YbQuNGA0LDQvdC1XCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwi0KHQutGA0LjQstCw0L3QtSDQvdCwINGB0YLRgNCw0L3QuNGG0LjRgNCw0L3QtVwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLQntCx0L3QvtCy0Y/QstCw0L3QtVwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cItCf0YDQtdCy0LrQu9GO0YfQstCw0L3QtVwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwi0J/QvtC60LDQt9Cy0LDQvdC1INC90LAg0LjQt9Cz0LvQtdC0INC60LDRgNGC0LBcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCLQodC60YDQuNCy0LDQvdC1INC90LAg0LjQt9Cz0LvQtdC0INC60LDRgNGC0LBcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwi0JrQvtC70L7QvdC4XCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cItCf0YDQtdCy0LrQu9GO0YfQstCw0L3QtSDQvdCwINCy0YHQuNGH0LrQuFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCLQptGP0Lsg0LXQutGA0LDQvVwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCLQktGB0LjRh9C60LhcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cItCQ0LLRgtC+0LzQsNGC0LjRh9C90L4g0L7QsdC90L7QstGP0LLQsNC90LVcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCLQldC60YHQv9C+0YDRgiDQvdCwINC00LDQvdC90LhcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCLQntCi0JjQlNCYXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLQoNCw0LfRiNC40YDQtdC90L4g0YLRitGA0YHQtdC90LVcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwi0JfQsNGC0LLQsNGA0Y/QvdC1XCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJiZy1CR1wiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJjYS1FU1wiXT1vLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcy5jYT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIkVzcGVyZXUsIHNpIHVzIHBsYXVcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiByZXN1bHRhdHMgcGVyIHDDoGdpbmFcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIk1vc3RyYW50IGRlIFwiLmNvbmNhdCh0LFwiIGZpbnMgXCIpLmNvbmNhdChuLFwiIC0gdG90YWwgXCIpLmNvbmNhdChvLFwiIHJlc3VsdGF0cyAoZmlsdGVyZWQgZnJvbSBcIikuY29uY2F0KHIsXCIgdG90YWwgcm93cylcIik6XCJNb3N0cmFudCBkZSBcIi5jb25jYXQodCxcIiBmaW5zIFwiKS5jb25jYXQobixcIiAtIHRvdGFsIFwiKS5jb25jYXQobyxcIiByZXN1bHRhdHNcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQ2xlYXIgU2VhcmNoXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQ2VyY2FcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCJObyBzJ2hhbiB0cm9iYXQgcmVzdWx0YXRzXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFtYWdhL01vc3RyYSBwYWdpbmFjacOzXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiUmVmcmVzY2FcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCJBbHRlcm5hIGZvcm1hdGFjacOzXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNhcmQgdmlld1wifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY2FyZCB2aWV3XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvbHVtbmVzXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZ2dsZSBhbGxcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiRnVsbHNjcmVlblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb3RzXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnQgZGF0YVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImNhLUVTXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImNzLUNaXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLmNzPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwixIxla2VqdGUsIHByb3PDrW1cIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiBwb2xvxb5layBuYSBzdHLDoW5rdVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiWm9icmF6ZW5hIFwiLmNvbmNhdCh0LFwiLiAtIFwiKS5jb25jYXQobixcIiAuIHBvbG/FvmthIHogY2Vsa292w71jaCBcIikuY29uY2F0KG8sXCIgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiWm9icmF6ZW5hIFwiLmNvbmNhdCh0LFwiLiAtIFwiKS5jb25jYXQobixcIiAuIHBvbG/FvmthIHogY2Vsa292w71jaCBcIikuY29uY2F0KG8pfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNsZWFyIFNlYXJjaFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlZ5aGxlZMOhdsOhbsOtXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiTmVuYWxlemVuYSDFvsOhZG7DoSB2eWhvdnVqw61jw60gcG9sb8W+a2FcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiU2tyw710L1pvYnJheml0IHN0csOhbmtvdsOhbsOtXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQWt0dWFsaXpvdmF0XCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiUMWZZXBuaVwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjYXJkIHZpZXdcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNhcmQgdmlld1wifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJTbG91cGNlXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZ2dsZSBhbGxcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiRnVsbHNjcmVlblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJWxaFlXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnQgZGF0YVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImNzLUNaXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImRhLURLXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLmRhPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiSW5kbMOmc2VyLCB2ZW50IHZlbmxpZ3N0XCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcG9zdGVyIHByIHNpZGVcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIlZpc2VyIFwiLmNvbmNhdCh0LFwiIHRpbCBcIikuY29uY2F0KG4sXCIgYWYgXCIpLmNvbmNhdChvLFwiIHLDpmtrZVwiKS5jb25jYXQobz4xP1wiclwiOlwiXCIsXCIgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiVmlzZXIgXCIuY29uY2F0KHQsXCIgdGlsIFwiKS5jb25jYXQobixcIiBhZiBcIikuY29uY2F0KG8sXCIgcsOma2tlXCIpLmNvbmNhdChvPjE/XCJyXCI6XCJcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiVmlzZXIgXCIuY29uY2F0KHQsXCIgcsOma2tlXCIpLmNvbmNhdCh0PjE/XCJyXCI6XCJcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJSeWQgZmlsdHJlXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiU8O4Z1wifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIkluZ2VuIHBvc3RlciBmdW5kZXRcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiU2tqdWwvdmlzIG51bW1lcmVyaW5nXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiT3BkYXRlclwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIlNraWZ0XCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNhcmQgdmlld1wifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY2FyZCB2aWV3XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cIktvbG9ubmVyXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZ2dsZSBhbGxcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiRnVsbHNjcmVlblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJBbGxlXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFa3Nwb3J0ZXJcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJkYS1ES1wiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJkZS1ERVwiXT1vLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcy5kZT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIlplaWxlbiBrb3BpZXJlblwifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiRHJ1Y2tlblwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiTGFkZSwgYml0dGUgd2FydGVuXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgWmVpbGVuIHBybyBTZWl0ZS5cIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIlplaWdlIFplaWxlIFwiLmNvbmNhdCh0LFwiIGJpcyBcIikuY29uY2F0KG4sXCIgdm9uIFwiKS5jb25jYXQobyxcIiBaZWlsZVwiKS5jb25jYXQobz4xP1wiblwiOlwiXCIsXCIgKEdlZmlsdGVydCB2b24gXCIpLmNvbmNhdChyLFwiIFplaWxlXCIpLmNvbmNhdChyPjE/XCJuXCI6XCJcIixcIilcIik6XCJaZWlnZSBaZWlsZSBcIi5jb25jYXQodCxcIiBiaXMgXCIpLmNvbmNhdChuLFwiIHZvbiBcIikuY29uY2F0KG8sXCIgWmVpbGVcIikuY29uY2F0KG8+MT9cIm5cIjpcIlwiLFwiLlwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwiVm9yaGVyaWdlIFNlaXRlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwiWnUgU2VpdGUgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwiTsOkY2hzdGUgU2VpdGVcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlplaWdlIFwiLmNvbmNhdCh0LFwiIFplaWxlXCIpLmNvbmNhdCh0PjE/XCJuXCI6XCJcIixcIi5cIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJMw7ZzY2hlIEZpbHRlclwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlN1Y2hlblwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIktlaW5lIHBhc3NlbmRlbiBFcmdlYm5pc3NlIGdlZnVuZGVuXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlZlcnN0ZWNrZS9aZWlnZSBOdW1tZXJpZXJ1bmdcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlplaWdlIE51bW1lcmllcnVuZ1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIlZlcnN0ZWNrZSBOdW1tZXJpZXJ1bmdcIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiTmV1IGxhZGVuXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiVW1zY2hhbHRlblwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiTm9ybWFsZSBBbnNpY2h0XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiS2FydGVuYW5zaWNodFwifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJTcGFsdGVuXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIkFsbGUgdW1zY2hhbHRlblwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJWb2xsYmlsZFwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJBbGxlXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvbWF0aXNjaGVzIE5ldWxhZGVuXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRGF0ZW5leHBvcnRcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJTcHJpbmdlblwifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiRXJ3ZWl0ZXJ0ZSBTdWNoZVwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTY2hsaWXDn2VuXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlZlcnN0ZWNrZS9aZWlnZSBGaWx0ZXJcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIlZlcnN0ZWNrZSBGaWx0ZXJcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlplaWdlIEZpbHRlclwifSxmb3JtYXRBZGRMZXZlbDpmdW5jdGlvbigpe3JldHVyblwiRWJlbmUgaGluenVmw7xnZW5cIn0sZm9ybWF0Q2FuY2VsOmZ1bmN0aW9uKCl7cmV0dXJuXCJBYmJyZWNoZW5cIn0sZm9ybWF0Q29sdW1uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTcGFsdGVcIn0sZm9ybWF0RGVsZXRlTGV2ZWw6ZnVuY3Rpb24oKXtyZXR1cm5cIkViZW5lIGVudGZlcm5lblwifSxmb3JtYXREdXBsaWNhdGVBbGVydFRpdGxlOmZ1bmN0aW9uKCl7cmV0dXJuXCJEb3BwZWx0ZSBFaW50csOkZ2UgZ2VmdW5kZW4hXCJ9LGZvcm1hdER1cGxpY2F0ZUFsZXJ0RGVzY3JpcHRpb246ZnVuY3Rpb24oKXtyZXR1cm5cIkJpdHRlIGRvcHBlbHRlIFNwYWx0ZW4gZW50ZmVuZW4gb2RlciDDpG5kZXJuXCJ9LGZvcm1hdE11bHRpcGxlU29ydDpmdW5jdGlvbigpe3JldHVyblwiTWVocmZhY2hzb3J0aWVydW5nXCJ9LGZvcm1hdE9yZGVyOmZ1bmN0aW9uKCl7cmV0dXJuXCJSZWloZW5mb2xnZVwifSxmb3JtYXRTb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJTb3J0aWVyZW5cIn0sZm9ybWF0U29ydEJ5OmZ1bmN0aW9uKCl7cmV0dXJuXCJTb3J0aWVyZW4gbmFjaFwifSxmb3JtYXRUaGVuQnk6ZnVuY3Rpb24oKXtyZXR1cm5cImFuc2NobGllw59lbmRcIn0sZm9ybWF0U29ydE9yZGVyczpmdW5jdGlvbigpe3JldHVybnthc2M6XCJBdWZzdGVpZ2VuZFwiLGRlc2M6XCJBYnN0ZWlnZW5kXCJ9fX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJkZS1ERVwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJlbC1HUlwiXT1vLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcy5lbD17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIs6mzr/Pgc+Ez47Ovc61zrksIM+AzrHPgc6xzrrOsc67z44gz4DOtc+BzrnOvM6tzr3Otc+EzrVcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiDOsc+Azr/PhM61zrvOrc+DzrzOsc+EzrEgzrHOvc6sIM+DzrXOu86vzrTOsVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wizpXOvM+GzrHOvc6vzrbOv869z4TOsc65IM6xz4DPjCDPhM63zr0gXCIuY29uY2F0KHQsXCIgz4nPgiDPhM63zr0gXCIpLmNvbmNhdChuLFwiIM6xz4DPjCDPg8+Nzr3Ov867zr8gXCIpLmNvbmNhdChvLFwiIM+DzrXOuc+Bz47OvSAoZmlsdGVyZWQgZnJvbSBcIikuY29uY2F0KHIsXCIgdG90YWwgcm93cylcIik6XCLOlc68z4bOsc69zq/Ots6/zr3PhM6xzrkgzrHPgM+MIM+EzrfOvSBcIi5jb25jYXQodCxcIiDPic+CIM+EzrfOvSBcIikuY29uY2F0KG4sXCIgzrHPgM+MIM+Dz43Ovc6/zrvOvyBcIikuY29uY2F0KG8sXCIgz4POtc65z4HPjs69XCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNsZWFyIFNlYXJjaFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIs6Rzr3Osc62zrfPhM6uz4PPhM61XCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwizpTOtc69IM6yz4HOrc64zrfOus6xzr0gzrHPgM6/z4TOtc67zq3Pg868zrHPhM6xXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiUmVmcmVzaFwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZ2dsZVwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjYXJkIHZpZXdcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNhcmQgdmlld1wifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb2x1bW5zXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZ2dsZSBhbGxcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiRnVsbHNjcmVlblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJBbGxcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVmcmVzaFwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4cG9ydCBkYXRhXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiR09cIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFkdmFuY2VkIHNlYXJjaFwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbG9zZVwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY29udHJvbHNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiZWwtR1JcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiZW4tVVNcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMuZW49e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJMb2FkaW5nLCBwbGVhc2Ugd2FpdFwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIHJvd3MgcGVyIHBhZ2VcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgdG8gXCIpLmNvbmNhdChuLFwiIG9mIFwiKS5jb25jYXQobyxcIiByb3dzIChmaWx0ZXJlZCBmcm9tIFwiKS5jb25jYXQocixcIiB0b3RhbCByb3dzKVwiKTpcIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgdG8gXCIpLmNvbmNhdChuLFwiIG9mIFwiKS5jb25jYXQobyxcIiByb3dzXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNsZWFyIFNlYXJjaFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlNlYXJjaFwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIk5vIG1hdGNoaW5nIHJlY29yZHMgZm91bmRcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJSZWZyZXNoXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNhcmQgdmlld1wifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY2FyZCB2aWV3XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvbHVtbnNcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkFsbFwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0IGRhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJlbi1VU1wiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJlcy1BUlwiXT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcGlhciBGaWxhc1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiSW1wcmltaXJcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhcmdhbmRvLCBlc3BlcmUgcG9yIGZhdm9yXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcmVnaXN0cm9zIHBvciBww6FnaW5hXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJNb3N0cmFuZG8gZGVzZGUgXCIuY29uY2F0KHQsXCIgYSBcIikuY29uY2F0KG4sXCIgZGUgXCIpLmNvbmNhdChvLFwiIGZpbGFzIChmaWx0cmFkbyBkZSBcIikuY29uY2F0KHIsXCIgY29sdW1uYXMgdG90YWxlcylcIik6XCJNb3N0cmFuZG8gZGVzZGUgXCIuY29uY2F0KHQsXCIgYSBcIikuY29uY2F0KG4sXCIgZGUgXCIpLmNvbmNhdChvLFwiIGZpbGFzXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJww6FnaW5hIGFudGVyaW9yXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwiYSBsYSBww6FnaW5hIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInNpZ3VpZW50ZSBww6FnaW5hXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCJNb3N0cmFuZG8gXCIuY29uY2F0KHQsXCIgY29sdW1uYXNcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJMaW1waWFyIGLDunNxdWVkYVwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkJ1c2NhclwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIk5vIHNlIGVuY29udHJhcm9uIHJlZ2lzdHJvc1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJPY3VsdGFyL01vc3RyYXIgcGFnaW5hY2nDs25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIk1vc3RyYXIgcGFnaW5hY2nDs25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJPY3VsdGFyIHBhZ2luYWNpw7NuXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlJlY2FyZ2FyXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiQ2FtYmlhclwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiTW9zdHJhciB2aXN0YSBkZSBjYXJ0YVwifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIgdmlzdGEgZGUgY2FydGFcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiQ29sdW1uYXNcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiQ2FtYmlhciB0b2RvXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIlBhbnRhbGxhIGNvbXBsZXRhXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZG9cIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVjYXJnYXJcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnRhciBkYXRvc1wifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIklyXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJCw7pzcXVlZGEgYXZhbnphZGFcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2VycmFyXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIvTW9zdHJhciBjb250cm9sZXNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIgY29udHJvbGVzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJNb3N0cmFyIGNvbnRyb2xlc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJlcy1BUlwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJlcy1DTFwiXT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcGlhciBGaWxhc1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiSW1wcmltaXJcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhcmdhbmRvLCBlc3BlcmUgcG9yIGZhdm9yXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgZmlsYXMgcG9yIHDDoWdpbmFcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIk1vc3RyYW5kbyBcIi5jb25jYXQodCxcIiBhIFwiKS5jb25jYXQobixcIiBkZSBcIikuY29uY2F0KG8sXCIgZmlsYXMgKGZpbHRyYWRvIGRlIFwiKS5jb25jYXQocixcIiBmaWxhcyB0b3RhbGVzKVwiKTpcIk1vc3RyYW5kbyBcIi5jb25jYXQodCxcIiBhIFwiKS5jb25jYXQobixcIiBkZSBcIikuY29uY2F0KG8sXCIgZmlsYXNcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInDDoWdpbmEgYW50ZXJpb3JcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJhIGxhIHDDoWdpbmEgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwic2lndWllbnRlIHDDoWdpbmFcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIk1vc3RyYW5kbyBcIi5jb25jYXQodCxcIiBmaWxhc1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkxpbXBpYXIgYsO6c3F1ZWRhXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQnVzY2FyXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiTm8gc2UgZW5jb250cmFyb24gcmVnaXN0cm9zXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIvTW9zdHJhciBwYWdpbmFjacOzblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwiTW9zdHJhciBwYWdpbmFjacOzblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIgcGFnaW5hY2nDs25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiUmVmcmVzY2FyXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiQ2FtYmlhclwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiTW9zdHJhciB2aXN0YSBkZSBjYXJ0YVwifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIgdmlzdGEgZGUgY2FydGFcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiQ29sdW1uYXNcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiQ2FtYmlhciB0b2RvXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIlBhbnRhbGxhIGNvbXBsZXRhXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZG9cIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVjYXJnYXJcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnRhciBkYXRvc1wifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIklSXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJCw7pzcXVlZGEgYXZhbnphZGFcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2VycmFyXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIvTW9zdHJhciBjb250cm9sZXNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIgY29udHJvbGVzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJNb3N0cmFyIGNvbnRyb2xlc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJlcy1DTFwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJlcy1DUlwiXT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhcmdhbmRvLCBwb3IgZmF2b3IgZXNwZXJlXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcmVnaXN0cm9zIHBvciBww6FnaW5hXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJNb3N0cmFuZG8gZGUgXCIuY29uY2F0KHQsXCIgYSBcIikuY29uY2F0KG4sXCIgcmVnaXN0cm9zIGRlIFwiKS5jb25jYXQobyxcIiByZWdpc3Ryb3MgZW4gdG90YWwgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiTW9zdHJhbmRvIGRlIFwiLmNvbmNhdCh0LFwiIGEgXCIpLmNvbmNhdChuLFwiIHJlZ2lzdHJvcyBkZSBcIikuY29uY2F0KG8sXCIgcmVnaXN0cm9zIGVuIHRvdGFsXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkxpbXBpYXIgYsO6c3F1ZWRhXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQnVzY2FyXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiTm8gc2UgZW5jb250cmFyb24gcmVnaXN0cm9zXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiUmVmcmVzY2FyXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiQWx0ZXJuYXJcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiQ29sdW1uYXNcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZG9cIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVmcmVzaFwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4cG9ydCBkYXRhXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiR09cIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFkdmFuY2VkIHNlYXJjaFwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbG9zZVwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJPY3VsdGFyL01vc3RyYXIgY29udHJvbGVzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJPY3VsdGFyIGNvbnRyb2xlc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiTW9zdHJhciBjb250cm9sZXNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiZXMtQ1JcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiZXMtRVNcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMuZXM9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3BpYXIgZmlsYXNcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkltcHJpbWlyXCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJQb3IgZmF2b3IgZXNwZXJlXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcmVzdWx0YWRvcyBwb3IgcMOhZ2luYVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiTW9zdHJhbmRvIGRlc2RlIFwiLmNvbmNhdCh0LFwiIGhhc3RhIFwiKS5jb25jYXQobixcIiAtIEVuIHRvdGFsIFwiKS5jb25jYXQobyxcIiByZXN1bHRhZG9zIChmaWx0cmFkbyBkZSBcIikuY29uY2F0KHIsXCIgZmlsYXMgdG90YWxlcylcIik6XCJNb3N0cmFuZG8gZGVzZGUgXCIuY29uY2F0KHQsXCIgaGFzdGEgXCIpLmNvbmNhdChuLFwiIC0gRW4gdG90YWwgXCIpLmNvbmNhdChvLFwiIHJlc3VsdGFkb3NcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInDDoWdpbmEgYW50ZXJpb3JcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJhIGxhIHDDoWdpbmEgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwic2lndWllbnRlIHDDoWdpbmFcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIk1vc3RyYW5kbyBcIi5jb25jYXQodCxcIiBmaWxhc1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkxpbXBpYXIgYsO6c3F1ZWRhXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQnVzY2FyXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiTm8gc2UgZW5jb250cmFyb24gcmVzdWx0YWRvc1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJPY3VsdGFyL01vc3RyYXIgcGFnaW5hY2nDs25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIk1vc3RyYXIgcGFnaW5hY2nDs25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJPY3VsdGFyIHBhZ2luYWNpw7NuXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlJlY2FyZ2FyXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiT2N1bHRhci9Nb3N0cmFyXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJNb3N0cmFyIHZpc3RhIGRlIGNhcnRhXCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiT2N1bHRhciB2aXN0YSBkZSBjYXJ0YVwifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb2x1bW5hc1wifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJDYW1iaWFyIHRvZG9cIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiUGFudGFsbGEgY29tcGxldGFcIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiVG9kb3NcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVjYXJnYXJcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnRhciBsb3MgZGF0b3NcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJJUlwifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQsO6c3F1ZWRhIGF2YW56YWRhXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNlcnJhclwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJPY3VsdGFyL01vc3RyYXIgY29udHJvbGVzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJPY3VsdGFyIGNvbnRyb2xlc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiTW9zdHJhciBjb250cm9sZXNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiZXMtRVNcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiZXMtTVhcIl09e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJDYXJnYW5kbywgZXNwZXJlIHBvciBmYXZvclwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIHJlZ2lzdHJvcyBwb3IgcMOhZ2luYVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiTW9zdHJhbmRvIFwiLmNvbmNhdCh0LFwiIGEgXCIpLmNvbmNhdChuLFwiIGRlIFwiKS5jb25jYXQobyxcIiBmaWxhcyAoZmlsdGVyZWQgZnJvbSBcIikuY29uY2F0KHIsXCIgdG90YWwgcm93cylcIik6XCJNb3N0cmFuZG8gXCIuY29uY2F0KHQsXCIgYSBcIikuY29uY2F0KG4sXCIgZGUgXCIpLmNvbmNhdChvLFwiIGZpbGFzXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIk1vc3RyYW5kbyBcIi5jb25jYXQodCxcIiBmaWxhc1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkxpbXBpYXIgYsO6c3F1ZWRhXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQnVzY2FyXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiTm8gc2UgZW5jb250cmFyb24gcmVnaXN0cm9zIHF1ZSBjb2luY2lkYW5cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiTW9zdHJhci9vY3VsdGFyIHBhZ2luYWNpw7NuXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQWN0dWFsaXphclwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhbWJpYXIgdmlzdGFcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiQ29sdW1uYXNcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJQYW50YWxsYSBjb21wbGV0YVwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb2RvXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnQgZGF0YVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiT2N1bHRhci9Nb3N0cmFyIGNvbnRyb2xlc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiT2N1bHRhciBjb250cm9sZXNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIk1vc3RyYXIgY29udHJvbGVzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImVzLU1YXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImVzLU5JXCJdPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiQ2FyZ2FuZG8sIHBvciBmYXZvciBlc3BlcmVcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiByZWdpc3Ryb3MgcG9yIHDDoWdpbmFcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIk1vc3RyYW5kbyBkZSBcIi5jb25jYXQodCxcIiBhIFwiKS5jb25jYXQobixcIiByZWdpc3Ryb3MgZGUgXCIpLmNvbmNhdChvLFwiIHJlZ2lzdHJvcyBlbiB0b3RhbCAoZmlsdGVyZWQgZnJvbSBcIikuY29uY2F0KHIsXCIgdG90YWwgcm93cylcIik6XCJNb3N0cmFuZG8gZGUgXCIuY29uY2F0KHQsXCIgYSBcIikuY29uY2F0KG4sXCIgcmVnaXN0cm9zIGRlIFwiKS5jb25jYXQobyxcIiByZWdpc3Ryb3MgZW4gdG90YWxcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiTGltcGlhciBiw7pzcXVlZGFcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJCdXNjYXJcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCJObyBzZSBlbmNvbnRyYXJvbiByZWdpc3Ryb3NcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJSZWZyZXNjYXJcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCJBbHRlcm5hclwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjYXJkIHZpZXdcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNhcmQgdmlld1wifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb2x1bW5hc1wifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb2dnbGUgYWxsXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIkZ1bGxzY3JlZW5cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiVG9kb1wifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0IGRhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIvTW9zdHJhciBjb250cm9sZXNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIgY29udHJvbGVzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJNb3N0cmFyIGNvbnRyb2xlc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJlcy1OSVwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJlcy1TUFwiXT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhcmdhbmRvLCBwb3IgZmF2b3IgZXNwZXJhXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcmVnaXN0cm9zIHBvciBwJiMyMjU7Z2luYS5cIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIlwiLmNvbmNhdCh0LFwiIC0gXCIpLmNvbmNhdChuLFwiIGRlIFwiKS5jb25jYXQobyxcIiByZWdpc3Ryb3MgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiXCIuY29uY2F0KHQsXCIgLSBcIikuY29uY2F0KG4sXCIgZGUgXCIpLmNvbmNhdChvLFwiIHJlZ2lzdHJvcy5cIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiTGltcGlhciBiw7pzcXVlZGFcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJCdXNjYXJcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCJObyBzZSBoYW4gZW5jb250cmFkbyByZWdpc3Ryb3MuXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQWN0dWFsaXphclwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkFsdGVybmFyXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNhcmQgdmlld1wifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY2FyZCB2aWV3XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvbHVtbmFzXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZ2dsZSBhbGxcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiRnVsbHNjcmVlblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb2RvXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnQgZGF0YVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiT2N1bHRhci9Nb3N0cmFyIGNvbnRyb2xlc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiT2N1bHRhciBjb250cm9sZXNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIk1vc3RyYXIgY29udHJvbGVzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImVzLVNQXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImV0LUVFXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLmV0PXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiUMOkcmluZyBrw6RpYiwgcGFsdW4gb290YVwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIHJpZGEgbGVoZSBrb2h0YVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiTsOkaXRhbiB0dWxlbXVzaSBcIi5jb25jYXQodCxcIiBrdW5pIFwiKS5jb25jYXQobixcIiAtIGtva2t1IFwiKS5jb25jYXQobyxcIiB0dWxlbXVzdCAoZmlsdGVyZWQgZnJvbSBcIikuY29uY2F0KHIsXCIgdG90YWwgcm93cylcIik6XCJOw6RpdGFuIHR1bGVtdXNpIFwiLmNvbmNhdCh0LFwiIGt1bmkgXCIpLmNvbmNhdChuLFwiIC0ga29ra3UgXCIpLmNvbmNhdChvLFwiIHR1bGVtdXN0XCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNsZWFyIFNlYXJjaFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk90c2lcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCJQw6RyaW5ndSB0aW5naW11c3RlbGUgZWkgdmFzdGFudWQgw7xodGVnaSB0dWxlbXVzdFwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJOw6RpdGEvUGVpZGEgbGVodGVkZWtzIGphZ2FtaW5lXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiVsOkcnNrZW5kYVwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkzDvGxpdGFcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiVmVlcnVkXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZ2dsZSBhbGxcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiRnVsbHNjcmVlblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJLw7Vpa1wifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0IGRhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJldC1FRVwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJldS1FVVwiXT1vLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcy5ldT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIkl0eGFyb24gbWVzZWRlelwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIGVtYWl0emEgb3JyaWtvLlwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiXCIuY29uY2F0KG8sXCIgZXJyZWdpc3Ryb2V0YXRpayBcIikuY29uY2F0KHQsXCJldGlrIFwiKS5jb25jYXQobixcImVyYWtvYWsgZXJha3VzdGVuIChmaWx0ZXJlZCBmcm9tIFwiKS5jb25jYXQocixcIiB0b3RhbCByb3dzKVwiKTpcIlwiLmNvbmNhdChvLFwiIGVycmVnaXN0cm9ldGF0aWsgXCIpLmNvbmNhdCh0LFwiZXRpayBcIikuY29uY2F0KG4sXCJlcmFrb2FrIGVyYWt1c3Rlbi5cIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQ2xlYXIgU2VhcmNoXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQmlsYXR1XCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiRXogZGEgZW1haXR6YXJpayBhdXJraXR1XCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkV6a3V0YXR1L0VyYWt1dHNpIG9ycmlrYXR6ZWFcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJFZ3VuZXJhdHVcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCJFemt1dGF0dS9FcmFrdXRzaVwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjYXJkIHZpZXdcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNhcmQgdmlld1wifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJadXRhYmVha1wifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb2dnbGUgYWxsXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIkZ1bGxzY3JlZW5cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiR3V6dGlha1wifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0IGRhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJldS1FVVwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJmYS1JUlwiXT1vLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcy5mYT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cItqp2b7bjCDYsdiv24zZgSDZh9inXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCLZvtix24zZhtiqXCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCLYr9ixINit2KfZhCDYqNin2LHar9iw2KfYsduMLCDZhNi32YHYpyDYtdio2LEg2qnZhtuM2K9cIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiDYsdqp2YjYsdivINiv2LEg2LXZgdit2YdcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cItmG2YXYp9uM2LQgXCIuY29uY2F0KHQsXCIg2KrYpyBcIikuY29uY2F0KG4sXCIg2KfYsiBcIikuY29uY2F0KG8sXCIg2LHYr9uM2YEgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwi2YbZhdin24zYtCBcIi5jb25jYXQodCxcIiDYqtinIFwiKS5jb25jYXQobixcIiDYp9iyIFwiKS5jb25jYXQobyxcIiDYsdiv24zZgVwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwi2LXZgdit2Ycg2YLYqNmE24xcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCLYqNmHINi12YHYrdmHIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIti12YHYrdmHINio2LnYr9uMXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCLZhtmF2KfbjNi0IFwiLmNvbmNhdCh0LFwiINiz2LfYsdmH2KdcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLZvtin2qkg2qnYsdiv2YYg2KzYs9iq2KzZiFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cItis2LPYqtis2YhcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCLYsdqp2YjYsdiv24wg24zYp9mB2Kog2YbYtNivLlwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLZhtmF2KfbjNi0L9mF2K7ZgduMINi12YHYrdmHINio2YbYr9uMXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCLZhtmF2KfbjNi0INi12YHYrdmHINio2YbYr9uMXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwi2b7ZhtmH2KfZhiDaqdix2K/ZhiDYtdmB2K3ZhyDYqNmG2K/bjFwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLYqNmHINix2YjYsiDYsdiz2KfZhtuMXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwi2KrYutuM24zYsSDZhtmF2KfbjNi0XCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNhcmQgdmlld1wifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY2FyZCB2aWV3XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cItiz2LfYsSDZh9inXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cItiq2LrbjNuM2LEg2YjYtti524zYqiDZh9mF2YdcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwi2KrZhdin2YUg2LXZgdit2YdcIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwi2YfZhdmHXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLYsdmB2LHYtCDYp9iq2YjZhdin2KrbjNqpXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwi2K7YsdmI2KzbjCDYr9uM2KrYp1wifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cItio2LHZiFwifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwi2KzYs9iq2KzZiNuMINm+24zYtNix2YHYqtmHXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cItio2LPYqtmGXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cItm+2YbZh9in2YYv2YbZhdin24zYtCDYr9in2K/ZhiDaqdmG2KrYsdmEINmH2KdcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cItm+2YbZh9in2YYg2qnYsdiv2YYg2qnZhtiq2LHZhCDZh9inXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCLZhtmF2KfbjNi0INqp2YbYqtix2YQg2YfYp1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJmYS1JUlwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJmaS1GSVwiXT1vLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcy5maT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIkxhZGF0YWFuLCBvbGUgaHl2w6QgamEgb2RvdGFcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiByaXZpw6Qgc2l2dWxsYVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiTsOkeXRldMOkw6RuIHJpdml0IFwiLmNvbmNhdCh0LFwiIC0gXCIpLmNvbmNhdChuLFwiIC8gXCIpLmNvbmNhdChvLFwiIChmaWx0ZXJlZCBmcm9tIFwiKS5jb25jYXQocixcIiB0b3RhbCByb3dzKVwiKTpcIk7DpHl0ZXTDpMOkbiByaXZpdCBcIi5jb25jYXQodCxcIiAtIFwiKS5jb25jYXQobixcIiAvIFwiKS5jb25jYXQobyl9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiUG9pc3RhIHN1b2RhdHRpbWV0XCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiSGFlXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiSGFrdWVodG9qYSB2YXN0YWF2aWEgdHVsb2tzaWEgZWkgbMO2eXR5bnl0XCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk7DpHl0w6QvUGlpbG90YSBzaXZ1dHVzXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiUMOkaXZpdMOkXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiVmFsaXRzZVwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjYXJkIHZpZXdcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNhcmQgdmlld1wifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJTYXJha2tlZXRcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkthaWtraVwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiVmllIHRpZWRvdFwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImZpLUZJXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImZyLUJFXCJdPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiQ2hhcmdlbWVudCBlbiBjb3Vyc1wifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIGxpZ25lcyBwYXIgcGFnZVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiQWZmaWNoZSBkZSBcIi5jb25jYXQodCxcIiDDoCBcIikuY29uY2F0KG4sXCIgc3VyIFwiKS5jb25jYXQobyxcIiBsaWduZXMgKGZpbHRyw6lzIMOgIHBhcnRpciBkZSBcIikuY29uY2F0KHIsXCIgbGlnbmVzKVwiKTpcIkFmZmljaGUgZGUgXCIuY29uY2F0KHQsXCIgw6AgXCIpLmNvbmNhdChuLFwiIHN1ciBcIikuY29uY2F0KG8sXCIgbGlnbmVzXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwYWdlIHByw6ljw6lkZW50ZVwifSxmb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dDpmdW5jdGlvbih0KXtyZXR1cm5cInZlcnMgbGEgcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwYWdlIHN1aXZhbnRlXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCJBZmZpY2hlIFwiLmNvbmNhdCh0LFwiIGxpZ25lc1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkVmZmFjZXIgbGEgcmVjaGVyY2hlXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiUmVjaGVyY2hlXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiUGFzIGRlIGxpZ25lcyB0cm91dsOpc1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJDYWNoZXIvQWZmaWNoZXIgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwiQWZmaWNoZXIgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhY2hlciBwYWdpbmF0aW9uXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlJhZnJhaWNoaXJcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCJCYXNjdWxlclwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiQWZmaWNoZXIgdnVlIGNhcnRlXCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiQ2FjaGVyIHZ1ZSBjYXJ0ZVwifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb2xvbm5lc1wifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb3V0IGJhc2N1bGVyXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIlBsZWluIMOpY3JhblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb3V0XCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJSYWZyYcOuY2hpc3NlbWVudCBhdXRvbWF0aXF1ZVwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4cG9ydGVyIGxlcyBkb25uw6llc1wifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkFsbGVyIMOgXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJSZWNoZXJjaGUgYXZhbmPDqWVcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiRmVybWVyXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhY2hlci9BZmZpY2hlciBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiQ2FjaGVyIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJBZmZpY2hlciBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJmci1CRVwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJmci1DSFwiXT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIkNoYXJnZW1lbnQgZW4gY291cnNcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiBsaWduZXMgcGFyIHBhZ2VcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIkFmZmljaGUgZGUgXCIuY29uY2F0KHQsXCIgw6AgXCIpLmNvbmNhdChuLFwiIHN1ciBcIikuY29uY2F0KG8sXCIgbGlnbmVzIChmaWx0csOpcyDDoCBwYXJ0aXIgZGUgXCIpLmNvbmNhdChyLFwiIGxpZ25lcylcIik6XCJBZmZpY2hlIGRlIFwiLmNvbmNhdCh0LFwiIMOgIFwiKS5jb25jYXQobixcIiBzdXIgXCIpLmNvbmNhdChvLFwiIGxpZ25lc1wiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwicGFnZSBwcsOpY8OpZGVudGVcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ2ZXJzIGxhIHBhZ2UgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwicGFnZSBzdWl2YW50ZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiQWZmaWNoZSBcIi5jb25jYXQodCxcIiBsaWduZXNcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJFZmZhY2VyIGxhIHJlY2hlcmNoZVwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlJlY2hlcmNoZVwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIlBhcyBkZSBsaWduZXMgdHJvdXbDqXNcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiQ2FjaGVyL0FmZmljaGVyIHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIkFmZmljaGVyIHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJDYWNoZXIgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJSYWZyYWljaGlyXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiQmFzY3VsZXJcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIkFmZmljaGVyIHZ1ZSBjYXJ0ZVwifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhY2hlciB2dWUgY2FydGVcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiQ29sb25uZXNcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG91dCBiYXNjdWxlclwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJQbGVpbiDDqWNyYW5cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiVG91dFwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiUmFmcmHDrmNoaXNzZW1lbnQgYXV0b21hdGlxdWVcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnRlciBsZXMgZG9ubsOpZXNcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJBbGxlciDDoFwifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiUmVjaGVyY2hlIGF2YW5jw6llXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkZlcm1lclwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJDYWNoZXIvQWZmaWNoZXIgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhY2hlciBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiQWZmaWNoZXIgY29udHJvbHNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiZnItQ0hcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiZnItRlJcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMuZnI9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3BpZXIgbGVzIGxpZ25lc1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiSW1wcmltZXJcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIkNoYXJnZW1lbnQgZW4gY291cnNcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiBsaWduZXMgcGFyIHBhZ2VcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIkFmZmljaGUgZGUgXCIuY29uY2F0KHQsXCIgw6AgXCIpLmNvbmNhdChuLFwiIHN1ciBcIikuY29uY2F0KG8sXCIgbGlnbmVzIChmaWx0csOpcyDDoCBwYXJ0aXIgZGUgXCIpLmNvbmNhdChyLFwiIGxpZ25lcylcIik6XCJBZmZpY2hlIGRlIFwiLmNvbmNhdCh0LFwiIMOgIFwiKS5jb25jYXQobixcIiBzdXIgXCIpLmNvbmNhdChvLFwiIGxpZ25lc1wiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwicGFnZSBwcsOpY8OpZGVudGVcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ2ZXJzIGxhIHBhZ2UgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwicGFnZSBzdWl2YW50ZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiQWZmaWNoZSBcIi5jb25jYXQodCxcIiBsaWduZXNcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJFZmZhY2VyIGxhIHJlY2hlcmNoZVwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlJlY2hlcmNoZVwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1Y3VuIHLDqXN1bHRhdFwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJNYXNxdWVyL0FmZmljaGVyIGxhIHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIkFmZmljaGVyIGxhIHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJNYXNxdWVyIGxhIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQWN0dWFsaXNlclwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkJhc2N1bGVyXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZmZpY2hlciBsYSB2dWUgY2FydGVcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJNYXNxdWVyIGxhIHZ1ZSBjYXJ0ZVwifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb2xvbm5lc1wifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb3V0IGJhc2N1bGVyXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIlBsZWluIMOpY3JhblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb3V0XCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBY3R1YWxpc2F0aW9uIGF1dG9tYXRpcXVlXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0ZXIgbGVzIGRvbm7DqWVzXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiQUxMRVJcIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlJlY2hlcmNoZSBhdmFuY8OpZVwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJGZXJtZXJcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiTWFzcXVlci9BZmZpY2hlciBsZXMgY29udHLDtGxlc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiTWFzcXVlciBsZXMgY29udHLDtGxlc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiQWZmaWNoZXIgbGVzIGNvbnRyw7RsZXNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiZnItRlJcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiZnItTFVcIl09e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJDaGFyZ2VtZW50IGVuIGNvdXJzXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgbGlnbmVzIHBhciBwYWdlXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJBZmZpY2hlIGRlIFwiLmNvbmNhdCh0LFwiIMOgIFwiKS5jb25jYXQobixcIiBzdXIgXCIpLmNvbmNhdChvLFwiIGxpZ25lcyAoZmlsdHLDqXMgw6AgcGFydGlyIGRlIFwiKS5jb25jYXQocixcIiBsaWduZXMpXCIpOlwiQWZmaWNoZSBkZSBcIi5jb25jYXQodCxcIiDDoCBcIikuY29uY2F0KG4sXCIgc3VyIFwiKS5jb25jYXQobyxcIiBsaWduZXNcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInBhZ2UgcHLDqWPDqWRlbnRlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidmVycyBsYSBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInBhZ2Ugc3VpdmFudGVcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIkFmZmljaGUgXCIuY29uY2F0KHQsXCIgbGlnbmVzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiRWZmYWNlciBsYSByZWNoZXJjaGVcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJSZWNoZXJjaGVcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCJQYXMgZGUgbGlnbmVzIHRyb3V2w6lzXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhY2hlci9BZmZpY2hlciBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZmZpY2hlciBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwiQ2FjaGVyIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiUmFmcmFpY2hpclwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkJhc2N1bGVyXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZmZpY2hlciB2dWUgY2FydGVcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJDYWNoZXIgdnVlIGNhcnRlXCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvbG9ubmVzXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvdXQgYmFzY3VsZXJcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiUGxlaW4gw6ljcmFuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvdXRcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlJhZnJhw65jaGlzc2VtZW50IGF1dG9tYXRpcXVlXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0ZXIgbGVzIGRvbm7DqWVzXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiQWxsZXIgw6BcIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlJlY2hlcmNoZSBhdmFuY8OpZVwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJGZXJtZXJcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiQ2FjaGVyL0FmZmljaGVyIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJDYWNoZXIgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIkFmZmljaGVyIGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImZyLUxVXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImhlLUlMXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLmhlPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwi15jXldei158sINeg15Ag15zXlNee16rXmdefXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIg16nXldeo15XXqiDXkdei157XldeTXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCLXntem15nXkiBcIi5jb25jYXQodCxcIiDXoteTIFwiKS5jb25jYXQobixcIiDXni1cIikuY29uY2F0KG8sXCLXqdeV16jXldeqXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwi157XpteZ15IgXCIuY29uY2F0KHQsXCIg16LXkyBcIikuY29uY2F0KG4sXCIg154tXCIpLmNvbmNhdChvLFwiINep15XXqNeV16pcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQ2xlYXIgU2VhcmNoXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwi15fXmdek15XXqVwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cItec15Ag16DXntem15DXlSDXqNep15XXnteV16og16rXldeQ157XldeqXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIteU16HXqteoL9eU16bXkiDXnteh16TXldeoINeT16TXmdedXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwi16jXoteg159cIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCLXlNeX15zXoyDXqtem15XXkteUXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNhcmQgdmlld1wifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY2FyZCB2aWV3XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cItei157XldeT15XXqlwifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb2dnbGUgYWxsXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIkZ1bGxzY3JlZW5cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwi15TXm9ecXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnQgZGF0YVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImhlLUlMXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImhyLUhSXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLmhyPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiTW9saW1vIHByacSNZWthanRlXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgYnJvaiB6YXBpc2EgcG8gc3RyYW5pY2lcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIlByaWthenVqZW0gXCIuY29uY2F0KHQsXCIuIC0gXCIpLmNvbmNhdChuLFwiLiBvZCB1a3Vwbm9nIGJyb2phIHphcGlzYSBcIikuY29uY2F0KG8sXCIgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiUHJpa2F6dWplbSBcIi5jb25jYXQodCxcIi4gLSBcIikuY29uY2F0KG4sXCIuIG9kIHVrdXBub2cgYnJvamEgemFwaXNhIFwiKS5jb25jYXQobyl9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQ2xlYXIgU2VhcmNoXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiUHJldHJhxb5pXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiTmlqZSBwcm9uYcSRZW4gbml0aSBqZWRhbiB6YXBpc1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmlrYcW+aS9zYWtyaWogc3RyYW5pY2VcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJPc3ZqZcW+aVwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIlByb21pamVuaSBwcmlrYXpcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiS29sb25lXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZ2dsZSBhbGxcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiRnVsbHNjcmVlblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJTdmVcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVmcmVzaFwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4cG9ydCBkYXRhXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiR09cIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFkdmFuY2VkIHNlYXJjaFwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbG9zZVwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY29udHJvbHNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiaHItSFJcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiaHUtSFVcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMuaHU9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJCZXTDtmx0w6lzLCBrw6lyZW0gdsOhcmpvblwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIHJla29yZCBwZXIgb2xkYWxcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIk1lZ2plbGVuw610dmUgXCIuY29uY2F0KHQsXCIgLSBcIikuY29uY2F0KG4sXCIgLyBcIikuY29uY2F0KG8sXCIgw7Zzc3plc2VuIChmaWx0ZXJlZCBmcm9tIFwiKS5jb25jYXQocixcIiB0b3RhbCByb3dzKVwiKTpcIk1lZ2plbGVuw610dmUgXCIuY29uY2F0KHQsXCIgLSBcIikuY29uY2F0KG4sXCIgLyBcIikuY29uY2F0KG8sXCIgw7Zzc3plc2VuXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNsZWFyIFNlYXJjaFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIktlcmVzw6lzXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiTmluY3MgdGFsw6FsYXRcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiTGFwb3rDsyBlbHJlanTDqXNlL21lZ2plbGVuw610w6lzZVwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBwYWdpbmF0aW9uXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkZyaXNzw610w6lzXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiw5Zzc3plY3N1ay9LaW55aXRcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiT3N6bG9wb2tcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIsOWc3N6ZXNcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVmcmVzaFwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4cG9ydCBkYXRhXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiR09cIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFkdmFuY2VkIHNlYXJjaFwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbG9zZVwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY29udHJvbHNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiaHUtSFVcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiaWQtSURcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMuaWQ9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJNZW11YXQsIG1vaG9uIHR1bmdndVwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIGJhcmlzIHBlciBoYWxhbWFuXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJNZW5hbXBpbGthbiBcIi5jb25jYXQodCxcIiBzYW1wYWkgXCIpLmNvbmNhdChuLFwiIGRhcmkgXCIpLmNvbmNhdChvLFwiIGJhcmlzIChmaWx0ZXJlZCBmcm9tIFwiKS5jb25jYXQocixcIiB0b3RhbCByb3dzKVwiKTpcIk1lbmFtcGlsa2FuIFwiLmNvbmNhdCh0LFwiIHNhbXBhaSBcIikuY29uY2F0KG4sXCIgZGFyaSBcIikuY29uY2F0KG8sXCIgYmFyaXNcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQmVyc2loa2FuIGZpbHRlclwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlBlbmNhcmlhblwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIlRpZGFrIGRpdGVtdWthbiBkYXRhIHlhbmcgY29jb2tcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiU2VtYnVueWlrYW4vVGFtcGlsa2FuIGhhbGFtYW5cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJNdWF0IHVsYW5nXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiQmVyYWxpaFwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjYXJkIHZpZXdcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNhcmQgdmlld1wifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJrb2xvbVwifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb2dnbGUgYWxsXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIkZ1bGxzY3JlZW5cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiU2VtdWFcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVmcmVzaFwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkVrc3BvciBkYXRhXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiR09cIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFkdmFuY2VkIHNlYXJjaFwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbG9zZVwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY29udHJvbHNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiaWQtSURcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiaXQtSVRcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMuaXQ9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJDYXJpY2FtZW50byBpbiBjb3Jzb1wifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIGVsZW1lbnRpIHBlciBwYWdpbmFcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIlZpc3VhbGl6emF6aW9uZSBkYSBcIi5jb25jYXQodCxcIiBhIFwiKS5jb25jYXQobixcIiBkaSBcIikuY29uY2F0KG8sXCIgZWxlbWVudGkgKGZpbHRyYXRpIGRhIFwiKS5jb25jYXQocixcIiBlbGVtZW50aSB0b3RhbGkpXCIpOlwiVmlzdWFsaXp6YXppb25lIGRhIFwiLmNvbmNhdCh0LFwiIGEgXCIpLmNvbmNhdChuLFwiIGRpIFwiKS5jb25jYXQobyxcIiBlbGVtZW50aVwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwicGFnaW5hIHByZWNlZGVudGVcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJhbGxhIHBhZ2luYSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwYWdpbmEgc3VjY2Vzc2l2YVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiTW9zdHJhbmRvIFwiLmNvbmNhdCh0LFwiIGVsZW1lbnRpXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiUHVsaXNjaSBmaWx0cmlcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJDZXJjYVwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIk5lc3N1biBlbGVtZW50byB0cm92YXRvXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk5hc2NvbmRpL01vc3RyYSBwYWdpbmF6aW9uZVwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwiTW9zdHJhIHBhZ2luYXppb25lXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwiTmFzY29uZGkgcGFnaW5hemlvbmVcIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQWdnaW9ybmFcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdHRpdmEvRGlzYXR0aXZhXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJNb3N0cmEgdmlzdWFsZSBhIHNjaGVkYVwifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIk5hc2NvbmRpIHZpc3VhbGUgYSBzY2hlZGFcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiQ29sb25uZVwifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJNb3N0cmEgdHV0dGVcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiU2NoZXJtbyBpbnRlcm9cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiVHV0dG9cIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gQWdnaW9ybmFtZW50b1wifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkVzcG9ydGEgZGF0aVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIlZBSVwifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiRmlsdHJpIGF2YW56YXRpXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNoaXVkaVwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY29udHJvbHNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiaXQtSVRcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiamEtSlBcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMuamE9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCLoqq3jgb/ovrzjgb/kuK3jgafjgZnjgILlsJHjgIXjgYrlvoXjgaHjgY/jgaDjgZXjgYTjgIJcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCLjg5rjg7zjgrjlvZPjgZ/jgormnIDlpKdcIi5jb25jYXQodCxcIuS7tlwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wi5YWoXCIuY29uY2F0KG8sXCLku7bjgYvjgonjgIFcIikuY29uY2F0KHQsXCLjgYvjgolcIikuY29uY2F0KG4sXCLku7bnm67jgb7jgafooajnpLrjgZfjgabjgYTjgb7jgZkgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwi5YWoXCIuY29uY2F0KG8sXCLku7bjgYvjgonjgIFcIikuY29uY2F0KHQsXCLjgYvjgolcIikuY29uY2F0KG4sXCLku7bnm67jgb7jgafooajnpLrjgZfjgabjgYTjgb7jgZlcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQ2xlYXIgU2VhcmNoXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwi5qSc57SiXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwi6Kmy5b2T44GZ44KL44Os44Kz44O844OJ44GM6KaL44Gk44GL44KK44G+44Gb44KTXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIuODmuODvOOCuOaVsOOCkuihqOekuuODu+mdnuihqOekulwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBwYWdpbmF0aW9uXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIuabtOaWsFwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIuODiOOCsOODq1wifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjYXJkIHZpZXdcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNhcmQgdmlld1wifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCLliJdcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIuOBmeOBueOBplwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0IGRhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJqYS1KUFwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJrYS1HRVwiXT1vLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcy5rYT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIuGDmOGDouGDleGDmOGDoOGDl+GDlOGDkeGDkCwg4YOS4YOX4YOu4YOd4YOV4YOXIOGDm+GDneGDmOGDquGDkOGDk+GDneGDl1wifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIOGDqeGDkOGDnOGDkOGDrOGDlOGDoOGDmCDhg5fhg5jhg5fhg50g4YOS4YOV4YOU4YOg4YOT4YOW4YOUXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCLhg5zhg5Dhg6nhg5Xhg5Thg5zhg5Thg5Hhg5jhg5AgXCIuY29uY2F0KHQsXCIt4YOT4YOQ4YOcIFwiKS5jb25jYXQobixcIi3hg5vhg5Phg5Qg4YOp4YOQ4YOc4YOQ4YOs4YOU4YOg4YOYIOGDr+GDkOGDm+GDo+GDoOGDmCBcIikuY29uY2F0KG8sXCIt4YOT4YOQ4YOcIChmaWx0ZXJlZCBmcm9tIFwiKS5jb25jYXQocixcIiB0b3RhbCByb3dzKVwiKTpcIuGDnOGDkOGDqeGDleGDlOGDnOGDlOGDkeGDmOGDkCBcIi5jb25jYXQodCxcIi3hg5Phg5Dhg5wgXCIpLmNvbmNhdChuLFwiLeGDm+GDk+GDlCDhg6nhg5Dhg5zhg5Dhg6zhg5Thg6Dhg5gg4YOv4YOQ4YOb4YOj4YOg4YOYIFwiKS5jb25jYXQobyxcIi3hg5Phg5Dhg5xcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQ2xlYXIgU2VhcmNoXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwi4YOr4YOU4YOR4YOc4YOQXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwi4YOb4YOd4YOc4YOQ4YOq4YOU4YOb4YOU4YOR4YOYIOGDkOGDoCDhg5Dhg6Dhg5jhg6FcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwi4YOS4YOV4YOU4YOg4YOT4YOU4YOR4YOY4YOhIOGDkuGDkOGDk+GDkOGDm+GDoOGDl+GDleGDlOGDmuGDmOGDoSDhg5Phg5Dhg5vhg5Dhg5rhg5Xhg5Av4YOS4YOQ4YOb4YOd4YOp4YOU4YOc4YOQXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwi4YOS4YOQ4YOc4YOQ4YOu4YOa4YOU4YOR4YOQXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwi4YOp4YOQ4YOg4YOX4YOV4YOQL+GDkuGDkOGDm+GDneGDoOGDl+GDleGDkFwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjYXJkIHZpZXdcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNhcmQgdmlld1wifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCLhg6Hhg5Xhg5Thg6Lhg5Thg5Hhg5hcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkFsbFwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0IGRhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJrYS1HRVwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJrby1LUlwiXT1vLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcy5rbz17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIuuNsOydtO2EsOulvCDrtojrn6zsmKTripQg7KSR7J6F64uI64ukXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwi7Y6Y7J207KeAIOuLuSBcIi5jb25jYXQodCxcIuqwnCDrjbDsnbTthLAg7Lac66ClXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCLsoITssrQgXCIuY29uY2F0KG8sXCLqsJwg7KSRIFwiKS5jb25jYXQodCxcIn5cIikuY29uY2F0KG4sXCLrsojsp7gg642w7J207YSwIOy2nOugpSwgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwi7KCE7LK0IFwiLmNvbmNhdChvLFwi6rCcIOykkSBcIikuY29uY2F0KHQsXCJ+XCIpLmNvbmNhdChuLFwi67KI7Ke4IOuNsOydtO2EsCDstpzroKUsXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNsZWFyIFNlYXJjaFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIuqygOyDiVwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIuyhsO2ajOuQnCDrjbDsnbTthLDqsIAg7JeG7Iq164uI64ukLlwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBwYWdpbmF0aW9uXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIuyDiOuhnCDqs6DsuahcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCLsoITtmZhcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwi7Lus65+8IO2VhO2EsOungVwifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb2dnbGUgYWxsXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIkZ1bGxzY3JlZW5cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiQWxsXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnQgZGF0YVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcImtvLUtSXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcIm1zLU1ZXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLm1zPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiUGVybWludGFhbiBzZWRhbmcgZGltdWF0a2FuLiBTaWxhIHR1bmdndSBzZWJlbnRhclwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIHJla29kIHNldGlhcCBtdWthIHN1cmF0XCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJTZWRhbmcgbWVtYXBhcmthbiByZWtvZCBcIi5jb25jYXQodCxcIiBoaW5nZ2EgXCIpLmNvbmNhdChuLFwiIGRhcmlwYWRhIGp1bWxhaCBcIikuY29uY2F0KG8sXCIgcmVrb2QgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiU2VkYW5nIG1lbWFwYXJrYW4gcmVrb2QgXCIuY29uY2F0KHQsXCIgaGluZ2dhIFwiKS5jb25jYXQobixcIiBkYXJpcGFkYSBqdW1sYWggXCIpLmNvbmNhdChvLFwiIHJla29kXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNsZWFyIFNlYXJjaFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhcmlcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCJUaWFkYSByZWtvZCB5YW5nIG1lbnlhbWFpIHBlcm1pbnRhYW5cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiVHVuanVrL3NlbWJ1bnlpIG11a2Egc3VyYXRcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJNdWF0c2VtdWxhXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiVHVrYXJcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiTGFqdXJcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIlNlbXVhXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnQgZGF0YVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcIm1zLU1ZXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcIm5iLU5PXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLm5iPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiT3BwZGF0ZXJlciwgdmVubmxpZ3N0IHZlbnRcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiBwb3N0ZXIgcHIgc2lkZVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiVmlzZXIgXCIuY29uY2F0KHQsXCIgdGlsIFwiKS5jb25jYXQobixcIiBhdiBcIikuY29uY2F0KG8sXCIgcmVra2VyIChmaWx0ZXJlZCBmcm9tIFwiKS5jb25jYXQocixcIiB0b3RhbCByb3dzKVwiKTpcIlZpc2VyIFwiLmNvbmNhdCh0LFwiIHRpbCBcIikuY29uY2F0KG4sXCIgYXYgXCIpLmNvbmNhdChvLFwiIHJla2tlclwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwicHJldmlvdXMgcGFnZVwifSxmb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dDpmdW5jdGlvbih0KXtyZXR1cm5cInRvIHBhZ2UgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwibmV4dCBwYWdlXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCJTaG93aW5nIFwiLmNvbmNhdCh0LFwiIHJvd3NcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbGVhciBTZWFyY2hcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJTw7hrXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiSW5nZW4gcG9zdGVyIGZ1bm5ldFwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBwYWdpbmF0aW9uXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk9wcGRhdGVyXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiRW5kcmVcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiS29sb25uZXJcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkFsbFwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0IGRhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJuYi1OT1wiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJubC1CRVwiXT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIkxhZGVuLCBldmVuIGdlZHVsZFwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIHJlY29yZHMgcGVyIHBhZ2luYVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiVG9vbiBcIi5jb25jYXQodCxcIiB0b3QgXCIpLmNvbmNhdChuLFwiIHZhbiBcIikuY29uY2F0KG8sXCIgcmVjb3JkXCIpLmNvbmNhdChvPjE/XCJzXCI6XCJcIixcIiAoZ2VmaWx0ZXJkIHZhbiBcIikuY29uY2F0KHIsXCIgcmVjb3JkcyBpbiB0b3RhYWwpXCIpOlwiVG9vbiBcIi5jb25jYXQodCxcIiB0b3QgXCIpLmNvbmNhdChuLFwiIHZhbiBcIikuY29uY2F0KG8sXCIgcmVjb3JkXCIpLmNvbmNhdChvPjE/XCJzXCI6XCJcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInZvcmlnZSBwYWdpbmFcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0b3QgcGFnaW5hIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInZvbGdlbmRlIHBhZ2luYVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiVG9vbiBcIi5jb25jYXQodCxcIiByZWNvcmRcIikuY29uY2F0KHQ+MT9cInNcIjpcIlwiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlZlcndpamRlciBmaWx0ZXJzXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiWm9la2VuXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiR2VlbiByZXN1bHRhdGVuIGdldm9uZGVuXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlZlcmJlcmcvVG9vbiBwYWdpbmVyaW5nXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb29uIHBhZ2luZXJpbmdcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJWZXJiZXJnIHBhZ2luZXJpbmdcIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiVmVybmlldXdlblwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIk9tc2NoYWtlbGVuXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb29uIGthYXJ0d2VlcmdhdmVcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJWZXJiZXJnIGthYXJ0d2VlcmdhdmVcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiS29sb21tZW5cIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiQWxsZW4gb21zY2hha2VsZW5cIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiVm9sbGVkaWcgc2NoZXJtXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkFsbGVcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG9tYXRpc2NoIHZlcm5pZXV3ZW5cIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnRlZXIgZ2VnZXZlbnNcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHQVwifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiR2VhdmFuY2VlcmQgem9la2VuXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIlNsdWl0ZW5cIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiVmVyYmVyZy9Ub29uIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJWZXJiZXJnIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJUb29uIGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcIm5sLUJFXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcIm5sLU5MXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLm5sPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiTGFkZW4sIGV2ZW4gZ2VkdWxkXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcmVjb3JkcyBwZXIgcGFnaW5hXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJUb29uIFwiLmNvbmNhdCh0LFwiIHRvdCBcIikuY29uY2F0KG4sXCIgdmFuIFwiKS5jb25jYXQobyxcIiByZWNvcmRcIikuY29uY2F0KG8+MT9cInNcIjpcIlwiLFwiIChnZWZpbHRlcmQgdmFuIFwiKS5jb25jYXQocixcIiByZWNvcmRzIGluIHRvdGFhbClcIik6XCJUb29uIFwiLmNvbmNhdCh0LFwiIHRvdCBcIikuY29uY2F0KG4sXCIgdmFuIFwiKS5jb25jYXQobyxcIiByZWNvcmRcIikuY29uY2F0KG8+MT9cInNcIjpcIlwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwidm9yaWdlIHBhZ2luYVwifSxmb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dDpmdW5jdGlvbih0KXtyZXR1cm5cInRvdCBwYWdpbmEgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwidm9sZ2VuZGUgcGFnaW5hXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCJUb29uIFwiLmNvbmNhdCh0LFwiIHJlY29yZFwiKS5jb25jYXQodD4xP1wic1wiOlwiXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiVmVyd2lqZGVyIGZpbHRlcnNcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJab2VrZW5cIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCJHZWVuIHJlc3VsdGF0ZW4gZ2V2b25kZW5cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiVmVyYmVyZy9Ub29uIHBhZ2luZXJpbmdcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlRvb24gcGFnaW5lcmluZ1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIlZlcmJlcmcgcGFnaW5lcmluZ1wifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJWZXJuaWV1d2VuXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiT21zY2hha2VsZW5cIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlRvb24ga2FhcnR3ZWVyZ2F2ZVwifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIlZlcmJlcmcga2FhcnR3ZWVyZ2F2ZVwifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJLb2xvbW1lblwifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJBbGxlbiBvbXNjaGFrZWxlblwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJWb2xsZWRpZyBzY2hlcm1cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiQWxsZVwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0b21hdGlzY2ggdmVybmlldXdlblwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4cG9ydGVlciBnZWdldmVuc1wifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdBXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJHZWF2YW5jZWVyZCB6b2VrZW5cIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiU2x1aXRlblwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJWZXJiZXJnL1Rvb24gY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIlZlcmJlcmcgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvb24gY29udHJvbHNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wibmwtTkxcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wicGwtUExcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMucGw9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJLb3BpdWogd2llcnN6ZVwifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIsWBYWRvd2FuaWUsIHByb3N6xJkgY3pla2HEh1wifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIHJla29yZMOzdyBuYSBzdHJvbsSZXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJXecWbd2lldGxhbmllIHJla29yZMOzdyBvZCBcIi5jb25jYXQodCxcIiBkbyBcIikuY29uY2F0KG4sXCIgeiBcIikuY29uY2F0KG8sXCIgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiV3nFm3dpZXRsYW5pZSByZWtvcmTDs3cgb2QgXCIuY29uY2F0KHQsXCIgZG8gXCIpLmNvbmNhdChuLFwiIHogXCIpLmNvbmNhdChvKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwicG9wcnplZG5pYSBzdHJvbmFcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ6IFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5hc3TEmXBuYSBzdHJvbmFcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIld5xZt3aWV0bGEgXCIuY29uY2F0KHQsXCIgd2llcnN6eVwiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIld5Y3p5xZvEhyB3eXN6dWtpd2FuaWVcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJTenVrYWpcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCJOaWVzdGV0eSwgbmljIG5pZSB6bmFsZXppb25vXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlBva2HFvC91a3J5aiBzdHJvbmljb3dhbmllXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJQb2thxbwgc3Ryb25pY293YW5pZVwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIlVrcnlqIHN0cm9uaWNvd2FuaWVcIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiT2TFm3dpZcW8XCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiUHJ6ZcWCxIVjelwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiUG9rYcW8IHVrxYJhZCBrYXJ0eVwifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIlVrcnlqIHVrxYJhZCBrYXJ0eVwifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJLb2x1bW55XCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlphem5hY3ogd3N6eXN0a29cIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiRnVsbHNjcmVlblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJXc3p5c3RraWVcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gb2TFm3dpZcW8YW5pZVwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkVrc3BvcnQgZGFueWNoXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiUHJ6ZWpkxbpcIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIld5c3p1a2l3YW5pZSB6YWF3YW5zb3dhbmVcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiWmFta25palwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJQb2thxbwvVWtyeWpcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIlBva2HFvFwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiVWtyeWpcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wicGwtUExcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wicHQtQlJcIl09e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJDYXJyZWdhbmRvLCBhZ3VhcmRlXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcmVnaXN0cm9zIHBvciBww6FnaW5hXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJFeGliaW5kbyBcIi5jb25jYXQodCxcIiBhdMOpIFwiKS5jb25jYXQobixcIiBkZSBcIikuY29uY2F0KG8sXCIgbGluaGFzIChmaWx0cmFkYXMgZGUgdW0gdG90YWwgZGUgXCIpLmNvbmNhdChyLFwiIGxpbmhhcylcIik6XCJFeGliaW5kbyBcIi5jb25jYXQodCxcIiBhdMOpIFwiKS5jb25jYXQobixcIiBkZSBcIikuY29uY2F0KG8sXCIgbGluaGFzXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJww6FnaW5hIGFudGVyaW9yXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwiUGFyYSBhIHDDoWdpbmEgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwicHLDs3hpbWEgcMOhZ2luYVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiTW9zdHJhbmRvIFwiLmNvbmNhdCh0LFwiIGxpbmhhc1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkxpbXBhciBQZXNxdWlzYVwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlBlc3F1aXNhclwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIk5lbmh1bSByZWdpc3RybyBlbmNvbnRyYWRvXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIvRXhpYmlyIHBhZ2luYcOnw6NvXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJNb3N0cmFyIFBhZ2luYcOnw6NvXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwiRXNjb25kZXIgUGFnaW5hw6fDo29cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiUmVjYXJyZWdhclwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkFsdGVybmFyXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNhcmQgdmlld1wifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY2FyZCB2aWV3XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvbHVuYXNcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiQWx0ZXJuYXIgdHVkb1wifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJUZWxhIGNoZWlhXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIlR1ZG9cIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF0dWFsaXphw6fDo28gQXV0b23DoXRpY2FcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnRhciBkYWRvc1wifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIklSXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJQZXNxdWlzYSBBdmFuw6dhZGFcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiRmVjaGFyXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk9jdWx0YXIvRXhpYmlyIGNvbnRyb2xlc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiT2N1bHRhciBjb250cm9sZXNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4aWJpciBjb250cm9sZXNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wicHQtQlJcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wicHQtUFRcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMucHQ9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3BpYXIgTGluaGFzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJJbXByaW1pclwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiQSBjYXJyZWdhciwgcG9yIGZhdm9yIGFndWFyZGVcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiByZWdpc3RvcyBwb3IgcMOhZ2luYVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiQSBtb3N0cmFyIFwiLmNvbmNhdCh0LFwiIGF0JmVhY3V0ZTsgXCIpLmNvbmNhdChuLFwiIGRlIFwiKS5jb25jYXQobyxcIiBsaW5oYXMgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiQSBtb3N0cmFyIFwiLmNvbmNhdCh0LFwiIGF0w6kgXCIpLmNvbmNhdChuLFwiIGRlIFwiKS5jb25jYXQobyxcIiBsaW5oYXNcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInDDoWdpbmEgYW50ZXJpb3JcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJpciBwYXJhIHDDoWdpbmEgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwicHLDs3hpbWEgcMOhZ2luYVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiTW9zdHJhbmRvIFwiLmNvbmNhdCh0LFwiIGxpbmhhc1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkxpbXBhciBQZXNxdWlzYVwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlBlc3F1aXNhXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiTmVuaHVtIHJlZ2lzdG8gZW5jb250cmFkb1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJFc2NvbmRlci9Nb3N0cmFyIHBhZ2luYcOnw6NvXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJNb3N0cmFyIHDDoWdpbmFcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJFc2NvbmRlciBww6FnaW5hXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFjdHVhbGl6YXJcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCJBbHRlcm5hclwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjYXJkIHZpZXdcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNhcmQgdmlld1wifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb2x1bmFzXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIkFjdGl2YXIgdHVkb1wifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJFY3LDoyBjb21wbGV0b1wifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJUdWRvXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBY3R1YWxpemHDp8OjbyBhdXRtw6F0aWNhXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0YXIgZGFkb3NcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdmFuw6dhclwifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiUGVzcXVpc2EgYXZhbsOnYWRhXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkZlY2hhclwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJFc2NvbmRlci9FeGliaXIgY29udHJvbG9zXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJFc2NvbmRlciBjb250cm9sb3NcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4aWJpciBjb250cm9sb3NcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wicHQtUFRcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wicm8tUk9cIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMucm89e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJTZSBpbmNhcmNhLCB2YSBydWdhbSBhc3RlcHRhdGlcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiBpbnJlZ2lzdHJhcmkgcGUgcGFnaW5hXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJBcmF0YSBkZSBsYSBcIi5jb25jYXQodCxcIiBwYW5hIGxhIFwiKS5jb25jYXQobixcIiBkaW4gXCIpLmNvbmNhdChvLFwiIHJhbmR1cmkgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiQXJhdGEgZGUgbGEgXCIuY29uY2F0KHQsXCIgcGFuYSBsYSBcIikuY29uY2F0KG4sXCIgZGluIFwiKS5jb25jYXQobyxcIiByYW5kdXJpXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNsZWFyIFNlYXJjaFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNhdXRhXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiTnUgYXUgZm9zdCBnYXNpdGUgaW5yZWdpc3RyYXJpXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFzY3VuZGUvQXJhdGEgcGFnaW5hdGlhXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIHBhZ2luYXRpb25cIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiUmVpbmNhcmNhXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiQ29tdXRhXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNhcmQgdmlld1wifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY2FyZCB2aWV3XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvbG9hbmVcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvYXRlXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvIFJlZnJlc2hcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCJFeHBvcnQgZGF0YVwifSxmb3JtYXRKdW1wVG86ZnVuY3Rpb24oKXtyZXR1cm5cIkdPXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBZHZhbmNlZCBzZWFyY2hcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiQ2xvc2VcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcInJvLVJPXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcInJ1LVJVXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLnJ1PXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwi0KHQutC+0L/QuNGA0L7QstCw0YLRjCDRgdGC0YDQvtC60LhcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cItCf0LXRh9Cw0YLRjFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwi0J/QvtC20LDQu9GD0LnRgdGC0LAsINC/0L7QtNC+0LbQtNC40YLQtSwg0LjQtNGR0YIg0LfQsNCz0YDRg9C30LrQsFwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiINC30LDQv9C40YHQtdC5INC90LAg0YHRgtGA0LDQvdC40YbRg1wiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wi0JfQsNC/0LjRgdC4INGBIFwiLmNvbmNhdCh0LFwiINC/0L4gXCIpLmNvbmNhdChuLFwiINC40LcgXCIpLmNvbmNhdChvLFwiICjQvtGC0YTQuNC70YzRgtGA0L7QstCw0L3Qviwg0LLRgdC10LPQviDQvdCwINGB0LXRgNCy0LXRgNC1IFwiKS5jb25jYXQocixcIiDQt9Cw0L/QuNGB0LXQuSlcIik6XCLQl9Cw0L/QuNGB0Lgg0YEgXCIuY29uY2F0KHQsXCIg0L/QviBcIikuY29uY2F0KG4sXCIg0LjQtyBcIikuY29uY2F0KG8pfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCLQv9GA0LXQtNGL0LTRg9GJ0LDRjyDRgdGC0YDQsNC90LjRhtCwXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwi0L/QtdGA0LXQudGC0Lgg0Log0YHRgtGA0LDQvdC40YbQtSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCLRgdC70LXQtNGD0Y7RidCw0Y8g0YHRgtGA0LDQvdC40YbQsFwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwi0JfQsNCz0YDRg9C20LXQvdC+IFwiLmNvbmNhdCh0LFwiINGB0YLRgNC+0LpcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLQntGH0LjRgdGC0LjRgtGMINGE0LjQu9GM0YLRgNGLXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwi0J/QvtC40YHQulwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cItCd0LjRh9C10LPQviDQvdC1INC90LDQudC00LXQvdC+XCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cItCh0LrRgNGL0YLRjC/Qn9C+0LrQsNC30LDRgtGMINC/0L7RgdGC0YDQsNC90LjRh9C90YPRjiDQvdCw0LLQuNCz0LDRhtC40Y5cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cItCf0L7QutCw0LfQsNGC0Ywg0L/QvtGB0YLRgNCw0L3QuNGH0L3Rg9GOINC90LDQstC40LPQsNGG0LjRjlwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cItCh0LrRgNGL0YLRjCDQv9C+0YHRgtGA0LDQvdC40YfQvdGD0Y4g0L3QsNCy0LjQs9Cw0YbQuNGOXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cItCe0LHQvdC+0LLQuNGC0YxcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCLQn9C10YDQtdC60LvRjtGH0LjRgtGMXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCLQn9C+0LrQsNC30LDRgtGMINC30LDQv9C40YHQuCDQsiDQstC40LTQtSDQutCw0YDRgtC+0YfQtdC6XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwi0KLQsNCx0LvQuNGH0L3Ri9C5INGA0LXQttC40Lwg0L/RgNC+0YHQvNC+0YLRgNCwXCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cItCa0L7Qu9C+0L3QutC4XCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cItCS0YvQsdGA0LDRgtGMINCy0YHQtVwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCLQn9C+0LvQvdC+0Y3QutGA0LDQvdC90YvQuSDRgNC10LbQuNC8XCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cItCS0YHQtVwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwi0JDQstGC0L7QvNCw0YLQuNGH0LXRgdC60L7QtSDQvtCx0L3QvtCy0LvQtdC90LjQtVwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cItCt0LrRgdC/0L7RgNGC0LjRgNC+0LLQsNGC0Ywg0LTQsNC90L3Ri9C1XCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwi0KHRgtGALlwifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwi0KDQsNGB0YjQuNGA0LXQvdC90YvQuSDQv9C+0LjRgdC6XCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cItCX0LDQutGA0YvRgtGMXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cItCh0LrRgNGL0YLRjC/Qn9C+0LrQsNC30LDRgtGMINC/0LDQvdC10LvRjCDQuNC90YHRgtGA0YPQvNC10L3RgtC+0LJcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cItCh0LrRgNGL0YLRjCDQv9Cw0L3QtdC70Ywg0LjQvdGB0YLRgNGD0LzQtdC90YLQvtCyXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCLQn9C+0LrQsNC30LDRgtGMINC/0LDQvdC10LvRjCDQuNC90YHRgtGA0YPQvNC10L3RgtC+0LJcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wicnUtUlVcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wic2stU0tcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMuc2s9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJTa29ww61yb3ZhxaUgcmlhZGt5XCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJWeXRsYcSNacWlXCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJQcm9zw61tIMSNYWthanRlXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgesOhem5hbW92IG5hIHN0cmFudVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiWm9icmF6ZW7DoSBcIi5jb25jYXQodCxcIi4gLSBcIikuY29uY2F0KG4sXCIuIHBvbG/FvmthIHogY2Vsa292w71jaCBcIikuY29uY2F0KG8sXCIgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiWm9icmF6ZW7DoSBcIi5jb25jYXQodCxcIi4gLSBcIikuY29uY2F0KG4sXCIuIHBvbG/FvmthIHogY2Vsa292w71jaCBcIikuY29uY2F0KG8pfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmVkY2jDoWR6YWrDumNhIHN0cmFuYVwifSxmb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dDpmdW5jdGlvbih0KXtyZXR1cm5cIm5hIHN0cmFudSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJOYXNsZWR1asO6Y2Egc3RyYW5hXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCJab2JyYXp1amUgc2EgXCIuY29uY2F0KHQsXCIgcmlhZGtvdlwiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk9kc3Ryw6HFiCBmaWx0cmVcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJWeWjEvmFkw6F2YW5pZVwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIk5lbsOhamRlbsOhIMW+aWFkbmEgdnlob3Z1asO6Y2EgcG9sb8W+a2FcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiU2tyeS9ab2JyYXogc3Ryw6Fua292YW5pZVwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwiWm9icmF6acWlIHN0csOhbmtvdmFuaWVcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJTa3J5xaUgc3Ryw6Fua292YW5pZVwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJPYm5vdmnFpVwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIlByZXBuaVwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwiWm9icmF6acWlIGthcnRvdsOpIHpvYnJhemVuaWVcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJza3J5xaUga2FydG92w6kgem9icmF6ZW5pZVwifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJTdMS6cGNlXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlByZXBuw7rFpSB2xaFldGt5XCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIkNlbMOhIG9icmF6b3ZrYVwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJWxaFldGt5XCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvbWF0aWNrw6kgb2Jub3ZlbmllXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0dWogZMOhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCLDjXPFpVwifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiUG9rcm/EjWlsw6kgdnloxL5hZMOhdmFuaWVcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwiWmF0dm9yacWlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlpvYnJhemnFpS9Ta3J5xaUgdGxhxI1pZGzDoVwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiU2tyecWlIHRsYcSNaWRsw6FcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlpvYnJhemnFpSB0bGHEjWlkbMOhXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcInNrLVNLXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcInNyLUN5cmwtUlNcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMuc3I9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCLQnNC+0LvQuNC8INGB0LDRh9C10LrQsNGYXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIg0YDQtdC00L7QstCwINC/0L4g0YHRgtGA0LDQvdC4XCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCLQn9GA0LjQutCw0LfQsNC90L4gXCIuY29uY2F0KHQsXCIuIC0gXCIpLmNvbmNhdChuLFwiLiDQvtC0INGD0LrRg9C/0L3QvtCzINCx0YDQvtGY0LAg0YDQtdC00L7QstCwIFwiKS5jb25jYXQobyxcIiAo0YTQuNC70YLRgNC40YDQsNC90L4g0L7QtCBcIikuY29uY2F0KHIsXCIpXCIpOlwi0J/RgNC40LrQsNC30LDQvdC+IFwiLmNvbmNhdCh0LFwiLiAtIFwiKS5jb25jYXQobixcIi4g0L7QtCDRg9C60YPQv9C90L7QsyDQsdGA0L7RmNCwINGA0LXQtNC+0LLQsCBcIikuY29uY2F0KG8pfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCLQv9GA0LXRgtGF0L7QtNC90LAg0YHRgtGA0LDQvdCwXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwi0L3QsCDRgdGC0YDQsNC90YMgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwi0YHQu9C10LTQtdGb0LAg0YHRgtGA0LDQvdCwXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCLQn9GA0LjQutCw0LfQsNC90L4gXCIuY29uY2F0KHQsXCIg0YDQtdC00L7QstCwXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwi0J7QsdGA0LjRiNC4INC/0YDQtdGC0YDQsNCz0YNcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLQn9GA0L7QvdCw0ZLQuFwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cItCd0LjRmNC1INC/0YDQvtC90LDRktC10L0g0L3QuCDRmNC10LTQsNC9INC/0L7QtNCw0YLQsNC6XCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cItCf0YDQuNC60LDQttC4L9GB0LDQutGA0LjRmCDQv9Cw0LPQuNC90LDRhtC40ZjRg1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwi0J/RgNC40LrQsNC20Lgg0L/QsNCz0LjQvdCw0YbQuNGY0YNcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCLQodCw0LrRgNC40Zgg0L/QsNCz0LjQvdCw0YbQuNGY0YNcIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwi0J7RgdCy0LXQttC4XCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwi0J/RgNC+0LzQtdC90Lgg0L/RgNC40LrQsNC3XCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCLQn9GA0LjQutCw0LbQuCDQutCw0YDRgtC40YbQtVwifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cItCh0LDQutGA0LjRmCDQutCw0YDRgtC40YbQtVwifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCLQmtC+0LvQvtC90LVcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwi0J/RgNC40LrQsNC20Lgv0YHQsNC60YDQuNGYINGB0LLQtVwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCLQptC10L4g0LXQutGA0LDQvVwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCLQodCy0LVcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cItCQ0YPRgtC+0LzQsNGC0YHQutC+INC+0YHQstC10LbQsNCy0LDRmtC1XCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwi0JjQt9Cy0LXQt9C4INC/0L7QtNCw0YLQutC1XCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwi0JjQtNC4XCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLQndCw0L/RgNC10LTQvdCwINC/0YDQtdGC0YDQsNCz0LBcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwi0JfQsNGC0LLQvtGA0LhcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hIaWRlOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlIGNvbnRyb2xzXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNvbnRyb2xzXCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcInNyLUN5cmwtUlNcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wic3ItTGF0bi1SU1wiXT17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIk1vbGltIHNhxI1la2FqXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcmVkb3ZhIHBvIHN0cmFuaVwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wiUHJpa2F6YW5vIFwiLmNvbmNhdCh0LFwiLiAtIFwiKS5jb25jYXQobixcIi4gb2QgdWt1cG5vZyBicm9qYSByZWRvdmEgXCIpLmNvbmNhdChvLFwiIChmaWx0cmlyYW5vIG9kIFwiKS5jb25jYXQocixcIilcIik6XCJQcmlrYXphbm8gXCIuY29uY2F0KHQsXCIuIC0gXCIpLmNvbmNhdChuLFwiLiBvZCB1a3Vwbm9nIGJyb2phIHJlZG92YSBcIikuY29uY2F0KG8pfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV0aG9kbmEgc3RyYW5hXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwibmEgc3RyYW51IFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInNsZWRlxIdhIHN0cmFuYVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiUHJpa2F6YW5vIFwiLmNvbmNhdCh0LFwiIHJlZG92YVwiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIk9icmnFoWkgcHJldHJhZ3VcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJQcm9uYcSRaVwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIk5pamUgcHJvbmHEkWVuIG5pIGplZGFuIHBvZGF0YWtcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiUHJpa2HFvmkvc2FrcmlqIHBhZ2luYWNpanVcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlByaWthxb5pIHBhZ2luYWNpanVcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCJTYWtyaWogcGFnaW5hY2lqdVwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJPc3Zlxb5pXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiUHJvbWVuaSBwcmlrYXpcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlByaWthxb5pIGthcnRpY2VcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCJTYWtyaWoga2FydGljZVwifSxmb3JtYXRDb2x1bW5zOmZ1bmN0aW9uKCl7cmV0dXJuXCJLb2xvbmVcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiUHJpa2HFvmkvc2FrcmlqIHN2ZVwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJDZW8gZWtyYW5cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiU3ZlXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJBdXRvbWF0c2tvIG9zdmXFvmF2YW5qZVwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkl6dmV6aSBwb2RhdGtlXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiSWRpXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJOYXByZWRuYSBwcmV0cmFnYVwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJaYXR2b3JpXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJzci1MYXRuLVJTXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcInN2LVNFXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLnN2PXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiTGFkZGFyLCB2w6RubGlnZW4gdsOkbnRhXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcmFkZXIgcGVyIHNpZGFcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIlZpc2EgXCIuY29uY2F0KHQsXCIgdGlsbCBcIikuY29uY2F0KG4sXCIgYXYgXCIpLmNvbmNhdChvLFwiIHJhZGVyIChmaWx0ZXJlZCBmcm9tIFwiKS5jb25jYXQocixcIiB0b3RhbCByb3dzKVwiKTpcIlZpc2EgXCIuY29uY2F0KHQsXCIgdGlsbCBcIikuY29uY2F0KG4sXCIgYXYgXCIpLmNvbmNhdChvLFwiIHJhZGVyXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkNsZWFyIFNlYXJjaFwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIlPDtmtcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCJJbmdhIG1hdGNoYW5kZSByZXN1bHRhdCBmdW5uYS5cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJVcHBkYXRlcmFcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCJTa2lmdGFcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwia29sdW1uXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZ2dsZSBhbGxcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiRnVsbHNjcmVlblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJBbGxcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVmcmVzaFwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4cG9ydCBkYXRhXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiR09cIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFkdmFuY2VkIHNlYXJjaFwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbG9zZVwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY29udHJvbHNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wic3YtU0VcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1widGgtVEhcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMudGg9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCLguIHguLPguKXguLHguIfguYLguKvguKXguJTguILguYnguK3guKHguLnguKUsIOC4geC4o+C4uOC4k+C4suC4o+C4reC4quC4seC4geC4hOC4o+C4ueC5iFwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiIOC4o+C4suC4ouC4geC4suC4o+C4leC5iOC4reC4q+C4meC5ieC4slwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wi4Lij4Liy4Lii4LiB4Liy4Lij4LiX4Li14LmIIFwiLmNvbmNhdCh0LFwiIOC4luC4tuC4hyBcIikuY29uY2F0KG4sXCIg4LiI4Liy4LiB4LiX4Lix4LmJ4LiH4Lir4Lih4LiUIFwiKS5jb25jYXQobyxcIiDguKPguLLguKLguIHguLLguKMgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwi4Lij4Liy4Lii4LiB4Liy4Lij4LiX4Li14LmIIFwiLmNvbmNhdCh0LFwiIOC4luC4tuC4hyBcIikuY29uY2F0KG4sXCIg4LiI4Liy4LiB4LiX4Lix4LmJ4LiH4Lir4Lih4LiUIFwiKS5jb25jYXQobyxcIiDguKPguLLguKLguIHguLLguKNcIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQ2xlYXIgU2VhcmNoXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwi4LiE4LmJ4LiZ4Lir4LiyXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwi4LmE4Lih4LmI4Lie4Lia4Lij4Liy4Lii4LiB4Liy4Lij4LiX4Li14LmI4LiE4LmJ4LiZ4Lir4LiyICFcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLguKPguLXguYDguJ/guKPguKpcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCLguKrguKXguLHguJrguKHguLjguKHguKHguK3guIdcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwi4LiE4Lit4Lil4Lix4Lih4LiZ4LmMXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIlRvZ2dsZSBhbGxcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwiRnVsbHNjcmVlblwifSxmb3JtYXRBbGxSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJBbGxcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVmcmVzaFwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4cG9ydCBkYXRhXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiR09cIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFkdmFuY2VkIHNlYXJjaFwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbG9zZVwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY29udHJvbHNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1widGgtVEhcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1widHItVFJcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMudHI9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCJZw7xrbGVuaXlvciwgbMO8dGZlbiBiZWtsZXlpblwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlNheWZhIGJhxZ/EsW5hIFwiLmNvbmNhdCh0LFwiIGthecSxdC5cIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIlwiLmNvbmNhdChvLFwiIGthecSxdHRhbiBcIikuY29uY2F0KHQsXCItXCIpLmNvbmNhdChuLFwiIGFyYXPEsSBnw7ZzdGVyaWxpeW9yIChmaWx0ZXJlZCBmcm9tIFwiKS5jb25jYXQocixcIiB0b3RhbCByb3dzKS5cIik6XCJcIi5jb25jYXQobyxcIiBrYXnEsXR0YW4gXCIpLmNvbmNhdCh0LFwiLVwiKS5jb25jYXQobixcIiBhcmFzxLEgZ8O2c3RlcmlsaXlvci5cIil9LGZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cInByZXZpb3VzIHBhZ2VcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCJ0byBwYWdlIFwiLmNvbmNhdCh0KX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIm5leHQgcGFnZVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwiU2hvd2luZyBcIi5jb25jYXQodCxcIiByb3dzXCIpfSxmb3JtYXRDbGVhclNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQ2xlYXIgU2VhcmNoXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQXJhXCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwiRcWfbGXFn2VuIGthecSxdCBidWx1bmFtYWTEsS5cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJZZW5pbGVcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCJEZcSfacWfdGlyXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNhcmQgdmlld1wifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY2FyZCB2aWV3XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cIlPDvHR1bmxhclwifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCJUb2dnbGUgYWxsXCJ9LGZvcm1hdEZ1bGxzY3JlZW46ZnVuY3Rpb24oKXtyZXR1cm5cIkZ1bGxzY3JlZW5cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwiVMO8bSBTYXTEsXJsYXJcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVmcmVzaFwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkV4cG9ydCBkYXRhXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwiR09cIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkFkdmFuY2VkIHNlYXJjaFwifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbG9zZVwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY29udHJvbHNcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaFNob3c6ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY29udHJvbHNcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1widHItVFJcIl0pLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1widWstVUFcIl09by5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXMudWs9e2Zvcm1hdENvcHlSb3dzOmZ1bmN0aW9uKCl7cmV0dXJuXCJDb3B5IFJvd3NcIn0sZm9ybWF0UHJpbnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIlByaW50XCJ9LGZvcm1hdExvYWRpbmdNZXNzYWdlOmZ1bmN0aW9uKCl7cmV0dXJuXCLQl9Cw0LLQsNC90YLQsNC20LXQvdC90Y8sINCx0YPQtNGMINC70LDRgdC60LAsINC30LDRh9C10LrQsNC50YLQtVwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIlwiLmNvbmNhdCh0LFwiINC30LDQv9C40YHRltCyINC90LAg0YHRgtC+0YDRltC90LrRg1wiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wi0J/QvtC60LDQt9Cw0L3QviDQtyBcIi5jb25jYXQodCxcIiDQv9C+IFwiKS5jb25jYXQobixcIi4g0JLRgdGM0L7Qs9C+OiBcIikuY29uY2F0KG8sXCIgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwi0J/QvtC60LDQt9Cw0L3QviDQtyBcIi5jb25jYXQodCxcIiDQv9C+IFwiKS5jb25jYXQobixcIi4g0JLRgdGM0L7Qs9C+OiBcIikuY29uY2F0KG8pfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJwcmV2aW91cyBwYWdlXCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwidG8gcGFnZSBcIi5jb25jYXQodCl9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCJuZXh0IHBhZ2VcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIlNob3dpbmcgXCIuY29uY2F0KHQsXCIgcm93c1wiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cItCe0YfQuNGB0YLQuNGC0Lgg0YTRltC70YzRgtGA0LhcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLQn9C+0YjRg9C6XCJ9LGZvcm1hdE5vTWF0Y2hlczpmdW5jdGlvbigpe3JldHVyblwi0J3QtSDQt9C90LDQudC00LXQvdC+INC20L7QtNC90L7Qs9C+INC30LDQv9C40YHRg1wifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJIaWRlL1Nob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBwYWdpbmF0aW9uXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBwYWdpbmF0aW9uXCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cItCe0L3QvtCy0LjRgtC4XCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwi0JfQvNGW0L3QuNGC0LhcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwi0KHRgtC+0LLQv9GG0ZZcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkFsbFwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0IGRhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJ1ay1VQVwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJ1ci1QS1wiXT1vLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcy51cj17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cItio2LHYp9uTINmF24HYsdio2KfZhtuMINin2YbYqti42KfYsSDaqduM2KzYptuSXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIg2LHbjNqp2KfYsdqI2LIg2YHbjCDYtdmB24EgXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCLYr9uM2qnavtuM2rogXCIuY29uY2F0KHQsXCIg2LPbkiBcIikuY29uY2F0KG4sXCIg2qnbkiBcIikuY29uY2F0KG8sXCLYsduM2qnYp9ix2ojYsiAoZmlsdGVyZWQgZnJvbSBcIikuY29uY2F0KHIsXCIgdG90YWwgcm93cylcIik6XCLYr9uM2qnavtuM2rogXCIuY29uY2F0KHQsXCIg2LPbkiBcIikuY29uY2F0KG4sXCIg2qnbkiBcIikuY29uY2F0KG8sXCLYsduM2qnYp9ix2ojYslwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwicHJldmlvdXMgcGFnZVwifSxmb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dDpmdW5jdGlvbih0KXtyZXR1cm5cInRvIHBhZ2UgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwibmV4dCBwYWdlXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCJTaG93aW5nIFwiLmNvbmNhdCh0LFwiIHJvd3NcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbGVhciBTZWFyY2hcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLYqtmE2KfYtFwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cItqp2YjYptuMINix24zaqdin2LHaiCDZhtuB24zauiDZhdmE2KdcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLYqtin2LLbgSDaqdix24zaulwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cItiq2KjYr9uM2YQg2qnYsduM2rpcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwi2qnYp9mE2YVcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkFsbFwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0IGRhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJ1ci1QS1wiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJ1ei1MYXRuLVVaXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLnV6PXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwiWXVrbGFueWFwdGksIGlsdGltb3Mga3V0aW5nXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwiXCIuY29uY2F0KHQsXCIgcWF0b3IgaGFyIHNhaGlmYWRhXCIpfSxmb3JtYXRTaG93aW5nUm93czpmdW5jdGlvbih0LG4sbyxyKXtyZXR1cm4gdm9pZCAwIT09ciYmcj4wJiZyPm8/XCJLbydyc2F0eXBhdGkgXCIuY29uY2F0KHQsXCIgZGFuIFwiKS5jb25jYXQobixcIiBnYWNoYSBcIikuY29uY2F0KG8sXCIgcWF0b3JsYXJuaSAoZmlsdGVyZWQgZnJvbSBcIikuY29uY2F0KHIsXCIgdG90YWwgcm93cylcIik6XCJLbydyc2F0eXBhdGkgXCIuY29uY2F0KHQsXCIgZGFuIFwiKS5jb25jYXQobixcIiBnYWNoYSBcIikuY29uY2F0KG8sXCIgcWF0b3JsYXJuaVwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwicHJldmlvdXMgcGFnZVwifSxmb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dDpmdW5jdGlvbih0KXtyZXR1cm5cInRvIHBhZ2UgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwibmV4dCBwYWdlXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCJTaG93aW5nIFwiLmNvbmNhdCh0LFwiIHJvd3NcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJGaWx0cmxhcm5pIHRvemFsYXNoXCJ9LGZvcm1hdFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiUWlkaXJpc2hcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCJIZWNoIG5hcnNhIHRvcGlsbWFkaVwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJTYWhpZmFsYXNobmkgeWFzaGlyaXNoL2tvJ3JzYXRpc2hcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJZYW5naWxhc2hcIn0sZm9ybWF0VG9nZ2xlOmZ1bmN0aW9uKCl7cmV0dXJuXCJLbydyaW5pc2hcIn0sZm9ybWF0VG9nZ2xlT246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgY2FyZCB2aWV3XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjYXJkIHZpZXdcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwiVXN0dW5sYXJcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkhhbW1hc2lcIn0sZm9ybWF0QXV0b1JlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkF1dG8gUmVmcmVzaFwifSxmb3JtYXRFeHBvcnQ6ZnVuY3Rpb24oKXtyZXR1cm5cIkVrc3BvcnRcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJ1ei1MYXRuLVVaXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcInZpLVZOXCJdPW8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzLnZpPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwixJBhbmcgdOG6o2lcIn0sZm9ybWF0UmVjb3Jkc1BlclBhZ2U6ZnVuY3Rpb24odCl7cmV0dXJuXCJcIi5jb25jYXQodCxcIiBi4bqjbiBnaGkgbeG7l2kgdHJhbmdcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIkhp4buDbiB0aOG7iyB04burIHRyYW5nIFwiLmNvbmNhdCh0LFwiIMSR4bq/biBcIikuY29uY2F0KG4sXCIgY+G7p2EgXCIpLmNvbmNhdChvLFwiIGLhuqNuZyBnaGkgKGZpbHRlcmVkIGZyb20gXCIpLmNvbmNhdChyLFwiIHRvdGFsIHJvd3MpXCIpOlwiSGnhu4NuIHRo4buLIHThu6sgdHJhbmcgXCIuY29uY2F0KHQsXCIgxJHhur9uIFwiKS5jb25jYXQobixcIiBj4bunYSBcIikuY29uY2F0KG8sXCIgYuG6o25nIGdoaVwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwicHJldmlvdXMgcGFnZVwifSxmb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dDpmdW5jdGlvbih0KXtyZXR1cm5cInRvIHBhZ2UgXCIuY29uY2F0KHQpfSxmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dDpmdW5jdGlvbigpe3JldHVyblwibmV4dCBwYWdlXCJ9LGZvcm1hdERldGFpbFBhZ2luYXRpb246ZnVuY3Rpb24odCl7cmV0dXJuXCJTaG93aW5nIFwiLmNvbmNhdCh0LFwiIHJvd3NcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJDbGVhciBTZWFyY2hcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJUw6xtIGtp4bq/bVwifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIktow7RuZyBjw7MgZOG7ryBsaeG7h3VcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwiSGlkZS9TaG93IHBhZ2luYXRpb25cIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaERvd246ZnVuY3Rpb24oKXtyZXR1cm5cIlNob3cgcGFnaW5hdGlvblwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXA6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgcGFnaW5hdGlvblwifSxmb3JtYXRSZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCJSZWZyZXNoXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCJTaG93IGNhcmQgdmlld1wifSxmb3JtYXRUb2dnbGVPZmY6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUgY2FyZCB2aWV3XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvbHVtbnNcIn0sZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDpmdW5jdGlvbigpe3JldHVyblwiVG9nZ2xlIGFsbFwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCJGdWxsc2NyZWVuXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkFsbFwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwiQXV0byBSZWZyZXNoXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwiRXhwb3J0IGRhdGFcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCJHT1wifSxmb3JtYXRBZHZhbmNlZFNlYXJjaDpmdW5jdGlvbigpe3JldHVyblwiQWR2YW5jZWQgc2VhcmNoXCJ9LGZvcm1hdEFkdmFuY2VkQ2xvc2VCdXR0b246ZnVuY3Rpb24oKXtyZXR1cm5cIkNsb3NlXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIkhpZGUvU2hvdyBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwiSGlkZSBjb250cm9sc1wifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwiU2hvdyBjb250cm9sc1wifX0sby5kZWZhdWx0LmV4dGVuZChvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMsby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJ2aS1WTlwiXSksby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmxvY2FsZXNbXCJ6aC1DTlwiXT1vLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcy56aD17Zm9ybWF0Q29weVJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIkNvcHkgUm93c1wifSxmb3JtYXRQcmludDpmdW5jdGlvbigpe3JldHVyblwiUHJpbnRcIn0sZm9ybWF0TG9hZGluZ01lc3NhZ2U6ZnVuY3Rpb24oKXtyZXR1cm5cIuato+WcqOWKquWKm+WcsOWKoOi9veaVsOaNruS4re+8jOivt+eojeWAmVwifSxmb3JtYXRSZWNvcmRzUGVyUGFnZTpmdW5jdGlvbih0KXtyZXR1cm5cIuavj+mhteaYvuekuiBcIi5jb25jYXQodCxcIiDmnaHorrDlvZVcIil9LGZvcm1hdFNob3dpbmdSb3dzOmZ1bmN0aW9uKHQsbixvLHIpe3JldHVybiB2b2lkIDAhPT1yJiZyPjAmJnI+bz9cIuaYvuekuuesrCBcIi5jb25jYXQodCxcIiDliLDnrKwgXCIpLmNvbmNhdChuLFwiIOadoeiusOW9le+8jOaAu+WFsSBcIikuY29uY2F0KG8sXCIg5p2h6K6w5b2V77yI5LuOIFwiKS5jb25jYXQocixcIiDmgLvorrDlvZXkuK3ov4fmu6TvvIlcIik6XCLmmL7npLrnrKwgXCIuY29uY2F0KHQsXCIg5Yiw56ysIFwiKS5jb25jYXQobixcIiDmnaHorrDlvZXvvIzmgLvlhbEgXCIpLmNvbmNhdChvLFwiIOadoeiusOW9lVwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uUHJlVGV4dDpmdW5jdGlvbigpe3JldHVyblwi5LiK5LiA6aG1XCJ9LGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OmZ1bmN0aW9uKHQpe3JldHVyblwi56ysXCIuY29uY2F0KHQsXCLpobVcIil9LGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCLkuIvkuIDpobVcIn0sZm9ybWF0RGV0YWlsUGFnaW5hdGlvbjpmdW5jdGlvbih0KXtyZXR1cm5cIuaAu+WFsSBcIi5jb25jYXQodCxcIiDmnaHorrDlvZVcIil9LGZvcm1hdENsZWFyU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLmuIXnqbrov4fmu6RcIn0sZm9ybWF0U2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLmkJzntKJcIn0sZm9ybWF0Tm9NYXRjaGVzOmZ1bmN0aW9uKCl7cmV0dXJuXCLmsqHmnInmib7liLDljLnphY3nmoTorrDlvZVcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwi6ZqQ6JePL+aYvuekuuWIhumhtVwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bjpmdW5jdGlvbigpe3JldHVyblwi5pi+56S65YiG6aG1XCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDpmdW5jdGlvbigpe3JldHVyblwi6ZqQ6JeP5YiG6aG1XCJ9LGZvcm1hdFJlZnJlc2g6ZnVuY3Rpb24oKXtyZXR1cm5cIuWIt+aWsFwifSxmb3JtYXRUb2dnbGU6ZnVuY3Rpb24oKXtyZXR1cm5cIuWIh+aNolwifSxmb3JtYXRUb2dnbGVPbjpmdW5jdGlvbigpe3JldHVyblwi5pi+56S65Y2h54mH6KeG5Zu+XCJ9LGZvcm1hdFRvZ2dsZU9mZjpmdW5jdGlvbigpe3JldHVyblwi6ZqQ6JeP5Y2h54mH6KeG5Zu+XCJ9LGZvcm1hdENvbHVtbnM6ZnVuY3Rpb24oKXtyZXR1cm5cIuWIl1wifSxmb3JtYXRDb2x1bW5zVG9nZ2xlQWxsOmZ1bmN0aW9uKCl7cmV0dXJuXCLliIfmjaLmiYDmnIlcIn0sZm9ybWF0RnVsbHNjcmVlbjpmdW5jdGlvbigpe3JldHVyblwi5YWo5bGPXCJ9LGZvcm1hdEFsbFJvd3M6ZnVuY3Rpb24oKXtyZXR1cm5cIuaJgOaciVwifSxmb3JtYXRBdXRvUmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwi6Ieq5Yqo5Yi35pawXCJ9LGZvcm1hdEV4cG9ydDpmdW5jdGlvbigpe3JldHVyblwi5a+85Ye65pWw5o2uXCJ9LGZvcm1hdEp1bXBUbzpmdW5jdGlvbigpe3JldHVyblwi6Lez6L2sXCJ9LGZvcm1hdEFkdmFuY2VkU2VhcmNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLpq5jnuqfmkJzntKJcIn0sZm9ybWF0QWR2YW5jZWRDbG9zZUJ1dHRvbjpmdW5jdGlvbigpe3JldHVyblwi5YWz6ZetXCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2g6ZnVuY3Rpb24oKXtyZXR1cm5cIumakOiXjy/mmL7npLrov4fmu6TmjqfliLZcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaEhpZGU6ZnVuY3Rpb24oKXtyZXR1cm5cIumakOiXj+i/h+a7pOaOp+WItlwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoU2hvdzpmdW5jdGlvbigpe3JldHVyblwi5pi+56S66L+H5ruk5o6n5Yi2XCJ9fSxvLmRlZmF1bHQuZXh0ZW5kKG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5kZWZhdWx0cyxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcInpoLUNOXCJdKSxvLmRlZmF1bHQuZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlc1tcInpoLVRXXCJdPXtmb3JtYXRDb3B5Um93czpmdW5jdGlvbigpe3JldHVyblwiQ29weSBSb3dzXCJ9LGZvcm1hdFByaW50OmZ1bmN0aW9uKCl7cmV0dXJuXCJQcmludFwifSxmb3JtYXRMb2FkaW5nTWVzc2FnZTpmdW5jdGlvbigpe3JldHVyblwi5q2j5Zyo5Yqq5Yqb5Zyw6LyJ5YWl6LOH5paZ77yM6KuL56iN5YCZXCJ9LGZvcm1hdFJlY29yZHNQZXJQYWdlOmZ1bmN0aW9uKHQpe3JldHVyblwi5q+P6aCB6aGv56S6IFwiLmNvbmNhdCh0LFwiIOmgheiomOmMhFwiKX0sZm9ybWF0U2hvd2luZ1Jvd3M6ZnVuY3Rpb24odCxuLG8scil7cmV0dXJuIHZvaWQgMCE9PXImJnI+MCYmcj5vP1wi6aGv56S656ysIFwiLmNvbmNhdCh0LFwiIOWIsOesrCBcIikuY29uY2F0KG4sXCIg6aCF6KiY6YyE77yM57i95YWxIFwiKS5jb25jYXQobyxcIiDpoIXoqJjpjITvvIjlvp4gXCIpLmNvbmNhdChyLFwiIOe4veiomOmMhOS4remBjua/vu+8iVwiKTpcIumhr+ekuuesrCBcIi5jb25jYXQodCxcIiDliLDnrKwgXCIpLmNvbmNhdChuLFwiIOmgheiomOmMhO+8jOe4veWFsSBcIikuY29uY2F0KG8sXCIg6aCF6KiY6YyEXCIpfSxmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OmZ1bmN0aW9uKCl7cmV0dXJuXCLkuIrkuIDpoIFcIn0sZm9ybWF0U1JQYWdpbmF0aW9uUGFnZVRleHQ6ZnVuY3Rpb24odCl7cmV0dXJuXCLnrKxcIi5jb25jYXQodCxcIumggVwiKX0sZm9ybWF0U1JQYWdpbmF0aW9uTmV4dFRleHQ6ZnVuY3Rpb24oKXtyZXR1cm5cIuS4i+S4gOmggVwifSxmb3JtYXREZXRhaWxQYWdpbmF0aW9uOmZ1bmN0aW9uKHQpe3JldHVyblwi57i95YWxIFwiLmNvbmNhdCh0LFwiIOmgheiomOmMhFwiKX0sZm9ybWF0Q2xlYXJTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIua4heepuumBjua/vlwifSxmb3JtYXRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIuaQnOWwi1wifSxmb3JtYXROb01hdGNoZXM6ZnVuY3Rpb24oKXtyZXR1cm5cIuaykuacieaJvuWIsOespuWQiOeahOe1kOaenFwifSxmb3JtYXRQYWdpbmF0aW9uU3dpdGNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLpmrHol48v6aGv56S65YiG6aCBXCJ9LGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOmZ1bmN0aW9uKCl7cmV0dXJuXCLpoa/npLrliIbpoIFcIn0sZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwOmZ1bmN0aW9uKCl7cmV0dXJuXCLpmrHol4/liIbpoIFcIn0sZm9ybWF0UmVmcmVzaDpmdW5jdGlvbigpe3JldHVyblwi6YeN5paw5pW055CGXCJ9LGZvcm1hdFRvZ2dsZTpmdW5jdGlvbigpe3JldHVyblwi5YiH5o+bXCJ9LGZvcm1hdFRvZ2dsZU9uOmZ1bmN0aW9uKCl7cmV0dXJuXCLpoa/npLrljaHniYfoppblnJZcIn0sZm9ybWF0VG9nZ2xlT2ZmOmZ1bmN0aW9uKCl7cmV0dXJuXCLpmrHol4/ljaHniYfoppblnJZcIn0sZm9ybWF0Q29sdW1uczpmdW5jdGlvbigpe3JldHVyblwi5YiXXCJ9LGZvcm1hdENvbHVtbnNUb2dnbGVBbGw6ZnVuY3Rpb24oKXtyZXR1cm5cIuWIh+aPm+aJgOaciVwifSxmb3JtYXRGdWxsc2NyZWVuOmZ1bmN0aW9uKCl7cmV0dXJuXCLlhajlsY9cIn0sZm9ybWF0QWxsUm93czpmdW5jdGlvbigpe3JldHVyblwi5omA5pyJXCJ9LGZvcm1hdEF1dG9SZWZyZXNoOmZ1bmN0aW9uKCl7cmV0dXJuXCLoh6rli5XliLfmlrBcIn0sZm9ybWF0RXhwb3J0OmZ1bmN0aW9uKCl7cmV0dXJuXCLlsI7lh7rmlbjmk5pcIn0sZm9ybWF0SnVtcFRvOmZ1bmN0aW9uKCl7cmV0dXJuXCLot7PovYlcIn0sZm9ybWF0QWR2YW5jZWRTZWFyY2g6ZnVuY3Rpb24oKXtyZXR1cm5cIumrmOe0muaQnOWwi1wifSxmb3JtYXRBZHZhbmNlZENsb3NlQnV0dG9uOmZ1bmN0aW9uKCl7cmV0dXJuXCLpl5zplolcIn0sZm9ybWF0RmlsdGVyQ29udHJvbFN3aXRjaDpmdW5jdGlvbigpe3JldHVyblwi6Zqx6JePL+mhr+ekuumBjua/vuaOp+WItlwifSxmb3JtYXRGaWx0ZXJDb250cm9sU3dpdGNoSGlkZTpmdW5jdGlvbigpe3JldHVyblwi6Zqx6JeP6YGO5r++5o6n5Yi2XCJ9LGZvcm1hdEZpbHRlckNvbnRyb2xTd2l0Y2hTaG93OmZ1bmN0aW9uKCl7cmV0dXJuXCLpoa/npLrpgY7mv77mjqfliLZcIn19LG8uZGVmYXVsdC5leHRlbmQoby5kZWZhdWx0LmZuLmJvb3RzdHJhcFRhYmxlLmRlZmF1bHRzLG8uZGVmYXVsdC5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzW1wiemgtVFdcIl0pfSkpO1xuIiwiKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KHJlcXVpcmUoJ2pxdWVyeScpKSA6XG4gIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2pxdWVyeSddLCBmYWN0b3J5KSA6XG4gIChnbG9iYWwgPSB0eXBlb2YgZ2xvYmFsVGhpcyAhPT0gJ3VuZGVmaW5lZCcgPyBnbG9iYWxUaGlzIDogZ2xvYmFsIHx8IHNlbGYsIGdsb2JhbC5Cb290c3RyYXBUYWJsZSA9IGZhY3RvcnkoZ2xvYmFsLmpRdWVyeSkpO1xufSh0aGlzLCAoZnVuY3Rpb24gKCQpIHsgJ3VzZSBzdHJpY3QnO1xuXG4gIGZ1bmN0aW9uIF9pbnRlcm9wRGVmYXVsdExlZ2FjeSAoZSkgeyByZXR1cm4gZSAmJiB0eXBlb2YgZSA9PT0gJ29iamVjdCcgJiYgJ2RlZmF1bHQnIGluIGUgPyBlIDogeyAnZGVmYXVsdCc6IGUgfTsgfVxuXG4gIHZhciAkX19kZWZhdWx0ID0gLyojX19QVVJFX18qL19pbnRlcm9wRGVmYXVsdExlZ2FjeSgkKTtcblxuICBmdW5jdGlvbiBfdHlwZW9mKG9iaikge1xuICAgIFwiQGJhYmVsL2hlbHBlcnMgLSB0eXBlb2ZcIjtcblxuICAgIGlmICh0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIFN5bWJvbC5pdGVyYXRvciA9PT0gXCJzeW1ib2xcIikge1xuICAgICAgX3R5cGVvZiA9IGZ1bmN0aW9uIChvYmopIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBvYmo7XG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBfdHlwZW9mID0gZnVuY3Rpb24gKG9iaikge1xuICAgICAgICByZXR1cm4gb2JqICYmIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvYmouY29uc3RydWN0b3IgPT09IFN5bWJvbCAmJiBvYmogIT09IFN5bWJvbC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogdHlwZW9mIG9iajtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIF90eXBlb2Yob2JqKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHtcbiAgICBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBfZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTtcbiAgICAgIGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTtcbiAgICAgIGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTtcbiAgICAgIGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gX2NyZWF0ZUNsYXNzKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykge1xuICAgIGlmIChwcm90b1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpO1xuICAgIGlmIChzdGF0aWNQcm9wcykgX2RlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTtcbiAgICByZXR1cm4gQ29uc3RydWN0b3I7XG4gIH1cblxuICBmdW5jdGlvbiBfc2xpY2VkVG9BcnJheShhcnIsIGkpIHtcbiAgICByZXR1cm4gX2FycmF5V2l0aEhvbGVzKGFycikgfHwgX2l0ZXJhYmxlVG9BcnJheUxpbWl0KGFyciwgaSkgfHwgX3Vuc3VwcG9ydGVkSXRlcmFibGVUb0FycmF5KGFyciwgaSkgfHwgX25vbkl0ZXJhYmxlUmVzdCgpO1xuICB9XG5cbiAgZnVuY3Rpb24gX3RvQ29uc3VtYWJsZUFycmF5KGFycikge1xuICAgIHJldHVybiBfYXJyYXlXaXRob3V0SG9sZXMoYXJyKSB8fCBfaXRlcmFibGVUb0FycmF5KGFycikgfHwgX3Vuc3VwcG9ydGVkSXRlcmFibGVUb0FycmF5KGFycikgfHwgX25vbkl0ZXJhYmxlU3ByZWFkKCk7XG4gIH1cblxuICBmdW5jdGlvbiBfYXJyYXlXaXRob3V0SG9sZXMoYXJyKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoYXJyKSkgcmV0dXJuIF9hcnJheUxpa2VUb0FycmF5KGFycik7XG4gIH1cblxuICBmdW5jdGlvbiBfYXJyYXlXaXRoSG9sZXMoYXJyKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoYXJyKSkgcmV0dXJuIGFycjtcbiAgfVxuXG4gIGZ1bmN0aW9uIF9pdGVyYWJsZVRvQXJyYXkoaXRlcikge1xuICAgIGlmICh0eXBlb2YgU3ltYm9sICE9PSBcInVuZGVmaW5lZFwiICYmIFN5bWJvbC5pdGVyYXRvciBpbiBPYmplY3QoaXRlcikpIHJldHVybiBBcnJheS5mcm9tKGl0ZXIpO1xuICB9XG5cbiAgZnVuY3Rpb24gX2l0ZXJhYmxlVG9BcnJheUxpbWl0KGFyciwgaSkge1xuICAgIGlmICh0eXBlb2YgU3ltYm9sID09PSBcInVuZGVmaW5lZFwiIHx8ICEoU3ltYm9sLml0ZXJhdG9yIGluIE9iamVjdChhcnIpKSkgcmV0dXJuO1xuICAgIHZhciBfYXJyID0gW107XG4gICAgdmFyIF9uID0gdHJ1ZTtcbiAgICB2YXIgX2QgPSBmYWxzZTtcbiAgICB2YXIgX2UgPSB1bmRlZmluZWQ7XG5cbiAgICB0cnkge1xuICAgICAgZm9yICh2YXIgX2kgPSBhcnJbU3ltYm9sLml0ZXJhdG9yXSgpLCBfczsgIShfbiA9IChfcyA9IF9pLm5leHQoKSkuZG9uZSk7IF9uID0gdHJ1ZSkge1xuICAgICAgICBfYXJyLnB1c2goX3MudmFsdWUpO1xuXG4gICAgICAgIGlmIChpICYmIF9hcnIubGVuZ3RoID09PSBpKSBicmVhaztcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIF9kID0gdHJ1ZTtcbiAgICAgIF9lID0gZXJyO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoIV9uICYmIF9pW1wicmV0dXJuXCJdICE9IG51bGwpIF9pW1wicmV0dXJuXCJdKCk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBpZiAoX2QpIHRocm93IF9lO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBfYXJyO1xuICB9XG5cbiAgZnVuY3Rpb24gX3Vuc3VwcG9ydGVkSXRlcmFibGVUb0FycmF5KG8sIG1pbkxlbikge1xuICAgIGlmICghbykgcmV0dXJuO1xuICAgIGlmICh0eXBlb2YgbyA9PT0gXCJzdHJpbmdcIikgcmV0dXJuIF9hcnJheUxpa2VUb0FycmF5KG8sIG1pbkxlbik7XG4gICAgdmFyIG4gPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobykuc2xpY2UoOCwgLTEpO1xuICAgIGlmIChuID09PSBcIk9iamVjdFwiICYmIG8uY29uc3RydWN0b3IpIG4gPSBvLmNvbnN0cnVjdG9yLm5hbWU7XG4gICAgaWYgKG4gPT09IFwiTWFwXCIgfHwgbiA9PT0gXCJTZXRcIikgcmV0dXJuIEFycmF5LmZyb20obyk7XG4gICAgaWYgKG4gPT09IFwiQXJndW1lbnRzXCIgfHwgL14oPzpVaXxJKW50KD86OHwxNnwzMikoPzpDbGFtcGVkKT9BcnJheSQvLnRlc3QobikpIHJldHVybiBfYXJyYXlMaWtlVG9BcnJheShvLCBtaW5MZW4pO1xuICB9XG5cbiAgZnVuY3Rpb24gX2FycmF5TGlrZVRvQXJyYXkoYXJyLCBsZW4pIHtcbiAgICBpZiAobGVuID09IG51bGwgfHwgbGVuID4gYXJyLmxlbmd0aCkgbGVuID0gYXJyLmxlbmd0aDtcblxuICAgIGZvciAodmFyIGkgPSAwLCBhcnIyID0gbmV3IEFycmF5KGxlbik7IGkgPCBsZW47IGkrKykgYXJyMltpXSA9IGFycltpXTtcblxuICAgIHJldHVybiBhcnIyO1xuICB9XG5cbiAgZnVuY3Rpb24gX25vbkl0ZXJhYmxlU3ByZWFkKCkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIGF0dGVtcHQgdG8gc3ByZWFkIG5vbi1pdGVyYWJsZSBpbnN0YW5jZS5cXG5JbiBvcmRlciB0byBiZSBpdGVyYWJsZSwgbm9uLWFycmF5IG9iamVjdHMgbXVzdCBoYXZlIGEgW1N5bWJvbC5pdGVyYXRvcl0oKSBtZXRob2QuXCIpO1xuICB9XG5cbiAgZnVuY3Rpb24gX25vbkl0ZXJhYmxlUmVzdCgpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiSW52YWxpZCBhdHRlbXB0IHRvIGRlc3RydWN0dXJlIG5vbi1pdGVyYWJsZSBpbnN0YW5jZS5cXG5JbiBvcmRlciB0byBiZSBpdGVyYWJsZSwgbm9uLWFycmF5IG9iamVjdHMgbXVzdCBoYXZlIGEgW1N5bWJvbC5pdGVyYXRvcl0oKSBtZXRob2QuXCIpO1xuICB9XG5cbiAgZnVuY3Rpb24gX2NyZWF0ZUZvck9mSXRlcmF0b3JIZWxwZXIobywgYWxsb3dBcnJheUxpa2UpIHtcbiAgICB2YXIgaXQ7XG5cbiAgICBpZiAodHlwZW9mIFN5bWJvbCA9PT0gXCJ1bmRlZmluZWRcIiB8fCBvW1N5bWJvbC5pdGVyYXRvcl0gPT0gbnVsbCkge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkobykgfHwgKGl0ID0gX3Vuc3VwcG9ydGVkSXRlcmFibGVUb0FycmF5KG8pKSB8fCBhbGxvd0FycmF5TGlrZSAmJiBvICYmIHR5cGVvZiBvLmxlbmd0aCA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICBpZiAoaXQpIG8gPSBpdDtcbiAgICAgICAgdmFyIGkgPSAwO1xuXG4gICAgICAgIHZhciBGID0gZnVuY3Rpb24gKCkge307XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzOiBGLFxuICAgICAgICAgIG46IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChpID49IG8ubGVuZ3RoKSByZXR1cm4ge1xuICAgICAgICAgICAgICBkb25lOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgZG9uZTogZmFsc2UsXG4gICAgICAgICAgICAgIHZhbHVlOiBvW2krK11cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfSxcbiAgICAgICAgICBlOiBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIGY6IEZcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgYXR0ZW1wdCB0byBpdGVyYXRlIG5vbi1pdGVyYWJsZSBpbnN0YW5jZS5cXG5JbiBvcmRlciB0byBiZSBpdGVyYWJsZSwgbm9uLWFycmF5IG9iamVjdHMgbXVzdCBoYXZlIGEgW1N5bWJvbC5pdGVyYXRvcl0oKSBtZXRob2QuXCIpO1xuICAgIH1cblxuICAgIHZhciBub3JtYWxDb21wbGV0aW9uID0gdHJ1ZSxcbiAgICAgICAgZGlkRXJyID0gZmFsc2UsXG4gICAgICAgIGVycjtcbiAgICByZXR1cm4ge1xuICAgICAgczogZnVuY3Rpb24gKCkge1xuICAgICAgICBpdCA9IG9bU3ltYm9sLml0ZXJhdG9yXSgpO1xuICAgICAgfSxcbiAgICAgIG46IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHN0ZXAgPSBpdC5uZXh0KCk7XG4gICAgICAgIG5vcm1hbENvbXBsZXRpb24gPSBzdGVwLmRvbmU7XG4gICAgICAgIHJldHVybiBzdGVwO1xuICAgICAgfSxcbiAgICAgIGU6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGRpZEVyciA9IHRydWU7XG4gICAgICAgIGVyciA9IGU7XG4gICAgICB9LFxuICAgICAgZjogZnVuY3Rpb24gKCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGlmICghbm9ybWFsQ29tcGxldGlvbiAmJiBpdC5yZXR1cm4gIT0gbnVsbCkgaXQucmV0dXJuKCk7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgaWYgKGRpZEVycikgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIHZhciBjb21tb25qc0dsb2JhbCA9IHR5cGVvZiBnbG9iYWxUaGlzICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbFRoaXMgOiB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnID8gc2VsZiA6IHt9O1xuXG4gIGZ1bmN0aW9uIGNyZWF0ZUNvbW1vbmpzTW9kdWxlKGZuLCBtb2R1bGUpIHtcbiAgXHRyZXR1cm4gbW9kdWxlID0geyBleHBvcnRzOiB7fSB9LCBmbihtb2R1bGUsIG1vZHVsZS5leHBvcnRzKSwgbW9kdWxlLmV4cG9ydHM7XG4gIH1cblxuICB2YXIgY2hlY2sgPSBmdW5jdGlvbiAoaXQpIHtcbiAgICByZXR1cm4gaXQgJiYgaXQuTWF0aCA9PSBNYXRoICYmIGl0O1xuICB9O1xuXG4gIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS96bG9pcm9jay9jb3JlLWpzL2lzc3Vlcy84NiNpc3N1ZWNvbW1lbnQtMTE1NzU5MDI4XG4gIHZhciBnbG9iYWxfMSA9XG4gICAgLyogZ2xvYmFsIGdsb2JhbFRoaXMgLS0gc2FmZSAqL1xuICAgIGNoZWNrKHR5cGVvZiBnbG9iYWxUaGlzID09ICdvYmplY3QnICYmIGdsb2JhbFRoaXMpIHx8XG4gICAgY2hlY2sodHlwZW9mIHdpbmRvdyA9PSAnb2JqZWN0JyAmJiB3aW5kb3cpIHx8XG4gICAgY2hlY2sodHlwZW9mIHNlbGYgPT0gJ29iamVjdCcgJiYgc2VsZikgfHxcbiAgICBjaGVjayh0eXBlb2YgY29tbW9uanNHbG9iYWwgPT0gJ29iamVjdCcgJiYgY29tbW9uanNHbG9iYWwpIHx8XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLW5ldy1mdW5jIC0tIGZhbGxiYWNrXG4gICAgKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0pKCkgfHwgRnVuY3Rpb24oJ3JldHVybiB0aGlzJykoKTtcblxuICB2YXIgZmFpbHMgPSBmdW5jdGlvbiAoZXhlYykge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gISFleGVjKCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfTtcblxuICAvLyBEZXRlY3QgSUU4J3MgaW5jb21wbGV0ZSBkZWZpbmVQcm9wZXJ0eSBpbXBsZW1lbnRhdGlvblxuICB2YXIgZGVzY3JpcHRvcnMgPSAhZmFpbHMoZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkoe30sIDEsIHsgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiA3OyB9IH0pWzFdICE9IDc7XG4gIH0pO1xuXG4gIHZhciBuYXRpdmVQcm9wZXJ0eUlzRW51bWVyYWJsZSA9IHt9LnByb3BlcnR5SXNFbnVtZXJhYmxlO1xuICB2YXIgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yJDQgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yO1xuXG4gIC8vIE5hc2hvcm4gfiBKREs4IGJ1Z1xuICB2YXIgTkFTSE9STl9CVUcgPSBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IkNCAmJiAhbmF0aXZlUHJvcGVydHlJc0VudW1lcmFibGUuY2FsbCh7IDE6IDIgfSwgMSk7XG5cbiAgLy8gYE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGVgIG1ldGhvZCBpbXBsZW1lbnRhdGlvblxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9iamVjdC5wcm90b3R5cGUucHJvcGVydHlpc2VudW1lcmFibGVcbiAgdmFyIGYkNCA9IE5BU0hPUk5fQlVHID8gZnVuY3Rpb24gcHJvcGVydHlJc0VudW1lcmFibGUoVikge1xuICAgIHZhciBkZXNjcmlwdG9yID0gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yJDQodGhpcywgVik7XG4gICAgcmV0dXJuICEhZGVzY3JpcHRvciAmJiBkZXNjcmlwdG9yLmVudW1lcmFibGU7XG4gIH0gOiBuYXRpdmVQcm9wZXJ0eUlzRW51bWVyYWJsZTtcblxuICB2YXIgb2JqZWN0UHJvcGVydHlJc0VudW1lcmFibGUgPSB7XG4gIFx0ZjogZiQ0XG4gIH07XG5cbiAgdmFyIGNyZWF0ZVByb3BlcnR5RGVzY3JpcHRvciA9IGZ1bmN0aW9uIChiaXRtYXAsIHZhbHVlKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGVudW1lcmFibGU6ICEoYml0bWFwICYgMSksXG4gICAgICBjb25maWd1cmFibGU6ICEoYml0bWFwICYgMiksXG4gICAgICB3cml0YWJsZTogIShiaXRtYXAgJiA0KSxcbiAgICAgIHZhbHVlOiB2YWx1ZVxuICAgIH07XG4gIH07XG5cbiAgdmFyIHRvU3RyaW5nID0ge30udG9TdHJpbmc7XG5cbiAgdmFyIGNsYXNzb2ZSYXcgPSBmdW5jdGlvbiAoaXQpIHtcbiAgICByZXR1cm4gdG9TdHJpbmcuY2FsbChpdCkuc2xpY2UoOCwgLTEpO1xuICB9O1xuXG4gIHZhciBzcGxpdCA9ICcnLnNwbGl0O1xuXG4gIC8vIGZhbGxiYWNrIGZvciBub24tYXJyYXktbGlrZSBFUzMgYW5kIG5vbi1lbnVtZXJhYmxlIG9sZCBWOCBzdHJpbmdzXG4gIHZhciBpbmRleGVkT2JqZWN0ID0gZmFpbHMoZnVuY3Rpb24gKCkge1xuICAgIC8vIHRocm93cyBhbiBlcnJvciBpbiByaGlubywgc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9tb3ppbGxhL3JoaW5vL2lzc3Vlcy8zNDZcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcHJvdG90eXBlLWJ1aWx0aW5zIC0tIHNhZmVcbiAgICByZXR1cm4gIU9iamVjdCgneicpLnByb3BlcnR5SXNFbnVtZXJhYmxlKDApO1xuICB9KSA/IGZ1bmN0aW9uIChpdCkge1xuICAgIHJldHVybiBjbGFzc29mUmF3KGl0KSA9PSAnU3RyaW5nJyA/IHNwbGl0LmNhbGwoaXQsICcnKSA6IE9iamVjdChpdCk7XG4gIH0gOiBPYmplY3Q7XG5cbiAgLy8gYFJlcXVpcmVPYmplY3RDb2VyY2libGVgIGFic3RyYWN0IG9wZXJhdGlvblxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXJlcXVpcmVvYmplY3Rjb2VyY2libGVcbiAgdmFyIHJlcXVpcmVPYmplY3RDb2VyY2libGUgPSBmdW5jdGlvbiAoaXQpIHtcbiAgICBpZiAoaXQgPT0gdW5kZWZpbmVkKSB0aHJvdyBUeXBlRXJyb3IoXCJDYW4ndCBjYWxsIG1ldGhvZCBvbiBcIiArIGl0KTtcbiAgICByZXR1cm4gaXQ7XG4gIH07XG5cbiAgLy8gdG9PYmplY3Qgd2l0aCBmYWxsYmFjayBmb3Igbm9uLWFycmF5LWxpa2UgRVMzIHN0cmluZ3NcblxuXG5cbiAgdmFyIHRvSW5kZXhlZE9iamVjdCA9IGZ1bmN0aW9uIChpdCkge1xuICAgIHJldHVybiBpbmRleGVkT2JqZWN0KHJlcXVpcmVPYmplY3RDb2VyY2libGUoaXQpKTtcbiAgfTtcblxuICB2YXIgaXNPYmplY3QgPSBmdW5jdGlvbiAoaXQpIHtcbiAgICByZXR1cm4gdHlwZW9mIGl0ID09PSAnb2JqZWN0JyA/IGl0ICE9PSBudWxsIDogdHlwZW9mIGl0ID09PSAnZnVuY3Rpb24nO1xuICB9O1xuXG4gIC8vIGBUb1ByaW1pdGl2ZWAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtdG9wcmltaXRpdmVcbiAgLy8gaW5zdGVhZCBvZiB0aGUgRVM2IHNwZWMgdmVyc2lvbiwgd2UgZGlkbid0IGltcGxlbWVudCBAQHRvUHJpbWl0aXZlIGNhc2VcbiAgLy8gYW5kIHRoZSBzZWNvbmQgYXJndW1lbnQgLSBmbGFnIC0gcHJlZmVycmVkIHR5cGUgaXMgYSBzdHJpbmdcbiAgdmFyIHRvUHJpbWl0aXZlID0gZnVuY3Rpb24gKGlucHV0LCBQUkVGRVJSRURfU1RSSU5HKSB7XG4gICAgaWYgKCFpc09iamVjdChpbnB1dCkpIHJldHVybiBpbnB1dDtcbiAgICB2YXIgZm4sIHZhbDtcbiAgICBpZiAoUFJFRkVSUkVEX1NUUklORyAmJiB0eXBlb2YgKGZuID0gaW5wdXQudG9TdHJpbmcpID09ICdmdW5jdGlvbicgJiYgIWlzT2JqZWN0KHZhbCA9IGZuLmNhbGwoaW5wdXQpKSkgcmV0dXJuIHZhbDtcbiAgICBpZiAodHlwZW9mIChmbiA9IGlucHV0LnZhbHVlT2YpID09ICdmdW5jdGlvbicgJiYgIWlzT2JqZWN0KHZhbCA9IGZuLmNhbGwoaW5wdXQpKSkgcmV0dXJuIHZhbDtcbiAgICBpZiAoIVBSRUZFUlJFRF9TVFJJTkcgJiYgdHlwZW9mIChmbiA9IGlucHV0LnRvU3RyaW5nKSA9PSAnZnVuY3Rpb24nICYmICFpc09iamVjdCh2YWwgPSBmbi5jYWxsKGlucHV0KSkpIHJldHVybiB2YWw7XG4gICAgdGhyb3cgVHlwZUVycm9yKFwiQ2FuJ3QgY29udmVydCBvYmplY3QgdG8gcHJpbWl0aXZlIHZhbHVlXCIpO1xuICB9O1xuXG4gIHZhciBoYXNPd25Qcm9wZXJ0eSA9IHt9Lmhhc093blByb3BlcnR5O1xuXG4gIHZhciBoYXMkMSA9IGZ1bmN0aW9uIChpdCwga2V5KSB7XG4gICAgcmV0dXJuIGhhc093blByb3BlcnR5LmNhbGwoaXQsIGtleSk7XG4gIH07XG5cbiAgdmFyIGRvY3VtZW50JDEgPSBnbG9iYWxfMS5kb2N1bWVudDtcbiAgLy8gdHlwZW9mIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQgaXMgJ29iamVjdCcgaW4gb2xkIElFXG4gIHZhciBFWElTVFMgPSBpc09iamVjdChkb2N1bWVudCQxKSAmJiBpc09iamVjdChkb2N1bWVudCQxLmNyZWF0ZUVsZW1lbnQpO1xuXG4gIHZhciBkb2N1bWVudENyZWF0ZUVsZW1lbnQgPSBmdW5jdGlvbiAoaXQpIHtcbiAgICByZXR1cm4gRVhJU1RTID8gZG9jdW1lbnQkMS5jcmVhdGVFbGVtZW50KGl0KSA6IHt9O1xuICB9O1xuXG4gIC8vIFRoYW5rJ3MgSUU4IGZvciBoaXMgZnVubnkgZGVmaW5lUHJvcGVydHlcbiAgdmFyIGllOERvbURlZmluZSA9ICFkZXNjcmlwdG9ycyAmJiAhZmFpbHMoZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkoZG9jdW1lbnRDcmVhdGVFbGVtZW50KCdkaXYnKSwgJ2EnLCB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIDc7IH1cbiAgICB9KS5hICE9IDc7XG4gIH0pO1xuXG4gIHZhciBuYXRpdmVHZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yO1xuXG4gIC8vIGBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yYCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1vYmplY3QuZ2V0b3ducHJvcGVydHlkZXNjcmlwdG9yXG4gIHZhciBmJDMgPSBkZXNjcmlwdG9ycyA/IG5hdGl2ZUdldE93blByb3BlcnR5RGVzY3JpcHRvciA6IGZ1bmN0aW9uIGdldE93blByb3BlcnR5RGVzY3JpcHRvcihPLCBQKSB7XG4gICAgTyA9IHRvSW5kZXhlZE9iamVjdChPKTtcbiAgICBQID0gdG9QcmltaXRpdmUoUCwgdHJ1ZSk7XG4gICAgaWYgKGllOERvbURlZmluZSkgdHJ5IHtcbiAgICAgIHJldHVybiBuYXRpdmVHZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoTywgUCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHsgLyogZW1wdHkgKi8gfVxuICAgIGlmIChoYXMkMShPLCBQKSkgcmV0dXJuIGNyZWF0ZVByb3BlcnR5RGVzY3JpcHRvcighb2JqZWN0UHJvcGVydHlJc0VudW1lcmFibGUuZi5jYWxsKE8sIFApLCBPW1BdKTtcbiAgfTtcblxuICB2YXIgb2JqZWN0R2V0T3duUHJvcGVydHlEZXNjcmlwdG9yID0ge1xuICBcdGY6IGYkM1xuICB9O1xuXG4gIHZhciBhbk9iamVjdCA9IGZ1bmN0aW9uIChpdCkge1xuICAgIGlmICghaXNPYmplY3QoaXQpKSB7XG4gICAgICB0aHJvdyBUeXBlRXJyb3IoU3RyaW5nKGl0KSArICcgaXMgbm90IGFuIG9iamVjdCcpO1xuICAgIH0gcmV0dXJuIGl0O1xuICB9O1xuXG4gIHZhciBuYXRpdmVEZWZpbmVQcm9wZXJ0eSA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eTtcblxuICAvLyBgT2JqZWN0LmRlZmluZVByb3BlcnR5YCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1vYmplY3QuZGVmaW5lcHJvcGVydHlcbiAgdmFyIGYkMiA9IGRlc2NyaXB0b3JzID8gbmF0aXZlRGVmaW5lUHJvcGVydHkgOiBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0eShPLCBQLCBBdHRyaWJ1dGVzKSB7XG4gICAgYW5PYmplY3QoTyk7XG4gICAgUCA9IHRvUHJpbWl0aXZlKFAsIHRydWUpO1xuICAgIGFuT2JqZWN0KEF0dHJpYnV0ZXMpO1xuICAgIGlmIChpZThEb21EZWZpbmUpIHRyeSB7XG4gICAgICByZXR1cm4gbmF0aXZlRGVmaW5lUHJvcGVydHkoTywgUCwgQXR0cmlidXRlcyk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHsgLyogZW1wdHkgKi8gfVxuICAgIGlmICgnZ2V0JyBpbiBBdHRyaWJ1dGVzIHx8ICdzZXQnIGluIEF0dHJpYnV0ZXMpIHRocm93IFR5cGVFcnJvcignQWNjZXNzb3JzIG5vdCBzdXBwb3J0ZWQnKTtcbiAgICBpZiAoJ3ZhbHVlJyBpbiBBdHRyaWJ1dGVzKSBPW1BdID0gQXR0cmlidXRlcy52YWx1ZTtcbiAgICByZXR1cm4gTztcbiAgfTtcblxuICB2YXIgb2JqZWN0RGVmaW5lUHJvcGVydHkgPSB7XG4gIFx0ZjogZiQyXG4gIH07XG5cbiAgdmFyIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eSA9IGRlc2NyaXB0b3JzID8gZnVuY3Rpb24gKG9iamVjdCwga2V5LCB2YWx1ZSkge1xuICAgIHJldHVybiBvYmplY3REZWZpbmVQcm9wZXJ0eS5mKG9iamVjdCwga2V5LCBjcmVhdGVQcm9wZXJ0eURlc2NyaXB0b3IoMSwgdmFsdWUpKTtcbiAgfSA6IGZ1bmN0aW9uIChvYmplY3QsIGtleSwgdmFsdWUpIHtcbiAgICBvYmplY3Rba2V5XSA9IHZhbHVlO1xuICAgIHJldHVybiBvYmplY3Q7XG4gIH07XG5cbiAgdmFyIHNldEdsb2JhbCA9IGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eShnbG9iYWxfMSwga2V5LCB2YWx1ZSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGdsb2JhbF8xW2tleV0gPSB2YWx1ZTtcbiAgICB9IHJldHVybiB2YWx1ZTtcbiAgfTtcblxuICB2YXIgU0hBUkVEID0gJ19fY29yZS1qc19zaGFyZWRfXyc7XG4gIHZhciBzdG9yZSQxID0gZ2xvYmFsXzFbU0hBUkVEXSB8fCBzZXRHbG9iYWwoU0hBUkVELCB7fSk7XG5cbiAgdmFyIHNoYXJlZFN0b3JlID0gc3RvcmUkMTtcblxuICB2YXIgZnVuY3Rpb25Ub1N0cmluZyA9IEZ1bmN0aW9uLnRvU3RyaW5nO1xuXG4gIC8vIHRoaXMgaGVscGVyIGJyb2tlbiBpbiBgMy40LjEtMy40LjRgLCBzbyB3ZSBjYW4ndCB1c2UgYHNoYXJlZGAgaGVscGVyXG4gIGlmICh0eXBlb2Ygc2hhcmVkU3RvcmUuaW5zcGVjdFNvdXJjZSAhPSAnZnVuY3Rpb24nKSB7XG4gICAgc2hhcmVkU3RvcmUuaW5zcGVjdFNvdXJjZSA9IGZ1bmN0aW9uIChpdCkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uVG9TdHJpbmcuY2FsbChpdCk7XG4gICAgfTtcbiAgfVxuXG4gIHZhciBpbnNwZWN0U291cmNlID0gc2hhcmVkU3RvcmUuaW5zcGVjdFNvdXJjZTtcblxuICB2YXIgV2Vha01hcCQxID0gZ2xvYmFsXzEuV2Vha01hcDtcblxuICB2YXIgbmF0aXZlV2Vha01hcCA9IHR5cGVvZiBXZWFrTWFwJDEgPT09ICdmdW5jdGlvbicgJiYgL25hdGl2ZSBjb2RlLy50ZXN0KGluc3BlY3RTb3VyY2UoV2Vha01hcCQxKSk7XG5cbiAgdmFyIHNoYXJlZCA9IGNyZWF0ZUNvbW1vbmpzTW9kdWxlKGZ1bmN0aW9uIChtb2R1bGUpIHtcbiAgKG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICByZXR1cm4gc2hhcmVkU3RvcmVba2V5XSB8fCAoc2hhcmVkU3RvcmVba2V5XSA9IHZhbHVlICE9PSB1bmRlZmluZWQgPyB2YWx1ZSA6IHt9KTtcbiAgfSkoJ3ZlcnNpb25zJywgW10pLnB1c2goe1xuICAgIHZlcnNpb246ICczLjkuMScsXG4gICAgbW9kZTogJ2dsb2JhbCcsXG4gICAgY29weXJpZ2h0OiAnwqkgMjAyMSBEZW5pcyBQdXNoa2FyZXYgKHpsb2lyb2NrLnJ1KSdcbiAgfSk7XG4gIH0pO1xuXG4gIHZhciBpZCA9IDA7XG4gIHZhciBwb3N0Zml4ID0gTWF0aC5yYW5kb20oKTtcblxuICB2YXIgdWlkID0gZnVuY3Rpb24gKGtleSkge1xuICAgIHJldHVybiAnU3ltYm9sKCcgKyBTdHJpbmcoa2V5ID09PSB1bmRlZmluZWQgPyAnJyA6IGtleSkgKyAnKV8nICsgKCsraWQgKyBwb3N0Zml4KS50b1N0cmluZygzNik7XG4gIH07XG5cbiAgdmFyIGtleXMkMiA9IHNoYXJlZCgna2V5cycpO1xuXG4gIHZhciBzaGFyZWRLZXkgPSBmdW5jdGlvbiAoa2V5KSB7XG4gICAgcmV0dXJuIGtleXMkMltrZXldIHx8IChrZXlzJDJba2V5XSA9IHVpZChrZXkpKTtcbiAgfTtcblxuICB2YXIgaGlkZGVuS2V5cyQxID0ge307XG5cbiAgdmFyIFdlYWtNYXAgPSBnbG9iYWxfMS5XZWFrTWFwO1xuICB2YXIgc2V0LCBnZXQsIGhhcztcblxuICB2YXIgZW5mb3JjZSA9IGZ1bmN0aW9uIChpdCkge1xuICAgIHJldHVybiBoYXMoaXQpID8gZ2V0KGl0KSA6IHNldChpdCwge30pO1xuICB9O1xuXG4gIHZhciBnZXR0ZXJGb3IgPSBmdW5jdGlvbiAoVFlQRSkge1xuICAgIHJldHVybiBmdW5jdGlvbiAoaXQpIHtcbiAgICAgIHZhciBzdGF0ZTtcbiAgICAgIGlmICghaXNPYmplY3QoaXQpIHx8IChzdGF0ZSA9IGdldChpdCkpLnR5cGUgIT09IFRZUEUpIHtcbiAgICAgICAgdGhyb3cgVHlwZUVycm9yKCdJbmNvbXBhdGlibGUgcmVjZWl2ZXIsICcgKyBUWVBFICsgJyByZXF1aXJlZCcpO1xuICAgICAgfSByZXR1cm4gc3RhdGU7XG4gICAgfTtcbiAgfTtcblxuICBpZiAobmF0aXZlV2Vha01hcCkge1xuICAgIHZhciBzdG9yZSA9IHNoYXJlZFN0b3JlLnN0YXRlIHx8IChzaGFyZWRTdG9yZS5zdGF0ZSA9IG5ldyBXZWFrTWFwKCkpO1xuICAgIHZhciB3bWdldCA9IHN0b3JlLmdldDtcbiAgICB2YXIgd21oYXMgPSBzdG9yZS5oYXM7XG4gICAgdmFyIHdtc2V0ID0gc3RvcmUuc2V0O1xuICAgIHNldCA9IGZ1bmN0aW9uIChpdCwgbWV0YWRhdGEpIHtcbiAgICAgIG1ldGFkYXRhLmZhY2FkZSA9IGl0O1xuICAgICAgd21zZXQuY2FsbChzdG9yZSwgaXQsIG1ldGFkYXRhKTtcbiAgICAgIHJldHVybiBtZXRhZGF0YTtcbiAgICB9O1xuICAgIGdldCA9IGZ1bmN0aW9uIChpdCkge1xuICAgICAgcmV0dXJuIHdtZ2V0LmNhbGwoc3RvcmUsIGl0KSB8fCB7fTtcbiAgICB9O1xuICAgIGhhcyA9IGZ1bmN0aW9uIChpdCkge1xuICAgICAgcmV0dXJuIHdtaGFzLmNhbGwoc3RvcmUsIGl0KTtcbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIHZhciBTVEFURSA9IHNoYXJlZEtleSgnc3RhdGUnKTtcbiAgICBoaWRkZW5LZXlzJDFbU1RBVEVdID0gdHJ1ZTtcbiAgICBzZXQgPSBmdW5jdGlvbiAoaXQsIG1ldGFkYXRhKSB7XG4gICAgICBtZXRhZGF0YS5mYWNhZGUgPSBpdDtcbiAgICAgIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eShpdCwgU1RBVEUsIG1ldGFkYXRhKTtcbiAgICAgIHJldHVybiBtZXRhZGF0YTtcbiAgICB9O1xuICAgIGdldCA9IGZ1bmN0aW9uIChpdCkge1xuICAgICAgcmV0dXJuIGhhcyQxKGl0LCBTVEFURSkgPyBpdFtTVEFURV0gOiB7fTtcbiAgICB9O1xuICAgIGhhcyA9IGZ1bmN0aW9uIChpdCkge1xuICAgICAgcmV0dXJuIGhhcyQxKGl0LCBTVEFURSk7XG4gICAgfTtcbiAgfVxuXG4gIHZhciBpbnRlcm5hbFN0YXRlID0ge1xuICAgIHNldDogc2V0LFxuICAgIGdldDogZ2V0LFxuICAgIGhhczogaGFzLFxuICAgIGVuZm9yY2U6IGVuZm9yY2UsXG4gICAgZ2V0dGVyRm9yOiBnZXR0ZXJGb3JcbiAgfTtcblxuICB2YXIgcmVkZWZpbmUgPSBjcmVhdGVDb21tb25qc01vZHVsZShmdW5jdGlvbiAobW9kdWxlKSB7XG4gIHZhciBnZXRJbnRlcm5hbFN0YXRlID0gaW50ZXJuYWxTdGF0ZS5nZXQ7XG4gIHZhciBlbmZvcmNlSW50ZXJuYWxTdGF0ZSA9IGludGVybmFsU3RhdGUuZW5mb3JjZTtcbiAgdmFyIFRFTVBMQVRFID0gU3RyaW5nKFN0cmluZykuc3BsaXQoJ1N0cmluZycpO1xuXG4gIChtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChPLCBrZXksIHZhbHVlLCBvcHRpb25zKSB7XG4gICAgdmFyIHVuc2FmZSA9IG9wdGlvbnMgPyAhIW9wdGlvbnMudW5zYWZlIDogZmFsc2U7XG4gICAgdmFyIHNpbXBsZSA9IG9wdGlvbnMgPyAhIW9wdGlvbnMuZW51bWVyYWJsZSA6IGZhbHNlO1xuICAgIHZhciBub1RhcmdldEdldCA9IG9wdGlvbnMgPyAhIW9wdGlvbnMubm9UYXJnZXRHZXQgOiBmYWxzZTtcbiAgICB2YXIgc3RhdGU7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICBpZiAodHlwZW9mIGtleSA9PSAnc3RyaW5nJyAmJiAhaGFzJDEodmFsdWUsICduYW1lJykpIHtcbiAgICAgICAgY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5KHZhbHVlLCAnbmFtZScsIGtleSk7XG4gICAgICB9XG4gICAgICBzdGF0ZSA9IGVuZm9yY2VJbnRlcm5hbFN0YXRlKHZhbHVlKTtcbiAgICAgIGlmICghc3RhdGUuc291cmNlKSB7XG4gICAgICAgIHN0YXRlLnNvdXJjZSA9IFRFTVBMQVRFLmpvaW4odHlwZW9mIGtleSA9PSAnc3RyaW5nJyA/IGtleSA6ICcnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKE8gPT09IGdsb2JhbF8xKSB7XG4gICAgICBpZiAoc2ltcGxlKSBPW2tleV0gPSB2YWx1ZTtcbiAgICAgIGVsc2Ugc2V0R2xvYmFsKGtleSwgdmFsdWUpO1xuICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSBpZiAoIXVuc2FmZSkge1xuICAgICAgZGVsZXRlIE9ba2V5XTtcbiAgICB9IGVsc2UgaWYgKCFub1RhcmdldEdldCAmJiBPW2tleV0pIHtcbiAgICAgIHNpbXBsZSA9IHRydWU7XG4gICAgfVxuICAgIGlmIChzaW1wbGUpIE9ba2V5XSA9IHZhbHVlO1xuICAgIGVsc2UgY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5KE8sIGtleSwgdmFsdWUpO1xuICAvLyBhZGQgZmFrZSBGdW5jdGlvbiN0b1N0cmluZyBmb3IgY29ycmVjdCB3b3JrIHdyYXBwZWQgbWV0aG9kcyAvIGNvbnN0cnVjdG9ycyB3aXRoIG1ldGhvZHMgbGlrZSBMb0Rhc2ggaXNOYXRpdmVcbiAgfSkoRnVuY3Rpb24ucHJvdG90eXBlLCAndG9TdHJpbmcnLCBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gdHlwZW9mIHRoaXMgPT0gJ2Z1bmN0aW9uJyAmJiBnZXRJbnRlcm5hbFN0YXRlKHRoaXMpLnNvdXJjZSB8fCBpbnNwZWN0U291cmNlKHRoaXMpO1xuICB9KTtcbiAgfSk7XG5cbiAgdmFyIHBhdGggPSBnbG9iYWxfMTtcblxuICB2YXIgYUZ1bmN0aW9uJDEgPSBmdW5jdGlvbiAodmFyaWFibGUpIHtcbiAgICByZXR1cm4gdHlwZW9mIHZhcmlhYmxlID09ICdmdW5jdGlvbicgPyB2YXJpYWJsZSA6IHVuZGVmaW5lZDtcbiAgfTtcblxuICB2YXIgZ2V0QnVpbHRJbiA9IGZ1bmN0aW9uIChuYW1lc3BhY2UsIG1ldGhvZCkge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoIDwgMiA/IGFGdW5jdGlvbiQxKHBhdGhbbmFtZXNwYWNlXSkgfHwgYUZ1bmN0aW9uJDEoZ2xvYmFsXzFbbmFtZXNwYWNlXSlcbiAgICAgIDogcGF0aFtuYW1lc3BhY2VdICYmIHBhdGhbbmFtZXNwYWNlXVttZXRob2RdIHx8IGdsb2JhbF8xW25hbWVzcGFjZV0gJiYgZ2xvYmFsXzFbbmFtZXNwYWNlXVttZXRob2RdO1xuICB9O1xuXG4gIHZhciBjZWlsID0gTWF0aC5jZWlsO1xuICB2YXIgZmxvb3IkMSA9IE1hdGguZmxvb3I7XG5cbiAgLy8gYFRvSW50ZWdlcmAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtdG9pbnRlZ2VyXG4gIHZhciB0b0ludGVnZXIgPSBmdW5jdGlvbiAoYXJndW1lbnQpIHtcbiAgICByZXR1cm4gaXNOYU4oYXJndW1lbnQgPSArYXJndW1lbnQpID8gMCA6IChhcmd1bWVudCA+IDAgPyBmbG9vciQxIDogY2VpbCkoYXJndW1lbnQpO1xuICB9O1xuXG4gIHZhciBtaW4kNiA9IE1hdGgubWluO1xuXG4gIC8vIGBUb0xlbmd0aGAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtdG9sZW5ndGhcbiAgdmFyIHRvTGVuZ3RoID0gZnVuY3Rpb24gKGFyZ3VtZW50KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50ID4gMCA/IG1pbiQ2KHRvSW50ZWdlcihhcmd1bWVudCksIDB4MUZGRkZGRkZGRkZGRkYpIDogMDsgLy8gMiAqKiA1MyAtIDEgPT0gOTAwNzE5OTI1NDc0MDk5MVxuICB9O1xuXG4gIHZhciBtYXgkMyA9IE1hdGgubWF4O1xuICB2YXIgbWluJDUgPSBNYXRoLm1pbjtcblxuICAvLyBIZWxwZXIgZm9yIGEgcG9wdWxhciByZXBlYXRpbmcgY2FzZSBvZiB0aGUgc3BlYzpcbiAgLy8gTGV0IGludGVnZXIgYmUgPyBUb0ludGVnZXIoaW5kZXgpLlxuICAvLyBJZiBpbnRlZ2VyIDwgMCwgbGV0IHJlc3VsdCBiZSBtYXgoKGxlbmd0aCArIGludGVnZXIpLCAwKTsgZWxzZSBsZXQgcmVzdWx0IGJlIG1pbihpbnRlZ2VyLCBsZW5ndGgpLlxuICB2YXIgdG9BYnNvbHV0ZUluZGV4ID0gZnVuY3Rpb24gKGluZGV4LCBsZW5ndGgpIHtcbiAgICB2YXIgaW50ZWdlciA9IHRvSW50ZWdlcihpbmRleCk7XG4gICAgcmV0dXJuIGludGVnZXIgPCAwID8gbWF4JDMoaW50ZWdlciArIGxlbmd0aCwgMCkgOiBtaW4kNShpbnRlZ2VyLCBsZW5ndGgpO1xuICB9O1xuXG4gIC8vIGBBcnJheS5wcm90b3R5cGUueyBpbmRleE9mLCBpbmNsdWRlcyB9YCBtZXRob2RzIGltcGxlbWVudGF0aW9uXG4gIHZhciBjcmVhdGVNZXRob2QkNCA9IGZ1bmN0aW9uIChJU19JTkNMVURFUykge1xuICAgIHJldHVybiBmdW5jdGlvbiAoJHRoaXMsIGVsLCBmcm9tSW5kZXgpIHtcbiAgICAgIHZhciBPID0gdG9JbmRleGVkT2JqZWN0KCR0aGlzKTtcbiAgICAgIHZhciBsZW5ndGggPSB0b0xlbmd0aChPLmxlbmd0aCk7XG4gICAgICB2YXIgaW5kZXggPSB0b0Fic29sdXRlSW5kZXgoZnJvbUluZGV4LCBsZW5ndGgpO1xuICAgICAgdmFyIHZhbHVlO1xuICAgICAgLy8gQXJyYXkjaW5jbHVkZXMgdXNlcyBTYW1lVmFsdWVaZXJvIGVxdWFsaXR5IGFsZ29yaXRobVxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXNlbGYtY29tcGFyZSAtLSBOYU4gY2hlY2tcbiAgICAgIGlmIChJU19JTkNMVURFUyAmJiBlbCAhPSBlbCkgd2hpbGUgKGxlbmd0aCA+IGluZGV4KSB7XG4gICAgICAgIHZhbHVlID0gT1tpbmRleCsrXTtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXNlbGYtY29tcGFyZSAtLSBOYU4gY2hlY2tcbiAgICAgICAgaWYgKHZhbHVlICE9IHZhbHVlKSByZXR1cm4gdHJ1ZTtcbiAgICAgIC8vIEFycmF5I2luZGV4T2YgaWdub3JlcyBob2xlcywgQXJyYXkjaW5jbHVkZXMgLSBub3RcbiAgICAgIH0gZWxzZSBmb3IgKDtsZW5ndGggPiBpbmRleDsgaW5kZXgrKykge1xuICAgICAgICBpZiAoKElTX0lOQ0xVREVTIHx8IGluZGV4IGluIE8pICYmIE9baW5kZXhdID09PSBlbCkgcmV0dXJuIElTX0lOQ0xVREVTIHx8IGluZGV4IHx8IDA7XG4gICAgICB9IHJldHVybiAhSVNfSU5DTFVERVMgJiYgLTE7XG4gICAgfTtcbiAgfTtcblxuICB2YXIgYXJyYXlJbmNsdWRlcyA9IHtcbiAgICAvLyBgQXJyYXkucHJvdG90eXBlLmluY2x1ZGVzYCBtZXRob2RcbiAgICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS5pbmNsdWRlc1xuICAgIGluY2x1ZGVzOiBjcmVhdGVNZXRob2QkNCh0cnVlKSxcbiAgICAvLyBgQXJyYXkucHJvdG90eXBlLmluZGV4T2ZgIG1ldGhvZFxuICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLmluZGV4b2ZcbiAgICBpbmRleE9mOiBjcmVhdGVNZXRob2QkNChmYWxzZSlcbiAgfTtcblxuICB2YXIgaW5kZXhPZiA9IGFycmF5SW5jbHVkZXMuaW5kZXhPZjtcblxuXG4gIHZhciBvYmplY3RLZXlzSW50ZXJuYWwgPSBmdW5jdGlvbiAob2JqZWN0LCBuYW1lcykge1xuICAgIHZhciBPID0gdG9JbmRleGVkT2JqZWN0KG9iamVjdCk7XG4gICAgdmFyIGkgPSAwO1xuICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICB2YXIga2V5O1xuICAgIGZvciAoa2V5IGluIE8pICFoYXMkMShoaWRkZW5LZXlzJDEsIGtleSkgJiYgaGFzJDEoTywga2V5KSAmJiByZXN1bHQucHVzaChrZXkpO1xuICAgIC8vIERvbid0IGVudW0gYnVnICYgaGlkZGVuIGtleXNcbiAgICB3aGlsZSAobmFtZXMubGVuZ3RoID4gaSkgaWYgKGhhcyQxKE8sIGtleSA9IG5hbWVzW2krK10pKSB7XG4gICAgICB+aW5kZXhPZihyZXN1bHQsIGtleSkgfHwgcmVzdWx0LnB1c2goa2V5KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICAvLyBJRTgtIGRvbid0IGVudW0gYnVnIGtleXNcbiAgdmFyIGVudW1CdWdLZXlzID0gW1xuICAgICdjb25zdHJ1Y3RvcicsXG4gICAgJ2hhc093blByb3BlcnR5JyxcbiAgICAnaXNQcm90b3R5cGVPZicsXG4gICAgJ3Byb3BlcnR5SXNFbnVtZXJhYmxlJyxcbiAgICAndG9Mb2NhbGVTdHJpbmcnLFxuICAgICd0b1N0cmluZycsXG4gICAgJ3ZhbHVlT2YnXG4gIF07XG5cbiAgdmFyIGhpZGRlbktleXMgPSBlbnVtQnVnS2V5cy5jb25jYXQoJ2xlbmd0aCcsICdwcm90b3R5cGUnKTtcblxuICAvLyBgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXNgIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9iamVjdC5nZXRvd25wcm9wZXJ0eW5hbWVzXG4gIHZhciBmJDEgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyB8fCBmdW5jdGlvbiBnZXRPd25Qcm9wZXJ0eU5hbWVzKE8pIHtcbiAgICByZXR1cm4gb2JqZWN0S2V5c0ludGVybmFsKE8sIGhpZGRlbktleXMpO1xuICB9O1xuXG4gIHZhciBvYmplY3RHZXRPd25Qcm9wZXJ0eU5hbWVzID0ge1xuICBcdGY6IGYkMVxuICB9O1xuXG4gIHZhciBmID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scztcblxuICB2YXIgb2JqZWN0R2V0T3duUHJvcGVydHlTeW1ib2xzID0ge1xuICBcdGY6IGZcbiAgfTtcblxuICAvLyBhbGwgb2JqZWN0IGtleXMsIGluY2x1ZGVzIG5vbi1lbnVtZXJhYmxlIGFuZCBzeW1ib2xzXG4gIHZhciBvd25LZXlzID0gZ2V0QnVpbHRJbignUmVmbGVjdCcsICdvd25LZXlzJykgfHwgZnVuY3Rpb24gb3duS2V5cyhpdCkge1xuICAgIHZhciBrZXlzID0gb2JqZWN0R2V0T3duUHJvcGVydHlOYW1lcy5mKGFuT2JqZWN0KGl0KSk7XG4gICAgdmFyIGdldE93blByb3BlcnR5U3ltYm9scyA9IG9iamVjdEdldE93blByb3BlcnR5U3ltYm9scy5mO1xuICAgIHJldHVybiBnZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPyBrZXlzLmNvbmNhdChnZXRPd25Qcm9wZXJ0eVN5bWJvbHMoaXQpKSA6IGtleXM7XG4gIH07XG5cbiAgdmFyIGNvcHlDb25zdHJ1Y3RvclByb3BlcnRpZXMgPSBmdW5jdGlvbiAodGFyZ2V0LCBzb3VyY2UpIHtcbiAgICB2YXIga2V5cyA9IG93bktleXMoc291cmNlKTtcbiAgICB2YXIgZGVmaW5lUHJvcGVydHkgPSBvYmplY3REZWZpbmVQcm9wZXJ0eS5mO1xuICAgIHZhciBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgPSBvYmplY3RHZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IuZjtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBrZXkgPSBrZXlzW2ldO1xuICAgICAgaWYgKCFoYXMkMSh0YXJnZXQsIGtleSkpIGRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Ioc291cmNlLCBrZXkpKTtcbiAgICB9XG4gIH07XG5cbiAgdmFyIHJlcGxhY2VtZW50ID0gLyN8XFwucHJvdG90eXBlXFwuLztcblxuICB2YXIgaXNGb3JjZWQgPSBmdW5jdGlvbiAoZmVhdHVyZSwgZGV0ZWN0aW9uKSB7XG4gICAgdmFyIHZhbHVlID0gZGF0YVtub3JtYWxpemUoZmVhdHVyZSldO1xuICAgIHJldHVybiB2YWx1ZSA9PSBQT0xZRklMTCA/IHRydWVcbiAgICAgIDogdmFsdWUgPT0gTkFUSVZFID8gZmFsc2VcbiAgICAgIDogdHlwZW9mIGRldGVjdGlvbiA9PSAnZnVuY3Rpb24nID8gZmFpbHMoZGV0ZWN0aW9uKVxuICAgICAgOiAhIWRldGVjdGlvbjtcbiAgfTtcblxuICB2YXIgbm9ybWFsaXplID0gaXNGb3JjZWQubm9ybWFsaXplID0gZnVuY3Rpb24gKHN0cmluZykge1xuICAgIHJldHVybiBTdHJpbmcoc3RyaW5nKS5yZXBsYWNlKHJlcGxhY2VtZW50LCAnLicpLnRvTG93ZXJDYXNlKCk7XG4gIH07XG5cbiAgdmFyIGRhdGEgPSBpc0ZvcmNlZC5kYXRhID0ge307XG4gIHZhciBOQVRJVkUgPSBpc0ZvcmNlZC5OQVRJVkUgPSAnTic7XG4gIHZhciBQT0xZRklMTCA9IGlzRm9yY2VkLlBPTFlGSUxMID0gJ1AnO1xuXG4gIHZhciBpc0ZvcmNlZF8xID0gaXNGb3JjZWQ7XG5cbiAgdmFyIGdldE93blByb3BlcnR5RGVzY3JpcHRvciQzID0gb2JqZWN0R2V0T3duUHJvcGVydHlEZXNjcmlwdG9yLmY7XG5cblxuXG5cblxuXG4gIC8qXG4gICAgb3B0aW9ucy50YXJnZXQgICAgICAtIG5hbWUgb2YgdGhlIHRhcmdldCBvYmplY3RcbiAgICBvcHRpb25zLmdsb2JhbCAgICAgIC0gdGFyZ2V0IGlzIHRoZSBnbG9iYWwgb2JqZWN0XG4gICAgb3B0aW9ucy5zdGF0ICAgICAgICAtIGV4cG9ydCBhcyBzdGF0aWMgbWV0aG9kcyBvZiB0YXJnZXRcbiAgICBvcHRpb25zLnByb3RvICAgICAgIC0gZXhwb3J0IGFzIHByb3RvdHlwZSBtZXRob2RzIG9mIHRhcmdldFxuICAgIG9wdGlvbnMucmVhbCAgICAgICAgLSByZWFsIHByb3RvdHlwZSBtZXRob2QgZm9yIHRoZSBgcHVyZWAgdmVyc2lvblxuICAgIG9wdGlvbnMuZm9yY2VkICAgICAgLSBleHBvcnQgZXZlbiBpZiB0aGUgbmF0aXZlIGZlYXR1cmUgaXMgYXZhaWxhYmxlXG4gICAgb3B0aW9ucy5iaW5kICAgICAgICAtIGJpbmQgbWV0aG9kcyB0byB0aGUgdGFyZ2V0LCByZXF1aXJlZCBmb3IgdGhlIGBwdXJlYCB2ZXJzaW9uXG4gICAgb3B0aW9ucy53cmFwICAgICAgICAtIHdyYXAgY29uc3RydWN0b3JzIHRvIHByZXZlbnRpbmcgZ2xvYmFsIHBvbGx1dGlvbiwgcmVxdWlyZWQgZm9yIHRoZSBgcHVyZWAgdmVyc2lvblxuICAgIG9wdGlvbnMudW5zYWZlICAgICAgLSB1c2UgdGhlIHNpbXBsZSBhc3NpZ25tZW50IG9mIHByb3BlcnR5IGluc3RlYWQgb2YgZGVsZXRlICsgZGVmaW5lUHJvcGVydHlcbiAgICBvcHRpb25zLnNoYW0gICAgICAgIC0gYWRkIGEgZmxhZyB0byBub3QgY29tcGxldGVseSBmdWxsIHBvbHlmaWxsc1xuICAgIG9wdGlvbnMuZW51bWVyYWJsZSAgLSBleHBvcnQgYXMgZW51bWVyYWJsZSBwcm9wZXJ0eVxuICAgIG9wdGlvbnMubm9UYXJnZXRHZXQgLSBwcmV2ZW50IGNhbGxpbmcgYSBnZXR0ZXIgb24gdGFyZ2V0XG4gICovXG4gIHZhciBfZXhwb3J0ID0gZnVuY3Rpb24gKG9wdGlvbnMsIHNvdXJjZSkge1xuICAgIHZhciBUQVJHRVQgPSBvcHRpb25zLnRhcmdldDtcbiAgICB2YXIgR0xPQkFMID0gb3B0aW9ucy5nbG9iYWw7XG4gICAgdmFyIFNUQVRJQyA9IG9wdGlvbnMuc3RhdDtcbiAgICB2YXIgRk9SQ0VELCB0YXJnZXQsIGtleSwgdGFyZ2V0UHJvcGVydHksIHNvdXJjZVByb3BlcnR5LCBkZXNjcmlwdG9yO1xuICAgIGlmIChHTE9CQUwpIHtcbiAgICAgIHRhcmdldCA9IGdsb2JhbF8xO1xuICAgIH0gZWxzZSBpZiAoU1RBVElDKSB7XG4gICAgICB0YXJnZXQgPSBnbG9iYWxfMVtUQVJHRVRdIHx8IHNldEdsb2JhbChUQVJHRVQsIHt9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGFyZ2V0ID0gKGdsb2JhbF8xW1RBUkdFVF0gfHwge30pLnByb3RvdHlwZTtcbiAgICB9XG4gICAgaWYgKHRhcmdldCkgZm9yIChrZXkgaW4gc291cmNlKSB7XG4gICAgICBzb3VyY2VQcm9wZXJ0eSA9IHNvdXJjZVtrZXldO1xuICAgICAgaWYgKG9wdGlvbnMubm9UYXJnZXRHZXQpIHtcbiAgICAgICAgZGVzY3JpcHRvciA9IGdldE93blByb3BlcnR5RGVzY3JpcHRvciQzKHRhcmdldCwga2V5KTtcbiAgICAgICAgdGFyZ2V0UHJvcGVydHkgPSBkZXNjcmlwdG9yICYmIGRlc2NyaXB0b3IudmFsdWU7XG4gICAgICB9IGVsc2UgdGFyZ2V0UHJvcGVydHkgPSB0YXJnZXRba2V5XTtcbiAgICAgIEZPUkNFRCA9IGlzRm9yY2VkXzEoR0xPQkFMID8ga2V5IDogVEFSR0VUICsgKFNUQVRJQyA/ICcuJyA6ICcjJykgKyBrZXksIG9wdGlvbnMuZm9yY2VkKTtcbiAgICAgIC8vIGNvbnRhaW5lZCBpbiB0YXJnZXRcbiAgICAgIGlmICghRk9SQ0VEICYmIHRhcmdldFByb3BlcnR5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBzb3VyY2VQcm9wZXJ0eSA9PT0gdHlwZW9mIHRhcmdldFByb3BlcnR5KSBjb250aW51ZTtcbiAgICAgICAgY29weUNvbnN0cnVjdG9yUHJvcGVydGllcyhzb3VyY2VQcm9wZXJ0eSwgdGFyZ2V0UHJvcGVydHkpO1xuICAgICAgfVxuICAgICAgLy8gYWRkIGEgZmxhZyB0byBub3QgY29tcGxldGVseSBmdWxsIHBvbHlmaWxsc1xuICAgICAgaWYgKG9wdGlvbnMuc2hhbSB8fCAodGFyZ2V0UHJvcGVydHkgJiYgdGFyZ2V0UHJvcGVydHkuc2hhbSkpIHtcbiAgICAgICAgY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5KHNvdXJjZVByb3BlcnR5LCAnc2hhbScsIHRydWUpO1xuICAgICAgfVxuICAgICAgLy8gZXh0ZW5kIGdsb2JhbFxuICAgICAgcmVkZWZpbmUodGFyZ2V0LCBrZXksIHNvdXJjZVByb3BlcnR5LCBvcHRpb25zKTtcbiAgICB9XG4gIH07XG5cbiAgLy8gYSBzdHJpbmcgb2YgYWxsIHZhbGlkIHVuaWNvZGUgd2hpdGVzcGFjZXNcbiAgdmFyIHdoaXRlc3BhY2VzID0gJ1xcdTAwMDlcXHUwMDBBXFx1MDAwQlxcdTAwMENcXHUwMDBEXFx1MDAyMFxcdTAwQTBcXHUxNjgwXFx1MjAwMFxcdTIwMDFcXHUyMDAyJyArXG4gICAgJ1xcdTIwMDNcXHUyMDA0XFx1MjAwNVxcdTIwMDZcXHUyMDA3XFx1MjAwOFxcdTIwMDlcXHUyMDBBXFx1MjAyRlxcdTIwNUZcXHUzMDAwXFx1MjAyOFxcdTIwMjlcXHVGRUZGJztcblxuICB2YXIgd2hpdGVzcGFjZSA9ICdbJyArIHdoaXRlc3BhY2VzICsgJ10nO1xuICB2YXIgbHRyaW0gPSBSZWdFeHAoJ14nICsgd2hpdGVzcGFjZSArIHdoaXRlc3BhY2UgKyAnKicpO1xuICB2YXIgcnRyaW0gPSBSZWdFeHAod2hpdGVzcGFjZSArIHdoaXRlc3BhY2UgKyAnKiQnKTtcblxuICAvLyBgU3RyaW5nLnByb3RvdHlwZS57IHRyaW0sIHRyaW1TdGFydCwgdHJpbUVuZCwgdHJpbUxlZnQsIHRyaW1SaWdodCB9YCBtZXRob2RzIGltcGxlbWVudGF0aW9uXG4gIHZhciBjcmVhdGVNZXRob2QkMyA9IGZ1bmN0aW9uIChUWVBFKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgkdGhpcykge1xuICAgICAgdmFyIHN0cmluZyA9IFN0cmluZyhyZXF1aXJlT2JqZWN0Q29lcmNpYmxlKCR0aGlzKSk7XG4gICAgICBpZiAoVFlQRSAmIDEpIHN0cmluZyA9IHN0cmluZy5yZXBsYWNlKGx0cmltLCAnJyk7XG4gICAgICBpZiAoVFlQRSAmIDIpIHN0cmluZyA9IHN0cmluZy5yZXBsYWNlKHJ0cmltLCAnJyk7XG4gICAgICByZXR1cm4gc3RyaW5nO1xuICAgIH07XG4gIH07XG5cbiAgdmFyIHN0cmluZ1RyaW0gPSB7XG4gICAgLy8gYFN0cmluZy5wcm90b3R5cGUueyB0cmltTGVmdCwgdHJpbVN0YXJ0IH1gIG1ldGhvZHNcbiAgICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXN0cmluZy5wcm90b3R5cGUudHJpbXN0YXJ0XG4gICAgc3RhcnQ6IGNyZWF0ZU1ldGhvZCQzKDEpLFxuICAgIC8vIGBTdHJpbmcucHJvdG90eXBlLnsgdHJpbVJpZ2h0LCB0cmltRW5kIH1gIG1ldGhvZHNcbiAgICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXN0cmluZy5wcm90b3R5cGUudHJpbWVuZFxuICAgIGVuZDogY3JlYXRlTWV0aG9kJDMoMiksXG4gICAgLy8gYFN0cmluZy5wcm90b3R5cGUudHJpbWAgbWV0aG9kXG4gICAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1zdHJpbmcucHJvdG90eXBlLnRyaW1cbiAgICB0cmltOiBjcmVhdGVNZXRob2QkMygzKVxuICB9O1xuXG4gIHZhciBub24gPSAnXFx1MjAwQlxcdTAwODVcXHUxODBFJztcblxuICAvLyBjaGVjayB0aGF0IGEgbWV0aG9kIHdvcmtzIHdpdGggdGhlIGNvcnJlY3QgbGlzdFxuICAvLyBvZiB3aGl0ZXNwYWNlcyBhbmQgaGFzIGEgY29ycmVjdCBuYW1lXG4gIHZhciBzdHJpbmdUcmltRm9yY2VkID0gZnVuY3Rpb24gKE1FVEhPRF9OQU1FKSB7XG4gICAgcmV0dXJuIGZhaWxzKGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAhIXdoaXRlc3BhY2VzW01FVEhPRF9OQU1FXSgpIHx8IG5vbltNRVRIT0RfTkFNRV0oKSAhPSBub24gfHwgd2hpdGVzcGFjZXNbTUVUSE9EX05BTUVdLm5hbWUgIT09IE1FVEhPRF9OQU1FO1xuICAgIH0pO1xuICB9O1xuXG4gIHZhciAkdHJpbSA9IHN0cmluZ1RyaW0udHJpbTtcblxuXG4gIC8vIGBTdHJpbmcucHJvdG90eXBlLnRyaW1gIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXN0cmluZy5wcm90b3R5cGUudHJpbVxuICBfZXhwb3J0KHsgdGFyZ2V0OiAnU3RyaW5nJywgcHJvdG86IHRydWUsIGZvcmNlZDogc3RyaW5nVHJpbUZvcmNlZCgndHJpbScpIH0sIHtcbiAgICB0cmltOiBmdW5jdGlvbiB0cmltKCkge1xuICAgICAgcmV0dXJuICR0cmltKHRoaXMpO1xuICAgIH1cbiAgfSk7XG5cbiAgdmFyIGFycmF5TWV0aG9kSXNTdHJpY3QgPSBmdW5jdGlvbiAoTUVUSE9EX05BTUUsIGFyZ3VtZW50KSB7XG4gICAgdmFyIG1ldGhvZCA9IFtdW01FVEhPRF9OQU1FXTtcbiAgICByZXR1cm4gISFtZXRob2QgJiYgZmFpbHMoZnVuY3Rpb24gKCkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVzZWxlc3MtY2FsbCxuby10aHJvdy1saXRlcmFsIC0tIHJlcXVpcmVkIGZvciB0ZXN0aW5nXG4gICAgICBtZXRob2QuY2FsbChudWxsLCBhcmd1bWVudCB8fCBmdW5jdGlvbiAoKSB7IHRocm93IDE7IH0sIDEpO1xuICAgIH0pO1xuICB9O1xuXG4gIHZhciBuYXRpdmVKb2luID0gW10uam9pbjtcblxuICB2YXIgRVMzX1NUUklOR1MgPSBpbmRleGVkT2JqZWN0ICE9IE9iamVjdDtcbiAgdmFyIFNUUklDVF9NRVRIT0QkMyA9IGFycmF5TWV0aG9kSXNTdHJpY3QoJ2pvaW4nLCAnLCcpO1xuXG4gIC8vIGBBcnJheS5wcm90b3R5cGUuam9pbmAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLmpvaW5cbiAgX2V4cG9ydCh7IHRhcmdldDogJ0FycmF5JywgcHJvdG86IHRydWUsIGZvcmNlZDogRVMzX1NUUklOR1MgfHwgIVNUUklDVF9NRVRIT0QkMyB9LCB7XG4gICAgam9pbjogZnVuY3Rpb24gam9pbihzZXBhcmF0b3IpIHtcbiAgICAgIHJldHVybiBuYXRpdmVKb2luLmNhbGwodG9JbmRleGVkT2JqZWN0KHRoaXMpLCBzZXBhcmF0b3IgPT09IHVuZGVmaW5lZCA/ICcsJyA6IHNlcGFyYXRvcik7XG4gICAgfVxuICB9KTtcblxuICAvLyBgUmVnRXhwLnByb3RvdHlwZS5mbGFnc2AgZ2V0dGVyIGltcGxlbWVudGF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtZ2V0LXJlZ2V4cC5wcm90b3R5cGUuZmxhZ3NcbiAgdmFyIHJlZ2V4cEZsYWdzID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciB0aGF0ID0gYW5PYmplY3QodGhpcyk7XG4gICAgdmFyIHJlc3VsdCA9ICcnO1xuICAgIGlmICh0aGF0Lmdsb2JhbCkgcmVzdWx0ICs9ICdnJztcbiAgICBpZiAodGhhdC5pZ25vcmVDYXNlKSByZXN1bHQgKz0gJ2knO1xuICAgIGlmICh0aGF0Lm11bHRpbGluZSkgcmVzdWx0ICs9ICdtJztcbiAgICBpZiAodGhhdC5kb3RBbGwpIHJlc3VsdCArPSAncyc7XG4gICAgaWYgKHRoYXQudW5pY29kZSkgcmVzdWx0ICs9ICd1JztcbiAgICBpZiAodGhhdC5zdGlja3kpIHJlc3VsdCArPSAneSc7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICAvLyBiYWJlbC1taW5pZnkgdHJhbnNwaWxlcyBSZWdFeHAoJ2EnLCAneScpIC0+IC9hL3kgYW5kIGl0IGNhdXNlcyBTeW50YXhFcnJvcixcbiAgLy8gc28gd2UgdXNlIGFuIGludGVybWVkaWF0ZSBmdW5jdGlvbi5cbiAgZnVuY3Rpb24gUkUocywgZikge1xuICAgIHJldHVybiBSZWdFeHAocywgZik7XG4gIH1cblxuICB2YXIgVU5TVVBQT1JURURfWSQyID0gZmFpbHMoZnVuY3Rpb24gKCkge1xuICAgIC8vIGJhYmVsLW1pbmlmeSB0cmFuc3BpbGVzIFJlZ0V4cCgnYScsICd5JykgLT4gL2EveSBhbmQgaXQgY2F1c2VzIFN5bnRheEVycm9yXG4gICAgdmFyIHJlID0gUkUoJ2EnLCAneScpO1xuICAgIHJlLmxhc3RJbmRleCA9IDI7XG4gICAgcmV0dXJuIHJlLmV4ZWMoJ2FiY2QnKSAhPSBudWxsO1xuICB9KTtcblxuICB2YXIgQlJPS0VOX0NBUkVUID0gZmFpbHMoZnVuY3Rpb24gKCkge1xuICAgIC8vIGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTc3MzY4N1xuICAgIHZhciByZSA9IFJFKCdecicsICdneScpO1xuICAgIHJlLmxhc3RJbmRleCA9IDI7XG4gICAgcmV0dXJuIHJlLmV4ZWMoJ3N0cicpICE9IG51bGw7XG4gIH0pO1xuXG4gIHZhciByZWdleHBTdGlja3lIZWxwZXJzID0ge1xuICBcdFVOU1VQUE9SVEVEX1k6IFVOU1VQUE9SVEVEX1kkMixcbiAgXHRCUk9LRU5fQ0FSRVQ6IEJST0tFTl9DQVJFVFxuICB9O1xuXG4gIHZhciBuYXRpdmVFeGVjID0gUmVnRXhwLnByb3RvdHlwZS5leGVjO1xuICAvLyBUaGlzIGFsd2F5cyByZWZlcnMgdG8gdGhlIG5hdGl2ZSBpbXBsZW1lbnRhdGlvbiwgYmVjYXVzZSB0aGVcbiAgLy8gU3RyaW5nI3JlcGxhY2UgcG9seWZpbGwgdXNlcyAuL2ZpeC1yZWdleHAtd2VsbC1rbm93bi1zeW1ib2wtbG9naWMuanMsXG4gIC8vIHdoaWNoIGxvYWRzIHRoaXMgZmlsZSBiZWZvcmUgcGF0Y2hpbmcgdGhlIG1ldGhvZC5cbiAgdmFyIG5hdGl2ZVJlcGxhY2UgPSBTdHJpbmcucHJvdG90eXBlLnJlcGxhY2U7XG5cbiAgdmFyIHBhdGNoZWRFeGVjID0gbmF0aXZlRXhlYztcblxuICB2YXIgVVBEQVRFU19MQVNUX0lOREVYX1dST05HID0gKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcmUxID0gL2EvO1xuICAgIHZhciByZTIgPSAvYiovZztcbiAgICBuYXRpdmVFeGVjLmNhbGwocmUxLCAnYScpO1xuICAgIG5hdGl2ZUV4ZWMuY2FsbChyZTIsICdhJyk7XG4gICAgcmV0dXJuIHJlMS5sYXN0SW5kZXggIT09IDAgfHwgcmUyLmxhc3RJbmRleCAhPT0gMDtcbiAgfSkoKTtcblxuICB2YXIgVU5TVVBQT1JURURfWSQxID0gcmVnZXhwU3RpY2t5SGVscGVycy5VTlNVUFBPUlRFRF9ZIHx8IHJlZ2V4cFN0aWNreUhlbHBlcnMuQlJPS0VOX0NBUkVUO1xuXG4gIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwLCBjb3BpZWQgZnJvbSBlczUtc2hpbSdzIFN0cmluZyNzcGxpdCBwYXRjaC5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHJlZ2V4cC9uby1hc3NlcnRpb24tY2FwdHVyaW5nLWdyb3VwLCByZWdleHAvbm8tZW1wdHktZ3JvdXAgLS0gcmVxdWlyZWQgZm9yIHRlc3RpbmdcbiAgdmFyIE5QQ0dfSU5DTFVERUQgPSAvKCk/Py8uZXhlYygnJylbMV0gIT09IHVuZGVmaW5lZDtcblxuICB2YXIgUEFUQ0ggPSBVUERBVEVTX0xBU1RfSU5ERVhfV1JPTkcgfHwgTlBDR19JTkNMVURFRCB8fCBVTlNVUFBPUlRFRF9ZJDE7XG5cbiAgaWYgKFBBVENIKSB7XG4gICAgcGF0Y2hlZEV4ZWMgPSBmdW5jdGlvbiBleGVjKHN0cikge1xuICAgICAgdmFyIHJlID0gdGhpcztcbiAgICAgIHZhciBsYXN0SW5kZXgsIHJlQ29weSwgbWF0Y2gsIGk7XG4gICAgICB2YXIgc3RpY2t5ID0gVU5TVVBQT1JURURfWSQxICYmIHJlLnN0aWNreTtcbiAgICAgIHZhciBmbGFncyA9IHJlZ2V4cEZsYWdzLmNhbGwocmUpO1xuICAgICAgdmFyIHNvdXJjZSA9IHJlLnNvdXJjZTtcbiAgICAgIHZhciBjaGFyc0FkZGVkID0gMDtcbiAgICAgIHZhciBzdHJDb3B5ID0gc3RyO1xuXG4gICAgICBpZiAoc3RpY2t5KSB7XG4gICAgICAgIGZsYWdzID0gZmxhZ3MucmVwbGFjZSgneScsICcnKTtcbiAgICAgICAgaWYgKGZsYWdzLmluZGV4T2YoJ2cnKSA9PT0gLTEpIHtcbiAgICAgICAgICBmbGFncyArPSAnZyc7XG4gICAgICAgIH1cblxuICAgICAgICBzdHJDb3B5ID0gU3RyaW5nKHN0cikuc2xpY2UocmUubGFzdEluZGV4KTtcbiAgICAgICAgLy8gU3VwcG9ydCBhbmNob3JlZCBzdGlja3kgYmVoYXZpb3IuXG4gICAgICAgIGlmIChyZS5sYXN0SW5kZXggPiAwICYmICghcmUubXVsdGlsaW5lIHx8IHJlLm11bHRpbGluZSAmJiBzdHJbcmUubGFzdEluZGV4IC0gMV0gIT09ICdcXG4nKSkge1xuICAgICAgICAgIHNvdXJjZSA9ICcoPzogJyArIHNvdXJjZSArICcpJztcbiAgICAgICAgICBzdHJDb3B5ID0gJyAnICsgc3RyQ29weTtcbiAgICAgICAgICBjaGFyc0FkZGVkKys7XG4gICAgICAgIH1cbiAgICAgICAgLy8gXig/ICsgcnggKyApIGlzIG5lZWRlZCwgaW4gY29tYmluYXRpb24gd2l0aCBzb21lIHN0ciBzbGljaW5nLCB0b1xuICAgICAgICAvLyBzaW11bGF0ZSB0aGUgJ3knIGZsYWcuXG4gICAgICAgIHJlQ29weSA9IG5ldyBSZWdFeHAoJ14oPzonICsgc291cmNlICsgJyknLCBmbGFncyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChOUENHX0lOQ0xVREVEKSB7XG4gICAgICAgIHJlQ29weSA9IG5ldyBSZWdFeHAoJ14nICsgc291cmNlICsgJyQoPyFcXFxccyknLCBmbGFncyk7XG4gICAgICB9XG4gICAgICBpZiAoVVBEQVRFU19MQVNUX0lOREVYX1dST05HKSBsYXN0SW5kZXggPSByZS5sYXN0SW5kZXg7XG5cbiAgICAgIG1hdGNoID0gbmF0aXZlRXhlYy5jYWxsKHN0aWNreSA/IHJlQ29weSA6IHJlLCBzdHJDb3B5KTtcblxuICAgICAgaWYgKHN0aWNreSkge1xuICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICBtYXRjaC5pbnB1dCA9IG1hdGNoLmlucHV0LnNsaWNlKGNoYXJzQWRkZWQpO1xuICAgICAgICAgIG1hdGNoWzBdID0gbWF0Y2hbMF0uc2xpY2UoY2hhcnNBZGRlZCk7XG4gICAgICAgICAgbWF0Y2guaW5kZXggPSByZS5sYXN0SW5kZXg7XG4gICAgICAgICAgcmUubGFzdEluZGV4ICs9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgfSBlbHNlIHJlLmxhc3RJbmRleCA9IDA7XG4gICAgICB9IGVsc2UgaWYgKFVQREFURVNfTEFTVF9JTkRFWF9XUk9ORyAmJiBtYXRjaCkge1xuICAgICAgICByZS5sYXN0SW5kZXggPSByZS5nbG9iYWwgPyBtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aCA6IGxhc3RJbmRleDtcbiAgICAgIH1cbiAgICAgIGlmIChOUENHX0lOQ0xVREVEICYmIG1hdGNoICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgLy8gRml4IGJyb3dzZXJzIHdob3NlIGBleGVjYCBtZXRob2RzIGRvbid0IGNvbnNpc3RlbnRseSByZXR1cm4gYHVuZGVmaW5lZGBcbiAgICAgICAgLy8gZm9yIE5QQ0csIGxpa2UgSUU4LiBOT1RFOiBUaGlzIGRvZXNuJyB3b3JrIGZvciAvKC4/KT8vXG4gICAgICAgIG5hdGl2ZVJlcGxhY2UuY2FsbChtYXRjaFswXSwgcmVDb3B5LCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgZm9yIChpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmaW5lZCkgbWF0Y2hbaV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG1hdGNoO1xuICAgIH07XG4gIH1cblxuICB2YXIgcmVnZXhwRXhlYyA9IHBhdGNoZWRFeGVjO1xuXG4gIC8vIGBSZWdFeHAucHJvdG90eXBlLmV4ZWNgIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXJlZ2V4cC5wcm90b3R5cGUuZXhlY1xuICBfZXhwb3J0KHsgdGFyZ2V0OiAnUmVnRXhwJywgcHJvdG86IHRydWUsIGZvcmNlZDogLy4vLmV4ZWMgIT09IHJlZ2V4cEV4ZWMgfSwge1xuICAgIGV4ZWM6IHJlZ2V4cEV4ZWNcbiAgfSk7XG5cbiAgdmFyIGVuZ2luZUlzTm9kZSA9IGNsYXNzb2ZSYXcoZ2xvYmFsXzEucHJvY2VzcykgPT0gJ3Byb2Nlc3MnO1xuXG4gIHZhciBlbmdpbmVVc2VyQWdlbnQgPSBnZXRCdWlsdEluKCduYXZpZ2F0b3InLCAndXNlckFnZW50JykgfHwgJyc7XG5cbiAgdmFyIHByb2Nlc3MgPSBnbG9iYWxfMS5wcm9jZXNzO1xuICB2YXIgdmVyc2lvbnMgPSBwcm9jZXNzICYmIHByb2Nlc3MudmVyc2lvbnM7XG4gIHZhciB2OCA9IHZlcnNpb25zICYmIHZlcnNpb25zLnY4O1xuICB2YXIgbWF0Y2gsIHZlcnNpb247XG5cbiAgaWYgKHY4KSB7XG4gICAgbWF0Y2ggPSB2OC5zcGxpdCgnLicpO1xuICAgIHZlcnNpb24gPSBtYXRjaFswXSArIG1hdGNoWzFdO1xuICB9IGVsc2UgaWYgKGVuZ2luZVVzZXJBZ2VudCkge1xuICAgIG1hdGNoID0gZW5naW5lVXNlckFnZW50Lm1hdGNoKC9FZGdlXFwvKFxcZCspLyk7XG4gICAgaWYgKCFtYXRjaCB8fCBtYXRjaFsxXSA+PSA3NCkge1xuICAgICAgbWF0Y2ggPSBlbmdpbmVVc2VyQWdlbnQubWF0Y2goL0Nocm9tZVxcLyhcXGQrKS8pO1xuICAgICAgaWYgKG1hdGNoKSB2ZXJzaW9uID0gbWF0Y2hbMV07XG4gICAgfVxuICB9XG5cbiAgdmFyIGVuZ2luZVY4VmVyc2lvbiA9IHZlcnNpb24gJiYgK3ZlcnNpb247XG5cbiAgdmFyIG5hdGl2ZVN5bWJvbCA9ICEhT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyAmJiAhZmFpbHMoZnVuY3Rpb24gKCkge1xuICAgIC8qIGdsb2JhbCBTeW1ib2wgLS0gcmVxdWlyZWQgZm9yIHRlc3RpbmcgKi9cbiAgICByZXR1cm4gIVN5bWJvbC5zaGFtICYmXG4gICAgICAvLyBDaHJvbWUgMzggU3ltYm9sIGhhcyBpbmNvcnJlY3QgdG9TdHJpbmcgY29udmVyc2lvblxuICAgICAgLy8gQ2hyb21lIDM4LTQwIHN5bWJvbHMgYXJlIG5vdCBpbmhlcml0ZWQgZnJvbSBET00gY29sbGVjdGlvbnMgcHJvdG90eXBlcyB0byBpbnN0YW5jZXNcbiAgICAgIChlbmdpbmVJc05vZGUgPyBlbmdpbmVWOFZlcnNpb24gPT09IDM4IDogZW5naW5lVjhWZXJzaW9uID4gMzcgJiYgZW5naW5lVjhWZXJzaW9uIDwgNDEpO1xuICB9KTtcblxuICB2YXIgdXNlU3ltYm9sQXNVaWQgPSBuYXRpdmVTeW1ib2xcbiAgICAvKiBnbG9iYWwgU3ltYm9sIC0tIHNhZmUgKi9cbiAgICAmJiAhU3ltYm9sLnNoYW1cbiAgICAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09ICdzeW1ib2wnO1xuXG4gIHZhciBXZWxsS25vd25TeW1ib2xzU3RvcmUgPSBzaGFyZWQoJ3drcycpO1xuICB2YXIgU3ltYm9sJDEgPSBnbG9iYWxfMS5TeW1ib2w7XG4gIHZhciBjcmVhdGVXZWxsS25vd25TeW1ib2wgPSB1c2VTeW1ib2xBc1VpZCA/IFN5bWJvbCQxIDogU3ltYm9sJDEgJiYgU3ltYm9sJDEud2l0aG91dFNldHRlciB8fCB1aWQ7XG5cbiAgdmFyIHdlbGxLbm93blN5bWJvbCA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgaWYgKCFoYXMkMShXZWxsS25vd25TeW1ib2xzU3RvcmUsIG5hbWUpIHx8ICEobmF0aXZlU3ltYm9sIHx8IHR5cGVvZiBXZWxsS25vd25TeW1ib2xzU3RvcmVbbmFtZV0gPT0gJ3N0cmluZycpKSB7XG4gICAgICBpZiAobmF0aXZlU3ltYm9sICYmIGhhcyQxKFN5bWJvbCQxLCBuYW1lKSkge1xuICAgICAgICBXZWxsS25vd25TeW1ib2xzU3RvcmVbbmFtZV0gPSBTeW1ib2wkMVtuYW1lXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIFdlbGxLbm93blN5bWJvbHNTdG9yZVtuYW1lXSA9IGNyZWF0ZVdlbGxLbm93blN5bWJvbCgnU3ltYm9sLicgKyBuYW1lKTtcbiAgICAgIH1cbiAgICB9IHJldHVybiBXZWxsS25vd25TeW1ib2xzU3RvcmVbbmFtZV07XG4gIH07XG5cbiAgLy8gVE9ETzogUmVtb3ZlIGZyb20gYGNvcmUtanNANGAgc2luY2UgaXQncyBtb3ZlZCB0byBlbnRyeSBwb2ludHNcblxuXG5cblxuXG5cblxuICB2YXIgU1BFQ0lFUyQ1ID0gd2VsbEtub3duU3ltYm9sKCdzcGVjaWVzJyk7XG5cbiAgdmFyIFJFUExBQ0VfU1VQUE9SVFNfTkFNRURfR1JPVVBTID0gIWZhaWxzKGZ1bmN0aW9uICgpIHtcbiAgICAvLyAjcmVwbGFjZSBuZWVkcyBidWlsdC1pbiBzdXBwb3J0IGZvciBuYW1lZCBncm91cHMuXG4gICAgLy8gI21hdGNoIHdvcmtzIGZpbmUgYmVjYXVzZSBpdCBqdXN0IHJldHVybiB0aGUgZXhlYyByZXN1bHRzLCBldmVuIGlmIGl0IGhhc1xuICAgIC8vIGEgXCJncm9wc1wiIHByb3BlcnR5LlxuICAgIHZhciByZSA9IC8uLztcbiAgICByZS5leGVjID0gZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgcmVzdWx0Lmdyb3VwcyA9IHsgYTogJzcnIH07XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gICAgcmV0dXJuICcnLnJlcGxhY2UocmUsICckPGE+JykgIT09ICc3JztcbiAgfSk7XG5cbiAgLy8gSUUgPD0gMTEgcmVwbGFjZXMgJDAgd2l0aCB0aGUgd2hvbGUgbWF0Y2gsIGFzIGlmIGl0IHdhcyAkJlxuICAvLyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82MDI0NjY2L2dldHRpbmctaWUtdG8tcmVwbGFjZS1hLXJlZ2V4LXdpdGgtdGhlLWxpdGVyYWwtc3RyaW5nLTBcbiAgdmFyIFJFUExBQ0VfS0VFUFNfJDAgPSAoZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAnYScucmVwbGFjZSgvLi8sICckMCcpID09PSAnJDAnO1xuICB9KSgpO1xuXG4gIHZhciBSRVBMQUNFID0gd2VsbEtub3duU3ltYm9sKCdyZXBsYWNlJyk7XG4gIC8vIFNhZmFyaSA8PSAxMy4wLjMoPykgc3Vic3RpdHV0ZXMgbnRoIGNhcHR1cmUgd2hlcmUgbj5tIHdpdGggYW4gZW1wdHkgc3RyaW5nXG4gIHZhciBSRUdFWFBfUkVQTEFDRV9TVUJTVElUVVRFU19VTkRFRklORURfQ0FQVFVSRSA9IChmdW5jdGlvbiAoKSB7XG4gICAgaWYgKC8uL1tSRVBMQUNFXSkge1xuICAgICAgcmV0dXJuIC8uL1tSRVBMQUNFXSgnYScsICckMCcpID09PSAnJztcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9KSgpO1xuXG4gIC8vIENocm9tZSA1MSBoYXMgYSBidWdneSBcInNwbGl0XCIgaW1wbGVtZW50YXRpb24gd2hlbiBSZWdFeHAjZXhlYyAhPT0gbmF0aXZlRXhlY1xuICAvLyBXZWV4IEpTIGhhcyBmcm96ZW4gYnVpbHQtaW4gcHJvdG90eXBlcywgc28gdXNlIHRyeSAvIGNhdGNoIHdyYXBwZXJcbiAgdmFyIFNQTElUX1dPUktTX1dJVEhfT1ZFUldSSVRURU5fRVhFQyA9ICFmYWlscyhmdW5jdGlvbiAoKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHJlZ2V4cC9uby1lbXB0eS1ncm91cCAtLSByZXF1aXJlZCBmb3IgdGVzdGluZ1xuICAgIHZhciByZSA9IC8oPzopLztcbiAgICB2YXIgb3JpZ2luYWxFeGVjID0gcmUuZXhlYztcbiAgICByZS5leGVjID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gb3JpZ2luYWxFeGVjLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7IH07XG4gICAgdmFyIHJlc3VsdCA9ICdhYicuc3BsaXQocmUpO1xuICAgIHJldHVybiByZXN1bHQubGVuZ3RoICE9PSAyIHx8IHJlc3VsdFswXSAhPT0gJ2EnIHx8IHJlc3VsdFsxXSAhPT0gJ2InO1xuICB9KTtcblxuICB2YXIgZml4UmVnZXhwV2VsbEtub3duU3ltYm9sTG9naWMgPSBmdW5jdGlvbiAoS0VZLCBsZW5ndGgsIGV4ZWMsIHNoYW0pIHtcbiAgICB2YXIgU1lNQk9MID0gd2VsbEtub3duU3ltYm9sKEtFWSk7XG5cbiAgICB2YXIgREVMRUdBVEVTX1RPX1NZTUJPTCA9ICFmYWlscyhmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBTdHJpbmcgbWV0aG9kcyBjYWxsIHN5bWJvbC1uYW1lZCBSZWdFcCBtZXRob2RzXG4gICAgICB2YXIgTyA9IHt9O1xuICAgICAgT1tTWU1CT0xdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gNzsgfTtcbiAgICAgIHJldHVybiAnJ1tLRVldKE8pICE9IDc7XG4gICAgfSk7XG5cbiAgICB2YXIgREVMRUdBVEVTX1RPX0VYRUMgPSBERUxFR0FURVNfVE9fU1lNQk9MICYmICFmYWlscyhmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBTeW1ib2wtbmFtZWQgUmVnRXhwIG1ldGhvZHMgY2FsbCAuZXhlY1xuICAgICAgdmFyIGV4ZWNDYWxsZWQgPSBmYWxzZTtcbiAgICAgIHZhciByZSA9IC9hLztcblxuICAgICAgaWYgKEtFWSA9PT0gJ3NwbGl0Jykge1xuICAgICAgICAvLyBXZSBjYW4ndCB1c2UgcmVhbCByZWdleCBoZXJlIHNpbmNlIGl0IGNhdXNlcyBkZW9wdGltaXphdGlvblxuICAgICAgICAvLyBhbmQgc2VyaW91cyBwZXJmb3JtYW5jZSBkZWdyYWRhdGlvbiBpbiBWOFxuICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vemxvaXJvY2svY29yZS1qcy9pc3N1ZXMvMzA2XG4gICAgICAgIHJlID0ge307XG4gICAgICAgIC8vIFJlZ0V4cFtAQHNwbGl0XSBkb2Vzbid0IGNhbGwgdGhlIHJlZ2V4J3MgZXhlYyBtZXRob2QsIGJ1dCBmaXJzdCBjcmVhdGVzXG4gICAgICAgIC8vIGEgbmV3IG9uZS4gV2UgbmVlZCB0byByZXR1cm4gdGhlIHBhdGNoZWQgcmVnZXggd2hlbiBjcmVhdGluZyB0aGUgbmV3IG9uZS5cbiAgICAgICAgcmUuY29uc3RydWN0b3IgPSB7fTtcbiAgICAgICAgcmUuY29uc3RydWN0b3JbU1BFQ0lFUyQ1XSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHJlOyB9O1xuICAgICAgICByZS5mbGFncyA9ICcnO1xuICAgICAgICByZVtTWU1CT0xdID0gLy4vW1NZTUJPTF07XG4gICAgICB9XG5cbiAgICAgIHJlLmV4ZWMgPSBmdW5jdGlvbiAoKSB7IGV4ZWNDYWxsZWQgPSB0cnVlOyByZXR1cm4gbnVsbDsgfTtcblxuICAgICAgcmVbU1lNQk9MXSgnJyk7XG4gICAgICByZXR1cm4gIWV4ZWNDYWxsZWQ7XG4gICAgfSk7XG5cbiAgICBpZiAoXG4gICAgICAhREVMRUdBVEVTX1RPX1NZTUJPTCB8fFxuICAgICAgIURFTEVHQVRFU19UT19FWEVDIHx8XG4gICAgICAoS0VZID09PSAncmVwbGFjZScgJiYgIShcbiAgICAgICAgUkVQTEFDRV9TVVBQT1JUU19OQU1FRF9HUk9VUFMgJiZcbiAgICAgICAgUkVQTEFDRV9LRUVQU18kMCAmJlxuICAgICAgICAhUkVHRVhQX1JFUExBQ0VfU1VCU1RJVFVURVNfVU5ERUZJTkVEX0NBUFRVUkVcbiAgICAgICkpIHx8XG4gICAgICAoS0VZID09PSAnc3BsaXQnICYmICFTUExJVF9XT1JLU19XSVRIX09WRVJXUklUVEVOX0VYRUMpXG4gICAgKSB7XG4gICAgICB2YXIgbmF0aXZlUmVnRXhwTWV0aG9kID0gLy4vW1NZTUJPTF07XG4gICAgICB2YXIgbWV0aG9kcyA9IGV4ZWMoU1lNQk9MLCAnJ1tLRVldLCBmdW5jdGlvbiAobmF0aXZlTWV0aG9kLCByZWdleHAsIHN0ciwgYXJnMiwgZm9yY2VTdHJpbmdNZXRob2QpIHtcbiAgICAgICAgaWYgKHJlZ2V4cC5leGVjID09PSByZWdleHBFeGVjKSB7XG4gICAgICAgICAgaWYgKERFTEVHQVRFU19UT19TWU1CT0wgJiYgIWZvcmNlU3RyaW5nTWV0aG9kKSB7XG4gICAgICAgICAgICAvLyBUaGUgbmF0aXZlIFN0cmluZyBtZXRob2QgYWxyZWFkeSBkZWxlZ2F0ZXMgdG8gQEBtZXRob2QgKHRoaXNcbiAgICAgICAgICAgIC8vIHBvbHlmaWxsZWQgZnVuY3Rpb24pLCBsZWFzaW5nIHRvIGluZmluaXRlIHJlY3Vyc2lvbi5cbiAgICAgICAgICAgIC8vIFdlIGF2b2lkIGl0IGJ5IGRpcmVjdGx5IGNhbGxpbmcgdGhlIG5hdGl2ZSBAQG1ldGhvZCBtZXRob2QuXG4gICAgICAgICAgICByZXR1cm4geyBkb25lOiB0cnVlLCB2YWx1ZTogbmF0aXZlUmVnRXhwTWV0aG9kLmNhbGwocmVnZXhwLCBzdHIsIGFyZzIpIH07XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB7IGRvbmU6IHRydWUsIHZhbHVlOiBuYXRpdmVNZXRob2QuY2FsbChzdHIsIHJlZ2V4cCwgYXJnMikgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyBkb25lOiBmYWxzZSB9O1xuICAgICAgfSwge1xuICAgICAgICBSRVBMQUNFX0tFRVBTXyQwOiBSRVBMQUNFX0tFRVBTXyQwLFxuICAgICAgICBSRUdFWFBfUkVQTEFDRV9TVUJTVElUVVRFU19VTkRFRklORURfQ0FQVFVSRTogUkVHRVhQX1JFUExBQ0VfU1VCU1RJVFVURVNfVU5ERUZJTkVEX0NBUFRVUkVcbiAgICAgIH0pO1xuICAgICAgdmFyIHN0cmluZ01ldGhvZCA9IG1ldGhvZHNbMF07XG4gICAgICB2YXIgcmVnZXhNZXRob2QgPSBtZXRob2RzWzFdO1xuXG4gICAgICByZWRlZmluZShTdHJpbmcucHJvdG90eXBlLCBLRVksIHN0cmluZ01ldGhvZCk7XG4gICAgICByZWRlZmluZShSZWdFeHAucHJvdG90eXBlLCBTWU1CT0wsIGxlbmd0aCA9PSAyXG4gICAgICAgIC8vIDIxLjIuNS44IFJlZ0V4cC5wcm90b3R5cGVbQEByZXBsYWNlXShzdHJpbmcsIHJlcGxhY2VWYWx1ZSlcbiAgICAgICAgLy8gMjEuMi41LjExIFJlZ0V4cC5wcm90b3R5cGVbQEBzcGxpdF0oc3RyaW5nLCBsaW1pdClcbiAgICAgICAgPyBmdW5jdGlvbiAoc3RyaW5nLCBhcmcpIHsgcmV0dXJuIHJlZ2V4TWV0aG9kLmNhbGwoc3RyaW5nLCB0aGlzLCBhcmcpOyB9XG4gICAgICAgIC8vIDIxLjIuNS42IFJlZ0V4cC5wcm90b3R5cGVbQEBtYXRjaF0oc3RyaW5nKVxuICAgICAgICAvLyAyMS4yLjUuOSBSZWdFeHAucHJvdG90eXBlW0BAc2VhcmNoXShzdHJpbmcpXG4gICAgICAgIDogZnVuY3Rpb24gKHN0cmluZykgeyByZXR1cm4gcmVnZXhNZXRob2QuY2FsbChzdHJpbmcsIHRoaXMpOyB9XG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChzaGFtKSBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkoUmVnRXhwLnByb3RvdHlwZVtTWU1CT0xdLCAnc2hhbScsIHRydWUpO1xuICB9O1xuXG4gIHZhciBNQVRDSCQyID0gd2VsbEtub3duU3ltYm9sKCdtYXRjaCcpO1xuXG4gIC8vIGBJc1JlZ0V4cGAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtaXNyZWdleHBcbiAgdmFyIGlzUmVnZXhwID0gZnVuY3Rpb24gKGl0KSB7XG4gICAgdmFyIGlzUmVnRXhwO1xuICAgIHJldHVybiBpc09iamVjdChpdCkgJiYgKChpc1JlZ0V4cCA9IGl0W01BVENIJDJdKSAhPT0gdW5kZWZpbmVkID8gISFpc1JlZ0V4cCA6IGNsYXNzb2ZSYXcoaXQpID09ICdSZWdFeHAnKTtcbiAgfTtcblxuICB2YXIgYUZ1bmN0aW9uID0gZnVuY3Rpb24gKGl0KSB7XG4gICAgaWYgKHR5cGVvZiBpdCAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICB0aHJvdyBUeXBlRXJyb3IoU3RyaW5nKGl0KSArICcgaXMgbm90IGEgZnVuY3Rpb24nKTtcbiAgICB9IHJldHVybiBpdDtcbiAgfTtcblxuICB2YXIgU1BFQ0lFUyQ0ID0gd2VsbEtub3duU3ltYm9sKCdzcGVjaWVzJyk7XG5cbiAgLy8gYFNwZWNpZXNDb25zdHJ1Y3RvcmAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtc3BlY2llc2NvbnN0cnVjdG9yXG4gIHZhciBzcGVjaWVzQ29uc3RydWN0b3IgPSBmdW5jdGlvbiAoTywgZGVmYXVsdENvbnN0cnVjdG9yKSB7XG4gICAgdmFyIEMgPSBhbk9iamVjdChPKS5jb25zdHJ1Y3RvcjtcbiAgICB2YXIgUztcbiAgICByZXR1cm4gQyA9PT0gdW5kZWZpbmVkIHx8IChTID0gYW5PYmplY3QoQylbU1BFQ0lFUyQ0XSkgPT0gdW5kZWZpbmVkID8gZGVmYXVsdENvbnN0cnVjdG9yIDogYUZ1bmN0aW9uKFMpO1xuICB9O1xuXG4gIC8vIGBTdHJpbmcucHJvdG90eXBlLnsgY29kZVBvaW50QXQsIGF0IH1gIG1ldGhvZHMgaW1wbGVtZW50YXRpb25cbiAgdmFyIGNyZWF0ZU1ldGhvZCQyID0gZnVuY3Rpb24gKENPTlZFUlRfVE9fU1RSSU5HKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgkdGhpcywgcG9zKSB7XG4gICAgICB2YXIgUyA9IFN0cmluZyhyZXF1aXJlT2JqZWN0Q29lcmNpYmxlKCR0aGlzKSk7XG4gICAgICB2YXIgcG9zaXRpb24gPSB0b0ludGVnZXIocG9zKTtcbiAgICAgIHZhciBzaXplID0gUy5sZW5ndGg7XG4gICAgICB2YXIgZmlyc3QsIHNlY29uZDtcbiAgICAgIGlmIChwb3NpdGlvbiA8IDAgfHwgcG9zaXRpb24gPj0gc2l6ZSkgcmV0dXJuIENPTlZFUlRfVE9fU1RSSU5HID8gJycgOiB1bmRlZmluZWQ7XG4gICAgICBmaXJzdCA9IFMuY2hhckNvZGVBdChwb3NpdGlvbik7XG4gICAgICByZXR1cm4gZmlyc3QgPCAweEQ4MDAgfHwgZmlyc3QgPiAweERCRkYgfHwgcG9zaXRpb24gKyAxID09PSBzaXplXG4gICAgICAgIHx8IChzZWNvbmQgPSBTLmNoYXJDb2RlQXQocG9zaXRpb24gKyAxKSkgPCAweERDMDAgfHwgc2Vjb25kID4gMHhERkZGXG4gICAgICAgICAgPyBDT05WRVJUX1RPX1NUUklORyA/IFMuY2hhckF0KHBvc2l0aW9uKSA6IGZpcnN0XG4gICAgICAgICAgOiBDT05WRVJUX1RPX1NUUklORyA/IFMuc2xpY2UocG9zaXRpb24sIHBvc2l0aW9uICsgMikgOiAoZmlyc3QgLSAweEQ4MDAgPDwgMTApICsgKHNlY29uZCAtIDB4REMwMCkgKyAweDEwMDAwO1xuICAgIH07XG4gIH07XG5cbiAgdmFyIHN0cmluZ011bHRpYnl0ZSA9IHtcbiAgICAvLyBgU3RyaW5nLnByb3RvdHlwZS5jb2RlUG9pbnRBdGAgbWV0aG9kXG4gICAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1zdHJpbmcucHJvdG90eXBlLmNvZGVwb2ludGF0XG4gICAgY29kZUF0OiBjcmVhdGVNZXRob2QkMihmYWxzZSksXG4gICAgLy8gYFN0cmluZy5wcm90b3R5cGUuYXRgIG1ldGhvZFxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9tYXRoaWFzYnluZW5zL1N0cmluZy5wcm90b3R5cGUuYXRcbiAgICBjaGFyQXQ6IGNyZWF0ZU1ldGhvZCQyKHRydWUpXG4gIH07XG5cbiAgdmFyIGNoYXJBdCA9IHN0cmluZ011bHRpYnl0ZS5jaGFyQXQ7XG5cbiAgLy8gYEFkdmFuY2VTdHJpbmdJbmRleGAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYWR2YW5jZXN0cmluZ2luZGV4XG4gIHZhciBhZHZhbmNlU3RyaW5nSW5kZXggPSBmdW5jdGlvbiAoUywgaW5kZXgsIHVuaWNvZGUpIHtcbiAgICByZXR1cm4gaW5kZXggKyAodW5pY29kZSA/IGNoYXJBdChTLCBpbmRleCkubGVuZ3RoIDogMSk7XG4gIH07XG5cbiAgLy8gYFJlZ0V4cEV4ZWNgIGFic3RyYWN0IG9wZXJhdGlvblxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXJlZ2V4cGV4ZWNcbiAgdmFyIHJlZ2V4cEV4ZWNBYnN0cmFjdCA9IGZ1bmN0aW9uIChSLCBTKSB7XG4gICAgdmFyIGV4ZWMgPSBSLmV4ZWM7XG4gICAgaWYgKHR5cGVvZiBleGVjID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gZXhlYy5jYWxsKFIsIFMpO1xuICAgICAgaWYgKHR5cGVvZiByZXN1bHQgIT09ICdvYmplY3QnKSB7XG4gICAgICAgIHRocm93IFR5cGVFcnJvcignUmVnRXhwIGV4ZWMgbWV0aG9kIHJldHVybmVkIHNvbWV0aGluZyBvdGhlciB0aGFuIGFuIE9iamVjdCBvciBudWxsJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGlmIChjbGFzc29mUmF3KFIpICE9PSAnUmVnRXhwJykge1xuICAgICAgdGhyb3cgVHlwZUVycm9yKCdSZWdFeHAjZXhlYyBjYWxsZWQgb24gaW5jb21wYXRpYmxlIHJlY2VpdmVyJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlZ2V4cEV4ZWMuY2FsbChSLCBTKTtcbiAgfTtcblxuICB2YXIgYXJyYXlQdXNoID0gW10ucHVzaDtcbiAgdmFyIG1pbiQ0ID0gTWF0aC5taW47XG4gIHZhciBNQVhfVUlOVDMyID0gMHhGRkZGRkZGRjtcblxuICAvLyBiYWJlbC1taW5pZnkgdHJhbnNwaWxlcyBSZWdFeHAoJ3gnLCAneScpIC0+IC94L3kgYW5kIGl0IGNhdXNlcyBTeW50YXhFcnJvclxuICB2YXIgU1VQUE9SVFNfWSA9ICFmYWlscyhmdW5jdGlvbiAoKSB7IHJldHVybiAhUmVnRXhwKE1BWF9VSU5UMzIsICd5Jyk7IH0pO1xuXG4gIC8vIEBAc3BsaXQgbG9naWNcbiAgZml4UmVnZXhwV2VsbEtub3duU3ltYm9sTG9naWMoJ3NwbGl0JywgMiwgZnVuY3Rpb24gKFNQTElULCBuYXRpdmVTcGxpdCwgbWF5YmVDYWxsTmF0aXZlKSB7XG4gICAgdmFyIGludGVybmFsU3BsaXQ7XG4gICAgaWYgKFxuICAgICAgJ2FiYmMnLnNwbGl0KC8oYikqLylbMV0gPT0gJ2MnIHx8XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVnZXhwL25vLWVtcHR5LWdyb3VwIC0tIHJlcXVpcmVkIGZvciB0ZXN0aW5nXG4gICAgICAndGVzdCcuc3BsaXQoLyg/OikvLCAtMSkubGVuZ3RoICE9IDQgfHxcbiAgICAgICdhYicuc3BsaXQoLyg/OmFiKSovKS5sZW5ndGggIT0gMiB8fFxuICAgICAgJy4nLnNwbGl0KC8oLj8pKC4/KS8pLmxlbmd0aCAhPSA0IHx8XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVnZXhwL25vLWFzc2VydGlvbi1jYXB0dXJpbmctZ3JvdXAsIHJlZ2V4cC9uby1lbXB0eS1ncm91cCAtLSByZXF1aXJlZCBmb3IgdGVzdGluZ1xuICAgICAgJy4nLnNwbGl0KC8oKSgpLykubGVuZ3RoID4gMSB8fFxuICAgICAgJycuc3BsaXQoLy4/LykubGVuZ3RoXG4gICAgKSB7XG4gICAgICAvLyBiYXNlZCBvbiBlczUtc2hpbSBpbXBsZW1lbnRhdGlvbiwgbmVlZCB0byByZXdvcmsgaXRcbiAgICAgIGludGVybmFsU3BsaXQgPSBmdW5jdGlvbiAoc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICB2YXIgc3RyaW5nID0gU3RyaW5nKHJlcXVpcmVPYmplY3RDb2VyY2libGUodGhpcykpO1xuICAgICAgICB2YXIgbGltID0gbGltaXQgPT09IHVuZGVmaW5lZCA/IE1BWF9VSU5UMzIgOiBsaW1pdCA+Pj4gMDtcbiAgICAgICAgaWYgKGxpbSA9PT0gMCkgcmV0dXJuIFtdO1xuICAgICAgICBpZiAoc2VwYXJhdG9yID09PSB1bmRlZmluZWQpIHJldHVybiBbc3RyaW5nXTtcbiAgICAgICAgLy8gSWYgYHNlcGFyYXRvcmAgaXMgbm90IGEgcmVnZXgsIHVzZSBuYXRpdmUgc3BsaXRcbiAgICAgICAgaWYgKCFpc1JlZ2V4cChzZXBhcmF0b3IpKSB7XG4gICAgICAgICAgcmV0dXJuIG5hdGl2ZVNwbGl0LmNhbGwoc3RyaW5nLCBzZXBhcmF0b3IsIGxpbSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG91dHB1dCA9IFtdO1xuICAgICAgICB2YXIgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyAnaScgOiAnJykgK1xuICAgICAgICAgICAgICAgICAgICAoc2VwYXJhdG9yLm11bHRpbGluZSA/ICdtJyA6ICcnKSArXG4gICAgICAgICAgICAgICAgICAgIChzZXBhcmF0b3IudW5pY29kZSA/ICd1JyA6ICcnKSArXG4gICAgICAgICAgICAgICAgICAgIChzZXBhcmF0b3Iuc3RpY2t5ID8gJ3knIDogJycpO1xuICAgICAgICB2YXIgbGFzdExhc3RJbmRleCA9IDA7XG4gICAgICAgIC8vIE1ha2UgYGdsb2JhbGAgYW5kIGF2b2lkIGBsYXN0SW5kZXhgIGlzc3VlcyBieSB3b3JraW5nIHdpdGggYSBjb3B5XG4gICAgICAgIHZhciBzZXBhcmF0b3JDb3B5ID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArICdnJyk7XG4gICAgICAgIHZhciBtYXRjaCwgbGFzdEluZGV4LCBsYXN0TGVuZ3RoO1xuICAgICAgICB3aGlsZSAobWF0Y2ggPSByZWdleHBFeGVjLmNhbGwoc2VwYXJhdG9yQ29weSwgc3RyaW5nKSkge1xuICAgICAgICAgIGxhc3RJbmRleCA9IHNlcGFyYXRvckNvcHkubGFzdEluZGV4O1xuICAgICAgICAgIGlmIChsYXN0SW5kZXggPiBsYXN0TGFzdEluZGV4KSB7XG4gICAgICAgICAgICBvdXRwdXQucHVzaChzdHJpbmcuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyaW5nLmxlbmd0aCkgYXJyYXlQdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICBpZiAob3V0cHV0Lmxlbmd0aCA+PSBsaW0pIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoc2VwYXJhdG9yQ29weS5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSBzZXBhcmF0b3JDb3B5Lmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgIH1cbiAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0cmluZy5sZW5ndGgpIHtcbiAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yQ29weS50ZXN0KCcnKSkgb3V0cHV0LnB1c2goJycpO1xuICAgICAgICB9IGVsc2Ugb3V0cHV0LnB1c2goc3RyaW5nLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW0gPyBvdXRwdXQuc2xpY2UoMCwgbGltKSA6IG91dHB1dDtcbiAgICAgIH07XG4gICAgLy8gQ2hha3JhLCBWOFxuICAgIH0gZWxzZSBpZiAoJzAnLnNwbGl0KHVuZGVmaW5lZCwgMCkubGVuZ3RoKSB7XG4gICAgICBpbnRlcm5hbFNwbGl0ID0gZnVuY3Rpb24gKHNlcGFyYXRvciwgbGltaXQpIHtcbiAgICAgICAgcmV0dXJuIHNlcGFyYXRvciA9PT0gdW5kZWZpbmVkICYmIGxpbWl0ID09PSAwID8gW10gOiBuYXRpdmVTcGxpdC5jYWxsKHRoaXMsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgfTtcbiAgICB9IGVsc2UgaW50ZXJuYWxTcGxpdCA9IG5hdGl2ZVNwbGl0O1xuXG4gICAgcmV0dXJuIFtcbiAgICAgIC8vIGBTdHJpbmcucHJvdG90eXBlLnNwbGl0YCBtZXRob2RcbiAgICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtc3RyaW5nLnByb3RvdHlwZS5zcGxpdFxuICAgICAgZnVuY3Rpb24gc3BsaXQoc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICB2YXIgTyA9IHJlcXVpcmVPYmplY3RDb2VyY2libGUodGhpcyk7XG4gICAgICAgIHZhciBzcGxpdHRlciA9IHNlcGFyYXRvciA9PSB1bmRlZmluZWQgPyB1bmRlZmluZWQgOiBzZXBhcmF0b3JbU1BMSVRdO1xuICAgICAgICByZXR1cm4gc3BsaXR0ZXIgIT09IHVuZGVmaW5lZFxuICAgICAgICAgID8gc3BsaXR0ZXIuY2FsbChzZXBhcmF0b3IsIE8sIGxpbWl0KVxuICAgICAgICAgIDogaW50ZXJuYWxTcGxpdC5jYWxsKFN0cmluZyhPKSwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICB9LFxuICAgICAgLy8gYFJlZ0V4cC5wcm90b3R5cGVbQEBzcGxpdF1gIG1ldGhvZFxuICAgICAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1yZWdleHAucHJvdG90eXBlLUBAc3BsaXRcbiAgICAgIC8vXG4gICAgICAvLyBOT1RFOiBUaGlzIGNhbm5vdCBiZSBwcm9wZXJseSBwb2x5ZmlsbGVkIGluIGVuZ2luZXMgdGhhdCBkb24ndCBzdXBwb3J0XG4gICAgICAvLyB0aGUgJ3knIGZsYWcuXG4gICAgICBmdW5jdGlvbiAocmVnZXhwLCBsaW1pdCkge1xuICAgICAgICB2YXIgcmVzID0gbWF5YmVDYWxsTmF0aXZlKGludGVybmFsU3BsaXQsIHJlZ2V4cCwgdGhpcywgbGltaXQsIGludGVybmFsU3BsaXQgIT09IG5hdGl2ZVNwbGl0KTtcbiAgICAgICAgaWYgKHJlcy5kb25lKSByZXR1cm4gcmVzLnZhbHVlO1xuXG4gICAgICAgIHZhciByeCA9IGFuT2JqZWN0KHJlZ2V4cCk7XG4gICAgICAgIHZhciBTID0gU3RyaW5nKHRoaXMpO1xuICAgICAgICB2YXIgQyA9IHNwZWNpZXNDb25zdHJ1Y3RvcihyeCwgUmVnRXhwKTtcblxuICAgICAgICB2YXIgdW5pY29kZU1hdGNoaW5nID0gcngudW5pY29kZTtcbiAgICAgICAgdmFyIGZsYWdzID0gKHJ4Lmlnbm9yZUNhc2UgPyAnaScgOiAnJykgK1xuICAgICAgICAgICAgICAgICAgICAocngubXVsdGlsaW5lID8gJ20nIDogJycpICtcbiAgICAgICAgICAgICAgICAgICAgKHJ4LnVuaWNvZGUgPyAndScgOiAnJykgK1xuICAgICAgICAgICAgICAgICAgICAoU1VQUE9SVFNfWSA/ICd5JyA6ICdnJyk7XG5cbiAgICAgICAgLy8gXig/ICsgcnggKyApIGlzIG5lZWRlZCwgaW4gY29tYmluYXRpb24gd2l0aCBzb21lIFMgc2xpY2luZywgdG9cbiAgICAgICAgLy8gc2ltdWxhdGUgdGhlICd5JyBmbGFnLlxuICAgICAgICB2YXIgc3BsaXR0ZXIgPSBuZXcgQyhTVVBQT1JUU19ZID8gcnggOiAnXig/OicgKyByeC5zb3VyY2UgKyAnKScsIGZsYWdzKTtcbiAgICAgICAgdmFyIGxpbSA9IGxpbWl0ID09PSB1bmRlZmluZWQgPyBNQVhfVUlOVDMyIDogbGltaXQgPj4+IDA7XG4gICAgICAgIGlmIChsaW0gPT09IDApIHJldHVybiBbXTtcbiAgICAgICAgaWYgKFMubGVuZ3RoID09PSAwKSByZXR1cm4gcmVnZXhwRXhlY0Fic3RyYWN0KHNwbGl0dGVyLCBTKSA9PT0gbnVsbCA/IFtTXSA6IFtdO1xuICAgICAgICB2YXIgcCA9IDA7XG4gICAgICAgIHZhciBxID0gMDtcbiAgICAgICAgdmFyIEEgPSBbXTtcbiAgICAgICAgd2hpbGUgKHEgPCBTLmxlbmd0aCkge1xuICAgICAgICAgIHNwbGl0dGVyLmxhc3RJbmRleCA9IFNVUFBPUlRTX1kgPyBxIDogMDtcbiAgICAgICAgICB2YXIgeiA9IHJlZ2V4cEV4ZWNBYnN0cmFjdChzcGxpdHRlciwgU1VQUE9SVFNfWSA/IFMgOiBTLnNsaWNlKHEpKTtcbiAgICAgICAgICB2YXIgZTtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICB6ID09PSBudWxsIHx8XG4gICAgICAgICAgICAoZSA9IG1pbiQ0KHRvTGVuZ3RoKHNwbGl0dGVyLmxhc3RJbmRleCArIChTVVBQT1JUU19ZID8gMCA6IHEpKSwgUy5sZW5ndGgpKSA9PT0gcFxuICAgICAgICAgICkge1xuICAgICAgICAgICAgcSA9IGFkdmFuY2VTdHJpbmdJbmRleChTLCBxLCB1bmljb2RlTWF0Y2hpbmcpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBBLnB1c2goUy5zbGljZShwLCBxKSk7XG4gICAgICAgICAgICBpZiAoQS5sZW5ndGggPT09IGxpbSkgcmV0dXJuIEE7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8PSB6Lmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgICAgICAgICBBLnB1c2goeltpXSk7XG4gICAgICAgICAgICAgIGlmIChBLmxlbmd0aCA9PT0gbGltKSByZXR1cm4gQTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHEgPSBwID0gZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgQS5wdXNoKFMuc2xpY2UocCkpO1xuICAgICAgICByZXR1cm4gQTtcbiAgICAgIH1cbiAgICBdO1xuICB9LCAhU1VQUE9SVFNfWSk7XG5cbiAgLy8gYE9iamVjdC5rZXlzYCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1vYmplY3Qua2V5c1xuICB2YXIgb2JqZWN0S2V5cyA9IE9iamVjdC5rZXlzIHx8IGZ1bmN0aW9uIGtleXMoTykge1xuICAgIHJldHVybiBvYmplY3RLZXlzSW50ZXJuYWwoTywgZW51bUJ1Z0tleXMpO1xuICB9O1xuXG4gIC8vIGBPYmplY3QuZGVmaW5lUHJvcGVydGllc2AgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtb2JqZWN0LmRlZmluZXByb3BlcnRpZXNcbiAgdmFyIG9iamVjdERlZmluZVByb3BlcnRpZXMgPSBkZXNjcmlwdG9ycyA/IE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzIDogZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyhPLCBQcm9wZXJ0aWVzKSB7XG4gICAgYW5PYmplY3QoTyk7XG4gICAgdmFyIGtleXMgPSBvYmplY3RLZXlzKFByb3BlcnRpZXMpO1xuICAgIHZhciBsZW5ndGggPSBrZXlzLmxlbmd0aDtcbiAgICB2YXIgaW5kZXggPSAwO1xuICAgIHZhciBrZXk7XG4gICAgd2hpbGUgKGxlbmd0aCA+IGluZGV4KSBvYmplY3REZWZpbmVQcm9wZXJ0eS5mKE8sIGtleSA9IGtleXNbaW5kZXgrK10sIFByb3BlcnRpZXNba2V5XSk7XG4gICAgcmV0dXJuIE87XG4gIH07XG5cbiAgdmFyIGh0bWwgPSBnZXRCdWlsdEluKCdkb2N1bWVudCcsICdkb2N1bWVudEVsZW1lbnQnKTtcblxuICB2YXIgR1QgPSAnPic7XG4gIHZhciBMVCA9ICc8JztcbiAgdmFyIFBST1RPVFlQRSA9ICdwcm90b3R5cGUnO1xuICB2YXIgU0NSSVBUID0gJ3NjcmlwdCc7XG4gIHZhciBJRV9QUk9UTyQxID0gc2hhcmVkS2V5KCdJRV9QUk9UTycpO1xuXG4gIHZhciBFbXB0eUNvbnN0cnVjdG9yID0gZnVuY3Rpb24gKCkgeyAvKiBlbXB0eSAqLyB9O1xuXG4gIHZhciBzY3JpcHRUYWcgPSBmdW5jdGlvbiAoY29udGVudCkge1xuICAgIHJldHVybiBMVCArIFNDUklQVCArIEdUICsgY29udGVudCArIExUICsgJy8nICsgU0NSSVBUICsgR1Q7XG4gIH07XG5cbiAgLy8gQ3JlYXRlIG9iamVjdCB3aXRoIGZha2UgYG51bGxgIHByb3RvdHlwZTogdXNlIEFjdGl2ZVggT2JqZWN0IHdpdGggY2xlYXJlZCBwcm90b3R5cGVcbiAgdmFyIE51bGxQcm90b09iamVjdFZpYUFjdGl2ZVggPSBmdW5jdGlvbiAoYWN0aXZlWERvY3VtZW50KSB7XG4gICAgYWN0aXZlWERvY3VtZW50LndyaXRlKHNjcmlwdFRhZygnJykpO1xuICAgIGFjdGl2ZVhEb2N1bWVudC5jbG9zZSgpO1xuICAgIHZhciB0ZW1wID0gYWN0aXZlWERvY3VtZW50LnBhcmVudFdpbmRvdy5PYmplY3Q7XG4gICAgYWN0aXZlWERvY3VtZW50ID0gbnVsbDsgLy8gYXZvaWQgbWVtb3J5IGxlYWtcbiAgICByZXR1cm4gdGVtcDtcbiAgfTtcblxuICAvLyBDcmVhdGUgb2JqZWN0IHdpdGggZmFrZSBgbnVsbGAgcHJvdG90eXBlOiB1c2UgaWZyYW1lIE9iamVjdCB3aXRoIGNsZWFyZWQgcHJvdG90eXBlXG4gIHZhciBOdWxsUHJvdG9PYmplY3RWaWFJRnJhbWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgLy8gVGhyYXNoLCB3YXN0ZSBhbmQgc29kb215OiBJRSBHQyBidWdcbiAgICB2YXIgaWZyYW1lID0gZG9jdW1lbnRDcmVhdGVFbGVtZW50KCdpZnJhbWUnKTtcbiAgICB2YXIgSlMgPSAnamF2YScgKyBTQ1JJUFQgKyAnOic7XG4gICAgdmFyIGlmcmFtZURvY3VtZW50O1xuICAgIGlmcmFtZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIGh0bWwuYXBwZW5kQ2hpbGQoaWZyYW1lKTtcbiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vemxvaXJvY2svY29yZS1qcy9pc3N1ZXMvNDc1XG4gICAgaWZyYW1lLnNyYyA9IFN0cmluZyhKUyk7XG4gICAgaWZyYW1lRG9jdW1lbnQgPSBpZnJhbWUuY29udGVudFdpbmRvdy5kb2N1bWVudDtcbiAgICBpZnJhbWVEb2N1bWVudC5vcGVuKCk7XG4gICAgaWZyYW1lRG9jdW1lbnQud3JpdGUoc2NyaXB0VGFnKCdkb2N1bWVudC5GPU9iamVjdCcpKTtcbiAgICBpZnJhbWVEb2N1bWVudC5jbG9zZSgpO1xuICAgIHJldHVybiBpZnJhbWVEb2N1bWVudC5GO1xuICB9O1xuXG4gIC8vIENoZWNrIGZvciBkb2N1bWVudC5kb21haW4gYW5kIGFjdGl2ZSB4IHN1cHBvcnRcbiAgLy8gTm8gbmVlZCB0byB1c2UgYWN0aXZlIHggYXBwcm9hY2ggd2hlbiBkb2N1bWVudC5kb21haW4gaXMgbm90IHNldFxuICAvLyBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2VzLXNoaW1zL2VzNS1zaGltL2lzc3Vlcy8xNTBcbiAgLy8gdmFyaWF0aW9uIG9mIGh0dHBzOi8vZ2l0aHViLmNvbS9raXRjYW1icmlkZ2UvZXM1LXNoaW0vY29tbWl0LzRmNzM4YWMwNjYzNDZcbiAgLy8gYXZvaWQgSUUgR0MgYnVnXG4gIHZhciBhY3RpdmVYRG9jdW1lbnQ7XG4gIHZhciBOdWxsUHJvdG9PYmplY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgdHJ5IHtcbiAgICAgIC8qIGdsb2JhbCBBY3RpdmVYT2JqZWN0IC0tIG9sZCBJRSAqL1xuICAgICAgYWN0aXZlWERvY3VtZW50ID0gZG9jdW1lbnQuZG9tYWluICYmIG5ldyBBY3RpdmVYT2JqZWN0KCdodG1sZmlsZScpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7IC8qIGlnbm9yZSAqLyB9XG4gICAgTnVsbFByb3RvT2JqZWN0ID0gYWN0aXZlWERvY3VtZW50ID8gTnVsbFByb3RvT2JqZWN0VmlhQWN0aXZlWChhY3RpdmVYRG9jdW1lbnQpIDogTnVsbFByb3RvT2JqZWN0VmlhSUZyYW1lKCk7XG4gICAgdmFyIGxlbmd0aCA9IGVudW1CdWdLZXlzLmxlbmd0aDtcbiAgICB3aGlsZSAobGVuZ3RoLS0pIGRlbGV0ZSBOdWxsUHJvdG9PYmplY3RbUFJPVE9UWVBFXVtlbnVtQnVnS2V5c1tsZW5ndGhdXTtcbiAgICByZXR1cm4gTnVsbFByb3RvT2JqZWN0KCk7XG4gIH07XG5cbiAgaGlkZGVuS2V5cyQxW0lFX1BST1RPJDFdID0gdHJ1ZTtcblxuICAvLyBgT2JqZWN0LmNyZWF0ZWAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtb2JqZWN0LmNyZWF0ZVxuICB2YXIgb2JqZWN0Q3JlYXRlID0gT2JqZWN0LmNyZWF0ZSB8fCBmdW5jdGlvbiBjcmVhdGUoTywgUHJvcGVydGllcykge1xuICAgIHZhciByZXN1bHQ7XG4gICAgaWYgKE8gIT09IG51bGwpIHtcbiAgICAgIEVtcHR5Q29uc3RydWN0b3JbUFJPVE9UWVBFXSA9IGFuT2JqZWN0KE8pO1xuICAgICAgcmVzdWx0ID0gbmV3IEVtcHR5Q29uc3RydWN0b3IoKTtcbiAgICAgIEVtcHR5Q29uc3RydWN0b3JbUFJPVE9UWVBFXSA9IG51bGw7XG4gICAgICAvLyBhZGQgXCJfX3Byb3RvX19cIiBmb3IgT2JqZWN0LmdldFByb3RvdHlwZU9mIHBvbHlmaWxsXG4gICAgICByZXN1bHRbSUVfUFJPVE8kMV0gPSBPO1xuICAgIH0gZWxzZSByZXN1bHQgPSBOdWxsUHJvdG9PYmplY3QoKTtcbiAgICByZXR1cm4gUHJvcGVydGllcyA9PT0gdW5kZWZpbmVkID8gcmVzdWx0IDogb2JqZWN0RGVmaW5lUHJvcGVydGllcyhyZXN1bHQsIFByb3BlcnRpZXMpO1xuICB9O1xuXG4gIHZhciBVTlNDT1BBQkxFUyA9IHdlbGxLbm93blN5bWJvbCgndW5zY29wYWJsZXMnKTtcbiAgdmFyIEFycmF5UHJvdG90eXBlID0gQXJyYXkucHJvdG90eXBlO1xuXG4gIC8vIEFycmF5LnByb3RvdHlwZVtAQHVuc2NvcGFibGVzXVxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS1AQHVuc2NvcGFibGVzXG4gIGlmIChBcnJheVByb3RvdHlwZVtVTlNDT1BBQkxFU10gPT0gdW5kZWZpbmVkKSB7XG4gICAgb2JqZWN0RGVmaW5lUHJvcGVydHkuZihBcnJheVByb3RvdHlwZSwgVU5TQ09QQUJMRVMsIHtcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgIHZhbHVlOiBvYmplY3RDcmVhdGUobnVsbClcbiAgICB9KTtcbiAgfVxuXG4gIC8vIGFkZCBhIGtleSB0byBBcnJheS5wcm90b3R5cGVbQEB1bnNjb3BhYmxlc11cbiAgdmFyIGFkZFRvVW5zY29wYWJsZXMgPSBmdW5jdGlvbiAoa2V5KSB7XG4gICAgQXJyYXlQcm90b3R5cGVbVU5TQ09QQUJMRVNdW2tleV0gPSB0cnVlO1xuICB9O1xuXG4gIHZhciAkaW5jbHVkZXMgPSBhcnJheUluY2x1ZGVzLmluY2x1ZGVzO1xuXG5cbiAgLy8gYEFycmF5LnByb3RvdHlwZS5pbmNsdWRlc2AgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLmluY2x1ZGVzXG4gIF9leHBvcnQoeyB0YXJnZXQ6ICdBcnJheScsIHByb3RvOiB0cnVlIH0sIHtcbiAgICBpbmNsdWRlczogZnVuY3Rpb24gaW5jbHVkZXMoZWwgLyogLCBmcm9tSW5kZXggPSAwICovKSB7XG4gICAgICByZXR1cm4gJGluY2x1ZGVzKHRoaXMsIGVsLCBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCk7XG4gICAgfVxuICB9KTtcblxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS1AQHVuc2NvcGFibGVzXG4gIGFkZFRvVW5zY29wYWJsZXMoJ2luY2x1ZGVzJyk7XG5cbiAgLy8gYElzQXJyYXlgIGFic3RyYWN0IG9wZXJhdGlvblxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWlzYXJyYXlcbiAgdmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5IHx8IGZ1bmN0aW9uIGlzQXJyYXkoYXJnKSB7XG4gICAgcmV0dXJuIGNsYXNzb2ZSYXcoYXJnKSA9PSAnQXJyYXknO1xuICB9O1xuXG4gIC8vIGBUb09iamVjdGAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtdG9vYmplY3RcbiAgdmFyIHRvT2JqZWN0ID0gZnVuY3Rpb24gKGFyZ3VtZW50KSB7XG4gICAgcmV0dXJuIE9iamVjdChyZXF1aXJlT2JqZWN0Q29lcmNpYmxlKGFyZ3VtZW50KSk7XG4gIH07XG5cbiAgdmFyIGNyZWF0ZVByb3BlcnR5ID0gZnVuY3Rpb24gKG9iamVjdCwga2V5LCB2YWx1ZSkge1xuICAgIHZhciBwcm9wZXJ0eUtleSA9IHRvUHJpbWl0aXZlKGtleSk7XG4gICAgaWYgKHByb3BlcnR5S2V5IGluIG9iamVjdCkgb2JqZWN0RGVmaW5lUHJvcGVydHkuZihvYmplY3QsIHByb3BlcnR5S2V5LCBjcmVhdGVQcm9wZXJ0eURlc2NyaXB0b3IoMCwgdmFsdWUpKTtcbiAgICBlbHNlIG9iamVjdFtwcm9wZXJ0eUtleV0gPSB2YWx1ZTtcbiAgfTtcblxuICB2YXIgU1BFQ0lFUyQzID0gd2VsbEtub3duU3ltYm9sKCdzcGVjaWVzJyk7XG5cbiAgLy8gYEFycmF5U3BlY2llc0NyZWF0ZWAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXlzcGVjaWVzY3JlYXRlXG4gIHZhciBhcnJheVNwZWNpZXNDcmVhdGUgPSBmdW5jdGlvbiAob3JpZ2luYWxBcnJheSwgbGVuZ3RoKSB7XG4gICAgdmFyIEM7XG4gICAgaWYgKGlzQXJyYXkob3JpZ2luYWxBcnJheSkpIHtcbiAgICAgIEMgPSBvcmlnaW5hbEFycmF5LmNvbnN0cnVjdG9yO1xuICAgICAgLy8gY3Jvc3MtcmVhbG0gZmFsbGJhY2tcbiAgICAgIGlmICh0eXBlb2YgQyA9PSAnZnVuY3Rpb24nICYmIChDID09PSBBcnJheSB8fCBpc0FycmF5KEMucHJvdG90eXBlKSkpIEMgPSB1bmRlZmluZWQ7XG4gICAgICBlbHNlIGlmIChpc09iamVjdChDKSkge1xuICAgICAgICBDID0gQ1tTUEVDSUVTJDNdO1xuICAgICAgICBpZiAoQyA9PT0gbnVsbCkgQyA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICB9IHJldHVybiBuZXcgKEMgPT09IHVuZGVmaW5lZCA/IEFycmF5IDogQykobGVuZ3RoID09PSAwID8gMCA6IGxlbmd0aCk7XG4gIH07XG5cbiAgdmFyIFNQRUNJRVMkMiA9IHdlbGxLbm93blN5bWJvbCgnc3BlY2llcycpO1xuXG4gIHZhciBhcnJheU1ldGhvZEhhc1NwZWNpZXNTdXBwb3J0ID0gZnVuY3Rpb24gKE1FVEhPRF9OQU1FKSB7XG4gICAgLy8gV2UgY2FuJ3QgdXNlIHRoaXMgZmVhdHVyZSBkZXRlY3Rpb24gaW4gVjggc2luY2UgaXQgY2F1c2VzXG4gICAgLy8gZGVvcHRpbWl6YXRpb24gYW5kIHNlcmlvdXMgcGVyZm9ybWFuY2UgZGVncmFkYXRpb25cbiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vemxvaXJvY2svY29yZS1qcy9pc3N1ZXMvNjc3XG4gICAgcmV0dXJuIGVuZ2luZVY4VmVyc2lvbiA+PSA1MSB8fCAhZmFpbHMoZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIGFycmF5ID0gW107XG4gICAgICB2YXIgY29uc3RydWN0b3IgPSBhcnJheS5jb25zdHJ1Y3RvciA9IHt9O1xuICAgICAgY29uc3RydWN0b3JbU1BFQ0lFUyQyXSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHsgZm9vOiAxIH07XG4gICAgICB9O1xuICAgICAgcmV0dXJuIGFycmF5W01FVEhPRF9OQU1FXShCb29sZWFuKS5mb28gIT09IDE7XG4gICAgfSk7XG4gIH07XG5cbiAgdmFyIElTX0NPTkNBVF9TUFJFQURBQkxFID0gd2VsbEtub3duU3ltYm9sKCdpc0NvbmNhdFNwcmVhZGFibGUnKTtcbiAgdmFyIE1BWF9TQUZFX0lOVEVHRVIkMSA9IDB4MUZGRkZGRkZGRkZGRkY7XG4gIHZhciBNQVhJTVVNX0FMTE9XRURfSU5ERVhfRVhDRUVERUQgPSAnTWF4aW11bSBhbGxvd2VkIGluZGV4IGV4Y2VlZGVkJztcblxuICAvLyBXZSBjYW4ndCB1c2UgdGhpcyBmZWF0dXJlIGRldGVjdGlvbiBpbiBWOCBzaW5jZSBpdCBjYXVzZXNcbiAgLy8gZGVvcHRpbWl6YXRpb24gYW5kIHNlcmlvdXMgcGVyZm9ybWFuY2UgZGVncmFkYXRpb25cbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMvaXNzdWVzLzY3OVxuICB2YXIgSVNfQ09OQ0FUX1NQUkVBREFCTEVfU1VQUE9SVCA9IGVuZ2luZVY4VmVyc2lvbiA+PSA1MSB8fCAhZmFpbHMoZnVuY3Rpb24gKCkge1xuICAgIHZhciBhcnJheSA9IFtdO1xuICAgIGFycmF5W0lTX0NPTkNBVF9TUFJFQURBQkxFXSA9IGZhbHNlO1xuICAgIHJldHVybiBhcnJheS5jb25jYXQoKVswXSAhPT0gYXJyYXk7XG4gIH0pO1xuXG4gIHZhciBTUEVDSUVTX1NVUFBPUlQgPSBhcnJheU1ldGhvZEhhc1NwZWNpZXNTdXBwb3J0KCdjb25jYXQnKTtcblxuICB2YXIgaXNDb25jYXRTcHJlYWRhYmxlID0gZnVuY3Rpb24gKE8pIHtcbiAgICBpZiAoIWlzT2JqZWN0KE8pKSByZXR1cm4gZmFsc2U7XG4gICAgdmFyIHNwcmVhZGFibGUgPSBPW0lTX0NPTkNBVF9TUFJFQURBQkxFXTtcbiAgICByZXR1cm4gc3ByZWFkYWJsZSAhPT0gdW5kZWZpbmVkID8gISFzcHJlYWRhYmxlIDogaXNBcnJheShPKTtcbiAgfTtcblxuICB2YXIgRk9SQ0VEJDQgPSAhSVNfQ09OQ0FUX1NQUkVBREFCTEVfU1VQUE9SVCB8fCAhU1BFQ0lFU19TVVBQT1JUO1xuXG4gIC8vIGBBcnJheS5wcm90b3R5cGUuY29uY2F0YCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUuY29uY2F0XG4gIC8vIHdpdGggYWRkaW5nIHN1cHBvcnQgb2YgQEBpc0NvbmNhdFNwcmVhZGFibGUgYW5kIEBAc3BlY2llc1xuICBfZXhwb3J0KHsgdGFyZ2V0OiAnQXJyYXknLCBwcm90bzogdHJ1ZSwgZm9yY2VkOiBGT1JDRUQkNCB9LCB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVudXNlZC12YXJzIC0tIHJlcXVpcmVkIGZvciBgLmxlbmd0aGBcbiAgICBjb25jYXQ6IGZ1bmN0aW9uIGNvbmNhdChhcmcpIHtcbiAgICAgIHZhciBPID0gdG9PYmplY3QodGhpcyk7XG4gICAgICB2YXIgQSA9IGFycmF5U3BlY2llc0NyZWF0ZShPLCAwKTtcbiAgICAgIHZhciBuID0gMDtcbiAgICAgIHZhciBpLCBrLCBsZW5ndGgsIGxlbiwgRTtcbiAgICAgIGZvciAoaSA9IC0xLCBsZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgRSA9IGkgPT09IC0xID8gTyA6IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgaWYgKGlzQ29uY2F0U3ByZWFkYWJsZShFKSkge1xuICAgICAgICAgIGxlbiA9IHRvTGVuZ3RoKEUubGVuZ3RoKTtcbiAgICAgICAgICBpZiAobiArIGxlbiA+IE1BWF9TQUZFX0lOVEVHRVIkMSkgdGhyb3cgVHlwZUVycm9yKE1BWElNVU1fQUxMT1dFRF9JTkRFWF9FWENFRURFRCk7XG4gICAgICAgICAgZm9yIChrID0gMDsgayA8IGxlbjsgaysrLCBuKyspIGlmIChrIGluIEUpIGNyZWF0ZVByb3BlcnR5KEEsIG4sIEVba10pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmIChuID49IE1BWF9TQUZFX0lOVEVHRVIkMSkgdGhyb3cgVHlwZUVycm9yKE1BWElNVU1fQUxMT1dFRF9JTkRFWF9FWENFRURFRCk7XG4gICAgICAgICAgY3JlYXRlUHJvcGVydHkoQSwgbisrLCBFKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgQS5sZW5ndGggPSBuO1xuICAgICAgcmV0dXJuIEE7XG4gICAgfVxuICB9KTtcblxuICAvLyBvcHRpb25hbCAvIHNpbXBsZSBjb250ZXh0IGJpbmRpbmdcbiAgdmFyIGZ1bmN0aW9uQmluZENvbnRleHQgPSBmdW5jdGlvbiAoZm4sIHRoYXQsIGxlbmd0aCkge1xuICAgIGFGdW5jdGlvbihmbik7XG4gICAgaWYgKHRoYXQgPT09IHVuZGVmaW5lZCkgcmV0dXJuIGZuO1xuICAgIHN3aXRjaCAobGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6IHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBmbi5jYWxsKHRoYXQpO1xuICAgICAgfTtcbiAgICAgIGNhc2UgMTogcmV0dXJuIGZ1bmN0aW9uIChhKSB7XG4gICAgICAgIHJldHVybiBmbi5jYWxsKHRoYXQsIGEpO1xuICAgICAgfTtcbiAgICAgIGNhc2UgMjogcmV0dXJuIGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgIHJldHVybiBmbi5jYWxsKHRoYXQsIGEsIGIpO1xuICAgICAgfTtcbiAgICAgIGNhc2UgMzogcmV0dXJuIGZ1bmN0aW9uIChhLCBiLCBjKSB7XG4gICAgICAgIHJldHVybiBmbi5jYWxsKHRoYXQsIGEsIGIsIGMpO1xuICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgvKiAuLi5hcmdzICovKSB7XG4gICAgICByZXR1cm4gZm4uYXBwbHkodGhhdCwgYXJndW1lbnRzKTtcbiAgICB9O1xuICB9O1xuXG4gIHZhciBwdXNoID0gW10ucHVzaDtcblxuICAvLyBgQXJyYXkucHJvdG90eXBlLnsgZm9yRWFjaCwgbWFwLCBmaWx0ZXIsIHNvbWUsIGV2ZXJ5LCBmaW5kLCBmaW5kSW5kZXgsIGZpbHRlck91dCB9YCBtZXRob2RzIGltcGxlbWVudGF0aW9uXG4gIHZhciBjcmVhdGVNZXRob2QkMSA9IGZ1bmN0aW9uIChUWVBFKSB7XG4gICAgdmFyIElTX01BUCA9IFRZUEUgPT0gMTtcbiAgICB2YXIgSVNfRklMVEVSID0gVFlQRSA9PSAyO1xuICAgIHZhciBJU19TT01FID0gVFlQRSA9PSAzO1xuICAgIHZhciBJU19FVkVSWSA9IFRZUEUgPT0gNDtcbiAgICB2YXIgSVNfRklORF9JTkRFWCA9IFRZUEUgPT0gNjtcbiAgICB2YXIgSVNfRklMVEVSX09VVCA9IFRZUEUgPT0gNztcbiAgICB2YXIgTk9fSE9MRVMgPSBUWVBFID09IDUgfHwgSVNfRklORF9JTkRFWDtcbiAgICByZXR1cm4gZnVuY3Rpb24gKCR0aGlzLCBjYWxsYmFja2ZuLCB0aGF0LCBzcGVjaWZpY0NyZWF0ZSkge1xuICAgICAgdmFyIE8gPSB0b09iamVjdCgkdGhpcyk7XG4gICAgICB2YXIgc2VsZiA9IGluZGV4ZWRPYmplY3QoTyk7XG4gICAgICB2YXIgYm91bmRGdW5jdGlvbiA9IGZ1bmN0aW9uQmluZENvbnRleHQoY2FsbGJhY2tmbiwgdGhhdCwgMyk7XG4gICAgICB2YXIgbGVuZ3RoID0gdG9MZW5ndGgoc2VsZi5sZW5ndGgpO1xuICAgICAgdmFyIGluZGV4ID0gMDtcbiAgICAgIHZhciBjcmVhdGUgPSBzcGVjaWZpY0NyZWF0ZSB8fCBhcnJheVNwZWNpZXNDcmVhdGU7XG4gICAgICB2YXIgdGFyZ2V0ID0gSVNfTUFQID8gY3JlYXRlKCR0aGlzLCBsZW5ndGgpIDogSVNfRklMVEVSIHx8IElTX0ZJTFRFUl9PVVQgPyBjcmVhdGUoJHRoaXMsIDApIDogdW5kZWZpbmVkO1xuICAgICAgdmFyIHZhbHVlLCByZXN1bHQ7XG4gICAgICBmb3IgKDtsZW5ndGggPiBpbmRleDsgaW5kZXgrKykgaWYgKE5PX0hPTEVTIHx8IGluZGV4IGluIHNlbGYpIHtcbiAgICAgICAgdmFsdWUgPSBzZWxmW2luZGV4XTtcbiAgICAgICAgcmVzdWx0ID0gYm91bmRGdW5jdGlvbih2YWx1ZSwgaW5kZXgsIE8pO1xuICAgICAgICBpZiAoVFlQRSkge1xuICAgICAgICAgIGlmIChJU19NQVApIHRhcmdldFtpbmRleF0gPSByZXN1bHQ7IC8vIG1hcFxuICAgICAgICAgIGVsc2UgaWYgKHJlc3VsdCkgc3dpdGNoIChUWVBFKSB7XG4gICAgICAgICAgICBjYXNlIDM6IHJldHVybiB0cnVlOyAgICAgICAgICAgICAgLy8gc29tZVxuICAgICAgICAgICAgY2FzZSA1OiByZXR1cm4gdmFsdWU7ICAgICAgICAgICAgIC8vIGZpbmRcbiAgICAgICAgICAgIGNhc2UgNjogcmV0dXJuIGluZGV4OyAgICAgICAgICAgICAvLyBmaW5kSW5kZXhcbiAgICAgICAgICAgIGNhc2UgMjogcHVzaC5jYWxsKHRhcmdldCwgdmFsdWUpOyAvLyBmaWx0ZXJcbiAgICAgICAgICB9IGVsc2Ugc3dpdGNoIChUWVBFKSB7XG4gICAgICAgICAgICBjYXNlIDQ6IHJldHVybiBmYWxzZTsgICAgICAgICAgICAgLy8gZXZlcnlcbiAgICAgICAgICAgIGNhc2UgNzogcHVzaC5jYWxsKHRhcmdldCwgdmFsdWUpOyAvLyBmaWx0ZXJPdXRcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBJU19GSU5EX0lOREVYID8gLTEgOiBJU19TT01FIHx8IElTX0VWRVJZID8gSVNfRVZFUlkgOiB0YXJnZXQ7XG4gICAgfTtcbiAgfTtcblxuICB2YXIgYXJyYXlJdGVyYXRpb24gPSB7XG4gICAgLy8gYEFycmF5LnByb3RvdHlwZS5mb3JFYWNoYCBtZXRob2RcbiAgICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS5mb3JlYWNoXG4gICAgZm9yRWFjaDogY3JlYXRlTWV0aG9kJDEoMCksXG4gICAgLy8gYEFycmF5LnByb3RvdHlwZS5tYXBgIG1ldGhvZFxuICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLm1hcFxuICAgIG1hcDogY3JlYXRlTWV0aG9kJDEoMSksXG4gICAgLy8gYEFycmF5LnByb3RvdHlwZS5maWx0ZXJgIG1ldGhvZFxuICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLmZpbHRlclxuICAgIGZpbHRlcjogY3JlYXRlTWV0aG9kJDEoMiksXG4gICAgLy8gYEFycmF5LnByb3RvdHlwZS5zb21lYCBtZXRob2RcbiAgICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS5zb21lXG4gICAgc29tZTogY3JlYXRlTWV0aG9kJDEoMyksXG4gICAgLy8gYEFycmF5LnByb3RvdHlwZS5ldmVyeWAgbWV0aG9kXG4gICAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUuZXZlcnlcbiAgICBldmVyeTogY3JlYXRlTWV0aG9kJDEoNCksXG4gICAgLy8gYEFycmF5LnByb3RvdHlwZS5maW5kYCBtZXRob2RcbiAgICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS5maW5kXG4gICAgZmluZDogY3JlYXRlTWV0aG9kJDEoNSksXG4gICAgLy8gYEFycmF5LnByb3RvdHlwZS5maW5kSW5kZXhgIG1ldGhvZFxuICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLmZpbmRJbmRleFxuICAgIGZpbmRJbmRleDogY3JlYXRlTWV0aG9kJDEoNiksXG4gICAgLy8gYEFycmF5LnByb3RvdHlwZS5maWx0ZXJPdXRgIG1ldGhvZFxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS90YzM5L3Byb3Bvc2FsLWFycmF5LWZpbHRlcmluZ1xuICAgIGZpbHRlck91dDogY3JlYXRlTWV0aG9kJDEoNylcbiAgfTtcblxuICB2YXIgJGZpbmQgPSBhcnJheUl0ZXJhdGlvbi5maW5kO1xuXG5cbiAgdmFyIEZJTkQgPSAnZmluZCc7XG4gIHZhciBTS0lQU19IT0xFUyQxID0gdHJ1ZTtcblxuICAvLyBTaG91bGRuJ3Qgc2tpcCBob2xlc1xuICBpZiAoRklORCBpbiBbXSkgQXJyYXkoMSlbRklORF0oZnVuY3Rpb24gKCkgeyBTS0lQU19IT0xFUyQxID0gZmFsc2U7IH0pO1xuXG4gIC8vIGBBcnJheS5wcm90b3R5cGUuZmluZGAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLmZpbmRcbiAgX2V4cG9ydCh7IHRhcmdldDogJ0FycmF5JywgcHJvdG86IHRydWUsIGZvcmNlZDogU0tJUFNfSE9MRVMkMSB9LCB7XG4gICAgZmluZDogZnVuY3Rpb24gZmluZChjYWxsYmFja2ZuIC8qICwgdGhhdCA9IHVuZGVmaW5lZCAqLykge1xuICAgICAgcmV0dXJuICRmaW5kKHRoaXMsIGNhbGxiYWNrZm4sIGFyZ3VtZW50cy5sZW5ndGggPiAxID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkKTtcbiAgICB9XG4gIH0pO1xuXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLUBAdW5zY29wYWJsZXNcbiAgYWRkVG9VbnNjb3BhYmxlcyhGSU5EKTtcblxuICB2YXIgbm90QVJlZ2V4cCA9IGZ1bmN0aW9uIChpdCkge1xuICAgIGlmIChpc1JlZ2V4cChpdCkpIHtcbiAgICAgIHRocm93IFR5cGVFcnJvcihcIlRoZSBtZXRob2QgZG9lc24ndCBhY2NlcHQgcmVndWxhciBleHByZXNzaW9uc1wiKTtcbiAgICB9IHJldHVybiBpdDtcbiAgfTtcblxuICB2YXIgTUFUQ0gkMSA9IHdlbGxLbm93blN5bWJvbCgnbWF0Y2gnKTtcblxuICB2YXIgY29ycmVjdElzUmVnZXhwTG9naWMgPSBmdW5jdGlvbiAoTUVUSE9EX05BTUUpIHtcbiAgICB2YXIgcmVnZXhwID0gLy4vO1xuICAgIHRyeSB7XG4gICAgICAnLy4vJ1tNRVRIT0RfTkFNRV0ocmVnZXhwKTtcbiAgICB9IGNhdGNoIChlcnJvcjEpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJlZ2V4cFtNQVRDSCQxXSA9IGZhbHNlO1xuICAgICAgICByZXR1cm4gJy8uLydbTUVUSE9EX05BTUVdKHJlZ2V4cCk7XG4gICAgICB9IGNhdGNoIChlcnJvcjIpIHsgLyogZW1wdHkgKi8gfVxuICAgIH0gcmV0dXJuIGZhbHNlO1xuICB9O1xuXG4gIC8vIGBTdHJpbmcucHJvdG90eXBlLmluY2x1ZGVzYCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1zdHJpbmcucHJvdG90eXBlLmluY2x1ZGVzXG4gIF9leHBvcnQoeyB0YXJnZXQ6ICdTdHJpbmcnLCBwcm90bzogdHJ1ZSwgZm9yY2VkOiAhY29ycmVjdElzUmVnZXhwTG9naWMoJ2luY2x1ZGVzJykgfSwge1xuICAgIGluY2x1ZGVzOiBmdW5jdGlvbiBpbmNsdWRlcyhzZWFyY2hTdHJpbmcgLyogLCBwb3NpdGlvbiA9IDAgKi8pIHtcbiAgICAgIHJldHVybiAhIX5TdHJpbmcocmVxdWlyZU9iamVjdENvZXJjaWJsZSh0aGlzKSlcbiAgICAgICAgLmluZGV4T2Yobm90QVJlZ2V4cChzZWFyY2hTdHJpbmcpLCBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCk7XG4gICAgfVxuICB9KTtcblxuICAvLyBpdGVyYWJsZSBET00gY29sbGVjdGlvbnNcbiAgLy8gZmxhZyAtIGBpdGVyYWJsZWAgaW50ZXJmYWNlIC0gJ2VudHJpZXMnLCAna2V5cycsICd2YWx1ZXMnLCAnZm9yRWFjaCcgbWV0aG9kc1xuICB2YXIgZG9tSXRlcmFibGVzID0ge1xuICAgIENTU1J1bGVMaXN0OiAwLFxuICAgIENTU1N0eWxlRGVjbGFyYXRpb246IDAsXG4gICAgQ1NTVmFsdWVMaXN0OiAwLFxuICAgIENsaWVudFJlY3RMaXN0OiAwLFxuICAgIERPTVJlY3RMaXN0OiAwLFxuICAgIERPTVN0cmluZ0xpc3Q6IDAsXG4gICAgRE9NVG9rZW5MaXN0OiAxLFxuICAgIERhdGFUcmFuc2Zlckl0ZW1MaXN0OiAwLFxuICAgIEZpbGVMaXN0OiAwLFxuICAgIEhUTUxBbGxDb2xsZWN0aW9uOiAwLFxuICAgIEhUTUxDb2xsZWN0aW9uOiAwLFxuICAgIEhUTUxGb3JtRWxlbWVudDogMCxcbiAgICBIVE1MU2VsZWN0RWxlbWVudDogMCxcbiAgICBNZWRpYUxpc3Q6IDAsXG4gICAgTWltZVR5cGVBcnJheTogMCxcbiAgICBOYW1lZE5vZGVNYXA6IDAsXG4gICAgTm9kZUxpc3Q6IDEsXG4gICAgUGFpbnRSZXF1ZXN0TGlzdDogMCxcbiAgICBQbHVnaW46IDAsXG4gICAgUGx1Z2luQXJyYXk6IDAsXG4gICAgU1ZHTGVuZ3RoTGlzdDogMCxcbiAgICBTVkdOdW1iZXJMaXN0OiAwLFxuICAgIFNWR1BhdGhTZWdMaXN0OiAwLFxuICAgIFNWR1BvaW50TGlzdDogMCxcbiAgICBTVkdTdHJpbmdMaXN0OiAwLFxuICAgIFNWR1RyYW5zZm9ybUxpc3Q6IDAsXG4gICAgU291cmNlQnVmZmVyTGlzdDogMCxcbiAgICBTdHlsZVNoZWV0TGlzdDogMCxcbiAgICBUZXh0VHJhY2tDdWVMaXN0OiAwLFxuICAgIFRleHRUcmFja0xpc3Q6IDAsXG4gICAgVG91Y2hMaXN0OiAwXG4gIH07XG5cbiAgdmFyICRmb3JFYWNoID0gYXJyYXlJdGVyYXRpb24uZm9yRWFjaDtcblxuXG4gIHZhciBTVFJJQ1RfTUVUSE9EJDIgPSBhcnJheU1ldGhvZElzU3RyaWN0KCdmb3JFYWNoJyk7XG5cbiAgLy8gYEFycmF5LnByb3RvdHlwZS5mb3JFYWNoYCBtZXRob2QgaW1wbGVtZW50YXRpb25cbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUuZm9yZWFjaFxuICB2YXIgYXJyYXlGb3JFYWNoID0gIVNUUklDVF9NRVRIT0QkMiA/IGZ1bmN0aW9uIGZvckVhY2goY2FsbGJhY2tmbiAvKiAsIHRoaXNBcmcgKi8pIHtcbiAgICByZXR1cm4gJGZvckVhY2godGhpcywgY2FsbGJhY2tmbiwgYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQpO1xuICB9IDogW10uZm9yRWFjaDtcblxuICBmb3IgKHZhciBDT0xMRUNUSU9OX05BTUUkMSBpbiBkb21JdGVyYWJsZXMpIHtcbiAgICB2YXIgQ29sbGVjdGlvbiQxID0gZ2xvYmFsXzFbQ09MTEVDVElPTl9OQU1FJDFdO1xuICAgIHZhciBDb2xsZWN0aW9uUHJvdG90eXBlJDEgPSBDb2xsZWN0aW9uJDEgJiYgQ29sbGVjdGlvbiQxLnByb3RvdHlwZTtcbiAgICAvLyBzb21lIENocm9tZSB2ZXJzaW9ucyBoYXZlIG5vbi1jb25maWd1cmFibGUgbWV0aG9kcyBvbiBET01Ub2tlbkxpc3RcbiAgICBpZiAoQ29sbGVjdGlvblByb3RvdHlwZSQxICYmIENvbGxlY3Rpb25Qcm90b3R5cGUkMS5mb3JFYWNoICE9PSBhcnJheUZvckVhY2gpIHRyeSB7XG4gICAgICBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkoQ29sbGVjdGlvblByb3RvdHlwZSQxLCAnZm9yRWFjaCcsIGFycmF5Rm9yRWFjaCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIENvbGxlY3Rpb25Qcm90b3R5cGUkMS5mb3JFYWNoID0gYXJyYXlGb3JFYWNoO1xuICAgIH1cbiAgfVxuXG4gIHZhciB0cmltJDIgPSBzdHJpbmdUcmltLnRyaW07XG5cblxuICB2YXIgJHBhcnNlRmxvYXQgPSBnbG9iYWxfMS5wYXJzZUZsb2F0O1xuICB2YXIgRk9SQ0VEJDMgPSAxIC8gJHBhcnNlRmxvYXQod2hpdGVzcGFjZXMgKyAnLTAnKSAhPT0gLUluZmluaXR5O1xuXG4gIC8vIGBwYXJzZUZsb2F0YCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1wYXJzZWZsb2F0LXN0cmluZ1xuICB2YXIgbnVtYmVyUGFyc2VGbG9hdCA9IEZPUkNFRCQzID8gZnVuY3Rpb24gcGFyc2VGbG9hdChzdHJpbmcpIHtcbiAgICB2YXIgdHJpbW1lZFN0cmluZyA9IHRyaW0kMihTdHJpbmcoc3RyaW5nKSk7XG4gICAgdmFyIHJlc3VsdCA9ICRwYXJzZUZsb2F0KHRyaW1tZWRTdHJpbmcpO1xuICAgIHJldHVybiByZXN1bHQgPT09IDAgJiYgdHJpbW1lZFN0cmluZy5jaGFyQXQoMCkgPT0gJy0nID8gLTAgOiByZXN1bHQ7XG4gIH0gOiAkcGFyc2VGbG9hdDtcblxuICAvLyBgcGFyc2VGbG9hdGAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtcGFyc2VmbG9hdC1zdHJpbmdcbiAgX2V4cG9ydCh7IGdsb2JhbDogdHJ1ZSwgZm9yY2VkOiBwYXJzZUZsb2F0ICE9IG51bWJlclBhcnNlRmxvYXQgfSwge1xuICAgIHBhcnNlRmxvYXQ6IG51bWJlclBhcnNlRmxvYXRcbiAgfSk7XG5cbiAgdmFyIHByb3BlcnR5SXNFbnVtZXJhYmxlID0gb2JqZWN0UHJvcGVydHlJc0VudW1lcmFibGUuZjtcblxuICAvLyBgT2JqZWN0LnsgZW50cmllcywgdmFsdWVzIH1gIG1ldGhvZHMgaW1wbGVtZW50YXRpb25cbiAgdmFyIGNyZWF0ZU1ldGhvZCA9IGZ1bmN0aW9uIChUT19FTlRSSUVTKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChpdCkge1xuICAgICAgdmFyIE8gPSB0b0luZGV4ZWRPYmplY3QoaXQpO1xuICAgICAgdmFyIGtleXMgPSBvYmplY3RLZXlzKE8pO1xuICAgICAgdmFyIGxlbmd0aCA9IGtleXMubGVuZ3RoO1xuICAgICAgdmFyIGkgPSAwO1xuICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgdmFyIGtleTtcbiAgICAgIHdoaWxlIChsZW5ndGggPiBpKSB7XG4gICAgICAgIGtleSA9IGtleXNbaSsrXTtcbiAgICAgICAgaWYgKCFkZXNjcmlwdG9ycyB8fCBwcm9wZXJ0eUlzRW51bWVyYWJsZS5jYWxsKE8sIGtleSkpIHtcbiAgICAgICAgICByZXN1bHQucHVzaChUT19FTlRSSUVTID8gW2tleSwgT1trZXldXSA6IE9ba2V5XSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgfTtcblxuICB2YXIgb2JqZWN0VG9BcnJheSA9IHtcbiAgICAvLyBgT2JqZWN0LmVudHJpZXNgIG1ldGhvZFxuICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtb2JqZWN0LmVudHJpZXNcbiAgICBlbnRyaWVzOiBjcmVhdGVNZXRob2QodHJ1ZSksXG4gICAgLy8gYE9iamVjdC52YWx1ZXNgIG1ldGhvZFxuICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtb2JqZWN0LnZhbHVlc1xuICAgIHZhbHVlczogY3JlYXRlTWV0aG9kKGZhbHNlKVxuICB9O1xuXG4gIHZhciAkZW50cmllcyA9IG9iamVjdFRvQXJyYXkuZW50cmllcztcblxuICAvLyBgT2JqZWN0LmVudHJpZXNgIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9iamVjdC5lbnRyaWVzXG4gIF9leHBvcnQoeyB0YXJnZXQ6ICdPYmplY3QnLCBzdGF0OiB0cnVlIH0sIHtcbiAgICBlbnRyaWVzOiBmdW5jdGlvbiBlbnRyaWVzKE8pIHtcbiAgICAgIHJldHVybiAkZW50cmllcyhPKTtcbiAgICB9XG4gIH0pO1xuXG4gIHZhciAkaW5kZXhPZiA9IGFycmF5SW5jbHVkZXMuaW5kZXhPZjtcblxuXG4gIHZhciBuYXRpdmVJbmRleE9mID0gW10uaW5kZXhPZjtcblxuICB2YXIgTkVHQVRJVkVfWkVSTyA9ICEhbmF0aXZlSW5kZXhPZiAmJiAxIC8gWzFdLmluZGV4T2YoMSwgLTApIDwgMDtcbiAgdmFyIFNUUklDVF9NRVRIT0QkMSA9IGFycmF5TWV0aG9kSXNTdHJpY3QoJ2luZGV4T2YnKTtcblxuICAvLyBgQXJyYXkucHJvdG90eXBlLmluZGV4T2ZgIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS5pbmRleG9mXG4gIF9leHBvcnQoeyB0YXJnZXQ6ICdBcnJheScsIHByb3RvOiB0cnVlLCBmb3JjZWQ6IE5FR0FUSVZFX1pFUk8gfHwgIVNUUklDVF9NRVRIT0QkMSB9LCB7XG4gICAgaW5kZXhPZjogZnVuY3Rpb24gaW5kZXhPZihzZWFyY2hFbGVtZW50IC8qICwgZnJvbUluZGV4ID0gMCAqLykge1xuICAgICAgcmV0dXJuIE5FR0FUSVZFX1pFUk9cbiAgICAgICAgLy8gY29udmVydCAtMCB0byArMFxuICAgICAgICA/IG5hdGl2ZUluZGV4T2YuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCAwXG4gICAgICAgIDogJGluZGV4T2YodGhpcywgc2VhcmNoRWxlbWVudCwgYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQpO1xuICAgIH1cbiAgfSk7XG5cbiAgdmFyIHRlc3QkMiA9IFtdO1xuICB2YXIgbmF0aXZlU29ydCA9IHRlc3QkMi5zb3J0O1xuXG4gIC8vIElFOC1cbiAgdmFyIEZBSUxTX09OX1VOREVGSU5FRCA9IGZhaWxzKGZ1bmN0aW9uICgpIHtcbiAgICB0ZXN0JDIuc29ydCh1bmRlZmluZWQpO1xuICB9KTtcbiAgLy8gVjggYnVnXG4gIHZhciBGQUlMU19PTl9OVUxMID0gZmFpbHMoZnVuY3Rpb24gKCkge1xuICAgIHRlc3QkMi5zb3J0KG51bGwpO1xuICB9KTtcbiAgLy8gT2xkIFdlYktpdFxuICB2YXIgU1RSSUNUX01FVEhPRCA9IGFycmF5TWV0aG9kSXNTdHJpY3QoJ3NvcnQnKTtcblxuICB2YXIgRk9SQ0VEJDIgPSBGQUlMU19PTl9VTkRFRklORUQgfHwgIUZBSUxTX09OX05VTEwgfHwgIVNUUklDVF9NRVRIT0Q7XG5cbiAgLy8gYEFycmF5LnByb3RvdHlwZS5zb3J0YCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUuc29ydFxuICBfZXhwb3J0KHsgdGFyZ2V0OiAnQXJyYXknLCBwcm90bzogdHJ1ZSwgZm9yY2VkOiBGT1JDRUQkMiB9LCB7XG4gICAgc29ydDogZnVuY3Rpb24gc29ydChjb21wYXJlZm4pIHtcbiAgICAgIHJldHVybiBjb21wYXJlZm4gPT09IHVuZGVmaW5lZFxuICAgICAgICA/IG5hdGl2ZVNvcnQuY2FsbCh0b09iamVjdCh0aGlzKSlcbiAgICAgICAgOiBuYXRpdmVTb3J0LmNhbGwodG9PYmplY3QodGhpcyksIGFGdW5jdGlvbihjb21wYXJlZm4pKTtcbiAgICB9XG4gIH0pO1xuXG4gIHZhciBmbG9vciA9IE1hdGguZmxvb3I7XG4gIHZhciByZXBsYWNlID0gJycucmVwbGFjZTtcbiAgdmFyIFNVQlNUSVRVVElPTl9TWU1CT0xTID0gL1xcJChbJCYnYF18XFxkezEsMn18PFtePl0qPikvZztcbiAgdmFyIFNVQlNUSVRVVElPTl9TWU1CT0xTX05PX05BTUVEID0gL1xcJChbJCYnYF18XFxkezEsMn0pL2c7XG5cbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1nZXRzdWJzdGl0dXRpb25cbiAgdmFyIGdldFN1YnN0aXR1dGlvbiA9IGZ1bmN0aW9uIChtYXRjaGVkLCBzdHIsIHBvc2l0aW9uLCBjYXB0dXJlcywgbmFtZWRDYXB0dXJlcywgcmVwbGFjZW1lbnQpIHtcbiAgICB2YXIgdGFpbFBvcyA9IHBvc2l0aW9uICsgbWF0Y2hlZC5sZW5ndGg7XG4gICAgdmFyIG0gPSBjYXB0dXJlcy5sZW5ndGg7XG4gICAgdmFyIHN5bWJvbHMgPSBTVUJTVElUVVRJT05fU1lNQk9MU19OT19OQU1FRDtcbiAgICBpZiAobmFtZWRDYXB0dXJlcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBuYW1lZENhcHR1cmVzID0gdG9PYmplY3QobmFtZWRDYXB0dXJlcyk7XG4gICAgICBzeW1ib2xzID0gU1VCU1RJVFVUSU9OX1NZTUJPTFM7XG4gICAgfVxuICAgIHJldHVybiByZXBsYWNlLmNhbGwocmVwbGFjZW1lbnQsIHN5bWJvbHMsIGZ1bmN0aW9uIChtYXRjaCwgY2gpIHtcbiAgICAgIHZhciBjYXB0dXJlO1xuICAgICAgc3dpdGNoIChjaC5jaGFyQXQoMCkpIHtcbiAgICAgICAgY2FzZSAnJCc6IHJldHVybiAnJCc7XG4gICAgICAgIGNhc2UgJyYnOiByZXR1cm4gbWF0Y2hlZDtcbiAgICAgICAgY2FzZSAnYCc6IHJldHVybiBzdHIuc2xpY2UoMCwgcG9zaXRpb24pO1xuICAgICAgICBjYXNlIFwiJ1wiOiByZXR1cm4gc3RyLnNsaWNlKHRhaWxQb3MpO1xuICAgICAgICBjYXNlICc8JzpcbiAgICAgICAgICBjYXB0dXJlID0gbmFtZWRDYXB0dXJlc1tjaC5zbGljZSgxLCAtMSldO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OiAvLyBcXGRcXGQ/XG4gICAgICAgICAgdmFyIG4gPSArY2g7XG4gICAgICAgICAgaWYgKG4gPT09IDApIHJldHVybiBtYXRjaDtcbiAgICAgICAgICBpZiAobiA+IG0pIHtcbiAgICAgICAgICAgIHZhciBmID0gZmxvb3IobiAvIDEwKTtcbiAgICAgICAgICAgIGlmIChmID09PSAwKSByZXR1cm4gbWF0Y2g7XG4gICAgICAgICAgICBpZiAoZiA8PSBtKSByZXR1cm4gY2FwdHVyZXNbZiAtIDFdID09PSB1bmRlZmluZWQgPyBjaC5jaGFyQXQoMSkgOiBjYXB0dXJlc1tmIC0gMV0gKyBjaC5jaGFyQXQoMSk7XG4gICAgICAgICAgICByZXR1cm4gbWF0Y2g7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNhcHR1cmUgPSBjYXB0dXJlc1tuIC0gMV07XG4gICAgICB9XG4gICAgICByZXR1cm4gY2FwdHVyZSA9PT0gdW5kZWZpbmVkID8gJycgOiBjYXB0dXJlO1xuICAgIH0pO1xuICB9O1xuXG4gIHZhciBtYXgkMiA9IE1hdGgubWF4O1xuICB2YXIgbWluJDMgPSBNYXRoLm1pbjtcblxuICB2YXIgbWF5YmVUb1N0cmluZyA9IGZ1bmN0aW9uIChpdCkge1xuICAgIHJldHVybiBpdCA9PT0gdW5kZWZpbmVkID8gaXQgOiBTdHJpbmcoaXQpO1xuICB9O1xuXG4gIC8vIEBAcmVwbGFjZSBsb2dpY1xuICBmaXhSZWdleHBXZWxsS25vd25TeW1ib2xMb2dpYygncmVwbGFjZScsIDIsIGZ1bmN0aW9uIChSRVBMQUNFLCBuYXRpdmVSZXBsYWNlLCBtYXliZUNhbGxOYXRpdmUsIHJlYXNvbikge1xuICAgIHZhciBSRUdFWFBfUkVQTEFDRV9TVUJTVElUVVRFU19VTkRFRklORURfQ0FQVFVSRSA9IHJlYXNvbi5SRUdFWFBfUkVQTEFDRV9TVUJTVElUVVRFU19VTkRFRklORURfQ0FQVFVSRTtcbiAgICB2YXIgUkVQTEFDRV9LRUVQU18kMCA9IHJlYXNvbi5SRVBMQUNFX0tFRVBTXyQwO1xuICAgIHZhciBVTlNBRkVfU1VCU1RJVFVURSA9IFJFR0VYUF9SRVBMQUNFX1NVQlNUSVRVVEVTX1VOREVGSU5FRF9DQVBUVVJFID8gJyQnIDogJyQwJztcblxuICAgIHJldHVybiBbXG4gICAgICAvLyBgU3RyaW5nLnByb3RvdHlwZS5yZXBsYWNlYCBtZXRob2RcbiAgICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtc3RyaW5nLnByb3RvdHlwZS5yZXBsYWNlXG4gICAgICBmdW5jdGlvbiByZXBsYWNlKHNlYXJjaFZhbHVlLCByZXBsYWNlVmFsdWUpIHtcbiAgICAgICAgdmFyIE8gPSByZXF1aXJlT2JqZWN0Q29lcmNpYmxlKHRoaXMpO1xuICAgICAgICB2YXIgcmVwbGFjZXIgPSBzZWFyY2hWYWx1ZSA9PSB1bmRlZmluZWQgPyB1bmRlZmluZWQgOiBzZWFyY2hWYWx1ZVtSRVBMQUNFXTtcbiAgICAgICAgcmV0dXJuIHJlcGxhY2VyICE9PSB1bmRlZmluZWRcbiAgICAgICAgICA/IHJlcGxhY2VyLmNhbGwoc2VhcmNoVmFsdWUsIE8sIHJlcGxhY2VWYWx1ZSlcbiAgICAgICAgICA6IG5hdGl2ZVJlcGxhY2UuY2FsbChTdHJpbmcoTyksIHNlYXJjaFZhbHVlLCByZXBsYWNlVmFsdWUpO1xuICAgICAgfSxcbiAgICAgIC8vIGBSZWdFeHAucHJvdG90eXBlW0BAcmVwbGFjZV1gIG1ldGhvZFxuICAgICAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1yZWdleHAucHJvdG90eXBlLUBAcmVwbGFjZVxuICAgICAgZnVuY3Rpb24gKHJlZ2V4cCwgcmVwbGFjZVZhbHVlKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAoIVJFR0VYUF9SRVBMQUNFX1NVQlNUSVRVVEVTX1VOREVGSU5FRF9DQVBUVVJFICYmIFJFUExBQ0VfS0VFUFNfJDApIHx8XG4gICAgICAgICAgKHR5cGVvZiByZXBsYWNlVmFsdWUgPT09ICdzdHJpbmcnICYmIHJlcGxhY2VWYWx1ZS5pbmRleE9mKFVOU0FGRV9TVUJTVElUVVRFKSA9PT0gLTEpXG4gICAgICAgICkge1xuICAgICAgICAgIHZhciByZXMgPSBtYXliZUNhbGxOYXRpdmUobmF0aXZlUmVwbGFjZSwgcmVnZXhwLCB0aGlzLCByZXBsYWNlVmFsdWUpO1xuICAgICAgICAgIGlmIChyZXMuZG9uZSkgcmV0dXJuIHJlcy52YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciByeCA9IGFuT2JqZWN0KHJlZ2V4cCk7XG4gICAgICAgIHZhciBTID0gU3RyaW5nKHRoaXMpO1xuXG4gICAgICAgIHZhciBmdW5jdGlvbmFsUmVwbGFjZSA9IHR5cGVvZiByZXBsYWNlVmFsdWUgPT09ICdmdW5jdGlvbic7XG4gICAgICAgIGlmICghZnVuY3Rpb25hbFJlcGxhY2UpIHJlcGxhY2VWYWx1ZSA9IFN0cmluZyhyZXBsYWNlVmFsdWUpO1xuXG4gICAgICAgIHZhciBnbG9iYWwgPSByeC5nbG9iYWw7XG4gICAgICAgIGlmIChnbG9iYWwpIHtcbiAgICAgICAgICB2YXIgZnVsbFVuaWNvZGUgPSByeC51bmljb2RlO1xuICAgICAgICAgIHJ4Lmxhc3RJbmRleCA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlc3VsdHMgPSBbXTtcbiAgICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICB2YXIgcmVzdWx0ID0gcmVnZXhwRXhlY0Fic3RyYWN0KHJ4LCBTKTtcbiAgICAgICAgICBpZiAocmVzdWx0ID09PSBudWxsKSBicmVhaztcblxuICAgICAgICAgIHJlc3VsdHMucHVzaChyZXN1bHQpO1xuICAgICAgICAgIGlmICghZ2xvYmFsKSBicmVhaztcblxuICAgICAgICAgIHZhciBtYXRjaFN0ciA9IFN0cmluZyhyZXN1bHRbMF0pO1xuICAgICAgICAgIGlmIChtYXRjaFN0ciA9PT0gJycpIHJ4Lmxhc3RJbmRleCA9IGFkdmFuY2VTdHJpbmdJbmRleChTLCB0b0xlbmd0aChyeC5sYXN0SW5kZXgpLCBmdWxsVW5pY29kZSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgYWNjdW11bGF0ZWRSZXN1bHQgPSAnJztcbiAgICAgICAgdmFyIG5leHRTb3VyY2VQb3NpdGlvbiA9IDA7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVzdWx0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdHNbaV07XG5cbiAgICAgICAgICB2YXIgbWF0Y2hlZCA9IFN0cmluZyhyZXN1bHRbMF0pO1xuICAgICAgICAgIHZhciBwb3NpdGlvbiA9IG1heCQyKG1pbiQzKHRvSW50ZWdlcihyZXN1bHQuaW5kZXgpLCBTLmxlbmd0aCksIDApO1xuICAgICAgICAgIHZhciBjYXB0dXJlcyA9IFtdO1xuICAgICAgICAgIC8vIE5PVEU6IFRoaXMgaXMgZXF1aXZhbGVudCB0b1xuICAgICAgICAgIC8vICAgY2FwdHVyZXMgPSByZXN1bHQuc2xpY2UoMSkubWFwKG1heWJlVG9TdHJpbmcpXG4gICAgICAgICAgLy8gYnV0IGZvciBzb21lIHJlYXNvbiBgbmF0aXZlU2xpY2UuY2FsbChyZXN1bHQsIDEsIHJlc3VsdC5sZW5ndGgpYCAoY2FsbGVkIGluXG4gICAgICAgICAgLy8gdGhlIHNsaWNlIHBvbHlmaWxsIHdoZW4gc2xpY2luZyBuYXRpdmUgYXJyYXlzKSBcImRvZXNuJ3Qgd29ya1wiIGluIHNhZmFyaSA5IGFuZFxuICAgICAgICAgIC8vIGNhdXNlcyBhIGNyYXNoIChodHRwczovL3Bhc3RlYmluLmNvbS9OMjFRemVRQSkgd2hlbiB0cnlpbmcgdG8gZGVidWcgaXQuXG4gICAgICAgICAgZm9yICh2YXIgaiA9IDE7IGogPCByZXN1bHQubGVuZ3RoOyBqKyspIGNhcHR1cmVzLnB1c2gobWF5YmVUb1N0cmluZyhyZXN1bHRbal0pKTtcbiAgICAgICAgICB2YXIgbmFtZWRDYXB0dXJlcyA9IHJlc3VsdC5ncm91cHM7XG4gICAgICAgICAgaWYgKGZ1bmN0aW9uYWxSZXBsYWNlKSB7XG4gICAgICAgICAgICB2YXIgcmVwbGFjZXJBcmdzID0gW21hdGNoZWRdLmNvbmNhdChjYXB0dXJlcywgcG9zaXRpb24sIFMpO1xuICAgICAgICAgICAgaWYgKG5hbWVkQ2FwdHVyZXMgIT09IHVuZGVmaW5lZCkgcmVwbGFjZXJBcmdzLnB1c2gobmFtZWRDYXB0dXJlcyk7XG4gICAgICAgICAgICB2YXIgcmVwbGFjZW1lbnQgPSBTdHJpbmcocmVwbGFjZVZhbHVlLmFwcGx5KHVuZGVmaW5lZCwgcmVwbGFjZXJBcmdzKSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcGxhY2VtZW50ID0gZ2V0U3Vic3RpdHV0aW9uKG1hdGNoZWQsIFMsIHBvc2l0aW9uLCBjYXB0dXJlcywgbmFtZWRDYXB0dXJlcywgcmVwbGFjZVZhbHVlKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHBvc2l0aW9uID49IG5leHRTb3VyY2VQb3NpdGlvbikge1xuICAgICAgICAgICAgYWNjdW11bGF0ZWRSZXN1bHQgKz0gUy5zbGljZShuZXh0U291cmNlUG9zaXRpb24sIHBvc2l0aW9uKSArIHJlcGxhY2VtZW50O1xuICAgICAgICAgICAgbmV4dFNvdXJjZVBvc2l0aW9uID0gcG9zaXRpb24gKyBtYXRjaGVkLmxlbmd0aDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFjY3VtdWxhdGVkUmVzdWx0ICsgUy5zbGljZShuZXh0U291cmNlUG9zaXRpb24pO1xuICAgICAgfVxuICAgIF07XG4gIH0pO1xuXG4gIHZhciBuYXRpdmVBc3NpZ24gPSBPYmplY3QuYXNzaWduO1xuICB2YXIgZGVmaW5lUHJvcGVydHkkMyA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eTtcblxuICAvLyBgT2JqZWN0LmFzc2lnbmAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtb2JqZWN0LmFzc2lnblxuICB2YXIgb2JqZWN0QXNzaWduID0gIW5hdGl2ZUFzc2lnbiB8fCBmYWlscyhmdW5jdGlvbiAoKSB7XG4gICAgLy8gc2hvdWxkIGhhdmUgY29ycmVjdCBvcmRlciBvZiBvcGVyYXRpb25zIChFZGdlIGJ1ZylcbiAgICBpZiAoZGVzY3JpcHRvcnMgJiYgbmF0aXZlQXNzaWduKHsgYjogMSB9LCBuYXRpdmVBc3NpZ24oZGVmaW5lUHJvcGVydHkkMyh7fSwgJ2EnLCB7XG4gICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGRlZmluZVByb3BlcnR5JDModGhpcywgJ2InLCB7XG4gICAgICAgICAgdmFsdWU6IDMsXG4gICAgICAgICAgZW51bWVyYWJsZTogZmFsc2VcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSksIHsgYjogMiB9KSkuYiAhPT0gMSkgcmV0dXJuIHRydWU7XG4gICAgLy8gc2hvdWxkIHdvcmsgd2l0aCBzeW1ib2xzIGFuZCBzaG91bGQgaGF2ZSBkZXRlcm1pbmlzdGljIHByb3BlcnR5IG9yZGVyIChWOCBidWcpXG4gICAgdmFyIEEgPSB7fTtcbiAgICB2YXIgQiA9IHt9O1xuICAgIC8qIGdsb2JhbCBTeW1ib2wgLS0gcmVxdWlyZWQgZm9yIHRlc3RpbmcgKi9cbiAgICB2YXIgc3ltYm9sID0gU3ltYm9sKCk7XG4gICAgdmFyIGFscGhhYmV0ID0gJ2FiY2RlZmdoaWprbG1ub3BxcnN0JztcbiAgICBBW3N5bWJvbF0gPSA3O1xuICAgIGFscGhhYmV0LnNwbGl0KCcnKS5mb3JFYWNoKGZ1bmN0aW9uIChjaHIpIHsgQltjaHJdID0gY2hyOyB9KTtcbiAgICByZXR1cm4gbmF0aXZlQXNzaWduKHt9LCBBKVtzeW1ib2xdICE9IDcgfHwgb2JqZWN0S2V5cyhuYXRpdmVBc3NpZ24oe30sIEIpKS5qb2luKCcnKSAhPSBhbHBoYWJldDtcbiAgfSkgPyBmdW5jdGlvbiBhc3NpZ24odGFyZ2V0LCBzb3VyY2UpIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFycyAtLSByZXF1aXJlZCBmb3IgYC5sZW5ndGhgXG4gICAgdmFyIFQgPSB0b09iamVjdCh0YXJnZXQpO1xuICAgIHZhciBhcmd1bWVudHNMZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgIHZhciBpbmRleCA9IDE7XG4gICAgdmFyIGdldE93blByb3BlcnR5U3ltYm9scyA9IG9iamVjdEdldE93blByb3BlcnR5U3ltYm9scy5mO1xuICAgIHZhciBwcm9wZXJ0eUlzRW51bWVyYWJsZSA9IG9iamVjdFByb3BlcnR5SXNFbnVtZXJhYmxlLmY7XG4gICAgd2hpbGUgKGFyZ3VtZW50c0xlbmd0aCA+IGluZGV4KSB7XG4gICAgICB2YXIgUyA9IGluZGV4ZWRPYmplY3QoYXJndW1lbnRzW2luZGV4KytdKTtcbiAgICAgIHZhciBrZXlzID0gZ2V0T3duUHJvcGVydHlTeW1ib2xzID8gb2JqZWN0S2V5cyhTKS5jb25jYXQoZ2V0T3duUHJvcGVydHlTeW1ib2xzKFMpKSA6IG9iamVjdEtleXMoUyk7XG4gICAgICB2YXIgbGVuZ3RoID0ga2V5cy5sZW5ndGg7XG4gICAgICB2YXIgaiA9IDA7XG4gICAgICB2YXIga2V5O1xuICAgICAgd2hpbGUgKGxlbmd0aCA+IGopIHtcbiAgICAgICAga2V5ID0ga2V5c1tqKytdO1xuICAgICAgICBpZiAoIWRlc2NyaXB0b3JzIHx8IHByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwoUywga2V5KSkgVFtrZXldID0gU1trZXldO1xuICAgICAgfVxuICAgIH0gcmV0dXJuIFQ7XG4gIH0gOiBuYXRpdmVBc3NpZ247XG5cbiAgLy8gYE9iamVjdC5hc3NpZ25gIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9iamVjdC5hc3NpZ25cbiAgX2V4cG9ydCh7IHRhcmdldDogJ09iamVjdCcsIHN0YXQ6IHRydWUsIGZvcmNlZDogT2JqZWN0LmFzc2lnbiAhPT0gb2JqZWN0QXNzaWduIH0sIHtcbiAgICBhc3NpZ246IG9iamVjdEFzc2lnblxuICB9KTtcblxuICB2YXIgJGZpbHRlciA9IGFycmF5SXRlcmF0aW9uLmZpbHRlcjtcblxuXG4gIHZhciBIQVNfU1BFQ0lFU19TVVBQT1JUJDMgPSBhcnJheU1ldGhvZEhhc1NwZWNpZXNTdXBwb3J0KCdmaWx0ZXInKTtcblxuICAvLyBgQXJyYXkucHJvdG90eXBlLmZpbHRlcmAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLmZpbHRlclxuICAvLyB3aXRoIGFkZGluZyBzdXBwb3J0IG9mIEBAc3BlY2llc1xuICBfZXhwb3J0KHsgdGFyZ2V0OiAnQXJyYXknLCBwcm90bzogdHJ1ZSwgZm9yY2VkOiAhSEFTX1NQRUNJRVNfU1VQUE9SVCQzIH0sIHtcbiAgICBmaWx0ZXI6IGZ1bmN0aW9uIGZpbHRlcihjYWxsYmFja2ZuIC8qICwgdGhpc0FyZyAqLykge1xuICAgICAgcmV0dXJuICRmaWx0ZXIodGhpcywgY2FsbGJhY2tmbiwgYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQpO1xuICAgIH1cbiAgfSk7XG5cbiAgLy8gYFNhbWVWYWx1ZWAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtc2FtZXZhbHVlXG4gIHZhciBzYW1lVmFsdWUgPSBPYmplY3QuaXMgfHwgZnVuY3Rpb24gaXMoeCwgeSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1zZWxmLWNvbXBhcmUgLS0gTmFOIGNoZWNrXG4gICAgcmV0dXJuIHggPT09IHkgPyB4ICE9PSAwIHx8IDEgLyB4ID09PSAxIC8geSA6IHggIT0geCAmJiB5ICE9IHk7XG4gIH07XG5cbiAgLy8gQEBzZWFyY2ggbG9naWNcbiAgZml4UmVnZXhwV2VsbEtub3duU3ltYm9sTG9naWMoJ3NlYXJjaCcsIDEsIGZ1bmN0aW9uIChTRUFSQ0gsIG5hdGl2ZVNlYXJjaCwgbWF5YmVDYWxsTmF0aXZlKSB7XG4gICAgcmV0dXJuIFtcbiAgICAgIC8vIGBTdHJpbmcucHJvdG90eXBlLnNlYXJjaGAgbWV0aG9kXG4gICAgICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXN0cmluZy5wcm90b3R5cGUuc2VhcmNoXG4gICAgICBmdW5jdGlvbiBzZWFyY2gocmVnZXhwKSB7XG4gICAgICAgIHZhciBPID0gcmVxdWlyZU9iamVjdENvZXJjaWJsZSh0aGlzKTtcbiAgICAgICAgdmFyIHNlYXJjaGVyID0gcmVnZXhwID09IHVuZGVmaW5lZCA/IHVuZGVmaW5lZCA6IHJlZ2V4cFtTRUFSQ0hdO1xuICAgICAgICByZXR1cm4gc2VhcmNoZXIgIT09IHVuZGVmaW5lZCA/IHNlYXJjaGVyLmNhbGwocmVnZXhwLCBPKSA6IG5ldyBSZWdFeHAocmVnZXhwKVtTRUFSQ0hdKFN0cmluZyhPKSk7XG4gICAgICB9LFxuICAgICAgLy8gYFJlZ0V4cC5wcm90b3R5cGVbQEBzZWFyY2hdYCBtZXRob2RcbiAgICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtcmVnZXhwLnByb3RvdHlwZS1AQHNlYXJjaFxuICAgICAgZnVuY3Rpb24gKHJlZ2V4cCkge1xuICAgICAgICB2YXIgcmVzID0gbWF5YmVDYWxsTmF0aXZlKG5hdGl2ZVNlYXJjaCwgcmVnZXhwLCB0aGlzKTtcbiAgICAgICAgaWYgKHJlcy5kb25lKSByZXR1cm4gcmVzLnZhbHVlO1xuXG4gICAgICAgIHZhciByeCA9IGFuT2JqZWN0KHJlZ2V4cCk7XG4gICAgICAgIHZhciBTID0gU3RyaW5nKHRoaXMpO1xuXG4gICAgICAgIHZhciBwcmV2aW91c0xhc3RJbmRleCA9IHJ4Lmxhc3RJbmRleDtcbiAgICAgICAgaWYgKCFzYW1lVmFsdWUocHJldmlvdXNMYXN0SW5kZXgsIDApKSByeC5sYXN0SW5kZXggPSAwO1xuICAgICAgICB2YXIgcmVzdWx0ID0gcmVnZXhwRXhlY0Fic3RyYWN0KHJ4LCBTKTtcbiAgICAgICAgaWYgKCFzYW1lVmFsdWUocngubGFzdEluZGV4LCBwcmV2aW91c0xhc3RJbmRleCkpIHJ4Lmxhc3RJbmRleCA9IHByZXZpb3VzTGFzdEluZGV4O1xuICAgICAgICByZXR1cm4gcmVzdWx0ID09PSBudWxsID8gLTEgOiByZXN1bHQuaW5kZXg7XG4gICAgICB9XG4gICAgXTtcbiAgfSk7XG5cbiAgdmFyIHRyaW0kMSA9IHN0cmluZ1RyaW0udHJpbTtcblxuXG4gIHZhciAkcGFyc2VJbnQgPSBnbG9iYWxfMS5wYXJzZUludDtcbiAgdmFyIGhleCA9IC9eWystXT8wW1h4XS87XG4gIHZhciBGT1JDRUQkMSA9ICRwYXJzZUludCh3aGl0ZXNwYWNlcyArICcwOCcpICE9PSA4IHx8ICRwYXJzZUludCh3aGl0ZXNwYWNlcyArICcweDE2JykgIT09IDIyO1xuXG4gIC8vIGBwYXJzZUludGAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtcGFyc2VpbnQtc3RyaW5nLXJhZGl4XG4gIHZhciBudW1iZXJQYXJzZUludCA9IEZPUkNFRCQxID8gZnVuY3Rpb24gcGFyc2VJbnQoc3RyaW5nLCByYWRpeCkge1xuICAgIHZhciBTID0gdHJpbSQxKFN0cmluZyhzdHJpbmcpKTtcbiAgICByZXR1cm4gJHBhcnNlSW50KFMsIChyYWRpeCA+Pj4gMCkgfHwgKGhleC50ZXN0KFMpID8gMTYgOiAxMCkpO1xuICB9IDogJHBhcnNlSW50O1xuXG4gIC8vIGBwYXJzZUludGAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtcGFyc2VpbnQtc3RyaW5nLXJhZGl4XG4gIF9leHBvcnQoeyBnbG9iYWw6IHRydWUsIGZvcmNlZDogcGFyc2VJbnQgIT0gbnVtYmVyUGFyc2VJbnQgfSwge1xuICAgIHBhcnNlSW50OiBudW1iZXJQYXJzZUludFxuICB9KTtcblxuICB2YXIgJG1hcCA9IGFycmF5SXRlcmF0aW9uLm1hcDtcblxuXG4gIHZhciBIQVNfU1BFQ0lFU19TVVBQT1JUJDIgPSBhcnJheU1ldGhvZEhhc1NwZWNpZXNTdXBwb3J0KCdtYXAnKTtcblxuICAvLyBgQXJyYXkucHJvdG90eXBlLm1hcGAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLm1hcFxuICAvLyB3aXRoIGFkZGluZyBzdXBwb3J0IG9mIEBAc3BlY2llc1xuICBfZXhwb3J0KHsgdGFyZ2V0OiAnQXJyYXknLCBwcm90bzogdHJ1ZSwgZm9yY2VkOiAhSEFTX1NQRUNJRVNfU1VQUE9SVCQyIH0sIHtcbiAgICBtYXA6IGZ1bmN0aW9uIG1hcChjYWxsYmFja2ZuIC8qICwgdGhpc0FyZyAqLykge1xuICAgICAgcmV0dXJuICRtYXAodGhpcywgY2FsbGJhY2tmbiwgYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQpO1xuICAgIH1cbiAgfSk7XG5cbiAgdmFyICRmaW5kSW5kZXggPSBhcnJheUl0ZXJhdGlvbi5maW5kSW5kZXg7XG5cblxuICB2YXIgRklORF9JTkRFWCA9ICdmaW5kSW5kZXgnO1xuICB2YXIgU0tJUFNfSE9MRVMgPSB0cnVlO1xuXG4gIC8vIFNob3VsZG4ndCBza2lwIGhvbGVzXG4gIGlmIChGSU5EX0lOREVYIGluIFtdKSBBcnJheSgxKVtGSU5EX0lOREVYXShmdW5jdGlvbiAoKSB7IFNLSVBTX0hPTEVTID0gZmFsc2U7IH0pO1xuXG4gIC8vIGBBcnJheS5wcm90b3R5cGUuZmluZEluZGV4YCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUuZmluZGluZGV4XG4gIF9leHBvcnQoeyB0YXJnZXQ6ICdBcnJheScsIHByb3RvOiB0cnVlLCBmb3JjZWQ6IFNLSVBTX0hPTEVTIH0sIHtcbiAgICBmaW5kSW5kZXg6IGZ1bmN0aW9uIGZpbmRJbmRleChjYWxsYmFja2ZuIC8qICwgdGhhdCA9IHVuZGVmaW5lZCAqLykge1xuICAgICAgcmV0dXJuICRmaW5kSW5kZXgodGhpcywgY2FsbGJhY2tmbiwgYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQpO1xuICAgIH1cbiAgfSk7XG5cbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUtQEB1bnNjb3BhYmxlc1xuICBhZGRUb1Vuc2NvcGFibGVzKEZJTkRfSU5ERVgpO1xuXG4gIHZhciBhUG9zc2libGVQcm90b3R5cGUgPSBmdW5jdGlvbiAoaXQpIHtcbiAgICBpZiAoIWlzT2JqZWN0KGl0KSAmJiBpdCAhPT0gbnVsbCkge1xuICAgICAgdGhyb3cgVHlwZUVycm9yKFwiQ2FuJ3Qgc2V0IFwiICsgU3RyaW5nKGl0KSArICcgYXMgYSBwcm90b3R5cGUnKTtcbiAgICB9IHJldHVybiBpdDtcbiAgfTtcblxuICAvKiBlc2xpbnQtZGlzYWJsZSBuby1wcm90byAtLSBzYWZlICovXG5cblxuXG4gIC8vIGBPYmplY3Quc2V0UHJvdG90eXBlT2ZgIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9iamVjdC5zZXRwcm90b3R5cGVvZlxuICAvLyBXb3JrcyB3aXRoIF9fcHJvdG9fXyBvbmx5LiBPbGQgdjggY2FuJ3Qgd29yayB3aXRoIG51bGwgcHJvdG8gb2JqZWN0cy5cbiAgdmFyIG9iamVjdFNldFByb3RvdHlwZU9mID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8ICgnX19wcm90b19fJyBpbiB7fSA/IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgQ09SUkVDVF9TRVRURVIgPSBmYWxzZTtcbiAgICB2YXIgdGVzdCA9IHt9O1xuICAgIHZhciBzZXR0ZXI7XG4gICAgdHJ5IHtcbiAgICAgIHNldHRlciA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoT2JqZWN0LnByb3RvdHlwZSwgJ19fcHJvdG9fXycpLnNldDtcbiAgICAgIHNldHRlci5jYWxsKHRlc3QsIFtdKTtcbiAgICAgIENPUlJFQ1RfU0VUVEVSID0gdGVzdCBpbnN0YW5jZW9mIEFycmF5O1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7IC8qIGVtcHR5ICovIH1cbiAgICByZXR1cm4gZnVuY3Rpb24gc2V0UHJvdG90eXBlT2YoTywgcHJvdG8pIHtcbiAgICAgIGFuT2JqZWN0KE8pO1xuICAgICAgYVBvc3NpYmxlUHJvdG90eXBlKHByb3RvKTtcbiAgICAgIGlmIChDT1JSRUNUX1NFVFRFUikgc2V0dGVyLmNhbGwoTywgcHJvdG8pO1xuICAgICAgZWxzZSBPLl9fcHJvdG9fXyA9IHByb3RvO1xuICAgICAgcmV0dXJuIE87XG4gICAgfTtcbiAgfSgpIDogdW5kZWZpbmVkKTtcblxuICAvLyBtYWtlcyBzdWJjbGFzc2luZyB3b3JrIGNvcnJlY3QgZm9yIHdyYXBwZWQgYnVpbHQtaW5zXG4gIHZhciBpbmhlcml0SWZSZXF1aXJlZCA9IGZ1bmN0aW9uICgkdGhpcywgZHVtbXksIFdyYXBwZXIpIHtcbiAgICB2YXIgTmV3VGFyZ2V0LCBOZXdUYXJnZXRQcm90b3R5cGU7XG4gICAgaWYgKFxuICAgICAgLy8gaXQgY2FuIHdvcmsgb25seSB3aXRoIG5hdGl2ZSBgc2V0UHJvdG90eXBlT2ZgXG4gICAgICBvYmplY3RTZXRQcm90b3R5cGVPZiAmJlxuICAgICAgLy8gd2UgaGF2ZW4ndCBjb21wbGV0ZWx5IGNvcnJlY3QgcHJlLUVTNiB3YXkgZm9yIGdldHRpbmcgYG5ldy50YXJnZXRgLCBzbyB1c2UgdGhpc1xuICAgICAgdHlwZW9mIChOZXdUYXJnZXQgPSBkdW1teS5jb25zdHJ1Y3RvcikgPT0gJ2Z1bmN0aW9uJyAmJlxuICAgICAgTmV3VGFyZ2V0ICE9PSBXcmFwcGVyICYmXG4gICAgICBpc09iamVjdChOZXdUYXJnZXRQcm90b3R5cGUgPSBOZXdUYXJnZXQucHJvdG90eXBlKSAmJlxuICAgICAgTmV3VGFyZ2V0UHJvdG90eXBlICE9PSBXcmFwcGVyLnByb3RvdHlwZVxuICAgICkgb2JqZWN0U2V0UHJvdG90eXBlT2YoJHRoaXMsIE5ld1RhcmdldFByb3RvdHlwZSk7XG4gICAgcmV0dXJuICR0aGlzO1xuICB9O1xuXG4gIHZhciBTUEVDSUVTJDEgPSB3ZWxsS25vd25TeW1ib2woJ3NwZWNpZXMnKTtcblxuICB2YXIgc2V0U3BlY2llcyA9IGZ1bmN0aW9uIChDT05TVFJVQ1RPUl9OQU1FKSB7XG4gICAgdmFyIENvbnN0cnVjdG9yID0gZ2V0QnVpbHRJbihDT05TVFJVQ1RPUl9OQU1FKTtcbiAgICB2YXIgZGVmaW5lUHJvcGVydHkgPSBvYmplY3REZWZpbmVQcm9wZXJ0eS5mO1xuXG4gICAgaWYgKGRlc2NyaXB0b3JzICYmIENvbnN0cnVjdG9yICYmICFDb25zdHJ1Y3RvcltTUEVDSUVTJDFdKSB7XG4gICAgICBkZWZpbmVQcm9wZXJ0eShDb25zdHJ1Y3RvciwgU1BFQ0lFUyQxLCB7XG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9XG4gICAgICB9KTtcbiAgICB9XG4gIH07XG5cbiAgdmFyIGRlZmluZVByb3BlcnR5JDIgPSBvYmplY3REZWZpbmVQcm9wZXJ0eS5mO1xuICB2YXIgZ2V0T3duUHJvcGVydHlOYW1lcyQxID0gb2JqZWN0R2V0T3duUHJvcGVydHlOYW1lcy5mO1xuXG5cblxuXG5cbiAgdmFyIHNldEludGVybmFsU3RhdGUkMSA9IGludGVybmFsU3RhdGUuc2V0O1xuXG5cblxuICB2YXIgTUFUQ0ggPSB3ZWxsS25vd25TeW1ib2woJ21hdGNoJyk7XG4gIHZhciBOYXRpdmVSZWdFeHAgPSBnbG9iYWxfMS5SZWdFeHA7XG4gIHZhciBSZWdFeHBQcm90b3R5cGUkMSA9IE5hdGl2ZVJlZ0V4cC5wcm90b3R5cGU7XG4gIHZhciByZTEgPSAvYS9nO1xuICB2YXIgcmUyID0gL2EvZztcblxuICAvLyBcIm5ld1wiIHNob3VsZCBjcmVhdGUgYSBuZXcgb2JqZWN0LCBvbGQgd2Via2l0IGJ1Z1xuICB2YXIgQ09SUkVDVF9ORVcgPSBuZXcgTmF0aXZlUmVnRXhwKHJlMSkgIT09IHJlMTtcblxuICB2YXIgVU5TVVBQT1JURURfWSA9IHJlZ2V4cFN0aWNreUhlbHBlcnMuVU5TVVBQT1JURURfWTtcblxuICB2YXIgRk9SQ0VEID0gZGVzY3JpcHRvcnMgJiYgaXNGb3JjZWRfMSgnUmVnRXhwJywgKCFDT1JSRUNUX05FVyB8fCBVTlNVUFBPUlRFRF9ZIHx8IGZhaWxzKGZ1bmN0aW9uICgpIHtcbiAgICByZTJbTUFUQ0hdID0gZmFsc2U7XG4gICAgLy8gUmVnRXhwIGNvbnN0cnVjdG9yIGNhbiBhbHRlciBmbGFncyBhbmQgSXNSZWdFeHAgd29ya3MgY29ycmVjdCB3aXRoIEBAbWF0Y2hcbiAgICByZXR1cm4gTmF0aXZlUmVnRXhwKHJlMSkgIT0gcmUxIHx8IE5hdGl2ZVJlZ0V4cChyZTIpID09IHJlMiB8fCBOYXRpdmVSZWdFeHAocmUxLCAnaScpICE9ICcvYS9pJztcbiAgfSkpKTtcblxuICAvLyBgUmVnRXhwYCBjb25zdHJ1Y3RvclxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXJlZ2V4cC1jb25zdHJ1Y3RvclxuICBpZiAoRk9SQ0VEKSB7XG4gICAgdmFyIFJlZ0V4cFdyYXBwZXIgPSBmdW5jdGlvbiBSZWdFeHAocGF0dGVybiwgZmxhZ3MpIHtcbiAgICAgIHZhciB0aGlzSXNSZWdFeHAgPSB0aGlzIGluc3RhbmNlb2YgUmVnRXhwV3JhcHBlcjtcbiAgICAgIHZhciBwYXR0ZXJuSXNSZWdFeHAgPSBpc1JlZ2V4cChwYXR0ZXJuKTtcbiAgICAgIHZhciBmbGFnc0FyZVVuZGVmaW5lZCA9IGZsYWdzID09PSB1bmRlZmluZWQ7XG4gICAgICB2YXIgc3RpY2t5O1xuXG4gICAgICBpZiAoIXRoaXNJc1JlZ0V4cCAmJiBwYXR0ZXJuSXNSZWdFeHAgJiYgcGF0dGVybi5jb25zdHJ1Y3RvciA9PT0gUmVnRXhwV3JhcHBlciAmJiBmbGFnc0FyZVVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gcGF0dGVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKENPUlJFQ1RfTkVXKSB7XG4gICAgICAgIGlmIChwYXR0ZXJuSXNSZWdFeHAgJiYgIWZsYWdzQXJlVW5kZWZpbmVkKSBwYXR0ZXJuID0gcGF0dGVybi5zb3VyY2U7XG4gICAgICB9IGVsc2UgaWYgKHBhdHRlcm4gaW5zdGFuY2VvZiBSZWdFeHBXcmFwcGVyKSB7XG4gICAgICAgIGlmIChmbGFnc0FyZVVuZGVmaW5lZCkgZmxhZ3MgPSByZWdleHBGbGFncy5jYWxsKHBhdHRlcm4pO1xuICAgICAgICBwYXR0ZXJuID0gcGF0dGVybi5zb3VyY2U7XG4gICAgICB9XG5cbiAgICAgIGlmIChVTlNVUFBPUlRFRF9ZKSB7XG4gICAgICAgIHN0aWNreSA9ICEhZmxhZ3MgJiYgZmxhZ3MuaW5kZXhPZigneScpID4gLTE7XG4gICAgICAgIGlmIChzdGlja3kpIGZsYWdzID0gZmxhZ3MucmVwbGFjZSgveS9nLCAnJyk7XG4gICAgICB9XG5cbiAgICAgIHZhciByZXN1bHQgPSBpbmhlcml0SWZSZXF1aXJlZChcbiAgICAgICAgQ09SUkVDVF9ORVcgPyBuZXcgTmF0aXZlUmVnRXhwKHBhdHRlcm4sIGZsYWdzKSA6IE5hdGl2ZVJlZ0V4cChwYXR0ZXJuLCBmbGFncyksXG4gICAgICAgIHRoaXNJc1JlZ0V4cCA/IHRoaXMgOiBSZWdFeHBQcm90b3R5cGUkMSxcbiAgICAgICAgUmVnRXhwV3JhcHBlclxuICAgICAgKTtcblxuICAgICAgaWYgKFVOU1VQUE9SVEVEX1kgJiYgc3RpY2t5KSBzZXRJbnRlcm5hbFN0YXRlJDEocmVzdWx0LCB7IHN0aWNreTogc3RpY2t5IH0pO1xuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gICAgdmFyIHByb3h5ID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAga2V5IGluIFJlZ0V4cFdyYXBwZXIgfHwgZGVmaW5lUHJvcGVydHkkMihSZWdFeHBXcmFwcGVyLCBrZXksIHtcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIE5hdGl2ZVJlZ0V4cFtrZXldOyB9LFxuICAgICAgICBzZXQ6IGZ1bmN0aW9uIChpdCkgeyBOYXRpdmVSZWdFeHBba2V5XSA9IGl0OyB9XG4gICAgICB9KTtcbiAgICB9O1xuICAgIHZhciBrZXlzJDEgPSBnZXRPd25Qcm9wZXJ0eU5hbWVzJDEoTmF0aXZlUmVnRXhwKTtcbiAgICB2YXIgaW5kZXggPSAwO1xuICAgIHdoaWxlIChrZXlzJDEubGVuZ3RoID4gaW5kZXgpIHByb3h5KGtleXMkMVtpbmRleCsrXSk7XG4gICAgUmVnRXhwUHJvdG90eXBlJDEuY29uc3RydWN0b3IgPSBSZWdFeHBXcmFwcGVyO1xuICAgIFJlZ0V4cFdyYXBwZXIucHJvdG90eXBlID0gUmVnRXhwUHJvdG90eXBlJDE7XG4gICAgcmVkZWZpbmUoZ2xvYmFsXzEsICdSZWdFeHAnLCBSZWdFeHBXcmFwcGVyKTtcbiAgfVxuXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtZ2V0LXJlZ2V4cC1AQHNwZWNpZXNcbiAgc2V0U3BlY2llcygnUmVnRXhwJyk7XG5cbiAgdmFyIFRPX1NUUklORyA9ICd0b1N0cmluZyc7XG4gIHZhciBSZWdFeHBQcm90b3R5cGUgPSBSZWdFeHAucHJvdG90eXBlO1xuICB2YXIgbmF0aXZlVG9TdHJpbmcgPSBSZWdFeHBQcm90b3R5cGVbVE9fU1RSSU5HXTtcblxuICB2YXIgTk9UX0dFTkVSSUMgPSBmYWlscyhmdW5jdGlvbiAoKSB7IHJldHVybiBuYXRpdmVUb1N0cmluZy5jYWxsKHsgc291cmNlOiAnYScsIGZsYWdzOiAnYicgfSkgIT0gJy9hL2InOyB9KTtcbiAgLy8gRkY0NC0gUmVnRXhwI3RvU3RyaW5nIGhhcyBhIHdyb25nIG5hbWVcbiAgdmFyIElOQ09SUkVDVF9OQU1FID0gbmF0aXZlVG9TdHJpbmcubmFtZSAhPSBUT19TVFJJTkc7XG5cbiAgLy8gYFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmdgIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXJlZ2V4cC5wcm90b3R5cGUudG9zdHJpbmdcbiAgaWYgKE5PVF9HRU5FUklDIHx8IElOQ09SUkVDVF9OQU1FKSB7XG4gICAgcmVkZWZpbmUoUmVnRXhwLnByb3RvdHlwZSwgVE9fU1RSSU5HLCBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgICAgIHZhciBSID0gYW5PYmplY3QodGhpcyk7XG4gICAgICB2YXIgcCA9IFN0cmluZyhSLnNvdXJjZSk7XG4gICAgICB2YXIgcmYgPSBSLmZsYWdzO1xuICAgICAgdmFyIGYgPSBTdHJpbmcocmYgPT09IHVuZGVmaW5lZCAmJiBSIGluc3RhbmNlb2YgUmVnRXhwICYmICEoJ2ZsYWdzJyBpbiBSZWdFeHBQcm90b3R5cGUpID8gcmVnZXhwRmxhZ3MuY2FsbChSKSA6IHJmKTtcbiAgICAgIHJldHVybiAnLycgKyBwICsgJy8nICsgZjtcbiAgICB9LCB7IHVuc2FmZTogdHJ1ZSB9KTtcbiAgfVxuXG4gIHZhciBUT19TVFJJTkdfVEFHJDMgPSB3ZWxsS25vd25TeW1ib2woJ3RvU3RyaW5nVGFnJyk7XG4gIHZhciB0ZXN0JDEgPSB7fTtcblxuICB0ZXN0JDFbVE9fU1RSSU5HX1RBRyQzXSA9ICd6JztcblxuICB2YXIgdG9TdHJpbmdUYWdTdXBwb3J0ID0gU3RyaW5nKHRlc3QkMSkgPT09ICdbb2JqZWN0IHpdJztcblxuICB2YXIgVE9fU1RSSU5HX1RBRyQyID0gd2VsbEtub3duU3ltYm9sKCd0b1N0cmluZ1RhZycpO1xuICAvLyBFUzMgd3JvbmcgaGVyZVxuICB2YXIgQ09SUkVDVF9BUkdVTUVOVFMgPSBjbGFzc29mUmF3KGZ1bmN0aW9uICgpIHsgcmV0dXJuIGFyZ3VtZW50czsgfSgpKSA9PSAnQXJndW1lbnRzJztcblxuICAvLyBmYWxsYmFjayBmb3IgSUUxMSBTY3JpcHQgQWNjZXNzIERlbmllZCBlcnJvclxuICB2YXIgdHJ5R2V0ID0gZnVuY3Rpb24gKGl0LCBrZXkpIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGl0W2tleV07XG4gICAgfSBjYXRjaCAoZXJyb3IpIHsgLyogZW1wdHkgKi8gfVxuICB9O1xuXG4gIC8vIGdldHRpbmcgdGFnIGZyb20gRVM2KyBgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ2BcbiAgdmFyIGNsYXNzb2YgPSB0b1N0cmluZ1RhZ1N1cHBvcnQgPyBjbGFzc29mUmF3IDogZnVuY3Rpb24gKGl0KSB7XG4gICAgdmFyIE8sIHRhZywgcmVzdWx0O1xuICAgIHJldHVybiBpdCA9PT0gdW5kZWZpbmVkID8gJ1VuZGVmaW5lZCcgOiBpdCA9PT0gbnVsbCA/ICdOdWxsJ1xuICAgICAgLy8gQEB0b1N0cmluZ1RhZyBjYXNlXG4gICAgICA6IHR5cGVvZiAodGFnID0gdHJ5R2V0KE8gPSBPYmplY3QoaXQpLCBUT19TVFJJTkdfVEFHJDIpKSA9PSAnc3RyaW5nJyA/IHRhZ1xuICAgICAgLy8gYnVpbHRpblRhZyBjYXNlXG4gICAgICA6IENPUlJFQ1RfQVJHVU1FTlRTID8gY2xhc3NvZlJhdyhPKVxuICAgICAgLy8gRVMzIGFyZ3VtZW50cyBmYWxsYmFja1xuICAgICAgOiAocmVzdWx0ID0gY2xhc3NvZlJhdyhPKSkgPT0gJ09iamVjdCcgJiYgdHlwZW9mIE8uY2FsbGVlID09ICdmdW5jdGlvbicgPyAnQXJndW1lbnRzJyA6IHJlc3VsdDtcbiAgfTtcblxuICAvLyBgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ2AgbWV0aG9kIGltcGxlbWVudGF0aW9uXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtb2JqZWN0LnByb3RvdHlwZS50b3N0cmluZ1xuICB2YXIgb2JqZWN0VG9TdHJpbmcgPSB0b1N0cmluZ1RhZ1N1cHBvcnQgPyB7fS50b1N0cmluZyA6IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiAnW29iamVjdCAnICsgY2xhc3NvZih0aGlzKSArICddJztcbiAgfTtcblxuICAvLyBgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ2AgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtb2JqZWN0LnByb3RvdHlwZS50b3N0cmluZ1xuICBpZiAoIXRvU3RyaW5nVGFnU3VwcG9ydCkge1xuICAgIHJlZGVmaW5lKE9iamVjdC5wcm90b3R5cGUsICd0b1N0cmluZycsIG9iamVjdFRvU3RyaW5nLCB7IHVuc2FmZTogdHJ1ZSB9KTtcbiAgfVxuXG4gIHZhciBIQVNfU1BFQ0lFU19TVVBQT1JUJDEgPSBhcnJheU1ldGhvZEhhc1NwZWNpZXNTdXBwb3J0KCdzbGljZScpO1xuXG4gIHZhciBTUEVDSUVTID0gd2VsbEtub3duU3ltYm9sKCdzcGVjaWVzJyk7XG4gIHZhciBuYXRpdmVTbGljZSA9IFtdLnNsaWNlO1xuICB2YXIgbWF4JDEgPSBNYXRoLm1heDtcblxuICAvLyBgQXJyYXkucHJvdG90eXBlLnNsaWNlYCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUuc2xpY2VcbiAgLy8gZmFsbGJhY2sgZm9yIG5vdCBhcnJheS1saWtlIEVTMyBzdHJpbmdzIGFuZCBET00gb2JqZWN0c1xuICBfZXhwb3J0KHsgdGFyZ2V0OiAnQXJyYXknLCBwcm90bzogdHJ1ZSwgZm9yY2VkOiAhSEFTX1NQRUNJRVNfU1VQUE9SVCQxIH0sIHtcbiAgICBzbGljZTogZnVuY3Rpb24gc2xpY2Uoc3RhcnQsIGVuZCkge1xuICAgICAgdmFyIE8gPSB0b0luZGV4ZWRPYmplY3QodGhpcyk7XG4gICAgICB2YXIgbGVuZ3RoID0gdG9MZW5ndGgoTy5sZW5ndGgpO1xuICAgICAgdmFyIGsgPSB0b0Fic29sdXRlSW5kZXgoc3RhcnQsIGxlbmd0aCk7XG4gICAgICB2YXIgZmluID0gdG9BYnNvbHV0ZUluZGV4KGVuZCA9PT0gdW5kZWZpbmVkID8gbGVuZ3RoIDogZW5kLCBsZW5ndGgpO1xuICAgICAgLy8gaW5saW5lIGBBcnJheVNwZWNpZXNDcmVhdGVgIGZvciB1c2FnZSBuYXRpdmUgYEFycmF5I3NsaWNlYCB3aGVyZSBpdCdzIHBvc3NpYmxlXG4gICAgICB2YXIgQ29uc3RydWN0b3IsIHJlc3VsdCwgbjtcbiAgICAgIGlmIChpc0FycmF5KE8pKSB7XG4gICAgICAgIENvbnN0cnVjdG9yID0gTy5jb25zdHJ1Y3RvcjtcbiAgICAgICAgLy8gY3Jvc3MtcmVhbG0gZmFsbGJhY2tcbiAgICAgICAgaWYgKHR5cGVvZiBDb25zdHJ1Y3RvciA9PSAnZnVuY3Rpb24nICYmIChDb25zdHJ1Y3RvciA9PT0gQXJyYXkgfHwgaXNBcnJheShDb25zdHJ1Y3Rvci5wcm90b3R5cGUpKSkge1xuICAgICAgICAgIENvbnN0cnVjdG9yID0gdW5kZWZpbmVkO1xuICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KENvbnN0cnVjdG9yKSkge1xuICAgICAgICAgIENvbnN0cnVjdG9yID0gQ29uc3RydWN0b3JbU1BFQ0lFU107XG4gICAgICAgICAgaWYgKENvbnN0cnVjdG9yID09PSBudWxsKSBDb25zdHJ1Y3RvciA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoQ29uc3RydWN0b3IgPT09IEFycmF5IHx8IENvbnN0cnVjdG9yID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICByZXR1cm4gbmF0aXZlU2xpY2UuY2FsbChPLCBrLCBmaW4pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXN1bHQgPSBuZXcgKENvbnN0cnVjdG9yID09PSB1bmRlZmluZWQgPyBBcnJheSA6IENvbnN0cnVjdG9yKShtYXgkMShmaW4gLSBrLCAwKSk7XG4gICAgICBmb3IgKG4gPSAwOyBrIDwgZmluOyBrKyssIG4rKykgaWYgKGsgaW4gTykgY3JlYXRlUHJvcGVydHkocmVzdWx0LCBuLCBPW2tdKTtcbiAgICAgIHJlc3VsdC5sZW5ndGggPSBuO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH0pO1xuXG4gIHZhciBjb3JyZWN0UHJvdG90eXBlR2V0dGVyID0gIWZhaWxzKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBGKCkgeyAvKiBlbXB0eSAqLyB9XG4gICAgRi5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBudWxsO1xuICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YobmV3IEYoKSkgIT09IEYucHJvdG90eXBlO1xuICB9KTtcblxuICB2YXIgSUVfUFJPVE8gPSBzaGFyZWRLZXkoJ0lFX1BST1RPJyk7XG4gIHZhciBPYmplY3RQcm90b3R5cGUgPSBPYmplY3QucHJvdG90eXBlO1xuXG4gIC8vIGBPYmplY3QuZ2V0UHJvdG90eXBlT2ZgIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9iamVjdC5nZXRwcm90b3R5cGVvZlxuICB2YXIgb2JqZWN0R2V0UHJvdG90eXBlT2YgPSBjb3JyZWN0UHJvdG90eXBlR2V0dGVyID8gT2JqZWN0LmdldFByb3RvdHlwZU9mIDogZnVuY3Rpb24gKE8pIHtcbiAgICBPID0gdG9PYmplY3QoTyk7XG4gICAgaWYgKGhhcyQxKE8sIElFX1BST1RPKSkgcmV0dXJuIE9bSUVfUFJPVE9dO1xuICAgIGlmICh0eXBlb2YgTy5jb25zdHJ1Y3RvciA9PSAnZnVuY3Rpb24nICYmIE8gaW5zdGFuY2VvZiBPLmNvbnN0cnVjdG9yKSB7XG4gICAgICByZXR1cm4gTy5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgfSByZXR1cm4gTyBpbnN0YW5jZW9mIE9iamVjdCA/IE9iamVjdFByb3RvdHlwZSA6IG51bGw7XG4gIH07XG5cbiAgdmFyIElURVJBVE9SJDIgPSB3ZWxsS25vd25TeW1ib2woJ2l0ZXJhdG9yJyk7XG4gIHZhciBCVUdHWV9TQUZBUklfSVRFUkFUT1JTJDEgPSBmYWxzZTtcblxuICB2YXIgcmV0dXJuVGhpcyQxID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfTtcblxuICAvLyBgJUl0ZXJhdG9yUHJvdG90eXBlJWAgb2JqZWN0XG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtJWl0ZXJhdG9ycHJvdG90eXBlJS1vYmplY3RcbiAgdmFyIEl0ZXJhdG9yUHJvdG90eXBlJDIsIFByb3RvdHlwZU9mQXJyYXlJdGVyYXRvclByb3RvdHlwZSwgYXJyYXlJdGVyYXRvcjtcblxuICBpZiAoW10ua2V5cykge1xuICAgIGFycmF5SXRlcmF0b3IgPSBbXS5rZXlzKCk7XG4gICAgLy8gU2FmYXJpIDggaGFzIGJ1Z2d5IGl0ZXJhdG9ycyB3L28gYG5leHRgXG4gICAgaWYgKCEoJ25leHQnIGluIGFycmF5SXRlcmF0b3IpKSBCVUdHWV9TQUZBUklfSVRFUkFUT1JTJDEgPSB0cnVlO1xuICAgIGVsc2Uge1xuICAgICAgUHJvdG90eXBlT2ZBcnJheUl0ZXJhdG9yUHJvdG90eXBlID0gb2JqZWN0R2V0UHJvdG90eXBlT2Yob2JqZWN0R2V0UHJvdG90eXBlT2YoYXJyYXlJdGVyYXRvcikpO1xuICAgICAgaWYgKFByb3RvdHlwZU9mQXJyYXlJdGVyYXRvclByb3RvdHlwZSAhPT0gT2JqZWN0LnByb3RvdHlwZSkgSXRlcmF0b3JQcm90b3R5cGUkMiA9IFByb3RvdHlwZU9mQXJyYXlJdGVyYXRvclByb3RvdHlwZTtcbiAgICB9XG4gIH1cblxuICB2YXIgTkVXX0lURVJBVE9SX1BST1RPVFlQRSA9IEl0ZXJhdG9yUHJvdG90eXBlJDIgPT0gdW5kZWZpbmVkIHx8IGZhaWxzKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgdGVzdCA9IHt9O1xuICAgIC8vIEZGNDQtIGxlZ2FjeSBpdGVyYXRvcnMgY2FzZVxuICAgIHJldHVybiBJdGVyYXRvclByb3RvdHlwZSQyW0lURVJBVE9SJDJdLmNhbGwodGVzdCkgIT09IHRlc3Q7XG4gIH0pO1xuXG4gIGlmIChORVdfSVRFUkFUT1JfUFJPVE9UWVBFKSBJdGVyYXRvclByb3RvdHlwZSQyID0ge307XG5cbiAgLy8gMjUuMS4yLjEuMSAlSXRlcmF0b3JQcm90b3R5cGUlW0BAaXRlcmF0b3JdKClcbiAgaWYgKCFoYXMkMShJdGVyYXRvclByb3RvdHlwZSQyLCBJVEVSQVRPUiQyKSkge1xuICAgIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eShJdGVyYXRvclByb3RvdHlwZSQyLCBJVEVSQVRPUiQyLCByZXR1cm5UaGlzJDEpO1xuICB9XG5cbiAgdmFyIGl0ZXJhdG9yc0NvcmUgPSB7XG4gICAgSXRlcmF0b3JQcm90b3R5cGU6IEl0ZXJhdG9yUHJvdG90eXBlJDIsXG4gICAgQlVHR1lfU0FGQVJJX0lURVJBVE9SUzogQlVHR1lfU0FGQVJJX0lURVJBVE9SUyQxXG4gIH07XG5cbiAgdmFyIGRlZmluZVByb3BlcnR5JDEgPSBvYmplY3REZWZpbmVQcm9wZXJ0eS5mO1xuXG5cblxuICB2YXIgVE9fU1RSSU5HX1RBRyQxID0gd2VsbEtub3duU3ltYm9sKCd0b1N0cmluZ1RhZycpO1xuXG4gIHZhciBzZXRUb1N0cmluZ1RhZyA9IGZ1bmN0aW9uIChpdCwgVEFHLCBTVEFUSUMpIHtcbiAgICBpZiAoaXQgJiYgIWhhcyQxKGl0ID0gU1RBVElDID8gaXQgOiBpdC5wcm90b3R5cGUsIFRPX1NUUklOR19UQUckMSkpIHtcbiAgICAgIGRlZmluZVByb3BlcnR5JDEoaXQsIFRPX1NUUklOR19UQUckMSwgeyBjb25maWd1cmFibGU6IHRydWUsIHZhbHVlOiBUQUcgfSk7XG4gICAgfVxuICB9O1xuXG4gIHZhciBJdGVyYXRvclByb3RvdHlwZSQxID0gaXRlcmF0b3JzQ29yZS5JdGVyYXRvclByb3RvdHlwZTtcblxuICB2YXIgY3JlYXRlSXRlcmF0b3JDb25zdHJ1Y3RvciA9IGZ1bmN0aW9uIChJdGVyYXRvckNvbnN0cnVjdG9yLCBOQU1FLCBuZXh0KSB7XG4gICAgdmFyIFRPX1NUUklOR19UQUcgPSBOQU1FICsgJyBJdGVyYXRvcic7XG4gICAgSXRlcmF0b3JDb25zdHJ1Y3Rvci5wcm90b3R5cGUgPSBvYmplY3RDcmVhdGUoSXRlcmF0b3JQcm90b3R5cGUkMSwgeyBuZXh0OiBjcmVhdGVQcm9wZXJ0eURlc2NyaXB0b3IoMSwgbmV4dCkgfSk7XG4gICAgc2V0VG9TdHJpbmdUYWcoSXRlcmF0b3JDb25zdHJ1Y3RvciwgVE9fU1RSSU5HX1RBRywgZmFsc2UpO1xuICAgIHJldHVybiBJdGVyYXRvckNvbnN0cnVjdG9yO1xuICB9O1xuXG4gIHZhciBJdGVyYXRvclByb3RvdHlwZSA9IGl0ZXJhdG9yc0NvcmUuSXRlcmF0b3JQcm90b3R5cGU7XG4gIHZhciBCVUdHWV9TQUZBUklfSVRFUkFUT1JTID0gaXRlcmF0b3JzQ29yZS5CVUdHWV9TQUZBUklfSVRFUkFUT1JTO1xuICB2YXIgSVRFUkFUT1IkMSA9IHdlbGxLbm93blN5bWJvbCgnaXRlcmF0b3InKTtcbiAgdmFyIEtFWVMgPSAna2V5cyc7XG4gIHZhciBWQUxVRVMgPSAndmFsdWVzJztcbiAgdmFyIEVOVFJJRVMgPSAnZW50cmllcyc7XG5cbiAgdmFyIHJldHVyblRoaXMgPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9O1xuXG4gIHZhciBkZWZpbmVJdGVyYXRvciA9IGZ1bmN0aW9uIChJdGVyYWJsZSwgTkFNRSwgSXRlcmF0b3JDb25zdHJ1Y3RvciwgbmV4dCwgREVGQVVMVCwgSVNfU0VULCBGT1JDRUQpIHtcbiAgICBjcmVhdGVJdGVyYXRvckNvbnN0cnVjdG9yKEl0ZXJhdG9yQ29uc3RydWN0b3IsIE5BTUUsIG5leHQpO1xuXG4gICAgdmFyIGdldEl0ZXJhdGlvbk1ldGhvZCA9IGZ1bmN0aW9uIChLSU5EKSB7XG4gICAgICBpZiAoS0lORCA9PT0gREVGQVVMVCAmJiBkZWZhdWx0SXRlcmF0b3IpIHJldHVybiBkZWZhdWx0SXRlcmF0b3I7XG4gICAgICBpZiAoIUJVR0dZX1NBRkFSSV9JVEVSQVRPUlMgJiYgS0lORCBpbiBJdGVyYWJsZVByb3RvdHlwZSkgcmV0dXJuIEl0ZXJhYmxlUHJvdG90eXBlW0tJTkRdO1xuICAgICAgc3dpdGNoIChLSU5EKSB7XG4gICAgICAgIGNhc2UgS0VZUzogcmV0dXJuIGZ1bmN0aW9uIGtleXMoKSB7IHJldHVybiBuZXcgSXRlcmF0b3JDb25zdHJ1Y3Rvcih0aGlzLCBLSU5EKTsgfTtcbiAgICAgICAgY2FzZSBWQUxVRVM6IHJldHVybiBmdW5jdGlvbiB2YWx1ZXMoKSB7IHJldHVybiBuZXcgSXRlcmF0b3JDb25zdHJ1Y3Rvcih0aGlzLCBLSU5EKTsgfTtcbiAgICAgICAgY2FzZSBFTlRSSUVTOiByZXR1cm4gZnVuY3Rpb24gZW50cmllcygpIHsgcmV0dXJuIG5ldyBJdGVyYXRvckNvbnN0cnVjdG9yKHRoaXMsIEtJTkQpOyB9O1xuICAgICAgfSByZXR1cm4gZnVuY3Rpb24gKCkgeyByZXR1cm4gbmV3IEl0ZXJhdG9yQ29uc3RydWN0b3IodGhpcyk7IH07XG4gICAgfTtcblxuICAgIHZhciBUT19TVFJJTkdfVEFHID0gTkFNRSArICcgSXRlcmF0b3InO1xuICAgIHZhciBJTkNPUlJFQ1RfVkFMVUVTX05BTUUgPSBmYWxzZTtcbiAgICB2YXIgSXRlcmFibGVQcm90b3R5cGUgPSBJdGVyYWJsZS5wcm90b3R5cGU7XG4gICAgdmFyIG5hdGl2ZUl0ZXJhdG9yID0gSXRlcmFibGVQcm90b3R5cGVbSVRFUkFUT1IkMV1cbiAgICAgIHx8IEl0ZXJhYmxlUHJvdG90eXBlWydAQGl0ZXJhdG9yJ11cbiAgICAgIHx8IERFRkFVTFQgJiYgSXRlcmFibGVQcm90b3R5cGVbREVGQVVMVF07XG4gICAgdmFyIGRlZmF1bHRJdGVyYXRvciA9ICFCVUdHWV9TQUZBUklfSVRFUkFUT1JTICYmIG5hdGl2ZUl0ZXJhdG9yIHx8IGdldEl0ZXJhdGlvbk1ldGhvZChERUZBVUxUKTtcbiAgICB2YXIgYW55TmF0aXZlSXRlcmF0b3IgPSBOQU1FID09ICdBcnJheScgPyBJdGVyYWJsZVByb3RvdHlwZS5lbnRyaWVzIHx8IG5hdGl2ZUl0ZXJhdG9yIDogbmF0aXZlSXRlcmF0b3I7XG4gICAgdmFyIEN1cnJlbnRJdGVyYXRvclByb3RvdHlwZSwgbWV0aG9kcywgS0VZO1xuXG4gICAgLy8gZml4IG5hdGl2ZVxuICAgIGlmIChhbnlOYXRpdmVJdGVyYXRvcikge1xuICAgICAgQ3VycmVudEl0ZXJhdG9yUHJvdG90eXBlID0gb2JqZWN0R2V0UHJvdG90eXBlT2YoYW55TmF0aXZlSXRlcmF0b3IuY2FsbChuZXcgSXRlcmFibGUoKSkpO1xuICAgICAgaWYgKEl0ZXJhdG9yUHJvdG90eXBlICE9PSBPYmplY3QucHJvdG90eXBlICYmIEN1cnJlbnRJdGVyYXRvclByb3RvdHlwZS5uZXh0KSB7XG4gICAgICAgIGlmIChvYmplY3RHZXRQcm90b3R5cGVPZihDdXJyZW50SXRlcmF0b3JQcm90b3R5cGUpICE9PSBJdGVyYXRvclByb3RvdHlwZSkge1xuICAgICAgICAgIGlmIChvYmplY3RTZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgb2JqZWN0U2V0UHJvdG90eXBlT2YoQ3VycmVudEl0ZXJhdG9yUHJvdG90eXBlLCBJdGVyYXRvclByb3RvdHlwZSk7XG4gICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgQ3VycmVudEl0ZXJhdG9yUHJvdG90eXBlW0lURVJBVE9SJDFdICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eShDdXJyZW50SXRlcmF0b3JQcm90b3R5cGUsIElURVJBVE9SJDEsIHJldHVyblRoaXMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBTZXQgQEB0b1N0cmluZ1RhZyB0byBuYXRpdmUgaXRlcmF0b3JzXG4gICAgICAgIHNldFRvU3RyaW5nVGFnKEN1cnJlbnRJdGVyYXRvclByb3RvdHlwZSwgVE9fU1RSSU5HX1RBRywgdHJ1ZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gZml4IEFycmF5I3t2YWx1ZXMsIEBAaXRlcmF0b3J9Lm5hbWUgaW4gVjggLyBGRlxuICAgIGlmIChERUZBVUxUID09IFZBTFVFUyAmJiBuYXRpdmVJdGVyYXRvciAmJiBuYXRpdmVJdGVyYXRvci5uYW1lICE9PSBWQUxVRVMpIHtcbiAgICAgIElOQ09SUkVDVF9WQUxVRVNfTkFNRSA9IHRydWU7XG4gICAgICBkZWZhdWx0SXRlcmF0b3IgPSBmdW5jdGlvbiB2YWx1ZXMoKSB7IHJldHVybiBuYXRpdmVJdGVyYXRvci5jYWxsKHRoaXMpOyB9O1xuICAgIH1cblxuICAgIC8vIGRlZmluZSBpdGVyYXRvclxuICAgIGlmIChJdGVyYWJsZVByb3RvdHlwZVtJVEVSQVRPUiQxXSAhPT0gZGVmYXVsdEl0ZXJhdG9yKSB7XG4gICAgICBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkoSXRlcmFibGVQcm90b3R5cGUsIElURVJBVE9SJDEsIGRlZmF1bHRJdGVyYXRvcik7XG4gICAgfVxuXG4gICAgLy8gZXhwb3J0IGFkZGl0aW9uYWwgbWV0aG9kc1xuICAgIGlmIChERUZBVUxUKSB7XG4gICAgICBtZXRob2RzID0ge1xuICAgICAgICB2YWx1ZXM6IGdldEl0ZXJhdGlvbk1ldGhvZChWQUxVRVMpLFxuICAgICAgICBrZXlzOiBJU19TRVQgPyBkZWZhdWx0SXRlcmF0b3IgOiBnZXRJdGVyYXRpb25NZXRob2QoS0VZUyksXG4gICAgICAgIGVudHJpZXM6IGdldEl0ZXJhdGlvbk1ldGhvZChFTlRSSUVTKVxuICAgICAgfTtcbiAgICAgIGlmIChGT1JDRUQpIGZvciAoS0VZIGluIG1ldGhvZHMpIHtcbiAgICAgICAgaWYgKEJVR0dZX1NBRkFSSV9JVEVSQVRPUlMgfHwgSU5DT1JSRUNUX1ZBTFVFU19OQU1FIHx8ICEoS0VZIGluIEl0ZXJhYmxlUHJvdG90eXBlKSkge1xuICAgICAgICAgIHJlZGVmaW5lKEl0ZXJhYmxlUHJvdG90eXBlLCBLRVksIG1ldGhvZHNbS0VZXSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBfZXhwb3J0KHsgdGFyZ2V0OiBOQU1FLCBwcm90bzogdHJ1ZSwgZm9yY2VkOiBCVUdHWV9TQUZBUklfSVRFUkFUT1JTIHx8IElOQ09SUkVDVF9WQUxVRVNfTkFNRSB9LCBtZXRob2RzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbWV0aG9kcztcbiAgfTtcblxuICB2YXIgQVJSQVlfSVRFUkFUT1IgPSAnQXJyYXkgSXRlcmF0b3InO1xuICB2YXIgc2V0SW50ZXJuYWxTdGF0ZSA9IGludGVybmFsU3RhdGUuc2V0O1xuICB2YXIgZ2V0SW50ZXJuYWxTdGF0ZSA9IGludGVybmFsU3RhdGUuZ2V0dGVyRm9yKEFSUkFZX0lURVJBVE9SKTtcblxuICAvLyBgQXJyYXkucHJvdG90eXBlLmVudHJpZXNgIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS5lbnRyaWVzXG4gIC8vIGBBcnJheS5wcm90b3R5cGUua2V5c2AgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLmtleXNcbiAgLy8gYEFycmF5LnByb3RvdHlwZS52YWx1ZXNgIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS52YWx1ZXNcbiAgLy8gYEFycmF5LnByb3RvdHlwZVtAQGl0ZXJhdG9yXWAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLUBAaXRlcmF0b3JcbiAgLy8gYENyZWF0ZUFycmF5SXRlcmF0b3JgIGludGVybmFsIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWNyZWF0ZWFycmF5aXRlcmF0b3JcbiAgdmFyIGVzX2FycmF5X2l0ZXJhdG9yID0gZGVmaW5lSXRlcmF0b3IoQXJyYXksICdBcnJheScsIGZ1bmN0aW9uIChpdGVyYXRlZCwga2luZCkge1xuICAgIHNldEludGVybmFsU3RhdGUodGhpcywge1xuICAgICAgdHlwZTogQVJSQVlfSVRFUkFUT1IsXG4gICAgICB0YXJnZXQ6IHRvSW5kZXhlZE9iamVjdChpdGVyYXRlZCksIC8vIHRhcmdldFxuICAgICAgaW5kZXg6IDAsICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBuZXh0IGluZGV4XG4gICAgICBraW5kOiBraW5kICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGtpbmRcbiAgICB9KTtcbiAgLy8gYCVBcnJheUl0ZXJhdG9yUHJvdG90eXBlJS5uZXh0YCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy0lYXJyYXlpdGVyYXRvcnByb3RvdHlwZSUubmV4dFxuICB9LCBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHN0YXRlID0gZ2V0SW50ZXJuYWxTdGF0ZSh0aGlzKTtcbiAgICB2YXIgdGFyZ2V0ID0gc3RhdGUudGFyZ2V0O1xuICAgIHZhciBraW5kID0gc3RhdGUua2luZDtcbiAgICB2YXIgaW5kZXggPSBzdGF0ZS5pbmRleCsrO1xuICAgIGlmICghdGFyZ2V0IHx8IGluZGV4ID49IHRhcmdldC5sZW5ndGgpIHtcbiAgICAgIHN0YXRlLnRhcmdldCA9IHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiB7IHZhbHVlOiB1bmRlZmluZWQsIGRvbmU6IHRydWUgfTtcbiAgICB9XG4gICAgaWYgKGtpbmQgPT0gJ2tleXMnKSByZXR1cm4geyB2YWx1ZTogaW5kZXgsIGRvbmU6IGZhbHNlIH07XG4gICAgaWYgKGtpbmQgPT0gJ3ZhbHVlcycpIHJldHVybiB7IHZhbHVlOiB0YXJnZXRbaW5kZXhdLCBkb25lOiBmYWxzZSB9O1xuICAgIHJldHVybiB7IHZhbHVlOiBbaW5kZXgsIHRhcmdldFtpbmRleF1dLCBkb25lOiBmYWxzZSB9O1xuICB9LCAndmFsdWVzJyk7XG5cbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUtQEB1bnNjb3BhYmxlc1xuICBhZGRUb1Vuc2NvcGFibGVzKCdrZXlzJyk7XG4gIGFkZFRvVW5zY29wYWJsZXMoJ3ZhbHVlcycpO1xuICBhZGRUb1Vuc2NvcGFibGVzKCdlbnRyaWVzJyk7XG5cbiAgdmFyIElURVJBVE9SID0gd2VsbEtub3duU3ltYm9sKCdpdGVyYXRvcicpO1xuICB2YXIgVE9fU1RSSU5HX1RBRyA9IHdlbGxLbm93blN5bWJvbCgndG9TdHJpbmdUYWcnKTtcbiAgdmFyIEFycmF5VmFsdWVzID0gZXNfYXJyYXlfaXRlcmF0b3IudmFsdWVzO1xuXG4gIGZvciAodmFyIENPTExFQ1RJT05fTkFNRSBpbiBkb21JdGVyYWJsZXMpIHtcbiAgICB2YXIgQ29sbGVjdGlvbiA9IGdsb2JhbF8xW0NPTExFQ1RJT05fTkFNRV07XG4gICAgdmFyIENvbGxlY3Rpb25Qcm90b3R5cGUgPSBDb2xsZWN0aW9uICYmIENvbGxlY3Rpb24ucHJvdG90eXBlO1xuICAgIGlmIChDb2xsZWN0aW9uUHJvdG90eXBlKSB7XG4gICAgICAvLyBzb21lIENocm9tZSB2ZXJzaW9ucyBoYXZlIG5vbi1jb25maWd1cmFibGUgbWV0aG9kcyBvbiBET01Ub2tlbkxpc3RcbiAgICAgIGlmIChDb2xsZWN0aW9uUHJvdG90eXBlW0lURVJBVE9SXSAhPT0gQXJyYXlWYWx1ZXMpIHRyeSB7XG4gICAgICAgIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eShDb2xsZWN0aW9uUHJvdG90eXBlLCBJVEVSQVRPUiwgQXJyYXlWYWx1ZXMpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgQ29sbGVjdGlvblByb3RvdHlwZVtJVEVSQVRPUl0gPSBBcnJheVZhbHVlcztcbiAgICAgIH1cbiAgICAgIGlmICghQ29sbGVjdGlvblByb3RvdHlwZVtUT19TVFJJTkdfVEFHXSkge1xuICAgICAgICBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkoQ29sbGVjdGlvblByb3RvdHlwZSwgVE9fU1RSSU5HX1RBRywgQ09MTEVDVElPTl9OQU1FKTtcbiAgICAgIH1cbiAgICAgIGlmIChkb21JdGVyYWJsZXNbQ09MTEVDVElPTl9OQU1FXSkgZm9yICh2YXIgTUVUSE9EX05BTUUgaW4gZXNfYXJyYXlfaXRlcmF0b3IpIHtcbiAgICAgICAgLy8gc29tZSBDaHJvbWUgdmVyc2lvbnMgaGF2ZSBub24tY29uZmlndXJhYmxlIG1ldGhvZHMgb24gRE9NVG9rZW5MaXN0XG4gICAgICAgIGlmIChDb2xsZWN0aW9uUHJvdG90eXBlW01FVEhPRF9OQU1FXSAhPT0gZXNfYXJyYXlfaXRlcmF0b3JbTUVUSE9EX05BTUVdKSB0cnkge1xuICAgICAgICAgIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eShDb2xsZWN0aW9uUHJvdG90eXBlLCBNRVRIT0RfTkFNRSwgZXNfYXJyYXlfaXRlcmF0b3JbTUVUSE9EX05BTUVdKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBDb2xsZWN0aW9uUHJvdG90eXBlW01FVEhPRF9OQU1FXSA9IGVzX2FycmF5X2l0ZXJhdG9yW01FVEhPRF9OQU1FXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHZhciBIQVNfU1BFQ0lFU19TVVBQT1JUID0gYXJyYXlNZXRob2RIYXNTcGVjaWVzU3VwcG9ydCgnc3BsaWNlJyk7XG5cbiAgdmFyIG1heCA9IE1hdGgubWF4O1xuICB2YXIgbWluJDIgPSBNYXRoLm1pbjtcbiAgdmFyIE1BWF9TQUZFX0lOVEVHRVIgPSAweDFGRkZGRkZGRkZGRkZGO1xuICB2YXIgTUFYSU1VTV9BTExPV0VEX0xFTkdUSF9FWENFRURFRCA9ICdNYXhpbXVtIGFsbG93ZWQgbGVuZ3RoIGV4Y2VlZGVkJztcblxuICAvLyBgQXJyYXkucHJvdG90eXBlLnNwbGljZWAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLnNwbGljZVxuICAvLyB3aXRoIGFkZGluZyBzdXBwb3J0IG9mIEBAc3BlY2llc1xuICBfZXhwb3J0KHsgdGFyZ2V0OiAnQXJyYXknLCBwcm90bzogdHJ1ZSwgZm9yY2VkOiAhSEFTX1NQRUNJRVNfU1VQUE9SVCB9LCB7XG4gICAgc3BsaWNlOiBmdW5jdGlvbiBzcGxpY2Uoc3RhcnQsIGRlbGV0ZUNvdW50IC8qICwgLi4uaXRlbXMgKi8pIHtcbiAgICAgIHZhciBPID0gdG9PYmplY3QodGhpcyk7XG4gICAgICB2YXIgbGVuID0gdG9MZW5ndGgoTy5sZW5ndGgpO1xuICAgICAgdmFyIGFjdHVhbFN0YXJ0ID0gdG9BYnNvbHV0ZUluZGV4KHN0YXJ0LCBsZW4pO1xuICAgICAgdmFyIGFyZ3VtZW50c0xlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgICB2YXIgaW5zZXJ0Q291bnQsIGFjdHVhbERlbGV0ZUNvdW50LCBBLCBrLCBmcm9tLCB0bztcbiAgICAgIGlmIChhcmd1bWVudHNMZW5ndGggPT09IDApIHtcbiAgICAgICAgaW5zZXJ0Q291bnQgPSBhY3R1YWxEZWxldGVDb3VudCA9IDA7XG4gICAgICB9IGVsc2UgaWYgKGFyZ3VtZW50c0xlbmd0aCA9PT0gMSkge1xuICAgICAgICBpbnNlcnRDb3VudCA9IDA7XG4gICAgICAgIGFjdHVhbERlbGV0ZUNvdW50ID0gbGVuIC0gYWN0dWFsU3RhcnQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpbnNlcnRDb3VudCA9IGFyZ3VtZW50c0xlbmd0aCAtIDI7XG4gICAgICAgIGFjdHVhbERlbGV0ZUNvdW50ID0gbWluJDIobWF4KHRvSW50ZWdlcihkZWxldGVDb3VudCksIDApLCBsZW4gLSBhY3R1YWxTdGFydCk7XG4gICAgICB9XG4gICAgICBpZiAobGVuICsgaW5zZXJ0Q291bnQgLSBhY3R1YWxEZWxldGVDb3VudCA+IE1BWF9TQUZFX0lOVEVHRVIpIHtcbiAgICAgICAgdGhyb3cgVHlwZUVycm9yKE1BWElNVU1fQUxMT1dFRF9MRU5HVEhfRVhDRUVERUQpO1xuICAgICAgfVxuICAgICAgQSA9IGFycmF5U3BlY2llc0NyZWF0ZShPLCBhY3R1YWxEZWxldGVDb3VudCk7XG4gICAgICBmb3IgKGsgPSAwOyBrIDwgYWN0dWFsRGVsZXRlQ291bnQ7IGsrKykge1xuICAgICAgICBmcm9tID0gYWN0dWFsU3RhcnQgKyBrO1xuICAgICAgICBpZiAoZnJvbSBpbiBPKSBjcmVhdGVQcm9wZXJ0eShBLCBrLCBPW2Zyb21dKTtcbiAgICAgIH1cbiAgICAgIEEubGVuZ3RoID0gYWN0dWFsRGVsZXRlQ291bnQ7XG4gICAgICBpZiAoaW5zZXJ0Q291bnQgPCBhY3R1YWxEZWxldGVDb3VudCkge1xuICAgICAgICBmb3IgKGsgPSBhY3R1YWxTdGFydDsgayA8IGxlbiAtIGFjdHVhbERlbGV0ZUNvdW50OyBrKyspIHtcbiAgICAgICAgICBmcm9tID0gayArIGFjdHVhbERlbGV0ZUNvdW50O1xuICAgICAgICAgIHRvID0gayArIGluc2VydENvdW50O1xuICAgICAgICAgIGlmIChmcm9tIGluIE8pIE9bdG9dID0gT1tmcm9tXTtcbiAgICAgICAgICBlbHNlIGRlbGV0ZSBPW3RvXTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGsgPSBsZW47IGsgPiBsZW4gLSBhY3R1YWxEZWxldGVDb3VudCArIGluc2VydENvdW50OyBrLS0pIGRlbGV0ZSBPW2sgLSAxXTtcbiAgICAgIH0gZWxzZSBpZiAoaW5zZXJ0Q291bnQgPiBhY3R1YWxEZWxldGVDb3VudCkge1xuICAgICAgICBmb3IgKGsgPSBsZW4gLSBhY3R1YWxEZWxldGVDb3VudDsgayA+IGFjdHVhbFN0YXJ0OyBrLS0pIHtcbiAgICAgICAgICBmcm9tID0gayArIGFjdHVhbERlbGV0ZUNvdW50IC0gMTtcbiAgICAgICAgICB0byA9IGsgKyBpbnNlcnRDb3VudCAtIDE7XG4gICAgICAgICAgaWYgKGZyb20gaW4gTykgT1t0b10gPSBPW2Zyb21dO1xuICAgICAgICAgIGVsc2UgZGVsZXRlIE9bdG9dO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmb3IgKGsgPSAwOyBrIDwgaW5zZXJ0Q291bnQ7IGsrKykge1xuICAgICAgICBPW2sgKyBhY3R1YWxTdGFydF0gPSBhcmd1bWVudHNbayArIDJdO1xuICAgICAgfVxuICAgICAgTy5sZW5ndGggPSBsZW4gLSBhY3R1YWxEZWxldGVDb3VudCArIGluc2VydENvdW50O1xuICAgICAgcmV0dXJuIEE7XG4gICAgfVxuICB9KTtcblxuICB2YXIgZ2V0T3duUHJvcGVydHlOYW1lcyA9IG9iamVjdEdldE93blByb3BlcnR5TmFtZXMuZjtcbiAgdmFyIGdldE93blByb3BlcnR5RGVzY3JpcHRvciQyID0gb2JqZWN0R2V0T3duUHJvcGVydHlEZXNjcmlwdG9yLmY7XG4gIHZhciBkZWZpbmVQcm9wZXJ0eSA9IG9iamVjdERlZmluZVByb3BlcnR5LmY7XG4gIHZhciB0cmltID0gc3RyaW5nVHJpbS50cmltO1xuXG4gIHZhciBOVU1CRVIgPSAnTnVtYmVyJztcbiAgdmFyIE5hdGl2ZU51bWJlciA9IGdsb2JhbF8xW05VTUJFUl07XG4gIHZhciBOdW1iZXJQcm90b3R5cGUgPSBOYXRpdmVOdW1iZXIucHJvdG90eXBlO1xuXG4gIC8vIE9wZXJhIH4xMiBoYXMgYnJva2VuIE9iamVjdCN0b1N0cmluZ1xuICB2YXIgQlJPS0VOX0NMQVNTT0YgPSBjbGFzc29mUmF3KG9iamVjdENyZWF0ZShOdW1iZXJQcm90b3R5cGUpKSA9PSBOVU1CRVI7XG5cbiAgLy8gYFRvTnVtYmVyYCBhYnN0cmFjdCBvcGVyYXRpb25cbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy10b251bWJlclxuICB2YXIgdG9OdW1iZXIgPSBmdW5jdGlvbiAoYXJndW1lbnQpIHtcbiAgICB2YXIgaXQgPSB0b1ByaW1pdGl2ZShhcmd1bWVudCwgZmFsc2UpO1xuICAgIHZhciBmaXJzdCwgdGhpcmQsIHJhZGl4LCBtYXhDb2RlLCBkaWdpdHMsIGxlbmd0aCwgaW5kZXgsIGNvZGU7XG4gICAgaWYgKHR5cGVvZiBpdCA9PSAnc3RyaW5nJyAmJiBpdC5sZW5ndGggPiAyKSB7XG4gICAgICBpdCA9IHRyaW0oaXQpO1xuICAgICAgZmlyc3QgPSBpdC5jaGFyQ29kZUF0KDApO1xuICAgICAgaWYgKGZpcnN0ID09PSA0MyB8fCBmaXJzdCA9PT0gNDUpIHtcbiAgICAgICAgdGhpcmQgPSBpdC5jaGFyQ29kZUF0KDIpO1xuICAgICAgICBpZiAodGhpcmQgPT09IDg4IHx8IHRoaXJkID09PSAxMjApIHJldHVybiBOYU47IC8vIE51bWJlcignKzB4MScpIHNob3VsZCBiZSBOYU4sIG9sZCBWOCBmaXhcbiAgICAgIH0gZWxzZSBpZiAoZmlyc3QgPT09IDQ4KSB7XG4gICAgICAgIHN3aXRjaCAoaXQuY2hhckNvZGVBdCgxKSkge1xuICAgICAgICAgIGNhc2UgNjY6IGNhc2UgOTg6IHJhZGl4ID0gMjsgbWF4Q29kZSA9IDQ5OyBicmVhazsgLy8gZmFzdCBlcXVhbCBvZiAvXjBiWzAxXSskL2lcbiAgICAgICAgICBjYXNlIDc5OiBjYXNlIDExMTogcmFkaXggPSA4OyBtYXhDb2RlID0gNTU7IGJyZWFrOyAvLyBmYXN0IGVxdWFsIG9mIC9eMG9bMC03XSskL2lcbiAgICAgICAgICBkZWZhdWx0OiByZXR1cm4gK2l0O1xuICAgICAgICB9XG4gICAgICAgIGRpZ2l0cyA9IGl0LnNsaWNlKDIpO1xuICAgICAgICBsZW5ndGggPSBkaWdpdHMubGVuZ3RoO1xuICAgICAgICBmb3IgKGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHtcbiAgICAgICAgICBjb2RlID0gZGlnaXRzLmNoYXJDb2RlQXQoaW5kZXgpO1xuICAgICAgICAgIC8vIHBhcnNlSW50IHBhcnNlcyBhIHN0cmluZyB0byBhIGZpcnN0IHVuYXZhaWxhYmxlIHN5bWJvbFxuICAgICAgICAgIC8vIGJ1dCBUb051bWJlciBzaG91bGQgcmV0dXJuIE5hTiBpZiBhIHN0cmluZyBjb250YWlucyB1bmF2YWlsYWJsZSBzeW1ib2xzXG4gICAgICAgICAgaWYgKGNvZGUgPCA0OCB8fCBjb2RlID4gbWF4Q29kZSkgcmV0dXJuIE5hTjtcbiAgICAgICAgfSByZXR1cm4gcGFyc2VJbnQoZGlnaXRzLCByYWRpeCk7XG4gICAgICB9XG4gICAgfSByZXR1cm4gK2l0O1xuICB9O1xuXG4gIC8vIGBOdW1iZXJgIGNvbnN0cnVjdG9yXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtbnVtYmVyLWNvbnN0cnVjdG9yXG4gIGlmIChpc0ZvcmNlZF8xKE5VTUJFUiwgIU5hdGl2ZU51bWJlcignIDBvMScpIHx8ICFOYXRpdmVOdW1iZXIoJzBiMScpIHx8IE5hdGl2ZU51bWJlcignKzB4MScpKSkge1xuICAgIHZhciBOdW1iZXJXcmFwcGVyID0gZnVuY3Rpb24gTnVtYmVyKHZhbHVlKSB7XG4gICAgICB2YXIgaXQgPSBhcmd1bWVudHMubGVuZ3RoIDwgMSA/IDAgOiB2YWx1ZTtcbiAgICAgIHZhciBkdW1teSA9IHRoaXM7XG4gICAgICByZXR1cm4gZHVtbXkgaW5zdGFuY2VvZiBOdW1iZXJXcmFwcGVyXG4gICAgICAgIC8vIGNoZWNrIG9uIDEuLmNvbnN0cnVjdG9yKGZvbykgY2FzZVxuICAgICAgICAmJiAoQlJPS0VOX0NMQVNTT0YgPyBmYWlscyhmdW5jdGlvbiAoKSB7IE51bWJlclByb3RvdHlwZS52YWx1ZU9mLmNhbGwoZHVtbXkpOyB9KSA6IGNsYXNzb2ZSYXcoZHVtbXkpICE9IE5VTUJFUilcbiAgICAgICAgICA/IGluaGVyaXRJZlJlcXVpcmVkKG5ldyBOYXRpdmVOdW1iZXIodG9OdW1iZXIoaXQpKSwgZHVtbXksIE51bWJlcldyYXBwZXIpIDogdG9OdW1iZXIoaXQpO1xuICAgIH07XG4gICAgZm9yICh2YXIga2V5cyA9IGRlc2NyaXB0b3JzID8gZ2V0T3duUHJvcGVydHlOYW1lcyhOYXRpdmVOdW1iZXIpIDogKFxuICAgICAgLy8gRVMzOlxuICAgICAgJ01BWF9WQUxVRSxNSU5fVkFMVUUsTmFOLE5FR0FUSVZFX0lORklOSVRZLFBPU0lUSVZFX0lORklOSVRZLCcgK1xuICAgICAgLy8gRVMyMDE1IChpbiBjYXNlLCBpZiBtb2R1bGVzIHdpdGggRVMyMDE1IE51bWJlciBzdGF0aWNzIHJlcXVpcmVkIGJlZm9yZSk6XG4gICAgICAnRVBTSUxPTixpc0Zpbml0ZSxpc0ludGVnZXIsaXNOYU4saXNTYWZlSW50ZWdlcixNQVhfU0FGRV9JTlRFR0VSLCcgK1xuICAgICAgJ01JTl9TQUZFX0lOVEVHRVIscGFyc2VGbG9hdCxwYXJzZUludCxpc0ludGVnZXIsJyArXG4gICAgICAvLyBFU05leHRcbiAgICAgICdmcm9tU3RyaW5nLHJhbmdlJ1xuICAgICkuc3BsaXQoJywnKSwgaiA9IDAsIGtleTsga2V5cy5sZW5ndGggPiBqOyBqKyspIHtcbiAgICAgIGlmIChoYXMkMShOYXRpdmVOdW1iZXIsIGtleSA9IGtleXNbal0pICYmICFoYXMkMShOdW1iZXJXcmFwcGVyLCBrZXkpKSB7XG4gICAgICAgIGRlZmluZVByb3BlcnR5KE51bWJlcldyYXBwZXIsIGtleSwgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yJDIoTmF0aXZlTnVtYmVyLCBrZXkpKTtcbiAgICAgIH1cbiAgICB9XG4gICAgTnVtYmVyV3JhcHBlci5wcm90b3R5cGUgPSBOdW1iZXJQcm90b3R5cGU7XG4gICAgTnVtYmVyUHJvdG90eXBlLmNvbnN0cnVjdG9yID0gTnVtYmVyV3JhcHBlcjtcbiAgICByZWRlZmluZShnbG9iYWxfMSwgTlVNQkVSLCBOdW1iZXJXcmFwcGVyKTtcbiAgfVxuXG4gIHZhciBuYXRpdmVSZXZlcnNlID0gW10ucmV2ZXJzZTtcbiAgdmFyIHRlc3QgPSBbMSwgMl07XG5cbiAgLy8gYEFycmF5LnByb3RvdHlwZS5yZXZlcnNlYCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUucmV2ZXJzZVxuICAvLyBmaXggZm9yIFNhZmFyaSAxMi4wIGJ1Z1xuICAvLyBodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTg4Nzk0XG4gIF9leHBvcnQoeyB0YXJnZXQ6ICdBcnJheScsIHByb3RvOiB0cnVlLCBmb3JjZWQ6IFN0cmluZyh0ZXN0KSA9PT0gU3RyaW5nKHRlc3QucmV2ZXJzZSgpKSB9LCB7XG4gICAgcmV2ZXJzZTogZnVuY3Rpb24gcmV2ZXJzZSgpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1zZWxmLWFzc2lnbiAtLSBkaXJ0eSBoYWNrXG4gICAgICBpZiAoaXNBcnJheSh0aGlzKSkgdGhpcy5sZW5ndGggPSB0aGlzLmxlbmd0aDtcbiAgICAgIHJldHVybiBuYXRpdmVSZXZlcnNlLmNhbGwodGhpcyk7XG4gICAgfVxuICB9KTtcblxuICAvKiBlc2xpbnQtZGlzYWJsZSBuby11bnVzZWQtdmFycyAqL1xuXG4gIHZhciBWRVJTSU9OID0gJzEuMTguMyc7XG4gIHZhciBib290c3RyYXBWZXJzaW9uID0gNDtcblxuICB0cnkge1xuICAgIHZhciByYXdWZXJzaW9uID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddLmZuLmRyb3Bkb3duLkNvbnN0cnVjdG9yLlZFUlNJT047IC8vIE9ubHkgdHJ5IHRvIHBhcnNlIFZFUlNJT04gaWYgaXQgaXMgZGVmaW5lZC5cbiAgICAvLyBJdCBpcyB1bmRlZmluZWQgaW4gb2xkZXIgdmVyc2lvbnMgb2YgQm9vdHN0cmFwICh0ZXN0ZWQgd2l0aCAzLjEuMSkuXG5cbiAgICBpZiAocmF3VmVyc2lvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBib290c3RyYXBWZXJzaW9uID0gcGFyc2VJbnQocmF3VmVyc2lvbiwgMTApO1xuICAgIH1cbiAgfSBjYXRjaCAoZSkgey8vIGlnbm9yZVxuICB9XG5cbiAgdHJ5IHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW5kZWZcbiAgICB2YXIgX3Jhd1ZlcnNpb24gPSBib290c3RyYXAuVG9vbHRpcC5WRVJTSU9OO1xuXG4gICAgaWYgKF9yYXdWZXJzaW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGJvb3RzdHJhcFZlcnNpb24gPSBwYXJzZUludChfcmF3VmVyc2lvbiwgMTApO1xuICAgIH1cbiAgfSBjYXRjaCAoZSkgey8vIGlnbm9yZVxuICB9XG5cbiAgdmFyIENPTlNUQU5UUyA9IHtcbiAgICAzOiB7XG4gICAgICBpY29uc1ByZWZpeDogJ2dseXBoaWNvbicsXG4gICAgICBpY29uczoge1xuICAgICAgICBwYWdpbmF0aW9uU3dpdGNoRG93bjogJ2dseXBoaWNvbi1jb2xsYXBzZS1kb3duIGljb24tY2hldnJvbi1kb3duJyxcbiAgICAgICAgcGFnaW5hdGlvblN3aXRjaFVwOiAnZ2x5cGhpY29uLWNvbGxhcHNlLXVwIGljb24tY2hldnJvbi11cCcsXG4gICAgICAgIHJlZnJlc2g6ICdnbHlwaGljb24tcmVmcmVzaCBpY29uLXJlZnJlc2gnLFxuICAgICAgICB0b2dnbGVPZmY6ICdnbHlwaGljb24tbGlzdC1hbHQgaWNvbi1saXN0LWFsdCcsXG4gICAgICAgIHRvZ2dsZU9uOiAnZ2x5cGhpY29uLWxpc3QtYWx0IGljb24tbGlzdC1hbHQnLFxuICAgICAgICBjb2x1bW5zOiAnZ2x5cGhpY29uLXRoIGljb24tdGgnLFxuICAgICAgICBkZXRhaWxPcGVuOiAnZ2x5cGhpY29uLXBsdXMgaWNvbi1wbHVzJyxcbiAgICAgICAgZGV0YWlsQ2xvc2U6ICdnbHlwaGljb24tbWludXMgaWNvbi1taW51cycsXG4gICAgICAgIGZ1bGxzY3JlZW46ICdnbHlwaGljb24tZnVsbHNjcmVlbicsXG4gICAgICAgIHNlYXJjaDogJ2dseXBoaWNvbi1zZWFyY2gnLFxuICAgICAgICBjbGVhclNlYXJjaDogJ2dseXBoaWNvbi10cmFzaCdcbiAgICAgIH0sXG4gICAgICBjbGFzc2VzOiB7XG4gICAgICAgIGJ1dHRvbnNQcmVmaXg6ICdidG4nLFxuICAgICAgICBidXR0b25zOiAnZGVmYXVsdCcsXG4gICAgICAgIGJ1dHRvbnNHcm91cDogJ2J0bi1ncm91cCcsXG4gICAgICAgIGJ1dHRvbnNEcm9wZG93bjogJ2J0bi1ncm91cCcsXG4gICAgICAgIHB1bGw6ICdwdWxsJyxcbiAgICAgICAgaW5wdXRHcm91cDogJ2lucHV0LWdyb3VwJyxcbiAgICAgICAgaW5wdXRQcmVmaXg6ICdpbnB1dC0nLFxuICAgICAgICBpbnB1dDogJ2Zvcm0tY29udHJvbCcsXG4gICAgICAgIHBhZ2luYXRpb25Ecm9wZG93bjogJ2J0bi1ncm91cCBkcm9wZG93bicsXG4gICAgICAgIGRyb3B1cDogJ2Ryb3B1cCcsXG4gICAgICAgIGRyb3Bkb3duQWN0aXZlOiAnYWN0aXZlJyxcbiAgICAgICAgcGFnaW5hdGlvbkFjdGl2ZTogJ2FjdGl2ZScsXG4gICAgICAgIGJ1dHRvbkFjdGl2ZTogJ2FjdGl2ZSdcbiAgICAgIH0sXG4gICAgICBodG1sOiB7XG4gICAgICAgIHRvb2xiYXJEcm9wZG93bjogWyc8dWwgY2xhc3M9XCJkcm9wZG93bi1tZW51XCIgcm9sZT1cIm1lbnVcIj4nLCAnPC91bD4nXSxcbiAgICAgICAgdG9vbGJhckRyb3Bkb3duSXRlbTogJzxsaSBjbGFzcz1cImRyb3Bkb3duLWl0ZW0tbWFya2VyXCIgcm9sZT1cIm1lbnVpdGVtXCI+PGxhYmVsPiVzPC9sYWJlbD48L2xpPicsXG4gICAgICAgIHRvb2xiYXJEcm9wZG93blNlcGFyYXRvcjogJzxsaSBjbGFzcz1cImRpdmlkZXJcIj48L2xpPicsXG4gICAgICAgIHBhZ2VEcm9wZG93bjogWyc8dWwgY2xhc3M9XCJkcm9wZG93bi1tZW51XCIgcm9sZT1cIm1lbnVcIj4nLCAnPC91bD4nXSxcbiAgICAgICAgcGFnZURyb3Bkb3duSXRlbTogJzxsaSByb2xlPVwibWVudWl0ZW1cIiBjbGFzcz1cIiVzXCI+PGEgaHJlZj1cIiNcIj4lczwvYT48L2xpPicsXG4gICAgICAgIGRyb3Bkb3duQ2FyZXQ6ICc8c3BhbiBjbGFzcz1cImNhcmV0XCI+PC9zcGFuPicsXG4gICAgICAgIHBhZ2luYXRpb246IFsnPHVsIGNsYXNzPVwicGFnaW5hdGlvbiVzXCI+JywgJzwvdWw+J10sXG4gICAgICAgIHBhZ2luYXRpb25JdGVtOiAnPGxpIGNsYXNzPVwicGFnZS1pdGVtJXNcIj48YSBjbGFzcz1cInBhZ2UtbGlua1wiIGFyaWEtbGFiZWw9XCIlc1wiIGhyZWY9XCJqYXZhc2NyaXB0OnZvaWQoMClcIj4lczwvYT48L2xpPicsXG4gICAgICAgIGljb246ICc8aSBjbGFzcz1cIiVzICVzXCI+PC9pPicsXG4gICAgICAgIGlucHV0R3JvdXA6ICc8ZGl2IGNsYXNzPVwiaW5wdXQtZ3JvdXBcIj4lczxzcGFuIGNsYXNzPVwiaW5wdXQtZ3JvdXAtYnRuXCI+JXM8L3NwYW4+PC9kaXY+JyxcbiAgICAgICAgc2VhcmNoSW5wdXQ6ICc8aW5wdXQgY2xhc3M9XCIlcyVzXCIgdHlwZT1cInRleHRcIiBwbGFjZWhvbGRlcj1cIiVzXCI+JyxcbiAgICAgICAgc2VhcmNoQnV0dG9uOiAnPGJ1dHRvbiBjbGFzcz1cIiVzXCIgdHlwZT1cImJ1dHRvblwiIG5hbWU9XCJzZWFyY2hcIiB0aXRsZT1cIiVzXCI+JXMgJXM8L2J1dHRvbj4nLFxuICAgICAgICBzZWFyY2hDbGVhckJ1dHRvbjogJzxidXR0b24gY2xhc3M9XCIlc1wiIHR5cGU9XCJidXR0b25cIiBuYW1lPVwiY2xlYXJTZWFyY2hcIiB0aXRsZT1cIiVzXCI+JXMgJXM8L2J1dHRvbj4nXG4gICAgICB9XG4gICAgfSxcbiAgICA0OiB7XG4gICAgICBpY29uc1ByZWZpeDogJ2ZhJyxcbiAgICAgIGljb25zOiB7XG4gICAgICAgIHBhZ2luYXRpb25Td2l0Y2hEb3duOiAnZmEtY2FyZXQtc3F1YXJlLWRvd24nLFxuICAgICAgICBwYWdpbmF0aW9uU3dpdGNoVXA6ICdmYS1jYXJldC1zcXVhcmUtdXAnLFxuICAgICAgICByZWZyZXNoOiAnZmEtc3luYycsXG4gICAgICAgIHRvZ2dsZU9mZjogJ2ZhLXRvZ2dsZS1vZmYnLFxuICAgICAgICB0b2dnbGVPbjogJ2ZhLXRvZ2dsZS1vbicsXG4gICAgICAgIGNvbHVtbnM6ICdmYS10aC1saXN0JyxcbiAgICAgICAgZGV0YWlsT3BlbjogJ2ZhLXBsdXMnLFxuICAgICAgICBkZXRhaWxDbG9zZTogJ2ZhLW1pbnVzJyxcbiAgICAgICAgZnVsbHNjcmVlbjogJ2ZhLWFycm93cy1hbHQnLFxuICAgICAgICBzZWFyY2g6ICdmYS1zZWFyY2gnLFxuICAgICAgICBjbGVhclNlYXJjaDogJ2ZhLXRyYXNoJ1xuICAgICAgfSxcbiAgICAgIGNsYXNzZXM6IHtcbiAgICAgICAgYnV0dG9uc1ByZWZpeDogJ2J0bicsXG4gICAgICAgIGJ1dHRvbnM6ICdzZWNvbmRhcnknLFxuICAgICAgICBidXR0b25zR3JvdXA6ICdidG4tZ3JvdXAnLFxuICAgICAgICBidXR0b25zRHJvcGRvd246ICdidG4tZ3JvdXAnLFxuICAgICAgICBwdWxsOiAnZmxvYXQnLFxuICAgICAgICBpbnB1dEdyb3VwOiAnYnRuLWdyb3VwJyxcbiAgICAgICAgaW5wdXRQcmVmaXg6ICdmb3JtLWNvbnRyb2wtJyxcbiAgICAgICAgaW5wdXQ6ICdmb3JtLWNvbnRyb2wnLFxuICAgICAgICBwYWdpbmF0aW9uRHJvcGRvd246ICdidG4tZ3JvdXAgZHJvcGRvd24nLFxuICAgICAgICBkcm9wdXA6ICdkcm9wdXAnLFxuICAgICAgICBkcm9wZG93bkFjdGl2ZTogJ2FjdGl2ZScsXG4gICAgICAgIHBhZ2luYXRpb25BY3RpdmU6ICdhY3RpdmUnLFxuICAgICAgICBidXR0b25BY3RpdmU6ICdhY3RpdmUnXG4gICAgICB9LFxuICAgICAgaHRtbDoge1xuICAgICAgICB0b29sYmFyRHJvcGRvd246IFsnPGRpdiBjbGFzcz1cImRyb3Bkb3duLW1lbnUgZHJvcGRvd24tbWVudS1yaWdodFwiPicsICc8L2Rpdj4nXSxcbiAgICAgICAgdG9vbGJhckRyb3Bkb3duSXRlbTogJzxsYWJlbCBjbGFzcz1cImRyb3Bkb3duLWl0ZW0gZHJvcGRvd24taXRlbS1tYXJrZXJcIj4lczwvbGFiZWw+JyxcbiAgICAgICAgcGFnZURyb3Bkb3duOiBbJzxkaXYgY2xhc3M9XCJkcm9wZG93bi1tZW51XCI+JywgJzwvZGl2PiddLFxuICAgICAgICBwYWdlRHJvcGRvd25JdGVtOiAnPGEgY2xhc3M9XCJkcm9wZG93bi1pdGVtICVzXCIgaHJlZj1cIiNcIj4lczwvYT4nLFxuICAgICAgICB0b29sYmFyRHJvcGRvd25TZXBhcmF0b3I6ICc8ZGl2IGNsYXNzPVwiZHJvcGRvd24tZGl2aWRlclwiPjwvZGl2PicsXG4gICAgICAgIGRyb3Bkb3duQ2FyZXQ6ICc8c3BhbiBjbGFzcz1cImNhcmV0XCI+PC9zcGFuPicsXG4gICAgICAgIHBhZ2luYXRpb246IFsnPHVsIGNsYXNzPVwicGFnaW5hdGlvbiVzXCI+JywgJzwvdWw+J10sXG4gICAgICAgIHBhZ2luYXRpb25JdGVtOiAnPGxpIGNsYXNzPVwicGFnZS1pdGVtJXNcIj48YSBjbGFzcz1cInBhZ2UtbGlua1wiIGFyaWEtbGFiZWw9XCIlc1wiIGhyZWY9XCJqYXZhc2NyaXB0OnZvaWQoMClcIj4lczwvYT48L2xpPicsXG4gICAgICAgIGljb246ICc8aSBjbGFzcz1cIiVzICVzXCI+PC9pPicsXG4gICAgICAgIGlucHV0R3JvdXA6ICc8ZGl2IGNsYXNzPVwiaW5wdXQtZ3JvdXBcIj4lczxkaXYgY2xhc3M9XCJpbnB1dC1ncm91cC1hcHBlbmRcIj4lczwvZGl2PjwvZGl2PicsXG4gICAgICAgIHNlYXJjaElucHV0OiAnPGlucHV0IGNsYXNzPVwiJXMlc1wiIHR5cGU9XCJ0ZXh0XCIgcGxhY2Vob2xkZXI9XCIlc1wiPicsXG4gICAgICAgIHNlYXJjaEJ1dHRvbjogJzxidXR0b24gY2xhc3M9XCIlc1wiIHR5cGU9XCJidXR0b25cIiBuYW1lPVwic2VhcmNoXCIgdGl0bGU9XCIlc1wiPiVzICVzPC9idXR0b24+JyxcbiAgICAgICAgc2VhcmNoQ2xlYXJCdXR0b246ICc8YnV0dG9uIGNsYXNzPVwiJXNcIiB0eXBlPVwiYnV0dG9uXCIgbmFtZT1cImNsZWFyU2VhcmNoXCIgdGl0bGU9XCIlc1wiPiVzICVzPC9idXR0b24+J1xuICAgICAgfVxuICAgIH0sXG4gICAgNToge1xuICAgICAgaWNvbnNQcmVmaXg6ICdmYScsXG4gICAgICBpY29uczoge1xuICAgICAgICBwYWdpbmF0aW9uU3dpdGNoRG93bjogJ2ZhLWNhcmV0LXNxdWFyZS1kb3duJyxcbiAgICAgICAgcGFnaW5hdGlvblN3aXRjaFVwOiAnZmEtY2FyZXQtc3F1YXJlLXVwJyxcbiAgICAgICAgcmVmcmVzaDogJ2ZhLXN5bmMnLFxuICAgICAgICB0b2dnbGVPZmY6ICdmYS10b2dnbGUtb2ZmJyxcbiAgICAgICAgdG9nZ2xlT246ICdmYS10b2dnbGUtb24nLFxuICAgICAgICBjb2x1bW5zOiAnZmEtdGgtbGlzdCcsXG4gICAgICAgIGRldGFpbE9wZW46ICdmYS1wbHVzJyxcbiAgICAgICAgZGV0YWlsQ2xvc2U6ICdmYS1taW51cycsXG4gICAgICAgIGZ1bGxzY3JlZW46ICdmYS1hcnJvd3MtYWx0JyxcbiAgICAgICAgc2VhcmNoOiAnZmEtc2VhcmNoJyxcbiAgICAgICAgY2xlYXJTZWFyY2g6ICdmYS10cmFzaCdcbiAgICAgIH0sXG4gICAgICBjbGFzc2VzOiB7XG4gICAgICAgIGJ1dHRvbnNQcmVmaXg6ICdidG4nLFxuICAgICAgICBidXR0b25zOiAnc2Vjb25kYXJ5JyxcbiAgICAgICAgYnV0dG9uc0dyb3VwOiAnYnRuLWdyb3VwJyxcbiAgICAgICAgYnV0dG9uc0Ryb3Bkb3duOiAnYnRuLWdyb3VwJyxcbiAgICAgICAgcHVsbDogJ2Zsb2F0JyxcbiAgICAgICAgaW5wdXRHcm91cDogJ2J0bi1ncm91cCcsXG4gICAgICAgIGlucHV0UHJlZml4OiAnZm9ybS1jb250cm9sLScsXG4gICAgICAgIGlucHV0OiAnZm9ybS1jb250cm9sJyxcbiAgICAgICAgcGFnaW5hdGlvbkRyb3Bkb3duOiAnYnRuLWdyb3VwIGRyb3Bkb3duJyxcbiAgICAgICAgZHJvcHVwOiAnZHJvcHVwJyxcbiAgICAgICAgZHJvcGRvd25BY3RpdmU6ICdhY3RpdmUnLFxuICAgICAgICBwYWdpbmF0aW9uQWN0aXZlOiAnYWN0aXZlJyxcbiAgICAgICAgYnV0dG9uQWN0aXZlOiAnYWN0aXZlJ1xuICAgICAgfSxcbiAgICAgIGh0bWw6IHtcbiAgICAgICAgZGF0YVRvZ2dsZTogJ2RhdGEtYnMtdG9nZ2xlJyxcbiAgICAgICAgdG9vbGJhckRyb3Bkb3duOiBbJzxkaXYgY2xhc3M9XCJkcm9wZG93bi1tZW51IGRyb3Bkb3duLW1lbnUtcmlnaHRcIj4nLCAnPC9kaXY+J10sXG4gICAgICAgIHRvb2xiYXJEcm9wZG93bkl0ZW06ICc8bGFiZWwgY2xhc3M9XCJkcm9wZG93bi1pdGVtIGRyb3Bkb3duLWl0ZW0tbWFya2VyXCI+JXM8L2xhYmVsPicsXG4gICAgICAgIHBhZ2VEcm9wZG93bjogWyc8ZGl2IGNsYXNzPVwiZHJvcGRvd24tbWVudVwiPicsICc8L2Rpdj4nXSxcbiAgICAgICAgcGFnZURyb3Bkb3duSXRlbTogJzxhIGNsYXNzPVwiZHJvcGRvd24taXRlbSAlc1wiIGhyZWY9XCIjXCI+JXM8L2E+JyxcbiAgICAgICAgdG9vbGJhckRyb3Bkb3duU2VwYXJhdG9yOiAnPGRpdiBjbGFzcz1cImRyb3Bkb3duLWRpdmlkZXJcIj48L2Rpdj4nLFxuICAgICAgICBkcm9wZG93bkNhcmV0OiAnPHNwYW4gY2xhc3M9XCJjYXJldFwiPjwvc3Bhbj4nLFxuICAgICAgICBwYWdpbmF0aW9uOiBbJzx1bCBjbGFzcz1cInBhZ2luYXRpb24lc1wiPicsICc8L3VsPiddLFxuICAgICAgICBwYWdpbmF0aW9uSXRlbTogJzxsaSBjbGFzcz1cInBhZ2UtaXRlbSVzXCI+PGEgY2xhc3M9XCJwYWdlLWxpbmtcIiBhcmlhLWxhYmVsPVwiJXNcIiBocmVmPVwiamF2YXNjcmlwdDp2b2lkKDApXCI+JXM8L2E+PC9saT4nLFxuICAgICAgICBpY29uOiAnPGkgY2xhc3M9XCIlcyAlc1wiPjwvaT4nLFxuICAgICAgICBpbnB1dEdyb3VwOiAnPGRpdiBjbGFzcz1cImlucHV0LWdyb3VwXCI+JXM8ZGl2IGNsYXNzPVwiaW5wdXQtZ3JvdXAtYXBwZW5kXCI+JXM8L2Rpdj48L2Rpdj4nLFxuICAgICAgICBzZWFyY2hJbnB1dDogJzxpbnB1dCBjbGFzcz1cIiVzJXNcIiB0eXBlPVwidGV4dFwiIHBsYWNlaG9sZGVyPVwiJXNcIj4nLFxuICAgICAgICBzZWFyY2hCdXR0b246ICc8YnV0dG9uIGNsYXNzPVwiJXNcIiB0eXBlPVwiYnV0dG9uXCIgbmFtZT1cInNlYXJjaFwiIHRpdGxlPVwiJXNcIj4lcyAlczwvYnV0dG9uPicsXG4gICAgICAgIHNlYXJjaENsZWFyQnV0dG9uOiAnPGJ1dHRvbiBjbGFzcz1cIiVzXCIgdHlwZT1cImJ1dHRvblwiIG5hbWU9XCJjbGVhclNlYXJjaFwiIHRpdGxlPVwiJXNcIj4lcyAlczwvYnV0dG9uPidcbiAgICAgIH1cbiAgICB9XG4gIH1bYm9vdHN0cmFwVmVyc2lvbl07XG4gIHZhciBERUZBVUxUUyA9IHtcbiAgICBoZWlnaHQ6IHVuZGVmaW5lZCxcbiAgICBjbGFzc2VzOiAndGFibGUgdGFibGUtYm9yZGVyZWQgdGFibGUtaG92ZXInLFxuICAgIGJ1dHRvbnM6IHt9LFxuICAgIHRoZWFkQ2xhc3NlczogJycsXG4gICAgaGVhZGVyU3R5bGU6IGZ1bmN0aW9uIGhlYWRlclN0eWxlKGNvbHVtbikge1xuICAgICAgcmV0dXJuIHt9O1xuICAgIH0sXG4gICAgcm93U3R5bGU6IGZ1bmN0aW9uIHJvd1N0eWxlKHJvdywgaW5kZXgpIHtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9LFxuICAgIHJvd0F0dHJpYnV0ZXM6IGZ1bmN0aW9uIHJvd0F0dHJpYnV0ZXMocm93LCBpbmRleCkge1xuICAgICAgcmV0dXJuIHt9O1xuICAgIH0sXG4gICAgdW5kZWZpbmVkVGV4dDogJy0nLFxuICAgIGxvY2FsZTogdW5kZWZpbmVkLFxuICAgIHZpcnR1YWxTY3JvbGw6IGZhbHNlLFxuICAgIHZpcnR1YWxTY3JvbGxJdGVtSGVpZ2h0OiB1bmRlZmluZWQsXG4gICAgc29ydGFibGU6IHRydWUsXG4gICAgc29ydENsYXNzOiB1bmRlZmluZWQsXG4gICAgc2lsZW50U29ydDogdHJ1ZSxcbiAgICBzb3J0TmFtZTogdW5kZWZpbmVkLFxuICAgIHNvcnRPcmRlcjogdW5kZWZpbmVkLFxuICAgIHNvcnRSZXNldDogZmFsc2UsXG4gICAgc29ydFN0YWJsZTogZmFsc2UsXG4gICAgcmVtZW1iZXJPcmRlcjogZmFsc2UsXG4gICAgc2VydmVyU29ydDogdHJ1ZSxcbiAgICBjdXN0b21Tb3J0OiB1bmRlZmluZWQsXG4gICAgY29sdW1uczogW1tdXSxcbiAgICBkYXRhOiBbXSxcbiAgICB1cmw6IHVuZGVmaW5lZCxcbiAgICBtZXRob2Q6ICdnZXQnLFxuICAgIGNhY2hlOiB0cnVlLFxuICAgIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgZGF0YVR5cGU6ICdqc29uJyxcbiAgICBhamF4OiB1bmRlZmluZWQsXG4gICAgYWpheE9wdGlvbnM6IHt9LFxuICAgIHF1ZXJ5UGFyYW1zOiBmdW5jdGlvbiBxdWVyeVBhcmFtcyhwYXJhbXMpIHtcbiAgICAgIHJldHVybiBwYXJhbXM7XG4gICAgfSxcbiAgICBxdWVyeVBhcmFtc1R5cGU6ICdsaW1pdCcsXG4gICAgLy8gJ2xpbWl0JywgdW5kZWZpbmVkXG4gICAgcmVzcG9uc2VIYW5kbGVyOiBmdW5jdGlvbiByZXNwb25zZUhhbmRsZXIocmVzKSB7XG4gICAgICByZXR1cm4gcmVzO1xuICAgIH0sXG4gICAgdG90YWxGaWVsZDogJ3RvdGFsJyxcbiAgICB0b3RhbE5vdEZpbHRlcmVkRmllbGQ6ICd0b3RhbE5vdEZpbHRlcmVkJyxcbiAgICBkYXRhRmllbGQ6ICdyb3dzJyxcbiAgICBmb290ZXJGaWVsZDogJ2Zvb3RlcicsXG4gICAgcGFnaW5hdGlvbjogZmFsc2UsXG4gICAgcGFnaW5hdGlvblBhcnRzOiBbJ3BhZ2VJbmZvJywgJ3BhZ2VTaXplJywgJ3BhZ2VMaXN0J10sXG4gICAgc2hvd0V4dGVuZGVkUGFnaW5hdGlvbjogZmFsc2UsXG4gICAgcGFnaW5hdGlvbkxvb3A6IHRydWUsXG4gICAgc2lkZVBhZ2luYXRpb246ICdjbGllbnQnLFxuICAgIC8vIGNsaWVudCBvciBzZXJ2ZXJcbiAgICB0b3RhbFJvd3M6IDAsXG4gICAgdG90YWxOb3RGaWx0ZXJlZDogMCxcbiAgICBwYWdlTnVtYmVyOiAxLFxuICAgIHBhZ2VTaXplOiAxMCxcbiAgICBwYWdlTGlzdDogWzEwLCAyNSwgNTAsIDEwMF0sXG4gICAgcGFnaW5hdGlvbkhBbGlnbjogJ3JpZ2h0JyxcbiAgICAvLyByaWdodCwgbGVmdFxuICAgIHBhZ2luYXRpb25WQWxpZ246ICdib3R0b20nLFxuICAgIC8vIGJvdHRvbSwgdG9wLCBib3RoXG4gICAgcGFnaW5hdGlvbkRldGFpbEhBbGlnbjogJ2xlZnQnLFxuICAgIC8vIHJpZ2h0LCBsZWZ0XG4gICAgcGFnaW5hdGlvblByZVRleHQ6ICcmbHNhcXVvOycsXG4gICAgcGFnaW5hdGlvbk5leHRUZXh0OiAnJnJzYXF1bzsnLFxuICAgIHBhZ2luYXRpb25TdWNjZXNzaXZlbHlTaXplOiA1LFxuICAgIC8vIE1heGltdW0gc3VjY2Vzc2l2ZWx5IG51bWJlciBvZiBwYWdlcyBpbiBhIHJvd1xuICAgIHBhZ2luYXRpb25QYWdlc0J5U2lkZTogMSxcbiAgICAvLyBOdW1iZXIgb2YgcGFnZXMgb24gZWFjaCBzaWRlIChyaWdodCwgbGVmdCkgb2YgdGhlIGN1cnJlbnQgcGFnZS5cbiAgICBwYWdpbmF0aW9uVXNlSW50ZXJtZWRpYXRlOiBmYWxzZSxcbiAgICAvLyBDYWxjdWxhdGUgaW50ZXJtZWRpYXRlIHBhZ2VzIGZvciBxdWljayBhY2Nlc3NcbiAgICBzZWFyY2g6IGZhbHNlLFxuICAgIHNlYXJjaEhpZ2hsaWdodDogZmFsc2UsXG4gICAgc2VhcmNoT25FbnRlcktleTogZmFsc2UsXG4gICAgc3RyaWN0U2VhcmNoOiBmYWxzZSxcbiAgICBzZWFyY2hTZWxlY3RvcjogZmFsc2UsXG4gICAgdmlzaWJsZVNlYXJjaDogZmFsc2UsXG4gICAgc2hvd0J1dHRvbkljb25zOiB0cnVlLFxuICAgIHNob3dCdXR0b25UZXh0OiBmYWxzZSxcbiAgICBzaG93U2VhcmNoQnV0dG9uOiBmYWxzZSxcbiAgICBzaG93U2VhcmNoQ2xlYXJCdXR0b246IGZhbHNlLFxuICAgIHRyaW1PblNlYXJjaDogdHJ1ZSxcbiAgICBzZWFyY2hBbGlnbjogJ3JpZ2h0JyxcbiAgICBzZWFyY2hUaW1lT3V0OiA1MDAsXG4gICAgc2VhcmNoVGV4dDogJycsXG4gICAgY3VzdG9tU2VhcmNoOiB1bmRlZmluZWQsXG4gICAgc2hvd0hlYWRlcjogdHJ1ZSxcbiAgICBzaG93Rm9vdGVyOiBmYWxzZSxcbiAgICBmb290ZXJTdHlsZTogZnVuY3Rpb24gZm9vdGVyU3R5bGUoY29sdW1uKSB7XG4gICAgICByZXR1cm4ge307XG4gICAgfSxcbiAgICBzZWFyY2hBY2NlbnROZXV0cmFsaXNlOiBmYWxzZSxcbiAgICBzaG93Q29sdW1uczogZmFsc2UsXG4gICAgc2hvd0NvbHVtbnNUb2dnbGVBbGw6IGZhbHNlLFxuICAgIHNob3dDb2x1bW5zU2VhcmNoOiBmYWxzZSxcbiAgICBtaW5pbXVtQ291bnRDb2x1bW5zOiAxLFxuICAgIHNob3dQYWdpbmF0aW9uU3dpdGNoOiBmYWxzZSxcbiAgICBzaG93UmVmcmVzaDogZmFsc2UsXG4gICAgc2hvd1RvZ2dsZTogZmFsc2UsXG4gICAgc2hvd0Z1bGxzY3JlZW46IGZhbHNlLFxuICAgIHNtYXJ0RGlzcGxheTogdHJ1ZSxcbiAgICBlc2NhcGU6IGZhbHNlLFxuICAgIGZpbHRlck9wdGlvbnM6IHtcbiAgICAgIGZpbHRlckFsZ29yaXRobTogJ2FuZCdcbiAgICB9LFxuICAgIGlkRmllbGQ6IHVuZGVmaW5lZCxcbiAgICBzZWxlY3RJdGVtTmFtZTogJ2J0U2VsZWN0SXRlbScsXG4gICAgY2xpY2tUb1NlbGVjdDogZmFsc2UsXG4gICAgaWdub3JlQ2xpY2tUb1NlbGVjdE9uOiBmdW5jdGlvbiBpZ25vcmVDbGlja1RvU2VsZWN0T24oX3JlZikge1xuICAgICAgdmFyIHRhZ05hbWUgPSBfcmVmLnRhZ05hbWU7XG4gICAgICByZXR1cm4gWydBJywgJ0JVVFRPTiddLmluY2x1ZGVzKHRhZ05hbWUpO1xuICAgIH0sXG4gICAgc2luZ2xlU2VsZWN0OiBmYWxzZSxcbiAgICBjaGVja2JveEhlYWRlcjogdHJ1ZSxcbiAgICBtYWludGFpbk1ldGFEYXRhOiBmYWxzZSxcbiAgICBtdWx0aXBsZVNlbGVjdFJvdzogZmFsc2UsXG4gICAgdW5pcXVlSWQ6IHVuZGVmaW5lZCxcbiAgICBjYXJkVmlldzogZmFsc2UsXG4gICAgZGV0YWlsVmlldzogZmFsc2UsXG4gICAgZGV0YWlsVmlld0ljb246IHRydWUsXG4gICAgZGV0YWlsVmlld0J5Q2xpY2s6IGZhbHNlLFxuICAgIGRldGFpbFZpZXdBbGlnbjogJ2xlZnQnLFxuICAgIGRldGFpbEZvcm1hdHRlcjogZnVuY3Rpb24gZGV0YWlsRm9ybWF0dGVyKGluZGV4LCByb3cpIHtcbiAgICAgIHJldHVybiAnJztcbiAgICB9LFxuICAgIGRldGFpbEZpbHRlcjogZnVuY3Rpb24gZGV0YWlsRmlsdGVyKGluZGV4LCByb3cpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG4gICAgdG9vbGJhcjogdW5kZWZpbmVkLFxuICAgIHRvb2xiYXJBbGlnbjogJ2xlZnQnLFxuICAgIGJ1dHRvbnNUb29sYmFyOiB1bmRlZmluZWQsXG4gICAgYnV0dG9uc0FsaWduOiAncmlnaHQnLFxuICAgIGJ1dHRvbnNPcmRlcjogWydwYWdpbmF0aW9uU3dpdGNoJywgJ3JlZnJlc2gnLCAndG9nZ2xlJywgJ2Z1bGxzY3JlZW4nLCAnY29sdW1ucyddLFxuICAgIGJ1dHRvbnNQcmVmaXg6IENPTlNUQU5UUy5jbGFzc2VzLmJ1dHRvbnNQcmVmaXgsXG4gICAgYnV0dG9uc0NsYXNzOiBDT05TVEFOVFMuY2xhc3Nlcy5idXR0b25zLFxuICAgIGljb25zOiBDT05TVEFOVFMuaWNvbnMsXG4gICAgaWNvblNpemU6IHVuZGVmaW5lZCxcbiAgICBpY29uc1ByZWZpeDogQ09OU1RBTlRTLmljb25zUHJlZml4LFxuICAgIC8vIGdseXBoaWNvbiBvciBmYShmb250LWF3ZXNvbWUpXG4gICAgbG9hZGluZ0ZvbnRTaXplOiAnYXV0bycsXG4gICAgbG9hZGluZ1RlbXBsYXRlOiBmdW5jdGlvbiBsb2FkaW5nVGVtcGxhdGUobG9hZGluZ01lc3NhZ2UpIHtcbiAgICAgIHJldHVybiBcIjxzcGFuIGNsYXNzPVxcXCJsb2FkaW5nLXdyYXBcXFwiPlxcbiAgICAgIDxzcGFuIGNsYXNzPVxcXCJsb2FkaW5nLXRleHRcXFwiPlwiLmNvbmNhdChsb2FkaW5nTWVzc2FnZSwgXCI8L3NwYW4+XFxuICAgICAgPHNwYW4gY2xhc3M9XFxcImFuaW1hdGlvbi13cmFwXFxcIj48c3BhbiBjbGFzcz1cXFwiYW5pbWF0aW9uLWRvdFxcXCI+PC9zcGFuPjwvc3Bhbj5cXG4gICAgICA8L3NwYW4+XFxuICAgIFwiKTtcbiAgICB9LFxuICAgIG9uQWxsOiBmdW5jdGlvbiBvbkFsbChuYW1lLCBhcmdzKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvbkNsaWNrQ2VsbDogZnVuY3Rpb24gb25DbGlja0NlbGwoZmllbGQsIHZhbHVlLCByb3csICRlbGVtZW50KSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvbkRibENsaWNrQ2VsbDogZnVuY3Rpb24gb25EYmxDbGlja0NlbGwoZmllbGQsIHZhbHVlLCByb3csICRlbGVtZW50KSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvbkNsaWNrUm93OiBmdW5jdGlvbiBvbkNsaWNrUm93KGl0ZW0sICRlbGVtZW50KSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvbkRibENsaWNrUm93OiBmdW5jdGlvbiBvbkRibENsaWNrUm93KGl0ZW0sICRlbGVtZW50KSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvblNvcnQ6IGZ1bmN0aW9uIG9uU29ydChuYW1lLCBvcmRlcikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG4gICAgb25DaGVjazogZnVuY3Rpb24gb25DaGVjayhyb3cpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LFxuICAgIG9uVW5jaGVjazogZnVuY3Rpb24gb25VbmNoZWNrKHJvdykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG4gICAgb25DaGVja0FsbDogZnVuY3Rpb24gb25DaGVja0FsbChyb3dzKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvblVuY2hlY2tBbGw6IGZ1bmN0aW9uIG9uVW5jaGVja0FsbChyb3dzKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvbkNoZWNrU29tZTogZnVuY3Rpb24gb25DaGVja1NvbWUocm93cykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG4gICAgb25VbmNoZWNrU29tZTogZnVuY3Rpb24gb25VbmNoZWNrU29tZShyb3dzKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvbkxvYWRTdWNjZXNzOiBmdW5jdGlvbiBvbkxvYWRTdWNjZXNzKGRhdGEpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LFxuICAgIG9uTG9hZEVycm9yOiBmdW5jdGlvbiBvbkxvYWRFcnJvcihzdGF0dXMpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LFxuICAgIG9uQ29sdW1uU3dpdGNoOiBmdW5jdGlvbiBvbkNvbHVtblN3aXRjaChmaWVsZCwgY2hlY2tlZCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG4gICAgb25QYWdlQ2hhbmdlOiBmdW5jdGlvbiBvblBhZ2VDaGFuZ2UobnVtYmVyLCBzaXplKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvblNlYXJjaDogZnVuY3Rpb24gb25TZWFyY2godGV4dCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG4gICAgb25Ub2dnbGU6IGZ1bmN0aW9uIG9uVG9nZ2xlKGNhcmRWaWV3KSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvblByZUJvZHk6IGZ1bmN0aW9uIG9uUHJlQm9keShkYXRhKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvblBvc3RCb2R5OiBmdW5jdGlvbiBvblBvc3RCb2R5KCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG4gICAgb25Qb3N0SGVhZGVyOiBmdW5jdGlvbiBvblBvc3RIZWFkZXIoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvblBvc3RGb290ZXI6IGZ1bmN0aW9uIG9uUG9zdEZvb3RlcigpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LFxuICAgIG9uRXhwYW5kUm93OiBmdW5jdGlvbiBvbkV4cGFuZFJvdyhpbmRleCwgcm93LCAkZGV0YWlsKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvbkNvbGxhcHNlUm93OiBmdW5jdGlvbiBvbkNvbGxhcHNlUm93KGluZGV4LCByb3cpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LFxuICAgIG9uUmVmcmVzaE9wdGlvbnM6IGZ1bmN0aW9uIG9uUmVmcmVzaE9wdGlvbnMob3B0aW9ucykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG4gICAgb25SZWZyZXNoOiBmdW5jdGlvbiBvblJlZnJlc2gocGFyYW1zKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvblJlc2V0VmlldzogZnVuY3Rpb24gb25SZXNldFZpZXcoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBvblNjcm9sbEJvZHk6IGZ1bmN0aW9uIG9uU2Nyb2xsQm9keSgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH07XG4gIHZhciBFTiA9IHtcbiAgICBmb3JtYXRMb2FkaW5nTWVzc2FnZTogZnVuY3Rpb24gZm9ybWF0TG9hZGluZ01lc3NhZ2UoKSB7XG4gICAgICByZXR1cm4gJ0xvYWRpbmcsIHBsZWFzZSB3YWl0JztcbiAgICB9LFxuICAgIGZvcm1hdFJlY29yZHNQZXJQYWdlOiBmdW5jdGlvbiBmb3JtYXRSZWNvcmRzUGVyUGFnZShwYWdlTnVtYmVyKSB7XG4gICAgICByZXR1cm4gXCJcIi5jb25jYXQocGFnZU51bWJlciwgXCIgcm93cyBwZXIgcGFnZVwiKTtcbiAgICB9LFxuICAgIGZvcm1hdFNob3dpbmdSb3dzOiBmdW5jdGlvbiBmb3JtYXRTaG93aW5nUm93cyhwYWdlRnJvbSwgcGFnZVRvLCB0b3RhbFJvd3MsIHRvdGFsTm90RmlsdGVyZWQpIHtcbiAgICAgIGlmICh0b3RhbE5vdEZpbHRlcmVkICE9PSB1bmRlZmluZWQgJiYgdG90YWxOb3RGaWx0ZXJlZCA+IDAgJiYgdG90YWxOb3RGaWx0ZXJlZCA+IHRvdGFsUm93cykge1xuICAgICAgICByZXR1cm4gXCJTaG93aW5nIFwiLmNvbmNhdChwYWdlRnJvbSwgXCIgdG8gXCIpLmNvbmNhdChwYWdlVG8sIFwiIG9mIFwiKS5jb25jYXQodG90YWxSb3dzLCBcIiByb3dzIChmaWx0ZXJlZCBmcm9tIFwiKS5jb25jYXQodG90YWxOb3RGaWx0ZXJlZCwgXCIgdG90YWwgcm93cylcIik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBcIlNob3dpbmcgXCIuY29uY2F0KHBhZ2VGcm9tLCBcIiB0byBcIikuY29uY2F0KHBhZ2VUbywgXCIgb2YgXCIpLmNvbmNhdCh0b3RhbFJvd3MsIFwiIHJvd3NcIik7XG4gICAgfSxcbiAgICBmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0OiBmdW5jdGlvbiBmb3JtYXRTUlBhZ2luYXRpb25QcmVUZXh0KCkge1xuICAgICAgcmV0dXJuICdwcmV2aW91cyBwYWdlJztcbiAgICB9LFxuICAgIGZvcm1hdFNSUGFnaW5hdGlvblBhZ2VUZXh0OiBmdW5jdGlvbiBmb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dChwYWdlKSB7XG4gICAgICByZXR1cm4gXCJ0byBwYWdlIFwiLmNvbmNhdChwYWdlKTtcbiAgICB9LFxuICAgIGZvcm1hdFNSUGFnaW5hdGlvbk5leHRUZXh0OiBmdW5jdGlvbiBmb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dCgpIHtcbiAgICAgIHJldHVybiAnbmV4dCBwYWdlJztcbiAgICB9LFxuICAgIGZvcm1hdERldGFpbFBhZ2luYXRpb246IGZ1bmN0aW9uIGZvcm1hdERldGFpbFBhZ2luYXRpb24odG90YWxSb3dzKSB7XG4gICAgICByZXR1cm4gXCJTaG93aW5nIFwiLmNvbmNhdCh0b3RhbFJvd3MsIFwiIHJvd3NcIik7XG4gICAgfSxcbiAgICBmb3JtYXRTZWFyY2g6IGZ1bmN0aW9uIGZvcm1hdFNlYXJjaCgpIHtcbiAgICAgIHJldHVybiAnU2VhcmNoJztcbiAgICB9LFxuICAgIGZvcm1hdENsZWFyU2VhcmNoOiBmdW5jdGlvbiBmb3JtYXRDbGVhclNlYXJjaCgpIHtcbiAgICAgIHJldHVybiAnQ2xlYXIgU2VhcmNoJztcbiAgICB9LFxuICAgIGZvcm1hdE5vTWF0Y2hlczogZnVuY3Rpb24gZm9ybWF0Tm9NYXRjaGVzKCkge1xuICAgICAgcmV0dXJuICdObyBtYXRjaGluZyByZWNvcmRzIGZvdW5kJztcbiAgICB9LFxuICAgIGZvcm1hdFBhZ2luYXRpb25Td2l0Y2g6IGZ1bmN0aW9uIGZvcm1hdFBhZ2luYXRpb25Td2l0Y2goKSB7XG4gICAgICByZXR1cm4gJ0hpZGUvU2hvdyBwYWdpbmF0aW9uJztcbiAgICB9LFxuICAgIGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hEb3duOiBmdW5jdGlvbiBmb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bigpIHtcbiAgICAgIHJldHVybiAnU2hvdyBwYWdpbmF0aW9uJztcbiAgICB9LFxuICAgIGZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcDogZnVuY3Rpb24gZm9ybWF0UGFnaW5hdGlvblN3aXRjaFVwKCkge1xuICAgICAgcmV0dXJuICdIaWRlIHBhZ2luYXRpb24nO1xuICAgIH0sXG4gICAgZm9ybWF0UmVmcmVzaDogZnVuY3Rpb24gZm9ybWF0UmVmcmVzaCgpIHtcbiAgICAgIHJldHVybiAnUmVmcmVzaCc7XG4gICAgfSxcbiAgICBmb3JtYXRUb2dnbGU6IGZ1bmN0aW9uIGZvcm1hdFRvZ2dsZSgpIHtcbiAgICAgIHJldHVybiAnVG9nZ2xlJztcbiAgICB9LFxuICAgIGZvcm1hdFRvZ2dsZU9uOiBmdW5jdGlvbiBmb3JtYXRUb2dnbGVPbigpIHtcbiAgICAgIHJldHVybiAnU2hvdyBjYXJkIHZpZXcnO1xuICAgIH0sXG4gICAgZm9ybWF0VG9nZ2xlT2ZmOiBmdW5jdGlvbiBmb3JtYXRUb2dnbGVPZmYoKSB7XG4gICAgICByZXR1cm4gJ0hpZGUgY2FyZCB2aWV3JztcbiAgICB9LFxuICAgIGZvcm1hdENvbHVtbnM6IGZ1bmN0aW9uIGZvcm1hdENvbHVtbnMoKSB7XG4gICAgICByZXR1cm4gJ0NvbHVtbnMnO1xuICAgIH0sXG4gICAgZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbDogZnVuY3Rpb24gZm9ybWF0Q29sdW1uc1RvZ2dsZUFsbCgpIHtcbiAgICAgIHJldHVybiAnVG9nZ2xlIGFsbCc7XG4gICAgfSxcbiAgICBmb3JtYXRGdWxsc2NyZWVuOiBmdW5jdGlvbiBmb3JtYXRGdWxsc2NyZWVuKCkge1xuICAgICAgcmV0dXJuICdGdWxsc2NyZWVuJztcbiAgICB9LFxuICAgIGZvcm1hdEFsbFJvd3M6IGZ1bmN0aW9uIGZvcm1hdEFsbFJvd3MoKSB7XG4gICAgICByZXR1cm4gJ0FsbCc7XG4gICAgfVxuICB9O1xuICB2YXIgQ09MVU1OX0RFRkFVTFRTID0ge1xuICAgIGZpZWxkOiB1bmRlZmluZWQsXG4gICAgdGl0bGU6IHVuZGVmaW5lZCxcbiAgICB0aXRsZVRvb2x0aXA6IHVuZGVmaW5lZCxcbiAgICBjbGFzczogdW5kZWZpbmVkLFxuICAgIHdpZHRoOiB1bmRlZmluZWQsXG4gICAgd2lkdGhVbml0OiAncHgnLFxuICAgIHJvd3NwYW46IHVuZGVmaW5lZCxcbiAgICBjb2xzcGFuOiB1bmRlZmluZWQsXG4gICAgYWxpZ246IHVuZGVmaW5lZCxcbiAgICAvLyBsZWZ0LCByaWdodCwgY2VudGVyXG4gICAgaGFsaWduOiB1bmRlZmluZWQsXG4gICAgLy8gbGVmdCwgcmlnaHQsIGNlbnRlclxuICAgIGZhbGlnbjogdW5kZWZpbmVkLFxuICAgIC8vIGxlZnQsIHJpZ2h0LCBjZW50ZXJcbiAgICB2YWxpZ246IHVuZGVmaW5lZCxcbiAgICAvLyB0b3AsIG1pZGRsZSwgYm90dG9tXG4gICAgY2VsbFN0eWxlOiB1bmRlZmluZWQsXG4gICAgcmFkaW86IGZhbHNlLFxuICAgIGNoZWNrYm94OiBmYWxzZSxcbiAgICBjaGVja2JveEVuYWJsZWQ6IHRydWUsXG4gICAgY2xpY2tUb1NlbGVjdDogdHJ1ZSxcbiAgICBzaG93U2VsZWN0VGl0bGU6IGZhbHNlLFxuICAgIHNvcnRhYmxlOiBmYWxzZSxcbiAgICBzb3J0TmFtZTogdW5kZWZpbmVkLFxuICAgIG9yZGVyOiAnYXNjJyxcbiAgICAvLyBhc2MsIGRlc2NcbiAgICBzb3J0ZXI6IHVuZGVmaW5lZCxcbiAgICB2aXNpYmxlOiB0cnVlLFxuICAgIHN3aXRjaGFibGU6IHRydWUsXG4gICAgY2FyZFZpc2libGU6IHRydWUsXG4gICAgc2VhcmNoYWJsZTogdHJ1ZSxcbiAgICBmb3JtYXR0ZXI6IHVuZGVmaW5lZCxcbiAgICBmb290ZXJGb3JtYXR0ZXI6IHVuZGVmaW5lZCxcbiAgICBkZXRhaWxGb3JtYXR0ZXI6IHVuZGVmaW5lZCxcbiAgICBzZWFyY2hGb3JtYXR0ZXI6IHRydWUsXG4gICAgc2VhcmNoSGlnaGxpZ2h0Rm9ybWF0dGVyOiBmYWxzZSxcbiAgICBlc2NhcGU6IGZhbHNlLFxuICAgIGV2ZW50czogdW5kZWZpbmVkXG4gIH07XG4gIHZhciBNRVRIT0RTID0gWydnZXRPcHRpb25zJywgJ3JlZnJlc2hPcHRpb25zJywgJ2dldERhdGEnLCAnZ2V0U2VsZWN0aW9ucycsICdsb2FkJywgJ2FwcGVuZCcsICdwcmVwZW5kJywgJ3JlbW92ZScsICdyZW1vdmVBbGwnLCAnaW5zZXJ0Um93JywgJ3VwZGF0ZVJvdycsICdnZXRSb3dCeVVuaXF1ZUlkJywgJ3VwZGF0ZUJ5VW5pcXVlSWQnLCAncmVtb3ZlQnlVbmlxdWVJZCcsICd1cGRhdGVDZWxsJywgJ3VwZGF0ZUNlbGxCeVVuaXF1ZUlkJywgJ3Nob3dSb3cnLCAnaGlkZVJvdycsICdnZXRIaWRkZW5Sb3dzJywgJ3Nob3dDb2x1bW4nLCAnaGlkZUNvbHVtbicsICdnZXRWaXNpYmxlQ29sdW1ucycsICdnZXRIaWRkZW5Db2x1bW5zJywgJ3Nob3dBbGxDb2x1bW5zJywgJ2hpZGVBbGxDb2x1bW5zJywgJ21lcmdlQ2VsbHMnLCAnY2hlY2tBbGwnLCAndW5jaGVja0FsbCcsICdjaGVja0ludmVydCcsICdjaGVjaycsICd1bmNoZWNrJywgJ2NoZWNrQnknLCAndW5jaGVja0J5JywgJ3JlZnJlc2gnLCAnZGVzdHJveScsICdyZXNldFZpZXcnLCAnc2hvd0xvYWRpbmcnLCAnaGlkZUxvYWRpbmcnLCAndG9nZ2xlUGFnaW5hdGlvbicsICd0b2dnbGVGdWxsc2NyZWVuJywgJ3RvZ2dsZVZpZXcnLCAncmVzZXRTZWFyY2gnLCAnZmlsdGVyQnknLCAnc2Nyb2xsVG8nLCAnZ2V0U2Nyb2xsUG9zaXRpb24nLCAnc2VsZWN0UGFnZScsICdwcmV2UGFnZScsICduZXh0UGFnZScsICd0b2dnbGVEZXRhaWxWaWV3JywgJ2V4cGFuZFJvdycsICdjb2xsYXBzZVJvdycsICdleHBhbmRSb3dCeVVuaXF1ZUlkJywgJ2NvbGxhcHNlUm93QnlVbmlxdWVJZCcsICdleHBhbmRBbGxSb3dzJywgJ2NvbGxhcHNlQWxsUm93cycsICd1cGRhdGVDb2x1bW5UaXRsZScsICd1cGRhdGVGb3JtYXRUZXh0J107XG4gIHZhciBFVkVOVFMgPSB7XG4gICAgJ2FsbC5icy50YWJsZSc6ICdvbkFsbCcsXG4gICAgJ2NsaWNrLXJvdy5icy50YWJsZSc6ICdvbkNsaWNrUm93JyxcbiAgICAnZGJsLWNsaWNrLXJvdy5icy50YWJsZSc6ICdvbkRibENsaWNrUm93JyxcbiAgICAnY2xpY2stY2VsbC5icy50YWJsZSc6ICdvbkNsaWNrQ2VsbCcsXG4gICAgJ2RibC1jbGljay1jZWxsLmJzLnRhYmxlJzogJ29uRGJsQ2xpY2tDZWxsJyxcbiAgICAnc29ydC5icy50YWJsZSc6ICdvblNvcnQnLFxuICAgICdjaGVjay5icy50YWJsZSc6ICdvbkNoZWNrJyxcbiAgICAndW5jaGVjay5icy50YWJsZSc6ICdvblVuY2hlY2snLFxuICAgICdjaGVjay1hbGwuYnMudGFibGUnOiAnb25DaGVja0FsbCcsXG4gICAgJ3VuY2hlY2stYWxsLmJzLnRhYmxlJzogJ29uVW5jaGVja0FsbCcsXG4gICAgJ2NoZWNrLXNvbWUuYnMudGFibGUnOiAnb25DaGVja1NvbWUnLFxuICAgICd1bmNoZWNrLXNvbWUuYnMudGFibGUnOiAnb25VbmNoZWNrU29tZScsXG4gICAgJ2xvYWQtc3VjY2Vzcy5icy50YWJsZSc6ICdvbkxvYWRTdWNjZXNzJyxcbiAgICAnbG9hZC1lcnJvci5icy50YWJsZSc6ICdvbkxvYWRFcnJvcicsXG4gICAgJ2NvbHVtbi1zd2l0Y2guYnMudGFibGUnOiAnb25Db2x1bW5Td2l0Y2gnLFxuICAgICdwYWdlLWNoYW5nZS5icy50YWJsZSc6ICdvblBhZ2VDaGFuZ2UnLFxuICAgICdzZWFyY2guYnMudGFibGUnOiAnb25TZWFyY2gnLFxuICAgICd0b2dnbGUuYnMudGFibGUnOiAnb25Ub2dnbGUnLFxuICAgICdwcmUtYm9keS5icy50YWJsZSc6ICdvblByZUJvZHknLFxuICAgICdwb3N0LWJvZHkuYnMudGFibGUnOiAnb25Qb3N0Qm9keScsXG4gICAgJ3Bvc3QtaGVhZGVyLmJzLnRhYmxlJzogJ29uUG9zdEhlYWRlcicsXG4gICAgJ3Bvc3QtZm9vdGVyLmJzLnRhYmxlJzogJ29uUG9zdEZvb3RlcicsXG4gICAgJ2V4cGFuZC1yb3cuYnMudGFibGUnOiAnb25FeHBhbmRSb3cnLFxuICAgICdjb2xsYXBzZS1yb3cuYnMudGFibGUnOiAnb25Db2xsYXBzZVJvdycsXG4gICAgJ3JlZnJlc2gtb3B0aW9ucy5icy50YWJsZSc6ICdvblJlZnJlc2hPcHRpb25zJyxcbiAgICAncmVzZXQtdmlldy5icy50YWJsZSc6ICdvblJlc2V0VmlldycsXG4gICAgJ3JlZnJlc2guYnMudGFibGUnOiAnb25SZWZyZXNoJyxcbiAgICAnc2Nyb2xsLWJvZHkuYnMudGFibGUnOiAnb25TY3JvbGxCb2R5J1xuICB9O1xuICBPYmplY3QuYXNzaWduKERFRkFVTFRTLCBFTik7XG4gIHZhciBDb25zdGFudHMgPSB7XG4gICAgVkVSU0lPTjogVkVSU0lPTixcbiAgICBUSEVNRTogXCJib290c3RyYXBcIi5jb25jYXQoYm9vdHN0cmFwVmVyc2lvbiksXG4gICAgQ09OU1RBTlRTOiBDT05TVEFOVFMsXG4gICAgREVGQVVMVFM6IERFRkFVTFRTLFxuICAgIENPTFVNTl9ERUZBVUxUUzogQ09MVU1OX0RFRkFVTFRTLFxuICAgIE1FVEhPRFM6IE1FVEhPRFMsXG4gICAgRVZFTlRTOiBFVkVOVFMsXG4gICAgTE9DQUxFUzoge1xuICAgICAgZW46IEVOLFxuICAgICAgJ2VuLVVTJzogRU5cbiAgICB9XG4gIH07XG5cbiAgdmFyIEZBSUxTX09OX1BSSU1JVElWRVMgPSBmYWlscyhmdW5jdGlvbiAoKSB7IG9iamVjdEtleXMoMSk7IH0pO1xuXG4gIC8vIGBPYmplY3Qua2V5c2AgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtb2JqZWN0LmtleXNcbiAgX2V4cG9ydCh7IHRhcmdldDogJ09iamVjdCcsIHN0YXQ6IHRydWUsIGZvcmNlZDogRkFJTFNfT05fUFJJTUlUSVZFUyB9LCB7XG4gICAga2V5czogZnVuY3Rpb24ga2V5cyhpdCkge1xuICAgICAgcmV0dXJuIG9iamVjdEtleXModG9PYmplY3QoaXQpKTtcbiAgICB9XG4gIH0pO1xuXG4gIHZhciBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IkMSA9IG9iamVjdEdldE93blByb3BlcnR5RGVzY3JpcHRvci5mO1xuXG5cblxuXG5cblxuICB2YXIgbmF0aXZlU3RhcnRzV2l0aCA9ICcnLnN0YXJ0c1dpdGg7XG4gIHZhciBtaW4kMSA9IE1hdGgubWluO1xuXG4gIHZhciBDT1JSRUNUX0lTX1JFR0VYUF9MT0dJQyQxID0gY29ycmVjdElzUmVnZXhwTG9naWMoJ3N0YXJ0c1dpdGgnKTtcbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMvcHVsbC83MDJcbiAgdmFyIE1ETl9QT0xZRklMTF9CVUckMSA9ICFDT1JSRUNUX0lTX1JFR0VYUF9MT0dJQyQxICYmICEhZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZXNjcmlwdG9yID0gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yJDEoU3RyaW5nLnByb3RvdHlwZSwgJ3N0YXJ0c1dpdGgnKTtcbiAgICByZXR1cm4gZGVzY3JpcHRvciAmJiAhZGVzY3JpcHRvci53cml0YWJsZTtcbiAgfSgpO1xuXG4gIC8vIGBTdHJpbmcucHJvdG90eXBlLnN0YXJ0c1dpdGhgIG1ldGhvZFxuICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXN0cmluZy5wcm90b3R5cGUuc3RhcnRzd2l0aFxuICBfZXhwb3J0KHsgdGFyZ2V0OiAnU3RyaW5nJywgcHJvdG86IHRydWUsIGZvcmNlZDogIU1ETl9QT0xZRklMTF9CVUckMSAmJiAhQ09SUkVDVF9JU19SRUdFWFBfTE9HSUMkMSB9LCB7XG4gICAgc3RhcnRzV2l0aDogZnVuY3Rpb24gc3RhcnRzV2l0aChzZWFyY2hTdHJpbmcgLyogLCBwb3NpdGlvbiA9IDAgKi8pIHtcbiAgICAgIHZhciB0aGF0ID0gU3RyaW5nKHJlcXVpcmVPYmplY3RDb2VyY2libGUodGhpcykpO1xuICAgICAgbm90QVJlZ2V4cChzZWFyY2hTdHJpbmcpO1xuICAgICAgdmFyIGluZGV4ID0gdG9MZW5ndGgobWluJDEoYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQsIHRoYXQubGVuZ3RoKSk7XG4gICAgICB2YXIgc2VhcmNoID0gU3RyaW5nKHNlYXJjaFN0cmluZyk7XG4gICAgICByZXR1cm4gbmF0aXZlU3RhcnRzV2l0aFxuICAgICAgICA/IG5hdGl2ZVN0YXJ0c1dpdGguY2FsbCh0aGF0LCBzZWFyY2gsIGluZGV4KVxuICAgICAgICA6IHRoYXQuc2xpY2UoaW5kZXgsIGluZGV4ICsgc2VhcmNoLmxlbmd0aCkgPT09IHNlYXJjaDtcbiAgICB9XG4gIH0pO1xuXG4gIHZhciBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgPSBvYmplY3RHZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IuZjtcblxuXG5cblxuXG5cbiAgdmFyIG5hdGl2ZUVuZHNXaXRoID0gJycuZW5kc1dpdGg7XG4gIHZhciBtaW4gPSBNYXRoLm1pbjtcblxuICB2YXIgQ09SUkVDVF9JU19SRUdFWFBfTE9HSUMgPSBjb3JyZWN0SXNSZWdleHBMb2dpYygnZW5kc1dpdGgnKTtcbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMvcHVsbC83MDJcbiAgdmFyIE1ETl9QT0xZRklMTF9CVUcgPSAhQ09SUkVDVF9JU19SRUdFWFBfTE9HSUMgJiYgISFmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlc2NyaXB0b3IgPSBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoU3RyaW5nLnByb3RvdHlwZSwgJ2VuZHNXaXRoJyk7XG4gICAgcmV0dXJuIGRlc2NyaXB0b3IgJiYgIWRlc2NyaXB0b3Iud3JpdGFibGU7XG4gIH0oKTtcblxuICAvLyBgU3RyaW5nLnByb3RvdHlwZS5lbmRzV2l0aGAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtc3RyaW5nLnByb3RvdHlwZS5lbmRzd2l0aFxuICBfZXhwb3J0KHsgdGFyZ2V0OiAnU3RyaW5nJywgcHJvdG86IHRydWUsIGZvcmNlZDogIU1ETl9QT0xZRklMTF9CVUcgJiYgIUNPUlJFQ1RfSVNfUkVHRVhQX0xPR0lDIH0sIHtcbiAgICBlbmRzV2l0aDogZnVuY3Rpb24gZW5kc1dpdGgoc2VhcmNoU3RyaW5nIC8qICwgZW5kUG9zaXRpb24gPSBAbGVuZ3RoICovKSB7XG4gICAgICB2YXIgdGhhdCA9IFN0cmluZyhyZXF1aXJlT2JqZWN0Q29lcmNpYmxlKHRoaXMpKTtcbiAgICAgIG5vdEFSZWdleHAoc2VhcmNoU3RyaW5nKTtcbiAgICAgIHZhciBlbmRQb3NpdGlvbiA9IGFyZ3VtZW50cy5sZW5ndGggPiAxID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkO1xuICAgICAgdmFyIGxlbiA9IHRvTGVuZ3RoKHRoYXQubGVuZ3RoKTtcbiAgICAgIHZhciBlbmQgPSBlbmRQb3NpdGlvbiA9PT0gdW5kZWZpbmVkID8gbGVuIDogbWluKHRvTGVuZ3RoKGVuZFBvc2l0aW9uKSwgbGVuKTtcbiAgICAgIHZhciBzZWFyY2ggPSBTdHJpbmcoc2VhcmNoU3RyaW5nKTtcbiAgICAgIHJldHVybiBuYXRpdmVFbmRzV2l0aFxuICAgICAgICA/IG5hdGl2ZUVuZHNXaXRoLmNhbGwodGhhdCwgc2VhcmNoLCBlbmQpXG4gICAgICAgIDogdGhhdC5zbGljZShlbmQgLSBzZWFyY2gubGVuZ3RoLCBlbmQpID09PSBzZWFyY2g7XG4gICAgfVxuICB9KTtcblxuICB2YXIgVXRpbHMgPSB7XG4gICAgZ2V0U2VhcmNoSW5wdXQ6IGZ1bmN0aW9uIGdldFNlYXJjaElucHV0KHRoYXQpIHtcbiAgICAgIGlmICh0eXBlb2YgdGhhdC5vcHRpb25zLnNlYXJjaFNlbGVjdG9yID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gJF9fZGVmYXVsdFsnZGVmYXVsdCddKHRoYXQub3B0aW9ucy5zZWFyY2hTZWxlY3Rvcik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGF0LiR0b29sYmFyLmZpbmQoJy5zZWFyY2ggaW5wdXQnKTtcbiAgICB9LFxuICAgIC8vIGl0IG9ubHkgZG9lcyAnJXMnLCBhbmQgcmV0dXJuICcnIHdoZW4gYXJndW1lbnRzIGFyZSB1bmRlZmluZWRcbiAgICBzcHJpbnRmOiBmdW5jdGlvbiBzcHJpbnRmKF9zdHIpIHtcbiAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4gPiAxID8gX2xlbiAtIDEgOiAwKSwgX2tleSA9IDE7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHtcbiAgICAgICAgYXJnc1tfa2V5IC0gMV0gPSBhcmd1bWVudHNbX2tleV07XG4gICAgICB9XG5cbiAgICAgIHZhciBmbGFnID0gdHJ1ZTtcbiAgICAgIHZhciBpID0gMDtcblxuICAgICAgdmFyIHN0ciA9IF9zdHIucmVwbGFjZSgvJXMvZywgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgYXJnID0gYXJnc1tpKytdO1xuXG4gICAgICAgIGlmICh0eXBlb2YgYXJnID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIGZsYWcgPSBmYWxzZTtcbiAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYXJnO1xuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiBmbGFnID8gc3RyIDogJyc7XG4gICAgfSxcbiAgICBpc09iamVjdDogZnVuY3Rpb24gaXNPYmplY3QodmFsKSB7XG4gICAgICByZXR1cm4gdmFsIGluc3RhbmNlb2YgT2JqZWN0ICYmICFBcnJheS5pc0FycmF5KHZhbCk7XG4gICAgfSxcbiAgICBpc0VtcHR5T2JqZWN0OiBmdW5jdGlvbiBpc0VtcHR5T2JqZWN0KCkge1xuICAgICAgdmFyIG9iaiA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDoge307XG4gICAgICByZXR1cm4gT2JqZWN0LmVudHJpZXMob2JqKS5sZW5ndGggPT09IDAgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBPYmplY3Q7XG4gICAgfSxcbiAgICBpc051bWVyaWM6IGZ1bmN0aW9uIGlzTnVtZXJpYyhuKSB7XG4gICAgICByZXR1cm4gIWlzTmFOKHBhcnNlRmxvYXQobikpICYmIGlzRmluaXRlKG4pO1xuICAgIH0sXG4gICAgZ2V0RmllbGRUaXRsZTogZnVuY3Rpb24gZ2V0RmllbGRUaXRsZShsaXN0LCB2YWx1ZSkge1xuICAgICAgdmFyIF9pdGVyYXRvciA9IF9jcmVhdGVGb3JPZkl0ZXJhdG9ySGVscGVyKGxpc3QpLFxuICAgICAgICAgIF9zdGVwO1xuXG4gICAgICB0cnkge1xuICAgICAgICBmb3IgKF9pdGVyYXRvci5zKCk7ICEoX3N0ZXAgPSBfaXRlcmF0b3IubigpKS5kb25lOykge1xuICAgICAgICAgIHZhciBpdGVtID0gX3N0ZXAudmFsdWU7XG5cbiAgICAgICAgICBpZiAoaXRlbS5maWVsZCA9PT0gdmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybiBpdGVtLnRpdGxlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIF9pdGVyYXRvci5lKGVycik7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBfaXRlcmF0b3IuZigpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gJyc7XG4gICAgfSxcbiAgICBzZXRGaWVsZEluZGV4OiBmdW5jdGlvbiBzZXRGaWVsZEluZGV4KGNvbHVtbnMpIHtcbiAgICAgIHZhciB0b3RhbENvbCA9IDA7XG4gICAgICB2YXIgZmxhZyA9IFtdO1xuXG4gICAgICB2YXIgX2l0ZXJhdG9yMiA9IF9jcmVhdGVGb3JPZkl0ZXJhdG9ySGVscGVyKGNvbHVtbnNbMF0pLFxuICAgICAgICAgIF9zdGVwMjtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgZm9yIChfaXRlcmF0b3IyLnMoKTsgIShfc3RlcDIgPSBfaXRlcmF0b3IyLm4oKSkuZG9uZTspIHtcbiAgICAgICAgICB2YXIgY29sdW1uID0gX3N0ZXAyLnZhbHVlO1xuICAgICAgICAgIHRvdGFsQ29sICs9IGNvbHVtbi5jb2xzcGFuIHx8IDE7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBfaXRlcmF0b3IyLmUoZXJyKTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIF9pdGVyYXRvcjIuZigpO1xuICAgICAgfVxuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvbHVtbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZmxhZ1tpXSA9IFtdO1xuXG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgdG90YWxDb2w7IGorKykge1xuICAgICAgICAgIGZsYWdbaV1bal0gPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgY29sdW1ucy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIF9pdGVyYXRvcjMgPSBfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlcihjb2x1bW5zW19pXSksXG4gICAgICAgICAgICBfc3RlcDM7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBmb3IgKF9pdGVyYXRvcjMucygpOyAhKF9zdGVwMyA9IF9pdGVyYXRvcjMubigpKS5kb25lOykge1xuICAgICAgICAgICAgdmFyIHIgPSBfc3RlcDMudmFsdWU7XG4gICAgICAgICAgICB2YXIgcm93c3BhbiA9IHIucm93c3BhbiB8fCAxO1xuICAgICAgICAgICAgdmFyIGNvbHNwYW4gPSByLmNvbHNwYW4gfHwgMTtcblxuICAgICAgICAgICAgdmFyIGluZGV4ID0gZmxhZ1tfaV0uaW5kZXhPZihmYWxzZSk7XG5cbiAgICAgICAgICAgIHIuY29sc3BhbkluZGV4ID0gaW5kZXg7XG5cbiAgICAgICAgICAgIGlmIChjb2xzcGFuID09PSAxKSB7XG4gICAgICAgICAgICAgIHIuZmllbGRJbmRleCA9IGluZGV4OyAvLyB3aGVuIGZpZWxkIGlzIHVuZGVmaW5lZCwgdXNlIGluZGV4IGluc3RlYWRcblxuICAgICAgICAgICAgICBpZiAodHlwZW9mIHIuZmllbGQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgci5maWVsZCA9IGluZGV4O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByLmNvbHNwYW5Hcm91cCA9IHIuY29sc3BhbjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yICh2YXIgX2ogPSAwOyBfaiA8IHJvd3NwYW47IF9qKyspIHtcbiAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBjb2xzcGFuOyBrKyspIHtcbiAgICAgICAgICAgICAgICBmbGFnW19pICsgX2pdW2luZGV4ICsga10gPSB0cnVlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBfaXRlcmF0b3IzLmUoZXJyKTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICBfaXRlcmF0b3IzLmYoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG4gICAgbm9ybWFsaXplQWNjZW50OiBmdW5jdGlvbiBub3JtYWxpemVBY2NlbnQodmFsdWUpIHtcbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHZhbHVlLm5vcm1hbGl6ZSgnTkZEJykucmVwbGFjZSgvW1xcdTAzMDAtXFx1MDM2Zl0vZywgJycpO1xuICAgIH0sXG4gICAgdXBkYXRlRmllbGRHcm91cDogZnVuY3Rpb24gdXBkYXRlRmllbGRHcm91cChjb2x1bW5zKSB7XG4gICAgICB2YXIgX3JlZjtcblxuICAgICAgdmFyIGFsbENvbHVtbnMgPSAoX3JlZiA9IFtdKS5jb25jYXQuYXBwbHkoX3JlZiwgX3RvQ29uc3VtYWJsZUFycmF5KGNvbHVtbnMpKTtcblxuICAgICAgdmFyIF9pdGVyYXRvcjQgPSBfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlcihjb2x1bW5zKSxcbiAgICAgICAgICBfc3RlcDQ7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGZvciAoX2l0ZXJhdG9yNC5zKCk7ICEoX3N0ZXA0ID0gX2l0ZXJhdG9yNC5uKCkpLmRvbmU7KSB7XG4gICAgICAgICAgdmFyIGMgPSBfc3RlcDQudmFsdWU7XG5cbiAgICAgICAgICB2YXIgX2l0ZXJhdG9yNSA9IF9jcmVhdGVGb3JPZkl0ZXJhdG9ySGVscGVyKGMpLFxuICAgICAgICAgICAgICBfc3RlcDU7XG5cbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgZm9yIChfaXRlcmF0b3I1LnMoKTsgIShfc3RlcDUgPSBfaXRlcmF0b3I1Lm4oKSkuZG9uZTspIHtcbiAgICAgICAgICAgICAgdmFyIHIgPSBfc3RlcDUudmFsdWU7XG5cbiAgICAgICAgICAgICAgaWYgKHIuY29sc3Bhbkdyb3VwID4gMSkge1xuICAgICAgICAgICAgICAgIHZhciBjb2xzcGFuID0gMDtcblxuICAgICAgICAgICAgICAgIHZhciBfbG9vcCA9IGZ1bmN0aW9uIF9sb29wKGkpIHtcbiAgICAgICAgICAgICAgICAgIHZhciBjb2x1bW4gPSBhbGxDb2x1bW5zLmZpbmQoZnVuY3Rpb24gKGNvbCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29sLmZpZWxkSW5kZXggPT09IGk7XG4gICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgaWYgKGNvbHVtbi52aXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbHNwYW4rKztcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IHIuY29sc3BhbkluZGV4OyBpIDwgci5jb2xzcGFuSW5kZXggKyByLmNvbHNwYW5Hcm91cDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICBfbG9vcChpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByLmNvbHNwYW4gPSBjb2xzcGFuO1xuICAgICAgICAgICAgICAgIHIudmlzaWJsZSA9IGNvbHNwYW4gPiAwO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBfaXRlcmF0b3I1LmUoZXJyKTtcbiAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgX2l0ZXJhdG9yNS5mKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgX2l0ZXJhdG9yNC5lKGVycik7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBfaXRlcmF0b3I0LmYoKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIGdldFNjcm9sbEJhcldpZHRoOiBmdW5jdGlvbiBnZXRTY3JvbGxCYXJXaWR0aCgpIHtcbiAgICAgIGlmICh0aGlzLmNhY2hlZFdpZHRoID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdmFyICRpbm5lciA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXSgnPGRpdi8+JykuYWRkQ2xhc3MoJ2ZpeGVkLXRhYmxlLXNjcm9sbC1pbm5lcicpO1xuICAgICAgICB2YXIgJG91dGVyID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKCc8ZGl2Lz4nKS5hZGRDbGFzcygnZml4ZWQtdGFibGUtc2Nyb2xsLW91dGVyJyk7XG4gICAgICAgICRvdXRlci5hcHBlbmQoJGlubmVyKTtcbiAgICAgICAgJF9fZGVmYXVsdFsnZGVmYXVsdCddKCdib2R5JykuYXBwZW5kKCRvdXRlcik7XG4gICAgICAgIHZhciB3MSA9ICRpbm5lclswXS5vZmZzZXRXaWR0aDtcbiAgICAgICAgJG91dGVyLmNzcygnb3ZlcmZsb3cnLCAnc2Nyb2xsJyk7XG4gICAgICAgIHZhciB3MiA9ICRpbm5lclswXS5vZmZzZXRXaWR0aDtcblxuICAgICAgICBpZiAodzEgPT09IHcyKSB7XG4gICAgICAgICAgdzIgPSAkb3V0ZXJbMF0uY2xpZW50V2lkdGg7XG4gICAgICAgIH1cblxuICAgICAgICAkb3V0ZXIucmVtb3ZlKCk7XG4gICAgICAgIHRoaXMuY2FjaGVkV2lkdGggPSB3MSAtIHcyO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5jYWNoZWRXaWR0aDtcbiAgICB9LFxuICAgIGNhbGN1bGF0ZU9iamVjdFZhbHVlOiBmdW5jdGlvbiBjYWxjdWxhdGVPYmplY3RWYWx1ZShzZWxmLCBuYW1lLCBhcmdzLCBkZWZhdWx0VmFsdWUpIHtcbiAgICAgIHZhciBmdW5jID0gbmFtZTtcblxuICAgICAgaWYgKHR5cGVvZiBuYW1lID09PSAnc3RyaW5nJykge1xuICAgICAgICAvLyBzdXBwb3J0IG9iai5mdW5jMS5mdW5jMlxuICAgICAgICB2YXIgbmFtZXMgPSBuYW1lLnNwbGl0KCcuJyk7XG5cbiAgICAgICAgaWYgKG5hbWVzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICBmdW5jID0gd2luZG93O1xuXG4gICAgICAgICAgdmFyIF9pdGVyYXRvcjYgPSBfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlcihuYW1lcyksXG4gICAgICAgICAgICAgIF9zdGVwNjtcblxuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBmb3IgKF9pdGVyYXRvcjYucygpOyAhKF9zdGVwNiA9IF9pdGVyYXRvcjYubigpKS5kb25lOykge1xuICAgICAgICAgICAgICB2YXIgZiA9IF9zdGVwNi52YWx1ZTtcbiAgICAgICAgICAgICAgZnVuYyA9IGZ1bmNbZl07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBfaXRlcmF0b3I2LmUoZXJyKTtcbiAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgX2l0ZXJhdG9yNi5mKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGZ1bmMgPSB3aW5kb3dbbmFtZV07XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGZ1bmMgIT09IG51bGwgJiYgX3R5cGVvZihmdW5jKSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmM7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgZnVuYyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gZnVuYy5hcHBseShzZWxmLCBhcmdzIHx8IFtdKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFmdW5jICYmIHR5cGVvZiBuYW1lID09PSAnc3RyaW5nJyAmJiB0aGlzLnNwcmludGYuYXBwbHkodGhpcywgW25hbWVdLmNvbmNhdChfdG9Db25zdW1hYmxlQXJyYXkoYXJncykpKSkge1xuICAgICAgICByZXR1cm4gdGhpcy5zcHJpbnRmLmFwcGx5KHRoaXMsIFtuYW1lXS5jb25jYXQoX3RvQ29uc3VtYWJsZUFycmF5KGFyZ3MpKSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBkZWZhdWx0VmFsdWU7XG4gICAgfSxcbiAgICBjb21wYXJlT2JqZWN0czogZnVuY3Rpb24gY29tcGFyZU9iamVjdHMob2JqZWN0QSwgb2JqZWN0QiwgY29tcGFyZUxlbmd0aCkge1xuICAgICAgdmFyIGFLZXlzID0gT2JqZWN0LmtleXMob2JqZWN0QSk7XG4gICAgICB2YXIgYktleXMgPSBPYmplY3Qua2V5cyhvYmplY3RCKTtcblxuICAgICAgaWYgKGNvbXBhcmVMZW5ndGggJiYgYUtleXMubGVuZ3RoICE9PSBiS2V5cy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBmb3IgKHZhciBfaTIgPSAwLCBfYUtleXMgPSBhS2V5czsgX2kyIDwgX2FLZXlzLmxlbmd0aDsgX2kyKyspIHtcbiAgICAgICAgdmFyIGtleSA9IF9hS2V5c1tfaTJdO1xuXG4gICAgICAgIGlmIChiS2V5cy5pbmNsdWRlcyhrZXkpICYmIG9iamVjdEFba2V5XSAhPT0gb2JqZWN0QltrZXldKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG4gICAgZXNjYXBlSFRNTDogZnVuY3Rpb24gZXNjYXBlSFRNTCh0ZXh0KSB7XG4gICAgICBpZiAodHlwZW9mIHRleHQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiB0ZXh0LnJlcGxhY2UoLyYvZywgJyZhbXA7JykucmVwbGFjZSgvPC9nLCAnJmx0OycpLnJlcGxhY2UoLz4vZywgJyZndDsnKS5yZXBsYWNlKC9cIi9nLCAnJnF1b3Q7JykucmVwbGFjZSgvJy9nLCAnJiMwMzk7JykucmVwbGFjZSgvYC9nLCAnJiN4NjA7Jyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0ZXh0O1xuICAgIH0sXG4gICAgdW5lc2NhcGVIVE1MOiBmdW5jdGlvbiB1bmVzY2FwZUhUTUwodGV4dCkge1xuICAgICAgaWYgKHR5cGVvZiB0ZXh0ID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gdGV4dC5yZXBsYWNlKC8mYW1wOy9nLCAnJicpLnJlcGxhY2UoLyZsdDsvZywgJzwnKS5yZXBsYWNlKC8mZ3Q7L2csICc+JykucmVwbGFjZSgvJnF1b3Q7L2csICdcIicpLnJlcGxhY2UoLyYjMDM5Oy9nLCAnXFwnJykucmVwbGFjZSgvJiN4NjA7L2csICdgJyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0ZXh0O1xuICAgIH0sXG4gICAgZ2V0UmVhbERhdGFBdHRyOiBmdW5jdGlvbiBnZXRSZWFsRGF0YUF0dHIoZGF0YUF0dHIpIHtcbiAgICAgIGZvciAodmFyIF9pMyA9IDAsIF9PYmplY3QkZW50cmllcyA9IE9iamVjdC5lbnRyaWVzKGRhdGFBdHRyKTsgX2kzIDwgX09iamVjdCRlbnRyaWVzLmxlbmd0aDsgX2kzKyspIHtcbiAgICAgICAgdmFyIF9PYmplY3QkZW50cmllcyRfaSA9IF9zbGljZWRUb0FycmF5KF9PYmplY3QkZW50cmllc1tfaTNdLCAyKSxcbiAgICAgICAgICAgIGF0dHIgPSBfT2JqZWN0JGVudHJpZXMkX2lbMF0sXG4gICAgICAgICAgICB2YWx1ZSA9IF9PYmplY3QkZW50cmllcyRfaVsxXTtcblxuICAgICAgICB2YXIgYXV4QXR0ciA9IGF0dHIuc3BsaXQoLyg/PVtBLVpdKS8pLmpvaW4oJy0nKS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICAgIGlmIChhdXhBdHRyICE9PSBhdHRyKSB7XG4gICAgICAgICAgZGF0YUF0dHJbYXV4QXR0cl0gPSB2YWx1ZTtcbiAgICAgICAgICBkZWxldGUgZGF0YUF0dHJbYXR0cl07XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGRhdGFBdHRyO1xuICAgIH0sXG4gICAgZ2V0SXRlbUZpZWxkOiBmdW5jdGlvbiBnZXRJdGVtRmllbGQoaXRlbSwgZmllbGQsIGVzY2FwZSkge1xuICAgICAgdmFyIHZhbHVlID0gaXRlbTtcblxuICAgICAgaWYgKHR5cGVvZiBmaWVsZCAhPT0gJ3N0cmluZycgfHwgaXRlbS5oYXNPd25Qcm9wZXJ0eShmaWVsZCkpIHtcbiAgICAgICAgcmV0dXJuIGVzY2FwZSA/IHRoaXMuZXNjYXBlSFRNTChpdGVtW2ZpZWxkXSkgOiBpdGVtW2ZpZWxkXTtcbiAgICAgIH1cblxuICAgICAgdmFyIHByb3BzID0gZmllbGQuc3BsaXQoJy4nKTtcblxuICAgICAgdmFyIF9pdGVyYXRvcjcgPSBfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlcihwcm9wcyksXG4gICAgICAgICAgX3N0ZXA3O1xuXG4gICAgICB0cnkge1xuICAgICAgICBmb3IgKF9pdGVyYXRvcjcucygpOyAhKF9zdGVwNyA9IF9pdGVyYXRvcjcubigpKS5kb25lOykge1xuICAgICAgICAgIHZhciBwID0gX3N0ZXA3LnZhbHVlO1xuICAgICAgICAgIHZhbHVlID0gdmFsdWUgJiYgdmFsdWVbcF07XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBfaXRlcmF0b3I3LmUoZXJyKTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIF9pdGVyYXRvcjcuZigpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZXNjYXBlID8gdGhpcy5lc2NhcGVIVE1MKHZhbHVlKSA6IHZhbHVlO1xuICAgIH0sXG4gICAgaXNJRUJyb3dzZXI6IGZ1bmN0aW9uIGlzSUVCcm93c2VyKCkge1xuICAgICAgcmV0dXJuIG5hdmlnYXRvci51c2VyQWdlbnQuaW5jbHVkZXMoJ01TSUUgJykgfHwgL1RyaWRlbnQuKnJ2OjExXFwuLy50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICAgIH0sXG4gICAgZmluZEluZGV4OiBmdW5jdGlvbiBmaW5kSW5kZXgoaXRlbXMsIGl0ZW0pIHtcbiAgICAgIHZhciBfaXRlcmF0b3I4ID0gX2NyZWF0ZUZvck9mSXRlcmF0b3JIZWxwZXIoaXRlbXMpLFxuICAgICAgICAgIF9zdGVwODtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgZm9yIChfaXRlcmF0b3I4LnMoKTsgIShfc3RlcDggPSBfaXRlcmF0b3I4Lm4oKSkuZG9uZTspIHtcbiAgICAgICAgICB2YXIgaXQgPSBfc3RlcDgudmFsdWU7XG5cbiAgICAgICAgICBpZiAoSlNPTi5zdHJpbmdpZnkoaXQpID09PSBKU09OLnN0cmluZ2lmeShpdGVtKSkge1xuICAgICAgICAgICAgcmV0dXJuIGl0ZW1zLmluZGV4T2YoaXQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIF9pdGVyYXRvcjguZShlcnIpO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgX2l0ZXJhdG9yOC5mKCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAtMTtcbiAgICB9LFxuICAgIHRyVG9EYXRhOiBmdW5jdGlvbiB0clRvRGF0YShjb2x1bW5zLCAkZWxzKSB7XG4gICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICB2YXIgZGF0YSA9IFtdO1xuICAgICAgdmFyIG0gPSBbXTtcbiAgICAgICRlbHMuZWFjaChmdW5jdGlvbiAoeSwgZWwpIHtcbiAgICAgICAgdmFyICRlbCA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlbCk7XG4gICAgICAgIHZhciByb3cgPSB7fTsgLy8gc2F2ZSB0cidzIGlkLCBjbGFzcyBhbmQgZGF0YS0qIGF0dHJpYnV0ZXNcblxuICAgICAgICByb3cuX2lkID0gJGVsLmF0dHIoJ2lkJyk7XG4gICAgICAgIHJvdy5fY2xhc3MgPSAkZWwuYXR0cignY2xhc3MnKTtcbiAgICAgICAgcm93Ll9kYXRhID0gX3RoaXMuZ2V0UmVhbERhdGFBdHRyKCRlbC5kYXRhKCkpO1xuICAgICAgICByb3cuX3N0eWxlID0gJGVsLmF0dHIoJ3N0eWxlJyk7XG4gICAgICAgICRlbC5maW5kKCc+dGQsPnRoJykuZWFjaChmdW5jdGlvbiAoX3gsIGVsKSB7XG4gICAgICAgICAgdmFyICRlbCA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlbCk7XG4gICAgICAgICAgdmFyIGNzcGFuID0gKyRlbC5hdHRyKCdjb2xzcGFuJykgfHwgMTtcbiAgICAgICAgICB2YXIgcnNwYW4gPSArJGVsLmF0dHIoJ3Jvd3NwYW4nKSB8fCAxO1xuICAgICAgICAgIHZhciB4ID0gX3g7IC8vIHNraXAgYWxyZWFkeSBvY2N1cGllZCBjZWxscyBpbiBjdXJyZW50IHJvd1xuXG4gICAgICAgICAgZm9yICg7IG1beV0gJiYgbVt5XVt4XTsgeCsrKSB7Ly8gaWdub3JlXG4gICAgICAgICAgfSAvLyBtYXJrIG1hdHJpeCBlbGVtZW50cyBvY2N1cGllZCBieSBjdXJyZW50IGNlbGwgd2l0aCB0cnVlXG5cblxuICAgICAgICAgIGZvciAodmFyIHR4ID0geDsgdHggPCB4ICsgY3NwYW47IHR4KyspIHtcbiAgICAgICAgICAgIGZvciAodmFyIHR5ID0geTsgdHkgPCB5ICsgcnNwYW47IHR5KyspIHtcbiAgICAgICAgICAgICAgaWYgKCFtW3R5XSkge1xuICAgICAgICAgICAgICAgIC8vIGZpbGwgbWlzc2luZyByb3dzXG4gICAgICAgICAgICAgICAgbVt0eV0gPSBbXTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIG1bdHldW3R4XSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIGZpZWxkID0gY29sdW1uc1t4XS5maWVsZDtcbiAgICAgICAgICByb3dbZmllbGRdID0gJGVsLmh0bWwoKS50cmltKCk7IC8vIHNhdmUgdGQncyBpZCwgY2xhc3MgYW5kIGRhdGEtKiBhdHRyaWJ1dGVzXG5cbiAgICAgICAgICByb3dbXCJfXCIuY29uY2F0KGZpZWxkLCBcIl9pZFwiKV0gPSAkZWwuYXR0cignaWQnKTtcbiAgICAgICAgICByb3dbXCJfXCIuY29uY2F0KGZpZWxkLCBcIl9jbGFzc1wiKV0gPSAkZWwuYXR0cignY2xhc3MnKTtcbiAgICAgICAgICByb3dbXCJfXCIuY29uY2F0KGZpZWxkLCBcIl9yb3dzcGFuXCIpXSA9ICRlbC5hdHRyKCdyb3dzcGFuJyk7XG4gICAgICAgICAgcm93W1wiX1wiLmNvbmNhdChmaWVsZCwgXCJfY29sc3BhblwiKV0gPSAkZWwuYXR0cignY29sc3BhbicpO1xuICAgICAgICAgIHJvd1tcIl9cIi5jb25jYXQoZmllbGQsIFwiX3RpdGxlXCIpXSA9ICRlbC5hdHRyKCd0aXRsZScpO1xuICAgICAgICAgIHJvd1tcIl9cIi5jb25jYXQoZmllbGQsIFwiX2RhdGFcIildID0gX3RoaXMuZ2V0UmVhbERhdGFBdHRyKCRlbC5kYXRhKCkpO1xuICAgICAgICAgIHJvd1tcIl9cIi5jb25jYXQoZmllbGQsIFwiX3N0eWxlXCIpXSA9ICRlbC5hdHRyKCdzdHlsZScpO1xuICAgICAgICB9KTtcbiAgICAgICAgZGF0YS5wdXNoKHJvdyk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH0sXG4gICAgc29ydDogZnVuY3Rpb24gc29ydChhLCBiLCBvcmRlciwgc29ydFN0YWJsZSwgYVBvc2l0aW9uLCBiUG9zaXRpb24pIHtcbiAgICAgIGlmIChhID09PSB1bmRlZmluZWQgfHwgYSA9PT0gbnVsbCkge1xuICAgICAgICBhID0gJyc7XG4gICAgICB9XG5cbiAgICAgIGlmIChiID09PSB1bmRlZmluZWQgfHwgYiA9PT0gbnVsbCkge1xuICAgICAgICBiID0gJyc7XG4gICAgICB9XG5cbiAgICAgIGlmIChzb3J0U3RhYmxlICYmIGEgPT09IGIpIHtcbiAgICAgICAgYSA9IGFQb3NpdGlvbjtcbiAgICAgICAgYiA9IGJQb3NpdGlvbjtcbiAgICAgIH0gLy8gSWYgYm90aCB2YWx1ZXMgYXJlIG51bWVyaWMsIGRvIGEgbnVtZXJpYyBjb21wYXJpc29uXG5cblxuICAgICAgaWYgKHRoaXMuaXNOdW1lcmljKGEpICYmIHRoaXMuaXNOdW1lcmljKGIpKSB7XG4gICAgICAgIC8vIENvbnZlcnQgbnVtZXJpY2FsIHZhbHVlcyBmb3JtIHN0cmluZyB0byBmbG9hdC5cbiAgICAgICAgYSA9IHBhcnNlRmxvYXQoYSk7XG4gICAgICAgIGIgPSBwYXJzZUZsb2F0KGIpO1xuXG4gICAgICAgIGlmIChhIDwgYikge1xuICAgICAgICAgIHJldHVybiBvcmRlciAqIC0xO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGEgPiBiKSB7XG4gICAgICAgICAgcmV0dXJuIG9yZGVyO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgICB9XG5cbiAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfSAvLyBJZiB2YWx1ZSBpcyBub3QgYSBzdHJpbmcsIGNvbnZlcnQgdG8gc3RyaW5nXG5cblxuICAgICAgaWYgKHR5cGVvZiBhICE9PSAnc3RyaW5nJykge1xuICAgICAgICBhID0gYS50b1N0cmluZygpO1xuICAgICAgfVxuXG4gICAgICBpZiAoYS5sb2NhbGVDb21wYXJlKGIpID09PSAtMSkge1xuICAgICAgICByZXR1cm4gb3JkZXIgKiAtMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG9yZGVyO1xuICAgIH0sXG4gICAgZ2V0RXZlbnROYW1lOiBmdW5jdGlvbiBnZXRFdmVudE5hbWUoZXZlbnRQcmVmaXgpIHtcbiAgICAgIHZhciBpZCA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogJyc7XG4gICAgICBpZCA9IGlkIHx8IFwiXCIuY29uY2F0KCtuZXcgRGF0ZSgpKS5jb25jYXQofn4oTWF0aC5yYW5kb20oKSAqIDEwMDAwMDApKTtcbiAgICAgIHJldHVybiBcIlwiLmNvbmNhdChldmVudFByZWZpeCwgXCItXCIpLmNvbmNhdChpZCk7XG4gICAgfSxcbiAgICBoYXNEZXRhaWxWaWV3SWNvbjogZnVuY3Rpb24gaGFzRGV0YWlsVmlld0ljb24ob3B0aW9ucykge1xuICAgICAgcmV0dXJuIG9wdGlvbnMuZGV0YWlsVmlldyAmJiBvcHRpb25zLmRldGFpbFZpZXdJY29uICYmICFvcHRpb25zLmNhcmRWaWV3O1xuICAgIH0sXG4gICAgZ2V0RGV0YWlsVmlld0luZGV4T2Zmc2V0OiBmdW5jdGlvbiBnZXREZXRhaWxWaWV3SW5kZXhPZmZzZXQob3B0aW9ucykge1xuICAgICAgcmV0dXJuIHRoaXMuaGFzRGV0YWlsVmlld0ljb24ob3B0aW9ucykgJiYgb3B0aW9ucy5kZXRhaWxWaWV3QWxpZ24gIT09ICdyaWdodCcgPyAxIDogMDtcbiAgICB9LFxuICAgIGNoZWNrQXV0b01lcmdlQ2VsbHM6IGZ1bmN0aW9uIGNoZWNrQXV0b01lcmdlQ2VsbHMoZGF0YSkge1xuICAgICAgdmFyIF9pdGVyYXRvcjkgPSBfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlcihkYXRhKSxcbiAgICAgICAgICBfc3RlcDk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGZvciAoX2l0ZXJhdG9yOS5zKCk7ICEoX3N0ZXA5ID0gX2l0ZXJhdG9yOS5uKCkpLmRvbmU7KSB7XG4gICAgICAgICAgdmFyIHJvdyA9IF9zdGVwOS52YWx1ZTtcblxuICAgICAgICAgIGZvciAodmFyIF9pNCA9IDAsIF9PYmplY3Qka2V5cyA9IE9iamVjdC5rZXlzKHJvdyk7IF9pNCA8IF9PYmplY3Qka2V5cy5sZW5ndGg7IF9pNCsrKSB7XG4gICAgICAgICAgICB2YXIga2V5ID0gX09iamVjdCRrZXlzW19pNF07XG5cbiAgICAgICAgICAgIGlmIChrZXkuc3RhcnRzV2l0aCgnXycpICYmIChrZXkuZW5kc1dpdGgoJ19yb3dzcGFuJykgfHwga2V5LmVuZHNXaXRoKCdfY29sc3BhbicpKSkge1xuICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBfaXRlcmF0b3I5LmUoZXJyKTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIF9pdGVyYXRvcjkuZigpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBkZWVwQ29weTogZnVuY3Rpb24gZGVlcENvcHkoYXJnKSB7XG4gICAgICBpZiAoYXJnID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIGFyZztcbiAgICAgIH1cblxuICAgICAgcmV0dXJuICRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5leHRlbmQodHJ1ZSwgQXJyYXkuaXNBcnJheShhcmcpID8gW10gOiB7fSwgYXJnKTtcbiAgICB9XG4gIH07XG5cbiAgdmFyIEJMT0NLX1JPV1MgPSA1MDtcbiAgdmFyIENMVVNURVJfQkxPQ0tTID0gNDtcblxuICB2YXIgVmlydHVhbFNjcm9sbCA9IC8qI19fUFVSRV9fKi9mdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gVmlydHVhbFNjcm9sbChvcHRpb25zKSB7XG4gICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgVmlydHVhbFNjcm9sbCk7XG5cbiAgICAgIHRoaXMucm93cyA9IG9wdGlvbnMucm93cztcbiAgICAgIHRoaXMuc2Nyb2xsRWwgPSBvcHRpb25zLnNjcm9sbEVsO1xuICAgICAgdGhpcy5jb250ZW50RWwgPSBvcHRpb25zLmNvbnRlbnRFbDtcbiAgICAgIHRoaXMuY2FsbGJhY2sgPSBvcHRpb25zLmNhbGxiYWNrO1xuICAgICAgdGhpcy5pdGVtSGVpZ2h0ID0gb3B0aW9ucy5pdGVtSGVpZ2h0O1xuICAgICAgdGhpcy5jYWNoZSA9IHt9O1xuICAgICAgdGhpcy5zY3JvbGxUb3AgPSB0aGlzLnNjcm9sbEVsLnNjcm9sbFRvcDtcbiAgICAgIHRoaXMuaW5pdERPTSh0aGlzLnJvd3MsIG9wdGlvbnMuZml4ZWRTY3JvbGwpO1xuICAgICAgdGhpcy5zY3JvbGxFbC5zY3JvbGxUb3AgPSB0aGlzLnNjcm9sbFRvcDtcbiAgICAgIHRoaXMubGFzdENsdXN0ZXIgPSAwO1xuXG4gICAgICB2YXIgb25TY3JvbGwgPSBmdW5jdGlvbiBvblNjcm9sbCgpIHtcbiAgICAgICAgaWYgKF90aGlzLmxhc3RDbHVzdGVyICE9PSAoX3RoaXMubGFzdENsdXN0ZXIgPSBfdGhpcy5nZXROdW0oKSkpIHtcbiAgICAgICAgICBfdGhpcy5pbml0RE9NKF90aGlzLnJvd3MpO1xuXG4gICAgICAgICAgX3RoaXMuY2FsbGJhY2soKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgdGhpcy5zY3JvbGxFbC5hZGRFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBvblNjcm9sbCwgZmFsc2UpO1xuXG4gICAgICB0aGlzLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIF90aGlzLmNvbnRlbnRFbC5pbm5lckh0bWwgPSAnJztcblxuICAgICAgICBfdGhpcy5zY3JvbGxFbC5yZW1vdmVFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBvblNjcm9sbCwgZmFsc2UpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBfY3JlYXRlQ2xhc3MoVmlydHVhbFNjcm9sbCwgW3tcbiAgICAgIGtleTogXCJpbml0RE9NXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaW5pdERPTShyb3dzLCBmaXhlZFNjcm9sbCkge1xuICAgICAgICBpZiAodHlwZW9mIHRoaXMuY2x1c3RlckhlaWdodCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICB0aGlzLmNhY2hlLnNjcm9sbFRvcCA9IHRoaXMuc2Nyb2xsRWwuc2Nyb2xsVG9wO1xuICAgICAgICAgIHRoaXMuY2FjaGUuZGF0YSA9IHRoaXMuY29udGVudEVsLmlubmVySFRNTCA9IHJvd3NbMF0gKyByb3dzWzBdICsgcm93c1swXTtcbiAgICAgICAgICB0aGlzLmdldFJvd3NIZWlnaHQocm93cyk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZGF0YSA9IHRoaXMuaW5pdERhdGEocm93cywgdGhpcy5nZXROdW0oZml4ZWRTY3JvbGwpKTtcbiAgICAgICAgdmFyIHRoaXNSb3dzID0gZGF0YS5yb3dzLmpvaW4oJycpO1xuICAgICAgICB2YXIgZGF0YUNoYW5nZWQgPSB0aGlzLmNoZWNrQ2hhbmdlcygnZGF0YScsIHRoaXNSb3dzKTtcbiAgICAgICAgdmFyIHRvcE9mZnNldENoYW5nZWQgPSB0aGlzLmNoZWNrQ2hhbmdlcygndG9wJywgZGF0YS50b3BPZmZzZXQpO1xuICAgICAgICB2YXIgYm90dG9tT2Zmc2V0Q2hhbmdlZCA9IHRoaXMuY2hlY2tDaGFuZ2VzKCdib3R0b20nLCBkYXRhLmJvdHRvbU9mZnNldCk7XG4gICAgICAgIHZhciBodG1sID0gW107XG5cbiAgICAgICAgaWYgKGRhdGFDaGFuZ2VkICYmIHRvcE9mZnNldENoYW5nZWQpIHtcbiAgICAgICAgICBpZiAoZGF0YS50b3BPZmZzZXQpIHtcbiAgICAgICAgICAgIGh0bWwucHVzaCh0aGlzLmdldEV4dHJhKCd0b3AnLCBkYXRhLnRvcE9mZnNldCkpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGh0bWwucHVzaCh0aGlzUm93cyk7XG5cbiAgICAgICAgICBpZiAoZGF0YS5ib3R0b21PZmZzZXQpIHtcbiAgICAgICAgICAgIGh0bWwucHVzaCh0aGlzLmdldEV4dHJhKCdib3R0b20nLCBkYXRhLmJvdHRvbU9mZnNldCkpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuY29udGVudEVsLmlubmVySFRNTCA9IGh0bWwuam9pbignJyk7XG5cbiAgICAgICAgICBpZiAoZml4ZWRTY3JvbGwpIHtcbiAgICAgICAgICAgIHRoaXMuY29udGVudEVsLnNjcm9sbFRvcCA9IHRoaXMuY2FjaGUuc2Nyb2xsVG9wO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChib3R0b21PZmZzZXRDaGFuZ2VkKSB7XG4gICAgICAgICAgdGhpcy5jb250ZW50RWwubGFzdENoaWxkLnN0eWxlLmhlaWdodCA9IFwiXCIuY29uY2F0KGRhdGEuYm90dG9tT2Zmc2V0LCBcInB4XCIpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImdldFJvd3NIZWlnaHRcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRSb3dzSGVpZ2h0KCkge1xuICAgICAgICBpZiAodHlwZW9mIHRoaXMuaXRlbUhlaWdodCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICB2YXIgbm9kZXMgPSB0aGlzLmNvbnRlbnRFbC5jaGlsZHJlbjtcbiAgICAgICAgICB2YXIgbm9kZSA9IG5vZGVzW01hdGguZmxvb3Iobm9kZXMubGVuZ3RoIC8gMildO1xuICAgICAgICAgIHRoaXMuaXRlbUhlaWdodCA9IG5vZGUub2Zmc2V0SGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5ibG9ja0hlaWdodCA9IHRoaXMuaXRlbUhlaWdodCAqIEJMT0NLX1JPV1M7XG4gICAgICAgIHRoaXMuY2x1c3RlclJvd3MgPSBCTE9DS19ST1dTICogQ0xVU1RFUl9CTE9DS1M7XG4gICAgICAgIHRoaXMuY2x1c3RlckhlaWdodCA9IHRoaXMuYmxvY2tIZWlnaHQgKiBDTFVTVEVSX0JMT0NLUztcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiZ2V0TnVtXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0TnVtKGZpeGVkU2Nyb2xsKSB7XG4gICAgICAgIHRoaXMuc2Nyb2xsVG9wID0gZml4ZWRTY3JvbGwgPyB0aGlzLmNhY2hlLnNjcm9sbFRvcCA6IHRoaXMuc2Nyb2xsRWwuc2Nyb2xsVG9wO1xuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcih0aGlzLnNjcm9sbFRvcCAvICh0aGlzLmNsdXN0ZXJIZWlnaHQgLSB0aGlzLmJsb2NrSGVpZ2h0KSkgfHwgMDtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiaW5pdERhdGFcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0RGF0YShyb3dzLCBudW0pIHtcbiAgICAgICAgaWYgKHJvd3MubGVuZ3RoIDwgQkxPQ0tfUk9XUykge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB0b3BPZmZzZXQ6IDAsXG4gICAgICAgICAgICBib3R0b21PZmZzZXQ6IDAsXG4gICAgICAgICAgICByb3dzQWJvdmU6IDAsXG4gICAgICAgICAgICByb3dzOiByb3dzXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzdGFydCA9IE1hdGgubWF4KCh0aGlzLmNsdXN0ZXJSb3dzIC0gQkxPQ0tfUk9XUykgKiBudW0sIDApO1xuICAgICAgICB2YXIgZW5kID0gc3RhcnQgKyB0aGlzLmNsdXN0ZXJSb3dzO1xuICAgICAgICB2YXIgdG9wT2Zmc2V0ID0gTWF0aC5tYXgoc3RhcnQgKiB0aGlzLml0ZW1IZWlnaHQsIDApO1xuICAgICAgICB2YXIgYm90dG9tT2Zmc2V0ID0gTWF0aC5tYXgoKHJvd3MubGVuZ3RoIC0gZW5kKSAqIHRoaXMuaXRlbUhlaWdodCwgMCk7XG4gICAgICAgIHZhciB0aGlzUm93cyA9IFtdO1xuICAgICAgICB2YXIgcm93c0Fib3ZlID0gc3RhcnQ7XG5cbiAgICAgICAgaWYgKHRvcE9mZnNldCA8IDEpIHtcbiAgICAgICAgICByb3dzQWJvdmUrKztcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgICAgICAgcm93c1tpXSAmJiB0aGlzUm93cy5wdXNoKHJvd3NbaV0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0b3BPZmZzZXQ6IHRvcE9mZnNldCxcbiAgICAgICAgICBib3R0b21PZmZzZXQ6IGJvdHRvbU9mZnNldCxcbiAgICAgICAgICByb3dzQWJvdmU6IHJvd3NBYm92ZSxcbiAgICAgICAgICByb3dzOiB0aGlzUm93c1xuICAgICAgICB9O1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJjaGVja0NoYW5nZXNcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBjaGVja0NoYW5nZXModHlwZSwgdmFsdWUpIHtcbiAgICAgICAgdmFyIGNoYW5nZWQgPSB2YWx1ZSAhPT0gdGhpcy5jYWNoZVt0eXBlXTtcbiAgICAgICAgdGhpcy5jYWNoZVt0eXBlXSA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gY2hhbmdlZDtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiZ2V0RXh0cmFcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRFeHRyYShjbGFzc05hbWUsIGhlaWdodCkge1xuICAgICAgICB2YXIgdGFnID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndHInKTtcbiAgICAgICAgdGFnLmNsYXNzTmFtZSA9IFwidmlydHVhbC1zY3JvbGwtXCIuY29uY2F0KGNsYXNzTmFtZSk7XG5cbiAgICAgICAgaWYgKGhlaWdodCkge1xuICAgICAgICAgIHRhZy5zdHlsZS5oZWlnaHQgPSBcIlwiLmNvbmNhdChoZWlnaHQsIFwicHhcIik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGFnLm91dGVySFRNTDtcbiAgICAgIH1cbiAgICB9XSk7XG5cbiAgICByZXR1cm4gVmlydHVhbFNjcm9sbDtcbiAgfSgpO1xuXG4gIHZhciBCb290c3RyYXBUYWJsZSA9IC8qI19fUFVSRV9fKi9mdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQm9vdHN0cmFwVGFibGUoZWwsIG9wdGlvbnMpIHtcbiAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBCb290c3RyYXBUYWJsZSk7XG5cbiAgICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgICB0aGlzLiRlbCA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlbCk7XG4gICAgICB0aGlzLiRlbF8gPSB0aGlzLiRlbC5jbG9uZSgpO1xuICAgICAgdGhpcy50aW1lb3V0SWRfID0gMDtcbiAgICAgIHRoaXMudGltZW91dEZvb3Rlcl8gPSAwO1xuICAgIH1cblxuICAgIF9jcmVhdGVDbGFzcyhCb290c3RyYXBUYWJsZSwgW3tcbiAgICAgIGtleTogXCJpbml0XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaW5pdCgpIHtcbiAgICAgICAgdGhpcy5pbml0Q29uc3RhbnRzKCk7XG4gICAgICAgIHRoaXMuaW5pdExvY2FsZSgpO1xuICAgICAgICB0aGlzLmluaXRDb250YWluZXIoKTtcbiAgICAgICAgdGhpcy5pbml0VGFibGUoKTtcbiAgICAgICAgdGhpcy5pbml0SGVhZGVyKCk7XG4gICAgICAgIHRoaXMuaW5pdERhdGEoKTtcbiAgICAgICAgdGhpcy5pbml0SGlkZGVuUm93cygpO1xuICAgICAgICB0aGlzLmluaXRUb29sYmFyKCk7XG4gICAgICAgIHRoaXMuaW5pdFBhZ2luYXRpb24oKTtcbiAgICAgICAgdGhpcy5pbml0Qm9keSgpO1xuICAgICAgICB0aGlzLmluaXRTZWFyY2hUZXh0KCk7XG4gICAgICAgIHRoaXMuaW5pdFNlcnZlcigpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJpbml0Q29uc3RhbnRzXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaW5pdENvbnN0YW50cygpIHtcbiAgICAgICAgdmFyIG9wdHMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIHRoaXMuY29uc3RhbnRzID0gQ29uc3RhbnRzLkNPTlNUQU5UUztcbiAgICAgICAgdGhpcy5jb25zdGFudHMudGhlbWUgPSAkX19kZWZhdWx0WydkZWZhdWx0J10uZm4uYm9vdHN0cmFwVGFibGUudGhlbWU7XG4gICAgICAgIHRoaXMuY29uc3RhbnRzLmRhdGFUb2dnbGUgPSB0aGlzLmNvbnN0YW50cy5odG1sLmRhdGFUb2dnbGUgfHwgJ2RhdGEtdG9nZ2xlJztcbiAgICAgICAgdmFyIGJ1dHRvbnNQcmVmaXggPSBvcHRzLmJ1dHRvbnNQcmVmaXggPyBcIlwiLmNvbmNhdChvcHRzLmJ1dHRvbnNQcmVmaXgsIFwiLVwiKSA6ICcnO1xuICAgICAgICB0aGlzLmNvbnN0YW50cy5idXR0b25zQ2xhc3MgPSBbb3B0cy5idXR0b25zUHJlZml4LCBidXR0b25zUHJlZml4ICsgb3B0cy5idXR0b25zQ2xhc3MsIFV0aWxzLnNwcmludGYoXCJcIi5jb25jYXQoYnV0dG9uc1ByZWZpeCwgXCIlc1wiKSwgb3B0cy5pY29uU2l6ZSldLmpvaW4oJyAnKS50cmltKCk7XG4gICAgICAgIHRoaXMuYnV0dG9ucyA9IFV0aWxzLmNhbGN1bGF0ZU9iamVjdFZhbHVlKHRoaXMsIG9wdHMuYnV0dG9ucywgW10sIHt9KTtcblxuICAgICAgICBpZiAoX3R5cGVvZih0aGlzLmJ1dHRvbnMpICE9PSAnb2JqZWN0Jykge1xuICAgICAgICAgIHRoaXMuYnV0dG9ucyA9IHt9O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBvcHRzLmljb25zID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIG9wdHMuaWNvbnMgPSBVdGlscy5jYWxjdWxhdGVPYmplY3RWYWx1ZShudWxsLCBvcHRzLmljb25zKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJpbml0TG9jYWxlXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaW5pdExvY2FsZSgpIHtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5sb2NhbGUpIHtcbiAgICAgICAgICB2YXIgbG9jYWxlcyA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5mbi5ib290c3RyYXBUYWJsZS5sb2NhbGVzO1xuICAgICAgICAgIHZhciBwYXJ0cyA9IHRoaXMub3B0aW9ucy5sb2NhbGUuc3BsaXQoLy18Xy8pO1xuICAgICAgICAgIHBhcnRzWzBdID0gcGFydHNbMF0udG9Mb3dlckNhc2UoKTtcblxuICAgICAgICAgIGlmIChwYXJ0c1sxXSkge1xuICAgICAgICAgICAgcGFydHNbMV0gPSBwYXJ0c1sxXS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChsb2NhbGVzW3RoaXMub3B0aW9ucy5sb2NhbGVdKSB7XG4gICAgICAgICAgICAkX19kZWZhdWx0WydkZWZhdWx0J10uZXh0ZW5kKHRoaXMub3B0aW9ucywgbG9jYWxlc1t0aGlzLm9wdGlvbnMubG9jYWxlXSk7XG4gICAgICAgICAgfSBlbHNlIGlmIChsb2NhbGVzW3BhcnRzLmpvaW4oJy0nKV0pIHtcbiAgICAgICAgICAgICRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5leHRlbmQodGhpcy5vcHRpb25zLCBsb2NhbGVzW3BhcnRzLmpvaW4oJy0nKV0pO1xuICAgICAgICAgIH0gZWxzZSBpZiAobG9jYWxlc1twYXJ0c1swXV0pIHtcbiAgICAgICAgICAgICRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5leHRlbmQodGhpcy5vcHRpb25zLCBsb2NhbGVzW3BhcnRzWzBdXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImluaXRDb250YWluZXJcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0Q29udGFpbmVyKCkge1xuICAgICAgICB2YXIgdG9wUGFnaW5hdGlvbiA9IFsndG9wJywgJ2JvdGgnXS5pbmNsdWRlcyh0aGlzLm9wdGlvbnMucGFnaW5hdGlvblZBbGlnbikgPyAnPGRpdiBjbGFzcz1cImZpeGVkLXRhYmxlLXBhZ2luYXRpb24gY2xlYXJmaXhcIj48L2Rpdj4nIDogJyc7XG4gICAgICAgIHZhciBib3R0b21QYWdpbmF0aW9uID0gWydib3R0b20nLCAnYm90aCddLmluY2x1ZGVzKHRoaXMub3B0aW9ucy5wYWdpbmF0aW9uVkFsaWduKSA/ICc8ZGl2IGNsYXNzPVwiZml4ZWQtdGFibGUtcGFnaW5hdGlvblwiPjwvZGl2PicgOiAnJztcbiAgICAgICAgdmFyIGxvYWRpbmdUZW1wbGF0ZSA9IFV0aWxzLmNhbGN1bGF0ZU9iamVjdFZhbHVlKHRoaXMub3B0aW9ucywgdGhpcy5vcHRpb25zLmxvYWRpbmdUZW1wbGF0ZSwgW3RoaXMub3B0aW9ucy5mb3JtYXRMb2FkaW5nTWVzc2FnZSgpXSk7XG4gICAgICAgIHRoaXMuJGNvbnRhaW5lciA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShcIlxcbiAgICAgIDxkaXYgY2xhc3M9XFxcImJvb3RzdHJhcC10YWJsZSBcIi5jb25jYXQodGhpcy5jb25zdGFudHMudGhlbWUsIFwiXFxcIj5cXG4gICAgICA8ZGl2IGNsYXNzPVxcXCJmaXhlZC10YWJsZS10b29sYmFyXFxcIj48L2Rpdj5cXG4gICAgICBcIikuY29uY2F0KHRvcFBhZ2luYXRpb24sIFwiXFxuICAgICAgPGRpdiBjbGFzcz1cXFwiZml4ZWQtdGFibGUtY29udGFpbmVyXFxcIj5cXG4gICAgICA8ZGl2IGNsYXNzPVxcXCJmaXhlZC10YWJsZS1oZWFkZXJcXFwiPjx0YWJsZT48L3RhYmxlPjwvZGl2PlxcbiAgICAgIDxkaXYgY2xhc3M9XFxcImZpeGVkLXRhYmxlLWJvZHlcXFwiPlxcbiAgICAgIDxkaXYgY2xhc3M9XFxcImZpeGVkLXRhYmxlLWxvYWRpbmdcXFwiPlxcbiAgICAgIFwiKS5jb25jYXQobG9hZGluZ1RlbXBsYXRlLCBcIlxcbiAgICAgIDwvZGl2PlxcbiAgICAgIDwvZGl2PlxcbiAgICAgIDxkaXYgY2xhc3M9XFxcImZpeGVkLXRhYmxlLWZvb3RlclxcXCI+PC9kaXY+XFxuICAgICAgPC9kaXY+XFxuICAgICAgXCIpLmNvbmNhdChib3R0b21QYWdpbmF0aW9uLCBcIlxcbiAgICAgIDwvZGl2PlxcbiAgICBcIikpO1xuICAgICAgICB0aGlzLiRjb250YWluZXIuaW5zZXJ0QWZ0ZXIodGhpcy4kZWwpO1xuICAgICAgICB0aGlzLiR0YWJsZUNvbnRhaW5lciA9IHRoaXMuJGNvbnRhaW5lci5maW5kKCcuZml4ZWQtdGFibGUtY29udGFpbmVyJyk7XG4gICAgICAgIHRoaXMuJHRhYmxlSGVhZGVyID0gdGhpcy4kY29udGFpbmVyLmZpbmQoJy5maXhlZC10YWJsZS1oZWFkZXInKTtcbiAgICAgICAgdGhpcy4kdGFibGVCb2R5ID0gdGhpcy4kY29udGFpbmVyLmZpbmQoJy5maXhlZC10YWJsZS1ib2R5Jyk7XG4gICAgICAgIHRoaXMuJHRhYmxlTG9hZGluZyA9IHRoaXMuJGNvbnRhaW5lci5maW5kKCcuZml4ZWQtdGFibGUtbG9hZGluZycpO1xuICAgICAgICB0aGlzLiR0YWJsZUZvb3RlciA9IHRoaXMuJGVsLmZpbmQoJ3Rmb290Jyk7IC8vIGNoZWNraW5nIGlmIGN1c3RvbSB0YWJsZS10b29sYmFyIGV4aXN0cyBvciBub3RcblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLmJ1dHRvbnNUb29sYmFyKSB7XG4gICAgICAgICAgdGhpcy4kdG9vbGJhciA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXSgnYm9keScpLmZpbmQodGhpcy5vcHRpb25zLmJ1dHRvbnNUb29sYmFyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLiR0b29sYmFyID0gdGhpcy4kY29udGFpbmVyLmZpbmQoJy5maXhlZC10YWJsZS10b29sYmFyJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLiRwYWdpbmF0aW9uID0gdGhpcy4kY29udGFpbmVyLmZpbmQoJy5maXhlZC10YWJsZS1wYWdpbmF0aW9uJyk7XG4gICAgICAgIHRoaXMuJHRhYmxlQm9keS5hcHBlbmQodGhpcy4kZWwpO1xuICAgICAgICB0aGlzLiRjb250YWluZXIuYWZ0ZXIoJzxkaXYgY2xhc3M9XCJjbGVhcmZpeFwiPjwvZGl2PicpO1xuICAgICAgICB0aGlzLiRlbC5hZGRDbGFzcyh0aGlzLm9wdGlvbnMuY2xhc3Nlcyk7XG4gICAgICAgIHRoaXMuJHRhYmxlTG9hZGluZy5hZGRDbGFzcyh0aGlzLm9wdGlvbnMuY2xhc3Nlcyk7XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5oZWlnaHQpIHtcbiAgICAgICAgICB0aGlzLiR0YWJsZUNvbnRhaW5lci5hZGRDbGFzcygnZml4ZWQtaGVpZ2h0Jyk7XG5cbiAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNob3dGb290ZXIpIHtcbiAgICAgICAgICAgIHRoaXMuJHRhYmxlQ29udGFpbmVyLmFkZENsYXNzKCdoYXMtZm9vdGVyJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5jbGFzc2VzLnNwbGl0KCcgJykuaW5jbHVkZXMoJ3RhYmxlLWJvcmRlcmVkJykpIHtcbiAgICAgICAgICAgIHRoaXMuJHRhYmxlQm9keS5hcHBlbmQoJzxkaXYgY2xhc3M9XCJmaXhlZC10YWJsZS1ib3JkZXJcIj48L2Rpdj4nKTtcbiAgICAgICAgICAgIHRoaXMuJHRhYmxlQm9yZGVyID0gdGhpcy4kdGFibGVCb2R5LmZpbmQoJy5maXhlZC10YWJsZS1ib3JkZXInKTtcbiAgICAgICAgICAgIHRoaXMuJHRhYmxlTG9hZGluZy5hZGRDbGFzcygnZml4ZWQtdGFibGUtYm9yZGVyJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy4kdGFibGVGb290ZXIgPSB0aGlzLiRjb250YWluZXIuZmluZCgnLmZpeGVkLXRhYmxlLWZvb3RlcicpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImluaXRUYWJsZVwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGluaXRUYWJsZSgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgICB2YXIgY29sdW1ucyA9IFtdO1xuICAgICAgICB0aGlzLiRoZWFkZXIgPSB0aGlzLiRlbC5maW5kKCc+dGhlYWQnKTtcblxuICAgICAgICBpZiAoIXRoaXMuJGhlYWRlci5sZW5ndGgpIHtcbiAgICAgICAgICB0aGlzLiRoZWFkZXIgPSAkX19kZWZhdWx0WydkZWZhdWx0J10oXCI8dGhlYWQgY2xhc3M9XFxcIlwiLmNvbmNhdCh0aGlzLm9wdGlvbnMudGhlYWRDbGFzc2VzLCBcIlxcXCI+PC90aGVhZD5cIikpLmFwcGVuZFRvKHRoaXMuJGVsKTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLm9wdGlvbnMudGhlYWRDbGFzc2VzKSB7XG4gICAgICAgICAgdGhpcy4kaGVhZGVyLmFkZENsYXNzKHRoaXMub3B0aW9ucy50aGVhZENsYXNzZXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5faGVhZGVyVHJDbGFzc2VzID0gW107XG4gICAgICAgIHRoaXMuX2hlYWRlclRyU3R5bGVzID0gW107XG4gICAgICAgIHRoaXMuJGhlYWRlci5maW5kKCd0cicpLmVhY2goZnVuY3Rpb24gKGksIGVsKSB7XG4gICAgICAgICAgdmFyICR0ciA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlbCk7XG4gICAgICAgICAgdmFyIGNvbHVtbiA9IFtdO1xuICAgICAgICAgICR0ci5maW5kKCd0aCcpLmVhY2goZnVuY3Rpb24gKGksIGVsKSB7XG4gICAgICAgICAgICB2YXIgJHRoID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKTsgLy8gIzIwMTQ6IGdldEZpZWxkSW5kZXggYW5kIGVsc2V3aGVyZSBhc3N1bWUgdGhpcyBpcyBzdHJpbmcsIGNhdXNlcyBpc3N1ZXMgaWYgbm90XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgJHRoLmRhdGEoJ2ZpZWxkJykgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICR0aC5kYXRhKCdmaWVsZCcsIFwiXCIuY29uY2F0KCR0aC5kYXRhKCdmaWVsZCcpKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbHVtbi5wdXNoKCRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5leHRlbmQoe30sIHtcbiAgICAgICAgICAgICAgdGl0bGU6ICR0aC5odG1sKCksXG4gICAgICAgICAgICAgIGNsYXNzOiAkdGguYXR0cignY2xhc3MnKSxcbiAgICAgICAgICAgICAgdGl0bGVUb29sdGlwOiAkdGguYXR0cigndGl0bGUnKSxcbiAgICAgICAgICAgICAgcm93c3BhbjogJHRoLmF0dHIoJ3Jvd3NwYW4nKSA/ICskdGguYXR0cigncm93c3BhbicpIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICBjb2xzcGFuOiAkdGguYXR0cignY29sc3BhbicpID8gKyR0aC5hdHRyKCdjb2xzcGFuJykgOiB1bmRlZmluZWRcbiAgICAgICAgICAgIH0sICR0aC5kYXRhKCkpKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBjb2x1bW5zLnB1c2goY29sdW1uKTtcblxuICAgICAgICAgIGlmICgkdHIuYXR0cignY2xhc3MnKSkge1xuICAgICAgICAgICAgX3RoaXMuX2hlYWRlclRyQ2xhc3Nlcy5wdXNoKCR0ci5hdHRyKCdjbGFzcycpKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoJHRyLmF0dHIoJ3N0eWxlJykpIHtcbiAgICAgICAgICAgIF90aGlzLl9oZWFkZXJUclN0eWxlcy5wdXNoKCR0ci5hdHRyKCdzdHlsZScpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICghQXJyYXkuaXNBcnJheSh0aGlzLm9wdGlvbnMuY29sdW1uc1swXSkpIHtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMuY29sdW1ucyA9IFt0aGlzLm9wdGlvbnMuY29sdW1uc107XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm9wdGlvbnMuY29sdW1ucyA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5leHRlbmQodHJ1ZSwgW10sIGNvbHVtbnMsIHRoaXMub3B0aW9ucy5jb2x1bW5zKTtcbiAgICAgICAgdGhpcy5jb2x1bW5zID0gW107XG4gICAgICAgIHRoaXMuZmllbGRzQ29sdW1uc0luZGV4ID0gW107XG4gICAgICAgIFV0aWxzLnNldEZpZWxkSW5kZXgodGhpcy5vcHRpb25zLmNvbHVtbnMpO1xuICAgICAgICB0aGlzLm9wdGlvbnMuY29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW5zLCBpKSB7XG4gICAgICAgICAgY29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChfY29sdW1uLCBqKSB7XG4gICAgICAgICAgICB2YXIgY29sdW1uID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddLmV4dGVuZCh7fSwgQm9vdHN0cmFwVGFibGUuQ09MVU1OX0RFRkFVTFRTLCBfY29sdW1uKTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBjb2x1bW4uZmllbGRJbmRleCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgX3RoaXMuY29sdW1uc1tjb2x1bW4uZmllbGRJbmRleF0gPSBjb2x1bW47XG4gICAgICAgICAgICAgIF90aGlzLmZpZWxkc0NvbHVtbnNJbmRleFtjb2x1bW4uZmllbGRdID0gY29sdW1uLmZpZWxkSW5kZXg7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIF90aGlzLm9wdGlvbnMuY29sdW1uc1tpXVtqXSA9IGNvbHVtbjtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7IC8vIGlmIG9wdGlvbnMuZGF0YSBpcyBzZXR0aW5nLCBkbyBub3QgcHJvY2VzcyB0Ym9keSBhbmQgdGZvb3QgZGF0YVxuXG4gICAgICAgIGlmICghdGhpcy5vcHRpb25zLmRhdGEubGVuZ3RoKSB7XG4gICAgICAgICAgdmFyIGh0bWxEYXRhID0gVXRpbHMudHJUb0RhdGEodGhpcy5jb2x1bW5zLCB0aGlzLiRlbC5maW5kKCc+dGJvZHk+dHInKSk7XG5cbiAgICAgICAgICBpZiAoaHRtbERhdGEubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aGlzLm9wdGlvbnMuZGF0YSA9IGh0bWxEYXRhO1xuICAgICAgICAgICAgdGhpcy5mcm9tSHRtbCA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEodGhpcy5vcHRpb25zLnBhZ2luYXRpb24gJiYgdGhpcy5vcHRpb25zLnNpZGVQYWdpbmF0aW9uICE9PSAnc2VydmVyJykpIHtcbiAgICAgICAgICB0aGlzLmZvb3RlckRhdGEgPSBVdGlscy50clRvRGF0YSh0aGlzLmNvbHVtbnMsIHRoaXMuJGVsLmZpbmQoJz50Zm9vdD50cicpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmZvb3RlckRhdGEpIHtcbiAgICAgICAgICB0aGlzLiRlbC5maW5kKCd0Zm9vdCcpLmh0bWwoJzx0cj48L3RyPicpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0aGlzLm9wdGlvbnMuc2hvd0Zvb3RlciB8fCB0aGlzLm9wdGlvbnMuY2FyZFZpZXcpIHtcbiAgICAgICAgICB0aGlzLiR0YWJsZUZvb3Rlci5oaWRlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy4kdGFibGVGb290ZXIuc2hvdygpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImluaXRIZWFkZXJcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0SGVhZGVyKCkge1xuICAgICAgICB2YXIgX3RoaXMyID0gdGhpcztcblxuICAgICAgICB2YXIgdmlzaWJsZUNvbHVtbnMgPSB7fTtcbiAgICAgICAgdmFyIGhlYWRlckh0bWwgPSBbXTtcbiAgICAgICAgdGhpcy5oZWFkZXIgPSB7XG4gICAgICAgICAgZmllbGRzOiBbXSxcbiAgICAgICAgICBzdHlsZXM6IFtdLFxuICAgICAgICAgIGNsYXNzZXM6IFtdLFxuICAgICAgICAgIGZvcm1hdHRlcnM6IFtdLFxuICAgICAgICAgIGRldGFpbEZvcm1hdHRlcnM6IFtdLFxuICAgICAgICAgIGV2ZW50czogW10sXG4gICAgICAgICAgc29ydGVyczogW10sXG4gICAgICAgICAgc29ydE5hbWVzOiBbXSxcbiAgICAgICAgICBjZWxsU3R5bGVzOiBbXSxcbiAgICAgICAgICBzZWFyY2hhYmxlczogW11cbiAgICAgICAgfTtcbiAgICAgICAgVXRpbHMudXBkYXRlRmllbGRHcm91cCh0aGlzLm9wdGlvbnMuY29sdW1ucyk7XG4gICAgICAgIHRoaXMub3B0aW9ucy5jb2x1bW5zLmZvckVhY2goZnVuY3Rpb24gKGNvbHVtbnMsIGkpIHtcbiAgICAgICAgICB2YXIgaHRtbCA9IFtdO1xuICAgICAgICAgIGh0bWwucHVzaChcIjx0clwiLmNvbmNhdChVdGlscy5zcHJpbnRmKCcgY2xhc3M9XCIlc1wiJywgX3RoaXMyLl9oZWFkZXJUckNsYXNzZXNbaV0pLCBcIiBcIikuY29uY2F0KFV0aWxzLnNwcmludGYoJyBzdHlsZT1cIiVzXCInLCBfdGhpczIuX2hlYWRlclRyU3R5bGVzW2ldKSwgXCI+XCIpKTtcbiAgICAgICAgICB2YXIgZGV0YWlsVmlld1RlbXBsYXRlID0gJyc7XG5cbiAgICAgICAgICBpZiAoaSA9PT0gMCAmJiBVdGlscy5oYXNEZXRhaWxWaWV3SWNvbihfdGhpczIub3B0aW9ucykpIHtcbiAgICAgICAgICAgIHZhciByb3dzcGFuID0gX3RoaXMyLm9wdGlvbnMuY29sdW1ucy5sZW5ndGggPiAxID8gXCIgcm93c3Bhbj1cXFwiXCIuY29uY2F0KF90aGlzMi5vcHRpb25zLmNvbHVtbnMubGVuZ3RoLCBcIlxcXCJcIikgOiAnJztcbiAgICAgICAgICAgIGRldGFpbFZpZXdUZW1wbGF0ZSA9IFwiPHRoIGNsYXNzPVxcXCJkZXRhaWxcXFwiXCIuY29uY2F0KHJvd3NwYW4sIFwiPlxcbiAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJmaHQtY2VsbFxcXCI+PC9kaXY+XFxuICAgICAgICAgIDwvdGg+XCIpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChkZXRhaWxWaWV3VGVtcGxhdGUgJiYgX3RoaXMyLm9wdGlvbnMuZGV0YWlsVmlld0FsaWduICE9PSAncmlnaHQnKSB7XG4gICAgICAgICAgICBodG1sLnB1c2goZGV0YWlsVmlld1RlbXBsYXRlKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb2x1bW5zLmZvckVhY2goZnVuY3Rpb24gKGNvbHVtbiwgaikge1xuICAgICAgICAgICAgdmFyIGNsYXNzXyA9IFV0aWxzLnNwcmludGYoJyBjbGFzcz1cIiVzXCInLCBjb2x1bW5bJ2NsYXNzJ10pO1xuICAgICAgICAgICAgdmFyIHVuaXRXaWR0aCA9IGNvbHVtbi53aWR0aFVuaXQ7XG4gICAgICAgICAgICB2YXIgd2lkdGggPSBwYXJzZUZsb2F0KGNvbHVtbi53aWR0aCk7XG4gICAgICAgICAgICB2YXIgaGFsaWduID0gVXRpbHMuc3ByaW50ZigndGV4dC1hbGlnbjogJXM7ICcsIGNvbHVtbi5oYWxpZ24gPyBjb2x1bW4uaGFsaWduIDogY29sdW1uLmFsaWduKTtcbiAgICAgICAgICAgIHZhciBhbGlnbiA9IFV0aWxzLnNwcmludGYoJ3RleHQtYWxpZ246ICVzOyAnLCBjb2x1bW4uYWxpZ24pO1xuICAgICAgICAgICAgdmFyIHN0eWxlID0gVXRpbHMuc3ByaW50ZigndmVydGljYWwtYWxpZ246ICVzOyAnLCBjb2x1bW4udmFsaWduKTtcbiAgICAgICAgICAgIHN0eWxlICs9IFV0aWxzLnNwcmludGYoJ3dpZHRoOiAlczsgJywgKGNvbHVtbi5jaGVja2JveCB8fCBjb2x1bW4ucmFkaW8pICYmICF3aWR0aCA/ICFjb2x1bW4uc2hvd1NlbGVjdFRpdGxlID8gJzM2cHgnIDogdW5kZWZpbmVkIDogd2lkdGggPyB3aWR0aCArIHVuaXRXaWR0aCA6IHVuZGVmaW5lZCk7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgY29sdW1uLmZpZWxkSW5kZXggPT09ICd1bmRlZmluZWQnICYmICFjb2x1bW4udmlzaWJsZSkge1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBoZWFkZXJTdHlsZSA9IFV0aWxzLmNhbGN1bGF0ZU9iamVjdFZhbHVlKG51bGwsIF90aGlzMi5vcHRpb25zLmhlYWRlclN0eWxlLCBbY29sdW1uXSk7XG4gICAgICAgICAgICB2YXIgY3NzZXMgPSBbXTtcbiAgICAgICAgICAgIHZhciBjbGFzc2VzID0gJyc7XG5cbiAgICAgICAgICAgIGlmIChoZWFkZXJTdHlsZSAmJiBoZWFkZXJTdHlsZS5jc3MpIHtcbiAgICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfT2JqZWN0JGVudHJpZXMgPSBPYmplY3QuZW50cmllcyhoZWFkZXJTdHlsZS5jc3MpOyBfaSA8IF9PYmplY3QkZW50cmllcy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgX09iamVjdCRlbnRyaWVzJF9pID0gX3NsaWNlZFRvQXJyYXkoX09iamVjdCRlbnRyaWVzW19pXSwgMiksXG4gICAgICAgICAgICAgICAgICAgIGtleSA9IF9PYmplY3QkZW50cmllcyRfaVswXSxcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBfT2JqZWN0JGVudHJpZXMkX2lbMV07XG5cbiAgICAgICAgICAgICAgICBjc3Nlcy5wdXNoKFwiXCIuY29uY2F0KGtleSwgXCI6IFwiKS5jb25jYXQodmFsdWUpKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoaGVhZGVyU3R5bGUgJiYgaGVhZGVyU3R5bGUuY2xhc3Nlcykge1xuICAgICAgICAgICAgICBjbGFzc2VzID0gVXRpbHMuc3ByaW50ZignIGNsYXNzPVwiJXNcIicsIGNvbHVtblsnY2xhc3MnXSA/IFtjb2x1bW5bJ2NsYXNzJ10sIGhlYWRlclN0eWxlLmNsYXNzZXNdLmpvaW4oJyAnKSA6IGhlYWRlclN0eWxlLmNsYXNzZXMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIGNvbHVtbi5maWVsZEluZGV4ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICBfdGhpczIuaGVhZGVyLmZpZWxkc1tjb2x1bW4uZmllbGRJbmRleF0gPSBjb2x1bW4uZmllbGQ7XG4gICAgICAgICAgICAgIF90aGlzMi5oZWFkZXIuc3R5bGVzW2NvbHVtbi5maWVsZEluZGV4XSA9IGFsaWduICsgc3R5bGU7XG4gICAgICAgICAgICAgIF90aGlzMi5oZWFkZXIuY2xhc3Nlc1tjb2x1bW4uZmllbGRJbmRleF0gPSBjbGFzc187XG4gICAgICAgICAgICAgIF90aGlzMi5oZWFkZXIuZm9ybWF0dGVyc1tjb2x1bW4uZmllbGRJbmRleF0gPSBjb2x1bW4uZm9ybWF0dGVyO1xuICAgICAgICAgICAgICBfdGhpczIuaGVhZGVyLmRldGFpbEZvcm1hdHRlcnNbY29sdW1uLmZpZWxkSW5kZXhdID0gY29sdW1uLmRldGFpbEZvcm1hdHRlcjtcbiAgICAgICAgICAgICAgX3RoaXMyLmhlYWRlci5ldmVudHNbY29sdW1uLmZpZWxkSW5kZXhdID0gY29sdW1uLmV2ZW50cztcbiAgICAgICAgICAgICAgX3RoaXMyLmhlYWRlci5zb3J0ZXJzW2NvbHVtbi5maWVsZEluZGV4XSA9IGNvbHVtbi5zb3J0ZXI7XG4gICAgICAgICAgICAgIF90aGlzMi5oZWFkZXIuc29ydE5hbWVzW2NvbHVtbi5maWVsZEluZGV4XSA9IGNvbHVtbi5zb3J0TmFtZTtcbiAgICAgICAgICAgICAgX3RoaXMyLmhlYWRlci5jZWxsU3R5bGVzW2NvbHVtbi5maWVsZEluZGV4XSA9IGNvbHVtbi5jZWxsU3R5bGU7XG4gICAgICAgICAgICAgIF90aGlzMi5oZWFkZXIuc2VhcmNoYWJsZXNbY29sdW1uLmZpZWxkSW5kZXhdID0gY29sdW1uLnNlYXJjaGFibGU7XG5cbiAgICAgICAgICAgICAgaWYgKCFjb2x1bW4udmlzaWJsZSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGlmIChfdGhpczIub3B0aW9ucy5jYXJkVmlldyAmJiAhY29sdW1uLmNhcmRWaXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgdmlzaWJsZUNvbHVtbnNbY29sdW1uLmZpZWxkXSA9IGNvbHVtbjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaHRtbC5wdXNoKFwiPHRoXCIuY29uY2F0KFV0aWxzLnNwcmludGYoJyB0aXRsZT1cIiVzXCInLCBjb2x1bW4udGl0bGVUb29sdGlwKSksIGNvbHVtbi5jaGVja2JveCB8fCBjb2x1bW4ucmFkaW8gPyBVdGlscy5zcHJpbnRmKCcgY2xhc3M9XCJicy1jaGVja2JveCAlc1wiJywgY29sdW1uWydjbGFzcyddIHx8ICcnKSA6IGNsYXNzZXMgfHwgY2xhc3NfLCBVdGlscy5zcHJpbnRmKCcgc3R5bGU9XCIlc1wiJywgaGFsaWduICsgc3R5bGUgKyBjc3Nlcy5qb2luKCc7ICcpKSwgVXRpbHMuc3ByaW50ZignIHJvd3NwYW49XCIlc1wiJywgY29sdW1uLnJvd3NwYW4pLCBVdGlscy5zcHJpbnRmKCcgY29sc3Bhbj1cIiVzXCInLCBjb2x1bW4uY29sc3BhbiksIFV0aWxzLnNwcmludGYoJyBkYXRhLWZpZWxkPVwiJXNcIicsIGNvbHVtbi5maWVsZCksIC8vIElmIGBjb2x1bW5gIGlzIG5vdCB0aGUgZmlyc3QgZWxlbWVudCBvZiBgdGhpcy5vcHRpb25zLmNvbHVtbnNbMF1gLCB0aGVuIGNsYXNzTmFtZSAnZGF0YS1ub3QtZmlyc3QtdGgnIHNob3VsZCBiZSBhZGRlZC5cbiAgICAgICAgICAgIGogPT09IDAgJiYgaSA+IDAgPyAnIGRhdGEtbm90LWZpcnN0LXRoJyA6ICcnLCAnPicpO1xuICAgICAgICAgICAgaHRtbC5wdXNoKFV0aWxzLnNwcmludGYoJzxkaXYgY2xhc3M9XCJ0aC1pbm5lciAlc1wiPicsIF90aGlzMi5vcHRpb25zLnNvcnRhYmxlICYmIGNvbHVtbi5zb3J0YWJsZSA/ICdzb3J0YWJsZSBib3RoJyA6ICcnKSk7XG4gICAgICAgICAgICB2YXIgdGV4dCA9IF90aGlzMi5vcHRpb25zLmVzY2FwZSA/IFV0aWxzLmVzY2FwZUhUTUwoY29sdW1uLnRpdGxlKSA6IGNvbHVtbi50aXRsZTtcbiAgICAgICAgICAgIHZhciB0aXRsZSA9IHRleHQ7XG5cbiAgICAgICAgICAgIGlmIChjb2x1bW4uY2hlY2tib3gpIHtcbiAgICAgICAgICAgICAgdGV4dCA9ICcnO1xuXG4gICAgICAgICAgICAgIGlmICghX3RoaXMyLm9wdGlvbnMuc2luZ2xlU2VsZWN0ICYmIF90aGlzMi5vcHRpb25zLmNoZWNrYm94SGVhZGVyKSB7XG4gICAgICAgICAgICAgICAgdGV4dCA9ICc8bGFiZWw+PGlucHV0IG5hbWU9XCJidFNlbGVjdEFsbFwiIHR5cGU9XCJjaGVja2JveFwiIC8+PHNwYW4+PC9zcGFuPjwvbGFiZWw+JztcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIF90aGlzMi5oZWFkZXIuc3RhdGVGaWVsZCA9IGNvbHVtbi5maWVsZDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNvbHVtbi5yYWRpbykge1xuICAgICAgICAgICAgICB0ZXh0ID0gJyc7XG4gICAgICAgICAgICAgIF90aGlzMi5oZWFkZXIuc3RhdGVGaWVsZCA9IGNvbHVtbi5maWVsZDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCF0ZXh0ICYmIGNvbHVtbi5zaG93U2VsZWN0VGl0bGUpIHtcbiAgICAgICAgICAgICAgdGV4dCArPSB0aXRsZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaHRtbC5wdXNoKHRleHQpO1xuICAgICAgICAgICAgaHRtbC5wdXNoKCc8L2Rpdj4nKTtcbiAgICAgICAgICAgIGh0bWwucHVzaCgnPGRpdiBjbGFzcz1cImZodC1jZWxsXCI+PC9kaXY+Jyk7XG4gICAgICAgICAgICBodG1sLnB1c2goJzwvZGl2PicpO1xuICAgICAgICAgICAgaHRtbC5wdXNoKCc8L3RoPicpO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaWYgKGRldGFpbFZpZXdUZW1wbGF0ZSAmJiBfdGhpczIub3B0aW9ucy5kZXRhaWxWaWV3QWxpZ24gPT09ICdyaWdodCcpIHtcbiAgICAgICAgICAgIGh0bWwucHVzaChkZXRhaWxWaWV3VGVtcGxhdGUpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGh0bWwucHVzaCgnPC90cj4nKTtcblxuICAgICAgICAgIGlmIChodG1sLmxlbmd0aCA+IDMpIHtcbiAgICAgICAgICAgIGhlYWRlckh0bWwucHVzaChodG1sLmpvaW4oJycpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLiRoZWFkZXIuaHRtbChoZWFkZXJIdG1sLmpvaW4oJycpKTtcbiAgICAgICAgdGhpcy4kaGVhZGVyLmZpbmQoJ3RoW2RhdGEtZmllbGRdJykuZWFjaChmdW5jdGlvbiAoaSwgZWwpIHtcbiAgICAgICAgICAkX19kZWZhdWx0WydkZWZhdWx0J10oZWwpLmRhdGEodmlzaWJsZUNvbHVtbnNbJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKS5kYXRhKCdmaWVsZCcpXSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLiRjb250YWluZXIub2ZmKCdjbGljaycsICcudGgtaW5uZXInKS5vbignY2xpY2snLCAnLnRoLWlubmVyJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICB2YXIgJHRoaXMgPSAkX19kZWZhdWx0WydkZWZhdWx0J10oZS5jdXJyZW50VGFyZ2V0KTtcblxuICAgICAgICAgIGlmIChfdGhpczIub3B0aW9ucy5kZXRhaWxWaWV3ICYmICEkdGhpcy5wYXJlbnQoKS5oYXNDbGFzcygnYnMtY2hlY2tib3gnKSkge1xuICAgICAgICAgICAgaWYgKCR0aGlzLmNsb3Nlc3QoJy5ib290c3RyYXAtdGFibGUnKVswXSAhPT0gX3RoaXMyLiRjb250YWluZXJbMF0pIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChfdGhpczIub3B0aW9ucy5zb3J0YWJsZSAmJiAkdGhpcy5wYXJlbnQoKS5kYXRhKCkuc29ydGFibGUpIHtcbiAgICAgICAgICAgIF90aGlzMi5vblNvcnQoZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy4kaGVhZGVyLmNoaWxkcmVuKCkuY2hpbGRyZW4oKS5vZmYoJ2tleXByZXNzJykub24oJ2tleXByZXNzJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICBpZiAoX3RoaXMyLm9wdGlvbnMuc29ydGFibGUgJiYgJF9fZGVmYXVsdFsnZGVmYXVsdCddKGUuY3VycmVudFRhcmdldCkuZGF0YSgpLnNvcnRhYmxlKSB7XG4gICAgICAgICAgICB2YXIgY29kZSA9IGUua2V5Q29kZSB8fCBlLndoaWNoO1xuXG4gICAgICAgICAgICBpZiAoY29kZSA9PT0gMTMpIHtcbiAgICAgICAgICAgICAgLy8gRW50ZXIga2V5Y29kZVxuICAgICAgICAgICAgICBfdGhpczIub25Tb3J0KGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHZhciByZXNpemVFdmVudCA9IFV0aWxzLmdldEV2ZW50TmFtZSgncmVzaXplLmJvb3RzdHJhcC10YWJsZScsIHRoaXMuJGVsLmF0dHIoJ2lkJykpO1xuICAgICAgICAkX19kZWZhdWx0WydkZWZhdWx0J10od2luZG93KS5vZmYocmVzaXplRXZlbnQpO1xuXG4gICAgICAgIGlmICghdGhpcy5vcHRpb25zLnNob3dIZWFkZXIgfHwgdGhpcy5vcHRpb25zLmNhcmRWaWV3KSB7XG4gICAgICAgICAgdGhpcy4kaGVhZGVyLmhpZGUoKTtcbiAgICAgICAgICB0aGlzLiR0YWJsZUhlYWRlci5oaWRlKCk7XG4gICAgICAgICAgdGhpcy4kdGFibGVMb2FkaW5nLmNzcygndG9wJywgMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy4kaGVhZGVyLnNob3coKTtcbiAgICAgICAgICB0aGlzLiR0YWJsZUhlYWRlci5zaG93KCk7XG4gICAgICAgICAgdGhpcy4kdGFibGVMb2FkaW5nLmNzcygndG9wJywgdGhpcy4kaGVhZGVyLm91dGVySGVpZ2h0KCkgKyAxKTsgLy8gQXNzaWduIHRoZSBjb3JyZWN0IHNvcnRhYmxlIGFycm93XG5cbiAgICAgICAgICB0aGlzLmdldENhcmV0KCk7XG4gICAgICAgICAgJF9fZGVmYXVsdFsnZGVmYXVsdCddKHdpbmRvdykub24ocmVzaXplRXZlbnQsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBfdGhpczIucmVzZXRWaWV3KCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLiRzZWxlY3RBbGwgPSB0aGlzLiRoZWFkZXIuZmluZCgnW25hbWU9XCJidFNlbGVjdEFsbFwiXScpO1xuICAgICAgICB0aGlzLiRzZWxlY3RBbGwub2ZmKCdjbGljaycpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICB2YXIgY2hlY2tlZCA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlLmN1cnJlbnRUYXJnZXQpLnByb3AoJ2NoZWNrZWQnKTtcblxuICAgICAgICAgIF90aGlzMltjaGVja2VkID8gJ2NoZWNrQWxsJyA6ICd1bmNoZWNrQWxsJ10oKTtcblxuICAgICAgICAgIF90aGlzMi51cGRhdGVTZWxlY3RlZCgpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiaW5pdERhdGFcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0RGF0YShkYXRhLCB0eXBlKSB7XG4gICAgICAgIGlmICh0eXBlID09PSAnYXBwZW5kJykge1xuICAgICAgICAgIHRoaXMub3B0aW9ucy5kYXRhID0gdGhpcy5vcHRpb25zLmRhdGEuY29uY2F0KGRhdGEpO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdwcmVwZW5kJykge1xuICAgICAgICAgIHRoaXMub3B0aW9ucy5kYXRhID0gW10uY29uY2F0KGRhdGEpLmNvbmNhdCh0aGlzLm9wdGlvbnMuZGF0YSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZGF0YSA9IGRhdGEgfHwgVXRpbHMuZGVlcENvcHkodGhpcy5vcHRpb25zLmRhdGEpO1xuICAgICAgICAgIHRoaXMub3B0aW9ucy5kYXRhID0gQXJyYXkuaXNBcnJheShkYXRhKSA/IGRhdGEgOiBkYXRhW3RoaXMub3B0aW9ucy5kYXRhRmllbGRdO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5kYXRhID0gX3RvQ29uc3VtYWJsZUFycmF5KHRoaXMub3B0aW9ucy5kYXRhKTtcblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNvcnRSZXNldCkge1xuICAgICAgICAgIHRoaXMudW5zb3J0ZWREYXRhID0gX3RvQ29uc3VtYWJsZUFycmF5KHRoaXMuZGF0YSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNpZGVQYWdpbmF0aW9uID09PSAnc2VydmVyJykge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaW5pdFNvcnQoKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiaW5pdFNvcnRcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0U29ydCgpIHtcbiAgICAgICAgdmFyIF90aGlzMyA9IHRoaXM7XG5cbiAgICAgICAgdmFyIG5hbWUgPSB0aGlzLm9wdGlvbnMuc29ydE5hbWU7XG4gICAgICAgIHZhciBvcmRlciA9IHRoaXMub3B0aW9ucy5zb3J0T3JkZXIgPT09ICdkZXNjJyA/IC0xIDogMTtcbiAgICAgICAgdmFyIGluZGV4ID0gdGhpcy5oZWFkZXIuZmllbGRzLmluZGV4T2YodGhpcy5vcHRpb25zLnNvcnROYW1lKTtcbiAgICAgICAgdmFyIHRpbWVvdXRJZCA9IDA7XG5cbiAgICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMuc29ydFN0YWJsZSkge1xuICAgICAgICAgICAgdGhpcy5kYXRhLmZvckVhY2goZnVuY3Rpb24gKHJvdywgaSkge1xuICAgICAgICAgICAgICBpZiAoIXJvdy5oYXNPd25Qcm9wZXJ0eSgnX3Bvc2l0aW9uJykpIHtcbiAgICAgICAgICAgICAgICByb3cuX3Bvc2l0aW9uID0gaTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5jdXN0b21Tb3J0KSB7XG4gICAgICAgICAgICBVdGlscy5jYWxjdWxhdGVPYmplY3RWYWx1ZSh0aGlzLm9wdGlvbnMsIHRoaXMub3B0aW9ucy5jdXN0b21Tb3J0LCBbdGhpcy5vcHRpb25zLnNvcnROYW1lLCB0aGlzLm9wdGlvbnMuc29ydE9yZGVyLCB0aGlzLmRhdGFdKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5kYXRhLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgICAgICAgaWYgKF90aGlzMy5oZWFkZXIuc29ydE5hbWVzW2luZGV4XSkge1xuICAgICAgICAgICAgICAgIG5hbWUgPSBfdGhpczMuaGVhZGVyLnNvcnROYW1lc1tpbmRleF07XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICB2YXIgYWEgPSBVdGlscy5nZXRJdGVtRmllbGQoYSwgbmFtZSwgX3RoaXMzLm9wdGlvbnMuZXNjYXBlKTtcbiAgICAgICAgICAgICAgdmFyIGJiID0gVXRpbHMuZ2V0SXRlbUZpZWxkKGIsIG5hbWUsIF90aGlzMy5vcHRpb25zLmVzY2FwZSk7XG4gICAgICAgICAgICAgIHZhciB2YWx1ZSA9IFV0aWxzLmNhbGN1bGF0ZU9iamVjdFZhbHVlKF90aGlzMy5oZWFkZXIsIF90aGlzMy5oZWFkZXIuc29ydGVyc1tpbmRleF0sIFthYSwgYmIsIGEsIGJdKTtcblxuICAgICAgICAgICAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpczMub3B0aW9ucy5zb3J0U3RhYmxlICYmIHZhbHVlID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gb3JkZXIgKiAoYS5fcG9zaXRpb24gLSBiLl9wb3NpdGlvbik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9yZGVyICogdmFsdWU7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICByZXR1cm4gVXRpbHMuc29ydChhYSwgYmIsIG9yZGVyLCBfdGhpczMub3B0aW9ucy5zb3J0U3RhYmxlLCBhLl9wb3NpdGlvbiwgYi5fcG9zaXRpb24pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5zb3J0Q2xhc3MgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXRJZCk7XG4gICAgICAgICAgICB0aW1lb3V0SWQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgX3RoaXMzLiRlbC5yZW1vdmVDbGFzcyhfdGhpczMub3B0aW9ucy5zb3J0Q2xhc3MpO1xuXG4gICAgICAgICAgICAgIHZhciBpbmRleCA9IF90aGlzMy4kaGVhZGVyLmZpbmQoXCJbZGF0YS1maWVsZD1cXFwiXCIuY29uY2F0KF90aGlzMy5vcHRpb25zLnNvcnROYW1lLCBcIlxcXCJdXCIpKS5pbmRleCgpO1xuXG4gICAgICAgICAgICAgIF90aGlzMy4kZWwuZmluZChcInRyIHRkOm50aC1jaGlsZChcIi5jb25jYXQoaW5kZXggKyAxLCBcIilcIikpLmFkZENsYXNzKF90aGlzMy5vcHRpb25zLnNvcnRDbGFzcyk7XG4gICAgICAgICAgICB9LCAyNTApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLm9wdGlvbnMuc29ydFJlc2V0KSB7XG4gICAgICAgICAgdGhpcy5kYXRhID0gX3RvQ29uc3VtYWJsZUFycmF5KHRoaXMudW5zb3J0ZWREYXRhKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJvblNvcnRcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBvblNvcnQoX3JlZikge1xuICAgICAgICB2YXIgdHlwZSA9IF9yZWYudHlwZSxcbiAgICAgICAgICAgIGN1cnJlbnRUYXJnZXQgPSBfcmVmLmN1cnJlbnRUYXJnZXQ7XG4gICAgICAgIHZhciAkdGhpcyA9IHR5cGUgPT09ICdrZXlwcmVzcycgPyAkX19kZWZhdWx0WydkZWZhdWx0J10oY3VycmVudFRhcmdldCkgOiAkX19kZWZhdWx0WydkZWZhdWx0J10oY3VycmVudFRhcmdldCkucGFyZW50KCk7XG4gICAgICAgIHZhciAkdGhpc18gPSB0aGlzLiRoZWFkZXIuZmluZCgndGgnKS5lcSgkdGhpcy5pbmRleCgpKTtcbiAgICAgICAgdGhpcy4kaGVhZGVyLmFkZCh0aGlzLiRoZWFkZXJfKS5maW5kKCdzcGFuLm9yZGVyJykucmVtb3ZlKCk7XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5zb3J0TmFtZSA9PT0gJHRoaXMuZGF0YSgnZmllbGQnKSkge1xuICAgICAgICAgIHZhciBjdXJyZW50U29ydE9yZGVyID0gdGhpcy5vcHRpb25zLnNvcnRPcmRlcjtcblxuICAgICAgICAgIGlmIChjdXJyZW50U29ydE9yZGVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMub3B0aW9ucy5zb3J0T3JkZXIgPSAnYXNjJztcbiAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRTb3J0T3JkZXIgPT09ICdhc2MnKSB7XG4gICAgICAgICAgICB0aGlzLm9wdGlvbnMuc29ydE9yZGVyID0gJ2Rlc2MnO1xuICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5vcHRpb25zLnNvcnRPcmRlciA9PT0gJ2Rlc2MnKSB7XG4gICAgICAgICAgICB0aGlzLm9wdGlvbnMuc29ydE9yZGVyID0gdGhpcy5vcHRpb25zLnNvcnRSZXNldCA/IHVuZGVmaW5lZCA6ICdhc2MnO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMuc29ydE9yZGVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMub3B0aW9ucy5zb3J0TmFtZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5vcHRpb25zLnNvcnROYW1lID0gJHRoaXMuZGF0YSgnZmllbGQnKTtcblxuICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMucmVtZW1iZXJPcmRlcikge1xuICAgICAgICAgICAgdGhpcy5vcHRpb25zLnNvcnRPcmRlciA9ICR0aGlzLmRhdGEoJ29yZGVyJykgPT09ICdhc2MnID8gJ2Rlc2MnIDogJ2FzYyc7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMub3B0aW9ucy5zb3J0T3JkZXIgPSB0aGlzLmNvbHVtbnNbdGhpcy5maWVsZHNDb2x1bW5zSW5kZXhbJHRoaXMuZGF0YSgnZmllbGQnKV1dLnNvcnRPcmRlciB8fCB0aGlzLmNvbHVtbnNbdGhpcy5maWVsZHNDb2x1bW5zSW5kZXhbJHRoaXMuZGF0YSgnZmllbGQnKV1dLm9yZGVyO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudHJpZ2dlcignc29ydCcsIHRoaXMub3B0aW9ucy5zb3J0TmFtZSwgdGhpcy5vcHRpb25zLnNvcnRPcmRlcik7XG4gICAgICAgICR0aGlzLmFkZCgkdGhpc18pLmRhdGEoJ29yZGVyJywgdGhpcy5vcHRpb25zLnNvcnRPcmRlcik7IC8vIEFzc2lnbiB0aGUgY29ycmVjdCBzb3J0YWJsZSBhcnJvd1xuXG4gICAgICAgIHRoaXMuZ2V0Q2FyZXQoKTtcblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNpZGVQYWdpbmF0aW9uID09PSAnc2VydmVyJyAmJiB0aGlzLm9wdGlvbnMuc2VydmVyU29ydCkge1xuICAgICAgICAgIHRoaXMub3B0aW9ucy5wYWdlTnVtYmVyID0gMTtcbiAgICAgICAgICB0aGlzLmluaXRTZXJ2ZXIodGhpcy5vcHRpb25zLnNpbGVudFNvcnQpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaW5pdFNvcnQoKTtcbiAgICAgICAgdGhpcy5pbml0Qm9keSgpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJpbml0VG9vbGJhclwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGluaXRUb29sYmFyKCkge1xuICAgICAgICB2YXIgX3RoaXM0ID0gdGhpcztcblxuICAgICAgICB2YXIgb3B0cyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgdmFyIGh0bWwgPSBbXTtcbiAgICAgICAgdmFyIHRpbWVvdXRJZCA9IDA7XG4gICAgICAgIHZhciAka2VlcE9wZW47XG4gICAgICAgIHZhciBzd2l0Y2hhYmxlQ291bnQgPSAwO1xuXG4gICAgICAgIGlmICh0aGlzLiR0b29sYmFyLmZpbmQoJy5icy1iYXJzJykuY2hpbGRyZW4oKS5sZW5ndGgpIHtcbiAgICAgICAgICAkX19kZWZhdWx0WydkZWZhdWx0J10oJ2JvZHknKS5hcHBlbmQoJF9fZGVmYXVsdFsnZGVmYXVsdCddKG9wdHMudG9vbGJhcikpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy4kdG9vbGJhci5odG1sKCcnKTtcblxuICAgICAgICBpZiAodHlwZW9mIG9wdHMudG9vbGJhciA9PT0gJ3N0cmluZycgfHwgX3R5cGVvZihvcHRzLnRvb2xiYXIpID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShVdGlscy5zcHJpbnRmKCc8ZGl2IGNsYXNzPVwiYnMtYmFycyAlcy0lc1wiPjwvZGl2PicsIHRoaXMuY29uc3RhbnRzLmNsYXNzZXMucHVsbCwgb3B0cy50b29sYmFyQWxpZ24pKS5hcHBlbmRUbyh0aGlzLiR0b29sYmFyKS5hcHBlbmQoJF9fZGVmYXVsdFsnZGVmYXVsdCddKG9wdHMudG9vbGJhcikpO1xuICAgICAgICB9IC8vIHNob3dDb2x1bW5zLCBzaG93VG9nZ2xlLCBzaG93UmVmcmVzaFxuXG5cbiAgICAgICAgaHRtbCA9IFtcIjxkaXYgY2xhc3M9XFxcIlwiLmNvbmNhdChbJ2NvbHVtbnMnLCBcImNvbHVtbnMtXCIuY29uY2F0KG9wdHMuYnV0dG9uc0FsaWduKSwgdGhpcy5jb25zdGFudHMuY2xhc3Nlcy5idXR0b25zR3JvdXAsIFwiXCIuY29uY2F0KHRoaXMuY29uc3RhbnRzLmNsYXNzZXMucHVsbCwgXCItXCIpLmNvbmNhdChvcHRzLmJ1dHRvbnNBbGlnbildLmpvaW4oJyAnKSwgXCJcXFwiPlwiKV07XG5cbiAgICAgICAgaWYgKHR5cGVvZiBvcHRzLmJ1dHRvbnNPcmRlciA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBvcHRzLmJ1dHRvbnNPcmRlciA9IG9wdHMuYnV0dG9uc09yZGVyLnJlcGxhY2UoL1xcW3xcXF18IHwnL2csICcnKS5zcGxpdCgnLCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5idXR0b25zID0gT2JqZWN0LmFzc2lnbih0aGlzLmJ1dHRvbnMsIHtcbiAgICAgICAgICBwYWdpbmF0aW9uU3dpdGNoOiB7XG4gICAgICAgICAgICB0ZXh0OiBvcHRzLnBhZ2luYXRpb24gPyBvcHRzLmZvcm1hdFBhZ2luYXRpb25Td2l0Y2hVcCgpIDogb3B0cy5mb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bigpLFxuICAgICAgICAgICAgaWNvbjogb3B0cy5wYWdpbmF0aW9uID8gb3B0cy5pY29ucy5wYWdpbmF0aW9uU3dpdGNoRG93biA6IG9wdHMuaWNvbnMucGFnaW5hdGlvblN3aXRjaFVwLFxuICAgICAgICAgICAgcmVuZGVyOiBmYWxzZSxcbiAgICAgICAgICAgIGV2ZW50OiB0aGlzLnRvZ2dsZVBhZ2luYXRpb24sXG4gICAgICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgICAgICdhcmlhLWxhYmVsJzogb3B0cy5mb3JtYXRQYWdpbmF0aW9uU3dpdGNoKCksXG4gICAgICAgICAgICAgIHRpdGxlOiBvcHRzLmZvcm1hdFBhZ2luYXRpb25Td2l0Y2goKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgcmVmcmVzaDoge1xuICAgICAgICAgICAgdGV4dDogb3B0cy5mb3JtYXRSZWZyZXNoKCksXG4gICAgICAgICAgICBpY29uOiBvcHRzLmljb25zLnJlZnJlc2gsXG4gICAgICAgICAgICByZW5kZXI6IGZhbHNlLFxuICAgICAgICAgICAgZXZlbnQ6IHRoaXMucmVmcmVzaCxcbiAgICAgICAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgICAgICAgJ2FyaWEtbGFiZWwnOiBvcHRzLmZvcm1hdFJlZnJlc2goKSxcbiAgICAgICAgICAgICAgdGl0bGU6IG9wdHMuZm9ybWF0UmVmcmVzaCgpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICB0b2dnbGU6IHtcbiAgICAgICAgICAgIHRleHQ6IG9wdHMuZm9ybWF0VG9nZ2xlKCksXG4gICAgICAgICAgICBpY29uOiBvcHRzLmljb25zLnRvZ2dsZU9mZixcbiAgICAgICAgICAgIHJlbmRlcjogZmFsc2UsXG4gICAgICAgICAgICBldmVudDogdGhpcy50b2dnbGVWaWV3LFxuICAgICAgICAgICAgYXR0cmlidXRlczoge1xuICAgICAgICAgICAgICAnYXJpYS1sYWJlbCc6IG9wdHMuZm9ybWF0VG9nZ2xlT24oKSxcbiAgICAgICAgICAgICAgdGl0bGU6IG9wdHMuZm9ybWF0VG9nZ2xlT24oKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgZnVsbHNjcmVlbjoge1xuICAgICAgICAgICAgdGV4dDogb3B0cy5mb3JtYXRGdWxsc2NyZWVuKCksXG4gICAgICAgICAgICBpY29uOiBvcHRzLmljb25zLmZ1bGxzY3JlZW4sXG4gICAgICAgICAgICByZW5kZXI6IGZhbHNlLFxuICAgICAgICAgICAgZXZlbnQ6IHRoaXMudG9nZ2xlRnVsbHNjcmVlbixcbiAgICAgICAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgICAgICAgJ2FyaWEtbGFiZWwnOiBvcHRzLmZvcm1hdEZ1bGxzY3JlZW4oKSxcbiAgICAgICAgICAgICAgdGl0bGU6IG9wdHMuZm9ybWF0RnVsbHNjcmVlbigpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBjb2x1bW5zOiB7XG4gICAgICAgICAgICByZW5kZXI6IGZhbHNlLFxuICAgICAgICAgICAgaHRtbDogZnVuY3Rpb24gaHRtbCgpIHtcbiAgICAgICAgICAgICAgdmFyIGh0bWwgPSBbXTtcbiAgICAgICAgICAgICAgaHRtbC5wdXNoKFwiPGRpdiBjbGFzcz1cXFwia2VlcC1vcGVuIFwiLmNvbmNhdChfdGhpczQuY29uc3RhbnRzLmNsYXNzZXMuYnV0dG9uc0Ryb3Bkb3duLCBcIlxcXCIgdGl0bGU9XFxcIlwiKS5jb25jYXQob3B0cy5mb3JtYXRDb2x1bW5zKCksIFwiXFxcIj5cXG4gICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVxcXCJcIikuY29uY2F0KF90aGlzNC5jb25zdGFudHMuYnV0dG9uc0NsYXNzLCBcIiBkcm9wZG93bi10b2dnbGVcXFwiIHR5cGU9XFxcImJ1dHRvblxcXCIgXCIpLmNvbmNhdChfdGhpczQuY29uc3RhbnRzLmRhdGFUb2dnbGUsIFwiPVxcXCJkcm9wZG93blxcXCJcXG4gICAgICAgICAgICBhcmlhLWxhYmVsPVxcXCJDb2x1bW5zXFxcIiB0aXRsZT1cXFwiXCIpLmNvbmNhdChvcHRzLmZvcm1hdENvbHVtbnMoKSwgXCJcXFwiPlxcbiAgICAgICAgICAgIFwiKS5jb25jYXQob3B0cy5zaG93QnV0dG9uSWNvbnMgPyBVdGlscy5zcHJpbnRmKF90aGlzNC5jb25zdGFudHMuaHRtbC5pY29uLCBvcHRzLmljb25zUHJlZml4LCBvcHRzLmljb25zLmNvbHVtbnMpIDogJycsIFwiXFxuICAgICAgICAgICAgXCIpLmNvbmNhdChvcHRzLnNob3dCdXR0b25UZXh0ID8gb3B0cy5mb3JtYXRDb2x1bW5zKCkgOiAnJywgXCJcXG4gICAgICAgICAgICBcIikuY29uY2F0KF90aGlzNC5jb25zdGFudHMuaHRtbC5kcm9wZG93bkNhcmV0LCBcIlxcbiAgICAgICAgICAgIDwvYnV0dG9uPlxcbiAgICAgICAgICAgIFwiKS5jb25jYXQoX3RoaXM0LmNvbnN0YW50cy5odG1sLnRvb2xiYXJEcm9wZG93blswXSkpO1xuXG4gICAgICAgICAgICAgIGlmIChvcHRzLnNob3dDb2x1bW5zU2VhcmNoKSB7XG4gICAgICAgICAgICAgICAgaHRtbC5wdXNoKFV0aWxzLnNwcmludGYoX3RoaXM0LmNvbnN0YW50cy5odG1sLnRvb2xiYXJEcm9wZG93bkl0ZW0sIFV0aWxzLnNwcmludGYoJzxpbnB1dCB0eXBlPVwidGV4dFwiIGNsYXNzPVwiJXNcIiBuYW1lPVwiY29sdW1uc1NlYXJjaFwiIHBsYWNlaG9sZGVyPVwiJXNcIiBhdXRvY29tcGxldGU9XCJvZmZcIj4nLCBfdGhpczQuY29uc3RhbnRzLmNsYXNzZXMuaW5wdXQsIG9wdHMuZm9ybWF0U2VhcmNoKCkpKSk7XG4gICAgICAgICAgICAgICAgaHRtbC5wdXNoKF90aGlzNC5jb25zdGFudHMuaHRtbC50b29sYmFyRHJvcGRvd25TZXBhcmF0b3IpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKG9wdHMuc2hvd0NvbHVtbnNUb2dnbGVBbGwpIHtcbiAgICAgICAgICAgICAgICB2YXIgYWxsRmllbGRzVmlzaWJsZSA9IF90aGlzNC5nZXRWaXNpYmxlQ29sdW1ucygpLmxlbmd0aCA9PT0gX3RoaXM0LmNvbHVtbnMuZmlsdGVyKGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiAhX3RoaXM0LmlzU2VsZWN0aW9uQ29sdW1uKGNvbHVtbik7XG4gICAgICAgICAgICAgICAgfSkubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgaHRtbC5wdXNoKFV0aWxzLnNwcmludGYoX3RoaXM0LmNvbnN0YW50cy5odG1sLnRvb2xiYXJEcm9wZG93bkl0ZW0sIFV0aWxzLnNwcmludGYoJzxpbnB1dCB0eXBlPVwiY2hlY2tib3hcIiBjbGFzcz1cInRvZ2dsZS1hbGxcIiAlcz4gPHNwYW4+JXM8L3NwYW4+JywgYWxsRmllbGRzVmlzaWJsZSA/ICdjaGVja2VkPVwiY2hlY2tlZFwiJyA6ICcnLCBvcHRzLmZvcm1hdENvbHVtbnNUb2dnbGVBbGwoKSkpKTtcbiAgICAgICAgICAgICAgICBodG1sLnB1c2goX3RoaXM0LmNvbnN0YW50cy5odG1sLnRvb2xiYXJEcm9wZG93blNlcGFyYXRvcik7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICB2YXIgdmlzaWJsZUNvbHVtbnMgPSAwO1xuXG4gICAgICAgICAgICAgIF90aGlzNC5jb2x1bW5zLmZvckVhY2goZnVuY3Rpb24gKGNvbHVtbikge1xuICAgICAgICAgICAgICAgIGlmIChjb2x1bW4udmlzaWJsZSkge1xuICAgICAgICAgICAgICAgICAgdmlzaWJsZUNvbHVtbnMrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgIF90aGlzNC5jb2x1bW5zLmZvckVhY2goZnVuY3Rpb24gKGNvbHVtbiwgaSkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpczQuaXNTZWxlY3Rpb25Db2x1bW4oY29sdW1uKSkge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChvcHRzLmNhcmRWaWV3ICYmICFjb2x1bW4uY2FyZFZpc2libGUpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgY2hlY2tlZCA9IGNvbHVtbi52aXNpYmxlID8gJyBjaGVja2VkPVwiY2hlY2tlZFwiJyA6ICcnO1xuICAgICAgICAgICAgICAgIHZhciBkaXNhYmxlZCA9IHZpc2libGVDb2x1bW5zIDw9IG9wdHMubWluaW11bUNvdW50Q29sdW1ucyAmJiBjaGVja2VkID8gJyBkaXNhYmxlZD1cImRpc2FibGVkXCInIDogJyc7XG5cbiAgICAgICAgICAgICAgICBpZiAoY29sdW1uLnN3aXRjaGFibGUpIHtcbiAgICAgICAgICAgICAgICAgIGh0bWwucHVzaChVdGlscy5zcHJpbnRmKF90aGlzNC5jb25zdGFudHMuaHRtbC50b29sYmFyRHJvcGRvd25JdGVtLCBVdGlscy5zcHJpbnRmKCc8aW5wdXQgdHlwZT1cImNoZWNrYm94XCIgZGF0YS1maWVsZD1cIiVzXCIgdmFsdWU9XCIlc1wiJXMlcz4gPHNwYW4+JXM8L3NwYW4+JywgY29sdW1uLmZpZWxkLCBpLCBjaGVja2VkLCBkaXNhYmxlZCwgY29sdW1uLnRpdGxlKSkpO1xuICAgICAgICAgICAgICAgICAgc3dpdGNoYWJsZUNvdW50Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICBodG1sLnB1c2goX3RoaXM0LmNvbnN0YW50cy5odG1sLnRvb2xiYXJEcm9wZG93blsxXSwgJzwvZGl2PicpO1xuICAgICAgICAgICAgICByZXR1cm4gaHRtbC5qb2luKCcnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgYnV0dG9uc0h0bWwgPSB7fTtcblxuICAgICAgICBmb3IgKHZhciBfaTIgPSAwLCBfT2JqZWN0JGVudHJpZXMyID0gT2JqZWN0LmVudHJpZXModGhpcy5idXR0b25zKTsgX2kyIDwgX09iamVjdCRlbnRyaWVzMi5sZW5ndGg7IF9pMisrKSB7XG4gICAgICAgICAgdmFyIF9PYmplY3QkZW50cmllczIkX2kgPSBfc2xpY2VkVG9BcnJheShfT2JqZWN0JGVudHJpZXMyW19pMl0sIDIpLFxuICAgICAgICAgICAgICBidXR0b25OYW1lID0gX09iamVjdCRlbnRyaWVzMiRfaVswXSxcbiAgICAgICAgICAgICAgYnV0dG9uQ29uZmlnID0gX09iamVjdCRlbnRyaWVzMiRfaVsxXTtcblxuICAgICAgICAgIHZhciBidXR0b25IdG1sID0gdm9pZCAwO1xuXG4gICAgICAgICAgaWYgKGJ1dHRvbkNvbmZpZy5oYXNPd25Qcm9wZXJ0eSgnaHRtbCcpKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGJ1dHRvbkNvbmZpZy5odG1sID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgIGJ1dHRvbkh0bWwgPSBidXR0b25Db25maWcuaHRtbCgpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYnV0dG9uQ29uZmlnLmh0bWwgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIGJ1dHRvbkh0bWwgPSBidXR0b25Db25maWcuaHRtbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYnV0dG9uSHRtbCA9IFwiPGJ1dHRvbiBjbGFzcz1cXFwiXCIuY29uY2F0KHRoaXMuY29uc3RhbnRzLmJ1dHRvbnNDbGFzcywgXCJcXFwiIHR5cGU9XFxcImJ1dHRvblxcXCIgbmFtZT1cXFwiXCIpLmNvbmNhdChidXR0b25OYW1lLCBcIlxcXCJcIik7XG5cbiAgICAgICAgICAgIGlmIChidXR0b25Db25maWcuaGFzT3duUHJvcGVydHkoJ2F0dHJpYnV0ZXMnKSkge1xuICAgICAgICAgICAgICBmb3IgKHZhciBfaTMgPSAwLCBfT2JqZWN0JGVudHJpZXMzID0gT2JqZWN0LmVudHJpZXMoYnV0dG9uQ29uZmlnLmF0dHJpYnV0ZXMpOyBfaTMgPCBfT2JqZWN0JGVudHJpZXMzLmxlbmd0aDsgX2kzKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgX09iamVjdCRlbnRyaWVzMyRfaSA9IF9zbGljZWRUb0FycmF5KF9PYmplY3QkZW50cmllczNbX2kzXSwgMiksXG4gICAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZU5hbWUgPSBfT2JqZWN0JGVudHJpZXMzJF9pWzBdLFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IF9PYmplY3QkZW50cmllczMkX2lbMV07XG5cbiAgICAgICAgICAgICAgICBidXR0b25IdG1sICs9IFwiIFwiLmNvbmNhdChhdHRyaWJ1dGVOYW1lLCBcIj1cXFwiXCIpLmNvbmNhdCh2YWx1ZSwgXCJcXFwiXCIpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGJ1dHRvbkh0bWwgKz0gJz4nO1xuXG4gICAgICAgICAgICBpZiAob3B0cy5zaG93QnV0dG9uSWNvbnMgJiYgYnV0dG9uQ29uZmlnLmhhc093blByb3BlcnR5KCdpY29uJykpIHtcbiAgICAgICAgICAgICAgYnV0dG9uSHRtbCArPSBcIlwiLmNvbmNhdChVdGlscy5zcHJpbnRmKHRoaXMuY29uc3RhbnRzLmh0bWwuaWNvbiwgb3B0cy5pY29uc1ByZWZpeCwgYnV0dG9uQ29uZmlnLmljb24pLCBcIiBcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChvcHRzLnNob3dCdXR0b25UZXh0ICYmIGJ1dHRvbkNvbmZpZy5oYXNPd25Qcm9wZXJ0eSgndGV4dCcpKSB7XG4gICAgICAgICAgICAgIGJ1dHRvbkh0bWwgKz0gYnV0dG9uQ29uZmlnLnRleHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGJ1dHRvbkh0bWwgKz0gJzwvYnV0dG9uPic7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYnV0dG9uc0h0bWxbYnV0dG9uTmFtZV0gPSBidXR0b25IdG1sO1xuICAgICAgICAgIHZhciBvcHRpb25OYW1lID0gXCJzaG93XCIuY29uY2F0KGJ1dHRvbk5hbWUuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkpLmNvbmNhdChidXR0b25OYW1lLnN1YnN0cmluZygxKSk7XG4gICAgICAgICAgdmFyIHNob3dPcHRpb24gPSBvcHRzW29wdGlvbk5hbWVdO1xuXG4gICAgICAgICAgaWYgKCghYnV0dG9uQ29uZmlnLmhhc093blByb3BlcnR5KCdyZW5kZXInKSB8fCBidXR0b25Db25maWcuaGFzT3duUHJvcGVydHkoJ3JlbmRlcicpICYmIGJ1dHRvbkNvbmZpZy5yZW5kZXIpICYmIChzaG93T3B0aW9uID09PSB1bmRlZmluZWQgfHwgc2hvd09wdGlvbiA9PT0gdHJ1ZSkpIHtcbiAgICAgICAgICAgIG9wdHNbb3B0aW9uTmFtZV0gPSB0cnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghb3B0cy5idXR0b25zT3JkZXIuaW5jbHVkZXMoYnV0dG9uTmFtZSkpIHtcbiAgICAgICAgICAgIG9wdHMuYnV0dG9uc09yZGVyLnB1c2goYnV0dG9uTmFtZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IC8vIEFkZGluZyB0aGUgYnV0dG9uIGh0bWwgdG8gdGhlIGZpbmFsIHRvb2xiYXIgaHRtbCB3aGVuIHRoZSBzaG93T3B0aW9uIGlzIHRydWVcblxuXG4gICAgICAgIHZhciBfaXRlcmF0b3IgPSBfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlcihvcHRzLmJ1dHRvbnNPcmRlciksXG4gICAgICAgICAgICBfc3RlcDtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGZvciAoX2l0ZXJhdG9yLnMoKTsgIShfc3RlcCA9IF9pdGVyYXRvci5uKCkpLmRvbmU7KSB7XG4gICAgICAgICAgICB2YXIgYnV0dG9uID0gX3N0ZXAudmFsdWU7XG4gICAgICAgICAgICB2YXIgX3Nob3dPcHRpb24gPSBvcHRzW1wic2hvd1wiLmNvbmNhdChidXR0b24uY2hhckF0KDApLnRvVXBwZXJDYXNlKCkpLmNvbmNhdChidXR0b24uc3Vic3RyaW5nKDEpKV07XG5cbiAgICAgICAgICAgIGlmIChfc2hvd09wdGlvbikge1xuICAgICAgICAgICAgICBodG1sLnB1c2goYnV0dG9uc0h0bWxbYnV0dG9uXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBfaXRlcmF0b3IuZShlcnIpO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIF9pdGVyYXRvci5mKCk7XG4gICAgICAgIH1cblxuICAgICAgICBodG1sLnB1c2goJzwvZGl2PicpOyAvLyBGaXggIzE4ODogdGhpcy5zaG93VG9vbGJhciBpcyBmb3IgZXh0ZW5zaW9uc1xuXG4gICAgICAgIGlmICh0aGlzLnNob3dUb29sYmFyIHx8IGh0bWwubGVuZ3RoID4gMikge1xuICAgICAgICAgIHRoaXMuJHRvb2xiYXIuYXBwZW5kKGh0bWwuam9pbignJykpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yICh2YXIgX2k0ID0gMCwgX09iamVjdCRlbnRyaWVzNCA9IE9iamVjdC5lbnRyaWVzKHRoaXMuYnV0dG9ucyk7IF9pNCA8IF9PYmplY3QkZW50cmllczQubGVuZ3RoOyBfaTQrKykge1xuICAgICAgICAgIHZhciBfT2JqZWN0JGVudHJpZXM0JF9pID0gX3NsaWNlZFRvQXJyYXkoX09iamVjdCRlbnRyaWVzNFtfaTRdLCAyKSxcbiAgICAgICAgICAgICAgX2J1dHRvbk5hbWUgPSBfT2JqZWN0JGVudHJpZXM0JF9pWzBdLFxuICAgICAgICAgICAgICBfYnV0dG9uQ29uZmlnID0gX09iamVjdCRlbnRyaWVzNCRfaVsxXTtcblxuICAgICAgICAgIGlmIChfYnV0dG9uQ29uZmlnLmhhc093blByb3BlcnR5KCdldmVudCcpKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIF9idXR0b25Db25maWcuZXZlbnQgPT09ICdmdW5jdGlvbicgfHwgdHlwZW9mIF9idXR0b25Db25maWcuZXZlbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIHZhciBfcmV0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBldmVudCA9IHR5cGVvZiBfYnV0dG9uQ29uZmlnLmV2ZW50ID09PSAnc3RyaW5nJyA/IHdpbmRvd1tfYnV0dG9uQ29uZmlnLmV2ZW50XSA6IF9idXR0b25Db25maWcuZXZlbnQ7XG5cbiAgICAgICAgICAgICAgICBfdGhpczQuJHRvb2xiYXIuZmluZChcImJ1dHRvbltuYW1lPVxcXCJcIi5jb25jYXQoX2J1dHRvbk5hbWUsIFwiXFxcIl1cIikpLm9mZignY2xpY2snKS5vbignY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gZXZlbnQuY2FsbChfdGhpczQpO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIFwiY29udGludWVcIjtcbiAgICAgICAgICAgICAgfSgpO1xuXG4gICAgICAgICAgICAgIGlmIChfcmV0ID09PSBcImNvbnRpbnVlXCIpIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgX2xvb3AgPSBmdW5jdGlvbiBfbG9vcCgpIHtcbiAgICAgICAgICAgICAgdmFyIF9PYmplY3QkZW50cmllczUkX2kgPSBfc2xpY2VkVG9BcnJheShfT2JqZWN0JGVudHJpZXM1W19pNV0sIDIpLFxuICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlID0gX09iamVjdCRlbnRyaWVzNSRfaVswXSxcbiAgICAgICAgICAgICAgICAgIGV2ZW50RnVuY3Rpb24gPSBfT2JqZWN0JGVudHJpZXM1JF9pWzFdO1xuXG4gICAgICAgICAgICAgIHZhciBldmVudCA9IHR5cGVvZiBldmVudEZ1bmN0aW9uID09PSAnc3RyaW5nJyA/IHdpbmRvd1tldmVudEZ1bmN0aW9uXSA6IGV2ZW50RnVuY3Rpb247XG5cbiAgICAgICAgICAgICAgX3RoaXM0LiR0b29sYmFyLmZpbmQoXCJidXR0b25bbmFtZT1cXFwiXCIuY29uY2F0KF9idXR0b25OYW1lLCBcIlxcXCJdXCIpKS5vZmYoZXZlbnRUeXBlKS5vbihldmVudFR5cGUsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXZlbnQuY2FsbChfdGhpczQpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGZvciAodmFyIF9pNSA9IDAsIF9PYmplY3QkZW50cmllczUgPSBPYmplY3QuZW50cmllcyhfYnV0dG9uQ29uZmlnLmV2ZW50KTsgX2k1IDwgX09iamVjdCRlbnRyaWVzNS5sZW5ndGg7IF9pNSsrKSB7XG4gICAgICAgICAgICAgIF9sb29wKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG9wdHMuc2hvd0NvbHVtbnMpIHtcbiAgICAgICAgICAka2VlcE9wZW4gPSB0aGlzLiR0b29sYmFyLmZpbmQoJy5rZWVwLW9wZW4nKTtcbiAgICAgICAgICB2YXIgJGNoZWNrYm94ZXMgPSAka2VlcE9wZW4uZmluZCgnaW5wdXRbdHlwZT1cImNoZWNrYm94XCJdOm5vdChcIi50b2dnbGUtYWxsXCIpJyk7XG4gICAgICAgICAgdmFyICR0b2dnbGVBbGwgPSAka2VlcE9wZW4uZmluZCgnaW5wdXRbdHlwZT1cImNoZWNrYm94XCJdLnRvZ2dsZS1hbGwnKTtcblxuICAgICAgICAgIGlmIChzd2l0Y2hhYmxlQ291bnQgPD0gb3B0cy5taW5pbXVtQ291bnRDb2x1bW5zKSB7XG4gICAgICAgICAgICAka2VlcE9wZW4uZmluZCgnaW5wdXQnKS5wcm9wKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgICRrZWVwT3Blbi5maW5kKCdsaSwgbGFiZWwnKS5vZmYoJ2NsaWNrJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgJGNoZWNrYm94ZXMub2ZmKCdjbGljaycpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChfcmVmMikge1xuICAgICAgICAgICAgdmFyIGN1cnJlbnRUYXJnZXQgPSBfcmVmMi5jdXJyZW50VGFyZ2V0O1xuICAgICAgICAgICAgdmFyICR0aGlzID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKGN1cnJlbnRUYXJnZXQpO1xuXG4gICAgICAgICAgICBfdGhpczQuX3RvZ2dsZUNvbHVtbigkdGhpcy52YWwoKSwgJHRoaXMucHJvcCgnY2hlY2tlZCcpLCBmYWxzZSk7XG5cbiAgICAgICAgICAgIF90aGlzNC50cmlnZ2VyKCdjb2x1bW4tc3dpdGNoJywgJHRoaXMuZGF0YSgnZmllbGQnKSwgJHRoaXMucHJvcCgnY2hlY2tlZCcpKTtcblxuICAgICAgICAgICAgJHRvZ2dsZUFsbC5wcm9wKCdjaGVja2VkJywgJGNoZWNrYm94ZXMuZmlsdGVyKCc6Y2hlY2tlZCcpLmxlbmd0aCA9PT0gX3RoaXM0LmNvbHVtbnMuZmlsdGVyKGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgICAgcmV0dXJuICFfdGhpczQuaXNTZWxlY3Rpb25Db2x1bW4oY29sdW1uKTtcbiAgICAgICAgICAgIH0pLmxlbmd0aCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgJHRvZ2dsZUFsbC5vZmYoJ2NsaWNrJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKF9yZWYzKSB7XG4gICAgICAgICAgICB2YXIgY3VycmVudFRhcmdldCA9IF9yZWYzLmN1cnJlbnRUYXJnZXQ7XG5cbiAgICAgICAgICAgIF90aGlzNC5fdG9nZ2xlQWxsQ29sdW1ucygkX19kZWZhdWx0WydkZWZhdWx0J10oY3VycmVudFRhcmdldCkucHJvcCgnY2hlY2tlZCcpKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGlmIChvcHRzLnNob3dDb2x1bW5zU2VhcmNoKSB7XG4gICAgICAgICAgICB2YXIgJGNvbHVtbnNTZWFyY2ggPSAka2VlcE9wZW4uZmluZCgnW25hbWU9XCJjb2x1bW5zU2VhcmNoXCJdJyk7XG4gICAgICAgICAgICB2YXIgJGxpc3RJdGVtcyA9ICRrZWVwT3Blbi5maW5kKCcuZHJvcGRvd24taXRlbS1tYXJrZXInKTtcbiAgICAgICAgICAgICRjb2x1bW5zU2VhcmNoLm9uKCdrZXl1cCBwYXN0ZSBjaGFuZ2UnLCBmdW5jdGlvbiAoX3JlZjQpIHtcbiAgICAgICAgICAgICAgdmFyIGN1cnJlbnRUYXJnZXQgPSBfcmVmNC5jdXJyZW50VGFyZ2V0O1xuICAgICAgICAgICAgICB2YXIgJHRoaXMgPSAkX19kZWZhdWx0WydkZWZhdWx0J10oY3VycmVudFRhcmdldCk7XG4gICAgICAgICAgICAgIHZhciBzZWFyY2hWYWx1ZSA9ICR0aGlzLnZhbCgpLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgICAgICAgICRsaXN0SXRlbXMuc2hvdygpO1xuICAgICAgICAgICAgICAkY2hlY2tib3hlcy5lYWNoKGZ1bmN0aW9uIChpLCBlbCkge1xuICAgICAgICAgICAgICAgIHZhciAkY2hlY2tib3ggPSAkX19kZWZhdWx0WydkZWZhdWx0J10oZWwpO1xuICAgICAgICAgICAgICAgIHZhciAkbGlzdEl0ZW0gPSAkY2hlY2tib3gucGFyZW50cygnLmRyb3Bkb3duLWl0ZW0tbWFya2VyJyk7XG4gICAgICAgICAgICAgICAgdmFyIHRleHQgPSAkbGlzdEl0ZW0udGV4dCgpLnRvTG93ZXJDYXNlKCk7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXRleHQuaW5jbHVkZXMoc2VhcmNoVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAkbGlzdEl0ZW0uaGlkZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgaGFuZGxlSW5wdXRFdmVudCA9IGZ1bmN0aW9uIGhhbmRsZUlucHV0RXZlbnQoJHNlYXJjaElucHV0KSB7XG4gICAgICAgICAgdmFyIGV2ZW50VHJpZ2dlcnMgPSAna2V5dXAgZHJvcCBibHVyIG1vdXNldXAnO1xuICAgICAgICAgICRzZWFyY2hJbnB1dC5vZmYoZXZlbnRUcmlnZ2Vycykub24oZXZlbnRUcmlnZ2VycywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICBpZiAob3B0cy5zZWFyY2hPbkVudGVyS2V5ICYmIGV2ZW50LmtleUNvZGUgIT09IDEzKSB7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKFszNywgMzgsIDM5LCA0MF0uaW5jbHVkZXMoZXZlbnQua2V5Q29kZSkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dElkKTsgLy8gZG9lc24ndCBtYXR0ZXIgaWYgaXQncyAwXG5cbiAgICAgICAgICAgIHRpbWVvdXRJZCA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICBfdGhpczQub25TZWFyY2goe1xuICAgICAgICAgICAgICAgIGN1cnJlbnRUYXJnZXQ6IGV2ZW50LmN1cnJlbnRUYXJnZXRcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LCBvcHRzLnNlYXJjaFRpbWVPdXQpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9OyAvLyBGaXggIzQ1MTY6IHRoaXMuc2hvd1NlYXJjaENsZWFyQnV0dG9uIGlzIGZvciBleHRlbnNpb25zXG5cblxuICAgICAgICBpZiAoKG9wdHMuc2VhcmNoIHx8IHRoaXMuc2hvd1NlYXJjaENsZWFyQnV0dG9uKSAmJiB0eXBlb2Ygb3B0cy5zZWFyY2hTZWxlY3RvciAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBodG1sID0gW107XG4gICAgICAgICAgdmFyIHNob3dTZWFyY2hCdXR0b24gPSBVdGlscy5zcHJpbnRmKHRoaXMuY29uc3RhbnRzLmh0bWwuc2VhcmNoQnV0dG9uLCB0aGlzLmNvbnN0YW50cy5idXR0b25zQ2xhc3MsIG9wdHMuZm9ybWF0U2VhcmNoKCksIG9wdHMuc2hvd0J1dHRvbkljb25zID8gVXRpbHMuc3ByaW50Zih0aGlzLmNvbnN0YW50cy5odG1sLmljb24sIG9wdHMuaWNvbnNQcmVmaXgsIG9wdHMuaWNvbnMuc2VhcmNoKSA6ICcnLCBvcHRzLnNob3dCdXR0b25UZXh0ID8gb3B0cy5mb3JtYXRTZWFyY2goKSA6ICcnKTtcbiAgICAgICAgICB2YXIgc2hvd1NlYXJjaENsZWFyQnV0dG9uID0gVXRpbHMuc3ByaW50Zih0aGlzLmNvbnN0YW50cy5odG1sLnNlYXJjaENsZWFyQnV0dG9uLCB0aGlzLmNvbnN0YW50cy5idXR0b25zQ2xhc3MsIG9wdHMuZm9ybWF0Q2xlYXJTZWFyY2goKSwgb3B0cy5zaG93QnV0dG9uSWNvbnMgPyBVdGlscy5zcHJpbnRmKHRoaXMuY29uc3RhbnRzLmh0bWwuaWNvbiwgb3B0cy5pY29uc1ByZWZpeCwgb3B0cy5pY29ucy5jbGVhclNlYXJjaCkgOiAnJywgb3B0cy5zaG93QnV0dG9uVGV4dCA/IG9wdHMuZm9ybWF0Q2xlYXJTZWFyY2goKSA6ICcnKTtcbiAgICAgICAgICB2YXIgc2VhcmNoSW5wdXRIdG1sID0gXCI8aW5wdXQgY2xhc3M9XFxcIlwiLmNvbmNhdCh0aGlzLmNvbnN0YW50cy5jbGFzc2VzLmlucHV0LCBcIlxcbiAgICAgICAgXCIpLmNvbmNhdChVdGlscy5zcHJpbnRmKCcgJXMlcycsIHRoaXMuY29uc3RhbnRzLmNsYXNzZXMuaW5wdXRQcmVmaXgsIG9wdHMuaWNvblNpemUpLCBcIlxcbiAgICAgICAgc2VhcmNoLWlucHV0XFxcIiB0eXBlPVxcXCJzZWFyY2hcXFwiIHBsYWNlaG9sZGVyPVxcXCJcIikuY29uY2F0KG9wdHMuZm9ybWF0U2VhcmNoKCksIFwiXFxcIiBhdXRvY29tcGxldGU9XFxcIm9mZlxcXCI+XCIpO1xuICAgICAgICAgIHZhciBzZWFyY2hJbnB1dEZpbmFsSHRtbCA9IHNlYXJjaElucHV0SHRtbDtcblxuICAgICAgICAgIGlmIChvcHRzLnNob3dTZWFyY2hCdXR0b24gfHwgb3B0cy5zaG93U2VhcmNoQ2xlYXJCdXR0b24pIHtcbiAgICAgICAgICAgIHZhciBfYnV0dG9uc0h0bWwgPSAob3B0cy5zaG93U2VhcmNoQnV0dG9uID8gc2hvd1NlYXJjaEJ1dHRvbiA6ICcnKSArIChvcHRzLnNob3dTZWFyY2hDbGVhckJ1dHRvbiA/IHNob3dTZWFyY2hDbGVhckJ1dHRvbiA6ICcnKTtcblxuICAgICAgICAgICAgc2VhcmNoSW5wdXRGaW5hbEh0bWwgPSBvcHRzLnNlYXJjaCA/IFV0aWxzLnNwcmludGYodGhpcy5jb25zdGFudHMuaHRtbC5pbnB1dEdyb3VwLCBzZWFyY2hJbnB1dEh0bWwsIF9idXR0b25zSHRtbCkgOiBfYnV0dG9uc0h0bWw7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaHRtbC5wdXNoKFV0aWxzLnNwcmludGYoXCJcXG4gICAgICAgIDxkaXYgY2xhc3M9XFxcIlwiLmNvbmNhdCh0aGlzLmNvbnN0YW50cy5jbGFzc2VzLnB1bGwsIFwiLVwiKS5jb25jYXQob3B0cy5zZWFyY2hBbGlnbiwgXCIgc2VhcmNoIFwiKS5jb25jYXQodGhpcy5jb25zdGFudHMuY2xhc3Nlcy5pbnB1dEdyb3VwLCBcIlxcXCI+XFxuICAgICAgICAgICVzXFxuICAgICAgICA8L2Rpdj5cXG4gICAgICBcIiksIHNlYXJjaElucHV0RmluYWxIdG1sKSk7XG4gICAgICAgICAgdGhpcy4kdG9vbGJhci5hcHBlbmQoaHRtbC5qb2luKCcnKSk7XG4gICAgICAgICAgdmFyICRzZWFyY2hJbnB1dCA9IFV0aWxzLmdldFNlYXJjaElucHV0KHRoaXMpO1xuXG4gICAgICAgICAgaWYgKG9wdHMuc2hvd1NlYXJjaEJ1dHRvbikge1xuICAgICAgICAgICAgdGhpcy4kdG9vbGJhci5maW5kKCcuc2VhcmNoIGJ1dHRvbltuYW1lPXNlYXJjaF0nKS5vZmYoJ2NsaWNrJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dElkKTsgLy8gZG9lc24ndCBtYXR0ZXIgaWYgaXQncyAwXG5cbiAgICAgICAgICAgICAgdGltZW91dElkID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXM0Lm9uU2VhcmNoKHtcbiAgICAgICAgICAgICAgICAgIGN1cnJlbnRUYXJnZXQ6ICRzZWFyY2hJbnB1dFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9LCBvcHRzLnNlYXJjaFRpbWVPdXQpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGlmIChvcHRzLnNlYXJjaE9uRW50ZXJLZXkpIHtcbiAgICAgICAgICAgICAgaGFuZGxlSW5wdXRFdmVudCgkc2VhcmNoSW5wdXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBoYW5kbGVJbnB1dEV2ZW50KCRzZWFyY2hJbnB1dCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKG9wdHMuc2hvd1NlYXJjaENsZWFyQnV0dG9uKSB7XG4gICAgICAgICAgICB0aGlzLiR0b29sYmFyLmZpbmQoJy5zZWFyY2ggYnV0dG9uW25hbWU9Y2xlYXJTZWFyY2hdJykuY2xpY2soZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICBfdGhpczQucmVzZXRTZWFyY2goKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygb3B0cy5zZWFyY2hTZWxlY3RvciA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICB2YXIgXyRzZWFyY2hJbnB1dCA9IFV0aWxzLmdldFNlYXJjaElucHV0KHRoaXMpO1xuXG4gICAgICAgICAgaGFuZGxlSW5wdXRFdmVudChfJHNlYXJjaElucHV0KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJvblNlYXJjaFwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIG9uU2VhcmNoKCkge1xuICAgICAgICB2YXIgX3JlZjUgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IHt9LFxuICAgICAgICAgICAgY3VycmVudFRhcmdldCA9IF9yZWY1LmN1cnJlbnRUYXJnZXQsXG4gICAgICAgICAgICBmaXJlZEJ5SW5pdFNlYXJjaFRleHQgPSBfcmVmNS5maXJlZEJ5SW5pdFNlYXJjaFRleHQ7XG5cbiAgICAgICAgdmFyIG92ZXJ3cml0ZVNlYXJjaFRleHQgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHRydWU7XG5cbiAgICAgICAgaWYgKGN1cnJlbnRUYXJnZXQgIT09IHVuZGVmaW5lZCAmJiAkX19kZWZhdWx0WydkZWZhdWx0J10oY3VycmVudFRhcmdldCkubGVuZ3RoICYmIG92ZXJ3cml0ZVNlYXJjaFRleHQpIHtcbiAgICAgICAgICB2YXIgdGV4dCA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShjdXJyZW50VGFyZ2V0KS52YWwoKS50cmltKCk7XG5cbiAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLnRyaW1PblNlYXJjaCAmJiAkX19kZWZhdWx0WydkZWZhdWx0J10oY3VycmVudFRhcmdldCkudmFsKCkgIT09IHRleHQpIHtcbiAgICAgICAgICAgICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShjdXJyZW50VGFyZ2V0KS52YWwodGV4dCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHRoaXMuc2VhcmNoVGV4dCA9PT0gdGV4dCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChjdXJyZW50VGFyZ2V0ID09PSBVdGlscy5nZXRTZWFyY2hJbnB1dCh0aGlzKVswXSB8fCAkX19kZWZhdWx0WydkZWZhdWx0J10oY3VycmVudFRhcmdldCkuaGFzQ2xhc3MoJ3NlYXJjaC1pbnB1dCcpKSB7XG4gICAgICAgICAgICB0aGlzLnNlYXJjaFRleHQgPSB0ZXh0O1xuICAgICAgICAgICAgdGhpcy5vcHRpb25zLnNlYXJjaFRleHQgPSB0ZXh0O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghZmlyZWRCeUluaXRTZWFyY2hUZXh0KSB7XG4gICAgICAgICAgdGhpcy5vcHRpb25zLnBhZ2VOdW1iZXIgPSAxO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5pbml0U2VhcmNoKCk7XG5cbiAgICAgICAgaWYgKGZpcmVkQnlJbml0U2VhcmNoVGV4dCkge1xuICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMuc2lkZVBhZ2luYXRpb24gPT09ICdjbGllbnQnKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVBhZ2luYXRpb24oKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy51cGRhdGVQYWdpbmF0aW9uKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnRyaWdnZXIoJ3NlYXJjaCcsIHRoaXMuc2VhcmNoVGV4dCk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImluaXRTZWFyY2hcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0U2VhcmNoKCkge1xuICAgICAgICB2YXIgX3RoaXM1ID0gdGhpcztcblxuICAgICAgICB0aGlzLmZpbHRlck9wdGlvbnMgPSB0aGlzLmZpbHRlck9wdGlvbnMgfHwgdGhpcy5vcHRpb25zLmZpbHRlck9wdGlvbnM7XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5zaWRlUGFnaW5hdGlvbiAhPT0gJ3NlcnZlcicpIHtcbiAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLmN1c3RvbVNlYXJjaCkge1xuICAgICAgICAgICAgdGhpcy5kYXRhID0gVXRpbHMuY2FsY3VsYXRlT2JqZWN0VmFsdWUodGhpcy5vcHRpb25zLCB0aGlzLm9wdGlvbnMuY3VzdG9tU2VhcmNoLCBbdGhpcy5vcHRpb25zLmRhdGEsIHRoaXMuc2VhcmNoVGV4dCwgdGhpcy5maWx0ZXJDb2x1bW5zXSk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMuc29ydFJlc2V0KSB7XG4gICAgICAgICAgICAgIHRoaXMudW5zb3J0ZWREYXRhID0gX3RvQ29uc3VtYWJsZUFycmF5KHRoaXMuZGF0YSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgcyA9IHRoaXMuc2VhcmNoVGV4dCAmJiAodGhpcy5mcm9tSHRtbCA/IFV0aWxzLmVzY2FwZUhUTUwodGhpcy5zZWFyY2hUZXh0KSA6IHRoaXMuc2VhcmNoVGV4dCkudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICB2YXIgZiA9IFV0aWxzLmlzRW1wdHlPYmplY3QodGhpcy5maWx0ZXJDb2x1bW5zKSA/IG51bGwgOiB0aGlzLmZpbHRlckNvbHVtbnM7XG5cbiAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNlYXJjaEFjY2VudE5ldXRyYWxpc2UpIHtcbiAgICAgICAgICAgIHMgPSBVdGlscy5ub3JtYWxpemVBY2NlbnQocyk7XG4gICAgICAgICAgfSAvLyBDaGVjayBmaWx0ZXJcblxuXG4gICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLmZpbHRlck9wdGlvbnMuZmlsdGVyQWxnb3JpdGhtID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICB0aGlzLmRhdGEgPSB0aGlzLm9wdGlvbnMuZGF0YS5maWx0ZXIoZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgICAgICAgcmV0dXJuIF90aGlzNS5maWx0ZXJPcHRpb25zLmZpbHRlckFsZ29yaXRobS5hcHBseShudWxsLCBbaXRlbSwgZl0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpcy5maWx0ZXJPcHRpb25zLmZpbHRlckFsZ29yaXRobSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRoaXMuZGF0YSA9IGYgPyB0aGlzLm9wdGlvbnMuZGF0YS5maWx0ZXIoZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgICAgICAgdmFyIGZpbHRlckFsZ29yaXRobSA9IF90aGlzNS5maWx0ZXJPcHRpb25zLmZpbHRlckFsZ29yaXRobTtcblxuICAgICAgICAgICAgICBpZiAoZmlsdGVyQWxnb3JpdGhtID09PSAnYW5kJykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBmKSB7XG4gICAgICAgICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShmW2tleV0pICYmICFmW2tleV0uaW5jbHVkZXMoaXRlbVtrZXldKSB8fCAhQXJyYXkuaXNBcnJheShmW2tleV0pICYmIGl0ZW1ba2V5XSAhPT0gZltrZXldKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAoZmlsdGVyQWxnb3JpdGhtID09PSAnb3InKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1hdGNoID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBfa2V5IGluIGYpIHtcbiAgICAgICAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGZbX2tleV0pICYmIGZbX2tleV0uaW5jbHVkZXMoaXRlbVtfa2V5XSkgfHwgIUFycmF5LmlzQXJyYXkoZltfa2V5XSkgJiYgaXRlbVtfa2V5XSA9PT0gZltfa2V5XSkge1xuICAgICAgICAgICAgICAgICAgICBtYXRjaCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG1hdGNoO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9KSA6IF90b0NvbnN1bWFibGVBcnJheSh0aGlzLm9wdGlvbnMuZGF0YSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIHZpc2libGVGaWVsZHMgPSB0aGlzLmdldFZpc2libGVGaWVsZHMoKTtcbiAgICAgICAgICB0aGlzLmRhdGEgPSBzID8gdGhpcy5kYXRhLmZpbHRlcihmdW5jdGlvbiAoaXRlbSwgaSkge1xuICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBfdGhpczUuaGVhZGVyLmZpZWxkcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICBpZiAoIV90aGlzNS5oZWFkZXIuc2VhcmNoYWJsZXNbal0gfHwgX3RoaXM1Lm9wdGlvbnMudmlzaWJsZVNlYXJjaCAmJiB2aXNpYmxlRmllbGRzLmluZGV4T2YoX3RoaXM1LmhlYWRlci5maWVsZHNbal0pID09PSAtMSkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgdmFyIGtleSA9IFV0aWxzLmlzTnVtZXJpYyhfdGhpczUuaGVhZGVyLmZpZWxkc1tqXSkgPyBwYXJzZUludChfdGhpczUuaGVhZGVyLmZpZWxkc1tqXSwgMTApIDogX3RoaXM1LmhlYWRlci5maWVsZHNbal07XG4gICAgICAgICAgICAgIHZhciBjb2x1bW4gPSBfdGhpczUuY29sdW1uc1tfdGhpczUuZmllbGRzQ29sdW1uc0luZGV4W2tleV1dO1xuICAgICAgICAgICAgICB2YXIgdmFsdWUgPSB2b2lkIDA7XG5cbiAgICAgICAgICAgICAgaWYgKHR5cGVvZiBrZXkgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSBpdGVtO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IGtleS5zcGxpdCgnLicpO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgX2k2ID0gMDsgX2k2IDwgcHJvcHMubGVuZ3RoOyBfaTYrKykge1xuICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlW3Byb3BzW19pNl1dICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWVbcHJvcHNbX2k2XV07XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gaXRlbVtrZXldO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKF90aGlzNS5vcHRpb25zLnNlYXJjaEFjY2VudE5ldXRyYWxpc2UpIHtcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IFV0aWxzLm5vcm1hbGl6ZUFjY2VudCh2YWx1ZSk7XG4gICAgICAgICAgICAgIH0gLy8gRml4ICMxNDI6IHJlc3BlY3Qgc2VhcmNoRm9ybWF0dGVyIGJvb2xlYW5cblxuXG4gICAgICAgICAgICAgIGlmIChjb2x1bW4gJiYgY29sdW1uLnNlYXJjaEZvcm1hdHRlcikge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gVXRpbHMuY2FsY3VsYXRlT2JqZWN0VmFsdWUoY29sdW1uLCBfdGhpczUuaGVhZGVyLmZvcm1hdHRlcnNbal0sIFt2YWx1ZSwgaXRlbSwgaSwgY29sdW1uLmZpZWxkXSwgdmFsdWUpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpczUub3B0aW9ucy5zdHJpY3RTZWFyY2gpIHtcbiAgICAgICAgICAgICAgICAgIGlmIChcIlwiLmNvbmNhdCh2YWx1ZSkudG9Mb3dlckNhc2UoKSA9PT0gcykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgdmFyIGxhcmdlclNtYWxsZXJFcXVhbHNSZWdleCA9IC8oPzooPD18PT58PTx8Pj18Pnw8KSg/OlxccyspPygtP1xcZCspP3woLT9cXGQrKT8oXFxzKyk/KDw9fD0+fD08fD49fD58PCkpL2dtO1xuICAgICAgICAgICAgICAgICAgdmFyIG1hdGNoZXMgPSBsYXJnZXJTbWFsbGVyRXF1YWxzUmVnZXguZXhlYyhfdGhpczUuc2VhcmNoVGV4dCk7XG4gICAgICAgICAgICAgICAgICB2YXIgY29tcGFyaXNvbkNoZWNrID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICAgIGlmIChtYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBvcGVyYXRvciA9IG1hdGNoZXNbMV0gfHwgXCJcIi5jb25jYXQobWF0Y2hlc1s1XSwgXCJsXCIpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgY29tcGFyaXNvblZhbHVlID0gbWF0Y2hlc1syXSB8fCBtYXRjaGVzWzNdO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaW50ID0gcGFyc2VJbnQodmFsdWUsIDEwKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNvbXBhcmlzb25JbnQgPSBwYXJzZUludChjb21wYXJpc29uVmFsdWUsIDEwKTtcblxuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKG9wZXJhdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSAnPic6XG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSAnPGwnOlxuICAgICAgICAgICAgICAgICAgICAgICAgY29tcGFyaXNvbkNoZWNrID0gaW50ID4gY29tcGFyaXNvbkludDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSAnPCc6XG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSAnPmwnOlxuICAgICAgICAgICAgICAgICAgICAgICAgY29tcGFyaXNvbkNoZWNrID0gaW50IDwgY29tcGFyaXNvbkludDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSAnPD0nOlxuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJz08JzpcbiAgICAgICAgICAgICAgICAgICAgICBjYXNlICc+PWwnOlxuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJz0+bCc6XG4gICAgICAgICAgICAgICAgICAgICAgICBjb21wYXJpc29uQ2hlY2sgPSBpbnQgPD0gY29tcGFyaXNvbkludDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSAnPj0nOlxuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJz0+JzpcbiAgICAgICAgICAgICAgICAgICAgICBjYXNlICc8PWwnOlxuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJz08bCc6XG4gICAgICAgICAgICAgICAgICAgICAgICBjb21wYXJpc29uQ2hlY2sgPSBpbnQgPj0gY29tcGFyaXNvbkludDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgIGlmIChjb21wYXJpc29uQ2hlY2sgfHwgXCJcIi5jb25jYXQodmFsdWUpLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMocykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9KSA6IHRoaXMuZGF0YTtcblxuICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMuc29ydFJlc2V0KSB7XG4gICAgICAgICAgICB0aGlzLnVuc29ydGVkRGF0YSA9IF90b0NvbnN1bWFibGVBcnJheSh0aGlzLmRhdGEpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuaW5pdFNvcnQoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJpbml0UGFnaW5hdGlvblwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGluaXRQYWdpbmF0aW9uKCkge1xuICAgICAgICB2YXIgX3RoaXM2ID0gdGhpcztcblxuICAgICAgICB2YXIgb3B0cyA9IHRoaXMub3B0aW9ucztcblxuICAgICAgICBpZiAoIW9wdHMucGFnaW5hdGlvbikge1xuICAgICAgICAgIHRoaXMuJHBhZ2luYXRpb24uaGlkZSgpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuJHBhZ2luYXRpb24uc2hvdygpO1xuICAgICAgICB2YXIgaHRtbCA9IFtdO1xuICAgICAgICB2YXIgYWxsU2VsZWN0ZWQgPSBmYWxzZTtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBmcm9tO1xuICAgICAgICB2YXIgdG87XG4gICAgICAgIHZhciAkcGFnZUxpc3Q7XG4gICAgICAgIHZhciAkcHJlO1xuICAgICAgICB2YXIgJG5leHQ7XG4gICAgICAgIHZhciAkbnVtYmVyO1xuICAgICAgICB2YXIgZGF0YSA9IHRoaXMuZ2V0RGF0YSh7XG4gICAgICAgICAgaW5jbHVkZUhpZGRlblJvd3M6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgcGFnZUxpc3QgPSBvcHRzLnBhZ2VMaXN0O1xuXG4gICAgICAgIGlmICh0eXBlb2YgcGFnZUxpc3QgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgcGFnZUxpc3QgPSBwYWdlTGlzdC5yZXBsYWNlKC9cXFt8XFxdfCAvZywgJycpLnRvTG93ZXJDYXNlKCkuc3BsaXQoJywnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHBhZ2VMaXN0ID0gcGFnZUxpc3QubWFwKGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWUudG9Mb3dlckNhc2UoKSA9PT0gb3B0cy5mb3JtYXRBbGxSb3dzKCkudG9Mb3dlckNhc2UoKSB8fCBbJ2FsbCcsICd1bmxpbWl0ZWQnXS5pbmNsdWRlcyh2YWx1ZS50b0xvd2VyQ2FzZSgpKSA/IG9wdHMuZm9ybWF0QWxsUm93cygpIDogK3ZhbHVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMucGFnaW5hdGlvblBhcnRzID0gb3B0cy5wYWdpbmF0aW9uUGFydHM7XG5cbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLnBhZ2luYXRpb25QYXJ0cyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICB0aGlzLnBhZ2luYXRpb25QYXJ0cyA9IHRoaXMucGFnaW5hdGlvblBhcnRzLnJlcGxhY2UoL1xcW3xcXF18IHwnL2csICcnKS5zcGxpdCgnLCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG9wdHMuc2lkZVBhZ2luYXRpb24gIT09ICdzZXJ2ZXInKSB7XG4gICAgICAgICAgb3B0cy50b3RhbFJvd3MgPSBkYXRhLmxlbmd0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudG90YWxQYWdlcyA9IDA7XG5cbiAgICAgICAgaWYgKG9wdHMudG90YWxSb3dzKSB7XG4gICAgICAgICAgaWYgKG9wdHMucGFnZVNpemUgPT09IG9wdHMuZm9ybWF0QWxsUm93cygpKSB7XG4gICAgICAgICAgICBvcHRzLnBhZ2VTaXplID0gb3B0cy50b3RhbFJvd3M7XG4gICAgICAgICAgICBhbGxTZWxlY3RlZCA9IHRydWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy50b3RhbFBhZ2VzID0gfn4oKG9wdHMudG90YWxSb3dzIC0gMSkgLyBvcHRzLnBhZ2VTaXplKSArIDE7XG4gICAgICAgICAgb3B0cy50b3RhbFBhZ2VzID0gdGhpcy50b3RhbFBhZ2VzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMudG90YWxQYWdlcyA+IDAgJiYgb3B0cy5wYWdlTnVtYmVyID4gdGhpcy50b3RhbFBhZ2VzKSB7XG4gICAgICAgICAgb3B0cy5wYWdlTnVtYmVyID0gdGhpcy50b3RhbFBhZ2VzO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5wYWdlRnJvbSA9IChvcHRzLnBhZ2VOdW1iZXIgLSAxKSAqIG9wdHMucGFnZVNpemUgKyAxO1xuICAgICAgICB0aGlzLnBhZ2VUbyA9IG9wdHMucGFnZU51bWJlciAqIG9wdHMucGFnZVNpemU7XG5cbiAgICAgICAgaWYgKHRoaXMucGFnZVRvID4gb3B0cy50b3RhbFJvd3MpIHtcbiAgICAgICAgICB0aGlzLnBhZ2VUbyA9IG9wdHMudG90YWxSb3dzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5wYWdpbmF0aW9uICYmIHRoaXMub3B0aW9ucy5zaWRlUGFnaW5hdGlvbiAhPT0gJ3NlcnZlcicpIHtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMudG90YWxOb3RGaWx0ZXJlZCA9IHRoaXMub3B0aW9ucy5kYXRhLmxlbmd0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5vcHRpb25zLnNob3dFeHRlbmRlZFBhZ2luYXRpb24pIHtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMudG90YWxOb3RGaWx0ZXJlZCA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnBhZ2luYXRpb25QYXJ0cy5pbmNsdWRlcygncGFnZUluZm8nKSB8fCB0aGlzLnBhZ2luYXRpb25QYXJ0cy5pbmNsdWRlcygncGFnZUluZm9TaG9ydCcpIHx8IHRoaXMucGFnaW5hdGlvblBhcnRzLmluY2x1ZGVzKCdwYWdlU2l6ZScpKSB7XG4gICAgICAgICAgaHRtbC5wdXNoKFwiPGRpdiBjbGFzcz1cXFwiXCIuY29uY2F0KHRoaXMuY29uc3RhbnRzLmNsYXNzZXMucHVsbCwgXCItXCIpLmNvbmNhdChvcHRzLnBhZ2luYXRpb25EZXRhaWxIQWxpZ24sIFwiIHBhZ2luYXRpb24tZGV0YWlsXFxcIj5cIikpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMucGFnaW5hdGlvblBhcnRzLmluY2x1ZGVzKCdwYWdlSW5mbycpIHx8IHRoaXMucGFnaW5hdGlvblBhcnRzLmluY2x1ZGVzKCdwYWdlSW5mb1Nob3J0JykpIHtcbiAgICAgICAgICB2YXIgcGFnaW5hdGlvbkluZm8gPSB0aGlzLnBhZ2luYXRpb25QYXJ0cy5pbmNsdWRlcygncGFnZUluZm9TaG9ydCcpID8gb3B0cy5mb3JtYXREZXRhaWxQYWdpbmF0aW9uKG9wdHMudG90YWxSb3dzKSA6IG9wdHMuZm9ybWF0U2hvd2luZ1Jvd3ModGhpcy5wYWdlRnJvbSwgdGhpcy5wYWdlVG8sIG9wdHMudG90YWxSb3dzLCBvcHRzLnRvdGFsTm90RmlsdGVyZWQpO1xuICAgICAgICAgIGh0bWwucHVzaChcIjxzcGFuIGNsYXNzPVxcXCJwYWdpbmF0aW9uLWluZm9cXFwiPlxcbiAgICAgIFwiLmNvbmNhdChwYWdpbmF0aW9uSW5mbywgXCJcXG4gICAgICA8L3NwYW4+XCIpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnBhZ2luYXRpb25QYXJ0cy5pbmNsdWRlcygncGFnZVNpemUnKSkge1xuICAgICAgICAgIGh0bWwucHVzaCgnPGRpdiBjbGFzcz1cInBhZ2UtbGlzdFwiPicpO1xuICAgICAgICAgIHZhciBwYWdlTnVtYmVyID0gW1wiPGRpdiBjbGFzcz1cXFwiXCIuY29uY2F0KHRoaXMuY29uc3RhbnRzLmNsYXNzZXMucGFnaW5hdGlvbkRyb3Bkb3duLCBcIlxcXCI+XFxuICAgICAgICA8YnV0dG9uIGNsYXNzPVxcXCJcIikuY29uY2F0KHRoaXMuY29uc3RhbnRzLmJ1dHRvbnNDbGFzcywgXCIgZHJvcGRvd24tdG9nZ2xlXFxcIiB0eXBlPVxcXCJidXR0b25cXFwiIFwiKS5jb25jYXQodGhpcy5jb25zdGFudHMuZGF0YVRvZ2dsZSwgXCI9XFxcImRyb3Bkb3duXFxcIj5cXG4gICAgICAgIDxzcGFuIGNsYXNzPVxcXCJwYWdlLXNpemVcXFwiPlxcbiAgICAgICAgXCIpLmNvbmNhdChhbGxTZWxlY3RlZCA/IG9wdHMuZm9ybWF0QWxsUm93cygpIDogb3B0cy5wYWdlU2l6ZSwgXCJcXG4gICAgICAgIDwvc3Bhbj5cXG4gICAgICAgIFwiKS5jb25jYXQodGhpcy5jb25zdGFudHMuaHRtbC5kcm9wZG93bkNhcmV0LCBcIlxcbiAgICAgICAgPC9idXR0b24+XFxuICAgICAgICBcIikuY29uY2F0KHRoaXMuY29uc3RhbnRzLmh0bWwucGFnZURyb3Bkb3duWzBdKV07XG4gICAgICAgICAgcGFnZUxpc3QuZm9yRWFjaChmdW5jdGlvbiAocGFnZSwgaSkge1xuICAgICAgICAgICAgaWYgKCFvcHRzLnNtYXJ0RGlzcGxheSB8fCBpID09PSAwIHx8IHBhZ2VMaXN0W2kgLSAxXSA8IG9wdHMudG90YWxSb3dzIHx8IHBhZ2UgPT09IG9wdHMuZm9ybWF0QWxsUm93cygpKSB7XG4gICAgICAgICAgICAgIHZhciBhY3RpdmU7XG5cbiAgICAgICAgICAgICAgaWYgKGFsbFNlbGVjdGVkKSB7XG4gICAgICAgICAgICAgICAgYWN0aXZlID0gcGFnZSA9PT0gb3B0cy5mb3JtYXRBbGxSb3dzKCkgPyBfdGhpczYuY29uc3RhbnRzLmNsYXNzZXMuZHJvcGRvd25BY3RpdmUgOiAnJztcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhY3RpdmUgPSBwYWdlID09PSBvcHRzLnBhZ2VTaXplID8gX3RoaXM2LmNvbnN0YW50cy5jbGFzc2VzLmRyb3Bkb3duQWN0aXZlIDogJyc7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBwYWdlTnVtYmVyLnB1c2goVXRpbHMuc3ByaW50ZihfdGhpczYuY29uc3RhbnRzLmh0bWwucGFnZURyb3Bkb3duSXRlbSwgYWN0aXZlLCBwYWdlKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcGFnZU51bWJlci5wdXNoKFwiXCIuY29uY2F0KHRoaXMuY29uc3RhbnRzLmh0bWwucGFnZURyb3Bkb3duWzFdLCBcIjwvZGl2PlwiKSk7XG4gICAgICAgICAgaHRtbC5wdXNoKG9wdHMuZm9ybWF0UmVjb3Jkc1BlclBhZ2UocGFnZU51bWJlci5qb2luKCcnKSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMucGFnaW5hdGlvblBhcnRzLmluY2x1ZGVzKCdwYWdlSW5mbycpIHx8IHRoaXMucGFnaW5hdGlvblBhcnRzLmluY2x1ZGVzKCdwYWdlSW5mb1Nob3J0JykgfHwgdGhpcy5wYWdpbmF0aW9uUGFydHMuaW5jbHVkZXMoJ3BhZ2VTaXplJykpIHtcbiAgICAgICAgICBodG1sLnB1c2goJzwvZGl2PjwvZGl2PicpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMucGFnaW5hdGlvblBhcnRzLmluY2x1ZGVzKCdwYWdlTGlzdCcpKSB7XG4gICAgICAgICAgaHRtbC5wdXNoKFwiPGRpdiBjbGFzcz1cXFwiXCIuY29uY2F0KHRoaXMuY29uc3RhbnRzLmNsYXNzZXMucHVsbCwgXCItXCIpLmNvbmNhdChvcHRzLnBhZ2luYXRpb25IQWxpZ24sIFwiIHBhZ2luYXRpb25cXFwiPlwiKSwgVXRpbHMuc3ByaW50Zih0aGlzLmNvbnN0YW50cy5odG1sLnBhZ2luYXRpb25bMF0sIFV0aWxzLnNwcmludGYoJyBwYWdpbmF0aW9uLSVzJywgb3B0cy5pY29uU2l6ZSkpLCBVdGlscy5zcHJpbnRmKHRoaXMuY29uc3RhbnRzLmh0bWwucGFnaW5hdGlvbkl0ZW0sICcgcGFnZS1wcmUnLCBvcHRzLmZvcm1hdFNSUGFnaW5hdGlvblByZVRleHQoKSwgb3B0cy5wYWdpbmF0aW9uUHJlVGV4dCkpO1xuXG4gICAgICAgICAgaWYgKHRoaXMudG90YWxQYWdlcyA8IG9wdHMucGFnaW5hdGlvblN1Y2Nlc3NpdmVseVNpemUpIHtcbiAgICAgICAgICAgIGZyb20gPSAxO1xuICAgICAgICAgICAgdG8gPSB0aGlzLnRvdGFsUGFnZXM7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZyb20gPSBvcHRzLnBhZ2VOdW1iZXIgLSBvcHRzLnBhZ2luYXRpb25QYWdlc0J5U2lkZTtcbiAgICAgICAgICAgIHRvID0gZnJvbSArIG9wdHMucGFnaW5hdGlvblBhZ2VzQnlTaWRlICogMjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAob3B0cy5wYWdlTnVtYmVyIDwgb3B0cy5wYWdpbmF0aW9uU3VjY2Vzc2l2ZWx5U2l6ZSAtIDEpIHtcbiAgICAgICAgICAgIHRvID0gb3B0cy5wYWdpbmF0aW9uU3VjY2Vzc2l2ZWx5U2l6ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAob3B0cy5wYWdpbmF0aW9uU3VjY2Vzc2l2ZWx5U2l6ZSA+IHRoaXMudG90YWxQYWdlcyAtIGZyb20pIHtcbiAgICAgICAgICAgIGZyb20gPSBmcm9tIC0gKG9wdHMucGFnaW5hdGlvblN1Y2Nlc3NpdmVseVNpemUgLSAodGhpcy50b3RhbFBhZ2VzIC0gZnJvbSkpICsgMTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoZnJvbSA8IDEpIHtcbiAgICAgICAgICAgIGZyb20gPSAxO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0byA+IHRoaXMudG90YWxQYWdlcykge1xuICAgICAgICAgICAgdG8gPSB0aGlzLnRvdGFsUGFnZXM7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIG1pZGRsZVNpemUgPSBNYXRoLnJvdW5kKG9wdHMucGFnaW5hdGlvblBhZ2VzQnlTaWRlIC8gMik7XG5cbiAgICAgICAgICB2YXIgcGFnZUl0ZW0gPSBmdW5jdGlvbiBwYWdlSXRlbShpKSB7XG4gICAgICAgICAgICB2YXIgY2xhc3NlcyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogJyc7XG4gICAgICAgICAgICByZXR1cm4gVXRpbHMuc3ByaW50ZihfdGhpczYuY29uc3RhbnRzLmh0bWwucGFnaW5hdGlvbkl0ZW0sIGNsYXNzZXMgKyAoaSA9PT0gb3B0cy5wYWdlTnVtYmVyID8gXCIgXCIuY29uY2F0KF90aGlzNi5jb25zdGFudHMuY2xhc3Nlcy5wYWdpbmF0aW9uQWN0aXZlKSA6ICcnKSwgb3B0cy5mb3JtYXRTUlBhZ2luYXRpb25QYWdlVGV4dChpKSwgaSk7XG4gICAgICAgICAgfTtcblxuICAgICAgICAgIGlmIChmcm9tID4gMSkge1xuICAgICAgICAgICAgdmFyIG1heCA9IG9wdHMucGFnaW5hdGlvblBhZ2VzQnlTaWRlO1xuICAgICAgICAgICAgaWYgKG1heCA+PSBmcm9tKSBtYXggPSBmcm9tIC0gMTtcblxuICAgICAgICAgICAgZm9yIChpID0gMTsgaSA8PSBtYXg7IGkrKykge1xuICAgICAgICAgICAgICBodG1sLnB1c2gocGFnZUl0ZW0oaSkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZnJvbSAtIDEgPT09IG1heCArIDEpIHtcbiAgICAgICAgICAgICAgaSA9IGZyb20gLSAxO1xuICAgICAgICAgICAgICBodG1sLnB1c2gocGFnZUl0ZW0oaSkpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChmcm9tIC0gMSA+IG1heCkge1xuICAgICAgICAgICAgICBpZiAoZnJvbSAtIG9wdHMucGFnaW5hdGlvblBhZ2VzQnlTaWRlICogMiA+IG9wdHMucGFnaW5hdGlvblBhZ2VzQnlTaWRlICYmIG9wdHMucGFnaW5hdGlvblVzZUludGVybWVkaWF0ZSkge1xuICAgICAgICAgICAgICAgIGkgPSBNYXRoLnJvdW5kKChmcm9tIC0gbWlkZGxlU2l6ZSkgLyAyICsgbWlkZGxlU2l6ZSk7XG4gICAgICAgICAgICAgICAgaHRtbC5wdXNoKHBhZ2VJdGVtKGksICcgcGFnZS1pbnRlcm1lZGlhdGUnKSk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaHRtbC5wdXNoKFV0aWxzLnNwcmludGYodGhpcy5jb25zdGFudHMuaHRtbC5wYWdpbmF0aW9uSXRlbSwgJyBwYWdlLWZpcnN0LXNlcGFyYXRvciBkaXNhYmxlZCcsICcnLCAnLi4uJykpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZm9yIChpID0gZnJvbTsgaSA8PSB0bzsgaSsrKSB7XG4gICAgICAgICAgICBodG1sLnB1c2gocGFnZUl0ZW0oaSkpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0aGlzLnRvdGFsUGFnZXMgPiB0bykge1xuICAgICAgICAgICAgdmFyIG1pbiA9IHRoaXMudG90YWxQYWdlcyAtIChvcHRzLnBhZ2luYXRpb25QYWdlc0J5U2lkZSAtIDEpO1xuICAgICAgICAgICAgaWYgKHRvID49IG1pbikgbWluID0gdG8gKyAxO1xuXG4gICAgICAgICAgICBpZiAodG8gKyAxID09PSBtaW4gLSAxKSB7XG4gICAgICAgICAgICAgIGkgPSB0byArIDE7XG4gICAgICAgICAgICAgIGh0bWwucHVzaChwYWdlSXRlbShpKSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1pbiA+IHRvICsgMSkge1xuICAgICAgICAgICAgICBpZiAodGhpcy50b3RhbFBhZ2VzIC0gdG8gPiBvcHRzLnBhZ2luYXRpb25QYWdlc0J5U2lkZSAqIDIgJiYgb3B0cy5wYWdpbmF0aW9uVXNlSW50ZXJtZWRpYXRlKSB7XG4gICAgICAgICAgICAgICAgaSA9IE1hdGgucm91bmQoKHRoaXMudG90YWxQYWdlcyAtIG1pZGRsZVNpemUgLSB0bykgLyAyICsgdG8pO1xuICAgICAgICAgICAgICAgIGh0bWwucHVzaChwYWdlSXRlbShpLCAnIHBhZ2UtaW50ZXJtZWRpYXRlJykpO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGh0bWwucHVzaChVdGlscy5zcHJpbnRmKHRoaXMuY29uc3RhbnRzLmh0bWwucGFnaW5hdGlvbkl0ZW0sICcgcGFnZS1sYXN0LXNlcGFyYXRvciBkaXNhYmxlZCcsICcnLCAnLi4uJykpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAoaSA9IG1pbjsgaSA8PSB0aGlzLnRvdGFsUGFnZXM7IGkrKykge1xuICAgICAgICAgICAgICBodG1sLnB1c2gocGFnZUl0ZW0oaSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGh0bWwucHVzaChVdGlscy5zcHJpbnRmKHRoaXMuY29uc3RhbnRzLmh0bWwucGFnaW5hdGlvbkl0ZW0sICcgcGFnZS1uZXh0Jywgb3B0cy5mb3JtYXRTUlBhZ2luYXRpb25OZXh0VGV4dCgpLCBvcHRzLnBhZ2luYXRpb25OZXh0VGV4dCkpO1xuICAgICAgICAgIGh0bWwucHVzaCh0aGlzLmNvbnN0YW50cy5odG1sLnBhZ2luYXRpb25bMV0sICc8L2Rpdj4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuJHBhZ2luYXRpb24uaHRtbChodG1sLmpvaW4oJycpKTtcbiAgICAgICAgdmFyIGRyb3B1cENsYXNzID0gWydib3R0b20nLCAnYm90aCddLmluY2x1ZGVzKG9wdHMucGFnaW5hdGlvblZBbGlnbikgPyBcIiBcIi5jb25jYXQodGhpcy5jb25zdGFudHMuY2xhc3Nlcy5kcm9wdXApIDogJyc7XG4gICAgICAgIHRoaXMuJHBhZ2luYXRpb24ubGFzdCgpLmZpbmQoJy5wYWdlLWxpc3QgPiBkaXYnKS5hZGRDbGFzcyhkcm9wdXBDbGFzcyk7XG5cbiAgICAgICAgaWYgKCFvcHRzLm9ubHlJbmZvUGFnaW5hdGlvbikge1xuICAgICAgICAgICRwYWdlTGlzdCA9IHRoaXMuJHBhZ2luYXRpb24uZmluZCgnLnBhZ2UtbGlzdCBhJyk7XG4gICAgICAgICAgJHByZSA9IHRoaXMuJHBhZ2luYXRpb24uZmluZCgnLnBhZ2UtcHJlJyk7XG4gICAgICAgICAgJG5leHQgPSB0aGlzLiRwYWdpbmF0aW9uLmZpbmQoJy5wYWdlLW5leHQnKTtcbiAgICAgICAgICAkbnVtYmVyID0gdGhpcy4kcGFnaW5hdGlvbi5maW5kKCcucGFnZS1pdGVtJykubm90KCcucGFnZS1uZXh0LCAucGFnZS1wcmUsIC5wYWdlLWxhc3Qtc2VwYXJhdG9yLCAucGFnZS1maXJzdC1zZXBhcmF0b3InKTtcblxuICAgICAgICAgIGlmICh0aGlzLnRvdGFsUGFnZXMgPD0gMSkge1xuICAgICAgICAgICAgdGhpcy4kcGFnaW5hdGlvbi5maW5kKCdkaXYucGFnaW5hdGlvbicpLmhpZGUoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAob3B0cy5zbWFydERpc3BsYXkpIHtcbiAgICAgICAgICAgIGlmIChwYWdlTGlzdC5sZW5ndGggPCAyIHx8IG9wdHMudG90YWxSb3dzIDw9IHBhZ2VMaXN0WzBdKSB7XG4gICAgICAgICAgICAgIHRoaXMuJHBhZ2luYXRpb24uZmluZCgnc3Bhbi5wYWdlLWxpc3QnKS5oaWRlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSAvLyB3aGVuIGRhdGEgaXMgZW1wdHksIGhpZGUgdGhlIHBhZ2luYXRpb25cblxuXG4gICAgICAgICAgdGhpcy4kcGFnaW5hdGlvblt0aGlzLmdldERhdGEoKS5sZW5ndGggPyAnc2hvdycgOiAnaGlkZSddKCk7XG5cbiAgICAgICAgICBpZiAoIW9wdHMucGFnaW5hdGlvbkxvb3ApIHtcbiAgICAgICAgICAgIGlmIChvcHRzLnBhZ2VOdW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgJHByZS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG9wdHMucGFnZU51bWJlciA9PT0gdGhpcy50b3RhbFBhZ2VzKSB7XG4gICAgICAgICAgICAgICRuZXh0LmFkZENsYXNzKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChhbGxTZWxlY3RlZCkge1xuICAgICAgICAgICAgb3B0cy5wYWdlU2l6ZSA9IG9wdHMuZm9ybWF0QWxsUm93cygpO1xuICAgICAgICAgIH0gLy8gcmVtb3ZlZCB0aGUgZXZlbnRzIGZvciBsYXN0IGFuZCBmaXJzdCwgb25QYWdlTnVtYmVyIGV4ZWN1dGVkcyB0aGUgc2FtZSBsb2dpY1xuXG5cbiAgICAgICAgICAkcGFnZUxpc3Qub2ZmKCdjbGljaycpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICByZXR1cm4gX3RoaXM2Lm9uUGFnZUxpc3RDaGFuZ2UoZSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgJHByZS5vZmYoJ2NsaWNrJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIHJldHVybiBfdGhpczYub25QYWdlUHJlKGUpO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgICRuZXh0Lm9mZignY2xpY2snKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIF90aGlzNi5vblBhZ2VOZXh0KGUpO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgICRudW1iZXIub2ZmKCdjbGljaycpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICByZXR1cm4gX3RoaXM2Lm9uUGFnZU51bWJlcihlKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJ1cGRhdGVQYWdpbmF0aW9uXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdXBkYXRlUGFnaW5hdGlvbihldmVudCkge1xuICAgICAgICAvLyBGaXggIzE3MTogSUUgZGlzYWJsZWQgYnV0dG9uIGNhbiBiZSBjbGlja2VkIGJ1Zy5cbiAgICAgICAgaWYgKGV2ZW50ICYmICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShldmVudC5jdXJyZW50VGFyZ2V0KS5oYXNDbGFzcygnZGlzYWJsZWQnKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5vcHRpb25zLm1haW50YWluTWV0YURhdGEpIHtcbiAgICAgICAgICB0aGlzLnJlc2V0Um93cygpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5pbml0UGFnaW5hdGlvbigpO1xuICAgICAgICB0aGlzLnRyaWdnZXIoJ3BhZ2UtY2hhbmdlJywgdGhpcy5vcHRpb25zLnBhZ2VOdW1iZXIsIHRoaXMub3B0aW9ucy5wYWdlU2l6ZSk7XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5zaWRlUGFnaW5hdGlvbiA9PT0gJ3NlcnZlcicpIHtcbiAgICAgICAgICB0aGlzLmluaXRTZXJ2ZXIoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmluaXRCb2R5KCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwib25QYWdlTGlzdENoYW5nZVwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIG9uUGFnZUxpc3RDaGFuZ2UoZXZlbnQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdmFyICR0aGlzID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKGV2ZW50LmN1cnJlbnRUYXJnZXQpO1xuICAgICAgICAkdGhpcy5wYXJlbnQoKS5hZGRDbGFzcyh0aGlzLmNvbnN0YW50cy5jbGFzc2VzLmRyb3Bkb3duQWN0aXZlKS5zaWJsaW5ncygpLnJlbW92ZUNsYXNzKHRoaXMuY29uc3RhbnRzLmNsYXNzZXMuZHJvcGRvd25BY3RpdmUpO1xuICAgICAgICB0aGlzLm9wdGlvbnMucGFnZVNpemUgPSAkdGhpcy50ZXh0KCkudG9VcHBlckNhc2UoKSA9PT0gdGhpcy5vcHRpb25zLmZvcm1hdEFsbFJvd3MoKS50b1VwcGVyQ2FzZSgpID8gdGhpcy5vcHRpb25zLmZvcm1hdEFsbFJvd3MoKSA6ICskdGhpcy50ZXh0KCk7XG4gICAgICAgIHRoaXMuJHRvb2xiYXIuZmluZCgnLnBhZ2Utc2l6ZScpLnRleHQodGhpcy5vcHRpb25zLnBhZ2VTaXplKTtcbiAgICAgICAgdGhpcy51cGRhdGVQYWdpbmF0aW9uKGV2ZW50KTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJvblBhZ2VQcmVcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBvblBhZ2VQcmUoZXZlbnQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnBhZ2VOdW1iZXIgLSAxID09PSAwKSB7XG4gICAgICAgICAgdGhpcy5vcHRpb25zLnBhZ2VOdW1iZXIgPSB0aGlzLm9wdGlvbnMudG90YWxQYWdlcztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMucGFnZU51bWJlci0tO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy51cGRhdGVQYWdpbmF0aW9uKGV2ZW50KTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJvblBhZ2VOZXh0XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gb25QYWdlTmV4dChldmVudCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMucGFnZU51bWJlciArIDEgPiB0aGlzLm9wdGlvbnMudG90YWxQYWdlcykge1xuICAgICAgICAgIHRoaXMub3B0aW9ucy5wYWdlTnVtYmVyID0gMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMucGFnZU51bWJlcisrO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy51cGRhdGVQYWdpbmF0aW9uKGV2ZW50KTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJvblBhZ2VOdW1iZXJcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBvblBhZ2VOdW1iZXIoZXZlbnQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnBhZ2VOdW1iZXIgPT09ICskX19kZWZhdWx0WydkZWZhdWx0J10oZXZlbnQuY3VycmVudFRhcmdldCkudGV4dCgpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5vcHRpb25zLnBhZ2VOdW1iZXIgPSArJF9fZGVmYXVsdFsnZGVmYXVsdCddKGV2ZW50LmN1cnJlbnRUYXJnZXQpLnRleHQoKTtcbiAgICAgICAgdGhpcy51cGRhdGVQYWdpbmF0aW9uKGV2ZW50KTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfSAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW51c2VkLXZhcnNcblxuICAgIH0sIHtcbiAgICAgIGtleTogXCJpbml0Um93XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaW5pdFJvdyhpdGVtLCBpLCBkYXRhLCB0ckZyYWdtZW50cykge1xuICAgICAgICB2YXIgX3RoaXM3ID0gdGhpcztcblxuICAgICAgICB2YXIgaHRtbCA9IFtdO1xuICAgICAgICB2YXIgc3R5bGUgPSB7fTtcbiAgICAgICAgdmFyIGNzc2VzID0gW107XG4gICAgICAgIHZhciBkYXRhXyA9ICcnO1xuICAgICAgICB2YXIgYXR0cmlidXRlcyA9IHt9O1xuICAgICAgICB2YXIgaHRtbEF0dHJpYnV0ZXMgPSBbXTtcblxuICAgICAgICBpZiAoVXRpbHMuZmluZEluZGV4KHRoaXMuaGlkZGVuUm93cywgaXRlbSkgPiAtMSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHN0eWxlID0gVXRpbHMuY2FsY3VsYXRlT2JqZWN0VmFsdWUodGhpcy5vcHRpb25zLCB0aGlzLm9wdGlvbnMucm93U3R5bGUsIFtpdGVtLCBpXSwgc3R5bGUpO1xuXG4gICAgICAgIGlmIChzdHlsZSAmJiBzdHlsZS5jc3MpIHtcbiAgICAgICAgICBmb3IgKHZhciBfaTcgPSAwLCBfT2JqZWN0JGVudHJpZXM2ID0gT2JqZWN0LmVudHJpZXMoc3R5bGUuY3NzKTsgX2k3IDwgX09iamVjdCRlbnRyaWVzNi5sZW5ndGg7IF9pNysrKSB7XG4gICAgICAgICAgICB2YXIgX09iamVjdCRlbnRyaWVzNiRfaSA9IF9zbGljZWRUb0FycmF5KF9PYmplY3QkZW50cmllczZbX2k3XSwgMiksXG4gICAgICAgICAgICAgICAga2V5ID0gX09iamVjdCRlbnRyaWVzNiRfaVswXSxcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IF9PYmplY3QkZW50cmllczYkX2lbMV07XG5cbiAgICAgICAgICAgIGNzc2VzLnB1c2goXCJcIi5jb25jYXQoa2V5LCBcIjogXCIpLmNvbmNhdCh2YWx1ZSkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGF0dHJpYnV0ZXMgPSBVdGlscy5jYWxjdWxhdGVPYmplY3RWYWx1ZSh0aGlzLm9wdGlvbnMsIHRoaXMub3B0aW9ucy5yb3dBdHRyaWJ1dGVzLCBbaXRlbSwgaV0sIGF0dHJpYnV0ZXMpO1xuXG4gICAgICAgIGlmIChhdHRyaWJ1dGVzKSB7XG4gICAgICAgICAgZm9yICh2YXIgX2k4ID0gMCwgX09iamVjdCRlbnRyaWVzNyA9IE9iamVjdC5lbnRyaWVzKGF0dHJpYnV0ZXMpOyBfaTggPCBfT2JqZWN0JGVudHJpZXM3Lmxlbmd0aDsgX2k4KyspIHtcbiAgICAgICAgICAgIHZhciBfT2JqZWN0JGVudHJpZXM3JF9pID0gX3NsaWNlZFRvQXJyYXkoX09iamVjdCRlbnRyaWVzN1tfaThdLCAyKSxcbiAgICAgICAgICAgICAgICBfa2V5MiA9IF9PYmplY3QkZW50cmllczckX2lbMF0sXG4gICAgICAgICAgICAgICAgX3ZhbHVlID0gX09iamVjdCRlbnRyaWVzNyRfaVsxXTtcblxuICAgICAgICAgICAgaHRtbEF0dHJpYnV0ZXMucHVzaChcIlwiLmNvbmNhdChfa2V5MiwgXCI9XFxcIlwiKS5jb25jYXQoVXRpbHMuZXNjYXBlSFRNTChfdmFsdWUpLCBcIlxcXCJcIikpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpdGVtLl9kYXRhICYmICFVdGlscy5pc0VtcHR5T2JqZWN0KGl0ZW0uX2RhdGEpKSB7XG4gICAgICAgICAgZm9yICh2YXIgX2k5ID0gMCwgX09iamVjdCRlbnRyaWVzOCA9IE9iamVjdC5lbnRyaWVzKGl0ZW0uX2RhdGEpOyBfaTkgPCBfT2JqZWN0JGVudHJpZXM4Lmxlbmd0aDsgX2k5KyspIHtcbiAgICAgICAgICAgIHZhciBfT2JqZWN0JGVudHJpZXM4JF9pID0gX3NsaWNlZFRvQXJyYXkoX09iamVjdCRlbnRyaWVzOFtfaTldLCAyKSxcbiAgICAgICAgICAgICAgICBrID0gX09iamVjdCRlbnRyaWVzOCRfaVswXSxcbiAgICAgICAgICAgICAgICB2ID0gX09iamVjdCRlbnRyaWVzOCRfaVsxXTtcblxuICAgICAgICAgICAgLy8gaWdub3JlIGRhdGEtaW5kZXhcbiAgICAgICAgICAgIGlmIChrID09PSAnaW5kZXgnKSB7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZGF0YV8gKz0gXCIgZGF0YS1cIi5jb25jYXQoaywgXCI9J1wiKS5jb25jYXQoX3R5cGVvZih2KSA9PT0gJ29iamVjdCcgPyBKU09OLnN0cmluZ2lmeSh2KSA6IHYsIFwiJ1wiKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBodG1sLnB1c2goJzx0cicsIFV0aWxzLnNwcmludGYoJyAlcycsIGh0bWxBdHRyaWJ1dGVzLmxlbmd0aCA/IGh0bWxBdHRyaWJ1dGVzLmpvaW4oJyAnKSA6IHVuZGVmaW5lZCksIFV0aWxzLnNwcmludGYoJyBpZD1cIiVzXCInLCBBcnJheS5pc0FycmF5KGl0ZW0pID8gdW5kZWZpbmVkIDogaXRlbS5faWQpLCBVdGlscy5zcHJpbnRmKCcgY2xhc3M9XCIlc1wiJywgc3R5bGUuY2xhc3NlcyB8fCAoQXJyYXkuaXNBcnJheShpdGVtKSA/IHVuZGVmaW5lZCA6IGl0ZW0uX2NsYXNzKSksIFV0aWxzLnNwcmludGYoJyBzdHlsZT1cIiVzXCInLCBBcnJheS5pc0FycmF5KGl0ZW0pID8gdW5kZWZpbmVkIDogaXRlbS5fc3R5bGUpLCBcIiBkYXRhLWluZGV4PVxcXCJcIi5jb25jYXQoaSwgXCJcXFwiXCIpLCBVdGlscy5zcHJpbnRmKCcgZGF0YS11bmlxdWVpZD1cIiVzXCInLCBVdGlscy5nZXRJdGVtRmllbGQoaXRlbSwgdGhpcy5vcHRpb25zLnVuaXF1ZUlkLCBmYWxzZSkpLCBVdGlscy5zcHJpbnRmKCcgZGF0YS1oYXMtZGV0YWlsLXZpZXc9XCIlc1wiJywgdGhpcy5vcHRpb25zLmRldGFpbFZpZXcgJiYgVXRpbHMuY2FsY3VsYXRlT2JqZWN0VmFsdWUobnVsbCwgdGhpcy5vcHRpb25zLmRldGFpbEZpbHRlciwgW2ksIGl0ZW1dKSA/ICd0cnVlJyA6IHVuZGVmaW5lZCksIFV0aWxzLnNwcmludGYoJyVzJywgZGF0YV8pLCAnPicpO1xuXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuY2FyZFZpZXcpIHtcbiAgICAgICAgICBodG1sLnB1c2goXCI8dGQgY29sc3Bhbj1cXFwiXCIuY29uY2F0KHRoaXMuaGVhZGVyLmZpZWxkcy5sZW5ndGgsIFwiXFxcIj48ZGl2IGNsYXNzPVxcXCJjYXJkLXZpZXdzXFxcIj5cIikpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGRldGFpbFZpZXdUZW1wbGF0ZSA9ICcnO1xuXG4gICAgICAgIGlmIChVdGlscy5oYXNEZXRhaWxWaWV3SWNvbih0aGlzLm9wdGlvbnMpKSB7XG4gICAgICAgICAgZGV0YWlsVmlld1RlbXBsYXRlID0gJzx0ZD4nO1xuXG4gICAgICAgICAgaWYgKFV0aWxzLmNhbGN1bGF0ZU9iamVjdFZhbHVlKG51bGwsIHRoaXMub3B0aW9ucy5kZXRhaWxGaWx0ZXIsIFtpLCBpdGVtXSkpIHtcbiAgICAgICAgICAgIGRldGFpbFZpZXdUZW1wbGF0ZSArPSBcIlxcbiAgICAgICAgICA8YSBjbGFzcz1cXFwiZGV0YWlsLWljb25cXFwiIGhyZWY9XFxcIiNcXFwiPlxcbiAgICAgICAgICBcIi5jb25jYXQoVXRpbHMuc3ByaW50Zih0aGlzLmNvbnN0YW50cy5odG1sLmljb24sIHRoaXMub3B0aW9ucy5pY29uc1ByZWZpeCwgdGhpcy5vcHRpb25zLmljb25zLmRldGFpbE9wZW4pLCBcIlxcbiAgICAgICAgICA8L2E+XFxuICAgICAgICBcIik7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZGV0YWlsVmlld1RlbXBsYXRlICs9ICc8L3RkPic7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZGV0YWlsVmlld1RlbXBsYXRlICYmIHRoaXMub3B0aW9ucy5kZXRhaWxWaWV3QWxpZ24gIT09ICdyaWdodCcpIHtcbiAgICAgICAgICBodG1sLnB1c2goZGV0YWlsVmlld1RlbXBsYXRlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaGVhZGVyLmZpZWxkcy5mb3JFYWNoKGZ1bmN0aW9uIChmaWVsZCwgaikge1xuICAgICAgICAgIHZhciB0ZXh0ID0gJyc7XG4gICAgICAgICAgdmFyIHZhbHVlXyA9IFV0aWxzLmdldEl0ZW1GaWVsZChpdGVtLCBmaWVsZCwgX3RoaXM3Lm9wdGlvbnMuZXNjYXBlKTtcbiAgICAgICAgICB2YXIgdmFsdWUgPSAnJztcbiAgICAgICAgICB2YXIgdHlwZSA9ICcnO1xuICAgICAgICAgIHZhciBjZWxsU3R5bGUgPSB7fTtcbiAgICAgICAgICB2YXIgaWRfID0gJyc7XG4gICAgICAgICAgdmFyIGNsYXNzXyA9IF90aGlzNy5oZWFkZXIuY2xhc3Nlc1tqXTtcbiAgICAgICAgICB2YXIgc3R5bGVfID0gJyc7XG4gICAgICAgICAgdmFyIHN0eWxlVG9BZGRfID0gJyc7XG4gICAgICAgICAgdmFyIGRhdGFfID0gJyc7XG4gICAgICAgICAgdmFyIHJvd3NwYW5fID0gJyc7XG4gICAgICAgICAgdmFyIGNvbHNwYW5fID0gJyc7XG4gICAgICAgICAgdmFyIHRpdGxlXyA9ICcnO1xuICAgICAgICAgIHZhciBjb2x1bW4gPSBfdGhpczcuY29sdW1uc1tqXTtcblxuICAgICAgICAgIGlmICgoX3RoaXM3LmZyb21IdG1sIHx8IF90aGlzNy5hdXRvTWVyZ2VDZWxscykgJiYgdHlwZW9mIHZhbHVlXyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIGlmICghY29sdW1uLmNoZWNrYm94ICYmICFjb2x1bW4ucmFkaW8pIHtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghY29sdW1uLnZpc2libGUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoX3RoaXM3Lm9wdGlvbnMuY2FyZFZpZXcgJiYgIWNvbHVtbi5jYXJkVmlzaWJsZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChjb2x1bW4uZXNjYXBlKSB7XG4gICAgICAgICAgICB2YWx1ZV8gPSBVdGlscy5lc2NhcGVIVE1MKHZhbHVlXyk7XG4gICAgICAgICAgfSAvLyBTdHlsZSBjb25jYXRcblxuXG4gICAgICAgICAgaWYgKGNzc2VzLmNvbmNhdChbX3RoaXM3LmhlYWRlci5zdHlsZXNbal1dKS5sZW5ndGgpIHtcbiAgICAgICAgICAgIHN0eWxlVG9BZGRfICs9IFwiXCIuY29uY2F0KGNzc2VzLmNvbmNhdChbX3RoaXM3LmhlYWRlci5zdHlsZXNbal1dKS5qb2luKCc7ICcpKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoaXRlbVtcIl9cIi5jb25jYXQoZmllbGQsIFwiX3N0eWxlXCIpXSkge1xuICAgICAgICAgICAgc3R5bGVUb0FkZF8gKz0gXCJcIi5jb25jYXQoaXRlbVtcIl9cIi5jb25jYXQoZmllbGQsIFwiX3N0eWxlXCIpXSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHN0eWxlVG9BZGRfKSB7XG4gICAgICAgICAgICBzdHlsZV8gPSBcIiBzdHlsZT1cXFwiXCIuY29uY2F0KHN0eWxlVG9BZGRfLCBcIlxcXCJcIik7XG4gICAgICAgICAgfSAvLyBTdHlsZSBjb25jYXRcbiAgICAgICAgICAvLyBoYW5kbGUgaWQgYW5kIGNsYXNzIG9mIHRkXG5cblxuICAgICAgICAgIGlmIChpdGVtW1wiX1wiLmNvbmNhdChmaWVsZCwgXCJfaWRcIildKSB7XG4gICAgICAgICAgICBpZF8gPSBVdGlscy5zcHJpbnRmKCcgaWQ9XCIlc1wiJywgaXRlbVtcIl9cIi5jb25jYXQoZmllbGQsIFwiX2lkXCIpXSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGl0ZW1bXCJfXCIuY29uY2F0KGZpZWxkLCBcIl9jbGFzc1wiKV0pIHtcbiAgICAgICAgICAgIGNsYXNzXyA9IFV0aWxzLnNwcmludGYoJyBjbGFzcz1cIiVzXCInLCBpdGVtW1wiX1wiLmNvbmNhdChmaWVsZCwgXCJfY2xhc3NcIildKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoaXRlbVtcIl9cIi5jb25jYXQoZmllbGQsIFwiX3Jvd3NwYW5cIildKSB7XG4gICAgICAgICAgICByb3dzcGFuXyA9IFV0aWxzLnNwcmludGYoJyByb3dzcGFuPVwiJXNcIicsIGl0ZW1bXCJfXCIuY29uY2F0KGZpZWxkLCBcIl9yb3dzcGFuXCIpXSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGl0ZW1bXCJfXCIuY29uY2F0KGZpZWxkLCBcIl9jb2xzcGFuXCIpXSkge1xuICAgICAgICAgICAgY29sc3Bhbl8gPSBVdGlscy5zcHJpbnRmKCcgY29sc3Bhbj1cIiVzXCInLCBpdGVtW1wiX1wiLmNvbmNhdChmaWVsZCwgXCJfY29sc3BhblwiKV0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChpdGVtW1wiX1wiLmNvbmNhdChmaWVsZCwgXCJfdGl0bGVcIildKSB7XG4gICAgICAgICAgICB0aXRsZV8gPSBVdGlscy5zcHJpbnRmKCcgdGl0bGU9XCIlc1wiJywgaXRlbVtcIl9cIi5jb25jYXQoZmllbGQsIFwiX3RpdGxlXCIpXSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY2VsbFN0eWxlID0gVXRpbHMuY2FsY3VsYXRlT2JqZWN0VmFsdWUoX3RoaXM3LmhlYWRlciwgX3RoaXM3LmhlYWRlci5jZWxsU3R5bGVzW2pdLCBbdmFsdWVfLCBpdGVtLCBpLCBmaWVsZF0sIGNlbGxTdHlsZSk7XG5cbiAgICAgICAgICBpZiAoY2VsbFN0eWxlLmNsYXNzZXMpIHtcbiAgICAgICAgICAgIGNsYXNzXyA9IFwiIGNsYXNzPVxcXCJcIi5jb25jYXQoY2VsbFN0eWxlLmNsYXNzZXMsIFwiXFxcIlwiKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoY2VsbFN0eWxlLmNzcykge1xuICAgICAgICAgICAgdmFyIGNzc2VzXyA9IFtdO1xuXG4gICAgICAgICAgICBmb3IgKHZhciBfaTEwID0gMCwgX09iamVjdCRlbnRyaWVzOSA9IE9iamVjdC5lbnRyaWVzKGNlbGxTdHlsZS5jc3MpOyBfaTEwIDwgX09iamVjdCRlbnRyaWVzOS5sZW5ndGg7IF9pMTArKykge1xuICAgICAgICAgICAgICB2YXIgX09iamVjdCRlbnRyaWVzOSRfaSA9IF9zbGljZWRUb0FycmF5KF9PYmplY3QkZW50cmllczlbX2kxMF0sIDIpLFxuICAgICAgICAgICAgICAgICAgX2tleTMgPSBfT2JqZWN0JGVudHJpZXM5JF9pWzBdLFxuICAgICAgICAgICAgICAgICAgX3ZhbHVlMiA9IF9PYmplY3QkZW50cmllczkkX2lbMV07XG5cbiAgICAgICAgICAgICAgY3NzZXNfLnB1c2goXCJcIi5jb25jYXQoX2tleTMsIFwiOiBcIikuY29uY2F0KF92YWx1ZTIpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc3R5bGVfID0gXCIgc3R5bGU9XFxcIlwiLmNvbmNhdChjc3Nlc18uY29uY2F0KF90aGlzNy5oZWFkZXIuc3R5bGVzW2pdKS5qb2luKCc7ICcpLCBcIlxcXCJcIik7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFsdWUgPSBVdGlscy5jYWxjdWxhdGVPYmplY3RWYWx1ZShjb2x1bW4sIF90aGlzNy5oZWFkZXIuZm9ybWF0dGVyc1tqXSwgW3ZhbHVlXywgaXRlbSwgaSwgZmllbGRdLCB2YWx1ZV8pO1xuXG4gICAgICAgICAgaWYgKCEoY29sdW1uLmNoZWNrYm94IHx8IGNvbHVtbi5yYWRpbykpIHtcbiAgICAgICAgICAgIHZhbHVlID0gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJyB8fCB2YWx1ZSA9PT0gbnVsbCA/IF90aGlzNy5vcHRpb25zLnVuZGVmaW5lZFRleHQgOiB2YWx1ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoY29sdW1uLnNlYXJjaGFibGUgJiYgX3RoaXM3LnNlYXJjaFRleHQgJiYgX3RoaXM3Lm9wdGlvbnMuc2VhcmNoSGlnaGxpZ2h0KSB7XG4gICAgICAgICAgICB2YXIgZGVmVmFsdWUgPSAnJztcbiAgICAgICAgICAgIHZhciByZWdFeHAgPSBuZXcgUmVnRXhwKFwiKFwiLmNvbmNhdChfdGhpczcuc2VhcmNoVGV4dC5yZXBsYWNlKC9bLiorP14ke30oKXxbXFxdXFxcXF0vZywgJ1xcXFwkJicpLCBcIilcIiksICdnaW0nKTtcbiAgICAgICAgICAgIHZhciBtYXJrZXIgPSAnPG1hcms+JDE8L21hcms+JztcbiAgICAgICAgICAgIHZhciBpc0hUTUwgPSB2YWx1ZSAmJiAvPCg/PS4qPyAuKj9cXC8gPz58YnJ8aHJ8aW5wdXR8IS0tfHdicilbYS16XSsuKj8+fDwoW2Etel0rKS4qPzxcXC9cXDE+L2kudGVzdCh2YWx1ZSk7XG5cbiAgICAgICAgICAgIGlmIChpc0hUTUwpIHtcbiAgICAgICAgICAgICAgLy8gdmFsdWUgY2FuIGNvbnRhaW5zIGEgSFRNTCB0YWdzXG4gICAgICAgICAgICAgIHZhciB0ZXh0Q29udGVudCA9IG5ldyBET01QYXJzZXIoKS5wYXJzZUZyb21TdHJpbmcodmFsdWUudG9TdHJpbmcoKSwgJ3RleHQvaHRtbCcpLmRvY3VtZW50RWxlbWVudC50ZXh0Q29udGVudDtcbiAgICAgICAgICAgICAgdmFyIHRleHRSZXBsYWNlZCA9IHRleHRDb250ZW50LnJlcGxhY2UocmVnRXhwLCBtYXJrZXIpO1xuICAgICAgICAgICAgICBkZWZWYWx1ZSA9IHZhbHVlLnJlcGxhY2UobmV3IFJlZ0V4cChcIig+XFxcXHMqKShcIi5jb25jYXQodGV4dENvbnRlbnQsIFwiKShcXFxccyopXCIpLCAnZ20nKSwgXCIkMVwiLmNvbmNhdCh0ZXh0UmVwbGFjZWQsIFwiJDNcIikpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gYnV0IHVzdWFsbHkgbm90XG4gICAgICAgICAgICAgIGRlZlZhbHVlID0gdmFsdWUudG9TdHJpbmcoKS5yZXBsYWNlKHJlZ0V4cCwgbWFya2VyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFsdWUgPSBVdGlscy5jYWxjdWxhdGVPYmplY3RWYWx1ZShjb2x1bW4sIGNvbHVtbi5zZWFyY2hIaWdobGlnaHRGb3JtYXR0ZXIsIFt2YWx1ZSwgX3RoaXM3LnNlYXJjaFRleHRdLCBkZWZWYWx1ZSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGl0ZW1bXCJfXCIuY29uY2F0KGZpZWxkLCBcIl9kYXRhXCIpXSAmJiAhVXRpbHMuaXNFbXB0eU9iamVjdChpdGVtW1wiX1wiLmNvbmNhdChmaWVsZCwgXCJfZGF0YVwiKV0pKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBfaTExID0gMCwgX09iamVjdCRlbnRyaWVzMTAgPSBPYmplY3QuZW50cmllcyhpdGVtW1wiX1wiLmNvbmNhdChmaWVsZCwgXCJfZGF0YVwiKV0pOyBfaTExIDwgX09iamVjdCRlbnRyaWVzMTAubGVuZ3RoOyBfaTExKyspIHtcbiAgICAgICAgICAgICAgdmFyIF9PYmplY3QkZW50cmllczEwJF9pID0gX3NsaWNlZFRvQXJyYXkoX09iamVjdCRlbnRyaWVzMTBbX2kxMV0sIDIpLFxuICAgICAgICAgICAgICAgICAgX2sgPSBfT2JqZWN0JGVudHJpZXMxMCRfaVswXSxcbiAgICAgICAgICAgICAgICAgIF92ID0gX09iamVjdCRlbnRyaWVzMTAkX2lbMV07XG5cbiAgICAgICAgICAgICAgLy8gaWdub3JlIGRhdGEtaW5kZXhcbiAgICAgICAgICAgICAgaWYgKF9rID09PSAnaW5kZXgnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgZGF0YV8gKz0gXCIgZGF0YS1cIi5jb25jYXQoX2ssIFwiPVxcXCJcIikuY29uY2F0KF92LCBcIlxcXCJcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGNvbHVtbi5jaGVja2JveCB8fCBjb2x1bW4ucmFkaW8pIHtcbiAgICAgICAgICAgIHR5cGUgPSBjb2x1bW4uY2hlY2tib3ggPyAnY2hlY2tib3gnIDogdHlwZTtcbiAgICAgICAgICAgIHR5cGUgPSBjb2x1bW4ucmFkaW8gPyAncmFkaW8nIDogdHlwZTtcbiAgICAgICAgICAgIHZhciBjID0gY29sdW1uWydjbGFzcyddIHx8ICcnO1xuICAgICAgICAgICAgdmFyIGlzQ2hlY2tlZCA9IFV0aWxzLmlzT2JqZWN0KHZhbHVlKSAmJiB2YWx1ZS5oYXNPd25Qcm9wZXJ0eSgnY2hlY2tlZCcpID8gdmFsdWUuY2hlY2tlZCA6ICh2YWx1ZSA9PT0gdHJ1ZSB8fCB2YWx1ZV8pICYmIHZhbHVlICE9PSBmYWxzZTtcbiAgICAgICAgICAgIHZhciBpc0Rpc2FibGVkID0gIWNvbHVtbi5jaGVja2JveEVuYWJsZWQgfHwgdmFsdWUgJiYgdmFsdWUuZGlzYWJsZWQ7XG4gICAgICAgICAgICB0ZXh0ID0gW190aGlzNy5vcHRpb25zLmNhcmRWaWV3ID8gXCI8ZGl2IGNsYXNzPVxcXCJjYXJkLXZpZXcgXCIuY29uY2F0KGMsIFwiXFxcIj5cIikgOiBcIjx0ZCBjbGFzcz1cXFwiYnMtY2hlY2tib3ggXCIuY29uY2F0KGMsIFwiXFxcIlwiKS5jb25jYXQoY2xhc3NfKS5jb25jYXQoc3R5bGVfLCBcIj5cIiksIFwiPGxhYmVsPlxcbiAgICAgICAgICAgIDxpbnB1dFxcbiAgICAgICAgICAgIGRhdGEtaW5kZXg9XFxcIlwiLmNvbmNhdChpLCBcIlxcXCJcXG4gICAgICAgICAgICBuYW1lPVxcXCJcIikuY29uY2F0KF90aGlzNy5vcHRpb25zLnNlbGVjdEl0ZW1OYW1lLCBcIlxcXCJcXG4gICAgICAgICAgICB0eXBlPVxcXCJcIikuY29uY2F0KHR5cGUsIFwiXFxcIlxcbiAgICAgICAgICAgIFwiKS5jb25jYXQoVXRpbHMuc3ByaW50ZigndmFsdWU9XCIlc1wiJywgaXRlbVtfdGhpczcub3B0aW9ucy5pZEZpZWxkXSksIFwiXFxuICAgICAgICAgICAgXCIpLmNvbmNhdChVdGlscy5zcHJpbnRmKCdjaGVja2VkPVwiJXNcIicsIGlzQ2hlY2tlZCA/ICdjaGVja2VkJyA6IHVuZGVmaW5lZCksIFwiXFxuICAgICAgICAgICAgXCIpLmNvbmNhdChVdGlscy5zcHJpbnRmKCdkaXNhYmxlZD1cIiVzXCInLCBpc0Rpc2FibGVkID8gJ2Rpc2FibGVkJyA6IHVuZGVmaW5lZCksIFwiIC8+XFxuICAgICAgICAgICAgPHNwYW4+PC9zcGFuPlxcbiAgICAgICAgICAgIDwvbGFiZWw+XCIpLCBfdGhpczcuaGVhZGVyLmZvcm1hdHRlcnNbal0gJiYgdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyA/IHZhbHVlIDogJycsIF90aGlzNy5vcHRpb25zLmNhcmRWaWV3ID8gJzwvZGl2PicgOiAnPC90ZD4nXS5qb2luKCcnKTtcbiAgICAgICAgICAgIGl0ZW1bX3RoaXM3LmhlYWRlci5zdGF0ZUZpZWxkXSA9IHZhbHVlID09PSB0cnVlIHx8ICEhdmFsdWVfIHx8IHZhbHVlICYmIHZhbHVlLmNoZWNrZWQ7XG4gICAgICAgICAgfSBlbHNlIGlmIChfdGhpczcub3B0aW9ucy5jYXJkVmlldykge1xuICAgICAgICAgICAgdmFyIGNhcmRUaXRsZSA9IF90aGlzNy5vcHRpb25zLnNob3dIZWFkZXIgPyBcIjxzcGFuIGNsYXNzPVxcXCJjYXJkLXZpZXctdGl0bGUgXCIuY29uY2F0KGNlbGxTdHlsZS5jbGFzc2VzLCBcIlxcXCJcIikuY29uY2F0KHN0eWxlXywgXCI+XCIpLmNvbmNhdChVdGlscy5nZXRGaWVsZFRpdGxlKF90aGlzNy5jb2x1bW5zLCBmaWVsZCksIFwiPC9zcGFuPlwiKSA6ICcnO1xuICAgICAgICAgICAgdGV4dCA9IFwiPGRpdiBjbGFzcz1cXFwiY2FyZC12aWV3XFxcIj5cIi5jb25jYXQoY2FyZFRpdGxlLCBcIjxzcGFuIGNsYXNzPVxcXCJjYXJkLXZpZXctdmFsdWUgXCIpLmNvbmNhdChjZWxsU3R5bGUuY2xhc3NlcywgXCJcXFwiXCIpLmNvbmNhdChzdHlsZV8sIFwiPlwiKS5jb25jYXQodmFsdWUsIFwiPC9zcGFuPjwvZGl2PlwiKTtcblxuICAgICAgICAgICAgaWYgKF90aGlzNy5vcHRpb25zLnNtYXJ0RGlzcGxheSAmJiB2YWx1ZSA9PT0gJycpIHtcbiAgICAgICAgICAgICAgdGV4dCA9ICc8ZGl2IGNsYXNzPVwiY2FyZC12aWV3XCI+PC9kaXY+JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGV4dCA9IFwiPHRkXCIuY29uY2F0KGlkXykuY29uY2F0KGNsYXNzXykuY29uY2F0KHN0eWxlXykuY29uY2F0KGRhdGFfKS5jb25jYXQocm93c3Bhbl8pLmNvbmNhdChjb2xzcGFuXykuY29uY2F0KHRpdGxlXywgXCI+XCIpLmNvbmNhdCh2YWx1ZSwgXCI8L3RkPlwiKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBodG1sLnB1c2godGV4dCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChkZXRhaWxWaWV3VGVtcGxhdGUgJiYgdGhpcy5vcHRpb25zLmRldGFpbFZpZXdBbGlnbiA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICAgIGh0bWwucHVzaChkZXRhaWxWaWV3VGVtcGxhdGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5jYXJkVmlldykge1xuICAgICAgICAgIGh0bWwucHVzaCgnPC9kaXY+PC90ZD4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGh0bWwucHVzaCgnPC90cj4nKTtcbiAgICAgICAgcmV0dXJuIGh0bWwuam9pbignJyk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImluaXRCb2R5XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaW5pdEJvZHkoZml4ZWRTY3JvbGwpIHtcbiAgICAgICAgdmFyIF90aGlzOCA9IHRoaXM7XG5cbiAgICAgICAgdmFyIGRhdGEgPSB0aGlzLmdldERhdGEoKTtcbiAgICAgICAgdGhpcy50cmlnZ2VyKCdwcmUtYm9keScsIGRhdGEpO1xuICAgICAgICB0aGlzLiRib2R5ID0gdGhpcy4kZWwuZmluZCgnPnRib2R5Jyk7XG5cbiAgICAgICAgaWYgKCF0aGlzLiRib2R5Lmxlbmd0aCkge1xuICAgICAgICAgIHRoaXMuJGJvZHkgPSAkX19kZWZhdWx0WydkZWZhdWx0J10oJzx0Ym9keT48L3Rib2R5PicpLmFwcGVuZFRvKHRoaXMuJGVsKTtcbiAgICAgICAgfSAvLyBGaXggIzM4OSBCb290c3RyYXAtdGFibGUtZmxhdEpTT04gaXMgbm90IHdvcmtpbmdcblxuXG4gICAgICAgIGlmICghdGhpcy5vcHRpb25zLnBhZ2luYXRpb24gfHwgdGhpcy5vcHRpb25zLnNpZGVQYWdpbmF0aW9uID09PSAnc2VydmVyJykge1xuICAgICAgICAgIHRoaXMucGFnZUZyb20gPSAxO1xuICAgICAgICAgIHRoaXMucGFnZVRvID0gZGF0YS5sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcm93cyA9IFtdO1xuICAgICAgICB2YXIgdHJGcmFnbWVudHMgPSAkX19kZWZhdWx0WydkZWZhdWx0J10oZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpKTtcbiAgICAgICAgdmFyIGhhc1RyID0gZmFsc2U7XG4gICAgICAgIHRoaXMuYXV0b01lcmdlQ2VsbHMgPSBVdGlscy5jaGVja0F1dG9NZXJnZUNlbGxzKGRhdGEuc2xpY2UodGhpcy5wYWdlRnJvbSAtIDEsIHRoaXMucGFnZVRvKSk7XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IHRoaXMucGFnZUZyb20gLSAxOyBpIDwgdGhpcy5wYWdlVG87IGkrKykge1xuICAgICAgICAgIHZhciBpdGVtID0gZGF0YVtpXTtcbiAgICAgICAgICB2YXIgdHIgPSB0aGlzLmluaXRSb3coaXRlbSwgaSwgZGF0YSwgdHJGcmFnbWVudHMpO1xuICAgICAgICAgIGhhc1RyID0gaGFzVHIgfHwgISF0cjtcblxuICAgICAgICAgIGlmICh0ciAmJiB0eXBlb2YgdHIgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMub3B0aW9ucy52aXJ0dWFsU2Nyb2xsKSB7XG4gICAgICAgICAgICAgIHRyRnJhZ21lbnRzLmFwcGVuZCh0cik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByb3dzLnB1c2godHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSAvLyBzaG93IG5vIHJlY29yZHNcblxuXG4gICAgICAgIGlmICghaGFzVHIpIHtcbiAgICAgICAgICB0aGlzLiRib2R5Lmh0bWwoXCI8dHIgY2xhc3M9XFxcIm5vLXJlY29yZHMtZm91bmRcXFwiPlwiLmNvbmNhdChVdGlscy5zcHJpbnRmKCc8dGQgY29sc3Bhbj1cIiVzXCI+JXM8L3RkPicsIHRoaXMuZ2V0VmlzaWJsZUZpZWxkcygpLmxlbmd0aCArIFV0aWxzLmdldERldGFpbFZpZXdJbmRleE9mZnNldCh0aGlzLm9wdGlvbnMpLCB0aGlzLm9wdGlvbnMuZm9ybWF0Tm9NYXRjaGVzKCkpLCBcIjwvdHI+XCIpKTtcbiAgICAgICAgfSBlbHNlIGlmICghdGhpcy5vcHRpb25zLnZpcnR1YWxTY3JvbGwpIHtcbiAgICAgICAgICB0aGlzLiRib2R5Lmh0bWwodHJGcmFnbWVudHMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICh0aGlzLnZpcnR1YWxTY3JvbGwpIHtcbiAgICAgICAgICAgIHRoaXMudmlydHVhbFNjcm9sbC5kZXN0cm95KCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy52aXJ0dWFsU2Nyb2xsID0gbmV3IFZpcnR1YWxTY3JvbGwoe1xuICAgICAgICAgICAgcm93czogcm93cyxcbiAgICAgICAgICAgIGZpeGVkU2Nyb2xsOiBmaXhlZFNjcm9sbCxcbiAgICAgICAgICAgIHNjcm9sbEVsOiB0aGlzLiR0YWJsZUJvZHlbMF0sXG4gICAgICAgICAgICBjb250ZW50RWw6IHRoaXMuJGJvZHlbMF0sXG4gICAgICAgICAgICBpdGVtSGVpZ2h0OiB0aGlzLm9wdGlvbnMudmlydHVhbFNjcm9sbEl0ZW1IZWlnaHQsXG4gICAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24gY2FsbGJhY2soKSB7XG4gICAgICAgICAgICAgIF90aGlzOC5maXRIZWFkZXIoKTtcblxuICAgICAgICAgICAgICBfdGhpczguaW5pdEJvZHlFdmVudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFmaXhlZFNjcm9sbCkge1xuICAgICAgICAgIHRoaXMuc2Nyb2xsVG8oMCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmluaXRCb2R5RXZlbnQoKTtcbiAgICAgICAgdGhpcy51cGRhdGVTZWxlY3RlZCgpO1xuICAgICAgICB0aGlzLmluaXRGb290ZXIoKTtcbiAgICAgICAgdGhpcy5yZXNldFZpZXcoKTtcblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNpZGVQYWdpbmF0aW9uICE9PSAnc2VydmVyJykge1xuICAgICAgICAgIHRoaXMub3B0aW9ucy50b3RhbFJvd3MgPSBkYXRhLmxlbmd0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudHJpZ2dlcigncG9zdC1ib2R5JywgZGF0YSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImluaXRCb2R5RXZlbnRcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0Qm9keUV2ZW50KCkge1xuICAgICAgICB2YXIgX3RoaXM5ID0gdGhpcztcblxuICAgICAgICAvLyBjbGljayB0byBzZWxlY3QgYnkgY29sdW1uXG4gICAgICAgIHRoaXMuJGJvZHkuZmluZCgnPiB0cltkYXRhLWluZGV4XSA+IHRkJykub2ZmKCdjbGljayBkYmxjbGljaycpLm9uKCdjbGljayBkYmxjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgdmFyICR0ZCA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlLmN1cnJlbnRUYXJnZXQpO1xuICAgICAgICAgIHZhciAkdHIgPSAkdGQucGFyZW50KCk7XG4gICAgICAgICAgdmFyICRjYXJkVmlld0FyciA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlLnRhcmdldCkucGFyZW50cygnLmNhcmQtdmlld3MnKS5jaGlsZHJlbigpO1xuICAgICAgICAgIHZhciAkY2FyZFZpZXdUYXJnZXQgPSAkX19kZWZhdWx0WydkZWZhdWx0J10oZS50YXJnZXQpLnBhcmVudHMoJy5jYXJkLXZpZXcnKTtcbiAgICAgICAgICB2YXIgcm93SW5kZXggPSAkdHIuZGF0YSgnaW5kZXgnKTtcbiAgICAgICAgICB2YXIgaXRlbSA9IF90aGlzOS5kYXRhW3Jvd0luZGV4XTtcbiAgICAgICAgICB2YXIgaW5kZXggPSBfdGhpczkub3B0aW9ucy5jYXJkVmlldyA/ICRjYXJkVmlld0Fyci5pbmRleCgkY2FyZFZpZXdUYXJnZXQpIDogJHRkWzBdLmNlbGxJbmRleDtcblxuICAgICAgICAgIHZhciBmaWVsZHMgPSBfdGhpczkuZ2V0VmlzaWJsZUZpZWxkcygpO1xuXG4gICAgICAgICAgdmFyIGZpZWxkID0gZmllbGRzW2luZGV4IC0gVXRpbHMuZ2V0RGV0YWlsVmlld0luZGV4T2Zmc2V0KF90aGlzOS5vcHRpb25zKV07XG4gICAgICAgICAgdmFyIGNvbHVtbiA9IF90aGlzOS5jb2x1bW5zW190aGlzOS5maWVsZHNDb2x1bW5zSW5kZXhbZmllbGRdXTtcbiAgICAgICAgICB2YXIgdmFsdWUgPSBVdGlscy5nZXRJdGVtRmllbGQoaXRlbSwgZmllbGQsIF90aGlzOS5vcHRpb25zLmVzY2FwZSk7XG5cbiAgICAgICAgICBpZiAoJHRkLmZpbmQoJy5kZXRhaWwtaWNvbicpLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIF90aGlzOS50cmlnZ2VyKGUudHlwZSA9PT0gJ2NsaWNrJyA/ICdjbGljay1jZWxsJyA6ICdkYmwtY2xpY2stY2VsbCcsIGZpZWxkLCB2YWx1ZSwgaXRlbSwgJHRkKTtcblxuICAgICAgICAgIF90aGlzOS50cmlnZ2VyKGUudHlwZSA9PT0gJ2NsaWNrJyA/ICdjbGljay1yb3cnIDogJ2RibC1jbGljay1yb3cnLCBpdGVtLCAkdHIsIGZpZWxkKTsgLy8gaWYgY2xpY2sgdG8gc2VsZWN0IC0gdGhlbiB0cmlnZ2VyIHRoZSBjaGVja2JveC9yYWRpbyBjbGlja1xuXG5cbiAgICAgICAgICBpZiAoZS50eXBlID09PSAnY2xpY2snICYmIF90aGlzOS5vcHRpb25zLmNsaWNrVG9TZWxlY3QgJiYgY29sdW1uLmNsaWNrVG9TZWxlY3QgJiYgIVV0aWxzLmNhbGN1bGF0ZU9iamVjdFZhbHVlKF90aGlzOS5vcHRpb25zLCBfdGhpczkub3B0aW9ucy5pZ25vcmVDbGlja1RvU2VsZWN0T24sIFtlLnRhcmdldF0pKSB7XG4gICAgICAgICAgICB2YXIgJHNlbGVjdEl0ZW0gPSAkdHIuZmluZChVdGlscy5zcHJpbnRmKCdbbmFtZT1cIiVzXCJdJywgX3RoaXM5Lm9wdGlvbnMuc2VsZWN0SXRlbU5hbWUpKTtcblxuICAgICAgICAgICAgaWYgKCRzZWxlY3RJdGVtLmxlbmd0aCkge1xuICAgICAgICAgICAgICAkc2VsZWN0SXRlbVswXS5jbGljaygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChlLnR5cGUgPT09ICdjbGljaycgJiYgX3RoaXM5Lm9wdGlvbnMuZGV0YWlsVmlld0J5Q2xpY2spIHtcbiAgICAgICAgICAgIF90aGlzOS50b2dnbGVEZXRhaWxWaWV3KHJvd0luZGV4LCBfdGhpczkuaGVhZGVyLmRldGFpbEZvcm1hdHRlcnNbX3RoaXM5LmZpZWxkc0NvbHVtbnNJbmRleFtmaWVsZF1dKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pLm9mZignbW91c2Vkb3duJykub24oJ21vdXNlZG93bicsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2pxdWVyeS9qcXVlcnkvaXNzdWVzLzE3NDFcbiAgICAgICAgICBfdGhpczkubXVsdGlwbGVTZWxlY3RSb3dDdHJsS2V5ID0gZS5jdHJsS2V5IHx8IGUubWV0YUtleTtcbiAgICAgICAgICBfdGhpczkubXVsdGlwbGVTZWxlY3RSb3dTaGlmdEtleSA9IGUuc2hpZnRLZXk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLiRib2R5LmZpbmQoJz4gdHJbZGF0YS1pbmRleF0gPiB0ZCA+IC5kZXRhaWwtaWNvbicpLm9mZignY2xpY2snKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICAgIF90aGlzOS50b2dnbGVEZXRhaWxWaWV3KCRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlLmN1cnJlbnRUYXJnZXQpLnBhcmVudCgpLnBhcmVudCgpLmRhdGEoJ2luZGV4JykpO1xuXG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy4kc2VsZWN0SXRlbSA9IHRoaXMuJGJvZHkuZmluZChVdGlscy5zcHJpbnRmKCdbbmFtZT1cIiVzXCJdJywgdGhpcy5vcHRpb25zLnNlbGVjdEl0ZW1OYW1lKSk7XG4gICAgICAgIHRoaXMuJHNlbGVjdEl0ZW0ub2ZmKCdjbGljaycpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICB2YXIgJHRoaXMgPSAkX19kZWZhdWx0WydkZWZhdWx0J10oZS5jdXJyZW50VGFyZ2V0KTtcblxuICAgICAgICAgIF90aGlzOS5fdG9nZ2xlQ2hlY2soJHRoaXMucHJvcCgnY2hlY2tlZCcpLCAkdGhpcy5kYXRhKCdpbmRleCcpKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuaGVhZGVyLmV2ZW50cy5mb3JFYWNoKGZ1bmN0aW9uIChfZXZlbnRzLCBpKSB7XG4gICAgICAgICAgdmFyIGV2ZW50cyA9IF9ldmVudHM7XG5cbiAgICAgICAgICBpZiAoIWV2ZW50cykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH0gLy8gZml4IGJ1ZywgaWYgZXZlbnRzIGlzIGRlZmluZWQgd2l0aCBuYW1lc3BhY2VcblxuXG4gICAgICAgICAgaWYgKHR5cGVvZiBldmVudHMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBldmVudHMgPSBVdGlscy5jYWxjdWxhdGVPYmplY3RWYWx1ZShudWxsLCBldmVudHMpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciBmaWVsZCA9IF90aGlzOS5oZWFkZXIuZmllbGRzW2ldO1xuXG4gICAgICAgICAgdmFyIGZpZWxkSW5kZXggPSBfdGhpczkuZ2V0VmlzaWJsZUZpZWxkcygpLmluZGV4T2YoZmllbGQpO1xuXG4gICAgICAgICAgaWYgKGZpZWxkSW5kZXggPT09IC0xKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZmllbGRJbmRleCArPSBVdGlscy5nZXREZXRhaWxWaWV3SW5kZXhPZmZzZXQoX3RoaXM5Lm9wdGlvbnMpO1xuXG4gICAgICAgICAgdmFyIF9sb29wMiA9IGZ1bmN0aW9uIF9sb29wMihrZXkpIHtcbiAgICAgICAgICAgIGlmICghZXZlbnRzLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIFwiY29udGludWVcIjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGV2ZW50ID0gZXZlbnRzW2tleV07XG5cbiAgICAgICAgICAgIF90aGlzOS4kYm9keS5maW5kKCc+dHI6bm90KC5uby1yZWNvcmRzLWZvdW5kKScpLmVhY2goZnVuY3Rpb24gKGksIHRyKSB7XG4gICAgICAgICAgICAgIHZhciAkdHIgPSAkX19kZWZhdWx0WydkZWZhdWx0J10odHIpO1xuICAgICAgICAgICAgICB2YXIgJHRkID0gJHRyLmZpbmQoX3RoaXM5Lm9wdGlvbnMuY2FyZFZpZXcgPyAnLmNhcmQtdmlld3M+LmNhcmQtdmlldycgOiAnPnRkJykuZXEoZmllbGRJbmRleCk7XG4gICAgICAgICAgICAgIHZhciBpbmRleCA9IGtleS5pbmRleE9mKCcgJyk7XG4gICAgICAgICAgICAgIHZhciBuYW1lID0ga2V5LnN1YnN0cmluZygwLCBpbmRleCk7XG4gICAgICAgICAgICAgIHZhciBlbCA9IGtleS5zdWJzdHJpbmcoaW5kZXggKyAxKTtcbiAgICAgICAgICAgICAgJHRkLmZpbmQoZWwpLm9mZihuYW1lKS5vbihuYW1lLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIHZhciBpbmRleCA9ICR0ci5kYXRhKCdpbmRleCcpO1xuICAgICAgICAgICAgICAgIHZhciByb3cgPSBfdGhpczkuZGF0YVtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcm93W2ZpZWxkXTtcbiAgICAgICAgICAgICAgICBldmVudC5hcHBseShfdGhpczksIFtlLCB2YWx1ZSwgcm93LCBpbmRleF0pO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH07XG5cbiAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gZXZlbnRzKSB7XG4gICAgICAgICAgICB2YXIgX3JldDIgPSBfbG9vcDIoa2V5KTtcblxuICAgICAgICAgICAgaWYgKF9yZXQyID09PSBcImNvbnRpbnVlXCIpIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImluaXRTZXJ2ZXJcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0U2VydmVyKHNpbGVudCwgcXVlcnksIHVybCkge1xuICAgICAgICB2YXIgX3RoaXMxMCA9IHRoaXM7XG5cbiAgICAgICAgdmFyIGRhdGEgPSB7fTtcbiAgICAgICAgdmFyIGluZGV4ID0gdGhpcy5oZWFkZXIuZmllbGRzLmluZGV4T2YodGhpcy5vcHRpb25zLnNvcnROYW1lKTtcbiAgICAgICAgdmFyIHBhcmFtcyA9IHtcbiAgICAgICAgICBzZWFyY2hUZXh0OiB0aGlzLnNlYXJjaFRleHQsXG4gICAgICAgICAgc29ydE5hbWU6IHRoaXMub3B0aW9ucy5zb3J0TmFtZSxcbiAgICAgICAgICBzb3J0T3JkZXI6IHRoaXMub3B0aW9ucy5zb3J0T3JkZXJcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAodGhpcy5oZWFkZXIuc29ydE5hbWVzW2luZGV4XSkge1xuICAgICAgICAgIHBhcmFtcy5zb3J0TmFtZSA9IHRoaXMuaGVhZGVyLnNvcnROYW1lc1tpbmRleF07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnBhZ2luYXRpb24gJiYgdGhpcy5vcHRpb25zLnNpZGVQYWdpbmF0aW9uID09PSAnc2VydmVyJykge1xuICAgICAgICAgIHBhcmFtcy5wYWdlU2l6ZSA9IHRoaXMub3B0aW9ucy5wYWdlU2l6ZSA9PT0gdGhpcy5vcHRpb25zLmZvcm1hdEFsbFJvd3MoKSA/IHRoaXMub3B0aW9ucy50b3RhbFJvd3MgOiB0aGlzLm9wdGlvbnMucGFnZVNpemU7XG4gICAgICAgICAgcGFyYW1zLnBhZ2VOdW1iZXIgPSB0aGlzLm9wdGlvbnMucGFnZU51bWJlcjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghKHVybCB8fCB0aGlzLm9wdGlvbnMudXJsKSAmJiAhdGhpcy5vcHRpb25zLmFqYXgpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnF1ZXJ5UGFyYW1zVHlwZSA9PT0gJ2xpbWl0Jykge1xuICAgICAgICAgIHBhcmFtcyA9IHtcbiAgICAgICAgICAgIHNlYXJjaDogcGFyYW1zLnNlYXJjaFRleHQsXG4gICAgICAgICAgICBzb3J0OiBwYXJhbXMuc29ydE5hbWUsXG4gICAgICAgICAgICBvcmRlcjogcGFyYW1zLnNvcnRPcmRlclxuICAgICAgICAgIH07XG5cbiAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLnBhZ2luYXRpb24gJiYgdGhpcy5vcHRpb25zLnNpZGVQYWdpbmF0aW9uID09PSAnc2VydmVyJykge1xuICAgICAgICAgICAgcGFyYW1zLm9mZnNldCA9IHRoaXMub3B0aW9ucy5wYWdlU2l6ZSA9PT0gdGhpcy5vcHRpb25zLmZvcm1hdEFsbFJvd3MoKSA/IDAgOiB0aGlzLm9wdGlvbnMucGFnZVNpemUgKiAodGhpcy5vcHRpb25zLnBhZ2VOdW1iZXIgLSAxKTtcbiAgICAgICAgICAgIHBhcmFtcy5saW1pdCA9IHRoaXMub3B0aW9ucy5wYWdlU2l6ZSA9PT0gdGhpcy5vcHRpb25zLmZvcm1hdEFsbFJvd3MoKSA/IHRoaXMub3B0aW9ucy50b3RhbFJvd3MgOiB0aGlzLm9wdGlvbnMucGFnZVNpemU7XG5cbiAgICAgICAgICAgIGlmIChwYXJhbXMubGltaXQgPT09IDApIHtcbiAgICAgICAgICAgICAgZGVsZXRlIHBhcmFtcy5saW1pdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNlYXJjaCAmJiB0aGlzLm9wdGlvbnMuc2lkZVBhZ2luYXRpb24gPT09ICdzZXJ2ZXInICYmIHRoaXMuY29sdW1ucy5maWx0ZXIoZnVuY3Rpb24gKGNvbHVtbikge1xuICAgICAgICAgIHJldHVybiAhY29sdW1uLnNlYXJjaGFibGU7XG4gICAgICAgIH0pLmxlbmd0aCkge1xuICAgICAgICAgIHBhcmFtcy5zZWFyY2hhYmxlID0gW107XG5cbiAgICAgICAgICB2YXIgX2l0ZXJhdG9yMiA9IF9jcmVhdGVGb3JPZkl0ZXJhdG9ySGVscGVyKHRoaXMuY29sdW1ucyksXG4gICAgICAgICAgICAgIF9zdGVwMjtcblxuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBmb3IgKF9pdGVyYXRvcjIucygpOyAhKF9zdGVwMiA9IF9pdGVyYXRvcjIubigpKS5kb25lOykge1xuICAgICAgICAgICAgICB2YXIgY29sdW1uID0gX3N0ZXAyLnZhbHVlO1xuXG4gICAgICAgICAgICAgIGlmICghY29sdW1uLmNoZWNrYm94ICYmIGNvbHVtbi5zZWFyY2hhYmxlICYmICh0aGlzLm9wdGlvbnMudmlzaWJsZVNlYXJjaCAmJiBjb2x1bW4udmlzaWJsZSB8fCAhdGhpcy5vcHRpb25zLnZpc2libGVTZWFyY2gpKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zLnNlYXJjaGFibGUucHVzaChjb2x1bW4uZmllbGQpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBfaXRlcmF0b3IyLmUoZXJyKTtcbiAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgX2l0ZXJhdG9yMi5mKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFVdGlscy5pc0VtcHR5T2JqZWN0KHRoaXMuZmlsdGVyQ29sdW1uc1BhcnRpYWwpKSB7XG4gICAgICAgICAgcGFyYW1zLmZpbHRlciA9IEpTT04uc3RyaW5naWZ5KHRoaXMuZmlsdGVyQ29sdW1uc1BhcnRpYWwsIG51bGwpO1xuICAgICAgICB9XG5cbiAgICAgICAgJF9fZGVmYXVsdFsnZGVmYXVsdCddLmV4dGVuZChwYXJhbXMsIHF1ZXJ5IHx8IHt9KTtcbiAgICAgICAgZGF0YSA9IFV0aWxzLmNhbGN1bGF0ZU9iamVjdFZhbHVlKHRoaXMub3B0aW9ucywgdGhpcy5vcHRpb25zLnF1ZXJ5UGFyYW1zLCBbcGFyYW1zXSwgZGF0YSk7IC8vIGZhbHNlIHRvIHN0b3AgcmVxdWVzdFxuXG4gICAgICAgIGlmIChkYXRhID09PSBmYWxzZSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghc2lsZW50KSB7XG4gICAgICAgICAgdGhpcy5zaG93TG9hZGluZygpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHJlcXVlc3QgPSAkX19kZWZhdWx0WydkZWZhdWx0J10uZXh0ZW5kKHt9LCBVdGlscy5jYWxjdWxhdGVPYmplY3RWYWx1ZShudWxsLCB0aGlzLm9wdGlvbnMuYWpheE9wdGlvbnMpLCB7XG4gICAgICAgICAgdHlwZTogdGhpcy5vcHRpb25zLm1ldGhvZCxcbiAgICAgICAgICB1cmw6IHVybCB8fCB0aGlzLm9wdGlvbnMudXJsLFxuICAgICAgICAgIGRhdGE6IHRoaXMub3B0aW9ucy5jb250ZW50VHlwZSA9PT0gJ2FwcGxpY2F0aW9uL2pzb24nICYmIHRoaXMub3B0aW9ucy5tZXRob2QgPT09ICdwb3N0JyA/IEpTT04uc3RyaW5naWZ5KGRhdGEpIDogZGF0YSxcbiAgICAgICAgICBjYWNoZTogdGhpcy5vcHRpb25zLmNhY2hlLFxuICAgICAgICAgIGNvbnRlbnRUeXBlOiB0aGlzLm9wdGlvbnMuY29udGVudFR5cGUsXG4gICAgICAgICAgZGF0YVR5cGU6IHRoaXMub3B0aW9ucy5kYXRhVHlwZSxcbiAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbiBzdWNjZXNzKF9yZXMsIHRleHRTdGF0dXMsIGpxWEhSKSB7XG4gICAgICAgICAgICB2YXIgcmVzID0gVXRpbHMuY2FsY3VsYXRlT2JqZWN0VmFsdWUoX3RoaXMxMC5vcHRpb25zLCBfdGhpczEwLm9wdGlvbnMucmVzcG9uc2VIYW5kbGVyLCBbX3JlcywganFYSFJdLCBfcmVzKTtcblxuICAgICAgICAgICAgX3RoaXMxMC5sb2FkKHJlcyk7XG5cbiAgICAgICAgICAgIF90aGlzMTAudHJpZ2dlcignbG9hZC1zdWNjZXNzJywgcmVzLCBqcVhIUiAmJiBqcVhIUi5zdGF0dXMsIGpxWEhSKTtcblxuICAgICAgICAgICAgaWYgKCFzaWxlbnQpIHtcbiAgICAgICAgICAgICAgX3RoaXMxMC5oaWRlTG9hZGluZygpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoX3RoaXMxMC5vcHRpb25zLnNpZGVQYWdpbmF0aW9uID09PSAnc2VydmVyJyAmJiByZXNbX3RoaXMxMC5vcHRpb25zLnRvdGFsRmllbGRdID4gMCAmJiAhcmVzW190aGlzMTAub3B0aW9ucy5kYXRhRmllbGRdLmxlbmd0aCkge1xuICAgICAgICAgICAgICBfdGhpczEwLnVwZGF0ZVBhZ2luYXRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIGVycm9yOiBmdW5jdGlvbiBlcnJvcihqcVhIUikge1xuICAgICAgICAgICAgdmFyIGRhdGEgPSBbXTtcblxuICAgICAgICAgICAgaWYgKF90aGlzMTAub3B0aW9ucy5zaWRlUGFnaW5hdGlvbiA9PT0gJ3NlcnZlcicpIHtcbiAgICAgICAgICAgICAgZGF0YSA9IHt9O1xuICAgICAgICAgICAgICBkYXRhW190aGlzMTAub3B0aW9ucy50b3RhbEZpZWxkXSA9IDA7XG4gICAgICAgICAgICAgIGRhdGFbX3RoaXMxMC5vcHRpb25zLmRhdGFGaWVsZF0gPSBbXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgX3RoaXMxMC5sb2FkKGRhdGEpO1xuXG4gICAgICAgICAgICBfdGhpczEwLnRyaWdnZXIoJ2xvYWQtZXJyb3InLCBqcVhIUiAmJiBqcVhIUi5zdGF0dXMsIGpxWEhSKTtcblxuICAgICAgICAgICAgaWYgKCFzaWxlbnQpIF90aGlzMTAuJHRhYmxlTG9hZGluZy5oaWRlKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLmFqYXgpIHtcbiAgICAgICAgICBVdGlscy5jYWxjdWxhdGVPYmplY3RWYWx1ZSh0aGlzLCB0aGlzLm9wdGlvbnMuYWpheCwgW3JlcXVlc3RdLCBudWxsKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAodGhpcy5feGhyICYmIHRoaXMuX3hoci5yZWFkeVN0YXRlICE9PSA0KSB7XG4gICAgICAgICAgICB0aGlzLl94aHIuYWJvcnQoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aGlzLl94aHIgPSAkX19kZWZhdWx0WydkZWZhdWx0J10uYWpheChyZXF1ZXN0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJpbml0U2VhcmNoVGV4dFwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGluaXRTZWFyY2hUZXh0KCkge1xuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNlYXJjaCkge1xuICAgICAgICAgIHRoaXMuc2VhcmNoVGV4dCA9ICcnO1xuXG4gICAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5zZWFyY2hUZXh0ICE9PSAnJykge1xuICAgICAgICAgICAgdmFyICRzZWFyY2ggPSBVdGlscy5nZXRTZWFyY2hJbnB1dCh0aGlzKTtcbiAgICAgICAgICAgICRzZWFyY2gudmFsKHRoaXMub3B0aW9ucy5zZWFyY2hUZXh0KTtcbiAgICAgICAgICAgIHRoaXMub25TZWFyY2goe1xuICAgICAgICAgICAgICBjdXJyZW50VGFyZ2V0OiAkc2VhcmNoLFxuICAgICAgICAgICAgICBmaXJlZEJ5SW5pdFNlYXJjaFRleHQ6IHRydWVcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJnZXRDYXJldFwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGdldENhcmV0KCkge1xuICAgICAgICB2YXIgX3RoaXMxMSA9IHRoaXM7XG5cbiAgICAgICAgdGhpcy4kaGVhZGVyLmZpbmQoJ3RoJykuZWFjaChmdW5jdGlvbiAoaSwgdGgpIHtcbiAgICAgICAgICAkX19kZWZhdWx0WydkZWZhdWx0J10odGgpLmZpbmQoJy5zb3J0YWJsZScpLnJlbW92ZUNsYXNzKCdkZXNjIGFzYycpLmFkZENsYXNzKCRfX2RlZmF1bHRbJ2RlZmF1bHQnXSh0aCkuZGF0YSgnZmllbGQnKSA9PT0gX3RoaXMxMS5vcHRpb25zLnNvcnROYW1lID8gX3RoaXMxMS5vcHRpb25zLnNvcnRPcmRlciA6ICdib3RoJyk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJ1cGRhdGVTZWxlY3RlZFwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHVwZGF0ZVNlbGVjdGVkKCkge1xuICAgICAgICB2YXIgY2hlY2tBbGwgPSB0aGlzLiRzZWxlY3RJdGVtLmZpbHRlcignOmVuYWJsZWQnKS5sZW5ndGggJiYgdGhpcy4kc2VsZWN0SXRlbS5maWx0ZXIoJzplbmFibGVkJykubGVuZ3RoID09PSB0aGlzLiRzZWxlY3RJdGVtLmZpbHRlcignOmVuYWJsZWQnKS5maWx0ZXIoJzpjaGVja2VkJykubGVuZ3RoO1xuICAgICAgICB0aGlzLiRzZWxlY3RBbGwuYWRkKHRoaXMuJHNlbGVjdEFsbF8pLnByb3AoJ2NoZWNrZWQnLCBjaGVja0FsbCk7XG4gICAgICAgIHRoaXMuJHNlbGVjdEl0ZW0uZWFjaChmdW5jdGlvbiAoaSwgZWwpIHtcbiAgICAgICAgICAkX19kZWZhdWx0WydkZWZhdWx0J10oZWwpLmNsb3Nlc3QoJ3RyJylbJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKS5wcm9wKCdjaGVja2VkJykgPyAnYWRkQ2xhc3MnIDogJ3JlbW92ZUNsYXNzJ10oJ3NlbGVjdGVkJyk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJ1cGRhdGVSb3dzXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdXBkYXRlUm93cygpIHtcbiAgICAgICAgdmFyIF90aGlzMTIgPSB0aGlzO1xuXG4gICAgICAgIHRoaXMuJHNlbGVjdEl0ZW0uZWFjaChmdW5jdGlvbiAoaSwgZWwpIHtcbiAgICAgICAgICBfdGhpczEyLmRhdGFbJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKS5kYXRhKCdpbmRleCcpXVtfdGhpczEyLmhlYWRlci5zdGF0ZUZpZWxkXSA9ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlbCkucHJvcCgnY2hlY2tlZCcpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwicmVzZXRSb3dzXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gcmVzZXRSb3dzKCkge1xuICAgICAgICB2YXIgX2l0ZXJhdG9yMyA9IF9jcmVhdGVGb3JPZkl0ZXJhdG9ySGVscGVyKHRoaXMuZGF0YSksXG4gICAgICAgICAgICBfc3RlcDM7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBmb3IgKF9pdGVyYXRvcjMucygpOyAhKF9zdGVwMyA9IF9pdGVyYXRvcjMubigpKS5kb25lOykge1xuICAgICAgICAgICAgdmFyIHJvdyA9IF9zdGVwMy52YWx1ZTtcbiAgICAgICAgICAgIHRoaXMuJHNlbGVjdEFsbC5wcm9wKCdjaGVja2VkJywgZmFsc2UpO1xuICAgICAgICAgICAgdGhpcy4kc2VsZWN0SXRlbS5wcm9wKCdjaGVja2VkJywgZmFsc2UpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5oZWFkZXIuc3RhdGVGaWVsZCkge1xuICAgICAgICAgICAgICByb3dbdGhpcy5oZWFkZXIuc3RhdGVGaWVsZF0gPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIF9pdGVyYXRvcjMuZShlcnIpO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIF9pdGVyYXRvcjMuZigpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5pbml0SGlkZGVuUm93cygpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJ0cmlnZ2VyXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdHJpZ2dlcihfbmFtZSkge1xuICAgICAgICB2YXIgX3RoaXMkb3B0aW9ucywgX3RoaXMkb3B0aW9uczI7XG5cbiAgICAgICAgdmFyIG5hbWUgPSBcIlwiLmNvbmNhdChfbmFtZSwgXCIuYnMudGFibGVcIik7XG5cbiAgICAgICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiA+IDEgPyBfbGVuIC0gMSA6IDApLCBfa2V5NCA9IDE7IF9rZXk0IDwgX2xlbjsgX2tleTQrKykge1xuICAgICAgICAgIGFyZ3NbX2tleTQgLSAxXSA9IGFyZ3VtZW50c1tfa2V5NF07XG4gICAgICAgIH1cblxuICAgICAgICAoX3RoaXMkb3B0aW9ucyA9IHRoaXMub3B0aW9ucylbQm9vdHN0cmFwVGFibGUuRVZFTlRTW25hbWVdXS5hcHBseShfdGhpcyRvcHRpb25zLCBbXS5jb25jYXQoYXJncywgW3RoaXNdKSk7XG5cbiAgICAgICAgdGhpcy4kZWwudHJpZ2dlcigkX19kZWZhdWx0WydkZWZhdWx0J10uRXZlbnQobmFtZSwge1xuICAgICAgICAgIHNlbmRlcjogdGhpc1xuICAgICAgICB9KSwgYXJncyk7XG5cbiAgICAgICAgKF90aGlzJG9wdGlvbnMyID0gdGhpcy5vcHRpb25zKS5vbkFsbC5hcHBseShfdGhpcyRvcHRpb25zMiwgW25hbWVdLmNvbmNhdChbXS5jb25jYXQoYXJncywgW3RoaXNdKSkpO1xuXG4gICAgICAgIHRoaXMuJGVsLnRyaWdnZXIoJF9fZGVmYXVsdFsnZGVmYXVsdCddLkV2ZW50KCdhbGwuYnMudGFibGUnLCB7XG4gICAgICAgICAgc2VuZGVyOiB0aGlzXG4gICAgICAgIH0pLCBbbmFtZSwgYXJnc10pO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJyZXNldEhlYWRlclwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHJlc2V0SGVhZGVyKCkge1xuICAgICAgICB2YXIgX3RoaXMxMyA9IHRoaXM7XG5cbiAgICAgICAgLy8gZml4ICM2MTogdGhlIGhpZGRlbiB0YWJsZSByZXNldCBoZWFkZXIgYnVnLlxuICAgICAgICAvLyBmaXggYnVnOiBnZXQgJGVsLmNzcygnd2lkdGgnKSBlcnJvciBzb21ldGltZSAoaGVpZ2h0ID0gNTAwKVxuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy50aW1lb3V0SWRfKTtcbiAgICAgICAgdGhpcy50aW1lb3V0SWRfID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgcmV0dXJuIF90aGlzMTMuZml0SGVhZGVyKCk7XG4gICAgICAgIH0sIHRoaXMuJGVsLmlzKCc6aGlkZGVuJykgPyAxMDAgOiAwKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiZml0SGVhZGVyXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gZml0SGVhZGVyKCkge1xuICAgICAgICB2YXIgX3RoaXMxNCA9IHRoaXM7XG5cbiAgICAgICAgaWYgKHRoaXMuJGVsLmlzKCc6aGlkZGVuJykpIHtcbiAgICAgICAgICB0aGlzLnRpbWVvdXRJZF8gPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBfdGhpczE0LmZpdEhlYWRlcigpO1xuICAgICAgICAgIH0sIDEwMCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGZpeGVkQm9keSA9IHRoaXMuJHRhYmxlQm9keS5nZXQoMCk7XG4gICAgICAgIHZhciBzY3JvbGxXaWR0aCA9IGZpeGVkQm9keS5zY3JvbGxXaWR0aCA+IGZpeGVkQm9keS5jbGllbnRXaWR0aCAmJiBmaXhlZEJvZHkuc2Nyb2xsSGVpZ2h0ID4gZml4ZWRCb2R5LmNsaWVudEhlaWdodCArIHRoaXMuJGhlYWRlci5vdXRlckhlaWdodCgpID8gVXRpbHMuZ2V0U2Nyb2xsQmFyV2lkdGgoKSA6IDA7XG4gICAgICAgIHRoaXMuJGVsLmNzcygnbWFyZ2luLXRvcCcsIC10aGlzLiRoZWFkZXIub3V0ZXJIZWlnaHQoKSk7XG4gICAgICAgIHZhciBmb2N1c2VkID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKCc6Zm9jdXMnKTtcblxuICAgICAgICBpZiAoZm9jdXNlZC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgdmFyICR0aCA9IGZvY3VzZWQucGFyZW50cygndGgnKTtcblxuICAgICAgICAgIGlmICgkdGgubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdmFyIGRhdGFGaWVsZCA9ICR0aC5hdHRyKCdkYXRhLWZpZWxkJyk7XG5cbiAgICAgICAgICAgIGlmIChkYXRhRmllbGQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICB2YXIgJGhlYWRlclRoID0gdGhpcy4kaGVhZGVyLmZpbmQoXCJbZGF0YS1maWVsZD0nXCIuY29uY2F0KGRhdGFGaWVsZCwgXCInXVwiKSk7XG5cbiAgICAgICAgICAgICAgaWYgKCRoZWFkZXJUaC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgJGhlYWRlclRoLmZpbmQoJzppbnB1dCcpLmFkZENsYXNzKCdmb2N1cy10ZW1wJyk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLiRoZWFkZXJfID0gdGhpcy4kaGVhZGVyLmNsb25lKHRydWUsIHRydWUpO1xuICAgICAgICB0aGlzLiRzZWxlY3RBbGxfID0gdGhpcy4kaGVhZGVyXy5maW5kKCdbbmFtZT1cImJ0U2VsZWN0QWxsXCJdJyk7XG4gICAgICAgIHRoaXMuJHRhYmxlSGVhZGVyLmNzcygnbWFyZ2luLXJpZ2h0Jywgc2Nyb2xsV2lkdGgpLmZpbmQoJ3RhYmxlJykuY3NzKCd3aWR0aCcsIHRoaXMuJGVsLm91dGVyV2lkdGgoKSkuaHRtbCgnJykuYXR0cignY2xhc3MnLCB0aGlzLiRlbC5hdHRyKCdjbGFzcycpKS5hcHBlbmQodGhpcy4kaGVhZGVyXyk7XG4gICAgICAgIHRoaXMuJHRhYmxlTG9hZGluZy5jc3MoJ3dpZHRoJywgdGhpcy4kZWwub3V0ZXJXaWR0aCgpKTtcbiAgICAgICAgdmFyIGZvY3VzZWRUZW1wID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKCcuZm9jdXMtdGVtcDp2aXNpYmxlOmVxKDApJyk7XG5cbiAgICAgICAgaWYgKGZvY3VzZWRUZW1wLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBmb2N1c2VkVGVtcC5mb2N1cygpO1xuICAgICAgICAgIHRoaXMuJGhlYWRlci5maW5kKCcuZm9jdXMtdGVtcCcpLnJlbW92ZUNsYXNzKCdmb2N1cy10ZW1wJyk7XG4gICAgICAgIH0gLy8gZml4IGJ1ZzogJC5kYXRhKCkgaXMgbm90IHdvcmtpbmcgYXMgZXhwZWN0ZWQgYWZ0ZXIgJC5hcHBlbmQoKVxuXG5cbiAgICAgICAgdGhpcy4kaGVhZGVyLmZpbmQoJ3RoW2RhdGEtZmllbGRdJykuZWFjaChmdW5jdGlvbiAoaSwgZWwpIHtcbiAgICAgICAgICBfdGhpczE0LiRoZWFkZXJfLmZpbmQoVXRpbHMuc3ByaW50ZigndGhbZGF0YS1maWVsZD1cIiVzXCJdJywgJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKS5kYXRhKCdmaWVsZCcpKSkuZGF0YSgkX19kZWZhdWx0WydkZWZhdWx0J10oZWwpLmRhdGEoKSk7XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgdmlzaWJsZUZpZWxkcyA9IHRoaXMuZ2V0VmlzaWJsZUZpZWxkcygpO1xuICAgICAgICB2YXIgJHRocyA9IHRoaXMuJGhlYWRlcl8uZmluZCgndGgnKTtcbiAgICAgICAgdmFyICR0ciA9IHRoaXMuJGJvZHkuZmluZCgnPnRyOm5vdCgubm8tcmVjb3Jkcy1mb3VuZCwudmlydHVhbC1zY3JvbGwtdG9wKScpLmVxKDApO1xuXG4gICAgICAgIHdoaWxlICgkdHIubGVuZ3RoICYmICR0ci5maW5kKCc+dGRbY29sc3Bhbl06bm90KFtjb2xzcGFuPVwiMVwiXSknKS5sZW5ndGgpIHtcbiAgICAgICAgICAkdHIgPSAkdHIubmV4dCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHRyTGVuZ3RoID0gJHRyLmZpbmQoJz4gKicpLmxlbmd0aDtcbiAgICAgICAgJHRyLmZpbmQoJz4gKicpLmVhY2goZnVuY3Rpb24gKGksIGVsKSB7XG4gICAgICAgICAgdmFyICR0aGlzID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKTtcblxuICAgICAgICAgIGlmIChVdGlscy5oYXNEZXRhaWxWaWV3SWNvbihfdGhpczE0Lm9wdGlvbnMpKSB7XG4gICAgICAgICAgICBpZiAoaSA9PT0gMCAmJiBfdGhpczE0Lm9wdGlvbnMuZGV0YWlsVmlld0FsaWduICE9PSAncmlnaHQnIHx8IGkgPT09IHRyTGVuZ3RoIC0gMSAmJiBfdGhpczE0Lm9wdGlvbnMuZGV0YWlsVmlld0FsaWduID09PSAncmlnaHQnKSB7XG4gICAgICAgICAgICAgIHZhciAkdGhEZXRhaWwgPSAkdGhzLmZpbHRlcignLmRldGFpbCcpO1xuXG4gICAgICAgICAgICAgIHZhciBfem9vbVdpZHRoID0gJHRoRGV0YWlsLmlubmVyV2lkdGgoKSAtICR0aERldGFpbC5maW5kKCcuZmh0LWNlbGwnKS53aWR0aCgpO1xuXG4gICAgICAgICAgICAgICR0aERldGFpbC5maW5kKCcuZmh0LWNlbGwnKS53aWR0aCgkdGhpcy5pbm5lcldpZHRoKCkgLSBfem9vbVdpZHRoKTtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciBpbmRleCA9IGkgLSBVdGlscy5nZXREZXRhaWxWaWV3SW5kZXhPZmZzZXQoX3RoaXMxNC5vcHRpb25zKTtcblxuICAgICAgICAgIHZhciAkdGggPSBfdGhpczE0LiRoZWFkZXJfLmZpbmQoVXRpbHMuc3ByaW50ZigndGhbZGF0YS1maWVsZD1cIiVzXCJdJywgdmlzaWJsZUZpZWxkc1tpbmRleF0pKTtcblxuICAgICAgICAgIGlmICgkdGgubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgJHRoID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKCR0aHNbJHRoaXNbMF0uY2VsbEluZGV4XSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIHpvb21XaWR0aCA9ICR0aC5pbm5lcldpZHRoKCkgLSAkdGguZmluZCgnLmZodC1jZWxsJykud2lkdGgoKTtcbiAgICAgICAgICAkdGguZmluZCgnLmZodC1jZWxsJykud2lkdGgoJHRoaXMuaW5uZXJXaWR0aCgpIC0gem9vbVdpZHRoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuaG9yaXpvbnRhbFNjcm9sbCgpO1xuICAgICAgICB0aGlzLnRyaWdnZXIoJ3Bvc3QtaGVhZGVyJyk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImluaXRGb290ZXJcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0Rm9vdGVyKCkge1xuICAgICAgICBpZiAoIXRoaXMub3B0aW9ucy5zaG93Rm9vdGVyIHx8IHRoaXMub3B0aW9ucy5jYXJkVmlldykge1xuICAgICAgICAgIC8vIGRvIG5vdGhpbmdcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZGF0YSA9IHRoaXMuZ2V0RGF0YSgpO1xuICAgICAgICB2YXIgaHRtbCA9IFtdO1xuICAgICAgICB2YXIgZGV0YWlsVGVtcGxhdGUgPSAnJztcblxuICAgICAgICBpZiAoVXRpbHMuaGFzRGV0YWlsVmlld0ljb24odGhpcy5vcHRpb25zKSkge1xuICAgICAgICAgIGRldGFpbFRlbXBsYXRlID0gJzx0aCBjbGFzcz1cImRldGFpbFwiPjxkaXYgY2xhc3M9XCJ0aC1pbm5lclwiPjwvZGl2PjxkaXYgY2xhc3M9XCJmaHQtY2VsbFwiPjwvZGl2PjwvdGg+JztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkZXRhaWxUZW1wbGF0ZSAmJiB0aGlzLm9wdGlvbnMuZGV0YWlsVmlld0FsaWduICE9PSAncmlnaHQnKSB7XG4gICAgICAgICAgaHRtbC5wdXNoKGRldGFpbFRlbXBsYXRlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBfaXRlcmF0b3I0ID0gX2NyZWF0ZUZvck9mSXRlcmF0b3JIZWxwZXIodGhpcy5jb2x1bW5zKSxcbiAgICAgICAgICAgIF9zdGVwNDtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGZvciAoX2l0ZXJhdG9yNC5zKCk7ICEoX3N0ZXA0ID0gX2l0ZXJhdG9yNC5uKCkpLmRvbmU7KSB7XG4gICAgICAgICAgICB2YXIgY29sdW1uID0gX3N0ZXA0LnZhbHVlO1xuICAgICAgICAgICAgdmFyIGZhbGlnbiA9ICcnO1xuICAgICAgICAgICAgdmFyIHZhbGlnbiA9ICcnO1xuICAgICAgICAgICAgdmFyIGNzc2VzID0gW107XG4gICAgICAgICAgICB2YXIgc3R5bGUgPSB7fTtcbiAgICAgICAgICAgIHZhciBjbGFzc18gPSBVdGlscy5zcHJpbnRmKCcgY2xhc3M9XCIlc1wiJywgY29sdW1uWydjbGFzcyddKTtcblxuICAgICAgICAgICAgaWYgKCFjb2x1bW4udmlzaWJsZSB8fCB0aGlzLmZvb3RlckRhdGEgJiYgdGhpcy5mb290ZXJEYXRhLmxlbmd0aCA+IDAgJiYgIShjb2x1bW4uZmllbGQgaW4gdGhpcy5mb290ZXJEYXRhWzBdKSkge1xuICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5jYXJkVmlldyAmJiAhY29sdW1uLmNhcmRWaXNpYmxlKSB7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZmFsaWduID0gVXRpbHMuc3ByaW50ZigndGV4dC1hbGlnbjogJXM7ICcsIGNvbHVtbi5mYWxpZ24gPyBjb2x1bW4uZmFsaWduIDogY29sdW1uLmFsaWduKTtcbiAgICAgICAgICAgIHZhbGlnbiA9IFV0aWxzLnNwcmludGYoJ3ZlcnRpY2FsLWFsaWduOiAlczsgJywgY29sdW1uLnZhbGlnbik7XG4gICAgICAgICAgICBzdHlsZSA9IFV0aWxzLmNhbGN1bGF0ZU9iamVjdFZhbHVlKG51bGwsIHRoaXMub3B0aW9ucy5mb290ZXJTdHlsZSwgW2NvbHVtbl0pO1xuXG4gICAgICAgICAgICBpZiAoc3R5bGUgJiYgc3R5bGUuY3NzKSB7XG4gICAgICAgICAgICAgIGZvciAodmFyIF9pMTIgPSAwLCBfT2JqZWN0JGVudHJpZXMxMSA9IE9iamVjdC5lbnRyaWVzKHN0eWxlLmNzcyk7IF9pMTIgPCBfT2JqZWN0JGVudHJpZXMxMS5sZW5ndGg7IF9pMTIrKykge1xuICAgICAgICAgICAgICAgIHZhciBfT2JqZWN0JGVudHJpZXMxMSRfaSA9IF9zbGljZWRUb0FycmF5KF9PYmplY3QkZW50cmllczExW19pMTJdLCAyKSxcbiAgICAgICAgICAgICAgICAgICAga2V5ID0gX09iamVjdCRlbnRyaWVzMTEkX2lbMF0sXG4gICAgICAgICAgICAgICAgICAgIF92YWx1ZTMgPSBfT2JqZWN0JGVudHJpZXMxMSRfaVsxXTtcblxuICAgICAgICAgICAgICAgIGNzc2VzLnB1c2goXCJcIi5jb25jYXQoa2V5LCBcIjogXCIpLmNvbmNhdChfdmFsdWUzKSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHN0eWxlICYmIHN0eWxlLmNsYXNzZXMpIHtcbiAgICAgICAgICAgICAgY2xhc3NfID0gVXRpbHMuc3ByaW50ZignIGNsYXNzPVwiJXNcIicsIGNvbHVtblsnY2xhc3MnXSA/IFtjb2x1bW5bJ2NsYXNzJ10sIHN0eWxlLmNsYXNzZXNdLmpvaW4oJyAnKSA6IHN0eWxlLmNsYXNzZXMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBodG1sLnB1c2goJzx0aCcsIGNsYXNzXywgVXRpbHMuc3ByaW50ZignIHN0eWxlPVwiJXNcIicsIGZhbGlnbiArIHZhbGlnbiArIGNzc2VzLmNvbmNhdCgpLmpvaW4oJzsgJykpKTtcbiAgICAgICAgICAgIHZhciBjb2xzcGFuID0gMDtcblxuICAgICAgICAgICAgaWYgKHRoaXMuZm9vdGVyRGF0YSAmJiB0aGlzLmZvb3RlckRhdGEubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICBjb2xzcGFuID0gdGhpcy5mb290ZXJEYXRhWzBdW1wiX1wiLmNvbmNhdChjb2x1bW4uZmllbGQsIFwiX2NvbHNwYW5cIildIHx8IDA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb2xzcGFuKSB7XG4gICAgICAgICAgICAgIGh0bWwucHVzaChcIiBjb2xzcGFuPVxcXCJcIi5jb25jYXQoY29sc3BhbiwgXCJcXFwiIFwiKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGh0bWwucHVzaCgnPicpO1xuICAgICAgICAgICAgaHRtbC5wdXNoKCc8ZGl2IGNsYXNzPVwidGgtaW5uZXJcIj4nKTtcbiAgICAgICAgICAgIHZhciB2YWx1ZSA9ICcnO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5mb290ZXJEYXRhICYmIHRoaXMuZm9vdGVyRGF0YS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgIHZhbHVlID0gdGhpcy5mb290ZXJEYXRhWzBdW2NvbHVtbi5maWVsZF0gfHwgJyc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGh0bWwucHVzaChVdGlscy5jYWxjdWxhdGVPYmplY3RWYWx1ZShjb2x1bW4sIGNvbHVtbi5mb290ZXJGb3JtYXR0ZXIsIFtkYXRhLCB2YWx1ZV0sIHZhbHVlKSk7XG4gICAgICAgICAgICBodG1sLnB1c2goJzwvZGl2PicpO1xuICAgICAgICAgICAgaHRtbC5wdXNoKCc8ZGl2IGNsYXNzPVwiZmh0LWNlbGxcIj48L2Rpdj4nKTtcbiAgICAgICAgICAgIGh0bWwucHVzaCgnPC9kaXY+Jyk7XG4gICAgICAgICAgICBodG1sLnB1c2goJzwvdGg+Jyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBfaXRlcmF0b3I0LmUoZXJyKTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICBfaXRlcmF0b3I0LmYoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkZXRhaWxUZW1wbGF0ZSAmJiB0aGlzLm9wdGlvbnMuZGV0YWlsVmlld0FsaWduID09PSAncmlnaHQnKSB7XG4gICAgICAgICAgaHRtbC5wdXNoKGRldGFpbFRlbXBsYXRlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5vcHRpb25zLmhlaWdodCAmJiAhdGhpcy4kdGFibGVGb290ZXIubGVuZ3RoKSB7XG4gICAgICAgICAgdGhpcy4kZWwuYXBwZW5kKCc8dGZvb3Q+PHRyPjwvdHI+PC90Zm9vdD4nKTtcbiAgICAgICAgICB0aGlzLiR0YWJsZUZvb3RlciA9IHRoaXMuJGVsLmZpbmQoJ3Rmb290Jyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuJHRhYmxlRm9vdGVyLmZpbmQoJ3RyJykubGVuZ3RoKSB7XG4gICAgICAgICAgdGhpcy4kdGFibGVGb290ZXIuaHRtbCgnPHRhYmxlPjx0aGVhZD48dHI+PC90cj48L3RoZWFkPjwvdGFibGU+Jyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLiR0YWJsZUZvb3Rlci5maW5kKCd0cicpLmh0bWwoaHRtbC5qb2luKCcnKSk7XG4gICAgICAgIHRoaXMudHJpZ2dlcigncG9zdC1mb290ZXInLCB0aGlzLiR0YWJsZUZvb3Rlcik7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImZpdEZvb3RlclwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGZpdEZvb3RlcigpIHtcbiAgICAgICAgdmFyIF90aGlzMTUgPSB0aGlzO1xuXG4gICAgICAgIGlmICh0aGlzLiRlbC5pcygnOmhpZGRlbicpKSB7XG4gICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gX3RoaXMxNS5maXRGb290ZXIoKTtcbiAgICAgICAgICB9LCAxMDApO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBmaXhlZEJvZHkgPSB0aGlzLiR0YWJsZUJvZHkuZ2V0KDApO1xuICAgICAgICB2YXIgc2Nyb2xsV2lkdGggPSBmaXhlZEJvZHkuc2Nyb2xsV2lkdGggPiBmaXhlZEJvZHkuY2xpZW50V2lkdGggJiYgZml4ZWRCb2R5LnNjcm9sbEhlaWdodCA+IGZpeGVkQm9keS5jbGllbnRIZWlnaHQgKyB0aGlzLiRoZWFkZXIub3V0ZXJIZWlnaHQoKSA/IFV0aWxzLmdldFNjcm9sbEJhcldpZHRoKCkgOiAwO1xuICAgICAgICB0aGlzLiR0YWJsZUZvb3Rlci5jc3MoJ21hcmdpbi1yaWdodCcsIHNjcm9sbFdpZHRoKS5maW5kKCd0YWJsZScpLmNzcygnd2lkdGgnLCB0aGlzLiRlbC5vdXRlcldpZHRoKCkpLmF0dHIoJ2NsYXNzJywgdGhpcy4kZWwuYXR0cignY2xhc3MnKSk7XG4gICAgICAgIHZhciAkdGhzID0gdGhpcy4kdGFibGVGb290ZXIuZmluZCgndGgnKTtcbiAgICAgICAgdmFyICR0ciA9IHRoaXMuJGJvZHkuZmluZCgnPnRyOmZpcnN0LWNoaWxkOm5vdCgubm8tcmVjb3Jkcy1mb3VuZCknKTtcbiAgICAgICAgJHRocy5maW5kKCcuZmh0LWNlbGwnKS53aWR0aCgnYXV0bycpO1xuXG4gICAgICAgIHdoaWxlICgkdHIubGVuZ3RoICYmICR0ci5maW5kKCc+dGRbY29sc3Bhbl06bm90KFtjb2xzcGFuPVwiMVwiXSknKS5sZW5ndGgpIHtcbiAgICAgICAgICAkdHIgPSAkdHIubmV4dCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHRyTGVuZ3RoID0gJHRyLmZpbmQoJz4gKicpLmxlbmd0aDtcbiAgICAgICAgJHRyLmZpbmQoJz4gKicpLmVhY2goZnVuY3Rpb24gKGksIGVsKSB7XG4gICAgICAgICAgdmFyICR0aGlzID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKTtcblxuICAgICAgICAgIGlmIChVdGlscy5oYXNEZXRhaWxWaWV3SWNvbihfdGhpczE1Lm9wdGlvbnMpKSB7XG4gICAgICAgICAgICBpZiAoaSA9PT0gMCAmJiBfdGhpczE1Lm9wdGlvbnMuZGV0YWlsVmlld0FsaWduID09PSAnbGVmdCcgfHwgaSA9PT0gdHJMZW5ndGggLSAxICYmIF90aGlzMTUub3B0aW9ucy5kZXRhaWxWaWV3QWxpZ24gPT09ICdyaWdodCcpIHtcbiAgICAgICAgICAgICAgdmFyICR0aERldGFpbCA9ICR0aHMuZmlsdGVyKCcuZGV0YWlsJyk7XG5cbiAgICAgICAgICAgICAgdmFyIF96b29tV2lkdGgyID0gJHRoRGV0YWlsLmlubmVyV2lkdGgoKSAtICR0aERldGFpbC5maW5kKCcuZmh0LWNlbGwnKS53aWR0aCgpO1xuXG4gICAgICAgICAgICAgICR0aERldGFpbC5maW5kKCcuZmh0LWNlbGwnKS53aWR0aCgkdGhpcy5pbm5lcldpZHRoKCkgLSBfem9vbVdpZHRoMik7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgJHRoID0gJHRocy5lcShpKTtcbiAgICAgICAgICB2YXIgem9vbVdpZHRoID0gJHRoLmlubmVyV2lkdGgoKSAtICR0aC5maW5kKCcuZmh0LWNlbGwnKS53aWR0aCgpO1xuICAgICAgICAgICR0aC5maW5kKCcuZmh0LWNlbGwnKS53aWR0aCgkdGhpcy5pbm5lcldpZHRoKCkgLSB6b29tV2lkdGgpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5ob3Jpem9udGFsU2Nyb2xsKCk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImhvcml6b250YWxTY3JvbGxcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBob3Jpem9udGFsU2Nyb2xsKCkge1xuICAgICAgICB2YXIgX3RoaXMxNiA9IHRoaXM7XG5cbiAgICAgICAgLy8gaG9yaXpvbnRhbCBzY3JvbGwgZXZlbnRcbiAgICAgICAgLy8gVE9ETzogaXQncyBwcm9iYWJseSBiZXR0ZXIgaW1wcm92aW5nIHRoZSBsYXlvdXQgdGhhbiBiaW5kaW5nIHRvIHNjcm9sbCBldmVudFxuICAgICAgICB0aGlzLiR0YWJsZUJvZHkub2ZmKCdzY3JvbGwnKS5vbignc2Nyb2xsJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHZhciBzY3JvbGxMZWZ0ID0gX3RoaXMxNi4kdGFibGVCb2R5LnNjcm9sbExlZnQoKTtcblxuICAgICAgICAgIGlmIChfdGhpczE2Lm9wdGlvbnMuc2hvd0hlYWRlciAmJiBfdGhpczE2Lm9wdGlvbnMuaGVpZ2h0KSB7XG4gICAgICAgICAgICBfdGhpczE2LiR0YWJsZUhlYWRlci5zY3JvbGxMZWZ0KHNjcm9sbExlZnQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChfdGhpczE2Lm9wdGlvbnMuc2hvd0Zvb3RlciAmJiAhX3RoaXMxNi5vcHRpb25zLmNhcmRWaWV3KSB7XG4gICAgICAgICAgICBfdGhpczE2LiR0YWJsZUZvb3Rlci5zY3JvbGxMZWZ0KHNjcm9sbExlZnQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIF90aGlzMTYudHJpZ2dlcignc2Nyb2xsLWJvZHknLCBfdGhpczE2LiR0YWJsZUJvZHkpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiZ2V0VmlzaWJsZUZpZWxkc1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGdldFZpc2libGVGaWVsZHMoKSB7XG4gICAgICAgIHZhciB2aXNpYmxlRmllbGRzID0gW107XG5cbiAgICAgICAgdmFyIF9pdGVyYXRvcjUgPSBfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlcih0aGlzLmhlYWRlci5maWVsZHMpLFxuICAgICAgICAgICAgX3N0ZXA1O1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZm9yIChfaXRlcmF0b3I1LnMoKTsgIShfc3RlcDUgPSBfaXRlcmF0b3I1Lm4oKSkuZG9uZTspIHtcbiAgICAgICAgICAgIHZhciBmaWVsZCA9IF9zdGVwNS52YWx1ZTtcbiAgICAgICAgICAgIHZhciBjb2x1bW4gPSB0aGlzLmNvbHVtbnNbdGhpcy5maWVsZHNDb2x1bW5zSW5kZXhbZmllbGRdXTtcblxuICAgICAgICAgICAgaWYgKCFjb2x1bW4gfHwgIWNvbHVtbi52aXNpYmxlKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2aXNpYmxlRmllbGRzLnB1c2goZmllbGQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgX2l0ZXJhdG9yNS5lKGVycik7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgX2l0ZXJhdG9yNS5mKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdmlzaWJsZUZpZWxkcztcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiaW5pdEhpZGRlblJvd3NcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0SGlkZGVuUm93cygpIHtcbiAgICAgICAgdGhpcy5oaWRkZW5Sb3dzID0gW107XG4gICAgICB9IC8vIFBVQkxJQyBGVU5DVElPTiBERUZJTklUSU9OXG4gICAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PVxuXG4gICAgfSwge1xuICAgICAga2V5OiBcImdldE9wdGlvbnNcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRPcHRpb25zKCkge1xuICAgICAgICAvLyBkZWVwIGNvcHkgYW5kIHJlbW92ZSBkYXRhXG4gICAgICAgIHZhciBvcHRpb25zID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddLmV4dGVuZCh7fSwgdGhpcy5vcHRpb25zKTtcbiAgICAgICAgZGVsZXRlIG9wdGlvbnMuZGF0YTtcbiAgICAgICAgcmV0dXJuICRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5leHRlbmQodHJ1ZSwge30sIG9wdGlvbnMpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJyZWZyZXNoT3B0aW9uc1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHJlZnJlc2hPcHRpb25zKG9wdGlvbnMpIHtcbiAgICAgICAgLy8gSWYgdGhlIG9iamVjdHMgYXJlIGVxdWl2YWxlbnQgdGhlbiBhdm9pZCB0aGUgY2FsbCBvZiBkZXN0cm95IC8gaW5pdCBtZXRob2RzXG4gICAgICAgIGlmIChVdGlscy5jb21wYXJlT2JqZWN0cyh0aGlzLm9wdGlvbnMsIG9wdGlvbnMsIHRydWUpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5vcHRpb25zID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddLmV4dGVuZCh0aGlzLm9wdGlvbnMsIG9wdGlvbnMpO1xuICAgICAgICB0aGlzLnRyaWdnZXIoJ3JlZnJlc2gtb3B0aW9ucycsIHRoaXMub3B0aW9ucyk7XG4gICAgICAgIHRoaXMuZGVzdHJveSgpO1xuICAgICAgICB0aGlzLmluaXQoKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiZ2V0RGF0YVwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGdldERhdGEocGFyYW1zKSB7XG4gICAgICAgIHZhciBfdGhpczE3ID0gdGhpcztcblxuICAgICAgICB2YXIgZGF0YSA9IHRoaXMub3B0aW9ucy5kYXRhO1xuXG4gICAgICAgIGlmICgodGhpcy5zZWFyY2hUZXh0IHx8IHRoaXMub3B0aW9ucy5jdXN0b21TZWFyY2ggfHwgdGhpcy5vcHRpb25zLnNvcnROYW1lICE9PSB1bmRlZmluZWQgfHwgdGhpcy5lbmFibGVDdXN0b21Tb3J0IHx8IC8vIEZpeCAjNDYxNjogdGhpcy5lbmFibGVDdXN0b21Tb3J0IGlzIGZvciBleHRlbnNpb25zXG4gICAgICAgICFVdGlscy5pc0VtcHR5T2JqZWN0KHRoaXMuZmlsdGVyQ29sdW1ucykgfHwgIVV0aWxzLmlzRW1wdHlPYmplY3QodGhpcy5maWx0ZXJDb2x1bW5zUGFydGlhbCkpICYmICghcGFyYW1zIHx8ICFwYXJhbXMudW5maWx0ZXJlZCkpIHtcbiAgICAgICAgICBkYXRhID0gdGhpcy5kYXRhO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcmFtcyAmJiBwYXJhbXMudXNlQ3VycmVudFBhZ2UpIHtcbiAgICAgICAgICBkYXRhID0gZGF0YS5zbGljZSh0aGlzLnBhZ2VGcm9tIC0gMSwgdGhpcy5wYWdlVG8pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcmFtcyAmJiAhcGFyYW1zLmluY2x1ZGVIaWRkZW5Sb3dzKSB7XG4gICAgICAgICAgdmFyIGhpZGRlblJvd3MgPSB0aGlzLmdldEhpZGRlblJvd3MoKTtcbiAgICAgICAgICBkYXRhID0gZGF0YS5maWx0ZXIoZnVuY3Rpb24gKHJvdykge1xuICAgICAgICAgICAgcmV0dXJuIFV0aWxzLmZpbmRJbmRleChoaWRkZW5Sb3dzLCByb3cpID09PSAtMTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwYXJhbXMgJiYgcGFyYW1zLmZvcm1hdHRlZCkge1xuICAgICAgICAgIGRhdGEuZm9yRWFjaChmdW5jdGlvbiAocm93KSB7XG4gICAgICAgICAgICBmb3IgKHZhciBfaTEzID0gMCwgX09iamVjdCRlbnRyaWVzMTIgPSBPYmplY3QuZW50cmllcyhyb3cpOyBfaTEzIDwgX09iamVjdCRlbnRyaWVzMTIubGVuZ3RoOyBfaTEzKyspIHtcbiAgICAgICAgICAgICAgdmFyIF9PYmplY3QkZW50cmllczEyJF9pID0gX3NsaWNlZFRvQXJyYXkoX09iamVjdCRlbnRyaWVzMTJbX2kxM10sIDIpLFxuICAgICAgICAgICAgICAgICAga2V5ID0gX09iamVjdCRlbnRyaWVzMTIkX2lbMF0sXG4gICAgICAgICAgICAgICAgICB2YWx1ZSA9IF9PYmplY3QkZW50cmllczEyJF9pWzFdO1xuXG4gICAgICAgICAgICAgIHZhciBjb2x1bW4gPSBfdGhpczE3LmNvbHVtbnNbX3RoaXMxNy5maWVsZHNDb2x1bW5zSW5kZXhba2V5XV07XG5cbiAgICAgICAgICAgICAgaWYgKCFjb2x1bW4pIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICByb3dba2V5XSA9IFV0aWxzLmNhbGN1bGF0ZU9iamVjdFZhbHVlKGNvbHVtbiwgX3RoaXMxNy5oZWFkZXIuZm9ybWF0dGVyc1tjb2x1bW4uZmllbGRJbmRleF0sIFt2YWx1ZSwgcm93LCByb3cuaW5kZXgsIGNvbHVtbi5maWVsZF0sIHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJnZXRTZWxlY3Rpb25zXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0U2VsZWN0aW9ucygpIHtcbiAgICAgICAgdmFyIF90aGlzMTggPSB0aGlzO1xuXG4gICAgICAgIHJldHVybiAodGhpcy5vcHRpb25zLm1haW50YWluTWV0YURhdGEgPyB0aGlzLm9wdGlvbnMuZGF0YSA6IHRoaXMuZGF0YSkuZmlsdGVyKGZ1bmN0aW9uIChyb3cpIHtcbiAgICAgICAgICByZXR1cm4gcm93W190aGlzMTguaGVhZGVyLnN0YXRlRmllbGRdID09PSB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwibG9hZFwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGxvYWQoX2RhdGEpIHtcbiAgICAgICAgdmFyIGZpeGVkU2Nyb2xsID0gZmFsc2U7XG4gICAgICAgIHZhciBkYXRhID0gX2RhdGE7IC8vICM0MzE6IHN1cHBvcnQgcGFnaW5hdGlvblxuXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMucGFnaW5hdGlvbiAmJiB0aGlzLm9wdGlvbnMuc2lkZVBhZ2luYXRpb24gPT09ICdzZXJ2ZXInKSB7XG4gICAgICAgICAgdGhpcy5vcHRpb25zLnRvdGFsUm93cyA9IGRhdGFbdGhpcy5vcHRpb25zLnRvdGFsRmllbGRdO1xuICAgICAgICAgIHRoaXMub3B0aW9ucy50b3RhbE5vdEZpbHRlcmVkID0gZGF0YVt0aGlzLm9wdGlvbnMudG90YWxOb3RGaWx0ZXJlZEZpZWxkXTtcbiAgICAgICAgICB0aGlzLmZvb3RlckRhdGEgPSBkYXRhW3RoaXMub3B0aW9ucy5mb290ZXJGaWVsZF0gPyBbZGF0YVt0aGlzLm9wdGlvbnMuZm9vdGVyRmllbGRdXSA6IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGZpeGVkU2Nyb2xsID0gZGF0YS5maXhlZFNjcm9sbDtcbiAgICAgICAgZGF0YSA9IEFycmF5LmlzQXJyYXkoZGF0YSkgPyBkYXRhIDogZGF0YVt0aGlzLm9wdGlvbnMuZGF0YUZpZWxkXTtcbiAgICAgICAgdGhpcy5pbml0RGF0YShkYXRhKTtcbiAgICAgICAgdGhpcy5pbml0U2VhcmNoKCk7XG4gICAgICAgIHRoaXMuaW5pdFBhZ2luYXRpb24oKTtcbiAgICAgICAgdGhpcy5pbml0Qm9keShmaXhlZFNjcm9sbCk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImFwcGVuZFwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGFwcGVuZChkYXRhKSB7XG4gICAgICAgIHRoaXMuaW5pdERhdGEoZGF0YSwgJ2FwcGVuZCcpO1xuICAgICAgICB0aGlzLmluaXRTZWFyY2goKTtcbiAgICAgICAgdGhpcy5pbml0UGFnaW5hdGlvbigpO1xuICAgICAgICB0aGlzLmluaXRTb3J0KCk7XG4gICAgICAgIHRoaXMuaW5pdEJvZHkodHJ1ZSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInByZXBlbmRcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBwcmVwZW5kKGRhdGEpIHtcbiAgICAgICAgdGhpcy5pbml0RGF0YShkYXRhLCAncHJlcGVuZCcpO1xuICAgICAgICB0aGlzLmluaXRTZWFyY2goKTtcbiAgICAgICAgdGhpcy5pbml0UGFnaW5hdGlvbigpO1xuICAgICAgICB0aGlzLmluaXRTb3J0KCk7XG4gICAgICAgIHRoaXMuaW5pdEJvZHkodHJ1ZSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInJlbW92ZVwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHJlbW92ZShwYXJhbXMpIHtcbiAgICAgICAgdmFyIHJlbW92ZWQgPSAwO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSB0aGlzLm9wdGlvbnMuZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgIHZhciByb3cgPSB0aGlzLm9wdGlvbnMuZGF0YVtpXTtcblxuICAgICAgICAgIGlmICghcm93Lmhhc093blByb3BlcnR5KHBhcmFtcy5maWVsZCkgJiYgcGFyYW1zLmZpZWxkICE9PSAnJGluZGV4Jykge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCFyb3cuaGFzT3duUHJvcGVydHkocGFyYW1zLmZpZWxkKSAmJiBwYXJhbXMuZmllbGQgPT09ICckaW5kZXgnICYmIHBhcmFtcy52YWx1ZXMuaW5jbHVkZXMoaSkgfHwgcGFyYW1zLnZhbHVlcy5pbmNsdWRlcyhyb3dbcGFyYW1zLmZpZWxkXSkpIHtcbiAgICAgICAgICAgIHJlbW92ZWQrKztcbiAgICAgICAgICAgIHRoaXMub3B0aW9ucy5kYXRhLnNwbGljZShpLCAxKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXJlbW92ZWQpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNpZGVQYWdpbmF0aW9uID09PSAnc2VydmVyJykge1xuICAgICAgICAgIHRoaXMub3B0aW9ucy50b3RhbFJvd3MgLT0gcmVtb3ZlZDtcbiAgICAgICAgICB0aGlzLmRhdGEgPSBfdG9Db25zdW1hYmxlQXJyYXkodGhpcy5vcHRpb25zLmRhdGEpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5pbml0U2VhcmNoKCk7XG4gICAgICAgIHRoaXMuaW5pdFBhZ2luYXRpb24oKTtcbiAgICAgICAgdGhpcy5pbml0U29ydCgpO1xuICAgICAgICB0aGlzLmluaXRCb2R5KHRydWUpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJyZW1vdmVBbGxcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiByZW1vdmVBbGwoKSB7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuZGF0YS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgdGhpcy5vcHRpb25zLmRhdGEuc3BsaWNlKDAsIHRoaXMub3B0aW9ucy5kYXRhLmxlbmd0aCk7XG4gICAgICAgICAgdGhpcy5pbml0U2VhcmNoKCk7XG4gICAgICAgICAgdGhpcy5pbml0UGFnaW5hdGlvbigpO1xuICAgICAgICAgIHRoaXMuaW5pdEJvZHkodHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiaW5zZXJ0Um93XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaW5zZXJ0Um93KHBhcmFtcykge1xuICAgICAgICBpZiAoIXBhcmFtcy5oYXNPd25Qcm9wZXJ0eSgnaW5kZXgnKSB8fCAhcGFyYW1zLmhhc093blByb3BlcnR5KCdyb3cnKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMub3B0aW9ucy5kYXRhLnNwbGljZShwYXJhbXMuaW5kZXgsIDAsIHBhcmFtcy5yb3cpO1xuICAgICAgICB0aGlzLmluaXRTZWFyY2goKTtcbiAgICAgICAgdGhpcy5pbml0UGFnaW5hdGlvbigpO1xuICAgICAgICB0aGlzLmluaXRTb3J0KCk7XG4gICAgICAgIHRoaXMuaW5pdEJvZHkodHJ1ZSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInVwZGF0ZVJvd1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHVwZGF0ZVJvdyhwYXJhbXMpIHtcbiAgICAgICAgdmFyIGFsbFBhcmFtcyA9IEFycmF5LmlzQXJyYXkocGFyYW1zKSA/IHBhcmFtcyA6IFtwYXJhbXNdO1xuXG4gICAgICAgIHZhciBfaXRlcmF0b3I2ID0gX2NyZWF0ZUZvck9mSXRlcmF0b3JIZWxwZXIoYWxsUGFyYW1zKSxcbiAgICAgICAgICAgIF9zdGVwNjtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGZvciAoX2l0ZXJhdG9yNi5zKCk7ICEoX3N0ZXA2ID0gX2l0ZXJhdG9yNi5uKCkpLmRvbmU7KSB7XG4gICAgICAgICAgICB2YXIgX3BhcmFtcyA9IF9zdGVwNi52YWx1ZTtcblxuICAgICAgICAgICAgaWYgKCFfcGFyYW1zLmhhc093blByb3BlcnR5KCdpbmRleCcpIHx8ICFfcGFyYW1zLmhhc093blByb3BlcnR5KCdyb3cnKSkge1xuICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKF9wYXJhbXMuaGFzT3duUHJvcGVydHkoJ3JlcGxhY2UnKSAmJiBfcGFyYW1zLnJlcGxhY2UpIHtcbiAgICAgICAgICAgICAgdGhpcy5vcHRpb25zLmRhdGFbX3BhcmFtcy5pbmRleF0gPSBfcGFyYW1zLnJvdztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5leHRlbmQodGhpcy5vcHRpb25zLmRhdGFbX3BhcmFtcy5pbmRleF0sIF9wYXJhbXMucm93KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIF9pdGVyYXRvcjYuZShlcnIpO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIF9pdGVyYXRvcjYuZigpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5pbml0U2VhcmNoKCk7XG4gICAgICAgIHRoaXMuaW5pdFBhZ2luYXRpb24oKTtcbiAgICAgICAgdGhpcy5pbml0U29ydCgpO1xuICAgICAgICB0aGlzLmluaXRCb2R5KHRydWUpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJnZXRSb3dCeVVuaXF1ZUlkXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0Um93QnlVbmlxdWVJZChfaWQpIHtcbiAgICAgICAgdmFyIHVuaXF1ZUlkID0gdGhpcy5vcHRpb25zLnVuaXF1ZUlkO1xuICAgICAgICB2YXIgbGVuID0gdGhpcy5vcHRpb25zLmRhdGEubGVuZ3RoO1xuICAgICAgICB2YXIgaWQgPSBfaWQ7XG4gICAgICAgIHZhciBkYXRhUm93ID0gbnVsbDtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciByb3c7XG4gICAgICAgIHZhciByb3dVbmlxdWVJZDtcblxuICAgICAgICBmb3IgKGkgPSBsZW4gLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgIHJvdyA9IHRoaXMub3B0aW9ucy5kYXRhW2ldO1xuXG4gICAgICAgICAgaWYgKHJvdy5oYXNPd25Qcm9wZXJ0eSh1bmlxdWVJZCkpIHtcbiAgICAgICAgICAgIC8vIHVuaXF1ZUlkIGlzIGEgY29sdW1uXG4gICAgICAgICAgICByb3dVbmlxdWVJZCA9IHJvd1t1bmlxdWVJZF07XG4gICAgICAgICAgfSBlbHNlIGlmIChyb3cuX2RhdGEgJiYgcm93Ll9kYXRhLmhhc093blByb3BlcnR5KHVuaXF1ZUlkKSkge1xuICAgICAgICAgICAgLy8gdW5pcXVlSWQgaXMgYSByb3cgZGF0YSBwcm9wZXJ0eVxuICAgICAgICAgICAgcm93VW5pcXVlSWQgPSByb3cuX2RhdGFbdW5pcXVlSWRdO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAodHlwZW9mIHJvd1VuaXF1ZUlkID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgaWQgPSBpZC50b1N0cmluZygpO1xuICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHJvd1VuaXF1ZUlkID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgaWYgKE51bWJlcihyb3dVbmlxdWVJZCkgPT09IHJvd1VuaXF1ZUlkICYmIHJvd1VuaXF1ZUlkICUgMSA9PT0gMCkge1xuICAgICAgICAgICAgICBpZCA9IHBhcnNlSW50KGlkKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocm93VW5pcXVlSWQgPT09IE51bWJlcihyb3dVbmlxdWVJZCkgJiYgcm93VW5pcXVlSWQgIT09IDApIHtcbiAgICAgICAgICAgICAgaWQgPSBwYXJzZUZsb2F0KGlkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAocm93VW5pcXVlSWQgPT09IGlkKSB7XG4gICAgICAgICAgICBkYXRhUm93ID0gcm93O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGRhdGFSb3c7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInVwZGF0ZUJ5VW5pcXVlSWRcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiB1cGRhdGVCeVVuaXF1ZUlkKHBhcmFtcykge1xuICAgICAgICB2YXIgYWxsUGFyYW1zID0gQXJyYXkuaXNBcnJheShwYXJhbXMpID8gcGFyYW1zIDogW3BhcmFtc107XG5cbiAgICAgICAgdmFyIF9pdGVyYXRvcjcgPSBfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlcihhbGxQYXJhbXMpLFxuICAgICAgICAgICAgX3N0ZXA3O1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZm9yIChfaXRlcmF0b3I3LnMoKTsgIShfc3RlcDcgPSBfaXRlcmF0b3I3Lm4oKSkuZG9uZTspIHtcbiAgICAgICAgICAgIHZhciBfcGFyYW1zMiA9IF9zdGVwNy52YWx1ZTtcblxuICAgICAgICAgICAgaWYgKCFfcGFyYW1zMi5oYXNPd25Qcm9wZXJ0eSgnaWQnKSB8fCAhX3BhcmFtczIuaGFzT3duUHJvcGVydHkoJ3JvdycpKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgcm93SWQgPSB0aGlzLm9wdGlvbnMuZGF0YS5pbmRleE9mKHRoaXMuZ2V0Um93QnlVbmlxdWVJZChfcGFyYW1zMi5pZCkpO1xuXG4gICAgICAgICAgICBpZiAocm93SWQgPT09IC0xKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoX3BhcmFtczIuaGFzT3duUHJvcGVydHkoJ3JlcGxhY2UnKSAmJiBfcGFyYW1zMi5yZXBsYWNlKSB7XG4gICAgICAgICAgICAgIHRoaXMub3B0aW9ucy5kYXRhW3Jvd0lkXSA9IF9wYXJhbXMyLnJvdztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5leHRlbmQodGhpcy5vcHRpb25zLmRhdGFbcm93SWRdLCBfcGFyYW1zMi5yb3cpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgX2l0ZXJhdG9yNy5lKGVycik7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgX2l0ZXJhdG9yNy5mKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmluaXRTZWFyY2goKTtcbiAgICAgICAgdGhpcy5pbml0UGFnaW5hdGlvbigpO1xuICAgICAgICB0aGlzLmluaXRTb3J0KCk7XG4gICAgICAgIHRoaXMuaW5pdEJvZHkodHJ1ZSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInJlbW92ZUJ5VW5pcXVlSWRcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiByZW1vdmVCeVVuaXF1ZUlkKGlkKSB7XG4gICAgICAgIHZhciBsZW4gPSB0aGlzLm9wdGlvbnMuZGF0YS5sZW5ndGg7XG4gICAgICAgIHZhciByb3cgPSB0aGlzLmdldFJvd0J5VW5pcXVlSWQoaWQpO1xuXG4gICAgICAgIGlmIChyb3cpIHtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMuZGF0YS5zcGxpY2UodGhpcy5vcHRpb25zLmRhdGEuaW5kZXhPZihyb3cpLCAxKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChsZW4gPT09IHRoaXMub3B0aW9ucy5kYXRhLmxlbmd0aCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuc2lkZVBhZ2luYXRpb24gPT09ICdzZXJ2ZXInKSB7XG4gICAgICAgICAgdGhpcy5vcHRpb25zLnRvdGFsUm93cyAtPSAxO1xuICAgICAgICAgIHRoaXMuZGF0YSA9IF90b0NvbnN1bWFibGVBcnJheSh0aGlzLm9wdGlvbnMuZGF0YSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmluaXRTZWFyY2goKTtcbiAgICAgICAgdGhpcy5pbml0UGFnaW5hdGlvbigpO1xuICAgICAgICB0aGlzLmluaXRCb2R5KHRydWUpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJ1cGRhdGVDZWxsXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdXBkYXRlQ2VsbChwYXJhbXMpIHtcbiAgICAgICAgaWYgKCFwYXJhbXMuaGFzT3duUHJvcGVydHkoJ2luZGV4JykgfHwgIXBhcmFtcy5oYXNPd25Qcm9wZXJ0eSgnZmllbGQnKSB8fCAhcGFyYW1zLmhhc093blByb3BlcnR5KCd2YWx1ZScpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5kYXRhW3BhcmFtcy5pbmRleF1bcGFyYW1zLmZpZWxkXSA9IHBhcmFtcy52YWx1ZTtcblxuICAgICAgICBpZiAocGFyYW1zLnJlaW5pdCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmluaXRTb3J0KCk7XG4gICAgICAgIHRoaXMuaW5pdEJvZHkodHJ1ZSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInVwZGF0ZUNlbGxCeVVuaXF1ZUlkXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdXBkYXRlQ2VsbEJ5VW5pcXVlSWQocGFyYW1zKSB7XG4gICAgICAgIHZhciBfdGhpczE5ID0gdGhpcztcblxuICAgICAgICB2YXIgYWxsUGFyYW1zID0gQXJyYXkuaXNBcnJheShwYXJhbXMpID8gcGFyYW1zIDogW3BhcmFtc107XG4gICAgICAgIGFsbFBhcmFtcy5mb3JFYWNoKGZ1bmN0aW9uIChfcmVmNikge1xuICAgICAgICAgIHZhciBpZCA9IF9yZWY2LmlkLFxuICAgICAgICAgICAgICBmaWVsZCA9IF9yZWY2LmZpZWxkLFxuICAgICAgICAgICAgICB2YWx1ZSA9IF9yZWY2LnZhbHVlO1xuXG4gICAgICAgICAgdmFyIHJvd0lkID0gX3RoaXMxOS5vcHRpb25zLmRhdGEuaW5kZXhPZihfdGhpczE5LmdldFJvd0J5VW5pcXVlSWQoaWQpKTtcblxuICAgICAgICAgIGlmIChyb3dJZCA9PT0gLTEpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBfdGhpczE5Lm9wdGlvbnMuZGF0YVtyb3dJZF1bZmllbGRdID0gdmFsdWU7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChwYXJhbXMucmVpbml0ID09PSBmYWxzZSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaW5pdFNvcnQoKTtcbiAgICAgICAgdGhpcy5pbml0Qm9keSh0cnVlKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwic2hvd1Jvd1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHNob3dSb3cocGFyYW1zKSB7XG4gICAgICAgIHRoaXMuX3RvZ2dsZVJvdyhwYXJhbXMsIHRydWUpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJoaWRlUm93XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaGlkZVJvdyhwYXJhbXMpIHtcbiAgICAgICAgdGhpcy5fdG9nZ2xlUm93KHBhcmFtcywgZmFsc2UpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJfdG9nZ2xlUm93XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gX3RvZ2dsZVJvdyhwYXJhbXMsIHZpc2libGUpIHtcbiAgICAgICAgdmFyIHJvdztcblxuICAgICAgICBpZiAocGFyYW1zLmhhc093blByb3BlcnR5KCdpbmRleCcpKSB7XG4gICAgICAgICAgcm93ID0gdGhpcy5nZXREYXRhKClbcGFyYW1zLmluZGV4XTtcbiAgICAgICAgfSBlbHNlIGlmIChwYXJhbXMuaGFzT3duUHJvcGVydHkoJ3VuaXF1ZUlkJykpIHtcbiAgICAgICAgICByb3cgPSB0aGlzLmdldFJvd0J5VW5pcXVlSWQocGFyYW1zLnVuaXF1ZUlkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghcm93KSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGluZGV4ID0gVXRpbHMuZmluZEluZGV4KHRoaXMuaGlkZGVuUm93cywgcm93KTtcblxuICAgICAgICBpZiAoIXZpc2libGUgJiYgaW5kZXggPT09IC0xKSB7XG4gICAgICAgICAgdGhpcy5oaWRkZW5Sb3dzLnB1c2gocm93KTtcbiAgICAgICAgfSBlbHNlIGlmICh2aXNpYmxlICYmIGluZGV4ID4gLTEpIHtcbiAgICAgICAgICB0aGlzLmhpZGRlblJvd3Muc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaW5pdEJvZHkodHJ1ZSk7XG4gICAgICAgIHRoaXMuaW5pdFBhZ2luYXRpb24oKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiZ2V0SGlkZGVuUm93c1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGdldEhpZGRlblJvd3Moc2hvdykge1xuICAgICAgICBpZiAoc2hvdykge1xuICAgICAgICAgIHRoaXMuaW5pdEhpZGRlblJvd3MoKTtcbiAgICAgICAgICB0aGlzLmluaXRCb2R5KHRydWUpO1xuICAgICAgICAgIHRoaXMuaW5pdFBhZ2luYXRpb24oKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZGF0YSA9IHRoaXMuZ2V0RGF0YSgpO1xuICAgICAgICB2YXIgcm93cyA9IFtdO1xuXG4gICAgICAgIHZhciBfaXRlcmF0b3I4ID0gX2NyZWF0ZUZvck9mSXRlcmF0b3JIZWxwZXIoZGF0YSksXG4gICAgICAgICAgICBfc3RlcDg7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBmb3IgKF9pdGVyYXRvcjgucygpOyAhKF9zdGVwOCA9IF9pdGVyYXRvcjgubigpKS5kb25lOykge1xuICAgICAgICAgICAgdmFyIHJvdyA9IF9zdGVwOC52YWx1ZTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuaGlkZGVuUm93cy5pbmNsdWRlcyhyb3cpKSB7XG4gICAgICAgICAgICAgIHJvd3MucHVzaChyb3cpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgX2l0ZXJhdG9yOC5lKGVycik7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgX2l0ZXJhdG9yOC5mKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmhpZGRlblJvd3MgPSByb3dzO1xuICAgICAgICByZXR1cm4gcm93cztcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwic2hvd0NvbHVtblwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHNob3dDb2x1bW4oZmllbGQpIHtcbiAgICAgICAgdmFyIF90aGlzMjAgPSB0aGlzO1xuXG4gICAgICAgIHZhciBmaWVsZHMgPSBBcnJheS5pc0FycmF5KGZpZWxkKSA/IGZpZWxkIDogW2ZpZWxkXTtcbiAgICAgICAgZmllbGRzLmZvckVhY2goZnVuY3Rpb24gKGZpZWxkKSB7XG4gICAgICAgICAgX3RoaXMyMC5fdG9nZ2xlQ29sdW1uKF90aGlzMjAuZmllbGRzQ29sdW1uc0luZGV4W2ZpZWxkXSwgdHJ1ZSwgdHJ1ZSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJoaWRlQ29sdW1uXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaGlkZUNvbHVtbihmaWVsZCkge1xuICAgICAgICB2YXIgX3RoaXMyMSA9IHRoaXM7XG5cbiAgICAgICAgdmFyIGZpZWxkcyA9IEFycmF5LmlzQXJyYXkoZmllbGQpID8gZmllbGQgOiBbZmllbGRdO1xuICAgICAgICBmaWVsZHMuZm9yRWFjaChmdW5jdGlvbiAoZmllbGQpIHtcbiAgICAgICAgICBfdGhpczIxLl90b2dnbGVDb2x1bW4oX3RoaXMyMS5maWVsZHNDb2x1bW5zSW5kZXhbZmllbGRdLCBmYWxzZSwgdHJ1ZSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJfdG9nZ2xlQ29sdW1uXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gX3RvZ2dsZUNvbHVtbihpbmRleCwgY2hlY2tlZCwgbmVlZFVwZGF0ZSkge1xuICAgICAgICBpZiAoaW5kZXggPT09IC0xIHx8IHRoaXMuY29sdW1uc1tpbmRleF0udmlzaWJsZSA9PT0gY2hlY2tlZCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY29sdW1uc1tpbmRleF0udmlzaWJsZSA9IGNoZWNrZWQ7XG4gICAgICAgIHRoaXMuaW5pdEhlYWRlcigpO1xuICAgICAgICB0aGlzLmluaXRTZWFyY2goKTtcbiAgICAgICAgdGhpcy5pbml0UGFnaW5hdGlvbigpO1xuICAgICAgICB0aGlzLmluaXRCb2R5KCk7XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5zaG93Q29sdW1ucykge1xuICAgICAgICAgIHZhciAkaXRlbXMgPSB0aGlzLiR0b29sYmFyLmZpbmQoJy5rZWVwLW9wZW4gaW5wdXQ6bm90KFwiLnRvZ2dsZS1hbGxcIiknKS5wcm9wKCdkaXNhYmxlZCcsIGZhbHNlKTtcblxuICAgICAgICAgIGlmIChuZWVkVXBkYXRlKSB7XG4gICAgICAgICAgICAkaXRlbXMuZmlsdGVyKFV0aWxzLnNwcmludGYoJ1t2YWx1ZT1cIiVzXCJdJywgaW5kZXgpKS5wcm9wKCdjaGVja2VkJywgY2hlY2tlZCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCRpdGVtcy5maWx0ZXIoJzpjaGVja2VkJykubGVuZ3RoIDw9IHRoaXMub3B0aW9ucy5taW5pbXVtQ291bnRDb2x1bW5zKSB7XG4gICAgICAgICAgICAkaXRlbXMuZmlsdGVyKCc6Y2hlY2tlZCcpLnByb3AoJ2Rpc2FibGVkJywgdHJ1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImdldFZpc2libGVDb2x1bW5zXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0VmlzaWJsZUNvbHVtbnMoKSB7XG4gICAgICAgIHZhciBfdGhpczIyID0gdGhpcztcblxuICAgICAgICByZXR1cm4gdGhpcy5jb2x1bW5zLmZpbHRlcihmdW5jdGlvbiAoY29sdW1uKSB7XG4gICAgICAgICAgcmV0dXJuIGNvbHVtbi52aXNpYmxlICYmICFfdGhpczIyLmlzU2VsZWN0aW9uQ29sdW1uKGNvbHVtbik7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJnZXRIaWRkZW5Db2x1bW5zXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0SGlkZGVuQ29sdW1ucygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29sdW1ucy5maWx0ZXIoZnVuY3Rpb24gKF9yZWY3KSB7XG4gICAgICAgICAgdmFyIHZpc2libGUgPSBfcmVmNy52aXNpYmxlO1xuICAgICAgICAgIHJldHVybiAhdmlzaWJsZTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImlzU2VsZWN0aW9uQ29sdW1uXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaXNTZWxlY3Rpb25Db2x1bW4oY29sdW1uKSB7XG4gICAgICAgIHJldHVybiBjb2x1bW4ucmFkaW8gfHwgY29sdW1uLmNoZWNrYm94O1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJzaG93QWxsQ29sdW1uc1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHNob3dBbGxDb2x1bW5zKCkge1xuICAgICAgICB0aGlzLl90b2dnbGVBbGxDb2x1bW5zKHRydWUpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJoaWRlQWxsQ29sdW1uc1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGhpZGVBbGxDb2x1bW5zKCkge1xuICAgICAgICB0aGlzLl90b2dnbGVBbGxDb2x1bW5zKGZhbHNlKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiX3RvZ2dsZUFsbENvbHVtbnNcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBfdG9nZ2xlQWxsQ29sdW1ucyh2aXNpYmxlKSB7XG4gICAgICAgIHZhciBfdGhpczIzID0gdGhpcztcblxuICAgICAgICB2YXIgX2l0ZXJhdG9yOSA9IF9jcmVhdGVGb3JPZkl0ZXJhdG9ySGVscGVyKHRoaXMuY29sdW1ucy5zbGljZSgpLnJldmVyc2UoKSksXG4gICAgICAgICAgICBfc3RlcDk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBmb3IgKF9pdGVyYXRvcjkucygpOyAhKF9zdGVwOSA9IF9pdGVyYXRvcjkubigpKS5kb25lOykge1xuICAgICAgICAgICAgdmFyIGNvbHVtbiA9IF9zdGVwOS52YWx1ZTtcblxuICAgICAgICAgICAgaWYgKGNvbHVtbi5zd2l0Y2hhYmxlKSB7XG4gICAgICAgICAgICAgIGlmICghdmlzaWJsZSAmJiB0aGlzLm9wdGlvbnMuc2hvd0NvbHVtbnMgJiYgdGhpcy5nZXRWaXNpYmxlQ29sdW1ucygpLmxlbmd0aCA9PT0gdGhpcy5vcHRpb25zLm1pbmltdW1Db3VudENvbHVtbnMpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGNvbHVtbi52aXNpYmxlID0gdmlzaWJsZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIF9pdGVyYXRvcjkuZShlcnIpO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIF9pdGVyYXRvcjkuZigpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5pbml0SGVhZGVyKCk7XG4gICAgICAgIHRoaXMuaW5pdFNlYXJjaCgpO1xuICAgICAgICB0aGlzLmluaXRQYWdpbmF0aW9uKCk7XG4gICAgICAgIHRoaXMuaW5pdEJvZHkoKTtcblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNob3dDb2x1bW5zKSB7XG4gICAgICAgICAgdmFyICRpdGVtcyA9IHRoaXMuJHRvb2xiYXIuZmluZCgnLmtlZXAtb3BlbiBpbnB1dFt0eXBlPVwiY2hlY2tib3hcIl06bm90KFwiLnRvZ2dsZS1hbGxcIiknKS5wcm9wKCdkaXNhYmxlZCcsIGZhbHNlKTtcblxuICAgICAgICAgIGlmICh2aXNpYmxlKSB7XG4gICAgICAgICAgICAkaXRlbXMucHJvcCgnY2hlY2tlZCcsIHZpc2libGUpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAkaXRlbXMuZ2V0KCkucmV2ZXJzZSgpLmZvckVhY2goZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgICAgICAgaWYgKCRpdGVtcy5maWx0ZXIoJzpjaGVja2VkJykubGVuZ3RoID4gX3RoaXMyMy5vcHRpb25zLm1pbmltdW1Db3VudENvbHVtbnMpIHtcbiAgICAgICAgICAgICAgICAkX19kZWZhdWx0WydkZWZhdWx0J10oaXRlbSkucHJvcCgnY2hlY2tlZCcsIHZpc2libGUpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoJGl0ZW1zLmZpbHRlcignOmNoZWNrZWQnKS5sZW5ndGggPD0gdGhpcy5vcHRpb25zLm1pbmltdW1Db3VudENvbHVtbnMpIHtcbiAgICAgICAgICAgICRpdGVtcy5maWx0ZXIoJzpjaGVja2VkJykucHJvcCgnZGlzYWJsZWQnLCB0cnVlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwibWVyZ2VDZWxsc1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIG1lcmdlQ2VsbHMob3B0aW9ucykge1xuICAgICAgICB2YXIgcm93ID0gb3B0aW9ucy5pbmRleDtcbiAgICAgICAgdmFyIGNvbCA9IHRoaXMuZ2V0VmlzaWJsZUZpZWxkcygpLmluZGV4T2Yob3B0aW9ucy5maWVsZCk7XG4gICAgICAgIHZhciByb3dzcGFuID0gb3B0aW9ucy5yb3dzcGFuIHx8IDE7XG4gICAgICAgIHZhciBjb2xzcGFuID0gb3B0aW9ucy5jb2xzcGFuIHx8IDE7XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIgajtcbiAgICAgICAgdmFyICR0ciA9IHRoaXMuJGJvZHkuZmluZCgnPnRyJyk7XG4gICAgICAgIGNvbCArPSBVdGlscy5nZXREZXRhaWxWaWV3SW5kZXhPZmZzZXQodGhpcy5vcHRpb25zKTtcbiAgICAgICAgdmFyICR0ZCA9ICR0ci5lcShyb3cpLmZpbmQoJz50ZCcpLmVxKGNvbCk7XG5cbiAgICAgICAgaWYgKHJvdyA8IDAgfHwgY29sIDwgMCB8fCByb3cgPj0gdGhpcy5kYXRhLmxlbmd0aCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAoaSA9IHJvdzsgaSA8IHJvdyArIHJvd3NwYW47IGkrKykge1xuICAgICAgICAgIGZvciAoaiA9IGNvbDsgaiA8IGNvbCArIGNvbHNwYW47IGorKykge1xuICAgICAgICAgICAgJHRyLmVxKGkpLmZpbmQoJz50ZCcpLmVxKGopLmhpZGUoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAkdGQuYXR0cigncm93c3BhbicsIHJvd3NwYW4pLmF0dHIoJ2NvbHNwYW4nLCBjb2xzcGFuKS5zaG93KCk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImNoZWNrQWxsXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gY2hlY2tBbGwoKSB7XG4gICAgICAgIHRoaXMuX3RvZ2dsZUNoZWNrQWxsKHRydWUpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJ1bmNoZWNrQWxsXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdW5jaGVja0FsbCgpIHtcbiAgICAgICAgdGhpcy5fdG9nZ2xlQ2hlY2tBbGwoZmFsc2UpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJfdG9nZ2xlQ2hlY2tBbGxcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBfdG9nZ2xlQ2hlY2tBbGwoY2hlY2tlZCkge1xuICAgICAgICB2YXIgcm93c0JlZm9yZSA9IHRoaXMuZ2V0U2VsZWN0aW9ucygpO1xuICAgICAgICB0aGlzLiRzZWxlY3RBbGwuYWRkKHRoaXMuJHNlbGVjdEFsbF8pLnByb3AoJ2NoZWNrZWQnLCBjaGVja2VkKTtcbiAgICAgICAgdGhpcy4kc2VsZWN0SXRlbS5maWx0ZXIoJzplbmFibGVkJykucHJvcCgnY2hlY2tlZCcsIGNoZWNrZWQpO1xuICAgICAgICB0aGlzLnVwZGF0ZVJvd3MoKTtcbiAgICAgICAgdGhpcy51cGRhdGVTZWxlY3RlZCgpO1xuICAgICAgICB2YXIgcm93c0FmdGVyID0gdGhpcy5nZXRTZWxlY3Rpb25zKCk7XG5cbiAgICAgICAgaWYgKGNoZWNrZWQpIHtcbiAgICAgICAgICB0aGlzLnRyaWdnZXIoJ2NoZWNrLWFsbCcsIHJvd3NBZnRlciwgcm93c0JlZm9yZSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy50cmlnZ2VyKCd1bmNoZWNrLWFsbCcsIHJvd3NBZnRlciwgcm93c0JlZm9yZSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImNoZWNrSW52ZXJ0XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gY2hlY2tJbnZlcnQoKSB7XG4gICAgICAgIHZhciAkaXRlbXMgPSB0aGlzLiRzZWxlY3RJdGVtLmZpbHRlcignOmVuYWJsZWQnKTtcbiAgICAgICAgdmFyIGNoZWNrZWQgPSAkaXRlbXMuZmlsdGVyKCc6Y2hlY2tlZCcpO1xuICAgICAgICAkaXRlbXMuZWFjaChmdW5jdGlvbiAoaSwgZWwpIHtcbiAgICAgICAgICAkX19kZWZhdWx0WydkZWZhdWx0J10oZWwpLnByb3AoJ2NoZWNrZWQnLCAhJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKS5wcm9wKCdjaGVja2VkJykpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy51cGRhdGVSb3dzKCk7XG4gICAgICAgIHRoaXMudXBkYXRlU2VsZWN0ZWQoKTtcbiAgICAgICAgdGhpcy50cmlnZ2VyKCd1bmNoZWNrLXNvbWUnLCBjaGVja2VkKTtcbiAgICAgICAgY2hlY2tlZCA9IHRoaXMuZ2V0U2VsZWN0aW9ucygpO1xuICAgICAgICB0aGlzLnRyaWdnZXIoJ2NoZWNrLXNvbWUnLCBjaGVja2VkKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiY2hlY2tcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBjaGVjayhpbmRleCkge1xuICAgICAgICB0aGlzLl90b2dnbGVDaGVjayh0cnVlLCBpbmRleCk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInVuY2hlY2tcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiB1bmNoZWNrKGluZGV4KSB7XG4gICAgICAgIHRoaXMuX3RvZ2dsZUNoZWNrKGZhbHNlLCBpbmRleCk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcIl90b2dnbGVDaGVja1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIF90b2dnbGVDaGVjayhjaGVja2VkLCBpbmRleCkge1xuICAgICAgICB2YXIgJGVsID0gdGhpcy4kc2VsZWN0SXRlbS5maWx0ZXIoXCJbZGF0YS1pbmRleD1cXFwiXCIuY29uY2F0KGluZGV4LCBcIlxcXCJdXCIpKTtcbiAgICAgICAgdmFyIHJvdyA9IHRoaXMuZGF0YVtpbmRleF07XG5cbiAgICAgICAgaWYgKCRlbC5pcygnOnJhZGlvJykgfHwgdGhpcy5vcHRpb25zLnNpbmdsZVNlbGVjdCB8fCB0aGlzLm9wdGlvbnMubXVsdGlwbGVTZWxlY3RSb3cgJiYgIXRoaXMubXVsdGlwbGVTZWxlY3RSb3dDdHJsS2V5ICYmICF0aGlzLm11bHRpcGxlU2VsZWN0Um93U2hpZnRLZXkpIHtcbiAgICAgICAgICB2YXIgX2l0ZXJhdG9yMTAgPSBfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlcih0aGlzLm9wdGlvbnMuZGF0YSksXG4gICAgICAgICAgICAgIF9zdGVwMTA7XG5cbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgZm9yIChfaXRlcmF0b3IxMC5zKCk7ICEoX3N0ZXAxMCA9IF9pdGVyYXRvcjEwLm4oKSkuZG9uZTspIHtcbiAgICAgICAgICAgICAgdmFyIHIgPSBfc3RlcDEwLnZhbHVlO1xuICAgICAgICAgICAgICByW3RoaXMuaGVhZGVyLnN0YXRlRmllbGRdID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBfaXRlcmF0b3IxMC5lKGVycik7XG4gICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgIF9pdGVyYXRvcjEwLmYoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aGlzLiRzZWxlY3RJdGVtLmZpbHRlcignOmNoZWNrZWQnKS5ub3QoJGVsKS5wcm9wKCdjaGVja2VkJywgZmFsc2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgcm93W3RoaXMuaGVhZGVyLnN0YXRlRmllbGRdID0gY2hlY2tlZDtcblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLm11bHRpcGxlU2VsZWN0Um93KSB7XG4gICAgICAgICAgaWYgKHRoaXMubXVsdGlwbGVTZWxlY3RSb3dTaGlmdEtleSAmJiB0aGlzLm11bHRpcGxlU2VsZWN0Um93TGFzdFNlbGVjdGVkSW5kZXggPj0gMCkge1xuICAgICAgICAgICAgdmFyIF9yZWY4ID0gdGhpcy5tdWx0aXBsZVNlbGVjdFJvd0xhc3RTZWxlY3RlZEluZGV4IDwgaW5kZXggPyBbdGhpcy5tdWx0aXBsZVNlbGVjdFJvd0xhc3RTZWxlY3RlZEluZGV4LCBpbmRleF0gOiBbaW5kZXgsIHRoaXMubXVsdGlwbGVTZWxlY3RSb3dMYXN0U2VsZWN0ZWRJbmRleF0sXG4gICAgICAgICAgICAgICAgX3JlZjkgPSBfc2xpY2VkVG9BcnJheShfcmVmOCwgMiksXG4gICAgICAgICAgICAgICAgZnJvbUluZGV4ID0gX3JlZjlbMF0sXG4gICAgICAgICAgICAgICAgdG9JbmRleCA9IF9yZWY5WzFdO1xuXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gZnJvbUluZGV4ICsgMTsgaSA8IHRvSW5kZXg7IGkrKykge1xuICAgICAgICAgICAgICB0aGlzLmRhdGFbaV1bdGhpcy5oZWFkZXIuc3RhdGVGaWVsZF0gPSB0cnVlO1xuICAgICAgICAgICAgICB0aGlzLiRzZWxlY3RJdGVtLmZpbHRlcihcIltkYXRhLWluZGV4PVxcXCJcIi5jb25jYXQoaSwgXCJcXFwiXVwiKSkucHJvcCgnY2hlY2tlZCcsIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMubXVsdGlwbGVTZWxlY3RSb3dDdHJsS2V5ID0gZmFsc2U7XG4gICAgICAgICAgdGhpcy5tdWx0aXBsZVNlbGVjdFJvd1NoaWZ0S2V5ID0gZmFsc2U7XG4gICAgICAgICAgdGhpcy5tdWx0aXBsZVNlbGVjdFJvd0xhc3RTZWxlY3RlZEluZGV4ID0gY2hlY2tlZCA/IGluZGV4IDogLTE7XG4gICAgICAgIH1cblxuICAgICAgICAkZWwucHJvcCgnY2hlY2tlZCcsIGNoZWNrZWQpO1xuICAgICAgICB0aGlzLnVwZGF0ZVNlbGVjdGVkKCk7XG4gICAgICAgIHRoaXMudHJpZ2dlcihjaGVja2VkID8gJ2NoZWNrJyA6ICd1bmNoZWNrJywgdGhpcy5kYXRhW2luZGV4XSwgJGVsKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiY2hlY2tCeVwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGNoZWNrQnkob2JqKSB7XG4gICAgICAgIHRoaXMuX3RvZ2dsZUNoZWNrQnkodHJ1ZSwgb2JqKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwidW5jaGVja0J5XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdW5jaGVja0J5KG9iaikge1xuICAgICAgICB0aGlzLl90b2dnbGVDaGVja0J5KGZhbHNlLCBvYmopO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJfdG9nZ2xlQ2hlY2tCeVwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIF90b2dnbGVDaGVja0J5KGNoZWNrZWQsIG9iaikge1xuICAgICAgICB2YXIgX3RoaXMyNCA9IHRoaXM7XG5cbiAgICAgICAgaWYgKCFvYmouaGFzT3duUHJvcGVydHkoJ2ZpZWxkJykgfHwgIW9iai5oYXNPd25Qcm9wZXJ0eSgndmFsdWVzJykpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcm93cyA9IFtdO1xuICAgICAgICB0aGlzLmRhdGEuZm9yRWFjaChmdW5jdGlvbiAocm93LCBpKSB7XG4gICAgICAgICAgaWYgKCFyb3cuaGFzT3duUHJvcGVydHkob2JqLmZpZWxkKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChvYmoudmFsdWVzLmluY2x1ZGVzKHJvd1tvYmouZmllbGRdKSkge1xuICAgICAgICAgICAgdmFyICRlbCA9IF90aGlzMjQuJHNlbGVjdEl0ZW0uZmlsdGVyKCc6ZW5hYmxlZCcpLmZpbHRlcihVdGlscy5zcHJpbnRmKCdbZGF0YS1pbmRleD1cIiVzXCJdJywgaSkpO1xuXG4gICAgICAgICAgICAkZWwgPSBjaGVja2VkID8gJGVsLm5vdCgnOmNoZWNrZWQnKSA6ICRlbC5maWx0ZXIoJzpjaGVja2VkJyk7XG5cbiAgICAgICAgICAgIGlmICghJGVsLmxlbmd0aCkge1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICRlbC5wcm9wKCdjaGVja2VkJywgY2hlY2tlZCk7XG4gICAgICAgICAgICByb3dbX3RoaXMyNC5oZWFkZXIuc3RhdGVGaWVsZF0gPSBjaGVja2VkO1xuICAgICAgICAgICAgcm93cy5wdXNoKHJvdyk7XG5cbiAgICAgICAgICAgIF90aGlzMjQudHJpZ2dlcihjaGVja2VkID8gJ2NoZWNrJyA6ICd1bmNoZWNrJywgcm93LCAkZWwpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMudXBkYXRlU2VsZWN0ZWQoKTtcbiAgICAgICAgdGhpcy50cmlnZ2VyKGNoZWNrZWQgPyAnY2hlY2stc29tZScgOiAndW5jaGVjay1zb21lJywgcm93cyk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInJlZnJlc2hcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiByZWZyZXNoKHBhcmFtcykge1xuICAgICAgICBpZiAocGFyYW1zICYmIHBhcmFtcy51cmwpIHtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMudXJsID0gcGFyYW1zLnVybDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwYXJhbXMgJiYgcGFyYW1zLnBhZ2VOdW1iZXIpIHtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMucGFnZU51bWJlciA9IHBhcmFtcy5wYWdlTnVtYmVyO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcmFtcyAmJiBwYXJhbXMucGFnZVNpemUpIHtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMucGFnZVNpemUgPSBwYXJhbXMucGFnZVNpemU7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnRyaWdnZXIoJ3JlZnJlc2gnLCB0aGlzLmluaXRTZXJ2ZXIocGFyYW1zICYmIHBhcmFtcy5zaWxlbnQsIHBhcmFtcyAmJiBwYXJhbXMucXVlcnksIHBhcmFtcyAmJiBwYXJhbXMudXJsKSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImRlc3Ryb3lcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBkZXN0cm95KCkge1xuICAgICAgICB0aGlzLiRlbC5pbnNlcnRCZWZvcmUodGhpcy4kY29udGFpbmVyKTtcbiAgICAgICAgJF9fZGVmYXVsdFsnZGVmYXVsdCddKHRoaXMub3B0aW9ucy50b29sYmFyKS5pbnNlcnRCZWZvcmUodGhpcy4kZWwpO1xuICAgICAgICB0aGlzLiRjb250YWluZXIubmV4dCgpLnJlbW92ZSgpO1xuICAgICAgICB0aGlzLiRjb250YWluZXIucmVtb3ZlKCk7XG4gICAgICAgIHRoaXMuJGVsLmh0bWwodGhpcy4kZWxfLmh0bWwoKSkuY3NzKCdtYXJnaW4tdG9wJywgJzAnKS5hdHRyKCdjbGFzcycsIHRoaXMuJGVsXy5hdHRyKCdjbGFzcycpIHx8ICcnKTsgLy8gcmVzZXQgdGhlIGNsYXNzXG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInJlc2V0Vmlld1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHJlc2V0VmlldyhwYXJhbXMpIHtcbiAgICAgICAgdmFyIHBhZGRpbmcgPSAwO1xuXG4gICAgICAgIGlmIChwYXJhbXMgJiYgcGFyYW1zLmhlaWdodCkge1xuICAgICAgICAgIHRoaXMub3B0aW9ucy5oZWlnaHQgPSBwYXJhbXMuaGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy4kc2VsZWN0QWxsLnByb3AoJ2NoZWNrZWQnLCB0aGlzLiRzZWxlY3RJdGVtLmxlbmd0aCA+IDAgJiYgdGhpcy4kc2VsZWN0SXRlbS5sZW5ndGggPT09IHRoaXMuJHNlbGVjdEl0ZW0uZmlsdGVyKCc6Y2hlY2tlZCcpLmxlbmd0aCk7XG4gICAgICAgIHRoaXMuJHRhYmxlQ29udGFpbmVyLnRvZ2dsZUNsYXNzKCdoYXMtY2FyZC12aWV3JywgdGhpcy5vcHRpb25zLmNhcmRWaWV3KTtcblxuICAgICAgICBpZiAoIXRoaXMub3B0aW9ucy5jYXJkVmlldyAmJiB0aGlzLm9wdGlvbnMuc2hvd0hlYWRlciAmJiB0aGlzLm9wdGlvbnMuaGVpZ2h0KSB7XG4gICAgICAgICAgdGhpcy4kdGFibGVIZWFkZXIuc2hvdygpO1xuICAgICAgICAgIHRoaXMucmVzZXRIZWFkZXIoKTtcbiAgICAgICAgICBwYWRkaW5nICs9IHRoaXMuJGhlYWRlci5vdXRlckhlaWdodCh0cnVlKSArIDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy4kdGFibGVIZWFkZXIuaGlkZSgpO1xuICAgICAgICAgIHRoaXMudHJpZ2dlcigncG9zdC1oZWFkZXInKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5vcHRpb25zLmNhcmRWaWV3ICYmIHRoaXMub3B0aW9ucy5zaG93Rm9vdGVyKSB7XG4gICAgICAgICAgdGhpcy4kdGFibGVGb290ZXIuc2hvdygpO1xuICAgICAgICAgIHRoaXMuZml0Rm9vdGVyKCk7XG5cbiAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLmhlaWdodCkge1xuICAgICAgICAgICAgcGFkZGluZyArPSB0aGlzLiR0YWJsZUZvb3Rlci5vdXRlckhlaWdodCh0cnVlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy4kY29udGFpbmVyLmhhc0NsYXNzKCdmdWxsc2NyZWVuJykpIHtcbiAgICAgICAgICB0aGlzLiR0YWJsZUNvbnRhaW5lci5jc3MoJ2hlaWdodCcsICcnKTtcbiAgICAgICAgICB0aGlzLiR0YWJsZUNvbnRhaW5lci5jc3MoJ3dpZHRoJywgJycpO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMub3B0aW9ucy5oZWlnaHQpIHtcbiAgICAgICAgICBpZiAodGhpcy4kdGFibGVCb3JkZXIpIHtcbiAgICAgICAgICAgIHRoaXMuJHRhYmxlQm9yZGVyLmNzcygnd2lkdGgnLCAnJyk7XG4gICAgICAgICAgICB0aGlzLiR0YWJsZUJvcmRlci5jc3MoJ2hlaWdodCcsICcnKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgdG9vbGJhckhlaWdodCA9IHRoaXMuJHRvb2xiYXIub3V0ZXJIZWlnaHQodHJ1ZSk7XG4gICAgICAgICAgdmFyIHBhZ2luYXRpb25IZWlnaHQgPSB0aGlzLiRwYWdpbmF0aW9uLm91dGVySGVpZ2h0KHRydWUpO1xuICAgICAgICAgIHZhciBoZWlnaHQgPSB0aGlzLm9wdGlvbnMuaGVpZ2h0IC0gdG9vbGJhckhlaWdodCAtIHBhZ2luYXRpb25IZWlnaHQ7XG4gICAgICAgICAgdmFyICRib2R5VGFibGUgPSB0aGlzLiR0YWJsZUJvZHkuZmluZCgnPnRhYmxlJyk7XG4gICAgICAgICAgdmFyIHRhYmxlSGVpZ2h0ID0gJGJvZHlUYWJsZS5vdXRlckhlaWdodCgpO1xuICAgICAgICAgIHRoaXMuJHRhYmxlQ29udGFpbmVyLmNzcygnaGVpZ2h0JywgXCJcIi5jb25jYXQoaGVpZ2h0LCBcInB4XCIpKTtcblxuICAgICAgICAgIGlmICh0aGlzLiR0YWJsZUJvcmRlciAmJiAkYm9keVRhYmxlLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICB2YXIgdGFibGVCb3JkZXJIZWlnaHQgPSBoZWlnaHQgLSB0YWJsZUhlaWdodCAtIDI7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLiR0YWJsZUJvZHlbMF0uc2Nyb2xsV2lkdGggLSB0aGlzLiR0YWJsZUJvZHkuaW5uZXJXaWR0aCgpKSB7XG4gICAgICAgICAgICAgIHRhYmxlQm9yZGVySGVpZ2h0IC09IFV0aWxzLmdldFNjcm9sbEJhcldpZHRoKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuJHRhYmxlQm9yZGVyLmNzcygnd2lkdGgnLCBcIlwiLmNvbmNhdCgkYm9keVRhYmxlLm91dGVyV2lkdGgoKSwgXCJweFwiKSk7XG4gICAgICAgICAgICB0aGlzLiR0YWJsZUJvcmRlci5jc3MoJ2hlaWdodCcsIFwiXCIuY29uY2F0KHRhYmxlQm9yZGVySGVpZ2h0LCBcInB4XCIpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLmNhcmRWaWV3KSB7XG4gICAgICAgICAgLy8gcmVtb3ZlIHRoZSBlbGVtZW50IGNzc1xuICAgICAgICAgIHRoaXMuJGVsLmNzcygnbWFyZ2luLXRvcCcsICcwJyk7XG4gICAgICAgICAgdGhpcy4kdGFibGVDb250YWluZXIuY3NzKCdwYWRkaW5nLWJvdHRvbScsICcwJyk7XG4gICAgICAgICAgdGhpcy4kdGFibGVGb290ZXIuaGlkZSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIEFzc2lnbiB0aGUgY29ycmVjdCBzb3J0YWJsZSBhcnJvd1xuICAgICAgICAgIHRoaXMuZ2V0Q2FyZXQoKTtcbiAgICAgICAgICB0aGlzLiR0YWJsZUNvbnRhaW5lci5jc3MoJ3BhZGRpbmctYm90dG9tJywgXCJcIi5jb25jYXQocGFkZGluZywgXCJweFwiKSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnRyaWdnZXIoJ3Jlc2V0LXZpZXcnKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwic2hvd0xvYWRpbmdcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBzaG93TG9hZGluZygpIHtcbiAgICAgICAgdGhpcy4kdGFibGVMb2FkaW5nLnRvZ2dsZUNsYXNzKCdvcGVuJywgdHJ1ZSk7XG4gICAgICAgIHZhciBmb250U2l6ZSA9IHRoaXMub3B0aW9ucy5sb2FkaW5nRm9udFNpemU7XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5sb2FkaW5nRm9udFNpemUgPT09ICdhdXRvJykge1xuICAgICAgICAgIGZvbnRTaXplID0gdGhpcy4kdGFibGVMb2FkaW5nLndpZHRoKCkgKiAwLjA0O1xuICAgICAgICAgIGZvbnRTaXplID0gTWF0aC5tYXgoMTIsIGZvbnRTaXplKTtcbiAgICAgICAgICBmb250U2l6ZSA9IE1hdGgubWluKDMyLCBmb250U2l6ZSk7XG4gICAgICAgICAgZm9udFNpemUgPSBcIlwiLmNvbmNhdChmb250U2l6ZSwgXCJweFwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuJHRhYmxlTG9hZGluZy5maW5kKCcubG9hZGluZy10ZXh0JykuY3NzKCdmb250LXNpemUnLCBmb250U2l6ZSk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImhpZGVMb2FkaW5nXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaGlkZUxvYWRpbmcoKSB7XG4gICAgICAgIHRoaXMuJHRhYmxlTG9hZGluZy50b2dnbGVDbGFzcygnb3BlbicsIGZhbHNlKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwidG9nZ2xlUGFnaW5hdGlvblwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHRvZ2dsZVBhZ2luYXRpb24oKSB7XG4gICAgICAgIHRoaXMub3B0aW9ucy5wYWdpbmF0aW9uID0gIXRoaXMub3B0aW9ucy5wYWdpbmF0aW9uO1xuICAgICAgICB2YXIgaWNvbiA9IHRoaXMub3B0aW9ucy5zaG93QnV0dG9uSWNvbnMgPyB0aGlzLm9wdGlvbnMucGFnaW5hdGlvbiA/IHRoaXMub3B0aW9ucy5pY29ucy5wYWdpbmF0aW9uU3dpdGNoRG93biA6IHRoaXMub3B0aW9ucy5pY29ucy5wYWdpbmF0aW9uU3dpdGNoVXAgOiAnJztcbiAgICAgICAgdmFyIHRleHQgPSB0aGlzLm9wdGlvbnMuc2hvd0J1dHRvblRleHQgPyB0aGlzLm9wdGlvbnMucGFnaW5hdGlvbiA/IHRoaXMub3B0aW9ucy5mb3JtYXRQYWdpbmF0aW9uU3dpdGNoVXAoKSA6IHRoaXMub3B0aW9ucy5mb3JtYXRQYWdpbmF0aW9uU3dpdGNoRG93bigpIDogJyc7XG4gICAgICAgIHRoaXMuJHRvb2xiYXIuZmluZCgnYnV0dG9uW25hbWU9XCJwYWdpbmF0aW9uU3dpdGNoXCJdJykuaHRtbChcIlwiLmNvbmNhdChVdGlscy5zcHJpbnRmKHRoaXMuY29uc3RhbnRzLmh0bWwuaWNvbiwgdGhpcy5vcHRpb25zLmljb25zUHJlZml4LCBpY29uKSwgXCIgXCIpLmNvbmNhdCh0ZXh0KSk7XG4gICAgICAgIHRoaXMudXBkYXRlUGFnaW5hdGlvbigpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJ0b2dnbGVGdWxsc2NyZWVuXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdG9nZ2xlRnVsbHNjcmVlbigpIHtcbiAgICAgICAgdGhpcy4kZWwuY2xvc2VzdCgnLmJvb3RzdHJhcC10YWJsZScpLnRvZ2dsZUNsYXNzKCdmdWxsc2NyZWVuJyk7XG4gICAgICAgIHRoaXMucmVzZXRWaWV3KCk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInRvZ2dsZVZpZXdcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiB0b2dnbGVWaWV3KCkge1xuICAgICAgICB0aGlzLm9wdGlvbnMuY2FyZFZpZXcgPSAhdGhpcy5vcHRpb25zLmNhcmRWaWV3O1xuICAgICAgICB0aGlzLmluaXRIZWFkZXIoKTtcbiAgICAgICAgdmFyIGljb24gPSB0aGlzLm9wdGlvbnMuc2hvd0J1dHRvbkljb25zID8gdGhpcy5vcHRpb25zLmNhcmRWaWV3ID8gdGhpcy5vcHRpb25zLmljb25zLnRvZ2dsZU9uIDogdGhpcy5vcHRpb25zLmljb25zLnRvZ2dsZU9mZiA6ICcnO1xuICAgICAgICB2YXIgdGV4dCA9IHRoaXMub3B0aW9ucy5zaG93QnV0dG9uVGV4dCA/IHRoaXMub3B0aW9ucy5jYXJkVmlldyA/IHRoaXMub3B0aW9ucy5mb3JtYXRUb2dnbGVPZmYoKSA6IHRoaXMub3B0aW9ucy5mb3JtYXRUb2dnbGVPbigpIDogJyc7XG4gICAgICAgIHRoaXMuJHRvb2xiYXIuZmluZCgnYnV0dG9uW25hbWU9XCJ0b2dnbGVcIl0nKS5odG1sKFwiXCIuY29uY2F0KFV0aWxzLnNwcmludGYodGhpcy5jb25zdGFudHMuaHRtbC5pY29uLCB0aGlzLm9wdGlvbnMuaWNvbnNQcmVmaXgsIGljb24pLCBcIiBcIikuY29uY2F0KHRleHQpKTtcbiAgICAgICAgdGhpcy5pbml0Qm9keSgpO1xuICAgICAgICB0aGlzLnRyaWdnZXIoJ3RvZ2dsZScsIHRoaXMub3B0aW9ucy5jYXJkVmlldyk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInJlc2V0U2VhcmNoXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gcmVzZXRTZWFyY2godGV4dCkge1xuICAgICAgICB2YXIgJHNlYXJjaCA9IFV0aWxzLmdldFNlYXJjaElucHV0KHRoaXMpO1xuICAgICAgICAkc2VhcmNoLnZhbCh0ZXh0IHx8ICcnKTtcbiAgICAgICAgdGhpcy5vblNlYXJjaCh7XG4gICAgICAgICAgY3VycmVudFRhcmdldDogJHNlYXJjaFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiZmlsdGVyQnlcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBmaWx0ZXJCeShjb2x1bW5zLCBvcHRpb25zKSB7XG4gICAgICAgIHRoaXMuZmlsdGVyT3B0aW9ucyA9IFV0aWxzLmlzRW1wdHlPYmplY3Qob3B0aW9ucykgPyB0aGlzLm9wdGlvbnMuZmlsdGVyT3B0aW9ucyA6ICRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5leHRlbmQodGhpcy5vcHRpb25zLmZpbHRlck9wdGlvbnMsIG9wdGlvbnMpO1xuICAgICAgICB0aGlzLmZpbHRlckNvbHVtbnMgPSBVdGlscy5pc0VtcHR5T2JqZWN0KGNvbHVtbnMpID8ge30gOiBjb2x1bW5zO1xuICAgICAgICB0aGlzLm9wdGlvbnMucGFnZU51bWJlciA9IDE7XG4gICAgICAgIHRoaXMuaW5pdFNlYXJjaCgpO1xuICAgICAgICB0aGlzLnVwZGF0ZVBhZ2luYXRpb24oKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwic2Nyb2xsVG9cIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBzY3JvbGxUbyhwYXJhbXMpIHtcbiAgICAgICAgdmFyIG9wdGlvbnMgPSB7XG4gICAgICAgICAgdW5pdDogJ3B4JyxcbiAgICAgICAgICB2YWx1ZTogMFxuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChfdHlwZW9mKHBhcmFtcykgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24ob3B0aW9ucywgcGFyYW1zKTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgcGFyYW1zID09PSAnc3RyaW5nJyAmJiBwYXJhbXMgPT09ICdib3R0b20nKSB7XG4gICAgICAgICAgb3B0aW9ucy52YWx1ZSA9IHRoaXMuJHRhYmxlQm9keVswXS5zY3JvbGxIZWlnaHQ7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHBhcmFtcyA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIHBhcmFtcyA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICBvcHRpb25zLnZhbHVlID0gcGFyYW1zO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHNjcm9sbFRvID0gb3B0aW9ucy52YWx1ZTtcblxuICAgICAgICBpZiAob3B0aW9ucy51bml0ID09PSAncm93cycpIHtcbiAgICAgICAgICBzY3JvbGxUbyA9IDA7XG4gICAgICAgICAgdGhpcy4kYm9keS5maW5kKFwiPiB0cjpsdChcIi5jb25jYXQob3B0aW9ucy52YWx1ZSwgXCIpXCIpKS5lYWNoKGZ1bmN0aW9uIChpLCBlbCkge1xuICAgICAgICAgICAgc2Nyb2xsVG8gKz0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKS5vdXRlckhlaWdodCh0cnVlKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuJHRhYmxlQm9keS5zY3JvbGxUb3Aoc2Nyb2xsVG8pO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJnZXRTY3JvbGxQb3NpdGlvblwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGdldFNjcm9sbFBvc2l0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy4kdGFibGVCb2R5LnNjcm9sbFRvcCgpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJzZWxlY3RQYWdlXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gc2VsZWN0UGFnZShwYWdlKSB7XG4gICAgICAgIGlmIChwYWdlID4gMCAmJiBwYWdlIDw9IHRoaXMub3B0aW9ucy50b3RhbFBhZ2VzKSB7XG4gICAgICAgICAgdGhpcy5vcHRpb25zLnBhZ2VOdW1iZXIgPSBwYWdlO1xuICAgICAgICAgIHRoaXMudXBkYXRlUGFnaW5hdGlvbigpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInByZXZQYWdlXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gcHJldlBhZ2UoKSB7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMucGFnZU51bWJlciA+IDEpIHtcbiAgICAgICAgICB0aGlzLm9wdGlvbnMucGFnZU51bWJlci0tO1xuICAgICAgICAgIHRoaXMudXBkYXRlUGFnaW5hdGlvbigpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcIm5leHRQYWdlXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gbmV4dFBhZ2UoKSB7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMucGFnZU51bWJlciA8IHRoaXMub3B0aW9ucy50b3RhbFBhZ2VzKSB7XG4gICAgICAgICAgdGhpcy5vcHRpb25zLnBhZ2VOdW1iZXIrKztcbiAgICAgICAgICB0aGlzLnVwZGF0ZVBhZ2luYXRpb24oKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJ0b2dnbGVEZXRhaWxWaWV3XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdG9nZ2xlRGV0YWlsVmlldyhpbmRleCwgX2NvbHVtbkRldGFpbEZvcm1hdHRlcikge1xuICAgICAgICB2YXIgJHRyID0gdGhpcy4kYm9keS5maW5kKFV0aWxzLnNwcmludGYoJz4gdHJbZGF0YS1pbmRleD1cIiVzXCJdJywgaW5kZXgpKTtcblxuICAgICAgICBpZiAoJHRyLm5leHQoKS5pcygndHIuZGV0YWlsLXZpZXcnKSkge1xuICAgICAgICAgIHRoaXMuY29sbGFwc2VSb3coaW5kZXgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuZXhwYW5kUm93KGluZGV4LCBfY29sdW1uRGV0YWlsRm9ybWF0dGVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucmVzZXRWaWV3KCk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImV4cGFuZFJvd1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGV4cGFuZFJvdyhpbmRleCwgX2NvbHVtbkRldGFpbEZvcm1hdHRlcikge1xuICAgICAgICB2YXIgcm93ID0gdGhpcy5kYXRhW2luZGV4XTtcbiAgICAgICAgdmFyICR0ciA9IHRoaXMuJGJvZHkuZmluZChVdGlscy5zcHJpbnRmKCc+IHRyW2RhdGEtaW5kZXg9XCIlc1wiXVtkYXRhLWhhcy1kZXRhaWwtdmlld10nLCBpbmRleCkpO1xuXG4gICAgICAgIGlmICgkdHIubmV4dCgpLmlzKCd0ci5kZXRhaWwtdmlldycpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5kZXRhaWxWaWV3SWNvbikge1xuICAgICAgICAgICR0ci5maW5kKCdhLmRldGFpbC1pY29uJykuaHRtbChVdGlscy5zcHJpbnRmKHRoaXMuY29uc3RhbnRzLmh0bWwuaWNvbiwgdGhpcy5vcHRpb25zLmljb25zUHJlZml4LCB0aGlzLm9wdGlvbnMuaWNvbnMuZGV0YWlsQ2xvc2UpKTtcbiAgICAgICAgfVxuXG4gICAgICAgICR0ci5hZnRlcihVdGlscy5zcHJpbnRmKCc8dHIgY2xhc3M9XCJkZXRhaWwtdmlld1wiPjx0ZCBjb2xzcGFuPVwiJXNcIj48L3RkPjwvdHI+JywgJHRyLmNoaWxkcmVuKCd0ZCcpLmxlbmd0aCkpO1xuICAgICAgICB2YXIgJGVsZW1lbnQgPSAkdHIubmV4dCgpLmZpbmQoJ3RkJyk7XG4gICAgICAgIHZhciBkZXRhaWxGb3JtYXR0ZXIgPSBfY29sdW1uRGV0YWlsRm9ybWF0dGVyIHx8IHRoaXMub3B0aW9ucy5kZXRhaWxGb3JtYXR0ZXI7XG4gICAgICAgIHZhciBjb250ZW50ID0gVXRpbHMuY2FsY3VsYXRlT2JqZWN0VmFsdWUodGhpcy5vcHRpb25zLCBkZXRhaWxGb3JtYXR0ZXIsIFtpbmRleCwgcm93LCAkZWxlbWVudF0sICcnKTtcblxuICAgICAgICBpZiAoJGVsZW1lbnQubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgJGVsZW1lbnQuYXBwZW5kKGNvbnRlbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy50cmlnZ2VyKCdleHBhbmQtcm93JywgaW5kZXgsIHJvdywgJGVsZW1lbnQpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJleHBhbmRSb3dCeVVuaXF1ZUlkXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gZXhwYW5kUm93QnlVbmlxdWVJZCh1bmlxdWVJZCkge1xuICAgICAgICB2YXIgcm93ID0gdGhpcy5nZXRSb3dCeVVuaXF1ZUlkKHVuaXF1ZUlkKTtcblxuICAgICAgICBpZiAoIXJvdykge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZXhwYW5kUm93KHRoaXMuZGF0YS5pbmRleE9mKHJvdykpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJjb2xsYXBzZVJvd1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGNvbGxhcHNlUm93KGluZGV4KSB7XG4gICAgICAgIHZhciByb3cgPSB0aGlzLmRhdGFbaW5kZXhdO1xuICAgICAgICB2YXIgJHRyID0gdGhpcy4kYm9keS5maW5kKFV0aWxzLnNwcmludGYoJz4gdHJbZGF0YS1pbmRleD1cIiVzXCJdW2RhdGEtaGFzLWRldGFpbC12aWV3XScsIGluZGV4KSk7XG5cbiAgICAgICAgaWYgKCEkdHIubmV4dCgpLmlzKCd0ci5kZXRhaWwtdmlldycpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5kZXRhaWxWaWV3SWNvbikge1xuICAgICAgICAgICR0ci5maW5kKCdhLmRldGFpbC1pY29uJykuaHRtbChVdGlscy5zcHJpbnRmKHRoaXMuY29uc3RhbnRzLmh0bWwuaWNvbiwgdGhpcy5vcHRpb25zLmljb25zUHJlZml4LCB0aGlzLm9wdGlvbnMuaWNvbnMuZGV0YWlsT3BlbikpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy50cmlnZ2VyKCdjb2xsYXBzZS1yb3cnLCBpbmRleCwgcm93LCAkdHIubmV4dCgpKTtcbiAgICAgICAgJHRyLm5leHQoKS5yZW1vdmUoKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiY29sbGFwc2VSb3dCeVVuaXF1ZUlkXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gY29sbGFwc2VSb3dCeVVuaXF1ZUlkKHVuaXF1ZUlkKSB7XG4gICAgICAgIHZhciByb3cgPSB0aGlzLmdldFJvd0J5VW5pcXVlSWQodW5pcXVlSWQpO1xuXG4gICAgICAgIGlmICghcm93KSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5jb2xsYXBzZVJvdyh0aGlzLmRhdGEuaW5kZXhPZihyb3cpKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiZXhwYW5kQWxsUm93c1wiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGV4cGFuZEFsbFJvd3MoKSB7XG4gICAgICAgIHZhciB0cnMgPSB0aGlzLiRib2R5LmZpbmQoJz4gdHJbZGF0YS1pbmRleF1bZGF0YS1oYXMtZGV0YWlsLXZpZXddJyk7XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0cnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICB0aGlzLmV4cGFuZFJvdygkX19kZWZhdWx0WydkZWZhdWx0J10odHJzW2ldKS5kYXRhKCdpbmRleCcpKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJjb2xsYXBzZUFsbFJvd3NcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBjb2xsYXBzZUFsbFJvd3MoKSB7XG4gICAgICAgIHZhciB0cnMgPSB0aGlzLiRib2R5LmZpbmQoJz4gdHJbZGF0YS1pbmRleF1bZGF0YS1oYXMtZGV0YWlsLXZpZXddJyk7XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0cnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICB0aGlzLmNvbGxhcHNlUm93KCRfX2RlZmF1bHRbJ2RlZmF1bHQnXSh0cnNbaV0pLmRhdGEoJ2luZGV4JykpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInVwZGF0ZUNvbHVtblRpdGxlXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdXBkYXRlQ29sdW1uVGl0bGUocGFyYW1zKSB7XG4gICAgICAgIGlmICghcGFyYW1zLmhhc093blByb3BlcnR5KCdmaWVsZCcpIHx8ICFwYXJhbXMuaGFzT3duUHJvcGVydHkoJ3RpdGxlJykpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmNvbHVtbnNbdGhpcy5maWVsZHNDb2x1bW5zSW5kZXhbcGFyYW1zLmZpZWxkXV0udGl0bGUgPSB0aGlzLm9wdGlvbnMuZXNjYXBlID8gVXRpbHMuZXNjYXBlSFRNTChwYXJhbXMudGl0bGUpIDogcGFyYW1zLnRpdGxlO1xuXG4gICAgICAgIGlmICh0aGlzLmNvbHVtbnNbdGhpcy5maWVsZHNDb2x1bW5zSW5kZXhbcGFyYW1zLmZpZWxkXV0udmlzaWJsZSkge1xuICAgICAgICAgIHRoaXMuJGhlYWRlci5maW5kKCd0aFtkYXRhLWZpZWxkXScpLmVhY2goZnVuY3Rpb24gKGksIGVsKSB7XG4gICAgICAgICAgICBpZiAoJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKS5kYXRhKCdmaWVsZCcpID09PSBwYXJhbXMuZmllbGQpIHtcbiAgICAgICAgICAgICAgJF9fZGVmYXVsdFsnZGVmYXVsdCddKCRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlbCkuZmluZCgnLnRoLWlubmVyJylbMF0pLnRleHQocGFyYW1zLnRpdGxlKTtcbiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHRoaXMucmVzZXRWaWV3KCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwidXBkYXRlRm9ybWF0VGV4dFwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHVwZGF0ZUZvcm1hdFRleHQoZm9ybWF0TmFtZSwgdGV4dCkge1xuICAgICAgICBpZiAoIS9eZm9ybWF0Ly50ZXN0KGZvcm1hdE5hbWUpIHx8ICF0aGlzLm9wdGlvbnNbZm9ybWF0TmFtZV0pIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIHRleHQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgdGhpcy5vcHRpb25zW2Zvcm1hdE5hbWVdID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRleHQ7XG4gICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGV4dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgIHRoaXMub3B0aW9uc1tmb3JtYXROYW1lXSA9IHRleHQ7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmluaXRUb29sYmFyKCk7XG4gICAgICAgIHRoaXMuaW5pdFBhZ2luYXRpb24oKTtcbiAgICAgICAgdGhpcy5pbml0Qm9keSgpO1xuICAgICAgfVxuICAgIH1dKTtcblxuICAgIHJldHVybiBCb290c3RyYXBUYWJsZTtcbiAgfSgpO1xuXG4gIEJvb3RzdHJhcFRhYmxlLlZFUlNJT04gPSBDb25zdGFudHMuVkVSU0lPTjtcbiAgQm9vdHN0cmFwVGFibGUuREVGQVVMVFMgPSBDb25zdGFudHMuREVGQVVMVFM7XG4gIEJvb3RzdHJhcFRhYmxlLkxPQ0FMRVMgPSBDb25zdGFudHMuTE9DQUxFUztcbiAgQm9vdHN0cmFwVGFibGUuQ09MVU1OX0RFRkFVTFRTID0gQ29uc3RhbnRzLkNPTFVNTl9ERUZBVUxUUztcbiAgQm9vdHN0cmFwVGFibGUuTUVUSE9EUyA9IENvbnN0YW50cy5NRVRIT0RTO1xuICBCb290c3RyYXBUYWJsZS5FVkVOVFMgPSBDb25zdGFudHMuRVZFTlRTOyAvLyBCT09UU1RSQVAgVEFCTEUgUExVR0lOIERFRklOSVRJT05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT1cblxuICAkX19kZWZhdWx0WydkZWZhdWx0J10uQm9vdHN0cmFwVGFibGUgPSBCb290c3RyYXBUYWJsZTtcblxuICAkX19kZWZhdWx0WydkZWZhdWx0J10uZm4uYm9vdHN0cmFwVGFibGUgPSBmdW5jdGlvbiAob3B0aW9uKSB7XG4gICAgZm9yICh2YXIgX2xlbjIgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4yID4gMSA/IF9sZW4yIC0gMSA6IDApLCBfa2V5NSA9IDE7IF9rZXk1IDwgX2xlbjI7IF9rZXk1KyspIHtcbiAgICAgIGFyZ3NbX2tleTUgLSAxXSA9IGFyZ3VtZW50c1tfa2V5NV07XG4gICAgfVxuXG4gICAgdmFyIHZhbHVlO1xuICAgIHRoaXMuZWFjaChmdW5jdGlvbiAoaSwgZWwpIHtcbiAgICAgIHZhciBkYXRhID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKS5kYXRhKCdib290c3RyYXAudGFibGUnKTtcbiAgICAgIHZhciBvcHRpb25zID0gJF9fZGVmYXVsdFsnZGVmYXVsdCddLmV4dGVuZCh7fSwgQm9vdHN0cmFwVGFibGUuREVGQVVMVFMsICRfX2RlZmF1bHRbJ2RlZmF1bHQnXShlbCkuZGF0YSgpLCBfdHlwZW9mKG9wdGlvbikgPT09ICdvYmplY3QnICYmIG9wdGlvbik7XG5cbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9uID09PSAnc3RyaW5nJykge1xuICAgICAgICB2YXIgX2RhdGEyO1xuXG4gICAgICAgIGlmICghQ29uc3RhbnRzLk1FVEhPRFMuaW5jbHVkZXMob3B0aW9uKSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVua25vd24gbWV0aG9kOiBcIi5jb25jYXQob3B0aW9uKSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YWx1ZSA9IChfZGF0YTIgPSBkYXRhKVtvcHRpb25dLmFwcGx5KF9kYXRhMiwgYXJncyk7XG5cbiAgICAgICAgaWYgKG9wdGlvbiA9PT0gJ2Rlc3Ryb3knKSB7XG4gICAgICAgICAgJF9fZGVmYXVsdFsnZGVmYXVsdCddKGVsKS5yZW1vdmVEYXRhKCdib290c3RyYXAudGFibGUnKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgZGF0YSA9IG5ldyAkX19kZWZhdWx0WydkZWZhdWx0J10uQm9vdHN0cmFwVGFibGUoZWwsIG9wdGlvbnMpO1xuICAgICAgICAkX19kZWZhdWx0WydkZWZhdWx0J10oZWwpLmRhdGEoJ2Jvb3RzdHJhcC50YWJsZScsIGRhdGEpO1xuICAgICAgICBkYXRhLmluaXQoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJyA/IHRoaXMgOiB2YWx1ZTtcbiAgfTtcblxuICAkX19kZWZhdWx0WydkZWZhdWx0J10uZm4uYm9vdHN0cmFwVGFibGUuQ29uc3RydWN0b3IgPSBCb290c3RyYXBUYWJsZTtcbiAgJF9fZGVmYXVsdFsnZGVmYXVsdCddLmZuLmJvb3RzdHJhcFRhYmxlLnRoZW1lID0gQ29uc3RhbnRzLlRIRU1FO1xuICAkX19kZWZhdWx0WydkZWZhdWx0J10uZm4uYm9vdHN0cmFwVGFibGUuVkVSU0lPTiA9IENvbnN0YW50cy5WRVJTSU9OO1xuICAkX19kZWZhdWx0WydkZWZhdWx0J10uZm4uYm9vdHN0cmFwVGFibGUuZGVmYXVsdHMgPSBCb290c3RyYXBUYWJsZS5ERUZBVUxUUztcbiAgJF9fZGVmYXVsdFsnZGVmYXVsdCddLmZuLmJvb3RzdHJhcFRhYmxlLmNvbHVtbkRlZmF1bHRzID0gQm9vdHN0cmFwVGFibGUuQ09MVU1OX0RFRkFVTFRTO1xuICAkX19kZWZhdWx0WydkZWZhdWx0J10uZm4uYm9vdHN0cmFwVGFibGUuZXZlbnRzID0gQm9vdHN0cmFwVGFibGUuRVZFTlRTO1xuICAkX19kZWZhdWx0WydkZWZhdWx0J10uZm4uYm9vdHN0cmFwVGFibGUubG9jYWxlcyA9IEJvb3RzdHJhcFRhYmxlLkxPQ0FMRVM7XG4gICRfX2RlZmF1bHRbJ2RlZmF1bHQnXS5mbi5ib290c3RyYXBUYWJsZS5tZXRob2RzID0gQm9vdHN0cmFwVGFibGUuTUVUSE9EUztcbiAgJF9fZGVmYXVsdFsnZGVmYXVsdCddLmZuLmJvb3RzdHJhcFRhYmxlLnV0aWxzID0gVXRpbHM7IC8vIEJPT1RTVFJBUCBUQUJMRSBJTklUXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgJF9fZGVmYXVsdFsnZGVmYXVsdCddKGZ1bmN0aW9uICgpIHtcbiAgICAkX19kZWZhdWx0WydkZWZhdWx0J10oJ1tkYXRhLXRvZ2dsZT1cInRhYmxlXCJdJykuYm9vdHN0cmFwVGFibGUoKTtcbiAgfSk7XG5cbiAgcmV0dXJuIEJvb3RzdHJhcFRhYmxlO1xuXG59KSkpO1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIHRvT2JqZWN0ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3RvLW9iamVjdCcpO1xudmFyIHRvQWJzb2x1dGVJbmRleCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy90by1hYnNvbHV0ZS1pbmRleCcpO1xudmFyIHRvTGVuZ3RoID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3RvLWxlbmd0aCcpO1xuXG4vLyBgQXJyYXkucHJvdG90eXBlLmZpbGxgIG1ldGhvZCBpbXBsZW1lbnRhdGlvblxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUuZmlsbFxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBmaWxsKHZhbHVlIC8qICwgc3RhcnQgPSAwLCBlbmQgPSBAbGVuZ3RoICovKSB7XG4gIHZhciBPID0gdG9PYmplY3QodGhpcyk7XG4gIHZhciBsZW5ndGggPSB0b0xlbmd0aChPLmxlbmd0aCk7XG4gIHZhciBhcmd1bWVudHNMZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoO1xuICB2YXIgaW5kZXggPSB0b0Fic29sdXRlSW5kZXgoYXJndW1lbnRzTGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCwgbGVuZ3RoKTtcbiAgdmFyIGVuZCA9IGFyZ3VtZW50c0xlbmd0aCA+IDIgPyBhcmd1bWVudHNbMl0gOiB1bmRlZmluZWQ7XG4gIHZhciBlbmRQb3MgPSBlbmQgPT09IHVuZGVmaW5lZCA/IGxlbmd0aCA6IHRvQWJzb2x1dGVJbmRleChlbmQsIGxlbmd0aCk7XG4gIHdoaWxlIChlbmRQb3MgPiBpbmRleCkgT1tpbmRleCsrXSA9IHZhbHVlO1xuICByZXR1cm4gTztcbn07XG4iLCJ2YXIgYUZ1bmN0aW9uID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2EtZnVuY3Rpb24nKTtcbnZhciB0b09iamVjdCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy90by1vYmplY3QnKTtcbnZhciBJbmRleGVkT2JqZWN0ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2luZGV4ZWQtb2JqZWN0Jyk7XG52YXIgdG9MZW5ndGggPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvdG8tbGVuZ3RoJyk7XG5cbi8vIGBBcnJheS5wcm90b3R5cGUueyByZWR1Y2UsIHJlZHVjZVJpZ2h0IH1gIG1ldGhvZHMgaW1wbGVtZW50YXRpb25cbnZhciBjcmVhdGVNZXRob2QgPSBmdW5jdGlvbiAoSVNfUklHSFQpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh0aGF0LCBjYWxsYmFja2ZuLCBhcmd1bWVudHNMZW5ndGgsIG1lbW8pIHtcbiAgICBhRnVuY3Rpb24oY2FsbGJhY2tmbik7XG4gICAgdmFyIE8gPSB0b09iamVjdCh0aGF0KTtcbiAgICB2YXIgc2VsZiA9IEluZGV4ZWRPYmplY3QoTyk7XG4gICAgdmFyIGxlbmd0aCA9IHRvTGVuZ3RoKE8ubGVuZ3RoKTtcbiAgICB2YXIgaW5kZXggPSBJU19SSUdIVCA/IGxlbmd0aCAtIDEgOiAwO1xuICAgIHZhciBpID0gSVNfUklHSFQgPyAtMSA6IDE7XG4gICAgaWYgKGFyZ3VtZW50c0xlbmd0aCA8IDIpIHdoaWxlICh0cnVlKSB7XG4gICAgICBpZiAoaW5kZXggaW4gc2VsZikge1xuICAgICAgICBtZW1vID0gc2VsZltpbmRleF07XG4gICAgICAgIGluZGV4ICs9IGk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgaW5kZXggKz0gaTtcbiAgICAgIGlmIChJU19SSUdIVCA/IGluZGV4IDwgMCA6IGxlbmd0aCA8PSBpbmRleCkge1xuICAgICAgICB0aHJvdyBUeXBlRXJyb3IoJ1JlZHVjZSBvZiBlbXB0eSBhcnJheSB3aXRoIG5vIGluaXRpYWwgdmFsdWUnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZm9yICg7SVNfUklHSFQgPyBpbmRleCA+PSAwIDogbGVuZ3RoID4gaW5kZXg7IGluZGV4ICs9IGkpIGlmIChpbmRleCBpbiBzZWxmKSB7XG4gICAgICBtZW1vID0gY2FsbGJhY2tmbihtZW1vLCBzZWxmW2luZGV4XSwgaW5kZXgsIE8pO1xuICAgIH1cbiAgICByZXR1cm4gbWVtbztcbiAgfTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAvLyBgQXJyYXkucHJvdG90eXBlLnJlZHVjZWAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLnJlZHVjZVxuICBsZWZ0OiBjcmVhdGVNZXRob2QoZmFsc2UpLFxuICAvLyBgQXJyYXkucHJvdG90eXBlLnJlZHVjZVJpZ2h0YCBtZXRob2RcbiAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUucmVkdWNlcmlnaHRcbiAgcmlnaHQ6IGNyZWF0ZU1ldGhvZCh0cnVlKVxufTtcbiIsInZhciBjbGFzc29mID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2NsYXNzb2YtcmF3Jyk7XG52YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2dsb2JhbCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNsYXNzb2YoZ2xvYmFsLnByb2Nlc3MpID09ICdwcm9jZXNzJztcbiIsInZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1vYmplY3QnKTtcbnZhciBzZXRQcm90b3R5cGVPZiA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9vYmplY3Qtc2V0LXByb3RvdHlwZS1vZicpO1xuXG4vLyBtYWtlcyBzdWJjbGFzc2luZyB3b3JrIGNvcnJlY3QgZm9yIHdyYXBwZWQgYnVpbHQtaW5zXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgkdGhpcywgZHVtbXksIFdyYXBwZXIpIHtcbiAgdmFyIE5ld1RhcmdldCwgTmV3VGFyZ2V0UHJvdG90eXBlO1xuICBpZiAoXG4gICAgLy8gaXQgY2FuIHdvcmsgb25seSB3aXRoIG5hdGl2ZSBgc2V0UHJvdG90eXBlT2ZgXG4gICAgc2V0UHJvdG90eXBlT2YgJiZcbiAgICAvLyB3ZSBoYXZlbid0IGNvbXBsZXRlbHkgY29ycmVjdCBwcmUtRVM2IHdheSBmb3IgZ2V0dGluZyBgbmV3LnRhcmdldGAsIHNvIHVzZSB0aGlzXG4gICAgdHlwZW9mIChOZXdUYXJnZXQgPSBkdW1teS5jb25zdHJ1Y3RvcikgPT0gJ2Z1bmN0aW9uJyAmJlxuICAgIE5ld1RhcmdldCAhPT0gV3JhcHBlciAmJlxuICAgIGlzT2JqZWN0KE5ld1RhcmdldFByb3RvdHlwZSA9IE5ld1RhcmdldC5wcm90b3R5cGUpICYmXG4gICAgTmV3VGFyZ2V0UHJvdG90eXBlICE9PSBXcmFwcGVyLnByb3RvdHlwZVxuICApIHNldFByb3RvdHlwZU9mKCR0aGlzLCBOZXdUYXJnZXRQcm90b3R5cGUpO1xuICByZXR1cm4gJHRoaXM7XG59O1xuIiwidmFyIGdsb2JhbCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9nbG9iYWwnKTtcbnZhciB0cmltID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3N0cmluZy10cmltJykudHJpbTtcbnZhciB3aGl0ZXNwYWNlcyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy93aGl0ZXNwYWNlcycpO1xuXG52YXIgJHBhcnNlRmxvYXQgPSBnbG9iYWwucGFyc2VGbG9hdDtcbnZhciBGT1JDRUQgPSAxIC8gJHBhcnNlRmxvYXQod2hpdGVzcGFjZXMgKyAnLTAnKSAhPT0gLUluZmluaXR5O1xuXG4vLyBgcGFyc2VGbG9hdGAgbWV0aG9kXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXBhcnNlZmxvYXQtc3RyaW5nXG5tb2R1bGUuZXhwb3J0cyA9IEZPUkNFRCA/IGZ1bmN0aW9uIHBhcnNlRmxvYXQoc3RyaW5nKSB7XG4gIHZhciB0cmltbWVkU3RyaW5nID0gdHJpbShTdHJpbmcoc3RyaW5nKSk7XG4gIHZhciByZXN1bHQgPSAkcGFyc2VGbG9hdCh0cmltbWVkU3RyaW5nKTtcbiAgcmV0dXJuIHJlc3VsdCA9PT0gMCAmJiB0cmltbWVkU3RyaW5nLmNoYXJBdCgwKSA9PSAnLScgPyAtMCA6IHJlc3VsdDtcbn0gOiAkcGFyc2VGbG9hdDtcbiIsIi8vIGBTYW1lVmFsdWVgIGFic3RyYWN0IG9wZXJhdGlvblxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1zYW1ldmFsdWVcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3QtaXMgLS0gc2FmZVxubW9kdWxlLmV4cG9ydHMgPSBPYmplY3QuaXMgfHwgZnVuY3Rpb24gaXMoeCwgeSkge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tc2VsZi1jb21wYXJlIC0tIE5hTiBjaGVja1xuICByZXR1cm4geCA9PT0geSA/IHggIT09IDAgfHwgMSAvIHggPT09IDEgLyB5IDogeCAhPSB4ICYmIHkgIT0geTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgZ2V0QnVpbHRJbiA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9nZXQtYnVpbHQtaW4nKTtcbnZhciBkZWZpbmVQcm9wZXJ0eU1vZHVsZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9vYmplY3QtZGVmaW5lLXByb3BlcnR5Jyk7XG52YXIgd2VsbEtub3duU3ltYm9sID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3dlbGwta25vd24tc3ltYm9sJyk7XG52YXIgREVTQ1JJUFRPUlMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZGVzY3JpcHRvcnMnKTtcblxudmFyIFNQRUNJRVMgPSB3ZWxsS25vd25TeW1ib2woJ3NwZWNpZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoQ09OU1RSVUNUT1JfTkFNRSkge1xuICB2YXIgQ29uc3RydWN0b3IgPSBnZXRCdWlsdEluKENPTlNUUlVDVE9SX05BTUUpO1xuICB2YXIgZGVmaW5lUHJvcGVydHkgPSBkZWZpbmVQcm9wZXJ0eU1vZHVsZS5mO1xuXG4gIGlmIChERVNDUklQVE9SUyAmJiBDb25zdHJ1Y3RvciAmJiAhQ29uc3RydWN0b3JbU1BFQ0lFU10pIHtcbiAgICBkZWZpbmVQcm9wZXJ0eShDb25zdHJ1Y3RvciwgU1BFQ0lFUywge1xuICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9XG4gICAgfSk7XG4gIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgdG9JbnRlZ2VyID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3RvLWludGVnZXInKTtcbnZhciByZXF1aXJlT2JqZWN0Q29lcmNpYmxlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3JlcXVpcmUtb2JqZWN0LWNvZXJjaWJsZScpO1xuXG4vLyBgU3RyaW5nLnByb3RvdHlwZS5yZXBlYXRgIG1ldGhvZCBpbXBsZW1lbnRhdGlvblxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1zdHJpbmcucHJvdG90eXBlLnJlcGVhdFxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiByZXBlYXQoY291bnQpIHtcbiAgdmFyIHN0ciA9IFN0cmluZyhyZXF1aXJlT2JqZWN0Q29lcmNpYmxlKHRoaXMpKTtcbiAgdmFyIHJlc3VsdCA9ICcnO1xuICB2YXIgbiA9IHRvSW50ZWdlcihjb3VudCk7XG4gIGlmIChuIDwgMCB8fCBuID09IEluZmluaXR5KSB0aHJvdyBSYW5nZUVycm9yKCdXcm9uZyBudW1iZXIgb2YgcmVwZXRpdGlvbnMnKTtcbiAgZm9yICg7biA+IDA7IChuID4+Pj0gMSkgJiYgKHN0ciArPSBzdHIpKSBpZiAobiAmIDEpIHJlc3VsdCArPSBzdHI7XG4gIHJldHVybiByZXN1bHQ7XG59O1xuIiwidmFyIGNsYXNzb2YgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvY2xhc3NvZi1yYXcnKTtcblxuLy8gYHRoaXNOdW1iZXJWYWx1ZWAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXRoaXNudW1iZXJ2YWx1ZVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPSAnbnVtYmVyJyAmJiBjbGFzc29mKHZhbHVlKSAhPSAnTnVtYmVyJykge1xuICAgIHRocm93IFR5cGVFcnJvcignSW5jb3JyZWN0IGludm9jYXRpb24nKTtcbiAgfVxuICByZXR1cm4gK3ZhbHVlO1xufTtcbiIsInZhciAkID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2V4cG9ydCcpO1xudmFyIGZpbGwgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvYXJyYXktZmlsbCcpO1xudmFyIGFkZFRvVW5zY29wYWJsZXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvYWRkLXRvLXVuc2NvcGFibGVzJyk7XG5cbi8vIGBBcnJheS5wcm90b3R5cGUuZmlsbGAgbWV0aG9kXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS5maWxsXG4kKHsgdGFyZ2V0OiAnQXJyYXknLCBwcm90bzogdHJ1ZSB9LCB7XG4gIGZpbGw6IGZpbGxcbn0pO1xuXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS1AQHVuc2NvcGFibGVzXG5hZGRUb1Vuc2NvcGFibGVzKCdmaWxsJyk7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgJCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9leHBvcnQnKTtcbnZhciAkZmluZCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9hcnJheS1pdGVyYXRpb24nKS5maW5kO1xudmFyIGFkZFRvVW5zY29wYWJsZXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvYWRkLXRvLXVuc2NvcGFibGVzJyk7XG5cbnZhciBGSU5EID0gJ2ZpbmQnO1xudmFyIFNLSVBTX0hPTEVTID0gdHJ1ZTtcblxuLy8gU2hvdWxkbid0IHNraXAgaG9sZXNcbmlmIChGSU5EIGluIFtdKSBBcnJheSgxKVtGSU5EXShmdW5jdGlvbiAoKSB7IFNLSVBTX0hPTEVTID0gZmFsc2U7IH0pO1xuXG4vLyBgQXJyYXkucHJvdG90eXBlLmZpbmRgIG1ldGhvZFxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUuZmluZFxuJCh7IHRhcmdldDogJ0FycmF5JywgcHJvdG86IHRydWUsIGZvcmNlZDogU0tJUFNfSE9MRVMgfSwge1xuICBmaW5kOiBmdW5jdGlvbiBmaW5kKGNhbGxiYWNrZm4gLyogLCB0aGF0ID0gdW5kZWZpbmVkICovKSB7XG4gICAgcmV0dXJuICRmaW5kKHRoaXMsIGNhbGxiYWNrZm4sIGFyZ3VtZW50cy5sZW5ndGggPiAxID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkKTtcbiAgfVxufSk7XG5cbi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLUBAdW5zY29wYWJsZXNcbmFkZFRvVW5zY29wYWJsZXMoRklORCk7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgJCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9leHBvcnQnKTtcbnZhciAkaW5jbHVkZXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvYXJyYXktaW5jbHVkZXMnKS5pbmNsdWRlcztcbnZhciBhZGRUb1Vuc2NvcGFibGVzID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2FkZC10by11bnNjb3BhYmxlcycpO1xuXG4vLyBgQXJyYXkucHJvdG90eXBlLmluY2x1ZGVzYCBtZXRob2Rcbi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLmluY2x1ZGVzXG4kKHsgdGFyZ2V0OiAnQXJyYXknLCBwcm90bzogdHJ1ZSB9LCB7XG4gIGluY2x1ZGVzOiBmdW5jdGlvbiBpbmNsdWRlcyhlbCAvKiAsIGZyb21JbmRleCA9IDAgKi8pIHtcbiAgICByZXR1cm4gJGluY2x1ZGVzKHRoaXMsIGVsLCBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCk7XG4gIH1cbn0pO1xuXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS1AQHVuc2NvcGFibGVzXG5hZGRUb1Vuc2NvcGFibGVzKCdpbmNsdWRlcycpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuLyogZXNsaW50LWRpc2FibGUgZXMvbm8tYXJyYXktcHJvdG90eXBlLWluZGV4b2YgLS0gcmVxdWlyZWQgZm9yIHRlc3RpbmcgKi9cbnZhciAkID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2V4cG9ydCcpO1xudmFyICRpbmRleE9mID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2FycmF5LWluY2x1ZGVzJykuaW5kZXhPZjtcbnZhciBhcnJheU1ldGhvZElzU3RyaWN0ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2FycmF5LW1ldGhvZC1pcy1zdHJpY3QnKTtcblxudmFyIG5hdGl2ZUluZGV4T2YgPSBbXS5pbmRleE9mO1xuXG52YXIgTkVHQVRJVkVfWkVSTyA9ICEhbmF0aXZlSW5kZXhPZiAmJiAxIC8gWzFdLmluZGV4T2YoMSwgLTApIDwgMDtcbnZhciBTVFJJQ1RfTUVUSE9EID0gYXJyYXlNZXRob2RJc1N0cmljdCgnaW5kZXhPZicpO1xuXG4vLyBgQXJyYXkucHJvdG90eXBlLmluZGV4T2ZgIG1ldGhvZFxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUuaW5kZXhvZlxuJCh7IHRhcmdldDogJ0FycmF5JywgcHJvdG86IHRydWUsIGZvcmNlZDogTkVHQVRJVkVfWkVSTyB8fCAhU1RSSUNUX01FVEhPRCB9LCB7XG4gIGluZGV4T2Y6IGZ1bmN0aW9uIGluZGV4T2Yoc2VhcmNoRWxlbWVudCAvKiAsIGZyb21JbmRleCA9IDAgKi8pIHtcbiAgICByZXR1cm4gTkVHQVRJVkVfWkVST1xuICAgICAgLy8gY29udmVydCAtMCB0byArMFxuICAgICAgPyBuYXRpdmVJbmRleE9mLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgMFxuICAgICAgOiAkaW5kZXhPZih0aGlzLCBzZWFyY2hFbGVtZW50LCBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCk7XG4gIH1cbn0pO1xuIiwidmFyICQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZXhwb3J0Jyk7XG52YXIgaXNBcnJheSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1hcnJheScpO1xuXG4vLyBgQXJyYXkuaXNBcnJheWAgbWV0aG9kXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LmlzYXJyYXlcbiQoeyB0YXJnZXQ6ICdBcnJheScsIHN0YXQ6IHRydWUgfSwge1xuICBpc0FycmF5OiBpc0FycmF5XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciAkID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2V4cG9ydCcpO1xudmFyICRyZWR1Y2UgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvYXJyYXktcmVkdWNlJykubGVmdDtcbnZhciBhcnJheU1ldGhvZElzU3RyaWN0ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2FycmF5LW1ldGhvZC1pcy1zdHJpY3QnKTtcbnZhciBDSFJPTUVfVkVSU0lPTiA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9lbmdpbmUtdjgtdmVyc2lvbicpO1xudmFyIElTX05PREUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZW5naW5lLWlzLW5vZGUnKTtcblxudmFyIFNUUklDVF9NRVRIT0QgPSBhcnJheU1ldGhvZElzU3RyaWN0KCdyZWR1Y2UnKTtcbi8vIENocm9tZSA4MC04MiBoYXMgYSBjcml0aWNhbCBidWdcbi8vIGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC9jaHJvbWl1bS9pc3N1ZXMvZGV0YWlsP2lkPTEwNDk5ODJcbnZhciBDSFJPTUVfQlVHID0gIUlTX05PREUgJiYgQ0hST01FX1ZFUlNJT04gPiA3OSAmJiBDSFJPTUVfVkVSU0lPTiA8IDgzO1xuXG4vLyBgQXJyYXkucHJvdG90eXBlLnJlZHVjZWAgbWV0aG9kXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS5yZWR1Y2VcbiQoeyB0YXJnZXQ6ICdBcnJheScsIHByb3RvOiB0cnVlLCBmb3JjZWQ6ICFTVFJJQ1RfTUVUSE9EIHx8IENIUk9NRV9CVUcgfSwge1xuICByZWR1Y2U6IGZ1bmN0aW9uIHJlZHVjZShjYWxsYmFja2ZuIC8qICwgaW5pdGlhbFZhbHVlICovKSB7XG4gICAgcmV0dXJuICRyZWR1Y2UodGhpcywgY2FsbGJhY2tmbiwgYXJndW1lbnRzLmxlbmd0aCwgYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQpO1xuICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciAkID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2V4cG9ydCcpO1xudmFyICRzb21lID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2FycmF5LWl0ZXJhdGlvbicpLnNvbWU7XG52YXIgYXJyYXlNZXRob2RJc1N0cmljdCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9hcnJheS1tZXRob2QtaXMtc3RyaWN0Jyk7XG5cbnZhciBTVFJJQ1RfTUVUSE9EID0gYXJyYXlNZXRob2RJc1N0cmljdCgnc29tZScpO1xuXG4vLyBgQXJyYXkucHJvdG90eXBlLnNvbWVgIG1ldGhvZFxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUuc29tZVxuJCh7IHRhcmdldDogJ0FycmF5JywgcHJvdG86IHRydWUsIGZvcmNlZDogIVNUUklDVF9NRVRIT0QgfSwge1xuICBzb21lOiBmdW5jdGlvbiBzb21lKGNhbGxiYWNrZm4gLyogLCB0aGlzQXJnICovKSB7XG4gICAgcmV0dXJuICRzb21lKHRoaXMsIGNhbGxiYWNrZm4sIGFyZ3VtZW50cy5sZW5ndGggPiAxID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkKTtcbiAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgJCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9leHBvcnQnKTtcbnZhciB0b0Fic29sdXRlSW5kZXggPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvdG8tYWJzb2x1dGUtaW5kZXgnKTtcbnZhciB0b0ludGVnZXIgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvdG8taW50ZWdlcicpO1xudmFyIHRvTGVuZ3RoID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3RvLWxlbmd0aCcpO1xudmFyIHRvT2JqZWN0ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3RvLW9iamVjdCcpO1xudmFyIGFycmF5U3BlY2llc0NyZWF0ZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9hcnJheS1zcGVjaWVzLWNyZWF0ZScpO1xudmFyIGNyZWF0ZVByb3BlcnR5ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2NyZWF0ZS1wcm9wZXJ0eScpO1xudmFyIGFycmF5TWV0aG9kSGFzU3BlY2llc1N1cHBvcnQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvYXJyYXktbWV0aG9kLWhhcy1zcGVjaWVzLXN1cHBvcnQnKTtcblxudmFyIEhBU19TUEVDSUVTX1NVUFBPUlQgPSBhcnJheU1ldGhvZEhhc1NwZWNpZXNTdXBwb3J0KCdzcGxpY2UnKTtcblxudmFyIG1heCA9IE1hdGgubWF4O1xudmFyIG1pbiA9IE1hdGgubWluO1xudmFyIE1BWF9TQUZFX0lOVEVHRVIgPSAweDFGRkZGRkZGRkZGRkZGO1xudmFyIE1BWElNVU1fQUxMT1dFRF9MRU5HVEhfRVhDRUVERUQgPSAnTWF4aW11bSBhbGxvd2VkIGxlbmd0aCBleGNlZWRlZCc7XG5cbi8vIGBBcnJheS5wcm90b3R5cGUuc3BsaWNlYCBtZXRob2Rcbi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtYXJyYXkucHJvdG90eXBlLnNwbGljZVxuLy8gd2l0aCBhZGRpbmcgc3VwcG9ydCBvZiBAQHNwZWNpZXNcbiQoeyB0YXJnZXQ6ICdBcnJheScsIHByb3RvOiB0cnVlLCBmb3JjZWQ6ICFIQVNfU1BFQ0lFU19TVVBQT1JUIH0sIHtcbiAgc3BsaWNlOiBmdW5jdGlvbiBzcGxpY2Uoc3RhcnQsIGRlbGV0ZUNvdW50IC8qICwgLi4uaXRlbXMgKi8pIHtcbiAgICB2YXIgTyA9IHRvT2JqZWN0KHRoaXMpO1xuICAgIHZhciBsZW4gPSB0b0xlbmd0aChPLmxlbmd0aCk7XG4gICAgdmFyIGFjdHVhbFN0YXJ0ID0gdG9BYnNvbHV0ZUluZGV4KHN0YXJ0LCBsZW4pO1xuICAgIHZhciBhcmd1bWVudHNMZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgIHZhciBpbnNlcnRDb3VudCwgYWN0dWFsRGVsZXRlQ291bnQsIEEsIGssIGZyb20sIHRvO1xuICAgIGlmIChhcmd1bWVudHNMZW5ndGggPT09IDApIHtcbiAgICAgIGluc2VydENvdW50ID0gYWN0dWFsRGVsZXRlQ291bnQgPSAwO1xuICAgIH0gZWxzZSBpZiAoYXJndW1lbnRzTGVuZ3RoID09PSAxKSB7XG4gICAgICBpbnNlcnRDb3VudCA9IDA7XG4gICAgICBhY3R1YWxEZWxldGVDb3VudCA9IGxlbiAtIGFjdHVhbFN0YXJ0O1xuICAgIH0gZWxzZSB7XG4gICAgICBpbnNlcnRDb3VudCA9IGFyZ3VtZW50c0xlbmd0aCAtIDI7XG4gICAgICBhY3R1YWxEZWxldGVDb3VudCA9IG1pbihtYXgodG9JbnRlZ2VyKGRlbGV0ZUNvdW50KSwgMCksIGxlbiAtIGFjdHVhbFN0YXJ0KTtcbiAgICB9XG4gICAgaWYgKGxlbiArIGluc2VydENvdW50IC0gYWN0dWFsRGVsZXRlQ291bnQgPiBNQVhfU0FGRV9JTlRFR0VSKSB7XG4gICAgICB0aHJvdyBUeXBlRXJyb3IoTUFYSU1VTV9BTExPV0VEX0xFTkdUSF9FWENFRURFRCk7XG4gICAgfVxuICAgIEEgPSBhcnJheVNwZWNpZXNDcmVhdGUoTywgYWN0dWFsRGVsZXRlQ291bnQpO1xuICAgIGZvciAoayA9IDA7IGsgPCBhY3R1YWxEZWxldGVDb3VudDsgaysrKSB7XG4gICAgICBmcm9tID0gYWN0dWFsU3RhcnQgKyBrO1xuICAgICAgaWYgKGZyb20gaW4gTykgY3JlYXRlUHJvcGVydHkoQSwgaywgT1tmcm9tXSk7XG4gICAgfVxuICAgIEEubGVuZ3RoID0gYWN0dWFsRGVsZXRlQ291bnQ7XG4gICAgaWYgKGluc2VydENvdW50IDwgYWN0dWFsRGVsZXRlQ291bnQpIHtcbiAgICAgIGZvciAoayA9IGFjdHVhbFN0YXJ0OyBrIDwgbGVuIC0gYWN0dWFsRGVsZXRlQ291bnQ7IGsrKykge1xuICAgICAgICBmcm9tID0gayArIGFjdHVhbERlbGV0ZUNvdW50O1xuICAgICAgICB0byA9IGsgKyBpbnNlcnRDb3VudDtcbiAgICAgICAgaWYgKGZyb20gaW4gTykgT1t0b10gPSBPW2Zyb21dO1xuICAgICAgICBlbHNlIGRlbGV0ZSBPW3RvXTtcbiAgICAgIH1cbiAgICAgIGZvciAoayA9IGxlbjsgayA+IGxlbiAtIGFjdHVhbERlbGV0ZUNvdW50ICsgaW5zZXJ0Q291bnQ7IGstLSkgZGVsZXRlIE9bayAtIDFdO1xuICAgIH0gZWxzZSBpZiAoaW5zZXJ0Q291bnQgPiBhY3R1YWxEZWxldGVDb3VudCkge1xuICAgICAgZm9yIChrID0gbGVuIC0gYWN0dWFsRGVsZXRlQ291bnQ7IGsgPiBhY3R1YWxTdGFydDsgay0tKSB7XG4gICAgICAgIGZyb20gPSBrICsgYWN0dWFsRGVsZXRlQ291bnQgLSAxO1xuICAgICAgICB0byA9IGsgKyBpbnNlcnRDb3VudCAtIDE7XG4gICAgICAgIGlmIChmcm9tIGluIE8pIE9bdG9dID0gT1tmcm9tXTtcbiAgICAgICAgZWxzZSBkZWxldGUgT1t0b107XG4gICAgICB9XG4gICAgfVxuICAgIGZvciAoayA9IDA7IGsgPCBpbnNlcnRDb3VudDsgaysrKSB7XG4gICAgICBPW2sgKyBhY3R1YWxTdGFydF0gPSBhcmd1bWVudHNbayArIDJdO1xuICAgIH1cbiAgICBPLmxlbmd0aCA9IGxlbiAtIGFjdHVhbERlbGV0ZUNvdW50ICsgaW5zZXJ0Q291bnQ7XG4gICAgcmV0dXJuIEE7XG4gIH1cbn0pO1xuIiwidmFyICQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZXhwb3J0Jyk7XG52YXIgYmluZCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9mdW5jdGlvbi1iaW5kJyk7XG5cbi8vIGBGdW5jdGlvbi5wcm90b3R5cGUuYmluZGAgbWV0aG9kXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kXG4kKHsgdGFyZ2V0OiAnRnVuY3Rpb24nLCBwcm90bzogdHJ1ZSB9LCB7XG4gIGJpbmQ6IGJpbmRcbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIERFU0NSSVBUT1JTID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2Rlc2NyaXB0b3JzJyk7XG52YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2dsb2JhbCcpO1xudmFyIGlzRm9yY2VkID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2lzLWZvcmNlZCcpO1xudmFyIHJlZGVmaW5lID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3JlZGVmaW5lJyk7XG52YXIgaGFzID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2hhcycpO1xudmFyIGNsYXNzb2YgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvY2xhc3NvZi1yYXcnKTtcbnZhciBpbmhlcml0SWZSZXF1aXJlZCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pbmhlcml0LWlmLXJlcXVpcmVkJyk7XG52YXIgdG9QcmltaXRpdmUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvdG8tcHJpbWl0aXZlJyk7XG52YXIgZmFpbHMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZmFpbHMnKTtcbnZhciBjcmVhdGUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvb2JqZWN0LWNyZWF0ZScpO1xudmFyIGdldE93blByb3BlcnR5TmFtZXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvb2JqZWN0LWdldC1vd24tcHJvcGVydHktbmFtZXMnKS5mO1xudmFyIGdldE93blByb3BlcnR5RGVzY3JpcHRvciA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9vYmplY3QtZ2V0LW93bi1wcm9wZXJ0eS1kZXNjcmlwdG9yJykuZjtcbnZhciBkZWZpbmVQcm9wZXJ0eSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9vYmplY3QtZGVmaW5lLXByb3BlcnR5JykuZjtcbnZhciB0cmltID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3N0cmluZy10cmltJykudHJpbTtcblxudmFyIE5VTUJFUiA9ICdOdW1iZXInO1xudmFyIE5hdGl2ZU51bWJlciA9IGdsb2JhbFtOVU1CRVJdO1xudmFyIE51bWJlclByb3RvdHlwZSA9IE5hdGl2ZU51bWJlci5wcm90b3R5cGU7XG5cbi8vIE9wZXJhIH4xMiBoYXMgYnJva2VuIE9iamVjdCN0b1N0cmluZ1xudmFyIEJST0tFTl9DTEFTU09GID0gY2xhc3NvZihjcmVhdGUoTnVtYmVyUHJvdG90eXBlKSkgPT0gTlVNQkVSO1xuXG4vLyBgVG9OdW1iZXJgIGFic3RyYWN0IG9wZXJhdGlvblxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy10b251bWJlclxudmFyIHRvTnVtYmVyID0gZnVuY3Rpb24gKGFyZ3VtZW50KSB7XG4gIHZhciBpdCA9IHRvUHJpbWl0aXZlKGFyZ3VtZW50LCBmYWxzZSk7XG4gIHZhciBmaXJzdCwgdGhpcmQsIHJhZGl4LCBtYXhDb2RlLCBkaWdpdHMsIGxlbmd0aCwgaW5kZXgsIGNvZGU7XG4gIGlmICh0eXBlb2YgaXQgPT0gJ3N0cmluZycgJiYgaXQubGVuZ3RoID4gMikge1xuICAgIGl0ID0gdHJpbShpdCk7XG4gICAgZmlyc3QgPSBpdC5jaGFyQ29kZUF0KDApO1xuICAgIGlmIChmaXJzdCA9PT0gNDMgfHwgZmlyc3QgPT09IDQ1KSB7XG4gICAgICB0aGlyZCA9IGl0LmNoYXJDb2RlQXQoMik7XG4gICAgICBpZiAodGhpcmQgPT09IDg4IHx8IHRoaXJkID09PSAxMjApIHJldHVybiBOYU47IC8vIE51bWJlcignKzB4MScpIHNob3VsZCBiZSBOYU4sIG9sZCBWOCBmaXhcbiAgICB9IGVsc2UgaWYgKGZpcnN0ID09PSA0OCkge1xuICAgICAgc3dpdGNoIChpdC5jaGFyQ29kZUF0KDEpKSB7XG4gICAgICAgIGNhc2UgNjY6IGNhc2UgOTg6IHJhZGl4ID0gMjsgbWF4Q29kZSA9IDQ5OyBicmVhazsgLy8gZmFzdCBlcXVhbCBvZiAvXjBiWzAxXSskL2lcbiAgICAgICAgY2FzZSA3OTogY2FzZSAxMTE6IHJhZGl4ID0gODsgbWF4Q29kZSA9IDU1OyBicmVhazsgLy8gZmFzdCBlcXVhbCBvZiAvXjBvWzAtN10rJC9pXG4gICAgICAgIGRlZmF1bHQ6IHJldHVybiAraXQ7XG4gICAgICB9XG4gICAgICBkaWdpdHMgPSBpdC5zbGljZSgyKTtcbiAgICAgIGxlbmd0aCA9IGRpZ2l0cy5sZW5ndGg7XG4gICAgICBmb3IgKGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHtcbiAgICAgICAgY29kZSA9IGRpZ2l0cy5jaGFyQ29kZUF0KGluZGV4KTtcbiAgICAgICAgLy8gcGFyc2VJbnQgcGFyc2VzIGEgc3RyaW5nIHRvIGEgZmlyc3QgdW5hdmFpbGFibGUgc3ltYm9sXG4gICAgICAgIC8vIGJ1dCBUb051bWJlciBzaG91bGQgcmV0dXJuIE5hTiBpZiBhIHN0cmluZyBjb250YWlucyB1bmF2YWlsYWJsZSBzeW1ib2xzXG4gICAgICAgIGlmIChjb2RlIDwgNDggfHwgY29kZSA+IG1heENvZGUpIHJldHVybiBOYU47XG4gICAgICB9IHJldHVybiBwYXJzZUludChkaWdpdHMsIHJhZGl4KTtcbiAgICB9XG4gIH0gcmV0dXJuICtpdDtcbn07XG5cbi8vIGBOdW1iZXJgIGNvbnN0cnVjdG9yXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW51bWJlci1jb25zdHJ1Y3RvclxuaWYgKGlzRm9yY2VkKE5VTUJFUiwgIU5hdGl2ZU51bWJlcignIDBvMScpIHx8ICFOYXRpdmVOdW1iZXIoJzBiMScpIHx8IE5hdGl2ZU51bWJlcignKzB4MScpKSkge1xuICB2YXIgTnVtYmVyV3JhcHBlciA9IGZ1bmN0aW9uIE51bWJlcih2YWx1ZSkge1xuICAgIHZhciBpdCA9IGFyZ3VtZW50cy5sZW5ndGggPCAxID8gMCA6IHZhbHVlO1xuICAgIHZhciBkdW1teSA9IHRoaXM7XG4gICAgcmV0dXJuIGR1bW15IGluc3RhbmNlb2YgTnVtYmVyV3JhcHBlclxuICAgICAgLy8gY2hlY2sgb24gMS4uY29uc3RydWN0b3IoZm9vKSBjYXNlXG4gICAgICAmJiAoQlJPS0VOX0NMQVNTT0YgPyBmYWlscyhmdW5jdGlvbiAoKSB7IE51bWJlclByb3RvdHlwZS52YWx1ZU9mLmNhbGwoZHVtbXkpOyB9KSA6IGNsYXNzb2YoZHVtbXkpICE9IE5VTUJFUilcbiAgICAgICAgPyBpbmhlcml0SWZSZXF1aXJlZChuZXcgTmF0aXZlTnVtYmVyKHRvTnVtYmVyKGl0KSksIGR1bW15LCBOdW1iZXJXcmFwcGVyKSA6IHRvTnVtYmVyKGl0KTtcbiAgfTtcbiAgZm9yICh2YXIga2V5cyA9IERFU0NSSVBUT1JTID8gZ2V0T3duUHJvcGVydHlOYW1lcyhOYXRpdmVOdW1iZXIpIDogKFxuICAgIC8vIEVTMzpcbiAgICAnTUFYX1ZBTFVFLE1JTl9WQUxVRSxOYU4sTkVHQVRJVkVfSU5GSU5JVFksUE9TSVRJVkVfSU5GSU5JVFksJyArXG4gICAgLy8gRVMyMDE1IChpbiBjYXNlLCBpZiBtb2R1bGVzIHdpdGggRVMyMDE1IE51bWJlciBzdGF0aWNzIHJlcXVpcmVkIGJlZm9yZSk6XG4gICAgJ0VQU0lMT04saXNGaW5pdGUsaXNJbnRlZ2VyLGlzTmFOLGlzU2FmZUludGVnZXIsTUFYX1NBRkVfSU5URUdFUiwnICtcbiAgICAnTUlOX1NBRkVfSU5URUdFUixwYXJzZUZsb2F0LHBhcnNlSW50LGlzSW50ZWdlciwnICtcbiAgICAvLyBFU05leHRcbiAgICAnZnJvbVN0cmluZyxyYW5nZSdcbiAgKS5zcGxpdCgnLCcpLCBqID0gMCwga2V5OyBrZXlzLmxlbmd0aCA+IGo7IGorKykge1xuICAgIGlmIChoYXMoTmF0aXZlTnVtYmVyLCBrZXkgPSBrZXlzW2pdKSAmJiAhaGFzKE51bWJlcldyYXBwZXIsIGtleSkpIHtcbiAgICAgIGRlZmluZVByb3BlcnR5KE51bWJlcldyYXBwZXIsIGtleSwgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKE5hdGl2ZU51bWJlciwga2V5KSk7XG4gICAgfVxuICB9XG4gIE51bWJlcldyYXBwZXIucHJvdG90eXBlID0gTnVtYmVyUHJvdG90eXBlO1xuICBOdW1iZXJQcm90b3R5cGUuY29uc3RydWN0b3IgPSBOdW1iZXJXcmFwcGVyO1xuICByZWRlZmluZShnbG9iYWwsIE5VTUJFUiwgTnVtYmVyV3JhcHBlcik7XG59XG4iLCIndXNlIHN0cmljdCc7XG52YXIgJCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9leHBvcnQnKTtcbnZhciB0b0ludGVnZXIgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvdG8taW50ZWdlcicpO1xudmFyIHRoaXNOdW1iZXJWYWx1ZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy90aGlzLW51bWJlci12YWx1ZScpO1xudmFyIHJlcGVhdCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9zdHJpbmctcmVwZWF0Jyk7XG52YXIgZmFpbHMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZmFpbHMnKTtcblxudmFyIG5hdGl2ZVRvRml4ZWQgPSAxLjAudG9GaXhlZDtcbnZhciBmbG9vciA9IE1hdGguZmxvb3I7XG5cbnZhciBwb3cgPSBmdW5jdGlvbiAoeCwgbiwgYWNjKSB7XG4gIHJldHVybiBuID09PSAwID8gYWNjIDogbiAlIDIgPT09IDEgPyBwb3coeCwgbiAtIDEsIGFjYyAqIHgpIDogcG93KHggKiB4LCBuIC8gMiwgYWNjKTtcbn07XG5cbnZhciBsb2cgPSBmdW5jdGlvbiAoeCkge1xuICB2YXIgbiA9IDA7XG4gIHZhciB4MiA9IHg7XG4gIHdoaWxlICh4MiA+PSA0MDk2KSB7XG4gICAgbiArPSAxMjtcbiAgICB4MiAvPSA0MDk2O1xuICB9XG4gIHdoaWxlICh4MiA+PSAyKSB7XG4gICAgbiArPSAxO1xuICAgIHgyIC89IDI7XG4gIH0gcmV0dXJuIG47XG59O1xuXG52YXIgbXVsdGlwbHkgPSBmdW5jdGlvbiAoZGF0YSwgbiwgYykge1xuICB2YXIgaW5kZXggPSAtMTtcbiAgdmFyIGMyID0gYztcbiAgd2hpbGUgKCsraW5kZXggPCA2KSB7XG4gICAgYzIgKz0gbiAqIGRhdGFbaW5kZXhdO1xuICAgIGRhdGFbaW5kZXhdID0gYzIgJSAxZTc7XG4gICAgYzIgPSBmbG9vcihjMiAvIDFlNyk7XG4gIH1cbn07XG5cbnZhciBkaXZpZGUgPSBmdW5jdGlvbiAoZGF0YSwgbikge1xuICB2YXIgaW5kZXggPSA2O1xuICB2YXIgYyA9IDA7XG4gIHdoaWxlICgtLWluZGV4ID49IDApIHtcbiAgICBjICs9IGRhdGFbaW5kZXhdO1xuICAgIGRhdGFbaW5kZXhdID0gZmxvb3IoYyAvIG4pO1xuICAgIGMgPSAoYyAlIG4pICogMWU3O1xuICB9XG59O1xuXG52YXIgZGF0YVRvU3RyaW5nID0gZnVuY3Rpb24gKGRhdGEpIHtcbiAgdmFyIGluZGV4ID0gNjtcbiAgdmFyIHMgPSAnJztcbiAgd2hpbGUgKC0taW5kZXggPj0gMCkge1xuICAgIGlmIChzICE9PSAnJyB8fCBpbmRleCA9PT0gMCB8fCBkYXRhW2luZGV4XSAhPT0gMCkge1xuICAgICAgdmFyIHQgPSBTdHJpbmcoZGF0YVtpbmRleF0pO1xuICAgICAgcyA9IHMgPT09ICcnID8gdCA6IHMgKyByZXBlYXQuY2FsbCgnMCcsIDcgLSB0Lmxlbmd0aCkgKyB0O1xuICAgIH1cbiAgfSByZXR1cm4gcztcbn07XG5cbnZhciBGT1JDRUQgPSBuYXRpdmVUb0ZpeGVkICYmIChcbiAgMC4wMDAwOC50b0ZpeGVkKDMpICE9PSAnMC4wMDAnIHx8XG4gIDAuOS50b0ZpeGVkKDApICE9PSAnMScgfHxcbiAgMS4yNTUudG9GaXhlZCgyKSAhPT0gJzEuMjUnIHx8XG4gIDEwMDAwMDAwMDAwMDAwMDAxMjguMC50b0ZpeGVkKDApICE9PSAnMTAwMDAwMDAwMDAwMDAwMDEyOCdcbikgfHwgIWZhaWxzKGZ1bmN0aW9uICgpIHtcbiAgLy8gVjggfiBBbmRyb2lkIDQuMy1cbiAgbmF0aXZlVG9GaXhlZC5jYWxsKHt9KTtcbn0pO1xuXG4vLyBgTnVtYmVyLnByb3RvdHlwZS50b0ZpeGVkYCBtZXRob2Rcbi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtbnVtYmVyLnByb3RvdHlwZS50b2ZpeGVkXG4kKHsgdGFyZ2V0OiAnTnVtYmVyJywgcHJvdG86IHRydWUsIGZvcmNlZDogRk9SQ0VEIH0sIHtcbiAgdG9GaXhlZDogZnVuY3Rpb24gdG9GaXhlZChmcmFjdGlvbkRpZ2l0cykge1xuICAgIHZhciBudW1iZXIgPSB0aGlzTnVtYmVyVmFsdWUodGhpcyk7XG4gICAgdmFyIGZyYWN0RGlnaXRzID0gdG9JbnRlZ2VyKGZyYWN0aW9uRGlnaXRzKTtcbiAgICB2YXIgZGF0YSA9IFswLCAwLCAwLCAwLCAwLCAwXTtcbiAgICB2YXIgc2lnbiA9ICcnO1xuICAgIHZhciByZXN1bHQgPSAnMCc7XG4gICAgdmFyIGUsIHosIGosIGs7XG5cbiAgICBpZiAoZnJhY3REaWdpdHMgPCAwIHx8IGZyYWN0RGlnaXRzID4gMjApIHRocm93IFJhbmdlRXJyb3IoJ0luY29ycmVjdCBmcmFjdGlvbiBkaWdpdHMnKTtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tc2VsZi1jb21wYXJlIC0tIE5hTiBjaGVja1xuICAgIGlmIChudW1iZXIgIT0gbnVtYmVyKSByZXR1cm4gJ05hTic7XG4gICAgaWYgKG51bWJlciA8PSAtMWUyMSB8fCBudW1iZXIgPj0gMWUyMSkgcmV0dXJuIFN0cmluZyhudW1iZXIpO1xuICAgIGlmIChudW1iZXIgPCAwKSB7XG4gICAgICBzaWduID0gJy0nO1xuICAgICAgbnVtYmVyID0gLW51bWJlcjtcbiAgICB9XG4gICAgaWYgKG51bWJlciA+IDFlLTIxKSB7XG4gICAgICBlID0gbG9nKG51bWJlciAqIHBvdygyLCA2OSwgMSkpIC0gNjk7XG4gICAgICB6ID0gZSA8IDAgPyBudW1iZXIgKiBwb3coMiwgLWUsIDEpIDogbnVtYmVyIC8gcG93KDIsIGUsIDEpO1xuICAgICAgeiAqPSAweDEwMDAwMDAwMDAwMDAwO1xuICAgICAgZSA9IDUyIC0gZTtcbiAgICAgIGlmIChlID4gMCkge1xuICAgICAgICBtdWx0aXBseShkYXRhLCAwLCB6KTtcbiAgICAgICAgaiA9IGZyYWN0RGlnaXRzO1xuICAgICAgICB3aGlsZSAoaiA+PSA3KSB7XG4gICAgICAgICAgbXVsdGlwbHkoZGF0YSwgMWU3LCAwKTtcbiAgICAgICAgICBqIC09IDc7XG4gICAgICAgIH1cbiAgICAgICAgbXVsdGlwbHkoZGF0YSwgcG93KDEwLCBqLCAxKSwgMCk7XG4gICAgICAgIGogPSBlIC0gMTtcbiAgICAgICAgd2hpbGUgKGogPj0gMjMpIHtcbiAgICAgICAgICBkaXZpZGUoZGF0YSwgMSA8PCAyMyk7XG4gICAgICAgICAgaiAtPSAyMztcbiAgICAgICAgfVxuICAgICAgICBkaXZpZGUoZGF0YSwgMSA8PCBqKTtcbiAgICAgICAgbXVsdGlwbHkoZGF0YSwgMSwgMSk7XG4gICAgICAgIGRpdmlkZShkYXRhLCAyKTtcbiAgICAgICAgcmVzdWx0ID0gZGF0YVRvU3RyaW5nKGRhdGEpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbXVsdGlwbHkoZGF0YSwgMCwgeik7XG4gICAgICAgIG11bHRpcGx5KGRhdGEsIDEgPDwgLWUsIDApO1xuICAgICAgICByZXN1bHQgPSBkYXRhVG9TdHJpbmcoZGF0YSkgKyByZXBlYXQuY2FsbCgnMCcsIGZyYWN0RGlnaXRzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGZyYWN0RGlnaXRzID4gMCkge1xuICAgICAgayA9IHJlc3VsdC5sZW5ndGg7XG4gICAgICByZXN1bHQgPSBzaWduICsgKGsgPD0gZnJhY3REaWdpdHNcbiAgICAgICAgPyAnMC4nICsgcmVwZWF0LmNhbGwoJzAnLCBmcmFjdERpZ2l0cyAtIGspICsgcmVzdWx0XG4gICAgICAgIDogcmVzdWx0LnNsaWNlKDAsIGsgLSBmcmFjdERpZ2l0cykgKyAnLicgKyByZXN1bHQuc2xpY2UoayAtIGZyYWN0RGlnaXRzKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3VsdCA9IHNpZ24gKyByZXN1bHQ7XG4gICAgfSByZXR1cm4gcmVzdWx0O1xuICB9XG59KTtcbiIsInZhciAkID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2V4cG9ydCcpO1xudmFyIHBhcnNlRmxvYXRJbXBsZW1lbnRhdGlvbiA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9udW1iZXItcGFyc2UtZmxvYXQnKTtcblxuLy8gYHBhcnNlRmxvYXRgIG1ldGhvZFxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1wYXJzZWZsb2F0LXN0cmluZ1xuJCh7IGdsb2JhbDogdHJ1ZSwgZm9yY2VkOiBwYXJzZUZsb2F0ICE9IHBhcnNlRmxvYXRJbXBsZW1lbnRhdGlvbiB9LCB7XG4gIHBhcnNlRmxvYXQ6IHBhcnNlRmxvYXRJbXBsZW1lbnRhdGlvblxufSk7XG4iLCJ2YXIgREVTQ1JJUFRPUlMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZGVzY3JpcHRvcnMnKTtcbnZhciBnbG9iYWwgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZ2xvYmFsJyk7XG52YXIgaXNGb3JjZWQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaXMtZm9yY2VkJyk7XG52YXIgaW5oZXJpdElmUmVxdWlyZWQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaW5oZXJpdC1pZi1yZXF1aXJlZCcpO1xudmFyIGRlZmluZVByb3BlcnR5ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL29iamVjdC1kZWZpbmUtcHJvcGVydHknKS5mO1xudmFyIGdldE93blByb3BlcnR5TmFtZXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvb2JqZWN0LWdldC1vd24tcHJvcGVydHktbmFtZXMnKS5mO1xudmFyIGlzUmVnRXhwID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2lzLXJlZ2V4cCcpO1xudmFyIGdldEZsYWdzID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3JlZ2V4cC1mbGFncycpO1xudmFyIHN0aWNreUhlbHBlcnMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvcmVnZXhwLXN0aWNreS1oZWxwZXJzJyk7XG52YXIgcmVkZWZpbmUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvcmVkZWZpbmUnKTtcbnZhciBmYWlscyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9mYWlscycpO1xudmFyIGVuZm9yY2VJbnRlcm5hbFN0YXRlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2ludGVybmFsLXN0YXRlJykuZW5mb3JjZTtcbnZhciBzZXRTcGVjaWVzID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3NldC1zcGVjaWVzJyk7XG52YXIgd2VsbEtub3duU3ltYm9sID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3dlbGwta25vd24tc3ltYm9sJyk7XG5cbnZhciBNQVRDSCA9IHdlbGxLbm93blN5bWJvbCgnbWF0Y2gnKTtcbnZhciBOYXRpdmVSZWdFeHAgPSBnbG9iYWwuUmVnRXhwO1xudmFyIFJlZ0V4cFByb3RvdHlwZSA9IE5hdGl2ZVJlZ0V4cC5wcm90b3R5cGU7XG52YXIgcmUxID0gL2EvZztcbnZhciByZTIgPSAvYS9nO1xuXG4vLyBcIm5ld1wiIHNob3VsZCBjcmVhdGUgYSBuZXcgb2JqZWN0LCBvbGQgd2Via2l0IGJ1Z1xudmFyIENPUlJFQ1RfTkVXID0gbmV3IE5hdGl2ZVJlZ0V4cChyZTEpICE9PSByZTE7XG5cbnZhciBVTlNVUFBPUlRFRF9ZID0gc3RpY2t5SGVscGVycy5VTlNVUFBPUlRFRF9ZO1xuXG52YXIgRk9SQ0VEID0gREVTQ1JJUFRPUlMgJiYgaXNGb3JjZWQoJ1JlZ0V4cCcsICghQ09SUkVDVF9ORVcgfHwgVU5TVVBQT1JURURfWSB8fCBmYWlscyhmdW5jdGlvbiAoKSB7XG4gIHJlMltNQVRDSF0gPSBmYWxzZTtcbiAgLy8gUmVnRXhwIGNvbnN0cnVjdG9yIGNhbiBhbHRlciBmbGFncyBhbmQgSXNSZWdFeHAgd29ya3MgY29ycmVjdCB3aXRoIEBAbWF0Y2hcbiAgcmV0dXJuIE5hdGl2ZVJlZ0V4cChyZTEpICE9IHJlMSB8fCBOYXRpdmVSZWdFeHAocmUyKSA9PSByZTIgfHwgTmF0aXZlUmVnRXhwKHJlMSwgJ2knKSAhPSAnL2EvaSc7XG59KSkpO1xuXG4vLyBgUmVnRXhwYCBjb25zdHJ1Y3RvclxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1yZWdleHAtY29uc3RydWN0b3JcbmlmIChGT1JDRUQpIHtcbiAgdmFyIFJlZ0V4cFdyYXBwZXIgPSBmdW5jdGlvbiBSZWdFeHAocGF0dGVybiwgZmxhZ3MpIHtcbiAgICB2YXIgdGhpc0lzUmVnRXhwID0gdGhpcyBpbnN0YW5jZW9mIFJlZ0V4cFdyYXBwZXI7XG4gICAgdmFyIHBhdHRlcm5Jc1JlZ0V4cCA9IGlzUmVnRXhwKHBhdHRlcm4pO1xuICAgIHZhciBmbGFnc0FyZVVuZGVmaW5lZCA9IGZsYWdzID09PSB1bmRlZmluZWQ7XG4gICAgdmFyIHN0aWNreTtcblxuICAgIGlmICghdGhpc0lzUmVnRXhwICYmIHBhdHRlcm5Jc1JlZ0V4cCAmJiBwYXR0ZXJuLmNvbnN0cnVjdG9yID09PSBSZWdFeHBXcmFwcGVyICYmIGZsYWdzQXJlVW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gcGF0dGVybjtcbiAgICB9XG5cbiAgICBpZiAoQ09SUkVDVF9ORVcpIHtcbiAgICAgIGlmIChwYXR0ZXJuSXNSZWdFeHAgJiYgIWZsYWdzQXJlVW5kZWZpbmVkKSBwYXR0ZXJuID0gcGF0dGVybi5zb3VyY2U7XG4gICAgfSBlbHNlIGlmIChwYXR0ZXJuIGluc3RhbmNlb2YgUmVnRXhwV3JhcHBlcikge1xuICAgICAgaWYgKGZsYWdzQXJlVW5kZWZpbmVkKSBmbGFncyA9IGdldEZsYWdzLmNhbGwocGF0dGVybik7XG4gICAgICBwYXR0ZXJuID0gcGF0dGVybi5zb3VyY2U7XG4gICAgfVxuXG4gICAgaWYgKFVOU1VQUE9SVEVEX1kpIHtcbiAgICAgIHN0aWNreSA9ICEhZmxhZ3MgJiYgZmxhZ3MuaW5kZXhPZigneScpID4gLTE7XG4gICAgICBpZiAoc3RpY2t5KSBmbGFncyA9IGZsYWdzLnJlcGxhY2UoL3kvZywgJycpO1xuICAgIH1cblxuICAgIHZhciByZXN1bHQgPSBpbmhlcml0SWZSZXF1aXJlZChcbiAgICAgIENPUlJFQ1RfTkVXID8gbmV3IE5hdGl2ZVJlZ0V4cChwYXR0ZXJuLCBmbGFncykgOiBOYXRpdmVSZWdFeHAocGF0dGVybiwgZmxhZ3MpLFxuICAgICAgdGhpc0lzUmVnRXhwID8gdGhpcyA6IFJlZ0V4cFByb3RvdHlwZSxcbiAgICAgIFJlZ0V4cFdyYXBwZXJcbiAgICApO1xuXG4gICAgaWYgKFVOU1VQUE9SVEVEX1kgJiYgc3RpY2t5KSB7XG4gICAgICB2YXIgc3RhdGUgPSBlbmZvcmNlSW50ZXJuYWxTdGF0ZShyZXN1bHQpO1xuICAgICAgc3RhdGUuc3RpY2t5ID0gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuICB2YXIgcHJveHkgPSBmdW5jdGlvbiAoa2V5KSB7XG4gICAga2V5IGluIFJlZ0V4cFdyYXBwZXIgfHwgZGVmaW5lUHJvcGVydHkoUmVnRXhwV3JhcHBlciwga2V5LCB7XG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIE5hdGl2ZVJlZ0V4cFtrZXldOyB9LFxuICAgICAgc2V0OiBmdW5jdGlvbiAoaXQpIHsgTmF0aXZlUmVnRXhwW2tleV0gPSBpdDsgfVxuICAgIH0pO1xuICB9O1xuICB2YXIga2V5cyA9IGdldE93blByb3BlcnR5TmFtZXMoTmF0aXZlUmVnRXhwKTtcbiAgdmFyIGluZGV4ID0gMDtcbiAgd2hpbGUgKGtleXMubGVuZ3RoID4gaW5kZXgpIHByb3h5KGtleXNbaW5kZXgrK10pO1xuICBSZWdFeHBQcm90b3R5cGUuY29uc3RydWN0b3IgPSBSZWdFeHBXcmFwcGVyO1xuICBSZWdFeHBXcmFwcGVyLnByb3RvdHlwZSA9IFJlZ0V4cFByb3RvdHlwZTtcbiAgcmVkZWZpbmUoZ2xvYmFsLCAnUmVnRXhwJywgUmVnRXhwV3JhcHBlcik7XG59XG5cbi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtZ2V0LXJlZ2V4cC1AQHNwZWNpZXNcbnNldFNwZWNpZXMoJ1JlZ0V4cCcpO1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIHJlZGVmaW5lID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3JlZGVmaW5lJyk7XG52YXIgYW5PYmplY3QgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvYW4tb2JqZWN0Jyk7XG52YXIgZmFpbHMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZmFpbHMnKTtcbnZhciBmbGFncyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9yZWdleHAtZmxhZ3MnKTtcblxudmFyIFRPX1NUUklORyA9ICd0b1N0cmluZyc7XG52YXIgUmVnRXhwUHJvdG90eXBlID0gUmVnRXhwLnByb3RvdHlwZTtcbnZhciBuYXRpdmVUb1N0cmluZyA9IFJlZ0V4cFByb3RvdHlwZVtUT19TVFJJTkddO1xuXG52YXIgTk9UX0dFTkVSSUMgPSBmYWlscyhmdW5jdGlvbiAoKSB7IHJldHVybiBuYXRpdmVUb1N0cmluZy5jYWxsKHsgc291cmNlOiAnYScsIGZsYWdzOiAnYicgfSkgIT0gJy9hL2InOyB9KTtcbi8vIEZGNDQtIFJlZ0V4cCN0b1N0cmluZyBoYXMgYSB3cm9uZyBuYW1lXG52YXIgSU5DT1JSRUNUX05BTUUgPSBuYXRpdmVUb1N0cmluZy5uYW1lICE9IFRPX1NUUklORztcblxuLy8gYFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmdgIG1ldGhvZFxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1yZWdleHAucHJvdG90eXBlLnRvc3RyaW5nXG5pZiAoTk9UX0dFTkVSSUMgfHwgSU5DT1JSRUNUX05BTUUpIHtcbiAgcmVkZWZpbmUoUmVnRXhwLnByb3RvdHlwZSwgVE9fU1RSSU5HLCBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgICB2YXIgUiA9IGFuT2JqZWN0KHRoaXMpO1xuICAgIHZhciBwID0gU3RyaW5nKFIuc291cmNlKTtcbiAgICB2YXIgcmYgPSBSLmZsYWdzO1xuICAgIHZhciBmID0gU3RyaW5nKHJmID09PSB1bmRlZmluZWQgJiYgUiBpbnN0YW5jZW9mIFJlZ0V4cCAmJiAhKCdmbGFncycgaW4gUmVnRXhwUHJvdG90eXBlKSA/IGZsYWdzLmNhbGwoUikgOiByZik7XG4gICAgcmV0dXJuICcvJyArIHAgKyAnLycgKyBmO1xuICB9LCB7IHVuc2FmZTogdHJ1ZSB9KTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcbnZhciBmaXhSZWdFeHBXZWxsS25vd25TeW1ib2xMb2dpYyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9maXgtcmVnZXhwLXdlbGwta25vd24tc3ltYm9sLWxvZ2ljJyk7XG52YXIgYW5PYmplY3QgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvYW4tb2JqZWN0Jyk7XG52YXIgcmVxdWlyZU9iamVjdENvZXJjaWJsZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9yZXF1aXJlLW9iamVjdC1jb2VyY2libGUnKTtcbnZhciBzYW1lVmFsdWUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvc2FtZS12YWx1ZScpO1xudmFyIHJlZ0V4cEV4ZWMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvcmVnZXhwLWV4ZWMtYWJzdHJhY3QnKTtcblxuLy8gQEBzZWFyY2ggbG9naWNcbmZpeFJlZ0V4cFdlbGxLbm93blN5bWJvbExvZ2ljKCdzZWFyY2gnLCAxLCBmdW5jdGlvbiAoU0VBUkNILCBuYXRpdmVTZWFyY2gsIG1heWJlQ2FsbE5hdGl2ZSkge1xuICByZXR1cm4gW1xuICAgIC8vIGBTdHJpbmcucHJvdG90eXBlLnNlYXJjaGAgbWV0aG9kXG4gICAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1zdHJpbmcucHJvdG90eXBlLnNlYXJjaFxuICAgIGZ1bmN0aW9uIHNlYXJjaChyZWdleHApIHtcbiAgICAgIHZhciBPID0gcmVxdWlyZU9iamVjdENvZXJjaWJsZSh0aGlzKTtcbiAgICAgIHZhciBzZWFyY2hlciA9IHJlZ2V4cCA9PSB1bmRlZmluZWQgPyB1bmRlZmluZWQgOiByZWdleHBbU0VBUkNIXTtcbiAgICAgIHJldHVybiBzZWFyY2hlciAhPT0gdW5kZWZpbmVkID8gc2VhcmNoZXIuY2FsbChyZWdleHAsIE8pIDogbmV3IFJlZ0V4cChyZWdleHApW1NFQVJDSF0oU3RyaW5nKE8pKTtcbiAgICB9LFxuICAgIC8vIGBSZWdFeHAucHJvdG90eXBlW0BAc2VhcmNoXWAgbWV0aG9kXG4gICAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1yZWdleHAucHJvdG90eXBlLUBAc2VhcmNoXG4gICAgZnVuY3Rpb24gKHJlZ2V4cCkge1xuICAgICAgdmFyIHJlcyA9IG1heWJlQ2FsbE5hdGl2ZShuYXRpdmVTZWFyY2gsIHJlZ2V4cCwgdGhpcyk7XG4gICAgICBpZiAocmVzLmRvbmUpIHJldHVybiByZXMudmFsdWU7XG5cbiAgICAgIHZhciByeCA9IGFuT2JqZWN0KHJlZ2V4cCk7XG4gICAgICB2YXIgUyA9IFN0cmluZyh0aGlzKTtcblxuICAgICAgdmFyIHByZXZpb3VzTGFzdEluZGV4ID0gcngubGFzdEluZGV4O1xuICAgICAgaWYgKCFzYW1lVmFsdWUocHJldmlvdXNMYXN0SW5kZXgsIDApKSByeC5sYXN0SW5kZXggPSAwO1xuICAgICAgdmFyIHJlc3VsdCA9IHJlZ0V4cEV4ZWMocngsIFMpO1xuICAgICAgaWYgKCFzYW1lVmFsdWUocngubGFzdEluZGV4LCBwcmV2aW91c0xhc3RJbmRleCkpIHJ4Lmxhc3RJbmRleCA9IHByZXZpb3VzTGFzdEluZGV4O1xuICAgICAgcmV0dXJuIHJlc3VsdCA9PT0gbnVsbCA/IC0xIDogcmVzdWx0LmluZGV4O1xuICAgIH1cbiAgXTtcbn0pO1xuIiwidmFyICQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZXhwb3J0Jyk7XG52YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2dsb2JhbCcpO1xudmFyIHVzZXJBZ2VudCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9lbmdpbmUtdXNlci1hZ2VudCcpO1xuXG52YXIgc2xpY2UgPSBbXS5zbGljZTtcbnZhciBNU0lFID0gL01TSUUgLlxcLi8udGVzdCh1c2VyQWdlbnQpOyAvLyA8LSBkaXJ0eSBpZTktIGNoZWNrXG5cbnZhciB3cmFwID0gZnVuY3Rpb24gKHNjaGVkdWxlcikge1xuICByZXR1cm4gZnVuY3Rpb24gKGhhbmRsZXIsIHRpbWVvdXQgLyogLCAuLi5hcmd1bWVudHMgKi8pIHtcbiAgICB2YXIgYm91bmRBcmdzID0gYXJndW1lbnRzLmxlbmd0aCA+IDI7XG4gICAgdmFyIGFyZ3MgPSBib3VuZEFyZ3MgPyBzbGljZS5jYWxsKGFyZ3VtZW50cywgMikgOiB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIHNjaGVkdWxlcihib3VuZEFyZ3MgPyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tbmV3LWZ1bmMgLS0gc3BlYyByZXF1aXJlbWVudFxuICAgICAgKHR5cGVvZiBoYW5kbGVyID09ICdmdW5jdGlvbicgPyBoYW5kbGVyIDogRnVuY3Rpb24oaGFuZGxlcikpLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgIH0gOiBoYW5kbGVyLCB0aW1lb3V0KTtcbiAgfTtcbn07XG5cbi8vIGllOS0gc2V0VGltZW91dCAmIHNldEludGVydmFsIGFkZGl0aW9uYWwgcGFyYW1ldGVycyBmaXhcbi8vIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvbXVsdGlwYWdlL3RpbWVycy1hbmQtdXNlci1wcm9tcHRzLmh0bWwjdGltZXJzXG4kKHsgZ2xvYmFsOiB0cnVlLCBiaW5kOiB0cnVlLCBmb3JjZWQ6IE1TSUUgfSwge1xuICAvLyBgc2V0VGltZW91dGAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvbXVsdGlwYWdlL3RpbWVycy1hbmQtdXNlci1wcm9tcHRzLmh0bWwjZG9tLXNldHRpbWVvdXRcbiAgc2V0VGltZW91dDogd3JhcChnbG9iYWwuc2V0VGltZW91dCksXG4gIC8vIGBzZXRJbnRlcnZhbGAgbWV0aG9kXG4gIC8vIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvbXVsdGlwYWdlL3RpbWVycy1hbmQtdXNlci1wcm9tcHRzLmh0bWwjZG9tLXNldGludGVydmFsXG4gIHNldEludGVydmFsOiB3cmFwKGdsb2JhbC5zZXRJbnRlcnZhbClcbn0pO1xuIiwiLyogQHByZXNlcnZlXG4gKiBMZWFmbGV0IDEuOS40LCBhIEpTIGxpYnJhcnkgZm9yIGludGVyYWN0aXZlIG1hcHMuIGh0dHBzOi8vbGVhZmxldGpzLmNvbVxuICogKGMpIDIwMTAtMjAyMyBWbGFkaW1pciBBZ2Fmb25raW4sIChjKSAyMDEwLTIwMTEgQ2xvdWRNYWRlXG4gKi9cblxuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzKSA6XG4gIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnXSwgZmFjdG9yeSkgOlxuICAoZ2xvYmFsID0gdHlwZW9mIGdsb2JhbFRoaXMgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsVGhpcyA6IGdsb2JhbCB8fCBzZWxmLCBmYWN0b3J5KGdsb2JhbC5sZWFmbGV0ID0ge30pKTtcbn0pKHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cykgeyAndXNlIHN0cmljdCc7XG5cbiAgdmFyIHZlcnNpb24gPSBcIjEuOS40XCI7XG5cbiAgLypcclxuICAgKiBAbmFtZXNwYWNlIFV0aWxcclxuICAgKlxyXG4gICAqIFZhcmlvdXMgdXRpbGl0eSBmdW5jdGlvbnMsIHVzZWQgYnkgTGVhZmxldCBpbnRlcm5hbGx5LlxyXG4gICAqL1xyXG5cclxuICAvLyBAZnVuY3Rpb24gZXh0ZW5kKGRlc3Q6IE9iamVjdCwgc3JjPzogT2JqZWN0KTogT2JqZWN0XHJcbiAgLy8gTWVyZ2VzIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBgc3JjYCBvYmplY3QgKG9yIG11bHRpcGxlIG9iamVjdHMpIGludG8gYGRlc3RgIG9iamVjdCBhbmQgcmV0dXJucyB0aGUgbGF0dGVyLiBIYXMgYW4gYEwuZXh0ZW5kYCBzaG9ydGN1dC5cclxuICBmdW5jdGlvbiBleHRlbmQoZGVzdCkge1xyXG4gIFx0dmFyIGksIGosIGxlbiwgc3JjO1xyXG5cclxuICBcdGZvciAoaiA9IDEsIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGogPCBsZW47IGorKykge1xyXG4gIFx0XHRzcmMgPSBhcmd1bWVudHNbal07XHJcbiAgXHRcdGZvciAoaSBpbiBzcmMpIHtcclxuICBcdFx0XHRkZXN0W2ldID0gc3JjW2ldO1xyXG4gIFx0XHR9XHJcbiAgXHR9XHJcbiAgXHRyZXR1cm4gZGVzdDtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBjcmVhdGUocHJvdG86IE9iamVjdCwgcHJvcGVydGllcz86IE9iamVjdCk6IE9iamVjdFxyXG4gIC8vIENvbXBhdGliaWxpdHkgcG9seWZpbGwgZm9yIFtPYmplY3QuY3JlYXRlXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9PYmplY3QvY3JlYXRlKVxyXG4gIHZhciBjcmVhdGUkMiA9IE9iamVjdC5jcmVhdGUgfHwgKGZ1bmN0aW9uICgpIHtcclxuICBcdGZ1bmN0aW9uIEYoKSB7fVxyXG4gIFx0cmV0dXJuIGZ1bmN0aW9uIChwcm90bykge1xyXG4gIFx0XHRGLnByb3RvdHlwZSA9IHByb3RvO1xyXG4gIFx0XHRyZXR1cm4gbmV3IEYoKTtcclxuICBcdH07XHJcbiAgfSkoKTtcclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGJpbmQoZm46IEZ1bmN0aW9uLCDigKYpOiBGdW5jdGlvblxyXG4gIC8vIFJldHVybnMgYSBuZXcgZnVuY3Rpb24gYm91bmQgdG8gdGhlIGFyZ3VtZW50cyBwYXNzZWQsIGxpa2UgW0Z1bmN0aW9uLnByb3RvdHlwZS5iaW5kXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9GdW5jdGlvbi9iaW5kKS5cclxuICAvLyBIYXMgYSBgTC5iaW5kKClgIHNob3J0Y3V0LlxyXG4gIGZ1bmN0aW9uIGJpbmQoZm4sIG9iaikge1xyXG4gIFx0dmFyIHNsaWNlID0gQXJyYXkucHJvdG90eXBlLnNsaWNlO1xyXG5cclxuICBcdGlmIChmbi5iaW5kKSB7XHJcbiAgXHRcdHJldHVybiBmbi5iaW5kLmFwcGx5KGZuLCBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xyXG4gIFx0fVxyXG5cclxuICBcdHZhciBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xyXG5cclxuICBcdHJldHVybiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiBmbi5hcHBseShvYmosIGFyZ3MubGVuZ3RoID8gYXJncy5jb25jYXQoc2xpY2UuY2FsbChhcmd1bWVudHMpKSA6IGFyZ3VtZW50cyk7XHJcbiAgXHR9O1xyXG4gIH1cclxuXHJcbiAgLy8gQHByb3BlcnR5IGxhc3RJZDogTnVtYmVyXHJcbiAgLy8gTGFzdCB1bmlxdWUgSUQgdXNlZCBieSBbYHN0YW1wKClgXSgjdXRpbC1zdGFtcClcclxuICB2YXIgbGFzdElkID0gMDtcclxuXHJcbiAgLy8gQGZ1bmN0aW9uIHN0YW1wKG9iajogT2JqZWN0KTogTnVtYmVyXHJcbiAgLy8gUmV0dXJucyB0aGUgdW5pcXVlIElEIG9mIGFuIG9iamVjdCwgYXNzaWduaW5nIGl0IG9uZSBpZiBpdCBkb2Vzbid0IGhhdmUgaXQuXHJcbiAgZnVuY3Rpb24gc3RhbXAob2JqKSB7XHJcbiAgXHRpZiAoISgnX2xlYWZsZXRfaWQnIGluIG9iaikpIHtcclxuICBcdFx0b2JqWydfbGVhZmxldF9pZCddID0gKytsYXN0SWQ7XHJcbiAgXHR9XHJcbiAgXHRyZXR1cm4gb2JqLl9sZWFmbGV0X2lkO1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIHRocm90dGxlKGZuOiBGdW5jdGlvbiwgdGltZTogTnVtYmVyLCBjb250ZXh0OiBPYmplY3QpOiBGdW5jdGlvblxyXG4gIC8vIFJldHVybnMgYSBmdW5jdGlvbiB3aGljaCBleGVjdXRlcyBmdW5jdGlvbiBgZm5gIHdpdGggdGhlIGdpdmVuIHNjb3BlIGBjb250ZXh0YFxyXG4gIC8vIChzbyB0aGF0IHRoZSBgdGhpc2Aga2V5d29yZCByZWZlcnMgdG8gYGNvbnRleHRgIGluc2lkZSBgZm5gJ3MgY29kZSkuIFRoZSBmdW5jdGlvblxyXG4gIC8vIGBmbmAgd2lsbCBiZSBjYWxsZWQgbm8gbW9yZSB0aGFuIG9uZSB0aW1lIHBlciBnaXZlbiBhbW91bnQgb2YgYHRpbWVgLiBUaGUgYXJndW1lbnRzXHJcbiAgLy8gcmVjZWl2ZWQgYnkgdGhlIGJvdW5kIGZ1bmN0aW9uIHdpbGwgYmUgYW55IGFyZ3VtZW50cyBwYXNzZWQgd2hlbiBiaW5kaW5nIHRoZVxyXG4gIC8vIGZ1bmN0aW9uLCBmb2xsb3dlZCBieSBhbnkgYXJndW1lbnRzIHBhc3NlZCB3aGVuIGludm9raW5nIHRoZSBib3VuZCBmdW5jdGlvbi5cclxuICAvLyBIYXMgYW4gYEwudGhyb3R0bGVgIHNob3J0Y3V0LlxyXG4gIGZ1bmN0aW9uIHRocm90dGxlKGZuLCB0aW1lLCBjb250ZXh0KSB7XHJcbiAgXHR2YXIgbG9jaywgYXJncywgd3JhcHBlckZuLCBsYXRlcjtcclxuXHJcbiAgXHRsYXRlciA9IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0Ly8gcmVzZXQgbG9jayBhbmQgY2FsbCBpZiBxdWV1ZWRcclxuICBcdFx0bG9jayA9IGZhbHNlO1xyXG4gIFx0XHRpZiAoYXJncykge1xyXG4gIFx0XHRcdHdyYXBwZXJGbi5hcHBseShjb250ZXh0LCBhcmdzKTtcclxuICBcdFx0XHRhcmdzID0gZmFsc2U7XHJcbiAgXHRcdH1cclxuICBcdH07XHJcblxyXG4gIFx0d3JhcHBlckZuID0gZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRpZiAobG9jaykge1xyXG4gIFx0XHRcdC8vIGNhbGxlZCB0b28gc29vbiwgcXVldWUgdG8gY2FsbCBsYXRlclxyXG4gIFx0XHRcdGFyZ3MgPSBhcmd1bWVudHM7XHJcblxyXG4gIFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdC8vIGNhbGwgYW5kIGxvY2sgdW50aWwgbGF0ZXJcclxuICBcdFx0XHRmbi5hcHBseShjb250ZXh0LCBhcmd1bWVudHMpO1xyXG4gIFx0XHRcdHNldFRpbWVvdXQobGF0ZXIsIHRpbWUpO1xyXG4gIFx0XHRcdGxvY2sgPSB0cnVlO1xyXG4gIFx0XHR9XHJcbiAgXHR9O1xyXG5cclxuICBcdHJldHVybiB3cmFwcGVyRm47XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gd3JhcE51bShudW06IE51bWJlciwgcmFuZ2U6IE51bWJlcltdLCBpbmNsdWRlTWF4PzogQm9vbGVhbik6IE51bWJlclxyXG4gIC8vIFJldHVybnMgdGhlIG51bWJlciBgbnVtYCBtb2R1bG8gYHJhbmdlYCBpbiBzdWNoIGEgd2F5IHNvIGl0IGxpZXMgd2l0aGluXHJcbiAgLy8gYHJhbmdlWzBdYCBhbmQgYHJhbmdlWzFdYC4gVGhlIHJldHVybmVkIHZhbHVlIHdpbGwgYmUgYWx3YXlzIHNtYWxsZXIgdGhhblxyXG4gIC8vIGByYW5nZVsxXWAgdW5sZXNzIGBpbmNsdWRlTWF4YCBpcyBzZXQgdG8gYHRydWVgLlxyXG4gIGZ1bmN0aW9uIHdyYXBOdW0oeCwgcmFuZ2UsIGluY2x1ZGVNYXgpIHtcclxuICBcdHZhciBtYXggPSByYW5nZVsxXSxcclxuICBcdCAgICBtaW4gPSByYW5nZVswXSxcclxuICBcdCAgICBkID0gbWF4IC0gbWluO1xyXG4gIFx0cmV0dXJuIHggPT09IG1heCAmJiBpbmNsdWRlTWF4ID8geCA6ICgoeCAtIG1pbikgJSBkICsgZCkgJSBkICsgbWluO1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGZhbHNlRm4oKTogRnVuY3Rpb25cclxuICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24gd2hpY2ggYWx3YXlzIHJldHVybnMgYGZhbHNlYC5cclxuICBmdW5jdGlvbiBmYWxzZUZuKCkgeyByZXR1cm4gZmFsc2U7IH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGZvcm1hdE51bShudW06IE51bWJlciwgcHJlY2lzaW9uPzogTnVtYmVyfGZhbHNlKTogTnVtYmVyXHJcbiAgLy8gUmV0dXJucyB0aGUgbnVtYmVyIGBudW1gIHJvdW5kZWQgd2l0aCBzcGVjaWZpZWQgYHByZWNpc2lvbmAuXHJcbiAgLy8gVGhlIGRlZmF1bHQgYHByZWNpc2lvbmAgdmFsdWUgaXMgNiBkZWNpbWFsIHBsYWNlcy5cclxuICAvLyBgZmFsc2VgIGNhbiBiZSBwYXNzZWQgdG8gc2tpcCBhbnkgcHJvY2Vzc2luZyAoY2FuIGJlIHVzZWZ1bCB0byBhdm9pZCByb3VuZC1vZmYgZXJyb3JzKS5cclxuICBmdW5jdGlvbiBmb3JtYXROdW0obnVtLCBwcmVjaXNpb24pIHtcclxuICBcdGlmIChwcmVjaXNpb24gPT09IGZhbHNlKSB7IHJldHVybiBudW07IH1cclxuICBcdHZhciBwb3cgPSBNYXRoLnBvdygxMCwgcHJlY2lzaW9uID09PSB1bmRlZmluZWQgPyA2IDogcHJlY2lzaW9uKTtcclxuICBcdHJldHVybiBNYXRoLnJvdW5kKG51bSAqIHBvdykgLyBwb3c7XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gdHJpbShzdHI6IFN0cmluZyk6IFN0cmluZ1xyXG4gIC8vIENvbXBhdGliaWxpdHkgcG9seWZpbGwgZm9yIFtTdHJpbmcucHJvdG90eXBlLnRyaW1dKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL1N0cmluZy9UcmltKVxyXG4gIGZ1bmN0aW9uIHRyaW0oc3RyKSB7XHJcbiAgXHRyZXR1cm4gc3RyLnRyaW0gPyBzdHIudHJpbSgpIDogc3RyLnJlcGxhY2UoL15cXHMrfFxccyskL2csICcnKTtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBzcGxpdFdvcmRzKHN0cjogU3RyaW5nKTogU3RyaW5nW11cclxuICAvLyBUcmltcyBhbmQgc3BsaXRzIHRoZSBzdHJpbmcgb24gd2hpdGVzcGFjZSBhbmQgcmV0dXJucyB0aGUgYXJyYXkgb2YgcGFydHMuXHJcbiAgZnVuY3Rpb24gc3BsaXRXb3JkcyhzdHIpIHtcclxuICBcdHJldHVybiB0cmltKHN0cikuc3BsaXQoL1xccysvKTtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBzZXRPcHRpb25zKG9iajogT2JqZWN0LCBvcHRpb25zOiBPYmplY3QpOiBPYmplY3RcclxuICAvLyBNZXJnZXMgdGhlIGdpdmVuIHByb3BlcnRpZXMgdG8gdGhlIGBvcHRpb25zYCBvZiB0aGUgYG9iamAgb2JqZWN0LCByZXR1cm5pbmcgdGhlIHJlc3VsdGluZyBvcHRpb25zLiBTZWUgYENsYXNzIG9wdGlvbnNgLiBIYXMgYW4gYEwuc2V0T3B0aW9uc2Agc2hvcnRjdXQuXHJcbiAgZnVuY3Rpb24gc2V0T3B0aW9ucyhvYmosIG9wdGlvbnMpIHtcclxuICBcdGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgJ29wdGlvbnMnKSkge1xyXG4gIFx0XHRvYmoub3B0aW9ucyA9IG9iai5vcHRpb25zID8gY3JlYXRlJDIob2JqLm9wdGlvbnMpIDoge307XHJcbiAgXHR9XHJcbiAgXHRmb3IgKHZhciBpIGluIG9wdGlvbnMpIHtcclxuICBcdFx0b2JqLm9wdGlvbnNbaV0gPSBvcHRpb25zW2ldO1xyXG4gIFx0fVxyXG4gIFx0cmV0dXJuIG9iai5vcHRpb25zO1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGdldFBhcmFtU3RyaW5nKG9iajogT2JqZWN0LCBleGlzdGluZ1VybD86IFN0cmluZywgdXBwZXJjYXNlPzogQm9vbGVhbik6IFN0cmluZ1xyXG4gIC8vIENvbnZlcnRzIGFuIG9iamVjdCBpbnRvIGEgcGFyYW1ldGVyIFVSTCBzdHJpbmcsIGUuZy4gYHthOiBcImZvb1wiLCBiOiBcImJhclwifWBcclxuICAvLyB0cmFuc2xhdGVzIHRvIGAnP2E9Zm9vJmI9YmFyJ2AuIElmIGBleGlzdGluZ1VybGAgaXMgc2V0LCB0aGUgcGFyYW1ldGVycyB3aWxsXHJcbiAgLy8gYmUgYXBwZW5kZWQgYXQgdGhlIGVuZC4gSWYgYHVwcGVyY2FzZWAgaXMgYHRydWVgLCB0aGUgcGFyYW1ldGVyIG5hbWVzIHdpbGxcclxuICAvLyBiZSB1cHBlcmNhc2VkIChlLmcuIGAnP0E9Zm9vJkI9YmFyJ2ApXHJcbiAgZnVuY3Rpb24gZ2V0UGFyYW1TdHJpbmcob2JqLCBleGlzdGluZ1VybCwgdXBwZXJjYXNlKSB7XHJcbiAgXHR2YXIgcGFyYW1zID0gW107XHJcbiAgXHRmb3IgKHZhciBpIGluIG9iaikge1xyXG4gIFx0XHRwYXJhbXMucHVzaChlbmNvZGVVUklDb21wb25lbnQodXBwZXJjYXNlID8gaS50b1VwcGVyQ2FzZSgpIDogaSkgKyAnPScgKyBlbmNvZGVVUklDb21wb25lbnQob2JqW2ldKSk7XHJcbiAgXHR9XHJcbiAgXHRyZXR1cm4gKCghZXhpc3RpbmdVcmwgfHwgZXhpc3RpbmdVcmwuaW5kZXhPZignPycpID09PSAtMSkgPyAnPycgOiAnJicpICsgcGFyYW1zLmpvaW4oJyYnKTtcclxuICB9XHJcblxyXG4gIHZhciB0ZW1wbGF0ZVJlID0gL1xceyAqKFtcXHdfIC1dKykgKlxcfS9nO1xyXG5cclxuICAvLyBAZnVuY3Rpb24gdGVtcGxhdGUoc3RyOiBTdHJpbmcsIGRhdGE6IE9iamVjdCk6IFN0cmluZ1xyXG4gIC8vIFNpbXBsZSB0ZW1wbGF0aW5nIGZhY2lsaXR5LCBhY2NlcHRzIGEgdGVtcGxhdGUgc3RyaW5nIG9mIHRoZSBmb3JtIGAnSGVsbG8ge2F9LCB7Yn0nYFxyXG4gIC8vIGFuZCBhIGRhdGEgb2JqZWN0IGxpa2UgYHthOiAnZm9vJywgYjogJ2Jhcid9YCwgcmV0dXJucyBldmFsdWF0ZWQgc3RyaW5nXHJcbiAgLy8gYCgnSGVsbG8gZm9vLCBiYXInKWAuIFlvdSBjYW4gYWxzbyBzcGVjaWZ5IGZ1bmN0aW9ucyBpbnN0ZWFkIG9mIHN0cmluZ3MgZm9yXHJcbiAgLy8gZGF0YSB2YWx1ZXMg4oCUIHRoZXkgd2lsbCBiZSBldmFsdWF0ZWQgcGFzc2luZyBgZGF0YWAgYXMgYW4gYXJndW1lbnQuXHJcbiAgZnVuY3Rpb24gdGVtcGxhdGUoc3RyLCBkYXRhKSB7XHJcbiAgXHRyZXR1cm4gc3RyLnJlcGxhY2UodGVtcGxhdGVSZSwgZnVuY3Rpb24gKHN0ciwga2V5KSB7XHJcbiAgXHRcdHZhciB2YWx1ZSA9IGRhdGFba2V5XTtcclxuXHJcbiAgXHRcdGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdObyB2YWx1ZSBwcm92aWRlZCBmb3IgdmFyaWFibGUgJyArIHN0cik7XHJcblxyXG4gIFx0XHR9IGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gIFx0XHRcdHZhbHVlID0gdmFsdWUoZGF0YSk7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHZhbHVlO1xyXG4gIFx0fSk7XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gaXNBcnJheShvYmopOiBCb29sZWFuXHJcbiAgLy8gQ29tcGF0aWJpbGl0eSBwb2x5ZmlsbCBmb3IgW0FycmF5LmlzQXJyYXldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0FycmF5L2lzQXJyYXkpXHJcbiAgdmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5IHx8IGZ1bmN0aW9uIChvYmopIHtcclxuICBcdHJldHVybiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG9iaikgPT09ICdbb2JqZWN0IEFycmF5XScpO1xyXG4gIH07XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBpbmRleE9mKGFycmF5OiBBcnJheSwgZWw6IE9iamVjdCk6IE51bWJlclxyXG4gIC8vIENvbXBhdGliaWxpdHkgcG9seWZpbGwgZm9yIFtBcnJheS5wcm90b3R5cGUuaW5kZXhPZl0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvQXJyYXkvaW5kZXhPZilcclxuICBmdW5jdGlvbiBpbmRleE9mKGFycmF5LCBlbCkge1xyXG4gIFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xyXG4gIFx0XHRpZiAoYXJyYXlbaV0gPT09IGVsKSB7IHJldHVybiBpOyB9XHJcbiAgXHR9XHJcbiAgXHRyZXR1cm4gLTE7XHJcbiAgfVxyXG5cclxuICAvLyBAcHJvcGVydHkgZW1wdHlJbWFnZVVybDogU3RyaW5nXHJcbiAgLy8gRGF0YSBVUkkgc3RyaW5nIGNvbnRhaW5pbmcgYSBiYXNlNjQtZW5jb2RlZCBlbXB0eSBHSUYgaW1hZ2UuXHJcbiAgLy8gVXNlZCBhcyBhIGhhY2sgdG8gZnJlZSBtZW1vcnkgZnJvbSB1bnVzZWQgaW1hZ2VzIG9uIFdlYktpdC1wb3dlcmVkXHJcbiAgLy8gbW9iaWxlIGRldmljZXMgKGJ5IHNldHRpbmcgaW1hZ2UgYHNyY2AgdG8gdGhpcyBzdHJpbmcpLlxyXG4gIHZhciBlbXB0eUltYWdlVXJsID0gJ2RhdGE6aW1hZ2UvZ2lmO2Jhc2U2NCxSMGxHT0RsaEFRQUJBQUQvQUN3QUFBQUFBUUFCQUFBQ0FEcz0nO1xyXG5cclxuICAvLyBpbnNwaXJlZCBieSBodHRwczovL3BhdWxpcmlzaC5jb20vMjAxMS9yZXF1ZXN0YW5pbWF0aW9uZnJhbWUtZm9yLXNtYXJ0LWFuaW1hdGluZy9cclxuXHJcbiAgZnVuY3Rpb24gZ2V0UHJlZml4ZWQobmFtZSkge1xyXG4gIFx0cmV0dXJuIHdpbmRvd1snd2Via2l0JyArIG5hbWVdIHx8IHdpbmRvd1snbW96JyArIG5hbWVdIHx8IHdpbmRvd1snbXMnICsgbmFtZV07XHJcbiAgfVxyXG5cclxuICB2YXIgbGFzdFRpbWUgPSAwO1xyXG5cclxuICAvLyBmYWxsYmFjayBmb3IgSUUgNy04XHJcbiAgZnVuY3Rpb24gdGltZW91dERlZmVyKGZuKSB7XHJcbiAgXHR2YXIgdGltZSA9ICtuZXcgRGF0ZSgpLFxyXG4gIFx0ICAgIHRpbWVUb0NhbGwgPSBNYXRoLm1heCgwLCAxNiAtICh0aW1lIC0gbGFzdFRpbWUpKTtcclxuXHJcbiAgXHRsYXN0VGltZSA9IHRpbWUgKyB0aW1lVG9DYWxsO1xyXG4gIFx0cmV0dXJuIHdpbmRvdy5zZXRUaW1lb3V0KGZuLCB0aW1lVG9DYWxsKTtcclxuICB9XHJcblxyXG4gIHZhciByZXF1ZXN0Rm4gPSB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lIHx8IGdldFByZWZpeGVkKCdSZXF1ZXN0QW5pbWF0aW9uRnJhbWUnKSB8fCB0aW1lb3V0RGVmZXI7XHJcbiAgdmFyIGNhbmNlbEZuID0gd2luZG93LmNhbmNlbEFuaW1hdGlvbkZyYW1lIHx8IGdldFByZWZpeGVkKCdDYW5jZWxBbmltYXRpb25GcmFtZScpIHx8XHJcbiAgXHRcdGdldFByZWZpeGVkKCdDYW5jZWxSZXF1ZXN0QW5pbWF0aW9uRnJhbWUnKSB8fCBmdW5jdGlvbiAoaWQpIHsgd2luZG93LmNsZWFyVGltZW91dChpZCk7IH07XHJcblxyXG4gIC8vIEBmdW5jdGlvbiByZXF1ZXN0QW5pbUZyYW1lKGZuOiBGdW5jdGlvbiwgY29udGV4dD86IE9iamVjdCwgaW1tZWRpYXRlPzogQm9vbGVhbik6IE51bWJlclxyXG4gIC8vIFNjaGVkdWxlcyBgZm5gIHRvIGJlIGV4ZWN1dGVkIHdoZW4gdGhlIGJyb3dzZXIgcmVwYWludHMuIGBmbmAgaXMgYm91bmQgdG9cclxuICAvLyBgY29udGV4dGAgaWYgZ2l2ZW4uIFdoZW4gYGltbWVkaWF0ZWAgaXMgc2V0LCBgZm5gIGlzIGNhbGxlZCBpbW1lZGlhdGVseSBpZlxyXG4gIC8vIHRoZSBicm93c2VyIGRvZXNuJ3QgaGF2ZSBuYXRpdmUgc3VwcG9ydCBmb3JcclxuICAvLyBbYHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWVgXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvd2luZG93L3JlcXVlc3RBbmltYXRpb25GcmFtZSksXHJcbiAgLy8gb3RoZXJ3aXNlIGl0J3MgZGVsYXllZC4gUmV0dXJucyBhIHJlcXVlc3QgSUQgdGhhdCBjYW4gYmUgdXNlZCB0byBjYW5jZWwgdGhlIHJlcXVlc3QuXHJcbiAgZnVuY3Rpb24gcmVxdWVzdEFuaW1GcmFtZShmbiwgY29udGV4dCwgaW1tZWRpYXRlKSB7XHJcbiAgXHRpZiAoaW1tZWRpYXRlICYmIHJlcXVlc3RGbiA9PT0gdGltZW91dERlZmVyKSB7XHJcbiAgXHRcdGZuLmNhbGwoY29udGV4dCk7XHJcbiAgXHR9IGVsc2Uge1xyXG4gIFx0XHRyZXR1cm4gcmVxdWVzdEZuLmNhbGwod2luZG93LCBiaW5kKGZuLCBjb250ZXh0KSk7XHJcbiAgXHR9XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gY2FuY2VsQW5pbUZyYW1lKGlkOiBOdW1iZXIpOiB1bmRlZmluZWRcclxuICAvLyBDYW5jZWxzIGEgcHJldmlvdXMgYHJlcXVlc3RBbmltRnJhbWVgLiBTZWUgYWxzbyBbd2luZG93LmNhbmNlbEFuaW1hdGlvbkZyYW1lXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvd2luZG93L2NhbmNlbEFuaW1hdGlvbkZyYW1lKS5cclxuICBmdW5jdGlvbiBjYW5jZWxBbmltRnJhbWUoaWQpIHtcclxuICBcdGlmIChpZCkge1xyXG4gIFx0XHRjYW5jZWxGbi5jYWxsKHdpbmRvdywgaWQpO1xyXG4gIFx0fVxyXG4gIH1cblxuICB2YXIgVXRpbCA9IHtcbiAgICBfX3Byb3RvX186IG51bGwsXG4gICAgZXh0ZW5kOiBleHRlbmQsXG4gICAgY3JlYXRlOiBjcmVhdGUkMixcbiAgICBiaW5kOiBiaW5kLFxuICAgIGdldCBsYXN0SWQgKCkgeyByZXR1cm4gbGFzdElkOyB9LFxuICAgIHN0YW1wOiBzdGFtcCxcbiAgICB0aHJvdHRsZTogdGhyb3R0bGUsXG4gICAgd3JhcE51bTogd3JhcE51bSxcbiAgICBmYWxzZUZuOiBmYWxzZUZuLFxuICAgIGZvcm1hdE51bTogZm9ybWF0TnVtLFxuICAgIHRyaW06IHRyaW0sXG4gICAgc3BsaXRXb3Jkczogc3BsaXRXb3JkcyxcbiAgICBzZXRPcHRpb25zOiBzZXRPcHRpb25zLFxuICAgIGdldFBhcmFtU3RyaW5nOiBnZXRQYXJhbVN0cmluZyxcbiAgICB0ZW1wbGF0ZTogdGVtcGxhdGUsXG4gICAgaXNBcnJheTogaXNBcnJheSxcbiAgICBpbmRleE9mOiBpbmRleE9mLFxuICAgIGVtcHR5SW1hZ2VVcmw6IGVtcHR5SW1hZ2VVcmwsXG4gICAgcmVxdWVzdEZuOiByZXF1ZXN0Rm4sXG4gICAgY2FuY2VsRm46IGNhbmNlbEZuLFxuICAgIHJlcXVlc3RBbmltRnJhbWU6IHJlcXVlc3RBbmltRnJhbWUsXG4gICAgY2FuY2VsQW5pbUZyYW1lOiBjYW5jZWxBbmltRnJhbWVcbiAgfTtcblxuICAvLyBAY2xhc3MgQ2xhc3NcclxuICAvLyBAYWthIEwuQ2xhc3NcclxuXHJcbiAgLy8gQHNlY3Rpb25cclxuICAvLyBAdW5pbmhlcml0YWJsZVxyXG5cclxuICAvLyBUaGFua3MgdG8gSm9obiBSZXNpZyBhbmQgRGVhbiBFZHdhcmRzIGZvciBpbnNwaXJhdGlvbiFcclxuXHJcbiAgZnVuY3Rpb24gQ2xhc3MoKSB7fVxyXG5cclxuICBDbGFzcy5leHRlbmQgPSBmdW5jdGlvbiAocHJvcHMpIHtcclxuXHJcbiAgXHQvLyBAZnVuY3Rpb24gZXh0ZW5kKHByb3BzOiBPYmplY3QpOiBGdW5jdGlvblxyXG4gIFx0Ly8gW0V4dGVuZHMgdGhlIGN1cnJlbnQgY2xhc3NdKCNjbGFzcy1pbmhlcml0YW5jZSkgZ2l2ZW4gdGhlIHByb3BlcnRpZXMgdG8gYmUgaW5jbHVkZWQuXHJcbiAgXHQvLyBSZXR1cm5zIGEgSmF2YXNjcmlwdCBmdW5jdGlvbiB0aGF0IGlzIGEgY2xhc3MgY29uc3RydWN0b3IgKHRvIGJlIGNhbGxlZCB3aXRoIGBuZXdgKS5cclxuICBcdHZhciBOZXdDbGFzcyA9IGZ1bmN0aW9uICgpIHtcclxuXHJcbiAgXHRcdHNldE9wdGlvbnModGhpcyk7XHJcblxyXG4gIFx0XHQvLyBjYWxsIHRoZSBjb25zdHJ1Y3RvclxyXG4gIFx0XHRpZiAodGhpcy5pbml0aWFsaXplKSB7XHJcbiAgXHRcdFx0dGhpcy5pbml0aWFsaXplLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdC8vIGNhbGwgYWxsIGNvbnN0cnVjdG9yIGhvb2tzXHJcbiAgXHRcdHRoaXMuY2FsbEluaXRIb29rcygpO1xyXG4gIFx0fTtcclxuXHJcbiAgXHR2YXIgcGFyZW50UHJvdG8gPSBOZXdDbGFzcy5fX3N1cGVyX18gPSB0aGlzLnByb3RvdHlwZTtcclxuXHJcbiAgXHR2YXIgcHJvdG8gPSBjcmVhdGUkMihwYXJlbnRQcm90byk7XHJcbiAgXHRwcm90by5jb25zdHJ1Y3RvciA9IE5ld0NsYXNzO1xyXG5cclxuICBcdE5ld0NsYXNzLnByb3RvdHlwZSA9IHByb3RvO1xyXG5cclxuICBcdC8vIGluaGVyaXQgcGFyZW50J3Mgc3RhdGljc1xyXG4gIFx0Zm9yICh2YXIgaSBpbiB0aGlzKSB7XHJcbiAgXHRcdGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodGhpcywgaSkgJiYgaSAhPT0gJ3Byb3RvdHlwZScgJiYgaSAhPT0gJ19fc3VwZXJfXycpIHtcclxuICBcdFx0XHROZXdDbGFzc1tpXSA9IHRoaXNbaV07XHJcbiAgXHRcdH1cclxuICBcdH1cclxuXHJcbiAgXHQvLyBtaXggc3RhdGljIHByb3BlcnRpZXMgaW50byB0aGUgY2xhc3NcclxuICBcdGlmIChwcm9wcy5zdGF0aWNzKSB7XHJcbiAgXHRcdGV4dGVuZChOZXdDbGFzcywgcHJvcHMuc3RhdGljcyk7XHJcbiAgXHR9XHJcblxyXG4gIFx0Ly8gbWl4IGluY2x1ZGVzIGludG8gdGhlIHByb3RvdHlwZVxyXG4gIFx0aWYgKHByb3BzLmluY2x1ZGVzKSB7XHJcbiAgXHRcdGNoZWNrRGVwcmVjYXRlZE1peGluRXZlbnRzKHByb3BzLmluY2x1ZGVzKTtcclxuICBcdFx0ZXh0ZW5kLmFwcGx5KG51bGwsIFtwcm90b10uY29uY2F0KHByb3BzLmluY2x1ZGVzKSk7XHJcbiAgXHR9XHJcblxyXG4gIFx0Ly8gbWl4IGdpdmVuIHByb3BlcnRpZXMgaW50byB0aGUgcHJvdG90eXBlXHJcbiAgXHRleHRlbmQocHJvdG8sIHByb3BzKTtcclxuICBcdGRlbGV0ZSBwcm90by5zdGF0aWNzO1xyXG4gIFx0ZGVsZXRlIHByb3RvLmluY2x1ZGVzO1xyXG5cclxuICBcdC8vIG1lcmdlIG9wdGlvbnNcclxuICBcdGlmIChwcm90by5vcHRpb25zKSB7XHJcbiAgXHRcdHByb3RvLm9wdGlvbnMgPSBwYXJlbnRQcm90by5vcHRpb25zID8gY3JlYXRlJDIocGFyZW50UHJvdG8ub3B0aW9ucykgOiB7fTtcclxuICBcdFx0ZXh0ZW5kKHByb3RvLm9wdGlvbnMsIHByb3BzLm9wdGlvbnMpO1xyXG4gIFx0fVxyXG5cclxuICBcdHByb3RvLl9pbml0SG9va3MgPSBbXTtcclxuXHJcbiAgXHQvLyBhZGQgbWV0aG9kIGZvciBjYWxsaW5nIGFsbCBob29rc1xyXG4gIFx0cHJvdG8uY2FsbEluaXRIb29rcyA9IGZ1bmN0aW9uICgpIHtcclxuXHJcbiAgXHRcdGlmICh0aGlzLl9pbml0SG9va3NDYWxsZWQpIHsgcmV0dXJuOyB9XHJcblxyXG4gIFx0XHRpZiAocGFyZW50UHJvdG8uY2FsbEluaXRIb29rcykge1xyXG4gIFx0XHRcdHBhcmVudFByb3RvLmNhbGxJbml0SG9va3MuY2FsbCh0aGlzKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5faW5pdEhvb2tzQ2FsbGVkID0gdHJ1ZTtcclxuXHJcbiAgXHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBwcm90by5faW5pdEhvb2tzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdFx0cHJvdG8uX2luaXRIb29rc1tpXS5jYWxsKHRoaXMpO1xyXG4gIFx0XHR9XHJcbiAgXHR9O1xyXG5cclxuICBcdHJldHVybiBOZXdDbGFzcztcclxuICB9O1xyXG5cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGluY2x1ZGUocHJvcGVydGllczogT2JqZWN0KTogdGhpc1xyXG4gIC8vIFtJbmNsdWRlcyBhIG1peGluXSgjY2xhc3MtaW5jbHVkZXMpIGludG8gdGhlIGN1cnJlbnQgY2xhc3MuXHJcbiAgQ2xhc3MuaW5jbHVkZSA9IGZ1bmN0aW9uIChwcm9wcykge1xyXG4gIFx0dmFyIHBhcmVudE9wdGlvbnMgPSB0aGlzLnByb3RvdHlwZS5vcHRpb25zO1xyXG4gIFx0ZXh0ZW5kKHRoaXMucHJvdG90eXBlLCBwcm9wcyk7XHJcbiAgXHRpZiAocHJvcHMub3B0aW9ucykge1xyXG4gIFx0XHR0aGlzLnByb3RvdHlwZS5vcHRpb25zID0gcGFyZW50T3B0aW9ucztcclxuICBcdFx0dGhpcy5tZXJnZU9wdGlvbnMocHJvcHMub3B0aW9ucyk7XHJcbiAgXHR9XHJcbiAgXHRyZXR1cm4gdGhpcztcclxuICB9O1xyXG5cclxuICAvLyBAZnVuY3Rpb24gbWVyZ2VPcHRpb25zKG9wdGlvbnM6IE9iamVjdCk6IHRoaXNcclxuICAvLyBbTWVyZ2VzIGBvcHRpb25zYF0oI2NsYXNzLW9wdGlvbnMpIGludG8gdGhlIGRlZmF1bHRzIG9mIHRoZSBjbGFzcy5cclxuICBDbGFzcy5tZXJnZU9wdGlvbnMgPSBmdW5jdGlvbiAob3B0aW9ucykge1xyXG4gIFx0ZXh0ZW5kKHRoaXMucHJvdG90eXBlLm9wdGlvbnMsIG9wdGlvbnMpO1xyXG4gIFx0cmV0dXJuIHRoaXM7XHJcbiAgfTtcclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGFkZEluaXRIb29rKGZuOiBGdW5jdGlvbik6IHRoaXNcclxuICAvLyBBZGRzIGEgW2NvbnN0cnVjdG9yIGhvb2tdKCNjbGFzcy1jb25zdHJ1Y3Rvci1ob29rcykgdG8gdGhlIGNsYXNzLlxyXG4gIENsYXNzLmFkZEluaXRIb29rID0gZnVuY3Rpb24gKGZuKSB7IC8vIChGdW5jdGlvbikgfHwgKFN0cmluZywgYXJncy4uLilcclxuICBcdHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcclxuXHJcbiAgXHR2YXIgaW5pdCA9IHR5cGVvZiBmbiA9PT0gJ2Z1bmN0aW9uJyA/IGZuIDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR0aGlzW2ZuXS5hcHBseSh0aGlzLCBhcmdzKTtcclxuICBcdH07XHJcblxyXG4gIFx0dGhpcy5wcm90b3R5cGUuX2luaXRIb29rcyA9IHRoaXMucHJvdG90eXBlLl9pbml0SG9va3MgfHwgW107XHJcbiAgXHR0aGlzLnByb3RvdHlwZS5faW5pdEhvb2tzLnB1c2goaW5pdCk7XHJcbiAgXHRyZXR1cm4gdGhpcztcclxuICB9O1xyXG5cclxuICBmdW5jdGlvbiBjaGVja0RlcHJlY2F0ZWRNaXhpbkV2ZW50cyhpbmNsdWRlcykge1xyXG4gIFx0LyogZ2xvYmFsIEw6IHRydWUgKi9cclxuICBcdGlmICh0eXBlb2YgTCA9PT0gJ3VuZGVmaW5lZCcgfHwgIUwgfHwgIUwuTWl4aW4pIHsgcmV0dXJuOyB9XHJcblxyXG4gIFx0aW5jbHVkZXMgPSBpc0FycmF5KGluY2x1ZGVzKSA/IGluY2x1ZGVzIDogW2luY2x1ZGVzXTtcclxuXHJcbiAgXHRmb3IgKHZhciBpID0gMDsgaSA8IGluY2x1ZGVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgXHRcdGlmIChpbmNsdWRlc1tpXSA9PT0gTC5NaXhpbi5FdmVudHMpIHtcclxuICBcdFx0XHRjb25zb2xlLndhcm4oJ0RlcHJlY2F0ZWQgaW5jbHVkZSBvZiBMLk1peGluLkV2ZW50czogJyArXHJcbiAgXHRcdFx0XHQndGhpcyBwcm9wZXJ0eSB3aWxsIGJlIHJlbW92ZWQgaW4gZnV0dXJlIHJlbGVhc2VzLCAnICtcclxuICBcdFx0XHRcdCdwbGVhc2UgaW5oZXJpdCBmcm9tIEwuRXZlbnRlZCBpbnN0ZWFkLicsIG5ldyBFcnJvcigpLnN0YWNrKTtcclxuICBcdFx0fVxyXG4gIFx0fVxyXG4gIH1cblxuICAvKlxyXG4gICAqIEBjbGFzcyBFdmVudGVkXHJcbiAgICogQGFrYSBMLkV2ZW50ZWRcclxuICAgKiBAaW5oZXJpdHMgQ2xhc3NcclxuICAgKlxyXG4gICAqIEEgc2V0IG9mIG1ldGhvZHMgc2hhcmVkIGJldHdlZW4gZXZlbnQtcG93ZXJlZCBjbGFzc2VzIChsaWtlIGBNYXBgIGFuZCBgTWFya2VyYCkuIEdlbmVyYWxseSwgZXZlbnRzIGFsbG93IHlvdSB0byBleGVjdXRlIHNvbWUgZnVuY3Rpb24gd2hlbiBzb21ldGhpbmcgaGFwcGVucyB3aXRoIGFuIG9iamVjdCAoZS5nLiB0aGUgdXNlciBjbGlja3Mgb24gdGhlIG1hcCwgY2F1c2luZyB0aGUgbWFwIHRvIGZpcmUgYCdjbGljaydgIGV2ZW50KS5cclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICpcclxuICAgKiBgYGBqc1xyXG4gICAqIG1hcC5vbignY2xpY2snLCBmdW5jdGlvbihlKSB7XHJcbiAgICogXHRhbGVydChlLmxhdGxuZyk7XHJcbiAgICogfSApO1xyXG4gICAqIGBgYFxyXG4gICAqXHJcbiAgICogTGVhZmxldCBkZWFscyB3aXRoIGV2ZW50IGxpc3RlbmVycyBieSByZWZlcmVuY2UsIHNvIGlmIHlvdSB3YW50IHRvIGFkZCBhIGxpc3RlbmVyIGFuZCB0aGVuIHJlbW92ZSBpdCwgZGVmaW5lIGl0IGFzIGEgZnVuY3Rpb246XHJcbiAgICpcclxuICAgKiBgYGBqc1xyXG4gICAqIGZ1bmN0aW9uIG9uQ2xpY2soZSkgeyAuLi4gfVxyXG4gICAqXHJcbiAgICogbWFwLm9uKCdjbGljaycsIG9uQ2xpY2spO1xyXG4gICAqIG1hcC5vZmYoJ2NsaWNrJywgb25DbGljayk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcblxyXG4gIHZhciBFdmVudHMgPSB7XHJcbiAgXHQvKiBAbWV0aG9kIG9uKHR5cGU6IFN0cmluZywgZm46IEZ1bmN0aW9uLCBjb250ZXh0PzogT2JqZWN0KTogdGhpc1xyXG4gIFx0ICogQWRkcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIChgZm5gKSB0byBhIHBhcnRpY3VsYXIgZXZlbnQgdHlwZSBvZiB0aGUgb2JqZWN0LiBZb3UgY2FuIG9wdGlvbmFsbHkgc3BlY2lmeSB0aGUgY29udGV4dCBvZiB0aGUgbGlzdGVuZXIgKG9iamVjdCB0aGUgdGhpcyBrZXl3b3JkIHdpbGwgcG9pbnQgdG8pLiBZb3UgY2FuIGFsc28gcGFzcyBzZXZlcmFsIHNwYWNlLXNlcGFyYXRlZCB0eXBlcyAoZS5nLiBgJ2NsaWNrIGRibGNsaWNrJ2ApLlxyXG4gIFx0ICpcclxuICBcdCAqIEBhbHRlcm5hdGl2ZVxyXG4gIFx0ICogQG1ldGhvZCBvbihldmVudE1hcDogT2JqZWN0KTogdGhpc1xyXG4gIFx0ICogQWRkcyBhIHNldCBvZiB0eXBlL2xpc3RlbmVyIHBhaXJzLCBlLmcuIGB7Y2xpY2s6IG9uQ2xpY2ssIG1vdXNlbW92ZTogb25Nb3VzZU1vdmV9YFxyXG4gIFx0ICovXHJcbiAgXHRvbjogZnVuY3Rpb24gKHR5cGVzLCBmbiwgY29udGV4dCkge1xyXG5cclxuICBcdFx0Ly8gdHlwZXMgY2FuIGJlIGEgbWFwIG9mIHR5cGVzL2hhbmRsZXJzXHJcbiAgXHRcdGlmICh0eXBlb2YgdHlwZXMgPT09ICdvYmplY3QnKSB7XHJcbiAgXHRcdFx0Zm9yICh2YXIgdHlwZSBpbiB0eXBlcykge1xyXG4gIFx0XHRcdFx0Ly8gd2UgZG9uJ3QgcHJvY2VzcyBzcGFjZS1zZXBhcmF0ZWQgZXZlbnRzIGhlcmUgZm9yIHBlcmZvcm1hbmNlO1xyXG4gIFx0XHRcdFx0Ly8gaXQncyBhIGhvdCBwYXRoIHNpbmNlIExheWVyIHVzZXMgdGhlIG9uKG9iaikgc3ludGF4XHJcbiAgXHRcdFx0XHR0aGlzLl9vbih0eXBlLCB0eXBlc1t0eXBlXSwgZm4pO1xyXG4gIFx0XHRcdH1cclxuXHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0Ly8gdHlwZXMgY2FuIGJlIGEgc3RyaW5nIG9mIHNwYWNlLXNlcGFyYXRlZCB3b3Jkc1xyXG4gIFx0XHRcdHR5cGVzID0gc3BsaXRXb3Jkcyh0eXBlcyk7XHJcblxyXG4gIFx0XHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSB0eXBlcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gIFx0XHRcdFx0dGhpcy5fb24odHlwZXNbaV0sIGZuLCBjb250ZXh0KTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvKiBAbWV0aG9kIG9mZih0eXBlOiBTdHJpbmcsIGZuPzogRnVuY3Rpb24sIGNvbnRleHQ/OiBPYmplY3QpOiB0aGlzXHJcbiAgXHQgKiBSZW1vdmVzIGEgcHJldmlvdXNseSBhZGRlZCBsaXN0ZW5lciBmdW5jdGlvbi4gSWYgbm8gZnVuY3Rpb24gaXMgc3BlY2lmaWVkLCBpdCB3aWxsIHJlbW92ZSBhbGwgdGhlIGxpc3RlbmVycyBvZiB0aGF0IHBhcnRpY3VsYXIgZXZlbnQgZnJvbSB0aGUgb2JqZWN0LiBOb3RlIHRoYXQgaWYgeW91IHBhc3NlZCBhIGN1c3RvbSBjb250ZXh0IHRvIGBvbmAsIHlvdSBtdXN0IHBhc3MgdGhlIHNhbWUgY29udGV4dCB0byBgb2ZmYCBpbiBvcmRlciB0byByZW1vdmUgdGhlIGxpc3RlbmVyLlxyXG4gIFx0ICpcclxuICBcdCAqIEBhbHRlcm5hdGl2ZVxyXG4gIFx0ICogQG1ldGhvZCBvZmYoZXZlbnRNYXA6IE9iamVjdCk6IHRoaXNcclxuICBcdCAqIFJlbW92ZXMgYSBzZXQgb2YgdHlwZS9saXN0ZW5lciBwYWlycy5cclxuICBcdCAqXHJcbiAgXHQgKiBAYWx0ZXJuYXRpdmVcclxuICBcdCAqIEBtZXRob2Qgb2ZmOiB0aGlzXHJcbiAgXHQgKiBSZW1vdmVzIGFsbCBsaXN0ZW5lcnMgdG8gYWxsIGV2ZW50cyBvbiB0aGUgb2JqZWN0LiBUaGlzIGluY2x1ZGVzIGltcGxpY2l0bHkgYXR0YWNoZWQgZXZlbnRzLlxyXG4gIFx0ICovXHJcbiAgXHRvZmY6IGZ1bmN0aW9uICh0eXBlcywgZm4sIGNvbnRleHQpIHtcclxuXHJcbiAgXHRcdGlmICghYXJndW1lbnRzLmxlbmd0aCkge1xyXG4gIFx0XHRcdC8vIGNsZWFyIGFsbCBsaXN0ZW5lcnMgaWYgY2FsbGVkIHdpdGhvdXQgYXJndW1lbnRzXHJcbiAgXHRcdFx0ZGVsZXRlIHRoaXMuX2V2ZW50cztcclxuXHJcbiAgXHRcdH0gZWxzZSBpZiAodHlwZW9mIHR5cGVzID09PSAnb2JqZWN0Jykge1xyXG4gIFx0XHRcdGZvciAodmFyIHR5cGUgaW4gdHlwZXMpIHtcclxuICBcdFx0XHRcdHRoaXMuX29mZih0eXBlLCB0eXBlc1t0eXBlXSwgZm4pO1xyXG4gIFx0XHRcdH1cclxuXHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0dHlwZXMgPSBzcGxpdFdvcmRzKHR5cGVzKTtcclxuXHJcbiAgXHRcdFx0dmFyIHJlbW92ZUFsbCA9IGFyZ3VtZW50cy5sZW5ndGggPT09IDE7XHJcbiAgXHRcdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IHR5cGVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdFx0XHRpZiAocmVtb3ZlQWxsKSB7XHJcbiAgXHRcdFx0XHRcdHRoaXMuX29mZih0eXBlc1tpXSk7XHJcbiAgXHRcdFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdFx0XHR0aGlzLl9vZmYodHlwZXNbaV0sIGZuLCBjb250ZXh0KTtcclxuICBcdFx0XHRcdH1cclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBhdHRhY2ggbGlzdGVuZXIgKHdpdGhvdXQgc3ludGFjdGljIHN1Z2FyIG5vdylcclxuICBcdF9vbjogZnVuY3Rpb24gKHR5cGUsIGZuLCBjb250ZXh0LCBfb25jZSkge1xyXG4gIFx0XHRpZiAodHlwZW9mIGZuICE9PSAnZnVuY3Rpb24nKSB7XHJcbiAgXHRcdFx0Y29uc29sZS53YXJuKCd3cm9uZyBsaXN0ZW5lciB0eXBlOiAnICsgdHlwZW9mIGZuKTtcclxuICBcdFx0XHRyZXR1cm47XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdC8vIGNoZWNrIGlmIGZuIGFscmVhZHkgdGhlcmVcclxuICBcdFx0aWYgKHRoaXMuX2xpc3RlbnModHlwZSwgZm4sIGNvbnRleHQpICE9PSBmYWxzZSkge1xyXG4gIFx0XHRcdHJldHVybjtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0aWYgKGNvbnRleHQgPT09IHRoaXMpIHtcclxuICBcdFx0XHQvLyBMZXNzIG1lbW9yeSBmb290cHJpbnQuXHJcbiAgXHRcdFx0Y29udGV4dCA9IHVuZGVmaW5lZDtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dmFyIG5ld0xpc3RlbmVyID0ge2ZuOiBmbiwgY3R4OiBjb250ZXh0fTtcclxuICBcdFx0aWYgKF9vbmNlKSB7XHJcbiAgXHRcdFx0bmV3TGlzdGVuZXIub25jZSA9IHRydWU7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX2V2ZW50cyA9IHRoaXMuX2V2ZW50cyB8fCB7fTtcclxuICBcdFx0dGhpcy5fZXZlbnRzW3R5cGVdID0gdGhpcy5fZXZlbnRzW3R5cGVdIHx8IFtdO1xyXG4gIFx0XHR0aGlzLl9ldmVudHNbdHlwZV0ucHVzaChuZXdMaXN0ZW5lcik7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9vZmY6IGZ1bmN0aW9uICh0eXBlLCBmbiwgY29udGV4dCkge1xyXG4gIFx0XHR2YXIgbGlzdGVuZXJzLFxyXG4gIFx0XHQgICAgaSxcclxuICBcdFx0ICAgIGxlbjtcclxuXHJcbiAgXHRcdGlmICghdGhpcy5fZXZlbnRzKSB7XHJcbiAgXHRcdFx0cmV0dXJuO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRsaXN0ZW5lcnMgPSB0aGlzLl9ldmVudHNbdHlwZV07XHJcbiAgXHRcdGlmICghbGlzdGVuZXJzKSB7XHJcbiAgXHRcdFx0cmV0dXJuO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkgeyAvLyByZW1vdmUgYWxsXHJcbiAgXHRcdFx0aWYgKHRoaXMuX2ZpcmluZ0NvdW50KSB7XHJcbiAgXHRcdFx0XHQvLyBTZXQgYWxsIHJlbW92ZWQgbGlzdGVuZXJzIHRvIG5vb3BcclxuICBcdFx0XHRcdC8vIHNvIHRoZXkgYXJlIG5vdCBjYWxsZWQgaWYgcmVtb3ZlIGhhcHBlbnMgaW4gZmlyZVxyXG4gIFx0XHRcdFx0Zm9yIChpID0gMCwgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdFx0XHRcdGxpc3RlbmVyc1tpXS5mbiA9IGZhbHNlRm47XHJcbiAgXHRcdFx0XHR9XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHRcdC8vIGNsZWFyIGFsbCBsaXN0ZW5lcnMgZm9yIGEgdHlwZSBpZiBmdW5jdGlvbiBpc24ndCBzcGVjaWZpZWRcclxuICBcdFx0XHRkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xyXG4gIFx0XHRcdHJldHVybjtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0aWYgKHR5cGVvZiBmbiAhPT0gJ2Z1bmN0aW9uJykge1xyXG4gIFx0XHRcdGNvbnNvbGUud2Fybignd3JvbmcgbGlzdGVuZXIgdHlwZTogJyArIHR5cGVvZiBmbik7XHJcbiAgXHRcdFx0cmV0dXJuO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHQvLyBmaW5kIGZuIGFuZCByZW1vdmUgaXRcclxuICBcdFx0dmFyIGluZGV4ID0gdGhpcy5fbGlzdGVucyh0eXBlLCBmbiwgY29udGV4dCk7XHJcbiAgXHRcdGlmIChpbmRleCAhPT0gZmFsc2UpIHtcclxuICBcdFx0XHR2YXIgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaW5kZXhdO1xyXG4gIFx0XHRcdGlmICh0aGlzLl9maXJpbmdDb3VudCkge1xyXG4gIFx0XHRcdFx0Ly8gc2V0IHRoZSByZW1vdmVkIGxpc3RlbmVyIHRvIG5vb3Agc28gdGhhdCdzIG5vdCBjYWxsZWQgaWYgcmVtb3ZlIGhhcHBlbnMgaW4gZmlyZVxyXG4gIFx0XHRcdFx0bGlzdGVuZXIuZm4gPSBmYWxzZUZuO1xyXG5cclxuICBcdFx0XHRcdC8qIGNvcHkgYXJyYXkgaW4gY2FzZSBldmVudHMgYXJlIGJlaW5nIGZpcmVkICovXHJcbiAgXHRcdFx0XHR0aGlzLl9ldmVudHNbdHlwZV0gPSBsaXN0ZW5lcnMgPSBsaXN0ZW5lcnMuc2xpY2UoKTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdFx0bGlzdGVuZXJzLnNwbGljZShpbmRleCwgMSk7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBmaXJlKHR5cGU6IFN0cmluZywgZGF0YT86IE9iamVjdCwgcHJvcGFnYXRlPzogQm9vbGVhbik6IHRoaXNcclxuICBcdC8vIEZpcmVzIGFuIGV2ZW50IG9mIHRoZSBzcGVjaWZpZWQgdHlwZS4gWW91IGNhbiBvcHRpb25hbGx5IHByb3ZpZGUgYSBkYXRhXHJcbiAgXHQvLyBvYmplY3Qg4oCUIHRoZSBmaXJzdCBhcmd1bWVudCBvZiB0aGUgbGlzdGVuZXIgZnVuY3Rpb24gd2lsbCBjb250YWluIGl0c1xyXG4gIFx0Ly8gcHJvcGVydGllcy4gVGhlIGV2ZW50IGNhbiBvcHRpb25hbGx5IGJlIHByb3BhZ2F0ZWQgdG8gZXZlbnQgcGFyZW50cy5cclxuICBcdGZpcmU6IGZ1bmN0aW9uICh0eXBlLCBkYXRhLCBwcm9wYWdhdGUpIHtcclxuICBcdFx0aWYgKCF0aGlzLmxpc3RlbnModHlwZSwgcHJvcGFnYXRlKSkgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuICBcdFx0dmFyIGV2ZW50ID0gZXh0ZW5kKHt9LCBkYXRhLCB7XHJcbiAgXHRcdFx0dHlwZTogdHlwZSxcclxuICBcdFx0XHR0YXJnZXQ6IHRoaXMsXHJcbiAgXHRcdFx0c291cmNlVGFyZ2V0OiBkYXRhICYmIGRhdGEuc291cmNlVGFyZ2V0IHx8IHRoaXNcclxuICBcdFx0fSk7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fZXZlbnRzKSB7XHJcbiAgXHRcdFx0dmFyIGxpc3RlbmVycyA9IHRoaXMuX2V2ZW50c1t0eXBlXTtcclxuICBcdFx0XHRpZiAobGlzdGVuZXJzKSB7XHJcbiAgXHRcdFx0XHR0aGlzLl9maXJpbmdDb3VudCA9ICh0aGlzLl9maXJpbmdDb3VudCArIDEpIHx8IDE7XHJcbiAgXHRcdFx0XHRmb3IgKHZhciBpID0gMCwgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdFx0XHRcdHZhciBsID0gbGlzdGVuZXJzW2ldO1xyXG4gIFx0XHRcdFx0XHQvLyBvZmYgb3ZlcndyaXRlcyBsLmZuLCBzbyB3ZSBuZWVkIHRvIGNvcHkgZm4gdG8gYSB2YXJcclxuICBcdFx0XHRcdFx0dmFyIGZuID0gbC5mbjtcclxuICBcdFx0XHRcdFx0aWYgKGwub25jZSkge1xyXG4gIFx0XHRcdFx0XHRcdHRoaXMub2ZmKHR5cGUsIGZuLCBsLmN0eCk7XHJcbiAgXHRcdFx0XHRcdH1cclxuICBcdFx0XHRcdFx0Zm4uY2FsbChsLmN0eCB8fCB0aGlzLCBldmVudCk7XHJcbiAgXHRcdFx0XHR9XHJcblxyXG4gIFx0XHRcdFx0dGhpcy5fZmlyaW5nQ291bnQtLTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmIChwcm9wYWdhdGUpIHtcclxuICBcdFx0XHQvLyBwcm9wYWdhdGUgdGhlIGV2ZW50IHRvIHBhcmVudHMgKHNldCB3aXRoIGFkZEV2ZW50UGFyZW50KVxyXG4gIFx0XHRcdHRoaXMuX3Byb3BhZ2F0ZUV2ZW50KGV2ZW50KTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgbGlzdGVucyh0eXBlOiBTdHJpbmcsIHByb3BhZ2F0ZT86IEJvb2xlYW4pOiBCb29sZWFuXHJcbiAgXHQvLyBAbWV0aG9kIGxpc3RlbnModHlwZTogU3RyaW5nLCBmbjogRnVuY3Rpb24sIGNvbnRleHQ/OiBPYmplY3QsIHByb3BhZ2F0ZT86IEJvb2xlYW4pOiBCb29sZWFuXHJcbiAgXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiBhIHBhcnRpY3VsYXIgZXZlbnQgdHlwZSBoYXMgYW55IGxpc3RlbmVycyBhdHRhY2hlZCB0byBpdC5cclxuICBcdC8vIFRoZSB2ZXJpZmljYXRpb24gY2FuIG9wdGlvbmFsbHkgYmUgcHJvcGFnYXRlZCwgaXQgd2lsbCByZXR1cm4gYHRydWVgIGlmIHBhcmVudHMgaGF2ZSB0aGUgbGlzdGVuZXIgYXR0YWNoZWQgdG8gaXQuXHJcbiAgXHRsaXN0ZW5zOiBmdW5jdGlvbiAodHlwZSwgZm4sIGNvbnRleHQsIHByb3BhZ2F0ZSkge1xyXG4gIFx0XHRpZiAodHlwZW9mIHR5cGUgIT09ICdzdHJpbmcnKSB7XHJcbiAgXHRcdFx0Y29uc29sZS53YXJuKCdcInN0cmluZ1wiIHR5cGUgYXJndW1lbnQgZXhwZWN0ZWQnKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gd2UgZG9uJ3Qgb3ZlcndyaXRlIHRoZSBpbnB1dCBgZm5gIHZhbHVlLCBiZWNhdXNlIHdlIG5lZWQgdG8gdXNlIGl0IGZvciBwcm9wYWdhdGlvblxyXG4gIFx0XHR2YXIgX2ZuID0gZm47XHJcbiAgXHRcdGlmICh0eXBlb2YgZm4gIT09ICdmdW5jdGlvbicpIHtcclxuICBcdFx0XHRwcm9wYWdhdGUgPSAhIWZuO1xyXG4gIFx0XHRcdF9mbiA9IHVuZGVmaW5lZDtcclxuICBcdFx0XHRjb250ZXh0ID0gdW5kZWZpbmVkO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgbGlzdGVuZXJzID0gdGhpcy5fZXZlbnRzICYmIHRoaXMuX2V2ZW50c1t0eXBlXTtcclxuICBcdFx0aWYgKGxpc3RlbmVycyAmJiBsaXN0ZW5lcnMubGVuZ3RoKSB7XHJcbiAgXHRcdFx0aWYgKHRoaXMuX2xpc3RlbnModHlwZSwgX2ZuLCBjb250ZXh0KSAhPT0gZmFsc2UpIHtcclxuICBcdFx0XHRcdHJldHVybiB0cnVlO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG5cclxuICBcdFx0aWYgKHByb3BhZ2F0ZSkge1xyXG4gIFx0XHRcdC8vIGFsc28gY2hlY2sgcGFyZW50cyBmb3IgbGlzdGVuZXJzIGlmIGV2ZW50IHByb3BhZ2F0ZXNcclxuICBcdFx0XHRmb3IgKHZhciBpZCBpbiB0aGlzLl9ldmVudFBhcmVudHMpIHtcclxuICBcdFx0XHRcdGlmICh0aGlzLl9ldmVudFBhcmVudHNbaWRdLmxpc3RlbnModHlwZSwgZm4sIGNvbnRleHQsIHByb3BhZ2F0ZSkpIHsgcmV0dXJuIHRydWU7IH1cclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIGZhbHNlO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyByZXR1cm5zIHRoZSBpbmRleCAobnVtYmVyKSBvciBmYWxzZVxyXG4gIFx0X2xpc3RlbnM6IGZ1bmN0aW9uICh0eXBlLCBmbiwgY29udGV4dCkge1xyXG4gIFx0XHRpZiAoIXRoaXMuX2V2ZW50cykge1xyXG4gIFx0XHRcdHJldHVybiBmYWxzZTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dmFyIGxpc3RlbmVycyA9IHRoaXMuX2V2ZW50c1t0eXBlXSB8fCBbXTtcclxuICBcdFx0aWYgKCFmbikge1xyXG4gIFx0XHRcdHJldHVybiAhIWxpc3RlbmVycy5sZW5ndGg7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmIChjb250ZXh0ID09PSB0aGlzKSB7XHJcbiAgXHRcdFx0Ly8gTGVzcyBtZW1vcnkgZm9vdHByaW50LlxyXG4gIFx0XHRcdGNvbnRleHQgPSB1bmRlZmluZWQ7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuICBcdFx0XHRpZiAobGlzdGVuZXJzW2ldLmZuID09PSBmbiAmJiBsaXN0ZW5lcnNbaV0uY3R4ID09PSBjb250ZXh0KSB7XHJcbiAgXHRcdFx0XHRyZXR1cm4gaTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIGZhbHNlO1xyXG5cclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBvbmNlKOKApik6IHRoaXNcclxuICBcdC8vIEJlaGF2ZXMgYXMgW2BvbijigKYpYF0oI2V2ZW50ZWQtb24pLCBleGNlcHQgdGhlIGxpc3RlbmVyIHdpbGwgb25seSBnZXQgZmlyZWQgb25jZSBhbmQgdGhlbiByZW1vdmVkLlxyXG4gIFx0b25jZTogZnVuY3Rpb24gKHR5cGVzLCBmbiwgY29udGV4dCkge1xyXG5cclxuICBcdFx0Ly8gdHlwZXMgY2FuIGJlIGEgbWFwIG9mIHR5cGVzL2hhbmRsZXJzXHJcbiAgXHRcdGlmICh0eXBlb2YgdHlwZXMgPT09ICdvYmplY3QnKSB7XHJcbiAgXHRcdFx0Zm9yICh2YXIgdHlwZSBpbiB0eXBlcykge1xyXG4gIFx0XHRcdFx0Ly8gd2UgZG9uJ3QgcHJvY2VzcyBzcGFjZS1zZXBhcmF0ZWQgZXZlbnRzIGhlcmUgZm9yIHBlcmZvcm1hbmNlO1xyXG4gIFx0XHRcdFx0Ly8gaXQncyBhIGhvdCBwYXRoIHNpbmNlIExheWVyIHVzZXMgdGhlIG9uKG9iaikgc3ludGF4XHJcbiAgXHRcdFx0XHR0aGlzLl9vbih0eXBlLCB0eXBlc1t0eXBlXSwgZm4sIHRydWUpO1xyXG4gIFx0XHRcdH1cclxuXHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0Ly8gdHlwZXMgY2FuIGJlIGEgc3RyaW5nIG9mIHNwYWNlLXNlcGFyYXRlZCB3b3Jkc1xyXG4gIFx0XHRcdHR5cGVzID0gc3BsaXRXb3Jkcyh0eXBlcyk7XHJcblxyXG4gIFx0XHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSB0eXBlcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gIFx0XHRcdFx0dGhpcy5fb24odHlwZXNbaV0sIGZuLCBjb250ZXh0LCB0cnVlKTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGFkZEV2ZW50UGFyZW50KG9iajogRXZlbnRlZCk6IHRoaXNcclxuICBcdC8vIEFkZHMgYW4gZXZlbnQgcGFyZW50IC0gYW4gYEV2ZW50ZWRgIHRoYXQgd2lsbCByZWNlaXZlIHByb3BhZ2F0ZWQgZXZlbnRzXHJcbiAgXHRhZGRFdmVudFBhcmVudDogZnVuY3Rpb24gKG9iaikge1xyXG4gIFx0XHR0aGlzLl9ldmVudFBhcmVudHMgPSB0aGlzLl9ldmVudFBhcmVudHMgfHwge307XHJcbiAgXHRcdHRoaXMuX2V2ZW50UGFyZW50c1tzdGFtcChvYmopXSA9IG9iajtcclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgcmVtb3ZlRXZlbnRQYXJlbnQob2JqOiBFdmVudGVkKTogdGhpc1xyXG4gIFx0Ly8gUmVtb3ZlcyBhbiBldmVudCBwYXJlbnQsIHNvIGl0IHdpbGwgc3RvcCByZWNlaXZpbmcgcHJvcGFnYXRlZCBldmVudHNcclxuICBcdHJlbW92ZUV2ZW50UGFyZW50OiBmdW5jdGlvbiAob2JqKSB7XHJcbiAgXHRcdGlmICh0aGlzLl9ldmVudFBhcmVudHMpIHtcclxuICBcdFx0XHRkZWxldGUgdGhpcy5fZXZlbnRQYXJlbnRzW3N0YW1wKG9iaildO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfcHJvcGFnYXRlRXZlbnQ6IGZ1bmN0aW9uIChlKSB7XHJcbiAgXHRcdGZvciAodmFyIGlkIGluIHRoaXMuX2V2ZW50UGFyZW50cykge1xyXG4gIFx0XHRcdHRoaXMuX2V2ZW50UGFyZW50c1tpZF0uZmlyZShlLnR5cGUsIGV4dGVuZCh7XHJcbiAgXHRcdFx0XHRsYXllcjogZS50YXJnZXQsXHJcbiAgXHRcdFx0XHRwcm9wYWdhdGVkRnJvbTogZS50YXJnZXRcclxuICBcdFx0XHR9LCBlKSwgdHJ1ZSk7XHJcbiAgXHRcdH1cclxuICBcdH1cclxuICB9O1xyXG5cclxuICAvLyBhbGlhc2VzOyB3ZSBzaG91bGQgZGl0Y2ggdGhvc2UgZXZlbnR1YWxseVxyXG5cclxuICAvLyBAbWV0aG9kIGFkZEV2ZW50TGlzdGVuZXIo4oCmKTogdGhpc1xyXG4gIC8vIEFsaWFzIHRvIFtgb24o4oCmKWBdKCNldmVudGVkLW9uKVxyXG4gIEV2ZW50cy5hZGRFdmVudExpc3RlbmVyID0gRXZlbnRzLm9uO1xyXG5cclxuICAvLyBAbWV0aG9kIHJlbW92ZUV2ZW50TGlzdGVuZXIo4oCmKTogdGhpc1xyXG4gIC8vIEFsaWFzIHRvIFtgb2ZmKOKApilgXSgjZXZlbnRlZC1vZmYpXHJcblxyXG4gIC8vIEBtZXRob2QgY2xlYXJBbGxFdmVudExpc3RlbmVycyjigKYpOiB0aGlzXHJcbiAgLy8gQWxpYXMgdG8gW2BvZmYoKWBdKCNldmVudGVkLW9mZilcclxuICBFdmVudHMucmVtb3ZlRXZlbnRMaXN0ZW5lciA9IEV2ZW50cy5jbGVhckFsbEV2ZW50TGlzdGVuZXJzID0gRXZlbnRzLm9mZjtcclxuXHJcbiAgLy8gQG1ldGhvZCBhZGRPbmVUaW1lRXZlbnRMaXN0ZW5lcijigKYpOiB0aGlzXHJcbiAgLy8gQWxpYXMgdG8gW2BvbmNlKOKApilgXSgjZXZlbnRlZC1vbmNlKVxyXG4gIEV2ZW50cy5hZGRPbmVUaW1lRXZlbnRMaXN0ZW5lciA9IEV2ZW50cy5vbmNlO1xyXG5cclxuICAvLyBAbWV0aG9kIGZpcmVFdmVudCjigKYpOiB0aGlzXHJcbiAgLy8gQWxpYXMgdG8gW2BmaXJlKOKApilgXSgjZXZlbnRlZC1maXJlKVxyXG4gIEV2ZW50cy5maXJlRXZlbnQgPSBFdmVudHMuZmlyZTtcclxuXHJcbiAgLy8gQG1ldGhvZCBoYXNFdmVudExpc3RlbmVycyjigKYpOiBCb29sZWFuXHJcbiAgLy8gQWxpYXMgdG8gW2BsaXN0ZW5zKOKApilgXSgjZXZlbnRlZC1saXN0ZW5zKVxyXG4gIEV2ZW50cy5oYXNFdmVudExpc3RlbmVycyA9IEV2ZW50cy5saXN0ZW5zO1xyXG5cclxuICB2YXIgRXZlbnRlZCA9IENsYXNzLmV4dGVuZChFdmVudHMpO1xuXG4gIC8qXHJcbiAgICogQGNsYXNzIFBvaW50XHJcbiAgICogQGFrYSBMLlBvaW50XHJcbiAgICpcclxuICAgKiBSZXByZXNlbnRzIGEgcG9pbnQgd2l0aCBgeGAgYW5kIGB5YCBjb29yZGluYXRlcyBpbiBwaXhlbHMuXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiB2YXIgcG9pbnQgPSBMLnBvaW50KDIwMCwgMzAwKTtcclxuICAgKiBgYGBcclxuICAgKlxyXG4gICAqIEFsbCBMZWFmbGV0IG1ldGhvZHMgYW5kIG9wdGlvbnMgdGhhdCBhY2NlcHQgYFBvaW50YCBvYmplY3RzIGFsc28gYWNjZXB0IHRoZW0gaW4gYSBzaW1wbGUgQXJyYXkgZm9ybSAodW5sZXNzIG5vdGVkIG90aGVyd2lzZSksIHNvIHRoZXNlIGxpbmVzIGFyZSBlcXVpdmFsZW50OlxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiBtYXAucGFuQnkoWzIwMCwgMzAwXSk7XHJcbiAgICogbWFwLnBhbkJ5KEwucG9pbnQoMjAwLCAzMDApKTtcclxuICAgKiBgYGBcclxuICAgKlxyXG4gICAqIE5vdGUgdGhhdCBgUG9pbnRgIGRvZXMgbm90IGluaGVyaXQgZnJvbSBMZWFmbGV0J3MgYENsYXNzYCBvYmplY3QsXHJcbiAgICogd2hpY2ggbWVhbnMgbmV3IGNsYXNzZXMgY2FuJ3QgaW5oZXJpdCBmcm9tIGl0LCBhbmQgbmV3IG1ldGhvZHNcclxuICAgKiBjYW4ndCBiZSBhZGRlZCB0byBpdCB3aXRoIHRoZSBgaW5jbHVkZWAgZnVuY3Rpb24uXHJcbiAgICovXHJcblxyXG4gIGZ1bmN0aW9uIFBvaW50KHgsIHksIHJvdW5kKSB7XHJcbiAgXHQvLyBAcHJvcGVydHkgeDogTnVtYmVyOyBUaGUgYHhgIGNvb3JkaW5hdGUgb2YgdGhlIHBvaW50XHJcbiAgXHR0aGlzLnggPSAocm91bmQgPyBNYXRoLnJvdW5kKHgpIDogeCk7XHJcbiAgXHQvLyBAcHJvcGVydHkgeTogTnVtYmVyOyBUaGUgYHlgIGNvb3JkaW5hdGUgb2YgdGhlIHBvaW50XHJcbiAgXHR0aGlzLnkgPSAocm91bmQgPyBNYXRoLnJvdW5kKHkpIDogeSk7XHJcbiAgfVxyXG5cclxuICB2YXIgdHJ1bmMgPSBNYXRoLnRydW5jIHx8IGZ1bmN0aW9uICh2KSB7XHJcbiAgXHRyZXR1cm4gdiA+IDAgPyBNYXRoLmZsb29yKHYpIDogTWF0aC5jZWlsKHYpO1xyXG4gIH07XHJcblxyXG4gIFBvaW50LnByb3RvdHlwZSA9IHtcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGNsb25lKCk6IFBvaW50XHJcbiAgXHQvLyBSZXR1cm5zIGEgY29weSBvZiB0aGUgY3VycmVudCBwb2ludC5cclxuICBcdGNsb25lOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiBuZXcgUG9pbnQodGhpcy54LCB0aGlzLnkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGFkZChvdGhlclBvaW50OiBQb2ludCk6IFBvaW50XHJcbiAgXHQvLyBSZXR1cm5zIHRoZSByZXN1bHQgb2YgYWRkaXRpb24gb2YgdGhlIGN1cnJlbnQgYW5kIHRoZSBnaXZlbiBwb2ludHMuXHJcbiAgXHRhZGQ6IGZ1bmN0aW9uIChwb2ludCkge1xyXG4gIFx0XHQvLyBub24tZGVzdHJ1Y3RpdmUsIHJldHVybnMgYSBuZXcgcG9pbnRcclxuICBcdFx0cmV0dXJuIHRoaXMuY2xvbmUoKS5fYWRkKHRvUG9pbnQocG9pbnQpKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X2FkZDogZnVuY3Rpb24gKHBvaW50KSB7XHJcbiAgXHRcdC8vIGRlc3RydWN0aXZlLCB1c2VkIGRpcmVjdGx5IGZvciBwZXJmb3JtYW5jZSBpbiBzaXR1YXRpb25zIHdoZXJlIGl0J3Mgc2FmZSB0byBtb2RpZnkgZXhpc3RpbmcgcG9pbnRcclxuICBcdFx0dGhpcy54ICs9IHBvaW50Lng7XHJcbiAgXHRcdHRoaXMueSArPSBwb2ludC55O1xyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBzdWJ0cmFjdChvdGhlclBvaW50OiBQb2ludCk6IFBvaW50XHJcbiAgXHQvLyBSZXR1cm5zIHRoZSByZXN1bHQgb2Ygc3VidHJhY3Rpb24gb2YgdGhlIGdpdmVuIHBvaW50IGZyb20gdGhlIGN1cnJlbnQuXHJcbiAgXHRzdWJ0cmFjdDogZnVuY3Rpb24gKHBvaW50KSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLmNsb25lKCkuX3N1YnRyYWN0KHRvUG9pbnQocG9pbnQpKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X3N1YnRyYWN0OiBmdW5jdGlvbiAocG9pbnQpIHtcclxuICBcdFx0dGhpcy54IC09IHBvaW50Lng7XHJcbiAgXHRcdHRoaXMueSAtPSBwb2ludC55O1xyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBkaXZpZGVCeShudW06IE51bWJlcik6IFBvaW50XHJcbiAgXHQvLyBSZXR1cm5zIHRoZSByZXN1bHQgb2YgZGl2aXNpb24gb2YgdGhlIGN1cnJlbnQgcG9pbnQgYnkgdGhlIGdpdmVuIG51bWJlci5cclxuICBcdGRpdmlkZUJ5OiBmdW5jdGlvbiAobnVtKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLmNsb25lKCkuX2RpdmlkZUJ5KG51bSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9kaXZpZGVCeTogZnVuY3Rpb24gKG51bSkge1xyXG4gIFx0XHR0aGlzLnggLz0gbnVtO1xyXG4gIFx0XHR0aGlzLnkgLz0gbnVtO1xyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBtdWx0aXBseUJ5KG51bTogTnVtYmVyKTogUG9pbnRcclxuICBcdC8vIFJldHVybnMgdGhlIHJlc3VsdCBvZiBtdWx0aXBsaWNhdGlvbiBvZiB0aGUgY3VycmVudCBwb2ludCBieSB0aGUgZ2l2ZW4gbnVtYmVyLlxyXG4gIFx0bXVsdGlwbHlCeTogZnVuY3Rpb24gKG51bSkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5jbG9uZSgpLl9tdWx0aXBseUJ5KG51bSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9tdWx0aXBseUJ5OiBmdW5jdGlvbiAobnVtKSB7XHJcbiAgXHRcdHRoaXMueCAqPSBudW07XHJcbiAgXHRcdHRoaXMueSAqPSBudW07XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNjYWxlQnkoc2NhbGU6IFBvaW50KTogUG9pbnRcclxuICBcdC8vIE11bHRpcGx5IGVhY2ggY29vcmRpbmF0ZSBvZiB0aGUgY3VycmVudCBwb2ludCBieSBlYWNoIGNvb3JkaW5hdGUgb2ZcclxuICBcdC8vIGBzY2FsZWAuIEluIGxpbmVhciBhbGdlYnJhIHRlcm1zLCBtdWx0aXBseSB0aGUgcG9pbnQgYnkgdGhlXHJcbiAgXHQvLyBbc2NhbGluZyBtYXRyaXhdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NjYWxpbmdfJTI4Z2VvbWV0cnklMjkjTWF0cml4X3JlcHJlc2VudGF0aW9uKVxyXG4gIFx0Ly8gZGVmaW5lZCBieSBgc2NhbGVgLlxyXG4gIFx0c2NhbGVCeTogZnVuY3Rpb24gKHBvaW50KSB7XHJcbiAgXHRcdHJldHVybiBuZXcgUG9pbnQodGhpcy54ICogcG9pbnQueCwgdGhpcy55ICogcG9pbnQueSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgdW5zY2FsZUJ5KHNjYWxlOiBQb2ludCk6IFBvaW50XHJcbiAgXHQvLyBJbnZlcnNlIG9mIGBzY2FsZUJ5YC4gRGl2aWRlIGVhY2ggY29vcmRpbmF0ZSBvZiB0aGUgY3VycmVudCBwb2ludCBieVxyXG4gIFx0Ly8gZWFjaCBjb29yZGluYXRlIG9mIGBzY2FsZWAuXHJcbiAgXHR1bnNjYWxlQnk6IGZ1bmN0aW9uIChwb2ludCkge1xyXG4gIFx0XHRyZXR1cm4gbmV3IFBvaW50KHRoaXMueCAvIHBvaW50LngsIHRoaXMueSAvIHBvaW50LnkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHJvdW5kKCk6IFBvaW50XHJcbiAgXHQvLyBSZXR1cm5zIGEgY29weSBvZiB0aGUgY3VycmVudCBwb2ludCB3aXRoIHJvdW5kZWQgY29vcmRpbmF0ZXMuXHJcbiAgXHRyb3VuZDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5jbG9uZSgpLl9yb3VuZCgpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfcm91bmQ6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dGhpcy54ID0gTWF0aC5yb3VuZCh0aGlzLngpO1xyXG4gIFx0XHR0aGlzLnkgPSBNYXRoLnJvdW5kKHRoaXMueSk7XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGZsb29yKCk6IFBvaW50XHJcbiAgXHQvLyBSZXR1cm5zIGEgY29weSBvZiB0aGUgY3VycmVudCBwb2ludCB3aXRoIGZsb29yZWQgY29vcmRpbmF0ZXMgKHJvdW5kZWQgZG93bikuXHJcbiAgXHRmbG9vcjogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5jbG9uZSgpLl9mbG9vcigpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfZmxvb3I6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dGhpcy54ID0gTWF0aC5mbG9vcih0aGlzLngpO1xyXG4gIFx0XHR0aGlzLnkgPSBNYXRoLmZsb29yKHRoaXMueSk7XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGNlaWwoKTogUG9pbnRcclxuICBcdC8vIFJldHVybnMgYSBjb3B5IG9mIHRoZSBjdXJyZW50IHBvaW50IHdpdGggY2VpbGVkIGNvb3JkaW5hdGVzIChyb3VuZGVkIHVwKS5cclxuICBcdGNlaWw6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuY2xvbmUoKS5fY2VpbCgpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfY2VpbDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR0aGlzLnggPSBNYXRoLmNlaWwodGhpcy54KTtcclxuICBcdFx0dGhpcy55ID0gTWF0aC5jZWlsKHRoaXMueSk7XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHRydW5jKCk6IFBvaW50XHJcbiAgXHQvLyBSZXR1cm5zIGEgY29weSBvZiB0aGUgY3VycmVudCBwb2ludCB3aXRoIHRydW5jYXRlZCBjb29yZGluYXRlcyAocm91bmRlZCB0b3dhcmRzIHplcm8pLlxyXG4gIFx0dHJ1bmM6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuY2xvbmUoKS5fdHJ1bmMoKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X3RydW5jOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHRoaXMueCA9IHRydW5jKHRoaXMueCk7XHJcbiAgXHRcdHRoaXMueSA9IHRydW5jKHRoaXMueSk7XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGRpc3RhbmNlVG8ob3RoZXJQb2ludDogUG9pbnQpOiBOdW1iZXJcclxuICBcdC8vIFJldHVybnMgdGhlIGNhcnRlc2lhbiBkaXN0YW5jZSBiZXR3ZWVuIHRoZSBjdXJyZW50IGFuZCB0aGUgZ2l2ZW4gcG9pbnRzLlxyXG4gIFx0ZGlzdGFuY2VUbzogZnVuY3Rpb24gKHBvaW50KSB7XHJcbiAgXHRcdHBvaW50ID0gdG9Qb2ludChwb2ludCk7XHJcblxyXG4gIFx0XHR2YXIgeCA9IHBvaW50LnggLSB0aGlzLngsXHJcbiAgXHRcdCAgICB5ID0gcG9pbnQueSAtIHRoaXMueTtcclxuXHJcbiAgXHRcdHJldHVybiBNYXRoLnNxcnQoeCAqIHggKyB5ICogeSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZXF1YWxzKG90aGVyUG9pbnQ6IFBvaW50KTogQm9vbGVhblxyXG4gIFx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGdpdmVuIHBvaW50IGhhcyB0aGUgc2FtZSBjb29yZGluYXRlcy5cclxuICBcdGVxdWFsczogZnVuY3Rpb24gKHBvaW50KSB7XHJcbiAgXHRcdHBvaW50ID0gdG9Qb2ludChwb2ludCk7XHJcblxyXG4gIFx0XHRyZXR1cm4gcG9pbnQueCA9PT0gdGhpcy54ICYmXHJcbiAgXHRcdCAgICAgICBwb2ludC55ID09PSB0aGlzLnk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgY29udGFpbnMob3RoZXJQb2ludDogUG9pbnQpOiBCb29sZWFuXHJcbiAgXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiBib3RoIGNvb3JkaW5hdGVzIG9mIHRoZSBnaXZlbiBwb2ludCBhcmUgbGVzcyB0aGFuIHRoZSBjb3JyZXNwb25kaW5nIGN1cnJlbnQgcG9pbnQgY29vcmRpbmF0ZXMgKGluIGFic29sdXRlIHZhbHVlcykuXHJcbiAgXHRjb250YWluczogZnVuY3Rpb24gKHBvaW50KSB7XHJcbiAgXHRcdHBvaW50ID0gdG9Qb2ludChwb2ludCk7XHJcblxyXG4gIFx0XHRyZXR1cm4gTWF0aC5hYnMocG9pbnQueCkgPD0gTWF0aC5hYnModGhpcy54KSAmJlxyXG4gIFx0XHQgICAgICAgTWF0aC5hYnMocG9pbnQueSkgPD0gTWF0aC5hYnModGhpcy55KTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCB0b1N0cmluZygpOiBTdHJpbmdcclxuICBcdC8vIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBvaW50IGZvciBkZWJ1Z2dpbmcgcHVycG9zZXMuXHJcbiAgXHR0b1N0cmluZzogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gJ1BvaW50KCcgK1xyXG4gIFx0XHQgICAgICAgIGZvcm1hdE51bSh0aGlzLngpICsgJywgJyArXHJcbiAgXHRcdCAgICAgICAgZm9ybWF0TnVtKHRoaXMueSkgKyAnKSc7XHJcbiAgXHR9XHJcbiAgfTtcclxuXHJcbiAgLy8gQGZhY3RvcnkgTC5wb2ludCh4OiBOdW1iZXIsIHk6IE51bWJlciwgcm91bmQ/OiBCb29sZWFuKVxyXG4gIC8vIENyZWF0ZXMgYSBQb2ludCBvYmplY3Qgd2l0aCB0aGUgZ2l2ZW4gYHhgIGFuZCBgeWAgY29vcmRpbmF0ZXMuIElmIG9wdGlvbmFsIGByb3VuZGAgaXMgc2V0IHRvIHRydWUsIHJvdW5kcyB0aGUgYHhgIGFuZCBgeWAgdmFsdWVzLlxyXG5cclxuICAvLyBAYWx0ZXJuYXRpdmVcclxuICAvLyBAZmFjdG9yeSBMLnBvaW50KGNvb3JkczogTnVtYmVyW10pXHJcbiAgLy8gRXhwZWN0cyBhbiBhcnJheSBvZiB0aGUgZm9ybSBgW3gsIHldYCBpbnN0ZWFkLlxyXG5cclxuICAvLyBAYWx0ZXJuYXRpdmVcclxuICAvLyBAZmFjdG9yeSBMLnBvaW50KGNvb3JkczogT2JqZWN0KVxyXG4gIC8vIEV4cGVjdHMgYSBwbGFpbiBvYmplY3Qgb2YgdGhlIGZvcm0gYHt4OiBOdW1iZXIsIHk6IE51bWJlcn1gIGluc3RlYWQuXHJcbiAgZnVuY3Rpb24gdG9Qb2ludCh4LCB5LCByb3VuZCkge1xyXG4gIFx0aWYgKHggaW5zdGFuY2VvZiBQb2ludCkge1xyXG4gIFx0XHRyZXR1cm4geDtcclxuICBcdH1cclxuICBcdGlmIChpc0FycmF5KHgpKSB7XHJcbiAgXHRcdHJldHVybiBuZXcgUG9pbnQoeFswXSwgeFsxXSk7XHJcbiAgXHR9XHJcbiAgXHRpZiAoeCA9PT0gdW5kZWZpbmVkIHx8IHggPT09IG51bGwpIHtcclxuICBcdFx0cmV0dXJuIHg7XHJcbiAgXHR9XHJcbiAgXHRpZiAodHlwZW9mIHggPT09ICdvYmplY3QnICYmICd4JyBpbiB4ICYmICd5JyBpbiB4KSB7XHJcbiAgXHRcdHJldHVybiBuZXcgUG9pbnQoeC54LCB4LnkpO1xyXG4gIFx0fVxyXG4gIFx0cmV0dXJuIG5ldyBQb2ludCh4LCB5LCByb3VuZCk7XHJcbiAgfVxuXG4gIC8qXHJcbiAgICogQGNsYXNzIEJvdW5kc1xyXG4gICAqIEBha2EgTC5Cb3VuZHNcclxuICAgKlxyXG4gICAqIFJlcHJlc2VudHMgYSByZWN0YW5ndWxhciBhcmVhIGluIHBpeGVsIGNvb3JkaW5hdGVzLlxyXG4gICAqXHJcbiAgICogQGV4YW1wbGVcclxuICAgKlxyXG4gICAqIGBgYGpzXHJcbiAgICogdmFyIHAxID0gTC5wb2ludCgxMCwgMTApLFxyXG4gICAqIHAyID0gTC5wb2ludCg0MCwgNjApLFxyXG4gICAqIGJvdW5kcyA9IEwuYm91bmRzKHAxLCBwMik7XHJcbiAgICogYGBgXHJcbiAgICpcclxuICAgKiBBbGwgTGVhZmxldCBtZXRob2RzIHRoYXQgYWNjZXB0IGBCb3VuZHNgIG9iamVjdHMgYWxzbyBhY2NlcHQgdGhlbSBpbiBhIHNpbXBsZSBBcnJheSBmb3JtICh1bmxlc3Mgbm90ZWQgb3RoZXJ3aXNlKSwgc28gdGhlIGJvdW5kcyBleGFtcGxlIGFib3ZlIGNhbiBiZSBwYXNzZWQgbGlrZSB0aGlzOlxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiBvdGhlckJvdW5kcy5pbnRlcnNlY3RzKFtbMTAsIDEwXSwgWzQwLCA2MF1dKTtcclxuICAgKiBgYGBcclxuICAgKlxyXG4gICAqIE5vdGUgdGhhdCBgQm91bmRzYCBkb2VzIG5vdCBpbmhlcml0IGZyb20gTGVhZmxldCdzIGBDbGFzc2Agb2JqZWN0LFxyXG4gICAqIHdoaWNoIG1lYW5zIG5ldyBjbGFzc2VzIGNhbid0IGluaGVyaXQgZnJvbSBpdCwgYW5kIG5ldyBtZXRob2RzXHJcbiAgICogY2FuJ3QgYmUgYWRkZWQgdG8gaXQgd2l0aCB0aGUgYGluY2x1ZGVgIGZ1bmN0aW9uLlxyXG4gICAqL1xyXG5cclxuICBmdW5jdGlvbiBCb3VuZHMoYSwgYikge1xyXG4gIFx0aWYgKCFhKSB7IHJldHVybjsgfVxyXG5cclxuICBcdHZhciBwb2ludHMgPSBiID8gW2EsIGJdIDogYTtcclxuXHJcbiAgXHRmb3IgKHZhciBpID0gMCwgbGVuID0gcG9pbnRzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdHRoaXMuZXh0ZW5kKHBvaW50c1tpXSk7XHJcbiAgXHR9XHJcbiAgfVxyXG5cclxuICBCb3VuZHMucHJvdG90eXBlID0ge1xyXG4gIFx0Ly8gQG1ldGhvZCBleHRlbmQocG9pbnQ6IFBvaW50KTogdGhpc1xyXG4gIFx0Ly8gRXh0ZW5kcyB0aGUgYm91bmRzIHRvIGNvbnRhaW4gdGhlIGdpdmVuIHBvaW50LlxyXG5cclxuICBcdC8vIEBhbHRlcm5hdGl2ZVxyXG4gIFx0Ly8gQG1ldGhvZCBleHRlbmQob3RoZXJCb3VuZHM6IEJvdW5kcyk6IHRoaXNcclxuICBcdC8vIEV4dGVuZCB0aGUgYm91bmRzIHRvIGNvbnRhaW4gdGhlIGdpdmVuIGJvdW5kc1xyXG4gIFx0ZXh0ZW5kOiBmdW5jdGlvbiAob2JqKSB7XHJcbiAgXHRcdHZhciBtaW4yLCBtYXgyO1xyXG4gIFx0XHRpZiAoIW9iaikgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuICBcdFx0aWYgKG9iaiBpbnN0YW5jZW9mIFBvaW50IHx8IHR5cGVvZiBvYmpbMF0gPT09ICdudW1iZXInIHx8ICd4JyBpbiBvYmopIHtcclxuICBcdFx0XHRtaW4yID0gbWF4MiA9IHRvUG9pbnQob2JqKTtcclxuICBcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRvYmogPSB0b0JvdW5kcyhvYmopO1xyXG4gIFx0XHRcdG1pbjIgPSBvYmoubWluO1xyXG4gIFx0XHRcdG1heDIgPSBvYmoubWF4O1xyXG5cclxuICBcdFx0XHRpZiAoIW1pbjIgfHwgIW1heDIpIHsgcmV0dXJuIHRoaXM7IH1cclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gQHByb3BlcnR5IG1pbjogUG9pbnRcclxuICBcdFx0Ly8gVGhlIHRvcCBsZWZ0IGNvcm5lciBvZiB0aGUgcmVjdGFuZ2xlLlxyXG4gIFx0XHQvLyBAcHJvcGVydHkgbWF4OiBQb2ludFxyXG4gIFx0XHQvLyBUaGUgYm90dG9tIHJpZ2h0IGNvcm5lciBvZiB0aGUgcmVjdGFuZ2xlLlxyXG4gIFx0XHRpZiAoIXRoaXMubWluICYmICF0aGlzLm1heCkge1xyXG4gIFx0XHRcdHRoaXMubWluID0gbWluMi5jbG9uZSgpO1xyXG4gIFx0XHRcdHRoaXMubWF4ID0gbWF4Mi5jbG9uZSgpO1xyXG4gIFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdHRoaXMubWluLnggPSBNYXRoLm1pbihtaW4yLngsIHRoaXMubWluLngpO1xyXG4gIFx0XHRcdHRoaXMubWF4LnggPSBNYXRoLm1heChtYXgyLngsIHRoaXMubWF4LngpO1xyXG4gIFx0XHRcdHRoaXMubWluLnkgPSBNYXRoLm1pbihtaW4yLnksIHRoaXMubWluLnkpO1xyXG4gIFx0XHRcdHRoaXMubWF4LnkgPSBNYXRoLm1heChtYXgyLnksIHRoaXMubWF4LnkpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldENlbnRlcihyb3VuZD86IEJvb2xlYW4pOiBQb2ludFxyXG4gIFx0Ly8gUmV0dXJucyB0aGUgY2VudGVyIHBvaW50IG9mIHRoZSBib3VuZHMuXHJcbiAgXHRnZXRDZW50ZXI6IGZ1bmN0aW9uIChyb3VuZCkge1xyXG4gIFx0XHRyZXR1cm4gdG9Qb2ludChcclxuICBcdFx0ICAgICAgICAodGhpcy5taW4ueCArIHRoaXMubWF4LngpIC8gMixcclxuICBcdFx0ICAgICAgICAodGhpcy5taW4ueSArIHRoaXMubWF4LnkpIC8gMiwgcm91bmQpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldEJvdHRvbUxlZnQoKTogUG9pbnRcclxuICBcdC8vIFJldHVybnMgdGhlIGJvdHRvbS1sZWZ0IHBvaW50IG9mIHRoZSBib3VuZHMuXHJcbiAgXHRnZXRCb3R0b21MZWZ0OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0b1BvaW50KHRoaXMubWluLngsIHRoaXMubWF4LnkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldFRvcFJpZ2h0KCk6IFBvaW50XHJcbiAgXHQvLyBSZXR1cm5zIHRoZSB0b3AtcmlnaHQgcG9pbnQgb2YgdGhlIGJvdW5kcy5cclxuICBcdGdldFRvcFJpZ2h0OiBmdW5jdGlvbiAoKSB7IC8vIC0+IFBvaW50XHJcbiAgXHRcdHJldHVybiB0b1BvaW50KHRoaXMubWF4LngsIHRoaXMubWluLnkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldFRvcExlZnQoKTogUG9pbnRcclxuICBcdC8vIFJldHVybnMgdGhlIHRvcC1sZWZ0IHBvaW50IG9mIHRoZSBib3VuZHMgKGkuZS4gW2B0aGlzLm1pbmBdKCNib3VuZHMtbWluKSkuXHJcbiAgXHRnZXRUb3BMZWZ0OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLm1pbjsgLy8gbGVmdCwgdG9wXHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0Qm90dG9tUmlnaHQoKTogUG9pbnRcclxuICBcdC8vIFJldHVybnMgdGhlIGJvdHRvbS1yaWdodCBwb2ludCBvZiB0aGUgYm91bmRzIChpLmUuIFtgdGhpcy5tYXhgXSgjYm91bmRzLW1heCkpLlxyXG4gIFx0Z2V0Qm90dG9tUmlnaHQ6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMubWF4OyAvLyByaWdodCwgYm90dG9tXHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0U2l6ZSgpOiBQb2ludFxyXG4gIFx0Ly8gUmV0dXJucyB0aGUgc2l6ZSBvZiB0aGUgZ2l2ZW4gYm91bmRzXHJcbiAgXHRnZXRTaXplOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLm1heC5zdWJ0cmFjdCh0aGlzLm1pbik7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgY29udGFpbnMob3RoZXJCb3VuZHM6IEJvdW5kcyk6IEJvb2xlYW5cclxuICBcdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSByZWN0YW5nbGUgY29udGFpbnMgdGhlIGdpdmVuIG9uZS5cclxuICBcdC8vIEBhbHRlcm5hdGl2ZVxyXG4gIFx0Ly8gQG1ldGhvZCBjb250YWlucyhwb2ludDogUG9pbnQpOiBCb29sZWFuXHJcbiAgXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcmVjdGFuZ2xlIGNvbnRhaW5zIHRoZSBnaXZlbiBwb2ludC5cclxuICBcdGNvbnRhaW5zOiBmdW5jdGlvbiAob2JqKSB7XHJcbiAgXHRcdHZhciBtaW4sIG1heDtcclxuXHJcbiAgXHRcdGlmICh0eXBlb2Ygb2JqWzBdID09PSAnbnVtYmVyJyB8fCBvYmogaW5zdGFuY2VvZiBQb2ludCkge1xyXG4gIFx0XHRcdG9iaiA9IHRvUG9pbnQob2JqKTtcclxuICBcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRvYmogPSB0b0JvdW5kcyhvYmopO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAob2JqIGluc3RhbmNlb2YgQm91bmRzKSB7XHJcbiAgXHRcdFx0bWluID0gb2JqLm1pbjtcclxuICBcdFx0XHRtYXggPSBvYmoubWF4O1xyXG4gIFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdG1pbiA9IG1heCA9IG9iajtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0cmV0dXJuIChtaW4ueCA+PSB0aGlzLm1pbi54KSAmJlxyXG4gIFx0XHQgICAgICAgKG1heC54IDw9IHRoaXMubWF4LngpICYmXHJcbiAgXHRcdCAgICAgICAobWluLnkgPj0gdGhpcy5taW4ueSkgJiZcclxuICBcdFx0ICAgICAgIChtYXgueSA8PSB0aGlzLm1heC55KTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBpbnRlcnNlY3RzKG90aGVyQm91bmRzOiBCb3VuZHMpOiBCb29sZWFuXHJcbiAgXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcmVjdGFuZ2xlIGludGVyc2VjdHMgdGhlIGdpdmVuIGJvdW5kcy4gVHdvIGJvdW5kc1xyXG4gIFx0Ly8gaW50ZXJzZWN0IGlmIHRoZXkgaGF2ZSBhdCBsZWFzdCBvbmUgcG9pbnQgaW4gY29tbW9uLlxyXG4gIFx0aW50ZXJzZWN0czogZnVuY3Rpb24gKGJvdW5kcykgeyAvLyAoQm91bmRzKSAtPiBCb29sZWFuXHJcbiAgXHRcdGJvdW5kcyA9IHRvQm91bmRzKGJvdW5kcyk7XHJcblxyXG4gIFx0XHR2YXIgbWluID0gdGhpcy5taW4sXHJcbiAgXHRcdCAgICBtYXggPSB0aGlzLm1heCxcclxuICBcdFx0ICAgIG1pbjIgPSBib3VuZHMubWluLFxyXG4gIFx0XHQgICAgbWF4MiA9IGJvdW5kcy5tYXgsXHJcbiAgXHRcdCAgICB4SW50ZXJzZWN0cyA9IChtYXgyLnggPj0gbWluLngpICYmIChtaW4yLnggPD0gbWF4LngpLFxyXG4gIFx0XHQgICAgeUludGVyc2VjdHMgPSAobWF4Mi55ID49IG1pbi55KSAmJiAobWluMi55IDw9IG1heC55KTtcclxuXHJcbiAgXHRcdHJldHVybiB4SW50ZXJzZWN0cyAmJiB5SW50ZXJzZWN0cztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBvdmVybGFwcyhvdGhlckJvdW5kczogQm91bmRzKTogQm9vbGVhblxyXG4gIFx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHJlY3RhbmdsZSBvdmVybGFwcyB0aGUgZ2l2ZW4gYm91bmRzLiBUd28gYm91bmRzXHJcbiAgXHQvLyBvdmVybGFwIGlmIHRoZWlyIGludGVyc2VjdGlvbiBpcyBhbiBhcmVhLlxyXG4gIFx0b3ZlcmxhcHM6IGZ1bmN0aW9uIChib3VuZHMpIHsgLy8gKEJvdW5kcykgLT4gQm9vbGVhblxyXG4gIFx0XHRib3VuZHMgPSB0b0JvdW5kcyhib3VuZHMpO1xyXG5cclxuICBcdFx0dmFyIG1pbiA9IHRoaXMubWluLFxyXG4gIFx0XHQgICAgbWF4ID0gdGhpcy5tYXgsXHJcbiAgXHRcdCAgICBtaW4yID0gYm91bmRzLm1pbixcclxuICBcdFx0ICAgIG1heDIgPSBib3VuZHMubWF4LFxyXG4gIFx0XHQgICAgeE92ZXJsYXBzID0gKG1heDIueCA+IG1pbi54KSAmJiAobWluMi54IDwgbWF4LngpLFxyXG4gIFx0XHQgICAgeU92ZXJsYXBzID0gKG1heDIueSA+IG1pbi55KSAmJiAobWluMi55IDwgbWF4LnkpO1xyXG5cclxuICBcdFx0cmV0dXJuIHhPdmVybGFwcyAmJiB5T3ZlcmxhcHM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgaXNWYWxpZCgpOiBCb29sZWFuXHJcbiAgXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgYm91bmRzIGFyZSBwcm9wZXJseSBpbml0aWFsaXplZC5cclxuICBcdGlzVmFsaWQ6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuICEhKHRoaXMubWluICYmIHRoaXMubWF4KTtcclxuICBcdH0sXHJcblxyXG5cclxuICBcdC8vIEBtZXRob2QgcGFkKGJ1ZmZlclJhdGlvOiBOdW1iZXIpOiBCb3VuZHNcclxuICBcdC8vIFJldHVybnMgYm91bmRzIGNyZWF0ZWQgYnkgZXh0ZW5kaW5nIG9yIHJldHJhY3RpbmcgdGhlIGN1cnJlbnQgYm91bmRzIGJ5IGEgZ2l2ZW4gcmF0aW8gaW4gZWFjaCBkaXJlY3Rpb24uXHJcbiAgXHQvLyBGb3IgZXhhbXBsZSwgYSByYXRpbyBvZiAwLjUgZXh0ZW5kcyB0aGUgYm91bmRzIGJ5IDUwJSBpbiBlYWNoIGRpcmVjdGlvbi5cclxuICBcdC8vIE5lZ2F0aXZlIHZhbHVlcyB3aWxsIHJldHJhY3QgdGhlIGJvdW5kcy5cclxuICBcdHBhZDogZnVuY3Rpb24gKGJ1ZmZlclJhdGlvKSB7XHJcbiAgXHRcdHZhciBtaW4gPSB0aGlzLm1pbixcclxuICBcdFx0bWF4ID0gdGhpcy5tYXgsXHJcbiAgXHRcdGhlaWdodEJ1ZmZlciA9IE1hdGguYWJzKG1pbi54IC0gbWF4LngpICogYnVmZmVyUmF0aW8sXHJcbiAgXHRcdHdpZHRoQnVmZmVyID0gTWF0aC5hYnMobWluLnkgLSBtYXgueSkgKiBidWZmZXJSYXRpbztcclxuXHJcblxyXG4gIFx0XHRyZXR1cm4gdG9Cb3VuZHMoXHJcbiAgXHRcdFx0dG9Qb2ludChtaW4ueCAtIGhlaWdodEJ1ZmZlciwgbWluLnkgLSB3aWR0aEJ1ZmZlciksXHJcbiAgXHRcdFx0dG9Qb2ludChtYXgueCArIGhlaWdodEJ1ZmZlciwgbWF4LnkgKyB3aWR0aEJ1ZmZlcikpO1xyXG4gIFx0fSxcclxuXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBlcXVhbHMob3RoZXJCb3VuZHM6IEJvdW5kcyk6IEJvb2xlYW5cclxuICBcdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSByZWN0YW5nbGUgaXMgZXF1aXZhbGVudCB0byB0aGUgZ2l2ZW4gYm91bmRzLlxyXG4gIFx0ZXF1YWxzOiBmdW5jdGlvbiAoYm91bmRzKSB7XHJcbiAgXHRcdGlmICghYm91bmRzKSB7IHJldHVybiBmYWxzZTsgfVxyXG5cclxuICBcdFx0Ym91bmRzID0gdG9Cb3VuZHMoYm91bmRzKTtcclxuXHJcbiAgXHRcdHJldHVybiB0aGlzLm1pbi5lcXVhbHMoYm91bmRzLmdldFRvcExlZnQoKSkgJiZcclxuICBcdFx0XHR0aGlzLm1heC5lcXVhbHMoYm91bmRzLmdldEJvdHRvbVJpZ2h0KCkpO1xyXG4gIFx0fSxcclxuICB9O1xyXG5cclxuXHJcbiAgLy8gQGZhY3RvcnkgTC5ib3VuZHMoY29ybmVyMTogUG9pbnQsIGNvcm5lcjI6IFBvaW50KVxyXG4gIC8vIENyZWF0ZXMgYSBCb3VuZHMgb2JqZWN0IGZyb20gdHdvIGNvcm5lcnMgY29vcmRpbmF0ZSBwYWlycy5cclxuICAvLyBAYWx0ZXJuYXRpdmVcclxuICAvLyBAZmFjdG9yeSBMLmJvdW5kcyhwb2ludHM6IFBvaW50W10pXHJcbiAgLy8gQ3JlYXRlcyBhIEJvdW5kcyBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gYXJyYXkgb2YgcG9pbnRzLlxyXG4gIGZ1bmN0aW9uIHRvQm91bmRzKGEsIGIpIHtcclxuICBcdGlmICghYSB8fCBhIGluc3RhbmNlb2YgQm91bmRzKSB7XHJcbiAgXHRcdHJldHVybiBhO1xyXG4gIFx0fVxyXG4gIFx0cmV0dXJuIG5ldyBCb3VuZHMoYSwgYik7XHJcbiAgfVxuXG4gIC8qXHJcbiAgICogQGNsYXNzIExhdExuZ0JvdW5kc1xyXG4gICAqIEBha2EgTC5MYXRMbmdCb3VuZHNcclxuICAgKlxyXG4gICAqIFJlcHJlc2VudHMgYSByZWN0YW5ndWxhciBnZW9ncmFwaGljYWwgYXJlYSBvbiBhIG1hcC5cclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICpcclxuICAgKiBgYGBqc1xyXG4gICAqIHZhciBjb3JuZXIxID0gTC5sYXRMbmcoNDAuNzEyLCAtNzQuMjI3KSxcclxuICAgKiBjb3JuZXIyID0gTC5sYXRMbmcoNDAuNzc0LCAtNzQuMTI1KSxcclxuICAgKiBib3VuZHMgPSBMLmxhdExuZ0JvdW5kcyhjb3JuZXIxLCBjb3JuZXIyKTtcclxuICAgKiBgYGBcclxuICAgKlxyXG4gICAqIEFsbCBMZWFmbGV0IG1ldGhvZHMgdGhhdCBhY2NlcHQgTGF0TG5nQm91bmRzIG9iamVjdHMgYWxzbyBhY2NlcHQgdGhlbSBpbiBhIHNpbXBsZSBBcnJheSBmb3JtICh1bmxlc3Mgbm90ZWQgb3RoZXJ3aXNlKSwgc28gdGhlIGJvdW5kcyBleGFtcGxlIGFib3ZlIGNhbiBiZSBwYXNzZWQgbGlrZSB0aGlzOlxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiBtYXAuZml0Qm91bmRzKFtcclxuICAgKiBcdFs0MC43MTIsIC03NC4yMjddLFxyXG4gICAqIFx0WzQwLjc3NCwgLTc0LjEyNV1cclxuICAgKiBdKTtcclxuICAgKiBgYGBcclxuICAgKlxyXG4gICAqIENhdXRpb246IGlmIHRoZSBhcmVhIGNyb3NzZXMgdGhlIGFudGltZXJpZGlhbiAob2Z0ZW4gY29uZnVzZWQgd2l0aCB0aGUgSW50ZXJuYXRpb25hbCBEYXRlIExpbmUpLCB5b3UgbXVzdCBzcGVjaWZ5IGNvcm5lcnMgX291dHNpZGVfIHRoZSBbLTE4MCwgMTgwXSBkZWdyZWVzIGxvbmdpdHVkZSByYW5nZS5cclxuICAgKlxyXG4gICAqIE5vdGUgdGhhdCBgTGF0TG5nQm91bmRzYCBkb2VzIG5vdCBpbmhlcml0IGZyb20gTGVhZmxldCdzIGBDbGFzc2Agb2JqZWN0LFxyXG4gICAqIHdoaWNoIG1lYW5zIG5ldyBjbGFzc2VzIGNhbid0IGluaGVyaXQgZnJvbSBpdCwgYW5kIG5ldyBtZXRob2RzXHJcbiAgICogY2FuJ3QgYmUgYWRkZWQgdG8gaXQgd2l0aCB0aGUgYGluY2x1ZGVgIGZ1bmN0aW9uLlxyXG4gICAqL1xyXG5cclxuICBmdW5jdGlvbiBMYXRMbmdCb3VuZHMoY29ybmVyMSwgY29ybmVyMikgeyAvLyAoTGF0TG5nLCBMYXRMbmcpIG9yIChMYXRMbmdbXSlcclxuICBcdGlmICghY29ybmVyMSkgeyByZXR1cm47IH1cclxuXHJcbiAgXHR2YXIgbGF0bG5ncyA9IGNvcm5lcjIgPyBbY29ybmVyMSwgY29ybmVyMl0gOiBjb3JuZXIxO1xyXG5cclxuICBcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBsYXRsbmdzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdHRoaXMuZXh0ZW5kKGxhdGxuZ3NbaV0pO1xyXG4gIFx0fVxyXG4gIH1cclxuXHJcbiAgTGF0TG5nQm91bmRzLnByb3RvdHlwZSA9IHtcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGV4dGVuZChsYXRsbmc6IExhdExuZyk6IHRoaXNcclxuICBcdC8vIEV4dGVuZCB0aGUgYm91bmRzIHRvIGNvbnRhaW4gdGhlIGdpdmVuIHBvaW50XHJcblxyXG4gIFx0Ly8gQGFsdGVybmF0aXZlXHJcbiAgXHQvLyBAbWV0aG9kIGV4dGVuZChvdGhlckJvdW5kczogTGF0TG5nQm91bmRzKTogdGhpc1xyXG4gIFx0Ly8gRXh0ZW5kIHRoZSBib3VuZHMgdG8gY29udGFpbiB0aGUgZ2l2ZW4gYm91bmRzXHJcbiAgXHRleHRlbmQ6IGZ1bmN0aW9uIChvYmopIHtcclxuICBcdFx0dmFyIHN3ID0gdGhpcy5fc291dGhXZXN0LFxyXG4gIFx0XHQgICAgbmUgPSB0aGlzLl9ub3J0aEVhc3QsXHJcbiAgXHRcdCAgICBzdzIsIG5lMjtcclxuXHJcbiAgXHRcdGlmIChvYmogaW5zdGFuY2VvZiBMYXRMbmcpIHtcclxuICBcdFx0XHRzdzIgPSBvYmo7XHJcbiAgXHRcdFx0bmUyID0gb2JqO1xyXG5cclxuICBcdFx0fSBlbHNlIGlmIChvYmogaW5zdGFuY2VvZiBMYXRMbmdCb3VuZHMpIHtcclxuICBcdFx0XHRzdzIgPSBvYmouX3NvdXRoV2VzdDtcclxuICBcdFx0XHRuZTIgPSBvYmouX25vcnRoRWFzdDtcclxuXHJcbiAgXHRcdFx0aWYgKCFzdzIgfHwgIW5lMikgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuICBcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRyZXR1cm4gb2JqID8gdGhpcy5leHRlbmQodG9MYXRMbmcob2JqKSB8fCB0b0xhdExuZ0JvdW5kcyhvYmopKSA6IHRoaXM7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmICghc3cgJiYgIW5lKSB7XHJcbiAgXHRcdFx0dGhpcy5fc291dGhXZXN0ID0gbmV3IExhdExuZyhzdzIubGF0LCBzdzIubG5nKTtcclxuICBcdFx0XHR0aGlzLl9ub3J0aEVhc3QgPSBuZXcgTGF0TG5nKG5lMi5sYXQsIG5lMi5sbmcpO1xyXG4gIFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdHN3LmxhdCA9IE1hdGgubWluKHN3Mi5sYXQsIHN3LmxhdCk7XHJcbiAgXHRcdFx0c3cubG5nID0gTWF0aC5taW4oc3cyLmxuZywgc3cubG5nKTtcclxuICBcdFx0XHRuZS5sYXQgPSBNYXRoLm1heChuZTIubGF0LCBuZS5sYXQpO1xyXG4gIFx0XHRcdG5lLmxuZyA9IE1hdGgubWF4KG5lMi5sbmcsIG5lLmxuZyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHBhZChidWZmZXJSYXRpbzogTnVtYmVyKTogTGF0TG5nQm91bmRzXHJcbiAgXHQvLyBSZXR1cm5zIGJvdW5kcyBjcmVhdGVkIGJ5IGV4dGVuZGluZyBvciByZXRyYWN0aW5nIHRoZSBjdXJyZW50IGJvdW5kcyBieSBhIGdpdmVuIHJhdGlvIGluIGVhY2ggZGlyZWN0aW9uLlxyXG4gIFx0Ly8gRm9yIGV4YW1wbGUsIGEgcmF0aW8gb2YgMC41IGV4dGVuZHMgdGhlIGJvdW5kcyBieSA1MCUgaW4gZWFjaCBkaXJlY3Rpb24uXHJcbiAgXHQvLyBOZWdhdGl2ZSB2YWx1ZXMgd2lsbCByZXRyYWN0IHRoZSBib3VuZHMuXHJcbiAgXHRwYWQ6IGZ1bmN0aW9uIChidWZmZXJSYXRpbykge1xyXG4gIFx0XHR2YXIgc3cgPSB0aGlzLl9zb3V0aFdlc3QsXHJcbiAgXHRcdCAgICBuZSA9IHRoaXMuX25vcnRoRWFzdCxcclxuICBcdFx0ICAgIGhlaWdodEJ1ZmZlciA9IE1hdGguYWJzKHN3LmxhdCAtIG5lLmxhdCkgKiBidWZmZXJSYXRpbyxcclxuICBcdFx0ICAgIHdpZHRoQnVmZmVyID0gTWF0aC5hYnMoc3cubG5nIC0gbmUubG5nKSAqIGJ1ZmZlclJhdGlvO1xyXG5cclxuICBcdFx0cmV0dXJuIG5ldyBMYXRMbmdCb3VuZHMoXHJcbiAgXHRcdCAgICAgICAgbmV3IExhdExuZyhzdy5sYXQgLSBoZWlnaHRCdWZmZXIsIHN3LmxuZyAtIHdpZHRoQnVmZmVyKSxcclxuICBcdFx0ICAgICAgICBuZXcgTGF0TG5nKG5lLmxhdCArIGhlaWdodEJ1ZmZlciwgbmUubG5nICsgd2lkdGhCdWZmZXIpKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRDZW50ZXIoKTogTGF0TG5nXHJcbiAgXHQvLyBSZXR1cm5zIHRoZSBjZW50ZXIgcG9pbnQgb2YgdGhlIGJvdW5kcy5cclxuICBcdGdldENlbnRlcjogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gbmV3IExhdExuZyhcclxuICBcdFx0ICAgICAgICAodGhpcy5fc291dGhXZXN0LmxhdCArIHRoaXMuX25vcnRoRWFzdC5sYXQpIC8gMixcclxuICBcdFx0ICAgICAgICAodGhpcy5fc291dGhXZXN0LmxuZyArIHRoaXMuX25vcnRoRWFzdC5sbmcpIC8gMik7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0U291dGhXZXN0KCk6IExhdExuZ1xyXG4gIFx0Ly8gUmV0dXJucyB0aGUgc291dGgtd2VzdCBwb2ludCBvZiB0aGUgYm91bmRzLlxyXG4gIFx0Z2V0U291dGhXZXN0OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLl9zb3V0aFdlc3Q7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0Tm9ydGhFYXN0KCk6IExhdExuZ1xyXG4gIFx0Ly8gUmV0dXJucyB0aGUgbm9ydGgtZWFzdCBwb2ludCBvZiB0aGUgYm91bmRzLlxyXG4gIFx0Z2V0Tm9ydGhFYXN0OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLl9ub3J0aEVhc3Q7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0Tm9ydGhXZXN0KCk6IExhdExuZ1xyXG4gIFx0Ly8gUmV0dXJucyB0aGUgbm9ydGgtd2VzdCBwb2ludCBvZiB0aGUgYm91bmRzLlxyXG4gIFx0Z2V0Tm9ydGhXZXN0OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiBuZXcgTGF0TG5nKHRoaXMuZ2V0Tm9ydGgoKSwgdGhpcy5nZXRXZXN0KCkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldFNvdXRoRWFzdCgpOiBMYXRMbmdcclxuICBcdC8vIFJldHVybnMgdGhlIHNvdXRoLWVhc3QgcG9pbnQgb2YgdGhlIGJvdW5kcy5cclxuICBcdGdldFNvdXRoRWFzdDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gbmV3IExhdExuZyh0aGlzLmdldFNvdXRoKCksIHRoaXMuZ2V0RWFzdCgpKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRXZXN0KCk6IE51bWJlclxyXG4gIFx0Ly8gUmV0dXJucyB0aGUgd2VzdCBsb25naXR1ZGUgb2YgdGhlIGJvdW5kc1xyXG4gIFx0Z2V0V2VzdDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5fc291dGhXZXN0LmxuZztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRTb3V0aCgpOiBOdW1iZXJcclxuICBcdC8vIFJldHVybnMgdGhlIHNvdXRoIGxhdGl0dWRlIG9mIHRoZSBib3VuZHNcclxuICBcdGdldFNvdXRoOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLl9zb3V0aFdlc3QubGF0O1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldEVhc3QoKTogTnVtYmVyXHJcbiAgXHQvLyBSZXR1cm5zIHRoZSBlYXN0IGxvbmdpdHVkZSBvZiB0aGUgYm91bmRzXHJcbiAgXHRnZXRFYXN0OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLl9ub3J0aEVhc3QubG5nO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldE5vcnRoKCk6IE51bWJlclxyXG4gIFx0Ly8gUmV0dXJucyB0aGUgbm9ydGggbGF0aXR1ZGUgb2YgdGhlIGJvdW5kc1xyXG4gIFx0Z2V0Tm9ydGg6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuX25vcnRoRWFzdC5sYXQ7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgY29udGFpbnMob3RoZXJCb3VuZHM6IExhdExuZ0JvdW5kcyk6IEJvb2xlYW5cclxuICBcdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSByZWN0YW5nbGUgY29udGFpbnMgdGhlIGdpdmVuIG9uZS5cclxuXHJcbiAgXHQvLyBAYWx0ZXJuYXRpdmVcclxuICBcdC8vIEBtZXRob2QgY29udGFpbnMgKGxhdGxuZzogTGF0TG5nKTogQm9vbGVhblxyXG4gIFx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHJlY3RhbmdsZSBjb250YWlucyB0aGUgZ2l2ZW4gcG9pbnQuXHJcbiAgXHRjb250YWluczogZnVuY3Rpb24gKG9iaikgeyAvLyAoTGF0TG5nQm91bmRzKSBvciAoTGF0TG5nKSAtPiBCb29sZWFuXHJcbiAgXHRcdGlmICh0eXBlb2Ygb2JqWzBdID09PSAnbnVtYmVyJyB8fCBvYmogaW5zdGFuY2VvZiBMYXRMbmcgfHwgJ2xhdCcgaW4gb2JqKSB7XHJcbiAgXHRcdFx0b2JqID0gdG9MYXRMbmcob2JqKTtcclxuICBcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRvYmogPSB0b0xhdExuZ0JvdW5kcyhvYmopO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgc3cgPSB0aGlzLl9zb3V0aFdlc3QsXHJcbiAgXHRcdCAgICBuZSA9IHRoaXMuX25vcnRoRWFzdCxcclxuICBcdFx0ICAgIHN3MiwgbmUyO1xyXG5cclxuICBcdFx0aWYgKG9iaiBpbnN0YW5jZW9mIExhdExuZ0JvdW5kcykge1xyXG4gIFx0XHRcdHN3MiA9IG9iai5nZXRTb3V0aFdlc3QoKTtcclxuICBcdFx0XHRuZTIgPSBvYmouZ2V0Tm9ydGhFYXN0KCk7XHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0c3cyID0gbmUyID0gb2JqO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gKHN3Mi5sYXQgPj0gc3cubGF0KSAmJiAobmUyLmxhdCA8PSBuZS5sYXQpICYmXHJcbiAgXHRcdCAgICAgICAoc3cyLmxuZyA+PSBzdy5sbmcpICYmIChuZTIubG5nIDw9IG5lLmxuZyk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgaW50ZXJzZWN0cyhvdGhlckJvdW5kczogTGF0TG5nQm91bmRzKTogQm9vbGVhblxyXG4gIFx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHJlY3RhbmdsZSBpbnRlcnNlY3RzIHRoZSBnaXZlbiBib3VuZHMuIFR3byBib3VuZHMgaW50ZXJzZWN0IGlmIHRoZXkgaGF2ZSBhdCBsZWFzdCBvbmUgcG9pbnQgaW4gY29tbW9uLlxyXG4gIFx0aW50ZXJzZWN0czogZnVuY3Rpb24gKGJvdW5kcykge1xyXG4gIFx0XHRib3VuZHMgPSB0b0xhdExuZ0JvdW5kcyhib3VuZHMpO1xyXG5cclxuICBcdFx0dmFyIHN3ID0gdGhpcy5fc291dGhXZXN0LFxyXG4gIFx0XHQgICAgbmUgPSB0aGlzLl9ub3J0aEVhc3QsXHJcbiAgXHRcdCAgICBzdzIgPSBib3VuZHMuZ2V0U291dGhXZXN0KCksXHJcbiAgXHRcdCAgICBuZTIgPSBib3VuZHMuZ2V0Tm9ydGhFYXN0KCksXHJcblxyXG4gIFx0XHQgICAgbGF0SW50ZXJzZWN0cyA9IChuZTIubGF0ID49IHN3LmxhdCkgJiYgKHN3Mi5sYXQgPD0gbmUubGF0KSxcclxuICBcdFx0ICAgIGxuZ0ludGVyc2VjdHMgPSAobmUyLmxuZyA+PSBzdy5sbmcpICYmIChzdzIubG5nIDw9IG5lLmxuZyk7XHJcblxyXG4gIFx0XHRyZXR1cm4gbGF0SW50ZXJzZWN0cyAmJiBsbmdJbnRlcnNlY3RzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIG92ZXJsYXBzKG90aGVyQm91bmRzOiBMYXRMbmdCb3VuZHMpOiBCb29sZWFuXHJcbiAgXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcmVjdGFuZ2xlIG92ZXJsYXBzIHRoZSBnaXZlbiBib3VuZHMuIFR3byBib3VuZHMgb3ZlcmxhcCBpZiB0aGVpciBpbnRlcnNlY3Rpb24gaXMgYW4gYXJlYS5cclxuICBcdG92ZXJsYXBzOiBmdW5jdGlvbiAoYm91bmRzKSB7XHJcbiAgXHRcdGJvdW5kcyA9IHRvTGF0TG5nQm91bmRzKGJvdW5kcyk7XHJcblxyXG4gIFx0XHR2YXIgc3cgPSB0aGlzLl9zb3V0aFdlc3QsXHJcbiAgXHRcdCAgICBuZSA9IHRoaXMuX25vcnRoRWFzdCxcclxuICBcdFx0ICAgIHN3MiA9IGJvdW5kcy5nZXRTb3V0aFdlc3QoKSxcclxuICBcdFx0ICAgIG5lMiA9IGJvdW5kcy5nZXROb3J0aEVhc3QoKSxcclxuXHJcbiAgXHRcdCAgICBsYXRPdmVybGFwcyA9IChuZTIubGF0ID4gc3cubGF0KSAmJiAoc3cyLmxhdCA8IG5lLmxhdCksXHJcbiAgXHRcdCAgICBsbmdPdmVybGFwcyA9IChuZTIubG5nID4gc3cubG5nKSAmJiAoc3cyLmxuZyA8IG5lLmxuZyk7XHJcblxyXG4gIFx0XHRyZXR1cm4gbGF0T3ZlcmxhcHMgJiYgbG5nT3ZlcmxhcHM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgdG9CQm94U3RyaW5nKCk6IFN0cmluZ1xyXG4gIFx0Ly8gUmV0dXJucyBhIHN0cmluZyB3aXRoIGJvdW5kaW5nIGJveCBjb29yZGluYXRlcyBpbiBhICdzb3V0aHdlc3RfbG5nLHNvdXRod2VzdF9sYXQsbm9ydGhlYXN0X2xuZyxub3J0aGVhc3RfbGF0JyBmb3JtYXQuIFVzZWZ1bCBmb3Igc2VuZGluZyByZXF1ZXN0cyB0byB3ZWIgc2VydmljZXMgdGhhdCByZXR1cm4gZ2VvIGRhdGEuXHJcbiAgXHR0b0JCb3hTdHJpbmc6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIFt0aGlzLmdldFdlc3QoKSwgdGhpcy5nZXRTb3V0aCgpLCB0aGlzLmdldEVhc3QoKSwgdGhpcy5nZXROb3J0aCgpXS5qb2luKCcsJyk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZXF1YWxzKG90aGVyQm91bmRzOiBMYXRMbmdCb3VuZHMsIG1heE1hcmdpbj86IE51bWJlcik6IEJvb2xlYW5cclxuICBcdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSByZWN0YW5nbGUgaXMgZXF1aXZhbGVudCAod2l0aGluIGEgc21hbGwgbWFyZ2luIG9mIGVycm9yKSB0byB0aGUgZ2l2ZW4gYm91bmRzLiBUaGUgbWFyZ2luIG9mIGVycm9yIGNhbiBiZSBvdmVycmlkZGVuIGJ5IHNldHRpbmcgYG1heE1hcmdpbmAgdG8gYSBzbWFsbCBudW1iZXIuXHJcbiAgXHRlcXVhbHM6IGZ1bmN0aW9uIChib3VuZHMsIG1heE1hcmdpbikge1xyXG4gIFx0XHRpZiAoIWJvdW5kcykgeyByZXR1cm4gZmFsc2U7IH1cclxuXHJcbiAgXHRcdGJvdW5kcyA9IHRvTGF0TG5nQm91bmRzKGJvdW5kcyk7XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcy5fc291dGhXZXN0LmVxdWFscyhib3VuZHMuZ2V0U291dGhXZXN0KCksIG1heE1hcmdpbikgJiZcclxuICBcdFx0ICAgICAgIHRoaXMuX25vcnRoRWFzdC5lcXVhbHMoYm91bmRzLmdldE5vcnRoRWFzdCgpLCBtYXhNYXJnaW4pO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGlzVmFsaWQoKTogQm9vbGVhblxyXG4gIFx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGJvdW5kcyBhcmUgcHJvcGVybHkgaW5pdGlhbGl6ZWQuXHJcbiAgXHRpc1ZhbGlkOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiAhISh0aGlzLl9zb3V0aFdlc3QgJiYgdGhpcy5fbm9ydGhFYXN0KTtcclxuICBcdH1cclxuICB9O1xyXG5cclxuICAvLyBUT0RPIEludGVybmF0aW9uYWwgZGF0ZSBsaW5lP1xyXG5cclxuICAvLyBAZmFjdG9yeSBMLmxhdExuZ0JvdW5kcyhjb3JuZXIxOiBMYXRMbmcsIGNvcm5lcjI6IExhdExuZylcclxuICAvLyBDcmVhdGVzIGEgYExhdExuZ0JvdW5kc2Agb2JqZWN0IGJ5IGRlZmluaW5nIHR3byBkaWFnb25hbGx5IG9wcG9zaXRlIGNvcm5lcnMgb2YgdGhlIHJlY3RhbmdsZS5cclxuXHJcbiAgLy8gQGFsdGVybmF0aXZlXHJcbiAgLy8gQGZhY3RvcnkgTC5sYXRMbmdCb3VuZHMobGF0bG5nczogTGF0TG5nW10pXHJcbiAgLy8gQ3JlYXRlcyBhIGBMYXRMbmdCb3VuZHNgIG9iamVjdCBkZWZpbmVkIGJ5IHRoZSBnZW9ncmFwaGljYWwgcG9pbnRzIGl0IGNvbnRhaW5zLiBWZXJ5IHVzZWZ1bCBmb3Igem9vbWluZyB0aGUgbWFwIHRvIGZpdCBhIHBhcnRpY3VsYXIgc2V0IG9mIGxvY2F0aW9ucyB3aXRoIFtgZml0Qm91bmRzYF0oI21hcC1maXRib3VuZHMpLlxyXG4gIGZ1bmN0aW9uIHRvTGF0TG5nQm91bmRzKGEsIGIpIHtcclxuICBcdGlmIChhIGluc3RhbmNlb2YgTGF0TG5nQm91bmRzKSB7XHJcbiAgXHRcdHJldHVybiBhO1xyXG4gIFx0fVxyXG4gIFx0cmV0dXJuIG5ldyBMYXRMbmdCb3VuZHMoYSwgYik7XHJcbiAgfVxuXG4gIC8qIEBjbGFzcyBMYXRMbmdcclxuICAgKiBAYWthIEwuTGF0TG5nXHJcbiAgICpcclxuICAgKiBSZXByZXNlbnRzIGEgZ2VvZ3JhcGhpY2FsIHBvaW50IHdpdGggYSBjZXJ0YWluIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUuXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqXHJcbiAgICogYGBgXHJcbiAgICogdmFyIGxhdGxuZyA9IEwubGF0TG5nKDUwLjUsIDMwLjUpO1xyXG4gICAqIGBgYFxyXG4gICAqXHJcbiAgICogQWxsIExlYWZsZXQgbWV0aG9kcyB0aGF0IGFjY2VwdCBMYXRMbmcgb2JqZWN0cyBhbHNvIGFjY2VwdCB0aGVtIGluIGEgc2ltcGxlIEFycmF5IGZvcm0gYW5kIHNpbXBsZSBvYmplY3QgZm9ybSAodW5sZXNzIG5vdGVkIG90aGVyd2lzZSksIHNvIHRoZXNlIGxpbmVzIGFyZSBlcXVpdmFsZW50OlxyXG4gICAqXHJcbiAgICogYGBgXHJcbiAgICogbWFwLnBhblRvKFs1MCwgMzBdKTtcclxuICAgKiBtYXAucGFuVG8oe2xvbjogMzAsIGxhdDogNTB9KTtcclxuICAgKiBtYXAucGFuVG8oe2xhdDogNTAsIGxuZzogMzB9KTtcclxuICAgKiBtYXAucGFuVG8oTC5sYXRMbmcoNTAsIDMwKSk7XHJcbiAgICogYGBgXHJcbiAgICpcclxuICAgKiBOb3RlIHRoYXQgYExhdExuZ2AgZG9lcyBub3QgaW5oZXJpdCBmcm9tIExlYWZsZXQncyBgQ2xhc3NgIG9iamVjdCxcclxuICAgKiB3aGljaCBtZWFucyBuZXcgY2xhc3NlcyBjYW4ndCBpbmhlcml0IGZyb20gaXQsIGFuZCBuZXcgbWV0aG9kc1xyXG4gICAqIGNhbid0IGJlIGFkZGVkIHRvIGl0IHdpdGggdGhlIGBpbmNsdWRlYCBmdW5jdGlvbi5cclxuICAgKi9cclxuXHJcbiAgZnVuY3Rpb24gTGF0TG5nKGxhdCwgbG5nLCBhbHQpIHtcclxuICBcdGlmIChpc05hTihsYXQpIHx8IGlzTmFOKGxuZykpIHtcclxuICBcdFx0dGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIExhdExuZyBvYmplY3Q6ICgnICsgbGF0ICsgJywgJyArIGxuZyArICcpJyk7XHJcbiAgXHR9XHJcblxyXG4gIFx0Ly8gQHByb3BlcnR5IGxhdDogTnVtYmVyXHJcbiAgXHQvLyBMYXRpdHVkZSBpbiBkZWdyZWVzXHJcbiAgXHR0aGlzLmxhdCA9ICtsYXQ7XHJcblxyXG4gIFx0Ly8gQHByb3BlcnR5IGxuZzogTnVtYmVyXHJcbiAgXHQvLyBMb25naXR1ZGUgaW4gZGVncmVlc1xyXG4gIFx0dGhpcy5sbmcgPSArbG5nO1xyXG5cclxuICBcdC8vIEBwcm9wZXJ0eSBhbHQ6IE51bWJlclxyXG4gIFx0Ly8gQWx0aXR1ZGUgaW4gbWV0ZXJzIChvcHRpb25hbClcclxuICBcdGlmIChhbHQgIT09IHVuZGVmaW5lZCkge1xyXG4gIFx0XHR0aGlzLmFsdCA9ICthbHQ7XHJcbiAgXHR9XHJcbiAgfVxyXG5cclxuICBMYXRMbmcucHJvdG90eXBlID0ge1xyXG4gIFx0Ly8gQG1ldGhvZCBlcXVhbHMob3RoZXJMYXRMbmc6IExhdExuZywgbWF4TWFyZ2luPzogTnVtYmVyKTogQm9vbGVhblxyXG4gIFx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGdpdmVuIGBMYXRMbmdgIHBvaW50IGlzIGF0IHRoZSBzYW1lIHBvc2l0aW9uICh3aXRoaW4gYSBzbWFsbCBtYXJnaW4gb2YgZXJyb3IpLiBUaGUgbWFyZ2luIG9mIGVycm9yIGNhbiBiZSBvdmVycmlkZGVuIGJ5IHNldHRpbmcgYG1heE1hcmdpbmAgdG8gYSBzbWFsbCBudW1iZXIuXHJcbiAgXHRlcXVhbHM6IGZ1bmN0aW9uIChvYmosIG1heE1hcmdpbikge1xyXG4gIFx0XHRpZiAoIW9iaikgeyByZXR1cm4gZmFsc2U7IH1cclxuXHJcbiAgXHRcdG9iaiA9IHRvTGF0TG5nKG9iaik7XHJcblxyXG4gIFx0XHR2YXIgbWFyZ2luID0gTWF0aC5tYXgoXHJcbiAgXHRcdCAgICAgICAgTWF0aC5hYnModGhpcy5sYXQgLSBvYmoubGF0KSxcclxuICBcdFx0ICAgICAgICBNYXRoLmFicyh0aGlzLmxuZyAtIG9iai5sbmcpKTtcclxuXHJcbiAgXHRcdHJldHVybiBtYXJnaW4gPD0gKG1heE1hcmdpbiA9PT0gdW5kZWZpbmVkID8gMS4wRS05IDogbWF4TWFyZ2luKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCB0b1N0cmluZygpOiBTdHJpbmdcclxuICBcdC8vIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBvaW50IChmb3IgZGVidWdnaW5nIHB1cnBvc2VzKS5cclxuICBcdHRvU3RyaW5nOiBmdW5jdGlvbiAocHJlY2lzaW9uKSB7XHJcbiAgXHRcdHJldHVybiAnTGF0TG5nKCcgK1xyXG4gIFx0XHQgICAgICAgIGZvcm1hdE51bSh0aGlzLmxhdCwgcHJlY2lzaW9uKSArICcsICcgK1xyXG4gIFx0XHQgICAgICAgIGZvcm1hdE51bSh0aGlzLmxuZywgcHJlY2lzaW9uKSArICcpJztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBkaXN0YW5jZVRvKG90aGVyTGF0TG5nOiBMYXRMbmcpOiBOdW1iZXJcclxuICBcdC8vIFJldHVybnMgdGhlIGRpc3RhbmNlIChpbiBtZXRlcnMpIHRvIHRoZSBnaXZlbiBgTGF0TG5nYCBjYWxjdWxhdGVkIHVzaW5nIHRoZSBbU3BoZXJpY2FsIExhdyBvZiBDb3NpbmVzXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TcGhlcmljYWxfbGF3X29mX2Nvc2luZXMpLlxyXG4gIFx0ZGlzdGFuY2VUbzogZnVuY3Rpb24gKG90aGVyKSB7XHJcbiAgXHRcdHJldHVybiBFYXJ0aC5kaXN0YW5jZSh0aGlzLCB0b0xhdExuZyhvdGhlcikpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHdyYXAoKTogTGF0TG5nXHJcbiAgXHQvLyBSZXR1cm5zIGEgbmV3IGBMYXRMbmdgIG9iamVjdCB3aXRoIHRoZSBsb25naXR1ZGUgd3JhcHBlZCBzbyBpdCdzIGFsd2F5cyBiZXR3ZWVuIC0xODAgYW5kICsxODAgZGVncmVlcy5cclxuICBcdHdyYXA6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIEVhcnRoLndyYXBMYXRMbmcodGhpcyk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgdG9Cb3VuZHMoc2l6ZUluTWV0ZXJzOiBOdW1iZXIpOiBMYXRMbmdCb3VuZHNcclxuICBcdC8vIFJldHVybnMgYSBuZXcgYExhdExuZ0JvdW5kc2Agb2JqZWN0IGluIHdoaWNoIGVhY2ggYm91bmRhcnkgaXMgYHNpemVJbk1ldGVycy8yYCBtZXRlcnMgYXBhcnQgZnJvbSB0aGUgYExhdExuZ2AuXHJcbiAgXHR0b0JvdW5kczogZnVuY3Rpb24gKHNpemVJbk1ldGVycykge1xyXG4gIFx0XHR2YXIgbGF0QWNjdXJhY3kgPSAxODAgKiBzaXplSW5NZXRlcnMgLyA0MDA3NTAxNyxcclxuICBcdFx0ICAgIGxuZ0FjY3VyYWN5ID0gbGF0QWNjdXJhY3kgLyBNYXRoLmNvcygoTWF0aC5QSSAvIDE4MCkgKiB0aGlzLmxhdCk7XHJcblxyXG4gIFx0XHRyZXR1cm4gdG9MYXRMbmdCb3VuZHMoXHJcbiAgXHRcdCAgICAgICAgW3RoaXMubGF0IC0gbGF0QWNjdXJhY3ksIHRoaXMubG5nIC0gbG5nQWNjdXJhY3ldLFxyXG4gIFx0XHQgICAgICAgIFt0aGlzLmxhdCArIGxhdEFjY3VyYWN5LCB0aGlzLmxuZyArIGxuZ0FjY3VyYWN5XSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdGNsb25lOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiBuZXcgTGF0TG5nKHRoaXMubGF0LCB0aGlzLmxuZywgdGhpcy5hbHQpO1xyXG4gIFx0fVxyXG4gIH07XHJcblxyXG5cclxuXHJcbiAgLy8gQGZhY3RvcnkgTC5sYXRMbmcobGF0aXR1ZGU6IE51bWJlciwgbG9uZ2l0dWRlOiBOdW1iZXIsIGFsdGl0dWRlPzogTnVtYmVyKTogTGF0TG5nXHJcbiAgLy8gQ3JlYXRlcyBhbiBvYmplY3QgcmVwcmVzZW50aW5nIGEgZ2VvZ3JhcGhpY2FsIHBvaW50IHdpdGggdGhlIGdpdmVuIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgKGFuZCBvcHRpb25hbGx5IGFsdGl0dWRlKS5cclxuXHJcbiAgLy8gQGFsdGVybmF0aXZlXHJcbiAgLy8gQGZhY3RvcnkgTC5sYXRMbmcoY29vcmRzOiBBcnJheSk6IExhdExuZ1xyXG4gIC8vIEV4cGVjdHMgYW4gYXJyYXkgb2YgdGhlIGZvcm0gYFtOdW1iZXIsIE51bWJlcl1gIG9yIGBbTnVtYmVyLCBOdW1iZXIsIE51bWJlcl1gIGluc3RlYWQuXHJcblxyXG4gIC8vIEBhbHRlcm5hdGl2ZVxyXG4gIC8vIEBmYWN0b3J5IEwubGF0TG5nKGNvb3JkczogT2JqZWN0KTogTGF0TG5nXHJcbiAgLy8gRXhwZWN0cyBhbiBwbGFpbiBvYmplY3Qgb2YgdGhlIGZvcm0gYHtsYXQ6IE51bWJlciwgbG5nOiBOdW1iZXJ9YCBvciBge2xhdDogTnVtYmVyLCBsbmc6IE51bWJlciwgYWx0OiBOdW1iZXJ9YCBpbnN0ZWFkLlxyXG5cclxuICBmdW5jdGlvbiB0b0xhdExuZyhhLCBiLCBjKSB7XHJcbiAgXHRpZiAoYSBpbnN0YW5jZW9mIExhdExuZykge1xyXG4gIFx0XHRyZXR1cm4gYTtcclxuICBcdH1cclxuICBcdGlmIChpc0FycmF5KGEpICYmIHR5cGVvZiBhWzBdICE9PSAnb2JqZWN0Jykge1xyXG4gIFx0XHRpZiAoYS5sZW5ndGggPT09IDMpIHtcclxuICBcdFx0XHRyZXR1cm4gbmV3IExhdExuZyhhWzBdLCBhWzFdLCBhWzJdKTtcclxuICBcdFx0fVxyXG4gIFx0XHRpZiAoYS5sZW5ndGggPT09IDIpIHtcclxuICBcdFx0XHRyZXR1cm4gbmV3IExhdExuZyhhWzBdLCBhWzFdKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gbnVsbDtcclxuICBcdH1cclxuICBcdGlmIChhID09PSB1bmRlZmluZWQgfHwgYSA9PT0gbnVsbCkge1xyXG4gIFx0XHRyZXR1cm4gYTtcclxuICBcdH1cclxuICBcdGlmICh0eXBlb2YgYSA9PT0gJ29iamVjdCcgJiYgJ2xhdCcgaW4gYSkge1xyXG4gIFx0XHRyZXR1cm4gbmV3IExhdExuZyhhLmxhdCwgJ2xuZycgaW4gYSA/IGEubG5nIDogYS5sb24sIGEuYWx0KTtcclxuICBcdH1cclxuICBcdGlmIChiID09PSB1bmRlZmluZWQpIHtcclxuICBcdFx0cmV0dXJuIG51bGw7XHJcbiAgXHR9XHJcbiAgXHRyZXR1cm4gbmV3IExhdExuZyhhLCBiLCBjKTtcclxuICB9XG5cbiAgLypcclxuICAgKiBAbmFtZXNwYWNlIENSU1xyXG4gICAqIEBjcnMgTC5DUlMuQmFzZVxyXG4gICAqIE9iamVjdCB0aGF0IGRlZmluZXMgY29vcmRpbmF0ZSByZWZlcmVuY2Ugc3lzdGVtcyBmb3IgcHJvamVjdGluZ1xyXG4gICAqIGdlb2dyYXBoaWNhbCBwb2ludHMgaW50byBwaXhlbCAoc2NyZWVuKSBjb29yZGluYXRlcyBhbmQgYmFjayAoYW5kIHRvXHJcbiAgICogY29vcmRpbmF0ZXMgaW4gb3RoZXIgdW5pdHMgZm9yIFtXTVNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1dlYl9NYXBfU2VydmljZSkgc2VydmljZXMpLiBTZWVcclxuICAgKiBbc3BhdGlhbCByZWZlcmVuY2Ugc3lzdGVtXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TcGF0aWFsX3JlZmVyZW5jZV9zeXN0ZW0pLlxyXG4gICAqXHJcbiAgICogTGVhZmxldCBkZWZpbmVzIHRoZSBtb3N0IHVzdWFsIENSU3MgYnkgZGVmYXVsdC4gSWYgeW91IHdhbnQgdG8gdXNlIGFcclxuICAgKiBDUlMgbm90IGRlZmluZWQgYnkgZGVmYXVsdCwgdGFrZSBhIGxvb2sgYXQgdGhlXHJcbiAgICogW1Byb2o0TGVhZmxldF0oaHR0cHM6Ly9naXRodWIuY29tL2thcnRlbmEvUHJvajRMZWFmbGV0KSBwbHVnaW4uXHJcbiAgICpcclxuICAgKiBOb3RlIHRoYXQgdGhlIENSUyBpbnN0YW5jZXMgZG8gbm90IGluaGVyaXQgZnJvbSBMZWFmbGV0J3MgYENsYXNzYCBvYmplY3QsXHJcbiAgICogYW5kIGNhbid0IGJlIGluc3RhbnRpYXRlZC4gQWxzbywgbmV3IGNsYXNzZXMgY2FuJ3QgaW5oZXJpdCBmcm9tIHRoZW0sXHJcbiAgICogYW5kIG1ldGhvZHMgY2FuJ3QgYmUgYWRkZWQgdG8gdGhlbSB3aXRoIHRoZSBgaW5jbHVkZWAgZnVuY3Rpb24uXHJcbiAgICovXHJcblxyXG4gIHZhciBDUlMgPSB7XHJcbiAgXHQvLyBAbWV0aG9kIGxhdExuZ1RvUG9pbnQobGF0bG5nOiBMYXRMbmcsIHpvb206IE51bWJlcik6IFBvaW50XHJcbiAgXHQvLyBQcm9qZWN0cyBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZXMgaW50byBwaXhlbCBjb29yZGluYXRlcyBmb3IgYSBnaXZlbiB6b29tLlxyXG4gIFx0bGF0TG5nVG9Qb2ludDogZnVuY3Rpb24gKGxhdGxuZywgem9vbSkge1xyXG4gIFx0XHR2YXIgcHJvamVjdGVkUG9pbnQgPSB0aGlzLnByb2plY3Rpb24ucHJvamVjdChsYXRsbmcpLFxyXG4gIFx0XHQgICAgc2NhbGUgPSB0aGlzLnNjYWxlKHpvb20pO1xyXG5cclxuICBcdFx0cmV0dXJuIHRoaXMudHJhbnNmb3JtYXRpb24uX3RyYW5zZm9ybShwcm9qZWN0ZWRQb2ludCwgc2NhbGUpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHBvaW50VG9MYXRMbmcocG9pbnQ6IFBvaW50LCB6b29tOiBOdW1iZXIpOiBMYXRMbmdcclxuICBcdC8vIFRoZSBpbnZlcnNlIG9mIGBsYXRMbmdUb1BvaW50YC4gUHJvamVjdHMgcGl4ZWwgY29vcmRpbmF0ZXMgb24gYSBnaXZlblxyXG4gIFx0Ly8gem9vbSBpbnRvIGdlb2dyYXBoaWNhbCBjb29yZGluYXRlcy5cclxuICBcdHBvaW50VG9MYXRMbmc6IGZ1bmN0aW9uIChwb2ludCwgem9vbSkge1xyXG4gIFx0XHR2YXIgc2NhbGUgPSB0aGlzLnNjYWxlKHpvb20pLFxyXG4gIFx0XHQgICAgdW50cmFuc2Zvcm1lZFBvaW50ID0gdGhpcy50cmFuc2Zvcm1hdGlvbi51bnRyYW5zZm9ybShwb2ludCwgc2NhbGUpO1xyXG5cclxuICBcdFx0cmV0dXJuIHRoaXMucHJvamVjdGlvbi51bnByb2plY3QodW50cmFuc2Zvcm1lZFBvaW50KTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBwcm9qZWN0KGxhdGxuZzogTGF0TG5nKTogUG9pbnRcclxuICBcdC8vIFByb2plY3RzIGdlb2dyYXBoaWNhbCBjb29yZGluYXRlcyBpbnRvIGNvb3JkaW5hdGVzIGluIHVuaXRzIGFjY2VwdGVkIGZvclxyXG4gIFx0Ly8gdGhpcyBDUlMgKGUuZy4gbWV0ZXJzIGZvciBFUFNHOjM4NTcsIGZvciBwYXNzaW5nIGl0IHRvIFdNUyBzZXJ2aWNlcykuXHJcbiAgXHRwcm9qZWN0OiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLnByb2plY3Rpb24ucHJvamVjdChsYXRsbmcpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHVucHJvamVjdChwb2ludDogUG9pbnQpOiBMYXRMbmdcclxuICBcdC8vIEdpdmVuIGEgcHJvamVjdGVkIGNvb3JkaW5hdGUgcmV0dXJucyB0aGUgY29ycmVzcG9uZGluZyBMYXRMbmcuXHJcbiAgXHQvLyBUaGUgaW52ZXJzZSBvZiBgcHJvamVjdGAuXHJcbiAgXHR1bnByb2plY3Q6IGZ1bmN0aW9uIChwb2ludCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5wcm9qZWN0aW9uLnVucHJvamVjdChwb2ludCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2NhbGUoem9vbTogTnVtYmVyKTogTnVtYmVyXHJcbiAgXHQvLyBSZXR1cm5zIHRoZSBzY2FsZSB1c2VkIHdoZW4gdHJhbnNmb3JtaW5nIHByb2plY3RlZCBjb29yZGluYXRlcyBpbnRvXHJcbiAgXHQvLyBwaXhlbCBjb29yZGluYXRlcyBmb3IgYSBwYXJ0aWN1bGFyIHpvb20uIEZvciBleGFtcGxlLCBpdCByZXR1cm5zXHJcbiAgXHQvLyBgMjU2ICogMl56b29tYCBmb3IgTWVyY2F0b3ItYmFzZWQgQ1JTLlxyXG4gIFx0c2NhbGU6IGZ1bmN0aW9uICh6b29tKSB7XHJcbiAgXHRcdHJldHVybiAyNTYgKiBNYXRoLnBvdygyLCB6b29tKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCB6b29tKHNjYWxlOiBOdW1iZXIpOiBOdW1iZXJcclxuICBcdC8vIEludmVyc2Ugb2YgYHNjYWxlKClgLCByZXR1cm5zIHRoZSB6b29tIGxldmVsIGNvcnJlc3BvbmRpbmcgdG8gYSBzY2FsZVxyXG4gIFx0Ly8gZmFjdG9yIG9mIGBzY2FsZWAuXHJcbiAgXHR6b29tOiBmdW5jdGlvbiAoc2NhbGUpIHtcclxuICBcdFx0cmV0dXJuIE1hdGgubG9nKHNjYWxlIC8gMjU2KSAvIE1hdGguTE4yO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldFByb2plY3RlZEJvdW5kcyh6b29tOiBOdW1iZXIpOiBCb3VuZHNcclxuICBcdC8vIFJldHVybnMgdGhlIHByb2plY3Rpb24ncyBib3VuZHMgc2NhbGVkIGFuZCB0cmFuc2Zvcm1lZCBmb3IgdGhlIHByb3ZpZGVkIGB6b29tYC5cclxuICBcdGdldFByb2plY3RlZEJvdW5kczogZnVuY3Rpb24gKHpvb20pIHtcclxuICBcdFx0aWYgKHRoaXMuaW5maW5pdGUpIHsgcmV0dXJuIG51bGw7IH1cclxuXHJcbiAgXHRcdHZhciBiID0gdGhpcy5wcm9qZWN0aW9uLmJvdW5kcyxcclxuICBcdFx0ICAgIHMgPSB0aGlzLnNjYWxlKHpvb20pLFxyXG4gIFx0XHQgICAgbWluID0gdGhpcy50cmFuc2Zvcm1hdGlvbi50cmFuc2Zvcm0oYi5taW4sIHMpLFxyXG4gIFx0XHQgICAgbWF4ID0gdGhpcy50cmFuc2Zvcm1hdGlvbi50cmFuc2Zvcm0oYi5tYXgsIHMpO1xyXG5cclxuICBcdFx0cmV0dXJuIG5ldyBCb3VuZHMobWluLCBtYXgpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGRpc3RhbmNlKGxhdGxuZzE6IExhdExuZywgbGF0bG5nMjogTGF0TG5nKTogTnVtYmVyXHJcbiAgXHQvLyBSZXR1cm5zIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHR3byBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZXMuXHJcblxyXG4gIFx0Ly8gQHByb3BlcnR5IGNvZGU6IFN0cmluZ1xyXG4gIFx0Ly8gU3RhbmRhcmQgY29kZSBuYW1lIG9mIHRoZSBDUlMgcGFzc2VkIGludG8gV01TIHNlcnZpY2VzIChlLmcuIGAnRVBTRzozODU3J2ApXHJcbiAgXHQvL1xyXG4gIFx0Ly8gQHByb3BlcnR5IHdyYXBMbmc6IE51bWJlcltdXHJcbiAgXHQvLyBBbiBhcnJheSBvZiB0d28gbnVtYmVycyBkZWZpbmluZyB3aGV0aGVyIHRoZSBsb25naXR1ZGUgKGhvcml6b250YWwpIGNvb3JkaW5hdGVcclxuICBcdC8vIGF4aXMgd3JhcHMgYXJvdW5kIGEgZ2l2ZW4gcmFuZ2UgYW5kIGhvdy4gRGVmYXVsdHMgdG8gYFstMTgwLCAxODBdYCBpbiBtb3N0XHJcbiAgXHQvLyBnZW9ncmFwaGljYWwgQ1JTcy4gSWYgYHVuZGVmaW5lZGAsIHRoZSBsb25naXR1ZGUgYXhpcyBkb2VzIG5vdCB3cmFwIGFyb3VuZC5cclxuICBcdC8vXHJcbiAgXHQvLyBAcHJvcGVydHkgd3JhcExhdDogTnVtYmVyW11cclxuICBcdC8vIExpa2UgYHdyYXBMbmdgLCBidXQgZm9yIHRoZSBsYXRpdHVkZSAodmVydGljYWwpIGF4aXMuXHJcblxyXG4gIFx0Ly8gd3JhcExuZzogW21pbiwgbWF4XSxcclxuICBcdC8vIHdyYXBMYXQ6IFttaW4sIG1heF0sXHJcblxyXG4gIFx0Ly8gQHByb3BlcnR5IGluZmluaXRlOiBCb29sZWFuXHJcbiAgXHQvLyBJZiB0cnVlLCB0aGUgY29vcmRpbmF0ZSBzcGFjZSB3aWxsIGJlIHVuYm91bmRlZCAoaW5maW5pdGUgaW4gYm90aCBheGVzKVxyXG4gIFx0aW5maW5pdGU6IGZhbHNlLFxyXG5cclxuICBcdC8vIEBtZXRob2Qgd3JhcExhdExuZyhsYXRsbmc6IExhdExuZyk6IExhdExuZ1xyXG4gIFx0Ly8gUmV0dXJucyBhIGBMYXRMbmdgIHdoZXJlIGxhdCBhbmQgbG5nIGhhcyBiZWVuIHdyYXBwZWQgYWNjb3JkaW5nIHRvIHRoZVxyXG4gIFx0Ly8gQ1JTJ3MgYHdyYXBMYXRgIGFuZCBgd3JhcExuZ2AgcHJvcGVydGllcywgaWYgdGhleSBhcmUgb3V0c2lkZSB0aGUgQ1JTJ3MgYm91bmRzLlxyXG4gIFx0d3JhcExhdExuZzogZnVuY3Rpb24gKGxhdGxuZykge1xyXG4gIFx0XHR2YXIgbG5nID0gdGhpcy53cmFwTG5nID8gd3JhcE51bShsYXRsbmcubG5nLCB0aGlzLndyYXBMbmcsIHRydWUpIDogbGF0bG5nLmxuZyxcclxuICBcdFx0ICAgIGxhdCA9IHRoaXMud3JhcExhdCA/IHdyYXBOdW0obGF0bG5nLmxhdCwgdGhpcy53cmFwTGF0LCB0cnVlKSA6IGxhdGxuZy5sYXQsXHJcbiAgXHRcdCAgICBhbHQgPSBsYXRsbmcuYWx0O1xyXG5cclxuICBcdFx0cmV0dXJuIG5ldyBMYXRMbmcobGF0LCBsbmcsIGFsdCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgd3JhcExhdExuZ0JvdW5kcyhib3VuZHM6IExhdExuZ0JvdW5kcyk6IExhdExuZ0JvdW5kc1xyXG4gIFx0Ly8gUmV0dXJucyBhIGBMYXRMbmdCb3VuZHNgIHdpdGggdGhlIHNhbWUgc2l6ZSBhcyB0aGUgZ2l2ZW4gb25lLCBlbnN1cmluZ1xyXG4gIFx0Ly8gdGhhdCBpdHMgY2VudGVyIGlzIHdpdGhpbiB0aGUgQ1JTJ3MgYm91bmRzLlxyXG4gIFx0Ly8gT25seSBhY2NlcHRzIGFjdHVhbCBgTC5MYXRMbmdCb3VuZHNgIGluc3RhbmNlcywgbm90IGFycmF5cy5cclxuICBcdHdyYXBMYXRMbmdCb3VuZHM6IGZ1bmN0aW9uIChib3VuZHMpIHtcclxuICBcdFx0dmFyIGNlbnRlciA9IGJvdW5kcy5nZXRDZW50ZXIoKSxcclxuICBcdFx0ICAgIG5ld0NlbnRlciA9IHRoaXMud3JhcExhdExuZyhjZW50ZXIpLFxyXG4gIFx0XHQgICAgbGF0U2hpZnQgPSBjZW50ZXIubGF0IC0gbmV3Q2VudGVyLmxhdCxcclxuICBcdFx0ICAgIGxuZ1NoaWZ0ID0gY2VudGVyLmxuZyAtIG5ld0NlbnRlci5sbmc7XHJcblxyXG4gIFx0XHRpZiAobGF0U2hpZnQgPT09IDAgJiYgbG5nU2hpZnQgPT09IDApIHtcclxuICBcdFx0XHRyZXR1cm4gYm91bmRzO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgc3cgPSBib3VuZHMuZ2V0U291dGhXZXN0KCksXHJcbiAgXHRcdCAgICBuZSA9IGJvdW5kcy5nZXROb3J0aEVhc3QoKSxcclxuICBcdFx0ICAgIG5ld1N3ID0gbmV3IExhdExuZyhzdy5sYXQgLSBsYXRTaGlmdCwgc3cubG5nIC0gbG5nU2hpZnQpLFxyXG4gIFx0XHQgICAgbmV3TmUgPSBuZXcgTGF0TG5nKG5lLmxhdCAtIGxhdFNoaWZ0LCBuZS5sbmcgLSBsbmdTaGlmdCk7XHJcblxyXG4gIFx0XHRyZXR1cm4gbmV3IExhdExuZ0JvdW5kcyhuZXdTdywgbmV3TmUpO1xyXG4gIFx0fVxyXG4gIH07XG5cbiAgLypcbiAgICogQG5hbWVzcGFjZSBDUlNcbiAgICogQGNycyBMLkNSUy5FYXJ0aFxuICAgKlxuICAgKiBTZXJ2ZXMgYXMgdGhlIGJhc2UgZm9yIENSUyB0aGF0IGFyZSBnbG9iYWwgc3VjaCB0aGF0IHRoZXkgY292ZXIgdGhlIGVhcnRoLlxuICAgKiBDYW4gb25seSBiZSB1c2VkIGFzIHRoZSBiYXNlIGZvciBvdGhlciBDUlMgYW5kIGNhbm5vdCBiZSB1c2VkIGRpcmVjdGx5LFxuICAgKiBzaW5jZSBpdCBkb2VzIG5vdCBoYXZlIGEgYGNvZGVgLCBgcHJvamVjdGlvbmAgb3IgYHRyYW5zZm9ybWF0aW9uYC4gYGRpc3RhbmNlKClgIHJldHVybnNcbiAgICogbWV0ZXJzLlxuICAgKi9cblxuICB2YXIgRWFydGggPSBleHRlbmQoe30sIENSUywge1xuICBcdHdyYXBMbmc6IFstMTgwLCAxODBdLFxuXG4gIFx0Ly8gTWVhbiBFYXJ0aCBSYWRpdXMsIGFzIHJlY29tbWVuZGVkIGZvciB1c2UgYnlcbiAgXHQvLyB0aGUgSW50ZXJuYXRpb25hbCBVbmlvbiBvZiBHZW9kZXN5IGFuZCBHZW9waHlzaWNzLFxuICBcdC8vIHNlZSBodHRwczovL3Jvc2V0dGFjb2RlLm9yZy93aWtpL0hhdmVyc2luZV9mb3JtdWxhXG4gIFx0UjogNjM3MTAwMCxcblxuICBcdC8vIGRpc3RhbmNlIGJldHdlZW4gdHdvIGdlb2dyYXBoaWNhbCBwb2ludHMgdXNpbmcgc3BoZXJpY2FsIGxhdyBvZiBjb3NpbmVzIGFwcHJveGltYXRpb25cbiAgXHRkaXN0YW5jZTogZnVuY3Rpb24gKGxhdGxuZzEsIGxhdGxuZzIpIHtcbiAgXHRcdHZhciByYWQgPSBNYXRoLlBJIC8gMTgwLFxuICBcdFx0ICAgIGxhdDEgPSBsYXRsbmcxLmxhdCAqIHJhZCxcbiAgXHRcdCAgICBsYXQyID0gbGF0bG5nMi5sYXQgKiByYWQsXG4gIFx0XHQgICAgc2luRExhdCA9IE1hdGguc2luKChsYXRsbmcyLmxhdCAtIGxhdGxuZzEubGF0KSAqIHJhZCAvIDIpLFxuICBcdFx0ICAgIHNpbkRMb24gPSBNYXRoLnNpbigobGF0bG5nMi5sbmcgLSBsYXRsbmcxLmxuZykgKiByYWQgLyAyKSxcbiAgXHRcdCAgICBhID0gc2luRExhdCAqIHNpbkRMYXQgKyBNYXRoLmNvcyhsYXQxKSAqIE1hdGguY29zKGxhdDIpICogc2luRExvbiAqIHNpbkRMb24sXG4gIFx0XHQgICAgYyA9IDIgKiBNYXRoLmF0YW4yKE1hdGguc3FydChhKSwgTWF0aC5zcXJ0KDEgLSBhKSk7XG4gIFx0XHRyZXR1cm4gdGhpcy5SICogYztcbiAgXHR9XG4gIH0pO1xuXG4gIC8qXHJcbiAgICogQG5hbWVzcGFjZSBQcm9qZWN0aW9uXHJcbiAgICogQHByb2plY3Rpb24gTC5Qcm9qZWN0aW9uLlNwaGVyaWNhbE1lcmNhdG9yXHJcbiAgICpcclxuICAgKiBTcGhlcmljYWwgTWVyY2F0b3IgcHJvamVjdGlvbiDigJQgdGhlIG1vc3QgY29tbW9uIHByb2plY3Rpb24gZm9yIG9ubGluZSBtYXBzLFxyXG4gICAqIHVzZWQgYnkgYWxtb3N0IGFsbCBmcmVlIGFuZCBjb21tZXJjaWFsIHRpbGUgcHJvdmlkZXJzLiBBc3N1bWVzIHRoYXQgRWFydGggaXNcclxuICAgKiBhIHNwaGVyZS4gVXNlZCBieSB0aGUgYEVQU0c6Mzg1N2AgQ1JTLlxyXG4gICAqL1xyXG5cclxuICB2YXIgZWFydGhSYWRpdXMgPSA2Mzc4MTM3O1xyXG5cclxuICB2YXIgU3BoZXJpY2FsTWVyY2F0b3IgPSB7XHJcblxyXG4gIFx0UjogZWFydGhSYWRpdXMsXHJcbiAgXHRNQVhfTEFUSVRVREU6IDg1LjA1MTEyODc3OTgsXHJcblxyXG4gIFx0cHJvamVjdDogZnVuY3Rpb24gKGxhdGxuZykge1xyXG4gIFx0XHR2YXIgZCA9IE1hdGguUEkgLyAxODAsXHJcbiAgXHRcdCAgICBtYXggPSB0aGlzLk1BWF9MQVRJVFVERSxcclxuICBcdFx0ICAgIGxhdCA9IE1hdGgubWF4KE1hdGgubWluKG1heCwgbGF0bG5nLmxhdCksIC1tYXgpLFxyXG4gIFx0XHQgICAgc2luID0gTWF0aC5zaW4obGF0ICogZCk7XHJcblxyXG4gIFx0XHRyZXR1cm4gbmV3IFBvaW50KFxyXG4gIFx0XHRcdHRoaXMuUiAqIGxhdGxuZy5sbmcgKiBkLFxyXG4gIFx0XHRcdHRoaXMuUiAqIE1hdGgubG9nKCgxICsgc2luKSAvICgxIC0gc2luKSkgLyAyKTtcclxuICBcdH0sXHJcblxyXG4gIFx0dW5wcm9qZWN0OiBmdW5jdGlvbiAocG9pbnQpIHtcclxuICBcdFx0dmFyIGQgPSAxODAgLyBNYXRoLlBJO1xyXG5cclxuICBcdFx0cmV0dXJuIG5ldyBMYXRMbmcoXHJcbiAgXHRcdFx0KDIgKiBNYXRoLmF0YW4oTWF0aC5leHAocG9pbnQueSAvIHRoaXMuUikpIC0gKE1hdGguUEkgLyAyKSkgKiBkLFxyXG4gIFx0XHRcdHBvaW50LnggKiBkIC8gdGhpcy5SKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ym91bmRzOiAoZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR2YXIgZCA9IGVhcnRoUmFkaXVzICogTWF0aC5QSTtcclxuICBcdFx0cmV0dXJuIG5ldyBCb3VuZHMoWy1kLCAtZF0sIFtkLCBkXSk7XHJcbiAgXHR9KSgpXHJcbiAgfTtcblxuICAvKlxyXG4gICAqIEBjbGFzcyBUcmFuc2Zvcm1hdGlvblxyXG4gICAqIEBha2EgTC5UcmFuc2Zvcm1hdGlvblxyXG4gICAqXHJcbiAgICogUmVwcmVzZW50cyBhbiBhZmZpbmUgdHJhbnNmb3JtYXRpb246IGEgc2V0IG9mIGNvZWZmaWNpZW50cyBgYWAsIGBiYCwgYGNgLCBgZGBcclxuICAgKiBmb3IgdHJhbnNmb3JtaW5nIGEgcG9pbnQgb2YgYSBmb3JtIGAoeCwgeSlgIGludG8gYChhKnggKyBiLCBjKnkgKyBkKWAgYW5kIGRvaW5nXHJcbiAgICogdGhlIHJldmVyc2UuIFVzZWQgYnkgTGVhZmxldCBpbiBpdHMgcHJvamVjdGlvbnMgY29kZS5cclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICpcclxuICAgKiBgYGBqc1xyXG4gICAqIHZhciB0cmFuc2Zvcm1hdGlvbiA9IEwudHJhbnNmb3JtYXRpb24oMiwgNSwgLTEsIDEwKSxcclxuICAgKiBcdHAgPSBMLnBvaW50KDEsIDIpLFxyXG4gICAqIFx0cDIgPSB0cmFuc2Zvcm1hdGlvbi50cmFuc2Zvcm0ocCksIC8vICBMLnBvaW50KDcsIDgpXHJcbiAgICogXHRwMyA9IHRyYW5zZm9ybWF0aW9uLnVudHJhbnNmb3JtKHAyKTsgLy8gIEwucG9pbnQoMSwgMilcclxuICAgKiBgYGBcclxuICAgKi9cclxuXHJcblxyXG4gIC8vIGZhY3RvcnkgbmV3IEwuVHJhbnNmb3JtYXRpb24oYTogTnVtYmVyLCBiOiBOdW1iZXIsIGM6IE51bWJlciwgZDogTnVtYmVyKVxyXG4gIC8vIENyZWF0ZXMgYSBgVHJhbnNmb3JtYXRpb25gIG9iamVjdCB3aXRoIHRoZSBnaXZlbiBjb2VmZmljaWVudHMuXHJcbiAgZnVuY3Rpb24gVHJhbnNmb3JtYXRpb24oYSwgYiwgYywgZCkge1xyXG4gIFx0aWYgKGlzQXJyYXkoYSkpIHtcclxuICBcdFx0Ly8gdXNlIGFycmF5IHByb3BlcnRpZXNcclxuICBcdFx0dGhpcy5fYSA9IGFbMF07XHJcbiAgXHRcdHRoaXMuX2IgPSBhWzFdO1xyXG4gIFx0XHR0aGlzLl9jID0gYVsyXTtcclxuICBcdFx0dGhpcy5fZCA9IGFbM107XHJcbiAgXHRcdHJldHVybjtcclxuICBcdH1cclxuICBcdHRoaXMuX2EgPSBhO1xyXG4gIFx0dGhpcy5fYiA9IGI7XHJcbiAgXHR0aGlzLl9jID0gYztcclxuICBcdHRoaXMuX2QgPSBkO1xyXG4gIH1cclxuXHJcbiAgVHJhbnNmb3JtYXRpb24ucHJvdG90eXBlID0ge1xyXG4gIFx0Ly8gQG1ldGhvZCB0cmFuc2Zvcm0ocG9pbnQ6IFBvaW50LCBzY2FsZT86IE51bWJlcik6IFBvaW50XHJcbiAgXHQvLyBSZXR1cm5zIGEgdHJhbnNmb3JtZWQgcG9pbnQsIG9wdGlvbmFsbHkgbXVsdGlwbGllZCBieSB0aGUgZ2l2ZW4gc2NhbGUuXHJcbiAgXHQvLyBPbmx5IGFjY2VwdHMgYWN0dWFsIGBMLlBvaW50YCBpbnN0YW5jZXMsIG5vdCBhcnJheXMuXHJcbiAgXHR0cmFuc2Zvcm06IGZ1bmN0aW9uIChwb2ludCwgc2NhbGUpIHsgLy8gKFBvaW50LCBOdW1iZXIpIC0+IFBvaW50XHJcbiAgXHRcdHJldHVybiB0aGlzLl90cmFuc2Zvcm0ocG9pbnQuY2xvbmUoKSwgc2NhbGUpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBkZXN0cnVjdGl2ZSB0cmFuc2Zvcm0gKGZhc3RlcilcclxuICBcdF90cmFuc2Zvcm06IGZ1bmN0aW9uIChwb2ludCwgc2NhbGUpIHtcclxuICBcdFx0c2NhbGUgPSBzY2FsZSB8fCAxO1xyXG4gIFx0XHRwb2ludC54ID0gc2NhbGUgKiAodGhpcy5fYSAqIHBvaW50LnggKyB0aGlzLl9iKTtcclxuICBcdFx0cG9pbnQueSA9IHNjYWxlICogKHRoaXMuX2MgKiBwb2ludC55ICsgdGhpcy5fZCk7XHJcbiAgXHRcdHJldHVybiBwb2ludDtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCB1bnRyYW5zZm9ybShwb2ludDogUG9pbnQsIHNjYWxlPzogTnVtYmVyKTogUG9pbnRcclxuICBcdC8vIFJldHVybnMgdGhlIHJldmVyc2UgdHJhbnNmb3JtYXRpb24gb2YgdGhlIGdpdmVuIHBvaW50LCBvcHRpb25hbGx5IGRpdmlkZWRcclxuICBcdC8vIGJ5IHRoZSBnaXZlbiBzY2FsZS4gT25seSBhY2NlcHRzIGFjdHVhbCBgTC5Qb2ludGAgaW5zdGFuY2VzLCBub3QgYXJyYXlzLlxyXG4gIFx0dW50cmFuc2Zvcm06IGZ1bmN0aW9uIChwb2ludCwgc2NhbGUpIHtcclxuICBcdFx0c2NhbGUgPSBzY2FsZSB8fCAxO1xyXG4gIFx0XHRyZXR1cm4gbmV3IFBvaW50KFxyXG4gIFx0XHQgICAgICAgIChwb2ludC54IC8gc2NhbGUgLSB0aGlzLl9iKSAvIHRoaXMuX2EsXHJcbiAgXHRcdCAgICAgICAgKHBvaW50LnkgLyBzY2FsZSAtIHRoaXMuX2QpIC8gdGhpcy5fYyk7XHJcbiAgXHR9XHJcbiAgfTtcclxuXHJcbiAgLy8gZmFjdG9yeSBMLnRyYW5zZm9ybWF0aW9uKGE6IE51bWJlciwgYjogTnVtYmVyLCBjOiBOdW1iZXIsIGQ6IE51bWJlcilcclxuXHJcbiAgLy8gQGZhY3RvcnkgTC50cmFuc2Zvcm1hdGlvbihhOiBOdW1iZXIsIGI6IE51bWJlciwgYzogTnVtYmVyLCBkOiBOdW1iZXIpXHJcbiAgLy8gSW5zdGFudGlhdGVzIGEgVHJhbnNmb3JtYXRpb24gb2JqZWN0IHdpdGggdGhlIGdpdmVuIGNvZWZmaWNpZW50cy5cclxuXHJcbiAgLy8gQGFsdGVybmF0aXZlXHJcbiAgLy8gQGZhY3RvcnkgTC50cmFuc2Zvcm1hdGlvbihjb2VmZmljaWVudHM6IEFycmF5KTogVHJhbnNmb3JtYXRpb25cclxuICAvLyBFeHBlY3RzIGFuIGNvZWZmaWNpZW50cyBhcnJheSBvZiB0aGUgZm9ybVxyXG4gIC8vIGBbYTogTnVtYmVyLCBiOiBOdW1iZXIsIGM6IE51bWJlciwgZDogTnVtYmVyXWAuXHJcblxyXG4gIGZ1bmN0aW9uIHRvVHJhbnNmb3JtYXRpb24oYSwgYiwgYywgZCkge1xyXG4gIFx0cmV0dXJuIG5ldyBUcmFuc2Zvcm1hdGlvbihhLCBiLCBjLCBkKTtcclxuICB9XG5cbiAgLypcclxuICAgKiBAbmFtZXNwYWNlIENSU1xyXG4gICAqIEBjcnMgTC5DUlMuRVBTRzM4NTdcclxuICAgKlxyXG4gICAqIFRoZSBtb3N0IGNvbW1vbiBDUlMgZm9yIG9ubGluZSBtYXBzLCB1c2VkIGJ5IGFsbW9zdCBhbGwgZnJlZSBhbmQgY29tbWVyY2lhbFxyXG4gICAqIHRpbGUgcHJvdmlkZXJzLiBVc2VzIFNwaGVyaWNhbCBNZXJjYXRvciBwcm9qZWN0aW9uLiBTZXQgaW4gYnkgZGVmYXVsdCBpblxyXG4gICAqIE1hcCdzIGBjcnNgIG9wdGlvbi5cclxuICAgKi9cclxuXHJcbiAgdmFyIEVQU0czODU3ID0gZXh0ZW5kKHt9LCBFYXJ0aCwge1xyXG4gIFx0Y29kZTogJ0VQU0c6Mzg1NycsXHJcbiAgXHRwcm9qZWN0aW9uOiBTcGhlcmljYWxNZXJjYXRvcixcclxuXHJcbiAgXHR0cmFuc2Zvcm1hdGlvbjogKGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dmFyIHNjYWxlID0gMC41IC8gKE1hdGguUEkgKiBTcGhlcmljYWxNZXJjYXRvci5SKTtcclxuICBcdFx0cmV0dXJuIHRvVHJhbnNmb3JtYXRpb24oc2NhbGUsIDAuNSwgLXNjYWxlLCAwLjUpO1xyXG4gIFx0fSgpKVxyXG4gIH0pO1xyXG5cclxuICB2YXIgRVBTRzkwMDkxMyA9IGV4dGVuZCh7fSwgRVBTRzM4NTcsIHtcclxuICBcdGNvZGU6ICdFUFNHOjkwMDkxMydcclxuICB9KTtcblxuICAvLyBAbmFtZXNwYWNlIFNWRzsgQHNlY3Rpb25cbiAgLy8gVGhlcmUgYXJlIHNldmVyYWwgc3RhdGljIGZ1bmN0aW9ucyB3aGljaCBjYW4gYmUgY2FsbGVkIHdpdGhvdXQgaW5zdGFudGlhdGluZyBMLlNWRzpcblxuICAvLyBAZnVuY3Rpb24gY3JlYXRlKG5hbWU6IFN0cmluZyk6IFNWR0VsZW1lbnRcbiAgLy8gUmV0dXJucyBhIGluc3RhbmNlIG9mIFtTVkdFbGVtZW50XShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvU1ZHRWxlbWVudCksXG4gIC8vIGNvcnJlc3BvbmRpbmcgdG8gdGhlIGNsYXNzIG5hbWUgcGFzc2VkLiBGb3IgZXhhbXBsZSwgdXNpbmcgJ2xpbmUnIHdpbGwgcmV0dXJuXG4gIC8vIGFuIGluc3RhbmNlIG9mIFtTVkdMaW5lRWxlbWVudF0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQVBJL1NWR0xpbmVFbGVtZW50KS5cbiAgZnVuY3Rpb24gc3ZnQ3JlYXRlKG5hbWUpIHtcbiAgXHRyZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKCdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZycsIG5hbWUpO1xuICB9XG5cbiAgLy8gQGZ1bmN0aW9uIHBvaW50c1RvUGF0aChyaW5nczogUG9pbnRbXSwgY2xvc2VkOiBCb29sZWFuKTogU3RyaW5nXG4gIC8vIEdlbmVyYXRlcyBhIFNWRyBwYXRoIHN0cmluZyBmb3IgbXVsdGlwbGUgcmluZ3MsIHdpdGggZWFjaCByaW5nIHR1cm5pbmdcbiAgLy8gaW50byBcIk0uLkwuLkwuLlwiIGluc3RydWN0aW9uc1xuICBmdW5jdGlvbiBwb2ludHNUb1BhdGgocmluZ3MsIGNsb3NlZCkge1xuICBcdHZhciBzdHIgPSAnJyxcbiAgXHRpLCBqLCBsZW4sIGxlbjIsIHBvaW50cywgcDtcblxuICBcdGZvciAoaSA9IDAsIGxlbiA9IHJpbmdzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gIFx0XHRwb2ludHMgPSByaW5nc1tpXTtcblxuICBcdFx0Zm9yIChqID0gMCwgbGVuMiA9IHBvaW50cy5sZW5ndGg7IGogPCBsZW4yOyBqKyspIHtcbiAgXHRcdFx0cCA9IHBvaW50c1tqXTtcbiAgXHRcdFx0c3RyICs9IChqID8gJ0wnIDogJ00nKSArIHAueCArICcgJyArIHAueTtcbiAgXHRcdH1cblxuICBcdFx0Ly8gY2xvc2VzIHRoZSByaW5nIGZvciBwb2x5Z29uczsgXCJ4XCIgaXMgVk1MIHN5bnRheFxuICBcdFx0c3RyICs9IGNsb3NlZCA/IChCcm93c2VyLnN2ZyA/ICd6JyA6ICd4JykgOiAnJztcbiAgXHR9XG5cbiAgXHQvLyBTVkcgY29tcGxhaW5zIGFib3V0IGVtcHR5IHBhdGggc3RyaW5nc1xuICBcdHJldHVybiBzdHIgfHwgJ00wIDAnO1xuICB9XG5cbiAgLypcclxuICAgKiBAbmFtZXNwYWNlIEJyb3dzZXJcclxuICAgKiBAYWthIEwuQnJvd3NlclxyXG4gICAqXHJcbiAgICogQSBuYW1lc3BhY2Ugd2l0aCBzdGF0aWMgcHJvcGVydGllcyBmb3IgYnJvd3Nlci9mZWF0dXJlIGRldGVjdGlvbiB1c2VkIGJ5IExlYWZsZXQgaW50ZXJuYWxseS5cclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICpcclxuICAgKiBgYGBqc1xyXG4gICAqIGlmIChMLkJyb3dzZXIuaWVsdDkpIHtcclxuICAgKiAgIGFsZXJ0KCdVcGdyYWRlIHlvdXIgYnJvd3NlciwgZHVkZSEnKTtcclxuICAgKiB9XHJcbiAgICogYGBgXHJcbiAgICovXHJcblxyXG4gIHZhciBzdHlsZSA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZTtcclxuXHJcbiAgLy8gQHByb3BlcnR5IGllOiBCb29sZWFuOyBgdHJ1ZWAgZm9yIGFsbCBJbnRlcm5ldCBFeHBsb3JlciB2ZXJzaW9ucyAobm90IEVkZ2UpLlxyXG4gIHZhciBpZSA9ICdBY3RpdmVYT2JqZWN0JyBpbiB3aW5kb3c7XHJcblxyXG4gIC8vIEBwcm9wZXJ0eSBpZWx0OTogQm9vbGVhbjsgYHRydWVgIGZvciBJbnRlcm5ldCBFeHBsb3JlciB2ZXJzaW9ucyBsZXNzIHRoYW4gOS5cclxuICB2YXIgaWVsdDkgPSBpZSAmJiAhZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcjtcclxuXHJcbiAgLy8gQHByb3BlcnR5IGVkZ2U6IEJvb2xlYW47IGB0cnVlYCBmb3IgdGhlIEVkZ2Ugd2ViIGJyb3dzZXIuXHJcbiAgdmFyIGVkZ2UgPSAnbXNMYXVuY2hVcmknIGluIG5hdmlnYXRvciAmJiAhKCdkb2N1bWVudE1vZGUnIGluIGRvY3VtZW50KTtcclxuXHJcbiAgLy8gQHByb3BlcnR5IHdlYmtpdDogQm9vbGVhbjtcclxuICAvLyBgdHJ1ZWAgZm9yIHdlYmtpdC1iYXNlZCBicm93c2VycyBsaWtlIENocm9tZSBhbmQgU2FmYXJpIChpbmNsdWRpbmcgbW9iaWxlIHZlcnNpb25zKS5cclxuICB2YXIgd2Via2l0ID0gdXNlckFnZW50Q29udGFpbnMoJ3dlYmtpdCcpO1xyXG5cclxuICAvLyBAcHJvcGVydHkgYW5kcm9pZDogQm9vbGVhblxyXG4gIC8vICoqRGVwcmVjYXRlZC4qKiBgdHJ1ZWAgZm9yIGFueSBicm93c2VyIHJ1bm5pbmcgb24gYW4gQW5kcm9pZCBwbGF0Zm9ybS5cclxuICB2YXIgYW5kcm9pZCA9IHVzZXJBZ2VudENvbnRhaW5zKCdhbmRyb2lkJyk7XHJcblxyXG4gIC8vIEBwcm9wZXJ0eSBhbmRyb2lkMjM6IEJvb2xlYW47ICoqRGVwcmVjYXRlZC4qKiBgdHJ1ZWAgZm9yIGJyb3dzZXJzIHJ1bm5pbmcgb24gQW5kcm9pZCAyIG9yIEFuZHJvaWQgMy5cclxuICB2YXIgYW5kcm9pZDIzID0gdXNlckFnZW50Q29udGFpbnMoJ2FuZHJvaWQgMicpIHx8IHVzZXJBZ2VudENvbnRhaW5zKCdhbmRyb2lkIDMnKTtcclxuXHJcbiAgLyogU2VlIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8xNzk2MTI2NiBmb3IgZGV0YWlscyBvbiBkZXRlY3Rpbmcgc3RvY2sgQW5kcm9pZCAqL1xyXG4gIHZhciB3ZWJraXRWZXIgPSBwYXJzZUludCgvV2ViS2l0XFwvKFswLTldKyl8JC8uZXhlYyhuYXZpZ2F0b3IudXNlckFnZW50KVsxXSwgMTApOyAvLyBhbHNvIG1hdGNoZXMgQXBwbGVXZWJLaXRcclxuICAvLyBAcHJvcGVydHkgYW5kcm9pZFN0b2NrOiBCb29sZWFuOyAqKkRlcHJlY2F0ZWQuKiogYHRydWVgIGZvciB0aGUgQW5kcm9pZCBzdG9jayBicm93c2VyIChpLmUuIG5vdCBDaHJvbWUpXHJcbiAgdmFyIGFuZHJvaWRTdG9jayA9IGFuZHJvaWQgJiYgdXNlckFnZW50Q29udGFpbnMoJ0dvb2dsZScpICYmIHdlYmtpdFZlciA8IDUzNyAmJiAhKCdBdWRpb05vZGUnIGluIHdpbmRvdyk7XHJcblxyXG4gIC8vIEBwcm9wZXJ0eSBvcGVyYTogQm9vbGVhbjsgYHRydWVgIGZvciB0aGUgT3BlcmEgYnJvd3NlclxyXG4gIHZhciBvcGVyYSA9ICEhd2luZG93Lm9wZXJhO1xyXG5cclxuICAvLyBAcHJvcGVydHkgY2hyb21lOiBCb29sZWFuOyBgdHJ1ZWAgZm9yIHRoZSBDaHJvbWUgYnJvd3Nlci5cclxuICB2YXIgY2hyb21lID0gIWVkZ2UgJiYgdXNlckFnZW50Q29udGFpbnMoJ2Nocm9tZScpO1xyXG5cclxuICAvLyBAcHJvcGVydHkgZ2Vja286IEJvb2xlYW47IGB0cnVlYCBmb3IgZ2Vja28tYmFzZWQgYnJvd3NlcnMgbGlrZSBGaXJlZm94LlxyXG4gIHZhciBnZWNrbyA9IHVzZXJBZ2VudENvbnRhaW5zKCdnZWNrbycpICYmICF3ZWJraXQgJiYgIW9wZXJhICYmICFpZTtcclxuXHJcbiAgLy8gQHByb3BlcnR5IHNhZmFyaTogQm9vbGVhbjsgYHRydWVgIGZvciB0aGUgU2FmYXJpIGJyb3dzZXIuXHJcbiAgdmFyIHNhZmFyaSA9ICFjaHJvbWUgJiYgdXNlckFnZW50Q29udGFpbnMoJ3NhZmFyaScpO1xyXG5cclxuICB2YXIgcGhhbnRvbSA9IHVzZXJBZ2VudENvbnRhaW5zKCdwaGFudG9tJyk7XHJcblxyXG4gIC8vIEBwcm9wZXJ0eSBvcGVyYTEyOiBCb29sZWFuXHJcbiAgLy8gYHRydWVgIGZvciB0aGUgT3BlcmEgYnJvd3NlciBzdXBwb3J0aW5nIENTUyB0cmFuc2Zvcm1zICh2ZXJzaW9uIDEyIG9yIGxhdGVyKS5cclxuICB2YXIgb3BlcmExMiA9ICdPVHJhbnNpdGlvbicgaW4gc3R5bGU7XHJcblxyXG4gIC8vIEBwcm9wZXJ0eSB3aW46IEJvb2xlYW47IGB0cnVlYCB3aGVuIHRoZSBicm93c2VyIGlzIHJ1bm5pbmcgaW4gYSBXaW5kb3dzIHBsYXRmb3JtXHJcbiAgdmFyIHdpbiA9IG5hdmlnYXRvci5wbGF0Zm9ybS5pbmRleE9mKCdXaW4nKSA9PT0gMDtcclxuXHJcbiAgLy8gQHByb3BlcnR5IGllM2Q6IEJvb2xlYW47IGB0cnVlYCBmb3IgYWxsIEludGVybmV0IEV4cGxvcmVyIHZlcnNpb25zIHN1cHBvcnRpbmcgQ1NTIHRyYW5zZm9ybXMuXHJcbiAgdmFyIGllM2QgPSBpZSAmJiAoJ3RyYW5zaXRpb24nIGluIHN0eWxlKTtcclxuXHJcbiAgLy8gQHByb3BlcnR5IHdlYmtpdDNkOiBCb29sZWFuOyBgdHJ1ZWAgZm9yIHdlYmtpdC1iYXNlZCBicm93c2VycyBzdXBwb3J0aW5nIENTUyB0cmFuc2Zvcm1zLlxyXG4gIHZhciB3ZWJraXQzZCA9ICgnV2ViS2l0Q1NTTWF0cml4JyBpbiB3aW5kb3cpICYmICgnbTExJyBpbiBuZXcgd2luZG93LldlYktpdENTU01hdHJpeCgpKSAmJiAhYW5kcm9pZDIzO1xyXG5cclxuICAvLyBAcHJvcGVydHkgZ2Vja28zZDogQm9vbGVhbjsgYHRydWVgIGZvciBnZWNrby1iYXNlZCBicm93c2VycyBzdXBwb3J0aW5nIENTUyB0cmFuc2Zvcm1zLlxyXG4gIHZhciBnZWNrbzNkID0gJ01velBlcnNwZWN0aXZlJyBpbiBzdHlsZTtcclxuXHJcbiAgLy8gQHByb3BlcnR5IGFueTNkOiBCb29sZWFuXHJcbiAgLy8gYHRydWVgIGZvciBhbGwgYnJvd3NlcnMgc3VwcG9ydGluZyBDU1MgdHJhbnNmb3Jtcy5cclxuICB2YXIgYW55M2QgPSAhd2luZG93LkxfRElTQUJMRV8zRCAmJiAoaWUzZCB8fCB3ZWJraXQzZCB8fCBnZWNrbzNkKSAmJiAhb3BlcmExMiAmJiAhcGhhbnRvbTtcclxuXHJcbiAgLy8gQHByb3BlcnR5IG1vYmlsZTogQm9vbGVhbjsgYHRydWVgIGZvciBhbGwgYnJvd3NlcnMgcnVubmluZyBpbiBhIG1vYmlsZSBkZXZpY2UuXHJcbiAgdmFyIG1vYmlsZSA9IHR5cGVvZiBvcmllbnRhdGlvbiAhPT0gJ3VuZGVmaW5lZCcgfHwgdXNlckFnZW50Q29udGFpbnMoJ21vYmlsZScpO1xyXG5cclxuICAvLyBAcHJvcGVydHkgbW9iaWxlV2Via2l0OiBCb29sZWFuOyBgdHJ1ZWAgZm9yIGFsbCB3ZWJraXQtYmFzZWQgYnJvd3NlcnMgaW4gYSBtb2JpbGUgZGV2aWNlLlxyXG4gIHZhciBtb2JpbGVXZWJraXQgPSBtb2JpbGUgJiYgd2Via2l0O1xyXG5cclxuICAvLyBAcHJvcGVydHkgbW9iaWxlV2Via2l0M2Q6IEJvb2xlYW5cclxuICAvLyBgdHJ1ZWAgZm9yIGFsbCB3ZWJraXQtYmFzZWQgYnJvd3NlcnMgaW4gYSBtb2JpbGUgZGV2aWNlIHN1cHBvcnRpbmcgQ1NTIHRyYW5zZm9ybXMuXHJcbiAgdmFyIG1vYmlsZVdlYmtpdDNkID0gbW9iaWxlICYmIHdlYmtpdDNkO1xyXG5cclxuICAvLyBAcHJvcGVydHkgbXNQb2ludGVyOiBCb29sZWFuXHJcbiAgLy8gYHRydWVgIGZvciBicm93c2VycyBpbXBsZW1lbnRpbmcgdGhlIE1pY3Jvc29mdCB0b3VjaCBldmVudHMgbW9kZWwgKG5vdGFibHkgSUUxMCkuXHJcbiAgdmFyIG1zUG9pbnRlciA9ICF3aW5kb3cuUG9pbnRlckV2ZW50ICYmIHdpbmRvdy5NU1BvaW50ZXJFdmVudDtcclxuXHJcbiAgLy8gQHByb3BlcnR5IHBvaW50ZXI6IEJvb2xlYW5cclxuICAvLyBgdHJ1ZWAgZm9yIGFsbCBicm93c2VycyBzdXBwb3J0aW5nIFtwb2ludGVyIGV2ZW50c10oaHR0cHM6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9kbjQzMzI0NCUyOHY9dnMuODUlMjkuYXNweCkuXHJcbiAgdmFyIHBvaW50ZXIgPSAhISh3aW5kb3cuUG9pbnRlckV2ZW50IHx8IG1zUG9pbnRlcik7XHJcblxyXG4gIC8vIEBwcm9wZXJ0eSB0b3VjaE5hdGl2ZTogQm9vbGVhblxyXG4gIC8vIGB0cnVlYCBmb3IgYWxsIGJyb3dzZXJzIHN1cHBvcnRpbmcgW3RvdWNoIGV2ZW50c10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQVBJL1RvdWNoX2V2ZW50cykuXHJcbiAgLy8gKipUaGlzIGRvZXMgbm90IG5lY2Vzc2FyaWx5IG1lYW4qKiB0aGF0IHRoZSBicm93c2VyIGlzIHJ1bm5pbmcgaW4gYSBjb21wdXRlciB3aXRoXHJcbiAgLy8gYSB0b3VjaHNjcmVlbiwgaXQgb25seSBtZWFucyB0aGF0IHRoZSBicm93c2VyIGlzIGNhcGFibGUgb2YgdW5kZXJzdGFuZGluZ1xyXG4gIC8vIHRvdWNoIGV2ZW50cy5cclxuICB2YXIgdG91Y2hOYXRpdmUgPSAnb250b3VjaHN0YXJ0JyBpbiB3aW5kb3cgfHwgISF3aW5kb3cuVG91Y2hFdmVudDtcclxuXHJcbiAgLy8gQHByb3BlcnR5IHRvdWNoOiBCb29sZWFuXHJcbiAgLy8gYHRydWVgIGZvciBhbGwgYnJvd3NlcnMgc3VwcG9ydGluZyBlaXRoZXIgW3RvdWNoXSgjYnJvd3Nlci10b3VjaCkgb3IgW3BvaW50ZXJdKCNicm93c2VyLXBvaW50ZXIpIGV2ZW50cy5cclxuICAvLyBOb3RlOiBwb2ludGVyIGV2ZW50cyB3aWxsIGJlIHByZWZlcnJlZCAoaWYgYXZhaWxhYmxlKSwgYW5kIHByb2Nlc3NlZCBmb3IgYWxsIGB0b3VjaCpgIGxpc3RlbmVycy5cclxuICB2YXIgdG91Y2ggPSAhd2luZG93LkxfTk9fVE9VQ0ggJiYgKHRvdWNoTmF0aXZlIHx8IHBvaW50ZXIpO1xyXG5cclxuICAvLyBAcHJvcGVydHkgbW9iaWxlT3BlcmE6IEJvb2xlYW47IGB0cnVlYCBmb3IgdGhlIE9wZXJhIGJyb3dzZXIgaW4gYSBtb2JpbGUgZGV2aWNlLlxyXG4gIHZhciBtb2JpbGVPcGVyYSA9IG1vYmlsZSAmJiBvcGVyYTtcclxuXHJcbiAgLy8gQHByb3BlcnR5IG1vYmlsZUdlY2tvOiBCb29sZWFuXHJcbiAgLy8gYHRydWVgIGZvciBnZWNrby1iYXNlZCBicm93c2VycyBydW5uaW5nIGluIGEgbW9iaWxlIGRldmljZS5cclxuICB2YXIgbW9iaWxlR2Vja28gPSBtb2JpbGUgJiYgZ2Vja287XHJcblxyXG4gIC8vIEBwcm9wZXJ0eSByZXRpbmE6IEJvb2xlYW5cclxuICAvLyBgdHJ1ZWAgZm9yIGJyb3dzZXJzIG9uIGEgaGlnaC1yZXNvbHV0aW9uIFwicmV0aW5hXCIgc2NyZWVuIG9yIG9uIGFueSBzY3JlZW4gd2hlbiBicm93c2VyJ3MgZGlzcGxheSB6b29tIGlzIG1vcmUgdGhhbiAxMDAlLlxyXG4gIHZhciByZXRpbmEgPSAod2luZG93LmRldmljZVBpeGVsUmF0aW8gfHwgKHdpbmRvdy5zY3JlZW4uZGV2aWNlWERQSSAvIHdpbmRvdy5zY3JlZW4ubG9naWNhbFhEUEkpKSA+IDE7XHJcblxyXG4gIC8vIEBwcm9wZXJ0eSBwYXNzaXZlRXZlbnRzOiBCb29sZWFuXHJcbiAgLy8gYHRydWVgIGZvciBicm93c2VycyB0aGF0IHN1cHBvcnQgcGFzc2l2ZSBldmVudHMuXHJcbiAgdmFyIHBhc3NpdmVFdmVudHMgPSAoZnVuY3Rpb24gKCkge1xyXG4gIFx0dmFyIHN1cHBvcnRzUGFzc2l2ZU9wdGlvbiA9IGZhbHNlO1xyXG4gIFx0dHJ5IHtcclxuICBcdFx0dmFyIG9wdHMgPSBPYmplY3QuZGVmaW5lUHJvcGVydHkoe30sICdwYXNzaXZlJywge1xyXG4gIFx0XHRcdGdldDogZnVuY3Rpb24gKCkgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGdldHRlci1yZXR1cm5cclxuICBcdFx0XHRcdHN1cHBvcnRzUGFzc2l2ZU9wdGlvbiA9IHRydWU7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9KTtcclxuICBcdFx0d2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Rlc3RQYXNzaXZlRXZlbnRTdXBwb3J0JywgZmFsc2VGbiwgb3B0cyk7XHJcbiAgXHRcdHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCd0ZXN0UGFzc2l2ZUV2ZW50U3VwcG9ydCcsIGZhbHNlRm4sIG9wdHMpO1xyXG4gIFx0fSBjYXRjaCAoZSkge1xyXG4gIFx0XHQvLyBFcnJvcnMgY2FuIHNhZmVseSBiZSBpZ25vcmVkIHNpbmNlIHRoaXMgaXMgb25seSBhIGJyb3dzZXIgc3VwcG9ydCB0ZXN0LlxyXG4gIFx0fVxyXG4gIFx0cmV0dXJuIHN1cHBvcnRzUGFzc2l2ZU9wdGlvbjtcclxuICB9KCkpO1xyXG5cclxuICAvLyBAcHJvcGVydHkgY2FudmFzOiBCb29sZWFuXHJcbiAgLy8gYHRydWVgIHdoZW4gdGhlIGJyb3dzZXIgc3VwcG9ydHMgW2A8Y2FudmFzPmBdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0FQSS9DYW52YXNfQVBJKS5cclxuICB2YXIgY2FudmFzJDEgPSAoZnVuY3Rpb24gKCkge1xyXG4gIFx0cmV0dXJuICEhZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJykuZ2V0Q29udGV4dDtcclxuICB9KCkpO1xyXG5cclxuICAvLyBAcHJvcGVydHkgc3ZnOiBCb29sZWFuXHJcbiAgLy8gYHRydWVgIHdoZW4gdGhlIGJyb3dzZXIgc3VwcG9ydHMgW1NWR10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvU1ZHKS5cclxuICB2YXIgc3ZnJDEgPSAhIShkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMgJiYgc3ZnQ3JlYXRlKCdzdmcnKS5jcmVhdGVTVkdSZWN0KTtcclxuXHJcbiAgdmFyIGlubGluZVN2ZyA9ICEhc3ZnJDEgJiYgKGZ1bmN0aW9uICgpIHtcclxuICBcdHZhciBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcclxuICBcdGRpdi5pbm5lckhUTUwgPSAnPHN2Zy8+JztcclxuICBcdHJldHVybiAoZGl2LmZpcnN0Q2hpbGQgJiYgZGl2LmZpcnN0Q2hpbGQubmFtZXNwYWNlVVJJKSA9PT0gJ2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJztcclxuICB9KSgpO1xyXG5cclxuICAvLyBAcHJvcGVydHkgdm1sOiBCb29sZWFuXHJcbiAgLy8gYHRydWVgIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIFtWTUxdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1ZlY3Rvcl9NYXJrdXBfTGFuZ3VhZ2UpLlxyXG4gIHZhciB2bWwgPSAhc3ZnJDEgJiYgKGZ1bmN0aW9uICgpIHtcclxuICBcdHRyeSB7XHJcbiAgXHRcdHZhciBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcclxuICBcdFx0ZGl2LmlubmVySFRNTCA9ICc8djpzaGFwZSBhZGo9XCIxXCIvPic7XHJcblxyXG4gIFx0XHR2YXIgc2hhcGUgPSBkaXYuZmlyc3RDaGlsZDtcclxuICBcdFx0c2hhcGUuc3R5bGUuYmVoYXZpb3IgPSAndXJsKCNkZWZhdWx0I1ZNTCknO1xyXG5cclxuICBcdFx0cmV0dXJuIHNoYXBlICYmICh0eXBlb2Ygc2hhcGUuYWRqID09PSAnb2JqZWN0Jyk7XHJcblxyXG4gIFx0fSBjYXRjaCAoZSkge1xyXG4gIFx0XHRyZXR1cm4gZmFsc2U7XHJcbiAgXHR9XHJcbiAgfSgpKTtcclxuXHJcblxyXG4gIC8vIEBwcm9wZXJ0eSBtYWM6IEJvb2xlYW47IGB0cnVlYCB3aGVuIHRoZSBicm93c2VyIGlzIHJ1bm5pbmcgaW4gYSBNYWMgcGxhdGZvcm1cclxuICB2YXIgbWFjID0gbmF2aWdhdG9yLnBsYXRmb3JtLmluZGV4T2YoJ01hYycpID09PSAwO1xyXG5cclxuICAvLyBAcHJvcGVydHkgbWFjOiBCb29sZWFuOyBgdHJ1ZWAgd2hlbiB0aGUgYnJvd3NlciBpcyBydW5uaW5nIGluIGEgTGludXggcGxhdGZvcm1cclxuICB2YXIgbGludXggPSBuYXZpZ2F0b3IucGxhdGZvcm0uaW5kZXhPZignTGludXgnKSA9PT0gMDtcclxuXHJcbiAgZnVuY3Rpb24gdXNlckFnZW50Q29udGFpbnMoc3RyKSB7XHJcbiAgXHRyZXR1cm4gbmF2aWdhdG9yLnVzZXJBZ2VudC50b0xvd2VyQ2FzZSgpLmluZGV4T2Yoc3RyKSA+PSAwO1xyXG4gIH1cclxuXHJcblxyXG4gIHZhciBCcm93c2VyID0ge1xyXG4gIFx0aWU6IGllLFxyXG4gIFx0aWVsdDk6IGllbHQ5LFxyXG4gIFx0ZWRnZTogZWRnZSxcclxuICBcdHdlYmtpdDogd2Via2l0LFxyXG4gIFx0YW5kcm9pZDogYW5kcm9pZCxcclxuICBcdGFuZHJvaWQyMzogYW5kcm9pZDIzLFxyXG4gIFx0YW5kcm9pZFN0b2NrOiBhbmRyb2lkU3RvY2ssXHJcbiAgXHRvcGVyYTogb3BlcmEsXHJcbiAgXHRjaHJvbWU6IGNocm9tZSxcclxuICBcdGdlY2tvOiBnZWNrbyxcclxuICBcdHNhZmFyaTogc2FmYXJpLFxyXG4gIFx0cGhhbnRvbTogcGhhbnRvbSxcclxuICBcdG9wZXJhMTI6IG9wZXJhMTIsXHJcbiAgXHR3aW46IHdpbixcclxuICBcdGllM2Q6IGllM2QsXHJcbiAgXHR3ZWJraXQzZDogd2Via2l0M2QsXHJcbiAgXHRnZWNrbzNkOiBnZWNrbzNkLFxyXG4gIFx0YW55M2Q6IGFueTNkLFxyXG4gIFx0bW9iaWxlOiBtb2JpbGUsXHJcbiAgXHRtb2JpbGVXZWJraXQ6IG1vYmlsZVdlYmtpdCxcclxuICBcdG1vYmlsZVdlYmtpdDNkOiBtb2JpbGVXZWJraXQzZCxcclxuICBcdG1zUG9pbnRlcjogbXNQb2ludGVyLFxyXG4gIFx0cG9pbnRlcjogcG9pbnRlcixcclxuICBcdHRvdWNoOiB0b3VjaCxcclxuICBcdHRvdWNoTmF0aXZlOiB0b3VjaE5hdGl2ZSxcclxuICBcdG1vYmlsZU9wZXJhOiBtb2JpbGVPcGVyYSxcclxuICBcdG1vYmlsZUdlY2tvOiBtb2JpbGVHZWNrbyxcclxuICBcdHJldGluYTogcmV0aW5hLFxyXG4gIFx0cGFzc2l2ZUV2ZW50czogcGFzc2l2ZUV2ZW50cyxcclxuICBcdGNhbnZhczogY2FudmFzJDEsXHJcbiAgXHRzdmc6IHN2ZyQxLFxyXG4gIFx0dm1sOiB2bWwsXHJcbiAgXHRpbmxpbmVTdmc6IGlubGluZVN2ZyxcclxuICBcdG1hYzogbWFjLFxyXG4gIFx0bGludXg6IGxpbnV4XHJcbiAgfTtcblxuICAvKlxuICAgKiBFeHRlbmRzIEwuRG9tRXZlbnQgdG8gcHJvdmlkZSB0b3VjaCBzdXBwb3J0IGZvciBJbnRlcm5ldCBFeHBsb3JlciBhbmQgV2luZG93cy1iYXNlZCBkZXZpY2VzLlxuICAgKi9cblxuICB2YXIgUE9JTlRFUl9ET1dOID0gICBCcm93c2VyLm1zUG9pbnRlciA/ICdNU1BvaW50ZXJEb3duJyAgIDogJ3BvaW50ZXJkb3duJztcbiAgdmFyIFBPSU5URVJfTU9WRSA9ICAgQnJvd3Nlci5tc1BvaW50ZXIgPyAnTVNQb2ludGVyTW92ZScgICA6ICdwb2ludGVybW92ZSc7XG4gIHZhciBQT0lOVEVSX1VQID0gICAgIEJyb3dzZXIubXNQb2ludGVyID8gJ01TUG9pbnRlclVwJyAgICAgOiAncG9pbnRlcnVwJztcbiAgdmFyIFBPSU5URVJfQ0FOQ0VMID0gQnJvd3Nlci5tc1BvaW50ZXIgPyAnTVNQb2ludGVyQ2FuY2VsJyA6ICdwb2ludGVyY2FuY2VsJztcbiAgdmFyIHBFdmVudCA9IHtcbiAgXHR0b3VjaHN0YXJ0ICA6IFBPSU5URVJfRE9XTixcbiAgXHR0b3VjaG1vdmUgICA6IFBPSU5URVJfTU9WRSxcbiAgXHR0b3VjaGVuZCAgICA6IFBPSU5URVJfVVAsXG4gIFx0dG91Y2hjYW5jZWwgOiBQT0lOVEVSX0NBTkNFTFxuICB9O1xuICB2YXIgaGFuZGxlID0ge1xuICBcdHRvdWNoc3RhcnQgIDogX29uUG9pbnRlclN0YXJ0LFxuICBcdHRvdWNobW92ZSAgIDogX2hhbmRsZVBvaW50ZXIsXG4gIFx0dG91Y2hlbmQgICAgOiBfaGFuZGxlUG9pbnRlcixcbiAgXHR0b3VjaGNhbmNlbCA6IF9oYW5kbGVQb2ludGVyXG4gIH07XG4gIHZhciBfcG9pbnRlcnMgPSB7fTtcbiAgdmFyIF9wb2ludGVyRG9jTGlzdGVuZXIgPSBmYWxzZTtcblxuICAvLyBQcm92aWRlcyBhIHRvdWNoIGV2ZW50cyB3cmFwcGVyIGZvciAobXMpcG9pbnRlciBldmVudHMuXG4gIC8vIHJlZiBodHRwczovL3d3dy53My5vcmcvVFIvcG9pbnRlcmV2ZW50cy8gaHR0cHM6Ly93d3cudzMub3JnL0J1Z3MvUHVibGljL3Nob3dfYnVnLmNnaT9pZD0yMjg5MFxuXG4gIGZ1bmN0aW9uIGFkZFBvaW50ZXJMaXN0ZW5lcihvYmosIHR5cGUsIGhhbmRsZXIpIHtcbiAgXHRpZiAodHlwZSA9PT0gJ3RvdWNoc3RhcnQnKSB7XG4gIFx0XHRfYWRkUG9pbnRlckRvY0xpc3RlbmVyKCk7XG4gIFx0fVxuICBcdGlmICghaGFuZGxlW3R5cGVdKSB7XG4gIFx0XHRjb25zb2xlLndhcm4oJ3dyb25nIGV2ZW50IHNwZWNpZmllZDonLCB0eXBlKTtcbiAgXHRcdHJldHVybiBmYWxzZUZuO1xuICBcdH1cbiAgXHRoYW5kbGVyID0gaGFuZGxlW3R5cGVdLmJpbmQodGhpcywgaGFuZGxlcik7XG4gIFx0b2JqLmFkZEV2ZW50TGlzdGVuZXIocEV2ZW50W3R5cGVdLCBoYW5kbGVyLCBmYWxzZSk7XG4gIFx0cmV0dXJuIGhhbmRsZXI7XG4gIH1cblxuICBmdW5jdGlvbiByZW1vdmVQb2ludGVyTGlzdGVuZXIob2JqLCB0eXBlLCBoYW5kbGVyKSB7XG4gIFx0aWYgKCFwRXZlbnRbdHlwZV0pIHtcbiAgXHRcdGNvbnNvbGUud2Fybignd3JvbmcgZXZlbnQgc3BlY2lmaWVkOicsIHR5cGUpO1xuICBcdFx0cmV0dXJuO1xuICBcdH1cbiAgXHRvYmoucmVtb3ZlRXZlbnRMaXN0ZW5lcihwRXZlbnRbdHlwZV0sIGhhbmRsZXIsIGZhbHNlKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIF9nbG9iYWxQb2ludGVyRG93bihlKSB7XG4gIFx0X3BvaW50ZXJzW2UucG9pbnRlcklkXSA9IGU7XG4gIH1cblxuICBmdW5jdGlvbiBfZ2xvYmFsUG9pbnRlck1vdmUoZSkge1xuICBcdGlmIChfcG9pbnRlcnNbZS5wb2ludGVySWRdKSB7XG4gIFx0XHRfcG9pbnRlcnNbZS5wb2ludGVySWRdID0gZTtcbiAgXHR9XG4gIH1cblxuICBmdW5jdGlvbiBfZ2xvYmFsUG9pbnRlclVwKGUpIHtcbiAgXHRkZWxldGUgX3BvaW50ZXJzW2UucG9pbnRlcklkXTtcbiAgfVxuXG4gIGZ1bmN0aW9uIF9hZGRQb2ludGVyRG9jTGlzdGVuZXIoKSB7XG4gIFx0Ly8gbmVlZCB0byBrZWVwIHRyYWNrIG9mIHdoYXQgcG9pbnRlcnMgYW5kIGhvdyBtYW55IGFyZSBhY3RpdmUgdG8gcHJvdmlkZSBlLnRvdWNoZXMgZW11bGF0aW9uXG4gIFx0aWYgKCFfcG9pbnRlckRvY0xpc3RlbmVyKSB7XG4gIFx0XHQvLyB3ZSBsaXN0ZW4gZG9jdW1lbnQgYXMgYW55IGRyYWdzIHRoYXQgZW5kIGJ5IG1vdmluZyB0aGUgdG91Y2ggb2ZmIHRoZSBzY3JlZW4gZ2V0IGZpcmVkIHRoZXJlXG4gIFx0XHRkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFBPSU5URVJfRE9XTiwgX2dsb2JhbFBvaW50ZXJEb3duLCB0cnVlKTtcbiAgXHRcdGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoUE9JTlRFUl9NT1ZFLCBfZ2xvYmFsUG9pbnRlck1vdmUsIHRydWUpO1xuICBcdFx0ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihQT0lOVEVSX1VQLCBfZ2xvYmFsUG9pbnRlclVwLCB0cnVlKTtcbiAgXHRcdGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoUE9JTlRFUl9DQU5DRUwsIF9nbG9iYWxQb2ludGVyVXAsIHRydWUpO1xuXG4gIFx0XHRfcG9pbnRlckRvY0xpc3RlbmVyID0gdHJ1ZTtcbiAgXHR9XG4gIH1cblxuICBmdW5jdGlvbiBfaGFuZGxlUG9pbnRlcihoYW5kbGVyLCBlKSB7XG4gIFx0aWYgKGUucG9pbnRlclR5cGUgPT09IChlLk1TUE9JTlRFUl9UWVBFX01PVVNFIHx8ICdtb3VzZScpKSB7IHJldHVybjsgfVxuXG4gIFx0ZS50b3VjaGVzID0gW107XG4gIFx0Zm9yICh2YXIgaSBpbiBfcG9pbnRlcnMpIHtcbiAgXHRcdGUudG91Y2hlcy5wdXNoKF9wb2ludGVyc1tpXSk7XG4gIFx0fVxuICBcdGUuY2hhbmdlZFRvdWNoZXMgPSBbZV07XG5cbiAgXHRoYW5kbGVyKGUpO1xuICB9XG5cbiAgZnVuY3Rpb24gX29uUG9pbnRlclN0YXJ0KGhhbmRsZXIsIGUpIHtcbiAgXHQvLyBJRTEwIHNwZWNpZmljOiBNc1RvdWNoIG5lZWRzIHByZXZlbnREZWZhdWx0LiBTZWUgIzIwMDBcbiAgXHRpZiAoZS5NU1BPSU5URVJfVFlQRV9UT1VDSCAmJiBlLnBvaW50ZXJUeXBlID09PSBlLk1TUE9JTlRFUl9UWVBFX1RPVUNIKSB7XG4gIFx0XHRwcmV2ZW50RGVmYXVsdChlKTtcbiAgXHR9XG4gIFx0X2hhbmRsZVBvaW50ZXIoaGFuZGxlciwgZSk7XG4gIH1cblxuICAvKlxyXG4gICAqIEV4dGVuZHMgdGhlIGV2ZW50IGhhbmRsaW5nIGNvZGUgd2l0aCBkb3VibGUgdGFwIHN1cHBvcnQgZm9yIG1vYmlsZSBicm93c2Vycy5cclxuICAgKlxyXG4gICAqIE5vdGU6IGN1cnJlbnRseSBtb3N0IGJyb3dzZXJzIGZpcmUgbmF0aXZlIGRibGNsaWNrLCB3aXRoIG9ubHkgYSBmZXcgZXhjZXB0aW9uc1xyXG4gICAqIChzZWUgaHR0cHM6Ly9naXRodWIuY29tL0xlYWZsZXQvTGVhZmxldC9pc3N1ZXMvNzAxMiNpc3N1ZWNvbW1lbnQtNTk1MDg3Mzg2KVxyXG4gICAqL1xyXG5cclxuICBmdW5jdGlvbiBtYWtlRGJsY2xpY2soZXZlbnQpIHtcclxuICBcdC8vIGluIG1vZGVybiBicm93c2VycyBgdHlwZWAgY2Fubm90IGJlIGp1c3Qgb3ZlcnJpZGRlbjpcclxuICBcdC8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0Vycm9ycy9HZXR0ZXJfb25seVxyXG4gIFx0dmFyIG5ld0V2ZW50ID0ge30sXHJcbiAgXHQgICAgcHJvcCwgaTtcclxuICBcdGZvciAoaSBpbiBldmVudCkge1xyXG4gIFx0XHRwcm9wID0gZXZlbnRbaV07XHJcbiAgXHRcdG5ld0V2ZW50W2ldID0gcHJvcCAmJiBwcm9wLmJpbmQgPyBwcm9wLmJpbmQoZXZlbnQpIDogcHJvcDtcclxuICBcdH1cclxuICBcdGV2ZW50ID0gbmV3RXZlbnQ7XHJcbiAgXHRuZXdFdmVudC50eXBlID0gJ2RibGNsaWNrJztcclxuICBcdG5ld0V2ZW50LmRldGFpbCA9IDI7XHJcbiAgXHRuZXdFdmVudC5pc1RydXN0ZWQgPSBmYWxzZTtcclxuICBcdG5ld0V2ZW50Ll9zaW11bGF0ZWQgPSB0cnVlOyAvLyBmb3IgZGVidWcgcHVycG9zZXNcclxuICBcdHJldHVybiBuZXdFdmVudDtcclxuICB9XHJcblxyXG4gIHZhciBkZWxheSA9IDIwMDtcclxuICBmdW5jdGlvbiBhZGREb3VibGVUYXBMaXN0ZW5lcihvYmosIGhhbmRsZXIpIHtcclxuICBcdC8vIE1vc3QgYnJvd3NlcnMgaGFuZGxlIGRvdWJsZSB0YXAgbmF0aXZlbHlcclxuICBcdG9iai5hZGRFdmVudExpc3RlbmVyKCdkYmxjbGljaycsIGhhbmRsZXIpO1xyXG5cclxuICBcdC8vIE9uIHNvbWUgcGxhdGZvcm1zIHRoZSBicm93c2VyIGRvZXNuJ3QgZmlyZSBuYXRpdmUgZGJsY2xpY2tzIGZvciB0b3VjaCBldmVudHMuXHJcbiAgXHQvLyBJdCBzZWVtcyB0aGF0IGluIGFsbCBzdWNoIGNhc2VzIGBkZXRhaWxgIHByb3BlcnR5IG9mIGBjbGlja2AgZXZlbnQgaXMgYWx3YXlzIGAxYC5cclxuICBcdC8vIFNvIGhlcmUgd2UgcmVseSBvbiB0aGF0IGZhY3QgdG8gYXZvaWQgZXhjZXNzaXZlICdkYmxjbGljaycgc2ltdWxhdGlvbiB3aGVuIG5vdCBuZWVkZWQuXHJcbiAgXHR2YXIgbGFzdCA9IDAsXHJcbiAgXHQgICAgZGV0YWlsO1xyXG4gIFx0ZnVuY3Rpb24gc2ltRGJsY2xpY2soZSkge1xyXG4gIFx0XHRpZiAoZS5kZXRhaWwgIT09IDEpIHtcclxuICBcdFx0XHRkZXRhaWwgPSBlLmRldGFpbDsgLy8ga2VlcCBpbiBzeW5jIHRvIGF2b2lkIGZhbHNlIGRibGNsaWNrIGluIHNvbWUgY2FzZXNcclxuICBcdFx0XHRyZXR1cm47XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmIChlLnBvaW50ZXJUeXBlID09PSAnbW91c2UnIHx8XHJcbiAgXHRcdFx0KGUuc291cmNlQ2FwYWJpbGl0aWVzICYmICFlLnNvdXJjZUNhcGFiaWxpdGllcy5maXJlc1RvdWNoRXZlbnRzKSkge1xyXG5cclxuICBcdFx0XHRyZXR1cm47XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdC8vIFdoZW4gY2xpY2tpbmcgb24gYW4gPGlucHV0PiwgdGhlIGJyb3dzZXIgZ2VuZXJhdGVzIGEgY2xpY2sgb24gaXRzXHJcbiAgXHRcdC8vIDxsYWJlbD4gKGFuZCB2aWNlIHZlcnNhKSB0cmlnZ2VyaW5nIHR3byBjbGlja3MgaW4gcXVpY2sgc3VjY2Vzc2lvbi5cclxuICBcdFx0Ly8gVGhpcyBpZ25vcmVzIGNsaWNrcyBvbiBlbGVtZW50cyB3aGljaCBhcmUgYSBsYWJlbCB3aXRoIGEgJ2ZvcidcclxuICBcdFx0Ly8gYXR0cmlidXRlIChvciBjaGlsZHJlbiBvZiBzdWNoIGEgbGFiZWwpLCBidXQgbm90IGNoaWxkcmVuIG9mXHJcbiAgXHRcdC8vIGEgPGlucHV0Pi5cclxuICBcdFx0dmFyIHBhdGggPSBnZXRQcm9wYWdhdGlvblBhdGgoZSk7XHJcbiAgXHRcdGlmIChwYXRoLnNvbWUoZnVuY3Rpb24gKGVsKSB7XHJcbiAgXHRcdFx0cmV0dXJuIGVsIGluc3RhbmNlb2YgSFRNTExhYmVsRWxlbWVudCAmJiBlbC5hdHRyaWJ1dGVzLmZvcjtcclxuICBcdFx0fSkgJiZcclxuICBcdFx0XHQhcGF0aC5zb21lKGZ1bmN0aW9uIChlbCkge1xyXG4gIFx0XHRcdFx0cmV0dXJuIChcclxuICBcdFx0XHRcdFx0ZWwgaW5zdGFuY2VvZiBIVE1MSW5wdXRFbGVtZW50IHx8XHJcbiAgXHRcdFx0XHRcdGVsIGluc3RhbmNlb2YgSFRNTFNlbGVjdEVsZW1lbnRcclxuICBcdFx0XHRcdCk7XHJcbiAgXHRcdFx0fSlcclxuICBcdFx0KSB7XHJcbiAgXHRcdFx0cmV0dXJuO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgbm93ID0gRGF0ZS5ub3coKTtcclxuICBcdFx0aWYgKG5vdyAtIGxhc3QgPD0gZGVsYXkpIHtcclxuICBcdFx0XHRkZXRhaWwrKztcclxuICBcdFx0XHRpZiAoZGV0YWlsID09PSAyKSB7XHJcbiAgXHRcdFx0XHRoYW5kbGVyKG1ha2VEYmxjbGljayhlKSk7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdGRldGFpbCA9IDE7XHJcbiAgXHRcdH1cclxuICBcdFx0bGFzdCA9IG5vdztcclxuICBcdH1cclxuXHJcbiAgXHRvYmouYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBzaW1EYmxjbGljayk7XHJcblxyXG4gIFx0cmV0dXJuIHtcclxuICBcdFx0ZGJsY2xpY2s6IGhhbmRsZXIsXHJcbiAgXHRcdHNpbURibGNsaWNrOiBzaW1EYmxjbGlja1xyXG4gIFx0fTtcclxuICB9XHJcblxyXG4gIGZ1bmN0aW9uIHJlbW92ZURvdWJsZVRhcExpc3RlbmVyKG9iaiwgaGFuZGxlcnMpIHtcclxuICBcdG9iai5yZW1vdmVFdmVudExpc3RlbmVyKCdkYmxjbGljaycsIGhhbmRsZXJzLmRibGNsaWNrKTtcclxuICBcdG9iai5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIGhhbmRsZXJzLnNpbURibGNsaWNrKTtcclxuICB9XG5cbiAgLypcclxuICAgKiBAbmFtZXNwYWNlIERvbVV0aWxcclxuICAgKlxyXG4gICAqIFV0aWxpdHkgZnVuY3Rpb25zIHRvIHdvcmsgd2l0aCB0aGUgW0RPTV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQVBJL0RvY3VtZW50X09iamVjdF9Nb2RlbClcclxuICAgKiB0cmVlLCB1c2VkIGJ5IExlYWZsZXQgaW50ZXJuYWxseS5cclxuICAgKlxyXG4gICAqIE1vc3QgZnVuY3Rpb25zIGV4cGVjdGluZyBvciByZXR1cm5pbmcgYSBgSFRNTEVsZW1lbnRgIGFsc28gd29yayBmb3JcclxuICAgKiBTVkcgZWxlbWVudHMuIFRoZSBvbmx5IGRpZmZlcmVuY2UgaXMgdGhhdCBjbGFzc2VzIHJlZmVyIHRvIENTUyBjbGFzc2VzXHJcbiAgICogaW4gSFRNTCBhbmQgU1ZHIGNsYXNzZXMgaW4gU1ZHLlxyXG4gICAqL1xyXG5cclxuXHJcbiAgLy8gQHByb3BlcnR5IFRSQU5TRk9STTogU3RyaW5nXHJcbiAgLy8gVmVuZG9yLXByZWZpeGVkIHRyYW5zZm9ybSBzdHlsZSBuYW1lIChlLmcuIGAnd2Via2l0VHJhbnNmb3JtJ2AgZm9yIFdlYktpdCkuXHJcbiAgdmFyIFRSQU5TRk9STSA9IHRlc3RQcm9wKFxyXG4gIFx0Wyd0cmFuc2Zvcm0nLCAnd2Via2l0VHJhbnNmb3JtJywgJ09UcmFuc2Zvcm0nLCAnTW96VHJhbnNmb3JtJywgJ21zVHJhbnNmb3JtJ10pO1xyXG5cclxuICAvLyB3ZWJraXRUcmFuc2l0aW9uIGNvbWVzIGZpcnN0IGJlY2F1c2Ugc29tZSBicm93c2VyIHZlcnNpb25zIHRoYXQgZHJvcCB2ZW5kb3IgcHJlZml4IGRvbid0IGRvXHJcbiAgLy8gdGhlIHNhbWUgZm9yIHRoZSB0cmFuc2l0aW9uZW5kIGV2ZW50LCBpbiBwYXJ0aWN1bGFyIHRoZSBBbmRyb2lkIDQuMSBzdG9jayBicm93c2VyXHJcblxyXG4gIC8vIEBwcm9wZXJ0eSBUUkFOU0lUSU9OOiBTdHJpbmdcclxuICAvLyBWZW5kb3ItcHJlZml4ZWQgdHJhbnNpdGlvbiBzdHlsZSBuYW1lLlxyXG4gIHZhciBUUkFOU0lUSU9OID0gdGVzdFByb3AoXHJcbiAgXHRbJ3dlYmtpdFRyYW5zaXRpb24nLCAndHJhbnNpdGlvbicsICdPVHJhbnNpdGlvbicsICdNb3pUcmFuc2l0aW9uJywgJ21zVHJhbnNpdGlvbiddKTtcclxuXHJcbiAgLy8gQHByb3BlcnR5IFRSQU5TSVRJT05fRU5EOiBTdHJpbmdcclxuICAvLyBWZW5kb3ItcHJlZml4ZWQgdHJhbnNpdGlvbmVuZCBldmVudCBuYW1lLlxyXG4gIHZhciBUUkFOU0lUSU9OX0VORCA9XHJcbiAgXHRUUkFOU0lUSU9OID09PSAnd2Via2l0VHJhbnNpdGlvbicgfHwgVFJBTlNJVElPTiA9PT0gJ09UcmFuc2l0aW9uJyA/IFRSQU5TSVRJT04gKyAnRW5kJyA6ICd0cmFuc2l0aW9uZW5kJztcclxuXHJcblxyXG4gIC8vIEBmdW5jdGlvbiBnZXQoaWQ6IFN0cmluZ3xIVE1MRWxlbWVudCk6IEhUTUxFbGVtZW50XHJcbiAgLy8gUmV0dXJucyBhbiBlbGVtZW50IGdpdmVuIGl0cyBET00gaWQsIG9yIHJldHVybnMgdGhlIGVsZW1lbnQgaXRzZWxmXHJcbiAgLy8gaWYgaXQgd2FzIHBhc3NlZCBkaXJlY3RseS5cclxuICBmdW5jdGlvbiBnZXQoaWQpIHtcclxuICBcdHJldHVybiB0eXBlb2YgaWQgPT09ICdzdHJpbmcnID8gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpIDogaWQ7XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gZ2V0U3R5bGUoZWw6IEhUTUxFbGVtZW50LCBzdHlsZUF0dHJpYjogU3RyaW5nKTogU3RyaW5nXHJcbiAgLy8gUmV0dXJucyB0aGUgdmFsdWUgZm9yIGEgY2VydGFpbiBzdHlsZSBhdHRyaWJ1dGUgb24gYW4gZWxlbWVudCxcclxuICAvLyBpbmNsdWRpbmcgY29tcHV0ZWQgdmFsdWVzIG9yIHZhbHVlcyBzZXQgdGhyb3VnaCBDU1MuXHJcbiAgZnVuY3Rpb24gZ2V0U3R5bGUoZWwsIHN0eWxlKSB7XHJcbiAgXHR2YXIgdmFsdWUgPSBlbC5zdHlsZVtzdHlsZV0gfHwgKGVsLmN1cnJlbnRTdHlsZSAmJiBlbC5jdXJyZW50U3R5bGVbc3R5bGVdKTtcclxuXHJcbiAgXHRpZiAoKCF2YWx1ZSB8fCB2YWx1ZSA9PT0gJ2F1dG8nKSAmJiBkb2N1bWVudC5kZWZhdWx0Vmlldykge1xyXG4gIFx0XHR2YXIgY3NzID0gZG9jdW1lbnQuZGVmYXVsdFZpZXcuZ2V0Q29tcHV0ZWRTdHlsZShlbCwgbnVsbCk7XHJcbiAgXHRcdHZhbHVlID0gY3NzID8gY3NzW3N0eWxlXSA6IG51bGw7XHJcbiAgXHR9XHJcbiAgXHRyZXR1cm4gdmFsdWUgPT09ICdhdXRvJyA/IG51bGwgOiB2YWx1ZTtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBjcmVhdGUodGFnTmFtZTogU3RyaW5nLCBjbGFzc05hbWU/OiBTdHJpbmcsIGNvbnRhaW5lcj86IEhUTUxFbGVtZW50KTogSFRNTEVsZW1lbnRcclxuICAvLyBDcmVhdGVzIGFuIEhUTUwgZWxlbWVudCB3aXRoIGB0YWdOYW1lYCwgc2V0cyBpdHMgY2xhc3MgdG8gYGNsYXNzTmFtZWAsIGFuZCBvcHRpb25hbGx5IGFwcGVuZHMgaXQgdG8gYGNvbnRhaW5lcmAgZWxlbWVudC5cclxuICBmdW5jdGlvbiBjcmVhdGUkMSh0YWdOYW1lLCBjbGFzc05hbWUsIGNvbnRhaW5lcikge1xyXG4gIFx0dmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWdOYW1lKTtcclxuICBcdGVsLmNsYXNzTmFtZSA9IGNsYXNzTmFtZSB8fCAnJztcclxuXHJcbiAgXHRpZiAoY29udGFpbmVyKSB7XHJcbiAgXHRcdGNvbnRhaW5lci5hcHBlbmRDaGlsZChlbCk7XHJcbiAgXHR9XHJcbiAgXHRyZXR1cm4gZWw7XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gcmVtb3ZlKGVsOiBIVE1MRWxlbWVudClcclxuICAvLyBSZW1vdmVzIGBlbGAgZnJvbSBpdHMgcGFyZW50IGVsZW1lbnRcclxuICBmdW5jdGlvbiByZW1vdmUoZWwpIHtcclxuICBcdHZhciBwYXJlbnQgPSBlbC5wYXJlbnROb2RlO1xyXG4gIFx0aWYgKHBhcmVudCkge1xyXG4gIFx0XHRwYXJlbnQucmVtb3ZlQ2hpbGQoZWwpO1xyXG4gIFx0fVxyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGVtcHR5KGVsOiBIVE1MRWxlbWVudClcclxuICAvLyBSZW1vdmVzIGFsbCBvZiBgZWxgJ3MgY2hpbGRyZW4gZWxlbWVudHMgZnJvbSBgZWxgXHJcbiAgZnVuY3Rpb24gZW1wdHkoZWwpIHtcclxuICBcdHdoaWxlIChlbC5maXJzdENoaWxkKSB7XHJcbiAgXHRcdGVsLnJlbW92ZUNoaWxkKGVsLmZpcnN0Q2hpbGQpO1xyXG4gIFx0fVxyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIHRvRnJvbnQoZWw6IEhUTUxFbGVtZW50KVxyXG4gIC8vIE1ha2VzIGBlbGAgdGhlIGxhc3QgY2hpbGQgb2YgaXRzIHBhcmVudCwgc28gaXQgcmVuZGVycyBpbiBmcm9udCBvZiB0aGUgb3RoZXIgY2hpbGRyZW4uXHJcbiAgZnVuY3Rpb24gdG9Gcm9udChlbCkge1xyXG4gIFx0dmFyIHBhcmVudCA9IGVsLnBhcmVudE5vZGU7XHJcbiAgXHRpZiAocGFyZW50ICYmIHBhcmVudC5sYXN0Q2hpbGQgIT09IGVsKSB7XHJcbiAgXHRcdHBhcmVudC5hcHBlbmRDaGlsZChlbCk7XHJcbiAgXHR9XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gdG9CYWNrKGVsOiBIVE1MRWxlbWVudClcclxuICAvLyBNYWtlcyBgZWxgIHRoZSBmaXJzdCBjaGlsZCBvZiBpdHMgcGFyZW50LCBzbyBpdCByZW5kZXJzIGJlaGluZCB0aGUgb3RoZXIgY2hpbGRyZW4uXHJcbiAgZnVuY3Rpb24gdG9CYWNrKGVsKSB7XHJcbiAgXHR2YXIgcGFyZW50ID0gZWwucGFyZW50Tm9kZTtcclxuICBcdGlmIChwYXJlbnQgJiYgcGFyZW50LmZpcnN0Q2hpbGQgIT09IGVsKSB7XHJcbiAgXHRcdHBhcmVudC5pbnNlcnRCZWZvcmUoZWwsIHBhcmVudC5maXJzdENoaWxkKTtcclxuICBcdH1cclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBoYXNDbGFzcyhlbDogSFRNTEVsZW1lbnQsIG5hbWU6IFN0cmluZyk6IEJvb2xlYW5cclxuICAvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZWxlbWVudCdzIGNsYXNzIGF0dHJpYnV0ZSBjb250YWlucyBgbmFtZWAuXHJcbiAgZnVuY3Rpb24gaGFzQ2xhc3MoZWwsIG5hbWUpIHtcclxuICBcdGlmIChlbC5jbGFzc0xpc3QgIT09IHVuZGVmaW5lZCkge1xyXG4gIFx0XHRyZXR1cm4gZWwuY2xhc3NMaXN0LmNvbnRhaW5zKG5hbWUpO1xyXG4gIFx0fVxyXG4gIFx0dmFyIGNsYXNzTmFtZSA9IGdldENsYXNzKGVsKTtcclxuICBcdHJldHVybiBjbGFzc05hbWUubGVuZ3RoID4gMCAmJiBuZXcgUmVnRXhwKCcoXnxcXFxccyknICsgbmFtZSArICcoXFxcXHN8JCknKS50ZXN0KGNsYXNzTmFtZSk7XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gYWRkQ2xhc3MoZWw6IEhUTUxFbGVtZW50LCBuYW1lOiBTdHJpbmcpXHJcbiAgLy8gQWRkcyBgbmFtZWAgdG8gdGhlIGVsZW1lbnQncyBjbGFzcyBhdHRyaWJ1dGUuXHJcbiAgZnVuY3Rpb24gYWRkQ2xhc3MoZWwsIG5hbWUpIHtcclxuICBcdGlmIChlbC5jbGFzc0xpc3QgIT09IHVuZGVmaW5lZCkge1xyXG4gIFx0XHR2YXIgY2xhc3NlcyA9IHNwbGl0V29yZHMobmFtZSk7XHJcbiAgXHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBjbGFzc2VzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdFx0ZWwuY2xhc3NMaXN0LmFkZChjbGFzc2VzW2ldKTtcclxuICBcdFx0fVxyXG4gIFx0fSBlbHNlIGlmICghaGFzQ2xhc3MoZWwsIG5hbWUpKSB7XHJcbiAgXHRcdHZhciBjbGFzc05hbWUgPSBnZXRDbGFzcyhlbCk7XHJcbiAgXHRcdHNldENsYXNzKGVsLCAoY2xhc3NOYW1lID8gY2xhc3NOYW1lICsgJyAnIDogJycpICsgbmFtZSk7XHJcbiAgXHR9XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gcmVtb3ZlQ2xhc3MoZWw6IEhUTUxFbGVtZW50LCBuYW1lOiBTdHJpbmcpXHJcbiAgLy8gUmVtb3ZlcyBgbmFtZWAgZnJvbSB0aGUgZWxlbWVudCdzIGNsYXNzIGF0dHJpYnV0ZS5cclxuICBmdW5jdGlvbiByZW1vdmVDbGFzcyhlbCwgbmFtZSkge1xyXG4gIFx0aWYgKGVsLmNsYXNzTGlzdCAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgXHRcdGVsLmNsYXNzTGlzdC5yZW1vdmUobmFtZSk7XHJcbiAgXHR9IGVsc2Uge1xyXG4gIFx0XHRzZXRDbGFzcyhlbCwgdHJpbSgoJyAnICsgZ2V0Q2xhc3MoZWwpICsgJyAnKS5yZXBsYWNlKCcgJyArIG5hbWUgKyAnICcsICcgJykpKTtcclxuICBcdH1cclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBzZXRDbGFzcyhlbDogSFRNTEVsZW1lbnQsIG5hbWU6IFN0cmluZylcclxuICAvLyBTZXRzIHRoZSBlbGVtZW50J3MgY2xhc3MuXHJcbiAgZnVuY3Rpb24gc2V0Q2xhc3MoZWwsIG5hbWUpIHtcclxuICBcdGlmIChlbC5jbGFzc05hbWUuYmFzZVZhbCA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgXHRcdGVsLmNsYXNzTmFtZSA9IG5hbWU7XHJcbiAgXHR9IGVsc2Uge1xyXG4gIFx0XHQvLyBpbiBjYXNlIG9mIFNWRyBlbGVtZW50XHJcbiAgXHRcdGVsLmNsYXNzTmFtZS5iYXNlVmFsID0gbmFtZTtcclxuICBcdH1cclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBnZXRDbGFzcyhlbDogSFRNTEVsZW1lbnQpOiBTdHJpbmdcclxuICAvLyBSZXR1cm5zIHRoZSBlbGVtZW50J3MgY2xhc3MuXHJcbiAgZnVuY3Rpb24gZ2V0Q2xhc3MoZWwpIHtcclxuICBcdC8vIENoZWNrIGlmIHRoZSBlbGVtZW50IGlzIGFuIFNWR0VsZW1lbnRJbnN0YW5jZSBhbmQgdXNlIHRoZSBjb3JyZXNwb25kaW5nRWxlbWVudCBpbnN0ZWFkXHJcbiAgXHQvLyAoUmVxdWlyZWQgZm9yIGxpbmtlZCBTVkcgZWxlbWVudHMgaW4gSUUxMS4pXHJcbiAgXHRpZiAoZWwuY29ycmVzcG9uZGluZ0VsZW1lbnQpIHtcclxuICBcdFx0ZWwgPSBlbC5jb3JyZXNwb25kaW5nRWxlbWVudDtcclxuICBcdH1cclxuICBcdHJldHVybiBlbC5jbGFzc05hbWUuYmFzZVZhbCA9PT0gdW5kZWZpbmVkID8gZWwuY2xhc3NOYW1lIDogZWwuY2xhc3NOYW1lLmJhc2VWYWw7XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gc2V0T3BhY2l0eShlbDogSFRNTEVsZW1lbnQsIG9wYWNpdHk6IE51bWJlcilcclxuICAvLyBTZXQgdGhlIG9wYWNpdHkgb2YgYW4gZWxlbWVudCAoaW5jbHVkaW5nIG9sZCBJRSBzdXBwb3J0KS5cclxuICAvLyBgb3BhY2l0eWAgbXVzdCBiZSBhIG51bWJlciBmcm9tIGAwYCB0byBgMWAuXHJcbiAgZnVuY3Rpb24gc2V0T3BhY2l0eShlbCwgdmFsdWUpIHtcclxuICBcdGlmICgnb3BhY2l0eScgaW4gZWwuc3R5bGUpIHtcclxuICBcdFx0ZWwuc3R5bGUub3BhY2l0eSA9IHZhbHVlO1xyXG4gIFx0fSBlbHNlIGlmICgnZmlsdGVyJyBpbiBlbC5zdHlsZSkge1xyXG4gIFx0XHRfc2V0T3BhY2l0eUlFKGVsLCB2YWx1ZSk7XHJcbiAgXHR9XHJcbiAgfVxyXG5cclxuICBmdW5jdGlvbiBfc2V0T3BhY2l0eUlFKGVsLCB2YWx1ZSkge1xyXG4gIFx0dmFyIGZpbHRlciA9IGZhbHNlLFxyXG4gIFx0ICAgIGZpbHRlck5hbWUgPSAnRFhJbWFnZVRyYW5zZm9ybS5NaWNyb3NvZnQuQWxwaGEnO1xyXG5cclxuICBcdC8vIGZpbHRlcnMgY29sbGVjdGlvbiB0aHJvd3MgYW4gZXJyb3IgaWYgd2UgdHJ5IHRvIHJldHJpZXZlIGEgZmlsdGVyIHRoYXQgZG9lc24ndCBleGlzdFxyXG4gIFx0dHJ5IHtcclxuICBcdFx0ZmlsdGVyID0gZWwuZmlsdGVycy5pdGVtKGZpbHRlck5hbWUpO1xyXG4gIFx0fSBjYXRjaCAoZSkge1xyXG4gIFx0XHQvLyBkb24ndCBzZXQgb3BhY2l0eSB0byAxIGlmIHdlIGhhdmVuJ3QgYWxyZWFkeSBzZXQgYW4gb3BhY2l0eSxcclxuICBcdFx0Ly8gaXQgaXNuJ3QgbmVlZGVkIGFuZCBicmVha3MgdHJhbnNwYXJlbnQgcG5ncy5cclxuICBcdFx0aWYgKHZhbHVlID09PSAxKSB7IHJldHVybjsgfVxyXG4gIFx0fVxyXG5cclxuICBcdHZhbHVlID0gTWF0aC5yb3VuZCh2YWx1ZSAqIDEwMCk7XHJcblxyXG4gIFx0aWYgKGZpbHRlcikge1xyXG4gIFx0XHRmaWx0ZXIuRW5hYmxlZCA9ICh2YWx1ZSAhPT0gMTAwKTtcclxuICBcdFx0ZmlsdGVyLk9wYWNpdHkgPSB2YWx1ZTtcclxuICBcdH0gZWxzZSB7XHJcbiAgXHRcdGVsLnN0eWxlLmZpbHRlciArPSAnIHByb2dpZDonICsgZmlsdGVyTmFtZSArICcob3BhY2l0eT0nICsgdmFsdWUgKyAnKSc7XHJcbiAgXHR9XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gdGVzdFByb3AocHJvcHM6IFN0cmluZ1tdKTogU3RyaW5nfGZhbHNlXHJcbiAgLy8gR29lcyB0aHJvdWdoIHRoZSBhcnJheSBvZiBzdHlsZSBuYW1lcyBhbmQgcmV0dXJucyB0aGUgZmlyc3QgbmFtZVxyXG4gIC8vIHRoYXQgaXMgYSB2YWxpZCBzdHlsZSBuYW1lIGZvciBhbiBlbGVtZW50LiBJZiBubyBzdWNoIG5hbWUgaXMgZm91bmQsXHJcbiAgLy8gaXQgcmV0dXJucyBmYWxzZS4gVXNlZnVsIGZvciB2ZW5kb3ItcHJlZml4ZWQgc3R5bGVzIGxpa2UgYHRyYW5zZm9ybWAuXHJcbiAgZnVuY3Rpb24gdGVzdFByb3AocHJvcHMpIHtcclxuICBcdHZhciBzdHlsZSA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZTtcclxuXHJcbiAgXHRmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7XHJcbiAgXHRcdGlmIChwcm9wc1tpXSBpbiBzdHlsZSkge1xyXG4gIFx0XHRcdHJldHVybiBwcm9wc1tpXTtcclxuICBcdFx0fVxyXG4gIFx0fVxyXG4gIFx0cmV0dXJuIGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIHNldFRyYW5zZm9ybShlbDogSFRNTEVsZW1lbnQsIG9mZnNldDogUG9pbnQsIHNjYWxlPzogTnVtYmVyKVxyXG4gIC8vIFJlc2V0cyB0aGUgM0QgQ1NTIHRyYW5zZm9ybSBvZiBgZWxgIHNvIGl0IGlzIHRyYW5zbGF0ZWQgYnkgYG9mZnNldGAgcGl4ZWxzXHJcbiAgLy8gYW5kIG9wdGlvbmFsbHkgc2NhbGVkIGJ5IGBzY2FsZWAuIERvZXMgbm90IGhhdmUgYW4gZWZmZWN0IGlmIHRoZVxyXG4gIC8vIGJyb3dzZXIgZG9lc24ndCBzdXBwb3J0IDNEIENTUyB0cmFuc2Zvcm1zLlxyXG4gIGZ1bmN0aW9uIHNldFRyYW5zZm9ybShlbCwgb2Zmc2V0LCBzY2FsZSkge1xyXG4gIFx0dmFyIHBvcyA9IG9mZnNldCB8fCBuZXcgUG9pbnQoMCwgMCk7XHJcblxyXG4gIFx0ZWwuc3R5bGVbVFJBTlNGT1JNXSA9XHJcbiAgXHRcdChCcm93c2VyLmllM2QgP1xyXG4gIFx0XHRcdCd0cmFuc2xhdGUoJyArIHBvcy54ICsgJ3B4LCcgKyBwb3MueSArICdweCknIDpcclxuICBcdFx0XHQndHJhbnNsYXRlM2QoJyArIHBvcy54ICsgJ3B4LCcgKyBwb3MueSArICdweCwwKScpICtcclxuICBcdFx0KHNjYWxlID8gJyBzY2FsZSgnICsgc2NhbGUgKyAnKScgOiAnJyk7XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gc2V0UG9zaXRpb24oZWw6IEhUTUxFbGVtZW50LCBwb3NpdGlvbjogUG9pbnQpXHJcbiAgLy8gU2V0cyB0aGUgcG9zaXRpb24gb2YgYGVsYCB0byBjb29yZGluYXRlcyBzcGVjaWZpZWQgYnkgYHBvc2l0aW9uYCxcclxuICAvLyB1c2luZyBDU1MgdHJhbnNsYXRlIG9yIHRvcC9sZWZ0IHBvc2l0aW9uaW5nIGRlcGVuZGluZyBvbiB0aGUgYnJvd3NlclxyXG4gIC8vICh1c2VkIGJ5IExlYWZsZXQgaW50ZXJuYWxseSB0byBwb3NpdGlvbiBpdHMgbGF5ZXJzKS5cclxuICBmdW5jdGlvbiBzZXRQb3NpdGlvbihlbCwgcG9pbnQpIHtcclxuXHJcbiAgXHQvKmVzbGludC1kaXNhYmxlICovXHJcbiAgXHRlbC5fbGVhZmxldF9wb3MgPSBwb2ludDtcclxuICBcdC8qIGVzbGludC1lbmFibGUgKi9cclxuXHJcbiAgXHRpZiAoQnJvd3Nlci5hbnkzZCkge1xyXG4gIFx0XHRzZXRUcmFuc2Zvcm0oZWwsIHBvaW50KTtcclxuICBcdH0gZWxzZSB7XHJcbiAgXHRcdGVsLnN0eWxlLmxlZnQgPSBwb2ludC54ICsgJ3B4JztcclxuICBcdFx0ZWwuc3R5bGUudG9wID0gcG9pbnQueSArICdweCc7XHJcbiAgXHR9XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gZ2V0UG9zaXRpb24oZWw6IEhUTUxFbGVtZW50KTogUG9pbnRcclxuICAvLyBSZXR1cm5zIHRoZSBjb29yZGluYXRlcyBvZiBhbiBlbGVtZW50IHByZXZpb3VzbHkgcG9zaXRpb25lZCB3aXRoIHNldFBvc2l0aW9uLlxyXG4gIGZ1bmN0aW9uIGdldFBvc2l0aW9uKGVsKSB7XHJcbiAgXHQvLyB0aGlzIG1ldGhvZCBpcyBvbmx5IHVzZWQgZm9yIGVsZW1lbnRzIHByZXZpb3VzbHkgcG9zaXRpb25lZCB1c2luZyBzZXRQb3NpdGlvbixcclxuICBcdC8vIHNvIGl0J3Mgc2FmZSB0byBjYWNoZSB0aGUgcG9zaXRpb24gZm9yIHBlcmZvcm1hbmNlXHJcblxyXG4gIFx0cmV0dXJuIGVsLl9sZWFmbGV0X3BvcyB8fCBuZXcgUG9pbnQoMCwgMCk7XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gZGlzYWJsZVRleHRTZWxlY3Rpb24oKVxyXG4gIC8vIFByZXZlbnRzIHRoZSB1c2VyIGZyb20gZ2VuZXJhdGluZyBgc2VsZWN0c3RhcnRgIERPTSBldmVudHMsIHVzdWFsbHkgZ2VuZXJhdGVkXHJcbiAgLy8gd2hlbiB0aGUgdXNlciBkcmFncyB0aGUgbW91c2UgdGhyb3VnaCBhIHBhZ2Ugd2l0aCB0ZXh0LiBVc2VkIGludGVybmFsbHlcclxuICAvLyBieSBMZWFmbGV0IHRvIG92ZXJyaWRlIHRoZSBiZWhhdmlvdXIgb2YgYW55IGNsaWNrLWFuZC1kcmFnIGludGVyYWN0aW9uIG9uXHJcbiAgLy8gdGhlIG1hcC4gQWZmZWN0cyBkcmFnIGludGVyYWN0aW9ucyBvbiB0aGUgd2hvbGUgZG9jdW1lbnQuXHJcblxyXG4gIC8vIEBmdW5jdGlvbiBlbmFibGVUZXh0U2VsZWN0aW9uKClcclxuICAvLyBDYW5jZWxzIHRoZSBlZmZlY3RzIG9mIGEgcHJldmlvdXMgW2BMLkRvbVV0aWwuZGlzYWJsZVRleHRTZWxlY3Rpb25gXSgjZG9tdXRpbC1kaXNhYmxldGV4dHNlbGVjdGlvbikuXHJcbiAgdmFyIGRpc2FibGVUZXh0U2VsZWN0aW9uO1xyXG4gIHZhciBlbmFibGVUZXh0U2VsZWN0aW9uO1xyXG4gIHZhciBfdXNlclNlbGVjdDtcclxuICBpZiAoJ29uc2VsZWN0c3RhcnQnIGluIGRvY3VtZW50KSB7XHJcbiAgXHRkaXNhYmxlVGV4dFNlbGVjdGlvbiA9IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0b24od2luZG93LCAnc2VsZWN0c3RhcnQnLCBwcmV2ZW50RGVmYXVsdCk7XHJcbiAgXHR9O1xyXG4gIFx0ZW5hYmxlVGV4dFNlbGVjdGlvbiA9IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0b2ZmKHdpbmRvdywgJ3NlbGVjdHN0YXJ0JywgcHJldmVudERlZmF1bHQpO1xyXG4gIFx0fTtcclxuICB9IGVsc2Uge1xyXG4gIFx0dmFyIHVzZXJTZWxlY3RQcm9wZXJ0eSA9IHRlc3RQcm9wKFxyXG4gIFx0XHRbJ3VzZXJTZWxlY3QnLCAnV2Via2l0VXNlclNlbGVjdCcsICdPVXNlclNlbGVjdCcsICdNb3pVc2VyU2VsZWN0JywgJ21zVXNlclNlbGVjdCddKTtcclxuXHJcbiAgXHRkaXNhYmxlVGV4dFNlbGVjdGlvbiA9IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKHVzZXJTZWxlY3RQcm9wZXJ0eSkge1xyXG4gIFx0XHRcdHZhciBzdHlsZSA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZTtcclxuICBcdFx0XHRfdXNlclNlbGVjdCA9IHN0eWxlW3VzZXJTZWxlY3RQcm9wZXJ0eV07XHJcbiAgXHRcdFx0c3R5bGVbdXNlclNlbGVjdFByb3BlcnR5XSA9ICdub25lJztcclxuICBcdFx0fVxyXG4gIFx0fTtcclxuICBcdGVuYWJsZVRleHRTZWxlY3Rpb24gPSBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICh1c2VyU2VsZWN0UHJvcGVydHkpIHtcclxuICBcdFx0XHRkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGVbdXNlclNlbGVjdFByb3BlcnR5XSA9IF91c2VyU2VsZWN0O1xyXG4gIFx0XHRcdF91c2VyU2VsZWN0ID0gdW5kZWZpbmVkO1xyXG4gIFx0XHR9XHJcbiAgXHR9O1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGRpc2FibGVJbWFnZURyYWcoKVxyXG4gIC8vIEFzIFtgTC5Eb21VdGlsLmRpc2FibGVUZXh0U2VsZWN0aW9uYF0oI2RvbXV0aWwtZGlzYWJsZXRleHRzZWxlY3Rpb24pLCBidXRcclxuICAvLyBmb3IgYGRyYWdzdGFydGAgRE9NIGV2ZW50cywgdXN1YWxseSBnZW5lcmF0ZWQgd2hlbiB0aGUgdXNlciBkcmFncyBhbiBpbWFnZS5cclxuICBmdW5jdGlvbiBkaXNhYmxlSW1hZ2VEcmFnKCkge1xyXG4gIFx0b24od2luZG93LCAnZHJhZ3N0YXJ0JywgcHJldmVudERlZmF1bHQpO1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGVuYWJsZUltYWdlRHJhZygpXHJcbiAgLy8gQ2FuY2VscyB0aGUgZWZmZWN0cyBvZiBhIHByZXZpb3VzIFtgTC5Eb21VdGlsLmRpc2FibGVJbWFnZURyYWdgXSgjZG9tdXRpbC1kaXNhYmxldGV4dHNlbGVjdGlvbikuXHJcbiAgZnVuY3Rpb24gZW5hYmxlSW1hZ2VEcmFnKCkge1xyXG4gIFx0b2ZmKHdpbmRvdywgJ2RyYWdzdGFydCcsIHByZXZlbnREZWZhdWx0KTtcclxuICB9XHJcblxyXG4gIHZhciBfb3V0bGluZUVsZW1lbnQsIF9vdXRsaW5lU3R5bGU7XHJcbiAgLy8gQGZ1bmN0aW9uIHByZXZlbnRPdXRsaW5lKGVsOiBIVE1MRWxlbWVudClcclxuICAvLyBNYWtlcyB0aGUgW291dGxpbmVdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0NTUy9vdXRsaW5lKVxyXG4gIC8vIG9mIHRoZSBlbGVtZW50IGBlbGAgaW52aXNpYmxlLiBVc2VkIGludGVybmFsbHkgYnkgTGVhZmxldCB0byBwcmV2ZW50XHJcbiAgLy8gZm9jdXNhYmxlIGVsZW1lbnRzIGZyb20gZGlzcGxheWluZyBhbiBvdXRsaW5lIHdoZW4gdGhlIHVzZXIgcGVyZm9ybXMgYVxyXG4gIC8vIGRyYWcgaW50ZXJhY3Rpb24gb24gdGhlbS5cclxuICBmdW5jdGlvbiBwcmV2ZW50T3V0bGluZShlbGVtZW50KSB7XHJcbiAgXHR3aGlsZSAoZWxlbWVudC50YWJJbmRleCA9PT0gLTEpIHtcclxuICBcdFx0ZWxlbWVudCA9IGVsZW1lbnQucGFyZW50Tm9kZTtcclxuICBcdH1cclxuICBcdGlmICghZWxlbWVudC5zdHlsZSkgeyByZXR1cm47IH1cclxuICBcdHJlc3RvcmVPdXRsaW5lKCk7XHJcbiAgXHRfb3V0bGluZUVsZW1lbnQgPSBlbGVtZW50O1xyXG4gIFx0X291dGxpbmVTdHlsZSA9IGVsZW1lbnQuc3R5bGUub3V0bGluZVN0eWxlO1xyXG4gIFx0ZWxlbWVudC5zdHlsZS5vdXRsaW5lU3R5bGUgPSAnbm9uZSc7XHJcbiAgXHRvbih3aW5kb3csICdrZXlkb3duJywgcmVzdG9yZU91dGxpbmUpO1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIHJlc3RvcmVPdXRsaW5lKClcclxuICAvLyBDYW5jZWxzIHRoZSBlZmZlY3RzIG9mIGEgcHJldmlvdXMgW2BMLkRvbVV0aWwucHJldmVudE91dGxpbmVgXSgpLlxyXG4gIGZ1bmN0aW9uIHJlc3RvcmVPdXRsaW5lKCkge1xyXG4gIFx0aWYgKCFfb3V0bGluZUVsZW1lbnQpIHsgcmV0dXJuOyB9XHJcbiAgXHRfb3V0bGluZUVsZW1lbnQuc3R5bGUub3V0bGluZVN0eWxlID0gX291dGxpbmVTdHlsZTtcclxuICBcdF9vdXRsaW5lRWxlbWVudCA9IHVuZGVmaW5lZDtcclxuICBcdF9vdXRsaW5lU3R5bGUgPSB1bmRlZmluZWQ7XHJcbiAgXHRvZmYod2luZG93LCAna2V5ZG93bicsIHJlc3RvcmVPdXRsaW5lKTtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBnZXRTaXplZFBhcmVudE5vZGUoZWw6IEhUTUxFbGVtZW50KTogSFRNTEVsZW1lbnRcclxuICAvLyBGaW5kcyB0aGUgY2xvc2VzdCBwYXJlbnQgbm9kZSB3aGljaCBzaXplICh3aWR0aCBhbmQgaGVpZ2h0KSBpcyBub3QgbnVsbC5cclxuICBmdW5jdGlvbiBnZXRTaXplZFBhcmVudE5vZGUoZWxlbWVudCkge1xyXG4gIFx0ZG8ge1xyXG4gIFx0XHRlbGVtZW50ID0gZWxlbWVudC5wYXJlbnROb2RlO1xyXG4gIFx0fSB3aGlsZSAoKCFlbGVtZW50Lm9mZnNldFdpZHRoIHx8ICFlbGVtZW50Lm9mZnNldEhlaWdodCkgJiYgZWxlbWVudCAhPT0gZG9jdW1lbnQuYm9keSk7XHJcbiAgXHRyZXR1cm4gZWxlbWVudDtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBnZXRTY2FsZShlbDogSFRNTEVsZW1lbnQpOiBPYmplY3RcclxuICAvLyBDb21wdXRlcyB0aGUgQ1NTIHNjYWxlIGN1cnJlbnRseSBhcHBsaWVkIG9uIHRoZSBlbGVtZW50LlxyXG4gIC8vIFJldHVybnMgYW4gb2JqZWN0IHdpdGggYHhgIGFuZCBgeWAgbWVtYmVycyBhcyBob3Jpem9udGFsIGFuZCB2ZXJ0aWNhbCBzY2FsZXMgcmVzcGVjdGl2ZWx5LFxyXG4gIC8vIGFuZCBgYm91bmRpbmdDbGllbnRSZWN0YCBhcyB0aGUgcmVzdWx0IG9mIFtgZ2V0Qm91bmRpbmdDbGllbnRSZWN0KClgXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvRWxlbWVudC9nZXRCb3VuZGluZ0NsaWVudFJlY3QpLlxyXG4gIGZ1bmN0aW9uIGdldFNjYWxlKGVsZW1lbnQpIHtcclxuICBcdHZhciByZWN0ID0gZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTsgLy8gUmVhZC1vbmx5IGluIG9sZCBicm93c2Vycy5cclxuXHJcbiAgXHRyZXR1cm4ge1xyXG4gIFx0XHR4OiByZWN0LndpZHRoIC8gZWxlbWVudC5vZmZzZXRXaWR0aCB8fCAxLFxyXG4gIFx0XHR5OiByZWN0LmhlaWdodCAvIGVsZW1lbnQub2Zmc2V0SGVpZ2h0IHx8IDEsXHJcbiAgXHRcdGJvdW5kaW5nQ2xpZW50UmVjdDogcmVjdFxyXG4gIFx0fTtcclxuICB9XG5cbiAgdmFyIERvbVV0aWwgPSB7XG4gICAgX19wcm90b19fOiBudWxsLFxuICAgIFRSQU5TRk9STTogVFJBTlNGT1JNLFxuICAgIFRSQU5TSVRJT046IFRSQU5TSVRJT04sXG4gICAgVFJBTlNJVElPTl9FTkQ6IFRSQU5TSVRJT05fRU5ELFxuICAgIGdldDogZ2V0LFxuICAgIGdldFN0eWxlOiBnZXRTdHlsZSxcbiAgICBjcmVhdGU6IGNyZWF0ZSQxLFxuICAgIHJlbW92ZTogcmVtb3ZlLFxuICAgIGVtcHR5OiBlbXB0eSxcbiAgICB0b0Zyb250OiB0b0Zyb250LFxuICAgIHRvQmFjazogdG9CYWNrLFxuICAgIGhhc0NsYXNzOiBoYXNDbGFzcyxcbiAgICBhZGRDbGFzczogYWRkQ2xhc3MsXG4gICAgcmVtb3ZlQ2xhc3M6IHJlbW92ZUNsYXNzLFxuICAgIHNldENsYXNzOiBzZXRDbGFzcyxcbiAgICBnZXRDbGFzczogZ2V0Q2xhc3MsXG4gICAgc2V0T3BhY2l0eTogc2V0T3BhY2l0eSxcbiAgICB0ZXN0UHJvcDogdGVzdFByb3AsXG4gICAgc2V0VHJhbnNmb3JtOiBzZXRUcmFuc2Zvcm0sXG4gICAgc2V0UG9zaXRpb246IHNldFBvc2l0aW9uLFxuICAgIGdldFBvc2l0aW9uOiBnZXRQb3NpdGlvbixcbiAgICBnZXQgZGlzYWJsZVRleHRTZWxlY3Rpb24gKCkgeyByZXR1cm4gZGlzYWJsZVRleHRTZWxlY3Rpb247IH0sXG4gICAgZ2V0IGVuYWJsZVRleHRTZWxlY3Rpb24gKCkgeyByZXR1cm4gZW5hYmxlVGV4dFNlbGVjdGlvbjsgfSxcbiAgICBkaXNhYmxlSW1hZ2VEcmFnOiBkaXNhYmxlSW1hZ2VEcmFnLFxuICAgIGVuYWJsZUltYWdlRHJhZzogZW5hYmxlSW1hZ2VEcmFnLFxuICAgIHByZXZlbnRPdXRsaW5lOiBwcmV2ZW50T3V0bGluZSxcbiAgICByZXN0b3JlT3V0bGluZTogcmVzdG9yZU91dGxpbmUsXG4gICAgZ2V0U2l6ZWRQYXJlbnROb2RlOiBnZXRTaXplZFBhcmVudE5vZGUsXG4gICAgZ2V0U2NhbGU6IGdldFNjYWxlXG4gIH07XG5cbiAgLypcclxuICAgKiBAbmFtZXNwYWNlIERvbUV2ZW50XHJcbiAgICogVXRpbGl0eSBmdW5jdGlvbnMgdG8gd29yayB3aXRoIHRoZSBbRE9NIGV2ZW50c10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQVBJL0V2ZW50KSwgdXNlZCBieSBMZWFmbGV0IGludGVybmFsbHkuXHJcbiAgICovXHJcblxyXG4gIC8vIEluc3BpcmVkIGJ5IEpvaG4gUmVzaWcsIERlYW4gRWR3YXJkcyBhbmQgWVVJIGFkZEV2ZW50IGltcGxlbWVudGF0aW9ucy5cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIG9uKGVsOiBIVE1MRWxlbWVudCwgdHlwZXM6IFN0cmluZywgZm46IEZ1bmN0aW9uLCBjb250ZXh0PzogT2JqZWN0KTogdGhpc1xyXG4gIC8vIEFkZHMgYSBsaXN0ZW5lciBmdW5jdGlvbiAoYGZuYCkgdG8gYSBwYXJ0aWN1bGFyIERPTSBldmVudCB0eXBlIG9mIHRoZVxyXG4gIC8vIGVsZW1lbnQgYGVsYC4gWW91IGNhbiBvcHRpb25hbGx5IHNwZWNpZnkgdGhlIGNvbnRleHQgb2YgdGhlIGxpc3RlbmVyXHJcbiAgLy8gKG9iamVjdCB0aGUgYHRoaXNgIGtleXdvcmQgd2lsbCBwb2ludCB0bykuIFlvdSBjYW4gYWxzbyBwYXNzIHNldmVyYWxcclxuICAvLyBzcGFjZS1zZXBhcmF0ZWQgdHlwZXMgKGUuZy4gYCdjbGljayBkYmxjbGljaydgKS5cclxuXHJcbiAgLy8gQGFsdGVybmF0aXZlXHJcbiAgLy8gQGZ1bmN0aW9uIG9uKGVsOiBIVE1MRWxlbWVudCwgZXZlbnRNYXA6IE9iamVjdCwgY29udGV4dD86IE9iamVjdCk6IHRoaXNcclxuICAvLyBBZGRzIGEgc2V0IG9mIHR5cGUvbGlzdGVuZXIgcGFpcnMsIGUuZy4gYHtjbGljazogb25DbGljaywgbW91c2Vtb3ZlOiBvbk1vdXNlTW92ZX1gXHJcbiAgZnVuY3Rpb24gb24ob2JqLCB0eXBlcywgZm4sIGNvbnRleHQpIHtcclxuXHJcbiAgXHRpZiAodHlwZXMgJiYgdHlwZW9mIHR5cGVzID09PSAnb2JqZWN0Jykge1xyXG4gIFx0XHRmb3IgKHZhciB0eXBlIGluIHR5cGVzKSB7XHJcbiAgXHRcdFx0YWRkT25lKG9iaiwgdHlwZSwgdHlwZXNbdHlwZV0sIGZuKTtcclxuICBcdFx0fVxyXG4gIFx0fSBlbHNlIHtcclxuICBcdFx0dHlwZXMgPSBzcGxpdFdvcmRzKHR5cGVzKTtcclxuXHJcbiAgXHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSB0eXBlcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gIFx0XHRcdGFkZE9uZShvYmosIHR5cGVzW2ldLCBmbiwgY29udGV4dCk7XHJcbiAgXHRcdH1cclxuICBcdH1cclxuXHJcbiAgXHRyZXR1cm4gdGhpcztcclxuICB9XHJcblxyXG4gIHZhciBldmVudHNLZXkgPSAnX2xlYWZsZXRfZXZlbnRzJztcclxuXHJcbiAgLy8gQGZ1bmN0aW9uIG9mZihlbDogSFRNTEVsZW1lbnQsIHR5cGVzOiBTdHJpbmcsIGZuOiBGdW5jdGlvbiwgY29udGV4dD86IE9iamVjdCk6IHRoaXNcclxuICAvLyBSZW1vdmVzIGEgcHJldmlvdXNseSBhZGRlZCBsaXN0ZW5lciBmdW5jdGlvbi5cclxuICAvLyBOb3RlIHRoYXQgaWYgeW91IHBhc3NlZCBhIGN1c3RvbSBjb250ZXh0IHRvIG9uLCB5b3UgbXVzdCBwYXNzIHRoZSBzYW1lXHJcbiAgLy8gY29udGV4dCB0byBgb2ZmYCBpbiBvcmRlciB0byByZW1vdmUgdGhlIGxpc3RlbmVyLlxyXG5cclxuICAvLyBAYWx0ZXJuYXRpdmVcclxuICAvLyBAZnVuY3Rpb24gb2ZmKGVsOiBIVE1MRWxlbWVudCwgZXZlbnRNYXA6IE9iamVjdCwgY29udGV4dD86IE9iamVjdCk6IHRoaXNcclxuICAvLyBSZW1vdmVzIGEgc2V0IG9mIHR5cGUvbGlzdGVuZXIgcGFpcnMsIGUuZy4gYHtjbGljazogb25DbGljaywgbW91c2Vtb3ZlOiBvbk1vdXNlTW92ZX1gXHJcblxyXG4gIC8vIEBhbHRlcm5hdGl2ZVxyXG4gIC8vIEBmdW5jdGlvbiBvZmYoZWw6IEhUTUxFbGVtZW50LCB0eXBlczogU3RyaW5nKTogdGhpc1xyXG4gIC8vIFJlbW92ZXMgYWxsIHByZXZpb3VzbHkgYWRkZWQgbGlzdGVuZXJzIG9mIGdpdmVuIHR5cGVzLlxyXG5cclxuICAvLyBAYWx0ZXJuYXRpdmVcclxuICAvLyBAZnVuY3Rpb24gb2ZmKGVsOiBIVE1MRWxlbWVudCk6IHRoaXNcclxuICAvLyBSZW1vdmVzIGFsbCBwcmV2aW91c2x5IGFkZGVkIGxpc3RlbmVycyBmcm9tIGdpdmVuIEhUTUxFbGVtZW50XHJcbiAgZnVuY3Rpb24gb2ZmKG9iaiwgdHlwZXMsIGZuLCBjb250ZXh0KSB7XHJcblxyXG4gIFx0aWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcclxuICBcdFx0YmF0Y2hSZW1vdmUob2JqKTtcclxuICBcdFx0ZGVsZXRlIG9ialtldmVudHNLZXldO1xyXG5cclxuICBcdH0gZWxzZSBpZiAodHlwZXMgJiYgdHlwZW9mIHR5cGVzID09PSAnb2JqZWN0Jykge1xyXG4gIFx0XHRmb3IgKHZhciB0eXBlIGluIHR5cGVzKSB7XHJcbiAgXHRcdFx0cmVtb3ZlT25lKG9iaiwgdHlwZSwgdHlwZXNbdHlwZV0sIGZuKTtcclxuICBcdFx0fVxyXG5cclxuICBcdH0gZWxzZSB7XHJcbiAgXHRcdHR5cGVzID0gc3BsaXRXb3Jkcyh0eXBlcyk7XHJcblxyXG4gIFx0XHRpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMikge1xyXG4gIFx0XHRcdGJhdGNoUmVtb3ZlKG9iaiwgZnVuY3Rpb24gKHR5cGUpIHtcclxuICBcdFx0XHRcdHJldHVybiBpbmRleE9mKHR5cGVzLCB0eXBlKSAhPT0gLTE7XHJcbiAgXHRcdFx0fSk7XHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IHR5cGVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdFx0XHRyZW1vdmVPbmUob2JqLCB0eXBlc1tpXSwgZm4sIGNvbnRleHQpO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG4gIFx0fVxyXG5cclxuICBcdHJldHVybiB0aGlzO1xyXG4gIH1cclxuXHJcbiAgZnVuY3Rpb24gYmF0Y2hSZW1vdmUob2JqLCBmaWx0ZXJGbikge1xyXG4gIFx0Zm9yICh2YXIgaWQgaW4gb2JqW2V2ZW50c0tleV0pIHtcclxuICBcdFx0dmFyIHR5cGUgPSBpZC5zcGxpdCgvXFxkLylbMF07XHJcbiAgXHRcdGlmICghZmlsdGVyRm4gfHwgZmlsdGVyRm4odHlwZSkpIHtcclxuICBcdFx0XHRyZW1vdmVPbmUob2JqLCB0eXBlLCBudWxsLCBudWxsLCBpZCk7XHJcbiAgXHRcdH1cclxuICBcdH1cclxuICB9XHJcblxyXG4gIHZhciBtb3VzZVN1YnN0ID0ge1xyXG4gIFx0bW91c2VlbnRlcjogJ21vdXNlb3ZlcicsXHJcbiAgXHRtb3VzZWxlYXZlOiAnbW91c2VvdXQnLFxyXG4gIFx0d2hlZWw6ICEoJ29ud2hlZWwnIGluIHdpbmRvdykgJiYgJ21vdXNld2hlZWwnXHJcbiAgfTtcclxuXHJcbiAgZnVuY3Rpb24gYWRkT25lKG9iaiwgdHlwZSwgZm4sIGNvbnRleHQpIHtcclxuICBcdHZhciBpZCA9IHR5cGUgKyBzdGFtcChmbikgKyAoY29udGV4dCA/ICdfJyArIHN0YW1wKGNvbnRleHQpIDogJycpO1xyXG5cclxuICBcdGlmIChvYmpbZXZlbnRzS2V5XSAmJiBvYmpbZXZlbnRzS2V5XVtpZF0pIHsgcmV0dXJuIHRoaXM7IH1cclxuXHJcbiAgXHR2YXIgaGFuZGxlciA9IGZ1bmN0aW9uIChlKSB7XHJcbiAgXHRcdHJldHVybiBmbi5jYWxsKGNvbnRleHQgfHwgb2JqLCBlIHx8IHdpbmRvdy5ldmVudCk7XHJcbiAgXHR9O1xyXG5cclxuICBcdHZhciBvcmlnaW5hbEhhbmRsZXIgPSBoYW5kbGVyO1xyXG5cclxuICBcdGlmICghQnJvd3Nlci50b3VjaE5hdGl2ZSAmJiBCcm93c2VyLnBvaW50ZXIgJiYgdHlwZS5pbmRleE9mKCd0b3VjaCcpID09PSAwKSB7XHJcbiAgXHRcdC8vIE5lZWRzIERvbUV2ZW50LlBvaW50ZXIuanNcclxuICBcdFx0aGFuZGxlciA9IGFkZFBvaW50ZXJMaXN0ZW5lcihvYmosIHR5cGUsIGhhbmRsZXIpO1xyXG5cclxuICBcdH0gZWxzZSBpZiAoQnJvd3Nlci50b3VjaCAmJiAodHlwZSA9PT0gJ2RibGNsaWNrJykpIHtcclxuICBcdFx0aGFuZGxlciA9IGFkZERvdWJsZVRhcExpc3RlbmVyKG9iaiwgaGFuZGxlcik7XHJcblxyXG4gIFx0fSBlbHNlIGlmICgnYWRkRXZlbnRMaXN0ZW5lcicgaW4gb2JqKSB7XHJcblxyXG4gIFx0XHRpZiAodHlwZSA9PT0gJ3RvdWNoc3RhcnQnIHx8IHR5cGUgPT09ICd0b3VjaG1vdmUnIHx8IHR5cGUgPT09ICd3aGVlbCcgfHwgIHR5cGUgPT09ICdtb3VzZXdoZWVsJykge1xyXG4gIFx0XHRcdG9iai5hZGRFdmVudExpc3RlbmVyKG1vdXNlU3Vic3RbdHlwZV0gfHwgdHlwZSwgaGFuZGxlciwgQnJvd3Nlci5wYXNzaXZlRXZlbnRzID8ge3Bhc3NpdmU6IGZhbHNlfSA6IGZhbHNlKTtcclxuXHJcbiAgXHRcdH0gZWxzZSBpZiAodHlwZSA9PT0gJ21vdXNlZW50ZXInIHx8IHR5cGUgPT09ICdtb3VzZWxlYXZlJykge1xyXG4gIFx0XHRcdGhhbmRsZXIgPSBmdW5jdGlvbiAoZSkge1xyXG4gIFx0XHRcdFx0ZSA9IGUgfHwgd2luZG93LmV2ZW50O1xyXG4gIFx0XHRcdFx0aWYgKGlzRXh0ZXJuYWxUYXJnZXQob2JqLCBlKSkge1xyXG4gIFx0XHRcdFx0XHRvcmlnaW5hbEhhbmRsZXIoZSk7XHJcbiAgXHRcdFx0XHR9XHJcbiAgXHRcdFx0fTtcclxuICBcdFx0XHRvYmouYWRkRXZlbnRMaXN0ZW5lcihtb3VzZVN1YnN0W3R5cGVdLCBoYW5kbGVyLCBmYWxzZSk7XHJcblxyXG4gIFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdG9iai5hZGRFdmVudExpc3RlbmVyKHR5cGUsIG9yaWdpbmFsSGFuZGxlciwgZmFsc2UpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0fSBlbHNlIHtcclxuICBcdFx0b2JqLmF0dGFjaEV2ZW50KCdvbicgKyB0eXBlLCBoYW5kbGVyKTtcclxuICBcdH1cclxuXHJcbiAgXHRvYmpbZXZlbnRzS2V5XSA9IG9ialtldmVudHNLZXldIHx8IHt9O1xyXG4gIFx0b2JqW2V2ZW50c0tleV1baWRdID0gaGFuZGxlcjtcclxuICB9XHJcblxyXG4gIGZ1bmN0aW9uIHJlbW92ZU9uZShvYmosIHR5cGUsIGZuLCBjb250ZXh0LCBpZCkge1xyXG4gIFx0aWQgPSBpZCB8fCB0eXBlICsgc3RhbXAoZm4pICsgKGNvbnRleHQgPyAnXycgKyBzdGFtcChjb250ZXh0KSA6ICcnKTtcclxuICBcdHZhciBoYW5kbGVyID0gb2JqW2V2ZW50c0tleV0gJiYgb2JqW2V2ZW50c0tleV1baWRdO1xyXG5cclxuICBcdGlmICghaGFuZGxlcikgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuICBcdGlmICghQnJvd3Nlci50b3VjaE5hdGl2ZSAmJiBCcm93c2VyLnBvaW50ZXIgJiYgdHlwZS5pbmRleE9mKCd0b3VjaCcpID09PSAwKSB7XHJcbiAgXHRcdHJlbW92ZVBvaW50ZXJMaXN0ZW5lcihvYmosIHR5cGUsIGhhbmRsZXIpO1xyXG5cclxuICBcdH0gZWxzZSBpZiAoQnJvd3Nlci50b3VjaCAmJiAodHlwZSA9PT0gJ2RibGNsaWNrJykpIHtcclxuICBcdFx0cmVtb3ZlRG91YmxlVGFwTGlzdGVuZXIob2JqLCBoYW5kbGVyKTtcclxuXHJcbiAgXHR9IGVsc2UgaWYgKCdyZW1vdmVFdmVudExpc3RlbmVyJyBpbiBvYmopIHtcclxuXHJcbiAgXHRcdG9iai5yZW1vdmVFdmVudExpc3RlbmVyKG1vdXNlU3Vic3RbdHlwZV0gfHwgdHlwZSwgaGFuZGxlciwgZmFsc2UpO1xyXG5cclxuICBcdH0gZWxzZSB7XHJcbiAgXHRcdG9iai5kZXRhY2hFdmVudCgnb24nICsgdHlwZSwgaGFuZGxlcik7XHJcbiAgXHR9XHJcblxyXG4gIFx0b2JqW2V2ZW50c0tleV1baWRdID0gbnVsbDtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBzdG9wUHJvcGFnYXRpb24oZXY6IERPTUV2ZW50KTogdGhpc1xyXG4gIC8vIFN0b3AgdGhlIGdpdmVuIGV2ZW50IGZyb20gcHJvcGFnYXRpb24gdG8gcGFyZW50IGVsZW1lbnRzLiBVc2VkIGluc2lkZSB0aGUgbGlzdGVuZXIgZnVuY3Rpb25zOlxyXG4gIC8vIGBgYGpzXHJcbiAgLy8gTC5Eb21FdmVudC5vbihkaXYsICdjbGljaycsIGZ1bmN0aW9uIChldikge1xyXG4gIC8vIFx0TC5Eb21FdmVudC5zdG9wUHJvcGFnYXRpb24oZXYpO1xyXG4gIC8vIH0pO1xyXG4gIC8vIGBgYFxyXG4gIGZ1bmN0aW9uIHN0b3BQcm9wYWdhdGlvbihlKSB7XHJcblxyXG4gIFx0aWYgKGUuc3RvcFByb3BhZ2F0aW9uKSB7XHJcbiAgXHRcdGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgXHR9IGVsc2UgaWYgKGUub3JpZ2luYWxFdmVudCkgeyAgLy8gSW4gY2FzZSBvZiBMZWFmbGV0IGV2ZW50LlxyXG4gIFx0XHRlLm9yaWdpbmFsRXZlbnQuX3N0b3BwZWQgPSB0cnVlO1xyXG4gIFx0fSBlbHNlIHtcclxuICBcdFx0ZS5jYW5jZWxCdWJibGUgPSB0cnVlO1xyXG4gIFx0fVxyXG5cclxuICBcdHJldHVybiB0aGlzO1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGRpc2FibGVTY3JvbGxQcm9wYWdhdGlvbihlbDogSFRNTEVsZW1lbnQpOiB0aGlzXHJcbiAgLy8gQWRkcyBgc3RvcFByb3BhZ2F0aW9uYCB0byB0aGUgZWxlbWVudCdzIGAnd2hlZWwnYCBldmVudHMgKHBsdXMgYnJvd3NlciB2YXJpYW50cykuXHJcbiAgZnVuY3Rpb24gZGlzYWJsZVNjcm9sbFByb3BhZ2F0aW9uKGVsKSB7XHJcbiAgXHRhZGRPbmUoZWwsICd3aGVlbCcsIHN0b3BQcm9wYWdhdGlvbik7XHJcbiAgXHRyZXR1cm4gdGhpcztcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBkaXNhYmxlQ2xpY2tQcm9wYWdhdGlvbihlbDogSFRNTEVsZW1lbnQpOiB0aGlzXHJcbiAgLy8gQWRkcyBgc3RvcFByb3BhZ2F0aW9uYCB0byB0aGUgZWxlbWVudCdzIGAnY2xpY2snYCwgYCdkYmxjbGljaydgLCBgJ2NvbnRleHRtZW51J2AsXHJcbiAgLy8gYCdtb3VzZWRvd24nYCBhbmQgYCd0b3VjaHN0YXJ0J2AgZXZlbnRzIChwbHVzIGJyb3dzZXIgdmFyaWFudHMpLlxyXG4gIGZ1bmN0aW9uIGRpc2FibGVDbGlja1Byb3BhZ2F0aW9uKGVsKSB7XHJcbiAgXHRvbihlbCwgJ21vdXNlZG93biB0b3VjaHN0YXJ0IGRibGNsaWNrIGNvbnRleHRtZW51Jywgc3RvcFByb3BhZ2F0aW9uKTtcclxuICBcdGVsWydfbGVhZmxldF9kaXNhYmxlX2NsaWNrJ10gPSB0cnVlO1xyXG4gIFx0cmV0dXJuIHRoaXM7XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gcHJldmVudERlZmF1bHQoZXY6IERPTUV2ZW50KTogdGhpc1xyXG4gIC8vIFByZXZlbnRzIHRoZSBkZWZhdWx0IGFjdGlvbiBvZiB0aGUgRE9NIEV2ZW50IGBldmAgZnJvbSBoYXBwZW5pbmcgKHN1Y2ggYXNcclxuICAvLyBmb2xsb3dpbmcgYSBsaW5rIGluIHRoZSBocmVmIG9mIHRoZSBhIGVsZW1lbnQsIG9yIGRvaW5nIGEgUE9TVCByZXF1ZXN0XHJcbiAgLy8gd2l0aCBwYWdlIHJlbG9hZCB3aGVuIGEgYDxmb3JtPmAgaXMgc3VibWl0dGVkKS5cclxuICAvLyBVc2UgaXQgaW5zaWRlIGxpc3RlbmVyIGZ1bmN0aW9ucy5cclxuICBmdW5jdGlvbiBwcmV2ZW50RGVmYXVsdChlKSB7XHJcbiAgXHRpZiAoZS5wcmV2ZW50RGVmYXVsdCkge1xyXG4gIFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgXHR9IGVsc2Uge1xyXG4gIFx0XHRlLnJldHVyblZhbHVlID0gZmFsc2U7XHJcbiAgXHR9XHJcbiAgXHRyZXR1cm4gdGhpcztcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBzdG9wKGV2OiBET01FdmVudCk6IHRoaXNcclxuICAvLyBEb2VzIGBzdG9wUHJvcGFnYXRpb25gIGFuZCBgcHJldmVudERlZmF1bHRgIGF0IHRoZSBzYW1lIHRpbWUuXHJcbiAgZnVuY3Rpb24gc3RvcChlKSB7XHJcbiAgXHRwcmV2ZW50RGVmYXVsdChlKTtcclxuICBcdHN0b3BQcm9wYWdhdGlvbihlKTtcclxuICBcdHJldHVybiB0aGlzO1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGdldFByb3BhZ2F0aW9uUGF0aChldjogRE9NRXZlbnQpOiBBcnJheVxyXG4gIC8vIENvbXBhdGliaWxpdHkgcG9seWZpbGwgZm9yIFtgRXZlbnQuY29tcG9zZWRQYXRoKClgXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvRXZlbnQvY29tcG9zZWRQYXRoKS5cclxuICAvLyBSZXR1cm5zIGFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIGBIVE1MRWxlbWVudGBzIHRoYXQgdGhlIGdpdmVuIERPTSBldmVudFxyXG4gIC8vIHNob3VsZCBwcm9wYWdhdGUgdG8gKGlmIG5vdCBzdG9wcGVkKS5cclxuICBmdW5jdGlvbiBnZXRQcm9wYWdhdGlvblBhdGgoZXYpIHtcclxuICBcdGlmIChldi5jb21wb3NlZFBhdGgpIHtcclxuICBcdFx0cmV0dXJuIGV2LmNvbXBvc2VkUGF0aCgpO1xyXG4gIFx0fVxyXG5cclxuICBcdHZhciBwYXRoID0gW107XHJcbiAgXHR2YXIgZWwgPSBldi50YXJnZXQ7XHJcblxyXG4gIFx0d2hpbGUgKGVsKSB7XHJcbiAgXHRcdHBhdGgucHVzaChlbCk7XHJcbiAgXHRcdGVsID0gZWwucGFyZW50Tm9kZTtcclxuICBcdH1cclxuICBcdHJldHVybiBwYXRoO1xyXG4gIH1cclxuXHJcblxyXG4gIC8vIEBmdW5jdGlvbiBnZXRNb3VzZVBvc2l0aW9uKGV2OiBET01FdmVudCwgY29udGFpbmVyPzogSFRNTEVsZW1lbnQpOiBQb2ludFxyXG4gIC8vIEdldHMgbm9ybWFsaXplZCBtb3VzZSBwb3NpdGlvbiBmcm9tIGEgRE9NIGV2ZW50IHJlbGF0aXZlIHRvIHRoZVxyXG4gIC8vIGBjb250YWluZXJgIChib3JkZXIgZXhjbHVkZWQpIG9yIHRvIHRoZSB3aG9sZSBwYWdlIGlmIG5vdCBzcGVjaWZpZWQuXHJcbiAgZnVuY3Rpb24gZ2V0TW91c2VQb3NpdGlvbihlLCBjb250YWluZXIpIHtcclxuICBcdGlmICghY29udGFpbmVyKSB7XHJcbiAgXHRcdHJldHVybiBuZXcgUG9pbnQoZS5jbGllbnRYLCBlLmNsaWVudFkpO1xyXG4gIFx0fVxyXG5cclxuICBcdHZhciBzY2FsZSA9IGdldFNjYWxlKGNvbnRhaW5lciksXHJcbiAgXHQgICAgb2Zmc2V0ID0gc2NhbGUuYm91bmRpbmdDbGllbnRSZWN0OyAvLyBsZWZ0IGFuZCB0b3AgIHZhbHVlcyBhcmUgaW4gcGFnZSBzY2FsZSAobGlrZSB0aGUgZXZlbnQgY2xpZW50WC9ZKVxyXG5cclxuICBcdHJldHVybiBuZXcgUG9pbnQoXHJcbiAgXHRcdC8vIG9mZnNldC5sZWZ0L3RvcCB2YWx1ZXMgYXJlIGluIHBhZ2Ugc2NhbGUgKGxpa2UgY2xpZW50WC9ZKSxcclxuICBcdFx0Ly8gd2hlcmVhcyBjbGllbnRMZWZ0L1RvcCAoYm9yZGVyIHdpZHRoKSB2YWx1ZXMgYXJlIHRoZSBvcmlnaW5hbCB2YWx1ZXMgKGJlZm9yZSBDU1Mgc2NhbGUgYXBwbGllcykuXHJcbiAgXHRcdChlLmNsaWVudFggLSBvZmZzZXQubGVmdCkgLyBzY2FsZS54IC0gY29udGFpbmVyLmNsaWVudExlZnQsXHJcbiAgXHRcdChlLmNsaWVudFkgLSBvZmZzZXQudG9wKSAvIHNjYWxlLnkgLSBjb250YWluZXIuY2xpZW50VG9wXHJcbiAgXHQpO1xyXG4gIH1cclxuXHJcblxyXG4gIC8vICBleGNlcHQgLCBTYWZhcmkgYW5kXHJcbiAgLy8gV2UgbmVlZCBkb3VibGUgdGhlIHNjcm9sbCBwaXhlbHMgKHNlZSAjNzQwMyBhbmQgIzQ1MzgpIGZvciBhbGwgQnJvd3NlcnNcclxuICAvLyBleGNlcHQgT1NYIChNYWMpIC0+IDN4LCBDaHJvbWUgcnVubmluZyBvbiBMaW51eCAxeFxyXG5cclxuICB2YXIgd2hlZWxQeEZhY3RvciA9XHJcbiAgXHQoQnJvd3Nlci5saW51eCAmJiBCcm93c2VyLmNocm9tZSkgPyB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyA6XHJcbiAgXHRCcm93c2VyLm1hYyA/IHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvICogMyA6XHJcbiAgXHR3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyA+IDAgPyAyICogd2luZG93LmRldmljZVBpeGVsUmF0aW8gOiAxO1xyXG4gIC8vIEBmdW5jdGlvbiBnZXRXaGVlbERlbHRhKGV2OiBET01FdmVudCk6IE51bWJlclxyXG4gIC8vIEdldHMgbm9ybWFsaXplZCB3aGVlbCBkZWx0YSBmcm9tIGEgd2hlZWwgRE9NIGV2ZW50LCBpbiB2ZXJ0aWNhbFxyXG4gIC8vIHBpeGVscyBzY3JvbGxlZCAobmVnYXRpdmUgaWYgc2Nyb2xsaW5nIGRvd24pLlxyXG4gIC8vIEV2ZW50cyBmcm9tIHBvaW50aW5nIGRldmljZXMgd2l0aG91dCBwcmVjaXNlIHNjcm9sbGluZyBhcmUgbWFwcGVkIHRvXHJcbiAgLy8gYSBiZXN0IGd1ZXNzIG9mIDYwIHBpeGVscy5cclxuICBmdW5jdGlvbiBnZXRXaGVlbERlbHRhKGUpIHtcclxuICBcdHJldHVybiAoQnJvd3Nlci5lZGdlKSA/IGUud2hlZWxEZWx0YVkgLyAyIDogLy8gRG9uJ3QgdHJ1c3Qgd2luZG93LWdlb21ldHJ5LWJhc2VkIGRlbHRhXHJcbiAgXHQgICAgICAgKGUuZGVsdGFZICYmIGUuZGVsdGFNb2RlID09PSAwKSA/IC1lLmRlbHRhWSAvIHdoZWVsUHhGYWN0b3IgOiAvLyBQaXhlbHNcclxuICBcdCAgICAgICAoZS5kZWx0YVkgJiYgZS5kZWx0YU1vZGUgPT09IDEpID8gLWUuZGVsdGFZICogMjAgOiAvLyBMaW5lc1xyXG4gIFx0ICAgICAgIChlLmRlbHRhWSAmJiBlLmRlbHRhTW9kZSA9PT0gMikgPyAtZS5kZWx0YVkgKiA2MCA6IC8vIFBhZ2VzXHJcbiAgXHQgICAgICAgKGUuZGVsdGFYIHx8IGUuZGVsdGFaKSA/IDAgOlx0Ly8gU2tpcCBob3Jpem9udGFsL2RlcHRoIHdoZWVsIGV2ZW50c1xyXG4gIFx0ICAgICAgIGUud2hlZWxEZWx0YSA/IChlLndoZWVsRGVsdGFZIHx8IGUud2hlZWxEZWx0YSkgLyAyIDogLy8gTGVnYWN5IElFIHBpeGVsc1xyXG4gIFx0ICAgICAgIChlLmRldGFpbCAmJiBNYXRoLmFicyhlLmRldGFpbCkgPCAzMjc2NSkgPyAtZS5kZXRhaWwgKiAyMCA6IC8vIExlZ2FjeSBNb3ogbGluZXNcclxuICBcdCAgICAgICBlLmRldGFpbCA/IGUuZGV0YWlsIC8gLTMyNzY1ICogNjAgOiAvLyBMZWdhY3kgTW96IHBhZ2VzXHJcbiAgXHQgICAgICAgMDtcclxuICB9XHJcblxyXG4gIC8vIGNoZWNrIGlmIGVsZW1lbnQgcmVhbGx5IGxlZnQvZW50ZXJlZCB0aGUgZXZlbnQgdGFyZ2V0IChmb3IgbW91c2VlbnRlci9tb3VzZWxlYXZlKVxyXG4gIGZ1bmN0aW9uIGlzRXh0ZXJuYWxUYXJnZXQoZWwsIGUpIHtcclxuXHJcbiAgXHR2YXIgcmVsYXRlZCA9IGUucmVsYXRlZFRhcmdldDtcclxuXHJcbiAgXHRpZiAoIXJlbGF0ZWQpIHsgcmV0dXJuIHRydWU7IH1cclxuXHJcbiAgXHR0cnkge1xyXG4gIFx0XHR3aGlsZSAocmVsYXRlZCAmJiAocmVsYXRlZCAhPT0gZWwpKSB7XHJcbiAgXHRcdFx0cmVsYXRlZCA9IHJlbGF0ZWQucGFyZW50Tm9kZTtcclxuICBcdFx0fVxyXG4gIFx0fSBjYXRjaCAoZXJyKSB7XHJcbiAgXHRcdHJldHVybiBmYWxzZTtcclxuICBcdH1cclxuICBcdHJldHVybiAocmVsYXRlZCAhPT0gZWwpO1xyXG4gIH1cblxuICB2YXIgRG9tRXZlbnQgPSB7XG4gICAgX19wcm90b19fOiBudWxsLFxuICAgIG9uOiBvbixcbiAgICBvZmY6IG9mZixcbiAgICBzdG9wUHJvcGFnYXRpb246IHN0b3BQcm9wYWdhdGlvbixcbiAgICBkaXNhYmxlU2Nyb2xsUHJvcGFnYXRpb246IGRpc2FibGVTY3JvbGxQcm9wYWdhdGlvbixcbiAgICBkaXNhYmxlQ2xpY2tQcm9wYWdhdGlvbjogZGlzYWJsZUNsaWNrUHJvcGFnYXRpb24sXG4gICAgcHJldmVudERlZmF1bHQ6IHByZXZlbnREZWZhdWx0LFxuICAgIHN0b3A6IHN0b3AsXG4gICAgZ2V0UHJvcGFnYXRpb25QYXRoOiBnZXRQcm9wYWdhdGlvblBhdGgsXG4gICAgZ2V0TW91c2VQb3NpdGlvbjogZ2V0TW91c2VQb3NpdGlvbixcbiAgICBnZXRXaGVlbERlbHRhOiBnZXRXaGVlbERlbHRhLFxuICAgIGlzRXh0ZXJuYWxUYXJnZXQ6IGlzRXh0ZXJuYWxUYXJnZXQsXG4gICAgYWRkTGlzdGVuZXI6IG9uLFxuICAgIHJlbW92ZUxpc3RlbmVyOiBvZmZcbiAgfTtcblxuICAvKlxuICAgKiBAY2xhc3MgUG9zQW5pbWF0aW9uXG4gICAqIEBha2EgTC5Qb3NBbmltYXRpb25cbiAgICogQGluaGVyaXRzIEV2ZW50ZWRcbiAgICogVXNlZCBpbnRlcm5hbGx5IGZvciBwYW5uaW5nIGFuaW1hdGlvbnMsIHV0aWxpemluZyBDU1MzIFRyYW5zaXRpb25zIGZvciBtb2Rlcm4gYnJvd3NlcnMgYW5kIGEgdGltZXIgZmFsbGJhY2sgZm9yIElFNi05LlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGBqc1xuICAgKiB2YXIgbXlQb3NpdGlvbk1hcmtlciA9IEwubWFya2VyKFs0OC44NjQ3MTYsIDIuMjk0Njk0XSkuYWRkVG8obWFwKTtcbiAgICpcbiAgICogbXlQb3NpdGlvbk1hcmtlci5vbihcImNsaWNrXCIsIGZ1bmN0aW9uKCkge1xuICAgKiBcdHZhciBwb3MgPSBtYXAubGF0TG5nVG9MYXllclBvaW50KG15UG9zaXRpb25NYXJrZXIuZ2V0TGF0TG5nKCkpO1xuICAgKiBcdHBvcy55IC09IDI1O1xuICAgKiBcdHZhciBmeCA9IG5ldyBMLlBvc0FuaW1hdGlvbigpO1xuICAgKlxuICAgKiBcdGZ4Lm9uY2UoJ2VuZCcsZnVuY3Rpb24oKSB7XG4gICAqIFx0XHRwb3MueSArPSAyNTtcbiAgICogXHRcdGZ4LnJ1bihteVBvc2l0aW9uTWFya2VyLl9pY29uLCBwb3MsIDAuOCk7XG4gICAqIFx0fSk7XG4gICAqXG4gICAqIFx0ZngucnVuKG15UG9zaXRpb25NYXJrZXIuX2ljb24sIHBvcywgMC4zKTtcbiAgICogfSk7XG4gICAqXG4gICAqIGBgYFxuICAgKlxuICAgKiBAY29uc3RydWN0b3IgTC5Qb3NBbmltYXRpb24oKVxuICAgKiBDcmVhdGVzIGEgYFBvc0FuaW1hdGlvbmAgb2JqZWN0LlxuICAgKlxuICAgKi9cblxuICB2YXIgUG9zQW5pbWF0aW9uID0gRXZlbnRlZC5leHRlbmQoe1xuXG4gIFx0Ly8gQG1ldGhvZCBydW4oZWw6IEhUTUxFbGVtZW50LCBuZXdQb3M6IFBvaW50LCBkdXJhdGlvbj86IE51bWJlciwgZWFzZUxpbmVhcml0eT86IE51bWJlcilcbiAgXHQvLyBSdW4gYW4gYW5pbWF0aW9uIG9mIGEgZ2l2ZW4gZWxlbWVudCB0byBhIG5ldyBwb3NpdGlvbiwgb3B0aW9uYWxseSBzZXR0aW5nXG4gIFx0Ly8gZHVyYXRpb24gaW4gc2Vjb25kcyAoYDAuMjVgIGJ5IGRlZmF1bHQpIGFuZCBlYXNpbmcgbGluZWFyaXR5IGZhY3RvciAoM3JkXG4gIFx0Ly8gYXJndW1lbnQgb2YgdGhlIFtjdWJpYyBiZXppZXIgY3VydmVdKGh0dHBzOi8vY3ViaWMtYmV6aWVyLmNvbS8jMCwwLC41LDEpLFxuICBcdC8vIGAwLjVgIGJ5IGRlZmF1bHQpLlxuICBcdHJ1bjogZnVuY3Rpb24gKGVsLCBuZXdQb3MsIGR1cmF0aW9uLCBlYXNlTGluZWFyaXR5KSB7XG4gIFx0XHR0aGlzLnN0b3AoKTtcblxuICBcdFx0dGhpcy5fZWwgPSBlbDtcbiAgXHRcdHRoaXMuX2luUHJvZ3Jlc3MgPSB0cnVlO1xuICBcdFx0dGhpcy5fZHVyYXRpb24gPSBkdXJhdGlvbiB8fCAwLjI1O1xuICBcdFx0dGhpcy5fZWFzZU91dFBvd2VyID0gMSAvIE1hdGgubWF4KGVhc2VMaW5lYXJpdHkgfHwgMC41LCAwLjIpO1xuXG4gIFx0XHR0aGlzLl9zdGFydFBvcyA9IGdldFBvc2l0aW9uKGVsKTtcbiAgXHRcdHRoaXMuX29mZnNldCA9IG5ld1Bvcy5zdWJ0cmFjdCh0aGlzLl9zdGFydFBvcyk7XG4gIFx0XHR0aGlzLl9zdGFydFRpbWUgPSArbmV3IERhdGUoKTtcblxuICBcdFx0Ly8gQGV2ZW50IHN0YXJ0OiBFdmVudFxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgYW5pbWF0aW9uIHN0YXJ0c1xuICBcdFx0dGhpcy5maXJlKCdzdGFydCcpO1xuXG4gIFx0XHR0aGlzLl9hbmltYXRlKCk7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2Qgc3RvcCgpXG4gIFx0Ly8gU3RvcHMgdGhlIGFuaW1hdGlvbiAoaWYgY3VycmVudGx5IHJ1bm5pbmcpLlxuICBcdHN0b3A6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICghdGhpcy5faW5Qcm9ncmVzcykgeyByZXR1cm47IH1cblxuICBcdFx0dGhpcy5fc3RlcCh0cnVlKTtcbiAgXHRcdHRoaXMuX2NvbXBsZXRlKCk7XG4gIFx0fSxcblxuICBcdF9hbmltYXRlOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHQvLyBhbmltYXRpb24gbG9vcFxuICBcdFx0dGhpcy5fYW5pbUlkID0gcmVxdWVzdEFuaW1GcmFtZSh0aGlzLl9hbmltYXRlLCB0aGlzKTtcbiAgXHRcdHRoaXMuX3N0ZXAoKTtcbiAgXHR9LFxuXG4gIFx0X3N0ZXA6IGZ1bmN0aW9uIChyb3VuZCkge1xuICBcdFx0dmFyIGVsYXBzZWQgPSAoK25ldyBEYXRlKCkpIC0gdGhpcy5fc3RhcnRUaW1lLFxuICBcdFx0ICAgIGR1cmF0aW9uID0gdGhpcy5fZHVyYXRpb24gKiAxMDAwO1xuXG4gIFx0XHRpZiAoZWxhcHNlZCA8IGR1cmF0aW9uKSB7XG4gIFx0XHRcdHRoaXMuX3J1bkZyYW1lKHRoaXMuX2Vhc2VPdXQoZWxhcHNlZCAvIGR1cmF0aW9uKSwgcm91bmQpO1xuICBcdFx0fSBlbHNlIHtcbiAgXHRcdFx0dGhpcy5fcnVuRnJhbWUoMSk7XG4gIFx0XHRcdHRoaXMuX2NvbXBsZXRlKCk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF9ydW5GcmFtZTogZnVuY3Rpb24gKHByb2dyZXNzLCByb3VuZCkge1xuICBcdFx0dmFyIHBvcyA9IHRoaXMuX3N0YXJ0UG9zLmFkZCh0aGlzLl9vZmZzZXQubXVsdGlwbHlCeShwcm9ncmVzcykpO1xuICBcdFx0aWYgKHJvdW5kKSB7XG4gIFx0XHRcdHBvcy5fcm91bmQoKTtcbiAgXHRcdH1cbiAgXHRcdHNldFBvc2l0aW9uKHRoaXMuX2VsLCBwb3MpO1xuXG4gIFx0XHQvLyBAZXZlbnQgc3RlcDogRXZlbnRcbiAgXHRcdC8vIEZpcmVkIGNvbnRpbnVvdXNseSBkdXJpbmcgdGhlIGFuaW1hdGlvbi5cbiAgXHRcdHRoaXMuZmlyZSgnc3RlcCcpO1xuICBcdH0sXG5cbiAgXHRfY29tcGxldGU6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGNhbmNlbEFuaW1GcmFtZSh0aGlzLl9hbmltSWQpO1xuXG4gIFx0XHR0aGlzLl9pblByb2dyZXNzID0gZmFsc2U7XG4gIFx0XHQvLyBAZXZlbnQgZW5kOiBFdmVudFxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgYW5pbWF0aW9uIGVuZHMuXG4gIFx0XHR0aGlzLmZpcmUoJ2VuZCcpO1xuICBcdH0sXG5cbiAgXHRfZWFzZU91dDogZnVuY3Rpb24gKHQpIHtcbiAgXHRcdHJldHVybiAxIC0gTWF0aC5wb3coMSAtIHQsIHRoaXMuX2Vhc2VPdXRQb3dlcik7XG4gIFx0fVxuICB9KTtcblxuICAvKlxyXG4gICAqIEBjbGFzcyBNYXBcclxuICAgKiBAYWthIEwuTWFwXHJcbiAgICogQGluaGVyaXRzIEV2ZW50ZWRcclxuICAgKlxyXG4gICAqIFRoZSBjZW50cmFsIGNsYXNzIG9mIHRoZSBBUEkg4oCUIGl0IGlzIHVzZWQgdG8gY3JlYXRlIGEgbWFwIG9uIGEgcGFnZSBhbmQgbWFuaXB1bGF0ZSBpdC5cclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICpcclxuICAgKiBgYGBqc1xyXG4gICAqIC8vIGluaXRpYWxpemUgdGhlIG1hcCBvbiB0aGUgXCJtYXBcIiBkaXYgd2l0aCBhIGdpdmVuIGNlbnRlciBhbmQgem9vbVxyXG4gICAqIHZhciBtYXAgPSBMLm1hcCgnbWFwJywge1xyXG4gICAqIFx0Y2VudGVyOiBbNTEuNTA1LCAtMC4wOV0sXHJcbiAgICogXHR6b29tOiAxM1xyXG4gICAqIH0pO1xyXG4gICAqIGBgYFxyXG4gICAqXHJcbiAgICovXHJcblxyXG4gIHZhciBNYXAgPSBFdmVudGVkLmV4dGVuZCh7XHJcblxyXG4gIFx0b3B0aW9uczoge1xyXG4gIFx0XHQvLyBAc2VjdGlvbiBNYXAgU3RhdGUgT3B0aW9uc1xyXG4gIFx0XHQvLyBAb3B0aW9uIGNyczogQ1JTID0gTC5DUlMuRVBTRzM4NTdcclxuICBcdFx0Ly8gVGhlIFtDb29yZGluYXRlIFJlZmVyZW5jZSBTeXN0ZW1dKCNjcnMpIHRvIHVzZS4gRG9uJ3QgY2hhbmdlIHRoaXMgaWYgeW91J3JlIG5vdFxyXG4gIFx0XHQvLyBzdXJlIHdoYXQgaXQgbWVhbnMuXHJcbiAgXHRcdGNyczogRVBTRzM4NTcsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIGNlbnRlcjogTGF0TG5nID0gdW5kZWZpbmVkXHJcbiAgXHRcdC8vIEluaXRpYWwgZ2VvZ3JhcGhpYyBjZW50ZXIgb2YgdGhlIG1hcFxyXG4gIFx0XHRjZW50ZXI6IHVuZGVmaW5lZCxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gem9vbTogTnVtYmVyID0gdW5kZWZpbmVkXHJcbiAgXHRcdC8vIEluaXRpYWwgbWFwIHpvb20gbGV2ZWxcclxuICBcdFx0em9vbTogdW5kZWZpbmVkLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBtaW5ab29tOiBOdW1iZXIgPSAqXHJcbiAgXHRcdC8vIE1pbmltdW0gem9vbSBsZXZlbCBvZiB0aGUgbWFwLlxyXG4gIFx0XHQvLyBJZiBub3Qgc3BlY2lmaWVkIGFuZCBhdCBsZWFzdCBvbmUgYEdyaWRMYXllcmAgb3IgYFRpbGVMYXllcmAgaXMgaW4gdGhlIG1hcCxcclxuICBcdFx0Ly8gdGhlIGxvd2VzdCBvZiB0aGVpciBgbWluWm9vbWAgb3B0aW9ucyB3aWxsIGJlIHVzZWQgaW5zdGVhZC5cclxuICBcdFx0bWluWm9vbTogdW5kZWZpbmVkLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBtYXhab29tOiBOdW1iZXIgPSAqXHJcbiAgXHRcdC8vIE1heGltdW0gem9vbSBsZXZlbCBvZiB0aGUgbWFwLlxyXG4gIFx0XHQvLyBJZiBub3Qgc3BlY2lmaWVkIGFuZCBhdCBsZWFzdCBvbmUgYEdyaWRMYXllcmAgb3IgYFRpbGVMYXllcmAgaXMgaW4gdGhlIG1hcCxcclxuICBcdFx0Ly8gdGhlIGhpZ2hlc3Qgb2YgdGhlaXIgYG1heFpvb21gIG9wdGlvbnMgd2lsbCBiZSB1c2VkIGluc3RlYWQuXHJcbiAgXHRcdG1heFpvb206IHVuZGVmaW5lZCxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gbGF5ZXJzOiBMYXllcltdID0gW11cclxuICBcdFx0Ly8gQXJyYXkgb2YgbGF5ZXJzIHRoYXQgd2lsbCBiZSBhZGRlZCB0byB0aGUgbWFwIGluaXRpYWxseVxyXG4gIFx0XHRsYXllcnM6IFtdLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBtYXhCb3VuZHM6IExhdExuZ0JvdW5kcyA9IG51bGxcclxuICBcdFx0Ly8gV2hlbiB0aGlzIG9wdGlvbiBpcyBzZXQsIHRoZSBtYXAgcmVzdHJpY3RzIHRoZSB2aWV3IHRvIHRoZSBnaXZlblxyXG4gIFx0XHQvLyBnZW9ncmFwaGljYWwgYm91bmRzLCBib3VuY2luZyB0aGUgdXNlciBiYWNrIGlmIHRoZSB1c2VyIHRyaWVzIHRvIHBhblxyXG4gIFx0XHQvLyBvdXRzaWRlIHRoZSB2aWV3LiBUbyBzZXQgdGhlIHJlc3RyaWN0aW9uIGR5bmFtaWNhbGx5LCB1c2VcclxuICBcdFx0Ly8gW2BzZXRNYXhCb3VuZHNgXSgjbWFwLXNldG1heGJvdW5kcykgbWV0aG9kLlxyXG4gIFx0XHRtYXhCb3VuZHM6IHVuZGVmaW5lZCxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gcmVuZGVyZXI6IFJlbmRlcmVyID0gKlxyXG4gIFx0XHQvLyBUaGUgZGVmYXVsdCBtZXRob2QgZm9yIGRyYXdpbmcgdmVjdG9yIGxheWVycyBvbiB0aGUgbWFwLiBgTC5TVkdgXHJcbiAgXHRcdC8vIG9yIGBMLkNhbnZhc2AgYnkgZGVmYXVsdCBkZXBlbmRpbmcgb24gYnJvd3NlciBzdXBwb3J0LlxyXG4gIFx0XHRyZW5kZXJlcjogdW5kZWZpbmVkLFxyXG5cclxuXHJcbiAgXHRcdC8vIEBzZWN0aW9uIEFuaW1hdGlvbiBPcHRpb25zXHJcbiAgXHRcdC8vIEBvcHRpb24gem9vbUFuaW1hdGlvbjogQm9vbGVhbiA9IHRydWVcclxuICBcdFx0Ly8gV2hldGhlciB0aGUgbWFwIHpvb20gYW5pbWF0aW9uIGlzIGVuYWJsZWQuIEJ5IGRlZmF1bHQgaXQncyBlbmFibGVkXHJcbiAgXHRcdC8vIGluIGFsbCBicm93c2VycyB0aGF0IHN1cHBvcnQgQ1NTMyBUcmFuc2l0aW9ucyBleGNlcHQgQW5kcm9pZC5cclxuICBcdFx0em9vbUFuaW1hdGlvbjogdHJ1ZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gem9vbUFuaW1hdGlvblRocmVzaG9sZDogTnVtYmVyID0gNFxyXG4gIFx0XHQvLyBXb24ndCBhbmltYXRlIHpvb20gaWYgdGhlIHpvb20gZGlmZmVyZW5jZSBleGNlZWRzIHRoaXMgdmFsdWUuXHJcbiAgXHRcdHpvb21BbmltYXRpb25UaHJlc2hvbGQ6IDQsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIGZhZGVBbmltYXRpb246IEJvb2xlYW4gPSB0cnVlXHJcbiAgXHRcdC8vIFdoZXRoZXIgdGhlIHRpbGUgZmFkZSBhbmltYXRpb24gaXMgZW5hYmxlZC4gQnkgZGVmYXVsdCBpdCdzIGVuYWJsZWRcclxuICBcdFx0Ly8gaW4gYWxsIGJyb3dzZXJzIHRoYXQgc3VwcG9ydCBDU1MzIFRyYW5zaXRpb25zIGV4Y2VwdCBBbmRyb2lkLlxyXG4gIFx0XHRmYWRlQW5pbWF0aW9uOiB0cnVlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBtYXJrZXJab29tQW5pbWF0aW9uOiBCb29sZWFuID0gdHJ1ZVxyXG4gIFx0XHQvLyBXaGV0aGVyIG1hcmtlcnMgYW5pbWF0ZSB0aGVpciB6b29tIHdpdGggdGhlIHpvb20gYW5pbWF0aW9uLCBpZiBkaXNhYmxlZFxyXG4gIFx0XHQvLyB0aGV5IHdpbGwgZGlzYXBwZWFyIGZvciB0aGUgbGVuZ3RoIG9mIHRoZSBhbmltYXRpb24uIEJ5IGRlZmF1bHQgaXQnc1xyXG4gIFx0XHQvLyBlbmFibGVkIGluIGFsbCBicm93c2VycyB0aGF0IHN1cHBvcnQgQ1NTMyBUcmFuc2l0aW9ucyBleGNlcHQgQW5kcm9pZC5cclxuICBcdFx0bWFya2VyWm9vbUFuaW1hdGlvbjogdHJ1ZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gdHJhbnNmb3JtM0RMaW1pdDogTnVtYmVyID0gMl4yM1xyXG4gIFx0XHQvLyBEZWZpbmVzIHRoZSBtYXhpbXVtIHNpemUgb2YgYSBDU1MgdHJhbnNsYXRpb24gdHJhbnNmb3JtLiBUaGUgZGVmYXVsdFxyXG4gIFx0XHQvLyB2YWx1ZSBzaG91bGQgbm90IGJlIGNoYW5nZWQgdW5sZXNzIGEgd2ViIGJyb3dzZXIgcG9zaXRpb25zIGxheWVycyBpblxyXG4gIFx0XHQvLyB0aGUgd3JvbmcgcGxhY2UgYWZ0ZXIgZG9pbmcgYSBsYXJnZSBgcGFuQnlgLlxyXG4gIFx0XHR0cmFuc2Zvcm0zRExpbWl0OiA4Mzg4NjA4LCAvLyBQcmVjaXNpb24gbGltaXQgb2YgYSAzMi1iaXQgZmxvYXRcclxuXHJcbiAgXHRcdC8vIEBzZWN0aW9uIEludGVyYWN0aW9uIE9wdGlvbnNcclxuICBcdFx0Ly8gQG9wdGlvbiB6b29tU25hcDogTnVtYmVyID0gMVxyXG4gIFx0XHQvLyBGb3JjZXMgdGhlIG1hcCdzIHpvb20gbGV2ZWwgdG8gYWx3YXlzIGJlIGEgbXVsdGlwbGUgb2YgdGhpcywgcGFydGljdWxhcmx5XHJcbiAgXHRcdC8vIHJpZ2h0IGFmdGVyIGEgW2BmaXRCb3VuZHMoKWBdKCNtYXAtZml0Ym91bmRzKSBvciBhIHBpbmNoLXpvb20uXHJcbiAgXHRcdC8vIEJ5IGRlZmF1bHQsIHRoZSB6b29tIGxldmVsIHNuYXBzIHRvIHRoZSBuZWFyZXN0IGludGVnZXI7IGxvd2VyIHZhbHVlc1xyXG4gIFx0XHQvLyAoZS5nLiBgMC41YCBvciBgMC4xYCkgYWxsb3cgZm9yIGdyZWF0ZXIgZ3JhbnVsYXJpdHkuIEEgdmFsdWUgb2YgYDBgXHJcbiAgXHRcdC8vIG1lYW5zIHRoZSB6b29tIGxldmVsIHdpbGwgbm90IGJlIHNuYXBwZWQgYWZ0ZXIgYGZpdEJvdW5kc2Agb3IgYSBwaW5jaC16b29tLlxyXG4gIFx0XHR6b29tU25hcDogMSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gem9vbURlbHRhOiBOdW1iZXIgPSAxXHJcbiAgXHRcdC8vIENvbnRyb2xzIGhvdyBtdWNoIHRoZSBtYXAncyB6b29tIGxldmVsIHdpbGwgY2hhbmdlIGFmdGVyIGFcclxuICBcdFx0Ly8gW2B6b29tSW4oKWBdKCNtYXAtem9vbWluKSwgW2B6b29tT3V0KClgXSgjbWFwLXpvb21vdXQpLCBwcmVzc2luZyBgK2BcclxuICBcdFx0Ly8gb3IgYC1gIG9uIHRoZSBrZXlib2FyZCwgb3IgdXNpbmcgdGhlIFt6b29tIGNvbnRyb2xzXSgjY29udHJvbC16b29tKS5cclxuICBcdFx0Ly8gVmFsdWVzIHNtYWxsZXIgdGhhbiBgMWAgKGUuZy4gYDAuNWApIGFsbG93IGZvciBncmVhdGVyIGdyYW51bGFyaXR5LlxyXG4gIFx0XHR6b29tRGVsdGE6IDEsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHRyYWNrUmVzaXplOiBCb29sZWFuID0gdHJ1ZVxyXG4gIFx0XHQvLyBXaGV0aGVyIHRoZSBtYXAgYXV0b21hdGljYWxseSBoYW5kbGVzIGJyb3dzZXIgd2luZG93IHJlc2l6ZSB0byB1cGRhdGUgaXRzZWxmLlxyXG4gIFx0XHR0cmFja1Jlc2l6ZTogdHJ1ZVxyXG4gIFx0fSxcclxuXHJcbiAgXHRpbml0aWFsaXplOiBmdW5jdGlvbiAoaWQsIG9wdGlvbnMpIHsgLy8gKEhUTUxFbGVtZW50IG9yIFN0cmluZywgT2JqZWN0KVxyXG4gIFx0XHRvcHRpb25zID0gc2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcclxuXHJcbiAgXHRcdC8vIE1ha2Ugc3VyZSB0byBhc3NpZ24gaW50ZXJuYWwgZmxhZ3MgYXQgdGhlIGJlZ2lubmluZyxcclxuICBcdFx0Ly8gdG8gYXZvaWQgaW5jb25zaXN0ZW50IHN0YXRlIGluIHNvbWUgZWRnZSBjYXNlcy5cclxuICBcdFx0dGhpcy5faGFuZGxlcnMgPSBbXTtcclxuICBcdFx0dGhpcy5fbGF5ZXJzID0ge307XHJcbiAgXHRcdHRoaXMuX3pvb21Cb3VuZExheWVycyA9IHt9O1xyXG4gIFx0XHR0aGlzLl9zaXplQ2hhbmdlZCA9IHRydWU7XHJcblxyXG4gIFx0XHR0aGlzLl9pbml0Q29udGFpbmVyKGlkKTtcclxuICBcdFx0dGhpcy5faW5pdExheW91dCgpO1xyXG5cclxuICBcdFx0Ly8gaGFjayBmb3IgaHR0cHM6Ly9naXRodWIuY29tL0xlYWZsZXQvTGVhZmxldC9pc3N1ZXMvMTk4MFxyXG4gIFx0XHR0aGlzLl9vblJlc2l6ZSA9IGJpbmQodGhpcy5fb25SZXNpemUsIHRoaXMpO1xyXG5cclxuICBcdFx0dGhpcy5faW5pdEV2ZW50cygpO1xyXG5cclxuICBcdFx0aWYgKG9wdGlvbnMubWF4Qm91bmRzKSB7XHJcbiAgXHRcdFx0dGhpcy5zZXRNYXhCb3VuZHMob3B0aW9ucy5tYXhCb3VuZHMpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAob3B0aW9ucy56b29tICE9PSB1bmRlZmluZWQpIHtcclxuICBcdFx0XHR0aGlzLl96b29tID0gdGhpcy5fbGltaXRab29tKG9wdGlvbnMuem9vbSk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmIChvcHRpb25zLmNlbnRlciAmJiBvcHRpb25zLnpvb20gIT09IHVuZGVmaW5lZCkge1xyXG4gIFx0XHRcdHRoaXMuc2V0Vmlldyh0b0xhdExuZyhvcHRpb25zLmNlbnRlciksIG9wdGlvbnMuem9vbSwge3Jlc2V0OiB0cnVlfSk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuY2FsbEluaXRIb29rcygpO1xyXG5cclxuICBcdFx0Ly8gZG9uJ3QgYW5pbWF0ZSBvbiBicm93c2VycyB3aXRob3V0IGhhcmR3YXJlLWFjY2VsZXJhdGVkIHRyYW5zaXRpb25zIG9yIG9sZCBBbmRyb2lkL09wZXJhXHJcbiAgXHRcdHRoaXMuX3pvb21BbmltYXRlZCA9IFRSQU5TSVRJT04gJiYgQnJvd3Nlci5hbnkzZCAmJiAhQnJvd3Nlci5tb2JpbGVPcGVyYSAmJlxyXG4gIFx0XHRcdFx0dGhpcy5vcHRpb25zLnpvb21BbmltYXRpb247XHJcblxyXG4gIFx0XHQvLyB6b29tIHRyYW5zaXRpb25zIHJ1biB3aXRoIHRoZSBzYW1lIGR1cmF0aW9uIGZvciBhbGwgbGF5ZXJzLCBzbyBpZiBvbmUgb2YgdHJhbnNpdGlvbmVuZCBldmVudHNcclxuICBcdFx0Ly8gaGFwcGVucyBhZnRlciBzdGFydGluZyB6b29tIGFuaW1hdGlvbiAocHJvcGFnYXRpbmcgdG8gdGhlIG1hcCBwYW5lKSwgd2Uga25vdyB0aGF0IGl0IGVuZGVkIGdsb2JhbGx5XHJcbiAgXHRcdGlmICh0aGlzLl96b29tQW5pbWF0ZWQpIHtcclxuICBcdFx0XHR0aGlzLl9jcmVhdGVBbmltUHJveHkoKTtcclxuICBcdFx0XHRvbih0aGlzLl9wcm94eSwgVFJBTlNJVElPTl9FTkQsIHRoaXMuX2NhdGNoVHJhbnNpdGlvbkVuZCwgdGhpcyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX2FkZExheWVycyh0aGlzLm9wdGlvbnMubGF5ZXJzKTtcclxuICBcdH0sXHJcblxyXG5cclxuICBcdC8vIEBzZWN0aW9uIE1ldGhvZHMgZm9yIG1vZGlmeWluZyBtYXAgc3RhdGVcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNldFZpZXcoY2VudGVyOiBMYXRMbmcsIHpvb206IE51bWJlciwgb3B0aW9ucz86IFpvb20vcGFuIG9wdGlvbnMpOiB0aGlzXHJcbiAgXHQvLyBTZXRzIHRoZSB2aWV3IG9mIHRoZSBtYXAgKGdlb2dyYXBoaWNhbCBjZW50ZXIgYW5kIHpvb20pIHdpdGggdGhlIGdpdmVuXHJcbiAgXHQvLyBhbmltYXRpb24gb3B0aW9ucy5cclxuICBcdHNldFZpZXc6IGZ1bmN0aW9uIChjZW50ZXIsIHpvb20sIG9wdGlvbnMpIHtcclxuXHJcbiAgXHRcdHpvb20gPSB6b29tID09PSB1bmRlZmluZWQgPyB0aGlzLl96b29tIDogdGhpcy5fbGltaXRab29tKHpvb20pO1xyXG4gIFx0XHRjZW50ZXIgPSB0aGlzLl9saW1pdENlbnRlcih0b0xhdExuZyhjZW50ZXIpLCB6b29tLCB0aGlzLm9wdGlvbnMubWF4Qm91bmRzKTtcclxuICBcdFx0b3B0aW9ucyA9IG9wdGlvbnMgfHwge307XHJcblxyXG4gIFx0XHR0aGlzLl9zdG9wKCk7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fbG9hZGVkICYmICFvcHRpb25zLnJlc2V0ICYmIG9wdGlvbnMgIT09IHRydWUpIHtcclxuXHJcbiAgXHRcdFx0aWYgKG9wdGlvbnMuYW5pbWF0ZSAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgXHRcdFx0XHRvcHRpb25zLnpvb20gPSBleHRlbmQoe2FuaW1hdGU6IG9wdGlvbnMuYW5pbWF0ZX0sIG9wdGlvbnMuem9vbSk7XHJcbiAgXHRcdFx0XHRvcHRpb25zLnBhbiA9IGV4dGVuZCh7YW5pbWF0ZTogb3B0aW9ucy5hbmltYXRlLCBkdXJhdGlvbjogb3B0aW9ucy5kdXJhdGlvbn0sIG9wdGlvbnMucGFuKTtcclxuICBcdFx0XHR9XHJcblxyXG4gIFx0XHRcdC8vIHRyeSBhbmltYXRpbmcgcGFuIG9yIHpvb21cclxuICBcdFx0XHR2YXIgbW92ZWQgPSAodGhpcy5fem9vbSAhPT0gem9vbSkgP1xyXG4gIFx0XHRcdFx0dGhpcy5fdHJ5QW5pbWF0ZWRab29tICYmIHRoaXMuX3RyeUFuaW1hdGVkWm9vbShjZW50ZXIsIHpvb20sIG9wdGlvbnMuem9vbSkgOlxyXG4gIFx0XHRcdFx0dGhpcy5fdHJ5QW5pbWF0ZWRQYW4oY2VudGVyLCBvcHRpb25zLnBhbik7XHJcblxyXG4gIFx0XHRcdGlmIChtb3ZlZCkge1xyXG4gIFx0XHRcdFx0Ly8gcHJldmVudCByZXNpemUgaGFuZGxlciBjYWxsLCB0aGUgdmlldyB3aWxsIHJlZnJlc2ggYWZ0ZXIgYW5pbWF0aW9uIGFueXdheVxyXG4gIFx0XHRcdFx0Y2xlYXJUaW1lb3V0KHRoaXMuX3NpemVUaW1lcik7XHJcbiAgXHRcdFx0XHRyZXR1cm4gdGhpcztcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdC8vIGFuaW1hdGlvbiBkaWRuJ3Qgc3RhcnQsIGp1c3QgcmVzZXQgdGhlIG1hcCB2aWV3XHJcbiAgXHRcdHRoaXMuX3Jlc2V0VmlldyhjZW50ZXIsIHpvb20sIG9wdGlvbnMucGFuICYmIG9wdGlvbnMucGFuLm5vTW92ZVN0YXJ0KTtcclxuXHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNldFpvb20oem9vbTogTnVtYmVyLCBvcHRpb25zPzogWm9vbS9wYW4gb3B0aW9ucyk6IHRoaXNcclxuICBcdC8vIFNldHMgdGhlIHpvb20gb2YgdGhlIG1hcC5cclxuICBcdHNldFpvb206IGZ1bmN0aW9uICh6b29tLCBvcHRpb25zKSB7XHJcbiAgXHRcdGlmICghdGhpcy5fbG9hZGVkKSB7XHJcbiAgXHRcdFx0dGhpcy5fem9vbSA9IHpvb207XHJcbiAgXHRcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXMuc2V0Vmlldyh0aGlzLmdldENlbnRlcigpLCB6b29tLCB7em9vbTogb3B0aW9uc30pO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHpvb21JbihkZWx0YT86IE51bWJlciwgb3B0aW9ucz86IFpvb20gb3B0aW9ucyk6IHRoaXNcclxuICBcdC8vIEluY3JlYXNlcyB0aGUgem9vbSBvZiB0aGUgbWFwIGJ5IGBkZWx0YWAgKFtgem9vbURlbHRhYF0oI21hcC16b29tZGVsdGEpIGJ5IGRlZmF1bHQpLlxyXG4gIFx0em9vbUluOiBmdW5jdGlvbiAoZGVsdGEsIG9wdGlvbnMpIHtcclxuICBcdFx0ZGVsdGEgPSBkZWx0YSB8fCAoQnJvd3Nlci5hbnkzZCA/IHRoaXMub3B0aW9ucy56b29tRGVsdGEgOiAxKTtcclxuICBcdFx0cmV0dXJuIHRoaXMuc2V0Wm9vbSh0aGlzLl96b29tICsgZGVsdGEsIG9wdGlvbnMpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHpvb21PdXQoZGVsdGE/OiBOdW1iZXIsIG9wdGlvbnM/OiBab29tIG9wdGlvbnMpOiB0aGlzXHJcbiAgXHQvLyBEZWNyZWFzZXMgdGhlIHpvb20gb2YgdGhlIG1hcCBieSBgZGVsdGFgIChbYHpvb21EZWx0YWBdKCNtYXAtem9vbWRlbHRhKSBieSBkZWZhdWx0KS5cclxuICBcdHpvb21PdXQ6IGZ1bmN0aW9uIChkZWx0YSwgb3B0aW9ucykge1xyXG4gIFx0XHRkZWx0YSA9IGRlbHRhIHx8IChCcm93c2VyLmFueTNkID8gdGhpcy5vcHRpb25zLnpvb21EZWx0YSA6IDEpO1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5zZXRab29tKHRoaXMuX3pvb20gLSBkZWx0YSwgb3B0aW9ucyk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2V0Wm9vbUFyb3VuZChsYXRsbmc6IExhdExuZywgem9vbTogTnVtYmVyLCBvcHRpb25zOiBab29tIG9wdGlvbnMpOiB0aGlzXHJcbiAgXHQvLyBab29tcyB0aGUgbWFwIHdoaWxlIGtlZXBpbmcgYSBzcGVjaWZpZWQgZ2VvZ3JhcGhpY2FsIHBvaW50IG9uIHRoZSBtYXBcclxuICBcdC8vIHN0YXRpb25hcnkgKGUuZy4gdXNlZCBpbnRlcm5hbGx5IGZvciBzY3JvbGwgem9vbSBhbmQgZG91YmxlLWNsaWNrIHpvb20pLlxyXG4gIFx0Ly8gQGFsdGVybmF0aXZlXHJcbiAgXHQvLyBAbWV0aG9kIHNldFpvb21Bcm91bmQob2Zmc2V0OiBQb2ludCwgem9vbTogTnVtYmVyLCBvcHRpb25zOiBab29tIG9wdGlvbnMpOiB0aGlzXHJcbiAgXHQvLyBab29tcyB0aGUgbWFwIHdoaWxlIGtlZXBpbmcgYSBzcGVjaWZpZWQgcGl4ZWwgb24gdGhlIG1hcCAocmVsYXRpdmUgdG8gdGhlIHRvcC1sZWZ0IGNvcm5lcikgc3RhdGlvbmFyeS5cclxuICBcdHNldFpvb21Bcm91bmQ6IGZ1bmN0aW9uIChsYXRsbmcsIHpvb20sIG9wdGlvbnMpIHtcclxuICBcdFx0dmFyIHNjYWxlID0gdGhpcy5nZXRab29tU2NhbGUoem9vbSksXHJcbiAgXHRcdCAgICB2aWV3SGFsZiA9IHRoaXMuZ2V0U2l6ZSgpLmRpdmlkZUJ5KDIpLFxyXG4gIFx0XHQgICAgY29udGFpbmVyUG9pbnQgPSBsYXRsbmcgaW5zdGFuY2VvZiBQb2ludCA/IGxhdGxuZyA6IHRoaXMubGF0TG5nVG9Db250YWluZXJQb2ludChsYXRsbmcpLFxyXG5cclxuICBcdFx0ICAgIGNlbnRlck9mZnNldCA9IGNvbnRhaW5lclBvaW50LnN1YnRyYWN0KHZpZXdIYWxmKS5tdWx0aXBseUJ5KDEgLSAxIC8gc2NhbGUpLFxyXG4gIFx0XHQgICAgbmV3Q2VudGVyID0gdGhpcy5jb250YWluZXJQb2ludFRvTGF0TG5nKHZpZXdIYWxmLmFkZChjZW50ZXJPZmZzZXQpKTtcclxuXHJcbiAgXHRcdHJldHVybiB0aGlzLnNldFZpZXcobmV3Q2VudGVyLCB6b29tLCB7em9vbTogb3B0aW9uc30pO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfZ2V0Qm91bmRzQ2VudGVyWm9vbTogZnVuY3Rpb24gKGJvdW5kcywgb3B0aW9ucykge1xyXG5cclxuICBcdFx0b3B0aW9ucyA9IG9wdGlvbnMgfHwge307XHJcbiAgXHRcdGJvdW5kcyA9IGJvdW5kcy5nZXRCb3VuZHMgPyBib3VuZHMuZ2V0Qm91bmRzKCkgOiB0b0xhdExuZ0JvdW5kcyhib3VuZHMpO1xyXG5cclxuICBcdFx0dmFyIHBhZGRpbmdUTCA9IHRvUG9pbnQob3B0aW9ucy5wYWRkaW5nVG9wTGVmdCB8fCBvcHRpb25zLnBhZGRpbmcgfHwgWzAsIDBdKSxcclxuICBcdFx0ICAgIHBhZGRpbmdCUiA9IHRvUG9pbnQob3B0aW9ucy5wYWRkaW5nQm90dG9tUmlnaHQgfHwgb3B0aW9ucy5wYWRkaW5nIHx8IFswLCAwXSksXHJcblxyXG4gIFx0XHQgICAgem9vbSA9IHRoaXMuZ2V0Qm91bmRzWm9vbShib3VuZHMsIGZhbHNlLCBwYWRkaW5nVEwuYWRkKHBhZGRpbmdCUikpO1xyXG5cclxuICBcdFx0em9vbSA9ICh0eXBlb2Ygb3B0aW9ucy5tYXhab29tID09PSAnbnVtYmVyJykgPyBNYXRoLm1pbihvcHRpb25zLm1heFpvb20sIHpvb20pIDogem9vbTtcclxuXHJcbiAgXHRcdGlmICh6b29tID09PSBJbmZpbml0eSkge1xyXG4gIFx0XHRcdHJldHVybiB7XHJcbiAgXHRcdFx0XHRjZW50ZXI6IGJvdW5kcy5nZXRDZW50ZXIoKSxcclxuICBcdFx0XHRcdHpvb206IHpvb21cclxuICBcdFx0XHR9O1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgcGFkZGluZ09mZnNldCA9IHBhZGRpbmdCUi5zdWJ0cmFjdChwYWRkaW5nVEwpLmRpdmlkZUJ5KDIpLFxyXG5cclxuICBcdFx0ICAgIHN3UG9pbnQgPSB0aGlzLnByb2plY3QoYm91bmRzLmdldFNvdXRoV2VzdCgpLCB6b29tKSxcclxuICBcdFx0ICAgIG5lUG9pbnQgPSB0aGlzLnByb2plY3QoYm91bmRzLmdldE5vcnRoRWFzdCgpLCB6b29tKSxcclxuICBcdFx0ICAgIGNlbnRlciA9IHRoaXMudW5wcm9qZWN0KHN3UG9pbnQuYWRkKG5lUG9pbnQpLmRpdmlkZUJ5KDIpLmFkZChwYWRkaW5nT2Zmc2V0KSwgem9vbSk7XHJcblxyXG4gIFx0XHRyZXR1cm4ge1xyXG4gIFx0XHRcdGNlbnRlcjogY2VudGVyLFxyXG4gIFx0XHRcdHpvb206IHpvb21cclxuICBcdFx0fTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBmaXRCb3VuZHMoYm91bmRzOiBMYXRMbmdCb3VuZHMsIG9wdGlvbnM/OiBmaXRCb3VuZHMgb3B0aW9ucyk6IHRoaXNcclxuICBcdC8vIFNldHMgYSBtYXAgdmlldyB0aGF0IGNvbnRhaW5zIHRoZSBnaXZlbiBnZW9ncmFwaGljYWwgYm91bmRzIHdpdGggdGhlXHJcbiAgXHQvLyBtYXhpbXVtIHpvb20gbGV2ZWwgcG9zc2libGUuXHJcbiAgXHRmaXRCb3VuZHM6IGZ1bmN0aW9uIChib3VuZHMsIG9wdGlvbnMpIHtcclxuXHJcbiAgXHRcdGJvdW5kcyA9IHRvTGF0TG5nQm91bmRzKGJvdW5kcyk7XHJcblxyXG4gIFx0XHRpZiAoIWJvdW5kcy5pc1ZhbGlkKCkpIHtcclxuICBcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0JvdW5kcyBhcmUgbm90IHZhbGlkLicpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgdGFyZ2V0ID0gdGhpcy5fZ2V0Qm91bmRzQ2VudGVyWm9vbShib3VuZHMsIG9wdGlvbnMpO1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5zZXRWaWV3KHRhcmdldC5jZW50ZXIsIHRhcmdldC56b29tLCBvcHRpb25zKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBmaXRXb3JsZChvcHRpb25zPzogZml0Qm91bmRzIG9wdGlvbnMpOiB0aGlzXHJcbiAgXHQvLyBTZXRzIGEgbWFwIHZpZXcgdGhhdCBtb3N0bHkgY29udGFpbnMgdGhlIHdob2xlIHdvcmxkIHdpdGggdGhlIG1heGltdW1cclxuICBcdC8vIHpvb20gbGV2ZWwgcG9zc2libGUuXHJcbiAgXHRmaXRXb3JsZDogZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuZml0Qm91bmRzKFtbLTkwLCAtMTgwXSwgWzkwLCAxODBdXSwgb3B0aW9ucyk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgcGFuVG8obGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/OiBQYW4gb3B0aW9ucyk6IHRoaXNcclxuICBcdC8vIFBhbnMgdGhlIG1hcCB0byBhIGdpdmVuIGNlbnRlci5cclxuICBcdHBhblRvOiBmdW5jdGlvbiAoY2VudGVyLCBvcHRpb25zKSB7IC8vIChMYXRMbmcpXHJcbiAgXHRcdHJldHVybiB0aGlzLnNldFZpZXcoY2VudGVyLCB0aGlzLl96b29tLCB7cGFuOiBvcHRpb25zfSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgcGFuQnkob2Zmc2V0OiBQb2ludCwgb3B0aW9ucz86IFBhbiBvcHRpb25zKTogdGhpc1xyXG4gIFx0Ly8gUGFucyB0aGUgbWFwIGJ5IGEgZ2l2ZW4gbnVtYmVyIG9mIHBpeGVscyAoYW5pbWF0ZWQpLlxyXG4gIFx0cGFuQnk6IGZ1bmN0aW9uIChvZmZzZXQsIG9wdGlvbnMpIHtcclxuICBcdFx0b2Zmc2V0ID0gdG9Qb2ludChvZmZzZXQpLnJvdW5kKCk7XHJcbiAgXHRcdG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xyXG5cclxuICBcdFx0aWYgKCFvZmZzZXQueCAmJiAhb2Zmc2V0LnkpIHtcclxuICBcdFx0XHRyZXR1cm4gdGhpcy5maXJlKCdtb3ZlZW5kJyk7XHJcbiAgXHRcdH1cclxuICBcdFx0Ly8gSWYgd2UgcGFuIHRvbyBmYXIsIENocm9tZSBnZXRzIGlzc3VlcyB3aXRoIHRpbGVzXHJcbiAgXHRcdC8vIGFuZCBtYWtlcyB0aGVtIGRpc2FwcGVhciBvciBhcHBlYXIgaW4gdGhlIHdyb25nIHBsYWNlIChzbGlnaHRseSBvZmZzZXQpICMyNjAyXHJcbiAgXHRcdGlmIChvcHRpb25zLmFuaW1hdGUgIT09IHRydWUgJiYgIXRoaXMuZ2V0U2l6ZSgpLmNvbnRhaW5zKG9mZnNldCkpIHtcclxuICBcdFx0XHR0aGlzLl9yZXNldFZpZXcodGhpcy51bnByb2plY3QodGhpcy5wcm9qZWN0KHRoaXMuZ2V0Q2VudGVyKCkpLmFkZChvZmZzZXQpKSwgdGhpcy5nZXRab29tKCkpO1xyXG4gIFx0XHRcdHJldHVybiB0aGlzO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAoIXRoaXMuX3BhbkFuaW0pIHtcclxuICBcdFx0XHR0aGlzLl9wYW5BbmltID0gbmV3IFBvc0FuaW1hdGlvbigpO1xyXG5cclxuICBcdFx0XHR0aGlzLl9wYW5BbmltLm9uKHtcclxuICBcdFx0XHRcdCdzdGVwJzogdGhpcy5fb25QYW5UcmFuc2l0aW9uU3RlcCxcclxuICBcdFx0XHRcdCdlbmQnOiB0aGlzLl9vblBhblRyYW5zaXRpb25FbmRcclxuICBcdFx0XHR9LCB0aGlzKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gZG9uJ3QgZmlyZSBtb3Zlc3RhcnQgaWYgYW5pbWF0aW5nIGluZXJ0aWFcclxuICBcdFx0aWYgKCFvcHRpb25zLm5vTW92ZVN0YXJ0KSB7XHJcbiAgXHRcdFx0dGhpcy5maXJlKCdtb3Zlc3RhcnQnKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gYW5pbWF0ZSBwYW4gdW5sZXNzIGFuaW1hdGU6IGZhbHNlIHNwZWNpZmllZFxyXG4gIFx0XHRpZiAob3B0aW9ucy5hbmltYXRlICE9PSBmYWxzZSkge1xyXG4gIFx0XHRcdGFkZENsYXNzKHRoaXMuX21hcFBhbmUsICdsZWFmbGV0LXBhbi1hbmltJyk7XHJcblxyXG4gIFx0XHRcdHZhciBuZXdQb3MgPSB0aGlzLl9nZXRNYXBQYW5lUG9zKCkuc3VidHJhY3Qob2Zmc2V0KS5yb3VuZCgpO1xyXG4gIFx0XHRcdHRoaXMuX3BhbkFuaW0ucnVuKHRoaXMuX21hcFBhbmUsIG5ld1Bvcywgb3B0aW9ucy5kdXJhdGlvbiB8fCAwLjI1LCBvcHRpb25zLmVhc2VMaW5lYXJpdHkpO1xyXG4gIFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdHRoaXMuX3Jhd1BhbkJ5KG9mZnNldCk7XHJcbiAgXHRcdFx0dGhpcy5maXJlKCdtb3ZlJykuZmlyZSgnbW92ZWVuZCcpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBmbHlUbyhsYXRsbmc6IExhdExuZywgem9vbT86IE51bWJlciwgb3B0aW9ucz86IFpvb20vcGFuIG9wdGlvbnMpOiB0aGlzXHJcbiAgXHQvLyBTZXRzIHRoZSB2aWV3IG9mIHRoZSBtYXAgKGdlb2dyYXBoaWNhbCBjZW50ZXIgYW5kIHpvb20pIHBlcmZvcm1pbmcgYSBzbW9vdGhcclxuICBcdC8vIHBhbi16b29tIGFuaW1hdGlvbi5cclxuICBcdGZseVRvOiBmdW5jdGlvbiAodGFyZ2V0Q2VudGVyLCB0YXJnZXRab29tLCBvcHRpb25zKSB7XHJcblxyXG4gIFx0XHRvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcclxuICBcdFx0aWYgKG9wdGlvbnMuYW5pbWF0ZSA9PT0gZmFsc2UgfHwgIUJyb3dzZXIuYW55M2QpIHtcclxuICBcdFx0XHRyZXR1cm4gdGhpcy5zZXRWaWV3KHRhcmdldENlbnRlciwgdGFyZ2V0Wm9vbSwgb3B0aW9ucyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX3N0b3AoKTtcclxuXHJcbiAgXHRcdHZhciBmcm9tID0gdGhpcy5wcm9qZWN0KHRoaXMuZ2V0Q2VudGVyKCkpLFxyXG4gIFx0XHQgICAgdG8gPSB0aGlzLnByb2plY3QodGFyZ2V0Q2VudGVyKSxcclxuICBcdFx0ICAgIHNpemUgPSB0aGlzLmdldFNpemUoKSxcclxuICBcdFx0ICAgIHN0YXJ0Wm9vbSA9IHRoaXMuX3pvb207XHJcblxyXG4gIFx0XHR0YXJnZXRDZW50ZXIgPSB0b0xhdExuZyh0YXJnZXRDZW50ZXIpO1xyXG4gIFx0XHR0YXJnZXRab29tID0gdGFyZ2V0Wm9vbSA9PT0gdW5kZWZpbmVkID8gc3RhcnRab29tIDogdGFyZ2V0Wm9vbTtcclxuXHJcbiAgXHRcdHZhciB3MCA9IE1hdGgubWF4KHNpemUueCwgc2l6ZS55KSxcclxuICBcdFx0ICAgIHcxID0gdzAgKiB0aGlzLmdldFpvb21TY2FsZShzdGFydFpvb20sIHRhcmdldFpvb20pLFxyXG4gIFx0XHQgICAgdTEgPSAodG8uZGlzdGFuY2VUbyhmcm9tKSkgfHwgMSxcclxuICBcdFx0ICAgIHJobyA9IDEuNDIsXHJcbiAgXHRcdCAgICByaG8yID0gcmhvICogcmhvO1xyXG5cclxuICBcdFx0ZnVuY3Rpb24gcihpKSB7XHJcbiAgXHRcdFx0dmFyIHMxID0gaSA/IC0xIDogMSxcclxuICBcdFx0XHQgICAgczIgPSBpID8gdzEgOiB3MCxcclxuICBcdFx0XHQgICAgdDEgPSB3MSAqIHcxIC0gdzAgKiB3MCArIHMxICogcmhvMiAqIHJobzIgKiB1MSAqIHUxLFxyXG4gIFx0XHRcdCAgICBiMSA9IDIgKiBzMiAqIHJobzIgKiB1MSxcclxuICBcdFx0XHQgICAgYiA9IHQxIC8gYjEsXHJcbiAgXHRcdFx0ICAgIHNxID0gTWF0aC5zcXJ0KGIgKiBiICsgMSkgLSBiO1xyXG5cclxuICBcdFx0XHQgICAgLy8gd29ya2Fyb3VuZCBmb3IgZmxvYXRpbmcgcG9pbnQgcHJlY2lzaW9uIGJ1ZyB3aGVuIHNxID0gMCwgbG9nID0gLUluZmluaXRlLFxyXG4gIFx0XHRcdCAgICAvLyB0aHVzIHRyaWdnZXJpbmcgYW4gaW5maW5pdGUgbG9vcCBpbiBmbHlUb1xyXG4gIFx0XHRcdCAgICB2YXIgbG9nID0gc3EgPCAwLjAwMDAwMDAwMSA/IC0xOCA6IE1hdGgubG9nKHNxKTtcclxuXHJcbiAgXHRcdFx0cmV0dXJuIGxvZztcclxuICBcdFx0fVxyXG5cclxuICBcdFx0ZnVuY3Rpb24gc2luaChuKSB7IHJldHVybiAoTWF0aC5leHAobikgLSBNYXRoLmV4cCgtbikpIC8gMjsgfVxyXG4gIFx0XHRmdW5jdGlvbiBjb3NoKG4pIHsgcmV0dXJuIChNYXRoLmV4cChuKSArIE1hdGguZXhwKC1uKSkgLyAyOyB9XHJcbiAgXHRcdGZ1bmN0aW9uIHRhbmgobikgeyByZXR1cm4gc2luaChuKSAvIGNvc2gobik7IH1cclxuXHJcbiAgXHRcdHZhciByMCA9IHIoMCk7XHJcblxyXG4gIFx0XHRmdW5jdGlvbiB3KHMpIHsgcmV0dXJuIHcwICogKGNvc2gocjApIC8gY29zaChyMCArIHJobyAqIHMpKTsgfVxyXG4gIFx0XHRmdW5jdGlvbiB1KHMpIHsgcmV0dXJuIHcwICogKGNvc2gocjApICogdGFuaChyMCArIHJobyAqIHMpIC0gc2luaChyMCkpIC8gcmhvMjsgfVxyXG5cclxuICBcdFx0ZnVuY3Rpb24gZWFzZU91dCh0KSB7IHJldHVybiAxIC0gTWF0aC5wb3coMSAtIHQsIDEuNSk7IH1cclxuXHJcbiAgXHRcdHZhciBzdGFydCA9IERhdGUubm93KCksXHJcbiAgXHRcdCAgICBTID0gKHIoMSkgLSByMCkgLyByaG8sXHJcbiAgXHRcdCAgICBkdXJhdGlvbiA9IG9wdGlvbnMuZHVyYXRpb24gPyAxMDAwICogb3B0aW9ucy5kdXJhdGlvbiA6IDEwMDAgKiBTICogMC44O1xyXG5cclxuICBcdFx0ZnVuY3Rpb24gZnJhbWUoKSB7XHJcbiAgXHRcdFx0dmFyIHQgPSAoRGF0ZS5ub3coKSAtIHN0YXJ0KSAvIGR1cmF0aW9uLFxyXG4gIFx0XHRcdCAgICBzID0gZWFzZU91dCh0KSAqIFM7XHJcblxyXG4gIFx0XHRcdGlmICh0IDw9IDEpIHtcclxuICBcdFx0XHRcdHRoaXMuX2ZseVRvRnJhbWUgPSByZXF1ZXN0QW5pbUZyYW1lKGZyYW1lLCB0aGlzKTtcclxuXHJcbiAgXHRcdFx0XHR0aGlzLl9tb3ZlKFxyXG4gIFx0XHRcdFx0XHR0aGlzLnVucHJvamVjdChmcm9tLmFkZCh0by5zdWJ0cmFjdChmcm9tKS5tdWx0aXBseUJ5KHUocykgLyB1MSkpLCBzdGFydFpvb20pLFxyXG4gIFx0XHRcdFx0XHR0aGlzLmdldFNjYWxlWm9vbSh3MCAvIHcocyksIHN0YXJ0Wm9vbSksXHJcbiAgXHRcdFx0XHRcdHtmbHlUbzogdHJ1ZX0pO1xyXG5cclxuICBcdFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdFx0dGhpc1xyXG4gIFx0XHRcdFx0XHQuX21vdmUodGFyZ2V0Q2VudGVyLCB0YXJnZXRab29tKVxyXG4gIFx0XHRcdFx0XHQuX21vdmVFbmQodHJ1ZSk7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR0aGlzLl9tb3ZlU3RhcnQodHJ1ZSwgb3B0aW9ucy5ub01vdmVTdGFydCk7XHJcblxyXG4gIFx0XHRmcmFtZS5jYWxsKHRoaXMpO1xyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBmbHlUb0JvdW5kcyhib3VuZHM6IExhdExuZ0JvdW5kcywgb3B0aW9ucz86IGZpdEJvdW5kcyBvcHRpb25zKTogdGhpc1xyXG4gIFx0Ly8gU2V0cyB0aGUgdmlldyBvZiB0aGUgbWFwIHdpdGggYSBzbW9vdGggYW5pbWF0aW9uIGxpa2UgW2BmbHlUb2BdKCNtYXAtZmx5dG8pLFxyXG4gIFx0Ly8gYnV0IHRha2VzIGEgYm91bmRzIHBhcmFtZXRlciBsaWtlIFtgZml0Qm91bmRzYF0oI21hcC1maXRib3VuZHMpLlxyXG4gIFx0Zmx5VG9Cb3VuZHM6IGZ1bmN0aW9uIChib3VuZHMsIG9wdGlvbnMpIHtcclxuICBcdFx0dmFyIHRhcmdldCA9IHRoaXMuX2dldEJvdW5kc0NlbnRlclpvb20oYm91bmRzLCBvcHRpb25zKTtcclxuICBcdFx0cmV0dXJuIHRoaXMuZmx5VG8odGFyZ2V0LmNlbnRlciwgdGFyZ2V0Lnpvb20sIG9wdGlvbnMpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNldE1heEJvdW5kcyhib3VuZHM6IExhdExuZ0JvdW5kcyk6IHRoaXNcclxuICBcdC8vIFJlc3RyaWN0cyB0aGUgbWFwIHZpZXcgdG8gdGhlIGdpdmVuIGJvdW5kcyAoc2VlIHRoZSBbbWF4Qm91bmRzXSgjbWFwLW1heGJvdW5kcykgb3B0aW9uKS5cclxuICBcdHNldE1heEJvdW5kczogZnVuY3Rpb24gKGJvdW5kcykge1xyXG4gIFx0XHRib3VuZHMgPSB0b0xhdExuZ0JvdW5kcyhib3VuZHMpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMubGlzdGVucygnbW92ZWVuZCcsIHRoaXMuX3Bhbkluc2lkZU1heEJvdW5kcykpIHtcclxuICBcdFx0XHR0aGlzLm9mZignbW92ZWVuZCcsIHRoaXMuX3Bhbkluc2lkZU1heEJvdW5kcyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmICghYm91bmRzLmlzVmFsaWQoKSkge1xyXG4gIFx0XHRcdHRoaXMub3B0aW9ucy5tYXhCb3VuZHMgPSBudWxsO1xyXG4gIFx0XHRcdHJldHVybiB0aGlzO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR0aGlzLm9wdGlvbnMubWF4Qm91bmRzID0gYm91bmRzO1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX2xvYWRlZCkge1xyXG4gIFx0XHRcdHRoaXMuX3Bhbkluc2lkZU1heEJvdW5kcygpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcy5vbignbW92ZWVuZCcsIHRoaXMuX3Bhbkluc2lkZU1heEJvdW5kcyk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2V0TWluWm9vbSh6b29tOiBOdW1iZXIpOiB0aGlzXHJcbiAgXHQvLyBTZXRzIHRoZSBsb3dlciBsaW1pdCBmb3IgdGhlIGF2YWlsYWJsZSB6b29tIGxldmVscyAoc2VlIHRoZSBbbWluWm9vbV0oI21hcC1taW56b29tKSBvcHRpb24pLlxyXG4gIFx0c2V0TWluWm9vbTogZnVuY3Rpb24gKHpvb20pIHtcclxuICBcdFx0dmFyIG9sZFpvb20gPSB0aGlzLm9wdGlvbnMubWluWm9vbTtcclxuICBcdFx0dGhpcy5vcHRpb25zLm1pblpvb20gPSB6b29tO1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX2xvYWRlZCAmJiBvbGRab29tICE9PSB6b29tKSB7XHJcbiAgXHRcdFx0dGhpcy5maXJlKCd6b29tbGV2ZWxzY2hhbmdlJyk7XHJcblxyXG4gIFx0XHRcdGlmICh0aGlzLmdldFpvb20oKSA8IHRoaXMub3B0aW9ucy5taW5ab29tKSB7XHJcbiAgXHRcdFx0XHRyZXR1cm4gdGhpcy5zZXRab29tKHpvb20pO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG5cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2V0TWF4Wm9vbSh6b29tOiBOdW1iZXIpOiB0aGlzXHJcbiAgXHQvLyBTZXRzIHRoZSB1cHBlciBsaW1pdCBmb3IgdGhlIGF2YWlsYWJsZSB6b29tIGxldmVscyAoc2VlIHRoZSBbbWF4Wm9vbV0oI21hcC1tYXh6b29tKSBvcHRpb24pLlxyXG4gIFx0c2V0TWF4Wm9vbTogZnVuY3Rpb24gKHpvb20pIHtcclxuICBcdFx0dmFyIG9sZFpvb20gPSB0aGlzLm9wdGlvbnMubWF4Wm9vbTtcclxuICBcdFx0dGhpcy5vcHRpb25zLm1heFpvb20gPSB6b29tO1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX2xvYWRlZCAmJiBvbGRab29tICE9PSB6b29tKSB7XHJcbiAgXHRcdFx0dGhpcy5maXJlKCd6b29tbGV2ZWxzY2hhbmdlJyk7XHJcblxyXG4gIFx0XHRcdGlmICh0aGlzLmdldFpvb20oKSA+IHRoaXMub3B0aW9ucy5tYXhab29tKSB7XHJcbiAgXHRcdFx0XHRyZXR1cm4gdGhpcy5zZXRab29tKHpvb20pO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG5cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgcGFuSW5zaWRlQm91bmRzKGJvdW5kczogTGF0TG5nQm91bmRzLCBvcHRpb25zPzogUGFuIG9wdGlvbnMpOiB0aGlzXHJcbiAgXHQvLyBQYW5zIHRoZSBtYXAgdG8gdGhlIGNsb3Nlc3QgdmlldyB0aGF0IHdvdWxkIGxpZSBpbnNpZGUgdGhlIGdpdmVuIGJvdW5kcyAoaWYgaXQncyBub3QgYWxyZWFkeSksIGNvbnRyb2xsaW5nIHRoZSBhbmltYXRpb24gdXNpbmcgdGhlIG9wdGlvbnMgc3BlY2lmaWMsIGlmIGFueS5cclxuICBcdHBhbkluc2lkZUJvdW5kczogZnVuY3Rpb24gKGJvdW5kcywgb3B0aW9ucykge1xyXG4gIFx0XHR0aGlzLl9lbmZvcmNpbmdCb3VuZHMgPSB0cnVlO1xyXG4gIFx0XHR2YXIgY2VudGVyID0gdGhpcy5nZXRDZW50ZXIoKSxcclxuICBcdFx0ICAgIG5ld0NlbnRlciA9IHRoaXMuX2xpbWl0Q2VudGVyKGNlbnRlciwgdGhpcy5fem9vbSwgdG9MYXRMbmdCb3VuZHMoYm91bmRzKSk7XHJcblxyXG4gIFx0XHRpZiAoIWNlbnRlci5lcXVhbHMobmV3Q2VudGVyKSkge1xyXG4gIFx0XHRcdHRoaXMucGFuVG8obmV3Q2VudGVyLCBvcHRpb25zKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5fZW5mb3JjaW5nQm91bmRzID0gZmFsc2U7XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHBhbkluc2lkZShsYXRsbmc6IExhdExuZywgb3B0aW9ucz86IHBhZGRpbmcgb3B0aW9ucyk6IHRoaXNcclxuICBcdC8vIFBhbnMgdGhlIG1hcCB0aGUgbWluaW11bSBhbW91bnQgdG8gbWFrZSB0aGUgYGxhdGxuZ2AgdmlzaWJsZS4gVXNlXHJcbiAgXHQvLyBwYWRkaW5nIG9wdGlvbnMgdG8gZml0IHRoZSBkaXNwbGF5IHRvIG1vcmUgcmVzdHJpY3RlZCBib3VuZHMuXHJcbiAgXHQvLyBJZiBgbGF0bG5nYCBpcyBhbHJlYWR5IHdpdGhpbiB0aGUgKG9wdGlvbmFsbHkgcGFkZGVkKSBkaXNwbGF5IGJvdW5kcyxcclxuICBcdC8vIHRoZSBtYXAgd2lsbCBub3QgYmUgcGFubmVkLlxyXG4gIFx0cGFuSW5zaWRlOiBmdW5jdGlvbiAobGF0bG5nLCBvcHRpb25zKSB7XHJcbiAgXHRcdG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xyXG5cclxuICBcdFx0dmFyIHBhZGRpbmdUTCA9IHRvUG9pbnQob3B0aW9ucy5wYWRkaW5nVG9wTGVmdCB8fCBvcHRpb25zLnBhZGRpbmcgfHwgWzAsIDBdKSxcclxuICBcdFx0ICAgIHBhZGRpbmdCUiA9IHRvUG9pbnQob3B0aW9ucy5wYWRkaW5nQm90dG9tUmlnaHQgfHwgb3B0aW9ucy5wYWRkaW5nIHx8IFswLCAwXSksXHJcbiAgXHRcdCAgICBwaXhlbENlbnRlciA9IHRoaXMucHJvamVjdCh0aGlzLmdldENlbnRlcigpKSxcclxuICBcdFx0ICAgIHBpeGVsUG9pbnQgPSB0aGlzLnByb2plY3QobGF0bG5nKSxcclxuICBcdFx0ICAgIHBpeGVsQm91bmRzID0gdGhpcy5nZXRQaXhlbEJvdW5kcygpLFxyXG4gIFx0XHQgICAgcGFkZGVkQm91bmRzID0gdG9Cb3VuZHMoW3BpeGVsQm91bmRzLm1pbi5hZGQocGFkZGluZ1RMKSwgcGl4ZWxCb3VuZHMubWF4LnN1YnRyYWN0KHBhZGRpbmdCUildKSxcclxuICBcdFx0ICAgIHBhZGRlZFNpemUgPSBwYWRkZWRCb3VuZHMuZ2V0U2l6ZSgpO1xyXG5cclxuICBcdFx0aWYgKCFwYWRkZWRCb3VuZHMuY29udGFpbnMocGl4ZWxQb2ludCkpIHtcclxuICBcdFx0XHR0aGlzLl9lbmZvcmNpbmdCb3VuZHMgPSB0cnVlO1xyXG4gIFx0XHRcdHZhciBjZW50ZXJPZmZzZXQgPSBwaXhlbFBvaW50LnN1YnRyYWN0KHBhZGRlZEJvdW5kcy5nZXRDZW50ZXIoKSk7XHJcbiAgXHRcdFx0dmFyIG9mZnNldCA9IHBhZGRlZEJvdW5kcy5leHRlbmQocGl4ZWxQb2ludCkuZ2V0U2l6ZSgpLnN1YnRyYWN0KHBhZGRlZFNpemUpO1xyXG4gIFx0XHRcdHBpeGVsQ2VudGVyLnggKz0gY2VudGVyT2Zmc2V0LnggPCAwID8gLW9mZnNldC54IDogb2Zmc2V0Lng7XHJcbiAgXHRcdFx0cGl4ZWxDZW50ZXIueSArPSBjZW50ZXJPZmZzZXQueSA8IDAgPyAtb2Zmc2V0LnkgOiBvZmZzZXQueTtcclxuICBcdFx0XHR0aGlzLnBhblRvKHRoaXMudW5wcm9qZWN0KHBpeGVsQ2VudGVyKSwgb3B0aW9ucyk7XHJcbiAgXHRcdFx0dGhpcy5fZW5mb3JjaW5nQm91bmRzID0gZmFsc2U7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgaW52YWxpZGF0ZVNpemUob3B0aW9uczogWm9vbS9wYW4gb3B0aW9ucyk6IHRoaXNcclxuICBcdC8vIENoZWNrcyBpZiB0aGUgbWFwIGNvbnRhaW5lciBzaXplIGNoYW5nZWQgYW5kIHVwZGF0ZXMgdGhlIG1hcCBpZiBzbyDigJRcclxuICBcdC8vIGNhbGwgaXQgYWZ0ZXIgeW91J3ZlIGNoYW5nZWQgdGhlIG1hcCBzaXplIGR5bmFtaWNhbGx5LCBhbHNvIGFuaW1hdGluZ1xyXG4gIFx0Ly8gcGFuIGJ5IGRlZmF1bHQuIElmIGBvcHRpb25zLnBhbmAgaXMgYGZhbHNlYCwgcGFubmluZyB3aWxsIG5vdCBvY2N1ci5cclxuICBcdC8vIElmIGBvcHRpb25zLmRlYm91bmNlTW92ZWVuZGAgaXMgYHRydWVgLCBpdCB3aWxsIGRlbGF5IGBtb3ZlZW5kYCBldmVudCBzb1xyXG4gIFx0Ly8gdGhhdCBpdCBkb2Vzbid0IGhhcHBlbiBvZnRlbiBldmVuIGlmIHRoZSBtZXRob2QgaXMgY2FsbGVkIG1hbnlcclxuICBcdC8vIHRpbWVzIGluIGEgcm93LlxyXG5cclxuICBcdC8vIEBhbHRlcm5hdGl2ZVxyXG4gIFx0Ly8gQG1ldGhvZCBpbnZhbGlkYXRlU2l6ZShhbmltYXRlOiBCb29sZWFuKTogdGhpc1xyXG4gIFx0Ly8gQ2hlY2tzIGlmIHRoZSBtYXAgY29udGFpbmVyIHNpemUgY2hhbmdlZCBhbmQgdXBkYXRlcyB0aGUgbWFwIGlmIHNvIOKAlFxyXG4gIFx0Ly8gY2FsbCBpdCBhZnRlciB5b3UndmUgY2hhbmdlZCB0aGUgbWFwIHNpemUgZHluYW1pY2FsbHksIGFsc28gYW5pbWF0aW5nXHJcbiAgXHQvLyBwYW4gYnkgZGVmYXVsdC5cclxuICBcdGludmFsaWRhdGVTaXplOiBmdW5jdGlvbiAob3B0aW9ucykge1xyXG4gIFx0XHRpZiAoIXRoaXMuX2xvYWRlZCkgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuICBcdFx0b3B0aW9ucyA9IGV4dGVuZCh7XHJcbiAgXHRcdFx0YW5pbWF0ZTogZmFsc2UsXHJcbiAgXHRcdFx0cGFuOiB0cnVlXHJcbiAgXHRcdH0sIG9wdGlvbnMgPT09IHRydWUgPyB7YW5pbWF0ZTogdHJ1ZX0gOiBvcHRpb25zKTtcclxuXHJcbiAgXHRcdHZhciBvbGRTaXplID0gdGhpcy5nZXRTaXplKCk7XHJcbiAgXHRcdHRoaXMuX3NpemVDaGFuZ2VkID0gdHJ1ZTtcclxuICBcdFx0dGhpcy5fbGFzdENlbnRlciA9IG51bGw7XHJcblxyXG4gIFx0XHR2YXIgbmV3U2l6ZSA9IHRoaXMuZ2V0U2l6ZSgpLFxyXG4gIFx0XHQgICAgb2xkQ2VudGVyID0gb2xkU2l6ZS5kaXZpZGVCeSgyKS5yb3VuZCgpLFxyXG4gIFx0XHQgICAgbmV3Q2VudGVyID0gbmV3U2l6ZS5kaXZpZGVCeSgyKS5yb3VuZCgpLFxyXG4gIFx0XHQgICAgb2Zmc2V0ID0gb2xkQ2VudGVyLnN1YnRyYWN0KG5ld0NlbnRlcik7XHJcblxyXG4gIFx0XHRpZiAoIW9mZnNldC54ICYmICFvZmZzZXQueSkgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuICBcdFx0aWYgKG9wdGlvbnMuYW5pbWF0ZSAmJiBvcHRpb25zLnBhbikge1xyXG4gIFx0XHRcdHRoaXMucGFuQnkob2Zmc2V0KTtcclxuXHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0aWYgKG9wdGlvbnMucGFuKSB7XHJcbiAgXHRcdFx0XHR0aGlzLl9yYXdQYW5CeShvZmZzZXQpO1xyXG4gIFx0XHRcdH1cclxuXHJcbiAgXHRcdFx0dGhpcy5maXJlKCdtb3ZlJyk7XHJcblxyXG4gIFx0XHRcdGlmIChvcHRpb25zLmRlYm91bmNlTW92ZWVuZCkge1xyXG4gIFx0XHRcdFx0Y2xlYXJUaW1lb3V0KHRoaXMuX3NpemVUaW1lcik7XHJcbiAgXHRcdFx0XHR0aGlzLl9zaXplVGltZXIgPSBzZXRUaW1lb3V0KGJpbmQodGhpcy5maXJlLCB0aGlzLCAnbW92ZWVuZCcpLCAyMDApO1xyXG4gIFx0XHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0XHR0aGlzLmZpcmUoJ21vdmVlbmQnKTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdC8vIEBzZWN0aW9uIE1hcCBzdGF0ZSBjaGFuZ2UgZXZlbnRzXHJcbiAgXHRcdC8vIEBldmVudCByZXNpemU6IFJlc2l6ZUV2ZW50XHJcbiAgXHRcdC8vIEZpcmVkIHdoZW4gdGhlIG1hcCBpcyByZXNpemVkLlxyXG4gIFx0XHRyZXR1cm4gdGhpcy5maXJlKCdyZXNpemUnLCB7XHJcbiAgXHRcdFx0b2xkU2l6ZTogb2xkU2l6ZSxcclxuICBcdFx0XHRuZXdTaXplOiBuZXdTaXplXHJcbiAgXHRcdH0pO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAc2VjdGlvbiBNZXRob2RzIGZvciBtb2RpZnlpbmcgbWFwIHN0YXRlXHJcbiAgXHQvLyBAbWV0aG9kIHN0b3AoKTogdGhpc1xyXG4gIFx0Ly8gU3RvcHMgdGhlIGN1cnJlbnRseSBydW5uaW5nIGBwYW5Ub2Agb3IgYGZseVRvYCBhbmltYXRpb24sIGlmIGFueS5cclxuICBcdHN0b3A6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dGhpcy5zZXRab29tKHRoaXMuX2xpbWl0Wm9vbSh0aGlzLl96b29tKSk7XHJcbiAgXHRcdGlmICghdGhpcy5vcHRpb25zLnpvb21TbmFwKSB7XHJcbiAgXHRcdFx0dGhpcy5maXJlKCd2aWV3cmVzZXQnKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcy5fc3RvcCgpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAc2VjdGlvbiBHZW9sb2NhdGlvbiBtZXRob2RzXHJcbiAgXHQvLyBAbWV0aG9kIGxvY2F0ZShvcHRpb25zPzogTG9jYXRlIG9wdGlvbnMpOiB0aGlzXHJcbiAgXHQvLyBUcmllcyB0byBsb2NhdGUgdGhlIHVzZXIgdXNpbmcgdGhlIEdlb2xvY2F0aW9uIEFQSSwgZmlyaW5nIGEgW2Bsb2NhdGlvbmZvdW5kYF0oI21hcC1sb2NhdGlvbmZvdW5kKVxyXG4gIFx0Ly8gZXZlbnQgd2l0aCBsb2NhdGlvbiBkYXRhIG9uIHN1Y2Nlc3Mgb3IgYSBbYGxvY2F0aW9uZXJyb3JgXSgjbWFwLWxvY2F0aW9uZXJyb3IpIGV2ZW50IG9uIGZhaWx1cmUsXHJcbiAgXHQvLyBhbmQgb3B0aW9uYWxseSBzZXRzIHRoZSBtYXAgdmlldyB0byB0aGUgdXNlcidzIGxvY2F0aW9uIHdpdGggcmVzcGVjdCB0b1xyXG4gIFx0Ly8gZGV0ZWN0aW9uIGFjY3VyYWN5IChvciB0byB0aGUgd29ybGQgdmlldyBpZiBnZW9sb2NhdGlvbiBmYWlsZWQpLlxyXG4gIFx0Ly8gTm90ZSB0aGF0LCBpZiB5b3VyIHBhZ2UgZG9lc24ndCB1c2UgSFRUUFMsIHRoaXMgbWV0aG9kIHdpbGwgZmFpbCBpblxyXG4gIFx0Ly8gbW9kZXJuIGJyb3dzZXJzIChbQ2hyb21lIDUwIGFuZCBuZXdlcl0oaHR0cHM6Ly9zaXRlcy5nb29nbGUuY29tL2EvY2hyb21pdW0ub3JnL2Rldi9Ib21lL2Nocm9taXVtLXNlY3VyaXR5L2RlcHJlY2F0aW5nLXBvd2VyZnVsLWZlYXR1cmVzLW9uLWluc2VjdXJlLW9yaWdpbnMpKVxyXG4gIFx0Ly8gU2VlIGBMb2NhdGUgb3B0aW9uc2AgZm9yIG1vcmUgZGV0YWlscy5cclxuICBcdGxvY2F0ZTogZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuXHJcbiAgXHRcdG9wdGlvbnMgPSB0aGlzLl9sb2NhdGVPcHRpb25zID0gZXh0ZW5kKHtcclxuICBcdFx0XHR0aW1lb3V0OiAxMDAwMCxcclxuICBcdFx0XHR3YXRjaDogZmFsc2VcclxuICBcdFx0XHQvLyBzZXRWaWV3OiBmYWxzZVxyXG4gIFx0XHRcdC8vIG1heFpvb206IDxOdW1iZXI+XHJcbiAgXHRcdFx0Ly8gbWF4aW11bUFnZTogMFxyXG4gIFx0XHRcdC8vIGVuYWJsZUhpZ2hBY2N1cmFjeTogZmFsc2VcclxuICBcdFx0fSwgb3B0aW9ucyk7XHJcblxyXG4gIFx0XHRpZiAoISgnZ2VvbG9jYXRpb24nIGluIG5hdmlnYXRvcikpIHtcclxuICBcdFx0XHR0aGlzLl9oYW5kbGVHZW9sb2NhdGlvbkVycm9yKHtcclxuICBcdFx0XHRcdGNvZGU6IDAsXHJcbiAgXHRcdFx0XHRtZXNzYWdlOiAnR2VvbG9jYXRpb24gbm90IHN1cHBvcnRlZC4nXHJcbiAgXHRcdFx0fSk7XHJcbiAgXHRcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHZhciBvblJlc3BvbnNlID0gYmluZCh0aGlzLl9oYW5kbGVHZW9sb2NhdGlvblJlc3BvbnNlLCB0aGlzKSxcclxuICBcdFx0ICAgIG9uRXJyb3IgPSBiaW5kKHRoaXMuX2hhbmRsZUdlb2xvY2F0aW9uRXJyb3IsIHRoaXMpO1xyXG5cclxuICBcdFx0aWYgKG9wdGlvbnMud2F0Y2gpIHtcclxuICBcdFx0XHR0aGlzLl9sb2NhdGlvbldhdGNoSWQgPVxyXG4gIFx0XHRcdCAgICAgICAgbmF2aWdhdG9yLmdlb2xvY2F0aW9uLndhdGNoUG9zaXRpb24ob25SZXNwb25zZSwgb25FcnJvciwgb3B0aW9ucyk7XHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0bmF2aWdhdG9yLmdlb2xvY2F0aW9uLmdldEN1cnJlbnRQb3NpdGlvbihvblJlc3BvbnNlLCBvbkVycm9yLCBvcHRpb25zKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBzdG9wTG9jYXRlKCk6IHRoaXNcclxuICBcdC8vIFN0b3BzIHdhdGNoaW5nIGxvY2F0aW9uIHByZXZpb3VzbHkgaW5pdGlhdGVkIGJ5IGBtYXAubG9jYXRlKHt3YXRjaDogdHJ1ZX0pYFxyXG4gIFx0Ly8gYW5kIGFib3J0cyByZXNldHRpbmcgdGhlIG1hcCB2aWV3IGlmIG1hcC5sb2NhdGUgd2FzIGNhbGxlZCB3aXRoXHJcbiAgXHQvLyBge3NldFZpZXc6IHRydWV9YC5cclxuICBcdHN0b3BMb2NhdGU6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKG5hdmlnYXRvci5nZW9sb2NhdGlvbiAmJiBuYXZpZ2F0b3IuZ2VvbG9jYXRpb24uY2xlYXJXYXRjaCkge1xyXG4gIFx0XHRcdG5hdmlnYXRvci5nZW9sb2NhdGlvbi5jbGVhcldhdGNoKHRoaXMuX2xvY2F0aW9uV2F0Y2hJZCk7XHJcbiAgXHRcdH1cclxuICBcdFx0aWYgKHRoaXMuX2xvY2F0ZU9wdGlvbnMpIHtcclxuICBcdFx0XHR0aGlzLl9sb2NhdGVPcHRpb25zLnNldFZpZXcgPSBmYWxzZTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0X2hhbmRsZUdlb2xvY2F0aW9uRXJyb3I6IGZ1bmN0aW9uIChlcnJvcikge1xyXG4gIFx0XHRpZiAoIXRoaXMuX2NvbnRhaW5lci5fbGVhZmxldF9pZCkgeyByZXR1cm47IH1cclxuXHJcbiAgXHRcdHZhciBjID0gZXJyb3IuY29kZSxcclxuICBcdFx0ICAgIG1lc3NhZ2UgPSBlcnJvci5tZXNzYWdlIHx8XHJcbiAgXHRcdCAgICAgICAgICAgIChjID09PSAxID8gJ3Blcm1pc3Npb24gZGVuaWVkJyA6XHJcbiAgXHRcdCAgICAgICAgICAgIChjID09PSAyID8gJ3Bvc2l0aW9uIHVuYXZhaWxhYmxlJyA6ICd0aW1lb3V0JykpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX2xvY2F0ZU9wdGlvbnMuc2V0VmlldyAmJiAhdGhpcy5fbG9hZGVkKSB7XHJcbiAgXHRcdFx0dGhpcy5maXRXb3JsZCgpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHQvLyBAc2VjdGlvbiBMb2NhdGlvbiBldmVudHNcclxuICBcdFx0Ly8gQGV2ZW50IGxvY2F0aW9uZXJyb3I6IEVycm9yRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiBnZW9sb2NhdGlvbiAodXNpbmcgdGhlIFtgbG9jYXRlYF0oI21hcC1sb2NhdGUpIG1ldGhvZCkgZmFpbGVkLlxyXG4gIFx0XHR0aGlzLmZpcmUoJ2xvY2F0aW9uZXJyb3InLCB7XHJcbiAgXHRcdFx0Y29kZTogYyxcclxuICBcdFx0XHRtZXNzYWdlOiAnR2VvbG9jYXRpb24gZXJyb3I6ICcgKyBtZXNzYWdlICsgJy4nXHJcbiAgXHRcdH0pO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfaGFuZGxlR2VvbG9jYXRpb25SZXNwb25zZTogZnVuY3Rpb24gKHBvcykge1xyXG4gIFx0XHRpZiAoIXRoaXMuX2NvbnRhaW5lci5fbGVhZmxldF9pZCkgeyByZXR1cm47IH1cclxuXHJcbiAgXHRcdHZhciBsYXQgPSBwb3MuY29vcmRzLmxhdGl0dWRlLFxyXG4gIFx0XHQgICAgbG5nID0gcG9zLmNvb3Jkcy5sb25naXR1ZGUsXHJcbiAgXHRcdCAgICBsYXRsbmcgPSBuZXcgTGF0TG5nKGxhdCwgbG5nKSxcclxuICBcdFx0ICAgIGJvdW5kcyA9IGxhdGxuZy50b0JvdW5kcyhwb3MuY29vcmRzLmFjY3VyYWN5ICogMiksXHJcbiAgXHRcdCAgICBvcHRpb25zID0gdGhpcy5fbG9jYXRlT3B0aW9ucztcclxuXHJcbiAgXHRcdGlmIChvcHRpb25zLnNldFZpZXcpIHtcclxuICBcdFx0XHR2YXIgem9vbSA9IHRoaXMuZ2V0Qm91bmRzWm9vbShib3VuZHMpO1xyXG4gIFx0XHRcdHRoaXMuc2V0VmlldyhsYXRsbmcsIG9wdGlvbnMubWF4Wm9vbSA/IE1hdGgubWluKHpvb20sIG9wdGlvbnMubWF4Wm9vbSkgOiB6b29tKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dmFyIGRhdGEgPSB7XHJcbiAgXHRcdFx0bGF0bG5nOiBsYXRsbmcsXHJcbiAgXHRcdFx0Ym91bmRzOiBib3VuZHMsXHJcbiAgXHRcdFx0dGltZXN0YW1wOiBwb3MudGltZXN0YW1wXHJcbiAgXHRcdH07XHJcblxyXG4gIFx0XHRmb3IgKHZhciBpIGluIHBvcy5jb29yZHMpIHtcclxuICBcdFx0XHRpZiAodHlwZW9mIHBvcy5jb29yZHNbaV0gPT09ICdudW1iZXInKSB7XHJcbiAgXHRcdFx0XHRkYXRhW2ldID0gcG9zLmNvb3Jkc1tpXTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdC8vIEBldmVudCBsb2NhdGlvbmZvdW5kOiBMb2NhdGlvbkV2ZW50XHJcbiAgXHRcdC8vIEZpcmVkIHdoZW4gZ2VvbG9jYXRpb24gKHVzaW5nIHRoZSBbYGxvY2F0ZWBdKCNtYXAtbG9jYXRlKSBtZXRob2QpXHJcbiAgXHRcdC8vIHdlbnQgc3VjY2Vzc2Z1bGx5LlxyXG4gIFx0XHR0aGlzLmZpcmUoJ2xvY2F0aW9uZm91bmQnLCBkYXRhKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gVE9ETyBBcHByb3ByaWF0ZSBkb2NzIHNlY3Rpb24/XHJcbiAgXHQvLyBAc2VjdGlvbiBPdGhlciBNZXRob2RzXHJcbiAgXHQvLyBAbWV0aG9kIGFkZEhhbmRsZXIobmFtZTogU3RyaW5nLCBIYW5kbGVyQ2xhc3M6IEZ1bmN0aW9uKTogdGhpc1xyXG4gIFx0Ly8gQWRkcyBhIG5ldyBgSGFuZGxlcmAgdG8gdGhlIG1hcCwgZ2l2ZW4gaXRzIG5hbWUgYW5kIGNvbnN0cnVjdG9yIGZ1bmN0aW9uLlxyXG4gIFx0YWRkSGFuZGxlcjogZnVuY3Rpb24gKG5hbWUsIEhhbmRsZXJDbGFzcykge1xyXG4gIFx0XHRpZiAoIUhhbmRsZXJDbGFzcykgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuICBcdFx0dmFyIGhhbmRsZXIgPSB0aGlzW25hbWVdID0gbmV3IEhhbmRsZXJDbGFzcyh0aGlzKTtcclxuXHJcbiAgXHRcdHRoaXMuX2hhbmRsZXJzLnB1c2goaGFuZGxlcik7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5vcHRpb25zW25hbWVdKSB7XHJcbiAgXHRcdFx0aGFuZGxlci5lbmFibGUoKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgcmVtb3ZlKCk6IHRoaXNcclxuICBcdC8vIERlc3Ryb3lzIHRoZSBtYXAgYW5kIGNsZWFycyBhbGwgcmVsYXRlZCBldmVudCBsaXN0ZW5lcnMuXHJcbiAgXHRyZW1vdmU6IGZ1bmN0aW9uICgpIHtcclxuXHJcbiAgXHRcdHRoaXMuX2luaXRFdmVudHModHJ1ZSk7XHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMubWF4Qm91bmRzKSB7IHRoaXMub2ZmKCdtb3ZlZW5kJywgdGhpcy5fcGFuSW5zaWRlTWF4Qm91bmRzKTsgfVxyXG5cclxuICBcdFx0aWYgKHRoaXMuX2NvbnRhaW5lcklkICE9PSB0aGlzLl9jb250YWluZXIuX2xlYWZsZXRfaWQpIHtcclxuICBcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ01hcCBjb250YWluZXIgaXMgYmVpbmcgcmV1c2VkIGJ5IGFub3RoZXIgaW5zdGFuY2UnKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dHJ5IHtcclxuICBcdFx0XHQvLyB0aHJvd3MgZXJyb3IgaW4gSUU2LThcclxuICBcdFx0XHRkZWxldGUgdGhpcy5fY29udGFpbmVyLl9sZWFmbGV0X2lkO1xyXG4gIFx0XHRcdGRlbGV0ZSB0aGlzLl9jb250YWluZXJJZDtcclxuICBcdFx0fSBjYXRjaCAoZSkge1xyXG4gIFx0XHRcdC8qZXNsaW50LWRpc2FibGUgKi9cclxuICBcdFx0XHR0aGlzLl9jb250YWluZXIuX2xlYWZsZXRfaWQgPSB1bmRlZmluZWQ7XHJcbiAgXHRcdFx0LyogZXNsaW50LWVuYWJsZSAqL1xyXG4gIFx0XHRcdHRoaXMuX2NvbnRhaW5lcklkID0gdW5kZWZpbmVkO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fbG9jYXRpb25XYXRjaElkICE9PSB1bmRlZmluZWQpIHtcclxuICBcdFx0XHR0aGlzLnN0b3BMb2NhdGUoKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5fc3RvcCgpO1xyXG5cclxuICBcdFx0cmVtb3ZlKHRoaXMuX21hcFBhbmUpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX2NsZWFyQ29udHJvbFBvcykge1xyXG4gIFx0XHRcdHRoaXMuX2NsZWFyQ29udHJvbFBvcygpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdGlmICh0aGlzLl9yZXNpemVSZXF1ZXN0KSB7XHJcbiAgXHRcdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX3Jlc2l6ZVJlcXVlc3QpO1xyXG4gIFx0XHRcdHRoaXMuX3Jlc2l6ZVJlcXVlc3QgPSBudWxsO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR0aGlzLl9jbGVhckhhbmRsZXJzKCk7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fbG9hZGVkKSB7XHJcbiAgXHRcdFx0Ly8gQHNlY3Rpb24gTWFwIHN0YXRlIGNoYW5nZSBldmVudHNcclxuICBcdFx0XHQvLyBAZXZlbnQgdW5sb2FkOiBFdmVudFxyXG4gIFx0XHRcdC8vIEZpcmVkIHdoZW4gdGhlIG1hcCBpcyBkZXN0cm95ZWQgd2l0aCBbcmVtb3ZlXSgjbWFwLXJlbW92ZSkgbWV0aG9kLlxyXG4gIFx0XHRcdHRoaXMuZmlyZSgndW5sb2FkJyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHZhciBpO1xyXG4gIFx0XHRmb3IgKGkgaW4gdGhpcy5fbGF5ZXJzKSB7XHJcbiAgXHRcdFx0dGhpcy5fbGF5ZXJzW2ldLnJlbW92ZSgpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdGZvciAoaSBpbiB0aGlzLl9wYW5lcykge1xyXG4gIFx0XHRcdHJlbW92ZSh0aGlzLl9wYW5lc1tpXSk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX2xheWVycyA9IFtdO1xyXG4gIFx0XHR0aGlzLl9wYW5lcyA9IFtdO1xyXG4gIFx0XHRkZWxldGUgdGhpcy5fbWFwUGFuZTtcclxuICBcdFx0ZGVsZXRlIHRoaXMuX3JlbmRlcmVyO1xyXG5cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBzZWN0aW9uIE90aGVyIE1ldGhvZHNcclxuICBcdC8vIEBtZXRob2QgY3JlYXRlUGFuZShuYW1lOiBTdHJpbmcsIGNvbnRhaW5lcj86IEhUTUxFbGVtZW50KTogSFRNTEVsZW1lbnRcclxuICBcdC8vIENyZWF0ZXMgYSBuZXcgW21hcCBwYW5lXSgjbWFwLXBhbmUpIHdpdGggdGhlIGdpdmVuIG5hbWUgaWYgaXQgZG9lc24ndCBleGlzdCBhbHJlYWR5LFxyXG4gIFx0Ly8gdGhlbiByZXR1cm5zIGl0LiBUaGUgcGFuZSBpcyBjcmVhdGVkIGFzIGEgY2hpbGQgb2YgYGNvbnRhaW5lcmAsIG9yXHJcbiAgXHQvLyBhcyBhIGNoaWxkIG9mIHRoZSBtYWluIG1hcCBwYW5lIGlmIG5vdCBzZXQuXHJcbiAgXHRjcmVhdGVQYW5lOiBmdW5jdGlvbiAobmFtZSwgY29udGFpbmVyKSB7XHJcbiAgXHRcdHZhciBjbGFzc05hbWUgPSAnbGVhZmxldC1wYW5lJyArIChuYW1lID8gJyBsZWFmbGV0LScgKyBuYW1lLnJlcGxhY2UoJ1BhbmUnLCAnJykgKyAnLXBhbmUnIDogJycpLFxyXG4gIFx0XHQgICAgcGFuZSA9IGNyZWF0ZSQxKCdkaXYnLCBjbGFzc05hbWUsIGNvbnRhaW5lciB8fCB0aGlzLl9tYXBQYW5lKTtcclxuXHJcbiAgXHRcdGlmIChuYW1lKSB7XHJcbiAgXHRcdFx0dGhpcy5fcGFuZXNbbmFtZV0gPSBwYW5lO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiBwYW5lO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAc2VjdGlvbiBNZXRob2RzIGZvciBHZXR0aW5nIE1hcCBTdGF0ZVxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0Q2VudGVyKCk6IExhdExuZ1xyXG4gIFx0Ly8gUmV0dXJucyB0aGUgZ2VvZ3JhcGhpY2FsIGNlbnRlciBvZiB0aGUgbWFwIHZpZXdcclxuICBcdGdldENlbnRlcjogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR0aGlzLl9jaGVja0lmTG9hZGVkKCk7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fbGFzdENlbnRlciAmJiAhdGhpcy5fbW92ZWQoKSkge1xyXG4gIFx0XHRcdHJldHVybiB0aGlzLl9sYXN0Q2VudGVyLmNsb25lKCk7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXMubGF5ZXJQb2ludFRvTGF0TG5nKHRoaXMuX2dldENlbnRlckxheWVyUG9pbnQoKSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0Wm9vbSgpOiBOdW1iZXJcclxuICBcdC8vIFJldHVybnMgdGhlIGN1cnJlbnQgem9vbSBsZXZlbCBvZiB0aGUgbWFwIHZpZXdcclxuICBcdGdldFpvb206IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuX3pvb207XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0Qm91bmRzKCk6IExhdExuZ0JvdW5kc1xyXG4gIFx0Ly8gUmV0dXJucyB0aGUgZ2VvZ3JhcGhpY2FsIGJvdW5kcyB2aXNpYmxlIGluIHRoZSBjdXJyZW50IG1hcCB2aWV3XHJcbiAgXHRnZXRCb3VuZHM6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dmFyIGJvdW5kcyA9IHRoaXMuZ2V0UGl4ZWxCb3VuZHMoKSxcclxuICBcdFx0ICAgIHN3ID0gdGhpcy51bnByb2plY3QoYm91bmRzLmdldEJvdHRvbUxlZnQoKSksXHJcbiAgXHRcdCAgICBuZSA9IHRoaXMudW5wcm9qZWN0KGJvdW5kcy5nZXRUb3BSaWdodCgpKTtcclxuXHJcbiAgXHRcdHJldHVybiBuZXcgTGF0TG5nQm91bmRzKHN3LCBuZSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0TWluWm9vbSgpOiBOdW1iZXJcclxuICBcdC8vIFJldHVybnMgdGhlIG1pbmltdW0gem9vbSBsZXZlbCBvZiB0aGUgbWFwIChpZiBzZXQgaW4gdGhlIGBtaW5ab29tYCBvcHRpb24gb2YgdGhlIG1hcCBvciBvZiBhbnkgbGF5ZXJzKSwgb3IgYDBgIGJ5IGRlZmF1bHQuXHJcbiAgXHRnZXRNaW5ab29tOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLm9wdGlvbnMubWluWm9vbSA9PT0gdW5kZWZpbmVkID8gdGhpcy5fbGF5ZXJzTWluWm9vbSB8fCAwIDogdGhpcy5vcHRpb25zLm1pblpvb207XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0TWF4Wm9vbSgpOiBOdW1iZXJcclxuICBcdC8vIFJldHVybnMgdGhlIG1heGltdW0gem9vbSBsZXZlbCBvZiB0aGUgbWFwIChpZiBzZXQgaW4gdGhlIGBtYXhab29tYCBvcHRpb24gb2YgdGhlIG1hcCBvciBvZiBhbnkgbGF5ZXJzKS5cclxuICBcdGdldE1heFpvb206IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMub3B0aW9ucy5tYXhab29tID09PSB1bmRlZmluZWQgP1xyXG4gIFx0XHRcdCh0aGlzLl9sYXllcnNNYXhab29tID09PSB1bmRlZmluZWQgPyBJbmZpbml0eSA6IHRoaXMuX2xheWVyc01heFpvb20pIDpcclxuICBcdFx0XHR0aGlzLm9wdGlvbnMubWF4Wm9vbTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRCb3VuZHNab29tKGJvdW5kczogTGF0TG5nQm91bmRzLCBpbnNpZGU/OiBCb29sZWFuLCBwYWRkaW5nPzogUG9pbnQpOiBOdW1iZXJcclxuICBcdC8vIFJldHVybnMgdGhlIG1heGltdW0gem9vbSBsZXZlbCBvbiB3aGljaCB0aGUgZ2l2ZW4gYm91bmRzIGZpdCB0byB0aGUgbWFwXHJcbiAgXHQvLyB2aWV3IGluIGl0cyBlbnRpcmV0eS4gSWYgYGluc2lkZWAgKG9wdGlvbmFsKSBpcyBzZXQgdG8gYHRydWVgLCB0aGUgbWV0aG9kXHJcbiAgXHQvLyBpbnN0ZWFkIHJldHVybnMgdGhlIG1pbmltdW0gem9vbSBsZXZlbCBvbiB3aGljaCB0aGUgbWFwIHZpZXcgZml0cyBpbnRvXHJcbiAgXHQvLyB0aGUgZ2l2ZW4gYm91bmRzIGluIGl0cyBlbnRpcmV0eS5cclxuICBcdGdldEJvdW5kc1pvb206IGZ1bmN0aW9uIChib3VuZHMsIGluc2lkZSwgcGFkZGluZykgeyAvLyAoTGF0TG5nQm91bmRzWywgQm9vbGVhbiwgUG9pbnRdKSAtPiBOdW1iZXJcclxuICBcdFx0Ym91bmRzID0gdG9MYXRMbmdCb3VuZHMoYm91bmRzKTtcclxuICBcdFx0cGFkZGluZyA9IHRvUG9pbnQocGFkZGluZyB8fCBbMCwgMF0pO1xyXG5cclxuICBcdFx0dmFyIHpvb20gPSB0aGlzLmdldFpvb20oKSB8fCAwLFxyXG4gIFx0XHQgICAgbWluID0gdGhpcy5nZXRNaW5ab29tKCksXHJcbiAgXHRcdCAgICBtYXggPSB0aGlzLmdldE1heFpvb20oKSxcclxuICBcdFx0ICAgIG53ID0gYm91bmRzLmdldE5vcnRoV2VzdCgpLFxyXG4gIFx0XHQgICAgc2UgPSBib3VuZHMuZ2V0U291dGhFYXN0KCksXHJcbiAgXHRcdCAgICBzaXplID0gdGhpcy5nZXRTaXplKCkuc3VidHJhY3QocGFkZGluZyksXHJcbiAgXHRcdCAgICBib3VuZHNTaXplID0gdG9Cb3VuZHModGhpcy5wcm9qZWN0KHNlLCB6b29tKSwgdGhpcy5wcm9qZWN0KG53LCB6b29tKSkuZ2V0U2l6ZSgpLFxyXG4gIFx0XHQgICAgc25hcCA9IEJyb3dzZXIuYW55M2QgPyB0aGlzLm9wdGlvbnMuem9vbVNuYXAgOiAxLFxyXG4gIFx0XHQgICAgc2NhbGV4ID0gc2l6ZS54IC8gYm91bmRzU2l6ZS54LFxyXG4gIFx0XHQgICAgc2NhbGV5ID0gc2l6ZS55IC8gYm91bmRzU2l6ZS55LFxyXG4gIFx0XHQgICAgc2NhbGUgPSBpbnNpZGUgPyBNYXRoLm1heChzY2FsZXgsIHNjYWxleSkgOiBNYXRoLm1pbihzY2FsZXgsIHNjYWxleSk7XHJcblxyXG4gIFx0XHR6b29tID0gdGhpcy5nZXRTY2FsZVpvb20oc2NhbGUsIHpvb20pO1xyXG5cclxuICBcdFx0aWYgKHNuYXApIHtcclxuICBcdFx0XHR6b29tID0gTWF0aC5yb3VuZCh6b29tIC8gKHNuYXAgLyAxMDApKSAqIChzbmFwIC8gMTAwKTsgLy8gZG9uJ3QganVtcCBpZiB3aXRoaW4gMSUgb2YgYSBzbmFwIGxldmVsXHJcbiAgXHRcdFx0em9vbSA9IGluc2lkZSA/IE1hdGguY2VpbCh6b29tIC8gc25hcCkgKiBzbmFwIDogTWF0aC5mbG9vcih6b29tIC8gc25hcCkgKiBzbmFwO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gTWF0aC5tYXgobWluLCBNYXRoLm1pbihtYXgsIHpvb20pKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRTaXplKCk6IFBvaW50XHJcbiAgXHQvLyBSZXR1cm5zIHRoZSBjdXJyZW50IHNpemUgb2YgdGhlIG1hcCBjb250YWluZXIgKGluIHBpeGVscykuXHJcbiAgXHRnZXRTaXplOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICghdGhpcy5fc2l6ZSB8fCB0aGlzLl9zaXplQ2hhbmdlZCkge1xyXG4gIFx0XHRcdHRoaXMuX3NpemUgPSBuZXcgUG9pbnQoXHJcbiAgXHRcdFx0XHR0aGlzLl9jb250YWluZXIuY2xpZW50V2lkdGggfHwgMCxcclxuICBcdFx0XHRcdHRoaXMuX2NvbnRhaW5lci5jbGllbnRIZWlnaHQgfHwgMCk7XHJcblxyXG4gIFx0XHRcdHRoaXMuX3NpemVDaGFuZ2VkID0gZmFsc2U7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXMuX3NpemUuY2xvbmUoKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRQaXhlbEJvdW5kcygpOiBCb3VuZHNcclxuICBcdC8vIFJldHVybnMgdGhlIGJvdW5kcyBvZiB0aGUgY3VycmVudCBtYXAgdmlldyBpbiBwcm9qZWN0ZWQgcGl4ZWxcclxuICBcdC8vIGNvb3JkaW5hdGVzIChzb21ldGltZXMgdXNlZnVsIGluIGxheWVyIGFuZCBvdmVybGF5IGltcGxlbWVudGF0aW9ucykuXHJcbiAgXHRnZXRQaXhlbEJvdW5kczogZnVuY3Rpb24gKGNlbnRlciwgem9vbSkge1xyXG4gIFx0XHR2YXIgdG9wTGVmdFBvaW50ID0gdGhpcy5fZ2V0VG9wTGVmdFBvaW50KGNlbnRlciwgem9vbSk7XHJcbiAgXHRcdHJldHVybiBuZXcgQm91bmRzKHRvcExlZnRQb2ludCwgdG9wTGVmdFBvaW50LmFkZCh0aGlzLmdldFNpemUoKSkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBUT0RPOiBDaGVjayBzZW1hbnRpY3MgLSBpc24ndCB0aGUgcGl4ZWwgb3JpZ2luIHRoZSAwLDAgY29vcmQgcmVsYXRpdmUgdG9cclxuICBcdC8vIHRoZSBtYXAgcGFuZT8gXCJsZWZ0IHBvaW50IG9mIHRoZSBtYXAgbGF5ZXJcIiBjYW4gYmUgY29uZnVzaW5nLCBzcGVjaWFsbHlcclxuICBcdC8vIHNpbmNlIHRoZXJlIGNhbiBiZSBuZWdhdGl2ZSBvZmZzZXRzLlxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRQaXhlbE9yaWdpbigpOiBQb2ludFxyXG4gIFx0Ly8gUmV0dXJucyB0aGUgcHJvamVjdGVkIHBpeGVsIGNvb3JkaW5hdGVzIG9mIHRoZSB0b3AgbGVmdCBwb2ludCBvZlxyXG4gIFx0Ly8gdGhlIG1hcCBsYXllciAodXNlZnVsIGluIGN1c3RvbSBsYXllciBhbmQgb3ZlcmxheSBpbXBsZW1lbnRhdGlvbnMpLlxyXG4gIFx0Z2V0UGl4ZWxPcmlnaW46IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dGhpcy5fY2hlY2tJZkxvYWRlZCgpO1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5fcGl4ZWxPcmlnaW47XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0UGl4ZWxXb3JsZEJvdW5kcyh6b29tPzogTnVtYmVyKTogQm91bmRzXHJcbiAgXHQvLyBSZXR1cm5zIHRoZSB3b3JsZCdzIGJvdW5kcyBpbiBwaXhlbCBjb29yZGluYXRlcyBmb3Igem9vbSBsZXZlbCBgem9vbWAuXHJcbiAgXHQvLyBJZiBgem9vbWAgaXMgb21pdHRlZCwgdGhlIG1hcCdzIGN1cnJlbnQgem9vbSBsZXZlbCBpcyB1c2VkLlxyXG4gIFx0Z2V0UGl4ZWxXb3JsZEJvdW5kczogZnVuY3Rpb24gKHpvb20pIHtcclxuICBcdFx0cmV0dXJuIHRoaXMub3B0aW9ucy5jcnMuZ2V0UHJvamVjdGVkQm91bmRzKHpvb20gPT09IHVuZGVmaW5lZCA/IHRoaXMuZ2V0Wm9vbSgpIDogem9vbSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBzZWN0aW9uIE90aGVyIE1ldGhvZHNcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldFBhbmUocGFuZTogU3RyaW5nfEhUTUxFbGVtZW50KTogSFRNTEVsZW1lbnRcclxuICBcdC8vIFJldHVybnMgYSBbbWFwIHBhbmVdKCNtYXAtcGFuZSksIGdpdmVuIGl0cyBuYW1lIG9yIGl0cyBIVE1MIGVsZW1lbnQgKGl0cyBpZGVudGl0eSkuXHJcbiAgXHRnZXRQYW5lOiBmdW5jdGlvbiAocGFuZSkge1xyXG4gIFx0XHRyZXR1cm4gdHlwZW9mIHBhbmUgPT09ICdzdHJpbmcnID8gdGhpcy5fcGFuZXNbcGFuZV0gOiBwYW5lO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldFBhbmVzKCk6IE9iamVjdFxyXG4gIFx0Ly8gUmV0dXJucyBhIHBsYWluIG9iamVjdCBjb250YWluaW5nIHRoZSBuYW1lcyBvZiBhbGwgW3BhbmVzXSgjbWFwLXBhbmUpIGFzIGtleXMgYW5kXHJcbiAgXHQvLyB0aGUgcGFuZXMgYXMgdmFsdWVzLlxyXG4gIFx0Z2V0UGFuZXM6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuX3BhbmVzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldENvbnRhaW5lcjogSFRNTEVsZW1lbnRcclxuICBcdC8vIFJldHVybnMgdGhlIEhUTUwgZWxlbWVudCB0aGF0IGNvbnRhaW5zIHRoZSBtYXAuXHJcbiAgXHRnZXRDb250YWluZXI6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuX2NvbnRhaW5lcjtcclxuICBcdH0sXHJcblxyXG5cclxuICBcdC8vIEBzZWN0aW9uIENvbnZlcnNpb24gTWV0aG9kc1xyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0Wm9vbVNjYWxlKHRvWm9vbTogTnVtYmVyLCBmcm9tWm9vbTogTnVtYmVyKTogTnVtYmVyXHJcbiAgXHQvLyBSZXR1cm5zIHRoZSBzY2FsZSBmYWN0b3IgdG8gYmUgYXBwbGllZCB0byBhIG1hcCB0cmFuc2l0aW9uIGZyb20gem9vbSBsZXZlbFxyXG4gIFx0Ly8gYGZyb21ab29tYCB0byBgdG9ab29tYC4gVXNlZCBpbnRlcm5hbGx5IHRvIGhlbHAgd2l0aCB6b29tIGFuaW1hdGlvbnMuXHJcbiAgXHRnZXRab29tU2NhbGU6IGZ1bmN0aW9uICh0b1pvb20sIGZyb21ab29tKSB7XHJcbiAgXHRcdC8vIFRPRE8gcmVwbGFjZSB3aXRoIHVuaXZlcnNhbCBpbXBsZW1lbnRhdGlvbiBhZnRlciByZWZhY3RvcmluZyBwcm9qZWN0aW9uc1xyXG4gIFx0XHR2YXIgY3JzID0gdGhpcy5vcHRpb25zLmNycztcclxuICBcdFx0ZnJvbVpvb20gPSBmcm9tWm9vbSA9PT0gdW5kZWZpbmVkID8gdGhpcy5fem9vbSA6IGZyb21ab29tO1xyXG4gIFx0XHRyZXR1cm4gY3JzLnNjYWxlKHRvWm9vbSkgLyBjcnMuc2NhbGUoZnJvbVpvb20pO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldFNjYWxlWm9vbShzY2FsZTogTnVtYmVyLCBmcm9tWm9vbTogTnVtYmVyKTogTnVtYmVyXHJcbiAgXHQvLyBSZXR1cm5zIHRoZSB6b29tIGxldmVsIHRoYXQgdGhlIG1hcCB3b3VsZCBlbmQgdXAgYXQsIGlmIGl0IGlzIGF0IGBmcm9tWm9vbWBcclxuICBcdC8vIGxldmVsIGFuZCBldmVyeXRoaW5nIGlzIHNjYWxlZCBieSBhIGZhY3RvciBvZiBgc2NhbGVgLiBJbnZlcnNlIG9mXHJcbiAgXHQvLyBbYGdldFpvb21TY2FsZWBdKCNtYXAtZ2V0Wm9vbVNjYWxlKS5cclxuICBcdGdldFNjYWxlWm9vbTogZnVuY3Rpb24gKHNjYWxlLCBmcm9tWm9vbSkge1xyXG4gIFx0XHR2YXIgY3JzID0gdGhpcy5vcHRpb25zLmNycztcclxuICBcdFx0ZnJvbVpvb20gPSBmcm9tWm9vbSA9PT0gdW5kZWZpbmVkID8gdGhpcy5fem9vbSA6IGZyb21ab29tO1xyXG4gIFx0XHR2YXIgem9vbSA9IGNycy56b29tKHNjYWxlICogY3JzLnNjYWxlKGZyb21ab29tKSk7XHJcbiAgXHRcdHJldHVybiBpc05hTih6b29tKSA/IEluZmluaXR5IDogem9vbTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBwcm9qZWN0KGxhdGxuZzogTGF0TG5nLCB6b29tOiBOdW1iZXIpOiBQb2ludFxyXG4gIFx0Ly8gUHJvamVjdHMgYSBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZSBgTGF0TG5nYCBhY2NvcmRpbmcgdG8gdGhlIHByb2plY3Rpb25cclxuICBcdC8vIG9mIHRoZSBtYXAncyBDUlMsIHRoZW4gc2NhbGVzIGl0IGFjY29yZGluZyB0byBgem9vbWAgYW5kIHRoZSBDUlMnc1xyXG4gIFx0Ly8gYFRyYW5zZm9ybWF0aW9uYC4gVGhlIHJlc3VsdCBpcyBwaXhlbCBjb29yZGluYXRlIHJlbGF0aXZlIHRvXHJcbiAgXHQvLyB0aGUgQ1JTIG9yaWdpbi5cclxuICBcdHByb2plY3Q6IGZ1bmN0aW9uIChsYXRsbmcsIHpvb20pIHtcclxuICBcdFx0em9vbSA9IHpvb20gPT09IHVuZGVmaW5lZCA/IHRoaXMuX3pvb20gOiB6b29tO1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmNycy5sYXRMbmdUb1BvaW50KHRvTGF0TG5nKGxhdGxuZyksIHpvb20pO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHVucHJvamVjdChwb2ludDogUG9pbnQsIHpvb206IE51bWJlcik6IExhdExuZ1xyXG4gIFx0Ly8gSW52ZXJzZSBvZiBbYHByb2plY3RgXSgjbWFwLXByb2plY3QpLlxyXG4gIFx0dW5wcm9qZWN0OiBmdW5jdGlvbiAocG9pbnQsIHpvb20pIHtcclxuICBcdFx0em9vbSA9IHpvb20gPT09IHVuZGVmaW5lZCA/IHRoaXMuX3pvb20gOiB6b29tO1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmNycy5wb2ludFRvTGF0TG5nKHRvUG9pbnQocG9pbnQpLCB6b29tKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBsYXllclBvaW50VG9MYXRMbmcocG9pbnQ6IFBvaW50KTogTGF0TG5nXHJcbiAgXHQvLyBHaXZlbiBhIHBpeGVsIGNvb3JkaW5hdGUgcmVsYXRpdmUgdG8gdGhlIFtvcmlnaW4gcGl4ZWxdKCNtYXAtZ2V0cGl4ZWxvcmlnaW4pLFxyXG4gIFx0Ly8gcmV0dXJucyB0aGUgY29ycmVzcG9uZGluZyBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZSAoZm9yIHRoZSBjdXJyZW50IHpvb20gbGV2ZWwpLlxyXG4gIFx0bGF5ZXJQb2ludFRvTGF0TG5nOiBmdW5jdGlvbiAocG9pbnQpIHtcclxuICBcdFx0dmFyIHByb2plY3RlZFBvaW50ID0gdG9Qb2ludChwb2ludCkuYWRkKHRoaXMuZ2V0UGl4ZWxPcmlnaW4oKSk7XHJcbiAgXHRcdHJldHVybiB0aGlzLnVucHJvamVjdChwcm9qZWN0ZWRQb2ludCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgbGF0TG5nVG9MYXllclBvaW50KGxhdGxuZzogTGF0TG5nKTogUG9pbnRcclxuICBcdC8vIEdpdmVuIGEgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGUsIHJldHVybnMgdGhlIGNvcnJlc3BvbmRpbmcgcGl4ZWwgY29vcmRpbmF0ZVxyXG4gIFx0Ly8gcmVsYXRpdmUgdG8gdGhlIFtvcmlnaW4gcGl4ZWxdKCNtYXAtZ2V0cGl4ZWxvcmlnaW4pLlxyXG4gIFx0bGF0TG5nVG9MYXllclBvaW50OiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcbiAgXHRcdHZhciBwcm9qZWN0ZWRQb2ludCA9IHRoaXMucHJvamVjdCh0b0xhdExuZyhsYXRsbmcpKS5fcm91bmQoKTtcclxuICBcdFx0cmV0dXJuIHByb2plY3RlZFBvaW50Ll9zdWJ0cmFjdCh0aGlzLmdldFBpeGVsT3JpZ2luKCkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHdyYXBMYXRMbmcobGF0bG5nOiBMYXRMbmcpOiBMYXRMbmdcclxuICBcdC8vIFJldHVybnMgYSBgTGF0TG5nYCB3aGVyZSBgbGF0YCBhbmQgYGxuZ2AgaGFzIGJlZW4gd3JhcHBlZCBhY2NvcmRpbmcgdG8gdGhlXHJcbiAgXHQvLyBtYXAncyBDUlMncyBgd3JhcExhdGAgYW5kIGB3cmFwTG5nYCBwcm9wZXJ0aWVzLCBpZiB0aGV5IGFyZSBvdXRzaWRlIHRoZVxyXG4gIFx0Ly8gQ1JTJ3MgYm91bmRzLlxyXG4gIFx0Ly8gQnkgZGVmYXVsdCB0aGlzIG1lYW5zIGxvbmdpdHVkZSBpcyB3cmFwcGVkIGFyb3VuZCB0aGUgZGF0ZWxpbmUgc28gaXRzXHJcbiAgXHQvLyB2YWx1ZSBpcyBiZXR3ZWVuIC0xODAgYW5kICsxODAgZGVncmVlcy5cclxuICBcdHdyYXBMYXRMbmc6IGZ1bmN0aW9uIChsYXRsbmcpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMub3B0aW9ucy5jcnMud3JhcExhdExuZyh0b0xhdExuZyhsYXRsbmcpKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCB3cmFwTGF0TG5nQm91bmRzKGJvdW5kczogTGF0TG5nQm91bmRzKTogTGF0TG5nQm91bmRzXHJcbiAgXHQvLyBSZXR1cm5zIGEgYExhdExuZ0JvdW5kc2Agd2l0aCB0aGUgc2FtZSBzaXplIGFzIHRoZSBnaXZlbiBvbmUsIGVuc3VyaW5nIHRoYXRcclxuICBcdC8vIGl0cyBjZW50ZXIgaXMgd2l0aGluIHRoZSBDUlMncyBib3VuZHMuXHJcbiAgXHQvLyBCeSBkZWZhdWx0IHRoaXMgbWVhbnMgdGhlIGNlbnRlciBsb25naXR1ZGUgaXMgd3JhcHBlZCBhcm91bmQgdGhlIGRhdGVsaW5lIHNvIGl0c1xyXG4gIFx0Ly8gdmFsdWUgaXMgYmV0d2VlbiAtMTgwIGFuZCArMTgwIGRlZ3JlZXMsIGFuZCB0aGUgbWFqb3JpdHkgb2YgdGhlIGJvdW5kc1xyXG4gIFx0Ly8gb3ZlcmxhcHMgdGhlIENSUydzIGJvdW5kcy5cclxuICBcdHdyYXBMYXRMbmdCb3VuZHM6IGZ1bmN0aW9uIChsYXRsbmcpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMub3B0aW9ucy5jcnMud3JhcExhdExuZ0JvdW5kcyh0b0xhdExuZ0JvdW5kcyhsYXRsbmcpKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBkaXN0YW5jZShsYXRsbmcxOiBMYXRMbmcsIGxhdGxuZzI6IExhdExuZyk6IE51bWJlclxyXG4gIFx0Ly8gUmV0dXJucyB0aGUgZGlzdGFuY2UgYmV0d2VlbiB0d28gZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGVzIGFjY29yZGluZyB0b1xyXG4gIFx0Ly8gdGhlIG1hcCdzIENSUy4gQnkgZGVmYXVsdCB0aGlzIG1lYXN1cmVzIGRpc3RhbmNlIGluIG1ldGVycy5cclxuICBcdGRpc3RhbmNlOiBmdW5jdGlvbiAobGF0bG5nMSwgbGF0bG5nMikge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmNycy5kaXN0YW5jZSh0b0xhdExuZyhsYXRsbmcxKSwgdG9MYXRMbmcobGF0bG5nMikpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGNvbnRhaW5lclBvaW50VG9MYXllclBvaW50KHBvaW50OiBQb2ludCk6IFBvaW50XHJcbiAgXHQvLyBHaXZlbiBhIHBpeGVsIGNvb3JkaW5hdGUgcmVsYXRpdmUgdG8gdGhlIG1hcCBjb250YWluZXIsIHJldHVybnMgdGhlIGNvcnJlc3BvbmRpbmdcclxuICBcdC8vIHBpeGVsIGNvb3JkaW5hdGUgcmVsYXRpdmUgdG8gdGhlIFtvcmlnaW4gcGl4ZWxdKCNtYXAtZ2V0cGl4ZWxvcmlnaW4pLlxyXG4gIFx0Y29udGFpbmVyUG9pbnRUb0xheWVyUG9pbnQ6IGZ1bmN0aW9uIChwb2ludCkgeyAvLyAoUG9pbnQpXHJcbiAgXHRcdHJldHVybiB0b1BvaW50KHBvaW50KS5zdWJ0cmFjdCh0aGlzLl9nZXRNYXBQYW5lUG9zKCkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGxheWVyUG9pbnRUb0NvbnRhaW5lclBvaW50KHBvaW50OiBQb2ludCk6IFBvaW50XHJcbiAgXHQvLyBHaXZlbiBhIHBpeGVsIGNvb3JkaW5hdGUgcmVsYXRpdmUgdG8gdGhlIFtvcmlnaW4gcGl4ZWxdKCNtYXAtZ2V0cGl4ZWxvcmlnaW4pLFxyXG4gIFx0Ly8gcmV0dXJucyB0aGUgY29ycmVzcG9uZGluZyBwaXhlbCBjb29yZGluYXRlIHJlbGF0aXZlIHRvIHRoZSBtYXAgY29udGFpbmVyLlxyXG4gIFx0bGF5ZXJQb2ludFRvQ29udGFpbmVyUG9pbnQ6IGZ1bmN0aW9uIChwb2ludCkgeyAvLyAoUG9pbnQpXHJcbiAgXHRcdHJldHVybiB0b1BvaW50KHBvaW50KS5hZGQodGhpcy5fZ2V0TWFwUGFuZVBvcygpKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBjb250YWluZXJQb2ludFRvTGF0TG5nKHBvaW50OiBQb2ludCk6IExhdExuZ1xyXG4gIFx0Ly8gR2l2ZW4gYSBwaXhlbCBjb29yZGluYXRlIHJlbGF0aXZlIHRvIHRoZSBtYXAgY29udGFpbmVyLCByZXR1cm5zXHJcbiAgXHQvLyB0aGUgY29ycmVzcG9uZGluZyBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZSAoZm9yIHRoZSBjdXJyZW50IHpvb20gbGV2ZWwpLlxyXG4gIFx0Y29udGFpbmVyUG9pbnRUb0xhdExuZzogZnVuY3Rpb24gKHBvaW50KSB7XHJcbiAgXHRcdHZhciBsYXllclBvaW50ID0gdGhpcy5jb250YWluZXJQb2ludFRvTGF5ZXJQb2ludCh0b1BvaW50KHBvaW50KSk7XHJcbiAgXHRcdHJldHVybiB0aGlzLmxheWVyUG9pbnRUb0xhdExuZyhsYXllclBvaW50KTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBsYXRMbmdUb0NvbnRhaW5lclBvaW50KGxhdGxuZzogTGF0TG5nKTogUG9pbnRcclxuICBcdC8vIEdpdmVuIGEgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGUsIHJldHVybnMgdGhlIGNvcnJlc3BvbmRpbmcgcGl4ZWwgY29vcmRpbmF0ZVxyXG4gIFx0Ly8gcmVsYXRpdmUgdG8gdGhlIG1hcCBjb250YWluZXIuXHJcbiAgXHRsYXRMbmdUb0NvbnRhaW5lclBvaW50OiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLmxheWVyUG9pbnRUb0NvbnRhaW5lclBvaW50KHRoaXMubGF0TG5nVG9MYXllclBvaW50KHRvTGF0TG5nKGxhdGxuZykpKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBtb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChldjogTW91c2VFdmVudCk6IFBvaW50XHJcbiAgXHQvLyBHaXZlbiBhIE1vdXNlRXZlbnQgb2JqZWN0LCByZXR1cm5zIHRoZSBwaXhlbCBjb29yZGluYXRlIHJlbGF0aXZlIHRvIHRoZVxyXG4gIFx0Ly8gbWFwIGNvbnRhaW5lciB3aGVyZSB0aGUgZXZlbnQgdG9vayBwbGFjZS5cclxuICBcdG1vdXNlRXZlbnRUb0NvbnRhaW5lclBvaW50OiBmdW5jdGlvbiAoZSkge1xyXG4gIFx0XHRyZXR1cm4gZ2V0TW91c2VQb3NpdGlvbihlLCB0aGlzLl9jb250YWluZXIpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIG1vdXNlRXZlbnRUb0xheWVyUG9pbnQoZXY6IE1vdXNlRXZlbnQpOiBQb2ludFxyXG4gIFx0Ly8gR2l2ZW4gYSBNb3VzZUV2ZW50IG9iamVjdCwgcmV0dXJucyB0aGUgcGl4ZWwgY29vcmRpbmF0ZSByZWxhdGl2ZSB0b1xyXG4gIFx0Ly8gdGhlIFtvcmlnaW4gcGl4ZWxdKCNtYXAtZ2V0cGl4ZWxvcmlnaW4pIHdoZXJlIHRoZSBldmVudCB0b29rIHBsYWNlLlxyXG4gIFx0bW91c2VFdmVudFRvTGF5ZXJQb2ludDogZnVuY3Rpb24gKGUpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuY29udGFpbmVyUG9pbnRUb0xheWVyUG9pbnQodGhpcy5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlKSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgbW91c2VFdmVudFRvTGF0TG5nKGV2OiBNb3VzZUV2ZW50KTogTGF0TG5nXHJcbiAgXHQvLyBHaXZlbiBhIE1vdXNlRXZlbnQgb2JqZWN0LCByZXR1cm5zIGdlb2dyYXBoaWNhbCBjb29yZGluYXRlIHdoZXJlIHRoZVxyXG4gIFx0Ly8gZXZlbnQgdG9vayBwbGFjZS5cclxuICBcdG1vdXNlRXZlbnRUb0xhdExuZzogZnVuY3Rpb24gKGUpIHsgLy8gKE1vdXNlRXZlbnQpXHJcbiAgXHRcdHJldHVybiB0aGlzLmxheWVyUG9pbnRUb0xhdExuZyh0aGlzLm1vdXNlRXZlbnRUb0xheWVyUG9pbnQoZSkpO1xyXG4gIFx0fSxcclxuXHJcblxyXG4gIFx0Ly8gbWFwIGluaXRpYWxpemF0aW9uIG1ldGhvZHNcclxuXHJcbiAgXHRfaW5pdENvbnRhaW5lcjogZnVuY3Rpb24gKGlkKSB7XHJcbiAgXHRcdHZhciBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXIgPSBnZXQoaWQpO1xyXG5cclxuICBcdFx0aWYgKCFjb250YWluZXIpIHtcclxuICBcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ01hcCBjb250YWluZXIgbm90IGZvdW5kLicpO1xyXG4gIFx0XHR9IGVsc2UgaWYgKGNvbnRhaW5lci5fbGVhZmxldF9pZCkge1xyXG4gIFx0XHRcdHRocm93IG5ldyBFcnJvcignTWFwIGNvbnRhaW5lciBpcyBhbHJlYWR5IGluaXRpYWxpemVkLicpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRvbihjb250YWluZXIsICdzY3JvbGwnLCB0aGlzLl9vblNjcm9sbCwgdGhpcyk7XHJcbiAgXHRcdHRoaXMuX2NvbnRhaW5lcklkID0gc3RhbXAoY29udGFpbmVyKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X2luaXRMYXlvdXQ6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dmFyIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRhaW5lcjtcclxuXHJcbiAgXHRcdHRoaXMuX2ZhZGVBbmltYXRlZCA9IHRoaXMub3B0aW9ucy5mYWRlQW5pbWF0aW9uICYmIEJyb3dzZXIuYW55M2Q7XHJcblxyXG4gIFx0XHRhZGRDbGFzcyhjb250YWluZXIsICdsZWFmbGV0LWNvbnRhaW5lcicgK1xyXG4gIFx0XHRcdChCcm93c2VyLnRvdWNoID8gJyBsZWFmbGV0LXRvdWNoJyA6ICcnKSArXHJcbiAgXHRcdFx0KEJyb3dzZXIucmV0aW5hID8gJyBsZWFmbGV0LXJldGluYScgOiAnJykgK1xyXG4gIFx0XHRcdChCcm93c2VyLmllbHQ5ID8gJyBsZWFmbGV0LW9sZGllJyA6ICcnKSArXHJcbiAgXHRcdFx0KEJyb3dzZXIuc2FmYXJpID8gJyBsZWFmbGV0LXNhZmFyaScgOiAnJykgK1xyXG4gIFx0XHRcdCh0aGlzLl9mYWRlQW5pbWF0ZWQgPyAnIGxlYWZsZXQtZmFkZS1hbmltJyA6ICcnKSk7XHJcblxyXG4gIFx0XHR2YXIgcG9zaXRpb24gPSBnZXRTdHlsZShjb250YWluZXIsICdwb3NpdGlvbicpO1xyXG5cclxuICBcdFx0aWYgKHBvc2l0aW9uICE9PSAnYWJzb2x1dGUnICYmIHBvc2l0aW9uICE9PSAncmVsYXRpdmUnICYmIHBvc2l0aW9uICE9PSAnZml4ZWQnICYmIHBvc2l0aW9uICE9PSAnc3RpY2t5Jykge1xyXG4gIFx0XHRcdGNvbnRhaW5lci5zdHlsZS5wb3NpdGlvbiA9ICdyZWxhdGl2ZSc7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX2luaXRQYW5lcygpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX2luaXRDb250cm9sUG9zKSB7XHJcbiAgXHRcdFx0dGhpcy5faW5pdENvbnRyb2xQb3MoKTtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHRfaW5pdFBhbmVzOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHZhciBwYW5lcyA9IHRoaXMuX3BhbmVzID0ge307XHJcbiAgXHRcdHRoaXMuX3BhbmVSZW5kZXJlcnMgPSB7fTtcclxuXHJcbiAgXHRcdC8vIEBzZWN0aW9uXHJcbiAgXHRcdC8vXHJcbiAgXHRcdC8vIFBhbmVzIGFyZSBET00gZWxlbWVudHMgdXNlZCB0byBjb250cm9sIHRoZSBvcmRlcmluZyBvZiBsYXllcnMgb24gdGhlIG1hcC4gWW91XHJcbiAgXHRcdC8vIGNhbiBhY2Nlc3MgcGFuZXMgd2l0aCBbYG1hcC5nZXRQYW5lYF0oI21hcC1nZXRwYW5lKSBvclxyXG4gIFx0XHQvLyBbYG1hcC5nZXRQYW5lc2BdKCNtYXAtZ2V0cGFuZXMpIG1ldGhvZHMuIE5ldyBwYW5lcyBjYW4gYmUgY3JlYXRlZCB3aXRoIHRoZVxyXG4gIFx0XHQvLyBbYG1hcC5jcmVhdGVQYW5lYF0oI21hcC1jcmVhdGVwYW5lKSBtZXRob2QuXHJcbiAgXHRcdC8vXHJcbiAgXHRcdC8vIEV2ZXJ5IG1hcCBoYXMgdGhlIGZvbGxvd2luZyBkZWZhdWx0IHBhbmVzIHRoYXQgZGlmZmVyIG9ubHkgaW4gekluZGV4LlxyXG4gIFx0XHQvL1xyXG4gIFx0XHQvLyBAcGFuZSBtYXBQYW5lOiBIVE1MRWxlbWVudCA9ICdhdXRvJ1xyXG4gIFx0XHQvLyBQYW5lIHRoYXQgY29udGFpbnMgYWxsIG90aGVyIG1hcCBwYW5lc1xyXG5cclxuICBcdFx0dGhpcy5fbWFwUGFuZSA9IHRoaXMuY3JlYXRlUGFuZSgnbWFwUGFuZScsIHRoaXMuX2NvbnRhaW5lcik7XHJcbiAgXHRcdHNldFBvc2l0aW9uKHRoaXMuX21hcFBhbmUsIG5ldyBQb2ludCgwLCAwKSk7XHJcblxyXG4gIFx0XHQvLyBAcGFuZSB0aWxlUGFuZTogSFRNTEVsZW1lbnQgPSAyMDBcclxuICBcdFx0Ly8gUGFuZSBmb3IgYEdyaWRMYXllcmBzIGFuZCBgVGlsZUxheWVyYHNcclxuICBcdFx0dGhpcy5jcmVhdGVQYW5lKCd0aWxlUGFuZScpO1xyXG4gIFx0XHQvLyBAcGFuZSBvdmVybGF5UGFuZTogSFRNTEVsZW1lbnQgPSA0MDBcclxuICBcdFx0Ly8gUGFuZSBmb3IgdmVjdG9ycyAoYFBhdGhgcywgbGlrZSBgUG9seWxpbmVgcyBhbmQgYFBvbHlnb25gcyksIGBJbWFnZU92ZXJsYXlgcyBhbmQgYFZpZGVvT3ZlcmxheWBzXHJcbiAgXHRcdHRoaXMuY3JlYXRlUGFuZSgnb3ZlcmxheVBhbmUnKTtcclxuICBcdFx0Ly8gQHBhbmUgc2hhZG93UGFuZTogSFRNTEVsZW1lbnQgPSA1MDBcclxuICBcdFx0Ly8gUGFuZSBmb3Igb3ZlcmxheSBzaGFkb3dzIChlLmcuIGBNYXJrZXJgIHNoYWRvd3MpXHJcbiAgXHRcdHRoaXMuY3JlYXRlUGFuZSgnc2hhZG93UGFuZScpO1xyXG4gIFx0XHQvLyBAcGFuZSBtYXJrZXJQYW5lOiBIVE1MRWxlbWVudCA9IDYwMFxyXG4gIFx0XHQvLyBQYW5lIGZvciBgSWNvbmBzIG9mIGBNYXJrZXJgc1xyXG4gIFx0XHR0aGlzLmNyZWF0ZVBhbmUoJ21hcmtlclBhbmUnKTtcclxuICBcdFx0Ly8gQHBhbmUgdG9vbHRpcFBhbmU6IEhUTUxFbGVtZW50ID0gNjUwXHJcbiAgXHRcdC8vIFBhbmUgZm9yIGBUb29sdGlwYHMuXHJcbiAgXHRcdHRoaXMuY3JlYXRlUGFuZSgndG9vbHRpcFBhbmUnKTtcclxuICBcdFx0Ly8gQHBhbmUgcG9wdXBQYW5lOiBIVE1MRWxlbWVudCA9IDcwMFxyXG4gIFx0XHQvLyBQYW5lIGZvciBgUG9wdXBgcy5cclxuICBcdFx0dGhpcy5jcmVhdGVQYW5lKCdwb3B1cFBhbmUnKTtcclxuXHJcbiAgXHRcdGlmICghdGhpcy5vcHRpb25zLm1hcmtlclpvb21BbmltYXRpb24pIHtcclxuICBcdFx0XHRhZGRDbGFzcyhwYW5lcy5tYXJrZXJQYW5lLCAnbGVhZmxldC16b29tLWhpZGUnKTtcclxuICBcdFx0XHRhZGRDbGFzcyhwYW5lcy5zaGFkb3dQYW5lLCAnbGVhZmxldC16b29tLWhpZGUnKTtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcblxyXG4gIFx0Ly8gcHJpdmF0ZSBtZXRob2RzIHRoYXQgbW9kaWZ5IG1hcCBzdGF0ZVxyXG5cclxuICBcdC8vIEBzZWN0aW9uIE1hcCBzdGF0ZSBjaGFuZ2UgZXZlbnRzXHJcbiAgXHRfcmVzZXRWaWV3OiBmdW5jdGlvbiAoY2VudGVyLCB6b29tLCBub01vdmVTdGFydCkge1xyXG4gIFx0XHRzZXRQb3NpdGlvbih0aGlzLl9tYXBQYW5lLCBuZXcgUG9pbnQoMCwgMCkpO1xyXG5cclxuICBcdFx0dmFyIGxvYWRpbmcgPSAhdGhpcy5fbG9hZGVkO1xyXG4gIFx0XHR0aGlzLl9sb2FkZWQgPSB0cnVlO1xyXG4gIFx0XHR6b29tID0gdGhpcy5fbGltaXRab29tKHpvb20pO1xyXG5cclxuICBcdFx0dGhpcy5maXJlKCd2aWV3cHJlcmVzZXQnKTtcclxuXHJcbiAgXHRcdHZhciB6b29tQ2hhbmdlZCA9IHRoaXMuX3pvb20gIT09IHpvb207XHJcbiAgXHRcdHRoaXNcclxuICBcdFx0XHQuX21vdmVTdGFydCh6b29tQ2hhbmdlZCwgbm9Nb3ZlU3RhcnQpXHJcbiAgXHRcdFx0Ll9tb3ZlKGNlbnRlciwgem9vbSlcclxuICBcdFx0XHQuX21vdmVFbmQoem9vbUNoYW5nZWQpO1xyXG5cclxuICBcdFx0Ly8gQGV2ZW50IHZpZXdyZXNldDogRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbWFwIG5lZWRzIHRvIHJlZHJhdyBpdHMgY29udGVudCAodGhpcyB1c3VhbGx5IGhhcHBlbnNcclxuICBcdFx0Ly8gb24gbWFwIHpvb20gb3IgbG9hZCkuIFZlcnkgdXNlZnVsIGZvciBjcmVhdGluZyBjdXN0b20gb3ZlcmxheXMuXHJcbiAgXHRcdHRoaXMuZmlyZSgndmlld3Jlc2V0Jyk7XHJcblxyXG4gIFx0XHQvLyBAZXZlbnQgbG9hZDogRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbWFwIGlzIGluaXRpYWxpemVkICh3aGVuIGl0cyBjZW50ZXIgYW5kIHpvb20gYXJlIHNldFxyXG4gIFx0XHQvLyBmb3IgdGhlIGZpcnN0IHRpbWUpLlxyXG4gIFx0XHRpZiAobG9hZGluZykge1xyXG4gIFx0XHRcdHRoaXMuZmlyZSgnbG9hZCcpO1xyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdF9tb3ZlU3RhcnQ6IGZ1bmN0aW9uICh6b29tQ2hhbmdlZCwgbm9Nb3ZlU3RhcnQpIHtcclxuICBcdFx0Ly8gQGV2ZW50IHpvb21zdGFydDogRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbWFwIHpvb20gaXMgYWJvdXQgdG8gY2hhbmdlIChlLmcuIGJlZm9yZSB6b29tIGFuaW1hdGlvbikuXHJcbiAgXHRcdC8vIEBldmVudCBtb3Zlc3RhcnQ6IEV2ZW50XHJcbiAgXHRcdC8vIEZpcmVkIHdoZW4gdGhlIHZpZXcgb2YgdGhlIG1hcCBzdGFydHMgY2hhbmdpbmcgKGUuZy4gdXNlciBzdGFydHMgZHJhZ2dpbmcgdGhlIG1hcCkuXHJcbiAgXHRcdGlmICh6b29tQ2hhbmdlZCkge1xyXG4gIFx0XHRcdHRoaXMuZmlyZSgnem9vbXN0YXJ0Jyk7XHJcbiAgXHRcdH1cclxuICBcdFx0aWYgKCFub01vdmVTdGFydCkge1xyXG4gIFx0XHRcdHRoaXMuZmlyZSgnbW92ZXN0YXJ0Jyk7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9tb3ZlOiBmdW5jdGlvbiAoY2VudGVyLCB6b29tLCBkYXRhLCBzdXByZXNzRXZlbnQpIHtcclxuICBcdFx0aWYgKHpvb20gPT09IHVuZGVmaW5lZCkge1xyXG4gIFx0XHRcdHpvb20gPSB0aGlzLl96b29tO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHZhciB6b29tQ2hhbmdlZCA9IHRoaXMuX3pvb20gIT09IHpvb207XHJcblxyXG4gIFx0XHR0aGlzLl96b29tID0gem9vbTtcclxuICBcdFx0dGhpcy5fbGFzdENlbnRlciA9IGNlbnRlcjtcclxuICBcdFx0dGhpcy5fcGl4ZWxPcmlnaW4gPSB0aGlzLl9nZXROZXdQaXhlbE9yaWdpbihjZW50ZXIpO1xyXG5cclxuICBcdFx0aWYgKCFzdXByZXNzRXZlbnQpIHtcclxuICBcdFx0XHQvLyBAZXZlbnQgem9vbTogRXZlbnRcclxuICBcdFx0XHQvLyBGaXJlZCByZXBlYXRlZGx5IGR1cmluZyBhbnkgY2hhbmdlIGluIHpvb20gbGV2ZWwsXHJcbiAgXHRcdFx0Ly8gaW5jbHVkaW5nIHpvb20gYW5kIGZseSBhbmltYXRpb25zLlxyXG4gIFx0XHRcdGlmICh6b29tQ2hhbmdlZCB8fCAoZGF0YSAmJiBkYXRhLnBpbmNoKSkge1x0Ly8gQWx3YXlzIGZpcmUgJ3pvb20nIGlmIHBpbmNoaW5nIGJlY2F1c2UgIzM1MzBcclxuICBcdFx0XHRcdHRoaXMuZmlyZSgnem9vbScsIGRhdGEpO1xyXG4gIFx0XHRcdH1cclxuXHJcbiAgXHRcdFx0Ly8gQGV2ZW50IG1vdmU6IEV2ZW50XHJcbiAgXHRcdFx0Ly8gRmlyZWQgcmVwZWF0ZWRseSBkdXJpbmcgYW55IG1vdmVtZW50IG9mIHRoZSBtYXAsXHJcbiAgXHRcdFx0Ly8gaW5jbHVkaW5nIHBhbiBhbmQgZmx5IGFuaW1hdGlvbnMuXHJcbiAgXHRcdFx0dGhpcy5maXJlKCdtb3ZlJywgZGF0YSk7XHJcbiAgXHRcdH0gZWxzZSBpZiAoZGF0YSAmJiBkYXRhLnBpbmNoKSB7XHQvLyBBbHdheXMgZmlyZSAnem9vbScgaWYgcGluY2hpbmcgYmVjYXVzZSAjMzUzMFxyXG4gIFx0XHRcdHRoaXMuZmlyZSgnem9vbScsIGRhdGEpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfbW92ZUVuZDogZnVuY3Rpb24gKHpvb21DaGFuZ2VkKSB7XHJcbiAgXHRcdC8vIEBldmVudCB6b29tZW5kOiBFdmVudFxyXG4gIFx0XHQvLyBGaXJlZCB3aGVuIHRoZSBtYXAgem9vbSBjaGFuZ2VkLCBhZnRlciBhbnkgYW5pbWF0aW9ucy5cclxuICBcdFx0aWYgKHpvb21DaGFuZ2VkKSB7XHJcbiAgXHRcdFx0dGhpcy5maXJlKCd6b29tZW5kJyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdC8vIEBldmVudCBtb3ZlZW5kOiBFdmVudFxyXG4gIFx0XHQvLyBGaXJlZCB3aGVuIHRoZSBjZW50ZXIgb2YgdGhlIG1hcCBzdG9wcyBjaGFuZ2luZ1xyXG4gIFx0XHQvLyAoZS5nLiB1c2VyIHN0b3BwZWQgZHJhZ2dpbmcgdGhlIG1hcCBvciBhZnRlciBub24tY2VudGVyZWQgem9vbSkuXHJcbiAgXHRcdHJldHVybiB0aGlzLmZpcmUoJ21vdmVlbmQnKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X3N0b3A6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX2ZseVRvRnJhbWUpO1xyXG4gIFx0XHRpZiAodGhpcy5fcGFuQW5pbSkge1xyXG4gIFx0XHRcdHRoaXMuX3BhbkFuaW0uc3RvcCgpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfcmF3UGFuQnk6IGZ1bmN0aW9uIChvZmZzZXQpIHtcclxuICBcdFx0c2V0UG9zaXRpb24odGhpcy5fbWFwUGFuZSwgdGhpcy5fZ2V0TWFwUGFuZVBvcygpLnN1YnRyYWN0KG9mZnNldCkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfZ2V0Wm9vbVNwYW46IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuZ2V0TWF4Wm9vbSgpIC0gdGhpcy5nZXRNaW5ab29tKCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9wYW5JbnNpZGVNYXhCb3VuZHM6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKCF0aGlzLl9lbmZvcmNpbmdCb3VuZHMpIHtcclxuICBcdFx0XHR0aGlzLnBhbkluc2lkZUJvdW5kcyh0aGlzLm9wdGlvbnMubWF4Qm91bmRzKTtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHRfY2hlY2tJZkxvYWRlZDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRpZiAoIXRoaXMuX2xvYWRlZCkge1xyXG4gIFx0XHRcdHRocm93IG5ldyBFcnJvcignU2V0IG1hcCBjZW50ZXIgYW5kIHpvb20gZmlyc3QuJyk7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gRE9NIGV2ZW50IGhhbmRsaW5nXHJcblxyXG4gIFx0Ly8gQHNlY3Rpb24gSW50ZXJhY3Rpb24gZXZlbnRzXHJcbiAgXHRfaW5pdEV2ZW50czogZnVuY3Rpb24gKHJlbW92ZSkge1xyXG4gIFx0XHR0aGlzLl90YXJnZXRzID0ge307XHJcbiAgXHRcdHRoaXMuX3RhcmdldHNbc3RhbXAodGhpcy5fY29udGFpbmVyKV0gPSB0aGlzO1xyXG5cclxuICBcdFx0dmFyIG9uT2ZmID0gcmVtb3ZlID8gb2ZmIDogb247XHJcblxyXG4gIFx0XHQvLyBAZXZlbnQgY2xpY2s6IE1vdXNlRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgdXNlciBjbGlja3MgKG9yIHRhcHMpIHRoZSBtYXAuXHJcbiAgXHRcdC8vIEBldmVudCBkYmxjbGljazogTW91c2VFdmVudFxyXG4gIFx0XHQvLyBGaXJlZCB3aGVuIHRoZSB1c2VyIGRvdWJsZS1jbGlja3MgKG9yIGRvdWJsZS10YXBzKSB0aGUgbWFwLlxyXG4gIFx0XHQvLyBAZXZlbnQgbW91c2Vkb3duOiBNb3VzZUV2ZW50XHJcbiAgXHRcdC8vIEZpcmVkIHdoZW4gdGhlIHVzZXIgcHVzaGVzIHRoZSBtb3VzZSBidXR0b24gb24gdGhlIG1hcC5cclxuICBcdFx0Ly8gQGV2ZW50IG1vdXNldXA6IE1vdXNlRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgdXNlciByZWxlYXNlcyB0aGUgbW91c2UgYnV0dG9uIG9uIHRoZSBtYXAuXHJcbiAgXHRcdC8vIEBldmVudCBtb3VzZW92ZXI6IE1vdXNlRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbW91c2UgZW50ZXJzIHRoZSBtYXAuXHJcbiAgXHRcdC8vIEBldmVudCBtb3VzZW91dDogTW91c2VFdmVudFxyXG4gIFx0XHQvLyBGaXJlZCB3aGVuIHRoZSBtb3VzZSBsZWF2ZXMgdGhlIG1hcC5cclxuICBcdFx0Ly8gQGV2ZW50IG1vdXNlbW92ZTogTW91c2VFdmVudFxyXG4gIFx0XHQvLyBGaXJlZCB3aGlsZSB0aGUgbW91c2UgbW92ZXMgb3ZlciB0aGUgbWFwLlxyXG4gIFx0XHQvLyBAZXZlbnQgY29udGV4dG1lbnU6IE1vdXNlRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgdXNlciBwdXNoZXMgdGhlIHJpZ2h0IG1vdXNlIGJ1dHRvbiBvbiB0aGUgbWFwLCBwcmV2ZW50c1xyXG4gIFx0XHQvLyBkZWZhdWx0IGJyb3dzZXIgY29udGV4dCBtZW51IGZyb20gc2hvd2luZyBpZiB0aGVyZSBhcmUgbGlzdGVuZXJzIG9uXHJcbiAgXHRcdC8vIHRoaXMgZXZlbnQuIEFsc28gZmlyZWQgb24gbW9iaWxlIHdoZW4gdGhlIHVzZXIgaG9sZHMgYSBzaW5nbGUgdG91Y2hcclxuICBcdFx0Ly8gZm9yIGEgc2Vjb25kIChhbHNvIGNhbGxlZCBsb25nIHByZXNzKS5cclxuICBcdFx0Ly8gQGV2ZW50IGtleXByZXNzOiBLZXlib2FyZEV2ZW50XHJcbiAgXHRcdC8vIEZpcmVkIHdoZW4gdGhlIHVzZXIgcHJlc3NlcyBhIGtleSBmcm9tIHRoZSBrZXlib2FyZCB0aGF0IHByb2R1Y2VzIGEgY2hhcmFjdGVyIHZhbHVlIHdoaWxlIHRoZSBtYXAgaXMgZm9jdXNlZC5cclxuICBcdFx0Ly8gQGV2ZW50IGtleWRvd246IEtleWJvYXJkRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgdXNlciBwcmVzc2VzIGEga2V5IGZyb20gdGhlIGtleWJvYXJkIHdoaWxlIHRoZSBtYXAgaXMgZm9jdXNlZC4gVW5saWtlIHRoZSBga2V5cHJlc3NgIGV2ZW50LFxyXG4gIFx0XHQvLyB0aGUgYGtleWRvd25gIGV2ZW50IGlzIGZpcmVkIGZvciBrZXlzIHRoYXQgcHJvZHVjZSBhIGNoYXJhY3RlciB2YWx1ZSBhbmQgZm9yIGtleXNcclxuICBcdFx0Ly8gdGhhdCBkbyBub3QgcHJvZHVjZSBhIGNoYXJhY3RlciB2YWx1ZS5cclxuICBcdFx0Ly8gQGV2ZW50IGtleXVwOiBLZXlib2FyZEV2ZW50XHJcbiAgXHRcdC8vIEZpcmVkIHdoZW4gdGhlIHVzZXIgcmVsZWFzZXMgYSBrZXkgZnJvbSB0aGUga2V5Ym9hcmQgd2hpbGUgdGhlIG1hcCBpcyBmb2N1c2VkLlxyXG4gIFx0XHRvbk9mZih0aGlzLl9jb250YWluZXIsICdjbGljayBkYmxjbGljayBtb3VzZWRvd24gbW91c2V1cCAnICtcclxuICBcdFx0XHQnbW91c2VvdmVyIG1vdXNlb3V0IG1vdXNlbW92ZSBjb250ZXh0bWVudSBrZXlwcmVzcyBrZXlkb3duIGtleXVwJywgdGhpcy5faGFuZGxlRE9NRXZlbnQsIHRoaXMpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy50cmFja1Jlc2l6ZSkge1xyXG4gIFx0XHRcdG9uT2ZmKHdpbmRvdywgJ3Jlc2l6ZScsIHRoaXMuX29uUmVzaXplLCB0aGlzKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0aWYgKEJyb3dzZXIuYW55M2QgJiYgdGhpcy5vcHRpb25zLnRyYW5zZm9ybTNETGltaXQpIHtcclxuICBcdFx0XHQocmVtb3ZlID8gdGhpcy5vZmYgOiB0aGlzLm9uKS5jYWxsKHRoaXMsICdtb3ZlZW5kJywgdGhpcy5fb25Nb3ZlRW5kKTtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHRfb25SZXNpemU6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX3Jlc2l6ZVJlcXVlc3QpO1xyXG4gIFx0XHR0aGlzLl9yZXNpemVSZXF1ZXN0ID0gcmVxdWVzdEFuaW1GcmFtZShcclxuICBcdFx0ICAgICAgICBmdW5jdGlvbiAoKSB7IHRoaXMuaW52YWxpZGF0ZVNpemUoe2RlYm91bmNlTW92ZWVuZDogdHJ1ZX0pOyB9LCB0aGlzKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X29uU2Nyb2xsOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHRoaXMuX2NvbnRhaW5lci5zY3JvbGxUb3AgID0gMDtcclxuICBcdFx0dGhpcy5fY29udGFpbmVyLnNjcm9sbExlZnQgPSAwO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfb25Nb3ZlRW5kOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHZhciBwb3MgPSB0aGlzLl9nZXRNYXBQYW5lUG9zKCk7XHJcbiAgXHRcdGlmIChNYXRoLm1heChNYXRoLmFicyhwb3MueCksIE1hdGguYWJzKHBvcy55KSkgPj0gdGhpcy5vcHRpb25zLnRyYW5zZm9ybTNETGltaXQpIHtcclxuICBcdFx0XHQvLyBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD0xMjAzODczIGJ1dCBXZWJraXQgYWxzbyBoYXZlXHJcbiAgXHRcdFx0Ly8gYSBwaXhlbCBvZmZzZXQgb24gdmVyeSBoaWdoIHZhbHVlcywgc2VlOiBodHRwczovL2pzZmlkZGxlLm5ldC9kZzZyNWhoYi9cclxuICBcdFx0XHR0aGlzLl9yZXNldFZpZXcodGhpcy5nZXRDZW50ZXIoKSwgdGhpcy5nZXRab29tKCkpO1xyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdF9maW5kRXZlbnRUYXJnZXRzOiBmdW5jdGlvbiAoZSwgdHlwZSkge1xyXG4gIFx0XHR2YXIgdGFyZ2V0cyA9IFtdLFxyXG4gIFx0XHQgICAgdGFyZ2V0LFxyXG4gIFx0XHQgICAgaXNIb3ZlciA9IHR5cGUgPT09ICdtb3VzZW91dCcgfHwgdHlwZSA9PT0gJ21vdXNlb3ZlcicsXHJcbiAgXHRcdCAgICBzcmMgPSBlLnRhcmdldCB8fCBlLnNyY0VsZW1lbnQsXHJcbiAgXHRcdCAgICBkcmFnZ2luZyA9IGZhbHNlO1xyXG5cclxuICBcdFx0d2hpbGUgKHNyYykge1xyXG4gIFx0XHRcdHRhcmdldCA9IHRoaXMuX3RhcmdldHNbc3RhbXAoc3JjKV07XHJcbiAgXHRcdFx0aWYgKHRhcmdldCAmJiAodHlwZSA9PT0gJ2NsaWNrJyB8fCB0eXBlID09PSAncHJlY2xpY2snKSAmJiB0aGlzLl9kcmFnZ2FibGVNb3ZlZCh0YXJnZXQpKSB7XHJcbiAgXHRcdFx0XHQvLyBQcmV2ZW50IGZpcmluZyBjbGljayBhZnRlciB5b3UganVzdCBkcmFnZ2VkIGFuIG9iamVjdC5cclxuICBcdFx0XHRcdGRyYWdnaW5nID0gdHJ1ZTtcclxuICBcdFx0XHRcdGJyZWFrO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0XHRpZiAodGFyZ2V0ICYmIHRhcmdldC5saXN0ZW5zKHR5cGUsIHRydWUpKSB7XHJcbiAgXHRcdFx0XHRpZiAoaXNIb3ZlciAmJiAhaXNFeHRlcm5hbFRhcmdldChzcmMsIGUpKSB7IGJyZWFrOyB9XHJcbiAgXHRcdFx0XHR0YXJnZXRzLnB1c2godGFyZ2V0KTtcclxuICBcdFx0XHRcdGlmIChpc0hvdmVyKSB7IGJyZWFrOyB9XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHRcdGlmIChzcmMgPT09IHRoaXMuX2NvbnRhaW5lcikgeyBicmVhazsgfVxyXG4gIFx0XHRcdHNyYyA9IHNyYy5wYXJlbnROb2RlO1xyXG4gIFx0XHR9XHJcbiAgXHRcdGlmICghdGFyZ2V0cy5sZW5ndGggJiYgIWRyYWdnaW5nICYmICFpc0hvdmVyICYmIHRoaXMubGlzdGVucyh0eXBlLCB0cnVlKSkge1xyXG4gIFx0XHRcdHRhcmdldHMgPSBbdGhpc107XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRhcmdldHM7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9pc0NsaWNrRGlzYWJsZWQ6IGZ1bmN0aW9uIChlbCkge1xyXG4gIFx0XHR3aGlsZSAoZWwgJiYgZWwgIT09IHRoaXMuX2NvbnRhaW5lcikge1xyXG4gIFx0XHRcdGlmIChlbFsnX2xlYWZsZXRfZGlzYWJsZV9jbGljayddKSB7IHJldHVybiB0cnVlOyB9XHJcbiAgXHRcdFx0ZWwgPSBlbC5wYXJlbnROb2RlO1xyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdF9oYW5kbGVET01FdmVudDogZnVuY3Rpb24gKGUpIHtcclxuICBcdFx0dmFyIGVsID0gKGUudGFyZ2V0IHx8IGUuc3JjRWxlbWVudCk7XHJcbiAgXHRcdGlmICghdGhpcy5fbG9hZGVkIHx8IGVsWydfbGVhZmxldF9kaXNhYmxlX2V2ZW50cyddIHx8IGUudHlwZSA9PT0gJ2NsaWNrJyAmJiB0aGlzLl9pc0NsaWNrRGlzYWJsZWQoZWwpKSB7XHJcbiAgXHRcdFx0cmV0dXJuO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgdHlwZSA9IGUudHlwZTtcclxuXHJcbiAgXHRcdGlmICh0eXBlID09PSAnbW91c2Vkb3duJykge1xyXG4gIFx0XHRcdC8vIHByZXZlbnRzIG91dGxpbmUgd2hlbiBjbGlja2luZyBvbiBrZXlib2FyZC1mb2N1c2FibGUgZWxlbWVudFxyXG4gIFx0XHRcdHByZXZlbnRPdXRsaW5lKGVsKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5fZmlyZURPTUV2ZW50KGUsIHR5cGUpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfbW91c2VFdmVudHM6IFsnY2xpY2snLCAnZGJsY2xpY2snLCAnbW91c2VvdmVyJywgJ21vdXNlb3V0JywgJ2NvbnRleHRtZW51J10sXHJcblxyXG4gIFx0X2ZpcmVET01FdmVudDogZnVuY3Rpb24gKGUsIHR5cGUsIGNhbnZhc1RhcmdldHMpIHtcclxuXHJcbiAgXHRcdGlmIChlLnR5cGUgPT09ICdjbGljaycpIHtcclxuICBcdFx0XHQvLyBGaXJlIGEgc3ludGhldGljICdwcmVjbGljaycgZXZlbnQgd2hpY2ggcHJvcGFnYXRlcyB1cCAobWFpbmx5IGZvciBjbG9zaW5nIHBvcHVwcykuXHJcbiAgXHRcdFx0Ly8gQGV2ZW50IHByZWNsaWNrOiBNb3VzZUV2ZW50XHJcbiAgXHRcdFx0Ly8gRmlyZWQgYmVmb3JlIG1vdXNlIGNsaWNrIG9uIHRoZSBtYXAgKHNvbWV0aW1lcyB1c2VmdWwgd2hlbiB5b3VcclxuICBcdFx0XHQvLyB3YW50IHNvbWV0aGluZyB0byBoYXBwZW4gb24gY2xpY2sgYmVmb3JlIGFueSBleGlzdGluZyBjbGlja1xyXG4gIFx0XHRcdC8vIGhhbmRsZXJzIHN0YXJ0IHJ1bm5pbmcpLlxyXG4gIFx0XHRcdHZhciBzeW50aCA9IGV4dGVuZCh7fSwgZSk7XHJcbiAgXHRcdFx0c3ludGgudHlwZSA9ICdwcmVjbGljayc7XHJcbiAgXHRcdFx0dGhpcy5fZmlyZURPTUV2ZW50KHN5bnRoLCBzeW50aC50eXBlLCBjYW52YXNUYXJnZXRzKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gRmluZCB0aGUgbGF5ZXIgdGhlIGV2ZW50IGlzIHByb3BhZ2F0aW5nIGZyb20gYW5kIGl0cyBwYXJlbnRzLlxyXG4gIFx0XHR2YXIgdGFyZ2V0cyA9IHRoaXMuX2ZpbmRFdmVudFRhcmdldHMoZSwgdHlwZSk7XHJcblxyXG4gIFx0XHRpZiAoY2FudmFzVGFyZ2V0cykge1xyXG4gIFx0XHRcdHZhciBmaWx0ZXJlZCA9IFtdOyAvLyBwaWNrIG9ubHkgdGFyZ2V0cyB3aXRoIGxpc3RlbmVyc1xyXG4gIFx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgY2FudmFzVGFyZ2V0cy5sZW5ndGg7IGkrKykge1xyXG4gIFx0XHRcdFx0aWYgKGNhbnZhc1RhcmdldHNbaV0ubGlzdGVucyh0eXBlLCB0cnVlKSkge1xyXG4gIFx0XHRcdFx0XHRmaWx0ZXJlZC5wdXNoKGNhbnZhc1RhcmdldHNbaV0pO1xyXG4gIFx0XHRcdFx0fVxyXG4gIFx0XHRcdH1cclxuICBcdFx0XHR0YXJnZXRzID0gZmlsdGVyZWQuY29uY2F0KHRhcmdldHMpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAoIXRhcmdldHMubGVuZ3RoKSB7IHJldHVybjsgfVxyXG5cclxuICBcdFx0aWYgKHR5cGUgPT09ICdjb250ZXh0bWVudScpIHtcclxuICBcdFx0XHRwcmV2ZW50RGVmYXVsdChlKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dmFyIHRhcmdldCA9IHRhcmdldHNbMF07XHJcbiAgXHRcdHZhciBkYXRhID0ge1xyXG4gIFx0XHRcdG9yaWdpbmFsRXZlbnQ6IGVcclxuICBcdFx0fTtcclxuXHJcbiAgXHRcdGlmIChlLnR5cGUgIT09ICdrZXlwcmVzcycgJiYgZS50eXBlICE9PSAna2V5ZG93bicgJiYgZS50eXBlICE9PSAna2V5dXAnKSB7XHJcbiAgXHRcdFx0dmFyIGlzTWFya2VyID0gdGFyZ2V0LmdldExhdExuZyAmJiAoIXRhcmdldC5fcmFkaXVzIHx8IHRhcmdldC5fcmFkaXVzIDw9IDEwKTtcclxuICBcdFx0XHRkYXRhLmNvbnRhaW5lclBvaW50ID0gaXNNYXJrZXIgP1xyXG4gIFx0XHRcdFx0dGhpcy5sYXRMbmdUb0NvbnRhaW5lclBvaW50KHRhcmdldC5nZXRMYXRMbmcoKSkgOiB0aGlzLm1vdXNlRXZlbnRUb0NvbnRhaW5lclBvaW50KGUpO1xyXG4gIFx0XHRcdGRhdGEubGF5ZXJQb2ludCA9IHRoaXMuY29udGFpbmVyUG9pbnRUb0xheWVyUG9pbnQoZGF0YS5jb250YWluZXJQb2ludCk7XHJcbiAgXHRcdFx0ZGF0YS5sYXRsbmcgPSBpc01hcmtlciA/IHRhcmdldC5nZXRMYXRMbmcoKSA6IHRoaXMubGF5ZXJQb2ludFRvTGF0TG5nKGRhdGEubGF5ZXJQb2ludCk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGZvciAoaSA9IDA7IGkgPCB0YXJnZXRzLmxlbmd0aDsgaSsrKSB7XHJcbiAgXHRcdFx0dGFyZ2V0c1tpXS5maXJlKHR5cGUsIGRhdGEsIHRydWUpO1xyXG4gIFx0XHRcdGlmIChkYXRhLm9yaWdpbmFsRXZlbnQuX3N0b3BwZWQgfHxcclxuICBcdFx0XHRcdCh0YXJnZXRzW2ldLm9wdGlvbnMuYnViYmxpbmdNb3VzZUV2ZW50cyA9PT0gZmFsc2UgJiYgaW5kZXhPZih0aGlzLl9tb3VzZUV2ZW50cywgdHlwZSkgIT09IC0xKSkgeyByZXR1cm47IH1cclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHRfZHJhZ2dhYmxlTW92ZWQ6IGZ1bmN0aW9uIChvYmopIHtcclxuICBcdFx0b2JqID0gb2JqLmRyYWdnaW5nICYmIG9iai5kcmFnZ2luZy5lbmFibGVkKCkgPyBvYmogOiB0aGlzO1xyXG4gIFx0XHRyZXR1cm4gKG9iai5kcmFnZ2luZyAmJiBvYmouZHJhZ2dpbmcubW92ZWQoKSkgfHwgKHRoaXMuYm94Wm9vbSAmJiB0aGlzLmJveFpvb20ubW92ZWQoKSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9jbGVhckhhbmRsZXJzOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSB0aGlzLl9oYW5kbGVycy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gIFx0XHRcdHRoaXMuX2hhbmRsZXJzW2ldLmRpc2FibGUoKTtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAc2VjdGlvbiBPdGhlciBNZXRob2RzXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCB3aGVuUmVhZHkoZm46IEZ1bmN0aW9uLCBjb250ZXh0PzogT2JqZWN0KTogdGhpc1xyXG4gIFx0Ly8gUnVucyB0aGUgZ2l2ZW4gZnVuY3Rpb24gYGZuYCB3aGVuIHRoZSBtYXAgZ2V0cyBpbml0aWFsaXplZCB3aXRoXHJcbiAgXHQvLyBhIHZpZXcgKGNlbnRlciBhbmQgem9vbSkgYW5kIGF0IGxlYXN0IG9uZSBsYXllciwgb3IgaW1tZWRpYXRlbHlcclxuICBcdC8vIGlmIGl0J3MgYWxyZWFkeSBpbml0aWFsaXplZCwgb3B0aW9uYWxseSBwYXNzaW5nIGEgZnVuY3Rpb24gY29udGV4dC5cclxuICBcdHdoZW5SZWFkeTogZnVuY3Rpb24gKGNhbGxiYWNrLCBjb250ZXh0KSB7XHJcbiAgXHRcdGlmICh0aGlzLl9sb2FkZWQpIHtcclxuICBcdFx0XHRjYWxsYmFjay5jYWxsKGNvbnRleHQgfHwgdGhpcywge3RhcmdldDogdGhpc30pO1xyXG4gIFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdHRoaXMub24oJ2xvYWQnLCBjYWxsYmFjaywgY29udGV4dCk7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuXHJcbiAgXHQvLyBwcml2YXRlIG1ldGhvZHMgZm9yIGdldHRpbmcgbWFwIHN0YXRlXHJcblxyXG4gIFx0X2dldE1hcFBhbmVQb3M6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIGdldFBvc2l0aW9uKHRoaXMuX21hcFBhbmUpIHx8IG5ldyBQb2ludCgwLCAwKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X21vdmVkOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHZhciBwb3MgPSB0aGlzLl9nZXRNYXBQYW5lUG9zKCk7XHJcbiAgXHRcdHJldHVybiBwb3MgJiYgIXBvcy5lcXVhbHMoWzAsIDBdKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X2dldFRvcExlZnRQb2ludDogZnVuY3Rpb24gKGNlbnRlciwgem9vbSkge1xyXG4gIFx0XHR2YXIgcGl4ZWxPcmlnaW4gPSBjZW50ZXIgJiYgem9vbSAhPT0gdW5kZWZpbmVkID9cclxuICBcdFx0XHR0aGlzLl9nZXROZXdQaXhlbE9yaWdpbihjZW50ZXIsIHpvb20pIDpcclxuICBcdFx0XHR0aGlzLmdldFBpeGVsT3JpZ2luKCk7XHJcbiAgXHRcdHJldHVybiBwaXhlbE9yaWdpbi5zdWJ0cmFjdCh0aGlzLl9nZXRNYXBQYW5lUG9zKCkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfZ2V0TmV3UGl4ZWxPcmlnaW46IGZ1bmN0aW9uIChjZW50ZXIsIHpvb20pIHtcclxuICBcdFx0dmFyIHZpZXdIYWxmID0gdGhpcy5nZXRTaXplKCkuX2RpdmlkZUJ5KDIpO1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5wcm9qZWN0KGNlbnRlciwgem9vbSkuX3N1YnRyYWN0KHZpZXdIYWxmKS5fYWRkKHRoaXMuX2dldE1hcFBhbmVQb3MoKSkuX3JvdW5kKCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9sYXRMbmdUb05ld0xheWVyUG9pbnQ6IGZ1bmN0aW9uIChsYXRsbmcsIHpvb20sIGNlbnRlcikge1xyXG4gIFx0XHR2YXIgdG9wTGVmdCA9IHRoaXMuX2dldE5ld1BpeGVsT3JpZ2luKGNlbnRlciwgem9vbSk7XHJcbiAgXHRcdHJldHVybiB0aGlzLnByb2plY3QobGF0bG5nLCB6b29tKS5fc3VidHJhY3QodG9wTGVmdCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9sYXRMbmdCb3VuZHNUb05ld0xheWVyQm91bmRzOiBmdW5jdGlvbiAobGF0TG5nQm91bmRzLCB6b29tLCBjZW50ZXIpIHtcclxuICBcdFx0dmFyIHRvcExlZnQgPSB0aGlzLl9nZXROZXdQaXhlbE9yaWdpbihjZW50ZXIsIHpvb20pO1xyXG4gIFx0XHRyZXR1cm4gdG9Cb3VuZHMoW1xyXG4gIFx0XHRcdHRoaXMucHJvamVjdChsYXRMbmdCb3VuZHMuZ2V0U291dGhXZXN0KCksIHpvb20pLl9zdWJ0cmFjdCh0b3BMZWZ0KSxcclxuICBcdFx0XHR0aGlzLnByb2plY3QobGF0TG5nQm91bmRzLmdldE5vcnRoV2VzdCgpLCB6b29tKS5fc3VidHJhY3QodG9wTGVmdCksXHJcbiAgXHRcdFx0dGhpcy5wcm9qZWN0KGxhdExuZ0JvdW5kcy5nZXRTb3V0aEVhc3QoKSwgem9vbSkuX3N1YnRyYWN0KHRvcExlZnQpLFxyXG4gIFx0XHRcdHRoaXMucHJvamVjdChsYXRMbmdCb3VuZHMuZ2V0Tm9ydGhFYXN0KCksIHpvb20pLl9zdWJ0cmFjdCh0b3BMZWZ0KVxyXG4gIFx0XHRdKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gbGF5ZXIgcG9pbnQgb2YgdGhlIGN1cnJlbnQgY2VudGVyXHJcbiAgXHRfZ2V0Q2VudGVyTGF5ZXJQb2ludDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5jb250YWluZXJQb2ludFRvTGF5ZXJQb2ludCh0aGlzLmdldFNpemUoKS5fZGl2aWRlQnkoMikpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBvZmZzZXQgb2YgdGhlIHNwZWNpZmllZCBwbGFjZSB0byB0aGUgY3VycmVudCBjZW50ZXIgaW4gcGl4ZWxzXHJcbiAgXHRfZ2V0Q2VudGVyT2Zmc2V0OiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLmxhdExuZ1RvTGF5ZXJQb2ludChsYXRsbmcpLnN1YnRyYWN0KHRoaXMuX2dldENlbnRlckxheWVyUG9pbnQoKSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIGFkanVzdCBjZW50ZXIgZm9yIHZpZXcgdG8gZ2V0IGluc2lkZSBib3VuZHNcclxuICBcdF9saW1pdENlbnRlcjogZnVuY3Rpb24gKGNlbnRlciwgem9vbSwgYm91bmRzKSB7XHJcblxyXG4gIFx0XHRpZiAoIWJvdW5kcykgeyByZXR1cm4gY2VudGVyOyB9XHJcblxyXG4gIFx0XHR2YXIgY2VudGVyUG9pbnQgPSB0aGlzLnByb2plY3QoY2VudGVyLCB6b29tKSxcclxuICBcdFx0ICAgIHZpZXdIYWxmID0gdGhpcy5nZXRTaXplKCkuZGl2aWRlQnkoMiksXHJcbiAgXHRcdCAgICB2aWV3Qm91bmRzID0gbmV3IEJvdW5kcyhjZW50ZXJQb2ludC5zdWJ0cmFjdCh2aWV3SGFsZiksIGNlbnRlclBvaW50LmFkZCh2aWV3SGFsZikpLFxyXG4gIFx0XHQgICAgb2Zmc2V0ID0gdGhpcy5fZ2V0Qm91bmRzT2Zmc2V0KHZpZXdCb3VuZHMsIGJvdW5kcywgem9vbSk7XHJcblxyXG4gIFx0XHQvLyBJZiBvZmZzZXQgaXMgbGVzcyB0aGFuIGEgcGl4ZWwsIGlnbm9yZS5cclxuICBcdFx0Ly8gVGhpcyBwcmV2ZW50cyB1bnN0YWJsZSBwcm9qZWN0aW9ucyBmcm9tIGdldHRpbmcgaW50b1xyXG4gIFx0XHQvLyBhbiBpbmZpbml0ZSBsb29wIG9mIHRpbnkgb2Zmc2V0cy5cclxuICBcdFx0aWYgKE1hdGguYWJzKG9mZnNldC54KSA8PSAxICYmIE1hdGguYWJzKG9mZnNldC55KSA8PSAxKSB7XHJcbiAgXHRcdFx0cmV0dXJuIGNlbnRlcjtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0cmV0dXJuIHRoaXMudW5wcm9qZWN0KGNlbnRlclBvaW50LmFkZChvZmZzZXQpLCB6b29tKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gYWRqdXN0IG9mZnNldCBmb3IgdmlldyB0byBnZXQgaW5zaWRlIGJvdW5kc1xyXG4gIFx0X2xpbWl0T2Zmc2V0OiBmdW5jdGlvbiAob2Zmc2V0LCBib3VuZHMpIHtcclxuICBcdFx0aWYgKCFib3VuZHMpIHsgcmV0dXJuIG9mZnNldDsgfVxyXG5cclxuICBcdFx0dmFyIHZpZXdCb3VuZHMgPSB0aGlzLmdldFBpeGVsQm91bmRzKCksXHJcbiAgXHRcdCAgICBuZXdCb3VuZHMgPSBuZXcgQm91bmRzKHZpZXdCb3VuZHMubWluLmFkZChvZmZzZXQpLCB2aWV3Qm91bmRzLm1heC5hZGQob2Zmc2V0KSk7XHJcblxyXG4gIFx0XHRyZXR1cm4gb2Zmc2V0LmFkZCh0aGlzLl9nZXRCb3VuZHNPZmZzZXQobmV3Qm91bmRzLCBib3VuZHMpKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gcmV0dXJucyBvZmZzZXQgbmVlZGVkIGZvciBweEJvdW5kcyB0byBnZXQgaW5zaWRlIG1heEJvdW5kcyBhdCBhIHNwZWNpZmllZCB6b29tXHJcbiAgXHRfZ2V0Qm91bmRzT2Zmc2V0OiBmdW5jdGlvbiAocHhCb3VuZHMsIG1heEJvdW5kcywgem9vbSkge1xyXG4gIFx0XHR2YXIgcHJvamVjdGVkTWF4Qm91bmRzID0gdG9Cb3VuZHMoXHJcbiAgXHRcdCAgICAgICAgdGhpcy5wcm9qZWN0KG1heEJvdW5kcy5nZXROb3J0aEVhc3QoKSwgem9vbSksXHJcbiAgXHRcdCAgICAgICAgdGhpcy5wcm9qZWN0KG1heEJvdW5kcy5nZXRTb3V0aFdlc3QoKSwgem9vbSlcclxuICBcdFx0ICAgICksXHJcbiAgXHRcdCAgICBtaW5PZmZzZXQgPSBwcm9qZWN0ZWRNYXhCb3VuZHMubWluLnN1YnRyYWN0KHB4Qm91bmRzLm1pbiksXHJcbiAgXHRcdCAgICBtYXhPZmZzZXQgPSBwcm9qZWN0ZWRNYXhCb3VuZHMubWF4LnN1YnRyYWN0KHB4Qm91bmRzLm1heCksXHJcblxyXG4gIFx0XHQgICAgZHggPSB0aGlzLl9yZWJvdW5kKG1pbk9mZnNldC54LCAtbWF4T2Zmc2V0LngpLFxyXG4gIFx0XHQgICAgZHkgPSB0aGlzLl9yZWJvdW5kKG1pbk9mZnNldC55LCAtbWF4T2Zmc2V0LnkpO1xyXG5cclxuICBcdFx0cmV0dXJuIG5ldyBQb2ludChkeCwgZHkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfcmVib3VuZDogZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XHJcbiAgXHRcdHJldHVybiBsZWZ0ICsgcmlnaHQgPiAwID9cclxuICBcdFx0XHRNYXRoLnJvdW5kKGxlZnQgLSByaWdodCkgLyAyIDpcclxuICBcdFx0XHRNYXRoLm1heCgwLCBNYXRoLmNlaWwobGVmdCkpIC0gTWF0aC5tYXgoMCwgTWF0aC5mbG9vcihyaWdodCkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfbGltaXRab29tOiBmdW5jdGlvbiAoem9vbSkge1xyXG4gIFx0XHR2YXIgbWluID0gdGhpcy5nZXRNaW5ab29tKCksXHJcbiAgXHRcdCAgICBtYXggPSB0aGlzLmdldE1heFpvb20oKSxcclxuICBcdFx0ICAgIHNuYXAgPSBCcm93c2VyLmFueTNkID8gdGhpcy5vcHRpb25zLnpvb21TbmFwIDogMTtcclxuICBcdFx0aWYgKHNuYXApIHtcclxuICBcdFx0XHR6b29tID0gTWF0aC5yb3VuZCh6b29tIC8gc25hcCkgKiBzbmFwO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiBNYXRoLm1heChtaW4sIE1hdGgubWluKG1heCwgem9vbSkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfb25QYW5UcmFuc2l0aW9uU3RlcDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR0aGlzLmZpcmUoJ21vdmUnKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X29uUGFuVHJhbnNpdGlvbkVuZDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZW1vdmVDbGFzcyh0aGlzLl9tYXBQYW5lLCAnbGVhZmxldC1wYW4tYW5pbScpO1xyXG4gIFx0XHR0aGlzLmZpcmUoJ21vdmVlbmQnKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X3RyeUFuaW1hdGVkUGFuOiBmdW5jdGlvbiAoY2VudGVyLCBvcHRpb25zKSB7XHJcbiAgXHRcdC8vIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbmV3IGFuZCBjdXJyZW50IGNlbnRlcnMgaW4gcGl4ZWxzXHJcbiAgXHRcdHZhciBvZmZzZXQgPSB0aGlzLl9nZXRDZW50ZXJPZmZzZXQoY2VudGVyKS5fdHJ1bmMoKTtcclxuXHJcbiAgXHRcdC8vIGRvbid0IGFuaW1hdGUgdG9vIGZhciB1bmxlc3MgYW5pbWF0ZTogdHJ1ZSBzcGVjaWZpZWQgaW4gb3B0aW9uc1xyXG4gIFx0XHRpZiAoKG9wdGlvbnMgJiYgb3B0aW9ucy5hbmltYXRlKSAhPT0gdHJ1ZSAmJiAhdGhpcy5nZXRTaXplKCkuY29udGFpbnMob2Zmc2V0KSkgeyByZXR1cm4gZmFsc2U7IH1cclxuXHJcbiAgXHRcdHRoaXMucGFuQnkob2Zmc2V0LCBvcHRpb25zKTtcclxuXHJcbiAgXHRcdHJldHVybiB0cnVlO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfY3JlYXRlQW5pbVByb3h5OiBmdW5jdGlvbiAoKSB7XHJcblxyXG4gIFx0XHR2YXIgcHJveHkgPSB0aGlzLl9wcm94eSA9IGNyZWF0ZSQxKCdkaXYnLCAnbGVhZmxldC1wcm94eSBsZWFmbGV0LXpvb20tYW5pbWF0ZWQnKTtcclxuICBcdFx0dGhpcy5fcGFuZXMubWFwUGFuZS5hcHBlbmRDaGlsZChwcm94eSk7XHJcblxyXG4gIFx0XHR0aGlzLm9uKCd6b29tYW5pbScsIGZ1bmN0aW9uIChlKSB7XHJcbiAgXHRcdFx0dmFyIHByb3AgPSBUUkFOU0ZPUk0sXHJcbiAgXHRcdFx0ICAgIHRyYW5zZm9ybSA9IHRoaXMuX3Byb3h5LnN0eWxlW3Byb3BdO1xyXG5cclxuICBcdFx0XHRzZXRUcmFuc2Zvcm0odGhpcy5fcHJveHksIHRoaXMucHJvamVjdChlLmNlbnRlciwgZS56b29tKSwgdGhpcy5nZXRab29tU2NhbGUoZS56b29tLCAxKSk7XHJcblxyXG4gIFx0XHRcdC8vIHdvcmthcm91bmQgZm9yIGNhc2Ugd2hlbiB0cmFuc2Zvcm0gaXMgdGhlIHNhbWUgYW5kIHNvIHRyYW5zaXRpb25lbmQgZXZlbnQgaXMgbm90IGZpcmVkXHJcbiAgXHRcdFx0aWYgKHRyYW5zZm9ybSA9PT0gdGhpcy5fcHJveHkuc3R5bGVbcHJvcF0gJiYgdGhpcy5fYW5pbWF0aW5nWm9vbSkge1xyXG4gIFx0XHRcdFx0dGhpcy5fb25ab29tVHJhbnNpdGlvbkVuZCgpO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fSwgdGhpcyk7XHJcblxyXG4gIFx0XHR0aGlzLm9uKCdsb2FkIG1vdmVlbmQnLCB0aGlzLl9hbmltTW92ZUVuZCwgdGhpcyk7XHJcblxyXG4gIFx0XHR0aGlzLl9vbigndW5sb2FkJywgdGhpcy5fZGVzdHJveUFuaW1Qcm94eSwgdGhpcyk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9kZXN0cm95QW5pbVByb3h5OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJlbW92ZSh0aGlzLl9wcm94eSk7XHJcbiAgXHRcdHRoaXMub2ZmKCdsb2FkIG1vdmVlbmQnLCB0aGlzLl9hbmltTW92ZUVuZCwgdGhpcyk7XHJcbiAgXHRcdGRlbGV0ZSB0aGlzLl9wcm94eTtcclxuICBcdH0sXHJcblxyXG4gIFx0X2FuaW1Nb3ZlRW5kOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHZhciBjID0gdGhpcy5nZXRDZW50ZXIoKSxcclxuICBcdFx0ICAgIHogPSB0aGlzLmdldFpvb20oKTtcclxuICBcdFx0c2V0VHJhbnNmb3JtKHRoaXMuX3Byb3h5LCB0aGlzLnByb2plY3QoYywgeiksIHRoaXMuZ2V0Wm9vbVNjYWxlKHosIDEpKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X2NhdGNoVHJhbnNpdGlvbkVuZDogZnVuY3Rpb24gKGUpIHtcclxuICBcdFx0aWYgKHRoaXMuX2FuaW1hdGluZ1pvb20gJiYgZS5wcm9wZXJ0eU5hbWUuaW5kZXhPZigndHJhbnNmb3JtJykgPj0gMCkge1xyXG4gIFx0XHRcdHRoaXMuX29uWm9vbVRyYW5zaXRpb25FbmQoKTtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHRfbm90aGluZ1RvQW5pbWF0ZTogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gIXRoaXMuX2NvbnRhaW5lci5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCdsZWFmbGV0LXpvb20tYW5pbWF0ZWQnKS5sZW5ndGg7XHJcbiAgXHR9LFxyXG5cclxuICBcdF90cnlBbmltYXRlZFpvb206IGZ1bmN0aW9uIChjZW50ZXIsIHpvb20sIG9wdGlvbnMpIHtcclxuXHJcbiAgXHRcdGlmICh0aGlzLl9hbmltYXRpbmdab29tKSB7IHJldHVybiB0cnVlOyB9XHJcblxyXG4gIFx0XHRvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcclxuXHJcbiAgXHRcdC8vIGRvbid0IGFuaW1hdGUgaWYgZGlzYWJsZWQsIG5vdCBzdXBwb3J0ZWQgb3Igem9vbSBkaWZmZXJlbmNlIGlzIHRvbyBsYXJnZVxyXG4gIFx0XHRpZiAoIXRoaXMuX3pvb21BbmltYXRlZCB8fCBvcHRpb25zLmFuaW1hdGUgPT09IGZhbHNlIHx8IHRoaXMuX25vdGhpbmdUb0FuaW1hdGUoKSB8fFxyXG4gIFx0XHQgICAgICAgIE1hdGguYWJzKHpvb20gLSB0aGlzLl96b29tKSA+IHRoaXMub3B0aW9ucy56b29tQW5pbWF0aW9uVGhyZXNob2xkKSB7IHJldHVybiBmYWxzZTsgfVxyXG5cclxuICBcdFx0Ly8gb2Zmc2V0IGlzIHRoZSBwaXhlbCBjb29yZHMgb2YgdGhlIHpvb20gb3JpZ2luIHJlbGF0aXZlIHRvIHRoZSBjdXJyZW50IGNlbnRlclxyXG4gIFx0XHR2YXIgc2NhbGUgPSB0aGlzLmdldFpvb21TY2FsZSh6b29tKSxcclxuICBcdFx0ICAgIG9mZnNldCA9IHRoaXMuX2dldENlbnRlck9mZnNldChjZW50ZXIpLl9kaXZpZGVCeSgxIC0gMSAvIHNjYWxlKTtcclxuXHJcbiAgXHRcdC8vIGRvbid0IGFuaW1hdGUgaWYgdGhlIHpvb20gb3JpZ2luIGlzbid0IHdpdGhpbiBvbmUgc2NyZWVuIGZyb20gdGhlIGN1cnJlbnQgY2VudGVyLCB1bmxlc3MgZm9yY2VkXHJcbiAgXHRcdGlmIChvcHRpb25zLmFuaW1hdGUgIT09IHRydWUgJiYgIXRoaXMuZ2V0U2l6ZSgpLmNvbnRhaW5zKG9mZnNldCkpIHsgcmV0dXJuIGZhbHNlOyB9XHJcblxyXG4gIFx0XHRyZXF1ZXN0QW5pbUZyYW1lKGZ1bmN0aW9uICgpIHtcclxuICBcdFx0XHR0aGlzXHJcbiAgXHRcdFx0ICAgIC5fbW92ZVN0YXJ0KHRydWUsIG9wdGlvbnMubm9Nb3ZlU3RhcnQgfHwgZmFsc2UpXHJcbiAgXHRcdFx0ICAgIC5fYW5pbWF0ZVpvb20oY2VudGVyLCB6b29tLCB0cnVlKTtcclxuICBcdFx0fSwgdGhpcyk7XHJcblxyXG4gIFx0XHRyZXR1cm4gdHJ1ZTtcclxuICBcdH0sXHJcblxyXG4gIFx0X2FuaW1hdGVab29tOiBmdW5jdGlvbiAoY2VudGVyLCB6b29tLCBzdGFydEFuaW0sIG5vVXBkYXRlKSB7XHJcbiAgXHRcdGlmICghdGhpcy5fbWFwUGFuZSkgeyByZXR1cm47IH1cclxuXHJcbiAgXHRcdGlmIChzdGFydEFuaW0pIHtcclxuICBcdFx0XHR0aGlzLl9hbmltYXRpbmdab29tID0gdHJ1ZTtcclxuXHJcbiAgXHRcdFx0Ly8gcmVtZW1iZXIgd2hhdCBjZW50ZXIvem9vbSB0byBzZXQgYWZ0ZXIgYW5pbWF0aW9uXHJcbiAgXHRcdFx0dGhpcy5fYW5pbWF0ZVRvQ2VudGVyID0gY2VudGVyO1xyXG4gIFx0XHRcdHRoaXMuX2FuaW1hdGVUb1pvb20gPSB6b29tO1xyXG5cclxuICBcdFx0XHRhZGRDbGFzcyh0aGlzLl9tYXBQYW5lLCAnbGVhZmxldC16b29tLWFuaW0nKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gQHNlY3Rpb24gT3RoZXIgRXZlbnRzXHJcbiAgXHRcdC8vIEBldmVudCB6b29tYW5pbTogWm9vbUFuaW1FdmVudFxyXG4gIFx0XHQvLyBGaXJlZCBhdCBsZWFzdCBvbmNlIHBlciB6b29tIGFuaW1hdGlvbi4gRm9yIGNvbnRpbnVvdXMgem9vbSwgbGlrZSBwaW5jaCB6b29taW5nLCBmaXJlZCBvbmNlIHBlciBmcmFtZSBkdXJpbmcgem9vbS5cclxuICBcdFx0dGhpcy5maXJlKCd6b29tYW5pbScsIHtcclxuICBcdFx0XHRjZW50ZXI6IGNlbnRlcixcclxuICBcdFx0XHR6b29tOiB6b29tLFxyXG4gIFx0XHRcdG5vVXBkYXRlOiBub1VwZGF0ZVxyXG4gIFx0XHR9KTtcclxuXHJcbiAgXHRcdGlmICghdGhpcy5fdGVtcEZpcmVab29tRXZlbnQpIHtcclxuICBcdFx0XHR0aGlzLl90ZW1wRmlyZVpvb21FdmVudCA9IHRoaXMuX3pvb20gIT09IHRoaXMuX2FuaW1hdGVUb1pvb207XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX21vdmUodGhpcy5fYW5pbWF0ZVRvQ2VudGVyLCB0aGlzLl9hbmltYXRlVG9ab29tLCB1bmRlZmluZWQsIHRydWUpO1xyXG5cclxuICBcdFx0Ly8gV29yayBhcm91bmQgd2Via2l0IG5vdCBmaXJpbmcgJ3RyYW5zaXRpb25lbmQnLCBzZWUgaHR0cHM6Ly9naXRodWIuY29tL0xlYWZsZXQvTGVhZmxldC9pc3N1ZXMvMzY4OSwgMjY5M1xyXG4gIFx0XHRzZXRUaW1lb3V0KGJpbmQodGhpcy5fb25ab29tVHJhbnNpdGlvbkVuZCwgdGhpcyksIDI1MCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9vblpvb21UcmFuc2l0aW9uRW5kOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICghdGhpcy5fYW5pbWF0aW5nWm9vbSkgeyByZXR1cm47IH1cclxuXHJcbiAgXHRcdGlmICh0aGlzLl9tYXBQYW5lKSB7XHJcbiAgXHRcdFx0cmVtb3ZlQ2xhc3ModGhpcy5fbWFwUGFuZSwgJ2xlYWZsZXQtem9vbS1hbmltJyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX2FuaW1hdGluZ1pvb20gPSBmYWxzZTtcclxuXHJcbiAgXHRcdHRoaXMuX21vdmUodGhpcy5fYW5pbWF0ZVRvQ2VudGVyLCB0aGlzLl9hbmltYXRlVG9ab29tLCB1bmRlZmluZWQsIHRydWUpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX3RlbXBGaXJlWm9vbUV2ZW50KSB7XHJcbiAgXHRcdFx0dGhpcy5maXJlKCd6b29tJyk7XHJcbiAgXHRcdH1cclxuICBcdFx0ZGVsZXRlIHRoaXMuX3RlbXBGaXJlWm9vbUV2ZW50O1xyXG5cclxuICBcdFx0dGhpcy5maXJlKCdtb3ZlJyk7XHJcblxyXG4gIFx0XHR0aGlzLl9tb3ZlRW5kKHRydWUpO1xyXG4gIFx0fVxyXG4gIH0pO1xyXG5cclxuICAvLyBAc2VjdGlvblxyXG5cclxuICAvLyBAZmFjdG9yeSBMLm1hcChpZDogU3RyaW5nLCBvcHRpb25zPzogTWFwIG9wdGlvbnMpXHJcbiAgLy8gSW5zdGFudGlhdGVzIGEgbWFwIG9iamVjdCBnaXZlbiB0aGUgRE9NIElEIG9mIGEgYDxkaXY+YCBlbGVtZW50XHJcbiAgLy8gYW5kIG9wdGlvbmFsbHkgYW4gb2JqZWN0IGxpdGVyYWwgd2l0aCBgTWFwIG9wdGlvbnNgLlxyXG4gIC8vXHJcbiAgLy8gQGFsdGVybmF0aXZlXHJcbiAgLy8gQGZhY3RvcnkgTC5tYXAoZWw6IEhUTUxFbGVtZW50LCBvcHRpb25zPzogTWFwIG9wdGlvbnMpXHJcbiAgLy8gSW5zdGFudGlhdGVzIGEgbWFwIG9iamVjdCBnaXZlbiBhbiBpbnN0YW5jZSBvZiBhIGA8ZGl2PmAgSFRNTCBlbGVtZW50XHJcbiAgLy8gYW5kIG9wdGlvbmFsbHkgYW4gb2JqZWN0IGxpdGVyYWwgd2l0aCBgTWFwIG9wdGlvbnNgLlxyXG4gIGZ1bmN0aW9uIGNyZWF0ZU1hcChpZCwgb3B0aW9ucykge1xyXG4gIFx0cmV0dXJuIG5ldyBNYXAoaWQsIG9wdGlvbnMpO1xyXG4gIH1cblxuICAvKlxyXG4gICAqIEBjbGFzcyBDb250cm9sXHJcbiAgICogQGFrYSBMLkNvbnRyb2xcclxuICAgKiBAaW5oZXJpdHMgQ2xhc3NcclxuICAgKlxyXG4gICAqIEwuQ29udHJvbCBpcyBhIGJhc2UgY2xhc3MgZm9yIGltcGxlbWVudGluZyBtYXAgY29udHJvbHMuIEhhbmRsZXMgcG9zaXRpb25pbmcuXHJcbiAgICogQWxsIG90aGVyIGNvbnRyb2xzIGV4dGVuZCBmcm9tIHRoaXMgY2xhc3MuXHJcbiAgICovXHJcblxyXG4gIHZhciBDb250cm9sID0gQ2xhc3MuZXh0ZW5kKHtcclxuICBcdC8vIEBzZWN0aW9uXHJcbiAgXHQvLyBAYWthIENvbnRyb2wgT3B0aW9uc1xyXG4gIFx0b3B0aW9uczoge1xyXG4gIFx0XHQvLyBAb3B0aW9uIHBvc2l0aW9uOiBTdHJpbmcgPSAndG9wcmlnaHQnXHJcbiAgXHRcdC8vIFRoZSBwb3NpdGlvbiBvZiB0aGUgY29udHJvbCAob25lIG9mIHRoZSBtYXAgY29ybmVycykuIFBvc3NpYmxlIHZhbHVlcyBhcmUgYCd0b3BsZWZ0J2AsXHJcbiAgXHRcdC8vIGAndG9wcmlnaHQnYCwgYCdib3R0b21sZWZ0J2Agb3IgYCdib3R0b21yaWdodCdgXHJcbiAgXHRcdHBvc2l0aW9uOiAndG9wcmlnaHQnXHJcbiAgXHR9LFxyXG5cclxuICBcdGluaXRpYWxpemU6IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcbiAgXHRcdHNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8qIEBzZWN0aW9uXHJcbiAgXHQgKiBDbGFzc2VzIGV4dGVuZGluZyBMLkNvbnRyb2wgd2lsbCBpbmhlcml0IHRoZSBmb2xsb3dpbmcgbWV0aG9kczpcclxuICBcdCAqXHJcbiAgXHQgKiBAbWV0aG9kIGdldFBvc2l0aW9uOiBzdHJpbmdcclxuICBcdCAqIFJldHVybnMgdGhlIHBvc2l0aW9uIG9mIHRoZSBjb250cm9sLlxyXG4gIFx0ICovXHJcbiAgXHRnZXRQb3NpdGlvbjogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLnBvc2l0aW9uO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNldFBvc2l0aW9uKHBvc2l0aW9uOiBzdHJpbmcpOiB0aGlzXHJcbiAgXHQvLyBTZXRzIHRoZSBwb3NpdGlvbiBvZiB0aGUgY29udHJvbC5cclxuICBcdHNldFBvc2l0aW9uOiBmdW5jdGlvbiAocG9zaXRpb24pIHtcclxuICBcdFx0dmFyIG1hcCA9IHRoaXMuX21hcDtcclxuXHJcbiAgXHRcdGlmIChtYXApIHtcclxuICBcdFx0XHRtYXAucmVtb3ZlQ29udHJvbCh0aGlzKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5vcHRpb25zLnBvc2l0aW9uID0gcG9zaXRpb247XHJcblxyXG4gIFx0XHRpZiAobWFwKSB7XHJcbiAgXHRcdFx0bWFwLmFkZENvbnRyb2wodGhpcyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldENvbnRhaW5lcjogSFRNTEVsZW1lbnRcclxuICBcdC8vIFJldHVybnMgdGhlIEhUTUxFbGVtZW50IHRoYXQgY29udGFpbnMgdGhlIGNvbnRyb2wuXHJcbiAgXHRnZXRDb250YWluZXI6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuX2NvbnRhaW5lcjtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBhZGRUbyhtYXA6IE1hcCk6IHRoaXNcclxuICBcdC8vIEFkZHMgdGhlIGNvbnRyb2wgdG8gdGhlIGdpdmVuIG1hcC5cclxuICBcdGFkZFRvOiBmdW5jdGlvbiAobWFwKSB7XHJcbiAgXHRcdHRoaXMucmVtb3ZlKCk7XHJcbiAgXHRcdHRoaXMuX21hcCA9IG1hcDtcclxuXHJcbiAgXHRcdHZhciBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXIgPSB0aGlzLm9uQWRkKG1hcCksXHJcbiAgXHRcdCAgICBwb3MgPSB0aGlzLmdldFBvc2l0aW9uKCksXHJcbiAgXHRcdCAgICBjb3JuZXIgPSBtYXAuX2NvbnRyb2xDb3JuZXJzW3Bvc107XHJcblxyXG4gIFx0XHRhZGRDbGFzcyhjb250YWluZXIsICdsZWFmbGV0LWNvbnRyb2wnKTtcclxuXHJcbiAgXHRcdGlmIChwb3MuaW5kZXhPZignYm90dG9tJykgIT09IC0xKSB7XHJcbiAgXHRcdFx0Y29ybmVyLmluc2VydEJlZm9yZShjb250YWluZXIsIGNvcm5lci5maXJzdENoaWxkKTtcclxuICBcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRjb3JuZXIuYXBwZW5kQ2hpbGQoY29udGFpbmVyKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5fbWFwLm9uKCd1bmxvYWQnLCB0aGlzLnJlbW92ZSwgdGhpcyk7XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCByZW1vdmU6IHRoaXNcclxuICBcdC8vIFJlbW92ZXMgdGhlIGNvbnRyb2wgZnJvbSB0aGUgbWFwIGl0IGlzIGN1cnJlbnRseSBhY3RpdmUgb24uXHJcbiAgXHRyZW1vdmU6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKCF0aGlzLl9tYXApIHtcclxuICBcdFx0XHRyZXR1cm4gdGhpcztcclxuICBcdFx0fVxyXG5cclxuICBcdFx0cmVtb3ZlKHRoaXMuX2NvbnRhaW5lcik7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5vblJlbW92ZSkge1xyXG4gIFx0XHRcdHRoaXMub25SZW1vdmUodGhpcy5fbWFwKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5fbWFwLm9mZigndW5sb2FkJywgdGhpcy5yZW1vdmUsIHRoaXMpO1xyXG4gIFx0XHR0aGlzLl9tYXAgPSBudWxsO1xyXG5cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9yZWZvY3VzT25NYXA6IGZ1bmN0aW9uIChlKSB7XHJcbiAgXHRcdC8vIGlmIG1hcCBleGlzdHMgYW5kIGV2ZW50IGlzIG5vdCBhIGtleWJvYXJkIGV2ZW50XHJcbiAgXHRcdGlmICh0aGlzLl9tYXAgJiYgZSAmJiBlLnNjcmVlblggPiAwICYmIGUuc2NyZWVuWSA+IDApIHtcclxuICBcdFx0XHR0aGlzLl9tYXAuZ2V0Q29udGFpbmVyKCkuZm9jdXMoKTtcclxuICBcdFx0fVxyXG4gIFx0fVxyXG4gIH0pO1xyXG5cclxuICB2YXIgY29udHJvbCA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcbiAgXHRyZXR1cm4gbmV3IENvbnRyb2wob3B0aW9ucyk7XHJcbiAgfTtcclxuXHJcbiAgLyogQHNlY3Rpb24gRXh0ZW5zaW9uIG1ldGhvZHNcclxuICAgKiBAdW5pbmhlcml0YWJsZVxyXG4gICAqXHJcbiAgICogRXZlcnkgY29udHJvbCBzaG91bGQgZXh0ZW5kIGZyb20gYEwuQ29udHJvbGAgYW5kIChyZS0paW1wbGVtZW50IHRoZSBmb2xsb3dpbmcgbWV0aG9kcy5cclxuICAgKlxyXG4gICAqIEBtZXRob2Qgb25BZGQobWFwOiBNYXApOiBIVE1MRWxlbWVudFxyXG4gICAqIFNob3VsZCByZXR1cm4gdGhlIGNvbnRhaW5lciBET00gZWxlbWVudCBmb3IgdGhlIGNvbnRyb2wgYW5kIGFkZCBsaXN0ZW5lcnMgb24gcmVsZXZhbnQgbWFwIGV2ZW50cy4gQ2FsbGVkIG9uIFtgY29udHJvbC5hZGRUbyhtYXApYF0oI2NvbnRyb2wtYWRkVG8pLlxyXG4gICAqXHJcbiAgICogQG1ldGhvZCBvblJlbW92ZShtYXA6IE1hcClcclxuICAgKiBPcHRpb25hbCBtZXRob2QuIFNob3VsZCBjb250YWluIGFsbCBjbGVhbiB1cCBjb2RlIHRoYXQgcmVtb3ZlcyB0aGUgbGlzdGVuZXJzIHByZXZpb3VzbHkgYWRkZWQgaW4gW2BvbkFkZGBdKCNjb250cm9sLW9uYWRkKS4gQ2FsbGVkIG9uIFtgY29udHJvbC5yZW1vdmUoKWBdKCNjb250cm9sLXJlbW92ZSkuXHJcbiAgICovXHJcblxyXG4gIC8qIEBuYW1lc3BhY2UgTWFwXHJcbiAgICogQHNlY3Rpb24gTWV0aG9kcyBmb3IgTGF5ZXJzIGFuZCBDb250cm9sc1xyXG4gICAqL1xyXG4gIE1hcC5pbmNsdWRlKHtcclxuICBcdC8vIEBtZXRob2QgYWRkQ29udHJvbChjb250cm9sOiBDb250cm9sKTogdGhpc1xyXG4gIFx0Ly8gQWRkcyB0aGUgZ2l2ZW4gY29udHJvbCB0byB0aGUgbWFwXHJcbiAgXHRhZGRDb250cm9sOiBmdW5jdGlvbiAoY29udHJvbCkge1xyXG4gIFx0XHRjb250cm9sLmFkZFRvKHRoaXMpO1xyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCByZW1vdmVDb250cm9sKGNvbnRyb2w6IENvbnRyb2wpOiB0aGlzXHJcbiAgXHQvLyBSZW1vdmVzIHRoZSBnaXZlbiBjb250cm9sIGZyb20gdGhlIG1hcFxyXG4gIFx0cmVtb3ZlQ29udHJvbDogZnVuY3Rpb24gKGNvbnRyb2wpIHtcclxuICBcdFx0Y29udHJvbC5yZW1vdmUoKTtcclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9pbml0Q29udHJvbFBvczogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR2YXIgY29ybmVycyA9IHRoaXMuX2NvbnRyb2xDb3JuZXJzID0ge30sXHJcbiAgXHRcdCAgICBsID0gJ2xlYWZsZXQtJyxcclxuICBcdFx0ICAgIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRyb2xDb250YWluZXIgPVxyXG4gIFx0XHQgICAgICAgICAgICBjcmVhdGUkMSgnZGl2JywgbCArICdjb250cm9sLWNvbnRhaW5lcicsIHRoaXMuX2NvbnRhaW5lcik7XHJcblxyXG4gIFx0XHRmdW5jdGlvbiBjcmVhdGVDb3JuZXIodlNpZGUsIGhTaWRlKSB7XHJcbiAgXHRcdFx0dmFyIGNsYXNzTmFtZSA9IGwgKyB2U2lkZSArICcgJyArIGwgKyBoU2lkZTtcclxuXHJcbiAgXHRcdFx0Y29ybmVyc1t2U2lkZSArIGhTaWRlXSA9IGNyZWF0ZSQxKCdkaXYnLCBjbGFzc05hbWUsIGNvbnRhaW5lcik7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGNyZWF0ZUNvcm5lcigndG9wJywgJ2xlZnQnKTtcclxuICBcdFx0Y3JlYXRlQ29ybmVyKCd0b3AnLCAncmlnaHQnKTtcclxuICBcdFx0Y3JlYXRlQ29ybmVyKCdib3R0b20nLCAnbGVmdCcpO1xyXG4gIFx0XHRjcmVhdGVDb3JuZXIoJ2JvdHRvbScsICdyaWdodCcpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfY2xlYXJDb250cm9sUG9zOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGZvciAodmFyIGkgaW4gdGhpcy5fY29udHJvbENvcm5lcnMpIHtcclxuICBcdFx0XHRyZW1vdmUodGhpcy5fY29udHJvbENvcm5lcnNbaV0pO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJlbW92ZSh0aGlzLl9jb250cm9sQ29udGFpbmVyKTtcclxuICBcdFx0ZGVsZXRlIHRoaXMuX2NvbnRyb2xDb3JuZXJzO1xyXG4gIFx0XHRkZWxldGUgdGhpcy5fY29udHJvbENvbnRhaW5lcjtcclxuICBcdH1cclxuICB9KTtcblxuICAvKlxyXG4gICAqIEBjbGFzcyBDb250cm9sLkxheWVyc1xyXG4gICAqIEBha2EgTC5Db250cm9sLkxheWVyc1xyXG4gICAqIEBpbmhlcml0cyBDb250cm9sXHJcbiAgICpcclxuICAgKiBUaGUgbGF5ZXJzIGNvbnRyb2wgZ2l2ZXMgdXNlcnMgdGhlIGFiaWxpdHkgdG8gc3dpdGNoIGJldHdlZW4gZGlmZmVyZW50IGJhc2UgbGF5ZXJzIGFuZCBzd2l0Y2ggb3ZlcmxheXMgb24vb2ZmIChjaGVjayBvdXQgdGhlIFtkZXRhaWxlZCBleGFtcGxlXShodHRwczovL2xlYWZsZXRqcy5jb20vZXhhbXBsZXMvbGF5ZXJzLWNvbnRyb2wvKSkuIEV4dGVuZHMgYENvbnRyb2xgLlxyXG4gICAqXHJcbiAgICogQGV4YW1wbGVcclxuICAgKlxyXG4gICAqIGBgYGpzXHJcbiAgICogdmFyIGJhc2VMYXllcnMgPSB7XHJcbiAgICogXHRcIk1hcGJveFwiOiBtYXBib3gsXHJcbiAgICogXHRcIk9wZW5TdHJlZXRNYXBcIjogb3NtXHJcbiAgICogfTtcclxuICAgKlxyXG4gICAqIHZhciBvdmVybGF5cyA9IHtcclxuICAgKiBcdFwiTWFya2VyXCI6IG1hcmtlcixcclxuICAgKiBcdFwiUm9hZHNcIjogcm9hZHNMYXllclxyXG4gICAqIH07XHJcbiAgICpcclxuICAgKiBMLmNvbnRyb2wubGF5ZXJzKGJhc2VMYXllcnMsIG92ZXJsYXlzKS5hZGRUbyhtYXApO1xyXG4gICAqIGBgYFxyXG4gICAqXHJcbiAgICogVGhlIGBiYXNlTGF5ZXJzYCBhbmQgYG92ZXJsYXlzYCBwYXJhbWV0ZXJzIGFyZSBvYmplY3QgbGl0ZXJhbHMgd2l0aCBsYXllciBuYW1lcyBhcyBrZXlzIGFuZCBgTGF5ZXJgIG9iamVjdHMgYXMgdmFsdWVzOlxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiB7XHJcbiAgICogICAgIFwiPHNvbWVOYW1lMT5cIjogbGF5ZXIxLFxyXG4gICAqICAgICBcIjxzb21lTmFtZTI+XCI6IGxheWVyMlxyXG4gICAqIH1cclxuICAgKiBgYGBcclxuICAgKlxyXG4gICAqIFRoZSBsYXllciBuYW1lcyBjYW4gY29udGFpbiBIVE1MLCB3aGljaCBhbGxvd3MgeW91IHRvIGFkZCBhZGRpdGlvbmFsIHN0eWxpbmcgdG8gdGhlIGl0ZW1zOlxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiB7XCI8aW1nIHNyYz0nbXktbGF5ZXItaWNvbicgLz4gPHNwYW4gY2xhc3M9J215LWxheWVyLWl0ZW0nPk15IExheWVyPC9zcGFuPlwiOiBteUxheWVyfVxyXG4gICAqIGBgYFxyXG4gICAqL1xyXG5cclxuICB2YXIgTGF5ZXJzID0gQ29udHJvbC5leHRlbmQoe1xyXG4gIFx0Ly8gQHNlY3Rpb25cclxuICBcdC8vIEBha2EgQ29udHJvbC5MYXllcnMgb3B0aW9uc1xyXG4gIFx0b3B0aW9uczoge1xyXG4gIFx0XHQvLyBAb3B0aW9uIGNvbGxhcHNlZDogQm9vbGVhbiA9IHRydWVcclxuICBcdFx0Ly8gSWYgYHRydWVgLCB0aGUgY29udHJvbCB3aWxsIGJlIGNvbGxhcHNlZCBpbnRvIGFuIGljb24gYW5kIGV4cGFuZGVkIG9uIG1vdXNlIGhvdmVyLCB0b3VjaCwgb3Iga2V5Ym9hcmQgYWN0aXZhdGlvbi5cclxuICBcdFx0Y29sbGFwc2VkOiB0cnVlLFxyXG4gIFx0XHRwb3NpdGlvbjogJ3RvcHJpZ2h0JyxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gYXV0b1pJbmRleDogQm9vbGVhbiA9IHRydWVcclxuICBcdFx0Ly8gSWYgYHRydWVgLCB0aGUgY29udHJvbCB3aWxsIGFzc2lnbiB6SW5kZXhlcyBpbiBpbmNyZWFzaW5nIG9yZGVyIHRvIGFsbCBvZiBpdHMgbGF5ZXJzIHNvIHRoYXQgdGhlIG9yZGVyIGlzIHByZXNlcnZlZCB3aGVuIHN3aXRjaGluZyB0aGVtIG9uL29mZi5cclxuICBcdFx0YXV0b1pJbmRleDogdHJ1ZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gaGlkZVNpbmdsZUJhc2U6IEJvb2xlYW4gPSBmYWxzZVxyXG4gIFx0XHQvLyBJZiBgdHJ1ZWAsIHRoZSBiYXNlIGxheWVycyBpbiB0aGUgY29udHJvbCB3aWxsIGJlIGhpZGRlbiB3aGVuIHRoZXJlIGlzIG9ubHkgb25lLlxyXG4gIFx0XHRoaWRlU2luZ2xlQmFzZTogZmFsc2UsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHNvcnRMYXllcnM6IEJvb2xlYW4gPSBmYWxzZVxyXG4gIFx0XHQvLyBXaGV0aGVyIHRvIHNvcnQgdGhlIGxheWVycy4gV2hlbiBgZmFsc2VgLCBsYXllcnMgd2lsbCBrZWVwIHRoZSBvcmRlclxyXG4gIFx0XHQvLyBpbiB3aGljaCB0aGV5IHdlcmUgYWRkZWQgdG8gdGhlIGNvbnRyb2wuXHJcbiAgXHRcdHNvcnRMYXllcnM6IGZhbHNlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBzb3J0RnVuY3Rpb246IEZ1bmN0aW9uID0gKlxyXG4gIFx0XHQvLyBBIFtjb21wYXJlIGZ1bmN0aW9uXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9BcnJheS9zb3J0KVxyXG4gIFx0XHQvLyB0aGF0IHdpbGwgYmUgdXNlZCBmb3Igc29ydGluZyB0aGUgbGF5ZXJzLCB3aGVuIGBzb3J0TGF5ZXJzYCBpcyBgdHJ1ZWAuXHJcbiAgXHRcdC8vIFRoZSBmdW5jdGlvbiByZWNlaXZlcyBib3RoIHRoZSBgTC5MYXllcmAgaW5zdGFuY2VzIGFuZCB0aGVpciBuYW1lcywgYXMgaW5cclxuICBcdFx0Ly8gYHNvcnRGdW5jdGlvbihsYXllckEsIGxheWVyQiwgbmFtZUEsIG5hbWVCKWAuXHJcbiAgXHRcdC8vIEJ5IGRlZmF1bHQsIGl0IHNvcnRzIGxheWVycyBhbHBoYWJldGljYWxseSBieSB0aGVpciBuYW1lLlxyXG4gIFx0XHRzb3J0RnVuY3Rpb246IGZ1bmN0aW9uIChsYXllckEsIGxheWVyQiwgbmFtZUEsIG5hbWVCKSB7XHJcbiAgXHRcdFx0cmV0dXJuIG5hbWVBIDwgbmFtZUIgPyAtMSA6IChuYW1lQiA8IG5hbWVBID8gMSA6IDApO1xyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdGluaXRpYWxpemU6IGZ1bmN0aW9uIChiYXNlTGF5ZXJzLCBvdmVybGF5cywgb3B0aW9ucykge1xyXG4gIFx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xyXG5cclxuICBcdFx0dGhpcy5fbGF5ZXJDb250cm9sSW5wdXRzID0gW107XHJcbiAgXHRcdHRoaXMuX2xheWVycyA9IFtdO1xyXG4gIFx0XHR0aGlzLl9sYXN0WkluZGV4ID0gMDtcclxuICBcdFx0dGhpcy5faGFuZGxpbmdDbGljayA9IGZhbHNlO1xyXG4gIFx0XHR0aGlzLl9wcmV2ZW50Q2xpY2sgPSBmYWxzZTtcclxuXHJcbiAgXHRcdGZvciAodmFyIGkgaW4gYmFzZUxheWVycykge1xyXG4gIFx0XHRcdHRoaXMuX2FkZExheWVyKGJhc2VMYXllcnNbaV0sIGkpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRmb3IgKGkgaW4gb3ZlcmxheXMpIHtcclxuICBcdFx0XHR0aGlzLl9hZGRMYXllcihvdmVybGF5c1tpXSwgaSwgdHJ1ZSk7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0b25BZGQ6IGZ1bmN0aW9uIChtYXApIHtcclxuICBcdFx0dGhpcy5faW5pdExheW91dCgpO1xyXG4gIFx0XHR0aGlzLl91cGRhdGUoKTtcclxuXHJcbiAgXHRcdHRoaXMuX21hcCA9IG1hcDtcclxuICBcdFx0bWFwLm9uKCd6b29tZW5kJywgdGhpcy5fY2hlY2tEaXNhYmxlZExheWVycywgdGhpcyk7XHJcblxyXG4gIFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2xheWVycy5sZW5ndGg7IGkrKykge1xyXG4gIFx0XHRcdHRoaXMuX2xheWVyc1tpXS5sYXllci5vbignYWRkIHJlbW92ZScsIHRoaXMuX29uTGF5ZXJDaGFuZ2UsIHRoaXMpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcy5fY29udGFpbmVyO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRhZGRUbzogZnVuY3Rpb24gKG1hcCkge1xyXG4gIFx0XHRDb250cm9sLnByb3RvdHlwZS5hZGRUby5jYWxsKHRoaXMsIG1hcCk7XHJcbiAgXHRcdC8vIFRyaWdnZXIgZXhwYW5kIGFmdGVyIExheWVycyBDb250cm9sIGhhcyBiZWVuIGluc2VydGVkIGludG8gRE9NIHNvIHRoYXQgaXMgbm93IGhhcyBhbiBhY3R1YWwgaGVpZ2h0LlxyXG4gIFx0XHRyZXR1cm4gdGhpcy5fZXhwYW5kSWZOb3RDb2xsYXBzZWQoKTtcclxuICBcdH0sXHJcblxyXG4gIFx0b25SZW1vdmU6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dGhpcy5fbWFwLm9mZignem9vbWVuZCcsIHRoaXMuX2NoZWNrRGlzYWJsZWRMYXllcnMsIHRoaXMpO1xyXG5cclxuICBcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9sYXllcnMubGVuZ3RoOyBpKyspIHtcclxuICBcdFx0XHR0aGlzLl9sYXllcnNbaV0ubGF5ZXIub2ZmKCdhZGQgcmVtb3ZlJywgdGhpcy5fb25MYXllckNoYW5nZSwgdGhpcyk7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBhZGRCYXNlTGF5ZXIobGF5ZXI6IExheWVyLCBuYW1lOiBTdHJpbmcpOiB0aGlzXHJcbiAgXHQvLyBBZGRzIGEgYmFzZSBsYXllciAocmFkaW8gYnV0dG9uIGVudHJ5KSB3aXRoIHRoZSBnaXZlbiBuYW1lIHRvIHRoZSBjb250cm9sLlxyXG4gIFx0YWRkQmFzZUxheWVyOiBmdW5jdGlvbiAobGF5ZXIsIG5hbWUpIHtcclxuICBcdFx0dGhpcy5fYWRkTGF5ZXIobGF5ZXIsIG5hbWUpO1xyXG4gIFx0XHRyZXR1cm4gKHRoaXMuX21hcCkgPyB0aGlzLl91cGRhdGUoKSA6IHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgYWRkT3ZlcmxheShsYXllcjogTGF5ZXIsIG5hbWU6IFN0cmluZyk6IHRoaXNcclxuICBcdC8vIEFkZHMgYW4gb3ZlcmxheSAoY2hlY2tib3ggZW50cnkpIHdpdGggdGhlIGdpdmVuIG5hbWUgdG8gdGhlIGNvbnRyb2wuXHJcbiAgXHRhZGRPdmVybGF5OiBmdW5jdGlvbiAobGF5ZXIsIG5hbWUpIHtcclxuICBcdFx0dGhpcy5fYWRkTGF5ZXIobGF5ZXIsIG5hbWUsIHRydWUpO1xyXG4gIFx0XHRyZXR1cm4gKHRoaXMuX21hcCkgPyB0aGlzLl91cGRhdGUoKSA6IHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgcmVtb3ZlTGF5ZXIobGF5ZXI6IExheWVyKTogdGhpc1xyXG4gIFx0Ly8gUmVtb3ZlIHRoZSBnaXZlbiBsYXllciBmcm9tIHRoZSBjb250cm9sLlxyXG4gIFx0cmVtb3ZlTGF5ZXI6IGZ1bmN0aW9uIChsYXllcikge1xyXG4gIFx0XHRsYXllci5vZmYoJ2FkZCByZW1vdmUnLCB0aGlzLl9vbkxheWVyQ2hhbmdlLCB0aGlzKTtcclxuXHJcbiAgXHRcdHZhciBvYmogPSB0aGlzLl9nZXRMYXllcihzdGFtcChsYXllcikpO1xyXG4gIFx0XHRpZiAob2JqKSB7XHJcbiAgXHRcdFx0dGhpcy5fbGF5ZXJzLnNwbGljZSh0aGlzLl9sYXllcnMuaW5kZXhPZihvYmopLCAxKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gKHRoaXMuX21hcCkgPyB0aGlzLl91cGRhdGUoKSA6IHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZXhwYW5kKCk6IHRoaXNcclxuICBcdC8vIEV4cGFuZCB0aGUgY29udHJvbCBjb250YWluZXIgaWYgY29sbGFwc2VkLlxyXG4gIFx0ZXhwYW5kOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGFkZENsYXNzKHRoaXMuX2NvbnRhaW5lciwgJ2xlYWZsZXQtY29udHJvbC1sYXllcnMtZXhwYW5kZWQnKTtcclxuICBcdFx0dGhpcy5fc2VjdGlvbi5zdHlsZS5oZWlnaHQgPSBudWxsO1xyXG4gIFx0XHR2YXIgYWNjZXB0YWJsZUhlaWdodCA9IHRoaXMuX21hcC5nZXRTaXplKCkueSAtICh0aGlzLl9jb250YWluZXIub2Zmc2V0VG9wICsgNTApO1xyXG4gIFx0XHRpZiAoYWNjZXB0YWJsZUhlaWdodCA8IHRoaXMuX3NlY3Rpb24uY2xpZW50SGVpZ2h0KSB7XHJcbiAgXHRcdFx0YWRkQ2xhc3ModGhpcy5fc2VjdGlvbiwgJ2xlYWZsZXQtY29udHJvbC1sYXllcnMtc2Nyb2xsYmFyJyk7XHJcbiAgXHRcdFx0dGhpcy5fc2VjdGlvbi5zdHlsZS5oZWlnaHQgPSBhY2NlcHRhYmxlSGVpZ2h0ICsgJ3B4JztcclxuICBcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRyZW1vdmVDbGFzcyh0aGlzLl9zZWN0aW9uLCAnbGVhZmxldC1jb250cm9sLWxheWVycy1zY3JvbGxiYXInKTtcclxuICBcdFx0fVxyXG4gIFx0XHR0aGlzLl9jaGVja0Rpc2FibGVkTGF5ZXJzKCk7XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGNvbGxhcHNlKCk6IHRoaXNcclxuICBcdC8vIENvbGxhcHNlIHRoZSBjb250cm9sIGNvbnRhaW5lciBpZiBleHBhbmRlZC5cclxuICBcdGNvbGxhcHNlOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJlbW92ZUNsYXNzKHRoaXMuX2NvbnRhaW5lciwgJ2xlYWZsZXQtY29udHJvbC1sYXllcnMtZXhwYW5kZWQnKTtcclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9pbml0TGF5b3V0OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHZhciBjbGFzc05hbWUgPSAnbGVhZmxldC1jb250cm9sLWxheWVycycsXHJcbiAgXHRcdCAgICBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXIgPSBjcmVhdGUkMSgnZGl2JywgY2xhc3NOYW1lKSxcclxuICBcdFx0ICAgIGNvbGxhcHNlZCA9IHRoaXMub3B0aW9ucy5jb2xsYXBzZWQ7XHJcblxyXG4gIFx0XHQvLyBtYWtlcyB0aGlzIHdvcmsgb24gSUUgdG91Y2ggZGV2aWNlcyBieSBzdG9wcGluZyBpdCBmcm9tIGZpcmluZyBhIG1vdXNlb3V0IGV2ZW50IHdoZW4gdGhlIHRvdWNoIGlzIHJlbGVhc2VkXHJcbiAgXHRcdGNvbnRhaW5lci5zZXRBdHRyaWJ1dGUoJ2FyaWEtaGFzcG9wdXAnLCB0cnVlKTtcclxuXHJcbiAgXHRcdGRpc2FibGVDbGlja1Byb3BhZ2F0aW9uKGNvbnRhaW5lcik7XHJcbiAgXHRcdGRpc2FibGVTY3JvbGxQcm9wYWdhdGlvbihjb250YWluZXIpO1xyXG5cclxuICBcdFx0dmFyIHNlY3Rpb24gPSB0aGlzLl9zZWN0aW9uID0gY3JlYXRlJDEoJ3NlY3Rpb24nLCBjbGFzc05hbWUgKyAnLWxpc3QnKTtcclxuXHJcbiAgXHRcdGlmIChjb2xsYXBzZWQpIHtcclxuICBcdFx0XHR0aGlzLl9tYXAub24oJ2NsaWNrJywgdGhpcy5jb2xsYXBzZSwgdGhpcyk7XHJcblxyXG4gIFx0XHRcdG9uKGNvbnRhaW5lciwge1xyXG4gIFx0XHRcdFx0bW91c2VlbnRlcjogdGhpcy5fZXhwYW5kU2FmZWx5LFxyXG4gIFx0XHRcdFx0bW91c2VsZWF2ZTogdGhpcy5jb2xsYXBzZVxyXG4gIFx0XHRcdH0sIHRoaXMpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgbGluayA9IHRoaXMuX2xheWVyc0xpbmsgPSBjcmVhdGUkMSgnYScsIGNsYXNzTmFtZSArICctdG9nZ2xlJywgY29udGFpbmVyKTtcclxuICBcdFx0bGluay5ocmVmID0gJyMnO1xyXG4gIFx0XHRsaW5rLnRpdGxlID0gJ0xheWVycyc7XHJcbiAgXHRcdGxpbmsuc2V0QXR0cmlidXRlKCdyb2xlJywgJ2J1dHRvbicpO1xyXG5cclxuICBcdFx0b24obGluaywge1xyXG4gIFx0XHRcdGtleWRvd246IGZ1bmN0aW9uIChlKSB7XHJcbiAgXHRcdFx0XHRpZiAoZS5rZXlDb2RlID09PSAxMykge1xyXG4gIFx0XHRcdFx0XHR0aGlzLl9leHBhbmRTYWZlbHkoKTtcclxuICBcdFx0XHRcdH1cclxuICBcdFx0XHR9LFxyXG4gIFx0XHRcdC8vIENlcnRhaW4gc2NyZWVuIHJlYWRlcnMgaW50ZXJjZXB0IHRoZSBrZXkgZXZlbnQgYW5kIGluc3RlYWQgc2VuZCBhIGNsaWNrIGV2ZW50XHJcbiAgXHRcdFx0Y2xpY2s6IGZ1bmN0aW9uIChlKSB7XHJcbiAgXHRcdFx0XHRwcmV2ZW50RGVmYXVsdChlKTtcclxuICBcdFx0XHRcdHRoaXMuX2V4cGFuZFNhZmVseSgpO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fSwgdGhpcyk7XHJcblxyXG4gIFx0XHRpZiAoIWNvbGxhcHNlZCkge1xyXG4gIFx0XHRcdHRoaXMuZXhwYW5kKCk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX2Jhc2VMYXllcnNMaXN0ID0gY3JlYXRlJDEoJ2RpdicsIGNsYXNzTmFtZSArICctYmFzZScsIHNlY3Rpb24pO1xyXG4gIFx0XHR0aGlzLl9zZXBhcmF0b3IgPSBjcmVhdGUkMSgnZGl2JywgY2xhc3NOYW1lICsgJy1zZXBhcmF0b3InLCBzZWN0aW9uKTtcclxuICBcdFx0dGhpcy5fb3ZlcmxheXNMaXN0ID0gY3JlYXRlJDEoJ2RpdicsIGNsYXNzTmFtZSArICctb3ZlcmxheXMnLCBzZWN0aW9uKTtcclxuXHJcbiAgXHRcdGNvbnRhaW5lci5hcHBlbmRDaGlsZChzZWN0aW9uKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X2dldExheWVyOiBmdW5jdGlvbiAoaWQpIHtcclxuICBcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9sYXllcnMubGVuZ3RoOyBpKyspIHtcclxuXHJcbiAgXHRcdFx0aWYgKHRoaXMuX2xheWVyc1tpXSAmJiBzdGFtcCh0aGlzLl9sYXllcnNbaV0ubGF5ZXIpID09PSBpZCkge1xyXG4gIFx0XHRcdFx0cmV0dXJuIHRoaXMuX2xheWVyc1tpXTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0X2FkZExheWVyOiBmdW5jdGlvbiAobGF5ZXIsIG5hbWUsIG92ZXJsYXkpIHtcclxuICBcdFx0aWYgKHRoaXMuX21hcCkge1xyXG4gIFx0XHRcdGxheWVyLm9uKCdhZGQgcmVtb3ZlJywgdGhpcy5fb25MYXllckNoYW5nZSwgdGhpcyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX2xheWVycy5wdXNoKHtcclxuICBcdFx0XHRsYXllcjogbGF5ZXIsXHJcbiAgXHRcdFx0bmFtZTogbmFtZSxcclxuICBcdFx0XHRvdmVybGF5OiBvdmVybGF5XHJcbiAgXHRcdH0pO1xyXG5cclxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5zb3J0TGF5ZXJzKSB7XHJcbiAgXHRcdFx0dGhpcy5fbGF5ZXJzLnNvcnQoYmluZChmdW5jdGlvbiAoYSwgYikge1xyXG4gIFx0XHRcdFx0cmV0dXJuIHRoaXMub3B0aW9ucy5zb3J0RnVuY3Rpb24oYS5sYXllciwgYi5sYXllciwgYS5uYW1lLCBiLm5hbWUpO1xyXG4gIFx0XHRcdH0sIHRoaXMpKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5hdXRvWkluZGV4ICYmIGxheWVyLnNldFpJbmRleCkge1xyXG4gIFx0XHRcdHRoaXMuX2xhc3RaSW5kZXgrKztcclxuICBcdFx0XHRsYXllci5zZXRaSW5kZXgodGhpcy5fbGFzdFpJbmRleCk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX2V4cGFuZElmTm90Q29sbGFwc2VkKCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF91cGRhdGU6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKCF0aGlzLl9jb250YWluZXIpIHsgcmV0dXJuIHRoaXM7IH1cclxuXHJcbiAgXHRcdGVtcHR5KHRoaXMuX2Jhc2VMYXllcnNMaXN0KTtcclxuICBcdFx0ZW1wdHkodGhpcy5fb3ZlcmxheXNMaXN0KTtcclxuXHJcbiAgXHRcdHRoaXMuX2xheWVyQ29udHJvbElucHV0cyA9IFtdO1xyXG4gIFx0XHR2YXIgYmFzZUxheWVyc1ByZXNlbnQsIG92ZXJsYXlzUHJlc2VudCwgaSwgb2JqLCBiYXNlTGF5ZXJzQ291bnQgPSAwO1xyXG5cclxuICBcdFx0Zm9yIChpID0gMDsgaSA8IHRoaXMuX2xheWVycy5sZW5ndGg7IGkrKykge1xyXG4gIFx0XHRcdG9iaiA9IHRoaXMuX2xheWVyc1tpXTtcclxuICBcdFx0XHR0aGlzLl9hZGRJdGVtKG9iaik7XHJcbiAgXHRcdFx0b3ZlcmxheXNQcmVzZW50ID0gb3ZlcmxheXNQcmVzZW50IHx8IG9iai5vdmVybGF5O1xyXG4gIFx0XHRcdGJhc2VMYXllcnNQcmVzZW50ID0gYmFzZUxheWVyc1ByZXNlbnQgfHwgIW9iai5vdmVybGF5O1xyXG4gIFx0XHRcdGJhc2VMYXllcnNDb3VudCArPSAhb2JqLm92ZXJsYXkgPyAxIDogMDtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gSGlkZSBiYXNlIGxheWVycyBzZWN0aW9uIGlmIHRoZXJlJ3Mgb25seSBvbmUgbGF5ZXIuXHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMuaGlkZVNpbmdsZUJhc2UpIHtcclxuICBcdFx0XHRiYXNlTGF5ZXJzUHJlc2VudCA9IGJhc2VMYXllcnNQcmVzZW50ICYmIGJhc2VMYXllcnNDb3VudCA+IDE7XHJcbiAgXHRcdFx0dGhpcy5fYmFzZUxheWVyc0xpc3Quc3R5bGUuZGlzcGxheSA9IGJhc2VMYXllcnNQcmVzZW50ID8gJycgOiAnbm9uZSc7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX3NlcGFyYXRvci5zdHlsZS5kaXNwbGF5ID0gb3ZlcmxheXNQcmVzZW50ICYmIGJhc2VMYXllcnNQcmVzZW50ID8gJycgOiAnbm9uZSc7XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0X29uTGF5ZXJDaGFuZ2U6IGZ1bmN0aW9uIChlKSB7XHJcbiAgXHRcdGlmICghdGhpcy5faGFuZGxpbmdDbGljaykge1xyXG4gIFx0XHRcdHRoaXMuX3VwZGF0ZSgpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgb2JqID0gdGhpcy5fZ2V0TGF5ZXIoc3RhbXAoZS50YXJnZXQpKTtcclxuXHJcbiAgXHRcdC8vIEBuYW1lc3BhY2UgTWFwXHJcbiAgXHRcdC8vIEBzZWN0aW9uIExheWVyIGV2ZW50c1xyXG4gIFx0XHQvLyBAZXZlbnQgYmFzZWxheWVyY2hhbmdlOiBMYXllcnNDb250cm9sRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgYmFzZSBsYXllciBpcyBjaGFuZ2VkIHRocm91Z2ggdGhlIFtsYXllcnMgY29udHJvbF0oI2NvbnRyb2wtbGF5ZXJzKS5cclxuICBcdFx0Ly8gQGV2ZW50IG92ZXJsYXlhZGQ6IExheWVyc0NvbnRyb2xFdmVudFxyXG4gIFx0XHQvLyBGaXJlZCB3aGVuIGFuIG92ZXJsYXkgaXMgc2VsZWN0ZWQgdGhyb3VnaCB0aGUgW2xheWVycyBjb250cm9sXSgjY29udHJvbC1sYXllcnMpLlxyXG4gIFx0XHQvLyBAZXZlbnQgb3ZlcmxheXJlbW92ZTogTGF5ZXJzQ29udHJvbEV2ZW50XHJcbiAgXHRcdC8vIEZpcmVkIHdoZW4gYW4gb3ZlcmxheSBpcyBkZXNlbGVjdGVkIHRocm91Z2ggdGhlIFtsYXllcnMgY29udHJvbF0oI2NvbnRyb2wtbGF5ZXJzKS5cclxuICBcdFx0Ly8gQG5hbWVzcGFjZSBDb250cm9sLkxheWVyc1xyXG4gIFx0XHR2YXIgdHlwZSA9IG9iai5vdmVybGF5ID9cclxuICBcdFx0XHQoZS50eXBlID09PSAnYWRkJyA/ICdvdmVybGF5YWRkJyA6ICdvdmVybGF5cmVtb3ZlJykgOlxyXG4gIFx0XHRcdChlLnR5cGUgPT09ICdhZGQnID8gJ2Jhc2VsYXllcmNoYW5nZScgOiBudWxsKTtcclxuXHJcbiAgXHRcdGlmICh0eXBlKSB7XHJcbiAgXHRcdFx0dGhpcy5fbWFwLmZpcmUodHlwZSwgb2JqKTtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBJRTcgYnVncyBvdXQgaWYgeW91IGNyZWF0ZSBhIHJhZGlvIGR5bmFtaWNhbGx5LCBzbyB5b3UgaGF2ZSB0byBkbyBpdCB0aGlzIGhhY2t5IHdheSAoc2VlIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8xMTkwNzkpXHJcbiAgXHRfY3JlYXRlUmFkaW9FbGVtZW50OiBmdW5jdGlvbiAobmFtZSwgY2hlY2tlZCkge1xyXG5cclxuICBcdFx0dmFyIHJhZGlvSHRtbCA9ICc8aW5wdXQgdHlwZT1cInJhZGlvXCIgY2xhc3M9XCJsZWFmbGV0LWNvbnRyb2wtbGF5ZXJzLXNlbGVjdG9yXCIgbmFtZT1cIicgK1xyXG4gIFx0XHRcdFx0bmFtZSArICdcIicgKyAoY2hlY2tlZCA/ICcgY2hlY2tlZD1cImNoZWNrZWRcIicgOiAnJykgKyAnLz4nO1xyXG5cclxuICBcdFx0dmFyIHJhZGlvRnJhZ21lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcclxuICBcdFx0cmFkaW9GcmFnbWVudC5pbm5lckhUTUwgPSByYWRpb0h0bWw7XHJcblxyXG4gIFx0XHRyZXR1cm4gcmFkaW9GcmFnbWVudC5maXJzdENoaWxkO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfYWRkSXRlbTogZnVuY3Rpb24gKG9iaikge1xyXG4gIFx0XHR2YXIgbGFiZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdsYWJlbCcpLFxyXG4gIFx0XHQgICAgY2hlY2tlZCA9IHRoaXMuX21hcC5oYXNMYXllcihvYmoubGF5ZXIpLFxyXG4gIFx0XHQgICAgaW5wdXQ7XHJcblxyXG4gIFx0XHRpZiAob2JqLm92ZXJsYXkpIHtcclxuICBcdFx0XHRpbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0Jyk7XHJcbiAgXHRcdFx0aW5wdXQudHlwZSA9ICdjaGVja2JveCc7XHJcbiAgXHRcdFx0aW5wdXQuY2xhc3NOYW1lID0gJ2xlYWZsZXQtY29udHJvbC1sYXllcnMtc2VsZWN0b3InO1xyXG4gIFx0XHRcdGlucHV0LmRlZmF1bHRDaGVja2VkID0gY2hlY2tlZDtcclxuICBcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRpbnB1dCA9IHRoaXMuX2NyZWF0ZVJhZGlvRWxlbWVudCgnbGVhZmxldC1iYXNlLWxheWVyc18nICsgc3RhbXAodGhpcyksIGNoZWNrZWQpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR0aGlzLl9sYXllckNvbnRyb2xJbnB1dHMucHVzaChpbnB1dCk7XHJcbiAgXHRcdGlucHV0LmxheWVySWQgPSBzdGFtcChvYmoubGF5ZXIpO1xyXG5cclxuICBcdFx0b24oaW5wdXQsICdjbGljaycsIHRoaXMuX29uSW5wdXRDbGljaywgdGhpcyk7XHJcblxyXG4gIFx0XHR2YXIgbmFtZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKTtcclxuICBcdFx0bmFtZS5pbm5lckhUTUwgPSAnICcgKyBvYmoubmFtZTtcclxuXHJcbiAgXHRcdC8vIEhlbHBzIGZyb20gcHJldmVudGluZyBsYXllciBjb250cm9sIGZsaWNrZXIgd2hlbiBjaGVja2JveGVzIGFyZSBkaXNhYmxlZFxyXG4gIFx0XHQvLyBodHRwczovL2dpdGh1Yi5jb20vTGVhZmxldC9MZWFmbGV0L2lzc3Vlcy8yNzcxXHJcbiAgXHRcdHZhciBob2xkZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyk7XHJcblxyXG4gIFx0XHRsYWJlbC5hcHBlbmRDaGlsZChob2xkZXIpO1xyXG4gIFx0XHRob2xkZXIuYXBwZW5kQ2hpbGQoaW5wdXQpO1xyXG4gIFx0XHRob2xkZXIuYXBwZW5kQ2hpbGQobmFtZSk7XHJcblxyXG4gIFx0XHR2YXIgY29udGFpbmVyID0gb2JqLm92ZXJsYXkgPyB0aGlzLl9vdmVybGF5c0xpc3QgOiB0aGlzLl9iYXNlTGF5ZXJzTGlzdDtcclxuICBcdFx0Y29udGFpbmVyLmFwcGVuZENoaWxkKGxhYmVsKTtcclxuXHJcbiAgXHRcdHRoaXMuX2NoZWNrRGlzYWJsZWRMYXllcnMoKTtcclxuICBcdFx0cmV0dXJuIGxhYmVsO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfb25JbnB1dENsaWNrOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdC8vIGV4cGFuZGluZyB0aGUgY29udHJvbCBvbiBtb2JpbGUgd2l0aCBhIGNsaWNrIGNhbiBjYXVzZSBhZGRpbmcgYSBsYXllciAtIHdlIGRvbid0IHdhbnQgdGhpc1xyXG4gIFx0XHRpZiAodGhpcy5fcHJldmVudENsaWNrKSB7XHJcbiAgXHRcdFx0cmV0dXJuO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgaW5wdXRzID0gdGhpcy5fbGF5ZXJDb250cm9sSW5wdXRzLFxyXG4gIFx0XHQgICAgaW5wdXQsIGxheWVyO1xyXG4gIFx0XHR2YXIgYWRkZWRMYXllcnMgPSBbXSxcclxuICBcdFx0ICAgIHJlbW92ZWRMYXllcnMgPSBbXTtcclxuXHJcbiAgXHRcdHRoaXMuX2hhbmRsaW5nQ2xpY2sgPSB0cnVlO1xyXG5cclxuICBcdFx0Zm9yICh2YXIgaSA9IGlucHV0cy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xyXG4gIFx0XHRcdGlucHV0ID0gaW5wdXRzW2ldO1xyXG4gIFx0XHRcdGxheWVyID0gdGhpcy5fZ2V0TGF5ZXIoaW5wdXQubGF5ZXJJZCkubGF5ZXI7XHJcblxyXG4gIFx0XHRcdGlmIChpbnB1dC5jaGVja2VkKSB7XHJcbiAgXHRcdFx0XHRhZGRlZExheWVycy5wdXNoKGxheWVyKTtcclxuICBcdFx0XHR9IGVsc2UgaWYgKCFpbnB1dC5jaGVja2VkKSB7XHJcbiAgXHRcdFx0XHRyZW1vdmVkTGF5ZXJzLnB1c2gobGF5ZXIpO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gQnVnZml4IGlzc3VlIDIzMTg6IFNob3VsZCByZW1vdmUgYWxsIG9sZCBsYXllcnMgYmVmb3JlIHJlYWRkaW5nIG5ldyBvbmVzXHJcbiAgXHRcdGZvciAoaSA9IDA7IGkgPCByZW1vdmVkTGF5ZXJzLmxlbmd0aDsgaSsrKSB7XHJcbiAgXHRcdFx0aWYgKHRoaXMuX21hcC5oYXNMYXllcihyZW1vdmVkTGF5ZXJzW2ldKSkge1xyXG4gIFx0XHRcdFx0dGhpcy5fbWFwLnJlbW92ZUxheWVyKHJlbW92ZWRMYXllcnNbaV0pO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG4gIFx0XHRmb3IgKGkgPSAwOyBpIDwgYWRkZWRMYXllcnMubGVuZ3RoOyBpKyspIHtcclxuICBcdFx0XHRpZiAoIXRoaXMuX21hcC5oYXNMYXllcihhZGRlZExheWVyc1tpXSkpIHtcclxuICBcdFx0XHRcdHRoaXMuX21hcC5hZGRMYXllcihhZGRlZExheWVyc1tpXSk7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR0aGlzLl9oYW5kbGluZ0NsaWNrID0gZmFsc2U7XHJcblxyXG4gIFx0XHR0aGlzLl9yZWZvY3VzT25NYXAoKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X2NoZWNrRGlzYWJsZWRMYXllcnM6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dmFyIGlucHV0cyA9IHRoaXMuX2xheWVyQ29udHJvbElucHV0cyxcclxuICBcdFx0ICAgIGlucHV0LFxyXG4gIFx0XHQgICAgbGF5ZXIsXHJcbiAgXHRcdCAgICB6b29tID0gdGhpcy5fbWFwLmdldFpvb20oKTtcclxuXHJcbiAgXHRcdGZvciAodmFyIGkgPSBpbnB1dHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcclxuICBcdFx0XHRpbnB1dCA9IGlucHV0c1tpXTtcclxuICBcdFx0XHRsYXllciA9IHRoaXMuX2dldExheWVyKGlucHV0LmxheWVySWQpLmxheWVyO1xyXG4gIFx0XHRcdGlucHV0LmRpc2FibGVkID0gKGxheWVyLm9wdGlvbnMubWluWm9vbSAhPT0gdW5kZWZpbmVkICYmIHpvb20gPCBsYXllci5vcHRpb25zLm1pblpvb20pIHx8XHJcbiAgXHRcdFx0ICAgICAgICAgICAgICAgICAobGF5ZXIub3B0aW9ucy5tYXhab29tICE9PSB1bmRlZmluZWQgJiYgem9vbSA+IGxheWVyLm9wdGlvbnMubWF4Wm9vbSk7XHJcblxyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdF9leHBhbmRJZk5vdENvbGxhcHNlZDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRpZiAodGhpcy5fbWFwICYmICF0aGlzLm9wdGlvbnMuY29sbGFwc2VkKSB7XHJcbiAgXHRcdFx0dGhpcy5leHBhbmQoKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0X2V4cGFuZFNhZmVseTogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR2YXIgc2VjdGlvbiA9IHRoaXMuX3NlY3Rpb247XHJcbiAgXHRcdHRoaXMuX3ByZXZlbnRDbGljayA9IHRydWU7XHJcbiAgXHRcdG9uKHNlY3Rpb24sICdjbGljaycsIHByZXZlbnREZWZhdWx0KTtcclxuICBcdFx0dGhpcy5leHBhbmQoKTtcclxuICBcdFx0dmFyIHRoYXQgPSB0aGlzO1xyXG4gIFx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcclxuICBcdFx0XHRvZmYoc2VjdGlvbiwgJ2NsaWNrJywgcHJldmVudERlZmF1bHQpO1xyXG4gIFx0XHRcdHRoYXQuX3ByZXZlbnRDbGljayA9IGZhbHNlO1xyXG4gIFx0XHR9KTtcclxuICBcdH1cclxuXHJcbiAgfSk7XHJcblxyXG5cclxuICAvLyBAZmFjdG9yeSBMLmNvbnRyb2wubGF5ZXJzKGJhc2VsYXllcnM/OiBPYmplY3QsIG92ZXJsYXlzPzogT2JqZWN0LCBvcHRpb25zPzogQ29udHJvbC5MYXllcnMgb3B0aW9ucylcclxuICAvLyBDcmVhdGVzIGEgbGF5ZXJzIGNvbnRyb2wgd2l0aCB0aGUgZ2l2ZW4gbGF5ZXJzLiBCYXNlIGxheWVycyB3aWxsIGJlIHN3aXRjaGVkIHdpdGggcmFkaW8gYnV0dG9ucywgd2hpbGUgb3ZlcmxheXMgd2lsbCBiZSBzd2l0Y2hlZCB3aXRoIGNoZWNrYm94ZXMuIE5vdGUgdGhhdCBhbGwgYmFzZSBsYXllcnMgc2hvdWxkIGJlIHBhc3NlZCBpbiB0aGUgYmFzZSBsYXllcnMgb2JqZWN0LCBidXQgb25seSBvbmUgc2hvdWxkIGJlIGFkZGVkIHRvIHRoZSBtYXAgZHVyaW5nIG1hcCBpbnN0YW50aWF0aW9uLlxyXG4gIHZhciBsYXllcnMgPSBmdW5jdGlvbiAoYmFzZUxheWVycywgb3ZlcmxheXMsIG9wdGlvbnMpIHtcclxuICBcdHJldHVybiBuZXcgTGF5ZXJzKGJhc2VMYXllcnMsIG92ZXJsYXlzLCBvcHRpb25zKTtcclxuICB9O1xuXG4gIC8qXHJcbiAgICogQGNsYXNzIENvbnRyb2wuWm9vbVxyXG4gICAqIEBha2EgTC5Db250cm9sLlpvb21cclxuICAgKiBAaW5oZXJpdHMgQ29udHJvbFxyXG4gICAqXHJcbiAgICogQSBiYXNpYyB6b29tIGNvbnRyb2wgd2l0aCB0d28gYnV0dG9ucyAoem9vbSBpbiBhbmQgem9vbSBvdXQpLiBJdCBpcyBwdXQgb24gdGhlIG1hcCBieSBkZWZhdWx0IHVubGVzcyB5b3Ugc2V0IGl0cyBbYHpvb21Db250cm9sYCBvcHRpb25dKCNtYXAtem9vbWNvbnRyb2wpIHRvIGBmYWxzZWAuIEV4dGVuZHMgYENvbnRyb2xgLlxyXG4gICAqL1xyXG5cclxuICB2YXIgWm9vbSA9IENvbnRyb2wuZXh0ZW5kKHtcclxuICBcdC8vIEBzZWN0aW9uXHJcbiAgXHQvLyBAYWthIENvbnRyb2wuWm9vbSBvcHRpb25zXHJcbiAgXHRvcHRpb25zOiB7XHJcbiAgXHRcdHBvc2l0aW9uOiAndG9wbGVmdCcsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHpvb21JblRleHQ6IFN0cmluZyA9ICc8c3BhbiBhcmlhLWhpZGRlbj1cInRydWVcIj4rPC9zcGFuPidcclxuICBcdFx0Ly8gVGhlIHRleHQgc2V0IG9uIHRoZSAnem9vbSBpbicgYnV0dG9uLlxyXG4gIFx0XHR6b29tSW5UZXh0OiAnPHNwYW4gYXJpYS1oaWRkZW49XCJ0cnVlXCI+Kzwvc3Bhbj4nLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiB6b29tSW5UaXRsZTogU3RyaW5nID0gJ1pvb20gaW4nXHJcbiAgXHRcdC8vIFRoZSB0aXRsZSBzZXQgb24gdGhlICd6b29tIGluJyBidXR0b24uXHJcbiAgXHRcdHpvb21JblRpdGxlOiAnWm9vbSBpbicsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHpvb21PdXRUZXh0OiBTdHJpbmcgPSAnPHNwYW4gYXJpYS1oaWRkZW49XCJ0cnVlXCI+JiN4MjIxMjs8L3NwYW4+J1xyXG4gIFx0XHQvLyBUaGUgdGV4dCBzZXQgb24gdGhlICd6b29tIG91dCcgYnV0dG9uLlxyXG4gIFx0XHR6b29tT3V0VGV4dDogJzxzcGFuIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPiYjeDIyMTI7PC9zcGFuPicsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHpvb21PdXRUaXRsZTogU3RyaW5nID0gJ1pvb20gb3V0J1xyXG4gIFx0XHQvLyBUaGUgdGl0bGUgc2V0IG9uIHRoZSAnem9vbSBvdXQnIGJ1dHRvbi5cclxuICBcdFx0em9vbU91dFRpdGxlOiAnWm9vbSBvdXQnXHJcbiAgXHR9LFxyXG5cclxuICBcdG9uQWRkOiBmdW5jdGlvbiAobWFwKSB7XHJcbiAgXHRcdHZhciB6b29tTmFtZSA9ICdsZWFmbGV0LWNvbnRyb2wtem9vbScsXHJcbiAgXHRcdCAgICBjb250YWluZXIgPSBjcmVhdGUkMSgnZGl2Jywgem9vbU5hbWUgKyAnIGxlYWZsZXQtYmFyJyksXHJcbiAgXHRcdCAgICBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xyXG5cclxuICBcdFx0dGhpcy5fem9vbUluQnV0dG9uICA9IHRoaXMuX2NyZWF0ZUJ1dHRvbihvcHRpb25zLnpvb21JblRleHQsIG9wdGlvbnMuem9vbUluVGl0bGUsXHJcbiAgXHRcdCAgICAgICAgem9vbU5hbWUgKyAnLWluJywgIGNvbnRhaW5lciwgdGhpcy5fem9vbUluKTtcclxuICBcdFx0dGhpcy5fem9vbU91dEJ1dHRvbiA9IHRoaXMuX2NyZWF0ZUJ1dHRvbihvcHRpb25zLnpvb21PdXRUZXh0LCBvcHRpb25zLnpvb21PdXRUaXRsZSxcclxuICBcdFx0ICAgICAgICB6b29tTmFtZSArICctb3V0JywgY29udGFpbmVyLCB0aGlzLl96b29tT3V0KTtcclxuXHJcbiAgXHRcdHRoaXMuX3VwZGF0ZURpc2FibGVkKCk7XHJcbiAgXHRcdG1hcC5vbignem9vbWVuZCB6b29tbGV2ZWxzY2hhbmdlJywgdGhpcy5fdXBkYXRlRGlzYWJsZWQsIHRoaXMpO1xyXG5cclxuICBcdFx0cmV0dXJuIGNvbnRhaW5lcjtcclxuICBcdH0sXHJcblxyXG4gIFx0b25SZW1vdmU6IGZ1bmN0aW9uIChtYXApIHtcclxuICBcdFx0bWFwLm9mZignem9vbWVuZCB6b29tbGV2ZWxzY2hhbmdlJywgdGhpcy5fdXBkYXRlRGlzYWJsZWQsIHRoaXMpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRkaXNhYmxlOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHRoaXMuX2Rpc2FibGVkID0gdHJ1ZTtcclxuICBcdFx0dGhpcy5fdXBkYXRlRGlzYWJsZWQoKTtcclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdGVuYWJsZTogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR0aGlzLl9kaXNhYmxlZCA9IGZhbHNlO1xyXG4gIFx0XHR0aGlzLl91cGRhdGVEaXNhYmxlZCgpO1xyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0X3pvb21JbjogZnVuY3Rpb24gKGUpIHtcclxuICBcdFx0aWYgKCF0aGlzLl9kaXNhYmxlZCAmJiB0aGlzLl9tYXAuX3pvb20gPCB0aGlzLl9tYXAuZ2V0TWF4Wm9vbSgpKSB7XHJcbiAgXHRcdFx0dGhpcy5fbWFwLnpvb21Jbih0aGlzLl9tYXAub3B0aW9ucy56b29tRGVsdGEgKiAoZS5zaGlmdEtleSA/IDMgOiAxKSk7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0X3pvb21PdXQ6IGZ1bmN0aW9uIChlKSB7XHJcbiAgXHRcdGlmICghdGhpcy5fZGlzYWJsZWQgJiYgdGhpcy5fbWFwLl96b29tID4gdGhpcy5fbWFwLmdldE1pblpvb20oKSkge1xyXG4gIFx0XHRcdHRoaXMuX21hcC56b29tT3V0KHRoaXMuX21hcC5vcHRpb25zLnpvb21EZWx0YSAqIChlLnNoaWZ0S2V5ID8gMyA6IDEpKTtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHRfY3JlYXRlQnV0dG9uOiBmdW5jdGlvbiAoaHRtbCwgdGl0bGUsIGNsYXNzTmFtZSwgY29udGFpbmVyLCBmbikge1xyXG4gIFx0XHR2YXIgbGluayA9IGNyZWF0ZSQxKCdhJywgY2xhc3NOYW1lLCBjb250YWluZXIpO1xyXG4gIFx0XHRsaW5rLmlubmVySFRNTCA9IGh0bWw7XHJcbiAgXHRcdGxpbmsuaHJlZiA9ICcjJztcclxuICBcdFx0bGluay50aXRsZSA9IHRpdGxlO1xyXG5cclxuICBcdFx0LypcclxuICBcdFx0ICogV2lsbCBmb3JjZSBzY3JlZW4gcmVhZGVycyBsaWtlIFZvaWNlT3ZlciB0byByZWFkIHRoaXMgYXMgXCJab29tIGluIC0gYnV0dG9uXCJcclxuICBcdFx0ICovXHJcbiAgXHRcdGxpbmsuc2V0QXR0cmlidXRlKCdyb2xlJywgJ2J1dHRvbicpO1xyXG4gIFx0XHRsaW5rLnNldEF0dHJpYnV0ZSgnYXJpYS1sYWJlbCcsIHRpdGxlKTtcclxuXHJcbiAgXHRcdGRpc2FibGVDbGlja1Byb3BhZ2F0aW9uKGxpbmspO1xyXG4gIFx0XHRvbihsaW5rLCAnY2xpY2snLCBzdG9wKTtcclxuICBcdFx0b24obGluaywgJ2NsaWNrJywgZm4sIHRoaXMpO1xyXG4gIFx0XHRvbihsaW5rLCAnY2xpY2snLCB0aGlzLl9yZWZvY3VzT25NYXAsIHRoaXMpO1xyXG5cclxuICBcdFx0cmV0dXJuIGxpbms7XHJcbiAgXHR9LFxyXG5cclxuICBcdF91cGRhdGVEaXNhYmxlZDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR2YXIgbWFwID0gdGhpcy5fbWFwLFxyXG4gIFx0XHQgICAgY2xhc3NOYW1lID0gJ2xlYWZsZXQtZGlzYWJsZWQnO1xyXG5cclxuICBcdFx0cmVtb3ZlQ2xhc3ModGhpcy5fem9vbUluQnV0dG9uLCBjbGFzc05hbWUpO1xyXG4gIFx0XHRyZW1vdmVDbGFzcyh0aGlzLl96b29tT3V0QnV0dG9uLCBjbGFzc05hbWUpO1xyXG4gIFx0XHR0aGlzLl96b29tSW5CdXR0b24uc2V0QXR0cmlidXRlKCdhcmlhLWRpc2FibGVkJywgJ2ZhbHNlJyk7XHJcbiAgXHRcdHRoaXMuX3pvb21PdXRCdXR0b24uc2V0QXR0cmlidXRlKCdhcmlhLWRpc2FibGVkJywgJ2ZhbHNlJyk7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fZGlzYWJsZWQgfHwgbWFwLl96b29tID09PSBtYXAuZ2V0TWluWm9vbSgpKSB7XHJcbiAgXHRcdFx0YWRkQ2xhc3ModGhpcy5fem9vbU91dEJ1dHRvbiwgY2xhc3NOYW1lKTtcclxuICBcdFx0XHR0aGlzLl96b29tT3V0QnV0dG9uLnNldEF0dHJpYnV0ZSgnYXJpYS1kaXNhYmxlZCcsICd0cnVlJyk7XHJcbiAgXHRcdH1cclxuICBcdFx0aWYgKHRoaXMuX2Rpc2FibGVkIHx8IG1hcC5fem9vbSA9PT0gbWFwLmdldE1heFpvb20oKSkge1xyXG4gIFx0XHRcdGFkZENsYXNzKHRoaXMuX3pvb21JbkJ1dHRvbiwgY2xhc3NOYW1lKTtcclxuICBcdFx0XHR0aGlzLl96b29tSW5CdXR0b24uc2V0QXR0cmlidXRlKCdhcmlhLWRpc2FibGVkJywgJ3RydWUnKTtcclxuICBcdFx0fVxyXG4gIFx0fVxyXG4gIH0pO1xyXG5cclxuICAvLyBAbmFtZXNwYWNlIE1hcFxyXG4gIC8vIEBzZWN0aW9uIENvbnRyb2wgb3B0aW9uc1xyXG4gIC8vIEBvcHRpb24gem9vbUNvbnRyb2w6IEJvb2xlYW4gPSB0cnVlXHJcbiAgLy8gV2hldGhlciBhIFt6b29tIGNvbnRyb2xdKCNjb250cm9sLXpvb20pIGlzIGFkZGVkIHRvIHRoZSBtYXAgYnkgZGVmYXVsdC5cclxuICBNYXAubWVyZ2VPcHRpb25zKHtcclxuICBcdHpvb21Db250cm9sOiB0cnVlXHJcbiAgfSk7XHJcblxyXG4gIE1hcC5hZGRJbml0SG9vayhmdW5jdGlvbiAoKSB7XHJcbiAgXHRpZiAodGhpcy5vcHRpb25zLnpvb21Db250cm9sKSB7XHJcbiAgXHRcdC8vIEBzZWN0aW9uIENvbnRyb2xzXHJcbiAgXHRcdC8vIEBwcm9wZXJ0eSB6b29tQ29udHJvbDogQ29udHJvbC5ab29tXHJcbiAgXHRcdC8vIFRoZSBkZWZhdWx0IHpvb20gY29udHJvbCAob25seSBhdmFpbGFibGUgaWYgdGhlXHJcbiAgXHRcdC8vIFtgem9vbUNvbnRyb2xgIG9wdGlvbl0oI21hcC16b29tY29udHJvbCkgd2FzIGB0cnVlYCB3aGVuIGNyZWF0aW5nIHRoZSBtYXApLlxyXG4gIFx0XHR0aGlzLnpvb21Db250cm9sID0gbmV3IFpvb20oKTtcclxuICBcdFx0dGhpcy5hZGRDb250cm9sKHRoaXMuem9vbUNvbnRyb2wpO1xyXG4gIFx0fVxyXG4gIH0pO1xyXG5cclxuICAvLyBAbmFtZXNwYWNlIENvbnRyb2wuWm9vbVxyXG4gIC8vIEBmYWN0b3J5IEwuY29udHJvbC56b29tKG9wdGlvbnM6IENvbnRyb2wuWm9vbSBvcHRpb25zKVxyXG4gIC8vIENyZWF0ZXMgYSB6b29tIGNvbnRyb2xcclxuICB2YXIgem9vbSA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcbiAgXHRyZXR1cm4gbmV3IFpvb20ob3B0aW9ucyk7XHJcbiAgfTtcblxuICAvKlxuICAgKiBAY2xhc3MgQ29udHJvbC5TY2FsZVxuICAgKiBAYWthIEwuQ29udHJvbC5TY2FsZVxuICAgKiBAaW5oZXJpdHMgQ29udHJvbFxuICAgKlxuICAgKiBBIHNpbXBsZSBzY2FsZSBjb250cm9sIHRoYXQgc2hvd3MgdGhlIHNjYWxlIG9mIHRoZSBjdXJyZW50IGNlbnRlciBvZiBzY3JlZW4gaW4gbWV0cmljIChtL2ttKSBhbmQgaW1wZXJpYWwgKG1pL2Z0KSBzeXN0ZW1zLiBFeHRlbmRzIGBDb250cm9sYC5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICpcbiAgICogYGBganNcbiAgICogTC5jb250cm9sLnNjYWxlKCkuYWRkVG8obWFwKTtcbiAgICogYGBgXG4gICAqL1xuXG4gIHZhciBTY2FsZSA9IENvbnRyb2wuZXh0ZW5kKHtcbiAgXHQvLyBAc2VjdGlvblxuICBcdC8vIEBha2EgQ29udHJvbC5TY2FsZSBvcHRpb25zXG4gIFx0b3B0aW9uczoge1xuICBcdFx0cG9zaXRpb246ICdib3R0b21sZWZ0JyxcblxuICBcdFx0Ly8gQG9wdGlvbiBtYXhXaWR0aDogTnVtYmVyID0gMTAwXG4gIFx0XHQvLyBNYXhpbXVtIHdpZHRoIG9mIHRoZSBjb250cm9sIGluIHBpeGVscy4gVGhlIHdpZHRoIGlzIHNldCBkeW5hbWljYWxseSB0byBzaG93IHJvdW5kIHZhbHVlcyAoZS5nLiAxMDAsIDIwMCwgNTAwKS5cbiAgXHRcdG1heFdpZHRoOiAxMDAsXG5cbiAgXHRcdC8vIEBvcHRpb24gbWV0cmljOiBCb29sZWFuID0gVHJ1ZVxuICBcdFx0Ly8gV2hldGhlciB0byBzaG93IHRoZSBtZXRyaWMgc2NhbGUgbGluZSAobS9rbSkuXG4gIFx0XHRtZXRyaWM6IHRydWUsXG5cbiAgXHRcdC8vIEBvcHRpb24gaW1wZXJpYWw6IEJvb2xlYW4gPSBUcnVlXG4gIFx0XHQvLyBXaGV0aGVyIHRvIHNob3cgdGhlIGltcGVyaWFsIHNjYWxlIGxpbmUgKG1pL2Z0KS5cbiAgXHRcdGltcGVyaWFsOiB0cnVlXG5cbiAgXHRcdC8vIEBvcHRpb24gdXBkYXRlV2hlbklkbGU6IEJvb2xlYW4gPSBmYWxzZVxuICBcdFx0Ly8gSWYgYHRydWVgLCB0aGUgY29udHJvbCBpcyB1cGRhdGVkIG9uIFtgbW92ZWVuZGBdKCNtYXAtbW92ZWVuZCksIG90aGVyd2lzZSBpdCdzIGFsd2F5cyB1cC10by1kYXRlICh1cGRhdGVkIG9uIFtgbW92ZWBdKCNtYXAtbW92ZSkpLlxuICBcdH0sXG5cbiAgXHRvbkFkZDogZnVuY3Rpb24gKG1hcCkge1xuICBcdFx0dmFyIGNsYXNzTmFtZSA9ICdsZWFmbGV0LWNvbnRyb2wtc2NhbGUnLFxuICBcdFx0ICAgIGNvbnRhaW5lciA9IGNyZWF0ZSQxKCdkaXYnLCBjbGFzc05hbWUpLFxuICBcdFx0ICAgIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG5cbiAgXHRcdHRoaXMuX2FkZFNjYWxlcyhvcHRpb25zLCBjbGFzc05hbWUgKyAnLWxpbmUnLCBjb250YWluZXIpO1xuXG4gIFx0XHRtYXAub24ob3B0aW9ucy51cGRhdGVXaGVuSWRsZSA/ICdtb3ZlZW5kJyA6ICdtb3ZlJywgdGhpcy5fdXBkYXRlLCB0aGlzKTtcbiAgXHRcdG1hcC53aGVuUmVhZHkodGhpcy5fdXBkYXRlLCB0aGlzKTtcblxuICBcdFx0cmV0dXJuIGNvbnRhaW5lcjtcbiAgXHR9LFxuXG4gIFx0b25SZW1vdmU6IGZ1bmN0aW9uIChtYXApIHtcbiAgXHRcdG1hcC5vZmYodGhpcy5vcHRpb25zLnVwZGF0ZVdoZW5JZGxlID8gJ21vdmVlbmQnIDogJ21vdmUnLCB0aGlzLl91cGRhdGUsIHRoaXMpO1xuICBcdH0sXG5cbiAgXHRfYWRkU2NhbGVzOiBmdW5jdGlvbiAob3B0aW9ucywgY2xhc3NOYW1lLCBjb250YWluZXIpIHtcbiAgXHRcdGlmIChvcHRpb25zLm1ldHJpYykge1xuICBcdFx0XHR0aGlzLl9tU2NhbGUgPSBjcmVhdGUkMSgnZGl2JywgY2xhc3NOYW1lLCBjb250YWluZXIpO1xuICBcdFx0fVxuICBcdFx0aWYgKG9wdGlvbnMuaW1wZXJpYWwpIHtcbiAgXHRcdFx0dGhpcy5faVNjYWxlID0gY3JlYXRlJDEoJ2RpdicsIGNsYXNzTmFtZSwgY29udGFpbmVyKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZTogZnVuY3Rpb24gKCkge1xuICBcdFx0dmFyIG1hcCA9IHRoaXMuX21hcCxcbiAgXHRcdCAgICB5ID0gbWFwLmdldFNpemUoKS55IC8gMjtcblxuICBcdFx0dmFyIG1heE1ldGVycyA9IG1hcC5kaXN0YW5jZShcbiAgXHRcdFx0bWFwLmNvbnRhaW5lclBvaW50VG9MYXRMbmcoWzAsIHldKSxcbiAgXHRcdFx0bWFwLmNvbnRhaW5lclBvaW50VG9MYXRMbmcoW3RoaXMub3B0aW9ucy5tYXhXaWR0aCwgeV0pKTtcblxuICBcdFx0dGhpcy5fdXBkYXRlU2NhbGVzKG1heE1ldGVycyk7XG4gIFx0fSxcblxuICBcdF91cGRhdGVTY2FsZXM6IGZ1bmN0aW9uIChtYXhNZXRlcnMpIHtcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMubWV0cmljICYmIG1heE1ldGVycykge1xuICBcdFx0XHR0aGlzLl91cGRhdGVNZXRyaWMobWF4TWV0ZXJzKTtcbiAgXHRcdH1cbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMuaW1wZXJpYWwgJiYgbWF4TWV0ZXJzKSB7XG4gIFx0XHRcdHRoaXMuX3VwZGF0ZUltcGVyaWFsKG1heE1ldGVycyk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF91cGRhdGVNZXRyaWM6IGZ1bmN0aW9uIChtYXhNZXRlcnMpIHtcbiAgXHRcdHZhciBtZXRlcnMgPSB0aGlzLl9nZXRSb3VuZE51bShtYXhNZXRlcnMpLFxuICBcdFx0ICAgIGxhYmVsID0gbWV0ZXJzIDwgMTAwMCA/IG1ldGVycyArICcgbScgOiAobWV0ZXJzIC8gMTAwMCkgKyAnIGttJztcblxuICBcdFx0dGhpcy5fdXBkYXRlU2NhbGUodGhpcy5fbVNjYWxlLCBsYWJlbCwgbWV0ZXJzIC8gbWF4TWV0ZXJzKTtcbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZUltcGVyaWFsOiBmdW5jdGlvbiAobWF4TWV0ZXJzKSB7XG4gIFx0XHR2YXIgbWF4RmVldCA9IG1heE1ldGVycyAqIDMuMjgwODM5OSxcbiAgXHRcdCAgICBtYXhNaWxlcywgbWlsZXMsIGZlZXQ7XG5cbiAgXHRcdGlmIChtYXhGZWV0ID4gNTI4MCkge1xuICBcdFx0XHRtYXhNaWxlcyA9IG1heEZlZXQgLyA1MjgwO1xuICBcdFx0XHRtaWxlcyA9IHRoaXMuX2dldFJvdW5kTnVtKG1heE1pbGVzKTtcbiAgXHRcdFx0dGhpcy5fdXBkYXRlU2NhbGUodGhpcy5faVNjYWxlLCBtaWxlcyArICcgbWknLCBtaWxlcyAvIG1heE1pbGVzKTtcblxuICBcdFx0fSBlbHNlIHtcbiAgXHRcdFx0ZmVldCA9IHRoaXMuX2dldFJvdW5kTnVtKG1heEZlZXQpO1xuICBcdFx0XHR0aGlzLl91cGRhdGVTY2FsZSh0aGlzLl9pU2NhbGUsIGZlZXQgKyAnIGZ0JywgZmVldCAvIG1heEZlZXQpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfdXBkYXRlU2NhbGU6IGZ1bmN0aW9uIChzY2FsZSwgdGV4dCwgcmF0aW8pIHtcbiAgXHRcdHNjYWxlLnN0eWxlLndpZHRoID0gTWF0aC5yb3VuZCh0aGlzLm9wdGlvbnMubWF4V2lkdGggKiByYXRpbykgKyAncHgnO1xuICBcdFx0c2NhbGUuaW5uZXJIVE1MID0gdGV4dDtcbiAgXHR9LFxuXG4gIFx0X2dldFJvdW5kTnVtOiBmdW5jdGlvbiAobnVtKSB7XG4gIFx0XHR2YXIgcG93MTAgPSBNYXRoLnBvdygxMCwgKE1hdGguZmxvb3IobnVtKSArICcnKS5sZW5ndGggLSAxKSxcbiAgXHRcdCAgICBkID0gbnVtIC8gcG93MTA7XG5cbiAgXHRcdGQgPSBkID49IDEwID8gMTAgOlxuICBcdFx0ICAgIGQgPj0gNSA/IDUgOlxuICBcdFx0ICAgIGQgPj0gMyA/IDMgOlxuICBcdFx0ICAgIGQgPj0gMiA/IDIgOiAxO1xuXG4gIFx0XHRyZXR1cm4gcG93MTAgKiBkO1xuICBcdH1cbiAgfSk7XG5cblxuICAvLyBAZmFjdG9yeSBMLmNvbnRyb2wuc2NhbGUob3B0aW9ucz86IENvbnRyb2wuU2NhbGUgb3B0aW9ucylcbiAgLy8gQ3JlYXRlcyBhbiBzY2FsZSBjb250cm9sIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuXG4gIHZhciBzY2FsZSA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gIFx0cmV0dXJuIG5ldyBTY2FsZShvcHRpb25zKTtcbiAgfTtcblxuICB2YXIgdWtyYWluaWFuRmxhZyA9ICc8c3ZnIGFyaWEtaGlkZGVuPVwidHJ1ZVwiIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB3aWR0aD1cIjEyXCIgaGVpZ2h0PVwiOFwiIHZpZXdCb3g9XCIwIDAgMTIgOFwiIGNsYXNzPVwibGVhZmxldC1hdHRyaWJ1dGlvbi1mbGFnXCI+PHBhdGggZmlsbD1cIiM0QzdCRTFcIiBkPVwiTTAgMGgxMnY0SDB6XCIvPjxwYXRoIGZpbGw9XCIjRkZENTAwXCIgZD1cIk0wIDRoMTJ2M0gwelwiLz48cGF0aCBmaWxsPVwiI0UwQkMwMFwiIGQ9XCJNMCA3aDEydjFIMHpcIi8+PC9zdmc+JztcclxuXHJcblxyXG4gIC8qXHJcbiAgICogQGNsYXNzIENvbnRyb2wuQXR0cmlidXRpb25cclxuICAgKiBAYWthIEwuQ29udHJvbC5BdHRyaWJ1dGlvblxyXG4gICAqIEBpbmhlcml0cyBDb250cm9sXHJcbiAgICpcclxuICAgKiBUaGUgYXR0cmlidXRpb24gY29udHJvbCBhbGxvd3MgeW91IHRvIGRpc3BsYXkgYXR0cmlidXRpb24gZGF0YSBpbiBhIHNtYWxsIHRleHQgYm94IG9uIGEgbWFwLiBJdCBpcyBwdXQgb24gdGhlIG1hcCBieSBkZWZhdWx0IHVubGVzcyB5b3Ugc2V0IGl0cyBbYGF0dHJpYnV0aW9uQ29udHJvbGAgb3B0aW9uXSgjbWFwLWF0dHJpYnV0aW9uY29udHJvbCkgdG8gYGZhbHNlYCwgYW5kIGl0IGZldGNoZXMgYXR0cmlidXRpb24gdGV4dHMgZnJvbSBsYXllcnMgd2l0aCB0aGUgW2BnZXRBdHRyaWJ1dGlvbmAgbWV0aG9kXSgjbGF5ZXItZ2V0YXR0cmlidXRpb24pIGF1dG9tYXRpY2FsbHkuIEV4dGVuZHMgQ29udHJvbC5cclxuICAgKi9cclxuXHJcbiAgdmFyIEF0dHJpYnV0aW9uID0gQ29udHJvbC5leHRlbmQoe1xyXG4gIFx0Ly8gQHNlY3Rpb25cclxuICBcdC8vIEBha2EgQ29udHJvbC5BdHRyaWJ1dGlvbiBvcHRpb25zXHJcbiAgXHRvcHRpb25zOiB7XHJcbiAgXHRcdHBvc2l0aW9uOiAnYm90dG9tcmlnaHQnLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBwcmVmaXg6IFN0cmluZ3xmYWxzZSA9ICdMZWFmbGV0J1xyXG4gIFx0XHQvLyBUaGUgSFRNTCB0ZXh0IHNob3duIGJlZm9yZSB0aGUgYXR0cmlidXRpb25zLiBQYXNzIGBmYWxzZWAgdG8gZGlzYWJsZS5cclxuICBcdFx0cHJlZml4OiAnPGEgaHJlZj1cImh0dHBzOi8vbGVhZmxldGpzLmNvbVwiIHRpdGxlPVwiQSBKYXZhU2NyaXB0IGxpYnJhcnkgZm9yIGludGVyYWN0aXZlIG1hcHNcIj4nICsgKEJyb3dzZXIuaW5saW5lU3ZnID8gdWtyYWluaWFuRmxhZyArICcgJyA6ICcnKSArICdMZWFmbGV0PC9hPidcclxuICBcdH0sXHJcblxyXG4gIFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuICBcdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcclxuXHJcbiAgXHRcdHRoaXMuX2F0dHJpYnV0aW9ucyA9IHt9O1xyXG4gIFx0fSxcclxuXHJcbiAgXHRvbkFkZDogZnVuY3Rpb24gKG1hcCkge1xyXG4gIFx0XHRtYXAuYXR0cmlidXRpb25Db250cm9sID0gdGhpcztcclxuICBcdFx0dGhpcy5fY29udGFpbmVyID0gY3JlYXRlJDEoJ2RpdicsICdsZWFmbGV0LWNvbnRyb2wtYXR0cmlidXRpb24nKTtcclxuICBcdFx0ZGlzYWJsZUNsaWNrUHJvcGFnYXRpb24odGhpcy5fY29udGFpbmVyKTtcclxuXHJcbiAgXHRcdC8vIFRPRE8gdWdseSwgcmVmYWN0b3JcclxuICBcdFx0Zm9yICh2YXIgaSBpbiBtYXAuX2xheWVycykge1xyXG4gIFx0XHRcdGlmIChtYXAuX2xheWVyc1tpXS5nZXRBdHRyaWJ1dGlvbikge1xyXG4gIFx0XHRcdFx0dGhpcy5hZGRBdHRyaWJ1dGlvbihtYXAuX2xheWVyc1tpXS5nZXRBdHRyaWJ1dGlvbigpKTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuX3VwZGF0ZSgpO1xyXG5cclxuICBcdFx0bWFwLm9uKCdsYXllcmFkZCcsIHRoaXMuX2FkZEF0dHJpYnV0aW9uLCB0aGlzKTtcclxuXHJcbiAgXHRcdHJldHVybiB0aGlzLl9jb250YWluZXI7XHJcbiAgXHR9LFxyXG5cclxuICBcdG9uUmVtb3ZlOiBmdW5jdGlvbiAobWFwKSB7XHJcbiAgXHRcdG1hcC5vZmYoJ2xheWVyYWRkJywgdGhpcy5fYWRkQXR0cmlidXRpb24sIHRoaXMpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfYWRkQXR0cmlidXRpb246IGZ1bmN0aW9uIChldikge1xyXG4gIFx0XHRpZiAoZXYubGF5ZXIuZ2V0QXR0cmlidXRpb24pIHtcclxuICBcdFx0XHR0aGlzLmFkZEF0dHJpYnV0aW9uKGV2LmxheWVyLmdldEF0dHJpYnV0aW9uKCkpO1xyXG4gIFx0XHRcdGV2LmxheWVyLm9uY2UoJ3JlbW92ZScsIGZ1bmN0aW9uICgpIHtcclxuICBcdFx0XHRcdHRoaXMucmVtb3ZlQXR0cmlidXRpb24oZXYubGF5ZXIuZ2V0QXR0cmlidXRpb24oKSk7XHJcbiAgXHRcdFx0fSwgdGhpcyk7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBzZXRQcmVmaXgocHJlZml4OiBTdHJpbmd8ZmFsc2UpOiB0aGlzXHJcbiAgXHQvLyBUaGUgSFRNTCB0ZXh0IHNob3duIGJlZm9yZSB0aGUgYXR0cmlidXRpb25zLiBQYXNzIGBmYWxzZWAgdG8gZGlzYWJsZS5cclxuICBcdHNldFByZWZpeDogZnVuY3Rpb24gKHByZWZpeCkge1xyXG4gIFx0XHR0aGlzLm9wdGlvbnMucHJlZml4ID0gcHJlZml4O1xyXG4gIFx0XHR0aGlzLl91cGRhdGUoKTtcclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgYWRkQXR0cmlidXRpb24odGV4dDogU3RyaW5nKTogdGhpc1xyXG4gIFx0Ly8gQWRkcyBhbiBhdHRyaWJ1dGlvbiB0ZXh0IChlLmcuIGAnJmNvcHk7IE9wZW5TdHJlZXRNYXAgY29udHJpYnV0b3JzJ2ApLlxyXG4gIFx0YWRkQXR0cmlidXRpb246IGZ1bmN0aW9uICh0ZXh0KSB7XHJcbiAgXHRcdGlmICghdGV4dCkgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuICBcdFx0aWYgKCF0aGlzLl9hdHRyaWJ1dGlvbnNbdGV4dF0pIHtcclxuICBcdFx0XHR0aGlzLl9hdHRyaWJ1dGlvbnNbdGV4dF0gPSAwO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHRoaXMuX2F0dHJpYnV0aW9uc1t0ZXh0XSsrO1xyXG5cclxuICBcdFx0dGhpcy5fdXBkYXRlKCk7XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCByZW1vdmVBdHRyaWJ1dGlvbih0ZXh0OiBTdHJpbmcpOiB0aGlzXHJcbiAgXHQvLyBSZW1vdmVzIGFuIGF0dHJpYnV0aW9uIHRleHQuXHJcbiAgXHRyZW1vdmVBdHRyaWJ1dGlvbjogZnVuY3Rpb24gKHRleHQpIHtcclxuICBcdFx0aWYgKCF0ZXh0KSB7IHJldHVybiB0aGlzOyB9XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fYXR0cmlidXRpb25zW3RleHRdKSB7XHJcbiAgXHRcdFx0dGhpcy5fYXR0cmlidXRpb25zW3RleHRdLS07XHJcbiAgXHRcdFx0dGhpcy5fdXBkYXRlKCk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfdXBkYXRlOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICghdGhpcy5fbWFwKSB7IHJldHVybjsgfVxyXG5cclxuICBcdFx0dmFyIGF0dHJpYnMgPSBbXTtcclxuXHJcbiAgXHRcdGZvciAodmFyIGkgaW4gdGhpcy5fYXR0cmlidXRpb25zKSB7XHJcbiAgXHRcdFx0aWYgKHRoaXMuX2F0dHJpYnV0aW9uc1tpXSkge1xyXG4gIFx0XHRcdFx0YXR0cmlicy5wdXNoKGkpO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG5cclxuICBcdFx0dmFyIHByZWZpeEFuZEF0dHJpYnMgPSBbXTtcclxuXHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMucHJlZml4KSB7XHJcbiAgXHRcdFx0cHJlZml4QW5kQXR0cmlicy5wdXNoKHRoaXMub3B0aW9ucy5wcmVmaXgpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdGlmIChhdHRyaWJzLmxlbmd0aCkge1xyXG4gIFx0XHRcdHByZWZpeEFuZEF0dHJpYnMucHVzaChhdHRyaWJzLmpvaW4oJywgJykpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR0aGlzLl9jb250YWluZXIuaW5uZXJIVE1MID0gcHJlZml4QW5kQXR0cmlicy5qb2luKCcgPHNwYW4gYXJpYS1oaWRkZW49XCJ0cnVlXCI+fDwvc3Bhbj4gJyk7XHJcbiAgXHR9XHJcbiAgfSk7XHJcblxyXG4gIC8vIEBuYW1lc3BhY2UgTWFwXHJcbiAgLy8gQHNlY3Rpb24gQ29udHJvbCBvcHRpb25zXHJcbiAgLy8gQG9wdGlvbiBhdHRyaWJ1dGlvbkNvbnRyb2w6IEJvb2xlYW4gPSB0cnVlXHJcbiAgLy8gV2hldGhlciBhIFthdHRyaWJ1dGlvbiBjb250cm9sXSgjY29udHJvbC1hdHRyaWJ1dGlvbikgaXMgYWRkZWQgdG8gdGhlIG1hcCBieSBkZWZhdWx0LlxyXG4gIE1hcC5tZXJnZU9wdGlvbnMoe1xyXG4gIFx0YXR0cmlidXRpb25Db250cm9sOiB0cnVlXHJcbiAgfSk7XHJcblxyXG4gIE1hcC5hZGRJbml0SG9vayhmdW5jdGlvbiAoKSB7XHJcbiAgXHRpZiAodGhpcy5vcHRpb25zLmF0dHJpYnV0aW9uQ29udHJvbCkge1xyXG4gIFx0XHRuZXcgQXR0cmlidXRpb24oKS5hZGRUbyh0aGlzKTtcclxuICBcdH1cclxuICB9KTtcclxuXHJcbiAgLy8gQG5hbWVzcGFjZSBDb250cm9sLkF0dHJpYnV0aW9uXHJcbiAgLy8gQGZhY3RvcnkgTC5jb250cm9sLmF0dHJpYnV0aW9uKG9wdGlvbnM6IENvbnRyb2wuQXR0cmlidXRpb24gb3B0aW9ucylcclxuICAvLyBDcmVhdGVzIGFuIGF0dHJpYnV0aW9uIGNvbnRyb2wuXHJcbiAgdmFyIGF0dHJpYnV0aW9uID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuICBcdHJldHVybiBuZXcgQXR0cmlidXRpb24ob3B0aW9ucyk7XHJcbiAgfTtcblxuICBDb250cm9sLkxheWVycyA9IExheWVycztcbiAgQ29udHJvbC5ab29tID0gWm9vbTtcbiAgQ29udHJvbC5TY2FsZSA9IFNjYWxlO1xuICBDb250cm9sLkF0dHJpYnV0aW9uID0gQXR0cmlidXRpb247XG5cbiAgY29udHJvbC5sYXllcnMgPSBsYXllcnM7XG4gIGNvbnRyb2wuem9vbSA9IHpvb207XG4gIGNvbnRyb2wuc2NhbGUgPSBzY2FsZTtcbiAgY29udHJvbC5hdHRyaWJ1dGlvbiA9IGF0dHJpYnV0aW9uO1xuXG4gIC8qXG4gIFx0TC5IYW5kbGVyIGlzIGEgYmFzZSBjbGFzcyBmb3IgaGFuZGxlciBjbGFzc2VzIHRoYXQgYXJlIHVzZWQgaW50ZXJuYWxseSB0byBpbmplY3RcbiAgXHRpbnRlcmFjdGlvbiBmZWF0dXJlcyBsaWtlIGRyYWdnaW5nIHRvIGNsYXNzZXMgbGlrZSBNYXAgYW5kIE1hcmtlci5cbiAgKi9cblxuICAvLyBAY2xhc3MgSGFuZGxlclxuICAvLyBAYWthIEwuSGFuZGxlclxuICAvLyBBYnN0cmFjdCBjbGFzcyBmb3IgbWFwIGludGVyYWN0aW9uIGhhbmRsZXJzXG5cbiAgdmFyIEhhbmRsZXIgPSBDbGFzcy5leHRlbmQoe1xuICBcdGluaXRpYWxpemU6IGZ1bmN0aW9uIChtYXApIHtcbiAgXHRcdHRoaXMuX21hcCA9IG1hcDtcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBlbmFibGUoKTogdGhpc1xuICBcdC8vIEVuYWJsZXMgdGhlIGhhbmRsZXJcbiAgXHRlbmFibGU6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICh0aGlzLl9lbmFibGVkKSB7IHJldHVybiB0aGlzOyB9XG5cbiAgXHRcdHRoaXMuX2VuYWJsZWQgPSB0cnVlO1xuICBcdFx0dGhpcy5hZGRIb29rcygpO1xuICBcdFx0cmV0dXJuIHRoaXM7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgZGlzYWJsZSgpOiB0aGlzXG4gIFx0Ly8gRGlzYWJsZXMgdGhlIGhhbmRsZXJcbiAgXHRkaXNhYmxlOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRpZiAoIXRoaXMuX2VuYWJsZWQpIHsgcmV0dXJuIHRoaXM7IH1cblxuICBcdFx0dGhpcy5fZW5hYmxlZCA9IGZhbHNlO1xuICBcdFx0dGhpcy5yZW1vdmVIb29rcygpO1xuICBcdFx0cmV0dXJuIHRoaXM7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgZW5hYmxlZCgpOiBCb29sZWFuXG4gIFx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGhhbmRsZXIgaXMgZW5hYmxlZFxuICBcdGVuYWJsZWQ6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHJldHVybiAhIXRoaXMuX2VuYWJsZWQ7XG4gIFx0fVxuXG4gIFx0Ly8gQHNlY3Rpb24gRXh0ZW5zaW9uIG1ldGhvZHNcbiAgXHQvLyBDbGFzc2VzIGluaGVyaXRpbmcgZnJvbSBgSGFuZGxlcmAgbXVzdCBpbXBsZW1lbnQgdGhlIHR3byBmb2xsb3dpbmcgbWV0aG9kczpcbiAgXHQvLyBAbWV0aG9kIGFkZEhvb2tzKClcbiAgXHQvLyBDYWxsZWQgd2hlbiB0aGUgaGFuZGxlciBpcyBlbmFibGVkLCBzaG91bGQgYWRkIGV2ZW50IGhvb2tzLlxuICBcdC8vIEBtZXRob2QgcmVtb3ZlSG9va3MoKVxuICBcdC8vIENhbGxlZCB3aGVuIHRoZSBoYW5kbGVyIGlzIGRpc2FibGVkLCBzaG91bGQgcmVtb3ZlIHRoZSBldmVudCBob29rcyBhZGRlZCBwcmV2aW91c2x5LlxuICB9KTtcblxuICAvLyBAc2VjdGlvbiBUaGVyZSBpcyBzdGF0aWMgZnVuY3Rpb24gd2hpY2ggY2FuIGJlIGNhbGxlZCB3aXRob3V0IGluc3RhbnRpYXRpbmcgTC5IYW5kbGVyOlxuICAvLyBAZnVuY3Rpb24gYWRkVG8obWFwOiBNYXAsIG5hbWU6IFN0cmluZyk6IHRoaXNcbiAgLy8gQWRkcyBhIG5ldyBIYW5kbGVyIHRvIHRoZSBnaXZlbiBtYXAgd2l0aCB0aGUgZ2l2ZW4gbmFtZS5cbiAgSGFuZGxlci5hZGRUbyA9IGZ1bmN0aW9uIChtYXAsIG5hbWUpIHtcbiAgXHRtYXAuYWRkSGFuZGxlcihuYW1lLCB0aGlzKTtcbiAgXHRyZXR1cm4gdGhpcztcbiAgfTtcblxuICB2YXIgTWl4aW4gPSB7RXZlbnRzOiBFdmVudHN9O1xuXG4gIC8qXHJcbiAgICogQGNsYXNzIERyYWdnYWJsZVxyXG4gICAqIEBha2EgTC5EcmFnZ2FibGVcclxuICAgKiBAaW5oZXJpdHMgRXZlbnRlZFxyXG4gICAqXHJcbiAgICogQSBjbGFzcyBmb3IgbWFraW5nIERPTSBlbGVtZW50cyBkcmFnZ2FibGUgKGluY2x1ZGluZyB0b3VjaCBzdXBwb3J0KS5cclxuICAgKiBVc2VkIGludGVybmFsbHkgZm9yIG1hcCBhbmQgbWFya2VyIGRyYWdnaW5nLiBPbmx5IHdvcmtzIGZvciBlbGVtZW50c1xyXG4gICAqIHRoYXQgd2VyZSBwb3NpdGlvbmVkIHdpdGggW2BMLkRvbVV0aWwuc2V0UG9zaXRpb25gXSgjZG9tdXRpbC1zZXRwb3NpdGlvbikuXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqIGBgYGpzXHJcbiAgICogdmFyIGRyYWdnYWJsZSA9IG5ldyBMLkRyYWdnYWJsZShlbGVtZW50VG9EcmFnKTtcclxuICAgKiBkcmFnZ2FibGUuZW5hYmxlKCk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcblxyXG4gIHZhciBTVEFSVCA9IEJyb3dzZXIudG91Y2ggPyAndG91Y2hzdGFydCBtb3VzZWRvd24nIDogJ21vdXNlZG93bic7XHJcblxyXG4gIHZhciBEcmFnZ2FibGUgPSBFdmVudGVkLmV4dGVuZCh7XHJcblxyXG4gIFx0b3B0aW9uczoge1xyXG4gIFx0XHQvLyBAc2VjdGlvblxyXG4gIFx0XHQvLyBAYWthIERyYWdnYWJsZSBvcHRpb25zXHJcbiAgXHRcdC8vIEBvcHRpb24gY2xpY2tUb2xlcmFuY2U6IE51bWJlciA9IDNcclxuICBcdFx0Ly8gVGhlIG1heCBudW1iZXIgb2YgcGl4ZWxzIGEgdXNlciBjYW4gc2hpZnQgdGhlIG1vdXNlIHBvaW50ZXIgZHVyaW5nIGEgY2xpY2tcclxuICBcdFx0Ly8gZm9yIGl0IHRvIGJlIGNvbnNpZGVyZWQgYSB2YWxpZCBjbGljayAoYXMgb3Bwb3NlZCB0byBhIG1vdXNlIGRyYWcpLlxyXG4gIFx0XHRjbGlja1RvbGVyYW5jZTogM1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAY29uc3RydWN0b3IgTC5EcmFnZ2FibGUoZWw6IEhUTUxFbGVtZW50LCBkcmFnSGFuZGxlPzogSFRNTEVsZW1lbnQsIHByZXZlbnRPdXRsaW5lPzogQm9vbGVhbiwgb3B0aW9ucz86IERyYWdnYWJsZSBvcHRpb25zKVxyXG4gIFx0Ly8gQ3JlYXRlcyBhIGBEcmFnZ2FibGVgIG9iamVjdCBmb3IgbW92aW5nIGBlbGAgd2hlbiB5b3Ugc3RhcnQgZHJhZ2dpbmcgdGhlIGBkcmFnSGFuZGxlYCBlbGVtZW50IChlcXVhbHMgYGVsYCBpdHNlbGYgYnkgZGVmYXVsdCkuXHJcbiAgXHRpbml0aWFsaXplOiBmdW5jdGlvbiAoZWxlbWVudCwgZHJhZ1N0YXJ0VGFyZ2V0LCBwcmV2ZW50T3V0bGluZSwgb3B0aW9ucykge1xyXG4gIFx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xyXG5cclxuICBcdFx0dGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XHJcbiAgXHRcdHRoaXMuX2RyYWdTdGFydFRhcmdldCA9IGRyYWdTdGFydFRhcmdldCB8fCBlbGVtZW50O1xyXG4gIFx0XHR0aGlzLl9wcmV2ZW50T3V0bGluZSA9IHByZXZlbnRPdXRsaW5lO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGVuYWJsZSgpXHJcbiAgXHQvLyBFbmFibGVzIHRoZSBkcmFnZ2luZyBhYmlsaXR5XHJcbiAgXHRlbmFibGU6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKHRoaXMuX2VuYWJsZWQpIHsgcmV0dXJuOyB9XHJcblxyXG4gIFx0XHRvbih0aGlzLl9kcmFnU3RhcnRUYXJnZXQsIFNUQVJULCB0aGlzLl9vbkRvd24sIHRoaXMpO1xyXG5cclxuICBcdFx0dGhpcy5fZW5hYmxlZCA9IHRydWU7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZGlzYWJsZSgpXHJcbiAgXHQvLyBEaXNhYmxlcyB0aGUgZHJhZ2dpbmcgYWJpbGl0eVxyXG4gIFx0ZGlzYWJsZTogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRpZiAoIXRoaXMuX2VuYWJsZWQpIHsgcmV0dXJuOyB9XHJcblxyXG4gIFx0XHQvLyBJZiB3ZSdyZSBjdXJyZW50bHkgZHJhZ2dpbmcgdGhpcyBkcmFnZ2FibGUsXHJcbiAgXHRcdC8vIGRpc2FibGluZyBpdCBjb3VudHMgYXMgZmlyc3QgZW5kaW5nIHRoZSBkcmFnLlxyXG4gIFx0XHRpZiAoRHJhZ2dhYmxlLl9kcmFnZ2luZyA9PT0gdGhpcykge1xyXG4gIFx0XHRcdHRoaXMuZmluaXNoRHJhZyh0cnVlKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0b2ZmKHRoaXMuX2RyYWdTdGFydFRhcmdldCwgU1RBUlQsIHRoaXMuX29uRG93biwgdGhpcyk7XHJcblxyXG4gIFx0XHR0aGlzLl9lbmFibGVkID0gZmFsc2U7XHJcbiAgXHRcdHRoaXMuX21vdmVkID0gZmFsc2U7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9vbkRvd246IGZ1bmN0aW9uIChlKSB7XHJcbiAgXHRcdC8vIElnbm9yZSB0aGUgZXZlbnQgaWYgZGlzYWJsZWQ7IHRoaXMgaGFwcGVucyBpbiBJRTExXHJcbiAgXHRcdC8vIHVuZGVyIHNvbWUgY2lyY3Vtc3RhbmNlcywgc2VlICMzNjY2LlxyXG4gIFx0XHRpZiAoIXRoaXMuX2VuYWJsZWQpIHsgcmV0dXJuOyB9XHJcblxyXG4gIFx0XHR0aGlzLl9tb3ZlZCA9IGZhbHNlO1xyXG5cclxuICBcdFx0aWYgKGhhc0NsYXNzKHRoaXMuX2VsZW1lbnQsICdsZWFmbGV0LXpvb20tYW5pbScpKSB7IHJldHVybjsgfVxyXG5cclxuICBcdFx0aWYgKGUudG91Y2hlcyAmJiBlLnRvdWNoZXMubGVuZ3RoICE9PSAxKSB7XHJcbiAgXHRcdFx0Ly8gRmluaXNoIGRyYWdnaW5nIHRvIGF2b2lkIGNvbmZsaWN0IHdpdGggdG91Y2hab29tXHJcbiAgXHRcdFx0aWYgKERyYWdnYWJsZS5fZHJhZ2dpbmcgPT09IHRoaXMpIHtcclxuICBcdFx0XHRcdHRoaXMuZmluaXNoRHJhZygpO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0XHRyZXR1cm47XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmIChEcmFnZ2FibGUuX2RyYWdnaW5nIHx8IGUuc2hpZnRLZXkgfHwgKChlLndoaWNoICE9PSAxKSAmJiAoZS5idXR0b24gIT09IDEpICYmICFlLnRvdWNoZXMpKSB7IHJldHVybjsgfVxyXG4gIFx0XHREcmFnZ2FibGUuX2RyYWdnaW5nID0gdGhpczsgIC8vIFByZXZlbnQgZHJhZ2dpbmcgbXVsdGlwbGUgb2JqZWN0cyBhdCBvbmNlLlxyXG5cclxuICBcdFx0aWYgKHRoaXMuX3ByZXZlbnRPdXRsaW5lKSB7XHJcbiAgXHRcdFx0cHJldmVudE91dGxpbmUodGhpcy5fZWxlbWVudCk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGRpc2FibGVJbWFnZURyYWcoKTtcclxuICBcdFx0ZGlzYWJsZVRleHRTZWxlY3Rpb24oKTtcclxuXHJcbiAgXHRcdGlmICh0aGlzLl9tb3ZpbmcpIHsgcmV0dXJuOyB9XHJcblxyXG4gIFx0XHQvLyBAZXZlbnQgZG93bjogRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiBhIGRyYWcgaXMgYWJvdXQgdG8gc3RhcnQuXHJcbiAgXHRcdHRoaXMuZmlyZSgnZG93bicpO1xyXG5cclxuICBcdFx0dmFyIGZpcnN0ID0gZS50b3VjaGVzID8gZS50b3VjaGVzWzBdIDogZSxcclxuICBcdFx0ICAgIHNpemVkUGFyZW50ID0gZ2V0U2l6ZWRQYXJlbnROb2RlKHRoaXMuX2VsZW1lbnQpO1xyXG5cclxuICBcdFx0dGhpcy5fc3RhcnRQb2ludCA9IG5ldyBQb2ludChmaXJzdC5jbGllbnRYLCBmaXJzdC5jbGllbnRZKTtcclxuICBcdFx0dGhpcy5fc3RhcnRQb3MgPSBnZXRQb3NpdGlvbih0aGlzLl9lbGVtZW50KTtcclxuXHJcbiAgXHRcdC8vIENhY2hlIHRoZSBzY2FsZSwgc28gdGhhdCB3ZSBjYW4gY29udGludW91c2x5IGNvbXBlbnNhdGUgZm9yIGl0IGR1cmluZyBkcmFnIChfb25Nb3ZlKS5cclxuICBcdFx0dGhpcy5fcGFyZW50U2NhbGUgPSBnZXRTY2FsZShzaXplZFBhcmVudCk7XHJcblxyXG4gIFx0XHR2YXIgbW91c2VldmVudCA9IGUudHlwZSA9PT0gJ21vdXNlZG93bic7XHJcbiAgXHRcdG9uKGRvY3VtZW50LCBtb3VzZWV2ZW50ID8gJ21vdXNlbW92ZScgOiAndG91Y2htb3ZlJywgdGhpcy5fb25Nb3ZlLCB0aGlzKTtcclxuICBcdFx0b24oZG9jdW1lbnQsIG1vdXNlZXZlbnQgPyAnbW91c2V1cCcgOiAndG91Y2hlbmQgdG91Y2hjYW5jZWwnLCB0aGlzLl9vblVwLCB0aGlzKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X29uTW92ZTogZnVuY3Rpb24gKGUpIHtcclxuICBcdFx0Ly8gSWdub3JlIHRoZSBldmVudCBpZiBkaXNhYmxlZDsgdGhpcyBoYXBwZW5zIGluIElFMTFcclxuICBcdFx0Ly8gdW5kZXIgc29tZSBjaXJjdW1zdGFuY2VzLCBzZWUgIzM2NjYuXHJcbiAgXHRcdGlmICghdGhpcy5fZW5hYmxlZCkgeyByZXR1cm47IH1cclxuXHJcbiAgXHRcdGlmIChlLnRvdWNoZXMgJiYgZS50b3VjaGVzLmxlbmd0aCA+IDEpIHtcclxuICBcdFx0XHR0aGlzLl9tb3ZlZCA9IHRydWU7XHJcbiAgXHRcdFx0cmV0dXJuO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgZmlyc3QgPSAoZS50b3VjaGVzICYmIGUudG91Y2hlcy5sZW5ndGggPT09IDEgPyBlLnRvdWNoZXNbMF0gOiBlKSxcclxuICBcdFx0ICAgIG9mZnNldCA9IG5ldyBQb2ludChmaXJzdC5jbGllbnRYLCBmaXJzdC5jbGllbnRZKS5fc3VidHJhY3QodGhpcy5fc3RhcnRQb2ludCk7XHJcblxyXG4gIFx0XHRpZiAoIW9mZnNldC54ICYmICFvZmZzZXQueSkgeyByZXR1cm47IH1cclxuICBcdFx0aWYgKE1hdGguYWJzKG9mZnNldC54KSArIE1hdGguYWJzKG9mZnNldC55KSA8IHRoaXMub3B0aW9ucy5jbGlja1RvbGVyYW5jZSkgeyByZXR1cm47IH1cclxuXHJcbiAgXHRcdC8vIFdlIGFzc3VtZSB0aGF0IHRoZSBwYXJlbnQgY29udGFpbmVyJ3MgcG9zaXRpb24sIGJvcmRlciBhbmQgc2NhbGUgZG8gbm90IGNoYW5nZSBmb3IgdGhlIGR1cmF0aW9uIG9mIHRoZSBkcmFnLlxyXG4gIFx0XHQvLyBUaGVyZWZvcmUgdGhlcmUgaXMgbm8gbmVlZCB0byBhY2NvdW50IGZvciB0aGUgcG9zaXRpb24gYW5kIGJvcmRlciAodGhleSBhcmUgZWxpbWluYXRlZCBieSB0aGUgc3VidHJhY3Rpb24pXHJcbiAgXHRcdC8vIGFuZCB3ZSBjYW4gdXNlIHRoZSBjYWNoZWQgdmFsdWUgZm9yIHRoZSBzY2FsZS5cclxuICBcdFx0b2Zmc2V0LnggLz0gdGhpcy5fcGFyZW50U2NhbGUueDtcclxuICBcdFx0b2Zmc2V0LnkgLz0gdGhpcy5fcGFyZW50U2NhbGUueTtcclxuXHJcbiAgXHRcdHByZXZlbnREZWZhdWx0KGUpO1xyXG5cclxuICBcdFx0aWYgKCF0aGlzLl9tb3ZlZCkge1xyXG4gIFx0XHRcdC8vIEBldmVudCBkcmFnc3RhcnQ6IEV2ZW50XHJcbiAgXHRcdFx0Ly8gRmlyZWQgd2hlbiBhIGRyYWcgc3RhcnRzXHJcbiAgXHRcdFx0dGhpcy5maXJlKCdkcmFnc3RhcnQnKTtcclxuXHJcbiAgXHRcdFx0dGhpcy5fbW92ZWQgPSB0cnVlO1xyXG5cclxuICBcdFx0XHRhZGRDbGFzcyhkb2N1bWVudC5ib2R5LCAnbGVhZmxldC1kcmFnZ2luZycpO1xyXG5cclxuICBcdFx0XHR0aGlzLl9sYXN0VGFyZ2V0ID0gZS50YXJnZXQgfHwgZS5zcmNFbGVtZW50O1xyXG4gIFx0XHRcdC8vIElFIGFuZCBFZGdlIGRvIG5vdCBnaXZlIHRoZSA8dXNlPiBlbGVtZW50LCBzbyBmZXRjaCBpdFxyXG4gIFx0XHRcdC8vIGlmIG5lY2Vzc2FyeVxyXG4gIFx0XHRcdGlmICh3aW5kb3cuU1ZHRWxlbWVudEluc3RhbmNlICYmIHRoaXMuX2xhc3RUYXJnZXQgaW5zdGFuY2VvZiB3aW5kb3cuU1ZHRWxlbWVudEluc3RhbmNlKSB7XHJcbiAgXHRcdFx0XHR0aGlzLl9sYXN0VGFyZ2V0ID0gdGhpcy5fbGFzdFRhcmdldC5jb3JyZXNwb25kaW5nVXNlRWxlbWVudDtcclxuICBcdFx0XHR9XHJcbiAgXHRcdFx0YWRkQ2xhc3ModGhpcy5fbGFzdFRhcmdldCwgJ2xlYWZsZXQtZHJhZy10YXJnZXQnKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5fbmV3UG9zID0gdGhpcy5fc3RhcnRQb3MuYWRkKG9mZnNldCk7XHJcbiAgXHRcdHRoaXMuX21vdmluZyA9IHRydWU7XHJcblxyXG4gIFx0XHR0aGlzLl9sYXN0RXZlbnQgPSBlO1xyXG4gIFx0XHR0aGlzLl91cGRhdGVQb3NpdGlvbigpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfdXBkYXRlUG9zaXRpb246IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dmFyIGUgPSB7b3JpZ2luYWxFdmVudDogdGhpcy5fbGFzdEV2ZW50fTtcclxuXHJcbiAgXHRcdC8vIEBldmVudCBwcmVkcmFnOiBFdmVudFxyXG4gIFx0XHQvLyBGaXJlZCBjb250aW51b3VzbHkgZHVyaW5nIGRyYWdnaW5nICpiZWZvcmUqIGVhY2ggY29ycmVzcG9uZGluZ1xyXG4gIFx0XHQvLyB1cGRhdGUgb2YgdGhlIGVsZW1lbnQncyBwb3NpdGlvbi5cclxuICBcdFx0dGhpcy5maXJlKCdwcmVkcmFnJywgZSk7XHJcbiAgXHRcdHNldFBvc2l0aW9uKHRoaXMuX2VsZW1lbnQsIHRoaXMuX25ld1Bvcyk7XHJcblxyXG4gIFx0XHQvLyBAZXZlbnQgZHJhZzogRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgY29udGludW91c2x5IGR1cmluZyBkcmFnZ2luZy5cclxuICBcdFx0dGhpcy5maXJlKCdkcmFnJywgZSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9vblVwOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdC8vIElnbm9yZSB0aGUgZXZlbnQgaWYgZGlzYWJsZWQ7IHRoaXMgaGFwcGVucyBpbiBJRTExXHJcbiAgXHRcdC8vIHVuZGVyIHNvbWUgY2lyY3Vtc3RhbmNlcywgc2VlICMzNjY2LlxyXG4gIFx0XHRpZiAoIXRoaXMuX2VuYWJsZWQpIHsgcmV0dXJuOyB9XHJcbiAgXHRcdHRoaXMuZmluaXNoRHJhZygpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRmaW5pc2hEcmFnOiBmdW5jdGlvbiAobm9JbmVydGlhKSB7XHJcbiAgXHRcdHJlbW92ZUNsYXNzKGRvY3VtZW50LmJvZHksICdsZWFmbGV0LWRyYWdnaW5nJyk7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fbGFzdFRhcmdldCkge1xyXG4gIFx0XHRcdHJlbW92ZUNsYXNzKHRoaXMuX2xhc3RUYXJnZXQsICdsZWFmbGV0LWRyYWctdGFyZ2V0Jyk7XHJcbiAgXHRcdFx0dGhpcy5fbGFzdFRhcmdldCA9IG51bGw7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdG9mZihkb2N1bWVudCwgJ21vdXNlbW92ZSB0b3VjaG1vdmUnLCB0aGlzLl9vbk1vdmUsIHRoaXMpO1xyXG4gIFx0XHRvZmYoZG9jdW1lbnQsICdtb3VzZXVwIHRvdWNoZW5kIHRvdWNoY2FuY2VsJywgdGhpcy5fb25VcCwgdGhpcyk7XHJcblxyXG4gIFx0XHRlbmFibGVJbWFnZURyYWcoKTtcclxuICBcdFx0ZW5hYmxlVGV4dFNlbGVjdGlvbigpO1xyXG5cclxuICBcdFx0dmFyIGZpcmVEcmFnZW5kID0gdGhpcy5fbW92ZWQgJiYgdGhpcy5fbW92aW5nO1xyXG5cclxuICBcdFx0dGhpcy5fbW92aW5nID0gZmFsc2U7XHJcbiAgXHRcdERyYWdnYWJsZS5fZHJhZ2dpbmcgPSBmYWxzZTtcclxuXHJcbiAgXHRcdGlmIChmaXJlRHJhZ2VuZCkge1xyXG4gIFx0XHRcdC8vIEBldmVudCBkcmFnZW5kOiBEcmFnRW5kRXZlbnRcclxuICBcdFx0XHQvLyBGaXJlZCB3aGVuIHRoZSBkcmFnIGVuZHMuXHJcbiAgXHRcdFx0dGhpcy5maXJlKCdkcmFnZW5kJywge1xyXG4gIFx0XHRcdFx0bm9JbmVydGlhOiBub0luZXJ0aWEsXHJcbiAgXHRcdFx0XHRkaXN0YW5jZTogdGhpcy5fbmV3UG9zLmRpc3RhbmNlVG8odGhpcy5fc3RhcnRQb3MpXHJcbiAgXHRcdFx0fSk7XHJcbiAgXHRcdH1cclxuICBcdH1cclxuXHJcbiAgfSk7XG5cbiAgLypcclxuICAgKiBAbmFtZXNwYWNlIFBvbHlVdGlsXHJcbiAgICogVmFyaW91cyB1dGlsaXR5IGZ1bmN0aW9ucyBmb3IgcG9seWdvbiBnZW9tZXRyaWVzLlxyXG4gICAqL1xyXG5cclxuICAvKiBAZnVuY3Rpb24gY2xpcFBvbHlnb24ocG9pbnRzOiBQb2ludFtdLCBib3VuZHM6IEJvdW5kcywgcm91bmQ/OiBCb29sZWFuKTogUG9pbnRbXVxyXG4gICAqIENsaXBzIHRoZSBwb2x5Z29uIGdlb21ldHJ5IGRlZmluZWQgYnkgdGhlIGdpdmVuIGBwb2ludHNgIGJ5IHRoZSBnaXZlbiBib3VuZHMgKHVzaW5nIHRoZSBbU3V0aGVybGFuZC1Ib2RnbWFuIGFsZ29yaXRobV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU3V0aGVybGFuZCVFMiU4MCU5M0hvZGdtYW5fYWxnb3JpdGhtKSkuXHJcbiAgICogVXNlZCBieSBMZWFmbGV0IHRvIG9ubHkgc2hvdyBwb2x5Z29uIHBvaW50cyB0aGF0IGFyZSBvbiB0aGUgc2NyZWVuIG9yIG5lYXIsIGluY3JlYXNpbmdcclxuICAgKiBwZXJmb3JtYW5jZS4gTm90ZSB0aGF0IHBvbHlnb24gcG9pbnRzIG5lZWRzIGRpZmZlcmVudCBhbGdvcml0aG0gZm9yIGNsaXBwaW5nXHJcbiAgICogdGhhbiBwb2x5bGluZSwgc28gdGhlcmUncyBhIHNlcGFyYXRlIG1ldGhvZCBmb3IgaXQuXHJcbiAgICovXHJcbiAgZnVuY3Rpb24gY2xpcFBvbHlnb24ocG9pbnRzLCBib3VuZHMsIHJvdW5kKSB7XHJcbiAgXHR2YXIgY2xpcHBlZFBvaW50cyxcclxuICBcdCAgICBlZGdlcyA9IFsxLCA0LCAyLCA4XSxcclxuICBcdCAgICBpLCBqLCBrLFxyXG4gIFx0ICAgIGEsIGIsXHJcbiAgXHQgICAgbGVuLCBlZGdlLCBwO1xyXG5cclxuICBcdGZvciAoaSA9IDAsIGxlbiA9IHBvaW50cy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gIFx0XHRwb2ludHNbaV0uX2NvZGUgPSBfZ2V0Qml0Q29kZShwb2ludHNbaV0sIGJvdW5kcyk7XHJcbiAgXHR9XHJcblxyXG4gIFx0Ly8gZm9yIGVhY2ggZWRnZSAobGVmdCwgYm90dG9tLCByaWdodCwgdG9wKVxyXG4gIFx0Zm9yIChrID0gMDsgayA8IDQ7IGsrKykge1xyXG4gIFx0XHRlZGdlID0gZWRnZXNba107XHJcbiAgXHRcdGNsaXBwZWRQb2ludHMgPSBbXTtcclxuXHJcbiAgXHRcdGZvciAoaSA9IDAsIGxlbiA9IHBvaW50cy5sZW5ndGgsIGogPSBsZW4gLSAxOyBpIDwgbGVuOyBqID0gaSsrKSB7XHJcbiAgXHRcdFx0YSA9IHBvaW50c1tpXTtcclxuICBcdFx0XHRiID0gcG9pbnRzW2pdO1xyXG5cclxuICBcdFx0XHQvLyBpZiBhIGlzIGluc2lkZSB0aGUgY2xpcCB3aW5kb3dcclxuICBcdFx0XHRpZiAoIShhLl9jb2RlICYgZWRnZSkpIHtcclxuICBcdFx0XHRcdC8vIGlmIGIgaXMgb3V0c2lkZSB0aGUgY2xpcCB3aW5kb3cgKGEtPmIgZ29lcyBvdXQgb2Ygc2NyZWVuKVxyXG4gIFx0XHRcdFx0aWYgKGIuX2NvZGUgJiBlZGdlKSB7XHJcbiAgXHRcdFx0XHRcdHAgPSBfZ2V0RWRnZUludGVyc2VjdGlvbihiLCBhLCBlZGdlLCBib3VuZHMsIHJvdW5kKTtcclxuICBcdFx0XHRcdFx0cC5fY29kZSA9IF9nZXRCaXRDb2RlKHAsIGJvdW5kcyk7XHJcbiAgXHRcdFx0XHRcdGNsaXBwZWRQb2ludHMucHVzaChwKTtcclxuICBcdFx0XHRcdH1cclxuICBcdFx0XHRcdGNsaXBwZWRQb2ludHMucHVzaChhKTtcclxuXHJcbiAgXHRcdFx0Ly8gZWxzZSBpZiBiIGlzIGluc2lkZSB0aGUgY2xpcCB3aW5kb3cgKGEtPmIgZW50ZXJzIHRoZSBzY3JlZW4pXHJcbiAgXHRcdFx0fSBlbHNlIGlmICghKGIuX2NvZGUgJiBlZGdlKSkge1xyXG4gIFx0XHRcdFx0cCA9IF9nZXRFZGdlSW50ZXJzZWN0aW9uKGIsIGEsIGVkZ2UsIGJvdW5kcywgcm91bmQpO1xyXG4gIFx0XHRcdFx0cC5fY29kZSA9IF9nZXRCaXRDb2RlKHAsIGJvdW5kcyk7XHJcbiAgXHRcdFx0XHRjbGlwcGVkUG9pbnRzLnB1c2gocCk7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcbiAgXHRcdHBvaW50cyA9IGNsaXBwZWRQb2ludHM7XHJcbiAgXHR9XHJcblxyXG4gIFx0cmV0dXJuIHBvaW50cztcclxuICB9XHJcblxyXG4gIC8qIEBmdW5jdGlvbiBwb2x5Z29uQ2VudGVyKGxhdGxuZ3M6IExhdExuZ1tdLCBjcnM6IENSUyk6IExhdExuZ1xyXG4gICAqIFJldHVybnMgdGhlIGNlbnRlciAoW2NlbnRyb2lkXShodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NlbnRyb2lkKSkgb2YgdGhlIHBhc3NlZCBMYXRMbmdzIChmaXJzdCByaW5nKSBmcm9tIGEgcG9seWdvbi5cclxuICAgKi9cclxuICBmdW5jdGlvbiBwb2x5Z29uQ2VudGVyKGxhdGxuZ3MsIGNycykge1xyXG4gIFx0dmFyIGksIGosIHAxLCBwMiwgZiwgYXJlYSwgeCwgeSwgY2VudGVyO1xyXG5cclxuICBcdGlmICghbGF0bG5ncyB8fCBsYXRsbmdzLmxlbmd0aCA9PT0gMCkge1xyXG4gIFx0XHR0aHJvdyBuZXcgRXJyb3IoJ2xhdGxuZ3Mgbm90IHBhc3NlZCcpO1xyXG4gIFx0fVxyXG5cclxuICBcdGlmICghaXNGbGF0KGxhdGxuZ3MpKSB7XHJcbiAgXHRcdGNvbnNvbGUud2FybignbGF0bG5ncyBhcmUgbm90IGZsYXQhIE9ubHkgdGhlIGZpcnN0IHJpbmcgd2lsbCBiZSB1c2VkJyk7XHJcbiAgXHRcdGxhdGxuZ3MgPSBsYXRsbmdzWzBdO1xyXG4gIFx0fVxyXG5cclxuICBcdHZhciBjZW50cm9pZExhdExuZyA9IHRvTGF0TG5nKFswLCAwXSk7XHJcblxyXG4gIFx0dmFyIGJvdW5kcyA9IHRvTGF0TG5nQm91bmRzKGxhdGxuZ3MpO1xyXG4gIFx0dmFyIGFyZWFCb3VuZHMgPSBib3VuZHMuZ2V0Tm9ydGhXZXN0KCkuZGlzdGFuY2VUbyhib3VuZHMuZ2V0U291dGhXZXN0KCkpICogYm91bmRzLmdldE5vcnRoRWFzdCgpLmRpc3RhbmNlVG8oYm91bmRzLmdldE5vcnRoV2VzdCgpKTtcclxuICBcdC8vIHRlc3RzIHNob3dlZCB0aGF0IGJlbG93IDE3MDAgcm91bmRpbmcgZXJyb3JzIGFyZSBoYXBwZW5pbmdcclxuICBcdGlmIChhcmVhQm91bmRzIDwgMTcwMCkge1xyXG4gIFx0XHQvLyBnZXR0aW5nIGEgaW5leGFjdCBjZW50ZXIsIHRvIG1vdmUgdGhlIGxhdGxuZ3MgbmVhciB0byBbMCwgMF0gdG8gcHJldmVudCByb3VuZGluZyBlcnJvcnNcclxuICBcdFx0Y2VudHJvaWRMYXRMbmcgPSBjZW50cm9pZChsYXRsbmdzKTtcclxuICBcdH1cclxuXHJcbiAgXHR2YXIgbGVuID0gbGF0bG5ncy5sZW5ndGg7XHJcbiAgXHR2YXIgcG9pbnRzID0gW107XHJcbiAgXHRmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcclxuICBcdFx0dmFyIGxhdGxuZyA9IHRvTGF0TG5nKGxhdGxuZ3NbaV0pO1xyXG4gIFx0XHRwb2ludHMucHVzaChjcnMucHJvamVjdCh0b0xhdExuZyhbbGF0bG5nLmxhdCAtIGNlbnRyb2lkTGF0TG5nLmxhdCwgbGF0bG5nLmxuZyAtIGNlbnRyb2lkTGF0TG5nLmxuZ10pKSk7XHJcbiAgXHR9XHJcblxyXG4gIFx0YXJlYSA9IHggPSB5ID0gMDtcclxuXHJcbiAgXHQvLyBwb2x5Z29uIGNlbnRyb2lkIGFsZ29yaXRobTtcclxuICBcdGZvciAoaSA9IDAsIGogPSBsZW4gLSAxOyBpIDwgbGVuOyBqID0gaSsrKSB7XHJcbiAgXHRcdHAxID0gcG9pbnRzW2ldO1xyXG4gIFx0XHRwMiA9IHBvaW50c1tqXTtcclxuXHJcbiAgXHRcdGYgPSBwMS55ICogcDIueCAtIHAyLnkgKiBwMS54O1xyXG4gIFx0XHR4ICs9IChwMS54ICsgcDIueCkgKiBmO1xyXG4gIFx0XHR5ICs9IChwMS55ICsgcDIueSkgKiBmO1xyXG4gIFx0XHRhcmVhICs9IGYgKiAzO1xyXG4gIFx0fVxyXG5cclxuICBcdGlmIChhcmVhID09PSAwKSB7XHJcbiAgXHRcdC8vIFBvbHlnb24gaXMgc28gc21hbGwgdGhhdCBhbGwgcG9pbnRzIGFyZSBvbiBzYW1lIHBpeGVsLlxyXG4gIFx0XHRjZW50ZXIgPSBwb2ludHNbMF07XHJcbiAgXHR9IGVsc2Uge1xyXG4gIFx0XHRjZW50ZXIgPSBbeCAvIGFyZWEsIHkgLyBhcmVhXTtcclxuICBcdH1cclxuXHJcbiAgXHR2YXIgbGF0bG5nQ2VudGVyID0gY3JzLnVucHJvamVjdCh0b1BvaW50KGNlbnRlcikpO1xyXG4gIFx0cmV0dXJuIHRvTGF0TG5nKFtsYXRsbmdDZW50ZXIubGF0ICsgY2VudHJvaWRMYXRMbmcubGF0LCBsYXRsbmdDZW50ZXIubG5nICsgY2VudHJvaWRMYXRMbmcubG5nXSk7XHJcbiAgfVxyXG5cclxuICAvKiBAZnVuY3Rpb24gY2VudHJvaWQobGF0bG5nczogTGF0TG5nW10pOiBMYXRMbmdcclxuICAgKiBSZXR1cm5zIHRoZSAnY2VudGVyIG9mIG1hc3MnIG9mIHRoZSBwYXNzZWQgTGF0TG5ncy5cclxuICAgKi9cclxuICBmdW5jdGlvbiBjZW50cm9pZChjb29yZHMpIHtcclxuICBcdHZhciBsYXRTdW0gPSAwO1xyXG4gIFx0dmFyIGxuZ1N1bSA9IDA7XHJcbiAgXHR2YXIgbGVuID0gMDtcclxuICBcdGZvciAodmFyIGkgPSAwOyBpIDwgY29vcmRzLmxlbmd0aDsgaSsrKSB7XHJcbiAgXHRcdHZhciBsYXRsbmcgPSB0b0xhdExuZyhjb29yZHNbaV0pO1xyXG4gIFx0XHRsYXRTdW0gKz0gbGF0bG5nLmxhdDtcclxuICBcdFx0bG5nU3VtICs9IGxhdGxuZy5sbmc7XHJcbiAgXHRcdGxlbisrO1xyXG4gIFx0fVxyXG4gIFx0cmV0dXJuIHRvTGF0TG5nKFtsYXRTdW0gLyBsZW4sIGxuZ1N1bSAvIGxlbl0pO1xyXG4gIH1cblxuICB2YXIgUG9seVV0aWwgPSB7XG4gICAgX19wcm90b19fOiBudWxsLFxuICAgIGNsaXBQb2x5Z29uOiBjbGlwUG9seWdvbixcbiAgICBwb2x5Z29uQ2VudGVyOiBwb2x5Z29uQ2VudGVyLFxuICAgIGNlbnRyb2lkOiBjZW50cm9pZFxuICB9O1xuXG4gIC8qXHJcbiAgICogQG5hbWVzcGFjZSBMaW5lVXRpbFxyXG4gICAqXHJcbiAgICogVmFyaW91cyB1dGlsaXR5IGZ1bmN0aW9ucyBmb3IgcG9seWxpbmUgcG9pbnRzIHByb2Nlc3NpbmcsIHVzZWQgYnkgTGVhZmxldCBpbnRlcm5hbGx5IHRvIG1ha2UgcG9seWxpbmVzIGxpZ2h0bmluZy1mYXN0LlxyXG4gICAqL1xyXG5cclxuICAvLyBTaW1wbGlmeSBwb2x5bGluZSB3aXRoIHZlcnRleCByZWR1Y3Rpb24gYW5kIERvdWdsYXMtUGV1Y2tlciBzaW1wbGlmaWNhdGlvbi5cclxuICAvLyBJbXByb3ZlcyByZW5kZXJpbmcgcGVyZm9ybWFuY2UgZHJhbWF0aWNhbGx5IGJ5IGxlc3NlbmluZyB0aGUgbnVtYmVyIG9mIHBvaW50cyB0byBkcmF3LlxyXG5cclxuICAvLyBAZnVuY3Rpb24gc2ltcGxpZnkocG9pbnRzOiBQb2ludFtdLCB0b2xlcmFuY2U6IE51bWJlcik6IFBvaW50W11cclxuICAvLyBEcmFtYXRpY2FsbHkgcmVkdWNlcyB0aGUgbnVtYmVyIG9mIHBvaW50cyBpbiBhIHBvbHlsaW5lIHdoaWxlIHJldGFpbmluZ1xyXG4gIC8vIGl0cyBzaGFwZSBhbmQgcmV0dXJucyBhIG5ldyBhcnJheSBvZiBzaW1wbGlmaWVkIHBvaW50cywgdXNpbmcgdGhlXHJcbiAgLy8gW1JhbWVyLURvdWdsYXMtUGV1Y2tlciBhbGdvcml0aG1dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1JhbWVyLURvdWdsYXMtUGV1Y2tlcl9hbGdvcml0aG0pLlxyXG4gIC8vIFVzZWQgZm9yIGEgaHVnZSBwZXJmb3JtYW5jZSBib29zdCB3aGVuIHByb2Nlc3NpbmcvZGlzcGxheWluZyBMZWFmbGV0IHBvbHlsaW5lcyBmb3JcclxuICAvLyBlYWNoIHpvb20gbGV2ZWwgYW5kIGFsc28gcmVkdWNpbmcgdmlzdWFsIG5vaXNlLiB0b2xlcmFuY2UgYWZmZWN0cyB0aGUgYW1vdW50IG9mXHJcbiAgLy8gc2ltcGxpZmljYXRpb24gKGxlc3NlciB2YWx1ZSBtZWFucyBoaWdoZXIgcXVhbGl0eSBidXQgc2xvd2VyIGFuZCB3aXRoIG1vcmUgcG9pbnRzKS5cclxuICAvLyBBbHNvIHJlbGVhc2VkIGFzIGEgc2VwYXJhdGVkIG1pY3JvLWxpYnJhcnkgW1NpbXBsaWZ5LmpzXShodHRwczovL21vdXJuZXIuZ2l0aHViLmlvL3NpbXBsaWZ5LWpzLykuXHJcbiAgZnVuY3Rpb24gc2ltcGxpZnkocG9pbnRzLCB0b2xlcmFuY2UpIHtcclxuICBcdGlmICghdG9sZXJhbmNlIHx8ICFwb2ludHMubGVuZ3RoKSB7XHJcbiAgXHRcdHJldHVybiBwb2ludHMuc2xpY2UoKTtcclxuICBcdH1cclxuXHJcbiAgXHR2YXIgc3FUb2xlcmFuY2UgPSB0b2xlcmFuY2UgKiB0b2xlcmFuY2U7XHJcblxyXG4gIFx0ICAgIC8vIHN0YWdlIDE6IHZlcnRleCByZWR1Y3Rpb25cclxuICBcdCAgICBwb2ludHMgPSBfcmVkdWNlUG9pbnRzKHBvaW50cywgc3FUb2xlcmFuY2UpO1xyXG5cclxuICBcdCAgICAvLyBzdGFnZSAyOiBEb3VnbGFzLVBldWNrZXIgc2ltcGxpZmljYXRpb25cclxuICBcdCAgICBwb2ludHMgPSBfc2ltcGxpZnlEUChwb2ludHMsIHNxVG9sZXJhbmNlKTtcclxuXHJcbiAgXHRyZXR1cm4gcG9pbnRzO1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIHBvaW50VG9TZWdtZW50RGlzdGFuY2UocDogUG9pbnQsIHAxOiBQb2ludCwgcDI6IFBvaW50KTogTnVtYmVyXHJcbiAgLy8gUmV0dXJucyB0aGUgZGlzdGFuY2UgYmV0d2VlbiBwb2ludCBgcGAgYW5kIHNlZ21lbnQgYHAxYCB0byBgcDJgLlxyXG4gIGZ1bmN0aW9uIHBvaW50VG9TZWdtZW50RGlzdGFuY2UocCwgcDEsIHAyKSB7XHJcbiAgXHRyZXR1cm4gTWF0aC5zcXJ0KF9zcUNsb3Nlc3RQb2ludE9uU2VnbWVudChwLCBwMSwgcDIsIHRydWUpKTtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBjbG9zZXN0UG9pbnRPblNlZ21lbnQocDogUG9pbnQsIHAxOiBQb2ludCwgcDI6IFBvaW50KTogTnVtYmVyXHJcbiAgLy8gUmV0dXJucyB0aGUgY2xvc2VzdCBwb2ludCBmcm9tIGEgcG9pbnQgYHBgIG9uIGEgc2VnbWVudCBgcDFgIHRvIGBwMmAuXHJcbiAgZnVuY3Rpb24gY2xvc2VzdFBvaW50T25TZWdtZW50KHAsIHAxLCBwMikge1xyXG4gIFx0cmV0dXJuIF9zcUNsb3Nlc3RQb2ludE9uU2VnbWVudChwLCBwMSwgcDIpO1xyXG4gIH1cclxuXHJcbiAgLy8gUmFtZXItRG91Z2xhcy1QZXVja2VyIHNpbXBsaWZpY2F0aW9uLCBzZWUgaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUmFtZXItRG91Z2xhcy1QZXVja2VyX2FsZ29yaXRobVxyXG4gIGZ1bmN0aW9uIF9zaW1wbGlmeURQKHBvaW50cywgc3FUb2xlcmFuY2UpIHtcclxuXHJcbiAgXHR2YXIgbGVuID0gcG9pbnRzLmxlbmd0aCxcclxuICBcdCAgICBBcnJheUNvbnN0cnVjdG9yID0gdHlwZW9mIFVpbnQ4QXJyYXkgIT09IHVuZGVmaW5lZCArICcnID8gVWludDhBcnJheSA6IEFycmF5LFxyXG4gIFx0ICAgIG1hcmtlcnMgPSBuZXcgQXJyYXlDb25zdHJ1Y3RvcihsZW4pO1xyXG5cclxuICBcdCAgICBtYXJrZXJzWzBdID0gbWFya2Vyc1tsZW4gLSAxXSA9IDE7XHJcblxyXG4gIFx0X3NpbXBsaWZ5RFBTdGVwKHBvaW50cywgbWFya2Vycywgc3FUb2xlcmFuY2UsIDAsIGxlbiAtIDEpO1xyXG5cclxuICBcdHZhciBpLFxyXG4gIFx0ICAgIG5ld1BvaW50cyA9IFtdO1xyXG5cclxuICBcdGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xyXG4gIFx0XHRpZiAobWFya2Vyc1tpXSkge1xyXG4gIFx0XHRcdG5ld1BvaW50cy5wdXNoKHBvaW50c1tpXSk7XHJcbiAgXHRcdH1cclxuICBcdH1cclxuXHJcbiAgXHRyZXR1cm4gbmV3UG9pbnRzO1xyXG4gIH1cclxuXHJcbiAgZnVuY3Rpb24gX3NpbXBsaWZ5RFBTdGVwKHBvaW50cywgbWFya2Vycywgc3FUb2xlcmFuY2UsIGZpcnN0LCBsYXN0KSB7XHJcblxyXG4gIFx0dmFyIG1heFNxRGlzdCA9IDAsXHJcbiAgXHRpbmRleCwgaSwgc3FEaXN0O1xyXG5cclxuICBcdGZvciAoaSA9IGZpcnN0ICsgMTsgaSA8PSBsYXN0IC0gMTsgaSsrKSB7XHJcbiAgXHRcdHNxRGlzdCA9IF9zcUNsb3Nlc3RQb2ludE9uU2VnbWVudChwb2ludHNbaV0sIHBvaW50c1tmaXJzdF0sIHBvaW50c1tsYXN0XSwgdHJ1ZSk7XHJcblxyXG4gIFx0XHRpZiAoc3FEaXN0ID4gbWF4U3FEaXN0KSB7XHJcbiAgXHRcdFx0aW5kZXggPSBpO1xyXG4gIFx0XHRcdG1heFNxRGlzdCA9IHNxRGlzdDtcclxuICBcdFx0fVxyXG4gIFx0fVxyXG5cclxuICBcdGlmIChtYXhTcURpc3QgPiBzcVRvbGVyYW5jZSkge1xyXG4gIFx0XHRtYXJrZXJzW2luZGV4XSA9IDE7XHJcblxyXG4gIFx0XHRfc2ltcGxpZnlEUFN0ZXAocG9pbnRzLCBtYXJrZXJzLCBzcVRvbGVyYW5jZSwgZmlyc3QsIGluZGV4KTtcclxuICBcdFx0X3NpbXBsaWZ5RFBTdGVwKHBvaW50cywgbWFya2Vycywgc3FUb2xlcmFuY2UsIGluZGV4LCBsYXN0KTtcclxuICBcdH1cclxuICB9XHJcblxyXG4gIC8vIHJlZHVjZSBwb2ludHMgdGhhdCBhcmUgdG9vIGNsb3NlIHRvIGVhY2ggb3RoZXIgdG8gYSBzaW5nbGUgcG9pbnRcclxuICBmdW5jdGlvbiBfcmVkdWNlUG9pbnRzKHBvaW50cywgc3FUb2xlcmFuY2UpIHtcclxuICBcdHZhciByZWR1Y2VkUG9pbnRzID0gW3BvaW50c1swXV07XHJcblxyXG4gIFx0Zm9yICh2YXIgaSA9IDEsIHByZXYgPSAwLCBsZW4gPSBwb2ludHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuICBcdFx0aWYgKF9zcURpc3QocG9pbnRzW2ldLCBwb2ludHNbcHJldl0pID4gc3FUb2xlcmFuY2UpIHtcclxuICBcdFx0XHRyZWR1Y2VkUG9pbnRzLnB1c2gocG9pbnRzW2ldKTtcclxuICBcdFx0XHRwcmV2ID0gaTtcclxuICBcdFx0fVxyXG4gIFx0fVxyXG4gIFx0aWYgKHByZXYgPCBsZW4gLSAxKSB7XHJcbiAgXHRcdHJlZHVjZWRQb2ludHMucHVzaChwb2ludHNbbGVuIC0gMV0pO1xyXG4gIFx0fVxyXG4gIFx0cmV0dXJuIHJlZHVjZWRQb2ludHM7XHJcbiAgfVxyXG5cclxuICB2YXIgX2xhc3RDb2RlO1xyXG5cclxuICAvLyBAZnVuY3Rpb24gY2xpcFNlZ21lbnQoYTogUG9pbnQsIGI6IFBvaW50LCBib3VuZHM6IEJvdW5kcywgdXNlTGFzdENvZGU/OiBCb29sZWFuLCByb3VuZD86IEJvb2xlYW4pOiBQb2ludFtdfEJvb2xlYW5cclxuICAvLyBDbGlwcyB0aGUgc2VnbWVudCBhIHRvIGIgYnkgcmVjdGFuZ3VsYXIgYm91bmRzIHdpdGggdGhlXHJcbiAgLy8gW0NvaGVuLVN1dGhlcmxhbmQgYWxnb3JpdGhtXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Db2hlbiVFMiU4MCU5M1N1dGhlcmxhbmRfYWxnb3JpdGhtKVxyXG4gIC8vIChtb2RpZnlpbmcgdGhlIHNlZ21lbnQgcG9pbnRzIGRpcmVjdGx5ISkuIFVzZWQgYnkgTGVhZmxldCB0byBvbmx5IHNob3cgcG9seWxpbmVcclxuICAvLyBwb2ludHMgdGhhdCBhcmUgb24gdGhlIHNjcmVlbiBvciBuZWFyLCBpbmNyZWFzaW5nIHBlcmZvcm1hbmNlLlxyXG4gIGZ1bmN0aW9uIGNsaXBTZWdtZW50KGEsIGIsIGJvdW5kcywgdXNlTGFzdENvZGUsIHJvdW5kKSB7XHJcbiAgXHR2YXIgY29kZUEgPSB1c2VMYXN0Q29kZSA/IF9sYXN0Q29kZSA6IF9nZXRCaXRDb2RlKGEsIGJvdW5kcyksXHJcbiAgXHQgICAgY29kZUIgPSBfZ2V0Qml0Q29kZShiLCBib3VuZHMpLFxyXG5cclxuICBcdCAgICBjb2RlT3V0LCBwLCBuZXdDb2RlO1xyXG5cclxuICBcdCAgICAvLyBzYXZlIDJuZCBjb2RlIHRvIGF2b2lkIGNhbGN1bGF0aW5nIGl0IG9uIHRoZSBuZXh0IHNlZ21lbnRcclxuICBcdCAgICBfbGFzdENvZGUgPSBjb2RlQjtcclxuXHJcbiAgXHR3aGlsZSAodHJ1ZSkge1xyXG4gIFx0XHQvLyBpZiBhLGIgaXMgaW5zaWRlIHRoZSBjbGlwIHdpbmRvdyAodHJpdmlhbCBhY2NlcHQpXHJcbiAgXHRcdGlmICghKGNvZGVBIHwgY29kZUIpKSB7XHJcbiAgXHRcdFx0cmV0dXJuIFthLCBiXTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gaWYgYSxiIGlzIG91dHNpZGUgdGhlIGNsaXAgd2luZG93ICh0cml2aWFsIHJlamVjdClcclxuICBcdFx0aWYgKGNvZGVBICYgY29kZUIpIHtcclxuICBcdFx0XHRyZXR1cm4gZmFsc2U7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdC8vIG90aGVyIGNhc2VzXHJcbiAgXHRcdGNvZGVPdXQgPSBjb2RlQSB8fCBjb2RlQjtcclxuICBcdFx0cCA9IF9nZXRFZGdlSW50ZXJzZWN0aW9uKGEsIGIsIGNvZGVPdXQsIGJvdW5kcywgcm91bmQpO1xyXG4gIFx0XHRuZXdDb2RlID0gX2dldEJpdENvZGUocCwgYm91bmRzKTtcclxuXHJcbiAgXHRcdGlmIChjb2RlT3V0ID09PSBjb2RlQSkge1xyXG4gIFx0XHRcdGEgPSBwO1xyXG4gIFx0XHRcdGNvZGVBID0gbmV3Q29kZTtcclxuICBcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRiID0gcDtcclxuICBcdFx0XHRjb2RlQiA9IG5ld0NvZGU7XHJcbiAgXHRcdH1cclxuICBcdH1cclxuICB9XHJcblxyXG4gIGZ1bmN0aW9uIF9nZXRFZGdlSW50ZXJzZWN0aW9uKGEsIGIsIGNvZGUsIGJvdW5kcywgcm91bmQpIHtcclxuICBcdHZhciBkeCA9IGIueCAtIGEueCxcclxuICBcdCAgICBkeSA9IGIueSAtIGEueSxcclxuICBcdCAgICBtaW4gPSBib3VuZHMubWluLFxyXG4gIFx0ICAgIG1heCA9IGJvdW5kcy5tYXgsXHJcbiAgXHQgICAgeCwgeTtcclxuXHJcbiAgXHRpZiAoY29kZSAmIDgpIHsgLy8gdG9wXHJcbiAgXHRcdHggPSBhLnggKyBkeCAqIChtYXgueSAtIGEueSkgLyBkeTtcclxuICBcdFx0eSA9IG1heC55O1xyXG5cclxuICBcdH0gZWxzZSBpZiAoY29kZSAmIDQpIHsgLy8gYm90dG9tXHJcbiAgXHRcdHggPSBhLnggKyBkeCAqIChtaW4ueSAtIGEueSkgLyBkeTtcclxuICBcdFx0eSA9IG1pbi55O1xyXG5cclxuICBcdH0gZWxzZSBpZiAoY29kZSAmIDIpIHsgLy8gcmlnaHRcclxuICBcdFx0eCA9IG1heC54O1xyXG4gIFx0XHR5ID0gYS55ICsgZHkgKiAobWF4LnggLSBhLngpIC8gZHg7XHJcblxyXG4gIFx0fSBlbHNlIGlmIChjb2RlICYgMSkgeyAvLyBsZWZ0XHJcbiAgXHRcdHggPSBtaW4ueDtcclxuICBcdFx0eSA9IGEueSArIGR5ICogKG1pbi54IC0gYS54KSAvIGR4O1xyXG4gIFx0fVxyXG5cclxuICBcdHJldHVybiBuZXcgUG9pbnQoeCwgeSwgcm91bmQpO1xyXG4gIH1cclxuXHJcbiAgZnVuY3Rpb24gX2dldEJpdENvZGUocCwgYm91bmRzKSB7XHJcbiAgXHR2YXIgY29kZSA9IDA7XHJcblxyXG4gIFx0aWYgKHAueCA8IGJvdW5kcy5taW4ueCkgeyAvLyBsZWZ0XHJcbiAgXHRcdGNvZGUgfD0gMTtcclxuICBcdH0gZWxzZSBpZiAocC54ID4gYm91bmRzLm1heC54KSB7IC8vIHJpZ2h0XHJcbiAgXHRcdGNvZGUgfD0gMjtcclxuICBcdH1cclxuXHJcbiAgXHRpZiAocC55IDwgYm91bmRzLm1pbi55KSB7IC8vIGJvdHRvbVxyXG4gIFx0XHRjb2RlIHw9IDQ7XHJcbiAgXHR9IGVsc2UgaWYgKHAueSA+IGJvdW5kcy5tYXgueSkgeyAvLyB0b3BcclxuICBcdFx0Y29kZSB8PSA4O1xyXG4gIFx0fVxyXG5cclxuICBcdHJldHVybiBjb2RlO1xyXG4gIH1cclxuXHJcbiAgLy8gc3F1YXJlIGRpc3RhbmNlICh0byBhdm9pZCB1bm5lY2Vzc2FyeSBNYXRoLnNxcnQgY2FsbHMpXHJcbiAgZnVuY3Rpb24gX3NxRGlzdChwMSwgcDIpIHtcclxuICBcdHZhciBkeCA9IHAyLnggLSBwMS54LFxyXG4gIFx0ICAgIGR5ID0gcDIueSAtIHAxLnk7XHJcbiAgXHRyZXR1cm4gZHggKiBkeCArIGR5ICogZHk7XHJcbiAgfVxyXG5cclxuICAvLyByZXR1cm4gY2xvc2VzdCBwb2ludCBvbiBzZWdtZW50IG9yIGRpc3RhbmNlIHRvIHRoYXQgcG9pbnRcclxuICBmdW5jdGlvbiBfc3FDbG9zZXN0UG9pbnRPblNlZ21lbnQocCwgcDEsIHAyLCBzcURpc3QpIHtcclxuICBcdHZhciB4ID0gcDEueCxcclxuICBcdCAgICB5ID0gcDEueSxcclxuICBcdCAgICBkeCA9IHAyLnggLSB4LFxyXG4gIFx0ICAgIGR5ID0gcDIueSAtIHksXHJcbiAgXHQgICAgZG90ID0gZHggKiBkeCArIGR5ICogZHksXHJcbiAgXHQgICAgdDtcclxuXHJcbiAgXHRpZiAoZG90ID4gMCkge1xyXG4gIFx0XHR0ID0gKChwLnggLSB4KSAqIGR4ICsgKHAueSAtIHkpICogZHkpIC8gZG90O1xyXG5cclxuICBcdFx0aWYgKHQgPiAxKSB7XHJcbiAgXHRcdFx0eCA9IHAyLng7XHJcbiAgXHRcdFx0eSA9IHAyLnk7XHJcbiAgXHRcdH0gZWxzZSBpZiAodCA+IDApIHtcclxuICBcdFx0XHR4ICs9IGR4ICogdDtcclxuICBcdFx0XHR5ICs9IGR5ICogdDtcclxuICBcdFx0fVxyXG4gIFx0fVxyXG5cclxuICBcdGR4ID0gcC54IC0geDtcclxuICBcdGR5ID0gcC55IC0geTtcclxuXHJcbiAgXHRyZXR1cm4gc3FEaXN0ID8gZHggKiBkeCArIGR5ICogZHkgOiBuZXcgUG9pbnQoeCwgeSk7XHJcbiAgfVxyXG5cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGlzRmxhdChsYXRsbmdzOiBMYXRMbmdbXSk6IEJvb2xlYW5cclxuICAvLyBSZXR1cm5zIHRydWUgaWYgYGxhdGxuZ3NgIGlzIGEgZmxhdCBhcnJheSwgZmFsc2UgaXMgbmVzdGVkLlxyXG4gIGZ1bmN0aW9uIGlzRmxhdChsYXRsbmdzKSB7XHJcbiAgXHRyZXR1cm4gIWlzQXJyYXkobGF0bG5nc1swXSkgfHwgKHR5cGVvZiBsYXRsbmdzWzBdWzBdICE9PSAnb2JqZWN0JyAmJiB0eXBlb2YgbGF0bG5nc1swXVswXSAhPT0gJ3VuZGVmaW5lZCcpO1xyXG4gIH1cclxuXHJcbiAgZnVuY3Rpb24gX2ZsYXQobGF0bG5ncykge1xyXG4gIFx0Y29uc29sZS53YXJuKCdEZXByZWNhdGVkIHVzZSBvZiBfZmxhdCwgcGxlYXNlIHVzZSBMLkxpbmVVdGlsLmlzRmxhdCBpbnN0ZWFkLicpO1xyXG4gIFx0cmV0dXJuIGlzRmxhdChsYXRsbmdzKTtcclxuICB9XHJcblxyXG4gIC8qIEBmdW5jdGlvbiBwb2x5bGluZUNlbnRlcihsYXRsbmdzOiBMYXRMbmdbXSwgY3JzOiBDUlMpOiBMYXRMbmdcclxuICAgKiBSZXR1cm5zIHRoZSBjZW50ZXIgKFtjZW50cm9pZF0oaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9DZW50cm9pZCkpIG9mIHRoZSBwYXNzZWQgTGF0TG5ncyAoZmlyc3QgcmluZykgZnJvbSBhIHBvbHlsaW5lLlxyXG4gICAqL1xyXG4gIGZ1bmN0aW9uIHBvbHlsaW5lQ2VudGVyKGxhdGxuZ3MsIGNycykge1xyXG4gIFx0dmFyIGksIGhhbGZEaXN0LCBzZWdEaXN0LCBkaXN0LCBwMSwgcDIsIHJhdGlvLCBjZW50ZXI7XHJcblxyXG4gIFx0aWYgKCFsYXRsbmdzIHx8IGxhdGxuZ3MubGVuZ3RoID09PSAwKSB7XHJcbiAgXHRcdHRocm93IG5ldyBFcnJvcignbGF0bG5ncyBub3QgcGFzc2VkJyk7XHJcbiAgXHR9XHJcblxyXG4gIFx0aWYgKCFpc0ZsYXQobGF0bG5ncykpIHtcclxuICBcdFx0Y29uc29sZS53YXJuKCdsYXRsbmdzIGFyZSBub3QgZmxhdCEgT25seSB0aGUgZmlyc3QgcmluZyB3aWxsIGJlIHVzZWQnKTtcclxuICBcdFx0bGF0bG5ncyA9IGxhdGxuZ3NbMF07XHJcbiAgXHR9XHJcblxyXG4gIFx0dmFyIGNlbnRyb2lkTGF0TG5nID0gdG9MYXRMbmcoWzAsIDBdKTtcclxuXHJcbiAgXHR2YXIgYm91bmRzID0gdG9MYXRMbmdCb3VuZHMobGF0bG5ncyk7XHJcbiAgXHR2YXIgYXJlYUJvdW5kcyA9IGJvdW5kcy5nZXROb3J0aFdlc3QoKS5kaXN0YW5jZVRvKGJvdW5kcy5nZXRTb3V0aFdlc3QoKSkgKiBib3VuZHMuZ2V0Tm9ydGhFYXN0KCkuZGlzdGFuY2VUbyhib3VuZHMuZ2V0Tm9ydGhXZXN0KCkpO1xyXG4gIFx0Ly8gdGVzdHMgc2hvd2VkIHRoYXQgYmVsb3cgMTcwMCByb3VuZGluZyBlcnJvcnMgYXJlIGhhcHBlbmluZ1xyXG4gIFx0aWYgKGFyZWFCb3VuZHMgPCAxNzAwKSB7XHJcbiAgXHRcdC8vIGdldHRpbmcgYSBpbmV4YWN0IGNlbnRlciwgdG8gbW92ZSB0aGUgbGF0bG5ncyBuZWFyIHRvIFswLCAwXSB0byBwcmV2ZW50IHJvdW5kaW5nIGVycm9yc1xyXG4gIFx0XHRjZW50cm9pZExhdExuZyA9IGNlbnRyb2lkKGxhdGxuZ3MpO1xyXG4gIFx0fVxyXG5cclxuICBcdHZhciBsZW4gPSBsYXRsbmdzLmxlbmd0aDtcclxuICBcdHZhciBwb2ludHMgPSBbXTtcclxuICBcdGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xyXG4gIFx0XHR2YXIgbGF0bG5nID0gdG9MYXRMbmcobGF0bG5nc1tpXSk7XHJcbiAgXHRcdHBvaW50cy5wdXNoKGNycy5wcm9qZWN0KHRvTGF0TG5nKFtsYXRsbmcubGF0IC0gY2VudHJvaWRMYXRMbmcubGF0LCBsYXRsbmcubG5nIC0gY2VudHJvaWRMYXRMbmcubG5nXSkpKTtcclxuICBcdH1cclxuXHJcbiAgXHRmb3IgKGkgPSAwLCBoYWxmRGlzdCA9IDA7IGkgPCBsZW4gLSAxOyBpKyspIHtcclxuICBcdFx0aGFsZkRpc3QgKz0gcG9pbnRzW2ldLmRpc3RhbmNlVG8ocG9pbnRzW2kgKyAxXSkgLyAyO1xyXG4gIFx0fVxyXG5cclxuICBcdC8vIFRoZSBsaW5lIGlzIHNvIHNtYWxsIGluIHRoZSBjdXJyZW50IHZpZXcgdGhhdCBhbGwgcG9pbnRzIGFyZSBvbiB0aGUgc2FtZSBwaXhlbC5cclxuICBcdGlmIChoYWxmRGlzdCA9PT0gMCkge1xyXG4gIFx0XHRjZW50ZXIgPSBwb2ludHNbMF07XHJcbiAgXHR9IGVsc2Uge1xyXG4gIFx0XHRmb3IgKGkgPSAwLCBkaXN0ID0gMDsgaSA8IGxlbiAtIDE7IGkrKykge1xyXG4gIFx0XHRcdHAxID0gcG9pbnRzW2ldO1xyXG4gIFx0XHRcdHAyID0gcG9pbnRzW2kgKyAxXTtcclxuICBcdFx0XHRzZWdEaXN0ID0gcDEuZGlzdGFuY2VUbyhwMik7XHJcbiAgXHRcdFx0ZGlzdCArPSBzZWdEaXN0O1xyXG5cclxuICBcdFx0XHRpZiAoZGlzdCA+IGhhbGZEaXN0KSB7XHJcbiAgXHRcdFx0XHRyYXRpbyA9IChkaXN0IC0gaGFsZkRpc3QpIC8gc2VnRGlzdDtcclxuICBcdFx0XHRcdGNlbnRlciA9IFtcclxuICBcdFx0XHRcdFx0cDIueCAtIHJhdGlvICogKHAyLnggLSBwMS54KSxcclxuICBcdFx0XHRcdFx0cDIueSAtIHJhdGlvICogKHAyLnkgLSBwMS55KVxyXG4gIFx0XHRcdFx0XTtcclxuICBcdFx0XHRcdGJyZWFrO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG4gIFx0fVxyXG5cclxuICBcdHZhciBsYXRsbmdDZW50ZXIgPSBjcnMudW5wcm9qZWN0KHRvUG9pbnQoY2VudGVyKSk7XHJcbiAgXHRyZXR1cm4gdG9MYXRMbmcoW2xhdGxuZ0NlbnRlci5sYXQgKyBjZW50cm9pZExhdExuZy5sYXQsIGxhdGxuZ0NlbnRlci5sbmcgKyBjZW50cm9pZExhdExuZy5sbmddKTtcclxuICB9XG5cbiAgdmFyIExpbmVVdGlsID0ge1xuICAgIF9fcHJvdG9fXzogbnVsbCxcbiAgICBzaW1wbGlmeTogc2ltcGxpZnksXG4gICAgcG9pbnRUb1NlZ21lbnREaXN0YW5jZTogcG9pbnRUb1NlZ21lbnREaXN0YW5jZSxcbiAgICBjbG9zZXN0UG9pbnRPblNlZ21lbnQ6IGNsb3Nlc3RQb2ludE9uU2VnbWVudCxcbiAgICBjbGlwU2VnbWVudDogY2xpcFNlZ21lbnQsXG4gICAgX2dldEVkZ2VJbnRlcnNlY3Rpb246IF9nZXRFZGdlSW50ZXJzZWN0aW9uLFxuICAgIF9nZXRCaXRDb2RlOiBfZ2V0Qml0Q29kZSxcbiAgICBfc3FDbG9zZXN0UG9pbnRPblNlZ21lbnQ6IF9zcUNsb3Nlc3RQb2ludE9uU2VnbWVudCxcbiAgICBpc0ZsYXQ6IGlzRmxhdCxcbiAgICBfZmxhdDogX2ZsYXQsXG4gICAgcG9seWxpbmVDZW50ZXI6IHBvbHlsaW5lQ2VudGVyXG4gIH07XG5cbiAgLypcclxuICAgKiBAbmFtZXNwYWNlIFByb2plY3Rpb25cclxuICAgKiBAc2VjdGlvblxyXG4gICAqIExlYWZsZXQgY29tZXMgd2l0aCBhIHNldCBvZiBhbHJlYWR5IGRlZmluZWQgUHJvamVjdGlvbnMgb3V0IG9mIHRoZSBib3g6XHJcbiAgICpcclxuICAgKiBAcHJvamVjdGlvbiBMLlByb2plY3Rpb24uTG9uTGF0XHJcbiAgICpcclxuICAgKiBFcXVpcmVjdGFuZ3VsYXIsIG9yIFBsYXRlIENhcnJlZSBwcm9qZWN0aW9uIOKAlCB0aGUgbW9zdCBzaW1wbGUgcHJvamVjdGlvbixcclxuICAgKiBtb3N0bHkgdXNlZCBieSBHSVMgZW50aHVzaWFzdHMuIERpcmVjdGx5IG1hcHMgYHhgIGFzIGxvbmdpdHVkZSwgYW5kIGB5YCBhc1xyXG4gICAqIGxhdGl0dWRlLiBBbHNvIHN1aXRhYmxlIGZvciBmbGF0IHdvcmxkcywgZS5nLiBnYW1lIG1hcHMuIFVzZWQgYnkgdGhlXHJcbiAgICogYEVQU0c6NDMyNmAgYW5kIGBTaW1wbGVgIENSUy5cclxuICAgKi9cclxuXHJcbiAgdmFyIExvbkxhdCA9IHtcclxuICBcdHByb2plY3Q6IGZ1bmN0aW9uIChsYXRsbmcpIHtcclxuICBcdFx0cmV0dXJuIG5ldyBQb2ludChsYXRsbmcubG5nLCBsYXRsbmcubGF0KTtcclxuICBcdH0sXHJcblxyXG4gIFx0dW5wcm9qZWN0OiBmdW5jdGlvbiAocG9pbnQpIHtcclxuICBcdFx0cmV0dXJuIG5ldyBMYXRMbmcocG9pbnQueSwgcG9pbnQueCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdGJvdW5kczogbmV3IEJvdW5kcyhbLTE4MCwgLTkwXSwgWzE4MCwgOTBdKVxyXG4gIH07XG5cbiAgLypcclxuICAgKiBAbmFtZXNwYWNlIFByb2plY3Rpb25cclxuICAgKiBAcHJvamVjdGlvbiBMLlByb2plY3Rpb24uTWVyY2F0b3JcclxuICAgKlxyXG4gICAqIEVsbGlwdGljYWwgTWVyY2F0b3IgcHJvamVjdGlvbiDigJQgbW9yZSBjb21wbGV4IHRoYW4gU3BoZXJpY2FsIE1lcmNhdG9yLiBBc3N1bWVzIHRoYXQgRWFydGggaXMgYW4gZWxsaXBzb2lkLiBVc2VkIGJ5IHRoZSBFUFNHOjMzOTUgQ1JTLlxyXG4gICAqL1xyXG5cclxuICB2YXIgTWVyY2F0b3IgPSB7XHJcbiAgXHRSOiA2Mzc4MTM3LFxyXG4gIFx0Ul9NSU5PUjogNjM1Njc1Mi4zMTQyNDUxNzksXHJcblxyXG4gIFx0Ym91bmRzOiBuZXcgQm91bmRzKFstMjAwMzc1MDguMzQyNzksIC0xNTQ5NjU3MC43Mzk3Ml0sIFsyMDAzNzUwOC4zNDI3OSwgMTg3NjQ2NTYuMjMxMzhdKSxcclxuXHJcbiAgXHRwcm9qZWN0OiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcbiAgXHRcdHZhciBkID0gTWF0aC5QSSAvIDE4MCxcclxuICBcdFx0ICAgIHIgPSB0aGlzLlIsXHJcbiAgXHRcdCAgICB5ID0gbGF0bG5nLmxhdCAqIGQsXHJcbiAgXHRcdCAgICB0bXAgPSB0aGlzLlJfTUlOT1IgLyByLFxyXG4gIFx0XHQgICAgZSA9IE1hdGguc3FydCgxIC0gdG1wICogdG1wKSxcclxuICBcdFx0ICAgIGNvbiA9IGUgKiBNYXRoLnNpbih5KTtcclxuXHJcbiAgXHRcdHZhciB0cyA9IE1hdGgudGFuKE1hdGguUEkgLyA0IC0geSAvIDIpIC8gTWF0aC5wb3coKDEgLSBjb24pIC8gKDEgKyBjb24pLCBlIC8gMik7XHJcbiAgXHRcdHkgPSAtciAqIE1hdGgubG9nKE1hdGgubWF4KHRzLCAxRS0xMCkpO1xyXG5cclxuICBcdFx0cmV0dXJuIG5ldyBQb2ludChsYXRsbmcubG5nICogZCAqIHIsIHkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHR1bnByb2plY3Q6IGZ1bmN0aW9uIChwb2ludCkge1xyXG4gIFx0XHR2YXIgZCA9IDE4MCAvIE1hdGguUEksXHJcbiAgXHRcdCAgICByID0gdGhpcy5SLFxyXG4gIFx0XHQgICAgdG1wID0gdGhpcy5SX01JTk9SIC8gcixcclxuICBcdFx0ICAgIGUgPSBNYXRoLnNxcnQoMSAtIHRtcCAqIHRtcCksXHJcbiAgXHRcdCAgICB0cyA9IE1hdGguZXhwKC1wb2ludC55IC8gciksXHJcbiAgXHRcdCAgICBwaGkgPSBNYXRoLlBJIC8gMiAtIDIgKiBNYXRoLmF0YW4odHMpO1xyXG5cclxuICBcdFx0Zm9yICh2YXIgaSA9IDAsIGRwaGkgPSAwLjEsIGNvbjsgaSA8IDE1ICYmIE1hdGguYWJzKGRwaGkpID4gMWUtNzsgaSsrKSB7XHJcbiAgXHRcdFx0Y29uID0gZSAqIE1hdGguc2luKHBoaSk7XHJcbiAgXHRcdFx0Y29uID0gTWF0aC5wb3coKDEgLSBjb24pIC8gKDEgKyBjb24pLCBlIC8gMik7XHJcbiAgXHRcdFx0ZHBoaSA9IE1hdGguUEkgLyAyIC0gMiAqIE1hdGguYXRhbih0cyAqIGNvbikgLSBwaGk7XHJcbiAgXHRcdFx0cGhpICs9IGRwaGk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiBuZXcgTGF0TG5nKHBoaSAqIGQsIHBvaW50LnggKiBkIC8gcik7XHJcbiAgXHR9XHJcbiAgfTtcblxuICAvKlxuICAgKiBAY2xhc3MgUHJvamVjdGlvblxuXG4gICAqIEFuIG9iamVjdCB3aXRoIG1ldGhvZHMgZm9yIHByb2plY3RpbmcgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGVzIG9mIHRoZSB3b3JsZCBvbnRvXG4gICAqIGEgZmxhdCBzdXJmYWNlIChhbmQgYmFjaykuIFNlZSBbTWFwIHByb2plY3Rpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL01hcF9wcm9qZWN0aW9uKS5cblxuICAgKiBAcHJvcGVydHkgYm91bmRzOiBCb3VuZHNcbiAgICogVGhlIGJvdW5kcyAoc3BlY2lmaWVkIGluIENSUyB1bml0cykgd2hlcmUgdGhlIHByb2plY3Rpb24gaXMgdmFsaWRcblxuICAgKiBAbWV0aG9kIHByb2plY3QobGF0bG5nOiBMYXRMbmcpOiBQb2ludFxuICAgKiBQcm9qZWN0cyBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZXMgaW50byBhIDJEIHBvaW50LlxuICAgKiBPbmx5IGFjY2VwdHMgYWN0dWFsIGBMLkxhdExuZ2AgaW5zdGFuY2VzLCBub3QgYXJyYXlzLlxuXG4gICAqIEBtZXRob2QgdW5wcm9qZWN0KHBvaW50OiBQb2ludCk6IExhdExuZ1xuICAgKiBUaGUgaW52ZXJzZSBvZiBgcHJvamVjdGAuIFByb2plY3RzIGEgMkQgcG9pbnQgaW50byBhIGdlb2dyYXBoaWNhbCBsb2NhdGlvbi5cbiAgICogT25seSBhY2NlcHRzIGFjdHVhbCBgTC5Qb2ludGAgaW5zdGFuY2VzLCBub3QgYXJyYXlzLlxuXG4gICAqIE5vdGUgdGhhdCB0aGUgcHJvamVjdGlvbiBpbnN0YW5jZXMgZG8gbm90IGluaGVyaXQgZnJvbSBMZWFmbGV0J3MgYENsYXNzYCBvYmplY3QsXG4gICAqIGFuZCBjYW4ndCBiZSBpbnN0YW50aWF0ZWQuIEFsc28sIG5ldyBjbGFzc2VzIGNhbid0IGluaGVyaXQgZnJvbSB0aGVtLFxuICAgKiBhbmQgbWV0aG9kcyBjYW4ndCBiZSBhZGRlZCB0byB0aGVtIHdpdGggdGhlIGBpbmNsdWRlYCBmdW5jdGlvbi5cblxuICAgKi9cblxuICB2YXIgaW5kZXggPSB7XG4gICAgX19wcm90b19fOiBudWxsLFxuICAgIExvbkxhdDogTG9uTGF0LFxuICAgIE1lcmNhdG9yOiBNZXJjYXRvcixcbiAgICBTcGhlcmljYWxNZXJjYXRvcjogU3BoZXJpY2FsTWVyY2F0b3JcbiAgfTtcblxuICAvKlxyXG4gICAqIEBuYW1lc3BhY2UgQ1JTXHJcbiAgICogQGNycyBMLkNSUy5FUFNHMzM5NVxyXG4gICAqXHJcbiAgICogUmFyZWx5IHVzZWQgYnkgc29tZSBjb21tZXJjaWFsIHRpbGUgcHJvdmlkZXJzLiBVc2VzIEVsbGlwdGljYWwgTWVyY2F0b3IgcHJvamVjdGlvbi5cclxuICAgKi9cclxuICB2YXIgRVBTRzMzOTUgPSBleHRlbmQoe30sIEVhcnRoLCB7XHJcbiAgXHRjb2RlOiAnRVBTRzozMzk1JyxcclxuICBcdHByb2plY3Rpb246IE1lcmNhdG9yLFxyXG5cclxuICBcdHRyYW5zZm9ybWF0aW9uOiAoZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR2YXIgc2NhbGUgPSAwLjUgLyAoTWF0aC5QSSAqIE1lcmNhdG9yLlIpO1xyXG4gIFx0XHRyZXR1cm4gdG9UcmFuc2Zvcm1hdGlvbihzY2FsZSwgMC41LCAtc2NhbGUsIDAuNSk7XHJcbiAgXHR9KCkpXHJcbiAgfSk7XG5cbiAgLypcclxuICAgKiBAbmFtZXNwYWNlIENSU1xyXG4gICAqIEBjcnMgTC5DUlMuRVBTRzQzMjZcclxuICAgKlxyXG4gICAqIEEgY29tbW9uIENSUyBhbW9uZyBHSVMgZW50aHVzaWFzdHMuIFVzZXMgc2ltcGxlIEVxdWlyZWN0YW5ndWxhciBwcm9qZWN0aW9uLlxyXG4gICAqXHJcbiAgICogTGVhZmxldCAxLjAueCBjb21wbGllcyB3aXRoIHRoZSBbVE1TIGNvb3JkaW5hdGUgc2NoZW1lIGZvciBFUFNHOjQzMjZdKGh0dHBzOi8vd2lraS5vc2dlby5vcmcvd2lraS9UaWxlX01hcF9TZXJ2aWNlX1NwZWNpZmljYXRpb24jZ2xvYmFsLWdlb2RldGljKSxcclxuICAgKiB3aGljaCBpcyBhIGJyZWFraW5nIGNoYW5nZSBmcm9tIDAuNy54IGJlaGF2aW91ci4gIElmIHlvdSBhcmUgdXNpbmcgYSBgVGlsZUxheWVyYFxyXG4gICAqIHdpdGggdGhpcyBDUlMsIGVuc3VyZSB0aGF0IHRoZXJlIGFyZSB0d28gMjU2eDI1NiBwaXhlbCB0aWxlcyBjb3ZlcmluZyB0aGVcclxuICAgKiB3aG9sZSBlYXJ0aCBhdCB6b29tIGxldmVsIHplcm8sIGFuZCB0aGF0IHRoZSB0aWxlIGNvb3JkaW5hdGUgb3JpZ2luIGlzICgtMTgwLCs5MCksXHJcbiAgICogb3IgKC0xODAsLTkwKSBmb3IgYFRpbGVMYXllcmBzIHdpdGggW3RoZSBgdG1zYCBvcHRpb25dKCN0aWxlbGF5ZXItdG1zKSBzZXQuXHJcbiAgICovXHJcblxyXG4gIHZhciBFUFNHNDMyNiA9IGV4dGVuZCh7fSwgRWFydGgsIHtcclxuICBcdGNvZGU6ICdFUFNHOjQzMjYnLFxyXG4gIFx0cHJvamVjdGlvbjogTG9uTGF0LFxyXG4gIFx0dHJhbnNmb3JtYXRpb246IHRvVHJhbnNmb3JtYXRpb24oMSAvIDE4MCwgMSwgLTEgLyAxODAsIDAuNSlcclxuICB9KTtcblxuICAvKlxuICAgKiBAbmFtZXNwYWNlIENSU1xuICAgKiBAY3JzIEwuQ1JTLlNpbXBsZVxuICAgKlxuICAgKiBBIHNpbXBsZSBDUlMgdGhhdCBtYXBzIGxvbmdpdHVkZSBhbmQgbGF0aXR1ZGUgaW50byBgeGAgYW5kIGB5YCBkaXJlY3RseS5cbiAgICogTWF5IGJlIHVzZWQgZm9yIG1hcHMgb2YgZmxhdCBzdXJmYWNlcyAoZS5nLiBnYW1lIG1hcHMpLiBOb3RlIHRoYXQgdGhlIGB5YFxuICAgKiBheGlzIHNob3VsZCBzdGlsbCBiZSBpbnZlcnRlZCAoZ29pbmcgZnJvbSBib3R0b20gdG8gdG9wKS4gYGRpc3RhbmNlKClgIHJldHVybnNcbiAgICogc2ltcGxlIGV1Y2xpZGVhbiBkaXN0YW5jZS5cbiAgICovXG5cbiAgdmFyIFNpbXBsZSA9IGV4dGVuZCh7fSwgQ1JTLCB7XG4gIFx0cHJvamVjdGlvbjogTG9uTGF0LFxuICBcdHRyYW5zZm9ybWF0aW9uOiB0b1RyYW5zZm9ybWF0aW9uKDEsIDAsIC0xLCAwKSxcblxuICBcdHNjYWxlOiBmdW5jdGlvbiAoem9vbSkge1xuICBcdFx0cmV0dXJuIE1hdGgucG93KDIsIHpvb20pO1xuICBcdH0sXG5cbiAgXHR6b29tOiBmdW5jdGlvbiAoc2NhbGUpIHtcbiAgXHRcdHJldHVybiBNYXRoLmxvZyhzY2FsZSkgLyBNYXRoLkxOMjtcbiAgXHR9LFxuXG4gIFx0ZGlzdGFuY2U6IGZ1bmN0aW9uIChsYXRsbmcxLCBsYXRsbmcyKSB7XG4gIFx0XHR2YXIgZHggPSBsYXRsbmcyLmxuZyAtIGxhdGxuZzEubG5nLFxuICBcdFx0ICAgIGR5ID0gbGF0bG5nMi5sYXQgLSBsYXRsbmcxLmxhdDtcblxuICBcdFx0cmV0dXJuIE1hdGguc3FydChkeCAqIGR4ICsgZHkgKiBkeSk7XG4gIFx0fSxcblxuICBcdGluZmluaXRlOiB0cnVlXG4gIH0pO1xuXG4gIENSUy5FYXJ0aCA9IEVhcnRoO1xuICBDUlMuRVBTRzMzOTUgPSBFUFNHMzM5NTtcbiAgQ1JTLkVQU0czODU3ID0gRVBTRzM4NTc7XG4gIENSUy5FUFNHOTAwOTEzID0gRVBTRzkwMDkxMztcbiAgQ1JTLkVQU0c0MzI2ID0gRVBTRzQzMjY7XG4gIENSUy5TaW1wbGUgPSBTaW1wbGU7XG5cbiAgLypcbiAgICogQGNsYXNzIExheWVyXG4gICAqIEBpbmhlcml0cyBFdmVudGVkXG4gICAqIEBha2EgTC5MYXllclxuICAgKiBAYWthIElMYXllclxuICAgKlxuICAgKiBBIHNldCBvZiBtZXRob2RzIGZyb20gdGhlIExheWVyIGJhc2UgY2xhc3MgdGhhdCBhbGwgTGVhZmxldCBsYXllcnMgdXNlLlxuICAgKiBJbmhlcml0cyBhbGwgbWV0aG9kcywgb3B0aW9ucyBhbmQgZXZlbnRzIGZyb20gYEwuRXZlbnRlZGAuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqIGBgYGpzXG4gICAqIHZhciBsYXllciA9IEwubWFya2VyKGxhdGxuZykuYWRkVG8obWFwKTtcbiAgICogbGF5ZXIuYWRkVG8obWFwKTtcbiAgICogbGF5ZXIucmVtb3ZlKCk7XG4gICAqIGBgYFxuICAgKlxuICAgKiBAZXZlbnQgYWRkOiBFdmVudFxuICAgKiBGaXJlZCBhZnRlciB0aGUgbGF5ZXIgaXMgYWRkZWQgdG8gYSBtYXBcbiAgICpcbiAgICogQGV2ZW50IHJlbW92ZTogRXZlbnRcbiAgICogRmlyZWQgYWZ0ZXIgdGhlIGxheWVyIGlzIHJlbW92ZWQgZnJvbSBhIG1hcFxuICAgKi9cblxuXG4gIHZhciBMYXllciA9IEV2ZW50ZWQuZXh0ZW5kKHtcblxuICBcdC8vIENsYXNzZXMgZXh0ZW5kaW5nIGBMLkxheWVyYCB3aWxsIGluaGVyaXQgdGhlIGZvbGxvd2luZyBvcHRpb25zOlxuICBcdG9wdGlvbnM6IHtcbiAgXHRcdC8vIEBvcHRpb24gcGFuZTogU3RyaW5nID0gJ292ZXJsYXlQYW5lJ1xuICBcdFx0Ly8gQnkgZGVmYXVsdCB0aGUgbGF5ZXIgd2lsbCBiZSBhZGRlZCB0byB0aGUgbWFwJ3MgW292ZXJsYXkgcGFuZV0oI21hcC1vdmVybGF5cGFuZSkuIE92ZXJyaWRpbmcgdGhpcyBvcHRpb24gd2lsbCBjYXVzZSB0aGUgbGF5ZXIgdG8gYmUgcGxhY2VkIG9uIGFub3RoZXIgcGFuZSBieSBkZWZhdWx0LlxuICBcdFx0cGFuZTogJ292ZXJsYXlQYW5lJyxcblxuICBcdFx0Ly8gQG9wdGlvbiBhdHRyaWJ1dGlvbjogU3RyaW5nID0gbnVsbFxuICBcdFx0Ly8gU3RyaW5nIHRvIGJlIHNob3duIGluIHRoZSBhdHRyaWJ1dGlvbiBjb250cm9sLCBlLmcuIFwiwqkgT3BlblN0cmVldE1hcCBjb250cmlidXRvcnNcIi4gSXQgZGVzY3JpYmVzIHRoZSBsYXllciBkYXRhIGFuZCBpcyBvZnRlbiBhIGxlZ2FsIG9ibGlnYXRpb24gdG93YXJkcyBjb3B5cmlnaHQgaG9sZGVycyBhbmQgdGlsZSBwcm92aWRlcnMuXG4gIFx0XHRhdHRyaWJ1dGlvbjogbnVsbCxcblxuICBcdFx0YnViYmxpbmdNb3VzZUV2ZW50czogdHJ1ZVxuICBcdH0sXG5cbiAgXHQvKiBAc2VjdGlvblxuICBcdCAqIENsYXNzZXMgZXh0ZW5kaW5nIGBMLkxheWVyYCB3aWxsIGluaGVyaXQgdGhlIGZvbGxvd2luZyBtZXRob2RzOlxuICBcdCAqXG4gIFx0ICogQG1ldGhvZCBhZGRUbyhtYXA6IE1hcHxMYXllckdyb3VwKTogdGhpc1xuICBcdCAqIEFkZHMgdGhlIGxheWVyIHRvIHRoZSBnaXZlbiBtYXAgb3IgbGF5ZXIgZ3JvdXAuXG4gIFx0ICovXG4gIFx0YWRkVG86IGZ1bmN0aW9uIChtYXApIHtcbiAgXHRcdG1hcC5hZGRMYXllcih0aGlzKTtcbiAgXHRcdHJldHVybiB0aGlzO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIHJlbW92ZTogdGhpc1xuICBcdC8vIFJlbW92ZXMgdGhlIGxheWVyIGZyb20gdGhlIG1hcCBpdCBpcyBjdXJyZW50bHkgYWN0aXZlIG9uLlxuICBcdHJlbW92ZTogZnVuY3Rpb24gKCkge1xuICBcdFx0cmV0dXJuIHRoaXMucmVtb3ZlRnJvbSh0aGlzLl9tYXAgfHwgdGhpcy5fbWFwVG9BZGQpO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIHJlbW92ZUZyb20obWFwOiBNYXApOiB0aGlzXG4gIFx0Ly8gUmVtb3ZlcyB0aGUgbGF5ZXIgZnJvbSB0aGUgZ2l2ZW4gbWFwXG4gIFx0Ly9cbiAgXHQvLyBAYWx0ZXJuYXRpdmVcbiAgXHQvLyBAbWV0aG9kIHJlbW92ZUZyb20oZ3JvdXA6IExheWVyR3JvdXApOiB0aGlzXG4gIFx0Ly8gUmVtb3ZlcyB0aGUgbGF5ZXIgZnJvbSB0aGUgZ2l2ZW4gYExheWVyR3JvdXBgXG4gIFx0cmVtb3ZlRnJvbTogZnVuY3Rpb24gKG9iaikge1xuICBcdFx0aWYgKG9iaikge1xuICBcdFx0XHRvYmoucmVtb3ZlTGF5ZXIodGhpcyk7XG4gIFx0XHR9XG4gIFx0XHRyZXR1cm4gdGhpcztcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBnZXRQYW5lKG5hbWU/IDogU3RyaW5nKTogSFRNTEVsZW1lbnRcbiAgXHQvLyBSZXR1cm5zIHRoZSBgSFRNTEVsZW1lbnRgIHJlcHJlc2VudGluZyB0aGUgbmFtZWQgcGFuZSBvbiB0aGUgbWFwLiBJZiBgbmFtZWAgaXMgb21pdHRlZCwgcmV0dXJucyB0aGUgcGFuZSBmb3IgdGhpcyBsYXllci5cbiAgXHRnZXRQYW5lOiBmdW5jdGlvbiAobmFtZSkge1xuICBcdFx0cmV0dXJuIHRoaXMuX21hcC5nZXRQYW5lKG5hbWUgPyAodGhpcy5vcHRpb25zW25hbWVdIHx8IG5hbWUpIDogdGhpcy5vcHRpb25zLnBhbmUpO1xuICBcdH0sXG5cbiAgXHRhZGRJbnRlcmFjdGl2ZVRhcmdldDogZnVuY3Rpb24gKHRhcmdldEVsKSB7XG4gIFx0XHR0aGlzLl9tYXAuX3RhcmdldHNbc3RhbXAodGFyZ2V0RWwpXSA9IHRoaXM7XG4gIFx0XHRyZXR1cm4gdGhpcztcbiAgXHR9LFxuXG4gIFx0cmVtb3ZlSW50ZXJhY3RpdmVUYXJnZXQ6IGZ1bmN0aW9uICh0YXJnZXRFbCkge1xuICBcdFx0ZGVsZXRlIHRoaXMuX21hcC5fdGFyZ2V0c1tzdGFtcCh0YXJnZXRFbCldO1xuICBcdFx0cmV0dXJuIHRoaXM7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgZ2V0QXR0cmlidXRpb246IFN0cmluZ1xuICBcdC8vIFVzZWQgYnkgdGhlIGBhdHRyaWJ1dGlvbiBjb250cm9sYCwgcmV0dXJucyB0aGUgW2F0dHJpYnV0aW9uIG9wdGlvbl0oI2dyaWRsYXllci1hdHRyaWJ1dGlvbikuXG4gIFx0Z2V0QXR0cmlidXRpb246IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHJldHVybiB0aGlzLm9wdGlvbnMuYXR0cmlidXRpb247XG4gIFx0fSxcblxuICBcdF9sYXllckFkZDogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdHZhciBtYXAgPSBlLnRhcmdldDtcblxuICBcdFx0Ly8gY2hlY2sgaW4gY2FzZSBsYXllciBnZXRzIGFkZGVkIGFuZCB0aGVuIHJlbW92ZWQgYmVmb3JlIHRoZSBtYXAgaXMgcmVhZHlcbiAgXHRcdGlmICghbWFwLmhhc0xheWVyKHRoaXMpKSB7IHJldHVybjsgfVxuXG4gIFx0XHR0aGlzLl9tYXAgPSBtYXA7XG4gIFx0XHR0aGlzLl96b29tQW5pbWF0ZWQgPSBtYXAuX3pvb21BbmltYXRlZDtcblxuICBcdFx0aWYgKHRoaXMuZ2V0RXZlbnRzKSB7XG4gIFx0XHRcdHZhciBldmVudHMgPSB0aGlzLmdldEV2ZW50cygpO1xuICBcdFx0XHRtYXAub24oZXZlbnRzLCB0aGlzKTtcbiAgXHRcdFx0dGhpcy5vbmNlKCdyZW1vdmUnLCBmdW5jdGlvbiAoKSB7XG4gIFx0XHRcdFx0bWFwLm9mZihldmVudHMsIHRoaXMpO1xuICBcdFx0XHR9LCB0aGlzKTtcbiAgXHRcdH1cblxuICBcdFx0dGhpcy5vbkFkZChtYXApO1xuXG4gIFx0XHR0aGlzLmZpcmUoJ2FkZCcpO1xuICBcdFx0bWFwLmZpcmUoJ2xheWVyYWRkJywge2xheWVyOiB0aGlzfSk7XG4gIFx0fVxuICB9KTtcblxuICAvKiBAc2VjdGlvbiBFeHRlbnNpb24gbWV0aG9kc1xuICAgKiBAdW5pbmhlcml0YWJsZVxuICAgKlxuICAgKiBFdmVyeSBsYXllciBzaG91bGQgZXh0ZW5kIGZyb20gYEwuTGF5ZXJgIGFuZCAocmUtKWltcGxlbWVudCB0aGUgZm9sbG93aW5nIG1ldGhvZHMuXG4gICAqXG4gICAqIEBtZXRob2Qgb25BZGQobWFwOiBNYXApOiB0aGlzXG4gICAqIFNob3VsZCBjb250YWluIGNvZGUgdGhhdCBjcmVhdGVzIERPTSBlbGVtZW50cyBmb3IgdGhlIGxheWVyLCBhZGRzIHRoZW0gdG8gYG1hcCBwYW5lc2Agd2hlcmUgdGhleSBzaG91bGQgYmVsb25nIGFuZCBwdXRzIGxpc3RlbmVycyBvbiByZWxldmFudCBtYXAgZXZlbnRzLiBDYWxsZWQgb24gW2BtYXAuYWRkTGF5ZXIobGF5ZXIpYF0oI21hcC1hZGRsYXllcikuXG4gICAqXG4gICAqIEBtZXRob2Qgb25SZW1vdmUobWFwOiBNYXApOiB0aGlzXG4gICAqIFNob3VsZCBjb250YWluIGFsbCBjbGVhbiB1cCBjb2RlIHRoYXQgcmVtb3ZlcyB0aGUgbGF5ZXIncyBlbGVtZW50cyBmcm9tIHRoZSBET00gYW5kIHJlbW92ZXMgbGlzdGVuZXJzIHByZXZpb3VzbHkgYWRkZWQgaW4gW2BvbkFkZGBdKCNsYXllci1vbmFkZCkuIENhbGxlZCBvbiBbYG1hcC5yZW1vdmVMYXllcihsYXllcilgXSgjbWFwLXJlbW92ZWxheWVyKS5cbiAgICpcbiAgICogQG1ldGhvZCBnZXRFdmVudHMoKTogT2JqZWN0XG4gICAqIFRoaXMgb3B0aW9uYWwgbWV0aG9kIHNob3VsZCByZXR1cm4gYW4gb2JqZWN0IGxpa2UgYHsgdmlld3Jlc2V0OiB0aGlzLl9yZXNldCB9YCBmb3IgW2BhZGRFdmVudExpc3RlbmVyYF0oI2V2ZW50ZWQtYWRkZXZlbnRsaXN0ZW5lcikuIFRoZSBldmVudCBoYW5kbGVycyBpbiB0aGlzIG9iamVjdCB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgYWRkZWQgYW5kIHJlbW92ZWQgZnJvbSB0aGUgbWFwIHdpdGggeW91ciBsYXllci5cbiAgICpcbiAgICogQG1ldGhvZCBnZXRBdHRyaWJ1dGlvbigpOiBTdHJpbmdcbiAgICogVGhpcyBvcHRpb25hbCBtZXRob2Qgc2hvdWxkIHJldHVybiBhIHN0cmluZyBjb250YWluaW5nIEhUTUwgdG8gYmUgc2hvd24gb24gdGhlIGBBdHRyaWJ1dGlvbiBjb250cm9sYCB3aGVuZXZlciB0aGUgbGF5ZXIgaXMgdmlzaWJsZS5cbiAgICpcbiAgICogQG1ldGhvZCBiZWZvcmVBZGQobWFwOiBNYXApOiB0aGlzXG4gICAqIE9wdGlvbmFsIG1ldGhvZC4gQ2FsbGVkIG9uIFtgbWFwLmFkZExheWVyKGxheWVyKWBdKCNtYXAtYWRkbGF5ZXIpLCBiZWZvcmUgdGhlIGxheWVyIGlzIGFkZGVkIHRvIHRoZSBtYXAsIGJlZm9yZSBldmVudHMgYXJlIGluaXRpYWxpemVkLCB3aXRob3V0IHdhaXRpbmcgdW50aWwgdGhlIG1hcCBpcyBpbiBhIHVzYWJsZSBzdGF0ZS4gVXNlIGZvciBlYXJseSBpbml0aWFsaXphdGlvbiBvbmx5LlxuICAgKi9cblxuXG4gIC8qIEBuYW1lc3BhY2UgTWFwXG4gICAqIEBzZWN0aW9uIExheWVyIGV2ZW50c1xuICAgKlxuICAgKiBAZXZlbnQgbGF5ZXJhZGQ6IExheWVyRXZlbnRcbiAgICogRmlyZWQgd2hlbiBhIG5ldyBsYXllciBpcyBhZGRlZCB0byB0aGUgbWFwLlxuICAgKlxuICAgKiBAZXZlbnQgbGF5ZXJyZW1vdmU6IExheWVyRXZlbnRcbiAgICogRmlyZWQgd2hlbiBzb21lIGxheWVyIGlzIHJlbW92ZWQgZnJvbSB0aGUgbWFwXG4gICAqXG4gICAqIEBzZWN0aW9uIE1ldGhvZHMgZm9yIExheWVycyBhbmQgQ29udHJvbHNcbiAgICovXG4gIE1hcC5pbmNsdWRlKHtcbiAgXHQvLyBAbWV0aG9kIGFkZExheWVyKGxheWVyOiBMYXllcik6IHRoaXNcbiAgXHQvLyBBZGRzIHRoZSBnaXZlbiBsYXllciB0byB0aGUgbWFwXG4gIFx0YWRkTGF5ZXI6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0aWYgKCFsYXllci5fbGF5ZXJBZGQpIHtcbiAgXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdUaGUgcHJvdmlkZWQgb2JqZWN0IGlzIG5vdCBhIExheWVyLicpO1xuICBcdFx0fVxuXG4gIFx0XHR2YXIgaWQgPSBzdGFtcChsYXllcik7XG4gIFx0XHRpZiAodGhpcy5fbGF5ZXJzW2lkXSkgeyByZXR1cm4gdGhpczsgfVxuICBcdFx0dGhpcy5fbGF5ZXJzW2lkXSA9IGxheWVyO1xuXG4gIFx0XHRsYXllci5fbWFwVG9BZGQgPSB0aGlzO1xuXG4gIFx0XHRpZiAobGF5ZXIuYmVmb3JlQWRkKSB7XG4gIFx0XHRcdGxheWVyLmJlZm9yZUFkZCh0aGlzKTtcbiAgXHRcdH1cblxuICBcdFx0dGhpcy53aGVuUmVhZHkobGF5ZXIuX2xheWVyQWRkLCBsYXllcik7XG5cbiAgXHRcdHJldHVybiB0aGlzO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIHJlbW92ZUxheWVyKGxheWVyOiBMYXllcik6IHRoaXNcbiAgXHQvLyBSZW1vdmVzIHRoZSBnaXZlbiBsYXllciBmcm9tIHRoZSBtYXAuXG4gIFx0cmVtb3ZlTGF5ZXI6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0dmFyIGlkID0gc3RhbXAobGF5ZXIpO1xuXG4gIFx0XHRpZiAoIXRoaXMuX2xheWVyc1tpZF0pIHsgcmV0dXJuIHRoaXM7IH1cblxuICBcdFx0aWYgKHRoaXMuX2xvYWRlZCkge1xuICBcdFx0XHRsYXllci5vblJlbW92ZSh0aGlzKTtcbiAgXHRcdH1cblxuICBcdFx0ZGVsZXRlIHRoaXMuX2xheWVyc1tpZF07XG5cbiAgXHRcdGlmICh0aGlzLl9sb2FkZWQpIHtcbiAgXHRcdFx0dGhpcy5maXJlKCdsYXllcnJlbW92ZScsIHtsYXllcjogbGF5ZXJ9KTtcbiAgXHRcdFx0bGF5ZXIuZmlyZSgncmVtb3ZlJyk7XG4gIFx0XHR9XG5cbiAgXHRcdGxheWVyLl9tYXAgPSBsYXllci5fbWFwVG9BZGQgPSBudWxsO1xuXG4gIFx0XHRyZXR1cm4gdGhpcztcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBoYXNMYXllcihsYXllcjogTGF5ZXIpOiBCb29sZWFuXG4gIFx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGdpdmVuIGxheWVyIGlzIGN1cnJlbnRseSBhZGRlZCB0byB0aGUgbWFwXG4gIFx0aGFzTGF5ZXI6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0cmV0dXJuIHN0YW1wKGxheWVyKSBpbiB0aGlzLl9sYXllcnM7XG4gIFx0fSxcblxuICBcdC8qIEBtZXRob2QgZWFjaExheWVyKGZuOiBGdW5jdGlvbiwgY29udGV4dD86IE9iamVjdCk6IHRoaXNcbiAgXHQgKiBJdGVyYXRlcyBvdmVyIHRoZSBsYXllcnMgb2YgdGhlIG1hcCwgb3B0aW9uYWxseSBzcGVjaWZ5aW5nIGNvbnRleHQgb2YgdGhlIGl0ZXJhdG9yIGZ1bmN0aW9uLlxuICBcdCAqIGBgYFxuICBcdCAqIG1hcC5lYWNoTGF5ZXIoZnVuY3Rpb24obGF5ZXIpe1xuICBcdCAqICAgICBsYXllci5iaW5kUG9wdXAoJ0hlbGxvJyk7XG4gIFx0ICogfSk7XG4gIFx0ICogYGBgXG4gIFx0ICovXG4gIFx0ZWFjaExheWVyOiBmdW5jdGlvbiAobWV0aG9kLCBjb250ZXh0KSB7XG4gIFx0XHRmb3IgKHZhciBpIGluIHRoaXMuX2xheWVycykge1xuICBcdFx0XHRtZXRob2QuY2FsbChjb250ZXh0LCB0aGlzLl9sYXllcnNbaV0pO1xuICBcdFx0fVxuICBcdFx0cmV0dXJuIHRoaXM7XG4gIFx0fSxcblxuICBcdF9hZGRMYXllcnM6IGZ1bmN0aW9uIChsYXllcnMpIHtcbiAgXHRcdGxheWVycyA9IGxheWVycyA/IChpc0FycmF5KGxheWVycykgPyBsYXllcnMgOiBbbGF5ZXJzXSkgOiBbXTtcblxuICBcdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IGxheWVycy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICBcdFx0XHR0aGlzLmFkZExheWVyKGxheWVyc1tpXSk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF9hZGRab29tTGltaXQ6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0aWYgKCFpc05hTihsYXllci5vcHRpb25zLm1heFpvb20pIHx8ICFpc05hTihsYXllci5vcHRpb25zLm1pblpvb20pKSB7XG4gIFx0XHRcdHRoaXMuX3pvb21Cb3VuZExheWVyc1tzdGFtcChsYXllcildID0gbGF5ZXI7XG4gIFx0XHRcdHRoaXMuX3VwZGF0ZVpvb21MZXZlbHMoKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3JlbW92ZVpvb21MaW1pdDogZnVuY3Rpb24gKGxheWVyKSB7XG4gIFx0XHR2YXIgaWQgPSBzdGFtcChsYXllcik7XG5cbiAgXHRcdGlmICh0aGlzLl96b29tQm91bmRMYXllcnNbaWRdKSB7XG4gIFx0XHRcdGRlbGV0ZSB0aGlzLl96b29tQm91bmRMYXllcnNbaWRdO1xuICBcdFx0XHR0aGlzLl91cGRhdGVab29tTGV2ZWxzKCk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF91cGRhdGVab29tTGV2ZWxzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR2YXIgbWluWm9vbSA9IEluZmluaXR5LFxuICBcdFx0ICAgIG1heFpvb20gPSAtSW5maW5pdHksXG4gIFx0XHQgICAgb2xkWm9vbVNwYW4gPSB0aGlzLl9nZXRab29tU3BhbigpO1xuXG4gIFx0XHRmb3IgKHZhciBpIGluIHRoaXMuX3pvb21Cb3VuZExheWVycykge1xuICBcdFx0XHR2YXIgb3B0aW9ucyA9IHRoaXMuX3pvb21Cb3VuZExheWVyc1tpXS5vcHRpb25zO1xuXG4gIFx0XHRcdG1pblpvb20gPSBvcHRpb25zLm1pblpvb20gPT09IHVuZGVmaW5lZCA/IG1pblpvb20gOiBNYXRoLm1pbihtaW5ab29tLCBvcHRpb25zLm1pblpvb20pO1xuICBcdFx0XHRtYXhab29tID0gb3B0aW9ucy5tYXhab29tID09PSB1bmRlZmluZWQgPyBtYXhab29tIDogTWF0aC5tYXgobWF4Wm9vbSwgb3B0aW9ucy5tYXhab29tKTtcbiAgXHRcdH1cblxuICBcdFx0dGhpcy5fbGF5ZXJzTWF4Wm9vbSA9IG1heFpvb20gPT09IC1JbmZpbml0eSA/IHVuZGVmaW5lZCA6IG1heFpvb207XG4gIFx0XHR0aGlzLl9sYXllcnNNaW5ab29tID0gbWluWm9vbSA9PT0gSW5maW5pdHkgPyB1bmRlZmluZWQgOiBtaW5ab29tO1xuXG4gIFx0XHQvLyBAc2VjdGlvbiBNYXAgc3RhdGUgY2hhbmdlIGV2ZW50c1xuICBcdFx0Ly8gQGV2ZW50IHpvb21sZXZlbHNjaGFuZ2U6IEV2ZW50XG4gIFx0XHQvLyBGaXJlZCB3aGVuIHRoZSBudW1iZXIgb2Ygem9vbWxldmVscyBvbiB0aGUgbWFwIGlzIGNoYW5nZWQgZHVlXG4gIFx0XHQvLyB0byBhZGRpbmcgb3IgcmVtb3ZpbmcgYSBsYXllci5cbiAgXHRcdGlmIChvbGRab29tU3BhbiAhPT0gdGhpcy5fZ2V0Wm9vbVNwYW4oKSkge1xuICBcdFx0XHR0aGlzLmZpcmUoJ3pvb21sZXZlbHNjaGFuZ2UnKTtcbiAgXHRcdH1cblxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5tYXhab29tID09PSB1bmRlZmluZWQgJiYgdGhpcy5fbGF5ZXJzTWF4Wm9vbSAmJiB0aGlzLmdldFpvb20oKSA+IHRoaXMuX2xheWVyc01heFpvb20pIHtcbiAgXHRcdFx0dGhpcy5zZXRab29tKHRoaXMuX2xheWVyc01heFpvb20pO1xuICBcdFx0fVxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5taW5ab29tID09PSB1bmRlZmluZWQgJiYgdGhpcy5fbGF5ZXJzTWluWm9vbSAmJiB0aGlzLmdldFpvb20oKSA8IHRoaXMuX2xheWVyc01pblpvb20pIHtcbiAgXHRcdFx0dGhpcy5zZXRab29tKHRoaXMuX2xheWVyc01pblpvb20pO1xuICBcdFx0fVxuICBcdH1cbiAgfSk7XG5cbiAgLypcclxuICAgKiBAY2xhc3MgTGF5ZXJHcm91cFxyXG4gICAqIEBha2EgTC5MYXllckdyb3VwXHJcbiAgICogQGluaGVyaXRzIEludGVyYWN0aXZlIGxheWVyXHJcbiAgICpcclxuICAgKiBVc2VkIHRvIGdyb3VwIHNldmVyYWwgbGF5ZXJzIGFuZCBoYW5kbGUgdGhlbSBhcyBvbmUuIElmIHlvdSBhZGQgaXQgdG8gdGhlIG1hcCxcclxuICAgKiBhbnkgbGF5ZXJzIGFkZGVkIG9yIHJlbW92ZWQgZnJvbSB0aGUgZ3JvdXAgd2lsbCBiZSBhZGRlZC9yZW1vdmVkIG9uIHRoZSBtYXAgYXNcclxuICAgKiB3ZWxsLiBFeHRlbmRzIGBMYXllcmAuXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiBMLmxheWVyR3JvdXAoW21hcmtlcjEsIG1hcmtlcjJdKVxyXG4gICAqIFx0LmFkZExheWVyKHBvbHlsaW5lKVxyXG4gICAqIFx0LmFkZFRvKG1hcCk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcblxyXG4gIHZhciBMYXllckdyb3VwID0gTGF5ZXIuZXh0ZW5kKHtcclxuXHJcbiAgXHRpbml0aWFsaXplOiBmdW5jdGlvbiAobGF5ZXJzLCBvcHRpb25zKSB7XHJcbiAgXHRcdHNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XHJcblxyXG4gIFx0XHR0aGlzLl9sYXllcnMgPSB7fTtcclxuXHJcbiAgXHRcdHZhciBpLCBsZW47XHJcblxyXG4gIFx0XHRpZiAobGF5ZXJzKSB7XHJcbiAgXHRcdFx0Zm9yIChpID0gMCwgbGVuID0gbGF5ZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdFx0XHR0aGlzLmFkZExheWVyKGxheWVyc1tpXSk7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgYWRkTGF5ZXIobGF5ZXI6IExheWVyKTogdGhpc1xyXG4gIFx0Ly8gQWRkcyB0aGUgZ2l2ZW4gbGF5ZXIgdG8gdGhlIGdyb3VwLlxyXG4gIFx0YWRkTGF5ZXI6IGZ1bmN0aW9uIChsYXllcikge1xyXG4gIFx0XHR2YXIgaWQgPSB0aGlzLmdldExheWVySWQobGF5ZXIpO1xyXG5cclxuICBcdFx0dGhpcy5fbGF5ZXJzW2lkXSA9IGxheWVyO1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX21hcCkge1xyXG4gIFx0XHRcdHRoaXMuX21hcC5hZGRMYXllcihsYXllcik7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHJlbW92ZUxheWVyKGxheWVyOiBMYXllcik6IHRoaXNcclxuICBcdC8vIFJlbW92ZXMgdGhlIGdpdmVuIGxheWVyIGZyb20gdGhlIGdyb3VwLlxyXG4gIFx0Ly8gQGFsdGVybmF0aXZlXHJcbiAgXHQvLyBAbWV0aG9kIHJlbW92ZUxheWVyKGlkOiBOdW1iZXIpOiB0aGlzXHJcbiAgXHQvLyBSZW1vdmVzIHRoZSBsYXllciB3aXRoIHRoZSBnaXZlbiBpbnRlcm5hbCBJRCBmcm9tIHRoZSBncm91cC5cclxuICBcdHJlbW92ZUxheWVyOiBmdW5jdGlvbiAobGF5ZXIpIHtcclxuICBcdFx0dmFyIGlkID0gbGF5ZXIgaW4gdGhpcy5fbGF5ZXJzID8gbGF5ZXIgOiB0aGlzLmdldExheWVySWQobGF5ZXIpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX21hcCAmJiB0aGlzLl9sYXllcnNbaWRdKSB7XHJcbiAgXHRcdFx0dGhpcy5fbWFwLnJlbW92ZUxheWVyKHRoaXMuX2xheWVyc1tpZF0pO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRkZWxldGUgdGhpcy5fbGF5ZXJzW2lkXTtcclxuXHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGhhc0xheWVyKGxheWVyOiBMYXllcik6IEJvb2xlYW5cclxuICBcdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSBnaXZlbiBsYXllciBpcyBjdXJyZW50bHkgYWRkZWQgdG8gdGhlIGdyb3VwLlxyXG4gIFx0Ly8gQGFsdGVybmF0aXZlXHJcbiAgXHQvLyBAbWV0aG9kIGhhc0xheWVyKGlkOiBOdW1iZXIpOiBCb29sZWFuXHJcbiAgXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZ2l2ZW4gaW50ZXJuYWwgSUQgaXMgY3VycmVudGx5IGFkZGVkIHRvIHRoZSBncm91cC5cclxuICBcdGhhc0xheWVyOiBmdW5jdGlvbiAobGF5ZXIpIHtcclxuICBcdFx0dmFyIGxheWVySWQgPSB0eXBlb2YgbGF5ZXIgPT09ICdudW1iZXInID8gbGF5ZXIgOiB0aGlzLmdldExheWVySWQobGF5ZXIpO1xyXG4gIFx0XHRyZXR1cm4gbGF5ZXJJZCBpbiB0aGlzLl9sYXllcnM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgY2xlYXJMYXllcnMoKTogdGhpc1xyXG4gIFx0Ly8gUmVtb3ZlcyBhbGwgdGhlIGxheWVycyBmcm9tIHRoZSBncm91cC5cclxuICBcdGNsZWFyTGF5ZXJzOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLmVhY2hMYXllcih0aGlzLnJlbW92ZUxheWVyLCB0aGlzKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBpbnZva2UobWV0aG9kTmFtZTogU3RyaW5nLCDigKYpOiB0aGlzXHJcbiAgXHQvLyBDYWxscyBgbWV0aG9kTmFtZWAgb24gZXZlcnkgbGF5ZXIgY29udGFpbmVkIGluIHRoaXMgZ3JvdXAsIHBhc3NpbmcgYW55XHJcbiAgXHQvLyBhZGRpdGlvbmFsIHBhcmFtZXRlcnMuIEhhcyBubyBlZmZlY3QgaWYgdGhlIGxheWVycyBjb250YWluZWQgZG8gbm90XHJcbiAgXHQvLyBpbXBsZW1lbnQgYG1ldGhvZE5hbWVgLlxyXG4gIFx0aW52b2tlOiBmdW5jdGlvbiAobWV0aG9kTmFtZSkge1xyXG4gIFx0XHR2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSksXHJcbiAgXHRcdCAgICBpLCBsYXllcjtcclxuXHJcbiAgXHRcdGZvciAoaSBpbiB0aGlzLl9sYXllcnMpIHtcclxuICBcdFx0XHRsYXllciA9IHRoaXMuX2xheWVyc1tpXTtcclxuXHJcbiAgXHRcdFx0aWYgKGxheWVyW21ldGhvZE5hbWVdKSB7XHJcbiAgXHRcdFx0XHRsYXllclttZXRob2ROYW1lXS5hcHBseShsYXllciwgYXJncyk7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0b25BZGQ6IGZ1bmN0aW9uIChtYXApIHtcclxuICBcdFx0dGhpcy5lYWNoTGF5ZXIobWFwLmFkZExheWVyLCBtYXApO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRvblJlbW92ZTogZnVuY3Rpb24gKG1hcCkge1xyXG4gIFx0XHR0aGlzLmVhY2hMYXllcihtYXAucmVtb3ZlTGF5ZXIsIG1hcCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgZWFjaExheWVyKGZuOiBGdW5jdGlvbiwgY29udGV4dD86IE9iamVjdCk6IHRoaXNcclxuICBcdC8vIEl0ZXJhdGVzIG92ZXIgdGhlIGxheWVycyBvZiB0aGUgZ3JvdXAsIG9wdGlvbmFsbHkgc3BlY2lmeWluZyBjb250ZXh0IG9mIHRoZSBpdGVyYXRvciBmdW5jdGlvbi5cclxuICBcdC8vIGBgYGpzXHJcbiAgXHQvLyBncm91cC5lYWNoTGF5ZXIoZnVuY3Rpb24gKGxheWVyKSB7XHJcbiAgXHQvLyBcdGxheWVyLmJpbmRQb3B1cCgnSGVsbG8nKTtcclxuICBcdC8vIH0pO1xyXG4gIFx0Ly8gYGBgXHJcbiAgXHRlYWNoTGF5ZXI6IGZ1bmN0aW9uIChtZXRob2QsIGNvbnRleHQpIHtcclxuICBcdFx0Zm9yICh2YXIgaSBpbiB0aGlzLl9sYXllcnMpIHtcclxuICBcdFx0XHRtZXRob2QuY2FsbChjb250ZXh0LCB0aGlzLl9sYXllcnNbaV0pO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldExheWVyKGlkOiBOdW1iZXIpOiBMYXllclxyXG4gIFx0Ly8gUmV0dXJucyB0aGUgbGF5ZXIgd2l0aCB0aGUgZ2l2ZW4gaW50ZXJuYWwgSUQuXHJcbiAgXHRnZXRMYXllcjogZnVuY3Rpb24gKGlkKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLl9sYXllcnNbaWRdO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldExheWVycygpOiBMYXllcltdXHJcbiAgXHQvLyBSZXR1cm5zIGFuIGFycmF5IG9mIGFsbCB0aGUgbGF5ZXJzIGFkZGVkIHRvIHRoZSBncm91cC5cclxuICBcdGdldExheWVyczogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR2YXIgbGF5ZXJzID0gW107XHJcbiAgXHRcdHRoaXMuZWFjaExheWVyKGxheWVycy5wdXNoLCBsYXllcnMpO1xyXG4gIFx0XHRyZXR1cm4gbGF5ZXJzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNldFpJbmRleCh6SW5kZXg6IE51bWJlcik6IHRoaXNcclxuICBcdC8vIENhbGxzIGBzZXRaSW5kZXhgIG9uIGV2ZXJ5IGxheWVyIGNvbnRhaW5lZCBpbiB0aGlzIGdyb3VwLCBwYXNzaW5nIHRoZSB6LWluZGV4LlxyXG4gIFx0c2V0WkluZGV4OiBmdW5jdGlvbiAoekluZGV4KSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLmludm9rZSgnc2V0WkluZGV4JywgekluZGV4KTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRMYXllcklkKGxheWVyOiBMYXllcik6IE51bWJlclxyXG4gIFx0Ly8gUmV0dXJucyB0aGUgaW50ZXJuYWwgSUQgZm9yIGEgbGF5ZXJcclxuICBcdGdldExheWVySWQ6IGZ1bmN0aW9uIChsYXllcikge1xyXG4gIFx0XHRyZXR1cm4gc3RhbXAobGF5ZXIpO1xyXG4gIFx0fVxyXG4gIH0pO1xyXG5cclxuXHJcbiAgLy8gQGZhY3RvcnkgTC5sYXllckdyb3VwKGxheWVycz86IExheWVyW10sIG9wdGlvbnM/OiBPYmplY3QpXHJcbiAgLy8gQ3JlYXRlIGEgbGF5ZXIgZ3JvdXAsIG9wdGlvbmFsbHkgZ2l2ZW4gYW4gaW5pdGlhbCBzZXQgb2YgbGF5ZXJzIGFuZCBhbiBgb3B0aW9uc2Agb2JqZWN0LlxyXG4gIHZhciBsYXllckdyb3VwID0gZnVuY3Rpb24gKGxheWVycywgb3B0aW9ucykge1xyXG4gIFx0cmV0dXJuIG5ldyBMYXllckdyb3VwKGxheWVycywgb3B0aW9ucyk7XHJcbiAgfTtcblxuICAvKlxyXG4gICAqIEBjbGFzcyBGZWF0dXJlR3JvdXBcclxuICAgKiBAYWthIEwuRmVhdHVyZUdyb3VwXHJcbiAgICogQGluaGVyaXRzIExheWVyR3JvdXBcclxuICAgKlxyXG4gICAqIEV4dGVuZGVkIGBMYXllckdyb3VwYCB0aGF0IG1ha2VzIGl0IGVhc2llciB0byBkbyB0aGUgc2FtZSB0aGluZyB0byBhbGwgaXRzIG1lbWJlciBsYXllcnM6XHJcbiAgICogICogW2BiaW5kUG9wdXBgXSgjbGF5ZXItYmluZHBvcHVwKSBiaW5kcyBhIHBvcHVwIHRvIGFsbCBvZiB0aGUgbGF5ZXJzIGF0IG9uY2UgKGxpa2V3aXNlIHdpdGggW2BiaW5kVG9vbHRpcGBdKCNsYXllci1iaW5kdG9vbHRpcCkpXHJcbiAgICogICogRXZlbnRzIGFyZSBwcm9wYWdhdGVkIHRvIHRoZSBgRmVhdHVyZUdyb3VwYCwgc28gaWYgdGhlIGdyb3VwIGhhcyBhbiBldmVudFxyXG4gICAqIGhhbmRsZXIsIGl0IHdpbGwgaGFuZGxlIGV2ZW50cyBmcm9tIGFueSBvZiB0aGUgbGF5ZXJzLiBUaGlzIGluY2x1ZGVzIG1vdXNlIGV2ZW50c1xyXG4gICAqIGFuZCBjdXN0b20gZXZlbnRzLlxyXG4gICAqICAqIEhhcyBgbGF5ZXJhZGRgIGFuZCBgbGF5ZXJyZW1vdmVgIGV2ZW50c1xyXG4gICAqXHJcbiAgICogQGV4YW1wbGVcclxuICAgKlxyXG4gICAqIGBgYGpzXHJcbiAgICogTC5mZWF0dXJlR3JvdXAoW21hcmtlcjEsIG1hcmtlcjIsIHBvbHlsaW5lXSlcclxuICAgKiBcdC5iaW5kUG9wdXAoJ0hlbGxvIHdvcmxkIScpXHJcbiAgICogXHQub24oJ2NsaWNrJywgZnVuY3Rpb24oKSB7IGFsZXJ0KCdDbGlja2VkIG9uIGEgbWVtYmVyIG9mIHRoZSBncm91cCEnKTsgfSlcclxuICAgKiBcdC5hZGRUbyhtYXApO1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG5cclxuICB2YXIgRmVhdHVyZUdyb3VwID0gTGF5ZXJHcm91cC5leHRlbmQoe1xyXG5cclxuICBcdGFkZExheWVyOiBmdW5jdGlvbiAobGF5ZXIpIHtcclxuICBcdFx0aWYgKHRoaXMuaGFzTGF5ZXIobGF5ZXIpKSB7XHJcbiAgXHRcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGxheWVyLmFkZEV2ZW50UGFyZW50KHRoaXMpO1xyXG5cclxuICBcdFx0TGF5ZXJHcm91cC5wcm90b3R5cGUuYWRkTGF5ZXIuY2FsbCh0aGlzLCBsYXllcik7XHJcblxyXG4gIFx0XHQvLyBAZXZlbnQgbGF5ZXJhZGQ6IExheWVyRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiBhIGxheWVyIGlzIGFkZGVkIHRvIHRoaXMgYEZlYXR1cmVHcm91cGBcclxuICBcdFx0cmV0dXJuIHRoaXMuZmlyZSgnbGF5ZXJhZGQnLCB7bGF5ZXI6IGxheWVyfSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdHJlbW92ZUxheWVyOiBmdW5jdGlvbiAobGF5ZXIpIHtcclxuICBcdFx0aWYgKCF0aGlzLmhhc0xheWVyKGxheWVyKSkge1xyXG4gIFx0XHRcdHJldHVybiB0aGlzO1xyXG4gIFx0XHR9XHJcbiAgXHRcdGlmIChsYXllciBpbiB0aGlzLl9sYXllcnMpIHtcclxuICBcdFx0XHRsYXllciA9IHRoaXMuX2xheWVyc1tsYXllcl07XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGxheWVyLnJlbW92ZUV2ZW50UGFyZW50KHRoaXMpO1xyXG5cclxuICBcdFx0TGF5ZXJHcm91cC5wcm90b3R5cGUucmVtb3ZlTGF5ZXIuY2FsbCh0aGlzLCBsYXllcik7XHJcblxyXG4gIFx0XHQvLyBAZXZlbnQgbGF5ZXJyZW1vdmU6IExheWVyRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiBhIGxheWVyIGlzIHJlbW92ZWQgZnJvbSB0aGlzIGBGZWF0dXJlR3JvdXBgXHJcbiAgXHRcdHJldHVybiB0aGlzLmZpcmUoJ2xheWVycmVtb3ZlJywge2xheWVyOiBsYXllcn0pO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNldFN0eWxlKHN0eWxlOiBQYXRoIG9wdGlvbnMpOiB0aGlzXHJcbiAgXHQvLyBTZXRzIHRoZSBnaXZlbiBwYXRoIG9wdGlvbnMgdG8gZWFjaCBsYXllciBvZiB0aGUgZ3JvdXAgdGhhdCBoYXMgYSBgc2V0U3R5bGVgIG1ldGhvZC5cclxuICBcdHNldFN0eWxlOiBmdW5jdGlvbiAoc3R5bGUpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuaW52b2tlKCdzZXRTdHlsZScsIHN0eWxlKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBicmluZ1RvRnJvbnQoKTogdGhpc1xyXG4gIFx0Ly8gQnJpbmdzIHRoZSBsYXllciBncm91cCB0byB0aGUgdG9wIG9mIGFsbCBvdGhlciBsYXllcnNcclxuICBcdGJyaW5nVG9Gcm9udDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5pbnZva2UoJ2JyaW5nVG9Gcm9udCcpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGJyaW5nVG9CYWNrKCk6IHRoaXNcclxuICBcdC8vIEJyaW5ncyB0aGUgbGF5ZXIgZ3JvdXAgdG8gdGhlIGJhY2sgb2YgYWxsIG90aGVyIGxheWVyc1xyXG4gIFx0YnJpbmdUb0JhY2s6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuaW52b2tlKCdicmluZ1RvQmFjaycpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldEJvdW5kcygpOiBMYXRMbmdCb3VuZHNcclxuICBcdC8vIFJldHVybnMgdGhlIExhdExuZ0JvdW5kcyBvZiB0aGUgRmVhdHVyZSBHcm91cCAoY3JlYXRlZCBmcm9tIGJvdW5kcyBhbmQgY29vcmRpbmF0ZXMgb2YgaXRzIGNoaWxkcmVuKS5cclxuICBcdGdldEJvdW5kczogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR2YXIgYm91bmRzID0gbmV3IExhdExuZ0JvdW5kcygpO1xyXG5cclxuICBcdFx0Zm9yICh2YXIgaWQgaW4gdGhpcy5fbGF5ZXJzKSB7XHJcbiAgXHRcdFx0dmFyIGxheWVyID0gdGhpcy5fbGF5ZXJzW2lkXTtcclxuICBcdFx0XHRib3VuZHMuZXh0ZW5kKGxheWVyLmdldEJvdW5kcyA/IGxheWVyLmdldEJvdW5kcygpIDogbGF5ZXIuZ2V0TGF0TG5nKCkpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiBib3VuZHM7XHJcbiAgXHR9XHJcbiAgfSk7XHJcblxyXG4gIC8vIEBmYWN0b3J5IEwuZmVhdHVyZUdyb3VwKGxheWVycz86IExheWVyW10sIG9wdGlvbnM/OiBPYmplY3QpXHJcbiAgLy8gQ3JlYXRlIGEgZmVhdHVyZSBncm91cCwgb3B0aW9uYWxseSBnaXZlbiBhbiBpbml0aWFsIHNldCBvZiBsYXllcnMgYW5kIGFuIGBvcHRpb25zYCBvYmplY3QuXHJcbiAgdmFyIGZlYXR1cmVHcm91cCA9IGZ1bmN0aW9uIChsYXllcnMsIG9wdGlvbnMpIHtcclxuICBcdHJldHVybiBuZXcgRmVhdHVyZUdyb3VwKGxheWVycywgb3B0aW9ucyk7XHJcbiAgfTtcblxuICAvKlxyXG4gICAqIEBjbGFzcyBJY29uXHJcbiAgICogQGFrYSBMLkljb25cclxuICAgKlxyXG4gICAqIFJlcHJlc2VudHMgYW4gaWNvbiB0byBwcm92aWRlIHdoZW4gY3JlYXRpbmcgYSBtYXJrZXIuXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiB2YXIgbXlJY29uID0gTC5pY29uKHtcclxuICAgKiAgICAgaWNvblVybDogJ215LWljb24ucG5nJyxcclxuICAgKiAgICAgaWNvblJldGluYVVybDogJ215LWljb25AMngucG5nJyxcclxuICAgKiAgICAgaWNvblNpemU6IFszOCwgOTVdLFxyXG4gICAqICAgICBpY29uQW5jaG9yOiBbMjIsIDk0XSxcclxuICAgKiAgICAgcG9wdXBBbmNob3I6IFstMywgLTc2XSxcclxuICAgKiAgICAgc2hhZG93VXJsOiAnbXktaWNvbi1zaGFkb3cucG5nJyxcclxuICAgKiAgICAgc2hhZG93UmV0aW5hVXJsOiAnbXktaWNvbi1zaGFkb3dAMngucG5nJyxcclxuICAgKiAgICAgc2hhZG93U2l6ZTogWzY4LCA5NV0sXHJcbiAgICogICAgIHNoYWRvd0FuY2hvcjogWzIyLCA5NF1cclxuICAgKiB9KTtcclxuICAgKlxyXG4gICAqIEwubWFya2VyKFs1MC41MDUsIDMwLjU3XSwge2ljb246IG15SWNvbn0pLmFkZFRvKG1hcCk7XHJcbiAgICogYGBgXHJcbiAgICpcclxuICAgKiBgTC5JY29uLkRlZmF1bHRgIGV4dGVuZHMgYEwuSWNvbmAgYW5kIGlzIHRoZSBibHVlIGljb24gTGVhZmxldCB1c2VzIGZvciBtYXJrZXJzIGJ5IGRlZmF1bHQuXHJcbiAgICpcclxuICAgKi9cclxuXHJcbiAgdmFyIEljb24gPSBDbGFzcy5leHRlbmQoe1xyXG5cclxuICBcdC8qIEBzZWN0aW9uXHJcbiAgXHQgKiBAYWthIEljb24gb3B0aW9uc1xyXG4gIFx0ICpcclxuICBcdCAqIEBvcHRpb24gaWNvblVybDogU3RyaW5nID0gbnVsbFxyXG4gIFx0ICogKioocmVxdWlyZWQpKiogVGhlIFVSTCB0byB0aGUgaWNvbiBpbWFnZSAoYWJzb2x1dGUgb3IgcmVsYXRpdmUgdG8geW91ciBzY3JpcHQgcGF0aCkuXHJcbiAgXHQgKlxyXG4gIFx0ICogQG9wdGlvbiBpY29uUmV0aW5hVXJsOiBTdHJpbmcgPSBudWxsXHJcbiAgXHQgKiBUaGUgVVJMIHRvIGEgcmV0aW5hIHNpemVkIHZlcnNpb24gb2YgdGhlIGljb24gaW1hZ2UgKGFic29sdXRlIG9yIHJlbGF0aXZlIHRvIHlvdXJcclxuICBcdCAqIHNjcmlwdCBwYXRoKS4gVXNlZCBmb3IgUmV0aW5hIHNjcmVlbiBkZXZpY2VzLlxyXG4gIFx0ICpcclxuICBcdCAqIEBvcHRpb24gaWNvblNpemU6IFBvaW50ID0gbnVsbFxyXG4gIFx0ICogU2l6ZSBvZiB0aGUgaWNvbiBpbWFnZSBpbiBwaXhlbHMuXHJcbiAgXHQgKlxyXG4gIFx0ICogQG9wdGlvbiBpY29uQW5jaG9yOiBQb2ludCA9IG51bGxcclxuICBcdCAqIFRoZSBjb29yZGluYXRlcyBvZiB0aGUgXCJ0aXBcIiBvZiB0aGUgaWNvbiAocmVsYXRpdmUgdG8gaXRzIHRvcCBsZWZ0IGNvcm5lcikuIFRoZSBpY29uXHJcbiAgXHQgKiB3aWxsIGJlIGFsaWduZWQgc28gdGhhdCB0aGlzIHBvaW50IGlzIGF0IHRoZSBtYXJrZXIncyBnZW9ncmFwaGljYWwgbG9jYXRpb24uIENlbnRlcmVkXHJcbiAgXHQgKiBieSBkZWZhdWx0IGlmIHNpemUgaXMgc3BlY2lmaWVkLCBhbHNvIGNhbiBiZSBzZXQgaW4gQ1NTIHdpdGggbmVnYXRpdmUgbWFyZ2lucy5cclxuICBcdCAqXHJcbiAgXHQgKiBAb3B0aW9uIHBvcHVwQW5jaG9yOiBQb2ludCA9IFswLCAwXVxyXG4gIFx0ICogVGhlIGNvb3JkaW5hdGVzIG9mIHRoZSBwb2ludCBmcm9tIHdoaWNoIHBvcHVwcyB3aWxsIFwib3BlblwiLCByZWxhdGl2ZSB0byB0aGUgaWNvbiBhbmNob3IuXHJcbiAgXHQgKlxyXG4gIFx0ICogQG9wdGlvbiB0b29sdGlwQW5jaG9yOiBQb2ludCA9IFswLCAwXVxyXG4gIFx0ICogVGhlIGNvb3JkaW5hdGVzIG9mIHRoZSBwb2ludCBmcm9tIHdoaWNoIHRvb2x0aXBzIHdpbGwgXCJvcGVuXCIsIHJlbGF0aXZlIHRvIHRoZSBpY29uIGFuY2hvci5cclxuICBcdCAqXHJcbiAgXHQgKiBAb3B0aW9uIHNoYWRvd1VybDogU3RyaW5nID0gbnVsbFxyXG4gIFx0ICogVGhlIFVSTCB0byB0aGUgaWNvbiBzaGFkb3cgaW1hZ2UuIElmIG5vdCBzcGVjaWZpZWQsIG5vIHNoYWRvdyBpbWFnZSB3aWxsIGJlIGNyZWF0ZWQuXHJcbiAgXHQgKlxyXG4gIFx0ICogQG9wdGlvbiBzaGFkb3dSZXRpbmFVcmw6IFN0cmluZyA9IG51bGxcclxuICBcdCAqXHJcbiAgXHQgKiBAb3B0aW9uIHNoYWRvd1NpemU6IFBvaW50ID0gbnVsbFxyXG4gIFx0ICogU2l6ZSBvZiB0aGUgc2hhZG93IGltYWdlIGluIHBpeGVscy5cclxuICBcdCAqXHJcbiAgXHQgKiBAb3B0aW9uIHNoYWRvd0FuY2hvcjogUG9pbnQgPSBudWxsXHJcbiAgXHQgKiBUaGUgY29vcmRpbmF0ZXMgb2YgdGhlIFwidGlwXCIgb2YgdGhlIHNoYWRvdyAocmVsYXRpdmUgdG8gaXRzIHRvcCBsZWZ0IGNvcm5lcikgKHRoZSBzYW1lXHJcbiAgXHQgKiBhcyBpY29uQW5jaG9yIGlmIG5vdCBzcGVjaWZpZWQpLlxyXG4gIFx0ICpcclxuICBcdCAqIEBvcHRpb24gY2xhc3NOYW1lOiBTdHJpbmcgPSAnJ1xyXG4gIFx0ICogQSBjdXN0b20gY2xhc3MgbmFtZSB0byBhc3NpZ24gdG8gYm90aCBpY29uIGFuZCBzaGFkb3cgaW1hZ2VzLiBFbXB0eSBieSBkZWZhdWx0LlxyXG4gIFx0ICovXHJcblxyXG4gIFx0b3B0aW9uczoge1xyXG4gIFx0XHRwb3B1cEFuY2hvcjogWzAsIDBdLFxyXG4gIFx0XHR0b29sdGlwQW5jaG9yOiBbMCwgMF0sXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIGNyb3NzT3JpZ2luOiBCb29sZWFufFN0cmluZyA9IGZhbHNlXHJcbiAgXHRcdC8vIFdoZXRoZXIgdGhlIGNyb3NzT3JpZ2luIGF0dHJpYnV0ZSB3aWxsIGJlIGFkZGVkIHRvIHRoZSB0aWxlcy5cclxuICBcdFx0Ly8gSWYgYSBTdHJpbmcgaXMgcHJvdmlkZWQsIGFsbCB0aWxlcyB3aWxsIGhhdmUgdGhlaXIgY3Jvc3NPcmlnaW4gYXR0cmlidXRlIHNldCB0byB0aGUgU3RyaW5nIHByb3ZpZGVkLiBUaGlzIGlzIG5lZWRlZCBpZiB5b3Ugd2FudCB0byBhY2Nlc3MgdGlsZSBwaXhlbCBkYXRhLlxyXG4gIFx0XHQvLyBSZWZlciB0byBbQ09SUyBTZXR0aW5nc10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSFRNTC9DT1JTX3NldHRpbmdzX2F0dHJpYnV0ZXMpIGZvciB2YWxpZCBTdHJpbmcgdmFsdWVzLlxyXG4gIFx0XHRjcm9zc09yaWdpbjogZmFsc2VcclxuICBcdH0sXHJcblxyXG4gIFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuICBcdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBjcmVhdGVJY29uKG9sZEljb24/OiBIVE1MRWxlbWVudCk6IEhUTUxFbGVtZW50XHJcbiAgXHQvLyBDYWxsZWQgaW50ZXJuYWxseSB3aGVuIHRoZSBpY29uIGhhcyB0byBiZSBzaG93biwgcmV0dXJucyBhIGA8aW1nPmAgSFRNTCBlbGVtZW50XHJcbiAgXHQvLyBzdHlsZWQgYWNjb3JkaW5nIHRvIHRoZSBvcHRpb25zLlxyXG4gIFx0Y3JlYXRlSWNvbjogZnVuY3Rpb24gKG9sZEljb24pIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuX2NyZWF0ZUljb24oJ2ljb24nLCBvbGRJY29uKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBjcmVhdGVTaGFkb3cob2xkSWNvbj86IEhUTUxFbGVtZW50KTogSFRNTEVsZW1lbnRcclxuICBcdC8vIEFzIGBjcmVhdGVJY29uYCwgYnV0IGZvciB0aGUgc2hhZG93IGJlbmVhdGggaXQuXHJcbiAgXHRjcmVhdGVTaGFkb3c6IGZ1bmN0aW9uIChvbGRJY29uKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLl9jcmVhdGVJY29uKCdzaGFkb3cnLCBvbGRJY29uKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X2NyZWF0ZUljb246IGZ1bmN0aW9uIChuYW1lLCBvbGRJY29uKSB7XHJcbiAgXHRcdHZhciBzcmMgPSB0aGlzLl9nZXRJY29uVXJsKG5hbWUpO1xyXG5cclxuICBcdFx0aWYgKCFzcmMpIHtcclxuICBcdFx0XHRpZiAobmFtZSA9PT0gJ2ljb24nKSB7XHJcbiAgXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ2ljb25Vcmwgbm90IHNldCBpbiBJY29uIG9wdGlvbnMgKHNlZSB0aGUgZG9jcykuJyk7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHRcdHJldHVybiBudWxsO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgaW1nID0gdGhpcy5fY3JlYXRlSW1nKHNyYywgb2xkSWNvbiAmJiBvbGRJY29uLnRhZ05hbWUgPT09ICdJTUcnID8gb2xkSWNvbiA6IG51bGwpO1xyXG4gIFx0XHR0aGlzLl9zZXRJY29uU3R5bGVzKGltZywgbmFtZSk7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5vcHRpb25zLmNyb3NzT3JpZ2luIHx8IHRoaXMub3B0aW9ucy5jcm9zc09yaWdpbiA9PT0gJycpIHtcclxuICBcdFx0XHRpbWcuY3Jvc3NPcmlnaW4gPSB0aGlzLm9wdGlvbnMuY3Jvc3NPcmlnaW4gPT09IHRydWUgPyAnJyA6IHRoaXMub3B0aW9ucy5jcm9zc09yaWdpbjtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0cmV0dXJuIGltZztcclxuICBcdH0sXHJcblxyXG4gIFx0X3NldEljb25TdHlsZXM6IGZ1bmN0aW9uIChpbWcsIG5hbWUpIHtcclxuICBcdFx0dmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XHJcbiAgXHRcdHZhciBzaXplT3B0aW9uID0gb3B0aW9uc1tuYW1lICsgJ1NpemUnXTtcclxuXHJcbiAgXHRcdGlmICh0eXBlb2Ygc2l6ZU9wdGlvbiA9PT0gJ251bWJlcicpIHtcclxuICBcdFx0XHRzaXplT3B0aW9uID0gW3NpemVPcHRpb24sIHNpemVPcHRpb25dO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgc2l6ZSA9IHRvUG9pbnQoc2l6ZU9wdGlvbiksXHJcbiAgXHRcdCAgICBhbmNob3IgPSB0b1BvaW50KG5hbWUgPT09ICdzaGFkb3cnICYmIG9wdGlvbnMuc2hhZG93QW5jaG9yIHx8IG9wdGlvbnMuaWNvbkFuY2hvciB8fFxyXG4gIFx0XHQgICAgICAgICAgICBzaXplICYmIHNpemUuZGl2aWRlQnkoMiwgdHJ1ZSkpO1xyXG5cclxuICBcdFx0aW1nLmNsYXNzTmFtZSA9ICdsZWFmbGV0LW1hcmtlci0nICsgbmFtZSArICcgJyArIChvcHRpb25zLmNsYXNzTmFtZSB8fCAnJyk7XHJcblxyXG4gIFx0XHRpZiAoYW5jaG9yKSB7XHJcbiAgXHRcdFx0aW1nLnN0eWxlLm1hcmdpbkxlZnQgPSAoLWFuY2hvci54KSArICdweCc7XHJcbiAgXHRcdFx0aW1nLnN0eWxlLm1hcmdpblRvcCAgPSAoLWFuY2hvci55KSArICdweCc7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmIChzaXplKSB7XHJcbiAgXHRcdFx0aW1nLnN0eWxlLndpZHRoICA9IHNpemUueCArICdweCc7XHJcbiAgXHRcdFx0aW1nLnN0eWxlLmhlaWdodCA9IHNpemUueSArICdweCc7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0X2NyZWF0ZUltZzogZnVuY3Rpb24gKHNyYywgZWwpIHtcclxuICBcdFx0ZWwgPSBlbCB8fCBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTtcclxuICBcdFx0ZWwuc3JjID0gc3JjO1xyXG4gIFx0XHRyZXR1cm4gZWw7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9nZXRJY29uVXJsOiBmdW5jdGlvbiAobmFtZSkge1xyXG4gIFx0XHRyZXR1cm4gQnJvd3Nlci5yZXRpbmEgJiYgdGhpcy5vcHRpb25zW25hbWUgKyAnUmV0aW5hVXJsJ10gfHwgdGhpcy5vcHRpb25zW25hbWUgKyAnVXJsJ107XHJcbiAgXHR9XHJcbiAgfSk7XHJcblxyXG5cclxuICAvLyBAZmFjdG9yeSBMLmljb24ob3B0aW9uczogSWNvbiBvcHRpb25zKVxyXG4gIC8vIENyZWF0ZXMgYW4gaWNvbiBpbnN0YW5jZSB3aXRoIHRoZSBnaXZlbiBvcHRpb25zLlxyXG4gIGZ1bmN0aW9uIGljb24ob3B0aW9ucykge1xyXG4gIFx0cmV0dXJuIG5ldyBJY29uKG9wdGlvbnMpO1xyXG4gIH1cblxuICAvKlxuICAgKiBAbWluaWNsYXNzIEljb24uRGVmYXVsdCAoSWNvbilcbiAgICogQGFrYSBMLkljb24uRGVmYXVsdFxuICAgKiBAc2VjdGlvblxuICAgKlxuICAgKiBBIHRyaXZpYWwgc3ViY2xhc3Mgb2YgYEljb25gLCByZXByZXNlbnRzIHRoZSBpY29uIHRvIHVzZSBpbiBgTWFya2VyYHMgd2hlblxuICAgKiBubyBpY29uIGlzIHNwZWNpZmllZC4gUG9pbnRzIHRvIHRoZSBibHVlIG1hcmtlciBpbWFnZSBkaXN0cmlidXRlZCB3aXRoIExlYWZsZXRcbiAgICogcmVsZWFzZXMuXG4gICAqXG4gICAqIEluIG9yZGVyIHRvIGN1c3RvbWl6ZSB0aGUgZGVmYXVsdCBpY29uLCBqdXN0IGNoYW5nZSB0aGUgcHJvcGVydGllcyBvZiBgTC5JY29uLkRlZmF1bHQucHJvdG90eXBlLm9wdGlvbnNgXG4gICAqICh3aGljaCBpcyBhIHNldCBvZiBgSWNvbiBvcHRpb25zYCkuXG4gICAqXG4gICAqIElmIHlvdSB3YW50IHRvIF9jb21wbGV0ZWx5XyByZXBsYWNlIHRoZSBkZWZhdWx0IGljb24sIG92ZXJyaWRlIHRoZVxuICAgKiBgTC5NYXJrZXIucHJvdG90eXBlLm9wdGlvbnMuaWNvbmAgd2l0aCB5b3VyIG93biBpY29uIGluc3RlYWQuXG4gICAqL1xuXG4gIHZhciBJY29uRGVmYXVsdCA9IEljb24uZXh0ZW5kKHtcblxuICBcdG9wdGlvbnM6IHtcbiAgXHRcdGljb25Vcmw6ICAgICAgICdtYXJrZXItaWNvbi5wbmcnLFxuICBcdFx0aWNvblJldGluYVVybDogJ21hcmtlci1pY29uLTJ4LnBuZycsXG4gIFx0XHRzaGFkb3dVcmw6ICAgICAnbWFya2VyLXNoYWRvdy5wbmcnLFxuICBcdFx0aWNvblNpemU6ICAgIFsyNSwgNDFdLFxuICBcdFx0aWNvbkFuY2hvcjogIFsxMiwgNDFdLFxuICBcdFx0cG9wdXBBbmNob3I6IFsxLCAtMzRdLFxuICBcdFx0dG9vbHRpcEFuY2hvcjogWzE2LCAtMjhdLFxuICBcdFx0c2hhZG93U2l6ZTogIFs0MSwgNDFdXG4gIFx0fSxcblxuICBcdF9nZXRJY29uVXJsOiBmdW5jdGlvbiAobmFtZSkge1xuICBcdFx0aWYgKHR5cGVvZiBJY29uRGVmYXVsdC5pbWFnZVBhdGggIT09ICdzdHJpbmcnKSB7XHQvLyBEZXByZWNhdGVkLCBiYWNrd2FyZHMtY29tcGF0aWJpbGl0eSBvbmx5XG4gIFx0XHRcdEljb25EZWZhdWx0LmltYWdlUGF0aCA9IHRoaXMuX2RldGVjdEljb25QYXRoKCk7XG4gIFx0XHR9XG5cbiAgXHRcdC8vIEBvcHRpb24gaW1hZ2VQYXRoOiBTdHJpbmdcbiAgXHRcdC8vIGBJY29uLkRlZmF1bHRgIHdpbGwgdHJ5IHRvIGF1dG8tZGV0ZWN0IHRoZSBsb2NhdGlvbiBvZiB0aGVcbiAgXHRcdC8vIGJsdWUgaWNvbiBpbWFnZXMuIElmIHlvdSBhcmUgcGxhY2luZyB0aGVzZSBpbWFnZXMgaW4gYSBub24tc3RhbmRhcmRcbiAgXHRcdC8vIHdheSwgc2V0IHRoaXMgb3B0aW9uIHRvIHBvaW50IHRvIHRoZSByaWdodCBwYXRoLlxuICBcdFx0cmV0dXJuICh0aGlzLm9wdGlvbnMuaW1hZ2VQYXRoIHx8IEljb25EZWZhdWx0LmltYWdlUGF0aCkgKyBJY29uLnByb3RvdHlwZS5fZ2V0SWNvblVybC5jYWxsKHRoaXMsIG5hbWUpO1xuICBcdH0sXG5cbiAgXHRfc3RyaXBVcmw6IGZ1bmN0aW9uIChwYXRoKSB7XHQvLyBzZXBhcmF0ZSBmdW5jdGlvbiB0byB1c2UgaW4gdGVzdHNcbiAgXHRcdHZhciBzdHJpcCA9IGZ1bmN0aW9uIChzdHIsIHJlLCBpZHgpIHtcbiAgXHRcdFx0dmFyIG1hdGNoID0gcmUuZXhlYyhzdHIpO1xuICBcdFx0XHRyZXR1cm4gbWF0Y2ggJiYgbWF0Y2hbaWR4XTtcbiAgXHRcdH07XG4gIFx0XHRwYXRoID0gc3RyaXAocGF0aCwgL151cmxcXCgoWydcIl0pPyguKylcXDFcXCkkLywgMik7XG4gIFx0XHRyZXR1cm4gcGF0aCAmJiBzdHJpcChwYXRoLCAvXiguKiltYXJrZXItaWNvblxcLnBuZyQvLCAxKTtcbiAgXHR9LFxuXG4gIFx0X2RldGVjdEljb25QYXRoOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR2YXIgZWwgPSBjcmVhdGUkMSgnZGl2JywgICdsZWFmbGV0LWRlZmF1bHQtaWNvbi1wYXRoJywgZG9jdW1lbnQuYm9keSk7XG4gIFx0XHR2YXIgcGF0aCA9IGdldFN0eWxlKGVsLCAnYmFja2dyb3VuZC1pbWFnZScpIHx8XG4gIFx0XHQgICAgICAgICAgIGdldFN0eWxlKGVsLCAnYmFja2dyb3VuZEltYWdlJyk7XHQvLyBJRThcblxuICBcdFx0ZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChlbCk7XG4gIFx0XHRwYXRoID0gdGhpcy5fc3RyaXBVcmwocGF0aCk7XG4gIFx0XHRpZiAocGF0aCkgeyByZXR1cm4gcGF0aDsgfVxuICBcdFx0dmFyIGxpbmsgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdsaW5rW2hyZWYkPVwibGVhZmxldC5jc3NcIl0nKTtcbiAgXHRcdGlmICghbGluaykgeyByZXR1cm4gJyc7IH1cbiAgXHRcdHJldHVybiBsaW5rLmhyZWYuc3Vic3RyaW5nKDAsIGxpbmsuaHJlZi5sZW5ndGggLSAnbGVhZmxldC5jc3MnLmxlbmd0aCAtIDEpO1xuICBcdH1cbiAgfSk7XG5cbiAgLypcbiAgICogTC5IYW5kbGVyLk1hcmtlckRyYWcgaXMgdXNlZCBpbnRlcm5hbGx5IGJ5IEwuTWFya2VyIHRvIG1ha2UgdGhlIG1hcmtlcnMgZHJhZ2dhYmxlLlxuICAgKi9cblxuXG4gIC8qIEBuYW1lc3BhY2UgTWFya2VyXG4gICAqIEBzZWN0aW9uIEludGVyYWN0aW9uIGhhbmRsZXJzXG4gICAqXG4gICAqIEludGVyYWN0aW9uIGhhbmRsZXJzIGFyZSBwcm9wZXJ0aWVzIG9mIGEgbWFya2VyIGluc3RhbmNlIHRoYXQgYWxsb3cgeW91IHRvIGNvbnRyb2wgaW50ZXJhY3Rpb24gYmVoYXZpb3IgaW4gcnVudGltZSwgZW5hYmxpbmcgb3IgZGlzYWJsaW5nIGNlcnRhaW4gZmVhdHVyZXMgc3VjaCBhcyBkcmFnZ2luZyAoc2VlIGBIYW5kbGVyYCBtZXRob2RzKS4gRXhhbXBsZTpcbiAgICpcbiAgICogYGBganNcbiAgICogbWFya2VyLmRyYWdnaW5nLmRpc2FibGUoKTtcbiAgICogYGBgXG4gICAqXG4gICAqIEBwcm9wZXJ0eSBkcmFnZ2luZzogSGFuZGxlclxuICAgKiBNYXJrZXIgZHJhZ2dpbmcgaGFuZGxlciAoYnkgYm90aCBtb3VzZSBhbmQgdG91Y2gpLiBPbmx5IHZhbGlkIHdoZW4gdGhlIG1hcmtlciBpcyBvbiB0aGUgbWFwIChPdGhlcndpc2Ugc2V0IFtgbWFya2VyLm9wdGlvbnMuZHJhZ2dhYmxlYF0oI21hcmtlci1kcmFnZ2FibGUpKS5cbiAgICovXG5cbiAgdmFyIE1hcmtlckRyYWcgPSBIYW5kbGVyLmV4dGVuZCh7XG4gIFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKG1hcmtlcikge1xuICBcdFx0dGhpcy5fbWFya2VyID0gbWFya2VyO1xuICBcdH0sXG5cbiAgXHRhZGRIb29rczogZnVuY3Rpb24gKCkge1xuICBcdFx0dmFyIGljb24gPSB0aGlzLl9tYXJrZXIuX2ljb247XG5cbiAgXHRcdGlmICghdGhpcy5fZHJhZ2dhYmxlKSB7XG4gIFx0XHRcdHRoaXMuX2RyYWdnYWJsZSA9IG5ldyBEcmFnZ2FibGUoaWNvbiwgaWNvbiwgdHJ1ZSk7XG4gIFx0XHR9XG5cbiAgXHRcdHRoaXMuX2RyYWdnYWJsZS5vbih7XG4gIFx0XHRcdGRyYWdzdGFydDogdGhpcy5fb25EcmFnU3RhcnQsXG4gIFx0XHRcdHByZWRyYWc6IHRoaXMuX29uUHJlRHJhZyxcbiAgXHRcdFx0ZHJhZzogdGhpcy5fb25EcmFnLFxuICBcdFx0XHRkcmFnZW5kOiB0aGlzLl9vbkRyYWdFbmRcbiAgXHRcdH0sIHRoaXMpLmVuYWJsZSgpO1xuXG4gIFx0XHRhZGRDbGFzcyhpY29uLCAnbGVhZmxldC1tYXJrZXItZHJhZ2dhYmxlJyk7XG4gIFx0fSxcblxuICBcdHJlbW92ZUhvb2tzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR0aGlzLl9kcmFnZ2FibGUub2ZmKHtcbiAgXHRcdFx0ZHJhZ3N0YXJ0OiB0aGlzLl9vbkRyYWdTdGFydCxcbiAgXHRcdFx0cHJlZHJhZzogdGhpcy5fb25QcmVEcmFnLFxuICBcdFx0XHRkcmFnOiB0aGlzLl9vbkRyYWcsXG4gIFx0XHRcdGRyYWdlbmQ6IHRoaXMuX29uRHJhZ0VuZFxuICBcdFx0fSwgdGhpcykuZGlzYWJsZSgpO1xuXG4gIFx0XHRpZiAodGhpcy5fbWFya2VyLl9pY29uKSB7XG4gIFx0XHRcdHJlbW92ZUNsYXNzKHRoaXMuX21hcmtlci5faWNvbiwgJ2xlYWZsZXQtbWFya2VyLWRyYWdnYWJsZScpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRtb3ZlZDogZnVuY3Rpb24gKCkge1xuICBcdFx0cmV0dXJuIHRoaXMuX2RyYWdnYWJsZSAmJiB0aGlzLl9kcmFnZ2FibGUuX21vdmVkO1xuICBcdH0sXG5cbiAgXHRfYWRqdXN0UGFuOiBmdW5jdGlvbiAoZSkge1xuICBcdFx0dmFyIG1hcmtlciA9IHRoaXMuX21hcmtlcixcbiAgXHRcdCAgICBtYXAgPSBtYXJrZXIuX21hcCxcbiAgXHRcdCAgICBzcGVlZCA9IHRoaXMuX21hcmtlci5vcHRpb25zLmF1dG9QYW5TcGVlZCxcbiAgXHRcdCAgICBwYWRkaW5nID0gdGhpcy5fbWFya2VyLm9wdGlvbnMuYXV0b1BhblBhZGRpbmcsXG4gIFx0XHQgICAgaWNvblBvcyA9IGdldFBvc2l0aW9uKG1hcmtlci5faWNvbiksXG4gIFx0XHQgICAgYm91bmRzID0gbWFwLmdldFBpeGVsQm91bmRzKCksXG4gIFx0XHQgICAgb3JpZ2luID0gbWFwLmdldFBpeGVsT3JpZ2luKCk7XG5cbiAgXHRcdHZhciBwYW5Cb3VuZHMgPSB0b0JvdW5kcyhcbiAgXHRcdFx0Ym91bmRzLm1pbi5fc3VidHJhY3Qob3JpZ2luKS5hZGQocGFkZGluZyksXG4gIFx0XHRcdGJvdW5kcy5tYXguX3N1YnRyYWN0KG9yaWdpbikuc3VidHJhY3QocGFkZGluZylcbiAgXHRcdCk7XG5cbiAgXHRcdGlmICghcGFuQm91bmRzLmNvbnRhaW5zKGljb25Qb3MpKSB7XG4gIFx0XHRcdC8vIENvbXB1dGUgaW5jcmVtZW50YWwgbW92ZW1lbnRcbiAgXHRcdFx0dmFyIG1vdmVtZW50ID0gdG9Qb2ludChcbiAgXHRcdFx0XHQoTWF0aC5tYXgocGFuQm91bmRzLm1heC54LCBpY29uUG9zLngpIC0gcGFuQm91bmRzLm1heC54KSAvIChib3VuZHMubWF4LnggLSBwYW5Cb3VuZHMubWF4LngpIC1cbiAgXHRcdFx0XHQoTWF0aC5taW4ocGFuQm91bmRzLm1pbi54LCBpY29uUG9zLngpIC0gcGFuQm91bmRzLm1pbi54KSAvIChib3VuZHMubWluLnggLSBwYW5Cb3VuZHMubWluLngpLFxuXG4gIFx0XHRcdFx0KE1hdGgubWF4KHBhbkJvdW5kcy5tYXgueSwgaWNvblBvcy55KSAtIHBhbkJvdW5kcy5tYXgueSkgLyAoYm91bmRzLm1heC55IC0gcGFuQm91bmRzLm1heC55KSAtXG4gIFx0XHRcdFx0KE1hdGgubWluKHBhbkJvdW5kcy5taW4ueSwgaWNvblBvcy55KSAtIHBhbkJvdW5kcy5taW4ueSkgLyAoYm91bmRzLm1pbi55IC0gcGFuQm91bmRzLm1pbi55KVxuICBcdFx0XHQpLm11bHRpcGx5Qnkoc3BlZWQpO1xuXG4gIFx0XHRcdG1hcC5wYW5CeShtb3ZlbWVudCwge2FuaW1hdGU6IGZhbHNlfSk7XG5cbiAgXHRcdFx0dGhpcy5fZHJhZ2dhYmxlLl9uZXdQb3MuX2FkZChtb3ZlbWVudCk7XG4gIFx0XHRcdHRoaXMuX2RyYWdnYWJsZS5fc3RhcnRQb3MuX2FkZChtb3ZlbWVudCk7XG5cbiAgXHRcdFx0c2V0UG9zaXRpb24obWFya2VyLl9pY29uLCB0aGlzLl9kcmFnZ2FibGUuX25ld1Bvcyk7XG4gIFx0XHRcdHRoaXMuX29uRHJhZyhlKTtcblxuICBcdFx0XHR0aGlzLl9wYW5SZXF1ZXN0ID0gcmVxdWVzdEFuaW1GcmFtZSh0aGlzLl9hZGp1c3RQYW4uYmluZCh0aGlzLCBlKSk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF9vbkRyYWdTdGFydDogZnVuY3Rpb24gKCkge1xuICBcdFx0Ly8gQHNlY3Rpb24gRHJhZ2dpbmcgZXZlbnRzXG4gIFx0XHQvLyBAZXZlbnQgZHJhZ3N0YXJ0OiBFdmVudFxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgdXNlciBzdGFydHMgZHJhZ2dpbmcgdGhlIG1hcmtlci5cblxuICBcdFx0Ly8gQGV2ZW50IG1vdmVzdGFydDogRXZlbnRcbiAgXHRcdC8vIEZpcmVkIHdoZW4gdGhlIG1hcmtlciBzdGFydHMgbW92aW5nIChiZWNhdXNlIG9mIGRyYWdnaW5nKS5cblxuICBcdFx0dGhpcy5fb2xkTGF0TG5nID0gdGhpcy5fbWFya2VyLmdldExhdExuZygpO1xuXG4gIFx0XHQvLyBXaGVuIHVzaW5nIEVTNiBpbXBvcnRzIGl0IGNvdWxkIG5vdCBiZSBzZXQgd2hlbiBgUG9wdXBgIHdhcyBub3QgaW1wb3J0ZWQgYXMgd2VsbFxuICBcdFx0dGhpcy5fbWFya2VyLmNsb3NlUG9wdXAgJiYgdGhpcy5fbWFya2VyLmNsb3NlUG9wdXAoKTtcblxuICBcdFx0dGhpcy5fbWFya2VyXG4gIFx0XHRcdC5maXJlKCdtb3Zlc3RhcnQnKVxuICBcdFx0XHQuZmlyZSgnZHJhZ3N0YXJ0Jyk7XG4gIFx0fSxcblxuICBcdF9vblByZURyYWc6IGZ1bmN0aW9uIChlKSB7XG4gIFx0XHRpZiAodGhpcy5fbWFya2VyLm9wdGlvbnMuYXV0b1Bhbikge1xuICBcdFx0XHRjYW5jZWxBbmltRnJhbWUodGhpcy5fcGFuUmVxdWVzdCk7XG4gIFx0XHRcdHRoaXMuX3BhblJlcXVlc3QgPSByZXF1ZXN0QW5pbUZyYW1lKHRoaXMuX2FkanVzdFBhbi5iaW5kKHRoaXMsIGUpKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X29uRHJhZzogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdHZhciBtYXJrZXIgPSB0aGlzLl9tYXJrZXIsXG4gIFx0XHQgICAgc2hhZG93ID0gbWFya2VyLl9zaGFkb3csXG4gIFx0XHQgICAgaWNvblBvcyA9IGdldFBvc2l0aW9uKG1hcmtlci5faWNvbiksXG4gIFx0XHQgICAgbGF0bG5nID0gbWFya2VyLl9tYXAubGF5ZXJQb2ludFRvTGF0TG5nKGljb25Qb3MpO1xuXG4gIFx0XHQvLyB1cGRhdGUgc2hhZG93IHBvc2l0aW9uXG4gIFx0XHRpZiAoc2hhZG93KSB7XG4gIFx0XHRcdHNldFBvc2l0aW9uKHNoYWRvdywgaWNvblBvcyk7XG4gIFx0XHR9XG5cbiAgXHRcdG1hcmtlci5fbGF0bG5nID0gbGF0bG5nO1xuICBcdFx0ZS5sYXRsbmcgPSBsYXRsbmc7XG4gIFx0XHRlLm9sZExhdExuZyA9IHRoaXMuX29sZExhdExuZztcblxuICBcdFx0Ly8gQGV2ZW50IGRyYWc6IEV2ZW50XG4gIFx0XHQvLyBGaXJlZCByZXBlYXRlZGx5IHdoaWxlIHRoZSB1c2VyIGRyYWdzIHRoZSBtYXJrZXIuXG4gIFx0XHRtYXJrZXJcbiAgXHRcdCAgICAuZmlyZSgnbW92ZScsIGUpXG4gIFx0XHQgICAgLmZpcmUoJ2RyYWcnLCBlKTtcbiAgXHR9LFxuXG4gIFx0X29uRHJhZ0VuZDogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdC8vIEBldmVudCBkcmFnZW5kOiBEcmFnRW5kRXZlbnRcbiAgXHRcdC8vIEZpcmVkIHdoZW4gdGhlIHVzZXIgc3RvcHMgZHJhZ2dpbmcgdGhlIG1hcmtlci5cblxuICBcdFx0IGNhbmNlbEFuaW1GcmFtZSh0aGlzLl9wYW5SZXF1ZXN0KTtcblxuICBcdFx0Ly8gQGV2ZW50IG1vdmVlbmQ6IEV2ZW50XG4gIFx0XHQvLyBGaXJlZCB3aGVuIHRoZSBtYXJrZXIgc3RvcHMgbW92aW5nIChiZWNhdXNlIG9mIGRyYWdnaW5nKS5cbiAgXHRcdGRlbGV0ZSB0aGlzLl9vbGRMYXRMbmc7XG4gIFx0XHR0aGlzLl9tYXJrZXJcbiAgXHRcdCAgICAuZmlyZSgnbW92ZWVuZCcpXG4gIFx0XHQgICAgLmZpcmUoJ2RyYWdlbmQnLCBlKTtcbiAgXHR9XG4gIH0pO1xuXG4gIC8qXHJcbiAgICogQGNsYXNzIE1hcmtlclxyXG4gICAqIEBpbmhlcml0cyBJbnRlcmFjdGl2ZSBsYXllclxyXG4gICAqIEBha2EgTC5NYXJrZXJcclxuICAgKiBMLk1hcmtlciBpcyB1c2VkIHRvIGRpc3BsYXkgY2xpY2thYmxlL2RyYWdnYWJsZSBpY29ucyBvbiB0aGUgbWFwLiBFeHRlbmRzIGBMYXllcmAuXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiBMLm1hcmtlcihbNTAuNSwgMzAuNV0pLmFkZFRvKG1hcCk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcblxyXG4gIHZhciBNYXJrZXIgPSBMYXllci5leHRlbmQoe1xyXG5cclxuICBcdC8vIEBzZWN0aW9uXHJcbiAgXHQvLyBAYWthIE1hcmtlciBvcHRpb25zXHJcbiAgXHRvcHRpb25zOiB7XHJcbiAgXHRcdC8vIEBvcHRpb24gaWNvbjogSWNvbiA9ICpcclxuICBcdFx0Ly8gSWNvbiBpbnN0YW5jZSB0byB1c2UgZm9yIHJlbmRlcmluZyB0aGUgbWFya2VyLlxyXG4gIFx0XHQvLyBTZWUgW0ljb24gZG9jdW1lbnRhdGlvbl0oI0wuSWNvbikgZm9yIGRldGFpbHMgb24gaG93IHRvIGN1c3RvbWl6ZSB0aGUgbWFya2VyIGljb24uXHJcbiAgXHRcdC8vIElmIG5vdCBzcGVjaWZpZWQsIGEgY29tbW9uIGluc3RhbmNlIG9mIGBMLkljb24uRGVmYXVsdGAgaXMgdXNlZC5cclxuICBcdFx0aWNvbjogbmV3IEljb25EZWZhdWx0KCksXHJcblxyXG4gIFx0XHQvLyBPcHRpb24gaW5oZXJpdGVkIGZyb20gXCJJbnRlcmFjdGl2ZSBsYXllclwiIGFic3RyYWN0IGNsYXNzXHJcbiAgXHRcdGludGVyYWN0aXZlOiB0cnVlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBrZXlib2FyZDogQm9vbGVhbiA9IHRydWVcclxuICBcdFx0Ly8gV2hldGhlciB0aGUgbWFya2VyIGNhbiBiZSB0YWJiZWQgdG8gd2l0aCBhIGtleWJvYXJkIGFuZCBjbGlja2VkIGJ5IHByZXNzaW5nIGVudGVyLlxyXG4gIFx0XHRrZXlib2FyZDogdHJ1ZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gdGl0bGU6IFN0cmluZyA9ICcnXHJcbiAgXHRcdC8vIFRleHQgZm9yIHRoZSBicm93c2VyIHRvb2x0aXAgdGhhdCBhcHBlYXIgb24gbWFya2VyIGhvdmVyIChubyB0b29sdGlwIGJ5IGRlZmF1bHQpLlxyXG4gIFx0XHQvLyBbVXNlZnVsIGZvciBhY2Nlc3NpYmlsaXR5XShodHRwczovL2xlYWZsZXRqcy5jb20vZXhhbXBsZXMvYWNjZXNzaWJpbGl0eS8jbWFya2Vycy1tdXN0LWJlLWxhYmVsbGVkKS5cclxuICBcdFx0dGl0bGU6ICcnLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBhbHQ6IFN0cmluZyA9ICdNYXJrZXInXHJcbiAgXHRcdC8vIFRleHQgZm9yIHRoZSBgYWx0YCBhdHRyaWJ1dGUgb2YgdGhlIGljb24gaW1hZ2UuXHJcbiAgXHRcdC8vIFtVc2VmdWwgZm9yIGFjY2Vzc2liaWxpdHldKGh0dHBzOi8vbGVhZmxldGpzLmNvbS9leGFtcGxlcy9hY2Nlc3NpYmlsaXR5LyNtYXJrZXJzLW11c3QtYmUtbGFiZWxsZWQpLlxyXG4gIFx0XHRhbHQ6ICdNYXJrZXInLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiB6SW5kZXhPZmZzZXQ6IE51bWJlciA9IDBcclxuICBcdFx0Ly8gQnkgZGVmYXVsdCwgbWFya2VyIGltYWdlcyB6SW5kZXggaXMgc2V0IGF1dG9tYXRpY2FsbHkgYmFzZWQgb24gaXRzIGxhdGl0dWRlLiBVc2UgdGhpcyBvcHRpb24gaWYgeW91IHdhbnQgdG8gcHV0IHRoZSBtYXJrZXIgb24gdG9wIG9mIGFsbCBvdGhlcnMgKG9yIGJlbG93KSwgc3BlY2lmeWluZyBhIGhpZ2ggdmFsdWUgbGlrZSBgMTAwMGAgKG9yIGhpZ2ggbmVnYXRpdmUgdmFsdWUsIHJlc3BlY3RpdmVseSkuXHJcbiAgXHRcdHpJbmRleE9mZnNldDogMCxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gb3BhY2l0eTogTnVtYmVyID0gMS4wXHJcbiAgXHRcdC8vIFRoZSBvcGFjaXR5IG9mIHRoZSBtYXJrZXIuXHJcbiAgXHRcdG9wYWNpdHk6IDEsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHJpc2VPbkhvdmVyOiBCb29sZWFuID0gZmFsc2VcclxuICBcdFx0Ly8gSWYgYHRydWVgLCB0aGUgbWFya2VyIHdpbGwgZ2V0IG9uIHRvcCBvZiBvdGhlcnMgd2hlbiB5b3UgaG92ZXIgdGhlIG1vdXNlIG92ZXIgaXQuXHJcbiAgXHRcdHJpc2VPbkhvdmVyOiBmYWxzZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gcmlzZU9mZnNldDogTnVtYmVyID0gMjUwXHJcbiAgXHRcdC8vIFRoZSB6LWluZGV4IG9mZnNldCB1c2VkIGZvciB0aGUgYHJpc2VPbkhvdmVyYCBmZWF0dXJlLlxyXG4gIFx0XHRyaXNlT2Zmc2V0OiAyNTAsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHBhbmU6IFN0cmluZyA9ICdtYXJrZXJQYW5lJ1xyXG4gIFx0XHQvLyBgTWFwIHBhbmVgIHdoZXJlIHRoZSBtYXJrZXJzIGljb24gd2lsbCBiZSBhZGRlZC5cclxuICBcdFx0cGFuZTogJ21hcmtlclBhbmUnLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBzaGFkb3dQYW5lOiBTdHJpbmcgPSAnc2hhZG93UGFuZSdcclxuICBcdFx0Ly8gYE1hcCBwYW5lYCB3aGVyZSB0aGUgbWFya2VycyBzaGFkb3cgd2lsbCBiZSBhZGRlZC5cclxuICBcdFx0c2hhZG93UGFuZTogJ3NoYWRvd1BhbmUnLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBidWJibGluZ01vdXNlRXZlbnRzOiBCb29sZWFuID0gZmFsc2VcclxuICBcdFx0Ly8gV2hlbiBgdHJ1ZWAsIGEgbW91c2UgZXZlbnQgb24gdGhpcyBtYXJrZXIgd2lsbCB0cmlnZ2VyIHRoZSBzYW1lIGV2ZW50IG9uIHRoZSBtYXBcclxuICBcdFx0Ly8gKHVubGVzcyBbYEwuRG9tRXZlbnQuc3RvcFByb3BhZ2F0aW9uYF0oI2RvbWV2ZW50LXN0b3Bwcm9wYWdhdGlvbikgaXMgdXNlZCkuXHJcbiAgXHRcdGJ1YmJsaW5nTW91c2VFdmVudHM6IGZhbHNlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBhdXRvUGFuT25Gb2N1czogQm9vbGVhbiA9IHRydWVcclxuICBcdFx0Ly8gV2hlbiBgdHJ1ZWAsIHRoZSBtYXAgd2lsbCBwYW4gd2hlbmV2ZXIgdGhlIG1hcmtlciBpcyBmb2N1c2VkICh2aWFcclxuICBcdFx0Ly8gZS5nLiBwcmVzc2luZyBgdGFiYCBvbiB0aGUga2V5Ym9hcmQpIHRvIGVuc3VyZSB0aGUgbWFya2VyIGlzXHJcbiAgXHRcdC8vIHZpc2libGUgd2l0aGluIHRoZSBtYXAncyBib3VuZHNcclxuICBcdFx0YXV0b1Bhbk9uRm9jdXM6IHRydWUsXHJcblxyXG4gIFx0XHQvLyBAc2VjdGlvbiBEcmFnZ2FibGUgbWFya2VyIG9wdGlvbnNcclxuICBcdFx0Ly8gQG9wdGlvbiBkcmFnZ2FibGU6IEJvb2xlYW4gPSBmYWxzZVxyXG4gIFx0XHQvLyBXaGV0aGVyIHRoZSBtYXJrZXIgaXMgZHJhZ2dhYmxlIHdpdGggbW91c2UvdG91Y2ggb3Igbm90LlxyXG4gIFx0XHRkcmFnZ2FibGU6IGZhbHNlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBhdXRvUGFuOiBCb29sZWFuID0gZmFsc2VcclxuICBcdFx0Ly8gV2hldGhlciB0byBwYW4gdGhlIG1hcCB3aGVuIGRyYWdnaW5nIHRoaXMgbWFya2VyIG5lYXIgaXRzIGVkZ2Ugb3Igbm90LlxyXG4gIFx0XHRhdXRvUGFuOiBmYWxzZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gYXV0b1BhblBhZGRpbmc6IFBvaW50ID0gUG9pbnQoNTAsIDUwKVxyXG4gIFx0XHQvLyBEaXN0YW5jZSAoaW4gcGl4ZWxzIHRvIHRoZSBsZWZ0L3JpZ2h0IGFuZCB0byB0aGUgdG9wL2JvdHRvbSkgb2YgdGhlXHJcbiAgXHRcdC8vIG1hcCBlZGdlIHRvIHN0YXJ0IHBhbm5pbmcgdGhlIG1hcC5cclxuICBcdFx0YXV0b1BhblBhZGRpbmc6IFs1MCwgNTBdLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBhdXRvUGFuU3BlZWQ6IE51bWJlciA9IDEwXHJcbiAgXHRcdC8vIE51bWJlciBvZiBwaXhlbHMgdGhlIG1hcCBzaG91bGQgcGFuIGJ5LlxyXG4gIFx0XHRhdXRvUGFuU3BlZWQ6IDEwXHJcbiAgXHR9LFxyXG5cclxuICBcdC8qIEBzZWN0aW9uXHJcbiAgXHQgKlxyXG4gIFx0ICogSW4gYWRkaXRpb24gdG8gW3NoYXJlZCBsYXllciBtZXRob2RzXSgjTGF5ZXIpIGxpa2UgYGFkZFRvKClgIGFuZCBgcmVtb3ZlKClgIGFuZCBbcG9wdXAgbWV0aG9kc10oI1BvcHVwKSBsaWtlIGJpbmRQb3B1cCgpIHlvdSBjYW4gYWxzbyB1c2UgdGhlIGZvbGxvd2luZyBtZXRob2RzOlxyXG4gIFx0ICovXHJcblxyXG4gIFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKGxhdGxuZywgb3B0aW9ucykge1xyXG4gIFx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xyXG4gIFx0XHR0aGlzLl9sYXRsbmcgPSB0b0xhdExuZyhsYXRsbmcpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRvbkFkZDogZnVuY3Rpb24gKG1hcCkge1xyXG4gIFx0XHR0aGlzLl96b29tQW5pbWF0ZWQgPSB0aGlzLl96b29tQW5pbWF0ZWQgJiYgbWFwLm9wdGlvbnMubWFya2VyWm9vbUFuaW1hdGlvbjtcclxuXHJcbiAgXHRcdGlmICh0aGlzLl96b29tQW5pbWF0ZWQpIHtcclxuICBcdFx0XHRtYXAub24oJ3pvb21hbmltJywgdGhpcy5fYW5pbWF0ZVpvb20sIHRoaXMpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR0aGlzLl9pbml0SWNvbigpO1xyXG4gIFx0XHR0aGlzLnVwZGF0ZSgpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRvblJlbW92ZTogZnVuY3Rpb24gKG1hcCkge1xyXG4gIFx0XHRpZiAodGhpcy5kcmFnZ2luZyAmJiB0aGlzLmRyYWdnaW5nLmVuYWJsZWQoKSkge1xyXG4gIFx0XHRcdHRoaXMub3B0aW9ucy5kcmFnZ2FibGUgPSB0cnVlO1xyXG4gIFx0XHRcdHRoaXMuZHJhZ2dpbmcucmVtb3ZlSG9va3MoKTtcclxuICBcdFx0fVxyXG4gIFx0XHRkZWxldGUgdGhpcy5kcmFnZ2luZztcclxuXHJcbiAgXHRcdGlmICh0aGlzLl96b29tQW5pbWF0ZWQpIHtcclxuICBcdFx0XHRtYXAub2ZmKCd6b29tYW5pbScsIHRoaXMuX2FuaW1hdGVab29tLCB0aGlzKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5fcmVtb3ZlSWNvbigpO1xyXG4gIFx0XHR0aGlzLl9yZW1vdmVTaGFkb3coKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Z2V0RXZlbnRzOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB7XHJcbiAgXHRcdFx0em9vbTogdGhpcy51cGRhdGUsXHJcbiAgXHRcdFx0dmlld3Jlc2V0OiB0aGlzLnVwZGF0ZVxyXG4gIFx0XHR9O1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldExhdExuZzogTGF0TG5nXHJcbiAgXHQvLyBSZXR1cm5zIHRoZSBjdXJyZW50IGdlb2dyYXBoaWNhbCBwb3NpdGlvbiBvZiB0aGUgbWFya2VyLlxyXG4gIFx0Z2V0TGF0TG5nOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLl9sYXRsbmc7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2V0TGF0TG5nKGxhdGxuZzogTGF0TG5nKTogdGhpc1xyXG4gIFx0Ly8gQ2hhbmdlcyB0aGUgbWFya2VyIHBvc2l0aW9uIHRvIHRoZSBnaXZlbiBwb2ludC5cclxuICBcdHNldExhdExuZzogZnVuY3Rpb24gKGxhdGxuZykge1xyXG4gIFx0XHR2YXIgb2xkTGF0TG5nID0gdGhpcy5fbGF0bG5nO1xyXG4gIFx0XHR0aGlzLl9sYXRsbmcgPSB0b0xhdExuZyhsYXRsbmcpO1xyXG4gIFx0XHR0aGlzLnVwZGF0ZSgpO1xyXG5cclxuICBcdFx0Ly8gQGV2ZW50IG1vdmU6IEV2ZW50XHJcbiAgXHRcdC8vIEZpcmVkIHdoZW4gdGhlIG1hcmtlciBpcyBtb3ZlZCB2aWEgW2BzZXRMYXRMbmdgXSgjbWFya2VyLXNldGxhdGxuZykgb3IgYnkgW2RyYWdnaW5nXSgjbWFya2VyLWRyYWdnaW5nKS4gT2xkIGFuZCBuZXcgY29vcmRpbmF0ZXMgYXJlIGluY2x1ZGVkIGluIGV2ZW50IGFyZ3VtZW50cyBhcyBgb2xkTGF0TG5nYCwgYGxhdGxuZ2AuXHJcbiAgXHRcdHJldHVybiB0aGlzLmZpcmUoJ21vdmUnLCB7b2xkTGF0TG5nOiBvbGRMYXRMbmcsIGxhdGxuZzogdGhpcy5fbGF0bG5nfSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2V0WkluZGV4T2Zmc2V0KG9mZnNldDogTnVtYmVyKTogdGhpc1xyXG4gIFx0Ly8gQ2hhbmdlcyB0aGUgW3pJbmRleCBvZmZzZXRdKCNtYXJrZXItemluZGV4b2Zmc2V0KSBvZiB0aGUgbWFya2VyLlxyXG4gIFx0c2V0WkluZGV4T2Zmc2V0OiBmdW5jdGlvbiAob2Zmc2V0KSB7XHJcbiAgXHRcdHRoaXMub3B0aW9ucy56SW5kZXhPZmZzZXQgPSBvZmZzZXQ7XHJcbiAgXHRcdHJldHVybiB0aGlzLnVwZGF0ZSgpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldEljb246IEljb25cclxuICBcdC8vIFJldHVybnMgdGhlIGN1cnJlbnQgaWNvbiB1c2VkIGJ5IHRoZSBtYXJrZXJcclxuICBcdGdldEljb246IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMub3B0aW9ucy5pY29uO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNldEljb24oaWNvbjogSWNvbik6IHRoaXNcclxuICBcdC8vIENoYW5nZXMgdGhlIG1hcmtlciBpY29uLlxyXG4gIFx0c2V0SWNvbjogZnVuY3Rpb24gKGljb24pIHtcclxuXHJcbiAgXHRcdHRoaXMub3B0aW9ucy5pY29uID0gaWNvbjtcclxuXHJcbiAgXHRcdGlmICh0aGlzLl9tYXApIHtcclxuICBcdFx0XHR0aGlzLl9pbml0SWNvbigpO1xyXG4gIFx0XHRcdHRoaXMudXBkYXRlKCk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmICh0aGlzLl9wb3B1cCkge1xyXG4gIFx0XHRcdHRoaXMuYmluZFBvcHVwKHRoaXMuX3BvcHVwLCB0aGlzLl9wb3B1cC5vcHRpb25zKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdGdldEVsZW1lbnQ6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuX2ljb247XHJcbiAgXHR9LFxyXG5cclxuICBcdHVwZGF0ZTogZnVuY3Rpb24gKCkge1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX2ljb24gJiYgdGhpcy5fbWFwKSB7XHJcbiAgXHRcdFx0dmFyIHBvcyA9IHRoaXMuX21hcC5sYXRMbmdUb0xheWVyUG9pbnQodGhpcy5fbGF0bG5nKS5yb3VuZCgpO1xyXG4gIFx0XHRcdHRoaXMuX3NldFBvcyhwb3MpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0X2luaXRJY29uOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHZhciBvcHRpb25zID0gdGhpcy5vcHRpb25zLFxyXG4gIFx0XHQgICAgY2xhc3NUb0FkZCA9ICdsZWFmbGV0LXpvb20tJyArICh0aGlzLl96b29tQW5pbWF0ZWQgPyAnYW5pbWF0ZWQnIDogJ2hpZGUnKTtcclxuXHJcbiAgXHRcdHZhciBpY29uID0gb3B0aW9ucy5pY29uLmNyZWF0ZUljb24odGhpcy5faWNvbiksXHJcbiAgXHRcdCAgICBhZGRJY29uID0gZmFsc2U7XHJcblxyXG4gIFx0XHQvLyBpZiB3ZSdyZSBub3QgcmV1c2luZyB0aGUgaWNvbiwgcmVtb3ZlIHRoZSBvbGQgb25lIGFuZCBpbml0IG5ldyBvbmVcclxuICBcdFx0aWYgKGljb24gIT09IHRoaXMuX2ljb24pIHtcclxuICBcdFx0XHRpZiAodGhpcy5faWNvbikge1xyXG4gIFx0XHRcdFx0dGhpcy5fcmVtb3ZlSWNvbigpO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0XHRhZGRJY29uID0gdHJ1ZTtcclxuXHJcbiAgXHRcdFx0aWYgKG9wdGlvbnMudGl0bGUpIHtcclxuICBcdFx0XHRcdGljb24udGl0bGUgPSBvcHRpb25zLnRpdGxlO1xyXG4gIFx0XHRcdH1cclxuXHJcbiAgXHRcdFx0aWYgKGljb24udGFnTmFtZSA9PT0gJ0lNRycpIHtcclxuICBcdFx0XHRcdGljb24uYWx0ID0gb3B0aW9ucy5hbHQgfHwgJyc7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRhZGRDbGFzcyhpY29uLCBjbGFzc1RvQWRkKTtcclxuXHJcbiAgXHRcdGlmIChvcHRpb25zLmtleWJvYXJkKSB7XHJcbiAgXHRcdFx0aWNvbi50YWJJbmRleCA9ICcwJztcclxuICBcdFx0XHRpY29uLnNldEF0dHJpYnV0ZSgncm9sZScsICdidXR0b24nKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5faWNvbiA9IGljb247XHJcblxyXG4gIFx0XHRpZiAob3B0aW9ucy5yaXNlT25Ib3Zlcikge1xyXG4gIFx0XHRcdHRoaXMub24oe1xyXG4gIFx0XHRcdFx0bW91c2VvdmVyOiB0aGlzLl9icmluZ1RvRnJvbnQsXHJcbiAgXHRcdFx0XHRtb3VzZW91dDogdGhpcy5fcmVzZXRaSW5kZXhcclxuICBcdFx0XHR9KTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5hdXRvUGFuT25Gb2N1cykge1xyXG4gIFx0XHRcdG9uKGljb24sICdmb2N1cycsIHRoaXMuX3Bhbk9uRm9jdXMsIHRoaXMpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR2YXIgbmV3U2hhZG93ID0gb3B0aW9ucy5pY29uLmNyZWF0ZVNoYWRvdyh0aGlzLl9zaGFkb3cpLFxyXG4gIFx0XHQgICAgYWRkU2hhZG93ID0gZmFsc2U7XHJcblxyXG4gIFx0XHRpZiAobmV3U2hhZG93ICE9PSB0aGlzLl9zaGFkb3cpIHtcclxuICBcdFx0XHR0aGlzLl9yZW1vdmVTaGFkb3coKTtcclxuICBcdFx0XHRhZGRTaGFkb3cgPSB0cnVlO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAobmV3U2hhZG93KSB7XHJcbiAgXHRcdFx0YWRkQ2xhc3MobmV3U2hhZG93LCBjbGFzc1RvQWRkKTtcclxuICBcdFx0XHRuZXdTaGFkb3cuYWx0ID0gJyc7XHJcbiAgXHRcdH1cclxuICBcdFx0dGhpcy5fc2hhZG93ID0gbmV3U2hhZG93O1xyXG5cclxuXHJcbiAgXHRcdGlmIChvcHRpb25zLm9wYWNpdHkgPCAxKSB7XHJcbiAgXHRcdFx0dGhpcy5fdXBkYXRlT3BhY2l0eSgpO1xyXG4gIFx0XHR9XHJcblxyXG5cclxuICBcdFx0aWYgKGFkZEljb24pIHtcclxuICBcdFx0XHR0aGlzLmdldFBhbmUoKS5hcHBlbmRDaGlsZCh0aGlzLl9pY29uKTtcclxuICBcdFx0fVxyXG4gIFx0XHR0aGlzLl9pbml0SW50ZXJhY3Rpb24oKTtcclxuICBcdFx0aWYgKG5ld1NoYWRvdyAmJiBhZGRTaGFkb3cpIHtcclxuICBcdFx0XHR0aGlzLmdldFBhbmUob3B0aW9ucy5zaGFkb3dQYW5lKS5hcHBlbmRDaGlsZCh0aGlzLl9zaGFkb3cpO1xyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdF9yZW1vdmVJY29uOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMucmlzZU9uSG92ZXIpIHtcclxuICBcdFx0XHR0aGlzLm9mZih7XHJcbiAgXHRcdFx0XHRtb3VzZW92ZXI6IHRoaXMuX2JyaW5nVG9Gcm9udCxcclxuICBcdFx0XHRcdG1vdXNlb3V0OiB0aGlzLl9yZXNldFpJbmRleFxyXG4gIFx0XHRcdH0pO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAodGhpcy5vcHRpb25zLmF1dG9QYW5PbkZvY3VzKSB7XHJcbiAgXHRcdFx0b2ZmKHRoaXMuX2ljb24sICdmb2N1cycsIHRoaXMuX3Bhbk9uRm9jdXMsIHRoaXMpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZW1vdmUodGhpcy5faWNvbik7XHJcbiAgXHRcdHRoaXMucmVtb3ZlSW50ZXJhY3RpdmVUYXJnZXQodGhpcy5faWNvbik7XHJcblxyXG4gIFx0XHR0aGlzLl9pY29uID0gbnVsbDtcclxuICBcdH0sXHJcblxyXG4gIFx0X3JlbW92ZVNoYWRvdzogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRpZiAodGhpcy5fc2hhZG93KSB7XHJcbiAgXHRcdFx0cmVtb3ZlKHRoaXMuX3NoYWRvdyk7XHJcbiAgXHRcdH1cclxuICBcdFx0dGhpcy5fc2hhZG93ID0gbnVsbDtcclxuICBcdH0sXHJcblxyXG4gIFx0X3NldFBvczogZnVuY3Rpb24gKHBvcykge1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX2ljb24pIHtcclxuICBcdFx0XHRzZXRQb3NpdGlvbih0aGlzLl9pY29uLCBwb3MpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fc2hhZG93KSB7XHJcbiAgXHRcdFx0c2V0UG9zaXRpb24odGhpcy5fc2hhZG93LCBwb3MpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR0aGlzLl96SW5kZXggPSBwb3MueSArIHRoaXMub3B0aW9ucy56SW5kZXhPZmZzZXQ7XHJcblxyXG4gIFx0XHR0aGlzLl9yZXNldFpJbmRleCgpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfdXBkYXRlWkluZGV4OiBmdW5jdGlvbiAob2Zmc2V0KSB7XHJcbiAgXHRcdGlmICh0aGlzLl9pY29uKSB7XHJcbiAgXHRcdFx0dGhpcy5faWNvbi5zdHlsZS56SW5kZXggPSB0aGlzLl96SW5kZXggKyBvZmZzZXQ7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0X2FuaW1hdGVab29tOiBmdW5jdGlvbiAob3B0KSB7XHJcbiAgXHRcdHZhciBwb3MgPSB0aGlzLl9tYXAuX2xhdExuZ1RvTmV3TGF5ZXJQb2ludCh0aGlzLl9sYXRsbmcsIG9wdC56b29tLCBvcHQuY2VudGVyKS5yb3VuZCgpO1xyXG5cclxuICBcdFx0dGhpcy5fc2V0UG9zKHBvcyk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9pbml0SW50ZXJhY3Rpb246IGZ1bmN0aW9uICgpIHtcclxuXHJcbiAgXHRcdGlmICghdGhpcy5vcHRpb25zLmludGVyYWN0aXZlKSB7IHJldHVybjsgfVxyXG5cclxuICBcdFx0YWRkQ2xhc3ModGhpcy5faWNvbiwgJ2xlYWZsZXQtaW50ZXJhY3RpdmUnKTtcclxuXHJcbiAgXHRcdHRoaXMuYWRkSW50ZXJhY3RpdmVUYXJnZXQodGhpcy5faWNvbik7XHJcblxyXG4gIFx0XHRpZiAoTWFya2VyRHJhZykge1xyXG4gIFx0XHRcdHZhciBkcmFnZ2FibGUgPSB0aGlzLm9wdGlvbnMuZHJhZ2dhYmxlO1xyXG4gIFx0XHRcdGlmICh0aGlzLmRyYWdnaW5nKSB7XHJcbiAgXHRcdFx0XHRkcmFnZ2FibGUgPSB0aGlzLmRyYWdnaW5nLmVuYWJsZWQoKTtcclxuICBcdFx0XHRcdHRoaXMuZHJhZ2dpbmcuZGlzYWJsZSgpO1xyXG4gIFx0XHRcdH1cclxuXHJcbiAgXHRcdFx0dGhpcy5kcmFnZ2luZyA9IG5ldyBNYXJrZXJEcmFnKHRoaXMpO1xyXG5cclxuICBcdFx0XHRpZiAoZHJhZ2dhYmxlKSB7XHJcbiAgXHRcdFx0XHR0aGlzLmRyYWdnaW5nLmVuYWJsZSgpO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNldE9wYWNpdHkob3BhY2l0eTogTnVtYmVyKTogdGhpc1xyXG4gIFx0Ly8gQ2hhbmdlcyB0aGUgb3BhY2l0eSBvZiB0aGUgbWFya2VyLlxyXG4gIFx0c2V0T3BhY2l0eTogZnVuY3Rpb24gKG9wYWNpdHkpIHtcclxuICBcdFx0dGhpcy5vcHRpb25zLm9wYWNpdHkgPSBvcGFjaXR5O1xyXG4gIFx0XHRpZiAodGhpcy5fbWFwKSB7XHJcbiAgXHRcdFx0dGhpcy5fdXBkYXRlT3BhY2l0eSgpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0X3VwZGF0ZU9wYWNpdHk6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dmFyIG9wYWNpdHkgPSB0aGlzLm9wdGlvbnMub3BhY2l0eTtcclxuXHJcbiAgXHRcdGlmICh0aGlzLl9pY29uKSB7XHJcbiAgXHRcdFx0c2V0T3BhY2l0eSh0aGlzLl9pY29uLCBvcGFjaXR5KTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0aWYgKHRoaXMuX3NoYWRvdykge1xyXG4gIFx0XHRcdHNldE9wYWNpdHkodGhpcy5fc2hhZG93LCBvcGFjaXR5KTtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHRfYnJpbmdUb0Zyb250OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHRoaXMuX3VwZGF0ZVpJbmRleCh0aGlzLm9wdGlvbnMucmlzZU9mZnNldCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9yZXNldFpJbmRleDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR0aGlzLl91cGRhdGVaSW5kZXgoMCk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9wYW5PbkZvY3VzOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHZhciBtYXAgPSB0aGlzLl9tYXA7XHJcbiAgXHRcdGlmICghbWFwKSB7IHJldHVybjsgfVxyXG5cclxuICBcdFx0dmFyIGljb25PcHRzID0gdGhpcy5vcHRpb25zLmljb24ub3B0aW9ucztcclxuICBcdFx0dmFyIHNpemUgPSBpY29uT3B0cy5pY29uU2l6ZSA/IHRvUG9pbnQoaWNvbk9wdHMuaWNvblNpemUpIDogdG9Qb2ludCgwLCAwKTtcclxuICBcdFx0dmFyIGFuY2hvciA9IGljb25PcHRzLmljb25BbmNob3IgPyB0b1BvaW50KGljb25PcHRzLmljb25BbmNob3IpIDogdG9Qb2ludCgwLCAwKTtcclxuXHJcbiAgXHRcdG1hcC5wYW5JbnNpZGUodGhpcy5fbGF0bG5nLCB7XHJcbiAgXHRcdFx0cGFkZGluZ1RvcExlZnQ6IGFuY2hvcixcclxuICBcdFx0XHRwYWRkaW5nQm90dG9tUmlnaHQ6IHNpemUuc3VidHJhY3QoYW5jaG9yKVxyXG4gIFx0XHR9KTtcclxuICBcdH0sXHJcblxyXG4gIFx0X2dldFBvcHVwQW5jaG9yOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLm9wdGlvbnMuaWNvbi5vcHRpb25zLnBvcHVwQW5jaG9yO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfZ2V0VG9vbHRpcEFuY2hvcjogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmljb24ub3B0aW9ucy50b29sdGlwQW5jaG9yO1xyXG4gIFx0fVxyXG4gIH0pO1xyXG5cclxuXHJcbiAgLy8gZmFjdG9yeSBMLm1hcmtlcihsYXRsbmc6IExhdExuZywgb3B0aW9ucz8gOiBNYXJrZXIgb3B0aW9ucylcclxuXHJcbiAgLy8gQGZhY3RvcnkgTC5tYXJrZXIobGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/IDogTWFya2VyIG9wdGlvbnMpXHJcbiAgLy8gSW5zdGFudGlhdGVzIGEgTWFya2VyIG9iamVjdCBnaXZlbiBhIGdlb2dyYXBoaWNhbCBwb2ludCBhbmQgb3B0aW9uYWxseSBhbiBvcHRpb25zIG9iamVjdC5cclxuICBmdW5jdGlvbiBtYXJrZXIobGF0bG5nLCBvcHRpb25zKSB7XHJcbiAgXHRyZXR1cm4gbmV3IE1hcmtlcihsYXRsbmcsIG9wdGlvbnMpO1xyXG4gIH1cblxuICAvKlxuICAgKiBAY2xhc3MgUGF0aFxuICAgKiBAYWthIEwuUGF0aFxuICAgKiBAaW5oZXJpdHMgSW50ZXJhY3RpdmUgbGF5ZXJcbiAgICpcbiAgICogQW4gYWJzdHJhY3QgY2xhc3MgdGhhdCBjb250YWlucyBvcHRpb25zIGFuZCBjb25zdGFudHMgc2hhcmVkIGJldHdlZW4gdmVjdG9yXG4gICAqIG92ZXJsYXlzIChQb2x5Z29uLCBQb2x5bGluZSwgQ2lyY2xlKS4gRG8gbm90IHVzZSBpdCBkaXJlY3RseS4gRXh0ZW5kcyBgTGF5ZXJgLlxuICAgKi9cblxuICB2YXIgUGF0aCA9IExheWVyLmV4dGVuZCh7XG5cbiAgXHQvLyBAc2VjdGlvblxuICBcdC8vIEBha2EgUGF0aCBvcHRpb25zXG4gIFx0b3B0aW9uczoge1xuICBcdFx0Ly8gQG9wdGlvbiBzdHJva2U6IEJvb2xlYW4gPSB0cnVlXG4gIFx0XHQvLyBXaGV0aGVyIHRvIGRyYXcgc3Ryb2tlIGFsb25nIHRoZSBwYXRoLiBTZXQgaXQgdG8gYGZhbHNlYCB0byBkaXNhYmxlIGJvcmRlcnMgb24gcG9seWdvbnMgb3IgY2lyY2xlcy5cbiAgXHRcdHN0cm9rZTogdHJ1ZSxcblxuICBcdFx0Ly8gQG9wdGlvbiBjb2xvcjogU3RyaW5nID0gJyMzMzg4ZmYnXG4gIFx0XHQvLyBTdHJva2UgY29sb3JcbiAgXHRcdGNvbG9yOiAnIzMzODhmZicsXG5cbiAgXHRcdC8vIEBvcHRpb24gd2VpZ2h0OiBOdW1iZXIgPSAzXG4gIFx0XHQvLyBTdHJva2Ugd2lkdGggaW4gcGl4ZWxzXG4gIFx0XHR3ZWlnaHQ6IDMsXG5cbiAgXHRcdC8vIEBvcHRpb24gb3BhY2l0eTogTnVtYmVyID0gMS4wXG4gIFx0XHQvLyBTdHJva2Ugb3BhY2l0eVxuICBcdFx0b3BhY2l0eTogMSxcblxuICBcdFx0Ly8gQG9wdGlvbiBsaW5lQ2FwOiBTdHJpbmc9ICdyb3VuZCdcbiAgXHRcdC8vIEEgc3RyaW5nIHRoYXQgZGVmaW5lcyBbc2hhcGUgdG8gYmUgdXNlZCBhdCB0aGUgZW5kXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9TVkcvQXR0cmlidXRlL3N0cm9rZS1saW5lY2FwKSBvZiB0aGUgc3Ryb2tlLlxuICBcdFx0bGluZUNhcDogJ3JvdW5kJyxcblxuICBcdFx0Ly8gQG9wdGlvbiBsaW5lSm9pbjogU3RyaW5nID0gJ3JvdW5kJ1xuICBcdFx0Ly8gQSBzdHJpbmcgdGhhdCBkZWZpbmVzIFtzaGFwZSB0byBiZSB1c2VkIGF0IHRoZSBjb3JuZXJzXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9TVkcvQXR0cmlidXRlL3N0cm9rZS1saW5lam9pbikgb2YgdGhlIHN0cm9rZS5cbiAgXHRcdGxpbmVKb2luOiAncm91bmQnLFxuXG4gIFx0XHQvLyBAb3B0aW9uIGRhc2hBcnJheTogU3RyaW5nID0gbnVsbFxuICBcdFx0Ly8gQSBzdHJpbmcgdGhhdCBkZWZpbmVzIHRoZSBzdHJva2UgW2Rhc2ggcGF0dGVybl0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvU1ZHL0F0dHJpYnV0ZS9zdHJva2UtZGFzaGFycmF5KS4gRG9lc24ndCB3b3JrIG9uIGBDYW52YXNgLXBvd2VyZWQgbGF5ZXJzIGluIFtzb21lIG9sZCBicm93c2Vyc10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQVBJL0NhbnZhc1JlbmRlcmluZ0NvbnRleHQyRC9zZXRMaW5lRGFzaCNCcm93c2VyX2NvbXBhdGliaWxpdHkpLlxuICBcdFx0ZGFzaEFycmF5OiBudWxsLFxuXG4gIFx0XHQvLyBAb3B0aW9uIGRhc2hPZmZzZXQ6IFN0cmluZyA9IG51bGxcbiAgXHRcdC8vIEEgc3RyaW5nIHRoYXQgZGVmaW5lcyB0aGUgW2Rpc3RhbmNlIGludG8gdGhlIGRhc2ggcGF0dGVybiB0byBzdGFydCB0aGUgZGFzaF0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvU1ZHL0F0dHJpYnV0ZS9zdHJva2UtZGFzaG9mZnNldCkuIERvZXNuJ3Qgd29yayBvbiBgQ2FudmFzYC1wb3dlcmVkIGxheWVycyBpbiBbc29tZSBvbGQgYnJvd3NlcnNdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0FQSS9DYW52YXNSZW5kZXJpbmdDb250ZXh0MkQvc2V0TGluZURhc2gjQnJvd3Nlcl9jb21wYXRpYmlsaXR5KS5cbiAgXHRcdGRhc2hPZmZzZXQ6IG51bGwsXG5cbiAgXHRcdC8vIEBvcHRpb24gZmlsbDogQm9vbGVhbiA9IGRlcGVuZHNcbiAgXHRcdC8vIFdoZXRoZXIgdG8gZmlsbCB0aGUgcGF0aCB3aXRoIGNvbG9yLiBTZXQgaXQgdG8gYGZhbHNlYCB0byBkaXNhYmxlIGZpbGxpbmcgb24gcG9seWdvbnMgb3IgY2lyY2xlcy5cbiAgXHRcdGZpbGw6IGZhbHNlLFxuXG4gIFx0XHQvLyBAb3B0aW9uIGZpbGxDb2xvcjogU3RyaW5nID0gKlxuICBcdFx0Ly8gRmlsbCBjb2xvci4gRGVmYXVsdHMgdG8gdGhlIHZhbHVlIG9mIHRoZSBbYGNvbG9yYF0oI3BhdGgtY29sb3IpIG9wdGlvblxuICBcdFx0ZmlsbENvbG9yOiBudWxsLFxuXG4gIFx0XHQvLyBAb3B0aW9uIGZpbGxPcGFjaXR5OiBOdW1iZXIgPSAwLjJcbiAgXHRcdC8vIEZpbGwgb3BhY2l0eS5cbiAgXHRcdGZpbGxPcGFjaXR5OiAwLjIsXG5cbiAgXHRcdC8vIEBvcHRpb24gZmlsbFJ1bGU6IFN0cmluZyA9ICdldmVub2RkJ1xuICBcdFx0Ly8gQSBzdHJpbmcgdGhhdCBkZWZpbmVzIFtob3cgdGhlIGluc2lkZSBvZiBhIHNoYXBlXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9TVkcvQXR0cmlidXRlL2ZpbGwtcnVsZSkgaXMgZGV0ZXJtaW5lZC5cbiAgXHRcdGZpbGxSdWxlOiAnZXZlbm9kZCcsXG5cbiAgXHRcdC8vIGNsYXNzTmFtZTogJycsXG5cbiAgXHRcdC8vIE9wdGlvbiBpbmhlcml0ZWQgZnJvbSBcIkludGVyYWN0aXZlIGxheWVyXCIgYWJzdHJhY3QgY2xhc3NcbiAgXHRcdGludGVyYWN0aXZlOiB0cnVlLFxuXG4gIFx0XHQvLyBAb3B0aW9uIGJ1YmJsaW5nTW91c2VFdmVudHM6IEJvb2xlYW4gPSB0cnVlXG4gIFx0XHQvLyBXaGVuIGB0cnVlYCwgYSBtb3VzZSBldmVudCBvbiB0aGlzIHBhdGggd2lsbCB0cmlnZ2VyIHRoZSBzYW1lIGV2ZW50IG9uIHRoZSBtYXBcbiAgXHRcdC8vICh1bmxlc3MgW2BMLkRvbUV2ZW50LnN0b3BQcm9wYWdhdGlvbmBdKCNkb21ldmVudC1zdG9wcHJvcGFnYXRpb24pIGlzIHVzZWQpLlxuICBcdFx0YnViYmxpbmdNb3VzZUV2ZW50czogdHJ1ZVxuICBcdH0sXG5cbiAgXHRiZWZvcmVBZGQ6IGZ1bmN0aW9uIChtYXApIHtcbiAgXHRcdC8vIFJlbmRlcmVyIGlzIHNldCBoZXJlIGJlY2F1c2Ugd2UgbmVlZCB0byBjYWxsIHJlbmRlcmVyLmdldEV2ZW50c1xuICBcdFx0Ly8gYmVmb3JlIHRoaXMuZ2V0RXZlbnRzLlxuICBcdFx0dGhpcy5fcmVuZGVyZXIgPSBtYXAuZ2V0UmVuZGVyZXIodGhpcyk7XG4gIFx0fSxcblxuICBcdG9uQWRkOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR0aGlzLl9yZW5kZXJlci5faW5pdFBhdGgodGhpcyk7XG4gIFx0XHR0aGlzLl9yZXNldCgpO1xuICBcdFx0dGhpcy5fcmVuZGVyZXIuX2FkZFBhdGgodGhpcyk7XG4gIFx0fSxcblxuICBcdG9uUmVtb3ZlOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR0aGlzLl9yZW5kZXJlci5fcmVtb3ZlUGF0aCh0aGlzKTtcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCByZWRyYXcoKTogdGhpc1xuICBcdC8vIFJlZHJhd3MgdGhlIGxheWVyLiBTb21ldGltZXMgdXNlZnVsIGFmdGVyIHlvdSBjaGFuZ2VkIHRoZSBjb29yZGluYXRlcyB0aGF0IHRoZSBwYXRoIHVzZXMuXG4gIFx0cmVkcmF3OiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRpZiAodGhpcy5fbWFwKSB7XG4gIFx0XHRcdHRoaXMuX3JlbmRlcmVyLl91cGRhdGVQYXRoKHRoaXMpO1xuICBcdFx0fVxuICBcdFx0cmV0dXJuIHRoaXM7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2Qgc2V0U3R5bGUoc3R5bGU6IFBhdGggb3B0aW9ucyk6IHRoaXNcbiAgXHQvLyBDaGFuZ2VzIHRoZSBhcHBlYXJhbmNlIG9mIGEgUGF0aCBiYXNlZCBvbiB0aGUgb3B0aW9ucyBpbiB0aGUgYFBhdGggb3B0aW9uc2Agb2JqZWN0LlxuICBcdHNldFN0eWxlOiBmdW5jdGlvbiAoc3R5bGUpIHtcbiAgXHRcdHNldE9wdGlvbnModGhpcywgc3R5bGUpO1xuICBcdFx0aWYgKHRoaXMuX3JlbmRlcmVyKSB7XG4gIFx0XHRcdHRoaXMuX3JlbmRlcmVyLl91cGRhdGVTdHlsZSh0aGlzKTtcbiAgXHRcdFx0aWYgKHRoaXMub3B0aW9ucy5zdHJva2UgJiYgc3R5bGUgJiYgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHN0eWxlLCAnd2VpZ2h0JykpIHtcbiAgXHRcdFx0XHR0aGlzLl91cGRhdGVCb3VuZHMoKTtcbiAgXHRcdFx0fVxuICBcdFx0fVxuICBcdFx0cmV0dXJuIHRoaXM7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgYnJpbmdUb0Zyb250KCk6IHRoaXNcbiAgXHQvLyBCcmluZ3MgdGhlIGxheWVyIHRvIHRoZSB0b3Agb2YgYWxsIHBhdGggbGF5ZXJzLlxuICBcdGJyaW5nVG9Gcm9udDogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKHRoaXMuX3JlbmRlcmVyKSB7XG4gIFx0XHRcdHRoaXMuX3JlbmRlcmVyLl9icmluZ1RvRnJvbnQodGhpcyk7XG4gIFx0XHR9XG4gIFx0XHRyZXR1cm4gdGhpcztcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBicmluZ1RvQmFjaygpOiB0aGlzXG4gIFx0Ly8gQnJpbmdzIHRoZSBsYXllciB0byB0aGUgYm90dG9tIG9mIGFsbCBwYXRoIGxheWVycy5cbiAgXHRicmluZ1RvQmFjazogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKHRoaXMuX3JlbmRlcmVyKSB7XG4gIFx0XHRcdHRoaXMuX3JlbmRlcmVyLl9icmluZ1RvQmFjayh0aGlzKTtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiB0aGlzO1xuICBcdH0sXG5cbiAgXHRnZXRFbGVtZW50OiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZXR1cm4gdGhpcy5fcGF0aDtcbiAgXHR9LFxuXG4gIFx0X3Jlc2V0OiBmdW5jdGlvbiAoKSB7XG4gIFx0XHQvLyBkZWZpbmVkIGluIGNoaWxkIGNsYXNzZXNcbiAgXHRcdHRoaXMuX3Byb2plY3QoKTtcbiAgXHRcdHRoaXMuX3VwZGF0ZSgpO1xuICBcdH0sXG5cbiAgXHRfY2xpY2tUb2xlcmFuY2U6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdC8vIHVzZWQgd2hlbiBkb2luZyBoaXQgZGV0ZWN0aW9uIGZvciBDYW52YXMgbGF5ZXJzXG4gIFx0XHRyZXR1cm4gKHRoaXMub3B0aW9ucy5zdHJva2UgPyB0aGlzLm9wdGlvbnMud2VpZ2h0IC8gMiA6IDApICtcbiAgXHRcdCAgKHRoaXMuX3JlbmRlcmVyLm9wdGlvbnMudG9sZXJhbmNlIHx8IDApO1xuICBcdH1cbiAgfSk7XG5cbiAgLypcbiAgICogQGNsYXNzIENpcmNsZU1hcmtlclxuICAgKiBAYWthIEwuQ2lyY2xlTWFya2VyXG4gICAqIEBpbmhlcml0cyBQYXRoXG4gICAqXG4gICAqIEEgY2lyY2xlIG9mIGEgZml4ZWQgc2l6ZSB3aXRoIHJhZGl1cyBzcGVjaWZpZWQgaW4gcGl4ZWxzLiBFeHRlbmRzIGBQYXRoYC5cbiAgICovXG5cbiAgdmFyIENpcmNsZU1hcmtlciA9IFBhdGguZXh0ZW5kKHtcblxuICBcdC8vIEBzZWN0aW9uXG4gIFx0Ly8gQGFrYSBDaXJjbGVNYXJrZXIgb3B0aW9uc1xuICBcdG9wdGlvbnM6IHtcbiAgXHRcdGZpbGw6IHRydWUsXG5cbiAgXHRcdC8vIEBvcHRpb24gcmFkaXVzOiBOdW1iZXIgPSAxMFxuICBcdFx0Ly8gUmFkaXVzIG9mIHRoZSBjaXJjbGUgbWFya2VyLCBpbiBwaXhlbHNcbiAgXHRcdHJhZGl1czogMTBcbiAgXHR9LFxuXG4gIFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKGxhdGxuZywgb3B0aW9ucykge1xuICBcdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcbiAgXHRcdHRoaXMuX2xhdGxuZyA9IHRvTGF0TG5nKGxhdGxuZyk7XG4gIFx0XHR0aGlzLl9yYWRpdXMgPSB0aGlzLm9wdGlvbnMucmFkaXVzO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIHNldExhdExuZyhsYXRMbmc6IExhdExuZyk6IHRoaXNcbiAgXHQvLyBTZXRzIHRoZSBwb3NpdGlvbiBvZiBhIGNpcmNsZSBtYXJrZXIgdG8gYSBuZXcgbG9jYXRpb24uXG4gIFx0c2V0TGF0TG5nOiBmdW5jdGlvbiAobGF0bG5nKSB7XG4gIFx0XHR2YXIgb2xkTGF0TG5nID0gdGhpcy5fbGF0bG5nO1xuICBcdFx0dGhpcy5fbGF0bG5nID0gdG9MYXRMbmcobGF0bG5nKTtcbiAgXHRcdHRoaXMucmVkcmF3KCk7XG5cbiAgXHRcdC8vIEBldmVudCBtb3ZlOiBFdmVudFxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbWFya2VyIGlzIG1vdmVkIHZpYSBbYHNldExhdExuZ2BdKCNjaXJjbGVtYXJrZXItc2V0bGF0bG5nKS4gT2xkIGFuZCBuZXcgY29vcmRpbmF0ZXMgYXJlIGluY2x1ZGVkIGluIGV2ZW50IGFyZ3VtZW50cyBhcyBgb2xkTGF0TG5nYCwgYGxhdGxuZ2AuXG4gIFx0XHRyZXR1cm4gdGhpcy5maXJlKCdtb3ZlJywge29sZExhdExuZzogb2xkTGF0TG5nLCBsYXRsbmc6IHRoaXMuX2xhdGxuZ30pO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIGdldExhdExuZygpOiBMYXRMbmdcbiAgXHQvLyBSZXR1cm5zIHRoZSBjdXJyZW50IGdlb2dyYXBoaWNhbCBwb3NpdGlvbiBvZiB0aGUgY2lyY2xlIG1hcmtlclxuICBcdGdldExhdExuZzogZnVuY3Rpb24gKCkge1xuICBcdFx0cmV0dXJuIHRoaXMuX2xhdGxuZztcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBzZXRSYWRpdXMocmFkaXVzOiBOdW1iZXIpOiB0aGlzXG4gIFx0Ly8gU2V0cyB0aGUgcmFkaXVzIG9mIGEgY2lyY2xlIG1hcmtlci4gVW5pdHMgYXJlIGluIHBpeGVscy5cbiAgXHRzZXRSYWRpdXM6IGZ1bmN0aW9uIChyYWRpdXMpIHtcbiAgXHRcdHRoaXMub3B0aW9ucy5yYWRpdXMgPSB0aGlzLl9yYWRpdXMgPSByYWRpdXM7XG4gIFx0XHRyZXR1cm4gdGhpcy5yZWRyYXcoKTtcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBnZXRSYWRpdXMoKTogTnVtYmVyXG4gIFx0Ly8gUmV0dXJucyB0aGUgY3VycmVudCByYWRpdXMgb2YgdGhlIGNpcmNsZVxuICBcdGdldFJhZGl1czogZnVuY3Rpb24gKCkge1xuICBcdFx0cmV0dXJuIHRoaXMuX3JhZGl1cztcbiAgXHR9LFxuXG4gIFx0c2V0U3R5bGUgOiBmdW5jdGlvbiAob3B0aW9ucykge1xuICBcdFx0dmFyIHJhZGl1cyA9IG9wdGlvbnMgJiYgb3B0aW9ucy5yYWRpdXMgfHwgdGhpcy5fcmFkaXVzO1xuICBcdFx0UGF0aC5wcm90b3R5cGUuc2V0U3R5bGUuY2FsbCh0aGlzLCBvcHRpb25zKTtcbiAgXHRcdHRoaXMuc2V0UmFkaXVzKHJhZGl1cyk7XG4gIFx0XHRyZXR1cm4gdGhpcztcbiAgXHR9LFxuXG4gIFx0X3Byb2plY3Q6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHRoaXMuX3BvaW50ID0gdGhpcy5fbWFwLmxhdExuZ1RvTGF5ZXJQb2ludCh0aGlzLl9sYXRsbmcpO1xuICBcdFx0dGhpcy5fdXBkYXRlQm91bmRzKCk7XG4gIFx0fSxcblxuICBcdF91cGRhdGVCb3VuZHM6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHZhciByID0gdGhpcy5fcmFkaXVzLFxuICBcdFx0ICAgIHIyID0gdGhpcy5fcmFkaXVzWSB8fCByLFxuICBcdFx0ICAgIHcgPSB0aGlzLl9jbGlja1RvbGVyYW5jZSgpLFxuICBcdFx0ICAgIHAgPSBbciArIHcsIHIyICsgd107XG4gIFx0XHR0aGlzLl9weEJvdW5kcyA9IG5ldyBCb3VuZHModGhpcy5fcG9pbnQuc3VidHJhY3QocCksIHRoaXMuX3BvaW50LmFkZChwKSk7XG4gIFx0fSxcblxuICBcdF91cGRhdGU6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICh0aGlzLl9tYXApIHtcbiAgXHRcdFx0dGhpcy5fdXBkYXRlUGF0aCgpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfdXBkYXRlUGF0aDogZnVuY3Rpb24gKCkge1xuICBcdFx0dGhpcy5fcmVuZGVyZXIuX3VwZGF0ZUNpcmNsZSh0aGlzKTtcbiAgXHR9LFxuXG4gIFx0X2VtcHR5OiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZXR1cm4gdGhpcy5fcmFkaXVzICYmICF0aGlzLl9yZW5kZXJlci5fYm91bmRzLmludGVyc2VjdHModGhpcy5fcHhCb3VuZHMpO1xuICBcdH0sXG5cbiAgXHQvLyBOZWVkZWQgYnkgdGhlIGBDYW52YXNgIHJlbmRlcmVyIGZvciBpbnRlcmFjdGl2aXR5XG4gIFx0X2NvbnRhaW5zUG9pbnQ6IGZ1bmN0aW9uIChwKSB7XG4gIFx0XHRyZXR1cm4gcC5kaXN0YW5jZVRvKHRoaXMuX3BvaW50KSA8PSB0aGlzLl9yYWRpdXMgKyB0aGlzLl9jbGlja1RvbGVyYW5jZSgpO1xuICBcdH1cbiAgfSk7XG5cblxuICAvLyBAZmFjdG9yeSBMLmNpcmNsZU1hcmtlcihsYXRsbmc6IExhdExuZywgb3B0aW9ucz86IENpcmNsZU1hcmtlciBvcHRpb25zKVxuICAvLyBJbnN0YW50aWF0ZXMgYSBjaXJjbGUgbWFya2VyIG9iamVjdCBnaXZlbiBhIGdlb2dyYXBoaWNhbCBwb2ludCwgYW5kIGFuIG9wdGlvbmFsIG9wdGlvbnMgb2JqZWN0LlxuICBmdW5jdGlvbiBjaXJjbGVNYXJrZXIobGF0bG5nLCBvcHRpb25zKSB7XG4gIFx0cmV0dXJuIG5ldyBDaXJjbGVNYXJrZXIobGF0bG5nLCBvcHRpb25zKTtcbiAgfVxuXG4gIC8qXG4gICAqIEBjbGFzcyBDaXJjbGVcbiAgICogQGFrYSBMLkNpcmNsZVxuICAgKiBAaW5oZXJpdHMgQ2lyY2xlTWFya2VyXG4gICAqXG4gICAqIEEgY2xhc3MgZm9yIGRyYXdpbmcgY2lyY2xlIG92ZXJsYXlzIG9uIGEgbWFwLiBFeHRlbmRzIGBDaXJjbGVNYXJrZXJgLlxuICAgKlxuICAgKiBJdCdzIGFuIGFwcHJveGltYXRpb24gYW5kIHN0YXJ0cyB0byBkaXZlcmdlIGZyb20gYSByZWFsIGNpcmNsZSBjbG9zZXIgdG8gcG9sZXMgKGR1ZSB0byBwcm9qZWN0aW9uIGRpc3RvcnRpb24pLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKlxuICAgKiBgYGBqc1xuICAgKiBMLmNpcmNsZShbNTAuNSwgMzAuNV0sIHtyYWRpdXM6IDIwMH0pLmFkZFRvKG1hcCk7XG4gICAqIGBgYFxuICAgKi9cblxuICB2YXIgQ2lyY2xlID0gQ2lyY2xlTWFya2VyLmV4dGVuZCh7XG5cbiAgXHRpbml0aWFsaXplOiBmdW5jdGlvbiAobGF0bG5nLCBvcHRpb25zLCBsZWdhY3lPcHRpb25zKSB7XG4gIFx0XHRpZiAodHlwZW9mIG9wdGlvbnMgPT09ICdudW1iZXInKSB7XG4gIFx0XHRcdC8vIEJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IHdpdGggMC43LnggZmFjdG9yeSAobGF0bG5nLCByYWRpdXMsIG9wdGlvbnM/KVxuICBcdFx0XHRvcHRpb25zID0gZXh0ZW5kKHt9LCBsZWdhY3lPcHRpb25zLCB7cmFkaXVzOiBvcHRpb25zfSk7XG4gIFx0XHR9XG4gIFx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xuICBcdFx0dGhpcy5fbGF0bG5nID0gdG9MYXRMbmcobGF0bG5nKTtcblxuICBcdFx0aWYgKGlzTmFOKHRoaXMub3B0aW9ucy5yYWRpdXMpKSB7IHRocm93IG5ldyBFcnJvcignQ2lyY2xlIHJhZGl1cyBjYW5ub3QgYmUgTmFOJyk7IH1cblxuICBcdFx0Ly8gQHNlY3Rpb25cbiAgXHRcdC8vIEBha2EgQ2lyY2xlIG9wdGlvbnNcbiAgXHRcdC8vIEBvcHRpb24gcmFkaXVzOiBOdW1iZXI7IFJhZGl1cyBvZiB0aGUgY2lyY2xlLCBpbiBtZXRlcnMuXG4gIFx0XHR0aGlzLl9tUmFkaXVzID0gdGhpcy5vcHRpb25zLnJhZGl1cztcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBzZXRSYWRpdXMocmFkaXVzOiBOdW1iZXIpOiB0aGlzXG4gIFx0Ly8gU2V0cyB0aGUgcmFkaXVzIG9mIGEgY2lyY2xlLiBVbml0cyBhcmUgaW4gbWV0ZXJzLlxuICBcdHNldFJhZGl1czogZnVuY3Rpb24gKHJhZGl1cykge1xuICBcdFx0dGhpcy5fbVJhZGl1cyA9IHJhZGl1cztcbiAgXHRcdHJldHVybiB0aGlzLnJlZHJhdygpO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIGdldFJhZGl1cygpOiBOdW1iZXJcbiAgXHQvLyBSZXR1cm5zIHRoZSBjdXJyZW50IHJhZGl1cyBvZiBhIGNpcmNsZS4gVW5pdHMgYXJlIGluIG1ldGVycy5cbiAgXHRnZXRSYWRpdXM6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHJldHVybiB0aGlzLl9tUmFkaXVzO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIGdldEJvdW5kcygpOiBMYXRMbmdCb3VuZHNcbiAgXHQvLyBSZXR1cm5zIHRoZSBgTGF0TG5nQm91bmRzYCBvZiB0aGUgcGF0aC5cbiAgXHRnZXRCb3VuZHM6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHZhciBoYWxmID0gW3RoaXMuX3JhZGl1cywgdGhpcy5fcmFkaXVzWSB8fCB0aGlzLl9yYWRpdXNdO1xuXG4gIFx0XHRyZXR1cm4gbmV3IExhdExuZ0JvdW5kcyhcbiAgXHRcdFx0dGhpcy5fbWFwLmxheWVyUG9pbnRUb0xhdExuZyh0aGlzLl9wb2ludC5zdWJ0cmFjdChoYWxmKSksXG4gIFx0XHRcdHRoaXMuX21hcC5sYXllclBvaW50VG9MYXRMbmcodGhpcy5fcG9pbnQuYWRkKGhhbGYpKSk7XG4gIFx0fSxcblxuICBcdHNldFN0eWxlOiBQYXRoLnByb3RvdHlwZS5zZXRTdHlsZSxcblxuICBcdF9wcm9qZWN0OiBmdW5jdGlvbiAoKSB7XG5cbiAgXHRcdHZhciBsbmcgPSB0aGlzLl9sYXRsbmcubG5nLFxuICBcdFx0ICAgIGxhdCA9IHRoaXMuX2xhdGxuZy5sYXQsXG4gIFx0XHQgICAgbWFwID0gdGhpcy5fbWFwLFxuICBcdFx0ICAgIGNycyA9IG1hcC5vcHRpb25zLmNycztcblxuICBcdFx0aWYgKGNycy5kaXN0YW5jZSA9PT0gRWFydGguZGlzdGFuY2UpIHtcbiAgXHRcdFx0dmFyIGQgPSBNYXRoLlBJIC8gMTgwLFxuICBcdFx0XHQgICAgbGF0UiA9ICh0aGlzLl9tUmFkaXVzIC8gRWFydGguUikgLyBkLFxuICBcdFx0XHQgICAgdG9wID0gbWFwLnByb2plY3QoW2xhdCArIGxhdFIsIGxuZ10pLFxuICBcdFx0XHQgICAgYm90dG9tID0gbWFwLnByb2plY3QoW2xhdCAtIGxhdFIsIGxuZ10pLFxuICBcdFx0XHQgICAgcCA9IHRvcC5hZGQoYm90dG9tKS5kaXZpZGVCeSgyKSxcbiAgXHRcdFx0ICAgIGxhdDIgPSBtYXAudW5wcm9qZWN0KHApLmxhdCxcbiAgXHRcdFx0ICAgIGxuZ1IgPSBNYXRoLmFjb3MoKE1hdGguY29zKGxhdFIgKiBkKSAtIE1hdGguc2luKGxhdCAqIGQpICogTWF0aC5zaW4obGF0MiAqIGQpKSAvXG4gIFx0XHRcdCAgICAgICAgICAgIChNYXRoLmNvcyhsYXQgKiBkKSAqIE1hdGguY29zKGxhdDIgKiBkKSkpIC8gZDtcblxuICBcdFx0XHRpZiAoaXNOYU4obG5nUikgfHwgbG5nUiA9PT0gMCkge1xuICBcdFx0XHRcdGxuZ1IgPSBsYXRSIC8gTWF0aC5jb3MoTWF0aC5QSSAvIDE4MCAqIGxhdCk7IC8vIEZhbGxiYWNrIGZvciBlZGdlIGNhc2UsICMyNDI1XG4gIFx0XHRcdH1cblxuICBcdFx0XHR0aGlzLl9wb2ludCA9IHAuc3VidHJhY3QobWFwLmdldFBpeGVsT3JpZ2luKCkpO1xuICBcdFx0XHR0aGlzLl9yYWRpdXMgPSBpc05hTihsbmdSKSA/IDAgOiBwLnggLSBtYXAucHJvamVjdChbbGF0MiwgbG5nIC0gbG5nUl0pLng7XG4gIFx0XHRcdHRoaXMuX3JhZGl1c1kgPSBwLnkgLSB0b3AueTtcblxuICBcdFx0fSBlbHNlIHtcbiAgXHRcdFx0dmFyIGxhdGxuZzIgPSBjcnMudW5wcm9qZWN0KGNycy5wcm9qZWN0KHRoaXMuX2xhdGxuZykuc3VidHJhY3QoW3RoaXMuX21SYWRpdXMsIDBdKSk7XG5cbiAgXHRcdFx0dGhpcy5fcG9pbnQgPSBtYXAubGF0TG5nVG9MYXllclBvaW50KHRoaXMuX2xhdGxuZyk7XG4gIFx0XHRcdHRoaXMuX3JhZGl1cyA9IHRoaXMuX3BvaW50LnggLSBtYXAubGF0TG5nVG9MYXllclBvaW50KGxhdGxuZzIpLng7XG4gIFx0XHR9XG5cbiAgXHRcdHRoaXMuX3VwZGF0ZUJvdW5kcygpO1xuICBcdH1cbiAgfSk7XG5cbiAgLy8gQGZhY3RvcnkgTC5jaXJjbGUobGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/OiBDaXJjbGUgb3B0aW9ucylcbiAgLy8gSW5zdGFudGlhdGVzIGEgY2lyY2xlIG9iamVjdCBnaXZlbiBhIGdlb2dyYXBoaWNhbCBwb2ludCwgYW5kIGFuIG9wdGlvbnMgb2JqZWN0XG4gIC8vIHdoaWNoIGNvbnRhaW5zIHRoZSBjaXJjbGUgcmFkaXVzLlxuICAvLyBAYWx0ZXJuYXRpdmVcbiAgLy8gQGZhY3RvcnkgTC5jaXJjbGUobGF0bG5nOiBMYXRMbmcsIHJhZGl1czogTnVtYmVyLCBvcHRpb25zPzogQ2lyY2xlIG9wdGlvbnMpXG4gIC8vIE9ic29sZXRlIHdheSBvZiBpbnN0YW50aWF0aW5nIGEgY2lyY2xlLCBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIDAuNy54IGNvZGUuXG4gIC8vIERvIG5vdCB1c2UgaW4gbmV3IGFwcGxpY2F0aW9ucyBvciBwbHVnaW5zLlxuICBmdW5jdGlvbiBjaXJjbGUobGF0bG5nLCBvcHRpb25zLCBsZWdhY3lPcHRpb25zKSB7XG4gIFx0cmV0dXJuIG5ldyBDaXJjbGUobGF0bG5nLCBvcHRpb25zLCBsZWdhY3lPcHRpb25zKTtcbiAgfVxuXG4gIC8qXG4gICAqIEBjbGFzcyBQb2x5bGluZVxuICAgKiBAYWthIEwuUG9seWxpbmVcbiAgICogQGluaGVyaXRzIFBhdGhcbiAgICpcbiAgICogQSBjbGFzcyBmb3IgZHJhd2luZyBwb2x5bGluZSBvdmVybGF5cyBvbiBhIG1hcC4gRXh0ZW5kcyBgUGF0aGAuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqIGBgYGpzXG4gICAqIC8vIGNyZWF0ZSBhIHJlZCBwb2x5bGluZSBmcm9tIGFuIGFycmF5IG9mIExhdExuZyBwb2ludHNcbiAgICogdmFyIGxhdGxuZ3MgPSBbXG4gICAqIFx0WzQ1LjUxLCAtMTIyLjY4XSxcbiAgICogXHRbMzcuNzcsIC0xMjIuNDNdLFxuICAgKiBcdFszNC4wNCwgLTExOC4yXVxuICAgKiBdO1xuICAgKlxuICAgKiB2YXIgcG9seWxpbmUgPSBMLnBvbHlsaW5lKGxhdGxuZ3MsIHtjb2xvcjogJ3JlZCd9KS5hZGRUbyhtYXApO1xuICAgKlxuICAgKiAvLyB6b29tIHRoZSBtYXAgdG8gdGhlIHBvbHlsaW5lXG4gICAqIG1hcC5maXRCb3VuZHMocG9seWxpbmUuZ2V0Qm91bmRzKCkpO1xuICAgKiBgYGBcbiAgICpcbiAgICogWW91IGNhbiBhbHNvIHBhc3MgYSBtdWx0aS1kaW1lbnNpb25hbCBhcnJheSB0byByZXByZXNlbnQgYSBgTXVsdGlQb2x5bGluZWAgc2hhcGU6XG4gICAqXG4gICAqIGBgYGpzXG4gICAqIC8vIGNyZWF0ZSBhIHJlZCBwb2x5bGluZSBmcm9tIGFuIGFycmF5IG9mIGFycmF5cyBvZiBMYXRMbmcgcG9pbnRzXG4gICAqIHZhciBsYXRsbmdzID0gW1xuICAgKiBcdFtbNDUuNTEsIC0xMjIuNjhdLFxuICAgKiBcdCBbMzcuNzcsIC0xMjIuNDNdLFxuICAgKiBcdCBbMzQuMDQsIC0xMTguMl1dLFxuICAgKiBcdFtbNDAuNzgsIC03My45MV0sXG4gICAqIFx0IFs0MS44MywgLTg3LjYyXSxcbiAgICogXHQgWzMyLjc2LCAtOTYuNzJdXVxuICAgKiBdO1xuICAgKiBgYGBcbiAgICovXG5cblxuICB2YXIgUG9seWxpbmUgPSBQYXRoLmV4dGVuZCh7XG5cbiAgXHQvLyBAc2VjdGlvblxuICBcdC8vIEBha2EgUG9seWxpbmUgb3B0aW9uc1xuICBcdG9wdGlvbnM6IHtcbiAgXHRcdC8vIEBvcHRpb24gc21vb3RoRmFjdG9yOiBOdW1iZXIgPSAxLjBcbiAgXHRcdC8vIEhvdyBtdWNoIHRvIHNpbXBsaWZ5IHRoZSBwb2x5bGluZSBvbiBlYWNoIHpvb20gbGV2ZWwuIE1vcmUgbWVhbnNcbiAgXHRcdC8vIGJldHRlciBwZXJmb3JtYW5jZSBhbmQgc21vb3RoZXIgbG9vaywgYW5kIGxlc3MgbWVhbnMgbW9yZSBhY2N1cmF0ZSByZXByZXNlbnRhdGlvbi5cbiAgXHRcdHNtb290aEZhY3RvcjogMS4wLFxuXG4gIFx0XHQvLyBAb3B0aW9uIG5vQ2xpcDogQm9vbGVhbiA9IGZhbHNlXG4gIFx0XHQvLyBEaXNhYmxlIHBvbHlsaW5lIGNsaXBwaW5nLlxuICBcdFx0bm9DbGlwOiBmYWxzZVxuICBcdH0sXG5cbiAgXHRpbml0aWFsaXplOiBmdW5jdGlvbiAobGF0bG5ncywgb3B0aW9ucykge1xuICBcdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcbiAgXHRcdHRoaXMuX3NldExhdExuZ3MobGF0bG5ncyk7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgZ2V0TGF0TG5ncygpOiBMYXRMbmdbXVxuICBcdC8vIFJldHVybnMgYW4gYXJyYXkgb2YgdGhlIHBvaW50cyBpbiB0aGUgcGF0aCwgb3IgbmVzdGVkIGFycmF5cyBvZiBwb2ludHMgaW4gY2FzZSBvZiBtdWx0aS1wb2x5bGluZS5cbiAgXHRnZXRMYXRMbmdzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZXR1cm4gdGhpcy5fbGF0bG5ncztcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBzZXRMYXRMbmdzKGxhdGxuZ3M6IExhdExuZ1tdKTogdGhpc1xuICBcdC8vIFJlcGxhY2VzIGFsbCB0aGUgcG9pbnRzIGluIHRoZSBwb2x5bGluZSB3aXRoIHRoZSBnaXZlbiBhcnJheSBvZiBnZW9ncmFwaGljYWwgcG9pbnRzLlxuICBcdHNldExhdExuZ3M6IGZ1bmN0aW9uIChsYXRsbmdzKSB7XG4gIFx0XHR0aGlzLl9zZXRMYXRMbmdzKGxhdGxuZ3MpO1xuICBcdFx0cmV0dXJuIHRoaXMucmVkcmF3KCk7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgaXNFbXB0eSgpOiBCb29sZWFuXG4gIFx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIFBvbHlsaW5lIGhhcyBubyBMYXRMbmdzLlxuICBcdGlzRW1wdHk6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHJldHVybiAhdGhpcy5fbGF0bG5ncy5sZW5ndGg7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgY2xvc2VzdExheWVyUG9pbnQocDogUG9pbnQpOiBQb2ludFxuICBcdC8vIFJldHVybnMgdGhlIHBvaW50IGNsb3Nlc3QgdG8gYHBgIG9uIHRoZSBQb2x5bGluZS5cbiAgXHRjbG9zZXN0TGF5ZXJQb2ludDogZnVuY3Rpb24gKHApIHtcbiAgXHRcdHZhciBtaW5EaXN0YW5jZSA9IEluZmluaXR5LFxuICBcdFx0ICAgIG1pblBvaW50ID0gbnVsbCxcbiAgXHRcdCAgICBjbG9zZXN0ID0gX3NxQ2xvc2VzdFBvaW50T25TZWdtZW50LFxuICBcdFx0ICAgIHAxLCBwMjtcblxuICBcdFx0Zm9yICh2YXIgaiA9IDAsIGpMZW4gPSB0aGlzLl9wYXJ0cy5sZW5ndGg7IGogPCBqTGVuOyBqKyspIHtcbiAgXHRcdFx0dmFyIHBvaW50cyA9IHRoaXMuX3BhcnRzW2pdO1xuXG4gIFx0XHRcdGZvciAodmFyIGkgPSAxLCBsZW4gPSBwb2ludHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgXHRcdFx0XHRwMSA9IHBvaW50c1tpIC0gMV07XG4gIFx0XHRcdFx0cDIgPSBwb2ludHNbaV07XG5cbiAgXHRcdFx0XHR2YXIgc3FEaXN0ID0gY2xvc2VzdChwLCBwMSwgcDIsIHRydWUpO1xuXG4gIFx0XHRcdFx0aWYgKHNxRGlzdCA8IG1pbkRpc3RhbmNlKSB7XG4gIFx0XHRcdFx0XHRtaW5EaXN0YW5jZSA9IHNxRGlzdDtcbiAgXHRcdFx0XHRcdG1pblBvaW50ID0gY2xvc2VzdChwLCBwMSwgcDIpO1xuICBcdFx0XHRcdH1cbiAgXHRcdFx0fVxuICBcdFx0fVxuICBcdFx0aWYgKG1pblBvaW50KSB7XG4gIFx0XHRcdG1pblBvaW50LmRpc3RhbmNlID0gTWF0aC5zcXJ0KG1pbkRpc3RhbmNlKTtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiBtaW5Qb2ludDtcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBnZXRDZW50ZXIoKTogTGF0TG5nXG4gIFx0Ly8gUmV0dXJucyB0aGUgY2VudGVyIChbY2VudHJvaWRdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NlbnRyb2lkKSkgb2YgdGhlIHBvbHlsaW5lLlxuICBcdGdldENlbnRlcjogZnVuY3Rpb24gKCkge1xuICBcdFx0Ly8gdGhyb3dzIGVycm9yIHdoZW4gbm90IHlldCBhZGRlZCB0byBtYXAgYXMgdGhpcyBjZW50ZXIgY2FsY3VsYXRpb24gcmVxdWlyZXMgcHJvamVjdGVkIGNvb3JkaW5hdGVzXG4gIFx0XHRpZiAoIXRoaXMuX21hcCkge1xuICBcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ011c3QgYWRkIGxheWVyIHRvIG1hcCBiZWZvcmUgdXNpbmcgZ2V0Q2VudGVyKCknKTtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiBwb2x5bGluZUNlbnRlcih0aGlzLl9kZWZhdWx0U2hhcGUoKSwgdGhpcy5fbWFwLm9wdGlvbnMuY3JzKTtcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBnZXRCb3VuZHMoKTogTGF0TG5nQm91bmRzXG4gIFx0Ly8gUmV0dXJucyB0aGUgYExhdExuZ0JvdW5kc2Agb2YgdGhlIHBhdGguXG4gIFx0Z2V0Qm91bmRzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZXR1cm4gdGhpcy5fYm91bmRzO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIGFkZExhdExuZyhsYXRsbmc6IExhdExuZywgbGF0bG5ncz86IExhdExuZ1tdKTogdGhpc1xuICBcdC8vIEFkZHMgYSBnaXZlbiBwb2ludCB0byB0aGUgcG9seWxpbmUuIEJ5IGRlZmF1bHQsIGFkZHMgdG8gdGhlIGZpcnN0IHJpbmcgb2ZcbiAgXHQvLyB0aGUgcG9seWxpbmUgaW4gY2FzZSBvZiBhIG11bHRpLXBvbHlsaW5lLCBidXQgY2FuIGJlIG92ZXJyaWRkZW4gYnkgcGFzc2luZ1xuICBcdC8vIGEgc3BlY2lmaWMgcmluZyBhcyBhIExhdExuZyBhcnJheSAodGhhdCB5b3UgY2FuIGVhcmxpZXIgYWNjZXNzIHdpdGggW2BnZXRMYXRMbmdzYF0oI3BvbHlsaW5lLWdldGxhdGxuZ3MpKS5cbiAgXHRhZGRMYXRMbmc6IGZ1bmN0aW9uIChsYXRsbmcsIGxhdGxuZ3MpIHtcbiAgXHRcdGxhdGxuZ3MgPSBsYXRsbmdzIHx8IHRoaXMuX2RlZmF1bHRTaGFwZSgpO1xuICBcdFx0bGF0bG5nID0gdG9MYXRMbmcobGF0bG5nKTtcbiAgXHRcdGxhdGxuZ3MucHVzaChsYXRsbmcpO1xuICBcdFx0dGhpcy5fYm91bmRzLmV4dGVuZChsYXRsbmcpO1xuICBcdFx0cmV0dXJuIHRoaXMucmVkcmF3KCk7XG4gIFx0fSxcblxuICBcdF9zZXRMYXRMbmdzOiBmdW5jdGlvbiAobGF0bG5ncykge1xuICBcdFx0dGhpcy5fYm91bmRzID0gbmV3IExhdExuZ0JvdW5kcygpO1xuICBcdFx0dGhpcy5fbGF0bG5ncyA9IHRoaXMuX2NvbnZlcnRMYXRMbmdzKGxhdGxuZ3MpO1xuICBcdH0sXG5cbiAgXHRfZGVmYXVsdFNoYXBlOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZXR1cm4gaXNGbGF0KHRoaXMuX2xhdGxuZ3MpID8gdGhpcy5fbGF0bG5ncyA6IHRoaXMuX2xhdGxuZ3NbMF07XG4gIFx0fSxcblxuICBcdC8vIHJlY3Vyc2l2ZWx5IGNvbnZlcnQgbGF0bG5ncyBpbnB1dCBpbnRvIGFjdHVhbCBMYXRMbmcgaW5zdGFuY2VzOyBjYWxjdWxhdGUgYm91bmRzIGFsb25nIHRoZSB3YXlcbiAgXHRfY29udmVydExhdExuZ3M6IGZ1bmN0aW9uIChsYXRsbmdzKSB7XG4gIFx0XHR2YXIgcmVzdWx0ID0gW10sXG4gIFx0XHQgICAgZmxhdCA9IGlzRmxhdChsYXRsbmdzKTtcblxuICBcdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IGxhdGxuZ3MubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgXHRcdFx0aWYgKGZsYXQpIHtcbiAgXHRcdFx0XHRyZXN1bHRbaV0gPSB0b0xhdExuZyhsYXRsbmdzW2ldKTtcbiAgXHRcdFx0XHR0aGlzLl9ib3VuZHMuZXh0ZW5kKHJlc3VsdFtpXSk7XG4gIFx0XHRcdH0gZWxzZSB7XG4gIFx0XHRcdFx0cmVzdWx0W2ldID0gdGhpcy5fY29udmVydExhdExuZ3MobGF0bG5nc1tpXSk7XG4gIFx0XHRcdH1cbiAgXHRcdH1cblxuICBcdFx0cmV0dXJuIHJlc3VsdDtcbiAgXHR9LFxuXG4gIFx0X3Byb2plY3Q6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHZhciBweEJvdW5kcyA9IG5ldyBCb3VuZHMoKTtcbiAgXHRcdHRoaXMuX3JpbmdzID0gW107XG4gIFx0XHR0aGlzLl9wcm9qZWN0TGF0bG5ncyh0aGlzLl9sYXRsbmdzLCB0aGlzLl9yaW5ncywgcHhCb3VuZHMpO1xuXG4gIFx0XHRpZiAodGhpcy5fYm91bmRzLmlzVmFsaWQoKSAmJiBweEJvdW5kcy5pc1ZhbGlkKCkpIHtcbiAgXHRcdFx0dGhpcy5fcmF3UHhCb3VuZHMgPSBweEJvdW5kcztcbiAgXHRcdFx0dGhpcy5fdXBkYXRlQm91bmRzKCk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF91cGRhdGVCb3VuZHM6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHZhciB3ID0gdGhpcy5fY2xpY2tUb2xlcmFuY2UoKSxcbiAgXHRcdCAgICBwID0gbmV3IFBvaW50KHcsIHcpO1xuXG4gIFx0XHRpZiAoIXRoaXMuX3Jhd1B4Qm91bmRzKSB7XG4gIFx0XHRcdHJldHVybjtcbiAgXHRcdH1cblxuICBcdFx0dGhpcy5fcHhCb3VuZHMgPSBuZXcgQm91bmRzKFtcbiAgXHRcdFx0dGhpcy5fcmF3UHhCb3VuZHMubWluLnN1YnRyYWN0KHApLFxuICBcdFx0XHR0aGlzLl9yYXdQeEJvdW5kcy5tYXguYWRkKHApXG4gIFx0XHRdKTtcbiAgXHR9LFxuXG4gIFx0Ly8gcmVjdXJzaXZlbHkgdHVybnMgbGF0bG5ncyBpbnRvIGEgc2V0IG9mIHJpbmdzIHdpdGggcHJvamVjdGVkIGNvb3JkaW5hdGVzXG4gIFx0X3Byb2plY3RMYXRsbmdzOiBmdW5jdGlvbiAobGF0bG5ncywgcmVzdWx0LCBwcm9qZWN0ZWRCb3VuZHMpIHtcbiAgXHRcdHZhciBmbGF0ID0gbGF0bG5nc1swXSBpbnN0YW5jZW9mIExhdExuZyxcbiAgXHRcdCAgICBsZW4gPSBsYXRsbmdzLmxlbmd0aCxcbiAgXHRcdCAgICBpLCByaW5nO1xuXG4gIFx0XHRpZiAoZmxhdCkge1xuICBcdFx0XHRyaW5nID0gW107XG4gIFx0XHRcdGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICBcdFx0XHRcdHJpbmdbaV0gPSB0aGlzLl9tYXAubGF0TG5nVG9MYXllclBvaW50KGxhdGxuZ3NbaV0pO1xuICBcdFx0XHRcdHByb2plY3RlZEJvdW5kcy5leHRlbmQocmluZ1tpXSk7XG4gIFx0XHRcdH1cbiAgXHRcdFx0cmVzdWx0LnB1c2gocmluZyk7XG4gIFx0XHR9IGVsc2Uge1xuICBcdFx0XHRmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgXHRcdFx0XHR0aGlzLl9wcm9qZWN0TGF0bG5ncyhsYXRsbmdzW2ldLCByZXN1bHQsIHByb2plY3RlZEJvdW5kcyk7XG4gIFx0XHRcdH1cbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0Ly8gY2xpcCBwb2x5bGluZSBieSByZW5kZXJlciBib3VuZHMgc28gdGhhdCB3ZSBoYXZlIGxlc3MgdG8gcmVuZGVyIGZvciBwZXJmb3JtYW5jZVxuICBcdF9jbGlwUG9pbnRzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR2YXIgYm91bmRzID0gdGhpcy5fcmVuZGVyZXIuX2JvdW5kcztcblxuICBcdFx0dGhpcy5fcGFydHMgPSBbXTtcbiAgXHRcdGlmICghdGhpcy5fcHhCb3VuZHMgfHwgIXRoaXMuX3B4Qm91bmRzLmludGVyc2VjdHMoYm91bmRzKSkge1xuICBcdFx0XHRyZXR1cm47XG4gIFx0XHR9XG5cbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMubm9DbGlwKSB7XG4gIFx0XHRcdHRoaXMuX3BhcnRzID0gdGhpcy5fcmluZ3M7XG4gIFx0XHRcdHJldHVybjtcbiAgXHRcdH1cblxuICBcdFx0dmFyIHBhcnRzID0gdGhpcy5fcGFydHMsXG4gIFx0XHQgICAgaSwgaiwgaywgbGVuLCBsZW4yLCBzZWdtZW50LCBwb2ludHM7XG5cbiAgXHRcdGZvciAoaSA9IDAsIGsgPSAwLCBsZW4gPSB0aGlzLl9yaW5ncy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICBcdFx0XHRwb2ludHMgPSB0aGlzLl9yaW5nc1tpXTtcblxuICBcdFx0XHRmb3IgKGogPSAwLCBsZW4yID0gcG9pbnRzLmxlbmd0aDsgaiA8IGxlbjIgLSAxOyBqKyspIHtcbiAgXHRcdFx0XHRzZWdtZW50ID0gY2xpcFNlZ21lbnQocG9pbnRzW2pdLCBwb2ludHNbaiArIDFdLCBib3VuZHMsIGosIHRydWUpO1xuXG4gIFx0XHRcdFx0aWYgKCFzZWdtZW50KSB7IGNvbnRpbnVlOyB9XG5cbiAgXHRcdFx0XHRwYXJ0c1trXSA9IHBhcnRzW2tdIHx8IFtdO1xuICBcdFx0XHRcdHBhcnRzW2tdLnB1c2goc2VnbWVudFswXSk7XG5cbiAgXHRcdFx0XHQvLyBpZiBzZWdtZW50IGdvZXMgb3V0IG9mIHNjcmVlbiwgb3IgaXQncyB0aGUgbGFzdCBvbmUsIGl0J3MgdGhlIGVuZCBvZiB0aGUgbGluZSBwYXJ0XG4gIFx0XHRcdFx0aWYgKChzZWdtZW50WzFdICE9PSBwb2ludHNbaiArIDFdKSB8fCAoaiA9PT0gbGVuMiAtIDIpKSB7XG4gIFx0XHRcdFx0XHRwYXJ0c1trXS5wdXNoKHNlZ21lbnRbMV0pO1xuICBcdFx0XHRcdFx0aysrO1xuICBcdFx0XHRcdH1cbiAgXHRcdFx0fVxuICBcdFx0fVxuICBcdH0sXG5cbiAgXHQvLyBzaW1wbGlmeSBlYWNoIGNsaXBwZWQgcGFydCBvZiB0aGUgcG9seWxpbmUgZm9yIHBlcmZvcm1hbmNlXG4gIFx0X3NpbXBsaWZ5UG9pbnRzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR2YXIgcGFydHMgPSB0aGlzLl9wYXJ0cyxcbiAgXHRcdCAgICB0b2xlcmFuY2UgPSB0aGlzLm9wdGlvbnMuc21vb3RoRmFjdG9yO1xuXG4gIFx0XHRmb3IgKHZhciBpID0gMCwgbGVuID0gcGFydHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgXHRcdFx0cGFydHNbaV0gPSBzaW1wbGlmeShwYXJ0c1tpXSwgdG9sZXJhbmNlKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZTogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKCF0aGlzLl9tYXApIHsgcmV0dXJuOyB9XG5cbiAgXHRcdHRoaXMuX2NsaXBQb2ludHMoKTtcbiAgXHRcdHRoaXMuX3NpbXBsaWZ5UG9pbnRzKCk7XG4gIFx0XHR0aGlzLl91cGRhdGVQYXRoKCk7XG4gIFx0fSxcblxuICBcdF91cGRhdGVQYXRoOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR0aGlzLl9yZW5kZXJlci5fdXBkYXRlUG9seSh0aGlzKTtcbiAgXHR9LFxuXG4gIFx0Ly8gTmVlZGVkIGJ5IHRoZSBgQ2FudmFzYCByZW5kZXJlciBmb3IgaW50ZXJhY3Rpdml0eVxuICBcdF9jb250YWluc1BvaW50OiBmdW5jdGlvbiAocCwgY2xvc2VkKSB7XG4gIFx0XHR2YXIgaSwgaiwgaywgbGVuLCBsZW4yLCBwYXJ0LFxuICBcdFx0ICAgIHcgPSB0aGlzLl9jbGlja1RvbGVyYW5jZSgpO1xuXG4gIFx0XHRpZiAoIXRoaXMuX3B4Qm91bmRzIHx8ICF0aGlzLl9weEJvdW5kcy5jb250YWlucyhwKSkgeyByZXR1cm4gZmFsc2U7IH1cblxuICBcdFx0Ly8gaGl0IGRldGVjdGlvbiBmb3IgcG9seWxpbmVzXG4gIFx0XHRmb3IgKGkgPSAwLCBsZW4gPSB0aGlzLl9wYXJ0cy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICBcdFx0XHRwYXJ0ID0gdGhpcy5fcGFydHNbaV07XG5cbiAgXHRcdFx0Zm9yIChqID0gMCwgbGVuMiA9IHBhcnQubGVuZ3RoLCBrID0gbGVuMiAtIDE7IGogPCBsZW4yOyBrID0gaisrKSB7XG4gIFx0XHRcdFx0aWYgKCFjbG9zZWQgJiYgKGogPT09IDApKSB7IGNvbnRpbnVlOyB9XG5cbiAgXHRcdFx0XHRpZiAocG9pbnRUb1NlZ21lbnREaXN0YW5jZShwLCBwYXJ0W2tdLCBwYXJ0W2pdKSA8PSB3KSB7XG4gIFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcbiAgXHRcdFx0XHR9XG4gIFx0XHRcdH1cbiAgXHRcdH1cbiAgXHRcdHJldHVybiBmYWxzZTtcbiAgXHR9XG4gIH0pO1xuXG4gIC8vIEBmYWN0b3J5IEwucG9seWxpbmUobGF0bG5nczogTGF0TG5nW10sIG9wdGlvbnM/OiBQb2x5bGluZSBvcHRpb25zKVxuICAvLyBJbnN0YW50aWF0ZXMgYSBwb2x5bGluZSBvYmplY3QgZ2l2ZW4gYW4gYXJyYXkgb2YgZ2VvZ3JhcGhpY2FsIHBvaW50cyBhbmRcbiAgLy8gb3B0aW9uYWxseSBhbiBvcHRpb25zIG9iamVjdC4gWW91IGNhbiBjcmVhdGUgYSBgUG9seWxpbmVgIG9iamVjdCB3aXRoXG4gIC8vIG11bHRpcGxlIHNlcGFyYXRlIGxpbmVzIChgTXVsdGlQb2x5bGluZWApIGJ5IHBhc3NpbmcgYW4gYXJyYXkgb2YgYXJyYXlzXG4gIC8vIG9mIGdlb2dyYXBoaWMgcG9pbnRzLlxuICBmdW5jdGlvbiBwb2x5bGluZShsYXRsbmdzLCBvcHRpb25zKSB7XG4gIFx0cmV0dXJuIG5ldyBQb2x5bGluZShsYXRsbmdzLCBvcHRpb25zKTtcbiAgfVxuXG4gIC8vIFJldHJvY29tcGF0LiBBbGxvdyBwbHVnaW5zIHRvIHN1cHBvcnQgTGVhZmxldCB2ZXJzaW9ucyBiZWZvcmUgYW5kIGFmdGVyIDEuMS5cbiAgUG9seWxpbmUuX2ZsYXQgPSBfZmxhdDtcblxuICAvKlxuICAgKiBAY2xhc3MgUG9seWdvblxuICAgKiBAYWthIEwuUG9seWdvblxuICAgKiBAaW5oZXJpdHMgUG9seWxpbmVcbiAgICpcbiAgICogQSBjbGFzcyBmb3IgZHJhd2luZyBwb2x5Z29uIG92ZXJsYXlzIG9uIGEgbWFwLiBFeHRlbmRzIGBQb2x5bGluZWAuXG4gICAqXG4gICAqIE5vdGUgdGhhdCBwb2ludHMgeW91IHBhc3Mgd2hlbiBjcmVhdGluZyBhIHBvbHlnb24gc2hvdWxkbid0IGhhdmUgYW4gYWRkaXRpb25hbCBsYXN0IHBvaW50IGVxdWFsIHRvIHRoZSBmaXJzdCBvbmUg4oCUIGl0J3MgYmV0dGVyIHRvIGZpbHRlciBvdXQgc3VjaCBwb2ludHMuXG4gICAqXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqIGBgYGpzXG4gICAqIC8vIGNyZWF0ZSBhIHJlZCBwb2x5Z29uIGZyb20gYW4gYXJyYXkgb2YgTGF0TG5nIHBvaW50c1xuICAgKiB2YXIgbGF0bG5ncyA9IFtbMzcsIC0xMDkuMDVdLFs0MSwgLTEwOS4wM10sWzQxLCAtMTAyLjA1XSxbMzcsIC0xMDIuMDRdXTtcbiAgICpcbiAgICogdmFyIHBvbHlnb24gPSBMLnBvbHlnb24obGF0bG5ncywge2NvbG9yOiAncmVkJ30pLmFkZFRvKG1hcCk7XG4gICAqXG4gICAqIC8vIHpvb20gdGhlIG1hcCB0byB0aGUgcG9seWdvblxuICAgKiBtYXAuZml0Qm91bmRzKHBvbHlnb24uZ2V0Qm91bmRzKCkpO1xuICAgKiBgYGBcbiAgICpcbiAgICogWW91IGNhbiBhbHNvIHBhc3MgYW4gYXJyYXkgb2YgYXJyYXlzIG9mIGxhdGxuZ3MsIHdpdGggdGhlIGZpcnN0IGFycmF5IHJlcHJlc2VudGluZyB0aGUgb3V0ZXIgc2hhcGUgYW5kIHRoZSBvdGhlciBhcnJheXMgcmVwcmVzZW50aW5nIGhvbGVzIGluIHRoZSBvdXRlciBzaGFwZTpcbiAgICpcbiAgICogYGBganNcbiAgICogdmFyIGxhdGxuZ3MgPSBbXG4gICAqICAgW1szNywgLTEwOS4wNV0sWzQxLCAtMTA5LjAzXSxbNDEsIC0xMDIuMDVdLFszNywgLTEwMi4wNF1dLCAvLyBvdXRlciByaW5nXG4gICAqICAgW1szNy4yOSwgLTEwOC41OF0sWzQwLjcxLCAtMTA4LjU4XSxbNDAuNzEsIC0xMDIuNTBdLFszNy4yOSwgLTEwMi41MF1dIC8vIGhvbGVcbiAgICogXTtcbiAgICogYGBgXG4gICAqXG4gICAqIEFkZGl0aW9uYWxseSwgeW91IGNhbiBwYXNzIGEgbXVsdGktZGltZW5zaW9uYWwgYXJyYXkgdG8gcmVwcmVzZW50IGEgTXVsdGlQb2x5Z29uIHNoYXBlLlxuICAgKlxuICAgKiBgYGBqc1xuICAgKiB2YXIgbGF0bG5ncyA9IFtcbiAgICogICBbIC8vIGZpcnN0IHBvbHlnb25cbiAgICogICAgIFtbMzcsIC0xMDkuMDVdLFs0MSwgLTEwOS4wM10sWzQxLCAtMTAyLjA1XSxbMzcsIC0xMDIuMDRdXSwgLy8gb3V0ZXIgcmluZ1xuICAgKiAgICAgW1szNy4yOSwgLTEwOC41OF0sWzQwLjcxLCAtMTA4LjU4XSxbNDAuNzEsIC0xMDIuNTBdLFszNy4yOSwgLTEwMi41MF1dIC8vIGhvbGVcbiAgICogICBdLFxuICAgKiAgIFsgLy8gc2Vjb25kIHBvbHlnb25cbiAgICogICAgIFtbNDEsIC0xMTEuMDNdLFs0NSwgLTExMS4wNF0sWzQ1LCAtMTA0LjA1XSxbNDEsIC0xMDQuMDVdXVxuICAgKiAgIF1cbiAgICogXTtcbiAgICogYGBgXG4gICAqL1xuXG4gIHZhciBQb2x5Z29uID0gUG9seWxpbmUuZXh0ZW5kKHtcblxuICBcdG9wdGlvbnM6IHtcbiAgXHRcdGZpbGw6IHRydWVcbiAgXHR9LFxuXG4gIFx0aXNFbXB0eTogZnVuY3Rpb24gKCkge1xuICBcdFx0cmV0dXJuICF0aGlzLl9sYXRsbmdzLmxlbmd0aCB8fCAhdGhpcy5fbGF0bG5nc1swXS5sZW5ndGg7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgZ2V0Q2VudGVyKCk6IExhdExuZ1xuICBcdC8vIFJldHVybnMgdGhlIGNlbnRlciAoW2NlbnRyb2lkXShodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NlbnRyb2lkKSkgb2YgdGhlIFBvbHlnb24uXG4gIFx0Z2V0Q2VudGVyOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHQvLyB0aHJvd3MgZXJyb3Igd2hlbiBub3QgeWV0IGFkZGVkIHRvIG1hcCBhcyB0aGlzIGNlbnRlciBjYWxjdWxhdGlvbiByZXF1aXJlcyBwcm9qZWN0ZWQgY29vcmRpbmF0ZXNcbiAgXHRcdGlmICghdGhpcy5fbWFwKSB7XG4gIFx0XHRcdHRocm93IG5ldyBFcnJvcignTXVzdCBhZGQgbGF5ZXIgdG8gbWFwIGJlZm9yZSB1c2luZyBnZXRDZW50ZXIoKScpO1xuICBcdFx0fVxuICBcdFx0cmV0dXJuIHBvbHlnb25DZW50ZXIodGhpcy5fZGVmYXVsdFNoYXBlKCksIHRoaXMuX21hcC5vcHRpb25zLmNycyk7XG4gIFx0fSxcblxuICBcdF9jb252ZXJ0TGF0TG5nczogZnVuY3Rpb24gKGxhdGxuZ3MpIHtcbiAgXHRcdHZhciByZXN1bHQgPSBQb2x5bGluZS5wcm90b3R5cGUuX2NvbnZlcnRMYXRMbmdzLmNhbGwodGhpcywgbGF0bG5ncyksXG4gIFx0XHQgICAgbGVuID0gcmVzdWx0Lmxlbmd0aDtcblxuICBcdFx0Ly8gcmVtb3ZlIGxhc3QgcG9pbnQgaWYgaXQgZXF1YWxzIGZpcnN0IG9uZVxuICBcdFx0aWYgKGxlbiA+PSAyICYmIHJlc3VsdFswXSBpbnN0YW5jZW9mIExhdExuZyAmJiByZXN1bHRbMF0uZXF1YWxzKHJlc3VsdFtsZW4gLSAxXSkpIHtcbiAgXHRcdFx0cmVzdWx0LnBvcCgpO1xuICBcdFx0fVxuICBcdFx0cmV0dXJuIHJlc3VsdDtcbiAgXHR9LFxuXG4gIFx0X3NldExhdExuZ3M6IGZ1bmN0aW9uIChsYXRsbmdzKSB7XG4gIFx0XHRQb2x5bGluZS5wcm90b3R5cGUuX3NldExhdExuZ3MuY2FsbCh0aGlzLCBsYXRsbmdzKTtcbiAgXHRcdGlmIChpc0ZsYXQodGhpcy5fbGF0bG5ncykpIHtcbiAgXHRcdFx0dGhpcy5fbGF0bG5ncyA9IFt0aGlzLl9sYXRsbmdzXTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X2RlZmF1bHRTaGFwZTogZnVuY3Rpb24gKCkge1xuICBcdFx0cmV0dXJuIGlzRmxhdCh0aGlzLl9sYXRsbmdzWzBdKSA/IHRoaXMuX2xhdGxuZ3NbMF0gOiB0aGlzLl9sYXRsbmdzWzBdWzBdO1xuICBcdH0sXG5cbiAgXHRfY2xpcFBvaW50czogZnVuY3Rpb24gKCkge1xuICBcdFx0Ly8gcG9seWdvbnMgbmVlZCBhIGRpZmZlcmVudCBjbGlwcGluZyBhbGdvcml0aG0gc28gd2UgcmVkZWZpbmUgdGhhdFxuXG4gIFx0XHR2YXIgYm91bmRzID0gdGhpcy5fcmVuZGVyZXIuX2JvdW5kcyxcbiAgXHRcdCAgICB3ID0gdGhpcy5vcHRpb25zLndlaWdodCxcbiAgXHRcdCAgICBwID0gbmV3IFBvaW50KHcsIHcpO1xuXG4gIFx0XHQvLyBpbmNyZWFzZSBjbGlwIHBhZGRpbmcgYnkgc3Ryb2tlIHdpZHRoIHRvIGF2b2lkIHN0cm9rZSBvbiBjbGlwIGVkZ2VzXG4gIFx0XHRib3VuZHMgPSBuZXcgQm91bmRzKGJvdW5kcy5taW4uc3VidHJhY3QocCksIGJvdW5kcy5tYXguYWRkKHApKTtcblxuICBcdFx0dGhpcy5fcGFydHMgPSBbXTtcbiAgXHRcdGlmICghdGhpcy5fcHhCb3VuZHMgfHwgIXRoaXMuX3B4Qm91bmRzLmludGVyc2VjdHMoYm91bmRzKSkge1xuICBcdFx0XHRyZXR1cm47XG4gIFx0XHR9XG5cbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMubm9DbGlwKSB7XG4gIFx0XHRcdHRoaXMuX3BhcnRzID0gdGhpcy5fcmluZ3M7XG4gIFx0XHRcdHJldHVybjtcbiAgXHRcdH1cblxuICBcdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IHRoaXMuX3JpbmdzLmxlbmd0aCwgY2xpcHBlZDsgaSA8IGxlbjsgaSsrKSB7XG4gIFx0XHRcdGNsaXBwZWQgPSBjbGlwUG9seWdvbih0aGlzLl9yaW5nc1tpXSwgYm91bmRzLCB0cnVlKTtcbiAgXHRcdFx0aWYgKGNsaXBwZWQubGVuZ3RoKSB7XG4gIFx0XHRcdFx0dGhpcy5fcGFydHMucHVzaChjbGlwcGVkKTtcbiAgXHRcdFx0fVxuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfdXBkYXRlUGF0aDogZnVuY3Rpb24gKCkge1xuICBcdFx0dGhpcy5fcmVuZGVyZXIuX3VwZGF0ZVBvbHkodGhpcywgdHJ1ZSk7XG4gIFx0fSxcblxuICBcdC8vIE5lZWRlZCBieSB0aGUgYENhbnZhc2AgcmVuZGVyZXIgZm9yIGludGVyYWN0aXZpdHlcbiAgXHRfY29udGFpbnNQb2ludDogZnVuY3Rpb24gKHApIHtcbiAgXHRcdHZhciBpbnNpZGUgPSBmYWxzZSxcbiAgXHRcdCAgICBwYXJ0LCBwMSwgcDIsIGksIGosIGssIGxlbiwgbGVuMjtcblxuICBcdFx0aWYgKCF0aGlzLl9weEJvdW5kcyB8fCAhdGhpcy5fcHhCb3VuZHMuY29udGFpbnMocCkpIHsgcmV0dXJuIGZhbHNlOyB9XG5cbiAgXHRcdC8vIHJheSBjYXN0aW5nIGFsZ29yaXRobSBmb3IgZGV0ZWN0aW5nIGlmIHBvaW50IGlzIGluIHBvbHlnb25cbiAgXHRcdGZvciAoaSA9IDAsIGxlbiA9IHRoaXMuX3BhcnRzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gIFx0XHRcdHBhcnQgPSB0aGlzLl9wYXJ0c1tpXTtcblxuICBcdFx0XHRmb3IgKGogPSAwLCBsZW4yID0gcGFydC5sZW5ndGgsIGsgPSBsZW4yIC0gMTsgaiA8IGxlbjI7IGsgPSBqKyspIHtcbiAgXHRcdFx0XHRwMSA9IHBhcnRbal07XG4gIFx0XHRcdFx0cDIgPSBwYXJ0W2tdO1xuXG4gIFx0XHRcdFx0aWYgKCgocDEueSA+IHAueSkgIT09IChwMi55ID4gcC55KSkgJiYgKHAueCA8IChwMi54IC0gcDEueCkgKiAocC55IC0gcDEueSkgLyAocDIueSAtIHAxLnkpICsgcDEueCkpIHtcbiAgXHRcdFx0XHRcdGluc2lkZSA9ICFpbnNpZGU7XG4gIFx0XHRcdFx0fVxuICBcdFx0XHR9XG4gIFx0XHR9XG5cbiAgXHRcdC8vIGFsc28gY2hlY2sgaWYgaXQncyBvbiBwb2x5Z29uIHN0cm9rZVxuICBcdFx0cmV0dXJuIGluc2lkZSB8fCBQb2x5bGluZS5wcm90b3R5cGUuX2NvbnRhaW5zUG9pbnQuY2FsbCh0aGlzLCBwLCB0cnVlKTtcbiAgXHR9XG5cbiAgfSk7XG5cblxuICAvLyBAZmFjdG9yeSBMLnBvbHlnb24obGF0bG5nczogTGF0TG5nW10sIG9wdGlvbnM/OiBQb2x5bGluZSBvcHRpb25zKVxuICBmdW5jdGlvbiBwb2x5Z29uKGxhdGxuZ3MsIG9wdGlvbnMpIHtcbiAgXHRyZXR1cm4gbmV3IFBvbHlnb24obGF0bG5ncywgb3B0aW9ucyk7XG4gIH1cblxuICAvKlxyXG4gICAqIEBjbGFzcyBHZW9KU09OXHJcbiAgICogQGFrYSBMLkdlb0pTT05cclxuICAgKiBAaW5oZXJpdHMgRmVhdHVyZUdyb3VwXHJcbiAgICpcclxuICAgKiBSZXByZXNlbnRzIGEgR2VvSlNPTiBvYmplY3Qgb3IgYW4gYXJyYXkgb2YgR2VvSlNPTiBvYmplY3RzLiBBbGxvd3MgeW91IHRvIHBhcnNlXHJcbiAgICogR2VvSlNPTiBkYXRhIGFuZCBkaXNwbGF5IGl0IG9uIHRoZSBtYXAuIEV4dGVuZHMgYEZlYXR1cmVHcm91cGAuXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiBMLmdlb0pTT04oZGF0YSwge1xyXG4gICAqIFx0c3R5bGU6IGZ1bmN0aW9uIChmZWF0dXJlKSB7XHJcbiAgICogXHRcdHJldHVybiB7Y29sb3I6IGZlYXR1cmUucHJvcGVydGllcy5jb2xvcn07XHJcbiAgICogXHR9XHJcbiAgICogfSkuYmluZFBvcHVwKGZ1bmN0aW9uIChsYXllcikge1xyXG4gICAqIFx0cmV0dXJuIGxheWVyLmZlYXR1cmUucHJvcGVydGllcy5kZXNjcmlwdGlvbjtcclxuICAgKiB9KS5hZGRUbyhtYXApO1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG5cclxuICB2YXIgR2VvSlNPTiA9IEZlYXR1cmVHcm91cC5leHRlbmQoe1xyXG5cclxuICBcdC8qIEBzZWN0aW9uXHJcbiAgXHQgKiBAYWthIEdlb0pTT04gb3B0aW9uc1xyXG4gIFx0ICpcclxuICBcdCAqIEBvcHRpb24gcG9pbnRUb0xheWVyOiBGdW5jdGlvbiA9ICpcclxuICBcdCAqIEEgYEZ1bmN0aW9uYCBkZWZpbmluZyBob3cgR2VvSlNPTiBwb2ludHMgc3Bhd24gTGVhZmxldCBsYXllcnMuIEl0IGlzIGludGVybmFsbHlcclxuICBcdCAqIGNhbGxlZCB3aGVuIGRhdGEgaXMgYWRkZWQsIHBhc3NpbmcgdGhlIEdlb0pTT04gcG9pbnQgZmVhdHVyZSBhbmQgaXRzIGBMYXRMbmdgLlxyXG4gIFx0ICogVGhlIGRlZmF1bHQgaXMgdG8gc3Bhd24gYSBkZWZhdWx0IGBNYXJrZXJgOlxyXG4gIFx0ICogYGBganNcclxuICBcdCAqIGZ1bmN0aW9uKGdlb0pzb25Qb2ludCwgbGF0bG5nKSB7XHJcbiAgXHQgKiBcdHJldHVybiBMLm1hcmtlcihsYXRsbmcpO1xyXG4gIFx0ICogfVxyXG4gIFx0ICogYGBgXHJcbiAgXHQgKlxyXG4gIFx0ICogQG9wdGlvbiBzdHlsZTogRnVuY3Rpb24gPSAqXHJcbiAgXHQgKiBBIGBGdW5jdGlvbmAgZGVmaW5pbmcgdGhlIGBQYXRoIG9wdGlvbnNgIGZvciBzdHlsaW5nIEdlb0pTT04gbGluZXMgYW5kIHBvbHlnb25zLFxyXG4gIFx0ICogY2FsbGVkIGludGVybmFsbHkgd2hlbiBkYXRhIGlzIGFkZGVkLlxyXG4gIFx0ICogVGhlIGRlZmF1bHQgdmFsdWUgaXMgdG8gbm90IG92ZXJyaWRlIGFueSBkZWZhdWx0czpcclxuICBcdCAqIGBgYGpzXHJcbiAgXHQgKiBmdW5jdGlvbiAoZ2VvSnNvbkZlYXR1cmUpIHtcclxuICBcdCAqIFx0cmV0dXJuIHt9XHJcbiAgXHQgKiB9XHJcbiAgXHQgKiBgYGBcclxuICBcdCAqXHJcbiAgXHQgKiBAb3B0aW9uIG9uRWFjaEZlYXR1cmU6IEZ1bmN0aW9uID0gKlxyXG4gIFx0ICogQSBgRnVuY3Rpb25gIHRoYXQgd2lsbCBiZSBjYWxsZWQgb25jZSBmb3IgZWFjaCBjcmVhdGVkIGBGZWF0dXJlYCwgYWZ0ZXIgaXQgaGFzXHJcbiAgXHQgKiBiZWVuIGNyZWF0ZWQgYW5kIHN0eWxlZC4gVXNlZnVsIGZvciBhdHRhY2hpbmcgZXZlbnRzIGFuZCBwb3B1cHMgdG8gZmVhdHVyZXMuXHJcbiAgXHQgKiBUaGUgZGVmYXVsdCBpcyB0byBkbyBub3RoaW5nIHdpdGggdGhlIG5ld2x5IGNyZWF0ZWQgbGF5ZXJzOlxyXG4gIFx0ICogYGBganNcclxuICBcdCAqIGZ1bmN0aW9uIChmZWF0dXJlLCBsYXllcikge31cclxuICBcdCAqIGBgYFxyXG4gIFx0ICpcclxuICBcdCAqIEBvcHRpb24gZmlsdGVyOiBGdW5jdGlvbiA9ICpcclxuICBcdCAqIEEgYEZ1bmN0aW9uYCB0aGF0IHdpbGwgYmUgdXNlZCB0byBkZWNpZGUgd2hldGhlciB0byBpbmNsdWRlIGEgZmVhdHVyZSBvciBub3QuXHJcbiAgXHQgKiBUaGUgZGVmYXVsdCBpcyB0byBpbmNsdWRlIGFsbCBmZWF0dXJlczpcclxuICBcdCAqIGBgYGpzXHJcbiAgXHQgKiBmdW5jdGlvbiAoZ2VvSnNvbkZlYXR1cmUpIHtcclxuICBcdCAqIFx0cmV0dXJuIHRydWU7XHJcbiAgXHQgKiB9XHJcbiAgXHQgKiBgYGBcclxuICBcdCAqIE5vdGU6IGR5bmFtaWNhbGx5IGNoYW5naW5nIHRoZSBgZmlsdGVyYCBvcHRpb24gd2lsbCBoYXZlIGVmZmVjdCBvbmx5IG9uIG5ld2x5XHJcbiAgXHQgKiBhZGRlZCBkYXRhLiBJdCB3aWxsIF9ub3RfIHJlLWV2YWx1YXRlIGFscmVhZHkgaW5jbHVkZWQgZmVhdHVyZXMuXHJcbiAgXHQgKlxyXG4gIFx0ICogQG9wdGlvbiBjb29yZHNUb0xhdExuZzogRnVuY3Rpb24gPSAqXHJcbiAgXHQgKiBBIGBGdW5jdGlvbmAgdGhhdCB3aWxsIGJlIHVzZWQgZm9yIGNvbnZlcnRpbmcgR2VvSlNPTiBjb29yZGluYXRlcyB0byBgTGF0TG5nYHMuXHJcbiAgXHQgKiBUaGUgZGVmYXVsdCBpcyB0aGUgYGNvb3Jkc1RvTGF0TG5nYCBzdGF0aWMgbWV0aG9kLlxyXG4gIFx0ICpcclxuICBcdCAqIEBvcHRpb24gbWFya2Vyc0luaGVyaXRPcHRpb25zOiBCb29sZWFuID0gZmFsc2VcclxuICBcdCAqIFdoZXRoZXIgZGVmYXVsdCBNYXJrZXJzIGZvciBcIlBvaW50XCIgdHlwZSBGZWF0dXJlcyBpbmhlcml0IGZyb20gZ3JvdXAgb3B0aW9ucy5cclxuICBcdCAqL1xyXG5cclxuICBcdGluaXRpYWxpemU6IGZ1bmN0aW9uIChnZW9qc29uLCBvcHRpb25zKSB7XHJcbiAgXHRcdHNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XHJcblxyXG4gIFx0XHR0aGlzLl9sYXllcnMgPSB7fTtcclxuXHJcbiAgXHRcdGlmIChnZW9qc29uKSB7XHJcbiAgXHRcdFx0dGhpcy5hZGREYXRhKGdlb2pzb24pO1xyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgYWRkRGF0YSggPEdlb0pTT04+IGRhdGEgKTogdGhpc1xyXG4gIFx0Ly8gQWRkcyBhIEdlb0pTT04gb2JqZWN0IHRvIHRoZSBsYXllci5cclxuICBcdGFkZERhdGE6IGZ1bmN0aW9uIChnZW9qc29uKSB7XHJcbiAgXHRcdHZhciBmZWF0dXJlcyA9IGlzQXJyYXkoZ2VvanNvbikgPyBnZW9qc29uIDogZ2VvanNvbi5mZWF0dXJlcyxcclxuICBcdFx0ICAgIGksIGxlbiwgZmVhdHVyZTtcclxuXHJcbiAgXHRcdGlmIChmZWF0dXJlcykge1xyXG4gIFx0XHRcdGZvciAoaSA9IDAsIGxlbiA9IGZlYXR1cmVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdFx0XHQvLyBvbmx5IGFkZCB0aGlzIGlmIGdlb21ldHJ5IG9yIGdlb21ldHJpZXMgYXJlIHNldCBhbmQgbm90IG51bGxcclxuICBcdFx0XHRcdGZlYXR1cmUgPSBmZWF0dXJlc1tpXTtcclxuICBcdFx0XHRcdGlmIChmZWF0dXJlLmdlb21ldHJpZXMgfHwgZmVhdHVyZS5nZW9tZXRyeSB8fCBmZWF0dXJlLmZlYXR1cmVzIHx8IGZlYXR1cmUuY29vcmRpbmF0ZXMpIHtcclxuICBcdFx0XHRcdFx0dGhpcy5hZGREYXRhKGZlYXR1cmUpO1xyXG4gIFx0XHRcdFx0fVxyXG4gIFx0XHRcdH1cclxuICBcdFx0XHRyZXR1cm4gdGhpcztcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XHJcblxyXG4gIFx0XHRpZiAob3B0aW9ucy5maWx0ZXIgJiYgIW9wdGlvbnMuZmlsdGVyKGdlb2pzb24pKSB7IHJldHVybiB0aGlzOyB9XHJcblxyXG4gIFx0XHR2YXIgbGF5ZXIgPSBnZW9tZXRyeVRvTGF5ZXIoZ2VvanNvbiwgb3B0aW9ucyk7XHJcbiAgXHRcdGlmICghbGF5ZXIpIHtcclxuICBcdFx0XHRyZXR1cm4gdGhpcztcclxuICBcdFx0fVxyXG4gIFx0XHRsYXllci5mZWF0dXJlID0gYXNGZWF0dXJlKGdlb2pzb24pO1xyXG5cclxuICBcdFx0bGF5ZXIuZGVmYXVsdE9wdGlvbnMgPSBsYXllci5vcHRpb25zO1xyXG4gIFx0XHR0aGlzLnJlc2V0U3R5bGUobGF5ZXIpO1xyXG5cclxuICBcdFx0aWYgKG9wdGlvbnMub25FYWNoRmVhdHVyZSkge1xyXG4gIFx0XHRcdG9wdGlvbnMub25FYWNoRmVhdHVyZShnZW9qc29uLCBsYXllcik7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiB0aGlzLmFkZExheWVyKGxheWVyKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCByZXNldFN0eWxlKCA8UGF0aD4gbGF5ZXI/ICk6IHRoaXNcclxuICBcdC8vIFJlc2V0cyB0aGUgZ2l2ZW4gdmVjdG9yIGxheWVyJ3Mgc3R5bGUgdG8gdGhlIG9yaWdpbmFsIEdlb0pTT04gc3R5bGUsIHVzZWZ1bCBmb3IgcmVzZXR0aW5nIHN0eWxlIGFmdGVyIGhvdmVyIGV2ZW50cy5cclxuICBcdC8vIElmIGBsYXllcmAgaXMgb21pdHRlZCwgdGhlIHN0eWxlIG9mIGFsbCBmZWF0dXJlcyBpbiB0aGUgY3VycmVudCBsYXllciBpcyByZXNldC5cclxuICBcdHJlc2V0U3R5bGU6IGZ1bmN0aW9uIChsYXllcikge1xyXG4gIFx0XHRpZiAobGF5ZXIgPT09IHVuZGVmaW5lZCkge1xyXG4gIFx0XHRcdHJldHVybiB0aGlzLmVhY2hMYXllcih0aGlzLnJlc2V0U3R5bGUsIHRoaXMpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdC8vIHJlc2V0IGFueSBjdXN0b20gc3R5bGVzXHJcbiAgXHRcdGxheWVyLm9wdGlvbnMgPSBleHRlbmQoe30sIGxheWVyLmRlZmF1bHRPcHRpb25zKTtcclxuICBcdFx0dGhpcy5fc2V0TGF5ZXJTdHlsZShsYXllciwgdGhpcy5vcHRpb25zLnN0eWxlKTtcclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2V0U3R5bGUoIDxGdW5jdGlvbj4gc3R5bGUgKTogdGhpc1xyXG4gIFx0Ly8gQ2hhbmdlcyBzdHlsZXMgb2YgR2VvSlNPTiB2ZWN0b3IgbGF5ZXJzIHdpdGggdGhlIGdpdmVuIHN0eWxlIGZ1bmN0aW9uLlxyXG4gIFx0c2V0U3R5bGU6IGZ1bmN0aW9uIChzdHlsZSkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5lYWNoTGF5ZXIoZnVuY3Rpb24gKGxheWVyKSB7XHJcbiAgXHRcdFx0dGhpcy5fc2V0TGF5ZXJTdHlsZShsYXllciwgc3R5bGUpO1xyXG4gIFx0XHR9LCB0aGlzKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X3NldExheWVyU3R5bGU6IGZ1bmN0aW9uIChsYXllciwgc3R5bGUpIHtcclxuICBcdFx0aWYgKGxheWVyLnNldFN0eWxlKSB7XHJcbiAgXHRcdFx0aWYgKHR5cGVvZiBzdHlsZSA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gIFx0XHRcdFx0c3R5bGUgPSBzdHlsZShsYXllci5mZWF0dXJlKTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdFx0bGF5ZXIuc2V0U3R5bGUoc3R5bGUpO1xyXG4gIFx0XHR9XHJcbiAgXHR9XHJcbiAgfSk7XHJcblxyXG4gIC8vIEBzZWN0aW9uXHJcbiAgLy8gVGhlcmUgYXJlIHNldmVyYWwgc3RhdGljIGZ1bmN0aW9ucyB3aGljaCBjYW4gYmUgY2FsbGVkIHdpdGhvdXQgaW5zdGFudGlhdGluZyBMLkdlb0pTT046XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBnZW9tZXRyeVRvTGF5ZXIoZmVhdHVyZURhdGE6IE9iamVjdCwgb3B0aW9ucz86IEdlb0pTT04gb3B0aW9ucyk6IExheWVyXHJcbiAgLy8gQ3JlYXRlcyBhIGBMYXllcmAgZnJvbSBhIGdpdmVuIEdlb0pTT04gZmVhdHVyZS4gQ2FuIHVzZSBhIGN1c3RvbVxyXG4gIC8vIFtgcG9pbnRUb0xheWVyYF0oI2dlb2pzb24tcG9pbnR0b2xheWVyKSBhbmQvb3IgW2Bjb29yZHNUb0xhdExuZ2BdKCNnZW9qc29uLWNvb3Jkc3RvbGF0bG5nKVxyXG4gIC8vIGZ1bmN0aW9ucyBpZiBwcm92aWRlZCBhcyBvcHRpb25zLlxyXG4gIGZ1bmN0aW9uIGdlb21ldHJ5VG9MYXllcihnZW9qc29uLCBvcHRpb25zKSB7XHJcblxyXG4gIFx0dmFyIGdlb21ldHJ5ID0gZ2VvanNvbi50eXBlID09PSAnRmVhdHVyZScgPyBnZW9qc29uLmdlb21ldHJ5IDogZ2VvanNvbixcclxuICBcdCAgICBjb29yZHMgPSBnZW9tZXRyeSA/IGdlb21ldHJ5LmNvb3JkaW5hdGVzIDogbnVsbCxcclxuICBcdCAgICBsYXllcnMgPSBbXSxcclxuICBcdCAgICBwb2ludFRvTGF5ZXIgPSBvcHRpb25zICYmIG9wdGlvbnMucG9pbnRUb0xheWVyLFxyXG4gIFx0ICAgIF9jb29yZHNUb0xhdExuZyA9IG9wdGlvbnMgJiYgb3B0aW9ucy5jb29yZHNUb0xhdExuZyB8fCBjb29yZHNUb0xhdExuZyxcclxuICBcdCAgICBsYXRsbmcsIGxhdGxuZ3MsIGksIGxlbjtcclxuXHJcbiAgXHRpZiAoIWNvb3JkcyAmJiAhZ2VvbWV0cnkpIHtcclxuICBcdFx0cmV0dXJuIG51bGw7XHJcbiAgXHR9XHJcblxyXG4gIFx0c3dpdGNoIChnZW9tZXRyeS50eXBlKSB7XHJcbiAgXHRjYXNlICdQb2ludCc6XHJcbiAgXHRcdGxhdGxuZyA9IF9jb29yZHNUb0xhdExuZyhjb29yZHMpO1xyXG4gIFx0XHRyZXR1cm4gX3BvaW50VG9MYXllcihwb2ludFRvTGF5ZXIsIGdlb2pzb24sIGxhdGxuZywgb3B0aW9ucyk7XHJcblxyXG4gIFx0Y2FzZSAnTXVsdGlQb2ludCc6XHJcbiAgXHRcdGZvciAoaSA9IDAsIGxlbiA9IGNvb3Jkcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gIFx0XHRcdGxhdGxuZyA9IF9jb29yZHNUb0xhdExuZyhjb29yZHNbaV0pO1xyXG4gIFx0XHRcdGxheWVycy5wdXNoKF9wb2ludFRvTGF5ZXIocG9pbnRUb0xheWVyLCBnZW9qc29uLCBsYXRsbmcsIG9wdGlvbnMpKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gbmV3IEZlYXR1cmVHcm91cChsYXllcnMpO1xyXG5cclxuICBcdGNhc2UgJ0xpbmVTdHJpbmcnOlxyXG4gIFx0Y2FzZSAnTXVsdGlMaW5lU3RyaW5nJzpcclxuICBcdFx0bGF0bG5ncyA9IGNvb3Jkc1RvTGF0TG5ncyhjb29yZHMsIGdlb21ldHJ5LnR5cGUgPT09ICdMaW5lU3RyaW5nJyA/IDAgOiAxLCBfY29vcmRzVG9MYXRMbmcpO1xyXG4gIFx0XHRyZXR1cm4gbmV3IFBvbHlsaW5lKGxhdGxuZ3MsIG9wdGlvbnMpO1xyXG5cclxuICBcdGNhc2UgJ1BvbHlnb24nOlxyXG4gIFx0Y2FzZSAnTXVsdGlQb2x5Z29uJzpcclxuICBcdFx0bGF0bG5ncyA9IGNvb3Jkc1RvTGF0TG5ncyhjb29yZHMsIGdlb21ldHJ5LnR5cGUgPT09ICdQb2x5Z29uJyA/IDEgOiAyLCBfY29vcmRzVG9MYXRMbmcpO1xyXG4gIFx0XHRyZXR1cm4gbmV3IFBvbHlnb24obGF0bG5ncywgb3B0aW9ucyk7XHJcblxyXG4gIFx0Y2FzZSAnR2VvbWV0cnlDb2xsZWN0aW9uJzpcclxuICBcdFx0Zm9yIChpID0gMCwgbGVuID0gZ2VvbWV0cnkuZ2VvbWV0cmllcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gIFx0XHRcdHZhciBnZW9MYXllciA9IGdlb21ldHJ5VG9MYXllcih7XHJcbiAgXHRcdFx0XHRnZW9tZXRyeTogZ2VvbWV0cnkuZ2VvbWV0cmllc1tpXSxcclxuICBcdFx0XHRcdHR5cGU6ICdGZWF0dXJlJyxcclxuICBcdFx0XHRcdHByb3BlcnRpZXM6IGdlb2pzb24ucHJvcGVydGllc1xyXG4gIFx0XHRcdH0sIG9wdGlvbnMpO1xyXG5cclxuICBcdFx0XHRpZiAoZ2VvTGF5ZXIpIHtcclxuICBcdFx0XHRcdGxheWVycy5wdXNoKGdlb0xheWVyKTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIG5ldyBGZWF0dXJlR3JvdXAobGF5ZXJzKTtcclxuXHJcbiAgXHRjYXNlICdGZWF0dXJlQ29sbGVjdGlvbic6XHJcbiAgXHRcdGZvciAoaSA9IDAsIGxlbiA9IGdlb21ldHJ5LmZlYXR1cmVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdFx0dmFyIGZlYXR1cmVMYXllciA9IGdlb21ldHJ5VG9MYXllcihnZW9tZXRyeS5mZWF0dXJlc1tpXSwgb3B0aW9ucyk7XHJcblxyXG4gIFx0XHRcdGlmIChmZWF0dXJlTGF5ZXIpIHtcclxuICBcdFx0XHRcdGxheWVycy5wdXNoKGZlYXR1cmVMYXllcik7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiBuZXcgRmVhdHVyZUdyb3VwKGxheWVycyk7XHJcblxyXG4gIFx0ZGVmYXVsdDpcclxuICBcdFx0dGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIEdlb0pTT04gb2JqZWN0LicpO1xyXG4gIFx0fVxyXG4gIH1cclxuXHJcbiAgZnVuY3Rpb24gX3BvaW50VG9MYXllcihwb2ludFRvTGF5ZXJGbiwgZ2VvanNvbiwgbGF0bG5nLCBvcHRpb25zKSB7XHJcbiAgXHRyZXR1cm4gcG9pbnRUb0xheWVyRm4gP1xyXG4gIFx0XHRwb2ludFRvTGF5ZXJGbihnZW9qc29uLCBsYXRsbmcpIDpcclxuICBcdFx0bmV3IE1hcmtlcihsYXRsbmcsIG9wdGlvbnMgJiYgb3B0aW9ucy5tYXJrZXJzSW5oZXJpdE9wdGlvbnMgJiYgb3B0aW9ucyk7XHJcbiAgfVxyXG5cclxuICAvLyBAZnVuY3Rpb24gY29vcmRzVG9MYXRMbmcoY29vcmRzOiBBcnJheSk6IExhdExuZ1xyXG4gIC8vIENyZWF0ZXMgYSBgTGF0TG5nYCBvYmplY3QgZnJvbSBhbiBhcnJheSBvZiAyIG51bWJlcnMgKGxvbmdpdHVkZSwgbGF0aXR1ZGUpXHJcbiAgLy8gb3IgMyBudW1iZXJzIChsb25naXR1ZGUsIGxhdGl0dWRlLCBhbHRpdHVkZSkgdXNlZCBpbiBHZW9KU09OIGZvciBwb2ludHMuXHJcbiAgZnVuY3Rpb24gY29vcmRzVG9MYXRMbmcoY29vcmRzKSB7XHJcbiAgXHRyZXR1cm4gbmV3IExhdExuZyhjb29yZHNbMV0sIGNvb3Jkc1swXSwgY29vcmRzWzJdKTtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBjb29yZHNUb0xhdExuZ3MoY29vcmRzOiBBcnJheSwgbGV2ZWxzRGVlcD86IE51bWJlciwgY29vcmRzVG9MYXRMbmc/OiBGdW5jdGlvbik6IEFycmF5XHJcbiAgLy8gQ3JlYXRlcyBhIG11bHRpZGltZW5zaW9uYWwgYXJyYXkgb2YgYExhdExuZ2BzIGZyb20gYSBHZW9KU09OIGNvb3JkaW5hdGVzIGFycmF5LlxyXG4gIC8vIGBsZXZlbHNEZWVwYCBzcGVjaWZpZXMgdGhlIG5lc3RpbmcgbGV2ZWwgKDAgaXMgZm9yIGFuIGFycmF5IG9mIHBvaW50cywgMSBmb3IgYW4gYXJyYXkgb2YgYXJyYXlzIG9mIHBvaW50cywgZXRjLiwgMCBieSBkZWZhdWx0KS5cclxuICAvLyBDYW4gdXNlIGEgY3VzdG9tIFtgY29vcmRzVG9MYXRMbmdgXSgjZ2VvanNvbi1jb29yZHN0b2xhdGxuZykgZnVuY3Rpb24uXHJcbiAgZnVuY3Rpb24gY29vcmRzVG9MYXRMbmdzKGNvb3JkcywgbGV2ZWxzRGVlcCwgX2Nvb3Jkc1RvTGF0TG5nKSB7XHJcbiAgXHR2YXIgbGF0bG5ncyA9IFtdO1xyXG5cclxuICBcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBjb29yZHMubGVuZ3RoLCBsYXRsbmc7IGkgPCBsZW47IGkrKykge1xyXG4gIFx0XHRsYXRsbmcgPSBsZXZlbHNEZWVwID9cclxuICBcdFx0XHRjb29yZHNUb0xhdExuZ3MoY29vcmRzW2ldLCBsZXZlbHNEZWVwIC0gMSwgX2Nvb3Jkc1RvTGF0TG5nKSA6XHJcbiAgXHRcdFx0KF9jb29yZHNUb0xhdExuZyB8fCBjb29yZHNUb0xhdExuZykoY29vcmRzW2ldKTtcclxuXHJcbiAgXHRcdGxhdGxuZ3MucHVzaChsYXRsbmcpO1xyXG4gIFx0fVxyXG5cclxuICBcdHJldHVybiBsYXRsbmdzO1xyXG4gIH1cclxuXHJcbiAgLy8gQGZ1bmN0aW9uIGxhdExuZ1RvQ29vcmRzKGxhdGxuZzogTGF0TG5nLCBwcmVjaXNpb24/OiBOdW1iZXJ8ZmFsc2UpOiBBcnJheVxyXG4gIC8vIFJldmVyc2Ugb2YgW2Bjb29yZHNUb0xhdExuZ2BdKCNnZW9qc29uLWNvb3Jkc3RvbGF0bG5nKVxyXG4gIC8vIENvb3JkaW5hdGVzIHZhbHVlcyBhcmUgcm91bmRlZCB3aXRoIFtgZm9ybWF0TnVtYF0oI3V0aWwtZm9ybWF0bnVtKSBmdW5jdGlvbi5cclxuICBmdW5jdGlvbiBsYXRMbmdUb0Nvb3JkcyhsYXRsbmcsIHByZWNpc2lvbikge1xyXG4gIFx0bGF0bG5nID0gdG9MYXRMbmcobGF0bG5nKTtcclxuICBcdHJldHVybiBsYXRsbmcuYWx0ICE9PSB1bmRlZmluZWQgP1xyXG4gIFx0XHRbZm9ybWF0TnVtKGxhdGxuZy5sbmcsIHByZWNpc2lvbiksIGZvcm1hdE51bShsYXRsbmcubGF0LCBwcmVjaXNpb24pLCBmb3JtYXROdW0obGF0bG5nLmFsdCwgcHJlY2lzaW9uKV0gOlxyXG4gIFx0XHRbZm9ybWF0TnVtKGxhdGxuZy5sbmcsIHByZWNpc2lvbiksIGZvcm1hdE51bShsYXRsbmcubGF0LCBwcmVjaXNpb24pXTtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBsYXRMbmdzVG9Db29yZHMobGF0bG5nczogQXJyYXksIGxldmVsc0RlZXA/OiBOdW1iZXIsIGNsb3NlZD86IEJvb2xlYW4sIHByZWNpc2lvbj86IE51bWJlcnxmYWxzZSk6IEFycmF5XHJcbiAgLy8gUmV2ZXJzZSBvZiBbYGNvb3Jkc1RvTGF0TG5nc2BdKCNnZW9qc29uLWNvb3Jkc3RvbGF0bG5ncylcclxuICAvLyBgY2xvc2VkYCBkZXRlcm1pbmVzIHdoZXRoZXIgdGhlIGZpcnN0IHBvaW50IHNob3VsZCBiZSBhcHBlbmRlZCB0byB0aGUgZW5kIG9mIHRoZSBhcnJheSB0byBjbG9zZSB0aGUgZmVhdHVyZSwgb25seSB1c2VkIHdoZW4gYGxldmVsc0RlZXBgIGlzIDAuIEZhbHNlIGJ5IGRlZmF1bHQuXHJcbiAgLy8gQ29vcmRpbmF0ZXMgdmFsdWVzIGFyZSByb3VuZGVkIHdpdGggW2Bmb3JtYXROdW1gXSgjdXRpbC1mb3JtYXRudW0pIGZ1bmN0aW9uLlxyXG4gIGZ1bmN0aW9uIGxhdExuZ3NUb0Nvb3JkcyhsYXRsbmdzLCBsZXZlbHNEZWVwLCBjbG9zZWQsIHByZWNpc2lvbikge1xyXG4gIFx0dmFyIGNvb3JkcyA9IFtdO1xyXG5cclxuICBcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBsYXRsbmdzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgXHRcdC8vIENoZWNrIGZvciBmbGF0IGFycmF5cyByZXF1aXJlZCB0byBlbnN1cmUgdW5iYWxhbmNlZCBhcnJheXMgYXJlIGNvcnJlY3RseSBjb252ZXJ0ZWQgaW4gcmVjdXJzaW9uXHJcbiAgXHRcdGNvb3Jkcy5wdXNoKGxldmVsc0RlZXAgP1xyXG4gIFx0XHRcdGxhdExuZ3NUb0Nvb3JkcyhsYXRsbmdzW2ldLCBpc0ZsYXQobGF0bG5nc1tpXSkgPyAwIDogbGV2ZWxzRGVlcCAtIDEsIGNsb3NlZCwgcHJlY2lzaW9uKSA6XHJcbiAgXHRcdFx0bGF0TG5nVG9Db29yZHMobGF0bG5nc1tpXSwgcHJlY2lzaW9uKSk7XHJcbiAgXHR9XHJcblxyXG4gIFx0aWYgKCFsZXZlbHNEZWVwICYmIGNsb3NlZCAmJiBjb29yZHMubGVuZ3RoID4gMCkge1xyXG4gIFx0XHRjb29yZHMucHVzaChjb29yZHNbMF0uc2xpY2UoKSk7XHJcbiAgXHR9XHJcblxyXG4gIFx0cmV0dXJuIGNvb3JkcztcclxuICB9XHJcblxyXG4gIGZ1bmN0aW9uIGdldEZlYXR1cmUobGF5ZXIsIG5ld0dlb21ldHJ5KSB7XHJcbiAgXHRyZXR1cm4gbGF5ZXIuZmVhdHVyZSA/XHJcbiAgXHRcdGV4dGVuZCh7fSwgbGF5ZXIuZmVhdHVyZSwge2dlb21ldHJ5OiBuZXdHZW9tZXRyeX0pIDpcclxuICBcdFx0YXNGZWF0dXJlKG5ld0dlb21ldHJ5KTtcclxuICB9XHJcblxyXG4gIC8vIEBmdW5jdGlvbiBhc0ZlYXR1cmUoZ2VvanNvbjogT2JqZWN0KTogT2JqZWN0XHJcbiAgLy8gTm9ybWFsaXplIEdlb0pTT04gZ2VvbWV0cmllcy9mZWF0dXJlcyBpbnRvIEdlb0pTT04gZmVhdHVyZXMuXHJcbiAgZnVuY3Rpb24gYXNGZWF0dXJlKGdlb2pzb24pIHtcclxuICBcdGlmIChnZW9qc29uLnR5cGUgPT09ICdGZWF0dXJlJyB8fCBnZW9qc29uLnR5cGUgPT09ICdGZWF0dXJlQ29sbGVjdGlvbicpIHtcclxuICBcdFx0cmV0dXJuIGdlb2pzb247XHJcbiAgXHR9XHJcblxyXG4gIFx0cmV0dXJuIHtcclxuICBcdFx0dHlwZTogJ0ZlYXR1cmUnLFxyXG4gIFx0XHRwcm9wZXJ0aWVzOiB7fSxcclxuICBcdFx0Z2VvbWV0cnk6IGdlb2pzb25cclxuICBcdH07XHJcbiAgfVxyXG5cclxuICB2YXIgUG9pbnRUb0dlb0pTT04gPSB7XHJcbiAgXHR0b0dlb0pTT046IGZ1bmN0aW9uIChwcmVjaXNpb24pIHtcclxuICBcdFx0cmV0dXJuIGdldEZlYXR1cmUodGhpcywge1xyXG4gIFx0XHRcdHR5cGU6ICdQb2ludCcsXHJcbiAgXHRcdFx0Y29vcmRpbmF0ZXM6IGxhdExuZ1RvQ29vcmRzKHRoaXMuZ2V0TGF0TG5nKCksIHByZWNpc2lvbilcclxuICBcdFx0fSk7XHJcbiAgXHR9XHJcbiAgfTtcclxuXHJcbiAgLy8gQG5hbWVzcGFjZSBNYXJrZXJcclxuICAvLyBAc2VjdGlvbiBPdGhlciBtZXRob2RzXHJcbiAgLy8gQG1ldGhvZCB0b0dlb0pTT04ocHJlY2lzaW9uPzogTnVtYmVyfGZhbHNlKTogT2JqZWN0XHJcbiAgLy8gQ29vcmRpbmF0ZXMgdmFsdWVzIGFyZSByb3VuZGVkIHdpdGggW2Bmb3JtYXROdW1gXSgjdXRpbC1mb3JtYXRudW0pIGZ1bmN0aW9uIHdpdGggZ2l2ZW4gYHByZWNpc2lvbmAuXHJcbiAgLy8gUmV0dXJucyBhIFtgR2VvSlNPTmBdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0dlb0pTT04pIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBtYXJrZXIgKGFzIGEgR2VvSlNPTiBgUG9pbnRgIEZlYXR1cmUpLlxyXG4gIE1hcmtlci5pbmNsdWRlKFBvaW50VG9HZW9KU09OKTtcclxuXHJcbiAgLy8gQG5hbWVzcGFjZSBDaXJjbGVNYXJrZXJcclxuICAvLyBAbWV0aG9kIHRvR2VvSlNPTihwcmVjaXNpb24/OiBOdW1iZXJ8ZmFsc2UpOiBPYmplY3RcclxuICAvLyBDb29yZGluYXRlcyB2YWx1ZXMgYXJlIHJvdW5kZWQgd2l0aCBbYGZvcm1hdE51bWBdKCN1dGlsLWZvcm1hdG51bSkgZnVuY3Rpb24gd2l0aCBnaXZlbiBgcHJlY2lzaW9uYC5cclxuICAvLyBSZXR1cm5zIGEgW2BHZW9KU09OYF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvR2VvSlNPTikgcmVwcmVzZW50YXRpb24gb2YgdGhlIGNpcmNsZSBtYXJrZXIgKGFzIGEgR2VvSlNPTiBgUG9pbnRgIEZlYXR1cmUpLlxyXG4gIENpcmNsZS5pbmNsdWRlKFBvaW50VG9HZW9KU09OKTtcclxuICBDaXJjbGVNYXJrZXIuaW5jbHVkZShQb2ludFRvR2VvSlNPTik7XHJcblxyXG5cclxuICAvLyBAbmFtZXNwYWNlIFBvbHlsaW5lXHJcbiAgLy8gQG1ldGhvZCB0b0dlb0pTT04ocHJlY2lzaW9uPzogTnVtYmVyfGZhbHNlKTogT2JqZWN0XHJcbiAgLy8gQ29vcmRpbmF0ZXMgdmFsdWVzIGFyZSByb3VuZGVkIHdpdGggW2Bmb3JtYXROdW1gXSgjdXRpbC1mb3JtYXRudW0pIGZ1bmN0aW9uIHdpdGggZ2l2ZW4gYHByZWNpc2lvbmAuXHJcbiAgLy8gUmV0dXJucyBhIFtgR2VvSlNPTmBdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0dlb0pTT04pIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBwb2x5bGluZSAoYXMgYSBHZW9KU09OIGBMaW5lU3RyaW5nYCBvciBgTXVsdGlMaW5lU3RyaW5nYCBGZWF0dXJlKS5cclxuICBQb2x5bGluZS5pbmNsdWRlKHtcclxuICBcdHRvR2VvSlNPTjogZnVuY3Rpb24gKHByZWNpc2lvbikge1xyXG4gIFx0XHR2YXIgbXVsdGkgPSAhaXNGbGF0KHRoaXMuX2xhdGxuZ3MpO1xyXG5cclxuICBcdFx0dmFyIGNvb3JkcyA9IGxhdExuZ3NUb0Nvb3Jkcyh0aGlzLl9sYXRsbmdzLCBtdWx0aSA/IDEgOiAwLCBmYWxzZSwgcHJlY2lzaW9uKTtcclxuXHJcbiAgXHRcdHJldHVybiBnZXRGZWF0dXJlKHRoaXMsIHtcclxuICBcdFx0XHR0eXBlOiAobXVsdGkgPyAnTXVsdGknIDogJycpICsgJ0xpbmVTdHJpbmcnLFxyXG4gIFx0XHRcdGNvb3JkaW5hdGVzOiBjb29yZHNcclxuICBcdFx0fSk7XHJcbiAgXHR9XHJcbiAgfSk7XHJcblxyXG4gIC8vIEBuYW1lc3BhY2UgUG9seWdvblxyXG4gIC8vIEBtZXRob2QgdG9HZW9KU09OKHByZWNpc2lvbj86IE51bWJlcnxmYWxzZSk6IE9iamVjdFxyXG4gIC8vIENvb3JkaW5hdGVzIHZhbHVlcyBhcmUgcm91bmRlZCB3aXRoIFtgZm9ybWF0TnVtYF0oI3V0aWwtZm9ybWF0bnVtKSBmdW5jdGlvbiB3aXRoIGdpdmVuIGBwcmVjaXNpb25gLlxyXG4gIC8vIFJldHVybnMgYSBbYEdlb0pTT05gXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9HZW9KU09OKSByZXByZXNlbnRhdGlvbiBvZiB0aGUgcG9seWdvbiAoYXMgYSBHZW9KU09OIGBQb2x5Z29uYCBvciBgTXVsdGlQb2x5Z29uYCBGZWF0dXJlKS5cclxuICBQb2x5Z29uLmluY2x1ZGUoe1xyXG4gIFx0dG9HZW9KU09OOiBmdW5jdGlvbiAocHJlY2lzaW9uKSB7XHJcbiAgXHRcdHZhciBob2xlcyA9ICFpc0ZsYXQodGhpcy5fbGF0bG5ncyksXHJcbiAgXHRcdCAgICBtdWx0aSA9IGhvbGVzICYmICFpc0ZsYXQodGhpcy5fbGF0bG5nc1swXSk7XHJcblxyXG4gIFx0XHR2YXIgY29vcmRzID0gbGF0TG5nc1RvQ29vcmRzKHRoaXMuX2xhdGxuZ3MsIG11bHRpID8gMiA6IGhvbGVzID8gMSA6IDAsIHRydWUsIHByZWNpc2lvbik7XHJcblxyXG4gIFx0XHRpZiAoIWhvbGVzKSB7XHJcbiAgXHRcdFx0Y29vcmRzID0gW2Nvb3Jkc107XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiBnZXRGZWF0dXJlKHRoaXMsIHtcclxuICBcdFx0XHR0eXBlOiAobXVsdGkgPyAnTXVsdGknIDogJycpICsgJ1BvbHlnb24nLFxyXG4gIFx0XHRcdGNvb3JkaW5hdGVzOiBjb29yZHNcclxuICBcdFx0fSk7XHJcbiAgXHR9XHJcbiAgfSk7XHJcblxyXG5cclxuICAvLyBAbmFtZXNwYWNlIExheWVyR3JvdXBcclxuICBMYXllckdyb3VwLmluY2x1ZGUoe1xyXG4gIFx0dG9NdWx0aVBvaW50OiBmdW5jdGlvbiAocHJlY2lzaW9uKSB7XHJcbiAgXHRcdHZhciBjb29yZHMgPSBbXTtcclxuXHJcbiAgXHRcdHRoaXMuZWFjaExheWVyKGZ1bmN0aW9uIChsYXllcikge1xyXG4gIFx0XHRcdGNvb3Jkcy5wdXNoKGxheWVyLnRvR2VvSlNPTihwcmVjaXNpb24pLmdlb21ldHJ5LmNvb3JkaW5hdGVzKTtcclxuICBcdFx0fSk7XHJcblxyXG4gIFx0XHRyZXR1cm4gZ2V0RmVhdHVyZSh0aGlzLCB7XHJcbiAgXHRcdFx0dHlwZTogJ011bHRpUG9pbnQnLFxyXG4gIFx0XHRcdGNvb3JkaW5hdGVzOiBjb29yZHNcclxuICBcdFx0fSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgdG9HZW9KU09OKHByZWNpc2lvbj86IE51bWJlcnxmYWxzZSk6IE9iamVjdFxyXG4gIFx0Ly8gQ29vcmRpbmF0ZXMgdmFsdWVzIGFyZSByb3VuZGVkIHdpdGggW2Bmb3JtYXROdW1gXSgjdXRpbC1mb3JtYXRudW0pIGZ1bmN0aW9uIHdpdGggZ2l2ZW4gYHByZWNpc2lvbmAuXHJcbiAgXHQvLyBSZXR1cm5zIGEgW2BHZW9KU09OYF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvR2VvSlNPTikgcmVwcmVzZW50YXRpb24gb2YgdGhlIGxheWVyIGdyb3VwIChhcyBhIEdlb0pTT04gYEZlYXR1cmVDb2xsZWN0aW9uYCwgYEdlb21ldHJ5Q29sbGVjdGlvbmAsIG9yIGBNdWx0aVBvaW50YCkuXHJcbiAgXHR0b0dlb0pTT046IGZ1bmN0aW9uIChwcmVjaXNpb24pIHtcclxuXHJcbiAgXHRcdHZhciB0eXBlID0gdGhpcy5mZWF0dXJlICYmIHRoaXMuZmVhdHVyZS5nZW9tZXRyeSAmJiB0aGlzLmZlYXR1cmUuZ2VvbWV0cnkudHlwZTtcclxuXHJcbiAgXHRcdGlmICh0eXBlID09PSAnTXVsdGlQb2ludCcpIHtcclxuICBcdFx0XHRyZXR1cm4gdGhpcy50b011bHRpUG9pbnQocHJlY2lzaW9uKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dmFyIGlzR2VvbWV0cnlDb2xsZWN0aW9uID0gdHlwZSA9PT0gJ0dlb21ldHJ5Q29sbGVjdGlvbicsXHJcbiAgXHRcdCAgICBqc29ucyA9IFtdO1xyXG5cclxuICBcdFx0dGhpcy5lYWNoTGF5ZXIoZnVuY3Rpb24gKGxheWVyKSB7XHJcbiAgXHRcdFx0aWYgKGxheWVyLnRvR2VvSlNPTikge1xyXG4gIFx0XHRcdFx0dmFyIGpzb24gPSBsYXllci50b0dlb0pTT04ocHJlY2lzaW9uKTtcclxuICBcdFx0XHRcdGlmIChpc0dlb21ldHJ5Q29sbGVjdGlvbikge1xyXG4gIFx0XHRcdFx0XHRqc29ucy5wdXNoKGpzb24uZ2VvbWV0cnkpO1xyXG4gIFx0XHRcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRcdFx0dmFyIGZlYXR1cmUgPSBhc0ZlYXR1cmUoanNvbik7XHJcbiAgXHRcdFx0XHRcdC8vIFNxdWFzaCBuZXN0ZWQgZmVhdHVyZSBjb2xsZWN0aW9uc1xyXG4gIFx0XHRcdFx0XHRpZiAoZmVhdHVyZS50eXBlID09PSAnRmVhdHVyZUNvbGxlY3Rpb24nKSB7XHJcbiAgXHRcdFx0XHRcdFx0anNvbnMucHVzaC5hcHBseShqc29ucywgZmVhdHVyZS5mZWF0dXJlcyk7XHJcbiAgXHRcdFx0XHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0XHRcdFx0anNvbnMucHVzaChmZWF0dXJlKTtcclxuICBcdFx0XHRcdFx0fVxyXG4gIFx0XHRcdFx0fVxyXG4gIFx0XHRcdH1cclxuICBcdFx0fSk7XHJcblxyXG4gIFx0XHRpZiAoaXNHZW9tZXRyeUNvbGxlY3Rpb24pIHtcclxuICBcdFx0XHRyZXR1cm4gZ2V0RmVhdHVyZSh0aGlzLCB7XHJcbiAgXHRcdFx0XHRnZW9tZXRyaWVzOiBqc29ucyxcclxuICBcdFx0XHRcdHR5cGU6ICdHZW9tZXRyeUNvbGxlY3Rpb24nXHJcbiAgXHRcdFx0fSk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiB7XHJcbiAgXHRcdFx0dHlwZTogJ0ZlYXR1cmVDb2xsZWN0aW9uJyxcclxuICBcdFx0XHRmZWF0dXJlczoganNvbnNcclxuICBcdFx0fTtcclxuICBcdH1cclxuICB9KTtcclxuXHJcbiAgLy8gQG5hbWVzcGFjZSBHZW9KU09OXHJcbiAgLy8gQGZhY3RvcnkgTC5nZW9KU09OKGdlb2pzb24/OiBPYmplY3QsIG9wdGlvbnM/OiBHZW9KU09OIG9wdGlvbnMpXHJcbiAgLy8gQ3JlYXRlcyBhIEdlb0pTT04gbGF5ZXIuIE9wdGlvbmFsbHkgYWNjZXB0cyBhbiBvYmplY3QgaW5cclxuICAvLyBbR2VvSlNPTiBmb3JtYXRdKGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmM3OTQ2KSB0byBkaXNwbGF5IG9uIHRoZSBtYXBcclxuICAvLyAoeW91IGNhbiBhbHRlcm5hdGl2ZWx5IGFkZCBpdCBsYXRlciB3aXRoIGBhZGREYXRhYCBtZXRob2QpIGFuZCBhbiBgb3B0aW9uc2Agb2JqZWN0LlxyXG4gIGZ1bmN0aW9uIGdlb0pTT04oZ2VvanNvbiwgb3B0aW9ucykge1xyXG4gIFx0cmV0dXJuIG5ldyBHZW9KU09OKGdlb2pzb24sIG9wdGlvbnMpO1xyXG4gIH1cclxuXHJcbiAgLy8gQmFja3dhcmQgY29tcGF0aWJpbGl0eS5cclxuICB2YXIgZ2VvSnNvbiA9IGdlb0pTT047XG5cbiAgLypcclxuICAgKiBAY2xhc3MgSW1hZ2VPdmVybGF5XHJcbiAgICogQGFrYSBMLkltYWdlT3ZlcmxheVxyXG4gICAqIEBpbmhlcml0cyBJbnRlcmFjdGl2ZSBsYXllclxyXG4gICAqXHJcbiAgICogVXNlZCB0byBsb2FkIGFuZCBkaXNwbGF5IGEgc2luZ2xlIGltYWdlIG92ZXIgc3BlY2lmaWMgYm91bmRzIG9mIHRoZSBtYXAuIEV4dGVuZHMgYExheWVyYC5cclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICpcclxuICAgKiBgYGBqc1xyXG4gICAqIHZhciBpbWFnZVVybCA9ICdodHRwczovL21hcHMubGliLnV0ZXhhcy5lZHUvbWFwcy9oaXN0b3JpY2FsL25ld2Fya19ual8xOTIyLmpwZycsXHJcbiAgICogXHRpbWFnZUJvdW5kcyA9IFtbNDAuNzEyMjE2LCAtNzQuMjI2NTVdLCBbNDAuNzczOTQxLCAtNzQuMTI1NDRdXTtcclxuICAgKiBMLmltYWdlT3ZlcmxheShpbWFnZVVybCwgaW1hZ2VCb3VuZHMpLmFkZFRvKG1hcCk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcblxyXG4gIHZhciBJbWFnZU92ZXJsYXkgPSBMYXllci5leHRlbmQoe1xyXG5cclxuICBcdC8vIEBzZWN0aW9uXHJcbiAgXHQvLyBAYWthIEltYWdlT3ZlcmxheSBvcHRpb25zXHJcbiAgXHRvcHRpb25zOiB7XHJcbiAgXHRcdC8vIEBvcHRpb24gb3BhY2l0eTogTnVtYmVyID0gMS4wXHJcbiAgXHRcdC8vIFRoZSBvcGFjaXR5IG9mIHRoZSBpbWFnZSBvdmVybGF5LlxyXG4gIFx0XHRvcGFjaXR5OiAxLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBhbHQ6IFN0cmluZyA9ICcnXHJcbiAgXHRcdC8vIFRleHQgZm9yIHRoZSBgYWx0YCBhdHRyaWJ1dGUgb2YgdGhlIGltYWdlICh1c2VmdWwgZm9yIGFjY2Vzc2liaWxpdHkpLlxyXG4gIFx0XHRhbHQ6ICcnLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBpbnRlcmFjdGl2ZTogQm9vbGVhbiA9IGZhbHNlXHJcbiAgXHRcdC8vIElmIGB0cnVlYCwgdGhlIGltYWdlIG92ZXJsYXkgd2lsbCBlbWl0IFttb3VzZSBldmVudHNdKCNpbnRlcmFjdGl2ZS1sYXllcikgd2hlbiBjbGlja2VkIG9yIGhvdmVyZWQuXHJcbiAgXHRcdGludGVyYWN0aXZlOiBmYWxzZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gY3Jvc3NPcmlnaW46IEJvb2xlYW58U3RyaW5nID0gZmFsc2VcclxuICBcdFx0Ly8gV2hldGhlciB0aGUgY3Jvc3NPcmlnaW4gYXR0cmlidXRlIHdpbGwgYmUgYWRkZWQgdG8gdGhlIGltYWdlLlxyXG4gIFx0XHQvLyBJZiBhIFN0cmluZyBpcyBwcm92aWRlZCwgdGhlIGltYWdlIHdpbGwgaGF2ZSBpdHMgY3Jvc3NPcmlnaW4gYXR0cmlidXRlIHNldCB0byB0aGUgU3RyaW5nIHByb3ZpZGVkLiBUaGlzIGlzIG5lZWRlZCBpZiB5b3Ugd2FudCB0byBhY2Nlc3MgaW1hZ2UgcGl4ZWwgZGF0YS5cclxuICBcdFx0Ly8gUmVmZXIgdG8gW0NPUlMgU2V0dGluZ3NdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0hUTUwvQ09SU19zZXR0aW5nc19hdHRyaWJ1dGVzKSBmb3IgdmFsaWQgU3RyaW5nIHZhbHVlcy5cclxuICBcdFx0Y3Jvc3NPcmlnaW46IGZhbHNlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBlcnJvck92ZXJsYXlVcmw6IFN0cmluZyA9ICcnXHJcbiAgXHRcdC8vIFVSTCB0byB0aGUgb3ZlcmxheSBpbWFnZSB0byBzaG93IGluIHBsYWNlIG9mIHRoZSBvdmVybGF5IHRoYXQgZmFpbGVkIHRvIGxvYWQuXHJcbiAgXHRcdGVycm9yT3ZlcmxheVVybDogJycsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHpJbmRleDogTnVtYmVyID0gMVxyXG4gIFx0XHQvLyBUaGUgZXhwbGljaXQgW3pJbmRleF0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQ1NTL0NTU19Qb3NpdGlvbmluZy9VbmRlcnN0YW5kaW5nX3pfaW5kZXgpIG9mIHRoZSBvdmVybGF5IGxheWVyLlxyXG4gIFx0XHR6SW5kZXg6IDEsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIGNsYXNzTmFtZTogU3RyaW5nID0gJydcclxuICBcdFx0Ly8gQSBjdXN0b20gY2xhc3MgbmFtZSB0byBhc3NpZ24gdG8gdGhlIGltYWdlLiBFbXB0eSBieSBkZWZhdWx0LlxyXG4gIFx0XHRjbGFzc05hbWU6ICcnXHJcbiAgXHR9LFxyXG5cclxuICBcdGluaXRpYWxpemU6IGZ1bmN0aW9uICh1cmwsIGJvdW5kcywgb3B0aW9ucykgeyAvLyAoU3RyaW5nLCBMYXRMbmdCb3VuZHMsIE9iamVjdClcclxuICBcdFx0dGhpcy5fdXJsID0gdXJsO1xyXG4gIFx0XHR0aGlzLl9ib3VuZHMgPSB0b0xhdExuZ0JvdW5kcyhib3VuZHMpO1xyXG5cclxuICBcdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcclxuICBcdH0sXHJcblxyXG4gIFx0b25BZGQ6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKCF0aGlzLl9pbWFnZSkge1xyXG4gIFx0XHRcdHRoaXMuX2luaXRJbWFnZSgpO1xyXG5cclxuICBcdFx0XHRpZiAodGhpcy5vcHRpb25zLm9wYWNpdHkgPCAxKSB7XHJcbiAgXHRcdFx0XHR0aGlzLl91cGRhdGVPcGFjaXR5KCk7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAodGhpcy5vcHRpb25zLmludGVyYWN0aXZlKSB7XHJcbiAgXHRcdFx0YWRkQ2xhc3ModGhpcy5faW1hZ2UsICdsZWFmbGV0LWludGVyYWN0aXZlJyk7XHJcbiAgXHRcdFx0dGhpcy5hZGRJbnRlcmFjdGl2ZVRhcmdldCh0aGlzLl9pbWFnZSk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMuZ2V0UGFuZSgpLmFwcGVuZENoaWxkKHRoaXMuX2ltYWdlKTtcclxuICBcdFx0dGhpcy5fcmVzZXQoKTtcclxuICBcdH0sXHJcblxyXG4gIFx0b25SZW1vdmU6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmVtb3ZlKHRoaXMuX2ltYWdlKTtcclxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5pbnRlcmFjdGl2ZSkge1xyXG4gIFx0XHRcdHRoaXMucmVtb3ZlSW50ZXJhY3RpdmVUYXJnZXQodGhpcy5faW1hZ2UpO1xyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2V0T3BhY2l0eShvcGFjaXR5OiBOdW1iZXIpOiB0aGlzXHJcbiAgXHQvLyBTZXRzIHRoZSBvcGFjaXR5IG9mIHRoZSBvdmVybGF5LlxyXG4gIFx0c2V0T3BhY2l0eTogZnVuY3Rpb24gKG9wYWNpdHkpIHtcclxuICBcdFx0dGhpcy5vcHRpb25zLm9wYWNpdHkgPSBvcGFjaXR5O1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX2ltYWdlKSB7XHJcbiAgXHRcdFx0dGhpcy5fdXBkYXRlT3BhY2l0eSgpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRzZXRTdHlsZTogZnVuY3Rpb24gKHN0eWxlT3B0cykge1xyXG4gIFx0XHRpZiAoc3R5bGVPcHRzLm9wYWNpdHkpIHtcclxuICBcdFx0XHR0aGlzLnNldE9wYWNpdHkoc3R5bGVPcHRzLm9wYWNpdHkpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGJyaW5nVG9Gcm9udCgpOiB0aGlzXHJcbiAgXHQvLyBCcmluZ3MgdGhlIGxheWVyIHRvIHRoZSB0b3Agb2YgYWxsIG92ZXJsYXlzLlxyXG4gIFx0YnJpbmdUb0Zyb250OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICh0aGlzLl9tYXApIHtcclxuICBcdFx0XHR0b0Zyb250KHRoaXMuX2ltYWdlKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBicmluZ1RvQmFjaygpOiB0aGlzXHJcbiAgXHQvLyBCcmluZ3MgdGhlIGxheWVyIHRvIHRoZSBib3R0b20gb2YgYWxsIG92ZXJsYXlzLlxyXG4gIFx0YnJpbmdUb0JhY2s6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKHRoaXMuX21hcCkge1xyXG4gIFx0XHRcdHRvQmFjayh0aGlzLl9pbWFnZSk7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2V0VXJsKHVybDogU3RyaW5nKTogdGhpc1xyXG4gIFx0Ly8gQ2hhbmdlcyB0aGUgVVJMIG9mIHRoZSBpbWFnZS5cclxuICBcdHNldFVybDogZnVuY3Rpb24gKHVybCkge1xyXG4gIFx0XHR0aGlzLl91cmwgPSB1cmw7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5faW1hZ2UpIHtcclxuICBcdFx0XHR0aGlzLl9pbWFnZS5zcmMgPSB1cmw7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2V0Qm91bmRzKGJvdW5kczogTGF0TG5nQm91bmRzKTogdGhpc1xyXG4gIFx0Ly8gVXBkYXRlIHRoZSBib3VuZHMgdGhhdCB0aGlzIEltYWdlT3ZlcmxheSBjb3ZlcnNcclxuICBcdHNldEJvdW5kczogZnVuY3Rpb24gKGJvdW5kcykge1xyXG4gIFx0XHR0aGlzLl9ib3VuZHMgPSB0b0xhdExuZ0JvdW5kcyhib3VuZHMpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX21hcCkge1xyXG4gIFx0XHRcdHRoaXMuX3Jlc2V0KCk7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdGdldEV2ZW50czogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR2YXIgZXZlbnRzID0ge1xyXG4gIFx0XHRcdHpvb206IHRoaXMuX3Jlc2V0LFxyXG4gIFx0XHRcdHZpZXdyZXNldDogdGhpcy5fcmVzZXRcclxuICBcdFx0fTtcclxuXHJcbiAgXHRcdGlmICh0aGlzLl96b29tQW5pbWF0ZWQpIHtcclxuICBcdFx0XHRldmVudHMuem9vbWFuaW0gPSB0aGlzLl9hbmltYXRlWm9vbTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0cmV0dXJuIGV2ZW50cztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBzZXRaSW5kZXgodmFsdWU6IE51bWJlcik6IHRoaXNcclxuICBcdC8vIENoYW5nZXMgdGhlIFt6SW5kZXhdKCNpbWFnZW92ZXJsYXktemluZGV4KSBvZiB0aGUgaW1hZ2Ugb3ZlcmxheS5cclxuICBcdHNldFpJbmRleDogZnVuY3Rpb24gKHZhbHVlKSB7XHJcbiAgXHRcdHRoaXMub3B0aW9ucy56SW5kZXggPSB2YWx1ZTtcclxuICBcdFx0dGhpcy5fdXBkYXRlWkluZGV4KCk7XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGdldEJvdW5kcygpOiBMYXRMbmdCb3VuZHNcclxuICBcdC8vIEdldCB0aGUgYm91bmRzIHRoYXQgdGhpcyBJbWFnZU92ZXJsYXkgY292ZXJzXHJcbiAgXHRnZXRCb3VuZHM6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0cmV0dXJuIHRoaXMuX2JvdW5kcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRFbGVtZW50KCk6IEhUTUxFbGVtZW50XHJcbiAgXHQvLyBSZXR1cm5zIHRoZSBpbnN0YW5jZSBvZiBbYEhUTUxJbWFnZUVsZW1lbnRgXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvSFRNTEltYWdlRWxlbWVudClcclxuICBcdC8vIHVzZWQgYnkgdGhpcyBvdmVybGF5LlxyXG4gIFx0Z2V0RWxlbWVudDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5faW1hZ2U7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9pbml0SW1hZ2U6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dmFyIHdhc0VsZW1lbnRTdXBwbGllZCA9IHRoaXMuX3VybC50YWdOYW1lID09PSAnSU1HJztcclxuICBcdFx0dmFyIGltZyA9IHRoaXMuX2ltYWdlID0gd2FzRWxlbWVudFN1cHBsaWVkID8gdGhpcy5fdXJsIDogY3JlYXRlJDEoJ2ltZycpO1xyXG5cclxuICBcdFx0YWRkQ2xhc3MoaW1nLCAnbGVhZmxldC1pbWFnZS1sYXllcicpO1xyXG4gIFx0XHRpZiAodGhpcy5fem9vbUFuaW1hdGVkKSB7IGFkZENsYXNzKGltZywgJ2xlYWZsZXQtem9vbS1hbmltYXRlZCcpOyB9XHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMuY2xhc3NOYW1lKSB7IGFkZENsYXNzKGltZywgdGhpcy5vcHRpb25zLmNsYXNzTmFtZSk7IH1cclxuXHJcbiAgXHRcdGltZy5vbnNlbGVjdHN0YXJ0ID0gZmFsc2VGbjtcclxuICBcdFx0aW1nLm9ubW91c2Vtb3ZlID0gZmFsc2VGbjtcclxuXHJcbiAgXHRcdC8vIEBldmVudCBsb2FkOiBFdmVudFxyXG4gIFx0XHQvLyBGaXJlZCB3aGVuIHRoZSBJbWFnZU92ZXJsYXkgbGF5ZXIgaGFzIGxvYWRlZCBpdHMgaW1hZ2VcclxuICBcdFx0aW1nLm9ubG9hZCA9IGJpbmQodGhpcy5maXJlLCB0aGlzLCAnbG9hZCcpO1xyXG4gIFx0XHRpbWcub25lcnJvciA9IGJpbmQodGhpcy5fb3ZlcmxheU9uRXJyb3IsIHRoaXMsICdlcnJvcicpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5jcm9zc09yaWdpbiB8fCB0aGlzLm9wdGlvbnMuY3Jvc3NPcmlnaW4gPT09ICcnKSB7XHJcbiAgXHRcdFx0aW1nLmNyb3NzT3JpZ2luID0gdGhpcy5vcHRpb25zLmNyb3NzT3JpZ2luID09PSB0cnVlID8gJycgOiB0aGlzLm9wdGlvbnMuY3Jvc3NPcmlnaW47XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMuekluZGV4KSB7XHJcbiAgXHRcdFx0dGhpcy5fdXBkYXRlWkluZGV4KCk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmICh3YXNFbGVtZW50U3VwcGxpZWQpIHtcclxuICBcdFx0XHR0aGlzLl91cmwgPSBpbWcuc3JjO1xyXG4gIFx0XHRcdHJldHVybjtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0aW1nLnNyYyA9IHRoaXMuX3VybDtcclxuICBcdFx0aW1nLmFsdCA9IHRoaXMub3B0aW9ucy5hbHQ7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9hbmltYXRlWm9vbTogZnVuY3Rpb24gKGUpIHtcclxuICBcdFx0dmFyIHNjYWxlID0gdGhpcy5fbWFwLmdldFpvb21TY2FsZShlLnpvb20pLFxyXG4gIFx0XHQgICAgb2Zmc2V0ID0gdGhpcy5fbWFwLl9sYXRMbmdCb3VuZHNUb05ld0xheWVyQm91bmRzKHRoaXMuX2JvdW5kcywgZS56b29tLCBlLmNlbnRlcikubWluO1xyXG5cclxuICBcdFx0c2V0VHJhbnNmb3JtKHRoaXMuX2ltYWdlLCBvZmZzZXQsIHNjYWxlKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X3Jlc2V0OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHZhciBpbWFnZSA9IHRoaXMuX2ltYWdlLFxyXG4gIFx0XHQgICAgYm91bmRzID0gbmV3IEJvdW5kcyhcclxuICBcdFx0ICAgICAgICB0aGlzLl9tYXAubGF0TG5nVG9MYXllclBvaW50KHRoaXMuX2JvdW5kcy5nZXROb3J0aFdlc3QoKSksXHJcbiAgXHRcdCAgICAgICAgdGhpcy5fbWFwLmxhdExuZ1RvTGF5ZXJQb2ludCh0aGlzLl9ib3VuZHMuZ2V0U291dGhFYXN0KCkpKSxcclxuICBcdFx0ICAgIHNpemUgPSBib3VuZHMuZ2V0U2l6ZSgpO1xyXG5cclxuICBcdFx0c2V0UG9zaXRpb24oaW1hZ2UsIGJvdW5kcy5taW4pO1xyXG5cclxuICBcdFx0aW1hZ2Uuc3R5bGUud2lkdGggID0gc2l6ZS54ICsgJ3B4JztcclxuICBcdFx0aW1hZ2Uuc3R5bGUuaGVpZ2h0ID0gc2l6ZS55ICsgJ3B4JztcclxuICBcdH0sXHJcblxyXG4gIFx0X3VwZGF0ZU9wYWNpdHk6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0c2V0T3BhY2l0eSh0aGlzLl9pbWFnZSwgdGhpcy5vcHRpb25zLm9wYWNpdHkpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfdXBkYXRlWkluZGV4OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICh0aGlzLl9pbWFnZSAmJiB0aGlzLm9wdGlvbnMuekluZGV4ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5vcHRpb25zLnpJbmRleCAhPT0gbnVsbCkge1xyXG4gIFx0XHRcdHRoaXMuX2ltYWdlLnN0eWxlLnpJbmRleCA9IHRoaXMub3B0aW9ucy56SW5kZXg7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0X292ZXJsYXlPbkVycm9yOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdC8vIEBldmVudCBlcnJvcjogRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgSW1hZ2VPdmVybGF5IGxheWVyIGZhaWxzIHRvIGxvYWQgaXRzIGltYWdlXHJcbiAgXHRcdHRoaXMuZmlyZSgnZXJyb3InKTtcclxuXHJcbiAgXHRcdHZhciBlcnJvclVybCA9IHRoaXMub3B0aW9ucy5lcnJvck92ZXJsYXlVcmw7XHJcbiAgXHRcdGlmIChlcnJvclVybCAmJiB0aGlzLl91cmwgIT09IGVycm9yVXJsKSB7XHJcbiAgXHRcdFx0dGhpcy5fdXJsID0gZXJyb3JVcmw7XHJcbiAgXHRcdFx0dGhpcy5faW1hZ2Uuc3JjID0gZXJyb3JVcmw7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRDZW50ZXIoKTogTGF0TG5nXHJcbiAgXHQvLyBSZXR1cm5zIHRoZSBjZW50ZXIgb2YgdGhlIEltYWdlT3ZlcmxheS5cclxuICBcdGdldENlbnRlcjogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5fYm91bmRzLmdldENlbnRlcigpO1xyXG4gIFx0fVxyXG4gIH0pO1xyXG5cclxuICAvLyBAZmFjdG9yeSBMLmltYWdlT3ZlcmxheShpbWFnZVVybDogU3RyaW5nLCBib3VuZHM6IExhdExuZ0JvdW5kcywgb3B0aW9ucz86IEltYWdlT3ZlcmxheSBvcHRpb25zKVxyXG4gIC8vIEluc3RhbnRpYXRlcyBhbiBpbWFnZSBvdmVybGF5IG9iamVjdCBnaXZlbiB0aGUgVVJMIG9mIHRoZSBpbWFnZSBhbmQgdGhlXHJcbiAgLy8gZ2VvZ3JhcGhpY2FsIGJvdW5kcyBpdCBpcyB0aWVkIHRvLlxyXG4gIHZhciBpbWFnZU92ZXJsYXkgPSBmdW5jdGlvbiAodXJsLCBib3VuZHMsIG9wdGlvbnMpIHtcclxuICBcdHJldHVybiBuZXcgSW1hZ2VPdmVybGF5KHVybCwgYm91bmRzLCBvcHRpb25zKTtcclxuICB9O1xuXG4gIC8qXHJcbiAgICogQGNsYXNzIFZpZGVvT3ZlcmxheVxyXG4gICAqIEBha2EgTC5WaWRlb092ZXJsYXlcclxuICAgKiBAaW5oZXJpdHMgSW1hZ2VPdmVybGF5XHJcbiAgICpcclxuICAgKiBVc2VkIHRvIGxvYWQgYW5kIGRpc3BsYXkgYSB2aWRlbyBwbGF5ZXIgb3ZlciBzcGVjaWZpYyBib3VuZHMgb2YgdGhlIG1hcC4gRXh0ZW5kcyBgSW1hZ2VPdmVybGF5YC5cclxuICAgKlxyXG4gICAqIEEgdmlkZW8gb3ZlcmxheSB1c2VzIHRoZSBbYDx2aWRlbz5gXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9IVE1ML0VsZW1lbnQvdmlkZW8pXHJcbiAgICogSFRNTDUgZWxlbWVudC5cclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICpcclxuICAgKiBgYGBqc1xyXG4gICAqIHZhciB2aWRlb1VybCA9ICdodHRwczovL3d3dy5tYXBib3guY29tL2JpdGVzLzAwMTg4L3BhdHJpY2lhX25hc2Eud2VibScsXHJcbiAgICogXHR2aWRlb0JvdW5kcyA9IFtbIDMyLCAtMTMwXSwgWyAxMywgLTEwMF1dO1xyXG4gICAqIEwudmlkZW9PdmVybGF5KHZpZGVvVXJsLCB2aWRlb0JvdW5kcyApLmFkZFRvKG1hcCk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcblxyXG4gIHZhciBWaWRlb092ZXJsYXkgPSBJbWFnZU92ZXJsYXkuZXh0ZW5kKHtcclxuXHJcbiAgXHQvLyBAc2VjdGlvblxyXG4gIFx0Ly8gQGFrYSBWaWRlb092ZXJsYXkgb3B0aW9uc1xyXG4gIFx0b3B0aW9uczoge1xyXG4gIFx0XHQvLyBAb3B0aW9uIGF1dG9wbGF5OiBCb29sZWFuID0gdHJ1ZVxyXG4gIFx0XHQvLyBXaGV0aGVyIHRoZSB2aWRlbyBzdGFydHMgcGxheWluZyBhdXRvbWF0aWNhbGx5IHdoZW4gbG9hZGVkLlxyXG4gIFx0XHQvLyBPbiBzb21lIGJyb3dzZXJzIGF1dG9wbGF5IHdpbGwgb25seSB3b3JrIHdpdGggYG11dGVkOiB0cnVlYFxyXG4gIFx0XHRhdXRvcGxheTogdHJ1ZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gbG9vcDogQm9vbGVhbiA9IHRydWVcclxuICBcdFx0Ly8gV2hldGhlciB0aGUgdmlkZW8gd2lsbCBsb29wIGJhY2sgdG8gdGhlIGJlZ2lubmluZyB3aGVuIHBsYXllZC5cclxuICBcdFx0bG9vcDogdHJ1ZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24ga2VlcEFzcGVjdFJhdGlvOiBCb29sZWFuID0gdHJ1ZVxyXG4gIFx0XHQvLyBXaGV0aGVyIHRoZSB2aWRlbyB3aWxsIHNhdmUgYXNwZWN0IHJhdGlvIGFmdGVyIHRoZSBwcm9qZWN0aW9uLlxyXG4gIFx0XHQvLyBSZWxldmFudCBmb3Igc3VwcG9ydGVkIGJyb3dzZXJzLiBTZWUgW2Jyb3dzZXIgY29tcGF0aWJpbGl0eV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQ1NTL29iamVjdC1maXQpXHJcbiAgXHRcdGtlZXBBc3BlY3RSYXRpbzogdHJ1ZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gbXV0ZWQ6IEJvb2xlYW4gPSBmYWxzZVxyXG4gIFx0XHQvLyBXaGV0aGVyIHRoZSB2aWRlbyBzdGFydHMgb24gbXV0ZSB3aGVuIGxvYWRlZC5cclxuICBcdFx0bXV0ZWQ6IGZhbHNlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBwbGF5c0lubGluZTogQm9vbGVhbiA9IHRydWVcclxuICBcdFx0Ly8gTW9iaWxlIGJyb3dzZXJzIHdpbGwgcGxheSB0aGUgdmlkZW8gcmlnaHQgd2hlcmUgaXQgaXMgaW5zdGVhZCBvZiBvcGVuIGl0IHVwIGluIGZ1bGxzY3JlZW4gbW9kZS5cclxuICBcdFx0cGxheXNJbmxpbmU6IHRydWVcclxuICBcdH0sXHJcblxyXG4gIFx0X2luaXRJbWFnZTogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR2YXIgd2FzRWxlbWVudFN1cHBsaWVkID0gdGhpcy5fdXJsLnRhZ05hbWUgPT09ICdWSURFTyc7XHJcbiAgXHRcdHZhciB2aWQgPSB0aGlzLl9pbWFnZSA9IHdhc0VsZW1lbnRTdXBwbGllZCA/IHRoaXMuX3VybCA6IGNyZWF0ZSQxKCd2aWRlbycpO1xyXG5cclxuICBcdFx0YWRkQ2xhc3ModmlkLCAnbGVhZmxldC1pbWFnZS1sYXllcicpO1xyXG4gIFx0XHRpZiAodGhpcy5fem9vbUFuaW1hdGVkKSB7IGFkZENsYXNzKHZpZCwgJ2xlYWZsZXQtem9vbS1hbmltYXRlZCcpOyB9XHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMuY2xhc3NOYW1lKSB7IGFkZENsYXNzKHZpZCwgdGhpcy5vcHRpb25zLmNsYXNzTmFtZSk7IH1cclxuXHJcbiAgXHRcdHZpZC5vbnNlbGVjdHN0YXJ0ID0gZmFsc2VGbjtcclxuICBcdFx0dmlkLm9ubW91c2Vtb3ZlID0gZmFsc2VGbjtcclxuXHJcbiAgXHRcdC8vIEBldmVudCBsb2FkOiBFdmVudFxyXG4gIFx0XHQvLyBGaXJlZCB3aGVuIHRoZSB2aWRlbyBoYXMgZmluaXNoZWQgbG9hZGluZyB0aGUgZmlyc3QgZnJhbWVcclxuICBcdFx0dmlkLm9ubG9hZGVkZGF0YSA9IGJpbmQodGhpcy5maXJlLCB0aGlzLCAnbG9hZCcpO1xyXG5cclxuICBcdFx0aWYgKHdhc0VsZW1lbnRTdXBwbGllZCkge1xyXG4gIFx0XHRcdHZhciBzb3VyY2VFbGVtZW50cyA9IHZpZC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnc291cmNlJyk7XHJcbiAgXHRcdFx0dmFyIHNvdXJjZXMgPSBbXTtcclxuICBcdFx0XHRmb3IgKHZhciBqID0gMDsgaiA8IHNvdXJjZUVsZW1lbnRzLmxlbmd0aDsgaisrKSB7XHJcbiAgXHRcdFx0XHRzb3VyY2VzLnB1c2goc291cmNlRWxlbWVudHNbal0uc3JjKTtcclxuICBcdFx0XHR9XHJcblxyXG4gIFx0XHRcdHRoaXMuX3VybCA9IChzb3VyY2VFbGVtZW50cy5sZW5ndGggPiAwKSA/IHNvdXJjZXMgOiBbdmlkLnNyY107XHJcbiAgXHRcdFx0cmV0dXJuO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRpZiAoIWlzQXJyYXkodGhpcy5fdXJsKSkgeyB0aGlzLl91cmwgPSBbdGhpcy5fdXJsXTsgfVxyXG5cclxuICBcdFx0aWYgKCF0aGlzLm9wdGlvbnMua2VlcEFzcGVjdFJhdGlvICYmIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh2aWQuc3R5bGUsICdvYmplY3RGaXQnKSkge1xyXG4gIFx0XHRcdHZpZC5zdHlsZVsnb2JqZWN0Rml0J10gPSAnZmlsbCc7XHJcbiAgXHRcdH1cclxuICBcdFx0dmlkLmF1dG9wbGF5ID0gISF0aGlzLm9wdGlvbnMuYXV0b3BsYXk7XHJcbiAgXHRcdHZpZC5sb29wID0gISF0aGlzLm9wdGlvbnMubG9vcDtcclxuICBcdFx0dmlkLm11dGVkID0gISF0aGlzLm9wdGlvbnMubXV0ZWQ7XHJcbiAgXHRcdHZpZC5wbGF5c0lubGluZSA9ICEhdGhpcy5vcHRpb25zLnBsYXlzSW5saW5lO1xyXG4gIFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX3VybC5sZW5ndGg7IGkrKykge1xyXG4gIFx0XHRcdHZhciBzb3VyY2UgPSBjcmVhdGUkMSgnc291cmNlJyk7XHJcbiAgXHRcdFx0c291cmNlLnNyYyA9IHRoaXMuX3VybFtpXTtcclxuICBcdFx0XHR2aWQuYXBwZW5kQ2hpbGQoc291cmNlKTtcclxuICBcdFx0fVxyXG4gIFx0fVxyXG5cclxuICBcdC8vIEBtZXRob2QgZ2V0RWxlbWVudCgpOiBIVE1MVmlkZW9FbGVtZW50XHJcbiAgXHQvLyBSZXR1cm5zIHRoZSBpbnN0YW5jZSBvZiBbYEhUTUxWaWRlb0VsZW1lbnRgXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvSFRNTFZpZGVvRWxlbWVudClcclxuICBcdC8vIHVzZWQgYnkgdGhpcyBvdmVybGF5LlxyXG4gIH0pO1xyXG5cclxuXHJcbiAgLy8gQGZhY3RvcnkgTC52aWRlb092ZXJsYXkodmlkZW86IFN0cmluZ3xBcnJheXxIVE1MVmlkZW9FbGVtZW50LCBib3VuZHM6IExhdExuZ0JvdW5kcywgb3B0aW9ucz86IFZpZGVvT3ZlcmxheSBvcHRpb25zKVxyXG4gIC8vIEluc3RhbnRpYXRlcyBhbiBpbWFnZSBvdmVybGF5IG9iamVjdCBnaXZlbiB0aGUgVVJMIG9mIHRoZSB2aWRlbyAob3IgYXJyYXkgb2YgVVJMcywgb3IgZXZlbiBhIHZpZGVvIGVsZW1lbnQpIGFuZCB0aGVcclxuICAvLyBnZW9ncmFwaGljYWwgYm91bmRzIGl0IGlzIHRpZWQgdG8uXHJcblxyXG4gIGZ1bmN0aW9uIHZpZGVvT3ZlcmxheSh2aWRlbywgYm91bmRzLCBvcHRpb25zKSB7XHJcbiAgXHRyZXR1cm4gbmV3IFZpZGVvT3ZlcmxheSh2aWRlbywgYm91bmRzLCBvcHRpb25zKTtcclxuICB9XG5cbiAgLypcbiAgICogQGNsYXNzIFNWR092ZXJsYXlcbiAgICogQGFrYSBMLlNWR092ZXJsYXlcbiAgICogQGluaGVyaXRzIEltYWdlT3ZlcmxheVxuICAgKlxuICAgKiBVc2VkIHRvIGxvYWQsIGRpc3BsYXkgYW5kIHByb3ZpZGUgRE9NIGFjY2VzcyB0byBhbiBTVkcgZmlsZSBvdmVyIHNwZWNpZmljIGJvdW5kcyBvZiB0aGUgbWFwLiBFeHRlbmRzIGBJbWFnZU92ZXJsYXlgLlxuICAgKlxuICAgKiBBbiBTVkcgb3ZlcmxheSB1c2VzIHRoZSBbYDxzdmc+YF0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvU1ZHL0VsZW1lbnQvc3ZnKSBlbGVtZW50LlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKlxuICAgKiBgYGBqc1xuICAgKiB2YXIgc3ZnRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsIFwic3ZnXCIpO1xuICAgKiBzdmdFbGVtZW50LnNldEF0dHJpYnV0ZSgneG1sbnMnLCBcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIpO1xuICAgKiBzdmdFbGVtZW50LnNldEF0dHJpYnV0ZSgndmlld0JveCcsIFwiMCAwIDIwMCAyMDBcIik7XG4gICAqIHN2Z0VsZW1lbnQuaW5uZXJIVE1MID0gJzxyZWN0IHdpZHRoPVwiMjAwXCIgaGVpZ2h0PVwiMjAwXCIvPjxyZWN0IHg9XCI3NVwiIHk9XCIyM1wiIHdpZHRoPVwiNTBcIiBoZWlnaHQ9XCI1MFwiIHN0eWxlPVwiZmlsbDpyZWRcIi8+PHJlY3QgeD1cIjc1XCIgeT1cIjEyM1wiIHdpZHRoPVwiNTBcIiBoZWlnaHQ9XCI1MFwiIHN0eWxlPVwiZmlsbDojMDAxM2ZmXCIvPic7XG4gICAqIHZhciBzdmdFbGVtZW50Qm91bmRzID0gWyBbIDMyLCAtMTMwIF0sIFsgMTMsIC0xMDAgXSBdO1xuICAgKiBMLnN2Z092ZXJsYXkoc3ZnRWxlbWVudCwgc3ZnRWxlbWVudEJvdW5kcykuYWRkVG8obWFwKTtcbiAgICogYGBgXG4gICAqL1xuXG4gIHZhciBTVkdPdmVybGF5ID0gSW1hZ2VPdmVybGF5LmV4dGVuZCh7XG4gIFx0X2luaXRJbWFnZTogZnVuY3Rpb24gKCkge1xuICBcdFx0dmFyIGVsID0gdGhpcy5faW1hZ2UgPSB0aGlzLl91cmw7XG5cbiAgXHRcdGFkZENsYXNzKGVsLCAnbGVhZmxldC1pbWFnZS1sYXllcicpO1xuICBcdFx0aWYgKHRoaXMuX3pvb21BbmltYXRlZCkgeyBhZGRDbGFzcyhlbCwgJ2xlYWZsZXQtem9vbS1hbmltYXRlZCcpOyB9XG4gIFx0XHRpZiAodGhpcy5vcHRpb25zLmNsYXNzTmFtZSkgeyBhZGRDbGFzcyhlbCwgdGhpcy5vcHRpb25zLmNsYXNzTmFtZSk7IH1cblxuICBcdFx0ZWwub25zZWxlY3RzdGFydCA9IGZhbHNlRm47XG4gIFx0XHRlbC5vbm1vdXNlbW92ZSA9IGZhbHNlRm47XG4gIFx0fVxuXG4gIFx0Ly8gQG1ldGhvZCBnZXRFbGVtZW50KCk6IFNWR0VsZW1lbnRcbiAgXHQvLyBSZXR1cm5zIHRoZSBpbnN0YW5jZSBvZiBbYFNWR0VsZW1lbnRgXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvU1ZHRWxlbWVudClcbiAgXHQvLyB1c2VkIGJ5IHRoaXMgb3ZlcmxheS5cbiAgfSk7XG5cblxuICAvLyBAZmFjdG9yeSBMLnN2Z092ZXJsYXkoc3ZnOiBTdHJpbmd8U1ZHRWxlbWVudCwgYm91bmRzOiBMYXRMbmdCb3VuZHMsIG9wdGlvbnM/OiBTVkdPdmVybGF5IG9wdGlvbnMpXG4gIC8vIEluc3RhbnRpYXRlcyBhbiBpbWFnZSBvdmVybGF5IG9iamVjdCBnaXZlbiBhbiBTVkcgZWxlbWVudCBhbmQgdGhlIGdlb2dyYXBoaWNhbCBib3VuZHMgaXQgaXMgdGllZCB0by5cbiAgLy8gQSB2aWV3Qm94IGF0dHJpYnV0ZSBpcyByZXF1aXJlZCBvbiB0aGUgU1ZHIGVsZW1lbnQgdG8gem9vbSBpbiBhbmQgb3V0IHByb3Blcmx5LlxuXG4gIGZ1bmN0aW9uIHN2Z092ZXJsYXkoZWwsIGJvdW5kcywgb3B0aW9ucykge1xuICBcdHJldHVybiBuZXcgU1ZHT3ZlcmxheShlbCwgYm91bmRzLCBvcHRpb25zKTtcbiAgfVxuXG4gIC8qXHJcbiAgICogQGNsYXNzIERpdk92ZXJsYXlcclxuICAgKiBAaW5oZXJpdHMgSW50ZXJhY3RpdmUgbGF5ZXJcclxuICAgKiBAYWthIEwuRGl2T3ZlcmxheVxyXG4gICAqIEJhc2UgbW9kZWwgZm9yIEwuUG9wdXAgYW5kIEwuVG9vbHRpcC4gSW5oZXJpdCBmcm9tIGl0IGZvciBjdXN0b20gb3ZlcmxheXMgbGlrZSBwbHVnaW5zLlxyXG4gICAqL1xyXG5cclxuICAvLyBAbmFtZXNwYWNlIERpdk92ZXJsYXlcclxuICB2YXIgRGl2T3ZlcmxheSA9IExheWVyLmV4dGVuZCh7XHJcblxyXG4gIFx0Ly8gQHNlY3Rpb25cclxuICBcdC8vIEBha2EgRGl2T3ZlcmxheSBvcHRpb25zXHJcbiAgXHRvcHRpb25zOiB7XHJcbiAgXHRcdC8vIEBvcHRpb24gaW50ZXJhY3RpdmU6IEJvb2xlYW4gPSBmYWxzZVxyXG4gIFx0XHQvLyBJZiB0cnVlLCB0aGUgcG9wdXAvdG9vbHRpcCB3aWxsIGxpc3RlbiB0byB0aGUgbW91c2UgZXZlbnRzLlxyXG4gIFx0XHRpbnRlcmFjdGl2ZTogZmFsc2UsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIG9mZnNldDogUG9pbnQgPSBQb2ludCgwLCAwKVxyXG4gIFx0XHQvLyBUaGUgb2Zmc2V0IG9mIHRoZSBvdmVybGF5IHBvc2l0aW9uLlxyXG4gIFx0XHRvZmZzZXQ6IFswLCAwXSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gY2xhc3NOYW1lOiBTdHJpbmcgPSAnJ1xyXG4gIFx0XHQvLyBBIGN1c3RvbSBDU1MgY2xhc3MgbmFtZSB0byBhc3NpZ24gdG8gdGhlIG92ZXJsYXkuXHJcbiAgXHRcdGNsYXNzTmFtZTogJycsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHBhbmU6IFN0cmluZyA9IHVuZGVmaW5lZFxyXG4gIFx0XHQvLyBgTWFwIHBhbmVgIHdoZXJlIHRoZSBvdmVybGF5IHdpbGwgYmUgYWRkZWQuXHJcbiAgXHRcdHBhbmU6IHVuZGVmaW5lZCxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gY29udGVudDogU3RyaW5nfEhUTUxFbGVtZW50fEZ1bmN0aW9uID0gJydcclxuICBcdFx0Ly8gU2V0cyB0aGUgSFRNTCBjb250ZW50IG9mIHRoZSBvdmVybGF5IHdoaWxlIGluaXRpYWxpemluZy4gSWYgYSBmdW5jdGlvbiBpcyBwYXNzZWQgdGhlIHNvdXJjZSBsYXllciB3aWxsIGJlXHJcbiAgXHRcdC8vIHBhc3NlZCB0byB0aGUgZnVuY3Rpb24uIFRoZSBmdW5jdGlvbiBzaG91bGQgcmV0dXJuIGEgYFN0cmluZ2Agb3IgYEhUTUxFbGVtZW50YCB0byBiZSB1c2VkIGluIHRoZSBvdmVybGF5LlxyXG4gIFx0XHRjb250ZW50OiAnJ1xyXG4gIFx0fSxcclxuXHJcbiAgXHRpbml0aWFsaXplOiBmdW5jdGlvbiAob3B0aW9ucywgc291cmNlKSB7XHJcbiAgXHRcdGlmIChvcHRpb25zICYmIChvcHRpb25zIGluc3RhbmNlb2YgTGF0TG5nIHx8IGlzQXJyYXkob3B0aW9ucykpKSB7XHJcbiAgXHRcdFx0dGhpcy5fbGF0bG5nID0gdG9MYXRMbmcob3B0aW9ucyk7XHJcbiAgXHRcdFx0c2V0T3B0aW9ucyh0aGlzLCBzb3VyY2UpO1xyXG4gIFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdHNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XHJcbiAgXHRcdFx0dGhpcy5fc291cmNlID0gc291cmNlO1xyXG4gIFx0XHR9XHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMuY29udGVudCkge1xyXG4gIFx0XHRcdHRoaXMuX2NvbnRlbnQgPSB0aGlzLm9wdGlvbnMuY29udGVudDtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIG9wZW5PbihtYXA6IE1hcCk6IHRoaXNcclxuICBcdC8vIEFkZHMgdGhlIG92ZXJsYXkgdG8gdGhlIG1hcC5cclxuICBcdC8vIEFsdGVybmF0aXZlIHRvIGBtYXAub3BlblBvcHVwKHBvcHVwKWAvYC5vcGVuVG9vbHRpcCh0b29sdGlwKWAuXHJcbiAgXHRvcGVuT246IGZ1bmN0aW9uIChtYXApIHtcclxuICBcdFx0bWFwID0gYXJndW1lbnRzLmxlbmd0aCA/IG1hcCA6IHRoaXMuX3NvdXJjZS5fbWFwOyAvLyBleHBlcmltZW50YWwsIG5vdCB0aGUgcGFydCBvZiBwdWJsaWMgYXBpXHJcbiAgXHRcdGlmICghbWFwLmhhc0xheWVyKHRoaXMpKSB7XHJcbiAgXHRcdFx0bWFwLmFkZExheWVyKHRoaXMpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGNsb3NlKCk6IHRoaXNcclxuICBcdC8vIENsb3NlcyB0aGUgb3ZlcmxheS5cclxuICBcdC8vIEFsdGVybmF0aXZlIHRvIGBtYXAuY2xvc2VQb3B1cChwb3B1cClgL2AuY2xvc2VUb29sdGlwKHRvb2x0aXApYFxyXG4gIFx0Ly8gYW5kIGBsYXllci5jbG9zZVBvcHVwKClgL2AuY2xvc2VUb29sdGlwKClgLlxyXG4gIFx0Y2xvc2U6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKHRoaXMuX21hcCkge1xyXG4gIFx0XHRcdHRoaXMuX21hcC5yZW1vdmVMYXllcih0aGlzKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCB0b2dnbGUobGF5ZXI/OiBMYXllcik6IHRoaXNcclxuICBcdC8vIE9wZW5zIG9yIGNsb3NlcyB0aGUgb3ZlcmxheSBib3VuZCB0byBsYXllciBkZXBlbmRpbmcgb24gaXRzIGN1cnJlbnQgc3RhdGUuXHJcbiAgXHQvLyBBcmd1bWVudCBtYXkgYmUgb21pdHRlZCBvbmx5IGZvciBvdmVybGF5IGJvdW5kIHRvIGxheWVyLlxyXG4gIFx0Ly8gQWx0ZXJuYXRpdmUgdG8gYGxheWVyLnRvZ2dsZVBvcHVwKClgL2AudG9nZ2xlVG9vbHRpcCgpYC5cclxuICBcdHRvZ2dsZTogZnVuY3Rpb24gKGxheWVyKSB7XHJcbiAgXHRcdGlmICh0aGlzLl9tYXApIHtcclxuICBcdFx0XHR0aGlzLmNsb3NlKCk7XHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0aWYgKGFyZ3VtZW50cy5sZW5ndGgpIHtcclxuICBcdFx0XHRcdHRoaXMuX3NvdXJjZSA9IGxheWVyO1xyXG4gIFx0XHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0XHRsYXllciA9IHRoaXMuX3NvdXJjZTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdFx0dGhpcy5fcHJlcGFyZU9wZW4oKTtcclxuXHJcbiAgXHRcdFx0Ly8gb3BlbiB0aGUgb3ZlcmxheSBvbiB0aGUgbWFwXHJcbiAgXHRcdFx0dGhpcy5vcGVuT24obGF5ZXIuX21hcCk7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdG9uQWRkOiBmdW5jdGlvbiAobWFwKSB7XHJcbiAgXHRcdHRoaXMuX3pvb21BbmltYXRlZCA9IG1hcC5fem9vbUFuaW1hdGVkO1xyXG5cclxuICBcdFx0aWYgKCF0aGlzLl9jb250YWluZXIpIHtcclxuICBcdFx0XHR0aGlzLl9pbml0TGF5b3V0KCk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmIChtYXAuX2ZhZGVBbmltYXRlZCkge1xyXG4gIFx0XHRcdHNldE9wYWNpdHkodGhpcy5fY29udGFpbmVyLCAwKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0Y2xlYXJUaW1lb3V0KHRoaXMuX3JlbW92ZVRpbWVvdXQpO1xyXG4gIFx0XHR0aGlzLmdldFBhbmUoKS5hcHBlbmRDaGlsZCh0aGlzLl9jb250YWluZXIpO1xyXG4gIFx0XHR0aGlzLnVwZGF0ZSgpO1xyXG5cclxuICBcdFx0aWYgKG1hcC5fZmFkZUFuaW1hdGVkKSB7XHJcbiAgXHRcdFx0c2V0T3BhY2l0eSh0aGlzLl9jb250YWluZXIsIDEpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR0aGlzLmJyaW5nVG9Gcm9udCgpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5pbnRlcmFjdGl2ZSkge1xyXG4gIFx0XHRcdGFkZENsYXNzKHRoaXMuX2NvbnRhaW5lciwgJ2xlYWZsZXQtaW50ZXJhY3RpdmUnKTtcclxuICBcdFx0XHR0aGlzLmFkZEludGVyYWN0aXZlVGFyZ2V0KHRoaXMuX2NvbnRhaW5lcik7XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0b25SZW1vdmU6IGZ1bmN0aW9uIChtYXApIHtcclxuICBcdFx0aWYgKG1hcC5fZmFkZUFuaW1hdGVkKSB7XHJcbiAgXHRcdFx0c2V0T3BhY2l0eSh0aGlzLl9jb250YWluZXIsIDApO1xyXG4gIFx0XHRcdHRoaXMuX3JlbW92ZVRpbWVvdXQgPSBzZXRUaW1lb3V0KGJpbmQocmVtb3ZlLCB1bmRlZmluZWQsIHRoaXMuX2NvbnRhaW5lciksIDIwMCk7XHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0cmVtb3ZlKHRoaXMuX2NvbnRhaW5lcik7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMuaW50ZXJhY3RpdmUpIHtcclxuICBcdFx0XHRyZW1vdmVDbGFzcyh0aGlzLl9jb250YWluZXIsICdsZWFmbGV0LWludGVyYWN0aXZlJyk7XHJcbiAgXHRcdFx0dGhpcy5yZW1vdmVJbnRlcmFjdGl2ZVRhcmdldCh0aGlzLl9jb250YWluZXIpO1xyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBuYW1lc3BhY2UgRGl2T3ZlcmxheVxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRMYXRMbmc6IExhdExuZ1xyXG4gIFx0Ly8gUmV0dXJucyB0aGUgZ2VvZ3JhcGhpY2FsIHBvaW50IG9mIHRoZSBvdmVybGF5LlxyXG4gIFx0Z2V0TGF0TG5nOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLl9sYXRsbmc7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2Qgc2V0TGF0TG5nKGxhdGxuZzogTGF0TG5nKTogdGhpc1xyXG4gIFx0Ly8gU2V0cyB0aGUgZ2VvZ3JhcGhpY2FsIHBvaW50IHdoZXJlIHRoZSBvdmVybGF5IHdpbGwgb3Blbi5cclxuICBcdHNldExhdExuZzogZnVuY3Rpb24gKGxhdGxuZykge1xyXG4gIFx0XHR0aGlzLl9sYXRsbmcgPSB0b0xhdExuZyhsYXRsbmcpO1xyXG4gIFx0XHRpZiAodGhpcy5fbWFwKSB7XHJcbiAgXHRcdFx0dGhpcy5fdXBkYXRlUG9zaXRpb24oKTtcclxuICBcdFx0XHR0aGlzLl9hZGp1c3RQYW4oKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRDb250ZW50OiBTdHJpbmd8SFRNTEVsZW1lbnRcclxuICBcdC8vIFJldHVybnMgdGhlIGNvbnRlbnQgb2YgdGhlIG92ZXJsYXkuXHJcbiAgXHRnZXRDb250ZW50OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLl9jb250ZW50O1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNldENvbnRlbnQoaHRtbENvbnRlbnQ6IFN0cmluZ3xIVE1MRWxlbWVudHxGdW5jdGlvbik6IHRoaXNcclxuICBcdC8vIFNldHMgdGhlIEhUTUwgY29udGVudCBvZiB0aGUgb3ZlcmxheS4gSWYgYSBmdW5jdGlvbiBpcyBwYXNzZWQgdGhlIHNvdXJjZSBsYXllciB3aWxsIGJlIHBhc3NlZCB0byB0aGUgZnVuY3Rpb24uXHJcbiAgXHQvLyBUaGUgZnVuY3Rpb24gc2hvdWxkIHJldHVybiBhIGBTdHJpbmdgIG9yIGBIVE1MRWxlbWVudGAgdG8gYmUgdXNlZCBpbiB0aGUgb3ZlcmxheS5cclxuICBcdHNldENvbnRlbnQ6IGZ1bmN0aW9uIChjb250ZW50KSB7XHJcbiAgXHRcdHRoaXMuX2NvbnRlbnQgPSBjb250ZW50O1xyXG4gIFx0XHR0aGlzLnVwZGF0ZSgpO1xyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRFbGVtZW50OiBTdHJpbmd8SFRNTEVsZW1lbnRcclxuICBcdC8vIFJldHVybnMgdGhlIEhUTUwgY29udGFpbmVyIG9mIHRoZSBvdmVybGF5LlxyXG4gIFx0Z2V0RWxlbWVudDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gdGhpcy5fY29udGFpbmVyO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHVwZGF0ZTogbnVsbFxyXG4gIFx0Ly8gVXBkYXRlcyB0aGUgb3ZlcmxheSBjb250ZW50LCBsYXlvdXQgYW5kIHBvc2l0aW9uLiBVc2VmdWwgZm9yIHVwZGF0aW5nIHRoZSBvdmVybGF5IGFmdGVyIHNvbWV0aGluZyBpbnNpZGUgY2hhbmdlZCwgZS5nLiBpbWFnZSBsb2FkZWQuXHJcbiAgXHR1cGRhdGU6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKCF0aGlzLl9tYXApIHsgcmV0dXJuOyB9XHJcblxyXG4gIFx0XHR0aGlzLl9jb250YWluZXIuc3R5bGUudmlzaWJpbGl0eSA9ICdoaWRkZW4nO1xyXG5cclxuICBcdFx0dGhpcy5fdXBkYXRlQ29udGVudCgpO1xyXG4gIFx0XHR0aGlzLl91cGRhdGVMYXlvdXQoKTtcclxuICBcdFx0dGhpcy5fdXBkYXRlUG9zaXRpb24oKTtcclxuXHJcbiAgXHRcdHRoaXMuX2NvbnRhaW5lci5zdHlsZS52aXNpYmlsaXR5ID0gJyc7XHJcblxyXG4gIFx0XHR0aGlzLl9hZGp1c3RQYW4oKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Z2V0RXZlbnRzOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHZhciBldmVudHMgPSB7XHJcbiAgXHRcdFx0em9vbTogdGhpcy5fdXBkYXRlUG9zaXRpb24sXHJcbiAgXHRcdFx0dmlld3Jlc2V0OiB0aGlzLl91cGRhdGVQb3NpdGlvblxyXG4gIFx0XHR9O1xyXG5cclxuICBcdFx0aWYgKHRoaXMuX3pvb21BbmltYXRlZCkge1xyXG4gIFx0XHRcdGV2ZW50cy56b29tYW5pbSA9IHRoaXMuX2FuaW1hdGVab29tO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiBldmVudHM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgaXNPcGVuOiBCb29sZWFuXHJcbiAgXHQvLyBSZXR1cm5zIGB0cnVlYCB3aGVuIHRoZSBvdmVybGF5IGlzIHZpc2libGUgb24gdGhlIG1hcC5cclxuICBcdGlzT3BlbjogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRyZXR1cm4gISF0aGlzLl9tYXAgJiYgdGhpcy5fbWFwLmhhc0xheWVyKHRoaXMpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGJyaW5nVG9Gcm9udDogdGhpc1xyXG4gIFx0Ly8gQnJpbmdzIHRoaXMgb3ZlcmxheSBpbiBmcm9udCBvZiBvdGhlciBvdmVybGF5cyAoaW4gdGhlIHNhbWUgbWFwIHBhbmUpLlxyXG4gIFx0YnJpbmdUb0Zyb250OiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICh0aGlzLl9tYXApIHtcclxuICBcdFx0XHR0b0Zyb250KHRoaXMuX2NvbnRhaW5lcik7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgYnJpbmdUb0JhY2s6IHRoaXNcclxuICBcdC8vIEJyaW5ncyB0aGlzIG92ZXJsYXkgdG8gdGhlIGJhY2sgb2Ygb3RoZXIgb3ZlcmxheXMgKGluIHRoZSBzYW1lIG1hcCBwYW5lKS5cclxuICBcdGJyaW5nVG9CYWNrOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICh0aGlzLl9tYXApIHtcclxuICBcdFx0XHR0b0JhY2sodGhpcy5fY29udGFpbmVyKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gcHJlcGFyZSBib3VuZCBvdmVybGF5IHRvIG9wZW46IHVwZGF0ZSBsYXRsbmcgcG9zIC8gY29udGVudCBzb3VyY2UgKGZvciBGZWF0dXJlR3JvdXApXHJcbiAgXHRfcHJlcGFyZU9wZW46IGZ1bmN0aW9uIChsYXRsbmcpIHtcclxuICBcdFx0dmFyIHNvdXJjZSA9IHRoaXMuX3NvdXJjZTtcclxuICBcdFx0aWYgKCFzb3VyY2UuX21hcCkgeyByZXR1cm4gZmFsc2U7IH1cclxuXHJcbiAgXHRcdGlmIChzb3VyY2UgaW5zdGFuY2VvZiBGZWF0dXJlR3JvdXApIHtcclxuICBcdFx0XHRzb3VyY2UgPSBudWxsO1xyXG4gIFx0XHRcdHZhciBsYXllcnMgPSB0aGlzLl9zb3VyY2UuX2xheWVycztcclxuICBcdFx0XHRmb3IgKHZhciBpZCBpbiBsYXllcnMpIHtcclxuICBcdFx0XHRcdGlmIChsYXllcnNbaWRdLl9tYXApIHtcclxuICBcdFx0XHRcdFx0c291cmNlID0gbGF5ZXJzW2lkXTtcclxuICBcdFx0XHRcdFx0YnJlYWs7XHJcbiAgXHRcdFx0XHR9XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHRcdGlmICghc291cmNlKSB7IHJldHVybiBmYWxzZTsgfSAvLyBVbmFibGUgdG8gZ2V0IHNvdXJjZSBsYXllci5cclxuXHJcbiAgXHRcdFx0Ly8gc2V0IG92ZXJsYXkgc291cmNlIHRvIHRoaXMgbGF5ZXJcclxuICBcdFx0XHR0aGlzLl9zb3VyY2UgPSBzb3VyY2U7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmICghbGF0bG5nKSB7XHJcbiAgXHRcdFx0aWYgKHNvdXJjZS5nZXRDZW50ZXIpIHtcclxuICBcdFx0XHRcdGxhdGxuZyA9IHNvdXJjZS5nZXRDZW50ZXIoKTtcclxuICBcdFx0XHR9IGVsc2UgaWYgKHNvdXJjZS5nZXRMYXRMbmcpIHtcclxuICBcdFx0XHRcdGxhdGxuZyA9IHNvdXJjZS5nZXRMYXRMbmcoKTtcclxuICBcdFx0XHR9IGVsc2UgaWYgKHNvdXJjZS5nZXRCb3VuZHMpIHtcclxuICBcdFx0XHRcdGxhdGxuZyA9IHNvdXJjZS5nZXRCb3VuZHMoKS5nZXRDZW50ZXIoKTtcclxuICBcdFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCdVbmFibGUgdG8gZ2V0IHNvdXJjZSBsYXllciBMYXRMbmcuJyk7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcbiAgXHRcdHRoaXMuc2V0TGF0TG5nKGxhdGxuZyk7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fbWFwKSB7XHJcbiAgXHRcdFx0Ly8gdXBkYXRlIHRoZSBvdmVybGF5IChjb250ZW50LCBsYXlvdXQsIGV0Yy4uLilcclxuICBcdFx0XHR0aGlzLnVwZGF0ZSgpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gdHJ1ZTtcclxuICBcdH0sXHJcblxyXG4gIFx0X3VwZGF0ZUNvbnRlbnQ6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0aWYgKCF0aGlzLl9jb250ZW50KSB7IHJldHVybjsgfVxyXG5cclxuICBcdFx0dmFyIG5vZGUgPSB0aGlzLl9jb250ZW50Tm9kZTtcclxuICBcdFx0dmFyIGNvbnRlbnQgPSAodHlwZW9mIHRoaXMuX2NvbnRlbnQgPT09ICdmdW5jdGlvbicpID8gdGhpcy5fY29udGVudCh0aGlzLl9zb3VyY2UgfHwgdGhpcykgOiB0aGlzLl9jb250ZW50O1xyXG5cclxuICBcdFx0aWYgKHR5cGVvZiBjb250ZW50ID09PSAnc3RyaW5nJykge1xyXG4gIFx0XHRcdG5vZGUuaW5uZXJIVE1MID0gY29udGVudDtcclxuICBcdFx0fSBlbHNlIHtcclxuICBcdFx0XHR3aGlsZSAobm9kZS5oYXNDaGlsZE5vZGVzKCkpIHtcclxuICBcdFx0XHRcdG5vZGUucmVtb3ZlQ2hpbGQobm9kZS5maXJzdENoaWxkKTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdFx0bm9kZS5hcHBlbmRDaGlsZChjb250ZW50KTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gQG5hbWVzcGFjZSBEaXZPdmVybGF5XHJcbiAgXHRcdC8vIEBzZWN0aW9uIERpdk92ZXJsYXkgZXZlbnRzXHJcbiAgXHRcdC8vIEBldmVudCBjb250ZW50dXBkYXRlOiBFdmVudFxyXG4gIFx0XHQvLyBGaXJlZCB3aGVuIHRoZSBjb250ZW50IG9mIHRoZSBvdmVybGF5IGlzIHVwZGF0ZWRcclxuICBcdFx0dGhpcy5maXJlKCdjb250ZW50dXBkYXRlJyk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF91cGRhdGVQb3NpdGlvbjogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHRpZiAoIXRoaXMuX21hcCkgeyByZXR1cm47IH1cclxuXHJcbiAgXHRcdHZhciBwb3MgPSB0aGlzLl9tYXAubGF0TG5nVG9MYXllclBvaW50KHRoaXMuX2xhdGxuZyksXHJcbiAgXHRcdCAgICBvZmZzZXQgPSB0b1BvaW50KHRoaXMub3B0aW9ucy5vZmZzZXQpLFxyXG4gIFx0XHQgICAgYW5jaG9yID0gdGhpcy5fZ2V0QW5jaG9yKCk7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fem9vbUFuaW1hdGVkKSB7XHJcbiAgXHRcdFx0c2V0UG9zaXRpb24odGhpcy5fY29udGFpbmVyLCBwb3MuYWRkKGFuY2hvcikpO1xyXG4gIFx0XHR9IGVsc2Uge1xyXG4gIFx0XHRcdG9mZnNldCA9IG9mZnNldC5hZGQocG9zKS5hZGQoYW5jaG9yKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dmFyIGJvdHRvbSA9IHRoaXMuX2NvbnRhaW5lckJvdHRvbSA9IC1vZmZzZXQueSxcclxuICBcdFx0ICAgIGxlZnQgPSB0aGlzLl9jb250YWluZXJMZWZ0ID0gLU1hdGgucm91bmQodGhpcy5fY29udGFpbmVyV2lkdGggLyAyKSArIG9mZnNldC54O1xyXG5cclxuICBcdFx0Ly8gYm90dG9tIHBvc2l0aW9uIHRoZSBvdmVybGF5IGluIGNhc2UgdGhlIGhlaWdodCBvZiB0aGUgb3ZlcmxheSBjaGFuZ2VzIChpbWFnZXMgbG9hZGluZyBldGMpXHJcbiAgXHRcdHRoaXMuX2NvbnRhaW5lci5zdHlsZS5ib3R0b20gPSBib3R0b20gKyAncHgnO1xyXG4gIFx0XHR0aGlzLl9jb250YWluZXIuc3R5bGUubGVmdCA9IGxlZnQgKyAncHgnO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfZ2V0QW5jaG9yOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiBbMCwgMF07XHJcbiAgXHR9XHJcblxyXG4gIH0pO1xyXG5cclxuICBNYXAuaW5jbHVkZSh7XHJcbiAgXHRfaW5pdE92ZXJsYXk6IGZ1bmN0aW9uIChPdmVybGF5Q2xhc3MsIGNvbnRlbnQsIGxhdGxuZywgb3B0aW9ucykge1xyXG4gIFx0XHR2YXIgb3ZlcmxheSA9IGNvbnRlbnQ7XHJcbiAgXHRcdGlmICghKG92ZXJsYXkgaW5zdGFuY2VvZiBPdmVybGF5Q2xhc3MpKSB7XHJcbiAgXHRcdFx0b3ZlcmxheSA9IG5ldyBPdmVybGF5Q2xhc3Mob3B0aW9ucykuc2V0Q29udGVudChjb250ZW50KTtcclxuICBcdFx0fVxyXG4gIFx0XHRpZiAobGF0bG5nKSB7XHJcbiAgXHRcdFx0b3ZlcmxheS5zZXRMYXRMbmcobGF0bG5nKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gb3ZlcmxheTtcclxuICBcdH1cclxuICB9KTtcclxuXHJcblxyXG4gIExheWVyLmluY2x1ZGUoe1xyXG4gIFx0X2luaXRPdmVybGF5OiBmdW5jdGlvbiAoT3ZlcmxheUNsYXNzLCBvbGQsIGNvbnRlbnQsIG9wdGlvbnMpIHtcclxuICBcdFx0dmFyIG92ZXJsYXkgPSBjb250ZW50O1xyXG4gIFx0XHRpZiAob3ZlcmxheSBpbnN0YW5jZW9mIE92ZXJsYXlDbGFzcykge1xyXG4gIFx0XHRcdHNldE9wdGlvbnMob3ZlcmxheSwgb3B0aW9ucyk7XHJcbiAgXHRcdFx0b3ZlcmxheS5fc291cmNlID0gdGhpcztcclxuICBcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRvdmVybGF5ID0gKG9sZCAmJiAhb3B0aW9ucykgPyBvbGQgOiBuZXcgT3ZlcmxheUNsYXNzKG9wdGlvbnMsIHRoaXMpO1xyXG4gIFx0XHRcdG92ZXJsYXkuc2V0Q29udGVudChjb250ZW50KTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gb3ZlcmxheTtcclxuICBcdH1cclxuICB9KTtcblxuICAvKlxyXG4gICAqIEBjbGFzcyBQb3B1cFxyXG4gICAqIEBpbmhlcml0cyBEaXZPdmVybGF5XHJcbiAgICogQGFrYSBMLlBvcHVwXHJcbiAgICogVXNlZCB0byBvcGVuIHBvcHVwcyBpbiBjZXJ0YWluIHBsYWNlcyBvZiB0aGUgbWFwLiBVc2UgW01hcC5vcGVuUG9wdXBdKCNtYXAtb3BlbnBvcHVwKSB0b1xyXG4gICAqIG9wZW4gcG9wdXBzIHdoaWxlIG1ha2luZyBzdXJlIHRoYXQgb25seSBvbmUgcG9wdXAgaXMgb3BlbiBhdCBvbmUgdGltZVxyXG4gICAqIChyZWNvbW1lbmRlZCBmb3IgdXNhYmlsaXR5KSwgb3IgdXNlIFtNYXAuYWRkTGF5ZXJdKCNtYXAtYWRkbGF5ZXIpIHRvIG9wZW4gYXMgbWFueSBhcyB5b3Ugd2FudC5cclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICpcclxuICAgKiBJZiB5b3Ugd2FudCB0byBqdXN0IGJpbmQgYSBwb3B1cCB0byBtYXJrZXIgY2xpY2sgYW5kIHRoZW4gb3BlbiBpdCwgaXQncyByZWFsbHkgZWFzeTpcclxuICAgKlxyXG4gICAqIGBgYGpzXHJcbiAgICogbWFya2VyLmJpbmRQb3B1cChwb3B1cENvbnRlbnQpLm9wZW5Qb3B1cCgpO1xyXG4gICAqIGBgYFxyXG4gICAqIFBhdGggb3ZlcmxheXMgbGlrZSBwb2x5bGluZXMgYWxzbyBoYXZlIGEgYGJpbmRQb3B1cGAgbWV0aG9kLlxyXG4gICAqXHJcbiAgICogQSBwb3B1cCBjYW4gYmUgYWxzbyBzdGFuZGFsb25lOlxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiB2YXIgcG9wdXAgPSBMLnBvcHVwKClcclxuICAgKiBcdC5zZXRMYXRMbmcobGF0bG5nKVxyXG4gICAqIFx0LnNldENvbnRlbnQoJzxwPkhlbGxvIHdvcmxkITxiciAvPlRoaXMgaXMgYSBuaWNlIHBvcHVwLjwvcD4nKVxyXG4gICAqIFx0Lm9wZW5PbihtYXApO1xyXG4gICAqIGBgYFxyXG4gICAqIG9yXHJcbiAgICogYGBganNcclxuICAgKiB2YXIgcG9wdXAgPSBMLnBvcHVwKGxhdGxuZywge2NvbnRlbnQ6ICc8cD5IZWxsbyB3b3JsZCE8YnIgLz5UaGlzIGlzIGEgbmljZSBwb3B1cC48L3A+JylcclxuICAgKiBcdC5vcGVuT24obWFwKTtcclxuICAgKiBgYGBcclxuICAgKi9cclxuXHJcblxyXG4gIC8vIEBuYW1lc3BhY2UgUG9wdXBcclxuICB2YXIgUG9wdXAgPSBEaXZPdmVybGF5LmV4dGVuZCh7XHJcblxyXG4gIFx0Ly8gQHNlY3Rpb25cclxuICBcdC8vIEBha2EgUG9wdXAgb3B0aW9uc1xyXG4gIFx0b3B0aW9uczoge1xyXG4gIFx0XHQvLyBAb3B0aW9uIHBhbmU6IFN0cmluZyA9ICdwb3B1cFBhbmUnXHJcbiAgXHRcdC8vIGBNYXAgcGFuZWAgd2hlcmUgdGhlIHBvcHVwIHdpbGwgYmUgYWRkZWQuXHJcbiAgXHRcdHBhbmU6ICdwb3B1cFBhbmUnLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBvZmZzZXQ6IFBvaW50ID0gUG9pbnQoMCwgNylcclxuICBcdFx0Ly8gVGhlIG9mZnNldCBvZiB0aGUgcG9wdXAgcG9zaXRpb24uXHJcbiAgXHRcdG9mZnNldDogWzAsIDddLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBtYXhXaWR0aDogTnVtYmVyID0gMzAwXHJcbiAgXHRcdC8vIE1heCB3aWR0aCBvZiB0aGUgcG9wdXAsIGluIHBpeGVscy5cclxuICBcdFx0bWF4V2lkdGg6IDMwMCxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gbWluV2lkdGg6IE51bWJlciA9IDUwXHJcbiAgXHRcdC8vIE1pbiB3aWR0aCBvZiB0aGUgcG9wdXAsIGluIHBpeGVscy5cclxuICBcdFx0bWluV2lkdGg6IDUwLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBtYXhIZWlnaHQ6IE51bWJlciA9IG51bGxcclxuICBcdFx0Ly8gSWYgc2V0LCBjcmVhdGVzIGEgc2Nyb2xsYWJsZSBjb250YWluZXIgb2YgdGhlIGdpdmVuIGhlaWdodFxyXG4gIFx0XHQvLyBpbnNpZGUgYSBwb3B1cCBpZiBpdHMgY29udGVudCBleGNlZWRzIGl0LlxyXG4gIFx0XHQvLyBUaGUgc2Nyb2xsYWJsZSBjb250YWluZXIgY2FuIGJlIHN0eWxlZCB1c2luZyB0aGVcclxuICBcdFx0Ly8gYGxlYWZsZXQtcG9wdXAtc2Nyb2xsZWRgIENTUyBjbGFzcyBzZWxlY3Rvci5cclxuICBcdFx0bWF4SGVpZ2h0OiBudWxsLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBhdXRvUGFuOiBCb29sZWFuID0gdHJ1ZVxyXG4gIFx0XHQvLyBTZXQgaXQgdG8gYGZhbHNlYCBpZiB5b3UgZG9uJ3Qgd2FudCB0aGUgbWFwIHRvIGRvIHBhbm5pbmcgYW5pbWF0aW9uXHJcbiAgXHRcdC8vIHRvIGZpdCB0aGUgb3BlbmVkIHBvcHVwLlxyXG4gIFx0XHRhdXRvUGFuOiB0cnVlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBhdXRvUGFuUGFkZGluZ1RvcExlZnQ6IFBvaW50ID0gbnVsbFxyXG4gIFx0XHQvLyBUaGUgbWFyZ2luIGJldHdlZW4gdGhlIHBvcHVwIGFuZCB0aGUgdG9wIGxlZnQgY29ybmVyIG9mIHRoZSBtYXBcclxuICBcdFx0Ly8gdmlldyBhZnRlciBhdXRvcGFubmluZyB3YXMgcGVyZm9ybWVkLlxyXG4gIFx0XHRhdXRvUGFuUGFkZGluZ1RvcExlZnQ6IG51bGwsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIGF1dG9QYW5QYWRkaW5nQm90dG9tUmlnaHQ6IFBvaW50ID0gbnVsbFxyXG4gIFx0XHQvLyBUaGUgbWFyZ2luIGJldHdlZW4gdGhlIHBvcHVwIGFuZCB0aGUgYm90dG9tIHJpZ2h0IGNvcm5lciBvZiB0aGUgbWFwXHJcbiAgXHRcdC8vIHZpZXcgYWZ0ZXIgYXV0b3Bhbm5pbmcgd2FzIHBlcmZvcm1lZC5cclxuICBcdFx0YXV0b1BhblBhZGRpbmdCb3R0b21SaWdodDogbnVsbCxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gYXV0b1BhblBhZGRpbmc6IFBvaW50ID0gUG9pbnQoNSwgNSlcclxuICBcdFx0Ly8gRXF1aXZhbGVudCBvZiBzZXR0aW5nIGJvdGggdG9wIGxlZnQgYW5kIGJvdHRvbSByaWdodCBhdXRvcGFuIHBhZGRpbmcgdG8gdGhlIHNhbWUgdmFsdWUuXHJcbiAgXHRcdGF1dG9QYW5QYWRkaW5nOiBbNSwgNV0sXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIGtlZXBJblZpZXc6IEJvb2xlYW4gPSBmYWxzZVxyXG4gIFx0XHQvLyBTZXQgaXQgdG8gYHRydWVgIGlmIHlvdSB3YW50IHRvIHByZXZlbnQgdXNlcnMgZnJvbSBwYW5uaW5nIHRoZSBwb3B1cFxyXG4gIFx0XHQvLyBvZmYgb2YgdGhlIHNjcmVlbiB3aGlsZSBpdCBpcyBvcGVuLlxyXG4gIFx0XHRrZWVwSW5WaWV3OiBmYWxzZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gY2xvc2VCdXR0b246IEJvb2xlYW4gPSB0cnVlXHJcbiAgXHRcdC8vIENvbnRyb2xzIHRoZSBwcmVzZW5jZSBvZiBhIGNsb3NlIGJ1dHRvbiBpbiB0aGUgcG9wdXAuXHJcbiAgXHRcdGNsb3NlQnV0dG9uOiB0cnVlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBhdXRvQ2xvc2U6IEJvb2xlYW4gPSB0cnVlXHJcbiAgXHRcdC8vIFNldCBpdCB0byBgZmFsc2VgIGlmIHlvdSB3YW50IHRvIG92ZXJyaWRlIHRoZSBkZWZhdWx0IGJlaGF2aW9yIG9mXHJcbiAgXHRcdC8vIHRoZSBwb3B1cCBjbG9zaW5nIHdoZW4gYW5vdGhlciBwb3B1cCBpcyBvcGVuZWQuXHJcbiAgXHRcdGF1dG9DbG9zZTogdHJ1ZSxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gY2xvc2VPbkVzY2FwZUtleTogQm9vbGVhbiA9IHRydWVcclxuICBcdFx0Ly8gU2V0IGl0IHRvIGBmYWxzZWAgaWYgeW91IHdhbnQgdG8gb3ZlcnJpZGUgdGhlIGRlZmF1bHQgYmVoYXZpb3Igb2ZcclxuICBcdFx0Ly8gdGhlIEVTQyBrZXkgZm9yIGNsb3Npbmcgb2YgdGhlIHBvcHVwLlxyXG4gIFx0XHRjbG9zZU9uRXNjYXBlS2V5OiB0cnVlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBjbG9zZU9uQ2xpY2s6IEJvb2xlYW4gPSAqXHJcbiAgXHRcdC8vIFNldCBpdCBpZiB5b3Ugd2FudCB0byBvdmVycmlkZSB0aGUgZGVmYXVsdCBiZWhhdmlvciBvZiB0aGUgcG9wdXAgY2xvc2luZyB3aGVuIHVzZXIgY2xpY2tzXHJcbiAgXHRcdC8vIG9uIHRoZSBtYXAuIERlZmF1bHRzIHRvIHRoZSBtYXAncyBbYGNsb3NlUG9wdXBPbkNsaWNrYF0oI21hcC1jbG9zZXBvcHVwb25jbGljaykgb3B0aW9uLlxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBjbGFzc05hbWU6IFN0cmluZyA9ICcnXHJcbiAgXHRcdC8vIEEgY3VzdG9tIENTUyBjbGFzcyBuYW1lIHRvIGFzc2lnbiB0byB0aGUgcG9wdXAuXHJcbiAgXHRcdGNsYXNzTmFtZTogJydcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG5hbWVzcGFjZSBQb3B1cFxyXG4gIFx0Ly8gQG1ldGhvZCBvcGVuT24obWFwOiBNYXApOiB0aGlzXHJcbiAgXHQvLyBBbHRlcm5hdGl2ZSB0byBgbWFwLm9wZW5Qb3B1cChwb3B1cClgLlxyXG4gIFx0Ly8gQWRkcyB0aGUgcG9wdXAgdG8gdGhlIG1hcCBhbmQgY2xvc2VzIHRoZSBwcmV2aW91cyBvbmUuXHJcbiAgXHRvcGVuT246IGZ1bmN0aW9uIChtYXApIHtcclxuICBcdFx0bWFwID0gYXJndW1lbnRzLmxlbmd0aCA/IG1hcCA6IHRoaXMuX3NvdXJjZS5fbWFwOyAvLyBleHBlcmltZW50YWwsIG5vdCB0aGUgcGFydCBvZiBwdWJsaWMgYXBpXHJcblxyXG4gIFx0XHRpZiAoIW1hcC5oYXNMYXllcih0aGlzKSAmJiBtYXAuX3BvcHVwICYmIG1hcC5fcG9wdXAub3B0aW9ucy5hdXRvQ2xvc2UpIHtcclxuICBcdFx0XHRtYXAucmVtb3ZlTGF5ZXIobWFwLl9wb3B1cCk7XHJcbiAgXHRcdH1cclxuICBcdFx0bWFwLl9wb3B1cCA9IHRoaXM7XHJcblxyXG4gIFx0XHRyZXR1cm4gRGl2T3ZlcmxheS5wcm90b3R5cGUub3Blbk9uLmNhbGwodGhpcywgbWFwKTtcclxuICBcdH0sXHJcblxyXG4gIFx0b25BZGQ6IGZ1bmN0aW9uIChtYXApIHtcclxuICBcdFx0RGl2T3ZlcmxheS5wcm90b3R5cGUub25BZGQuY2FsbCh0aGlzLCBtYXApO1xyXG5cclxuICBcdFx0Ly8gQG5hbWVzcGFjZSBNYXBcclxuICBcdFx0Ly8gQHNlY3Rpb24gUG9wdXAgZXZlbnRzXHJcbiAgXHRcdC8vIEBldmVudCBwb3B1cG9wZW46IFBvcHVwRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiBhIHBvcHVwIGlzIG9wZW5lZCBpbiB0aGUgbWFwXHJcbiAgXHRcdG1hcC5maXJlKCdwb3B1cG9wZW4nLCB7cG9wdXA6IHRoaXN9KTtcclxuXHJcbiAgXHRcdGlmICh0aGlzLl9zb3VyY2UpIHtcclxuICBcdFx0XHQvLyBAbmFtZXNwYWNlIExheWVyXHJcbiAgXHRcdFx0Ly8gQHNlY3Rpb24gUG9wdXAgZXZlbnRzXHJcbiAgXHRcdFx0Ly8gQGV2ZW50IHBvcHVwb3BlbjogUG9wdXBFdmVudFxyXG4gIFx0XHRcdC8vIEZpcmVkIHdoZW4gYSBwb3B1cCBib3VuZCB0byB0aGlzIGxheWVyIGlzIG9wZW5lZFxyXG4gIFx0XHRcdHRoaXMuX3NvdXJjZS5maXJlKCdwb3B1cG9wZW4nLCB7cG9wdXA6IHRoaXN9LCB0cnVlKTtcclxuICBcdFx0XHQvLyBGb3Igbm9uLXBhdGggbGF5ZXJzLCB3ZSB0b2dnbGUgdGhlIHBvcHVwIHdoZW4gY2xpY2tpbmdcclxuICBcdFx0XHQvLyBhZ2FpbiB0aGUgbGF5ZXIsIHNvIHByZXZlbnQgdGhlIG1hcCB0byByZW9wZW4gaXQuXHJcbiAgXHRcdFx0aWYgKCEodGhpcy5fc291cmNlIGluc3RhbmNlb2YgUGF0aCkpIHtcclxuICBcdFx0XHRcdHRoaXMuX3NvdXJjZS5vbigncHJlY2xpY2snLCBzdG9wUHJvcGFnYXRpb24pO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHRvblJlbW92ZTogZnVuY3Rpb24gKG1hcCkge1xyXG4gIFx0XHREaXZPdmVybGF5LnByb3RvdHlwZS5vblJlbW92ZS5jYWxsKHRoaXMsIG1hcCk7XHJcblxyXG4gIFx0XHQvLyBAbmFtZXNwYWNlIE1hcFxyXG4gIFx0XHQvLyBAc2VjdGlvbiBQb3B1cCBldmVudHNcclxuICBcdFx0Ly8gQGV2ZW50IHBvcHVwY2xvc2U6IFBvcHVwRXZlbnRcclxuICBcdFx0Ly8gRmlyZWQgd2hlbiBhIHBvcHVwIGluIHRoZSBtYXAgaXMgY2xvc2VkXHJcbiAgXHRcdG1hcC5maXJlKCdwb3B1cGNsb3NlJywge3BvcHVwOiB0aGlzfSk7XHJcblxyXG4gIFx0XHRpZiAodGhpcy5fc291cmNlKSB7XHJcbiAgXHRcdFx0Ly8gQG5hbWVzcGFjZSBMYXllclxyXG4gIFx0XHRcdC8vIEBzZWN0aW9uIFBvcHVwIGV2ZW50c1xyXG4gIFx0XHRcdC8vIEBldmVudCBwb3B1cGNsb3NlOiBQb3B1cEV2ZW50XHJcbiAgXHRcdFx0Ly8gRmlyZWQgd2hlbiBhIHBvcHVwIGJvdW5kIHRvIHRoaXMgbGF5ZXIgaXMgY2xvc2VkXHJcbiAgXHRcdFx0dGhpcy5fc291cmNlLmZpcmUoJ3BvcHVwY2xvc2UnLCB7cG9wdXA6IHRoaXN9LCB0cnVlKTtcclxuICBcdFx0XHRpZiAoISh0aGlzLl9zb3VyY2UgaW5zdGFuY2VvZiBQYXRoKSkge1xyXG4gIFx0XHRcdFx0dGhpcy5fc291cmNlLm9mZigncHJlY2xpY2snLCBzdG9wUHJvcGFnYXRpb24pO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHRnZXRFdmVudHM6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dmFyIGV2ZW50cyA9IERpdk92ZXJsYXkucHJvdG90eXBlLmdldEV2ZW50cy5jYWxsKHRoaXMpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5jbG9zZU9uQ2xpY2sgIT09IHVuZGVmaW5lZCA/IHRoaXMub3B0aW9ucy5jbG9zZU9uQ2xpY2sgOiB0aGlzLl9tYXAub3B0aW9ucy5jbG9zZVBvcHVwT25DbGljaykge1xyXG4gIFx0XHRcdGV2ZW50cy5wcmVjbGljayA9IHRoaXMuY2xvc2U7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMua2VlcEluVmlldykge1xyXG4gIFx0XHRcdGV2ZW50cy5tb3ZlZW5kID0gdGhpcy5fYWRqdXN0UGFuO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gZXZlbnRzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfaW5pdExheW91dDogZnVuY3Rpb24gKCkge1xyXG4gIFx0XHR2YXIgcHJlZml4ID0gJ2xlYWZsZXQtcG9wdXAnLFxyXG4gIFx0XHQgICAgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyID0gY3JlYXRlJDEoJ2RpdicsXHJcbiAgXHRcdFx0cHJlZml4ICsgJyAnICsgKHRoaXMub3B0aW9ucy5jbGFzc05hbWUgfHwgJycpICtcclxuICBcdFx0XHQnIGxlYWZsZXQtem9vbS1hbmltYXRlZCcpO1xyXG5cclxuICBcdFx0dmFyIHdyYXBwZXIgPSB0aGlzLl93cmFwcGVyID0gY3JlYXRlJDEoJ2RpdicsIHByZWZpeCArICctY29udGVudC13cmFwcGVyJywgY29udGFpbmVyKTtcclxuICBcdFx0dGhpcy5fY29udGVudE5vZGUgPSBjcmVhdGUkMSgnZGl2JywgcHJlZml4ICsgJy1jb250ZW50Jywgd3JhcHBlcik7XHJcblxyXG4gIFx0XHRkaXNhYmxlQ2xpY2tQcm9wYWdhdGlvbihjb250YWluZXIpO1xyXG4gIFx0XHRkaXNhYmxlU2Nyb2xsUHJvcGFnYXRpb24odGhpcy5fY29udGVudE5vZGUpO1xyXG4gIFx0XHRvbihjb250YWluZXIsICdjb250ZXh0bWVudScsIHN0b3BQcm9wYWdhdGlvbik7XHJcblxyXG4gIFx0XHR0aGlzLl90aXBDb250YWluZXIgPSBjcmVhdGUkMSgnZGl2JywgcHJlZml4ICsgJy10aXAtY29udGFpbmVyJywgY29udGFpbmVyKTtcclxuICBcdFx0dGhpcy5fdGlwID0gY3JlYXRlJDEoJ2RpdicsIHByZWZpeCArICctdGlwJywgdGhpcy5fdGlwQ29udGFpbmVyKTtcclxuXHJcbiAgXHRcdGlmICh0aGlzLm9wdGlvbnMuY2xvc2VCdXR0b24pIHtcclxuICBcdFx0XHR2YXIgY2xvc2VCdXR0b24gPSB0aGlzLl9jbG9zZUJ1dHRvbiA9IGNyZWF0ZSQxKCdhJywgcHJlZml4ICsgJy1jbG9zZS1idXR0b24nLCBjb250YWluZXIpO1xyXG4gIFx0XHRcdGNsb3NlQnV0dG9uLnNldEF0dHJpYnV0ZSgncm9sZScsICdidXR0b24nKTsgLy8gb3ZlcnJpZGVzIHRoZSBpbXBsaWNpdCByb2xlPWxpbmsgb2YgPGE+IGVsZW1lbnRzICM3Mzk5XHJcbiAgXHRcdFx0Y2xvc2VCdXR0b24uc2V0QXR0cmlidXRlKCdhcmlhLWxhYmVsJywgJ0Nsb3NlIHBvcHVwJyk7XHJcbiAgXHRcdFx0Y2xvc2VCdXR0b24uaHJlZiA9ICcjY2xvc2UnO1xyXG4gIFx0XHRcdGNsb3NlQnV0dG9uLmlubmVySFRNTCA9ICc8c3BhbiBhcmlhLWhpZGRlbj1cInRydWVcIj4mIzIxNTs8L3NwYW4+JztcclxuXHJcbiAgXHRcdFx0b24oY2xvc2VCdXR0b24sICdjbGljaycsIGZ1bmN0aW9uIChldikge1xyXG4gIFx0XHRcdFx0cHJldmVudERlZmF1bHQoZXYpO1xyXG4gIFx0XHRcdFx0dGhpcy5jbG9zZSgpO1xyXG4gIFx0XHRcdH0sIHRoaXMpO1xyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdF91cGRhdGVMYXlvdXQ6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dmFyIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRlbnROb2RlLFxyXG4gIFx0XHQgICAgc3R5bGUgPSBjb250YWluZXIuc3R5bGU7XHJcblxyXG4gIFx0XHRzdHlsZS53aWR0aCA9ICcnO1xyXG4gIFx0XHRzdHlsZS53aGl0ZVNwYWNlID0gJ25vd3JhcCc7XHJcblxyXG4gIFx0XHR2YXIgd2lkdGggPSBjb250YWluZXIub2Zmc2V0V2lkdGg7XHJcbiAgXHRcdHdpZHRoID0gTWF0aC5taW4od2lkdGgsIHRoaXMub3B0aW9ucy5tYXhXaWR0aCk7XHJcbiAgXHRcdHdpZHRoID0gTWF0aC5tYXgod2lkdGgsIHRoaXMub3B0aW9ucy5taW5XaWR0aCk7XHJcblxyXG4gIFx0XHRzdHlsZS53aWR0aCA9ICh3aWR0aCArIDEpICsgJ3B4JztcclxuICBcdFx0c3R5bGUud2hpdGVTcGFjZSA9ICcnO1xyXG5cclxuICBcdFx0c3R5bGUuaGVpZ2h0ID0gJyc7XHJcblxyXG4gIFx0XHR2YXIgaGVpZ2h0ID0gY29udGFpbmVyLm9mZnNldEhlaWdodCxcclxuICBcdFx0ICAgIG1heEhlaWdodCA9IHRoaXMub3B0aW9ucy5tYXhIZWlnaHQsXHJcbiAgXHRcdCAgICBzY3JvbGxlZENsYXNzID0gJ2xlYWZsZXQtcG9wdXAtc2Nyb2xsZWQnO1xyXG5cclxuICBcdFx0aWYgKG1heEhlaWdodCAmJiBoZWlnaHQgPiBtYXhIZWlnaHQpIHtcclxuICBcdFx0XHRzdHlsZS5oZWlnaHQgPSBtYXhIZWlnaHQgKyAncHgnO1xyXG4gIFx0XHRcdGFkZENsYXNzKGNvbnRhaW5lciwgc2Nyb2xsZWRDbGFzcyk7XHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0cmVtb3ZlQ2xhc3MoY29udGFpbmVyLCBzY3JvbGxlZENsYXNzKTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dGhpcy5fY29udGFpbmVyV2lkdGggPSB0aGlzLl9jb250YWluZXIub2Zmc2V0V2lkdGg7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9hbmltYXRlWm9vbTogZnVuY3Rpb24gKGUpIHtcclxuICBcdFx0dmFyIHBvcyA9IHRoaXMuX21hcC5fbGF0TG5nVG9OZXdMYXllclBvaW50KHRoaXMuX2xhdGxuZywgZS56b29tLCBlLmNlbnRlciksXHJcbiAgXHRcdCAgICBhbmNob3IgPSB0aGlzLl9nZXRBbmNob3IoKTtcclxuICBcdFx0c2V0UG9zaXRpb24odGhpcy5fY29udGFpbmVyLCBwb3MuYWRkKGFuY2hvcikpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfYWRqdXN0UGFuOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICghdGhpcy5vcHRpb25zLmF1dG9QYW4pIHsgcmV0dXJuOyB9XHJcbiAgXHRcdGlmICh0aGlzLl9tYXAuX3BhbkFuaW0pIHsgdGhpcy5fbWFwLl9wYW5BbmltLnN0b3AoKTsgfVxyXG5cclxuICBcdFx0Ly8gV2UgY2FuIGVuZGxlc3NseSByZWN1cnNlIGlmIGtlZXBJblZpZXcgaXMgc2V0IGFuZCB0aGUgdmlldyByZXNldHMuXHJcbiAgXHRcdC8vIExldCdzIGd1YXJkIGFnYWluc3QgdGhhdCBieSBleGl0aW5nIGVhcmx5IGlmIHdlJ3JlIHJlc3BvbmRpbmcgdG8gb3VyIG93biBhdXRvcGFuLlxyXG4gIFx0XHRpZiAodGhpcy5fYXV0b3Bhbm5pbmcpIHtcclxuICBcdFx0XHR0aGlzLl9hdXRvcGFubmluZyA9IGZhbHNlO1xyXG4gIFx0XHRcdHJldHVybjtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0dmFyIG1hcCA9IHRoaXMuX21hcCxcclxuICBcdFx0ICAgIG1hcmdpbkJvdHRvbSA9IHBhcnNlSW50KGdldFN0eWxlKHRoaXMuX2NvbnRhaW5lciwgJ21hcmdpbkJvdHRvbScpLCAxMCkgfHwgMCxcclxuICBcdFx0ICAgIGNvbnRhaW5lckhlaWdodCA9IHRoaXMuX2NvbnRhaW5lci5vZmZzZXRIZWlnaHQgKyBtYXJnaW5Cb3R0b20sXHJcbiAgXHRcdCAgICBjb250YWluZXJXaWR0aCA9IHRoaXMuX2NvbnRhaW5lcldpZHRoLFxyXG4gIFx0XHQgICAgbGF5ZXJQb3MgPSBuZXcgUG9pbnQodGhpcy5fY29udGFpbmVyTGVmdCwgLWNvbnRhaW5lckhlaWdodCAtIHRoaXMuX2NvbnRhaW5lckJvdHRvbSk7XHJcblxyXG4gIFx0XHRsYXllclBvcy5fYWRkKGdldFBvc2l0aW9uKHRoaXMuX2NvbnRhaW5lcikpO1xyXG5cclxuICBcdFx0dmFyIGNvbnRhaW5lclBvcyA9IG1hcC5sYXllclBvaW50VG9Db250YWluZXJQb2ludChsYXllclBvcyksXHJcbiAgXHRcdCAgICBwYWRkaW5nID0gdG9Qb2ludCh0aGlzLm9wdGlvbnMuYXV0b1BhblBhZGRpbmcpLFxyXG4gIFx0XHQgICAgcGFkZGluZ1RMID0gdG9Qb2ludCh0aGlzLm9wdGlvbnMuYXV0b1BhblBhZGRpbmdUb3BMZWZ0IHx8IHBhZGRpbmcpLFxyXG4gIFx0XHQgICAgcGFkZGluZ0JSID0gdG9Qb2ludCh0aGlzLm9wdGlvbnMuYXV0b1BhblBhZGRpbmdCb3R0b21SaWdodCB8fCBwYWRkaW5nKSxcclxuICBcdFx0ICAgIHNpemUgPSBtYXAuZ2V0U2l6ZSgpLFxyXG4gIFx0XHQgICAgZHggPSAwLFxyXG4gIFx0XHQgICAgZHkgPSAwO1xyXG5cclxuICBcdFx0aWYgKGNvbnRhaW5lclBvcy54ICsgY29udGFpbmVyV2lkdGggKyBwYWRkaW5nQlIueCA+IHNpemUueCkgeyAvLyByaWdodFxyXG4gIFx0XHRcdGR4ID0gY29udGFpbmVyUG9zLnggKyBjb250YWluZXJXaWR0aCAtIHNpemUueCArIHBhZGRpbmdCUi54O1xyXG4gIFx0XHR9XHJcbiAgXHRcdGlmIChjb250YWluZXJQb3MueCAtIGR4IC0gcGFkZGluZ1RMLnggPCAwKSB7IC8vIGxlZnRcclxuICBcdFx0XHRkeCA9IGNvbnRhaW5lclBvcy54IC0gcGFkZGluZ1RMLng7XHJcbiAgXHRcdH1cclxuICBcdFx0aWYgKGNvbnRhaW5lclBvcy55ICsgY29udGFpbmVySGVpZ2h0ICsgcGFkZGluZ0JSLnkgPiBzaXplLnkpIHsgLy8gYm90dG9tXHJcbiAgXHRcdFx0ZHkgPSBjb250YWluZXJQb3MueSArIGNvbnRhaW5lckhlaWdodCAtIHNpemUueSArIHBhZGRpbmdCUi55O1xyXG4gIFx0XHR9XHJcbiAgXHRcdGlmIChjb250YWluZXJQb3MueSAtIGR5IC0gcGFkZGluZ1RMLnkgPCAwKSB7IC8vIHRvcFxyXG4gIFx0XHRcdGR5ID0gY29udGFpbmVyUG9zLnkgLSBwYWRkaW5nVEwueTtcclxuICBcdFx0fVxyXG5cclxuICBcdFx0Ly8gQG5hbWVzcGFjZSBNYXBcclxuICBcdFx0Ly8gQHNlY3Rpb24gUG9wdXAgZXZlbnRzXHJcbiAgXHRcdC8vIEBldmVudCBhdXRvcGFuc3RhcnQ6IEV2ZW50XHJcbiAgXHRcdC8vIEZpcmVkIHdoZW4gdGhlIG1hcCBzdGFydHMgYXV0b3Bhbm5pbmcgd2hlbiBvcGVuaW5nIGEgcG9wdXAuXHJcbiAgXHRcdGlmIChkeCB8fCBkeSkge1xyXG4gIFx0XHRcdC8vIFRyYWNrIHRoYXQgd2UncmUgYXV0b3Bhbm5pbmcsIGFzIHRoaXMgZnVuY3Rpb24gd2lsbCBiZSByZS1yYW4gb24gbW92ZWVuZFxyXG4gIFx0XHRcdGlmICh0aGlzLm9wdGlvbnMua2VlcEluVmlldykge1xyXG4gIFx0XHRcdFx0dGhpcy5fYXV0b3Bhbm5pbmcgPSB0cnVlO1xyXG4gIFx0XHRcdH1cclxuXHJcbiAgXHRcdFx0bWFwXHJcbiAgXHRcdFx0ICAgIC5maXJlKCdhdXRvcGFuc3RhcnQnKVxyXG4gIFx0XHRcdCAgICAucGFuQnkoW2R4LCBkeV0pO1xyXG4gIFx0XHR9XHJcbiAgXHR9LFxyXG5cclxuICBcdF9nZXRBbmNob3I6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0Ly8gV2hlcmUgc2hvdWxkIHdlIGFuY2hvciB0aGUgcG9wdXAgb24gdGhlIHNvdXJjZSBsYXllcj9cclxuICBcdFx0cmV0dXJuIHRvUG9pbnQodGhpcy5fc291cmNlICYmIHRoaXMuX3NvdXJjZS5fZ2V0UG9wdXBBbmNob3IgPyB0aGlzLl9zb3VyY2UuX2dldFBvcHVwQW5jaG9yKCkgOiBbMCwgMF0pO1xyXG4gIFx0fVxyXG5cclxuICB9KTtcclxuXHJcbiAgLy8gQG5hbWVzcGFjZSBQb3B1cFxyXG4gIC8vIEBmYWN0b3J5IEwucG9wdXAob3B0aW9ucz86IFBvcHVwIG9wdGlvbnMsIHNvdXJjZT86IExheWVyKVxyXG4gIC8vIEluc3RhbnRpYXRlcyBhIGBQb3B1cGAgb2JqZWN0IGdpdmVuIGFuIG9wdGlvbmFsIGBvcHRpb25zYCBvYmplY3QgdGhhdCBkZXNjcmliZXMgaXRzIGFwcGVhcmFuY2UgYW5kIGxvY2F0aW9uIGFuZCBhbiBvcHRpb25hbCBgc291cmNlYCBvYmplY3QgdGhhdCBpcyB1c2VkIHRvIHRhZyB0aGUgcG9wdXAgd2l0aCBhIHJlZmVyZW5jZSB0byB0aGUgTGF5ZXIgdG8gd2hpY2ggaXQgcmVmZXJzLlxyXG4gIC8vIEBhbHRlcm5hdGl2ZVxyXG4gIC8vIEBmYWN0b3J5IEwucG9wdXAobGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/OiBQb3B1cCBvcHRpb25zKVxyXG4gIC8vIEluc3RhbnRpYXRlcyBhIGBQb3B1cGAgb2JqZWN0IGdpdmVuIGBsYXRsbmdgIHdoZXJlIHRoZSBwb3B1cCB3aWxsIG9wZW4gYW5kIGFuIG9wdGlvbmFsIGBvcHRpb25zYCBvYmplY3QgdGhhdCBkZXNjcmliZXMgaXRzIGFwcGVhcmFuY2UgYW5kIGxvY2F0aW9uLlxyXG4gIHZhciBwb3B1cCA9IGZ1bmN0aW9uIChvcHRpb25zLCBzb3VyY2UpIHtcclxuICBcdHJldHVybiBuZXcgUG9wdXAob3B0aW9ucywgc291cmNlKTtcclxuICB9O1xyXG5cclxuXHJcbiAgLyogQG5hbWVzcGFjZSBNYXBcclxuICAgKiBAc2VjdGlvbiBJbnRlcmFjdGlvbiBPcHRpb25zXHJcbiAgICogQG9wdGlvbiBjbG9zZVBvcHVwT25DbGljazogQm9vbGVhbiA9IHRydWVcclxuICAgKiBTZXQgaXQgdG8gYGZhbHNlYCBpZiB5b3UgZG9uJ3Qgd2FudCBwb3B1cHMgdG8gY2xvc2Ugd2hlbiB1c2VyIGNsaWNrcyB0aGUgbWFwLlxyXG4gICAqL1xyXG4gIE1hcC5tZXJnZU9wdGlvbnMoe1xyXG4gIFx0Y2xvc2VQb3B1cE9uQ2xpY2s6IHRydWVcclxuICB9KTtcclxuXHJcblxyXG4gIC8vIEBuYW1lc3BhY2UgTWFwXHJcbiAgLy8gQHNlY3Rpb24gTWV0aG9kcyBmb3IgTGF5ZXJzIGFuZCBDb250cm9sc1xyXG4gIE1hcC5pbmNsdWRlKHtcclxuICBcdC8vIEBtZXRob2Qgb3BlblBvcHVwKHBvcHVwOiBQb3B1cCk6IHRoaXNcclxuICBcdC8vIE9wZW5zIHRoZSBzcGVjaWZpZWQgcG9wdXAgd2hpbGUgY2xvc2luZyB0aGUgcHJldmlvdXNseSBvcGVuZWQgKHRvIG1ha2Ugc3VyZSBvbmx5IG9uZSBpcyBvcGVuZWQgYXQgb25lIHRpbWUgZm9yIHVzYWJpbGl0eSkuXHJcbiAgXHQvLyBAYWx0ZXJuYXRpdmVcclxuICBcdC8vIEBtZXRob2Qgb3BlblBvcHVwKGNvbnRlbnQ6IFN0cmluZ3xIVE1MRWxlbWVudCwgbGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/OiBQb3B1cCBvcHRpb25zKTogdGhpc1xyXG4gIFx0Ly8gQ3JlYXRlcyBhIHBvcHVwIHdpdGggdGhlIHNwZWNpZmllZCBjb250ZW50IGFuZCBvcHRpb25zIGFuZCBvcGVucyBpdCBpbiB0aGUgZ2l2ZW4gcG9pbnQgb24gYSBtYXAuXHJcbiAgXHRvcGVuUG9wdXA6IGZ1bmN0aW9uIChwb3B1cCwgbGF0bG5nLCBvcHRpb25zKSB7XHJcbiAgXHRcdHRoaXMuX2luaXRPdmVybGF5KFBvcHVwLCBwb3B1cCwgbGF0bG5nLCBvcHRpb25zKVxyXG4gIFx0XHQgIC5vcGVuT24odGhpcyk7XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBjbG9zZVBvcHVwKHBvcHVwPzogUG9wdXApOiB0aGlzXHJcbiAgXHQvLyBDbG9zZXMgdGhlIHBvcHVwIHByZXZpb3VzbHkgb3BlbmVkIHdpdGggW29wZW5Qb3B1cF0oI21hcC1vcGVucG9wdXApIChvciB0aGUgZ2l2ZW4gb25lKS5cclxuICBcdGNsb3NlUG9wdXA6IGZ1bmN0aW9uIChwb3B1cCkge1xyXG4gIFx0XHRwb3B1cCA9IGFyZ3VtZW50cy5sZW5ndGggPyBwb3B1cCA6IHRoaXMuX3BvcHVwO1xyXG4gIFx0XHRpZiAocG9wdXApIHtcclxuICBcdFx0XHRwb3B1cC5jbG9zZSgpO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fVxyXG4gIH0pO1xyXG5cclxuICAvKlxyXG4gICAqIEBuYW1lc3BhY2UgTGF5ZXJcclxuICAgKiBAc2VjdGlvbiBQb3B1cCBtZXRob2RzIGV4YW1wbGVcclxuICAgKlxyXG4gICAqIEFsbCBsYXllcnMgc2hhcmUgYSBzZXQgb2YgbWV0aG9kcyBjb252ZW5pZW50IGZvciBiaW5kaW5nIHBvcHVwcyB0byBpdC5cclxuICAgKlxyXG4gICAqIGBgYGpzXHJcbiAgICogdmFyIGxheWVyID0gTC5Qb2x5Z29uKGxhdGxuZ3MpLmJpbmRQb3B1cCgnSGkgVGhlcmUhJykuYWRkVG8obWFwKTtcclxuICAgKiBsYXllci5vcGVuUG9wdXAoKTtcclxuICAgKiBsYXllci5jbG9zZVBvcHVwKCk7XHJcbiAgICogYGBgXHJcbiAgICpcclxuICAgKiBQb3B1cHMgd2lsbCBhbHNvIGJlIGF1dG9tYXRpY2FsbHkgb3BlbmVkIHdoZW4gdGhlIGxheWVyIGlzIGNsaWNrZWQgb24gYW5kIGNsb3NlZCB3aGVuIHRoZSBsYXllciBpcyByZW1vdmVkIGZyb20gdGhlIG1hcCBvciBhbm90aGVyIHBvcHVwIGlzIG9wZW5lZC5cclxuICAgKi9cclxuXHJcbiAgLy8gQHNlY3Rpb24gUG9wdXAgbWV0aG9kc1xyXG4gIExheWVyLmluY2x1ZGUoe1xyXG5cclxuICBcdC8vIEBtZXRob2QgYmluZFBvcHVwKGNvbnRlbnQ6IFN0cmluZ3xIVE1MRWxlbWVudHxGdW5jdGlvbnxQb3B1cCwgb3B0aW9ucz86IFBvcHVwIG9wdGlvbnMpOiB0aGlzXHJcbiAgXHQvLyBCaW5kcyBhIHBvcHVwIHRvIHRoZSBsYXllciB3aXRoIHRoZSBwYXNzZWQgYGNvbnRlbnRgIGFuZCBzZXRzIHVwIHRoZVxyXG4gIFx0Ly8gbmVjZXNzYXJ5IGV2ZW50IGxpc3RlbmVycy4gSWYgYSBgRnVuY3Rpb25gIGlzIHBhc3NlZCBpdCB3aWxsIHJlY2VpdmVcclxuICBcdC8vIHRoZSBsYXllciBhcyB0aGUgZmlyc3QgYXJndW1lbnQgYW5kIHNob3VsZCByZXR1cm4gYSBgU3RyaW5nYCBvciBgSFRNTEVsZW1lbnRgLlxyXG4gIFx0YmluZFBvcHVwOiBmdW5jdGlvbiAoY29udGVudCwgb3B0aW9ucykge1xyXG4gIFx0XHR0aGlzLl9wb3B1cCA9IHRoaXMuX2luaXRPdmVybGF5KFBvcHVwLCB0aGlzLl9wb3B1cCwgY29udGVudCwgb3B0aW9ucyk7XHJcbiAgXHRcdGlmICghdGhpcy5fcG9wdXBIYW5kbGVyc0FkZGVkKSB7XHJcbiAgXHRcdFx0dGhpcy5vbih7XHJcbiAgXHRcdFx0XHRjbGljazogdGhpcy5fb3BlblBvcHVwLFxyXG4gIFx0XHRcdFx0a2V5cHJlc3M6IHRoaXMuX29uS2V5UHJlc3MsXHJcbiAgXHRcdFx0XHRyZW1vdmU6IHRoaXMuY2xvc2VQb3B1cCxcclxuICBcdFx0XHRcdG1vdmU6IHRoaXMuX21vdmVQb3B1cFxyXG4gIFx0XHRcdH0pO1xyXG4gIFx0XHRcdHRoaXMuX3BvcHVwSGFuZGxlcnNBZGRlZCA9IHRydWU7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHVuYmluZFBvcHVwKCk6IHRoaXNcclxuICBcdC8vIFJlbW92ZXMgdGhlIHBvcHVwIHByZXZpb3VzbHkgYm91bmQgd2l0aCBgYmluZFBvcHVwYC5cclxuICBcdHVuYmluZFBvcHVwOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICh0aGlzLl9wb3B1cCkge1xyXG4gIFx0XHRcdHRoaXMub2ZmKHtcclxuICBcdFx0XHRcdGNsaWNrOiB0aGlzLl9vcGVuUG9wdXAsXHJcbiAgXHRcdFx0XHRrZXlwcmVzczogdGhpcy5fb25LZXlQcmVzcyxcclxuICBcdFx0XHRcdHJlbW92ZTogdGhpcy5jbG9zZVBvcHVwLFxyXG4gIFx0XHRcdFx0bW92ZTogdGhpcy5fbW92ZVBvcHVwXHJcbiAgXHRcdFx0fSk7XHJcbiAgXHRcdFx0dGhpcy5fcG9wdXBIYW5kbGVyc0FkZGVkID0gZmFsc2U7XHJcbiAgXHRcdFx0dGhpcy5fcG9wdXAgPSBudWxsO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIG9wZW5Qb3B1cChsYXRsbmc/OiBMYXRMbmcpOiB0aGlzXHJcbiAgXHQvLyBPcGVucyB0aGUgYm91bmQgcG9wdXAgYXQgdGhlIHNwZWNpZmllZCBgbGF0bG5nYCBvciBhdCB0aGUgZGVmYXVsdCBwb3B1cCBhbmNob3IgaWYgbm8gYGxhdGxuZ2AgaXMgcGFzc2VkLlxyXG4gIFx0b3BlblBvcHVwOiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcbiAgXHRcdGlmICh0aGlzLl9wb3B1cCkge1xyXG4gIFx0XHRcdGlmICghKHRoaXMgaW5zdGFuY2VvZiBGZWF0dXJlR3JvdXApKSB7XHJcbiAgXHRcdFx0XHR0aGlzLl9wb3B1cC5fc291cmNlID0gdGhpcztcclxuICBcdFx0XHR9XHJcbiAgXHRcdFx0aWYgKHRoaXMuX3BvcHVwLl9wcmVwYXJlT3BlbihsYXRsbmcgfHwgdGhpcy5fbGF0bG5nKSkge1xyXG4gIFx0XHRcdFx0Ly8gb3BlbiB0aGUgcG9wdXAgb24gdGhlIG1hcFxyXG4gIFx0XHRcdFx0dGhpcy5fcG9wdXAub3Blbk9uKHRoaXMuX21hcCk7XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcbiAgXHRcdHJldHVybiB0aGlzO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIGNsb3NlUG9wdXAoKTogdGhpc1xyXG4gIFx0Ly8gQ2xvc2VzIHRoZSBwb3B1cCBib3VuZCB0byB0aGlzIGxheWVyIGlmIGl0IGlzIG9wZW4uXHJcbiAgXHRjbG9zZVBvcHVwOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICh0aGlzLl9wb3B1cCkge1xyXG4gIFx0XHRcdHRoaXMuX3BvcHVwLmNsb3NlKCk7XHJcbiAgXHRcdH1cclxuICBcdFx0cmV0dXJuIHRoaXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIEBtZXRob2QgdG9nZ2xlUG9wdXAoKTogdGhpc1xyXG4gIFx0Ly8gT3BlbnMgb3IgY2xvc2VzIHRoZSBwb3B1cCBib3VuZCB0byB0aGlzIGxheWVyIGRlcGVuZGluZyBvbiBpdHMgY3VycmVudCBzdGF0ZS5cclxuICBcdHRvZ2dsZVBvcHVwOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdGlmICh0aGlzLl9wb3B1cCkge1xyXG4gIFx0XHRcdHRoaXMuX3BvcHVwLnRvZ2dsZSh0aGlzKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBpc1BvcHVwT3BlbigpOiBib29sZWFuXHJcbiAgXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcG9wdXAgYm91bmQgdG8gdGhpcyBsYXllciBpcyBjdXJyZW50bHkgb3Blbi5cclxuICBcdGlzUG9wdXBPcGVuOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiAodGhpcy5fcG9wdXAgPyB0aGlzLl9wb3B1cC5pc09wZW4oKSA6IGZhbHNlKTtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBzZXRQb3B1cENvbnRlbnQoY29udGVudDogU3RyaW5nfEhUTUxFbGVtZW50fFBvcHVwKTogdGhpc1xyXG4gIFx0Ly8gU2V0cyB0aGUgY29udGVudCBvZiB0aGUgcG9wdXAgYm91bmQgdG8gdGhpcyBsYXllci5cclxuICBcdHNldFBvcHVwQ29udGVudDogZnVuY3Rpb24gKGNvbnRlbnQpIHtcclxuICBcdFx0aWYgKHRoaXMuX3BvcHVwKSB7XHJcbiAgXHRcdFx0dGhpcy5fcG9wdXAuc2V0Q29udGVudChjb250ZW50KTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBnZXRQb3B1cCgpOiBQb3B1cFxyXG4gIFx0Ly8gUmV0dXJucyB0aGUgcG9wdXAgYm91bmQgdG8gdGhpcyBsYXllci5cclxuICBcdGdldFBvcHVwOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHJldHVybiB0aGlzLl9wb3B1cDtcclxuICBcdH0sXHJcblxyXG4gIFx0X29wZW5Qb3B1cDogZnVuY3Rpb24gKGUpIHtcclxuICBcdFx0aWYgKCF0aGlzLl9wb3B1cCB8fCAhdGhpcy5fbWFwKSB7XHJcbiAgXHRcdFx0cmV0dXJuO1xyXG4gIFx0XHR9XHJcbiAgXHRcdC8vIHByZXZlbnQgbWFwIGNsaWNrXHJcbiAgXHRcdHN0b3AoZSk7XHJcblxyXG4gIFx0XHR2YXIgdGFyZ2V0ID0gZS5sYXllciB8fCBlLnRhcmdldDtcclxuICBcdFx0aWYgKHRoaXMuX3BvcHVwLl9zb3VyY2UgPT09IHRhcmdldCAmJiAhKHRhcmdldCBpbnN0YW5jZW9mIFBhdGgpKSB7XHJcbiAgXHRcdFx0Ly8gdHJlYXQgaXQgbGlrZSBhIG1hcmtlciBhbmQgZmlndXJlIG91dFxyXG4gIFx0XHRcdC8vIGlmIHdlIHNob3VsZCB0b2dnbGUgaXQgb3Blbi9jbG9zZWRcclxuICBcdFx0XHRpZiAodGhpcy5fbWFwLmhhc0xheWVyKHRoaXMuX3BvcHVwKSkge1xyXG4gIFx0XHRcdFx0dGhpcy5jbG9zZVBvcHVwKCk7XHJcbiAgXHRcdFx0fSBlbHNlIHtcclxuICBcdFx0XHRcdHRoaXMub3BlblBvcHVwKGUubGF0bG5nKTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdFx0cmV0dXJuO1xyXG4gIFx0XHR9XHJcbiAgXHRcdHRoaXMuX3BvcHVwLl9zb3VyY2UgPSB0YXJnZXQ7XHJcbiAgXHRcdHRoaXMub3BlblBvcHVwKGUubGF0bG5nKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X21vdmVQb3B1cDogZnVuY3Rpb24gKGUpIHtcclxuICBcdFx0dGhpcy5fcG9wdXAuc2V0TGF0TG5nKGUubGF0bG5nKTtcclxuICBcdH0sXHJcblxyXG4gIFx0X29uS2V5UHJlc3M6IGZ1bmN0aW9uIChlKSB7XHJcbiAgXHRcdGlmIChlLm9yaWdpbmFsRXZlbnQua2V5Q29kZSA9PT0gMTMpIHtcclxuICBcdFx0XHR0aGlzLl9vcGVuUG9wdXAoZSk7XHJcbiAgXHRcdH1cclxuICBcdH1cclxuICB9KTtcblxuICAvKlxuICAgKiBAY2xhc3MgVG9vbHRpcFxuICAgKiBAaW5oZXJpdHMgRGl2T3ZlcmxheVxuICAgKiBAYWthIEwuVG9vbHRpcFxuICAgKiBVc2VkIHRvIGRpc3BsYXkgc21hbGwgdGV4dHMgb24gdG9wIG9mIG1hcCBsYXllcnMuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIElmIHlvdSB3YW50IHRvIGp1c3QgYmluZCBhIHRvb2x0aXAgdG8gbWFya2VyOlxuICAgKlxuICAgKiBgYGBqc1xuICAgKiBtYXJrZXIuYmluZFRvb2x0aXAoXCJteSB0b29sdGlwIHRleHRcIikub3BlblRvb2x0aXAoKTtcbiAgICogYGBgXG4gICAqIFBhdGggb3ZlcmxheXMgbGlrZSBwb2x5bGluZXMgYWxzbyBoYXZlIGEgYGJpbmRUb29sdGlwYCBtZXRob2QuXG4gICAqXG4gICAqIEEgdG9vbHRpcCBjYW4gYmUgYWxzbyBzdGFuZGFsb25lOlxuICAgKlxuICAgKiBgYGBqc1xuICAgKiB2YXIgdG9vbHRpcCA9IEwudG9vbHRpcCgpXG4gICAqIFx0LnNldExhdExuZyhsYXRsbmcpXG4gICAqIFx0LnNldENvbnRlbnQoJ0hlbGxvIHdvcmxkITxiciAvPlRoaXMgaXMgYSBuaWNlIHRvb2x0aXAuJylcbiAgICogXHQuYWRkVG8obWFwKTtcbiAgICogYGBgXG4gICAqIG9yXG4gICAqIGBgYGpzXG4gICAqIHZhciB0b29sdGlwID0gTC50b29sdGlwKGxhdGxuZywge2NvbnRlbnQ6ICdIZWxsbyB3b3JsZCE8YnIgLz5UaGlzIGlzIGEgbmljZSB0b29sdGlwLid9KVxuICAgKiBcdC5hZGRUbyhtYXApO1xuICAgKiBgYGBcbiAgICpcbiAgICpcbiAgICogTm90ZSBhYm91dCB0b29sdGlwIG9mZnNldC4gTGVhZmxldCB0YWtlcyB0d28gb3B0aW9ucyBpbiBjb25zaWRlcmF0aW9uXG4gICAqIGZvciBjb21wdXRpbmcgdG9vbHRpcCBvZmZzZXR0aW5nOlxuICAgKiAtIHRoZSBgb2Zmc2V0YCBUb29sdGlwIG9wdGlvbjogaXQgZGVmYXVsdHMgdG8gWzAsIDBdLCBhbmQgaXQncyBzcGVjaWZpYyB0byBvbmUgdG9vbHRpcC5cbiAgICogICBBZGQgYSBwb3NpdGl2ZSB4IG9mZnNldCB0byBtb3ZlIHRoZSB0b29sdGlwIHRvIHRoZSByaWdodCwgYW5kIGEgcG9zaXRpdmUgeSBvZmZzZXQgdG9cbiAgICogICBtb3ZlIGl0IHRvIHRoZSBib3R0b20uIE5lZ2F0aXZlcyB3aWxsIG1vdmUgdG8gdGhlIGxlZnQgYW5kIHRvcC5cbiAgICogLSB0aGUgYHRvb2x0aXBBbmNob3JgIEljb24gb3B0aW9uOiB0aGlzIHdpbGwgb25seSBiZSBjb25zaWRlcmVkIGZvciBNYXJrZXIuIFlvdVxuICAgKiAgIHNob3VsZCBhZGFwdCB0aGlzIHZhbHVlIGlmIHlvdSB1c2UgYSBjdXN0b20gaWNvbi5cbiAgICovXG5cblxuICAvLyBAbmFtZXNwYWNlIFRvb2x0aXBcbiAgdmFyIFRvb2x0aXAgPSBEaXZPdmVybGF5LmV4dGVuZCh7XG5cbiAgXHQvLyBAc2VjdGlvblxuICBcdC8vIEBha2EgVG9vbHRpcCBvcHRpb25zXG4gIFx0b3B0aW9uczoge1xuICBcdFx0Ly8gQG9wdGlvbiBwYW5lOiBTdHJpbmcgPSAndG9vbHRpcFBhbmUnXG4gIFx0XHQvLyBgTWFwIHBhbmVgIHdoZXJlIHRoZSB0b29sdGlwIHdpbGwgYmUgYWRkZWQuXG4gIFx0XHRwYW5lOiAndG9vbHRpcFBhbmUnLFxuXG4gIFx0XHQvLyBAb3B0aW9uIG9mZnNldDogUG9pbnQgPSBQb2ludCgwLCAwKVxuICBcdFx0Ly8gT3B0aW9uYWwgb2Zmc2V0IG9mIHRoZSB0b29sdGlwIHBvc2l0aW9uLlxuICBcdFx0b2Zmc2V0OiBbMCwgMF0sXG5cbiAgXHRcdC8vIEBvcHRpb24gZGlyZWN0aW9uOiBTdHJpbmcgPSAnYXV0bydcbiAgXHRcdC8vIERpcmVjdGlvbiB3aGVyZSB0byBvcGVuIHRoZSB0b29sdGlwLiBQb3NzaWJsZSB2YWx1ZXMgYXJlOiBgcmlnaHRgLCBgbGVmdGAsXG4gIFx0XHQvLyBgdG9wYCwgYGJvdHRvbWAsIGBjZW50ZXJgLCBgYXV0b2AuXG4gIFx0XHQvLyBgYXV0b2Agd2lsbCBkeW5hbWljYWxseSBzd2l0Y2ggYmV0d2VlbiBgcmlnaHRgIGFuZCBgbGVmdGAgYWNjb3JkaW5nIHRvIHRoZSB0b29sdGlwXG4gIFx0XHQvLyBwb3NpdGlvbiBvbiB0aGUgbWFwLlxuICBcdFx0ZGlyZWN0aW9uOiAnYXV0bycsXG5cbiAgXHRcdC8vIEBvcHRpb24gcGVybWFuZW50OiBCb29sZWFuID0gZmFsc2VcbiAgXHRcdC8vIFdoZXRoZXIgdG8gb3BlbiB0aGUgdG9vbHRpcCBwZXJtYW5lbnRseSBvciBvbmx5IG9uIG1vdXNlb3Zlci5cbiAgXHRcdHBlcm1hbmVudDogZmFsc2UsXG5cbiAgXHRcdC8vIEBvcHRpb24gc3RpY2t5OiBCb29sZWFuID0gZmFsc2VcbiAgXHRcdC8vIElmIHRydWUsIHRoZSB0b29sdGlwIHdpbGwgZm9sbG93IHRoZSBtb3VzZSBpbnN0ZWFkIG9mIGJlaW5nIGZpeGVkIGF0IHRoZSBmZWF0dXJlIGNlbnRlci5cbiAgXHRcdHN0aWNreTogZmFsc2UsXG5cbiAgXHRcdC8vIEBvcHRpb24gb3BhY2l0eTogTnVtYmVyID0gMC45XG4gIFx0XHQvLyBUb29sdGlwIGNvbnRhaW5lciBvcGFjaXR5LlxuICBcdFx0b3BhY2l0eTogMC45XG4gIFx0fSxcblxuICBcdG9uQWRkOiBmdW5jdGlvbiAobWFwKSB7XG4gIFx0XHREaXZPdmVybGF5LnByb3RvdHlwZS5vbkFkZC5jYWxsKHRoaXMsIG1hcCk7XG4gIFx0XHR0aGlzLnNldE9wYWNpdHkodGhpcy5vcHRpb25zLm9wYWNpdHkpO1xuXG4gIFx0XHQvLyBAbmFtZXNwYWNlIE1hcFxuICBcdFx0Ly8gQHNlY3Rpb24gVG9vbHRpcCBldmVudHNcbiAgXHRcdC8vIEBldmVudCB0b29sdGlwb3BlbjogVG9vbHRpcEV2ZW50XG4gIFx0XHQvLyBGaXJlZCB3aGVuIGEgdG9vbHRpcCBpcyBvcGVuZWQgaW4gdGhlIG1hcC5cbiAgXHRcdG1hcC5maXJlKCd0b29sdGlwb3BlbicsIHt0b29sdGlwOiB0aGlzfSk7XG5cbiAgXHRcdGlmICh0aGlzLl9zb3VyY2UpIHtcbiAgXHRcdFx0dGhpcy5hZGRFdmVudFBhcmVudCh0aGlzLl9zb3VyY2UpO1xuXG4gIFx0XHRcdC8vIEBuYW1lc3BhY2UgTGF5ZXJcbiAgXHRcdFx0Ly8gQHNlY3Rpb24gVG9vbHRpcCBldmVudHNcbiAgXHRcdFx0Ly8gQGV2ZW50IHRvb2x0aXBvcGVuOiBUb29sdGlwRXZlbnRcbiAgXHRcdFx0Ly8gRmlyZWQgd2hlbiBhIHRvb2x0aXAgYm91bmQgdG8gdGhpcyBsYXllciBpcyBvcGVuZWQuXG4gIFx0XHRcdHRoaXMuX3NvdXJjZS5maXJlKCd0b29sdGlwb3BlbicsIHt0b29sdGlwOiB0aGlzfSwgdHJ1ZSk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdG9uUmVtb3ZlOiBmdW5jdGlvbiAobWFwKSB7XG4gIFx0XHREaXZPdmVybGF5LnByb3RvdHlwZS5vblJlbW92ZS5jYWxsKHRoaXMsIG1hcCk7XG5cbiAgXHRcdC8vIEBuYW1lc3BhY2UgTWFwXG4gIFx0XHQvLyBAc2VjdGlvbiBUb29sdGlwIGV2ZW50c1xuICBcdFx0Ly8gQGV2ZW50IHRvb2x0aXBjbG9zZTogVG9vbHRpcEV2ZW50XG4gIFx0XHQvLyBGaXJlZCB3aGVuIGEgdG9vbHRpcCBpbiB0aGUgbWFwIGlzIGNsb3NlZC5cbiAgXHRcdG1hcC5maXJlKCd0b29sdGlwY2xvc2UnLCB7dG9vbHRpcDogdGhpc30pO1xuXG4gIFx0XHRpZiAodGhpcy5fc291cmNlKSB7XG4gIFx0XHRcdHRoaXMucmVtb3ZlRXZlbnRQYXJlbnQodGhpcy5fc291cmNlKTtcblxuICBcdFx0XHQvLyBAbmFtZXNwYWNlIExheWVyXG4gIFx0XHRcdC8vIEBzZWN0aW9uIFRvb2x0aXAgZXZlbnRzXG4gIFx0XHRcdC8vIEBldmVudCB0b29sdGlwY2xvc2U6IFRvb2x0aXBFdmVudFxuICBcdFx0XHQvLyBGaXJlZCB3aGVuIGEgdG9vbHRpcCBib3VuZCB0byB0aGlzIGxheWVyIGlzIGNsb3NlZC5cbiAgXHRcdFx0dGhpcy5fc291cmNlLmZpcmUoJ3Rvb2x0aXBjbG9zZScsIHt0b29sdGlwOiB0aGlzfSwgdHJ1ZSk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdGdldEV2ZW50czogZnVuY3Rpb24gKCkge1xuICBcdFx0dmFyIGV2ZW50cyA9IERpdk92ZXJsYXkucHJvdG90eXBlLmdldEV2ZW50cy5jYWxsKHRoaXMpO1xuXG4gIFx0XHRpZiAoIXRoaXMub3B0aW9ucy5wZXJtYW5lbnQpIHtcbiAgXHRcdFx0ZXZlbnRzLnByZWNsaWNrID0gdGhpcy5jbG9zZTtcbiAgXHRcdH1cblxuICBcdFx0cmV0dXJuIGV2ZW50cztcbiAgXHR9LFxuXG4gIFx0X2luaXRMYXlvdXQ6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHZhciBwcmVmaXggPSAnbGVhZmxldC10b29sdGlwJyxcbiAgXHRcdCAgICBjbGFzc05hbWUgPSBwcmVmaXggKyAnICcgKyAodGhpcy5vcHRpb25zLmNsYXNzTmFtZSB8fCAnJykgKyAnIGxlYWZsZXQtem9vbS0nICsgKHRoaXMuX3pvb21BbmltYXRlZCA/ICdhbmltYXRlZCcgOiAnaGlkZScpO1xuXG4gIFx0XHR0aGlzLl9jb250ZW50Tm9kZSA9IHRoaXMuX2NvbnRhaW5lciA9IGNyZWF0ZSQxKCdkaXYnLCBjbGFzc05hbWUpO1xuXG4gIFx0XHR0aGlzLl9jb250YWluZXIuc2V0QXR0cmlidXRlKCdyb2xlJywgJ3Rvb2x0aXAnKTtcbiAgXHRcdHRoaXMuX2NvbnRhaW5lci5zZXRBdHRyaWJ1dGUoJ2lkJywgJ2xlYWZsZXQtdG9vbHRpcC0nICsgc3RhbXAodGhpcykpO1xuICBcdH0sXG5cbiAgXHRfdXBkYXRlTGF5b3V0OiBmdW5jdGlvbiAoKSB7fSxcblxuICBcdF9hZGp1c3RQYW46IGZ1bmN0aW9uICgpIHt9LFxuXG4gIFx0X3NldFBvc2l0aW9uOiBmdW5jdGlvbiAocG9zKSB7XG4gIFx0XHR2YXIgc3ViWCwgc3ViWSxcbiAgXHRcdCAgICBtYXAgPSB0aGlzLl9tYXAsXG4gIFx0XHQgICAgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyLFxuICBcdFx0ICAgIGNlbnRlclBvaW50ID0gbWFwLmxhdExuZ1RvQ29udGFpbmVyUG9pbnQobWFwLmdldENlbnRlcigpKSxcbiAgXHRcdCAgICB0b29sdGlwUG9pbnQgPSBtYXAubGF5ZXJQb2ludFRvQ29udGFpbmVyUG9pbnQocG9zKSxcbiAgXHRcdCAgICBkaXJlY3Rpb24gPSB0aGlzLm9wdGlvbnMuZGlyZWN0aW9uLFxuICBcdFx0ICAgIHRvb2x0aXBXaWR0aCA9IGNvbnRhaW5lci5vZmZzZXRXaWR0aCxcbiAgXHRcdCAgICB0b29sdGlwSGVpZ2h0ID0gY29udGFpbmVyLm9mZnNldEhlaWdodCxcbiAgXHRcdCAgICBvZmZzZXQgPSB0b1BvaW50KHRoaXMub3B0aW9ucy5vZmZzZXQpLFxuICBcdFx0ICAgIGFuY2hvciA9IHRoaXMuX2dldEFuY2hvcigpO1xuXG4gIFx0XHRpZiAoZGlyZWN0aW9uID09PSAndG9wJykge1xuICBcdFx0XHRzdWJYID0gdG9vbHRpcFdpZHRoIC8gMjtcbiAgXHRcdFx0c3ViWSA9IHRvb2x0aXBIZWlnaHQ7XG4gIFx0XHR9IGVsc2UgaWYgKGRpcmVjdGlvbiA9PT0gJ2JvdHRvbScpIHtcbiAgXHRcdFx0c3ViWCA9IHRvb2x0aXBXaWR0aCAvIDI7XG4gIFx0XHRcdHN1YlkgPSAwO1xuICBcdFx0fSBlbHNlIGlmIChkaXJlY3Rpb24gPT09ICdjZW50ZXInKSB7XG4gIFx0XHRcdHN1YlggPSB0b29sdGlwV2lkdGggLyAyO1xuICBcdFx0XHRzdWJZID0gdG9vbHRpcEhlaWdodCAvIDI7XG4gIFx0XHR9IGVsc2UgaWYgKGRpcmVjdGlvbiA9PT0gJ3JpZ2h0Jykge1xuICBcdFx0XHRzdWJYID0gMDtcbiAgXHRcdFx0c3ViWSA9IHRvb2x0aXBIZWlnaHQgLyAyO1xuICBcdFx0fSBlbHNlIGlmIChkaXJlY3Rpb24gPT09ICdsZWZ0Jykge1xuICBcdFx0XHRzdWJYID0gdG9vbHRpcFdpZHRoO1xuICBcdFx0XHRzdWJZID0gdG9vbHRpcEhlaWdodCAvIDI7XG4gIFx0XHR9IGVsc2UgaWYgKHRvb2x0aXBQb2ludC54IDwgY2VudGVyUG9pbnQueCkge1xuICBcdFx0XHRkaXJlY3Rpb24gPSAncmlnaHQnO1xuICBcdFx0XHRzdWJYID0gMDtcbiAgXHRcdFx0c3ViWSA9IHRvb2x0aXBIZWlnaHQgLyAyO1xuICBcdFx0fSBlbHNlIHtcbiAgXHRcdFx0ZGlyZWN0aW9uID0gJ2xlZnQnO1xuICBcdFx0XHRzdWJYID0gdG9vbHRpcFdpZHRoICsgKG9mZnNldC54ICsgYW5jaG9yLngpICogMjtcbiAgXHRcdFx0c3ViWSA9IHRvb2x0aXBIZWlnaHQgLyAyO1xuICBcdFx0fVxuXG4gIFx0XHRwb3MgPSBwb3Muc3VidHJhY3QodG9Qb2ludChzdWJYLCBzdWJZLCB0cnVlKSkuYWRkKG9mZnNldCkuYWRkKGFuY2hvcik7XG5cbiAgXHRcdHJlbW92ZUNsYXNzKGNvbnRhaW5lciwgJ2xlYWZsZXQtdG9vbHRpcC1yaWdodCcpO1xuICBcdFx0cmVtb3ZlQ2xhc3MoY29udGFpbmVyLCAnbGVhZmxldC10b29sdGlwLWxlZnQnKTtcbiAgXHRcdHJlbW92ZUNsYXNzKGNvbnRhaW5lciwgJ2xlYWZsZXQtdG9vbHRpcC10b3AnKTtcbiAgXHRcdHJlbW92ZUNsYXNzKGNvbnRhaW5lciwgJ2xlYWZsZXQtdG9vbHRpcC1ib3R0b20nKTtcbiAgXHRcdGFkZENsYXNzKGNvbnRhaW5lciwgJ2xlYWZsZXQtdG9vbHRpcC0nICsgZGlyZWN0aW9uKTtcbiAgXHRcdHNldFBvc2l0aW9uKGNvbnRhaW5lciwgcG9zKTtcbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZVBvc2l0aW9uOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR2YXIgcG9zID0gdGhpcy5fbWFwLmxhdExuZ1RvTGF5ZXJQb2ludCh0aGlzLl9sYXRsbmcpO1xuICBcdFx0dGhpcy5fc2V0UG9zaXRpb24ocG9zKTtcbiAgXHR9LFxuXG4gIFx0c2V0T3BhY2l0eTogZnVuY3Rpb24gKG9wYWNpdHkpIHtcbiAgXHRcdHRoaXMub3B0aW9ucy5vcGFjaXR5ID0gb3BhY2l0eTtcblxuICBcdFx0aWYgKHRoaXMuX2NvbnRhaW5lcikge1xuICBcdFx0XHRzZXRPcGFjaXR5KHRoaXMuX2NvbnRhaW5lciwgb3BhY2l0eSk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF9hbmltYXRlWm9vbTogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdHZhciBwb3MgPSB0aGlzLl9tYXAuX2xhdExuZ1RvTmV3TGF5ZXJQb2ludCh0aGlzLl9sYXRsbmcsIGUuem9vbSwgZS5jZW50ZXIpO1xuICBcdFx0dGhpcy5fc2V0UG9zaXRpb24ocG9zKTtcbiAgXHR9LFxuXG4gIFx0X2dldEFuY2hvcjogZnVuY3Rpb24gKCkge1xuICBcdFx0Ly8gV2hlcmUgc2hvdWxkIHdlIGFuY2hvciB0aGUgdG9vbHRpcCBvbiB0aGUgc291cmNlIGxheWVyP1xuICBcdFx0cmV0dXJuIHRvUG9pbnQodGhpcy5fc291cmNlICYmIHRoaXMuX3NvdXJjZS5fZ2V0VG9vbHRpcEFuY2hvciAmJiAhdGhpcy5vcHRpb25zLnN0aWNreSA/IHRoaXMuX3NvdXJjZS5fZ2V0VG9vbHRpcEFuY2hvcigpIDogWzAsIDBdKTtcbiAgXHR9XG5cbiAgfSk7XG5cbiAgLy8gQG5hbWVzcGFjZSBUb29sdGlwXG4gIC8vIEBmYWN0b3J5IEwudG9vbHRpcChvcHRpb25zPzogVG9vbHRpcCBvcHRpb25zLCBzb3VyY2U/OiBMYXllcilcbiAgLy8gSW5zdGFudGlhdGVzIGEgYFRvb2x0aXBgIG9iamVjdCBnaXZlbiBhbiBvcHRpb25hbCBgb3B0aW9uc2Agb2JqZWN0IHRoYXQgZGVzY3JpYmVzIGl0cyBhcHBlYXJhbmNlIGFuZCBsb2NhdGlvbiBhbmQgYW4gb3B0aW9uYWwgYHNvdXJjZWAgb2JqZWN0IHRoYXQgaXMgdXNlZCB0byB0YWcgdGhlIHRvb2x0aXAgd2l0aCBhIHJlZmVyZW5jZSB0byB0aGUgTGF5ZXIgdG8gd2hpY2ggaXQgcmVmZXJzLlxuICAvLyBAYWx0ZXJuYXRpdmVcbiAgLy8gQGZhY3RvcnkgTC50b29sdGlwKGxhdGxuZzogTGF0TG5nLCBvcHRpb25zPzogVG9vbHRpcCBvcHRpb25zKVxuICAvLyBJbnN0YW50aWF0ZXMgYSBgVG9vbHRpcGAgb2JqZWN0IGdpdmVuIGBsYXRsbmdgIHdoZXJlIHRoZSB0b29sdGlwIHdpbGwgb3BlbiBhbmQgYW4gb3B0aW9uYWwgYG9wdGlvbnNgIG9iamVjdCB0aGF0IGRlc2NyaWJlcyBpdHMgYXBwZWFyYW5jZSBhbmQgbG9jYXRpb24uXG4gIHZhciB0b29sdGlwID0gZnVuY3Rpb24gKG9wdGlvbnMsIHNvdXJjZSkge1xuICBcdHJldHVybiBuZXcgVG9vbHRpcChvcHRpb25zLCBzb3VyY2UpO1xuICB9O1xuXG4gIC8vIEBuYW1lc3BhY2UgTWFwXG4gIC8vIEBzZWN0aW9uIE1ldGhvZHMgZm9yIExheWVycyBhbmQgQ29udHJvbHNcbiAgTWFwLmluY2x1ZGUoe1xuXG4gIFx0Ly8gQG1ldGhvZCBvcGVuVG9vbHRpcCh0b29sdGlwOiBUb29sdGlwKTogdGhpc1xuICBcdC8vIE9wZW5zIHRoZSBzcGVjaWZpZWQgdG9vbHRpcC5cbiAgXHQvLyBAYWx0ZXJuYXRpdmVcbiAgXHQvLyBAbWV0aG9kIG9wZW5Ub29sdGlwKGNvbnRlbnQ6IFN0cmluZ3xIVE1MRWxlbWVudCwgbGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/OiBUb29sdGlwIG9wdGlvbnMpOiB0aGlzXG4gIFx0Ly8gQ3JlYXRlcyBhIHRvb2x0aXAgd2l0aCB0aGUgc3BlY2lmaWVkIGNvbnRlbnQgYW5kIG9wdGlvbnMgYW5kIG9wZW4gaXQuXG4gIFx0b3BlblRvb2x0aXA6IGZ1bmN0aW9uICh0b29sdGlwLCBsYXRsbmcsIG9wdGlvbnMpIHtcbiAgXHRcdHRoaXMuX2luaXRPdmVybGF5KFRvb2x0aXAsIHRvb2x0aXAsIGxhdGxuZywgb3B0aW9ucylcbiAgXHRcdCAgLm9wZW5Pbih0aGlzKTtcblxuICBcdFx0cmV0dXJuIHRoaXM7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgY2xvc2VUb29sdGlwKHRvb2x0aXA6IFRvb2x0aXApOiB0aGlzXG4gIFx0Ly8gQ2xvc2VzIHRoZSB0b29sdGlwIGdpdmVuIGFzIHBhcmFtZXRlci5cbiAgXHRjbG9zZVRvb2x0aXA6IGZ1bmN0aW9uICh0b29sdGlwKSB7XG4gIFx0XHR0b29sdGlwLmNsb3NlKCk7XG4gIFx0XHRyZXR1cm4gdGhpcztcbiAgXHR9XG5cbiAgfSk7XG5cbiAgLypcbiAgICogQG5hbWVzcGFjZSBMYXllclxuICAgKiBAc2VjdGlvbiBUb29sdGlwIG1ldGhvZHMgZXhhbXBsZVxuICAgKlxuICAgKiBBbGwgbGF5ZXJzIHNoYXJlIGEgc2V0IG9mIG1ldGhvZHMgY29udmVuaWVudCBmb3IgYmluZGluZyB0b29sdGlwcyB0byBpdC5cbiAgICpcbiAgICogYGBganNcbiAgICogdmFyIGxheWVyID0gTC5Qb2x5Z29uKGxhdGxuZ3MpLmJpbmRUb29sdGlwKCdIaSBUaGVyZSEnKS5hZGRUbyhtYXApO1xuICAgKiBsYXllci5vcGVuVG9vbHRpcCgpO1xuICAgKiBsYXllci5jbG9zZVRvb2x0aXAoKTtcbiAgICogYGBgXG4gICAqL1xuXG4gIC8vIEBzZWN0aW9uIFRvb2x0aXAgbWV0aG9kc1xuICBMYXllci5pbmNsdWRlKHtcblxuICBcdC8vIEBtZXRob2QgYmluZFRvb2x0aXAoY29udGVudDogU3RyaW5nfEhUTUxFbGVtZW50fEZ1bmN0aW9ufFRvb2x0aXAsIG9wdGlvbnM/OiBUb29sdGlwIG9wdGlvbnMpOiB0aGlzXG4gIFx0Ly8gQmluZHMgYSB0b29sdGlwIHRvIHRoZSBsYXllciB3aXRoIHRoZSBwYXNzZWQgYGNvbnRlbnRgIGFuZCBzZXRzIHVwIHRoZVxuICBcdC8vIG5lY2Vzc2FyeSBldmVudCBsaXN0ZW5lcnMuIElmIGEgYEZ1bmN0aW9uYCBpcyBwYXNzZWQgaXQgd2lsbCByZWNlaXZlXG4gIFx0Ly8gdGhlIGxheWVyIGFzIHRoZSBmaXJzdCBhcmd1bWVudCBhbmQgc2hvdWxkIHJldHVybiBhIGBTdHJpbmdgIG9yIGBIVE1MRWxlbWVudGAuXG4gIFx0YmluZFRvb2x0aXA6IGZ1bmN0aW9uIChjb250ZW50LCBvcHRpb25zKSB7XG5cbiAgXHRcdGlmICh0aGlzLl90b29sdGlwICYmIHRoaXMuaXNUb29sdGlwT3BlbigpKSB7XG4gIFx0XHRcdHRoaXMudW5iaW5kVG9vbHRpcCgpO1xuICBcdFx0fVxuXG4gIFx0XHR0aGlzLl90b29sdGlwID0gdGhpcy5faW5pdE92ZXJsYXkoVG9vbHRpcCwgdGhpcy5fdG9vbHRpcCwgY29udGVudCwgb3B0aW9ucyk7XG4gIFx0XHR0aGlzLl9pbml0VG9vbHRpcEludGVyYWN0aW9ucygpO1xuXG4gIFx0XHRpZiAodGhpcy5fdG9vbHRpcC5vcHRpb25zLnBlcm1hbmVudCAmJiB0aGlzLl9tYXAgJiYgdGhpcy5fbWFwLmhhc0xheWVyKHRoaXMpKSB7XG4gIFx0XHRcdHRoaXMub3BlblRvb2x0aXAoKTtcbiAgXHRcdH1cblxuICBcdFx0cmV0dXJuIHRoaXM7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgdW5iaW5kVG9vbHRpcCgpOiB0aGlzXG4gIFx0Ly8gUmVtb3ZlcyB0aGUgdG9vbHRpcCBwcmV2aW91c2x5IGJvdW5kIHdpdGggYGJpbmRUb29sdGlwYC5cbiAgXHR1bmJpbmRUb29sdGlwOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRpZiAodGhpcy5fdG9vbHRpcCkge1xuICBcdFx0XHR0aGlzLl9pbml0VG9vbHRpcEludGVyYWN0aW9ucyh0cnVlKTtcbiAgXHRcdFx0dGhpcy5jbG9zZVRvb2x0aXAoKTtcbiAgXHRcdFx0dGhpcy5fdG9vbHRpcCA9IG51bGw7XG4gIFx0XHR9XG4gIFx0XHRyZXR1cm4gdGhpcztcbiAgXHR9LFxuXG4gIFx0X2luaXRUb29sdGlwSW50ZXJhY3Rpb25zOiBmdW5jdGlvbiAocmVtb3ZlKSB7XG4gIFx0XHRpZiAoIXJlbW92ZSAmJiB0aGlzLl90b29sdGlwSGFuZGxlcnNBZGRlZCkgeyByZXR1cm47IH1cbiAgXHRcdHZhciBvbk9mZiA9IHJlbW92ZSA/ICdvZmYnIDogJ29uJyxcbiAgXHRcdCAgICBldmVudHMgPSB7XG4gIFx0XHRcdHJlbW92ZTogdGhpcy5jbG9zZVRvb2x0aXAsXG4gIFx0XHRcdG1vdmU6IHRoaXMuX21vdmVUb29sdGlwXG4gIFx0XHQgICAgfTtcbiAgXHRcdGlmICghdGhpcy5fdG9vbHRpcC5vcHRpb25zLnBlcm1hbmVudCkge1xuICBcdFx0XHRldmVudHMubW91c2VvdmVyID0gdGhpcy5fb3BlblRvb2x0aXA7XG4gIFx0XHRcdGV2ZW50cy5tb3VzZW91dCA9IHRoaXMuY2xvc2VUb29sdGlwO1xuICBcdFx0XHRldmVudHMuY2xpY2sgPSB0aGlzLl9vcGVuVG9vbHRpcDtcbiAgXHRcdFx0aWYgKHRoaXMuX21hcCkge1xuICBcdFx0XHRcdHRoaXMuX2FkZEZvY3VzTGlzdGVuZXJzKCk7XG4gIFx0XHRcdH0gZWxzZSB7XG4gIFx0XHRcdFx0ZXZlbnRzLmFkZCA9IHRoaXMuX2FkZEZvY3VzTGlzdGVuZXJzO1xuICBcdFx0XHR9XG4gIFx0XHR9IGVsc2Uge1xuICBcdFx0XHRldmVudHMuYWRkID0gdGhpcy5fb3BlblRvb2x0aXA7XG4gIFx0XHR9XG4gIFx0XHRpZiAodGhpcy5fdG9vbHRpcC5vcHRpb25zLnN0aWNreSkge1xuICBcdFx0XHRldmVudHMubW91c2Vtb3ZlID0gdGhpcy5fbW92ZVRvb2x0aXA7XG4gIFx0XHR9XG4gIFx0XHR0aGlzW29uT2ZmXShldmVudHMpO1xuICBcdFx0dGhpcy5fdG9vbHRpcEhhbmRsZXJzQWRkZWQgPSAhcmVtb3ZlO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIG9wZW5Ub29sdGlwKGxhdGxuZz86IExhdExuZyk6IHRoaXNcbiAgXHQvLyBPcGVucyB0aGUgYm91bmQgdG9vbHRpcCBhdCB0aGUgc3BlY2lmaWVkIGBsYXRsbmdgIG9yIGF0IHRoZSBkZWZhdWx0IHRvb2x0aXAgYW5jaG9yIGlmIG5vIGBsYXRsbmdgIGlzIHBhc3NlZC5cbiAgXHRvcGVuVG9vbHRpcDogZnVuY3Rpb24gKGxhdGxuZykge1xuICBcdFx0aWYgKHRoaXMuX3Rvb2x0aXApIHtcbiAgXHRcdFx0aWYgKCEodGhpcyBpbnN0YW5jZW9mIEZlYXR1cmVHcm91cCkpIHtcbiAgXHRcdFx0XHR0aGlzLl90b29sdGlwLl9zb3VyY2UgPSB0aGlzO1xuICBcdFx0XHR9XG4gIFx0XHRcdGlmICh0aGlzLl90b29sdGlwLl9wcmVwYXJlT3BlbihsYXRsbmcpKSB7XG4gIFx0XHRcdFx0Ly8gb3BlbiB0aGUgdG9vbHRpcCBvbiB0aGUgbWFwXG4gIFx0XHRcdFx0dGhpcy5fdG9vbHRpcC5vcGVuT24odGhpcy5fbWFwKTtcblxuICBcdFx0XHRcdGlmICh0aGlzLmdldEVsZW1lbnQpIHtcbiAgXHRcdFx0XHRcdHRoaXMuX3NldEFyaWFEZXNjcmliZWRCeU9uTGF5ZXIodGhpcyk7XG4gIFx0XHRcdFx0fSBlbHNlIGlmICh0aGlzLmVhY2hMYXllcikge1xuICBcdFx0XHRcdFx0dGhpcy5lYWNoTGF5ZXIodGhpcy5fc2V0QXJpYURlc2NyaWJlZEJ5T25MYXllciwgdGhpcyk7XG4gIFx0XHRcdFx0fVxuICBcdFx0XHR9XG4gIFx0XHR9XG4gIFx0XHRyZXR1cm4gdGhpcztcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBjbG9zZVRvb2x0aXAoKTogdGhpc1xuICBcdC8vIENsb3NlcyB0aGUgdG9vbHRpcCBib3VuZCB0byB0aGlzIGxheWVyIGlmIGl0IGlzIG9wZW4uXG4gIFx0Y2xvc2VUb29sdGlwOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRpZiAodGhpcy5fdG9vbHRpcCkge1xuICBcdFx0XHRyZXR1cm4gdGhpcy5fdG9vbHRpcC5jbG9zZSgpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIHRvZ2dsZVRvb2x0aXAoKTogdGhpc1xuICBcdC8vIE9wZW5zIG9yIGNsb3NlcyB0aGUgdG9vbHRpcCBib3VuZCB0byB0aGlzIGxheWVyIGRlcGVuZGluZyBvbiBpdHMgY3VycmVudCBzdGF0ZS5cbiAgXHR0b2dnbGVUb29sdGlwOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRpZiAodGhpcy5fdG9vbHRpcCkge1xuICBcdFx0XHR0aGlzLl90b29sdGlwLnRvZ2dsZSh0aGlzKTtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiB0aGlzO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIGlzVG9vbHRpcE9wZW4oKTogYm9vbGVhblxuICBcdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSB0b29sdGlwIGJvdW5kIHRvIHRoaXMgbGF5ZXIgaXMgY3VycmVudGx5IG9wZW4uXG4gIFx0aXNUb29sdGlwT3BlbjogZnVuY3Rpb24gKCkge1xuICBcdFx0cmV0dXJuIHRoaXMuX3Rvb2x0aXAuaXNPcGVuKCk7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2Qgc2V0VG9vbHRpcENvbnRlbnQoY29udGVudDogU3RyaW5nfEhUTUxFbGVtZW50fFRvb2x0aXApOiB0aGlzXG4gIFx0Ly8gU2V0cyB0aGUgY29udGVudCBvZiB0aGUgdG9vbHRpcCBib3VuZCB0byB0aGlzIGxheWVyLlxuICBcdHNldFRvb2x0aXBDb250ZW50OiBmdW5jdGlvbiAoY29udGVudCkge1xuICBcdFx0aWYgKHRoaXMuX3Rvb2x0aXApIHtcbiAgXHRcdFx0dGhpcy5fdG9vbHRpcC5zZXRDb250ZW50KGNvbnRlbnQpO1xuICBcdFx0fVxuICBcdFx0cmV0dXJuIHRoaXM7XG4gIFx0fSxcblxuICBcdC8vIEBtZXRob2QgZ2V0VG9vbHRpcCgpOiBUb29sdGlwXG4gIFx0Ly8gUmV0dXJucyB0aGUgdG9vbHRpcCBib3VuZCB0byB0aGlzIGxheWVyLlxuICBcdGdldFRvb2x0aXA6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHJldHVybiB0aGlzLl90b29sdGlwO1xuICBcdH0sXG5cbiAgXHRfYWRkRm9jdXNMaXN0ZW5lcnM6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICh0aGlzLmdldEVsZW1lbnQpIHtcbiAgXHRcdFx0dGhpcy5fYWRkRm9jdXNMaXN0ZW5lcnNPbkxheWVyKHRoaXMpO1xuICBcdFx0fSBlbHNlIGlmICh0aGlzLmVhY2hMYXllcikge1xuICBcdFx0XHR0aGlzLmVhY2hMYXllcih0aGlzLl9hZGRGb2N1c0xpc3RlbmVyc09uTGF5ZXIsIHRoaXMpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfYWRkRm9jdXNMaXN0ZW5lcnNPbkxheWVyOiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdHZhciBlbCA9IHR5cGVvZiBsYXllci5nZXRFbGVtZW50ID09PSAnZnVuY3Rpb24nICYmIGxheWVyLmdldEVsZW1lbnQoKTtcbiAgXHRcdGlmIChlbCkge1xuICBcdFx0XHRvbihlbCwgJ2ZvY3VzJywgZnVuY3Rpb24gKCkge1xuICBcdFx0XHRcdHRoaXMuX3Rvb2x0aXAuX3NvdXJjZSA9IGxheWVyO1xuICBcdFx0XHRcdHRoaXMub3BlblRvb2x0aXAoKTtcbiAgXHRcdFx0fSwgdGhpcyk7XG4gIFx0XHRcdG9uKGVsLCAnYmx1cicsIHRoaXMuY2xvc2VUb29sdGlwLCB0aGlzKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3NldEFyaWFEZXNjcmliZWRCeU9uTGF5ZXI6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0dmFyIGVsID0gdHlwZW9mIGxheWVyLmdldEVsZW1lbnQgPT09ICdmdW5jdGlvbicgJiYgbGF5ZXIuZ2V0RWxlbWVudCgpO1xuICBcdFx0aWYgKGVsKSB7XG4gIFx0XHRcdGVsLnNldEF0dHJpYnV0ZSgnYXJpYS1kZXNjcmliZWRieScsIHRoaXMuX3Rvb2x0aXAuX2NvbnRhaW5lci5pZCk7XG4gIFx0XHR9XG4gIFx0fSxcblxuXG4gIFx0X29wZW5Ub29sdGlwOiBmdW5jdGlvbiAoZSkge1xuICBcdFx0aWYgKCF0aGlzLl90b29sdGlwIHx8ICF0aGlzLl9tYXApIHtcbiAgXHRcdFx0cmV0dXJuO1xuICBcdFx0fVxuXG4gIFx0XHQvLyBJZiB0aGUgbWFwIGlzIG1vdmluZywgd2Ugd2lsbCBzaG93IHRoZSB0b29sdGlwIGFmdGVyIGl0J3MgZG9uZS5cbiAgXHRcdGlmICh0aGlzLl9tYXAuZHJhZ2dpbmcgJiYgdGhpcy5fbWFwLmRyYWdnaW5nLm1vdmluZygpICYmICF0aGlzLl9vcGVuT25jZUZsYWcpIHtcbiAgXHRcdFx0dGhpcy5fb3Blbk9uY2VGbGFnID0gdHJ1ZTtcbiAgXHRcdFx0dmFyIHRoYXQgPSB0aGlzO1xuICBcdFx0XHR0aGlzLl9tYXAub25jZSgnbW92ZWVuZCcsIGZ1bmN0aW9uICgpIHtcbiAgXHRcdFx0XHR0aGF0Ll9vcGVuT25jZUZsYWcgPSBmYWxzZTtcbiAgXHRcdFx0XHR0aGF0Ll9vcGVuVG9vbHRpcChlKTtcbiAgXHRcdFx0fSk7XG4gIFx0XHRcdHJldHVybjtcbiAgXHRcdH1cblxuICBcdFx0dGhpcy5fdG9vbHRpcC5fc291cmNlID0gZS5sYXllciB8fCBlLnRhcmdldDtcblxuICBcdFx0dGhpcy5vcGVuVG9vbHRpcCh0aGlzLl90b29sdGlwLm9wdGlvbnMuc3RpY2t5ID8gZS5sYXRsbmcgOiB1bmRlZmluZWQpO1xuICBcdH0sXG5cbiAgXHRfbW92ZVRvb2x0aXA6IGZ1bmN0aW9uIChlKSB7XG4gIFx0XHR2YXIgbGF0bG5nID0gZS5sYXRsbmcsIGNvbnRhaW5lclBvaW50LCBsYXllclBvaW50O1xuICBcdFx0aWYgKHRoaXMuX3Rvb2x0aXAub3B0aW9ucy5zdGlja3kgJiYgZS5vcmlnaW5hbEV2ZW50KSB7XG4gIFx0XHRcdGNvbnRhaW5lclBvaW50ID0gdGhpcy5fbWFwLm1vdXNlRXZlbnRUb0NvbnRhaW5lclBvaW50KGUub3JpZ2luYWxFdmVudCk7XG4gIFx0XHRcdGxheWVyUG9pbnQgPSB0aGlzLl9tYXAuY29udGFpbmVyUG9pbnRUb0xheWVyUG9pbnQoY29udGFpbmVyUG9pbnQpO1xuICBcdFx0XHRsYXRsbmcgPSB0aGlzLl9tYXAubGF5ZXJQb2ludFRvTGF0TG5nKGxheWVyUG9pbnQpO1xuICBcdFx0fVxuICBcdFx0dGhpcy5fdG9vbHRpcC5zZXRMYXRMbmcobGF0bG5nKTtcbiAgXHR9XG4gIH0pO1xuXG4gIC8qXG4gICAqIEBjbGFzcyBEaXZJY29uXG4gICAqIEBha2EgTC5EaXZJY29uXG4gICAqIEBpbmhlcml0cyBJY29uXG4gICAqXG4gICAqIFJlcHJlc2VudHMgYSBsaWdodHdlaWdodCBpY29uIGZvciBtYXJrZXJzIHRoYXQgdXNlcyBhIHNpbXBsZSBgPGRpdj5gXG4gICAqIGVsZW1lbnQgaW5zdGVhZCBvZiBhbiBpbWFnZS4gSW5oZXJpdHMgZnJvbSBgSWNvbmAgYnV0IGlnbm9yZXMgdGhlIGBpY29uVXJsYCBhbmQgc2hhZG93IG9wdGlvbnMuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYGpzXG4gICAqIHZhciBteUljb24gPSBMLmRpdkljb24oe2NsYXNzTmFtZTogJ215LWRpdi1pY29uJ30pO1xuICAgKiAvLyB5b3UgY2FuIHNldCAubXktZGl2LWljb24gc3R5bGVzIGluIENTU1xuICAgKlxuICAgKiBMLm1hcmtlcihbNTAuNTA1LCAzMC41N10sIHtpY29uOiBteUljb259KS5hZGRUbyhtYXApO1xuICAgKiBgYGBcbiAgICpcbiAgICogQnkgZGVmYXVsdCwgaXQgaGFzIGEgJ2xlYWZsZXQtZGl2LWljb24nIENTUyBjbGFzcyBhbmQgaXMgc3R5bGVkIGFzIGEgbGl0dGxlIHdoaXRlIHNxdWFyZSB3aXRoIGEgc2hhZG93LlxuICAgKi9cblxuICB2YXIgRGl2SWNvbiA9IEljb24uZXh0ZW5kKHtcbiAgXHRvcHRpb25zOiB7XG4gIFx0XHQvLyBAc2VjdGlvblxuICBcdFx0Ly8gQGFrYSBEaXZJY29uIG9wdGlvbnNcbiAgXHRcdGljb25TaXplOiBbMTIsIDEyXSwgLy8gYWxzbyBjYW4gYmUgc2V0IHRocm91Z2ggQ1NTXG5cbiAgXHRcdC8vIGljb25BbmNob3I6IChQb2ludCksXG4gIFx0XHQvLyBwb3B1cEFuY2hvcjogKFBvaW50KSxcblxuICBcdFx0Ly8gQG9wdGlvbiBodG1sOiBTdHJpbmd8SFRNTEVsZW1lbnQgPSAnJ1xuICBcdFx0Ly8gQ3VzdG9tIEhUTUwgY29kZSB0byBwdXQgaW5zaWRlIHRoZSBkaXYgZWxlbWVudCwgZW1wdHkgYnkgZGVmYXVsdC4gQWx0ZXJuYXRpdmVseSxcbiAgXHRcdC8vIGFuIGluc3RhbmNlIG9mIGBIVE1MRWxlbWVudGAuXG4gIFx0XHRodG1sOiBmYWxzZSxcblxuICBcdFx0Ly8gQG9wdGlvbiBiZ1BvczogUG9pbnQgPSBbMCwgMF1cbiAgXHRcdC8vIE9wdGlvbmFsIHJlbGF0aXZlIHBvc2l0aW9uIG9mIHRoZSBiYWNrZ3JvdW5kLCBpbiBwaXhlbHNcbiAgXHRcdGJnUG9zOiBudWxsLFxuXG4gIFx0XHRjbGFzc05hbWU6ICdsZWFmbGV0LWRpdi1pY29uJ1xuICBcdH0sXG5cbiAgXHRjcmVhdGVJY29uOiBmdW5jdGlvbiAob2xkSWNvbikge1xuICBcdFx0dmFyIGRpdiA9IChvbGRJY29uICYmIG9sZEljb24udGFnTmFtZSA9PT0gJ0RJVicpID8gb2xkSWNvbiA6IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpLFxuICBcdFx0ICAgIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG5cbiAgXHRcdGlmIChvcHRpb25zLmh0bWwgaW5zdGFuY2VvZiBFbGVtZW50KSB7XG4gIFx0XHRcdGVtcHR5KGRpdik7XG4gIFx0XHRcdGRpdi5hcHBlbmRDaGlsZChvcHRpb25zLmh0bWwpO1xuICBcdFx0fSBlbHNlIHtcbiAgXHRcdFx0ZGl2LmlubmVySFRNTCA9IG9wdGlvbnMuaHRtbCAhPT0gZmFsc2UgPyBvcHRpb25zLmh0bWwgOiAnJztcbiAgXHRcdH1cblxuICBcdFx0aWYgKG9wdGlvbnMuYmdQb3MpIHtcbiAgXHRcdFx0dmFyIGJnUG9zID0gdG9Qb2ludChvcHRpb25zLmJnUG9zKTtcbiAgXHRcdFx0ZGl2LnN0eWxlLmJhY2tncm91bmRQb3NpdGlvbiA9ICgtYmdQb3MueCkgKyAncHggJyArICgtYmdQb3MueSkgKyAncHgnO1xuICBcdFx0fVxuICBcdFx0dGhpcy5fc2V0SWNvblN0eWxlcyhkaXYsICdpY29uJyk7XG5cbiAgXHRcdHJldHVybiBkaXY7XG4gIFx0fSxcblxuICBcdGNyZWF0ZVNoYWRvdzogZnVuY3Rpb24gKCkge1xuICBcdFx0cmV0dXJuIG51bGw7XG4gIFx0fVxuICB9KTtcblxuICAvLyBAZmFjdG9yeSBMLmRpdkljb24ob3B0aW9uczogRGl2SWNvbiBvcHRpb25zKVxuICAvLyBDcmVhdGVzIGEgYERpdkljb25gIGluc3RhbmNlIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuXG4gIGZ1bmN0aW9uIGRpdkljb24ob3B0aW9ucykge1xuICBcdHJldHVybiBuZXcgRGl2SWNvbihvcHRpb25zKTtcbiAgfVxuXG4gIEljb24uRGVmYXVsdCA9IEljb25EZWZhdWx0O1xuXG4gIC8qXG4gICAqIEBjbGFzcyBHcmlkTGF5ZXJcbiAgICogQGluaGVyaXRzIExheWVyXG4gICAqIEBha2EgTC5HcmlkTGF5ZXJcbiAgICpcbiAgICogR2VuZXJpYyBjbGFzcyBmb3IgaGFuZGxpbmcgYSB0aWxlZCBncmlkIG9mIEhUTUwgZWxlbWVudHMuIFRoaXMgaXMgdGhlIGJhc2UgY2xhc3MgZm9yIGFsbCB0aWxlIGxheWVycyBhbmQgcmVwbGFjZXMgYFRpbGVMYXllci5DYW52YXNgLlxuICAgKiBHcmlkTGF5ZXIgY2FuIGJlIGV4dGVuZGVkIHRvIGNyZWF0ZSBhIHRpbGVkIGdyaWQgb2YgSFRNTCBlbGVtZW50cyBsaWtlIGA8Y2FudmFzPmAsIGA8aW1nPmAgb3IgYDxkaXY+YC4gR3JpZExheWVyIHdpbGwgaGFuZGxlIGNyZWF0aW5nIGFuZCBhbmltYXRpbmcgdGhlc2UgRE9NIGVsZW1lbnRzIGZvciB5b3UuXG4gICAqXG4gICAqXG4gICAqIEBzZWN0aW9uIFN5bmNocm9ub3VzIHVzYWdlXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqIFRvIGNyZWF0ZSBhIGN1c3RvbSBsYXllciwgZXh0ZW5kIEdyaWRMYXllciBhbmQgaW1wbGVtZW50IHRoZSBgY3JlYXRlVGlsZSgpYCBtZXRob2QsIHdoaWNoIHdpbGwgYmUgcGFzc2VkIGEgYFBvaW50YCBvYmplY3Qgd2l0aCB0aGUgYHhgLCBgeWAsIGFuZCBgemAgKHpvb20gbGV2ZWwpIGNvb3JkaW5hdGVzIHRvIGRyYXcgeW91ciB0aWxlLlxuICAgKlxuICAgKiBgYGBqc1xuICAgKiB2YXIgQ2FudmFzTGF5ZXIgPSBMLkdyaWRMYXllci5leHRlbmQoe1xuICAgKiAgICAgY3JlYXRlVGlsZTogZnVuY3Rpb24oY29vcmRzKXtcbiAgICogICAgICAgICAvLyBjcmVhdGUgYSA8Y2FudmFzPiBlbGVtZW50IGZvciBkcmF3aW5nXG4gICAqICAgICAgICAgdmFyIHRpbGUgPSBMLkRvbVV0aWwuY3JlYXRlKCdjYW52YXMnLCAnbGVhZmxldC10aWxlJyk7XG4gICAqXG4gICAqICAgICAgICAgLy8gc2V0dXAgdGlsZSB3aWR0aCBhbmQgaGVpZ2h0IGFjY29yZGluZyB0byB0aGUgb3B0aW9uc1xuICAgKiAgICAgICAgIHZhciBzaXplID0gdGhpcy5nZXRUaWxlU2l6ZSgpO1xuICAgKiAgICAgICAgIHRpbGUud2lkdGggPSBzaXplLng7XG4gICAqICAgICAgICAgdGlsZS5oZWlnaHQgPSBzaXplLnk7XG4gICAqXG4gICAqICAgICAgICAgLy8gZ2V0IGEgY2FudmFzIGNvbnRleHQgYW5kIGRyYXcgc29tZXRoaW5nIG9uIGl0IHVzaW5nIGNvb3Jkcy54LCBjb29yZHMueSBhbmQgY29vcmRzLnpcbiAgICogICAgICAgICB2YXIgY3R4ID0gdGlsZS5nZXRDb250ZXh0KCcyZCcpO1xuICAgKlxuICAgKiAgICAgICAgIC8vIHJldHVybiB0aGUgdGlsZSBzbyBpdCBjYW4gYmUgcmVuZGVyZWQgb24gc2NyZWVuXG4gICAqICAgICAgICAgcmV0dXJuIHRpbGU7XG4gICAqICAgICB9XG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICpcbiAgICogQHNlY3Rpb24gQXN5bmNocm9ub3VzIHVzYWdlXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqIFRpbGUgY3JlYXRpb24gY2FuIGFsc28gYmUgYXN5bmNocm9ub3VzLCB0aGlzIGlzIHVzZWZ1bCB3aGVuIHVzaW5nIGEgdGhpcmQtcGFydHkgZHJhd2luZyBsaWJyYXJ5LiBPbmNlIHRoZSB0aWxlIGlzIGZpbmlzaGVkIGRyYXdpbmcgaXQgY2FuIGJlIHBhc3NlZCB0byB0aGUgYGRvbmUoKWAgY2FsbGJhY2suXG4gICAqXG4gICAqIGBgYGpzXG4gICAqIHZhciBDYW52YXNMYXllciA9IEwuR3JpZExheWVyLmV4dGVuZCh7XG4gICAqICAgICBjcmVhdGVUaWxlOiBmdW5jdGlvbihjb29yZHMsIGRvbmUpe1xuICAgKiAgICAgICAgIHZhciBlcnJvcjtcbiAgICpcbiAgICogICAgICAgICAvLyBjcmVhdGUgYSA8Y2FudmFzPiBlbGVtZW50IGZvciBkcmF3aW5nXG4gICAqICAgICAgICAgdmFyIHRpbGUgPSBMLkRvbVV0aWwuY3JlYXRlKCdjYW52YXMnLCAnbGVhZmxldC10aWxlJyk7XG4gICAqXG4gICAqICAgICAgICAgLy8gc2V0dXAgdGlsZSB3aWR0aCBhbmQgaGVpZ2h0IGFjY29yZGluZyB0byB0aGUgb3B0aW9uc1xuICAgKiAgICAgICAgIHZhciBzaXplID0gdGhpcy5nZXRUaWxlU2l6ZSgpO1xuICAgKiAgICAgICAgIHRpbGUud2lkdGggPSBzaXplLng7XG4gICAqICAgICAgICAgdGlsZS5oZWlnaHQgPSBzaXplLnk7XG4gICAqXG4gICAqICAgICAgICAgLy8gZHJhdyBzb21ldGhpbmcgYXN5bmNocm9ub3VzbHkgYW5kIHBhc3MgdGhlIHRpbGUgdG8gdGhlIGRvbmUoKSBjYWxsYmFja1xuICAgKiAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAqICAgICAgICAgICAgIGRvbmUoZXJyb3IsIHRpbGUpO1xuICAgKiAgICAgICAgIH0sIDEwMDApO1xuICAgKlxuICAgKiAgICAgICAgIHJldHVybiB0aWxlO1xuICAgKiAgICAgfVxuICAgKiB9KTtcbiAgICogYGBgXG4gICAqXG4gICAqIEBzZWN0aW9uXG4gICAqL1xuXG5cbiAgdmFyIEdyaWRMYXllciA9IExheWVyLmV4dGVuZCh7XG5cbiAgXHQvLyBAc2VjdGlvblxuICBcdC8vIEBha2EgR3JpZExheWVyIG9wdGlvbnNcbiAgXHRvcHRpb25zOiB7XG4gIFx0XHQvLyBAb3B0aW9uIHRpbGVTaXplOiBOdW1iZXJ8UG9pbnQgPSAyNTZcbiAgXHRcdC8vIFdpZHRoIGFuZCBoZWlnaHQgb2YgdGlsZXMgaW4gdGhlIGdyaWQuIFVzZSBhIG51bWJlciBpZiB3aWR0aCBhbmQgaGVpZ2h0IGFyZSBlcXVhbCwgb3IgYEwucG9pbnQod2lkdGgsIGhlaWdodClgIG90aGVyd2lzZS5cbiAgXHRcdHRpbGVTaXplOiAyNTYsXG5cbiAgXHRcdC8vIEBvcHRpb24gb3BhY2l0eTogTnVtYmVyID0gMS4wXG4gIFx0XHQvLyBPcGFjaXR5IG9mIHRoZSB0aWxlcy4gQ2FuIGJlIHVzZWQgaW4gdGhlIGBjcmVhdGVUaWxlKClgIGZ1bmN0aW9uLlxuICBcdFx0b3BhY2l0eTogMSxcblxuICBcdFx0Ly8gQG9wdGlvbiB1cGRhdGVXaGVuSWRsZTogQm9vbGVhbiA9IChkZXBlbmRzKVxuICBcdFx0Ly8gTG9hZCBuZXcgdGlsZXMgb25seSB3aGVuIHBhbm5pbmcgZW5kcy5cbiAgXHRcdC8vIGB0cnVlYCBieSBkZWZhdWx0IG9uIG1vYmlsZSBicm93c2VycywgaW4gb3JkZXIgdG8gYXZvaWQgdG9vIG1hbnkgcmVxdWVzdHMgYW5kIGtlZXAgc21vb3RoIG5hdmlnYXRpb24uXG4gIFx0XHQvLyBgZmFsc2VgIG90aGVyd2lzZSBpbiBvcmRlciB0byBkaXNwbGF5IG5ldyB0aWxlcyBfZHVyaW5nXyBwYW5uaW5nLCBzaW5jZSBpdCBpcyBlYXN5IHRvIHBhbiBvdXRzaWRlIHRoZVxuICBcdFx0Ly8gW2BrZWVwQnVmZmVyYF0oI2dyaWRsYXllci1rZWVwYnVmZmVyKSBvcHRpb24gaW4gZGVza3RvcCBicm93c2Vycy5cbiAgXHRcdHVwZGF0ZVdoZW5JZGxlOiBCcm93c2VyLm1vYmlsZSxcblxuICBcdFx0Ly8gQG9wdGlvbiB1cGRhdGVXaGVuWm9vbWluZzogQm9vbGVhbiA9IHRydWVcbiAgXHRcdC8vIEJ5IGRlZmF1bHQsIGEgc21vb3RoIHpvb20gYW5pbWF0aW9uIChkdXJpbmcgYSBbdG91Y2ggem9vbV0oI21hcC10b3VjaHpvb20pIG9yIGEgW2BmbHlUbygpYF0oI21hcC1mbHl0bykpIHdpbGwgdXBkYXRlIGdyaWQgbGF5ZXJzIGV2ZXJ5IGludGVnZXIgem9vbSBsZXZlbC4gU2V0dGluZyB0aGlzIG9wdGlvbiB0byBgZmFsc2VgIHdpbGwgdXBkYXRlIHRoZSBncmlkIGxheWVyIG9ubHkgd2hlbiB0aGUgc21vb3RoIGFuaW1hdGlvbiBlbmRzLlxuICBcdFx0dXBkYXRlV2hlblpvb21pbmc6IHRydWUsXG5cbiAgXHRcdC8vIEBvcHRpb24gdXBkYXRlSW50ZXJ2YWw6IE51bWJlciA9IDIwMFxuICBcdFx0Ly8gVGlsZXMgd2lsbCBub3QgdXBkYXRlIG1vcmUgdGhhbiBvbmNlIGV2ZXJ5IGB1cGRhdGVJbnRlcnZhbGAgbWlsbGlzZWNvbmRzIHdoZW4gcGFubmluZy5cbiAgXHRcdHVwZGF0ZUludGVydmFsOiAyMDAsXG5cbiAgXHRcdC8vIEBvcHRpb24gekluZGV4OiBOdW1iZXIgPSAxXG4gIFx0XHQvLyBUaGUgZXhwbGljaXQgekluZGV4IG9mIHRoZSB0aWxlIGxheWVyLlxuICBcdFx0ekluZGV4OiAxLFxuXG4gIFx0XHQvLyBAb3B0aW9uIGJvdW5kczogTGF0TG5nQm91bmRzID0gdW5kZWZpbmVkXG4gIFx0XHQvLyBJZiBzZXQsIHRpbGVzIHdpbGwgb25seSBiZSBsb2FkZWQgaW5zaWRlIHRoZSBzZXQgYExhdExuZ0JvdW5kc2AuXG4gIFx0XHRib3VuZHM6IG51bGwsXG5cbiAgXHRcdC8vIEBvcHRpb24gbWluWm9vbTogTnVtYmVyID0gMFxuICBcdFx0Ly8gVGhlIG1pbmltdW0gem9vbSBsZXZlbCBkb3duIHRvIHdoaWNoIHRoaXMgbGF5ZXIgd2lsbCBiZSBkaXNwbGF5ZWQgKGluY2x1c2l2ZSkuXG4gIFx0XHRtaW5ab29tOiAwLFxuXG4gIFx0XHQvLyBAb3B0aW9uIG1heFpvb206IE51bWJlciA9IHVuZGVmaW5lZFxuICBcdFx0Ly8gVGhlIG1heGltdW0gem9vbSBsZXZlbCB1cCB0byB3aGljaCB0aGlzIGxheWVyIHdpbGwgYmUgZGlzcGxheWVkIChpbmNsdXNpdmUpLlxuICBcdFx0bWF4Wm9vbTogdW5kZWZpbmVkLFxuXG4gIFx0XHQvLyBAb3B0aW9uIG1heE5hdGl2ZVpvb206IE51bWJlciA9IHVuZGVmaW5lZFxuICBcdFx0Ly8gTWF4aW11bSB6b29tIG51bWJlciB0aGUgdGlsZSBzb3VyY2UgaGFzIGF2YWlsYWJsZS4gSWYgaXQgaXMgc3BlY2lmaWVkLFxuICBcdFx0Ly8gdGhlIHRpbGVzIG9uIGFsbCB6b29tIGxldmVscyBoaWdoZXIgdGhhbiBgbWF4TmF0aXZlWm9vbWAgd2lsbCBiZSBsb2FkZWRcbiAgXHRcdC8vIGZyb20gYG1heE5hdGl2ZVpvb21gIGxldmVsIGFuZCBhdXRvLXNjYWxlZC5cbiAgXHRcdG1heE5hdGl2ZVpvb206IHVuZGVmaW5lZCxcblxuICBcdFx0Ly8gQG9wdGlvbiBtaW5OYXRpdmVab29tOiBOdW1iZXIgPSB1bmRlZmluZWRcbiAgXHRcdC8vIE1pbmltdW0gem9vbSBudW1iZXIgdGhlIHRpbGUgc291cmNlIGhhcyBhdmFpbGFibGUuIElmIGl0IGlzIHNwZWNpZmllZCxcbiAgXHRcdC8vIHRoZSB0aWxlcyBvbiBhbGwgem9vbSBsZXZlbHMgbG93ZXIgdGhhbiBgbWluTmF0aXZlWm9vbWAgd2lsbCBiZSBsb2FkZWRcbiAgXHRcdC8vIGZyb20gYG1pbk5hdGl2ZVpvb21gIGxldmVsIGFuZCBhdXRvLXNjYWxlZC5cbiAgXHRcdG1pbk5hdGl2ZVpvb206IHVuZGVmaW5lZCxcblxuICBcdFx0Ly8gQG9wdGlvbiBub1dyYXA6IEJvb2xlYW4gPSBmYWxzZVxuICBcdFx0Ly8gV2hldGhlciB0aGUgbGF5ZXIgaXMgd3JhcHBlZCBhcm91bmQgdGhlIGFudGltZXJpZGlhbi4gSWYgYHRydWVgLCB0aGVcbiAgXHRcdC8vIEdyaWRMYXllciB3aWxsIG9ubHkgYmUgZGlzcGxheWVkIG9uY2UgYXQgbG93IHpvb20gbGV2ZWxzLiBIYXMgbm9cbiAgXHRcdC8vIGVmZmVjdCB3aGVuIHRoZSBbbWFwIENSU10oI21hcC1jcnMpIGRvZXNuJ3Qgd3JhcCBhcm91bmQuIENhbiBiZSB1c2VkXG4gIFx0XHQvLyBpbiBjb21iaW5hdGlvbiB3aXRoIFtgYm91bmRzYF0oI2dyaWRsYXllci1ib3VuZHMpIHRvIHByZXZlbnQgcmVxdWVzdGluZ1xuICBcdFx0Ly8gdGlsZXMgb3V0c2lkZSB0aGUgQ1JTIGxpbWl0cy5cbiAgXHRcdG5vV3JhcDogZmFsc2UsXG5cbiAgXHRcdC8vIEBvcHRpb24gcGFuZTogU3RyaW5nID0gJ3RpbGVQYW5lJ1xuICBcdFx0Ly8gYE1hcCBwYW5lYCB3aGVyZSB0aGUgZ3JpZCBsYXllciB3aWxsIGJlIGFkZGVkLlxuICBcdFx0cGFuZTogJ3RpbGVQYW5lJyxcblxuICBcdFx0Ly8gQG9wdGlvbiBjbGFzc05hbWU6IFN0cmluZyA9ICcnXG4gIFx0XHQvLyBBIGN1c3RvbSBjbGFzcyBuYW1lIHRvIGFzc2lnbiB0byB0aGUgdGlsZSBsYXllci4gRW1wdHkgYnkgZGVmYXVsdC5cbiAgXHRcdGNsYXNzTmFtZTogJycsXG5cbiAgXHRcdC8vIEBvcHRpb24ga2VlcEJ1ZmZlcjogTnVtYmVyID0gMlxuICBcdFx0Ly8gV2hlbiBwYW5uaW5nIHRoZSBtYXAsIGtlZXAgdGhpcyBtYW55IHJvd3MgYW5kIGNvbHVtbnMgb2YgdGlsZXMgYmVmb3JlIHVubG9hZGluZyB0aGVtLlxuICBcdFx0a2VlcEJ1ZmZlcjogMlxuICBcdH0sXG5cbiAgXHRpbml0aWFsaXplOiBmdW5jdGlvbiAob3B0aW9ucykge1xuICBcdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcbiAgXHR9LFxuXG4gIFx0b25BZGQ6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHRoaXMuX2luaXRDb250YWluZXIoKTtcblxuICBcdFx0dGhpcy5fbGV2ZWxzID0ge307XG4gIFx0XHR0aGlzLl90aWxlcyA9IHt9O1xuXG4gIFx0XHR0aGlzLl9yZXNldFZpZXcoKTsgLy8gaW1wbGljaXQgX3VwZGF0ZSgpIGNhbGxcbiAgXHR9LFxuXG4gIFx0YmVmb3JlQWRkOiBmdW5jdGlvbiAobWFwKSB7XG4gIFx0XHRtYXAuX2FkZFpvb21MaW1pdCh0aGlzKTtcbiAgXHR9LFxuXG4gIFx0b25SZW1vdmU6IGZ1bmN0aW9uIChtYXApIHtcbiAgXHRcdHRoaXMuX3JlbW92ZUFsbFRpbGVzKCk7XG4gIFx0XHRyZW1vdmUodGhpcy5fY29udGFpbmVyKTtcbiAgXHRcdG1hcC5fcmVtb3ZlWm9vbUxpbWl0KHRoaXMpO1xuICBcdFx0dGhpcy5fY29udGFpbmVyID0gbnVsbDtcbiAgXHRcdHRoaXMuX3RpbGVab29tID0gdW5kZWZpbmVkO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIGJyaW5nVG9Gcm9udDogdGhpc1xuICBcdC8vIEJyaW5ncyB0aGUgdGlsZSBsYXllciB0byB0aGUgdG9wIG9mIGFsbCB0aWxlIGxheWVycy5cbiAgXHRicmluZ1RvRnJvbnQ6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICh0aGlzLl9tYXApIHtcbiAgXHRcdFx0dG9Gcm9udCh0aGlzLl9jb250YWluZXIpO1xuICBcdFx0XHR0aGlzLl9zZXRBdXRvWkluZGV4KE1hdGgubWF4KTtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiB0aGlzO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIGJyaW5nVG9CYWNrOiB0aGlzXG4gIFx0Ly8gQnJpbmdzIHRoZSB0aWxlIGxheWVyIHRvIHRoZSBib3R0b20gb2YgYWxsIHRpbGUgbGF5ZXJzLlxuICBcdGJyaW5nVG9CYWNrOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRpZiAodGhpcy5fbWFwKSB7XG4gIFx0XHRcdHRvQmFjayh0aGlzLl9jb250YWluZXIpO1xuICBcdFx0XHR0aGlzLl9zZXRBdXRvWkluZGV4KE1hdGgubWluKTtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiB0aGlzO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIGdldENvbnRhaW5lcjogSFRNTEVsZW1lbnRcbiAgXHQvLyBSZXR1cm5zIHRoZSBIVE1MIGVsZW1lbnQgdGhhdCBjb250YWlucyB0aGUgdGlsZXMgZm9yIHRoaXMgbGF5ZXIuXG4gIFx0Z2V0Q29udGFpbmVyOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZXR1cm4gdGhpcy5fY29udGFpbmVyO1xuICBcdH0sXG5cbiAgXHQvLyBAbWV0aG9kIHNldE9wYWNpdHkob3BhY2l0eTogTnVtYmVyKTogdGhpc1xuICBcdC8vIENoYW5nZXMgdGhlIFtvcGFjaXR5XSgjZ3JpZGxheWVyLW9wYWNpdHkpIG9mIHRoZSBncmlkIGxheWVyLlxuICBcdHNldE9wYWNpdHk6IGZ1bmN0aW9uIChvcGFjaXR5KSB7XG4gIFx0XHR0aGlzLm9wdGlvbnMub3BhY2l0eSA9IG9wYWNpdHk7XG4gIFx0XHR0aGlzLl91cGRhdGVPcGFjaXR5KCk7XG4gIFx0XHRyZXR1cm4gdGhpcztcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBzZXRaSW5kZXgoekluZGV4OiBOdW1iZXIpOiB0aGlzXG4gIFx0Ly8gQ2hhbmdlcyB0aGUgW3pJbmRleF0oI2dyaWRsYXllci16aW5kZXgpIG9mIHRoZSBncmlkIGxheWVyLlxuICBcdHNldFpJbmRleDogZnVuY3Rpb24gKHpJbmRleCkge1xuICBcdFx0dGhpcy5vcHRpb25zLnpJbmRleCA9IHpJbmRleDtcbiAgXHRcdHRoaXMuX3VwZGF0ZVpJbmRleCgpO1xuXG4gIFx0XHRyZXR1cm4gdGhpcztcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBpc0xvYWRpbmc6IEJvb2xlYW5cbiAgXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiBhbnkgdGlsZSBpbiB0aGUgZ3JpZCBsYXllciBoYXMgbm90IGZpbmlzaGVkIGxvYWRpbmcuXG4gIFx0aXNMb2FkaW5nOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZXR1cm4gdGhpcy5fbG9hZGluZztcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCByZWRyYXc6IHRoaXNcbiAgXHQvLyBDYXVzZXMgdGhlIGxheWVyIHRvIGNsZWFyIGFsbCB0aGUgdGlsZXMgYW5kIHJlcXVlc3QgdGhlbSBhZ2Fpbi5cbiAgXHRyZWRyYXc6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICh0aGlzLl9tYXApIHtcbiAgXHRcdFx0dGhpcy5fcmVtb3ZlQWxsVGlsZXMoKTtcbiAgXHRcdFx0dmFyIHRpbGVab29tID0gdGhpcy5fY2xhbXBab29tKHRoaXMuX21hcC5nZXRab29tKCkpO1xuICBcdFx0XHRpZiAodGlsZVpvb20gIT09IHRoaXMuX3RpbGVab29tKSB7XG4gIFx0XHRcdFx0dGhpcy5fdGlsZVpvb20gPSB0aWxlWm9vbTtcbiAgXHRcdFx0XHR0aGlzLl91cGRhdGVMZXZlbHMoKTtcbiAgXHRcdFx0fVxuICBcdFx0XHR0aGlzLl91cGRhdGUoKTtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiB0aGlzO1xuICBcdH0sXG5cbiAgXHRnZXRFdmVudHM6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHZhciBldmVudHMgPSB7XG4gIFx0XHRcdHZpZXdwcmVyZXNldDogdGhpcy5faW52YWxpZGF0ZUFsbCxcbiAgXHRcdFx0dmlld3Jlc2V0OiB0aGlzLl9yZXNldFZpZXcsXG4gIFx0XHRcdHpvb206IHRoaXMuX3Jlc2V0VmlldyxcbiAgXHRcdFx0bW92ZWVuZDogdGhpcy5fb25Nb3ZlRW5kXG4gIFx0XHR9O1xuXG4gIFx0XHRpZiAoIXRoaXMub3B0aW9ucy51cGRhdGVXaGVuSWRsZSkge1xuICBcdFx0XHQvLyB1cGRhdGUgdGlsZXMgb24gbW92ZSwgYnV0IG5vdCBtb3JlIG9mdGVuIHRoYW4gb25jZSBwZXIgZ2l2ZW4gaW50ZXJ2YWxcbiAgXHRcdFx0aWYgKCF0aGlzLl9vbk1vdmUpIHtcbiAgXHRcdFx0XHR0aGlzLl9vbk1vdmUgPSB0aHJvdHRsZSh0aGlzLl9vbk1vdmVFbmQsIHRoaXMub3B0aW9ucy51cGRhdGVJbnRlcnZhbCwgdGhpcyk7XG4gIFx0XHRcdH1cblxuICBcdFx0XHRldmVudHMubW92ZSA9IHRoaXMuX29uTW92ZTtcbiAgXHRcdH1cblxuICBcdFx0aWYgKHRoaXMuX3pvb21BbmltYXRlZCkge1xuICBcdFx0XHRldmVudHMuem9vbWFuaW0gPSB0aGlzLl9hbmltYXRlWm9vbTtcbiAgXHRcdH1cblxuICBcdFx0cmV0dXJuIGV2ZW50cztcbiAgXHR9LFxuXG4gIFx0Ly8gQHNlY3Rpb24gRXh0ZW5zaW9uIG1ldGhvZHNcbiAgXHQvLyBMYXllcnMgZXh0ZW5kaW5nIGBHcmlkTGF5ZXJgIHNoYWxsIHJlaW1wbGVtZW50IHRoZSBmb2xsb3dpbmcgbWV0aG9kLlxuICBcdC8vIEBtZXRob2QgY3JlYXRlVGlsZShjb29yZHM6IE9iamVjdCwgZG9uZT86IEZ1bmN0aW9uKTogSFRNTEVsZW1lbnRcbiAgXHQvLyBDYWxsZWQgb25seSBpbnRlcm5hbGx5LCBtdXN0IGJlIG92ZXJyaWRkZW4gYnkgY2xhc3NlcyBleHRlbmRpbmcgYEdyaWRMYXllcmAuXG4gIFx0Ly8gUmV0dXJucyB0aGUgYEhUTUxFbGVtZW50YCBjb3JyZXNwb25kaW5nIHRvIHRoZSBnaXZlbiBgY29vcmRzYC4gSWYgdGhlIGBkb25lYCBjYWxsYmFja1xuICBcdC8vIGlzIHNwZWNpZmllZCwgaXQgbXVzdCBiZSBjYWxsZWQgd2hlbiB0aGUgdGlsZSBoYXMgZmluaXNoZWQgbG9hZGluZyBhbmQgZHJhd2luZy5cbiAgXHRjcmVhdGVUaWxlOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gIFx0fSxcblxuICBcdC8vIEBzZWN0aW9uXG4gIFx0Ly8gQG1ldGhvZCBnZXRUaWxlU2l6ZTogUG9pbnRcbiAgXHQvLyBOb3JtYWxpemVzIHRoZSBbdGlsZVNpemUgb3B0aW9uXSgjZ3JpZGxheWVyLXRpbGVzaXplKSBpbnRvIGEgcG9pbnQuIFVzZWQgYnkgdGhlIGBjcmVhdGVUaWxlKClgIG1ldGhvZC5cbiAgXHRnZXRUaWxlU2l6ZTogZnVuY3Rpb24gKCkge1xuICBcdFx0dmFyIHMgPSB0aGlzLm9wdGlvbnMudGlsZVNpemU7XG4gIFx0XHRyZXR1cm4gcyBpbnN0YW5jZW9mIFBvaW50ID8gcyA6IG5ldyBQb2ludChzLCBzKTtcbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZVpJbmRleDogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKHRoaXMuX2NvbnRhaW5lciAmJiB0aGlzLm9wdGlvbnMuekluZGV4ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5vcHRpb25zLnpJbmRleCAhPT0gbnVsbCkge1xuICBcdFx0XHR0aGlzLl9jb250YWluZXIuc3R5bGUuekluZGV4ID0gdGhpcy5vcHRpb25zLnpJbmRleDtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3NldEF1dG9aSW5kZXg6IGZ1bmN0aW9uIChjb21wYXJlKSB7XG4gIFx0XHQvLyBnbyB0aHJvdWdoIGFsbCBvdGhlciBsYXllcnMgb2YgdGhlIHNhbWUgcGFuZSwgc2V0IHpJbmRleCB0byBtYXggKyAxIChmcm9udCkgb3IgbWluIC0gMSAoYmFjaylcblxuICBcdFx0dmFyIGxheWVycyA9IHRoaXMuZ2V0UGFuZSgpLmNoaWxkcmVuLFxuICBcdFx0ICAgIGVkZ2VaSW5kZXggPSAtY29tcGFyZSgtSW5maW5pdHksIEluZmluaXR5KTsgLy8gLUluZmluaXR5IGZvciBtYXgsIEluZmluaXR5IGZvciBtaW5cblxuICBcdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IGxheWVycy5sZW5ndGgsIHpJbmRleDsgaSA8IGxlbjsgaSsrKSB7XG5cbiAgXHRcdFx0ekluZGV4ID0gbGF5ZXJzW2ldLnN0eWxlLnpJbmRleDtcblxuICBcdFx0XHRpZiAobGF5ZXJzW2ldICE9PSB0aGlzLl9jb250YWluZXIgJiYgekluZGV4KSB7XG4gIFx0XHRcdFx0ZWRnZVpJbmRleCA9IGNvbXBhcmUoZWRnZVpJbmRleCwgK3pJbmRleCk7XG4gIFx0XHRcdH1cbiAgXHRcdH1cblxuICBcdFx0aWYgKGlzRmluaXRlKGVkZ2VaSW5kZXgpKSB7XG4gIFx0XHRcdHRoaXMub3B0aW9ucy56SW5kZXggPSBlZGdlWkluZGV4ICsgY29tcGFyZSgtMSwgMSk7XG4gIFx0XHRcdHRoaXMuX3VwZGF0ZVpJbmRleCgpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfdXBkYXRlT3BhY2l0eTogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKCF0aGlzLl9tYXApIHsgcmV0dXJuOyB9XG5cbiAgXHRcdC8vIElFIGRvZXNuJ3QgaW5oZXJpdCBmaWx0ZXIgb3BhY2l0eSBwcm9wZXJseSwgc28gd2UncmUgZm9yY2VkIHRvIHNldCBpdCBvbiB0aWxlc1xuICBcdFx0aWYgKEJyb3dzZXIuaWVsdDkpIHsgcmV0dXJuOyB9XG5cbiAgXHRcdHNldE9wYWNpdHkodGhpcy5fY29udGFpbmVyLCB0aGlzLm9wdGlvbnMub3BhY2l0eSk7XG5cbiAgXHRcdHZhciBub3cgPSArbmV3IERhdGUoKSxcbiAgXHRcdCAgICBuZXh0RnJhbWUgPSBmYWxzZSxcbiAgXHRcdCAgICB3aWxsUHJ1bmUgPSBmYWxzZTtcblxuICBcdFx0Zm9yICh2YXIga2V5IGluIHRoaXMuX3RpbGVzKSB7XG4gIFx0XHRcdHZhciB0aWxlID0gdGhpcy5fdGlsZXNba2V5XTtcbiAgXHRcdFx0aWYgKCF0aWxlLmN1cnJlbnQgfHwgIXRpbGUubG9hZGVkKSB7IGNvbnRpbnVlOyB9XG5cbiAgXHRcdFx0dmFyIGZhZGUgPSBNYXRoLm1pbigxLCAobm93IC0gdGlsZS5sb2FkZWQpIC8gMjAwKTtcblxuICBcdFx0XHRzZXRPcGFjaXR5KHRpbGUuZWwsIGZhZGUpO1xuICBcdFx0XHRpZiAoZmFkZSA8IDEpIHtcbiAgXHRcdFx0XHRuZXh0RnJhbWUgPSB0cnVlO1xuICBcdFx0XHR9IGVsc2Uge1xuICBcdFx0XHRcdGlmICh0aWxlLmFjdGl2ZSkge1xuICBcdFx0XHRcdFx0d2lsbFBydW5lID0gdHJ1ZTtcbiAgXHRcdFx0XHR9IGVsc2Uge1xuICBcdFx0XHRcdFx0dGhpcy5fb25PcGFxdWVUaWxlKHRpbGUpO1xuICBcdFx0XHRcdH1cbiAgXHRcdFx0XHR0aWxlLmFjdGl2ZSA9IHRydWU7XG4gIFx0XHRcdH1cbiAgXHRcdH1cblxuICBcdFx0aWYgKHdpbGxQcnVuZSAmJiAhdGhpcy5fbm9QcnVuZSkgeyB0aGlzLl9wcnVuZVRpbGVzKCk7IH1cblxuICBcdFx0aWYgKG5leHRGcmFtZSkge1xuICBcdFx0XHRjYW5jZWxBbmltRnJhbWUodGhpcy5fZmFkZUZyYW1lKTtcbiAgXHRcdFx0dGhpcy5fZmFkZUZyYW1lID0gcmVxdWVzdEFuaW1GcmFtZSh0aGlzLl91cGRhdGVPcGFjaXR5LCB0aGlzKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X29uT3BhcXVlVGlsZTogZmFsc2VGbixcblxuICBcdF9pbml0Q29udGFpbmVyOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRpZiAodGhpcy5fY29udGFpbmVyKSB7IHJldHVybjsgfVxuXG4gIFx0XHR0aGlzLl9jb250YWluZXIgPSBjcmVhdGUkMSgnZGl2JywgJ2xlYWZsZXQtbGF5ZXIgJyArICh0aGlzLm9wdGlvbnMuY2xhc3NOYW1lIHx8ICcnKSk7XG4gIFx0XHR0aGlzLl91cGRhdGVaSW5kZXgoKTtcblxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5vcGFjaXR5IDwgMSkge1xuICBcdFx0XHR0aGlzLl91cGRhdGVPcGFjaXR5KCk7XG4gIFx0XHR9XG5cbiAgXHRcdHRoaXMuZ2V0UGFuZSgpLmFwcGVuZENoaWxkKHRoaXMuX2NvbnRhaW5lcik7XG4gIFx0fSxcblxuICBcdF91cGRhdGVMZXZlbHM6IGZ1bmN0aW9uICgpIHtcblxuICBcdFx0dmFyIHpvb20gPSB0aGlzLl90aWxlWm9vbSxcbiAgXHRcdCAgICBtYXhab29tID0gdGhpcy5vcHRpb25zLm1heFpvb207XG5cbiAgXHRcdGlmICh6b29tID09PSB1bmRlZmluZWQpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfVxuXG4gIFx0XHRmb3IgKHZhciB6IGluIHRoaXMuX2xldmVscykge1xuICBcdFx0XHR6ID0gTnVtYmVyKHopO1xuICBcdFx0XHRpZiAodGhpcy5fbGV2ZWxzW3pdLmVsLmNoaWxkcmVuLmxlbmd0aCB8fCB6ID09PSB6b29tKSB7XG4gIFx0XHRcdFx0dGhpcy5fbGV2ZWxzW3pdLmVsLnN0eWxlLnpJbmRleCA9IG1heFpvb20gLSBNYXRoLmFicyh6b29tIC0geik7XG4gIFx0XHRcdFx0dGhpcy5fb25VcGRhdGVMZXZlbCh6KTtcbiAgXHRcdFx0fSBlbHNlIHtcbiAgXHRcdFx0XHRyZW1vdmUodGhpcy5fbGV2ZWxzW3pdLmVsKTtcbiAgXHRcdFx0XHR0aGlzLl9yZW1vdmVUaWxlc0F0Wm9vbSh6KTtcbiAgXHRcdFx0XHR0aGlzLl9vblJlbW92ZUxldmVsKHopO1xuICBcdFx0XHRcdGRlbGV0ZSB0aGlzLl9sZXZlbHNbel07XG4gIFx0XHRcdH1cbiAgXHRcdH1cblxuICBcdFx0dmFyIGxldmVsID0gdGhpcy5fbGV2ZWxzW3pvb21dLFxuICBcdFx0ICAgIG1hcCA9IHRoaXMuX21hcDtcblxuICBcdFx0aWYgKCFsZXZlbCkge1xuICBcdFx0XHRsZXZlbCA9IHRoaXMuX2xldmVsc1t6b29tXSA9IHt9O1xuXG4gIFx0XHRcdGxldmVsLmVsID0gY3JlYXRlJDEoJ2RpdicsICdsZWFmbGV0LXRpbGUtY29udGFpbmVyIGxlYWZsZXQtem9vbS1hbmltYXRlZCcsIHRoaXMuX2NvbnRhaW5lcik7XG4gIFx0XHRcdGxldmVsLmVsLnN0eWxlLnpJbmRleCA9IG1heFpvb207XG5cbiAgXHRcdFx0bGV2ZWwub3JpZ2luID0gbWFwLnByb2plY3QobWFwLnVucHJvamVjdChtYXAuZ2V0UGl4ZWxPcmlnaW4oKSksIHpvb20pLnJvdW5kKCk7XG4gIFx0XHRcdGxldmVsLnpvb20gPSB6b29tO1xuXG4gIFx0XHRcdHRoaXMuX3NldFpvb21UcmFuc2Zvcm0obGV2ZWwsIG1hcC5nZXRDZW50ZXIoKSwgbWFwLmdldFpvb20oKSk7XG5cbiAgXHRcdFx0Ly8gZm9yY2UgdGhlIGJyb3dzZXIgdG8gY29uc2lkZXIgdGhlIG5ld2x5IGFkZGVkIGVsZW1lbnQgZm9yIHRyYW5zaXRpb25cbiAgXHRcdFx0ZmFsc2VGbihsZXZlbC5lbC5vZmZzZXRXaWR0aCk7XG5cbiAgXHRcdFx0dGhpcy5fb25DcmVhdGVMZXZlbChsZXZlbCk7XG4gIFx0XHR9XG5cbiAgXHRcdHRoaXMuX2xldmVsID0gbGV2ZWw7XG5cbiAgXHRcdHJldHVybiBsZXZlbDtcbiAgXHR9LFxuXG4gIFx0X29uVXBkYXRlTGV2ZWw6IGZhbHNlRm4sXG5cbiAgXHRfb25SZW1vdmVMZXZlbDogZmFsc2VGbixcblxuICBcdF9vbkNyZWF0ZUxldmVsOiBmYWxzZUZuLFxuXG4gIFx0X3BydW5lVGlsZXM6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICghdGhpcy5fbWFwKSB7XG4gIFx0XHRcdHJldHVybjtcbiAgXHRcdH1cblxuICBcdFx0dmFyIGtleSwgdGlsZTtcblxuICBcdFx0dmFyIHpvb20gPSB0aGlzLl9tYXAuZ2V0Wm9vbSgpO1xuICBcdFx0aWYgKHpvb20gPiB0aGlzLm9wdGlvbnMubWF4Wm9vbSB8fFxuICBcdFx0XHR6b29tIDwgdGhpcy5vcHRpb25zLm1pblpvb20pIHtcbiAgXHRcdFx0dGhpcy5fcmVtb3ZlQWxsVGlsZXMoKTtcbiAgXHRcdFx0cmV0dXJuO1xuICBcdFx0fVxuXG4gIFx0XHRmb3IgKGtleSBpbiB0aGlzLl90aWxlcykge1xuICBcdFx0XHR0aWxlID0gdGhpcy5fdGlsZXNba2V5XTtcbiAgXHRcdFx0dGlsZS5yZXRhaW4gPSB0aWxlLmN1cnJlbnQ7XG4gIFx0XHR9XG5cbiAgXHRcdGZvciAoa2V5IGluIHRoaXMuX3RpbGVzKSB7XG4gIFx0XHRcdHRpbGUgPSB0aGlzLl90aWxlc1trZXldO1xuICBcdFx0XHRpZiAodGlsZS5jdXJyZW50ICYmICF0aWxlLmFjdGl2ZSkge1xuICBcdFx0XHRcdHZhciBjb29yZHMgPSB0aWxlLmNvb3JkcztcbiAgXHRcdFx0XHRpZiAoIXRoaXMuX3JldGFpblBhcmVudChjb29yZHMueCwgY29vcmRzLnksIGNvb3Jkcy56LCBjb29yZHMueiAtIDUpKSB7XG4gIFx0XHRcdFx0XHR0aGlzLl9yZXRhaW5DaGlsZHJlbihjb29yZHMueCwgY29vcmRzLnksIGNvb3Jkcy56LCBjb29yZHMueiArIDIpO1xuICBcdFx0XHRcdH1cbiAgXHRcdFx0fVxuICBcdFx0fVxuXG4gIFx0XHRmb3IgKGtleSBpbiB0aGlzLl90aWxlcykge1xuICBcdFx0XHRpZiAoIXRoaXMuX3RpbGVzW2tleV0ucmV0YWluKSB7XG4gIFx0XHRcdFx0dGhpcy5fcmVtb3ZlVGlsZShrZXkpO1xuICBcdFx0XHR9XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF9yZW1vdmVUaWxlc0F0Wm9vbTogZnVuY3Rpb24gKHpvb20pIHtcbiAgXHRcdGZvciAodmFyIGtleSBpbiB0aGlzLl90aWxlcykge1xuICBcdFx0XHRpZiAodGhpcy5fdGlsZXNba2V5XS5jb29yZHMueiAhPT0gem9vbSkge1xuICBcdFx0XHRcdGNvbnRpbnVlO1xuICBcdFx0XHR9XG4gIFx0XHRcdHRoaXMuX3JlbW92ZVRpbGUoa2V5KTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3JlbW92ZUFsbFRpbGVzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRmb3IgKHZhciBrZXkgaW4gdGhpcy5fdGlsZXMpIHtcbiAgXHRcdFx0dGhpcy5fcmVtb3ZlVGlsZShrZXkpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfaW52YWxpZGF0ZUFsbDogZnVuY3Rpb24gKCkge1xuICBcdFx0Zm9yICh2YXIgeiBpbiB0aGlzLl9sZXZlbHMpIHtcbiAgXHRcdFx0cmVtb3ZlKHRoaXMuX2xldmVsc1t6XS5lbCk7XG4gIFx0XHRcdHRoaXMuX29uUmVtb3ZlTGV2ZWwoTnVtYmVyKHopKTtcbiAgXHRcdFx0ZGVsZXRlIHRoaXMuX2xldmVsc1t6XTtcbiAgXHRcdH1cbiAgXHRcdHRoaXMuX3JlbW92ZUFsbFRpbGVzKCk7XG5cbiAgXHRcdHRoaXMuX3RpbGVab29tID0gdW5kZWZpbmVkO1xuICBcdH0sXG5cbiAgXHRfcmV0YWluUGFyZW50OiBmdW5jdGlvbiAoeCwgeSwgeiwgbWluWm9vbSkge1xuICBcdFx0dmFyIHgyID0gTWF0aC5mbG9vcih4IC8gMiksXG4gIFx0XHQgICAgeTIgPSBNYXRoLmZsb29yKHkgLyAyKSxcbiAgXHRcdCAgICB6MiA9IHogLSAxLFxuICBcdFx0ICAgIGNvb3JkczIgPSBuZXcgUG9pbnQoK3gyLCAreTIpO1xuICBcdFx0Y29vcmRzMi56ID0gK3oyO1xuXG4gIFx0XHR2YXIga2V5ID0gdGhpcy5fdGlsZUNvb3Jkc1RvS2V5KGNvb3JkczIpLFxuICBcdFx0ICAgIHRpbGUgPSB0aGlzLl90aWxlc1trZXldO1xuXG4gIFx0XHRpZiAodGlsZSAmJiB0aWxlLmFjdGl2ZSkge1xuICBcdFx0XHR0aWxlLnJldGFpbiA9IHRydWU7XG4gIFx0XHRcdHJldHVybiB0cnVlO1xuXG4gIFx0XHR9IGVsc2UgaWYgKHRpbGUgJiYgdGlsZS5sb2FkZWQpIHtcbiAgXHRcdFx0dGlsZS5yZXRhaW4gPSB0cnVlO1xuICBcdFx0fVxuXG4gIFx0XHRpZiAoejIgPiBtaW5ab29tKSB7XG4gIFx0XHRcdHJldHVybiB0aGlzLl9yZXRhaW5QYXJlbnQoeDIsIHkyLCB6MiwgbWluWm9vbSk7XG4gIFx0XHR9XG5cbiAgXHRcdHJldHVybiBmYWxzZTtcbiAgXHR9LFxuXG4gIFx0X3JldGFpbkNoaWxkcmVuOiBmdW5jdGlvbiAoeCwgeSwgeiwgbWF4Wm9vbSkge1xuXG4gIFx0XHRmb3IgKHZhciBpID0gMiAqIHg7IGkgPCAyICogeCArIDI7IGkrKykge1xuICBcdFx0XHRmb3IgKHZhciBqID0gMiAqIHk7IGogPCAyICogeSArIDI7IGorKykge1xuXG4gIFx0XHRcdFx0dmFyIGNvb3JkcyA9IG5ldyBQb2ludChpLCBqKTtcbiAgXHRcdFx0XHRjb29yZHMueiA9IHogKyAxO1xuXG4gIFx0XHRcdFx0dmFyIGtleSA9IHRoaXMuX3RpbGVDb29yZHNUb0tleShjb29yZHMpLFxuICBcdFx0XHRcdCAgICB0aWxlID0gdGhpcy5fdGlsZXNba2V5XTtcblxuICBcdFx0XHRcdGlmICh0aWxlICYmIHRpbGUuYWN0aXZlKSB7XG4gIFx0XHRcdFx0XHR0aWxlLnJldGFpbiA9IHRydWU7XG4gIFx0XHRcdFx0XHRjb250aW51ZTtcblxuICBcdFx0XHRcdH0gZWxzZSBpZiAodGlsZSAmJiB0aWxlLmxvYWRlZCkge1xuICBcdFx0XHRcdFx0dGlsZS5yZXRhaW4gPSB0cnVlO1xuICBcdFx0XHRcdH1cblxuICBcdFx0XHRcdGlmICh6ICsgMSA8IG1heFpvb20pIHtcbiAgXHRcdFx0XHRcdHRoaXMuX3JldGFpbkNoaWxkcmVuKGksIGosIHogKyAxLCBtYXhab29tKTtcbiAgXHRcdFx0XHR9XG4gIFx0XHRcdH1cbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3Jlc2V0VmlldzogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdHZhciBhbmltYXRpbmcgPSBlICYmIChlLnBpbmNoIHx8IGUuZmx5VG8pO1xuICBcdFx0dGhpcy5fc2V0Vmlldyh0aGlzLl9tYXAuZ2V0Q2VudGVyKCksIHRoaXMuX21hcC5nZXRab29tKCksIGFuaW1hdGluZywgYW5pbWF0aW5nKTtcbiAgXHR9LFxuXG4gIFx0X2FuaW1hdGVab29tOiBmdW5jdGlvbiAoZSkge1xuICBcdFx0dGhpcy5fc2V0VmlldyhlLmNlbnRlciwgZS56b29tLCB0cnVlLCBlLm5vVXBkYXRlKTtcbiAgXHR9LFxuXG4gIFx0X2NsYW1wWm9vbTogZnVuY3Rpb24gKHpvb20pIHtcbiAgXHRcdHZhciBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuXG4gIFx0XHRpZiAodW5kZWZpbmVkICE9PSBvcHRpb25zLm1pbk5hdGl2ZVpvb20gJiYgem9vbSA8IG9wdGlvbnMubWluTmF0aXZlWm9vbSkge1xuICBcdFx0XHRyZXR1cm4gb3B0aW9ucy5taW5OYXRpdmVab29tO1xuICBcdFx0fVxuXG4gIFx0XHRpZiAodW5kZWZpbmVkICE9PSBvcHRpb25zLm1heE5hdGl2ZVpvb20gJiYgb3B0aW9ucy5tYXhOYXRpdmVab29tIDwgem9vbSkge1xuICBcdFx0XHRyZXR1cm4gb3B0aW9ucy5tYXhOYXRpdmVab29tO1xuICBcdFx0fVxuXG4gIFx0XHRyZXR1cm4gem9vbTtcbiAgXHR9LFxuXG4gIFx0X3NldFZpZXc6IGZ1bmN0aW9uIChjZW50ZXIsIHpvb20sIG5vUHJ1bmUsIG5vVXBkYXRlKSB7XG4gIFx0XHR2YXIgdGlsZVpvb20gPSBNYXRoLnJvdW5kKHpvb20pO1xuICBcdFx0aWYgKCh0aGlzLm9wdGlvbnMubWF4Wm9vbSAhPT0gdW5kZWZpbmVkICYmIHRpbGVab29tID4gdGhpcy5vcHRpb25zLm1heFpvb20pIHx8XG4gIFx0XHQgICAgKHRoaXMub3B0aW9ucy5taW5ab29tICE9PSB1bmRlZmluZWQgJiYgdGlsZVpvb20gPCB0aGlzLm9wdGlvbnMubWluWm9vbSkpIHtcbiAgXHRcdFx0dGlsZVpvb20gPSB1bmRlZmluZWQ7XG4gIFx0XHR9IGVsc2Uge1xuICBcdFx0XHR0aWxlWm9vbSA9IHRoaXMuX2NsYW1wWm9vbSh0aWxlWm9vbSk7XG4gIFx0XHR9XG5cbiAgXHRcdHZhciB0aWxlWm9vbUNoYW5nZWQgPSB0aGlzLm9wdGlvbnMudXBkYXRlV2hlblpvb21pbmcgJiYgKHRpbGVab29tICE9PSB0aGlzLl90aWxlWm9vbSk7XG5cbiAgXHRcdGlmICghbm9VcGRhdGUgfHwgdGlsZVpvb21DaGFuZ2VkKSB7XG5cbiAgXHRcdFx0dGhpcy5fdGlsZVpvb20gPSB0aWxlWm9vbTtcblxuICBcdFx0XHRpZiAodGhpcy5fYWJvcnRMb2FkaW5nKSB7XG4gIFx0XHRcdFx0dGhpcy5fYWJvcnRMb2FkaW5nKCk7XG4gIFx0XHRcdH1cblxuICBcdFx0XHR0aGlzLl91cGRhdGVMZXZlbHMoKTtcbiAgXHRcdFx0dGhpcy5fcmVzZXRHcmlkKCk7XG5cbiAgXHRcdFx0aWYgKHRpbGVab29tICE9PSB1bmRlZmluZWQpIHtcbiAgXHRcdFx0XHR0aGlzLl91cGRhdGUoY2VudGVyKTtcbiAgXHRcdFx0fVxuXG4gIFx0XHRcdGlmICghbm9QcnVuZSkge1xuICBcdFx0XHRcdHRoaXMuX3BydW5lVGlsZXMoKTtcbiAgXHRcdFx0fVxuXG4gIFx0XHRcdC8vIEZsYWcgdG8gcHJldmVudCBfdXBkYXRlT3BhY2l0eSBmcm9tIHBydW5pbmcgdGlsZXMgZHVyaW5nXG4gIFx0XHRcdC8vIGEgem9vbSBhbmltIG9yIGEgcGluY2ggZ2VzdHVyZVxuICBcdFx0XHR0aGlzLl9ub1BydW5lID0gISFub1BydW5lO1xuICBcdFx0fVxuXG4gIFx0XHR0aGlzLl9zZXRab29tVHJhbnNmb3JtcyhjZW50ZXIsIHpvb20pO1xuICBcdH0sXG5cbiAgXHRfc2V0Wm9vbVRyYW5zZm9ybXM6IGZ1bmN0aW9uIChjZW50ZXIsIHpvb20pIHtcbiAgXHRcdGZvciAodmFyIGkgaW4gdGhpcy5fbGV2ZWxzKSB7XG4gIFx0XHRcdHRoaXMuX3NldFpvb21UcmFuc2Zvcm0odGhpcy5fbGV2ZWxzW2ldLCBjZW50ZXIsIHpvb20pO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfc2V0Wm9vbVRyYW5zZm9ybTogZnVuY3Rpb24gKGxldmVsLCBjZW50ZXIsIHpvb20pIHtcbiAgXHRcdHZhciBzY2FsZSA9IHRoaXMuX21hcC5nZXRab29tU2NhbGUoem9vbSwgbGV2ZWwuem9vbSksXG4gIFx0XHQgICAgdHJhbnNsYXRlID0gbGV2ZWwub3JpZ2luLm11bHRpcGx5Qnkoc2NhbGUpXG4gIFx0XHQgICAgICAgIC5zdWJ0cmFjdCh0aGlzLl9tYXAuX2dldE5ld1BpeGVsT3JpZ2luKGNlbnRlciwgem9vbSkpLnJvdW5kKCk7XG5cbiAgXHRcdGlmIChCcm93c2VyLmFueTNkKSB7XG4gIFx0XHRcdHNldFRyYW5zZm9ybShsZXZlbC5lbCwgdHJhbnNsYXRlLCBzY2FsZSk7XG4gIFx0XHR9IGVsc2Uge1xuICBcdFx0XHRzZXRQb3NpdGlvbihsZXZlbC5lbCwgdHJhbnNsYXRlKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3Jlc2V0R3JpZDogZnVuY3Rpb24gKCkge1xuICBcdFx0dmFyIG1hcCA9IHRoaXMuX21hcCxcbiAgXHRcdCAgICBjcnMgPSBtYXAub3B0aW9ucy5jcnMsXG4gIFx0XHQgICAgdGlsZVNpemUgPSB0aGlzLl90aWxlU2l6ZSA9IHRoaXMuZ2V0VGlsZVNpemUoKSxcbiAgXHRcdCAgICB0aWxlWm9vbSA9IHRoaXMuX3RpbGVab29tO1xuXG4gIFx0XHR2YXIgYm91bmRzID0gdGhpcy5fbWFwLmdldFBpeGVsV29ybGRCb3VuZHModGhpcy5fdGlsZVpvb20pO1xuICBcdFx0aWYgKGJvdW5kcykge1xuICBcdFx0XHR0aGlzLl9nbG9iYWxUaWxlUmFuZ2UgPSB0aGlzLl9weEJvdW5kc1RvVGlsZVJhbmdlKGJvdW5kcyk7XG4gIFx0XHR9XG5cbiAgXHRcdHRoaXMuX3dyYXBYID0gY3JzLndyYXBMbmcgJiYgIXRoaXMub3B0aW9ucy5ub1dyYXAgJiYgW1xuICBcdFx0XHRNYXRoLmZsb29yKG1hcC5wcm9qZWN0KFswLCBjcnMud3JhcExuZ1swXV0sIHRpbGVab29tKS54IC8gdGlsZVNpemUueCksXG4gIFx0XHRcdE1hdGguY2VpbChtYXAucHJvamVjdChbMCwgY3JzLndyYXBMbmdbMV1dLCB0aWxlWm9vbSkueCAvIHRpbGVTaXplLnkpXG4gIFx0XHRdO1xuICBcdFx0dGhpcy5fd3JhcFkgPSBjcnMud3JhcExhdCAmJiAhdGhpcy5vcHRpb25zLm5vV3JhcCAmJiBbXG4gIFx0XHRcdE1hdGguZmxvb3IobWFwLnByb2plY3QoW2Nycy53cmFwTGF0WzBdLCAwXSwgdGlsZVpvb20pLnkgLyB0aWxlU2l6ZS54KSxcbiAgXHRcdFx0TWF0aC5jZWlsKG1hcC5wcm9qZWN0KFtjcnMud3JhcExhdFsxXSwgMF0sIHRpbGVab29tKS55IC8gdGlsZVNpemUueSlcbiAgXHRcdF07XG4gIFx0fSxcblxuICBcdF9vbk1vdmVFbmQ6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICghdGhpcy5fbWFwIHx8IHRoaXMuX21hcC5fYW5pbWF0aW5nWm9vbSkgeyByZXR1cm47IH1cblxuICBcdFx0dGhpcy5fdXBkYXRlKCk7XG4gIFx0fSxcblxuICBcdF9nZXRUaWxlZFBpeGVsQm91bmRzOiBmdW5jdGlvbiAoY2VudGVyKSB7XG4gIFx0XHR2YXIgbWFwID0gdGhpcy5fbWFwLFxuICBcdFx0ICAgIG1hcFpvb20gPSBtYXAuX2FuaW1hdGluZ1pvb20gPyBNYXRoLm1heChtYXAuX2FuaW1hdGVUb1pvb20sIG1hcC5nZXRab29tKCkpIDogbWFwLmdldFpvb20oKSxcbiAgXHRcdCAgICBzY2FsZSA9IG1hcC5nZXRab29tU2NhbGUobWFwWm9vbSwgdGhpcy5fdGlsZVpvb20pLFxuICBcdFx0ICAgIHBpeGVsQ2VudGVyID0gbWFwLnByb2plY3QoY2VudGVyLCB0aGlzLl90aWxlWm9vbSkuZmxvb3IoKSxcbiAgXHRcdCAgICBoYWxmU2l6ZSA9IG1hcC5nZXRTaXplKCkuZGl2aWRlQnkoc2NhbGUgKiAyKTtcblxuICBcdFx0cmV0dXJuIG5ldyBCb3VuZHMocGl4ZWxDZW50ZXIuc3VidHJhY3QoaGFsZlNpemUpLCBwaXhlbENlbnRlci5hZGQoaGFsZlNpemUpKTtcbiAgXHR9LFxuXG4gIFx0Ly8gUHJpdmF0ZSBtZXRob2QgdG8gbG9hZCB0aWxlcyBpbiB0aGUgZ3JpZCdzIGFjdGl2ZSB6b29tIGxldmVsIGFjY29yZGluZyB0byBtYXAgYm91bmRzXG4gIFx0X3VwZGF0ZTogZnVuY3Rpb24gKGNlbnRlcikge1xuICBcdFx0dmFyIG1hcCA9IHRoaXMuX21hcDtcbiAgXHRcdGlmICghbWFwKSB7IHJldHVybjsgfVxuICBcdFx0dmFyIHpvb20gPSB0aGlzLl9jbGFtcFpvb20obWFwLmdldFpvb20oKSk7XG5cbiAgXHRcdGlmIChjZW50ZXIgPT09IHVuZGVmaW5lZCkgeyBjZW50ZXIgPSBtYXAuZ2V0Q2VudGVyKCk7IH1cbiAgXHRcdGlmICh0aGlzLl90aWxlWm9vbSA9PT0gdW5kZWZpbmVkKSB7IHJldHVybjsgfVx0Ly8gaWYgb3V0IG9mIG1pbnpvb20vbWF4em9vbVxuXG4gIFx0XHR2YXIgcGl4ZWxCb3VuZHMgPSB0aGlzLl9nZXRUaWxlZFBpeGVsQm91bmRzKGNlbnRlciksXG4gIFx0XHQgICAgdGlsZVJhbmdlID0gdGhpcy5fcHhCb3VuZHNUb1RpbGVSYW5nZShwaXhlbEJvdW5kcyksXG4gIFx0XHQgICAgdGlsZUNlbnRlciA9IHRpbGVSYW5nZS5nZXRDZW50ZXIoKSxcbiAgXHRcdCAgICBxdWV1ZSA9IFtdLFxuICBcdFx0ICAgIG1hcmdpbiA9IHRoaXMub3B0aW9ucy5rZWVwQnVmZmVyLFxuICBcdFx0ICAgIG5vUHJ1bmVSYW5nZSA9IG5ldyBCb3VuZHModGlsZVJhbmdlLmdldEJvdHRvbUxlZnQoKS5zdWJ0cmFjdChbbWFyZ2luLCAtbWFyZ2luXSksXG4gIFx0XHQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWxlUmFuZ2UuZ2V0VG9wUmlnaHQoKS5hZGQoW21hcmdpbiwgLW1hcmdpbl0pKTtcblxuICBcdFx0Ly8gU2FuaXR5IGNoZWNrOiBwYW5pYyBpZiB0aGUgdGlsZSByYW5nZSBjb250YWlucyBJbmZpbml0eSBzb21ld2hlcmUuXG4gIFx0XHRpZiAoIShpc0Zpbml0ZSh0aWxlUmFuZ2UubWluLngpICYmXG4gIFx0XHQgICAgICBpc0Zpbml0ZSh0aWxlUmFuZ2UubWluLnkpICYmXG4gIFx0XHQgICAgICBpc0Zpbml0ZSh0aWxlUmFuZ2UubWF4LngpICYmXG4gIFx0XHQgICAgICBpc0Zpbml0ZSh0aWxlUmFuZ2UubWF4LnkpKSkgeyB0aHJvdyBuZXcgRXJyb3IoJ0F0dGVtcHRlZCB0byBsb2FkIGFuIGluZmluaXRlIG51bWJlciBvZiB0aWxlcycpOyB9XG5cbiAgXHRcdGZvciAodmFyIGtleSBpbiB0aGlzLl90aWxlcykge1xuICBcdFx0XHR2YXIgYyA9IHRoaXMuX3RpbGVzW2tleV0uY29vcmRzO1xuICBcdFx0XHRpZiAoYy56ICE9PSB0aGlzLl90aWxlWm9vbSB8fCAhbm9QcnVuZVJhbmdlLmNvbnRhaW5zKG5ldyBQb2ludChjLngsIGMueSkpKSB7XG4gIFx0XHRcdFx0dGhpcy5fdGlsZXNba2V5XS5jdXJyZW50ID0gZmFsc2U7XG4gIFx0XHRcdH1cbiAgXHRcdH1cblxuICBcdFx0Ly8gX3VwZGF0ZSBqdXN0IGxvYWRzIG1vcmUgdGlsZXMuIElmIHRoZSB0aWxlIHpvb20gbGV2ZWwgZGlmZmVycyB0b28gbXVjaFxuICBcdFx0Ly8gZnJvbSB0aGUgbWFwJ3MsIGxldCBfc2V0VmlldyByZXNldCBsZXZlbHMgYW5kIHBydW5lIG9sZCB0aWxlcy5cbiAgXHRcdGlmIChNYXRoLmFicyh6b29tIC0gdGhpcy5fdGlsZVpvb20pID4gMSkgeyB0aGlzLl9zZXRWaWV3KGNlbnRlciwgem9vbSk7IHJldHVybjsgfVxuXG4gIFx0XHQvLyBjcmVhdGUgYSBxdWV1ZSBvZiBjb29yZGluYXRlcyB0byBsb2FkIHRpbGVzIGZyb21cbiAgXHRcdGZvciAodmFyIGogPSB0aWxlUmFuZ2UubWluLnk7IGogPD0gdGlsZVJhbmdlLm1heC55OyBqKyspIHtcbiAgXHRcdFx0Zm9yICh2YXIgaSA9IHRpbGVSYW5nZS5taW4ueDsgaSA8PSB0aWxlUmFuZ2UubWF4Lng7IGkrKykge1xuICBcdFx0XHRcdHZhciBjb29yZHMgPSBuZXcgUG9pbnQoaSwgaik7XG4gIFx0XHRcdFx0Y29vcmRzLnogPSB0aGlzLl90aWxlWm9vbTtcblxuICBcdFx0XHRcdGlmICghdGhpcy5faXNWYWxpZFRpbGUoY29vcmRzKSkgeyBjb250aW51ZTsgfVxuXG4gIFx0XHRcdFx0dmFyIHRpbGUgPSB0aGlzLl90aWxlc1t0aGlzLl90aWxlQ29vcmRzVG9LZXkoY29vcmRzKV07XG4gIFx0XHRcdFx0aWYgKHRpbGUpIHtcbiAgXHRcdFx0XHRcdHRpbGUuY3VycmVudCA9IHRydWU7XG4gIFx0XHRcdFx0fSBlbHNlIHtcbiAgXHRcdFx0XHRcdHF1ZXVlLnB1c2goY29vcmRzKTtcbiAgXHRcdFx0XHR9XG4gIFx0XHRcdH1cbiAgXHRcdH1cblxuICBcdFx0Ly8gc29ydCB0aWxlIHF1ZXVlIHRvIGxvYWQgdGlsZXMgaW4gb3JkZXIgb2YgdGhlaXIgZGlzdGFuY2UgdG8gY2VudGVyXG4gIFx0XHRxdWV1ZS5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gIFx0XHRcdHJldHVybiBhLmRpc3RhbmNlVG8odGlsZUNlbnRlcikgLSBiLmRpc3RhbmNlVG8odGlsZUNlbnRlcik7XG4gIFx0XHR9KTtcblxuICBcdFx0aWYgKHF1ZXVlLmxlbmd0aCAhPT0gMCkge1xuICBcdFx0XHQvLyBpZiBpdCdzIHRoZSBmaXJzdCBiYXRjaCBvZiB0aWxlcyB0byBsb2FkXG4gIFx0XHRcdGlmICghdGhpcy5fbG9hZGluZykge1xuICBcdFx0XHRcdHRoaXMuX2xvYWRpbmcgPSB0cnVlO1xuICBcdFx0XHRcdC8vIEBldmVudCBsb2FkaW5nOiBFdmVudFxuICBcdFx0XHRcdC8vIEZpcmVkIHdoZW4gdGhlIGdyaWQgbGF5ZXIgc3RhcnRzIGxvYWRpbmcgdGlsZXMuXG4gIFx0XHRcdFx0dGhpcy5maXJlKCdsb2FkaW5nJyk7XG4gIFx0XHRcdH1cblxuICBcdFx0XHQvLyBjcmVhdGUgRE9NIGZyYWdtZW50IHRvIGFwcGVuZCB0aWxlcyBpbiBvbmUgYmF0Y2hcbiAgXHRcdFx0dmFyIGZyYWdtZW50ID0gZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpO1xuXG4gIFx0XHRcdGZvciAoaSA9IDA7IGkgPCBxdWV1ZS5sZW5ndGg7IGkrKykge1xuICBcdFx0XHRcdHRoaXMuX2FkZFRpbGUocXVldWVbaV0sIGZyYWdtZW50KTtcbiAgXHRcdFx0fVxuXG4gIFx0XHRcdHRoaXMuX2xldmVsLmVsLmFwcGVuZENoaWxkKGZyYWdtZW50KTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X2lzVmFsaWRUaWxlOiBmdW5jdGlvbiAoY29vcmRzKSB7XG4gIFx0XHR2YXIgY3JzID0gdGhpcy5fbWFwLm9wdGlvbnMuY3JzO1xuXG4gIFx0XHRpZiAoIWNycy5pbmZpbml0ZSkge1xuICBcdFx0XHQvLyBkb24ndCBsb2FkIHRpbGUgaWYgaXQncyBvdXQgb2YgYm91bmRzIGFuZCBub3Qgd3JhcHBlZFxuICBcdFx0XHR2YXIgYm91bmRzID0gdGhpcy5fZ2xvYmFsVGlsZVJhbmdlO1xuICBcdFx0XHRpZiAoKCFjcnMud3JhcExuZyAmJiAoY29vcmRzLnggPCBib3VuZHMubWluLnggfHwgY29vcmRzLnggPiBib3VuZHMubWF4LngpKSB8fFxuICBcdFx0XHQgICAgKCFjcnMud3JhcExhdCAmJiAoY29vcmRzLnkgPCBib3VuZHMubWluLnkgfHwgY29vcmRzLnkgPiBib3VuZHMubWF4LnkpKSkgeyByZXR1cm4gZmFsc2U7IH1cbiAgXHRcdH1cblxuICBcdFx0aWYgKCF0aGlzLm9wdGlvbnMuYm91bmRzKSB7IHJldHVybiB0cnVlOyB9XG5cbiAgXHRcdC8vIGRvbid0IGxvYWQgdGlsZSBpZiBpdCBkb2Vzbid0IGludGVyc2VjdCB0aGUgYm91bmRzIGluIG9wdGlvbnNcbiAgXHRcdHZhciB0aWxlQm91bmRzID0gdGhpcy5fdGlsZUNvb3Jkc1RvQm91bmRzKGNvb3Jkcyk7XG4gIFx0XHRyZXR1cm4gdG9MYXRMbmdCb3VuZHModGhpcy5vcHRpb25zLmJvdW5kcykub3ZlcmxhcHModGlsZUJvdW5kcyk7XG4gIFx0fSxcblxuICBcdF9rZXlUb0JvdW5kczogZnVuY3Rpb24gKGtleSkge1xuICBcdFx0cmV0dXJuIHRoaXMuX3RpbGVDb29yZHNUb0JvdW5kcyh0aGlzLl9rZXlUb1RpbGVDb29yZHMoa2V5KSk7XG4gIFx0fSxcblxuICBcdF90aWxlQ29vcmRzVG9Od1NlOiBmdW5jdGlvbiAoY29vcmRzKSB7XG4gIFx0XHR2YXIgbWFwID0gdGhpcy5fbWFwLFxuICBcdFx0ICAgIHRpbGVTaXplID0gdGhpcy5nZXRUaWxlU2l6ZSgpLFxuICBcdFx0ICAgIG53UG9pbnQgPSBjb29yZHMuc2NhbGVCeSh0aWxlU2l6ZSksXG4gIFx0XHQgICAgc2VQb2ludCA9IG53UG9pbnQuYWRkKHRpbGVTaXplKSxcbiAgXHRcdCAgICBudyA9IG1hcC51bnByb2plY3QobndQb2ludCwgY29vcmRzLnopLFxuICBcdFx0ICAgIHNlID0gbWFwLnVucHJvamVjdChzZVBvaW50LCBjb29yZHMueik7XG4gIFx0XHRyZXR1cm4gW253LCBzZV07XG4gIFx0fSxcblxuICBcdC8vIGNvbnZlcnRzIHRpbGUgY29vcmRpbmF0ZXMgdG8gaXRzIGdlb2dyYXBoaWNhbCBib3VuZHNcbiAgXHRfdGlsZUNvb3Jkc1RvQm91bmRzOiBmdW5jdGlvbiAoY29vcmRzKSB7XG4gIFx0XHR2YXIgYnAgPSB0aGlzLl90aWxlQ29vcmRzVG9Od1NlKGNvb3JkcyksXG4gIFx0XHQgICAgYm91bmRzID0gbmV3IExhdExuZ0JvdW5kcyhicFswXSwgYnBbMV0pO1xuXG4gIFx0XHRpZiAoIXRoaXMub3B0aW9ucy5ub1dyYXApIHtcbiAgXHRcdFx0Ym91bmRzID0gdGhpcy5fbWFwLndyYXBMYXRMbmdCb3VuZHMoYm91bmRzKTtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiBib3VuZHM7XG4gIFx0fSxcbiAgXHQvLyBjb252ZXJ0cyB0aWxlIGNvb3JkaW5hdGVzIHRvIGtleSBmb3IgdGhlIHRpbGUgY2FjaGVcbiAgXHRfdGlsZUNvb3Jkc1RvS2V5OiBmdW5jdGlvbiAoY29vcmRzKSB7XG4gIFx0XHRyZXR1cm4gY29vcmRzLnggKyAnOicgKyBjb29yZHMueSArICc6JyArIGNvb3Jkcy56O1xuICBcdH0sXG5cbiAgXHQvLyBjb252ZXJ0cyB0aWxlIGNhY2hlIGtleSB0byBjb29yZGluYXRlc1xuICBcdF9rZXlUb1RpbGVDb29yZHM6IGZ1bmN0aW9uIChrZXkpIHtcbiAgXHRcdHZhciBrID0ga2V5LnNwbGl0KCc6JyksXG4gIFx0XHQgICAgY29vcmRzID0gbmV3IFBvaW50KCtrWzBdLCAra1sxXSk7XG4gIFx0XHRjb29yZHMueiA9ICtrWzJdO1xuICBcdFx0cmV0dXJuIGNvb3JkcztcbiAgXHR9LFxuXG4gIFx0X3JlbW92ZVRpbGU6IGZ1bmN0aW9uIChrZXkpIHtcbiAgXHRcdHZhciB0aWxlID0gdGhpcy5fdGlsZXNba2V5XTtcbiAgXHRcdGlmICghdGlsZSkgeyByZXR1cm47IH1cblxuICBcdFx0cmVtb3ZlKHRpbGUuZWwpO1xuXG4gIFx0XHRkZWxldGUgdGhpcy5fdGlsZXNba2V5XTtcblxuICBcdFx0Ly8gQGV2ZW50IHRpbGV1bmxvYWQ6IFRpbGVFdmVudFxuICBcdFx0Ly8gRmlyZWQgd2hlbiBhIHRpbGUgaXMgcmVtb3ZlZCAoZS5nLiB3aGVuIGEgdGlsZSBnb2VzIG9mZiB0aGUgc2NyZWVuKS5cbiAgXHRcdHRoaXMuZmlyZSgndGlsZXVubG9hZCcsIHtcbiAgXHRcdFx0dGlsZTogdGlsZS5lbCxcbiAgXHRcdFx0Y29vcmRzOiB0aGlzLl9rZXlUb1RpbGVDb29yZHMoa2V5KVxuICBcdFx0fSk7XG4gIFx0fSxcblxuICBcdF9pbml0VGlsZTogZnVuY3Rpb24gKHRpbGUpIHtcbiAgXHRcdGFkZENsYXNzKHRpbGUsICdsZWFmbGV0LXRpbGUnKTtcblxuICBcdFx0dmFyIHRpbGVTaXplID0gdGhpcy5nZXRUaWxlU2l6ZSgpO1xuICBcdFx0dGlsZS5zdHlsZS53aWR0aCA9IHRpbGVTaXplLnggKyAncHgnO1xuICBcdFx0dGlsZS5zdHlsZS5oZWlnaHQgPSB0aWxlU2l6ZS55ICsgJ3B4JztcblxuICBcdFx0dGlsZS5vbnNlbGVjdHN0YXJ0ID0gZmFsc2VGbjtcbiAgXHRcdHRpbGUub25tb3VzZW1vdmUgPSBmYWxzZUZuO1xuXG4gIFx0XHQvLyB1cGRhdGUgb3BhY2l0eSBvbiB0aWxlcyBpbiBJRTctOCBiZWNhdXNlIG9mIGZpbHRlciBpbmhlcml0YW5jZSBwcm9ibGVtc1xuICBcdFx0aWYgKEJyb3dzZXIuaWVsdDkgJiYgdGhpcy5vcHRpb25zLm9wYWNpdHkgPCAxKSB7XG4gIFx0XHRcdHNldE9wYWNpdHkodGlsZSwgdGhpcy5vcHRpb25zLm9wYWNpdHkpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfYWRkVGlsZTogZnVuY3Rpb24gKGNvb3JkcywgY29udGFpbmVyKSB7XG4gIFx0XHR2YXIgdGlsZVBvcyA9IHRoaXMuX2dldFRpbGVQb3MoY29vcmRzKSxcbiAgXHRcdCAgICBrZXkgPSB0aGlzLl90aWxlQ29vcmRzVG9LZXkoY29vcmRzKTtcblxuICBcdFx0dmFyIHRpbGUgPSB0aGlzLmNyZWF0ZVRpbGUodGhpcy5fd3JhcENvb3Jkcyhjb29yZHMpLCBiaW5kKHRoaXMuX3RpbGVSZWFkeSwgdGhpcywgY29vcmRzKSk7XG5cbiAgXHRcdHRoaXMuX2luaXRUaWxlKHRpbGUpO1xuXG4gIFx0XHQvLyBpZiBjcmVhdGVUaWxlIGlzIGRlZmluZWQgd2l0aCBhIHNlY29uZCBhcmd1bWVudCAoXCJkb25lXCIgY2FsbGJhY2spLFxuICBcdFx0Ly8gd2Uga25vdyB0aGF0IHRpbGUgaXMgYXN5bmMgYW5kIHdpbGwgYmUgcmVhZHkgbGF0ZXI7IG90aGVyd2lzZVxuICBcdFx0aWYgKHRoaXMuY3JlYXRlVGlsZS5sZW5ndGggPCAyKSB7XG4gIFx0XHRcdC8vIG1hcmsgdGlsZSBhcyByZWFkeSwgYnV0IGRlbGF5IG9uZSBmcmFtZSBmb3Igb3BhY2l0eSBhbmltYXRpb24gdG8gaGFwcGVuXG4gIFx0XHRcdHJlcXVlc3RBbmltRnJhbWUoYmluZCh0aGlzLl90aWxlUmVhZHksIHRoaXMsIGNvb3JkcywgbnVsbCwgdGlsZSkpO1xuICBcdFx0fVxuXG4gIFx0XHRzZXRQb3NpdGlvbih0aWxlLCB0aWxlUG9zKTtcblxuICBcdFx0Ly8gc2F2ZSB0aWxlIGluIGNhY2hlXG4gIFx0XHR0aGlzLl90aWxlc1trZXldID0ge1xuICBcdFx0XHRlbDogdGlsZSxcbiAgXHRcdFx0Y29vcmRzOiBjb29yZHMsXG4gIFx0XHRcdGN1cnJlbnQ6IHRydWVcbiAgXHRcdH07XG5cbiAgXHRcdGNvbnRhaW5lci5hcHBlbmRDaGlsZCh0aWxlKTtcbiAgXHRcdC8vIEBldmVudCB0aWxlbG9hZHN0YXJ0OiBUaWxlRXZlbnRcbiAgXHRcdC8vIEZpcmVkIHdoZW4gYSB0aWxlIGlzIHJlcXVlc3RlZCBhbmQgc3RhcnRzIGxvYWRpbmcuXG4gIFx0XHR0aGlzLmZpcmUoJ3RpbGVsb2Fkc3RhcnQnLCB7XG4gIFx0XHRcdHRpbGU6IHRpbGUsXG4gIFx0XHRcdGNvb3JkczogY29vcmRzXG4gIFx0XHR9KTtcbiAgXHR9LFxuXG4gIFx0X3RpbGVSZWFkeTogZnVuY3Rpb24gKGNvb3JkcywgZXJyLCB0aWxlKSB7XG4gIFx0XHRpZiAoZXJyKSB7XG4gIFx0XHRcdC8vIEBldmVudCB0aWxlZXJyb3I6IFRpbGVFcnJvckV2ZW50XG4gIFx0XHRcdC8vIEZpcmVkIHdoZW4gdGhlcmUgaXMgYW4gZXJyb3IgbG9hZGluZyBhIHRpbGUuXG4gIFx0XHRcdHRoaXMuZmlyZSgndGlsZWVycm9yJywge1xuICBcdFx0XHRcdGVycm9yOiBlcnIsXG4gIFx0XHRcdFx0dGlsZTogdGlsZSxcbiAgXHRcdFx0XHRjb29yZHM6IGNvb3Jkc1xuICBcdFx0XHR9KTtcbiAgXHRcdH1cblxuICBcdFx0dmFyIGtleSA9IHRoaXMuX3RpbGVDb29yZHNUb0tleShjb29yZHMpO1xuXG4gIFx0XHR0aWxlID0gdGhpcy5fdGlsZXNba2V5XTtcbiAgXHRcdGlmICghdGlsZSkgeyByZXR1cm47IH1cblxuICBcdFx0dGlsZS5sb2FkZWQgPSArbmV3IERhdGUoKTtcbiAgXHRcdGlmICh0aGlzLl9tYXAuX2ZhZGVBbmltYXRlZCkge1xuICBcdFx0XHRzZXRPcGFjaXR5KHRpbGUuZWwsIDApO1xuICBcdFx0XHRjYW5jZWxBbmltRnJhbWUodGhpcy5fZmFkZUZyYW1lKTtcbiAgXHRcdFx0dGhpcy5fZmFkZUZyYW1lID0gcmVxdWVzdEFuaW1GcmFtZSh0aGlzLl91cGRhdGVPcGFjaXR5LCB0aGlzKTtcbiAgXHRcdH0gZWxzZSB7XG4gIFx0XHRcdHRpbGUuYWN0aXZlID0gdHJ1ZTtcbiAgXHRcdFx0dGhpcy5fcHJ1bmVUaWxlcygpO1xuICBcdFx0fVxuXG4gIFx0XHRpZiAoIWVycikge1xuICBcdFx0XHRhZGRDbGFzcyh0aWxlLmVsLCAnbGVhZmxldC10aWxlLWxvYWRlZCcpO1xuXG4gIFx0XHRcdC8vIEBldmVudCB0aWxlbG9hZDogVGlsZUV2ZW50XG4gIFx0XHRcdC8vIEZpcmVkIHdoZW4gYSB0aWxlIGxvYWRzLlxuICBcdFx0XHR0aGlzLmZpcmUoJ3RpbGVsb2FkJywge1xuICBcdFx0XHRcdHRpbGU6IHRpbGUuZWwsXG4gIFx0XHRcdFx0Y29vcmRzOiBjb29yZHNcbiAgXHRcdFx0fSk7XG4gIFx0XHR9XG5cbiAgXHRcdGlmICh0aGlzLl9ub1RpbGVzVG9Mb2FkKCkpIHtcbiAgXHRcdFx0dGhpcy5fbG9hZGluZyA9IGZhbHNlO1xuICBcdFx0XHQvLyBAZXZlbnQgbG9hZDogRXZlbnRcbiAgXHRcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgZ3JpZCBsYXllciBsb2FkZWQgYWxsIHZpc2libGUgdGlsZXMuXG4gIFx0XHRcdHRoaXMuZmlyZSgnbG9hZCcpO1xuXG4gIFx0XHRcdGlmIChCcm93c2VyLmllbHQ5IHx8ICF0aGlzLl9tYXAuX2ZhZGVBbmltYXRlZCkge1xuICBcdFx0XHRcdHJlcXVlc3RBbmltRnJhbWUodGhpcy5fcHJ1bmVUaWxlcywgdGhpcyk7XG4gIFx0XHRcdH0gZWxzZSB7XG4gIFx0XHRcdFx0Ly8gV2FpdCBhIGJpdCBtb3JlIHRoYW4gMC4yIHNlY3MgKHRoZSBkdXJhdGlvbiBvZiB0aGUgdGlsZSBmYWRlLWluKVxuICBcdFx0XHRcdC8vIHRvIHRyaWdnZXIgYSBwcnVuaW5nLlxuICBcdFx0XHRcdHNldFRpbWVvdXQoYmluZCh0aGlzLl9wcnVuZVRpbGVzLCB0aGlzKSwgMjUwKTtcbiAgXHRcdFx0fVxuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfZ2V0VGlsZVBvczogZnVuY3Rpb24gKGNvb3Jkcykge1xuICBcdFx0cmV0dXJuIGNvb3Jkcy5zY2FsZUJ5KHRoaXMuZ2V0VGlsZVNpemUoKSkuc3VidHJhY3QodGhpcy5fbGV2ZWwub3JpZ2luKTtcbiAgXHR9LFxuXG4gIFx0X3dyYXBDb29yZHM6IGZ1bmN0aW9uIChjb29yZHMpIHtcbiAgXHRcdHZhciBuZXdDb29yZHMgPSBuZXcgUG9pbnQoXG4gIFx0XHRcdHRoaXMuX3dyYXBYID8gd3JhcE51bShjb29yZHMueCwgdGhpcy5fd3JhcFgpIDogY29vcmRzLngsXG4gIFx0XHRcdHRoaXMuX3dyYXBZID8gd3JhcE51bShjb29yZHMueSwgdGhpcy5fd3JhcFkpIDogY29vcmRzLnkpO1xuICBcdFx0bmV3Q29vcmRzLnogPSBjb29yZHMuejtcbiAgXHRcdHJldHVybiBuZXdDb29yZHM7XG4gIFx0fSxcblxuICBcdF9weEJvdW5kc1RvVGlsZVJhbmdlOiBmdW5jdGlvbiAoYm91bmRzKSB7XG4gIFx0XHR2YXIgdGlsZVNpemUgPSB0aGlzLmdldFRpbGVTaXplKCk7XG4gIFx0XHRyZXR1cm4gbmV3IEJvdW5kcyhcbiAgXHRcdFx0Ym91bmRzLm1pbi51bnNjYWxlQnkodGlsZVNpemUpLmZsb29yKCksXG4gIFx0XHRcdGJvdW5kcy5tYXgudW5zY2FsZUJ5KHRpbGVTaXplKS5jZWlsKCkuc3VidHJhY3QoWzEsIDFdKSk7XG4gIFx0fSxcblxuICBcdF9ub1RpbGVzVG9Mb2FkOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRmb3IgKHZhciBrZXkgaW4gdGhpcy5fdGlsZXMpIHtcbiAgXHRcdFx0aWYgKCF0aGlzLl90aWxlc1trZXldLmxvYWRlZCkgeyByZXR1cm4gZmFsc2U7IH1cbiAgXHRcdH1cbiAgXHRcdHJldHVybiB0cnVlO1xuICBcdH1cbiAgfSk7XG5cbiAgLy8gQGZhY3RvcnkgTC5ncmlkTGF5ZXIob3B0aW9ucz86IEdyaWRMYXllciBvcHRpb25zKVxuICAvLyBDcmVhdGVzIGEgbmV3IGluc3RhbmNlIG9mIEdyaWRMYXllciB3aXRoIHRoZSBzdXBwbGllZCBvcHRpb25zLlxuICBmdW5jdGlvbiBncmlkTGF5ZXIob3B0aW9ucykge1xuICBcdHJldHVybiBuZXcgR3JpZExheWVyKG9wdGlvbnMpO1xuICB9XG5cbiAgLypcclxuICAgKiBAY2xhc3MgVGlsZUxheWVyXHJcbiAgICogQGluaGVyaXRzIEdyaWRMYXllclxyXG4gICAqIEBha2EgTC5UaWxlTGF5ZXJcclxuICAgKiBVc2VkIHRvIGxvYWQgYW5kIGRpc3BsYXkgdGlsZSBsYXllcnMgb24gdGhlIG1hcC4gTm90ZSB0aGF0IG1vc3QgdGlsZSBzZXJ2ZXJzIHJlcXVpcmUgYXR0cmlidXRpb24sIHdoaWNoIHlvdSBjYW4gc2V0IHVuZGVyIGBMYXllcmAuIEV4dGVuZHMgYEdyaWRMYXllcmAuXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiBMLnRpbGVMYXllcignaHR0cHM6Ly90aWxlLm9wZW5zdHJlZXRtYXAub3JnL3t6fS97eH0ve3l9LnBuZz97Zm9vfScsIHtmb286ICdiYXInLCBhdHRyaWJ1dGlvbjogJyZjb3B5OyA8YSBocmVmPVwiaHR0cHM6Ly93d3cub3BlbnN0cmVldG1hcC5vcmcvY29weXJpZ2h0XCI+T3BlblN0cmVldE1hcDwvYT4gY29udHJpYnV0b3JzJ30pLmFkZFRvKG1hcCk7XG4gICAqIGBgYFxyXG4gICAqXHJcbiAgICogQHNlY3Rpb24gVVJMIHRlbXBsYXRlXHJcbiAgICogQGV4YW1wbGVcclxuICAgKlxyXG4gICAqIEEgc3RyaW5nIG9mIHRoZSBmb2xsb3dpbmcgZm9ybTpcclxuICAgKlxyXG4gICAqIGBgYFxyXG4gICAqICdodHRwczovL3tzfS5zb21lZG9tYWluLmNvbS9ibGFibGEve3p9L3t4fS97eX17cn0ucG5nJ1xyXG4gICAqIGBgYFxyXG4gICAqXHJcbiAgICogYHtzfWAgbWVhbnMgb25lIG9mIHRoZSBhdmFpbGFibGUgc3ViZG9tYWlucyAodXNlZCBzZXF1ZW50aWFsbHkgdG8gaGVscCB3aXRoIGJyb3dzZXIgcGFyYWxsZWwgcmVxdWVzdHMgcGVyIGRvbWFpbiBsaW1pdGF0aW9uOyBzdWJkb21haW4gdmFsdWVzIGFyZSBzcGVjaWZpZWQgaW4gb3B0aW9uczsgYGFgLCBgYmAgb3IgYGNgIGJ5IGRlZmF1bHQsIGNhbiBiZSBvbWl0dGVkKSwgYHt6fWAg4oCUIHpvb20gbGV2ZWwsIGB7eH1gIGFuZCBge3l9YCDigJQgdGlsZSBjb29yZGluYXRlcy4gYHtyfWAgY2FuIGJlIHVzZWQgdG8gYWRkIFwiJmNvbW1hdDsyeFwiIHRvIHRoZSBVUkwgdG8gbG9hZCByZXRpbmEgdGlsZXMuXHJcbiAgICpcclxuICAgKiBZb3UgY2FuIHVzZSBjdXN0b20ga2V5cyBpbiB0aGUgdGVtcGxhdGUsIHdoaWNoIHdpbGwgYmUgW2V2YWx1YXRlZF0oI3V0aWwtdGVtcGxhdGUpIGZyb20gVGlsZUxheWVyIG9wdGlvbnMsIGxpa2UgdGhpczpcclxuICAgKlxyXG4gICAqIGBgYFxyXG4gICAqIEwudGlsZUxheWVyKCdodHRwczovL3tzfS5zb21lZG9tYWluLmNvbS97Zm9vfS97en0ve3h9L3t5fS5wbmcnLCB7Zm9vOiAnYmFyJ30pO1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG5cclxuXHJcbiAgdmFyIFRpbGVMYXllciA9IEdyaWRMYXllci5leHRlbmQoe1xyXG5cclxuICBcdC8vIEBzZWN0aW9uXHJcbiAgXHQvLyBAYWthIFRpbGVMYXllciBvcHRpb25zXHJcbiAgXHRvcHRpb25zOiB7XHJcbiAgXHRcdC8vIEBvcHRpb24gbWluWm9vbTogTnVtYmVyID0gMFxyXG4gIFx0XHQvLyBUaGUgbWluaW11bSB6b29tIGxldmVsIGRvd24gdG8gd2hpY2ggdGhpcyBsYXllciB3aWxsIGJlIGRpc3BsYXllZCAoaW5jbHVzaXZlKS5cclxuICBcdFx0bWluWm9vbTogMCxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gbWF4Wm9vbTogTnVtYmVyID0gMThcclxuICBcdFx0Ly8gVGhlIG1heGltdW0gem9vbSBsZXZlbCB1cCB0byB3aGljaCB0aGlzIGxheWVyIHdpbGwgYmUgZGlzcGxheWVkIChpbmNsdXNpdmUpLlxyXG4gIFx0XHRtYXhab29tOiAxOCxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gc3ViZG9tYWluczogU3RyaW5nfFN0cmluZ1tdID0gJ2FiYydcclxuICBcdFx0Ly8gU3ViZG9tYWlucyBvZiB0aGUgdGlsZSBzZXJ2aWNlLiBDYW4gYmUgcGFzc2VkIGluIHRoZSBmb3JtIG9mIG9uZSBzdHJpbmcgKHdoZXJlIGVhY2ggbGV0dGVyIGlzIGEgc3ViZG9tYWluIG5hbWUpIG9yIGFuIGFycmF5IG9mIHN0cmluZ3MuXHJcbiAgXHRcdHN1YmRvbWFpbnM6ICdhYmMnLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBlcnJvclRpbGVVcmw6IFN0cmluZyA9ICcnXHJcbiAgXHRcdC8vIFVSTCB0byB0aGUgdGlsZSBpbWFnZSB0byBzaG93IGluIHBsYWNlIG9mIHRoZSB0aWxlIHRoYXQgZmFpbGVkIHRvIGxvYWQuXHJcbiAgXHRcdGVycm9yVGlsZVVybDogJycsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHpvb21PZmZzZXQ6IE51bWJlciA9IDBcclxuICBcdFx0Ly8gVGhlIHpvb20gbnVtYmVyIHVzZWQgaW4gdGlsZSBVUkxzIHdpbGwgYmUgb2Zmc2V0IHdpdGggdGhpcyB2YWx1ZS5cclxuICBcdFx0em9vbU9mZnNldDogMCxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gdG1zOiBCb29sZWFuID0gZmFsc2VcclxuICBcdFx0Ly8gSWYgYHRydWVgLCBpbnZlcnNlcyBZIGF4aXMgbnVtYmVyaW5nIGZvciB0aWxlcyAodHVybiB0aGlzIG9uIGZvciBbVE1TXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9UaWxlX01hcF9TZXJ2aWNlKSBzZXJ2aWNlcykuXHJcbiAgXHRcdHRtczogZmFsc2UsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHpvb21SZXZlcnNlOiBCb29sZWFuID0gZmFsc2VcclxuICBcdFx0Ly8gSWYgc2V0IHRvIHRydWUsIHRoZSB6b29tIG51bWJlciB1c2VkIGluIHRpbGUgVVJMcyB3aWxsIGJlIHJldmVyc2VkIChgbWF4Wm9vbSAtIHpvb21gIGluc3RlYWQgb2YgYHpvb21gKVxyXG4gIFx0XHR6b29tUmV2ZXJzZTogZmFsc2UsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIGRldGVjdFJldGluYTogQm9vbGVhbiA9IGZhbHNlXHJcbiAgXHRcdC8vIElmIGB0cnVlYCBhbmQgdXNlciBpcyBvbiBhIHJldGluYSBkaXNwbGF5LCBpdCB3aWxsIHJlcXVlc3QgZm91ciB0aWxlcyBvZiBoYWxmIHRoZSBzcGVjaWZpZWQgc2l6ZSBhbmQgYSBiaWdnZXIgem9vbSBsZXZlbCBpbiBwbGFjZSBvZiBvbmUgdG8gdXRpbGl6ZSB0aGUgaGlnaCByZXNvbHV0aW9uLlxyXG4gIFx0XHRkZXRlY3RSZXRpbmE6IGZhbHNlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBjcm9zc09yaWdpbjogQm9vbGVhbnxTdHJpbmcgPSBmYWxzZVxyXG4gIFx0XHQvLyBXaGV0aGVyIHRoZSBjcm9zc09yaWdpbiBhdHRyaWJ1dGUgd2lsbCBiZSBhZGRlZCB0byB0aGUgdGlsZXMuXHJcbiAgXHRcdC8vIElmIGEgU3RyaW5nIGlzIHByb3ZpZGVkLCBhbGwgdGlsZXMgd2lsbCBoYXZlIHRoZWlyIGNyb3NzT3JpZ2luIGF0dHJpYnV0ZSBzZXQgdG8gdGhlIFN0cmluZyBwcm92aWRlZC4gVGhpcyBpcyBuZWVkZWQgaWYgeW91IHdhbnQgdG8gYWNjZXNzIHRpbGUgcGl4ZWwgZGF0YS5cclxuICBcdFx0Ly8gUmVmZXIgdG8gW0NPUlMgU2V0dGluZ3NdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0hUTUwvQ09SU19zZXR0aW5nc19hdHRyaWJ1dGVzKSBmb3IgdmFsaWQgU3RyaW5nIHZhbHVlcy5cclxuICBcdFx0Y3Jvc3NPcmlnaW46IGZhbHNlLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiByZWZlcnJlclBvbGljeTogQm9vbGVhbnxTdHJpbmcgPSBmYWxzZVxyXG4gIFx0XHQvLyBXaGV0aGVyIHRoZSByZWZlcnJlclBvbGljeSBhdHRyaWJ1dGUgd2lsbCBiZSBhZGRlZCB0byB0aGUgdGlsZXMuXHJcbiAgXHRcdC8vIElmIGEgU3RyaW5nIGlzIHByb3ZpZGVkLCBhbGwgdGlsZXMgd2lsbCBoYXZlIHRoZWlyIHJlZmVycmVyUG9saWN5IGF0dHJpYnV0ZSBzZXQgdG8gdGhlIFN0cmluZyBwcm92aWRlZC5cclxuICBcdFx0Ly8gVGhpcyBtYXkgYmUgbmVlZGVkIGlmIHlvdXIgbWFwJ3MgcmVuZGVyaW5nIGNvbnRleHQgaGFzIGEgc3RyaWN0IGRlZmF1bHQgYnV0IHlvdXIgdGlsZSBwcm92aWRlciBleHBlY3RzIGEgdmFsaWQgcmVmZXJyZXJcclxuICBcdFx0Ly8gKGUuZy4gdG8gdmFsaWRhdGUgYW4gQVBJIHRva2VuKS5cclxuICBcdFx0Ly8gUmVmZXIgdG8gW0hUTUxJbWFnZUVsZW1lbnQucmVmZXJyZXJQb2xpY3ldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9IVE1MSW1hZ2VFbGVtZW50L3JlZmVycmVyUG9saWN5KSBmb3IgdmFsaWQgU3RyaW5nIHZhbHVlcy5cclxuICBcdFx0cmVmZXJyZXJQb2xpY3k6IGZhbHNlXHJcbiAgXHR9LFxyXG5cclxuICBcdGluaXRpYWxpemU6IGZ1bmN0aW9uICh1cmwsIG9wdGlvbnMpIHtcclxuXHJcbiAgXHRcdHRoaXMuX3VybCA9IHVybDtcclxuXHJcbiAgXHRcdG9wdGlvbnMgPSBzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xyXG5cclxuICBcdFx0Ly8gZGV0ZWN0aW5nIHJldGluYSBkaXNwbGF5cywgYWRqdXN0aW5nIHRpbGVTaXplIGFuZCB6b29tIGxldmVsc1xyXG4gIFx0XHRpZiAob3B0aW9ucy5kZXRlY3RSZXRpbmEgJiYgQnJvd3Nlci5yZXRpbmEgJiYgb3B0aW9ucy5tYXhab29tID4gMCkge1xyXG5cclxuICBcdFx0XHRvcHRpb25zLnRpbGVTaXplID0gTWF0aC5mbG9vcihvcHRpb25zLnRpbGVTaXplIC8gMik7XHJcblxyXG4gIFx0XHRcdGlmICghb3B0aW9ucy56b29tUmV2ZXJzZSkge1xyXG4gIFx0XHRcdFx0b3B0aW9ucy56b29tT2Zmc2V0Kys7XHJcbiAgXHRcdFx0XHRvcHRpb25zLm1heFpvb20gPSBNYXRoLm1heChvcHRpb25zLm1pblpvb20sIG9wdGlvbnMubWF4Wm9vbSAtIDEpO1xyXG4gIFx0XHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0XHRvcHRpb25zLnpvb21PZmZzZXQtLTtcclxuICBcdFx0XHRcdG9wdGlvbnMubWluWm9vbSA9IE1hdGgubWluKG9wdGlvbnMubWF4Wm9vbSwgb3B0aW9ucy5taW5ab29tICsgMSk7XHJcbiAgXHRcdFx0fVxyXG5cclxuICBcdFx0XHRvcHRpb25zLm1pblpvb20gPSBNYXRoLm1heCgwLCBvcHRpb25zLm1pblpvb20pO1xyXG4gIFx0XHR9IGVsc2UgaWYgKCFvcHRpb25zLnpvb21SZXZlcnNlKSB7XHJcbiAgXHRcdFx0Ly8gbWFrZSBzdXJlIG1heFpvb20gaXMgZ3RlIG1pblpvb21cclxuICBcdFx0XHRvcHRpb25zLm1heFpvb20gPSBNYXRoLm1heChvcHRpb25zLm1pblpvb20sIG9wdGlvbnMubWF4Wm9vbSk7XHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0Ly8gbWFrZSBzdXJlIG1pblpvb20gaXMgbHRlIG1heFpvb21cclxuICBcdFx0XHRvcHRpb25zLm1pblpvb20gPSBNYXRoLm1pbihvcHRpb25zLm1heFpvb20sIG9wdGlvbnMubWluWm9vbSk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdGlmICh0eXBlb2Ygb3B0aW9ucy5zdWJkb21haW5zID09PSAnc3RyaW5nJykge1xyXG4gIFx0XHRcdG9wdGlvbnMuc3ViZG9tYWlucyA9IG9wdGlvbnMuc3ViZG9tYWlucy5zcGxpdCgnJyk7XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHRoaXMub24oJ3RpbGV1bmxvYWQnLCB0aGlzLl9vblRpbGVSZW1vdmUpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAbWV0aG9kIHNldFVybCh1cmw6IFN0cmluZywgbm9SZWRyYXc/OiBCb29sZWFuKTogdGhpc1xyXG4gIFx0Ly8gVXBkYXRlcyB0aGUgbGF5ZXIncyBVUkwgdGVtcGxhdGUgYW5kIHJlZHJhd3MgaXQgKHVubGVzcyBgbm9SZWRyYXdgIGlzIHNldCB0byBgdHJ1ZWApLlxyXG4gIFx0Ly8gSWYgdGhlIFVSTCBkb2VzIG5vdCBjaGFuZ2UsIHRoZSBsYXllciB3aWxsIG5vdCBiZSByZWRyYXduIHVubGVzc1xyXG4gIFx0Ly8gdGhlIG5vUmVkcmF3IHBhcmFtZXRlciBpcyBzZXQgdG8gZmFsc2UuXHJcbiAgXHRzZXRVcmw6IGZ1bmN0aW9uICh1cmwsIG5vUmVkcmF3KSB7XHJcbiAgXHRcdGlmICh0aGlzLl91cmwgPT09IHVybCAmJiBub1JlZHJhdyA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgXHRcdFx0bm9SZWRyYXcgPSB0cnVlO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHR0aGlzLl91cmwgPSB1cmw7XHJcblxyXG4gIFx0XHRpZiAoIW5vUmVkcmF3KSB7XHJcbiAgXHRcdFx0dGhpcy5yZWRyYXcoKTtcclxuICBcdFx0fVxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBjcmVhdGVUaWxlKGNvb3JkczogT2JqZWN0LCBkb25lPzogRnVuY3Rpb24pOiBIVE1MRWxlbWVudFxyXG4gIFx0Ly8gQ2FsbGVkIG9ubHkgaW50ZXJuYWxseSwgb3ZlcnJpZGVzIEdyaWRMYXllcidzIFtgY3JlYXRlVGlsZSgpYF0oI2dyaWRsYXllci1jcmVhdGV0aWxlKVxyXG4gIFx0Ly8gdG8gcmV0dXJuIGFuIGA8aW1nPmAgSFRNTCBlbGVtZW50IHdpdGggdGhlIGFwcHJvcHJpYXRlIGltYWdlIFVSTCBnaXZlbiBgY29vcmRzYC4gVGhlIGBkb25lYFxyXG4gIFx0Ly8gY2FsbGJhY2sgaXMgY2FsbGVkIHdoZW4gdGhlIHRpbGUgaGFzIGJlZW4gbG9hZGVkLlxyXG4gIFx0Y3JlYXRlVGlsZTogZnVuY3Rpb24gKGNvb3JkcywgZG9uZSkge1xyXG4gIFx0XHR2YXIgdGlsZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ltZycpO1xyXG5cclxuICBcdFx0b24odGlsZSwgJ2xvYWQnLCBiaW5kKHRoaXMuX3RpbGVPbkxvYWQsIHRoaXMsIGRvbmUsIHRpbGUpKTtcclxuICBcdFx0b24odGlsZSwgJ2Vycm9yJywgYmluZCh0aGlzLl90aWxlT25FcnJvciwgdGhpcywgZG9uZSwgdGlsZSkpO1xyXG5cclxuICBcdFx0aWYgKHRoaXMub3B0aW9ucy5jcm9zc09yaWdpbiB8fCB0aGlzLm9wdGlvbnMuY3Jvc3NPcmlnaW4gPT09ICcnKSB7XHJcbiAgXHRcdFx0dGlsZS5jcm9zc09yaWdpbiA9IHRoaXMub3B0aW9ucy5jcm9zc09yaWdpbiA9PT0gdHJ1ZSA/ICcnIDogdGhpcy5vcHRpb25zLmNyb3NzT3JpZ2luO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHQvLyBmb3IgdGhpcyBuZXcgb3B0aW9uIHdlIGZvbGxvdyB0aGUgZG9jdW1lbnRlZCBiZWhhdmlvclxyXG4gIFx0XHQvLyBtb3JlIGNsb3NlbHkgYnkgb25seSBzZXR0aW5nIHRoZSBwcm9wZXJ0eSB3aGVuIHN0cmluZ1xyXG4gIFx0XHRpZiAodHlwZW9mIHRoaXMub3B0aW9ucy5yZWZlcnJlclBvbGljeSA9PT0gJ3N0cmluZycpIHtcclxuICBcdFx0XHR0aWxlLnJlZmVycmVyUG9saWN5ID0gdGhpcy5vcHRpb25zLnJlZmVycmVyUG9saWN5O1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHQvLyBUaGUgYWx0IGF0dHJpYnV0ZSBpcyBzZXQgdG8gdGhlIGVtcHR5IHN0cmluZyxcclxuICBcdFx0Ly8gYWxsb3dpbmcgc2NyZWVuIHJlYWRlcnMgdG8gaWdub3JlIHRoZSBkZWNvcmF0aXZlIGltYWdlIHRpbGVzLlxyXG4gIFx0XHQvLyBodHRwczovL3d3dy53My5vcmcvV0FJL3R1dG9yaWFscy9pbWFnZXMvZGVjb3JhdGl2ZS9cclxuICBcdFx0Ly8gaHR0cHM6Ly93d3cudzMub3JnL1RSL2h0bWwtYXJpYS8jZWwtaW1nLWVtcHR5LWFsdFxyXG4gIFx0XHR0aWxlLmFsdCA9ICcnO1xyXG5cclxuICBcdFx0dGlsZS5zcmMgPSB0aGlzLmdldFRpbGVVcmwoY29vcmRzKTtcclxuXHJcbiAgXHRcdHJldHVybiB0aWxlO1xyXG4gIFx0fSxcclxuXHJcbiAgXHQvLyBAc2VjdGlvbiBFeHRlbnNpb24gbWV0aG9kc1xyXG4gIFx0Ly8gQHVuaW5oZXJpdGFibGVcclxuICBcdC8vIExheWVycyBleHRlbmRpbmcgYFRpbGVMYXllcmAgbWlnaHQgcmVpbXBsZW1lbnQgdGhlIGZvbGxvd2luZyBtZXRob2QuXHJcbiAgXHQvLyBAbWV0aG9kIGdldFRpbGVVcmwoY29vcmRzOiBPYmplY3QpOiBTdHJpbmdcclxuICBcdC8vIENhbGxlZCBvbmx5IGludGVybmFsbHksIHJldHVybnMgdGhlIFVSTCBmb3IgYSB0aWxlIGdpdmVuIGl0cyBjb29yZGluYXRlcy5cclxuICBcdC8vIENsYXNzZXMgZXh0ZW5kaW5nIGBUaWxlTGF5ZXJgIGNhbiBvdmVycmlkZSB0aGlzIGZ1bmN0aW9uIHRvIHByb3ZpZGUgY3VzdG9tIHRpbGUgVVJMIG5hbWluZyBzY2hlbWVzLlxyXG4gIFx0Z2V0VGlsZVVybDogZnVuY3Rpb24gKGNvb3Jkcykge1xyXG4gIFx0XHR2YXIgZGF0YSA9IHtcclxuICBcdFx0XHRyOiBCcm93c2VyLnJldGluYSA/ICdAMngnIDogJycsXHJcbiAgXHRcdFx0czogdGhpcy5fZ2V0U3ViZG9tYWluKGNvb3JkcyksXHJcbiAgXHRcdFx0eDogY29vcmRzLngsXHJcbiAgXHRcdFx0eTogY29vcmRzLnksXHJcbiAgXHRcdFx0ejogdGhpcy5fZ2V0Wm9vbUZvclVybCgpXHJcbiAgXHRcdH07XHJcbiAgXHRcdGlmICh0aGlzLl9tYXAgJiYgIXRoaXMuX21hcC5vcHRpb25zLmNycy5pbmZpbml0ZSkge1xyXG4gIFx0XHRcdHZhciBpbnZlcnRlZFkgPSB0aGlzLl9nbG9iYWxUaWxlUmFuZ2UubWF4LnkgLSBjb29yZHMueTtcclxuICBcdFx0XHRpZiAodGhpcy5vcHRpb25zLnRtcykge1xyXG4gIFx0XHRcdFx0ZGF0YVsneSddID0gaW52ZXJ0ZWRZO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0XHRkYXRhWycteSddID0gaW52ZXJ0ZWRZO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gdGVtcGxhdGUodGhpcy5fdXJsLCBleHRlbmQoZGF0YSwgdGhpcy5vcHRpb25zKSk7XHJcbiAgXHR9LFxyXG5cclxuICBcdF90aWxlT25Mb2FkOiBmdW5jdGlvbiAoZG9uZSwgdGlsZSkge1xyXG4gIFx0XHQvLyBGb3IgaHR0cHM6Ly9naXRodWIuY29tL0xlYWZsZXQvTGVhZmxldC9pc3N1ZXMvMzMzMlxyXG4gIFx0XHRpZiAoQnJvd3Nlci5pZWx0OSkge1xyXG4gIFx0XHRcdHNldFRpbWVvdXQoYmluZChkb25lLCB0aGlzLCBudWxsLCB0aWxlKSwgMCk7XHJcbiAgXHRcdH0gZWxzZSB7XHJcbiAgXHRcdFx0ZG9uZShudWxsLCB0aWxlKTtcclxuICBcdFx0fVxyXG4gIFx0fSxcclxuXHJcbiAgXHRfdGlsZU9uRXJyb3I6IGZ1bmN0aW9uIChkb25lLCB0aWxlLCBlKSB7XHJcbiAgXHRcdHZhciBlcnJvclVybCA9IHRoaXMub3B0aW9ucy5lcnJvclRpbGVVcmw7XHJcbiAgXHRcdGlmIChlcnJvclVybCAmJiB0aWxlLmdldEF0dHJpYnV0ZSgnc3JjJykgIT09IGVycm9yVXJsKSB7XHJcbiAgXHRcdFx0dGlsZS5zcmMgPSBlcnJvclVybDtcclxuICBcdFx0fVxyXG4gIFx0XHRkb25lKGUsIHRpbGUpO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRfb25UaWxlUmVtb3ZlOiBmdW5jdGlvbiAoZSkge1xyXG4gIFx0XHRlLnRpbGUub25sb2FkID0gbnVsbDtcclxuICBcdH0sXHJcblxyXG4gIFx0X2dldFpvb21Gb3JVcmw6IGZ1bmN0aW9uICgpIHtcclxuICBcdFx0dmFyIHpvb20gPSB0aGlzLl90aWxlWm9vbSxcclxuICBcdFx0bWF4Wm9vbSA9IHRoaXMub3B0aW9ucy5tYXhab29tLFxyXG4gIFx0XHR6b29tUmV2ZXJzZSA9IHRoaXMub3B0aW9ucy56b29tUmV2ZXJzZSxcclxuICBcdFx0em9vbU9mZnNldCA9IHRoaXMub3B0aW9ucy56b29tT2Zmc2V0O1xyXG5cclxuICBcdFx0aWYgKHpvb21SZXZlcnNlKSB7XHJcbiAgXHRcdFx0em9vbSA9IG1heFpvb20gLSB6b29tO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gem9vbSArIHpvb21PZmZzZXQ7XHJcbiAgXHR9LFxyXG5cclxuICBcdF9nZXRTdWJkb21haW46IGZ1bmN0aW9uICh0aWxlUG9pbnQpIHtcclxuICBcdFx0dmFyIGluZGV4ID0gTWF0aC5hYnModGlsZVBvaW50LnggKyB0aWxlUG9pbnQueSkgJSB0aGlzLm9wdGlvbnMuc3ViZG9tYWlucy5sZW5ndGg7XHJcbiAgXHRcdHJldHVybiB0aGlzLm9wdGlvbnMuc3ViZG9tYWluc1tpbmRleF07XHJcbiAgXHR9LFxyXG5cclxuICBcdC8vIHN0b3BzIGxvYWRpbmcgYWxsIHRpbGVzIGluIHRoZSBiYWNrZ3JvdW5kIGxheWVyXHJcbiAgXHRfYWJvcnRMb2FkaW5nOiBmdW5jdGlvbiAoKSB7XHJcbiAgXHRcdHZhciBpLCB0aWxlO1xyXG4gIFx0XHRmb3IgKGkgaW4gdGhpcy5fdGlsZXMpIHtcclxuICBcdFx0XHRpZiAodGhpcy5fdGlsZXNbaV0uY29vcmRzLnogIT09IHRoaXMuX3RpbGVab29tKSB7XHJcbiAgXHRcdFx0XHR0aWxlID0gdGhpcy5fdGlsZXNbaV0uZWw7XHJcblxyXG4gIFx0XHRcdFx0dGlsZS5vbmxvYWQgPSBmYWxzZUZuO1xyXG4gIFx0XHRcdFx0dGlsZS5vbmVycm9yID0gZmFsc2VGbjtcclxuXHJcbiAgXHRcdFx0XHRpZiAoIXRpbGUuY29tcGxldGUpIHtcclxuICBcdFx0XHRcdFx0dGlsZS5zcmMgPSBlbXB0eUltYWdlVXJsO1xyXG4gIFx0XHRcdFx0XHR2YXIgY29vcmRzID0gdGhpcy5fdGlsZXNbaV0uY29vcmRzO1xyXG4gIFx0XHRcdFx0XHRyZW1vdmUodGlsZSk7XHJcbiAgXHRcdFx0XHRcdGRlbGV0ZSB0aGlzLl90aWxlc1tpXTtcclxuICBcdFx0XHRcdFx0Ly8gQGV2ZW50IHRpbGVhYm9ydDogVGlsZUV2ZW50XHJcbiAgXHRcdFx0XHRcdC8vIEZpcmVkIHdoZW4gYSB0aWxlIHdhcyBsb2FkaW5nIGJ1dCBpcyBub3cgbm90IHdhbnRlZC5cclxuICBcdFx0XHRcdFx0dGhpcy5maXJlKCd0aWxlYWJvcnQnLCB7XHJcbiAgXHRcdFx0XHRcdFx0dGlsZTogdGlsZSxcclxuICBcdFx0XHRcdFx0XHRjb29yZHM6IGNvb3Jkc1xyXG4gIFx0XHRcdFx0XHR9KTtcclxuICBcdFx0XHRcdH1cclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuICBcdH0sXHJcblxyXG4gIFx0X3JlbW92ZVRpbGU6IGZ1bmN0aW9uIChrZXkpIHtcclxuICBcdFx0dmFyIHRpbGUgPSB0aGlzLl90aWxlc1trZXldO1xyXG4gIFx0XHRpZiAoIXRpbGUpIHsgcmV0dXJuOyB9XHJcblxyXG4gIFx0XHQvLyBDYW5jZWxzIGFueSBwZW5kaW5nIGh0dHAgcmVxdWVzdHMgYXNzb2NpYXRlZCB3aXRoIHRoZSB0aWxlXHJcbiAgXHRcdHRpbGUuZWwuc2V0QXR0cmlidXRlKCdzcmMnLCBlbXB0eUltYWdlVXJsKTtcclxuXHJcbiAgXHRcdHJldHVybiBHcmlkTGF5ZXIucHJvdG90eXBlLl9yZW1vdmVUaWxlLmNhbGwodGhpcywga2V5KTtcclxuICBcdH0sXHJcblxyXG4gIFx0X3RpbGVSZWFkeTogZnVuY3Rpb24gKGNvb3JkcywgZXJyLCB0aWxlKSB7XHJcbiAgXHRcdGlmICghdGhpcy5fbWFwIHx8ICh0aWxlICYmIHRpbGUuZ2V0QXR0cmlidXRlKCdzcmMnKSA9PT0gZW1wdHlJbWFnZVVybCkpIHtcclxuICBcdFx0XHRyZXR1cm47XHJcbiAgXHRcdH1cclxuXHJcbiAgXHRcdHJldHVybiBHcmlkTGF5ZXIucHJvdG90eXBlLl90aWxlUmVhZHkuY2FsbCh0aGlzLCBjb29yZHMsIGVyciwgdGlsZSk7XHJcbiAgXHR9XHJcbiAgfSk7XHJcblxyXG5cclxuICAvLyBAZmFjdG9yeSBMLnRpbGVsYXllcih1cmxUZW1wbGF0ZTogU3RyaW5nLCBvcHRpb25zPzogVGlsZUxheWVyIG9wdGlvbnMpXHJcbiAgLy8gSW5zdGFudGlhdGVzIGEgdGlsZSBsYXllciBvYmplY3QgZ2l2ZW4gYSBgVVJMIHRlbXBsYXRlYCBhbmQgb3B0aW9uYWxseSBhbiBvcHRpb25zIG9iamVjdC5cclxuXHJcbiAgZnVuY3Rpb24gdGlsZUxheWVyKHVybCwgb3B0aW9ucykge1xyXG4gIFx0cmV0dXJuIG5ldyBUaWxlTGF5ZXIodXJsLCBvcHRpb25zKTtcclxuICB9XG5cbiAgLypcclxuICAgKiBAY2xhc3MgVGlsZUxheWVyLldNU1xyXG4gICAqIEBpbmhlcml0cyBUaWxlTGF5ZXJcclxuICAgKiBAYWthIEwuVGlsZUxheWVyLldNU1xyXG4gICAqIFVzZWQgdG8gZGlzcGxheSBbV01TXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9XZWJfTWFwX1NlcnZpY2UpIHNlcnZpY2VzIGFzIHRpbGUgbGF5ZXJzIG9uIHRoZSBtYXAuIEV4dGVuZHMgYFRpbGVMYXllcmAuXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqXHJcbiAgICogYGBganNcclxuICAgKiB2YXIgbmV4cmFkID0gTC50aWxlTGF5ZXIud21zKFwiaHR0cDovL21lc29uZXQuYWdyb24uaWFzdGF0ZS5lZHUvY2dpLWJpbi93bXMvbmV4cmFkL24wci5jZ2lcIiwge1xyXG4gICAqIFx0bGF5ZXJzOiAnbmV4cmFkLW4wci05MDA5MTMnLFxyXG4gICAqIFx0Zm9ybWF0OiAnaW1hZ2UvcG5nJyxcclxuICAgKiBcdHRyYW5zcGFyZW50OiB0cnVlLFxyXG4gICAqIFx0YXR0cmlidXRpb246IFwiV2VhdGhlciBkYXRhIMKpIDIwMTIgSUVNIE5leHJhZFwiXHJcbiAgICogfSk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcblxyXG4gIHZhciBUaWxlTGF5ZXJXTVMgPSBUaWxlTGF5ZXIuZXh0ZW5kKHtcclxuXHJcbiAgXHQvLyBAc2VjdGlvblxyXG4gIFx0Ly8gQGFrYSBUaWxlTGF5ZXIuV01TIG9wdGlvbnNcclxuICBcdC8vIElmIGFueSBjdXN0b20gb3B0aW9ucyBub3QgZG9jdW1lbnRlZCBoZXJlIGFyZSB1c2VkLCB0aGV5IHdpbGwgYmUgc2VudCB0byB0aGVcclxuICBcdC8vIFdNUyBzZXJ2ZXIgYXMgZXh0cmEgcGFyYW1ldGVycyBpbiBlYWNoIHJlcXVlc3QgVVJMLiBUaGlzIGNhbiBiZSB1c2VmdWwgZm9yXHJcbiAgXHQvLyBbbm9uLXN0YW5kYXJkIHZlbmRvciBXTVMgcGFyYW1ldGVyc10oaHR0cHM6Ly9kb2NzLmdlb3NlcnZlci5vcmcvc3RhYmxlL2VuL3VzZXIvc2VydmljZXMvd21zL3ZlbmRvci5odG1sKS5cclxuICBcdGRlZmF1bHRXbXNQYXJhbXM6IHtcclxuICBcdFx0c2VydmljZTogJ1dNUycsXHJcbiAgXHRcdHJlcXVlc3Q6ICdHZXRNYXAnLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBsYXllcnM6IFN0cmluZyA9ICcnXHJcbiAgXHRcdC8vICoqKHJlcXVpcmVkKSoqIENvbW1hLXNlcGFyYXRlZCBsaXN0IG9mIFdNUyBsYXllcnMgdG8gc2hvdy5cclxuICBcdFx0bGF5ZXJzOiAnJyxcclxuXHJcbiAgXHRcdC8vIEBvcHRpb24gc3R5bGVzOiBTdHJpbmcgPSAnJ1xyXG4gIFx0XHQvLyBDb21tYS1zZXBhcmF0ZWQgbGlzdCBvZiBXTVMgc3R5bGVzLlxyXG4gIFx0XHRzdHlsZXM6ICcnLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiBmb3JtYXQ6IFN0cmluZyA9ICdpbWFnZS9qcGVnJ1xyXG4gIFx0XHQvLyBXTVMgaW1hZ2UgZm9ybWF0ICh1c2UgYCdpbWFnZS9wbmcnYCBmb3IgbGF5ZXJzIHdpdGggdHJhbnNwYXJlbmN5KS5cclxuICBcdFx0Zm9ybWF0OiAnaW1hZ2UvanBlZycsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHRyYW5zcGFyZW50OiBCb29sZWFuID0gZmFsc2VcclxuICBcdFx0Ly8gSWYgYHRydWVgLCB0aGUgV01TIHNlcnZpY2Ugd2lsbCByZXR1cm4gaW1hZ2VzIHdpdGggdHJhbnNwYXJlbmN5LlxyXG4gIFx0XHR0cmFuc3BhcmVudDogZmFsc2UsXHJcblxyXG4gIFx0XHQvLyBAb3B0aW9uIHZlcnNpb246IFN0cmluZyA9ICcxLjEuMSdcclxuICBcdFx0Ly8gVmVyc2lvbiBvZiB0aGUgV01TIHNlcnZpY2UgdG8gdXNlXHJcbiAgXHRcdHZlcnNpb246ICcxLjEuMSdcclxuICBcdH0sXHJcblxyXG4gIFx0b3B0aW9uczoge1xyXG4gIFx0XHQvLyBAb3B0aW9uIGNyczogQ1JTID0gbnVsbFxyXG4gIFx0XHQvLyBDb29yZGluYXRlIFJlZmVyZW5jZSBTeXN0ZW0gdG8gdXNlIGZvciB0aGUgV01TIHJlcXVlc3RzLCBkZWZhdWx0cyB0b1xyXG4gIFx0XHQvLyBtYXAgQ1JTLiBEb24ndCBjaGFuZ2UgdGhpcyBpZiB5b3UncmUgbm90IHN1cmUgd2hhdCBpdCBtZWFucy5cclxuICBcdFx0Y3JzOiBudWxsLFxyXG5cclxuICBcdFx0Ly8gQG9wdGlvbiB1cHBlcmNhc2U6IEJvb2xlYW4gPSBmYWxzZVxyXG4gIFx0XHQvLyBJZiBgdHJ1ZWAsIFdNUyByZXF1ZXN0IHBhcmFtZXRlciBrZXlzIHdpbGwgYmUgdXBwZXJjYXNlLlxyXG4gIFx0XHR1cHBlcmNhc2U6IGZhbHNlXHJcbiAgXHR9LFxyXG5cclxuICBcdGluaXRpYWxpemU6IGZ1bmN0aW9uICh1cmwsIG9wdGlvbnMpIHtcclxuXHJcbiAgXHRcdHRoaXMuX3VybCA9IHVybDtcclxuXHJcbiAgXHRcdHZhciB3bXNQYXJhbXMgPSBleHRlbmQoe30sIHRoaXMuZGVmYXVsdFdtc1BhcmFtcyk7XHJcblxyXG4gIFx0XHQvLyBhbGwga2V5cyB0aGF0IGFyZSBub3QgVGlsZUxheWVyIG9wdGlvbnMgZ28gdG8gV01TIHBhcmFtc1xyXG4gIFx0XHRmb3IgKHZhciBpIGluIG9wdGlvbnMpIHtcclxuICBcdFx0XHRpZiAoIShpIGluIHRoaXMub3B0aW9ucykpIHtcclxuICBcdFx0XHRcdHdtc1BhcmFtc1tpXSA9IG9wdGlvbnNbaV07XHJcbiAgXHRcdFx0fVxyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRvcHRpb25zID0gc2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcclxuXHJcbiAgXHRcdHZhciByZWFsUmV0aW5hID0gb3B0aW9ucy5kZXRlY3RSZXRpbmEgJiYgQnJvd3Nlci5yZXRpbmEgPyAyIDogMTtcclxuICBcdFx0dmFyIHRpbGVTaXplID0gdGhpcy5nZXRUaWxlU2l6ZSgpO1xyXG4gIFx0XHR3bXNQYXJhbXMud2lkdGggPSB0aWxlU2l6ZS54ICogcmVhbFJldGluYTtcclxuICBcdFx0d21zUGFyYW1zLmhlaWdodCA9IHRpbGVTaXplLnkgKiByZWFsUmV0aW5hO1xyXG5cclxuICBcdFx0dGhpcy53bXNQYXJhbXMgPSB3bXNQYXJhbXM7XHJcbiAgXHR9LFxyXG5cclxuICBcdG9uQWRkOiBmdW5jdGlvbiAobWFwKSB7XHJcblxyXG4gIFx0XHR0aGlzLl9jcnMgPSB0aGlzLm9wdGlvbnMuY3JzIHx8IG1hcC5vcHRpb25zLmNycztcclxuICBcdFx0dGhpcy5fd21zVmVyc2lvbiA9IHBhcnNlRmxvYXQodGhpcy53bXNQYXJhbXMudmVyc2lvbik7XHJcblxyXG4gIFx0XHR2YXIgcHJvamVjdGlvbktleSA9IHRoaXMuX3dtc1ZlcnNpb24gPj0gMS4zID8gJ2NycycgOiAnc3JzJztcclxuICBcdFx0dGhpcy53bXNQYXJhbXNbcHJvamVjdGlvbktleV0gPSB0aGlzLl9jcnMuY29kZTtcclxuXHJcbiAgXHRcdFRpbGVMYXllci5wcm90b3R5cGUub25BZGQuY2FsbCh0aGlzLCBtYXApO1xyXG4gIFx0fSxcclxuXHJcbiAgXHRnZXRUaWxlVXJsOiBmdW5jdGlvbiAoY29vcmRzKSB7XHJcblxyXG4gIFx0XHR2YXIgdGlsZUJvdW5kcyA9IHRoaXMuX3RpbGVDb29yZHNUb053U2UoY29vcmRzKSxcclxuICBcdFx0ICAgIGNycyA9IHRoaXMuX2NycyxcclxuICBcdFx0ICAgIGJvdW5kcyA9IHRvQm91bmRzKGNycy5wcm9qZWN0KHRpbGVCb3VuZHNbMF0pLCBjcnMucHJvamVjdCh0aWxlQm91bmRzWzFdKSksXHJcbiAgXHRcdCAgICBtaW4gPSBib3VuZHMubWluLFxyXG4gIFx0XHQgICAgbWF4ID0gYm91bmRzLm1heCxcclxuICBcdFx0ICAgIGJib3ggPSAodGhpcy5fd21zVmVyc2lvbiA+PSAxLjMgJiYgdGhpcy5fY3JzID09PSBFUFNHNDMyNiA/XHJcbiAgXHRcdCAgICBbbWluLnksIG1pbi54LCBtYXgueSwgbWF4LnhdIDpcclxuICBcdFx0ICAgIFttaW4ueCwgbWluLnksIG1heC54LCBtYXgueV0pLmpvaW4oJywnKSxcclxuICBcdFx0ICAgIHVybCA9IFRpbGVMYXllci5wcm90b3R5cGUuZ2V0VGlsZVVybC5jYWxsKHRoaXMsIGNvb3Jkcyk7XHJcbiAgXHRcdHJldHVybiB1cmwgK1xyXG4gIFx0XHRcdGdldFBhcmFtU3RyaW5nKHRoaXMud21zUGFyYW1zLCB1cmwsIHRoaXMub3B0aW9ucy51cHBlcmNhc2UpICtcclxuICBcdFx0XHQodGhpcy5vcHRpb25zLnVwcGVyY2FzZSA/ICcmQkJPWD0nIDogJyZiYm94PScpICsgYmJveDtcclxuICBcdH0sXHJcblxyXG4gIFx0Ly8gQG1ldGhvZCBzZXRQYXJhbXMocGFyYW1zOiBPYmplY3QsIG5vUmVkcmF3PzogQm9vbGVhbik6IHRoaXNcclxuICBcdC8vIE1lcmdlcyBhbiBvYmplY3Qgd2l0aCB0aGUgbmV3IHBhcmFtZXRlcnMgYW5kIHJlLXJlcXVlc3RzIHRpbGVzIG9uIHRoZSBjdXJyZW50IHNjcmVlbiAodW5sZXNzIGBub1JlZHJhd2Agd2FzIHNldCB0byB0cnVlKS5cclxuICBcdHNldFBhcmFtczogZnVuY3Rpb24gKHBhcmFtcywgbm9SZWRyYXcpIHtcclxuXHJcbiAgXHRcdGV4dGVuZCh0aGlzLndtc1BhcmFtcywgcGFyYW1zKTtcclxuXHJcbiAgXHRcdGlmICghbm9SZWRyYXcpIHtcclxuICBcdFx0XHR0aGlzLnJlZHJhdygpO1xyXG4gIFx0XHR9XHJcblxyXG4gIFx0XHRyZXR1cm4gdGhpcztcclxuICBcdH1cclxuICB9KTtcclxuXHJcblxyXG4gIC8vIEBmYWN0b3J5IEwudGlsZUxheWVyLndtcyhiYXNlVXJsOiBTdHJpbmcsIG9wdGlvbnM6IFRpbGVMYXllci5XTVMgb3B0aW9ucylcclxuICAvLyBJbnN0YW50aWF0ZXMgYSBXTVMgdGlsZSBsYXllciBvYmplY3QgZ2l2ZW4gYSBiYXNlIFVSTCBvZiB0aGUgV01TIHNlcnZpY2UgYW5kIGEgV01TIHBhcmFtZXRlcnMvb3B0aW9ucyBvYmplY3QuXHJcbiAgZnVuY3Rpb24gdGlsZUxheWVyV01TKHVybCwgb3B0aW9ucykge1xyXG4gIFx0cmV0dXJuIG5ldyBUaWxlTGF5ZXJXTVModXJsLCBvcHRpb25zKTtcclxuICB9XG5cbiAgVGlsZUxheWVyLldNUyA9IFRpbGVMYXllcldNUztcbiAgdGlsZUxheWVyLndtcyA9IHRpbGVMYXllcldNUztcblxuICAvKlxuICAgKiBAY2xhc3MgUmVuZGVyZXJcbiAgICogQGluaGVyaXRzIExheWVyXG4gICAqIEBha2EgTC5SZW5kZXJlclxuICAgKlxuICAgKiBCYXNlIGNsYXNzIGZvciB2ZWN0b3IgcmVuZGVyZXIgaW1wbGVtZW50YXRpb25zIChgU1ZHYCwgYENhbnZhc2ApLiBIYW5kbGVzIHRoZVxuICAgKiBET00gY29udGFpbmVyIG9mIHRoZSByZW5kZXJlciwgaXRzIGJvdW5kcywgYW5kIGl0cyB6b29tIGFuaW1hdGlvbi5cbiAgICpcbiAgICogQSBgUmVuZGVyZXJgIHdvcmtzIGFzIGFuIGltcGxpY2l0IGxheWVyIGdyb3VwIGZvciBhbGwgYFBhdGhgcyAtIHRoZSByZW5kZXJlclxuICAgKiBpdHNlbGYgY2FuIGJlIGFkZGVkIG9yIHJlbW92ZWQgdG8gdGhlIG1hcC4gQWxsIHBhdGhzIHVzZSBhIHJlbmRlcmVyLCB3aGljaCBjYW5cbiAgICogYmUgaW1wbGljaXQgKHRoZSBtYXAgd2lsbCBkZWNpZGUgdGhlIHR5cGUgb2YgcmVuZGVyZXIgYW5kIHVzZSBpdCBhdXRvbWF0aWNhbGx5KVxuICAgKiBvciBleHBsaWNpdCAodXNpbmcgdGhlIFtgcmVuZGVyZXJgXSgjcGF0aC1yZW5kZXJlcikgb3B0aW9uIG9mIHRoZSBwYXRoKS5cbiAgICpcbiAgICogRG8gbm90IHVzZSB0aGlzIGNsYXNzIGRpcmVjdGx5LCB1c2UgYFNWR2AgYW5kIGBDYW52YXNgIGluc3RlYWQuXG4gICAqXG4gICAqIEBldmVudCB1cGRhdGU6IEV2ZW50XG4gICAqIEZpcmVkIHdoZW4gdGhlIHJlbmRlcmVyIHVwZGF0ZXMgaXRzIGJvdW5kcywgY2VudGVyIGFuZCB6b29tLCBmb3IgZXhhbXBsZSB3aGVuXG4gICAqIGl0cyBtYXAgaGFzIG1vdmVkXG4gICAqL1xuXG4gIHZhciBSZW5kZXJlciA9IExheWVyLmV4dGVuZCh7XG5cbiAgXHQvLyBAc2VjdGlvblxuICBcdC8vIEBha2EgUmVuZGVyZXIgb3B0aW9uc1xuICBcdG9wdGlvbnM6IHtcbiAgXHRcdC8vIEBvcHRpb24gcGFkZGluZzogTnVtYmVyID0gMC4xXG4gIFx0XHQvLyBIb3cgbXVjaCB0byBleHRlbmQgdGhlIGNsaXAgYXJlYSBhcm91bmQgdGhlIG1hcCB2aWV3IChyZWxhdGl2ZSB0byBpdHMgc2l6ZSlcbiAgXHRcdC8vIGUuZy4gMC4xIHdvdWxkIGJlIDEwJSBvZiBtYXAgdmlldyBpbiBlYWNoIGRpcmVjdGlvblxuICBcdFx0cGFkZGluZzogMC4xXG4gIFx0fSxcblxuICBcdGluaXRpYWxpemU6IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gIFx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xuICBcdFx0c3RhbXAodGhpcyk7XG4gIFx0XHR0aGlzLl9sYXllcnMgPSB0aGlzLl9sYXllcnMgfHwge307XG4gIFx0fSxcblxuICBcdG9uQWRkOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRpZiAoIXRoaXMuX2NvbnRhaW5lcikge1xuICBcdFx0XHR0aGlzLl9pbml0Q29udGFpbmVyKCk7IC8vIGRlZmluZWQgYnkgcmVuZGVyZXIgaW1wbGVtZW50YXRpb25zXG5cbiAgXHRcdFx0Ly8gYWx3YXlzIGtlZXAgdHJhbnNmb3JtLW9yaWdpbiBhcyAwIDBcbiAgXHRcdFx0YWRkQ2xhc3ModGhpcy5fY29udGFpbmVyLCAnbGVhZmxldC16b29tLWFuaW1hdGVkJyk7XG4gIFx0XHR9XG5cbiAgXHRcdHRoaXMuZ2V0UGFuZSgpLmFwcGVuZENoaWxkKHRoaXMuX2NvbnRhaW5lcik7XG4gIFx0XHR0aGlzLl91cGRhdGUoKTtcbiAgXHRcdHRoaXMub24oJ3VwZGF0ZScsIHRoaXMuX3VwZGF0ZVBhdGhzLCB0aGlzKTtcbiAgXHR9LFxuXG4gIFx0b25SZW1vdmU6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHRoaXMub2ZmKCd1cGRhdGUnLCB0aGlzLl91cGRhdGVQYXRocywgdGhpcyk7XG4gIFx0XHR0aGlzLl9kZXN0cm95Q29udGFpbmVyKCk7XG4gIFx0fSxcblxuICBcdGdldEV2ZW50czogZnVuY3Rpb24gKCkge1xuICBcdFx0dmFyIGV2ZW50cyA9IHtcbiAgXHRcdFx0dmlld3Jlc2V0OiB0aGlzLl9yZXNldCxcbiAgXHRcdFx0em9vbTogdGhpcy5fb25ab29tLFxuICBcdFx0XHRtb3ZlZW5kOiB0aGlzLl91cGRhdGUsXG4gIFx0XHRcdHpvb21lbmQ6IHRoaXMuX29uWm9vbUVuZFxuICBcdFx0fTtcbiAgXHRcdGlmICh0aGlzLl96b29tQW5pbWF0ZWQpIHtcbiAgXHRcdFx0ZXZlbnRzLnpvb21hbmltID0gdGhpcy5fb25BbmltWm9vbTtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiBldmVudHM7XG4gIFx0fSxcblxuICBcdF9vbkFuaW1ab29tOiBmdW5jdGlvbiAoZXYpIHtcbiAgXHRcdHRoaXMuX3VwZGF0ZVRyYW5zZm9ybShldi5jZW50ZXIsIGV2Lnpvb20pO1xuICBcdH0sXG5cbiAgXHRfb25ab29tOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR0aGlzLl91cGRhdGVUcmFuc2Zvcm0odGhpcy5fbWFwLmdldENlbnRlcigpLCB0aGlzLl9tYXAuZ2V0Wm9vbSgpKTtcbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZVRyYW5zZm9ybTogZnVuY3Rpb24gKGNlbnRlciwgem9vbSkge1xuICBcdFx0dmFyIHNjYWxlID0gdGhpcy5fbWFwLmdldFpvb21TY2FsZSh6b29tLCB0aGlzLl96b29tKSxcbiAgXHRcdCAgICB2aWV3SGFsZiA9IHRoaXMuX21hcC5nZXRTaXplKCkubXVsdGlwbHlCeSgwLjUgKyB0aGlzLm9wdGlvbnMucGFkZGluZyksXG4gIFx0XHQgICAgY3VycmVudENlbnRlclBvaW50ID0gdGhpcy5fbWFwLnByb2plY3QodGhpcy5fY2VudGVyLCB6b29tKSxcblxuICBcdFx0ICAgIHRvcExlZnRPZmZzZXQgPSB2aWV3SGFsZi5tdWx0aXBseUJ5KC1zY2FsZSkuYWRkKGN1cnJlbnRDZW50ZXJQb2ludClcbiAgXHRcdFx0XHQgIC5zdWJ0cmFjdCh0aGlzLl9tYXAuX2dldE5ld1BpeGVsT3JpZ2luKGNlbnRlciwgem9vbSkpO1xuXG4gIFx0XHRpZiAoQnJvd3Nlci5hbnkzZCkge1xuICBcdFx0XHRzZXRUcmFuc2Zvcm0odGhpcy5fY29udGFpbmVyLCB0b3BMZWZ0T2Zmc2V0LCBzY2FsZSk7XG4gIFx0XHR9IGVsc2Uge1xuICBcdFx0XHRzZXRQb3NpdGlvbih0aGlzLl9jb250YWluZXIsIHRvcExlZnRPZmZzZXQpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfcmVzZXQ6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHRoaXMuX3VwZGF0ZSgpO1xuICBcdFx0dGhpcy5fdXBkYXRlVHJhbnNmb3JtKHRoaXMuX2NlbnRlciwgdGhpcy5fem9vbSk7XG5cbiAgXHRcdGZvciAodmFyIGlkIGluIHRoaXMuX2xheWVycykge1xuICBcdFx0XHR0aGlzLl9sYXllcnNbaWRdLl9yZXNldCgpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfb25ab29tRW5kOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRmb3IgKHZhciBpZCBpbiB0aGlzLl9sYXllcnMpIHtcbiAgXHRcdFx0dGhpcy5fbGF5ZXJzW2lkXS5fcHJvamVjdCgpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfdXBkYXRlUGF0aHM6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGZvciAodmFyIGlkIGluIHRoaXMuX2xheWVycykge1xuICBcdFx0XHR0aGlzLl9sYXllcnNbaWRdLl91cGRhdGUoKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZTogZnVuY3Rpb24gKCkge1xuICBcdFx0Ly8gVXBkYXRlIHBpeGVsIGJvdW5kcyBvZiByZW5kZXJlciBjb250YWluZXIgKGZvciBwb3NpdGlvbmluZy9zaXppbmcvY2xpcHBpbmcgbGF0ZXIpXG4gIFx0XHQvLyBTdWJjbGFzc2VzIGFyZSByZXNwb25zaWJsZSBvZiBmaXJpbmcgdGhlICd1cGRhdGUnIGV2ZW50LlxuICBcdFx0dmFyIHAgPSB0aGlzLm9wdGlvbnMucGFkZGluZyxcbiAgXHRcdCAgICBzaXplID0gdGhpcy5fbWFwLmdldFNpemUoKSxcbiAgXHRcdCAgICBtaW4gPSB0aGlzLl9tYXAuY29udGFpbmVyUG9pbnRUb0xheWVyUG9pbnQoc2l6ZS5tdWx0aXBseUJ5KC1wKSkucm91bmQoKTtcblxuICBcdFx0dGhpcy5fYm91bmRzID0gbmV3IEJvdW5kcyhtaW4sIG1pbi5hZGQoc2l6ZS5tdWx0aXBseUJ5KDEgKyBwICogMikpLnJvdW5kKCkpO1xuXG4gIFx0XHR0aGlzLl9jZW50ZXIgPSB0aGlzLl9tYXAuZ2V0Q2VudGVyKCk7XG4gIFx0XHR0aGlzLl96b29tID0gdGhpcy5fbWFwLmdldFpvb20oKTtcbiAgXHR9XG4gIH0pO1xuXG4gIC8qXG4gICAqIEBjbGFzcyBDYW52YXNcbiAgICogQGluaGVyaXRzIFJlbmRlcmVyXG4gICAqIEBha2EgTC5DYW52YXNcbiAgICpcbiAgICogQWxsb3dzIHZlY3RvciBsYXllcnMgdG8gYmUgZGlzcGxheWVkIHdpdGggW2A8Y2FudmFzPmBdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0FQSS9DYW52YXNfQVBJKS5cbiAgICogSW5oZXJpdHMgYFJlbmRlcmVyYC5cbiAgICpcbiAgICogRHVlIHRvIFt0ZWNobmljYWwgbGltaXRhdGlvbnNdKGh0dHBzOi8vY2FuaXVzZS5jb20vY2FudmFzKSwgQ2FudmFzIGlzIG5vdFxuICAgKiBhdmFpbGFibGUgaW4gYWxsIHdlYiBicm93c2Vycywgbm90YWJseSBJRTgsIGFuZCBvdmVybGFwcGluZyBnZW9tZXRyaWVzIG1pZ2h0XG4gICAqIG5vdCBkaXNwbGF5IHByb3Blcmx5IGluIHNvbWUgZWRnZSBjYXNlcy5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICpcbiAgICogVXNlIENhbnZhcyBieSBkZWZhdWx0IGZvciBhbGwgcGF0aHMgaW4gdGhlIG1hcDpcbiAgICpcbiAgICogYGBganNcbiAgICogdmFyIG1hcCA9IEwubWFwKCdtYXAnLCB7XG4gICAqIFx0cmVuZGVyZXI6IEwuY2FudmFzKClcbiAgICogfSk7XG4gICAqIGBgYFxuICAgKlxuICAgKiBVc2UgYSBDYW52YXMgcmVuZGVyZXIgd2l0aCBleHRyYSBwYWRkaW5nIGZvciBzcGVjaWZpYyB2ZWN0b3IgZ2VvbWV0cmllczpcbiAgICpcbiAgICogYGBganNcbiAgICogdmFyIG1hcCA9IEwubWFwKCdtYXAnKTtcbiAgICogdmFyIG15UmVuZGVyZXIgPSBMLmNhbnZhcyh7IHBhZGRpbmc6IDAuNSB9KTtcbiAgICogdmFyIGxpbmUgPSBMLnBvbHlsaW5lKCBjb29yZGluYXRlcywgeyByZW5kZXJlcjogbXlSZW5kZXJlciB9ICk7XG4gICAqIHZhciBjaXJjbGUgPSBMLmNpcmNsZSggY2VudGVyLCB7IHJlbmRlcmVyOiBteVJlbmRlcmVyIH0gKTtcbiAgICogYGBgXG4gICAqL1xuXG4gIHZhciBDYW52YXMgPSBSZW5kZXJlci5leHRlbmQoe1xuXG4gIFx0Ly8gQHNlY3Rpb25cbiAgXHQvLyBAYWthIENhbnZhcyBvcHRpb25zXG4gIFx0b3B0aW9uczoge1xuICBcdFx0Ly8gQG9wdGlvbiB0b2xlcmFuY2U6IE51bWJlciA9IDBcbiAgXHRcdC8vIEhvdyBtdWNoIHRvIGV4dGVuZCB0aGUgY2xpY2sgdG9sZXJhbmNlIGFyb3VuZCBhIHBhdGgvb2JqZWN0IG9uIHRoZSBtYXAuXG4gIFx0XHR0b2xlcmFuY2U6IDBcbiAgXHR9LFxuXG4gIFx0Z2V0RXZlbnRzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR2YXIgZXZlbnRzID0gUmVuZGVyZXIucHJvdG90eXBlLmdldEV2ZW50cy5jYWxsKHRoaXMpO1xuICBcdFx0ZXZlbnRzLnZpZXdwcmVyZXNldCA9IHRoaXMuX29uVmlld1ByZVJlc2V0O1xuICBcdFx0cmV0dXJuIGV2ZW50cztcbiAgXHR9LFxuXG4gIFx0X29uVmlld1ByZVJlc2V0OiBmdW5jdGlvbiAoKSB7XG4gIFx0XHQvLyBTZXQgYSBmbGFnIHNvIHRoYXQgYSB2aWV3cHJlcmVzZXQrbW92ZWVuZCt2aWV3cmVzZXQgb25seSB1cGRhdGVzJnJlZHJhd3Mgb25jZVxuICBcdFx0dGhpcy5fcG9zdHBvbmVVcGRhdGVQYXRocyA9IHRydWU7XG4gIFx0fSxcblxuICBcdG9uQWRkOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRSZW5kZXJlci5wcm90b3R5cGUub25BZGQuY2FsbCh0aGlzKTtcblxuICBcdFx0Ly8gUmVkcmF3IHZlY3RvcnMgc2luY2UgY2FudmFzIGlzIGNsZWFyZWQgdXBvbiByZW1vdmFsLFxuICBcdFx0Ly8gaW4gY2FzZSBvZiByZW1vdmluZyB0aGUgcmVuZGVyZXIgaXRzZWxmIGZyb20gdGhlIG1hcC5cbiAgXHRcdHRoaXMuX2RyYXcoKTtcbiAgXHR9LFxuXG4gIFx0X2luaXRDb250YWluZXI6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHZhciBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcblxuICBcdFx0b24oY29udGFpbmVyLCAnbW91c2Vtb3ZlJywgdGhpcy5fb25Nb3VzZU1vdmUsIHRoaXMpO1xuICBcdFx0b24oY29udGFpbmVyLCAnY2xpY2sgZGJsY2xpY2sgbW91c2Vkb3duIG1vdXNldXAgY29udGV4dG1lbnUnLCB0aGlzLl9vbkNsaWNrLCB0aGlzKTtcbiAgXHRcdG9uKGNvbnRhaW5lciwgJ21vdXNlb3V0JywgdGhpcy5faGFuZGxlTW91c2VPdXQsIHRoaXMpO1xuICBcdFx0Y29udGFpbmVyWydfbGVhZmxldF9kaXNhYmxlX2V2ZW50cyddID0gdHJ1ZTtcblxuICBcdFx0dGhpcy5fY3R4ID0gY29udGFpbmVyLmdldENvbnRleHQoJzJkJyk7XG4gIFx0fSxcblxuICBcdF9kZXN0cm95Q29udGFpbmVyOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRjYW5jZWxBbmltRnJhbWUodGhpcy5fcmVkcmF3UmVxdWVzdCk7XG4gIFx0XHRkZWxldGUgdGhpcy5fY3R4O1xuICBcdFx0cmVtb3ZlKHRoaXMuX2NvbnRhaW5lcik7XG4gIFx0XHRvZmYodGhpcy5fY29udGFpbmVyKTtcbiAgXHRcdGRlbGV0ZSB0aGlzLl9jb250YWluZXI7XG4gIFx0fSxcblxuICBcdF91cGRhdGVQYXRoczogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKHRoaXMuX3Bvc3Rwb25lVXBkYXRlUGF0aHMpIHsgcmV0dXJuOyB9XG5cbiAgXHRcdHZhciBsYXllcjtcbiAgXHRcdHRoaXMuX3JlZHJhd0JvdW5kcyA9IG51bGw7XG4gIFx0XHRmb3IgKHZhciBpZCBpbiB0aGlzLl9sYXllcnMpIHtcbiAgXHRcdFx0bGF5ZXIgPSB0aGlzLl9sYXllcnNbaWRdO1xuICBcdFx0XHRsYXllci5fdXBkYXRlKCk7XG4gIFx0XHR9XG4gIFx0XHR0aGlzLl9yZWRyYXcoKTtcbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZTogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKHRoaXMuX21hcC5fYW5pbWF0aW5nWm9vbSAmJiB0aGlzLl9ib3VuZHMpIHsgcmV0dXJuOyB9XG5cbiAgXHRcdFJlbmRlcmVyLnByb3RvdHlwZS5fdXBkYXRlLmNhbGwodGhpcyk7XG5cbiAgXHRcdHZhciBiID0gdGhpcy5fYm91bmRzLFxuICBcdFx0ICAgIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRhaW5lcixcbiAgXHRcdCAgICBzaXplID0gYi5nZXRTaXplKCksXG4gIFx0XHQgICAgbSA9IEJyb3dzZXIucmV0aW5hID8gMiA6IDE7XG5cbiAgXHRcdHNldFBvc2l0aW9uKGNvbnRhaW5lciwgYi5taW4pO1xuXG4gIFx0XHQvLyBzZXQgY2FudmFzIHNpemUgKGFsc28gY2xlYXJpbmcgaXQpOyB1c2UgZG91YmxlIHNpemUgb24gcmV0aW5hXG4gIFx0XHRjb250YWluZXIud2lkdGggPSBtICogc2l6ZS54O1xuICBcdFx0Y29udGFpbmVyLmhlaWdodCA9IG0gKiBzaXplLnk7XG4gIFx0XHRjb250YWluZXIuc3R5bGUud2lkdGggPSBzaXplLnggKyAncHgnO1xuICBcdFx0Y29udGFpbmVyLnN0eWxlLmhlaWdodCA9IHNpemUueSArICdweCc7XG5cbiAgXHRcdGlmIChCcm93c2VyLnJldGluYSkge1xuICBcdFx0XHR0aGlzLl9jdHguc2NhbGUoMiwgMik7XG4gIFx0XHR9XG5cbiAgXHRcdC8vIHRyYW5zbGF0ZSBzbyB3ZSB1c2UgdGhlIHNhbWUgcGF0aCBjb29yZGluYXRlcyBhZnRlciBjYW52YXMgZWxlbWVudCBtb3Zlc1xuICBcdFx0dGhpcy5fY3R4LnRyYW5zbGF0ZSgtYi5taW4ueCwgLWIubWluLnkpO1xuXG4gIFx0XHQvLyBUZWxsIHBhdGhzIHRvIHJlZHJhdyB0aGVtc2VsdmVzXG4gIFx0XHR0aGlzLmZpcmUoJ3VwZGF0ZScpO1xuICBcdH0sXG5cbiAgXHRfcmVzZXQ6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdFJlbmRlcmVyLnByb3RvdHlwZS5fcmVzZXQuY2FsbCh0aGlzKTtcblxuICBcdFx0aWYgKHRoaXMuX3Bvc3Rwb25lVXBkYXRlUGF0aHMpIHtcbiAgXHRcdFx0dGhpcy5fcG9zdHBvbmVVcGRhdGVQYXRocyA9IGZhbHNlO1xuICBcdFx0XHR0aGlzLl91cGRhdGVQYXRocygpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfaW5pdFBhdGg6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0dGhpcy5fdXBkYXRlRGFzaEFycmF5KGxheWVyKTtcbiAgXHRcdHRoaXMuX2xheWVyc1tzdGFtcChsYXllcildID0gbGF5ZXI7XG5cbiAgXHRcdHZhciBvcmRlciA9IGxheWVyLl9vcmRlciA9IHtcbiAgXHRcdFx0bGF5ZXI6IGxheWVyLFxuICBcdFx0XHRwcmV2OiB0aGlzLl9kcmF3TGFzdCxcbiAgXHRcdFx0bmV4dDogbnVsbFxuICBcdFx0fTtcbiAgXHRcdGlmICh0aGlzLl9kcmF3TGFzdCkgeyB0aGlzLl9kcmF3TGFzdC5uZXh0ID0gb3JkZXI7IH1cbiAgXHRcdHRoaXMuX2RyYXdMYXN0ID0gb3JkZXI7XG4gIFx0XHR0aGlzLl9kcmF3Rmlyc3QgPSB0aGlzLl9kcmF3Rmlyc3QgfHwgdGhpcy5fZHJhd0xhc3Q7XG4gIFx0fSxcblxuICBcdF9hZGRQYXRoOiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdHRoaXMuX3JlcXVlc3RSZWRyYXcobGF5ZXIpO1xuICBcdH0sXG5cbiAgXHRfcmVtb3ZlUGF0aDogZnVuY3Rpb24gKGxheWVyKSB7XG4gIFx0XHR2YXIgb3JkZXIgPSBsYXllci5fb3JkZXI7XG4gIFx0XHR2YXIgbmV4dCA9IG9yZGVyLm5leHQ7XG4gIFx0XHR2YXIgcHJldiA9IG9yZGVyLnByZXY7XG5cbiAgXHRcdGlmIChuZXh0KSB7XG4gIFx0XHRcdG5leHQucHJldiA9IHByZXY7XG4gIFx0XHR9IGVsc2Uge1xuICBcdFx0XHR0aGlzLl9kcmF3TGFzdCA9IHByZXY7XG4gIFx0XHR9XG4gIFx0XHRpZiAocHJldikge1xuICBcdFx0XHRwcmV2Lm5leHQgPSBuZXh0O1xuICBcdFx0fSBlbHNlIHtcbiAgXHRcdFx0dGhpcy5fZHJhd0ZpcnN0ID0gbmV4dDtcbiAgXHRcdH1cblxuICBcdFx0ZGVsZXRlIGxheWVyLl9vcmRlcjtcblxuICBcdFx0ZGVsZXRlIHRoaXMuX2xheWVyc1tzdGFtcChsYXllcildO1xuXG4gIFx0XHR0aGlzLl9yZXF1ZXN0UmVkcmF3KGxheWVyKTtcbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZVBhdGg6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0Ly8gUmVkcmF3IHRoZSB1bmlvbiBvZiB0aGUgbGF5ZXIncyBvbGQgcGl4ZWxcbiAgXHRcdC8vIGJvdW5kcyBhbmQgdGhlIG5ldyBwaXhlbCBib3VuZHMuXG4gIFx0XHR0aGlzLl9leHRlbmRSZWRyYXdCb3VuZHMobGF5ZXIpO1xuICBcdFx0bGF5ZXIuX3Byb2plY3QoKTtcbiAgXHRcdGxheWVyLl91cGRhdGUoKTtcbiAgXHRcdC8vIFRoZSByZWRyYXcgd2lsbCBleHRlbmQgdGhlIHJlZHJhdyBib3VuZHNcbiAgXHRcdC8vIHdpdGggdGhlIG5ldyBwaXhlbCBib3VuZHMuXG4gIFx0XHR0aGlzLl9yZXF1ZXN0UmVkcmF3KGxheWVyKTtcbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZVN0eWxlOiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdHRoaXMuX3VwZGF0ZURhc2hBcnJheShsYXllcik7XG4gIFx0XHR0aGlzLl9yZXF1ZXN0UmVkcmF3KGxheWVyKTtcbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZURhc2hBcnJheTogZnVuY3Rpb24gKGxheWVyKSB7XG4gIFx0XHRpZiAodHlwZW9mIGxheWVyLm9wdGlvbnMuZGFzaEFycmF5ID09PSAnc3RyaW5nJykge1xuICBcdFx0XHR2YXIgcGFydHMgPSBsYXllci5vcHRpb25zLmRhc2hBcnJheS5zcGxpdCgvWywgXSsvKSxcbiAgXHRcdFx0ICAgIGRhc2hBcnJheSA9IFtdLFxuICBcdFx0XHQgICAgZGFzaFZhbHVlLFxuICBcdFx0XHQgICAgaTtcbiAgXHRcdFx0Zm9yIChpID0gMDsgaSA8IHBhcnRzLmxlbmd0aDsgaSsrKSB7XG4gIFx0XHRcdFx0ZGFzaFZhbHVlID0gTnVtYmVyKHBhcnRzW2ldKTtcbiAgXHRcdFx0XHQvLyBJZ25vcmUgZGFzaCBhcnJheSBjb250YWluaW5nIGludmFsaWQgbGVuZ3Roc1xuICBcdFx0XHRcdGlmIChpc05hTihkYXNoVmFsdWUpKSB7IHJldHVybjsgfVxuICBcdFx0XHRcdGRhc2hBcnJheS5wdXNoKGRhc2hWYWx1ZSk7XG4gIFx0XHRcdH1cbiAgXHRcdFx0bGF5ZXIub3B0aW9ucy5fZGFzaEFycmF5ID0gZGFzaEFycmF5O1xuICBcdFx0fSBlbHNlIHtcbiAgXHRcdFx0bGF5ZXIub3B0aW9ucy5fZGFzaEFycmF5ID0gbGF5ZXIub3B0aW9ucy5kYXNoQXJyYXk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF9yZXF1ZXN0UmVkcmF3OiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdGlmICghdGhpcy5fbWFwKSB7IHJldHVybjsgfVxuXG4gIFx0XHR0aGlzLl9leHRlbmRSZWRyYXdCb3VuZHMobGF5ZXIpO1xuICBcdFx0dGhpcy5fcmVkcmF3UmVxdWVzdCA9IHRoaXMuX3JlZHJhd1JlcXVlc3QgfHwgcmVxdWVzdEFuaW1GcmFtZSh0aGlzLl9yZWRyYXcsIHRoaXMpO1xuICBcdH0sXG5cbiAgXHRfZXh0ZW5kUmVkcmF3Qm91bmRzOiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdGlmIChsYXllci5fcHhCb3VuZHMpIHtcbiAgXHRcdFx0dmFyIHBhZGRpbmcgPSAobGF5ZXIub3B0aW9ucy53ZWlnaHQgfHwgMCkgKyAxO1xuICBcdFx0XHR0aGlzLl9yZWRyYXdCb3VuZHMgPSB0aGlzLl9yZWRyYXdCb3VuZHMgfHwgbmV3IEJvdW5kcygpO1xuICBcdFx0XHR0aGlzLl9yZWRyYXdCb3VuZHMuZXh0ZW5kKGxheWVyLl9weEJvdW5kcy5taW4uc3VidHJhY3QoW3BhZGRpbmcsIHBhZGRpbmddKSk7XG4gIFx0XHRcdHRoaXMuX3JlZHJhd0JvdW5kcy5leHRlbmQobGF5ZXIuX3B4Qm91bmRzLm1heC5hZGQoW3BhZGRpbmcsIHBhZGRpbmddKSk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF9yZWRyYXc6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHRoaXMuX3JlZHJhd1JlcXVlc3QgPSBudWxsO1xuXG4gIFx0XHRpZiAodGhpcy5fcmVkcmF3Qm91bmRzKSB7XG4gIFx0XHRcdHRoaXMuX3JlZHJhd0JvdW5kcy5taW4uX2Zsb29yKCk7XG4gIFx0XHRcdHRoaXMuX3JlZHJhd0JvdW5kcy5tYXguX2NlaWwoKTtcbiAgXHRcdH1cblxuICBcdFx0dGhpcy5fY2xlYXIoKTsgLy8gY2xlYXIgbGF5ZXJzIGluIHJlZHJhdyBib3VuZHNcbiAgXHRcdHRoaXMuX2RyYXcoKTsgLy8gZHJhdyBsYXllcnNcblxuICBcdFx0dGhpcy5fcmVkcmF3Qm91bmRzID0gbnVsbDtcbiAgXHR9LFxuXG4gIFx0X2NsZWFyOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR2YXIgYm91bmRzID0gdGhpcy5fcmVkcmF3Qm91bmRzO1xuICBcdFx0aWYgKGJvdW5kcykge1xuICBcdFx0XHR2YXIgc2l6ZSA9IGJvdW5kcy5nZXRTaXplKCk7XG4gIFx0XHRcdHRoaXMuX2N0eC5jbGVhclJlY3QoYm91bmRzLm1pbi54LCBib3VuZHMubWluLnksIHNpemUueCwgc2l6ZS55KTtcbiAgXHRcdH0gZWxzZSB7XG4gIFx0XHRcdHRoaXMuX2N0eC5zYXZlKCk7XG4gIFx0XHRcdHRoaXMuX2N0eC5zZXRUcmFuc2Zvcm0oMSwgMCwgMCwgMSwgMCwgMCk7XG4gIFx0XHRcdHRoaXMuX2N0eC5jbGVhclJlY3QoMCwgMCwgdGhpcy5fY29udGFpbmVyLndpZHRoLCB0aGlzLl9jb250YWluZXIuaGVpZ2h0KTtcbiAgXHRcdFx0dGhpcy5fY3R4LnJlc3RvcmUoKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X2RyYXc6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHZhciBsYXllciwgYm91bmRzID0gdGhpcy5fcmVkcmF3Qm91bmRzO1xuICBcdFx0dGhpcy5fY3R4LnNhdmUoKTtcbiAgXHRcdGlmIChib3VuZHMpIHtcbiAgXHRcdFx0dmFyIHNpemUgPSBib3VuZHMuZ2V0U2l6ZSgpO1xuICBcdFx0XHR0aGlzLl9jdHguYmVnaW5QYXRoKCk7XG4gIFx0XHRcdHRoaXMuX2N0eC5yZWN0KGJvdW5kcy5taW4ueCwgYm91bmRzLm1pbi55LCBzaXplLngsIHNpemUueSk7XG4gIFx0XHRcdHRoaXMuX2N0eC5jbGlwKCk7XG4gIFx0XHR9XG5cbiAgXHRcdHRoaXMuX2RyYXdpbmcgPSB0cnVlO1xuXG4gIFx0XHRmb3IgKHZhciBvcmRlciA9IHRoaXMuX2RyYXdGaXJzdDsgb3JkZXI7IG9yZGVyID0gb3JkZXIubmV4dCkge1xuICBcdFx0XHRsYXllciA9IG9yZGVyLmxheWVyO1xuICBcdFx0XHRpZiAoIWJvdW5kcyB8fCAobGF5ZXIuX3B4Qm91bmRzICYmIGxheWVyLl9weEJvdW5kcy5pbnRlcnNlY3RzKGJvdW5kcykpKSB7XG4gIFx0XHRcdFx0bGF5ZXIuX3VwZGF0ZVBhdGgoKTtcbiAgXHRcdFx0fVxuICBcdFx0fVxuXG4gIFx0XHR0aGlzLl9kcmF3aW5nID0gZmFsc2U7XG5cbiAgXHRcdHRoaXMuX2N0eC5yZXN0b3JlKCk7ICAvLyBSZXN0b3JlIHN0YXRlIGJlZm9yZSBjbGlwcGluZy5cbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZVBvbHk6IGZ1bmN0aW9uIChsYXllciwgY2xvc2VkKSB7XG4gIFx0XHRpZiAoIXRoaXMuX2RyYXdpbmcpIHsgcmV0dXJuOyB9XG5cbiAgXHRcdHZhciBpLCBqLCBsZW4yLCBwLFxuICBcdFx0ICAgIHBhcnRzID0gbGF5ZXIuX3BhcnRzLFxuICBcdFx0ICAgIGxlbiA9IHBhcnRzLmxlbmd0aCxcbiAgXHRcdCAgICBjdHggPSB0aGlzLl9jdHg7XG5cbiAgXHRcdGlmICghbGVuKSB7IHJldHVybjsgfVxuXG4gIFx0XHRjdHguYmVnaW5QYXRoKCk7XG5cbiAgXHRcdGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICBcdFx0XHRmb3IgKGogPSAwLCBsZW4yID0gcGFydHNbaV0ubGVuZ3RoOyBqIDwgbGVuMjsgaisrKSB7XG4gIFx0XHRcdFx0cCA9IHBhcnRzW2ldW2pdO1xuICBcdFx0XHRcdGN0eFtqID8gJ2xpbmVUbycgOiAnbW92ZVRvJ10ocC54LCBwLnkpO1xuICBcdFx0XHR9XG4gIFx0XHRcdGlmIChjbG9zZWQpIHtcbiAgXHRcdFx0XHRjdHguY2xvc2VQYXRoKCk7XG4gIFx0XHRcdH1cbiAgXHRcdH1cblxuICBcdFx0dGhpcy5fZmlsbFN0cm9rZShjdHgsIGxheWVyKTtcblxuICBcdFx0Ly8gVE9ETyBvcHRpbWl6YXRpb246IDEgZmlsbC9zdHJva2UgZm9yIGFsbCBmZWF0dXJlcyB3aXRoIGVxdWFsIHN0eWxlIGluc3RlYWQgb2YgMSBmb3IgZWFjaCBmZWF0dXJlXG4gIFx0fSxcblxuICBcdF91cGRhdGVDaXJjbGU6IGZ1bmN0aW9uIChsYXllcikge1xuXG4gIFx0XHRpZiAoIXRoaXMuX2RyYXdpbmcgfHwgbGF5ZXIuX2VtcHR5KCkpIHsgcmV0dXJuOyB9XG5cbiAgXHRcdHZhciBwID0gbGF5ZXIuX3BvaW50LFxuICBcdFx0ICAgIGN0eCA9IHRoaXMuX2N0eCxcbiAgXHRcdCAgICByID0gTWF0aC5tYXgoTWF0aC5yb3VuZChsYXllci5fcmFkaXVzKSwgMSksXG4gIFx0XHQgICAgcyA9IChNYXRoLm1heChNYXRoLnJvdW5kKGxheWVyLl9yYWRpdXNZKSwgMSkgfHwgcikgLyByO1xuXG4gIFx0XHRpZiAocyAhPT0gMSkge1xuICBcdFx0XHRjdHguc2F2ZSgpO1xuICBcdFx0XHRjdHguc2NhbGUoMSwgcyk7XG4gIFx0XHR9XG5cbiAgXHRcdGN0eC5iZWdpblBhdGgoKTtcbiAgXHRcdGN0eC5hcmMocC54LCBwLnkgLyBzLCByLCAwLCBNYXRoLlBJICogMiwgZmFsc2UpO1xuXG4gIFx0XHRpZiAocyAhPT0gMSkge1xuICBcdFx0XHRjdHgucmVzdG9yZSgpO1xuICBcdFx0fVxuXG4gIFx0XHR0aGlzLl9maWxsU3Ryb2tlKGN0eCwgbGF5ZXIpO1xuICBcdH0sXG5cbiAgXHRfZmlsbFN0cm9rZTogZnVuY3Rpb24gKGN0eCwgbGF5ZXIpIHtcbiAgXHRcdHZhciBvcHRpb25zID0gbGF5ZXIub3B0aW9ucztcblxuICBcdFx0aWYgKG9wdGlvbnMuZmlsbCkge1xuICBcdFx0XHRjdHguZ2xvYmFsQWxwaGEgPSBvcHRpb25zLmZpbGxPcGFjaXR5O1xuICBcdFx0XHRjdHguZmlsbFN0eWxlID0gb3B0aW9ucy5maWxsQ29sb3IgfHwgb3B0aW9ucy5jb2xvcjtcbiAgXHRcdFx0Y3R4LmZpbGwob3B0aW9ucy5maWxsUnVsZSB8fCAnZXZlbm9kZCcpO1xuICBcdFx0fVxuXG4gIFx0XHRpZiAob3B0aW9ucy5zdHJva2UgJiYgb3B0aW9ucy53ZWlnaHQgIT09IDApIHtcbiAgXHRcdFx0aWYgKGN0eC5zZXRMaW5lRGFzaCkge1xuICBcdFx0XHRcdGN0eC5zZXRMaW5lRGFzaChsYXllci5vcHRpb25zICYmIGxheWVyLm9wdGlvbnMuX2Rhc2hBcnJheSB8fCBbXSk7XG4gIFx0XHRcdH1cbiAgXHRcdFx0Y3R4Lmdsb2JhbEFscGhhID0gb3B0aW9ucy5vcGFjaXR5O1xuICBcdFx0XHRjdHgubGluZVdpZHRoID0gb3B0aW9ucy53ZWlnaHQ7XG4gIFx0XHRcdGN0eC5zdHJva2VTdHlsZSA9IG9wdGlvbnMuY29sb3I7XG4gIFx0XHRcdGN0eC5saW5lQ2FwID0gb3B0aW9ucy5saW5lQ2FwO1xuICBcdFx0XHRjdHgubGluZUpvaW4gPSBvcHRpb25zLmxpbmVKb2luO1xuICBcdFx0XHRjdHguc3Ryb2tlKCk7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdC8vIENhbnZhcyBvYnZpb3VzbHkgZG9lc24ndCBoYXZlIG1vdXNlIGV2ZW50cyBmb3IgaW5kaXZpZHVhbCBkcmF3biBvYmplY3RzLFxuICBcdC8vIHNvIHdlIGVtdWxhdGUgdGhhdCBieSBjYWxjdWxhdGluZyB3aGF0J3MgdW5kZXIgdGhlIG1vdXNlIG9uIG1vdXNlbW92ZS9jbGljayBtYW51YWxseVxuXG4gIFx0X29uQ2xpY2s6IGZ1bmN0aW9uIChlKSB7XG4gIFx0XHR2YXIgcG9pbnQgPSB0aGlzLl9tYXAubW91c2VFdmVudFRvTGF5ZXJQb2ludChlKSwgbGF5ZXIsIGNsaWNrZWRMYXllcjtcblxuICBcdFx0Zm9yICh2YXIgb3JkZXIgPSB0aGlzLl9kcmF3Rmlyc3Q7IG9yZGVyOyBvcmRlciA9IG9yZGVyLm5leHQpIHtcbiAgXHRcdFx0bGF5ZXIgPSBvcmRlci5sYXllcjtcbiAgXHRcdFx0aWYgKGxheWVyLm9wdGlvbnMuaW50ZXJhY3RpdmUgJiYgbGF5ZXIuX2NvbnRhaW5zUG9pbnQocG9pbnQpKSB7XG4gIFx0XHRcdFx0aWYgKCEoZS50eXBlID09PSAnY2xpY2snIHx8IGUudHlwZSA9PT0gJ3ByZWNsaWNrJykgfHwgIXRoaXMuX21hcC5fZHJhZ2dhYmxlTW92ZWQobGF5ZXIpKSB7XG4gIFx0XHRcdFx0XHRjbGlja2VkTGF5ZXIgPSBsYXllcjtcbiAgXHRcdFx0XHR9XG4gIFx0XHRcdH1cbiAgXHRcdH1cbiAgXHRcdHRoaXMuX2ZpcmVFdmVudChjbGlja2VkTGF5ZXIgPyBbY2xpY2tlZExheWVyXSA6IGZhbHNlLCBlKTtcbiAgXHR9LFxuXG4gIFx0X29uTW91c2VNb3ZlOiBmdW5jdGlvbiAoZSkge1xuICBcdFx0aWYgKCF0aGlzLl9tYXAgfHwgdGhpcy5fbWFwLmRyYWdnaW5nLm1vdmluZygpIHx8IHRoaXMuX21hcC5fYW5pbWF0aW5nWm9vbSkgeyByZXR1cm47IH1cblxuICBcdFx0dmFyIHBvaW50ID0gdGhpcy5fbWFwLm1vdXNlRXZlbnRUb0xheWVyUG9pbnQoZSk7XG4gIFx0XHR0aGlzLl9oYW5kbGVNb3VzZUhvdmVyKGUsIHBvaW50KTtcbiAgXHR9LFxuXG5cbiAgXHRfaGFuZGxlTW91c2VPdXQ6IGZ1bmN0aW9uIChlKSB7XG4gIFx0XHR2YXIgbGF5ZXIgPSB0aGlzLl9ob3ZlcmVkTGF5ZXI7XG4gIFx0XHRpZiAobGF5ZXIpIHtcbiAgXHRcdFx0Ly8gaWYgd2UncmUgbGVhdmluZyB0aGUgbGF5ZXIsIGZpcmUgbW91c2VvdXRcbiAgXHRcdFx0cmVtb3ZlQ2xhc3ModGhpcy5fY29udGFpbmVyLCAnbGVhZmxldC1pbnRlcmFjdGl2ZScpO1xuICBcdFx0XHR0aGlzLl9maXJlRXZlbnQoW2xheWVyXSwgZSwgJ21vdXNlb3V0Jyk7XG4gIFx0XHRcdHRoaXMuX2hvdmVyZWRMYXllciA9IG51bGw7XG4gIFx0XHRcdHRoaXMuX21vdXNlSG92ZXJUaHJvdHRsZWQgPSBmYWxzZTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X2hhbmRsZU1vdXNlSG92ZXI6IGZ1bmN0aW9uIChlLCBwb2ludCkge1xuICBcdFx0aWYgKHRoaXMuX21vdXNlSG92ZXJUaHJvdHRsZWQpIHtcbiAgXHRcdFx0cmV0dXJuO1xuICBcdFx0fVxuXG4gIFx0XHR2YXIgbGF5ZXIsIGNhbmRpZGF0ZUhvdmVyZWRMYXllcjtcblxuICBcdFx0Zm9yICh2YXIgb3JkZXIgPSB0aGlzLl9kcmF3Rmlyc3Q7IG9yZGVyOyBvcmRlciA9IG9yZGVyLm5leHQpIHtcbiAgXHRcdFx0bGF5ZXIgPSBvcmRlci5sYXllcjtcbiAgXHRcdFx0aWYgKGxheWVyLm9wdGlvbnMuaW50ZXJhY3RpdmUgJiYgbGF5ZXIuX2NvbnRhaW5zUG9pbnQocG9pbnQpKSB7XG4gIFx0XHRcdFx0Y2FuZGlkYXRlSG92ZXJlZExheWVyID0gbGF5ZXI7XG4gIFx0XHRcdH1cbiAgXHRcdH1cblxuICBcdFx0aWYgKGNhbmRpZGF0ZUhvdmVyZWRMYXllciAhPT0gdGhpcy5faG92ZXJlZExheWVyKSB7XG4gIFx0XHRcdHRoaXMuX2hhbmRsZU1vdXNlT3V0KGUpO1xuXG4gIFx0XHRcdGlmIChjYW5kaWRhdGVIb3ZlcmVkTGF5ZXIpIHtcbiAgXHRcdFx0XHRhZGRDbGFzcyh0aGlzLl9jb250YWluZXIsICdsZWFmbGV0LWludGVyYWN0aXZlJyk7IC8vIGNoYW5nZSBjdXJzb3JcbiAgXHRcdFx0XHR0aGlzLl9maXJlRXZlbnQoW2NhbmRpZGF0ZUhvdmVyZWRMYXllcl0sIGUsICdtb3VzZW92ZXInKTtcbiAgXHRcdFx0XHR0aGlzLl9ob3ZlcmVkTGF5ZXIgPSBjYW5kaWRhdGVIb3ZlcmVkTGF5ZXI7XG4gIFx0XHRcdH1cbiAgXHRcdH1cblxuICBcdFx0dGhpcy5fZmlyZUV2ZW50KHRoaXMuX2hvdmVyZWRMYXllciA/IFt0aGlzLl9ob3ZlcmVkTGF5ZXJdIDogZmFsc2UsIGUpO1xuXG4gIFx0XHR0aGlzLl9tb3VzZUhvdmVyVGhyb3R0bGVkID0gdHJ1ZTtcbiAgXHRcdHNldFRpbWVvdXQoYmluZChmdW5jdGlvbiAoKSB7XG4gIFx0XHRcdHRoaXMuX21vdXNlSG92ZXJUaHJvdHRsZWQgPSBmYWxzZTtcbiAgXHRcdH0sIHRoaXMpLCAzMik7XG4gIFx0fSxcblxuICBcdF9maXJlRXZlbnQ6IGZ1bmN0aW9uIChsYXllcnMsIGUsIHR5cGUpIHtcbiAgXHRcdHRoaXMuX21hcC5fZmlyZURPTUV2ZW50KGUsIHR5cGUgfHwgZS50eXBlLCBsYXllcnMpO1xuICBcdH0sXG5cbiAgXHRfYnJpbmdUb0Zyb250OiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdHZhciBvcmRlciA9IGxheWVyLl9vcmRlcjtcblxuICBcdFx0aWYgKCFvcmRlcikgeyByZXR1cm47IH1cblxuICBcdFx0dmFyIG5leHQgPSBvcmRlci5uZXh0O1xuICBcdFx0dmFyIHByZXYgPSBvcmRlci5wcmV2O1xuXG4gIFx0XHRpZiAobmV4dCkge1xuICBcdFx0XHRuZXh0LnByZXYgPSBwcmV2O1xuICBcdFx0fSBlbHNlIHtcbiAgXHRcdFx0Ly8gQWxyZWFkeSBsYXN0XG4gIFx0XHRcdHJldHVybjtcbiAgXHRcdH1cbiAgXHRcdGlmIChwcmV2KSB7XG4gIFx0XHRcdHByZXYubmV4dCA9IG5leHQ7XG4gIFx0XHR9IGVsc2UgaWYgKG5leHQpIHtcbiAgXHRcdFx0Ly8gVXBkYXRlIGZpcnN0IGVudHJ5IHVubGVzcyB0aGlzIGlzIHRoZVxuICBcdFx0XHQvLyBzaW5nbGUgZW50cnlcbiAgXHRcdFx0dGhpcy5fZHJhd0ZpcnN0ID0gbmV4dDtcbiAgXHRcdH1cblxuICBcdFx0b3JkZXIucHJldiA9IHRoaXMuX2RyYXdMYXN0O1xuICBcdFx0dGhpcy5fZHJhd0xhc3QubmV4dCA9IG9yZGVyO1xuXG4gIFx0XHRvcmRlci5uZXh0ID0gbnVsbDtcbiAgXHRcdHRoaXMuX2RyYXdMYXN0ID0gb3JkZXI7XG5cbiAgXHRcdHRoaXMuX3JlcXVlc3RSZWRyYXcobGF5ZXIpO1xuICBcdH0sXG5cbiAgXHRfYnJpbmdUb0JhY2s6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0dmFyIG9yZGVyID0gbGF5ZXIuX29yZGVyO1xuXG4gIFx0XHRpZiAoIW9yZGVyKSB7IHJldHVybjsgfVxuXG4gIFx0XHR2YXIgbmV4dCA9IG9yZGVyLm5leHQ7XG4gIFx0XHR2YXIgcHJldiA9IG9yZGVyLnByZXY7XG5cbiAgXHRcdGlmIChwcmV2KSB7XG4gIFx0XHRcdHByZXYubmV4dCA9IG5leHQ7XG4gIFx0XHR9IGVsc2Uge1xuICBcdFx0XHQvLyBBbHJlYWR5IGZpcnN0XG4gIFx0XHRcdHJldHVybjtcbiAgXHRcdH1cbiAgXHRcdGlmIChuZXh0KSB7XG4gIFx0XHRcdG5leHQucHJldiA9IHByZXY7XG4gIFx0XHR9IGVsc2UgaWYgKHByZXYpIHtcbiAgXHRcdFx0Ly8gVXBkYXRlIGxhc3QgZW50cnkgdW5sZXNzIHRoaXMgaXMgdGhlXG4gIFx0XHRcdC8vIHNpbmdsZSBlbnRyeVxuICBcdFx0XHR0aGlzLl9kcmF3TGFzdCA9IHByZXY7XG4gIFx0XHR9XG5cbiAgXHRcdG9yZGVyLnByZXYgPSBudWxsO1xuXG4gIFx0XHRvcmRlci5uZXh0ID0gdGhpcy5fZHJhd0ZpcnN0O1xuICBcdFx0dGhpcy5fZHJhd0ZpcnN0LnByZXYgPSBvcmRlcjtcbiAgXHRcdHRoaXMuX2RyYXdGaXJzdCA9IG9yZGVyO1xuXG4gIFx0XHR0aGlzLl9yZXF1ZXN0UmVkcmF3KGxheWVyKTtcbiAgXHR9XG4gIH0pO1xuXG4gIC8vIEBmYWN0b3J5IEwuY2FudmFzKG9wdGlvbnM/OiBSZW5kZXJlciBvcHRpb25zKVxuICAvLyBDcmVhdGVzIGEgQ2FudmFzIHJlbmRlcmVyIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuXG4gIGZ1bmN0aW9uIGNhbnZhcyhvcHRpb25zKSB7XG4gIFx0cmV0dXJuIEJyb3dzZXIuY2FudmFzID8gbmV3IENhbnZhcyhvcHRpb25zKSA6IG51bGw7XG4gIH1cblxuICAvKlxuICAgKiBUaGFua3MgdG8gRG1pdHJ5IEJhcmFub3Zza3kgYW5kIGhpcyBSYXBoYWVsIGxpYnJhcnkgZm9yIGluc3BpcmF0aW9uIVxuICAgKi9cblxuXG4gIHZhciB2bWxDcmVhdGUgPSAoZnVuY3Rpb24gKCkge1xuICBcdHRyeSB7XG4gIFx0XHRkb2N1bWVudC5uYW1lc3BhY2VzLmFkZCgnbHZtbCcsICd1cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOnZtbCcpO1xuICBcdFx0cmV0dXJuIGZ1bmN0aW9uIChuYW1lKSB7XG4gIFx0XHRcdHJldHVybiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCc8bHZtbDonICsgbmFtZSArICcgY2xhc3M9XCJsdm1sXCI+Jyk7XG4gIFx0XHR9O1xuICBcdH0gY2F0Y2ggKGUpIHtcbiAgXHRcdC8vIERvIG5vdCByZXR1cm4gZm4gZnJvbSBjYXRjaCBibG9jayBzbyBgZWAgY2FuIGJlIGdhcmJhZ2UgY29sbGVjdGVkXG4gIFx0XHQvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL0xlYWZsZXQvTGVhZmxldC9wdWxsLzcyNzlcbiAgXHR9XG4gIFx0cmV0dXJuIGZ1bmN0aW9uIChuYW1lKSB7XG4gIFx0XHRyZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnPCcgKyBuYW1lICsgJyB4bWxucz1cInVybjpzY2hlbWFzLW1pY3Jvc29mdC5jb206dm1sXCIgY2xhc3M9XCJsdm1sXCI+Jyk7XG4gIFx0fTtcbiAgfSkoKTtcblxuXG4gIC8qXG4gICAqIEBjbGFzcyBTVkdcbiAgICpcbiAgICpcbiAgICogVk1MIHdhcyBkZXByZWNhdGVkIGluIDIwMTIsIHdoaWNoIG1lYW5zIFZNTCBmdW5jdGlvbmFsaXR5IGV4aXN0cyBvbmx5IGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eVxuICAgKiB3aXRoIG9sZCB2ZXJzaW9ucyBvZiBJbnRlcm5ldCBFeHBsb3Jlci5cbiAgICovXG5cbiAgLy8gbWl4aW4gdG8gcmVkZWZpbmUgc29tZSBTVkcgbWV0aG9kcyB0byBoYW5kbGUgVk1MIHN5bnRheCB3aGljaCBpcyBzaW1pbGFyIGJ1dCB3aXRoIHNvbWUgZGlmZmVyZW5jZXNcbiAgdmFyIHZtbE1peGluID0ge1xuXG4gIFx0X2luaXRDb250YWluZXI6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHRoaXMuX2NvbnRhaW5lciA9IGNyZWF0ZSQxKCdkaXYnLCAnbGVhZmxldC12bWwtY29udGFpbmVyJyk7XG4gIFx0fSxcblxuICBcdF91cGRhdGU6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICh0aGlzLl9tYXAuX2FuaW1hdGluZ1pvb20pIHsgcmV0dXJuOyB9XG4gIFx0XHRSZW5kZXJlci5wcm90b3R5cGUuX3VwZGF0ZS5jYWxsKHRoaXMpO1xuICBcdFx0dGhpcy5maXJlKCd1cGRhdGUnKTtcbiAgXHR9LFxuXG4gIFx0X2luaXRQYXRoOiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdHZhciBjb250YWluZXIgPSBsYXllci5fY29udGFpbmVyID0gdm1sQ3JlYXRlKCdzaGFwZScpO1xuXG4gIFx0XHRhZGRDbGFzcyhjb250YWluZXIsICdsZWFmbGV0LXZtbC1zaGFwZSAnICsgKHRoaXMub3B0aW9ucy5jbGFzc05hbWUgfHwgJycpKTtcblxuICBcdFx0Y29udGFpbmVyLmNvb3Jkc2l6ZSA9ICcxIDEnO1xuXG4gIFx0XHRsYXllci5fcGF0aCA9IHZtbENyZWF0ZSgncGF0aCcpO1xuICBcdFx0Y29udGFpbmVyLmFwcGVuZENoaWxkKGxheWVyLl9wYXRoKTtcblxuICBcdFx0dGhpcy5fdXBkYXRlU3R5bGUobGF5ZXIpO1xuICBcdFx0dGhpcy5fbGF5ZXJzW3N0YW1wKGxheWVyKV0gPSBsYXllcjtcbiAgXHR9LFxuXG4gIFx0X2FkZFBhdGg6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0dmFyIGNvbnRhaW5lciA9IGxheWVyLl9jb250YWluZXI7XG4gIFx0XHR0aGlzLl9jb250YWluZXIuYXBwZW5kQ2hpbGQoY29udGFpbmVyKTtcblxuICBcdFx0aWYgKGxheWVyLm9wdGlvbnMuaW50ZXJhY3RpdmUpIHtcbiAgXHRcdFx0bGF5ZXIuYWRkSW50ZXJhY3RpdmVUYXJnZXQoY29udGFpbmVyKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3JlbW92ZVBhdGg6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0dmFyIGNvbnRhaW5lciA9IGxheWVyLl9jb250YWluZXI7XG4gIFx0XHRyZW1vdmUoY29udGFpbmVyKTtcbiAgXHRcdGxheWVyLnJlbW92ZUludGVyYWN0aXZlVGFyZ2V0KGNvbnRhaW5lcik7XG4gIFx0XHRkZWxldGUgdGhpcy5fbGF5ZXJzW3N0YW1wKGxheWVyKV07XG4gIFx0fSxcblxuICBcdF91cGRhdGVTdHlsZTogZnVuY3Rpb24gKGxheWVyKSB7XG4gIFx0XHR2YXIgc3Ryb2tlID0gbGF5ZXIuX3N0cm9rZSxcbiAgXHRcdCAgICBmaWxsID0gbGF5ZXIuX2ZpbGwsXG4gIFx0XHQgICAgb3B0aW9ucyA9IGxheWVyLm9wdGlvbnMsXG4gIFx0XHQgICAgY29udGFpbmVyID0gbGF5ZXIuX2NvbnRhaW5lcjtcblxuICBcdFx0Y29udGFpbmVyLnN0cm9rZWQgPSAhIW9wdGlvbnMuc3Ryb2tlO1xuICBcdFx0Y29udGFpbmVyLmZpbGxlZCA9ICEhb3B0aW9ucy5maWxsO1xuXG4gIFx0XHRpZiAob3B0aW9ucy5zdHJva2UpIHtcbiAgXHRcdFx0aWYgKCFzdHJva2UpIHtcbiAgXHRcdFx0XHRzdHJva2UgPSBsYXllci5fc3Ryb2tlID0gdm1sQ3JlYXRlKCdzdHJva2UnKTtcbiAgXHRcdFx0fVxuICBcdFx0XHRjb250YWluZXIuYXBwZW5kQ2hpbGQoc3Ryb2tlKTtcbiAgXHRcdFx0c3Ryb2tlLndlaWdodCA9IG9wdGlvbnMud2VpZ2h0ICsgJ3B4JztcbiAgXHRcdFx0c3Ryb2tlLmNvbG9yID0gb3B0aW9ucy5jb2xvcjtcbiAgXHRcdFx0c3Ryb2tlLm9wYWNpdHkgPSBvcHRpb25zLm9wYWNpdHk7XG5cbiAgXHRcdFx0aWYgKG9wdGlvbnMuZGFzaEFycmF5KSB7XG4gIFx0XHRcdFx0c3Ryb2tlLmRhc2hTdHlsZSA9IGlzQXJyYXkob3B0aW9ucy5kYXNoQXJyYXkpID9cbiAgXHRcdFx0XHQgICAgb3B0aW9ucy5kYXNoQXJyYXkuam9pbignICcpIDpcbiAgXHRcdFx0XHQgICAgb3B0aW9ucy5kYXNoQXJyYXkucmVwbGFjZSgvKCAqLCAqKS9nLCAnICcpO1xuICBcdFx0XHR9IGVsc2Uge1xuICBcdFx0XHRcdHN0cm9rZS5kYXNoU3R5bGUgPSAnJztcbiAgXHRcdFx0fVxuICBcdFx0XHRzdHJva2UuZW5kY2FwID0gb3B0aW9ucy5saW5lQ2FwLnJlcGxhY2UoJ2J1dHQnLCAnZmxhdCcpO1xuICBcdFx0XHRzdHJva2Uuam9pbnN0eWxlID0gb3B0aW9ucy5saW5lSm9pbjtcblxuICBcdFx0fSBlbHNlIGlmIChzdHJva2UpIHtcbiAgXHRcdFx0Y29udGFpbmVyLnJlbW92ZUNoaWxkKHN0cm9rZSk7XG4gIFx0XHRcdGxheWVyLl9zdHJva2UgPSBudWxsO1xuICBcdFx0fVxuXG4gIFx0XHRpZiAob3B0aW9ucy5maWxsKSB7XG4gIFx0XHRcdGlmICghZmlsbCkge1xuICBcdFx0XHRcdGZpbGwgPSBsYXllci5fZmlsbCA9IHZtbENyZWF0ZSgnZmlsbCcpO1xuICBcdFx0XHR9XG4gIFx0XHRcdGNvbnRhaW5lci5hcHBlbmRDaGlsZChmaWxsKTtcbiAgXHRcdFx0ZmlsbC5jb2xvciA9IG9wdGlvbnMuZmlsbENvbG9yIHx8IG9wdGlvbnMuY29sb3I7XG4gIFx0XHRcdGZpbGwub3BhY2l0eSA9IG9wdGlvbnMuZmlsbE9wYWNpdHk7XG5cbiAgXHRcdH0gZWxzZSBpZiAoZmlsbCkge1xuICBcdFx0XHRjb250YWluZXIucmVtb3ZlQ2hpbGQoZmlsbCk7XG4gIFx0XHRcdGxheWVyLl9maWxsID0gbnVsbDtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZUNpcmNsZTogZnVuY3Rpb24gKGxheWVyKSB7XG4gIFx0XHR2YXIgcCA9IGxheWVyLl9wb2ludC5yb3VuZCgpLFxuICBcdFx0ICAgIHIgPSBNYXRoLnJvdW5kKGxheWVyLl9yYWRpdXMpLFxuICBcdFx0ICAgIHIyID0gTWF0aC5yb3VuZChsYXllci5fcmFkaXVzWSB8fCByKTtcblxuICBcdFx0dGhpcy5fc2V0UGF0aChsYXllciwgbGF5ZXIuX2VtcHR5KCkgPyAnTTAgMCcgOlxuICBcdFx0XHQnQUwgJyArIHAueCArICcsJyArIHAueSArICcgJyArIHIgKyAnLCcgKyByMiArICcgMCwnICsgKDY1NTM1ICogMzYwKSk7XG4gIFx0fSxcblxuICBcdF9zZXRQYXRoOiBmdW5jdGlvbiAobGF5ZXIsIHBhdGgpIHtcbiAgXHRcdGxheWVyLl9wYXRoLnYgPSBwYXRoO1xuICBcdH0sXG5cbiAgXHRfYnJpbmdUb0Zyb250OiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdHRvRnJvbnQobGF5ZXIuX2NvbnRhaW5lcik7XG4gIFx0fSxcblxuICBcdF9icmluZ1RvQmFjazogZnVuY3Rpb24gKGxheWVyKSB7XG4gIFx0XHR0b0JhY2sobGF5ZXIuX2NvbnRhaW5lcik7XG4gIFx0fVxuICB9O1xuXG4gIHZhciBjcmVhdGUgPSBCcm93c2VyLnZtbCA/IHZtbENyZWF0ZSA6IHN2Z0NyZWF0ZTtcblxuICAvKlxuICAgKiBAY2xhc3MgU1ZHXG4gICAqIEBpbmhlcml0cyBSZW5kZXJlclxuICAgKiBAYWthIEwuU1ZHXG4gICAqXG4gICAqIEFsbG93cyB2ZWN0b3IgbGF5ZXJzIHRvIGJlIGRpc3BsYXllZCB3aXRoIFtTVkddKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL1NWRykuXG4gICAqIEluaGVyaXRzIGBSZW5kZXJlcmAuXG4gICAqXG4gICAqIER1ZSB0byBbdGVjaG5pY2FsIGxpbWl0YXRpb25zXShodHRwczovL2Nhbml1c2UuY29tL3N2ZyksIFNWRyBpcyBub3RcbiAgICogYXZhaWxhYmxlIGluIGFsbCB3ZWIgYnJvd3NlcnMsIG5vdGFibHkgQW5kcm9pZCAyLnggYW5kIDMueC5cbiAgICpcbiAgICogQWx0aG91Z2ggU1ZHIGlzIG5vdCBhdmFpbGFibGUgb24gSUU3IGFuZCBJRTgsIHRoZXNlIGJyb3dzZXJzIHN1cHBvcnRcbiAgICogW1ZNTF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvVmVjdG9yX01hcmt1cF9MYW5ndWFnZSlcbiAgICogKGEgbm93IGRlcHJlY2F0ZWQgdGVjaG5vbG9neSksIGFuZCB0aGUgU1ZHIHJlbmRlcmVyIHdpbGwgZmFsbCBiYWNrIHRvIFZNTCBpblxuICAgKiB0aGlzIGNhc2UuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqIFVzZSBTVkcgYnkgZGVmYXVsdCBmb3IgYWxsIHBhdGhzIGluIHRoZSBtYXA6XG4gICAqXG4gICAqIGBgYGpzXG4gICAqIHZhciBtYXAgPSBMLm1hcCgnbWFwJywge1xuICAgKiBcdHJlbmRlcmVyOiBMLnN2ZygpXG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICpcbiAgICogVXNlIGEgU1ZHIHJlbmRlcmVyIHdpdGggZXh0cmEgcGFkZGluZyBmb3Igc3BlY2lmaWMgdmVjdG9yIGdlb21ldHJpZXM6XG4gICAqXG4gICAqIGBgYGpzXG4gICAqIHZhciBtYXAgPSBMLm1hcCgnbWFwJyk7XG4gICAqIHZhciBteVJlbmRlcmVyID0gTC5zdmcoeyBwYWRkaW5nOiAwLjUgfSk7XG4gICAqIHZhciBsaW5lID0gTC5wb2x5bGluZSggY29vcmRpbmF0ZXMsIHsgcmVuZGVyZXI6IG15UmVuZGVyZXIgfSApO1xuICAgKiB2YXIgY2lyY2xlID0gTC5jaXJjbGUoIGNlbnRlciwgeyByZW5kZXJlcjogbXlSZW5kZXJlciB9ICk7XG4gICAqIGBgYFxuICAgKi9cblxuICB2YXIgU1ZHID0gUmVuZGVyZXIuZXh0ZW5kKHtcblxuICBcdF9pbml0Q29udGFpbmVyOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR0aGlzLl9jb250YWluZXIgPSBjcmVhdGUoJ3N2ZycpO1xuXG4gIFx0XHQvLyBtYWtlcyBpdCBwb3NzaWJsZSB0byBjbGljayB0aHJvdWdoIHN2ZyByb290OyB3ZSdsbCByZXNldCBpdCBiYWNrIGluIGluZGl2aWR1YWwgcGF0aHNcbiAgXHRcdHRoaXMuX2NvbnRhaW5lci5zZXRBdHRyaWJ1dGUoJ3BvaW50ZXItZXZlbnRzJywgJ25vbmUnKTtcblxuICBcdFx0dGhpcy5fcm9vdEdyb3VwID0gY3JlYXRlKCdnJyk7XG4gIFx0XHR0aGlzLl9jb250YWluZXIuYXBwZW5kQ2hpbGQodGhpcy5fcm9vdEdyb3VwKTtcbiAgXHR9LFxuXG4gIFx0X2Rlc3Ryb3lDb250YWluZXI6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHJlbW92ZSh0aGlzLl9jb250YWluZXIpO1xuICBcdFx0b2ZmKHRoaXMuX2NvbnRhaW5lcik7XG4gIFx0XHRkZWxldGUgdGhpcy5fY29udGFpbmVyO1xuICBcdFx0ZGVsZXRlIHRoaXMuX3Jvb3RHcm91cDtcbiAgXHRcdGRlbGV0ZSB0aGlzLl9zdmdTaXplO1xuICBcdH0sXG5cbiAgXHRfdXBkYXRlOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRpZiAodGhpcy5fbWFwLl9hbmltYXRpbmdab29tICYmIHRoaXMuX2JvdW5kcykgeyByZXR1cm47IH1cblxuICBcdFx0UmVuZGVyZXIucHJvdG90eXBlLl91cGRhdGUuY2FsbCh0aGlzKTtcblxuICBcdFx0dmFyIGIgPSB0aGlzLl9ib3VuZHMsXG4gIFx0XHQgICAgc2l6ZSA9IGIuZ2V0U2l6ZSgpLFxuICBcdFx0ICAgIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRhaW5lcjtcblxuICBcdFx0Ly8gc2V0IHNpemUgb2Ygc3ZnLWNvbnRhaW5lciBpZiBjaGFuZ2VkXG4gIFx0XHRpZiAoIXRoaXMuX3N2Z1NpemUgfHwgIXRoaXMuX3N2Z1NpemUuZXF1YWxzKHNpemUpKSB7XG4gIFx0XHRcdHRoaXMuX3N2Z1NpemUgPSBzaXplO1xuICBcdFx0XHRjb250YWluZXIuc2V0QXR0cmlidXRlKCd3aWR0aCcsIHNpemUueCk7XG4gIFx0XHRcdGNvbnRhaW5lci5zZXRBdHRyaWJ1dGUoJ2hlaWdodCcsIHNpemUueSk7XG4gIFx0XHR9XG5cbiAgXHRcdC8vIG1vdmVtZW50OiB1cGRhdGUgY29udGFpbmVyIHZpZXdCb3ggc28gdGhhdCB3ZSBkb24ndCBoYXZlIHRvIGNoYW5nZSBjb29yZGluYXRlcyBvZiBpbmRpdmlkdWFsIGxheWVyc1xuICBcdFx0c2V0UG9zaXRpb24oY29udGFpbmVyLCBiLm1pbik7XG4gIFx0XHRjb250YWluZXIuc2V0QXR0cmlidXRlKCd2aWV3Qm94JywgW2IubWluLngsIGIubWluLnksIHNpemUueCwgc2l6ZS55XS5qb2luKCcgJykpO1xuXG4gIFx0XHR0aGlzLmZpcmUoJ3VwZGF0ZScpO1xuICBcdH0sXG5cbiAgXHQvLyBtZXRob2RzIGJlbG93IGFyZSBjYWxsZWQgYnkgdmVjdG9yIGxheWVycyBpbXBsZW1lbnRhdGlvbnNcblxuICBcdF9pbml0UGF0aDogZnVuY3Rpb24gKGxheWVyKSB7XG4gIFx0XHR2YXIgcGF0aCA9IGxheWVyLl9wYXRoID0gY3JlYXRlKCdwYXRoJyk7XG5cbiAgXHRcdC8vIEBuYW1lc3BhY2UgUGF0aFxuICBcdFx0Ly8gQG9wdGlvbiBjbGFzc05hbWU6IFN0cmluZyA9IG51bGxcbiAgXHRcdC8vIEN1c3RvbSBjbGFzcyBuYW1lIHNldCBvbiBhbiBlbGVtZW50LiBPbmx5IGZvciBTVkcgcmVuZGVyZXIuXG4gIFx0XHRpZiAobGF5ZXIub3B0aW9ucy5jbGFzc05hbWUpIHtcbiAgXHRcdFx0YWRkQ2xhc3MocGF0aCwgbGF5ZXIub3B0aW9ucy5jbGFzc05hbWUpO1xuICBcdFx0fVxuXG4gIFx0XHRpZiAobGF5ZXIub3B0aW9ucy5pbnRlcmFjdGl2ZSkge1xuICBcdFx0XHRhZGRDbGFzcyhwYXRoLCAnbGVhZmxldC1pbnRlcmFjdGl2ZScpO1xuICBcdFx0fVxuXG4gIFx0XHR0aGlzLl91cGRhdGVTdHlsZShsYXllcik7XG4gIFx0XHR0aGlzLl9sYXllcnNbc3RhbXAobGF5ZXIpXSA9IGxheWVyO1xuICBcdH0sXG5cbiAgXHRfYWRkUGF0aDogZnVuY3Rpb24gKGxheWVyKSB7XG4gIFx0XHRpZiAoIXRoaXMuX3Jvb3RHcm91cCkgeyB0aGlzLl9pbml0Q29udGFpbmVyKCk7IH1cbiAgXHRcdHRoaXMuX3Jvb3RHcm91cC5hcHBlbmRDaGlsZChsYXllci5fcGF0aCk7XG4gIFx0XHRsYXllci5hZGRJbnRlcmFjdGl2ZVRhcmdldChsYXllci5fcGF0aCk7XG4gIFx0fSxcblxuICBcdF9yZW1vdmVQYXRoOiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdHJlbW92ZShsYXllci5fcGF0aCk7XG4gIFx0XHRsYXllci5yZW1vdmVJbnRlcmFjdGl2ZVRhcmdldChsYXllci5fcGF0aCk7XG4gIFx0XHRkZWxldGUgdGhpcy5fbGF5ZXJzW3N0YW1wKGxheWVyKV07XG4gIFx0fSxcblxuICBcdF91cGRhdGVQYXRoOiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdGxheWVyLl9wcm9qZWN0KCk7XG4gIFx0XHRsYXllci5fdXBkYXRlKCk7XG4gIFx0fSxcblxuICBcdF91cGRhdGVTdHlsZTogZnVuY3Rpb24gKGxheWVyKSB7XG4gIFx0XHR2YXIgcGF0aCA9IGxheWVyLl9wYXRoLFxuICBcdFx0ICAgIG9wdGlvbnMgPSBsYXllci5vcHRpb25zO1xuXG4gIFx0XHRpZiAoIXBhdGgpIHsgcmV0dXJuOyB9XG5cbiAgXHRcdGlmIChvcHRpb25zLnN0cm9rZSkge1xuICBcdFx0XHRwYXRoLnNldEF0dHJpYnV0ZSgnc3Ryb2tlJywgb3B0aW9ucy5jb2xvcik7XG4gIFx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2Utb3BhY2l0eScsIG9wdGlvbnMub3BhY2l0eSk7XG4gIFx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2Utd2lkdGgnLCBvcHRpb25zLndlaWdodCk7XG4gIFx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2UtbGluZWNhcCcsIG9wdGlvbnMubGluZUNhcCk7XG4gIFx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2UtbGluZWpvaW4nLCBvcHRpb25zLmxpbmVKb2luKTtcblxuICBcdFx0XHRpZiAob3B0aW9ucy5kYXNoQXJyYXkpIHtcbiAgXHRcdFx0XHRwYXRoLnNldEF0dHJpYnV0ZSgnc3Ryb2tlLWRhc2hhcnJheScsIG9wdGlvbnMuZGFzaEFycmF5KTtcbiAgXHRcdFx0fSBlbHNlIHtcbiAgXHRcdFx0XHRwYXRoLnJlbW92ZUF0dHJpYnV0ZSgnc3Ryb2tlLWRhc2hhcnJheScpO1xuICBcdFx0XHR9XG5cbiAgXHRcdFx0aWYgKG9wdGlvbnMuZGFzaE9mZnNldCkge1xuICBcdFx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2UtZGFzaG9mZnNldCcsIG9wdGlvbnMuZGFzaE9mZnNldCk7XG4gIFx0XHRcdH0gZWxzZSB7XG4gIFx0XHRcdFx0cGF0aC5yZW1vdmVBdHRyaWJ1dGUoJ3N0cm9rZS1kYXNob2Zmc2V0Jyk7XG4gIFx0XHRcdH1cbiAgXHRcdH0gZWxzZSB7XG4gIFx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2UnLCAnbm9uZScpO1xuICBcdFx0fVxuXG4gIFx0XHRpZiAob3B0aW9ucy5maWxsKSB7XG4gIFx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdmaWxsJywgb3B0aW9ucy5maWxsQ29sb3IgfHwgb3B0aW9ucy5jb2xvcik7XG4gIFx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdmaWxsLW9wYWNpdHknLCBvcHRpb25zLmZpbGxPcGFjaXR5KTtcbiAgXHRcdFx0cGF0aC5zZXRBdHRyaWJ1dGUoJ2ZpbGwtcnVsZScsIG9wdGlvbnMuZmlsbFJ1bGUgfHwgJ2V2ZW5vZGQnKTtcbiAgXHRcdH0gZWxzZSB7XG4gIFx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdmaWxsJywgJ25vbmUnKTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZVBvbHk6IGZ1bmN0aW9uIChsYXllciwgY2xvc2VkKSB7XG4gIFx0XHR0aGlzLl9zZXRQYXRoKGxheWVyLCBwb2ludHNUb1BhdGgobGF5ZXIuX3BhcnRzLCBjbG9zZWQpKTtcbiAgXHR9LFxuXG4gIFx0X3VwZGF0ZUNpcmNsZTogZnVuY3Rpb24gKGxheWVyKSB7XG4gIFx0XHR2YXIgcCA9IGxheWVyLl9wb2ludCxcbiAgXHRcdCAgICByID0gTWF0aC5tYXgoTWF0aC5yb3VuZChsYXllci5fcmFkaXVzKSwgMSksXG4gIFx0XHQgICAgcjIgPSBNYXRoLm1heChNYXRoLnJvdW5kKGxheWVyLl9yYWRpdXNZKSwgMSkgfHwgcixcbiAgXHRcdCAgICBhcmMgPSAnYScgKyByICsgJywnICsgcjIgKyAnIDAgMSwwICc7XG5cbiAgXHRcdC8vIGRyYXdpbmcgYSBjaXJjbGUgd2l0aCB0d28gaGFsZi1hcmNzXG4gIFx0XHR2YXIgZCA9IGxheWVyLl9lbXB0eSgpID8gJ00wIDAnIDpcbiAgXHRcdFx0J00nICsgKHAueCAtIHIpICsgJywnICsgcC55ICtcbiAgXHRcdFx0YXJjICsgKHIgKiAyKSArICcsMCAnICtcbiAgXHRcdFx0YXJjICsgKC1yICogMikgKyAnLDAgJztcblxuICBcdFx0dGhpcy5fc2V0UGF0aChsYXllciwgZCk7XG4gIFx0fSxcblxuICBcdF9zZXRQYXRoOiBmdW5jdGlvbiAobGF5ZXIsIHBhdGgpIHtcbiAgXHRcdGxheWVyLl9wYXRoLnNldEF0dHJpYnV0ZSgnZCcsIHBhdGgpO1xuICBcdH0sXG5cbiAgXHQvLyBTVkcgZG9lcyBub3QgaGF2ZSB0aGUgY29uY2VwdCBvZiB6SW5kZXggc28gd2UgcmVzb3J0IHRvIGNoYW5naW5nIHRoZSBET00gb3JkZXIgb2YgZWxlbWVudHNcbiAgXHRfYnJpbmdUb0Zyb250OiBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgXHRcdHRvRnJvbnQobGF5ZXIuX3BhdGgpO1xuICBcdH0sXG5cbiAgXHRfYnJpbmdUb0JhY2s6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0dG9CYWNrKGxheWVyLl9wYXRoKTtcbiAgXHR9XG4gIH0pO1xuXG4gIGlmIChCcm93c2VyLnZtbCkge1xuICBcdFNWRy5pbmNsdWRlKHZtbE1peGluKTtcbiAgfVxuXG4gIC8vIEBuYW1lc3BhY2UgU1ZHXG4gIC8vIEBmYWN0b3J5IEwuc3ZnKG9wdGlvbnM/OiBSZW5kZXJlciBvcHRpb25zKVxuICAvLyBDcmVhdGVzIGEgU1ZHIHJlbmRlcmVyIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuXG4gIGZ1bmN0aW9uIHN2ZyhvcHRpb25zKSB7XG4gIFx0cmV0dXJuIEJyb3dzZXIuc3ZnIHx8IEJyb3dzZXIudm1sID8gbmV3IFNWRyhvcHRpb25zKSA6IG51bGw7XG4gIH1cblxuICBNYXAuaW5jbHVkZSh7XG4gIFx0Ly8gQG5hbWVzcGFjZSBNYXA7IEBtZXRob2QgZ2V0UmVuZGVyZXIobGF5ZXI6IFBhdGgpOiBSZW5kZXJlclxuICBcdC8vIFJldHVybnMgdGhlIGluc3RhbmNlIG9mIGBSZW5kZXJlcmAgdGhhdCBzaG91bGQgYmUgdXNlZCB0byByZW5kZXIgdGhlIGdpdmVuXG4gIFx0Ly8gYFBhdGhgLiBJdCB3aWxsIGVuc3VyZSB0aGF0IHRoZSBgcmVuZGVyZXJgIG9wdGlvbnMgb2YgdGhlIG1hcCBhbmQgcGF0aHNcbiAgXHQvLyBhcmUgcmVzcGVjdGVkLCBhbmQgdGhhdCB0aGUgcmVuZGVyZXJzIGRvIGV4aXN0IG9uIHRoZSBtYXAuXG4gIFx0Z2V0UmVuZGVyZXI6IGZ1bmN0aW9uIChsYXllcikge1xuICBcdFx0Ly8gQG5hbWVzcGFjZSBQYXRoOyBAb3B0aW9uIHJlbmRlcmVyOiBSZW5kZXJlclxuICBcdFx0Ly8gVXNlIHRoaXMgc3BlY2lmaWMgaW5zdGFuY2Ugb2YgYFJlbmRlcmVyYCBmb3IgdGhpcyBwYXRoLiBUYWtlc1xuICBcdFx0Ly8gcHJlY2VkZW5jZSBvdmVyIHRoZSBtYXAncyBbZGVmYXVsdCByZW5kZXJlcl0oI21hcC1yZW5kZXJlcikuXG4gIFx0XHR2YXIgcmVuZGVyZXIgPSBsYXllci5vcHRpb25zLnJlbmRlcmVyIHx8IHRoaXMuX2dldFBhbmVSZW5kZXJlcihsYXllci5vcHRpb25zLnBhbmUpIHx8IHRoaXMub3B0aW9ucy5yZW5kZXJlciB8fCB0aGlzLl9yZW5kZXJlcjtcblxuICBcdFx0aWYgKCFyZW5kZXJlcikge1xuICBcdFx0XHRyZW5kZXJlciA9IHRoaXMuX3JlbmRlcmVyID0gdGhpcy5fY3JlYXRlUmVuZGVyZXIoKTtcbiAgXHRcdH1cblxuICBcdFx0aWYgKCF0aGlzLmhhc0xheWVyKHJlbmRlcmVyKSkge1xuICBcdFx0XHR0aGlzLmFkZExheWVyKHJlbmRlcmVyKTtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiByZW5kZXJlcjtcbiAgXHR9LFxuXG4gIFx0X2dldFBhbmVSZW5kZXJlcjogZnVuY3Rpb24gKG5hbWUpIHtcbiAgXHRcdGlmIChuYW1lID09PSAnb3ZlcmxheVBhbmUnIHx8IG5hbWUgPT09IHVuZGVmaW5lZCkge1xuICBcdFx0XHRyZXR1cm4gZmFsc2U7XG4gIFx0XHR9XG5cbiAgXHRcdHZhciByZW5kZXJlciA9IHRoaXMuX3BhbmVSZW5kZXJlcnNbbmFtZV07XG4gIFx0XHRpZiAocmVuZGVyZXIgPT09IHVuZGVmaW5lZCkge1xuICBcdFx0XHRyZW5kZXJlciA9IHRoaXMuX2NyZWF0ZVJlbmRlcmVyKHtwYW5lOiBuYW1lfSk7XG4gIFx0XHRcdHRoaXMuX3BhbmVSZW5kZXJlcnNbbmFtZV0gPSByZW5kZXJlcjtcbiAgXHRcdH1cbiAgXHRcdHJldHVybiByZW5kZXJlcjtcbiAgXHR9LFxuXG4gIFx0X2NyZWF0ZVJlbmRlcmVyOiBmdW5jdGlvbiAob3B0aW9ucykge1xuICBcdFx0Ly8gQG5hbWVzcGFjZSBNYXA7IEBvcHRpb24gcHJlZmVyQ2FudmFzOiBCb29sZWFuID0gZmFsc2VcbiAgXHRcdC8vIFdoZXRoZXIgYFBhdGhgcyBzaG91bGQgYmUgcmVuZGVyZWQgb24gYSBgQ2FudmFzYCByZW5kZXJlci5cbiAgXHRcdC8vIEJ5IGRlZmF1bHQsIGFsbCBgUGF0aGBzIGFyZSByZW5kZXJlZCBpbiBhIGBTVkdgIHJlbmRlcmVyLlxuICBcdFx0cmV0dXJuICh0aGlzLm9wdGlvbnMucHJlZmVyQ2FudmFzICYmIGNhbnZhcyhvcHRpb25zKSkgfHwgc3ZnKG9wdGlvbnMpO1xuICBcdH1cbiAgfSk7XG5cbiAgLypcbiAgICogTC5SZWN0YW5nbGUgZXh0ZW5kcyBQb2x5Z29uIGFuZCBjcmVhdGVzIGEgcmVjdGFuZ2xlIHdoZW4gcGFzc2VkIGEgTGF0TG5nQm91bmRzIG9iamVjdC5cbiAgICovXG5cbiAgLypcbiAgICogQGNsYXNzIFJlY3RhbmdsZVxuICAgKiBAYWthIEwuUmVjdGFuZ2xlXG4gICAqIEBpbmhlcml0cyBQb2x5Z29uXG4gICAqXG4gICAqIEEgY2xhc3MgZm9yIGRyYXdpbmcgcmVjdGFuZ2xlIG92ZXJsYXlzIG9uIGEgbWFwLiBFeHRlbmRzIGBQb2x5Z29uYC5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICpcbiAgICogYGBganNcbiAgICogLy8gZGVmaW5lIHJlY3RhbmdsZSBnZW9ncmFwaGljYWwgYm91bmRzXG4gICAqIHZhciBib3VuZHMgPSBbWzU0LjU1OTMyMiwgLTUuNzY3ODIyXSwgWzU2LjEyMTA2MDQsIC0zLjAyMTI0MF1dO1xuICAgKlxuICAgKiAvLyBjcmVhdGUgYW4gb3JhbmdlIHJlY3RhbmdsZVxuICAgKiBMLnJlY3RhbmdsZShib3VuZHMsIHtjb2xvcjogXCIjZmY3ODAwXCIsIHdlaWdodDogMX0pLmFkZFRvKG1hcCk7XG4gICAqXG4gICAqIC8vIHpvb20gdGhlIG1hcCB0byB0aGUgcmVjdGFuZ2xlIGJvdW5kc1xuICAgKiBtYXAuZml0Qm91bmRzKGJvdW5kcyk7XG4gICAqIGBgYFxuICAgKlxuICAgKi9cblxuXG4gIHZhciBSZWN0YW5nbGUgPSBQb2x5Z29uLmV4dGVuZCh7XG4gIFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKGxhdExuZ0JvdW5kcywgb3B0aW9ucykge1xuICBcdFx0UG9seWdvbi5wcm90b3R5cGUuaW5pdGlhbGl6ZS5jYWxsKHRoaXMsIHRoaXMuX2JvdW5kc1RvTGF0TG5ncyhsYXRMbmdCb3VuZHMpLCBvcHRpb25zKTtcbiAgXHR9LFxuXG4gIFx0Ly8gQG1ldGhvZCBzZXRCb3VuZHMobGF0TG5nQm91bmRzOiBMYXRMbmdCb3VuZHMpOiB0aGlzXG4gIFx0Ly8gUmVkcmF3cyB0aGUgcmVjdGFuZ2xlIHdpdGggdGhlIHBhc3NlZCBib3VuZHMuXG4gIFx0c2V0Qm91bmRzOiBmdW5jdGlvbiAobGF0TG5nQm91bmRzKSB7XG4gIFx0XHRyZXR1cm4gdGhpcy5zZXRMYXRMbmdzKHRoaXMuX2JvdW5kc1RvTGF0TG5ncyhsYXRMbmdCb3VuZHMpKTtcbiAgXHR9LFxuXG4gIFx0X2JvdW5kc1RvTGF0TG5nczogZnVuY3Rpb24gKGxhdExuZ0JvdW5kcykge1xuICBcdFx0bGF0TG5nQm91bmRzID0gdG9MYXRMbmdCb3VuZHMobGF0TG5nQm91bmRzKTtcbiAgXHRcdHJldHVybiBbXG4gIFx0XHRcdGxhdExuZ0JvdW5kcy5nZXRTb3V0aFdlc3QoKSxcbiAgXHRcdFx0bGF0TG5nQm91bmRzLmdldE5vcnRoV2VzdCgpLFxuICBcdFx0XHRsYXRMbmdCb3VuZHMuZ2V0Tm9ydGhFYXN0KCksXG4gIFx0XHRcdGxhdExuZ0JvdW5kcy5nZXRTb3V0aEVhc3QoKVxuICBcdFx0XTtcbiAgXHR9XG4gIH0pO1xuXG5cbiAgLy8gQGZhY3RvcnkgTC5yZWN0YW5nbGUobGF0TG5nQm91bmRzOiBMYXRMbmdCb3VuZHMsIG9wdGlvbnM/OiBQb2x5bGluZSBvcHRpb25zKVxuICBmdW5jdGlvbiByZWN0YW5nbGUobGF0TG5nQm91bmRzLCBvcHRpb25zKSB7XG4gIFx0cmV0dXJuIG5ldyBSZWN0YW5nbGUobGF0TG5nQm91bmRzLCBvcHRpb25zKTtcbiAgfVxuXG4gIFNWRy5jcmVhdGUgPSBjcmVhdGU7XG4gIFNWRy5wb2ludHNUb1BhdGggPSBwb2ludHNUb1BhdGg7XG5cbiAgR2VvSlNPTi5nZW9tZXRyeVRvTGF5ZXIgPSBnZW9tZXRyeVRvTGF5ZXI7XG4gIEdlb0pTT04uY29vcmRzVG9MYXRMbmcgPSBjb29yZHNUb0xhdExuZztcbiAgR2VvSlNPTi5jb29yZHNUb0xhdExuZ3MgPSBjb29yZHNUb0xhdExuZ3M7XG4gIEdlb0pTT04ubGF0TG5nVG9Db29yZHMgPSBsYXRMbmdUb0Nvb3JkcztcbiAgR2VvSlNPTi5sYXRMbmdzVG9Db29yZHMgPSBsYXRMbmdzVG9Db29yZHM7XG4gIEdlb0pTT04uZ2V0RmVhdHVyZSA9IGdldEZlYXR1cmU7XG4gIEdlb0pTT04uYXNGZWF0dXJlID0gYXNGZWF0dXJlO1xuXG4gIC8qXG4gICAqIEwuSGFuZGxlci5Cb3hab29tIGlzIHVzZWQgdG8gYWRkIHNoaWZ0LWRyYWcgem9vbSBpbnRlcmFjdGlvbiB0byB0aGUgbWFwXG4gICAqICh6b29tIHRvIGEgc2VsZWN0ZWQgYm91bmRpbmcgYm94KSwgZW5hYmxlZCBieSBkZWZhdWx0LlxuICAgKi9cblxuICAvLyBAbmFtZXNwYWNlIE1hcFxuICAvLyBAc2VjdGlvbiBJbnRlcmFjdGlvbiBPcHRpb25zXG4gIE1hcC5tZXJnZU9wdGlvbnMoe1xuICBcdC8vIEBvcHRpb24gYm94Wm9vbTogQm9vbGVhbiA9IHRydWVcbiAgXHQvLyBXaGV0aGVyIHRoZSBtYXAgY2FuIGJlIHpvb21lZCB0byBhIHJlY3Rhbmd1bGFyIGFyZWEgc3BlY2lmaWVkIGJ5XG4gIFx0Ly8gZHJhZ2dpbmcgdGhlIG1vdXNlIHdoaWxlIHByZXNzaW5nIHRoZSBzaGlmdCBrZXkuXG4gIFx0Ym94Wm9vbTogdHJ1ZVxuICB9KTtcblxuICB2YXIgQm94Wm9vbSA9IEhhbmRsZXIuZXh0ZW5kKHtcbiAgXHRpbml0aWFsaXplOiBmdW5jdGlvbiAobWFwKSB7XG4gIFx0XHR0aGlzLl9tYXAgPSBtYXA7XG4gIFx0XHR0aGlzLl9jb250YWluZXIgPSBtYXAuX2NvbnRhaW5lcjtcbiAgXHRcdHRoaXMuX3BhbmUgPSBtYXAuX3BhbmVzLm92ZXJsYXlQYW5lO1xuICBcdFx0dGhpcy5fcmVzZXRTdGF0ZVRpbWVvdXQgPSAwO1xuICBcdFx0bWFwLm9uKCd1bmxvYWQnLCB0aGlzLl9kZXN0cm95LCB0aGlzKTtcbiAgXHR9LFxuXG4gIFx0YWRkSG9va3M6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdG9uKHRoaXMuX2NvbnRhaW5lciwgJ21vdXNlZG93bicsIHRoaXMuX29uTW91c2VEb3duLCB0aGlzKTtcbiAgXHR9LFxuXG4gIFx0cmVtb3ZlSG9va3M6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdG9mZih0aGlzLl9jb250YWluZXIsICdtb3VzZWRvd24nLCB0aGlzLl9vbk1vdXNlRG93biwgdGhpcyk7XG4gIFx0fSxcblxuICBcdG1vdmVkOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZXR1cm4gdGhpcy5fbW92ZWQ7XG4gIFx0fSxcblxuICBcdF9kZXN0cm95OiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZW1vdmUodGhpcy5fcGFuZSk7XG4gIFx0XHRkZWxldGUgdGhpcy5fcGFuZTtcbiAgXHR9LFxuXG4gIFx0X3Jlc2V0U3RhdGU6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHRoaXMuX3Jlc2V0U3RhdGVUaW1lb3V0ID0gMDtcbiAgXHRcdHRoaXMuX21vdmVkID0gZmFsc2U7XG4gIFx0fSxcblxuICBcdF9jbGVhckRlZmVycmVkUmVzZXRTdGF0ZTogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKHRoaXMuX3Jlc2V0U3RhdGVUaW1lb3V0ICE9PSAwKSB7XG4gIFx0XHRcdGNsZWFyVGltZW91dCh0aGlzLl9yZXNldFN0YXRlVGltZW91dCk7XG4gIFx0XHRcdHRoaXMuX3Jlc2V0U3RhdGVUaW1lb3V0ID0gMDtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X29uTW91c2VEb3duOiBmdW5jdGlvbiAoZSkge1xuICBcdFx0aWYgKCFlLnNoaWZ0S2V5IHx8ICgoZS53aGljaCAhPT0gMSkgJiYgKGUuYnV0dG9uICE9PSAxKSkpIHsgcmV0dXJuIGZhbHNlOyB9XG5cbiAgXHRcdC8vIENsZWFyIHRoZSBkZWZlcnJlZCByZXNldFN0YXRlIGlmIGl0IGhhc24ndCBleGVjdXRlZCB5ZXQsIG90aGVyd2lzZSBpdFxuICBcdFx0Ly8gd2lsbCBpbnRlcnJ1cHQgdGhlIGludGVyYWN0aW9uIGFuZCBvcnBoYW4gYSBib3ggZWxlbWVudCBpbiB0aGUgY29udGFpbmVyLlxuICBcdFx0dGhpcy5fY2xlYXJEZWZlcnJlZFJlc2V0U3RhdGUoKTtcbiAgXHRcdHRoaXMuX3Jlc2V0U3RhdGUoKTtcblxuICBcdFx0ZGlzYWJsZVRleHRTZWxlY3Rpb24oKTtcbiAgXHRcdGRpc2FibGVJbWFnZURyYWcoKTtcblxuICBcdFx0dGhpcy5fc3RhcnRQb2ludCA9IHRoaXMuX21hcC5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlKTtcblxuICBcdFx0b24oZG9jdW1lbnQsIHtcbiAgXHRcdFx0Y29udGV4dG1lbnU6IHN0b3AsXG4gIFx0XHRcdG1vdXNlbW92ZTogdGhpcy5fb25Nb3VzZU1vdmUsXG4gIFx0XHRcdG1vdXNldXA6IHRoaXMuX29uTW91c2VVcCxcbiAgXHRcdFx0a2V5ZG93bjogdGhpcy5fb25LZXlEb3duXG4gIFx0XHR9LCB0aGlzKTtcbiAgXHR9LFxuXG4gIFx0X29uTW91c2VNb3ZlOiBmdW5jdGlvbiAoZSkge1xuICBcdFx0aWYgKCF0aGlzLl9tb3ZlZCkge1xuICBcdFx0XHR0aGlzLl9tb3ZlZCA9IHRydWU7XG5cbiAgXHRcdFx0dGhpcy5fYm94ID0gY3JlYXRlJDEoJ2RpdicsICdsZWFmbGV0LXpvb20tYm94JywgdGhpcy5fY29udGFpbmVyKTtcbiAgXHRcdFx0YWRkQ2xhc3ModGhpcy5fY29udGFpbmVyLCAnbGVhZmxldC1jcm9zc2hhaXInKTtcblxuICBcdFx0XHR0aGlzLl9tYXAuZmlyZSgnYm94em9vbXN0YXJ0Jyk7XG4gIFx0XHR9XG5cbiAgXHRcdHRoaXMuX3BvaW50ID0gdGhpcy5fbWFwLm1vdXNlRXZlbnRUb0NvbnRhaW5lclBvaW50KGUpO1xuXG4gIFx0XHR2YXIgYm91bmRzID0gbmV3IEJvdW5kcyh0aGlzLl9wb2ludCwgdGhpcy5fc3RhcnRQb2ludCksXG4gIFx0XHQgICAgc2l6ZSA9IGJvdW5kcy5nZXRTaXplKCk7XG5cbiAgXHRcdHNldFBvc2l0aW9uKHRoaXMuX2JveCwgYm91bmRzLm1pbik7XG5cbiAgXHRcdHRoaXMuX2JveC5zdHlsZS53aWR0aCAgPSBzaXplLnggKyAncHgnO1xuICBcdFx0dGhpcy5fYm94LnN0eWxlLmhlaWdodCA9IHNpemUueSArICdweCc7XG4gIFx0fSxcblxuICBcdF9maW5pc2g6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICh0aGlzLl9tb3ZlZCkge1xuICBcdFx0XHRyZW1vdmUodGhpcy5fYm94KTtcbiAgXHRcdFx0cmVtb3ZlQ2xhc3ModGhpcy5fY29udGFpbmVyLCAnbGVhZmxldC1jcm9zc2hhaXInKTtcbiAgXHRcdH1cblxuICBcdFx0ZW5hYmxlVGV4dFNlbGVjdGlvbigpO1xuICBcdFx0ZW5hYmxlSW1hZ2VEcmFnKCk7XG5cbiAgXHRcdG9mZihkb2N1bWVudCwge1xuICBcdFx0XHRjb250ZXh0bWVudTogc3RvcCxcbiAgXHRcdFx0bW91c2Vtb3ZlOiB0aGlzLl9vbk1vdXNlTW92ZSxcbiAgXHRcdFx0bW91c2V1cDogdGhpcy5fb25Nb3VzZVVwLFxuICBcdFx0XHRrZXlkb3duOiB0aGlzLl9vbktleURvd25cbiAgXHRcdH0sIHRoaXMpO1xuICBcdH0sXG5cbiAgXHRfb25Nb3VzZVVwOiBmdW5jdGlvbiAoZSkge1xuICBcdFx0aWYgKChlLndoaWNoICE9PSAxKSAmJiAoZS5idXR0b24gIT09IDEpKSB7IHJldHVybjsgfVxuXG4gIFx0XHR0aGlzLl9maW5pc2goKTtcblxuICBcdFx0aWYgKCF0aGlzLl9tb3ZlZCkgeyByZXR1cm47IH1cbiAgXHRcdC8vIFBvc3Rwb25lIHRvIG5leHQgSlMgdGljayBzbyBpbnRlcm5hbCBjbGljayBldmVudCBoYW5kbGluZ1xuICBcdFx0Ly8gc3RpbGwgc2VlIGl0IGFzIFwibW92ZWRcIi5cbiAgXHRcdHRoaXMuX2NsZWFyRGVmZXJyZWRSZXNldFN0YXRlKCk7XG4gIFx0XHR0aGlzLl9yZXNldFN0YXRlVGltZW91dCA9IHNldFRpbWVvdXQoYmluZCh0aGlzLl9yZXNldFN0YXRlLCB0aGlzKSwgMCk7XG5cbiAgXHRcdHZhciBib3VuZHMgPSBuZXcgTGF0TG5nQm91bmRzKFxuICBcdFx0ICAgICAgICB0aGlzLl9tYXAuY29udGFpbmVyUG9pbnRUb0xhdExuZyh0aGlzLl9zdGFydFBvaW50KSxcbiAgXHRcdCAgICAgICAgdGhpcy5fbWFwLmNvbnRhaW5lclBvaW50VG9MYXRMbmcodGhpcy5fcG9pbnQpKTtcblxuICBcdFx0dGhpcy5fbWFwXG4gIFx0XHRcdC5maXRCb3VuZHMoYm91bmRzKVxuICBcdFx0XHQuZmlyZSgnYm94em9vbWVuZCcsIHtib3hab29tQm91bmRzOiBib3VuZHN9KTtcbiAgXHR9LFxuXG4gIFx0X29uS2V5RG93bjogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdGlmIChlLmtleUNvZGUgPT09IDI3KSB7XG4gIFx0XHRcdHRoaXMuX2ZpbmlzaCgpO1xuICBcdFx0XHR0aGlzLl9jbGVhckRlZmVycmVkUmVzZXRTdGF0ZSgpO1xuICBcdFx0XHR0aGlzLl9yZXNldFN0YXRlKCk7XG4gIFx0XHR9XG4gIFx0fVxuICB9KTtcblxuICAvLyBAc2VjdGlvbiBIYW5kbGVyc1xuICAvLyBAcHJvcGVydHkgYm94Wm9vbTogSGFuZGxlclxuICAvLyBCb3ggKHNoaWZ0LWRyYWcgd2l0aCBtb3VzZSkgem9vbSBoYW5kbGVyLlxuICBNYXAuYWRkSW5pdEhvb2soJ2FkZEhhbmRsZXInLCAnYm94Wm9vbScsIEJveFpvb20pO1xuXG4gIC8qXG4gICAqIEwuSGFuZGxlci5Eb3VibGVDbGlja1pvb20gaXMgdXNlZCB0byBoYW5kbGUgZG91YmxlLWNsaWNrIHpvb20gb24gdGhlIG1hcCwgZW5hYmxlZCBieSBkZWZhdWx0LlxuICAgKi9cblxuICAvLyBAbmFtZXNwYWNlIE1hcFxuICAvLyBAc2VjdGlvbiBJbnRlcmFjdGlvbiBPcHRpb25zXG5cbiAgTWFwLm1lcmdlT3B0aW9ucyh7XG4gIFx0Ly8gQG9wdGlvbiBkb3VibGVDbGlja1pvb206IEJvb2xlYW58U3RyaW5nID0gdHJ1ZVxuICBcdC8vIFdoZXRoZXIgdGhlIG1hcCBjYW4gYmUgem9vbWVkIGluIGJ5IGRvdWJsZSBjbGlja2luZyBvbiBpdCBhbmRcbiAgXHQvLyB6b29tZWQgb3V0IGJ5IGRvdWJsZSBjbGlja2luZyB3aGlsZSBob2xkaW5nIHNoaWZ0LiBJZiBwYXNzZWRcbiAgXHQvLyBgJ2NlbnRlcidgLCBkb3VibGUtY2xpY2sgem9vbSB3aWxsIHpvb20gdG8gdGhlIGNlbnRlciBvZiB0aGVcbiAgXHQvLyAgdmlldyByZWdhcmRsZXNzIG9mIHdoZXJlIHRoZSBtb3VzZSB3YXMuXG4gIFx0ZG91YmxlQ2xpY2tab29tOiB0cnVlXG4gIH0pO1xuXG4gIHZhciBEb3VibGVDbGlja1pvb20gPSBIYW5kbGVyLmV4dGVuZCh7XG4gIFx0YWRkSG9va3M6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHRoaXMuX21hcC5vbignZGJsY2xpY2snLCB0aGlzLl9vbkRvdWJsZUNsaWNrLCB0aGlzKTtcbiAgXHR9LFxuXG4gIFx0cmVtb3ZlSG9va3M6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHRoaXMuX21hcC5vZmYoJ2RibGNsaWNrJywgdGhpcy5fb25Eb3VibGVDbGljaywgdGhpcyk7XG4gIFx0fSxcblxuICBcdF9vbkRvdWJsZUNsaWNrOiBmdW5jdGlvbiAoZSkge1xuICBcdFx0dmFyIG1hcCA9IHRoaXMuX21hcCxcbiAgXHRcdCAgICBvbGRab29tID0gbWFwLmdldFpvb20oKSxcbiAgXHRcdCAgICBkZWx0YSA9IG1hcC5vcHRpb25zLnpvb21EZWx0YSxcbiAgXHRcdCAgICB6b29tID0gZS5vcmlnaW5hbEV2ZW50LnNoaWZ0S2V5ID8gb2xkWm9vbSAtIGRlbHRhIDogb2xkWm9vbSArIGRlbHRhO1xuXG4gIFx0XHRpZiAobWFwLm9wdGlvbnMuZG91YmxlQ2xpY2tab29tID09PSAnY2VudGVyJykge1xuICBcdFx0XHRtYXAuc2V0Wm9vbSh6b29tKTtcbiAgXHRcdH0gZWxzZSB7XG4gIFx0XHRcdG1hcC5zZXRab29tQXJvdW5kKGUuY29udGFpbmVyUG9pbnQsIHpvb20pO1xuICBcdFx0fVxuICBcdH1cbiAgfSk7XG5cbiAgLy8gQHNlY3Rpb24gSGFuZGxlcnNcbiAgLy9cbiAgLy8gTWFwIHByb3BlcnRpZXMgaW5jbHVkZSBpbnRlcmFjdGlvbiBoYW5kbGVycyB0aGF0IGFsbG93IHlvdSB0byBjb250cm9sXG4gIC8vIGludGVyYWN0aW9uIGJlaGF2aW9yIGluIHJ1bnRpbWUsIGVuYWJsaW5nIG9yIGRpc2FibGluZyBjZXJ0YWluIGZlYXR1cmVzIHN1Y2hcbiAgLy8gYXMgZHJhZ2dpbmcgb3IgdG91Y2ggem9vbSAoc2VlIGBIYW5kbGVyYCBtZXRob2RzKS4gRm9yIGV4YW1wbGU6XG4gIC8vXG4gIC8vIGBgYGpzXG4gIC8vIG1hcC5kb3VibGVDbGlja1pvb20uZGlzYWJsZSgpO1xuICAvLyBgYGBcbiAgLy9cbiAgLy8gQHByb3BlcnR5IGRvdWJsZUNsaWNrWm9vbTogSGFuZGxlclxuICAvLyBEb3VibGUgY2xpY2sgem9vbSBoYW5kbGVyLlxuICBNYXAuYWRkSW5pdEhvb2soJ2FkZEhhbmRsZXInLCAnZG91YmxlQ2xpY2tab29tJywgRG91YmxlQ2xpY2tab29tKTtcblxuICAvKlxuICAgKiBMLkhhbmRsZXIuTWFwRHJhZyBpcyB1c2VkIHRvIG1ha2UgdGhlIG1hcCBkcmFnZ2FibGUgKHdpdGggcGFubmluZyBpbmVydGlhKSwgZW5hYmxlZCBieSBkZWZhdWx0LlxuICAgKi9cblxuICAvLyBAbmFtZXNwYWNlIE1hcFxuICAvLyBAc2VjdGlvbiBJbnRlcmFjdGlvbiBPcHRpb25zXG4gIE1hcC5tZXJnZU9wdGlvbnMoe1xuICBcdC8vIEBvcHRpb24gZHJhZ2dpbmc6IEJvb2xlYW4gPSB0cnVlXG4gIFx0Ly8gV2hldGhlciB0aGUgbWFwIGlzIGRyYWdnYWJsZSB3aXRoIG1vdXNlL3RvdWNoIG9yIG5vdC5cbiAgXHRkcmFnZ2luZzogdHJ1ZSxcblxuICBcdC8vIEBzZWN0aW9uIFBhbm5pbmcgSW5lcnRpYSBPcHRpb25zXG4gIFx0Ly8gQG9wdGlvbiBpbmVydGlhOiBCb29sZWFuID0gKlxuICBcdC8vIElmIGVuYWJsZWQsIHBhbm5pbmcgb2YgdGhlIG1hcCB3aWxsIGhhdmUgYW4gaW5lcnRpYSBlZmZlY3Qgd2hlcmVcbiAgXHQvLyB0aGUgbWFwIGJ1aWxkcyBtb21lbnR1bSB3aGlsZSBkcmFnZ2luZyBhbmQgY29udGludWVzIG1vdmluZyBpblxuICBcdC8vIHRoZSBzYW1lIGRpcmVjdGlvbiBmb3Igc29tZSB0aW1lLiBGZWVscyBlc3BlY2lhbGx5IG5pY2Ugb24gdG91Y2hcbiAgXHQvLyBkZXZpY2VzLiBFbmFibGVkIGJ5IGRlZmF1bHQuXG4gIFx0aW5lcnRpYTogdHJ1ZSxcblxuICBcdC8vIEBvcHRpb24gaW5lcnRpYURlY2VsZXJhdGlvbjogTnVtYmVyID0gMzAwMFxuICBcdC8vIFRoZSByYXRlIHdpdGggd2hpY2ggdGhlIGluZXJ0aWFsIG1vdmVtZW50IHNsb3dzIGRvd24sIGluIHBpeGVscy9zZWNvbmTCsi5cbiAgXHRpbmVydGlhRGVjZWxlcmF0aW9uOiAzNDAwLCAvLyBweC9zXjJcblxuICBcdC8vIEBvcHRpb24gaW5lcnRpYU1heFNwZWVkOiBOdW1iZXIgPSBJbmZpbml0eVxuICBcdC8vIE1heCBzcGVlZCBvZiB0aGUgaW5lcnRpYWwgbW92ZW1lbnQsIGluIHBpeGVscy9zZWNvbmQuXG4gIFx0aW5lcnRpYU1heFNwZWVkOiBJbmZpbml0eSwgLy8gcHgvc1xuXG4gIFx0Ly8gQG9wdGlvbiBlYXNlTGluZWFyaXR5OiBOdW1iZXIgPSAwLjJcbiAgXHRlYXNlTGluZWFyaXR5OiAwLjIsXG5cbiAgXHQvLyBUT0RPIHJlZmFjdG9yLCBtb3ZlIHRvIENSU1xuICBcdC8vIEBvcHRpb24gd29ybGRDb3B5SnVtcDogQm9vbGVhbiA9IGZhbHNlXG4gIFx0Ly8gV2l0aCB0aGlzIG9wdGlvbiBlbmFibGVkLCB0aGUgbWFwIHRyYWNrcyB3aGVuIHlvdSBwYW4gdG8gYW5vdGhlciBcImNvcHlcIlxuICBcdC8vIG9mIHRoZSB3b3JsZCBhbmQgc2VhbWxlc3NseSBqdW1wcyB0byB0aGUgb3JpZ2luYWwgb25lIHNvIHRoYXQgYWxsIG92ZXJsYXlzXG4gIFx0Ly8gbGlrZSBtYXJrZXJzIGFuZCB2ZWN0b3IgbGF5ZXJzIGFyZSBzdGlsbCB2aXNpYmxlLlxuICBcdHdvcmxkQ29weUp1bXA6IGZhbHNlLFxuXG4gIFx0Ly8gQG9wdGlvbiBtYXhCb3VuZHNWaXNjb3NpdHk6IE51bWJlciA9IDAuMFxuICBcdC8vIElmIGBtYXhCb3VuZHNgIGlzIHNldCwgdGhpcyBvcHRpb24gd2lsbCBjb250cm9sIGhvdyBzb2xpZCB0aGUgYm91bmRzXG4gIFx0Ly8gYXJlIHdoZW4gZHJhZ2dpbmcgdGhlIG1hcCBhcm91bmQuIFRoZSBkZWZhdWx0IHZhbHVlIG9mIGAwLjBgIGFsbG93cyB0aGVcbiAgXHQvLyB1c2VyIHRvIGRyYWcgb3V0c2lkZSB0aGUgYm91bmRzIGF0IG5vcm1hbCBzcGVlZCwgaGlnaGVyIHZhbHVlcyB3aWxsXG4gIFx0Ly8gc2xvdyBkb3duIG1hcCBkcmFnZ2luZyBvdXRzaWRlIGJvdW5kcywgYW5kIGAxLjBgIG1ha2VzIHRoZSBib3VuZHMgZnVsbHlcbiAgXHQvLyBzb2xpZCwgcHJldmVudGluZyB0aGUgdXNlciBmcm9tIGRyYWdnaW5nIG91dHNpZGUgdGhlIGJvdW5kcy5cbiAgXHRtYXhCb3VuZHNWaXNjb3NpdHk6IDAuMFxuICB9KTtcblxuICB2YXIgRHJhZyA9IEhhbmRsZXIuZXh0ZW5kKHtcbiAgXHRhZGRIb29rczogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKCF0aGlzLl9kcmFnZ2FibGUpIHtcbiAgXHRcdFx0dmFyIG1hcCA9IHRoaXMuX21hcDtcblxuICBcdFx0XHR0aGlzLl9kcmFnZ2FibGUgPSBuZXcgRHJhZ2dhYmxlKG1hcC5fbWFwUGFuZSwgbWFwLl9jb250YWluZXIpO1xuXG4gIFx0XHRcdHRoaXMuX2RyYWdnYWJsZS5vbih7XG4gIFx0XHRcdFx0ZHJhZ3N0YXJ0OiB0aGlzLl9vbkRyYWdTdGFydCxcbiAgXHRcdFx0XHRkcmFnOiB0aGlzLl9vbkRyYWcsXG4gIFx0XHRcdFx0ZHJhZ2VuZDogdGhpcy5fb25EcmFnRW5kXG4gIFx0XHRcdH0sIHRoaXMpO1xuXG4gIFx0XHRcdHRoaXMuX2RyYWdnYWJsZS5vbigncHJlZHJhZycsIHRoaXMuX29uUHJlRHJhZ0xpbWl0LCB0aGlzKTtcbiAgXHRcdFx0aWYgKG1hcC5vcHRpb25zLndvcmxkQ29weUp1bXApIHtcbiAgXHRcdFx0XHR0aGlzLl9kcmFnZ2FibGUub24oJ3ByZWRyYWcnLCB0aGlzLl9vblByZURyYWdXcmFwLCB0aGlzKTtcbiAgXHRcdFx0XHRtYXAub24oJ3pvb21lbmQnLCB0aGlzLl9vblpvb21FbmQsIHRoaXMpO1xuXG4gIFx0XHRcdFx0bWFwLndoZW5SZWFkeSh0aGlzLl9vblpvb21FbmQsIHRoaXMpO1xuICBcdFx0XHR9XG4gIFx0XHR9XG4gIFx0XHRhZGRDbGFzcyh0aGlzLl9tYXAuX2NvbnRhaW5lciwgJ2xlYWZsZXQtZ3JhYiBsZWFmbGV0LXRvdWNoLWRyYWcnKTtcbiAgXHRcdHRoaXMuX2RyYWdnYWJsZS5lbmFibGUoKTtcbiAgXHRcdHRoaXMuX3Bvc2l0aW9ucyA9IFtdO1xuICBcdFx0dGhpcy5fdGltZXMgPSBbXTtcbiAgXHR9LFxuXG4gIFx0cmVtb3ZlSG9va3M6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHJlbW92ZUNsYXNzKHRoaXMuX21hcC5fY29udGFpbmVyLCAnbGVhZmxldC1ncmFiJyk7XG4gIFx0XHRyZW1vdmVDbGFzcyh0aGlzLl9tYXAuX2NvbnRhaW5lciwgJ2xlYWZsZXQtdG91Y2gtZHJhZycpO1xuICBcdFx0dGhpcy5fZHJhZ2dhYmxlLmRpc2FibGUoKTtcbiAgXHR9LFxuXG4gIFx0bW92ZWQ6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHJldHVybiB0aGlzLl9kcmFnZ2FibGUgJiYgdGhpcy5fZHJhZ2dhYmxlLl9tb3ZlZDtcbiAgXHR9LFxuXG4gIFx0bW92aW5nOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZXR1cm4gdGhpcy5fZHJhZ2dhYmxlICYmIHRoaXMuX2RyYWdnYWJsZS5fbW92aW5nO1xuICBcdH0sXG5cbiAgXHRfb25EcmFnU3RhcnQ6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHZhciBtYXAgPSB0aGlzLl9tYXA7XG5cbiAgXHRcdG1hcC5fc3RvcCgpO1xuICBcdFx0aWYgKHRoaXMuX21hcC5vcHRpb25zLm1heEJvdW5kcyAmJiB0aGlzLl9tYXAub3B0aW9ucy5tYXhCb3VuZHNWaXNjb3NpdHkpIHtcbiAgXHRcdFx0dmFyIGJvdW5kcyA9IHRvTGF0TG5nQm91bmRzKHRoaXMuX21hcC5vcHRpb25zLm1heEJvdW5kcyk7XG5cbiAgXHRcdFx0dGhpcy5fb2Zmc2V0TGltaXQgPSB0b0JvdW5kcyhcbiAgXHRcdFx0XHR0aGlzLl9tYXAubGF0TG5nVG9Db250YWluZXJQb2ludChib3VuZHMuZ2V0Tm9ydGhXZXN0KCkpLm11bHRpcGx5QnkoLTEpLFxuICBcdFx0XHRcdHRoaXMuX21hcC5sYXRMbmdUb0NvbnRhaW5lclBvaW50KGJvdW5kcy5nZXRTb3V0aEVhc3QoKSkubXVsdGlwbHlCeSgtMSlcbiAgXHRcdFx0XHRcdC5hZGQodGhpcy5fbWFwLmdldFNpemUoKSkpO1xuXG4gIFx0XHRcdHRoaXMuX3Zpc2Nvc2l0eSA9IE1hdGgubWluKDEuMCwgTWF0aC5tYXgoMC4wLCB0aGlzLl9tYXAub3B0aW9ucy5tYXhCb3VuZHNWaXNjb3NpdHkpKTtcbiAgXHRcdH0gZWxzZSB7XG4gIFx0XHRcdHRoaXMuX29mZnNldExpbWl0ID0gbnVsbDtcbiAgXHRcdH1cblxuICBcdFx0bWFwXG4gIFx0XHQgICAgLmZpcmUoJ21vdmVzdGFydCcpXG4gIFx0XHQgICAgLmZpcmUoJ2RyYWdzdGFydCcpO1xuXG4gIFx0XHRpZiAobWFwLm9wdGlvbnMuaW5lcnRpYSkge1xuICBcdFx0XHR0aGlzLl9wb3NpdGlvbnMgPSBbXTtcbiAgXHRcdFx0dGhpcy5fdGltZXMgPSBbXTtcbiAgXHRcdH1cbiAgXHR9LFxuXG4gIFx0X29uRHJhZzogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdGlmICh0aGlzLl9tYXAub3B0aW9ucy5pbmVydGlhKSB7XG4gIFx0XHRcdHZhciB0aW1lID0gdGhpcy5fbGFzdFRpbWUgPSArbmV3IERhdGUoKSxcbiAgXHRcdFx0ICAgIHBvcyA9IHRoaXMuX2xhc3RQb3MgPSB0aGlzLl9kcmFnZ2FibGUuX2Fic1BvcyB8fCB0aGlzLl9kcmFnZ2FibGUuX25ld1BvcztcblxuICBcdFx0XHR0aGlzLl9wb3NpdGlvbnMucHVzaChwb3MpO1xuICBcdFx0XHR0aGlzLl90aW1lcy5wdXNoKHRpbWUpO1xuXG4gIFx0XHRcdHRoaXMuX3BydW5lUG9zaXRpb25zKHRpbWUpO1xuICBcdFx0fVxuXG4gIFx0XHR0aGlzLl9tYXBcbiAgXHRcdCAgICAuZmlyZSgnbW92ZScsIGUpXG4gIFx0XHQgICAgLmZpcmUoJ2RyYWcnLCBlKTtcbiAgXHR9LFxuXG4gIFx0X3BydW5lUG9zaXRpb25zOiBmdW5jdGlvbiAodGltZSkge1xuICBcdFx0d2hpbGUgKHRoaXMuX3Bvc2l0aW9ucy5sZW5ndGggPiAxICYmIHRpbWUgLSB0aGlzLl90aW1lc1swXSA+IDUwKSB7XG4gIFx0XHRcdHRoaXMuX3Bvc2l0aW9ucy5zaGlmdCgpO1xuICBcdFx0XHR0aGlzLl90aW1lcy5zaGlmdCgpO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfb25ab29tRW5kOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR2YXIgcHhDZW50ZXIgPSB0aGlzLl9tYXAuZ2V0U2l6ZSgpLmRpdmlkZUJ5KDIpLFxuICBcdFx0ICAgIHB4V29ybGRDZW50ZXIgPSB0aGlzLl9tYXAubGF0TG5nVG9MYXllclBvaW50KFswLCAwXSk7XG5cbiAgXHRcdHRoaXMuX2luaXRpYWxXb3JsZE9mZnNldCA9IHB4V29ybGRDZW50ZXIuc3VidHJhY3QocHhDZW50ZXIpLng7XG4gIFx0XHR0aGlzLl93b3JsZFdpZHRoID0gdGhpcy5fbWFwLmdldFBpeGVsV29ybGRCb3VuZHMoKS5nZXRTaXplKCkueDtcbiAgXHR9LFxuXG4gIFx0X3Zpc2NvdXNMaW1pdDogZnVuY3Rpb24gKHZhbHVlLCB0aHJlc2hvbGQpIHtcbiAgXHRcdHJldHVybiB2YWx1ZSAtICh2YWx1ZSAtIHRocmVzaG9sZCkgKiB0aGlzLl92aXNjb3NpdHk7XG4gIFx0fSxcblxuICBcdF9vblByZURyYWdMaW1pdDogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKCF0aGlzLl92aXNjb3NpdHkgfHwgIXRoaXMuX29mZnNldExpbWl0KSB7IHJldHVybjsgfVxuXG4gIFx0XHR2YXIgb2Zmc2V0ID0gdGhpcy5fZHJhZ2dhYmxlLl9uZXdQb3Muc3VidHJhY3QodGhpcy5fZHJhZ2dhYmxlLl9zdGFydFBvcyk7XG5cbiAgXHRcdHZhciBsaW1pdCA9IHRoaXMuX29mZnNldExpbWl0O1xuICBcdFx0aWYgKG9mZnNldC54IDwgbGltaXQubWluLngpIHsgb2Zmc2V0LnggPSB0aGlzLl92aXNjb3VzTGltaXQob2Zmc2V0LngsIGxpbWl0Lm1pbi54KTsgfVxuICBcdFx0aWYgKG9mZnNldC55IDwgbGltaXQubWluLnkpIHsgb2Zmc2V0LnkgPSB0aGlzLl92aXNjb3VzTGltaXQob2Zmc2V0LnksIGxpbWl0Lm1pbi55KTsgfVxuICBcdFx0aWYgKG9mZnNldC54ID4gbGltaXQubWF4LngpIHsgb2Zmc2V0LnggPSB0aGlzLl92aXNjb3VzTGltaXQob2Zmc2V0LngsIGxpbWl0Lm1heC54KTsgfVxuICBcdFx0aWYgKG9mZnNldC55ID4gbGltaXQubWF4LnkpIHsgb2Zmc2V0LnkgPSB0aGlzLl92aXNjb3VzTGltaXQob2Zmc2V0LnksIGxpbWl0Lm1heC55KTsgfVxuXG4gIFx0XHR0aGlzLl9kcmFnZ2FibGUuX25ld1BvcyA9IHRoaXMuX2RyYWdnYWJsZS5fc3RhcnRQb3MuYWRkKG9mZnNldCk7XG4gIFx0fSxcblxuICBcdF9vblByZURyYWdXcmFwOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHQvLyBUT0RPIHJlZmFjdG9yIHRvIGJlIGFibGUgdG8gYWRqdXN0IG1hcCBwYW5lIHBvc2l0aW9uIGFmdGVyIHpvb21cbiAgXHRcdHZhciB3b3JsZFdpZHRoID0gdGhpcy5fd29ybGRXaWR0aCxcbiAgXHRcdCAgICBoYWxmV2lkdGggPSBNYXRoLnJvdW5kKHdvcmxkV2lkdGggLyAyKSxcbiAgXHRcdCAgICBkeCA9IHRoaXMuX2luaXRpYWxXb3JsZE9mZnNldCxcbiAgXHRcdCAgICB4ID0gdGhpcy5fZHJhZ2dhYmxlLl9uZXdQb3MueCxcbiAgXHRcdCAgICBuZXdYMSA9ICh4IC0gaGFsZldpZHRoICsgZHgpICUgd29ybGRXaWR0aCArIGhhbGZXaWR0aCAtIGR4LFxuICBcdFx0ICAgIG5ld1gyID0gKHggKyBoYWxmV2lkdGggKyBkeCkgJSB3b3JsZFdpZHRoIC0gaGFsZldpZHRoIC0gZHgsXG4gIFx0XHQgICAgbmV3WCA9IE1hdGguYWJzKG5ld1gxICsgZHgpIDwgTWF0aC5hYnMobmV3WDIgKyBkeCkgPyBuZXdYMSA6IG5ld1gyO1xuXG4gIFx0XHR0aGlzLl9kcmFnZ2FibGUuX2Fic1BvcyA9IHRoaXMuX2RyYWdnYWJsZS5fbmV3UG9zLmNsb25lKCk7XG4gIFx0XHR0aGlzLl9kcmFnZ2FibGUuX25ld1Bvcy54ID0gbmV3WDtcbiAgXHR9LFxuXG4gIFx0X29uRHJhZ0VuZDogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdHZhciBtYXAgPSB0aGlzLl9tYXAsXG4gIFx0XHQgICAgb3B0aW9ucyA9IG1hcC5vcHRpb25zLFxuXG4gIFx0XHQgICAgbm9JbmVydGlhID0gIW9wdGlvbnMuaW5lcnRpYSB8fCBlLm5vSW5lcnRpYSB8fCB0aGlzLl90aW1lcy5sZW5ndGggPCAyO1xuXG4gIFx0XHRtYXAuZmlyZSgnZHJhZ2VuZCcsIGUpO1xuXG4gIFx0XHRpZiAobm9JbmVydGlhKSB7XG4gIFx0XHRcdG1hcC5maXJlKCdtb3ZlZW5kJyk7XG5cbiAgXHRcdH0gZWxzZSB7XG4gIFx0XHRcdHRoaXMuX3BydW5lUG9zaXRpb25zKCtuZXcgRGF0ZSgpKTtcblxuICBcdFx0XHR2YXIgZGlyZWN0aW9uID0gdGhpcy5fbGFzdFBvcy5zdWJ0cmFjdCh0aGlzLl9wb3NpdGlvbnNbMF0pLFxuICBcdFx0XHQgICAgZHVyYXRpb24gPSAodGhpcy5fbGFzdFRpbWUgLSB0aGlzLl90aW1lc1swXSkgLyAxMDAwLFxuICBcdFx0XHQgICAgZWFzZSA9IG9wdGlvbnMuZWFzZUxpbmVhcml0eSxcblxuICBcdFx0XHQgICAgc3BlZWRWZWN0b3IgPSBkaXJlY3Rpb24ubXVsdGlwbHlCeShlYXNlIC8gZHVyYXRpb24pLFxuICBcdFx0XHQgICAgc3BlZWQgPSBzcGVlZFZlY3Rvci5kaXN0YW5jZVRvKFswLCAwXSksXG5cbiAgXHRcdFx0ICAgIGxpbWl0ZWRTcGVlZCA9IE1hdGgubWluKG9wdGlvbnMuaW5lcnRpYU1heFNwZWVkLCBzcGVlZCksXG4gIFx0XHRcdCAgICBsaW1pdGVkU3BlZWRWZWN0b3IgPSBzcGVlZFZlY3Rvci5tdWx0aXBseUJ5KGxpbWl0ZWRTcGVlZCAvIHNwZWVkKSxcblxuICBcdFx0XHQgICAgZGVjZWxlcmF0aW9uRHVyYXRpb24gPSBsaW1pdGVkU3BlZWQgLyAob3B0aW9ucy5pbmVydGlhRGVjZWxlcmF0aW9uICogZWFzZSksXG4gIFx0XHRcdCAgICBvZmZzZXQgPSBsaW1pdGVkU3BlZWRWZWN0b3IubXVsdGlwbHlCeSgtZGVjZWxlcmF0aW9uRHVyYXRpb24gLyAyKS5yb3VuZCgpO1xuXG4gIFx0XHRcdGlmICghb2Zmc2V0LnggJiYgIW9mZnNldC55KSB7XG4gIFx0XHRcdFx0bWFwLmZpcmUoJ21vdmVlbmQnKTtcblxuICBcdFx0XHR9IGVsc2Uge1xuICBcdFx0XHRcdG9mZnNldCA9IG1hcC5fbGltaXRPZmZzZXQob2Zmc2V0LCBtYXAub3B0aW9ucy5tYXhCb3VuZHMpO1xuXG4gIFx0XHRcdFx0cmVxdWVzdEFuaW1GcmFtZShmdW5jdGlvbiAoKSB7XG4gIFx0XHRcdFx0XHRtYXAucGFuQnkob2Zmc2V0LCB7XG4gIFx0XHRcdFx0XHRcdGR1cmF0aW9uOiBkZWNlbGVyYXRpb25EdXJhdGlvbixcbiAgXHRcdFx0XHRcdFx0ZWFzZUxpbmVhcml0eTogZWFzZSxcbiAgXHRcdFx0XHRcdFx0bm9Nb3ZlU3RhcnQ6IHRydWUsXG4gIFx0XHRcdFx0XHRcdGFuaW1hdGU6IHRydWVcbiAgXHRcdFx0XHRcdH0pO1xuICBcdFx0XHRcdH0pO1xuICBcdFx0XHR9XG4gIFx0XHR9XG4gIFx0fVxuICB9KTtcblxuICAvLyBAc2VjdGlvbiBIYW5kbGVyc1xuICAvLyBAcHJvcGVydHkgZHJhZ2dpbmc6IEhhbmRsZXJcbiAgLy8gTWFwIGRyYWdnaW5nIGhhbmRsZXIgKGJ5IGJvdGggbW91c2UgYW5kIHRvdWNoKS5cbiAgTWFwLmFkZEluaXRIb29rKCdhZGRIYW5kbGVyJywgJ2RyYWdnaW5nJywgRHJhZyk7XG5cbiAgLypcbiAgICogTC5NYXAuS2V5Ym9hcmQgaXMgaGFuZGxpbmcga2V5Ym9hcmQgaW50ZXJhY3Rpb24gd2l0aCB0aGUgbWFwLCBlbmFibGVkIGJ5IGRlZmF1bHQuXG4gICAqL1xuXG4gIC8vIEBuYW1lc3BhY2UgTWFwXG4gIC8vIEBzZWN0aW9uIEtleWJvYXJkIE5hdmlnYXRpb24gT3B0aW9uc1xuICBNYXAubWVyZ2VPcHRpb25zKHtcbiAgXHQvLyBAb3B0aW9uIGtleWJvYXJkOiBCb29sZWFuID0gdHJ1ZVxuICBcdC8vIE1ha2VzIHRoZSBtYXAgZm9jdXNhYmxlIGFuZCBhbGxvd3MgdXNlcnMgdG8gbmF2aWdhdGUgdGhlIG1hcCB3aXRoIGtleWJvYXJkXG4gIFx0Ly8gYXJyb3dzIGFuZCBgK2AvYC1gIGtleXMuXG4gIFx0a2V5Ym9hcmQ6IHRydWUsXG5cbiAgXHQvLyBAb3B0aW9uIGtleWJvYXJkUGFuRGVsdGE6IE51bWJlciA9IDgwXG4gIFx0Ly8gQW1vdW50IG9mIHBpeGVscyB0byBwYW4gd2hlbiBwcmVzc2luZyBhbiBhcnJvdyBrZXkuXG4gIFx0a2V5Ym9hcmRQYW5EZWx0YTogODBcbiAgfSk7XG5cbiAgdmFyIEtleWJvYXJkID0gSGFuZGxlci5leHRlbmQoe1xuXG4gIFx0a2V5Q29kZXM6IHtcbiAgXHRcdGxlZnQ6ICAgIFszN10sXG4gIFx0XHRyaWdodDogICBbMzldLFxuICBcdFx0ZG93bjogICAgWzQwXSxcbiAgXHRcdHVwOiAgICAgIFszOF0sXG4gIFx0XHR6b29tSW46ICBbMTg3LCAxMDcsIDYxLCAxNzFdLFxuICBcdFx0em9vbU91dDogWzE4OSwgMTA5LCA1NCwgMTczXVxuICBcdH0sXG5cbiAgXHRpbml0aWFsaXplOiBmdW5jdGlvbiAobWFwKSB7XG4gIFx0XHR0aGlzLl9tYXAgPSBtYXA7XG5cbiAgXHRcdHRoaXMuX3NldFBhbkRlbHRhKG1hcC5vcHRpb25zLmtleWJvYXJkUGFuRGVsdGEpO1xuICBcdFx0dGhpcy5fc2V0Wm9vbURlbHRhKG1hcC5vcHRpb25zLnpvb21EZWx0YSk7XG4gIFx0fSxcblxuICBcdGFkZEhvb2tzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR2YXIgY29udGFpbmVyID0gdGhpcy5fbWFwLl9jb250YWluZXI7XG5cbiAgXHRcdC8vIG1ha2UgdGhlIGNvbnRhaW5lciBmb2N1c2FibGUgYnkgdGFiYmluZ1xuICBcdFx0aWYgKGNvbnRhaW5lci50YWJJbmRleCA8PSAwKSB7XG4gIFx0XHRcdGNvbnRhaW5lci50YWJJbmRleCA9ICcwJztcbiAgXHRcdH1cblxuICBcdFx0b24oY29udGFpbmVyLCB7XG4gIFx0XHRcdGZvY3VzOiB0aGlzLl9vbkZvY3VzLFxuICBcdFx0XHRibHVyOiB0aGlzLl9vbkJsdXIsXG4gIFx0XHRcdG1vdXNlZG93bjogdGhpcy5fb25Nb3VzZURvd25cbiAgXHRcdH0sIHRoaXMpO1xuXG4gIFx0XHR0aGlzLl9tYXAub24oe1xuICBcdFx0XHRmb2N1czogdGhpcy5fYWRkSG9va3MsXG4gIFx0XHRcdGJsdXI6IHRoaXMuX3JlbW92ZUhvb2tzXG4gIFx0XHR9LCB0aGlzKTtcbiAgXHR9LFxuXG4gIFx0cmVtb3ZlSG9va3M6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdHRoaXMuX3JlbW92ZUhvb2tzKCk7XG5cbiAgXHRcdG9mZih0aGlzLl9tYXAuX2NvbnRhaW5lciwge1xuICBcdFx0XHRmb2N1czogdGhpcy5fb25Gb2N1cyxcbiAgXHRcdFx0Ymx1cjogdGhpcy5fb25CbHVyLFxuICBcdFx0XHRtb3VzZWRvd246IHRoaXMuX29uTW91c2VEb3duXG4gIFx0XHR9LCB0aGlzKTtcblxuICBcdFx0dGhpcy5fbWFwLm9mZih7XG4gIFx0XHRcdGZvY3VzOiB0aGlzLl9hZGRIb29rcyxcbiAgXHRcdFx0Ymx1cjogdGhpcy5fcmVtb3ZlSG9va3NcbiAgXHRcdH0sIHRoaXMpO1xuICBcdH0sXG5cbiAgXHRfb25Nb3VzZURvd246IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGlmICh0aGlzLl9mb2N1c2VkKSB7IHJldHVybjsgfVxuXG4gIFx0XHR2YXIgYm9keSA9IGRvY3VtZW50LmJvZHksXG4gIFx0XHQgICAgZG9jRWwgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsXG4gIFx0XHQgICAgdG9wID0gYm9keS5zY3JvbGxUb3AgfHwgZG9jRWwuc2Nyb2xsVG9wLFxuICBcdFx0ICAgIGxlZnQgPSBib2R5LnNjcm9sbExlZnQgfHwgZG9jRWwuc2Nyb2xsTGVmdDtcblxuICBcdFx0dGhpcy5fbWFwLl9jb250YWluZXIuZm9jdXMoKTtcblxuICBcdFx0d2luZG93LnNjcm9sbFRvKGxlZnQsIHRvcCk7XG4gIFx0fSxcblxuICBcdF9vbkZvY3VzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR0aGlzLl9mb2N1c2VkID0gdHJ1ZTtcbiAgXHRcdHRoaXMuX21hcC5maXJlKCdmb2N1cycpO1xuICBcdH0sXG5cbiAgXHRfb25CbHVyOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHR0aGlzLl9mb2N1c2VkID0gZmFsc2U7XG4gIFx0XHR0aGlzLl9tYXAuZmlyZSgnYmx1cicpO1xuICBcdH0sXG5cbiAgXHRfc2V0UGFuRGVsdGE6IGZ1bmN0aW9uIChwYW5EZWx0YSkge1xuICBcdFx0dmFyIGtleXMgPSB0aGlzLl9wYW5LZXlzID0ge30sXG4gIFx0XHQgICAgY29kZXMgPSB0aGlzLmtleUNvZGVzLFxuICBcdFx0ICAgIGksIGxlbjtcblxuICBcdFx0Zm9yIChpID0gMCwgbGVuID0gY29kZXMubGVmdC5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICBcdFx0XHRrZXlzW2NvZGVzLmxlZnRbaV1dID0gWy0xICogcGFuRGVsdGEsIDBdO1xuICBcdFx0fVxuICBcdFx0Zm9yIChpID0gMCwgbGVuID0gY29kZXMucmlnaHQubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgXHRcdFx0a2V5c1tjb2Rlcy5yaWdodFtpXV0gPSBbcGFuRGVsdGEsIDBdO1xuICBcdFx0fVxuICBcdFx0Zm9yIChpID0gMCwgbGVuID0gY29kZXMuZG93bi5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICBcdFx0XHRrZXlzW2NvZGVzLmRvd25baV1dID0gWzAsIHBhbkRlbHRhXTtcbiAgXHRcdH1cbiAgXHRcdGZvciAoaSA9IDAsIGxlbiA9IGNvZGVzLnVwLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gIFx0XHRcdGtleXNbY29kZXMudXBbaV1dID0gWzAsIC0xICogcGFuRGVsdGFdO1xuICBcdFx0fVxuICBcdH0sXG5cbiAgXHRfc2V0Wm9vbURlbHRhOiBmdW5jdGlvbiAoem9vbURlbHRhKSB7XG4gIFx0XHR2YXIga2V5cyA9IHRoaXMuX3pvb21LZXlzID0ge30sXG4gIFx0XHQgICAgY29kZXMgPSB0aGlzLmtleUNvZGVzLFxuICBcdFx0ICAgIGksIGxlbjtcblxuICBcdFx0Zm9yIChpID0gMCwgbGVuID0gY29kZXMuem9vbUluLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gIFx0XHRcdGtleXNbY29kZXMuem9vbUluW2ldXSA9IHpvb21EZWx0YTtcbiAgXHRcdH1cbiAgXHRcdGZvciAoaSA9IDAsIGxlbiA9IGNvZGVzLnpvb21PdXQubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgXHRcdFx0a2V5c1tjb2Rlcy56b29tT3V0W2ldXSA9IC16b29tRGVsdGE7XG4gIFx0XHR9XG4gIFx0fSxcblxuICBcdF9hZGRIb29rczogZnVuY3Rpb24gKCkge1xuICBcdFx0b24oZG9jdW1lbnQsICdrZXlkb3duJywgdGhpcy5fb25LZXlEb3duLCB0aGlzKTtcbiAgXHR9LFxuXG4gIFx0X3JlbW92ZUhvb2tzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRvZmYoZG9jdW1lbnQsICdrZXlkb3duJywgdGhpcy5fb25LZXlEb3duLCB0aGlzKTtcbiAgXHR9LFxuXG4gIFx0X29uS2V5RG93bjogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdGlmIChlLmFsdEtleSB8fCBlLmN0cmxLZXkgfHwgZS5tZXRhS2V5KSB7IHJldHVybjsgfVxuXG4gIFx0XHR2YXIga2V5ID0gZS5rZXlDb2RlLFxuICBcdFx0ICAgIG1hcCA9IHRoaXMuX21hcCxcbiAgXHRcdCAgICBvZmZzZXQ7XG5cbiAgXHRcdGlmIChrZXkgaW4gdGhpcy5fcGFuS2V5cykge1xuICBcdFx0XHRpZiAoIW1hcC5fcGFuQW5pbSB8fCAhbWFwLl9wYW5BbmltLl9pblByb2dyZXNzKSB7XG4gIFx0XHRcdFx0b2Zmc2V0ID0gdGhpcy5fcGFuS2V5c1trZXldO1xuICBcdFx0XHRcdGlmIChlLnNoaWZ0S2V5KSB7XG4gIFx0XHRcdFx0XHRvZmZzZXQgPSB0b1BvaW50KG9mZnNldCkubXVsdGlwbHlCeSgzKTtcbiAgXHRcdFx0XHR9XG5cbiAgXHRcdFx0XHRpZiAobWFwLm9wdGlvbnMubWF4Qm91bmRzKSB7XG4gIFx0XHRcdFx0XHRvZmZzZXQgPSBtYXAuX2xpbWl0T2Zmc2V0KHRvUG9pbnQob2Zmc2V0KSwgbWFwLm9wdGlvbnMubWF4Qm91bmRzKTtcbiAgXHRcdFx0XHR9XG5cbiAgXHRcdFx0XHRpZiAobWFwLm9wdGlvbnMud29ybGRDb3B5SnVtcCkge1xuICBcdFx0XHRcdFx0dmFyIG5ld0xhdExuZyA9IG1hcC53cmFwTGF0TG5nKG1hcC51bnByb2plY3QobWFwLnByb2plY3QobWFwLmdldENlbnRlcigpKS5hZGQob2Zmc2V0KSkpO1xuICBcdFx0XHRcdFx0bWFwLnBhblRvKG5ld0xhdExuZyk7XG4gIFx0XHRcdFx0fSBlbHNlIHtcbiAgXHRcdFx0XHRcdG1hcC5wYW5CeShvZmZzZXQpO1xuICBcdFx0XHRcdH1cbiAgXHRcdFx0fVxuICBcdFx0fSBlbHNlIGlmIChrZXkgaW4gdGhpcy5fem9vbUtleXMpIHtcbiAgXHRcdFx0bWFwLnNldFpvb20obWFwLmdldFpvb20oKSArIChlLnNoaWZ0S2V5ID8gMyA6IDEpICogdGhpcy5fem9vbUtleXNba2V5XSk7XG5cbiAgXHRcdH0gZWxzZSBpZiAoa2V5ID09PSAyNyAmJiBtYXAuX3BvcHVwICYmIG1hcC5fcG9wdXAub3B0aW9ucy5jbG9zZU9uRXNjYXBlS2V5KSB7XG4gIFx0XHRcdG1hcC5jbG9zZVBvcHVwKCk7XG5cbiAgXHRcdH0gZWxzZSB7XG4gIFx0XHRcdHJldHVybjtcbiAgXHRcdH1cblxuICBcdFx0c3RvcChlKTtcbiAgXHR9XG4gIH0pO1xuXG4gIC8vIEBzZWN0aW9uIEhhbmRsZXJzXG4gIC8vIEBzZWN0aW9uIEhhbmRsZXJzXG4gIC8vIEBwcm9wZXJ0eSBrZXlib2FyZDogSGFuZGxlclxuICAvLyBLZXlib2FyZCBuYXZpZ2F0aW9uIGhhbmRsZXIuXG4gIE1hcC5hZGRJbml0SG9vaygnYWRkSGFuZGxlcicsICdrZXlib2FyZCcsIEtleWJvYXJkKTtcblxuICAvKlxuICAgKiBMLkhhbmRsZXIuU2Nyb2xsV2hlZWxab29tIGlzIHVzZWQgYnkgTC5NYXAgdG8gZW5hYmxlIG1vdXNlIHNjcm9sbCB3aGVlbCB6b29tIG9uIHRoZSBtYXAuXG4gICAqL1xuXG4gIC8vIEBuYW1lc3BhY2UgTWFwXG4gIC8vIEBzZWN0aW9uIEludGVyYWN0aW9uIE9wdGlvbnNcbiAgTWFwLm1lcmdlT3B0aW9ucyh7XG4gIFx0Ly8gQHNlY3Rpb24gTW91c2Ugd2hlZWwgb3B0aW9uc1xuICBcdC8vIEBvcHRpb24gc2Nyb2xsV2hlZWxab29tOiBCb29sZWFufFN0cmluZyA9IHRydWVcbiAgXHQvLyBXaGV0aGVyIHRoZSBtYXAgY2FuIGJlIHpvb21lZCBieSB1c2luZyB0aGUgbW91c2Ugd2hlZWwuIElmIHBhc3NlZCBgJ2NlbnRlcidgLFxuICBcdC8vIGl0IHdpbGwgem9vbSB0byB0aGUgY2VudGVyIG9mIHRoZSB2aWV3IHJlZ2FyZGxlc3Mgb2Ygd2hlcmUgdGhlIG1vdXNlIHdhcy5cbiAgXHRzY3JvbGxXaGVlbFpvb206IHRydWUsXG5cbiAgXHQvLyBAb3B0aW9uIHdoZWVsRGVib3VuY2VUaW1lOiBOdW1iZXIgPSA0MFxuICBcdC8vIExpbWl0cyB0aGUgcmF0ZSBhdCB3aGljaCBhIHdoZWVsIGNhbiBmaXJlIChpbiBtaWxsaXNlY29uZHMpLiBCeSBkZWZhdWx0XG4gIFx0Ly8gdXNlciBjYW4ndCB6b29tIHZpYSB3aGVlbCBtb3JlIG9mdGVuIHRoYW4gb25jZSBwZXIgNDAgbXMuXG4gIFx0d2hlZWxEZWJvdW5jZVRpbWU6IDQwLFxuXG4gIFx0Ly8gQG9wdGlvbiB3aGVlbFB4UGVyWm9vbUxldmVsOiBOdW1iZXIgPSA2MFxuICBcdC8vIEhvdyBtYW55IHNjcm9sbCBwaXhlbHMgKGFzIHJlcG9ydGVkIGJ5IFtMLkRvbUV2ZW50LmdldFdoZWVsRGVsdGFdKCNkb21ldmVudC1nZXR3aGVlbGRlbHRhKSlcbiAgXHQvLyBtZWFuIGEgY2hhbmdlIG9mIG9uZSBmdWxsIHpvb20gbGV2ZWwuIFNtYWxsZXIgdmFsdWVzIHdpbGwgbWFrZSB3aGVlbC16b29taW5nXG4gIFx0Ly8gZmFzdGVyIChhbmQgdmljZSB2ZXJzYSkuXG4gIFx0d2hlZWxQeFBlclpvb21MZXZlbDogNjBcbiAgfSk7XG5cbiAgdmFyIFNjcm9sbFdoZWVsWm9vbSA9IEhhbmRsZXIuZXh0ZW5kKHtcbiAgXHRhZGRIb29rczogZnVuY3Rpb24gKCkge1xuICBcdFx0b24odGhpcy5fbWFwLl9jb250YWluZXIsICd3aGVlbCcsIHRoaXMuX29uV2hlZWxTY3JvbGwsIHRoaXMpO1xuXG4gIFx0XHR0aGlzLl9kZWx0YSA9IDA7XG4gIFx0fSxcblxuICBcdHJlbW92ZUhvb2tzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRvZmYodGhpcy5fbWFwLl9jb250YWluZXIsICd3aGVlbCcsIHRoaXMuX29uV2hlZWxTY3JvbGwsIHRoaXMpO1xuICBcdH0sXG5cbiAgXHRfb25XaGVlbFNjcm9sbDogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdHZhciBkZWx0YSA9IGdldFdoZWVsRGVsdGEoZSk7XG5cbiAgXHRcdHZhciBkZWJvdW5jZSA9IHRoaXMuX21hcC5vcHRpb25zLndoZWVsRGVib3VuY2VUaW1lO1xuXG4gIFx0XHR0aGlzLl9kZWx0YSArPSBkZWx0YTtcbiAgXHRcdHRoaXMuX2xhc3RNb3VzZVBvcyA9IHRoaXMuX21hcC5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlKTtcblxuICBcdFx0aWYgKCF0aGlzLl9zdGFydFRpbWUpIHtcbiAgXHRcdFx0dGhpcy5fc3RhcnRUaW1lID0gK25ldyBEYXRlKCk7XG4gIFx0XHR9XG5cbiAgXHRcdHZhciBsZWZ0ID0gTWF0aC5tYXgoZGVib3VuY2UgLSAoK25ldyBEYXRlKCkgLSB0aGlzLl9zdGFydFRpbWUpLCAwKTtcblxuICBcdFx0Y2xlYXJUaW1lb3V0KHRoaXMuX3RpbWVyKTtcbiAgXHRcdHRoaXMuX3RpbWVyID0gc2V0VGltZW91dChiaW5kKHRoaXMuX3BlcmZvcm1ab29tLCB0aGlzKSwgbGVmdCk7XG5cbiAgXHRcdHN0b3AoZSk7XG4gIFx0fSxcblxuICBcdF9wZXJmb3JtWm9vbTogZnVuY3Rpb24gKCkge1xuICBcdFx0dmFyIG1hcCA9IHRoaXMuX21hcCxcbiAgXHRcdCAgICB6b29tID0gbWFwLmdldFpvb20oKSxcbiAgXHRcdCAgICBzbmFwID0gdGhpcy5fbWFwLm9wdGlvbnMuem9vbVNuYXAgfHwgMDtcblxuICBcdFx0bWFwLl9zdG9wKCk7IC8vIHN0b3AgcGFubmluZyBhbmQgZmx5IGFuaW1hdGlvbnMgaWYgYW55XG5cbiAgXHRcdC8vIG1hcCB0aGUgZGVsdGEgd2l0aCBhIHNpZ21vaWQgZnVuY3Rpb24gdG8gLTQuLjQgcmFuZ2UgbGVhbmluZyBvbiAtMS4uMVxuICBcdFx0dmFyIGQyID0gdGhpcy5fZGVsdGEgLyAodGhpcy5fbWFwLm9wdGlvbnMud2hlZWxQeFBlclpvb21MZXZlbCAqIDQpLFxuICBcdFx0ICAgIGQzID0gNCAqIE1hdGgubG9nKDIgLyAoMSArIE1hdGguZXhwKC1NYXRoLmFicyhkMikpKSkgLyBNYXRoLkxOMixcbiAgXHRcdCAgICBkNCA9IHNuYXAgPyBNYXRoLmNlaWwoZDMgLyBzbmFwKSAqIHNuYXAgOiBkMyxcbiAgXHRcdCAgICBkZWx0YSA9IG1hcC5fbGltaXRab29tKHpvb20gKyAodGhpcy5fZGVsdGEgPiAwID8gZDQgOiAtZDQpKSAtIHpvb207XG5cbiAgXHRcdHRoaXMuX2RlbHRhID0gMDtcbiAgXHRcdHRoaXMuX3N0YXJ0VGltZSA9IG51bGw7XG5cbiAgXHRcdGlmICghZGVsdGEpIHsgcmV0dXJuOyB9XG5cbiAgXHRcdGlmIChtYXAub3B0aW9ucy5zY3JvbGxXaGVlbFpvb20gPT09ICdjZW50ZXInKSB7XG4gIFx0XHRcdG1hcC5zZXRab29tKHpvb20gKyBkZWx0YSk7XG4gIFx0XHR9IGVsc2Uge1xuICBcdFx0XHRtYXAuc2V0Wm9vbUFyb3VuZCh0aGlzLl9sYXN0TW91c2VQb3MsIHpvb20gKyBkZWx0YSk7XG4gIFx0XHR9XG4gIFx0fVxuICB9KTtcblxuICAvLyBAc2VjdGlvbiBIYW5kbGVyc1xuICAvLyBAcHJvcGVydHkgc2Nyb2xsV2hlZWxab29tOiBIYW5kbGVyXG4gIC8vIFNjcm9sbCB3aGVlbCB6b29tIGhhbmRsZXIuXG4gIE1hcC5hZGRJbml0SG9vaygnYWRkSGFuZGxlcicsICdzY3JvbGxXaGVlbFpvb20nLCBTY3JvbGxXaGVlbFpvb20pO1xuXG4gIC8qXG4gICAqIEwuTWFwLlRhcEhvbGQgaXMgdXNlZCB0byBzaW11bGF0ZSBgY29udGV4dG1lbnVgIGV2ZW50IG9uIGxvbmcgaG9sZCxcbiAgICogd2hpY2ggb3RoZXJ3aXNlIGlzIG5vdCBmaXJlZCBieSBtb2JpbGUgU2FmYXJpLlxuICAgKi9cblxuICB2YXIgdGFwSG9sZERlbGF5ID0gNjAwO1xuXG4gIC8vIEBuYW1lc3BhY2UgTWFwXG4gIC8vIEBzZWN0aW9uIEludGVyYWN0aW9uIE9wdGlvbnNcbiAgTWFwLm1lcmdlT3B0aW9ucyh7XG4gIFx0Ly8gQHNlY3Rpb24gVG91Y2ggaW50ZXJhY3Rpb24gb3B0aW9uc1xuICBcdC8vIEBvcHRpb24gdGFwSG9sZDogQm9vbGVhblxuICBcdC8vIEVuYWJsZXMgc2ltdWxhdGlvbiBvZiBgY29udGV4dG1lbnVgIGV2ZW50LCBkZWZhdWx0IGlzIGB0cnVlYCBmb3IgbW9iaWxlIFNhZmFyaS5cbiAgXHR0YXBIb2xkOiBCcm93c2VyLnRvdWNoTmF0aXZlICYmIEJyb3dzZXIuc2FmYXJpICYmIEJyb3dzZXIubW9iaWxlLFxuXG4gIFx0Ly8gQG9wdGlvbiB0YXBUb2xlcmFuY2U6IE51bWJlciA9IDE1XG4gIFx0Ly8gVGhlIG1heCBudW1iZXIgb2YgcGl4ZWxzIGEgdXNlciBjYW4gc2hpZnQgaGlzIGZpbmdlciBkdXJpbmcgdG91Y2hcbiAgXHQvLyBmb3IgaXQgdG8gYmUgY29uc2lkZXJlZCBhIHZhbGlkIHRhcC5cbiAgXHR0YXBUb2xlcmFuY2U6IDE1XG4gIH0pO1xuXG4gIHZhciBUYXBIb2xkID0gSGFuZGxlci5leHRlbmQoe1xuICBcdGFkZEhvb2tzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRvbih0aGlzLl9tYXAuX2NvbnRhaW5lciwgJ3RvdWNoc3RhcnQnLCB0aGlzLl9vbkRvd24sIHRoaXMpO1xuICBcdH0sXG5cbiAgXHRyZW1vdmVIb29rczogZnVuY3Rpb24gKCkge1xuICBcdFx0b2ZmKHRoaXMuX21hcC5fY29udGFpbmVyLCAndG91Y2hzdGFydCcsIHRoaXMuX29uRG93biwgdGhpcyk7XG4gIFx0fSxcblxuICBcdF9vbkRvd246IGZ1bmN0aW9uIChlKSB7XG4gIFx0XHRjbGVhclRpbWVvdXQodGhpcy5faG9sZFRpbWVvdXQpO1xuICBcdFx0aWYgKGUudG91Y2hlcy5sZW5ndGggIT09IDEpIHsgcmV0dXJuOyB9XG5cbiAgXHRcdHZhciBmaXJzdCA9IGUudG91Y2hlc1swXTtcbiAgXHRcdHRoaXMuX3N0YXJ0UG9zID0gdGhpcy5fbmV3UG9zID0gbmV3IFBvaW50KGZpcnN0LmNsaWVudFgsIGZpcnN0LmNsaWVudFkpO1xuXG4gIFx0XHR0aGlzLl9ob2xkVGltZW91dCA9IHNldFRpbWVvdXQoYmluZChmdW5jdGlvbiAoKSB7XG4gIFx0XHRcdHRoaXMuX2NhbmNlbCgpO1xuICBcdFx0XHRpZiAoIXRoaXMuX2lzVGFwVmFsaWQoKSkgeyByZXR1cm47IH1cblxuICBcdFx0XHQvLyBwcmV2ZW50IHNpbXVsYXRlZCBtb3VzZSBldmVudHMgaHR0cHM6Ly93M2MuZ2l0aHViLmlvL3RvdWNoLWV2ZW50cy8jbW91c2UtZXZlbnRzXG4gIFx0XHRcdG9uKGRvY3VtZW50LCAndG91Y2hlbmQnLCBwcmV2ZW50RGVmYXVsdCk7XG4gIFx0XHRcdG9uKGRvY3VtZW50LCAndG91Y2hlbmQgdG91Y2hjYW5jZWwnLCB0aGlzLl9jYW5jZWxDbGlja1ByZXZlbnQpO1xuICBcdFx0XHR0aGlzLl9zaW11bGF0ZUV2ZW50KCdjb250ZXh0bWVudScsIGZpcnN0KTtcbiAgXHRcdH0sIHRoaXMpLCB0YXBIb2xkRGVsYXkpO1xuXG4gIFx0XHRvbihkb2N1bWVudCwgJ3RvdWNoZW5kIHRvdWNoY2FuY2VsIGNvbnRleHRtZW51JywgdGhpcy5fY2FuY2VsLCB0aGlzKTtcbiAgXHRcdG9uKGRvY3VtZW50LCAndG91Y2htb3ZlJywgdGhpcy5fb25Nb3ZlLCB0aGlzKTtcbiAgXHR9LFxuXG4gIFx0X2NhbmNlbENsaWNrUHJldmVudDogZnVuY3Rpb24gY2FuY2VsQ2xpY2tQcmV2ZW50KCkge1xuICBcdFx0b2ZmKGRvY3VtZW50LCAndG91Y2hlbmQnLCBwcmV2ZW50RGVmYXVsdCk7XG4gIFx0XHRvZmYoZG9jdW1lbnQsICd0b3VjaGVuZCB0b3VjaGNhbmNlbCcsIGNhbmNlbENsaWNrUHJldmVudCk7XG4gIFx0fSxcblxuICBcdF9jYW5jZWw6IGZ1bmN0aW9uICgpIHtcbiAgXHRcdGNsZWFyVGltZW91dCh0aGlzLl9ob2xkVGltZW91dCk7XG4gIFx0XHRvZmYoZG9jdW1lbnQsICd0b3VjaGVuZCB0b3VjaGNhbmNlbCBjb250ZXh0bWVudScsIHRoaXMuX2NhbmNlbCwgdGhpcyk7XG4gIFx0XHRvZmYoZG9jdW1lbnQsICd0b3VjaG1vdmUnLCB0aGlzLl9vbk1vdmUsIHRoaXMpO1xuICBcdH0sXG5cbiAgXHRfb25Nb3ZlOiBmdW5jdGlvbiAoZSkge1xuICBcdFx0dmFyIGZpcnN0ID0gZS50b3VjaGVzWzBdO1xuICBcdFx0dGhpcy5fbmV3UG9zID0gbmV3IFBvaW50KGZpcnN0LmNsaWVudFgsIGZpcnN0LmNsaWVudFkpO1xuICBcdH0sXG5cbiAgXHRfaXNUYXBWYWxpZDogZnVuY3Rpb24gKCkge1xuICBcdFx0cmV0dXJuIHRoaXMuX25ld1Bvcy5kaXN0YW5jZVRvKHRoaXMuX3N0YXJ0UG9zKSA8PSB0aGlzLl9tYXAub3B0aW9ucy50YXBUb2xlcmFuY2U7XG4gIFx0fSxcblxuICBcdF9zaW11bGF0ZUV2ZW50OiBmdW5jdGlvbiAodHlwZSwgZSkge1xuICBcdFx0dmFyIHNpbXVsYXRlZEV2ZW50ID0gbmV3IE1vdXNlRXZlbnQodHlwZSwge1xuICBcdFx0XHRidWJibGVzOiB0cnVlLFxuICBcdFx0XHRjYW5jZWxhYmxlOiB0cnVlLFxuICBcdFx0XHR2aWV3OiB3aW5kb3csXG4gIFx0XHRcdC8vIGRldGFpbDogMSxcbiAgXHRcdFx0c2NyZWVuWDogZS5zY3JlZW5YLFxuICBcdFx0XHRzY3JlZW5ZOiBlLnNjcmVlblksXG4gIFx0XHRcdGNsaWVudFg6IGUuY2xpZW50WCxcbiAgXHRcdFx0Y2xpZW50WTogZS5jbGllbnRZLFxuICBcdFx0XHQvLyBidXR0b246IDIsXG4gIFx0XHRcdC8vIGJ1dHRvbnM6IDJcbiAgXHRcdH0pO1xuXG4gIFx0XHRzaW11bGF0ZWRFdmVudC5fc2ltdWxhdGVkID0gdHJ1ZTtcblxuICBcdFx0ZS50YXJnZXQuZGlzcGF0Y2hFdmVudChzaW11bGF0ZWRFdmVudCk7XG4gIFx0fVxuICB9KTtcblxuICAvLyBAc2VjdGlvbiBIYW5kbGVyc1xuICAvLyBAcHJvcGVydHkgdGFwSG9sZDogSGFuZGxlclxuICAvLyBMb25nIHRhcCBoYW5kbGVyIHRvIHNpbXVsYXRlIGBjb250ZXh0bWVudWAgZXZlbnQgKHVzZWZ1bCBpbiBtb2JpbGUgU2FmYXJpKS5cbiAgTWFwLmFkZEluaXRIb29rKCdhZGRIYW5kbGVyJywgJ3RhcEhvbGQnLCBUYXBIb2xkKTtcblxuICAvKlxuICAgKiBMLkhhbmRsZXIuVG91Y2hab29tIGlzIHVzZWQgYnkgTC5NYXAgdG8gYWRkIHBpbmNoIHpvb20gb24gc3VwcG9ydGVkIG1vYmlsZSBicm93c2Vycy5cbiAgICovXG5cbiAgLy8gQG5hbWVzcGFjZSBNYXBcbiAgLy8gQHNlY3Rpb24gSW50ZXJhY3Rpb24gT3B0aW9uc1xuICBNYXAubWVyZ2VPcHRpb25zKHtcbiAgXHQvLyBAc2VjdGlvbiBUb3VjaCBpbnRlcmFjdGlvbiBvcHRpb25zXG4gIFx0Ly8gQG9wdGlvbiB0b3VjaFpvb206IEJvb2xlYW58U3RyaW5nID0gKlxuICBcdC8vIFdoZXRoZXIgdGhlIG1hcCBjYW4gYmUgem9vbWVkIGJ5IHRvdWNoLWRyYWdnaW5nIHdpdGggdHdvIGZpbmdlcnMuIElmXG4gIFx0Ly8gcGFzc2VkIGAnY2VudGVyJ2AsIGl0IHdpbGwgem9vbSB0byB0aGUgY2VudGVyIG9mIHRoZSB2aWV3IHJlZ2FyZGxlc3Mgb2ZcbiAgXHQvLyB3aGVyZSB0aGUgdG91Y2ggZXZlbnRzIChmaW5nZXJzKSB3ZXJlLiBFbmFibGVkIGZvciB0b3VjaC1jYXBhYmxlIHdlYlxuICBcdC8vIGJyb3dzZXJzLlxuICBcdHRvdWNoWm9vbTogQnJvd3Nlci50b3VjaCxcblxuICBcdC8vIEBvcHRpb24gYm91bmNlQXRab29tTGltaXRzOiBCb29sZWFuID0gdHJ1ZVxuICBcdC8vIFNldCBpdCB0byBmYWxzZSBpZiB5b3UgZG9uJ3Qgd2FudCB0aGUgbWFwIHRvIHpvb20gYmV5b25kIG1pbi9tYXggem9vbVxuICBcdC8vIGFuZCB0aGVuIGJvdW5jZSBiYWNrIHdoZW4gcGluY2gtem9vbWluZy5cbiAgXHRib3VuY2VBdFpvb21MaW1pdHM6IHRydWVcbiAgfSk7XG5cbiAgdmFyIFRvdWNoWm9vbSA9IEhhbmRsZXIuZXh0ZW5kKHtcbiAgXHRhZGRIb29rczogZnVuY3Rpb24gKCkge1xuICBcdFx0YWRkQ2xhc3ModGhpcy5fbWFwLl9jb250YWluZXIsICdsZWFmbGV0LXRvdWNoLXpvb20nKTtcbiAgXHRcdG9uKHRoaXMuX21hcC5fY29udGFpbmVyLCAndG91Y2hzdGFydCcsIHRoaXMuX29uVG91Y2hTdGFydCwgdGhpcyk7XG4gIFx0fSxcblxuICBcdHJlbW92ZUhvb2tzOiBmdW5jdGlvbiAoKSB7XG4gIFx0XHRyZW1vdmVDbGFzcyh0aGlzLl9tYXAuX2NvbnRhaW5lciwgJ2xlYWZsZXQtdG91Y2gtem9vbScpO1xuICBcdFx0b2ZmKHRoaXMuX21hcC5fY29udGFpbmVyLCAndG91Y2hzdGFydCcsIHRoaXMuX29uVG91Y2hTdGFydCwgdGhpcyk7XG4gIFx0fSxcblxuICBcdF9vblRvdWNoU3RhcnQ6IGZ1bmN0aW9uIChlKSB7XG4gIFx0XHR2YXIgbWFwID0gdGhpcy5fbWFwO1xuICBcdFx0aWYgKCFlLnRvdWNoZXMgfHwgZS50b3VjaGVzLmxlbmd0aCAhPT0gMiB8fCBtYXAuX2FuaW1hdGluZ1pvb20gfHwgdGhpcy5fem9vbWluZykgeyByZXR1cm47IH1cblxuICBcdFx0dmFyIHAxID0gbWFwLm1vdXNlRXZlbnRUb0NvbnRhaW5lclBvaW50KGUudG91Y2hlc1swXSksXG4gIFx0XHQgICAgcDIgPSBtYXAubW91c2VFdmVudFRvQ29udGFpbmVyUG9pbnQoZS50b3VjaGVzWzFdKTtcblxuICBcdFx0dGhpcy5fY2VudGVyUG9pbnQgPSBtYXAuZ2V0U2l6ZSgpLl9kaXZpZGVCeSgyKTtcbiAgXHRcdHRoaXMuX3N0YXJ0TGF0TG5nID0gbWFwLmNvbnRhaW5lclBvaW50VG9MYXRMbmcodGhpcy5fY2VudGVyUG9pbnQpO1xuICBcdFx0aWYgKG1hcC5vcHRpb25zLnRvdWNoWm9vbSAhPT0gJ2NlbnRlcicpIHtcbiAgXHRcdFx0dGhpcy5fcGluY2hTdGFydExhdExuZyA9IG1hcC5jb250YWluZXJQb2ludFRvTGF0TG5nKHAxLmFkZChwMikuX2RpdmlkZUJ5KDIpKTtcbiAgXHRcdH1cblxuICBcdFx0dGhpcy5fc3RhcnREaXN0ID0gcDEuZGlzdGFuY2VUbyhwMik7XG4gIFx0XHR0aGlzLl9zdGFydFpvb20gPSBtYXAuZ2V0Wm9vbSgpO1xuXG4gIFx0XHR0aGlzLl9tb3ZlZCA9IGZhbHNlO1xuICBcdFx0dGhpcy5fem9vbWluZyA9IHRydWU7XG5cbiAgXHRcdG1hcC5fc3RvcCgpO1xuXG4gIFx0XHRvbihkb2N1bWVudCwgJ3RvdWNobW92ZScsIHRoaXMuX29uVG91Y2hNb3ZlLCB0aGlzKTtcbiAgXHRcdG9uKGRvY3VtZW50LCAndG91Y2hlbmQgdG91Y2hjYW5jZWwnLCB0aGlzLl9vblRvdWNoRW5kLCB0aGlzKTtcblxuICBcdFx0cHJldmVudERlZmF1bHQoZSk7XG4gIFx0fSxcblxuICBcdF9vblRvdWNoTW92ZTogZnVuY3Rpb24gKGUpIHtcbiAgXHRcdGlmICghZS50b3VjaGVzIHx8IGUudG91Y2hlcy5sZW5ndGggIT09IDIgfHwgIXRoaXMuX3pvb21pbmcpIHsgcmV0dXJuOyB9XG5cbiAgXHRcdHZhciBtYXAgPSB0aGlzLl9tYXAsXG4gIFx0XHQgICAgcDEgPSBtYXAubW91c2VFdmVudFRvQ29udGFpbmVyUG9pbnQoZS50b3VjaGVzWzBdKSxcbiAgXHRcdCAgICBwMiA9IG1hcC5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlLnRvdWNoZXNbMV0pLFxuICBcdFx0ICAgIHNjYWxlID0gcDEuZGlzdGFuY2VUbyhwMikgLyB0aGlzLl9zdGFydERpc3Q7XG5cbiAgXHRcdHRoaXMuX3pvb20gPSBtYXAuZ2V0U2NhbGVab29tKHNjYWxlLCB0aGlzLl9zdGFydFpvb20pO1xuXG4gIFx0XHRpZiAoIW1hcC5vcHRpb25zLmJvdW5jZUF0Wm9vbUxpbWl0cyAmJiAoXG4gIFx0XHRcdCh0aGlzLl96b29tIDwgbWFwLmdldE1pblpvb20oKSAmJiBzY2FsZSA8IDEpIHx8XG4gIFx0XHRcdCh0aGlzLl96b29tID4gbWFwLmdldE1heFpvb20oKSAmJiBzY2FsZSA+IDEpKSkge1xuICBcdFx0XHR0aGlzLl96b29tID0gbWFwLl9saW1pdFpvb20odGhpcy5fem9vbSk7XG4gIFx0XHR9XG5cbiAgXHRcdGlmIChtYXAub3B0aW9ucy50b3VjaFpvb20gPT09ICdjZW50ZXInKSB7XG4gIFx0XHRcdHRoaXMuX2NlbnRlciA9IHRoaXMuX3N0YXJ0TGF0TG5nO1xuICBcdFx0XHRpZiAoc2NhbGUgPT09IDEpIHsgcmV0dXJuOyB9XG4gIFx0XHR9IGVsc2Uge1xuICBcdFx0XHQvLyBHZXQgZGVsdGEgZnJvbSBwaW5jaCB0byBjZW50ZXIsIHNvIGNlbnRlckxhdExuZyBpcyBkZWx0YSBhcHBsaWVkIHRvIGluaXRpYWwgcGluY2hMYXRMbmdcbiAgXHRcdFx0dmFyIGRlbHRhID0gcDEuX2FkZChwMikuX2RpdmlkZUJ5KDIpLl9zdWJ0cmFjdCh0aGlzLl9jZW50ZXJQb2ludCk7XG4gIFx0XHRcdGlmIChzY2FsZSA9PT0gMSAmJiBkZWx0YS54ID09PSAwICYmIGRlbHRhLnkgPT09IDApIHsgcmV0dXJuOyB9XG4gIFx0XHRcdHRoaXMuX2NlbnRlciA9IG1hcC51bnByb2plY3QobWFwLnByb2plY3QodGhpcy5fcGluY2hTdGFydExhdExuZywgdGhpcy5fem9vbSkuc3VidHJhY3QoZGVsdGEpLCB0aGlzLl96b29tKTtcbiAgXHRcdH1cblxuICBcdFx0aWYgKCF0aGlzLl9tb3ZlZCkge1xuICBcdFx0XHRtYXAuX21vdmVTdGFydCh0cnVlLCBmYWxzZSk7XG4gIFx0XHRcdHRoaXMuX21vdmVkID0gdHJ1ZTtcbiAgXHRcdH1cblxuICBcdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX2FuaW1SZXF1ZXN0KTtcblxuICBcdFx0dmFyIG1vdmVGbiA9IGJpbmQobWFwLl9tb3ZlLCBtYXAsIHRoaXMuX2NlbnRlciwgdGhpcy5fem9vbSwge3BpbmNoOiB0cnVlLCByb3VuZDogZmFsc2V9LCB1bmRlZmluZWQpO1xuICBcdFx0dGhpcy5fYW5pbVJlcXVlc3QgPSByZXF1ZXN0QW5pbUZyYW1lKG1vdmVGbiwgdGhpcywgdHJ1ZSk7XG5cbiAgXHRcdHByZXZlbnREZWZhdWx0KGUpO1xuICBcdH0sXG5cbiAgXHRfb25Ub3VjaEVuZDogZnVuY3Rpb24gKCkge1xuICBcdFx0aWYgKCF0aGlzLl9tb3ZlZCB8fCAhdGhpcy5fem9vbWluZykge1xuICBcdFx0XHR0aGlzLl96b29taW5nID0gZmFsc2U7XG4gIFx0XHRcdHJldHVybjtcbiAgXHRcdH1cblxuICBcdFx0dGhpcy5fem9vbWluZyA9IGZhbHNlO1xuICBcdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX2FuaW1SZXF1ZXN0KTtcblxuICBcdFx0b2ZmKGRvY3VtZW50LCAndG91Y2htb3ZlJywgdGhpcy5fb25Ub3VjaE1vdmUsIHRoaXMpO1xuICBcdFx0b2ZmKGRvY3VtZW50LCAndG91Y2hlbmQgdG91Y2hjYW5jZWwnLCB0aGlzLl9vblRvdWNoRW5kLCB0aGlzKTtcblxuICBcdFx0Ly8gUGluY2ggdXBkYXRlcyBHcmlkTGF5ZXJzJyBsZXZlbHMgb25seSB3aGVuIHpvb21TbmFwIGlzIG9mZiwgc28gem9vbVNuYXAgYmVjb21lcyBub1VwZGF0ZS5cbiAgXHRcdGlmICh0aGlzLl9tYXAub3B0aW9ucy56b29tQW5pbWF0aW9uKSB7XG4gIFx0XHRcdHRoaXMuX21hcC5fYW5pbWF0ZVpvb20odGhpcy5fY2VudGVyLCB0aGlzLl9tYXAuX2xpbWl0Wm9vbSh0aGlzLl96b29tKSwgdHJ1ZSwgdGhpcy5fbWFwLm9wdGlvbnMuem9vbVNuYXApO1xuICBcdFx0fSBlbHNlIHtcbiAgXHRcdFx0dGhpcy5fbWFwLl9yZXNldFZpZXcodGhpcy5fY2VudGVyLCB0aGlzLl9tYXAuX2xpbWl0Wm9vbSh0aGlzLl96b29tKSk7XG4gIFx0XHR9XG4gIFx0fVxuICB9KTtcblxuICAvLyBAc2VjdGlvbiBIYW5kbGVyc1xuICAvLyBAcHJvcGVydHkgdG91Y2hab29tOiBIYW5kbGVyXG4gIC8vIFRvdWNoIHpvb20gaGFuZGxlci5cbiAgTWFwLmFkZEluaXRIb29rKCdhZGRIYW5kbGVyJywgJ3RvdWNoWm9vbScsIFRvdWNoWm9vbSk7XG5cbiAgTWFwLkJveFpvb20gPSBCb3hab29tO1xuICBNYXAuRG91YmxlQ2xpY2tab29tID0gRG91YmxlQ2xpY2tab29tO1xuICBNYXAuRHJhZyA9IERyYWc7XG4gIE1hcC5LZXlib2FyZCA9IEtleWJvYXJkO1xuICBNYXAuU2Nyb2xsV2hlZWxab29tID0gU2Nyb2xsV2hlZWxab29tO1xuICBNYXAuVGFwSG9sZCA9IFRhcEhvbGQ7XG4gIE1hcC5Ub3VjaFpvb20gPSBUb3VjaFpvb207XG5cbiAgZXhwb3J0cy5Cb3VuZHMgPSBCb3VuZHM7XG4gIGV4cG9ydHMuQnJvd3NlciA9IEJyb3dzZXI7XG4gIGV4cG9ydHMuQ1JTID0gQ1JTO1xuICBleHBvcnRzLkNhbnZhcyA9IENhbnZhcztcbiAgZXhwb3J0cy5DaXJjbGUgPSBDaXJjbGU7XG4gIGV4cG9ydHMuQ2lyY2xlTWFya2VyID0gQ2lyY2xlTWFya2VyO1xuICBleHBvcnRzLkNsYXNzID0gQ2xhc3M7XG4gIGV4cG9ydHMuQ29udHJvbCA9IENvbnRyb2w7XG4gIGV4cG9ydHMuRGl2SWNvbiA9IERpdkljb247XG4gIGV4cG9ydHMuRGl2T3ZlcmxheSA9IERpdk92ZXJsYXk7XG4gIGV4cG9ydHMuRG9tRXZlbnQgPSBEb21FdmVudDtcbiAgZXhwb3J0cy5Eb21VdGlsID0gRG9tVXRpbDtcbiAgZXhwb3J0cy5EcmFnZ2FibGUgPSBEcmFnZ2FibGU7XG4gIGV4cG9ydHMuRXZlbnRlZCA9IEV2ZW50ZWQ7XG4gIGV4cG9ydHMuRmVhdHVyZUdyb3VwID0gRmVhdHVyZUdyb3VwO1xuICBleHBvcnRzLkdlb0pTT04gPSBHZW9KU09OO1xuICBleHBvcnRzLkdyaWRMYXllciA9IEdyaWRMYXllcjtcbiAgZXhwb3J0cy5IYW5kbGVyID0gSGFuZGxlcjtcbiAgZXhwb3J0cy5JY29uID0gSWNvbjtcbiAgZXhwb3J0cy5JbWFnZU92ZXJsYXkgPSBJbWFnZU92ZXJsYXk7XG4gIGV4cG9ydHMuTGF0TG5nID0gTGF0TG5nO1xuICBleHBvcnRzLkxhdExuZ0JvdW5kcyA9IExhdExuZ0JvdW5kcztcbiAgZXhwb3J0cy5MYXllciA9IExheWVyO1xuICBleHBvcnRzLkxheWVyR3JvdXAgPSBMYXllckdyb3VwO1xuICBleHBvcnRzLkxpbmVVdGlsID0gTGluZVV0aWw7XG4gIGV4cG9ydHMuTWFwID0gTWFwO1xuICBleHBvcnRzLk1hcmtlciA9IE1hcmtlcjtcbiAgZXhwb3J0cy5NaXhpbiA9IE1peGluO1xuICBleHBvcnRzLlBhdGggPSBQYXRoO1xuICBleHBvcnRzLlBvaW50ID0gUG9pbnQ7XG4gIGV4cG9ydHMuUG9seVV0aWwgPSBQb2x5VXRpbDtcbiAgZXhwb3J0cy5Qb2x5Z29uID0gUG9seWdvbjtcbiAgZXhwb3J0cy5Qb2x5bGluZSA9IFBvbHlsaW5lO1xuICBleHBvcnRzLlBvcHVwID0gUG9wdXA7XG4gIGV4cG9ydHMuUG9zQW5pbWF0aW9uID0gUG9zQW5pbWF0aW9uO1xuICBleHBvcnRzLlByb2plY3Rpb24gPSBpbmRleDtcbiAgZXhwb3J0cy5SZWN0YW5nbGUgPSBSZWN0YW5nbGU7XG4gIGV4cG9ydHMuUmVuZGVyZXIgPSBSZW5kZXJlcjtcbiAgZXhwb3J0cy5TVkcgPSBTVkc7XG4gIGV4cG9ydHMuU1ZHT3ZlcmxheSA9IFNWR092ZXJsYXk7XG4gIGV4cG9ydHMuVGlsZUxheWVyID0gVGlsZUxheWVyO1xuICBleHBvcnRzLlRvb2x0aXAgPSBUb29sdGlwO1xuICBleHBvcnRzLlRyYW5zZm9ybWF0aW9uID0gVHJhbnNmb3JtYXRpb247XG4gIGV4cG9ydHMuVXRpbCA9IFV0aWw7XG4gIGV4cG9ydHMuVmlkZW9PdmVybGF5ID0gVmlkZW9PdmVybGF5O1xuICBleHBvcnRzLmJpbmQgPSBiaW5kO1xuICBleHBvcnRzLmJvdW5kcyA9IHRvQm91bmRzO1xuICBleHBvcnRzLmNhbnZhcyA9IGNhbnZhcztcbiAgZXhwb3J0cy5jaXJjbGUgPSBjaXJjbGU7XG4gIGV4cG9ydHMuY2lyY2xlTWFya2VyID0gY2lyY2xlTWFya2VyO1xuICBleHBvcnRzLmNvbnRyb2wgPSBjb250cm9sO1xuICBleHBvcnRzLmRpdkljb24gPSBkaXZJY29uO1xuICBleHBvcnRzLmV4dGVuZCA9IGV4dGVuZDtcbiAgZXhwb3J0cy5mZWF0dXJlR3JvdXAgPSBmZWF0dXJlR3JvdXA7XG4gIGV4cG9ydHMuZ2VvSlNPTiA9IGdlb0pTT047XG4gIGV4cG9ydHMuZ2VvSnNvbiA9IGdlb0pzb247XG4gIGV4cG9ydHMuZ3JpZExheWVyID0gZ3JpZExheWVyO1xuICBleHBvcnRzLmljb24gPSBpY29uO1xuICBleHBvcnRzLmltYWdlT3ZlcmxheSA9IGltYWdlT3ZlcmxheTtcbiAgZXhwb3J0cy5sYXRMbmcgPSB0b0xhdExuZztcbiAgZXhwb3J0cy5sYXRMbmdCb3VuZHMgPSB0b0xhdExuZ0JvdW5kcztcbiAgZXhwb3J0cy5sYXllckdyb3VwID0gbGF5ZXJHcm91cDtcbiAgZXhwb3J0cy5tYXAgPSBjcmVhdGVNYXA7XG4gIGV4cG9ydHMubWFya2VyID0gbWFya2VyO1xuICBleHBvcnRzLnBvaW50ID0gdG9Qb2ludDtcbiAgZXhwb3J0cy5wb2x5Z29uID0gcG9seWdvbjtcbiAgZXhwb3J0cy5wb2x5bGluZSA9IHBvbHlsaW5lO1xuICBleHBvcnRzLnBvcHVwID0gcG9wdXA7XG4gIGV4cG9ydHMucmVjdGFuZ2xlID0gcmVjdGFuZ2xlO1xuICBleHBvcnRzLnNldE9wdGlvbnMgPSBzZXRPcHRpb25zO1xuICBleHBvcnRzLnN0YW1wID0gc3RhbXA7XG4gIGV4cG9ydHMuc3ZnID0gc3ZnO1xuICBleHBvcnRzLnN2Z092ZXJsYXkgPSBzdmdPdmVybGF5O1xuICBleHBvcnRzLnRpbGVMYXllciA9IHRpbGVMYXllcjtcbiAgZXhwb3J0cy50b29sdGlwID0gdG9vbHRpcDtcbiAgZXhwb3J0cy50cmFuc2Zvcm1hdGlvbiA9IHRvVHJhbnNmb3JtYXRpb247XG4gIGV4cG9ydHMudmVyc2lvbiA9IHZlcnNpb247XG4gIGV4cG9ydHMudmlkZW9PdmVybGF5ID0gdmlkZW9PdmVybGF5O1xuXG4gIHZhciBvbGRMID0gd2luZG93Lkw7XG4gIGV4cG9ydHMubm9Db25mbGljdCA9IGZ1bmN0aW9uKCkge1xuICBcdHdpbmRvdy5MID0gb2xkTDtcbiAgXHRyZXR1cm4gdGhpcztcbiAgfVxuICAvLyBBbHdheXMgZXhwb3J0IHVzIHRvIHdpbmRvdyBnbG9iYWwgKHNlZSAjMjM2NClcbiAgd2luZG93LkwgPSBleHBvcnRzO1xuXG59KSk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1sZWFmbGV0LXNyYy5qcy5tYXBcbiIsIi8vIGV4dHJhY3RlZCBieSBtaW5pLWNzcy1leHRyYWN0LXBsdWdpblxuZXhwb3J0IHt9OyIsIi8vIGV4dHJhY3RlZCBieSBtaW5pLWNzcy1leHRyYWN0LXBsdWdpblxuZXhwb3J0IHt9OyJdLCJzb3VyY2VSb290IjoiIn0=", "@public_path/build/vendors-node_modules_bootstrap-table_dist_bootstrap-table-locale-all_min_js-node_modules_boot-3f0fd0.js", "/builds/dev/refonte_sav/public/build/vendors-node_modules_bootstrap-table_dist_bootstrap-table-locale-all_min_js-node_modules_boot-3f0fd0.js");
    }
}
