capibara 1.1.56 → 1.1.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/util/tableElements.js +10 -17
package/dist/index.js
CHANGED
|
@@ -243,7 +243,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _uti
|
|
|
243
243
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
244
244
|
|
|
245
245
|
"use strict";
|
|
246
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _util_domUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/domUtils */ \"./src/util/domUtils.js\");\n/* harmony import */ var _util_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/utils */ \"./src/util/utils.js\");\n/* harmony import */ var _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../util/dateUtils */ \"./src/util/dateUtils.js\");\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n /**\n * Crea elemento Table\n * Contendrá los elementos que apareceran dentro de la tabla de planilla\n * Se Usa para :\n * - Agregar background con patron estilo tabla\n * - Agregar dayMouseOver, div que indica posicion de mouse\n * - Agregar DetailDay, para detalles de datos en tabla\n * - Agregar SelectedContainer, para dias seleccionados\n * - Agregar FloatBoxContainer, para visualizacion de datos en tabla\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom creado\n */\n createAgTable(config) {\n let e = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"capibara\"\n });\n\n if (config.timeline.dark) {\n e.classList.add(\"dark-theme\");\n }\n\n if (config.timeline.header.extend.isShow) {\n e.classList.add(\"header-extended\");\n }\n\n return e;\n },\n\n /**\n * Recrea Background, que es el fondo grid, como tabla\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} $elem - Elemento relacionado, donde se cre el background\n * @return {Object} Elemento Dom Corner Footer\n */\n redrawBackground(config, $elem) {\n return this.createBackground(config, $elem);\n },\n\n /**\n * Crea y posiciona fondo de tabla\n * Este fondo contiene un patron de CSS que le da la apariencia de tabla\n * por lo cual se debe reposicionar segun la fecha de inicio, para hacer\n * calzar los fines de semana\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} [$elem = null] - Elemento background, si es null, lo crea\n * @return {Object} elemento Dom Background\n */\n createBackground(config, $elem = null) {\n let {\n height,\n width,\n dayWidth\n } = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getTableDimensions(config);\n let start = new Date(config.timeline.start);\n let end = new Date(config.timeline.end);\n end.setTime(end.getTime() + _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].dayInMilliseconds); // add 24 hours\n\n let dCorrected = new Date(start.valueOf() + start.getTimezoneOffset() * 60000);\n let weekDay = dCorrected.getDay();\n let diffWeekDays = (weekDay - 1) * dayWidth * -1;\n $elem = $elem || _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"background-grid\"\n });\n $elem.style[\"background-position\"] = diffWeekDays + \"px 0, 0 0, \" + diffWeekDays + \"px 0\";\n $elem.style.width = width + \"px\";\n $elem.style.height = height + 1 + \"px\";\n return $elem;\n },\n\n /**\n * Crea Plot Container Vertical\n * Los plots son elementos que agregan secciones de fondo en la planilla\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom plotVerticalContainer\n */\n createPlotVerticalContainer(config) {\n let $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"plot-vertical-container\"\n });\n return this.redrawPlotVerticalContainer(config, $elem);\n },\n\n createPlotHorizontalContainer(config) {\n let $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"plot-horizontal-container\"\n });\n return this.redrawPlotHorizontalContainer(config, $elem);\n },\n\n /**\n * Recrea plotVerticalContainer, usando elemento existente\n * usa un elemento existente para usar la funcion para redibujar el elemento\n *\n * Los Plots se insertan como divs, con posicion especificada,\n * con ancho de dia\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} $elem - Elemento Dom donde crea plotVerticalContainer\n * @return {Object} Elemento Dom plotVerticalContainer\n */\n redrawPlotVerticalContainer(config, $elem) {\n $elem.innerHTML = \"\";\n\n if (config.timeline.plots && config.timeline.plots.vertical) {\n let {\n height,\n dayWidth\n } = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getTableDimensions(config);\n config.timeline.plots.vertical.forEach(p => {\n let diffDays = Math.floor(_util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].diffDays(config.timeline.start, p.date));\n let left = diffDays * dayWidth;\n let plot = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n classNames: [\"plot-vertical\", p.className || \"\"],\n style: {\n \"margin-left\": left + \"px\",\n height: height + \"px\"\n }\n });\n $elem.appendChild(plot);\n });\n }\n\n return $elem;\n },\n\n redrawPlotHorizontalContainer(config, $elem) {\n $elem.innerHTML = \"\";\n\n if (config.timeline.plots && config.timeline.plots.horizontal) {\n let {\n width,\n itemHeight\n } = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getTableDimensions(config);\n config.timeline.plots.horizontal.forEach(p => {\n let item = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getItemById(config, p.idNode, p.typeNode);\n let topPosition = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getPositionByItem(config, item, \"parent\");\n let plot = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n classNames: [\"plot-horizontal\", p.className || \"\"],\n style: {\n \"margin-top\": topPosition * itemHeight + \"px\",\n width: width + \"px\"\n }\n });\n $elem.appendChild(plot);\n });\n }\n\n return $elem;\n },\n\n /**\n * Crea Corner Izquierdo\n * Se usa para :\n * - titulos relacionados con los datos del sidebar izquierdo\n * - titulos para inputs de header, absolute a la derecha\n * - boton para mostrar/ocultar sidebar izquierdo\n * - promedios\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom Corner\n */\n createCorner(config, tab = null) {\n let $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"corner\"\n });\n return this.redrawCorner($elem, config, tab);\n },\n\n redrawCorner($elem, config, tab = null) {\n let labelsInitialCorner = config.timeline.nav.left.initial.vars.filter(v => v.onlyTab == undefined || v.onlyTab && tab && v.onlyTab == tab.key).map(d => `<span class=\"item-col\">${d.label}</span>`).join(\"\");\n let labelsExtendCorner = config.timeline.nav.left.extend.vars.filter(v => v.onlyTab == undefined || v.onlyTab && tab && v.onlyTab == tab.key).map(d => `<span class=\"item-col\">${d.label}</span>`).join(\"\");\n let labelsHeaderExtend = config.timeline.header.extend.data.map(d => {\n if (d.isHidden) return \"\";\n let avg = \"\";\n let tooltip = \"\";\n let className = \"\";\n let isAccent = d.isAccent;\n\n if (d.average) {\n avg = ` <span class=\"average \"> ( <span> <span class=\"symbol\">x̄</span> ${d.average} </span>) </span> `;\n tooltip = `cap-tooltip=\"Promedio ${d.label} : ${d.average} ${d.suffix || \"\"}\"`;\n }\n\n if (d.color) {\n if (isAccent) {\n className = d.color ? \"c-\" + d.color + \"--background\" : \"\";\n } else {\n className = d.color ? \"c-\" + d.color + \"--text \" : \"\";\n }\n }\n\n return `<div class=\"input-title-container ${isAccent ? \"input-title--accent\" : \"\"} ${d.isPersistent ? \"persistent\" : \"\"}\">\n <span ${tooltip} class=\"input-title ${className}\">\n ${avg}\n ${d.label}\n </span>\n\n </div>`;\n }).join(\"\");\n let toggleSidebarBtnString = `\n <button toggle-sidebar class=\"cap-btn-icon cap-btn-icon-raised cap-btn-toggle-sidebar \">\n <span>\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z\" />\n </svg>\n </span>\n </button> `;\n\n if (config.timeline.nav.left.hideToggleSidebarButton) {\n toggleSidebarBtnString = \"\";\n }\n\n let template = `<div>\n\n ${toggleSidebarBtnString}\n <div class=\"corner-title\">\n <span class=\"bottom-text\">\n ${config.timeline.corner.left.label}\n </span>\n </div>\n\n <div class=\"initial-corner\">\n <div class=\"initial-corner-title\">\n <span class=\"bottom-container hide\">\n ${config.timeline.corner.initial.label}\n </span>\n\n <div class=\"bottom-container\">\n ${labelsInitialCorner}\n </div>\n\n </div>\n </div>\n\n\n <div class=\"extend-corner\">\n <div class=\"ex-corner-title\">\n <span class=\"bottom-container hide\">\n ${config.timeline.corner.extend.label}\n </span>\n\n <div class=\"bottom-container\">\n ${labelsExtendCorner}\n </div>\n\n </div>\n </div>\n\n\n <div class=\"cap-btn-nav-corner\">\n <div class=\"input-titles\">\n ${labelsHeaderExtend}\n </div>\n </div>\n\n <div class=\"progress-bar progress-bar-left hide-progress\"></div>\n\n </div>`;\n let r = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(template);\n $elem.innerHTML = \"\";\n $elem.append(r);\n let toggleSidebar = $elem.querySelector(\"[toggle-sidebar]\");\n\n if (toggleSidebar) {\n toggleSidebar.addEventListener(\"click\", e => {\n r.dispatchEvent(new CustomEvent(\"toggleSidebar\", {\n bubbles: true,\n cancelable: false\n }));\n });\n }\n\n return $elem;\n },\n\n /**\n * Crea Corner Derecho\n * Se usa para :\n * - titulos relacionados con los datos del sidebar Derecho\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom corner\n */\n createCornerRight(config, tab = null) {\n let $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n classNames: [\"corner\", \"right\"]\n });\n return this.redrawCornerRight($elem, config, tab);\n },\n\n redrawCornerRight($el, config, tab = null) {\n let label = \"\";\n\n if (config.timeline.corner.right.label) {\n ` <span>\n ${config.timeline.corner.right.label}\n </span>`;\n }\n\n let str = `\n <div class=\"corner-title\">\n ${label}\n <div class=\"btn-container\"></div>\n </div>\n <div class=\"progress-bar progress-bar-right hide-progress\"></div>\n `;\n $el.innerHTML = str.trim();\n let $btnContainer = $el.querySelector(\".btn-container\");\n\n if (config.timeline.corner.right.buttons) {\n config.timeline.corner.right.buttons.forEach(btn => {\n let isEnabled = btn.getIsEnabled ? btn.getIsEnabled() : true;\n\n if (isEnabled) {\n let $btn = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <button class=\"corner-btn cap-btn-raised\">\n ${btn.label || \"\"}\n </button> `);\n\n if (btn.onClick) {\n $btn.addEventListener(\"click\", btn.onClick);\n }\n\n $btnContainer.appendChild($btn);\n }\n });\n }\n\n if (config.timeline.corner.right.inputs) {\n config.timeline.corner.right.inputs.forEach(input => {\n let $input = this.createCornerRightInput({\n inputConfig: input\n });\n $btnContainer.appendChild($btn);\n });\n }\n\n return $el;\n },\n\n createCornerRightInput({\n inputConfig,\n dataDay = null,\n daySelected = null\n }) {\n let r = null;\n\n switch (inputConfig.type) {\n case 'autocomplete-crud':\n r = this.createCornerRightInputAutocompleteCrud({\n inputConfig,\n dataDay,\n daySelected\n });\n break;\n }\n\n return r;\n },\n\n createCornerRightInputAutocompleteCrud({\n inputConfig,\n dataDay,\n daySelected\n }) {\n let elem = \"test\";\n return elem;\n },\n\n /**\n * Crea Header Top\n * Se usa para :\n * - Manejo de tabs\n * - Botones de navegación y selección de fecha\n * - Boton toggle Dark mode\n * - Boton toggle Header extended\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom\n */\n createHeaderTop(config, tabSelected = null) {\n return this.redrawHeaderTop(config, tabSelected, _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\"));\n },\n\n redrawHeaderTop(config, tabSelected = null, $elem) {\n let str = `\n <div class=\"header-top\">`;\n\n if (config.timeline.tabs) {\n let showTabs = true;\n\n if (config.timeline.tabs.filter(t => !t.isHidden).length == 0) {\n showTabs = false;\n }\n\n if (showTabs) {\n str += ` <div class=\"tab-select-container c-d-desktop-none c-d-mobile-flex\">\n <select class=\"tabs-select\" >`;\n config.timeline.tabs.forEach(tab => {\n if (!tab.isHidden) {\n str += ` <option ${tab == tabSelected ? 'selected=\"selected\"' : \"\"} value=\"${tab.id}\"> ${tab.label} </option>`;\n }\n });\n str += `</select> </div>`;\n str += ` <div class=\"tabs-container c-d-desktop-flex c-d-mobile-none\">`;\n config.timeline.tabs.forEach(tab => {\n if (!tab.isHidden) {\n str += ` <button\n class=\"tab ${tab.disabled ? \"disabled\" : \"\"} ${tab == tabSelected ? \"active\" : \"\"} ${tab.color}\"\n color=\"${tab.color}\"\n input-key=\"${tab.id}\"\n ${tab.tooltip ? 'cap-tooltip=\"' + tab.tooltip + '\"' : \"\"} >\n <span>${tab.label}</span>\n ${tab.icon || \"\"}\n </button>\n `;\n }\n });\n str += `</div>`;\n }\n }\n\n if (tabSelected) {\n if (tabSelected.legends) {\n /*\n str += `<div class=\"legends-select-container c-d-desktop-none c-d-mobile-flex\">\n <select class=\"legends-select\" multiple>`;\n tabSelected.legends.forEach(legend => {\n str +=` <option value=\"${legend.id}\"> ${legend.label} </option>`\n });\n str += `</select>\n </div>`;\n */\n let toggleLegendsIconPath = \"M7,5H21V7H7V5M7,13V11H21V13H7M4,4.5A1.5,1.5 0 0,1 5.5,6A1.5,1.5 0 0,1 4,7.5A1.5,1.5 0 0,1 2.5,6A1.5,1.5 0 0,1 4,4.5M4,10.5A1.5,1.5 0 0,1 5.5,12A1.5,1.5 0 0,1 4,13.5A1.5,1.5 0 0,1 2.5,12A1.5,1.5 0 0,1 4,10.5M7,19V17H21V19H7M4,16.5A1.5,1.5 0 0,1 5.5,18A1.5,1.5 0 0,1 4,19.5A1.5,1.5 0 0,1 2.5,18A1.5,1.5 0 0,1 4,16.5Z\";\n str += ` \n <button toggle-legends class=\"cap-btn-icon cap-btn-icon-raised \">\n <span>\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"${toggleLegendsIconPath}\" />\n </svg>\n </span>\n </button> \n\n <div class=\"legends-container force-mobile-style hide\"> `;\n tabSelected.legends.forEach(legend => {\n let colorClass = \"\";\n let colorBg = \"\";\n\n if (_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].isHexColor(legend.color)) {\n colorBg = \"background:\" + legend.color;\n } else {\n colorClass = legend.color ? legend.color + \"--background\" : \"\";\n }\n\n str += ` <div\n class=\"legend ${legend.active ? \"active\" : \"\"}\"\n input-key=\"${legend.key}\"\n ${legend.tooltip ? `cap-tooltip=\"${legend.tooltip}\"` : \"\"} >\n <div class=\"icon-legend ${colorClass} ${legend.shape}\" style=\"${colorBg}\"></div>\n <span>${legend.label}</span>\n </div>`;\n });\n str += `</div>`;\n }\n }\n\n str += `\n\n <div class=\"spacer\"></div>\n\n\n\n <button cap-btn-prev class=\"cap-btn-icon cap-btn-icon-raised\">\n <span class=\"icon\">\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M20,10V14H11L14.5,17.5L12.08,19.92L4.16,12L12.08,4.08L14.5,6.5L11,10H20Z\" />\n </svg>\n </span>\n\n <span class=\"loading-icon\">\n <svg version=\"1.1\" id=\"loader-1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n width=\"32px\" height=\"32px\" viewBox=\"0 0 40 40\" enable-background=\"new 0 0 40 40\" xml:space=\"preserve\">\n <path opacity=\"0.2\" fill=\"#000\" d=\"M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946\n s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634\n c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z\"/>\n <path fill=\"#000\" d=\"M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0\n C22.32,8.481,24.301,9.057,26.013,10.047z\">\n <animateTransform attributeType=\"xml\"\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 20 20\"\n to=\"360 20 20\"\n dur=\"1.5s\"\n repeatCount=\"indefinite\"/>\n </path>\n </svg>\n </span>\n </button>\n\n\n <button cap-btn-calendar class=\"cap-btn-icon cap-btn-icon-raised\">\n <span>\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M19,19H5V8H19M16,1V3H8V1H6V3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3H18V1M17,12H12V17H17V12Z\" />\n </svg>\n </span>\n <span class=\"loading-icon\">\n <svg version=\"1.1\" id=\"loader-1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n width=\"32px\" height=\"32px\" viewBox=\"0 0 40 40\" enable-background=\"new 0 0 40 40\" xml:space=\"preserve\">\n <path opacity=\"0.2\" fill=\"#000\" d=\"M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946\n s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634\n c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z\"/>\n <path fill=\"#000\" d=\"M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0\n C22.32,8.481,24.301,9.057,26.013,10.047z\">\n <animateTransform attributeType=\"xml\"\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 20 20\"\n to=\"360 20 20\"\n dur=\"1.5s\"\n repeatCount=\"indefinite\"/>\n </path>\n </svg>\n </span>\n </button>\n\n <button cap-btn-next class=\"cap-btn-icon cap-btn-icon-raised\">\n <span>\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M4,10V14H13L9.5,17.5L11.92,19.92L19.84,12L11.92,4.08L9.5,6.5L13,10H4Z\" />\n </svg>\n </span>\n <span class=\"loading-icon\">\n <svg version=\"1.1\" id=\"loader-1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n width=\"32px\" height=\"32px\" viewBox=\"0 0 40 40\" enable-background=\"new 0 0 40 40\" xml:space=\"preserve\">\n <path opacity=\"0.2\" fill=\"#000\" d=\"M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946\n s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634\n c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z\"/>\n <path fill=\"#000\" d=\"M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0\n C22.32,8.481,24.301,9.057,26.013,10.047z\">\n <animateTransform attributeType=\"xml\"\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 20 20\"\n to=\"360 20 20\"\n dur=\"1.5s\"\n repeatCount=\"indefinite\"/>\n </path>\n </svg>\n </span>\n </button>\n\n <div class=\"spacer\"></div>\n\n <button toggle-dark class=\"cap-btn-icon cap-btn-header c-d-mobile-none ${config.timeline.withDarkToggle == false ? \"hide\" : \"\"}\">\n <span class=\"hide-light\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M13,4.8C9,4.8 9,19.2 13,19.2C17,19.2 22,16.5 22,12C22,7.5 17,4.8 13,4.8M13.1,17.2C12.7,16.8 12,15 12,12C12,9 12.7,7.2 13.1,6.8C16,6.9 20,8.7 20,12C20,15.3 15.9,17.1 13.1,17.2M8,10.5C8,11 7.9,11.5 7.9,12C7.9,12.2 7.9,12.4 7.9,12.6L2.4,14L1.9,12.1L8,10.5M2,7L9.4,5.1C9.2,5.4 9,5.8 8.9,6.3C8.8,6.6 8.7,7 8.6,7.4L2.5,8.9L2,7M8.2,15.5C8.3,16.2 8.5,16.9 8.7,17.4L2.4,19L1.9,17.1L8.2,15.5Z\" />\n </svg>\n </span>\n <span class=\"hide-dark\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M13,4.8C9,4.8 9,19.2 13,19.2C17,19.2 22,16.5 22,12C22,7.5 17,4.8 13,4.8M13.1,17.2C12.7,16.8 12,15 12,12C12,9 12.7,7.2 13.1,6.8C16,6.9 20,8.7 20,12C20,15.3 16,17.1 13.1,17.2M2,5H9.5C9.3,5.4 9,5.8 8.9,6.4C8.8,6.6 8.8,6.8 8.7,7H2V5M8,11H2V9H8.2C8.1,9.6 8.1,10.3 8,11M8.7,17C8.9,17.8 9.2,18.4 9.6,19H2.1V17H8.7M8.2,15H2V13H8C8.1,13.7 8.1,14.4 8.2,15Z\" />\n </svg>\n </span>\n </button>`;\n\n if (config.timeline.header.extend.enabled !== false) {\n str += `<button toggle-header class=\"cap-btn-icon cap-btn-icon-raised\">\n <span>\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z\" />\n </svg>\n </span>\n </button>`;\n }\n\n str += ` <div class=\"button-right-container\"></div>\n </div>`;\n /*\n `\n <button toggle-sidebar-right class=\"cap-btn-icon cap-btn-icon-raised\">\n <span>\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M15.41,16.58L10.83,12L15.41,7.41L14,6L8,12L14,18L15.41,16.58Z\" />\n </svg>\n </span>\n </button>\n </div>\n `;\n */\n\n let $r = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n $elem.replaceWith($r);\n\n if (config.timeline.header.rightButtons) {\n let $buttonContainer = $r.querySelector(\".button-right-container\");\n config.timeline.header.rightButtons.forEach(button => {\n let hasBadge = false;\n\n if (button.hasBadge) {\n hasBadge = button.hasBadge();\n }\n\n let str = `<button class=\"cap-btn-icon cap-btn-icon-raised ${hasBadge ? \"cap-btn-has-badge\" : \"\"}\">\n <span>\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"${button.icon}\" />\n </svg>\n </span>\n </button>`;\n let $button = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n $button.addEventListener(\"click\", evt => button.onClick({\n evt\n }));\n $buttonContainer.append($button);\n });\n }\n\n let $toggleDark = $r.querySelector(\"[toggle-dark]\");\n\n if ($toggleDark) {\n $toggleDark.addEventListener(\"click\", e => {\n $r.dispatchEvent(new CustomEvent(\"toggleDark\", {\n bubbles: true,\n cancelable: false\n }));\n });\n }\n\n let $btnCalendar = $r.querySelector(\"[cap-btn-calendar]\");\n\n if ($btnCalendar) {\n $btnCalendar.addEventListener(\"click\", e => {\n let x = e.x;\n let y = e.y;\n $r.dispatchEvent(new CustomEvent(\"clickCalendarIcon\", {\n bubbles: true,\n cancelable: false,\n detail: {\n x,\n y\n }\n }));\n });\n }\n\n let $btnToggleHeader = $r.querySelector(\"[toggle-header]\");\n\n if ($btnToggleHeader) {\n $btnToggleHeader.addEventListener(\"click\", e => {\n $r.dispatchEvent(new CustomEvent(\"toggleHeader\", {\n bubbles: true,\n cancelable: false\n }));\n });\n }\n /*\n $r.querySelector(\"[toggle-sidebar-right]\").addEventListener(\"click\", e => {\n $r.dispatchEvent(new CustomEvent(\"toggleSidebarRight\", {\n bubbles: true,\n cancelable: false,\n }));\n });\n */\n\n\n $r.querySelector(\"[cap-btn-prev]\").addEventListener(\"click\", e => {\n $r.dispatchEvent(new CustomEvent(\"headerPrev\", {\n bubbles: true,\n cancelable: false,\n detail: {\n originalEvt: e\n }\n }));\n });\n $r.querySelector(\"[cap-btn-calendar]\").addEventListener(\"click\", e => {\n $r.dispatchEvent(new CustomEvent(\"headerCalendar\", {\n bubbles: true,\n cancelable: false,\n detail: {\n originalEvt: e\n }\n }));\n });\n $r.querySelector(\"[cap-btn-next]\").addEventListener(\"click\", e => {\n $r.dispatchEvent(new CustomEvent(\"headerNext\", {\n bubbles: true,\n cancelable: false,\n detail: {\n originalEvt: e\n }\n }));\n });\n let $toggleLegendsBtn = $r.querySelector(\"[toggle-legends]\");\n\n if ($toggleLegendsBtn) {\n $toggleLegendsBtn.addEventListener(\"click\", e => {\n let $legendContainer = $r.querySelector(\".legends-container\");\n\n if ($legendContainer) {\n $legendContainer.classList.toggle(\"hide\");\n }\n });\n }\n\n $r.querySelectorAll(\".legend\").forEach($legend => {\n $legend.addEventListener(\"click\", e => {\n let key = e.currentTarget.getAttribute(\"input-key\");\n\n if (key) {\n let legendSelected = tabSelected.legends.find(tab => tab.key === key);\n\n if (legendSelected) {\n $r.dispatchEvent(new CustomEvent(\"selectLegendHeader\", {\n bubbles: true,\n cancelable: false,\n detail: {\n legend: legendSelected,\n $legend\n }\n }));\n }\n }\n });\n });\n $r.querySelectorAll(\".tab:not(.disabled)\").forEach($tab => {\n $tab.addEventListener(\"click\", e => {\n let key = e.currentTarget.getAttribute(\"input-key\");\n\n if (key) {\n let tabSelected = config.timeline.tabs.find(tab => tab.id == key);\n\n if (tabSelected) {\n $r.dispatchEvent(new CustomEvent(\"selectTabHeader\", {\n bubbles: true,\n cancelable: false,\n detail: {\n tab: tabSelected\n }\n }));\n }\n }\n });\n });\n $r.querySelectorAll(\".tabs-select:not(.disabled)\").forEach($tab => {\n $tab.addEventListener(\"change\", e => {\n let key = parseFloat(e.currentTarget.value);\n\n if (key) {\n let tabSelected = config.timeline.tabs.find(tab => tab.id == key);\n\n if (tabSelected) {\n $r.dispatchEvent(new CustomEvent(\"selectTabHeader\", {\n bubbles: true,\n cancelable: false,\n detail: {\n tab: tabSelected\n }\n }));\n }\n }\n });\n });\n return $r;\n },\n\n /**\n * Crea Header\n * Se usa para :\n * - Mostrar fechas en header\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom\n */\n createHeader(config) {\n let $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"header\");\n return this.redrawHeader(config, $elem);\n },\n\n /**\n * Recrea Header, usado para redibujar\n * utiliza $elem como elemento dom donde recrearlo\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} $elem - Elemento Dom donde crea Header\n * @return {Object} Elemento Dom\n */\n redrawHeader(config, $elem) {\n let datesTree = _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].getDateTreeRange(new Date(config.timeline.start), new Date(config.timeline.end));\n let str = `<div class=\"header-container\"> `;\n Object.keys(datesTree).forEach(keyY => {\n let year = datesTree[keyY];\n str += `<div class=\"agno-calendario\">\n <span class=\"agno hide\">${keyY}</span>\n <div class=\"meses\">`;\n Object.keys(year).forEach(keyM => {\n let month = datesTree[keyY][keyM];\n str += ` <div class=\"mes-calendario\">\n <div class=\"mes ${Object.keys(month).length < 4 ? \"mes-reduced mes-reduced-\" + Object.keys(month).length : \"\"}\">\n <div class=\"mes-label\">\n ${_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getMonthByPosition(keyM)} ${keyY}\n </div>\n </div>\n <div class=\"dias\">`;\n Object.keys(month).forEach(keyD => {\n let day = datesTree[keyY][keyM][keyD];\n let isWeekend = day.isWeekend;\n let isToday = day.isToday;\n let date = _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].formatDate(day.Date);\n str += `<div class=\"dia-calendario ${isToday ? \"today\" : \"\"} ${isWeekend ? \"weekend\" : \"\"} ${config.timeline.dateSelectable ? \"is-clickeable\" : \"\"}\" date=\"${date}\">${keyD}</div>`;\n });\n str += `</div></div>`;\n });\n str += `</div> </div>`;\n });\n str += `</div>`;\n $elem.innerHTML = \"\";\n $elem.append(_util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str));\n\n if (config.timeline.dateSelectable) {\n $elem.querySelectorAll(\".dia-calendario[date]\").forEach($dia => {\n $dia.addEventListener(\"contextmenu\", evt => {\n $elem.dispatchEvent(new CustomEvent(\"contextMenuDate\", {\n bubbles: true,\n cancelable: false,\n detail: {\n $elem: $dia,\n date: $dia.getAttribute(\"date\"),\n clientX: evt.clientX,\n clientY: evt.clientY\n }\n }));\n });\n $dia.addEventListener(\"click\", evt => {\n $elem.dispatchEvent(new CustomEvent(\"clickDate\", {\n bubbles: true,\n cancelable: false,\n detail: {\n $elem: $dia,\n date: $dia.getAttribute(\"date\")\n }\n }));\n });\n });\n }\n\n return $elem;\n },\n\n /**\n * Crea Header extended\n * Se usa para :\n * -Mostrar inputs y datos para fechas en header\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom headerExtended\n */\n createHeaderExtended(config) {\n if (config.timeline.header.extend.enabled == false) return null;\n let dates = _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].getDateRange(new Date(config.timeline.start), new Date(config.timeline.end));\n let str = `<div class=\"header-container-extended\">`;\n config.timeline.header.extend.data.forEach((d, d_index) => {\n if (d.isHidden) return \"\";\n let isPersistent = d.isPersistent;\n str += `<div class=\"input-list ${isPersistent ? \"persistent\" : \"\"}\">`;\n str += dates.map(date => {\n let value = \"\";\n let isFuture = _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].isFuture(date);\n let isToday = _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].isToday(date);\n\n if (d.data) {\n let dataFounded = d.data.find(dataInput => {\n return _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].isSameDate(new Date(dataInput.date), date);\n });\n\n if (dataFounded) {\n value = dataFounded.value || \"\";\n }\n }\n\n if (d.editable === false || isFuture && d.editableFuture == false || isToday && d.editableToday == false) {\n return `<div>\n <span date=\"${date}\" \n index=\"${d_index}\" \n class=\"${date.varName} ${d.color ? \"c-\" + d.color + \"--text\" : \"\"}\" > \n ${value} \n </span>\n </div>`;\n }\n\n let isDisabled = false;\n\n if (config.timeline.editable === false) {\n isDisabled = true;\n }\n\n return `<div class=\"dia-input\">\n <input \n date=\"${date}\" \n index=\"${d_index}\" \n class=\"header-input \n ${date.varName} ${d.color ? \"c-\" + d.color + \"--text\" : \"\"}\" \n type=\"number\"\n ${isDisabled ? \"disabled\" : \"\"} \n value=\"${value}\">\n </div>`;\n }).join(\"\");\n str += `</div>`;\n });\n str += `</div>`;\n let r = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n r.querySelectorAll(\"input.header-input\").forEach(input => {\n input.addEventListener(\"input\", e => {\n let date = e.currentTarget.getAttribute(\"date\");\n let index = e.currentTarget.getAttribute(\"index\");\n let value = e.currentTarget.value;\n let typeData = config.timeline.header.extend.data[index]; //refresh config value\n\n let data = typeData.data.find(d => _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].isSameDate(new Date(d.date), new Date(date)));\n data.value = value;\n r.dispatchEvent(new CustomEvent(\"changeInputHeader\", {\n bubbles: true,\n cancelable: false,\n detail: {\n date: date,\n typeData: typeData,\n value: value\n }\n }));\n });\n });\n return r;\n },\n\n /**\n * Crear Sidebar Izquierdo\n * - Maneja items como arbol de 2 niveles (parent, children)\n * - El sidebar se divide en navList - InitialNav - extendedNav - BtnNav\n * - Se agrega itemDetail, para detalles de items\n *\n *\n * TODO: para evitar incrustar las ids en los inputs, se deben crear\n * los nodos uno por uno como elemento DOM, y agregarles los eventos directamente\n * ahora se hace seleccionando todos los inputs con querySelectorAll\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom Sidebar Izquierdo\n */\n createNavLeft(config, tab = null) {\n let $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"nav\", {\n className: \"left\"\n });\n return this.redrawNavLeft($elem, config, tab);\n },\n\n /**\n * Recrea Sidebar izquierdo, usado para redibujar\n * Utiliza $elem como elemento dom donde recrearlo\n *\n *\n * @param {Object} $elem - Elemento Dom donde crea el sidebar izquierdo\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom navLeft\n */\n redrawNavLeft($elem, config, tab = null) {\n let navList = \"\";\n let initialNavList = \"\";\n let exNavList = \"\";\n let btnNavList = \"\";\n let isDisabled = false;\n\n if (config.timeline.editable === false) {\n isDisabled = true;\n }\n\n config.data.forEach(d => {\n if (d.isHidden) return;\n navList += `\n <div class=\"nav-item\">\n\n\n <div class=\"nav-item-container parent\">`;\n\n if (d.children) {\n navList += `<button class=\"tree-icon ${d.isClosed ? \"\" : \"cap-rotate\"}\" item-id=\"${d.id || -1}\" type-node=\"${d.type || \"\"}\" >\n <span>\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z\" />\n </svg>\n </span>\n </button>`;\n }\n\n navList += `\n <div class=\"item-title truncate full-width ${d.clickeable ? \"clickeable\" : \"\"}\n ${d.navOver ? \"hoverable\" : \"\"} \" item-id=\"${d.id || -1}\" type-node=\"${d.type || \"\"}\" >\n ${d.label}\n </div>\n </div>`;\n\n if (d.children) {\n navList += `\n <div class=\"children-items ${d.isClosed ? \"hide\" : \"\"} \" child-list=\"${d.id || -1}\">`;\n d.children.forEach(c => {\n if (c.isHidden) return;\n navList += `\n <div class=\"child-nav-item\">\n <div class=\"nav-item-container\">\n `;\n /*\n <span class=\"nav-item-icon\">\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M19,15L13,21L11.58,19.58L15.17,16H4V4H6V14H15.17L11.58,10.42L13,9L19,15Z\" />\n </svg>\n </span>\n */\n\n navList += `\n ${c.light ? '<span class=\"light ' + (c.light ? c.light + \"-light\" : \"\") + '\"></span>' : \"\"}\n\n <div class=\"item-title ${c.clickeable ? \"clickeable\" : \"\"}\n ${c.navOver ? \"hoverable\" : \"\"}\" item-id=\"${c.id || -1}\" type-node=\"${c.type || \"\"}\">\n <div class=\"truncate\">\n ${c.label}\n </div>\n </div>\n </div>\n </div>`;\n });\n navList += `\n </div>`;\n }\n\n navList += `</div>`; //initial\n\n initialNavList += `<div class=\"initial-nav-item parent\">`;\n\n if (d.withNav) {\n config.timeline.nav.left.initial.vars.forEach(v => {\n let value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(d.values, v.varName);\n\n if (v.round && !isNaN(value)) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].round(value, v.round);\n }\n\n if (v.input) {\n switch (v.input) {\n case \"hour\":\n value = value.split(\":\");\n let hhValue = value[0];\n let mmValue = value[1];\n initialNavList += `\n <div class=\"item-col has-input\">\n <div class=\"hour-input\">\n <input type=\"number\"\n input-type=\"time\"\n max=\"23\"\n min=\"00\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${d.id || -1}\"\n type-node=\"${d.type || \"\"}\"\n value=\"${hhValue}\"\n ${isDisabled ? \"disabled\" : \"\"}\n class=\"hh\">\n <span>:</span>\n <input type=\"number\"\n input-type=\"time\"\n max=\"59\"\n min=\"00\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${d.id || -1}\"\n type-node=\"${d.type || \"\"}\"\n value=\"${mmValue}\"\n ${isDisabled ? \"disabled\" : \"\"}\n class=\"mm\">\n </div>\n </div>`;\n break;\n\n case \"text\":\n case \"number\":\n default:\n initialNavList += `\n <div class=\"item-col has-input\">\n <input \n type=\"${v.input || \"text\"}\"\n input-type=\"${v.input || \"text\"}\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${d.id || -1}\"\n type-node=\"${d.type || \"\"}\"\n ${isDisabled ? \"disabled\" : \"\"}\n value=\"${value}\"/>\n </div>`;\n }\n } else {\n initialNavList += `\n <div class=\"item-col\">\n ${value}\n </div>`;\n }\n });\n }\n\n initialNavList += `\n </div>`;\n\n if (d.children) {\n d.children.forEach(c => {\n if (c.isHidden) return;\n initialNavList += `<div class=\"child-initial-nav-item ${d.isClosed ? \"hide\" : \"\"}\" child=\"${d.id || -1}\">`;\n\n if (c.withNav !== false) {\n config.timeline.nav.left.initial.vars.forEach(v => {\n if (v.onlyTab && tab && v.onlyTab !== tab.key) return;\n let value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(c.values, v.varName);\n\n if (v.round && !isNaN(value)) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].round(value, v.round);\n }\n\n if (v.input) {\n switch (v.input) {\n case \"hour\":\n value = value.split(\":\");\n let hhValue = value[0];\n let mmValue = value[1];\n initialNavList += `\n <div class=\"item-col has-input\">\n <div class=\"hour-input\">\n <input type=\"number\"\n input-type=\"time\"\n max=\"23\"\n min=\"00\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${c.id || -1}\"\n type-node=\"${c.type || \"\"}\"\n value=\"${hhValue}\"\n ${isDisabled ? \"disabled\" : \"\"}\n class=\"hh\">\n <span>:</span>\n <input type=\"number\"\n input-type=\"time\"\n max=\"59\"\n min=\"00\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${c.id || -1}\"\n type-node=\"${c.type || \"\"}\"\n value=\"${mmValue}\"\n ${isDisabled ? \"disabled\" : \"\"}\n class=\"mm\">\n </div>\n </div>`;\n break;\n\n case \"text\":\n case \"number\":\n default:\n initialNavList += `\n <div class=\"item-col has-input\">\n <input\n type=\"${v.input || \"text\"}\"\n input-type=\"${v.input || \"text\"}\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${c.id || -1}\"\n type-node=\"${c.type || \"\"}\"\n ${isDisabled ? \"disabled\" : \"\"}\n value=\"${value}\"/>\n </div>`;\n }\n } else {\n initialNavList += `\n <div class=\"item-col\">\n ${value}\n </div>`;\n }\n });\n }\n\n initialNavList += `\n </div>`;\n });\n } //Ext\n\n\n exNavList += `<div class=\"ex-nav-item parent\">`;\n\n if (d.withExNav) {\n config.timeline.nav.left.extend.vars.forEach(v => {\n let value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(d.values, v.varName);\n\n if (v.round && !isNaN(value)) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].round(value, v.round);\n }\n\n if (v.input) {\n switch (v.input) {\n case \"hour\":\n value = value.split(\":\");\n let hhValue = value[0];\n let mmValue = value[1];\n exNavList += `\n <div class=\"item-col has-input\">\n <div class=\"hour-input\">\n <input type=\"number\"\n input-type=\"time\"\n max=\"23\"\n min=\"0\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${d.id || -1}\"\n type-node=\"${d.type || \"\"}\"\n value=\"${hhValue}\"\n ${isDisabled ? \"disabled\" : \"\"}\n class=\"hh\">\n <span>:</span>\n <input type=\"number\"\n input-type=\"time\"\n max=\"59\"\n min=\"0\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${d.id || -1}\"\n type-node=\"${d.type || \"\"}\"\n value=\"${mmValue}\"\n ${isDisabled ? \"disabled\" : \"\"}\n class=\"mm\">\n </div>\n </div>`;\n break;\n\n case \"text\":\n case \"number\":\n default:\n exNavList += `\n <div class=\"item-col has-input\">\n <input\n type=\"${v.input || \"text\"}\"\n input-type=\"${v.input || \"text\"}\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${d.id || -1}\"\n type-node=\"${d.type || \"\"}\"\n ${isDisabled ? \"disabled\" : \"\"}\n value=\"${value}\"/>\n </div>`;\n }\n } else {\n exNavList += `\n <div class=\"item-col\">\n ${value}\n </div>`;\n }\n });\n }\n\n exNavList += `\n </div>`;\n\n if (d.children) {\n d.children.forEach(c => {\n if (c.isHidden) return;\n exNavList += `<div class=\"child-ex-nav-item ${d.isClosed ? \"hide\" : \"\"}\" child=\"${d.id || -1}\">`;\n\n if (c.withNav !== false) {\n config.timeline.nav.left.extend.vars.forEach(v => {\n if (v.onlyTab && tab && v.onlyTab !== tab.key) return;\n let value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(c.values, v.varName);\n\n if (v.round && !isNaN(value)) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].round(value, v.round);\n }\n\n if (v.input) {\n switch (v.input) {\n case \"hour\":\n value = value ? value.split(\":\") : [0, 0];\n let hhValue = value[0];\n let mmValue = value[1];\n exNavList += `\n <div class=\"item-col has-input\">\n <div class=\"hour-input\">\n <input type=\"number\"\n input-type=\"time\"\n max=\"23\"\n min=\"0\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${c.id || -1}\"\n type-node=\"${c.type || \"\"}\"\n value=\"${hhValue}\"\n ${isDisabled ? \"disabled\" : \"\"}\n class=\"hh\">\n <span>:</span>\n <input type=\"number\"\n input-type=\"time\"\n max=\"59\"\n min=\"0\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${c.id || -1}\"\n type-node=\"${c.type || \"\"}\"\n value=\"${mmValue}\"\n ${isDisabled ? \"disabled\" : \"\"}\n class=\"mm\">\n </div>\n </div>`;\n break;\n\n case \"text\":\n case \"number\":\n default:\n exNavList += `\n <div class=\"item-col has-input\">\n <input \n type=\"${v.input || \"text\"}\"\n input-type=\"${v.input || \"text\"}\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${c.id || -1}\"\n type-node=\"${c.type || \"\"}\"\n ${isDisabled ? \"disabled\" : \"\"}\n value=\"${value}\"/>\n </div>`;\n }\n } else {\n exNavList += `\n <div class=\"item-col\">\n ${value}\n </div>`;\n }\n });\n }\n\n exNavList += `\n </div>`;\n });\n } //buttons\n\n\n btnNavList += `<div class=\"cap-btn-nav-item parent\">\n <div class=\"cap-btn-nav-item-content\">`;\n\n if (config.timeline.nav.left.buttons && config.timeline.nav.left.buttons.vars) {\n config.timeline.nav.left.buttons.vars.forEach(btn => {\n if (d.withBtnNav) {\n let btnContent = \"\";\n let className = btn.className || \"\";\n\n if (btn.icon) {\n btnContent = btn.icon ? btn.icon : \"\";\n }\n\n if (btn.iconFormatter) {\n btnContent = btn.iconFormatter ? btn.iconFormatter(d, btn) : \"\";\n }\n\n if (btn.shape) {\n className += \" cap-btn-\" + btn.shape;\n btnContent += `<span> ${btn.formatter ? btn.formatter(d, btn) : \"\"} </span> `;\n }\n\n if (btn.btnClassNameFormatter) {\n let newClassName = btn.btnClassNameFormatter(d, btn);\n\n if (newClassName) {\n className += \" \" + newClassName;\n }\n }\n\n btnNavList += `\n <button class=\"cap-btn-shape ${className}\"\n input-key=\"${btn.key || \"\"}\"\n item-id=\"${d.id || -1}\"\n ${isDisabled ? \"disabled\" : \"\"}\n type-node=\"${d.type || \"\"}\">\n ${btnContent}\n </button>`;\n }\n });\n }\n\n btnNavList += `\n </div>\n </div>`;\n\n if (d.children) {\n d.children.forEach(c => {\n if (c.isHidden) return; //buttons\n\n btnNavList += `<div class=\"cap-btn-child-nav-item parent ${d.isClosed ? \"hide\" : \"\"}\" child=\"${d.id || -1}\">\n <div class=\"cap-btn-nav-item-content\">`;\n\n if (config.timeline.nav.left.buttons && config.timeline.nav.left.buttons.vars) {\n config.timeline.nav.left.buttons.vars.forEach(btn => {\n if (c.withNav !== false) {\n let btnContent = \"\";\n let className = btn.className || \"\";\n\n if (btn.icon) {\n btnContent = btn.icon ? btn.icon : \"\";\n }\n\n if (btn.iconFormatter) {\n btnContent = btn.iconFormatter ? btn.iconFormatter(c, btn) : \"\";\n }\n\n if (btn.shape) {\n className += \" cap-btn-\" + btn.shape;\n btnContent += `<span> ${btn.formatter ? btn.formatter(c, btn) : \"\"} </span> `;\n }\n\n if (btn.btnClassNameFormatter) {\n let newClassName = btn.btnClassNameFormatter(c, btn);\n\n if (newClassName) {\n className += \" \" + newClassName;\n }\n }\n\n btnNavList += `\n <button class=\"cap-btn-shape ${className}\"\n input-key=\"${btn.key || \"\"}\"\n item-id=\"${c.id || -1}\"\n ${isDisabled ? \"disabled\" : \"\"}\n type-node=\"${c.type || \"\"}\">\n ${btnContent}\n </button>`;\n }\n });\n }\n\n btnNavList += `\n </div>\n </div>`;\n });\n }\n });\n let itemDetail = ` <div class=\"detail-nav-item hide\">\n ${this.getDetailNavItemContent()}\n </div>`;\n let str = `<div class=\"nav-container\">\n ${itemDetail}\n <div class=\"nav-item-list\">\n ${navList}\n </div>\n <div class=\"initial-nav-list\">\n ${initialNavList}\n </div>\n <div class=\"extend-nav-list\">\n ${exNavList}\n </div>\n <div class=\"cap-btn-nav-list\">\n ${btnNavList}\n </div>\n </div>`;\n let navContainer = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n $elem.innerHTML = \"\";\n $elem.append(navContainer); //detalle de nav-item\n\n $elem.querySelectorAll(\".item-title.hoverable\").forEach(i => {\n i.addEventListener(\"mouseover\", e => {\n let pos = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].eventToPositionNavLeft(config, e, $elem);\n let itemId = i.getAttribute(\"item-id\");\n let item = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getItemById(config, itemId);\n let typeNode = i.getAttribute(\"type-node\");\n i.dispatchEvent(new CustomEvent(\"overNavItem\", {\n bubbles: true,\n cancelable: false,\n detail: {\n originalEvt: e,\n item: item,\n type: typeNode,\n pos: pos\n }\n }));\n });\n }); //oculta detalle de nav-item, al salir del nav-item-list\n\n $elem.querySelectorAll(\".nav-item-list\").forEach(i => {\n i.addEventListener(\"mouseleave\", e => {\n i.dispatchEvent(new CustomEvent(\"leaveNavItem\", {\n bubbles: true,\n cancelable: false\n }));\n });\n }); //oculta detalle de nav-item-list, al salir de nav-item\n\n $elem.querySelectorAll(\".item-title:not(.hoverable)\").forEach(i => {\n i.addEventListener(\"mousemove\", e => {\n i.dispatchEvent(new CustomEvent(\"leaveNavItem\", {\n bubbles: true,\n cancelable: false\n }));\n });\n });\n $elem.querySelectorAll(\".item-title.clickeable\").forEach(i => {\n i.addEventListener(\"click\", e => {\n let itemId = i.getAttribute(\"item-id\");\n let typeNode = i.getAttribute(\"type-node\");\n let value = i.value;\n i.dispatchEvent(new CustomEvent(\"clickNavLeftItem\", {\n bubbles: true,\n cancelable: false,\n detail: {\n itemId: itemId,\n type: typeNode,\n value: value\n }\n }));\n });\n });\n $elem.querySelectorAll(\"input\").forEach(i => {\n i.addEventListener(\"change\", e => {\n let inputType = i.getAttribute(\"input-type\");\n let key = i.getAttribute(\"input-key\");\n let itemId = i.getAttribute(\"item-id\");\n let typeNode = i.getAttribute(\"type-node\");\n let item = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getItemById(config, itemId);\n let value = i.value;\n\n if (inputType == \"time\") {\n let hh_input = i.parentElement.querySelector(\"input.hh\").value;\n let mm_input = i.parentElement.querySelector(\"input.mm\").value;\n mm_input = mm_input < 10 ? \"0\" + parseFloat(mm_input) : mm_input;\n i.parentElement.querySelector(\"input.mm\").value = mm_input;\n value = hh_input + \":\" + mm_input;\n }\n\n i.dispatchEvent(new CustomEvent(\"saveNavLeftInput\", {\n bubbles: true,\n cancelable: false,\n detail: {\n key: key,\n itemId: itemId,\n item: item,\n type: typeNode,\n value: value,\n tabSelected: tab\n }\n }));\n });\n });\n $elem.querySelectorAll(\"button.cap-btn-shape\").forEach(i => {\n i.addEventListener(\"click\", e => {\n let key = i.getAttribute(\"input-key\");\n let itemId = i.getAttribute(\"item-id\");\n let typeNode = i.getAttribute(\"type-node\");\n i.dispatchEvent(new CustomEvent(\"clickNavLeftButton\", {\n bubbles: true,\n cancelable: false,\n detail: {\n key: key,\n itemId: itemId,\n type: typeNode\n }\n }));\n });\n });\n $elem.querySelectorAll(\"button.tree-icon\").forEach(i => {\n i.addEventListener(\"click\", e => {\n let itemId = i.getAttribute(\"item-id\");\n let typeNode = i.getAttribute(\"type-node\");\n let dataConfig = config.data.find(d => d.id == itemId);\n let $navItem = e.currentTarget.closest(\".nav-item\");\n let $children = $navItem.querySelector(\".children-items\");\n let itemsToHide = e.currentTarget.closest(\"nav.left\").querySelectorAll(\"[child='\" + itemId + \"'], [child-list='\" + itemId + \"']\");\n\n if ($children) {\n if ($children.classList.contains(\"hide\")) {\n e.currentTarget.classList.add(\"cap-rotate\");\n itemsToHide.forEach(i => i.classList.remove(\"hide\"));\n dataConfig.isClosed = false;\n } else {\n e.currentTarget.classList.remove(\"cap-rotate\");\n itemsToHide.forEach(i => i.classList.add(\"hide\"));\n dataConfig.isClosed = true;\n }\n }\n\n i.dispatchEvent(new CustomEvent(\"clickNavLeftTreeIcon\", {\n bubbles: true,\n cancelable: false,\n detail: {\n itemId: itemId,\n type: typeNode\n }\n })); //e.currentTarget.parent\n });\n });\n return $elem;\n },\n\n /**\n * Crea Html como String, para el detalle de items en el Sidebar Izquierdo\n *\n * @param {Object} [item={}] - Configuracion de item\n * @return {String} Html de ventana de detalle\n */\n getDetailNavItemContent(item = {}) {\n if (item.navOver == undefined) item.navOver = {};\n return `\n <div class=\"header-detail\">\n <div class=\"detail-title truncate\">\n ${item.label || \"\"}\n </div>\n <div class=\"detail-subtitle\">\n ${item.navOver.subtitle || \"\"}\n </div>\n <div class=\"header-chip ${item.light ? item.light + \"-light\" : \"\"} ${item.navOver.chip ? \"\" : \"hide\"}\">\n ${item.navOver.chip || \"\"}\n </div>\n </div>\n\n <div class=\"detail-container\">\n ${item.navOver.content || \"\"}\n </div>`;\n },\n\n /**\n * Crea Sidebar Derecho\n * Usado principalmente para formulario de ingreso de datos para los dias\n * seleccionados\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} tab - Tab de referencia, para la creacion del formulario\n * @return {Object} {element, inputs}, element es el elemento Dom del sidebar,\n * inputs es un array de elementos Dom de cada input creado\n * (no son elementos html de tipo input)\n */\n createNavRight(config, tab = null) {\n var $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"nav\", {\n className: \"right\"\n });\n return this.redrawNavRight(config, $elem, tab, []);\n },\n\n /**\n * Recrea Sidebar Derecho\n * Utiliza $elem como elemento dom donde recrearlo\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} $elem - Elemento Dom donde crea el sidebar derecho\n * @param {Object} tab - Tab de referencia, para la creacion del formulario\n * @param {Object} dataDay - datos del dia seleccionando, para autorrelleno de formulario\n * @param {Object} daySelected - datos del dia seleccionado\n * @param {String} daySelected.date - fecha del dia seleccionado\n * @param {Object} daySelected.item - Item de Sidebar relacionado al dia seleccionado\n * @param {Object} daySelected.pos - posicion de dia seleccionado\n * @return {Object} Elemento Dom Sidebar Derecho\n */\n redrawNavRight(config, $elem, selected = null, tab = null, dataDay = null, daySelected = null) {\n let $navRight = $elem; //dom.createElement(\"nav\",{className:\"right\"});\n\n let $divContainer = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"nav-input-container\"\n });\n let $inputs = [];\n let checkboxInputs = [];\n let inputsWithReload = [];\n let tabSelected = tab;\n selected = selected || [daySelected];\n\n if (tabSelected && tabSelected.inputs) {\n tabSelected.inputs.forEach(i => {\n if (i.disabled) return;\n let $input = this.createInput(i, dataDay, daySelected, selected);\n\n if ($input) {\n $divContainer.appendChild($input);\n $inputs.push($input);\n\n if (i.type == \"checkbox\") {\n checkboxInputs.push($input);\n }\n\n if (i.reloadOnSelect != null) {\n inputsWithReload.push({\n $input,\n config: i\n });\n }\n }\n });\n } //manejo de eventos para inputs con showIf\n\n\n if (checkboxInputs) {\n checkboxInputs.forEach($c => {\n //obtiene key de checkbox\n let key = $c.getAttribute(\"input-key\");\n let props = tabSelected.inputs.find(i => {\n return i.key == key;\n });\n let isChecked = false;\n\n if (dataDay) {\n isChecked = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n } //obtiene inputs relacionados desde config para mostrar/ocultar\n\n\n let inputsToHide = tabSelected.inputs.filter(i => {\n return i.showIf && i.showIf == key;\n });\n let inputsToHideKeys = inputsToHide.map(i => i.key); //obtiene inputs del dom, filtrando con inputsToHide\n\n let $inputsHidden = $inputs.filter($i => {\n let inputKey = $i.getAttribute(\"input-key\");\n return inputsToHideKeys.indexOf(inputKey) > -1;\n }); //si hay inputs,\n\n if ($inputsHidden) {\n if (!isChecked) {\n $inputsHidden.forEach($i => {\n $i.classList.add(\"hide\");\n });\n }\n\n $c.addEventListener(\"input\", e => {\n $inputsHidden.forEach($i => {\n let fn = $c.querySelector(\"input[type='checkbox']\").checked ? \"remove\" : \"add\";\n $i.classList[fn](\"hide\");\n });\n });\n }\n });\n }\n\n let saveCancelBtns = this.createNavRightbuttons();\n $divContainer.appendChild(saveCancelBtns);\n $navRight.innerHTML = \"\";\n $navRight.appendChild($divContainer);\n return {\n element: $navRight,\n inputs: $inputs,\n inputsWithReload,\n saveCancelBtns\n };\n },\n\n /**\n * Crea Corner inferior izquierdo, como titulo para footer\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom Corner Footer\n */\n createCornerFooter(config) {\n if (config.timeline.footer === undefined || config.timeline.footer.enabled == false) return null;\n let str = \"\";\n\n if (config.timeline.footer) {\n str += `<div class=\"corner-footer\">\n <div class=\"corner-title\">\n <span>\n ${config.timeline.footer.label}\n </span>\n </div>\n </div>`;\n }\n\n return _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n },\n\n /**\n * Crea Footer para planilla\n * Inicialmente creado para totales\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom Corner Footer\n */\n createFooter(config) {\n if (config.timeline.footer === undefined || config.timeline.footer.enabled == false) return null;\n let str = `\n <footer>\n <div class=\"footer-container\">\n `;\n config.timeline.footer.data.forEach(d => {\n str += `\n <div class=\"footer-item\">${d.value}</div>\n `;\n });\n str += `\n </div>\n </footer>\n `;\n return _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n },\n\n /**\n * Crea Footer para planilla\n * Inicialmente creado para totales\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object[]} selected - array de objetos, de dias seleccionados\n * @return {Object} Elemento Dom Corner Footer\n */\n createSelectBoard(config, selected) {\n let $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"select-container\"\n });\n return this.redrawSelectBoard($elem, selected);\n },\n\n /**\n * Crea linea vertical para fecha Actual\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom Corner Footer\n */\n createTodayLine(config) {\n return this.redrawTodayLine(config, _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"today-line\"\n }));\n },\n\n /**\n * Recrea linea vertical para fecha Actual\n * si el elemento $elem no es enviado, se crea un nuevo elemento\n *\n * Si el dia actual no esta dentro del rango de fechas del config,\n * deshabilita la linea con la clase css .disable-line\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} [$elem=null] - Elemento Dom donde recrea la linea, si es null, la crea\n * @return {Object} Elemento Dom Corner Footer\n */\n redrawTodayLine(config, $elem = null) {\n let endTime = new Date(config.timeline.end).getTime();\n let todayTime = new Date().getTime();\n let {\n height,\n dayWidth\n } = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getTableDimensions(config);\n if ($elem == null) $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"today-line\"\n });\n\n if (endTime < todayTime) {\n $elem.classList.add(\"disable-line\");\n } else {\n $elem.classList.remove(\"disable-line\");\n }\n\n let diffDays = Math.floor(_util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].diffDays(config.timeline.start, _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].formatDate(new Date())));\n let diff = diffDays * dayWidth;\n diff += dayWidth / 2 - 2; // para centrar linea\n\n Object.assign($elem.style, {\n \"margin-left\": diff + \"px\",\n height: height + \"px\"\n });\n return $elem;\n },\n\n /**\n * Crea elemento FloatBox, que contiene los datos que se muestra en la tabla\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} tab - Tab de referencia, para mostrar datos configurados por tab\n * @return {Object} Elemento Dom Corner Footer\n */\n createFloatBox(config, tab) {\n let $container = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"float-box-container\"\n });\n return this.redrawFloatBox(config, tab, $container);\n },\n\n /**\n * Recrea elemento FloatBox, que contiene los datos que se muestra en la tabla\n * Se usa principalmente para mostrar datos en la tabla de la planilla\n * los muestra de manera flotante, calculando el Top y el Left segun la poscion\n *\n * Se consideran los elementos padres ocultos, para ocultar los datos\n *\n * Se insertan los elementos FloatBox, como elemento con datos de un item y dia especifico\n *\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} tab - Tab de referencia, para mostrar datos configurados por tab\n * @return {Object} Elemento Dom Corner Footer\n */\n redrawFloatBox(config, tab, $container) {\n $container.innerHTML = \"\"; //let tabSelected = tab || null;\n\n config.data.forEach(de => {\n if (de.isHidden) return;\n de.children.forEach(ds => {\n if (ds.isHidden) return;\n ds.data.forEach(data => {\n if ((!data.message || data.message.value == null) && (data.values == null || data.values == undefined || Object.entries(data.values).length === 0)) {\n return null;\n } //children Data\n\n\n let position = this.getPositionFloatBox(config, data, ds);\n let className = \"\";\n\n if (data.errors && data.errors.length > 0) {\n className += \"has-errors \";\n }\n\n if (de.isClosed) {\n className += \"hide \";\n }\n\n let str = `\n <div class=\"float-box ${className} ${de.isClosed ? \"hide\" : \"\"}\"\n style=\"${position ? position : \"\"}\"\n item-id=\"${ds.id || -1}\"\n type-node=\"${ds.type || \"\"}\"> `;\n\n if (tab && tab.floatBox) {\n if (tab.floatBox.messagePath) {\n let msg = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(data, tab.floatBox.messagePath);\n\n if (msg || data.message && data.message.value) {\n className += \"has-message \";\n }\n } //numeros en el floatBox\n\n\n if (tab.floatBox.nums) {\n tab.floatBox.nums.forEach(n => {\n if (tab.legends && n.tabKey) {\n let legend = tab.legends.find(l => l.key == n.tabKey);\n if (legend && !legend.active) return;\n }\n\n let dataFloatBox = null;\n let className = \"\";\n let showIf = true;\n let hideIf = false;\n let colorClass = \"\";\n let colorStyle = \"\";\n\n if (n.varName) {\n dataFloatBox = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(data.values, n.varName);\n }\n\n if (n.varShow) {\n showIf = Boolean(_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(data.values, n.varShow));\n dataFloatBox = dataFloatBox || \"\";\n }\n\n if (n.varHide) {\n hideIf = Boolean(_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(data.values, n.varHide));\n }\n\n if (n.shape) {\n className += \"shape-\" + n.shape;\n }\n\n if (n.color) {\n if (_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].isHexColor(n.color)) {\n colorStyle = `--local-color: ${n.color}`;\n } else {\n colorClass = n.color;\n }\n }\n\n if (dataFloatBox !== null && showIf && !hideIf) {\n str += `<span class=\"data ${colorClass} ${className}\" style=\"${colorStyle}\">\n ${dataFloatBox}\n </span>`;\n }\n });\n } //puntos en el floatBox\n\n\n if (tab.floatBox.dots) {\n str += `\n <div class=\"dot-container-middle\">`;\n tab.floatBox.dots.forEach(n => {\n if (_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(data.values, n.varName) !== null) {\n str += `\n <div class=\"dot ${n.color} ${n.shape || \"\"}\"></div>`;\n }\n });\n str += `\n </div>`;\n } //fila de puntos en floatBox\n\n\n if (tab.floatBox.rowDots) {\n tab.floatBox.rowDots.forEach(row => {\n let freeColumns = 4;\n str += `<span class=\"rowdot--row \">`;\n row.forEach(dot => {\n if (tab.legends && dot.tabKey) {\n let legend = tab.legends.find(l => l.key == dot.tabKey);\n if (legend && !legend.active) return;\n }\n\n let dataFloatBox = null;\n let className = \"\";\n let showIf = true;\n let hideIf = false;\n let colorClass = \"\";\n let colorStyle = \"\";\n\n if (dot.varName) {\n dataFloatBox = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(data.values, dot.varName);\n dataFloatBox = parseInt(dataFloatBox);\n }\n\n if (dot.varShow) {\n showIf = Boolean(_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(data.values, dot.varShow));\n dataFloatBox = dataFloatBox || \"\";\n }\n\n if (dot.varHide) {\n hideIf = Boolean(_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(data.values, dot.varHide));\n }\n\n if (dot.shape) {\n className += \" shape-\" + dot.shape;\n }\n\n if (dot.color) {\n if (_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].isHexColor(dot.color)) {\n colorStyle = `--local-color: ${dot.color}`;\n } else {\n colorClass = dot.color;\n }\n }\n\n if (dataFloatBox !== null && dataFloatBox > 0 && showIf && !hideIf && freeColumns > 0) {\n let n = dataFloatBox > freeColumns ? freeColumns : dataFloatBox;\n freeColumns -= n;\n\n for (let index = 0; index < n; index++) {\n str += `<div class=\"rowdot--dot ${colorClass} ${className}\" style=\"${colorStyle}\"></div>`;\n }\n }\n });\n str += `</span>`;\n });\n }\n }\n\n str += `\n </div>`;\n let $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n $elem.addEventListener(\"mouseover\", e => {\n $elem.dispatchEvent(new CustomEvent(\"mouseOverFloatBox\", {\n bubbles: true,\n cancelable: false,\n detail: {\n item: ds,\n data: data,\n originalEvt: e\n }\n }));\n });\n $elem.addEventListener(\"click\", e => {\n $elem.dispatchEvent(new CustomEvent(\"clickFloatBox\", {\n bubbles: true,\n cancelable: false,\n detail: {\n item: ds,\n data: data,\n originalEvt: e\n }\n }));\n });\n $container.appendChild($elem);\n });\n });\n });\n return $container;\n },\n\n /**\n * Crea DetailDay, detalle de valores de item y Dia\n * se usa para:\n * - Muestra nombre de item y detalles\n * - Muestra capsulas de datos\n * - Muestra Pills, pildoras de datos resumidos\n * - Muestra alertas\n * - Muestra Mensaje\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} item - Item relacionado\n * @param {Object} dataDay - valores de item y Dia\n * @param {Boolean} [onlyStringContent = false] - para escoger si devuelve String o DomElement\n * @return {String|Object} Elemento como String o DomElement\n */\n createDetailDay(config, item = {}, dataDay, tabSelected, onlyStringContent = false) {\n let str = `\n <div class=\"header-detail\">\n <div class=\"title truncate\">\n ${item.label || \"\"}\n </div>\n <div class=\"subtitle\">\n ${dataDay ? _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].formatDateReadeable(dataDay.date) : \"\"}\n </div>\n </div>\n\n <div class=\"list-detail list\">`; //CAPSULES\n\n if (dataDay) {\n config.timeline.detailDay.capsules.forEach(cap => {\n //para comprobar si tiene datos, se obtiene el primer valor\n //de la lista de values de una capsula\n let hasValues = cap.values.filter(v => _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay.values, v.varName)).length > 0;\n let hideIf = false;\n\n if (cap.hideIf) {\n hideIf = Boolean(_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay.values, cap.hideIf));\n }\n\n let colorClass = \"\";\n let colorStyle = \"\";\n\n if (cap.color) {\n if (_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].isHexColor(cap.color)) {\n colorStyle = `--local-color: ${cap.color};`;\n colorStyle += `--local-color-font: ${cap.color};`;\n } else {\n colorClass = cap.color;\n }\n }\n\n if (hasValues && !hideIf) {\n str += `\n <div class=\"item-detail ${colorClass}\" style=\"${colorStyle}\">\n\n <div class=\"left-icon ${cap.shape || \"\"} \"></div>\n\n <div class=\"name\">\n <span>\n ${cap.title || \"\"}\n </span>\n </div>`;\n str += `\n <div class=\"item-description\"> `;\n cap.values.forEach(v => {\n let value = v.varName ? _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay.values, v.varName) : null;\n\n if (cap.isLabeledArray) {\n value.forEach(valueLabeled => {\n let outputValue = null;\n let valueName = v.valueName ? v.valueName : \"value\";\n let tempValue = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(valueLabeled, valueName);\n\n if (tempValue) {\n outputValue = v.round ? _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].round(tempValue, v.round) : tempValue;\n }\n\n if (v.formatter) {\n outputValue = v.formatter(valueLabeled);\n }\n\n if (typeof outputValue == \"number\") {\n outputValue = new Intl.NumberFormat().format(outputValue);\n }\n\n str += outputValue == null ? \"\" : `\n <div class=\"desc ${v.showColumn ? 'desc-column' : ''}\">\n <div class=\"label\">\n ${v.hideLabel ? \"\" : valueLabeled.label}\n </div >\n <div class=\"val\">\n <span class=\"prefix\">\n ${v.prefix || \"\"}\n </span>\n <span class=\"value\">\n ${outputValue}\n </span>\n <span class=\"suffix\">\n ${valueLabeled.suffix || v.suffix || \"\"}\n </span>\n </div>\n </div>`;\n });\n } else {\n let outputValue = v.round ? _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].round(value, v.round) : value;\n\n if (v.formatter) {\n outputValue = v.formatter({\n options: v,\n dataDay,\n outputValue\n });\n }\n\n if (typeof outputValue == \"number\") {\n outputValue = new Intl.NumberFormat().format(outputValue);\n }\n\n str += outputValue == null ? \"\" : `\n <div class=\"desc\">\n <span class=\"prefix\">\n ${v.prefix || \"\"}\n </span>\n <span class=\"value\">\n ${outputValue}\n </span>\n <span class=\"suffix\">\n ${v.suffix || \"\"}\n </span>\n </div>`;\n }\n });\n str += `\n </div>`;\n str += `\n </div>`; // end .item-detail\n }\n });\n }\n\n str += `\n </div>`; // list-detail\n //PILLS\n\n if (config.timeline.detailDay.pillsVarName && dataDay && dataDay.values[config.timeline.detailDay.pillsVarName]) {\n str += `\n <div class=\"elements-detail\">\n <div class=\"name\"> ${config.timeline.detailDay.pillsTitle} </div>\n <div class=\"elements-list\">`;\n dataDay.values[config.timeline.detailDay.pillsVarName].forEach(e => {\n let value = e.value;\n\n if (typeof outputValue == \"number\") {\n value = new Intl.NumberFormat().format(value);\n }\n\n str += `\n <div class=\"element-detail\">\n <b>${e.label}</b>\n ${value}\n </div>`;\n });\n str += `\n </div>\n </div>`; //end .element-detail > .element-list\n } //str += `</div>`;\n\n\n if (dataDay && dataDay.errors && dataDay.errors.length > 0) {\n dataDay.errors.forEach(err => {\n let alertIcon = `<span class=\"alert-icon\">\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M13 14H11V9H13M13 18H11V16H13M1 21H23L12 2L1 21Z\" />\n </svg>\n </span>`;\n str += `\n <div class=\"alert\">\n ${alertIcon}\n ${err.label}\n </div>`;\n });\n }\n\n let msg = null;\n let author = null;\n let dateMsg = null;\n\n if (dataDay) {\n msg = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, tabSelected.floatBox.messagePath);\n\n if (!msg && dataDay.message && dataDay.message.value) {\n msg = dataDay.message.value;\n author = dataDay.message.author;\n dateMsg = _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].formatDateReadeable(new Date(dataDay.message.date));\n }\n }\n\n if (msg) {\n //msg = msg.replace(/(\\r\\n|\\r|\\n)/g, '<br>');\n str += `\n <div class=\"msj-container\">\n <div class=\"msj\">\n <pre>${msg || \"\"}</pre>\n </div>\n <div class=\"msj-detail\">\n <span class=\"email\"> ${author || \"\"} </span>\n <span class=\"date\"> ${dateMsg || \"\"} </span>\n </div>\n </div>`;\n }\n\n let strContainer = `<div class=\"detail-day dd-hide\"> ${str} </div>`;\n if (onlyStringContent) return str;\n return _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(strContainer);\n },\n\n /**\n * Recrea HTML de detailDay\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} item - Item relacionado\n * @param {Object} dataDay - valores de item y Dia\n * @return {String} Elemento como String, de detailDay\n */\n redrawDetailDay(config, item, dataDay, tabSelected) {\n return this.createDetailDay(config, item, dataDay, tabSelected, true);\n },\n\n /**\n * Reposiciona FloatBox\n * verifica si el parent esta desplegado, para ocultar los datos\n *\n * Solo actualiza las alturas de los floatbox\n * no recrea los floatbox, es mas optimo\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} item - Item relacionado\n */\n repositionFloatBox(config, $floatBoxContainer) {\n $floatBoxContainer.querySelectorAll(\".float-box\").forEach($f => {\n let itemId = $f.getAttribute(\"item-id\");\n let itemHeight = parseFloat(_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getCSSVariable(config, \"--item-height\"));\n let item, parent;\n ({\n item,\n parent\n } = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getItemById(config, itemId, \"child\", true));\n\n if (item) {\n let top = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getPositionByItem(config, item);\n $f.style.top = top * itemHeight + \"px\";\n\n if (parent && parent.isClosed) {\n $f.classList.add(\"hide\");\n } else if ($f.classList.contains(\"hide\")) {\n $f.classList.remove(\"hide\");\n }\n }\n });\n },\n\n /**\n * Recrea indicadores de dias seleccionados\n *\n * @param {Object} $elem - Elemento Dom donde crea los elementos seleccionados\n * @param {Object[]} selected - Array con los dias seleccionados\n * @return {Object} Elemento Dom que contiene los indicadores de dias seleccionados\n */\n redrawSelectBoard($elem, selected) {\n $elem.innerHTML = \"\";\n let hasNumber = true;\n\n if (selected) {\n if (selected.length == 1) hasNumber = false;\n selected.forEach(s => {\n let attributes = [];\n\n if (hasNumber) {\n attributes.push({\n name: \"cap-badge\",\n value: s.index\n });\n }\n\n let $s = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"selected-day\",\n attributes\n });\n $s.style.left = s.pos.left + \"px\";\n $s.style.top = s.pos.top + \"px\";\n $elem.append($s);\n });\n }\n\n return $elem;\n },\n\n /**\n * Obtiene String con estilos CSS de la posicion de un floatBox\n * calculado segun item y fecha de los valores\n *\n * @param {Object} config - Configuracion capibara, para ver fecha de inicio\n * @param {Object} data - Datos del dia indicado\n * @param {Object} item - Item relacionado\n * @return {String} String CSS top y left , para posicionar floatBox en table\n */\n getPositionFloatBox(config, data, item) {\n let left = _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].diffDays(config.timeline.start, data.date);\n let top = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getPositionByItem(config, item);\n let dayWidth = parseFloat(_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getCSSVariable(config, \"--day-width\"));\n let itemHeight = parseFloat(_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getCSSVariable(config, \"--item-height\"));\n left *= dayWidth;\n top *= itemHeight;\n return \"top: \" + top + \".5px; left:\" + left + \".5px;\";\n },\n\n /**\n * Crea Boton como elemento Dom\n *\n * @param {Object} props - propiedades para boton\n * @param {String} props.className - classes css para boton\n * @param {*} props.key - key para identificar a boton\n * @param {String} props.label - Texto boton\n * @return {Object} Elemento Dom del boton creado\n */\n createButton(props) {\n return _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <button class=\"${props.className || \"\"}\" input-key=\"${props.key || \"\"}\">\n ${props.label || \"\"}\n </button>`);\n },\n\n /**\n * Crea Botones de guardar y cancelar los datos de formulario del sidebar derecho\n *\n * @return {Object} Elemento Dom del botones creados\n */\n createNavRightbuttons() {\n let saveBtn = this.createButton({\n label: \"Guardar\",\n className: \"cap-btn-raised\"\n });\n let cancelBtn = this.createButton({\n label: \"Cancelar\",\n className: \"cap-btn-outline\"\n });\n let btnSection = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`<div class=\"button-section\"></div>`);\n btnSection.appendChild(saveBtn);\n btnSection.appendChild(cancelBtn);\n saveBtn.addEventListener(\"click\", e => {\n saveBtn.dispatchEvent(new CustomEvent(\"saveMultiInput\", {\n bubbles: true,\n cancelable: false\n }));\n });\n cancelBtn.addEventListener(\"click\", e => {\n cancelBtn.dispatchEvent(new CustomEvent(\"cancelMultiInput\", {\n bubbles: true,\n cancelable: false\n }));\n });\n return btnSection;\n },\n\n /**\n * Crea Input como elemento Dom\n *\n * @param {Object} props - config para Input\n * @param {Object} [dataDay = null] - valores de item y Dia, opcional\n * @param {Object} [daySelected = null] - datos del dia seleccionado\n * @return {Object} Elemento Dom del input creado\n */\n createInput(props, dataDay = null, daySelected = null, selected = []) {\n let r = null;\n if (props.isHidden) return r;\n\n switch (props.type) {\n case \"inputList\":\n r = this.createInputList(props, dataDay, daySelected);\n break;\n\n case \"select\":\n r = this.createInputSelect(props, dataDay, daySelected);\n break;\n\n case \"file\":\n r = this.createInputFile(props, dataDay);\n break;\n\n case \"fileLink\":\n r = this.createFileLink(props, dataDay);\n break;\n\n case \"text\":\n r = this.createText(props, selected);\n break;\n\n case \"title\":\n r = this.createTitle(props);\n break;\n\n case \"number\":\n r = this.createInputNumber(props, dataDay);\n break;\n\n case \"float\":\n r = this.createInputFloat(props, dataDay);\n break;\n\n case \"message\":\n r = this.createInputMessage(props, dataDay);\n break;\n\n case \"textarea\":\n r = this.createInputTextArea(props, dataDay);\n break;\n\n case \"checkbox\":\n r = this.createInputCheckbox(props, dataDay);\n break;\n\n case \"input-box\":\n r = this.createInputBox(props, dataDay);\n break;\n\n case \"list\":\n r = this.createList(props, dataDay);\n break;\n\n case \"button\":\n r = this.createInputButton(props, dataDay);\n break;\n\n case \"time\":\n r = this.createInputTime(props, dataDay);\n break;\n\n case \"text\":\n default:\n r = this.createInputText(props, dataDay);\n }\n\n return r;\n },\n\n /**\n * Crea Input con formato Hora, como elemento Dom\n *\n * Usa 2 inputs, hora y minutos\n *\n * el value que interpreta es String HH:MM\n *\n * @param {Object} props - config para Input\n * @param {Object} [dataDay = null] - valores de item y Dia, opcional\n * @return {Object} Elemento Dom del input creado\n */\n createInputTime(props, dataDay) {\n let hhValue = \"\";\n let mmValue = \"\";\n\n if (dataDay && dataDay.values) {\n let value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n\n if (value) {\n value = value.split(\":\");\n hhValue = value[0];\n mmValue = value[1];\n }\n }\n\n let r = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section\" input-key=\"${props.key || \"\"}\">\n <span class=\"text-subtitle d-block\">\n ${props.label || \"\"}\n </span>\n <div class=\"time\">\n <input type=\"number\"\n class=\"hour\"\n id=\"test\"\n placeholder=\"00\"\n min=\"0\"\n max=\"24\"\n value=\"${hhValue}\">\n <span class=\"symbol\">:</span>\n <input type=\"number\"\n class=\"minutes\"\n placeholder=\"00\"\n min=\"0\"\n max=\"59\"\n value=\"${mmValue}\">\n </div>\n </div>`);\n let hh = r.querySelector(\".hour\");\n let mm = r.querySelector(\".minutes\");\n hh.addEventListener(\"input\", e => {\n hh.dispatchEvent(new CustomEvent(\"changeTimeInputHH\", {\n bubbles: true,\n cancelable: false,\n detail: {\n key: props.key,\n value: e.srcElement.value\n }\n }));\n });\n mm.addEventListener(\"input\", e => {\n mm.dispatchEvent(new CustomEvent(\"changeTimeInputMM\", {\n bubbles: true,\n cancelable: false,\n detail: {\n key: props.key,\n value: e.srcElement.value\n }\n }));\n });\n this.addKeyDownInputEvents(hh);\n this.addKeyDownInputEvents(mm);\n return r;\n },\n\n /**\n * Crea Text como elemento Dom\n * Se configura como input, pero no devuelve datos, es un texto\n *\n * @param {Object} props - config para Input\n * @return {Object} Elemento Dom del input creado\n */\n createText(props, selected) {\n let label = props.label;\n\n if (props.formatter) {\n label = props.formatter({\n selected\n });\n }\n\n let $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section\" input-key=\"${props.key || \"\"}\">\n <span class=\"${props.classNames || \"\"}\">\n ${label}\n </span>\n </div>`);\n return $elem;\n },\n\n /**\n * Crea Title como elemento Dom\n * Se configura como input, pero no devuelve datos, es un texto\n *\n * @param {Object} props - config para Input\n * @return {Object} Elemento Dom del input creado\n */\n createTitle(props) {\n let classNames = \"text-title\";\n\n if (props.isSubtitle) {\n classNames = \"text-subtitle\";\n }\n\n return _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section\" input-key=\"${props.key || \"\"}\">\n <span class=\"${classNames}\">\n ${props.label}\n </span>\n </div>`);\n },\n\n /**\n * Crea Input tipo Numerico como elemento Dom\n *\n * @param {Object} props - config para Input\n * @param {Object} dataDay - valores de item y Dia, opcional\n * @return {Object} Elemento Dom del input creado\n */\n createInputNumber(props, dataDay) {\n let value = \"\";\n\n if (dataDay && dataDay.values) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n }\n\n value = value || \"\";\n let elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section ${props.classNames || \"\"}\" input-key=\"${props.key || \"\"}\">\n <div class=\"input-section-title\">\n <span class=\"text-subtitle\">\n ${props.label}\n </span>\n <span class=\"text-subtitle-2 \">\n ${props.suffix ? \"(\" + props.suffix + \")\" : \"\"}\n </span>\n </div>\n <input type=\"number\"\n class=\"nav-input\"\n value=\"${value}\">\n </div>`);\n let inputElem = elem.querySelector(\"input\");\n this.addKeyDownInputEvents(inputElem);\n return elem;\n },\n\n /**\n * Crea Input tipo FIlepicker como elemento Dom\n *\n * @param {Object} props - config para Input\n * @param {Object} dataDay - valores de item y Dia, opcional\n * @return {Object} Elemento Dom del input creado\n */\n createInputFile(props, dataDay) {\n let value = \"\";\n let fileName = \"\";\n let filePath = \"\";\n\n if (dataDay && dataDay.values) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n fileName = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.fileNameValue);\n filePath = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.filePathValue);\n }\n\n value = value || \"\";\n fileName = fileName || \"\";\n filePath = filePath || \"\";\n let elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section ${props.classNames || \"\"}\" input-key=\"${props.key || \"\"}\">\n\n <div class=\"input-section-title\">\n <span class=\"text-subtitle\">\n ${props.label}\n </span>\n </div>\n\n <div class=\"nav-input-file\" >\n <button class=\"small-close clear-file-input\">x</button>\n <label >\n <span class=\"nav-input-file-label\">\n ${props.pickerLabel || \"Seleccionar Archivo\"}\n </span>\n <input type=\"file\" value=\"${value}\">\n </label>\n </div>\n\n <div class=\"input-section-link\">\n <a href=\"${filePath}\" target=\"_blank\" >\n ${fileName}\n </a>\n </div>\n\n </div>`);\n let $inputElem = elem.querySelector(\"input\");\n let $clearBtn = elem.querySelector(\".clear-file-input\");\n let $fileInputLabel = elem.querySelector(\".nav-input-file-label\");\n $inputElem.addEventListener(\"change\", evt => {\n let fileName = $inputElem.files[0].name;\n $fileInputLabel.textContent = fileName;\n });\n $clearBtn.addEventListener(\"click\", evt => {\n $inputElem.value = \"\";\n $fileInputLabel.textContent = props.pickerLabel || \"Seleccionar Archivo\";\n evt.stopPropagation();\n });\n return elem;\n },\n\n createFileLink(props, dataDay) {\n let fileName = \"\";\n let filePath = \"\";\n\n if (dataDay && dataDay.values) {\n //value = utils.getVarByPath(dataDay, props.varName);\n fileName = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.fileNameValue);\n filePath = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.filePathValue);\n }\n\n if (fileName == \"\") return null;\n fileName = fileName || \"\";\n filePath = filePath || \"\";\n let elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section ${props.classNames || \"\"}\" input-key=\"${props.key || \"\"}\">\n\n <div class=\"input-section-title\">\n <span class=\"text-subtitle\">\n ${props.label}\n </span>\n </div>\n\n <div class=\"input-section-link\">\n <a href=\"${filePath}\" target=\"_blank\" >\n ${fileName}\n </a>\n </div>\n\n </div>`);\n return elem;\n },\n\n /**\n * Crea lista de Inputs, con array de valores, como elemento Dom\n *\n * @param {Object} props - config para Input\n * @param {Object} dataDay - valores de item y Dia, opcional\n * @param {Object} [daySelected = null] - datos del dia seleccionado\n * @return {Object} Elemento Dom del input creado\n */\n createInputList(props, dataDay, daySelected = null) {\n let value = null;\n let inputList = []; //obtiene inputs default, para crearlos, sin valores\n\n if (daySelected && Array.isArray(daySelected.item.values[props.inputList])) {\n inputList = daySelected.item.values[props.inputList].map(inputRow => {\n //limpia inputList inputs\n inputRow.inputs.map(input => {\n input.value = null;\n return input;\n }); //obtiene valores del dia\n\n if (dataDay && dataDay.values) {\n let inputValues = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.valuesPath); //autorrellena\n\n if (inputValues) {\n inputRow.inputs.forEach(input => {\n let values = inputValues.find(v => v.id == inputRow.id);\n input.value = values ? values[input.varName] : null;\n });\n }\n }\n\n return inputRow;\n });\n }\n\n let str = `<div input-key=\"${props.key || \"\"}\" >`;\n inputList.forEach(inputRow => {\n str += `\n <div class=\"input-section \" >\n <span class=\"text-subtitle\">\n ${inputRow.label}\n </span>`;\n inputRow.inputs.forEach(input => {\n str += ` \n <div class=\"input-section-col\" >\n <span class=\"text-subtitle \">\n ${input.label}\n </span>\n <input type=\"number\"\n input-id=\"${inputRow.id}\"\n input-label=\"${input.label}\"\n class=\"nav-input\"\n value=\"${input.value}\">\n </div>`;\n });\n str += `\n </div>`;\n });\n str += `</div>`;\n let elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n let inputsElem = elem.querySelectorAll(\"input\");\n inputsElem.forEach(inputElem => this.addKeyDownInputEvents(inputElem));\n return elem;\n },\n\n createInputSelect(props, dataDay, daySelected = null) {\n let value = null;\n let options = props.options;\n\n if (dataDay && dataDay.values) {\n let val = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n value = val ? val.value : null;\n }\n\n let str = `<div input-key=\"${props.key || \"\"}\" >\n <div class=\"input-section \" >\n <span class=\"text-subtitle\">\n ${props.label}\n </span>\n\n <select class=\"input-select\">\n\n <option value=\"\" ${value == null ? 'selected' : ''}>\n ${props.noDataLabel || \"-- sin asignar --\"}\n </option>\n\n `;\n options.forEach(option => {\n str += `\n <option value=\"${option.id}\" ${option.id == value ? 'selected' : ''}>\n ${option.label}\n </option>\n `;\n });\n str += `\n\n </select>\n </div>\n\n </div>`;\n let elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n return elem;\n },\n\n /**\n * Crea Input de texto TextArea como elemento Dom\n *\n * @param {Object} props - config para Input\n * @param {Object} dataDay - valores de item y Dia, opcional\n * @return {Object} Elemento Dom del input creado\n */\n createInputTextArea(props, dataDay) {\n let value = \"\";\n\n if (dataDay && dataDay.values) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n }\n\n let elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section\" input-key=\"${props.key || \"\"}\">\n <span class=\"text-subtitle d-block\">\n ${props.label}\n </span>\n <textarea class=\"\" value=\"${value}\"></textarea>\n </div>`);\n let inputElem = elem.querySelector(\"textarea\");\n this.addKeyDownInputEvents(inputElem);\n return elem;\n },\n\n /**\n * Crea Input de Mensaje como elemento Dom\n * utiliza TextArea\n *\n * @param {Object} props - config para Input\n * @param {Object} dataDay - valores de item y Dia, opcional\n * @return {Object} Elemento Dom del input creado\n */\n createInputMessage(props, dataDay) {\n let value = dataDay ? _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName) : null;\n let elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section msj-input-container\"\n input-key=\"${props.key || \"\"}\">\n <span class=\"text-subtitle d-block\">\n Mensaje\n </span>\n <textarea class=\"msj\">${value || \"\"}</textarea>\n </div>`);\n let inputElem = elem.querySelector(\"textarea\"); //this.addKeyDownInputEvents(inputElem);\n\n return elem;\n },\n\n /**\n * Crea Input de texto como elemento Dom\n *\n * @param {Object} props - config para Input\n * @param {Object} dataDay - valores de item y Dia, opcional\n * @return {Object} Elemento Dom del input creado\n */\n createInputText(props, dataDay) {\n let value = \"\";\n\n if (dataDay && dataDay.values) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n }\n\n let elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section\" input-key=\"${props.key || \"\"}\">\n <span class=\"text-subtitle d-block\">\n ${props.label}\n </span>\n <input type=\"text\" class=\"nav-input\" value=\"${value}\">\n </div>`);\n let inputElem = elem.querySelector(\"input\");\n this.addKeyDownInputEvents(inputElem);\n return elem;\n },\n\n /**\n * Crea Input Numero Flotante, como elemento Dom\n *\n * @param {Object} props - config para Input\n * @param {Object} dataDay - valores de item y Dia, opcional\n * @return {Object} Elemento Dom del input creado\n */\n createInputFloat(props, dataDay) {\n let value = \"\";\n\n if (dataDay && dataDay.values) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n }\n\n let elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section\" input-key=\"${props.key || \"\"}\">\n <span class=\"text-subtitle d-block\">\n ${props.label}\n </span>\n <input type=\"number\" class=\"nav-input\" value=\"${value}\">\n </div>`);\n let inputElem = elem.querySelector(\"input\");\n this.addKeyDownInputEvents(inputElem);\n return elem;\n },\n\n createList(props, dataDay) {\n let value = [];\n\n if (dataDay && dataDay.values) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n }\n\n let tabsContainer = \"\";\n\n if (props.tabs) {\n let tabs = \"\";\n props.tabs.forEach(tab => {\n tabs += `\n <div class=\"input-box-tab\" tab-key=\"${tab.key}\">\n ${tab.name}\n </div>`;\n });\n tabsContainer = `\n <div class=\"input-box-tab-container\">\n ${tabs}\n </div>\n `;\n }\n\n let closeIcon = `<span class=\"close-icon\">\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z\" />\n </svg>\n </span>`;\n let linkIcon = ` <span class=\"close-icon\">\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M14,3V5H17.59L7.76,14.83L9.17,16.24L19,6.41V10H21V3M19,19H5V5H12V3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V12H19V19Z\" />\n </svg>\n </span>\n `;\n let searchInput = `\n <div class=\"search-input-container\">\n <input id=\"\" type=\"text\" name=\"\" class=\"search-input\" placeholder=\"buscar\">\n <button class=\"search-input-clear\">\n ${closeIcon}\n </button>\n </div>\n `;\n let str = `\n <div class=\"input-section\" input-key=\"${props.key || \"\"}\">\n <span class=\"text-subtitle d-block\">\n ${props.label}\n </span>\n\n ${tabsContainer}\n <div class=\"input-box \" input-key=\"${props.key || \"\"}\">\n\n ${searchInput}\n `; //TODO obtener input segun fila\n\n if (props.inputs) {\n props.inputs.forEach(i => {\n if (i.isTitle) {\n let tooltip = \"\";\n let icon = \"\";\n\n if (i.tooltip) {\n tooltip = `\n <div class=\"mini-input-section--tooltip\">\n ${i.tooltip}\n ${i.suffix ? \"(\" + i.suffix + \")\" : \"\"}\n </div>`;\n }\n\n if (i.colorIcon) {\n if (_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].isHexColor(i.colorIcon)) {\n icon = `<div class=\"mini-input-section--icon\" style=\"background:${i.colorIcon}\"> </div>`;\n } else {\n icon = `<div class=\"mini-input-section--icon ${i.colorIcon}\"> </div>`;\n }\n }\n\n str += `\n <div class=\"mini-input-section is-title\" input-tab-key=\"${i.tabKey || \"\"}\" label=\"${i.label}\">\n <label>\n ${icon}\n <div class=\"mini-input-section--title truncate\">\n ${i.label}\n </div>\n </label>\n ${tooltip}\n </div>`;\n } else {\n let value_found = value ? value.find(val => val.id == i.id) : null;\n let v = value_found || \"\";\n let inputValue = props.varNameInput && v[props.varNameInput] ? v[props.varNameInput] : v.value;\n let tooltip = \"\";\n let icon = \"\";\n let link = \"\";\n\n if (i.tooltip) {\n tooltip = `\n <div class=\"mini-input-section--tooltip\">\n ${i.tooltip}\n </div>`;\n }\n\n if (i.colorIcon) {\n if (_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].isHexColor(i.colorIcon)) {\n icon = `<div class=\"mini-input-section--icon\" style=\"background:${i.colorIcon}\"> </div>`;\n } else {\n icon = `<div class=\"mini-input-section--icon ${i.colorIcon}\"> </div>`;\n }\n }\n\n if (i.link) {\n link = `<a class=\"mini-input-section--link\" target=\"_blank\" href=\"${i.link}\">\n ${linkIcon}\n </a> `;\n }\n\n str += `\n <div class=\"mini-input-section\" input-tab-key=\"${i.tabKey || \"\"}\" label=\"${i.label}\">\n <label>\n\n ${icon}\n\n <div class=\"mini-input-section--name truncate\">\n ${i.label}\n </div>\n\n <div class=\"mini-input-section--suffix\" >${i.suffix ? \"(\" + i.suffix + \")\" : \"\"}</div>\n\n ${link}\n\n </label>\n <div class=\"mini-input-section--footer\">\n <span class=\"start\"> test </span>\n <span class=\"end\"> test end </span>\n </div>\n ${tooltip}\n </div>`;\n }\n });\n }\n\n str += `\n </div>\n </div> `;\n let $el = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n let $tabs = $el.querySelectorAll(\".input-box-tab[tab-key]\") || [];\n let $searchInput = $el.querySelector(\".search-input\") || null;\n let $searchInputClear = $el.querySelector(\".search-input-clear\") || null;\n $tabs.forEach(t => {\n t.addEventListener(\"click\", e => {\n this.selectInputBoxTab(t, $el);\n $searchInput.value = \"\";\n $searchInput.dispatchEvent(new Event('input', {\n bubbles: true\n }));\n });\n });\n\n if ($searchInputClear) {\n $searchInputClear.addEventListener(\"click\", e => {\n $searchInput.value = \"\";\n $searchInput.dispatchEvent(new Event('input', {\n bubbles: true\n }));\n });\n }\n\n if ($searchInput) {\n $searchInput.addEventListener('keydown', e => {\n if (e.key === \"Escape\") {\n $searchInput.value = \"\";\n $searchInput.dispatchEvent(new Event('input', {\n bubbles: true\n }));\n }\n });\n $searchInput.addEventListener(\"input\", e => {\n let $tabSelected = $el.querySelector(\".input-box-tab[tab-key].active\") || null;\n let $inputs = [];\n\n if ($tabSelected) {\n let tabKey = $tabSelected.getAttribute(\"tab-key\");\n $inputs = $el.querySelectorAll(\".mini-input-section[input-tab-key='\" + tabKey + \"']\") || [];\n } else {\n $inputs = $el.querySelectorAll(\".mini-input-section\") || [];\n }\n\n $inputs.forEach($i => {\n let label = $i.getAttribute(\"label\");\n let search = $searchInput.value;\n\n if (label.toLowerCase().includes(search.toLowerCase())) {\n $i.classList.remove(\"hide\");\n } else {\n $i.classList.add(\"hide\");\n }\n });\n });\n }\n\n this.selectInputBoxTab(_.first($tabs), $el);\n return $el;\n },\n\n /**\n * Crea InputBox, como elemento Dom\n * un InputBox es un contenedor con una lista de inputs\n *\n * @param {Object} props - config para Input\n * @param {Object} dataDay - valores de item y Dia, opcional\n * @return {Object} Elemento Dom del input creado\n */\n createInputBox(props, dataDay) {\n let value = [];\n\n if (dataDay && dataDay.values) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n }\n\n let tabsContainer = \"\";\n\n if (props.tabs) {\n let tabs = \"\";\n props.tabs.forEach(tab => {\n tabs += `\n <div class=\"input-box-tab\" tab-key=\"${tab.key}\">\n ${tab.name}\n </div>`;\n });\n tabsContainer = `\n <div class=\"input-box-tab-container\">\n ${tabs}\n </div>\n `;\n }\n\n let closeIcon = `<span class=\"close-icon\">\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z\" />\n </svg>\n </span>`;\n let linkIcon = ` <span class=\"close-icon\">\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M14,3V5H17.59L7.76,14.83L9.17,16.24L19,6.41V10H21V3M19,19H5V5H12V3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V12H19V19Z\" />\n </svg>\n </span>\n `;\n let searchInput = `\n <div class=\"search-input-container\">\n <input id=\"\" type=\"text\" name=\"\" class=\"search-input\" placeholder=\"buscar\">\n <button class=\"search-input-clear\">\n ${closeIcon}\n </button>\n </div>\n `;\n let str = `\n <div class=\"input-section\" input-key=\"${props.key || \"\"}\">\n <span class=\"text-subtitle d-block\">\n ${props.label}\n </span>\n\n ${tabsContainer}\n <div class=\"input-box \" input-key=\"${props.key || \"\"}\">\n\n ${searchInput}\n `;\n\n if (props.inputs) {\n props.inputs.forEach(i => {\n if (i.isTitle) {\n let tooltip = \"\";\n let icon = \"\";\n\n if (i.tooltip) {\n tooltip = `\n <div class=\"mini-input-section--tooltip\">\n ${i.tooltip}\n ${i.suffix ? \"(\" + i.suffix + \")\" : \"\"}\n </div>`;\n }\n\n if (i.colorIcon) {\n if (_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].isHexColor(i.colorIcon)) {\n icon = `<div class=\"mini-input-section--icon\" style=\"background:${i.colorIcon}\"> </div>`;\n } else {\n icon = `<div class=\"mini-input-section--icon ${i.colorIcon}\"> </div>`;\n }\n }\n\n str += `\n <div class=\"mini-input-section is-title\" input-tab-key=\"${i.tabKey || \"\"}\" label=\"${i.label}\">\n <label>\n ${icon}\n <div class=\"mini-input-section--title truncate\">\n ${i.label}\n </div>\n </label>\n ${tooltip}\n </div>`;\n } else {\n let value_found = value ? value.find(val => val.id == i.id) : null;\n let v = value_found || \"\";\n let inputValue = props.varNameInput && v[props.varNameInput] ? v[props.varNameInput] : v.value;\n let tooltip = \"\";\n let icon = \"\";\n let link = \"\";\n\n if (i.tooltip) {\n tooltip = `\n <div class=\"mini-input-section--tooltip\">\n ${i.tooltip}\n </div>`;\n }\n\n if (i.colorIcon) {\n if (_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].isHexColor(i.colorIcon)) {\n icon = `<div class=\"mini-input-section--icon\" style=\"background:${i.colorIcon}\"> </div>`;\n } else {\n icon = `<div class=\"mini-input-section--icon ${i.colorIcon}\"> </div>`;\n }\n }\n\n if (i.link) {\n link = `<a class=\"mini-input-section--link\" target=\"_blank\" href=\"${i.link}\">\n ${linkIcon}\n </a> `;\n }\n\n str += `\n <div class=\"mini-input-section\" input-tab-key=\"${i.tabKey || \"\"}\" label=\"${i.label}\">\n <label>\n <input type=\"number\"\n class=\"mini-input\"\n input-id=\"${i.id || \"\"}\"\n input-key=\"${i.key || i.label}\"\n value=\"${inputValue || \"\"}\">\n\n ${icon}\n\n <div class=\"mini-input-section--name truncate\">\n ${i.label}\n </div>\n\n <div class=\"mini-input-section--suffix\" >${i.suffix ? \"(\" + i.suffix + \")\" : \"\"}</div>\n\n ${link}\n\n </label>\n ${tooltip}\n </div>`;\n }\n });\n }\n\n str += `\n </div>\n </div> `;\n let $el = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n let $tabs = $el.querySelectorAll(\".input-box-tab[tab-key]\") || [];\n let $inputs = $el.querySelectorAll(\"input.mini-input\") || [];\n let $searchInput = $el.querySelector(\".search-input\") || null;\n let $searchInputClear = $el.querySelector(\".search-input-clear\") || null;\n $tabs.forEach(t => {\n t.addEventListener(\"click\", e => {\n this.selectInputBoxTab(t, $el);\n $searchInput.value = \"\";\n $searchInput.dispatchEvent(new Event('input', {\n bubbles: true\n }));\n });\n });\n\n if ($searchInputClear) {\n $searchInputClear.addEventListener(\"click\", e => {\n $searchInput.value = \"\";\n $searchInput.dispatchEvent(new Event('input', {\n bubbles: true\n }));\n });\n }\n\n if ($searchInput) {\n $searchInput.addEventListener('keydown', e => {\n if (e.key === \"Escape\") {\n $searchInput.value = \"\";\n $searchInput.dispatchEvent(new Event('input', {\n bubbles: true\n }));\n }\n });\n $searchInput.addEventListener(\"input\", e => {\n let $tabSelected = $el.querySelector(\".input-box-tab[tab-key].active\") || null;\n let $inputs = [];\n\n if ($tabSelected) {\n let tabKey = $tabSelected.getAttribute(\"tab-key\");\n $inputs = $el.querySelectorAll(\".mini-input-section[input-tab-key='\" + tabKey + \"']\") || [];\n } else {\n $inputs = $el.querySelectorAll(\".mini-input-section\") || [];\n }\n\n $inputs.forEach($i => {\n let label = $i.getAttribute(\"label\");\n let search = $searchInput.value;\n\n if (label.toLowerCase().includes(search.toLowerCase())) {\n $i.classList.remove(\"hide\");\n } else {\n $i.classList.add(\"hide\");\n }\n });\n });\n }\n\n this.selectInputBoxTab(_.first($tabs), $el);\n $inputs.forEach(i => this.addKeyDownInputEvents(i));\n return $el;\n },\n\n selectInputBoxTab($tab, $el) {\n let $tabs = $el.querySelectorAll(\".input-box-tab[tab-key]\") || [];\n let $inputSections = $el.querySelectorAll(\".mini-input-section\") || [];\n $tabs.forEach(t => {\n t.classList.remove(\"active\");\n });\n\n if ($tab) {\n $tab.classList.add(\"active\");\n $inputSections.forEach(i => {\n let key = i.getAttribute(\"input-tab-key\");\n\n if (key == $tab.getAttribute(\"tab-key\")) {\n i.classList.remove(\"hide\");\n } else {\n i.classList.add(\"hide\");\n }\n });\n }\n },\n\n /**\n * Crea Checkbox, como elemento Dom\n *\n * @param {Object} props - config para Input\n * @param {Object} dataDay - valores de item y Dia, opcional\n * @return {Object} Elemento Dom del input creado\n */\n createInputCheckbox(props, dataDay) {\n let value = \"\";\n\n if (dataDay && dataDay.values) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n }\n\n let r = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section\" input-key=\"${props.key || \"\"}\">\n <label>\n <input type=\"checkbox\" name=\"${props.key || \"\"}\" input-key=\"${props.key || \"\"}\" ${value ? \"checked\" : \"\"}>\n ${props.label}\n </label>\n </div>`);\n return r;\n },\n\n createInputButton(props) {\n let r = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section\" input-key=\"${props.key || \"\"}\">\n <button name=\"${props.key || \"\"}\" input-key=\"${props.key || \"\"}\" class=\"cap-btn-outline\">\n ${props.label}\n </button>\n </div>`);\n let button = r.querySelector(\"button\");\n button.addEventListener(\"click\", e => props.onClick({\n props,\n event: e\n }));\n return r;\n },\n\n addKeyDownInputEvents(input) {\n input.addEventListener(\"keydown\", function (event) {\n if (event.keyCode === 13) {\n //ENTER\n input.dispatchEvent(new CustomEvent(\"saveMultiInput\", {\n bubbles: true,\n cancelable: false\n }));\n }\n\n if (event.keyCode === 27) {\n //ESC\n input.dispatchEvent(new CustomEvent(\"cancelMultiInput\", {\n bubbles: true,\n cancelable: false\n }));\n }\n });\n },\n\n createContextMenu({\n config,\n $capibaraElem = null,\n evt = null,\n date = null,\n item = null,\n selected = [],\n tabSelected = null,\n left = null,\n top = null,\n name = \"\"\n }) {\n if (config.timeline.contextMenu === undefined) return {\n elem: null,\n isVisible: false\n };\n let className = \"\";\n let style = \"\";\n let strHtml = \"\";\n let leftPosition = null;\n let topPosition = null;\n let isVisible = true;\n let boundRectCapibara = null;\n let gap = 15; //px\n\n if ($capibaraElem) {\n boundRectCapibara = $capibaraElem.getBoundingClientRect();\n }\n\n if (evt && boundRectCapibara) {\n left = evt.clientX;\n top = evt.clientY - boundRectCapibara.top;\n }\n\n if (left) {\n leftPosition = left;\n }\n\n if (top) {\n topPosition = top;\n }\n\n if (leftPosition !== null & topPosition !== null) {\n if (boundRectCapibara) {\n let transformStyle = \"\";\n\n if (topPosition > boundRectCapibara.height * 2 / 6 && topPosition <= boundRectCapibara.height * 4 / 6) {\n transformStyle += `translateY(-50%)`;\n }\n\n if (topPosition > boundRectCapibara.height * 4 / 6) {\n transformStyle += `translateY(-100%)`;\n }\n\n if (leftPosition > boundRectCapibara.width * 4 / 6) {\n transformStyle += `translateX(-100%)`;\n leftPosition -= gap;\n } else {\n leftPosition += gap;\n }\n\n if (transformStyle != \"\") {\n style += ` transform: ${transformStyle};`;\n }\n }\n\n style += `top: ${topPosition}px; left: ${leftPosition}px;`;\n } else {\n className += \"cm-hide\";\n isVisible = false;\n }\n\n strHtml += ` <div class=\"cap-context-menu-container ${className}\">\n <div class=\"cap-context-menu\" style=\"${style}\">\n </div>\n </div>`;\n let $contextMenuContainer = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(strHtml);\n let $contextMenu = $contextMenuContainer.querySelector(\".cap-context-menu\");\n config.timeline.contextMenu.options.forEach(option => {\n if (option.showIf) {\n let show = option.showIf({\n item,\n date,\n selected,\n name,\n tabSelected\n });\n if (!show) return;\n }\n\n let isEnabled = true;\n let isClickeable = true;\n\n if (option.enableIf) {\n isEnabled = option.enableIf({\n item,\n date,\n selected,\n name,\n tabSelected\n });\n }\n\n let optionClassName = \"\";\n let strIcon = \"\";\n let label = \"\";\n\n if (!isEnabled) {\n optionClassName += \"is-disabled \";\n }\n\n if (option.isDivider) {\n isClickeable = false;\n optionClassName += \"is-divider \";\n }\n\n if (option.label) {\n label = `<span>${option.label}</span>`;\n }\n\n if (option.icon) {\n strIcon = `<div class=\"cap-context-menu_item_icon\">\n <svg viewBox=\"0 0 24 24\">\n <path d=\"${option.icon}\" />\n </svg>\n </div>`;\n }\n\n let optionStrHtml = `\n <div class=\"cap-context-menu_item ${optionClassName}\">\n ${strIcon}\n ${label}\n </div>`;\n let $option = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(optionStrHtml);\n\n if (isEnabled && isClickeable) {\n $option.addEventListener(\"click\", evtClick => option.onClick({\n config,\n evt: evtClick,\n date,\n item,\n selected,\n tabSelected\n }));\n } else {\n $option.addEventListener(\"click\", evtClick => {\n evtClick.preventDefault();\n evtClick.stopPropagation();\n });\n }\n\n $contextMenu.append($option);\n });\n return {\n elem: $contextMenuContainer,\n isVisible\n };\n }\n\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvdXRpbC90YWJsZUVsZW1lbnRzLmpzLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vQ2FwaWJhcmEvLi9zcmMvdXRpbC90YWJsZUVsZW1lbnRzLmpzPzFkODYiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGRvbSBmcm9tIFwiLi4vdXRpbC9kb21VdGlsc1wiO1xuaW1wb3J0IHV0aWxzIGZyb20gXCIuLi91dGlsL3V0aWxzXCI7XG5pbXBvcnQgZGF0ZVV0aWxzIGZyb20gXCIuLi91dGlsL2RhdGVVdGlsc1wiO1xuXG5leHBvcnQgZGVmYXVsdCB7XG4gIC8qKlxuICAgKiBDcmVhIGVsZW1lbnRvIFRhYmxlXG4gICAqIENvbnRlbmRyw6EgbG9zIGVsZW1lbnRvcyBxdWUgYXBhcmVjZXJhbiBkZW50cm8gZGUgbGEgdGFibGEgZGUgcGxhbmlsbGFcbiAgICogU2UgVXNhIHBhcmEgOlxuICAgKiAgICAtIEFncmVnYXIgYmFja2dyb3VuZCBjb24gcGF0cm9uIGVzdGlsbyB0YWJsYVxuICAgKiAgICAtIEFncmVnYXIgZGF5TW91c2VPdmVyLCBkaXYgcXVlIGluZGljYSBwb3NpY2lvbiBkZSBtb3VzZVxuICAgKiAgICAtIEFncmVnYXIgRGV0YWlsRGF5LCBwYXJhIGRldGFsbGVzIGRlIGRhdG9zIGVuIHRhYmxhXG4gICAqICAgIC0gQWdyZWdhciBTZWxlY3RlZENvbnRhaW5lciwgcGFyYSBkaWFzIHNlbGVjY2lvbmFkb3NcbiAgICogICAgLSBBZ3JlZ2FyIEZsb2F0Qm94Q29udGFpbmVyLCBwYXJhIHZpc3VhbGl6YWNpb24gZGUgZGF0b3MgZW4gdGFibGFcbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIENvbmZpZ3VyYWNpb24gY2FwaWJhcmFcbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gY3JlYWRvXG4gICAqL1xuICBjcmVhdGVBZ1RhYmxlKGNvbmZpZykge1xuICAgIGxldCBlID0gZG9tLmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IFwiY2FwaWJhcmFcIiB9KTtcbiAgICBpZiAoY29uZmlnLnRpbWVsaW5lLmRhcmspIHtcbiAgICAgIGUuY2xhc3NMaXN0LmFkZChcImRhcmstdGhlbWVcIik7XG4gICAgfVxuICAgIGlmIChjb25maWcudGltZWxpbmUuaGVhZGVyLmV4dGVuZC5pc1Nob3cpIHtcbiAgICAgIGUuY2xhc3NMaXN0LmFkZChcImhlYWRlci1leHRlbmRlZFwiKTtcbiAgICB9XG4gICAgcmV0dXJuIGU7XG4gIH0sXG5cbiAgLyoqXG4gICAqIFJlY3JlYSBCYWNrZ3JvdW5kLCBxdWUgZXMgZWwgZm9uZG8gZ3JpZCwgY29tbyB0YWJsYVxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcGFyYW0ge09iamVjdH0gJGVsZW0gLSBFbGVtZW50byByZWxhY2lvbmFkbywgZG9uZGUgc2UgY3JlIGVsIGJhY2tncm91bmRcbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gQ29ybmVyIEZvb3RlclxuICAgKi9cbiAgcmVkcmF3QmFja2dyb3VuZChjb25maWcsICRlbGVtKSB7XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlQmFja2dyb3VuZChjb25maWcsICRlbGVtKTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSB5IHBvc2ljaW9uYSBmb25kbyBkZSB0YWJsYVxuICAgKiBFc3RlIGZvbmRvIGNvbnRpZW5lIHVuIHBhdHJvbiBkZSBDU1MgcXVlIGxlIGRhIGxhIGFwYXJpZW5jaWEgZGUgdGFibGFcbiAgICogcG9yIGxvIGN1YWwgc2UgZGViZSByZXBvc2ljaW9uYXIgc2VndW4gbGEgZmVjaGEgZGUgaW5pY2lvLCBwYXJhIGhhY2VyXG4gICAqIGNhbHphciBsb3MgZmluZXMgZGUgc2VtYW5hXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBjb25maWcgLSBDb25maWd1cmFjaW9uIGNhcGliYXJhXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbJGVsZW0gPSBudWxsXSAtIEVsZW1lbnRvIGJhY2tncm91bmQsIHNpIGVzIG51bGwsIGxvIGNyZWFcbiAgICogQHJldHVybiB7T2JqZWN0fSBlbGVtZW50byBEb20gQmFja2dyb3VuZFxuICAgKi9cbiAgY3JlYXRlQmFja2dyb3VuZChjb25maWcsICRlbGVtID0gbnVsbCkge1xuICAgIGxldCB7IGhlaWdodCwgd2lkdGgsIGRheVdpZHRoIH0gPSB1dGlscy5nZXRUYWJsZURpbWVuc2lvbnMoY29uZmlnKTtcblxuICAgIGxldCBzdGFydCA9IG5ldyBEYXRlKGNvbmZpZy50aW1lbGluZS5zdGFydCk7XG4gICAgbGV0IGVuZCA9IG5ldyBEYXRlKGNvbmZpZy50aW1lbGluZS5lbmQpO1xuXG4gICAgZW5kLnNldFRpbWUoZW5kLmdldFRpbWUoKSArIGRhdGVVdGlscy5kYXlJbk1pbGxpc2Vjb25kcyk7IC8vIGFkZCAyNCBob3Vyc1xuXG4gICAgbGV0IGRDb3JyZWN0ZWQgPSBuZXcgRGF0ZShcbiAgICAgIHN0YXJ0LnZhbHVlT2YoKSArIHN0YXJ0LmdldFRpbWV6b25lT2Zmc2V0KCkgKiA2MDAwMFxuICAgICk7XG4gICAgbGV0IHdlZWtEYXkgPSBkQ29ycmVjdGVkLmdldERheSgpO1xuICAgIGxldCBkaWZmV2Vla0RheXMgPSAod2Vla0RheSAtIDEpICogZGF5V2lkdGggKiAtMTtcblxuICAgICRlbGVtID0gJGVsZW0gfHwgZG9tLmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IFwiYmFja2dyb3VuZC1ncmlkXCIgfSk7XG4gICAgJGVsZW0uc3R5bGVbXCJiYWNrZ3JvdW5kLXBvc2l0aW9uXCJdID1cbiAgICAgIGRpZmZXZWVrRGF5cyArIFwicHggMCwgMCAwLCBcIiArIGRpZmZXZWVrRGF5cyArIFwicHggMFwiO1xuICAgICRlbGVtLnN0eWxlLndpZHRoID0gd2lkdGggKyBcInB4XCI7XG4gICAgJGVsZW0uc3R5bGUuaGVpZ2h0ID0gaGVpZ2h0ICsgMSArIFwicHhcIjtcbiAgICByZXR1cm4gJGVsZW07XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWEgUGxvdCBDb250YWluZXIgVmVydGljYWxcbiAgICogTG9zIHBsb3RzIHNvbiBlbGVtZW50b3MgcXVlIGFncmVnYW4gc2VjY2lvbmVzIGRlIGZvbmRvIGVuIGxhIHBsYW5pbGxhXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBjb25maWcgLSBDb25maWd1cmFjaW9uIGNhcGliYXJhXG4gICAqIEByZXR1cm4ge09iamVjdH0gRWxlbWVudG8gRG9tIHBsb3RWZXJ0aWNhbENvbnRhaW5lclxuICAgKi9cbiAgY3JlYXRlUGxvdFZlcnRpY2FsQ29udGFpbmVyKGNvbmZpZykge1xuICAgIGxldCAkZWxlbSA9IGRvbS5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtcbiAgICAgIGNsYXNzTmFtZTogXCJwbG90LXZlcnRpY2FsLWNvbnRhaW5lclwiLFxuICAgIH0pO1xuICAgIHJldHVybiB0aGlzLnJlZHJhd1Bsb3RWZXJ0aWNhbENvbnRhaW5lcihjb25maWcsICRlbGVtKTtcbiAgfSxcblxuICBjcmVhdGVQbG90SG9yaXpvbnRhbENvbnRhaW5lcihjb25maWcpIHtcbiAgICBsZXQgJGVsZW0gPSBkb20uY3JlYXRlRWxlbWVudChcImRpdlwiLCB7XG4gICAgICBjbGFzc05hbWU6IFwicGxvdC1ob3Jpem9udGFsLWNvbnRhaW5lclwiLFxuICAgIH0pO1xuICAgIHJldHVybiB0aGlzLnJlZHJhd1Bsb3RIb3Jpem9udGFsQ29udGFpbmVyKGNvbmZpZywgJGVsZW0pO1xuICB9LFxuXG4gIC8qKlxuICAgKiBSZWNyZWEgcGxvdFZlcnRpY2FsQ29udGFpbmVyLCB1c2FuZG8gZWxlbWVudG8gZXhpc3RlbnRlXG4gICAqIHVzYSB1biBlbGVtZW50byBleGlzdGVudGUgcGFyYSB1c2FyIGxhIGZ1bmNpb24gcGFyYSByZWRpYnVqYXIgZWwgZWxlbWVudG9cbiAgICpcbiAgICogTG9zIFBsb3RzIHNlIGluc2VydGFuIGNvbW8gZGl2cywgY29uIHBvc2ljaW9uIGVzcGVjaWZpY2FkYSxcbiAgICogY29uIGFuY2hvIGRlIGRpYVxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcGFyYW0ge09iamVjdH0gJGVsZW0gLSBFbGVtZW50byBEb20gZG9uZGUgY3JlYSBwbG90VmVydGljYWxDb250YWluZXJcbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gcGxvdFZlcnRpY2FsQ29udGFpbmVyXG4gICAqL1xuICByZWRyYXdQbG90VmVydGljYWxDb250YWluZXIoY29uZmlnLCAkZWxlbSkge1xuICAgICRlbGVtLmlubmVySFRNTCA9IFwiXCI7XG4gICAgaWYgKGNvbmZpZy50aW1lbGluZS5wbG90cyAmJiBjb25maWcudGltZWxpbmUucGxvdHMudmVydGljYWwpIHtcbiAgICAgIGxldCB7IGhlaWdodCwgZGF5V2lkdGggfSA9IHV0aWxzLmdldFRhYmxlRGltZW5zaW9ucyhjb25maWcpO1xuXG4gICAgICBjb25maWcudGltZWxpbmUucGxvdHMudmVydGljYWwuZm9yRWFjaCgocCkgPT4ge1xuICAgICAgICBsZXQgZGlmZkRheXMgPSBNYXRoLmZsb29yKFxuICAgICAgICAgIGRhdGVVdGlscy5kaWZmRGF5cyhjb25maWcudGltZWxpbmUuc3RhcnQsIHAuZGF0ZSlcbiAgICAgICAgKTtcbiAgICAgICAgbGV0IGxlZnQgPSBkaWZmRGF5cyAqIGRheVdpZHRoO1xuICAgICAgICBsZXQgcGxvdCA9IGRvbS5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtcbiAgICAgICAgICBjbGFzc05hbWVzOiBbXCJwbG90LXZlcnRpY2FsXCIsIHAuY2xhc3NOYW1lIHx8IFwiXCJdLFxuICAgICAgICAgIHN0eWxlOiB7XG4gICAgICAgICAgICBcIm1hcmdpbi1sZWZ0XCI6IGxlZnQgKyBcInB4XCIsXG4gICAgICAgICAgICBoZWlnaHQ6IGhlaWdodCArIFwicHhcIixcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgICAgJGVsZW0uYXBwZW5kQ2hpbGQocGxvdCk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuICRlbGVtO1xuICB9LFxuXG4gIHJlZHJhd1Bsb3RIb3Jpem9udGFsQ29udGFpbmVyKGNvbmZpZywgJGVsZW0pIHtcbiAgICAkZWxlbS5pbm5lckhUTUwgPSBcIlwiO1xuICAgIGlmIChjb25maWcudGltZWxpbmUucGxvdHMgJiYgY29uZmlnLnRpbWVsaW5lLnBsb3RzLmhvcml6b250YWwpIHtcbiAgICAgIGxldCB7IHdpZHRoLCBpdGVtSGVpZ2h0IH0gPSB1dGlscy5nZXRUYWJsZURpbWVuc2lvbnMoY29uZmlnKTtcbiAgICAgIGNvbmZpZy50aW1lbGluZS5wbG90cy5ob3Jpem9udGFsLmZvckVhY2goKHApID0+IHtcbiAgICAgICAgbGV0IGl0ZW0gPSB1dGlscy5nZXRJdGVtQnlJZChjb25maWcsIHAuaWROb2RlLCBwLnR5cGVOb2RlKTtcbiAgICAgICAgbGV0IHRvcFBvc2l0aW9uID0gdXRpbHMuZ2V0UG9zaXRpb25CeUl0ZW0oY29uZmlnLCBpdGVtLCBcInBhcmVudFwiKTtcbiAgICAgICAgbGV0IHBsb3QgPSBkb20uY3JlYXRlRWxlbWVudChcImRpdlwiLCB7XG4gICAgICAgICAgY2xhc3NOYW1lczogW1wicGxvdC1ob3Jpem9udGFsXCIsIHAuY2xhc3NOYW1lIHx8IFwiXCJdLFxuICAgICAgICAgIHN0eWxlOiB7XG4gICAgICAgICAgICBcIm1hcmdpbi10b3BcIjogdG9wUG9zaXRpb24gKiBpdGVtSGVpZ2h0ICsgXCJweFwiLFxuICAgICAgICAgICAgd2lkdGg6IHdpZHRoICsgXCJweFwiLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgICAkZWxlbS5hcHBlbmRDaGlsZChwbG90KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gJGVsZW07XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWEgQ29ybmVyIEl6cXVpZXJkb1xuICAgKiBTZSB1c2EgcGFyYSA6XG4gICAqICAgIC0gdGl0dWxvcyByZWxhY2lvbmFkb3MgY29uIGxvcyBkYXRvcyBkZWwgc2lkZWJhciBpenF1aWVyZG9cbiAgICogICAgLSB0aXR1bG9zIHBhcmEgaW5wdXRzIGRlIGhlYWRlciwgYWJzb2x1dGUgYSBsYSBkZXJlY2hhXG4gICAqICAgIC0gYm90b24gcGFyYSBtb3N0cmFyL29jdWx0YXIgc2lkZWJhciBpenF1aWVyZG9cbiAgICogICAgLSBwcm9tZWRpb3NcbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIENvbmZpZ3VyYWNpb24gY2FwaWJhcmFcbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gQ29ybmVyXG4gICAqL1xuICBjcmVhdGVDb3JuZXIoY29uZmlnLCB0YWIgPSBudWxsKSB7XG4gICAgbGV0ICRlbGVtID0gZG9tLmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IFwiY29ybmVyXCIgfSk7XG4gICAgcmV0dXJuIHRoaXMucmVkcmF3Q29ybmVyKCRlbGVtLCBjb25maWcsIHRhYik7XG4gIH0sXG5cbiAgcmVkcmF3Q29ybmVyKCRlbGVtLCBjb25maWcsIHRhYiA9IG51bGwpIHtcbiAgICBsZXQgbGFiZWxzSW5pdGlhbENvcm5lciA9IGNvbmZpZy50aW1lbGluZS5uYXYubGVmdC5pbml0aWFsLnZhcnNcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgICh2KSA9PlxuICAgICAgICAgIHYub25seVRhYiA9PSB1bmRlZmluZWQgfHwgKHYub25seVRhYiAmJiB0YWIgJiYgdi5vbmx5VGFiID09IHRhYi5rZXkpXG4gICAgICApXG4gICAgICAubWFwKChkKSA9PiBgPHNwYW4gY2xhc3M9XCJpdGVtLWNvbFwiPiR7ZC5sYWJlbH08L3NwYW4+YClcbiAgICAgIC5qb2luKFwiXCIpO1xuXG4gICAgbGV0IGxhYmVsc0V4dGVuZENvcm5lciA9IGNvbmZpZy50aW1lbGluZS5uYXYubGVmdC5leHRlbmQudmFyc1xuICAgICAgLmZpbHRlcihcbiAgICAgICAgKHYpID0+XG4gICAgICAgICAgdi5vbmx5VGFiID09IHVuZGVmaW5lZCB8fCAodi5vbmx5VGFiICYmIHRhYiAmJiB2Lm9ubHlUYWIgPT0gdGFiLmtleSlcbiAgICAgIClcbiAgICAgIC5tYXAoKGQpID0+IGA8c3BhbiBjbGFzcz1cIml0ZW0tY29sXCI+JHtkLmxhYmVsfTwvc3Bhbj5gKVxuICAgICAgLmpvaW4oXCJcIik7XG5cbiAgICBsZXQgbGFiZWxzSGVhZGVyRXh0ZW5kID0gY29uZmlnLnRpbWVsaW5lLmhlYWRlci5leHRlbmQuZGF0YVxuICAgICAgLm1hcCgoZCkgPT4ge1xuICAgICAgICBpZiAoZC5pc0hpZGRlbikgcmV0dXJuIFwiXCI7XG5cbiAgICAgICAgbGV0IGF2ZyA9IFwiXCI7XG4gICAgICAgIGxldCB0b29sdGlwID0gXCJcIjtcbiAgICAgICAgbGV0IGNsYXNzTmFtZSA9IFwiXCI7XG4gICAgICAgIGxldCBpc0FjY2VudCA9IGQuaXNBY2NlbnQ7XG5cbiAgICAgICAgaWYgKGQuYXZlcmFnZSkge1xuICAgICAgICAgIGF2ZyA9IGAgPHNwYW4gY2xhc3M9XCJhdmVyYWdlIFwiPiAoIDxzcGFuPiA8c3BhbiBjbGFzcz1cInN5bWJvbFwiPnjMhDwvc3Bhbj4gJHtkLmF2ZXJhZ2V9IDwvc3Bhbj4pICA8L3NwYW4+ICAgYDtcblxuICAgICAgICAgIHRvb2x0aXAgPSBgY2FwLXRvb2x0aXA9XCJQcm9tZWRpbyAke2QubGFiZWx9IDogJHtkLmF2ZXJhZ2V9ICR7XG4gICAgICAgICAgICBkLnN1ZmZpeCB8fCBcIlwiXG4gICAgICAgICAgfVwiYDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkLmNvbG9yKSB7XG4gICAgICAgICAgaWYgKGlzQWNjZW50KSB7XG4gICAgICAgICAgICBjbGFzc05hbWUgPSBkLmNvbG9yID8gXCJjLVwiICsgZC5jb2xvciArIFwiLS1iYWNrZ3JvdW5kXCIgOiBcIlwiO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjbGFzc05hbWUgPSBkLmNvbG9yID8gXCJjLVwiICsgZC5jb2xvciArIFwiLS10ZXh0IFwiIDogXCJcIjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYDxkaXYgY2xhc3M9XCJpbnB1dC10aXRsZS1jb250YWluZXIgJHtcbiAgICAgICAgICBpc0FjY2VudCA/IFwiaW5wdXQtdGl0bGUtLWFjY2VudFwiIDogXCJcIlxuICAgICAgICB9ICR7ZC5pc1BlcnNpc3RlbnQgPyBcInBlcnNpc3RlbnRcIiA6IFwiXCJ9XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gJHt0b29sdGlwfSBjbGFzcz1cImlucHV0LXRpdGxlICR7Y2xhc3NOYW1lfVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHthdmd9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAke2QubGFiZWx9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PmA7XG4gICAgICB9KVxuICAgICAgLmpvaW4oXCJcIik7XG5cbiAgICBsZXQgdG9nZ2xlU2lkZWJhckJ0blN0cmluZyA9IGBcbiAgICAgICAgICA8YnV0dG9uIHRvZ2dsZS1zaWRlYmFyIGNsYXNzPVwiY2FwLWJ0bi1pY29uIGNhcC1idG4taWNvbi1yYWlzZWQgY2FwLWJ0bi10b2dnbGUtc2lkZWJhciBcIj5cbiAgICAgICAgICAgIDxzcGFuPlxuICAgICAgICAgICAgICA8c3ZnIHN0eWxlPVwid2lkdGg6MjRweDtoZWlnaHQ6MjRweFwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIj5cbiAgICAgICAgICAgICAgICAgIDxwYXRoIGZpbGw9XCJjdXJyZW50Q29sb3JcIiBkPVwiTTguNTksMTYuNThMMTMuMTcsMTJMOC41OSw3LjQxTDEwLDZMMTYsMTJMMTAsMThMOC41OSwxNi41OFpcIiAvPlxuICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICA8L2J1dHRvbj4gYDtcblxuICAgIGlmKGNvbmZpZy50aW1lbGluZS5uYXYubGVmdC5oaWRlVG9nZ2xlU2lkZWJhckJ1dHRvbil7XG4gICAgICB0b2dnbGVTaWRlYmFyQnRuU3RyaW5nID0gXCJcIjtcbiAgICB9XG5cbiAgICBsZXQgdGVtcGxhdGUgPSBgPGRpdj5cblxuICAgICAgICAgICR7dG9nZ2xlU2lkZWJhckJ0blN0cmluZ31cbiAgICAgICAgPGRpdiBjbGFzcz1cImNvcm5lci10aXRsZVwiPlxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYm90dG9tLXRleHRcIj5cbiAgICAgICAgICAgICR7Y29uZmlnLnRpbWVsaW5lLmNvcm5lci5sZWZ0LmxhYmVsfVxuICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgPGRpdiBjbGFzcz1cImluaXRpYWwtY29ybmVyXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImluaXRpYWwtY29ybmVyLXRpdGxlXCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImJvdHRvbS1jb250YWluZXIgaGlkZVwiPlxuICAgICAgICAgICAgICAke2NvbmZpZy50aW1lbGluZS5jb3JuZXIuaW5pdGlhbC5sYWJlbH1cbiAgICAgICAgICAgIDwvc3Bhbj5cblxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImJvdHRvbS1jb250YWluZXJcIj5cbiAgICAgICAgICAgICAgJHtsYWJlbHNJbml0aWFsQ29ybmVyfVxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG5cblxuICAgICAgICA8ZGl2IGNsYXNzPVwiZXh0ZW5kLWNvcm5lclwiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJleC1jb3JuZXItdGl0bGVcIj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYm90dG9tLWNvbnRhaW5lciBoaWRlXCI+XG4gICAgICAgICAgICAgICR7Y29uZmlnLnRpbWVsaW5lLmNvcm5lci5leHRlbmQubGFiZWx9XG4gICAgICAgICAgICA8L3NwYW4+XG5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJib3R0b20tY29udGFpbmVyXCI+XG4gICAgICAgICAgICAgICR7bGFiZWxzRXh0ZW5kQ29ybmVyfVxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG5cblxuICAgICAgICA8ZGl2IGNsYXNzPVwiY2FwLWJ0bi1uYXYtY29ybmVyXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXRpdGxlc1wiPlxuICAgICAgICAgICAgICAke2xhYmVsc0hlYWRlckV4dGVuZH1cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgPGRpdiBjbGFzcz1cInByb2dyZXNzLWJhciBwcm9ncmVzcy1iYXItbGVmdCBoaWRlLXByb2dyZXNzXCI+PC9kaXY+XG5cbiAgICAgIDwvZGl2PmA7XG5cbiAgICBsZXQgciA9IGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwodGVtcGxhdGUpO1xuXG4gICAgJGVsZW0uaW5uZXJIVE1MID0gXCJcIjtcbiAgICAkZWxlbS5hcHBlbmQocik7XG5cbiAgICBsZXQgdG9nZ2xlU2lkZWJhciA9ICRlbGVtLnF1ZXJ5U2VsZWN0b3IoXCJbdG9nZ2xlLXNpZGViYXJdXCIpO1xuICAgIGlmKHRvZ2dsZVNpZGViYXIpe1xuICAgICAgdG9nZ2xlU2lkZWJhci5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGUpID0+IHtcbiAgICAgICAgci5kaXNwYXRjaEV2ZW50KFxuICAgICAgICAgIG5ldyBDdXN0b21FdmVudChcInRvZ2dsZVNpZGViYXJcIiwge1xuICAgICAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgICAgIGNhbmNlbGFibGU6IGZhbHNlLFxuICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gJGVsZW07XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWEgQ29ybmVyIERlcmVjaG9cbiAgICogU2UgdXNhIHBhcmEgOlxuICAgKiAgICAtIHRpdHVsb3MgcmVsYWNpb25hZG9zIGNvbiBsb3MgZGF0b3MgZGVsIHNpZGViYXIgRGVyZWNob1xuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBjb3JuZXJcbiAgICovXG4gIGNyZWF0ZUNvcm5lclJpZ2h0KGNvbmZpZywgdGFiID0gbnVsbCkge1xuICAgIGxldCAkZWxlbSA9IGRvbS5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lczogW1wiY29ybmVyXCIsXCJyaWdodFwiXSB9KTtcbiAgICByZXR1cm4gdGhpcy5yZWRyYXdDb3JuZXJSaWdodCgkZWxlbSwgY29uZmlnLCB0YWIpO1xuICB9LFxuXG4gIHJlZHJhd0Nvcm5lclJpZ2h0KCRlbCwgY29uZmlnLCB0YWIgPSBudWxsKSB7XG4gICAgbGV0IGxhYmVsID0gXCJcIjtcblxuICAgIGlmIChjb25maWcudGltZWxpbmUuY29ybmVyLnJpZ2h0LmxhYmVsKSB7XG4gICAgICBgIDxzcGFuPlxuICAgICAgICAgICAgJHtjb25maWcudGltZWxpbmUuY29ybmVyLnJpZ2h0LmxhYmVsfVxuICAgICAgICAgIDwvc3Bhbj5gO1xuICAgIH1cblxuICAgIGxldCBzdHIgPSBgXG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb3JuZXItdGl0bGVcIj5cbiAgICAgICAgJHtsYWJlbH1cbiAgICAgICAgPGRpdiBjbGFzcz1cImJ0bi1jb250YWluZXJcIj48L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzcy1iYXIgcHJvZ3Jlc3MtYmFyLXJpZ2h0IGhpZGUtcHJvZ3Jlc3NcIj48L2Rpdj5cbiAgICBgO1xuICAgICRlbC5pbm5lckhUTUwgPSBzdHIudHJpbSgpO1xuICAgIGxldCAkYnRuQ29udGFpbmVyID0gJGVsLnF1ZXJ5U2VsZWN0b3IoXCIuYnRuLWNvbnRhaW5lclwiKTtcblxuICAgIGlmIChjb25maWcudGltZWxpbmUuY29ybmVyLnJpZ2h0LmJ1dHRvbnMpIHtcbiAgICAgIGNvbmZpZy50aW1lbGluZS5jb3JuZXIucmlnaHQuYnV0dG9ucy5mb3JFYWNoKChidG4pID0+IHtcbiAgICAgICAgbGV0IGlzRW5hYmxlZCA9IGJ0bi5nZXRJc0VuYWJsZWQgPyBidG4uZ2V0SXNFbmFibGVkKCkgOiB0cnVlO1xuICAgICAgICBpZihpc0VuYWJsZWQpe1xuICAgICAgICAgIGxldCAkYnRuID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChgXG4gICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiY29ybmVyLWJ0biBjYXAtYnRuLXJhaXNlZFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAke2J0bi5sYWJlbCB8fCBcIlwifVxuICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+IGApO1xuXG4gICAgICAgICAgaWYgKGJ0bi5vbkNsaWNrKSB7XG4gICAgICAgICAgICAkYnRuLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBidG4ub25DbGljayk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgJGJ0bkNvbnRhaW5lci5hcHBlbmRDaGlsZCgkYnRuKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICAgIGlmKGNvbmZpZy50aW1lbGluZS5jb3JuZXIucmlnaHQuaW5wdXRzKXtcbiAgICAgIGNvbmZpZy50aW1lbGluZS5jb3JuZXIucmlnaHQuaW5wdXRzLmZvckVhY2goaW5wdXQgPT4ge1xuICAgICAgICBsZXQgJGlucHV0ID0gdGhpcy5jcmVhdGVDb3JuZXJSaWdodElucHV0KHtpbnB1dENvbmZpZzppbnB1dH0pO1xuICAgICAgICAkYnRuQ29udGFpbmVyLmFwcGVuZENoaWxkKCRidG4pO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiAkZWw7XG4gIH0sXG5cbiAgY3JlYXRlQ29ybmVyUmlnaHRJbnB1dCh7aW5wdXRDb25maWcsIGRhdGFEYXkgPSBudWxsLCBkYXlTZWxlY3RlZCA9IG51bGwgfSl7XG4gICAgbGV0IHIgPSBudWxsO1xuICAgIHN3aXRjaChpbnB1dENvbmZpZy50eXBlKXtcbiAgICAgIGNhc2UgJ2F1dG9jb21wbGV0ZS1jcnVkJzpcbiAgICAgICAgciA9IHRoaXMuY3JlYXRlQ29ybmVyUmlnaHRJbnB1dEF1dG9jb21wbGV0ZUNydWQoe2lucHV0Q29uZmlnLCBkYXRhRGF5LCBkYXlTZWxlY3RlZH0pO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gICAgcmV0dXJuIHI7XG4gIH0sXG5cbiAgY3JlYXRlQ29ybmVyUmlnaHRJbnB1dEF1dG9jb21wbGV0ZUNydWQoe2lucHV0Q29uZmlnLCBkYXRhRGF5LCBkYXlTZWxlY3RlZCB9KXtcbiAgICBsZXQgZWxlbSA9IFwidGVzdFwiO1xuICAgIHJldHVybiBlbGVtO1xuICB9LFxuXG4gIC8qKlxuICAgKiBDcmVhIEhlYWRlciBUb3BcbiAgICogU2UgdXNhIHBhcmEgOlxuICAgKiAgICAtIE1hbmVqbyBkZSB0YWJzXG4gICAqICAgIC0gQm90b25lcyBkZSBuYXZlZ2FjacOzbiB5IHNlbGVjY2nDs24gZGUgZmVjaGFcbiAgICogICAgLSBCb3RvbiB0b2dnbGUgRGFyayBtb2RlXG4gICAqICAgIC0gQm90b24gdG9nZ2xlIEhlYWRlciBleHRlbmRlZFxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbVxuICAgKi9cblxuICBjcmVhdGVIZWFkZXJUb3AoY29uZmlnLCB0YWJTZWxlY3RlZCA9IG51bGwpIHtcbiAgICByZXR1cm4gdGhpcy5yZWRyYXdIZWFkZXJUb3AoY29uZmlnLCB0YWJTZWxlY3RlZCwgZG9tLmNyZWF0ZUVsZW1lbnQoXCJkaXZcIikpO1xuICB9LFxuXG4gIHJlZHJhd0hlYWRlclRvcChjb25maWcsIHRhYlNlbGVjdGVkID0gbnVsbCwgJGVsZW0pIHtcbiAgICBsZXQgc3RyID0gYFxuICAgICAgPGRpdiBjbGFzcz1cImhlYWRlci10b3BcIj5gO1xuXG4gICAgaWYgKGNvbmZpZy50aW1lbGluZS50YWJzKSB7XG4gICAgICBsZXQgc2hvd1RhYnMgPSB0cnVlO1xuXG4gICAgICBpZiAoY29uZmlnLnRpbWVsaW5lLnRhYnMuZmlsdGVyKCh0KSA9PiAhdC5pc0hpZGRlbikubGVuZ3RoID09IDApIHtcbiAgICAgICAgc2hvd1RhYnMgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHNob3dUYWJzKSB7XG4gICAgICAgIHN0ciArPSBgIDxkaXYgY2xhc3M9XCJ0YWItc2VsZWN0LWNvbnRhaW5lciBjLWQtZGVza3RvcC1ub25lIGMtZC1tb2JpbGUtZmxleFwiPlxuICAgICAgICAgICAgICAgICAgPHNlbGVjdCBjbGFzcz1cInRhYnMtc2VsZWN0XCIgPmA7XG5cbiAgICAgICAgY29uZmlnLnRpbWVsaW5lLnRhYnMuZm9yRWFjaCgodGFiKSA9PiB7XG4gICAgICAgICAgaWYgKCF0YWIuaXNIaWRkZW4pIHtcbiAgICAgICAgICAgIHN0ciArPSBgIDxvcHRpb24gJHtcbiAgICAgICAgICAgICAgdGFiID09IHRhYlNlbGVjdGVkID8gJ3NlbGVjdGVkPVwic2VsZWN0ZWRcIicgOiBcIlwiXG4gICAgICAgICAgICB9IHZhbHVlPVwiJHt0YWIuaWR9XCI+ICR7dGFiLmxhYmVsfSA8L29wdGlvbj5gO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgc3RyICs9IGA8L3NlbGVjdD4gPC9kaXY+YDtcblxuICAgICAgICBzdHIgKz0gYCA8ZGl2IGNsYXNzPVwidGFicy1jb250YWluZXIgYy1kLWRlc2t0b3AtZmxleCBjLWQtbW9iaWxlLW5vbmVcIj5gO1xuXG4gICAgICAgIGNvbmZpZy50aW1lbGluZS50YWJzLmZvckVhY2goKHRhYikgPT4ge1xuICAgICAgICAgIGlmICghdGFiLmlzSGlkZGVuKSB7XG4gICAgICAgICAgICBzdHIgKz0gYCA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cInRhYiAke3RhYi5kaXNhYmxlZCA/IFwiZGlzYWJsZWRcIiA6IFwiXCJ9ICAke1xuICAgICAgICAgICAgICB0YWIgPT0gdGFiU2VsZWN0ZWQgPyBcImFjdGl2ZVwiIDogXCJcIlxuICAgICAgICAgICAgfSAgJHt0YWIuY29sb3J9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yPVwiJHt0YWIuY29sb3J9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LWtleT1cIiR7dGFiLmlkfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAke1xuICAgICAgICAgICAgICAgICAgICAgICAgICB0YWIudG9vbHRpcCA/ICdjYXAtdG9vbHRpcD1cIicgKyB0YWIudG9vbHRpcCArICdcIicgOiBcIlwiXG4gICAgICAgICAgICAgICAgICAgICAgICB9ID5cbiAgICAgICAgICAgICAgICAgICAgPHNwYW4+JHt0YWIubGFiZWx9PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAke3RhYi5pY29uIHx8IFwiXCJ9XG4gICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgIGA7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBzdHIgKz0gYDwvZGl2PmA7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRhYlNlbGVjdGVkKSB7XG4gICAgICBpZiAodGFiU2VsZWN0ZWQubGVnZW5kcykge1xuICAgICAgICAvKlxuICAgICAgICBzdHIgKz0gYDxkaXYgY2xhc3M9XCJsZWdlbmRzLXNlbGVjdC1jb250YWluZXIgYy1kLWRlc2t0b3Atbm9uZSBjLWQtbW9iaWxlLWZsZXhcIj5cbiAgICAgICAgICAgICAgICA8c2VsZWN0IGNsYXNzPVwibGVnZW5kcy1zZWxlY3RcIiBtdWx0aXBsZT5gO1xuXG4gICAgICAgIHRhYlNlbGVjdGVkLmxlZ2VuZHMuZm9yRWFjaChsZWdlbmQgPT4ge1xuICAgICAgICAgICAgc3RyICs9YCA8b3B0aW9uIHZhbHVlPVwiJHtsZWdlbmQuaWR9XCI+ICR7bGVnZW5kLmxhYmVsfSA8L29wdGlvbj5gXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHN0ciArPSBgPC9zZWxlY3Q+XG4gICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICAgICAgKi9cblxuICAgICAgICBsZXQgdG9nZ2xlTGVnZW5kc0ljb25QYXRoID1cbiAgICAgICAgICBcIk03LDVIMjFWN0g3VjVNNywxM1YxMUgyMVYxM0g3TTQsNC41QTEuNSwxLjUgMCAwLDEgNS41LDZBMS41LDEuNSAwIDAsMSA0LDcuNUExLjUsMS41IDAgMCwxIDIuNSw2QTEuNSwxLjUgMCAwLDEgNCw0LjVNNCwxMC41QTEuNSwxLjUgMCAwLDEgNS41LDEyQTEuNSwxLjUgMCAwLDEgNCwxMy41QTEuNSwxLjUgMCAwLDEgMi41LDEyQTEuNSwxLjUgMCAwLDEgNCwxMC41TTcsMTlWMTdIMjFWMTlIN000LDE2LjVBMS41LDEuNSAwIDAsMSA1LjUsMThBMS41LDEuNSAwIDAsMSA0LDE5LjVBMS41LDEuNSAwIDAsMSAyLjUsMThBMS41LDEuNSAwIDAsMSA0LDE2LjVaXCI7XG5cbiAgICAgICAgc3RyICs9IGAgXG4gICAgICAgIDxidXR0b24gdG9nZ2xlLWxlZ2VuZHMgY2xhc3M9XCJjYXAtYnRuLWljb24gY2FwLWJ0bi1pY29uLXJhaXNlZCBcIj5cbiAgICAgICAgICA8c3Bhbj5cbiAgICAgICAgICAgIDxzdmcgc3R5bGU9XCJ3aWR0aDoyNHB4O2hlaWdodDoyNHB4XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiPlxuICAgICAgICAgICAgICAgIDxwYXRoIGZpbGw9XCJjdXJyZW50Q29sb3JcIiBkPVwiJHt0b2dnbGVMZWdlbmRzSWNvblBhdGh9XCIgLz5cbiAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgPC9idXR0b24+IFxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJsZWdlbmRzLWNvbnRhaW5lciBmb3JjZS1tb2JpbGUtc3R5bGUgaGlkZVwiPiBgO1xuXG4gICAgICAgIHRhYlNlbGVjdGVkLmxlZ2VuZHMuZm9yRWFjaCgobGVnZW5kKSA9PiB7XG4gICAgICAgICAgbGV0IGNvbG9yQ2xhc3MgPSBcIlwiO1xuICAgICAgICAgIGxldCBjb2xvckJnID0gXCJcIjtcblxuICAgICAgICAgIGlmICh1dGlscy5pc0hleENvbG9yKGxlZ2VuZC5jb2xvcikpIHtcbiAgICAgICAgICAgIGNvbG9yQmcgPSBcImJhY2tncm91bmQ6XCIgKyBsZWdlbmQuY29sb3I7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbG9yQ2xhc3MgPSBsZWdlbmQuY29sb3IgPyBsZWdlbmQuY29sb3IgKyBcIi0tYmFja2dyb3VuZFwiIDogXCJcIjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBzdHIgKz0gYCA8ZGl2XG4gICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJsZWdlbmQgJHtsZWdlbmQuYWN0aXZlID8gXCJhY3RpdmVcIiA6IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1rZXk9XCIke2xlZ2VuZC5rZXl9XCJcbiAgICAgICAgICAgICAgICAgICAgICAke1xuICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRvb2x0aXAgPyBgY2FwLXRvb2x0aXA9XCIke2xlZ2VuZC50b29sdGlwfVwiYCA6IFwiXCJcbiAgICAgICAgICAgICAgICAgICAgICB9ID5cbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpY29uLWxlZ2VuZCAke2NvbG9yQ2xhc3N9ICR7XG4gICAgICAgICAgICBsZWdlbmQuc2hhcGVcbiAgICAgICAgICB9XCIgc3R5bGU9XCIke2NvbG9yQmd9XCI+PC9kaXY+XG4gICAgICAgICAgICAgICAgICA8c3Bhbj4ke2xlZ2VuZC5sYWJlbH08L3NwYW4+XG4gICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc3RyICs9IGA8L2Rpdj5gO1xuICAgICAgfVxuICAgIH1cblxuICAgIHN0ciArPSBgXG5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwic3BhY2VyXCI+PC9kaXY+XG5cblxuXG4gICAgICAgICAgPGJ1dHRvbiBjYXAtYnRuLXByZXYgY2xhc3M9XCJjYXAtYnRuLWljb24gY2FwLWJ0bi1pY29uLXJhaXNlZFwiPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImljb25cIj5cbiAgICAgICAgICAgICAgPHN2ZyBzdHlsZT1cIndpZHRoOjI0cHg7aGVpZ2h0OjI0cHhcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgICAgICAgICAgICAgICA8cGF0aCBmaWxsPVwiY3VycmVudENvbG9yXCIgZD1cIk0yMCwxMFYxNEgxMUwxNC41LDE3LjVMMTIuMDgsMTkuOTJMNC4xNiwxMkwxMi4wOCw0LjA4TDE0LjUsNi41TDExLDEwSDIwWlwiIC8+XG4gICAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgICAgICA8L3NwYW4+XG5cbiAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJsb2FkaW5nLWljb25cIj5cbiAgICAgICAgICAgICAgICA8c3ZnIHZlcnNpb249XCIxLjFcIiBpZD1cImxvYWRlci0xXCIgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIHhtbG5zOnhsaW5rPVwiaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlua1wiIHg9XCIwcHhcIiB5PVwiMHB4XCJcbiAgICAgICAgICAgICAgIHdpZHRoPVwiMzJweFwiIGhlaWdodD1cIjMycHhcIiB2aWV3Qm94PVwiMCAwIDQwIDQwXCIgZW5hYmxlLWJhY2tncm91bmQ9XCJuZXcgMCAwIDQwIDQwXCIgeG1sOnNwYWNlPVwicHJlc2VydmVcIj5cbiAgICAgICAgICAgICAgPHBhdGggb3BhY2l0eT1cIjAuMlwiIGZpbGw9XCIjMDAwXCIgZD1cIk0yMC4yMDEsNS4xNjljLTguMjU0LDAtMTQuOTQ2LDYuNjkyLTE0Ljk0NiwxNC45NDZjMCw4LjI1NSw2LjY5MiwxNC45NDYsMTQuOTQ2LDE0Ljk0NlxuICAgICAgICAgICAgICAgIHMxNC45NDYtNi42OTEsMTQuOTQ2LTE0Ljk0NkMzNS4xNDYsMTEuODYxLDI4LjQ1NSw1LjE2OSwyMC4yMDEsNS4xNjl6IE0yMC4yMDEsMzEuNzQ5Yy02LjQyNSwwLTExLjYzNC01LjIwOC0xMS42MzQtMTEuNjM0XG4gICAgICAgICAgICAgICAgYzAtNi40MjUsNS4yMDktMTEuNjM0LDExLjYzNC0xMS42MzRjNi40MjUsMCwxMS42MzMsNS4yMDksMTEuNjMzLDExLjYzNEMzMS44MzQsMjYuNTQxLDI2LjYyNiwzMS43NDksMjAuMjAxLDMxLjc0OXpcIi8+XG4gICAgICAgICAgICAgIDxwYXRoIGZpbGw9XCIjMDAwXCIgZD1cIk0yNi4wMTMsMTAuMDQ3bDEuNjU0LTIuODY2Yy0yLjE5OC0xLjI3Mi00Ljc0My0yLjAxMi03LjQ2Ni0yLjAxMmgwdjMuMzEyaDBcbiAgICAgICAgICAgICAgICBDMjIuMzIsOC40ODEsMjQuMzAxLDkuMDU3LDI2LjAxMywxMC4wNDd6XCI+XG4gICAgICAgICAgICAgICAgPGFuaW1hdGVUcmFuc2Zvcm0gYXR0cmlidXRlVHlwZT1cInhtbFwiXG4gICAgICAgICAgICAgICAgICBhdHRyaWJ1dGVOYW1lPVwidHJhbnNmb3JtXCJcbiAgICAgICAgICAgICAgICAgIHR5cGU9XCJyb3RhdGVcIlxuICAgICAgICAgICAgICAgICAgZnJvbT1cIjAgMjAgMjBcIlxuICAgICAgICAgICAgICAgICAgdG89XCIzNjAgMjAgMjBcIlxuICAgICAgICAgICAgICAgICAgZHVyPVwiMS41c1wiXG4gICAgICAgICAgICAgICAgICByZXBlYXRDb3VudD1cImluZGVmaW5pdGVcIi8+XG4gICAgICAgICAgICAgICAgPC9wYXRoPlxuICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgIDwvYnV0dG9uPlxuXG5cbiAgICAgICAgICA8YnV0dG9uIGNhcC1idG4tY2FsZW5kYXIgY2xhc3M9XCJjYXAtYnRuLWljb24gY2FwLWJ0bi1pY29uLXJhaXNlZFwiPlxuICAgICAgICAgICAgPHNwYW4+XG4gICAgICAgICAgICAgIDxzdmcgc3R5bGU9XCJ3aWR0aDoyNHB4O2hlaWdodDoyNHB4XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiPlxuICAgICAgICAgICAgICAgIDxwYXRoIGZpbGw9XCJjdXJyZW50Q29sb3JcIiBkPVwiTTE5LDE5SDVWOEgxOU0xNiwxVjNIOFYxSDZWM0g1QzMuODksMyAzLDMuODkgMyw1VjE5QTIsMiAwIDAsMCA1LDIxSDE5QTIsMiAwIDAsMCAyMSwxOVY1QzIxLDMuODkgMjAuMSwzIDE5LDNIMThWMU0xNywxMkgxMlYxN0gxN1YxMlpcIiAvPlxuICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibG9hZGluZy1pY29uXCI+XG4gICAgICAgICAgICAgICAgPHN2ZyB2ZXJzaW9uPVwiMS4xXCIgaWQ9XCJsb2FkZXItMVwiIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB4bWxuczp4bGluaz1cImh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmtcIiB4PVwiMHB4XCIgeT1cIjBweFwiXG4gICAgICAgICAgICAgICB3aWR0aD1cIjMycHhcIiBoZWlnaHQ9XCIzMnB4XCIgdmlld0JveD1cIjAgMCA0MCA0MFwiIGVuYWJsZS1iYWNrZ3JvdW5kPVwibmV3IDAgMCA0MCA0MFwiIHhtbDpzcGFjZT1cInByZXNlcnZlXCI+XG4gICAgICAgICAgICAgIDxwYXRoIG9wYWNpdHk9XCIwLjJcIiBmaWxsPVwiIzAwMFwiIGQ9XCJNMjAuMjAxLDUuMTY5Yy04LjI1NCwwLTE0Ljk0Niw2LjY5Mi0xNC45NDYsMTQuOTQ2YzAsOC4yNTUsNi42OTIsMTQuOTQ2LDE0Ljk0NiwxNC45NDZcbiAgICAgICAgICAgICAgICBzMTQuOTQ2LTYuNjkxLDE0Ljk0Ni0xNC45NDZDMzUuMTQ2LDExLjg2MSwyOC40NTUsNS4xNjksMjAuMjAxLDUuMTY5eiBNMjAuMjAxLDMxLjc0OWMtNi40MjUsMC0xMS42MzQtNS4yMDgtMTEuNjM0LTExLjYzNFxuICAgICAgICAgICAgICAgIGMwLTYuNDI1LDUuMjA5LTExLjYzNCwxMS42MzQtMTEuNjM0YzYuNDI1LDAsMTEuNjMzLDUuMjA5LDExLjYzMywxMS42MzRDMzEuODM0LDI2LjU0MSwyNi42MjYsMzEuNzQ5LDIwLjIwMSwzMS43NDl6XCIvPlxuICAgICAgICAgICAgICA8cGF0aCBmaWxsPVwiIzAwMFwiIGQ9XCJNMjYuMDEzLDEwLjA0N2wxLjY1NC0yLjg2NmMtMi4xOTgtMS4yNzItNC43NDMtMi4wMTItNy40NjYtMi4wMTJoMHYzLjMxMmgwXG4gICAgICAgICAgICAgICAgQzIyLjMyLDguNDgxLDI0LjMwMSw5LjA1NywyNi4wMTMsMTAuMDQ3elwiPlxuICAgICAgICAgICAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZVR5cGU9XCJ4bWxcIlxuICAgICAgICAgICAgICAgICAgYXR0cmlidXRlTmFtZT1cInRyYW5zZm9ybVwiXG4gICAgICAgICAgICAgICAgICB0eXBlPVwicm90YXRlXCJcbiAgICAgICAgICAgICAgICAgIGZyb209XCIwIDIwIDIwXCJcbiAgICAgICAgICAgICAgICAgIHRvPVwiMzYwIDIwIDIwXCJcbiAgICAgICAgICAgICAgICAgIGR1cj1cIjEuNXNcIlxuICAgICAgICAgICAgICAgICAgcmVwZWF0Q291bnQ9XCJpbmRlZmluaXRlXCIvPlxuICAgICAgICAgICAgICAgIDwvcGF0aD5cbiAgICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICA8L2J1dHRvbj5cblxuICAgICAgICAgIDxidXR0b24gY2FwLWJ0bi1uZXh0IGNsYXNzPVwiY2FwLWJ0bi1pY29uIGNhcC1idG4taWNvbi1yYWlzZWRcIj5cbiAgICAgICAgICAgIDxzcGFuPlxuICAgICAgICAgICAgICA8c3ZnIHN0eWxlPVwid2lkdGg6MjRweDtoZWlnaHQ6MjRweFwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIj5cbiAgICAgICAgICAgICAgICAgIDxwYXRoIGZpbGw9XCJjdXJyZW50Q29sb3JcIiBkPVwiTTQsMTBWMTRIMTNMOS41LDE3LjVMMTEuOTIsMTkuOTJMMTkuODQsMTJMMTEuOTIsNC4wOEw5LjUsNi41TDEzLDEwSDRaXCIgLz5cbiAgICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImxvYWRpbmctaWNvblwiPlxuICAgICAgICAgICAgICAgIDxzdmcgdmVyc2lvbj1cIjEuMVwiIGlkPVwibG9hZGVyLTFcIiB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgeG1sbnM6eGxpbms9XCJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rXCIgeD1cIjBweFwiIHk9XCIwcHhcIlxuICAgICAgICAgICAgICAgd2lkdGg9XCIzMnB4XCIgaGVpZ2h0PVwiMzJweFwiIHZpZXdCb3g9XCIwIDAgNDAgNDBcIiBlbmFibGUtYmFja2dyb3VuZD1cIm5ldyAwIDAgNDAgNDBcIiB4bWw6c3BhY2U9XCJwcmVzZXJ2ZVwiPlxuICAgICAgICAgICAgICA8cGF0aCBvcGFjaXR5PVwiMC4yXCIgZmlsbD1cIiMwMDBcIiBkPVwiTTIwLjIwMSw1LjE2OWMtOC4yNTQsMC0xNC45NDYsNi42OTItMTQuOTQ2LDE0Ljk0NmMwLDguMjU1LDYuNjkyLDE0Ljk0NiwxNC45NDYsMTQuOTQ2XG4gICAgICAgICAgICAgICAgczE0Ljk0Ni02LjY5MSwxNC45NDYtMTQuOTQ2QzM1LjE0NiwxMS44NjEsMjguNDU1LDUuMTY5LDIwLjIwMSw1LjE2OXogTTIwLjIwMSwzMS43NDljLTYuNDI1LDAtMTEuNjM0LTUuMjA4LTExLjYzNC0xMS42MzRcbiAgICAgICAgICAgICAgICBjMC02LjQyNSw1LjIwOS0xMS42MzQsMTEuNjM0LTExLjYzNGM2LjQyNSwwLDExLjYzMyw1LjIwOSwxMS42MzMsMTEuNjM0QzMxLjgzNCwyNi41NDEsMjYuNjI2LDMxLjc0OSwyMC4yMDEsMzEuNzQ5elwiLz5cbiAgICAgICAgICAgICAgPHBhdGggZmlsbD1cIiMwMDBcIiBkPVwiTTI2LjAxMywxMC4wNDdsMS42NTQtMi44NjZjLTIuMTk4LTEuMjcyLTQuNzQzLTIuMDEyLTcuNDY2LTIuMDEyaDB2My4zMTJoMFxuICAgICAgICAgICAgICAgIEMyMi4zMiw4LjQ4MSwyNC4zMDEsOS4wNTcsMjYuMDEzLDEwLjA0N3pcIj5cbiAgICAgICAgICAgICAgICA8YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVUeXBlPVwieG1sXCJcbiAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZU5hbWU9XCJ0cmFuc2Zvcm1cIlxuICAgICAgICAgICAgICAgICAgdHlwZT1cInJvdGF0ZVwiXG4gICAgICAgICAgICAgICAgICBmcm9tPVwiMCAyMCAyMFwiXG4gICAgICAgICAgICAgICAgICB0bz1cIjM2MCAyMCAyMFwiXG4gICAgICAgICAgICAgICAgICBkdXI9XCIxLjVzXCJcbiAgICAgICAgICAgICAgICAgIHJlcGVhdENvdW50PVwiaW5kZWZpbml0ZVwiLz5cbiAgICAgICAgICAgICAgICA8L3BhdGg+XG4gICAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgPC9idXR0b24+XG5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwic3BhY2VyXCI+PC9kaXY+XG5cbiAgICAgICAgICA8YnV0dG9uIHRvZ2dsZS1kYXJrIGNsYXNzPVwiY2FwLWJ0bi1pY29uIGNhcC1idG4taGVhZGVyIGMtZC1tb2JpbGUtbm9uZSAke1xuICAgICAgICAgICAgY29uZmlnLnRpbWVsaW5lLndpdGhEYXJrVG9nZ2xlID09IGZhbHNlID8gXCJoaWRlXCIgOiBcIlwiXG4gICAgICAgICAgfVwiPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJoaWRlLWxpZ2h0XCI+XG4gICAgICAgICAgICAgIDxzdmcgd2lkdGg9XCIyNFwiIGhlaWdodD1cIjI0XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiPlxuICAgICAgICAgICAgICAgIDxwYXRoICBmaWxsPVwiY3VycmVudENvbG9yXCIgZD1cIk0xMyw0LjhDOSw0LjggOSwxOS4yIDEzLDE5LjJDMTcsMTkuMiAyMiwxNi41IDIyLDEyQzIyLDcuNSAxNyw0LjggMTMsNC44TTEzLjEsMTcuMkMxMi43LDE2LjggMTIsMTUgMTIsMTJDMTIsOSAxMi43LDcuMiAxMy4xLDYuOEMxNiw2LjkgMjAsOC43IDIwLDEyQzIwLDE1LjMgMTUuOSwxNy4xIDEzLjEsMTcuMk04LDEwLjVDOCwxMSA3LjksMTEuNSA3LjksMTJDNy45LDEyLjIgNy45LDEyLjQgNy45LDEyLjZMMi40LDE0TDEuOSwxMi4xTDgsMTAuNU0yLDdMOS40LDUuMUM5LjIsNS40IDksNS44IDguOSw2LjNDOC44LDYuNiA4LjcsNyA4LjYsNy40TDIuNSw4LjlMMiw3TTguMiwxNS41QzguMywxNi4yIDguNSwxNi45IDguNywxNy40TDIuNCwxOUwxLjksMTcuMUw4LjIsMTUuNVpcIiAvPlxuICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiaGlkZS1kYXJrXCI+XG4gICAgICAgICAgICAgIDxzdmcgd2lkdGg9XCIyNFwiIGhlaWdodD1cIjI0XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiPlxuICAgICAgICAgICAgICAgIDxwYXRoICBmaWxsPVwiY3VycmVudENvbG9yXCIgZD1cIk0xMyw0LjhDOSw0LjggOSwxOS4yIDEzLDE5LjJDMTcsMTkuMiAyMiwxNi41IDIyLDEyQzIyLDcuNSAxNyw0LjggMTMsNC44TTEzLjEsMTcuMkMxMi43LDE2LjggMTIsMTUgMTIsMTJDMTIsOSAxMi43LDcuMiAxMy4xLDYuOEMxNiw2LjkgMjAsOC43IDIwLDEyQzIwLDE1LjMgMTYsMTcuMSAxMy4xLDE3LjJNMiw1SDkuNUM5LjMsNS40IDksNS44IDguOSw2LjRDOC44LDYuNiA4LjgsNi44IDguNyw3SDJWNU04LDExSDJWOUg4LjJDOC4xLDkuNiA4LjEsMTAuMyA4LDExTTguNywxN0M4LjksMTcuOCA5LjIsMTguNCA5LjYsMTlIMi4xVjE3SDguN004LjIsMTVIMlYxM0g4QzguMSwxMy43IDguMSwxNC40IDguMiwxNVpcIiAvPlxuICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICA8L2J1dHRvbj5gO1xuXG4gICAgaWYgKGNvbmZpZy50aW1lbGluZS5oZWFkZXIuZXh0ZW5kLmVuYWJsZWQgIT09IGZhbHNlKSB7XG4gICAgICBzdHIgKz0gYDxidXR0b24gdG9nZ2xlLWhlYWRlciBjbGFzcz1cImNhcC1idG4taWNvbiBjYXAtYnRuLWljb24tcmFpc2VkXCI+XG4gICAgICAgICAgICA8c3Bhbj5cbiAgICAgICAgICAgICAgPHN2ZyBzdHlsZT1cIndpZHRoOjI0cHg7aGVpZ2h0OjI0cHhcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgICAgICAgICAgICAgICA8cGF0aCBmaWxsPVwiY3VycmVudENvbG9yXCIgZD1cIk03LjQxLDguNThMMTIsMTMuMTdMMTYuNTksOC41OEwxOCwxMEwxMiwxNkw2LDEwTDcuNDEsOC41OFpcIiAvPlxuICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICA8L2J1dHRvbj5gO1xuICAgIH1cblxuICAgIHN0ciArPSBgIDxkaXYgY2xhc3M9XCJidXR0b24tcmlnaHQtY29udGFpbmVyXCI+PC9kaXY+XG4gICAgICAgIDwvZGl2PmA7XG4gICAgLypcbiAgICAgICAgICBgXG4gICAgICAgICAgPGJ1dHRvbiB0b2dnbGUtc2lkZWJhci1yaWdodCBjbGFzcz1cImNhcC1idG4taWNvbiBjYXAtYnRuLWljb24tcmFpc2VkXCI+XG4gICAgICAgICAgICA8c3Bhbj5cbiAgICAgICAgICAgICAgPHN2ZyBzdHlsZT1cIndpZHRoOjI0cHg7aGVpZ2h0OjI0cHhcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgICAgICAgICAgICAgICA8cGF0aCBmaWxsPVwiY3VycmVudENvbG9yXCIgZD1cIk0xNS40MSwxNi41OEwxMC44MywxMkwxNS40MSw3LjQxTDE0LDZMOCwxMkwxNCwxOEwxNS40MSwxNi41OFpcIiAvPlxuICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICA8L2J1dHRvbj5cblxuICAgICAgPC9kaXY+XG4gICAgYDtcbiAgICAqL1xuXG4gICAgbGV0ICRyID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChzdHIpO1xuICAgICRlbGVtLnJlcGxhY2VXaXRoKCRyKTtcblxuICAgIGlmIChjb25maWcudGltZWxpbmUuaGVhZGVyLnJpZ2h0QnV0dG9ucykge1xuICAgICAgbGV0ICRidXR0b25Db250YWluZXIgPSAkci5xdWVyeVNlbGVjdG9yKFwiLmJ1dHRvbi1yaWdodC1jb250YWluZXJcIik7XG4gICAgICBjb25maWcudGltZWxpbmUuaGVhZGVyLnJpZ2h0QnV0dG9ucy5mb3JFYWNoKChidXR0b24pID0+IHtcbiAgICAgICAgbGV0IGhhc0JhZGdlID0gZmFsc2U7XG4gICAgICAgIGlmIChidXR0b24uaGFzQmFkZ2UpIHtcbiAgICAgICAgICBoYXNCYWRnZSA9IGJ1dHRvbi5oYXNCYWRnZSgpO1xuICAgICAgICB9XG4gICAgICAgIGxldCBzdHIgPSBgPGJ1dHRvbiBjbGFzcz1cImNhcC1idG4taWNvbiBjYXAtYnRuLWljb24tcmFpc2VkICR7XG4gICAgICAgICAgaGFzQmFkZ2UgPyBcImNhcC1idG4taGFzLWJhZGdlXCIgOiBcIlwiXG4gICAgICAgIH1cIj5cbiAgICAgICAgICAgIDxzcGFuPlxuICAgICAgICAgICAgICA8c3ZnIHN0eWxlPVwid2lkdGg6MjRweDtoZWlnaHQ6MjRweFwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIj5cbiAgICAgICAgICAgICAgICAgIDxwYXRoIGZpbGw9XCJjdXJyZW50Q29sb3JcIiBkPVwiJHtidXR0b24uaWNvbn1cIiAvPlxuICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICA8L2J1dHRvbj5gO1xuICAgICAgICBsZXQgJGJ1dHRvbiA9IGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoc3RyKTtcbiAgICAgICAgJGJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGV2dCkgPT4gYnV0dG9uLm9uQ2xpY2soeyBldnQgfSkpO1xuICAgICAgICAkYnV0dG9uQ29udGFpbmVyLmFwcGVuZCgkYnV0dG9uKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGxldCAkdG9nZ2xlRGFyayA9ICRyLnF1ZXJ5U2VsZWN0b3IoXCJbdG9nZ2xlLWRhcmtdXCIpO1xuICAgIGlmICgkdG9nZ2xlRGFyaykge1xuICAgICAgJHRvZ2dsZURhcmsuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIChlKSA9PiB7XG4gICAgICAgICRyLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwidG9nZ2xlRGFya1wiLCB7XG4gICAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGxldCAkYnRuQ2FsZW5kYXIgPSAkci5xdWVyeVNlbGVjdG9yKFwiW2NhcC1idG4tY2FsZW5kYXJdXCIpO1xuICAgIGlmICgkYnRuQ2FsZW5kYXIpIHtcbiAgICAgICRidG5DYWxlbmRhci5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGUpID0+IHtcbiAgICAgICAgbGV0IHggPSBlLng7XG4gICAgICAgIGxldCB5ID0gZS55O1xuICAgICAgICAkci5kaXNwYXRjaEV2ZW50KFxuICAgICAgICAgIG5ldyBDdXN0b21FdmVudChcImNsaWNrQ2FsZW5kYXJJY29uXCIsIHtcbiAgICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIGRldGFpbDogeyB4LCB5IH0sXG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGxldCAkYnRuVG9nZ2xlSGVhZGVyID0gJHIucXVlcnlTZWxlY3RvcihcIlt0b2dnbGUtaGVhZGVyXVwiKTtcbiAgICBpZiAoJGJ0blRvZ2dsZUhlYWRlcikge1xuICAgICAgJGJ0blRvZ2dsZUhlYWRlci5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGUpID0+IHtcbiAgICAgICAgJHIuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICBuZXcgQ3VzdG9tRXZlbnQoXCJ0b2dnbGVIZWFkZXJcIiwge1xuICAgICAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgICAgIGNhbmNlbGFibGU6IGZhbHNlLFxuICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKlxuICAgICRyLnF1ZXJ5U2VsZWN0b3IoXCJbdG9nZ2xlLXNpZGViYXItcmlnaHRdXCIpLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBlID0+IHtcbiAgICAgICRyLmRpc3BhdGNoRXZlbnQobmV3IEN1c3RvbUV2ZW50KFwidG9nZ2xlU2lkZWJhclJpZ2h0XCIsIHtcbiAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICB9KSk7XG4gICAgfSk7XG4gICAgKi9cblxuICAgICRyLnF1ZXJ5U2VsZWN0b3IoXCJbY2FwLWJ0bi1wcmV2XVwiKS5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGUpID0+IHtcbiAgICAgICRyLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgIG5ldyBDdXN0b21FdmVudChcImhlYWRlclByZXZcIiwge1xuICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICAgICAgZGV0YWlsOiB7XG4gICAgICAgICAgICBvcmlnaW5hbEV2dDogZSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgICRyLnF1ZXJ5U2VsZWN0b3IoXCJbY2FwLWJ0bi1jYWxlbmRhcl1cIikuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIChlKSA9PiB7XG4gICAgICAkci5kaXNwYXRjaEV2ZW50KFxuICAgICAgICBuZXcgQ3VzdG9tRXZlbnQoXCJoZWFkZXJDYWxlbmRhclwiLCB7XG4gICAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICBkZXRhaWw6IHtcbiAgICAgICAgICAgIG9yaWdpbmFsRXZ0OiBlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgJHIucXVlcnlTZWxlY3RvcihcIltjYXAtYnRuLW5leHRdXCIpLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCAoZSkgPT4ge1xuICAgICAgJHIuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwiaGVhZGVyTmV4dFwiLCB7XG4gICAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICBkZXRhaWw6IHtcbiAgICAgICAgICAgIG9yaWdpbmFsRXZ0OiBlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgbGV0ICR0b2dnbGVMZWdlbmRzQnRuID0gJHIucXVlcnlTZWxlY3RvcihcIlt0b2dnbGUtbGVnZW5kc11cIik7XG4gICAgaWYgKCR0b2dnbGVMZWdlbmRzQnRuKSB7XG4gICAgICAkdG9nZ2xlTGVnZW5kc0J0bi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGUpID0+IHtcbiAgICAgICAgbGV0ICRsZWdlbmRDb250YWluZXIgPSAkci5xdWVyeVNlbGVjdG9yKFwiLmxlZ2VuZHMtY29udGFpbmVyXCIpO1xuICAgICAgICBpZiAoJGxlZ2VuZENvbnRhaW5lcikge1xuICAgICAgICAgICRsZWdlbmRDb250YWluZXIuY2xhc3NMaXN0LnRvZ2dsZShcImhpZGVcIik7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgICRyLnF1ZXJ5U2VsZWN0b3JBbGwoXCIubGVnZW5kXCIpLmZvckVhY2goKCRsZWdlbmQpID0+IHtcbiAgICAgICRsZWdlbmQuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIChlKSA9PiB7XG4gICAgICAgIGxldCBrZXkgPSBlLmN1cnJlbnRUYXJnZXQuZ2V0QXR0cmlidXRlKFwiaW5wdXQta2V5XCIpO1xuXG4gICAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgICBsZXQgbGVnZW5kU2VsZWN0ZWQgPSB0YWJTZWxlY3RlZC5sZWdlbmRzLmZpbmQoXG4gICAgICAgICAgICAodGFiKSA9PiB0YWIua2V5ID09PSBrZXlcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmIChsZWdlbmRTZWxlY3RlZCkge1xuICAgICAgICAgICAgJHIuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwic2VsZWN0TGVnZW5kSGVhZGVyXCIsIHtcbiAgICAgICAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNhbmNlbGFibGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGRldGFpbDoge1xuICAgICAgICAgICAgICAgICAgbGVnZW5kOiBsZWdlbmRTZWxlY3RlZCxcbiAgICAgICAgICAgICAgICAgICRsZWdlbmQsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgICRyLnF1ZXJ5U2VsZWN0b3JBbGwoXCIudGFiOm5vdCguZGlzYWJsZWQpXCIpLmZvckVhY2goKCR0YWIpID0+IHtcbiAgICAgICR0YWIuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIChlKSA9PiB7XG4gICAgICAgIGxldCBrZXkgPSBlLmN1cnJlbnRUYXJnZXQuZ2V0QXR0cmlidXRlKFwiaW5wdXQta2V5XCIpO1xuXG4gICAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgICBsZXQgdGFiU2VsZWN0ZWQgPSBjb25maWcudGltZWxpbmUudGFicy5maW5kKCh0YWIpID0+IHRhYi5pZCA9PSBrZXkpO1xuICAgICAgICAgIGlmICh0YWJTZWxlY3RlZCkge1xuICAgICAgICAgICAgJHIuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwic2VsZWN0VGFiSGVhZGVyXCIsIHtcbiAgICAgICAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNhbmNlbGFibGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGRldGFpbDoge1xuICAgICAgICAgICAgICAgICAgdGFiOiB0YWJTZWxlY3RlZCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgJHIucXVlcnlTZWxlY3RvckFsbChcIi50YWJzLXNlbGVjdDpub3QoLmRpc2FibGVkKVwiKS5mb3JFYWNoKCgkdGFiKSA9PiB7XG4gICAgICAkdGFiLmFkZEV2ZW50TGlzdGVuZXIoXCJjaGFuZ2VcIiwgKGUpID0+IHtcbiAgICAgICAgbGV0IGtleSA9IHBhcnNlRmxvYXQoZS5jdXJyZW50VGFyZ2V0LnZhbHVlKTtcblxuICAgICAgICBpZiAoa2V5KSB7XG4gICAgICAgICAgbGV0IHRhYlNlbGVjdGVkID0gY29uZmlnLnRpbWVsaW5lLnRhYnMuZmluZCgodGFiKSA9PiB0YWIuaWQgPT0ga2V5KTtcbiAgICAgICAgICBpZiAodGFiU2VsZWN0ZWQpIHtcbiAgICAgICAgICAgICRyLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgICAgIG5ldyBDdXN0b21FdmVudChcInNlbGVjdFRhYkhlYWRlclwiLCB7XG4gICAgICAgICAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBkZXRhaWw6IHtcbiAgICAgICAgICAgICAgICAgIHRhYjogdGFiU2VsZWN0ZWQsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHJldHVybiAkcjtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBIZWFkZXJcbiAgICogU2UgdXNhIHBhcmEgOlxuICAgKiAgICAtIE1vc3RyYXIgZmVjaGFzIGVuIGhlYWRlclxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbVxuICAgKi9cbiAgY3JlYXRlSGVhZGVyKGNvbmZpZykge1xuICAgIGxldCAkZWxlbSA9IGRvbS5jcmVhdGVFbGVtZW50KFwiaGVhZGVyXCIpO1xuICAgIHJldHVybiB0aGlzLnJlZHJhd0hlYWRlcihjb25maWcsICRlbGVtKTtcbiAgfSxcblxuICAvKipcbiAgICogUmVjcmVhIEhlYWRlciwgdXNhZG8gcGFyYSByZWRpYnVqYXJcbiAgICogdXRpbGl6YSAkZWxlbSBjb21vIGVsZW1lbnRvIGRvbSBkb25kZSByZWNyZWFybG9cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIENvbmZpZ3VyYWNpb24gY2FwaWJhcmFcbiAgICogQHBhcmFtIHtPYmplY3R9ICRlbGVtIC0gRWxlbWVudG8gRG9tIGRvbmRlIGNyZWEgSGVhZGVyXG4gICAqIEByZXR1cm4ge09iamVjdH0gRWxlbWVudG8gRG9tXG4gICAqL1xuICByZWRyYXdIZWFkZXIoY29uZmlnLCAkZWxlbSkge1xuICAgIGxldCBkYXRlc1RyZWUgPSBkYXRlVXRpbHMuZ2V0RGF0ZVRyZWVSYW5nZShcbiAgICAgIG5ldyBEYXRlKGNvbmZpZy50aW1lbGluZS5zdGFydCksXG4gICAgICBuZXcgRGF0ZShjb25maWcudGltZWxpbmUuZW5kKVxuICAgICk7XG5cbiAgICBsZXQgc3RyID0gYDxkaXYgY2xhc3M9XCJoZWFkZXItY29udGFpbmVyXCI+IGA7XG5cbiAgICBPYmplY3Qua2V5cyhkYXRlc1RyZWUpLmZvckVhY2goKGtleVkpID0+IHtcbiAgICAgIGxldCB5ZWFyID0gZGF0ZXNUcmVlW2tleVldO1xuICAgICAgc3RyICs9IGA8ZGl2IGNsYXNzPVwiYWduby1jYWxlbmRhcmlvXCI+XG4gICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYWdubyBoaWRlXCI+JHtrZXlZfTwvc3Bhbj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1lc2VzXCI+YDtcblxuICAgICAgT2JqZWN0LmtleXMoeWVhcikuZm9yRWFjaCgoa2V5TSkgPT4ge1xuICAgICAgICBsZXQgbW9udGggPSBkYXRlc1RyZWVba2V5WV1ba2V5TV07XG4gICAgICAgIHN0ciArPSBgIDxkaXYgY2xhc3M9XCJtZXMtY2FsZW5kYXJpb1wiPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWVzICR7XG4gICAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmtleXMobW9udGgpLmxlbmd0aCA8IDRcbiAgICAgICAgICAgICAgICAgICAgICAgID8gXCJtZXMtcmVkdWNlZCBtZXMtcmVkdWNlZC1cIiArIE9iamVjdC5rZXlzKG1vbnRoKS5sZW5ndGhcbiAgICAgICAgICAgICAgICAgICAgICAgIDogXCJcIlxuICAgICAgICAgICAgICAgICAgICB9XCI+XG4gICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1lcy1sYWJlbFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgJHt1dGlscy5nZXRNb250aEJ5UG9zaXRpb24oa2V5TSl9ICR7a2V5WX1cbiAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkaWFzXCI+YDtcbiAgICAgICAgT2JqZWN0LmtleXMobW9udGgpLmZvckVhY2goKGtleUQpID0+IHtcbiAgICAgICAgICBsZXQgZGF5ID0gZGF0ZXNUcmVlW2tleVldW2tleU1dW2tleURdO1xuICAgICAgICAgIGxldCBpc1dlZWtlbmQgPSBkYXkuaXNXZWVrZW5kO1xuICAgICAgICAgIGxldCBpc1RvZGF5ID0gZGF5LmlzVG9kYXk7XG4gICAgICAgICAgbGV0IGRhdGUgPSBkYXRlVXRpbHMuZm9ybWF0RGF0ZShkYXkuRGF0ZSk7XG4gICAgICAgICAgc3RyICs9IGA8ZGl2IGNsYXNzPVwiZGlhLWNhbGVuZGFyaW8gJHtpc1RvZGF5ID8gXCJ0b2RheVwiIDogXCJcIn0gICR7XG4gICAgICAgICAgICBpc1dlZWtlbmQgPyBcIndlZWtlbmRcIiA6IFwiXCJcbiAgICAgICAgICB9ICR7XG4gICAgICAgICAgICBjb25maWcudGltZWxpbmUuZGF0ZVNlbGVjdGFibGUgPyBcImlzLWNsaWNrZWFibGVcIiA6IFwiXCJcbiAgICAgICAgICB9XCIgZGF0ZT1cIiR7ZGF0ZX1cIj4ke2tleUR9PC9kaXY+YDtcbiAgICAgICAgfSk7XG4gICAgICAgIHN0ciArPSBgPC9kaXY+PC9kaXY+YDtcbiAgICAgIH0pO1xuICAgICAgc3RyICs9IGA8L2Rpdj4gPC9kaXY+YDtcbiAgICB9KTtcblxuICAgIHN0ciArPSBgPC9kaXY+YDtcbiAgICAkZWxlbS5pbm5lckhUTUwgPSBcIlwiO1xuICAgICRlbGVtLmFwcGVuZChkb20uY3JlYXRlRWxlbWVudEZyb21IVE1MKHN0cikpO1xuXG4gICAgaWYgKGNvbmZpZy50aW1lbGluZS5kYXRlU2VsZWN0YWJsZSkge1xuICAgICAgJGVsZW0ucXVlcnlTZWxlY3RvckFsbChcIi5kaWEtY2FsZW5kYXJpb1tkYXRlXVwiKS5mb3JFYWNoKCgkZGlhKSA9PiB7XG4gICAgICAgICRkaWEuYWRkRXZlbnRMaXN0ZW5lcihcImNvbnRleHRtZW51XCIsIChldnQpID0+IHtcbiAgICAgICAgICAkZWxlbS5kaXNwYXRjaEV2ZW50KFxuICAgICAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwiY29udGV4dE1lbnVEYXRlXCIsIHtcbiAgICAgICAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICAgICAgICAgIGRldGFpbDoge1xuICAgICAgICAgICAgICAgICRlbGVtOiAkZGlhLFxuICAgICAgICAgICAgICAgIGRhdGU6ICRkaWEuZ2V0QXR0cmlidXRlKFwiZGF0ZVwiKSxcbiAgICAgICAgICAgICAgICBjbGllbnRYOiBldnQuY2xpZW50WCxcbiAgICAgICAgICAgICAgICBjbGllbnRZOiBldnQuY2xpZW50WSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgJGRpYS5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGV2dCkgPT4ge1xuICAgICAgICAgICRlbGVtLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgICBuZXcgQ3VzdG9tRXZlbnQoXCJjbGlja0RhdGVcIiwge1xuICAgICAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgZGV0YWlsOiB7XG4gICAgICAgICAgICAgICAgJGVsZW06ICRkaWEsXG4gICAgICAgICAgICAgICAgZGF0ZTogJGRpYS5nZXRBdHRyaWJ1dGUoXCJkYXRlXCIpLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiAkZWxlbTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBIZWFkZXIgZXh0ZW5kZWRcbiAgICogU2UgdXNhIHBhcmEgOlxuICAgKiAgICAtTW9zdHJhciBpbnB1dHMgeSBkYXRvcyBwYXJhIGZlY2hhcyBlbiBoZWFkZXJcbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIENvbmZpZ3VyYWNpb24gY2FwaWJhcmFcbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gaGVhZGVyRXh0ZW5kZWRcbiAgICovXG4gIGNyZWF0ZUhlYWRlckV4dGVuZGVkKGNvbmZpZykge1xuICAgIGlmIChjb25maWcudGltZWxpbmUuaGVhZGVyLmV4dGVuZC5lbmFibGVkID09IGZhbHNlKSByZXR1cm4gbnVsbDtcblxuICAgIGxldCBkYXRlcyA9IGRhdGVVdGlscy5nZXREYXRlUmFuZ2UoXG4gICAgICBuZXcgRGF0ZShjb25maWcudGltZWxpbmUuc3RhcnQpLFxuICAgICAgbmV3IERhdGUoY29uZmlnLnRpbWVsaW5lLmVuZClcbiAgICApO1xuICAgIGxldCBzdHIgPSBgPGRpdiBjbGFzcz1cImhlYWRlci1jb250YWluZXItZXh0ZW5kZWRcIj5gO1xuXG4gICAgY29uZmlnLnRpbWVsaW5lLmhlYWRlci5leHRlbmQuZGF0YS5mb3JFYWNoKChkLCBkX2luZGV4KSA9PiB7XG4gICAgICBpZiAoZC5pc0hpZGRlbikgcmV0dXJuIFwiXCI7XG5cbiAgICAgIGxldCBpc1BlcnNpc3RlbnQgPSBkLmlzUGVyc2lzdGVudDtcbiAgICAgIHN0ciArPSBgPGRpdiBjbGFzcz1cImlucHV0LWxpc3QgJHtpc1BlcnNpc3RlbnQgPyBcInBlcnNpc3RlbnRcIiA6IFwiXCJ9XCI+YDtcbiAgICAgIHN0ciArPSBkYXRlc1xuICAgICAgICAubWFwKChkYXRlKSA9PiB7XG4gICAgICAgICAgbGV0IHZhbHVlID0gXCJcIjtcbiAgICAgICAgICBsZXQgaXNGdXR1cmUgPSBkYXRlVXRpbHMuaXNGdXR1cmUoZGF0ZSk7XG4gICAgICAgICAgbGV0IGlzVG9kYXkgPSBkYXRlVXRpbHMuaXNUb2RheShkYXRlKTtcblxuICAgICAgICAgIGlmIChkLmRhdGEpIHtcbiAgICAgICAgICAgIGxldCBkYXRhRm91bmRlZCA9IGQuZGF0YS5maW5kKChkYXRhSW5wdXQpID0+IHtcbiAgICAgICAgICAgICAgcmV0dXJuIGRhdGVVdGlscy5pc1NhbWVEYXRlKG5ldyBEYXRlKGRhdGFJbnB1dC5kYXRlKSwgZGF0ZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChkYXRhRm91bmRlZCkge1xuICAgICAgICAgICAgICB2YWx1ZSA9IGRhdGFGb3VuZGVkLnZhbHVlIHx8IFwiXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgZC5lZGl0YWJsZSA9PT0gZmFsc2UgfHxcbiAgICAgICAgICAgIChpc0Z1dHVyZSAmJiBkLmVkaXRhYmxlRnV0dXJlID09IGZhbHNlKSB8fFxuICAgICAgICAgICAgKGlzVG9kYXkgJiYgZC5lZGl0YWJsZVRvZGF5ID09IGZhbHNlKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuIGA8ZGl2PlxuICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGRhdGU9XCIke2RhdGV9XCIgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXg9XCIke2RfaW5kZXh9XCIgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCIke2RhdGUudmFyTmFtZX0gJHtcbiAgICAgICAgICAgICAgZC5jb2xvciA/IFwiYy1cIiArIGQuY29sb3IgKyBcIi0tdGV4dFwiIDogXCJcIlxuICAgICAgICAgICAgfVwiID4gXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHt2YWx1ZX0gXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGxldCBpc0Rpc2FibGVkID0gZmFsc2U7XG4gICAgICAgICAgaWYgKGNvbmZpZy50aW1lbGluZS5lZGl0YWJsZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGlzRGlzYWJsZWQgPSB0cnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBgPGRpdiBjbGFzcz1cImRpYS1pbnB1dFwiPlxuICAgICAgICAgICAgICAgICAgPGlucHV0IFxuICAgICAgICAgICAgICAgICAgZGF0ZT1cIiR7ZGF0ZX1cIiBcbiAgICAgICAgICAgICAgICAgIGluZGV4PVwiJHtkX2luZGV4fVwiIFxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJoZWFkZXItaW5wdXQgXG4gICAgICAgICAgICAgICAgICAke2RhdGUudmFyTmFtZX0gJHtkLmNvbG9yID8gXCJjLVwiICsgZC5jb2xvciArIFwiLS10ZXh0XCIgOiBcIlwifVwiIFxuICAgICAgICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXG4gICAgICAgICAgICAgICAgICAke2lzRGlzYWJsZWQgPyBcImRpc2FibGVkXCIgOiBcIlwifSBcbiAgICAgICAgICAgICAgICAgIHZhbHVlPVwiJHt2YWx1ZX1cIj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICB9KVxuICAgICAgICAuam9pbihcIlwiKTtcbiAgICAgIHN0ciArPSBgPC9kaXY+YDtcbiAgICB9KTtcblxuICAgIHN0ciArPSBgPC9kaXY+YDtcblxuICAgIGxldCByID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChzdHIpO1xuXG4gICAgci5xdWVyeVNlbGVjdG9yQWxsKFwiaW5wdXQuaGVhZGVyLWlucHV0XCIpLmZvckVhY2goKGlucHV0KSA9PiB7XG4gICAgICBpbnB1dC5hZGRFdmVudExpc3RlbmVyKFwiaW5wdXRcIiwgKGUpID0+IHtcbiAgICAgICAgbGV0IGRhdGUgPSBlLmN1cnJlbnRUYXJnZXQuZ2V0QXR0cmlidXRlKFwiZGF0ZVwiKTtcbiAgICAgICAgbGV0IGluZGV4ID0gZS5jdXJyZW50VGFyZ2V0LmdldEF0dHJpYnV0ZShcImluZGV4XCIpO1xuICAgICAgICBsZXQgdmFsdWUgPSBlLmN1cnJlbnRUYXJnZXQudmFsdWU7XG4gICAgICAgIGxldCB0eXBlRGF0YSA9IGNvbmZpZy50aW1lbGluZS5oZWFkZXIuZXh0ZW5kLmRhdGFbaW5kZXhdO1xuXG4gICAgICAgIC8vcmVmcmVzaCBjb25maWcgdmFsdWVcbiAgICAgICAgbGV0IGRhdGEgPSB0eXBlRGF0YS5kYXRhLmZpbmQoKGQpID0+XG4gICAgICAgICAgZGF0ZVV0aWxzLmlzU2FtZURhdGUobmV3IERhdGUoZC5kYXRlKSwgbmV3IERhdGUoZGF0ZSkpXG4gICAgICAgICk7XG4gICAgICAgIGRhdGEudmFsdWUgPSB2YWx1ZTtcblxuICAgICAgICByLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwiY2hhbmdlSW5wdXRIZWFkZXJcIiwge1xuICAgICAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgICAgIGNhbmNlbGFibGU6IGZhbHNlLFxuICAgICAgICAgICAgZGV0YWlsOiB7XG4gICAgICAgICAgICAgIGRhdGU6IGRhdGUsXG4gICAgICAgICAgICAgIHR5cGVEYXRhOiB0eXBlRGF0YSxcbiAgICAgICAgICAgICAgdmFsdWU6IHZhbHVlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gcjtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYXIgU2lkZWJhciBJenF1aWVyZG9cbiAgICogICAgLSBNYW5lamEgaXRlbXMgY29tbyBhcmJvbCBkZSAyIG5pdmVsZXMgKHBhcmVudCwgY2hpbGRyZW4pXG4gICAqICAgIC0gRWwgc2lkZWJhciBzZSBkaXZpZGUgZW4gbmF2TGlzdCAtIEluaXRpYWxOYXYgLSBleHRlbmRlZE5hdiAtIEJ0bk5hdlxuICAgKiAgICAtIFNlIGFncmVnYSBpdGVtRGV0YWlsLCBwYXJhIGRldGFsbGVzIGRlIGl0ZW1zXG4gICAqXG4gICAqXG4gICAqIFRPRE86IHBhcmEgZXZpdGFyIGluY3J1c3RhciBsYXMgaWRzIGVuIGxvcyBpbnB1dHMsIHNlIGRlYmVuIGNyZWFyXG4gICAqIGxvcyBub2RvcyB1bm8gcG9yIHVubyBjb21vIGVsZW1lbnRvIERPTSwgeSBhZ3JlZ2FybGVzIGxvcyBldmVudG9zIGRpcmVjdGFtZW50ZVxuICAgKiBhaG9yYSBzZSBoYWNlIHNlbGVjY2lvbmFuZG8gdG9kb3MgbG9zIGlucHV0cyBjb24gcXVlcnlTZWxlY3RvckFsbFxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBTaWRlYmFyIEl6cXVpZXJkb1xuICAgKi9cbiAgY3JlYXRlTmF2TGVmdChjb25maWcsIHRhYiA9IG51bGwpIHtcbiAgICBsZXQgJGVsZW0gPSBkb20uY3JlYXRlRWxlbWVudChcIm5hdlwiLCB7IGNsYXNzTmFtZTogXCJsZWZ0XCIgfSk7XG4gICAgcmV0dXJuIHRoaXMucmVkcmF3TmF2TGVmdCgkZWxlbSwgY29uZmlnLCB0YWIpO1xuICB9LFxuXG4gIC8qKlxuICAgKiBSZWNyZWEgU2lkZWJhciBpenF1aWVyZG8sIHVzYWRvIHBhcmEgcmVkaWJ1amFyXG4gICAqIFV0aWxpemEgJGVsZW0gY29tbyBlbGVtZW50byBkb20gZG9uZGUgcmVjcmVhcmxvXG4gICAqXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSAkZWxlbSAtIEVsZW1lbnRvIERvbSBkb25kZSBjcmVhIGVsIHNpZGViYXIgaXpxdWllcmRvXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBjb25maWcgLSBDb25maWd1cmFjaW9uIGNhcGliYXJhXG4gICAqIEByZXR1cm4ge09iamVjdH0gRWxlbWVudG8gRG9tIG5hdkxlZnRcbiAgICovXG5cbiAgcmVkcmF3TmF2TGVmdCgkZWxlbSwgY29uZmlnLCB0YWIgPSBudWxsKSB7XG4gICAgbGV0IG5hdkxpc3QgPSBcIlwiO1xuICAgIGxldCBpbml0aWFsTmF2TGlzdCA9IFwiXCI7XG4gICAgbGV0IGV4TmF2TGlzdCA9IFwiXCI7XG4gICAgbGV0IGJ0bk5hdkxpc3QgPSBcIlwiO1xuICAgIGxldCBpc0Rpc2FibGVkID0gZmFsc2U7XG4gICAgaWYgKGNvbmZpZy50aW1lbGluZS5lZGl0YWJsZSA9PT0gZmFsc2UpIHtcbiAgICAgIGlzRGlzYWJsZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIGNvbmZpZy5kYXRhLmZvckVhY2goKGQpID0+IHtcbiAgICAgIGlmIChkLmlzSGlkZGVuKSByZXR1cm47XG5cbiAgICAgIG5hdkxpc3QgKz0gYFxuICAgICAgIDxkaXYgY2xhc3M9XCJuYXYtaXRlbVwiPlxuXG5cbiAgICAgICAgPGRpdiBjbGFzcz1cIm5hdi1pdGVtLWNvbnRhaW5lciBwYXJlbnRcIj5gO1xuXG4gICAgICBpZiAoZC5jaGlsZHJlbikge1xuICAgICAgICBuYXZMaXN0ICs9IGA8YnV0dG9uIGNsYXNzPVwidHJlZS1pY29uICR7XG4gICAgICAgICAgZC5pc0Nsb3NlZCA/IFwiXCIgOiBcImNhcC1yb3RhdGVcIlxuICAgICAgICB9XCIgaXRlbS1pZD1cIiR7ZC5pZCB8fCAtMX1cIiB0eXBlLW5vZGU9XCIke2QudHlwZSB8fCBcIlwifVwiID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHN2ZyBzdHlsZT1cIndpZHRoOjI0cHg7aGVpZ2h0OjI0cHhcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGZpbGw9XCJjdXJyZW50Q29sb3JcIiBkPVwiTTcuNDEsOC41OEwxMiwxMy4xN0wxNi41OSw4LjU4TDE4LDEwTDEyLDE2TDYsMTBMNy40MSw4LjU4WlwiIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+YDtcbiAgICAgIH1cblxuICAgICAgbmF2TGlzdCArPSBgXG4gICAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tdGl0bGUgdHJ1bmNhdGUgZnVsbC13aWR0aCAke1xuICAgICAgICAgICAgICAgICAgICAgIGQuY2xpY2tlYWJsZSA/IFwiY2xpY2tlYWJsZVwiIDogXCJcIiB9XG4gICAgICAgICAgICAgICAgICAgICAgJHsgZC5uYXZPdmVyPyBcImhvdmVyYWJsZVwiIDogXCJcIlxuICAgICAgICAgIH0gXCIgaXRlbS1pZD1cIiR7ZC5pZCB8fCAtMX1cIiB0eXBlLW5vZGU9XCIke2QudHlwZSB8fCBcIlwifVwiID5cbiAgICAgICAgICAgICR7ZC5sYWJlbH1cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+YDtcblxuICAgICAgaWYgKGQuY2hpbGRyZW4pIHtcbiAgICAgICAgbmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjaGlsZHJlbi1pdGVtcyAke1xuICAgICAgICAgICAgICAgIGQuaXNDbG9zZWQgPyBcImhpZGVcIiA6IFwiXCJcbiAgICAgICAgICAgICAgfSBcIiBjaGlsZC1saXN0PVwiJHtkLmlkIHx8IC0xfVwiPmA7XG5cbiAgICAgICAgZC5jaGlsZHJlbi5mb3JFYWNoKChjKSA9PiB7XG4gICAgICAgICAgaWYgKGMuaXNIaWRkZW4pIHJldHVybjtcblxuICAgICAgICAgIG5hdkxpc3QgKz0gYFxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjaGlsZC1uYXYtaXRlbVwiPlxuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm5hdi1pdGVtLWNvbnRhaW5lclwiPlxuICAgICAgICAgICAgICAgICAgICBgO1xuXG4gICAgICAgICAgLypcbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJuYXYtaXRlbS1pY29uXCI+XG4gICAgICAgICAgICAgICAgICAgICAgPHN2ZyBzdHlsZT1cIndpZHRoOjI0cHg7aGVpZ2h0OjI0cHhcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGZpbGw9XCJjdXJyZW50Q29sb3JcIiBkPVwiTTE5LDE1TDEzLDIxTDExLjU4LDE5LjU4TDE1LjE3LDE2SDRWNEg2VjE0SDE1LjE3TDExLjU4LDEwLjQyTDEzLDlMMTksMTVaXCIgLz5cbiAgICAgICAgICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICovXG5cbiAgICAgICAgICBuYXZMaXN0ICs9IGBcbiAgICAgICAgICAgICAgICAgICAgJHtcbiAgICAgICAgICAgICAgICAgICAgICBjLmxpZ2h0XG4gICAgICAgICAgICAgICAgICAgICAgICA/ICc8c3BhbiBjbGFzcz1cImxpZ2h0ICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAoYy5saWdodCA/IGMubGlnaHQgKyBcIi1saWdodFwiIDogXCJcIikgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAnXCI+PC9zcGFuPidcbiAgICAgICAgICAgICAgICAgICAgICAgIDogXCJcIlxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tdGl0bGUgJHtcbiAgICAgICAgICAgICAgICAgICAgICBjLmNsaWNrZWFibGUgPyBcImNsaWNrZWFibGVcIiA6IFwiXCIgfVxuICAgICAgICAgICAgICAgICAgICAgICR7IGMubmF2T3Zlcj8gXCJob3ZlcmFibGVcIiA6IFwiXCJcbiAgICAgICAgICAgICAgICAgICAgfVwiIGl0ZW0taWQ9XCIke2MuaWQgfHwgLTF9XCIgdHlwZS1ub2RlPVwiJHtjLnR5cGUgfHwgXCJcIn1cIj5cbiAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidHJ1bmNhdGVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICR7Yy5sYWJlbH1cbiAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICB9KTtcblxuICAgICAgICBuYXZMaXN0ICs9IGBcbiAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgIH1cblxuICAgICAgbmF2TGlzdCArPSBgPC9kaXY+YDtcblxuICAgICAgLy9pbml0aWFsXG4gICAgICBpbml0aWFsTmF2TGlzdCArPSBgPGRpdiBjbGFzcz1cImluaXRpYWwtbmF2LWl0ZW0gcGFyZW50XCI+YDtcbiAgICAgIGlmIChkLndpdGhOYXYpIHtcbiAgICAgICAgY29uZmlnLnRpbWVsaW5lLm5hdi5sZWZ0LmluaXRpYWwudmFycy5mb3JFYWNoKCh2KSA9PiB7XG4gICAgICAgICAgbGV0IHZhbHVlID0gdXRpbHMuZ2V0VmFyQnlQYXRoKGQudmFsdWVzLCB2LnZhck5hbWUpXG5cbiAgICAgICAgICBpZiAodi5yb3VuZCAmJiAhaXNOYU4odmFsdWUpKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHV0aWxzLnJvdW5kKHZhbHVlLCB2LnJvdW5kKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHYuaW5wdXQpIHtcbiAgICAgICAgICAgIHN3aXRjaCAodi5pbnB1dCkge1xuICAgICAgICAgICAgICBjYXNlIFwiaG91clwiOlxuICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWUuc3BsaXQoXCI6XCIpO1xuICAgICAgICAgICAgICAgIGxldCBoaFZhbHVlID0gdmFsdWVbMF07XG4gICAgICAgICAgICAgICAgbGV0IG1tVmFsdWUgPSB2YWx1ZVsxXTtcbiAgICAgICAgICAgICAgICBpbml0aWFsTmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tY29sIGhhcy1pbnB1dFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImhvdXItaW5wdXRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC10eXBlPVwidGltZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heD1cIjIzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluPVwiMDBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1rZXk9XCIke3Yua2V5IHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS1pZD1cIiR7ZC5pZCB8fCAtMX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlLW5vZGU9XCIke2QudHlwZSB8fCBcIlwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPVwiJHtoaFZhbHVlfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7aXNEaXNhYmxlZCA/IFwiZGlzYWJsZWRcIiA6IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiaGhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4+Ojwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC10eXBlPVwidGltZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heD1cIjU5XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluPVwiMDBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1rZXk9XCIke3Yua2V5IHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS1pZD1cIiR7ZC5pZCB8fCAtMX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlLW5vZGU9XCIke2QudHlwZSB8fCBcIlwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPVwiJHttbVZhbHVlfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7aXNEaXNhYmxlZCA/IFwiZGlzYWJsZWRcIiA6IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwibW1cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PmA7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIGNhc2UgXCJ0ZXh0XCI6XG4gICAgICAgICAgICAgIGNhc2UgXCJudW1iZXJcIjpcbiAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBpbml0aWFsTmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tY29sIGhhcy1pbnB1dFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0ICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cIiR7di5pbnB1dCB8fCBcInRleHRcIn1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC10eXBlPVwiJHt2LmlucHV0IHx8IFwidGV4dFwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LWtleT1cIiR7di5rZXkgfHwgXCJcIn1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLWlkPVwiJHtkLmlkIHx8IC0xfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUtbm9kZT1cIiR7ZC50eXBlIHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHtpc0Rpc2FibGVkID8gXCJkaXNhYmxlZFwiIDogXCJcIn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9XCIke3ZhbHVlfVwiLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpbml0aWFsTmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpdGVtLWNvbFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7dmFsdWV9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PmA7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaW5pdGlhbE5hdkxpc3QgKz0gYFxuICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcblxuICAgICAgaWYgKGQuY2hpbGRyZW4pIHtcbiAgICAgICAgZC5jaGlsZHJlbi5mb3JFYWNoKChjKSA9PiB7XG4gICAgICAgICAgaWYgKGMuaXNIaWRkZW4pIHJldHVybjtcbiAgICAgICAgICBpbml0aWFsTmF2TGlzdCArPSBgPGRpdiBjbGFzcz1cImNoaWxkLWluaXRpYWwtbmF2LWl0ZW0gJHtcbiAgICAgICAgICAgIGQuaXNDbG9zZWQgPyBcImhpZGVcIiA6IFwiXCJcbiAgICAgICAgICB9XCIgY2hpbGQ9XCIke2QuaWQgfHwgLTF9XCI+YDtcblxuICAgICAgICAgIGlmKGMud2l0aE5hdiAhPT0gZmFsc2Upe1xuICAgICAgICAgICAgY29uZmlnLnRpbWVsaW5lLm5hdi5sZWZ0LmluaXRpYWwudmFycy5mb3JFYWNoKCh2KSA9PiB7XG4gICAgICAgICAgICAgIGlmICh2Lm9ubHlUYWIgJiYgdGFiICYmIHYub25seVRhYiAhPT0gdGFiLmtleSkgcmV0dXJuO1xuXG4gICAgICAgICAgICAgIGxldCB2YWx1ZSA9IHV0aWxzLmdldFZhckJ5UGF0aChjLnZhbHVlcywgdi52YXJOYW1lKVxuICAgICAgICAgICAgICBpZiAodi5yb3VuZCAmJiAhaXNOYU4odmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSB1dGlscy5yb3VuZCh2YWx1ZSwgdi5yb3VuZCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKHYuaW5wdXQpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHYuaW5wdXQpIHtcbiAgICAgICAgICAgICAgICAgIGNhc2UgXCJob3VyXCI6XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWUuc3BsaXQoXCI6XCIpO1xuICAgICAgICAgICAgICAgICAgICBsZXQgaGhWYWx1ZSA9IHZhbHVlWzBdO1xuICAgICAgICAgICAgICAgICAgICBsZXQgbW1WYWx1ZSA9IHZhbHVlWzFdO1xuICAgICAgICAgICAgICAgICAgICBpbml0aWFsTmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tY29sIGhhcy1pbnB1dFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImhvdXItaW5wdXRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC10eXBlPVwidGltZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heD1cIjIzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluPVwiMDBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1rZXk9XCIke3Yua2V5IHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS1pZD1cIiR7Yy5pZCB8fCAtMX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlLW5vZGU9XCIke2MudHlwZSB8fCBcIlwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPVwiJHtoaFZhbHVlfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7aXNEaXNhYmxlZCA/IFwiZGlzYWJsZWRcIiA6IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiaGhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4+Ojwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC10eXBlPVwidGltZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heD1cIjU5XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluPVwiMDBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1rZXk9XCIke3Yua2V5IHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS1pZD1cIiR7Yy5pZCB8fCAtMX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlLW5vZGU9XCIke2MudHlwZSB8fCBcIlwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPVwiJHttbVZhbHVlfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7aXNEaXNhYmxlZCA/IFwiZGlzYWJsZWRcIiA6IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwibW1cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PmA7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgY2FzZSBcInRleHRcIjpcbiAgICAgICAgICAgICAgICAgIGNhc2UgXCJudW1iZXJcIjpcbiAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGluaXRpYWxOYXZMaXN0ICs9IGBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaXRlbS1jb2wgaGFzLWlucHV0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cIiR7di5pbnB1dCB8fCBcInRleHRcIn1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC10eXBlPVwiJHt2LmlucHV0IHx8IFwidGV4dFwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LWtleT1cIiR7di5rZXkgfHwgXCJcIn1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLWlkPVwiJHtjLmlkIHx8IC0xfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUtbm9kZT1cIiR7Yy50eXBlIHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHtpc0Rpc2FibGVkID8gXCJkaXNhYmxlZFwiIDogXCJcIn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9XCIke3ZhbHVlfVwiLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpbml0aWFsTmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpdGVtLWNvbFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7dmFsdWV9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PmA7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIGluaXRpYWxOYXZMaXN0ICs9IGBcbiAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgLy9FeHRcbiAgICAgIGV4TmF2TGlzdCArPSBgPGRpdiBjbGFzcz1cImV4LW5hdi1pdGVtIHBhcmVudFwiPmA7XG4gICAgICBpZiAoZC53aXRoRXhOYXYpIHtcbiAgICAgICAgY29uZmlnLnRpbWVsaW5lLm5hdi5sZWZ0LmV4dGVuZC52YXJzLmZvckVhY2goKHYpID0+IHtcbiAgICAgICAgICBsZXQgdmFsdWUgPSB1dGlscy5nZXRWYXJCeVBhdGgoZC52YWx1ZXMsIHYudmFyTmFtZSlcbiAgICAgICAgICBpZiAodi5yb3VuZCAmJiAhaXNOYU4odmFsdWUpKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHV0aWxzLnJvdW5kKHZhbHVlLCB2LnJvdW5kKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHYuaW5wdXQpIHtcbiAgICAgICAgICAgIHN3aXRjaCAodi5pbnB1dCkge1xuICAgICAgICAgICAgICBjYXNlIFwiaG91clwiOlxuICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWUuc3BsaXQoXCI6XCIpO1xuICAgICAgICAgICAgICAgIGxldCBoaFZhbHVlID0gdmFsdWVbMF07XG4gICAgICAgICAgICAgICAgbGV0IG1tVmFsdWUgPSB2YWx1ZVsxXTtcbiAgICAgICAgICAgICAgICBleE5hdkxpc3QgKz0gYFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpdGVtLWNvbCBoYXMtaW5wdXRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJob3VyLWlucHV0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwibnVtYmVyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQtdHlwZT1cInRpbWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXg9XCIyM1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbj1cIjBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1rZXk9XCIke3Yua2V5IHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS1pZD1cIiR7ZC5pZCB8fCAtMX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlLW5vZGU9XCIke2QudHlwZSB8fCBcIlwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPVwiJHtoaFZhbHVlfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7aXNEaXNhYmxlZCA/IFwiZGlzYWJsZWRcIiA6IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiaGhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4+Ojwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC10eXBlPVwidGltZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heD1cIjU5XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluPVwiMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LWtleT1cIiR7di5rZXkgfHwgXCJcIn1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLWlkPVwiJHtkLmlkIHx8IC0xfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUtbm9kZT1cIiR7ZC50eXBlIHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9XCIke21tVmFsdWV9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHtpc0Rpc2FibGVkID8gXCJkaXNhYmxlZFwiIDogXCJcIn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJtbVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgY2FzZSBcInRleHRcIjpcbiAgICAgICAgICAgICAgY2FzZSBcIm51bWJlclwiOlxuICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGV4TmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tY29sIGhhcy1pbnB1dFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCIke3YuaW5wdXQgfHwgXCJ0ZXh0XCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQtdHlwZT1cIiR7di5pbnB1dCB8fCBcInRleHRcIn1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1rZXk9XCIke3Yua2V5IHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS1pZD1cIiR7ZC5pZCB8fCAtMX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlLW5vZGU9XCIke2QudHlwZSB8fCBcIlwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7aXNEaXNhYmxlZCA/IFwiZGlzYWJsZWRcIiA6IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPVwiJHt2YWx1ZX1cIi8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZXhOYXZMaXN0ICs9IGBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tY29sXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHt2YWx1ZX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBleE5hdkxpc3QgKz0gYFxuICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcblxuICAgICAgaWYgKGQuY2hpbGRyZW4pIHtcbiAgICAgICAgZC5jaGlsZHJlbi5mb3JFYWNoKChjKSA9PiB7XG4gICAgICAgICAgaWYgKGMuaXNIaWRkZW4pIHJldHVybjtcbiAgICAgICAgICBleE5hdkxpc3QgKz0gYDxkaXYgY2xhc3M9XCJjaGlsZC1leC1uYXYtaXRlbSAke1xuICAgICAgICAgICAgZC5pc0Nsb3NlZCA/IFwiaGlkZVwiIDogXCJcIlxuICAgICAgICAgIH1cIiBjaGlsZD1cIiR7ZC5pZCB8fCAtMX1cIj5gO1xuXG4gICAgICAgICAgaWYoYy53aXRoTmF2ICE9PSBmYWxzZSl7XG4gICAgICAgICAgICBjb25maWcudGltZWxpbmUubmF2LmxlZnQuZXh0ZW5kLnZhcnMuZm9yRWFjaCgodikgPT4ge1xuICAgICAgICAgICAgICBpZiAodi5vbmx5VGFiICYmIHRhYiAmJiB2Lm9ubHlUYWIgIT09IHRhYi5rZXkpIHJldHVybjtcblxuICAgICAgICAgICAgICBsZXQgdmFsdWUgPSB1dGlscy5nZXRWYXJCeVBhdGgoYy52YWx1ZXMsIHYudmFyTmFtZSlcbiAgICAgICAgICAgICAgaWYgKHYucm91bmQgJiYgIWlzTmFOKHZhbHVlKSkge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gdXRpbHMucm91bmQodmFsdWUsIHYucm91bmQpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKHYuaW5wdXQpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHYuaW5wdXQpIHtcbiAgICAgICAgICAgICAgICAgIGNhc2UgXCJob3VyXCI6XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWUgPyB2YWx1ZS5zcGxpdChcIjpcIikgOiBbMCwgMF07XG4gICAgICAgICAgICAgICAgICAgIGxldCBoaFZhbHVlID0gdmFsdWVbMF07XG4gICAgICAgICAgICAgICAgICAgIGxldCBtbVZhbHVlID0gdmFsdWVbMV07XG4gICAgICAgICAgICAgICAgICAgIGV4TmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tY29sIGhhcy1pbnB1dFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImhvdXItaW5wdXRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC10eXBlPVwidGltZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heD1cIjIzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluPVwiMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LWtleT1cIiR7di5rZXkgfHwgXCJcIn1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLWlkPVwiJHtjLmlkIHx8IC0xfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUtbm9kZT1cIiR7Yy50eXBlIHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9XCIke2hoVmFsdWV9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHtpc0Rpc2FibGVkID8gXCJkaXNhYmxlZFwiIDogXCJcIn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJoaFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3Bhbj46PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cIm51bWJlclwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LXR5cGU9XCJ0aW1lXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4PVwiNTlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW49XCIwXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQta2V5PVwiJHt2LmtleSB8fCBcIlwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW0taWQ9XCIke2MuaWQgfHwgLTF9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZS1ub2RlPVwiJHtjLnR5cGUgfHwgXCJcIn1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZT1cIiR7bW1WYWx1ZX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAke2lzRGlzYWJsZWQgPyBcImRpc2FibGVkXCIgOiBcIlwifVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cIm1tXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgIGNhc2UgXCJ0ZXh0XCI6XG4gICAgICAgICAgICAgICAgICBjYXNlIFwibnVtYmVyXCI6XG4gICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBleE5hdkxpc3QgKz0gYFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpdGVtLWNvbCBoYXMtaW5wdXRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCAgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCIke3YuaW5wdXQgfHwgXCJ0ZXh0XCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQtdHlwZT1cIiR7di5pbnB1dCB8fCBcInRleHRcIn1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1rZXk9XCIke3Yua2V5IHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS1pZD1cIiR7Yy5pZCB8fCAtMX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlLW5vZGU9XCIke2MudHlwZSB8fCBcIlwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7aXNEaXNhYmxlZCA/IFwiZGlzYWJsZWRcIiA6IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPVwiJHt2YWx1ZX1cIi8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZXhOYXZMaXN0ICs9IGBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tY29sXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHt2YWx1ZX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGV4TmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIC8vYnV0dG9uc1xuICAgICAgYnRuTmF2TGlzdCArPSBgPGRpdiBjbGFzcz1cImNhcC1idG4tbmF2LWl0ZW0gcGFyZW50XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY2FwLWJ0bi1uYXYtaXRlbS1jb250ZW50XCI+YDtcbiAgICAgIGlmIChcbiAgICAgICAgY29uZmlnLnRpbWVsaW5lLm5hdi5sZWZ0LmJ1dHRvbnMgJiZcbiAgICAgICAgY29uZmlnLnRpbWVsaW5lLm5hdi5sZWZ0LmJ1dHRvbnMudmFyc1xuICAgICAgKSB7XG4gICAgICAgIGNvbmZpZy50aW1lbGluZS5uYXYubGVmdC5idXR0b25zLnZhcnMuZm9yRWFjaCgoYnRuKSA9PiB7XG4gICAgICAgICAgaWYgKGQud2l0aEJ0bk5hdikge1xuICAgICAgICAgICAgbGV0IGJ0bkNvbnRlbnQgPSBcIlwiO1xuICAgICAgICAgICAgbGV0IGNsYXNzTmFtZSA9IGJ0bi5jbGFzc05hbWUgfHwgXCJcIjtcblxuICAgICAgICAgICAgaWYgKGJ0bi5pY29uKSB7XG4gICAgICAgICAgICAgIGJ0bkNvbnRlbnQgPSBidG4uaWNvbiA/IGJ0bi5pY29uIDogXCJcIjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGJ0bi5pY29uRm9ybWF0dGVyKSB7XG4gICAgICAgICAgICAgIGJ0bkNvbnRlbnQgPSBidG4uaWNvbkZvcm1hdHRlciA/IGJ0bi5pY29uRm9ybWF0dGVyKGQsIGJ0bikgOiBcIlwiO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoYnRuLnNoYXBlKSB7XG4gICAgICAgICAgICAgIGNsYXNzTmFtZSArPSBcIiBjYXAtYnRuLVwiICsgYnRuLnNoYXBlO1xuICAgICAgICAgICAgICBidG5Db250ZW50ICs9IGA8c3Bhbj4gJHtcbiAgICAgICAgICAgICAgICBidG4uZm9ybWF0dGVyID8gYnRuLmZvcm1hdHRlcihkLCBidG4pIDogXCJcIlxuICAgICAgICAgICAgICB9IDwvc3Bhbj4gYDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChidG4uYnRuQ2xhc3NOYW1lRm9ybWF0dGVyKSB7XG4gICAgICAgICAgICAgIGxldCBuZXdDbGFzc05hbWUgPSBidG4uYnRuQ2xhc3NOYW1lRm9ybWF0dGVyKGQsIGJ0bik7XG4gICAgICAgICAgICAgIGlmIChuZXdDbGFzc05hbWUpIHtcbiAgICAgICAgICAgICAgICBjbGFzc05hbWUgKz0gXCIgXCIgKyBuZXdDbGFzc05hbWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYnRuTmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJjYXAtYnRuLXNoYXBlICR7Y2xhc3NOYW1lfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQta2V5PVwiJHtidG4ua2V5IHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLWlkPVwiJHtkLmlkIHx8IC0xfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHtpc0Rpc2FibGVkID8gXCJkaXNhYmxlZFwiIDogXCJcIn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlLW5vZGU9XCIke2QudHlwZSB8fCBcIlwifVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7YnRuQ29udGVudH1cbiAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+YDtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgYnRuTmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PmA7XG5cbiAgICAgIGlmIChkLmNoaWxkcmVuKSB7XG4gICAgICAgIGQuY2hpbGRyZW4uZm9yRWFjaCgoYykgPT4ge1xuICAgICAgICAgIGlmIChjLmlzSGlkZGVuKSByZXR1cm47XG5cbiAgICAgICAgICAvL2J1dHRvbnNcbiAgICAgICAgICBidG5OYXZMaXN0ICs9IGA8ZGl2IGNsYXNzPVwiY2FwLWJ0bi1jaGlsZC1uYXYtaXRlbSBwYXJlbnQgJHtcbiAgICAgICAgICAgIGQuaXNDbG9zZWQgPyBcImhpZGVcIiA6IFwiXCJcbiAgICAgICAgICB9XCIgY2hpbGQ9XCIke2QuaWQgfHwgLTF9XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNhcC1idG4tbmF2LWl0ZW0tY29udGVudFwiPmA7XG5cbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBjb25maWcudGltZWxpbmUubmF2LmxlZnQuYnV0dG9ucyAmJlxuICAgICAgICAgICAgY29uZmlnLnRpbWVsaW5lLm5hdi5sZWZ0LmJ1dHRvbnMudmFyc1xuICAgICAgICAgICkge1xuICAgICAgICAgICAgY29uZmlnLnRpbWVsaW5lLm5hdi5sZWZ0LmJ1dHRvbnMudmFycy5mb3JFYWNoKChidG4pID0+IHtcbiAgICAgICAgICAgICAgaWYoYy53aXRoTmF2ICE9PSBmYWxzZSl7XG4gICAgICAgICAgICAgICAgbGV0IGJ0bkNvbnRlbnQgPSBcIlwiO1xuICAgICAgICAgICAgICAgIGxldCBjbGFzc05hbWUgPSBidG4uY2xhc3NOYW1lIHx8IFwiXCI7XG5cbiAgICAgICAgICAgICAgICBpZiAoYnRuLmljb24pIHtcbiAgICAgICAgICAgICAgICAgIGJ0bkNvbnRlbnQgPSBidG4uaWNvbiA/IGJ0bi5pY29uIDogXCJcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYnRuLmljb25Gb3JtYXR0ZXIpIHtcbiAgICAgICAgICAgICAgICAgIGJ0bkNvbnRlbnQgPSBidG4uaWNvbkZvcm1hdHRlciA/IGJ0bi5pY29uRm9ybWF0dGVyKGMsIGJ0bikgOiBcIlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChidG4uc2hhcGUpIHtcbiAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZSArPSBcIiBjYXAtYnRuLVwiICsgYnRuLnNoYXBlO1xuICAgICAgICAgICAgICAgICAgYnRuQ29udGVudCArPSBgPHNwYW4+ICR7XG4gICAgICAgICAgICAgICAgICAgIGJ0bi5mb3JtYXR0ZXIgPyBidG4uZm9ybWF0dGVyKGMsIGJ0bikgOiBcIlwiXG4gICAgICAgICAgICAgICAgICB9IDwvc3Bhbj4gYDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGJ0bi5idG5DbGFzc05hbWVGb3JtYXR0ZXIpIHtcbiAgICAgICAgICAgICAgICAgIGxldCBuZXdDbGFzc05hbWUgPSBidG4uYnRuQ2xhc3NOYW1lRm9ybWF0dGVyKGMsIGJ0bik7XG4gICAgICAgICAgICAgICAgICBpZiAobmV3Q2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZSArPSBcIiBcIiArIG5ld0NsYXNzTmFtZTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBidG5OYXZMaXN0ICs9IGBcbiAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiY2FwLWJ0bi1zaGFwZSAke2NsYXNzTmFtZX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQta2V5PVwiJHtidG4ua2V5IHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW0taWQ9XCIke2MuaWQgfHwgLTF9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7aXNEaXNhYmxlZCA/IFwiZGlzYWJsZWRcIiA6IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlLW5vZGU9XCIke2MudHlwZSB8fCBcIlwifVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHtidG5Db250ZW50fVxuICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPmA7XG5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYnRuTmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBsZXQgaXRlbURldGFpbCA9IGAgPGRpdiBjbGFzcz1cImRldGFpbC1uYXYtaXRlbSBoaWRlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICR7dGhpcy5nZXREZXRhaWxOYXZJdGVtQ29udGVudCgpfVxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcblxuICAgIGxldCBzdHIgPSBgPGRpdiBjbGFzcz1cIm5hdi1jb250YWluZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAke2l0ZW1EZXRhaWx9XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJuYXYtaXRlbS1saXN0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgJHtuYXZMaXN0fVxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImluaXRpYWwtbmF2LWxpc3RcIj5cbiAgICAgICAgICAgICAgICAgICAgICAke2luaXRpYWxOYXZMaXN0fVxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImV4dGVuZC1uYXYtbGlzdFwiPlxuICAgICAgICAgICAgICAgICAgICAgICR7ZXhOYXZMaXN0fVxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNhcC1idG4tbmF2LWxpc3RcIj5cbiAgICAgICAgICAgICAgICAgICAgICAke2J0bk5hdkxpc3R9XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcblxuICAgIGxldCBuYXZDb250YWluZXIgPSBkb20uY3JlYXRlRWxlbWVudEZyb21IVE1MKHN0cik7XG4gICAgJGVsZW0uaW5uZXJIVE1MID0gXCJcIjtcbiAgICAkZWxlbS5hcHBlbmQobmF2Q29udGFpbmVyKTtcblxuICAgIC8vZGV0YWxsZSBkZSBuYXYtaXRlbVxuICAgICRlbGVtLnF1ZXJ5U2VsZWN0b3JBbGwoXCIuaXRlbS10aXRsZS5ob3ZlcmFibGVcIikuZm9yRWFjaCgoaSkgPT4ge1xuICAgICAgaS5hZGRFdmVudExpc3RlbmVyKFwibW91c2VvdmVyXCIsIChlKSA9PiB7XG4gICAgICAgIGxldCBwb3MgPSB1dGlscy5ldmVudFRvUG9zaXRpb25OYXZMZWZ0KGNvbmZpZywgZSwgJGVsZW0pO1xuICAgICAgICBsZXQgaXRlbUlkID0gaS5nZXRBdHRyaWJ1dGUoXCJpdGVtLWlkXCIpO1xuICAgICAgICBsZXQgaXRlbSA9IHV0aWxzLmdldEl0ZW1CeUlkKGNvbmZpZywgaXRlbUlkKTtcbiAgICAgICAgbGV0IHR5cGVOb2RlID0gaS5nZXRBdHRyaWJ1dGUoXCJ0eXBlLW5vZGVcIik7XG4gICAgICAgIGkuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICBuZXcgQ3VzdG9tRXZlbnQoXCJvdmVyTmF2SXRlbVwiLCB7XG4gICAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICAgICAgICBkZXRhaWw6IHtcbiAgICAgICAgICAgICAgb3JpZ2luYWxFdnQ6IGUsXG4gICAgICAgICAgICAgIGl0ZW06IGl0ZW0sXG4gICAgICAgICAgICAgIHR5cGU6IHR5cGVOb2RlLFxuICAgICAgICAgICAgICBwb3M6IHBvcyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLy9vY3VsdGEgZGV0YWxsZSBkZSBuYXYtaXRlbSwgYWwgc2FsaXIgZGVsIG5hdi1pdGVtLWxpc3RcbiAgICAkZWxlbS5xdWVyeVNlbGVjdG9yQWxsKFwiLm5hdi1pdGVtLWxpc3RcIikuZm9yRWFjaCgoaSkgPT4ge1xuICAgICAgaS5hZGRFdmVudExpc3RlbmVyKFwibW91c2VsZWF2ZVwiLCAoZSkgPT4ge1xuICAgICAgICBpLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwibGVhdmVOYXZJdGVtXCIsIHtcbiAgICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvL29jdWx0YSBkZXRhbGxlIGRlIG5hdi1pdGVtLWxpc3QsIGFsIHNhbGlyIGRlIG5hdi1pdGVtXG4gICAgJGVsZW0ucXVlcnlTZWxlY3RvckFsbChcIi5pdGVtLXRpdGxlOm5vdCguaG92ZXJhYmxlKVwiKS5mb3JFYWNoKChpKSA9PiB7XG4gICAgICBpLmFkZEV2ZW50TGlzdGVuZXIoXCJtb3VzZW1vdmVcIiwgKGUpID0+IHtcbiAgICAgICAgaS5kaXNwYXRjaEV2ZW50KFxuICAgICAgICAgIG5ldyBDdXN0b21FdmVudChcImxlYXZlTmF2SXRlbVwiLCB7XG4gICAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgJGVsZW0ucXVlcnlTZWxlY3RvckFsbChcIi5pdGVtLXRpdGxlLmNsaWNrZWFibGVcIikuZm9yRWFjaCgoaSkgPT4ge1xuICAgICAgaS5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGUpID0+IHtcbiAgICAgICAgbGV0IGl0ZW1JZCA9IGkuZ2V0QXR0cmlidXRlKFwiaXRlbS1pZFwiKTtcbiAgICAgICAgbGV0IHR5cGVOb2RlID0gaS5nZXRBdHRyaWJ1dGUoXCJ0eXBlLW5vZGVcIik7XG4gICAgICAgIGxldCB2YWx1ZSA9IGkudmFsdWU7XG4gICAgICAgIGkuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICBuZXcgQ3VzdG9tRXZlbnQoXCJjbGlja05hdkxlZnRJdGVtXCIsIHtcbiAgICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIGRldGFpbDoge1xuICAgICAgICAgICAgICBpdGVtSWQ6IGl0ZW1JZCxcbiAgICAgICAgICAgICAgdHlwZTogdHlwZU5vZGUsXG4gICAgICAgICAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgJGVsZW0ucXVlcnlTZWxlY3RvckFsbChcImlucHV0XCIpLmZvckVhY2goKGkpID0+IHtcbiAgICAgIGkuYWRkRXZlbnRMaXN0ZW5lcihcImNoYW5nZVwiLCAoZSkgPT4ge1xuICAgICAgICBsZXQgaW5wdXRUeXBlID0gaS5nZXRBdHRyaWJ1dGUoXCJpbnB1dC10eXBlXCIpO1xuICAgICAgICBsZXQga2V5ID0gaS5nZXRBdHRyaWJ1dGUoXCJpbnB1dC1rZXlcIik7XG4gICAgICAgIGxldCBpdGVtSWQgPSBpLmdldEF0dHJpYnV0ZShcIml0ZW0taWRcIik7XG4gICAgICAgIGxldCB0eXBlTm9kZSA9IGkuZ2V0QXR0cmlidXRlKFwidHlwZS1ub2RlXCIpO1xuICAgICAgICBsZXQgaXRlbSA9IHV0aWxzLmdldEl0ZW1CeUlkKGNvbmZpZywgaXRlbUlkKTtcbiAgICAgICAgbGV0IHZhbHVlID0gaS52YWx1ZTtcbiAgICAgICAgaWYgKGlucHV0VHlwZSA9PSBcInRpbWVcIikge1xuICAgICAgICAgIGxldCBoaF9pbnB1dCA9IGkucGFyZW50RWxlbWVudC5xdWVyeVNlbGVjdG9yKFwiaW5wdXQuaGhcIikudmFsdWU7XG4gICAgICAgICAgbGV0IG1tX2lucHV0ID0gaS5wYXJlbnRFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoXCJpbnB1dC5tbVwiKS52YWx1ZTtcbiAgICAgICAgICBtbV9pbnB1dCA9IG1tX2lucHV0IDwgMTAgPyBcIjBcIiArIHBhcnNlRmxvYXQobW1faW5wdXQpIDogbW1faW5wdXQ7XG4gICAgICAgICAgaS5wYXJlbnRFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoXCJpbnB1dC5tbVwiKS52YWx1ZSA9IG1tX2lucHV0O1xuICAgICAgICAgIHZhbHVlID0gaGhfaW5wdXQgKyBcIjpcIiArIG1tX2lucHV0O1xuICAgICAgICB9XG4gICAgICAgIGkuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICBuZXcgQ3VzdG9tRXZlbnQoXCJzYXZlTmF2TGVmdElucHV0XCIsIHtcbiAgICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIGRldGFpbDoge1xuICAgICAgICAgICAgICBrZXk6IGtleSxcbiAgICAgICAgICAgICAgaXRlbUlkOiBpdGVtSWQsXG4gICAgICAgICAgICAgIGl0ZW06IGl0ZW0sXG4gICAgICAgICAgICAgIHR5cGU6IHR5cGVOb2RlLFxuICAgICAgICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICAgICAgICAgIHRhYlNlbGVjdGVkOiB0YWIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgICRlbGVtLnF1ZXJ5U2VsZWN0b3JBbGwoXCJidXR0b24uY2FwLWJ0bi1zaGFwZVwiKS5mb3JFYWNoKChpKSA9PiB7XG4gICAgICBpLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCAoZSkgPT4ge1xuICAgICAgICBsZXQga2V5ID0gaS5nZXRBdHRyaWJ1dGUoXCJpbnB1dC1rZXlcIik7XG4gICAgICAgIGxldCBpdGVtSWQgPSBpLmdldEF0dHJpYnV0ZShcIml0ZW0taWRcIik7XG4gICAgICAgIGxldCB0eXBlTm9kZSA9IGkuZ2V0QXR0cmlidXRlKFwidHlwZS1ub2RlXCIpO1xuICAgICAgICBpLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwiY2xpY2tOYXZMZWZ0QnV0dG9uXCIsIHtcbiAgICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIGRldGFpbDoge1xuICAgICAgICAgICAgICBrZXk6IGtleSxcbiAgICAgICAgICAgICAgaXRlbUlkOiBpdGVtSWQsXG4gICAgICAgICAgICAgIHR5cGU6IHR5cGVOb2RlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAkZWxlbS5xdWVyeVNlbGVjdG9yQWxsKFwiYnV0dG9uLnRyZWUtaWNvblwiKS5mb3JFYWNoKChpKSA9PiB7XG4gICAgICBpLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCAoZSkgPT4ge1xuICAgICAgICBsZXQgaXRlbUlkID0gaS5nZXRBdHRyaWJ1dGUoXCJpdGVtLWlkXCIpO1xuICAgICAgICBsZXQgdHlwZU5vZGUgPSBpLmdldEF0dHJpYnV0ZShcInR5cGUtbm9kZVwiKTtcbiAgICAgICAgbGV0IGRhdGFDb25maWcgPSBjb25maWcuZGF0YS5maW5kKChkKSA9PiBkLmlkID09IGl0ZW1JZCk7XG5cbiAgICAgICAgbGV0ICRuYXZJdGVtID0gZS5jdXJyZW50VGFyZ2V0LmNsb3Nlc3QoXCIubmF2LWl0ZW1cIik7XG4gICAgICAgIGxldCAkY2hpbGRyZW4gPSAkbmF2SXRlbS5xdWVyeVNlbGVjdG9yKFwiLmNoaWxkcmVuLWl0ZW1zXCIpO1xuICAgICAgICBsZXQgaXRlbXNUb0hpZGUgPSBlLmN1cnJlbnRUYXJnZXRcbiAgICAgICAgICAuY2xvc2VzdChcIm5hdi5sZWZ0XCIpXG4gICAgICAgICAgLnF1ZXJ5U2VsZWN0b3JBbGwoXG4gICAgICAgICAgICBcIltjaGlsZD0nXCIgKyBpdGVtSWQgKyBcIiddLCBbY2hpbGQtbGlzdD0nXCIgKyBpdGVtSWQgKyBcIiddXCJcbiAgICAgICAgICApO1xuXG4gICAgICAgIGlmICgkY2hpbGRyZW4pIHtcbiAgICAgICAgICBpZiAoJGNoaWxkcmVuLmNsYXNzTGlzdC5jb250YWlucyhcImhpZGVcIikpIHtcbiAgICAgICAgICAgIGUuY3VycmVudFRhcmdldC5jbGFzc0xpc3QuYWRkKFwiY2FwLXJvdGF0ZVwiKTtcbiAgICAgICAgICAgIGl0ZW1zVG9IaWRlLmZvckVhY2goKGkpID0+IGkuY2xhc3NMaXN0LnJlbW92ZShcImhpZGVcIikpO1xuICAgICAgICAgICAgZGF0YUNvbmZpZy5pc0Nsb3NlZCA9IGZhbHNlO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlLmN1cnJlbnRUYXJnZXQuY2xhc3NMaXN0LnJlbW92ZShcImNhcC1yb3RhdGVcIik7XG4gICAgICAgICAgICBpdGVtc1RvSGlkZS5mb3JFYWNoKChpKSA9PiBpLmNsYXNzTGlzdC5hZGQoXCJoaWRlXCIpKTtcbiAgICAgICAgICAgIGRhdGFDb25maWcuaXNDbG9zZWQgPSB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGkuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICBuZXcgQ3VzdG9tRXZlbnQoXCJjbGlja05hdkxlZnRUcmVlSWNvblwiLCB7XG4gICAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICAgICAgICBkZXRhaWw6IHtcbiAgICAgICAgICAgICAgaXRlbUlkOiBpdGVtSWQsXG4gICAgICAgICAgICAgIHR5cGU6IHR5cGVOb2RlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuXG4gICAgICAgIC8vZS5jdXJyZW50VGFyZ2V0LnBhcmVudFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gJGVsZW07XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWEgSHRtbCBjb21vIFN0cmluZywgcGFyYSBlbCBkZXRhbGxlIGRlIGl0ZW1zIGVuIGVsIFNpZGViYXIgSXpxdWllcmRvXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbaXRlbT17fV0gLSBDb25maWd1cmFjaW9uIGRlIGl0ZW1cbiAgICogQHJldHVybiB7U3RyaW5nfSBIdG1sIGRlIHZlbnRhbmEgZGUgZGV0YWxsZVxuICAgKi9cbiAgZ2V0RGV0YWlsTmF2SXRlbUNvbnRlbnQoaXRlbSA9IHt9KSB7XG4gICAgaWYgKGl0ZW0ubmF2T3ZlciA9PSB1bmRlZmluZWQpIGl0ZW0ubmF2T3ZlciA9IHt9O1xuXG4gICAgcmV0dXJuIGBcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImhlYWRlci1kZXRhaWxcIj5cbiAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGV0YWlsLXRpdGxlIHRydW5jYXRlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAke2l0ZW0ubGFiZWwgfHwgXCJcIn1cbiAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGV0YWlsLXN1YnRpdGxlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAke2l0ZW0ubmF2T3Zlci5zdWJ0aXRsZSB8fCBcIlwifVxuICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJoZWFkZXItY2hpcCAke1xuICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS5saWdodCA/IGl0ZW0ubGlnaHQgKyBcIi1saWdodFwiIDogXCJcIlxuICAgICAgICAgICAgICAgICAgICAgIH0gICR7aXRlbS5uYXZPdmVyLmNoaXAgPyBcIlwiIDogXCJoaWRlXCJ9XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAke2l0ZW0ubmF2T3Zlci5jaGlwIHx8IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkZXRhaWwtY29udGFpbmVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgJHtpdGVtLm5hdk92ZXIuY29udGVudCB8fCBcIlwifVxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICB9LFxuXG4gIC8qKlxuICAgKiBDcmVhIFNpZGViYXIgRGVyZWNob1xuICAgKiBVc2FkbyBwcmluY2lwYWxtZW50ZSBwYXJhIGZvcm11bGFyaW8gZGUgaW5ncmVzbyBkZSBkYXRvcyBwYXJhIGxvcyBkaWFzXG4gICAqIHNlbGVjY2lvbmFkb3NcbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIENvbmZpZ3VyYWNpb24gY2FwaWJhcmFcbiAgICogQHBhcmFtIHtPYmplY3R9IHRhYiAtIFRhYiBkZSByZWZlcmVuY2lhLCBwYXJhIGxhIGNyZWFjaW9uIGRlbCBmb3JtdWxhcmlvXG4gICAqIEByZXR1cm4ge09iamVjdH0ge2VsZW1lbnQsIGlucHV0c30sIGVsZW1lbnQgZXMgZWwgZWxlbWVudG8gRG9tIGRlbCBzaWRlYmFyLFxuICAgKiAgICAgICAgICAgICAgICAgIGlucHV0cyBlcyB1biBhcnJheSBkZSBlbGVtZW50b3MgRG9tIGRlIGNhZGEgaW5wdXQgY3JlYWRvXG4gICAqICAgICAgICAgICAgICAgICAgKG5vIHNvbiBlbGVtZW50b3MgaHRtbCBkZSB0aXBvIGlucHV0KVxuICAgKi9cbiAgY3JlYXRlTmF2UmlnaHQoY29uZmlnLCB0YWIgPSBudWxsKSB7XG4gICAgdmFyICRlbGVtID0gZG9tLmNyZWF0ZUVsZW1lbnQoXCJuYXZcIiwgeyBjbGFzc05hbWU6IFwicmlnaHRcIiB9KTtcbiAgICByZXR1cm4gdGhpcy5yZWRyYXdOYXZSaWdodChjb25maWcsICRlbGVtLCB0YWIsIFtdKTtcbiAgfSxcblxuICAvKipcbiAgICogUmVjcmVhIFNpZGViYXIgRGVyZWNob1xuICAgKiBVdGlsaXphICRlbGVtIGNvbW8gZWxlbWVudG8gZG9tIGRvbmRlIHJlY3JlYXJsb1xuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcGFyYW0ge09iamVjdH0gJGVsZW0gLSBFbGVtZW50byBEb20gZG9uZGUgY3JlYSBlbCBzaWRlYmFyIGRlcmVjaG9cbiAgICogQHBhcmFtIHtPYmplY3R9IHRhYiAtIFRhYiBkZSByZWZlcmVuY2lhLCBwYXJhIGxhIGNyZWFjaW9uIGRlbCBmb3JtdWxhcmlvXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhRGF5IC0gZGF0b3MgZGVsIGRpYSBzZWxlY2Npb25hbmRvLCBwYXJhIGF1dG9ycmVsbGVubyBkZSBmb3JtdWxhcmlvXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXlTZWxlY3RlZCAtIGRhdG9zIGRlbCBkaWEgc2VsZWNjaW9uYWRvXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBkYXlTZWxlY3RlZC5kYXRlIC0gZmVjaGEgZGVsIGRpYSBzZWxlY2Npb25hZG9cbiAgICogQHBhcmFtIHtPYmplY3R9IGRheVNlbGVjdGVkLml0ZW0gLSBJdGVtIGRlIFNpZGViYXIgcmVsYWNpb25hZG8gYWwgZGlhIHNlbGVjY2lvbmFkb1xuICAgKiBAcGFyYW0ge09iamVjdH0gZGF5U2VsZWN0ZWQucG9zIC0gcG9zaWNpb24gZGUgZGlhIHNlbGVjY2lvbmFkb1xuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBTaWRlYmFyIERlcmVjaG9cbiAgICovXG4gIHJlZHJhd05hdlJpZ2h0KFxuICAgIGNvbmZpZyxcbiAgICAkZWxlbSxcbiAgICBzZWxlY3RlZCA9IG51bGwsXG4gICAgdGFiID0gbnVsbCxcbiAgICBkYXRhRGF5ID0gbnVsbCxcbiAgICBkYXlTZWxlY3RlZCA9IG51bGxcbiAgKSB7XG4gICAgbGV0ICRuYXZSaWdodCA9ICRlbGVtOyAvL2RvbS5jcmVhdGVFbGVtZW50KFwibmF2XCIse2NsYXNzTmFtZTpcInJpZ2h0XCJ9KTtcbiAgICBsZXQgJGRpdkNvbnRhaW5lciA9IGRvbS5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtcbiAgICAgIGNsYXNzTmFtZTogXCJuYXYtaW5wdXQtY29udGFpbmVyXCIsXG4gICAgfSk7XG4gICAgbGV0ICRpbnB1dHMgPSBbXTtcbiAgICBsZXQgY2hlY2tib3hJbnB1dHMgPSBbXTtcbiAgICBsZXQgaW5wdXRzV2l0aFJlbG9hZCA9IFtdO1xuICAgIGxldCB0YWJTZWxlY3RlZCA9IHRhYjtcbiAgICBzZWxlY3RlZCA9IHNlbGVjdGVkIHx8IFtkYXlTZWxlY3RlZF07XG5cbiAgICBpZiAodGFiU2VsZWN0ZWQgJiYgdGFiU2VsZWN0ZWQuaW5wdXRzKSB7XG4gICAgICB0YWJTZWxlY3RlZC5pbnB1dHMuZm9yRWFjaCgoaSkgPT4ge1xuICAgICAgICBpZiAoaS5kaXNhYmxlZCkgcmV0dXJuO1xuXG4gICAgICAgIGxldCAkaW5wdXQgPSB0aGlzLmNyZWF0ZUlucHV0KGksIGRhdGFEYXksIGRheVNlbGVjdGVkLCBzZWxlY3RlZCk7XG4gICAgICAgIGlmICgkaW5wdXQpIHtcbiAgICAgICAgICAkZGl2Q29udGFpbmVyLmFwcGVuZENoaWxkKCRpbnB1dCk7XG4gICAgICAgICAgJGlucHV0cy5wdXNoKCRpbnB1dCk7XG5cbiAgICAgICAgICBpZiAoaS50eXBlID09IFwiY2hlY2tib3hcIikge1xuICAgICAgICAgICAgY2hlY2tib3hJbnB1dHMucHVzaCgkaW5wdXQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChpLnJlbG9hZE9uU2VsZWN0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIGlucHV0c1dpdGhSZWxvYWQucHVzaCh7ICRpbnB1dCwgY29uZmlnOiBpIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy9tYW5lam8gZGUgZXZlbnRvcyBwYXJhIGlucHV0cyBjb24gc2hvd0lmXG4gICAgaWYgKGNoZWNrYm94SW5wdXRzKSB7XG4gICAgICBjaGVja2JveElucHV0cy5mb3JFYWNoKCgkYykgPT4ge1xuICAgICAgICAvL29idGllbmUga2V5IGRlIGNoZWNrYm94XG4gICAgICAgIGxldCBrZXkgPSAkYy5nZXRBdHRyaWJ1dGUoXCJpbnB1dC1rZXlcIik7XG4gICAgICAgIGxldCBwcm9wcyA9IHRhYlNlbGVjdGVkLmlucHV0cy5maW5kKChpKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGkua2V5ID09IGtleTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgbGV0IGlzQ2hlY2tlZCA9IGZhbHNlO1xuICAgICAgICBpZiAoZGF0YURheSkge1xuICAgICAgICAgIGlzQ2hlY2tlZCA9IHV0aWxzLmdldFZhckJ5UGF0aChkYXRhRGF5LCBwcm9wcy52YXJOYW1lKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vb2J0aWVuZSBpbnB1dHMgcmVsYWNpb25hZG9zIGRlc2RlIGNvbmZpZyBwYXJhIG1vc3RyYXIvb2N1bHRhclxuICAgICAgICBsZXQgaW5wdXRzVG9IaWRlID0gdGFiU2VsZWN0ZWQuaW5wdXRzLmZpbHRlcigoaSkgPT4ge1xuICAgICAgICAgIHJldHVybiBpLnNob3dJZiAmJiBpLnNob3dJZiA9PSBrZXk7XG4gICAgICAgIH0pO1xuICAgICAgICBsZXQgaW5wdXRzVG9IaWRlS2V5cyA9IGlucHV0c1RvSGlkZS5tYXAoKGkpID0+IGkua2V5KTtcblxuICAgICAgICAvL29idGllbmUgaW5wdXRzIGRlbCBkb20sIGZpbHRyYW5kbyBjb24gaW5wdXRzVG9IaWRlXG4gICAgICAgIGxldCAkaW5wdXRzSGlkZGVuID0gJGlucHV0cy5maWx0ZXIoKCRpKSA9PiB7XG4gICAgICAgICAgbGV0IGlucHV0S2V5ID0gJGkuZ2V0QXR0cmlidXRlKFwiaW5wdXQta2V5XCIpO1xuICAgICAgICAgIHJldHVybiBpbnB1dHNUb0hpZGVLZXlzLmluZGV4T2YoaW5wdXRLZXkpID4gLTE7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vc2kgaGF5IGlucHV0cyxcbiAgICAgICAgaWYgKCRpbnB1dHNIaWRkZW4pIHtcbiAgICAgICAgICBpZiAoIWlzQ2hlY2tlZCkge1xuICAgICAgICAgICAgJGlucHV0c0hpZGRlbi5mb3JFYWNoKCgkaSkgPT4ge1xuICAgICAgICAgICAgICAkaS5jbGFzc0xpc3QuYWRkKFwiaGlkZVwiKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICAkYy5hZGRFdmVudExpc3RlbmVyKFwiaW5wdXRcIiwgKGUpID0+IHtcbiAgICAgICAgICAgICRpbnB1dHNIaWRkZW4uZm9yRWFjaCgoJGkpID0+IHtcbiAgICAgICAgICAgICAgbGV0IGZuID0gJGMucXVlcnlTZWxlY3RvcihcImlucHV0W3R5cGU9J2NoZWNrYm94J11cIikuY2hlY2tlZFxuICAgICAgICAgICAgICAgID8gXCJyZW1vdmVcIlxuICAgICAgICAgICAgICAgIDogXCJhZGRcIjtcbiAgICAgICAgICAgICAgJGkuY2xhc3NMaXN0W2ZuXShcImhpZGVcIik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgbGV0IHNhdmVDYW5jZWxCdG5zID0gdGhpcy5jcmVhdGVOYXZSaWdodGJ1dHRvbnMoKTtcbiAgICAkZGl2Q29udGFpbmVyLmFwcGVuZENoaWxkKHNhdmVDYW5jZWxCdG5zKTtcbiAgICAkbmF2UmlnaHQuaW5uZXJIVE1MID0gXCJcIjtcbiAgICAkbmF2UmlnaHQuYXBwZW5kQ2hpbGQoJGRpdkNvbnRhaW5lcik7XG5cbiAgICByZXR1cm4ge1xuICAgICAgZWxlbWVudDogJG5hdlJpZ2h0LFxuICAgICAgaW5wdXRzOiAkaW5wdXRzLFxuICAgICAgaW5wdXRzV2l0aFJlbG9hZCxcbiAgICAgIHNhdmVDYW5jZWxCdG5zXG4gICAgfTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBDb3JuZXIgaW5mZXJpb3IgaXpxdWllcmRvLCBjb21vIHRpdHVsbyBwYXJhIGZvb3RlclxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBDb3JuZXIgRm9vdGVyXG4gICAqL1xuICBjcmVhdGVDb3JuZXJGb290ZXIoY29uZmlnKSB7XG4gICAgaWYgKFxuICAgICAgY29uZmlnLnRpbWVsaW5lLmZvb3RlciA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICBjb25maWcudGltZWxpbmUuZm9vdGVyLmVuYWJsZWQgPT0gZmFsc2VcbiAgICApXG4gICAgICByZXR1cm4gbnVsbDtcbiAgICBsZXQgc3RyID0gXCJcIjtcblxuICAgIGlmIChjb25maWcudGltZWxpbmUuZm9vdGVyKSB7XG4gICAgICBzdHIgKz0gYDxkaXYgY2xhc3M9XCJjb3JuZXItZm9vdGVyXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNvcm5lci10aXRsZVwiPlxuICAgICAgICAgICAgPHNwYW4+XG4gICAgICAgICAgICAgICR7Y29uZmlnLnRpbWVsaW5lLmZvb3Rlci5sYWJlbH1cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+YDtcbiAgICB9XG4gICAgcmV0dXJuIGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoc3RyKTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBGb290ZXIgcGFyYSBwbGFuaWxsYVxuICAgKiBJbmljaWFsbWVudGUgY3JlYWRvIHBhcmEgdG90YWxlc1xuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBDb3JuZXIgRm9vdGVyXG4gICAqL1xuICBjcmVhdGVGb290ZXIoY29uZmlnKSB7XG4gICAgaWYgKFxuICAgICAgY29uZmlnLnRpbWVsaW5lLmZvb3RlciA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICBjb25maWcudGltZWxpbmUuZm9vdGVyLmVuYWJsZWQgPT0gZmFsc2VcbiAgICApXG4gICAgICByZXR1cm4gbnVsbDtcblxuICAgIGxldCBzdHIgPSBgXG4gICAgICAgIDxmb290ZXI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZvb3Rlci1jb250YWluZXJcIj5cbiAgICAgICAgICBgO1xuICAgIGNvbmZpZy50aW1lbGluZS5mb290ZXIuZGF0YS5mb3JFYWNoKChkKSA9PiB7XG4gICAgICBzdHIgKz0gYFxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZm9vdGVyLWl0ZW1cIj4ke2QudmFsdWV9PC9kaXY+XG4gICAgICAgICAgICBgO1xuICAgIH0pO1xuICAgIHN0ciArPSBgXG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZm9vdGVyPlxuICAgICAgICBgO1xuXG4gICAgcmV0dXJuIGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoc3RyKTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBGb290ZXIgcGFyYSBwbGFuaWxsYVxuICAgKiBJbmljaWFsbWVudGUgY3JlYWRvIHBhcmEgdG90YWxlc1xuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcGFyYW0ge09iamVjdFtdfSBzZWxlY3RlZCAtIGFycmF5IGRlIG9iamV0b3MsIGRlIGRpYXMgc2VsZWNjaW9uYWRvc1xuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBDb3JuZXIgRm9vdGVyXG4gICAqL1xuICBjcmVhdGVTZWxlY3RCb2FyZChjb25maWcsIHNlbGVjdGVkKSB7XG4gICAgbGV0ICRlbGVtID0gZG9tLmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IFwic2VsZWN0LWNvbnRhaW5lclwiIH0pO1xuICAgIHJldHVybiB0aGlzLnJlZHJhd1NlbGVjdEJvYXJkKCRlbGVtLCBzZWxlY3RlZCk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWEgbGluZWEgdmVydGljYWwgcGFyYSBmZWNoYSBBY3R1YWxcbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIENvbmZpZ3VyYWNpb24gY2FwaWJhcmFcbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gQ29ybmVyIEZvb3RlclxuICAgKi9cbiAgY3JlYXRlVG9kYXlMaW5lKGNvbmZpZykge1xuICAgIHJldHVybiB0aGlzLnJlZHJhd1RvZGF5TGluZShcbiAgICAgIGNvbmZpZyxcbiAgICAgIGRvbS5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBcInRvZGF5LWxpbmVcIiB9KVxuICAgICk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIFJlY3JlYSBsaW5lYSB2ZXJ0aWNhbCBwYXJhIGZlY2hhIEFjdHVhbFxuICAgKiBzaSBlbCBlbGVtZW50byAkZWxlbSBubyBlcyBlbnZpYWRvLCBzZSBjcmVhIHVuIG51ZXZvIGVsZW1lbnRvXG4gICAqXG4gICAqIFNpIGVsIGRpYSBhY3R1YWwgbm8gZXN0YSBkZW50cm8gZGVsIHJhbmdvIGRlIGZlY2hhcyBkZWwgY29uZmlnLFxuICAgKiBkZXNoYWJpbGl0YSBsYSBsaW5lYSBjb24gbGEgY2xhc2UgY3NzIC5kaXNhYmxlLWxpbmVcbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIENvbmZpZ3VyYWNpb24gY2FwaWJhcmFcbiAgICogQHBhcmFtIHtPYmplY3R9IFskZWxlbT1udWxsXSAtIEVsZW1lbnRvIERvbSBkb25kZSByZWNyZWEgbGEgbGluZWEsIHNpIGVzIG51bGwsIGxhIGNyZWFcbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gQ29ybmVyIEZvb3RlclxuICAgKi9cbiAgcmVkcmF3VG9kYXlMaW5lKGNvbmZpZywgJGVsZW0gPSBudWxsKSB7XG4gICAgbGV0IGVuZFRpbWUgPSBuZXcgRGF0ZShjb25maWcudGltZWxpbmUuZW5kKS5nZXRUaW1lKCk7XG4gICAgbGV0IHRvZGF5VGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgIGxldCB7IGhlaWdodCwgZGF5V2lkdGggfSA9IHV0aWxzLmdldFRhYmxlRGltZW5zaW9ucyhjb25maWcpO1xuXG4gICAgaWYgKCRlbGVtID09IG51bGwpXG4gICAgICAkZWxlbSA9IGRvbS5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBcInRvZGF5LWxpbmVcIiB9KTtcblxuICAgIGlmIChlbmRUaW1lIDwgdG9kYXlUaW1lKSB7XG4gICAgICAkZWxlbS5jbGFzc0xpc3QuYWRkKFwiZGlzYWJsZS1saW5lXCIpO1xuICAgIH0gZWxzZSB7XG4gICAgICAkZWxlbS5jbGFzc0xpc3QucmVtb3ZlKFwiZGlzYWJsZS1saW5lXCIpO1xuICAgIH1cblxuICAgIGxldCBkaWZmRGF5cyA9IE1hdGguZmxvb3IoXG4gICAgICBkYXRlVXRpbHMuZGlmZkRheXMoXG4gICAgICAgIGNvbmZpZy50aW1lbGluZS5zdGFydCxcbiAgICAgICAgZGF0ZVV0aWxzLmZvcm1hdERhdGUobmV3IERhdGUoKSlcbiAgICAgIClcbiAgICApO1xuICAgIGxldCBkaWZmID0gZGlmZkRheXMgKiBkYXlXaWR0aDtcbiAgICBkaWZmICs9IGRheVdpZHRoIC8gMiAtIDI7IC8vIHBhcmEgY2VudHJhciBsaW5lYVxuICAgIE9iamVjdC5hc3NpZ24oJGVsZW0uc3R5bGUsIHtcbiAgICAgIFwibWFyZ2luLWxlZnRcIjogZGlmZiArIFwicHhcIixcbiAgICAgIGhlaWdodDogaGVpZ2h0ICsgXCJweFwiLFxuICAgIH0pO1xuICAgIHJldHVybiAkZWxlbTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBlbGVtZW50byBGbG9hdEJveCwgcXVlIGNvbnRpZW5lIGxvcyBkYXRvcyBxdWUgc2UgbXVlc3RyYSBlbiBsYSB0YWJsYVxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcGFyYW0ge09iamVjdH0gdGFiIC0gVGFiIGRlIHJlZmVyZW5jaWEsIHBhcmEgbW9zdHJhciBkYXRvcyBjb25maWd1cmFkb3MgcG9yIHRhYlxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBDb3JuZXIgRm9vdGVyXG4gICAqL1xuICBjcmVhdGVGbG9hdEJveChjb25maWcsIHRhYikge1xuICAgIGxldCAkY29udGFpbmVyID0gZG9tLmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwge1xuICAgICAgY2xhc3NOYW1lOiBcImZsb2F0LWJveC1jb250YWluZXJcIixcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcy5yZWRyYXdGbG9hdEJveChjb25maWcsIHRhYiwgJGNvbnRhaW5lcik7XG4gIH0sXG5cbiAgLyoqXG4gICAqIFJlY3JlYSBlbGVtZW50byBGbG9hdEJveCwgcXVlIGNvbnRpZW5lIGxvcyBkYXRvcyBxdWUgc2UgbXVlc3RyYSBlbiBsYSB0YWJsYVxuICAgKiBTZSB1c2EgcHJpbmNpcGFsbWVudGUgcGFyYSBtb3N0cmFyIGRhdG9zIGVuIGxhIHRhYmxhIGRlIGxhIHBsYW5pbGxhXG4gICAqIGxvcyBtdWVzdHJhIGRlIG1hbmVyYSBmbG90YW50ZSwgY2FsY3VsYW5kbyBlbCBUb3AgeSBlbCBMZWZ0IHNlZ3VuIGxhIHBvc2Npb25cbiAgICpcbiAgICogU2UgY29uc2lkZXJhbiBsb3MgZWxlbWVudG9zIHBhZHJlcyBvY3VsdG9zLCBwYXJhIG9jdWx0YXIgbG9zIGRhdG9zXG4gICAqXG4gICAqIFNlIGluc2VydGFuIGxvcyBlbGVtZW50b3MgRmxvYXRCb3gsIGNvbW8gZWxlbWVudG8gY29uIGRhdG9zIGRlIHVuIGl0ZW0geSBkaWEgZXNwZWNpZmljb1xuICAgKlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcGFyYW0ge09iamVjdH0gdGFiIC0gVGFiIGRlIHJlZmVyZW5jaWEsIHBhcmEgbW9zdHJhciBkYXRvcyBjb25maWd1cmFkb3MgcG9yIHRhYlxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBDb3JuZXIgRm9vdGVyXG4gICAqL1xuICByZWRyYXdGbG9hdEJveChjb25maWcsIHRhYiwgJGNvbnRhaW5lcikge1xuICAgICRjb250YWluZXIuaW5uZXJIVE1MID0gXCJcIjtcbiAgICAvL2xldCB0YWJTZWxlY3RlZCA9IHRhYiB8fCBudWxsO1xuXG4gICAgY29uZmlnLmRhdGEuZm9yRWFjaCgoZGUpID0+IHtcbiAgICAgIGlmIChkZS5pc0hpZGRlbikgcmV0dXJuO1xuICAgICAgZGUuY2hpbGRyZW4uZm9yRWFjaCgoZHMpID0+IHtcbiAgICAgICAgaWYgKGRzLmlzSGlkZGVuKSByZXR1cm47XG5cbiAgICAgICAgZHMuZGF0YS5mb3JFYWNoKChkYXRhKSA9PiB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgKCFkYXRhLm1lc3NhZ2UgfHwgZGF0YS5tZXNzYWdlLnZhbHVlID09IG51bGwpICYmXG4gICAgICAgICAgICAoZGF0YS52YWx1ZXMgPT0gbnVsbCB8fCBkYXRhLnZhbHVlcyA9PSB1bmRlZmluZWQgfHxcbiAgICAgICAgICAgIE9iamVjdC5lbnRyaWVzKGRhdGEudmFsdWVzKS5sZW5ndGggPT09IDAgKVxuICAgICAgICAgICl7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICB9XG5cblxuICAgICAgICAgIC8vY2hpbGRyZW4gRGF0YVxuICAgICAgICAgIGxldCBwb3NpdGlvbiA9IHRoaXMuZ2V0UG9zaXRpb25GbG9hdEJveChjb25maWcsIGRhdGEsIGRzKTtcblxuICAgICAgICAgIGxldCBjbGFzc05hbWUgPSBcIlwiO1xuXG5cbiAgICAgICAgICBpZiAoZGF0YS5lcnJvcnMgJiYgZGF0YS5lcnJvcnMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY2xhc3NOYW1lICs9IFwiaGFzLWVycm9ycyBcIjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoZGUuaXNDbG9zZWQpIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZSArPSBcImhpZGUgXCI7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgbGV0IHN0ciA9IGBcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxvYXQtYm94ICR7Y2xhc3NOYW1lfSAke2RlLmlzQ2xvc2VkID8gXCJoaWRlXCIgOiBcIlwifVwiXG4gICAgICAgICAgICAgICAgICAgICBzdHlsZT1cIiR7cG9zaXRpb24gPyBwb3NpdGlvbiA6IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgIGl0ZW0taWQ9XCIke2RzLmlkIHx8IC0xfVwiXG4gICAgICAgICAgICAgICAgICAgICB0eXBlLW5vZGU9XCIke2RzLnR5cGUgfHwgXCJcIn1cIj4gYDtcblxuICAgICAgICAgIGlmICh0YWIgJiYgdGFiLmZsb2F0Qm94KSB7XG5cbiAgICAgICAgICBpZih0YWIuZmxvYXRCb3gubWVzc2FnZVBhdGgpe1xuICAgICAgICAgICAgbGV0IG1zZyA9IHV0aWxzLmdldFZhckJ5UGF0aChkYXRhLCB0YWIuZmxvYXRCb3gubWVzc2FnZVBhdGgpO1xuXG4gICAgICAgICAgICBpZiAobXNnIHx8IChkYXRhLm1lc3NhZ2UgJiYgZGF0YS5tZXNzYWdlLnZhbHVlKSkge1xuICAgICAgICAgICAgICBjbGFzc05hbWUgKz0gXCJoYXMtbWVzc2FnZSBcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cblxuXG5cblxuXG5cblxuXG4gICAgICAgICAgICAvL251bWVyb3MgZW4gZWwgZmxvYXRCb3hcbiAgICAgICAgICAgIGlmICh0YWIuZmxvYXRCb3gubnVtcykge1xuICAgICAgICAgICAgICB0YWIuZmxvYXRCb3gubnVtcy5mb3JFYWNoKChuKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRhYi5sZWdlbmRzICYmIG4udGFiS2V5KSB7XG4gICAgICAgICAgICAgICAgICBsZXQgbGVnZW5kID10YWIubGVnZW5kcy5maW5kKFxuICAgICAgICAgICAgICAgICAgICAobCkgPT4gbC5rZXkgPT0gbi50YWJLZXlcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICBpZiAobGVnZW5kICYmICFsZWdlbmQuYWN0aXZlKSByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbGV0IGRhdGFGbG9hdEJveCA9IG51bGw7XG4gICAgICAgICAgICAgICAgbGV0IGNsYXNzTmFtZSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgbGV0IHNob3dJZiA9IHRydWU7XG4gICAgICAgICAgICAgICAgbGV0IGhpZGVJZiA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGxldCBjb2xvckNsYXNzID0gXCJcIjtcbiAgICAgICAgICAgICAgICBsZXQgY29sb3JTdHlsZSA9IFwiXCI7XG5cblxuICAgICAgICAgICAgICAgIGlmIChuLnZhck5hbWUpIHtcbiAgICAgICAgICAgICAgICAgIGRhdGFGbG9hdEJveCA9IHV0aWxzLmdldFZhckJ5UGF0aChkYXRhLnZhbHVlcywgbi52YXJOYW1lKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAobi52YXJTaG93KSB7XG4gICAgICAgICAgICAgICAgICBzaG93SWYgPSBCb29sZWFuKHV0aWxzLmdldFZhckJ5UGF0aChkYXRhLnZhbHVlcywgbi52YXJTaG93KSk7XG4gICAgICAgICAgICAgICAgICBkYXRhRmxvYXRCb3ggPSBkYXRhRmxvYXRCb3ggfHwgXCJcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAobi52YXJIaWRlKSB7XG4gICAgICAgICAgICAgICAgICBoaWRlSWYgPSBCb29sZWFuKHV0aWxzLmdldFZhckJ5UGF0aChkYXRhLnZhbHVlcywgbi52YXJIaWRlKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG4uc2hhcGUpIHtcbiAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZSArPSBcInNoYXBlLVwiICsgbi5zaGFwZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAobi5jb2xvcikge1xuICAgICAgICAgICAgICAgICAgaWYgKHV0aWxzLmlzSGV4Q29sb3Iobi5jb2xvcikpIHtcbiAgICAgICAgICAgICAgICAgICAgY29sb3JTdHlsZSA9IGAtLWxvY2FsLWNvbG9yOiAke24uY29sb3J9YDtcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbG9yQ2xhc3MgPSBuLmNvbG9yO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChkYXRhRmxvYXRCb3ggIT09IG51bGwgJiYgc2hvd0lmICYmICFoaWRlSWYpIHtcbiAgICAgICAgICAgICAgICAgIHN0ciArPSBgPHNwYW4gY2xhc3M9XCJkYXRhICR7Y29sb3JDbGFzc30gJHtjbGFzc05hbWV9XCIgc3R5bGU9XCIke2NvbG9yU3R5bGV9XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7ZGF0YUZsb2F0Qm94fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPmA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cblxuXG5cblxuICAgICAgICAgICAgLy9wdW50b3MgZW4gZWwgZmxvYXRCb3hcbiAgICAgICAgICAgIGlmICh0YWIuZmxvYXRCb3guZG90cykge1xuICAgICAgICAgICAgICBzdHIgKz0gYFxuICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkb3QtY29udGFpbmVyLW1pZGRsZVwiPmA7XG4gICAgICAgICAgICAgIHRhYi5mbG9hdEJveC5kb3RzLmZvckVhY2goKG4pID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodXRpbHMuZ2V0VmFyQnlQYXRoKGRhdGEudmFsdWVzLCBuLnZhck5hbWUpICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICBzdHIgKz0gYFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkb3QgJHtuLmNvbG9yfSAke1xuICAgICAgICAgICAgICAgICAgICBuLnNoYXBlIHx8IFwiXCJcbiAgICAgICAgICAgICAgICAgIH1cIj48L2Rpdj5gO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHN0ciArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICAgICAgfVxuXG5cblxuXG4gICAgICAgICAgICAvL2ZpbGEgZGUgcHVudG9zIGVuIGZsb2F0Qm94XG4gICAgICAgICAgICBpZiAodGFiLmZsb2F0Qm94LnJvd0RvdHMpIHtcbiAgICAgICAgICAgICAgdGFiLmZsb2F0Qm94LnJvd0RvdHMuZm9yRWFjaCgocm93KSA9PiB7XG5cbiAgICAgICAgICAgICAgICBsZXQgZnJlZUNvbHVtbnMgPSA0O1xuICAgICAgICAgICAgICAgIHN0ciArPSBgPHNwYW4gY2xhc3M9XCJyb3dkb3QtLXJvdyBcIj5gO1xuXG4gICAgICAgICAgICAgICAgcm93LmZvckVhY2goZG90ID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICh0YWIubGVnZW5kcyAmJiBkb3QudGFiS2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBsZWdlbmQgPXRhYi5sZWdlbmRzLmZpbmQoXG4gICAgICAgICAgICAgICAgICAgICAgKGwpID0+IGwua2V5ID09IGRvdC50YWJLZXlcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGxlZ2VuZCAmJiAhbGVnZW5kLmFjdGl2ZSkgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICBsZXQgZGF0YUZsb2F0Qm94ID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgIGxldCBjbGFzc05hbWUgPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgbGV0IHNob3dJZiA9IHRydWU7XG4gICAgICAgICAgICAgICAgICBsZXQgaGlkZUlmID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICBsZXQgY29sb3JDbGFzcyA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICBsZXQgY29sb3JTdHlsZSA9IFwiXCI7XG5cblxuICAgICAgICAgICAgICAgICAgaWYgKCBkb3QudmFyTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICBkYXRhRmxvYXRCb3ggPSB1dGlscy5nZXRWYXJCeVBhdGgoZGF0YS52YWx1ZXMsIGRvdC52YXJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgZGF0YUZsb2F0Qm94ID0gcGFyc2VJbnQoZGF0YUZsb2F0Qm94KTtcbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgaWYgKCBkb3QudmFyU2hvdykge1xuICAgICAgICAgICAgICAgICAgICBzaG93SWYgPSBCb29sZWFuKHV0aWxzLmdldFZhckJ5UGF0aChkYXRhLnZhbHVlcywgZG90LnZhclNob3cpKTtcbiAgICAgICAgICAgICAgICAgICAgZGF0YUZsb2F0Qm94ID0gZGF0YUZsb2F0Qm94IHx8IFwiXCI7XG4gICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgIGlmICggZG90LnZhckhpZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaGlkZUlmID0gQm9vbGVhbih1dGlscy5nZXRWYXJCeVBhdGgoZGF0YS52YWx1ZXMsIGRvdC52YXJIaWRlKSk7XG4gICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgIGlmICggZG90LnNoYXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZSArPSBcIiBzaGFwZS1cIiArIGRvdC5zaGFwZTtcbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgaWYgKCBkb3QuY29sb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHV0aWxzLmlzSGV4Q29sb3IoIGRvdC5jb2xvcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb2xvclN0eWxlID0gYC0tbG9jYWwtY29sb3I6ICR7IGRvdC5jb2xvcn1gO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbG9yQ2xhc3MgPSBkb3QuY29sb3I7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgaWYgKGRhdGFGbG9hdEJveCAhPT0gbnVsbCAmJiBkYXRhRmxvYXRCb3ggPiAwICYmIHNob3dJZiAmJiAhaGlkZUlmICYmIGZyZWVDb2x1bW5zID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgbiA9IGRhdGFGbG9hdEJveCA+IGZyZWVDb2x1bW5zID8gZnJlZUNvbHVtbnMgOiBkYXRhRmxvYXRCb3g7XG4gICAgICAgICAgICAgICAgICAgIGZyZWVDb2x1bW5zIC09IG47XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBuIDsgaW5kZXgrKykge1xuICAgICAgICAgICAgICAgICAgICAgIHN0ciArPSBgPGRpdiBjbGFzcz1cInJvd2RvdC0tZG90ICR7Y29sb3JDbGFzc30gJHtjbGFzc05hbWV9XCIgc3R5bGU9XCIke2NvbG9yU3R5bGV9XCI+PC9kaXY+YDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICBzdHIgKz0gYDwvc3Bhbj5gO1xuXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cblxuXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgc3RyICs9IGBcbiAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuXG4gICAgICAgICAgbGV0ICRlbGVtID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChzdHIpO1xuXG4gICAgICAgICAgJGVsZW0uYWRkRXZlbnRMaXN0ZW5lcihcIm1vdXNlb3ZlclwiLCAoZSkgPT4ge1xuICAgICAgICAgICAgJGVsZW0uZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwibW91c2VPdmVyRmxvYXRCb3hcIiwge1xuICAgICAgICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgZGV0YWlsOiB7XG4gICAgICAgICAgICAgICAgICBpdGVtOiBkcyxcbiAgICAgICAgICAgICAgICAgIGRhdGE6IGRhdGEsXG4gICAgICAgICAgICAgICAgICBvcmlnaW5hbEV2dDogZSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgICRlbGVtLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCAoZSkgPT4ge1xuICAgICAgICAgICAgJGVsZW0uZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwiY2xpY2tGbG9hdEJveFwiLCB7XG4gICAgICAgICAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBkZXRhaWw6IHtcbiAgICAgICAgICAgICAgICAgIGl0ZW06IGRzLFxuICAgICAgICAgICAgICAgICAgZGF0YTogZGF0YSxcbiAgICAgICAgICAgICAgICAgIG9yaWdpbmFsRXZ0OiBlLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgJGNvbnRhaW5lci5hcHBlbmRDaGlsZCgkZWxlbSk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gJGNvbnRhaW5lcjtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBEZXRhaWxEYXksIGRldGFsbGUgZGUgdmFsb3JlcyBkZSBpdGVtIHkgRGlhXG4gICAqIHNlIHVzYSBwYXJhOlxuICAgKiAgICAtIE11ZXN0cmEgbm9tYnJlIGRlIGl0ZW0geSBkZXRhbGxlc1xuICAgKiAgICAtIE11ZXN0cmEgY2Fwc3VsYXMgZGUgZGF0b3NcbiAgICogICAgLSBNdWVzdHJhIFBpbGxzLCBwaWxkb3JhcyBkZSBkYXRvcyByZXN1bWlkb3NcbiAgICogICAgLSBNdWVzdHJhIGFsZXJ0YXNcbiAgICogICAgLSBNdWVzdHJhIE1lbnNhamVcbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIENvbmZpZ3VyYWNpb24gY2FwaWJhcmFcbiAgICogQHBhcmFtIHtPYmplY3R9IGl0ZW0gLSBJdGVtIHJlbGFjaW9uYWRvXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhRGF5IC0gdmFsb3JlcyBkZSBpdGVtIHkgRGlhXG4gICAqIEBwYXJhbSB7Qm9vbGVhbn0gW29ubHlTdHJpbmdDb250ZW50ID0gZmFsc2VdIC0gcGFyYSBlc2NvZ2VyIHNpIGRldnVlbHZlIFN0cmluZyBvIERvbUVsZW1lbnRcbiAgICogQHJldHVybiB7U3RyaW5nfE9iamVjdH0gRWxlbWVudG8gY29tbyBTdHJpbmcgbyBEb21FbGVtZW50XG4gICAqL1xuICBjcmVhdGVEZXRhaWxEYXkoY29uZmlnLCBpdGVtID0ge30sIGRhdGFEYXksIHRhYlNlbGVjdGVkLCBvbmx5U3RyaW5nQ29udGVudCA9IGZhbHNlKSB7XG4gICAgbGV0IHN0ciA9IGBcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiaGVhZGVyLWRldGFpbFwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRpdGxlIHRydW5jYXRlXCI+XG4gICAgICAgICAgICAgICR7aXRlbS5sYWJlbCB8fCBcIlwifVxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3VidGl0bGVcIj5cbiAgICAgICAgICAgICAgJHtkYXRhRGF5ID8gZGF0ZVV0aWxzLmZvcm1hdERhdGVSZWFkZWFibGUoZGF0YURheS5kYXRlKSA6IFwiXCJ9XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJsaXN0LWRldGFpbCBsaXN0XCI+YDtcblxuICAgIC8vQ0FQU1VMRVNcbiAgICBpZiAoZGF0YURheSkge1xuICAgICAgY29uZmlnLnRpbWVsaW5lLmRldGFpbERheS5jYXBzdWxlcy5mb3JFYWNoKChjYXApID0+IHtcbiAgICAgICAgLy9wYXJhIGNvbXByb2JhciBzaSB0aWVuZSBkYXRvcywgc2Ugb2J0aWVuZSBlbCBwcmltZXIgdmFsb3JcbiAgICAgICAgLy9kZSBsYSBsaXN0YSBkZSB2YWx1ZXMgZGUgdW5hIGNhcHN1bGFcbiAgICAgICAgbGV0IGhhc1ZhbHVlcyA9XG4gICAgICAgICAgY2FwLnZhbHVlcy5maWx0ZXIoKHYpID0+XG4gICAgICAgICAgICB1dGlscy5nZXRWYXJCeVBhdGgoZGF0YURheS52YWx1ZXMsIHYudmFyTmFtZSlcbiAgICAgICAgICApLmxlbmd0aCA+IDA7XG4gICAgICAgIGxldCBoaWRlSWYgPSBmYWxzZTtcblxuICAgICAgICBpZiAoY2FwLmhpZGVJZikge1xuICAgICAgICAgIGhpZGVJZiA9IEJvb2xlYW4odXRpbHMuZ2V0VmFyQnlQYXRoKGRhdGFEYXkudmFsdWVzLCBjYXAuaGlkZUlmKSk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgY29sb3JDbGFzcyA9IFwiXCI7XG4gICAgICAgIGxldCBjb2xvclN0eWxlID0gXCJcIjtcblxuICAgICAgICBpZiAoY2FwLmNvbG9yKSB7XG4gICAgICAgICAgaWYgKHV0aWxzLmlzSGV4Q29sb3IoY2FwLmNvbG9yKSkge1xuICAgICAgICAgICAgY29sb3JTdHlsZSA9IGAtLWxvY2FsLWNvbG9yOiAke2NhcC5jb2xvcn07YDtcbiAgICAgICAgICAgIGNvbG9yU3R5bGUgKz0gYC0tbG9jYWwtY29sb3ItZm9udDogJHtjYXAuY29sb3J9O2A7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbG9yQ2xhc3MgPSBjYXAuY29sb3I7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChoYXNWYWx1ZXMgJiYgIWhpZGVJZikge1xuICAgICAgICAgIHN0ciArPSBgXG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpdGVtLWRldGFpbCAke2NvbG9yQ2xhc3N9XCIgc3R5bGU9XCIke2NvbG9yU3R5bGV9XCI+XG5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibGVmdC1pY29uICR7Y2FwLnNoYXBlIHx8IFwiXCJ9IFwiPjwvZGl2PlxuXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm5hbWVcIj5cbiAgICAgICAgICAgICAgICAgIDxzcGFuPlxuICAgICAgICAgICAgICAgICAgICAke2NhcC50aXRsZSB8fCBcIlwifVxuICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgIDwvZGl2PmA7XG5cbiAgICAgICAgICBzdHIgKz0gYFxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJpdGVtLWRlc2NyaXB0aW9uXCI+IGA7XG5cbiAgICAgICAgICBjYXAudmFsdWVzLmZvckVhY2goKHYpID0+IHtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbGV0IHZhbHVlID0gdi52YXJOYW1lID8gdXRpbHMuZ2V0VmFyQnlQYXRoKGRhdGFEYXkudmFsdWVzLCB2LnZhck5hbWUpIDogbnVsbDtcblxuICAgICAgICAgICAgaWYgKGNhcC5pc0xhYmVsZWRBcnJheSkge1xuICAgICAgICAgICAgICB2YWx1ZS5mb3JFYWNoKCh2YWx1ZUxhYmVsZWQpID0+IHtcbiAgICAgICAgICAgICAgICBsZXQgb3V0cHV0VmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgICAgIGxldCB2YWx1ZU5hbWUgPSB2LnZhbHVlTmFtZSA/IHYudmFsdWVOYW1lIDogXCJ2YWx1ZVwiO1xuXG4gICAgICAgICAgICAgICAgbGV0IHRlbXBWYWx1ZSA9IHV0aWxzLmdldFZhckJ5UGF0aCh2YWx1ZUxhYmVsZWQsIHZhbHVlTmFtZSk7XG5cbiAgICAgICAgICAgICAgICBpZiAodGVtcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICBvdXRwdXRWYWx1ZSA9IHYucm91bmQgPyB1dGlscy5yb3VuZCh0ZW1wVmFsdWUsIHYucm91bmQpIDogdGVtcFZhbHVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh2LmZvcm1hdHRlcikge1xuICAgICAgICAgICAgICAgICAgb3V0cHV0VmFsdWUgPSB2LmZvcm1hdHRlcih2YWx1ZUxhYmVsZWQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKHR5cGVvZiBvdXRwdXRWYWx1ZSA9PSBcIm51bWJlclwiKXtcbiAgICAgICAgICAgICAgICAgIG91dHB1dFZhbHVlID0gbmV3IEludGwuTnVtYmVyRm9ybWF0KCkuZm9ybWF0KG91dHB1dFZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBzdHIgKz1cbiAgICAgICAgICAgICAgICAgIG91dHB1dFZhbHVlID09IG51bGxcbiAgICAgICAgICAgICAgICAgICAgPyBcIlwiXG4gICAgICAgICAgICAgICAgICAgIDogYFxuICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkZXNjICR7di5zaG93Q29sdW1uID8gJ2Rlc2MtY29sdW1uJyA6ICcnfVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxhYmVsXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICR7IHYuaGlkZUxhYmVsID8gXCJcIiA6ICB2YWx1ZUxhYmVsZWQubGFiZWx9XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2RpdiA+XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidmFsXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwicHJlZml4XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHt2LnByZWZpeCB8fCBcIlwifVxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidmFsdWVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAke291dHB1dFZhbHVlfVxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwic3VmZml4XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHt2YWx1ZUxhYmVsZWQuc3VmZml4IHx8IHYuc3VmZml4IHx8IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PmA7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgbGV0IG91dHB1dFZhbHVlID0gdi5yb3VuZCA/IHV0aWxzLnJvdW5kKHZhbHVlLCB2LnJvdW5kKSA6IHZhbHVlO1xuXG4gICAgICAgICAgICAgIGlmICh2LmZvcm1hdHRlcikge1xuICAgICAgICAgICAgICAgIG91dHB1dFZhbHVlID0gdi5mb3JtYXR0ZXIoe29wdGlvbnM6dixkYXRhRGF5LCBvdXRwdXRWYWx1ZX0pO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYodHlwZW9mIG91dHB1dFZhbHVlID09IFwibnVtYmVyXCIpe1xuICAgICAgICAgICAgICAgIG91dHB1dFZhbHVlID0gbmV3IEludGwuTnVtYmVyRm9ybWF0KCkuZm9ybWF0KG91dHB1dFZhbHVlKTtcbiAgICAgICAgICAgICAgfVxuXG5cbiAgICAgICAgICAgICAgc3RyICs9XG4gICAgICAgICAgICAgICAgb3V0cHV0VmFsdWUgPT0gbnVsbFxuICAgICAgICAgICAgICAgICAgPyBcIlwiXG4gICAgICAgICAgICAgICAgICA6IGBcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRlc2NcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJwcmVmaXhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAke3YucHJlZml4IHx8IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ2YWx1ZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7b3V0cHV0VmFsdWV9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJzdWZmaXhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAke3Yuc3VmZml4IHx8IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIHN0ciArPSBgXG4gICAgICAgICAgICAgICAgPC9kaXY+YDtcblxuICAgICAgICAgIHN0ciArPSBgXG4gICAgICAgICAgICAgIDwvZGl2PmA7IC8vIGVuZCAuaXRlbS1kZXRhaWxcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgc3RyICs9IGBcbiAgICAgICAgPC9kaXY+YDsgLy8gbGlzdC1kZXRhaWxcblxuICAgIC8vUElMTFNcbiAgICBpZiAoXG4gICAgICBjb25maWcudGltZWxpbmUuZGV0YWlsRGF5LnBpbGxzVmFyTmFtZSAmJlxuICAgICAgZGF0YURheSAmJlxuICAgICAgZGF0YURheS52YWx1ZXNbY29uZmlnLnRpbWVsaW5lLmRldGFpbERheS5waWxsc1Zhck5hbWVdXG4gICAgKSB7XG4gICAgICBzdHIgKz0gYFxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJlbGVtZW50cy1kZXRhaWxcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJuYW1lXCI+ICR7Y29uZmlnLnRpbWVsaW5lLmRldGFpbERheS5waWxsc1RpdGxlfSA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJlbGVtZW50cy1saXN0XCI+YDtcblxuICAgICAgZGF0YURheS52YWx1ZXNbY29uZmlnLnRpbWVsaW5lLmRldGFpbERheS5waWxsc1Zhck5hbWVdLmZvckVhY2goKGUpID0+IHtcbiAgICAgICAgbGV0IHZhbHVlID0gZS52YWx1ZTtcblxuICAgICAgICBpZih0eXBlb2Ygb3V0cHV0VmFsdWUgPT0gXCJudW1iZXJcIil7XG4gICAgICAgICAgdmFsdWUgPSBuZXcgSW50bC5OdW1iZXJGb3JtYXQoKS5mb3JtYXQodmFsdWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgc3RyICs9IGBcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJlbGVtZW50LWRldGFpbFwiPlxuICAgICAgICAgICAgICA8Yj4ke2UubGFiZWx9PC9iPlxuICAgICAgICAgICAgICAke3ZhbHVlfVxuICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgIH0pO1xuXG4gICAgICBzdHIgKz0gYFxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5gOyAvL2VuZCAuZWxlbWVudC1kZXRhaWwgPiAuZWxlbWVudC1saXN0XG4gICAgfVxuXG4gICAgLy9zdHIgKz0gYDwvZGl2PmA7XG5cbiAgICBpZiAoZGF0YURheSAmJiBkYXRhRGF5LmVycm9ycyAmJiBkYXRhRGF5LmVycm9ycy5sZW5ndGggPiAwKSB7XG4gICAgICBkYXRhRGF5LmVycm9ycy5mb3JFYWNoKChlcnIpID0+IHtcbiAgICAgICAgbGV0IGFsZXJ0SWNvbiA9IGA8c3BhbiBjbGFzcz1cImFsZXJ0LWljb25cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPHN2ZyBzdHlsZT1cIndpZHRoOjI0cHg7aGVpZ2h0OjI0cHhcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBmaWxsPVwiY3VycmVudENvbG9yXCIgZD1cIk0xMyAxNEgxMVY5SDEzTTEzIDE4SDExVjE2SDEzTTEgMjFIMjNMMTIgMkwxIDIxWlwiIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPmA7XG4gICAgICAgIHN0ciArPSBgXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImFsZXJ0XCI+XG4gICAgICAgICAgICAke2FsZXJ0SWNvbn1cbiAgICAgICAgICAgICR7ZXJyLmxhYmVsfVxuICAgICAgICAgIDwvZGl2PmA7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBsZXQgbXNnID0gbnVsbDtcbiAgICBsZXQgYXV0aG9yID0gbnVsbDtcbiAgICBsZXQgZGF0ZU1zZyA9IG51bGw7XG4gICAgaWYgKGRhdGFEYXkgKSB7XG4gICAgICBtc2cgPSB1dGlscy5nZXRWYXJCeVBhdGgoZGF0YURheSwgdGFiU2VsZWN0ZWQuZmxvYXRCb3gubWVzc2FnZVBhdGgpO1xuXG4gICAgICBpZighbXNnICYmIGRhdGFEYXkubWVzc2FnZSAmJiBkYXRhRGF5Lm1lc3NhZ2UudmFsdWUpe1xuICAgICAgICBtc2cgPSBkYXRhRGF5Lm1lc3NhZ2UudmFsdWU7XG4gICAgICAgIGF1dGhvciA9IGRhdGFEYXkubWVzc2FnZS5hdXRob3I7XG4gICAgICAgIGRhdGVNc2cgPSBkYXRlVXRpbHMuZm9ybWF0RGF0ZVJlYWRlYWJsZSggbmV3IERhdGUoZGF0YURheS5tZXNzYWdlLmRhdGUpKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYobXNnKXtcbiAgICAgIC8vbXNnID0gbXNnLnJlcGxhY2UoLyhcXHJcXG58XFxyfFxcbikvZywgJzxicj4nKTtcbiAgICAgIHN0ciArPSBgXG4gICAgICAgICAgPGRpdiBjbGFzcz1cIm1zai1jb250YWluZXJcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtc2pcIj5cbiAgICAgICAgICAgIDxwcmU+JHttc2cgfHwgXCJcIn08L3ByZT5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1zai1kZXRhaWxcIj5cbiAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJlbWFpbFwiPiAke2F1dGhvciB8fCBcIlwifSA8L3NwYW4+XG4gICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZGF0ZVwiPiAke2RhdGVNc2cgfHwgXCJcIn0gPC9zcGFuPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PmA7XG4gICAgfVxuXG4gICAgbGV0IHN0ckNvbnRhaW5lciA9IGA8ZGl2IGNsYXNzPVwiZGV0YWlsLWRheSBkZC1oaWRlXCI+ICR7c3RyfSA8L2Rpdj5gO1xuXG4gICAgaWYgKG9ubHlTdHJpbmdDb250ZW50KSByZXR1cm4gc3RyO1xuXG4gICAgcmV0dXJuIGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoc3RyQ29udGFpbmVyKTtcbiAgfSxcblxuICAvKipcbiAgICogUmVjcmVhIEhUTUwgZGUgZGV0YWlsRGF5XG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBjb25maWcgLSBDb25maWd1cmFjaW9uIGNhcGliYXJhXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBpdGVtIC0gSXRlbSByZWxhY2lvbmFkb1xuICAgKiBAcGFyYW0ge09iamVjdH0gZGF0YURheSAtIHZhbG9yZXMgZGUgaXRlbSB5IERpYVxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IEVsZW1lbnRvIGNvbW8gU3RyaW5nLCBkZSBkZXRhaWxEYXlcbiAgICovXG4gIHJlZHJhd0RldGFpbERheShjb25maWcsIGl0ZW0sIGRhdGFEYXksIHRhYlNlbGVjdGVkKSB7XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlRGV0YWlsRGF5KGNvbmZpZywgaXRlbSwgZGF0YURheSwgdGFiU2VsZWN0ZWQsdHJ1ZSk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIFJlcG9zaWNpb25hIEZsb2F0Qm94XG4gICAqIHZlcmlmaWNhIHNpIGVsIHBhcmVudCBlc3RhIGRlc3BsZWdhZG8sIHBhcmEgb2N1bHRhciBsb3MgZGF0b3NcbiAgICpcbiAgICogU29sbyBhY3R1YWxpemEgbGFzIGFsdHVyYXMgZGUgbG9zIGZsb2F0Ym94XG4gICAqIG5vIHJlY3JlYSBsb3MgZmxvYXRib3gsIGVzIG1hcyBvcHRpbW9cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIENvbmZpZ3VyYWNpb24gY2FwaWJhcmFcbiAgICogQHBhcmFtIHtPYmplY3R9IGl0ZW0gLSBJdGVtIHJlbGFjaW9uYWRvXG4gICAqL1xuICByZXBvc2l0aW9uRmxvYXRCb3goY29uZmlnLCAkZmxvYXRCb3hDb250YWluZXIpIHtcbiAgICAkZmxvYXRCb3hDb250YWluZXIucXVlcnlTZWxlY3RvckFsbChcIi5mbG9hdC1ib3hcIikuZm9yRWFjaCgoJGYpID0+IHtcbiAgICAgIGxldCBpdGVtSWQgPSAkZi5nZXRBdHRyaWJ1dGUoXCJpdGVtLWlkXCIpO1xuICAgICAgbGV0IGl0ZW1IZWlnaHQgPSBwYXJzZUZsb2F0KFxuICAgICAgICB1dGlscy5nZXRDU1NWYXJpYWJsZShjb25maWcsIFwiLS1pdGVtLWhlaWdodFwiKVxuICAgICAgKTtcbiAgICAgIGxldCBpdGVtLCBwYXJlbnQ7XG4gICAgICAoeyBpdGVtLCBwYXJlbnQgfSA9IHV0aWxzLmdldEl0ZW1CeUlkKGNvbmZpZywgaXRlbUlkLCBcImNoaWxkXCIsIHRydWUpKTtcbiAgICAgIGlmIChpdGVtKSB7XG4gICAgICAgIGxldCB0b3AgPSB1dGlscy5nZXRQb3NpdGlvbkJ5SXRlbShjb25maWcsIGl0ZW0pO1xuICAgICAgICAkZi5zdHlsZS50b3AgPSB0b3AgKiBpdGVtSGVpZ2h0ICsgXCJweFwiO1xuICAgICAgICBpZiAocGFyZW50ICYmIHBhcmVudC5pc0Nsb3NlZCkge1xuICAgICAgICAgICRmLmNsYXNzTGlzdC5hZGQoXCJoaWRlXCIpO1xuICAgICAgICB9IGVsc2UgaWYgKCRmLmNsYXNzTGlzdC5jb250YWlucyhcImhpZGVcIikpIHtcbiAgICAgICAgICAkZi5jbGFzc0xpc3QucmVtb3ZlKFwiaGlkZVwiKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9LFxuXG4gIC8qKlxuICAgKiBSZWNyZWEgaW5kaWNhZG9yZXMgZGUgZGlhcyBzZWxlY2Npb25hZG9zXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSAkZWxlbSAtIEVsZW1lbnRvIERvbSBkb25kZSBjcmVhIGxvcyBlbGVtZW50b3Mgc2VsZWNjaW9uYWRvc1xuICAgKiBAcGFyYW0ge09iamVjdFtdfSBzZWxlY3RlZCAtIEFycmF5IGNvbiBsb3MgZGlhcyBzZWxlY2Npb25hZG9zXG4gICAqIEByZXR1cm4ge09iamVjdH0gRWxlbWVudG8gRG9tIHF1ZSBjb250aWVuZSBsb3MgaW5kaWNhZG9yZXMgZGUgZGlhcyBzZWxlY2Npb25hZG9zXG4gICAqL1xuICByZWRyYXdTZWxlY3RCb2FyZCgkZWxlbSwgc2VsZWN0ZWQpIHtcbiAgICAkZWxlbS5pbm5lckhUTUwgPSBcIlwiO1xuICAgIGxldCBoYXNOdW1iZXIgPSB0cnVlO1xuXG4gICAgaWYgKHNlbGVjdGVkKSB7XG4gICAgICBpZiAoc2VsZWN0ZWQubGVuZ3RoID09IDEpIGhhc051bWJlciA9IGZhbHNlO1xuXG4gICAgICBzZWxlY3RlZC5mb3JFYWNoKChzKSA9PiB7XG4gICAgICAgIGxldCBhdHRyaWJ1dGVzID0gW107XG5cbiAgICAgICAgaWYgKGhhc051bWJlcikge1xuICAgICAgICAgIGF0dHJpYnV0ZXMucHVzaCh7IG5hbWU6IFwiY2FwLWJhZGdlXCIsIHZhbHVlOiBzLmluZGV4IH0pO1xuICAgICAgICB9XG4gICAgICAgIGxldCAkcyA9IGRvbS5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtcbiAgICAgICAgICBjbGFzc05hbWU6IFwic2VsZWN0ZWQtZGF5XCIsXG4gICAgICAgICAgYXR0cmlidXRlcyxcbiAgICAgICAgfSk7XG4gICAgICAgICRzLnN0eWxlLmxlZnQgPSBzLnBvcy5sZWZ0ICsgXCJweFwiO1xuICAgICAgICAkcy5zdHlsZS50b3AgPSBzLnBvcy50b3AgKyBcInB4XCI7XG4gICAgICAgICRlbGVtLmFwcGVuZCgkcyk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuICRlbGVtO1xuICB9LFxuXG4gIC8qKlxuICAgKiBPYnRpZW5lIFN0cmluZyBjb24gZXN0aWxvcyBDU1MgZGUgbGEgcG9zaWNpb24gZGUgdW4gZmxvYXRCb3hcbiAgICogY2FsY3VsYWRvIHNlZ3VuIGl0ZW0geSBmZWNoYSBkZSBsb3MgdmFsb3Jlc1xuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYSwgcGFyYSB2ZXIgZmVjaGEgZGUgaW5pY2lvXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhIC0gRGF0b3MgZGVsIGRpYSBpbmRpY2Fkb1xuICAgKiBAcGFyYW0ge09iamVjdH0gaXRlbSAtIEl0ZW0gcmVsYWNpb25hZG9cbiAgICogQHJldHVybiB7U3RyaW5nfSBTdHJpbmcgQ1NTIHRvcCB5IGxlZnQgLCBwYXJhIHBvc2ljaW9uYXIgZmxvYXRCb3ggZW4gdGFibGVcbiAgICovXG4gIGdldFBvc2l0aW9uRmxvYXRCb3goY29uZmlnLCBkYXRhLCBpdGVtKSB7XG4gICAgbGV0IGxlZnQgPSBkYXRlVXRpbHMuZGlmZkRheXMoY29uZmlnLnRpbWVsaW5lLnN0YXJ0LCBkYXRhLmRhdGUpO1xuICAgIGxldCB0b3AgPSB1dGlscy5nZXRQb3NpdGlvbkJ5SXRlbShjb25maWcsIGl0ZW0pO1xuICAgIGxldCBkYXlXaWR0aCA9IHBhcnNlRmxvYXQodXRpbHMuZ2V0Q1NTVmFyaWFibGUoY29uZmlnLCBcIi0tZGF5LXdpZHRoXCIpKTtcbiAgICBsZXQgaXRlbUhlaWdodCA9IHBhcnNlRmxvYXQodXRpbHMuZ2V0Q1NTVmFyaWFibGUoY29uZmlnLCBcIi0taXRlbS1oZWlnaHRcIikpO1xuICAgIGxlZnQgKj0gZGF5V2lkdGg7XG4gICAgdG9wICo9IGl0ZW1IZWlnaHQ7XG4gICAgcmV0dXJuIFwidG9wOiBcIiArIHRvcCArIFwiLjVweDsgbGVmdDpcIiArIGxlZnQgKyBcIi41cHg7XCI7XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWEgQm90b24gY29tbyBlbGVtZW50byBEb21cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IHByb3BzIC0gcHJvcGllZGFkZXMgcGFyYSBib3RvblxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcHMuY2xhc3NOYW1lIC0gY2xhc3NlcyBjc3MgcGFyYSBib3RvblxuICAgKiBAcGFyYW0geyp9IHByb3BzLmtleSAtIGtleSBwYXJhIGlkZW50aWZpY2FyIGEgYm90b25cbiAgICogQHBhcmFtIHtTdHJpbmd9IHByb3BzLmxhYmVsIC0gVGV4dG8gYm90b25cbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gZGVsIGJvdG9uIGNyZWFkb1xuICAgKi9cbiAgY3JlYXRlQnV0dG9uKHByb3BzKSB7XG4gICAgcmV0dXJuIGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoYFxuICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cIiR7cHJvcHMuY2xhc3NOYW1lIHx8IFwiXCJ9XCIgaW5wdXQta2V5PVwiJHtcbiAgICAgIHByb3BzLmtleSB8fCBcIlwiXG4gICAgfVwiPlxuICAgICAgICAgICAgICAke3Byb3BzLmxhYmVsIHx8IFwiXCJ9XG4gICAgICAgICAgICA8L2J1dHRvbj5gKTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBCb3RvbmVzIGRlIGd1YXJkYXIgeSBjYW5jZWxhciBsb3MgZGF0b3MgZGUgZm9ybXVsYXJpbyBkZWwgc2lkZWJhciBkZXJlY2hvXG4gICAqXG4gICAqIEByZXR1cm4ge09iamVjdH0gRWxlbWVudG8gRG9tIGRlbCBib3RvbmVzIGNyZWFkb3NcbiAgICovXG4gIGNyZWF0ZU5hdlJpZ2h0YnV0dG9ucygpIHtcbiAgICBsZXQgc2F2ZUJ0biA9IHRoaXMuY3JlYXRlQnV0dG9uKHtcbiAgICAgIGxhYmVsOiBcIkd1YXJkYXJcIixcbiAgICAgIGNsYXNzTmFtZTogXCJjYXAtYnRuLXJhaXNlZFwiLFxuICAgIH0pO1xuICAgIGxldCBjYW5jZWxCdG4gPSB0aGlzLmNyZWF0ZUJ1dHRvbih7XG4gICAgICBsYWJlbDogXCJDYW5jZWxhclwiLFxuICAgICAgY2xhc3NOYW1lOiBcImNhcC1idG4tb3V0bGluZVwiLFxuICAgIH0pO1xuICAgIGxldCBidG5TZWN0aW9uID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChcbiAgICAgIGA8ZGl2IGNsYXNzPVwiYnV0dG9uLXNlY3Rpb25cIj48L2Rpdj5gXG4gICAgKTtcbiAgICBidG5TZWN0aW9uLmFwcGVuZENoaWxkKHNhdmVCdG4pO1xuICAgIGJ0blNlY3Rpb24uYXBwZW5kQ2hpbGQoY2FuY2VsQnRuKTtcblxuICAgIHNhdmVCdG4uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIChlKSA9PiB7XG4gICAgICBzYXZlQnRuLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgIG5ldyBDdXN0b21FdmVudChcInNhdmVNdWx0aUlucHV0XCIsIHtcbiAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgIGNhbmNlbGFibGU6IGZhbHNlLFxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGNhbmNlbEJ0bi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGUpID0+IHtcbiAgICAgIGNhbmNlbEJ0bi5kaXNwYXRjaEV2ZW50KFxuICAgICAgICBuZXcgQ3VzdG9tRXZlbnQoXCJjYW5jZWxNdWx0aUlucHV0XCIsIHtcbiAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgIGNhbmNlbGFibGU6IGZhbHNlLFxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIHJldHVybiBidG5TZWN0aW9uO1xuICB9LFxuXG4gIC8qKlxuICAgKiBDcmVhIElucHV0IGNvbW8gZWxlbWVudG8gRG9tXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwcm9wcyAtIGNvbmZpZyBwYXJhIElucHV0XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbZGF0YURheSA9IG51bGxdIC0gdmFsb3JlcyBkZSBpdGVtIHkgRGlhLCBvcGNpb25hbFxuICAgKiBAcGFyYW0ge09iamVjdH0gW2RheVNlbGVjdGVkID0gbnVsbF0gLSBkYXRvcyBkZWwgZGlhIHNlbGVjY2lvbmFkb1xuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBkZWwgaW5wdXQgY3JlYWRvXG4gICAqL1xuICBjcmVhdGVJbnB1dChwcm9wcywgZGF0YURheSA9IG51bGwsIGRheVNlbGVjdGVkID0gbnVsbCwgc2VsZWN0ZWQgPSBbXSkge1xuICAgIGxldCByID0gbnVsbDtcblxuICAgIGlmIChwcm9wcy5pc0hpZGRlbikgcmV0dXJuIHI7XG5cbiAgICBzd2l0Y2ggKHByb3BzLnR5cGUpIHtcbiAgICAgIGNhc2UgXCJpbnB1dExpc3RcIjpcbiAgICAgICAgciA9IHRoaXMuY3JlYXRlSW5wdXRMaXN0KHByb3BzLCBkYXRhRGF5LCBkYXlTZWxlY3RlZCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBcInNlbGVjdFwiOlxuICAgICAgICByID0gdGhpcy5jcmVhdGVJbnB1dFNlbGVjdChwcm9wcywgZGF0YURheSwgZGF5U2VsZWN0ZWQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgXCJmaWxlXCI6XG4gICAgICAgIHIgPSB0aGlzLmNyZWF0ZUlucHV0RmlsZShwcm9wcywgZGF0YURheSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBcImZpbGVMaW5rXCI6XG4gICAgICAgIHIgPSB0aGlzLmNyZWF0ZUZpbGVMaW5rKHByb3BzLCBkYXRhRGF5KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFwidGV4dFwiOlxuICAgICAgICByID0gdGhpcy5jcmVhdGVUZXh0KHByb3BzLCBzZWxlY3RlZCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBcInRpdGxlXCI6IFxuICAgICAgICByID0gdGhpcy5jcmVhdGVUaXRsZShwcm9wcyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBcIm51bWJlclwiOlxuICAgICAgICByID0gdGhpcy5jcmVhdGVJbnB1dE51bWJlcihwcm9wcywgZGF0YURheSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBcImZsb2F0XCI6XG4gICAgICAgIHIgPSB0aGlzLmNyZWF0ZUlucHV0RmxvYXQocHJvcHMsIGRhdGFEYXkpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgXCJtZXNzYWdlXCI6XG4gICAgICAgIHIgPSB0aGlzLmNyZWF0ZUlucHV0TWVzc2FnZShwcm9wcywgZGF0YURheSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBcInRleHRhcmVhXCI6XG4gICAgICAgIHIgPSB0aGlzLmNyZWF0ZUlucHV0VGV4dEFyZWEocHJvcHMsIGRhdGFEYXkpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgXCJjaGVja2JveFwiOlxuICAgICAgICByID0gdGhpcy5jcmVhdGVJbnB1dENoZWNrYm94KHByb3BzLCBkYXRhRGF5KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFwiaW5wdXQtYm94XCI6XG4gICAgICAgIHIgPSB0aGlzLmNyZWF0ZUlucHV0Qm94KHByb3BzLCBkYXRhRGF5KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFwibGlzdFwiOlxuICAgICAgICByID0gdGhpcy5jcmVhdGVMaXN0KHByb3BzLCBkYXRhRGF5KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFwiYnV0dG9uXCI6XG4gICAgICAgIHIgPSB0aGlzLmNyZWF0ZUlucHV0QnV0dG9uKHByb3BzLCBkYXRhRGF5KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFwidGltZVwiOlxuICAgICAgICByID0gdGhpcy5jcmVhdGVJbnB1dFRpbWUocHJvcHMsIGRhdGFEYXkpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgXCJ0ZXh0XCI6XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByID0gdGhpcy5jcmVhdGVJbnB1dFRleHQocHJvcHMsIGRhdGFEYXkpO1xuICAgIH1cblxuICAgIHJldHVybiByO1xuICB9LFxuXG4gIC8qKlxuICAgKiBDcmVhIElucHV0IGNvbiBmb3JtYXRvIEhvcmEsIGNvbW8gZWxlbWVudG8gRG9tXG4gICAqXG4gICAqIFVzYSAyIGlucHV0cywgaG9yYSB5IG1pbnV0b3NcbiAgICpcbiAgICogZWwgdmFsdWUgcXVlIGludGVycHJldGEgZXMgU3RyaW5nIEhIOk1NXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwcm9wcyAtIGNvbmZpZyBwYXJhIElucHV0XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbZGF0YURheSA9IG51bGxdIC0gdmFsb3JlcyBkZSBpdGVtIHkgRGlhLCBvcGNpb25hbFxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBkZWwgaW5wdXQgY3JlYWRvXG4gICAqL1xuICBjcmVhdGVJbnB1dFRpbWUocHJvcHMsIGRhdGFEYXkpIHtcbiAgICBsZXQgaGhWYWx1ZSA9IFwiXCI7XG4gICAgbGV0IG1tVmFsdWUgPSBcIlwiO1xuXG4gICAgaWYgKGRhdGFEYXkgJiYgZGF0YURheS52YWx1ZXMpIHtcbiAgICAgIGxldCB2YWx1ZSA9IHV0aWxzLmdldFZhckJ5UGF0aChkYXRhRGF5LCBwcm9wcy52YXJOYW1lKTtcblxuICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgIHZhbHVlID0gdmFsdWUuc3BsaXQoXCI6XCIpO1xuICAgICAgICBoaFZhbHVlID0gdmFsdWVbMF07XG4gICAgICAgIG1tVmFsdWUgPSB2YWx1ZVsxXTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgciA9IGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoYFxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1zZWN0aW9uXCIgaW5wdXQta2V5PVwiJHtwcm9wcy5rZXkgfHwgXCJcIn1cIj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC1zdWJ0aXRsZSBkLWJsb2NrXCI+XG4gICAgICAgICAgICAgICR7cHJvcHMubGFiZWwgfHwgXCJcIn1cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0aW1lXCI+XG4gICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwibnVtYmVyXCJcbiAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiaG91clwiXG4gICAgICAgICAgICAgICAgICAgICBpZD1cInRlc3RcIlxuICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCIwMFwiXG4gICAgICAgICAgICAgICAgICAgICBtaW49XCIwXCJcbiAgICAgICAgICAgICAgICAgICAgIG1heD1cIjI0XCJcbiAgICAgICAgICAgICAgICAgICAgIHZhbHVlPVwiJHtoaFZhbHVlfVwiPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInN5bWJvbFwiPjo8L3NwYW4+XG4gICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwibnVtYmVyXCJcbiAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwibWludXRlc1wiXG4gICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIjAwXCJcbiAgICAgICAgICAgICAgICAgICAgIG1pbj1cIjBcIlxuICAgICAgICAgICAgICAgICAgICAgbWF4PVwiNTlcIlxuICAgICAgICAgICAgICAgICAgICAgdmFsdWU9XCIke21tVmFsdWV9XCI+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5gKTtcblxuICAgIGxldCBoaCA9IHIucXVlcnlTZWxlY3RvcihcIi5ob3VyXCIpO1xuICAgIGxldCBtbSA9IHIucXVlcnlTZWxlY3RvcihcIi5taW51dGVzXCIpO1xuXG4gICAgaGguYWRkRXZlbnRMaXN0ZW5lcihcImlucHV0XCIsIChlKSA9PiB7XG4gICAgICBoaC5kaXNwYXRjaEV2ZW50KFxuICAgICAgICBuZXcgQ3VzdG9tRXZlbnQoXCJjaGFuZ2VUaW1lSW5wdXRISFwiLCB7XG4gICAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICBkZXRhaWw6IHtcbiAgICAgICAgICAgIGtleTogcHJvcHMua2V5LFxuICAgICAgICAgICAgdmFsdWU6IGUuc3JjRWxlbWVudC52YWx1ZSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIG1tLmFkZEV2ZW50TGlzdGVuZXIoXCJpbnB1dFwiLCAoZSkgPT4ge1xuICAgICAgbW0uZGlzcGF0Y2hFdmVudChcbiAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwiY2hhbmdlVGltZUlucHV0TU1cIiwge1xuICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICAgICAgZGV0YWlsOiB7XG4gICAgICAgICAgICBrZXk6IHByb3BzLmtleSxcbiAgICAgICAgICAgIHZhbHVlOiBlLnNyY0VsZW1lbnQudmFsdWUsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZEtleURvd25JbnB1dEV2ZW50cyhoaCk7XG4gICAgdGhpcy5hZGRLZXlEb3duSW5wdXRFdmVudHMobW0pO1xuXG4gICAgcmV0dXJuIHI7XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWEgVGV4dCBjb21vIGVsZW1lbnRvIERvbVxuICAgKiBTZSBjb25maWd1cmEgY29tbyBpbnB1dCwgcGVybyBubyBkZXZ1ZWx2ZSBkYXRvcywgZXMgdW4gdGV4dG9cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IHByb3BzIC0gY29uZmlnIHBhcmEgSW5wdXRcbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gZGVsIGlucHV0IGNyZWFkb1xuICAgKi9cbiAgY3JlYXRlVGV4dChwcm9wcywgc2VsZWN0ZWQpIHtcbiAgICBsZXQgbGFiZWwgPSBwcm9wcy5sYWJlbDtcbiAgICBpZiAocHJvcHMuZm9ybWF0dGVyKSB7XG4gICAgICBsYWJlbCA9IHByb3BzLmZvcm1hdHRlcih7IHNlbGVjdGVkIH0pO1xuICAgIH1cbiAgICBsZXQgJGVsZW0gPSBkb20uY3JlYXRlRWxlbWVudEZyb21IVE1MKGBcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiaW5wdXQtc2VjdGlvblwiIGlucHV0LWtleT1cIiR7cHJvcHMua2V5IHx8IFwiXCJ9XCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cIiR7cHJvcHMuY2xhc3NOYW1lcyB8fCBcIlwifVwiPlxuICAgICAgICAgICAgJHtsYWJlbH1cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICA8L2Rpdj5gKTtcbiAgICByZXR1cm4gJGVsZW07XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWEgVGl0bGUgY29tbyBlbGVtZW50byBEb21cbiAgICogU2UgY29uZmlndXJhIGNvbW8gaW5wdXQsIHBlcm8gbm8gZGV2dWVsdmUgZGF0b3MsIGVzIHVuIHRleHRvXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwcm9wcyAtIGNvbmZpZyBwYXJhIElucHV0XG4gICAqIEByZXR1cm4ge09iamVjdH0gRWxlbWVudG8gRG9tIGRlbCBpbnB1dCBjcmVhZG9cbiAgICovXG4gIGNyZWF0ZVRpdGxlKHByb3BzKSB7XG4gICAgbGV0IGNsYXNzTmFtZXMgPSBcInRleHQtdGl0bGVcIjtcbiAgICBpZiAocHJvcHMuaXNTdWJ0aXRsZSkge1xuICAgICAgY2xhc3NOYW1lcyA9IFwidGV4dC1zdWJ0aXRsZVwiO1xuICAgIH1cbiAgICByZXR1cm4gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChgXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb25cIiBpbnB1dC1rZXk9XCIke3Byb3BzLmtleSB8fCBcIlwifVwiPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCIke2NsYXNzTmFtZXN9XCI+XG4gICAgICAgICAgICAgICR7cHJvcHMubGFiZWx9XG4gICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgPC9kaXY+YCk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWEgSW5wdXQgdGlwbyBOdW1lcmljbyBjb21vIGVsZW1lbnRvIERvbVxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gcHJvcHMgLSBjb25maWcgcGFyYSBJbnB1dFxuICAgKiBAcGFyYW0ge09iamVjdH0gZGF0YURheSAtIHZhbG9yZXMgZGUgaXRlbSB5IERpYSwgb3BjaW9uYWxcbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gZGVsIGlucHV0IGNyZWFkb1xuICAgKi9cbiAgY3JlYXRlSW5wdXROdW1iZXIocHJvcHMsIGRhdGFEYXkpIHtcbiAgICBsZXQgdmFsdWUgPSBcIlwiO1xuICAgIGlmIChkYXRhRGF5ICYmIGRhdGFEYXkudmFsdWVzKSB7XG4gICAgICB2YWx1ZSA9IHV0aWxzLmdldFZhckJ5UGF0aChkYXRhRGF5LCBwcm9wcy52YXJOYW1lKTtcbiAgICB9XG4gICAgdmFsdWUgPSB2YWx1ZSB8fCBcIlwiO1xuXG4gICAgbGV0IGVsZW0gPSBkb20uY3JlYXRlRWxlbWVudEZyb21IVE1MKGBcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiaW5wdXQtc2VjdGlvbiAke3Byb3BzLmNsYXNzTmFtZXMgfHwgXCJcIn1cIiBpbnB1dC1rZXk9XCIke1xuICAgICAgcHJvcHMua2V5IHx8IFwiXCJcbiAgICB9XCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaW5wdXQtc2VjdGlvbi10aXRsZVwiPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtc3VidGl0bGVcIj5cbiAgICAgICAgICAgICAgICAke3Byb3BzLmxhYmVsfVxuICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC1zdWJ0aXRsZS0yIFwiPlxuICAgICAgICAgICAgICAgICR7cHJvcHMuc3VmZml4ID8gXCIoXCIgKyBwcm9wcy5zdWZmaXggKyBcIilcIiA6IFwiXCJ9XG4gICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJuYXYtaW5wdXRcIlxuICAgICAgICAgICAgICAgICAgdmFsdWU9XCIke3ZhbHVlfVwiPlxuICAgICAgICAgIDwvZGl2PmApO1xuXG4gICAgbGV0IGlucHV0RWxlbSA9IGVsZW0ucXVlcnlTZWxlY3RvcihcImlucHV0XCIpO1xuICAgIHRoaXMuYWRkS2V5RG93bklucHV0RXZlbnRzKGlucHV0RWxlbSk7XG5cbiAgICByZXR1cm4gZWxlbTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBJbnB1dCB0aXBvIEZJbGVwaWNrZXIgY29tbyBlbGVtZW50byBEb21cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IHByb3BzIC0gY29uZmlnIHBhcmEgSW5wdXRcbiAgICogQHBhcmFtIHtPYmplY3R9IGRhdGFEYXkgLSB2YWxvcmVzIGRlIGl0ZW0geSBEaWEsIG9wY2lvbmFsXG4gICAqIEByZXR1cm4ge09iamVjdH0gRWxlbWVudG8gRG9tIGRlbCBpbnB1dCBjcmVhZG9cbiAgICovXG4gIGNyZWF0ZUlucHV0RmlsZShwcm9wcywgZGF0YURheSkge1xuICAgIGxldCB2YWx1ZSA9IFwiXCI7XG4gICAgbGV0IGZpbGVOYW1lID0gXCJcIjtcbiAgICBsZXQgZmlsZVBhdGggPSBcIlwiO1xuXG4gICAgaWYgKGRhdGFEYXkgJiYgZGF0YURheS52YWx1ZXMpIHtcbiAgICAgIHZhbHVlID0gdXRpbHMuZ2V0VmFyQnlQYXRoKGRhdGFEYXksIHByb3BzLnZhck5hbWUpO1xuICAgICAgZmlsZU5hbWUgPSB1dGlscy5nZXRWYXJCeVBhdGgoZGF0YURheSwgcHJvcHMuZmlsZU5hbWVWYWx1ZSk7XG4gICAgICBmaWxlUGF0aCA9IHV0aWxzLmdldFZhckJ5UGF0aChkYXRhRGF5LCBwcm9wcy5maWxlUGF0aFZhbHVlKTtcbiAgICB9XG5cbiAgICB2YWx1ZSA9IHZhbHVlIHx8IFwiXCI7XG4gICAgZmlsZU5hbWUgPSBmaWxlTmFtZSB8fCBcIlwiO1xuICAgIGZpbGVQYXRoID0gZmlsZVBhdGggfHwgXCJcIjtcblxuICAgIGxldCBlbGVtID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChgXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb24gJHtwcm9wcy5jbGFzc05hbWVzIHx8IFwiXCJ9XCIgaW5wdXQta2V5PVwiJHtcbiAgICAgIHByb3BzLmtleSB8fCBcIlwiXG4gICAgfVwiPlxuXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaW5wdXQtc2VjdGlvbi10aXRsZVwiPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtc3VidGl0bGVcIj5cbiAgICAgICAgICAgICAgICAke3Byb3BzLmxhYmVsfVxuICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm5hdi1pbnB1dC1maWxlXCIgPlxuICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwic21hbGwtY2xvc2UgY2xlYXItZmlsZS1pbnB1dFwiPng8L2J1dHRvbj5cbiAgICAgICAgICAgICAgPGxhYmVsID5cbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm5hdi1pbnB1dC1maWxlLWxhYmVsXCI+XG4gICAgICAgICAgICAgICAgICAke3Byb3BzLnBpY2tlckxhYmVsIHx8IFwiU2VsZWNjaW9uYXIgQXJjaGl2b1wifVxuICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cImZpbGVcIiB2YWx1ZT1cIiR7dmFsdWV9XCI+XG4gICAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb24tbGlua1wiPlxuICAgICAgICAgICAgICA8YSBocmVmPVwiJHtmaWxlUGF0aH1cIiB0YXJnZXQ9XCJfYmxhbmtcIiA+XG4gICAgICAgICAgICAgICAgJHtmaWxlTmFtZX1cbiAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8L2Rpdj5gKTtcblxuICAgIGxldCAkaW5wdXRFbGVtID0gZWxlbS5xdWVyeVNlbGVjdG9yKFwiaW5wdXRcIik7XG4gICAgbGV0ICRjbGVhckJ0biA9IGVsZW0ucXVlcnlTZWxlY3RvcihcIi5jbGVhci1maWxlLWlucHV0XCIpO1xuICAgIGxldCAkZmlsZUlucHV0TGFiZWwgPSBlbGVtLnF1ZXJ5U2VsZWN0b3IoXCIubmF2LWlucHV0LWZpbGUtbGFiZWxcIik7XG5cbiAgICAkaW5wdXRFbGVtLmFkZEV2ZW50TGlzdGVuZXIoXCJjaGFuZ2VcIiwgKGV2dCkgPT4ge1xuICAgICAgbGV0IGZpbGVOYW1lID0gJGlucHV0RWxlbS5maWxlc1swXS5uYW1lO1xuICAgICAgJGZpbGVJbnB1dExhYmVsLnRleHRDb250ZW50ID0gZmlsZU5hbWU7XG4gICAgfSk7XG5cbiAgICAkY2xlYXJCdG4uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIChldnQpID0+IHtcbiAgICAgICRpbnB1dEVsZW0udmFsdWUgPSBcIlwiO1xuICAgICAgJGZpbGVJbnB1dExhYmVsLnRleHRDb250ZW50ID0gcHJvcHMucGlja2VyTGFiZWwgfHwgXCJTZWxlY2Npb25hciBBcmNoaXZvXCI7XG4gICAgICBldnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gZWxlbTtcbiAgfSxcblxuXG4gIGNyZWF0ZUZpbGVMaW5rKHByb3BzLCBkYXRhRGF5KSB7XG4gICAgbGV0IGZpbGVOYW1lID0gXCJcIjtcbiAgICBsZXQgZmlsZVBhdGggPSBcIlwiO1xuXG4gICAgaWYgKGRhdGFEYXkgJiYgZGF0YURheS52YWx1ZXMpIHtcbiAgICAgIC8vdmFsdWUgPSB1dGlscy5nZXRWYXJCeVBhdGgoZGF0YURheSwgcHJvcHMudmFyTmFtZSk7XG4gICAgICBmaWxlTmFtZSA9IHV0aWxzLmdldFZhckJ5UGF0aChkYXRhRGF5LCBwcm9wcy5maWxlTmFtZVZhbHVlKTtcbiAgICAgIGZpbGVQYXRoID0gdXRpbHMuZ2V0VmFyQnlQYXRoKGRhdGFEYXksIHByb3BzLmZpbGVQYXRoVmFsdWUpO1xuICAgIH1cblxuICAgIGlmKGZpbGVOYW1lID09IFwiXCIpIHJldHVybiBudWxsOyBcblxuICAgIGZpbGVOYW1lID0gZmlsZU5hbWUgfHwgXCJcIjtcbiAgICBmaWxlUGF0aCA9IGZpbGVQYXRoIHx8IFwiXCI7XG5cbiAgICBsZXQgZWxlbSA9IGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoYFxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1zZWN0aW9uICR7cHJvcHMuY2xhc3NOYW1lcyB8fCBcIlwifVwiIGlucHV0LWtleT1cIiR7XG4gICAgICBwcm9wcy5rZXkgfHwgXCJcIlxuICAgIH1cIj5cblxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb24tdGl0bGVcIj5cbiAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LXN1YnRpdGxlXCI+XG4gICAgICAgICAgICAgICAgJHtwcm9wcy5sYWJlbH1cbiAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1zZWN0aW9uLWxpbmtcIj5cbiAgICAgICAgICAgICAgPGEgaHJlZj1cIiR7ZmlsZVBhdGh9XCIgdGFyZ2V0PVwiX2JsYW5rXCIgPlxuICAgICAgICAgICAgICAgICR7ZmlsZU5hbWV9XG4gICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgPC9kaXY+YCk7XG5cbiAgICByZXR1cm4gZWxlbTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBsaXN0YSBkZSBJbnB1dHMsIGNvbiBhcnJheSBkZSB2YWxvcmVzLCBjb21vIGVsZW1lbnRvIERvbVxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gcHJvcHMgLSBjb25maWcgcGFyYSBJbnB1dFxuICAgKiBAcGFyYW0ge09iamVjdH0gZGF0YURheSAtIHZhbG9yZXMgZGUgaXRlbSB5IERpYSwgb3BjaW9uYWxcbiAgICogQHBhcmFtIHtPYmplY3R9IFtkYXlTZWxlY3RlZCA9IG51bGxdIC0gZGF0b3MgZGVsIGRpYSBzZWxlY2Npb25hZG9cbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gZGVsIGlucHV0IGNyZWFkb1xuICAgKi9cbiAgY3JlYXRlSW5wdXRMaXN0KHByb3BzLCBkYXRhRGF5LCBkYXlTZWxlY3RlZCA9IG51bGwpIHtcbiAgICBsZXQgdmFsdWUgPSBudWxsO1xuICAgIGxldCBpbnB1dExpc3QgPSBbXTtcblxuICAgIC8vb2J0aWVuZSBpbnB1dHMgZGVmYXVsdCwgcGFyYSBjcmVhcmxvcywgc2luIHZhbG9yZXNcbiAgICBpZiAoXG4gICAgICBkYXlTZWxlY3RlZCAmJlxuICAgICAgQXJyYXkuaXNBcnJheShkYXlTZWxlY3RlZC5pdGVtLnZhbHVlc1twcm9wcy5pbnB1dExpc3RdKVxuICAgICkge1xuICAgICAgaW5wdXRMaXN0ID0gZGF5U2VsZWN0ZWQuaXRlbS52YWx1ZXNbcHJvcHMuaW5wdXRMaXN0XS5tYXAoKGlucHV0Um93KSA9PiB7XG4gICAgICAgIC8vbGltcGlhIGlucHV0TGlzdCBpbnB1dHNcbiAgICAgICAgaW5wdXRSb3cuaW5wdXRzLm1hcCgoaW5wdXQpID0+IHtcbiAgICAgICAgICBpbnB1dC52YWx1ZSA9IG51bGw7XG4gICAgICAgICAgcmV0dXJuIGlucHV0O1xuICAgICAgICB9KTtcblxuICAgICAgICAvL29idGllbmUgdmFsb3JlcyBkZWwgZGlhXG4gICAgICAgIGlmIChkYXRhRGF5ICYmIGRhdGFEYXkudmFsdWVzKSB7XG4gICAgICAgICAgbGV0IGlucHV0VmFsdWVzID0gdXRpbHMuZ2V0VmFyQnlQYXRoKGRhdGFEYXksIHByb3BzLnZhbHVlc1BhdGgpO1xuXG4gICAgICAgICAgLy9hdXRvcnJlbGxlbmFcbiAgICAgICAgICBpZiAoaW5wdXRWYWx1ZXMpIHtcbiAgICAgICAgICAgIGlucHV0Um93LmlucHV0cy5mb3JFYWNoKChpbnB1dCkgPT4ge1xuICAgICAgICAgICAgICBsZXQgdmFsdWVzID0gaW5wdXRWYWx1ZXMuZmluZCgodikgPT4gdi5pZCA9PSBpbnB1dFJvdy5pZCk7XG4gICAgICAgICAgICAgIGlucHV0LnZhbHVlID0gdmFsdWVzID8gdmFsdWVzW2lucHV0LnZhck5hbWVdIDogbnVsbDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBpbnB1dFJvdztcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGxldCBzdHIgPSBgPGRpdiBpbnB1dC1rZXk9XCIke3Byb3BzLmtleSB8fCBcIlwifVwiID5gO1xuICAgIGlucHV0TGlzdC5mb3JFYWNoKChpbnB1dFJvdykgPT4ge1xuICAgICAgc3RyICs9IGBcbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1zZWN0aW9uIFwiID5cbiAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtc3VidGl0bGVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICR7aW5wdXRSb3cubGFiZWx9XG4gICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPmA7XG5cbiAgICAgIGlucHV0Um93LmlucHV0cy5mb3JFYWNoKChpbnB1dCkgPT4ge1xuICAgICAgICBzdHIgKz0gYCBcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb24tY29sXCIgPlxuICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC1zdWJ0aXRsZSBcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICR7aW5wdXQubGFiZWx9XG4gICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwibnVtYmVyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1pZD1cIiR7aW5wdXRSb3cuaWR9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1sYWJlbD1cIiR7aW5wdXQubGFiZWx9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cIm5hdi1pbnB1dFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9XCIke2lucHV0LnZhbHVlfVwiPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgfSk7XG4gICAgICBzdHIgKz0gYFxuICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICB9KTtcbiAgICBzdHIgKz0gYDwvZGl2PmA7XG5cbiAgICBsZXQgZWxlbSA9IGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoc3RyKTtcblxuICAgIGxldCBpbnB1dHNFbGVtID0gZWxlbS5xdWVyeVNlbGVjdG9yQWxsKFwiaW5wdXRcIik7XG4gICAgaW5wdXRzRWxlbS5mb3JFYWNoKChpbnB1dEVsZW0pID0+IHRoaXMuYWRkS2V5RG93bklucHV0RXZlbnRzKGlucHV0RWxlbSkpO1xuICAgIHJldHVybiBlbGVtO1xuICB9LFxuXG5cbiAgY3JlYXRlSW5wdXRTZWxlY3QocHJvcHMsIGRhdGFEYXksIGRheVNlbGVjdGVkID0gbnVsbCkge1xuICAgIGxldCB2YWx1ZSA9IG51bGw7XG4gICAgbGV0IG9wdGlvbnMgPSBwcm9wcy5vcHRpb25zO1xuXG4gICAgaWYgKGRhdGFEYXkgJiYgZGF0YURheS52YWx1ZXMpIHtcbiAgICAgIGxldCB2YWwgPSB1dGlscy5nZXRWYXJCeVBhdGgoZGF0YURheSwgcHJvcHMudmFyTmFtZSk7XG4gICAgICB2YWx1ZSA9IHZhbCA/IHZhbC52YWx1ZSA6IG51bGw7XG4gICAgfVxuXG4gICAgbGV0IHN0ciA9IGA8ZGl2IGlucHV0LWtleT1cIiR7cHJvcHMua2V5IHx8IFwiXCJ9XCIgPlxuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb24gXCIgPlxuICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC1zdWJ0aXRsZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgJHtwcm9wcy5sYWJlbH1cbiAgICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XG5cbiAgICAgICAgICAgICAgICAgICAgICA8c2VsZWN0IGNsYXNzPVwiaW5wdXQtc2VsZWN0XCI+XG5cbiAgICAgICAgICAgICAgICAgPG9wdGlvbiB2YWx1ZT1cIlwiICR7dmFsdWUgPT0gbnVsbCA/ICdzZWxlY3RlZCcgOiAnJ30+XG4gICAgICAgICAgICAgICAgICAke3Byb3BzLm5vRGF0YUxhYmVsIHx8IFwiLS0gc2luIGFzaWduYXIgLS1cIn1cbiAgICAgICAgICAgICAgICAgPC9vcHRpb24+XG5cbiAgICAgICAgYDtcblxuXG4gICAgICBvcHRpb25zLmZvckVhY2goKG9wdGlvbikgPT4ge1xuICAgICAgICBzdHIgKz0gYFxuICAgICAgICAgICAgICAgICA8b3B0aW9uIHZhbHVlPVwiJHtvcHRpb24uaWR9XCIgJHtvcHRpb24uaWQgPT0gdmFsdWUgPyAnc2VsZWN0ZWQnIDogJyd9PlxuICAgICAgICAgICAgICAgICAke29wdGlvbi5sYWJlbH1cbiAgICAgICAgICAgICAgICAgPC9vcHRpb24+XG4gICAgICAgICAgICAgICAgYDtcbiAgICAgIH0pO1xuICAgICAgc3RyICs9IGBcblxuICAgICAgICAgICAgICAgICAgICAgIDwvc2VsZWN0PlxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgIDwvZGl2PmA7XG5cbiAgICBsZXQgZWxlbSA9IGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoc3RyKTtcblxuICAgIHJldHVybiBlbGVtO1xuICB9LFxuXG4gIC8qKlxuICAgKiBDcmVhIElucHV0IGRlIHRleHRvIFRleHRBcmVhIGNvbW8gZWxlbWVudG8gRG9tXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwcm9wcyAtIGNvbmZpZyBwYXJhIElucHV0XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhRGF5IC0gdmFsb3JlcyBkZSBpdGVtIHkgRGlhLCBvcGNpb25hbFxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBkZWwgaW5wdXQgY3JlYWRvXG4gICAqL1xuICBjcmVhdGVJbnB1dFRleHRBcmVhKHByb3BzLCBkYXRhRGF5KSB7XG4gICAgbGV0IHZhbHVlID0gXCJcIjtcbiAgICBpZiAoZGF0YURheSAmJiBkYXRhRGF5LnZhbHVlcykge1xuICAgICAgdmFsdWUgPSB1dGlscy5nZXRWYXJCeVBhdGgoZGF0YURheSwgcHJvcHMudmFyTmFtZSk7XG4gICAgfVxuICAgIGxldCBlbGVtID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChgXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb25cIiBpbnB1dC1rZXk9XCIke3Byb3BzLmtleSB8fCBcIlwifVwiPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LXN1YnRpdGxlIGQtYmxvY2tcIj5cbiAgICAgICAgICAgICAgJHtwcm9wcy5sYWJlbH1cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDx0ZXh0YXJlYSBjbGFzcz1cIlwiIHZhbHVlPVwiJHt2YWx1ZX1cIj48L3RleHRhcmVhPlxuICAgICAgICAgIDwvZGl2PmApO1xuXG4gICAgbGV0IGlucHV0RWxlbSA9IGVsZW0ucXVlcnlTZWxlY3RvcihcInRleHRhcmVhXCIpO1xuICAgIHRoaXMuYWRkS2V5RG93bklucHV0RXZlbnRzKGlucHV0RWxlbSk7XG4gICAgcmV0dXJuIGVsZW07XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWEgSW5wdXQgZGUgTWVuc2FqZSBjb21vIGVsZW1lbnRvIERvbVxuICAgKiB1dGlsaXphIFRleHRBcmVhXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwcm9wcyAtIGNvbmZpZyBwYXJhIElucHV0XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhRGF5IC0gdmFsb3JlcyBkZSBpdGVtIHkgRGlhLCBvcGNpb25hbFxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBkZWwgaW5wdXQgY3JlYWRvXG4gICAqL1xuICBjcmVhdGVJbnB1dE1lc3NhZ2UocHJvcHMsIGRhdGFEYXkpIHtcbiAgICBsZXQgdmFsdWUgPSBkYXRhRGF5ID8gdXRpbHMuZ2V0VmFyQnlQYXRoKGRhdGFEYXksIHByb3BzLnZhck5hbWUpIDogbnVsbDtcbiAgICBsZXQgZWxlbSA9IGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoYFxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1zZWN0aW9uIG1zai1pbnB1dC1jb250YWluZXJcIlxuICAgICAgICAgICAgICBpbnB1dC1rZXk9XCIke3Byb3BzLmtleSB8fCBcIlwifVwiPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LXN1YnRpdGxlIGQtYmxvY2tcIj5cbiAgICAgICAgICAgICAgTWVuc2FqZVxuICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgPHRleHRhcmVhIGNsYXNzPVwibXNqXCI+JHt2YWx1ZSB8fCBcIlwifTwvdGV4dGFyZWE+XG4gICAgICAgICAgPC9kaXY+YCk7XG5cbiAgICBsZXQgaW5wdXRFbGVtID0gZWxlbS5xdWVyeVNlbGVjdG9yKFwidGV4dGFyZWFcIik7XG4gICAgLy90aGlzLmFkZEtleURvd25JbnB1dEV2ZW50cyhpbnB1dEVsZW0pO1xuICAgIHJldHVybiBlbGVtO1xuICB9LFxuXG4gIC8qKlxuICAgKiBDcmVhIElucHV0IGRlIHRleHRvIGNvbW8gZWxlbWVudG8gRG9tXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwcm9wcyAtIGNvbmZpZyBwYXJhIElucHV0XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhRGF5IC0gdmFsb3JlcyBkZSBpdGVtIHkgRGlhLCBvcGNpb25hbFxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBkZWwgaW5wdXQgY3JlYWRvXG4gICAqL1xuICBjcmVhdGVJbnB1dFRleHQocHJvcHMsIGRhdGFEYXkpIHtcbiAgICBsZXQgdmFsdWUgPSBcIlwiO1xuICAgIGlmIChkYXRhRGF5ICYmIGRhdGFEYXkudmFsdWVzKSB7XG4gICAgICB2YWx1ZSA9IHV0aWxzLmdldFZhckJ5UGF0aChkYXRhRGF5LCBwcm9wcy52YXJOYW1lKTtcbiAgICB9XG4gICAgbGV0IGVsZW0gPSBkb20uY3JlYXRlRWxlbWVudEZyb21IVE1MKGBcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiaW5wdXQtc2VjdGlvblwiIGlucHV0LWtleT1cIiR7cHJvcHMua2V5IHx8IFwiXCJ9XCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtc3VidGl0bGUgZC1ibG9ja1wiPlxuICAgICAgICAgICAgICAke3Byb3BzLmxhYmVsfVxuICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgY2xhc3M9XCJuYXYtaW5wdXRcIiB2YWx1ZT1cIiR7dmFsdWV9XCI+XG4gICAgICAgICAgPC9kaXY+YCk7XG5cbiAgICBsZXQgaW5wdXRFbGVtID0gZWxlbS5xdWVyeVNlbGVjdG9yKFwiaW5wdXRcIik7XG4gICAgdGhpcy5hZGRLZXlEb3duSW5wdXRFdmVudHMoaW5wdXRFbGVtKTtcbiAgICByZXR1cm4gZWxlbTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBJbnB1dCBOdW1lcm8gRmxvdGFudGUsIGNvbW8gZWxlbWVudG8gRG9tXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwcm9wcyAtIGNvbmZpZyBwYXJhIElucHV0XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhRGF5IC0gdmFsb3JlcyBkZSBpdGVtIHkgRGlhLCBvcGNpb25hbFxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBkZWwgaW5wdXQgY3JlYWRvXG4gICAqL1xuICBjcmVhdGVJbnB1dEZsb2F0KHByb3BzLCBkYXRhRGF5KSB7XG4gICAgbGV0IHZhbHVlID0gXCJcIjtcbiAgICBpZiAoZGF0YURheSAmJiBkYXRhRGF5LnZhbHVlcykge1xuICAgICAgdmFsdWUgPSB1dGlscy5nZXRWYXJCeVBhdGgoZGF0YURheSwgcHJvcHMudmFyTmFtZSk7XG4gICAgfVxuICAgIGxldCBlbGVtID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChgXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb25cIiBpbnB1dC1rZXk9XCIke3Byb3BzLmtleSB8fCBcIlwifVwiPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LXN1YnRpdGxlIGQtYmxvY2tcIj5cbiAgICAgICAgICAgICAgJHtwcm9wcy5sYWJlbH1cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwibnVtYmVyXCIgY2xhc3M9XCJuYXYtaW5wdXRcIiB2YWx1ZT1cIiR7dmFsdWV9XCI+XG4gICAgICAgICAgPC9kaXY+YCk7XG5cbiAgICBsZXQgaW5wdXRFbGVtID0gZWxlbS5xdWVyeVNlbGVjdG9yKFwiaW5wdXRcIik7XG4gICAgdGhpcy5hZGRLZXlEb3duSW5wdXRFdmVudHMoaW5wdXRFbGVtKTtcbiAgICByZXR1cm4gZWxlbTtcbiAgfSxcblxuXG5cblxuXG5cbiAgY3JlYXRlTGlzdChwcm9wcywgZGF0YURheSkge1xuICAgIGxldCB2YWx1ZSA9IFtdO1xuICAgIGlmIChkYXRhRGF5ICYmIGRhdGFEYXkudmFsdWVzKSB7XG4gICAgICB2YWx1ZSA9IHV0aWxzLmdldFZhckJ5UGF0aChkYXRhRGF5LCBwcm9wcy52YXJOYW1lKTtcbiAgICB9XG5cbiAgICBsZXQgdGFic0NvbnRhaW5lciA9IFwiXCI7XG5cbiAgICBpZiAocHJvcHMudGFicykge1xuICAgICAgbGV0IHRhYnMgPSBcIlwiO1xuICAgICAgcHJvcHMudGFicy5mb3JFYWNoKCh0YWIpID0+IHtcbiAgICAgICAgdGFicyArPSBgXG4gICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1ib3gtdGFiXCIgdGFiLWtleT1cIiR7dGFiLmtleX1cIj5cbiAgICAgICAgICAke3RhYi5uYW1lfVxuICAgICAgICA8L2Rpdj5gO1xuICAgICAgfSk7XG5cbiAgICAgIHRhYnNDb250YWluZXIgPSBgXG4gICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1ib3gtdGFiLWNvbnRhaW5lclwiPlxuICAgICAgICAke3RhYnN9XG4gICAgICAgIDwvZGl2PlxuICAgICAgYDtcbiAgICB9XG5cbiAgICBsZXQgY2xvc2VJY29uID0gYDxzcGFuIGNsYXNzPVwiY2xvc2UtaWNvblwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxzdmcgc3R5bGU9XCJ3aWR0aDoyNHB4O2hlaWdodDoyNHB4XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBmaWxsPVwiY3VycmVudENvbG9yXCIgZD1cIk0xOSw2LjQxTDE3LjU5LDVMMTIsMTAuNTlMNi40MSw1TDUsNi40MUwxMC41OSwxMkw1LDE3LjU5TDYuNDEsMTlMMTIsMTMuNDFMMTcuNTksMTlMMTksMTcuNTlMMTMuNDEsMTJMMTksNi40MVpcIiAvPlxuICAgICAgICAgICAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgICAgICAgICAgICA8L3NwYW4+YDtcblxuICAgIGxldCBsaW5rSWNvbiA9IGAgPHNwYW4gY2xhc3M9XCJjbG9zZS1pY29uXCI+XG4gICAgICAgICAgICAgICAgICAgICAgPHN2ZyBzdHlsZT1cIndpZHRoOjI0cHg7aGVpZ2h0OjI0cHhcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGZpbGw9XCJjdXJyZW50Q29sb3JcIiBkPVwiTTE0LDNWNUgxNy41OUw3Ljc2LDE0LjgzTDkuMTcsMTYuMjRMMTksNi40MVYxMEgyMVYzTTE5LDE5SDVWNUgxMlYzSDVDMy44OSwzIDMsMy45IDMsNVYxOUEyLDIgMCAwLDAgNSwyMUgxOUEyLDIgMCAwLDAgMjEsMTlWMTJIMTlWMTlaXCIgLz5cbiAgICAgICAgICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgIGA7XG5cbiAgICBsZXQgc2VhcmNoSW5wdXQ9IGBcbiAgICAgIDxkaXYgY2xhc3M9XCJzZWFyY2gtaW5wdXQtY29udGFpbmVyXCI+XG4gICAgICAgIDxpbnB1dCBpZD1cIlwiIHR5cGU9XCJ0ZXh0XCIgbmFtZT1cIlwiIGNsYXNzPVwic2VhcmNoLWlucHV0XCIgcGxhY2Vob2xkZXI9XCJidXNjYXJcIj5cbiAgICAgICAgPGJ1dHRvbiBjbGFzcz1cInNlYXJjaC1pbnB1dC1jbGVhclwiPlxuICAgICAgICAgJHtjbG9zZUljb259XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgYDtcblxuXG5cbiAgICBsZXQgc3RyID0gYFxuICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb25cIiBpbnB1dC1rZXk9XCIke3Byb3BzLmtleSB8fCBcIlwifVwiPlxuICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtc3VidGl0bGUgZC1ibG9ja1wiPlxuICAgICAgICAgICAgICAke3Byb3BzLmxhYmVsfVxuICAgICAgICAgICAgPC9zcGFuPlxuXG4gICAgICAgICAgICAke3RhYnNDb250YWluZXJ9XG4gICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1ib3ggXCIgaW5wdXQta2V5PVwiJHtwcm9wcy5rZXkgfHwgXCJcIn1cIj5cblxuICAgICAgICAgICAgJHtzZWFyY2hJbnB1dH1cbiAgICAgIGA7XG5cbiAgICAvL1RPRE8gb2J0ZW5lciBpbnB1dCBzZWd1biBmaWxhXG4gICAgaWYgKHByb3BzLmlucHV0cykge1xuICAgICAgcHJvcHMuaW5wdXRzLmZvckVhY2goKGkpID0+IHtcbiAgICAgICAgaWYoaS5pc1RpdGxlKXtcblxuICAgICAgICAgIGxldCB0b29sdGlwID0gXCJcIjtcbiAgICAgICAgICBsZXQgaWNvbiA9IFwiXCI7XG5cbiAgICAgICAgICBpZiAoaS50b29sdGlwKSB7XG4gICAgICAgICAgICB0b29sdGlwID0gYFxuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1pbmktaW5wdXQtc2VjdGlvbi0tdG9vbHRpcFwiPlxuICAgICAgICAgICAgICAgICAgICAke2kudG9vbHRpcH1cbiAgICAgICAgICAgICAgICAgICAgJHtpLnN1ZmZpeCA/IFwiKFwiICsgaS5zdWZmaXggKyBcIilcIiA6IFwiXCJ9XG4gICAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChpLmNvbG9ySWNvbikge1xuICAgICAgICAgICAgaWYgKHV0aWxzLmlzSGV4Q29sb3IoaS5jb2xvckljb24pKSB7XG4gICAgICAgICAgICAgIGljb24gPSBgPGRpdiBjbGFzcz1cIm1pbmktaW5wdXQtc2VjdGlvbi0taWNvblwiIHN0eWxlPVwiYmFja2dyb3VuZDoke2kuY29sb3JJY29ufVwiPiA8L2Rpdj5gO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaWNvbiA9IGA8ZGl2IGNsYXNzPVwibWluaS1pbnB1dC1zZWN0aW9uLS1pY29uICR7aS5jb2xvckljb259XCI+IDwvZGl2PmA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG5cbiAgICAgICAgc3RyICs9IGBcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtaW5pLWlucHV0LXNlY3Rpb24gaXMtdGl0bGVcIiBpbnB1dC10YWIta2V5PVwiJHtpLnRhYktleSB8fCBcIlwifVwiIGxhYmVsPVwiJHtpLmxhYmVsfVwiPlxuICAgICAgICAgICAgICA8bGFiZWw+XG4gICAgICAgICAgICAgICAgJHtpY29ufVxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtaW5pLWlucHV0LXNlY3Rpb24tLXRpdGxlIHRydW5jYXRlXCI+XG4gICAgICAgICAgICAgICAgICAke2kubGFiZWx9XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgICAgICR7dG9vbHRpcH1cbiAgICAgICAgICAgIDwvZGl2PmA7XG5cblxuXG4gICAgICAgIH1lbHNle1xuICAgICAgICAgIGxldCB2YWx1ZV9mb3VuZCA9IHZhbHVlID8gdmFsdWUuZmluZCgodmFsKSA9PiB2YWwuaWQgPT0gaS5pZCkgOiBudWxsO1xuICAgICAgICAgIGxldCB2ID0gdmFsdWVfZm91bmQgfHwgXCJcIjtcbiAgICAgICAgICBsZXQgaW5wdXRWYWx1ZSA9cHJvcHMudmFyTmFtZUlucHV0ICYmIHZbcHJvcHMudmFyTmFtZUlucHV0IF0gPyB2W3Byb3BzLnZhck5hbWVJbnB1dCBdIDogdi52YWx1ZTtcbiAgICAgICAgICBsZXQgdG9vbHRpcCA9IFwiXCI7XG4gICAgICAgICAgbGV0IGljb24gPSBcIlwiO1xuICAgICAgICAgIGxldCBsaW5rID0gXCJcIjtcblxuICAgICAgICAgIGlmIChpLnRvb2x0aXApIHtcbiAgICAgICAgICAgIHRvb2x0aXAgPSBgXG4gICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWluaS1pbnB1dC1zZWN0aW9uLS10b29sdGlwXCI+XG4gICAgICAgICAgICAgICAgICAgICR7aS50b29sdGlwfVxuICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoaS5jb2xvckljb24pIHtcbiAgICAgICAgICAgIGlmICh1dGlscy5pc0hleENvbG9yKGkuY29sb3JJY29uKSkge1xuICAgICAgICAgICAgICBpY29uID0gYDxkaXYgY2xhc3M9XCJtaW5pLWlucHV0LXNlY3Rpb24tLWljb25cIiBzdHlsZT1cImJhY2tncm91bmQ6JHtpLmNvbG9ySWNvbn1cIj4gPC9kaXY+YDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGljb24gPSBgPGRpdiBjbGFzcz1cIm1pbmktaW5wdXQtc2VjdGlvbi0taWNvbiAke2kuY29sb3JJY29ufVwiPiA8L2Rpdj5gO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmKGkubGluayl7XG4gICAgICAgICAgICBsaW5rID0gYDxhIGNsYXNzPVwibWluaS1pbnB1dC1zZWN0aW9uLS1saW5rXCIgdGFyZ2V0PVwiX2JsYW5rXCIgaHJlZj1cIiR7aS5saW5rfVwiPlxuICAgICAgICAgICAgICAgICR7bGlua0ljb259XG4gICAgICAgICAgICAgICAgPC9hPiBgXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgc3RyICs9IGBcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtaW5pLWlucHV0LXNlY3Rpb25cIiBpbnB1dC10YWIta2V5PVwiJHtpLnRhYktleSB8fCBcIlwifVwiIGxhYmVsPVwiJHtpLmxhYmVsfVwiPlxuICAgICAgICAgICAgICA8bGFiZWw+XG5cbiAgICAgICAgICAgICAgICAke2ljb259XG5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWluaS1pbnB1dC1zZWN0aW9uLS1uYW1lIHRydW5jYXRlXCI+XG4gICAgICAgICAgICAgICAgICAke2kubGFiZWx9XG4gICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWluaS1pbnB1dC1zZWN0aW9uLS1zdWZmaXhcIiA+JHtcbiAgICAgICAgICAgICAgICAgIGkuc3VmZml4ID8gXCIoXCIgKyBpLnN1ZmZpeCArIFwiKVwiIDogXCJcIlxuICAgICAgICAgICAgICAgIH08L2Rpdj5cblxuICAgICAgICAgICAgICAgICR7bGlua31cblxuICAgICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWluaS1pbnB1dC1zZWN0aW9uLS1mb290ZXJcIj5cbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInN0YXJ0XCI+IHRlc3QgPC9zcGFuPlxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZW5kXCI+IHRlc3QgZW5kIDwvc3Bhbj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICR7dG9vbHRpcH1cbiAgICAgICAgICAgIDwvZGl2PmA7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHN0ciArPSBgXG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+IGA7XG5cbiAgICBsZXQgJGVsID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChzdHIpO1xuICAgIGxldCAkdGFicyA9ICRlbC5xdWVyeVNlbGVjdG9yQWxsKFwiLmlucHV0LWJveC10YWJbdGFiLWtleV1cIikgfHwgW107XG4gICAgbGV0ICRzZWFyY2hJbnB1dCA9ICRlbC5xdWVyeVNlbGVjdG9yKFwiLnNlYXJjaC1pbnB1dFwiKSB8fCBudWxsO1xuICAgIGxldCAkc2VhcmNoSW5wdXRDbGVhciA9ICRlbC5xdWVyeVNlbGVjdG9yKFwiLnNlYXJjaC1pbnB1dC1jbGVhclwiKSB8fCBudWxsO1xuXG4gICAgJHRhYnMuZm9yRWFjaCgodCkgPT4ge1xuICAgICAgdC5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGUpID0+IHtcbiAgICAgICAgdGhpcy5zZWxlY3RJbnB1dEJveFRhYih0LCAkZWwpO1xuICAgICAgICAkc2VhcmNoSW5wdXQudmFsdWUgPSBcIlwiO1xuICAgICAgICAkc2VhcmNoSW5wdXQuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoJ2lucHV0Jywge2J1YmJsZXM6dHJ1ZX0pKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaWYoJHNlYXJjaElucHV0Q2xlYXIpe1xuICAgICAgJHNlYXJjaElucHV0Q2xlYXIuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGUgPT4ge1xuICAgICAgICAkc2VhcmNoSW5wdXQudmFsdWUgPSBcIlwiO1xuICAgICAgICAkc2VhcmNoSW5wdXQuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoJ2lucHV0Jywge2J1YmJsZXM6dHJ1ZX0pKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmKCRzZWFyY2hJbnB1dCl7XG4gICAgICAkc2VhcmNoSW5wdXQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsZSA9PiB7XG4gICAgICAgIGlmKGUua2V5ID09PSBcIkVzY2FwZVwiKXtcbiAgICAgICAgICAkc2VhcmNoSW5wdXQudmFsdWUgPSBcIlwiO1xuICAgICAgICAgICRzZWFyY2hJbnB1dC5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudCgnaW5wdXQnLCB7YnViYmxlczp0cnVlfSkpO1xuICAgICAgICB9XG4gICAgICB9KTsgXG5cbiAgICAgICRzZWFyY2hJbnB1dC5hZGRFdmVudExpc3RlbmVyKFwiaW5wdXRcIiwgZSA9PiB7XG4gICAgICAgIGxldCAkdGFiU2VsZWN0ZWQgPSAkZWwucXVlcnlTZWxlY3RvcihcIi5pbnB1dC1ib3gtdGFiW3RhYi1rZXldLmFjdGl2ZVwiKSB8fCBudWxsO1xuICAgICAgICBsZXQgJGlucHV0cyA9IFtdO1xuICAgICAgICBpZigkdGFiU2VsZWN0ZWQpe1xuICAgICAgICAgIGxldCB0YWJLZXkgPSAkdGFiU2VsZWN0ZWQuZ2V0QXR0cmlidXRlKFwidGFiLWtleVwiKTtcbiAgICAgICAgICAkaW5wdXRzID0gJGVsLnF1ZXJ5U2VsZWN0b3JBbGwoXCIubWluaS1pbnB1dC1zZWN0aW9uW2lucHV0LXRhYi1rZXk9J1wiK3RhYktleStcIiddXCIpIHx8IFtdO1xuICAgICAgICB9ZWxzZXtcbiAgICAgICAgICAkaW5wdXRzID0gJGVsLnF1ZXJ5U2VsZWN0b3JBbGwoXCIubWluaS1pbnB1dC1zZWN0aW9uXCIpIHx8IFtdO1xuICAgICAgICB9XG4gICAgICAgICRpbnB1dHMuZm9yRWFjaCgkaSA9PiB7XG4gICAgICAgICAgbGV0IGxhYmVsID0gJGkuZ2V0QXR0cmlidXRlKFwibGFiZWxcIik7XG4gICAgICAgICAgbGV0IHNlYXJjaCA9ICRzZWFyY2hJbnB1dC52YWx1ZTtcbiAgICAgICAgICBpZihsYWJlbC50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHNlYXJjaC50b0xvd2VyQ2FzZSgpKSl7XG4gICAgICAgICAgICAkaS5jbGFzc0xpc3QucmVtb3ZlKFwiaGlkZVwiKTtcbiAgICAgICAgICB9ZWxzZXtcbiAgICAgICAgICAgICRpLmNsYXNzTGlzdC5hZGQoXCJoaWRlXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB0aGlzLnNlbGVjdElucHV0Qm94VGFiKF8uZmlyc3QoJHRhYnMpLCAkZWwpO1xuXG4gICAgcmV0dXJuICRlbDtcbiAgfSxcblxuXG5cblxuXG4gIC8qKlxuICAgKiBDcmVhIElucHV0Qm94LCBjb21vIGVsZW1lbnRvIERvbVxuICAgKiB1biBJbnB1dEJveCBlcyB1biBjb250ZW5lZG9yIGNvbiB1bmEgbGlzdGEgZGUgaW5wdXRzXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwcm9wcyAtIGNvbmZpZyBwYXJhIElucHV0XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhRGF5IC0gdmFsb3JlcyBkZSBpdGVtIHkgRGlhLCBvcGNpb25hbFxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBkZWwgaW5wdXQgY3JlYWRvXG4gICAqL1xuICBjcmVhdGVJbnB1dEJveChwcm9wcywgZGF0YURheSkge1xuICAgIGxldCB2YWx1ZSA9IFtdO1xuICAgIGlmIChkYXRhRGF5ICYmIGRhdGFEYXkudmFsdWVzKSB7XG4gICAgICB2YWx1ZSA9IHV0aWxzLmdldFZhckJ5UGF0aChkYXRhRGF5LCBwcm9wcy52YXJOYW1lKTtcbiAgICB9XG5cbiAgICBsZXQgdGFic0NvbnRhaW5lciA9IFwiXCI7XG5cbiAgICBpZiAocHJvcHMudGFicykge1xuICAgICAgbGV0IHRhYnMgPSBcIlwiO1xuICAgICAgcHJvcHMudGFicy5mb3JFYWNoKCh0YWIpID0+IHtcbiAgICAgICAgdGFicyArPSBgXG4gICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1ib3gtdGFiXCIgdGFiLWtleT1cIiR7dGFiLmtleX1cIj5cbiAgICAgICAgICAke3RhYi5uYW1lfVxuICAgICAgICA8L2Rpdj5gO1xuICAgICAgfSk7XG5cbiAgICAgIHRhYnNDb250YWluZXIgPSBgXG4gICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1ib3gtdGFiLWNvbnRhaW5lclwiPlxuICAgICAgICAke3RhYnN9XG4gICAgICAgIDwvZGl2PlxuICAgICAgYDtcbiAgICB9XG5cbiAgICBsZXQgY2xvc2VJY29uID0gYDxzcGFuIGNsYXNzPVwiY2xvc2UtaWNvblwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxzdmcgc3R5bGU9XCJ3aWR0aDoyNHB4O2hlaWdodDoyNHB4XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBmaWxsPVwiY3VycmVudENvbG9yXCIgZD1cIk0xOSw2LjQxTDE3LjU5LDVMMTIsMTAuNTlMNi40MSw1TDUsNi40MUwxMC41OSwxMkw1LDE3LjU5TDYuNDEsMTlMMTIsMTMuNDFMMTcuNTksMTlMMTksMTcuNTlMMTMuNDEsMTJMMTksNi40MVpcIiAvPlxuICAgICAgICAgICAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgICAgICAgICAgICA8L3NwYW4+YDtcblxuICAgIGxldCBsaW5rSWNvbiA9IGAgPHNwYW4gY2xhc3M9XCJjbG9zZS1pY29uXCI+XG4gICAgICAgICAgICAgICAgICAgICAgPHN2ZyBzdHlsZT1cIndpZHRoOjI0cHg7aGVpZ2h0OjI0cHhcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGZpbGw9XCJjdXJyZW50Q29sb3JcIiBkPVwiTTE0LDNWNUgxNy41OUw3Ljc2LDE0LjgzTDkuMTcsMTYuMjRMMTksNi40MVYxMEgyMVYzTTE5LDE5SDVWNUgxMlYzSDVDMy44OSwzIDMsMy45IDMsNVYxOUEyLDIgMCAwLDAgNSwyMUgxOUEyLDIgMCAwLDAgMjEsMTlWMTJIMTlWMTlaXCIgLz5cbiAgICAgICAgICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgIGA7XG5cbiAgICBsZXQgc2VhcmNoSW5wdXQ9IGBcbiAgICAgIDxkaXYgY2xhc3M9XCJzZWFyY2gtaW5wdXQtY29udGFpbmVyXCI+XG4gICAgICAgIDxpbnB1dCBpZD1cIlwiIHR5cGU9XCJ0ZXh0XCIgbmFtZT1cIlwiIGNsYXNzPVwic2VhcmNoLWlucHV0XCIgcGxhY2Vob2xkZXI9XCJidXNjYXJcIj5cbiAgICAgICAgPGJ1dHRvbiBjbGFzcz1cInNlYXJjaC1pbnB1dC1jbGVhclwiPlxuICAgICAgICAgJHtjbG9zZUljb259XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgYDtcblxuXG5cbiAgICBsZXQgc3RyID0gYFxuICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb25cIiBpbnB1dC1rZXk9XCIke3Byb3BzLmtleSB8fCBcIlwifVwiPlxuICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtc3VidGl0bGUgZC1ibG9ja1wiPlxuICAgICAgICAgICAgICAke3Byb3BzLmxhYmVsfVxuICAgICAgICAgICAgPC9zcGFuPlxuXG4gICAgICAgICAgICAke3RhYnNDb250YWluZXJ9XG4gICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1ib3ggXCIgaW5wdXQta2V5PVwiJHtwcm9wcy5rZXkgfHwgXCJcIn1cIj5cblxuICAgICAgICAgICAgJHtzZWFyY2hJbnB1dH1cbiAgICAgIGA7XG5cbiAgICBpZiAocHJvcHMuaW5wdXRzKSB7XG4gICAgICBwcm9wcy5pbnB1dHMuZm9yRWFjaCgoaSkgPT4ge1xuICAgICAgICBpZihpLmlzVGl0bGUpe1xuXG4gICAgICAgICAgbGV0IHRvb2x0aXAgPSBcIlwiO1xuICAgICAgICAgIGxldCBpY29uID0gXCJcIjtcblxuICAgICAgICAgIGlmIChpLnRvb2x0aXApIHtcbiAgICAgICAgICAgIHRvb2x0aXAgPSBgXG4gICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWluaS1pbnB1dC1zZWN0aW9uLS10b29sdGlwXCI+XG4gICAgICAgICAgICAgICAgICAgICR7aS50b29sdGlwfVxuICAgICAgICAgICAgICAgICAgICAke2kuc3VmZml4ID8gXCIoXCIgKyBpLnN1ZmZpeCArIFwiKVwiIDogXCJcIn1cbiAgICAgICAgICAgICAgICAgIDwvZGl2PmA7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGkuY29sb3JJY29uKSB7XG4gICAgICAgICAgICBpZiAodXRpbHMuaXNIZXhDb2xvcihpLmNvbG9ySWNvbikpIHtcbiAgICAgICAgICAgICAgaWNvbiA9IGA8ZGl2IGNsYXNzPVwibWluaS1pbnB1dC1zZWN0aW9uLS1pY29uXCIgc3R5bGU9XCJiYWNrZ3JvdW5kOiR7aS5jb2xvckljb259XCI+IDwvZGl2PmA7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBpY29uID0gYDxkaXYgY2xhc3M9XCJtaW5pLWlucHV0LXNlY3Rpb24tLWljb24gJHtpLmNvbG9ySWNvbn1cIj4gPC9kaXY+YDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cblxuICAgICAgICBzdHIgKz0gYFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1pbmktaW5wdXQtc2VjdGlvbiBpcy10aXRsZVwiIGlucHV0LXRhYi1rZXk9XCIke2kudGFiS2V5IHx8IFwiXCJ9XCIgbGFiZWw9XCIke2kubGFiZWx9XCI+XG4gICAgICAgICAgICAgIDxsYWJlbD5cbiAgICAgICAgICAgICAgICAke2ljb259XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1pbmktaW5wdXQtc2VjdGlvbi0tdGl0bGUgdHJ1bmNhdGVcIj5cbiAgICAgICAgICAgICAgICAgICR7aS5sYWJlbH1cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgICAgICAgJHt0b29sdGlwfVxuICAgICAgICAgICAgPC9kaXY+YDtcblxuXG5cbiAgICAgICAgfWVsc2V7XG4gICAgICAgICAgbGV0IHZhbHVlX2ZvdW5kID0gdmFsdWUgPyB2YWx1ZS5maW5kKCh2YWwpID0+IHZhbC5pZCA9PSBpLmlkKSA6IG51bGw7XG4gICAgICAgICAgbGV0IHYgPSB2YWx1ZV9mb3VuZCB8fCBcIlwiO1xuICAgICAgICAgIGxldCBpbnB1dFZhbHVlID1wcm9wcy52YXJOYW1lSW5wdXQgJiYgdltwcm9wcy52YXJOYW1lSW5wdXQgXSA/IHZbcHJvcHMudmFyTmFtZUlucHV0IF0gOiB2LnZhbHVlO1xuICAgICAgICAgIGxldCB0b29sdGlwID0gXCJcIjtcbiAgICAgICAgICBsZXQgaWNvbiA9IFwiXCI7XG4gICAgICAgICAgbGV0IGxpbmsgPSBcIlwiO1xuXG4gICAgICAgICAgaWYgKGkudG9vbHRpcCkge1xuICAgICAgICAgICAgdG9vbHRpcCA9IGBcbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtaW5pLWlucHV0LXNlY3Rpb24tLXRvb2x0aXBcIj5cbiAgICAgICAgICAgICAgICAgICAgJHtpLnRvb2x0aXB9XG4gICAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChpLmNvbG9ySWNvbikge1xuICAgICAgICAgICAgaWYgKHV0aWxzLmlzSGV4Q29sb3IoaS5jb2xvckljb24pKSB7XG4gICAgICAgICAgICAgIGljb24gPSBgPGRpdiBjbGFzcz1cIm1pbmktaW5wdXQtc2VjdGlvbi0taWNvblwiIHN0eWxlPVwiYmFja2dyb3VuZDoke2kuY29sb3JJY29ufVwiPiA8L2Rpdj5gO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaWNvbiA9IGA8ZGl2IGNsYXNzPVwibWluaS1pbnB1dC1zZWN0aW9uLS1pY29uICR7aS5jb2xvckljb259XCI+IDwvZGl2PmA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYoaS5saW5rKXtcbiAgICAgICAgICAgIGxpbmsgPSBgPGEgY2xhc3M9XCJtaW5pLWlucHV0LXNlY3Rpb24tLWxpbmtcIiB0YXJnZXQ9XCJfYmxhbmtcIiBocmVmPVwiJHtpLmxpbmt9XCI+XG4gICAgICAgICAgICAgICAgJHtsaW5rSWNvbn1cbiAgICAgICAgICAgICAgICA8L2E+IGBcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBzdHIgKz0gYFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1pbmktaW5wdXQtc2VjdGlvblwiIGlucHV0LXRhYi1rZXk9XCIke2kudGFiS2V5IHx8IFwiXCJ9XCIgbGFiZWw9XCIke2kubGFiZWx9XCI+XG4gICAgICAgICAgICAgIDxsYWJlbD5cbiAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cIm51bWJlclwiXG4gICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJtaW5pLWlucHV0XCJcbiAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1pZD1cIiR7aS5pZCB8fCBcIlwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgaW5wdXQta2V5PVwiJHtpLmtleSB8fCBpLmxhYmVsfVwiXG4gICAgICAgICAgICAgICAgICAgICAgdmFsdWU9XCIke2lucHV0VmFsdWUgfHwgXCJcIn1cIj5cblxuICAgICAgICAgICAgICAgICR7aWNvbn1cblxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtaW5pLWlucHV0LXNlY3Rpb24tLW5hbWUgdHJ1bmNhdGVcIj5cbiAgICAgICAgICAgICAgICAgICR7aS5sYWJlbH1cbiAgICAgICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtaW5pLWlucHV0LXNlY3Rpb24tLXN1ZmZpeFwiID4ke1xuICAgICAgICAgICAgICAgICAgaS5zdWZmaXggPyBcIihcIiArIGkuc3VmZml4ICsgXCIpXCIgOiBcIlwiXG4gICAgICAgICAgICAgICAgfTwvZGl2PlxuXG4gICAgICAgICAgICAgICAgJHtsaW5rfVxuXG4gICAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgICAgICR7dG9vbHRpcH1cbiAgICAgICAgICAgIDwvZGl2PmA7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHN0ciArPSBgXG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+IGA7XG5cbiAgICBsZXQgJGVsID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChzdHIpO1xuICAgIGxldCAkdGFicyA9ICRlbC5xdWVyeVNlbGVjdG9yQWxsKFwiLmlucHV0LWJveC10YWJbdGFiLWtleV1cIikgfHwgW107XG4gICAgbGV0ICRpbnB1dHMgPSAkZWwucXVlcnlTZWxlY3RvckFsbChcImlucHV0Lm1pbmktaW5wdXRcIikgfHwgW107XG4gICAgbGV0ICRzZWFyY2hJbnB1dCA9ICRlbC5xdWVyeVNlbGVjdG9yKFwiLnNlYXJjaC1pbnB1dFwiKSB8fCBudWxsO1xuICAgIGxldCAkc2VhcmNoSW5wdXRDbGVhciA9ICRlbC5xdWVyeVNlbGVjdG9yKFwiLnNlYXJjaC1pbnB1dC1jbGVhclwiKSB8fCBudWxsO1xuXG4gICAgJHRhYnMuZm9yRWFjaCgodCkgPT4ge1xuICAgICAgdC5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGUpID0+IHtcbiAgICAgICAgdGhpcy5zZWxlY3RJbnB1dEJveFRhYih0LCAkZWwpO1xuICAgICAgICAkc2VhcmNoSW5wdXQudmFsdWUgPSBcIlwiO1xuICAgICAgICAkc2VhcmNoSW5wdXQuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoJ2lucHV0Jywge2J1YmJsZXM6dHJ1ZX0pKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaWYoJHNlYXJjaElucHV0Q2xlYXIpe1xuICAgICAgJHNlYXJjaElucHV0Q2xlYXIuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGUgPT4ge1xuICAgICAgICAkc2VhcmNoSW5wdXQudmFsdWUgPSBcIlwiO1xuICAgICAgICAkc2VhcmNoSW5wdXQuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoJ2lucHV0Jywge2J1YmJsZXM6dHJ1ZX0pKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmKCRzZWFyY2hJbnB1dCl7XG4gICAgICAkc2VhcmNoSW5wdXQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsZSA9PiB7XG4gICAgICAgIGlmKGUua2V5ID09PSBcIkVzY2FwZVwiKXtcbiAgICAgICAgICAkc2VhcmNoSW5wdXQudmFsdWUgPSBcIlwiO1xuICAgICAgICAgICRzZWFyY2hJbnB1dC5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudCgnaW5wdXQnLCB7YnViYmxlczp0cnVlfSkpO1xuICAgICAgICB9XG4gICAgICB9KTsgXG5cbiAgICAgICRzZWFyY2hJbnB1dC5hZGRFdmVudExpc3RlbmVyKFwiaW5wdXRcIiwgZSA9PiB7XG4gICAgICAgIGxldCAkdGFiU2VsZWN0ZWQgPSAkZWwucXVlcnlTZWxlY3RvcihcIi5pbnB1dC1ib3gtdGFiW3RhYi1rZXldLmFjdGl2ZVwiKSB8fCBudWxsO1xuICAgICAgICBsZXQgJGlucHV0cyA9IFtdO1xuICAgICAgICBpZigkdGFiU2VsZWN0ZWQpe1xuICAgICAgICAgIGxldCB0YWJLZXkgPSAkdGFiU2VsZWN0ZWQuZ2V0QXR0cmlidXRlKFwidGFiLWtleVwiKTtcbiAgICAgICAgICAkaW5wdXRzID0gJGVsLnF1ZXJ5U2VsZWN0b3JBbGwoXCIubWluaS1pbnB1dC1zZWN0aW9uW2lucHV0LXRhYi1rZXk9J1wiK3RhYktleStcIiddXCIpIHx8IFtdO1xuICAgICAgICB9ZWxzZXtcbiAgICAgICAgICAkaW5wdXRzID0gJGVsLnF1ZXJ5U2VsZWN0b3JBbGwoXCIubWluaS1pbnB1dC1zZWN0aW9uXCIpIHx8IFtdO1xuICAgICAgICB9XG4gICAgICAgICRpbnB1dHMuZm9yRWFjaCgkaSA9PiB7XG4gICAgICAgICAgbGV0IGxhYmVsID0gJGkuZ2V0QXR0cmlidXRlKFwibGFiZWxcIik7XG4gICAgICAgICAgbGV0IHNlYXJjaCA9ICRzZWFyY2hJbnB1dC52YWx1ZTtcbiAgICAgICAgICBpZihsYWJlbC50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHNlYXJjaC50b0xvd2VyQ2FzZSgpKSl7XG4gICAgICAgICAgICAkaS5jbGFzc0xpc3QucmVtb3ZlKFwiaGlkZVwiKTtcbiAgICAgICAgICB9ZWxzZXtcbiAgICAgICAgICAgICRpLmNsYXNzTGlzdC5hZGQoXCJoaWRlXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB0aGlzLnNlbGVjdElucHV0Qm94VGFiKF8uZmlyc3QoJHRhYnMpLCAkZWwpO1xuXG4gICAgJGlucHV0cy5mb3JFYWNoKChpKSA9PiB0aGlzLmFkZEtleURvd25JbnB1dEV2ZW50cyhpKSk7XG5cbiAgICByZXR1cm4gJGVsO1xuICB9LFxuXG4gIHNlbGVjdElucHV0Qm94VGFiKCR0YWIsICRlbCkge1xuICAgIGxldCAkdGFicyA9ICRlbC5xdWVyeVNlbGVjdG9yQWxsKFwiLmlucHV0LWJveC10YWJbdGFiLWtleV1cIikgfHwgW107XG4gICAgbGV0ICRpbnB1dFNlY3Rpb25zID0gJGVsLnF1ZXJ5U2VsZWN0b3JBbGwoXCIubWluaS1pbnB1dC1zZWN0aW9uXCIpIHx8IFtdO1xuXG4gICAgJHRhYnMuZm9yRWFjaCgodCkgPT4ge1xuICAgICAgdC5jbGFzc0xpc3QucmVtb3ZlKFwiYWN0aXZlXCIpO1xuICAgIH0pO1xuXG4gICAgaWYgKCR0YWIpIHtcbiAgICAgICR0YWIuY2xhc3NMaXN0LmFkZChcImFjdGl2ZVwiKTtcblxuICAgICAgJGlucHV0U2VjdGlvbnMuZm9yRWFjaCgoaSkgPT4ge1xuICAgICAgICBsZXQga2V5ID0gaS5nZXRBdHRyaWJ1dGUoXCJpbnB1dC10YWIta2V5XCIpO1xuICAgICAgICBpZiAoa2V5ID09ICR0YWIuZ2V0QXR0cmlidXRlKFwidGFiLWtleVwiKSkge1xuICAgICAgICAgIGkuY2xhc3NMaXN0LnJlbW92ZShcImhpZGVcIik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaS5jbGFzc0xpc3QuYWRkKFwiaGlkZVwiKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9LFxuXG4gIC8qKlxuICAgKiBDcmVhIENoZWNrYm94LCBjb21vIGVsZW1lbnRvIERvbVxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gcHJvcHMgLSBjb25maWcgcGFyYSBJbnB1dFxuICAgKiBAcGFyYW0ge09iamVjdH0gZGF0YURheSAtIHZhbG9yZXMgZGUgaXRlbSB5IERpYSwgb3BjaW9uYWxcbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gZGVsIGlucHV0IGNyZWFkb1xuICAgKi9cbiAgY3JlYXRlSW5wdXRDaGVja2JveChwcm9wcywgZGF0YURheSkge1xuICAgIGxldCB2YWx1ZSA9IFwiXCI7XG4gICAgaWYgKGRhdGFEYXkgJiYgZGF0YURheS52YWx1ZXMpIHtcbiAgICAgIHZhbHVlID0gdXRpbHMuZ2V0VmFyQnlQYXRoKGRhdGFEYXksIHByb3BzLnZhck5hbWUpO1xuICAgIH1cbiAgICBsZXQgciA9IGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoYFxuICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb25cIiBpbnB1dC1rZXk9XCIke3Byb3BzLmtleSB8fCBcIlwifVwiPlxuICAgICAgICA8bGFiZWw+XG4gICAgICAgICAgPGlucHV0IHR5cGU9XCJjaGVja2JveFwiIG5hbWU9XCIke3Byb3BzLmtleSB8fCBcIlwifVwiIGlucHV0LWtleT1cIiR7XG4gICAgICBwcm9wcy5rZXkgfHwgXCJcIlxuICAgIH1cIiAke3ZhbHVlID8gXCJjaGVja2VkXCIgOiBcIlwifT5cbiAgICAgICAgICAke3Byb3BzLmxhYmVsfVxuICAgICAgICA8L2xhYmVsPlxuICAgICAgPC9kaXY+YCk7XG5cbiAgICByZXR1cm4gcjtcbiAgfSxcblxuICBjcmVhdGVJbnB1dEJ1dHRvbihwcm9wcykge1xuICAgIGxldCByID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChgXG4gICAgICA8ZGl2IGNsYXNzPVwiaW5wdXQtc2VjdGlvblwiIGlucHV0LWtleT1cIiR7cHJvcHMua2V5IHx8IFwiXCJ9XCI+XG4gICAgICAgICAgPGJ1dHRvbiBuYW1lPVwiJHtwcm9wcy5rZXkgfHwgXCJcIn1cIiBpbnB1dC1rZXk9XCIkeyBwcm9wcy5rZXkgfHwgXCJcIiB9XCIgIGNsYXNzPVwiY2FwLWJ0bi1vdXRsaW5lXCI+XG4gICAgICAgICAgICAke3Byb3BzLmxhYmVsfVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+YCk7XG5cbiAgICBsZXQgYnV0dG9uID0gci5xdWVyeVNlbGVjdG9yKFwiYnV0dG9uXCIpO1xuICAgIGJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgZSA9PiBwcm9wcy5vbkNsaWNrKHtwcm9wcywgZXZlbnQ6ZX0pKVxuXG4gICAgcmV0dXJuIHI7XG4gIH0sXG5cbiAgYWRkS2V5RG93bklucHV0RXZlbnRzKGlucHV0KSB7XG4gICAgaW5wdXQuYWRkRXZlbnRMaXN0ZW5lcihcImtleWRvd25cIiwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICBpZiAoZXZlbnQua2V5Q29kZSA9PT0gMTMpIHtcbiAgICAgICAgLy9FTlRFUlxuICAgICAgICBpbnB1dC5kaXNwYXRjaEV2ZW50KFxuICAgICAgICAgIG5ldyBDdXN0b21FdmVudChcInNhdmVNdWx0aUlucHV0XCIsIHtcbiAgICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKGV2ZW50LmtleUNvZGUgPT09IDI3KSB7XG4gICAgICAgIC8vRVNDXG4gICAgICAgIGlucHV0LmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwiY2FuY2VsTXVsdGlJbnB1dFwiLCB7XG4gICAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSxcblxuICBjcmVhdGVDb250ZXh0TWVudSh7XG4gICAgY29uZmlnLFxuICAgICRjYXBpYmFyYUVsZW0gPSBudWxsLFxuICAgIGV2dCA9IG51bGwsXG4gICAgZGF0ZSA9IG51bGwsXG4gICAgaXRlbSA9IG51bGwsXG4gICAgc2VsZWN0ZWQgPSBbXSxcbiAgICB0YWJTZWxlY3RlZCA9IG51bGwsXG4gICAgbGVmdCA9IG51bGwsXG4gICAgdG9wID0gbnVsbCxcbiAgICBuYW1lID0gXCJcIixcbiAgfSkge1xuICAgIGlmIChjb25maWcudGltZWxpbmUuY29udGV4dE1lbnUgPT09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB7IGVsZW06IG51bGwsIGlzVmlzaWJsZTogZmFsc2UgfTtcblxuICAgIGxldCBjbGFzc05hbWUgPSBcIlwiO1xuICAgIGxldCBzdHlsZSA9IFwiXCI7XG4gICAgbGV0IHN0ckh0bWwgPSBcIlwiO1xuICAgIGxldCBsZWZ0UG9zaXRpb24gPSBudWxsO1xuICAgIGxldCB0b3BQb3NpdGlvbiA9IG51bGw7XG4gICAgbGV0IGlzVmlzaWJsZSA9IHRydWU7XG4gICAgbGV0IGJvdW5kUmVjdENhcGliYXJhID0gbnVsbDtcbiAgICBsZXQgZ2FwID0gMTU7IC8vcHhcblxuICAgIGlmKCRjYXBpYmFyYUVsZW0pe1xuICAgICAgYm91bmRSZWN0Q2FwaWJhcmEgPSAkY2FwaWJhcmFFbGVtLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIH1cblxuICAgIGlmIChldnQgJiYgYm91bmRSZWN0Q2FwaWJhcmEpIHtcbiAgICAgIGxlZnQgPSBldnQuY2xpZW50WDtcbiAgICAgIHRvcCA9IGV2dC5jbGllbnRZIC0gYm91bmRSZWN0Q2FwaWJhcmEudG9wO1xuICAgIH1cblxuICAgIGlmIChsZWZ0KSB7XG4gICAgICBsZWZ0UG9zaXRpb24gPSBsZWZ0O1xuICAgIH1cblxuICAgIGlmICh0b3ApIHtcbiAgICAgIHRvcFBvc2l0aW9uID0gdG9wO1xuICAgIH1cblxuXG5cbiAgICBpZiAoKGxlZnRQb3NpdGlvbiAhPT0gbnVsbCkgJiAodG9wUG9zaXRpb24gIT09IG51bGwpKSB7XG5cblxuICAgICAgaWYoYm91bmRSZWN0Q2FwaWJhcmEpe1xuICAgICAgICBsZXQgdHJhbnNmb3JtU3R5bGUgPSBcIlwiO1xuICAgICAgICBpZih0b3BQb3NpdGlvbiA+IGJvdW5kUmVjdENhcGliYXJhLmhlaWdodCoyLzYgJiYgdG9wUG9zaXRpb24gPD0gYm91bmRSZWN0Q2FwaWJhcmEuaGVpZ2h0KjQvNil7XG4gICAgICAgICAgdHJhbnNmb3JtU3R5bGUrPSBgdHJhbnNsYXRlWSgtNTAlKWA7XG4gICAgICAgIH1cbiAgICAgICAgaWYodG9wUG9zaXRpb24gPiBib3VuZFJlY3RDYXBpYmFyYS5oZWlnaHQqNC82KXtcbiAgICAgICAgICB0cmFuc2Zvcm1TdHlsZSs9IGB0cmFuc2xhdGVZKC0xMDAlKWA7XG4gICAgICAgIH1cblxuICAgICAgICBpZihsZWZ0UG9zaXRpb24+IGJvdW5kUmVjdENhcGliYXJhLndpZHRoKjQvNil7XG4gICAgICAgICAgdHJhbnNmb3JtU3R5bGUrPSBgdHJhbnNsYXRlWCgtMTAwJSlgO1xuICAgICAgICAgIGxlZnRQb3NpdGlvbiAtPSBnYXA7XG4gICAgICAgIH1lbHNle1xuICAgICAgICAgIGxlZnRQb3NpdGlvbiArPSBnYXA7XG4gICAgICAgIH1cbiAgICAgICAgaWYodHJhbnNmb3JtU3R5bGUgIT1cIlwiKXtcbiAgICAgICAgICAgIHN0eWxlICs9IGAgdHJhbnNmb3JtOiAke3RyYW5zZm9ybVN0eWxlfTtgO1xuICAgICAgICB9XG4gICAgICB9XG5cblxuICAgICAgc3R5bGUgKz0gYHRvcDogJHt0b3BQb3NpdGlvbn1weDsgbGVmdDogJHtsZWZ0UG9zaXRpb259cHg7YDtcblxuICAgIH0gZWxzZSB7XG4gICAgICBjbGFzc05hbWUgKz0gXCJjbS1oaWRlXCI7XG4gICAgICBpc1Zpc2libGUgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBzdHJIdG1sICs9IGAgPGRpdiBjbGFzcz1cImNhcC1jb250ZXh0LW1lbnUtY29udGFpbmVyICR7Y2xhc3NOYW1lfVwiPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY2FwLWNvbnRleHQtbWVudVwiIHN0eWxlPVwiJHtzdHlsZX1cIj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgIDwvZGl2PmA7XG5cbiAgICBsZXQgJGNvbnRleHRNZW51Q29udGFpbmVyID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChzdHJIdG1sKTtcbiAgICBsZXQgJGNvbnRleHRNZW51ID0gJGNvbnRleHRNZW51Q29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoXCIuY2FwLWNvbnRleHQtbWVudVwiKTtcblxuICAgIGNvbmZpZy50aW1lbGluZS5jb250ZXh0TWVudS5vcHRpb25zLmZvckVhY2goKG9wdGlvbikgPT4ge1xuXG4gICAgICBpZiAob3B0aW9uLnNob3dJZikge1xuICAgICAgICBsZXQgc2hvdyA9IG9wdGlvbi5zaG93SWYoeyBpdGVtLCBkYXRlLCBzZWxlY3RlZCwgbmFtZSwgdGFiU2VsZWN0ZWQgfSk7XG4gICAgICAgIGlmICghc2hvdykgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBsZXQgaXNFbmFibGVkID0gdHJ1ZTtcbiAgICAgIGxldCBpc0NsaWNrZWFibGUgPSB0cnVlO1xuICAgICAgaWYgKG9wdGlvbi5lbmFibGVJZikge1xuICAgICAgICBpc0VuYWJsZWQgPSBvcHRpb24uZW5hYmxlSWYoe1xuICAgICAgICAgIGl0ZW0sXG4gICAgICAgICAgZGF0ZSxcbiAgICAgICAgICBzZWxlY3RlZCxcbiAgICAgICAgICBuYW1lLFxuICAgICAgICAgIHRhYlNlbGVjdGVkLFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgbGV0IG9wdGlvbkNsYXNzTmFtZSA9IFwiXCI7XG4gICAgICBsZXQgc3RySWNvbiA9IFwiXCI7XG4gICAgICBsZXQgbGFiZWwgPSBcIlwiO1xuXG4gICAgICBpZiAoIWlzRW5hYmxlZCkge1xuICAgICAgICBvcHRpb25DbGFzc05hbWUgKz0gXCJpcy1kaXNhYmxlZCBcIjtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbi5pc0RpdmlkZXIpIHtcbiAgICAgICAgaXNDbGlja2VhYmxlID0gZmFsc2U7XG4gICAgICAgIG9wdGlvbkNsYXNzTmFtZSArPSBcImlzLWRpdmlkZXIgXCI7XG4gICAgICB9XG5cbiAgICAgIGlmKG9wdGlvbi5sYWJlbCl7XG4gICAgICAgIGxhYmVsID0gYDxzcGFuPiR7b3B0aW9uLmxhYmVsfTwvc3Bhbj5gO1xuICAgICAgfVxuXG5cbiAgICAgIGlmIChvcHRpb24uaWNvbikge1xuICAgICAgICBzdHJJY29uID0gYDxkaXYgY2xhc3M9XCJjYXAtY29udGV4dC1tZW51X2l0ZW1faWNvblwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxzdmcgdmlld0JveD1cIjAgMCAyNCAyNFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHBhdGggZD1cIiR7b3B0aW9uLmljb259XCIgLz5cbiAgICAgICAgICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgICAgICAgIDwvZGl2PmA7XG4gICAgICB9XG5cbiAgICAgIGxldCBvcHRpb25TdHJIdG1sID0gYFxuICAgICAgICA8ZGl2IGNsYXNzPVwiY2FwLWNvbnRleHQtbWVudV9pdGVtICR7b3B0aW9uQ2xhc3NOYW1lfVwiPlxuICAgICAgICAgICR7c3RySWNvbn1cbiAgICAgICAgICAke2xhYmVsfVxuICAgICAgICA8L2Rpdj5gO1xuXG4gICAgICBsZXQgJG9wdGlvbiA9IGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwob3B0aW9uU3RySHRtbCk7XG5cbiAgICAgIGlmIChpc0VuYWJsZWQgJiYgaXNDbGlja2VhYmxlKSB7XG4gICAgICAgICRvcHRpb24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIChldnRDbGljaykgPT5cbiAgICAgICAgICBvcHRpb24ub25DbGljayh7XG4gICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICBldnQ6IGV2dENsaWNrLFxuICAgICAgICAgICAgZGF0ZSxcbiAgICAgICAgICAgIGl0ZW0sXG4gICAgICAgICAgICBzZWxlY3RlZCxcbiAgICAgICAgICAgIHRhYlNlbGVjdGVkLFxuICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAkb3B0aW9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCAoZXZ0Q2xpY2spID0+IHtcbiAgICAgICAgICBldnRDbGljay5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgIGV2dENsaWNrLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgJGNvbnRleHRNZW51LmFwcGVuZCgkb3B0aW9uKTtcbiAgICB9KTtcblxuICAgIHJldHVybiB7XG4gICAgICBlbGVtOiAkY29udGV4dE1lbnVDb250YWluZXIsXG4gICAgICBpc1Zpc2libGUsXG4gICAgfTtcbiAgfSxcbn07XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFFQTtBQUFBO0FBQUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQURBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBREE7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUVBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFGQTtBQUZBO0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUZBO0FBRkE7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFRQTtBQVFBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRkE7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBSEE7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBRUE7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUdBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFGQTtBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBSEE7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUZBO0FBS0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBREE7QUFIQTtBQVFBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBREE7QUFIQTtBQVFBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBREE7QUFIQTtBQVFBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUZBO0FBSEE7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBREE7QUFIQTtBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFEQTtBQUhBO0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBS0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUpBO0FBSEE7QUFXQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRkE7QUFIQTtBQVNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUlBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFHQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSEE7QUFIQTtBQVVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQU9BO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUE3Q0E7QUErQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQTdDQTtBQStDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQTdDQTtBQStDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBN0NBO0FBK0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUdBO0FBQ0E7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFKQTtBQUhBO0FBV0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUZBO0FBS0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUZBO0FBS0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUhBO0FBSEE7QUFVQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBTkE7QUFIQTtBQWFBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFIQTtBQUhBO0FBVUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUZBO0FBSEE7QUFXQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVFBO0FBQ0E7QUFBQTtBQUNBO0FBREE7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSkE7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQU1BO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUZBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFEQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBRUE7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSEE7QUFIQTtBQVVBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUhBO0FBSEE7QUFVQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQUE7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUZBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUZBO0FBSUE7QUFDQTtBQUNBO0FBRkE7QUFJQTtBQUdBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUZBO0FBS0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUZBO0FBS0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQWhEQTtBQUNBO0FBa0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFGQTtBQUhBO0FBU0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUZBO0FBSEE7QUFTQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBRUE7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBTUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRkE7QUFLQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUZBO0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBVkE7QUFZQTtBQUNBO0FBQUE7QUFBQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUdBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUxBO0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBTkE7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFGQTtBQUlBO0FBQ0E7QUE5eUhBIiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./src/util/tableElements.js\n");
|
|
246
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _util_domUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/domUtils */ \"./src/util/domUtils.js\");\n/* harmony import */ var _util_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/utils */ \"./src/util/utils.js\");\n/* harmony import */ var _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../util/dateUtils */ \"./src/util/dateUtils.js\");\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n /**\n * Crea elemento Table\n * Contendrá los elementos que apareceran dentro de la tabla de planilla\n * Se Usa para :\n * - Agregar background con patron estilo tabla\n * - Agregar dayMouseOver, div que indica posicion de mouse\n * - Agregar DetailDay, para detalles de datos en tabla\n * - Agregar SelectedContainer, para dias seleccionados\n * - Agregar FloatBoxContainer, para visualizacion de datos en tabla\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom creado\n */\n createAgTable(config) {\n let e = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"capibara\"\n });\n\n if (config.timeline.dark) {\n e.classList.add(\"dark-theme\");\n }\n\n if (config.timeline.header.extend.isShow) {\n e.classList.add(\"header-extended\");\n }\n\n return e;\n },\n\n /**\n * Recrea Background, que es el fondo grid, como tabla\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} $elem - Elemento relacionado, donde se cre el background\n * @return {Object} Elemento Dom Corner Footer\n */\n redrawBackground(config, $elem) {\n return this.createBackground(config, $elem);\n },\n\n /**\n * Crea y posiciona fondo de tabla\n * Este fondo contiene un patron de CSS que le da la apariencia de tabla\n * por lo cual se debe reposicionar segun la fecha de inicio, para hacer\n * calzar los fines de semana\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} [$elem = null] - Elemento background, si es null, lo crea\n * @return {Object} elemento Dom Background\n */\n createBackground(config, $elem = null) {\n let {\n height,\n width,\n dayWidth\n } = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getTableDimensions(config);\n let start = new Date(config.timeline.start);\n let end = new Date(config.timeline.end);\n end.setTime(end.getTime() + _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].dayInMilliseconds); // add 24 hours\n\n let dCorrected = new Date(start.valueOf() + start.getTimezoneOffset() * 60000);\n let weekDay = dCorrected.getDay();\n let diffWeekDays = (weekDay - 1) * dayWidth * -1;\n $elem = $elem || _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"background-grid\"\n });\n $elem.style[\"background-position\"] = diffWeekDays + \"px 0, 0 0, \" + diffWeekDays + \"px 0\";\n $elem.style.width = width + \"px\";\n $elem.style.height = height + 1 + \"px\";\n return $elem;\n },\n\n /**\n * Crea Plot Container Vertical\n * Los plots son elementos que agregan secciones de fondo en la planilla\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom plotVerticalContainer\n */\n createPlotVerticalContainer(config) {\n let $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"plot-vertical-container\"\n });\n return this.redrawPlotVerticalContainer(config, $elem);\n },\n\n createPlotHorizontalContainer(config) {\n let $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"plot-horizontal-container\"\n });\n return this.redrawPlotHorizontalContainer(config, $elem);\n },\n\n /**\n * Recrea plotVerticalContainer, usando elemento existente\n * usa un elemento existente para usar la funcion para redibujar el elemento\n *\n * Los Plots se insertan como divs, con posicion especificada,\n * con ancho de dia\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} $elem - Elemento Dom donde crea plotVerticalContainer\n * @return {Object} Elemento Dom plotVerticalContainer\n */\n redrawPlotVerticalContainer(config, $elem) {\n $elem.innerHTML = \"\";\n\n if (config.timeline.plots && config.timeline.plots.vertical) {\n let {\n height,\n dayWidth\n } = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getTableDimensions(config);\n config.timeline.plots.vertical.forEach(p => {\n let diffDays = Math.floor(_util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].diffDays(config.timeline.start, p.date));\n let left = diffDays * dayWidth;\n let plot = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n classNames: [\"plot-vertical\", p.className || \"\"],\n style: {\n \"margin-left\": left + \"px\",\n height: height + \"px\"\n }\n });\n $elem.appendChild(plot);\n });\n }\n\n return $elem;\n },\n\n redrawPlotHorizontalContainer(config, $elem) {\n $elem.innerHTML = \"\";\n\n if (config.timeline.plots && config.timeline.plots.horizontal) {\n let {\n width,\n itemHeight\n } = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getTableDimensions(config);\n config.timeline.plots.horizontal.forEach(p => {\n let item = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getItemById(config, p.idNode, p.typeNode);\n let topPosition = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getPositionByItem(config, item, \"parent\");\n let plot = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n classNames: [\"plot-horizontal\", p.className || \"\"],\n style: {\n \"margin-top\": topPosition * itemHeight + \"px\",\n width: width + \"px\"\n }\n });\n $elem.appendChild(plot);\n });\n }\n\n return $elem;\n },\n\n /**\n * Crea Corner Izquierdo\n * Se usa para :\n * - titulos relacionados con los datos del sidebar izquierdo\n * - titulos para inputs de header, absolute a la derecha\n * - boton para mostrar/ocultar sidebar izquierdo\n * - promedios\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom Corner\n */\n createCorner(config, tab = null) {\n let $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"corner\"\n });\n return this.redrawCorner($elem, config, tab);\n },\n\n redrawCorner($elem, config, tab = null) {\n let labelsInitialCorner = config.timeline.nav.left.initial.vars.filter(v => v.onlyTab == undefined || v.onlyTab && tab && v.onlyTab == tab.key).map(d => `<span class=\"item-col\">${d.label}</span>`).join(\"\");\n let labelsExtendCorner = config.timeline.nav.left.extend.vars.filter(v => v.onlyTab == undefined || v.onlyTab && tab && v.onlyTab == tab.key).map(d => `<span class=\"item-col\">${d.label}</span>`).join(\"\");\n let labelsHeaderExtend = config.timeline.header.extend.data.map(d => {\n if (d.isHidden) return \"\";\n let avg = \"\";\n let tooltip = \"\";\n let className = \"\";\n let isAccent = d.isAccent;\n\n if (d.average) {\n avg = ` <span class=\"average \"> ( <span> <span class=\"symbol\">x̄</span> ${d.average} </span>) </span> `;\n tooltip = `cap-tooltip=\"Promedio ${d.label} : ${d.average} ${d.suffix || \"\"}\"`;\n }\n\n if (d.color) {\n if (isAccent) {\n className = d.color ? \"c-\" + d.color + \"--background\" : \"\";\n } else {\n className = d.color ? \"c-\" + d.color + \"--text \" : \"\";\n }\n }\n\n return `<div class=\"input-title-container ${isAccent ? \"input-title--accent\" : \"\"} ${d.isPersistent ? \"persistent\" : \"\"}\">\n <span ${tooltip} class=\"input-title ${className}\">\n ${avg}\n ${d.label}\n </span>\n\n </div>`;\n }).join(\"\");\n let toggleSidebarBtnString = `\n <button toggle-sidebar class=\"cap-btn-icon cap-btn-icon-raised cap-btn-toggle-sidebar \">\n <span>\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z\" />\n </svg>\n </span>\n </button> `;\n\n if (config.timeline.nav.left.hideToggleSidebarButton) {\n toggleSidebarBtnString = \"\";\n }\n\n let template = `<div>\n\n ${toggleSidebarBtnString}\n <div class=\"corner-title\">\n <span class=\"bottom-text\">\n ${config.timeline.corner.left.label}\n </span>\n </div>\n\n <div class=\"initial-corner\">\n <div class=\"initial-corner-title\">\n <span class=\"bottom-container hide\">\n ${config.timeline.corner.initial.label}\n </span>\n\n <div class=\"bottom-container\">\n ${labelsInitialCorner}\n </div>\n\n </div>\n </div>\n\n\n <div class=\"extend-corner\">\n <div class=\"ex-corner-title\">\n <span class=\"bottom-container hide\">\n ${config.timeline.corner.extend.label}\n </span>\n\n <div class=\"bottom-container\">\n ${labelsExtendCorner}\n </div>\n\n </div>\n </div>\n\n\n <div class=\"cap-btn-nav-corner\">\n <div class=\"input-titles\">\n ${labelsHeaderExtend}\n </div>\n </div>\n\n <div class=\"progress-bar progress-bar-left hide-progress\"></div>\n\n </div>`;\n let r = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(template);\n $elem.innerHTML = \"\";\n $elem.append(r);\n let toggleSidebar = $elem.querySelector(\"[toggle-sidebar]\");\n\n if (toggleSidebar) {\n toggleSidebar.addEventListener(\"click\", e => {\n r.dispatchEvent(new CustomEvent(\"toggleSidebar\", {\n bubbles: true,\n cancelable: false\n }));\n });\n }\n\n return $elem;\n },\n\n /**\n * Crea Corner Derecho\n * Se usa para :\n * - titulos relacionados con los datos del sidebar Derecho\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom corner\n */\n createCornerRight(config, tab = null) {\n let $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n classNames: [\"corner\", \"right\"]\n });\n return this.redrawCornerRight($elem, config, tab);\n },\n\n redrawCornerRight($el, config, tab = null) {\n let label = \"\";\n\n if (config.timeline.corner.right.label) {\n ` <span>\n ${config.timeline.corner.right.label}\n </span>`;\n }\n\n let str = `\n <div class=\"corner-title\">\n ${label}\n <div class=\"btn-container\"></div>\n </div>\n <div class=\"progress-bar progress-bar-right hide-progress\"></div>\n `;\n $el.innerHTML = str.trim();\n let $btnContainer = $el.querySelector(\".btn-container\");\n\n if (config.timeline.corner.right.buttons) {\n config.timeline.corner.right.buttons.forEach(btn => {\n let isEnabled = btn.getIsEnabled ? btn.getIsEnabled() : true;\n\n if (isEnabled) {\n let $btn = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <button class=\"corner-btn cap-btn-raised\">\n ${btn.label || \"\"}\n </button> `);\n\n if (btn.onClick) {\n $btn.addEventListener(\"click\", btn.onClick);\n }\n\n $btnContainer.appendChild($btn);\n }\n });\n }\n\n if (config.timeline.corner.right.inputs) {\n config.timeline.corner.right.inputs.forEach(input => {\n let $input = this.createCornerRightInput({\n inputConfig: input\n });\n $btnContainer.appendChild($btn);\n });\n }\n\n return $el;\n },\n\n createCornerRightInput({\n inputConfig,\n dataDay = null,\n daySelected = null\n }) {\n let r = null;\n\n switch (inputConfig.type) {\n case 'autocomplete-crud':\n r = this.createCornerRightInputAutocompleteCrud({\n inputConfig,\n dataDay,\n daySelected\n });\n break;\n }\n\n return r;\n },\n\n createCornerRightInputAutocompleteCrud({\n inputConfig,\n dataDay,\n daySelected\n }) {\n let elem = \"test\";\n return elem;\n },\n\n /**\n * Crea Header Top\n * Se usa para :\n * - Manejo de tabs\n * - Botones de navegación y selección de fecha\n * - Boton toggle Dark mode\n * - Boton toggle Header extended\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom\n */\n createHeaderTop(config, tabSelected = null) {\n return this.redrawHeaderTop(config, tabSelected, _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\"));\n },\n\n redrawHeaderTop(config, tabSelected = null, $elem) {\n let str = `\n <div class=\"header-top\">`;\n\n if (config.timeline.tabs) {\n let showTabs = true;\n\n if (config.timeline.tabs.filter(t => !t.isHidden).length == 0) {\n showTabs = false;\n }\n\n if (showTabs) {\n str += ` <div class=\"tab-select-container c-d-desktop-none c-d-mobile-flex\">\n <select class=\"tabs-select\" >`;\n config.timeline.tabs.forEach(tab => {\n if (!tab.isHidden) {\n str += ` <option ${tab == tabSelected ? 'selected=\"selected\"' : \"\"} value=\"${tab.id}\"> ${tab.label} </option>`;\n }\n });\n str += `</select> </div>`;\n str += ` <div class=\"tabs-container c-d-desktop-flex c-d-mobile-none\">`;\n config.timeline.tabs.forEach(tab => {\n if (!tab.isHidden) {\n str += ` <button\n class=\"tab ${tab.disabled ? \"disabled\" : \"\"} ${tab == tabSelected ? \"active\" : \"\"} ${tab.color}\"\n color=\"${tab.color}\"\n input-key=\"${tab.id}\"\n ${tab.tooltip ? 'cap-tooltip=\"' + tab.tooltip + '\"' : \"\"} >\n <span>${tab.label}</span>\n ${tab.icon || \"\"}\n </button>\n `;\n }\n });\n str += `</div>`;\n }\n }\n\n if (tabSelected) {\n if (tabSelected.legends) {\n /*\n str += `<div class=\"legends-select-container c-d-desktop-none c-d-mobile-flex\">\n <select class=\"legends-select\" multiple>`;\n tabSelected.legends.forEach(legend => {\n str +=` <option value=\"${legend.id}\"> ${legend.label} </option>`\n });\n str += `</select>\n </div>`;\n */\n let toggleLegendsIconPath = \"M7,5H21V7H7V5M7,13V11H21V13H7M4,4.5A1.5,1.5 0 0,1 5.5,6A1.5,1.5 0 0,1 4,7.5A1.5,1.5 0 0,1 2.5,6A1.5,1.5 0 0,1 4,4.5M4,10.5A1.5,1.5 0 0,1 5.5,12A1.5,1.5 0 0,1 4,13.5A1.5,1.5 0 0,1 2.5,12A1.5,1.5 0 0,1 4,10.5M7,19V17H21V19H7M4,16.5A1.5,1.5 0 0,1 5.5,18A1.5,1.5 0 0,1 4,19.5A1.5,1.5 0 0,1 2.5,18A1.5,1.5 0 0,1 4,16.5Z\";\n str += ` \n <button toggle-legends class=\"cap-btn-icon cap-btn-icon-raised \">\n <span>\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"${toggleLegendsIconPath}\" />\n </svg>\n </span>\n </button> \n\n <div class=\"legends-container force-mobile-style hide\"> `;\n tabSelected.legends.forEach(legend => {\n let colorClass = \"\";\n let colorBg = \"\";\n\n if (_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].isHexColor(legend.color)) {\n colorBg = \"background:\" + legend.color;\n } else {\n colorClass = legend.color ? legend.color + \"--background\" : \"\";\n }\n\n str += ` <div\n class=\"legend ${legend.active ? \"active\" : \"\"}\"\n input-key=\"${legend.key}\"\n ${legend.tooltip ? `cap-tooltip=\"${legend.tooltip}\"` : \"\"} >\n <div class=\"icon-legend ${colorClass} ${legend.shape}\" style=\"${colorBg}\"></div>\n <span>${legend.label}</span>\n </div>`;\n });\n str += `</div>`;\n }\n }\n\n str += `\n\n <div class=\"spacer\"></div>\n\n\n\n <button cap-btn-prev class=\"cap-btn-icon cap-btn-icon-raised\">\n <span class=\"icon\">\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M20,10V14H11L14.5,17.5L12.08,19.92L4.16,12L12.08,4.08L14.5,6.5L11,10H20Z\" />\n </svg>\n </span>\n\n <span class=\"loading-icon\">\n <svg version=\"1.1\" id=\"loader-1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n width=\"32px\" height=\"32px\" viewBox=\"0 0 40 40\" enable-background=\"new 0 0 40 40\" xml:space=\"preserve\">\n <path opacity=\"0.2\" fill=\"#000\" d=\"M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946\n s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634\n c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z\"/>\n <path fill=\"#000\" d=\"M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0\n C22.32,8.481,24.301,9.057,26.013,10.047z\">\n <animateTransform attributeType=\"xml\"\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 20 20\"\n to=\"360 20 20\"\n dur=\"1.5s\"\n repeatCount=\"indefinite\"/>\n </path>\n </svg>\n </span>\n </button>\n\n\n <button cap-btn-calendar class=\"cap-btn-icon cap-btn-icon-raised\">\n <span>\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M19,19H5V8H19M16,1V3H8V1H6V3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3H18V1M17,12H12V17H17V12Z\" />\n </svg>\n </span>\n <span class=\"loading-icon\">\n <svg version=\"1.1\" id=\"loader-1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n width=\"32px\" height=\"32px\" viewBox=\"0 0 40 40\" enable-background=\"new 0 0 40 40\" xml:space=\"preserve\">\n <path opacity=\"0.2\" fill=\"#000\" d=\"M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946\n s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634\n c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z\"/>\n <path fill=\"#000\" d=\"M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0\n C22.32,8.481,24.301,9.057,26.013,10.047z\">\n <animateTransform attributeType=\"xml\"\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 20 20\"\n to=\"360 20 20\"\n dur=\"1.5s\"\n repeatCount=\"indefinite\"/>\n </path>\n </svg>\n </span>\n </button>\n\n <button cap-btn-next class=\"cap-btn-icon cap-btn-icon-raised\">\n <span>\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M4,10V14H13L9.5,17.5L11.92,19.92L19.84,12L11.92,4.08L9.5,6.5L13,10H4Z\" />\n </svg>\n </span>\n <span class=\"loading-icon\">\n <svg version=\"1.1\" id=\"loader-1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n width=\"32px\" height=\"32px\" viewBox=\"0 0 40 40\" enable-background=\"new 0 0 40 40\" xml:space=\"preserve\">\n <path opacity=\"0.2\" fill=\"#000\" d=\"M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946\n s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634\n c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z\"/>\n <path fill=\"#000\" d=\"M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0\n C22.32,8.481,24.301,9.057,26.013,10.047z\">\n <animateTransform attributeType=\"xml\"\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 20 20\"\n to=\"360 20 20\"\n dur=\"1.5s\"\n repeatCount=\"indefinite\"/>\n </path>\n </svg>\n </span>\n </button>\n\n <div class=\"spacer\"></div>\n\n <button toggle-dark class=\"cap-btn-icon cap-btn-header c-d-mobile-none ${config.timeline.withDarkToggle == false ? \"hide\" : \"\"}\">\n <span class=\"hide-light\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M13,4.8C9,4.8 9,19.2 13,19.2C17,19.2 22,16.5 22,12C22,7.5 17,4.8 13,4.8M13.1,17.2C12.7,16.8 12,15 12,12C12,9 12.7,7.2 13.1,6.8C16,6.9 20,8.7 20,12C20,15.3 15.9,17.1 13.1,17.2M8,10.5C8,11 7.9,11.5 7.9,12C7.9,12.2 7.9,12.4 7.9,12.6L2.4,14L1.9,12.1L8,10.5M2,7L9.4,5.1C9.2,5.4 9,5.8 8.9,6.3C8.8,6.6 8.7,7 8.6,7.4L2.5,8.9L2,7M8.2,15.5C8.3,16.2 8.5,16.9 8.7,17.4L2.4,19L1.9,17.1L8.2,15.5Z\" />\n </svg>\n </span>\n <span class=\"hide-dark\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M13,4.8C9,4.8 9,19.2 13,19.2C17,19.2 22,16.5 22,12C22,7.5 17,4.8 13,4.8M13.1,17.2C12.7,16.8 12,15 12,12C12,9 12.7,7.2 13.1,6.8C16,6.9 20,8.7 20,12C20,15.3 16,17.1 13.1,17.2M2,5H9.5C9.3,5.4 9,5.8 8.9,6.4C8.8,6.6 8.8,6.8 8.7,7H2V5M8,11H2V9H8.2C8.1,9.6 8.1,10.3 8,11M8.7,17C8.9,17.8 9.2,18.4 9.6,19H2.1V17H8.7M8.2,15H2V13H8C8.1,13.7 8.1,14.4 8.2,15Z\" />\n </svg>\n </span>\n </button>`;\n\n if (config.timeline.header.extend.enabled !== false) {\n str += `<button toggle-header class=\"cap-btn-icon cap-btn-icon-raised\">\n <span>\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z\" />\n </svg>\n </span>\n </button>`;\n }\n\n str += ` <div class=\"button-right-container\"></div>\n </div>`;\n /*\n `\n <button toggle-sidebar-right class=\"cap-btn-icon cap-btn-icon-raised\">\n <span>\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M15.41,16.58L10.83,12L15.41,7.41L14,6L8,12L14,18L15.41,16.58Z\" />\n </svg>\n </span>\n </button>\n </div>\n `;\n */\n\n let $r = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n $elem.replaceWith($r);\n\n if (config.timeline.header.rightButtons) {\n let $buttonContainer = $r.querySelector(\".button-right-container\");\n config.timeline.header.rightButtons.forEach(button => {\n let hasBadge = false;\n\n if (button.hasBadge) {\n hasBadge = button.hasBadge();\n }\n\n let str = `<button class=\"cap-btn-icon cap-btn-icon-raised ${hasBadge ? \"cap-btn-has-badge\" : \"\"}\">\n <span>\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"${button.icon}\" />\n </svg>\n </span>\n </button>`;\n let $button = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n $button.addEventListener(\"click\", evt => button.onClick({\n evt\n }));\n $buttonContainer.append($button);\n });\n }\n\n let $toggleDark = $r.querySelector(\"[toggle-dark]\");\n\n if ($toggleDark) {\n $toggleDark.addEventListener(\"click\", e => {\n $r.dispatchEvent(new CustomEvent(\"toggleDark\", {\n bubbles: true,\n cancelable: false\n }));\n });\n }\n\n let $btnCalendar = $r.querySelector(\"[cap-btn-calendar]\");\n\n if ($btnCalendar) {\n $btnCalendar.addEventListener(\"click\", e => {\n let x = e.x;\n let y = e.y;\n $r.dispatchEvent(new CustomEvent(\"clickCalendarIcon\", {\n bubbles: true,\n cancelable: false,\n detail: {\n x,\n y\n }\n }));\n });\n }\n\n let $btnToggleHeader = $r.querySelector(\"[toggle-header]\");\n\n if ($btnToggleHeader) {\n $btnToggleHeader.addEventListener(\"click\", e => {\n $r.dispatchEvent(new CustomEvent(\"toggleHeader\", {\n bubbles: true,\n cancelable: false\n }));\n });\n }\n /*\n $r.querySelector(\"[toggle-sidebar-right]\").addEventListener(\"click\", e => {\n $r.dispatchEvent(new CustomEvent(\"toggleSidebarRight\", {\n bubbles: true,\n cancelable: false,\n }));\n });\n */\n\n\n $r.querySelector(\"[cap-btn-prev]\").addEventListener(\"click\", e => {\n $r.dispatchEvent(new CustomEvent(\"headerPrev\", {\n bubbles: true,\n cancelable: false,\n detail: {\n originalEvt: e\n }\n }));\n });\n $r.querySelector(\"[cap-btn-calendar]\").addEventListener(\"click\", e => {\n $r.dispatchEvent(new CustomEvent(\"headerCalendar\", {\n bubbles: true,\n cancelable: false,\n detail: {\n originalEvt: e\n }\n }));\n });\n $r.querySelector(\"[cap-btn-next]\").addEventListener(\"click\", e => {\n $r.dispatchEvent(new CustomEvent(\"headerNext\", {\n bubbles: true,\n cancelable: false,\n detail: {\n originalEvt: e\n }\n }));\n });\n let $toggleLegendsBtn = $r.querySelector(\"[toggle-legends]\");\n\n if ($toggleLegendsBtn) {\n $toggleLegendsBtn.addEventListener(\"click\", e => {\n let $legendContainer = $r.querySelector(\".legends-container\");\n\n if ($legendContainer) {\n $legendContainer.classList.toggle(\"hide\");\n }\n });\n }\n\n $r.querySelectorAll(\".legend\").forEach($legend => {\n $legend.addEventListener(\"click\", e => {\n let key = e.currentTarget.getAttribute(\"input-key\");\n\n if (key) {\n let legendSelected = tabSelected.legends.find(tab => tab.key === key);\n\n if (legendSelected) {\n $r.dispatchEvent(new CustomEvent(\"selectLegendHeader\", {\n bubbles: true,\n cancelable: false,\n detail: {\n legend: legendSelected,\n $legend\n }\n }));\n }\n }\n });\n });\n $r.querySelectorAll(\".tab:not(.disabled)\").forEach($tab => {\n $tab.addEventListener(\"click\", e => {\n let key = e.currentTarget.getAttribute(\"input-key\");\n\n if (key) {\n let tabSelected = config.timeline.tabs.find(tab => tab.id == key);\n\n if (tabSelected) {\n $r.dispatchEvent(new CustomEvent(\"selectTabHeader\", {\n bubbles: true,\n cancelable: false,\n detail: {\n tab: tabSelected\n }\n }));\n }\n }\n });\n });\n $r.querySelectorAll(\".tabs-select:not(.disabled)\").forEach($tab => {\n $tab.addEventListener(\"change\", e => {\n let key = parseFloat(e.currentTarget.value);\n\n if (key) {\n let tabSelected = config.timeline.tabs.find(tab => tab.id == key);\n\n if (tabSelected) {\n $r.dispatchEvent(new CustomEvent(\"selectTabHeader\", {\n bubbles: true,\n cancelable: false,\n detail: {\n tab: tabSelected\n }\n }));\n }\n }\n });\n });\n return $r;\n },\n\n /**\n * Crea Header\n * Se usa para :\n * - Mostrar fechas en header\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom\n */\n createHeader(config) {\n let $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"header\");\n return this.redrawHeader(config, $elem);\n },\n\n /**\n * Recrea Header, usado para redibujar\n * utiliza $elem como elemento dom donde recrearlo\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} $elem - Elemento Dom donde crea Header\n * @return {Object} Elemento Dom\n */\n redrawHeader(config, $elem) {\n let datesTree = _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].getDateTreeRange(new Date(config.timeline.start), new Date(config.timeline.end));\n let str = `<div class=\"header-container\"> `;\n Object.keys(datesTree).forEach(keyY => {\n let year = datesTree[keyY];\n str += `<div class=\"agno-calendario\">\n <span class=\"agno hide\">${keyY}</span>\n <div class=\"meses\">`;\n Object.keys(year).forEach(keyM => {\n let month = datesTree[keyY][keyM];\n str += ` <div class=\"mes-calendario\">\n <div class=\"mes ${Object.keys(month).length < 4 ? \"mes-reduced mes-reduced-\" + Object.keys(month).length : \"\"}\">\n <div class=\"mes-label\">\n ${_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getMonthByPosition(keyM)} ${keyY}\n </div>\n </div>\n <div class=\"dias\">`;\n Object.keys(month).forEach(keyD => {\n let day = datesTree[keyY][keyM][keyD];\n let isWeekend = day.isWeekend;\n let isToday = day.isToday;\n let date = _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].formatDate(day.Date);\n str += `<div class=\"dia-calendario ${isToday ? \"today\" : \"\"} ${isWeekend ? \"weekend\" : \"\"} ${config.timeline.dateSelectable ? \"is-clickeable\" : \"\"}\" date=\"${date}\">${keyD}</div>`;\n });\n str += `</div></div>`;\n });\n str += `</div> </div>`;\n });\n str += `</div>`;\n $elem.innerHTML = \"\";\n $elem.append(_util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str));\n\n if (config.timeline.dateSelectable) {\n $elem.querySelectorAll(\".dia-calendario[date]\").forEach($dia => {\n $dia.addEventListener(\"contextmenu\", evt => {\n $elem.dispatchEvent(new CustomEvent(\"contextMenuDate\", {\n bubbles: true,\n cancelable: false,\n detail: {\n $elem: $dia,\n date: $dia.getAttribute(\"date\"),\n clientX: evt.clientX,\n clientY: evt.clientY\n }\n }));\n });\n $dia.addEventListener(\"click\", evt => {\n $elem.dispatchEvent(new CustomEvent(\"clickDate\", {\n bubbles: true,\n cancelable: false,\n detail: {\n $elem: $dia,\n date: $dia.getAttribute(\"date\")\n }\n }));\n });\n });\n }\n\n return $elem;\n },\n\n /**\n * Crea Header extended\n * Se usa para :\n * -Mostrar inputs y datos para fechas en header\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom headerExtended\n */\n createHeaderExtended(config) {\n if (config.timeline.header.extend.enabled == false) return null;\n let dates = _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].getDateRange(new Date(config.timeline.start), new Date(config.timeline.end));\n let str = `<div class=\"header-container-extended\">`;\n config.timeline.header.extend.data.forEach((d, d_index) => {\n if (d.isHidden) return \"\";\n let isPersistent = d.isPersistent;\n str += `<div class=\"input-list ${isPersistent ? \"persistent\" : \"\"}\">`;\n str += dates.map(date => {\n let value = \"\";\n let isFuture = _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].isFuture(date);\n let isToday = _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].isToday(date);\n\n if (d.data) {\n let dataFounded = d.data.find(dataInput => {\n return _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].isSameDate(new Date(dataInput.date), date);\n });\n\n if (dataFounded) {\n value = dataFounded.value || \"\";\n }\n }\n\n if (d.editable === false || isFuture && d.editableFuture == false || isToday && d.editableToday == false) {\n return `<div>\n <span date=\"${date}\" \n index=\"${d_index}\" \n class=\"${date.varName} ${d.color ? \"c-\" + d.color + \"--text\" : \"\"}\" > \n ${value} \n </span>\n </div>`;\n }\n\n let isDisabled = false;\n\n if (config.timeline.editable === false) {\n isDisabled = true;\n }\n\n return `<div class=\"dia-input\">\n <input \n date=\"${date}\" \n index=\"${d_index}\" \n class=\"header-input \n ${date.varName} ${d.color ? \"c-\" + d.color + \"--text\" : \"\"}\" \n type=\"number\"\n ${isDisabled ? \"disabled\" : \"\"} \n value=\"${value}\">\n </div>`;\n }).join(\"\");\n str += `</div>`;\n });\n str += `</div>`;\n let r = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n r.querySelectorAll(\"input.header-input\").forEach(input => {\n input.addEventListener(\"input\", e => {\n let date = e.currentTarget.getAttribute(\"date\");\n let index = e.currentTarget.getAttribute(\"index\");\n let value = e.currentTarget.value;\n let typeData = config.timeline.header.extend.data[index]; //refresh config value\n\n let data = typeData.data.find(d => _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].isSameDate(new Date(d.date), new Date(date)));\n data.value = value;\n r.dispatchEvent(new CustomEvent(\"changeInputHeader\", {\n bubbles: true,\n cancelable: false,\n detail: {\n date: date,\n typeData: typeData,\n value: value\n }\n }));\n });\n });\n return r;\n },\n\n /**\n * Crear Sidebar Izquierdo\n * - Maneja items como arbol de 2 niveles (parent, children)\n * - El sidebar se divide en navList - InitialNav - extendedNav - BtnNav\n * - Se agrega itemDetail, para detalles de items\n *\n *\n * TODO: para evitar incrustar las ids en los inputs, se deben crear\n * los nodos uno por uno como elemento DOM, y agregarles los eventos directamente\n * ahora se hace seleccionando todos los inputs con querySelectorAll\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom Sidebar Izquierdo\n */\n createNavLeft(config, tab = null) {\n let $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"nav\", {\n className: \"left\"\n });\n return this.redrawNavLeft($elem, config, tab);\n },\n\n /**\n * Recrea Sidebar izquierdo, usado para redibujar\n * Utiliza $elem como elemento dom donde recrearlo\n *\n *\n * @param {Object} $elem - Elemento Dom donde crea el sidebar izquierdo\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom navLeft\n */\n redrawNavLeft($elem, config, tab = null) {\n let navList = \"\";\n let initialNavList = \"\";\n let exNavList = \"\";\n let btnNavList = \"\";\n let isDisabled = false;\n\n if (config.timeline.editable === false) {\n isDisabled = true;\n }\n\n config.data.forEach(d => {\n if (d.isHidden) return;\n navList += `\n <div class=\"nav-item\">\n\n\n <div class=\"nav-item-container parent\">`;\n\n if (d.children) {\n navList += `<button class=\"tree-icon ${d.isClosed ? \"\" : \"cap-rotate\"}\" item-id=\"${d.id || -1}\" type-node=\"${d.type || \"\"}\" >\n <span>\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z\" />\n </svg>\n </span>\n </button>`;\n }\n\n navList += `\n <div class=\"item-title truncate full-width ${d.clickeable ? \"clickeable\" : \"\"}\n ${d.navOver ? \"hoverable\" : \"\"} \" item-id=\"${d.id || -1}\" type-node=\"${d.type || \"\"}\" >\n ${d.label}\n </div>\n </div>`;\n\n if (d.children) {\n navList += `\n <div class=\"children-items ${d.isClosed ? \"hide\" : \"\"} \" child-list=\"${d.id || -1}\">`;\n d.children.forEach(c => {\n if (c.isHidden) return;\n navList += `\n <div class=\"child-nav-item\">\n <div class=\"nav-item-container\">\n `;\n /*\n <span class=\"nav-item-icon\">\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M19,15L13,21L11.58,19.58L15.17,16H4V4H6V14H15.17L11.58,10.42L13,9L19,15Z\" />\n </svg>\n </span>\n */\n\n navList += `\n ${c.light ? '<span class=\"light ' + (c.light ? c.light + \"-light\" : \"\") + '\"></span>' : \"\"}\n\n <div class=\"item-title ${c.clickeable ? \"clickeable\" : \"\"}\n ${c.navOver ? \"hoverable\" : \"\"}\" item-id=\"${c.id || -1}\" type-node=\"${c.type || \"\"}\">\n <div class=\"truncate\">\n ${c.label}\n </div>\n </div>\n </div>\n </div>`;\n });\n navList += `\n </div>`;\n }\n\n navList += `</div>`; //initial\n\n initialNavList += `<div class=\"initial-nav-item parent\">`;\n\n if (d.withNav) {\n config.timeline.nav.left.initial.vars.forEach(v => {\n let value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(d.values, v.varName);\n\n if (v.round && !isNaN(value)) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].round(value, v.round);\n }\n\n if (v.input) {\n switch (v.input) {\n case \"hour\":\n value = value.split(\":\");\n let hhValue = value[0];\n let mmValue = value[1];\n initialNavList += `\n <div class=\"item-col has-input\">\n <div class=\"hour-input\">\n <input type=\"number\"\n input-type=\"time\"\n max=\"23\"\n min=\"00\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${d.id || -1}\"\n type-node=\"${d.type || \"\"}\"\n value=\"${hhValue}\"\n ${isDisabled ? \"disabled\" : \"\"}\n class=\"hh\">\n <span>:</span>\n <input type=\"number\"\n input-type=\"time\"\n max=\"59\"\n min=\"00\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${d.id || -1}\"\n type-node=\"${d.type || \"\"}\"\n value=\"${mmValue}\"\n ${isDisabled ? \"disabled\" : \"\"}\n class=\"mm\">\n </div>\n </div>`;\n break;\n\n case \"text\":\n case \"number\":\n default:\n initialNavList += `\n <div class=\"item-col has-input\">\n <input \n type=\"${v.input || \"text\"}\"\n input-type=\"${v.input || \"text\"}\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${d.id || -1}\"\n type-node=\"${d.type || \"\"}\"\n ${isDisabled ? \"disabled\" : \"\"}\n value=\"${value}\"/>\n </div>`;\n }\n } else {\n initialNavList += `\n <div class=\"item-col\">\n ${value}\n </div>`;\n }\n });\n }\n\n initialNavList += `\n </div>`;\n\n if (d.children) {\n d.children.forEach(c => {\n if (c.isHidden) return;\n initialNavList += `<div class=\"child-initial-nav-item ${d.isClosed ? \"hide\" : \"\"}\" child=\"${d.id || -1}\">`;\n\n if (c.withNav !== false) {\n config.timeline.nav.left.initial.vars.forEach(v => {\n if (v.onlyTab && tab && v.onlyTab !== tab.key) return;\n let value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(c.values, v.varName);\n\n if (v.round && !isNaN(value)) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].round(value, v.round);\n }\n\n if (v.input) {\n switch (v.input) {\n case \"hour\":\n value = value.split(\":\");\n let hhValue = value[0];\n let mmValue = value[1];\n initialNavList += `\n <div class=\"item-col has-input\">\n <div class=\"hour-input\">\n <input type=\"number\"\n input-type=\"time\"\n max=\"23\"\n min=\"00\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${c.id || -1}\"\n type-node=\"${c.type || \"\"}\"\n value=\"${hhValue}\"\n ${isDisabled ? \"disabled\" : \"\"}\n class=\"hh\">\n <span>:</span>\n <input type=\"number\"\n input-type=\"time\"\n max=\"59\"\n min=\"00\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${c.id || -1}\"\n type-node=\"${c.type || \"\"}\"\n value=\"${mmValue}\"\n ${isDisabled ? \"disabled\" : \"\"}\n class=\"mm\">\n </div>\n </div>`;\n break;\n\n case \"text\":\n case \"number\":\n default:\n initialNavList += `\n <div class=\"item-col has-input\">\n <input\n type=\"${v.input || \"text\"}\"\n input-type=\"${v.input || \"text\"}\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${c.id || -1}\"\n type-node=\"${c.type || \"\"}\"\n ${isDisabled ? \"disabled\" : \"\"}\n value=\"${value}\"/>\n </div>`;\n }\n } else {\n initialNavList += `\n <div class=\"item-col\">\n ${value}\n </div>`;\n }\n });\n }\n\n initialNavList += `\n </div>`;\n });\n } //Ext\n\n\n exNavList += `<div class=\"ex-nav-item parent\">`;\n\n if (d.withExNav) {\n config.timeline.nav.left.extend.vars.forEach(v => {\n let value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(d.values, v.varName);\n\n if (v.round && !isNaN(value)) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].round(value, v.round);\n }\n\n if (v.input) {\n switch (v.input) {\n case \"hour\":\n value = value.split(\":\");\n let hhValue = value[0];\n let mmValue = value[1];\n exNavList += `\n <div class=\"item-col has-input\">\n <div class=\"hour-input\">\n <input type=\"number\"\n input-type=\"time\"\n max=\"23\"\n min=\"0\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${d.id || -1}\"\n type-node=\"${d.type || \"\"}\"\n value=\"${hhValue}\"\n ${isDisabled ? \"disabled\" : \"\"}\n class=\"hh\">\n <span>:</span>\n <input type=\"number\"\n input-type=\"time\"\n max=\"59\"\n min=\"0\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${d.id || -1}\"\n type-node=\"${d.type || \"\"}\"\n value=\"${mmValue}\"\n ${isDisabled ? \"disabled\" : \"\"}\n class=\"mm\">\n </div>\n </div>`;\n break;\n\n case \"text\":\n case \"number\":\n default:\n exNavList += `\n <div class=\"item-col has-input\">\n <input\n type=\"${v.input || \"text\"}\"\n input-type=\"${v.input || \"text\"}\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${d.id || -1}\"\n type-node=\"${d.type || \"\"}\"\n ${isDisabled ? \"disabled\" : \"\"}\n value=\"${value}\"/>\n </div>`;\n }\n } else {\n exNavList += `\n <div class=\"item-col\">\n ${value}\n </div>`;\n }\n });\n }\n\n exNavList += `\n </div>`;\n\n if (d.children) {\n d.children.forEach(c => {\n if (c.isHidden) return;\n exNavList += `<div class=\"child-ex-nav-item ${d.isClosed ? \"hide\" : \"\"}\" child=\"${d.id || -1}\">`;\n\n if (c.withNav !== false) {\n config.timeline.nav.left.extend.vars.forEach(v => {\n if (v.onlyTab && tab && v.onlyTab !== tab.key) return;\n let value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(c.values, v.varName);\n\n if (v.round && !isNaN(value)) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].round(value, v.round);\n }\n\n if (v.input) {\n switch (v.input) {\n case \"hour\":\n value = value ? value.split(\":\") : [0, 0];\n let hhValue = value[0];\n let mmValue = value[1];\n exNavList += `\n <div class=\"item-col has-input\">\n <div class=\"hour-input\">\n <input type=\"number\"\n input-type=\"time\"\n max=\"23\"\n min=\"0\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${c.id || -1}\"\n type-node=\"${c.type || \"\"}\"\n value=\"${hhValue}\"\n ${isDisabled ? \"disabled\" : \"\"}\n class=\"hh\">\n <span>:</span>\n <input type=\"number\"\n input-type=\"time\"\n max=\"59\"\n min=\"0\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${c.id || -1}\"\n type-node=\"${c.type || \"\"}\"\n value=\"${mmValue}\"\n ${isDisabled ? \"disabled\" : \"\"}\n class=\"mm\">\n </div>\n </div>`;\n break;\n\n case \"text\":\n case \"number\":\n default:\n exNavList += `\n <div class=\"item-col has-input\">\n <input \n type=\"${v.input || \"text\"}\"\n input-type=\"${v.input || \"text\"}\"\n input-key=\"${v.key || \"\"}\"\n item-id=\"${c.id || -1}\"\n type-node=\"${c.type || \"\"}\"\n ${isDisabled ? \"disabled\" : \"\"}\n value=\"${value}\"/>\n </div>`;\n }\n } else {\n exNavList += `\n <div class=\"item-col\">\n ${value}\n </div>`;\n }\n });\n }\n\n exNavList += `\n </div>`;\n });\n } //buttons\n\n\n btnNavList += `<div class=\"cap-btn-nav-item parent\">\n <div class=\"cap-btn-nav-item-content\">`;\n\n if (config.timeline.nav.left.buttons && config.timeline.nav.left.buttons.vars) {\n config.timeline.nav.left.buttons.vars.forEach(btn => {\n if (d.withBtnNav) {\n let btnContent = \"\";\n let className = btn.className || \"\";\n\n if (btn.icon) {\n btnContent = btn.icon ? btn.icon : \"\";\n }\n\n if (btn.iconFormatter) {\n btnContent = btn.iconFormatter ? btn.iconFormatter(d, btn) : \"\";\n }\n\n if (btn.shape) {\n className += \" cap-btn-\" + btn.shape;\n btnContent += `<span> ${btn.formatter ? btn.formatter(d, btn) : \"\"} </span> `;\n }\n\n if (btn.btnClassNameFormatter) {\n let newClassName = btn.btnClassNameFormatter(d, btn);\n\n if (newClassName) {\n className += \" \" + newClassName;\n }\n }\n\n btnNavList += `\n <button class=\"cap-btn-shape ${className}\"\n input-key=\"${btn.key || \"\"}\"\n item-id=\"${d.id || -1}\"\n ${isDisabled ? \"disabled\" : \"\"}\n type-node=\"${d.type || \"\"}\">\n ${btnContent}\n </button>`;\n }\n });\n }\n\n btnNavList += `\n </div>\n </div>`;\n\n if (d.children) {\n d.children.forEach(c => {\n if (c.isHidden) return; //buttons\n\n btnNavList += `<div class=\"cap-btn-child-nav-item parent ${d.isClosed ? \"hide\" : \"\"}\" child=\"${d.id || -1}\">\n <div class=\"cap-btn-nav-item-content\">`;\n\n if (config.timeline.nav.left.buttons && config.timeline.nav.left.buttons.vars) {\n config.timeline.nav.left.buttons.vars.forEach(btn => {\n if (c.withNav !== false) {\n let btnContent = \"\";\n let className = btn.className || \"\";\n\n if (btn.icon) {\n btnContent = btn.icon ? btn.icon : \"\";\n }\n\n if (btn.iconFormatter) {\n btnContent = btn.iconFormatter ? btn.iconFormatter(c, btn) : \"\";\n }\n\n if (btn.shape) {\n className += \" cap-btn-\" + btn.shape;\n btnContent += `<span> ${btn.formatter ? btn.formatter(c, btn) : \"\"} </span> `;\n }\n\n if (btn.btnClassNameFormatter) {\n let newClassName = btn.btnClassNameFormatter(c, btn);\n\n if (newClassName) {\n className += \" \" + newClassName;\n }\n }\n\n btnNavList += `\n <button class=\"cap-btn-shape ${className}\"\n input-key=\"${btn.key || \"\"}\"\n item-id=\"${c.id || -1}\"\n ${isDisabled ? \"disabled\" : \"\"}\n type-node=\"${c.type || \"\"}\">\n ${btnContent}\n </button>`;\n }\n });\n }\n\n btnNavList += `\n </div>\n </div>`;\n });\n }\n });\n let itemDetail = ` <div class=\"detail-nav-item hide\">\n ${this.getDetailNavItemContent()}\n </div>`;\n let str = `<div class=\"nav-container\">\n ${itemDetail}\n <div class=\"nav-item-list\">\n ${navList}\n </div>\n <div class=\"initial-nav-list\">\n ${initialNavList}\n </div>\n <div class=\"extend-nav-list\">\n ${exNavList}\n </div>\n <div class=\"cap-btn-nav-list\">\n ${btnNavList}\n </div>\n </div>`;\n let navContainer = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n $elem.innerHTML = \"\";\n $elem.append(navContainer); //detalle de nav-item\n\n $elem.querySelectorAll(\".item-title.hoverable\").forEach(i => {\n i.addEventListener(\"mouseover\", e => {\n let pos = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].eventToPositionNavLeft(config, e, $elem);\n let itemId = i.getAttribute(\"item-id\");\n let item = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getItemById(config, itemId);\n let typeNode = i.getAttribute(\"type-node\");\n i.dispatchEvent(new CustomEvent(\"overNavItem\", {\n bubbles: true,\n cancelable: false,\n detail: {\n originalEvt: e,\n item: item,\n type: typeNode,\n pos: pos\n }\n }));\n });\n }); //oculta detalle de nav-item, al salir del nav-item-list\n\n $elem.querySelectorAll(\".nav-item-list\").forEach(i => {\n i.addEventListener(\"mouseleave\", e => {\n i.dispatchEvent(new CustomEvent(\"leaveNavItem\", {\n bubbles: true,\n cancelable: false\n }));\n });\n }); //oculta detalle de nav-item-list, al salir de nav-item\n\n $elem.querySelectorAll(\".item-title:not(.hoverable)\").forEach(i => {\n i.addEventListener(\"mousemove\", e => {\n i.dispatchEvent(new CustomEvent(\"leaveNavItem\", {\n bubbles: true,\n cancelable: false\n }));\n });\n });\n $elem.querySelectorAll(\".item-title.clickeable\").forEach(i => {\n i.addEventListener(\"click\", e => {\n let itemId = i.getAttribute(\"item-id\");\n let typeNode = i.getAttribute(\"type-node\");\n let value = i.value;\n i.dispatchEvent(new CustomEvent(\"clickNavLeftItem\", {\n bubbles: true,\n cancelable: false,\n detail: {\n itemId: itemId,\n type: typeNode,\n value: value\n }\n }));\n });\n });\n $elem.querySelectorAll(\"input\").forEach(i => {\n i.addEventListener(\"change\", e => {\n let inputType = i.getAttribute(\"input-type\");\n let key = i.getAttribute(\"input-key\");\n let itemId = i.getAttribute(\"item-id\");\n let typeNode = i.getAttribute(\"type-node\");\n let item = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getItemById(config, itemId);\n let value = i.value;\n\n if (inputType == \"time\") {\n let hh_input = i.parentElement.querySelector(\"input.hh\").value;\n let mm_input = i.parentElement.querySelector(\"input.mm\").value;\n mm_input = mm_input < 10 ? \"0\" + parseFloat(mm_input) : mm_input;\n i.parentElement.querySelector(\"input.mm\").value = mm_input;\n value = hh_input + \":\" + mm_input;\n }\n\n i.dispatchEvent(new CustomEvent(\"saveNavLeftInput\", {\n bubbles: true,\n cancelable: false,\n detail: {\n key: key,\n itemId: itemId,\n item: item,\n type: typeNode,\n value: value,\n tabSelected: tab\n }\n }));\n });\n });\n $elem.querySelectorAll(\"button.cap-btn-shape\").forEach(i => {\n i.addEventListener(\"click\", e => {\n let key = i.getAttribute(\"input-key\");\n let itemId = i.getAttribute(\"item-id\");\n let typeNode = i.getAttribute(\"type-node\");\n i.dispatchEvent(new CustomEvent(\"clickNavLeftButton\", {\n bubbles: true,\n cancelable: false,\n detail: {\n key: key,\n itemId: itemId,\n type: typeNode\n }\n }));\n });\n });\n $elem.querySelectorAll(\"button.tree-icon\").forEach(i => {\n i.addEventListener(\"click\", e => {\n let itemId = i.getAttribute(\"item-id\");\n let typeNode = i.getAttribute(\"type-node\");\n let dataConfig = config.data.find(d => d.id == itemId);\n let $navItem = e.currentTarget.closest(\".nav-item\");\n let $children = $navItem.querySelector(\".children-items\");\n let itemsToHide = e.currentTarget.closest(\"nav.left\").querySelectorAll(\"[child='\" + itemId + \"'], [child-list='\" + itemId + \"']\");\n\n if ($children) {\n if ($children.classList.contains(\"hide\")) {\n e.currentTarget.classList.add(\"cap-rotate\");\n itemsToHide.forEach(i => i.classList.remove(\"hide\"));\n dataConfig.isClosed = false;\n } else {\n e.currentTarget.classList.remove(\"cap-rotate\");\n itemsToHide.forEach(i => i.classList.add(\"hide\"));\n dataConfig.isClosed = true;\n }\n }\n\n i.dispatchEvent(new CustomEvent(\"clickNavLeftTreeIcon\", {\n bubbles: true,\n cancelable: false,\n detail: {\n itemId: itemId,\n type: typeNode\n }\n })); //e.currentTarget.parent\n });\n });\n return $elem;\n },\n\n /**\n * Crea Html como String, para el detalle de items en el Sidebar Izquierdo\n *\n * @param {Object} [item={}] - Configuracion de item\n * @return {String} Html de ventana de detalle\n */\n getDetailNavItemContent(item = {}) {\n if (item.navOver == undefined) item.navOver = {};\n return `\n <div class=\"header-detail\">\n <div class=\"detail-title truncate\">\n ${item.label || \"\"}\n </div>\n <div class=\"detail-subtitle\">\n ${item.navOver.subtitle || \"\"}\n </div>\n <div class=\"header-chip ${item.light ? item.light + \"-light\" : \"\"} ${item.navOver.chip ? \"\" : \"hide\"}\">\n ${item.navOver.chip || \"\"}\n </div>\n </div>\n\n <div class=\"detail-container\">\n ${item.navOver.content || \"\"}\n </div>`;\n },\n\n /**\n * Crea Sidebar Derecho\n * Usado principalmente para formulario de ingreso de datos para los dias\n * seleccionados\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} tab - Tab de referencia, para la creacion del formulario\n * @return {Object} {element, inputs}, element es el elemento Dom del sidebar,\n * inputs es un array de elementos Dom de cada input creado\n * (no son elementos html de tipo input)\n */\n createNavRight(config, tab = null) {\n var $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"nav\", {\n className: \"right\"\n });\n return this.redrawNavRight(config, $elem, tab, []);\n },\n\n /**\n * Recrea Sidebar Derecho\n * Utiliza $elem como elemento dom donde recrearlo\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} $elem - Elemento Dom donde crea el sidebar derecho\n * @param {Object} tab - Tab de referencia, para la creacion del formulario\n * @param {Object} dataDay - datos del dia seleccionando, para autorrelleno de formulario\n * @param {Object} daySelected - datos del dia seleccionado\n * @param {String} daySelected.date - fecha del dia seleccionado\n * @param {Object} daySelected.item - Item de Sidebar relacionado al dia seleccionado\n * @param {Object} daySelected.pos - posicion de dia seleccionado\n * @return {Object} Elemento Dom Sidebar Derecho\n */\n redrawNavRight(config, $elem, selected = null, tab = null, dataDay = null, daySelected = null) {\n let $navRight = $elem; //dom.createElement(\"nav\",{className:\"right\"});\n\n let $divContainer = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"nav-input-container\"\n });\n let $inputs = [];\n let checkboxInputs = [];\n let inputsWithReload = [];\n let tabSelected = tab;\n selected = selected || [daySelected];\n\n if (tabSelected && tabSelected.inputs) {\n tabSelected.inputs.forEach(i => {\n if (i.disabled) return;\n let $input = this.createInput(i, dataDay, daySelected, selected);\n\n if ($input) {\n $divContainer.appendChild($input);\n $inputs.push($input);\n\n if (i.type == \"checkbox\") {\n checkboxInputs.push($input);\n }\n\n if (i.reloadOnSelect != null) {\n inputsWithReload.push({\n $input,\n config: i\n });\n }\n }\n });\n } //manejo de eventos para inputs con showIf\n\n\n if (checkboxInputs) {\n checkboxInputs.forEach($c => {\n //obtiene key de checkbox\n let key = $c.getAttribute(\"input-key\");\n let props = tabSelected.inputs.find(i => {\n return i.key == key;\n });\n let isChecked = false;\n\n if (dataDay) {\n isChecked = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n } //obtiene inputs relacionados desde config para mostrar/ocultar\n\n\n let inputsToHide = tabSelected.inputs.filter(i => {\n return i.showIf && i.showIf == key;\n });\n let inputsToHideKeys = inputsToHide.map(i => i.key); //obtiene inputs del dom, filtrando con inputsToHide\n\n let $inputsHidden = $inputs.filter($i => {\n let inputKey = $i.getAttribute(\"input-key\");\n return inputsToHideKeys.indexOf(inputKey) > -1;\n }); //si hay inputs,\n\n if ($inputsHidden) {\n if (!isChecked) {\n $inputsHidden.forEach($i => {\n $i.classList.add(\"hide\");\n });\n }\n\n $c.addEventListener(\"input\", e => {\n $inputsHidden.forEach($i => {\n let fn = $c.querySelector(\"input[type='checkbox']\").checked ? \"remove\" : \"add\";\n $i.classList[fn](\"hide\");\n });\n });\n }\n });\n }\n\n let saveCancelBtns = this.createNavRightbuttons();\n $divContainer.appendChild(saveCancelBtns);\n $navRight.innerHTML = \"\";\n $navRight.appendChild($divContainer);\n return {\n element: $navRight,\n inputs: $inputs,\n inputsWithReload,\n saveCancelBtns\n };\n },\n\n /**\n * Crea Corner inferior izquierdo, como titulo para footer\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom Corner Footer\n */\n createCornerFooter(config) {\n if (config.timeline.footer === undefined || config.timeline.footer.enabled == false) return null;\n let str = \"\";\n\n if (config.timeline.footer) {\n str += `<div class=\"corner-footer\">\n <div class=\"corner-title\">\n <span>\n ${config.timeline.footer.label}\n </span>\n </div>\n </div>`;\n }\n\n return _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n },\n\n /**\n * Crea Footer para planilla\n * Inicialmente creado para totales\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom Corner Footer\n */\n createFooter(config) {\n if (config.timeline.footer === undefined || config.timeline.footer.enabled == false) return null;\n let str = `\n <footer>\n <div class=\"footer-container\">\n `;\n config.timeline.footer.data.forEach(d => {\n str += `\n <div class=\"footer-item\">${d.value}</div>\n `;\n });\n str += `\n </div>\n </footer>\n `;\n return _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n },\n\n /**\n * Crea Footer para planilla\n * Inicialmente creado para totales\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object[]} selected - array de objetos, de dias seleccionados\n * @return {Object} Elemento Dom Corner Footer\n */\n createSelectBoard(config, selected) {\n let $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"select-container\"\n });\n return this.redrawSelectBoard($elem, selected);\n },\n\n /**\n * Crea linea vertical para fecha Actual\n *\n * @param {Object} config - Configuracion capibara\n * @return {Object} Elemento Dom Corner Footer\n */\n createTodayLine(config) {\n return this.redrawTodayLine(config, _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"today-line\"\n }));\n },\n\n /**\n * Recrea linea vertical para fecha Actual\n * si el elemento $elem no es enviado, se crea un nuevo elemento\n *\n * Si el dia actual no esta dentro del rango de fechas del config,\n * deshabilita la linea con la clase css .disable-line\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} [$elem=null] - Elemento Dom donde recrea la linea, si es null, la crea\n * @return {Object} Elemento Dom Corner Footer\n */\n redrawTodayLine(config, $elem = null) {\n let endTime = new Date(config.timeline.end).getTime();\n let todayTime = new Date().getTime();\n let {\n height,\n dayWidth\n } = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getTableDimensions(config);\n if ($elem == null) $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"today-line\"\n });\n\n if (endTime < todayTime) {\n $elem.classList.add(\"disable-line\");\n } else {\n $elem.classList.remove(\"disable-line\");\n }\n\n let diffDays = Math.floor(_util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].diffDays(config.timeline.start, _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].formatDate(new Date())));\n let diff = diffDays * dayWidth;\n diff += dayWidth / 2 - 2; // para centrar linea\n\n Object.assign($elem.style, {\n \"margin-left\": diff + \"px\",\n height: height + \"px\"\n });\n return $elem;\n },\n\n /**\n * Crea elemento FloatBox, que contiene los datos que se muestra en la tabla\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} tab - Tab de referencia, para mostrar datos configurados por tab\n * @return {Object} Elemento Dom Corner Footer\n */\n createFloatBox(config, tab) {\n let $container = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"float-box-container\"\n });\n return this.redrawFloatBox(config, tab, $container);\n },\n\n /**\n * Recrea elemento FloatBox, que contiene los datos que se muestra en la tabla\n * Se usa principalmente para mostrar datos en la tabla de la planilla\n * los muestra de manera flotante, calculando el Top y el Left segun la poscion\n *\n * Se consideran los elementos padres ocultos, para ocultar los datos\n *\n * Se insertan los elementos FloatBox, como elemento con datos de un item y dia especifico\n *\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} tab - Tab de referencia, para mostrar datos configurados por tab\n * @return {Object} Elemento Dom Corner Footer\n */\n redrawFloatBox(config, tab, $container) {\n $container.innerHTML = \"\"; //let tabSelected = tab || null;\n\n config.data.forEach(de => {\n if (de.isHidden) return;\n de.children.forEach(ds => {\n if (ds.isHidden) return;\n ds.data.forEach(data => {\n if ((!data.message || data.message.value == null) && (data.values == null || data.values == undefined || Object.entries(data.values).length === 0)) {\n return null;\n } //children Data\n\n\n let position = this.getPositionFloatBox(config, data, ds);\n let className = \"\";\n\n if (data.errors && data.errors.length > 0) {\n className += \"has-errors \";\n }\n\n if (de.isClosed) {\n className += \"hide \";\n }\n\n let msg = null;\n\n if (tab.floatBox.messagePath) {\n msg = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(data, tab.floatBox.messagePath);\n }\n\n if (msg || data.message && data.message.value) {\n className += \"has-message \";\n }\n\n let str = `\n <div class=\"float-box ${className} ${de.isClosed ? \"hide\" : \"\"}\"\n style=\"${position ? position : \"\"}\"\n item-id=\"${ds.id || -1}\"\n type-node=\"${ds.type || \"\"}\"> `;\n\n if (tab && tab.floatBox) {\n //numeros en el floatBox\n if (tab.floatBox.nums) {\n tab.floatBox.nums.forEach(n => {\n if (tab.legends && n.tabKey) {\n let legend = tab.legends.find(l => l.key == n.tabKey);\n if (legend && !legend.active) return;\n }\n\n let dataFloatBox = null;\n let className = \"\";\n let showIf = true;\n let hideIf = false;\n let colorClass = \"\";\n let colorStyle = \"\";\n\n if (n.varName) {\n dataFloatBox = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(data.values, n.varName);\n }\n\n if (n.varShow) {\n showIf = Boolean(_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(data.values, n.varShow));\n dataFloatBox = dataFloatBox || \"\";\n }\n\n if (n.varHide) {\n hideIf = Boolean(_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(data.values, n.varHide));\n }\n\n if (n.shape) {\n className += \"shape-\" + n.shape;\n }\n\n if (n.color) {\n if (_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].isHexColor(n.color)) {\n colorStyle = `--local-color: ${n.color}`;\n } else {\n colorClass = n.color;\n }\n }\n\n if (dataFloatBox !== null && showIf && !hideIf) {\n str += `<span class=\"data ${colorClass} ${className}\" style=\"${colorStyle}\">\n ${dataFloatBox}\n </span>`;\n }\n });\n } //puntos en el floatBox\n\n\n if (tab.floatBox.dots) {\n str += `\n <div class=\"dot-container-middle\">`;\n tab.floatBox.dots.forEach(n => {\n if (_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(data.values, n.varName) !== null) {\n str += `\n <div class=\"dot ${n.color} ${n.shape || \"\"}\"></div>`;\n }\n });\n str += `\n </div>`;\n } //fila de puntos en floatBox\n\n\n if (tab.floatBox.rowDots) {\n tab.floatBox.rowDots.forEach(row => {\n let freeColumns = 4;\n str += `<span class=\"rowdot--row \">`;\n row.forEach(dot => {\n if (tab.legends && dot.tabKey) {\n let legend = tab.legends.find(l => l.key == dot.tabKey);\n if (legend && !legend.active) return;\n }\n\n let dataFloatBox = null;\n let className = \"\";\n let showIf = true;\n let hideIf = false;\n let colorClass = \"\";\n let colorStyle = \"\";\n\n if (dot.varName) {\n dataFloatBox = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(data.values, dot.varName);\n dataFloatBox = parseInt(dataFloatBox);\n }\n\n if (dot.varShow) {\n showIf = Boolean(_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(data.values, dot.varShow));\n dataFloatBox = dataFloatBox || \"\";\n }\n\n if (dot.varHide) {\n hideIf = Boolean(_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(data.values, dot.varHide));\n }\n\n if (dot.shape) {\n className += \" shape-\" + dot.shape;\n }\n\n if (dot.color) {\n if (_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].isHexColor(dot.color)) {\n colorStyle = `--local-color: ${dot.color}`;\n } else {\n colorClass = dot.color;\n }\n }\n\n if (dataFloatBox !== null && dataFloatBox > 0 && showIf && !hideIf && freeColumns > 0) {\n let n = dataFloatBox > freeColumns ? freeColumns : dataFloatBox;\n freeColumns -= n;\n\n for (let index = 0; index < n; index++) {\n str += `<div class=\"rowdot--dot ${colorClass} ${className}\" style=\"${colorStyle}\"></div>`;\n }\n }\n });\n str += `</span>`;\n });\n }\n }\n\n str += `\n </div>`;\n let $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n $elem.addEventListener(\"mouseover\", e => {\n $elem.dispatchEvent(new CustomEvent(\"mouseOverFloatBox\", {\n bubbles: true,\n cancelable: false,\n detail: {\n item: ds,\n data: data,\n originalEvt: e\n }\n }));\n });\n $elem.addEventListener(\"click\", e => {\n $elem.dispatchEvent(new CustomEvent(\"clickFloatBox\", {\n bubbles: true,\n cancelable: false,\n detail: {\n item: ds,\n data: data,\n originalEvt: e\n }\n }));\n });\n $container.appendChild($elem);\n });\n });\n });\n return $container;\n },\n\n /**\n * Crea DetailDay, detalle de valores de item y Dia\n * se usa para:\n * - Muestra nombre de item y detalles\n * - Muestra capsulas de datos\n * - Muestra Pills, pildoras de datos resumidos\n * - Muestra alertas\n * - Muestra Mensaje\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} item - Item relacionado\n * @param {Object} dataDay - valores de item y Dia\n * @param {Boolean} [onlyStringContent = false] - para escoger si devuelve String o DomElement\n * @return {String|Object} Elemento como String o DomElement\n */\n createDetailDay(config, item = {}, dataDay, tabSelected, onlyStringContent = false) {\n let str = `\n <div class=\"header-detail\">\n <div class=\"title truncate\">\n ${item.label || \"\"}\n </div>\n <div class=\"subtitle\">\n ${dataDay ? _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].formatDateReadeable(dataDay.date) : \"\"}\n </div>\n </div>\n\n <div class=\"list-detail list\">`; //CAPSULES\n\n if (dataDay) {\n config.timeline.detailDay.capsules.forEach(cap => {\n //para comprobar si tiene datos, se obtiene el primer valor\n //de la lista de values de una capsula\n let hasValues = cap.values.filter(v => _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay.values, v.varName)).length > 0;\n let hideIf = false;\n\n if (cap.hideIf) {\n hideIf = Boolean(_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay.values, cap.hideIf));\n }\n\n let colorClass = \"\";\n let colorStyle = \"\";\n\n if (cap.color) {\n if (_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].isHexColor(cap.color)) {\n colorStyle = `--local-color: ${cap.color};`;\n colorStyle += `--local-color-font: ${cap.color};`;\n } else {\n colorClass = cap.color;\n }\n }\n\n if (hasValues && !hideIf) {\n str += `\n <div class=\"item-detail ${colorClass}\" style=\"${colorStyle}\">\n\n <div class=\"left-icon ${cap.shape || \"\"} \"></div>\n\n <div class=\"name\">\n <span>\n ${cap.title || \"\"}\n </span>\n </div>`;\n str += `\n <div class=\"item-description\"> `;\n cap.values.forEach(v => {\n let value = v.varName ? _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay.values, v.varName) : null;\n\n if (cap.isLabeledArray) {\n value.forEach(valueLabeled => {\n let outputValue = null;\n let valueName = v.valueName ? v.valueName : \"value\";\n let tempValue = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(valueLabeled, valueName);\n\n if (tempValue) {\n outputValue = v.round ? _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].round(tempValue, v.round) : tempValue;\n }\n\n if (v.formatter) {\n outputValue = v.formatter(valueLabeled);\n }\n\n if (typeof outputValue == \"number\") {\n outputValue = new Intl.NumberFormat().format(outputValue);\n }\n\n str += outputValue == null ? \"\" : `\n <div class=\"desc ${v.showColumn ? 'desc-column' : ''}\">\n <div class=\"label\">\n ${v.hideLabel ? \"\" : valueLabeled.label}\n </div >\n <div class=\"val\">\n <span class=\"prefix\">\n ${v.prefix || \"\"}\n </span>\n <span class=\"value\">\n ${outputValue}\n </span>\n <span class=\"suffix\">\n ${valueLabeled.suffix || v.suffix || \"\"}\n </span>\n </div>\n </div>`;\n });\n } else {\n let outputValue = v.round ? _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].round(value, v.round) : value;\n\n if (v.formatter) {\n outputValue = v.formatter({\n options: v,\n dataDay,\n outputValue\n });\n }\n\n if (typeof outputValue == \"number\") {\n outputValue = new Intl.NumberFormat().format(outputValue);\n }\n\n str += outputValue == null ? \"\" : `\n <div class=\"desc\">\n <span class=\"prefix\">\n ${v.prefix || \"\"}\n </span>\n <span class=\"value\">\n ${outputValue}\n </span>\n <span class=\"suffix\">\n ${v.suffix || \"\"}\n </span>\n </div>`;\n }\n });\n str += `\n </div>`;\n str += `\n </div>`; // end .item-detail\n }\n });\n }\n\n str += `\n </div>`; // list-detail\n //PILLS\n\n if (config.timeline.detailDay.pillsVarName && dataDay && dataDay.values[config.timeline.detailDay.pillsVarName]) {\n str += `\n <div class=\"elements-detail\">\n <div class=\"name\"> ${config.timeline.detailDay.pillsTitle} </div>\n <div class=\"elements-list\">`;\n dataDay.values[config.timeline.detailDay.pillsVarName].forEach(e => {\n let value = e.value;\n\n if (typeof outputValue == \"number\") {\n value = new Intl.NumberFormat().format(value);\n }\n\n str += `\n <div class=\"element-detail\">\n <b>${e.label}</b>\n ${value}\n </div>`;\n });\n str += `\n </div>\n </div>`; //end .element-detail > .element-list\n } //str += `</div>`;\n\n\n if (dataDay && dataDay.errors && dataDay.errors.length > 0) {\n dataDay.errors.forEach(err => {\n let alertIcon = `<span class=\"alert-icon\">\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M13 14H11V9H13M13 18H11V16H13M1 21H23L12 2L1 21Z\" />\n </svg>\n </span>`;\n str += `\n <div class=\"alert\">\n ${alertIcon}\n ${err.label}\n </div>`;\n });\n }\n\n let msg = null;\n let author = null;\n let dateMsg = null;\n\n if (dataDay) {\n msg = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, tabSelected.floatBox.messagePath);\n\n if (!msg && dataDay.message && dataDay.message.value) {\n msg = dataDay.message.value;\n author = dataDay.message.author;\n dateMsg = _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].formatDateReadeable(new Date(dataDay.message.date));\n }\n }\n\n if (msg) {\n //msg = msg.replace(/(\\r\\n|\\r|\\n)/g, '<br>');\n str += `\n <div class=\"msj-container\">\n <div class=\"msj\">\n <pre>${msg || \"\"}</pre>\n </div>\n <div class=\"msj-detail\">\n <span class=\"email\"> ${author || \"\"} </span>\n <span class=\"date\"> ${dateMsg || \"\"} </span>\n </div>\n </div>`;\n }\n\n let strContainer = `<div class=\"detail-day dd-hide\"> ${str} </div>`;\n if (onlyStringContent) return str;\n return _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(strContainer);\n },\n\n /**\n * Recrea HTML de detailDay\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} item - Item relacionado\n * @param {Object} dataDay - valores de item y Dia\n * @return {String} Elemento como String, de detailDay\n */\n redrawDetailDay(config, item, dataDay, tabSelected) {\n return this.createDetailDay(config, item, dataDay, tabSelected, true);\n },\n\n /**\n * Reposiciona FloatBox\n * verifica si el parent esta desplegado, para ocultar los datos\n *\n * Solo actualiza las alturas de los floatbox\n * no recrea los floatbox, es mas optimo\n *\n * @param {Object} config - Configuracion capibara\n * @param {Object} item - Item relacionado\n */\n repositionFloatBox(config, $floatBoxContainer) {\n $floatBoxContainer.querySelectorAll(\".float-box\").forEach($f => {\n let itemId = $f.getAttribute(\"item-id\");\n let itemHeight = parseFloat(_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getCSSVariable(config, \"--item-height\"));\n let item, parent;\n ({\n item,\n parent\n } = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getItemById(config, itemId, \"child\", true));\n\n if (item) {\n let top = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getPositionByItem(config, item);\n $f.style.top = top * itemHeight + \"px\";\n\n if (parent && parent.isClosed) {\n $f.classList.add(\"hide\");\n } else if ($f.classList.contains(\"hide\")) {\n $f.classList.remove(\"hide\");\n }\n }\n });\n },\n\n /**\n * Recrea indicadores de dias seleccionados\n *\n * @param {Object} $elem - Elemento Dom donde crea los elementos seleccionados\n * @param {Object[]} selected - Array con los dias seleccionados\n * @return {Object} Elemento Dom que contiene los indicadores de dias seleccionados\n */\n redrawSelectBoard($elem, selected) {\n $elem.innerHTML = \"\";\n let hasNumber = true;\n\n if (selected) {\n if (selected.length == 1) hasNumber = false;\n selected.forEach(s => {\n let attributes = [];\n\n if (hasNumber) {\n attributes.push({\n name: \"cap-badge\",\n value: s.index\n });\n }\n\n let $s = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", {\n className: \"selected-day\",\n attributes\n });\n $s.style.left = s.pos.left + \"px\";\n $s.style.top = s.pos.top + \"px\";\n $elem.append($s);\n });\n }\n\n return $elem;\n },\n\n /**\n * Obtiene String con estilos CSS de la posicion de un floatBox\n * calculado segun item y fecha de los valores\n *\n * @param {Object} config - Configuracion capibara, para ver fecha de inicio\n * @param {Object} data - Datos del dia indicado\n * @param {Object} item - Item relacionado\n * @return {String} String CSS top y left , para posicionar floatBox en table\n */\n getPositionFloatBox(config, data, item) {\n let left = _util_dateUtils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].diffDays(config.timeline.start, data.date);\n let top = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getPositionByItem(config, item);\n let dayWidth = parseFloat(_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getCSSVariable(config, \"--day-width\"));\n let itemHeight = parseFloat(_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getCSSVariable(config, \"--item-height\"));\n left *= dayWidth;\n top *= itemHeight;\n return \"top: \" + top + \".5px; left:\" + left + \".5px;\";\n },\n\n /**\n * Crea Boton como elemento Dom\n *\n * @param {Object} props - propiedades para boton\n * @param {String} props.className - classes css para boton\n * @param {*} props.key - key para identificar a boton\n * @param {String} props.label - Texto boton\n * @return {Object} Elemento Dom del boton creado\n */\n createButton(props) {\n return _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <button class=\"${props.className || \"\"}\" input-key=\"${props.key || \"\"}\">\n ${props.label || \"\"}\n </button>`);\n },\n\n /**\n * Crea Botones de guardar y cancelar los datos de formulario del sidebar derecho\n *\n * @return {Object} Elemento Dom del botones creados\n */\n createNavRightbuttons() {\n let saveBtn = this.createButton({\n label: \"Guardar\",\n className: \"cap-btn-raised\"\n });\n let cancelBtn = this.createButton({\n label: \"Cancelar\",\n className: \"cap-btn-outline\"\n });\n let btnSection = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`<div class=\"button-section\"></div>`);\n btnSection.appendChild(saveBtn);\n btnSection.appendChild(cancelBtn);\n saveBtn.addEventListener(\"click\", e => {\n saveBtn.dispatchEvent(new CustomEvent(\"saveMultiInput\", {\n bubbles: true,\n cancelable: false\n }));\n });\n cancelBtn.addEventListener(\"click\", e => {\n cancelBtn.dispatchEvent(new CustomEvent(\"cancelMultiInput\", {\n bubbles: true,\n cancelable: false\n }));\n });\n return btnSection;\n },\n\n /**\n * Crea Input como elemento Dom\n *\n * @param {Object} props - config para Input\n * @param {Object} [dataDay = null] - valores de item y Dia, opcional\n * @param {Object} [daySelected = null] - datos del dia seleccionado\n * @return {Object} Elemento Dom del input creado\n */\n createInput(props, dataDay = null, daySelected = null, selected = []) {\n let r = null;\n if (props.isHidden) return r;\n\n switch (props.type) {\n case \"inputList\":\n r = this.createInputList(props, dataDay, daySelected);\n break;\n\n case \"select\":\n r = this.createInputSelect(props, dataDay, daySelected);\n break;\n\n case \"file\":\n r = this.createInputFile(props, dataDay);\n break;\n\n case \"fileLink\":\n r = this.createFileLink(props, dataDay);\n break;\n\n case \"text\":\n r = this.createText(props, selected);\n break;\n\n case \"title\":\n r = this.createTitle(props);\n break;\n\n case \"number\":\n r = this.createInputNumber(props, dataDay);\n break;\n\n case \"float\":\n r = this.createInputFloat(props, dataDay);\n break;\n\n case \"message\":\n r = this.createInputMessage(props, dataDay);\n break;\n\n case \"textarea\":\n r = this.createInputTextArea(props, dataDay);\n break;\n\n case \"checkbox\":\n r = this.createInputCheckbox(props, dataDay);\n break;\n\n case \"input-box\":\n r = this.createInputBox(props, dataDay);\n break;\n\n case \"list\":\n r = this.createList(props, dataDay);\n break;\n\n case \"button\":\n r = this.createInputButton(props, dataDay);\n break;\n\n case \"time\":\n r = this.createInputTime(props, dataDay);\n break;\n\n case \"text\":\n default:\n r = this.createInputText(props, dataDay);\n }\n\n return r;\n },\n\n /**\n * Crea Input con formato Hora, como elemento Dom\n *\n * Usa 2 inputs, hora y minutos\n *\n * el value que interpreta es String HH:MM\n *\n * @param {Object} props - config para Input\n * @param {Object} [dataDay = null] - valores de item y Dia, opcional\n * @return {Object} Elemento Dom del input creado\n */\n createInputTime(props, dataDay) {\n let hhValue = \"\";\n let mmValue = \"\";\n\n if (dataDay && dataDay.values) {\n let value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n\n if (value) {\n value = value.split(\":\");\n hhValue = value[0];\n mmValue = value[1];\n }\n }\n\n let r = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section\" input-key=\"${props.key || \"\"}\">\n <span class=\"text-subtitle d-block\">\n ${props.label || \"\"}\n </span>\n <div class=\"time\">\n <input type=\"number\"\n class=\"hour\"\n id=\"test\"\n placeholder=\"00\"\n min=\"0\"\n max=\"24\"\n value=\"${hhValue}\">\n <span class=\"symbol\">:</span>\n <input type=\"number\"\n class=\"minutes\"\n placeholder=\"00\"\n min=\"0\"\n max=\"59\"\n value=\"${mmValue}\">\n </div>\n </div>`);\n let hh = r.querySelector(\".hour\");\n let mm = r.querySelector(\".minutes\");\n hh.addEventListener(\"input\", e => {\n hh.dispatchEvent(new CustomEvent(\"changeTimeInputHH\", {\n bubbles: true,\n cancelable: false,\n detail: {\n key: props.key,\n value: e.srcElement.value\n }\n }));\n });\n mm.addEventListener(\"input\", e => {\n mm.dispatchEvent(new CustomEvent(\"changeTimeInputMM\", {\n bubbles: true,\n cancelable: false,\n detail: {\n key: props.key,\n value: e.srcElement.value\n }\n }));\n });\n this.addKeyDownInputEvents(hh);\n this.addKeyDownInputEvents(mm);\n return r;\n },\n\n /**\n * Crea Text como elemento Dom\n * Se configura como input, pero no devuelve datos, es un texto\n *\n * @param {Object} props - config para Input\n * @return {Object} Elemento Dom del input creado\n */\n createText(props, selected) {\n let label = props.label;\n\n if (props.formatter) {\n label = props.formatter({\n selected\n });\n }\n\n let $elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section\" input-key=\"${props.key || \"\"}\">\n <span class=\"${props.classNames || \"\"}\">\n ${label}\n </span>\n </div>`);\n return $elem;\n },\n\n /**\n * Crea Title como elemento Dom\n * Se configura como input, pero no devuelve datos, es un texto\n *\n * @param {Object} props - config para Input\n * @return {Object} Elemento Dom del input creado\n */\n createTitle(props) {\n let classNames = \"text-title\";\n\n if (props.isSubtitle) {\n classNames = \"text-subtitle\";\n }\n\n return _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section\" input-key=\"${props.key || \"\"}\">\n <span class=\"${classNames}\">\n ${props.label}\n </span>\n </div>`);\n },\n\n /**\n * Crea Input tipo Numerico como elemento Dom\n *\n * @param {Object} props - config para Input\n * @param {Object} dataDay - valores de item y Dia, opcional\n * @return {Object} Elemento Dom del input creado\n */\n createInputNumber(props, dataDay) {\n let value = \"\";\n\n if (dataDay && dataDay.values) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n }\n\n value = value || \"\";\n let elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section ${props.classNames || \"\"}\" input-key=\"${props.key || \"\"}\">\n <div class=\"input-section-title\">\n <span class=\"text-subtitle\">\n ${props.label}\n </span>\n <span class=\"text-subtitle-2 \">\n ${props.suffix ? \"(\" + props.suffix + \")\" : \"\"}\n </span>\n </div>\n <input type=\"number\"\n class=\"nav-input\"\n value=\"${value}\">\n </div>`);\n let inputElem = elem.querySelector(\"input\");\n this.addKeyDownInputEvents(inputElem);\n return elem;\n },\n\n /**\n * Crea Input tipo FIlepicker como elemento Dom\n *\n * @param {Object} props - config para Input\n * @param {Object} dataDay - valores de item y Dia, opcional\n * @return {Object} Elemento Dom del input creado\n */\n createInputFile(props, dataDay) {\n let value = \"\";\n let fileName = \"\";\n let filePath = \"\";\n\n if (dataDay && dataDay.values) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n fileName = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.fileNameValue);\n filePath = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.filePathValue);\n }\n\n value = value || \"\";\n fileName = fileName || \"\";\n filePath = filePath || \"\";\n let elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section ${props.classNames || \"\"}\" input-key=\"${props.key || \"\"}\">\n\n <div class=\"input-section-title\">\n <span class=\"text-subtitle\">\n ${props.label}\n </span>\n </div>\n\n <div class=\"nav-input-file\" >\n <button class=\"small-close clear-file-input\">x</button>\n <label >\n <span class=\"nav-input-file-label\">\n ${props.pickerLabel || \"Seleccionar Archivo\"}\n </span>\n <input type=\"file\" value=\"${value}\">\n </label>\n </div>\n\n <div class=\"input-section-link\">\n <a href=\"${filePath}\" target=\"_blank\" >\n ${fileName}\n </a>\n </div>\n\n </div>`);\n let $inputElem = elem.querySelector(\"input\");\n let $clearBtn = elem.querySelector(\".clear-file-input\");\n let $fileInputLabel = elem.querySelector(\".nav-input-file-label\");\n $inputElem.addEventListener(\"change\", evt => {\n let fileName = $inputElem.files[0].name;\n $fileInputLabel.textContent = fileName;\n });\n $clearBtn.addEventListener(\"click\", evt => {\n $inputElem.value = \"\";\n $fileInputLabel.textContent = props.pickerLabel || \"Seleccionar Archivo\";\n evt.stopPropagation();\n });\n return elem;\n },\n\n createFileLink(props, dataDay) {\n let fileName = \"\";\n let filePath = \"\";\n\n if (dataDay && dataDay.values) {\n //value = utils.getVarByPath(dataDay, props.varName);\n fileName = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.fileNameValue);\n filePath = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.filePathValue);\n }\n\n if (fileName == \"\") return null;\n fileName = fileName || \"\";\n filePath = filePath || \"\";\n let elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section ${props.classNames || \"\"}\" input-key=\"${props.key || \"\"}\">\n\n <div class=\"input-section-title\">\n <span class=\"text-subtitle\">\n ${props.label}\n </span>\n </div>\n\n <div class=\"input-section-link\">\n <a href=\"${filePath}\" target=\"_blank\" >\n ${fileName}\n </a>\n </div>\n\n </div>`);\n return elem;\n },\n\n /**\n * Crea lista de Inputs, con array de valores, como elemento Dom\n *\n * @param {Object} props - config para Input\n * @param {Object} dataDay - valores de item y Dia, opcional\n * @param {Object} [daySelected = null] - datos del dia seleccionado\n * @return {Object} Elemento Dom del input creado\n */\n createInputList(props, dataDay, daySelected = null) {\n let value = null;\n let inputList = []; //obtiene inputs default, para crearlos, sin valores\n\n if (daySelected && Array.isArray(daySelected.item.values[props.inputList])) {\n inputList = daySelected.item.values[props.inputList].map(inputRow => {\n //limpia inputList inputs\n inputRow.inputs.map(input => {\n input.value = null;\n return input;\n }); //obtiene valores del dia\n\n if (dataDay && dataDay.values) {\n let inputValues = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.valuesPath); //autorrellena\n\n if (inputValues) {\n inputRow.inputs.forEach(input => {\n let values = inputValues.find(v => v.id == inputRow.id);\n input.value = values ? values[input.varName] : null;\n });\n }\n }\n\n return inputRow;\n });\n }\n\n let str = `<div input-key=\"${props.key || \"\"}\" >`;\n inputList.forEach(inputRow => {\n str += `\n <div class=\"input-section \" >\n <span class=\"text-subtitle\">\n ${inputRow.label}\n </span>`;\n inputRow.inputs.forEach(input => {\n str += ` \n <div class=\"input-section-col\" >\n <span class=\"text-subtitle \">\n ${input.label}\n </span>\n <input type=\"number\"\n input-id=\"${inputRow.id}\"\n input-label=\"${input.label}\"\n class=\"nav-input\"\n value=\"${input.value}\">\n </div>`;\n });\n str += `\n </div>`;\n });\n str += `</div>`;\n let elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n let inputsElem = elem.querySelectorAll(\"input\");\n inputsElem.forEach(inputElem => this.addKeyDownInputEvents(inputElem));\n return elem;\n },\n\n createInputSelect(props, dataDay, daySelected = null) {\n let value = null;\n let options = props.options;\n\n if (dataDay && dataDay.values) {\n let val = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n value = val ? val.value : null;\n }\n\n let str = `<div input-key=\"${props.key || \"\"}\" >\n <div class=\"input-section \" >\n <span class=\"text-subtitle\">\n ${props.label}\n </span>\n\n <select class=\"input-select\">\n\n <option value=\"\" ${value == null ? 'selected' : ''}>\n ${props.noDataLabel || \"-- sin asignar --\"}\n </option>\n\n `;\n options.forEach(option => {\n str += `\n <option value=\"${option.id}\" ${option.id == value ? 'selected' : ''}>\n ${option.label}\n </option>\n `;\n });\n str += `\n\n </select>\n </div>\n\n </div>`;\n let elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n return elem;\n },\n\n /**\n * Crea Input de texto TextArea como elemento Dom\n *\n * @param {Object} props - config para Input\n * @param {Object} dataDay - valores de item y Dia, opcional\n * @return {Object} Elemento Dom del input creado\n */\n createInputTextArea(props, dataDay) {\n let value = \"\";\n\n if (dataDay && dataDay.values) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n }\n\n let elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section\" input-key=\"${props.key || \"\"}\">\n <span class=\"text-subtitle d-block\">\n ${props.label}\n </span>\n <textarea class=\"\" value=\"${value}\"></textarea>\n </div>`);\n let inputElem = elem.querySelector(\"textarea\");\n this.addKeyDownInputEvents(inputElem);\n return elem;\n },\n\n /**\n * Crea Input de Mensaje como elemento Dom\n * utiliza TextArea\n *\n * @param {Object} props - config para Input\n * @param {Object} dataDay - valores de item y Dia, opcional\n * @return {Object} Elemento Dom del input creado\n */\n createInputMessage(props, dataDay) {\n let value = dataDay ? _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName) : null;\n let elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section msj-input-container\"\n input-key=\"${props.key || \"\"}\">\n <span class=\"text-subtitle d-block\">\n Mensaje\n </span>\n <textarea class=\"msj\">${value || \"\"}</textarea>\n </div>`);\n let inputElem = elem.querySelector(\"textarea\"); //this.addKeyDownInputEvents(inputElem);\n\n return elem;\n },\n\n /**\n * Crea Input de texto como elemento Dom\n *\n * @param {Object} props - config para Input\n * @param {Object} dataDay - valores de item y Dia, opcional\n * @return {Object} Elemento Dom del input creado\n */\n createInputText(props, dataDay) {\n let value = \"\";\n\n if (dataDay && dataDay.values) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n }\n\n let elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section\" input-key=\"${props.key || \"\"}\">\n <span class=\"text-subtitle d-block\">\n ${props.label}\n </span>\n <input type=\"text\" class=\"nav-input\" value=\"${value}\">\n </div>`);\n let inputElem = elem.querySelector(\"input\");\n this.addKeyDownInputEvents(inputElem);\n return elem;\n },\n\n /**\n * Crea Input Numero Flotante, como elemento Dom\n *\n * @param {Object} props - config para Input\n * @param {Object} dataDay - valores de item y Dia, opcional\n * @return {Object} Elemento Dom del input creado\n */\n createInputFloat(props, dataDay) {\n let value = \"\";\n\n if (dataDay && dataDay.values) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n }\n\n let elem = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section\" input-key=\"${props.key || \"\"}\">\n <span class=\"text-subtitle d-block\">\n ${props.label}\n </span>\n <input type=\"number\" class=\"nav-input\" value=\"${value}\">\n </div>`);\n let inputElem = elem.querySelector(\"input\");\n this.addKeyDownInputEvents(inputElem);\n return elem;\n },\n\n createList(props, dataDay) {\n let value = [];\n\n if (dataDay && dataDay.values) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n }\n\n let tabsContainer = \"\";\n\n if (props.tabs) {\n let tabs = \"\";\n props.tabs.forEach(tab => {\n tabs += `\n <div class=\"input-box-tab\" tab-key=\"${tab.key}\">\n ${tab.name}\n </div>`;\n });\n tabsContainer = `\n <div class=\"input-box-tab-container\">\n ${tabs}\n </div>\n `;\n }\n\n let closeIcon = `<span class=\"close-icon\">\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z\" />\n </svg>\n </span>`;\n let linkIcon = ` <span class=\"close-icon\">\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M14,3V5H17.59L7.76,14.83L9.17,16.24L19,6.41V10H21V3M19,19H5V5H12V3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V12H19V19Z\" />\n </svg>\n </span>\n `;\n let searchInput = `\n <div class=\"search-input-container\">\n <input id=\"\" type=\"text\" name=\"\" class=\"search-input\" placeholder=\"buscar\">\n <button class=\"search-input-clear\">\n ${closeIcon}\n </button>\n </div>\n `;\n let str = `\n <div class=\"input-section\" input-key=\"${props.key || \"\"}\">\n <span class=\"text-subtitle d-block\">\n ${props.label}\n </span>\n\n ${tabsContainer}\n <div class=\"input-box \" input-key=\"${props.key || \"\"}\">\n\n ${searchInput}\n `; //TODO obtener input segun fila\n\n if (props.inputs) {\n props.inputs.forEach(i => {\n if (i.isTitle) {\n let tooltip = \"\";\n let icon = \"\";\n\n if (i.tooltip) {\n tooltip = `\n <div class=\"mini-input-section--tooltip\">\n ${i.tooltip}\n ${i.suffix ? \"(\" + i.suffix + \")\" : \"\"}\n </div>`;\n }\n\n if (i.colorIcon) {\n if (_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].isHexColor(i.colorIcon)) {\n icon = `<div class=\"mini-input-section--icon\" style=\"background:${i.colorIcon}\"> </div>`;\n } else {\n icon = `<div class=\"mini-input-section--icon ${i.colorIcon}\"> </div>`;\n }\n }\n\n str += `\n <div class=\"mini-input-section is-title\" input-tab-key=\"${i.tabKey || \"\"}\" label=\"${i.label}\">\n <label>\n ${icon}\n <div class=\"mini-input-section--title truncate\">\n ${i.label}\n </div>\n </label>\n ${tooltip}\n </div>`;\n } else {\n let value_found = value ? value.find(val => val.id == i.id) : null;\n let v = value_found || \"\";\n let inputValue = props.varNameInput && v[props.varNameInput] ? v[props.varNameInput] : v.value;\n let tooltip = \"\";\n let icon = \"\";\n let link = \"\";\n\n if (i.tooltip) {\n tooltip = `\n <div class=\"mini-input-section--tooltip\">\n ${i.tooltip}\n </div>`;\n }\n\n if (i.colorIcon) {\n if (_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].isHexColor(i.colorIcon)) {\n icon = `<div class=\"mini-input-section--icon\" style=\"background:${i.colorIcon}\"> </div>`;\n } else {\n icon = `<div class=\"mini-input-section--icon ${i.colorIcon}\"> </div>`;\n }\n }\n\n if (i.link) {\n link = `<a class=\"mini-input-section--link\" target=\"_blank\" href=\"${i.link}\">\n ${linkIcon}\n </a> `;\n }\n\n str += `\n <div class=\"mini-input-section\" input-tab-key=\"${i.tabKey || \"\"}\" label=\"${i.label}\">\n <label>\n\n ${icon}\n\n <div class=\"mini-input-section--name truncate\">\n ${i.label}\n </div>\n\n <div class=\"mini-input-section--suffix\" >${i.suffix ? \"(\" + i.suffix + \")\" : \"\"}</div>\n\n ${link}\n\n </label>\n <div class=\"mini-input-section--footer\">\n <span class=\"start\"> test </span>\n <span class=\"end\"> test end </span>\n </div>\n ${tooltip}\n </div>`;\n }\n });\n }\n\n str += `\n </div>\n </div> `;\n let $el = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n let $tabs = $el.querySelectorAll(\".input-box-tab[tab-key]\") || [];\n let $searchInput = $el.querySelector(\".search-input\") || null;\n let $searchInputClear = $el.querySelector(\".search-input-clear\") || null;\n $tabs.forEach(t => {\n t.addEventListener(\"click\", e => {\n this.selectInputBoxTab(t, $el);\n $searchInput.value = \"\";\n $searchInput.dispatchEvent(new Event('input', {\n bubbles: true\n }));\n });\n });\n\n if ($searchInputClear) {\n $searchInputClear.addEventListener(\"click\", e => {\n $searchInput.value = \"\";\n $searchInput.dispatchEvent(new Event('input', {\n bubbles: true\n }));\n });\n }\n\n if ($searchInput) {\n $searchInput.addEventListener('keydown', e => {\n if (e.key === \"Escape\") {\n $searchInput.value = \"\";\n $searchInput.dispatchEvent(new Event('input', {\n bubbles: true\n }));\n }\n });\n $searchInput.addEventListener(\"input\", e => {\n let $tabSelected = $el.querySelector(\".input-box-tab[tab-key].active\") || null;\n let $inputs = [];\n\n if ($tabSelected) {\n let tabKey = $tabSelected.getAttribute(\"tab-key\");\n $inputs = $el.querySelectorAll(\".mini-input-section[input-tab-key='\" + tabKey + \"']\") || [];\n } else {\n $inputs = $el.querySelectorAll(\".mini-input-section\") || [];\n }\n\n $inputs.forEach($i => {\n let label = $i.getAttribute(\"label\");\n let search = $searchInput.value;\n\n if (label.toLowerCase().includes(search.toLowerCase())) {\n $i.classList.remove(\"hide\");\n } else {\n $i.classList.add(\"hide\");\n }\n });\n });\n }\n\n this.selectInputBoxTab(_.first($tabs), $el);\n return $el;\n },\n\n /**\n * Crea InputBox, como elemento Dom\n * un InputBox es un contenedor con una lista de inputs\n *\n * @param {Object} props - config para Input\n * @param {Object} dataDay - valores de item y Dia, opcional\n * @return {Object} Elemento Dom del input creado\n */\n createInputBox(props, dataDay) {\n let value = [];\n\n if (dataDay && dataDay.values) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n }\n\n let tabsContainer = \"\";\n\n if (props.tabs) {\n let tabs = \"\";\n props.tabs.forEach(tab => {\n tabs += `\n <div class=\"input-box-tab\" tab-key=\"${tab.key}\">\n ${tab.name}\n </div>`;\n });\n tabsContainer = `\n <div class=\"input-box-tab-container\">\n ${tabs}\n </div>\n `;\n }\n\n let closeIcon = `<span class=\"close-icon\">\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z\" />\n </svg>\n </span>`;\n let linkIcon = ` <span class=\"close-icon\">\n <svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M14,3V5H17.59L7.76,14.83L9.17,16.24L19,6.41V10H21V3M19,19H5V5H12V3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V12H19V19Z\" />\n </svg>\n </span>\n `;\n let searchInput = `\n <div class=\"search-input-container\">\n <input id=\"\" type=\"text\" name=\"\" class=\"search-input\" placeholder=\"buscar\">\n <button class=\"search-input-clear\">\n ${closeIcon}\n </button>\n </div>\n `;\n let str = `\n <div class=\"input-section\" input-key=\"${props.key || \"\"}\">\n <span class=\"text-subtitle d-block\">\n ${props.label}\n </span>\n\n ${tabsContainer}\n <div class=\"input-box \" input-key=\"${props.key || \"\"}\">\n\n ${searchInput}\n `;\n\n if (props.inputs) {\n props.inputs.forEach(i => {\n if (i.isTitle) {\n let tooltip = \"\";\n let icon = \"\";\n\n if (i.tooltip) {\n tooltip = `\n <div class=\"mini-input-section--tooltip\">\n ${i.tooltip}\n ${i.suffix ? \"(\" + i.suffix + \")\" : \"\"}\n </div>`;\n }\n\n if (i.colorIcon) {\n if (_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].isHexColor(i.colorIcon)) {\n icon = `<div class=\"mini-input-section--icon\" style=\"background:${i.colorIcon}\"> </div>`;\n } else {\n icon = `<div class=\"mini-input-section--icon ${i.colorIcon}\"> </div>`;\n }\n }\n\n str += `\n <div class=\"mini-input-section is-title\" input-tab-key=\"${i.tabKey || \"\"}\" label=\"${i.label}\">\n <label>\n ${icon}\n <div class=\"mini-input-section--title truncate\">\n ${i.label}\n </div>\n </label>\n ${tooltip}\n </div>`;\n } else {\n let value_found = value ? value.find(val => val.id == i.id) : null;\n let v = value_found || \"\";\n let inputValue = props.varNameInput && v[props.varNameInput] ? v[props.varNameInput] : v.value;\n let tooltip = \"\";\n let icon = \"\";\n let link = \"\";\n\n if (i.tooltip) {\n tooltip = `\n <div class=\"mini-input-section--tooltip\">\n ${i.tooltip}\n </div>`;\n }\n\n if (i.colorIcon) {\n if (_util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].isHexColor(i.colorIcon)) {\n icon = `<div class=\"mini-input-section--icon\" style=\"background:${i.colorIcon}\"> </div>`;\n } else {\n icon = `<div class=\"mini-input-section--icon ${i.colorIcon}\"> </div>`;\n }\n }\n\n if (i.link) {\n link = `<a class=\"mini-input-section--link\" target=\"_blank\" href=\"${i.link}\">\n ${linkIcon}\n </a> `;\n }\n\n str += `\n <div class=\"mini-input-section\" input-tab-key=\"${i.tabKey || \"\"}\" label=\"${i.label}\">\n <label>\n <input type=\"number\"\n class=\"mini-input\"\n input-id=\"${i.id || \"\"}\"\n input-key=\"${i.key || i.label}\"\n value=\"${inputValue || \"\"}\">\n\n ${icon}\n\n <div class=\"mini-input-section--name truncate\">\n ${i.label}\n </div>\n\n <div class=\"mini-input-section--suffix\" >${i.suffix ? \"(\" + i.suffix + \")\" : \"\"}</div>\n\n ${link}\n\n </label>\n ${tooltip}\n </div>`;\n }\n });\n }\n\n str += `\n </div>\n </div> `;\n let $el = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(str);\n let $tabs = $el.querySelectorAll(\".input-box-tab[tab-key]\") || [];\n let $inputs = $el.querySelectorAll(\"input.mini-input\") || [];\n let $searchInput = $el.querySelector(\".search-input\") || null;\n let $searchInputClear = $el.querySelector(\".search-input-clear\") || null;\n $tabs.forEach(t => {\n t.addEventListener(\"click\", e => {\n this.selectInputBoxTab(t, $el);\n $searchInput.value = \"\";\n $searchInput.dispatchEvent(new Event('input', {\n bubbles: true\n }));\n });\n });\n\n if ($searchInputClear) {\n $searchInputClear.addEventListener(\"click\", e => {\n $searchInput.value = \"\";\n $searchInput.dispatchEvent(new Event('input', {\n bubbles: true\n }));\n });\n }\n\n if ($searchInput) {\n $searchInput.addEventListener('keydown', e => {\n if (e.key === \"Escape\") {\n $searchInput.value = \"\";\n $searchInput.dispatchEvent(new Event('input', {\n bubbles: true\n }));\n }\n });\n $searchInput.addEventListener(\"input\", e => {\n let $tabSelected = $el.querySelector(\".input-box-tab[tab-key].active\") || null;\n let $inputs = [];\n\n if ($tabSelected) {\n let tabKey = $tabSelected.getAttribute(\"tab-key\");\n $inputs = $el.querySelectorAll(\".mini-input-section[input-tab-key='\" + tabKey + \"']\") || [];\n } else {\n $inputs = $el.querySelectorAll(\".mini-input-section\") || [];\n }\n\n $inputs.forEach($i => {\n let label = $i.getAttribute(\"label\");\n let search = $searchInput.value;\n\n if (label.toLowerCase().includes(search.toLowerCase())) {\n $i.classList.remove(\"hide\");\n } else {\n $i.classList.add(\"hide\");\n }\n });\n });\n }\n\n this.selectInputBoxTab(_.first($tabs), $el);\n $inputs.forEach(i => this.addKeyDownInputEvents(i));\n return $el;\n },\n\n selectInputBoxTab($tab, $el) {\n let $tabs = $el.querySelectorAll(\".input-box-tab[tab-key]\") || [];\n let $inputSections = $el.querySelectorAll(\".mini-input-section\") || [];\n $tabs.forEach(t => {\n t.classList.remove(\"active\");\n });\n\n if ($tab) {\n $tab.classList.add(\"active\");\n $inputSections.forEach(i => {\n let key = i.getAttribute(\"input-tab-key\");\n\n if (key == $tab.getAttribute(\"tab-key\")) {\n i.classList.remove(\"hide\");\n } else {\n i.classList.add(\"hide\");\n }\n });\n }\n },\n\n /**\n * Crea Checkbox, como elemento Dom\n *\n * @param {Object} props - config para Input\n * @param {Object} dataDay - valores de item y Dia, opcional\n * @return {Object} Elemento Dom del input creado\n */\n createInputCheckbox(props, dataDay) {\n let value = \"\";\n\n if (dataDay && dataDay.values) {\n value = _util_utils__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getVarByPath(dataDay, props.varName);\n }\n\n let r = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section\" input-key=\"${props.key || \"\"}\">\n <label>\n <input type=\"checkbox\" name=\"${props.key || \"\"}\" input-key=\"${props.key || \"\"}\" ${value ? \"checked\" : \"\"}>\n ${props.label}\n </label>\n </div>`);\n return r;\n },\n\n createInputButton(props) {\n let r = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(`\n <div class=\"input-section\" input-key=\"${props.key || \"\"}\">\n <button name=\"${props.key || \"\"}\" input-key=\"${props.key || \"\"}\" class=\"cap-btn-outline\">\n ${props.label}\n </button>\n </div>`);\n let button = r.querySelector(\"button\");\n button.addEventListener(\"click\", e => props.onClick({\n props,\n event: e\n }));\n return r;\n },\n\n addKeyDownInputEvents(input) {\n input.addEventListener(\"keydown\", function (event) {\n if (event.keyCode === 13) {\n //ENTER\n input.dispatchEvent(new CustomEvent(\"saveMultiInput\", {\n bubbles: true,\n cancelable: false\n }));\n }\n\n if (event.keyCode === 27) {\n //ESC\n input.dispatchEvent(new CustomEvent(\"cancelMultiInput\", {\n bubbles: true,\n cancelable: false\n }));\n }\n });\n },\n\n createContextMenu({\n config,\n $capibaraElem = null,\n evt = null,\n date = null,\n item = null,\n selected = [],\n tabSelected = null,\n left = null,\n top = null,\n name = \"\"\n }) {\n if (config.timeline.contextMenu === undefined) return {\n elem: null,\n isVisible: false\n };\n let className = \"\";\n let style = \"\";\n let strHtml = \"\";\n let leftPosition = null;\n let topPosition = null;\n let isVisible = true;\n let boundRectCapibara = null;\n let gap = 15; //px\n\n if ($capibaraElem) {\n boundRectCapibara = $capibaraElem.getBoundingClientRect();\n }\n\n if (evt && boundRectCapibara) {\n left = evt.clientX;\n top = evt.clientY - boundRectCapibara.top;\n }\n\n if (left) {\n leftPosition = left;\n }\n\n if (top) {\n topPosition = top;\n }\n\n if (leftPosition !== null & topPosition !== null) {\n if (boundRectCapibara) {\n let transformStyle = \"\";\n\n if (topPosition > boundRectCapibara.height * 2 / 6 && topPosition <= boundRectCapibara.height * 4 / 6) {\n transformStyle += `translateY(-50%)`;\n }\n\n if (topPosition > boundRectCapibara.height * 4 / 6) {\n transformStyle += `translateY(-100%)`;\n }\n\n if (leftPosition > boundRectCapibara.width * 4 / 6) {\n transformStyle += `translateX(-100%)`;\n leftPosition -= gap;\n } else {\n leftPosition += gap;\n }\n\n if (transformStyle != \"\") {\n style += ` transform: ${transformStyle};`;\n }\n }\n\n style += `top: ${topPosition}px; left: ${leftPosition}px;`;\n } else {\n className += \"cm-hide\";\n isVisible = false;\n }\n\n strHtml += ` <div class=\"cap-context-menu-container ${className}\">\n <div class=\"cap-context-menu\" style=\"${style}\">\n </div>\n </div>`;\n let $contextMenuContainer = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(strHtml);\n let $contextMenu = $contextMenuContainer.querySelector(\".cap-context-menu\");\n config.timeline.contextMenu.options.forEach(option => {\n if (option.showIf) {\n let show = option.showIf({\n item,\n date,\n selected,\n name,\n tabSelected\n });\n if (!show) return;\n }\n\n let isEnabled = true;\n let isClickeable = true;\n\n if (option.enableIf) {\n isEnabled = option.enableIf({\n item,\n date,\n selected,\n name,\n tabSelected\n });\n }\n\n let optionClassName = \"\";\n let strIcon = \"\";\n let label = \"\";\n\n if (!isEnabled) {\n optionClassName += \"is-disabled \";\n }\n\n if (option.isDivider) {\n isClickeable = false;\n optionClassName += \"is-divider \";\n }\n\n if (option.label) {\n label = `<span>${option.label}</span>`;\n }\n\n if (option.icon) {\n strIcon = `<div class=\"cap-context-menu_item_icon\">\n <svg viewBox=\"0 0 24 24\">\n <path d=\"${option.icon}\" />\n </svg>\n </div>`;\n }\n\n let optionStrHtml = `\n <div class=\"cap-context-menu_item ${optionClassName}\">\n ${strIcon}\n ${label}\n </div>`;\n let $option = _util_domUtils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElementFromHTML(optionStrHtml);\n\n if (isEnabled && isClickeable) {\n $option.addEventListener(\"click\", evtClick => option.onClick({\n config,\n evt: evtClick,\n date,\n item,\n selected,\n tabSelected\n }));\n } else {\n $option.addEventListener(\"click\", evtClick => {\n evtClick.preventDefault();\n evtClick.stopPropagation();\n });\n }\n\n $contextMenu.append($option);\n });\n return {\n elem: $contextMenuContainer,\n isVisible\n };\n }\n\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvdXRpbC90YWJsZUVsZW1lbnRzLmpzLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vQ2FwaWJhcmEvLi9zcmMvdXRpbC90YWJsZUVsZW1lbnRzLmpzPzFkODYiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGRvbSBmcm9tIFwiLi4vdXRpbC9kb21VdGlsc1wiO1xuaW1wb3J0IHV0aWxzIGZyb20gXCIuLi91dGlsL3V0aWxzXCI7XG5pbXBvcnQgZGF0ZVV0aWxzIGZyb20gXCIuLi91dGlsL2RhdGVVdGlsc1wiO1xuXG5leHBvcnQgZGVmYXVsdCB7XG4gIC8qKlxuICAgKiBDcmVhIGVsZW1lbnRvIFRhYmxlXG4gICAqIENvbnRlbmRyw6EgbG9zIGVsZW1lbnRvcyBxdWUgYXBhcmVjZXJhbiBkZW50cm8gZGUgbGEgdGFibGEgZGUgcGxhbmlsbGFcbiAgICogU2UgVXNhIHBhcmEgOlxuICAgKiAgICAtIEFncmVnYXIgYmFja2dyb3VuZCBjb24gcGF0cm9uIGVzdGlsbyB0YWJsYVxuICAgKiAgICAtIEFncmVnYXIgZGF5TW91c2VPdmVyLCBkaXYgcXVlIGluZGljYSBwb3NpY2lvbiBkZSBtb3VzZVxuICAgKiAgICAtIEFncmVnYXIgRGV0YWlsRGF5LCBwYXJhIGRldGFsbGVzIGRlIGRhdG9zIGVuIHRhYmxhXG4gICAqICAgIC0gQWdyZWdhciBTZWxlY3RlZENvbnRhaW5lciwgcGFyYSBkaWFzIHNlbGVjY2lvbmFkb3NcbiAgICogICAgLSBBZ3JlZ2FyIEZsb2F0Qm94Q29udGFpbmVyLCBwYXJhIHZpc3VhbGl6YWNpb24gZGUgZGF0b3MgZW4gdGFibGFcbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIENvbmZpZ3VyYWNpb24gY2FwaWJhcmFcbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gY3JlYWRvXG4gICAqL1xuICBjcmVhdGVBZ1RhYmxlKGNvbmZpZykge1xuICAgIGxldCBlID0gZG9tLmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IFwiY2FwaWJhcmFcIiB9KTtcbiAgICBpZiAoY29uZmlnLnRpbWVsaW5lLmRhcmspIHtcbiAgICAgIGUuY2xhc3NMaXN0LmFkZChcImRhcmstdGhlbWVcIik7XG4gICAgfVxuICAgIGlmIChjb25maWcudGltZWxpbmUuaGVhZGVyLmV4dGVuZC5pc1Nob3cpIHtcbiAgICAgIGUuY2xhc3NMaXN0LmFkZChcImhlYWRlci1leHRlbmRlZFwiKTtcbiAgICB9XG4gICAgcmV0dXJuIGU7XG4gIH0sXG5cbiAgLyoqXG4gICAqIFJlY3JlYSBCYWNrZ3JvdW5kLCBxdWUgZXMgZWwgZm9uZG8gZ3JpZCwgY29tbyB0YWJsYVxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcGFyYW0ge09iamVjdH0gJGVsZW0gLSBFbGVtZW50byByZWxhY2lvbmFkbywgZG9uZGUgc2UgY3JlIGVsIGJhY2tncm91bmRcbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gQ29ybmVyIEZvb3RlclxuICAgKi9cbiAgcmVkcmF3QmFja2dyb3VuZChjb25maWcsICRlbGVtKSB7XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlQmFja2dyb3VuZChjb25maWcsICRlbGVtKTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSB5IHBvc2ljaW9uYSBmb25kbyBkZSB0YWJsYVxuICAgKiBFc3RlIGZvbmRvIGNvbnRpZW5lIHVuIHBhdHJvbiBkZSBDU1MgcXVlIGxlIGRhIGxhIGFwYXJpZW5jaWEgZGUgdGFibGFcbiAgICogcG9yIGxvIGN1YWwgc2UgZGViZSByZXBvc2ljaW9uYXIgc2VndW4gbGEgZmVjaGEgZGUgaW5pY2lvLCBwYXJhIGhhY2VyXG4gICAqIGNhbHphciBsb3MgZmluZXMgZGUgc2VtYW5hXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBjb25maWcgLSBDb25maWd1cmFjaW9uIGNhcGliYXJhXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbJGVsZW0gPSBudWxsXSAtIEVsZW1lbnRvIGJhY2tncm91bmQsIHNpIGVzIG51bGwsIGxvIGNyZWFcbiAgICogQHJldHVybiB7T2JqZWN0fSBlbGVtZW50byBEb20gQmFja2dyb3VuZFxuICAgKi9cbiAgY3JlYXRlQmFja2dyb3VuZChjb25maWcsICRlbGVtID0gbnVsbCkge1xuICAgIGxldCB7IGhlaWdodCwgd2lkdGgsIGRheVdpZHRoIH0gPSB1dGlscy5nZXRUYWJsZURpbWVuc2lvbnMoY29uZmlnKTtcblxuICAgIGxldCBzdGFydCA9IG5ldyBEYXRlKGNvbmZpZy50aW1lbGluZS5zdGFydCk7XG4gICAgbGV0IGVuZCA9IG5ldyBEYXRlKGNvbmZpZy50aW1lbGluZS5lbmQpO1xuXG4gICAgZW5kLnNldFRpbWUoZW5kLmdldFRpbWUoKSArIGRhdGVVdGlscy5kYXlJbk1pbGxpc2Vjb25kcyk7IC8vIGFkZCAyNCBob3Vyc1xuXG4gICAgbGV0IGRDb3JyZWN0ZWQgPSBuZXcgRGF0ZShcbiAgICAgIHN0YXJ0LnZhbHVlT2YoKSArIHN0YXJ0LmdldFRpbWV6b25lT2Zmc2V0KCkgKiA2MDAwMFxuICAgICk7XG4gICAgbGV0IHdlZWtEYXkgPSBkQ29ycmVjdGVkLmdldERheSgpO1xuICAgIGxldCBkaWZmV2Vla0RheXMgPSAod2Vla0RheSAtIDEpICogZGF5V2lkdGggKiAtMTtcblxuICAgICRlbGVtID0gJGVsZW0gfHwgZG9tLmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IFwiYmFja2dyb3VuZC1ncmlkXCIgfSk7XG4gICAgJGVsZW0uc3R5bGVbXCJiYWNrZ3JvdW5kLXBvc2l0aW9uXCJdID1cbiAgICAgIGRpZmZXZWVrRGF5cyArIFwicHggMCwgMCAwLCBcIiArIGRpZmZXZWVrRGF5cyArIFwicHggMFwiO1xuICAgICRlbGVtLnN0eWxlLndpZHRoID0gd2lkdGggKyBcInB4XCI7XG4gICAgJGVsZW0uc3R5bGUuaGVpZ2h0ID0gaGVpZ2h0ICsgMSArIFwicHhcIjtcbiAgICByZXR1cm4gJGVsZW07XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWEgUGxvdCBDb250YWluZXIgVmVydGljYWxcbiAgICogTG9zIHBsb3RzIHNvbiBlbGVtZW50b3MgcXVlIGFncmVnYW4gc2VjY2lvbmVzIGRlIGZvbmRvIGVuIGxhIHBsYW5pbGxhXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBjb25maWcgLSBDb25maWd1cmFjaW9uIGNhcGliYXJhXG4gICAqIEByZXR1cm4ge09iamVjdH0gRWxlbWVudG8gRG9tIHBsb3RWZXJ0aWNhbENvbnRhaW5lclxuICAgKi9cbiAgY3JlYXRlUGxvdFZlcnRpY2FsQ29udGFpbmVyKGNvbmZpZykge1xuICAgIGxldCAkZWxlbSA9IGRvbS5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtcbiAgICAgIGNsYXNzTmFtZTogXCJwbG90LXZlcnRpY2FsLWNvbnRhaW5lclwiLFxuICAgIH0pO1xuICAgIHJldHVybiB0aGlzLnJlZHJhd1Bsb3RWZXJ0aWNhbENvbnRhaW5lcihjb25maWcsICRlbGVtKTtcbiAgfSxcblxuICBjcmVhdGVQbG90SG9yaXpvbnRhbENvbnRhaW5lcihjb25maWcpIHtcbiAgICBsZXQgJGVsZW0gPSBkb20uY3JlYXRlRWxlbWVudChcImRpdlwiLCB7XG4gICAgICBjbGFzc05hbWU6IFwicGxvdC1ob3Jpem9udGFsLWNvbnRhaW5lclwiLFxuICAgIH0pO1xuICAgIHJldHVybiB0aGlzLnJlZHJhd1Bsb3RIb3Jpem9udGFsQ29udGFpbmVyKGNvbmZpZywgJGVsZW0pO1xuICB9LFxuXG4gIC8qKlxuICAgKiBSZWNyZWEgcGxvdFZlcnRpY2FsQ29udGFpbmVyLCB1c2FuZG8gZWxlbWVudG8gZXhpc3RlbnRlXG4gICAqIHVzYSB1biBlbGVtZW50byBleGlzdGVudGUgcGFyYSB1c2FyIGxhIGZ1bmNpb24gcGFyYSByZWRpYnVqYXIgZWwgZWxlbWVudG9cbiAgICpcbiAgICogTG9zIFBsb3RzIHNlIGluc2VydGFuIGNvbW8gZGl2cywgY29uIHBvc2ljaW9uIGVzcGVjaWZpY2FkYSxcbiAgICogY29uIGFuY2hvIGRlIGRpYVxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcGFyYW0ge09iamVjdH0gJGVsZW0gLSBFbGVtZW50byBEb20gZG9uZGUgY3JlYSBwbG90VmVydGljYWxDb250YWluZXJcbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gcGxvdFZlcnRpY2FsQ29udGFpbmVyXG4gICAqL1xuICByZWRyYXdQbG90VmVydGljYWxDb250YWluZXIoY29uZmlnLCAkZWxlbSkge1xuICAgICRlbGVtLmlubmVySFRNTCA9IFwiXCI7XG4gICAgaWYgKGNvbmZpZy50aW1lbGluZS5wbG90cyAmJiBjb25maWcudGltZWxpbmUucGxvdHMudmVydGljYWwpIHtcbiAgICAgIGxldCB7IGhlaWdodCwgZGF5V2lkdGggfSA9IHV0aWxzLmdldFRhYmxlRGltZW5zaW9ucyhjb25maWcpO1xuXG4gICAgICBjb25maWcudGltZWxpbmUucGxvdHMudmVydGljYWwuZm9yRWFjaCgocCkgPT4ge1xuICAgICAgICBsZXQgZGlmZkRheXMgPSBNYXRoLmZsb29yKFxuICAgICAgICAgIGRhdGVVdGlscy5kaWZmRGF5cyhjb25maWcudGltZWxpbmUuc3RhcnQsIHAuZGF0ZSlcbiAgICAgICAgKTtcbiAgICAgICAgbGV0IGxlZnQgPSBkaWZmRGF5cyAqIGRheVdpZHRoO1xuICAgICAgICBsZXQgcGxvdCA9IGRvbS5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtcbiAgICAgICAgICBjbGFzc05hbWVzOiBbXCJwbG90LXZlcnRpY2FsXCIsIHAuY2xhc3NOYW1lIHx8IFwiXCJdLFxuICAgICAgICAgIHN0eWxlOiB7XG4gICAgICAgICAgICBcIm1hcmdpbi1sZWZ0XCI6IGxlZnQgKyBcInB4XCIsXG4gICAgICAgICAgICBoZWlnaHQ6IGhlaWdodCArIFwicHhcIixcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgICAgJGVsZW0uYXBwZW5kQ2hpbGQocGxvdCk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuICRlbGVtO1xuICB9LFxuXG4gIHJlZHJhd1Bsb3RIb3Jpem9udGFsQ29udGFpbmVyKGNvbmZpZywgJGVsZW0pIHtcbiAgICAkZWxlbS5pbm5lckhUTUwgPSBcIlwiO1xuICAgIGlmIChjb25maWcudGltZWxpbmUucGxvdHMgJiYgY29uZmlnLnRpbWVsaW5lLnBsb3RzLmhvcml6b250YWwpIHtcbiAgICAgIGxldCB7IHdpZHRoLCBpdGVtSGVpZ2h0IH0gPSB1dGlscy5nZXRUYWJsZURpbWVuc2lvbnMoY29uZmlnKTtcbiAgICAgIGNvbmZpZy50aW1lbGluZS5wbG90cy5ob3Jpem9udGFsLmZvckVhY2goKHApID0+IHtcbiAgICAgICAgbGV0IGl0ZW0gPSB1dGlscy5nZXRJdGVtQnlJZChjb25maWcsIHAuaWROb2RlLCBwLnR5cGVOb2RlKTtcbiAgICAgICAgbGV0IHRvcFBvc2l0aW9uID0gdXRpbHMuZ2V0UG9zaXRpb25CeUl0ZW0oY29uZmlnLCBpdGVtLCBcInBhcmVudFwiKTtcbiAgICAgICAgbGV0IHBsb3QgPSBkb20uY3JlYXRlRWxlbWVudChcImRpdlwiLCB7XG4gICAgICAgICAgY2xhc3NOYW1lczogW1wicGxvdC1ob3Jpem9udGFsXCIsIHAuY2xhc3NOYW1lIHx8IFwiXCJdLFxuICAgICAgICAgIHN0eWxlOiB7XG4gICAgICAgICAgICBcIm1hcmdpbi10b3BcIjogdG9wUG9zaXRpb24gKiBpdGVtSGVpZ2h0ICsgXCJweFwiLFxuICAgICAgICAgICAgd2lkdGg6IHdpZHRoICsgXCJweFwiLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgICAkZWxlbS5hcHBlbmRDaGlsZChwbG90KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gJGVsZW07XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWEgQ29ybmVyIEl6cXVpZXJkb1xuICAgKiBTZSB1c2EgcGFyYSA6XG4gICAqICAgIC0gdGl0dWxvcyByZWxhY2lvbmFkb3MgY29uIGxvcyBkYXRvcyBkZWwgc2lkZWJhciBpenF1aWVyZG9cbiAgICogICAgLSB0aXR1bG9zIHBhcmEgaW5wdXRzIGRlIGhlYWRlciwgYWJzb2x1dGUgYSBsYSBkZXJlY2hhXG4gICAqICAgIC0gYm90b24gcGFyYSBtb3N0cmFyL29jdWx0YXIgc2lkZWJhciBpenF1aWVyZG9cbiAgICogICAgLSBwcm9tZWRpb3NcbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIENvbmZpZ3VyYWNpb24gY2FwaWJhcmFcbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gQ29ybmVyXG4gICAqL1xuICBjcmVhdGVDb3JuZXIoY29uZmlnLCB0YWIgPSBudWxsKSB7XG4gICAgbGV0ICRlbGVtID0gZG9tLmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IFwiY29ybmVyXCIgfSk7XG4gICAgcmV0dXJuIHRoaXMucmVkcmF3Q29ybmVyKCRlbGVtLCBjb25maWcsIHRhYik7XG4gIH0sXG5cbiAgcmVkcmF3Q29ybmVyKCRlbGVtLCBjb25maWcsIHRhYiA9IG51bGwpIHtcbiAgICBsZXQgbGFiZWxzSW5pdGlhbENvcm5lciA9IGNvbmZpZy50aW1lbGluZS5uYXYubGVmdC5pbml0aWFsLnZhcnNcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgICh2KSA9PlxuICAgICAgICAgIHYub25seVRhYiA9PSB1bmRlZmluZWQgfHwgKHYub25seVRhYiAmJiB0YWIgJiYgdi5vbmx5VGFiID09IHRhYi5rZXkpXG4gICAgICApXG4gICAgICAubWFwKChkKSA9PiBgPHNwYW4gY2xhc3M9XCJpdGVtLWNvbFwiPiR7ZC5sYWJlbH08L3NwYW4+YClcbiAgICAgIC5qb2luKFwiXCIpO1xuXG4gICAgbGV0IGxhYmVsc0V4dGVuZENvcm5lciA9IGNvbmZpZy50aW1lbGluZS5uYXYubGVmdC5leHRlbmQudmFyc1xuICAgICAgLmZpbHRlcihcbiAgICAgICAgKHYpID0+XG4gICAgICAgICAgdi5vbmx5VGFiID09IHVuZGVmaW5lZCB8fCAodi5vbmx5VGFiICYmIHRhYiAmJiB2Lm9ubHlUYWIgPT0gdGFiLmtleSlcbiAgICAgIClcbiAgICAgIC5tYXAoKGQpID0+IGA8c3BhbiBjbGFzcz1cIml0ZW0tY29sXCI+JHtkLmxhYmVsfTwvc3Bhbj5gKVxuICAgICAgLmpvaW4oXCJcIik7XG5cbiAgICBsZXQgbGFiZWxzSGVhZGVyRXh0ZW5kID0gY29uZmlnLnRpbWVsaW5lLmhlYWRlci5leHRlbmQuZGF0YVxuICAgICAgLm1hcCgoZCkgPT4ge1xuICAgICAgICBpZiAoZC5pc0hpZGRlbikgcmV0dXJuIFwiXCI7XG5cbiAgICAgICAgbGV0IGF2ZyA9IFwiXCI7XG4gICAgICAgIGxldCB0b29sdGlwID0gXCJcIjtcbiAgICAgICAgbGV0IGNsYXNzTmFtZSA9IFwiXCI7XG4gICAgICAgIGxldCBpc0FjY2VudCA9IGQuaXNBY2NlbnQ7XG5cbiAgICAgICAgaWYgKGQuYXZlcmFnZSkge1xuICAgICAgICAgIGF2ZyA9IGAgPHNwYW4gY2xhc3M9XCJhdmVyYWdlIFwiPiAoIDxzcGFuPiA8c3BhbiBjbGFzcz1cInN5bWJvbFwiPnjMhDwvc3Bhbj4gJHtkLmF2ZXJhZ2V9IDwvc3Bhbj4pICA8L3NwYW4+ICAgYDtcblxuICAgICAgICAgIHRvb2x0aXAgPSBgY2FwLXRvb2x0aXA9XCJQcm9tZWRpbyAke2QubGFiZWx9IDogJHtkLmF2ZXJhZ2V9ICR7XG4gICAgICAgICAgICBkLnN1ZmZpeCB8fCBcIlwiXG4gICAgICAgICAgfVwiYDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkLmNvbG9yKSB7XG4gICAgICAgICAgaWYgKGlzQWNjZW50KSB7XG4gICAgICAgICAgICBjbGFzc05hbWUgPSBkLmNvbG9yID8gXCJjLVwiICsgZC5jb2xvciArIFwiLS1iYWNrZ3JvdW5kXCIgOiBcIlwiO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjbGFzc05hbWUgPSBkLmNvbG9yID8gXCJjLVwiICsgZC5jb2xvciArIFwiLS10ZXh0IFwiIDogXCJcIjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYDxkaXYgY2xhc3M9XCJpbnB1dC10aXRsZS1jb250YWluZXIgJHtcbiAgICAgICAgICBpc0FjY2VudCA/IFwiaW5wdXQtdGl0bGUtLWFjY2VudFwiIDogXCJcIlxuICAgICAgICB9ICR7ZC5pc1BlcnNpc3RlbnQgPyBcInBlcnNpc3RlbnRcIiA6IFwiXCJ9XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gJHt0b29sdGlwfSBjbGFzcz1cImlucHV0LXRpdGxlICR7Y2xhc3NOYW1lfVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHthdmd9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAke2QubGFiZWx9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PmA7XG4gICAgICB9KVxuICAgICAgLmpvaW4oXCJcIik7XG5cbiAgICBsZXQgdG9nZ2xlU2lkZWJhckJ0blN0cmluZyA9IGBcbiAgICAgICAgICA8YnV0dG9uIHRvZ2dsZS1zaWRlYmFyIGNsYXNzPVwiY2FwLWJ0bi1pY29uIGNhcC1idG4taWNvbi1yYWlzZWQgY2FwLWJ0bi10b2dnbGUtc2lkZWJhciBcIj5cbiAgICAgICAgICAgIDxzcGFuPlxuICAgICAgICAgICAgICA8c3ZnIHN0eWxlPVwid2lkdGg6MjRweDtoZWlnaHQ6MjRweFwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIj5cbiAgICAgICAgICAgICAgICAgIDxwYXRoIGZpbGw9XCJjdXJyZW50Q29sb3JcIiBkPVwiTTguNTksMTYuNThMMTMuMTcsMTJMOC41OSw3LjQxTDEwLDZMMTYsMTJMMTAsMThMOC41OSwxNi41OFpcIiAvPlxuICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICA8L2J1dHRvbj4gYDtcblxuICAgIGlmKGNvbmZpZy50aW1lbGluZS5uYXYubGVmdC5oaWRlVG9nZ2xlU2lkZWJhckJ1dHRvbil7XG4gICAgICB0b2dnbGVTaWRlYmFyQnRuU3RyaW5nID0gXCJcIjtcbiAgICB9XG5cbiAgICBsZXQgdGVtcGxhdGUgPSBgPGRpdj5cblxuICAgICAgICAgICR7dG9nZ2xlU2lkZWJhckJ0blN0cmluZ31cbiAgICAgICAgPGRpdiBjbGFzcz1cImNvcm5lci10aXRsZVwiPlxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYm90dG9tLXRleHRcIj5cbiAgICAgICAgICAgICR7Y29uZmlnLnRpbWVsaW5lLmNvcm5lci5sZWZ0LmxhYmVsfVxuICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgPGRpdiBjbGFzcz1cImluaXRpYWwtY29ybmVyXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImluaXRpYWwtY29ybmVyLXRpdGxlXCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImJvdHRvbS1jb250YWluZXIgaGlkZVwiPlxuICAgICAgICAgICAgICAke2NvbmZpZy50aW1lbGluZS5jb3JuZXIuaW5pdGlhbC5sYWJlbH1cbiAgICAgICAgICAgIDwvc3Bhbj5cblxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImJvdHRvbS1jb250YWluZXJcIj5cbiAgICAgICAgICAgICAgJHtsYWJlbHNJbml0aWFsQ29ybmVyfVxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG5cblxuICAgICAgICA8ZGl2IGNsYXNzPVwiZXh0ZW5kLWNvcm5lclwiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJleC1jb3JuZXItdGl0bGVcIj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYm90dG9tLWNvbnRhaW5lciBoaWRlXCI+XG4gICAgICAgICAgICAgICR7Y29uZmlnLnRpbWVsaW5lLmNvcm5lci5leHRlbmQubGFiZWx9XG4gICAgICAgICAgICA8L3NwYW4+XG5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJib3R0b20tY29udGFpbmVyXCI+XG4gICAgICAgICAgICAgICR7bGFiZWxzRXh0ZW5kQ29ybmVyfVxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG5cblxuICAgICAgICA8ZGl2IGNsYXNzPVwiY2FwLWJ0bi1uYXYtY29ybmVyXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXRpdGxlc1wiPlxuICAgICAgICAgICAgICAke2xhYmVsc0hlYWRlckV4dGVuZH1cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgPGRpdiBjbGFzcz1cInByb2dyZXNzLWJhciBwcm9ncmVzcy1iYXItbGVmdCBoaWRlLXByb2dyZXNzXCI+PC9kaXY+XG5cbiAgICAgIDwvZGl2PmA7XG5cbiAgICBsZXQgciA9IGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwodGVtcGxhdGUpO1xuXG4gICAgJGVsZW0uaW5uZXJIVE1MID0gXCJcIjtcbiAgICAkZWxlbS5hcHBlbmQocik7XG5cbiAgICBsZXQgdG9nZ2xlU2lkZWJhciA9ICRlbGVtLnF1ZXJ5U2VsZWN0b3IoXCJbdG9nZ2xlLXNpZGViYXJdXCIpO1xuICAgIGlmKHRvZ2dsZVNpZGViYXIpe1xuICAgICAgdG9nZ2xlU2lkZWJhci5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGUpID0+IHtcbiAgICAgICAgci5kaXNwYXRjaEV2ZW50KFxuICAgICAgICAgIG5ldyBDdXN0b21FdmVudChcInRvZ2dsZVNpZGViYXJcIiwge1xuICAgICAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgICAgIGNhbmNlbGFibGU6IGZhbHNlLFxuICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gJGVsZW07XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWEgQ29ybmVyIERlcmVjaG9cbiAgICogU2UgdXNhIHBhcmEgOlxuICAgKiAgICAtIHRpdHVsb3MgcmVsYWNpb25hZG9zIGNvbiBsb3MgZGF0b3MgZGVsIHNpZGViYXIgRGVyZWNob1xuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBjb3JuZXJcbiAgICovXG4gIGNyZWF0ZUNvcm5lclJpZ2h0KGNvbmZpZywgdGFiID0gbnVsbCkge1xuICAgIGxldCAkZWxlbSA9IGRvbS5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lczogW1wiY29ybmVyXCIsXCJyaWdodFwiXSB9KTtcbiAgICByZXR1cm4gdGhpcy5yZWRyYXdDb3JuZXJSaWdodCgkZWxlbSwgY29uZmlnLCB0YWIpO1xuICB9LFxuXG4gIHJlZHJhd0Nvcm5lclJpZ2h0KCRlbCwgY29uZmlnLCB0YWIgPSBudWxsKSB7XG4gICAgbGV0IGxhYmVsID0gXCJcIjtcblxuICAgIGlmIChjb25maWcudGltZWxpbmUuY29ybmVyLnJpZ2h0LmxhYmVsKSB7XG4gICAgICBgIDxzcGFuPlxuICAgICAgICAgICAgJHtjb25maWcudGltZWxpbmUuY29ybmVyLnJpZ2h0LmxhYmVsfVxuICAgICAgICAgIDwvc3Bhbj5gO1xuICAgIH1cblxuICAgIGxldCBzdHIgPSBgXG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb3JuZXItdGl0bGVcIj5cbiAgICAgICAgJHtsYWJlbH1cbiAgICAgICAgPGRpdiBjbGFzcz1cImJ0bi1jb250YWluZXJcIj48L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzcy1iYXIgcHJvZ3Jlc3MtYmFyLXJpZ2h0IGhpZGUtcHJvZ3Jlc3NcIj48L2Rpdj5cbiAgICBgO1xuICAgICRlbC5pbm5lckhUTUwgPSBzdHIudHJpbSgpO1xuICAgIGxldCAkYnRuQ29udGFpbmVyID0gJGVsLnF1ZXJ5U2VsZWN0b3IoXCIuYnRuLWNvbnRhaW5lclwiKTtcblxuICAgIGlmIChjb25maWcudGltZWxpbmUuY29ybmVyLnJpZ2h0LmJ1dHRvbnMpIHtcbiAgICAgIGNvbmZpZy50aW1lbGluZS5jb3JuZXIucmlnaHQuYnV0dG9ucy5mb3JFYWNoKChidG4pID0+IHtcbiAgICAgICAgbGV0IGlzRW5hYmxlZCA9IGJ0bi5nZXRJc0VuYWJsZWQgPyBidG4uZ2V0SXNFbmFibGVkKCkgOiB0cnVlO1xuICAgICAgICBpZihpc0VuYWJsZWQpe1xuICAgICAgICAgIGxldCAkYnRuID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChgXG4gICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiY29ybmVyLWJ0biBjYXAtYnRuLXJhaXNlZFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAke2J0bi5sYWJlbCB8fCBcIlwifVxuICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+IGApO1xuXG4gICAgICAgICAgaWYgKGJ0bi5vbkNsaWNrKSB7XG4gICAgICAgICAgICAkYnRuLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBidG4ub25DbGljayk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgJGJ0bkNvbnRhaW5lci5hcHBlbmRDaGlsZCgkYnRuKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICAgIGlmKGNvbmZpZy50aW1lbGluZS5jb3JuZXIucmlnaHQuaW5wdXRzKXtcbiAgICAgIGNvbmZpZy50aW1lbGluZS5jb3JuZXIucmlnaHQuaW5wdXRzLmZvckVhY2goaW5wdXQgPT4ge1xuICAgICAgICBsZXQgJGlucHV0ID0gdGhpcy5jcmVhdGVDb3JuZXJSaWdodElucHV0KHtpbnB1dENvbmZpZzppbnB1dH0pO1xuICAgICAgICAkYnRuQ29udGFpbmVyLmFwcGVuZENoaWxkKCRidG4pO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiAkZWw7XG4gIH0sXG5cbiAgY3JlYXRlQ29ybmVyUmlnaHRJbnB1dCh7aW5wdXRDb25maWcsIGRhdGFEYXkgPSBudWxsLCBkYXlTZWxlY3RlZCA9IG51bGwgfSl7XG4gICAgbGV0IHIgPSBudWxsO1xuICAgIHN3aXRjaChpbnB1dENvbmZpZy50eXBlKXtcbiAgICAgIGNhc2UgJ2F1dG9jb21wbGV0ZS1jcnVkJzpcbiAgICAgICAgciA9IHRoaXMuY3JlYXRlQ29ybmVyUmlnaHRJbnB1dEF1dG9jb21wbGV0ZUNydWQoe2lucHV0Q29uZmlnLCBkYXRhRGF5LCBkYXlTZWxlY3RlZH0pO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gICAgcmV0dXJuIHI7XG4gIH0sXG5cbiAgY3JlYXRlQ29ybmVyUmlnaHRJbnB1dEF1dG9jb21wbGV0ZUNydWQoe2lucHV0Q29uZmlnLCBkYXRhRGF5LCBkYXlTZWxlY3RlZCB9KXtcbiAgICBsZXQgZWxlbSA9IFwidGVzdFwiO1xuICAgIHJldHVybiBlbGVtO1xuICB9LFxuXG4gIC8qKlxuICAgKiBDcmVhIEhlYWRlciBUb3BcbiAgICogU2UgdXNhIHBhcmEgOlxuICAgKiAgICAtIE1hbmVqbyBkZSB0YWJzXG4gICAqICAgIC0gQm90b25lcyBkZSBuYXZlZ2FjacOzbiB5IHNlbGVjY2nDs24gZGUgZmVjaGFcbiAgICogICAgLSBCb3RvbiB0b2dnbGUgRGFyayBtb2RlXG4gICAqICAgIC0gQm90b24gdG9nZ2xlIEhlYWRlciBleHRlbmRlZFxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbVxuICAgKi9cblxuICBjcmVhdGVIZWFkZXJUb3AoY29uZmlnLCB0YWJTZWxlY3RlZCA9IG51bGwpIHtcbiAgICByZXR1cm4gdGhpcy5yZWRyYXdIZWFkZXJUb3AoY29uZmlnLCB0YWJTZWxlY3RlZCwgZG9tLmNyZWF0ZUVsZW1lbnQoXCJkaXZcIikpO1xuICB9LFxuXG4gIHJlZHJhd0hlYWRlclRvcChjb25maWcsIHRhYlNlbGVjdGVkID0gbnVsbCwgJGVsZW0pIHtcbiAgICBsZXQgc3RyID0gYFxuICAgICAgPGRpdiBjbGFzcz1cImhlYWRlci10b3BcIj5gO1xuXG4gICAgaWYgKGNvbmZpZy50aW1lbGluZS50YWJzKSB7XG4gICAgICBsZXQgc2hvd1RhYnMgPSB0cnVlO1xuXG4gICAgICBpZiAoY29uZmlnLnRpbWVsaW5lLnRhYnMuZmlsdGVyKCh0KSA9PiAhdC5pc0hpZGRlbikubGVuZ3RoID09IDApIHtcbiAgICAgICAgc2hvd1RhYnMgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHNob3dUYWJzKSB7XG4gICAgICAgIHN0ciArPSBgIDxkaXYgY2xhc3M9XCJ0YWItc2VsZWN0LWNvbnRhaW5lciBjLWQtZGVza3RvcC1ub25lIGMtZC1tb2JpbGUtZmxleFwiPlxuICAgICAgICAgICAgICAgICAgPHNlbGVjdCBjbGFzcz1cInRhYnMtc2VsZWN0XCIgPmA7XG5cbiAgICAgICAgY29uZmlnLnRpbWVsaW5lLnRhYnMuZm9yRWFjaCgodGFiKSA9PiB7XG4gICAgICAgICAgaWYgKCF0YWIuaXNIaWRkZW4pIHtcbiAgICAgICAgICAgIHN0ciArPSBgIDxvcHRpb24gJHtcbiAgICAgICAgICAgICAgdGFiID09IHRhYlNlbGVjdGVkID8gJ3NlbGVjdGVkPVwic2VsZWN0ZWRcIicgOiBcIlwiXG4gICAgICAgICAgICB9IHZhbHVlPVwiJHt0YWIuaWR9XCI+ICR7dGFiLmxhYmVsfSA8L29wdGlvbj5gO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgc3RyICs9IGA8L3NlbGVjdD4gPC9kaXY+YDtcblxuICAgICAgICBzdHIgKz0gYCA8ZGl2IGNsYXNzPVwidGFicy1jb250YWluZXIgYy1kLWRlc2t0b3AtZmxleCBjLWQtbW9iaWxlLW5vbmVcIj5gO1xuXG4gICAgICAgIGNvbmZpZy50aW1lbGluZS50YWJzLmZvckVhY2goKHRhYikgPT4ge1xuICAgICAgICAgIGlmICghdGFiLmlzSGlkZGVuKSB7XG4gICAgICAgICAgICBzdHIgKz0gYCA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cInRhYiAke3RhYi5kaXNhYmxlZCA/IFwiZGlzYWJsZWRcIiA6IFwiXCJ9ICAke1xuICAgICAgICAgICAgICB0YWIgPT0gdGFiU2VsZWN0ZWQgPyBcImFjdGl2ZVwiIDogXCJcIlxuICAgICAgICAgICAgfSAgJHt0YWIuY29sb3J9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yPVwiJHt0YWIuY29sb3J9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LWtleT1cIiR7dGFiLmlkfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAke1xuICAgICAgICAgICAgICAgICAgICAgICAgICB0YWIudG9vbHRpcCA/ICdjYXAtdG9vbHRpcD1cIicgKyB0YWIudG9vbHRpcCArICdcIicgOiBcIlwiXG4gICAgICAgICAgICAgICAgICAgICAgICB9ID5cbiAgICAgICAgICAgICAgICAgICAgPHNwYW4+JHt0YWIubGFiZWx9PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAke3RhYi5pY29uIHx8IFwiXCJ9XG4gICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgIGA7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBzdHIgKz0gYDwvZGl2PmA7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRhYlNlbGVjdGVkKSB7XG4gICAgICBpZiAodGFiU2VsZWN0ZWQubGVnZW5kcykge1xuICAgICAgICAvKlxuICAgICAgICBzdHIgKz0gYDxkaXYgY2xhc3M9XCJsZWdlbmRzLXNlbGVjdC1jb250YWluZXIgYy1kLWRlc2t0b3Atbm9uZSBjLWQtbW9iaWxlLWZsZXhcIj5cbiAgICAgICAgICAgICAgICA8c2VsZWN0IGNsYXNzPVwibGVnZW5kcy1zZWxlY3RcIiBtdWx0aXBsZT5gO1xuXG4gICAgICAgIHRhYlNlbGVjdGVkLmxlZ2VuZHMuZm9yRWFjaChsZWdlbmQgPT4ge1xuICAgICAgICAgICAgc3RyICs9YCA8b3B0aW9uIHZhbHVlPVwiJHtsZWdlbmQuaWR9XCI+ICR7bGVnZW5kLmxhYmVsfSA8L29wdGlvbj5gXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHN0ciArPSBgPC9zZWxlY3Q+XG4gICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICAgICAgKi9cblxuICAgICAgICBsZXQgdG9nZ2xlTGVnZW5kc0ljb25QYXRoID1cbiAgICAgICAgICBcIk03LDVIMjFWN0g3VjVNNywxM1YxMUgyMVYxM0g3TTQsNC41QTEuNSwxLjUgMCAwLDEgNS41LDZBMS41LDEuNSAwIDAsMSA0LDcuNUExLjUsMS41IDAgMCwxIDIuNSw2QTEuNSwxLjUgMCAwLDEgNCw0LjVNNCwxMC41QTEuNSwxLjUgMCAwLDEgNS41LDEyQTEuNSwxLjUgMCAwLDEgNCwxMy41QTEuNSwxLjUgMCAwLDEgMi41LDEyQTEuNSwxLjUgMCAwLDEgNCwxMC41TTcsMTlWMTdIMjFWMTlIN000LDE2LjVBMS41LDEuNSAwIDAsMSA1LjUsMThBMS41LDEuNSAwIDAsMSA0LDE5LjVBMS41LDEuNSAwIDAsMSAyLjUsMThBMS41LDEuNSAwIDAsMSA0LDE2LjVaXCI7XG5cbiAgICAgICAgc3RyICs9IGAgXG4gICAgICAgIDxidXR0b24gdG9nZ2xlLWxlZ2VuZHMgY2xhc3M9XCJjYXAtYnRuLWljb24gY2FwLWJ0bi1pY29uLXJhaXNlZCBcIj5cbiAgICAgICAgICA8c3Bhbj5cbiAgICAgICAgICAgIDxzdmcgc3R5bGU9XCJ3aWR0aDoyNHB4O2hlaWdodDoyNHB4XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiPlxuICAgICAgICAgICAgICAgIDxwYXRoIGZpbGw9XCJjdXJyZW50Q29sb3JcIiBkPVwiJHt0b2dnbGVMZWdlbmRzSWNvblBhdGh9XCIgLz5cbiAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgPC9idXR0b24+IFxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJsZWdlbmRzLWNvbnRhaW5lciBmb3JjZS1tb2JpbGUtc3R5bGUgaGlkZVwiPiBgO1xuXG4gICAgICAgIHRhYlNlbGVjdGVkLmxlZ2VuZHMuZm9yRWFjaCgobGVnZW5kKSA9PiB7XG4gICAgICAgICAgbGV0IGNvbG9yQ2xhc3MgPSBcIlwiO1xuICAgICAgICAgIGxldCBjb2xvckJnID0gXCJcIjtcblxuICAgICAgICAgIGlmICh1dGlscy5pc0hleENvbG9yKGxlZ2VuZC5jb2xvcikpIHtcbiAgICAgICAgICAgIGNvbG9yQmcgPSBcImJhY2tncm91bmQ6XCIgKyBsZWdlbmQuY29sb3I7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbG9yQ2xhc3MgPSBsZWdlbmQuY29sb3IgPyBsZWdlbmQuY29sb3IgKyBcIi0tYmFja2dyb3VuZFwiIDogXCJcIjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBzdHIgKz0gYCA8ZGl2XG4gICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJsZWdlbmQgJHtsZWdlbmQuYWN0aXZlID8gXCJhY3RpdmVcIiA6IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1rZXk9XCIke2xlZ2VuZC5rZXl9XCJcbiAgICAgICAgICAgICAgICAgICAgICAke1xuICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRvb2x0aXAgPyBgY2FwLXRvb2x0aXA9XCIke2xlZ2VuZC50b29sdGlwfVwiYCA6IFwiXCJcbiAgICAgICAgICAgICAgICAgICAgICB9ID5cbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpY29uLWxlZ2VuZCAke2NvbG9yQ2xhc3N9ICR7XG4gICAgICAgICAgICBsZWdlbmQuc2hhcGVcbiAgICAgICAgICB9XCIgc3R5bGU9XCIke2NvbG9yQmd9XCI+PC9kaXY+XG4gICAgICAgICAgICAgICAgICA8c3Bhbj4ke2xlZ2VuZC5sYWJlbH08L3NwYW4+XG4gICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc3RyICs9IGA8L2Rpdj5gO1xuICAgICAgfVxuICAgIH1cblxuICAgIHN0ciArPSBgXG5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwic3BhY2VyXCI+PC9kaXY+XG5cblxuXG4gICAgICAgICAgPGJ1dHRvbiBjYXAtYnRuLXByZXYgY2xhc3M9XCJjYXAtYnRuLWljb24gY2FwLWJ0bi1pY29uLXJhaXNlZFwiPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImljb25cIj5cbiAgICAgICAgICAgICAgPHN2ZyBzdHlsZT1cIndpZHRoOjI0cHg7aGVpZ2h0OjI0cHhcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgICAgICAgICAgICAgICA8cGF0aCBmaWxsPVwiY3VycmVudENvbG9yXCIgZD1cIk0yMCwxMFYxNEgxMUwxNC41LDE3LjVMMTIuMDgsMTkuOTJMNC4xNiwxMkwxMi4wOCw0LjA4TDE0LjUsNi41TDExLDEwSDIwWlwiIC8+XG4gICAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgICAgICA8L3NwYW4+XG5cbiAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJsb2FkaW5nLWljb25cIj5cbiAgICAgICAgICAgICAgICA8c3ZnIHZlcnNpb249XCIxLjFcIiBpZD1cImxvYWRlci0xXCIgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIHhtbG5zOnhsaW5rPVwiaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlua1wiIHg9XCIwcHhcIiB5PVwiMHB4XCJcbiAgICAgICAgICAgICAgIHdpZHRoPVwiMzJweFwiIGhlaWdodD1cIjMycHhcIiB2aWV3Qm94PVwiMCAwIDQwIDQwXCIgZW5hYmxlLWJhY2tncm91bmQ9XCJuZXcgMCAwIDQwIDQwXCIgeG1sOnNwYWNlPVwicHJlc2VydmVcIj5cbiAgICAgICAgICAgICAgPHBhdGggb3BhY2l0eT1cIjAuMlwiIGZpbGw9XCIjMDAwXCIgZD1cIk0yMC4yMDEsNS4xNjljLTguMjU0LDAtMTQuOTQ2LDYuNjkyLTE0Ljk0NiwxNC45NDZjMCw4LjI1NSw2LjY5MiwxNC45NDYsMTQuOTQ2LDE0Ljk0NlxuICAgICAgICAgICAgICAgIHMxNC45NDYtNi42OTEsMTQuOTQ2LTE0Ljk0NkMzNS4xNDYsMTEuODYxLDI4LjQ1NSw1LjE2OSwyMC4yMDEsNS4xNjl6IE0yMC4yMDEsMzEuNzQ5Yy02LjQyNSwwLTExLjYzNC01LjIwOC0xMS42MzQtMTEuNjM0XG4gICAgICAgICAgICAgICAgYzAtNi40MjUsNS4yMDktMTEuNjM0LDExLjYzNC0xMS42MzRjNi40MjUsMCwxMS42MzMsNS4yMDksMTEuNjMzLDExLjYzNEMzMS44MzQsMjYuNTQxLDI2LjYyNiwzMS43NDksMjAuMjAxLDMxLjc0OXpcIi8+XG4gICAgICAgICAgICAgIDxwYXRoIGZpbGw9XCIjMDAwXCIgZD1cIk0yNi4wMTMsMTAuMDQ3bDEuNjU0LTIuODY2Yy0yLjE5OC0xLjI3Mi00Ljc0My0yLjAxMi03LjQ2Ni0yLjAxMmgwdjMuMzEyaDBcbiAgICAgICAgICAgICAgICBDMjIuMzIsOC40ODEsMjQuMzAxLDkuMDU3LDI2LjAxMywxMC4wNDd6XCI+XG4gICAgICAgICAgICAgICAgPGFuaW1hdGVUcmFuc2Zvcm0gYXR0cmlidXRlVHlwZT1cInhtbFwiXG4gICAgICAgICAgICAgICAgICBhdHRyaWJ1dGVOYW1lPVwidHJhbnNmb3JtXCJcbiAgICAgICAgICAgICAgICAgIHR5cGU9XCJyb3RhdGVcIlxuICAgICAgICAgICAgICAgICAgZnJvbT1cIjAgMjAgMjBcIlxuICAgICAgICAgICAgICAgICAgdG89XCIzNjAgMjAgMjBcIlxuICAgICAgICAgICAgICAgICAgZHVyPVwiMS41c1wiXG4gICAgICAgICAgICAgICAgICByZXBlYXRDb3VudD1cImluZGVmaW5pdGVcIi8+XG4gICAgICAgICAgICAgICAgPC9wYXRoPlxuICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgIDwvYnV0dG9uPlxuXG5cbiAgICAgICAgICA8YnV0dG9uIGNhcC1idG4tY2FsZW5kYXIgY2xhc3M9XCJjYXAtYnRuLWljb24gY2FwLWJ0bi1pY29uLXJhaXNlZFwiPlxuICAgICAgICAgICAgPHNwYW4+XG4gICAgICAgICAgICAgIDxzdmcgc3R5bGU9XCJ3aWR0aDoyNHB4O2hlaWdodDoyNHB4XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiPlxuICAgICAgICAgICAgICAgIDxwYXRoIGZpbGw9XCJjdXJyZW50Q29sb3JcIiBkPVwiTTE5LDE5SDVWOEgxOU0xNiwxVjNIOFYxSDZWM0g1QzMuODksMyAzLDMuODkgMyw1VjE5QTIsMiAwIDAsMCA1LDIxSDE5QTIsMiAwIDAsMCAyMSwxOVY1QzIxLDMuODkgMjAuMSwzIDE5LDNIMThWMU0xNywxMkgxMlYxN0gxN1YxMlpcIiAvPlxuICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibG9hZGluZy1pY29uXCI+XG4gICAgICAgICAgICAgICAgPHN2ZyB2ZXJzaW9uPVwiMS4xXCIgaWQ9XCJsb2FkZXItMVwiIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB4bWxuczp4bGluaz1cImh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmtcIiB4PVwiMHB4XCIgeT1cIjBweFwiXG4gICAgICAgICAgICAgICB3aWR0aD1cIjMycHhcIiBoZWlnaHQ9XCIzMnB4XCIgdmlld0JveD1cIjAgMCA0MCA0MFwiIGVuYWJsZS1iYWNrZ3JvdW5kPVwibmV3IDAgMCA0MCA0MFwiIHhtbDpzcGFjZT1cInByZXNlcnZlXCI+XG4gICAgICAgICAgICAgIDxwYXRoIG9wYWNpdHk9XCIwLjJcIiBmaWxsPVwiIzAwMFwiIGQ9XCJNMjAuMjAxLDUuMTY5Yy04LjI1NCwwLTE0Ljk0Niw2LjY5Mi0xNC45NDYsMTQuOTQ2YzAsOC4yNTUsNi42OTIsMTQuOTQ2LDE0Ljk0NiwxNC45NDZcbiAgICAgICAgICAgICAgICBzMTQuOTQ2LTYuNjkxLDE0Ljk0Ni0xNC45NDZDMzUuMTQ2LDExLjg2MSwyOC40NTUsNS4xNjksMjAuMjAxLDUuMTY5eiBNMjAuMjAxLDMxLjc0OWMtNi40MjUsMC0xMS42MzQtNS4yMDgtMTEuNjM0LTExLjYzNFxuICAgICAgICAgICAgICAgIGMwLTYuNDI1LDUuMjA5LTExLjYzNCwxMS42MzQtMTEuNjM0YzYuNDI1LDAsMTEuNjMzLDUuMjA5LDExLjYzMywxMS42MzRDMzEuODM0LDI2LjU0MSwyNi42MjYsMzEuNzQ5LDIwLjIwMSwzMS43NDl6XCIvPlxuICAgICAgICAgICAgICA8cGF0aCBmaWxsPVwiIzAwMFwiIGQ9XCJNMjYuMDEzLDEwLjA0N2wxLjY1NC0yLjg2NmMtMi4xOTgtMS4yNzItNC43NDMtMi4wMTItNy40NjYtMi4wMTJoMHYzLjMxMmgwXG4gICAgICAgICAgICAgICAgQzIyLjMyLDguNDgxLDI0LjMwMSw5LjA1NywyNi4wMTMsMTAuMDQ3elwiPlxuICAgICAgICAgICAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZVR5cGU9XCJ4bWxcIlxuICAgICAgICAgICAgICAgICAgYXR0cmlidXRlTmFtZT1cInRyYW5zZm9ybVwiXG4gICAgICAgICAgICAgICAgICB0eXBlPVwicm90YXRlXCJcbiAgICAgICAgICAgICAgICAgIGZyb209XCIwIDIwIDIwXCJcbiAgICAgICAgICAgICAgICAgIHRvPVwiMzYwIDIwIDIwXCJcbiAgICAgICAgICAgICAgICAgIGR1cj1cIjEuNXNcIlxuICAgICAgICAgICAgICAgICAgcmVwZWF0Q291bnQ9XCJpbmRlZmluaXRlXCIvPlxuICAgICAgICAgICAgICAgIDwvcGF0aD5cbiAgICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICA8L2J1dHRvbj5cblxuICAgICAgICAgIDxidXR0b24gY2FwLWJ0bi1uZXh0IGNsYXNzPVwiY2FwLWJ0bi1pY29uIGNhcC1idG4taWNvbi1yYWlzZWRcIj5cbiAgICAgICAgICAgIDxzcGFuPlxuICAgICAgICAgICAgICA8c3ZnIHN0eWxlPVwid2lkdGg6MjRweDtoZWlnaHQ6MjRweFwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIj5cbiAgICAgICAgICAgICAgICAgIDxwYXRoIGZpbGw9XCJjdXJyZW50Q29sb3JcIiBkPVwiTTQsMTBWMTRIMTNMOS41LDE3LjVMMTEuOTIsMTkuOTJMMTkuODQsMTJMMTEuOTIsNC4wOEw5LjUsNi41TDEzLDEwSDRaXCIgLz5cbiAgICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImxvYWRpbmctaWNvblwiPlxuICAgICAgICAgICAgICAgIDxzdmcgdmVyc2lvbj1cIjEuMVwiIGlkPVwibG9hZGVyLTFcIiB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgeG1sbnM6eGxpbms9XCJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rXCIgeD1cIjBweFwiIHk9XCIwcHhcIlxuICAgICAgICAgICAgICAgd2lkdGg9XCIzMnB4XCIgaGVpZ2h0PVwiMzJweFwiIHZpZXdCb3g9XCIwIDAgNDAgNDBcIiBlbmFibGUtYmFja2dyb3VuZD1cIm5ldyAwIDAgNDAgNDBcIiB4bWw6c3BhY2U9XCJwcmVzZXJ2ZVwiPlxuICAgICAgICAgICAgICA8cGF0aCBvcGFjaXR5PVwiMC4yXCIgZmlsbD1cIiMwMDBcIiBkPVwiTTIwLjIwMSw1LjE2OWMtOC4yNTQsMC0xNC45NDYsNi42OTItMTQuOTQ2LDE0Ljk0NmMwLDguMjU1LDYuNjkyLDE0Ljk0NiwxNC45NDYsMTQuOTQ2XG4gICAgICAgICAgICAgICAgczE0Ljk0Ni02LjY5MSwxNC45NDYtMTQuOTQ2QzM1LjE0NiwxMS44NjEsMjguNDU1LDUuMTY5LDIwLjIwMSw1LjE2OXogTTIwLjIwMSwzMS43NDljLTYuNDI1LDAtMTEuNjM0LTUuMjA4LTExLjYzNC0xMS42MzRcbiAgICAgICAgICAgICAgICBjMC02LjQyNSw1LjIwOS0xMS42MzQsMTEuNjM0LTExLjYzNGM2LjQyNSwwLDExLjYzMyw1LjIwOSwxMS42MzMsMTEuNjM0QzMxLjgzNCwyNi41NDEsMjYuNjI2LDMxLjc0OSwyMC4yMDEsMzEuNzQ5elwiLz5cbiAgICAgICAgICAgICAgPHBhdGggZmlsbD1cIiMwMDBcIiBkPVwiTTI2LjAxMywxMC4wNDdsMS42NTQtMi44NjZjLTIuMTk4LTEuMjcyLTQuNzQzLTIuMDEyLTcuNDY2LTIuMDEyaDB2My4zMTJoMFxuICAgICAgICAgICAgICAgIEMyMi4zMiw4LjQ4MSwyNC4zMDEsOS4wNTcsMjYuMDEzLDEwLjA0N3pcIj5cbiAgICAgICAgICAgICAgICA8YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVUeXBlPVwieG1sXCJcbiAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZU5hbWU9XCJ0cmFuc2Zvcm1cIlxuICAgICAgICAgICAgICAgICAgdHlwZT1cInJvdGF0ZVwiXG4gICAgICAgICAgICAgICAgICBmcm9tPVwiMCAyMCAyMFwiXG4gICAgICAgICAgICAgICAgICB0bz1cIjM2MCAyMCAyMFwiXG4gICAgICAgICAgICAgICAgICBkdXI9XCIxLjVzXCJcbiAgICAgICAgICAgICAgICAgIHJlcGVhdENvdW50PVwiaW5kZWZpbml0ZVwiLz5cbiAgICAgICAgICAgICAgICA8L3BhdGg+XG4gICAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgPC9idXR0b24+XG5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwic3BhY2VyXCI+PC9kaXY+XG5cbiAgICAgICAgICA8YnV0dG9uIHRvZ2dsZS1kYXJrIGNsYXNzPVwiY2FwLWJ0bi1pY29uIGNhcC1idG4taGVhZGVyIGMtZC1tb2JpbGUtbm9uZSAke1xuICAgICAgICAgICAgY29uZmlnLnRpbWVsaW5lLndpdGhEYXJrVG9nZ2xlID09IGZhbHNlID8gXCJoaWRlXCIgOiBcIlwiXG4gICAgICAgICAgfVwiPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJoaWRlLWxpZ2h0XCI+XG4gICAgICAgICAgICAgIDxzdmcgd2lkdGg9XCIyNFwiIGhlaWdodD1cIjI0XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiPlxuICAgICAgICAgICAgICAgIDxwYXRoICBmaWxsPVwiY3VycmVudENvbG9yXCIgZD1cIk0xMyw0LjhDOSw0LjggOSwxOS4yIDEzLDE5LjJDMTcsMTkuMiAyMiwxNi41IDIyLDEyQzIyLDcuNSAxNyw0LjggMTMsNC44TTEzLjEsMTcuMkMxMi43LDE2LjggMTIsMTUgMTIsMTJDMTIsOSAxMi43LDcuMiAxMy4xLDYuOEMxNiw2LjkgMjAsOC43IDIwLDEyQzIwLDE1LjMgMTUuOSwxNy4xIDEzLjEsMTcuMk04LDEwLjVDOCwxMSA3LjksMTEuNSA3LjksMTJDNy45LDEyLjIgNy45LDEyLjQgNy45LDEyLjZMMi40LDE0TDEuOSwxMi4xTDgsMTAuNU0yLDdMOS40LDUuMUM5LjIsNS40IDksNS44IDguOSw2LjNDOC44LDYuNiA4LjcsNyA4LjYsNy40TDIuNSw4LjlMMiw3TTguMiwxNS41QzguMywxNi4yIDguNSwxNi45IDguNywxNy40TDIuNCwxOUwxLjksMTcuMUw4LjIsMTUuNVpcIiAvPlxuICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiaGlkZS1kYXJrXCI+XG4gICAgICAgICAgICAgIDxzdmcgd2lkdGg9XCIyNFwiIGhlaWdodD1cIjI0XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiPlxuICAgICAgICAgICAgICAgIDxwYXRoICBmaWxsPVwiY3VycmVudENvbG9yXCIgZD1cIk0xMyw0LjhDOSw0LjggOSwxOS4yIDEzLDE5LjJDMTcsMTkuMiAyMiwxNi41IDIyLDEyQzIyLDcuNSAxNyw0LjggMTMsNC44TTEzLjEsMTcuMkMxMi43LDE2LjggMTIsMTUgMTIsMTJDMTIsOSAxMi43LDcuMiAxMy4xLDYuOEMxNiw2LjkgMjAsOC43IDIwLDEyQzIwLDE1LjMgMTYsMTcuMSAxMy4xLDE3LjJNMiw1SDkuNUM5LjMsNS40IDksNS44IDguOSw2LjRDOC44LDYuNiA4LjgsNi44IDguNyw3SDJWNU04LDExSDJWOUg4LjJDOC4xLDkuNiA4LjEsMTAuMyA4LDExTTguNywxN0M4LjksMTcuOCA5LjIsMTguNCA5LjYsMTlIMi4xVjE3SDguN004LjIsMTVIMlYxM0g4QzguMSwxMy43IDguMSwxNC40IDguMiwxNVpcIiAvPlxuICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICA8L2J1dHRvbj5gO1xuXG4gICAgaWYgKGNvbmZpZy50aW1lbGluZS5oZWFkZXIuZXh0ZW5kLmVuYWJsZWQgIT09IGZhbHNlKSB7XG4gICAgICBzdHIgKz0gYDxidXR0b24gdG9nZ2xlLWhlYWRlciBjbGFzcz1cImNhcC1idG4taWNvbiBjYXAtYnRuLWljb24tcmFpc2VkXCI+XG4gICAgICAgICAgICA8c3Bhbj5cbiAgICAgICAgICAgICAgPHN2ZyBzdHlsZT1cIndpZHRoOjI0cHg7aGVpZ2h0OjI0cHhcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgICAgICAgICAgICAgICA8cGF0aCBmaWxsPVwiY3VycmVudENvbG9yXCIgZD1cIk03LjQxLDguNThMMTIsMTMuMTdMMTYuNTksOC41OEwxOCwxMEwxMiwxNkw2LDEwTDcuNDEsOC41OFpcIiAvPlxuICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICA8L2J1dHRvbj5gO1xuICAgIH1cblxuICAgIHN0ciArPSBgIDxkaXYgY2xhc3M9XCJidXR0b24tcmlnaHQtY29udGFpbmVyXCI+PC9kaXY+XG4gICAgICAgIDwvZGl2PmA7XG4gICAgLypcbiAgICAgICAgICBgXG4gICAgICAgICAgPGJ1dHRvbiB0b2dnbGUtc2lkZWJhci1yaWdodCBjbGFzcz1cImNhcC1idG4taWNvbiBjYXAtYnRuLWljb24tcmFpc2VkXCI+XG4gICAgICAgICAgICA8c3Bhbj5cbiAgICAgICAgICAgICAgPHN2ZyBzdHlsZT1cIndpZHRoOjI0cHg7aGVpZ2h0OjI0cHhcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgICAgICAgICAgICAgICA8cGF0aCBmaWxsPVwiY3VycmVudENvbG9yXCIgZD1cIk0xNS40MSwxNi41OEwxMC44MywxMkwxNS40MSw3LjQxTDE0LDZMOCwxMkwxNCwxOEwxNS40MSwxNi41OFpcIiAvPlxuICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICA8L2J1dHRvbj5cblxuICAgICAgPC9kaXY+XG4gICAgYDtcbiAgICAqL1xuXG4gICAgbGV0ICRyID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChzdHIpO1xuICAgICRlbGVtLnJlcGxhY2VXaXRoKCRyKTtcblxuICAgIGlmIChjb25maWcudGltZWxpbmUuaGVhZGVyLnJpZ2h0QnV0dG9ucykge1xuICAgICAgbGV0ICRidXR0b25Db250YWluZXIgPSAkci5xdWVyeVNlbGVjdG9yKFwiLmJ1dHRvbi1yaWdodC1jb250YWluZXJcIik7XG4gICAgICBjb25maWcudGltZWxpbmUuaGVhZGVyLnJpZ2h0QnV0dG9ucy5mb3JFYWNoKChidXR0b24pID0+IHtcbiAgICAgICAgbGV0IGhhc0JhZGdlID0gZmFsc2U7XG4gICAgICAgIGlmIChidXR0b24uaGFzQmFkZ2UpIHtcbiAgICAgICAgICBoYXNCYWRnZSA9IGJ1dHRvbi5oYXNCYWRnZSgpO1xuICAgICAgICB9XG4gICAgICAgIGxldCBzdHIgPSBgPGJ1dHRvbiBjbGFzcz1cImNhcC1idG4taWNvbiBjYXAtYnRuLWljb24tcmFpc2VkICR7XG4gICAgICAgICAgaGFzQmFkZ2UgPyBcImNhcC1idG4taGFzLWJhZGdlXCIgOiBcIlwiXG4gICAgICAgIH1cIj5cbiAgICAgICAgICAgIDxzcGFuPlxuICAgICAgICAgICAgICA8c3ZnIHN0eWxlPVwid2lkdGg6MjRweDtoZWlnaHQ6MjRweFwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIj5cbiAgICAgICAgICAgICAgICAgIDxwYXRoIGZpbGw9XCJjdXJyZW50Q29sb3JcIiBkPVwiJHtidXR0b24uaWNvbn1cIiAvPlxuICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICA8L2J1dHRvbj5gO1xuICAgICAgICBsZXQgJGJ1dHRvbiA9IGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoc3RyKTtcbiAgICAgICAgJGJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGV2dCkgPT4gYnV0dG9uLm9uQ2xpY2soeyBldnQgfSkpO1xuICAgICAgICAkYnV0dG9uQ29udGFpbmVyLmFwcGVuZCgkYnV0dG9uKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGxldCAkdG9nZ2xlRGFyayA9ICRyLnF1ZXJ5U2VsZWN0b3IoXCJbdG9nZ2xlLWRhcmtdXCIpO1xuICAgIGlmICgkdG9nZ2xlRGFyaykge1xuICAgICAgJHRvZ2dsZURhcmsuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIChlKSA9PiB7XG4gICAgICAgICRyLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwidG9nZ2xlRGFya1wiLCB7XG4gICAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGxldCAkYnRuQ2FsZW5kYXIgPSAkci5xdWVyeVNlbGVjdG9yKFwiW2NhcC1idG4tY2FsZW5kYXJdXCIpO1xuICAgIGlmICgkYnRuQ2FsZW5kYXIpIHtcbiAgICAgICRidG5DYWxlbmRhci5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGUpID0+IHtcbiAgICAgICAgbGV0IHggPSBlLng7XG4gICAgICAgIGxldCB5ID0gZS55O1xuICAgICAgICAkci5kaXNwYXRjaEV2ZW50KFxuICAgICAgICAgIG5ldyBDdXN0b21FdmVudChcImNsaWNrQ2FsZW5kYXJJY29uXCIsIHtcbiAgICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIGRldGFpbDogeyB4LCB5IH0sXG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGxldCAkYnRuVG9nZ2xlSGVhZGVyID0gJHIucXVlcnlTZWxlY3RvcihcIlt0b2dnbGUtaGVhZGVyXVwiKTtcbiAgICBpZiAoJGJ0blRvZ2dsZUhlYWRlcikge1xuICAgICAgJGJ0blRvZ2dsZUhlYWRlci5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGUpID0+IHtcbiAgICAgICAgJHIuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICBuZXcgQ3VzdG9tRXZlbnQoXCJ0b2dnbGVIZWFkZXJcIiwge1xuICAgICAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgICAgIGNhbmNlbGFibGU6IGZhbHNlLFxuICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKlxuICAgICRyLnF1ZXJ5U2VsZWN0b3IoXCJbdG9nZ2xlLXNpZGViYXItcmlnaHRdXCIpLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBlID0+IHtcbiAgICAgICRyLmRpc3BhdGNoRXZlbnQobmV3IEN1c3RvbUV2ZW50KFwidG9nZ2xlU2lkZWJhclJpZ2h0XCIsIHtcbiAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICB9KSk7XG4gICAgfSk7XG4gICAgKi9cblxuICAgICRyLnF1ZXJ5U2VsZWN0b3IoXCJbY2FwLWJ0bi1wcmV2XVwiKS5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGUpID0+IHtcbiAgICAgICRyLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgIG5ldyBDdXN0b21FdmVudChcImhlYWRlclByZXZcIiwge1xuICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICAgICAgZGV0YWlsOiB7XG4gICAgICAgICAgICBvcmlnaW5hbEV2dDogZSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgICRyLnF1ZXJ5U2VsZWN0b3IoXCJbY2FwLWJ0bi1jYWxlbmRhcl1cIikuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIChlKSA9PiB7XG4gICAgICAkci5kaXNwYXRjaEV2ZW50KFxuICAgICAgICBuZXcgQ3VzdG9tRXZlbnQoXCJoZWFkZXJDYWxlbmRhclwiLCB7XG4gICAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICBkZXRhaWw6IHtcbiAgICAgICAgICAgIG9yaWdpbmFsRXZ0OiBlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgJHIucXVlcnlTZWxlY3RvcihcIltjYXAtYnRuLW5leHRdXCIpLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCAoZSkgPT4ge1xuICAgICAgJHIuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwiaGVhZGVyTmV4dFwiLCB7XG4gICAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICBkZXRhaWw6IHtcbiAgICAgICAgICAgIG9yaWdpbmFsRXZ0OiBlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgbGV0ICR0b2dnbGVMZWdlbmRzQnRuID0gJHIucXVlcnlTZWxlY3RvcihcIlt0b2dnbGUtbGVnZW5kc11cIik7XG4gICAgaWYgKCR0b2dnbGVMZWdlbmRzQnRuKSB7XG4gICAgICAkdG9nZ2xlTGVnZW5kc0J0bi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGUpID0+IHtcbiAgICAgICAgbGV0ICRsZWdlbmRDb250YWluZXIgPSAkci5xdWVyeVNlbGVjdG9yKFwiLmxlZ2VuZHMtY29udGFpbmVyXCIpO1xuICAgICAgICBpZiAoJGxlZ2VuZENvbnRhaW5lcikge1xuICAgICAgICAgICRsZWdlbmRDb250YWluZXIuY2xhc3NMaXN0LnRvZ2dsZShcImhpZGVcIik7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgICRyLnF1ZXJ5U2VsZWN0b3JBbGwoXCIubGVnZW5kXCIpLmZvckVhY2goKCRsZWdlbmQpID0+IHtcbiAgICAgICRsZWdlbmQuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIChlKSA9PiB7XG4gICAgICAgIGxldCBrZXkgPSBlLmN1cnJlbnRUYXJnZXQuZ2V0QXR0cmlidXRlKFwiaW5wdXQta2V5XCIpO1xuXG4gICAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgICBsZXQgbGVnZW5kU2VsZWN0ZWQgPSB0YWJTZWxlY3RlZC5sZWdlbmRzLmZpbmQoXG4gICAgICAgICAgICAodGFiKSA9PiB0YWIua2V5ID09PSBrZXlcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmIChsZWdlbmRTZWxlY3RlZCkge1xuICAgICAgICAgICAgJHIuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwic2VsZWN0TGVnZW5kSGVhZGVyXCIsIHtcbiAgICAgICAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNhbmNlbGFibGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGRldGFpbDoge1xuICAgICAgICAgICAgICAgICAgbGVnZW5kOiBsZWdlbmRTZWxlY3RlZCxcbiAgICAgICAgICAgICAgICAgICRsZWdlbmQsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgICRyLnF1ZXJ5U2VsZWN0b3JBbGwoXCIudGFiOm5vdCguZGlzYWJsZWQpXCIpLmZvckVhY2goKCR0YWIpID0+IHtcbiAgICAgICR0YWIuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIChlKSA9PiB7XG4gICAgICAgIGxldCBrZXkgPSBlLmN1cnJlbnRUYXJnZXQuZ2V0QXR0cmlidXRlKFwiaW5wdXQta2V5XCIpO1xuXG4gICAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgICBsZXQgdGFiU2VsZWN0ZWQgPSBjb25maWcudGltZWxpbmUudGFicy5maW5kKCh0YWIpID0+IHRhYi5pZCA9PSBrZXkpO1xuICAgICAgICAgIGlmICh0YWJTZWxlY3RlZCkge1xuICAgICAgICAgICAgJHIuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwic2VsZWN0VGFiSGVhZGVyXCIsIHtcbiAgICAgICAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNhbmNlbGFibGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGRldGFpbDoge1xuICAgICAgICAgICAgICAgICAgdGFiOiB0YWJTZWxlY3RlZCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgJHIucXVlcnlTZWxlY3RvckFsbChcIi50YWJzLXNlbGVjdDpub3QoLmRpc2FibGVkKVwiKS5mb3JFYWNoKCgkdGFiKSA9PiB7XG4gICAgICAkdGFiLmFkZEV2ZW50TGlzdGVuZXIoXCJjaGFuZ2VcIiwgKGUpID0+IHtcbiAgICAgICAgbGV0IGtleSA9IHBhcnNlRmxvYXQoZS5jdXJyZW50VGFyZ2V0LnZhbHVlKTtcblxuICAgICAgICBpZiAoa2V5KSB7XG4gICAgICAgICAgbGV0IHRhYlNlbGVjdGVkID0gY29uZmlnLnRpbWVsaW5lLnRhYnMuZmluZCgodGFiKSA9PiB0YWIuaWQgPT0ga2V5KTtcbiAgICAgICAgICBpZiAodGFiU2VsZWN0ZWQpIHtcbiAgICAgICAgICAgICRyLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgICAgIG5ldyBDdXN0b21FdmVudChcInNlbGVjdFRhYkhlYWRlclwiLCB7XG4gICAgICAgICAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBkZXRhaWw6IHtcbiAgICAgICAgICAgICAgICAgIHRhYjogdGFiU2VsZWN0ZWQsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHJldHVybiAkcjtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBIZWFkZXJcbiAgICogU2UgdXNhIHBhcmEgOlxuICAgKiAgICAtIE1vc3RyYXIgZmVjaGFzIGVuIGhlYWRlclxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbVxuICAgKi9cbiAgY3JlYXRlSGVhZGVyKGNvbmZpZykge1xuICAgIGxldCAkZWxlbSA9IGRvbS5jcmVhdGVFbGVtZW50KFwiaGVhZGVyXCIpO1xuICAgIHJldHVybiB0aGlzLnJlZHJhd0hlYWRlcihjb25maWcsICRlbGVtKTtcbiAgfSxcblxuICAvKipcbiAgICogUmVjcmVhIEhlYWRlciwgdXNhZG8gcGFyYSByZWRpYnVqYXJcbiAgICogdXRpbGl6YSAkZWxlbSBjb21vIGVsZW1lbnRvIGRvbSBkb25kZSByZWNyZWFybG9cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIENvbmZpZ3VyYWNpb24gY2FwaWJhcmFcbiAgICogQHBhcmFtIHtPYmplY3R9ICRlbGVtIC0gRWxlbWVudG8gRG9tIGRvbmRlIGNyZWEgSGVhZGVyXG4gICAqIEByZXR1cm4ge09iamVjdH0gRWxlbWVudG8gRG9tXG4gICAqL1xuICByZWRyYXdIZWFkZXIoY29uZmlnLCAkZWxlbSkge1xuICAgIGxldCBkYXRlc1RyZWUgPSBkYXRlVXRpbHMuZ2V0RGF0ZVRyZWVSYW5nZShcbiAgICAgIG5ldyBEYXRlKGNvbmZpZy50aW1lbGluZS5zdGFydCksXG4gICAgICBuZXcgRGF0ZShjb25maWcudGltZWxpbmUuZW5kKVxuICAgICk7XG5cbiAgICBsZXQgc3RyID0gYDxkaXYgY2xhc3M9XCJoZWFkZXItY29udGFpbmVyXCI+IGA7XG5cbiAgICBPYmplY3Qua2V5cyhkYXRlc1RyZWUpLmZvckVhY2goKGtleVkpID0+IHtcbiAgICAgIGxldCB5ZWFyID0gZGF0ZXNUcmVlW2tleVldO1xuICAgICAgc3RyICs9IGA8ZGl2IGNsYXNzPVwiYWduby1jYWxlbmRhcmlvXCI+XG4gICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYWdubyBoaWRlXCI+JHtrZXlZfTwvc3Bhbj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1lc2VzXCI+YDtcblxuICAgICAgT2JqZWN0LmtleXMoeWVhcikuZm9yRWFjaCgoa2V5TSkgPT4ge1xuICAgICAgICBsZXQgbW9udGggPSBkYXRlc1RyZWVba2V5WV1ba2V5TV07XG4gICAgICAgIHN0ciArPSBgIDxkaXYgY2xhc3M9XCJtZXMtY2FsZW5kYXJpb1wiPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWVzICR7XG4gICAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmtleXMobW9udGgpLmxlbmd0aCA8IDRcbiAgICAgICAgICAgICAgICAgICAgICAgID8gXCJtZXMtcmVkdWNlZCBtZXMtcmVkdWNlZC1cIiArIE9iamVjdC5rZXlzKG1vbnRoKS5sZW5ndGhcbiAgICAgICAgICAgICAgICAgICAgICAgIDogXCJcIlxuICAgICAgICAgICAgICAgICAgICB9XCI+XG4gICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1lcy1sYWJlbFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgJHt1dGlscy5nZXRNb250aEJ5UG9zaXRpb24oa2V5TSl9ICR7a2V5WX1cbiAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkaWFzXCI+YDtcbiAgICAgICAgT2JqZWN0LmtleXMobW9udGgpLmZvckVhY2goKGtleUQpID0+IHtcbiAgICAgICAgICBsZXQgZGF5ID0gZGF0ZXNUcmVlW2tleVldW2tleU1dW2tleURdO1xuICAgICAgICAgIGxldCBpc1dlZWtlbmQgPSBkYXkuaXNXZWVrZW5kO1xuICAgICAgICAgIGxldCBpc1RvZGF5ID0gZGF5LmlzVG9kYXk7XG4gICAgICAgICAgbGV0IGRhdGUgPSBkYXRlVXRpbHMuZm9ybWF0RGF0ZShkYXkuRGF0ZSk7XG4gICAgICAgICAgc3RyICs9IGA8ZGl2IGNsYXNzPVwiZGlhLWNhbGVuZGFyaW8gJHtpc1RvZGF5ID8gXCJ0b2RheVwiIDogXCJcIn0gICR7XG4gICAgICAgICAgICBpc1dlZWtlbmQgPyBcIndlZWtlbmRcIiA6IFwiXCJcbiAgICAgICAgICB9ICR7XG4gICAgICAgICAgICBjb25maWcudGltZWxpbmUuZGF0ZVNlbGVjdGFibGUgPyBcImlzLWNsaWNrZWFibGVcIiA6IFwiXCJcbiAgICAgICAgICB9XCIgZGF0ZT1cIiR7ZGF0ZX1cIj4ke2tleUR9PC9kaXY+YDtcbiAgICAgICAgfSk7XG4gICAgICAgIHN0ciArPSBgPC9kaXY+PC9kaXY+YDtcbiAgICAgIH0pO1xuICAgICAgc3RyICs9IGA8L2Rpdj4gPC9kaXY+YDtcbiAgICB9KTtcblxuICAgIHN0ciArPSBgPC9kaXY+YDtcbiAgICAkZWxlbS5pbm5lckhUTUwgPSBcIlwiO1xuICAgICRlbGVtLmFwcGVuZChkb20uY3JlYXRlRWxlbWVudEZyb21IVE1MKHN0cikpO1xuXG4gICAgaWYgKGNvbmZpZy50aW1lbGluZS5kYXRlU2VsZWN0YWJsZSkge1xuICAgICAgJGVsZW0ucXVlcnlTZWxlY3RvckFsbChcIi5kaWEtY2FsZW5kYXJpb1tkYXRlXVwiKS5mb3JFYWNoKCgkZGlhKSA9PiB7XG4gICAgICAgICRkaWEuYWRkRXZlbnRMaXN0ZW5lcihcImNvbnRleHRtZW51XCIsIChldnQpID0+IHtcbiAgICAgICAgICAkZWxlbS5kaXNwYXRjaEV2ZW50KFxuICAgICAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwiY29udGV4dE1lbnVEYXRlXCIsIHtcbiAgICAgICAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICAgICAgICAgIGRldGFpbDoge1xuICAgICAgICAgICAgICAgICRlbGVtOiAkZGlhLFxuICAgICAgICAgICAgICAgIGRhdGU6ICRkaWEuZ2V0QXR0cmlidXRlKFwiZGF0ZVwiKSxcbiAgICAgICAgICAgICAgICBjbGllbnRYOiBldnQuY2xpZW50WCxcbiAgICAgICAgICAgICAgICBjbGllbnRZOiBldnQuY2xpZW50WSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgJGRpYS5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGV2dCkgPT4ge1xuICAgICAgICAgICRlbGVtLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgICBuZXcgQ3VzdG9tRXZlbnQoXCJjbGlja0RhdGVcIiwge1xuICAgICAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgZGV0YWlsOiB7XG4gICAgICAgICAgICAgICAgJGVsZW06ICRkaWEsXG4gICAgICAgICAgICAgICAgZGF0ZTogJGRpYS5nZXRBdHRyaWJ1dGUoXCJkYXRlXCIpLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiAkZWxlbTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBIZWFkZXIgZXh0ZW5kZWRcbiAgICogU2UgdXNhIHBhcmEgOlxuICAgKiAgICAtTW9zdHJhciBpbnB1dHMgeSBkYXRvcyBwYXJhIGZlY2hhcyBlbiBoZWFkZXJcbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIENvbmZpZ3VyYWNpb24gY2FwaWJhcmFcbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gaGVhZGVyRXh0ZW5kZWRcbiAgICovXG4gIGNyZWF0ZUhlYWRlckV4dGVuZGVkKGNvbmZpZykge1xuICAgIGlmIChjb25maWcudGltZWxpbmUuaGVhZGVyLmV4dGVuZC5lbmFibGVkID09IGZhbHNlKSByZXR1cm4gbnVsbDtcblxuICAgIGxldCBkYXRlcyA9IGRhdGVVdGlscy5nZXREYXRlUmFuZ2UoXG4gICAgICBuZXcgRGF0ZShjb25maWcudGltZWxpbmUuc3RhcnQpLFxuICAgICAgbmV3IERhdGUoY29uZmlnLnRpbWVsaW5lLmVuZClcbiAgICApO1xuICAgIGxldCBzdHIgPSBgPGRpdiBjbGFzcz1cImhlYWRlci1jb250YWluZXItZXh0ZW5kZWRcIj5gO1xuXG4gICAgY29uZmlnLnRpbWVsaW5lLmhlYWRlci5leHRlbmQuZGF0YS5mb3JFYWNoKChkLCBkX2luZGV4KSA9PiB7XG4gICAgICBpZiAoZC5pc0hpZGRlbikgcmV0dXJuIFwiXCI7XG5cbiAgICAgIGxldCBpc1BlcnNpc3RlbnQgPSBkLmlzUGVyc2lzdGVudDtcbiAgICAgIHN0ciArPSBgPGRpdiBjbGFzcz1cImlucHV0LWxpc3QgJHtpc1BlcnNpc3RlbnQgPyBcInBlcnNpc3RlbnRcIiA6IFwiXCJ9XCI+YDtcbiAgICAgIHN0ciArPSBkYXRlc1xuICAgICAgICAubWFwKChkYXRlKSA9PiB7XG4gICAgICAgICAgbGV0IHZhbHVlID0gXCJcIjtcbiAgICAgICAgICBsZXQgaXNGdXR1cmUgPSBkYXRlVXRpbHMuaXNGdXR1cmUoZGF0ZSk7XG4gICAgICAgICAgbGV0IGlzVG9kYXkgPSBkYXRlVXRpbHMuaXNUb2RheShkYXRlKTtcblxuICAgICAgICAgIGlmIChkLmRhdGEpIHtcbiAgICAgICAgICAgIGxldCBkYXRhRm91bmRlZCA9IGQuZGF0YS5maW5kKChkYXRhSW5wdXQpID0+IHtcbiAgICAgICAgICAgICAgcmV0dXJuIGRhdGVVdGlscy5pc1NhbWVEYXRlKG5ldyBEYXRlKGRhdGFJbnB1dC5kYXRlKSwgZGF0ZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChkYXRhRm91bmRlZCkge1xuICAgICAgICAgICAgICB2YWx1ZSA9IGRhdGFGb3VuZGVkLnZhbHVlIHx8IFwiXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgZC5lZGl0YWJsZSA9PT0gZmFsc2UgfHxcbiAgICAgICAgICAgIChpc0Z1dHVyZSAmJiBkLmVkaXRhYmxlRnV0dXJlID09IGZhbHNlKSB8fFxuICAgICAgICAgICAgKGlzVG9kYXkgJiYgZC5lZGl0YWJsZVRvZGF5ID09IGZhbHNlKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuIGA8ZGl2PlxuICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGRhdGU9XCIke2RhdGV9XCIgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXg9XCIke2RfaW5kZXh9XCIgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCIke2RhdGUudmFyTmFtZX0gJHtcbiAgICAgICAgICAgICAgZC5jb2xvciA/IFwiYy1cIiArIGQuY29sb3IgKyBcIi0tdGV4dFwiIDogXCJcIlxuICAgICAgICAgICAgfVwiID4gXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHt2YWx1ZX0gXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGxldCBpc0Rpc2FibGVkID0gZmFsc2U7XG4gICAgICAgICAgaWYgKGNvbmZpZy50aW1lbGluZS5lZGl0YWJsZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGlzRGlzYWJsZWQgPSB0cnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBgPGRpdiBjbGFzcz1cImRpYS1pbnB1dFwiPlxuICAgICAgICAgICAgICAgICAgPGlucHV0IFxuICAgICAgICAgICAgICAgICAgZGF0ZT1cIiR7ZGF0ZX1cIiBcbiAgICAgICAgICAgICAgICAgIGluZGV4PVwiJHtkX2luZGV4fVwiIFxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJoZWFkZXItaW5wdXQgXG4gICAgICAgICAgICAgICAgICAke2RhdGUudmFyTmFtZX0gJHtkLmNvbG9yID8gXCJjLVwiICsgZC5jb2xvciArIFwiLS10ZXh0XCIgOiBcIlwifVwiIFxuICAgICAgICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXG4gICAgICAgICAgICAgICAgICAke2lzRGlzYWJsZWQgPyBcImRpc2FibGVkXCIgOiBcIlwifSBcbiAgICAgICAgICAgICAgICAgIHZhbHVlPVwiJHt2YWx1ZX1cIj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICB9KVxuICAgICAgICAuam9pbihcIlwiKTtcbiAgICAgIHN0ciArPSBgPC9kaXY+YDtcbiAgICB9KTtcblxuICAgIHN0ciArPSBgPC9kaXY+YDtcblxuICAgIGxldCByID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChzdHIpO1xuXG4gICAgci5xdWVyeVNlbGVjdG9yQWxsKFwiaW5wdXQuaGVhZGVyLWlucHV0XCIpLmZvckVhY2goKGlucHV0KSA9PiB7XG4gICAgICBpbnB1dC5hZGRFdmVudExpc3RlbmVyKFwiaW5wdXRcIiwgKGUpID0+IHtcbiAgICAgICAgbGV0IGRhdGUgPSBlLmN1cnJlbnRUYXJnZXQuZ2V0QXR0cmlidXRlKFwiZGF0ZVwiKTtcbiAgICAgICAgbGV0IGluZGV4ID0gZS5jdXJyZW50VGFyZ2V0LmdldEF0dHJpYnV0ZShcImluZGV4XCIpO1xuICAgICAgICBsZXQgdmFsdWUgPSBlLmN1cnJlbnRUYXJnZXQudmFsdWU7XG4gICAgICAgIGxldCB0eXBlRGF0YSA9IGNvbmZpZy50aW1lbGluZS5oZWFkZXIuZXh0ZW5kLmRhdGFbaW5kZXhdO1xuXG4gICAgICAgIC8vcmVmcmVzaCBjb25maWcgdmFsdWVcbiAgICAgICAgbGV0IGRhdGEgPSB0eXBlRGF0YS5kYXRhLmZpbmQoKGQpID0+XG4gICAgICAgICAgZGF0ZVV0aWxzLmlzU2FtZURhdGUobmV3IERhdGUoZC5kYXRlKSwgbmV3IERhdGUoZGF0ZSkpXG4gICAgICAgICk7XG4gICAgICAgIGRhdGEudmFsdWUgPSB2YWx1ZTtcblxuICAgICAgICByLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwiY2hhbmdlSW5wdXRIZWFkZXJcIiwge1xuICAgICAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgICAgIGNhbmNlbGFibGU6IGZhbHNlLFxuICAgICAgICAgICAgZGV0YWlsOiB7XG4gICAgICAgICAgICAgIGRhdGU6IGRhdGUsXG4gICAgICAgICAgICAgIHR5cGVEYXRhOiB0eXBlRGF0YSxcbiAgICAgICAgICAgICAgdmFsdWU6IHZhbHVlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gcjtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYXIgU2lkZWJhciBJenF1aWVyZG9cbiAgICogICAgLSBNYW5lamEgaXRlbXMgY29tbyBhcmJvbCBkZSAyIG5pdmVsZXMgKHBhcmVudCwgY2hpbGRyZW4pXG4gICAqICAgIC0gRWwgc2lkZWJhciBzZSBkaXZpZGUgZW4gbmF2TGlzdCAtIEluaXRpYWxOYXYgLSBleHRlbmRlZE5hdiAtIEJ0bk5hdlxuICAgKiAgICAtIFNlIGFncmVnYSBpdGVtRGV0YWlsLCBwYXJhIGRldGFsbGVzIGRlIGl0ZW1zXG4gICAqXG4gICAqXG4gICAqIFRPRE86IHBhcmEgZXZpdGFyIGluY3J1c3RhciBsYXMgaWRzIGVuIGxvcyBpbnB1dHMsIHNlIGRlYmVuIGNyZWFyXG4gICAqIGxvcyBub2RvcyB1bm8gcG9yIHVubyBjb21vIGVsZW1lbnRvIERPTSwgeSBhZ3JlZ2FybGVzIGxvcyBldmVudG9zIGRpcmVjdGFtZW50ZVxuICAgKiBhaG9yYSBzZSBoYWNlIHNlbGVjY2lvbmFuZG8gdG9kb3MgbG9zIGlucHV0cyBjb24gcXVlcnlTZWxlY3RvckFsbFxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBTaWRlYmFyIEl6cXVpZXJkb1xuICAgKi9cbiAgY3JlYXRlTmF2TGVmdChjb25maWcsIHRhYiA9IG51bGwpIHtcbiAgICBsZXQgJGVsZW0gPSBkb20uY3JlYXRlRWxlbWVudChcIm5hdlwiLCB7IGNsYXNzTmFtZTogXCJsZWZ0XCIgfSk7XG4gICAgcmV0dXJuIHRoaXMucmVkcmF3TmF2TGVmdCgkZWxlbSwgY29uZmlnLCB0YWIpO1xuICB9LFxuXG4gIC8qKlxuICAgKiBSZWNyZWEgU2lkZWJhciBpenF1aWVyZG8sIHVzYWRvIHBhcmEgcmVkaWJ1amFyXG4gICAqIFV0aWxpemEgJGVsZW0gY29tbyBlbGVtZW50byBkb20gZG9uZGUgcmVjcmVhcmxvXG4gICAqXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSAkZWxlbSAtIEVsZW1lbnRvIERvbSBkb25kZSBjcmVhIGVsIHNpZGViYXIgaXpxdWllcmRvXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBjb25maWcgLSBDb25maWd1cmFjaW9uIGNhcGliYXJhXG4gICAqIEByZXR1cm4ge09iamVjdH0gRWxlbWVudG8gRG9tIG5hdkxlZnRcbiAgICovXG5cbiAgcmVkcmF3TmF2TGVmdCgkZWxlbSwgY29uZmlnLCB0YWIgPSBudWxsKSB7XG4gICAgbGV0IG5hdkxpc3QgPSBcIlwiO1xuICAgIGxldCBpbml0aWFsTmF2TGlzdCA9IFwiXCI7XG4gICAgbGV0IGV4TmF2TGlzdCA9IFwiXCI7XG4gICAgbGV0IGJ0bk5hdkxpc3QgPSBcIlwiO1xuICAgIGxldCBpc0Rpc2FibGVkID0gZmFsc2U7XG4gICAgaWYgKGNvbmZpZy50aW1lbGluZS5lZGl0YWJsZSA9PT0gZmFsc2UpIHtcbiAgICAgIGlzRGlzYWJsZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIGNvbmZpZy5kYXRhLmZvckVhY2goKGQpID0+IHtcbiAgICAgIGlmIChkLmlzSGlkZGVuKSByZXR1cm47XG5cbiAgICAgIG5hdkxpc3QgKz0gYFxuICAgICAgIDxkaXYgY2xhc3M9XCJuYXYtaXRlbVwiPlxuXG5cbiAgICAgICAgPGRpdiBjbGFzcz1cIm5hdi1pdGVtLWNvbnRhaW5lciBwYXJlbnRcIj5gO1xuXG4gICAgICBpZiAoZC5jaGlsZHJlbikge1xuICAgICAgICBuYXZMaXN0ICs9IGA8YnV0dG9uIGNsYXNzPVwidHJlZS1pY29uICR7XG4gICAgICAgICAgZC5pc0Nsb3NlZCA/IFwiXCIgOiBcImNhcC1yb3RhdGVcIlxuICAgICAgICB9XCIgaXRlbS1pZD1cIiR7ZC5pZCB8fCAtMX1cIiB0eXBlLW5vZGU9XCIke2QudHlwZSB8fCBcIlwifVwiID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHN2ZyBzdHlsZT1cIndpZHRoOjI0cHg7aGVpZ2h0OjI0cHhcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGZpbGw9XCJjdXJyZW50Q29sb3JcIiBkPVwiTTcuNDEsOC41OEwxMiwxMy4xN0wxNi41OSw4LjU4TDE4LDEwTDEyLDE2TDYsMTBMNy40MSw4LjU4WlwiIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+YDtcbiAgICAgIH1cblxuICAgICAgbmF2TGlzdCArPSBgXG4gICAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tdGl0bGUgdHJ1bmNhdGUgZnVsbC13aWR0aCAke1xuICAgICAgICAgICAgICAgICAgICAgIGQuY2xpY2tlYWJsZSA/IFwiY2xpY2tlYWJsZVwiIDogXCJcIiB9XG4gICAgICAgICAgICAgICAgICAgICAgJHsgZC5uYXZPdmVyPyBcImhvdmVyYWJsZVwiIDogXCJcIlxuICAgICAgICAgIH0gXCIgaXRlbS1pZD1cIiR7ZC5pZCB8fCAtMX1cIiB0eXBlLW5vZGU9XCIke2QudHlwZSB8fCBcIlwifVwiID5cbiAgICAgICAgICAgICR7ZC5sYWJlbH1cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+YDtcblxuICAgICAgaWYgKGQuY2hpbGRyZW4pIHtcbiAgICAgICAgbmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjaGlsZHJlbi1pdGVtcyAke1xuICAgICAgICAgICAgICAgIGQuaXNDbG9zZWQgPyBcImhpZGVcIiA6IFwiXCJcbiAgICAgICAgICAgICAgfSBcIiBjaGlsZC1saXN0PVwiJHtkLmlkIHx8IC0xfVwiPmA7XG5cbiAgICAgICAgZC5jaGlsZHJlbi5mb3JFYWNoKChjKSA9PiB7XG4gICAgICAgICAgaWYgKGMuaXNIaWRkZW4pIHJldHVybjtcblxuICAgICAgICAgIG5hdkxpc3QgKz0gYFxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjaGlsZC1uYXYtaXRlbVwiPlxuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm5hdi1pdGVtLWNvbnRhaW5lclwiPlxuICAgICAgICAgICAgICAgICAgICBgO1xuXG4gICAgICAgICAgLypcbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJuYXYtaXRlbS1pY29uXCI+XG4gICAgICAgICAgICAgICAgICAgICAgPHN2ZyBzdHlsZT1cIndpZHRoOjI0cHg7aGVpZ2h0OjI0cHhcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGZpbGw9XCJjdXJyZW50Q29sb3JcIiBkPVwiTTE5LDE1TDEzLDIxTDExLjU4LDE5LjU4TDE1LjE3LDE2SDRWNEg2VjE0SDE1LjE3TDExLjU4LDEwLjQyTDEzLDlMMTksMTVaXCIgLz5cbiAgICAgICAgICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICovXG5cbiAgICAgICAgICBuYXZMaXN0ICs9IGBcbiAgICAgICAgICAgICAgICAgICAgJHtcbiAgICAgICAgICAgICAgICAgICAgICBjLmxpZ2h0XG4gICAgICAgICAgICAgICAgICAgICAgICA/ICc8c3BhbiBjbGFzcz1cImxpZ2h0ICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAoYy5saWdodCA/IGMubGlnaHQgKyBcIi1saWdodFwiIDogXCJcIikgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAnXCI+PC9zcGFuPidcbiAgICAgICAgICAgICAgICAgICAgICAgIDogXCJcIlxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tdGl0bGUgJHtcbiAgICAgICAgICAgICAgICAgICAgICBjLmNsaWNrZWFibGUgPyBcImNsaWNrZWFibGVcIiA6IFwiXCIgfVxuICAgICAgICAgICAgICAgICAgICAgICR7IGMubmF2T3Zlcj8gXCJob3ZlcmFibGVcIiA6IFwiXCJcbiAgICAgICAgICAgICAgICAgICAgfVwiIGl0ZW0taWQ9XCIke2MuaWQgfHwgLTF9XCIgdHlwZS1ub2RlPVwiJHtjLnR5cGUgfHwgXCJcIn1cIj5cbiAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidHJ1bmNhdGVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICR7Yy5sYWJlbH1cbiAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICB9KTtcblxuICAgICAgICBuYXZMaXN0ICs9IGBcbiAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgIH1cblxuICAgICAgbmF2TGlzdCArPSBgPC9kaXY+YDtcblxuICAgICAgLy9pbml0aWFsXG4gICAgICBpbml0aWFsTmF2TGlzdCArPSBgPGRpdiBjbGFzcz1cImluaXRpYWwtbmF2LWl0ZW0gcGFyZW50XCI+YDtcbiAgICAgIGlmIChkLndpdGhOYXYpIHtcbiAgICAgICAgY29uZmlnLnRpbWVsaW5lLm5hdi5sZWZ0LmluaXRpYWwudmFycy5mb3JFYWNoKCh2KSA9PiB7XG4gICAgICAgICAgbGV0IHZhbHVlID0gdXRpbHMuZ2V0VmFyQnlQYXRoKGQudmFsdWVzLCB2LnZhck5hbWUpXG5cbiAgICAgICAgICBpZiAodi5yb3VuZCAmJiAhaXNOYU4odmFsdWUpKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHV0aWxzLnJvdW5kKHZhbHVlLCB2LnJvdW5kKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHYuaW5wdXQpIHtcbiAgICAgICAgICAgIHN3aXRjaCAodi5pbnB1dCkge1xuICAgICAgICAgICAgICBjYXNlIFwiaG91clwiOlxuICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWUuc3BsaXQoXCI6XCIpO1xuICAgICAgICAgICAgICAgIGxldCBoaFZhbHVlID0gdmFsdWVbMF07XG4gICAgICAgICAgICAgICAgbGV0IG1tVmFsdWUgPSB2YWx1ZVsxXTtcbiAgICAgICAgICAgICAgICBpbml0aWFsTmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tY29sIGhhcy1pbnB1dFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImhvdXItaW5wdXRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC10eXBlPVwidGltZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heD1cIjIzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluPVwiMDBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1rZXk9XCIke3Yua2V5IHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS1pZD1cIiR7ZC5pZCB8fCAtMX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlLW5vZGU9XCIke2QudHlwZSB8fCBcIlwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPVwiJHtoaFZhbHVlfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7aXNEaXNhYmxlZCA/IFwiZGlzYWJsZWRcIiA6IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiaGhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4+Ojwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC10eXBlPVwidGltZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heD1cIjU5XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluPVwiMDBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1rZXk9XCIke3Yua2V5IHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS1pZD1cIiR7ZC5pZCB8fCAtMX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlLW5vZGU9XCIke2QudHlwZSB8fCBcIlwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPVwiJHttbVZhbHVlfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7aXNEaXNhYmxlZCA/IFwiZGlzYWJsZWRcIiA6IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwibW1cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PmA7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIGNhc2UgXCJ0ZXh0XCI6XG4gICAgICAgICAgICAgIGNhc2UgXCJudW1iZXJcIjpcbiAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBpbml0aWFsTmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tY29sIGhhcy1pbnB1dFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0ICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cIiR7di5pbnB1dCB8fCBcInRleHRcIn1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC10eXBlPVwiJHt2LmlucHV0IHx8IFwidGV4dFwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LWtleT1cIiR7di5rZXkgfHwgXCJcIn1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLWlkPVwiJHtkLmlkIHx8IC0xfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUtbm9kZT1cIiR7ZC50eXBlIHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHtpc0Rpc2FibGVkID8gXCJkaXNhYmxlZFwiIDogXCJcIn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9XCIke3ZhbHVlfVwiLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpbml0aWFsTmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpdGVtLWNvbFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7dmFsdWV9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PmA7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaW5pdGlhbE5hdkxpc3QgKz0gYFxuICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcblxuICAgICAgaWYgKGQuY2hpbGRyZW4pIHtcbiAgICAgICAgZC5jaGlsZHJlbi5mb3JFYWNoKChjKSA9PiB7XG4gICAgICAgICAgaWYgKGMuaXNIaWRkZW4pIHJldHVybjtcbiAgICAgICAgICBpbml0aWFsTmF2TGlzdCArPSBgPGRpdiBjbGFzcz1cImNoaWxkLWluaXRpYWwtbmF2LWl0ZW0gJHtcbiAgICAgICAgICAgIGQuaXNDbG9zZWQgPyBcImhpZGVcIiA6IFwiXCJcbiAgICAgICAgICB9XCIgY2hpbGQ9XCIke2QuaWQgfHwgLTF9XCI+YDtcblxuICAgICAgICAgIGlmKGMud2l0aE5hdiAhPT0gZmFsc2Upe1xuICAgICAgICAgICAgY29uZmlnLnRpbWVsaW5lLm5hdi5sZWZ0LmluaXRpYWwudmFycy5mb3JFYWNoKCh2KSA9PiB7XG4gICAgICAgICAgICAgIGlmICh2Lm9ubHlUYWIgJiYgdGFiICYmIHYub25seVRhYiAhPT0gdGFiLmtleSkgcmV0dXJuO1xuXG4gICAgICAgICAgICAgIGxldCB2YWx1ZSA9IHV0aWxzLmdldFZhckJ5UGF0aChjLnZhbHVlcywgdi52YXJOYW1lKVxuICAgICAgICAgICAgICBpZiAodi5yb3VuZCAmJiAhaXNOYU4odmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSB1dGlscy5yb3VuZCh2YWx1ZSwgdi5yb3VuZCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKHYuaW5wdXQpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHYuaW5wdXQpIHtcbiAgICAgICAgICAgICAgICAgIGNhc2UgXCJob3VyXCI6XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWUuc3BsaXQoXCI6XCIpO1xuICAgICAgICAgICAgICAgICAgICBsZXQgaGhWYWx1ZSA9IHZhbHVlWzBdO1xuICAgICAgICAgICAgICAgICAgICBsZXQgbW1WYWx1ZSA9IHZhbHVlWzFdO1xuICAgICAgICAgICAgICAgICAgICBpbml0aWFsTmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tY29sIGhhcy1pbnB1dFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImhvdXItaW5wdXRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC10eXBlPVwidGltZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heD1cIjIzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluPVwiMDBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1rZXk9XCIke3Yua2V5IHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS1pZD1cIiR7Yy5pZCB8fCAtMX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlLW5vZGU9XCIke2MudHlwZSB8fCBcIlwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPVwiJHtoaFZhbHVlfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7aXNEaXNhYmxlZCA/IFwiZGlzYWJsZWRcIiA6IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiaGhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4+Ojwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC10eXBlPVwidGltZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heD1cIjU5XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluPVwiMDBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1rZXk9XCIke3Yua2V5IHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS1pZD1cIiR7Yy5pZCB8fCAtMX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlLW5vZGU9XCIke2MudHlwZSB8fCBcIlwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPVwiJHttbVZhbHVlfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7aXNEaXNhYmxlZCA/IFwiZGlzYWJsZWRcIiA6IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwibW1cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PmA7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgY2FzZSBcInRleHRcIjpcbiAgICAgICAgICAgICAgICAgIGNhc2UgXCJudW1iZXJcIjpcbiAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGluaXRpYWxOYXZMaXN0ICs9IGBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaXRlbS1jb2wgaGFzLWlucHV0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cIiR7di5pbnB1dCB8fCBcInRleHRcIn1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC10eXBlPVwiJHt2LmlucHV0IHx8IFwidGV4dFwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LWtleT1cIiR7di5rZXkgfHwgXCJcIn1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLWlkPVwiJHtjLmlkIHx8IC0xfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUtbm9kZT1cIiR7Yy50eXBlIHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHtpc0Rpc2FibGVkID8gXCJkaXNhYmxlZFwiIDogXCJcIn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9XCIke3ZhbHVlfVwiLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpbml0aWFsTmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpdGVtLWNvbFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7dmFsdWV9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PmA7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIGluaXRpYWxOYXZMaXN0ICs9IGBcbiAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgLy9FeHRcbiAgICAgIGV4TmF2TGlzdCArPSBgPGRpdiBjbGFzcz1cImV4LW5hdi1pdGVtIHBhcmVudFwiPmA7XG4gICAgICBpZiAoZC53aXRoRXhOYXYpIHtcbiAgICAgICAgY29uZmlnLnRpbWVsaW5lLm5hdi5sZWZ0LmV4dGVuZC52YXJzLmZvckVhY2goKHYpID0+IHtcbiAgICAgICAgICBsZXQgdmFsdWUgPSB1dGlscy5nZXRWYXJCeVBhdGgoZC52YWx1ZXMsIHYudmFyTmFtZSlcbiAgICAgICAgICBpZiAodi5yb3VuZCAmJiAhaXNOYU4odmFsdWUpKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHV0aWxzLnJvdW5kKHZhbHVlLCB2LnJvdW5kKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHYuaW5wdXQpIHtcbiAgICAgICAgICAgIHN3aXRjaCAodi5pbnB1dCkge1xuICAgICAgICAgICAgICBjYXNlIFwiaG91clwiOlxuICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWUuc3BsaXQoXCI6XCIpO1xuICAgICAgICAgICAgICAgIGxldCBoaFZhbHVlID0gdmFsdWVbMF07XG4gICAgICAgICAgICAgICAgbGV0IG1tVmFsdWUgPSB2YWx1ZVsxXTtcbiAgICAgICAgICAgICAgICBleE5hdkxpc3QgKz0gYFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpdGVtLWNvbCBoYXMtaW5wdXRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJob3VyLWlucHV0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwibnVtYmVyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQtdHlwZT1cInRpbWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXg9XCIyM1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbj1cIjBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1rZXk9XCIke3Yua2V5IHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS1pZD1cIiR7ZC5pZCB8fCAtMX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlLW5vZGU9XCIke2QudHlwZSB8fCBcIlwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPVwiJHtoaFZhbHVlfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7aXNEaXNhYmxlZCA/IFwiZGlzYWJsZWRcIiA6IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiaGhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4+Ojwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC10eXBlPVwidGltZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heD1cIjU5XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluPVwiMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LWtleT1cIiR7di5rZXkgfHwgXCJcIn1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLWlkPVwiJHtkLmlkIHx8IC0xfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUtbm9kZT1cIiR7ZC50eXBlIHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9XCIke21tVmFsdWV9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHtpc0Rpc2FibGVkID8gXCJkaXNhYmxlZFwiIDogXCJcIn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJtbVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgY2FzZSBcInRleHRcIjpcbiAgICAgICAgICAgICAgY2FzZSBcIm51bWJlclwiOlxuICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGV4TmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tY29sIGhhcy1pbnB1dFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCIke3YuaW5wdXQgfHwgXCJ0ZXh0XCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQtdHlwZT1cIiR7di5pbnB1dCB8fCBcInRleHRcIn1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1rZXk9XCIke3Yua2V5IHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS1pZD1cIiR7ZC5pZCB8fCAtMX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlLW5vZGU9XCIke2QudHlwZSB8fCBcIlwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7aXNEaXNhYmxlZCA/IFwiZGlzYWJsZWRcIiA6IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPVwiJHt2YWx1ZX1cIi8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZXhOYXZMaXN0ICs9IGBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tY29sXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHt2YWx1ZX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBleE5hdkxpc3QgKz0gYFxuICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcblxuICAgICAgaWYgKGQuY2hpbGRyZW4pIHtcbiAgICAgICAgZC5jaGlsZHJlbi5mb3JFYWNoKChjKSA9PiB7XG4gICAgICAgICAgaWYgKGMuaXNIaWRkZW4pIHJldHVybjtcbiAgICAgICAgICBleE5hdkxpc3QgKz0gYDxkaXYgY2xhc3M9XCJjaGlsZC1leC1uYXYtaXRlbSAke1xuICAgICAgICAgICAgZC5pc0Nsb3NlZCA/IFwiaGlkZVwiIDogXCJcIlxuICAgICAgICAgIH1cIiBjaGlsZD1cIiR7ZC5pZCB8fCAtMX1cIj5gO1xuXG4gICAgICAgICAgaWYoYy53aXRoTmF2ICE9PSBmYWxzZSl7XG4gICAgICAgICAgICBjb25maWcudGltZWxpbmUubmF2LmxlZnQuZXh0ZW5kLnZhcnMuZm9yRWFjaCgodikgPT4ge1xuICAgICAgICAgICAgICBpZiAodi5vbmx5VGFiICYmIHRhYiAmJiB2Lm9ubHlUYWIgIT09IHRhYi5rZXkpIHJldHVybjtcblxuICAgICAgICAgICAgICBsZXQgdmFsdWUgPSB1dGlscy5nZXRWYXJCeVBhdGgoYy52YWx1ZXMsIHYudmFyTmFtZSlcbiAgICAgICAgICAgICAgaWYgKHYucm91bmQgJiYgIWlzTmFOKHZhbHVlKSkge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gdXRpbHMucm91bmQodmFsdWUsIHYucm91bmQpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKHYuaW5wdXQpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHYuaW5wdXQpIHtcbiAgICAgICAgICAgICAgICAgIGNhc2UgXCJob3VyXCI6XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWUgPyB2YWx1ZS5zcGxpdChcIjpcIikgOiBbMCwgMF07XG4gICAgICAgICAgICAgICAgICAgIGxldCBoaFZhbHVlID0gdmFsdWVbMF07XG4gICAgICAgICAgICAgICAgICAgIGxldCBtbVZhbHVlID0gdmFsdWVbMV07XG4gICAgICAgICAgICAgICAgICAgIGV4TmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tY29sIGhhcy1pbnB1dFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImhvdXItaW5wdXRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC10eXBlPVwidGltZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heD1cIjIzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluPVwiMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LWtleT1cIiR7di5rZXkgfHwgXCJcIn1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLWlkPVwiJHtjLmlkIHx8IC0xfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUtbm9kZT1cIiR7Yy50eXBlIHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9XCIke2hoVmFsdWV9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHtpc0Rpc2FibGVkID8gXCJkaXNhYmxlZFwiIDogXCJcIn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJoaFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3Bhbj46PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cIm51bWJlclwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LXR5cGU9XCJ0aW1lXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4PVwiNTlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW49XCIwXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQta2V5PVwiJHt2LmtleSB8fCBcIlwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW0taWQ9XCIke2MuaWQgfHwgLTF9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZS1ub2RlPVwiJHtjLnR5cGUgfHwgXCJcIn1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZT1cIiR7bW1WYWx1ZX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAke2lzRGlzYWJsZWQgPyBcImRpc2FibGVkXCIgOiBcIlwifVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cIm1tXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgIGNhc2UgXCJ0ZXh0XCI6XG4gICAgICAgICAgICAgICAgICBjYXNlIFwibnVtYmVyXCI6XG4gICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBleE5hdkxpc3QgKz0gYFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpdGVtLWNvbCBoYXMtaW5wdXRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCAgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCIke3YuaW5wdXQgfHwgXCJ0ZXh0XCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQtdHlwZT1cIiR7di5pbnB1dCB8fCBcInRleHRcIn1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1rZXk9XCIke3Yua2V5IHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS1pZD1cIiR7Yy5pZCB8fCAtMX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlLW5vZGU9XCIke2MudHlwZSB8fCBcIlwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7aXNEaXNhYmxlZCA/IFwiZGlzYWJsZWRcIiA6IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPVwiJHt2YWx1ZX1cIi8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZXhOYXZMaXN0ICs9IGBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tY29sXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHt2YWx1ZX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGV4TmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIC8vYnV0dG9uc1xuICAgICAgYnRuTmF2TGlzdCArPSBgPGRpdiBjbGFzcz1cImNhcC1idG4tbmF2LWl0ZW0gcGFyZW50XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY2FwLWJ0bi1uYXYtaXRlbS1jb250ZW50XCI+YDtcbiAgICAgIGlmIChcbiAgICAgICAgY29uZmlnLnRpbWVsaW5lLm5hdi5sZWZ0LmJ1dHRvbnMgJiZcbiAgICAgICAgY29uZmlnLnRpbWVsaW5lLm5hdi5sZWZ0LmJ1dHRvbnMudmFyc1xuICAgICAgKSB7XG4gICAgICAgIGNvbmZpZy50aW1lbGluZS5uYXYubGVmdC5idXR0b25zLnZhcnMuZm9yRWFjaCgoYnRuKSA9PiB7XG4gICAgICAgICAgaWYgKGQud2l0aEJ0bk5hdikge1xuICAgICAgICAgICAgbGV0IGJ0bkNvbnRlbnQgPSBcIlwiO1xuICAgICAgICAgICAgbGV0IGNsYXNzTmFtZSA9IGJ0bi5jbGFzc05hbWUgfHwgXCJcIjtcblxuICAgICAgICAgICAgaWYgKGJ0bi5pY29uKSB7XG4gICAgICAgICAgICAgIGJ0bkNvbnRlbnQgPSBidG4uaWNvbiA/IGJ0bi5pY29uIDogXCJcIjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGJ0bi5pY29uRm9ybWF0dGVyKSB7XG4gICAgICAgICAgICAgIGJ0bkNvbnRlbnQgPSBidG4uaWNvbkZvcm1hdHRlciA/IGJ0bi5pY29uRm9ybWF0dGVyKGQsIGJ0bikgOiBcIlwiO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoYnRuLnNoYXBlKSB7XG4gICAgICAgICAgICAgIGNsYXNzTmFtZSArPSBcIiBjYXAtYnRuLVwiICsgYnRuLnNoYXBlO1xuICAgICAgICAgICAgICBidG5Db250ZW50ICs9IGA8c3Bhbj4gJHtcbiAgICAgICAgICAgICAgICBidG4uZm9ybWF0dGVyID8gYnRuLmZvcm1hdHRlcihkLCBidG4pIDogXCJcIlxuICAgICAgICAgICAgICB9IDwvc3Bhbj4gYDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChidG4uYnRuQ2xhc3NOYW1lRm9ybWF0dGVyKSB7XG4gICAgICAgICAgICAgIGxldCBuZXdDbGFzc05hbWUgPSBidG4uYnRuQ2xhc3NOYW1lRm9ybWF0dGVyKGQsIGJ0bik7XG4gICAgICAgICAgICAgIGlmIChuZXdDbGFzc05hbWUpIHtcbiAgICAgICAgICAgICAgICBjbGFzc05hbWUgKz0gXCIgXCIgKyBuZXdDbGFzc05hbWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYnRuTmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJjYXAtYnRuLXNoYXBlICR7Y2xhc3NOYW1lfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQta2V5PVwiJHtidG4ua2V5IHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLWlkPVwiJHtkLmlkIHx8IC0xfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHtpc0Rpc2FibGVkID8gXCJkaXNhYmxlZFwiIDogXCJcIn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlLW5vZGU9XCIke2QudHlwZSB8fCBcIlwifVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7YnRuQ29udGVudH1cbiAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+YDtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgYnRuTmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PmA7XG5cbiAgICAgIGlmIChkLmNoaWxkcmVuKSB7XG4gICAgICAgIGQuY2hpbGRyZW4uZm9yRWFjaCgoYykgPT4ge1xuICAgICAgICAgIGlmIChjLmlzSGlkZGVuKSByZXR1cm47XG5cbiAgICAgICAgICAvL2J1dHRvbnNcbiAgICAgICAgICBidG5OYXZMaXN0ICs9IGA8ZGl2IGNsYXNzPVwiY2FwLWJ0bi1jaGlsZC1uYXYtaXRlbSBwYXJlbnQgJHtcbiAgICAgICAgICAgIGQuaXNDbG9zZWQgPyBcImhpZGVcIiA6IFwiXCJcbiAgICAgICAgICB9XCIgY2hpbGQ9XCIke2QuaWQgfHwgLTF9XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNhcC1idG4tbmF2LWl0ZW0tY29udGVudFwiPmA7XG5cbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBjb25maWcudGltZWxpbmUubmF2LmxlZnQuYnV0dG9ucyAmJlxuICAgICAgICAgICAgY29uZmlnLnRpbWVsaW5lLm5hdi5sZWZ0LmJ1dHRvbnMudmFyc1xuICAgICAgICAgICkge1xuICAgICAgICAgICAgY29uZmlnLnRpbWVsaW5lLm5hdi5sZWZ0LmJ1dHRvbnMudmFycy5mb3JFYWNoKChidG4pID0+IHtcbiAgICAgICAgICAgICAgaWYoYy53aXRoTmF2ICE9PSBmYWxzZSl7XG4gICAgICAgICAgICAgICAgbGV0IGJ0bkNvbnRlbnQgPSBcIlwiO1xuICAgICAgICAgICAgICAgIGxldCBjbGFzc05hbWUgPSBidG4uY2xhc3NOYW1lIHx8IFwiXCI7XG5cbiAgICAgICAgICAgICAgICBpZiAoYnRuLmljb24pIHtcbiAgICAgICAgICAgICAgICAgIGJ0bkNvbnRlbnQgPSBidG4uaWNvbiA/IGJ0bi5pY29uIDogXCJcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYnRuLmljb25Gb3JtYXR0ZXIpIHtcbiAgICAgICAgICAgICAgICAgIGJ0bkNvbnRlbnQgPSBidG4uaWNvbkZvcm1hdHRlciA/IGJ0bi5pY29uRm9ybWF0dGVyKGMsIGJ0bikgOiBcIlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChidG4uc2hhcGUpIHtcbiAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZSArPSBcIiBjYXAtYnRuLVwiICsgYnRuLnNoYXBlO1xuICAgICAgICAgICAgICAgICAgYnRuQ29udGVudCArPSBgPHNwYW4+ICR7XG4gICAgICAgICAgICAgICAgICAgIGJ0bi5mb3JtYXR0ZXIgPyBidG4uZm9ybWF0dGVyKGMsIGJ0bikgOiBcIlwiXG4gICAgICAgICAgICAgICAgICB9IDwvc3Bhbj4gYDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGJ0bi5idG5DbGFzc05hbWVGb3JtYXR0ZXIpIHtcbiAgICAgICAgICAgICAgICAgIGxldCBuZXdDbGFzc05hbWUgPSBidG4uYnRuQ2xhc3NOYW1lRm9ybWF0dGVyKGMsIGJ0bik7XG4gICAgICAgICAgICAgICAgICBpZiAobmV3Q2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZSArPSBcIiBcIiArIG5ld0NsYXNzTmFtZTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBidG5OYXZMaXN0ICs9IGBcbiAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiY2FwLWJ0bi1zaGFwZSAke2NsYXNzTmFtZX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQta2V5PVwiJHtidG4ua2V5IHx8IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW0taWQ9XCIke2MuaWQgfHwgLTF9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7aXNEaXNhYmxlZCA/IFwiZGlzYWJsZWRcIiA6IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlLW5vZGU9XCIke2MudHlwZSB8fCBcIlwifVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHtidG5Db250ZW50fVxuICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPmA7XG5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYnRuTmF2TGlzdCArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBsZXQgaXRlbURldGFpbCA9IGAgPGRpdiBjbGFzcz1cImRldGFpbC1uYXYtaXRlbSBoaWRlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICR7dGhpcy5nZXREZXRhaWxOYXZJdGVtQ29udGVudCgpfVxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcblxuICAgIGxldCBzdHIgPSBgPGRpdiBjbGFzcz1cIm5hdi1jb250YWluZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAke2l0ZW1EZXRhaWx9XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJuYXYtaXRlbS1saXN0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgJHtuYXZMaXN0fVxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImluaXRpYWwtbmF2LWxpc3RcIj5cbiAgICAgICAgICAgICAgICAgICAgICAke2luaXRpYWxOYXZMaXN0fVxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImV4dGVuZC1uYXYtbGlzdFwiPlxuICAgICAgICAgICAgICAgICAgICAgICR7ZXhOYXZMaXN0fVxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNhcC1idG4tbmF2LWxpc3RcIj5cbiAgICAgICAgICAgICAgICAgICAgICAke2J0bk5hdkxpc3R9XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcblxuICAgIGxldCBuYXZDb250YWluZXIgPSBkb20uY3JlYXRlRWxlbWVudEZyb21IVE1MKHN0cik7XG4gICAgJGVsZW0uaW5uZXJIVE1MID0gXCJcIjtcbiAgICAkZWxlbS5hcHBlbmQobmF2Q29udGFpbmVyKTtcblxuICAgIC8vZGV0YWxsZSBkZSBuYXYtaXRlbVxuICAgICRlbGVtLnF1ZXJ5U2VsZWN0b3JBbGwoXCIuaXRlbS10aXRsZS5ob3ZlcmFibGVcIikuZm9yRWFjaCgoaSkgPT4ge1xuICAgICAgaS5hZGRFdmVudExpc3RlbmVyKFwibW91c2VvdmVyXCIsIChlKSA9PiB7XG4gICAgICAgIGxldCBwb3MgPSB1dGlscy5ldmVudFRvUG9zaXRpb25OYXZMZWZ0KGNvbmZpZywgZSwgJGVsZW0pO1xuICAgICAgICBsZXQgaXRlbUlkID0gaS5nZXRBdHRyaWJ1dGUoXCJpdGVtLWlkXCIpO1xuICAgICAgICBsZXQgaXRlbSA9IHV0aWxzLmdldEl0ZW1CeUlkKGNvbmZpZywgaXRlbUlkKTtcbiAgICAgICAgbGV0IHR5cGVOb2RlID0gaS5nZXRBdHRyaWJ1dGUoXCJ0eXBlLW5vZGVcIik7XG4gICAgICAgIGkuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICBuZXcgQ3VzdG9tRXZlbnQoXCJvdmVyTmF2SXRlbVwiLCB7XG4gICAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICAgICAgICBkZXRhaWw6IHtcbiAgICAgICAgICAgICAgb3JpZ2luYWxFdnQ6IGUsXG4gICAgICAgICAgICAgIGl0ZW06IGl0ZW0sXG4gICAgICAgICAgICAgIHR5cGU6IHR5cGVOb2RlLFxuICAgICAgICAgICAgICBwb3M6IHBvcyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLy9vY3VsdGEgZGV0YWxsZSBkZSBuYXYtaXRlbSwgYWwgc2FsaXIgZGVsIG5hdi1pdGVtLWxpc3RcbiAgICAkZWxlbS5xdWVyeVNlbGVjdG9yQWxsKFwiLm5hdi1pdGVtLWxpc3RcIikuZm9yRWFjaCgoaSkgPT4ge1xuICAgICAgaS5hZGRFdmVudExpc3RlbmVyKFwibW91c2VsZWF2ZVwiLCAoZSkgPT4ge1xuICAgICAgICBpLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwibGVhdmVOYXZJdGVtXCIsIHtcbiAgICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvL29jdWx0YSBkZXRhbGxlIGRlIG5hdi1pdGVtLWxpc3QsIGFsIHNhbGlyIGRlIG5hdi1pdGVtXG4gICAgJGVsZW0ucXVlcnlTZWxlY3RvckFsbChcIi5pdGVtLXRpdGxlOm5vdCguaG92ZXJhYmxlKVwiKS5mb3JFYWNoKChpKSA9PiB7XG4gICAgICBpLmFkZEV2ZW50TGlzdGVuZXIoXCJtb3VzZW1vdmVcIiwgKGUpID0+IHtcbiAgICAgICAgaS5kaXNwYXRjaEV2ZW50KFxuICAgICAgICAgIG5ldyBDdXN0b21FdmVudChcImxlYXZlTmF2SXRlbVwiLCB7XG4gICAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgJGVsZW0ucXVlcnlTZWxlY3RvckFsbChcIi5pdGVtLXRpdGxlLmNsaWNrZWFibGVcIikuZm9yRWFjaCgoaSkgPT4ge1xuICAgICAgaS5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGUpID0+IHtcbiAgICAgICAgbGV0IGl0ZW1JZCA9IGkuZ2V0QXR0cmlidXRlKFwiaXRlbS1pZFwiKTtcbiAgICAgICAgbGV0IHR5cGVOb2RlID0gaS5nZXRBdHRyaWJ1dGUoXCJ0eXBlLW5vZGVcIik7XG4gICAgICAgIGxldCB2YWx1ZSA9IGkudmFsdWU7XG4gICAgICAgIGkuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICBuZXcgQ3VzdG9tRXZlbnQoXCJjbGlja05hdkxlZnRJdGVtXCIsIHtcbiAgICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIGRldGFpbDoge1xuICAgICAgICAgICAgICBpdGVtSWQ6IGl0ZW1JZCxcbiAgICAgICAgICAgICAgdHlwZTogdHlwZU5vZGUsXG4gICAgICAgICAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgJGVsZW0ucXVlcnlTZWxlY3RvckFsbChcImlucHV0XCIpLmZvckVhY2goKGkpID0+IHtcbiAgICAgIGkuYWRkRXZlbnRMaXN0ZW5lcihcImNoYW5nZVwiLCAoZSkgPT4ge1xuICAgICAgICBsZXQgaW5wdXRUeXBlID0gaS5nZXRBdHRyaWJ1dGUoXCJpbnB1dC10eXBlXCIpO1xuICAgICAgICBsZXQga2V5ID0gaS5nZXRBdHRyaWJ1dGUoXCJpbnB1dC1rZXlcIik7XG4gICAgICAgIGxldCBpdGVtSWQgPSBpLmdldEF0dHJpYnV0ZShcIml0ZW0taWRcIik7XG4gICAgICAgIGxldCB0eXBlTm9kZSA9IGkuZ2V0QXR0cmlidXRlKFwidHlwZS1ub2RlXCIpO1xuICAgICAgICBsZXQgaXRlbSA9IHV0aWxzLmdldEl0ZW1CeUlkKGNvbmZpZywgaXRlbUlkKTtcbiAgICAgICAgbGV0IHZhbHVlID0gaS52YWx1ZTtcbiAgICAgICAgaWYgKGlucHV0VHlwZSA9PSBcInRpbWVcIikge1xuICAgICAgICAgIGxldCBoaF9pbnB1dCA9IGkucGFyZW50RWxlbWVudC5xdWVyeVNlbGVjdG9yKFwiaW5wdXQuaGhcIikudmFsdWU7XG4gICAgICAgICAgbGV0IG1tX2lucHV0ID0gaS5wYXJlbnRFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoXCJpbnB1dC5tbVwiKS52YWx1ZTtcbiAgICAgICAgICBtbV9pbnB1dCA9IG1tX2lucHV0IDwgMTAgPyBcIjBcIiArIHBhcnNlRmxvYXQobW1faW5wdXQpIDogbW1faW5wdXQ7XG4gICAgICAgICAgaS5wYXJlbnRFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoXCJpbnB1dC5tbVwiKS52YWx1ZSA9IG1tX2lucHV0O1xuICAgICAgICAgIHZhbHVlID0gaGhfaW5wdXQgKyBcIjpcIiArIG1tX2lucHV0O1xuICAgICAgICB9XG4gICAgICAgIGkuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICBuZXcgQ3VzdG9tRXZlbnQoXCJzYXZlTmF2TGVmdElucHV0XCIsIHtcbiAgICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIGRldGFpbDoge1xuICAgICAgICAgICAgICBrZXk6IGtleSxcbiAgICAgICAgICAgICAgaXRlbUlkOiBpdGVtSWQsXG4gICAgICAgICAgICAgIGl0ZW06IGl0ZW0sXG4gICAgICAgICAgICAgIHR5cGU6IHR5cGVOb2RlLFxuICAgICAgICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICAgICAgICAgIHRhYlNlbGVjdGVkOiB0YWIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgICRlbGVtLnF1ZXJ5U2VsZWN0b3JBbGwoXCJidXR0b24uY2FwLWJ0bi1zaGFwZVwiKS5mb3JFYWNoKChpKSA9PiB7XG4gICAgICBpLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCAoZSkgPT4ge1xuICAgICAgICBsZXQga2V5ID0gaS5nZXRBdHRyaWJ1dGUoXCJpbnB1dC1rZXlcIik7XG4gICAgICAgIGxldCBpdGVtSWQgPSBpLmdldEF0dHJpYnV0ZShcIml0ZW0taWRcIik7XG4gICAgICAgIGxldCB0eXBlTm9kZSA9IGkuZ2V0QXR0cmlidXRlKFwidHlwZS1ub2RlXCIpO1xuICAgICAgICBpLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwiY2xpY2tOYXZMZWZ0QnV0dG9uXCIsIHtcbiAgICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIGRldGFpbDoge1xuICAgICAgICAgICAgICBrZXk6IGtleSxcbiAgICAgICAgICAgICAgaXRlbUlkOiBpdGVtSWQsXG4gICAgICAgICAgICAgIHR5cGU6IHR5cGVOb2RlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAkZWxlbS5xdWVyeVNlbGVjdG9yQWxsKFwiYnV0dG9uLnRyZWUtaWNvblwiKS5mb3JFYWNoKChpKSA9PiB7XG4gICAgICBpLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCAoZSkgPT4ge1xuICAgICAgICBsZXQgaXRlbUlkID0gaS5nZXRBdHRyaWJ1dGUoXCJpdGVtLWlkXCIpO1xuICAgICAgICBsZXQgdHlwZU5vZGUgPSBpLmdldEF0dHJpYnV0ZShcInR5cGUtbm9kZVwiKTtcbiAgICAgICAgbGV0IGRhdGFDb25maWcgPSBjb25maWcuZGF0YS5maW5kKChkKSA9PiBkLmlkID09IGl0ZW1JZCk7XG5cbiAgICAgICAgbGV0ICRuYXZJdGVtID0gZS5jdXJyZW50VGFyZ2V0LmNsb3Nlc3QoXCIubmF2LWl0ZW1cIik7XG4gICAgICAgIGxldCAkY2hpbGRyZW4gPSAkbmF2SXRlbS5xdWVyeVNlbGVjdG9yKFwiLmNoaWxkcmVuLWl0ZW1zXCIpO1xuICAgICAgICBsZXQgaXRlbXNUb0hpZGUgPSBlLmN1cnJlbnRUYXJnZXRcbiAgICAgICAgICAuY2xvc2VzdChcIm5hdi5sZWZ0XCIpXG4gICAgICAgICAgLnF1ZXJ5U2VsZWN0b3JBbGwoXG4gICAgICAgICAgICBcIltjaGlsZD0nXCIgKyBpdGVtSWQgKyBcIiddLCBbY2hpbGQtbGlzdD0nXCIgKyBpdGVtSWQgKyBcIiddXCJcbiAgICAgICAgICApO1xuXG4gICAgICAgIGlmICgkY2hpbGRyZW4pIHtcbiAgICAgICAgICBpZiAoJGNoaWxkcmVuLmNsYXNzTGlzdC5jb250YWlucyhcImhpZGVcIikpIHtcbiAgICAgICAgICAgIGUuY3VycmVudFRhcmdldC5jbGFzc0xpc3QuYWRkKFwiY2FwLXJvdGF0ZVwiKTtcbiAgICAgICAgICAgIGl0ZW1zVG9IaWRlLmZvckVhY2goKGkpID0+IGkuY2xhc3NMaXN0LnJlbW92ZShcImhpZGVcIikpO1xuICAgICAgICAgICAgZGF0YUNvbmZpZy5pc0Nsb3NlZCA9IGZhbHNlO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlLmN1cnJlbnRUYXJnZXQuY2xhc3NMaXN0LnJlbW92ZShcImNhcC1yb3RhdGVcIik7XG4gICAgICAgICAgICBpdGVtc1RvSGlkZS5mb3JFYWNoKChpKSA9PiBpLmNsYXNzTGlzdC5hZGQoXCJoaWRlXCIpKTtcbiAgICAgICAgICAgIGRhdGFDb25maWcuaXNDbG9zZWQgPSB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGkuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICBuZXcgQ3VzdG9tRXZlbnQoXCJjbGlja05hdkxlZnRUcmVlSWNvblwiLCB7XG4gICAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICAgICAgICBkZXRhaWw6IHtcbiAgICAgICAgICAgICAgaXRlbUlkOiBpdGVtSWQsXG4gICAgICAgICAgICAgIHR5cGU6IHR5cGVOb2RlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuXG4gICAgICAgIC8vZS5jdXJyZW50VGFyZ2V0LnBhcmVudFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gJGVsZW07XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWEgSHRtbCBjb21vIFN0cmluZywgcGFyYSBlbCBkZXRhbGxlIGRlIGl0ZW1zIGVuIGVsIFNpZGViYXIgSXpxdWllcmRvXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbaXRlbT17fV0gLSBDb25maWd1cmFjaW9uIGRlIGl0ZW1cbiAgICogQHJldHVybiB7U3RyaW5nfSBIdG1sIGRlIHZlbnRhbmEgZGUgZGV0YWxsZVxuICAgKi9cbiAgZ2V0RGV0YWlsTmF2SXRlbUNvbnRlbnQoaXRlbSA9IHt9KSB7XG4gICAgaWYgKGl0ZW0ubmF2T3ZlciA9PSB1bmRlZmluZWQpIGl0ZW0ubmF2T3ZlciA9IHt9O1xuXG4gICAgcmV0dXJuIGBcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImhlYWRlci1kZXRhaWxcIj5cbiAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGV0YWlsLXRpdGxlIHRydW5jYXRlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAke2l0ZW0ubGFiZWwgfHwgXCJcIn1cbiAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGV0YWlsLXN1YnRpdGxlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAke2l0ZW0ubmF2T3Zlci5zdWJ0aXRsZSB8fCBcIlwifVxuICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJoZWFkZXItY2hpcCAke1xuICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS5saWdodCA/IGl0ZW0ubGlnaHQgKyBcIi1saWdodFwiIDogXCJcIlxuICAgICAgICAgICAgICAgICAgICAgIH0gICR7aXRlbS5uYXZPdmVyLmNoaXAgPyBcIlwiIDogXCJoaWRlXCJ9XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAke2l0ZW0ubmF2T3Zlci5jaGlwIHx8IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkZXRhaWwtY29udGFpbmVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgJHtpdGVtLm5hdk92ZXIuY29udGVudCB8fCBcIlwifVxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICB9LFxuXG4gIC8qKlxuICAgKiBDcmVhIFNpZGViYXIgRGVyZWNob1xuICAgKiBVc2FkbyBwcmluY2lwYWxtZW50ZSBwYXJhIGZvcm11bGFyaW8gZGUgaW5ncmVzbyBkZSBkYXRvcyBwYXJhIGxvcyBkaWFzXG4gICAqIHNlbGVjY2lvbmFkb3NcbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIENvbmZpZ3VyYWNpb24gY2FwaWJhcmFcbiAgICogQHBhcmFtIHtPYmplY3R9IHRhYiAtIFRhYiBkZSByZWZlcmVuY2lhLCBwYXJhIGxhIGNyZWFjaW9uIGRlbCBmb3JtdWxhcmlvXG4gICAqIEByZXR1cm4ge09iamVjdH0ge2VsZW1lbnQsIGlucHV0c30sIGVsZW1lbnQgZXMgZWwgZWxlbWVudG8gRG9tIGRlbCBzaWRlYmFyLFxuICAgKiAgICAgICAgICAgICAgICAgIGlucHV0cyBlcyB1biBhcnJheSBkZSBlbGVtZW50b3MgRG9tIGRlIGNhZGEgaW5wdXQgY3JlYWRvXG4gICAqICAgICAgICAgICAgICAgICAgKG5vIHNvbiBlbGVtZW50b3MgaHRtbCBkZSB0aXBvIGlucHV0KVxuICAgKi9cbiAgY3JlYXRlTmF2UmlnaHQoY29uZmlnLCB0YWIgPSBudWxsKSB7XG4gICAgdmFyICRlbGVtID0gZG9tLmNyZWF0ZUVsZW1lbnQoXCJuYXZcIiwgeyBjbGFzc05hbWU6IFwicmlnaHRcIiB9KTtcbiAgICByZXR1cm4gdGhpcy5yZWRyYXdOYXZSaWdodChjb25maWcsICRlbGVtLCB0YWIsIFtdKTtcbiAgfSxcblxuICAvKipcbiAgICogUmVjcmVhIFNpZGViYXIgRGVyZWNob1xuICAgKiBVdGlsaXphICRlbGVtIGNvbW8gZWxlbWVudG8gZG9tIGRvbmRlIHJlY3JlYXJsb1xuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcGFyYW0ge09iamVjdH0gJGVsZW0gLSBFbGVtZW50byBEb20gZG9uZGUgY3JlYSBlbCBzaWRlYmFyIGRlcmVjaG9cbiAgICogQHBhcmFtIHtPYmplY3R9IHRhYiAtIFRhYiBkZSByZWZlcmVuY2lhLCBwYXJhIGxhIGNyZWFjaW9uIGRlbCBmb3JtdWxhcmlvXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhRGF5IC0gZGF0b3MgZGVsIGRpYSBzZWxlY2Npb25hbmRvLCBwYXJhIGF1dG9ycmVsbGVubyBkZSBmb3JtdWxhcmlvXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXlTZWxlY3RlZCAtIGRhdG9zIGRlbCBkaWEgc2VsZWNjaW9uYWRvXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBkYXlTZWxlY3RlZC5kYXRlIC0gZmVjaGEgZGVsIGRpYSBzZWxlY2Npb25hZG9cbiAgICogQHBhcmFtIHtPYmplY3R9IGRheVNlbGVjdGVkLml0ZW0gLSBJdGVtIGRlIFNpZGViYXIgcmVsYWNpb25hZG8gYWwgZGlhIHNlbGVjY2lvbmFkb1xuICAgKiBAcGFyYW0ge09iamVjdH0gZGF5U2VsZWN0ZWQucG9zIC0gcG9zaWNpb24gZGUgZGlhIHNlbGVjY2lvbmFkb1xuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBTaWRlYmFyIERlcmVjaG9cbiAgICovXG4gIHJlZHJhd05hdlJpZ2h0KFxuICAgIGNvbmZpZyxcbiAgICAkZWxlbSxcbiAgICBzZWxlY3RlZCA9IG51bGwsXG4gICAgdGFiID0gbnVsbCxcbiAgICBkYXRhRGF5ID0gbnVsbCxcbiAgICBkYXlTZWxlY3RlZCA9IG51bGxcbiAgKSB7XG4gICAgbGV0ICRuYXZSaWdodCA9ICRlbGVtOyAvL2RvbS5jcmVhdGVFbGVtZW50KFwibmF2XCIse2NsYXNzTmFtZTpcInJpZ2h0XCJ9KTtcbiAgICBsZXQgJGRpdkNvbnRhaW5lciA9IGRvbS5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtcbiAgICAgIGNsYXNzTmFtZTogXCJuYXYtaW5wdXQtY29udGFpbmVyXCIsXG4gICAgfSk7XG4gICAgbGV0ICRpbnB1dHMgPSBbXTtcbiAgICBsZXQgY2hlY2tib3hJbnB1dHMgPSBbXTtcbiAgICBsZXQgaW5wdXRzV2l0aFJlbG9hZCA9IFtdO1xuICAgIGxldCB0YWJTZWxlY3RlZCA9IHRhYjtcbiAgICBzZWxlY3RlZCA9IHNlbGVjdGVkIHx8IFtkYXlTZWxlY3RlZF07XG5cbiAgICBpZiAodGFiU2VsZWN0ZWQgJiYgdGFiU2VsZWN0ZWQuaW5wdXRzKSB7XG4gICAgICB0YWJTZWxlY3RlZC5pbnB1dHMuZm9yRWFjaCgoaSkgPT4ge1xuICAgICAgICBpZiAoaS5kaXNhYmxlZCkgcmV0dXJuO1xuXG4gICAgICAgIGxldCAkaW5wdXQgPSB0aGlzLmNyZWF0ZUlucHV0KGksIGRhdGFEYXksIGRheVNlbGVjdGVkLCBzZWxlY3RlZCk7XG4gICAgICAgIGlmICgkaW5wdXQpIHtcbiAgICAgICAgICAkZGl2Q29udGFpbmVyLmFwcGVuZENoaWxkKCRpbnB1dCk7XG4gICAgICAgICAgJGlucHV0cy5wdXNoKCRpbnB1dCk7XG5cbiAgICAgICAgICBpZiAoaS50eXBlID09IFwiY2hlY2tib3hcIikge1xuICAgICAgICAgICAgY2hlY2tib3hJbnB1dHMucHVzaCgkaW5wdXQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChpLnJlbG9hZE9uU2VsZWN0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIGlucHV0c1dpdGhSZWxvYWQucHVzaCh7ICRpbnB1dCwgY29uZmlnOiBpIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy9tYW5lam8gZGUgZXZlbnRvcyBwYXJhIGlucHV0cyBjb24gc2hvd0lmXG4gICAgaWYgKGNoZWNrYm94SW5wdXRzKSB7XG4gICAgICBjaGVja2JveElucHV0cy5mb3JFYWNoKCgkYykgPT4ge1xuICAgICAgICAvL29idGllbmUga2V5IGRlIGNoZWNrYm94XG4gICAgICAgIGxldCBrZXkgPSAkYy5nZXRBdHRyaWJ1dGUoXCJpbnB1dC1rZXlcIik7XG4gICAgICAgIGxldCBwcm9wcyA9IHRhYlNlbGVjdGVkLmlucHV0cy5maW5kKChpKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGkua2V5ID09IGtleTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgbGV0IGlzQ2hlY2tlZCA9IGZhbHNlO1xuICAgICAgICBpZiAoZGF0YURheSkge1xuICAgICAgICAgIGlzQ2hlY2tlZCA9IHV0aWxzLmdldFZhckJ5UGF0aChkYXRhRGF5LCBwcm9wcy52YXJOYW1lKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vb2J0aWVuZSBpbnB1dHMgcmVsYWNpb25hZG9zIGRlc2RlIGNvbmZpZyBwYXJhIG1vc3RyYXIvb2N1bHRhclxuICAgICAgICBsZXQgaW5wdXRzVG9IaWRlID0gdGFiU2VsZWN0ZWQuaW5wdXRzLmZpbHRlcigoaSkgPT4ge1xuICAgICAgICAgIHJldHVybiBpLnNob3dJZiAmJiBpLnNob3dJZiA9PSBrZXk7XG4gICAgICAgIH0pO1xuICAgICAgICBsZXQgaW5wdXRzVG9IaWRlS2V5cyA9IGlucHV0c1RvSGlkZS5tYXAoKGkpID0+IGkua2V5KTtcblxuICAgICAgICAvL29idGllbmUgaW5wdXRzIGRlbCBkb20sIGZpbHRyYW5kbyBjb24gaW5wdXRzVG9IaWRlXG4gICAgICAgIGxldCAkaW5wdXRzSGlkZGVuID0gJGlucHV0cy5maWx0ZXIoKCRpKSA9PiB7XG4gICAgICAgICAgbGV0IGlucHV0S2V5ID0gJGkuZ2V0QXR0cmlidXRlKFwiaW5wdXQta2V5XCIpO1xuICAgICAgICAgIHJldHVybiBpbnB1dHNUb0hpZGVLZXlzLmluZGV4T2YoaW5wdXRLZXkpID4gLTE7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vc2kgaGF5IGlucHV0cyxcbiAgICAgICAgaWYgKCRpbnB1dHNIaWRkZW4pIHtcbiAgICAgICAgICBpZiAoIWlzQ2hlY2tlZCkge1xuICAgICAgICAgICAgJGlucHV0c0hpZGRlbi5mb3JFYWNoKCgkaSkgPT4ge1xuICAgICAgICAgICAgICAkaS5jbGFzc0xpc3QuYWRkKFwiaGlkZVwiKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICAkYy5hZGRFdmVudExpc3RlbmVyKFwiaW5wdXRcIiwgKGUpID0+IHtcbiAgICAgICAgICAgICRpbnB1dHNIaWRkZW4uZm9yRWFjaCgoJGkpID0+IHtcbiAgICAgICAgICAgICAgbGV0IGZuID0gJGMucXVlcnlTZWxlY3RvcihcImlucHV0W3R5cGU9J2NoZWNrYm94J11cIikuY2hlY2tlZFxuICAgICAgICAgICAgICAgID8gXCJyZW1vdmVcIlxuICAgICAgICAgICAgICAgIDogXCJhZGRcIjtcbiAgICAgICAgICAgICAgJGkuY2xhc3NMaXN0W2ZuXShcImhpZGVcIik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgbGV0IHNhdmVDYW5jZWxCdG5zID0gdGhpcy5jcmVhdGVOYXZSaWdodGJ1dHRvbnMoKTtcbiAgICAkZGl2Q29udGFpbmVyLmFwcGVuZENoaWxkKHNhdmVDYW5jZWxCdG5zKTtcbiAgICAkbmF2UmlnaHQuaW5uZXJIVE1MID0gXCJcIjtcbiAgICAkbmF2UmlnaHQuYXBwZW5kQ2hpbGQoJGRpdkNvbnRhaW5lcik7XG5cbiAgICByZXR1cm4ge1xuICAgICAgZWxlbWVudDogJG5hdlJpZ2h0LFxuICAgICAgaW5wdXRzOiAkaW5wdXRzLFxuICAgICAgaW5wdXRzV2l0aFJlbG9hZCxcbiAgICAgIHNhdmVDYW5jZWxCdG5zXG4gICAgfTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBDb3JuZXIgaW5mZXJpb3IgaXpxdWllcmRvLCBjb21vIHRpdHVsbyBwYXJhIGZvb3RlclxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBDb3JuZXIgRm9vdGVyXG4gICAqL1xuICBjcmVhdGVDb3JuZXJGb290ZXIoY29uZmlnKSB7XG4gICAgaWYgKFxuICAgICAgY29uZmlnLnRpbWVsaW5lLmZvb3RlciA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICBjb25maWcudGltZWxpbmUuZm9vdGVyLmVuYWJsZWQgPT0gZmFsc2VcbiAgICApXG4gICAgICByZXR1cm4gbnVsbDtcbiAgICBsZXQgc3RyID0gXCJcIjtcblxuICAgIGlmIChjb25maWcudGltZWxpbmUuZm9vdGVyKSB7XG4gICAgICBzdHIgKz0gYDxkaXYgY2xhc3M9XCJjb3JuZXItZm9vdGVyXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNvcm5lci10aXRsZVwiPlxuICAgICAgICAgICAgPHNwYW4+XG4gICAgICAgICAgICAgICR7Y29uZmlnLnRpbWVsaW5lLmZvb3Rlci5sYWJlbH1cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+YDtcbiAgICB9XG4gICAgcmV0dXJuIGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoc3RyKTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBGb290ZXIgcGFyYSBwbGFuaWxsYVxuICAgKiBJbmljaWFsbWVudGUgY3JlYWRvIHBhcmEgdG90YWxlc1xuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBDb3JuZXIgRm9vdGVyXG4gICAqL1xuICBjcmVhdGVGb290ZXIoY29uZmlnKSB7XG4gICAgaWYgKFxuICAgICAgY29uZmlnLnRpbWVsaW5lLmZvb3RlciA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICBjb25maWcudGltZWxpbmUuZm9vdGVyLmVuYWJsZWQgPT0gZmFsc2VcbiAgICApXG4gICAgICByZXR1cm4gbnVsbDtcblxuICAgIGxldCBzdHIgPSBgXG4gICAgICAgIDxmb290ZXI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZvb3Rlci1jb250YWluZXJcIj5cbiAgICAgICAgICBgO1xuICAgIGNvbmZpZy50aW1lbGluZS5mb290ZXIuZGF0YS5mb3JFYWNoKChkKSA9PiB7XG4gICAgICBzdHIgKz0gYFxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZm9vdGVyLWl0ZW1cIj4ke2QudmFsdWV9PC9kaXY+XG4gICAgICAgICAgICBgO1xuICAgIH0pO1xuICAgIHN0ciArPSBgXG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZm9vdGVyPlxuICAgICAgICBgO1xuXG4gICAgcmV0dXJuIGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoc3RyKTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBGb290ZXIgcGFyYSBwbGFuaWxsYVxuICAgKiBJbmljaWFsbWVudGUgY3JlYWRvIHBhcmEgdG90YWxlc1xuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcGFyYW0ge09iamVjdFtdfSBzZWxlY3RlZCAtIGFycmF5IGRlIG9iamV0b3MsIGRlIGRpYXMgc2VsZWNjaW9uYWRvc1xuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBDb3JuZXIgRm9vdGVyXG4gICAqL1xuICBjcmVhdGVTZWxlY3RCb2FyZChjb25maWcsIHNlbGVjdGVkKSB7XG4gICAgbGV0ICRlbGVtID0gZG9tLmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IFwic2VsZWN0LWNvbnRhaW5lclwiIH0pO1xuICAgIHJldHVybiB0aGlzLnJlZHJhd1NlbGVjdEJvYXJkKCRlbGVtLCBzZWxlY3RlZCk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWEgbGluZWEgdmVydGljYWwgcGFyYSBmZWNoYSBBY3R1YWxcbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIENvbmZpZ3VyYWNpb24gY2FwaWJhcmFcbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gQ29ybmVyIEZvb3RlclxuICAgKi9cbiAgY3JlYXRlVG9kYXlMaW5lKGNvbmZpZykge1xuICAgIHJldHVybiB0aGlzLnJlZHJhd1RvZGF5TGluZShcbiAgICAgIGNvbmZpZyxcbiAgICAgIGRvbS5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBcInRvZGF5LWxpbmVcIiB9KVxuICAgICk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIFJlY3JlYSBsaW5lYSB2ZXJ0aWNhbCBwYXJhIGZlY2hhIEFjdHVhbFxuICAgKiBzaSBlbCBlbGVtZW50byAkZWxlbSBubyBlcyBlbnZpYWRvLCBzZSBjcmVhIHVuIG51ZXZvIGVsZW1lbnRvXG4gICAqXG4gICAqIFNpIGVsIGRpYSBhY3R1YWwgbm8gZXN0YSBkZW50cm8gZGVsIHJhbmdvIGRlIGZlY2hhcyBkZWwgY29uZmlnLFxuICAgKiBkZXNoYWJpbGl0YSBsYSBsaW5lYSBjb24gbGEgY2xhc2UgY3NzIC5kaXNhYmxlLWxpbmVcbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIENvbmZpZ3VyYWNpb24gY2FwaWJhcmFcbiAgICogQHBhcmFtIHtPYmplY3R9IFskZWxlbT1udWxsXSAtIEVsZW1lbnRvIERvbSBkb25kZSByZWNyZWEgbGEgbGluZWEsIHNpIGVzIG51bGwsIGxhIGNyZWFcbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gQ29ybmVyIEZvb3RlclxuICAgKi9cbiAgcmVkcmF3VG9kYXlMaW5lKGNvbmZpZywgJGVsZW0gPSBudWxsKSB7XG4gICAgbGV0IGVuZFRpbWUgPSBuZXcgRGF0ZShjb25maWcudGltZWxpbmUuZW5kKS5nZXRUaW1lKCk7XG4gICAgbGV0IHRvZGF5VGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgIGxldCB7IGhlaWdodCwgZGF5V2lkdGggfSA9IHV0aWxzLmdldFRhYmxlRGltZW5zaW9ucyhjb25maWcpO1xuXG4gICAgaWYgKCRlbGVtID09IG51bGwpXG4gICAgICAkZWxlbSA9IGRvbS5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBcInRvZGF5LWxpbmVcIiB9KTtcblxuICAgIGlmIChlbmRUaW1lIDwgdG9kYXlUaW1lKSB7XG4gICAgICAkZWxlbS5jbGFzc0xpc3QuYWRkKFwiZGlzYWJsZS1saW5lXCIpO1xuICAgIH0gZWxzZSB7XG4gICAgICAkZWxlbS5jbGFzc0xpc3QucmVtb3ZlKFwiZGlzYWJsZS1saW5lXCIpO1xuICAgIH1cblxuICAgIGxldCBkaWZmRGF5cyA9IE1hdGguZmxvb3IoXG4gICAgICBkYXRlVXRpbHMuZGlmZkRheXMoXG4gICAgICAgIGNvbmZpZy50aW1lbGluZS5zdGFydCxcbiAgICAgICAgZGF0ZVV0aWxzLmZvcm1hdERhdGUobmV3IERhdGUoKSlcbiAgICAgIClcbiAgICApO1xuICAgIGxldCBkaWZmID0gZGlmZkRheXMgKiBkYXlXaWR0aDtcbiAgICBkaWZmICs9IGRheVdpZHRoIC8gMiAtIDI7IC8vIHBhcmEgY2VudHJhciBsaW5lYVxuICAgIE9iamVjdC5hc3NpZ24oJGVsZW0uc3R5bGUsIHtcbiAgICAgIFwibWFyZ2luLWxlZnRcIjogZGlmZiArIFwicHhcIixcbiAgICAgIGhlaWdodDogaGVpZ2h0ICsgXCJweFwiLFxuICAgIH0pO1xuICAgIHJldHVybiAkZWxlbTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBlbGVtZW50byBGbG9hdEJveCwgcXVlIGNvbnRpZW5lIGxvcyBkYXRvcyBxdWUgc2UgbXVlc3RyYSBlbiBsYSB0YWJsYVxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcGFyYW0ge09iamVjdH0gdGFiIC0gVGFiIGRlIHJlZmVyZW5jaWEsIHBhcmEgbW9zdHJhciBkYXRvcyBjb25maWd1cmFkb3MgcG9yIHRhYlxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBDb3JuZXIgRm9vdGVyXG4gICAqL1xuICBjcmVhdGVGbG9hdEJveChjb25maWcsIHRhYikge1xuICAgIGxldCAkY29udGFpbmVyID0gZG9tLmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwge1xuICAgICAgY2xhc3NOYW1lOiBcImZsb2F0LWJveC1jb250YWluZXJcIixcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcy5yZWRyYXdGbG9hdEJveChjb25maWcsIHRhYiwgJGNvbnRhaW5lcik7XG4gIH0sXG5cbiAgLyoqXG4gICAqIFJlY3JlYSBlbGVtZW50byBGbG9hdEJveCwgcXVlIGNvbnRpZW5lIGxvcyBkYXRvcyBxdWUgc2UgbXVlc3RyYSBlbiBsYSB0YWJsYVxuICAgKiBTZSB1c2EgcHJpbmNpcGFsbWVudGUgcGFyYSBtb3N0cmFyIGRhdG9zIGVuIGxhIHRhYmxhIGRlIGxhIHBsYW5pbGxhXG4gICAqIGxvcyBtdWVzdHJhIGRlIG1hbmVyYSBmbG90YW50ZSwgY2FsY3VsYW5kbyBlbCBUb3AgeSBlbCBMZWZ0IHNlZ3VuIGxhIHBvc2Npb25cbiAgICpcbiAgICogU2UgY29uc2lkZXJhbiBsb3MgZWxlbWVudG9zIHBhZHJlcyBvY3VsdG9zLCBwYXJhIG9jdWx0YXIgbG9zIGRhdG9zXG4gICAqXG4gICAqIFNlIGluc2VydGFuIGxvcyBlbGVtZW50b3MgRmxvYXRCb3gsIGNvbW8gZWxlbWVudG8gY29uIGRhdG9zIGRlIHVuIGl0ZW0geSBkaWEgZXNwZWNpZmljb1xuICAgKlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYVxuICAgKiBAcGFyYW0ge09iamVjdH0gdGFiIC0gVGFiIGRlIHJlZmVyZW5jaWEsIHBhcmEgbW9zdHJhciBkYXRvcyBjb25maWd1cmFkb3MgcG9yIHRhYlxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBDb3JuZXIgRm9vdGVyXG4gICAqL1xuICByZWRyYXdGbG9hdEJveChjb25maWcsIHRhYiwgJGNvbnRhaW5lcikge1xuICAgICRjb250YWluZXIuaW5uZXJIVE1MID0gXCJcIjtcbiAgICAvL2xldCB0YWJTZWxlY3RlZCA9IHRhYiB8fCBudWxsO1xuXG4gICAgY29uZmlnLmRhdGEuZm9yRWFjaCgoZGUpID0+IHtcbiAgICAgIGlmIChkZS5pc0hpZGRlbikgcmV0dXJuO1xuICAgICAgZGUuY2hpbGRyZW4uZm9yRWFjaCgoZHMpID0+IHtcbiAgICAgICAgaWYgKGRzLmlzSGlkZGVuKSByZXR1cm47XG5cbiAgICAgICAgZHMuZGF0YS5mb3JFYWNoKChkYXRhKSA9PiB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgKCFkYXRhLm1lc3NhZ2UgfHwgZGF0YS5tZXNzYWdlLnZhbHVlID09IG51bGwpICYmXG4gICAgICAgICAgICAoZGF0YS52YWx1ZXMgPT0gbnVsbCB8fCBkYXRhLnZhbHVlcyA9PSB1bmRlZmluZWQgfHxcbiAgICAgICAgICAgIE9iamVjdC5lbnRyaWVzKGRhdGEudmFsdWVzKS5sZW5ndGggPT09IDAgKVxuICAgICAgICAgICl7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICB9XG5cblxuICAgICAgICAgIC8vY2hpbGRyZW4gRGF0YVxuICAgICAgICAgIGxldCBwb3NpdGlvbiA9IHRoaXMuZ2V0UG9zaXRpb25GbG9hdEJveChjb25maWcsIGRhdGEsIGRzKTtcblxuICAgICAgICAgIGxldCBjbGFzc05hbWUgPSBcIlwiO1xuXG5cbiAgICAgICAgICBpZiAoZGF0YS5lcnJvcnMgJiYgZGF0YS5lcnJvcnMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY2xhc3NOYW1lICs9IFwiaGFzLWVycm9ycyBcIjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoZGUuaXNDbG9zZWQpIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZSArPSBcImhpZGUgXCI7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgbGV0IG1zZyA9IG51bGw7XG4gICAgICAgICAgaWYodGFiLmZsb2F0Qm94Lm1lc3NhZ2VQYXRoKXtcbiAgICAgICAgICAgIG1zZyA9IHV0aWxzLmdldFZhckJ5UGF0aChkYXRhLCB0YWIuZmxvYXRCb3gubWVzc2FnZVBhdGgpO1xuICAgICAgICAgIH1cblxuXG4gICAgICAgICAgaWYgKG1zZyB8fCAoZGF0YS5tZXNzYWdlICYmIGRhdGEubWVzc2FnZS52YWx1ZSkpIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZSArPSBcImhhcy1tZXNzYWdlIFwiO1xuICAgICAgICAgIH1cblxuXG4gICAgICAgICAgbGV0IHN0ciA9IGBcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxvYXQtYm94ICR7Y2xhc3NOYW1lfSAke2RlLmlzQ2xvc2VkID8gXCJoaWRlXCIgOiBcIlwifVwiXG4gICAgICAgICAgICAgICAgICAgICBzdHlsZT1cIiR7cG9zaXRpb24gPyBwb3NpdGlvbiA6IFwiXCJ9XCJcbiAgICAgICAgICAgICAgICAgICAgIGl0ZW0taWQ9XCIke2RzLmlkIHx8IC0xfVwiXG4gICAgICAgICAgICAgICAgICAgICB0eXBlLW5vZGU9XCIke2RzLnR5cGUgfHwgXCJcIn1cIj4gYDtcblxuICAgICAgICAgIGlmICh0YWIgJiYgdGFiLmZsb2F0Qm94KSB7XG4gICAgICAgICAgICAvL251bWVyb3MgZW4gZWwgZmxvYXRCb3hcbiAgICAgICAgICAgIGlmICh0YWIuZmxvYXRCb3gubnVtcykge1xuICAgICAgICAgICAgICB0YWIuZmxvYXRCb3gubnVtcy5mb3JFYWNoKChuKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRhYi5sZWdlbmRzICYmIG4udGFiS2V5KSB7XG4gICAgICAgICAgICAgICAgICBsZXQgbGVnZW5kID10YWIubGVnZW5kcy5maW5kKFxuICAgICAgICAgICAgICAgICAgICAobCkgPT4gbC5rZXkgPT0gbi50YWJLZXlcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICBpZiAobGVnZW5kICYmICFsZWdlbmQuYWN0aXZlKSByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbGV0IGRhdGFGbG9hdEJveCA9IG51bGw7XG4gICAgICAgICAgICAgICAgbGV0IGNsYXNzTmFtZSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgbGV0IHNob3dJZiA9IHRydWU7XG4gICAgICAgICAgICAgICAgbGV0IGhpZGVJZiA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGxldCBjb2xvckNsYXNzID0gXCJcIjtcbiAgICAgICAgICAgICAgICBsZXQgY29sb3JTdHlsZSA9IFwiXCI7XG5cblxuICAgICAgICAgICAgICAgIGlmIChuLnZhck5hbWUpIHtcbiAgICAgICAgICAgICAgICAgIGRhdGFGbG9hdEJveCA9IHV0aWxzLmdldFZhckJ5UGF0aChkYXRhLnZhbHVlcywgbi52YXJOYW1lKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAobi52YXJTaG93KSB7XG4gICAgICAgICAgICAgICAgICBzaG93SWYgPSBCb29sZWFuKHV0aWxzLmdldFZhckJ5UGF0aChkYXRhLnZhbHVlcywgbi52YXJTaG93KSk7XG4gICAgICAgICAgICAgICAgICBkYXRhRmxvYXRCb3ggPSBkYXRhRmxvYXRCb3ggfHwgXCJcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAobi52YXJIaWRlKSB7XG4gICAgICAgICAgICAgICAgICBoaWRlSWYgPSBCb29sZWFuKHV0aWxzLmdldFZhckJ5UGF0aChkYXRhLnZhbHVlcywgbi52YXJIaWRlKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG4uc2hhcGUpIHtcbiAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZSArPSBcInNoYXBlLVwiICsgbi5zaGFwZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAobi5jb2xvcikge1xuICAgICAgICAgICAgICAgICAgaWYgKHV0aWxzLmlzSGV4Q29sb3Iobi5jb2xvcikpIHtcbiAgICAgICAgICAgICAgICAgICAgY29sb3JTdHlsZSA9IGAtLWxvY2FsLWNvbG9yOiAke24uY29sb3J9YDtcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbG9yQ2xhc3MgPSBuLmNvbG9yO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChkYXRhRmxvYXRCb3ggIT09IG51bGwgJiYgc2hvd0lmICYmICFoaWRlSWYpIHtcbiAgICAgICAgICAgICAgICAgIHN0ciArPSBgPHNwYW4gY2xhc3M9XCJkYXRhICR7Y29sb3JDbGFzc30gJHtjbGFzc05hbWV9XCIgc3R5bGU9XCIke2NvbG9yU3R5bGV9XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7ZGF0YUZsb2F0Qm94fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPmA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cblxuXG5cblxuICAgICAgICAgICAgLy9wdW50b3MgZW4gZWwgZmxvYXRCb3hcbiAgICAgICAgICAgIGlmICh0YWIuZmxvYXRCb3guZG90cykge1xuICAgICAgICAgICAgICBzdHIgKz0gYFxuICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkb3QtY29udGFpbmVyLW1pZGRsZVwiPmA7XG4gICAgICAgICAgICAgIHRhYi5mbG9hdEJveC5kb3RzLmZvckVhY2goKG4pID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodXRpbHMuZ2V0VmFyQnlQYXRoKGRhdGEudmFsdWVzLCBuLnZhck5hbWUpICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICBzdHIgKz0gYFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkb3QgJHtuLmNvbG9yfSAke1xuICAgICAgICAgICAgICAgICAgICBuLnNoYXBlIHx8IFwiXCJcbiAgICAgICAgICAgICAgICAgIH1cIj48L2Rpdj5gO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHN0ciArPSBgXG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICAgICAgfVxuXG5cblxuXG4gICAgICAgICAgICAvL2ZpbGEgZGUgcHVudG9zIGVuIGZsb2F0Qm94XG4gICAgICAgICAgICBpZiAodGFiLmZsb2F0Qm94LnJvd0RvdHMpIHtcbiAgICAgICAgICAgICAgdGFiLmZsb2F0Qm94LnJvd0RvdHMuZm9yRWFjaCgocm93KSA9PiB7XG5cbiAgICAgICAgICAgICAgICBsZXQgZnJlZUNvbHVtbnMgPSA0O1xuICAgICAgICAgICAgICAgIHN0ciArPSBgPHNwYW4gY2xhc3M9XCJyb3dkb3QtLXJvdyBcIj5gO1xuXG4gICAgICAgICAgICAgICAgcm93LmZvckVhY2goZG90ID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICh0YWIubGVnZW5kcyAmJiBkb3QudGFiS2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBsZWdlbmQgPXRhYi5sZWdlbmRzLmZpbmQoXG4gICAgICAgICAgICAgICAgICAgICAgKGwpID0+IGwua2V5ID09IGRvdC50YWJLZXlcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGxlZ2VuZCAmJiAhbGVnZW5kLmFjdGl2ZSkgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICBsZXQgZGF0YUZsb2F0Qm94ID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgIGxldCBjbGFzc05hbWUgPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgbGV0IHNob3dJZiA9IHRydWU7XG4gICAgICAgICAgICAgICAgICBsZXQgaGlkZUlmID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICBsZXQgY29sb3JDbGFzcyA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICBsZXQgY29sb3JTdHlsZSA9IFwiXCI7XG5cblxuICAgICAgICAgICAgICAgICAgaWYgKCBkb3QudmFyTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICBkYXRhRmxvYXRCb3ggPSB1dGlscy5nZXRWYXJCeVBhdGgoZGF0YS52YWx1ZXMsIGRvdC52YXJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgZGF0YUZsb2F0Qm94ID0gcGFyc2VJbnQoZGF0YUZsb2F0Qm94KTtcbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgaWYgKCBkb3QudmFyU2hvdykge1xuICAgICAgICAgICAgICAgICAgICBzaG93SWYgPSBCb29sZWFuKHV0aWxzLmdldFZhckJ5UGF0aChkYXRhLnZhbHVlcywgZG90LnZhclNob3cpKTtcbiAgICAgICAgICAgICAgICAgICAgZGF0YUZsb2F0Qm94ID0gZGF0YUZsb2F0Qm94IHx8IFwiXCI7XG4gICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgIGlmICggZG90LnZhckhpZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaGlkZUlmID0gQm9vbGVhbih1dGlscy5nZXRWYXJCeVBhdGgoZGF0YS52YWx1ZXMsIGRvdC52YXJIaWRlKSk7XG4gICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgIGlmICggZG90LnNoYXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZSArPSBcIiBzaGFwZS1cIiArIGRvdC5zaGFwZTtcbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgaWYgKCBkb3QuY29sb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHV0aWxzLmlzSGV4Q29sb3IoIGRvdC5jb2xvcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb2xvclN0eWxlID0gYC0tbG9jYWwtY29sb3I6ICR7IGRvdC5jb2xvcn1gO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbG9yQ2xhc3MgPSBkb3QuY29sb3I7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgaWYgKGRhdGFGbG9hdEJveCAhPT0gbnVsbCAmJiBkYXRhRmxvYXRCb3ggPiAwICYmIHNob3dJZiAmJiAhaGlkZUlmICYmIGZyZWVDb2x1bW5zID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgbiA9IGRhdGFGbG9hdEJveCA+IGZyZWVDb2x1bW5zID8gZnJlZUNvbHVtbnMgOiBkYXRhRmxvYXRCb3g7XG4gICAgICAgICAgICAgICAgICAgIGZyZWVDb2x1bW5zIC09IG47XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBuIDsgaW5kZXgrKykge1xuICAgICAgICAgICAgICAgICAgICAgIHN0ciArPSBgPGRpdiBjbGFzcz1cInJvd2RvdC0tZG90ICR7Y29sb3JDbGFzc30gJHtjbGFzc05hbWV9XCIgc3R5bGU9XCIke2NvbG9yU3R5bGV9XCI+PC9kaXY+YDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICBzdHIgKz0gYDwvc3Bhbj5gO1xuXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cblxuXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgc3RyICs9IGBcbiAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuXG4gICAgICAgICAgbGV0ICRlbGVtID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChzdHIpO1xuXG4gICAgICAgICAgJGVsZW0uYWRkRXZlbnRMaXN0ZW5lcihcIm1vdXNlb3ZlclwiLCAoZSkgPT4ge1xuICAgICAgICAgICAgJGVsZW0uZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwibW91c2VPdmVyRmxvYXRCb3hcIiwge1xuICAgICAgICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgZGV0YWlsOiB7XG4gICAgICAgICAgICAgICAgICBpdGVtOiBkcyxcbiAgICAgICAgICAgICAgICAgIGRhdGE6IGRhdGEsXG4gICAgICAgICAgICAgICAgICBvcmlnaW5hbEV2dDogZSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgICRlbGVtLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCAoZSkgPT4ge1xuICAgICAgICAgICAgJGVsZW0uZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwiY2xpY2tGbG9hdEJveFwiLCB7XG4gICAgICAgICAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBkZXRhaWw6IHtcbiAgICAgICAgICAgICAgICAgIGl0ZW06IGRzLFxuICAgICAgICAgICAgICAgICAgZGF0YTogZGF0YSxcbiAgICAgICAgICAgICAgICAgIG9yaWdpbmFsRXZ0OiBlLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgJGNvbnRhaW5lci5hcHBlbmRDaGlsZCgkZWxlbSk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gJGNvbnRhaW5lcjtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBEZXRhaWxEYXksIGRldGFsbGUgZGUgdmFsb3JlcyBkZSBpdGVtIHkgRGlhXG4gICAqIHNlIHVzYSBwYXJhOlxuICAgKiAgICAtIE11ZXN0cmEgbm9tYnJlIGRlIGl0ZW0geSBkZXRhbGxlc1xuICAgKiAgICAtIE11ZXN0cmEgY2Fwc3VsYXMgZGUgZGF0b3NcbiAgICogICAgLSBNdWVzdHJhIFBpbGxzLCBwaWxkb3JhcyBkZSBkYXRvcyByZXN1bWlkb3NcbiAgICogICAgLSBNdWVzdHJhIGFsZXJ0YXNcbiAgICogICAgLSBNdWVzdHJhIE1lbnNhamVcbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIENvbmZpZ3VyYWNpb24gY2FwaWJhcmFcbiAgICogQHBhcmFtIHtPYmplY3R9IGl0ZW0gLSBJdGVtIHJlbGFjaW9uYWRvXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhRGF5IC0gdmFsb3JlcyBkZSBpdGVtIHkgRGlhXG4gICAqIEBwYXJhbSB7Qm9vbGVhbn0gW29ubHlTdHJpbmdDb250ZW50ID0gZmFsc2VdIC0gcGFyYSBlc2NvZ2VyIHNpIGRldnVlbHZlIFN0cmluZyBvIERvbUVsZW1lbnRcbiAgICogQHJldHVybiB7U3RyaW5nfE9iamVjdH0gRWxlbWVudG8gY29tbyBTdHJpbmcgbyBEb21FbGVtZW50XG4gICAqL1xuICBjcmVhdGVEZXRhaWxEYXkoY29uZmlnLCBpdGVtID0ge30sIGRhdGFEYXksIHRhYlNlbGVjdGVkLCBvbmx5U3RyaW5nQ29udGVudCA9IGZhbHNlKSB7XG4gICAgbGV0IHN0ciA9IGBcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiaGVhZGVyLWRldGFpbFwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRpdGxlIHRydW5jYXRlXCI+XG4gICAgICAgICAgICAgICR7aXRlbS5sYWJlbCB8fCBcIlwifVxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3VidGl0bGVcIj5cbiAgICAgICAgICAgICAgJHtkYXRhRGF5ID8gZGF0ZVV0aWxzLmZvcm1hdERhdGVSZWFkZWFibGUoZGF0YURheS5kYXRlKSA6IFwiXCJ9XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJsaXN0LWRldGFpbCBsaXN0XCI+YDtcblxuICAgIC8vQ0FQU1VMRVNcbiAgICBpZiAoZGF0YURheSkge1xuICAgICAgY29uZmlnLnRpbWVsaW5lLmRldGFpbERheS5jYXBzdWxlcy5mb3JFYWNoKChjYXApID0+IHtcbiAgICAgICAgLy9wYXJhIGNvbXByb2JhciBzaSB0aWVuZSBkYXRvcywgc2Ugb2J0aWVuZSBlbCBwcmltZXIgdmFsb3JcbiAgICAgICAgLy9kZSBsYSBsaXN0YSBkZSB2YWx1ZXMgZGUgdW5hIGNhcHN1bGFcbiAgICAgICAgbGV0IGhhc1ZhbHVlcyA9XG4gICAgICAgICAgY2FwLnZhbHVlcy5maWx0ZXIoKHYpID0+XG4gICAgICAgICAgICB1dGlscy5nZXRWYXJCeVBhdGgoZGF0YURheS52YWx1ZXMsIHYudmFyTmFtZSlcbiAgICAgICAgICApLmxlbmd0aCA+IDA7XG4gICAgICAgIGxldCBoaWRlSWYgPSBmYWxzZTtcblxuICAgICAgICBpZiAoY2FwLmhpZGVJZikge1xuICAgICAgICAgIGhpZGVJZiA9IEJvb2xlYW4odXRpbHMuZ2V0VmFyQnlQYXRoKGRhdGFEYXkudmFsdWVzLCBjYXAuaGlkZUlmKSk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgY29sb3JDbGFzcyA9IFwiXCI7XG4gICAgICAgIGxldCBjb2xvclN0eWxlID0gXCJcIjtcblxuICAgICAgICBpZiAoY2FwLmNvbG9yKSB7XG4gICAgICAgICAgaWYgKHV0aWxzLmlzSGV4Q29sb3IoY2FwLmNvbG9yKSkge1xuICAgICAgICAgICAgY29sb3JTdHlsZSA9IGAtLWxvY2FsLWNvbG9yOiAke2NhcC5jb2xvcn07YDtcbiAgICAgICAgICAgIGNvbG9yU3R5bGUgKz0gYC0tbG9jYWwtY29sb3ItZm9udDogJHtjYXAuY29sb3J9O2A7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbG9yQ2xhc3MgPSBjYXAuY29sb3I7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChoYXNWYWx1ZXMgJiYgIWhpZGVJZikge1xuICAgICAgICAgIHN0ciArPSBgXG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpdGVtLWRldGFpbCAke2NvbG9yQ2xhc3N9XCIgc3R5bGU9XCIke2NvbG9yU3R5bGV9XCI+XG5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibGVmdC1pY29uICR7Y2FwLnNoYXBlIHx8IFwiXCJ9IFwiPjwvZGl2PlxuXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm5hbWVcIj5cbiAgICAgICAgICAgICAgICAgIDxzcGFuPlxuICAgICAgICAgICAgICAgICAgICAke2NhcC50aXRsZSB8fCBcIlwifVxuICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgIDwvZGl2PmA7XG5cbiAgICAgICAgICBzdHIgKz0gYFxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJpdGVtLWRlc2NyaXB0aW9uXCI+IGA7XG5cbiAgICAgICAgICBjYXAudmFsdWVzLmZvckVhY2goKHYpID0+IHtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbGV0IHZhbHVlID0gdi52YXJOYW1lID8gdXRpbHMuZ2V0VmFyQnlQYXRoKGRhdGFEYXkudmFsdWVzLCB2LnZhck5hbWUpIDogbnVsbDtcblxuICAgICAgICAgICAgaWYgKGNhcC5pc0xhYmVsZWRBcnJheSkge1xuICAgICAgICAgICAgICB2YWx1ZS5mb3JFYWNoKCh2YWx1ZUxhYmVsZWQpID0+IHtcbiAgICAgICAgICAgICAgICBsZXQgb3V0cHV0VmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgICAgIGxldCB2YWx1ZU5hbWUgPSB2LnZhbHVlTmFtZSA/IHYudmFsdWVOYW1lIDogXCJ2YWx1ZVwiO1xuXG4gICAgICAgICAgICAgICAgbGV0IHRlbXBWYWx1ZSA9IHV0aWxzLmdldFZhckJ5UGF0aCh2YWx1ZUxhYmVsZWQsIHZhbHVlTmFtZSk7XG5cbiAgICAgICAgICAgICAgICBpZiAodGVtcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICBvdXRwdXRWYWx1ZSA9IHYucm91bmQgPyB1dGlscy5yb3VuZCh0ZW1wVmFsdWUsIHYucm91bmQpIDogdGVtcFZhbHVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh2LmZvcm1hdHRlcikge1xuICAgICAgICAgICAgICAgICAgb3V0cHV0VmFsdWUgPSB2LmZvcm1hdHRlcih2YWx1ZUxhYmVsZWQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKHR5cGVvZiBvdXRwdXRWYWx1ZSA9PSBcIm51bWJlclwiKXtcbiAgICAgICAgICAgICAgICAgIG91dHB1dFZhbHVlID0gbmV3IEludGwuTnVtYmVyRm9ybWF0KCkuZm9ybWF0KG91dHB1dFZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBzdHIgKz1cbiAgICAgICAgICAgICAgICAgIG91dHB1dFZhbHVlID09IG51bGxcbiAgICAgICAgICAgICAgICAgICAgPyBcIlwiXG4gICAgICAgICAgICAgICAgICAgIDogYFxuICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkZXNjICR7di5zaG93Q29sdW1uID8gJ2Rlc2MtY29sdW1uJyA6ICcnfVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxhYmVsXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICR7IHYuaGlkZUxhYmVsID8gXCJcIiA6ICB2YWx1ZUxhYmVsZWQubGFiZWx9XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2RpdiA+XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidmFsXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwicHJlZml4XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHt2LnByZWZpeCB8fCBcIlwifVxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidmFsdWVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAke291dHB1dFZhbHVlfVxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwic3VmZml4XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHt2YWx1ZUxhYmVsZWQuc3VmZml4IHx8IHYuc3VmZml4IHx8IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PmA7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgbGV0IG91dHB1dFZhbHVlID0gdi5yb3VuZCA/IHV0aWxzLnJvdW5kKHZhbHVlLCB2LnJvdW5kKSA6IHZhbHVlO1xuXG4gICAgICAgICAgICAgIGlmICh2LmZvcm1hdHRlcikge1xuICAgICAgICAgICAgICAgIG91dHB1dFZhbHVlID0gdi5mb3JtYXR0ZXIoe29wdGlvbnM6dixkYXRhRGF5LCBvdXRwdXRWYWx1ZX0pO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYodHlwZW9mIG91dHB1dFZhbHVlID09IFwibnVtYmVyXCIpe1xuICAgICAgICAgICAgICAgIG91dHB1dFZhbHVlID0gbmV3IEludGwuTnVtYmVyRm9ybWF0KCkuZm9ybWF0KG91dHB1dFZhbHVlKTtcbiAgICAgICAgICAgICAgfVxuXG5cbiAgICAgICAgICAgICAgc3RyICs9XG4gICAgICAgICAgICAgICAgb3V0cHV0VmFsdWUgPT0gbnVsbFxuICAgICAgICAgICAgICAgICAgPyBcIlwiXG4gICAgICAgICAgICAgICAgICA6IGBcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRlc2NcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJwcmVmaXhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAke3YucHJlZml4IHx8IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ2YWx1ZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7b3V0cHV0VmFsdWV9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJzdWZmaXhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAke3Yuc3VmZml4IHx8IFwiXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIHN0ciArPSBgXG4gICAgICAgICAgICAgICAgPC9kaXY+YDtcblxuICAgICAgICAgIHN0ciArPSBgXG4gICAgICAgICAgICAgIDwvZGl2PmA7IC8vIGVuZCAuaXRlbS1kZXRhaWxcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgc3RyICs9IGBcbiAgICAgICAgPC9kaXY+YDsgLy8gbGlzdC1kZXRhaWxcblxuICAgIC8vUElMTFNcbiAgICBpZiAoXG4gICAgICBjb25maWcudGltZWxpbmUuZGV0YWlsRGF5LnBpbGxzVmFyTmFtZSAmJlxuICAgICAgZGF0YURheSAmJlxuICAgICAgZGF0YURheS52YWx1ZXNbY29uZmlnLnRpbWVsaW5lLmRldGFpbERheS5waWxsc1Zhck5hbWVdXG4gICAgKSB7XG4gICAgICBzdHIgKz0gYFxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJlbGVtZW50cy1kZXRhaWxcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJuYW1lXCI+ICR7Y29uZmlnLnRpbWVsaW5lLmRldGFpbERheS5waWxsc1RpdGxlfSA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJlbGVtZW50cy1saXN0XCI+YDtcblxuICAgICAgZGF0YURheS52YWx1ZXNbY29uZmlnLnRpbWVsaW5lLmRldGFpbERheS5waWxsc1Zhck5hbWVdLmZvckVhY2goKGUpID0+IHtcbiAgICAgICAgbGV0IHZhbHVlID0gZS52YWx1ZTtcblxuICAgICAgICBpZih0eXBlb2Ygb3V0cHV0VmFsdWUgPT0gXCJudW1iZXJcIil7XG4gICAgICAgICAgdmFsdWUgPSBuZXcgSW50bC5OdW1iZXJGb3JtYXQoKS5mb3JtYXQodmFsdWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgc3RyICs9IGBcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJlbGVtZW50LWRldGFpbFwiPlxuICAgICAgICAgICAgICA8Yj4ke2UubGFiZWx9PC9iPlxuICAgICAgICAgICAgICAke3ZhbHVlfVxuICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgIH0pO1xuXG4gICAgICBzdHIgKz0gYFxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5gOyAvL2VuZCAuZWxlbWVudC1kZXRhaWwgPiAuZWxlbWVudC1saXN0XG4gICAgfVxuXG4gICAgLy9zdHIgKz0gYDwvZGl2PmA7XG5cbiAgICBpZiAoZGF0YURheSAmJiBkYXRhRGF5LmVycm9ycyAmJiBkYXRhRGF5LmVycm9ycy5sZW5ndGggPiAwKSB7XG4gICAgICBkYXRhRGF5LmVycm9ycy5mb3JFYWNoKChlcnIpID0+IHtcbiAgICAgICAgbGV0IGFsZXJ0SWNvbiA9IGA8c3BhbiBjbGFzcz1cImFsZXJ0LWljb25cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPHN2ZyBzdHlsZT1cIndpZHRoOjI0cHg7aGVpZ2h0OjI0cHhcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBmaWxsPVwiY3VycmVudENvbG9yXCIgZD1cIk0xMyAxNEgxMVY5SDEzTTEzIDE4SDExVjE2SDEzTTEgMjFIMjNMMTIgMkwxIDIxWlwiIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPmA7XG4gICAgICAgIHN0ciArPSBgXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImFsZXJ0XCI+XG4gICAgICAgICAgICAke2FsZXJ0SWNvbn1cbiAgICAgICAgICAgICR7ZXJyLmxhYmVsfVxuICAgICAgICAgIDwvZGl2PmA7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBsZXQgbXNnID0gbnVsbDtcbiAgICBsZXQgYXV0aG9yID0gbnVsbDtcbiAgICBsZXQgZGF0ZU1zZyA9IG51bGw7XG4gICAgaWYgKGRhdGFEYXkgKSB7XG4gICAgICBtc2cgPSB1dGlscy5nZXRWYXJCeVBhdGgoZGF0YURheSwgdGFiU2VsZWN0ZWQuZmxvYXRCb3gubWVzc2FnZVBhdGgpO1xuXG4gICAgICBpZighbXNnICYmIGRhdGFEYXkubWVzc2FnZSAmJiBkYXRhRGF5Lm1lc3NhZ2UudmFsdWUpe1xuICAgICAgICBtc2cgPSBkYXRhRGF5Lm1lc3NhZ2UudmFsdWU7XG4gICAgICAgIGF1dGhvciA9IGRhdGFEYXkubWVzc2FnZS5hdXRob3I7XG4gICAgICAgIGRhdGVNc2cgPSBkYXRlVXRpbHMuZm9ybWF0RGF0ZVJlYWRlYWJsZSggbmV3IERhdGUoZGF0YURheS5tZXNzYWdlLmRhdGUpKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYobXNnKXtcbiAgICAgIC8vbXNnID0gbXNnLnJlcGxhY2UoLyhcXHJcXG58XFxyfFxcbikvZywgJzxicj4nKTtcbiAgICAgIHN0ciArPSBgXG4gICAgICAgICAgPGRpdiBjbGFzcz1cIm1zai1jb250YWluZXJcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtc2pcIj5cbiAgICAgICAgICAgIDxwcmU+JHttc2cgfHwgXCJcIn08L3ByZT5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1zai1kZXRhaWxcIj5cbiAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJlbWFpbFwiPiAke2F1dGhvciB8fCBcIlwifSA8L3NwYW4+XG4gICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZGF0ZVwiPiAke2RhdGVNc2cgfHwgXCJcIn0gPC9zcGFuPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PmA7XG4gICAgfVxuXG4gICAgbGV0IHN0ckNvbnRhaW5lciA9IGA8ZGl2IGNsYXNzPVwiZGV0YWlsLWRheSBkZC1oaWRlXCI+ICR7c3RyfSA8L2Rpdj5gO1xuXG4gICAgaWYgKG9ubHlTdHJpbmdDb250ZW50KSByZXR1cm4gc3RyO1xuXG4gICAgcmV0dXJuIGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoc3RyQ29udGFpbmVyKTtcbiAgfSxcblxuICAvKipcbiAgICogUmVjcmVhIEhUTUwgZGUgZGV0YWlsRGF5XG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBjb25maWcgLSBDb25maWd1cmFjaW9uIGNhcGliYXJhXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBpdGVtIC0gSXRlbSByZWxhY2lvbmFkb1xuICAgKiBAcGFyYW0ge09iamVjdH0gZGF0YURheSAtIHZhbG9yZXMgZGUgaXRlbSB5IERpYVxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IEVsZW1lbnRvIGNvbW8gU3RyaW5nLCBkZSBkZXRhaWxEYXlcbiAgICovXG4gIHJlZHJhd0RldGFpbERheShjb25maWcsIGl0ZW0sIGRhdGFEYXksIHRhYlNlbGVjdGVkKSB7XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlRGV0YWlsRGF5KGNvbmZpZywgaXRlbSwgZGF0YURheSwgdGFiU2VsZWN0ZWQsdHJ1ZSk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIFJlcG9zaWNpb25hIEZsb2F0Qm94XG4gICAqIHZlcmlmaWNhIHNpIGVsIHBhcmVudCBlc3RhIGRlc3BsZWdhZG8sIHBhcmEgb2N1bHRhciBsb3MgZGF0b3NcbiAgICpcbiAgICogU29sbyBhY3R1YWxpemEgbGFzIGFsdHVyYXMgZGUgbG9zIGZsb2F0Ym94XG4gICAqIG5vIHJlY3JlYSBsb3MgZmxvYXRib3gsIGVzIG1hcyBvcHRpbW9cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIENvbmZpZ3VyYWNpb24gY2FwaWJhcmFcbiAgICogQHBhcmFtIHtPYmplY3R9IGl0ZW0gLSBJdGVtIHJlbGFjaW9uYWRvXG4gICAqL1xuICByZXBvc2l0aW9uRmxvYXRCb3goY29uZmlnLCAkZmxvYXRCb3hDb250YWluZXIpIHtcbiAgICAkZmxvYXRCb3hDb250YWluZXIucXVlcnlTZWxlY3RvckFsbChcIi5mbG9hdC1ib3hcIikuZm9yRWFjaCgoJGYpID0+IHtcbiAgICAgIGxldCBpdGVtSWQgPSAkZi5nZXRBdHRyaWJ1dGUoXCJpdGVtLWlkXCIpO1xuICAgICAgbGV0IGl0ZW1IZWlnaHQgPSBwYXJzZUZsb2F0KFxuICAgICAgICB1dGlscy5nZXRDU1NWYXJpYWJsZShjb25maWcsIFwiLS1pdGVtLWhlaWdodFwiKVxuICAgICAgKTtcbiAgICAgIGxldCBpdGVtLCBwYXJlbnQ7XG4gICAgICAoeyBpdGVtLCBwYXJlbnQgfSA9IHV0aWxzLmdldEl0ZW1CeUlkKGNvbmZpZywgaXRlbUlkLCBcImNoaWxkXCIsIHRydWUpKTtcbiAgICAgIGlmIChpdGVtKSB7XG4gICAgICAgIGxldCB0b3AgPSB1dGlscy5nZXRQb3NpdGlvbkJ5SXRlbShjb25maWcsIGl0ZW0pO1xuICAgICAgICAkZi5zdHlsZS50b3AgPSB0b3AgKiBpdGVtSGVpZ2h0ICsgXCJweFwiO1xuICAgICAgICBpZiAocGFyZW50ICYmIHBhcmVudC5pc0Nsb3NlZCkge1xuICAgICAgICAgICRmLmNsYXNzTGlzdC5hZGQoXCJoaWRlXCIpO1xuICAgICAgICB9IGVsc2UgaWYgKCRmLmNsYXNzTGlzdC5jb250YWlucyhcImhpZGVcIikpIHtcbiAgICAgICAgICAkZi5jbGFzc0xpc3QucmVtb3ZlKFwiaGlkZVwiKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9LFxuXG4gIC8qKlxuICAgKiBSZWNyZWEgaW5kaWNhZG9yZXMgZGUgZGlhcyBzZWxlY2Npb25hZG9zXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSAkZWxlbSAtIEVsZW1lbnRvIERvbSBkb25kZSBjcmVhIGxvcyBlbGVtZW50b3Mgc2VsZWNjaW9uYWRvc1xuICAgKiBAcGFyYW0ge09iamVjdFtdfSBzZWxlY3RlZCAtIEFycmF5IGNvbiBsb3MgZGlhcyBzZWxlY2Npb25hZG9zXG4gICAqIEByZXR1cm4ge09iamVjdH0gRWxlbWVudG8gRG9tIHF1ZSBjb250aWVuZSBsb3MgaW5kaWNhZG9yZXMgZGUgZGlhcyBzZWxlY2Npb25hZG9zXG4gICAqL1xuICByZWRyYXdTZWxlY3RCb2FyZCgkZWxlbSwgc2VsZWN0ZWQpIHtcbiAgICAkZWxlbS5pbm5lckhUTUwgPSBcIlwiO1xuICAgIGxldCBoYXNOdW1iZXIgPSB0cnVlO1xuXG4gICAgaWYgKHNlbGVjdGVkKSB7XG4gICAgICBpZiAoc2VsZWN0ZWQubGVuZ3RoID09IDEpIGhhc051bWJlciA9IGZhbHNlO1xuXG4gICAgICBzZWxlY3RlZC5mb3JFYWNoKChzKSA9PiB7XG4gICAgICAgIGxldCBhdHRyaWJ1dGVzID0gW107XG5cbiAgICAgICAgaWYgKGhhc051bWJlcikge1xuICAgICAgICAgIGF0dHJpYnV0ZXMucHVzaCh7IG5hbWU6IFwiY2FwLWJhZGdlXCIsIHZhbHVlOiBzLmluZGV4IH0pO1xuICAgICAgICB9XG4gICAgICAgIGxldCAkcyA9IGRvbS5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtcbiAgICAgICAgICBjbGFzc05hbWU6IFwic2VsZWN0ZWQtZGF5XCIsXG4gICAgICAgICAgYXR0cmlidXRlcyxcbiAgICAgICAgfSk7XG4gICAgICAgICRzLnN0eWxlLmxlZnQgPSBzLnBvcy5sZWZ0ICsgXCJweFwiO1xuICAgICAgICAkcy5zdHlsZS50b3AgPSBzLnBvcy50b3AgKyBcInB4XCI7XG4gICAgICAgICRlbGVtLmFwcGVuZCgkcyk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuICRlbGVtO1xuICB9LFxuXG4gIC8qKlxuICAgKiBPYnRpZW5lIFN0cmluZyBjb24gZXN0aWxvcyBDU1MgZGUgbGEgcG9zaWNpb24gZGUgdW4gZmxvYXRCb3hcbiAgICogY2FsY3VsYWRvIHNlZ3VuIGl0ZW0geSBmZWNoYSBkZSBsb3MgdmFsb3Jlc1xuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIC0gQ29uZmlndXJhY2lvbiBjYXBpYmFyYSwgcGFyYSB2ZXIgZmVjaGEgZGUgaW5pY2lvXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhIC0gRGF0b3MgZGVsIGRpYSBpbmRpY2Fkb1xuICAgKiBAcGFyYW0ge09iamVjdH0gaXRlbSAtIEl0ZW0gcmVsYWNpb25hZG9cbiAgICogQHJldHVybiB7U3RyaW5nfSBTdHJpbmcgQ1NTIHRvcCB5IGxlZnQgLCBwYXJhIHBvc2ljaW9uYXIgZmxvYXRCb3ggZW4gdGFibGVcbiAgICovXG4gIGdldFBvc2l0aW9uRmxvYXRCb3goY29uZmlnLCBkYXRhLCBpdGVtKSB7XG4gICAgbGV0IGxlZnQgPSBkYXRlVXRpbHMuZGlmZkRheXMoY29uZmlnLnRpbWVsaW5lLnN0YXJ0LCBkYXRhLmRhdGUpO1xuICAgIGxldCB0b3AgPSB1dGlscy5nZXRQb3NpdGlvbkJ5SXRlbShjb25maWcsIGl0ZW0pO1xuICAgIGxldCBkYXlXaWR0aCA9IHBhcnNlRmxvYXQodXRpbHMuZ2V0Q1NTVmFyaWFibGUoY29uZmlnLCBcIi0tZGF5LXdpZHRoXCIpKTtcbiAgICBsZXQgaXRlbUhlaWdodCA9IHBhcnNlRmxvYXQodXRpbHMuZ2V0Q1NTVmFyaWFibGUoY29uZmlnLCBcIi0taXRlbS1oZWlnaHRcIikpO1xuICAgIGxlZnQgKj0gZGF5V2lkdGg7XG4gICAgdG9wICo9IGl0ZW1IZWlnaHQ7XG4gICAgcmV0dXJuIFwidG9wOiBcIiArIHRvcCArIFwiLjVweDsgbGVmdDpcIiArIGxlZnQgKyBcIi41cHg7XCI7XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWEgQm90b24gY29tbyBlbGVtZW50byBEb21cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IHByb3BzIC0gcHJvcGllZGFkZXMgcGFyYSBib3RvblxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcHMuY2xhc3NOYW1lIC0gY2xhc3NlcyBjc3MgcGFyYSBib3RvblxuICAgKiBAcGFyYW0geyp9IHByb3BzLmtleSAtIGtleSBwYXJhIGlkZW50aWZpY2FyIGEgYm90b25cbiAgICogQHBhcmFtIHtTdHJpbmd9IHByb3BzLmxhYmVsIC0gVGV4dG8gYm90b25cbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gZGVsIGJvdG9uIGNyZWFkb1xuICAgKi9cbiAgY3JlYXRlQnV0dG9uKHByb3BzKSB7XG4gICAgcmV0dXJuIGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoYFxuICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cIiR7cHJvcHMuY2xhc3NOYW1lIHx8IFwiXCJ9XCIgaW5wdXQta2V5PVwiJHtcbiAgICAgIHByb3BzLmtleSB8fCBcIlwiXG4gICAgfVwiPlxuICAgICAgICAgICAgICAke3Byb3BzLmxhYmVsIHx8IFwiXCJ9XG4gICAgICAgICAgICA8L2J1dHRvbj5gKTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBCb3RvbmVzIGRlIGd1YXJkYXIgeSBjYW5jZWxhciBsb3MgZGF0b3MgZGUgZm9ybXVsYXJpbyBkZWwgc2lkZWJhciBkZXJlY2hvXG4gICAqXG4gICAqIEByZXR1cm4ge09iamVjdH0gRWxlbWVudG8gRG9tIGRlbCBib3RvbmVzIGNyZWFkb3NcbiAgICovXG4gIGNyZWF0ZU5hdlJpZ2h0YnV0dG9ucygpIHtcbiAgICBsZXQgc2F2ZUJ0biA9IHRoaXMuY3JlYXRlQnV0dG9uKHtcbiAgICAgIGxhYmVsOiBcIkd1YXJkYXJcIixcbiAgICAgIGNsYXNzTmFtZTogXCJjYXAtYnRuLXJhaXNlZFwiLFxuICAgIH0pO1xuICAgIGxldCBjYW5jZWxCdG4gPSB0aGlzLmNyZWF0ZUJ1dHRvbih7XG4gICAgICBsYWJlbDogXCJDYW5jZWxhclwiLFxuICAgICAgY2xhc3NOYW1lOiBcImNhcC1idG4tb3V0bGluZVwiLFxuICAgIH0pO1xuICAgIGxldCBidG5TZWN0aW9uID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChcbiAgICAgIGA8ZGl2IGNsYXNzPVwiYnV0dG9uLXNlY3Rpb25cIj48L2Rpdj5gXG4gICAgKTtcbiAgICBidG5TZWN0aW9uLmFwcGVuZENoaWxkKHNhdmVCdG4pO1xuICAgIGJ0blNlY3Rpb24uYXBwZW5kQ2hpbGQoY2FuY2VsQnRuKTtcblxuICAgIHNhdmVCdG4uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIChlKSA9PiB7XG4gICAgICBzYXZlQnRuLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgIG5ldyBDdXN0b21FdmVudChcInNhdmVNdWx0aUlucHV0XCIsIHtcbiAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgIGNhbmNlbGFibGU6IGZhbHNlLFxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGNhbmNlbEJ0bi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGUpID0+IHtcbiAgICAgIGNhbmNlbEJ0bi5kaXNwYXRjaEV2ZW50KFxuICAgICAgICBuZXcgQ3VzdG9tRXZlbnQoXCJjYW5jZWxNdWx0aUlucHV0XCIsIHtcbiAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgIGNhbmNlbGFibGU6IGZhbHNlLFxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIHJldHVybiBidG5TZWN0aW9uO1xuICB9LFxuXG4gIC8qKlxuICAgKiBDcmVhIElucHV0IGNvbW8gZWxlbWVudG8gRG9tXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwcm9wcyAtIGNvbmZpZyBwYXJhIElucHV0XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbZGF0YURheSA9IG51bGxdIC0gdmFsb3JlcyBkZSBpdGVtIHkgRGlhLCBvcGNpb25hbFxuICAgKiBAcGFyYW0ge09iamVjdH0gW2RheVNlbGVjdGVkID0gbnVsbF0gLSBkYXRvcyBkZWwgZGlhIHNlbGVjY2lvbmFkb1xuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBkZWwgaW5wdXQgY3JlYWRvXG4gICAqL1xuICBjcmVhdGVJbnB1dChwcm9wcywgZGF0YURheSA9IG51bGwsIGRheVNlbGVjdGVkID0gbnVsbCwgc2VsZWN0ZWQgPSBbXSkge1xuICAgIGxldCByID0gbnVsbDtcblxuICAgIGlmIChwcm9wcy5pc0hpZGRlbikgcmV0dXJuIHI7XG5cbiAgICBzd2l0Y2ggKHByb3BzLnR5cGUpIHtcbiAgICAgIGNhc2UgXCJpbnB1dExpc3RcIjpcbiAgICAgICAgciA9IHRoaXMuY3JlYXRlSW5wdXRMaXN0KHByb3BzLCBkYXRhRGF5LCBkYXlTZWxlY3RlZCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBcInNlbGVjdFwiOlxuICAgICAgICByID0gdGhpcy5jcmVhdGVJbnB1dFNlbGVjdChwcm9wcywgZGF0YURheSwgZGF5U2VsZWN0ZWQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgXCJmaWxlXCI6XG4gICAgICAgIHIgPSB0aGlzLmNyZWF0ZUlucHV0RmlsZShwcm9wcywgZGF0YURheSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBcImZpbGVMaW5rXCI6XG4gICAgICAgIHIgPSB0aGlzLmNyZWF0ZUZpbGVMaW5rKHByb3BzLCBkYXRhRGF5KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFwidGV4dFwiOlxuICAgICAgICByID0gdGhpcy5jcmVhdGVUZXh0KHByb3BzLCBzZWxlY3RlZCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBcInRpdGxlXCI6IFxuICAgICAgICByID0gdGhpcy5jcmVhdGVUaXRsZShwcm9wcyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBcIm51bWJlclwiOlxuICAgICAgICByID0gdGhpcy5jcmVhdGVJbnB1dE51bWJlcihwcm9wcywgZGF0YURheSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBcImZsb2F0XCI6XG4gICAgICAgIHIgPSB0aGlzLmNyZWF0ZUlucHV0RmxvYXQocHJvcHMsIGRhdGFEYXkpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgXCJtZXNzYWdlXCI6XG4gICAgICAgIHIgPSB0aGlzLmNyZWF0ZUlucHV0TWVzc2FnZShwcm9wcywgZGF0YURheSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBcInRleHRhcmVhXCI6XG4gICAgICAgIHIgPSB0aGlzLmNyZWF0ZUlucHV0VGV4dEFyZWEocHJvcHMsIGRhdGFEYXkpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgXCJjaGVja2JveFwiOlxuICAgICAgICByID0gdGhpcy5jcmVhdGVJbnB1dENoZWNrYm94KHByb3BzLCBkYXRhRGF5KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFwiaW5wdXQtYm94XCI6XG4gICAgICAgIHIgPSB0aGlzLmNyZWF0ZUlucHV0Qm94KHByb3BzLCBkYXRhRGF5KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFwibGlzdFwiOlxuICAgICAgICByID0gdGhpcy5jcmVhdGVMaXN0KHByb3BzLCBkYXRhRGF5KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFwiYnV0dG9uXCI6XG4gICAgICAgIHIgPSB0aGlzLmNyZWF0ZUlucHV0QnV0dG9uKHByb3BzLCBkYXRhRGF5KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFwidGltZVwiOlxuICAgICAgICByID0gdGhpcy5jcmVhdGVJbnB1dFRpbWUocHJvcHMsIGRhdGFEYXkpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgXCJ0ZXh0XCI6XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByID0gdGhpcy5jcmVhdGVJbnB1dFRleHQocHJvcHMsIGRhdGFEYXkpO1xuICAgIH1cblxuICAgIHJldHVybiByO1xuICB9LFxuXG4gIC8qKlxuICAgKiBDcmVhIElucHV0IGNvbiBmb3JtYXRvIEhvcmEsIGNvbW8gZWxlbWVudG8gRG9tXG4gICAqXG4gICAqIFVzYSAyIGlucHV0cywgaG9yYSB5IG1pbnV0b3NcbiAgICpcbiAgICogZWwgdmFsdWUgcXVlIGludGVycHJldGEgZXMgU3RyaW5nIEhIOk1NXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwcm9wcyAtIGNvbmZpZyBwYXJhIElucHV0XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbZGF0YURheSA9IG51bGxdIC0gdmFsb3JlcyBkZSBpdGVtIHkgRGlhLCBvcGNpb25hbFxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBkZWwgaW5wdXQgY3JlYWRvXG4gICAqL1xuICBjcmVhdGVJbnB1dFRpbWUocHJvcHMsIGRhdGFEYXkpIHtcbiAgICBsZXQgaGhWYWx1ZSA9IFwiXCI7XG4gICAgbGV0IG1tVmFsdWUgPSBcIlwiO1xuXG4gICAgaWYgKGRhdGFEYXkgJiYgZGF0YURheS52YWx1ZXMpIHtcbiAgICAgIGxldCB2YWx1ZSA9IHV0aWxzLmdldFZhckJ5UGF0aChkYXRhRGF5LCBwcm9wcy52YXJOYW1lKTtcblxuICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgIHZhbHVlID0gdmFsdWUuc3BsaXQoXCI6XCIpO1xuICAgICAgICBoaFZhbHVlID0gdmFsdWVbMF07XG4gICAgICAgIG1tVmFsdWUgPSB2YWx1ZVsxXTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgciA9IGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoYFxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1zZWN0aW9uXCIgaW5wdXQta2V5PVwiJHtwcm9wcy5rZXkgfHwgXCJcIn1cIj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC1zdWJ0aXRsZSBkLWJsb2NrXCI+XG4gICAgICAgICAgICAgICR7cHJvcHMubGFiZWwgfHwgXCJcIn1cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0aW1lXCI+XG4gICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwibnVtYmVyXCJcbiAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiaG91clwiXG4gICAgICAgICAgICAgICAgICAgICBpZD1cInRlc3RcIlxuICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCIwMFwiXG4gICAgICAgICAgICAgICAgICAgICBtaW49XCIwXCJcbiAgICAgICAgICAgICAgICAgICAgIG1heD1cIjI0XCJcbiAgICAgICAgICAgICAgICAgICAgIHZhbHVlPVwiJHtoaFZhbHVlfVwiPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInN5bWJvbFwiPjo8L3NwYW4+XG4gICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwibnVtYmVyXCJcbiAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwibWludXRlc1wiXG4gICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIjAwXCJcbiAgICAgICAgICAgICAgICAgICAgIG1pbj1cIjBcIlxuICAgICAgICAgICAgICAgICAgICAgbWF4PVwiNTlcIlxuICAgICAgICAgICAgICAgICAgICAgdmFsdWU9XCIke21tVmFsdWV9XCI+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5gKTtcblxuICAgIGxldCBoaCA9IHIucXVlcnlTZWxlY3RvcihcIi5ob3VyXCIpO1xuICAgIGxldCBtbSA9IHIucXVlcnlTZWxlY3RvcihcIi5taW51dGVzXCIpO1xuXG4gICAgaGguYWRkRXZlbnRMaXN0ZW5lcihcImlucHV0XCIsIChlKSA9PiB7XG4gICAgICBoaC5kaXNwYXRjaEV2ZW50KFxuICAgICAgICBuZXcgQ3VzdG9tRXZlbnQoXCJjaGFuZ2VUaW1lSW5wdXRISFwiLCB7XG4gICAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICBkZXRhaWw6IHtcbiAgICAgICAgICAgIGtleTogcHJvcHMua2V5LFxuICAgICAgICAgICAgdmFsdWU6IGUuc3JjRWxlbWVudC52YWx1ZSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIG1tLmFkZEV2ZW50TGlzdGVuZXIoXCJpbnB1dFwiLCAoZSkgPT4ge1xuICAgICAgbW0uZGlzcGF0Y2hFdmVudChcbiAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwiY2hhbmdlVGltZUlucHV0TU1cIiwge1xuICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICAgICAgZGV0YWlsOiB7XG4gICAgICAgICAgICBrZXk6IHByb3BzLmtleSxcbiAgICAgICAgICAgIHZhbHVlOiBlLnNyY0VsZW1lbnQudmFsdWUsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZEtleURvd25JbnB1dEV2ZW50cyhoaCk7XG4gICAgdGhpcy5hZGRLZXlEb3duSW5wdXRFdmVudHMobW0pO1xuXG4gICAgcmV0dXJuIHI7XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWEgVGV4dCBjb21vIGVsZW1lbnRvIERvbVxuICAgKiBTZSBjb25maWd1cmEgY29tbyBpbnB1dCwgcGVybyBubyBkZXZ1ZWx2ZSBkYXRvcywgZXMgdW4gdGV4dG9cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IHByb3BzIC0gY29uZmlnIHBhcmEgSW5wdXRcbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gZGVsIGlucHV0IGNyZWFkb1xuICAgKi9cbiAgY3JlYXRlVGV4dChwcm9wcywgc2VsZWN0ZWQpIHtcbiAgICBsZXQgbGFiZWwgPSBwcm9wcy5sYWJlbDtcbiAgICBpZiAocHJvcHMuZm9ybWF0dGVyKSB7XG4gICAgICBsYWJlbCA9IHByb3BzLmZvcm1hdHRlcih7IHNlbGVjdGVkIH0pO1xuICAgIH1cbiAgICBsZXQgJGVsZW0gPSBkb20uY3JlYXRlRWxlbWVudEZyb21IVE1MKGBcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiaW5wdXQtc2VjdGlvblwiIGlucHV0LWtleT1cIiR7cHJvcHMua2V5IHx8IFwiXCJ9XCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cIiR7cHJvcHMuY2xhc3NOYW1lcyB8fCBcIlwifVwiPlxuICAgICAgICAgICAgJHtsYWJlbH1cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICA8L2Rpdj5gKTtcbiAgICByZXR1cm4gJGVsZW07XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWEgVGl0bGUgY29tbyBlbGVtZW50byBEb21cbiAgICogU2UgY29uZmlndXJhIGNvbW8gaW5wdXQsIHBlcm8gbm8gZGV2dWVsdmUgZGF0b3MsIGVzIHVuIHRleHRvXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwcm9wcyAtIGNvbmZpZyBwYXJhIElucHV0XG4gICAqIEByZXR1cm4ge09iamVjdH0gRWxlbWVudG8gRG9tIGRlbCBpbnB1dCBjcmVhZG9cbiAgICovXG4gIGNyZWF0ZVRpdGxlKHByb3BzKSB7XG4gICAgbGV0IGNsYXNzTmFtZXMgPSBcInRleHQtdGl0bGVcIjtcbiAgICBpZiAocHJvcHMuaXNTdWJ0aXRsZSkge1xuICAgICAgY2xhc3NOYW1lcyA9IFwidGV4dC1zdWJ0aXRsZVwiO1xuICAgIH1cbiAgICByZXR1cm4gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChgXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb25cIiBpbnB1dC1rZXk9XCIke3Byb3BzLmtleSB8fCBcIlwifVwiPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCIke2NsYXNzTmFtZXN9XCI+XG4gICAgICAgICAgICAgICR7cHJvcHMubGFiZWx9XG4gICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgPC9kaXY+YCk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWEgSW5wdXQgdGlwbyBOdW1lcmljbyBjb21vIGVsZW1lbnRvIERvbVxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gcHJvcHMgLSBjb25maWcgcGFyYSBJbnB1dFxuICAgKiBAcGFyYW0ge09iamVjdH0gZGF0YURheSAtIHZhbG9yZXMgZGUgaXRlbSB5IERpYSwgb3BjaW9uYWxcbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gZGVsIGlucHV0IGNyZWFkb1xuICAgKi9cbiAgY3JlYXRlSW5wdXROdW1iZXIocHJvcHMsIGRhdGFEYXkpIHtcbiAgICBsZXQgdmFsdWUgPSBcIlwiO1xuICAgIGlmIChkYXRhRGF5ICYmIGRhdGFEYXkudmFsdWVzKSB7XG4gICAgICB2YWx1ZSA9IHV0aWxzLmdldFZhckJ5UGF0aChkYXRhRGF5LCBwcm9wcy52YXJOYW1lKTtcbiAgICB9XG4gICAgdmFsdWUgPSB2YWx1ZSB8fCBcIlwiO1xuXG4gICAgbGV0IGVsZW0gPSBkb20uY3JlYXRlRWxlbWVudEZyb21IVE1MKGBcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiaW5wdXQtc2VjdGlvbiAke3Byb3BzLmNsYXNzTmFtZXMgfHwgXCJcIn1cIiBpbnB1dC1rZXk9XCIke1xuICAgICAgcHJvcHMua2V5IHx8IFwiXCJcbiAgICB9XCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaW5wdXQtc2VjdGlvbi10aXRsZVwiPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtc3VidGl0bGVcIj5cbiAgICAgICAgICAgICAgICAke3Byb3BzLmxhYmVsfVxuICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC1zdWJ0aXRsZS0yIFwiPlxuICAgICAgICAgICAgICAgICR7cHJvcHMuc3VmZml4ID8gXCIoXCIgKyBwcm9wcy5zdWZmaXggKyBcIilcIiA6IFwiXCJ9XG4gICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJuYXYtaW5wdXRcIlxuICAgICAgICAgICAgICAgICAgdmFsdWU9XCIke3ZhbHVlfVwiPlxuICAgICAgICAgIDwvZGl2PmApO1xuXG4gICAgbGV0IGlucHV0RWxlbSA9IGVsZW0ucXVlcnlTZWxlY3RvcihcImlucHV0XCIpO1xuICAgIHRoaXMuYWRkS2V5RG93bklucHV0RXZlbnRzKGlucHV0RWxlbSk7XG5cbiAgICByZXR1cm4gZWxlbTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBJbnB1dCB0aXBvIEZJbGVwaWNrZXIgY29tbyBlbGVtZW50byBEb21cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IHByb3BzIC0gY29uZmlnIHBhcmEgSW5wdXRcbiAgICogQHBhcmFtIHtPYmplY3R9IGRhdGFEYXkgLSB2YWxvcmVzIGRlIGl0ZW0geSBEaWEsIG9wY2lvbmFsXG4gICAqIEByZXR1cm4ge09iamVjdH0gRWxlbWVudG8gRG9tIGRlbCBpbnB1dCBjcmVhZG9cbiAgICovXG4gIGNyZWF0ZUlucHV0RmlsZShwcm9wcywgZGF0YURheSkge1xuICAgIGxldCB2YWx1ZSA9IFwiXCI7XG4gICAgbGV0IGZpbGVOYW1lID0gXCJcIjtcbiAgICBsZXQgZmlsZVBhdGggPSBcIlwiO1xuXG4gICAgaWYgKGRhdGFEYXkgJiYgZGF0YURheS52YWx1ZXMpIHtcbiAgICAgIHZhbHVlID0gdXRpbHMuZ2V0VmFyQnlQYXRoKGRhdGFEYXksIHByb3BzLnZhck5hbWUpO1xuICAgICAgZmlsZU5hbWUgPSB1dGlscy5nZXRWYXJCeVBhdGgoZGF0YURheSwgcHJvcHMuZmlsZU5hbWVWYWx1ZSk7XG4gICAgICBmaWxlUGF0aCA9IHV0aWxzLmdldFZhckJ5UGF0aChkYXRhRGF5LCBwcm9wcy5maWxlUGF0aFZhbHVlKTtcbiAgICB9XG5cbiAgICB2YWx1ZSA9IHZhbHVlIHx8IFwiXCI7XG4gICAgZmlsZU5hbWUgPSBmaWxlTmFtZSB8fCBcIlwiO1xuICAgIGZpbGVQYXRoID0gZmlsZVBhdGggfHwgXCJcIjtcblxuICAgIGxldCBlbGVtID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChgXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb24gJHtwcm9wcy5jbGFzc05hbWVzIHx8IFwiXCJ9XCIgaW5wdXQta2V5PVwiJHtcbiAgICAgIHByb3BzLmtleSB8fCBcIlwiXG4gICAgfVwiPlxuXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaW5wdXQtc2VjdGlvbi10aXRsZVwiPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtc3VidGl0bGVcIj5cbiAgICAgICAgICAgICAgICAke3Byb3BzLmxhYmVsfVxuICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm5hdi1pbnB1dC1maWxlXCIgPlxuICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwic21hbGwtY2xvc2UgY2xlYXItZmlsZS1pbnB1dFwiPng8L2J1dHRvbj5cbiAgICAgICAgICAgICAgPGxhYmVsID5cbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm5hdi1pbnB1dC1maWxlLWxhYmVsXCI+XG4gICAgICAgICAgICAgICAgICAke3Byb3BzLnBpY2tlckxhYmVsIHx8IFwiU2VsZWNjaW9uYXIgQXJjaGl2b1wifVxuICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cImZpbGVcIiB2YWx1ZT1cIiR7dmFsdWV9XCI+XG4gICAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb24tbGlua1wiPlxuICAgICAgICAgICAgICA8YSBocmVmPVwiJHtmaWxlUGF0aH1cIiB0YXJnZXQ9XCJfYmxhbmtcIiA+XG4gICAgICAgICAgICAgICAgJHtmaWxlTmFtZX1cbiAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8L2Rpdj5gKTtcblxuICAgIGxldCAkaW5wdXRFbGVtID0gZWxlbS5xdWVyeVNlbGVjdG9yKFwiaW5wdXRcIik7XG4gICAgbGV0ICRjbGVhckJ0biA9IGVsZW0ucXVlcnlTZWxlY3RvcihcIi5jbGVhci1maWxlLWlucHV0XCIpO1xuICAgIGxldCAkZmlsZUlucHV0TGFiZWwgPSBlbGVtLnF1ZXJ5U2VsZWN0b3IoXCIubmF2LWlucHV0LWZpbGUtbGFiZWxcIik7XG5cbiAgICAkaW5wdXRFbGVtLmFkZEV2ZW50TGlzdGVuZXIoXCJjaGFuZ2VcIiwgKGV2dCkgPT4ge1xuICAgICAgbGV0IGZpbGVOYW1lID0gJGlucHV0RWxlbS5maWxlc1swXS5uYW1lO1xuICAgICAgJGZpbGVJbnB1dExhYmVsLnRleHRDb250ZW50ID0gZmlsZU5hbWU7XG4gICAgfSk7XG5cbiAgICAkY2xlYXJCdG4uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIChldnQpID0+IHtcbiAgICAgICRpbnB1dEVsZW0udmFsdWUgPSBcIlwiO1xuICAgICAgJGZpbGVJbnB1dExhYmVsLnRleHRDb250ZW50ID0gcHJvcHMucGlja2VyTGFiZWwgfHwgXCJTZWxlY2Npb25hciBBcmNoaXZvXCI7XG4gICAgICBldnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gZWxlbTtcbiAgfSxcblxuXG4gIGNyZWF0ZUZpbGVMaW5rKHByb3BzLCBkYXRhRGF5KSB7XG4gICAgbGV0IGZpbGVOYW1lID0gXCJcIjtcbiAgICBsZXQgZmlsZVBhdGggPSBcIlwiO1xuXG4gICAgaWYgKGRhdGFEYXkgJiYgZGF0YURheS52YWx1ZXMpIHtcbiAgICAgIC8vdmFsdWUgPSB1dGlscy5nZXRWYXJCeVBhdGgoZGF0YURheSwgcHJvcHMudmFyTmFtZSk7XG4gICAgICBmaWxlTmFtZSA9IHV0aWxzLmdldFZhckJ5UGF0aChkYXRhRGF5LCBwcm9wcy5maWxlTmFtZVZhbHVlKTtcbiAgICAgIGZpbGVQYXRoID0gdXRpbHMuZ2V0VmFyQnlQYXRoKGRhdGFEYXksIHByb3BzLmZpbGVQYXRoVmFsdWUpO1xuICAgIH1cblxuICAgIGlmKGZpbGVOYW1lID09IFwiXCIpIHJldHVybiBudWxsOyBcblxuICAgIGZpbGVOYW1lID0gZmlsZU5hbWUgfHwgXCJcIjtcbiAgICBmaWxlUGF0aCA9IGZpbGVQYXRoIHx8IFwiXCI7XG5cbiAgICBsZXQgZWxlbSA9IGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoYFxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1zZWN0aW9uICR7cHJvcHMuY2xhc3NOYW1lcyB8fCBcIlwifVwiIGlucHV0LWtleT1cIiR7XG4gICAgICBwcm9wcy5rZXkgfHwgXCJcIlxuICAgIH1cIj5cblxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb24tdGl0bGVcIj5cbiAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LXN1YnRpdGxlXCI+XG4gICAgICAgICAgICAgICAgJHtwcm9wcy5sYWJlbH1cbiAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1zZWN0aW9uLWxpbmtcIj5cbiAgICAgICAgICAgICAgPGEgaHJlZj1cIiR7ZmlsZVBhdGh9XCIgdGFyZ2V0PVwiX2JsYW5rXCIgPlxuICAgICAgICAgICAgICAgICR7ZmlsZU5hbWV9XG4gICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgPC9kaXY+YCk7XG5cbiAgICByZXR1cm4gZWxlbTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBsaXN0YSBkZSBJbnB1dHMsIGNvbiBhcnJheSBkZSB2YWxvcmVzLCBjb21vIGVsZW1lbnRvIERvbVxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gcHJvcHMgLSBjb25maWcgcGFyYSBJbnB1dFxuICAgKiBAcGFyYW0ge09iamVjdH0gZGF0YURheSAtIHZhbG9yZXMgZGUgaXRlbSB5IERpYSwgb3BjaW9uYWxcbiAgICogQHBhcmFtIHtPYmplY3R9IFtkYXlTZWxlY3RlZCA9IG51bGxdIC0gZGF0b3MgZGVsIGRpYSBzZWxlY2Npb25hZG9cbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gZGVsIGlucHV0IGNyZWFkb1xuICAgKi9cbiAgY3JlYXRlSW5wdXRMaXN0KHByb3BzLCBkYXRhRGF5LCBkYXlTZWxlY3RlZCA9IG51bGwpIHtcbiAgICBsZXQgdmFsdWUgPSBudWxsO1xuICAgIGxldCBpbnB1dExpc3QgPSBbXTtcblxuICAgIC8vb2J0aWVuZSBpbnB1dHMgZGVmYXVsdCwgcGFyYSBjcmVhcmxvcywgc2luIHZhbG9yZXNcbiAgICBpZiAoXG4gICAgICBkYXlTZWxlY3RlZCAmJlxuICAgICAgQXJyYXkuaXNBcnJheShkYXlTZWxlY3RlZC5pdGVtLnZhbHVlc1twcm9wcy5pbnB1dExpc3RdKVxuICAgICkge1xuICAgICAgaW5wdXRMaXN0ID0gZGF5U2VsZWN0ZWQuaXRlbS52YWx1ZXNbcHJvcHMuaW5wdXRMaXN0XS5tYXAoKGlucHV0Um93KSA9PiB7XG4gICAgICAgIC8vbGltcGlhIGlucHV0TGlzdCBpbnB1dHNcbiAgICAgICAgaW5wdXRSb3cuaW5wdXRzLm1hcCgoaW5wdXQpID0+IHtcbiAgICAgICAgICBpbnB1dC52YWx1ZSA9IG51bGw7XG4gICAgICAgICAgcmV0dXJuIGlucHV0O1xuICAgICAgICB9KTtcblxuICAgICAgICAvL29idGllbmUgdmFsb3JlcyBkZWwgZGlhXG4gICAgICAgIGlmIChkYXRhRGF5ICYmIGRhdGFEYXkudmFsdWVzKSB7XG4gICAgICAgICAgbGV0IGlucHV0VmFsdWVzID0gdXRpbHMuZ2V0VmFyQnlQYXRoKGRhdGFEYXksIHByb3BzLnZhbHVlc1BhdGgpO1xuXG4gICAgICAgICAgLy9hdXRvcnJlbGxlbmFcbiAgICAgICAgICBpZiAoaW5wdXRWYWx1ZXMpIHtcbiAgICAgICAgICAgIGlucHV0Um93LmlucHV0cy5mb3JFYWNoKChpbnB1dCkgPT4ge1xuICAgICAgICAgICAgICBsZXQgdmFsdWVzID0gaW5wdXRWYWx1ZXMuZmluZCgodikgPT4gdi5pZCA9PSBpbnB1dFJvdy5pZCk7XG4gICAgICAgICAgICAgIGlucHV0LnZhbHVlID0gdmFsdWVzID8gdmFsdWVzW2lucHV0LnZhck5hbWVdIDogbnVsbDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBpbnB1dFJvdztcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGxldCBzdHIgPSBgPGRpdiBpbnB1dC1rZXk9XCIke3Byb3BzLmtleSB8fCBcIlwifVwiID5gO1xuICAgIGlucHV0TGlzdC5mb3JFYWNoKChpbnB1dFJvdykgPT4ge1xuICAgICAgc3RyICs9IGBcbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1zZWN0aW9uIFwiID5cbiAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtc3VidGl0bGVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICR7aW5wdXRSb3cubGFiZWx9XG4gICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPmA7XG5cbiAgICAgIGlucHV0Um93LmlucHV0cy5mb3JFYWNoKChpbnB1dCkgPT4ge1xuICAgICAgICBzdHIgKz0gYCBcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb24tY29sXCIgPlxuICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC1zdWJ0aXRsZSBcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICR7aW5wdXQubGFiZWx9XG4gICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwibnVtYmVyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1pZD1cIiR7aW5wdXRSb3cuaWR9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1sYWJlbD1cIiR7aW5wdXQubGFiZWx9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cIm5hdi1pbnB1dFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9XCIke2lucHV0LnZhbHVlfVwiPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgfSk7XG4gICAgICBzdHIgKz0gYFxuICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICB9KTtcbiAgICBzdHIgKz0gYDwvZGl2PmA7XG5cbiAgICBsZXQgZWxlbSA9IGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoc3RyKTtcblxuICAgIGxldCBpbnB1dHNFbGVtID0gZWxlbS5xdWVyeVNlbGVjdG9yQWxsKFwiaW5wdXRcIik7XG4gICAgaW5wdXRzRWxlbS5mb3JFYWNoKChpbnB1dEVsZW0pID0+IHRoaXMuYWRkS2V5RG93bklucHV0RXZlbnRzKGlucHV0RWxlbSkpO1xuICAgIHJldHVybiBlbGVtO1xuICB9LFxuXG5cbiAgY3JlYXRlSW5wdXRTZWxlY3QocHJvcHMsIGRhdGFEYXksIGRheVNlbGVjdGVkID0gbnVsbCkge1xuICAgIGxldCB2YWx1ZSA9IG51bGw7XG4gICAgbGV0IG9wdGlvbnMgPSBwcm9wcy5vcHRpb25zO1xuXG4gICAgaWYgKGRhdGFEYXkgJiYgZGF0YURheS52YWx1ZXMpIHtcbiAgICAgIGxldCB2YWwgPSB1dGlscy5nZXRWYXJCeVBhdGgoZGF0YURheSwgcHJvcHMudmFyTmFtZSk7XG4gICAgICB2YWx1ZSA9IHZhbCA/IHZhbC52YWx1ZSA6IG51bGw7XG4gICAgfVxuXG4gICAgbGV0IHN0ciA9IGA8ZGl2IGlucHV0LWtleT1cIiR7cHJvcHMua2V5IHx8IFwiXCJ9XCIgPlxuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb24gXCIgPlxuICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC1zdWJ0aXRsZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgJHtwcm9wcy5sYWJlbH1cbiAgICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XG5cbiAgICAgICAgICAgICAgICAgICAgICA8c2VsZWN0IGNsYXNzPVwiaW5wdXQtc2VsZWN0XCI+XG5cbiAgICAgICAgICAgICAgICAgPG9wdGlvbiB2YWx1ZT1cIlwiICR7dmFsdWUgPT0gbnVsbCA/ICdzZWxlY3RlZCcgOiAnJ30+XG4gICAgICAgICAgICAgICAgICAke3Byb3BzLm5vRGF0YUxhYmVsIHx8IFwiLS0gc2luIGFzaWduYXIgLS1cIn1cbiAgICAgICAgICAgICAgICAgPC9vcHRpb24+XG5cbiAgICAgICAgYDtcblxuXG4gICAgICBvcHRpb25zLmZvckVhY2goKG9wdGlvbikgPT4ge1xuICAgICAgICBzdHIgKz0gYFxuICAgICAgICAgICAgICAgICA8b3B0aW9uIHZhbHVlPVwiJHtvcHRpb24uaWR9XCIgJHtvcHRpb24uaWQgPT0gdmFsdWUgPyAnc2VsZWN0ZWQnIDogJyd9PlxuICAgICAgICAgICAgICAgICAke29wdGlvbi5sYWJlbH1cbiAgICAgICAgICAgICAgICAgPC9vcHRpb24+XG4gICAgICAgICAgICAgICAgYDtcbiAgICAgIH0pO1xuICAgICAgc3RyICs9IGBcblxuICAgICAgICAgICAgICAgICAgICAgIDwvc2VsZWN0PlxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgIDwvZGl2PmA7XG5cbiAgICBsZXQgZWxlbSA9IGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoc3RyKTtcblxuICAgIHJldHVybiBlbGVtO1xuICB9LFxuXG4gIC8qKlxuICAgKiBDcmVhIElucHV0IGRlIHRleHRvIFRleHRBcmVhIGNvbW8gZWxlbWVudG8gRG9tXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwcm9wcyAtIGNvbmZpZyBwYXJhIElucHV0XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhRGF5IC0gdmFsb3JlcyBkZSBpdGVtIHkgRGlhLCBvcGNpb25hbFxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBkZWwgaW5wdXQgY3JlYWRvXG4gICAqL1xuICBjcmVhdGVJbnB1dFRleHRBcmVhKHByb3BzLCBkYXRhRGF5KSB7XG4gICAgbGV0IHZhbHVlID0gXCJcIjtcbiAgICBpZiAoZGF0YURheSAmJiBkYXRhRGF5LnZhbHVlcykge1xuICAgICAgdmFsdWUgPSB1dGlscy5nZXRWYXJCeVBhdGgoZGF0YURheSwgcHJvcHMudmFyTmFtZSk7XG4gICAgfVxuICAgIGxldCBlbGVtID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChgXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb25cIiBpbnB1dC1rZXk9XCIke3Byb3BzLmtleSB8fCBcIlwifVwiPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LXN1YnRpdGxlIGQtYmxvY2tcIj5cbiAgICAgICAgICAgICAgJHtwcm9wcy5sYWJlbH1cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDx0ZXh0YXJlYSBjbGFzcz1cIlwiIHZhbHVlPVwiJHt2YWx1ZX1cIj48L3RleHRhcmVhPlxuICAgICAgICAgIDwvZGl2PmApO1xuXG4gICAgbGV0IGlucHV0RWxlbSA9IGVsZW0ucXVlcnlTZWxlY3RvcihcInRleHRhcmVhXCIpO1xuICAgIHRoaXMuYWRkS2V5RG93bklucHV0RXZlbnRzKGlucHV0RWxlbSk7XG4gICAgcmV0dXJuIGVsZW07XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWEgSW5wdXQgZGUgTWVuc2FqZSBjb21vIGVsZW1lbnRvIERvbVxuICAgKiB1dGlsaXphIFRleHRBcmVhXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwcm9wcyAtIGNvbmZpZyBwYXJhIElucHV0XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhRGF5IC0gdmFsb3JlcyBkZSBpdGVtIHkgRGlhLCBvcGNpb25hbFxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBkZWwgaW5wdXQgY3JlYWRvXG4gICAqL1xuICBjcmVhdGVJbnB1dE1lc3NhZ2UocHJvcHMsIGRhdGFEYXkpIHtcbiAgICBsZXQgdmFsdWUgPSBkYXRhRGF5ID8gdXRpbHMuZ2V0VmFyQnlQYXRoKGRhdGFEYXksIHByb3BzLnZhck5hbWUpIDogbnVsbDtcbiAgICBsZXQgZWxlbSA9IGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoYFxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1zZWN0aW9uIG1zai1pbnB1dC1jb250YWluZXJcIlxuICAgICAgICAgICAgICBpbnB1dC1rZXk9XCIke3Byb3BzLmtleSB8fCBcIlwifVwiPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LXN1YnRpdGxlIGQtYmxvY2tcIj5cbiAgICAgICAgICAgICAgTWVuc2FqZVxuICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgPHRleHRhcmVhIGNsYXNzPVwibXNqXCI+JHt2YWx1ZSB8fCBcIlwifTwvdGV4dGFyZWE+XG4gICAgICAgICAgPC9kaXY+YCk7XG5cbiAgICBsZXQgaW5wdXRFbGVtID0gZWxlbS5xdWVyeVNlbGVjdG9yKFwidGV4dGFyZWFcIik7XG4gICAgLy90aGlzLmFkZEtleURvd25JbnB1dEV2ZW50cyhpbnB1dEVsZW0pO1xuICAgIHJldHVybiBlbGVtO1xuICB9LFxuXG4gIC8qKlxuICAgKiBDcmVhIElucHV0IGRlIHRleHRvIGNvbW8gZWxlbWVudG8gRG9tXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwcm9wcyAtIGNvbmZpZyBwYXJhIElucHV0XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhRGF5IC0gdmFsb3JlcyBkZSBpdGVtIHkgRGlhLCBvcGNpb25hbFxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBkZWwgaW5wdXQgY3JlYWRvXG4gICAqL1xuICBjcmVhdGVJbnB1dFRleHQocHJvcHMsIGRhdGFEYXkpIHtcbiAgICBsZXQgdmFsdWUgPSBcIlwiO1xuICAgIGlmIChkYXRhRGF5ICYmIGRhdGFEYXkudmFsdWVzKSB7XG4gICAgICB2YWx1ZSA9IHV0aWxzLmdldFZhckJ5UGF0aChkYXRhRGF5LCBwcm9wcy52YXJOYW1lKTtcbiAgICB9XG4gICAgbGV0IGVsZW0gPSBkb20uY3JlYXRlRWxlbWVudEZyb21IVE1MKGBcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiaW5wdXQtc2VjdGlvblwiIGlucHV0LWtleT1cIiR7cHJvcHMua2V5IHx8IFwiXCJ9XCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtc3VidGl0bGUgZC1ibG9ja1wiPlxuICAgICAgICAgICAgICAke3Byb3BzLmxhYmVsfVxuICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgY2xhc3M9XCJuYXYtaW5wdXRcIiB2YWx1ZT1cIiR7dmFsdWV9XCI+XG4gICAgICAgICAgPC9kaXY+YCk7XG5cbiAgICBsZXQgaW5wdXRFbGVtID0gZWxlbS5xdWVyeVNlbGVjdG9yKFwiaW5wdXRcIik7XG4gICAgdGhpcy5hZGRLZXlEb3duSW5wdXRFdmVudHMoaW5wdXRFbGVtKTtcbiAgICByZXR1cm4gZWxlbTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYSBJbnB1dCBOdW1lcm8gRmxvdGFudGUsIGNvbW8gZWxlbWVudG8gRG9tXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwcm9wcyAtIGNvbmZpZyBwYXJhIElucHV0XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhRGF5IC0gdmFsb3JlcyBkZSBpdGVtIHkgRGlhLCBvcGNpb25hbFxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBkZWwgaW5wdXQgY3JlYWRvXG4gICAqL1xuICBjcmVhdGVJbnB1dEZsb2F0KHByb3BzLCBkYXRhRGF5KSB7XG4gICAgbGV0IHZhbHVlID0gXCJcIjtcbiAgICBpZiAoZGF0YURheSAmJiBkYXRhRGF5LnZhbHVlcykge1xuICAgICAgdmFsdWUgPSB1dGlscy5nZXRWYXJCeVBhdGgoZGF0YURheSwgcHJvcHMudmFyTmFtZSk7XG4gICAgfVxuICAgIGxldCBlbGVtID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChgXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb25cIiBpbnB1dC1rZXk9XCIke3Byb3BzLmtleSB8fCBcIlwifVwiPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LXN1YnRpdGxlIGQtYmxvY2tcIj5cbiAgICAgICAgICAgICAgJHtwcm9wcy5sYWJlbH1cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwibnVtYmVyXCIgY2xhc3M9XCJuYXYtaW5wdXRcIiB2YWx1ZT1cIiR7dmFsdWV9XCI+XG4gICAgICAgICAgPC9kaXY+YCk7XG5cbiAgICBsZXQgaW5wdXRFbGVtID0gZWxlbS5xdWVyeVNlbGVjdG9yKFwiaW5wdXRcIik7XG4gICAgdGhpcy5hZGRLZXlEb3duSW5wdXRFdmVudHMoaW5wdXRFbGVtKTtcbiAgICByZXR1cm4gZWxlbTtcbiAgfSxcblxuXG5cblxuXG5cbiAgY3JlYXRlTGlzdChwcm9wcywgZGF0YURheSkge1xuICAgIGxldCB2YWx1ZSA9IFtdO1xuICAgIGlmIChkYXRhRGF5ICYmIGRhdGFEYXkudmFsdWVzKSB7XG4gICAgICB2YWx1ZSA9IHV0aWxzLmdldFZhckJ5UGF0aChkYXRhRGF5LCBwcm9wcy52YXJOYW1lKTtcbiAgICB9XG5cbiAgICBsZXQgdGFic0NvbnRhaW5lciA9IFwiXCI7XG5cbiAgICBpZiAocHJvcHMudGFicykge1xuICAgICAgbGV0IHRhYnMgPSBcIlwiO1xuICAgICAgcHJvcHMudGFicy5mb3JFYWNoKCh0YWIpID0+IHtcbiAgICAgICAgdGFicyArPSBgXG4gICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1ib3gtdGFiXCIgdGFiLWtleT1cIiR7dGFiLmtleX1cIj5cbiAgICAgICAgICAke3RhYi5uYW1lfVxuICAgICAgICA8L2Rpdj5gO1xuICAgICAgfSk7XG5cbiAgICAgIHRhYnNDb250YWluZXIgPSBgXG4gICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1ib3gtdGFiLWNvbnRhaW5lclwiPlxuICAgICAgICAke3RhYnN9XG4gICAgICAgIDwvZGl2PlxuICAgICAgYDtcbiAgICB9XG5cbiAgICBsZXQgY2xvc2VJY29uID0gYDxzcGFuIGNsYXNzPVwiY2xvc2UtaWNvblwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxzdmcgc3R5bGU9XCJ3aWR0aDoyNHB4O2hlaWdodDoyNHB4XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBmaWxsPVwiY3VycmVudENvbG9yXCIgZD1cIk0xOSw2LjQxTDE3LjU5LDVMMTIsMTAuNTlMNi40MSw1TDUsNi40MUwxMC41OSwxMkw1LDE3LjU5TDYuNDEsMTlMMTIsMTMuNDFMMTcuNTksMTlMMTksMTcuNTlMMTMuNDEsMTJMMTksNi40MVpcIiAvPlxuICAgICAgICAgICAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgICAgICAgICAgICA8L3NwYW4+YDtcblxuICAgIGxldCBsaW5rSWNvbiA9IGAgPHNwYW4gY2xhc3M9XCJjbG9zZS1pY29uXCI+XG4gICAgICAgICAgICAgICAgICAgICAgPHN2ZyBzdHlsZT1cIndpZHRoOjI0cHg7aGVpZ2h0OjI0cHhcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGZpbGw9XCJjdXJyZW50Q29sb3JcIiBkPVwiTTE0LDNWNUgxNy41OUw3Ljc2LDE0LjgzTDkuMTcsMTYuMjRMMTksNi40MVYxMEgyMVYzTTE5LDE5SDVWNUgxMlYzSDVDMy44OSwzIDMsMy45IDMsNVYxOUEyLDIgMCAwLDAgNSwyMUgxOUEyLDIgMCAwLDAgMjEsMTlWMTJIMTlWMTlaXCIgLz5cbiAgICAgICAgICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgIGA7XG5cbiAgICBsZXQgc2VhcmNoSW5wdXQ9IGBcbiAgICAgIDxkaXYgY2xhc3M9XCJzZWFyY2gtaW5wdXQtY29udGFpbmVyXCI+XG4gICAgICAgIDxpbnB1dCBpZD1cIlwiIHR5cGU9XCJ0ZXh0XCIgbmFtZT1cIlwiIGNsYXNzPVwic2VhcmNoLWlucHV0XCIgcGxhY2Vob2xkZXI9XCJidXNjYXJcIj5cbiAgICAgICAgPGJ1dHRvbiBjbGFzcz1cInNlYXJjaC1pbnB1dC1jbGVhclwiPlxuICAgICAgICAgJHtjbG9zZUljb259XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgYDtcblxuXG5cbiAgICBsZXQgc3RyID0gYFxuICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb25cIiBpbnB1dC1rZXk9XCIke3Byb3BzLmtleSB8fCBcIlwifVwiPlxuICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtc3VidGl0bGUgZC1ibG9ja1wiPlxuICAgICAgICAgICAgICAke3Byb3BzLmxhYmVsfVxuICAgICAgICAgICAgPC9zcGFuPlxuXG4gICAgICAgICAgICAke3RhYnNDb250YWluZXJ9XG4gICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1ib3ggXCIgaW5wdXQta2V5PVwiJHtwcm9wcy5rZXkgfHwgXCJcIn1cIj5cblxuICAgICAgICAgICAgJHtzZWFyY2hJbnB1dH1cbiAgICAgIGA7XG5cbiAgICAvL1RPRE8gb2J0ZW5lciBpbnB1dCBzZWd1biBmaWxhXG4gICAgaWYgKHByb3BzLmlucHV0cykge1xuICAgICAgcHJvcHMuaW5wdXRzLmZvckVhY2goKGkpID0+IHtcbiAgICAgICAgaWYoaS5pc1RpdGxlKXtcblxuICAgICAgICAgIGxldCB0b29sdGlwID0gXCJcIjtcbiAgICAgICAgICBsZXQgaWNvbiA9IFwiXCI7XG5cbiAgICAgICAgICBpZiAoaS50b29sdGlwKSB7XG4gICAgICAgICAgICB0b29sdGlwID0gYFxuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1pbmktaW5wdXQtc2VjdGlvbi0tdG9vbHRpcFwiPlxuICAgICAgICAgICAgICAgICAgICAke2kudG9vbHRpcH1cbiAgICAgICAgICAgICAgICAgICAgJHtpLnN1ZmZpeCA/IFwiKFwiICsgaS5zdWZmaXggKyBcIilcIiA6IFwiXCJ9XG4gICAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChpLmNvbG9ySWNvbikge1xuICAgICAgICAgICAgaWYgKHV0aWxzLmlzSGV4Q29sb3IoaS5jb2xvckljb24pKSB7XG4gICAgICAgICAgICAgIGljb24gPSBgPGRpdiBjbGFzcz1cIm1pbmktaW5wdXQtc2VjdGlvbi0taWNvblwiIHN0eWxlPVwiYmFja2dyb3VuZDoke2kuY29sb3JJY29ufVwiPiA8L2Rpdj5gO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaWNvbiA9IGA8ZGl2IGNsYXNzPVwibWluaS1pbnB1dC1zZWN0aW9uLS1pY29uICR7aS5jb2xvckljb259XCI+IDwvZGl2PmA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG5cbiAgICAgICAgc3RyICs9IGBcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtaW5pLWlucHV0LXNlY3Rpb24gaXMtdGl0bGVcIiBpbnB1dC10YWIta2V5PVwiJHtpLnRhYktleSB8fCBcIlwifVwiIGxhYmVsPVwiJHtpLmxhYmVsfVwiPlxuICAgICAgICAgICAgICA8bGFiZWw+XG4gICAgICAgICAgICAgICAgJHtpY29ufVxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtaW5pLWlucHV0LXNlY3Rpb24tLXRpdGxlIHRydW5jYXRlXCI+XG4gICAgICAgICAgICAgICAgICAke2kubGFiZWx9XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgICAgICR7dG9vbHRpcH1cbiAgICAgICAgICAgIDwvZGl2PmA7XG5cblxuXG4gICAgICAgIH1lbHNle1xuICAgICAgICAgIGxldCB2YWx1ZV9mb3VuZCA9IHZhbHVlID8gdmFsdWUuZmluZCgodmFsKSA9PiB2YWwuaWQgPT0gaS5pZCkgOiBudWxsO1xuICAgICAgICAgIGxldCB2ID0gdmFsdWVfZm91bmQgfHwgXCJcIjtcbiAgICAgICAgICBsZXQgaW5wdXRWYWx1ZSA9cHJvcHMudmFyTmFtZUlucHV0ICYmIHZbcHJvcHMudmFyTmFtZUlucHV0IF0gPyB2W3Byb3BzLnZhck5hbWVJbnB1dCBdIDogdi52YWx1ZTtcbiAgICAgICAgICBsZXQgdG9vbHRpcCA9IFwiXCI7XG4gICAgICAgICAgbGV0IGljb24gPSBcIlwiO1xuICAgICAgICAgIGxldCBsaW5rID0gXCJcIjtcblxuICAgICAgICAgIGlmIChpLnRvb2x0aXApIHtcbiAgICAgICAgICAgIHRvb2x0aXAgPSBgXG4gICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWluaS1pbnB1dC1zZWN0aW9uLS10b29sdGlwXCI+XG4gICAgICAgICAgICAgICAgICAgICR7aS50b29sdGlwfVxuICAgICAgICAgICAgICAgICAgPC9kaXY+YDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoaS5jb2xvckljb24pIHtcbiAgICAgICAgICAgIGlmICh1dGlscy5pc0hleENvbG9yKGkuY29sb3JJY29uKSkge1xuICAgICAgICAgICAgICBpY29uID0gYDxkaXYgY2xhc3M9XCJtaW5pLWlucHV0LXNlY3Rpb24tLWljb25cIiBzdHlsZT1cImJhY2tncm91bmQ6JHtpLmNvbG9ySWNvbn1cIj4gPC9kaXY+YDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGljb24gPSBgPGRpdiBjbGFzcz1cIm1pbmktaW5wdXQtc2VjdGlvbi0taWNvbiAke2kuY29sb3JJY29ufVwiPiA8L2Rpdj5gO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmKGkubGluayl7XG4gICAgICAgICAgICBsaW5rID0gYDxhIGNsYXNzPVwibWluaS1pbnB1dC1zZWN0aW9uLS1saW5rXCIgdGFyZ2V0PVwiX2JsYW5rXCIgaHJlZj1cIiR7aS5saW5rfVwiPlxuICAgICAgICAgICAgICAgICR7bGlua0ljb259XG4gICAgICAgICAgICAgICAgPC9hPiBgXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgc3RyICs9IGBcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtaW5pLWlucHV0LXNlY3Rpb25cIiBpbnB1dC10YWIta2V5PVwiJHtpLnRhYktleSB8fCBcIlwifVwiIGxhYmVsPVwiJHtpLmxhYmVsfVwiPlxuICAgICAgICAgICAgICA8bGFiZWw+XG5cbiAgICAgICAgICAgICAgICAke2ljb259XG5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWluaS1pbnB1dC1zZWN0aW9uLS1uYW1lIHRydW5jYXRlXCI+XG4gICAgICAgICAgICAgICAgICAke2kubGFiZWx9XG4gICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWluaS1pbnB1dC1zZWN0aW9uLS1zdWZmaXhcIiA+JHtcbiAgICAgICAgICAgICAgICAgIGkuc3VmZml4ID8gXCIoXCIgKyBpLnN1ZmZpeCArIFwiKVwiIDogXCJcIlxuICAgICAgICAgICAgICAgIH08L2Rpdj5cblxuICAgICAgICAgICAgICAgICR7bGlua31cblxuICAgICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWluaS1pbnB1dC1zZWN0aW9uLS1mb290ZXJcIj5cbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInN0YXJ0XCI+IHRlc3QgPC9zcGFuPlxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZW5kXCI+IHRlc3QgZW5kIDwvc3Bhbj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICR7dG9vbHRpcH1cbiAgICAgICAgICAgIDwvZGl2PmA7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHN0ciArPSBgXG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+IGA7XG5cbiAgICBsZXQgJGVsID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChzdHIpO1xuICAgIGxldCAkdGFicyA9ICRlbC5xdWVyeVNlbGVjdG9yQWxsKFwiLmlucHV0LWJveC10YWJbdGFiLWtleV1cIikgfHwgW107XG4gICAgbGV0ICRzZWFyY2hJbnB1dCA9ICRlbC5xdWVyeVNlbGVjdG9yKFwiLnNlYXJjaC1pbnB1dFwiKSB8fCBudWxsO1xuICAgIGxldCAkc2VhcmNoSW5wdXRDbGVhciA9ICRlbC5xdWVyeVNlbGVjdG9yKFwiLnNlYXJjaC1pbnB1dC1jbGVhclwiKSB8fCBudWxsO1xuXG4gICAgJHRhYnMuZm9yRWFjaCgodCkgPT4ge1xuICAgICAgdC5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGUpID0+IHtcbiAgICAgICAgdGhpcy5zZWxlY3RJbnB1dEJveFRhYih0LCAkZWwpO1xuICAgICAgICAkc2VhcmNoSW5wdXQudmFsdWUgPSBcIlwiO1xuICAgICAgICAkc2VhcmNoSW5wdXQuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoJ2lucHV0Jywge2J1YmJsZXM6dHJ1ZX0pKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaWYoJHNlYXJjaElucHV0Q2xlYXIpe1xuICAgICAgJHNlYXJjaElucHV0Q2xlYXIuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGUgPT4ge1xuICAgICAgICAkc2VhcmNoSW5wdXQudmFsdWUgPSBcIlwiO1xuICAgICAgICAkc2VhcmNoSW5wdXQuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoJ2lucHV0Jywge2J1YmJsZXM6dHJ1ZX0pKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmKCRzZWFyY2hJbnB1dCl7XG4gICAgICAkc2VhcmNoSW5wdXQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsZSA9PiB7XG4gICAgICAgIGlmKGUua2V5ID09PSBcIkVzY2FwZVwiKXtcbiAgICAgICAgICAkc2VhcmNoSW5wdXQudmFsdWUgPSBcIlwiO1xuICAgICAgICAgICRzZWFyY2hJbnB1dC5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudCgnaW5wdXQnLCB7YnViYmxlczp0cnVlfSkpO1xuICAgICAgICB9XG4gICAgICB9KTsgXG5cbiAgICAgICRzZWFyY2hJbnB1dC5hZGRFdmVudExpc3RlbmVyKFwiaW5wdXRcIiwgZSA9PiB7XG4gICAgICAgIGxldCAkdGFiU2VsZWN0ZWQgPSAkZWwucXVlcnlTZWxlY3RvcihcIi5pbnB1dC1ib3gtdGFiW3RhYi1rZXldLmFjdGl2ZVwiKSB8fCBudWxsO1xuICAgICAgICBsZXQgJGlucHV0cyA9IFtdO1xuICAgICAgICBpZigkdGFiU2VsZWN0ZWQpe1xuICAgICAgICAgIGxldCB0YWJLZXkgPSAkdGFiU2VsZWN0ZWQuZ2V0QXR0cmlidXRlKFwidGFiLWtleVwiKTtcbiAgICAgICAgICAkaW5wdXRzID0gJGVsLnF1ZXJ5U2VsZWN0b3JBbGwoXCIubWluaS1pbnB1dC1zZWN0aW9uW2lucHV0LXRhYi1rZXk9J1wiK3RhYktleStcIiddXCIpIHx8IFtdO1xuICAgICAgICB9ZWxzZXtcbiAgICAgICAgICAkaW5wdXRzID0gJGVsLnF1ZXJ5U2VsZWN0b3JBbGwoXCIubWluaS1pbnB1dC1zZWN0aW9uXCIpIHx8IFtdO1xuICAgICAgICB9XG4gICAgICAgICRpbnB1dHMuZm9yRWFjaCgkaSA9PiB7XG4gICAgICAgICAgbGV0IGxhYmVsID0gJGkuZ2V0QXR0cmlidXRlKFwibGFiZWxcIik7XG4gICAgICAgICAgbGV0IHNlYXJjaCA9ICRzZWFyY2hJbnB1dC52YWx1ZTtcbiAgICAgICAgICBpZihsYWJlbC50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHNlYXJjaC50b0xvd2VyQ2FzZSgpKSl7XG4gICAgICAgICAgICAkaS5jbGFzc0xpc3QucmVtb3ZlKFwiaGlkZVwiKTtcbiAgICAgICAgICB9ZWxzZXtcbiAgICAgICAgICAgICRpLmNsYXNzTGlzdC5hZGQoXCJoaWRlXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB0aGlzLnNlbGVjdElucHV0Qm94VGFiKF8uZmlyc3QoJHRhYnMpLCAkZWwpO1xuXG4gICAgcmV0dXJuICRlbDtcbiAgfSxcblxuXG5cblxuXG4gIC8qKlxuICAgKiBDcmVhIElucHV0Qm94LCBjb21vIGVsZW1lbnRvIERvbVxuICAgKiB1biBJbnB1dEJveCBlcyB1biBjb250ZW5lZG9yIGNvbiB1bmEgbGlzdGEgZGUgaW5wdXRzXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwcm9wcyAtIGNvbmZpZyBwYXJhIElucHV0XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhRGF5IC0gdmFsb3JlcyBkZSBpdGVtIHkgRGlhLCBvcGNpb25hbFxuICAgKiBAcmV0dXJuIHtPYmplY3R9IEVsZW1lbnRvIERvbSBkZWwgaW5wdXQgY3JlYWRvXG4gICAqL1xuICBjcmVhdGVJbnB1dEJveChwcm9wcywgZGF0YURheSkge1xuICAgIGxldCB2YWx1ZSA9IFtdO1xuICAgIGlmIChkYXRhRGF5ICYmIGRhdGFEYXkudmFsdWVzKSB7XG4gICAgICB2YWx1ZSA9IHV0aWxzLmdldFZhckJ5UGF0aChkYXRhRGF5LCBwcm9wcy52YXJOYW1lKTtcbiAgICB9XG5cbiAgICBsZXQgdGFic0NvbnRhaW5lciA9IFwiXCI7XG5cbiAgICBpZiAocHJvcHMudGFicykge1xuICAgICAgbGV0IHRhYnMgPSBcIlwiO1xuICAgICAgcHJvcHMudGFicy5mb3JFYWNoKCh0YWIpID0+IHtcbiAgICAgICAgdGFicyArPSBgXG4gICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1ib3gtdGFiXCIgdGFiLWtleT1cIiR7dGFiLmtleX1cIj5cbiAgICAgICAgICAke3RhYi5uYW1lfVxuICAgICAgICA8L2Rpdj5gO1xuICAgICAgfSk7XG5cbiAgICAgIHRhYnNDb250YWluZXIgPSBgXG4gICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1ib3gtdGFiLWNvbnRhaW5lclwiPlxuICAgICAgICAke3RhYnN9XG4gICAgICAgIDwvZGl2PlxuICAgICAgYDtcbiAgICB9XG5cbiAgICBsZXQgY2xvc2VJY29uID0gYDxzcGFuIGNsYXNzPVwiY2xvc2UtaWNvblwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxzdmcgc3R5bGU9XCJ3aWR0aDoyNHB4O2hlaWdodDoyNHB4XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBmaWxsPVwiY3VycmVudENvbG9yXCIgZD1cIk0xOSw2LjQxTDE3LjU5LDVMMTIsMTAuNTlMNi40MSw1TDUsNi40MUwxMC41OSwxMkw1LDE3LjU5TDYuNDEsMTlMMTIsMTMuNDFMMTcuNTksMTlMMTksMTcuNTlMMTMuNDEsMTJMMTksNi40MVpcIiAvPlxuICAgICAgICAgICAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgICAgICAgICAgICA8L3NwYW4+YDtcblxuICAgIGxldCBsaW5rSWNvbiA9IGAgPHNwYW4gY2xhc3M9XCJjbG9zZS1pY29uXCI+XG4gICAgICAgICAgICAgICAgICAgICAgPHN2ZyBzdHlsZT1cIndpZHRoOjI0cHg7aGVpZ2h0OjI0cHhcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGZpbGw9XCJjdXJyZW50Q29sb3JcIiBkPVwiTTE0LDNWNUgxNy41OUw3Ljc2LDE0LjgzTDkuMTcsMTYuMjRMMTksNi40MVYxMEgyMVYzTTE5LDE5SDVWNUgxMlYzSDVDMy44OSwzIDMsMy45IDMsNVYxOUEyLDIgMCAwLDAgNSwyMUgxOUEyLDIgMCAwLDAgMjEsMTlWMTJIMTlWMTlaXCIgLz5cbiAgICAgICAgICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgIGA7XG5cbiAgICBsZXQgc2VhcmNoSW5wdXQ9IGBcbiAgICAgIDxkaXYgY2xhc3M9XCJzZWFyY2gtaW5wdXQtY29udGFpbmVyXCI+XG4gICAgICAgIDxpbnB1dCBpZD1cIlwiIHR5cGU9XCJ0ZXh0XCIgbmFtZT1cIlwiIGNsYXNzPVwic2VhcmNoLWlucHV0XCIgcGxhY2Vob2xkZXI9XCJidXNjYXJcIj5cbiAgICAgICAgPGJ1dHRvbiBjbGFzcz1cInNlYXJjaC1pbnB1dC1jbGVhclwiPlxuICAgICAgICAgJHtjbG9zZUljb259XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgYDtcblxuXG5cbiAgICBsZXQgc3RyID0gYFxuICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb25cIiBpbnB1dC1rZXk9XCIke3Byb3BzLmtleSB8fCBcIlwifVwiPlxuICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtc3VidGl0bGUgZC1ibG9ja1wiPlxuICAgICAgICAgICAgICAke3Byb3BzLmxhYmVsfVxuICAgICAgICAgICAgPC9zcGFuPlxuXG4gICAgICAgICAgICAke3RhYnNDb250YWluZXJ9XG4gICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1ib3ggXCIgaW5wdXQta2V5PVwiJHtwcm9wcy5rZXkgfHwgXCJcIn1cIj5cblxuICAgICAgICAgICAgJHtzZWFyY2hJbnB1dH1cbiAgICAgIGA7XG5cbiAgICBpZiAocHJvcHMuaW5wdXRzKSB7XG4gICAgICBwcm9wcy5pbnB1dHMuZm9yRWFjaCgoaSkgPT4ge1xuICAgICAgICBpZihpLmlzVGl0bGUpe1xuXG4gICAgICAgICAgbGV0IHRvb2x0aXAgPSBcIlwiO1xuICAgICAgICAgIGxldCBpY29uID0gXCJcIjtcblxuICAgICAgICAgIGlmIChpLnRvb2x0aXApIHtcbiAgICAgICAgICAgIHRvb2x0aXAgPSBgXG4gICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWluaS1pbnB1dC1zZWN0aW9uLS10b29sdGlwXCI+XG4gICAgICAgICAgICAgICAgICAgICR7aS50b29sdGlwfVxuICAgICAgICAgICAgICAgICAgICAke2kuc3VmZml4ID8gXCIoXCIgKyBpLnN1ZmZpeCArIFwiKVwiIDogXCJcIn1cbiAgICAgICAgICAgICAgICAgIDwvZGl2PmA7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGkuY29sb3JJY29uKSB7XG4gICAgICAgICAgICBpZiAodXRpbHMuaXNIZXhDb2xvcihpLmNvbG9ySWNvbikpIHtcbiAgICAgICAgICAgICAgaWNvbiA9IGA8ZGl2IGNsYXNzPVwibWluaS1pbnB1dC1zZWN0aW9uLS1pY29uXCIgc3R5bGU9XCJiYWNrZ3JvdW5kOiR7aS5jb2xvckljb259XCI+IDwvZGl2PmA7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBpY29uID0gYDxkaXYgY2xhc3M9XCJtaW5pLWlucHV0LXNlY3Rpb24tLWljb24gJHtpLmNvbG9ySWNvbn1cIj4gPC9kaXY+YDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cblxuICAgICAgICBzdHIgKz0gYFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1pbmktaW5wdXQtc2VjdGlvbiBpcy10aXRsZVwiIGlucHV0LXRhYi1rZXk9XCIke2kudGFiS2V5IHx8IFwiXCJ9XCIgbGFiZWw9XCIke2kubGFiZWx9XCI+XG4gICAgICAgICAgICAgIDxsYWJlbD5cbiAgICAgICAgICAgICAgICAke2ljb259XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1pbmktaW5wdXQtc2VjdGlvbi0tdGl0bGUgdHJ1bmNhdGVcIj5cbiAgICAgICAgICAgICAgICAgICR7aS5sYWJlbH1cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgICAgICAgJHt0b29sdGlwfVxuICAgICAgICAgICAgPC9kaXY+YDtcblxuXG5cbiAgICAgICAgfWVsc2V7XG4gICAgICAgICAgbGV0IHZhbHVlX2ZvdW5kID0gdmFsdWUgPyB2YWx1ZS5maW5kKCh2YWwpID0+IHZhbC5pZCA9PSBpLmlkKSA6IG51bGw7XG4gICAgICAgICAgbGV0IHYgPSB2YWx1ZV9mb3VuZCB8fCBcIlwiO1xuICAgICAgICAgIGxldCBpbnB1dFZhbHVlID1wcm9wcy52YXJOYW1lSW5wdXQgJiYgdltwcm9wcy52YXJOYW1lSW5wdXQgXSA/IHZbcHJvcHMudmFyTmFtZUlucHV0IF0gOiB2LnZhbHVlO1xuICAgICAgICAgIGxldCB0b29sdGlwID0gXCJcIjtcbiAgICAgICAgICBsZXQgaWNvbiA9IFwiXCI7XG4gICAgICAgICAgbGV0IGxpbmsgPSBcIlwiO1xuXG4gICAgICAgICAgaWYgKGkudG9vbHRpcCkge1xuICAgICAgICAgICAgdG9vbHRpcCA9IGBcbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtaW5pLWlucHV0LXNlY3Rpb24tLXRvb2x0aXBcIj5cbiAgICAgICAgICAgICAgICAgICAgJHtpLnRvb2x0aXB9XG4gICAgICAgICAgICAgICAgICA8L2Rpdj5gO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChpLmNvbG9ySWNvbikge1xuICAgICAgICAgICAgaWYgKHV0aWxzLmlzSGV4Q29sb3IoaS5jb2xvckljb24pKSB7XG4gICAgICAgICAgICAgIGljb24gPSBgPGRpdiBjbGFzcz1cIm1pbmktaW5wdXQtc2VjdGlvbi0taWNvblwiIHN0eWxlPVwiYmFja2dyb3VuZDoke2kuY29sb3JJY29ufVwiPiA8L2Rpdj5gO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaWNvbiA9IGA8ZGl2IGNsYXNzPVwibWluaS1pbnB1dC1zZWN0aW9uLS1pY29uICR7aS5jb2xvckljb259XCI+IDwvZGl2PmA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYoaS5saW5rKXtcbiAgICAgICAgICAgIGxpbmsgPSBgPGEgY2xhc3M9XCJtaW5pLWlucHV0LXNlY3Rpb24tLWxpbmtcIiB0YXJnZXQ9XCJfYmxhbmtcIiBocmVmPVwiJHtpLmxpbmt9XCI+XG4gICAgICAgICAgICAgICAgJHtsaW5rSWNvbn1cbiAgICAgICAgICAgICAgICA8L2E+IGBcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBzdHIgKz0gYFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1pbmktaW5wdXQtc2VjdGlvblwiIGlucHV0LXRhYi1rZXk9XCIke2kudGFiS2V5IHx8IFwiXCJ9XCIgbGFiZWw9XCIke2kubGFiZWx9XCI+XG4gICAgICAgICAgICAgIDxsYWJlbD5cbiAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cIm51bWJlclwiXG4gICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJtaW5pLWlucHV0XCJcbiAgICAgICAgICAgICAgICAgICAgICBpbnB1dC1pZD1cIiR7aS5pZCB8fCBcIlwifVwiXG4gICAgICAgICAgICAgICAgICAgICAgaW5wdXQta2V5PVwiJHtpLmtleSB8fCBpLmxhYmVsfVwiXG4gICAgICAgICAgICAgICAgICAgICAgdmFsdWU9XCIke2lucHV0VmFsdWUgfHwgXCJcIn1cIj5cblxuICAgICAgICAgICAgICAgICR7aWNvbn1cblxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtaW5pLWlucHV0LXNlY3Rpb24tLW5hbWUgdHJ1bmNhdGVcIj5cbiAgICAgICAgICAgICAgICAgICR7aS5sYWJlbH1cbiAgICAgICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtaW5pLWlucHV0LXNlY3Rpb24tLXN1ZmZpeFwiID4ke1xuICAgICAgICAgICAgICAgICAgaS5zdWZmaXggPyBcIihcIiArIGkuc3VmZml4ICsgXCIpXCIgOiBcIlwiXG4gICAgICAgICAgICAgICAgfTwvZGl2PlxuXG4gICAgICAgICAgICAgICAgJHtsaW5rfVxuXG4gICAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgICAgICR7dG9vbHRpcH1cbiAgICAgICAgICAgIDwvZGl2PmA7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHN0ciArPSBgXG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+IGA7XG5cbiAgICBsZXQgJGVsID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChzdHIpO1xuICAgIGxldCAkdGFicyA9ICRlbC5xdWVyeVNlbGVjdG9yQWxsKFwiLmlucHV0LWJveC10YWJbdGFiLWtleV1cIikgfHwgW107XG4gICAgbGV0ICRpbnB1dHMgPSAkZWwucXVlcnlTZWxlY3RvckFsbChcImlucHV0Lm1pbmktaW5wdXRcIikgfHwgW107XG4gICAgbGV0ICRzZWFyY2hJbnB1dCA9ICRlbC5xdWVyeVNlbGVjdG9yKFwiLnNlYXJjaC1pbnB1dFwiKSB8fCBudWxsO1xuICAgIGxldCAkc2VhcmNoSW5wdXRDbGVhciA9ICRlbC5xdWVyeVNlbGVjdG9yKFwiLnNlYXJjaC1pbnB1dC1jbGVhclwiKSB8fCBudWxsO1xuXG4gICAgJHRhYnMuZm9yRWFjaCgodCkgPT4ge1xuICAgICAgdC5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGUpID0+IHtcbiAgICAgICAgdGhpcy5zZWxlY3RJbnB1dEJveFRhYih0LCAkZWwpO1xuICAgICAgICAkc2VhcmNoSW5wdXQudmFsdWUgPSBcIlwiO1xuICAgICAgICAkc2VhcmNoSW5wdXQuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoJ2lucHV0Jywge2J1YmJsZXM6dHJ1ZX0pKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaWYoJHNlYXJjaElucHV0Q2xlYXIpe1xuICAgICAgJHNlYXJjaElucHV0Q2xlYXIuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGUgPT4ge1xuICAgICAgICAkc2VhcmNoSW5wdXQudmFsdWUgPSBcIlwiO1xuICAgICAgICAkc2VhcmNoSW5wdXQuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoJ2lucHV0Jywge2J1YmJsZXM6dHJ1ZX0pKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmKCRzZWFyY2hJbnB1dCl7XG4gICAgICAkc2VhcmNoSW5wdXQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsZSA9PiB7XG4gICAgICAgIGlmKGUua2V5ID09PSBcIkVzY2FwZVwiKXtcbiAgICAgICAgICAkc2VhcmNoSW5wdXQudmFsdWUgPSBcIlwiO1xuICAgICAgICAgICRzZWFyY2hJbnB1dC5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudCgnaW5wdXQnLCB7YnViYmxlczp0cnVlfSkpO1xuICAgICAgICB9XG4gICAgICB9KTsgXG5cbiAgICAgICRzZWFyY2hJbnB1dC5hZGRFdmVudExpc3RlbmVyKFwiaW5wdXRcIiwgZSA9PiB7XG4gICAgICAgIGxldCAkdGFiU2VsZWN0ZWQgPSAkZWwucXVlcnlTZWxlY3RvcihcIi5pbnB1dC1ib3gtdGFiW3RhYi1rZXldLmFjdGl2ZVwiKSB8fCBudWxsO1xuICAgICAgICBsZXQgJGlucHV0cyA9IFtdO1xuICAgICAgICBpZigkdGFiU2VsZWN0ZWQpe1xuICAgICAgICAgIGxldCB0YWJLZXkgPSAkdGFiU2VsZWN0ZWQuZ2V0QXR0cmlidXRlKFwidGFiLWtleVwiKTtcbiAgICAgICAgICAkaW5wdXRzID0gJGVsLnF1ZXJ5U2VsZWN0b3JBbGwoXCIubWluaS1pbnB1dC1zZWN0aW9uW2lucHV0LXRhYi1rZXk9J1wiK3RhYktleStcIiddXCIpIHx8IFtdO1xuICAgICAgICB9ZWxzZXtcbiAgICAgICAgICAkaW5wdXRzID0gJGVsLnF1ZXJ5U2VsZWN0b3JBbGwoXCIubWluaS1pbnB1dC1zZWN0aW9uXCIpIHx8IFtdO1xuICAgICAgICB9XG4gICAgICAgICRpbnB1dHMuZm9yRWFjaCgkaSA9PiB7XG4gICAgICAgICAgbGV0IGxhYmVsID0gJGkuZ2V0QXR0cmlidXRlKFwibGFiZWxcIik7XG4gICAgICAgICAgbGV0IHNlYXJjaCA9ICRzZWFyY2hJbnB1dC52YWx1ZTtcbiAgICAgICAgICBpZihsYWJlbC50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHNlYXJjaC50b0xvd2VyQ2FzZSgpKSl7XG4gICAgICAgICAgICAkaS5jbGFzc0xpc3QucmVtb3ZlKFwiaGlkZVwiKTtcbiAgICAgICAgICB9ZWxzZXtcbiAgICAgICAgICAgICRpLmNsYXNzTGlzdC5hZGQoXCJoaWRlXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB0aGlzLnNlbGVjdElucHV0Qm94VGFiKF8uZmlyc3QoJHRhYnMpLCAkZWwpO1xuXG4gICAgJGlucHV0cy5mb3JFYWNoKChpKSA9PiB0aGlzLmFkZEtleURvd25JbnB1dEV2ZW50cyhpKSk7XG5cbiAgICByZXR1cm4gJGVsO1xuICB9LFxuXG4gIHNlbGVjdElucHV0Qm94VGFiKCR0YWIsICRlbCkge1xuICAgIGxldCAkdGFicyA9ICRlbC5xdWVyeVNlbGVjdG9yQWxsKFwiLmlucHV0LWJveC10YWJbdGFiLWtleV1cIikgfHwgW107XG4gICAgbGV0ICRpbnB1dFNlY3Rpb25zID0gJGVsLnF1ZXJ5U2VsZWN0b3JBbGwoXCIubWluaS1pbnB1dC1zZWN0aW9uXCIpIHx8IFtdO1xuXG4gICAgJHRhYnMuZm9yRWFjaCgodCkgPT4ge1xuICAgICAgdC5jbGFzc0xpc3QucmVtb3ZlKFwiYWN0aXZlXCIpO1xuICAgIH0pO1xuXG4gICAgaWYgKCR0YWIpIHtcbiAgICAgICR0YWIuY2xhc3NMaXN0LmFkZChcImFjdGl2ZVwiKTtcblxuICAgICAgJGlucHV0U2VjdGlvbnMuZm9yRWFjaCgoaSkgPT4ge1xuICAgICAgICBsZXQga2V5ID0gaS5nZXRBdHRyaWJ1dGUoXCJpbnB1dC10YWIta2V5XCIpO1xuICAgICAgICBpZiAoa2V5ID09ICR0YWIuZ2V0QXR0cmlidXRlKFwidGFiLWtleVwiKSkge1xuICAgICAgICAgIGkuY2xhc3NMaXN0LnJlbW92ZShcImhpZGVcIik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaS5jbGFzc0xpc3QuYWRkKFwiaGlkZVwiKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9LFxuXG4gIC8qKlxuICAgKiBDcmVhIENoZWNrYm94LCBjb21vIGVsZW1lbnRvIERvbVxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gcHJvcHMgLSBjb25maWcgcGFyYSBJbnB1dFxuICAgKiBAcGFyYW0ge09iamVjdH0gZGF0YURheSAtIHZhbG9yZXMgZGUgaXRlbSB5IERpYSwgb3BjaW9uYWxcbiAgICogQHJldHVybiB7T2JqZWN0fSBFbGVtZW50byBEb20gZGVsIGlucHV0IGNyZWFkb1xuICAgKi9cbiAgY3JlYXRlSW5wdXRDaGVja2JveChwcm9wcywgZGF0YURheSkge1xuICAgIGxldCB2YWx1ZSA9IFwiXCI7XG4gICAgaWYgKGRhdGFEYXkgJiYgZGF0YURheS52YWx1ZXMpIHtcbiAgICAgIHZhbHVlID0gdXRpbHMuZ2V0VmFyQnlQYXRoKGRhdGFEYXksIHByb3BzLnZhck5hbWUpO1xuICAgIH1cbiAgICBsZXQgciA9IGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwoYFxuICAgICAgPGRpdiBjbGFzcz1cImlucHV0LXNlY3Rpb25cIiBpbnB1dC1rZXk9XCIke3Byb3BzLmtleSB8fCBcIlwifVwiPlxuICAgICAgICA8bGFiZWw+XG4gICAgICAgICAgPGlucHV0IHR5cGU9XCJjaGVja2JveFwiIG5hbWU9XCIke3Byb3BzLmtleSB8fCBcIlwifVwiIGlucHV0LWtleT1cIiR7XG4gICAgICBwcm9wcy5rZXkgfHwgXCJcIlxuICAgIH1cIiAke3ZhbHVlID8gXCJjaGVja2VkXCIgOiBcIlwifT5cbiAgICAgICAgICAke3Byb3BzLmxhYmVsfVxuICAgICAgICA8L2xhYmVsPlxuICAgICAgPC9kaXY+YCk7XG5cbiAgICByZXR1cm4gcjtcbiAgfSxcblxuICBjcmVhdGVJbnB1dEJ1dHRvbihwcm9wcykge1xuICAgIGxldCByID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChgXG4gICAgICA8ZGl2IGNsYXNzPVwiaW5wdXQtc2VjdGlvblwiIGlucHV0LWtleT1cIiR7cHJvcHMua2V5IHx8IFwiXCJ9XCI+XG4gICAgICAgICAgPGJ1dHRvbiBuYW1lPVwiJHtwcm9wcy5rZXkgfHwgXCJcIn1cIiBpbnB1dC1rZXk9XCIkeyBwcm9wcy5rZXkgfHwgXCJcIiB9XCIgIGNsYXNzPVwiY2FwLWJ0bi1vdXRsaW5lXCI+XG4gICAgICAgICAgICAke3Byb3BzLmxhYmVsfVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+YCk7XG5cbiAgICBsZXQgYnV0dG9uID0gci5xdWVyeVNlbGVjdG9yKFwiYnV0dG9uXCIpO1xuICAgIGJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgZSA9PiBwcm9wcy5vbkNsaWNrKHtwcm9wcywgZXZlbnQ6ZX0pKVxuXG4gICAgcmV0dXJuIHI7XG4gIH0sXG5cbiAgYWRkS2V5RG93bklucHV0RXZlbnRzKGlucHV0KSB7XG4gICAgaW5wdXQuYWRkRXZlbnRMaXN0ZW5lcihcImtleWRvd25cIiwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICBpZiAoZXZlbnQua2V5Q29kZSA9PT0gMTMpIHtcbiAgICAgICAgLy9FTlRFUlxuICAgICAgICBpbnB1dC5kaXNwYXRjaEV2ZW50KFxuICAgICAgICAgIG5ldyBDdXN0b21FdmVudChcInNhdmVNdWx0aUlucHV0XCIsIHtcbiAgICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKGV2ZW50LmtleUNvZGUgPT09IDI3KSB7XG4gICAgICAgIC8vRVNDXG4gICAgICAgIGlucHV0LmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgbmV3IEN1c3RvbUV2ZW50KFwiY2FuY2VsTXVsdGlJbnB1dFwiLCB7XG4gICAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSxcblxuICBjcmVhdGVDb250ZXh0TWVudSh7XG4gICAgY29uZmlnLFxuICAgICRjYXBpYmFyYUVsZW0gPSBudWxsLFxuICAgIGV2dCA9IG51bGwsXG4gICAgZGF0ZSA9IG51bGwsXG4gICAgaXRlbSA9IG51bGwsXG4gICAgc2VsZWN0ZWQgPSBbXSxcbiAgICB0YWJTZWxlY3RlZCA9IG51bGwsXG4gICAgbGVmdCA9IG51bGwsXG4gICAgdG9wID0gbnVsbCxcbiAgICBuYW1lID0gXCJcIixcbiAgfSkge1xuICAgIGlmIChjb25maWcudGltZWxpbmUuY29udGV4dE1lbnUgPT09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB7IGVsZW06IG51bGwsIGlzVmlzaWJsZTogZmFsc2UgfTtcblxuICAgIGxldCBjbGFzc05hbWUgPSBcIlwiO1xuICAgIGxldCBzdHlsZSA9IFwiXCI7XG4gICAgbGV0IHN0ckh0bWwgPSBcIlwiO1xuICAgIGxldCBsZWZ0UG9zaXRpb24gPSBudWxsO1xuICAgIGxldCB0b3BQb3NpdGlvbiA9IG51bGw7XG4gICAgbGV0IGlzVmlzaWJsZSA9IHRydWU7XG4gICAgbGV0IGJvdW5kUmVjdENhcGliYXJhID0gbnVsbDtcbiAgICBsZXQgZ2FwID0gMTU7IC8vcHhcblxuICAgIGlmKCRjYXBpYmFyYUVsZW0pe1xuICAgICAgYm91bmRSZWN0Q2FwaWJhcmEgPSAkY2FwaWJhcmFFbGVtLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIH1cblxuICAgIGlmIChldnQgJiYgYm91bmRSZWN0Q2FwaWJhcmEpIHtcbiAgICAgIGxlZnQgPSBldnQuY2xpZW50WDtcbiAgICAgIHRvcCA9IGV2dC5jbGllbnRZIC0gYm91bmRSZWN0Q2FwaWJhcmEudG9wO1xuICAgIH1cblxuICAgIGlmIChsZWZ0KSB7XG4gICAgICBsZWZ0UG9zaXRpb24gPSBsZWZ0O1xuICAgIH1cblxuICAgIGlmICh0b3ApIHtcbiAgICAgIHRvcFBvc2l0aW9uID0gdG9wO1xuICAgIH1cblxuXG5cbiAgICBpZiAoKGxlZnRQb3NpdGlvbiAhPT0gbnVsbCkgJiAodG9wUG9zaXRpb24gIT09IG51bGwpKSB7XG5cblxuICAgICAgaWYoYm91bmRSZWN0Q2FwaWJhcmEpe1xuICAgICAgICBsZXQgdHJhbnNmb3JtU3R5bGUgPSBcIlwiO1xuICAgICAgICBpZih0b3BQb3NpdGlvbiA+IGJvdW5kUmVjdENhcGliYXJhLmhlaWdodCoyLzYgJiYgdG9wUG9zaXRpb24gPD0gYm91bmRSZWN0Q2FwaWJhcmEuaGVpZ2h0KjQvNil7XG4gICAgICAgICAgdHJhbnNmb3JtU3R5bGUrPSBgdHJhbnNsYXRlWSgtNTAlKWA7XG4gICAgICAgIH1cbiAgICAgICAgaWYodG9wUG9zaXRpb24gPiBib3VuZFJlY3RDYXBpYmFyYS5oZWlnaHQqNC82KXtcbiAgICAgICAgICB0cmFuc2Zvcm1TdHlsZSs9IGB0cmFuc2xhdGVZKC0xMDAlKWA7XG4gICAgICAgIH1cblxuICAgICAgICBpZihsZWZ0UG9zaXRpb24+IGJvdW5kUmVjdENhcGliYXJhLndpZHRoKjQvNil7XG4gICAgICAgICAgdHJhbnNmb3JtU3R5bGUrPSBgdHJhbnNsYXRlWCgtMTAwJSlgO1xuICAgICAgICAgIGxlZnRQb3NpdGlvbiAtPSBnYXA7XG4gICAgICAgIH1lbHNle1xuICAgICAgICAgIGxlZnRQb3NpdGlvbiArPSBnYXA7XG4gICAgICAgIH1cbiAgICAgICAgaWYodHJhbnNmb3JtU3R5bGUgIT1cIlwiKXtcbiAgICAgICAgICAgIHN0eWxlICs9IGAgdHJhbnNmb3JtOiAke3RyYW5zZm9ybVN0eWxlfTtgO1xuICAgICAgICB9XG4gICAgICB9XG5cblxuICAgICAgc3R5bGUgKz0gYHRvcDogJHt0b3BQb3NpdGlvbn1weDsgbGVmdDogJHtsZWZ0UG9zaXRpb259cHg7YDtcblxuICAgIH0gZWxzZSB7XG4gICAgICBjbGFzc05hbWUgKz0gXCJjbS1oaWRlXCI7XG4gICAgICBpc1Zpc2libGUgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBzdHJIdG1sICs9IGAgPGRpdiBjbGFzcz1cImNhcC1jb250ZXh0LW1lbnUtY29udGFpbmVyICR7Y2xhc3NOYW1lfVwiPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY2FwLWNvbnRleHQtbWVudVwiIHN0eWxlPVwiJHtzdHlsZX1cIj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgIDwvZGl2PmA7XG5cbiAgICBsZXQgJGNvbnRleHRNZW51Q29udGFpbmVyID0gZG9tLmNyZWF0ZUVsZW1lbnRGcm9tSFRNTChzdHJIdG1sKTtcbiAgICBsZXQgJGNvbnRleHRNZW51ID0gJGNvbnRleHRNZW51Q29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoXCIuY2FwLWNvbnRleHQtbWVudVwiKTtcblxuICAgIGNvbmZpZy50aW1lbGluZS5jb250ZXh0TWVudS5vcHRpb25zLmZvckVhY2goKG9wdGlvbikgPT4ge1xuXG4gICAgICBpZiAob3B0aW9uLnNob3dJZikge1xuICAgICAgICBsZXQgc2hvdyA9IG9wdGlvbi5zaG93SWYoeyBpdGVtLCBkYXRlLCBzZWxlY3RlZCwgbmFtZSwgdGFiU2VsZWN0ZWQgfSk7XG4gICAgICAgIGlmICghc2hvdykgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBsZXQgaXNFbmFibGVkID0gdHJ1ZTtcbiAgICAgIGxldCBpc0NsaWNrZWFibGUgPSB0cnVlO1xuICAgICAgaWYgKG9wdGlvbi5lbmFibGVJZikge1xuICAgICAgICBpc0VuYWJsZWQgPSBvcHRpb24uZW5hYmxlSWYoe1xuICAgICAgICAgIGl0ZW0sXG4gICAgICAgICAgZGF0ZSxcbiAgICAgICAgICBzZWxlY3RlZCxcbiAgICAgICAgICBuYW1lLFxuICAgICAgICAgIHRhYlNlbGVjdGVkLFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgbGV0IG9wdGlvbkNsYXNzTmFtZSA9IFwiXCI7XG4gICAgICBsZXQgc3RySWNvbiA9IFwiXCI7XG4gICAgICBsZXQgbGFiZWwgPSBcIlwiO1xuXG4gICAgICBpZiAoIWlzRW5hYmxlZCkge1xuICAgICAgICBvcHRpb25DbGFzc05hbWUgKz0gXCJpcy1kaXNhYmxlZCBcIjtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbi5pc0RpdmlkZXIpIHtcbiAgICAgICAgaXNDbGlja2VhYmxlID0gZmFsc2U7XG4gICAgICAgIG9wdGlvbkNsYXNzTmFtZSArPSBcImlzLWRpdmlkZXIgXCI7XG4gICAgICB9XG5cbiAgICAgIGlmKG9wdGlvbi5sYWJlbCl7XG4gICAgICAgIGxhYmVsID0gYDxzcGFuPiR7b3B0aW9uLmxhYmVsfTwvc3Bhbj5gO1xuICAgICAgfVxuXG5cbiAgICAgIGlmIChvcHRpb24uaWNvbikge1xuICAgICAgICBzdHJJY29uID0gYDxkaXYgY2xhc3M9XCJjYXAtY29udGV4dC1tZW51X2l0ZW1faWNvblwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxzdmcgdmlld0JveD1cIjAgMCAyNCAyNFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHBhdGggZD1cIiR7b3B0aW9uLmljb259XCIgLz5cbiAgICAgICAgICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgICAgICAgIDwvZGl2PmA7XG4gICAgICB9XG5cbiAgICAgIGxldCBvcHRpb25TdHJIdG1sID0gYFxuICAgICAgICA8ZGl2IGNsYXNzPVwiY2FwLWNvbnRleHQtbWVudV9pdGVtICR7b3B0aW9uQ2xhc3NOYW1lfVwiPlxuICAgICAgICAgICR7c3RySWNvbn1cbiAgICAgICAgICAke2xhYmVsfVxuICAgICAgICA8L2Rpdj5gO1xuXG4gICAgICBsZXQgJG9wdGlvbiA9IGRvbS5jcmVhdGVFbGVtZW50RnJvbUhUTUwob3B0aW9uU3RySHRtbCk7XG5cbiAgICAgIGlmIChpc0VuYWJsZWQgJiYgaXNDbGlja2VhYmxlKSB7XG4gICAgICAgICRvcHRpb24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIChldnRDbGljaykgPT5cbiAgICAgICAgICBvcHRpb24ub25DbGljayh7XG4gICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICBldnQ6IGV2dENsaWNrLFxuICAgICAgICAgICAgZGF0ZSxcbiAgICAgICAgICAgIGl0ZW0sXG4gICAgICAgICAgICBzZWxlY3RlZCxcbiAgICAgICAgICAgIHRhYlNlbGVjdGVkLFxuICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAkb3B0aW9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCAoZXZ0Q2xpY2spID0+IHtcbiAgICAgICAgICBldnRDbGljay5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgIGV2dENsaWNrLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgJGNvbnRleHRNZW51LmFwcGVuZCgkb3B0aW9uKTtcbiAgICB9KTtcblxuICAgIHJldHVybiB7XG4gICAgICBlbGVtOiAkY29udGV4dE1lbnVDb250YWluZXIsXG4gICAgICBpc1Zpc2libGUsXG4gICAgfTtcbiAgfSxcbn07XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFFQTtBQUFBO0FBQUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQURBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBREE7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUVBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFGQTtBQUZBO0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUZBO0FBRkE7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFRQTtBQVFBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRkE7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBSEE7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBRUE7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUdBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFGQTtBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBSEE7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUZBO0FBS0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBREE7QUFIQTtBQVFBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBREE7QUFIQTtBQVFBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBREE7QUFIQTtBQVFBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUZBO0FBSEE7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBREE7QUFIQTtBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFEQTtBQUhBO0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBS0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUpBO0FBSEE7QUFXQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRkE7QUFIQTtBQVNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUlBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFHQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSEE7QUFIQTtBQVVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQU9BO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUE3Q0E7QUErQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQTdDQTtBQStDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQTdDQTtBQStDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBN0NBO0FBK0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUdBO0FBQ0E7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFKQTtBQUhBO0FBV0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUZBO0FBS0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUZBO0FBS0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUhBO0FBSEE7QUFVQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBTkE7QUFIQTtBQWFBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFIQTtBQUhBO0FBVUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUZBO0FBSEE7QUFXQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVFBO0FBQ0E7QUFBQTtBQUNBO0FBREE7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSkE7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQU1BO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUZBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFEQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUVBO0FBQ0E7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUhBO0FBSEE7QUFVQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFIQTtBQUhBO0FBVUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUFBO0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFGQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFGQTtBQUlBO0FBQ0E7QUFDQTtBQUZBO0FBSUE7QUFHQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFGQTtBQUtBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFGQTtBQUtBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFoREE7QUFDQTtBQWtEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRkE7QUFIQTtBQVNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFGQTtBQUhBO0FBU0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUVBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQU1BO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUZBO0FBS0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFGQTtBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVZBO0FBWUE7QUFDQTtBQUFBO0FBQUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFHQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFMQTtBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQU5BO0FBU0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRkE7QUFJQTtBQUNBO0FBeHlIQSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./src/util/tableElements.js\n");
|
|
247
247
|
|
|
248
248
|
/***/ }),
|
|
249
249
|
|