From 9fb0cf72b042944bcad9a26a04e221e80773a9ba Mon Sep 17 00:00:00 2001 From: pvictor Date: Wed, 11 Oct 2023 12:07:04 +0200 Subject: [PATCH] updated uPlot to 1.6.26 --- DESCRIPTION | 4 +- inst/htmlwidgets/uPlot.js | 6441 +------------------------------------ man/uPlot.Rd | 9 +- package-lock.json | 14 +- package.json | 2 +- 5 files changed, 19 insertions(+), 6451 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index ecd7ca1..d3c84f9 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: uPlot Title: Fast Interactive Charts with 'µPlot' 'JavaScript' Library -Version: 0.0.0.9100 +Version: 0.0.0.9200 Authors@R: c(person(given = "Victor", family = "Perrier", @@ -19,7 +19,7 @@ Description: An interface for 'µPlot' 'JavaScript' library in R. License: MIT + file LICENSE Encoding: UTF-8 Roxygen: list(markdown = TRUE) -RoxygenNote: 7.2.1 +RoxygenNote: 7.2.3 Imports: htmlwidgets Depends: diff --git a/inst/htmlwidgets/uPlot.js b/inst/htmlwidgets/uPlot.js index 68225d1..5866f78 100644 --- a/inst/htmlwidgets/uPlot.js +++ b/inst/htmlwidgets/uPlot.js @@ -1,6440 +1 @@ -/******/ (() => { // webpackBootstrap -/******/ "use strict"; -/******/ var __webpack_modules__ = ({ - -/***/ "./node_modules/css-loader/dist/cjs.js!./node_modules/uplot/dist/uPlot.min.css": -/*!*************************************************************************************!*\ - !*** ./node_modules/css-loader/dist/cjs.js!./node_modules/uplot/dist/uPlot.min.css ***! - \*************************************************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) -/* harmony export */ }); -/* harmony import */ var _css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../css-loader/dist/runtime/sourceMaps.js */ "./node_modules/css-loader/dist/runtime/sourceMaps.js"); -/* harmony import */ var _css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../css-loader/dist/runtime/api.js */ "./node_modules/css-loader/dist/runtime/api.js"); -/* harmony import */ var _css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__); -// Imports - - -var ___CSS_LOADER_EXPORT___ = _css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default())); -// Module -___CSS_LOADER_EXPORT___.push([module.id, ".uplot, .uplot *, .uplot *::before, .uplot *::after {box-sizing: border-box;}.uplot {font-family: system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";line-height: 1.5;width: min-content;}.u-title {text-align: center;font-size: 18px;font-weight: bold;}.u-wrap {position: relative;user-select: none;}.u-over, .u-under {position: absolute;}.u-under {overflow: hidden;}.uplot canvas {display: block;position: relative;width: 100%;height: 100%;}.u-axis {position: absolute;}.u-legend {font-size: 14px;margin: auto;text-align: center;}.u-inline {display: block;}.u-inline * {display: inline-block;}.u-inline tr {margin-right: 16px;}.u-legend th {font-weight: 600;}.u-legend th > * {vertical-align: middle;display: inline-block;}.u-legend .u-marker {width: 1em;height: 1em;margin-right: 4px;background-clip: padding-box !important;}.u-inline.u-live th::after {content: \":\";vertical-align: middle;}.u-inline:not(.u-live) .u-value {display: none;}.u-series > * {padding: 4px;}.u-series th {cursor: pointer;}.u-legend .u-off > * {opacity: 0.3;}.u-select {background: rgba(0,0,0,0.07);position: absolute;pointer-events: none;}.u-cursor-x, .u-cursor-y {position: absolute;left: 0;top: 0;pointer-events: none;will-change: transform;z-index: 100;}.u-hz .u-cursor-x, .u-vt .u-cursor-y {height: 100%;border-right: 1px dashed #607D8B;}.u-hz .u-cursor-y, .u-vt .u-cursor-x {width: 100%;border-bottom: 1px dashed #607D8B;}.u-cursor-pt {position: absolute;top: 0;left: 0;border-radius: 50%;border: 0 solid;pointer-events: none;will-change: transform;z-index: 100;/*this has to be !important since we set inline \"background\" shorthand */background-clip: padding-box !important;}.u-axis.u-off, .u-select.u-off, .u-cursor-x.u-off, .u-cursor-y.u-off, .u-cursor-pt.u-off {display: none;}", "",{"version":3,"sources":["webpack://./node_modules/uplot/dist/uPlot.min.css"],"names":[],"mappings":"AAAA,qDAAqD,sBAAsB,CAAC,CAAC,QAAQ,yLAAyL,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,CAAC,UAAU,kBAAkB,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC,SAAS,kBAAkB,CAAC,iBAAiB,CAAC,CAAC,mBAAmB,kBAAkB,CAAC,CAAC,UAAU,gBAAgB,CAAC,CAAC,eAAe,cAAc,CAAC,kBAAkB,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,SAAS,kBAAkB,CAAC,CAAC,WAAW,eAAe,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC,WAAW,cAAc,CAAC,CAAC,aAAa,qBAAqB,CAAC,CAAC,cAAc,kBAAkB,CAAC,CAAC,cAAc,gBAAgB,CAAC,CAAC,kBAAkB,sBAAsB,CAAC,qBAAqB,CAAC,CAAC,qBAAqB,UAAU,CAAC,WAAW,CAAC,iBAAiB,CAAC,uCAAuC,CAAC,CAAC,4BAA4B,YAAY,CAAC,sBAAsB,CAAC,CAAC,iCAAiC,aAAa,CAAC,CAAC,eAAe,YAAY,CAAC,CAAC,cAAc,eAAe,CAAC,CAAC,sBAAsB,YAAY,CAAC,CAAC,WAAW,4BAA4B,CAAC,kBAAkB,CAAC,oBAAoB,CAAC,CAAC,0BAA0B,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAC,sBAAsB,CAAC,YAAY,CAAC,CAAC,sCAAsC,YAAY,CAAC,gCAAgC,CAAC,CAAC,sCAAsC,WAAW,CAAC,iCAAiC,CAAC,CAAC,cAAc,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,eAAe,CAAC,oBAAoB,CAAC,sBAAsB,CAAC,YAAY,CAAC,wEAAwE,CAAC,uCAAuC,CAAC,CAAC,0FAA0F,aAAa,CAAC","sourcesContent":[".uplot, .uplot *, .uplot *::before, .uplot *::after {box-sizing: border-box;}.uplot {font-family: system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";line-height: 1.5;width: min-content;}.u-title {text-align: center;font-size: 18px;font-weight: bold;}.u-wrap {position: relative;user-select: none;}.u-over, .u-under {position: absolute;}.u-under {overflow: hidden;}.uplot canvas {display: block;position: relative;width: 100%;height: 100%;}.u-axis {position: absolute;}.u-legend {font-size: 14px;margin: auto;text-align: center;}.u-inline {display: block;}.u-inline * {display: inline-block;}.u-inline tr {margin-right: 16px;}.u-legend th {font-weight: 600;}.u-legend th > * {vertical-align: middle;display: inline-block;}.u-legend .u-marker {width: 1em;height: 1em;margin-right: 4px;background-clip: padding-box !important;}.u-inline.u-live th::after {content: \":\";vertical-align: middle;}.u-inline:not(.u-live) .u-value {display: none;}.u-series > * {padding: 4px;}.u-series th {cursor: pointer;}.u-legend .u-off > * {opacity: 0.3;}.u-select {background: rgba(0,0,0,0.07);position: absolute;pointer-events: none;}.u-cursor-x, .u-cursor-y {position: absolute;left: 0;top: 0;pointer-events: none;will-change: transform;z-index: 100;}.u-hz .u-cursor-x, .u-vt .u-cursor-y {height: 100%;border-right: 1px dashed #607D8B;}.u-hz .u-cursor-y, .u-vt .u-cursor-x {width: 100%;border-bottom: 1px dashed #607D8B;}.u-cursor-pt {position: absolute;top: 0;left: 0;border-radius: 50%;border: 0 solid;pointer-events: none;will-change: transform;z-index: 100;/*this has to be !important since we set inline \"background\" shorthand */background-clip: padding-box !important;}.u-axis.u-off, .u-select.u-off, .u-cursor-x.u-off, .u-cursor-y.u-off, .u-cursor-pt.u-off {display: none;}"],"sourceRoot":""}]); -// Exports -/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___); - - -/***/ }), - -/***/ "./node_modules/css-loader/dist/runtime/api.js": -/*!*****************************************************!*\ - !*** ./node_modules/css-loader/dist/runtime/api.js ***! - \*****************************************************/ -/***/ ((module) => { - - - -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -module.exports = function (cssWithMappingToString) { - var list = []; // return the list of modules as css string - - list.toString = function toString() { - return this.map(function (item) { - var content = ""; - var needLayer = typeof item[5] !== "undefined"; - - if (item[4]) { - content += "@supports (".concat(item[4], ") {"); - } - - if (item[2]) { - content += "@media ".concat(item[2], " {"); - } - - if (needLayer) { - content += "@layer".concat(item[5].length > 0 ? " ".concat(item[5]) : "", " {"); - } - - content += cssWithMappingToString(item); - - if (needLayer) { - content += "}"; - } - - if (item[2]) { - content += "}"; - } - - if (item[4]) { - content += "}"; - } - - return content; - }).join(""); - }; // import a list of modules into the list - - - list.i = function i(modules, media, dedupe, supports, layer) { - if (typeof modules === "string") { - modules = [[null, modules, undefined]]; - } - - var alreadyImportedModules = {}; - - if (dedupe) { - for (var k = 0; k < this.length; k++) { - var id = this[k][0]; - - if (id != null) { - alreadyImportedModules[id] = true; - } - } - } - - for (var _k = 0; _k < modules.length; _k++) { - var item = [].concat(modules[_k]); - - if (dedupe && alreadyImportedModules[item[0]]) { - continue; - } - - if (typeof layer !== "undefined") { - if (typeof item[5] === "undefined") { - item[5] = layer; - } else { - item[1] = "@layer".concat(item[5].length > 0 ? " ".concat(item[5]) : "", " {").concat(item[1], "}"); - item[5] = layer; - } - } - - if (media) { - if (!item[2]) { - item[2] = media; - } else { - item[1] = "@media ".concat(item[2], " {").concat(item[1], "}"); - item[2] = media; - } - } - - if (supports) { - if (!item[4]) { - item[4] = "".concat(supports); - } else { - item[1] = "@supports (".concat(item[4], ") {").concat(item[1], "}"); - item[4] = supports; - } - } - - list.push(item); - } - }; - - return list; -}; - -/***/ }), - -/***/ "./node_modules/css-loader/dist/runtime/sourceMaps.js": -/*!************************************************************!*\ - !*** ./node_modules/css-loader/dist/runtime/sourceMaps.js ***! - \************************************************************/ -/***/ ((module) => { - - - -module.exports = function (item) { - var content = item[1]; - var cssMapping = item[3]; - - if (!cssMapping) { - return content; - } - - if (typeof btoa === "function") { - var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(cssMapping)))); - var data = "sourceMappingURL=data:application/json;charset=utf-8;base64,".concat(base64); - var sourceMapping = "/*# ".concat(data, " */"); - var sourceURLs = cssMapping.sources.map(function (source) { - return "/*# sourceURL=".concat(cssMapping.sourceRoot || "").concat(source, " */"); - }); - return [content].concat(sourceURLs).concat([sourceMapping]).join("\n"); - } - - return [content].join("\n"); -}; - -/***/ }), - -/***/ "./node_modules/uplot/dist/uPlot.min.css": -/*!***********************************************!*\ - !*** ./node_modules/uplot/dist/uPlot.min.css ***! - \***********************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) -/* harmony export */ }); -/* harmony import */ var _style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !../../style-loader/dist/runtime/injectStylesIntoStyleTag.js */ "./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js"); -/* harmony import */ var _style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! !../../style-loader/dist/runtime/styleDomAPI.js */ "./node_modules/style-loader/dist/runtime/styleDomAPI.js"); -/* harmony import */ var _style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var _style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../../style-loader/dist/runtime/insertBySelector.js */ "./node_modules/style-loader/dist/runtime/insertBySelector.js"); -/* harmony import */ var _style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! !../../style-loader/dist/runtime/setAttributesWithoutAttributes.js */ "./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js"); -/* harmony import */ var _style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! !../../style-loader/dist/runtime/insertStyleElement.js */ "./node_modules/style-loader/dist/runtime/insertStyleElement.js"); -/* harmony import */ var _style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__); -/* harmony import */ var _style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! !../../style-loader/dist/runtime/styleTagTransform.js */ "./node_modules/style-loader/dist/runtime/styleTagTransform.js"); -/* harmony import */ var _style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__); -/* harmony import */ var _css_loader_dist_cjs_js_uPlot_min_css__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! !!../../css-loader/dist/cjs.js!./uPlot.min.css */ "./node_modules/css-loader/dist/cjs.js!./node_modules/uplot/dist/uPlot.min.css"); - - - - - - - - - - - -var options = {}; - -options.styleTagTransform = (_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default()); -options.setAttributes = (_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default()); - - options.insert = _style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default().bind(null, "head"); - -options.domAPI = (_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default()); -options.insertStyleElement = (_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default()); - -var update = _style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default()(_css_loader_dist_cjs_js_uPlot_min_css__WEBPACK_IMPORTED_MODULE_6__["default"], options); - - - - - /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_css_loader_dist_cjs_js_uPlot_min_css__WEBPACK_IMPORTED_MODULE_6__["default"] && _css_loader_dist_cjs_js_uPlot_min_css__WEBPACK_IMPORTED_MODULE_6__["default"].locals ? _css_loader_dist_cjs_js_uPlot_min_css__WEBPACK_IMPORTED_MODULE_6__["default"].locals : undefined); - - -/***/ }), - -/***/ "./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js": -/*!****************************************************************************!*\ - !*** ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js ***! - \****************************************************************************/ -/***/ ((module) => { - - - -var stylesInDOM = []; - -function getIndexByIdentifier(identifier) { - var result = -1; - - for (var i = 0; i < stylesInDOM.length; i++) { - if (stylesInDOM[i].identifier === identifier) { - result = i; - break; - } - } - - return result; -} - -function modulesToDom(list, options) { - var idCountMap = {}; - var identifiers = []; - - for (var i = 0; i < list.length; i++) { - var item = list[i]; - var id = options.base ? item[0] + options.base : item[0]; - var count = idCountMap[id] || 0; - var identifier = "".concat(id, " ").concat(count); - idCountMap[id] = count + 1; - var indexByIdentifier = getIndexByIdentifier(identifier); - var obj = { - css: item[1], - media: item[2], - sourceMap: item[3], - supports: item[4], - layer: item[5] - }; - - if (indexByIdentifier !== -1) { - stylesInDOM[indexByIdentifier].references++; - stylesInDOM[indexByIdentifier].updater(obj); - } else { - var updater = addElementStyle(obj, options); - options.byIndex = i; - stylesInDOM.splice(i, 0, { - identifier: identifier, - updater: updater, - references: 1 - }); - } - - identifiers.push(identifier); - } - - return identifiers; -} - -function addElementStyle(obj, options) { - var api = options.domAPI(options); - api.update(obj); - - var updater = function updater(newObj) { - if (newObj) { - if (newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap && newObj.supports === obj.supports && newObj.layer === obj.layer) { - return; - } - - api.update(obj = newObj); - } else { - api.remove(); - } - }; - - return updater; -} - -module.exports = function (list, options) { - options = options || {}; - list = list || []; - var lastIdentifiers = modulesToDom(list, options); - return function update(newList) { - newList = newList || []; - - for (var i = 0; i < lastIdentifiers.length; i++) { - var identifier = lastIdentifiers[i]; - var index = getIndexByIdentifier(identifier); - stylesInDOM[index].references--; - } - - var newLastIdentifiers = modulesToDom(newList, options); - - for (var _i = 0; _i < lastIdentifiers.length; _i++) { - var _identifier = lastIdentifiers[_i]; - - var _index = getIndexByIdentifier(_identifier); - - if (stylesInDOM[_index].references === 0) { - stylesInDOM[_index].updater(); - - stylesInDOM.splice(_index, 1); - } - } - - lastIdentifiers = newLastIdentifiers; - }; -}; - -/***/ }), - -/***/ "./node_modules/style-loader/dist/runtime/insertBySelector.js": -/*!********************************************************************!*\ - !*** ./node_modules/style-loader/dist/runtime/insertBySelector.js ***! - \********************************************************************/ -/***/ ((module) => { - - - -var memo = {}; -/* istanbul ignore next */ - -function getTarget(target) { - if (typeof memo[target] === "undefined") { - var styleTarget = document.querySelector(target); // Special case to return head of iframe instead of iframe itself - - if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) { - try { - // This will throw an exception if access to iframe is blocked - // due to cross-origin restrictions - styleTarget = styleTarget.contentDocument.head; - } catch (e) { - // istanbul ignore next - styleTarget = null; - } - } - - memo[target] = styleTarget; - } - - return memo[target]; -} -/* istanbul ignore next */ - - -function insertBySelector(insert, style) { - var target = getTarget(insert); - - if (!target) { - throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid."); - } - - target.appendChild(style); -} - -module.exports = insertBySelector; - -/***/ }), - -/***/ "./node_modules/style-loader/dist/runtime/insertStyleElement.js": -/*!**********************************************************************!*\ - !*** ./node_modules/style-loader/dist/runtime/insertStyleElement.js ***! - \**********************************************************************/ -/***/ ((module) => { - - - -/* istanbul ignore next */ -function insertStyleElement(options) { - var element = document.createElement("style"); - options.setAttributes(element, options.attributes); - options.insert(element, options.options); - return element; -} - -module.exports = insertStyleElement; - -/***/ }), - -/***/ "./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js": -/*!**********************************************************************************!*\ - !*** ./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js ***! - \**********************************************************************************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - - - -/* istanbul ignore next */ -function setAttributesWithoutAttributes(styleElement) { - var nonce = true ? __webpack_require__.nc : 0; - - if (nonce) { - styleElement.setAttribute("nonce", nonce); - } -} - -module.exports = setAttributesWithoutAttributes; - -/***/ }), - -/***/ "./node_modules/style-loader/dist/runtime/styleDomAPI.js": -/*!***************************************************************!*\ - !*** ./node_modules/style-loader/dist/runtime/styleDomAPI.js ***! - \***************************************************************/ -/***/ ((module) => { - - - -/* istanbul ignore next */ -function apply(styleElement, options, obj) { - var css = ""; - - if (obj.supports) { - css += "@supports (".concat(obj.supports, ") {"); - } - - if (obj.media) { - css += "@media ".concat(obj.media, " {"); - } - - var needLayer = typeof obj.layer !== "undefined"; - - if (needLayer) { - css += "@layer".concat(obj.layer.length > 0 ? " ".concat(obj.layer) : "", " {"); - } - - css += obj.css; - - if (needLayer) { - css += "}"; - } - - if (obj.media) { - css += "}"; - } - - if (obj.supports) { - css += "}"; - } - - var sourceMap = obj.sourceMap; - - if (sourceMap && typeof btoa !== "undefined") { - css += "\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))), " */"); - } // For old IE - - /* istanbul ignore if */ - - - options.styleTagTransform(css, styleElement, options.options); -} - -function removeStyleElement(styleElement) { - // istanbul ignore if - if (styleElement.parentNode === null) { - return false; - } - - styleElement.parentNode.removeChild(styleElement); -} -/* istanbul ignore next */ - - -function domAPI(options) { - var styleElement = options.insertStyleElement(options); - return { - update: function update(obj) { - apply(styleElement, options, obj); - }, - remove: function remove() { - removeStyleElement(styleElement); - } - }; -} - -module.exports = domAPI; - -/***/ }), - -/***/ "./node_modules/style-loader/dist/runtime/styleTagTransform.js": -/*!*********************************************************************!*\ - !*** ./node_modules/style-loader/dist/runtime/styleTagTransform.js ***! - \*********************************************************************/ -/***/ ((module) => { - - - -/* istanbul ignore next */ -function styleTagTransform(css, styleElement) { - if (styleElement.styleSheet) { - styleElement.styleSheet.cssText = css; - } else { - while (styleElement.firstChild) { - styleElement.removeChild(styleElement.firstChild); - } - - styleElement.appendChild(document.createTextNode(css)); - } -} - -module.exports = styleTagTransform; - -/***/ }), - -/***/ "./node_modules/uplot/dist/uPlot.esm.js": -/*!**********************************************!*\ - !*** ./node_modules/uplot/dist/uPlot.esm.js ***! - \**********************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ uPlot) -/* harmony export */ }); -/** -* Copyright (c) 2022, Leon Sorokin -* All rights reserved. (MIT Licensed) -* -* uPlot.js (μPlot) -* A small, fast chart for time series, lines, areas, ohlc & bars -* https://github.com/leeoniya/uPlot (v1.6.22) -*/ - -const FEAT_TIME = true; - -const pre = "u-"; - -const UPLOT = "uplot"; -const ORI_HZ = pre + "hz"; -const ORI_VT = pre + "vt"; -const TITLE = pre + "title"; -const WRAP = pre + "wrap"; -const UNDER = pre + "under"; -const OVER = pre + "over"; -const AXIS = pre + "axis"; -const OFF = pre + "off"; -const SELECT = pre + "select"; -const CURSOR_X = pre + "cursor-x"; -const CURSOR_Y = pre + "cursor-y"; -const CURSOR_PT = pre + "cursor-pt"; -const LEGEND = pre + "legend"; -const LEGEND_LIVE = pre + "live"; -const LEGEND_INLINE = pre + "inline"; -const LEGEND_THEAD = pre + "thead"; -const LEGEND_SERIES = pre + "series"; -const LEGEND_MARKER = pre + "marker"; -const LEGEND_LABEL = pre + "label"; -const LEGEND_VALUE = pre + "value"; - -const WIDTH = "width"; -const HEIGHT = "height"; -const TOP = "top"; -const BOTTOM = "bottom"; -const LEFT = "left"; -const RIGHT = "right"; -const hexBlack = "#000"; -const transparent = hexBlack + "0"; - -const mousemove = "mousemove"; -const mousedown = "mousedown"; -const mouseup = "mouseup"; -const mouseenter = "mouseenter"; -const mouseleave = "mouseleave"; -const dblclick = "dblclick"; -const resize = "resize"; -const scroll = "scroll"; - -const change = "change"; -const dppxchange = "dppxchange"; - -const domEnv = typeof window != 'undefined'; - -const doc = domEnv ? document : null; -const win = domEnv ? window : null; -const nav = domEnv ? navigator : null; - -let pxRatio; - -let query; - -function setPxRatio() { - let _pxRatio = devicePixelRatio; - - // during print preview, Chrome fires off these dppx queries even without changes - if (pxRatio != _pxRatio) { - pxRatio = _pxRatio; - - query && off(change, query, setPxRatio); - query = matchMedia(`(min-resolution: ${pxRatio - 0.001}dppx) and (max-resolution: ${pxRatio + 0.001}dppx)`); - on(change, query, setPxRatio); - - win.dispatchEvent(new CustomEvent(dppxchange)); - } -} - -function addClass(el, c) { - if (c != null) { - let cl = el.classList; - !cl.contains(c) && cl.add(c); - } -} - -function remClass(el, c) { - let cl = el.classList; - cl.contains(c) && cl.remove(c); -} - -function setStylePx(el, name, value) { - el.style[name] = value + "px"; -} - -function placeTag(tag, cls, targ, refEl) { - let el = doc.createElement(tag); - - if (cls != null) - addClass(el, cls); - - if (targ != null) - targ.insertBefore(el, refEl); - - return el; -} - -function placeDiv(cls, targ) { - return placeTag("div", cls, targ); -} - -const xformCache = new WeakMap(); - -function elTrans(el, xPos, yPos, xMax, yMax) { - let xform = "translate(" + xPos + "px," + yPos + "px)"; - let xformOld = xformCache.get(el); - - if (xform != xformOld) { - el.style.transform = xform; - xformCache.set(el, xform); - - if (xPos < 0 || yPos < 0 || xPos > xMax || yPos > yMax) - addClass(el, OFF); - else - remClass(el, OFF); - } -} - -const colorCache = new WeakMap(); - -function elColor(el, background, borderColor) { - let newColor = background + borderColor; - let oldColor = colorCache.get(el); - - if (newColor != oldColor) { - colorCache.set(el, newColor); - el.style.background = background; - el.style.borderColor = borderColor; - } -} - -const sizeCache = new WeakMap(); - -function elSize(el, newWid, newHgt, centered) { - let newSize = newWid + "" + newHgt; - let oldSize = sizeCache.get(el); - - if (newSize != oldSize) { - sizeCache.set(el, newSize); - el.style.height = newHgt + "px"; - el.style.width = newWid + "px"; - el.style.marginLeft = centered ? -newWid/2 + "px" : 0; - el.style.marginTop = centered ? -newHgt/2 + "px" : 0; - } -} - -const evOpts = {passive: true}; -const evOpts2 = {...evOpts, capture: true}; - -function on(ev, el, cb, capt) { - el.addEventListener(ev, cb, capt ? evOpts2 : evOpts); -} - -function off(ev, el, cb, capt) { - el.removeEventListener(ev, cb, capt ? evOpts2 : evOpts); -} - -domEnv && setPxRatio(); - -// binary search for index of closest value -function closestIdx(num, arr, lo, hi) { - let mid; - lo = lo || 0; - hi = hi || arr.length - 1; - let bitwise = hi <= 2147483647; - - while (hi - lo > 1) { - mid = bitwise ? (lo + hi) >> 1 : floor((lo + hi) / 2); - - if (arr[mid] < num) - lo = mid; - else - hi = mid; - } - - if (num - arr[lo] <= arr[hi] - num) - return lo; - - return hi; -} - -function nonNullIdx(data, _i0, _i1, dir) { - for (let i = dir == 1 ? _i0 : _i1; i >= _i0 && i <= _i1; i += dir) { - if (data[i] != null) - return i; - } - - return -1; -} - -function getMinMax(data, _i0, _i1, sorted) { -// console.log("getMinMax()"); - - let _min = inf; - let _max = -inf; - - if (sorted == 1) { - _min = data[_i0]; - _max = data[_i1]; - } - else if (sorted == -1) { - _min = data[_i1]; - _max = data[_i0]; - } - else { - for (let i = _i0; i <= _i1; i++) { - if (data[i] != null) { - _min = min(_min, data[i]); - _max = max(_max, data[i]); - } - } - } - - return [_min, _max]; -} - -function getMinMaxLog(data, _i0, _i1) { -// console.log("getMinMax()"); - - let _min = inf; - let _max = -inf; - - for (let i = _i0; i <= _i1; i++) { - if (data[i] > 0) { - _min = min(_min, data[i]); - _max = max(_max, data[i]); - } - } - - return [ - _min == inf ? 1 : _min, - _max == -inf ? 10 : _max, - ]; -} - -const _fixedTuple = [0, 0]; - -function fixIncr(minIncr, maxIncr, minExp, maxExp) { - _fixedTuple[0] = minExp < 0 ? roundDec(minIncr, -minExp) : minIncr; - _fixedTuple[1] = maxExp < 0 ? roundDec(maxIncr, -maxExp) : maxIncr; - return _fixedTuple; -} - -function rangeLog(min, max, base, fullMags) { - let minSign = sign(min); - - let logFn = base == 10 ? log10 : log2; - - if (min == max) { - if (minSign == -1) { - min *= base; - max /= base; - } - else { - min /= base; - max *= base; - } - } - - let minExp, maxExp, minMaxIncrs; - - if (fullMags) { - minExp = floor(logFn(min)); - maxExp = ceil(logFn(max)); - - minMaxIncrs = fixIncr(pow(base, minExp), pow(base, maxExp), minExp, maxExp); - - min = minMaxIncrs[0]; - max = minMaxIncrs[1]; - } - else { - minExp = floor(logFn(abs(min))); - maxExp = floor(logFn(abs(max))); - - minMaxIncrs = fixIncr(pow(base, minExp), pow(base, maxExp), minExp, maxExp); - - min = incrRoundDn(min, minMaxIncrs[0]); - max = incrRoundUp(max, minMaxIncrs[1]); - } - - return [min, max]; -} - -function rangeAsinh(min, max, base, fullMags) { - let minMax = rangeLog(min, max, base, fullMags); - - if (min == 0) - minMax[0] = 0; - - if (max == 0) - minMax[1] = 0; - - return minMax; -} - -const rangePad = 0.1; - -const autoRangePart = { - mode: 3, - pad: rangePad, -}; - -const _eqRangePart = { - pad: 0, - soft: null, - mode: 0, -}; - -const _eqRange = { - min: _eqRangePart, - max: _eqRangePart, -}; - -// this ensures that non-temporal/numeric y-axes get multiple-snapped padding added above/below -// TODO: also account for incrs when snapping to ensure top of axis gets a tick & value -function rangeNum(_min, _max, mult, extra) { - if (isObj(mult)) - return _rangeNum(_min, _max, mult); - - _eqRangePart.pad = mult; - _eqRangePart.soft = extra ? 0 : null; - _eqRangePart.mode = extra ? 3 : 0; - - return _rangeNum(_min, _max, _eqRange); -} - -// nullish coalesce -function ifNull(lh, rh) { - return lh == null ? rh : lh; -} - -// checks if given index range in an array contains a non-null value -// aka a range-bounded Array.some() -function hasData(data, idx0, idx1) { - idx0 = ifNull(idx0, 0); - idx1 = ifNull(idx1, data.length - 1); - - while (idx0 <= idx1) { - if (data[idx0] != null) - return true; - idx0++; - } - - return false; -} - -function _rangeNum(_min, _max, cfg) { - let cmin = cfg.min; - let cmax = cfg.max; - - let padMin = ifNull(cmin.pad, 0); - let padMax = ifNull(cmax.pad, 0); - - let hardMin = ifNull(cmin.hard, -inf); - let hardMax = ifNull(cmax.hard, inf); - - let softMin = ifNull(cmin.soft, inf); - let softMax = ifNull(cmax.soft, -inf); - - let softMinMode = ifNull(cmin.mode, 0); - let softMaxMode = ifNull(cmax.mode, 0); - - let delta = _max - _min; - - // this handles situations like 89.7, 89.69999999999999 - // by assuming 0.001x deltas are precision errors -// if (delta > 0 && delta < abs(_max) / 1e3) -// delta = 0; - - // treat data as flat if delta is less than 1 billionth - if (delta < 1e-9) { - delta = 0; - - // if soft mode is 2 and all vals are flat at 0, avoid the 0.1 * 1e3 fallback - // this prevents 0,0,0 from ranging to -100,100 when softMin/softMax are -1,1 - if (_min == 0 || _max == 0) { - delta = 1e-9; - - if (softMinMode == 2 && softMin != inf) - padMin = 0; - - if (softMaxMode == 2 && softMax != -inf) - padMax = 0; - } - } - - let nonZeroDelta = delta || abs(_max) || 1e3; - let mag = log10(nonZeroDelta); - let base = pow(10, floor(mag)); - - let _padMin = nonZeroDelta * (delta == 0 ? (_min == 0 ? .1 : 1) : padMin); - let _newMin = roundDec(incrRoundDn(_min - _padMin, base/10), 9); - let _softMin = _min >= softMin && (softMinMode == 1 || softMinMode == 3 && _newMin <= softMin || softMinMode == 2 && _newMin >= softMin) ? softMin : inf; - let minLim = max(hardMin, _newMin < _softMin && _min >= _softMin ? _softMin : min(_softMin, _newMin)); - - let _padMax = nonZeroDelta * (delta == 0 ? (_max == 0 ? .1 : 1) : padMax); - let _newMax = roundDec(incrRoundUp(_max + _padMax, base/10), 9); - let _softMax = _max <= softMax && (softMaxMode == 1 || softMaxMode == 3 && _newMax >= softMax || softMaxMode == 2 && _newMax <= softMax) ? softMax : -inf; - let maxLim = min(hardMax, _newMax > _softMax && _max <= _softMax ? _softMax : max(_softMax, _newMax)); - - if (minLim == maxLim && minLim == 0) - maxLim = 100; - - return [minLim, maxLim]; -} - -// alternative: https://stackoverflow.com/a/2254896 -const numFormatter = new Intl.NumberFormat(domEnv ? nav.language : 'en-US'); -const fmtNum = val => numFormatter.format(val); - -const M = Math; - -const PI = M.PI; -const abs = M.abs; -const floor = M.floor; -const round = M.round; -const ceil = M.ceil; -const min = M.min; -const max = M.max; -const pow = M.pow; -const sign = M.sign; -const log10 = M.log10; -const log2 = M.log2; -// TODO: seems like this needs to match asinh impl if the passed v is tweaked? -const sinh = (v, linthresh = 1) => M.sinh(v) * linthresh; -const asinh = (v, linthresh = 1) => M.asinh(v / linthresh); - -const inf = Infinity; - -function numIntDigits(x) { - return (log10((x ^ (x >> 31)) - (x >> 31)) | 0) + 1; -} - -function incrRound(num, incr) { - return round(num/incr)*incr; -} - -function clamp(num, _min, _max) { - return min(max(num, _min), _max); -} - -function fnOrSelf(v) { - return typeof v == "function" ? v : () => v; -} - -const retArg0 = _0 => _0; - -const retArg1 = (_0, _1) => _1; - -const retNull = _ => null; - -const retTrue = _ => true; - -const retEq = (a, b) => a == b; - -function incrRoundUp(num, incr) { - return ceil(num/incr)*incr; -} - -function incrRoundDn(num, incr) { - return floor(num/incr)*incr; -} - -function roundDec(val, dec) { - return round(val * (dec = 10**dec)) / dec; -} - -const fixedDec = new Map(); - -function guessDec(num) { - return ((""+num).split(".")[1] || "").length; -} - -function genIncrs(base, minExp, maxExp, mults) { - let incrs = []; - - let multDec = mults.map(guessDec); - - for (let exp = minExp; exp < maxExp; exp++) { - let expa = abs(exp); - let mag = roundDec(pow(base, exp), expa); - - for (let i = 0; i < mults.length; i++) { - let _incr = mults[i] * mag; - let dec = (_incr >= 0 && exp >= 0 ? 0 : expa) + (exp >= multDec[i] ? 0 : multDec[i]); - let incr = roundDec(_incr, dec); - incrs.push(incr); - fixedDec.set(incr, dec); - } - } - - return incrs; -} - -//export const assign = Object.assign; - -const EMPTY_OBJ = {}; -const EMPTY_ARR = []; - -const nullNullTuple = [null, null]; - -const isArr = Array.isArray; - -function isStr(v) { - return typeof v == 'string'; -} - -function isObj(v) { - let is = false; - - if (v != null) { - let c = v.constructor; - is = c == null || c == Object; - } - - return is; -} - -function fastIsObj(v) { - return v != null && typeof v == 'object'; -} - -const TypedArray = Object.getPrototypeOf(Uint8Array); - -function copy(o, _isObj = isObj) { - let out; - - if (isArr(o)) { - let val = o.find(v => v != null); - - if (isArr(val) || _isObj(val)) { - out = Array(o.length); - for (let i = 0; i < o.length; i++) - out[i] = copy(o[i], _isObj); - } - else - out = o.slice(); - } - else if (o instanceof TypedArray) // also (ArrayBuffer.isView(o) && !(o instanceof DataView)) - out = o.slice(); - else if (_isObj(o)) { - out = {}; - for (let k in o) - out[k] = copy(o[k], _isObj); - } - else - out = o; - - return out; -} - -function assign(targ) { - let args = arguments; - - for (let i = 1; i < args.length; i++) { - let src = args[i]; - - for (let key in src) { - if (isObj(targ[key])) - assign(targ[key], copy(src[key])); - else - targ[key] = copy(src[key]); - } - } - - return targ; -} - -// nullModes -const NULL_REMOVE = 0; // nulls are converted to undefined (e.g. for spanGaps: true) -const NULL_RETAIN = 1; // nulls are retained, with alignment artifacts set to undefined (default) -const NULL_EXPAND = 2; // nulls are expanded to include any adjacent alignment artifacts - -// sets undefined values to nulls when adjacent to existing nulls (minesweeper) -function nullExpand(yVals, nullIdxs, alignedLen) { - for (let i = 0, xi, lastNullIdx = -1; i < nullIdxs.length; i++) { - let nullIdx = nullIdxs[i]; - - if (nullIdx > lastNullIdx) { - xi = nullIdx - 1; - while (xi >= 0 && yVals[xi] == null) - yVals[xi--] = null; - - xi = nullIdx + 1; - while (xi < alignedLen && yVals[xi] == null) - yVals[lastNullIdx = xi++] = null; - } - } -} - -// nullModes is a tables-matched array indicating how to treat nulls in each series -// output is sorted ASC on the joined field (table[0]) and duplicate join values are collapsed -function join(tables, nullModes) { - let xVals = new Set(); - - for (let ti = 0; ti < tables.length; ti++) { - let t = tables[ti]; - let xs = t[0]; - let len = xs.length; - - for (let i = 0; i < len; i++) - xVals.add(xs[i]); - } - - let data = [Array.from(xVals).sort((a, b) => a - b)]; - - let alignedLen = data[0].length; - - let xIdxs = new Map(); - - for (let i = 0; i < alignedLen; i++) - xIdxs.set(data[0][i], i); - - for (let ti = 0; ti < tables.length; ti++) { - let t = tables[ti]; - let xs = t[0]; - - for (let si = 1; si < t.length; si++) { - let ys = t[si]; - - let yVals = Array(alignedLen).fill(undefined); - - let nullMode = nullModes ? nullModes[ti][si] : NULL_RETAIN; - - let nullIdxs = []; - - for (let i = 0; i < ys.length; i++) { - let yVal = ys[i]; - let alignedIdx = xIdxs.get(xs[i]); - - if (yVal === null) { - if (nullMode != NULL_REMOVE) { - yVals[alignedIdx] = yVal; - - if (nullMode == NULL_EXPAND) - nullIdxs.push(alignedIdx); - } - } - else - yVals[alignedIdx] = yVal; - } - - nullExpand(yVals, nullIdxs, alignedLen); - - data.push(yVals); - } - } - - return data; -} - -const microTask = typeof queueMicrotask == "undefined" ? fn => Promise.resolve().then(fn) : queueMicrotask; - -const months = [ - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December", -]; - -const days = [ - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", -]; - -function slice3(str) { - return str.slice(0, 3); -} - -const days3 = days.map(slice3); - -const months3 = months.map(slice3); - -const engNames = { - MMMM: months, - MMM: months3, - WWWW: days, - WWW: days3, -}; - -function zeroPad2(int) { - return (int < 10 ? '0' : '') + int; -} - -function zeroPad3(int) { - return (int < 10 ? '00' : int < 100 ? '0' : '') + int; -} - -/* -function suffix(int) { - let mod10 = int % 10; - - return int + ( - mod10 == 1 && int != 11 ? "st" : - mod10 == 2 && int != 12 ? "nd" : - mod10 == 3 && int != 13 ? "rd" : "th" - ); -} -*/ - -const subs = { - // 2019 - YYYY: d => d.getFullYear(), - // 19 - YY: d => (d.getFullYear()+'').slice(2), - // July - MMMM: (d, names) => names.MMMM[d.getMonth()], - // Jul - MMM: (d, names) => names.MMM[d.getMonth()], - // 07 - MM: d => zeroPad2(d.getMonth()+1), - // 7 - M: d => d.getMonth()+1, - // 09 - DD: d => zeroPad2(d.getDate()), - // 9 - D: d => d.getDate(), - // Monday - WWWW: (d, names) => names.WWWW[d.getDay()], - // Mon - WWW: (d, names) => names.WWW[d.getDay()], - // 03 - HH: d => zeroPad2(d.getHours()), - // 3 - H: d => d.getHours(), - // 9 (12hr, unpadded) - h: d => {let h = d.getHours(); return h == 0 ? 12 : h > 12 ? h - 12 : h;}, - // AM - AA: d => d.getHours() >= 12 ? 'PM' : 'AM', - // am - aa: d => d.getHours() >= 12 ? 'pm' : 'am', - // a - a: d => d.getHours() >= 12 ? 'p' : 'a', - // 09 - mm: d => zeroPad2(d.getMinutes()), - // 9 - m: d => d.getMinutes(), - // 09 - ss: d => zeroPad2(d.getSeconds()), - // 9 - s: d => d.getSeconds(), - // 374 - fff: d => zeroPad3(d.getMilliseconds()), -}; - -function fmtDate(tpl, names) { - names = names || engNames; - let parts = []; - - let R = /\{([a-z]+)\}|[^{]+/gi, m; - - while (m = R.exec(tpl)) - parts.push(m[0][0] == '{' ? subs[m[1]] : m[0]); - - return d => { - let out = ''; - - for (let i = 0; i < parts.length; i++) - out += typeof parts[i] == "string" ? parts[i] : parts[i](d, names); - - return out; - } -} - -const localTz = new Intl.DateTimeFormat().resolvedOptions().timeZone; - -// https://stackoverflow.com/questions/15141762/how-to-initialize-a-javascript-date-to-a-particular-time-zone/53652131#53652131 -function tzDate(date, tz) { - let date2; - - // perf optimization - if (tz == 'UTC' || tz == 'Etc/UTC') - date2 = new Date(+date + date.getTimezoneOffset() * 6e4); - else if (tz == localTz) - date2 = date; - else { - date2 = new Date(date.toLocaleString('en-US', {timeZone: tz})); - date2.setMilliseconds(date.getMilliseconds()); - } - - return date2; -} - -//export const series = []; - -// default formatters: - -const onlyWhole = v => v % 1 == 0; - -const allMults = [1,2,2.5,5]; - -// ...0.01, 0.02, 0.025, 0.05, 0.1, 0.2, 0.25, 0.5 -const decIncrs = genIncrs(10, -16, 0, allMults); - -// 1, 2, 2.5, 5, 10, 20, 25, 50... -const oneIncrs = genIncrs(10, 0, 16, allMults); - -// 1, 2, 5, 10, 20, 25, 50... -const wholeIncrs = oneIncrs.filter(onlyWhole); - -const numIncrs = decIncrs.concat(oneIncrs); - -const NL = "\n"; - -const yyyy = "{YYYY}"; -const NLyyyy = NL + yyyy; -const md = "{M}/{D}"; -const NLmd = NL + md; -const NLmdyy = NLmd + "/{YY}"; - -const aa = "{aa}"; -const hmm = "{h}:{mm}"; -const hmmaa = hmm + aa; -const NLhmmaa = NL + hmmaa; -const ss = ":{ss}"; - -const _ = null; - -function genTimeStuffs(ms) { - let s = ms * 1e3, - m = s * 60, - h = m * 60, - d = h * 24, - mo = d * 30, - y = d * 365; - - // min of 1e-3 prevents setting a temporal x ticks too small since Date objects cannot advance ticks smaller than 1ms - let subSecIncrs = ms == 1 ? genIncrs(10, 0, 3, allMults).filter(onlyWhole) : genIncrs(10, -3, 0, allMults); - - let timeIncrs = subSecIncrs.concat([ - // minute divisors (# of secs) - s, - s * 5, - s * 10, - s * 15, - s * 30, - // hour divisors (# of mins) - m, - m * 5, - m * 10, - m * 15, - m * 30, - // day divisors (# of hrs) - h, - h * 2, - h * 3, - h * 4, - h * 6, - h * 8, - h * 12, - // month divisors TODO: need more? - d, - d * 2, - d * 3, - d * 4, - d * 5, - d * 6, - d * 7, - d * 8, - d * 9, - d * 10, - d * 15, - // year divisors (# months, approx) - mo, - mo * 2, - mo * 3, - mo * 4, - mo * 6, - // century divisors - y, - y * 2, - y * 5, - y * 10, - y * 25, - y * 50, - y * 100, - ]); - - // [0]: minimum num secs in the tick incr - // [1]: default tick format - // [2-7]: rollover tick formats - // [8]: mode: 0: replace [1] -> [2-7], 1: concat [1] + [2-7] - const _timeAxisStamps = [ - // tick incr default year month day hour min sec mode - [y, yyyy, _, _, _, _, _, _, 1], - [d * 28, "{MMM}", NLyyyy, _, _, _, _, _, 1], - [d, md, NLyyyy, _, _, _, _, _, 1], - [h, "{h}" + aa, NLmdyy, _, NLmd, _, _, _, 1], - [m, hmmaa, NLmdyy, _, NLmd, _, _, _, 1], - [s, ss, NLmdyy + " " + hmmaa, _, NLmd + " " + hmmaa, _, NLhmmaa, _, 1], - [ms, ss + ".{fff}", NLmdyy + " " + hmmaa, _, NLmd + " " + hmmaa, _, NLhmmaa, _, 1], - ]; - - // the ensures that axis ticks, values & grid are aligned to logical temporal breakpoints and not an arbitrary timestamp - // https://www.timeanddate.com/time/dst/ - // https://www.timeanddate.com/time/dst/2019.html - // https://www.epochconverter.com/timezones - function timeAxisSplits(tzDate) { - return (self, axisIdx, scaleMin, scaleMax, foundIncr, foundSpace) => { - let splits = []; - let isYr = foundIncr >= y; - let isMo = foundIncr >= mo && foundIncr < y; - - // get the timezone-adjusted date - let minDate = tzDate(scaleMin); - let minDateTs = roundDec(minDate * ms, 3); - - // get ts of 12am (this lands us at or before the original scaleMin) - let minMin = mkDate(minDate.getFullYear(), isYr ? 0 : minDate.getMonth(), isMo || isYr ? 1 : minDate.getDate()); - let minMinTs = roundDec(minMin * ms, 3); - - if (isMo || isYr) { - let moIncr = isMo ? foundIncr / mo : 0; - let yrIncr = isYr ? foundIncr / y : 0; - // let tzOffset = scaleMin - minDateTs; // needed? - let split = minDateTs == minMinTs ? minDateTs : roundDec(mkDate(minMin.getFullYear() + yrIncr, minMin.getMonth() + moIncr, 1) * ms, 3); - let splitDate = new Date(round(split / ms)); - let baseYear = splitDate.getFullYear(); - let baseMonth = splitDate.getMonth(); - - for (let i = 0; split <= scaleMax; i++) { - let next = mkDate(baseYear + yrIncr * i, baseMonth + moIncr * i, 1); - let offs = next - tzDate(roundDec(next * ms, 3)); - - split = roundDec((+next + offs) * ms, 3); - - if (split <= scaleMax) - splits.push(split); - } - } - else { - let incr0 = foundIncr >= d ? d : foundIncr; - let tzOffset = floor(scaleMin) - floor(minDateTs); - let split = minMinTs + tzOffset + incrRoundUp(minDateTs - minMinTs, incr0); - splits.push(split); - - let date0 = tzDate(split); - - let prevHour = date0.getHours() + (date0.getMinutes() / m) + (date0.getSeconds() / h); - let incrHours = foundIncr / h; - - let minSpace = self.axes[axisIdx]._space; - let pctSpace = foundSpace / minSpace; - - while (1) { - split = roundDec(split + foundIncr, ms == 1 ? 0 : 3); - - if (split > scaleMax) - break; - - if (incrHours > 1) { - let expectedHour = floor(roundDec(prevHour + incrHours, 6)) % 24; - let splitDate = tzDate(split); - let actualHour = splitDate.getHours(); - - let dstShift = actualHour - expectedHour; - - if (dstShift > 1) - dstShift = -1; - - split -= dstShift * h; - - prevHour = (prevHour + incrHours) % 24; - - // add a tick only if it's further than 70% of the min allowed label spacing - let prevSplit = splits[splits.length - 1]; - let pctIncr = roundDec((split - prevSplit) / foundIncr, 3); - - if (pctIncr * pctSpace >= .7) - splits.push(split); - } - else - splits.push(split); - } - } - - return splits; - } - } - - return [ - timeIncrs, - _timeAxisStamps, - timeAxisSplits, - ]; -} - -const [ timeIncrsMs, _timeAxisStampsMs, timeAxisSplitsMs ] = genTimeStuffs(1); -const [ timeIncrsS, _timeAxisStampsS, timeAxisSplitsS ] = genTimeStuffs(1e-3); - -// base 2 -genIncrs(2, -53, 53, [1]); - -/* -console.log({ - decIncrs, - oneIncrs, - wholeIncrs, - numIncrs, - timeIncrs, - fixedDec, -}); -*/ - -function timeAxisStamps(stampCfg, fmtDate) { - return stampCfg.map(s => s.map((v, i) => - i == 0 || i == 8 || v == null ? v : fmtDate(i == 1 || s[8] == 0 ? v : s[1] + v) - )); -} - -// TODO: will need to accept spaces[] and pull incr into the loop when grid will be non-uniform, eg for log scales. -// currently we ignore this for months since they're *nearly* uniform and the added complexity is not worth it -function timeAxisVals(tzDate, stamps) { - return (self, splits, axisIdx, foundSpace, foundIncr) => { - let s = stamps.find(s => foundIncr >= s[0]) || stamps[stamps.length - 1]; - - // these track boundaries when a full label is needed again - let prevYear; - let prevMnth; - let prevDate; - let prevHour; - let prevMins; - let prevSecs; - - return splits.map(split => { - let date = tzDate(split); - - let newYear = date.getFullYear(); - let newMnth = date.getMonth(); - let newDate = date.getDate(); - let newHour = date.getHours(); - let newMins = date.getMinutes(); - let newSecs = date.getSeconds(); - - let stamp = ( - newYear != prevYear && s[2] || - newMnth != prevMnth && s[3] || - newDate != prevDate && s[4] || - newHour != prevHour && s[5] || - newMins != prevMins && s[6] || - newSecs != prevSecs && s[7] || - s[1] - ); - - prevYear = newYear; - prevMnth = newMnth; - prevDate = newDate; - prevHour = newHour; - prevMins = newMins; - prevSecs = newSecs; - - return stamp(date); - }); - } -} - -// for when axis.values is defined as a static fmtDate template string -function timeAxisVal(tzDate, dateTpl) { - let stamp = fmtDate(dateTpl); - return (self, splits, axisIdx, foundSpace, foundIncr) => splits.map(split => stamp(tzDate(split))); -} - -function mkDate(y, m, d) { - return new Date(y, m, d); -} - -function timeSeriesStamp(stampCfg, fmtDate) { - return fmtDate(stampCfg); -} -const _timeSeriesStamp = '{YYYY}-{MM}-{DD} {h}:{mm}{aa}'; - -function timeSeriesVal(tzDate, stamp) { - return (self, val) => stamp(tzDate(val)); -} - -function legendStroke(self, seriesIdx) { - let s = self.series[seriesIdx]; - return s.width ? s.stroke(self, seriesIdx) : s.points.width ? s.points.stroke(self, seriesIdx) : null; -} - -function legendFill(self, seriesIdx) { - return self.series[seriesIdx].fill(self, seriesIdx); -} - -const legendOpts = { - show: true, - live: true, - isolate: false, - markers: { - show: true, - width: 2, - stroke: legendStroke, - fill: legendFill, - dash: "solid", - }, - idx: null, - idxs: null, - values: [], -}; - -function cursorPointShow(self, si) { - let o = self.cursor.points; - - let pt = placeDiv(); - - let size = o.size(self, si); - setStylePx(pt, WIDTH, size); - setStylePx(pt, HEIGHT, size); - - let mar = size / -2; - setStylePx(pt, "marginLeft", mar); - setStylePx(pt, "marginTop", mar); - - let width = o.width(self, si, size); - width && setStylePx(pt, "borderWidth", width); - - return pt; -} - -function cursorPointFill(self, si) { - let sp = self.series[si].points; - return sp._fill || sp._stroke; -} - -function cursorPointStroke(self, si) { - let sp = self.series[si].points; - return sp._stroke || sp._fill; -} - -function cursorPointSize(self, si) { - let sp = self.series[si].points; - return ptDia(sp.width, 1); -} - -function dataIdx(self, seriesIdx, cursorIdx) { - return cursorIdx; -} - -const moveTuple = [0,0]; - -function cursorMove(self, mouseLeft1, mouseTop1) { - moveTuple[0] = mouseLeft1; - moveTuple[1] = mouseTop1; - return moveTuple; -} - -function filtBtn0(self, targ, handle) { - return e => { - e.button == 0 && handle(e); - }; -} - -function passThru(self, targ, handle) { - return handle; -} - -const cursorOpts = { - show: true, - x: true, - y: true, - lock: false, - move: cursorMove, - points: { - show: cursorPointShow, - size: cursorPointSize, - width: 0, - stroke: cursorPointStroke, - fill: cursorPointFill, - }, - - bind: { - mousedown: filtBtn0, - mouseup: filtBtn0, - click: filtBtn0, - dblclick: filtBtn0, - - mousemove: passThru, - mouseleave: passThru, - mouseenter: passThru, - }, - - drag: { - setScale: true, - x: true, - y: false, - dist: 0, - uni: null, - _x: false, - _y: false, - }, - - focus: { - prox: -1, - }, - - left: -10, - top: -10, - idx: null, - dataIdx, - idxs: null, -}; - -const axisLines = { - show: true, - stroke: "rgba(0,0,0,0.07)", - width: 2, -// dash: [], -}; - -const grid = assign({}, axisLines, { - filter: retArg1, -}); - -const ticks = assign({}, grid, { - size: 10, -}); - -const border = assign({}, axisLines, { - show: false, -}); - -const font = '12px system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"'; -const labelFont = "bold " + font; -const lineMult = 1.5; // font-size multiplier - -const xAxisOpts = { - show: true, - scale: "x", - stroke: hexBlack, - space: 50, - gap: 5, - size: 50, - labelGap: 0, - labelSize: 30, - labelFont, - side: 2, -// class: "x-vals", -// incrs: timeIncrs, -// values: timeVals, -// filter: retArg1, - grid, - ticks, - border, - font, - rotate: 0, -}; - -const numSeriesLabel = "Value"; -const timeSeriesLabel = "Time"; - -const xSeriesOpts = { - show: true, - scale: "x", - auto: false, - sorted: 1, -// label: "Time", -// value: v => stamp(new Date(v * 1e3)), - - // internal caches - min: inf, - max: -inf, - idxs: [], -}; - -function numAxisVals(self, splits, axisIdx, foundSpace, foundIncr) { - return splits.map(v => v == null ? "" : fmtNum(v)); -} - -function numAxisSplits(self, axisIdx, scaleMin, scaleMax, foundIncr, foundSpace, forceMin) { - let splits = []; - - let numDec = fixedDec.get(foundIncr) || 0; - - scaleMin = forceMin ? scaleMin : roundDec(incrRoundUp(scaleMin, foundIncr), numDec); - - for (let val = scaleMin; val <= scaleMax; val = roundDec(val + foundIncr, numDec)) - splits.push(Object.is(val, -0) ? 0 : val); // coalesces -0 - - return splits; -} - -// this doesnt work for sin, which needs to come off from 0 independently in pos and neg dirs -function logAxisSplits(self, axisIdx, scaleMin, scaleMax, foundIncr, foundSpace, forceMin) { - const splits = []; - - const logBase = self.scales[self.axes[axisIdx].scale].log; - - const logFn = logBase == 10 ? log10 : log2; - - const exp = floor(logFn(scaleMin)); - - foundIncr = pow(logBase, exp); - - if (exp < 0) - foundIncr = roundDec(foundIncr, -exp); - - let split = scaleMin; - - do { - splits.push(split); - split = roundDec(split + foundIncr, fixedDec.get(foundIncr)); - - if (split >= foundIncr * logBase) - foundIncr = split; - - } while (split <= scaleMax); - - return splits; -} - -function asinhAxisSplits(self, axisIdx, scaleMin, scaleMax, foundIncr, foundSpace, forceMin) { - let sc = self.scales[self.axes[axisIdx].scale]; - - let linthresh = sc.asinh; - - let posSplits = scaleMax > linthresh ? logAxisSplits(self, axisIdx, max(linthresh, scaleMin), scaleMax, foundIncr) : [linthresh]; - let zero = scaleMax >= 0 && scaleMin <= 0 ? [0] : []; - let negSplits = scaleMin < -linthresh ? logAxisSplits(self, axisIdx, max(linthresh, -scaleMax), -scaleMin, foundIncr): [linthresh]; - - return negSplits.reverse().map(v => -v).concat(zero, posSplits); -} - -const RE_ALL = /./; -const RE_12357 = /[12357]/; -const RE_125 = /[125]/; -const RE_1 = /1/; - -function logAxisValsFilt(self, splits, axisIdx, foundSpace, foundIncr) { - let axis = self.axes[axisIdx]; - let scaleKey = axis.scale; - let sc = self.scales[scaleKey]; - - if (sc.distr == 3 && sc.log == 2) - return splits; - - let valToPos = self.valToPos; - - let minSpace = axis._space; - - let _10 = valToPos(10, scaleKey); - - let re = ( - valToPos(9, scaleKey) - _10 >= minSpace ? RE_ALL : - valToPos(7, scaleKey) - _10 >= minSpace ? RE_12357 : - valToPos(5, scaleKey) - _10 >= minSpace ? RE_125 : - RE_1 - ); - - return splits.map(v => ((sc.distr == 4 && v == 0) || re.test(v)) ? v : null); -} - -function numSeriesVal(self, val) { - return val == null ? "" : fmtNum(val); -} - -const yAxisOpts = { - show: true, - scale: "y", - stroke: hexBlack, - space: 30, - gap: 5, - size: 50, - labelGap: 0, - labelSize: 30, - labelFont, - side: 3, -// class: "y-vals", -// incrs: numIncrs, -// values: (vals, space) => vals, -// filter: retArg1, - grid, - ticks, - border, - font, - rotate: 0, -}; - -// takes stroke width -function ptDia(width, mult) { - let dia = 3 + (width || 1) * 2; - return roundDec(dia * mult, 3); -} - -function seriesPointsShow(self, si) { - let { scale, idxs } = self.series[0]; - let xData = self._data[0]; - let p0 = self.valToPos(xData[idxs[0]], scale, true); - let p1 = self.valToPos(xData[idxs[1]], scale, true); - let dim = abs(p1 - p0); - - let s = self.series[si]; -// const dia = ptDia(s.width, pxRatio); - let maxPts = dim / (s.points.space * pxRatio); - return idxs[1] - idxs[0] <= maxPts; -} - -const facet = { - scale: null, - auto: true, - sorted: 0, - - // internal caches - min: inf, - max: -inf, -}; - -const xySeriesOpts = { - show: true, - auto: true, - sorted: 0, - alpha: 1, - facets: [ - assign({}, facet, {scale: 'x'}), - assign({}, facet, {scale: 'y'}), - ], -}; - -const ySeriesOpts = { - scale: "y", - auto: true, - sorted: 0, - show: true, - spanGaps: false, - gaps: (self, seriesIdx, idx0, idx1, nullGaps) => nullGaps, - alpha: 1, - points: { - show: seriesPointsShow, - filter: null, - // paths: - // stroke: "#000", - // fill: "#fff", - // width: 1, - // size: 10, - }, -// label: "Value", -// value: v => v, - values: null, - - // internal caches - min: inf, - max: -inf, - idxs: [], - - path: null, - clip: null, -}; - -function clampScale(self, val, scaleMin, scaleMax, scaleKey) { -/* - if (val < 0) { - let cssHgt = self.bbox.height / pxRatio; - let absPos = self.valToPos(abs(val), scaleKey); - let fromBtm = cssHgt - absPos; - return self.posToVal(cssHgt + fromBtm, scaleKey); - } -*/ - return scaleMin / 10; -} - -const xScaleOpts = { - time: FEAT_TIME, - auto: true, - distr: 1, - log: 10, - asinh: 1, - min: null, - max: null, - dir: 1, - ori: 0, -}; - -const yScaleOpts = assign({}, xScaleOpts, { - time: false, - ori: 1, -}); - -const syncs = {}; - -function _sync(key, opts) { - let s = syncs[key]; - - if (!s) { - s = { - key, - plots: [], - sub(plot) { - s.plots.push(plot); - }, - unsub(plot) { - s.plots = s.plots.filter(c => c != plot); - }, - pub(type, self, x, y, w, h, i) { - for (let j = 0; j < s.plots.length; j++) - s.plots[j] != self && s.plots[j].pub(type, self, x, y, w, h, i); - }, - }; - - if (key != null) - syncs[key] = s; - } - - return s; -} - -const BAND_CLIP_FILL = 1 << 0; -const BAND_CLIP_STROKE = 1 << 1; - -function orient(u, seriesIdx, cb) { - const series = u.series[seriesIdx]; - const scales = u.scales; - const bbox = u.bbox; - const scaleX = u.mode == 2 ? scales[series.facets[0].scale] : scales[u.series[0].scale]; - - let dx = u._data[0], - dy = u._data[seriesIdx], - sx = scaleX, - sy = u.mode == 2 ? scales[series.facets[1].scale] : scales[series.scale], - l = bbox.left, - t = bbox.top, - w = bbox.width, - h = bbox.height, - H = u.valToPosH, - V = u.valToPosV; - - return (sx.ori == 0 - ? cb( - series, - dx, - dy, - sx, - sy, - H, - V, - l, - t, - w, - h, - moveToH, - lineToH, - rectH, - arcH, - bezierCurveToH, - ) - : cb( - series, - dx, - dy, - sx, - sy, - V, - H, - t, - l, - h, - w, - moveToV, - lineToV, - rectV, - arcV, - bezierCurveToV, - ) - ); -} - -function bandFillClipDirs(self, seriesIdx) { - let fillDir = 0; - - // 2 bits, -1 | 1 - let clipDirs = 0; - - let bands = ifNull(self.bands, EMPTY_ARR); - - for (let i = 0; i < bands.length; i++) { - let b = bands[i]; - - // is a "from" band edge - if (b.series[0] == seriesIdx) - fillDir = b.dir; - // is a "to" band edge - else if (b.series[1] == seriesIdx) { - if (b.dir == 1) - clipDirs |= 1; - else - clipDirs |= 2; - } - } - - return [ - fillDir, - ( - clipDirs == 1 ? -1 : // neg only - clipDirs == 2 ? 1 : // pos only - clipDirs == 3 ? 2 : // both - 0 // neither - ) - ]; -} - -function seriesFillTo(self, seriesIdx, dataMin, dataMax, bandFillDir) { - let scale = self.scales[self.series[seriesIdx].scale]; - - return ( - bandFillDir == -1 ? scale.min : - bandFillDir == 1 ? scale.max : - scale.distr == 3 ? ( - scale.dir == 1 ? scale.min : - scale.max - ) : 0 - ); -} - -// creates inverted band clip path (from stroke path -> yMax || yMin) -// clipDir is always inverse of fillDir -// default clip dir is upwards (1), since default band fill is downwards/fillBelowTo (-1) (highIdx -> lowIdx) -function clipBandLine(self, seriesIdx, idx0, idx1, strokePath, clipDir) { - return orient(self, seriesIdx, (series, dataX, dataY, scaleX, scaleY, valToPosX, valToPosY, xOff, yOff, xDim, yDim) => { - let pxRound = series.pxRound; - - const dir = scaleX.dir * (scaleX.ori == 0 ? 1 : -1); - const lineTo = scaleX.ori == 0 ? lineToH : lineToV; - - let frIdx, toIdx; - - if (dir == 1) { - frIdx = idx0; - toIdx = idx1; - } - else { - frIdx = idx1; - toIdx = idx0; - } - - // path start - let x0 = pxRound(valToPosX(dataX[frIdx], scaleX, xDim, xOff)); - let y0 = pxRound(valToPosY(dataY[frIdx], scaleY, yDim, yOff)); - // path end x - let x1 = pxRound(valToPosX(dataX[toIdx], scaleX, xDim, xOff)); - // upper or lower y limit - let yLimit = pxRound(valToPosY(clipDir == 1 ? scaleY.max : scaleY.min, scaleY, yDim, yOff)); - - let clip = new Path2D(strokePath); - - lineTo(clip, x1, yLimit); - lineTo(clip, x0, yLimit); - lineTo(clip, x0, y0); - - return clip; - }); -} - -function clipGaps(gaps, ori, plotLft, plotTop, plotWid, plotHgt) { - let clip = null; - - // create clip path (invert gaps and non-gaps) - if (gaps.length > 0) { - clip = new Path2D(); - - const rect = ori == 0 ? rectH : rectV; - - let prevGapEnd = plotLft; - - for (let i = 0; i < gaps.length; i++) { - let g = gaps[i]; - - if (g[1] > g[0]) { - let w = g[0] - prevGapEnd; - - w > 0 && rect(clip, prevGapEnd, plotTop, w, plotTop + plotHgt); - - prevGapEnd = g[1]; - } - } - - let w = plotLft + plotWid - prevGapEnd; - - w > 0 && rect(clip, prevGapEnd, plotTop, w, plotTop + plotHgt); - } - - return clip; -} - -function addGap(gaps, fromX, toX) { - let prevGap = gaps[gaps.length - 1]; - - if (prevGap && prevGap[0] == fromX) // TODO: gaps must be encoded at stroke widths? - prevGap[1] = toX; - else - gaps.push([fromX, toX]); -} - -function findGaps(xs, ys, idx0, idx1, dir, pixelForX, align) { - let gaps = []; - - for (let i = dir == 1 ? idx0 : idx1; i >= idx0 && i <= idx1; i += dir) { - let yVal = ys[i]; - - if (yVal === null) { - let fr = i, to = i; - - if (dir == 1) { - while (++i <= idx1 && ys[i] === null) - to = i; - } - else { - while (--i >= idx0 && ys[i] === null) - to = i; - } - - let frPx = pixelForX(xs[fr]); - let toPx = to == fr ? frPx : pixelForX(xs[to]); - - // if value adjacent to edge null is same pixel, then it's partially - // filled and gap should start at next pixel - let frPx2 = align <= 0 ? pixelForX(xs[fr-dir]) : frPx; - // if (frPx2 == frPx) - // frPx++; - // else - frPx = frPx2; - - let toPx2 = align >= 0 ? pixelForX(xs[to+dir]) : toPx; - // if (toPx2 == toPx) - // toPx--; - // else - toPx = toPx2; - - if (toPx >= frPx) - gaps.push([frPx, toPx]); // addGap - } - } - - return gaps; -} - -function pxRoundGen(pxAlign) { - return pxAlign == 0 ? retArg0 : pxAlign == 1 ? round : v => incrRound(v, pxAlign); -} - -function rect(ori) { - let moveTo = ori == 0 ? - moveToH : - moveToV; - - let arcTo = ori == 0 ? - (p, x1, y1, x2, y2, r) => { p.arcTo(x1, y1, x2, y2, r); } : - (p, y1, x1, y2, x2, r) => { p.arcTo(x1, y1, x2, y2, r); }; - - let rect = ori == 0 ? - (p, x, y, w, h) => { p.rect(x, y, w, h); } : - (p, y, x, h, w) => { p.rect(x, y, w, h); }; - - return (p, x, y, w, h, r = 0) => { - if (r == 0) - rect(p, x, y, w, h); - else { - r = min(r, w / 2, h / 2); - - // adapted from https://stackoverflow.com/questions/1255512/how-to-draw-a-rounded-rectangle-using-html-canvas/7838871#7838871 - moveTo(p, x + r, y); - arcTo(p, x + w, y, x + w, y + h, r); - arcTo(p, x + w, y + h, x, y + h, r); - arcTo(p, x, y + h, x, y, r); - arcTo(p, x, y, x + w, y, r); - p.closePath(); - } - }; -} - -// orientation-inverting canvas functions -const moveToH = (p, x, y) => { p.moveTo(x, y); }; -const moveToV = (p, y, x) => { p.moveTo(x, y); }; -const lineToH = (p, x, y) => { p.lineTo(x, y); }; -const lineToV = (p, y, x) => { p.lineTo(x, y); }; -const rectH = rect(0); -const rectV = rect(1); -const arcH = (p, x, y, r, startAngle, endAngle) => { p.arc(x, y, r, startAngle, endAngle); }; -const arcV = (p, y, x, r, startAngle, endAngle) => { p.arc(x, y, r, startAngle, endAngle); }; -const bezierCurveToH = (p, bp1x, bp1y, bp2x, bp2y, p2x, p2y) => { p.bezierCurveTo(bp1x, bp1y, bp2x, bp2y, p2x, p2y); }; -const bezierCurveToV = (p, bp1y, bp1x, bp2y, bp2x, p2y, p2x) => { p.bezierCurveTo(bp1x, bp1y, bp2x, bp2y, p2x, p2y); }; - -// TODO: drawWrap(seriesIdx, drawPoints) (save, restore, translate, clip) -function points(opts) { - return (u, seriesIdx, idx0, idx1, filtIdxs) => { - // log("drawPoints()", arguments); - - return orient(u, seriesIdx, (series, dataX, dataY, scaleX, scaleY, valToPosX, valToPosY, xOff, yOff, xDim, yDim) => { - let { pxRound, points } = series; - - let moveTo, arc; - - if (scaleX.ori == 0) { - moveTo = moveToH; - arc = arcH; - } - else { - moveTo = moveToV; - arc = arcV; - } - - const width = roundDec(points.width * pxRatio, 3); - - let rad = (points.size - points.width) / 2 * pxRatio; - let dia = roundDec(rad * 2, 3); - - let fill = new Path2D(); - let clip = new Path2D(); - - let { left: lft, top: top, width: wid, height: hgt } = u.bbox; - - rectH(clip, - lft - dia, - top - dia, - wid + dia * 2, - hgt + dia * 2, - ); - - const drawPoint = pi => { - if (dataY[pi] != null) { - let x = pxRound(valToPosX(dataX[pi], scaleX, xDim, xOff)); - let y = pxRound(valToPosY(dataY[pi], scaleY, yDim, yOff)); - - moveTo(fill, x + rad, y); - arc(fill, x, y, rad, 0, PI * 2); - } - }; - - if (filtIdxs) - filtIdxs.forEach(drawPoint); - else { - for (let pi = idx0; pi <= idx1; pi++) - drawPoint(pi); - } - - return { - stroke: width > 0 ? fill : null, - fill, - clip, - flags: BAND_CLIP_FILL | BAND_CLIP_STROKE, - }; - }); - }; -} - -function _drawAcc(lineTo) { - return (stroke, accX, minY, maxY, inY, outY) => { - if (minY != maxY) { - if (inY != minY && outY != minY) - lineTo(stroke, accX, minY); - if (inY != maxY && outY != maxY) - lineTo(stroke, accX, maxY); - - lineTo(stroke, accX, outY); - } - }; -} - -const drawAccH = _drawAcc(lineToH); -const drawAccV = _drawAcc(lineToV); - -function linear(opts) { - const alignGaps = ifNull(opts?.alignGaps, 0); - - return (u, seriesIdx, idx0, idx1) => { - return orient(u, seriesIdx, (series, dataX, dataY, scaleX, scaleY, valToPosX, valToPosY, xOff, yOff, xDim, yDim) => { - let pxRound = series.pxRound; - - let pixelForX = val => pxRound(valToPosX(val, scaleX, xDim, xOff)); - let pixelForY = val => pxRound(valToPosY(val, scaleY, yDim, yOff)); - - let lineTo, drawAcc; - - if (scaleX.ori == 0) { - lineTo = lineToH; - drawAcc = drawAccH; - } - else { - lineTo = lineToV; - drawAcc = drawAccV; - } - - const dir = scaleX.dir * (scaleX.ori == 0 ? 1 : -1); - - const _paths = {stroke: new Path2D(), fill: null, clip: null, band: null, gaps: null, flags: BAND_CLIP_FILL}; - const stroke = _paths.stroke; - - let minY = inf, - maxY = -inf, - inY, outY, drawnAtX; - - let accX = pixelForX(dataX[dir == 1 ? idx0 : idx1]); - - // data edges - let lftIdx = nonNullIdx(dataY, idx0, idx1, 1 * dir); - let rgtIdx = nonNullIdx(dataY, idx0, idx1, -1 * dir); - let lftX = pixelForX(dataX[lftIdx]); - let rgtX = pixelForX(dataX[rgtIdx]); - - for (let i = dir == 1 ? idx0 : idx1; i >= idx0 && i <= idx1; i += dir) { - let x = pixelForX(dataX[i]); - - if (x == accX) { - if (dataY[i] != null) { - outY = pixelForY(dataY[i]); - - if (minY == inf) { - lineTo(stroke, x, outY); - inY = outY; - } - - minY = min(outY, minY); - maxY = max(outY, maxY); - } - } - else { - if (minY != inf) { - drawAcc(stroke, accX, minY, maxY, inY, outY); - drawnAtX = accX; - } - - if (dataY[i] != null) { - outY = pixelForY(dataY[i]); - lineTo(stroke, x, outY); - minY = maxY = inY = outY; - } - else { - minY = inf; - maxY = -inf; - } - - accX = x; - } - } - - if (minY != inf && minY != maxY && drawnAtX != accX) - drawAcc(stroke, accX, minY, maxY, inY, outY); - - let [ bandFillDir, bandClipDir ] = bandFillClipDirs(u, seriesIdx); - - if (series.fill != null || bandFillDir != 0) { - let fill = _paths.fill = new Path2D(stroke); - - let fillToVal = series.fillTo(u, seriesIdx, series.min, series.max, bandFillDir); - let fillToY = pixelForY(fillToVal); - - lineTo(fill, rgtX, fillToY); - lineTo(fill, lftX, fillToY); - } - - if (!series.spanGaps) { - // console.time('gaps'); - let gaps = []; - - gaps.push(...findGaps(dataX, dataY, idx0, idx1, dir, pixelForX, alignGaps)); - - // console.timeEnd('gaps'); - - // console.log('gaps', JSON.stringify(gaps)); - - _paths.gaps = gaps = series.gaps(u, seriesIdx, idx0, idx1, gaps); - - _paths.clip = clipGaps(gaps, scaleX.ori, xOff, yOff, xDim, yDim); - } - - if (bandClipDir != 0) { - _paths.band = bandClipDir == 2 ? [ - clipBandLine(u, seriesIdx, idx0, idx1, stroke, -1), - clipBandLine(u, seriesIdx, idx0, idx1, stroke, 1), - ] : clipBandLine(u, seriesIdx, idx0, idx1, stroke, bandClipDir); - } - - return _paths; - }); - }; -} - -function stepped(opts) { - const align = ifNull(opts.align, 1); - // whether to draw ascenders/descenders at null/gap bondaries - const ascDesc = ifNull(opts.ascDesc, false); - - const alignGaps = ifNull(opts.alignGaps, 0); - - return (u, seriesIdx, idx0, idx1) => { - return orient(u, seriesIdx, (series, dataX, dataY, scaleX, scaleY, valToPosX, valToPosY, xOff, yOff, xDim, yDim) => { - let pxRound = series.pxRound; - - let pixelForX = val => pxRound(valToPosX(val, scaleX, xDim, xOff)); - let pixelForY = val => pxRound(valToPosY(val, scaleY, yDim, yOff)); - - let lineTo = scaleX.ori == 0 ? lineToH : lineToV; - - const _paths = {stroke: new Path2D(), fill: null, clip: null, band: null, gaps: null, flags: BAND_CLIP_FILL}; - const stroke = _paths.stroke; - - const dir = scaleX.dir * (scaleX.ori == 0 ? 1 : -1); - - idx0 = nonNullIdx(dataY, idx0, idx1, 1); - idx1 = nonNullIdx(dataY, idx0, idx1, -1); - - let prevYPos = pixelForY(dataY[dir == 1 ? idx0 : idx1]); - let firstXPos = pixelForX(dataX[dir == 1 ? idx0 : idx1]); - let prevXPos = firstXPos; - - lineTo(stroke, firstXPos, prevYPos); - - for (let i = dir == 1 ? idx0 : idx1; i >= idx0 && i <= idx1; i += dir) { - let yVal1 = dataY[i]; - - if (yVal1 == null) - continue; - - let x1 = pixelForX(dataX[i]); - let y1 = pixelForY(yVal1); - - if (align == 1) - lineTo(stroke, x1, prevYPos); - else - lineTo(stroke, prevXPos, y1); - - lineTo(stroke, x1, y1); - - prevYPos = y1; - prevXPos = x1; - } - - let [ bandFillDir, bandClipDir ] = bandFillClipDirs(u, seriesIdx); - - if (series.fill != null || bandFillDir != 0) { - let fill = _paths.fill = new Path2D(stroke); - - let fillTo = series.fillTo(u, seriesIdx, series.min, series.max, bandFillDir); - let fillToY = pixelForY(fillTo); - - lineTo(fill, prevXPos, fillToY); - lineTo(fill, firstXPos, fillToY); - } - - if (!series.spanGaps) { - // console.time('gaps'); - let gaps = []; - - gaps.push(...findGaps(dataX, dataY, idx0, idx1, dir, pixelForX, alignGaps)); - - // console.timeEnd('gaps'); - - // console.log('gaps', JSON.stringify(gaps)); - - // expand/contract clips for ascenders/descenders - let halfStroke = (series.width * pxRatio) / 2; - let startsOffset = (ascDesc || align == 1) ? halfStroke : -halfStroke; - let endsOffset = (ascDesc || align == -1) ? -halfStroke : halfStroke; - - gaps.forEach(g => { - g[0] += startsOffset; - g[1] += endsOffset; - }); - - _paths.gaps = gaps = series.gaps(u, seriesIdx, idx0, idx1, gaps); - - _paths.clip = clipGaps(gaps, scaleX.ori, xOff, yOff, xDim, yDim); - } - - if (bandClipDir != 0) { - _paths.band = bandClipDir == 2 ? [ - clipBandLine(u, seriesIdx, idx0, idx1, stroke, -1), - clipBandLine(u, seriesIdx, idx0, idx1, stroke, 1), - ] : clipBandLine(u, seriesIdx, idx0, idx1, stroke, bandClipDir); - } - - return _paths; - }); - }; -} - -function bars(opts) { - opts = opts || EMPTY_OBJ; - const size = ifNull(opts.size, [0.6, inf, 1]); - const align = opts.align || 0; - const extraGap = (opts.gap || 0) * pxRatio; - - const radius = ifNull(opts.radius, 0); - - const gapFactor = 1 - size[0]; - const maxWidth = ifNull(size[1], inf) * pxRatio; - const minWidth = ifNull(size[2], 1) * pxRatio; - - const disp = ifNull(opts.disp, EMPTY_OBJ); - const _each = ifNull(opts.each, _ => {}); - - const { fill: dispFills, stroke: dispStrokes } = disp; - - return (u, seriesIdx, idx0, idx1) => { - return orient(u, seriesIdx, (series, dataX, dataY, scaleX, scaleY, valToPosX, valToPosY, xOff, yOff, xDim, yDim) => { - let pxRound = series.pxRound; - - const _dirX = scaleX.dir * (scaleX.ori == 0 ? 1 : -1); - const _dirY = scaleY.dir * (scaleY.ori == 1 ? 1 : -1); - - let rect = scaleX.ori == 0 ? rectH : rectV; - - let each = scaleX.ori == 0 ? _each : (u, seriesIdx, i, top, lft, hgt, wid) => { - _each(u, seriesIdx, i, lft, top, wid, hgt); - }; - - let [ bandFillDir, bandClipDir ] = bandFillClipDirs(u, seriesIdx); - - // let fillToY = series.fillTo(u, seriesIdx, series.min, series.max, bandFillDir); - let fillToY = scaleY.distr == 3 ? (bandFillDir == 1 ? scaleY.max : scaleY.min) : 0; - - let y0Pos = valToPosY(fillToY, scaleY, yDim, yOff); - - // barWid is to center of stroke - let xShift, barWid; - - let strokeWidth = pxRound(series.width * pxRatio); - - let multiPath = false; - - let fillColors = null; - let fillPaths = null; - let strokeColors = null; - let strokePaths = null; - - if (dispFills != null && (strokeWidth == 0 || dispStrokes != null)) { - multiPath = true; - - fillColors = dispFills.values(u, seriesIdx, idx0, idx1); - fillPaths = new Map(); - (new Set(fillColors)).forEach(color => { - if (color != null) - fillPaths.set(color, new Path2D()); - }); - - if (strokeWidth > 0) { - strokeColors = dispStrokes.values(u, seriesIdx, idx0, idx1); - strokePaths = new Map(); - (new Set(strokeColors)).forEach(color => { - if (color != null) - strokePaths.set(color, new Path2D()); - }); - } - } - - let { x0, size } = disp; - - if (x0 != null && size != null) { - dataX = x0.values(u, seriesIdx, idx0, idx1); - - if (x0.unit == 2) - dataX = dataX.map(pct => u.posToVal(xOff + pct * xDim, scaleX.key, true)); - - // assumes uniform sizes, for now - let sizes = size.values(u, seriesIdx, idx0, idx1); - - if (size.unit == 2) - barWid = sizes[0] * xDim; - else - barWid = valToPosX(sizes[0], scaleX, xDim, xOff) - valToPosX(0, scaleX, xDim, xOff); // assumes linear scale (delta from 0) - - barWid = pxRound(barWid - strokeWidth); - - xShift = (_dirX == 1 ? -strokeWidth / 2 : barWid + strokeWidth / 2); - } - else { - let colWid = xDim; - - if (dataX.length > 1) { - // prior index with non-undefined y data - let prevIdx = null; - - // scan full dataset for smallest adjacent delta - // will not work properly for non-linear x scales, since does not do expensive valToPosX calcs till end - for (let i = 0, minDelta = Infinity; i < dataX.length; i++) { - if (dataY[i] !== undefined) { - if (prevIdx != null) { - let delta = abs(dataX[i] - dataX[prevIdx]); - - if (delta < minDelta) { - minDelta = delta; - colWid = abs(valToPosX(dataX[i], scaleX, xDim, xOff) - valToPosX(dataX[prevIdx], scaleX, xDim, xOff)); - } - } - - prevIdx = i; - } - } - } - - let gapWid = colWid * gapFactor; - - barWid = pxRound(min(maxWidth, max(minWidth, colWid - gapWid)) - strokeWidth - extraGap); - - xShift = (align == 0 ? barWid / 2 : align == _dirX ? 0 : barWid) - align * _dirX * extraGap / 2; - } - - const _paths = {stroke: null, fill: null, clip: null, band: null, gaps: null, flags: BAND_CLIP_FILL | BAND_CLIP_STROKE}; // disp, geom - - let yLimit; - - if (bandClipDir != 0) { - _paths.band = new Path2D(); - yLimit = pxRound(valToPosY(bandClipDir == 1 ? scaleY.max : scaleY.min, scaleY, yDim, yOff)); - } - - const stroke = multiPath ? null : new Path2D(); - const band = _paths.band; - - let { y0, y1 } = disp; - - let dataY0 = null; - - if (y0 != null && y1 != null) { - dataY = y1.values(u, seriesIdx, idx0, idx1); - dataY0 = y0.values(u, seriesIdx, idx0, idx1); - } - - for (let i = _dirX == 1 ? idx0 : idx1; i >= idx0 && i <= idx1; i += _dirX) { - let yVal = dataY[i]; - - // we can skip both, drawing and band clipping for alignment artifacts - if (yVal === undefined) - continue; - - /* - // interpolate upwards band clips - if (yVal == null) { - // if (hasBands) - // yVal = costlyLerp(i, idx0, idx1, _dirX, dataY); - // else - continue; - } - */ - - let xVal = scaleX.distr != 2 || disp != null ? dataX[i] : i; - - // TODO: all xPos can be pre-computed once for all series in aligned set - let xPos = valToPosX(xVal, scaleX, xDim, xOff); - let yPos = valToPosY(ifNull(yVal, fillToY), scaleY, yDim, yOff); - - if (dataY0 != null && yVal != null) - y0Pos = valToPosY(dataY0[i], scaleY, yDim, yOff); - - let lft = pxRound(xPos - xShift); - let btm = pxRound(max(yPos, y0Pos)); - let top = pxRound(min(yPos, y0Pos)); - // this includes the stroke - let barHgt = btm - top; - - let r = radius * barWid; - - if (yVal != null) { // && yVal != fillToY (0 height bar) - if (multiPath) { - if (strokeWidth > 0 && strokeColors[i] != null) - rect(strokePaths.get(strokeColors[i]), lft, top + floor(strokeWidth / 2), barWid, max(0, barHgt - strokeWidth), r); - - if (fillColors[i] != null) - rect(fillPaths.get(fillColors[i]), lft, top + floor(strokeWidth / 2), barWid, max(0, barHgt - strokeWidth), r); - } - else - rect(stroke, lft, top + floor(strokeWidth / 2), barWid, max(0, barHgt - strokeWidth), r); - - each(u, seriesIdx, i, - lft - strokeWidth / 2, - top, - barWid + strokeWidth, - barHgt, - ); - } - - if (bandClipDir != 0) { - if (_dirY * bandClipDir == 1) { - btm = top; - top = yLimit; - } - else { - top = btm; - btm = yLimit; - } - - barHgt = btm - top; - - rect(band, lft - strokeWidth / 2, top, barWid + strokeWidth, max(0, barHgt), 0); - } - } - - if (strokeWidth > 0) - _paths.stroke = multiPath ? strokePaths : stroke; - - _paths.fill = multiPath ? fillPaths : stroke; - - return _paths; - }); - }; -} - -function splineInterp(interp, opts) { - const alignGaps = ifNull(opts?.alignGaps, 0); - - return (u, seriesIdx, idx0, idx1) => { - return orient(u, seriesIdx, (series, dataX, dataY, scaleX, scaleY, valToPosX, valToPosY, xOff, yOff, xDim, yDim) => { - let pxRound = series.pxRound; - - let pixelForX = val => pxRound(valToPosX(val, scaleX, xDim, xOff)); - let pixelForY = val => pxRound(valToPosY(val, scaleY, yDim, yOff)); - - let moveTo, bezierCurveTo, lineTo; - - if (scaleX.ori == 0) { - moveTo = moveToH; - lineTo = lineToH; - bezierCurveTo = bezierCurveToH; - } - else { - moveTo = moveToV; - lineTo = lineToV; - bezierCurveTo = bezierCurveToV; - } - - const dir = scaleX.dir * (scaleX.ori == 0 ? 1 : -1); - - idx0 = nonNullIdx(dataY, idx0, idx1, 1); - idx1 = nonNullIdx(dataY, idx0, idx1, -1); - - let firstXPos = pixelForX(dataX[dir == 1 ? idx0 : idx1]); - let prevXPos = firstXPos; - - let xCoords = []; - let yCoords = []; - - for (let i = dir == 1 ? idx0 : idx1; i >= idx0 && i <= idx1; i += dir) { - let yVal = dataY[i]; - - if (yVal != null) { - let xVal = dataX[i]; - let xPos = pixelForX(xVal); - - xCoords.push(prevXPos = xPos); - yCoords.push(pixelForY(dataY[i])); - } - } - - const _paths = {stroke: interp(xCoords, yCoords, moveTo, lineTo, bezierCurveTo, pxRound), fill: null, clip: null, band: null, gaps: null, flags: BAND_CLIP_FILL}; - const stroke = _paths.stroke; - - let [ bandFillDir, bandClipDir ] = bandFillClipDirs(u, seriesIdx); - - if (series.fill != null || bandFillDir != 0) { - let fill = _paths.fill = new Path2D(stroke); - - let fillTo = series.fillTo(u, seriesIdx, series.min, series.max, bandFillDir); - let fillToY = pixelForY(fillTo); - - lineTo(fill, prevXPos, fillToY); - lineTo(fill, firstXPos, fillToY); - } - - if (!series.spanGaps) { - // console.time('gaps'); - let gaps = []; - - gaps.push(...findGaps(dataX, dataY, idx0, idx1, dir, pixelForX, alignGaps)); - - // console.timeEnd('gaps'); - - // console.log('gaps', JSON.stringify(gaps)); - - _paths.gaps = gaps = series.gaps(u, seriesIdx, idx0, idx1, gaps); - - _paths.clip = clipGaps(gaps, scaleX.ori, xOff, yOff, xDim, yDim); - } - - if (bandClipDir != 0) { - _paths.band = bandClipDir == 2 ? [ - clipBandLine(u, seriesIdx, idx0, idx1, stroke, -1), - clipBandLine(u, seriesIdx, idx0, idx1, stroke, 1), - ] : clipBandLine(u, seriesIdx, idx0, idx1, stroke, bandClipDir); - } - - return _paths; - - // if FEAT_PATHS: false in rollup.config.js - // u.ctx.save(); - // u.ctx.beginPath(); - // u.ctx.rect(u.bbox.left, u.bbox.top, u.bbox.width, u.bbox.height); - // u.ctx.clip(); - // u.ctx.strokeStyle = u.series[sidx].stroke; - // u.ctx.stroke(stroke); - // u.ctx.fillStyle = u.series[sidx].fill; - // u.ctx.fill(fill); - // u.ctx.restore(); - // return null; - }); - }; -} - -function monotoneCubic(opts) { - return splineInterp(_monotoneCubic, opts); -} - -// Monotone Cubic Spline interpolation, adapted from the Chartist.js implementation: -// https://github.com/gionkunz/chartist-js/blob/e7e78201bffe9609915e5e53cfafa29a5d6c49f9/src/scripts/interpolation.js#L240-L369 -function _monotoneCubic(xs, ys, moveTo, lineTo, bezierCurveTo, pxRound) { - const n = xs.length; - - if (n < 2) - return null; - - const path = new Path2D(); - - moveTo(path, xs[0], ys[0]); - - if (n == 2) - lineTo(path, xs[1], ys[1]); - else { - let ms = Array(n), - ds = Array(n - 1), - dys = Array(n - 1), - dxs = Array(n - 1); - - // calc deltas and derivative - for (let i = 0; i < n - 1; i++) { - dys[i] = ys[i + 1] - ys[i]; - dxs[i] = xs[i + 1] - xs[i]; - ds[i] = dys[i] / dxs[i]; - } - - // determine desired slope (m) at each point using Fritsch-Carlson method - // http://math.stackexchange.com/questions/45218/implementation-of-monotone-cubic-interpolation - ms[0] = ds[0]; - - for (let i = 1; i < n - 1; i++) { - if (ds[i] === 0 || ds[i - 1] === 0 || (ds[i - 1] > 0) !== (ds[i] > 0)) - ms[i] = 0; - else { - ms[i] = 3 * (dxs[i - 1] + dxs[i]) / ( - (2 * dxs[i] + dxs[i - 1]) / ds[i - 1] + - (dxs[i] + 2 * dxs[i - 1]) / ds[i] - ); - - if (!isFinite(ms[i])) - ms[i] = 0; - } - } - - ms[n - 1] = ds[n - 2]; - - for (let i = 0; i < n - 1; i++) { - bezierCurveTo( - path, - xs[i] + dxs[i] / 3, - ys[i] + ms[i] * dxs[i] / 3, - xs[i + 1] - dxs[i] / 3, - ys[i + 1] - ms[i + 1] * dxs[i] / 3, - xs[i + 1], - ys[i + 1], - ); - } - } - - return path; -} - -const cursorPlots = new Set(); - -function invalidateRects() { - cursorPlots.forEach(u => { - u.syncRect(true); - }); -} - -if (domEnv) { - on(resize, win, invalidateRects); - on(scroll, win, invalidateRects, true); - on(dppxchange, win, () => { uPlot.pxRatio = pxRatio; }); -} - -const linearPath = linear() ; -const pointsPath = points() ; - -function setDefaults(d, xo, yo, initY) { - let d2 = initY ? [d[0], d[1]].concat(d.slice(2)) : [d[0]].concat(d.slice(1)); - return d2.map((o, i) => setDefault(o, i, xo, yo)); -} - -function setDefaults2(d, xyo) { - return d.map((o, i) => i == 0 ? null : assign({}, xyo, o)); // todo: assign() will not merge facet arrays -} - -function setDefault(o, i, xo, yo) { - return assign({}, (i == 0 ? xo : yo), o); -} - -function snapNumX(self, dataMin, dataMax) { - return dataMin == null ? nullNullTuple : [dataMin, dataMax]; -} - -const snapTimeX = snapNumX; - -// this ensures that non-temporal/numeric y-axes get multiple-snapped padding added above/below -// TODO: also account for incrs when snapping to ensure top of axis gets a tick & value -function snapNumY(self, dataMin, dataMax) { - return dataMin == null ? nullNullTuple : rangeNum(dataMin, dataMax, rangePad, true); -} - -function snapLogY(self, dataMin, dataMax, scale) { - return dataMin == null ? nullNullTuple : rangeLog(dataMin, dataMax, self.scales[scale].log, false); -} - -const snapLogX = snapLogY; - -function snapAsinhY(self, dataMin, dataMax, scale) { - return dataMin == null ? nullNullTuple : rangeAsinh(dataMin, dataMax, self.scales[scale].log, false); -} - -const snapAsinhX = snapAsinhY; - -// dim is logical (getClientBoundingRect) pixels, not canvas pixels -function findIncr(minVal, maxVal, incrs, dim, minSpace) { - let intDigits = max(numIntDigits(minVal), numIntDigits(maxVal)); - - let delta = maxVal - minVal; - - let incrIdx = closestIdx((minSpace / dim) * delta, incrs); - - do { - let foundIncr = incrs[incrIdx]; - let foundSpace = dim * foundIncr / delta; - - if (foundSpace >= minSpace && intDigits + (foundIncr < 5 ? fixedDec.get(foundIncr) : 0) <= 17) - return [foundIncr, foundSpace]; - } while (++incrIdx < incrs.length); - - return [0, 0]; -} - -function pxRatioFont(font) { - let fontSize, fontSizeCss; - font = font.replace(/(\d+)px/, (m, p1) => (fontSize = round((fontSizeCss = +p1) * pxRatio)) + 'px'); - return [font, fontSize, fontSizeCss]; -} - -function syncFontSize(axis) { - if (axis.show) { - [axis.font, axis.labelFont].forEach(f => { - let size = roundDec(f[2] * pxRatio, 1); - f[0] = f[0].replace(/[0-9.]+px/, size + 'px'); - f[1] = size; - }); - } -} - -function uPlot(opts, data, then) { - const self = { - mode: ifNull(opts.mode, 1), - }; - - const mode = self.mode; - - // TODO: cache denoms & mins scale.cache = {r, min, } - function getValPct(val, scale) { - let _val = ( - scale.distr == 3 ? log10(val > 0 ? val : scale.clamp(self, val, scale.min, scale.max, scale.key)) : - scale.distr == 4 ? asinh(val, scale.asinh) : - val - ); - - return (_val - scale._min) / (scale._max - scale._min); - } - - function getHPos(val, scale, dim, off) { - let pct = getValPct(val, scale); - return off + dim * (scale.dir == -1 ? (1 - pct) : pct); - } - - function getVPos(val, scale, dim, off) { - let pct = getValPct(val, scale); - return off + dim * (scale.dir == -1 ? pct : (1 - pct)); - } - - function getPos(val, scale, dim, off) { - return scale.ori == 0 ? getHPos(val, scale, dim, off) : getVPos(val, scale, dim, off); - } - - self.valToPosH = getHPos; - self.valToPosV = getVPos; - - let ready = false; - self.status = 0; - - const root = self.root = placeDiv(UPLOT); - - if (opts.id != null) - root.id = opts.id; - - addClass(root, opts.class); - - if (opts.title) { - let title = placeDiv(TITLE, root); - title.textContent = opts.title; - } - - const can = placeTag("canvas"); - const ctx = self.ctx = can.getContext("2d"); - - const wrap = placeDiv(WRAP, root); - const under = self.under = placeDiv(UNDER, wrap); - wrap.appendChild(can); - const over = self.over = placeDiv(OVER, wrap); - - opts = copy(opts); - - const pxAlign = +ifNull(opts.pxAlign, 1); - - const pxRound = pxRoundGen(pxAlign); - - (opts.plugins || []).forEach(p => { - if (p.opts) - opts = p.opts(self, opts) || opts; - }); - - const ms = opts.ms || 1e-3; - - const series = self.series = mode == 1 ? - setDefaults(opts.series || [], xSeriesOpts, ySeriesOpts, false) : - setDefaults2(opts.series || [null], xySeriesOpts); - const axes = self.axes = setDefaults(opts.axes || [], xAxisOpts, yAxisOpts, true); - const scales = self.scales = {}; - const bands = self.bands = opts.bands || []; - - bands.forEach(b => { - b.fill = fnOrSelf(b.fill || null); - b.dir = ifNull(b.dir, -1); - }); - - const xScaleKey = mode == 2 ? series[1].facets[0].scale : series[0].scale; - - const drawOrderMap = { - axes: drawAxesGrid, - series: drawSeries, - }; - - const drawOrder = (opts.drawOrder || ["axes", "series"]).map(key => drawOrderMap[key]); - - function initScale(scaleKey) { - let sc = scales[scaleKey]; - - if (sc == null) { - let scaleOpts = (opts.scales || EMPTY_OBJ)[scaleKey] || EMPTY_OBJ; - - if (scaleOpts.from != null) { - // ensure parent is initialized - initScale(scaleOpts.from); - // dependent scales inherit - scales[scaleKey] = assign({}, scales[scaleOpts.from], scaleOpts, {key: scaleKey}); - } - else { - sc = scales[scaleKey] = assign({}, (scaleKey == xScaleKey ? xScaleOpts : yScaleOpts), scaleOpts); - - sc.key = scaleKey; - - let isTime = sc.time; - - let rn = sc.range; - - let rangeIsArr = isArr(rn); - - if (scaleKey != xScaleKey || (mode == 2 && !isTime)) { - // if range array has null limits, it should be auto - if (rangeIsArr && (rn[0] == null || rn[1] == null)) { - rn = { - min: rn[0] == null ? autoRangePart : { - mode: 1, - hard: rn[0], - soft: rn[0], - }, - max: rn[1] == null ? autoRangePart : { - mode: 1, - hard: rn[1], - soft: rn[1], - }, - }; - rangeIsArr = false; - } - - if (!rangeIsArr && isObj(rn)) { - let cfg = rn; - // this is similar to snapNumY - rn = (self, dataMin, dataMax) => dataMin == null ? nullNullTuple : rangeNum(dataMin, dataMax, cfg); - } - } - - sc.range = fnOrSelf(rn || (isTime ? snapTimeX : scaleKey == xScaleKey ? - (sc.distr == 3 ? snapLogX : sc.distr == 4 ? snapAsinhX : snapNumX) : - (sc.distr == 3 ? snapLogY : sc.distr == 4 ? snapAsinhY : snapNumY) - )); - - sc.auto = fnOrSelf(rangeIsArr ? false : sc.auto); - - sc.clamp = fnOrSelf(sc.clamp || clampScale); - - // caches for expensive ops like asinh() & log() - sc._min = sc._max = null; - } - } - } - - initScale("x"); - initScale("y"); - - // TODO: init scales from facets in mode: 2 - if (mode == 1) { - series.forEach(s => { - initScale(s.scale); - }); - } - - axes.forEach(a => { - initScale(a.scale); - }); - - for (let k in opts.scales) - initScale(k); - - const scaleX = scales[xScaleKey]; - - const xScaleDistr = scaleX.distr; - - let valToPosX, valToPosY; - - if (scaleX.ori == 0) { - addClass(root, ORI_HZ); - valToPosX = getHPos; - valToPosY = getVPos; - /* - updOriDims = () => { - xDimCan = plotWid; - xOffCan = plotLft; - yDimCan = plotHgt; - yOffCan = plotTop; - - xDimCss = plotWidCss; - xOffCss = plotLftCss; - yDimCss = plotHgtCss; - yOffCss = plotTopCss; - }; - */ - } - else { - addClass(root, ORI_VT); - valToPosX = getVPos; - valToPosY = getHPos; - /* - updOriDims = () => { - xDimCan = plotHgt; - xOffCan = plotTop; - yDimCan = plotWid; - yOffCan = plotLft; - - xDimCss = plotHgtCss; - xOffCss = plotTopCss; - yDimCss = plotWidCss; - yOffCss = plotLftCss; - }; - */ - } - - const pendScales = {}; - - // explicitly-set initial scales - for (let k in scales) { - let sc = scales[k]; - - if (sc.min != null || sc.max != null) { - pendScales[k] = {min: sc.min, max: sc.max}; - sc.min = sc.max = null; - } - } - -// self.tz = opts.tz || Intl.DateTimeFormat().resolvedOptions().timeZone; - const _tzDate = (opts.tzDate || (ts => new Date(round(ts / ms)))); - const _fmtDate = (opts.fmtDate || fmtDate); - - const _timeAxisSplits = (ms == 1 ? timeAxisSplitsMs(_tzDate) : timeAxisSplitsS(_tzDate)); - const _timeAxisVals = timeAxisVals(_tzDate, timeAxisStamps((ms == 1 ? _timeAxisStampsMs : _timeAxisStampsS), _fmtDate)); - const _timeSeriesVal = timeSeriesVal(_tzDate, timeSeriesStamp(_timeSeriesStamp, _fmtDate)); - - const activeIdxs = []; - - const legend = (self.legend = assign({}, legendOpts, opts.legend)); - const showLegend = legend.show; - const markers = legend.markers; - - { - legend.idxs = activeIdxs; - - markers.width = fnOrSelf(markers.width); - markers.dash = fnOrSelf(markers.dash); - markers.stroke = fnOrSelf(markers.stroke); - markers.fill = fnOrSelf(markers.fill); - } - - let legendEl; - let legendRows = []; - let legendCells = []; - let legendCols; - let multiValLegend = false; - let NULL_LEGEND_VALUES = {}; - - if (legend.live) { - const getMultiVals = series[1] ? series[1].values : null; - multiValLegend = getMultiVals != null; - legendCols = multiValLegend ? getMultiVals(self, 1, 0) : {_: 0}; - - for (let k in legendCols) - NULL_LEGEND_VALUES[k] = "--"; - } - - if (showLegend) { - legendEl = placeTag("table", LEGEND, root); - - if (multiValLegend) { - let head = placeTag("tr", LEGEND_THEAD, legendEl); - placeTag("th", null, head); - - for (var key in legendCols) - placeTag("th", LEGEND_LABEL, head).textContent = key; - } - else { - addClass(legendEl, LEGEND_INLINE); - legend.live && addClass(legendEl, LEGEND_LIVE); - } - } - - const son = {show: true}; - const soff = {show: false}; - - function initLegendRow(s, i) { - if (i == 0 && (multiValLegend || !legend.live || mode == 2)) - return nullNullTuple; - - let cells = []; - - let row = placeTag("tr", LEGEND_SERIES, legendEl, legendEl.childNodes[i]); - - addClass(row, s.class); - - if (!s.show) - addClass(row, OFF); - - let label = placeTag("th", null, row); - - if (markers.show) { - let indic = placeDiv(LEGEND_MARKER, label); - - if (i > 0) { - let width = markers.width(self, i); - - if (width) - indic.style.border = width + "px " + markers.dash(self, i) + " " + markers.stroke(self, i); - - indic.style.background = markers.fill(self, i); - } - } - - let text = placeDiv(LEGEND_LABEL, label); - text.textContent = s.label; - - if (i > 0) { - if (!markers.show) - text.style.color = s.width > 0 ? markers.stroke(self, i) : markers.fill(self, i); - - onMouse("click", label, e => { - if (cursor._lock) - return; - - let seriesIdx = series.indexOf(s); - - if ((e.ctrlKey || e.metaKey) != legend.isolate) { - // if any other series is shown, isolate this one. else show all - let isolate = series.some((s, i) => i > 0 && i != seriesIdx && s.show); - - series.forEach((s, i) => { - i > 0 && setSeries(i, isolate ? (i == seriesIdx ? son : soff) : son, true, syncOpts.setSeries); - }); - } - else - setSeries(seriesIdx, {show: !s.show}, true, syncOpts.setSeries); - }); - - if (cursorFocus) { - onMouse(mouseenter, label, e => { - if (cursor._lock) - return; - - setSeries(series.indexOf(s), FOCUS_TRUE, true, syncOpts.setSeries); - }); - } - } - - for (var key in legendCols) { - let v = placeTag("td", LEGEND_VALUE, row); - v.textContent = "--"; - cells.push(v); - } - - return [row, cells]; - } - - const mouseListeners = new Map(); - - function onMouse(ev, targ, fn) { - const targListeners = mouseListeners.get(targ) || {}; - const listener = cursor.bind[ev](self, targ, fn); - - if (listener) { - on(ev, targ, targListeners[ev] = listener); - mouseListeners.set(targ, targListeners); - } - } - - function offMouse(ev, targ, fn) { - const targListeners = mouseListeners.get(targ) || {}; - - for (let k in targListeners) { - if (ev == null || k == ev) { - off(k, targ, targListeners[k]); - delete targListeners[k]; - } - } - - if (ev == null) - mouseListeners.delete(targ); - } - - let fullWidCss = 0; - let fullHgtCss = 0; - - let plotWidCss = 0; - let plotHgtCss = 0; - - // plot margins to account for axes - let plotLftCss = 0; - let plotTopCss = 0; - - let plotLft = 0; - let plotTop = 0; - let plotWid = 0; - let plotHgt = 0; - - self.bbox = {}; - - let shouldSetScales = false; - let shouldSetSize = false; - let shouldConvergeSize = false; - let shouldSetCursor = false; - let shouldSetLegend = false; - - function _setSize(width, height, force) { - if (force || (width != self.width || height != self.height)) - calcSize(width, height); - - resetYSeries(false); - - shouldConvergeSize = true; - shouldSetSize = true; - shouldSetCursor = shouldSetLegend = cursor.left >= 0; - commit(); - } - - function calcSize(width, height) { - // log("calcSize()", arguments); - - self.width = fullWidCss = plotWidCss = width; - self.height = fullHgtCss = plotHgtCss = height; - plotLftCss = plotTopCss = 0; - - calcPlotRect(); - calcAxesRects(); - - let bb = self.bbox; - - plotLft = bb.left = incrRound(plotLftCss * pxRatio, 0.5); - plotTop = bb.top = incrRound(plotTopCss * pxRatio, 0.5); - plotWid = bb.width = incrRound(plotWidCss * pxRatio, 0.5); - plotHgt = bb.height = incrRound(plotHgtCss * pxRatio, 0.5); - - // updOriDims(); - } - - // ensures size calc convergence - const CYCLE_LIMIT = 3; - - function convergeSize() { - let converged = false; - - let cycleNum = 0; - - while (!converged) { - cycleNum++; - - let axesConverged = axesCalc(cycleNum); - let paddingConverged = paddingCalc(cycleNum); - - converged = cycleNum == CYCLE_LIMIT || (axesConverged && paddingConverged); - - if (!converged) { - calcSize(self.width, self.height); - shouldSetSize = true; - } - } - } - - function setSize({width, height}) { - _setSize(width, height); - } - - self.setSize = setSize; - - // accumulate axis offsets, reduce canvas width - function calcPlotRect() { - // easements for edge labels - let hasTopAxis = false; - let hasBtmAxis = false; - let hasRgtAxis = false; - let hasLftAxis = false; - - axes.forEach((axis, i) => { - if (axis.show && axis._show) { - let {side, _size} = axis; - let isVt = side % 2; - let labelSize = axis.label != null ? axis.labelSize : 0; - - let fullSize = _size + labelSize; - - if (fullSize > 0) { - if (isVt) { - plotWidCss -= fullSize; - - if (side == 3) { - plotLftCss += fullSize; - hasLftAxis = true; - } - else - hasRgtAxis = true; - } - else { - plotHgtCss -= fullSize; - - if (side == 0) { - plotTopCss += fullSize; - hasTopAxis = true; - } - else - hasBtmAxis = true; - } - } - } - }); - - sidesWithAxes[0] = hasTopAxis; - sidesWithAxes[1] = hasRgtAxis; - sidesWithAxes[2] = hasBtmAxis; - sidesWithAxes[3] = hasLftAxis; - - // hz padding - plotWidCss -= _padding[1] + _padding[3]; - plotLftCss += _padding[3]; - - // vt padding - plotHgtCss -= _padding[2] + _padding[0]; - plotTopCss += _padding[0]; - } - - function calcAxesRects() { - // will accum + - let off1 = plotLftCss + plotWidCss; - let off2 = plotTopCss + plotHgtCss; - // will accum - - let off3 = plotLftCss; - let off0 = plotTopCss; - - function incrOffset(side, size) { - switch (side) { - case 1: off1 += size; return off1 - size; - case 2: off2 += size; return off2 - size; - case 3: off3 -= size; return off3 + size; - case 0: off0 -= size; return off0 + size; - } - } - - axes.forEach((axis, i) => { - if (axis.show && axis._show) { - let side = axis.side; - - axis._pos = incrOffset(side, axis._size); - - if (axis.label != null) - axis._lpos = incrOffset(side, axis.labelSize); - } - }); - } - - const cursor = (self.cursor = assign({}, cursorOpts, {drag: {y: mode == 2}}, opts.cursor)); - - { - cursor.idxs = activeIdxs; - - cursor._lock = false; - - let points = cursor.points; - - points.show = fnOrSelf(points.show); - points.size = fnOrSelf(points.size); - points.stroke = fnOrSelf(points.stroke); - points.width = fnOrSelf(points.width); - points.fill = fnOrSelf(points.fill); - } - - const focus = self.focus = assign({}, opts.focus || {alpha: 0.3}, cursor.focus); - const cursorFocus = focus.prox >= 0; - - // series-intersection markers - let cursorPts = [null]; - - function initCursorPt(s, si) { - if (si > 0) { - let pt = cursor.points.show(self, si); - - if (pt) { - addClass(pt, CURSOR_PT); - addClass(pt, s.class); - elTrans(pt, -10, -10, plotWidCss, plotHgtCss); - over.insertBefore(pt, cursorPts[si]); - - return pt; - } - } - } - - function initSeries(s, i) { - if (mode == 1 || i > 0) { - let isTime = mode == 1 && scales[s.scale].time; - - let sv = s.value; - s.value = isTime ? (isStr(sv) ? timeSeriesVal(_tzDate, timeSeriesStamp(sv, _fmtDate)) : sv || _timeSeriesVal) : sv || numSeriesVal; - s.label = s.label || (isTime ? timeSeriesLabel : numSeriesLabel); - } - - if (i > 0) { - s.width = s.width == null ? 1 : s.width; - s.paths = s.paths || linearPath || retNull; - s.fillTo = fnOrSelf(s.fillTo || seriesFillTo); - s.pxAlign = +ifNull(s.pxAlign, pxAlign); - s.pxRound = pxRoundGen(s.pxAlign); - - s.stroke = fnOrSelf(s.stroke || null); - s.fill = fnOrSelf(s.fill || null); - s._stroke = s._fill = s._paths = s._focus = null; - - let _ptDia = ptDia(s.width, 1); - let points = s.points = assign({}, { - size: _ptDia, - width: max(1, _ptDia * .2), - stroke: s.stroke, - space: _ptDia * 2, - paths: pointsPath, - _stroke: null, - _fill: null, - }, s.points); - points.show = fnOrSelf(points.show); - points.filter = fnOrSelf(points.filter); - points.fill = fnOrSelf(points.fill); - points.stroke = fnOrSelf(points.stroke); - points.paths = fnOrSelf(points.paths); - points.pxAlign = s.pxAlign; - } - - if (showLegend) { - let rowCells = initLegendRow(s, i); - legendRows.splice(i, 0, rowCells[0]); - legendCells.splice(i, 0, rowCells[1]); - legend.values.push(null); // NULL_LEGEND_VALS not yet avil here :( - } - - if (cursor.show) { - activeIdxs.splice(i, 0, null); - - let pt = initCursorPt(s, i); - pt && cursorPts.splice(i, 0, pt); - } - - fire("addSeries", i); - } - - function addSeries(opts, si) { - si = si == null ? series.length : si; - - opts = setDefault(opts, si, xSeriesOpts, ySeriesOpts); - series.splice(si, 0, opts); - initSeries(series[si], si); - } - - self.addSeries = addSeries; - - function delSeries(i) { - series.splice(i, 1); - - if (showLegend) { - legend.values.splice(i, 1); - - legendCells.splice(i, 1); - let tr = legendRows.splice(i, 1)[0]; - offMouse(null, tr.firstChild); - tr.remove(); - } - - if (cursor.show) { - activeIdxs.splice(i, 1); - - cursorPts.length > 1 && cursorPts.splice(i, 1)[0].remove(); - } - - // TODO: de-init no-longer-needed scales? - - fire("delSeries", i); - } - - self.delSeries = delSeries; - - const sidesWithAxes = [false, false, false, false]; - - function initAxis(axis, i) { - axis._show = axis.show; - - if (axis.show) { - let isVt = axis.side % 2; - - let sc = scales[axis.scale]; - - // this can occur if all series specify non-default scales - if (sc == null) { - axis.scale = isVt ? series[1].scale : xScaleKey; - sc = scales[axis.scale]; - } - - // also set defaults for incrs & values based on axis distr - let isTime = sc.time; - - axis.size = fnOrSelf(axis.size); - axis.space = fnOrSelf(axis.space); - axis.rotate = fnOrSelf(axis.rotate); - axis.incrs = fnOrSelf(axis.incrs || ( sc.distr == 2 ? wholeIncrs : (isTime ? (ms == 1 ? timeIncrsMs : timeIncrsS) : numIncrs))); - axis.splits = fnOrSelf(axis.splits || (isTime && sc.distr == 1 ? _timeAxisSplits : sc.distr == 3 ? logAxisSplits : sc.distr == 4 ? asinhAxisSplits : numAxisSplits)); - - axis.stroke = fnOrSelf(axis.stroke); - axis.grid.stroke = fnOrSelf(axis.grid.stroke); - axis.ticks.stroke = fnOrSelf(axis.ticks.stroke); - axis.border.stroke = fnOrSelf(axis.border.stroke); - - let av = axis.values; - - axis.values = ( - // static array of tick values - isArr(av) && !isArr(av[0]) ? fnOrSelf(av) : - // temporal - isTime ? ( - // config array of fmtDate string tpls - isArr(av) ? - timeAxisVals(_tzDate, timeAxisStamps(av, _fmtDate)) : - // fmtDate string tpl - isStr(av) ? - timeAxisVal(_tzDate, av) : - av || _timeAxisVals - ) : av || numAxisVals - ); - - axis.filter = fnOrSelf(axis.filter || ( sc.distr >= 3 ? logAxisValsFilt : retArg1)); - - axis.font = pxRatioFont(axis.font); - axis.labelFont = pxRatioFont(axis.labelFont); - - axis._size = axis.size(self, null, i, 0); - - axis._space = - axis._rotate = - axis._incrs = - axis._found = // foundIncrSpace - axis._splits = - axis._values = null; - - if (axis._size > 0) { - sidesWithAxes[i] = true; - axis._el = placeDiv(AXIS, wrap); - } - - // debug - // axis._el.style.background = "#" + Math.floor(Math.random()*16777215).toString(16) + '80'; - } - } - - function autoPadSide(self, side, sidesWithAxes, cycleNum) { - let [hasTopAxis, hasRgtAxis, hasBtmAxis, hasLftAxis] = sidesWithAxes; - - let ori = side % 2; - let size = 0; - - if (ori == 0 && (hasLftAxis || hasRgtAxis)) - size = (side == 0 && !hasTopAxis || side == 2 && !hasBtmAxis ? round(xAxisOpts.size / 3) : 0); - if (ori == 1 && (hasTopAxis || hasBtmAxis)) - size = (side == 1 && !hasRgtAxis || side == 3 && !hasLftAxis ? round(yAxisOpts.size / 2) : 0); - - return size; - } - - const padding = self.padding = (opts.padding || [autoPadSide,autoPadSide,autoPadSide,autoPadSide]).map(p => fnOrSelf(ifNull(p, autoPadSide))); - const _padding = self._padding = padding.map((p, i) => p(self, i, sidesWithAxes, 0)); - - let dataLen; - - // rendered data window - let i0 = null; - let i1 = null; - const idxs = mode == 1 ? series[0].idxs : null; - - let data0 = null; - - let viaAutoScaleX = false; - - function setData(_data, _resetScales) { - data = _data == null ? [] : copy(_data, fastIsObj); - - if (mode == 2) { - dataLen = 0; - for (let i = 1; i < series.length; i++) - dataLen += data[i][0].length; - self.data = data = _data; - } - else { - if (data[0] == null) - data[0] = []; - - self.data = data.slice(); - - data0 = data[0]; - dataLen = data0.length; - - if (xScaleDistr == 2) { - data[0] = Array(dataLen); - for (let i = 0; i < dataLen; i++) - data[0][i] = i; - } - } - - self._data = data; - - resetYSeries(true); - - fire("setData"); - - // forces x axis tick values to re-generate when neither x scale nor y scale changes - // in ordinal mode, scale range is by index, so will not change if new data has same length, but tick values are from data - if (xScaleDistr == 2) { - shouldConvergeSize = true; - - /* or somewhat cheaper, and uglier: - if (ready) { - // logic extracted from axesCalc() - let i = 0; - let axis = axes[i]; - let _splits = axis._splits.map(i => data0[i]); - let [_incr, _space] = axis._found; - let incr = data0[_splits[1]] - data0[_splits[0]]; - axis._values = axis.values(self, axis.filter(self, _splits, i, _space, incr), i, _space, incr); - } - */ - } - - if (_resetScales !== false) { - let xsc = scaleX; - - if (xsc.auto(self, viaAutoScaleX)) - autoScaleX(); - else - _setScale(xScaleKey, xsc.min, xsc.max); - - shouldSetCursor = cursor.left >= 0; - shouldSetLegend = true; - commit(); - } - } - - self.setData = setData; - - function autoScaleX() { - viaAutoScaleX = true; - - let _min, _max; - - if (mode == 1) { - if (dataLen > 0) { - i0 = idxs[0] = 0; - i1 = idxs[1] = dataLen - 1; - - _min = data[0][i0]; - _max = data[0][i1]; - - if (xScaleDistr == 2) { - _min = i0; - _max = i1; - } - else if (dataLen == 1) { - if (xScaleDistr == 3) - [_min, _max] = rangeLog(_min, _min, scaleX.log, false); - else if (xScaleDistr == 4) - [_min, _max] = rangeAsinh(_min, _min, scaleX.log, false); - else if (scaleX.time) - _max = _min + round(86400 / ms); - else - [_min, _max] = rangeNum(_min, _max, rangePad, true); - } - } - else { - i0 = idxs[0] = _min = null; - i1 = idxs[1] = _max = null; - } - } - - _setScale(xScaleKey, _min, _max); - } - - let ctxStroke, ctxFill, ctxWidth, ctxDash, ctxJoin, ctxCap, ctxFont, ctxAlign, ctxBaseline; - let ctxAlpha; - - function setCtxStyle(stroke = transparent, width, dash = EMPTY_ARR, cap = "butt", fill = transparent, join = "round") { - if (stroke != ctxStroke) - ctx.strokeStyle = ctxStroke = stroke; - if (fill != ctxFill) - ctx.fillStyle = ctxFill = fill; - if (width != ctxWidth) - ctx.lineWidth = ctxWidth = width; - if (join != ctxJoin) - ctx.lineJoin = ctxJoin = join; - if (cap != ctxCap) - ctx.lineCap = ctxCap = cap; // (‿|‿) - if (dash != ctxDash) - ctx.setLineDash(ctxDash = dash); - } - - function setFontStyle(font, fill, align, baseline) { - if (fill != ctxFill) - ctx.fillStyle = ctxFill = fill; - if (font != ctxFont) - ctx.font = ctxFont = font; - if (align != ctxAlign) - ctx.textAlign = ctxAlign = align; - if (baseline != ctxBaseline) - ctx.textBaseline = ctxBaseline = baseline; - } - - function accScale(wsc, psc, facet, data, sorted = 0) { - if (data.length > 0 && wsc.auto(self, viaAutoScaleX) && (psc == null || psc.min == null)) { - let _i0 = ifNull(i0, 0); - let _i1 = ifNull(i1, data.length - 1); - - // only run getMinMax() for invalidated series data, else reuse - let minMax = facet.min == null ? (wsc.distr == 3 ? getMinMaxLog(data, _i0, _i1) : getMinMax(data, _i0, _i1, sorted)) : [facet.min, facet.max]; - - // initial min/max - wsc.min = min(wsc.min, facet.min = minMax[0]); - wsc.max = max(wsc.max, facet.max = minMax[1]); - } - } - - function setScales() { - // log("setScales()", arguments); - - // wip scales - let wipScales = copy(scales, fastIsObj); - - for (let k in wipScales) { - let wsc = wipScales[k]; - let psc = pendScales[k]; - - if (psc != null && psc.min != null) { - assign(wsc, psc); - - // explicitly setting the x-scale invalidates everything (acts as redraw) - if (k == xScaleKey) - resetYSeries(true); - } - else if (k != xScaleKey || mode == 2) { - if (dataLen == 0 && wsc.from == null) { - let minMax = wsc.range(self, null, null, k); - wsc.min = minMax[0]; - wsc.max = minMax[1]; - } - else { - wsc.min = inf; - wsc.max = -inf; - } - } - } - - if (dataLen > 0) { - // pre-range y-scales from y series' data values - series.forEach((s, i) => { - if (mode == 1) { - let k = s.scale; - let wsc = wipScales[k]; - let psc = pendScales[k]; - - if (i == 0) { - let minMax = wsc.range(self, wsc.min, wsc.max, k); - - wsc.min = minMax[0]; - wsc.max = minMax[1]; - - i0 = closestIdx(wsc.min, data[0]); - i1 = closestIdx(wsc.max, data[0]); - - // closest indices can be outside of view - if (data[0][i0] < wsc.min) - i0++; - if (data[0][i1] > wsc.max) - i1--; - - s.min = data0[i0]; - s.max = data0[i1]; - } - else if (s.show && s.auto) - accScale(wsc, psc, s, data[i], s.sorted); - - s.idxs[0] = i0; - s.idxs[1] = i1; - } - else { - if (i > 0) { - if (s.show && s.auto) { - // TODO: only handles, assumes and requires facets[0] / 'x' scale, and facets[1] / 'y' scale - let [ xFacet, yFacet ] = s.facets; - let xScaleKey = xFacet.scale; - let yScaleKey = yFacet.scale; - let [ xData, yData ] = data[i]; - - accScale(wipScales[xScaleKey], pendScales[xScaleKey], xFacet, xData, xFacet.sorted); - accScale(wipScales[yScaleKey], pendScales[yScaleKey], yFacet, yData, yFacet.sorted); - - // temp - s.min = yFacet.min; - s.max = yFacet.max; - } - } - } - }); - - // range independent scales - for (let k in wipScales) { - let wsc = wipScales[k]; - let psc = pendScales[k]; - - if (wsc.from == null && (psc == null || psc.min == null)) { - let minMax = wsc.range( - self, - wsc.min == inf ? null : wsc.min, - wsc.max == -inf ? null : wsc.max, - k - ); - wsc.min = minMax[0]; - wsc.max = minMax[1]; - } - } - } - - // range dependent scales - for (let k in wipScales) { - let wsc = wipScales[k]; - - if (wsc.from != null) { - let base = wipScales[wsc.from]; - - if (base.min == null) - wsc.min = wsc.max = null; - else { - let minMax = wsc.range(self, base.min, base.max, k); - wsc.min = minMax[0]; - wsc.max = minMax[1]; - } - } - } - - let changed = {}; - let anyChanged = false; - - for (let k in wipScales) { - let wsc = wipScales[k]; - let sc = scales[k]; - - if (sc.min != wsc.min || sc.max != wsc.max) { - sc.min = wsc.min; - sc.max = wsc.max; - - let distr = sc.distr; - - sc._min = distr == 3 ? log10(sc.min) : distr == 4 ? asinh(sc.min, sc.asinh) : sc.min; - sc._max = distr == 3 ? log10(sc.max) : distr == 4 ? asinh(sc.max, sc.asinh) : sc.max; - - changed[k] = anyChanged = true; - } - } - - if (anyChanged) { - // invalidate paths of all series on changed scales - series.forEach((s, i) => { - if (mode == 2) { - if (i > 0 && changed.y) - s._paths = null; - } - else { - if (changed[s.scale]) - s._paths = null; - } - }); - - for (let k in changed) { - shouldConvergeSize = true; - fire("setScale", k); - } - - if (cursor.show) - shouldSetCursor = shouldSetLegend = cursor.left >= 0; - } - - for (let k in pendScales) - pendScales[k] = null; - } - - // grabs the nearest indices with y data outside of x-scale limits - function getOuterIdxs(ydata) { - let _i0 = clamp(i0 - 1, 0, dataLen - 1); - let _i1 = clamp(i1 + 1, 0, dataLen - 1); - - while (ydata[_i0] == null && _i0 > 0) - _i0--; - - while (ydata[_i1] == null && _i1 < dataLen - 1) - _i1++; - - return [_i0, _i1]; - } - - function drawSeries() { - if (dataLen > 0) { - series.forEach((s, i) => { - if (i > 0 && s.show && s._paths == null) { - let _idxs = getOuterIdxs(data[i]); - s._paths = s.paths(self, i, _idxs[0], _idxs[1]); - } - }); - - series.forEach((s, i) => { - if (i > 0 && s.show) { - if (ctxAlpha != s.alpha) - ctx.globalAlpha = ctxAlpha = s.alpha; - - { - cacheStrokeFill(i, false); - s._paths && drawPath(i, false); - } - - { - cacheStrokeFill(i, true); - - let show = s.points.show(self, i, i0, i1); - let idxs = s.points.filter(self, i, show, s._paths ? s._paths.gaps : null); - - if (show || idxs) { - s.points._paths = s.points.paths(self, i, i0, i1, idxs); - drawPath(i, true); - } - } - - if (ctxAlpha != 1) - ctx.globalAlpha = ctxAlpha = 1; - - fire("drawSeries", i); - } - }); - } - } - - function cacheStrokeFill(si, _points) { - let s = _points ? series[si].points : series[si]; - - s._stroke = s.stroke(self, si); - s._fill = s.fill(self, si); - } - - function drawPath(si, _points) { - let s = _points ? series[si].points : series[si]; - - let strokeStyle = s._stroke; - let fillStyle = s._fill; - - let { stroke, fill, clip: gapsClip, flags } = s._paths; - let boundsClip = null; - let width = roundDec(s.width * pxRatio, 3); - let offset = (width % 2) / 2; - - if (_points && fillStyle == null) - fillStyle = width > 0 ? "#fff" : strokeStyle; - - let _pxAlign = s.pxAlign == 1; - - _pxAlign && ctx.translate(offset, offset); - - if (!_points) { - let lft = plotLft, - top = plotTop, - wid = plotWid, - hgt = plotHgt; - - let halfWid = width * pxRatio / 2; - - if (s.min == 0) - hgt += halfWid; - - if (s.max == 0) { - top -= halfWid; - hgt += halfWid; - } - - boundsClip = new Path2D(); - boundsClip.rect(lft, top, wid, hgt); - } - - // the points pathbuilder's gapsClip is its boundsClip, since points dont need gaps clipping, and bounds depend on point size - if (_points) - strokeFill(strokeStyle, width, s.dash, s.cap, fillStyle, stroke, fill, flags, gapsClip); - else - fillStroke(si, strokeStyle, width, s.dash, s.cap, fillStyle, stroke, fill, flags, boundsClip, gapsClip); - - _pxAlign && ctx.translate(-offset, -offset); - } - - function fillStroke(si, strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip) { - let didStrokeFill = false; - - // for all bands where this series is the top edge, create upwards clips using the bottom edges - // and apply clips + fill with band fill or dfltFill - bands.forEach((b, bi) => { - // isUpperEdge? - if (b.series[0] == si) { - let lowerEdge = series[b.series[1]]; - let lowerData = data[b.series[1]]; - - let bandClip = (lowerEdge._paths || EMPTY_OBJ).band; - - if (isArr(bandClip)) - bandClip = b.dir == 1 ? bandClip[0] : bandClip[1]; - - let gapsClip2; - - let _fillStyle = null; - - // hasLowerEdge? - if (lowerEdge.show && bandClip && hasData(lowerData, i0, i1)) { - _fillStyle = b.fill(self, bi) || fillStyle; - gapsClip2 = lowerEdge._paths.clip; - } - else - bandClip = null; - - strokeFill(strokeStyle, lineWidth, lineDash, lineCap, _fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip, gapsClip2, bandClip); - - didStrokeFill = true; - } - }); - - if (!didStrokeFill) - strokeFill(strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip); - } - - const CLIP_FILL_STROKE = BAND_CLIP_FILL | BAND_CLIP_STROKE; - - function strokeFill(strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip, gapsClip2, bandClip) { - setCtxStyle(strokeStyle, lineWidth, lineDash, lineCap, fillStyle); - - if (boundsClip || gapsClip || bandClip) { - ctx.save(); - boundsClip && ctx.clip(boundsClip); - gapsClip && ctx.clip(gapsClip); - } - - if (bandClip) { - if ((flags & CLIP_FILL_STROKE) == CLIP_FILL_STROKE) { - ctx.clip(bandClip); - gapsClip2 && ctx.clip(gapsClip2); - doFill(fillStyle, fillPath); - doStroke(strokeStyle, strokePath, lineWidth); - } - else if (flags & BAND_CLIP_STROKE) { - doFill(fillStyle, fillPath); - ctx.clip(bandClip); - doStroke(strokeStyle, strokePath, lineWidth); - } - else if (flags & BAND_CLIP_FILL) { - ctx.save(); - ctx.clip(bandClip); - gapsClip2 && ctx.clip(gapsClip2); - doFill(fillStyle, fillPath); - ctx.restore(); - doStroke(strokeStyle, strokePath, lineWidth); - } - } - else { - doFill(fillStyle, fillPath); - doStroke(strokeStyle, strokePath, lineWidth); - } - - if (boundsClip || gapsClip || bandClip) - ctx.restore(); - } - - function doStroke(strokeStyle, strokePath, lineWidth) { - if (lineWidth > 0) { - if (strokePath instanceof Map) { - strokePath.forEach((strokePath, strokeStyle) => { - ctx.strokeStyle = ctxStroke = strokeStyle; - ctx.stroke(strokePath); - }); - } - else - strokePath != null && strokeStyle && ctx.stroke(strokePath); - } - } - - function doFill(fillStyle, fillPath) { - if (fillPath instanceof Map) { - fillPath.forEach((fillPath, fillStyle) => { - ctx.fillStyle = ctxFill = fillStyle; - ctx.fill(fillPath); - }); - } - else - fillPath != null && fillStyle && ctx.fill(fillPath); - } - - function getIncrSpace(axisIdx, min, max, fullDim) { - let axis = axes[axisIdx]; - - let incrSpace; - - if (fullDim <= 0) - incrSpace = [0, 0]; - else { - let minSpace = axis._space = axis.space(self, axisIdx, min, max, fullDim); - let incrs = axis._incrs = axis.incrs(self, axisIdx, min, max, fullDim, minSpace); - incrSpace = findIncr(min, max, incrs, fullDim, minSpace); - } - - return (axis._found = incrSpace); - } - - function drawOrthoLines(offs, filts, ori, side, pos0, len, width, stroke, dash, cap) { - let offset = (width % 2) / 2; - - pxAlign == 1 && ctx.translate(offset, offset); - - setCtxStyle(stroke, width, dash, cap, stroke); - - ctx.beginPath(); - - let x0, y0, x1, y1, pos1 = pos0 + (side == 0 || side == 3 ? -len : len); - - if (ori == 0) { - y0 = pos0; - y1 = pos1; - } - else { - x0 = pos0; - x1 = pos1; - } - - for (let i = 0; i < offs.length; i++) { - if (filts[i] != null) { - if (ori == 0) - x0 = x1 = offs[i]; - else - y0 = y1 = offs[i]; - - ctx.moveTo(x0, y0); - ctx.lineTo(x1, y1); - } - } - - ctx.stroke(); - - pxAlign == 1 && ctx.translate(-offset, -offset); - } - - function axesCalc(cycleNum) { - // log("axesCalc()", arguments); - - let converged = true; - - axes.forEach((axis, i) => { - if (!axis.show) - return; - - let scale = scales[axis.scale]; - - if (scale.min == null) { - if (axis._show) { - converged = false; - axis._show = false; - resetYSeries(false); - } - return; - } - else { - if (!axis._show) { - converged = false; - axis._show = true; - resetYSeries(false); - } - } - - let side = axis.side; - let ori = side % 2; - - let {min, max} = scale; // // should this toggle them ._show = false - - let [_incr, _space] = getIncrSpace(i, min, max, ori == 0 ? plotWidCss : plotHgtCss); - - if (_space == 0) - return; - - // if we're using index positions, force first tick to match passed index - let forceMin = scale.distr == 2; - - let _splits = axis._splits = axis.splits(self, i, min, max, _incr, _space, forceMin); - - // tick labels - // BOO this assumes a specific data/series - let splits = scale.distr == 2 ? _splits.map(i => data0[i]) : _splits; - let incr = scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr; - - let values = axis._values = axis.values(self, axis.filter(self, splits, i, _space, incr), i, _space, incr); - - // rotating of labels only supported on bottom x axis - axis._rotate = side == 2 ? axis.rotate(self, values, i, _space) : 0; - - let oldSize = axis._size; - - axis._size = ceil(axis.size(self, values, i, cycleNum)); - - if (oldSize != null && axis._size != oldSize) // ready && ? - converged = false; - }); - - return converged; - } - - function paddingCalc(cycleNum) { - let converged = true; - - padding.forEach((p, i) => { - let _p = p(self, i, sidesWithAxes, cycleNum); - - if (_p != _padding[i]) - converged = false; - - _padding[i] = _p; - }); - - return converged; - } - - function drawAxesGrid() { - for (let i = 0; i < axes.length; i++) { - let axis = axes[i]; - - if (!axis.show || !axis._show) - continue; - - let side = axis.side; - let ori = side % 2; - - let x, y; - - let fillStyle = axis.stroke(self, i); - - let shiftDir = side == 0 || side == 3 ? -1 : 1; - - // axis label - if (axis.label) { - let shiftAmt = axis.labelGap * shiftDir; - let baseLpos = round((axis._lpos + shiftAmt) * pxRatio); - - setFontStyle(axis.labelFont[0], fillStyle, "center", side == 2 ? TOP : BOTTOM); - - ctx.save(); - - if (ori == 1) { - x = y = 0; - - ctx.translate( - baseLpos, - round(plotTop + plotHgt / 2), - ); - ctx.rotate((side == 3 ? -PI : PI) / 2); - - } - else { - x = round(plotLft + plotWid / 2); - y = baseLpos; - } - - ctx.fillText(axis.label, x, y); - - ctx.restore(); - } - - let [_incr, _space] = axis._found; - - if (_space == 0) - continue; - - let scale = scales[axis.scale]; - - let plotDim = ori == 0 ? plotWid : plotHgt; - let plotOff = ori == 0 ? plotLft : plotTop; - - let axisGap = round(axis.gap * pxRatio); - - let _splits = axis._splits; - - // tick labels - // BOO this assumes a specific data/series - let splits = scale.distr == 2 ? _splits.map(i => data0[i]) : _splits; - let incr = scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr; - - let ticks = axis.ticks; - let border = axis.border; - let tickSize = ticks.show ? round(ticks.size * pxRatio) : 0; - - // rotating of labels only supported on bottom x axis - let angle = axis._rotate * -PI/180; - - let basePos = pxRound(axis._pos * pxRatio); - let shiftAmt = (tickSize + axisGap) * shiftDir; - let finalPos = basePos + shiftAmt; - y = ori == 0 ? finalPos : 0; - x = ori == 1 ? finalPos : 0; - - let font = axis.font[0]; - let textAlign = axis.align == 1 ? LEFT : - axis.align == 2 ? RIGHT : - angle > 0 ? LEFT : - angle < 0 ? RIGHT : - ori == 0 ? "center" : side == 3 ? RIGHT : LEFT; - let textBaseline = angle || - ori == 1 ? "middle" : side == 2 ? TOP : BOTTOM; - - setFontStyle(font, fillStyle, textAlign, textBaseline); - - let lineHeight = axis.font[1] * lineMult; - - let canOffs = _splits.map(val => pxRound(getPos(val, scale, plotDim, plotOff))); - - let _values = axis._values; - - for (let i = 0; i < _values.length; i++) { - let val = _values[i]; - - if (val != null) { - if (ori == 0) - x = canOffs[i]; - else - y = canOffs[i]; - - val = "" + val; - - let _parts = val.indexOf("\n") == -1 ? [val] : val.split(/\n/gm); - - for (let j = 0; j < _parts.length; j++) { - let text = _parts[j]; - - if (angle) { - ctx.save(); - ctx.translate(x, y + j * lineHeight); // can this be replaced with position math? - ctx.rotate(angle); // can this be done once? - ctx.fillText(text, 0, 0); - ctx.restore(); - } - else - ctx.fillText(text, x, y + j * lineHeight); - } - } - } - - // ticks - if (ticks.show) { - drawOrthoLines( - canOffs, - ticks.filter(self, splits, i, _space, incr), - ori, - side, - basePos, - tickSize, - roundDec(ticks.width * pxRatio, 3), - ticks.stroke(self, i), - ticks.dash, - ticks.cap, - ); - } - - // grid - let grid = axis.grid; - - if (grid.show) { - drawOrthoLines( - canOffs, - grid.filter(self, splits, i, _space, incr), - ori, - ori == 0 ? 2 : 1, - ori == 0 ? plotTop : plotLft, - ori == 0 ? plotHgt : plotWid, - roundDec(grid.width * pxRatio, 3), - grid.stroke(self, i), - grid.dash, - grid.cap, - ); - } - - if (border.show) { - drawOrthoLines( - [basePos], - [1], - ori == 0 ? 1 : 0, - ori == 0 ? 1 : 2, - ori == 1 ? plotTop : plotLft, - ori == 1 ? plotHgt : plotWid, - roundDec(border.width * pxRatio, 3), - border.stroke(self, i), - border.dash, - border.cap, - ); - } - } - - fire("drawAxes"); - } - - function resetYSeries(minMax) { - // log("resetYSeries()", arguments); - - series.forEach((s, i) => { - if (i > 0) { - s._paths = null; - - if (minMax) { - if (mode == 1) { - s.min = null; - s.max = null; - } - else { - s.facets.forEach(f => { - f.min = null; - f.max = null; - }); - } - } - } - }); - } - - let queuedCommit = false; - - function commit() { - if (!queuedCommit) { - microTask(_commit); - queuedCommit = true; - } - } - - function _commit() { - // log("_commit()", arguments); - - if (shouldSetScales) { - setScales(); - shouldSetScales = false; - } - - if (shouldConvergeSize) { - convergeSize(); - shouldConvergeSize = false; - } - - if (shouldSetSize) { - setStylePx(under, LEFT, plotLftCss); - setStylePx(under, TOP, plotTopCss); - setStylePx(under, WIDTH, plotWidCss); - setStylePx(under, HEIGHT, plotHgtCss); - - setStylePx(over, LEFT, plotLftCss); - setStylePx(over, TOP, plotTopCss); - setStylePx(over, WIDTH, plotWidCss); - setStylePx(over, HEIGHT, plotHgtCss); - - setStylePx(wrap, WIDTH, fullWidCss); - setStylePx(wrap, HEIGHT, fullHgtCss); - - // NOTE: mutating this during print preview in Chrome forces transparent - // canvas pixels to white, even when followed up with clearRect() below - can.width = round(fullWidCss * pxRatio); - can.height = round(fullHgtCss * pxRatio); - - axes.forEach(({ _el, _show, _size, _pos, side }) => { - if (_el != null) { - if (_show) { - let posOffset = (side === 3 || side === 0 ? _size : 0); - let isVt = side % 2 == 1; - - setStylePx(_el, isVt ? "left" : "top", _pos - posOffset); - setStylePx(_el, isVt ? "width" : "height", _size); - setStylePx(_el, isVt ? "top" : "left", isVt ? plotTopCss : plotLftCss); - setStylePx(_el, isVt ? "height" : "width", isVt ? plotHgtCss : plotWidCss); - - remClass(_el, OFF); - } - else - addClass(_el, OFF); - } - }); - - // invalidate ctx style cache - ctxStroke = ctxFill = ctxWidth = ctxJoin = ctxCap = ctxFont = ctxAlign = ctxBaseline = ctxDash = null; - ctxAlpha = 1; - - syncRect(true); - - fire("setSize"); - - shouldSetSize = false; - } - - if (fullWidCss > 0 && fullHgtCss > 0) { - ctx.clearRect(0, 0, can.width, can.height); - fire("drawClear"); - drawOrder.forEach(fn => fn()); - fire("draw"); - } - - // if (shouldSetSelect) { - // TODO: update .u-select metrics (if visible) - // setStylePx(selectDiv, TOP, select.top = 0); - // setStylePx(selectDiv, LEFT, select.left = 0); - // setStylePx(selectDiv, WIDTH, select.width = 0); - // setStylePx(selectDiv, HEIGHT, select.height = 0); - // shouldSetSelect = false; - // } - - if (cursor.show && shouldSetCursor) { - updateCursor(null, true, false); - shouldSetCursor = false; - } - - // if (FEAT_LEGEND && legend.show && legend.live && shouldSetLegend) {} - - if (!ready) { - ready = true; - self.status = 1; - - fire("ready"); - } - - viaAutoScaleX = false; - - queuedCommit = false; - } - - self.redraw = (rebuildPaths, recalcAxes) => { - shouldConvergeSize = recalcAxes || false; - - if (rebuildPaths !== false) - _setScale(xScaleKey, scaleX.min, scaleX.max); - else - commit(); - }; - - // redraw() => setScale('x', scales.x.min, scales.x.max); - - // explicit, never re-ranged (is this actually true? for x and y) - function setScale(key, opts) { - let sc = scales[key]; - - if (sc.from == null) { - if (dataLen == 0) { - let minMax = sc.range(self, opts.min, opts.max, key); - opts.min = minMax[0]; - opts.max = minMax[1]; - } - - if (opts.min > opts.max) { - let _min = opts.min; - opts.min = opts.max; - opts.max = _min; - } - - if (dataLen > 1 && opts.min != null && opts.max != null && opts.max - opts.min < 1e-16) - return; - - if (key == xScaleKey) { - if (sc.distr == 2 && dataLen > 0) { - opts.min = closestIdx(opts.min, data[0]); - opts.max = closestIdx(opts.max, data[0]); - - if (opts.min == opts.max) - opts.max++; - } - } - - // log("setScale()", arguments); - - pendScales[key] = opts; - - shouldSetScales = true; - commit(); - } - } - - self.setScale = setScale; - -// INTERACTION - - let xCursor; - let yCursor; - let vCursor; - let hCursor; - - // starting position before cursor.move - let rawMouseLeft0; - let rawMouseTop0; - - // starting position - let mouseLeft0; - let mouseTop0; - - // current position before cursor.move - let rawMouseLeft1; - let rawMouseTop1; - - // current position - let mouseLeft1; - let mouseTop1; - - let dragging = false; - - const drag = cursor.drag; - - let dragX = drag.x; - let dragY = drag.y; - - if (cursor.show) { - if (cursor.x) - xCursor = placeDiv(CURSOR_X, over); - if (cursor.y) - yCursor = placeDiv(CURSOR_Y, over); - - if (scaleX.ori == 0) { - vCursor = xCursor; - hCursor = yCursor; - } - else { - vCursor = yCursor; - hCursor = xCursor; - } - - mouseLeft1 = cursor.left; - mouseTop1 = cursor.top; - } - - const select = self.select = assign({ - show: true, - over: true, - left: 0, - width: 0, - top: 0, - height: 0, - }, opts.select); - - const selectDiv = select.show ? placeDiv(SELECT, select.over ? over : under) : null; - - function setSelect(opts, _fire) { - if (select.show) { - for (let prop in opts) - setStylePx(selectDiv, prop, select[prop] = opts[prop]); - - _fire !== false && fire("setSelect"); - } - } - - self.setSelect = setSelect; - - function toggleDOM(i, onOff) { - let s = series[i]; - let label = showLegend ? legendRows[i] : null; - - if (s.show) - label && remClass(label, OFF); - else { - label && addClass(label, OFF); - cursorPts.length > 1 && elTrans(cursorPts[i], -10, -10, plotWidCss, plotHgtCss); - } - } - - function _setScale(key, min, max) { - setScale(key, {min, max}); - } - - function setSeries(i, opts, _fire, _pub) { - // log("setSeries()", arguments); - - if (opts.focus != null) - setFocus(i); - - if (opts.show != null) { - series.forEach((s, si) => { - if (si > 0 && (i == si || i == null)) { - s.show = opts.show; - toggleDOM(si, opts.show); - - _setScale(mode == 2 ? s.facets[1].scale : s.scale, null, null); - commit(); - } - }); - } - - _fire !== false && fire("setSeries", i, opts); - - _pub && pubSync("setSeries", self, i, opts); - } - - self.setSeries = setSeries; - - function setBand(bi, opts) { - assign(bands[bi], opts); - } - - function addBand(opts, bi) { - opts.fill = fnOrSelf(opts.fill || null); - opts.dir = ifNull(opts.dir, -1); - bi = bi == null ? bands.length : bi; - bands.splice(bi, 0, opts); - } - - function delBand(bi) { - if (bi == null) - bands.length = 0; - else - bands.splice(bi, 1); - } - - self.addBand = addBand; - self.setBand = setBand; - self.delBand = delBand; - - function setAlpha(i, value) { - series[i].alpha = value; - - if (cursor.show && cursorPts[i]) - cursorPts[i].style.opacity = value; - - if (showLegend && legendRows[i]) - legendRows[i].style.opacity = value; - } - - // y-distance - let closestDist; - let closestSeries; - let focusedSeries; - const FOCUS_TRUE = {focus: true}; - - function setFocus(i) { - if (i != focusedSeries) { - // log("setFocus()", arguments); - - let allFocused = i == null; - - let _setAlpha = focus.alpha != 1; - - series.forEach((s, i2) => { - let isFocused = allFocused || i2 == 0 || i2 == i; - s._focus = allFocused ? null : isFocused; - _setAlpha && setAlpha(i2, isFocused ? 1 : focus.alpha); - }); - - focusedSeries = i; - _setAlpha && commit(); - } - } - - if (showLegend && cursorFocus) { - on(mouseleave, legendEl, e => { - if (cursor._lock) - return; - - if (focusedSeries != null) - setSeries(null, FOCUS_TRUE, true, syncOpts.setSeries); - }); - } - - function posToVal(pos, scale, can) { - let sc = scales[scale]; - - if (can) - pos = pos / pxRatio - (sc.ori == 1 ? plotTopCss : plotLftCss); - - let dim = plotWidCss; - - if (sc.ori == 1) { - dim = plotHgtCss; - pos = dim - pos; - } - - if (sc.dir == -1) - pos = dim - pos; - - let _min = sc._min, - _max = sc._max, - pct = pos / dim; - - let sv = _min + (_max - _min) * pct; - - let distr = sc.distr; - - return ( - distr == 3 ? pow(10, sv) : - distr == 4 ? sinh(sv, sc.asinh) : - sv - ); - } - - function closestIdxFromXpos(pos, can) { - let v = posToVal(pos, xScaleKey, can); - return closestIdx(v, data[0], i0, i1); - } - - self.valToIdx = val => closestIdx(val, data[0]); - self.posToIdx = closestIdxFromXpos; - self.posToVal = posToVal; - self.valToPos = (val, scale, can) => ( - scales[scale].ori == 0 ? - getHPos(val, scales[scale], - can ? plotWid : plotWidCss, - can ? plotLft : 0, - ) : - getVPos(val, scales[scale], - can ? plotHgt : plotHgtCss, - can ? plotTop : 0, - ) - ); - - // defers calling expensive functions - function batch(fn) { - fn(self); - commit(); - } - - self.batch = batch; - - (self.setCursor = (opts, _fire, _pub) => { - mouseLeft1 = opts.left; - mouseTop1 = opts.top; - // assign(cursor, opts); - updateCursor(null, _fire, _pub); - }); - - function setSelH(off, dim) { - setStylePx(selectDiv, LEFT, select.left = off); - setStylePx(selectDiv, WIDTH, select.width = dim); - } - - function setSelV(off, dim) { - setStylePx(selectDiv, TOP, select.top = off); - setStylePx(selectDiv, HEIGHT, select.height = dim); - } - - let setSelX = scaleX.ori == 0 ? setSelH : setSelV; - let setSelY = scaleX.ori == 1 ? setSelH : setSelV; - - function syncLegend() { - if (showLegend && legend.live) { - for (let i = mode == 2 ? 1 : 0; i < series.length; i++) { - if (i == 0 && multiValLegend) - continue; - - let vals = legend.values[i]; - - let j = 0; - - for (let k in vals) - legendCells[i][j++].firstChild.nodeValue = vals[k]; - } - } - } - - function setLegend(opts, _fire) { - if (opts != null) { - let idx = opts.idx; - - legend.idx = idx; - series.forEach((s, sidx) => { - (sidx > 0 || !multiValLegend) && setLegendValues(sidx, idx); - }); - } - - if (showLegend && legend.live) - syncLegend(); - - shouldSetLegend = false; - - _fire !== false && fire("setLegend"); - } - - self.setLegend = setLegend; - - function setLegendValues(sidx, idx) { - let val; - - if (idx == null) - val = NULL_LEGEND_VALUES; - else { - let s = series[sidx]; - let src = sidx == 0 && xScaleDistr == 2 ? data0 : data[sidx]; - val = multiValLegend ? s.values(self, sidx, idx) : {_: s.value(self, src[idx], sidx, idx)}; - } - - legend.values[sidx] = val; - } - - function updateCursor(src, _fire, _pub) { - // ts == null && log("updateCursor()", arguments); - - rawMouseLeft1 = mouseLeft1; - rawMouseTop1 = mouseTop1; - - [mouseLeft1, mouseTop1] = cursor.move(self, mouseLeft1, mouseTop1); - - if (cursor.show) { - vCursor && elTrans(vCursor, round(mouseLeft1), 0, plotWidCss, plotHgtCss); - hCursor && elTrans(hCursor, 0, round(mouseTop1), plotWidCss, plotHgtCss); - } - - let idx; - - // when zooming to an x scale range between datapoints the binary search - // for nearest min/max indices results in this condition. cheap hack :D - let noDataInRange = i0 > i1; // works for mode 1 only - - closestDist = inf; - - // TODO: extract - let xDim = scaleX.ori == 0 ? plotWidCss : plotHgtCss; - let yDim = scaleX.ori == 1 ? plotWidCss : plotHgtCss; - - // if cursor hidden, hide points & clear legend vals - if (mouseLeft1 < 0 || dataLen == 0 || noDataInRange) { - idx = null; - - for (let i = 0; i < series.length; i++) { - if (i > 0) { - cursorPts.length > 1 && elTrans(cursorPts[i], -10, -10, plotWidCss, plotHgtCss); - } - } - - if (cursorFocus) - setSeries(null, FOCUS_TRUE, true, src == null && syncOpts.setSeries); - - if (legend.live) { - activeIdxs.fill(null); - shouldSetLegend = true; - - for (let i = 0; i < series.length; i++) - legend.values[i] = NULL_LEGEND_VALUES; - } - } - else { - // let pctY = 1 - (y / rect.height); - - let mouseXPos, valAtPosX, xPos; - - if (mode == 1) { - mouseXPos = scaleX.ori == 0 ? mouseLeft1 : mouseTop1; - valAtPosX = posToVal(mouseXPos, xScaleKey); - idx = closestIdx(valAtPosX, data[0], i0, i1); - xPos = incrRoundUp(valToPosX(data[0][idx], scaleX, xDim, 0), 0.5); - } - - for (let i = mode == 2 ? 1 : 0; i < series.length; i++) { - let s = series[i]; - - let idx1 = activeIdxs[i]; - let yVal1 = mode == 1 ? data[i][idx1] : data[i][1][idx1]; - - let idx2 = cursor.dataIdx(self, i, idx, valAtPosX); - let yVal2 = mode == 1 ? data[i][idx2] : data[i][1][idx2]; - - shouldSetLegend = shouldSetLegend || yVal2 != yVal1 || idx2 != idx1; - - activeIdxs[i] = idx2; - - let xPos2 = idx2 == idx ? xPos : incrRoundUp(valToPosX(mode == 1 ? data[0][idx2] : data[i][0][idx2], scaleX, xDim, 0), 0.5); - - if (i > 0 && s.show) { - let yPos = yVal2 == null ? -10 : incrRoundUp(valToPosY(yVal2, mode == 1 ? scales[s.scale] : scales[s.facets[1].scale], yDim, 0), 0.5); - - if (yPos > 0 && mode == 1) { - let dist = abs(yPos - mouseTop1); - - if (dist <= closestDist) { - closestDist = dist; - closestSeries = i; - } - } - - let hPos, vPos; - - if (scaleX.ori == 0) { - hPos = xPos2; - vPos = yPos; - } - else { - hPos = yPos; - vPos = xPos2; - } - - if (shouldSetLegend && cursorPts.length > 1) { - elColor(cursorPts[i], cursor.points.fill(self, i), cursor.points.stroke(self, i)); - - let ptWid, ptHgt, ptLft, ptTop, - centered = true, - getBBox = cursor.points.bbox; - - if (getBBox != null) { - centered = false; - - let bbox = getBBox(self, i); - - ptLft = bbox.left; - ptTop = bbox.top; - ptWid = bbox.width; - ptHgt = bbox.height; - } - else { - ptLft = hPos; - ptTop = vPos; - ptWid = ptHgt = cursor.points.size(self, i); - } - - elSize(cursorPts[i], ptWid, ptHgt, centered); - elTrans(cursorPts[i], ptLft, ptTop, plotWidCss, plotHgtCss); - } - } - - if (legend.live) { - if (!shouldSetLegend || i == 0 && multiValLegend) - continue; - - setLegendValues(i, idx2); - } - } - } - - cursor.idx = idx; - cursor.left = mouseLeft1; - cursor.top = mouseTop1; - - if (shouldSetLegend) { - legend.idx = idx; - setLegend(); - } - - // nit: cursor.drag.setSelect is assumed always true - if (select.show && dragging) { - if (src != null) { - let [xKey, yKey] = syncOpts.scales; - let [matchXKeys, matchYKeys] = syncOpts.match; - let [xKeySrc, yKeySrc] = src.cursor.sync.scales; - - // match the dragX/dragY implicitness/explicitness of src - let sdrag = src.cursor.drag; - dragX = sdrag._x; - dragY = sdrag._y; - - if (dragX || dragY) { - let { left, top, width, height } = src.select; - - let sori = src.scales[xKey].ori; - let sPosToVal = src.posToVal; - - let sOff, sDim, sc, a, b; - - let matchingX = xKey != null && matchXKeys(xKey, xKeySrc); - let matchingY = yKey != null && matchYKeys(yKey, yKeySrc); - - if (matchingX && dragX) { - if (sori == 0) { - sOff = left; - sDim = width; - } - else { - sOff = top; - sDim = height; - } - - sc = scales[xKey]; - - a = valToPosX(sPosToVal(sOff, xKeySrc), sc, xDim, 0); - b = valToPosX(sPosToVal(sOff + sDim, xKeySrc), sc, xDim, 0); - - setSelX(min(a,b), abs(b-a)); - } - else - setSelX(0, xDim); - - if (matchingY && dragY) { - if (sori == 1) { - sOff = left; - sDim = width; - } - else { - sOff = top; - sDim = height; - } - - sc = scales[yKey]; - - a = valToPosY(sPosToVal(sOff, yKeySrc), sc, yDim, 0); - b = valToPosY(sPosToVal(sOff + sDim, yKeySrc), sc, yDim, 0); - - setSelY(min(a,b), abs(b-a)); - } - else - setSelY(0, yDim); - } - else - hideSelect(); - } - else { - let rawDX = abs(rawMouseLeft1 - rawMouseLeft0); - let rawDY = abs(rawMouseTop1 - rawMouseTop0); - - if (scaleX.ori == 1) { - let _rawDX = rawDX; - rawDX = rawDY; - rawDY = _rawDX; - } - - dragX = drag.x && rawDX >= drag.dist; - dragY = drag.y && rawDY >= drag.dist; - - let uni = drag.uni; - - if (uni != null) { - // only calc drag status if they pass the dist thresh - if (dragX && dragY) { - dragX = rawDX >= uni; - dragY = rawDY >= uni; - - // force unidirectionality when both are under uni limit - if (!dragX && !dragY) { - if (rawDY > rawDX) - dragY = true; - else - dragX = true; - } - } - } - else if (drag.x && drag.y && (dragX || dragY)) - // if omni with no uni then both dragX / dragY should be true if either is true - dragX = dragY = true; - - let p0, p1; - - if (dragX) { - if (scaleX.ori == 0) { - p0 = mouseLeft0; - p1 = mouseLeft1; - } - else { - p0 = mouseTop0; - p1 = mouseTop1; - } - - setSelX(min(p0, p1), abs(p1 - p0)); - - if (!dragY) - setSelY(0, yDim); - } - - if (dragY) { - if (scaleX.ori == 1) { - p0 = mouseLeft0; - p1 = mouseLeft1; - } - else { - p0 = mouseTop0; - p1 = mouseTop1; - } - - setSelY(min(p0, p1), abs(p1 - p0)); - - if (!dragX) - setSelX(0, xDim); - } - - // the drag didn't pass the dist requirement - if (!dragX && !dragY) { - setSelX(0, 0); - setSelY(0, 0); - } - } - } - - drag._x = dragX; - drag._y = dragY; - - if (src == null) { - if (_pub) { - if (syncKey != null) { - let [xSyncKey, ySyncKey] = syncOpts.scales; - - syncOpts.values[0] = xSyncKey != null ? posToVal(scaleX.ori == 0 ? mouseLeft1 : mouseTop1, xSyncKey) : null; - syncOpts.values[1] = ySyncKey != null ? posToVal(scaleX.ori == 1 ? mouseLeft1 : mouseTop1, ySyncKey) : null; - } - - pubSync(mousemove, self, mouseLeft1, mouseTop1, plotWidCss, plotHgtCss, idx); - } - - if (cursorFocus) { - let shouldPub = _pub && syncOpts.setSeries; - let p = focus.prox; - - if (focusedSeries == null) { - if (closestDist <= p) - setSeries(closestSeries, FOCUS_TRUE, true, shouldPub); - } - else { - if (closestDist > p) - setSeries(null, FOCUS_TRUE, true, shouldPub); - else if (closestSeries != focusedSeries) - setSeries(closestSeries, FOCUS_TRUE, true, shouldPub); - } - } - } - - ready && _fire !== false && fire("setCursor"); - } - - let rect = null; - - function syncRect(defer) { - if (defer === true) - rect = null; - else { - rect = over.getBoundingClientRect(); - fire("syncRect", rect); - } - } - - function mouseMove(e, src, _l, _t, _w, _h, _i) { - if (cursor._lock) - return; - - cacheMouse(e, src, _l, _t, _w, _h, _i, false, e != null); - - if (e != null) - updateCursor(null, true, true); - else - updateCursor(src, true, false); - } - - function cacheMouse(e, src, _l, _t, _w, _h, _i, initial, snap) { - if (rect == null) - syncRect(false); - - if (e != null) { - _l = e.clientX - rect.left; - _t = e.clientY - rect.top; - } - else { - if (_l < 0 || _t < 0) { - mouseLeft1 = -10; - mouseTop1 = -10; - return; - } - - let [xKey, yKey] = syncOpts.scales; - - let syncOptsSrc = src.cursor.sync; - let [xValSrc, yValSrc] = syncOptsSrc.values; - let [xKeySrc, yKeySrc] = syncOptsSrc.scales; - let [matchXKeys, matchYKeys] = syncOpts.match; - - let rotSrc = src.axes[0].side % 2 == 1; - - let xDim = scaleX.ori == 0 ? plotWidCss : plotHgtCss, - yDim = scaleX.ori == 1 ? plotWidCss : plotHgtCss, - _xDim = rotSrc ? _h : _w, - _yDim = rotSrc ? _w : _h, - _xPos = rotSrc ? _t : _l, - _yPos = rotSrc ? _l : _t; - - if (xKeySrc != null) - _l = matchXKeys(xKey, xKeySrc) ? getPos(xValSrc, scales[xKey], xDim, 0) : -10; - else - _l = xDim * (_xPos/_xDim); - - if (yKeySrc != null) - _t = matchYKeys(yKey, yKeySrc) ? getPos(yValSrc, scales[yKey], yDim, 0) : -10; - else - _t = yDim * (_yPos/_yDim); - - if (scaleX.ori == 1) { - let __l = _l; - _l = _t; - _t = __l; - } - } - - if (snap) { - if (_l <= 1 || _l >= plotWidCss - 1) - _l = incrRound(_l, plotWidCss); - - if (_t <= 1 || _t >= plotHgtCss - 1) - _t = incrRound(_t, plotHgtCss); - } - - if (initial) { - rawMouseLeft0 = _l; - rawMouseTop0 = _t; - - [mouseLeft0, mouseTop0] = cursor.move(self, _l, _t); - } - else { - mouseLeft1 = _l; - mouseTop1 = _t; - } - } - - const _hideProps = { - width: 0, - height: 0, - }; - - function hideSelect() { - setSelect(_hideProps, false); - } - - function mouseDown(e, src, _l, _t, _w, _h, _i) { - dragging = true; - dragX = dragY = drag._x = drag._y = false; - - cacheMouse(e, src, _l, _t, _w, _h, _i, true, false); - - if (e != null) { - onMouse(mouseup, doc, mouseUp); - pubSync(mousedown, self, mouseLeft0, mouseTop0, plotWidCss, plotHgtCss, null); - } - } - - function mouseUp(e, src, _l, _t, _w, _h, _i) { - dragging = drag._x = drag._y = false; - - cacheMouse(e, src, _l, _t, _w, _h, _i, false, true); - - let { left, top, width, height } = select; - - let hasSelect = width > 0 || height > 0; - - hasSelect && setSelect(select); - - if (drag.setScale && hasSelect) { - // if (syncKey != null) { - // dragX = drag.x; - // dragY = drag.y; - // } - - let xOff = left, - xDim = width, - yOff = top, - yDim = height; - - if (scaleX.ori == 1) { - xOff = top, - xDim = height, - yOff = left, - yDim = width; - } - - if (dragX) { - _setScale(xScaleKey, - posToVal(xOff, xScaleKey), - posToVal(xOff + xDim, xScaleKey) - ); - } - - if (dragY) { - for (let k in scales) { - let sc = scales[k]; - - if (k != xScaleKey && sc.from == null && sc.min != inf) { - _setScale(k, - posToVal(yOff + yDim, k), - posToVal(yOff, k) - ); - } - } - } - - hideSelect(); - } - else if (cursor.lock) { - cursor._lock = !cursor._lock; - - if (!cursor._lock) - updateCursor(null, true, false); - } - - if (e != null) { - offMouse(mouseup, doc); - pubSync(mouseup, self, mouseLeft1, mouseTop1, plotWidCss, plotHgtCss, null); - } - } - - function mouseLeave(e, src, _l, _t, _w, _h, _i) { - if (!cursor._lock) { - let _dragging = dragging; - - if (dragging) { - // handle case when mousemove aren't fired all the way to edges by browser - let snapH = true; - let snapV = true; - let snapProx = 10; - - let dragH, dragV; - - if (scaleX.ori == 0) { - dragH = dragX; - dragV = dragY; - } - else { - dragH = dragY; - dragV = dragX; - } - - if (dragH && dragV) { - // maybe omni corner snap - snapH = mouseLeft1 <= snapProx || mouseLeft1 >= plotWidCss - snapProx; - snapV = mouseTop1 <= snapProx || mouseTop1 >= plotHgtCss - snapProx; - } - - if (dragH && snapH) - mouseLeft1 = mouseLeft1 < mouseLeft0 ? 0 : plotWidCss; - - if (dragV && snapV) - mouseTop1 = mouseTop1 < mouseTop0 ? 0 : plotHgtCss; - - updateCursor(null, true, true); - - dragging = false; - } - - mouseLeft1 = -10; - mouseTop1 = -10; - - // passing a non-null timestamp to force sync/mousemove event - updateCursor(null, true, true); - - if (_dragging) - dragging = _dragging; - } - } - - function dblClick(e, src, _l, _t, _w, _h, _i) { - autoScaleX(); - - hideSelect(); - - if (e != null) - pubSync(dblclick, self, mouseLeft1, mouseTop1, plotWidCss, plotHgtCss, null); - } - - function syncPxRatio() { - axes.forEach(syncFontSize); - _setSize(self.width, self.height, true); - } - - on(dppxchange, win, syncPxRatio); - - // internal pub/sub - const events = {}; - - events.mousedown = mouseDown; - events.mousemove = mouseMove; - events.mouseup = mouseUp; - events.dblclick = dblClick; - events["setSeries"] = (e, src, idx, opts) => { - setSeries(idx, opts, true, false); - }; - - if (cursor.show) { - onMouse(mousedown, over, mouseDown); - onMouse(mousemove, over, mouseMove); - onMouse(mouseenter, over, syncRect); - onMouse(mouseleave, over, mouseLeave); - - onMouse(dblclick, over, dblClick); - - cursorPlots.add(self); - - self.syncRect = syncRect; - } - - // external on/off - const hooks = self.hooks = opts.hooks || {}; - - function fire(evName, a1, a2) { - if (evName in hooks) { - hooks[evName].forEach(fn => { - fn.call(null, self, a1, a2); - }); - } - } - - (opts.plugins || []).forEach(p => { - for (let evName in p.hooks) - hooks[evName] = (hooks[evName] || []).concat(p.hooks[evName]); - }); - - const syncOpts = assign({ - key: null, - setSeries: false, - filters: { - pub: retTrue, - sub: retTrue, - }, - scales: [xScaleKey, series[1] ? series[1].scale : null], - match: [retEq, retEq], - values: [null, null], - }, cursor.sync); - - (cursor.sync = syncOpts); - - const syncKey = syncOpts.key; - - const sync = _sync(syncKey); - - function pubSync(type, src, x, y, w, h, i) { - if (syncOpts.filters.pub(type, src, x, y, w, h, i)) - sync.pub(type, src, x, y, w, h, i); - } - - sync.sub(self); - - function pub(type, src, x, y, w, h, i) { - if (syncOpts.filters.sub(type, src, x, y, w, h, i)) - events[type](null, src, x, y, w, h, i); - } - - (self.pub = pub); - - function destroy() { - sync.unsub(self); - cursorPlots.delete(self); - mouseListeners.clear(); - off(dppxchange, win, syncPxRatio); - root.remove(); - fire("destroy"); - } - - self.destroy = destroy; - - function _init() { - fire("init", opts, data); - - setData(data || opts.data, false); - - if (pendScales[xScaleKey]) - setScale(xScaleKey, pendScales[xScaleKey]); - else - autoScaleX(); - - _setSize(opts.width, opts.height); - - updateCursor(null, true, false); - - setSelect(select, false); - } - - series.forEach(initSeries); - - axes.forEach(initAxis); - - if (then) { - if (then instanceof HTMLElement) { - then.appendChild(root); - _init(); - } - else - then(self, _init); - } - else - _init(); - - return self; -} - -uPlot.assign = assign; -uPlot.fmtNum = fmtNum; -uPlot.rangeNum = rangeNum; -uPlot.rangeLog = rangeLog; -uPlot.rangeAsinh = rangeAsinh; -uPlot.orient = orient; -uPlot.pxRatio = pxRatio; - -{ - uPlot.join = join; -} - -{ - uPlot.fmtDate = fmtDate; - uPlot.tzDate = tzDate; -} - -{ - uPlot.sync = _sync; -} - -{ - uPlot.addGap = addGap; - uPlot.clipGaps = clipGaps; - - let paths = uPlot.paths = { - points, - }; - - (paths.linear = linear); - (paths.stepped = stepped); - (paths.bars = bars); - (paths.spline = monotoneCubic); -} - - - - -/***/ }), - -/***/ "./srcjs/modules/stack.js": -/*!********************************!*\ - !*** ./srcjs/modules/stack.js ***! - \********************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "stackedChart": () => (/* binding */ stackedChart) -/* harmony export */ }); -function stack(data, omit) { - let data2 = []; - let bands = []; - let d0Len = data[0].length; - let accum = Array(d0Len); - - for (let i = 0; i < d0Len; i++) accum[i] = 0; - - for (let i = 1; i < data.length; i++) - data2.push(omit(i) ? data[i] : data[i].map((v, i) => (accum[i] += +v))); - - for (let i = 1; i < data.length; i++) - !omit(i) && - bands.push({ - series: [data.findIndex((s, j) => j > i && !omit(j)), i] - }); - - bands = bands.filter(b => b.series[1] > -1); - - return { - data: [data[0]].concat(data2), - bands - }; -} - -function getOpts(title, series) { - return { - scales: { - x: { - time: true - } - }, - series - }; -} - -function getStackedOpts(title, series, data, interp) { - let opts = getOpts(title, series); - - let interped = interp ? interp(data) : data; - - let stacked = stack(interped, i => false); - opts.bands = stacked.bands; - - opts.cursor = opts.cursor || {}; - opts.cursor.dataIdx = (u, seriesIdx, closestIdx, xValue) => { - return data[seriesIdx][closestIdx] === null ? null : closestIdx; - }; - - opts.series.forEach(s => { - s.value = (u, v, si, i) => data[si][i]; - - s.points = s.points || {}; - - // scan raw unstacked data to return only real points - s.points.filter = (u, seriesIdx, show, gaps) => { - if (show) { - let pts = []; - data[seriesIdx].forEach((v, i) => { - v !== null && pts.push(i); - }); - return pts; - } - }; - }); - - // force 0 to be the sum minimum this instead of the bottom series - opts.scales.y = { - range: (u, min, max) => { - let minMax = uPlot.rangeNum(min, max, 0.1, true); - return [minMax[0], minMax[1]]; - } - }; - - // restack on toggle - opts.hooks = { - setSeries: [ - (u, i) => { - let stacked = stack(data, i => !u.series[i].show); - u.delBand(null); - stacked.bands.forEach(b => u.addBand(b)); - u.setData(stacked.data); - } - ] - }; - - return { opts, data: stacked.data }; -} - -function stack2(series) { - // for uplot data - let data = Array(series.length); - let bands = []; - - let dataLen = series[0].values.length; - - let zeroArr = Array(dataLen).fill(0); - - let stackGroups = new Map(); - let seriesStackKeys = Array(series.length); - - series.forEach((s, si) => { - let vals = s.values.slice(); - - // apply negY - if (s.negY) { - for (let i = 0; i < vals.length; i++) { - if (vals[i] !== null) vals[i] *= -1; - } - } - - if (s.stacking.mode != "none") { - let hasPos = vals.some(v => v > 0); - // derive stacking key - let stackKey = (seriesStackKeys[si] = - s.stacking.mode + s.scaleKey + s.stacking.group + (hasPos ? "+" : "-")); - let group = stackGroups.get(stackKey); - - // initialize stacking group - if (group === null) { - group = { - series: [], - acc: zeroArr.slice(), - dir: hasPos ? -1 : 1 - }; - stackGroups.set(stackKey, group); - } - - // push for bands gen - group.series.unshift(si); - - let stacked = (data[si] = Array(dataLen)); - let { acc } = group; - - for (let i = 0; i < dataLen; i++) { - let v = vals[i]; - - if (v !== null) stacked[i] = acc[i] += v; - else stacked[i] = v; // we may want to coerce to 0 here - } - } else data[si] = vals; - }); - - // re-compute by percent - series.forEach((s, si) => { - if (s.stacking.mode == "percent") { - let group = stackGroups.get(seriesStackKeys[si]); - let { acc } = group; - - // re-negatify percent - let sign = group.dir * -1; - - let stacked = data[si]; - - for (let i = 0; i < dataLen; i++) { - let v = stacked[i]; - - if (v !== null) stacked[i] = sign * (v / acc[i]); - } - } - }); - - // generate bands between adjacent group series - stackGroups.forEach(group => { - let { series, dir } = group; - let lastIdx = series.length - 1; - - series.forEach((si, i) => { - if (i != lastIdx) { - let nextIdx = series[i + 1]; - bands.push({ - // since we're not passing x series[0] for stacking, real idxs are actually +1 - series: [si + 1, nextIdx + 1], - dir - }); - } - }); - }); - - return { - data, - bands - }; -} - -function stackedChart(title, series, _data, interp, width, height, hooks, el) { - let { opts, data } = getStackedOpts(title, series, _data, interp); - opts.title = title; - opts.width = width; - opts.height = height; - opts.hooks = Object.assign(opts.hooks, hooks); - console.log(opts); - return new uPlot(opts, data, el); -} - - - -/***/ }), - -/***/ "./srcjs/modules/utils.js": -/*!********************************!*\ - !*** ./srcjs/modules/utils.js ***! - \********************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "getWidget": () => (/* binding */ getWidget) -/* harmony export */ }); -// From Friss tuto (https://github.com/FrissAnalytics/shinyJsTutorials/blob/master/tutorials/tutorial_03.Rmd) -function getWidget(id) { - var htmlWidgetsObj = HTMLWidgets.find("#" + id); - var widgetObj; - if (typeof htmlWidgetsObj !== "undefined") { - widgetObj = htmlWidgetsObj.getWidget(); - } - return widgetObj; -} - - -/***/ }), - -/***/ "widgets": -/*!******************************!*\ - !*** external "HTMLWidgets" ***! - \******************************/ -/***/ ((module) => { - -module.exports = window["HTMLWidgets"]; - -/***/ }) - -/******/ }); -/************************************************************************/ -/******/ // The module cache -/******/ var __webpack_module_cache__ = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ // Check if module is in cache -/******/ var cachedModule = __webpack_module_cache__[moduleId]; -/******/ if (cachedModule !== undefined) { -/******/ return cachedModule.exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = __webpack_module_cache__[moduleId] = { -/******/ id: moduleId, -/******/ // no module.loaded needed -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/************************************************************************/ -/******/ /* webpack/runtime/compat get default export */ -/******/ (() => { -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = (module) => { -/******/ var getter = module && module.__esModule ? -/******/ () => (module['default']) : -/******/ () => (module); -/******/ __webpack_require__.d(getter, { a: getter }); -/******/ return getter; -/******/ }; -/******/ })(); -/******/ -/******/ /* webpack/runtime/define property getters */ -/******/ (() => { -/******/ // define getter functions for harmony exports -/******/ __webpack_require__.d = (exports, definition) => { -/******/ for(var key in definition) { -/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { -/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); -/******/ } -/******/ } -/******/ }; -/******/ })(); -/******/ -/******/ /* webpack/runtime/hasOwnProperty shorthand */ -/******/ (() => { -/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) -/******/ })(); -/******/ -/******/ /* webpack/runtime/make namespace object */ -/******/ (() => { -/******/ // define __esModule on exports -/******/ __webpack_require__.r = (exports) => { -/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { -/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); -/******/ } -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ })(); -/******/ -/******/ /* webpack/runtime/nonce */ -/******/ (() => { -/******/ __webpack_require__.nc = undefined; -/******/ })(); -/******/ -/************************************************************************/ -var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { -/*!********************************!*\ - !*** ./srcjs/widgets/uPlot.js ***! - \********************************/ -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "drawPoints": () => (/* binding */ drawPoints), -/* harmony export */ "uPlot": () => (/* reexport safe */ uplot__WEBPACK_IMPORTED_MODULE_1__["default"]) -/* harmony export */ }); -/* harmony import */ var widgets__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! widgets */ "widgets"); -/* harmony import */ var widgets__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(widgets__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var uplot__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! uplot */ "./node_modules/uplot/dist/uPlot.esm.js"); -/* harmony import */ var uplot_dist_uPlot_min_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! uplot/dist/uPlot.min.css */ "./node_modules/uplot/dist/uPlot.min.css"); -/* harmony import */ var _modules_utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../modules/utils */ "./srcjs/modules/utils.js"); -/* harmony import */ var _modules_stack__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../modules/stack */ "./srcjs/modules/stack.js"); - - - - - - -const resizer = el => { - const func = (u, init) => { - const resizeObserver = new ResizeObserver(entries => { - for (let entry of entries) { - let adjHeight = entry.contentRect.height; - let adjWidth = entry.contentRect.width; - const extras = u.root.querySelectorAll(".u-legend, .u-title"); - for (let extra of extras) { - adjHeight -= Math.floor(extra.offsetHeight); - } - u.setSize({ width: adjWidth, height: adjHeight }); - } - }); - resizeObserver.observe(el); - el.appendChild(u.root); - init(); - }; - return func; -}; - -const drawPoints = (u, seriesIdx, idx0, idx1) => { - const size = 5 * devicePixelRatio; - - uplot__WEBPACK_IMPORTED_MODULE_1__["default"].orient( - u, - seriesIdx, - ( - series, - dataX, - dataY, - scaleX, - scaleY, - valToPosX, - valToPosY, - xOff, - yOff, - xDim, - yDim, - moveTo, - lineTo, - rect, - arc - ) => { - let d = u.data[seriesIdx]; - - u.ctx.fillStyle = series.stroke(); - - let deg360 = 2 * Math.PI; - - console.time("points"); - - // let cir = new Path2D(); - // cir.moveTo(0, 0); - // arc(cir, 0, 0, 3, 0, deg360); - - // Create transformation matrix that moves 200 points to the right - // let m = document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGMatrix(); - // m.a = 1; m.b = 0; - // m.c = 0; m.d = 1; - // m.e = 200; m.f = 0; - - let p = new Path2D(); - - for (let i = 0; i < d[0].length; i++) { - let xVal = d[0][i]; - let yVal = d[1][i]; - - if ( - xVal >= scaleX.min && - xVal <= scaleX.max && - yVal >= scaleY.min && - yVal <= scaleY.max - ) { - let cx = valToPosX(xVal, scaleX, xDim, xOff); - let cy = valToPosY(yVal, scaleY, yDim, yOff); - - p.moveTo(cx + size / 2, cy); - // arc(p, cx, cy, 3, 0, deg360); - arc(p, cx, cy, size / 2, 0, deg360); - - // m.e = cx; - // m.f = cy; - // p.addPath(cir, m); - - // qt.add({x: cx - 1.5, y: cy - 1.5, w: 3, h: 3, sidx: seriesIdx, didx: i}); - } - } - - console.timeEnd("points"); - - u.ctx.fill(p); - } - ); - - return null; -}; - -HTMLWidgets.widget({ - name: "uPlot", - - type: "output", - - factory: function(el, width, height) { - var plot, options, data; - - return { - renderValue: function(x) { - if (typeof plot !== "undefined") { - plot.destroy(); - } - options = x.options; - options.width = width; - options.height = height; - data = x.data; - if (x.stacked) { - if (!options.hooks) - options.hooks = {}; - options.hooks.init = [ - u => { - [...u.root.querySelectorAll(".u-legend .u-series")].forEach( - (el, i) => { - if (u.series[i]._hide) { - el.style.display = "none"; - } - } - ); - } - ]; - plot = (0,_modules_stack__WEBPACK_IMPORTED_MODULE_4__.stackedChart)( - options.title, - options.series, - data, - null, - width, - height, - options.hooks, - resizer(el) - ); - } else { - plot = new uplot__WEBPACK_IMPORTED_MODULE_1__["default"](options, data, resizer(el)); - } - }, - getWidget: function() { - return plot; - }, - resize: function(width, height) {} - }; - } -}); - -if (HTMLWidgets.shinyMode) { - Shiny.addCustomMessageHandler("uplot-api", function(obj) { - var plot = _modules_utils__WEBPACK_IMPORTED_MODULE_3__.getWidget(obj.id); - if (typeof plot != "undefined") { - plot[obj.name].apply(null, obj.args); - } - }); - Shiny.addCustomMessageHandler("uplot-setData", function(obj) { - var plot = _modules_utils__WEBPACK_IMPORTED_MODULE_3__.getWidget(obj.id); - if (typeof plot != "undefined") { - plot.setData(obj.data); - } - }); -} - - - - -})(); - -var __webpack_export_target__ = window; -for(var i in __webpack_exports__) __webpack_export_target__[i] = __webpack_exports__[i]; -if(__webpack_exports__.__esModule) Object.defineProperty(__webpack_export_target__, "__esModule", { value: true }); -/******/ })() -; -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidVBsb3QuanMiLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFDZ0c7QUFDakI7QUFDL0UsOEJBQThCLHNFQUEyQixDQUFDLCtFQUFxQztBQUMvRjtBQUNBLCtGQUErRix3QkFBd0IsUUFBUSx3TUFBd00saUJBQWlCLG9CQUFvQixVQUFVLG1CQUFtQixnQkFBZ0IsbUJBQW1CLFNBQVMsbUJBQW1CLG1CQUFtQixtQkFBbUIsb0JBQW9CLFVBQVUsa0JBQWtCLGVBQWUsZUFBZSxtQkFBbUIsWUFBWSxjQUFjLFNBQVMsb0JBQW9CLFdBQVcsZ0JBQWdCLGFBQWEsb0JBQW9CLFdBQVcsZ0JBQWdCLGFBQWEsdUJBQXVCLGNBQWMsb0JBQW9CLGNBQWMsa0JBQWtCLGtCQUFrQix1QkFBdUIsdUJBQXVCLHFCQUFxQixXQUFXLFlBQVksa0JBQWtCLHlDQUF5Qyw0QkFBNEIsZUFBZSx3QkFBd0IsaUNBQWlDLGVBQWUsZUFBZSxjQUFjLGNBQWMsaUJBQWlCLHNCQUFzQixjQUFjLFdBQVcsNkJBQTZCLG1CQUFtQixzQkFBc0IsMEJBQTBCLG1CQUFtQixRQUFRLE9BQU8scUJBQXFCLHVCQUF1QixjQUFjLHNDQUFzQyxhQUFhLGtDQUFrQyxzQ0FBc0MsWUFBWSxtQ0FBbUMsY0FBYyxtQkFBbUIsT0FBTyxRQUFRLG1CQUFtQixnQkFBZ0IscUJBQXFCLHVCQUF1QixhQUFhLG9IQUFvSCwwRkFBMEYsZUFBZSxPQUFPLDBsQ0FBMGxDLHdCQUF3QixRQUFRLHdNQUF3TSxpQkFBaUIsb0JBQW9CLFVBQVUsbUJBQW1CLGdCQUFnQixtQkFBbUIsU0FBUyxtQkFBbUIsbUJBQW1CLG1CQUFtQixvQkFBb0IsVUFBVSxrQkFBa0IsZUFBZSxlQUFlLG1CQUFtQixZQUFZLGNBQWMsU0FBUyxvQkFBb0IsV0FBVyxnQkFBZ0IsYUFBYSxvQkFBb0IsV0FBVyxnQkFBZ0IsYUFBYSx1QkFBdUIsY0FBYyxvQkFBb0IsY0FBYyxrQkFBa0Isa0JBQWtCLHVCQUF1Qix1QkFBdUIscUJBQXFCLFdBQVcsWUFBWSxrQkFBa0IseUNBQXlDLDRCQUE0QixlQUFlLHdCQUF3QixpQ0FBaUMsZUFBZSxlQUFlLGNBQWMsY0FBYyxpQkFBaUIsc0JBQXNCLGNBQWMsV0FBVyw2QkFBNkIsbUJBQW1CLHNCQUFzQiwwQkFBMEIsbUJBQW1CLFFBQVEsT0FBTyxxQkFBcUIsdUJBQXVCLGNBQWMsc0NBQXNDLGFBQWEsa0NBQWtDLHNDQUFzQyxZQUFZLG1DQUFtQyxjQUFjLG1CQUFtQixPQUFPLFFBQVEsbUJBQW1CLGdCQUFnQixxQkFBcUIsdUJBQXVCLGFBQWEsb0hBQW9ILDBGQUEwRixlQUFlLG1CQUFtQjtBQUNuMEo7QUFDQSxpRUFBZSx1QkFBdUIsRUFBQzs7Ozs7Ozs7Ozs7QUNQMUI7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxxREFBcUQ7QUFDckQ7O0FBRUE7QUFDQSxnREFBZ0Q7QUFDaEQ7O0FBRUE7QUFDQSxxRkFBcUY7QUFDckY7O0FBRUE7O0FBRUE7QUFDQSxxQkFBcUI7QUFDckI7O0FBRUE7QUFDQSxxQkFBcUI7QUFDckI7O0FBRUE7QUFDQSxxQkFBcUI7QUFDckI7O0FBRUE7QUFDQSxLQUFLO0FBQ0wsS0FBSzs7O0FBR0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxzQkFBc0IsaUJBQWlCO0FBQ3ZDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEscUJBQXFCLHFCQUFxQjtBQUMxQzs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWLHNGQUFzRixxQkFBcUI7QUFDM0c7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVixpREFBaUQscUJBQXFCO0FBQ3RFO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Ysc0RBQXNELHFCQUFxQjtBQUMzRTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7Ozs7Ozs7Ozs7QUNyR2E7O0FBRWI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsdURBQXVELGNBQWM7QUFDckU7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQ3BCQSxNQUFxRjtBQUNyRixNQUEyRTtBQUMzRSxNQUFrRjtBQUNsRixNQUFxRztBQUNyRyxNQUE4RjtBQUM5RixNQUE4RjtBQUM5RixNQUE2RjtBQUM3RjtBQUNBOztBQUVBOztBQUVBLDRCQUE0Qix3RkFBbUI7QUFDL0Msd0JBQXdCLHFHQUFhOztBQUVyQyx1QkFBdUIsMEZBQWE7QUFDcEM7QUFDQSxpQkFBaUIsa0ZBQU07QUFDdkIsNkJBQTZCLHlGQUFrQjs7QUFFL0MsYUFBYSw2RkFBRyxDQUFDLDZFQUFPOzs7O0FBSXVDO0FBQy9ELE9BQU8saUVBQWUsNkVBQU8sSUFBSSxvRkFBYyxHQUFHLG9GQUFjLFlBQVksRUFBQzs7Ozs7Ozs7Ozs7QUMxQmhFOztBQUViOztBQUVBO0FBQ0E7O0FBRUEsa0JBQWtCLHdCQUF3QjtBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLGtCQUFrQixpQkFBaUI7QUFDbkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG9CQUFvQiw0QkFBNEI7QUFDaEQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEscUJBQXFCLDZCQUE2QjtBQUNsRDs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUN2R2E7O0FBRWI7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esc0RBQXNEOztBQUV0RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOzs7Ozs7Ozs7O0FDdENhOztBQUViO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7O0FDVmE7O0FBRWI7QUFDQTtBQUNBLGNBQWMsS0FBd0MsR0FBRyxzQkFBaUIsR0FBRyxDQUFJOztBQUVqRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7OztBQ1hhOztBQUViO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGtEQUFrRDtBQUNsRDs7QUFFQTtBQUNBLDBDQUEwQztBQUMxQzs7QUFFQTs7QUFFQTtBQUNBLGlGQUFpRjtBQUNqRjs7QUFFQTs7QUFFQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTs7QUFFQTtBQUNBLHlEQUF5RDtBQUN6RCxJQUFJOztBQUVKOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7QUNyRWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7Ozs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx5Q0FBeUMsZ0JBQWdCLDZCQUE2QixnQkFBZ0I7QUFDdEc7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxnQkFBZ0I7QUFDaEIsaUJBQWlCOztBQUVqQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0Esb0NBQW9DLHNCQUFzQjtBQUMxRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLFVBQVU7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBLG1CQUFtQixVQUFVO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQSx3QkFBd0IsY0FBYztBQUN0QztBQUNBOztBQUVBLGtCQUFrQixrQkFBa0I7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsbUJBQW1CLGNBQWM7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsaUJBQWlCLGlCQUFpQjtBQUNsQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0Esd0JBQXdCO0FBQ3hCLHdCQUF3QjtBQUN4Qix3QkFBd0I7O0FBRXhCO0FBQ0E7QUFDQSx1Q0FBdUMscUJBQXFCO0FBQzVEOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0Isb0JBQW9CO0FBQ3RDO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0IsU0FBUztBQUMzQjtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBLGlCQUFpQixnQkFBZ0I7QUFDakM7O0FBRUEsa0JBQWtCLG9CQUFvQjtBQUN0QztBQUNBOztBQUVBLG1CQUFtQixlQUFlO0FBQ2xDOztBQUVBOztBQUVBOztBQUVBOztBQUVBLG1CQUFtQixlQUFlO0FBQ2xDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsc0JBQXNCLDBDQUEwQztBQUMzRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxZQUFZLFVBQVUsSUFBSTs7QUFFMUI7QUFDQSwwQkFBMEI7O0FBRTFCO0FBQ0E7O0FBRUEsa0JBQWtCLGtCQUFrQjtBQUNwQzs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlEQUFpRCxhQUFhO0FBQzlEO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQSxrQkFBa0IsS0FBSztBQUN2QjtBQUNBLGtCQUFrQixFQUFFLEVBQUUsRUFBRTtBQUN4QjtBQUNBLDBCQUEwQixHQUFHOztBQUU3QixrQkFBa0IsR0FBRztBQUNyQixrQkFBa0IsRUFBRSxFQUFFLEdBQUc7QUFDekI7QUFDQTtBQUNBLG1CQUFtQixHQUFHOztBQUV0Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixJQUFJO0FBQ3RCO0FBQ0Esa0JBQWtCLEVBQUU7QUFDcEI7QUFDQTtBQUNBLHdCQUF3QixJQUFJO0FBQzVCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDRDQUE0QztBQUM1QztBQUNBO0FBQ0E7QUFDQTs7QUFFQSxvQkFBb0IsbUJBQW1CO0FBQ3ZDO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQixLQUFLLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxFQUFFLElBQUksR0FBRzs7QUFFdkQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsc0JBQXNCO0FBQ3RCO0FBQ0EsQ0FBQzs7QUFFRCx1QkFBdUI7QUFDdkI7QUFDQSxDQUFDOztBQUVELHdCQUF3QjtBQUN4QjtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBLHVCQUF1Qjs7QUFFdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQSwwQkFBMEIsaUJBQWlCO0FBQzNDLDhDQUE4Qzs7QUFFOUM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLE9BQU8sY0FBYztBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsVUFBVSxXQUFXO0FBQ2hDLFdBQVcsVUFBVSxXQUFXO0FBQ2hDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsNEJBQTRCO0FBQzVCO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQSxvQkFBb0Isb0JBQW9CO0FBQ3hDO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBLGlCQUFpQixrQkFBa0I7QUFDbkM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQSxrQkFBa0IsaUJBQWlCO0FBQ25DOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxzQ0FBc0Msd0JBQXdCO0FBQzlEOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw2QkFBNkI7QUFDN0I7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDhCQUE4Qiw4QkFBOEI7QUFDNUQsOEJBQThCOztBQUU5QjtBQUNBLHVCQUF1QixzQkFBc0I7QUFDN0MsdUJBQXVCOztBQUV2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsK0JBQStCO0FBQy9CLCtCQUErQjtBQUMvQiwrQkFBK0I7QUFDL0IsK0JBQStCO0FBQy9CO0FBQ0E7QUFDQSxxREFBcUQ7QUFDckQscURBQXFEO0FBQ3JELGtFQUFrRTtBQUNsRSxrRUFBa0U7O0FBRWxFO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsU0FBUyxrQkFBa0I7O0FBRTNCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBLFNBQVMsK0NBQStDOztBQUV4RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLFlBQVk7QUFDcEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxtQkFBbUI7QUFDbkI7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsd0NBQXdDLHdCQUF3QjtBQUNoRTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBLG1CQUFtQjtBQUNuQjs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSx3Q0FBd0Msd0JBQXdCO0FBQ2hFOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0Esd0NBQXdDOztBQUV4QyxTQUFTLHVDQUF1Qzs7QUFFaEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBOztBQUVBLFNBQVMsV0FBVzs7QUFFcEI7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsMEZBQTBGOztBQUUxRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDBDQUEwQyxrQkFBa0I7QUFDNUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQSxtQkFBbUIsMEdBQTBHOztBQUU3SDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLFNBQVMsU0FBUzs7QUFFbEI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsMENBQTBDLHdCQUF3QjtBQUNsRTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsd0NBQXdDLHdCQUF3QjtBQUNoRTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsbUJBQW1CO0FBQ25COztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGtCQUFrQixXQUFXO0FBQzdCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0IsV0FBVztBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxrQkFBa0IsV0FBVztBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDZCQUE2QiwwQkFBMEI7QUFDdkQ7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGlEQUFpRCxhQUFhO0FBQzlEOztBQUVBO0FBQ0EsaUJBQWlCO0FBQ2pCOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsNkNBQTZDO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDLHNDQUFzQyxjQUFjO0FBQ3BGO0FBQ0E7QUFDQSxxQ0FBcUM7O0FBRXJDOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLG9CQUFvQjtBQUNwQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSw0Q0FBNEM7QUFDNUM7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDREQUE0RDs7QUFFNUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsZUFBZTtBQUNmLGVBQWU7O0FBRWY7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0EsMkJBQTJCLGNBQWM7QUFDekMsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxtQkFBbUIsY0FBYztBQUNqQztBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTLGFBQWE7QUFDdEI7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwwQkFBMEI7QUFDMUIsMEJBQTBCO0FBQzFCLDBCQUEwQjtBQUMxQiwwQkFBMEI7QUFDMUI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBLHdDQUF3QyxlQUFlLE9BQU8sY0FBYzs7QUFFNUU7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEscUNBQXFDLGlCQUFpQixXQUFXO0FBQ2pFOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxvQ0FBb0M7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkI7QUFDN0I7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsbUJBQW1CLG1CQUFtQjtBQUN0QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esb0JBQW9CLGFBQWE7QUFDakM7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0JBQStCO0FBQy9CO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsUUFBUSxzQ0FBc0M7QUFDOUM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0IsaUJBQWlCO0FBQ25DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxRQUFRLFVBQVUsVUFBVTs7QUFFNUI7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTtBQUNBLGtCQUFrQixpQkFBaUI7QUFDbkM7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQSxtQkFBbUIsb0JBQW9CO0FBQ3ZDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUEscUJBQXFCLG1CQUFtQjtBQUN4Qzs7QUFFQTtBQUNBO0FBQ0EsNkNBQTZDO0FBQzdDLDBCQUEwQjtBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsbUJBQW1CLCtCQUErQjtBQUNsRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaUJBQWlCLFNBQVM7QUFDMUI7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0I7O0FBRXRCO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxtQ0FBbUMsbUJBQW1CO0FBQ3REO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1REFBdUQ7QUFDdkQ7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLCtCQUErQjs7QUFFL0I7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxtQkFBbUIsbUJBQW1CO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLG9CQUFvQixtQkFBbUI7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsbUNBQW1DLG1CQUFtQjtBQUN0RDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsV0FBVywyQkFBMkI7O0FBRXRDO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQSxRQUFRLDJCQUEyQjs7QUFFbkM7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFNEI7Ozs7Ozs7Ozs7Ozs7OztBQ253SzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCLFdBQVc7O0FBRTdCLGtCQUFrQixpQkFBaUI7QUFDbkM7O0FBRUEsa0JBQWtCLGlCQUFpQjtBQUNuQztBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFdBQVc7QUFDWDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHNCQUFzQixpQkFBaUI7QUFDdkM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLFlBQVksTUFBTTs7QUFFbEIsc0JBQXNCLGFBQWE7QUFDbkM7O0FBRUE7QUFDQSw2QkFBNkI7QUFDN0I7QUFDQSxNQUFNO0FBQ04sR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVksTUFBTTs7QUFFbEI7QUFDQTs7QUFFQTs7QUFFQSxzQkFBc0IsYUFBYTtBQUNuQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxVQUFVLGNBQWM7QUFDeEI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0wsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVPO0FBQ1AsUUFBUSxhQUFhO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7O0FDak1BO0FBQ087QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUNSQTs7Ozs7O1VDQUE7VUFDQTs7VUFFQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTs7VUFFQTtVQUNBOztVQUVBO1VBQ0E7VUFDQTs7Ozs7V0N0QkE7V0FDQTtXQUNBO1dBQ0E7V0FDQTtXQUNBLGlDQUFpQyxXQUFXO1dBQzVDO1dBQ0E7Ozs7O1dDUEE7V0FDQTtXQUNBO1dBQ0E7V0FDQSx5Q0FBeUMsd0NBQXdDO1dBQ2pGO1dBQ0E7V0FDQTs7Ozs7V0NQQTs7Ozs7V0NBQTtXQUNBO1dBQ0E7V0FDQSx1REFBdUQsaUJBQWlCO1dBQ3hFO1dBQ0EsZ0RBQWdELGFBQWE7V0FDN0Q7Ozs7O1dDTkE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQ0FpQjtBQUNTO0FBQ1E7QUFDUTtBQUNNOztBQUVoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixvQ0FBb0M7QUFDeEQ7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsRUFBRSxvREFBWTtBQUNkO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEIsb0JBQW9CO0FBQ3BCLG9CQUFvQjs7QUFFcEI7O0FBRUEsc0JBQXNCLGlCQUFpQjtBQUN2QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxxQkFBcUIsK0RBQStEO0FBQ3BGO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUIsNERBQVk7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWLHFCQUFxQiw2Q0FBSztBQUMxQjtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBLGVBQWUscURBQWU7QUFDOUI7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsZUFBZSxxREFBZTtBQUM5QjtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRTZCIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vdXBsb3QvLi9ub2RlX21vZHVsZXMvdXBsb3QvZGlzdC91UGxvdC5taW4uY3NzIiwid2VicGFjazovL3VwbG90Ly4vbm9kZV9tb2R1bGVzL2Nzcy1sb2FkZXIvZGlzdC9ydW50aW1lL2FwaS5qcyIsIndlYnBhY2s6Ly91cGxvdC8uL25vZGVfbW9kdWxlcy9jc3MtbG9hZGVyL2Rpc3QvcnVudGltZS9zb3VyY2VNYXBzLmpzIiwid2VicGFjazovL3VwbG90Ly4vbm9kZV9tb2R1bGVzL3VwbG90L2Rpc3QvdVBsb3QubWluLmNzcz9mOGZhIiwid2VicGFjazovL3VwbG90Ly4vbm9kZV9tb2R1bGVzL3N0eWxlLWxvYWRlci9kaXN0L3J1bnRpbWUvaW5qZWN0U3R5bGVzSW50b1N0eWxlVGFnLmpzIiwid2VicGFjazovL3VwbG90Ly4vbm9kZV9tb2R1bGVzL3N0eWxlLWxvYWRlci9kaXN0L3J1bnRpbWUvaW5zZXJ0QnlTZWxlY3Rvci5qcyIsIndlYnBhY2s6Ly91cGxvdC8uL25vZGVfbW9kdWxlcy9zdHlsZS1sb2FkZXIvZGlzdC9ydW50aW1lL2luc2VydFN0eWxlRWxlbWVudC5qcyIsIndlYnBhY2s6Ly91cGxvdC8uL25vZGVfbW9kdWxlcy9zdHlsZS1sb2FkZXIvZGlzdC9ydW50aW1lL3NldEF0dHJpYnV0ZXNXaXRob3V0QXR0cmlidXRlcy5qcyIsIndlYnBhY2s6Ly91cGxvdC8uL25vZGVfbW9kdWxlcy9zdHlsZS1sb2FkZXIvZGlzdC9ydW50aW1lL3N0eWxlRG9tQVBJLmpzIiwid2VicGFjazovL3VwbG90Ly4vbm9kZV9tb2R1bGVzL3N0eWxlLWxvYWRlci9kaXN0L3J1bnRpbWUvc3R5bGVUYWdUcmFuc2Zvcm0uanMiLCJ3ZWJwYWNrOi8vdXBsb3QvLi9ub2RlX21vZHVsZXMvdXBsb3QvZGlzdC91UGxvdC5lc20uanMiLCJ3ZWJwYWNrOi8vdXBsb3QvLi9zcmNqcy9tb2R1bGVzL3N0YWNrLmpzIiwid2VicGFjazovL3VwbG90Ly4vc3JjanMvbW9kdWxlcy91dGlscy5qcyIsIndlYnBhY2s6Ly91cGxvdC9leHRlcm5hbCB3aW5kb3cgXCJIVE1MV2lkZ2V0c1wiIiwid2VicGFjazovL3VwbG90L3dlYnBhY2svYm9vdHN0cmFwIiwid2VicGFjazovL3VwbG90L3dlYnBhY2svcnVudGltZS9jb21wYXQgZ2V0IGRlZmF1bHQgZXhwb3J0Iiwid2VicGFjazovL3VwbG90L3dlYnBhY2svcnVudGltZS9kZWZpbmUgcHJvcGVydHkgZ2V0dGVycyIsIndlYnBhY2s6Ly91cGxvdC93ZWJwYWNrL3J1bnRpbWUvaGFzT3duUHJvcGVydHkgc2hvcnRoYW5kIiwid2VicGFjazovL3VwbG90L3dlYnBhY2svcnVudGltZS9tYWtlIG5hbWVzcGFjZSBvYmplY3QiLCJ3ZWJwYWNrOi8vdXBsb3Qvd2VicGFjay9ydW50aW1lL25vbmNlIiwid2VicGFjazovL3VwbG90Ly4vc3JjanMvd2lkZ2V0cy91UGxvdC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBJbXBvcnRzXG5pbXBvcnQgX19fQ1NTX0xPQURFUl9BUElfU09VUkNFTUFQX0lNUE9SVF9fXyBmcm9tIFwiLi4vLi4vY3NzLWxvYWRlci9kaXN0L3J1bnRpbWUvc291cmNlTWFwcy5qc1wiO1xuaW1wb3J0IF9fX0NTU19MT0FERVJfQVBJX0lNUE9SVF9fXyBmcm9tIFwiLi4vLi4vY3NzLWxvYWRlci9kaXN0L3J1bnRpbWUvYXBpLmpzXCI7XG52YXIgX19fQ1NTX0xPQURFUl9FWFBPUlRfX18gPSBfX19DU1NfTE9BREVSX0FQSV9JTVBPUlRfX18oX19fQ1NTX0xPQURFUl9BUElfU09VUkNFTUFQX0lNUE9SVF9fXyk7XG4vLyBNb2R1bGVcbl9fX0NTU19MT0FERVJfRVhQT1JUX19fLnB1c2goW21vZHVsZS5pZCwgXCIudXBsb3QsIC51cGxvdCAqLCAudXBsb3QgKjo6YmVmb3JlLCAudXBsb3QgKjo6YWZ0ZXIge2JveC1zaXppbmc6IGJvcmRlci1ib3g7fS51cGxvdCB7Zm9udC1mYW1pbHk6IHN5c3RlbS11aSwgLWFwcGxlLXN5c3RlbSwgXFxcIlNlZ29lIFVJXFxcIiwgUm9ib3RvLCBcXFwiSGVsdmV0aWNhIE5ldWVcXFwiLCBBcmlhbCwgXFxcIk5vdG8gU2Fuc1xcXCIsIHNhbnMtc2VyaWYsIFxcXCJBcHBsZSBDb2xvciBFbW9qaVxcXCIsIFxcXCJTZWdvZSBVSSBFbW9qaVxcXCIsIFxcXCJTZWdvZSBVSSBTeW1ib2xcXFwiLCBcXFwiTm90byBDb2xvciBFbW9qaVxcXCI7bGluZS1oZWlnaHQ6IDEuNTt3aWR0aDogbWluLWNvbnRlbnQ7fS51LXRpdGxlIHt0ZXh0LWFsaWduOiBjZW50ZXI7Zm9udC1zaXplOiAxOHB4O2ZvbnQtd2VpZ2h0OiBib2xkO30udS13cmFwIHtwb3NpdGlvbjogcmVsYXRpdmU7dXNlci1zZWxlY3Q6IG5vbmU7fS51LW92ZXIsIC51LXVuZGVyIHtwb3NpdGlvbjogYWJzb2x1dGU7fS51LXVuZGVyIHtvdmVyZmxvdzogaGlkZGVuO30udXBsb3QgY2FudmFzIHtkaXNwbGF5OiBibG9jaztwb3NpdGlvbjogcmVsYXRpdmU7d2lkdGg6IDEwMCU7aGVpZ2h0OiAxMDAlO30udS1heGlzIHtwb3NpdGlvbjogYWJzb2x1dGU7fS51LWxlZ2VuZCB7Zm9udC1zaXplOiAxNHB4O21hcmdpbjogYXV0bzt0ZXh0LWFsaWduOiBjZW50ZXI7fS51LWlubGluZSB7ZGlzcGxheTogYmxvY2s7fS51LWlubGluZSAqIHtkaXNwbGF5OiBpbmxpbmUtYmxvY2s7fS51LWlubGluZSB0ciB7bWFyZ2luLXJpZ2h0OiAxNnB4O30udS1sZWdlbmQgdGgge2ZvbnQtd2VpZ2h0OiA2MDA7fS51LWxlZ2VuZCB0aCA+ICoge3ZlcnRpY2FsLWFsaWduOiBtaWRkbGU7ZGlzcGxheTogaW5saW5lLWJsb2NrO30udS1sZWdlbmQgLnUtbWFya2VyIHt3aWR0aDogMWVtO2hlaWdodDogMWVtO21hcmdpbi1yaWdodDogNHB4O2JhY2tncm91bmQtY2xpcDogcGFkZGluZy1ib3ggIWltcG9ydGFudDt9LnUtaW5saW5lLnUtbGl2ZSB0aDo6YWZ0ZXIge2NvbnRlbnQ6IFxcXCI6XFxcIjt2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlO30udS1pbmxpbmU6bm90KC51LWxpdmUpIC51LXZhbHVlIHtkaXNwbGF5OiBub25lO30udS1zZXJpZXMgPiAqIHtwYWRkaW5nOiA0cHg7fS51LXNlcmllcyB0aCB7Y3Vyc29yOiBwb2ludGVyO30udS1sZWdlbmQgLnUtb2ZmID4gKiB7b3BhY2l0eTogMC4zO30udS1zZWxlY3Qge2JhY2tncm91bmQ6IHJnYmEoMCwwLDAsMC4wNyk7cG9zaXRpb246IGFic29sdXRlO3BvaW50ZXItZXZlbnRzOiBub25lO30udS1jdXJzb3IteCwgLnUtY3Vyc29yLXkge3Bvc2l0aW9uOiBhYnNvbHV0ZTtsZWZ0OiAwO3RvcDogMDtwb2ludGVyLWV2ZW50czogbm9uZTt3aWxsLWNoYW5nZTogdHJhbnNmb3JtO3otaW5kZXg6IDEwMDt9LnUtaHogLnUtY3Vyc29yLXgsIC51LXZ0IC51LWN1cnNvci15IHtoZWlnaHQ6IDEwMCU7Ym9yZGVyLXJpZ2h0OiAxcHggZGFzaGVkICM2MDdEOEI7fS51LWh6IC51LWN1cnNvci15LCAudS12dCAudS1jdXJzb3IteCB7d2lkdGg6IDEwMCU7Ym9yZGVyLWJvdHRvbTogMXB4IGRhc2hlZCAjNjA3RDhCO30udS1jdXJzb3ItcHQge3Bvc2l0aW9uOiBhYnNvbHV0ZTt0b3A6IDA7bGVmdDogMDtib3JkZXItcmFkaXVzOiA1MCU7Ym9yZGVyOiAwIHNvbGlkO3BvaW50ZXItZXZlbnRzOiBub25lO3dpbGwtY2hhbmdlOiB0cmFuc2Zvcm07ei1pbmRleDogMTAwOy8qdGhpcyBoYXMgdG8gYmUgIWltcG9ydGFudCBzaW5jZSB3ZSBzZXQgaW5saW5lIFxcXCJiYWNrZ3JvdW5kXFxcIiBzaG9ydGhhbmQgKi9iYWNrZ3JvdW5kLWNsaXA6IHBhZGRpbmctYm94ICFpbXBvcnRhbnQ7fS51LWF4aXMudS1vZmYsIC51LXNlbGVjdC51LW9mZiwgLnUtY3Vyc29yLXgudS1vZmYsIC51LWN1cnNvci15LnUtb2ZmLCAudS1jdXJzb3ItcHQudS1vZmYge2Rpc3BsYXk6IG5vbmU7fVwiLCBcIlwiLHtcInZlcnNpb25cIjozLFwic291cmNlc1wiOltcIndlYnBhY2s6Ly8uL25vZGVfbW9kdWxlcy91cGxvdC9kaXN0L3VQbG90Lm1pbi5jc3NcIl0sXCJuYW1lc1wiOltdLFwibWFwcGluZ3NcIjpcIkFBQUEscURBQXFELHNCQUFzQixDQUFDLENBQUMsUUFBUSx5TEFBeUwsQ0FBQyxnQkFBZ0IsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLFVBQVUsa0JBQWtCLENBQUMsZUFBZSxDQUFDLGlCQUFpQixDQUFDLENBQUMsU0FBUyxrQkFBa0IsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLG1CQUFtQixrQkFBa0IsQ0FBQyxDQUFDLFVBQVUsZ0JBQWdCLENBQUMsQ0FBQyxlQUFlLGNBQWMsQ0FBQyxrQkFBa0IsQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLENBQUMsU0FBUyxrQkFBa0IsQ0FBQyxDQUFDLFdBQVcsZUFBZSxDQUFDLFlBQVksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLFdBQVcsY0FBYyxDQUFDLENBQUMsYUFBYSxxQkFBcUIsQ0FBQyxDQUFDLGNBQWMsa0JBQWtCLENBQUMsQ0FBQyxjQUFjLGdCQUFnQixDQUFDLENBQUMsa0JBQWtCLHNCQUFzQixDQUFDLHFCQUFxQixDQUFDLENBQUMscUJBQXFCLFVBQVUsQ0FBQyxXQUFXLENBQUMsaUJBQWlCLENBQUMsdUNBQXVDLENBQUMsQ0FBQyw0QkFBNEIsWUFBWSxDQUFDLHNCQUFzQixDQUFDLENBQUMsaUNBQWlDLGFBQWEsQ0FBQyxDQUFDLGVBQWUsWUFBWSxDQUFDLENBQUMsY0FBYyxlQUFlLENBQUMsQ0FBQyxzQkFBc0IsWUFBWSxDQUFDLENBQUMsV0FBVyw0QkFBNEIsQ0FBQyxrQkFBa0IsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLDBCQUEwQixrQkFBa0IsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLG9CQUFvQixDQUFDLHNCQUFzQixDQUFDLFlBQVksQ0FBQyxDQUFDLHNDQUFzQyxZQUFZLENBQUMsZ0NBQWdDLENBQUMsQ0FBQyxzQ0FBc0MsV0FBVyxDQUFDLGlDQUFpQyxDQUFDLENBQUMsY0FBYyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLGtCQUFrQixDQUFDLGVBQWUsQ0FBQyxvQkFBb0IsQ0FBQyxzQkFBc0IsQ0FBQyxZQUFZLENBQUMsd0VBQXdFLENBQUMsdUNBQXVDLENBQUMsQ0FBQywwRkFBMEYsYUFBYSxDQUFDXCIsXCJzb3VyY2VzQ29udGVudFwiOltcIi51cGxvdCwgLnVwbG90ICosIC51cGxvdCAqOjpiZWZvcmUsIC51cGxvdCAqOjphZnRlciB7Ym94LXNpemluZzogYm9yZGVyLWJveDt9LnVwbG90IHtmb250LWZhbWlseTogc3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBcXFwiU2Vnb2UgVUlcXFwiLCBSb2JvdG8sIFxcXCJIZWx2ZXRpY2EgTmV1ZVxcXCIsIEFyaWFsLCBcXFwiTm90byBTYW5zXFxcIiwgc2Fucy1zZXJpZiwgXFxcIkFwcGxlIENvbG9yIEVtb2ppXFxcIiwgXFxcIlNlZ29lIFVJIEVtb2ppXFxcIiwgXFxcIlNlZ29lIFVJIFN5bWJvbFxcXCIsIFxcXCJOb3RvIENvbG9yIEVtb2ppXFxcIjtsaW5lLWhlaWdodDogMS41O3dpZHRoOiBtaW4tY29udGVudDt9LnUtdGl0bGUge3RleHQtYWxpZ246IGNlbnRlcjtmb250LXNpemU6IDE4cHg7Zm9udC13ZWlnaHQ6IGJvbGQ7fS51LXdyYXAge3Bvc2l0aW9uOiByZWxhdGl2ZTt1c2VyLXNlbGVjdDogbm9uZTt9LnUtb3ZlciwgLnUtdW5kZXIge3Bvc2l0aW9uOiBhYnNvbHV0ZTt9LnUtdW5kZXIge292ZXJmbG93OiBoaWRkZW47fS51cGxvdCBjYW52YXMge2Rpc3BsYXk6IGJsb2NrO3Bvc2l0aW9uOiByZWxhdGl2ZTt3aWR0aDogMTAwJTtoZWlnaHQ6IDEwMCU7fS51LWF4aXMge3Bvc2l0aW9uOiBhYnNvbHV0ZTt9LnUtbGVnZW5kIHtmb250LXNpemU6IDE0cHg7bWFyZ2luOiBhdXRvO3RleHQtYWxpZ246IGNlbnRlcjt9LnUtaW5saW5lIHtkaXNwbGF5OiBibG9jazt9LnUtaW5saW5lICoge2Rpc3BsYXk6IGlubGluZS1ibG9jazt9LnUtaW5saW5lIHRyIHttYXJnaW4tcmlnaHQ6IDE2cHg7fS51LWxlZ2VuZCB0aCB7Zm9udC13ZWlnaHQ6IDYwMDt9LnUtbGVnZW5kIHRoID4gKiB7dmVydGljYWwtYWxpZ246IG1pZGRsZTtkaXNwbGF5OiBpbmxpbmUtYmxvY2s7fS51LWxlZ2VuZCAudS1tYXJrZXIge3dpZHRoOiAxZW07aGVpZ2h0OiAxZW07bWFyZ2luLXJpZ2h0OiA0cHg7YmFja2dyb3VuZC1jbGlwOiBwYWRkaW5nLWJveCAhaW1wb3J0YW50O30udS1pbmxpbmUudS1saXZlIHRoOjphZnRlciB7Y29udGVudDogXFxcIjpcXFwiO3ZlcnRpY2FsLWFsaWduOiBtaWRkbGU7fS51LWlubGluZTpub3QoLnUtbGl2ZSkgLnUtdmFsdWUge2Rpc3BsYXk6IG5vbmU7fS51LXNlcmllcyA+ICoge3BhZGRpbmc6IDRweDt9LnUtc2VyaWVzIHRoIHtjdXJzb3I6IHBvaW50ZXI7fS51LWxlZ2VuZCAudS1vZmYgPiAqIHtvcGFjaXR5OiAwLjM7fS51LXNlbGVjdCB7YmFja2dyb3VuZDogcmdiYSgwLDAsMCwwLjA3KTtwb3NpdGlvbjogYWJzb2x1dGU7cG9pbnRlci1ldmVudHM6IG5vbmU7fS51LWN1cnNvci14LCAudS1jdXJzb3IteSB7cG9zaXRpb246IGFic29sdXRlO2xlZnQ6IDA7dG9wOiAwO3BvaW50ZXItZXZlbnRzOiBub25lO3dpbGwtY2hhbmdlOiB0cmFuc2Zvcm07ei1pbmRleDogMTAwO30udS1oeiAudS1jdXJzb3IteCwgLnUtdnQgLnUtY3Vyc29yLXkge2hlaWdodDogMTAwJTtib3JkZXItcmlnaHQ6IDFweCBkYXNoZWQgIzYwN0Q4Qjt9LnUtaHogLnUtY3Vyc29yLXksIC51LXZ0IC51LWN1cnNvci14IHt3aWR0aDogMTAwJTtib3JkZXItYm90dG9tOiAxcHggZGFzaGVkICM2MDdEOEI7fS51LWN1cnNvci1wdCB7cG9zaXRpb246IGFic29sdXRlO3RvcDogMDtsZWZ0OiAwO2JvcmRlci1yYWRpdXM6IDUwJTtib3JkZXI6IDAgc29saWQ7cG9pbnRlci1ldmVudHM6IG5vbmU7d2lsbC1jaGFuZ2U6IHRyYW5zZm9ybTt6LWluZGV4OiAxMDA7Lyp0aGlzIGhhcyB0byBiZSAhaW1wb3J0YW50IHNpbmNlIHdlIHNldCBpbmxpbmUgXFxcImJhY2tncm91bmRcXFwiIHNob3J0aGFuZCAqL2JhY2tncm91bmQtY2xpcDogcGFkZGluZy1ib3ggIWltcG9ydGFudDt9LnUtYXhpcy51LW9mZiwgLnUtc2VsZWN0LnUtb2ZmLCAudS1jdXJzb3IteC51LW9mZiwgLnUtY3Vyc29yLXkudS1vZmYsIC51LWN1cnNvci1wdC51LW9mZiB7ZGlzcGxheTogbm9uZTt9XCJdLFwic291cmNlUm9vdFwiOlwiXCJ9XSk7XG4vLyBFeHBvcnRzXG5leHBvcnQgZGVmYXVsdCBfX19DU1NfTE9BREVSX0VYUE9SVF9fXztcbiIsIlwidXNlIHN0cmljdFwiO1xuXG4vKlxuICBNSVQgTGljZW5zZSBodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL21pdC1saWNlbnNlLnBocFxuICBBdXRob3IgVG9iaWFzIEtvcHBlcnMgQHNva3JhXG4qL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoY3NzV2l0aE1hcHBpbmdUb1N0cmluZykge1xuICB2YXIgbGlzdCA9IFtdOyAvLyByZXR1cm4gdGhlIGxpc3Qgb2YgbW9kdWxlcyBhcyBjc3Mgc3RyaW5nXG5cbiAgbGlzdC50b1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiB0aGlzLm1hcChmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgdmFyIGNvbnRlbnQgPSBcIlwiO1xuICAgICAgdmFyIG5lZWRMYXllciA9IHR5cGVvZiBpdGVtWzVdICE9PSBcInVuZGVmaW5lZFwiO1xuXG4gICAgICBpZiAoaXRlbVs0XSkge1xuICAgICAgICBjb250ZW50ICs9IFwiQHN1cHBvcnRzIChcIi5jb25jYXQoaXRlbVs0XSwgXCIpIHtcIik7XG4gICAgICB9XG5cbiAgICAgIGlmIChpdGVtWzJdKSB7XG4gICAgICAgIGNvbnRlbnQgKz0gXCJAbWVkaWEgXCIuY29uY2F0KGl0ZW1bMl0sIFwiIHtcIik7XG4gICAgICB9XG5cbiAgICAgIGlmIChuZWVkTGF5ZXIpIHtcbiAgICAgICAgY29udGVudCArPSBcIkBsYXllclwiLmNvbmNhdChpdGVtWzVdLmxlbmd0aCA+IDAgPyBcIiBcIi5jb25jYXQoaXRlbVs1XSkgOiBcIlwiLCBcIiB7XCIpO1xuICAgICAgfVxuXG4gICAgICBjb250ZW50ICs9IGNzc1dpdGhNYXBwaW5nVG9TdHJpbmcoaXRlbSk7XG5cbiAgICAgIGlmIChuZWVkTGF5ZXIpIHtcbiAgICAgICAgY29udGVudCArPSBcIn1cIjtcbiAgICAgIH1cblxuICAgICAgaWYgKGl0ZW1bMl0pIHtcbiAgICAgICAgY29udGVudCArPSBcIn1cIjtcbiAgICAgIH1cblxuICAgICAgaWYgKGl0ZW1bNF0pIHtcbiAgICAgICAgY29udGVudCArPSBcIn1cIjtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNvbnRlbnQ7XG4gICAgfSkuam9pbihcIlwiKTtcbiAgfTsgLy8gaW1wb3J0IGEgbGlzdCBvZiBtb2R1bGVzIGludG8gdGhlIGxpc3RcblxuXG4gIGxpc3QuaSA9IGZ1bmN0aW9uIGkobW9kdWxlcywgbWVkaWEsIGRlZHVwZSwgc3VwcG9ydHMsIGxheWVyKSB7XG4gICAgaWYgKHR5cGVvZiBtb2R1bGVzID09PSBcInN0cmluZ1wiKSB7XG4gICAgICBtb2R1bGVzID0gW1tudWxsLCBtb2R1bGVzLCB1bmRlZmluZWRdXTtcbiAgICB9XG5cbiAgICB2YXIgYWxyZWFkeUltcG9ydGVkTW9kdWxlcyA9IHt9O1xuXG4gICAgaWYgKGRlZHVwZSkge1xuICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCB0aGlzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIHZhciBpZCA9IHRoaXNba11bMF07XG5cbiAgICAgICAgaWYgKGlkICE9IG51bGwpIHtcbiAgICAgICAgICBhbHJlYWR5SW1wb3J0ZWRNb2R1bGVzW2lkXSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKHZhciBfayA9IDA7IF9rIDwgbW9kdWxlcy5sZW5ndGg7IF9rKyspIHtcbiAgICAgIHZhciBpdGVtID0gW10uY29uY2F0KG1vZHVsZXNbX2tdKTtcblxuICAgICAgaWYgKGRlZHVwZSAmJiBhbHJlYWR5SW1wb3J0ZWRNb2R1bGVzW2l0ZW1bMF1dKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIGxheWVyICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgIGlmICh0eXBlb2YgaXRlbVs1XSA9PT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgIGl0ZW1bNV0gPSBsYXllcjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpdGVtWzFdID0gXCJAbGF5ZXJcIi5jb25jYXQoaXRlbVs1XS5sZW5ndGggPiAwID8gXCIgXCIuY29uY2F0KGl0ZW1bNV0pIDogXCJcIiwgXCIge1wiKS5jb25jYXQoaXRlbVsxXSwgXCJ9XCIpO1xuICAgICAgICAgIGl0ZW1bNV0gPSBsYXllcjtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAobWVkaWEpIHtcbiAgICAgICAgaWYgKCFpdGVtWzJdKSB7XG4gICAgICAgICAgaXRlbVsyXSA9IG1lZGlhO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGl0ZW1bMV0gPSBcIkBtZWRpYSBcIi5jb25jYXQoaXRlbVsyXSwgXCIge1wiKS5jb25jYXQoaXRlbVsxXSwgXCJ9XCIpO1xuICAgICAgICAgIGl0ZW1bMl0gPSBtZWRpYTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoc3VwcG9ydHMpIHtcbiAgICAgICAgaWYgKCFpdGVtWzRdKSB7XG4gICAgICAgICAgaXRlbVs0XSA9IFwiXCIuY29uY2F0KHN1cHBvcnRzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpdGVtWzFdID0gXCJAc3VwcG9ydHMgKFwiLmNvbmNhdChpdGVtWzRdLCBcIikge1wiKS5jb25jYXQoaXRlbVsxXSwgXCJ9XCIpO1xuICAgICAgICAgIGl0ZW1bNF0gPSBzdXBwb3J0cztcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBsaXN0LnB1c2goaXRlbSk7XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBsaXN0O1xufTsiLCJcInVzZSBzdHJpY3RcIjtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXRlbSkge1xuICB2YXIgY29udGVudCA9IGl0ZW1bMV07XG4gIHZhciBjc3NNYXBwaW5nID0gaXRlbVszXTtcblxuICBpZiAoIWNzc01hcHBpbmcpIHtcbiAgICByZXR1cm4gY29udGVudDtcbiAgfVxuXG4gIGlmICh0eXBlb2YgYnRvYSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgdmFyIGJhc2U2NCA9IGJ0b2EodW5lc2NhcGUoZW5jb2RlVVJJQ29tcG9uZW50KEpTT04uc3RyaW5naWZ5KGNzc01hcHBpbmcpKSkpO1xuICAgIHZhciBkYXRhID0gXCJzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtjaGFyc2V0PXV0Zi04O2Jhc2U2NCxcIi5jb25jYXQoYmFzZTY0KTtcbiAgICB2YXIgc291cmNlTWFwcGluZyA9IFwiLyojIFwiLmNvbmNhdChkYXRhLCBcIiAqL1wiKTtcbiAgICB2YXIgc291cmNlVVJMcyA9IGNzc01hcHBpbmcuc291cmNlcy5tYXAoZnVuY3Rpb24gKHNvdXJjZSkge1xuICAgICAgcmV0dXJuIFwiLyojIHNvdXJjZVVSTD1cIi5jb25jYXQoY3NzTWFwcGluZy5zb3VyY2VSb290IHx8IFwiXCIpLmNvbmNhdChzb3VyY2UsIFwiICovXCIpO1xuICAgIH0pO1xuICAgIHJldHVybiBbY29udGVudF0uY29uY2F0KHNvdXJjZVVSTHMpLmNvbmNhdChbc291cmNlTWFwcGluZ10pLmpvaW4oXCJcXG5cIik7XG4gIH1cblxuICByZXR1cm4gW2NvbnRlbnRdLmpvaW4oXCJcXG5cIik7XG59OyIsIlxuICAgICAgaW1wb3J0IEFQSSBmcm9tIFwiIS4uLy4uL3N0eWxlLWxvYWRlci9kaXN0L3J1bnRpbWUvaW5qZWN0U3R5bGVzSW50b1N0eWxlVGFnLmpzXCI7XG4gICAgICBpbXBvcnQgZG9tQVBJIGZyb20gXCIhLi4vLi4vc3R5bGUtbG9hZGVyL2Rpc3QvcnVudGltZS9zdHlsZURvbUFQSS5qc1wiO1xuICAgICAgaW1wb3J0IGluc2VydEZuIGZyb20gXCIhLi4vLi4vc3R5bGUtbG9hZGVyL2Rpc3QvcnVudGltZS9pbnNlcnRCeVNlbGVjdG9yLmpzXCI7XG4gICAgICBpbXBvcnQgc2V0QXR0cmlidXRlcyBmcm9tIFwiIS4uLy4uL3N0eWxlLWxvYWRlci9kaXN0L3J1bnRpbWUvc2V0QXR0cmlidXRlc1dpdGhvdXRBdHRyaWJ1dGVzLmpzXCI7XG4gICAgICBpbXBvcnQgaW5zZXJ0U3R5bGVFbGVtZW50IGZyb20gXCIhLi4vLi4vc3R5bGUtbG9hZGVyL2Rpc3QvcnVudGltZS9pbnNlcnRTdHlsZUVsZW1lbnQuanNcIjtcbiAgICAgIGltcG9ydCBzdHlsZVRhZ1RyYW5zZm9ybUZuIGZyb20gXCIhLi4vLi4vc3R5bGUtbG9hZGVyL2Rpc3QvcnVudGltZS9zdHlsZVRhZ1RyYW5zZm9ybS5qc1wiO1xuICAgICAgaW1wb3J0IGNvbnRlbnQsICogYXMgbmFtZWRFeHBvcnQgZnJvbSBcIiEhLi4vLi4vY3NzLWxvYWRlci9kaXN0L2Nqcy5qcyEuL3VQbG90Lm1pbi5jc3NcIjtcbiAgICAgIFxuICAgICAgXG5cbnZhciBvcHRpb25zID0ge307XG5cbm9wdGlvbnMuc3R5bGVUYWdUcmFuc2Zvcm0gPSBzdHlsZVRhZ1RyYW5zZm9ybUZuO1xub3B0aW9ucy5zZXRBdHRyaWJ1dGVzID0gc2V0QXR0cmlidXRlcztcblxuICAgICAgb3B0aW9ucy5pbnNlcnQgPSBpbnNlcnRGbi5iaW5kKG51bGwsIFwiaGVhZFwiKTtcbiAgICBcbm9wdGlvbnMuZG9tQVBJID0gZG9tQVBJO1xub3B0aW9ucy5pbnNlcnRTdHlsZUVsZW1lbnQgPSBpbnNlcnRTdHlsZUVsZW1lbnQ7XG5cbnZhciB1cGRhdGUgPSBBUEkoY29udGVudCwgb3B0aW9ucyk7XG5cblxuXG5leHBvcnQgKiBmcm9tIFwiISEuLi8uLi9jc3MtbG9hZGVyL2Rpc3QvY2pzLmpzIS4vdVBsb3QubWluLmNzc1wiO1xuICAgICAgIGV4cG9ydCBkZWZhdWx0IGNvbnRlbnQgJiYgY29udGVudC5sb2NhbHMgPyBjb250ZW50LmxvY2FscyA6IHVuZGVmaW5lZDtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgc3R5bGVzSW5ET00gPSBbXTtcblxuZnVuY3Rpb24gZ2V0SW5kZXhCeUlkZW50aWZpZXIoaWRlbnRpZmllcikge1xuICB2YXIgcmVzdWx0ID0gLTE7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHlsZXNJbkRPTS5sZW5ndGg7IGkrKykge1xuICAgIGlmIChzdHlsZXNJbkRPTVtpXS5pZGVudGlmaWVyID09PSBpZGVudGlmaWVyKSB7XG4gICAgICByZXN1bHQgPSBpO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gbW9kdWxlc1RvRG9tKGxpc3QsIG9wdGlvbnMpIHtcbiAgdmFyIGlkQ291bnRNYXAgPSB7fTtcbiAgdmFyIGlkZW50aWZpZXJzID0gW107XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGl0ZW0gPSBsaXN0W2ldO1xuICAgIHZhciBpZCA9IG9wdGlvbnMuYmFzZSA/IGl0ZW1bMF0gKyBvcHRpb25zLmJhc2UgOiBpdGVtWzBdO1xuICAgIHZhciBjb3VudCA9IGlkQ291bnRNYXBbaWRdIHx8IDA7XG4gICAgdmFyIGlkZW50aWZpZXIgPSBcIlwiLmNvbmNhdChpZCwgXCIgXCIpLmNvbmNhdChjb3VudCk7XG4gICAgaWRDb3VudE1hcFtpZF0gPSBjb3VudCArIDE7XG4gICAgdmFyIGluZGV4QnlJZGVudGlmaWVyID0gZ2V0SW5kZXhCeUlkZW50aWZpZXIoaWRlbnRpZmllcik7XG4gICAgdmFyIG9iaiA9IHtcbiAgICAgIGNzczogaXRlbVsxXSxcbiAgICAgIG1lZGlhOiBpdGVtWzJdLFxuICAgICAgc291cmNlTWFwOiBpdGVtWzNdLFxuICAgICAgc3VwcG9ydHM6IGl0ZW1bNF0sXG4gICAgICBsYXllcjogaXRlbVs1XVxuICAgIH07XG5cbiAgICBpZiAoaW5kZXhCeUlkZW50aWZpZXIgIT09IC0xKSB7XG4gICAgICBzdHlsZXNJbkRPTVtpbmRleEJ5SWRlbnRpZmllcl0ucmVmZXJlbmNlcysrO1xuICAgICAgc3R5bGVzSW5ET01baW5kZXhCeUlkZW50aWZpZXJdLnVwZGF0ZXIob2JqKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIHVwZGF0ZXIgPSBhZGRFbGVtZW50U3R5bGUob2JqLCBvcHRpb25zKTtcbiAgICAgIG9wdGlvbnMuYnlJbmRleCA9IGk7XG4gICAgICBzdHlsZXNJbkRPTS5zcGxpY2UoaSwgMCwge1xuICAgICAgICBpZGVudGlmaWVyOiBpZGVudGlmaWVyLFxuICAgICAgICB1cGRhdGVyOiB1cGRhdGVyLFxuICAgICAgICByZWZlcmVuY2VzOiAxXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZGVudGlmaWVycy5wdXNoKGlkZW50aWZpZXIpO1xuICB9XG5cbiAgcmV0dXJuIGlkZW50aWZpZXJzO1xufVxuXG5mdW5jdGlvbiBhZGRFbGVtZW50U3R5bGUob2JqLCBvcHRpb25zKSB7XG4gIHZhciBhcGkgPSBvcHRpb25zLmRvbUFQSShvcHRpb25zKTtcbiAgYXBpLnVwZGF0ZShvYmopO1xuXG4gIHZhciB1cGRhdGVyID0gZnVuY3Rpb24gdXBkYXRlcihuZXdPYmopIHtcbiAgICBpZiAobmV3T2JqKSB7XG4gICAgICBpZiAobmV3T2JqLmNzcyA9PT0gb2JqLmNzcyAmJiBuZXdPYmoubWVkaWEgPT09IG9iai5tZWRpYSAmJiBuZXdPYmouc291cmNlTWFwID09PSBvYmouc291cmNlTWFwICYmIG5ld09iai5zdXBwb3J0cyA9PT0gb2JqLnN1cHBvcnRzICYmIG5ld09iai5sYXllciA9PT0gb2JqLmxheWVyKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgYXBpLnVwZGF0ZShvYmogPSBuZXdPYmopO1xuICAgIH0gZWxzZSB7XG4gICAgICBhcGkucmVtb3ZlKCk7XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiB1cGRhdGVyO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChsaXN0LCBvcHRpb25zKSB7XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICBsaXN0ID0gbGlzdCB8fCBbXTtcbiAgdmFyIGxhc3RJZGVudGlmaWVycyA9IG1vZHVsZXNUb0RvbShsaXN0LCBvcHRpb25zKTtcbiAgcmV0dXJuIGZ1bmN0aW9uIHVwZGF0ZShuZXdMaXN0KSB7XG4gICAgbmV3TGlzdCA9IG5ld0xpc3QgfHwgW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxhc3RJZGVudGlmaWVycy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGlkZW50aWZpZXIgPSBsYXN0SWRlbnRpZmllcnNbaV07XG4gICAgICB2YXIgaW5kZXggPSBnZXRJbmRleEJ5SWRlbnRpZmllcihpZGVudGlmaWVyKTtcbiAgICAgIHN0eWxlc0luRE9NW2luZGV4XS5yZWZlcmVuY2VzLS07XG4gICAgfVxuXG4gICAgdmFyIG5ld0xhc3RJZGVudGlmaWVycyA9IG1vZHVsZXNUb0RvbShuZXdMaXN0LCBvcHRpb25zKTtcblxuICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBsYXN0SWRlbnRpZmllcnMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICB2YXIgX2lkZW50aWZpZXIgPSBsYXN0SWRlbnRpZmllcnNbX2ldO1xuXG4gICAgICB2YXIgX2luZGV4ID0gZ2V0SW5kZXhCeUlkZW50aWZpZXIoX2lkZW50aWZpZXIpO1xuXG4gICAgICBpZiAoc3R5bGVzSW5ET01bX2luZGV4XS5yZWZlcmVuY2VzID09PSAwKSB7XG4gICAgICAgIHN0eWxlc0luRE9NW19pbmRleF0udXBkYXRlcigpO1xuXG4gICAgICAgIHN0eWxlc0luRE9NLnNwbGljZShfaW5kZXgsIDEpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGxhc3RJZGVudGlmaWVycyA9IG5ld0xhc3RJZGVudGlmaWVycztcbiAgfTtcbn07IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBtZW1vID0ge307XG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAgKi9cblxuZnVuY3Rpb24gZ2V0VGFyZ2V0KHRhcmdldCkge1xuICBpZiAodHlwZW9mIG1lbW9bdGFyZ2V0XSA9PT0gXCJ1bmRlZmluZWRcIikge1xuICAgIHZhciBzdHlsZVRhcmdldCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodGFyZ2V0KTsgLy8gU3BlY2lhbCBjYXNlIHRvIHJldHVybiBoZWFkIG9mIGlmcmFtZSBpbnN0ZWFkIG9mIGlmcmFtZSBpdHNlbGZcblxuICAgIGlmICh3aW5kb3cuSFRNTElGcmFtZUVsZW1lbnQgJiYgc3R5bGVUYXJnZXQgaW5zdGFuY2VvZiB3aW5kb3cuSFRNTElGcmFtZUVsZW1lbnQpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIFRoaXMgd2lsbCB0aHJvdyBhbiBleGNlcHRpb24gaWYgYWNjZXNzIHRvIGlmcmFtZSBpcyBibG9ja2VkXG4gICAgICAgIC8vIGR1ZSB0byBjcm9zcy1vcmlnaW4gcmVzdHJpY3Rpb25zXG4gICAgICAgIHN0eWxlVGFyZ2V0ID0gc3R5bGVUYXJnZXQuY29udGVudERvY3VtZW50LmhlYWQ7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIC8vIGlzdGFuYnVsIGlnbm9yZSBuZXh0XG4gICAgICAgIHN0eWxlVGFyZ2V0ID0gbnVsbDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBtZW1vW3RhcmdldF0gPSBzdHlsZVRhcmdldDtcbiAgfVxuXG4gIHJldHVybiBtZW1vW3RhcmdldF07XG59XG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAgKi9cblxuXG5mdW5jdGlvbiBpbnNlcnRCeVNlbGVjdG9yKGluc2VydCwgc3R5bGUpIHtcbiAgdmFyIHRhcmdldCA9IGdldFRhcmdldChpbnNlcnQpO1xuXG4gIGlmICghdGFyZ2V0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiQ291bGRuJ3QgZmluZCBhIHN0eWxlIHRhcmdldC4gVGhpcyBwcm9iYWJseSBtZWFucyB0aGF0IHRoZSB2YWx1ZSBmb3IgdGhlICdpbnNlcnQnIHBhcmFtZXRlciBpcyBpbnZhbGlkLlwiKTtcbiAgfVxuXG4gIHRhcmdldC5hcHBlbmRDaGlsZChzdHlsZSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaW5zZXJ0QnlTZWxlY3RvcjsiLCJcInVzZSBzdHJpY3RcIjtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQgICovXG5mdW5jdGlvbiBpbnNlcnRTdHlsZUVsZW1lbnQob3B0aW9ucykge1xuICB2YXIgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJzdHlsZVwiKTtcbiAgb3B0aW9ucy5zZXRBdHRyaWJ1dGVzKGVsZW1lbnQsIG9wdGlvbnMuYXR0cmlidXRlcyk7XG4gIG9wdGlvbnMuaW5zZXJ0KGVsZW1lbnQsIG9wdGlvbnMub3B0aW9ucyk7XG4gIHJldHVybiBlbGVtZW50O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGluc2VydFN0eWxlRWxlbWVudDsiLCJcInVzZSBzdHJpY3RcIjtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQgICovXG5mdW5jdGlvbiBzZXRBdHRyaWJ1dGVzV2l0aG91dEF0dHJpYnV0ZXMoc3R5bGVFbGVtZW50KSB7XG4gIHZhciBub25jZSA9IHR5cGVvZiBfX3dlYnBhY2tfbm9uY2VfXyAhPT0gXCJ1bmRlZmluZWRcIiA/IF9fd2VicGFja19ub25jZV9fIDogbnVsbDtcblxuICBpZiAobm9uY2UpIHtcbiAgICBzdHlsZUVsZW1lbnQuc2V0QXR0cmlidXRlKFwibm9uY2VcIiwgbm9uY2UpO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gc2V0QXR0cmlidXRlc1dpdGhvdXRBdHRyaWJ1dGVzOyIsIlwidXNlIHN0cmljdFwiO1xuXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAgKi9cbmZ1bmN0aW9uIGFwcGx5KHN0eWxlRWxlbWVudCwgb3B0aW9ucywgb2JqKSB7XG4gIHZhciBjc3MgPSBcIlwiO1xuXG4gIGlmIChvYmouc3VwcG9ydHMpIHtcbiAgICBjc3MgKz0gXCJAc3VwcG9ydHMgKFwiLmNvbmNhdChvYmouc3VwcG9ydHMsIFwiKSB7XCIpO1xuICB9XG5cbiAgaWYgKG9iai5tZWRpYSkge1xuICAgIGNzcyArPSBcIkBtZWRpYSBcIi5jb25jYXQob2JqLm1lZGlhLCBcIiB7XCIpO1xuICB9XG5cbiAgdmFyIG5lZWRMYXllciA9IHR5cGVvZiBvYmoubGF5ZXIgIT09IFwidW5kZWZpbmVkXCI7XG5cbiAgaWYgKG5lZWRMYXllcikge1xuICAgIGNzcyArPSBcIkBsYXllclwiLmNvbmNhdChvYmoubGF5ZXIubGVuZ3RoID4gMCA/IFwiIFwiLmNvbmNhdChvYmoubGF5ZXIpIDogXCJcIiwgXCIge1wiKTtcbiAgfVxuXG4gIGNzcyArPSBvYmouY3NzO1xuXG4gIGlmIChuZWVkTGF5ZXIpIHtcbiAgICBjc3MgKz0gXCJ9XCI7XG4gIH1cblxuICBpZiAob2JqLm1lZGlhKSB7XG4gICAgY3NzICs9IFwifVwiO1xuICB9XG5cbiAgaWYgKG9iai5zdXBwb3J0cykge1xuICAgIGNzcyArPSBcIn1cIjtcbiAgfVxuXG4gIHZhciBzb3VyY2VNYXAgPSBvYmouc291cmNlTWFwO1xuXG4gIGlmIChzb3VyY2VNYXAgJiYgdHlwZW9mIGJ0b2EgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICBjc3MgKz0gXCJcXG4vKiMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LFwiLmNvbmNhdChidG9hKHVuZXNjYXBlKGVuY29kZVVSSUNvbXBvbmVudChKU09OLnN0cmluZ2lmeShzb3VyY2VNYXApKSkpLCBcIiAqL1wiKTtcbiAgfSAvLyBGb3Igb2xkIElFXG5cbiAgLyogaXN0YW5idWwgaWdub3JlIGlmICAqL1xuXG5cbiAgb3B0aW9ucy5zdHlsZVRhZ1RyYW5zZm9ybShjc3MsIHN0eWxlRWxlbWVudCwgb3B0aW9ucy5vcHRpb25zKTtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlU3R5bGVFbGVtZW50KHN0eWxlRWxlbWVudCkge1xuICAvLyBpc3RhbmJ1bCBpZ25vcmUgaWZcbiAgaWYgKHN0eWxlRWxlbWVudC5wYXJlbnROb2RlID09PSBudWxsKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgc3R5bGVFbGVtZW50LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoc3R5bGVFbGVtZW50KTtcbn1cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICAqL1xuXG5cbmZ1bmN0aW9uIGRvbUFQSShvcHRpb25zKSB7XG4gIHZhciBzdHlsZUVsZW1lbnQgPSBvcHRpb25zLmluc2VydFN0eWxlRWxlbWVudChvcHRpb25zKTtcbiAgcmV0dXJuIHtcbiAgICB1cGRhdGU6IGZ1bmN0aW9uIHVwZGF0ZShvYmopIHtcbiAgICAgIGFwcGx5KHN0eWxlRWxlbWVudCwgb3B0aW9ucywgb2JqKTtcbiAgICB9LFxuICAgIHJlbW92ZTogZnVuY3Rpb24gcmVtb3ZlKCkge1xuICAgICAgcmVtb3ZlU3R5bGVFbGVtZW50KHN0eWxlRWxlbWVudCk7XG4gICAgfVxuICB9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGRvbUFQSTsiLCJcInVzZSBzdHJpY3RcIjtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQgICovXG5mdW5jdGlvbiBzdHlsZVRhZ1RyYW5zZm9ybShjc3MsIHN0eWxlRWxlbWVudCkge1xuICBpZiAoc3R5bGVFbGVtZW50LnN0eWxlU2hlZXQpIHtcbiAgICBzdHlsZUVsZW1lbnQuc3R5bGVTaGVldC5jc3NUZXh0ID0gY3NzO1xuICB9IGVsc2Uge1xuICAgIHdoaWxlIChzdHlsZUVsZW1lbnQuZmlyc3RDaGlsZCkge1xuICAgICAgc3R5bGVFbGVtZW50LnJlbW92ZUNoaWxkKHN0eWxlRWxlbWVudC5maXJzdENoaWxkKTtcbiAgICB9XG5cbiAgICBzdHlsZUVsZW1lbnQuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoY3NzKSk7XG4gIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBzdHlsZVRhZ1RyYW5zZm9ybTsiLCIvKipcbiogQ29weXJpZ2h0IChjKSAyMDIyLCBMZW9uIFNvcm9raW5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC4gKE1JVCBMaWNlbnNlZClcbipcbiogdVBsb3QuanMgKM68UGxvdClcbiogQSBzbWFsbCwgZmFzdCBjaGFydCBmb3IgdGltZSBzZXJpZXMsIGxpbmVzLCBhcmVhcywgb2hsYyAmIGJhcnNcbiogaHR0cHM6Ly9naXRodWIuY29tL2xlZW9uaXlhL3VQbG90ICh2MS42LjIyKVxuKi9cblxuY29uc3QgRkVBVF9USU1FICAgICAgICAgID0gdHJ1ZTtcblxuY29uc3QgcHJlID0gXCJ1LVwiO1xuXG5jb25zdCBVUExPVCAgICAgICAgICA9ICAgICAgIFwidXBsb3RcIjtcbmNvbnN0IE9SSV9IWiAgICAgICAgID0gcHJlICsgXCJoelwiO1xuY29uc3QgT1JJX1ZUICAgICAgICAgPSBwcmUgKyBcInZ0XCI7XG5jb25zdCBUSVRMRSAgICAgICAgICA9IHByZSArIFwidGl0bGVcIjtcbmNvbnN0IFdSQVAgICAgICAgICAgID0gcHJlICsgXCJ3cmFwXCI7XG5jb25zdCBVTkRFUiAgICAgICAgICA9IHByZSArIFwidW5kZXJcIjtcbmNvbnN0IE9WRVIgICAgICAgICAgID0gcHJlICsgXCJvdmVyXCI7XG5jb25zdCBBWElTICAgICAgICAgICA9IHByZSArIFwiYXhpc1wiO1xuY29uc3QgT0ZGICAgICAgICAgICAgPSBwcmUgKyBcIm9mZlwiO1xuY29uc3QgU0VMRUNUICAgICAgICAgPSBwcmUgKyBcInNlbGVjdFwiO1xuY29uc3QgQ1VSU09SX1ggICAgICAgPSBwcmUgKyBcImN1cnNvci14XCI7XG5jb25zdCBDVVJTT1JfWSAgICAgICA9IHByZSArIFwiY3Vyc29yLXlcIjtcbmNvbnN0IENVUlNPUl9QVCAgICAgID0gcHJlICsgXCJjdXJzb3ItcHRcIjtcbmNvbnN0IExFR0VORCAgICAgICAgID0gcHJlICsgXCJsZWdlbmRcIjtcbmNvbnN0IExFR0VORF9MSVZFICAgID0gcHJlICsgXCJsaXZlXCI7XG5jb25zdCBMRUdFTkRfSU5MSU5FICA9IHByZSArIFwiaW5saW5lXCI7XG5jb25zdCBMRUdFTkRfVEhFQUQgICA9IHByZSArIFwidGhlYWRcIjtcbmNvbnN0IExFR0VORF9TRVJJRVMgID0gcHJlICsgXCJzZXJpZXNcIjtcbmNvbnN0IExFR0VORF9NQVJLRVIgID0gcHJlICsgXCJtYXJrZXJcIjtcbmNvbnN0IExFR0VORF9MQUJFTCAgID0gcHJlICsgXCJsYWJlbFwiO1xuY29uc3QgTEVHRU5EX1ZBTFVFICAgPSBwcmUgKyBcInZhbHVlXCI7XG5cbmNvbnN0IFdJRFRIICAgICAgID0gXCJ3aWR0aFwiO1xuY29uc3QgSEVJR0hUICAgICAgPSBcImhlaWdodFwiO1xuY29uc3QgVE9QICAgICAgICAgPSBcInRvcFwiO1xuY29uc3QgQk9UVE9NICAgICAgPSBcImJvdHRvbVwiO1xuY29uc3QgTEVGVCAgICAgICAgPSBcImxlZnRcIjtcbmNvbnN0IFJJR0hUICAgICAgID0gXCJyaWdodFwiO1xuY29uc3QgaGV4QmxhY2sgICAgPSBcIiMwMDBcIjtcbmNvbnN0IHRyYW5zcGFyZW50ID0gaGV4QmxhY2sgKyBcIjBcIjtcblxuY29uc3QgbW91c2Vtb3ZlICAgPSBcIm1vdXNlbW92ZVwiO1xuY29uc3QgbW91c2Vkb3duICAgPSBcIm1vdXNlZG93blwiO1xuY29uc3QgbW91c2V1cCAgICAgPSBcIm1vdXNldXBcIjtcbmNvbnN0IG1vdXNlZW50ZXIgID0gXCJtb3VzZWVudGVyXCI7XG5jb25zdCBtb3VzZWxlYXZlICA9IFwibW91c2VsZWF2ZVwiO1xuY29uc3QgZGJsY2xpY2sgICAgPSBcImRibGNsaWNrXCI7XG5jb25zdCByZXNpemUgICAgICA9IFwicmVzaXplXCI7XG5jb25zdCBzY3JvbGwgICAgICA9IFwic2Nyb2xsXCI7XG5cbmNvbnN0IGNoYW5nZSAgICAgID0gXCJjaGFuZ2VcIjtcbmNvbnN0IGRwcHhjaGFuZ2UgID0gXCJkcHB4Y2hhbmdlXCI7XG5cbmNvbnN0IGRvbUVudiA9IHR5cGVvZiB3aW5kb3cgIT0gJ3VuZGVmaW5lZCc7XG5cbmNvbnN0IGRvYyA9IGRvbUVudiA/IGRvY3VtZW50ICA6IG51bGw7XG5jb25zdCB3aW4gPSBkb21FbnYgPyB3aW5kb3cgICAgOiBudWxsO1xuY29uc3QgbmF2ID0gZG9tRW52ID8gbmF2aWdhdG9yIDogbnVsbDtcblxubGV0IHB4UmF0aW87XG5cbmxldCBxdWVyeTtcblxuZnVuY3Rpb24gc2V0UHhSYXRpbygpIHtcblx0bGV0IF9weFJhdGlvID0gZGV2aWNlUGl4ZWxSYXRpbztcblxuXHQvLyBkdXJpbmcgcHJpbnQgcHJldmlldywgQ2hyb21lIGZpcmVzIG9mZiB0aGVzZSBkcHB4IHF1ZXJpZXMgZXZlbiB3aXRob3V0IGNoYW5nZXNcblx0aWYgKHB4UmF0aW8gIT0gX3B4UmF0aW8pIHtcblx0XHRweFJhdGlvID0gX3B4UmF0aW87XG5cblx0XHRxdWVyeSAmJiBvZmYoY2hhbmdlLCBxdWVyeSwgc2V0UHhSYXRpbyk7XG5cdFx0cXVlcnkgPSBtYXRjaE1lZGlhKGAobWluLXJlc29sdXRpb246ICR7cHhSYXRpbyAtIDAuMDAxfWRwcHgpIGFuZCAobWF4LXJlc29sdXRpb246ICR7cHhSYXRpbyArIDAuMDAxfWRwcHgpYCk7XG5cdFx0b24oY2hhbmdlLCBxdWVyeSwgc2V0UHhSYXRpbyk7XG5cblx0XHR3aW4uZGlzcGF0Y2hFdmVudChuZXcgQ3VzdG9tRXZlbnQoZHBweGNoYW5nZSkpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGFkZENsYXNzKGVsLCBjKSB7XG5cdGlmIChjICE9IG51bGwpIHtcblx0XHRsZXQgY2wgPSBlbC5jbGFzc0xpc3Q7XG5cdFx0IWNsLmNvbnRhaW5zKGMpICYmIGNsLmFkZChjKTtcblx0fVxufVxuXG5mdW5jdGlvbiByZW1DbGFzcyhlbCwgYykge1xuXHRsZXQgY2wgPSBlbC5jbGFzc0xpc3Q7XG5cdGNsLmNvbnRhaW5zKGMpICYmIGNsLnJlbW92ZShjKTtcbn1cblxuZnVuY3Rpb24gc2V0U3R5bGVQeChlbCwgbmFtZSwgdmFsdWUpIHtcblx0ZWwuc3R5bGVbbmFtZV0gPSB2YWx1ZSArIFwicHhcIjtcbn1cblxuZnVuY3Rpb24gcGxhY2VUYWcodGFnLCBjbHMsIHRhcmcsIHJlZkVsKSB7XG5cdGxldCBlbCA9IGRvYy5jcmVhdGVFbGVtZW50KHRhZyk7XG5cblx0aWYgKGNscyAhPSBudWxsKVxuXHRcdGFkZENsYXNzKGVsLCBjbHMpO1xuXG5cdGlmICh0YXJnICE9IG51bGwpXG5cdFx0dGFyZy5pbnNlcnRCZWZvcmUoZWwsIHJlZkVsKTtcblxuXHRyZXR1cm4gZWw7XG59XG5cbmZ1bmN0aW9uIHBsYWNlRGl2KGNscywgdGFyZykge1xuXHRyZXR1cm4gcGxhY2VUYWcoXCJkaXZcIiwgY2xzLCB0YXJnKTtcbn1cblxuY29uc3QgeGZvcm1DYWNoZSA9IG5ldyBXZWFrTWFwKCk7XG5cbmZ1bmN0aW9uIGVsVHJhbnMoZWwsIHhQb3MsIHlQb3MsIHhNYXgsIHlNYXgpIHtcblx0bGV0IHhmb3JtID0gXCJ0cmFuc2xhdGUoXCIgKyB4UG9zICsgXCJweCxcIiArIHlQb3MgKyBcInB4KVwiO1xuXHRsZXQgeGZvcm1PbGQgPSB4Zm9ybUNhY2hlLmdldChlbCk7XG5cblx0aWYgKHhmb3JtICE9IHhmb3JtT2xkKSB7XG5cdFx0ZWwuc3R5bGUudHJhbnNmb3JtID0geGZvcm07XG5cdFx0eGZvcm1DYWNoZS5zZXQoZWwsIHhmb3JtKTtcblxuXHRcdGlmICh4UG9zIDwgMCB8fCB5UG9zIDwgMCB8fCB4UG9zID4geE1heCB8fCB5UG9zID4geU1heClcblx0XHRcdGFkZENsYXNzKGVsLCBPRkYpO1xuXHRcdGVsc2Vcblx0XHRcdHJlbUNsYXNzKGVsLCBPRkYpO1xuXHR9XG59XG5cbmNvbnN0IGNvbG9yQ2FjaGUgPSBuZXcgV2Vha01hcCgpO1xuXG5mdW5jdGlvbiBlbENvbG9yKGVsLCBiYWNrZ3JvdW5kLCBib3JkZXJDb2xvcikge1xuXHRsZXQgbmV3Q29sb3IgPSBiYWNrZ3JvdW5kICsgYm9yZGVyQ29sb3I7XG5cdGxldCBvbGRDb2xvciA9IGNvbG9yQ2FjaGUuZ2V0KGVsKTtcblxuXHRpZiAobmV3Q29sb3IgIT0gb2xkQ29sb3IpIHtcblx0XHRjb2xvckNhY2hlLnNldChlbCwgbmV3Q29sb3IpO1xuXHRcdGVsLnN0eWxlLmJhY2tncm91bmQgPSBiYWNrZ3JvdW5kO1xuXHRcdGVsLnN0eWxlLmJvcmRlckNvbG9yID0gYm9yZGVyQ29sb3I7XG5cdH1cbn1cblxuY29uc3Qgc2l6ZUNhY2hlID0gbmV3IFdlYWtNYXAoKTtcblxuZnVuY3Rpb24gZWxTaXplKGVsLCBuZXdXaWQsIG5ld0hndCwgY2VudGVyZWQpIHtcblx0bGV0IG5ld1NpemUgPSBuZXdXaWQgKyBcIlwiICsgbmV3SGd0O1xuXHRsZXQgb2xkU2l6ZSA9IHNpemVDYWNoZS5nZXQoZWwpO1xuXG5cdGlmIChuZXdTaXplICE9IG9sZFNpemUpIHtcblx0XHRzaXplQ2FjaGUuc2V0KGVsLCBuZXdTaXplKTtcblx0XHRlbC5zdHlsZS5oZWlnaHQgPSBuZXdIZ3QgKyBcInB4XCI7XG5cdFx0ZWwuc3R5bGUud2lkdGggPSBuZXdXaWQgKyBcInB4XCI7XG5cdFx0ZWwuc3R5bGUubWFyZ2luTGVmdCA9IGNlbnRlcmVkID8gLW5ld1dpZC8yICsgXCJweFwiIDogMDtcblx0XHRlbC5zdHlsZS5tYXJnaW5Ub3AgPSBjZW50ZXJlZCA/IC1uZXdIZ3QvMiArIFwicHhcIiA6IDA7XG5cdH1cbn1cblxuY29uc3QgZXZPcHRzID0ge3Bhc3NpdmU6IHRydWV9O1xuY29uc3QgZXZPcHRzMiA9IHsuLi5ldk9wdHMsIGNhcHR1cmU6IHRydWV9O1xuXG5mdW5jdGlvbiBvbihldiwgZWwsIGNiLCBjYXB0KSB7XG5cdGVsLmFkZEV2ZW50TGlzdGVuZXIoZXYsIGNiLCBjYXB0ID8gZXZPcHRzMiA6IGV2T3B0cyk7XG59XG5cbmZ1bmN0aW9uIG9mZihldiwgZWwsIGNiLCBjYXB0KSB7XG5cdGVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoZXYsIGNiLCBjYXB0ID8gZXZPcHRzMiA6IGV2T3B0cyk7XG59XG5cbmRvbUVudiAmJiBzZXRQeFJhdGlvKCk7XG5cbi8vIGJpbmFyeSBzZWFyY2ggZm9yIGluZGV4IG9mIGNsb3Nlc3QgdmFsdWVcbmZ1bmN0aW9uIGNsb3Nlc3RJZHgobnVtLCBhcnIsIGxvLCBoaSkge1xuXHRsZXQgbWlkO1xuXHRsbyA9IGxvIHx8IDA7XG5cdGhpID0gaGkgfHwgYXJyLmxlbmd0aCAtIDE7XG5cdGxldCBiaXR3aXNlID0gaGkgPD0gMjE0NzQ4MzY0NztcblxuXHR3aGlsZSAoaGkgLSBsbyA+IDEpIHtcblx0XHRtaWQgPSBiaXR3aXNlID8gKGxvICsgaGkpID4+IDEgOiBmbG9vcigobG8gKyBoaSkgLyAyKTtcblxuXHRcdGlmIChhcnJbbWlkXSA8IG51bSlcblx0XHRcdGxvID0gbWlkO1xuXHRcdGVsc2Vcblx0XHRcdGhpID0gbWlkO1xuXHR9XG5cblx0aWYgKG51bSAtIGFycltsb10gPD0gYXJyW2hpXSAtIG51bSlcblx0XHRyZXR1cm4gbG87XG5cblx0cmV0dXJuIGhpO1xufVxuXG5mdW5jdGlvbiBub25OdWxsSWR4KGRhdGEsIF9pMCwgX2kxLCBkaXIpIHtcblx0Zm9yIChsZXQgaSA9IGRpciA9PSAxID8gX2kwIDogX2kxOyBpID49IF9pMCAmJiBpIDw9IF9pMTsgaSArPSBkaXIpIHtcblx0XHRpZiAoZGF0YVtpXSAhPSBudWxsKVxuXHRcdFx0cmV0dXJuIGk7XG5cdH1cblxuXHRyZXR1cm4gLTE7XG59XG5cbmZ1bmN0aW9uIGdldE1pbk1heChkYXRhLCBfaTAsIF9pMSwgc29ydGVkKSB7XG4vL1x0Y29uc29sZS5sb2coXCJnZXRNaW5NYXgoKVwiKTtcblxuXHRsZXQgX21pbiA9IGluZjtcblx0bGV0IF9tYXggPSAtaW5mO1xuXG5cdGlmIChzb3J0ZWQgPT0gMSkge1xuXHRcdF9taW4gPSBkYXRhW19pMF07XG5cdFx0X21heCA9IGRhdGFbX2kxXTtcblx0fVxuXHRlbHNlIGlmIChzb3J0ZWQgPT0gLTEpIHtcblx0XHRfbWluID0gZGF0YVtfaTFdO1xuXHRcdF9tYXggPSBkYXRhW19pMF07XG5cdH1cblx0ZWxzZSB7XG5cdFx0Zm9yIChsZXQgaSA9IF9pMDsgaSA8PSBfaTE7IGkrKykge1xuXHRcdFx0aWYgKGRhdGFbaV0gIT0gbnVsbCkge1xuXHRcdFx0XHRfbWluID0gbWluKF9taW4sIGRhdGFbaV0pO1xuXHRcdFx0XHRfbWF4ID0gbWF4KF9tYXgsIGRhdGFbaV0pO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHJldHVybiBbX21pbiwgX21heF07XG59XG5cbmZ1bmN0aW9uIGdldE1pbk1heExvZyhkYXRhLCBfaTAsIF9pMSkge1xuLy9cdGNvbnNvbGUubG9nKFwiZ2V0TWluTWF4KClcIik7XG5cblx0bGV0IF9taW4gPSBpbmY7XG5cdGxldCBfbWF4ID0gLWluZjtcblxuXHRmb3IgKGxldCBpID0gX2kwOyBpIDw9IF9pMTsgaSsrKSB7XG5cdFx0aWYgKGRhdGFbaV0gPiAwKSB7XG5cdFx0XHRfbWluID0gbWluKF9taW4sIGRhdGFbaV0pO1xuXHRcdFx0X21heCA9IG1heChfbWF4LCBkYXRhW2ldKTtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gW1xuXHRcdF9taW4gPT0gIGluZiA/ICAxIDogX21pbixcblx0XHRfbWF4ID09IC1pbmYgPyAxMCA6IF9tYXgsXG5cdF07XG59XG5cbmNvbnN0IF9maXhlZFR1cGxlID0gWzAsIDBdO1xuXG5mdW5jdGlvbiBmaXhJbmNyKG1pbkluY3IsIG1heEluY3IsIG1pbkV4cCwgbWF4RXhwKSB7XG5cdF9maXhlZFR1cGxlWzBdID0gbWluRXhwIDwgMCA/IHJvdW5kRGVjKG1pbkluY3IsIC1taW5FeHApIDogbWluSW5jcjtcblx0X2ZpeGVkVHVwbGVbMV0gPSBtYXhFeHAgPCAwID8gcm91bmREZWMobWF4SW5jciwgLW1heEV4cCkgOiBtYXhJbmNyO1xuXHRyZXR1cm4gX2ZpeGVkVHVwbGU7XG59XG5cbmZ1bmN0aW9uIHJhbmdlTG9nKG1pbiwgbWF4LCBiYXNlLCBmdWxsTWFncykge1xuXHRsZXQgbWluU2lnbiA9IHNpZ24obWluKTtcblxuXHRsZXQgbG9nRm4gPSBiYXNlID09IDEwID8gbG9nMTAgOiBsb2cyO1xuXG5cdGlmIChtaW4gPT0gbWF4KSB7XG5cdFx0aWYgKG1pblNpZ24gPT0gLTEpIHtcblx0XHRcdG1pbiAqPSBiYXNlO1xuXHRcdFx0bWF4IC89IGJhc2U7XG5cdFx0fVxuXHRcdGVsc2Uge1xuXHRcdFx0bWluIC89IGJhc2U7XG5cdFx0XHRtYXggKj0gYmFzZTtcblx0XHR9XG5cdH1cblxuXHRsZXQgbWluRXhwLCBtYXhFeHAsIG1pbk1heEluY3JzO1xuXG5cdGlmIChmdWxsTWFncykge1xuXHRcdG1pbkV4cCA9IGZsb29yKGxvZ0ZuKG1pbikpO1xuXHRcdG1heEV4cCA9ICBjZWlsKGxvZ0ZuKG1heCkpO1xuXG5cdFx0bWluTWF4SW5jcnMgPSBmaXhJbmNyKHBvdyhiYXNlLCBtaW5FeHApLCBwb3coYmFzZSwgbWF4RXhwKSwgbWluRXhwLCBtYXhFeHApO1xuXG5cdFx0bWluID0gbWluTWF4SW5jcnNbMF07XG5cdFx0bWF4ID0gbWluTWF4SW5jcnNbMV07XG5cdH1cblx0ZWxzZSB7XG5cdFx0bWluRXhwID0gZmxvb3IobG9nRm4oYWJzKG1pbikpKTtcblx0XHRtYXhFeHAgPSBmbG9vcihsb2dGbihhYnMobWF4KSkpO1xuXG5cdFx0bWluTWF4SW5jcnMgPSBmaXhJbmNyKHBvdyhiYXNlLCBtaW5FeHApLCBwb3coYmFzZSwgbWF4RXhwKSwgbWluRXhwLCBtYXhFeHApO1xuXG5cdFx0bWluID0gaW5jclJvdW5kRG4obWluLCBtaW5NYXhJbmNyc1swXSk7XG5cdFx0bWF4ID0gaW5jclJvdW5kVXAobWF4LCBtaW5NYXhJbmNyc1sxXSk7XG5cdH1cblxuXHRyZXR1cm4gW21pbiwgbWF4XTtcbn1cblxuZnVuY3Rpb24gcmFuZ2VBc2luaChtaW4sIG1heCwgYmFzZSwgZnVsbE1hZ3MpIHtcblx0bGV0IG1pbk1heCA9IHJhbmdlTG9nKG1pbiwgbWF4LCBiYXNlLCBmdWxsTWFncyk7XG5cblx0aWYgKG1pbiA9PSAwKVxuXHRcdG1pbk1heFswXSA9IDA7XG5cblx0aWYgKG1heCA9PSAwKVxuXHRcdG1pbk1heFsxXSA9IDA7XG5cblx0cmV0dXJuIG1pbk1heDtcbn1cblxuY29uc3QgcmFuZ2VQYWQgPSAwLjE7XG5cbmNvbnN0IGF1dG9SYW5nZVBhcnQgPSB7XG5cdG1vZGU6IDMsXG5cdHBhZDogcmFuZ2VQYWQsXG59O1xuXG5jb25zdCBfZXFSYW5nZVBhcnQgPSB7XG5cdHBhZDogIDAsXG5cdHNvZnQ6IG51bGwsXG5cdG1vZGU6IDAsXG59O1xuXG5jb25zdCBfZXFSYW5nZSA9IHtcblx0bWluOiBfZXFSYW5nZVBhcnQsXG5cdG1heDogX2VxUmFuZ2VQYXJ0LFxufTtcblxuLy8gdGhpcyBlbnN1cmVzIHRoYXQgbm9uLXRlbXBvcmFsL251bWVyaWMgeS1heGVzIGdldCBtdWx0aXBsZS1zbmFwcGVkIHBhZGRpbmcgYWRkZWQgYWJvdmUvYmVsb3dcbi8vIFRPRE86IGFsc28gYWNjb3VudCBmb3IgaW5jcnMgd2hlbiBzbmFwcGluZyB0byBlbnN1cmUgdG9wIG9mIGF4aXMgZ2V0cyBhIHRpY2sgJiB2YWx1ZVxuZnVuY3Rpb24gcmFuZ2VOdW0oX21pbiwgX21heCwgbXVsdCwgZXh0cmEpIHtcblx0aWYgKGlzT2JqKG11bHQpKVxuXHRcdHJldHVybiBfcmFuZ2VOdW0oX21pbiwgX21heCwgbXVsdCk7XG5cblx0X2VxUmFuZ2VQYXJ0LnBhZCAgPSBtdWx0O1xuXHRfZXFSYW5nZVBhcnQuc29mdCA9IGV4dHJhID8gMCA6IG51bGw7XG5cdF9lcVJhbmdlUGFydC5tb2RlID0gZXh0cmEgPyAzIDogMDtcblxuXHRyZXR1cm4gX3JhbmdlTnVtKF9taW4sIF9tYXgsIF9lcVJhbmdlKTtcbn1cblxuLy8gbnVsbGlzaCBjb2FsZXNjZVxuZnVuY3Rpb24gaWZOdWxsKGxoLCByaCkge1xuXHRyZXR1cm4gbGggPT0gbnVsbCA/IHJoIDogbGg7XG59XG5cbi8vIGNoZWNrcyBpZiBnaXZlbiBpbmRleCByYW5nZSBpbiBhbiBhcnJheSBjb250YWlucyBhIG5vbi1udWxsIHZhbHVlXG4vLyBha2EgYSByYW5nZS1ib3VuZGVkIEFycmF5LnNvbWUoKVxuZnVuY3Rpb24gaGFzRGF0YShkYXRhLCBpZHgwLCBpZHgxKSB7XG5cdGlkeDAgPSBpZk51bGwoaWR4MCwgMCk7XG5cdGlkeDEgPSBpZk51bGwoaWR4MSwgZGF0YS5sZW5ndGggLSAxKTtcblxuXHR3aGlsZSAoaWR4MCA8PSBpZHgxKSB7XG5cdFx0aWYgKGRhdGFbaWR4MF0gIT0gbnVsbClcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdGlkeDArKztcblx0fVxuXG5cdHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gX3JhbmdlTnVtKF9taW4sIF9tYXgsIGNmZykge1xuXHRsZXQgY21pbiA9IGNmZy5taW47XG5cdGxldCBjbWF4ID0gY2ZnLm1heDtcblxuXHRsZXQgcGFkTWluID0gaWZOdWxsKGNtaW4ucGFkLCAwKTtcblx0bGV0IHBhZE1heCA9IGlmTnVsbChjbWF4LnBhZCwgMCk7XG5cblx0bGV0IGhhcmRNaW4gPSBpZk51bGwoY21pbi5oYXJkLCAtaW5mKTtcblx0bGV0IGhhcmRNYXggPSBpZk51bGwoY21heC5oYXJkLCAgaW5mKTtcblxuXHRsZXQgc29mdE1pbiA9IGlmTnVsbChjbWluLnNvZnQsICBpbmYpO1xuXHRsZXQgc29mdE1heCA9IGlmTnVsbChjbWF4LnNvZnQsIC1pbmYpO1xuXG5cdGxldCBzb2Z0TWluTW9kZSA9IGlmTnVsbChjbWluLm1vZGUsIDApO1xuXHRsZXQgc29mdE1heE1vZGUgPSBpZk51bGwoY21heC5tb2RlLCAwKTtcblxuXHRsZXQgZGVsdGEgICAgICAgID0gX21heCAtIF9taW47XG5cblx0Ly8gdGhpcyBoYW5kbGVzIHNpdHVhdGlvbnMgbGlrZSA4OS43LCA4OS42OTk5OTk5OTk5OTk5OVxuXHQvLyBieSBhc3N1bWluZyAwLjAwMXggZGVsdGFzIGFyZSBwcmVjaXNpb24gZXJyb3JzXG4vL1x0aWYgKGRlbHRhID4gMCAmJiBkZWx0YSA8IGFicyhfbWF4KSAvIDFlMylcbi8vXHRcdGRlbHRhID0gMDtcblxuXHQvLyB0cmVhdCBkYXRhIGFzIGZsYXQgaWYgZGVsdGEgaXMgbGVzcyB0aGFuIDEgYmlsbGlvbnRoXG5cdGlmIChkZWx0YSA8IDFlLTkpIHtcblx0XHRkZWx0YSA9IDA7XG5cblx0XHQvLyBpZiBzb2Z0IG1vZGUgaXMgMiBhbmQgYWxsIHZhbHMgYXJlIGZsYXQgYXQgMCwgYXZvaWQgdGhlIDAuMSAqIDFlMyBmYWxsYmFja1xuXHRcdC8vIHRoaXMgcHJldmVudHMgMCwwLDAgZnJvbSByYW5naW5nIHRvIC0xMDAsMTAwIHdoZW4gc29mdE1pbi9zb2Z0TWF4IGFyZSAtMSwxXG5cdFx0aWYgKF9taW4gPT0gMCB8fCBfbWF4ID09IDApIHtcblx0XHRcdGRlbHRhID0gMWUtOTtcblxuXHRcdFx0aWYgKHNvZnRNaW5Nb2RlID09IDIgJiYgc29mdE1pbiAhPSBpbmYpXG5cdFx0XHRcdHBhZE1pbiA9IDA7XG5cblx0XHRcdGlmIChzb2Z0TWF4TW9kZSA9PSAyICYmIHNvZnRNYXggIT0gLWluZilcblx0XHRcdFx0cGFkTWF4ID0gMDtcblx0XHR9XG5cdH1cblxuXHRsZXQgbm9uWmVyb0RlbHRhID0gZGVsdGEgfHwgYWJzKF9tYXgpIHx8IDFlMztcblx0bGV0IG1hZyAgICAgICAgICA9IGxvZzEwKG5vblplcm9EZWx0YSk7XG5cdGxldCBiYXNlICAgICAgICAgPSBwb3coMTAsIGZsb29yKG1hZykpO1xuXG5cdGxldCBfcGFkTWluICA9IG5vblplcm9EZWx0YSAqIChkZWx0YSA9PSAwID8gKF9taW4gPT0gMCA/IC4xIDogMSkgOiBwYWRNaW4pO1xuXHRsZXQgX25ld01pbiAgPSByb3VuZERlYyhpbmNyUm91bmREbihfbWluIC0gX3BhZE1pbiwgYmFzZS8xMCksIDkpO1xuXHRsZXQgX3NvZnRNaW4gPSBfbWluID49IHNvZnRNaW4gJiYgKHNvZnRNaW5Nb2RlID09IDEgfHwgc29mdE1pbk1vZGUgPT0gMyAmJiBfbmV3TWluIDw9IHNvZnRNaW4gfHwgc29mdE1pbk1vZGUgPT0gMiAmJiBfbmV3TWluID49IHNvZnRNaW4pID8gc29mdE1pbiA6IGluZjtcblx0bGV0IG1pbkxpbSAgID0gbWF4KGhhcmRNaW4sIF9uZXdNaW4gPCBfc29mdE1pbiAmJiBfbWluID49IF9zb2Z0TWluID8gX3NvZnRNaW4gOiBtaW4oX3NvZnRNaW4sIF9uZXdNaW4pKTtcblxuXHRsZXQgX3BhZE1heCAgPSBub25aZXJvRGVsdGEgKiAoZGVsdGEgPT0gMCA/IChfbWF4ID09IDAgPyAuMSA6IDEpIDogcGFkTWF4KTtcblx0bGV0IF9uZXdNYXggID0gcm91bmREZWMoaW5jclJvdW5kVXAoX21heCArIF9wYWRNYXgsIGJhc2UvMTApLCA5KTtcblx0bGV0IF9zb2Z0TWF4ID0gX21heCA8PSBzb2Z0TWF4ICYmIChzb2Z0TWF4TW9kZSA9PSAxIHx8IHNvZnRNYXhNb2RlID09IDMgJiYgX25ld01heCA+PSBzb2Z0TWF4IHx8IHNvZnRNYXhNb2RlID09IDIgJiYgX25ld01heCA8PSBzb2Z0TWF4KSA/IHNvZnRNYXggOiAtaW5mO1xuXHRsZXQgbWF4TGltICAgPSBtaW4oaGFyZE1heCwgX25ld01heCA+IF9zb2Z0TWF4ICYmIF9tYXggPD0gX3NvZnRNYXggPyBfc29mdE1heCA6IG1heChfc29mdE1heCwgX25ld01heCkpO1xuXG5cdGlmIChtaW5MaW0gPT0gbWF4TGltICYmIG1pbkxpbSA9PSAwKVxuXHRcdG1heExpbSA9IDEwMDtcblxuXHRyZXR1cm4gW21pbkxpbSwgbWF4TGltXTtcbn1cblxuLy8gYWx0ZXJuYXRpdmU6IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8yMjU0ODk2XG5jb25zdCBudW1Gb3JtYXR0ZXIgPSBuZXcgSW50bC5OdW1iZXJGb3JtYXQoZG9tRW52ID8gbmF2Lmxhbmd1YWdlIDogJ2VuLVVTJyk7XG5jb25zdCBmbXROdW0gPSB2YWwgPT4gbnVtRm9ybWF0dGVyLmZvcm1hdCh2YWwpO1xuXG5jb25zdCBNID0gTWF0aDtcblxuY29uc3QgUEkgPSBNLlBJO1xuY29uc3QgYWJzID0gTS5hYnM7XG5jb25zdCBmbG9vciA9IE0uZmxvb3I7XG5jb25zdCByb3VuZCA9IE0ucm91bmQ7XG5jb25zdCBjZWlsID0gTS5jZWlsO1xuY29uc3QgbWluID0gTS5taW47XG5jb25zdCBtYXggPSBNLm1heDtcbmNvbnN0IHBvdyA9IE0ucG93O1xuY29uc3Qgc2lnbiA9IE0uc2lnbjtcbmNvbnN0IGxvZzEwID0gTS5sb2cxMDtcbmNvbnN0IGxvZzIgPSBNLmxvZzI7XG4vLyBUT0RPOiBzZWVtcyBsaWtlIHRoaXMgbmVlZHMgdG8gbWF0Y2ggYXNpbmggaW1wbCBpZiB0aGUgcGFzc2VkIHYgaXMgdHdlYWtlZD9cbmNvbnN0IHNpbmggPSAgKHYsIGxpbnRocmVzaCA9IDEpID0+IE0uc2luaCh2KSAqIGxpbnRocmVzaDtcbmNvbnN0IGFzaW5oID0gKHYsIGxpbnRocmVzaCA9IDEpID0+IE0uYXNpbmgodiAvIGxpbnRocmVzaCk7XG5cbmNvbnN0IGluZiA9IEluZmluaXR5O1xuXG5mdW5jdGlvbiBudW1JbnREaWdpdHMoeCkge1xuXHRyZXR1cm4gKGxvZzEwKCh4IF4gKHggPj4gMzEpKSAtICh4ID4+IDMxKSkgfCAwKSArIDE7XG59XG5cbmZ1bmN0aW9uIGluY3JSb3VuZChudW0sIGluY3IpIHtcblx0cmV0dXJuIHJvdW5kKG51bS9pbmNyKSppbmNyO1xufVxuXG5mdW5jdGlvbiBjbGFtcChudW0sIF9taW4sIF9tYXgpIHtcblx0cmV0dXJuIG1pbihtYXgobnVtLCBfbWluKSwgX21heCk7XG59XG5cbmZ1bmN0aW9uIGZuT3JTZWxmKHYpIHtcblx0cmV0dXJuIHR5cGVvZiB2ID09IFwiZnVuY3Rpb25cIiA/IHYgOiAoKSA9PiB2O1xufVxuXG5jb25zdCByZXRBcmcwID0gXzAgPT4gXzA7XG5cbmNvbnN0IHJldEFyZzEgPSAoXzAsIF8xKSA9PiBfMTtcblxuY29uc3QgcmV0TnVsbCA9IF8gPT4gbnVsbDtcblxuY29uc3QgcmV0VHJ1ZSA9IF8gPT4gdHJ1ZTtcblxuY29uc3QgcmV0RXEgPSAoYSwgYikgPT4gYSA9PSBiO1xuXG5mdW5jdGlvbiBpbmNyUm91bmRVcChudW0sIGluY3IpIHtcblx0cmV0dXJuIGNlaWwobnVtL2luY3IpKmluY3I7XG59XG5cbmZ1bmN0aW9uIGluY3JSb3VuZERuKG51bSwgaW5jcikge1xuXHRyZXR1cm4gZmxvb3IobnVtL2luY3IpKmluY3I7XG59XG5cbmZ1bmN0aW9uIHJvdW5kRGVjKHZhbCwgZGVjKSB7XG5cdHJldHVybiByb3VuZCh2YWwgKiAoZGVjID0gMTAqKmRlYykpIC8gZGVjO1xufVxuXG5jb25zdCBmaXhlZERlYyA9IG5ldyBNYXAoKTtcblxuZnVuY3Rpb24gZ3Vlc3NEZWMobnVtKSB7XG5cdHJldHVybiAoKFwiXCIrbnVtKS5zcGxpdChcIi5cIilbMV0gfHwgXCJcIikubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBnZW5JbmNycyhiYXNlLCBtaW5FeHAsIG1heEV4cCwgbXVsdHMpIHtcblx0bGV0IGluY3JzID0gW107XG5cblx0bGV0IG11bHREZWMgPSBtdWx0cy5tYXAoZ3Vlc3NEZWMpO1xuXG5cdGZvciAobGV0IGV4cCA9IG1pbkV4cDsgZXhwIDwgbWF4RXhwOyBleHArKykge1xuXHRcdGxldCBleHBhID0gYWJzKGV4cCk7XG5cdFx0bGV0IG1hZyA9IHJvdW5kRGVjKHBvdyhiYXNlLCBleHApLCBleHBhKTtcblxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgbXVsdHMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGxldCBfaW5jciA9IG11bHRzW2ldICogbWFnO1xuXHRcdFx0bGV0IGRlYyA9IChfaW5jciA+PSAwICYmIGV4cCA+PSAwID8gMCA6IGV4cGEpICsgKGV4cCA+PSBtdWx0RGVjW2ldID8gMCA6IG11bHREZWNbaV0pO1xuXHRcdFx0bGV0IGluY3IgPSByb3VuZERlYyhfaW5jciwgZGVjKTtcblx0XHRcdGluY3JzLnB1c2goaW5jcik7XG5cdFx0XHRmaXhlZERlYy5zZXQoaW5jciwgZGVjKTtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gaW5jcnM7XG59XG5cbi8vZXhwb3J0IGNvbnN0IGFzc2lnbiA9IE9iamVjdC5hc3NpZ247XG5cbmNvbnN0IEVNUFRZX09CSiA9IHt9O1xuY29uc3QgRU1QVFlfQVJSID0gW107XG5cbmNvbnN0IG51bGxOdWxsVHVwbGUgPSBbbnVsbCwgbnVsbF07XG5cbmNvbnN0IGlzQXJyID0gQXJyYXkuaXNBcnJheTtcblxuZnVuY3Rpb24gaXNTdHIodikge1xuXHRyZXR1cm4gdHlwZW9mIHYgPT0gJ3N0cmluZyc7XG59XG5cbmZ1bmN0aW9uIGlzT2JqKHYpIHtcblx0bGV0IGlzID0gZmFsc2U7XG5cblx0aWYgKHYgIT0gbnVsbCkge1xuXHRcdGxldCBjID0gdi5jb25zdHJ1Y3Rvcjtcblx0XHRpcyA9IGMgPT0gbnVsbCB8fCBjID09IE9iamVjdDtcblx0fVxuXG5cdHJldHVybiBpcztcbn1cblxuZnVuY3Rpb24gZmFzdElzT2JqKHYpIHtcblx0cmV0dXJuIHYgIT0gbnVsbCAmJiB0eXBlb2YgdiA9PSAnb2JqZWN0Jztcbn1cblxuY29uc3QgVHlwZWRBcnJheSA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihVaW50OEFycmF5KTtcblxuZnVuY3Rpb24gY29weShvLCBfaXNPYmogPSBpc09iaikge1xuXHRsZXQgb3V0O1xuXG5cdGlmIChpc0FycihvKSkge1xuXHRcdGxldCB2YWwgPSBvLmZpbmQodiA9PiB2ICE9IG51bGwpO1xuXG5cdFx0aWYgKGlzQXJyKHZhbCkgfHwgX2lzT2JqKHZhbCkpIHtcblx0XHRcdG91dCA9IEFycmF5KG8ubGVuZ3RoKTtcblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgby5sZW5ndGg7IGkrKylcblx0XHRcdFx0b3V0W2ldID0gY29weShvW2ldLCBfaXNPYmopO1xuXHRcdH1cblx0XHRlbHNlXG5cdFx0XHRvdXQgPSBvLnNsaWNlKCk7XG5cdH1cblx0ZWxzZSBpZiAobyBpbnN0YW5jZW9mIFR5cGVkQXJyYXkpIC8vIGFsc28gKEFycmF5QnVmZmVyLmlzVmlldyhvKSAmJiAhKG8gaW5zdGFuY2VvZiBEYXRhVmlldykpXG5cdFx0b3V0ID0gby5zbGljZSgpO1xuXHRlbHNlIGlmIChfaXNPYmoobykpIHtcblx0XHRvdXQgPSB7fTtcblx0XHRmb3IgKGxldCBrIGluIG8pXG5cdFx0XHRvdXRba10gPSBjb3B5KG9ba10sIF9pc09iaik7XG5cdH1cblx0ZWxzZVxuXHRcdG91dCA9IG87XG5cblx0cmV0dXJuIG91dDtcbn1cblxuZnVuY3Rpb24gYXNzaWduKHRhcmcpIHtcblx0bGV0IGFyZ3MgPSBhcmd1bWVudHM7XG5cblx0Zm9yIChsZXQgaSA9IDE7IGkgPCBhcmdzLmxlbmd0aDsgaSsrKSB7XG5cdFx0bGV0IHNyYyA9IGFyZ3NbaV07XG5cblx0XHRmb3IgKGxldCBrZXkgaW4gc3JjKSB7XG5cdFx0XHRpZiAoaXNPYmoodGFyZ1trZXldKSlcblx0XHRcdFx0YXNzaWduKHRhcmdba2V5XSwgY29weShzcmNba2V5XSkpO1xuXHRcdFx0ZWxzZVxuXHRcdFx0XHR0YXJnW2tleV0gPSBjb3B5KHNyY1trZXldKTtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gdGFyZztcbn1cblxuLy8gbnVsbE1vZGVzXG5jb25zdCBOVUxMX1JFTU9WRSA9IDA7ICAvLyBudWxscyBhcmUgY29udmVydGVkIHRvIHVuZGVmaW5lZCAoZS5nLiBmb3Igc3BhbkdhcHM6IHRydWUpXG5jb25zdCBOVUxMX1JFVEFJTiA9IDE7ICAvLyBudWxscyBhcmUgcmV0YWluZWQsIHdpdGggYWxpZ25tZW50IGFydGlmYWN0cyBzZXQgdG8gdW5kZWZpbmVkIChkZWZhdWx0KVxuY29uc3QgTlVMTF9FWFBBTkQgPSAyOyAgLy8gbnVsbHMgYXJlIGV4cGFuZGVkIHRvIGluY2x1ZGUgYW55IGFkamFjZW50IGFsaWdubWVudCBhcnRpZmFjdHNcblxuLy8gc2V0cyB1bmRlZmluZWQgdmFsdWVzIHRvIG51bGxzIHdoZW4gYWRqYWNlbnQgdG8gZXhpc3RpbmcgbnVsbHMgKG1pbmVzd2VlcGVyKVxuZnVuY3Rpb24gbnVsbEV4cGFuZCh5VmFscywgbnVsbElkeHMsIGFsaWduZWRMZW4pIHtcblx0Zm9yIChsZXQgaSA9IDAsIHhpLCBsYXN0TnVsbElkeCA9IC0xOyBpIDwgbnVsbElkeHMubGVuZ3RoOyBpKyspIHtcblx0XHRsZXQgbnVsbElkeCA9IG51bGxJZHhzW2ldO1xuXG5cdFx0aWYgKG51bGxJZHggPiBsYXN0TnVsbElkeCkge1xuXHRcdFx0eGkgPSBudWxsSWR4IC0gMTtcblx0XHRcdHdoaWxlICh4aSA+PSAwICYmIHlWYWxzW3hpXSA9PSBudWxsKVxuXHRcdFx0XHR5VmFsc1t4aS0tXSA9IG51bGw7XG5cblx0XHRcdHhpID0gbnVsbElkeCArIDE7XG5cdFx0XHR3aGlsZSAoeGkgPCBhbGlnbmVkTGVuICYmIHlWYWxzW3hpXSA9PSBudWxsKVxuXHRcdFx0XHR5VmFsc1tsYXN0TnVsbElkeCA9IHhpKytdID0gbnVsbDtcblx0XHR9XG5cdH1cbn1cblxuLy8gbnVsbE1vZGVzIGlzIGEgdGFibGVzLW1hdGNoZWQgYXJyYXkgaW5kaWNhdGluZyBob3cgdG8gdHJlYXQgbnVsbHMgaW4gZWFjaCBzZXJpZXNcbi8vIG91dHB1dCBpcyBzb3J0ZWQgQVNDIG9uIHRoZSBqb2luZWQgZmllbGQgKHRhYmxlWzBdKSBhbmQgZHVwbGljYXRlIGpvaW4gdmFsdWVzIGFyZSBjb2xsYXBzZWRcbmZ1bmN0aW9uIGpvaW4odGFibGVzLCBudWxsTW9kZXMpIHtcblx0bGV0IHhWYWxzID0gbmV3IFNldCgpO1xuXG5cdGZvciAobGV0IHRpID0gMDsgdGkgPCB0YWJsZXMubGVuZ3RoOyB0aSsrKSB7XG5cdFx0bGV0IHQgPSB0YWJsZXNbdGldO1xuXHRcdGxldCB4cyA9IHRbMF07XG5cdFx0bGV0IGxlbiA9IHhzLmxlbmd0aDtcblxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspXG5cdFx0XHR4VmFscy5hZGQoeHNbaV0pO1xuXHR9XG5cblx0bGV0IGRhdGEgPSBbQXJyYXkuZnJvbSh4VmFscykuc29ydCgoYSwgYikgPT4gYSAtIGIpXTtcblxuXHRsZXQgYWxpZ25lZExlbiA9IGRhdGFbMF0ubGVuZ3RoO1xuXG5cdGxldCB4SWR4cyA9IG5ldyBNYXAoKTtcblxuXHRmb3IgKGxldCBpID0gMDsgaSA8IGFsaWduZWRMZW47IGkrKylcblx0XHR4SWR4cy5zZXQoZGF0YVswXVtpXSwgaSk7XG5cblx0Zm9yIChsZXQgdGkgPSAwOyB0aSA8IHRhYmxlcy5sZW5ndGg7IHRpKyspIHtcblx0XHRsZXQgdCA9IHRhYmxlc1t0aV07XG5cdFx0bGV0IHhzID0gdFswXTtcblxuXHRcdGZvciAobGV0IHNpID0gMTsgc2kgPCB0Lmxlbmd0aDsgc2krKykge1xuXHRcdFx0bGV0IHlzID0gdFtzaV07XG5cblx0XHRcdGxldCB5VmFscyA9IEFycmF5KGFsaWduZWRMZW4pLmZpbGwodW5kZWZpbmVkKTtcblxuXHRcdFx0bGV0IG51bGxNb2RlID0gbnVsbE1vZGVzID8gbnVsbE1vZGVzW3RpXVtzaV0gOiBOVUxMX1JFVEFJTjtcblxuXHRcdFx0bGV0IG51bGxJZHhzID0gW107XG5cblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgeXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdFx0bGV0IHlWYWwgPSB5c1tpXTtcblx0XHRcdFx0bGV0IGFsaWduZWRJZHggPSB4SWR4cy5nZXQoeHNbaV0pO1xuXG5cdFx0XHRcdGlmICh5VmFsID09PSBudWxsKSB7XG5cdFx0XHRcdFx0aWYgKG51bGxNb2RlICE9IE5VTExfUkVNT1ZFKSB7XG5cdFx0XHRcdFx0XHR5VmFsc1thbGlnbmVkSWR4XSA9IHlWYWw7XG5cblx0XHRcdFx0XHRcdGlmIChudWxsTW9kZSA9PSBOVUxMX0VYUEFORClcblx0XHRcdFx0XHRcdFx0bnVsbElkeHMucHVzaChhbGlnbmVkSWR4KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdHlWYWxzW2FsaWduZWRJZHhdID0geVZhbDtcblx0XHRcdH1cblxuXHRcdFx0bnVsbEV4cGFuZCh5VmFscywgbnVsbElkeHMsIGFsaWduZWRMZW4pO1xuXG5cdFx0XHRkYXRhLnB1c2goeVZhbHMpO1xuXHRcdH1cblx0fVxuXG5cdHJldHVybiBkYXRhO1xufVxuXG5jb25zdCBtaWNyb1Rhc2sgPSB0eXBlb2YgcXVldWVNaWNyb3Rhc2sgPT0gXCJ1bmRlZmluZWRcIiA/IGZuID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oZm4pIDogcXVldWVNaWNyb3Rhc2s7XG5cbmNvbnN0IG1vbnRocyA9IFtcblx0XCJKYW51YXJ5XCIsXG5cdFwiRmVicnVhcnlcIixcblx0XCJNYXJjaFwiLFxuXHRcIkFwcmlsXCIsXG5cdFwiTWF5XCIsXG5cdFwiSnVuZVwiLFxuXHRcIkp1bHlcIixcblx0XCJBdWd1c3RcIixcblx0XCJTZXB0ZW1iZXJcIixcblx0XCJPY3RvYmVyXCIsXG5cdFwiTm92ZW1iZXJcIixcblx0XCJEZWNlbWJlclwiLFxuXTtcblxuY29uc3QgZGF5cyA9IFtcblx0XCJTdW5kYXlcIixcblx0XCJNb25kYXlcIixcblx0XCJUdWVzZGF5XCIsXG5cdFwiV2VkbmVzZGF5XCIsXG5cdFwiVGh1cnNkYXlcIixcblx0XCJGcmlkYXlcIixcblx0XCJTYXR1cmRheVwiLFxuXTtcblxuZnVuY3Rpb24gc2xpY2UzKHN0cikge1xuXHRyZXR1cm4gc3RyLnNsaWNlKDAsIDMpO1xufVxuXG5jb25zdCBkYXlzMyA9IGRheXMubWFwKHNsaWNlMyk7XG5cbmNvbnN0IG1vbnRoczMgPSBtb250aHMubWFwKHNsaWNlMyk7XG5cbmNvbnN0IGVuZ05hbWVzID0ge1xuXHRNTU1NOiBtb250aHMsXG5cdE1NTTogIG1vbnRoczMsXG5cdFdXV1c6IGRheXMsXG5cdFdXVzogIGRheXMzLFxufTtcblxuZnVuY3Rpb24gemVyb1BhZDIoaW50KSB7XG5cdHJldHVybiAoaW50IDwgMTAgPyAnMCcgOiAnJykgKyBpbnQ7XG59XG5cbmZ1bmN0aW9uIHplcm9QYWQzKGludCkge1xuXHRyZXR1cm4gKGludCA8IDEwID8gJzAwJyA6IGludCA8IDEwMCA/ICcwJyA6ICcnKSArIGludDtcbn1cblxuLypcbmZ1bmN0aW9uIHN1ZmZpeChpbnQpIHtcblx0bGV0IG1vZDEwID0gaW50ICUgMTA7XG5cblx0cmV0dXJuIGludCArIChcblx0XHRtb2QxMCA9PSAxICYmIGludCAhPSAxMSA/IFwic3RcIiA6XG5cdFx0bW9kMTAgPT0gMiAmJiBpbnQgIT0gMTIgPyBcIm5kXCIgOlxuXHRcdG1vZDEwID09IDMgJiYgaW50ICE9IDEzID8gXCJyZFwiIDogXCJ0aFwiXG5cdCk7XG59XG4qL1xuXG5jb25zdCBzdWJzID0ge1xuXHQvLyAyMDE5XG5cdFlZWVk6XHRkID0+IGQuZ2V0RnVsbFllYXIoKSxcblx0Ly8gMTlcblx0WVk6XHRcdGQgPT4gKGQuZ2V0RnVsbFllYXIoKSsnJykuc2xpY2UoMiksXG5cdC8vIEp1bHlcblx0TU1NTTpcdChkLCBuYW1lcykgPT4gbmFtZXMuTU1NTVtkLmdldE1vbnRoKCldLFxuXHQvLyBKdWxcblx0TU1NOlx0KGQsIG5hbWVzKSA9PiBuYW1lcy5NTU1bZC5nZXRNb250aCgpXSxcblx0Ly8gMDdcblx0TU06XHRcdGQgPT4gemVyb1BhZDIoZC5nZXRNb250aCgpKzEpLFxuXHQvLyA3XG5cdE06XHRcdGQgPT4gZC5nZXRNb250aCgpKzEsXG5cdC8vIDA5XG5cdEREOlx0XHRkID0+IHplcm9QYWQyKGQuZ2V0RGF0ZSgpKSxcblx0Ly8gOVxuXHREOlx0XHRkID0+IGQuZ2V0RGF0ZSgpLFxuXHQvLyBNb25kYXlcblx0V1dXVzpcdChkLCBuYW1lcykgPT4gbmFtZXMuV1dXV1tkLmdldERheSgpXSxcblx0Ly8gTW9uXG5cdFdXVzpcdChkLCBuYW1lcykgPT4gbmFtZXMuV1dXW2QuZ2V0RGF5KCldLFxuXHQvLyAwM1xuXHRISDpcdFx0ZCA9PiB6ZXJvUGFkMihkLmdldEhvdXJzKCkpLFxuXHQvLyAzXG5cdEg6XHRcdGQgPT4gZC5nZXRIb3VycygpLFxuXHQvLyA5ICgxMmhyLCB1bnBhZGRlZClcblx0aDpcdFx0ZCA9PiB7bGV0IGggPSBkLmdldEhvdXJzKCk7IHJldHVybiBoID09IDAgPyAxMiA6IGggPiAxMiA/IGggLSAxMiA6IGg7fSxcblx0Ly8gQU1cblx0QUE6XHRcdGQgPT4gZC5nZXRIb3VycygpID49IDEyID8gJ1BNJyA6ICdBTScsXG5cdC8vIGFtXG5cdGFhOlx0XHRkID0+IGQuZ2V0SG91cnMoKSA+PSAxMiA/ICdwbScgOiAnYW0nLFxuXHQvLyBhXG5cdGE6XHRcdGQgPT4gZC5nZXRIb3VycygpID49IDEyID8gJ3AnIDogJ2EnLFxuXHQvLyAwOVxuXHRtbTpcdFx0ZCA9PiB6ZXJvUGFkMihkLmdldE1pbnV0ZXMoKSksXG5cdC8vIDlcblx0bTpcdFx0ZCA9PiBkLmdldE1pbnV0ZXMoKSxcblx0Ly8gMDlcblx0c3M6XHRcdGQgPT4gemVyb1BhZDIoZC5nZXRTZWNvbmRzKCkpLFxuXHQvLyA5XG5cdHM6XHRcdGQgPT4gZC5nZXRTZWNvbmRzKCksXG5cdC8vIDM3NFxuXHRmZmY6XHRkID0+IHplcm9QYWQzKGQuZ2V0TWlsbGlzZWNvbmRzKCkpLFxufTtcblxuZnVuY3Rpb24gZm10RGF0ZSh0cGwsIG5hbWVzKSB7XG5cdG5hbWVzID0gbmFtZXMgfHwgZW5nTmFtZXM7XG5cdGxldCBwYXJ0cyA9IFtdO1xuXG5cdGxldCBSID0gL1xceyhbYS16XSspXFx9fFtee10rL2dpLCBtO1xuXG5cdHdoaWxlIChtID0gUi5leGVjKHRwbCkpXG5cdFx0cGFydHMucHVzaChtWzBdWzBdID09ICd7JyA/IHN1YnNbbVsxXV0gOiBtWzBdKTtcblxuXHRyZXR1cm4gZCA9PiB7XG5cdFx0bGV0IG91dCA9ICcnO1xuXG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBwYXJ0cy5sZW5ndGg7IGkrKylcblx0XHRcdG91dCArPSB0eXBlb2YgcGFydHNbaV0gPT0gXCJzdHJpbmdcIiA/IHBhcnRzW2ldIDogcGFydHNbaV0oZCwgbmFtZXMpO1xuXG5cdFx0cmV0dXJuIG91dDtcblx0fVxufVxuXG5jb25zdCBsb2NhbFR6ID0gbmV3IEludGwuRGF0ZVRpbWVGb3JtYXQoKS5yZXNvbHZlZE9wdGlvbnMoKS50aW1lWm9uZTtcblxuLy8gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTUxNDE3NjIvaG93LXRvLWluaXRpYWxpemUtYS1qYXZhc2NyaXB0LWRhdGUtdG8tYS1wYXJ0aWN1bGFyLXRpbWUtem9uZS81MzY1MjEzMSM1MzY1MjEzMVxuZnVuY3Rpb24gdHpEYXRlKGRhdGUsIHR6KSB7XG5cdGxldCBkYXRlMjtcblxuXHQvLyBwZXJmIG9wdGltaXphdGlvblxuXHRpZiAodHogPT0gJ1VUQycgfHwgdHogPT0gJ0V0Yy9VVEMnKVxuXHRcdGRhdGUyID0gbmV3IERhdGUoK2RhdGUgKyBkYXRlLmdldFRpbWV6b25lT2Zmc2V0KCkgKiA2ZTQpO1xuXHRlbHNlIGlmICh0eiA9PSBsb2NhbFR6KVxuXHRcdGRhdGUyID0gZGF0ZTtcblx0ZWxzZSB7XG5cdFx0ZGF0ZTIgPSBuZXcgRGF0ZShkYXRlLnRvTG9jYWxlU3RyaW5nKCdlbi1VUycsIHt0aW1lWm9uZTogdHp9KSk7XG5cdFx0ZGF0ZTIuc2V0TWlsbGlzZWNvbmRzKGRhdGUuZ2V0TWlsbGlzZWNvbmRzKCkpO1xuXHR9XG5cblx0cmV0dXJuIGRhdGUyO1xufVxuXG4vL2V4cG9ydCBjb25zdCBzZXJpZXMgPSBbXTtcblxuLy8gZGVmYXVsdCBmb3JtYXR0ZXJzOlxuXG5jb25zdCBvbmx5V2hvbGUgPSB2ID0+IHYgJSAxID09IDA7XG5cbmNvbnN0IGFsbE11bHRzID0gWzEsMiwyLjUsNV07XG5cbi8vIC4uLjAuMDEsIDAuMDIsIDAuMDI1LCAwLjA1LCAwLjEsIDAuMiwgMC4yNSwgMC41XG5jb25zdCBkZWNJbmNycyA9IGdlbkluY3JzKDEwLCAtMTYsIDAsIGFsbE11bHRzKTtcblxuLy8gMSwgMiwgMi41LCA1LCAxMCwgMjAsIDI1LCA1MC4uLlxuY29uc3Qgb25lSW5jcnMgPSBnZW5JbmNycygxMCwgMCwgMTYsIGFsbE11bHRzKTtcblxuLy8gMSwgMiwgICAgICA1LCAxMCwgMjAsIDI1LCA1MC4uLlxuY29uc3Qgd2hvbGVJbmNycyA9IG9uZUluY3JzLmZpbHRlcihvbmx5V2hvbGUpO1xuXG5jb25zdCBudW1JbmNycyA9IGRlY0luY3JzLmNvbmNhdChvbmVJbmNycyk7XG5cbmNvbnN0IE5MID0gXCJcXG5cIjtcblxuY29uc3QgeXl5eSAgICA9IFwie1lZWVl9XCI7XG5jb25zdCBOTHl5eXkgID0gTkwgKyB5eXl5O1xuY29uc3QgbWQgICAgICA9IFwie019L3tEfVwiO1xuY29uc3QgTkxtZCAgICA9IE5MICsgbWQ7XG5jb25zdCBOTG1keXkgID0gTkxtZCArIFwiL3tZWX1cIjtcblxuY29uc3QgYWEgICAgICA9IFwie2FhfVwiO1xuY29uc3QgaG1tICAgICA9IFwie2h9OnttbX1cIjtcbmNvbnN0IGhtbWFhICAgPSBobW0gKyBhYTtcbmNvbnN0IE5MaG1tYWEgPSBOTCArIGhtbWFhO1xuY29uc3Qgc3MgICAgICA9IFwiOntzc31cIjtcblxuY29uc3QgXyA9IG51bGw7XG5cbmZ1bmN0aW9uIGdlblRpbWVTdHVmZnMobXMpIHtcblx0bGV0XHRzICA9IG1zICogMWUzLFxuXHRcdG0gID0gcyAgKiA2MCxcblx0XHRoICA9IG0gICogNjAsXG5cdFx0ZCAgPSBoICAqIDI0LFxuXHRcdG1vID0gZCAgKiAzMCxcblx0XHR5ICA9IGQgICogMzY1O1xuXG5cdC8vIG1pbiBvZiAxZS0zIHByZXZlbnRzIHNldHRpbmcgYSB0ZW1wb3JhbCB4IHRpY2tzIHRvbyBzbWFsbCBzaW5jZSBEYXRlIG9iamVjdHMgY2Fubm90IGFkdmFuY2UgdGlja3Mgc21hbGxlciB0aGFuIDFtc1xuXHRsZXQgc3ViU2VjSW5jcnMgPSBtcyA9PSAxID8gZ2VuSW5jcnMoMTAsIDAsIDMsIGFsbE11bHRzKS5maWx0ZXIob25seVdob2xlKSA6IGdlbkluY3JzKDEwLCAtMywgMCwgYWxsTXVsdHMpO1xuXG5cdGxldCB0aW1lSW5jcnMgPSBzdWJTZWNJbmNycy5jb25jYXQoW1xuXHRcdC8vIG1pbnV0ZSBkaXZpc29ycyAoIyBvZiBzZWNzKVxuXHRcdHMsXG5cdFx0cyAqIDUsXG5cdFx0cyAqIDEwLFxuXHRcdHMgKiAxNSxcblx0XHRzICogMzAsXG5cdFx0Ly8gaG91ciBkaXZpc29ycyAoIyBvZiBtaW5zKVxuXHRcdG0sXG5cdFx0bSAqIDUsXG5cdFx0bSAqIDEwLFxuXHRcdG0gKiAxNSxcblx0XHRtICogMzAsXG5cdFx0Ly8gZGF5IGRpdmlzb3JzICgjIG9mIGhycylcblx0XHRoLFxuXHRcdGggKiAyLFxuXHRcdGggKiAzLFxuXHRcdGggKiA0LFxuXHRcdGggKiA2LFxuXHRcdGggKiA4LFxuXHRcdGggKiAxMixcblx0XHQvLyBtb250aCBkaXZpc29ycyBUT0RPOiBuZWVkIG1vcmU/XG5cdFx0ZCxcblx0XHRkICogMixcblx0XHRkICogMyxcblx0XHRkICogNCxcblx0XHRkICogNSxcblx0XHRkICogNixcblx0XHRkICogNyxcblx0XHRkICogOCxcblx0XHRkICogOSxcblx0XHRkICogMTAsXG5cdFx0ZCAqIDE1LFxuXHRcdC8vIHllYXIgZGl2aXNvcnMgKCMgbW9udGhzLCBhcHByb3gpXG5cdFx0bW8sXG5cdFx0bW8gKiAyLFxuXHRcdG1vICogMyxcblx0XHRtbyAqIDQsXG5cdFx0bW8gKiA2LFxuXHRcdC8vIGNlbnR1cnkgZGl2aXNvcnNcblx0XHR5LFxuXHRcdHkgKiAyLFxuXHRcdHkgKiA1LFxuXHRcdHkgKiAxMCxcblx0XHR5ICogMjUsXG5cdFx0eSAqIDUwLFxuXHRcdHkgKiAxMDAsXG5cdF0pO1xuXG5cdC8vIFswXTogICBtaW5pbXVtIG51bSBzZWNzIGluIHRoZSB0aWNrIGluY3Jcblx0Ly8gWzFdOiAgIGRlZmF1bHQgdGljayBmb3JtYXRcblx0Ly8gWzItN106IHJvbGxvdmVyIHRpY2sgZm9ybWF0c1xuXHQvLyBbOF06ICAgbW9kZTogMDogcmVwbGFjZSBbMV0gLT4gWzItN10sIDE6IGNvbmNhdCBbMV0gKyBbMi03XVxuXHRjb25zdCBfdGltZUF4aXNTdGFtcHMgPSBbXG5cdC8vICAgdGljayBpbmNyICAgIGRlZmF1bHQgICAgICAgICAgeWVhciAgICAgICAgICAgICAgICAgICAgbW9udGggICBkYXkgICAgICAgICAgICAgICAgICAgaG91ciAgICBtaW4gICAgICAgc2VjICAgbW9kZVxuXHRcdFt5LCAgICAgICAgICAgeXl5eSwgICAgICAgICAgICBfLCAgICAgICAgICAgICAgICAgICAgICBfLCAgICAgIF8sICAgICAgICAgICAgICAgICAgICBfLCAgICAgIF8sICAgICAgICBfLCAgICAgICAxXSxcblx0XHRbZCAqIDI4LCAgICAgIFwie01NTX1cIiwgICAgICAgICBOTHl5eXksICAgICAgICAgICAgICAgICBfLCAgICAgIF8sICAgICAgICAgICAgICAgICAgICBfLCAgICAgIF8sICAgICAgICBfLCAgICAgICAxXSxcblx0XHRbZCwgICAgICAgICAgIG1kLCAgICAgICAgICAgICAgTkx5eXl5LCAgICAgICAgICAgICAgICAgXywgICAgICBfLCAgICAgICAgICAgICAgICAgICAgXywgICAgICBfLCAgICAgICAgXywgICAgICAgMV0sXG5cdFx0W2gsICAgICAgICAgICBcIntofVwiICsgYWEsICAgICAgTkxtZHl5LCAgICAgICAgICAgICAgICAgXywgICAgICBOTG1kLCAgICAgICAgICAgICAgICAgXywgICAgICBfLCAgICAgICAgXywgICAgICAgMV0sXG5cdFx0W20sICAgICAgICAgICBobW1hYSwgICAgICAgICAgIE5MbWR5eSwgICAgICAgICAgICAgICAgIF8sICAgICAgTkxtZCwgICAgICAgICAgICAgICAgIF8sICAgICAgXywgICAgICAgIF8sICAgICAgIDFdLFxuXHRcdFtzLCAgICAgICAgICAgc3MsICAgICAgICAgICAgICBOTG1keXkgKyBcIiBcIiArIGhtbWFhLCAgIF8sICAgICAgTkxtZCArIFwiIFwiICsgaG1tYWEsICAgXywgICAgICBOTGhtbWFhLCAgXywgICAgICAgMV0sXG5cdFx0W21zLCAgICAgICAgICBzcyArIFwiLntmZmZ9XCIsICAgTkxtZHl5ICsgXCIgXCIgKyBobW1hYSwgICBfLCAgICAgIE5MbWQgKyBcIiBcIiArIGhtbWFhLCAgIF8sICAgICAgTkxobW1hYSwgIF8sICAgICAgIDFdLFxuXHRdO1xuXG5cdC8vIHRoZSBlbnN1cmVzIHRoYXQgYXhpcyB0aWNrcywgdmFsdWVzICYgZ3JpZCBhcmUgYWxpZ25lZCB0byBsb2dpY2FsIHRlbXBvcmFsIGJyZWFrcG9pbnRzIGFuZCBub3QgYW4gYXJiaXRyYXJ5IHRpbWVzdGFtcFxuXHQvLyBodHRwczovL3d3dy50aW1lYW5kZGF0ZS5jb20vdGltZS9kc3QvXG5cdC8vIGh0dHBzOi8vd3d3LnRpbWVhbmRkYXRlLmNvbS90aW1lL2RzdC8yMDE5Lmh0bWxcblx0Ly8gaHR0cHM6Ly93d3cuZXBvY2hjb252ZXJ0ZXIuY29tL3RpbWV6b25lc1xuXHRmdW5jdGlvbiB0aW1lQXhpc1NwbGl0cyh0ekRhdGUpIHtcblx0XHRyZXR1cm4gKHNlbGYsIGF4aXNJZHgsIHNjYWxlTWluLCBzY2FsZU1heCwgZm91bmRJbmNyLCBmb3VuZFNwYWNlKSA9PiB7XG5cdFx0XHRsZXQgc3BsaXRzID0gW107XG5cdFx0XHRsZXQgaXNZciA9IGZvdW5kSW5jciA+PSB5O1xuXHRcdFx0bGV0IGlzTW8gPSBmb3VuZEluY3IgPj0gbW8gJiYgZm91bmRJbmNyIDwgeTtcblxuXHRcdFx0Ly8gZ2V0IHRoZSB0aW1lem9uZS1hZGp1c3RlZCBkYXRlXG5cdFx0XHRsZXQgbWluRGF0ZSA9IHR6RGF0ZShzY2FsZU1pbik7XG5cdFx0XHRsZXQgbWluRGF0ZVRzID0gcm91bmREZWMobWluRGF0ZSAqIG1zLCAzKTtcblxuXHRcdFx0Ly8gZ2V0IHRzIG9mIDEyYW0gKHRoaXMgbGFuZHMgdXMgYXQgb3IgYmVmb3JlIHRoZSBvcmlnaW5hbCBzY2FsZU1pbilcblx0XHRcdGxldCBtaW5NaW4gPSBta0RhdGUobWluRGF0ZS5nZXRGdWxsWWVhcigpLCBpc1lyID8gMCA6IG1pbkRhdGUuZ2V0TW9udGgoKSwgaXNNbyB8fCBpc1lyID8gMSA6IG1pbkRhdGUuZ2V0RGF0ZSgpKTtcblx0XHRcdGxldCBtaW5NaW5UcyA9IHJvdW5kRGVjKG1pbk1pbiAqIG1zLCAzKTtcblxuXHRcdFx0aWYgKGlzTW8gfHwgaXNZcikge1xuXHRcdFx0XHRsZXQgbW9JbmNyID0gaXNNbyA/IGZvdW5kSW5jciAvIG1vIDogMDtcblx0XHRcdFx0bGV0IHlySW5jciA9IGlzWXIgPyBmb3VuZEluY3IgLyB5ICA6IDA7XG5cdFx0XHQvL1x0bGV0IHR6T2Zmc2V0ID0gc2NhbGVNaW4gLSBtaW5EYXRlVHM7XHRcdC8vIG5lZWRlZD9cblx0XHRcdFx0bGV0IHNwbGl0ID0gbWluRGF0ZVRzID09IG1pbk1pblRzID8gbWluRGF0ZVRzIDogcm91bmREZWMobWtEYXRlKG1pbk1pbi5nZXRGdWxsWWVhcigpICsgeXJJbmNyLCBtaW5NaW4uZ2V0TW9udGgoKSArIG1vSW5jciwgMSkgKiBtcywgMyk7XG5cdFx0XHRcdGxldCBzcGxpdERhdGUgPSBuZXcgRGF0ZShyb3VuZChzcGxpdCAvIG1zKSk7XG5cdFx0XHRcdGxldCBiYXNlWWVhciA9IHNwbGl0RGF0ZS5nZXRGdWxsWWVhcigpO1xuXHRcdFx0XHRsZXQgYmFzZU1vbnRoID0gc3BsaXREYXRlLmdldE1vbnRoKCk7XG5cblx0XHRcdFx0Zm9yIChsZXQgaSA9IDA7IHNwbGl0IDw9IHNjYWxlTWF4OyBpKyspIHtcblx0XHRcdFx0XHRsZXQgbmV4dCA9IG1rRGF0ZShiYXNlWWVhciArIHlySW5jciAqIGksIGJhc2VNb250aCArIG1vSW5jciAqIGksIDEpO1xuXHRcdFx0XHRcdGxldCBvZmZzID0gbmV4dCAtIHR6RGF0ZShyb3VuZERlYyhuZXh0ICogbXMsIDMpKTtcblxuXHRcdFx0XHRcdHNwbGl0ID0gcm91bmREZWMoKCtuZXh0ICsgb2ZmcykgKiBtcywgMyk7XG5cblx0XHRcdFx0XHRpZiAoc3BsaXQgPD0gc2NhbGVNYXgpXG5cdFx0XHRcdFx0XHRzcGxpdHMucHVzaChzcGxpdCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHRsZXQgaW5jcjAgPSBmb3VuZEluY3IgPj0gZCA/IGQgOiBmb3VuZEluY3I7XG5cdFx0XHRcdGxldCB0ek9mZnNldCA9IGZsb29yKHNjYWxlTWluKSAtIGZsb29yKG1pbkRhdGVUcyk7XG5cdFx0XHRcdGxldCBzcGxpdCA9IG1pbk1pblRzICsgdHpPZmZzZXQgKyBpbmNyUm91bmRVcChtaW5EYXRlVHMgLSBtaW5NaW5UcywgaW5jcjApO1xuXHRcdFx0XHRzcGxpdHMucHVzaChzcGxpdCk7XG5cblx0XHRcdFx0bGV0IGRhdGUwID0gdHpEYXRlKHNwbGl0KTtcblxuXHRcdFx0XHRsZXQgcHJldkhvdXIgPSBkYXRlMC5nZXRIb3VycygpICsgKGRhdGUwLmdldE1pbnV0ZXMoKSAvIG0pICsgKGRhdGUwLmdldFNlY29uZHMoKSAvIGgpO1xuXHRcdFx0XHRsZXQgaW5jckhvdXJzID0gZm91bmRJbmNyIC8gaDtcblxuXHRcdFx0XHRsZXQgbWluU3BhY2UgPSBzZWxmLmF4ZXNbYXhpc0lkeF0uX3NwYWNlO1xuXHRcdFx0XHRsZXQgcGN0U3BhY2UgPSBmb3VuZFNwYWNlIC8gbWluU3BhY2U7XG5cblx0XHRcdFx0d2hpbGUgKDEpIHtcblx0XHRcdFx0XHRzcGxpdCA9IHJvdW5kRGVjKHNwbGl0ICsgZm91bmRJbmNyLCBtcyA9PSAxID8gMCA6IDMpO1xuXG5cdFx0XHRcdFx0aWYgKHNwbGl0ID4gc2NhbGVNYXgpXG5cdFx0XHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRcdGlmIChpbmNySG91cnMgPiAxKSB7XG5cdFx0XHRcdFx0XHRsZXQgZXhwZWN0ZWRIb3VyID0gZmxvb3Iocm91bmREZWMocHJldkhvdXIgKyBpbmNySG91cnMsIDYpKSAlIDI0O1xuXHRcdFx0XHRcdFx0bGV0IHNwbGl0RGF0ZSA9IHR6RGF0ZShzcGxpdCk7XG5cdFx0XHRcdFx0XHRsZXQgYWN0dWFsSG91ciA9IHNwbGl0RGF0ZS5nZXRIb3VycygpO1xuXG5cdFx0XHRcdFx0XHRsZXQgZHN0U2hpZnQgPSBhY3R1YWxIb3VyIC0gZXhwZWN0ZWRIb3VyO1xuXG5cdFx0XHRcdFx0XHRpZiAoZHN0U2hpZnQgPiAxKVxuXHRcdFx0XHRcdFx0XHRkc3RTaGlmdCA9IC0xO1xuXG5cdFx0XHRcdFx0XHRzcGxpdCAtPSBkc3RTaGlmdCAqIGg7XG5cblx0XHRcdFx0XHRcdHByZXZIb3VyID0gKHByZXZIb3VyICsgaW5jckhvdXJzKSAlIDI0O1xuXG5cdFx0XHRcdFx0XHQvLyBhZGQgYSB0aWNrIG9ubHkgaWYgaXQncyBmdXJ0aGVyIHRoYW4gNzAlIG9mIHRoZSBtaW4gYWxsb3dlZCBsYWJlbCBzcGFjaW5nXG5cdFx0XHRcdFx0XHRsZXQgcHJldlNwbGl0ID0gc3BsaXRzW3NwbGl0cy5sZW5ndGggLSAxXTtcblx0XHRcdFx0XHRcdGxldCBwY3RJbmNyID0gcm91bmREZWMoKHNwbGl0IC0gcHJldlNwbGl0KSAvIGZvdW5kSW5jciwgMyk7XG5cblx0XHRcdFx0XHRcdGlmIChwY3RJbmNyICogcGN0U3BhY2UgPj0gLjcpXG5cdFx0XHRcdFx0XHRcdHNwbGl0cy5wdXNoKHNwbGl0KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdFx0c3BsaXRzLnB1c2goc3BsaXQpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBzcGxpdHM7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIFtcblx0XHR0aW1lSW5jcnMsXG5cdFx0X3RpbWVBeGlzU3RhbXBzLFxuXHRcdHRpbWVBeGlzU3BsaXRzLFxuXHRdO1xufVxuXG5jb25zdCBbIHRpbWVJbmNyc01zLCBfdGltZUF4aXNTdGFtcHNNcywgdGltZUF4aXNTcGxpdHNNcyBdID0gZ2VuVGltZVN0dWZmcygxKTtcbmNvbnN0IFsgdGltZUluY3JzUywgIF90aW1lQXhpc1N0YW1wc1MsICB0aW1lQXhpc1NwbGl0c1MgIF0gPSBnZW5UaW1lU3R1ZmZzKDFlLTMpO1xuXG4vLyBiYXNlIDJcbmdlbkluY3JzKDIsIC01MywgNTMsIFsxXSk7XG5cbi8qXG5jb25zb2xlLmxvZyh7XG5cdGRlY0luY3JzLFxuXHRvbmVJbmNycyxcblx0d2hvbGVJbmNycyxcblx0bnVtSW5jcnMsXG5cdHRpbWVJbmNycyxcblx0Zml4ZWREZWMsXG59KTtcbiovXG5cbmZ1bmN0aW9uIHRpbWVBeGlzU3RhbXBzKHN0YW1wQ2ZnLCBmbXREYXRlKSB7XG5cdHJldHVybiBzdGFtcENmZy5tYXAocyA9PiBzLm1hcCgodiwgaSkgPT5cblx0XHRpID09IDAgfHwgaSA9PSA4IHx8IHYgPT0gbnVsbCA/IHYgOiBmbXREYXRlKGkgPT0gMSB8fCBzWzhdID09IDAgPyB2IDogc1sxXSArIHYpXG5cdCkpO1xufVxuXG4vLyBUT0RPOiB3aWxsIG5lZWQgdG8gYWNjZXB0IHNwYWNlc1tdIGFuZCBwdWxsIGluY3IgaW50byB0aGUgbG9vcCB3aGVuIGdyaWQgd2lsbCBiZSBub24tdW5pZm9ybSwgZWcgZm9yIGxvZyBzY2FsZXMuXG4vLyBjdXJyZW50bHkgd2UgaWdub3JlIHRoaXMgZm9yIG1vbnRocyBzaW5jZSB0aGV5J3JlICpuZWFybHkqIHVuaWZvcm0gYW5kIHRoZSBhZGRlZCBjb21wbGV4aXR5IGlzIG5vdCB3b3J0aCBpdFxuZnVuY3Rpb24gdGltZUF4aXNWYWxzKHR6RGF0ZSwgc3RhbXBzKSB7XG5cdHJldHVybiAoc2VsZiwgc3BsaXRzLCBheGlzSWR4LCBmb3VuZFNwYWNlLCBmb3VuZEluY3IpID0+IHtcblx0XHRsZXQgcyA9IHN0YW1wcy5maW5kKHMgPT4gZm91bmRJbmNyID49IHNbMF0pIHx8IHN0YW1wc1tzdGFtcHMubGVuZ3RoIC0gMV07XG5cblx0XHQvLyB0aGVzZSB0cmFjayBib3VuZGFyaWVzIHdoZW4gYSBmdWxsIGxhYmVsIGlzIG5lZWRlZCBhZ2FpblxuXHRcdGxldCBwcmV2WWVhcjtcblx0XHRsZXQgcHJldk1udGg7XG5cdFx0bGV0IHByZXZEYXRlO1xuXHRcdGxldCBwcmV2SG91cjtcblx0XHRsZXQgcHJldk1pbnM7XG5cdFx0bGV0IHByZXZTZWNzO1xuXG5cdFx0cmV0dXJuIHNwbGl0cy5tYXAoc3BsaXQgPT4ge1xuXHRcdFx0bGV0IGRhdGUgPSB0ekRhdGUoc3BsaXQpO1xuXG5cdFx0XHRsZXQgbmV3WWVhciA9IGRhdGUuZ2V0RnVsbFllYXIoKTtcblx0XHRcdGxldCBuZXdNbnRoID0gZGF0ZS5nZXRNb250aCgpO1xuXHRcdFx0bGV0IG5ld0RhdGUgPSBkYXRlLmdldERhdGUoKTtcblx0XHRcdGxldCBuZXdIb3VyID0gZGF0ZS5nZXRIb3VycygpO1xuXHRcdFx0bGV0IG5ld01pbnMgPSBkYXRlLmdldE1pbnV0ZXMoKTtcblx0XHRcdGxldCBuZXdTZWNzID0gZGF0ZS5nZXRTZWNvbmRzKCk7XG5cblx0XHRcdGxldCBzdGFtcCA9IChcblx0XHRcdFx0bmV3WWVhciAhPSBwcmV2WWVhciAmJiBzWzJdIHx8XG5cdFx0XHRcdG5ld01udGggIT0gcHJldk1udGggJiYgc1szXSB8fFxuXHRcdFx0XHRuZXdEYXRlICE9IHByZXZEYXRlICYmIHNbNF0gfHxcblx0XHRcdFx0bmV3SG91ciAhPSBwcmV2SG91ciAmJiBzWzVdIHx8XG5cdFx0XHRcdG5ld01pbnMgIT0gcHJldk1pbnMgJiYgc1s2XSB8fFxuXHRcdFx0XHRuZXdTZWNzICE9IHByZXZTZWNzICYmIHNbN10gfHxcblx0XHRcdFx0ICAgICAgICAgICAgICAgICAgICAgICBzWzFdXG5cdFx0XHQpO1xuXG5cdFx0XHRwcmV2WWVhciA9IG5ld1llYXI7XG5cdFx0XHRwcmV2TW50aCA9IG5ld01udGg7XG5cdFx0XHRwcmV2RGF0ZSA9IG5ld0RhdGU7XG5cdFx0XHRwcmV2SG91ciA9IG5ld0hvdXI7XG5cdFx0XHRwcmV2TWlucyA9IG5ld01pbnM7XG5cdFx0XHRwcmV2U2VjcyA9IG5ld1NlY3M7XG5cblx0XHRcdHJldHVybiBzdGFtcChkYXRlKTtcblx0XHR9KTtcblx0fVxufVxuXG4vLyBmb3Igd2hlbiBheGlzLnZhbHVlcyBpcyBkZWZpbmVkIGFzIGEgc3RhdGljIGZtdERhdGUgdGVtcGxhdGUgc3RyaW5nXG5mdW5jdGlvbiB0aW1lQXhpc1ZhbCh0ekRhdGUsIGRhdGVUcGwpIHtcblx0bGV0IHN0YW1wID0gZm10RGF0ZShkYXRlVHBsKTtcblx0cmV0dXJuIChzZWxmLCBzcGxpdHMsIGF4aXNJZHgsIGZvdW5kU3BhY2UsIGZvdW5kSW5jcikgPT4gc3BsaXRzLm1hcChzcGxpdCA9PiBzdGFtcCh0ekRhdGUoc3BsaXQpKSk7XG59XG5cbmZ1bmN0aW9uIG1rRGF0ZSh5LCBtLCBkKSB7XG5cdHJldHVybiBuZXcgRGF0ZSh5LCBtLCBkKTtcbn1cblxuZnVuY3Rpb24gdGltZVNlcmllc1N0YW1wKHN0YW1wQ2ZnLCBmbXREYXRlKSB7XG5cdHJldHVybiBmbXREYXRlKHN0YW1wQ2ZnKTtcbn1cbmNvbnN0IF90aW1lU2VyaWVzU3RhbXAgPSAne1lZWVl9LXtNTX0te0REfSB7aH06e21tfXthYX0nO1xuXG5mdW5jdGlvbiB0aW1lU2VyaWVzVmFsKHR6RGF0ZSwgc3RhbXApIHtcblx0cmV0dXJuIChzZWxmLCB2YWwpID0+IHN0YW1wKHR6RGF0ZSh2YWwpKTtcbn1cblxuZnVuY3Rpb24gbGVnZW5kU3Ryb2tlKHNlbGYsIHNlcmllc0lkeCkge1xuXHRsZXQgcyA9IHNlbGYuc2VyaWVzW3Nlcmllc0lkeF07XG5cdHJldHVybiBzLndpZHRoID8gcy5zdHJva2Uoc2VsZiwgc2VyaWVzSWR4KSA6IHMucG9pbnRzLndpZHRoID8gcy5wb2ludHMuc3Ryb2tlKHNlbGYsIHNlcmllc0lkeCkgOiBudWxsO1xufVxuXG5mdW5jdGlvbiBsZWdlbmRGaWxsKHNlbGYsIHNlcmllc0lkeCkge1xuXHRyZXR1cm4gc2VsZi5zZXJpZXNbc2VyaWVzSWR4XS5maWxsKHNlbGYsIHNlcmllc0lkeCk7XG59XG5cbmNvbnN0IGxlZ2VuZE9wdHMgPSB7XG5cdHNob3c6IHRydWUsXG5cdGxpdmU6IHRydWUsXG5cdGlzb2xhdGU6IGZhbHNlLFxuXHRtYXJrZXJzOiB7XG5cdFx0c2hvdzogdHJ1ZSxcblx0XHR3aWR0aDogMixcblx0XHRzdHJva2U6IGxlZ2VuZFN0cm9rZSxcblx0XHRmaWxsOiBsZWdlbmRGaWxsLFxuXHRcdGRhc2g6IFwic29saWRcIixcblx0fSxcblx0aWR4OiBudWxsLFxuXHRpZHhzOiBudWxsLFxuXHR2YWx1ZXM6IFtdLFxufTtcblxuZnVuY3Rpb24gY3Vyc29yUG9pbnRTaG93KHNlbGYsIHNpKSB7XG5cdGxldCBvID0gc2VsZi5jdXJzb3IucG9pbnRzO1xuXG5cdGxldCBwdCA9IHBsYWNlRGl2KCk7XG5cblx0bGV0IHNpemUgPSBvLnNpemUoc2VsZiwgc2kpO1xuXHRzZXRTdHlsZVB4KHB0LCBXSURUSCwgc2l6ZSk7XG5cdHNldFN0eWxlUHgocHQsIEhFSUdIVCwgc2l6ZSk7XG5cblx0bGV0IG1hciA9IHNpemUgLyAtMjtcblx0c2V0U3R5bGVQeChwdCwgXCJtYXJnaW5MZWZ0XCIsIG1hcik7XG5cdHNldFN0eWxlUHgocHQsIFwibWFyZ2luVG9wXCIsIG1hcik7XG5cblx0bGV0IHdpZHRoID0gby53aWR0aChzZWxmLCBzaSwgc2l6ZSk7XG5cdHdpZHRoICYmIHNldFN0eWxlUHgocHQsIFwiYm9yZGVyV2lkdGhcIiwgd2lkdGgpO1xuXG5cdHJldHVybiBwdDtcbn1cblxuZnVuY3Rpb24gY3Vyc29yUG9pbnRGaWxsKHNlbGYsIHNpKSB7XG5cdGxldCBzcCA9IHNlbGYuc2VyaWVzW3NpXS5wb2ludHM7XG5cdHJldHVybiBzcC5fZmlsbCB8fCBzcC5fc3Ryb2tlO1xufVxuXG5mdW5jdGlvbiBjdXJzb3JQb2ludFN0cm9rZShzZWxmLCBzaSkge1xuXHRsZXQgc3AgPSBzZWxmLnNlcmllc1tzaV0ucG9pbnRzO1xuXHRyZXR1cm4gc3AuX3N0cm9rZSB8fCBzcC5fZmlsbDtcbn1cblxuZnVuY3Rpb24gY3Vyc29yUG9pbnRTaXplKHNlbGYsIHNpKSB7XG5cdGxldCBzcCA9IHNlbGYuc2VyaWVzW3NpXS5wb2ludHM7XG5cdHJldHVybiBwdERpYShzcC53aWR0aCwgMSk7XG59XG5cbmZ1bmN0aW9uIGRhdGFJZHgoc2VsZiwgc2VyaWVzSWR4LCBjdXJzb3JJZHgpIHtcblx0cmV0dXJuIGN1cnNvcklkeDtcbn1cblxuY29uc3QgbW92ZVR1cGxlID0gWzAsMF07XG5cbmZ1bmN0aW9uIGN1cnNvck1vdmUoc2VsZiwgbW91c2VMZWZ0MSwgbW91c2VUb3AxKSB7XG5cdG1vdmVUdXBsZVswXSA9IG1vdXNlTGVmdDE7XG5cdG1vdmVUdXBsZVsxXSA9IG1vdXNlVG9wMTtcblx0cmV0dXJuIG1vdmVUdXBsZTtcbn1cblxuZnVuY3Rpb24gZmlsdEJ0bjAoc2VsZiwgdGFyZywgaGFuZGxlKSB7XG5cdHJldHVybiBlID0+IHtcblx0XHRlLmJ1dHRvbiA9PSAwICYmIGhhbmRsZShlKTtcblx0fTtcbn1cblxuZnVuY3Rpb24gcGFzc1RocnUoc2VsZiwgdGFyZywgaGFuZGxlKSB7XG5cdHJldHVybiBoYW5kbGU7XG59XG5cbmNvbnN0IGN1cnNvck9wdHMgPSB7XG5cdHNob3c6IHRydWUsXG5cdHg6IHRydWUsXG5cdHk6IHRydWUsXG5cdGxvY2s6IGZhbHNlLFxuXHRtb3ZlOiBjdXJzb3JNb3ZlLFxuXHRwb2ludHM6IHtcblx0XHRzaG93OiAgIGN1cnNvclBvaW50U2hvdyxcblx0XHRzaXplOiAgIGN1cnNvclBvaW50U2l6ZSxcblx0XHR3aWR0aDogIDAsXG5cdFx0c3Ryb2tlOiBjdXJzb3JQb2ludFN0cm9rZSxcblx0XHRmaWxsOiAgIGN1cnNvclBvaW50RmlsbCxcblx0fSxcblxuXHRiaW5kOiB7XG5cdFx0bW91c2Vkb3duOiAgIGZpbHRCdG4wLFxuXHRcdG1vdXNldXA6ICAgICBmaWx0QnRuMCxcblx0XHRjbGljazogICAgICAgZmlsdEJ0bjAsXG5cdFx0ZGJsY2xpY2s6ICAgIGZpbHRCdG4wLFxuXG5cdFx0bW91c2Vtb3ZlOiAgIHBhc3NUaHJ1LFxuXHRcdG1vdXNlbGVhdmU6ICBwYXNzVGhydSxcblx0XHRtb3VzZWVudGVyOiAgcGFzc1RocnUsXG5cdH0sXG5cblx0ZHJhZzoge1xuXHRcdHNldFNjYWxlOiB0cnVlLFxuXHRcdHg6IHRydWUsXG5cdFx0eTogZmFsc2UsXG5cdFx0ZGlzdDogMCxcblx0XHR1bmk6IG51bGwsXG5cdFx0X3g6IGZhbHNlLFxuXHRcdF95OiBmYWxzZSxcblx0fSxcblxuXHRmb2N1czoge1xuXHRcdHByb3g6IC0xLFxuXHR9LFxuXG5cdGxlZnQ6IC0xMCxcblx0dG9wOiAtMTAsXG5cdGlkeDogbnVsbCxcblx0ZGF0YUlkeCxcblx0aWR4czogbnVsbCxcbn07XG5cbmNvbnN0IGF4aXNMaW5lcyA9IHtcblx0c2hvdzogdHJ1ZSxcblx0c3Ryb2tlOiBcInJnYmEoMCwwLDAsMC4wNylcIixcblx0d2lkdGg6IDIsXG4vL1x0ZGFzaDogW10sXG59O1xuXG5jb25zdCBncmlkID0gYXNzaWduKHt9LCBheGlzTGluZXMsIHtcblx0ZmlsdGVyOiByZXRBcmcxLFxufSk7XG5cbmNvbnN0IHRpY2tzID0gYXNzaWduKHt9LCBncmlkLCB7XG5cdHNpemU6IDEwLFxufSk7XG5cbmNvbnN0IGJvcmRlciA9IGFzc2lnbih7fSwgYXhpc0xpbmVzLCB7XG5cdHNob3c6IGZhbHNlLFxufSk7XG5cbmNvbnN0IGZvbnQgICAgICA9ICcxMnB4IHN5c3RlbS11aSwgLWFwcGxlLXN5c3RlbSwgXCJTZWdvZSBVSVwiLCBSb2JvdG8sIFwiSGVsdmV0aWNhIE5ldWVcIiwgQXJpYWwsIFwiTm90byBTYW5zXCIsIHNhbnMtc2VyaWYsIFwiQXBwbGUgQ29sb3IgRW1vamlcIiwgXCJTZWdvZSBVSSBFbW9qaVwiLCBcIlNlZ29lIFVJIFN5bWJvbFwiLCBcIk5vdG8gQ29sb3IgRW1vamlcIic7XG5jb25zdCBsYWJlbEZvbnQgPSBcImJvbGQgXCIgKyBmb250O1xuY29uc3QgbGluZU11bHQgPSAxLjU7XHRcdC8vIGZvbnQtc2l6ZSBtdWx0aXBsaWVyXG5cbmNvbnN0IHhBeGlzT3B0cyA9IHtcblx0c2hvdzogdHJ1ZSxcblx0c2NhbGU6IFwieFwiLFxuXHRzdHJva2U6IGhleEJsYWNrLFxuXHRzcGFjZTogNTAsXG5cdGdhcDogNSxcblx0c2l6ZTogNTAsXG5cdGxhYmVsR2FwOiAwLFxuXHRsYWJlbFNpemU6IDMwLFxuXHRsYWJlbEZvbnQsXG5cdHNpZGU6IDIsXG4vL1x0Y2xhc3M6IFwieC12YWxzXCIsXG4vL1x0aW5jcnM6IHRpbWVJbmNycyxcbi8vXHR2YWx1ZXM6IHRpbWVWYWxzLFxuLy9cdGZpbHRlcjogcmV0QXJnMSxcblx0Z3JpZCxcblx0dGlja3MsXG5cdGJvcmRlcixcblx0Zm9udCxcblx0cm90YXRlOiAwLFxufTtcblxuY29uc3QgbnVtU2VyaWVzTGFiZWwgPSBcIlZhbHVlXCI7XG5jb25zdCB0aW1lU2VyaWVzTGFiZWwgPSBcIlRpbWVcIjtcblxuY29uc3QgeFNlcmllc09wdHMgPSB7XG5cdHNob3c6IHRydWUsXG5cdHNjYWxlOiBcInhcIixcblx0YXV0bzogZmFsc2UsXG5cdHNvcnRlZDogMSxcbi8vXHRsYWJlbDogXCJUaW1lXCIsXG4vL1x0dmFsdWU6IHYgPT4gc3RhbXAobmV3IERhdGUodiAqIDFlMykpLFxuXG5cdC8vIGludGVybmFsIGNhY2hlc1xuXHRtaW46IGluZixcblx0bWF4OiAtaW5mLFxuXHRpZHhzOiBbXSxcbn07XG5cbmZ1bmN0aW9uIG51bUF4aXNWYWxzKHNlbGYsIHNwbGl0cywgYXhpc0lkeCwgZm91bmRTcGFjZSwgZm91bmRJbmNyKSB7XG5cdHJldHVybiBzcGxpdHMubWFwKHYgPT4gdiA9PSBudWxsID8gXCJcIiA6IGZtdE51bSh2KSk7XG59XG5cbmZ1bmN0aW9uIG51bUF4aXNTcGxpdHMoc2VsZiwgYXhpc0lkeCwgc2NhbGVNaW4sIHNjYWxlTWF4LCBmb3VuZEluY3IsIGZvdW5kU3BhY2UsIGZvcmNlTWluKSB7XG5cdGxldCBzcGxpdHMgPSBbXTtcblxuXHRsZXQgbnVtRGVjID0gZml4ZWREZWMuZ2V0KGZvdW5kSW5jcikgfHwgMDtcblxuXHRzY2FsZU1pbiA9IGZvcmNlTWluID8gc2NhbGVNaW4gOiByb3VuZERlYyhpbmNyUm91bmRVcChzY2FsZU1pbiwgZm91bmRJbmNyKSwgbnVtRGVjKTtcblxuXHRmb3IgKGxldCB2YWwgPSBzY2FsZU1pbjsgdmFsIDw9IHNjYWxlTWF4OyB2YWwgPSByb3VuZERlYyh2YWwgKyBmb3VuZEluY3IsIG51bURlYykpXG5cdFx0c3BsaXRzLnB1c2goT2JqZWN0LmlzKHZhbCwgLTApID8gMCA6IHZhbCk7XHRcdC8vIGNvYWxlc2NlcyAtMFxuXG5cdHJldHVybiBzcGxpdHM7XG59XG5cbi8vIHRoaXMgZG9lc250IHdvcmsgZm9yIHNpbiwgd2hpY2ggbmVlZHMgdG8gY29tZSBvZmYgZnJvbSAwIGluZGVwZW5kZW50bHkgaW4gcG9zIGFuZCBuZWcgZGlyc1xuZnVuY3Rpb24gbG9nQXhpc1NwbGl0cyhzZWxmLCBheGlzSWR4LCBzY2FsZU1pbiwgc2NhbGVNYXgsIGZvdW5kSW5jciwgZm91bmRTcGFjZSwgZm9yY2VNaW4pIHtcblx0Y29uc3Qgc3BsaXRzID0gW107XG5cblx0Y29uc3QgbG9nQmFzZSA9IHNlbGYuc2NhbGVzW3NlbGYuYXhlc1theGlzSWR4XS5zY2FsZV0ubG9nO1xuXG5cdGNvbnN0IGxvZ0ZuID0gbG9nQmFzZSA9PSAxMCA/IGxvZzEwIDogbG9nMjtcblxuXHRjb25zdCBleHAgPSBmbG9vcihsb2dGbihzY2FsZU1pbikpO1xuXG5cdGZvdW5kSW5jciA9IHBvdyhsb2dCYXNlLCBleHApO1xuXG5cdGlmIChleHAgPCAwKVxuXHRcdGZvdW5kSW5jciA9IHJvdW5kRGVjKGZvdW5kSW5jciwgLWV4cCk7XG5cblx0bGV0IHNwbGl0ID0gc2NhbGVNaW47XG5cblx0ZG8ge1xuXHRcdHNwbGl0cy5wdXNoKHNwbGl0KTtcblx0XHRzcGxpdCA9IHJvdW5kRGVjKHNwbGl0ICsgZm91bmRJbmNyLCBmaXhlZERlYy5nZXQoZm91bmRJbmNyKSk7XG5cblx0XHRpZiAoc3BsaXQgPj0gZm91bmRJbmNyICogbG9nQmFzZSlcblx0XHRcdGZvdW5kSW5jciA9IHNwbGl0O1xuXG5cdH0gd2hpbGUgKHNwbGl0IDw9IHNjYWxlTWF4KTtcblxuXHRyZXR1cm4gc3BsaXRzO1xufVxuXG5mdW5jdGlvbiBhc2luaEF4aXNTcGxpdHMoc2VsZiwgYXhpc0lkeCwgc2NhbGVNaW4sIHNjYWxlTWF4LCBmb3VuZEluY3IsIGZvdW5kU3BhY2UsIGZvcmNlTWluKSB7XG5cdGxldCBzYyA9IHNlbGYuc2NhbGVzW3NlbGYuYXhlc1theGlzSWR4XS5zY2FsZV07XG5cblx0bGV0IGxpbnRocmVzaCA9IHNjLmFzaW5oO1xuXG5cdGxldCBwb3NTcGxpdHMgPSBzY2FsZU1heCA+IGxpbnRocmVzaCA/IGxvZ0F4aXNTcGxpdHMoc2VsZiwgYXhpc0lkeCwgbWF4KGxpbnRocmVzaCwgc2NhbGVNaW4pLCBzY2FsZU1heCwgZm91bmRJbmNyKSA6IFtsaW50aHJlc2hdO1xuXHRsZXQgemVybyA9IHNjYWxlTWF4ID49IDAgJiYgc2NhbGVNaW4gPD0gMCA/IFswXSA6IFtdO1xuXHRsZXQgbmVnU3BsaXRzID0gc2NhbGVNaW4gPCAtbGludGhyZXNoID8gbG9nQXhpc1NwbGl0cyhzZWxmLCBheGlzSWR4LCBtYXgobGludGhyZXNoLCAtc2NhbGVNYXgpLCAtc2NhbGVNaW4sIGZvdW5kSW5jcik6IFtsaW50aHJlc2hdO1xuXG5cdHJldHVybiBuZWdTcGxpdHMucmV2ZXJzZSgpLm1hcCh2ID0+IC12KS5jb25jYXQoemVybywgcG9zU3BsaXRzKTtcbn1cblxuY29uc3QgUkVfQUxMICAgPSAvLi87XG5jb25zdCBSRV8xMjM1NyA9IC9bMTIzNTddLztcbmNvbnN0IFJFXzEyNSAgID0gL1sxMjVdLztcbmNvbnN0IFJFXzEgICAgID0gLzEvO1xuXG5mdW5jdGlvbiBsb2dBeGlzVmFsc0ZpbHQoc2VsZiwgc3BsaXRzLCBheGlzSWR4LCBmb3VuZFNwYWNlLCBmb3VuZEluY3IpIHtcblx0bGV0IGF4aXMgPSBzZWxmLmF4ZXNbYXhpc0lkeF07XG5cdGxldCBzY2FsZUtleSA9IGF4aXMuc2NhbGU7XG5cdGxldCBzYyA9IHNlbGYuc2NhbGVzW3NjYWxlS2V5XTtcblxuXHRpZiAoc2MuZGlzdHIgPT0gMyAmJiBzYy5sb2cgPT0gMilcblx0XHRyZXR1cm4gc3BsaXRzO1xuXG5cdGxldCB2YWxUb1BvcyA9IHNlbGYudmFsVG9Qb3M7XG5cblx0bGV0IG1pblNwYWNlID0gYXhpcy5fc3BhY2U7XG5cblx0bGV0IF8xMCA9IHZhbFRvUG9zKDEwLCBzY2FsZUtleSk7XG5cblx0bGV0IHJlID0gKFxuXHRcdHZhbFRvUG9zKDksIHNjYWxlS2V5KSAtIF8xMCA+PSBtaW5TcGFjZSA/IFJFX0FMTCA6XG5cdFx0dmFsVG9Qb3MoNywgc2NhbGVLZXkpIC0gXzEwID49IG1pblNwYWNlID8gUkVfMTIzNTcgOlxuXHRcdHZhbFRvUG9zKDUsIHNjYWxlS2V5KSAtIF8xMCA+PSBtaW5TcGFjZSA/IFJFXzEyNSA6XG5cdFx0UkVfMVxuXHQpO1xuXG5cdHJldHVybiBzcGxpdHMubWFwKHYgPT4gKChzYy5kaXN0ciA9PSA0ICYmIHYgPT0gMCkgfHwgcmUudGVzdCh2KSkgPyB2IDogbnVsbCk7XG59XG5cbmZ1bmN0aW9uIG51bVNlcmllc1ZhbChzZWxmLCB2YWwpIHtcblx0cmV0dXJuIHZhbCA9PSBudWxsID8gXCJcIiA6IGZtdE51bSh2YWwpO1xufVxuXG5jb25zdCB5QXhpc09wdHMgPSB7XG5cdHNob3c6IHRydWUsXG5cdHNjYWxlOiBcInlcIixcblx0c3Ryb2tlOiBoZXhCbGFjayxcblx0c3BhY2U6IDMwLFxuXHRnYXA6IDUsXG5cdHNpemU6IDUwLFxuXHRsYWJlbEdhcDogMCxcblx0bGFiZWxTaXplOiAzMCxcblx0bGFiZWxGb250LFxuXHRzaWRlOiAzLFxuLy9cdGNsYXNzOiBcInktdmFsc1wiLFxuLy9cdGluY3JzOiBudW1JbmNycyxcbi8vXHR2YWx1ZXM6ICh2YWxzLCBzcGFjZSkgPT4gdmFscyxcbi8vXHRmaWx0ZXI6IHJldEFyZzEsXG5cdGdyaWQsXG5cdHRpY2tzLFxuXHRib3JkZXIsXG5cdGZvbnQsXG5cdHJvdGF0ZTogMCxcbn07XG5cbi8vIHRha2VzIHN0cm9rZSB3aWR0aFxuZnVuY3Rpb24gcHREaWEod2lkdGgsIG11bHQpIHtcblx0bGV0IGRpYSA9IDMgKyAod2lkdGggfHwgMSkgKiAyO1xuXHRyZXR1cm4gcm91bmREZWMoZGlhICogbXVsdCwgMyk7XG59XG5cbmZ1bmN0aW9uIHNlcmllc1BvaW50c1Nob3coc2VsZiwgc2kpIHtcblx0bGV0IHsgc2NhbGUsIGlkeHMgfSA9IHNlbGYuc2VyaWVzWzBdO1xuXHRsZXQgeERhdGEgPSBzZWxmLl9kYXRhWzBdO1xuXHRsZXQgcDAgPSBzZWxmLnZhbFRvUG9zKHhEYXRhW2lkeHNbMF1dLCBzY2FsZSwgdHJ1ZSk7XG5cdGxldCBwMSA9IHNlbGYudmFsVG9Qb3MoeERhdGFbaWR4c1sxXV0sIHNjYWxlLCB0cnVlKTtcblx0bGV0IGRpbSA9IGFicyhwMSAtIHAwKTtcblxuXHRsZXQgcyA9IHNlbGYuc2VyaWVzW3NpXTtcbi8vXHRjb25zdCBkaWEgPSBwdERpYShzLndpZHRoLCBweFJhdGlvKTtcblx0bGV0IG1heFB0cyA9IGRpbSAvIChzLnBvaW50cy5zcGFjZSAqIHB4UmF0aW8pO1xuXHRyZXR1cm4gaWR4c1sxXSAtIGlkeHNbMF0gPD0gbWF4UHRzO1xufVxuXG5jb25zdCBmYWNldCA9IHtcblx0c2NhbGU6IG51bGwsXG5cdGF1dG86IHRydWUsXG5cdHNvcnRlZDogMCxcblxuXHQvLyBpbnRlcm5hbCBjYWNoZXNcblx0bWluOiBpbmYsXG5cdG1heDogLWluZixcbn07XG5cbmNvbnN0IHh5U2VyaWVzT3B0cyA9IHtcblx0c2hvdzogdHJ1ZSxcblx0YXV0bzogdHJ1ZSxcblx0c29ydGVkOiAwLFxuXHRhbHBoYTogMSxcblx0ZmFjZXRzOiBbXG5cdFx0YXNzaWduKHt9LCBmYWNldCwge3NjYWxlOiAneCd9KSxcblx0XHRhc3NpZ24oe30sIGZhY2V0LCB7c2NhbGU6ICd5J30pLFxuXHRdLFxufTtcblxuY29uc3QgeVNlcmllc09wdHMgPSB7XG5cdHNjYWxlOiBcInlcIixcblx0YXV0bzogdHJ1ZSxcblx0c29ydGVkOiAwLFxuXHRzaG93OiB0cnVlLFxuXHRzcGFuR2FwczogZmFsc2UsXG5cdGdhcHM6IChzZWxmLCBzZXJpZXNJZHgsIGlkeDAsIGlkeDEsIG51bGxHYXBzKSA9PiBudWxsR2Fwcyxcblx0YWxwaGE6IDEsXG5cdHBvaW50czoge1xuXHRcdHNob3c6IHNlcmllc1BvaW50c1Nob3csXG5cdFx0ZmlsdGVyOiBudWxsLFxuXHQvLyAgcGF0aHM6XG5cdC8vXHRzdHJva2U6IFwiIzAwMFwiLFxuXHQvL1x0ZmlsbDogXCIjZmZmXCIsXG5cdC8vXHR3aWR0aDogMSxcblx0Ly9cdHNpemU6IDEwLFxuXHR9LFxuLy9cdGxhYmVsOiBcIlZhbHVlXCIsXG4vL1x0dmFsdWU6IHYgPT4gdixcblx0dmFsdWVzOiBudWxsLFxuXG5cdC8vIGludGVybmFsIGNhY2hlc1xuXHRtaW46IGluZixcblx0bWF4OiAtaW5mLFxuXHRpZHhzOiBbXSxcblxuXHRwYXRoOiBudWxsLFxuXHRjbGlwOiBudWxsLFxufTtcblxuZnVuY3Rpb24gY2xhbXBTY2FsZShzZWxmLCB2YWwsIHNjYWxlTWluLCBzY2FsZU1heCwgc2NhbGVLZXkpIHtcbi8qXG5cdGlmICh2YWwgPCAwKSB7XG5cdFx0bGV0IGNzc0hndCA9IHNlbGYuYmJveC5oZWlnaHQgLyBweFJhdGlvO1xuXHRcdGxldCBhYnNQb3MgPSBzZWxmLnZhbFRvUG9zKGFicyh2YWwpLCBzY2FsZUtleSk7XG5cdFx0bGV0IGZyb21CdG0gPSBjc3NIZ3QgLSBhYnNQb3M7XG5cdFx0cmV0dXJuIHNlbGYucG9zVG9WYWwoY3NzSGd0ICsgZnJvbUJ0bSwgc2NhbGVLZXkpO1xuXHR9XG4qL1xuXHRyZXR1cm4gc2NhbGVNaW4gLyAxMDtcbn1cblxuY29uc3QgeFNjYWxlT3B0cyA9IHtcblx0dGltZTogRkVBVF9USU1FLFxuXHRhdXRvOiB0cnVlLFxuXHRkaXN0cjogMSxcblx0bG9nOiAxMCxcblx0YXNpbmg6IDEsXG5cdG1pbjogbnVsbCxcblx0bWF4OiBudWxsLFxuXHRkaXI6IDEsXG5cdG9yaTogMCxcbn07XG5cbmNvbnN0IHlTY2FsZU9wdHMgPSBhc3NpZ24oe30sIHhTY2FsZU9wdHMsIHtcblx0dGltZTogZmFsc2UsXG5cdG9yaTogMSxcbn0pO1xuXG5jb25zdCBzeW5jcyA9IHt9O1xuXG5mdW5jdGlvbiBfc3luYyhrZXksIG9wdHMpIHtcblx0bGV0IHMgPSBzeW5jc1trZXldO1xuXG5cdGlmICghcykge1xuXHRcdHMgPSB7XG5cdFx0XHRrZXksXG5cdFx0XHRwbG90czogW10sXG5cdFx0XHRzdWIocGxvdCkge1xuXHRcdFx0XHRzLnBsb3RzLnB1c2gocGxvdCk7XG5cdFx0XHR9LFxuXHRcdFx0dW5zdWIocGxvdCkge1xuXHRcdFx0XHRzLnBsb3RzID0gcy5wbG90cy5maWx0ZXIoYyA9PiBjICE9IHBsb3QpO1xuXHRcdFx0fSxcblx0XHRcdHB1Yih0eXBlLCBzZWxmLCB4LCB5LCB3LCBoLCBpKSB7XG5cdFx0XHRcdGZvciAobGV0IGogPSAwOyBqIDwgcy5wbG90cy5sZW5ndGg7IGorKylcblx0XHRcdFx0XHRzLnBsb3RzW2pdICE9IHNlbGYgJiYgcy5wbG90c1tqXS5wdWIodHlwZSwgc2VsZiwgeCwgeSwgdywgaCwgaSk7XG5cdFx0XHR9LFxuXHRcdH07XG5cblx0XHRpZiAoa2V5ICE9IG51bGwpXG5cdFx0XHRzeW5jc1trZXldID0gcztcblx0fVxuXG5cdHJldHVybiBzO1xufVxuXG5jb25zdCBCQU5EX0NMSVBfRklMTCAgID0gMSA8PCAwO1xuY29uc3QgQkFORF9DTElQX1NUUk9LRSA9IDEgPDwgMTtcblxuZnVuY3Rpb24gb3JpZW50KHUsIHNlcmllc0lkeCwgY2IpIHtcblx0Y29uc3Qgc2VyaWVzID0gdS5zZXJpZXNbc2VyaWVzSWR4XTtcblx0Y29uc3Qgc2NhbGVzID0gdS5zY2FsZXM7XG5cdGNvbnN0IGJib3ggICA9IHUuYmJveDtcblx0Y29uc3Qgc2NhbGVYID0gdS5tb2RlID09IDIgPyBzY2FsZXNbc2VyaWVzLmZhY2V0c1swXS5zY2FsZV0gOiBzY2FsZXNbdS5zZXJpZXNbMF0uc2NhbGVdO1xuXG5cdGxldCBkeCA9IHUuX2RhdGFbMF0sXG5cdFx0ZHkgPSB1Ll9kYXRhW3Nlcmllc0lkeF0sXG5cdFx0c3ggPSBzY2FsZVgsXG5cdFx0c3kgPSB1Lm1vZGUgPT0gMiA/IHNjYWxlc1tzZXJpZXMuZmFjZXRzWzFdLnNjYWxlXSA6IHNjYWxlc1tzZXJpZXMuc2NhbGVdLFxuXHRcdGwgPSBiYm94LmxlZnQsXG5cdFx0dCA9IGJib3gudG9wLFxuXHRcdHcgPSBiYm94LndpZHRoLFxuXHRcdGggPSBiYm94LmhlaWdodCxcblx0XHRIID0gdS52YWxUb1Bvc0gsXG5cdFx0ViA9IHUudmFsVG9Qb3NWO1xuXG5cdHJldHVybiAoc3gub3JpID09IDBcblx0XHQ/IGNiKFxuXHRcdFx0c2VyaWVzLFxuXHRcdFx0ZHgsXG5cdFx0XHRkeSxcblx0XHRcdHN4LFxuXHRcdFx0c3ksXG5cdFx0XHRILFxuXHRcdFx0Vixcblx0XHRcdGwsXG5cdFx0XHR0LFxuXHRcdFx0dyxcblx0XHRcdGgsXG5cdFx0XHRtb3ZlVG9ILFxuXHRcdFx0bGluZVRvSCxcblx0XHRcdHJlY3RILFxuXHRcdFx0YXJjSCxcblx0XHRcdGJlemllckN1cnZlVG9ILFxuXHRcdClcblx0XHQ6IGNiKFxuXHRcdFx0c2VyaWVzLFxuXHRcdFx0ZHgsXG5cdFx0XHRkeSxcblx0XHRcdHN4LFxuXHRcdFx0c3ksXG5cdFx0XHRWLFxuXHRcdFx0SCxcblx0XHRcdHQsXG5cdFx0XHRsLFxuXHRcdFx0aCxcblx0XHRcdHcsXG5cdFx0XHRtb3ZlVG9WLFxuXHRcdFx0bGluZVRvVixcblx0XHRcdHJlY3RWLFxuXHRcdFx0YXJjVixcblx0XHRcdGJlemllckN1cnZlVG9WLFxuXHRcdClcblx0KTtcbn1cblxuZnVuY3Rpb24gYmFuZEZpbGxDbGlwRGlycyhzZWxmLCBzZXJpZXNJZHgpIHtcblx0bGV0IGZpbGxEaXIgPSAwO1xuXG5cdC8vIDIgYml0cywgLTEgfCAxXG5cdGxldCBjbGlwRGlycyA9IDA7XG5cblx0bGV0IGJhbmRzID0gaWZOdWxsKHNlbGYuYmFuZHMsIEVNUFRZX0FSUik7XG5cblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBiYW5kcy5sZW5ndGg7IGkrKykge1xuXHRcdGxldCBiID0gYmFuZHNbaV07XG5cblx0XHQvLyBpcyBhIFwiZnJvbVwiIGJhbmQgZWRnZVxuXHRcdGlmIChiLnNlcmllc1swXSA9PSBzZXJpZXNJZHgpXG5cdFx0XHRmaWxsRGlyID0gYi5kaXI7XG5cdFx0Ly8gaXMgYSBcInRvXCIgYmFuZCBlZGdlXG5cdFx0ZWxzZSBpZiAoYi5zZXJpZXNbMV0gPT0gc2VyaWVzSWR4KSB7XG5cdFx0XHRpZiAoYi5kaXIgPT0gMSlcblx0XHRcdFx0Y2xpcERpcnMgfD0gMTtcblx0XHRcdGVsc2Vcblx0XHRcdFx0Y2xpcERpcnMgfD0gMjtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gW1xuXHRcdGZpbGxEaXIsXG5cdFx0KFxuXHRcdFx0Y2xpcERpcnMgPT0gMSA/IC0xIDogLy8gbmVnIG9ubHlcblx0XHRcdGNsaXBEaXJzID09IDIgPyAgMSA6IC8vIHBvcyBvbmx5XG5cdFx0XHRjbGlwRGlycyA9PSAzID8gIDIgOiAvLyBib3RoXG5cdFx0XHQgICAgICAgICAgICAgICAgIDAgICAvLyBuZWl0aGVyXG5cdFx0KVxuXHRdO1xufVxuXG5mdW5jdGlvbiBzZXJpZXNGaWxsVG8oc2VsZiwgc2VyaWVzSWR4LCBkYXRhTWluLCBkYXRhTWF4LCBiYW5kRmlsbERpcikge1xuXHRsZXQgc2NhbGUgPSBzZWxmLnNjYWxlc1tzZWxmLnNlcmllc1tzZXJpZXNJZHhdLnNjYWxlXTtcblxuXHRyZXR1cm4gKFxuXHRcdGJhbmRGaWxsRGlyID09IC0xID8gc2NhbGUubWluIDpcblx0XHRiYW5kRmlsbERpciA9PSAgMSA/IHNjYWxlLm1heCA6XG5cdFx0c2NhbGUuZGlzdHIgPT0gIDMgPyAoXG5cdFx0XHRzY2FsZS5kaXIgPT0gMSA/IHNjYWxlLm1pbiA6XG5cdFx0XHRzY2FsZS5tYXhcblx0XHQpIDogMFxuXHQpO1xufVxuXG4vLyBjcmVhdGVzIGludmVydGVkIGJhbmQgY2xpcCBwYXRoIChmcm9tIHN0cm9rZSBwYXRoIC0+IHlNYXggfHwgeU1pbilcbi8vIGNsaXBEaXIgaXMgYWx3YXlzIGludmVyc2Ugb2YgZmlsbERpclxuLy8gZGVmYXVsdCBjbGlwIGRpciBpcyB1cHdhcmRzICgxKSwgc2luY2UgZGVmYXVsdCBiYW5kIGZpbGwgaXMgZG93bndhcmRzL2ZpbGxCZWxvd1RvICgtMSkgKGhpZ2hJZHggLT4gbG93SWR4KVxuZnVuY3Rpb24gY2xpcEJhbmRMaW5lKHNlbGYsIHNlcmllc0lkeCwgaWR4MCwgaWR4MSwgc3Ryb2tlUGF0aCwgY2xpcERpcikge1xuXHRyZXR1cm4gb3JpZW50KHNlbGYsIHNlcmllc0lkeCwgKHNlcmllcywgZGF0YVgsIGRhdGFZLCBzY2FsZVgsIHNjYWxlWSwgdmFsVG9Qb3NYLCB2YWxUb1Bvc1ksIHhPZmYsIHlPZmYsIHhEaW0sIHlEaW0pID0+IHtcblx0XHRsZXQgcHhSb3VuZCA9IHNlcmllcy5weFJvdW5kO1xuXG5cdFx0Y29uc3QgZGlyID0gc2NhbGVYLmRpciAqIChzY2FsZVgub3JpID09IDAgPyAxIDogLTEpO1xuXHRcdGNvbnN0IGxpbmVUbyA9IHNjYWxlWC5vcmkgPT0gMCA/IGxpbmVUb0ggOiBsaW5lVG9WO1xuXG5cdFx0bGV0IGZySWR4LCB0b0lkeDtcblxuXHRcdGlmIChkaXIgPT0gMSkge1xuXHRcdFx0ZnJJZHggPSBpZHgwO1xuXHRcdFx0dG9JZHggPSBpZHgxO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGZySWR4ID0gaWR4MTtcblx0XHRcdHRvSWR4ID0gaWR4MDtcblx0XHR9XG5cblx0XHQvLyBwYXRoIHN0YXJ0XG5cdFx0bGV0IHgwID0gcHhSb3VuZCh2YWxUb1Bvc1goZGF0YVhbZnJJZHhdLCBzY2FsZVgsIHhEaW0sIHhPZmYpKTtcblx0XHRsZXQgeTAgPSBweFJvdW5kKHZhbFRvUG9zWShkYXRhWVtmcklkeF0sIHNjYWxlWSwgeURpbSwgeU9mZikpO1xuXHRcdC8vIHBhdGggZW5kIHhcblx0XHRsZXQgeDEgPSBweFJvdW5kKHZhbFRvUG9zWChkYXRhWFt0b0lkeF0sIHNjYWxlWCwgeERpbSwgeE9mZikpO1xuXHRcdC8vIHVwcGVyIG9yIGxvd2VyIHkgbGltaXRcblx0XHRsZXQgeUxpbWl0ID0gcHhSb3VuZCh2YWxUb1Bvc1koY2xpcERpciA9PSAxID8gc2NhbGVZLm1heCA6IHNjYWxlWS5taW4sIHNjYWxlWSwgeURpbSwgeU9mZikpO1xuXG5cdFx0bGV0IGNsaXAgPSBuZXcgUGF0aDJEKHN0cm9rZVBhdGgpO1xuXG5cdFx0bGluZVRvKGNsaXAsIHgxLCB5TGltaXQpO1xuXHRcdGxpbmVUbyhjbGlwLCB4MCwgeUxpbWl0KTtcblx0XHRsaW5lVG8oY2xpcCwgeDAsIHkwKTtcblxuXHRcdHJldHVybiBjbGlwO1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gY2xpcEdhcHMoZ2Fwcywgb3JpLCBwbG90TGZ0LCBwbG90VG9wLCBwbG90V2lkLCBwbG90SGd0KSB7XG5cdGxldCBjbGlwID0gbnVsbDtcblxuXHQvLyBjcmVhdGUgY2xpcCBwYXRoIChpbnZlcnQgZ2FwcyBhbmQgbm9uLWdhcHMpXG5cdGlmIChnYXBzLmxlbmd0aCA+IDApIHtcblx0XHRjbGlwID0gbmV3IFBhdGgyRCgpO1xuXG5cdFx0Y29uc3QgcmVjdCA9IG9yaSA9PSAwID8gcmVjdEggOiByZWN0VjtcblxuXHRcdGxldCBwcmV2R2FwRW5kID0gcGxvdExmdDtcblxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgZ2Fwcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0bGV0IGcgPSBnYXBzW2ldO1xuXG5cdFx0XHRpZiAoZ1sxXSA+IGdbMF0pIHtcblx0XHRcdFx0bGV0IHcgPSBnWzBdIC0gcHJldkdhcEVuZDtcblxuXHRcdFx0XHR3ID4gMCAmJiByZWN0KGNsaXAsIHByZXZHYXBFbmQsIHBsb3RUb3AsIHcsIHBsb3RUb3AgKyBwbG90SGd0KTtcblxuXHRcdFx0XHRwcmV2R2FwRW5kID0gZ1sxXTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRsZXQgdyA9IHBsb3RMZnQgKyBwbG90V2lkIC0gcHJldkdhcEVuZDtcblxuXHRcdHcgPiAwICYmIHJlY3QoY2xpcCwgcHJldkdhcEVuZCwgcGxvdFRvcCwgdywgcGxvdFRvcCArIHBsb3RIZ3QpO1xuXHR9XG5cblx0cmV0dXJuIGNsaXA7XG59XG5cbmZ1bmN0aW9uIGFkZEdhcChnYXBzLCBmcm9tWCwgdG9YKSB7XG5cdGxldCBwcmV2R2FwID0gZ2Fwc1tnYXBzLmxlbmd0aCAtIDFdO1xuXG5cdGlmIChwcmV2R2FwICYmIHByZXZHYXBbMF0gPT0gZnJvbVgpXHRcdFx0Ly8gVE9ETzogZ2FwcyBtdXN0IGJlIGVuY29kZWQgYXQgc3Ryb2tlIHdpZHRocz9cblx0XHRwcmV2R2FwWzFdID0gdG9YO1xuXHRlbHNlXG5cdFx0Z2Fwcy5wdXNoKFtmcm9tWCwgdG9YXSk7XG59XG5cbmZ1bmN0aW9uIGZpbmRHYXBzKHhzLCB5cywgaWR4MCwgaWR4MSwgZGlyLCBwaXhlbEZvclgsIGFsaWduKSB7XG5cdGxldCBnYXBzID0gW107XG5cblx0Zm9yIChsZXQgaSA9IGRpciA9PSAxID8gaWR4MCA6IGlkeDE7IGkgPj0gaWR4MCAmJiBpIDw9IGlkeDE7IGkgKz0gZGlyKSB7XG5cdFx0bGV0IHlWYWwgPSB5c1tpXTtcblxuXHRcdGlmICh5VmFsID09PSBudWxsKSB7XG5cdFx0XHRsZXQgZnIgPSBpLCB0byA9IGk7XG5cblx0XHRcdGlmIChkaXIgPT0gMSkge1xuXHRcdFx0XHR3aGlsZSAoKytpIDw9IGlkeDEgJiYgeXNbaV0gPT09IG51bGwpXG5cdFx0XHRcdFx0dG8gPSBpO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdHdoaWxlICgtLWkgPj0gaWR4MCAmJiB5c1tpXSA9PT0gbnVsbClcblx0XHRcdFx0XHR0byA9IGk7XG5cdFx0XHR9XG5cblx0XHRcdGxldCBmclB4ID0gcGl4ZWxGb3JYKHhzW2ZyXSk7XG5cdFx0XHRsZXQgdG9QeCA9IHRvID09IGZyID8gZnJQeCA6IHBpeGVsRm9yWCh4c1t0b10pO1xuXG5cdFx0XHQvLyBpZiB2YWx1ZSBhZGphY2VudCB0byBlZGdlIG51bGwgaXMgc2FtZSBwaXhlbCwgdGhlbiBpdCdzIHBhcnRpYWxseVxuXHRcdFx0Ly8gZmlsbGVkIGFuZCBnYXAgc2hvdWxkIHN0YXJ0IGF0IG5leHQgcGl4ZWxcblx0XHRcdGxldCBmclB4MiA9IGFsaWduIDw9IDAgPyBwaXhlbEZvclgoeHNbZnItZGlyXSkgOiBmclB4O1xuXHRcdC8vXHRpZiAoZnJQeDIgPT0gZnJQeClcblx0XHQvL1x0XHRmclB4Kys7XG5cdFx0Ly9cdGVsc2Vcblx0XHRcdFx0ZnJQeCA9IGZyUHgyO1xuXG5cdFx0XHRsZXQgdG9QeDIgPSBhbGlnbiA+PSAwID8gcGl4ZWxGb3JYKHhzW3RvK2Rpcl0pIDogdG9QeDtcblx0XHQvL1x0aWYgKHRvUHgyID09IHRvUHgpXG5cdFx0Ly9cdFx0dG9QeC0tO1xuXHRcdC8vXHRlbHNlXG5cdFx0XHRcdHRvUHggPSB0b1B4MjtcblxuXHRcdFx0aWYgKHRvUHggPj0gZnJQeClcblx0XHRcdFx0Z2Fwcy5wdXNoKFtmclB4LCB0b1B4XSk7IC8vIGFkZEdhcFxuXHRcdH1cblx0fVxuXG5cdHJldHVybiBnYXBzO1xufVxuXG5mdW5jdGlvbiBweFJvdW5kR2VuKHB4QWxpZ24pIHtcblx0cmV0dXJuIHB4QWxpZ24gPT0gMCA/IHJldEFyZzAgOiBweEFsaWduID09IDEgPyByb3VuZCA6IHYgPT4gaW5jclJvdW5kKHYsIHB4QWxpZ24pO1xufVxuXG5mdW5jdGlvbiByZWN0KG9yaSkge1xuXHRsZXQgbW92ZVRvID0gb3JpID09IDAgP1xuXHRcdG1vdmVUb0ggOlxuXHRcdG1vdmVUb1Y7XG5cblx0bGV0IGFyY1RvID0gb3JpID09IDAgP1xuXHRcdChwLCB4MSwgeTEsIHgyLCB5MiwgcikgPT4geyBwLmFyY1RvKHgxLCB5MSwgeDIsIHkyLCByKTsgfSA6XG5cdFx0KHAsIHkxLCB4MSwgeTIsIHgyLCByKSA9PiB7IHAuYXJjVG8oeDEsIHkxLCB4MiwgeTIsIHIpOyB9O1xuXG5cdGxldCByZWN0ID0gb3JpID09IDAgP1xuXHRcdChwLCB4LCB5LCB3LCBoKSA9PiB7IHAucmVjdCh4LCB5LCB3LCBoKTsgfSA6XG5cdFx0KHAsIHksIHgsIGgsIHcpID0+IHsgcC5yZWN0KHgsIHksIHcsIGgpOyB9O1xuXG5cdHJldHVybiAocCwgeCwgeSwgdywgaCwgciA9IDApID0+IHtcblx0XHRpZiAociA9PSAwKVxuXHRcdFx0cmVjdChwLCB4LCB5LCB3LCBoKTtcblx0XHRlbHNlIHtcblx0XHRcdHIgPSBtaW4ociwgdyAvIDIsIGggLyAyKTtcblxuXHRcdFx0Ly8gYWRhcHRlZCBmcm9tIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzEyNTU1MTIvaG93LXRvLWRyYXctYS1yb3VuZGVkLXJlY3RhbmdsZS11c2luZy1odG1sLWNhbnZhcy83ODM4ODcxIzc4Mzg4NzFcblx0XHRcdG1vdmVUbyhwLCB4ICsgciwgeSk7XG5cdFx0XHRhcmNUbyhwLCB4ICsgdywgeSwgeCArIHcsIHkgKyBoLCByKTtcblx0XHRcdGFyY1RvKHAsIHggKyB3LCB5ICsgaCwgeCwgeSArIGgsIHIpO1xuXHRcdFx0YXJjVG8ocCwgeCwgeSArIGgsIHgsIHksIHIpO1xuXHRcdFx0YXJjVG8ocCwgeCwgeSwgeCArIHcsIHksIHIpO1xuXHRcdFx0cC5jbG9zZVBhdGgoKTtcblx0XHR9XG5cdH07XG59XG5cbi8vIG9yaWVudGF0aW9uLWludmVydGluZyBjYW52YXMgZnVuY3Rpb25zXG5jb25zdCBtb3ZlVG9IID0gKHAsIHgsIHkpID0+IHsgcC5tb3ZlVG8oeCwgeSk7IH07XG5jb25zdCBtb3ZlVG9WID0gKHAsIHksIHgpID0+IHsgcC5tb3ZlVG8oeCwgeSk7IH07XG5jb25zdCBsaW5lVG9IID0gKHAsIHgsIHkpID0+IHsgcC5saW5lVG8oeCwgeSk7IH07XG5jb25zdCBsaW5lVG9WID0gKHAsIHksIHgpID0+IHsgcC5saW5lVG8oeCwgeSk7IH07XG5jb25zdCByZWN0SCA9IHJlY3QoMCk7XG5jb25zdCByZWN0ViA9IHJlY3QoMSk7XG5jb25zdCBhcmNIID0gKHAsIHgsIHksIHIsIHN0YXJ0QW5nbGUsIGVuZEFuZ2xlKSA9PiB7IHAuYXJjKHgsIHksIHIsIHN0YXJ0QW5nbGUsIGVuZEFuZ2xlKTsgfTtcbmNvbnN0IGFyY1YgPSAocCwgeSwgeCwgciwgc3RhcnRBbmdsZSwgZW5kQW5nbGUpID0+IHsgcC5hcmMoeCwgeSwgciwgc3RhcnRBbmdsZSwgZW5kQW5nbGUpOyB9O1xuY29uc3QgYmV6aWVyQ3VydmVUb0ggPSAocCwgYnAxeCwgYnAxeSwgYnAyeCwgYnAyeSwgcDJ4LCBwMnkpID0+IHsgcC5iZXppZXJDdXJ2ZVRvKGJwMXgsIGJwMXksIGJwMngsIGJwMnksIHAyeCwgcDJ5KTsgfTtcbmNvbnN0IGJlemllckN1cnZlVG9WID0gKHAsIGJwMXksIGJwMXgsIGJwMnksIGJwMngsIHAyeSwgcDJ4KSA9PiB7IHAuYmV6aWVyQ3VydmVUbyhicDF4LCBicDF5LCBicDJ4LCBicDJ5LCBwMngsIHAyeSk7IH07XG5cbi8vIFRPRE86IGRyYXdXcmFwKHNlcmllc0lkeCwgZHJhd1BvaW50cykgKHNhdmUsIHJlc3RvcmUsIHRyYW5zbGF0ZSwgY2xpcClcbmZ1bmN0aW9uIHBvaW50cyhvcHRzKSB7XG5cdHJldHVybiAodSwgc2VyaWVzSWR4LCBpZHgwLCBpZHgxLCBmaWx0SWR4cykgPT4ge1xuXHQvL1x0bG9nKFwiZHJhd1BvaW50cygpXCIsIGFyZ3VtZW50cyk7XG5cblx0XHRyZXR1cm4gb3JpZW50KHUsIHNlcmllc0lkeCwgKHNlcmllcywgZGF0YVgsIGRhdGFZLCBzY2FsZVgsIHNjYWxlWSwgdmFsVG9Qb3NYLCB2YWxUb1Bvc1ksIHhPZmYsIHlPZmYsIHhEaW0sIHlEaW0pID0+IHtcblx0XHRcdGxldCB7IHB4Um91bmQsIHBvaW50cyB9ID0gc2VyaWVzO1xuXG5cdFx0XHRsZXQgbW92ZVRvLCBhcmM7XG5cblx0XHRcdGlmIChzY2FsZVgub3JpID09IDApIHtcblx0XHRcdFx0bW92ZVRvID0gbW92ZVRvSDtcblx0XHRcdFx0YXJjID0gYXJjSDtcblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHRtb3ZlVG8gPSBtb3ZlVG9WO1xuXHRcdFx0XHRhcmMgPSBhcmNWO1xuXHRcdFx0fVxuXG5cdFx0XHRjb25zdCB3aWR0aCA9IHJvdW5kRGVjKHBvaW50cy53aWR0aCAqIHB4UmF0aW8sIDMpO1xuXG5cdFx0XHRsZXQgcmFkID0gKHBvaW50cy5zaXplIC0gcG9pbnRzLndpZHRoKSAvIDIgKiBweFJhdGlvO1xuXHRcdFx0bGV0IGRpYSA9IHJvdW5kRGVjKHJhZCAqIDIsIDMpO1xuXG5cdFx0XHRsZXQgZmlsbCA9IG5ldyBQYXRoMkQoKTtcblx0XHRcdGxldCBjbGlwID0gbmV3IFBhdGgyRCgpO1xuXG5cdFx0XHRsZXQgeyBsZWZ0OiBsZnQsIHRvcDogdG9wLCB3aWR0aDogd2lkLCBoZWlnaHQ6IGhndCB9ID0gdS5iYm94O1xuXG5cdFx0XHRyZWN0SChjbGlwLFxuXHRcdFx0XHRsZnQgLSBkaWEsXG5cdFx0XHRcdHRvcCAtIGRpYSxcblx0XHRcdFx0d2lkICsgZGlhICogMixcblx0XHRcdFx0aGd0ICsgZGlhICogMixcblx0XHRcdCk7XG5cblx0XHRcdGNvbnN0IGRyYXdQb2ludCA9IHBpID0+IHtcblx0XHRcdFx0aWYgKGRhdGFZW3BpXSAhPSBudWxsKSB7XG5cdFx0XHRcdFx0bGV0IHggPSBweFJvdW5kKHZhbFRvUG9zWChkYXRhWFtwaV0sIHNjYWxlWCwgeERpbSwgeE9mZikpO1xuXHRcdFx0XHRcdGxldCB5ID0gcHhSb3VuZCh2YWxUb1Bvc1koZGF0YVlbcGldLCBzY2FsZVksIHlEaW0sIHlPZmYpKTtcblxuXHRcdFx0XHRcdG1vdmVUbyhmaWxsLCB4ICsgcmFkLCB5KTtcblx0XHRcdFx0XHRhcmMoZmlsbCwgeCwgeSwgcmFkLCAwLCBQSSAqIDIpO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXG5cdFx0XHRpZiAoZmlsdElkeHMpXG5cdFx0XHRcdGZpbHRJZHhzLmZvckVhY2goZHJhd1BvaW50KTtcblx0XHRcdGVsc2Uge1xuXHRcdFx0XHRmb3IgKGxldCBwaSA9IGlkeDA7IHBpIDw9IGlkeDE7IHBpKyspXG5cdFx0XHRcdFx0ZHJhd1BvaW50KHBpKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0c3Ryb2tlOiB3aWR0aCA+IDAgPyBmaWxsIDogbnVsbCxcblx0XHRcdFx0ZmlsbCxcblx0XHRcdFx0Y2xpcCxcblx0XHRcdFx0ZmxhZ3M6IEJBTkRfQ0xJUF9GSUxMIHwgQkFORF9DTElQX1NUUk9LRSxcblx0XHRcdH07XG5cdFx0fSk7XG5cdH07XG59XG5cbmZ1bmN0aW9uIF9kcmF3QWNjKGxpbmVUbykge1xuXHRyZXR1cm4gKHN0cm9rZSwgYWNjWCwgbWluWSwgbWF4WSwgaW5ZLCBvdXRZKSA9PiB7XG5cdFx0aWYgKG1pblkgIT0gbWF4WSkge1xuXHRcdFx0aWYgKGluWSAhPSBtaW5ZICYmIG91dFkgIT0gbWluWSlcblx0XHRcdFx0bGluZVRvKHN0cm9rZSwgYWNjWCwgbWluWSk7XG5cdFx0XHRpZiAoaW5ZICE9IG1heFkgJiYgb3V0WSAhPSBtYXhZKVxuXHRcdFx0XHRsaW5lVG8oc3Ryb2tlLCBhY2NYLCBtYXhZKTtcblxuXHRcdFx0bGluZVRvKHN0cm9rZSwgYWNjWCwgb3V0WSk7XG5cdFx0fVxuXHR9O1xufVxuXG5jb25zdCBkcmF3QWNjSCA9IF9kcmF3QWNjKGxpbmVUb0gpO1xuY29uc3QgZHJhd0FjY1YgPSBfZHJhd0FjYyhsaW5lVG9WKTtcblxuZnVuY3Rpb24gbGluZWFyKG9wdHMpIHtcblx0Y29uc3QgYWxpZ25HYXBzID0gaWZOdWxsKG9wdHM/LmFsaWduR2FwcywgMCk7XG5cblx0cmV0dXJuICh1LCBzZXJpZXNJZHgsIGlkeDAsIGlkeDEpID0+IHtcblx0XHRyZXR1cm4gb3JpZW50KHUsIHNlcmllc0lkeCwgKHNlcmllcywgZGF0YVgsIGRhdGFZLCBzY2FsZVgsIHNjYWxlWSwgdmFsVG9Qb3NYLCB2YWxUb1Bvc1ksIHhPZmYsIHlPZmYsIHhEaW0sIHlEaW0pID0+IHtcblx0XHRcdGxldCBweFJvdW5kID0gc2VyaWVzLnB4Um91bmQ7XG5cblx0XHRcdGxldCBwaXhlbEZvclggPSB2YWwgPT4gcHhSb3VuZCh2YWxUb1Bvc1godmFsLCBzY2FsZVgsIHhEaW0sIHhPZmYpKTtcblx0XHRcdGxldCBwaXhlbEZvclkgPSB2YWwgPT4gcHhSb3VuZCh2YWxUb1Bvc1kodmFsLCBzY2FsZVksIHlEaW0sIHlPZmYpKTtcblxuXHRcdFx0bGV0IGxpbmVUbywgZHJhd0FjYztcblxuXHRcdFx0aWYgKHNjYWxlWC5vcmkgPT0gMCkge1xuXHRcdFx0XHRsaW5lVG8gPSBsaW5lVG9IO1xuXHRcdFx0XHRkcmF3QWNjID0gZHJhd0FjY0g7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0bGluZVRvID0gbGluZVRvVjtcblx0XHRcdFx0ZHJhd0FjYyA9IGRyYXdBY2NWO1xuXHRcdFx0fVxuXG5cdFx0XHRjb25zdCBkaXIgPSBzY2FsZVguZGlyICogKHNjYWxlWC5vcmkgPT0gMCA/IDEgOiAtMSk7XG5cblx0XHRcdGNvbnN0IF9wYXRocyA9IHtzdHJva2U6IG5ldyBQYXRoMkQoKSwgZmlsbDogbnVsbCwgY2xpcDogbnVsbCwgYmFuZDogbnVsbCwgZ2FwczogbnVsbCwgZmxhZ3M6IEJBTkRfQ0xJUF9GSUxMfTtcblx0XHRcdGNvbnN0IHN0cm9rZSA9IF9wYXRocy5zdHJva2U7XG5cblx0XHRcdGxldCBtaW5ZID0gaW5mLFxuXHRcdFx0XHRtYXhZID0gLWluZixcblx0XHRcdFx0aW5ZLCBvdXRZLCBkcmF3bkF0WDtcblxuXHRcdFx0bGV0IGFjY1ggPSBwaXhlbEZvclgoZGF0YVhbZGlyID09IDEgPyBpZHgwIDogaWR4MV0pO1xuXG5cdFx0XHQvLyBkYXRhIGVkZ2VzXG5cdFx0XHRsZXQgbGZ0SWR4ID0gbm9uTnVsbElkeChkYXRhWSwgaWR4MCwgaWR4MSwgIDEgKiBkaXIpO1xuXHRcdFx0bGV0IHJndElkeCA9IG5vbk51bGxJZHgoZGF0YVksIGlkeDAsIGlkeDEsIC0xICogZGlyKTtcblx0XHRcdGxldCBsZnRYICAgPSAgcGl4ZWxGb3JYKGRhdGFYW2xmdElkeF0pO1xuXHRcdFx0bGV0IHJndFggICA9ICBwaXhlbEZvclgoZGF0YVhbcmd0SWR4XSk7XG5cblx0XHRcdGZvciAobGV0IGkgPSBkaXIgPT0gMSA/IGlkeDAgOiBpZHgxOyBpID49IGlkeDAgJiYgaSA8PSBpZHgxOyBpICs9IGRpcikge1xuXHRcdFx0XHRsZXQgeCA9IHBpeGVsRm9yWChkYXRhWFtpXSk7XG5cblx0XHRcdFx0aWYgKHggPT0gYWNjWCkge1xuXHRcdFx0XHRcdGlmIChkYXRhWVtpXSAhPSBudWxsKSB7XG5cdFx0XHRcdFx0XHRvdXRZID0gcGl4ZWxGb3JZKGRhdGFZW2ldKTtcblxuXHRcdFx0XHRcdFx0aWYgKG1pblkgPT0gaW5mKSB7XG5cdFx0XHRcdFx0XHRcdGxpbmVUbyhzdHJva2UsIHgsIG91dFkpO1xuXHRcdFx0XHRcdFx0XHRpblkgPSBvdXRZO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRtaW5ZID0gbWluKG91dFksIG1pblkpO1xuXHRcdFx0XHRcdFx0bWF4WSA9IG1heChvdXRZLCBtYXhZKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0aWYgKG1pblkgIT0gaW5mKSB7XG5cdFx0XHRcdFx0XHRkcmF3QWNjKHN0cm9rZSwgYWNjWCwgbWluWSwgbWF4WSwgaW5ZLCBvdXRZKTtcblx0XHRcdFx0XHRcdGRyYXduQXRYID0gYWNjWDtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoZGF0YVlbaV0gIT0gbnVsbCkge1xuXHRcdFx0XHRcdFx0b3V0WSA9IHBpeGVsRm9yWShkYXRhWVtpXSk7XG5cdFx0XHRcdFx0XHRsaW5lVG8oc3Ryb2tlLCB4LCBvdXRZKTtcblx0XHRcdFx0XHRcdG1pblkgPSBtYXhZID0gaW5ZID0gb3V0WTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0XHRtaW5ZID0gaW5mO1xuXHRcdFx0XHRcdFx0bWF4WSA9IC1pbmY7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0YWNjWCA9IHg7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0aWYgKG1pblkgIT0gaW5mICYmIG1pblkgIT0gbWF4WSAmJiBkcmF3bkF0WCAhPSBhY2NYKVxuXHRcdFx0XHRkcmF3QWNjKHN0cm9rZSwgYWNjWCwgbWluWSwgbWF4WSwgaW5ZLCBvdXRZKTtcblxuXHRcdFx0bGV0IFsgYmFuZEZpbGxEaXIsIGJhbmRDbGlwRGlyIF0gPSBiYW5kRmlsbENsaXBEaXJzKHUsIHNlcmllc0lkeCk7XG5cblx0XHRcdGlmIChzZXJpZXMuZmlsbCAhPSBudWxsIHx8IGJhbmRGaWxsRGlyICE9IDApIHtcblx0XHRcdFx0bGV0IGZpbGwgPSBfcGF0aHMuZmlsbCA9IG5ldyBQYXRoMkQoc3Ryb2tlKTtcblxuXHRcdFx0XHRsZXQgZmlsbFRvVmFsID0gc2VyaWVzLmZpbGxUbyh1LCBzZXJpZXNJZHgsIHNlcmllcy5taW4sIHNlcmllcy5tYXgsIGJhbmRGaWxsRGlyKTtcblx0XHRcdFx0bGV0IGZpbGxUb1kgPSBwaXhlbEZvclkoZmlsbFRvVmFsKTtcblxuXHRcdFx0XHRsaW5lVG8oZmlsbCwgcmd0WCwgZmlsbFRvWSk7XG5cdFx0XHRcdGxpbmVUbyhmaWxsLCBsZnRYLCBmaWxsVG9ZKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCFzZXJpZXMuc3BhbkdhcHMpIHtcblx0XHRcdC8vXHRjb25zb2xlLnRpbWUoJ2dhcHMnKTtcblx0XHRcdFx0bGV0IGdhcHMgPSBbXTtcblxuXHRcdFx0XHRnYXBzLnB1c2goLi4uZmluZEdhcHMoZGF0YVgsIGRhdGFZLCBpZHgwLCBpZHgxLCBkaXIsIHBpeGVsRm9yWCwgYWxpZ25HYXBzKSk7XG5cblx0XHRcdC8vXHRjb25zb2xlLnRpbWVFbmQoJ2dhcHMnKTtcblxuXHRcdFx0Ly9cdGNvbnNvbGUubG9nKCdnYXBzJywgSlNPTi5zdHJpbmdpZnkoZ2FwcykpO1xuXG5cdFx0XHRcdF9wYXRocy5nYXBzID0gZ2FwcyA9IHNlcmllcy5nYXBzKHUsIHNlcmllc0lkeCwgaWR4MCwgaWR4MSwgZ2Fwcyk7XG5cblx0XHRcdFx0X3BhdGhzLmNsaXAgPSBjbGlwR2FwcyhnYXBzLCBzY2FsZVgub3JpLCB4T2ZmLCB5T2ZmLCB4RGltLCB5RGltKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGJhbmRDbGlwRGlyICE9IDApIHtcblx0XHRcdFx0X3BhdGhzLmJhbmQgPSBiYW5kQ2xpcERpciA9PSAyID8gW1xuXHRcdFx0XHRcdGNsaXBCYW5kTGluZSh1LCBzZXJpZXNJZHgsIGlkeDAsIGlkeDEsIHN0cm9rZSwgLTEpLFxuXHRcdFx0XHRcdGNsaXBCYW5kTGluZSh1LCBzZXJpZXNJZHgsIGlkeDAsIGlkeDEsIHN0cm9rZSwgIDEpLFxuXHRcdFx0XHRdIDogY2xpcEJhbmRMaW5lKHUsIHNlcmllc0lkeCwgaWR4MCwgaWR4MSwgc3Ryb2tlLCBiYW5kQ2xpcERpcik7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBfcGF0aHM7XG5cdFx0fSk7XG5cdH07XG59XG5cbmZ1bmN0aW9uIHN0ZXBwZWQob3B0cykge1xuXHRjb25zdCBhbGlnbiA9IGlmTnVsbChvcHRzLmFsaWduLCAxKTtcblx0Ly8gd2hldGhlciB0byBkcmF3IGFzY2VuZGVycy9kZXNjZW5kZXJzIGF0IG51bGwvZ2FwIGJvbmRhcmllc1xuXHRjb25zdCBhc2NEZXNjID0gaWZOdWxsKG9wdHMuYXNjRGVzYywgZmFsc2UpO1xuXG5cdGNvbnN0IGFsaWduR2FwcyA9IGlmTnVsbChvcHRzLmFsaWduR2FwcywgMCk7XG5cblx0cmV0dXJuICh1LCBzZXJpZXNJZHgsIGlkeDAsIGlkeDEpID0+IHtcblx0XHRyZXR1cm4gb3JpZW50KHUsIHNlcmllc0lkeCwgKHNlcmllcywgZGF0YVgsIGRhdGFZLCBzY2FsZVgsIHNjYWxlWSwgdmFsVG9Qb3NYLCB2YWxUb1Bvc1ksIHhPZmYsIHlPZmYsIHhEaW0sIHlEaW0pID0+IHtcblx0XHRcdGxldCBweFJvdW5kID0gc2VyaWVzLnB4Um91bmQ7XG5cblx0XHRcdGxldCBwaXhlbEZvclggPSB2YWwgPT4gcHhSb3VuZCh2YWxUb1Bvc1godmFsLCBzY2FsZVgsIHhEaW0sIHhPZmYpKTtcblx0XHRcdGxldCBwaXhlbEZvclkgPSB2YWwgPT4gcHhSb3VuZCh2YWxUb1Bvc1kodmFsLCBzY2FsZVksIHlEaW0sIHlPZmYpKTtcblxuXHRcdFx0bGV0IGxpbmVUbyA9IHNjYWxlWC5vcmkgPT0gMCA/IGxpbmVUb0ggOiBsaW5lVG9WO1xuXG5cdFx0XHRjb25zdCBfcGF0aHMgPSB7c3Ryb2tlOiBuZXcgUGF0aDJEKCksIGZpbGw6IG51bGwsIGNsaXA6IG51bGwsIGJhbmQ6IG51bGwsIGdhcHM6IG51bGwsIGZsYWdzOiBCQU5EX0NMSVBfRklMTH07XG5cdFx0XHRjb25zdCBzdHJva2UgPSBfcGF0aHMuc3Ryb2tlO1xuXG5cdFx0XHRjb25zdCBkaXIgPSBzY2FsZVguZGlyICogKHNjYWxlWC5vcmkgPT0gMCA/IDEgOiAtMSk7XG5cblx0XHRcdGlkeDAgPSBub25OdWxsSWR4KGRhdGFZLCBpZHgwLCBpZHgxLCAgMSk7XG5cdFx0XHRpZHgxID0gbm9uTnVsbElkeChkYXRhWSwgaWR4MCwgaWR4MSwgLTEpO1xuXG5cdFx0XHRsZXQgcHJldllQb3MgID0gcGl4ZWxGb3JZKGRhdGFZW2RpciA9PSAxID8gaWR4MCA6IGlkeDFdKTtcblx0XHRcdGxldCBmaXJzdFhQb3MgPSBwaXhlbEZvclgoZGF0YVhbZGlyID09IDEgPyBpZHgwIDogaWR4MV0pO1xuXHRcdFx0bGV0IHByZXZYUG9zID0gZmlyc3RYUG9zO1xuXG5cdFx0XHRsaW5lVG8oc3Ryb2tlLCBmaXJzdFhQb3MsIHByZXZZUG9zKTtcblxuXHRcdFx0Zm9yIChsZXQgaSA9IGRpciA9PSAxID8gaWR4MCA6IGlkeDE7IGkgPj0gaWR4MCAmJiBpIDw9IGlkeDE7IGkgKz0gZGlyKSB7XG5cdFx0XHRcdGxldCB5VmFsMSA9IGRhdGFZW2ldO1xuXG5cdFx0XHRcdGlmICh5VmFsMSA9PSBudWxsKVxuXHRcdFx0XHRcdGNvbnRpbnVlO1xuXG5cdFx0XHRcdGxldCB4MSA9IHBpeGVsRm9yWChkYXRhWFtpXSk7XG5cdFx0XHRcdGxldCB5MSA9IHBpeGVsRm9yWSh5VmFsMSk7XG5cblx0XHRcdFx0aWYgKGFsaWduID09IDEpXG5cdFx0XHRcdFx0bGluZVRvKHN0cm9rZSwgeDEsIHByZXZZUG9zKTtcblx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdGxpbmVUbyhzdHJva2UsIHByZXZYUG9zLCB5MSk7XG5cblx0XHRcdFx0bGluZVRvKHN0cm9rZSwgeDEsIHkxKTtcblxuXHRcdFx0XHRwcmV2WVBvcyA9IHkxO1xuXHRcdFx0XHRwcmV2WFBvcyA9IHgxO1xuXHRcdFx0fVxuXG5cdFx0XHRsZXQgWyBiYW5kRmlsbERpciwgYmFuZENsaXBEaXIgXSA9IGJhbmRGaWxsQ2xpcERpcnModSwgc2VyaWVzSWR4KTtcblxuXHRcdFx0aWYgKHNlcmllcy5maWxsICE9IG51bGwgfHwgYmFuZEZpbGxEaXIgIT0gMCkge1xuXHRcdFx0XHRsZXQgZmlsbCA9IF9wYXRocy5maWxsID0gbmV3IFBhdGgyRChzdHJva2UpO1xuXG5cdFx0XHRcdGxldCBmaWxsVG8gPSBzZXJpZXMuZmlsbFRvKHUsIHNlcmllc0lkeCwgc2VyaWVzLm1pbiwgc2VyaWVzLm1heCwgYmFuZEZpbGxEaXIpO1xuXHRcdFx0XHRsZXQgZmlsbFRvWSA9IHBpeGVsRm9yWShmaWxsVG8pO1xuXG5cdFx0XHRcdGxpbmVUbyhmaWxsLCBwcmV2WFBvcywgZmlsbFRvWSk7XG5cdFx0XHRcdGxpbmVUbyhmaWxsLCBmaXJzdFhQb3MsIGZpbGxUb1kpO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIXNlcmllcy5zcGFuR2Fwcykge1xuXHRcdFx0Ly9cdGNvbnNvbGUudGltZSgnZ2FwcycpO1xuXHRcdFx0XHRsZXQgZ2FwcyA9IFtdO1xuXG5cdFx0XHRcdGdhcHMucHVzaCguLi5maW5kR2FwcyhkYXRhWCwgZGF0YVksIGlkeDAsIGlkeDEsIGRpciwgcGl4ZWxGb3JYLCBhbGlnbkdhcHMpKTtcblxuXHRcdFx0Ly9cdGNvbnNvbGUudGltZUVuZCgnZ2FwcycpO1xuXG5cdFx0XHQvL1x0Y29uc29sZS5sb2coJ2dhcHMnLCBKU09OLnN0cmluZ2lmeShnYXBzKSk7XG5cblx0XHRcdFx0Ly8gZXhwYW5kL2NvbnRyYWN0IGNsaXBzIGZvciBhc2NlbmRlcnMvZGVzY2VuZGVyc1xuXHRcdFx0XHRsZXQgaGFsZlN0cm9rZSA9IChzZXJpZXMud2lkdGggKiBweFJhdGlvKSAvIDI7XG5cdFx0XHRcdGxldCBzdGFydHNPZmZzZXQgPSAoYXNjRGVzYyB8fCBhbGlnbiA9PSAgMSkgPyAgaGFsZlN0cm9rZSA6IC1oYWxmU3Ryb2tlO1xuXHRcdFx0XHRsZXQgZW5kc09mZnNldCAgID0gKGFzY0Rlc2MgfHwgYWxpZ24gPT0gLTEpID8gLWhhbGZTdHJva2UgOiAgaGFsZlN0cm9rZTtcblxuXHRcdFx0XHRnYXBzLmZvckVhY2goZyA9PiB7XG5cdFx0XHRcdFx0Z1swXSArPSBzdGFydHNPZmZzZXQ7XG5cdFx0XHRcdFx0Z1sxXSArPSBlbmRzT2Zmc2V0O1xuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHRfcGF0aHMuZ2FwcyA9IGdhcHMgPSBzZXJpZXMuZ2Fwcyh1LCBzZXJpZXNJZHgsIGlkeDAsIGlkeDEsIGdhcHMpO1xuXG5cdFx0XHRcdF9wYXRocy5jbGlwID0gY2xpcEdhcHMoZ2Fwcywgc2NhbGVYLm9yaSwgeE9mZiwgeU9mZiwgeERpbSwgeURpbSk7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChiYW5kQ2xpcERpciAhPSAwKSB7XG5cdFx0XHRcdF9wYXRocy5iYW5kID0gYmFuZENsaXBEaXIgPT0gMiA/IFtcblx0XHRcdFx0XHRjbGlwQmFuZExpbmUodSwgc2VyaWVzSWR4LCBpZHgwLCBpZHgxLCBzdHJva2UsIC0xKSxcblx0XHRcdFx0XHRjbGlwQmFuZExpbmUodSwgc2VyaWVzSWR4LCBpZHgwLCBpZHgxLCBzdHJva2UsICAxKSxcblx0XHRcdFx0XSA6IGNsaXBCYW5kTGluZSh1LCBzZXJpZXNJZHgsIGlkeDAsIGlkeDEsIHN0cm9rZSwgYmFuZENsaXBEaXIpO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gX3BhdGhzO1xuXHRcdH0pO1xuXHR9O1xufVxuXG5mdW5jdGlvbiBiYXJzKG9wdHMpIHtcblx0b3B0cyA9IG9wdHMgfHwgRU1QVFlfT0JKO1xuXHRjb25zdCBzaXplID0gaWZOdWxsKG9wdHMuc2l6ZSwgWzAuNiwgaW5mLCAxXSk7XG5cdGNvbnN0IGFsaWduID0gb3B0cy5hbGlnbiB8fCAwO1xuXHRjb25zdCBleHRyYUdhcCA9IChvcHRzLmdhcCB8fCAwKSAqIHB4UmF0aW87XG5cblx0Y29uc3QgcmFkaXVzID0gaWZOdWxsKG9wdHMucmFkaXVzLCAwKTtcblxuXHRjb25zdCBnYXBGYWN0b3IgPSAxIC0gc2l6ZVswXTtcblx0Y29uc3QgbWF4V2lkdGggID0gaWZOdWxsKHNpemVbMV0sIGluZikgKiBweFJhdGlvO1xuXHRjb25zdCBtaW5XaWR0aCAgPSBpZk51bGwoc2l6ZVsyXSwgMSkgKiBweFJhdGlvO1xuXG5cdGNvbnN0IGRpc3AgPSBpZk51bGwob3B0cy5kaXNwLCBFTVBUWV9PQkopO1xuXHRjb25zdCBfZWFjaCA9IGlmTnVsbChvcHRzLmVhY2gsIF8gPT4ge30pO1xuXG5cdGNvbnN0IHsgZmlsbDogZGlzcEZpbGxzLCBzdHJva2U6IGRpc3BTdHJva2VzIH0gPSBkaXNwO1xuXG5cdHJldHVybiAodSwgc2VyaWVzSWR4LCBpZHgwLCBpZHgxKSA9PiB7XG5cdFx0cmV0dXJuIG9yaWVudCh1LCBzZXJpZXNJZHgsIChzZXJpZXMsIGRhdGFYLCBkYXRhWSwgc2NhbGVYLCBzY2FsZVksIHZhbFRvUG9zWCwgdmFsVG9Qb3NZLCB4T2ZmLCB5T2ZmLCB4RGltLCB5RGltKSA9PiB7XG5cdFx0XHRsZXQgcHhSb3VuZCA9IHNlcmllcy5weFJvdW5kO1xuXG5cdFx0XHRjb25zdCBfZGlyWCA9IHNjYWxlWC5kaXIgKiAoc2NhbGVYLm9yaSA9PSAwID8gMSA6IC0xKTtcblx0XHRcdGNvbnN0IF9kaXJZID0gc2NhbGVZLmRpciAqIChzY2FsZVkub3JpID09IDEgPyAxIDogLTEpO1xuXG5cdFx0XHRsZXQgcmVjdCA9IHNjYWxlWC5vcmkgPT0gMCA/IHJlY3RIIDogcmVjdFY7XG5cblx0XHRcdGxldCBlYWNoID0gc2NhbGVYLm9yaSA9PSAwID8gX2VhY2ggOiAodSwgc2VyaWVzSWR4LCBpLCB0b3AsIGxmdCwgaGd0LCB3aWQpID0+IHtcblx0XHRcdFx0X2VhY2godSwgc2VyaWVzSWR4LCBpLCBsZnQsIHRvcCwgd2lkLCBoZ3QpO1xuXHRcdFx0fTtcblxuXHRcdFx0bGV0IFsgYmFuZEZpbGxEaXIsIGJhbmRDbGlwRGlyIF0gPSBiYW5kRmlsbENsaXBEaXJzKHUsIHNlcmllc0lkeCk7XG5cblx0XHQvL1x0bGV0IGZpbGxUb1kgPSBzZXJpZXMuZmlsbFRvKHUsIHNlcmllc0lkeCwgc2VyaWVzLm1pbiwgc2VyaWVzLm1heCwgYmFuZEZpbGxEaXIpO1xuXHRcdFx0bGV0IGZpbGxUb1kgPSBzY2FsZVkuZGlzdHIgPT0gMyA/IChiYW5kRmlsbERpciA9PSAxID8gc2NhbGVZLm1heCA6IHNjYWxlWS5taW4pIDogMDtcblxuXHRcdFx0bGV0IHkwUG9zID0gdmFsVG9Qb3NZKGZpbGxUb1ksIHNjYWxlWSwgeURpbSwgeU9mZik7XG5cblx0XHRcdC8vIGJhcldpZCBpcyB0byBjZW50ZXIgb2Ygc3Ryb2tlXG5cdFx0XHRsZXQgeFNoaWZ0LCBiYXJXaWQ7XG5cblx0XHRcdGxldCBzdHJva2VXaWR0aCA9IHB4Um91bmQoc2VyaWVzLndpZHRoICogcHhSYXRpbyk7XG5cblx0XHRcdGxldCBtdWx0aVBhdGggPSBmYWxzZTtcblxuXHRcdFx0bGV0IGZpbGxDb2xvcnMgPSBudWxsO1xuXHRcdFx0bGV0IGZpbGxQYXRocyA9IG51bGw7XG5cdFx0XHRsZXQgc3Ryb2tlQ29sb3JzID0gbnVsbDtcblx0XHRcdGxldCBzdHJva2VQYXRocyA9IG51bGw7XG5cblx0XHRcdGlmIChkaXNwRmlsbHMgIT0gbnVsbCAmJiAoc3Ryb2tlV2lkdGggPT0gMCB8fCBkaXNwU3Ryb2tlcyAhPSBudWxsKSkge1xuXHRcdFx0XHRtdWx0aVBhdGggPSB0cnVlO1xuXG5cdFx0XHRcdGZpbGxDb2xvcnMgPSBkaXNwRmlsbHMudmFsdWVzKHUsIHNlcmllc0lkeCwgaWR4MCwgaWR4MSk7XG5cdFx0XHRcdGZpbGxQYXRocyA9IG5ldyBNYXAoKTtcblx0XHRcdFx0KG5ldyBTZXQoZmlsbENvbG9ycykpLmZvckVhY2goY29sb3IgPT4ge1xuXHRcdFx0XHRcdGlmIChjb2xvciAhPSBudWxsKVxuXHRcdFx0XHRcdFx0ZmlsbFBhdGhzLnNldChjb2xvciwgbmV3IFBhdGgyRCgpKTtcblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0aWYgKHN0cm9rZVdpZHRoID4gMCkge1xuXHRcdFx0XHRcdHN0cm9rZUNvbG9ycyA9IGRpc3BTdHJva2VzLnZhbHVlcyh1LCBzZXJpZXNJZHgsIGlkeDAsIGlkeDEpO1xuXHRcdFx0XHRcdHN0cm9rZVBhdGhzID0gbmV3IE1hcCgpO1xuXHRcdFx0XHRcdChuZXcgU2V0KHN0cm9rZUNvbG9ycykpLmZvckVhY2goY29sb3IgPT4ge1xuXHRcdFx0XHRcdFx0aWYgKGNvbG9yICE9IG51bGwpXG5cdFx0XHRcdFx0XHRcdHN0cm9rZVBhdGhzLnNldChjb2xvciwgbmV3IFBhdGgyRCgpKTtcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRsZXQgeyB4MCwgc2l6ZSB9ID0gZGlzcDtcblxuXHRcdFx0aWYgKHgwICE9IG51bGwgJiYgc2l6ZSAhPSBudWxsKSB7XG5cdFx0XHRcdGRhdGFYID0geDAudmFsdWVzKHUsIHNlcmllc0lkeCwgaWR4MCwgaWR4MSk7XG5cblx0XHRcdFx0aWYgKHgwLnVuaXQgPT0gMilcblx0XHRcdFx0XHRkYXRhWCA9IGRhdGFYLm1hcChwY3QgPT4gdS5wb3NUb1ZhbCh4T2ZmICsgcGN0ICogeERpbSwgc2NhbGVYLmtleSwgdHJ1ZSkpO1xuXG5cdFx0XHRcdC8vIGFzc3VtZXMgdW5pZm9ybSBzaXplcywgZm9yIG5vd1xuXHRcdFx0XHRsZXQgc2l6ZXMgPSBzaXplLnZhbHVlcyh1LCBzZXJpZXNJZHgsIGlkeDAsIGlkeDEpO1xuXG5cdFx0XHRcdGlmIChzaXplLnVuaXQgPT0gMilcblx0XHRcdFx0XHRiYXJXaWQgPSBzaXplc1swXSAqIHhEaW07XG5cdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHRiYXJXaWQgPSB2YWxUb1Bvc1goc2l6ZXNbMF0sIHNjYWxlWCwgeERpbSwgeE9mZikgLSB2YWxUb1Bvc1goMCwgc2NhbGVYLCB4RGltLCB4T2ZmKTsgLy8gYXNzdW1lcyBsaW5lYXIgc2NhbGUgKGRlbHRhIGZyb20gMClcblxuXHRcdFx0XHRiYXJXaWQgPSBweFJvdW5kKGJhcldpZCAtIHN0cm9rZVdpZHRoKTtcblxuXHRcdFx0XHR4U2hpZnQgPSAoX2RpclggPT0gMSA/IC1zdHJva2VXaWR0aCAvIDIgOiBiYXJXaWQgKyBzdHJva2VXaWR0aCAvIDIpO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdGxldCBjb2xXaWQgPSB4RGltO1xuXG5cdFx0XHRcdGlmIChkYXRhWC5sZW5ndGggPiAxKSB7XG5cdFx0XHRcdFx0Ly8gcHJpb3IgaW5kZXggd2l0aCBub24tdW5kZWZpbmVkIHkgZGF0YVxuXHRcdFx0XHRcdGxldCBwcmV2SWR4ID0gbnVsbDtcblxuXHRcdFx0XHRcdC8vIHNjYW4gZnVsbCBkYXRhc2V0IGZvciBzbWFsbGVzdCBhZGphY2VudCBkZWx0YVxuXHRcdFx0XHRcdC8vIHdpbGwgbm90IHdvcmsgcHJvcGVybHkgZm9yIG5vbi1saW5lYXIgeCBzY2FsZXMsIHNpbmNlIGRvZXMgbm90IGRvIGV4cGVuc2l2ZSB2YWxUb1Bvc1ggY2FsY3MgdGlsbCBlbmRcblx0XHRcdFx0XHRmb3IgKGxldCBpID0gMCwgbWluRGVsdGEgPSBJbmZpbml0eTsgaSA8IGRhdGFYLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdFx0XHRpZiAoZGF0YVlbaV0gIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdFx0XHRpZiAocHJldklkeCAhPSBudWxsKSB7XG5cdFx0XHRcdFx0XHRcdFx0bGV0IGRlbHRhID0gYWJzKGRhdGFYW2ldIC0gZGF0YVhbcHJldklkeF0pO1xuXG5cdFx0XHRcdFx0XHRcdFx0aWYgKGRlbHRhIDwgbWluRGVsdGEpIHtcblx0XHRcdFx0XHRcdFx0XHRcdG1pbkRlbHRhID0gZGVsdGE7XG5cdFx0XHRcdFx0XHRcdFx0XHRjb2xXaWQgPSBhYnModmFsVG9Qb3NYKGRhdGFYW2ldLCBzY2FsZVgsIHhEaW0sIHhPZmYpIC0gdmFsVG9Qb3NYKGRhdGFYW3ByZXZJZHhdLCBzY2FsZVgsIHhEaW0sIHhPZmYpKTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRwcmV2SWR4ID0gaTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRsZXQgZ2FwV2lkID0gY29sV2lkICogZ2FwRmFjdG9yO1xuXG5cdFx0XHRcdGJhcldpZCA9IHB4Um91bmQobWluKG1heFdpZHRoLCBtYXgobWluV2lkdGgsIGNvbFdpZCAtIGdhcFdpZCkpIC0gc3Ryb2tlV2lkdGggLSBleHRyYUdhcCk7XG5cblx0XHRcdFx0eFNoaWZ0ID0gKGFsaWduID09IDAgPyBiYXJXaWQgLyAyIDogYWxpZ24gPT0gX2RpclggPyAwIDogYmFyV2lkKSAtIGFsaWduICogX2RpclggKiBleHRyYUdhcCAvIDI7XG5cdFx0XHR9XG5cblx0XHRcdGNvbnN0IF9wYXRocyA9IHtzdHJva2U6IG51bGwsIGZpbGw6IG51bGwsIGNsaXA6IG51bGwsIGJhbmQ6IG51bGwsIGdhcHM6IG51bGwsIGZsYWdzOiBCQU5EX0NMSVBfRklMTCB8IEJBTkRfQ0xJUF9TVFJPS0V9OyAgLy8gZGlzcCwgZ2VvbVxuXG5cdFx0XHRsZXQgeUxpbWl0O1xuXG5cdFx0XHRpZiAoYmFuZENsaXBEaXIgIT0gMCkge1xuXHRcdFx0XHRfcGF0aHMuYmFuZCA9IG5ldyBQYXRoMkQoKTtcblx0XHRcdFx0eUxpbWl0ID0gcHhSb3VuZCh2YWxUb1Bvc1koYmFuZENsaXBEaXIgPT0gMSA/IHNjYWxlWS5tYXggOiBzY2FsZVkubWluLCBzY2FsZVksIHlEaW0sIHlPZmYpKTtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3Qgc3Ryb2tlID0gbXVsdGlQYXRoID8gbnVsbCA6IG5ldyBQYXRoMkQoKTtcblx0XHRcdGNvbnN0IGJhbmQgPSBfcGF0aHMuYmFuZDtcblxuXHRcdFx0bGV0IHsgeTAsIHkxIH0gPSBkaXNwO1xuXG5cdFx0XHRsZXQgZGF0YVkwID0gbnVsbDtcblxuXHRcdFx0aWYgKHkwICE9IG51bGwgJiYgeTEgIT0gbnVsbCkge1xuXHRcdFx0XHRkYXRhWSA9IHkxLnZhbHVlcyh1LCBzZXJpZXNJZHgsIGlkeDAsIGlkeDEpO1xuXHRcdFx0XHRkYXRhWTAgPSB5MC52YWx1ZXModSwgc2VyaWVzSWR4LCBpZHgwLCBpZHgxKTtcblx0XHRcdH1cblxuXHRcdFx0Zm9yIChsZXQgaSA9IF9kaXJYID09IDEgPyBpZHgwIDogaWR4MTsgaSA+PSBpZHgwICYmIGkgPD0gaWR4MTsgaSArPSBfZGlyWCkge1xuXHRcdFx0XHRsZXQgeVZhbCA9IGRhdGFZW2ldO1xuXG5cdFx0XHRcdC8vIHdlIGNhbiBza2lwIGJvdGgsIGRyYXdpbmcgYW5kIGJhbmQgY2xpcHBpbmcgZm9yIGFsaWdubWVudCBhcnRpZmFjdHNcblx0XHRcdFx0aWYgKHlWYWwgPT09IHVuZGVmaW5lZClcblx0XHRcdFx0XHRjb250aW51ZTtcblxuXHRcdFx0Lypcblx0XHRcdFx0Ly8gaW50ZXJwb2xhdGUgdXB3YXJkcyBiYW5kIGNsaXBzXG5cdFx0XHRcdGlmICh5VmFsID09IG51bGwpIHtcblx0XHRcdFx0Ly9cdGlmIChoYXNCYW5kcylcblx0XHRcdFx0Ly9cdFx0eVZhbCA9IGNvc3RseUxlcnAoaSwgaWR4MCwgaWR4MSwgX2RpclgsIGRhdGFZKTtcblx0XHRcdFx0Ly9cdGVsc2Vcblx0XHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHR9XG5cdFx0XHQqL1xuXG5cdFx0XHRcdGxldCB4VmFsID0gc2NhbGVYLmRpc3RyICE9IDIgfHwgZGlzcCAhPSBudWxsID8gZGF0YVhbaV0gOiBpO1xuXG5cdFx0XHRcdC8vIFRPRE86IGFsbCB4UG9zIGNhbiBiZSBwcmUtY29tcHV0ZWQgb25jZSBmb3IgYWxsIHNlcmllcyBpbiBhbGlnbmVkIHNldFxuXHRcdFx0XHRsZXQgeFBvcyA9IHZhbFRvUG9zWCh4VmFsLCBzY2FsZVgsIHhEaW0sIHhPZmYpO1xuXHRcdFx0XHRsZXQgeVBvcyA9IHZhbFRvUG9zWShpZk51bGwoeVZhbCwgZmlsbFRvWSksIHNjYWxlWSwgeURpbSwgeU9mZik7XG5cblx0XHRcdFx0aWYgKGRhdGFZMCAhPSBudWxsICYmIHlWYWwgIT0gbnVsbClcblx0XHRcdFx0XHR5MFBvcyA9IHZhbFRvUG9zWShkYXRhWTBbaV0sIHNjYWxlWSwgeURpbSwgeU9mZik7XG5cblx0XHRcdFx0bGV0IGxmdCA9IHB4Um91bmQoeFBvcyAtIHhTaGlmdCk7XG5cdFx0XHRcdGxldCBidG0gPSBweFJvdW5kKG1heCh5UG9zLCB5MFBvcykpO1xuXHRcdFx0XHRsZXQgdG9wID0gcHhSb3VuZChtaW4oeVBvcywgeTBQb3MpKTtcblx0XHRcdFx0Ly8gdGhpcyBpbmNsdWRlcyB0aGUgc3Ryb2tlXG5cdFx0XHRcdGxldCBiYXJIZ3QgPSBidG0gLSB0b3A7XG5cblx0XHRcdFx0bGV0IHIgPSByYWRpdXMgKiBiYXJXaWQ7XG5cblx0XHRcdFx0aWYgKHlWYWwgIT0gbnVsbCkgeyAgLy8gJiYgeVZhbCAhPSBmaWxsVG9ZICgwIGhlaWdodCBiYXIpXG5cdFx0XHRcdFx0aWYgKG11bHRpUGF0aCkge1xuXHRcdFx0XHRcdFx0aWYgKHN0cm9rZVdpZHRoID4gMCAmJiBzdHJva2VDb2xvcnNbaV0gIT0gbnVsbClcblx0XHRcdFx0XHRcdFx0cmVjdChzdHJva2VQYXRocy5nZXQoc3Ryb2tlQ29sb3JzW2ldKSwgbGZ0LCB0b3AgKyBmbG9vcihzdHJva2VXaWR0aCAvIDIpLCBiYXJXaWQsIG1heCgwLCBiYXJIZ3QgLSBzdHJva2VXaWR0aCksIHIpO1xuXG5cdFx0XHRcdFx0XHRpZiAoZmlsbENvbG9yc1tpXSAhPSBudWxsKVxuXHRcdFx0XHRcdFx0XHRyZWN0KGZpbGxQYXRocy5nZXQoZmlsbENvbG9yc1tpXSksIGxmdCwgdG9wICsgZmxvb3Ioc3Ryb2tlV2lkdGggLyAyKSwgYmFyV2lkLCBtYXgoMCwgYmFySGd0IC0gc3Ryb2tlV2lkdGgpLCByKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdFx0cmVjdChzdHJva2UsIGxmdCwgdG9wICsgZmxvb3Ioc3Ryb2tlV2lkdGggLyAyKSwgYmFyV2lkLCBtYXgoMCwgYmFySGd0IC0gc3Ryb2tlV2lkdGgpLCByKTtcblxuXHRcdFx0XHRcdGVhY2godSwgc2VyaWVzSWR4LCBpLFxuXHRcdFx0XHRcdFx0bGZ0ICAgIC0gc3Ryb2tlV2lkdGggLyAyLFxuXHRcdFx0XHRcdFx0dG9wLFxuXHRcdFx0XHRcdFx0YmFyV2lkICsgc3Ryb2tlV2lkdGgsXG5cdFx0XHRcdFx0XHRiYXJIZ3QsXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChiYW5kQ2xpcERpciAhPSAwKSB7XG5cdFx0XHRcdFx0aWYgKF9kaXJZICogYmFuZENsaXBEaXIgPT0gMSkge1xuXHRcdFx0XHRcdFx0YnRtID0gdG9wO1xuXHRcdFx0XHRcdFx0dG9wID0geUxpbWl0O1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHRcdHRvcCA9IGJ0bTtcblx0XHRcdFx0XHRcdGJ0bSA9IHlMaW1pdDtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRiYXJIZ3QgPSBidG0gLSB0b3A7XG5cblx0XHRcdFx0XHRyZWN0KGJhbmQsIGxmdCAtIHN0cm9rZVdpZHRoIC8gMiwgdG9wLCBiYXJXaWQgKyBzdHJva2VXaWR0aCwgbWF4KDAsIGJhckhndCksIDApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGlmIChzdHJva2VXaWR0aCA+IDApXG5cdFx0XHRcdF9wYXRocy5zdHJva2UgPSBtdWx0aVBhdGggPyBzdHJva2VQYXRocyA6IHN0cm9rZTtcblxuXHRcdFx0X3BhdGhzLmZpbGwgPSBtdWx0aVBhdGggPyBmaWxsUGF0aHMgOiBzdHJva2U7XG5cblx0XHRcdHJldHVybiBfcGF0aHM7XG5cdFx0fSk7XG5cdH07XG59XG5cbmZ1bmN0aW9uIHNwbGluZUludGVycChpbnRlcnAsIG9wdHMpIHtcblx0Y29uc3QgYWxpZ25HYXBzID0gaWZOdWxsKG9wdHM/LmFsaWduR2FwcywgMCk7XG5cblx0cmV0dXJuICh1LCBzZXJpZXNJZHgsIGlkeDAsIGlkeDEpID0+IHtcblx0XHRyZXR1cm4gb3JpZW50KHUsIHNlcmllc0lkeCwgKHNlcmllcywgZGF0YVgsIGRhdGFZLCBzY2FsZVgsIHNjYWxlWSwgdmFsVG9Qb3NYLCB2YWxUb1Bvc1ksIHhPZmYsIHlPZmYsIHhEaW0sIHlEaW0pID0+IHtcblx0XHRcdGxldCBweFJvdW5kID0gc2VyaWVzLnB4Um91bmQ7XG5cblx0XHRcdGxldCBwaXhlbEZvclggPSB2YWwgPT4gcHhSb3VuZCh2YWxUb1Bvc1godmFsLCBzY2FsZVgsIHhEaW0sIHhPZmYpKTtcblx0XHRcdGxldCBwaXhlbEZvclkgPSB2YWwgPT4gcHhSb3VuZCh2YWxUb1Bvc1kodmFsLCBzY2FsZVksIHlEaW0sIHlPZmYpKTtcblxuXHRcdFx0bGV0IG1vdmVUbywgYmV6aWVyQ3VydmVUbywgbGluZVRvO1xuXG5cdFx0XHRpZiAoc2NhbGVYLm9yaSA9PSAwKSB7XG5cdFx0XHRcdG1vdmVUbyA9IG1vdmVUb0g7XG5cdFx0XHRcdGxpbmVUbyA9IGxpbmVUb0g7XG5cdFx0XHRcdGJlemllckN1cnZlVG8gPSBiZXppZXJDdXJ2ZVRvSDtcblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHRtb3ZlVG8gPSBtb3ZlVG9WO1xuXHRcdFx0XHRsaW5lVG8gPSBsaW5lVG9WO1xuXHRcdFx0XHRiZXppZXJDdXJ2ZVRvID0gYmV6aWVyQ3VydmVUb1Y7XG5cdFx0XHR9XG5cblx0XHRcdGNvbnN0IGRpciA9IHNjYWxlWC5kaXIgKiAoc2NhbGVYLm9yaSA9PSAwID8gMSA6IC0xKTtcblxuXHRcdFx0aWR4MCA9IG5vbk51bGxJZHgoZGF0YVksIGlkeDAsIGlkeDEsICAxKTtcblx0XHRcdGlkeDEgPSBub25OdWxsSWR4KGRhdGFZLCBpZHgwLCBpZHgxLCAtMSk7XG5cblx0XHRcdGxldCBmaXJzdFhQb3MgPSBwaXhlbEZvclgoZGF0YVhbZGlyID09IDEgPyBpZHgwIDogaWR4MV0pO1xuXHRcdFx0bGV0IHByZXZYUG9zID0gZmlyc3RYUG9zO1xuXG5cdFx0XHRsZXQgeENvb3JkcyA9IFtdO1xuXHRcdFx0bGV0IHlDb29yZHMgPSBbXTtcblxuXHRcdFx0Zm9yIChsZXQgaSA9IGRpciA9PSAxID8gaWR4MCA6IGlkeDE7IGkgPj0gaWR4MCAmJiBpIDw9IGlkeDE7IGkgKz0gZGlyKSB7XG5cdFx0XHRcdGxldCB5VmFsID0gZGF0YVlbaV07XG5cblx0XHRcdFx0aWYgKHlWYWwgIT0gbnVsbCkge1xuXHRcdFx0XHRcdGxldCB4VmFsID0gZGF0YVhbaV07XG5cdFx0XHRcdFx0bGV0IHhQb3MgPSBwaXhlbEZvclgoeFZhbCk7XG5cblx0XHRcdFx0XHR4Q29vcmRzLnB1c2gocHJldlhQb3MgPSB4UG9zKTtcblx0XHRcdFx0XHR5Q29vcmRzLnB1c2gocGl4ZWxGb3JZKGRhdGFZW2ldKSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Y29uc3QgX3BhdGhzID0ge3N0cm9rZTogaW50ZXJwKHhDb29yZHMsIHlDb29yZHMsIG1vdmVUbywgbGluZVRvLCBiZXppZXJDdXJ2ZVRvLCBweFJvdW5kKSwgZmlsbDogbnVsbCwgY2xpcDogbnVsbCwgYmFuZDogbnVsbCwgZ2FwczogbnVsbCwgZmxhZ3M6IEJBTkRfQ0xJUF9GSUxMfTtcblx0XHRcdGNvbnN0IHN0cm9rZSA9IF9wYXRocy5zdHJva2U7XG5cblx0XHRcdGxldCBbIGJhbmRGaWxsRGlyLCBiYW5kQ2xpcERpciBdID0gYmFuZEZpbGxDbGlwRGlycyh1LCBzZXJpZXNJZHgpO1xuXG5cdFx0XHRpZiAoc2VyaWVzLmZpbGwgIT0gbnVsbCB8fCBiYW5kRmlsbERpciAhPSAwKSB7XG5cdFx0XHRcdGxldCBmaWxsID0gX3BhdGhzLmZpbGwgPSBuZXcgUGF0aDJEKHN0cm9rZSk7XG5cblx0XHRcdFx0bGV0IGZpbGxUbyA9IHNlcmllcy5maWxsVG8odSwgc2VyaWVzSWR4LCBzZXJpZXMubWluLCBzZXJpZXMubWF4LCBiYW5kRmlsbERpcik7XG5cdFx0XHRcdGxldCBmaWxsVG9ZID0gcGl4ZWxGb3JZKGZpbGxUbyk7XG5cblx0XHRcdFx0bGluZVRvKGZpbGwsIHByZXZYUG9zLCBmaWxsVG9ZKTtcblx0XHRcdFx0bGluZVRvKGZpbGwsIGZpcnN0WFBvcywgZmlsbFRvWSk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICghc2VyaWVzLnNwYW5HYXBzKSB7XG5cdFx0XHQvL1x0Y29uc29sZS50aW1lKCdnYXBzJyk7XG5cdFx0XHRcdGxldCBnYXBzID0gW107XG5cblx0XHRcdFx0Z2Fwcy5wdXNoKC4uLmZpbmRHYXBzKGRhdGFYLCBkYXRhWSwgaWR4MCwgaWR4MSwgZGlyLCBwaXhlbEZvclgsIGFsaWduR2FwcykpO1xuXG5cdFx0XHQvL1x0Y29uc29sZS50aW1lRW5kKCdnYXBzJyk7XG5cblx0XHRcdC8vXHRjb25zb2xlLmxvZygnZ2FwcycsIEpTT04uc3RyaW5naWZ5KGdhcHMpKTtcblxuXHRcdFx0XHRfcGF0aHMuZ2FwcyA9IGdhcHMgPSBzZXJpZXMuZ2Fwcyh1LCBzZXJpZXNJZHgsIGlkeDAsIGlkeDEsIGdhcHMpO1xuXG5cdFx0XHRcdF9wYXRocy5jbGlwID0gY2xpcEdhcHMoZ2Fwcywgc2NhbGVYLm9yaSwgeE9mZiwgeU9mZiwgeERpbSwgeURpbSk7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChiYW5kQ2xpcERpciAhPSAwKSB7XG5cdFx0XHRcdF9wYXRocy5iYW5kID0gYmFuZENsaXBEaXIgPT0gMiA/IFtcblx0XHRcdFx0XHRjbGlwQmFuZExpbmUodSwgc2VyaWVzSWR4LCBpZHgwLCBpZHgxLCBzdHJva2UsIC0xKSxcblx0XHRcdFx0XHRjbGlwQmFuZExpbmUodSwgc2VyaWVzSWR4LCBpZHgwLCBpZHgxLCBzdHJva2UsICAxKSxcblx0XHRcdFx0XSA6IGNsaXBCYW5kTGluZSh1LCBzZXJpZXNJZHgsIGlkeDAsIGlkeDEsIHN0cm9rZSwgYmFuZENsaXBEaXIpO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gX3BhdGhzO1xuXG5cdFx0XHQvLyAgaWYgRkVBVF9QQVRIUzogZmFsc2UgaW4gcm9sbHVwLmNvbmZpZy5qc1xuXHRcdFx0Ly9cdHUuY3R4LnNhdmUoKTtcblx0XHRcdC8vXHR1LmN0eC5iZWdpblBhdGgoKTtcblx0XHRcdC8vXHR1LmN0eC5yZWN0KHUuYmJveC5sZWZ0LCB1LmJib3gudG9wLCB1LmJib3gud2lkdGgsIHUuYmJveC5oZWlnaHQpO1xuXHRcdFx0Ly9cdHUuY3R4LmNsaXAoKTtcblx0XHRcdC8vXHR1LmN0eC5zdHJva2VTdHlsZSA9IHUuc2VyaWVzW3NpZHhdLnN0cm9rZTtcblx0XHRcdC8vXHR1LmN0eC5zdHJva2Uoc3Ryb2tlKTtcblx0XHRcdC8vXHR1LmN0eC5maWxsU3R5bGUgPSB1LnNlcmllc1tzaWR4XS5maWxsO1xuXHRcdFx0Ly9cdHUuY3R4LmZpbGwoZmlsbCk7XG5cdFx0XHQvL1x0dS5jdHgucmVzdG9yZSgpO1xuXHRcdFx0Ly9cdHJldHVybiBudWxsO1xuXHRcdH0pO1xuXHR9O1xufVxuXG5mdW5jdGlvbiBtb25vdG9uZUN1YmljKG9wdHMpIHtcblx0cmV0dXJuIHNwbGluZUludGVycChfbW9ub3RvbmVDdWJpYywgb3B0cyk7XG59XG5cbi8vIE1vbm90b25lIEN1YmljIFNwbGluZSBpbnRlcnBvbGF0aW9uLCBhZGFwdGVkIGZyb20gdGhlIENoYXJ0aXN0LmpzIGltcGxlbWVudGF0aW9uOlxuLy8gaHR0cHM6Ly9naXRodWIuY29tL2dpb25rdW56L2NoYXJ0aXN0LWpzL2Jsb2IvZTdlNzgyMDFiZmZlOTYwOTkxNWU1ZTUzY2ZhZmEyOWE1ZDZjNDlmOS9zcmMvc2NyaXB0cy9pbnRlcnBvbGF0aW9uLmpzI0wyNDAtTDM2OVxuZnVuY3Rpb24gX21vbm90b25lQ3ViaWMoeHMsIHlzLCBtb3ZlVG8sIGxpbmVUbywgYmV6aWVyQ3VydmVUbywgcHhSb3VuZCkge1xuXHRjb25zdCBuID0geHMubGVuZ3RoO1xuXG5cdGlmIChuIDwgMilcblx0XHRyZXR1cm4gbnVsbDtcblxuXHRjb25zdCBwYXRoID0gbmV3IFBhdGgyRCgpO1xuXG5cdG1vdmVUbyhwYXRoLCB4c1swXSwgeXNbMF0pO1xuXG5cdGlmIChuID09IDIpXG5cdFx0bGluZVRvKHBhdGgsIHhzWzFdLCB5c1sxXSk7XG5cdGVsc2Uge1xuXHRcdGxldCBtcyAgPSBBcnJheShuKSxcblx0XHRcdGRzICA9IEFycmF5KG4gLSAxKSxcblx0XHRcdGR5cyA9IEFycmF5KG4gLSAxKSxcblx0XHRcdGR4cyA9IEFycmF5KG4gLSAxKTtcblxuXHRcdC8vIGNhbGMgZGVsdGFzIGFuZCBkZXJpdmF0aXZlXG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBuIC0gMTsgaSsrKSB7XG5cdFx0XHRkeXNbaV0gPSB5c1tpICsgMV0gLSB5c1tpXTtcblx0XHRcdGR4c1tpXSA9IHhzW2kgKyAxXSAtIHhzW2ldO1xuXHRcdFx0ZHNbaV0gID0gZHlzW2ldIC8gZHhzW2ldO1xuXHRcdH1cblxuXHRcdC8vIGRldGVybWluZSBkZXNpcmVkIHNsb3BlIChtKSBhdCBlYWNoIHBvaW50IHVzaW5nIEZyaXRzY2gtQ2FybHNvbiBtZXRob2Rcblx0XHQvLyBodHRwOi8vbWF0aC5zdGFja2V4Y2hhbmdlLmNvbS9xdWVzdGlvbnMvNDUyMTgvaW1wbGVtZW50YXRpb24tb2YtbW9ub3RvbmUtY3ViaWMtaW50ZXJwb2xhdGlvblxuXHRcdG1zWzBdID0gZHNbMF07XG5cblx0XHRmb3IgKGxldCBpID0gMTsgaSA8IG4gLSAxOyBpKyspIHtcblx0XHRcdGlmIChkc1tpXSA9PT0gMCB8fCBkc1tpIC0gMV0gPT09IDAgfHwgKGRzW2kgLSAxXSA+IDApICE9PSAoZHNbaV0gPiAwKSlcblx0XHRcdFx0bXNbaV0gPSAwO1xuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdG1zW2ldID0gMyAqIChkeHNbaSAtIDFdICsgZHhzW2ldKSAvIChcblx0XHRcdFx0XHQoMiAqIGR4c1tpXSArIGR4c1tpIC0gMV0pIC8gZHNbaSAtIDFdICtcblx0XHRcdFx0XHQoZHhzW2ldICsgMiAqIGR4c1tpIC0gMV0pIC8gZHNbaV1cblx0XHRcdFx0KTtcblxuXHRcdFx0XHRpZiAoIWlzRmluaXRlKG1zW2ldKSlcblx0XHRcdFx0XHRtc1tpXSA9IDA7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0bXNbbiAtIDFdID0gZHNbbiAtIDJdO1xuXG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBuIC0gMTsgaSsrKSB7XG5cdFx0XHRiZXppZXJDdXJ2ZVRvKFxuXHRcdFx0XHRwYXRoLFxuXHRcdFx0XHR4c1tpXSArIGR4c1tpXSAvIDMsXG5cdFx0XHRcdHlzW2ldICsgbXNbaV0gKiBkeHNbaV0gLyAzLFxuXHRcdFx0XHR4c1tpICsgMV0gLSBkeHNbaV0gLyAzLFxuXHRcdFx0XHR5c1tpICsgMV0gLSBtc1tpICsgMV0gKiBkeHNbaV0gLyAzLFxuXHRcdFx0XHR4c1tpICsgMV0sXG5cdFx0XHRcdHlzW2kgKyAxXSxcblx0XHRcdCk7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIHBhdGg7XG59XG5cbmNvbnN0IGN1cnNvclBsb3RzID0gbmV3IFNldCgpO1xuXG5mdW5jdGlvbiBpbnZhbGlkYXRlUmVjdHMoKSB7XG5cdGN1cnNvclBsb3RzLmZvckVhY2godSA9PiB7XG5cdFx0dS5zeW5jUmVjdCh0cnVlKTtcblx0fSk7XG59XG5cbmlmIChkb21FbnYpIHtcblx0b24ocmVzaXplLCB3aW4sIGludmFsaWRhdGVSZWN0cyk7XG5cdG9uKHNjcm9sbCwgd2luLCBpbnZhbGlkYXRlUmVjdHMsIHRydWUpO1xuXHRvbihkcHB4Y2hhbmdlLCB3aW4sICgpID0+IHsgdVBsb3QucHhSYXRpbyA9IHB4UmF0aW87IH0pO1xufVxuXG5jb25zdCBsaW5lYXJQYXRoID0gbGluZWFyKCkgO1xuY29uc3QgcG9pbnRzUGF0aCA9IHBvaW50cygpIDtcblxuZnVuY3Rpb24gc2V0RGVmYXVsdHMoZCwgeG8sIHlvLCBpbml0WSkge1xuXHRsZXQgZDIgPSBpbml0WSA/IFtkWzBdLCBkWzFdXS5jb25jYXQoZC5zbGljZSgyKSkgOiBbZFswXV0uY29uY2F0KGQuc2xpY2UoMSkpO1xuXHRyZXR1cm4gZDIubWFwKChvLCBpKSA9PiBzZXREZWZhdWx0KG8sIGksIHhvLCB5bykpO1xufVxuXG5mdW5jdGlvbiBzZXREZWZhdWx0czIoZCwgeHlvKSB7XG5cdHJldHVybiBkLm1hcCgobywgaSkgPT4gaSA9PSAwID8gbnVsbCA6IGFzc2lnbih7fSwgeHlvLCBvKSk7ICAvLyB0b2RvOiBhc3NpZ24oKSB3aWxsIG5vdCBtZXJnZSBmYWNldCBhcnJheXNcbn1cblxuZnVuY3Rpb24gc2V0RGVmYXVsdChvLCBpLCB4bywgeW8pIHtcblx0cmV0dXJuIGFzc2lnbih7fSwgKGkgPT0gMCA/IHhvIDogeW8pLCBvKTtcbn1cblxuZnVuY3Rpb24gc25hcE51bVgoc2VsZiwgZGF0YU1pbiwgZGF0YU1heCkge1xuXHRyZXR1cm4gZGF0YU1pbiA9PSBudWxsID8gbnVsbE51bGxUdXBsZSA6IFtkYXRhTWluLCBkYXRhTWF4XTtcbn1cblxuY29uc3Qgc25hcFRpbWVYID0gc25hcE51bVg7XG5cbi8vIHRoaXMgZW5zdXJlcyB0aGF0IG5vbi10ZW1wb3JhbC9udW1lcmljIHktYXhlcyBnZXQgbXVsdGlwbGUtc25hcHBlZCBwYWRkaW5nIGFkZGVkIGFib3ZlL2JlbG93XG4vLyBUT0RPOiBhbHNvIGFjY291bnQgZm9yIGluY3JzIHdoZW4gc25hcHBpbmcgdG8gZW5zdXJlIHRvcCBvZiBheGlzIGdldHMgYSB0aWNrICYgdmFsdWVcbmZ1bmN0aW9uIHNuYXBOdW1ZKHNlbGYsIGRhdGFNaW4sIGRhdGFNYXgpIHtcblx0cmV0dXJuIGRhdGFNaW4gPT0gbnVsbCA/IG51bGxOdWxsVHVwbGUgOiByYW5nZU51bShkYXRhTWluLCBkYXRhTWF4LCByYW5nZVBhZCwgdHJ1ZSk7XG59XG5cbmZ1bmN0aW9uIHNuYXBMb2dZKHNlbGYsIGRhdGFNaW4sIGRhdGFNYXgsIHNjYWxlKSB7XG5cdHJldHVybiBkYXRhTWluID09IG51bGwgPyBudWxsTnVsbFR1cGxlIDogcmFuZ2VMb2coZGF0YU1pbiwgZGF0YU1heCwgc2VsZi5zY2FsZXNbc2NhbGVdLmxvZywgZmFsc2UpO1xufVxuXG5jb25zdCBzbmFwTG9nWCA9IHNuYXBMb2dZO1xuXG5mdW5jdGlvbiBzbmFwQXNpbmhZKHNlbGYsIGRhdGFNaW4sIGRhdGFNYXgsIHNjYWxlKSB7XG5cdHJldHVybiBkYXRhTWluID09IG51bGwgPyBudWxsTnVsbFR1cGxlIDogcmFuZ2VBc2luaChkYXRhTWluLCBkYXRhTWF4LCBzZWxmLnNjYWxlc1tzY2FsZV0ubG9nLCBmYWxzZSk7XG59XG5cbmNvbnN0IHNuYXBBc2luaFggPSBzbmFwQXNpbmhZO1xuXG4vLyBkaW0gaXMgbG9naWNhbCAoZ2V0Q2xpZW50Qm91bmRpbmdSZWN0KSBwaXhlbHMsIG5vdCBjYW52YXMgcGl4ZWxzXG5mdW5jdGlvbiBmaW5kSW5jcihtaW5WYWwsIG1heFZhbCwgaW5jcnMsIGRpbSwgbWluU3BhY2UpIHtcblx0bGV0IGludERpZ2l0cyA9IG1heChudW1JbnREaWdpdHMobWluVmFsKSwgbnVtSW50RGlnaXRzKG1heFZhbCkpO1xuXG5cdGxldCBkZWx0YSA9IG1heFZhbCAtIG1pblZhbDtcblxuXHRsZXQgaW5jcklkeCA9IGNsb3Nlc3RJZHgoKG1pblNwYWNlIC8gZGltKSAqIGRlbHRhLCBpbmNycyk7XG5cblx0ZG8ge1xuXHRcdGxldCBmb3VuZEluY3IgPSBpbmNyc1tpbmNySWR4XTtcblx0XHRsZXQgZm91bmRTcGFjZSA9IGRpbSAqIGZvdW5kSW5jciAvIGRlbHRhO1xuXG5cdFx0aWYgKGZvdW5kU3BhY2UgPj0gbWluU3BhY2UgJiYgaW50RGlnaXRzICsgKGZvdW5kSW5jciA8IDUgPyBmaXhlZERlYy5nZXQoZm91bmRJbmNyKSA6IDApIDw9IDE3KVxuXHRcdFx0cmV0dXJuIFtmb3VuZEluY3IsIGZvdW5kU3BhY2VdO1xuXHR9IHdoaWxlICgrK2luY3JJZHggPCBpbmNycy5sZW5ndGgpO1xuXG5cdHJldHVybiBbMCwgMF07XG59XG5cbmZ1bmN0aW9uIHB4UmF0aW9Gb250KGZvbnQpIHtcblx0bGV0IGZvbnRTaXplLCBmb250U2l6ZUNzcztcblx0Zm9udCA9IGZvbnQucmVwbGFjZSgvKFxcZCspcHgvLCAobSwgcDEpID0+IChmb250U2l6ZSA9IHJvdW5kKChmb250U2l6ZUNzcyA9ICtwMSkgKiBweFJhdGlvKSkgKyAncHgnKTtcblx0cmV0dXJuIFtmb250LCBmb250U2l6ZSwgZm9udFNpemVDc3NdO1xufVxuXG5mdW5jdGlvbiBzeW5jRm9udFNpemUoYXhpcykge1xuXHRpZiAoYXhpcy5zaG93KSB7XG5cdFx0W2F4aXMuZm9udCwgYXhpcy5sYWJlbEZvbnRdLmZvckVhY2goZiA9PiB7XG5cdFx0XHRsZXQgc2l6ZSA9IHJvdW5kRGVjKGZbMl0gKiBweFJhdGlvLCAxKTtcblx0XHRcdGZbMF0gPSBmWzBdLnJlcGxhY2UoL1swLTkuXStweC8sIHNpemUgKyAncHgnKTtcblx0XHRcdGZbMV0gPSBzaXplO1xuXHRcdH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHVQbG90KG9wdHMsIGRhdGEsIHRoZW4pIHtcblx0Y29uc3Qgc2VsZiA9IHtcblx0XHRtb2RlOiBpZk51bGwob3B0cy5tb2RlLCAxKSxcblx0fTtcblxuXHRjb25zdCBtb2RlID0gc2VsZi5tb2RlO1xuXG5cdC8vIFRPRE86IGNhY2hlIGRlbm9tcyAmIG1pbnMgc2NhbGUuY2FjaGUgPSB7ciwgbWluLCB9XG5cdGZ1bmN0aW9uIGdldFZhbFBjdCh2YWwsIHNjYWxlKSB7XG5cdFx0bGV0IF92YWwgPSAoXG5cdFx0XHRzY2FsZS5kaXN0ciA9PSAzID8gbG9nMTAodmFsID4gMCA/IHZhbCA6IHNjYWxlLmNsYW1wKHNlbGYsIHZhbCwgc2NhbGUubWluLCBzY2FsZS5tYXgsIHNjYWxlLmtleSkpIDpcblx0XHRcdHNjYWxlLmRpc3RyID09IDQgPyBhc2luaCh2YWwsIHNjYWxlLmFzaW5oKSA6XG5cdFx0XHR2YWxcblx0XHQpO1xuXG5cdFx0cmV0dXJuIChfdmFsIC0gc2NhbGUuX21pbikgLyAoc2NhbGUuX21heCAtIHNjYWxlLl9taW4pO1xuXHR9XG5cblx0ZnVuY3Rpb24gZ2V0SFBvcyh2YWwsIHNjYWxlLCBkaW0sIG9mZikge1xuXHRcdGxldCBwY3QgPSBnZXRWYWxQY3QodmFsLCBzY2FsZSk7XG5cdFx0cmV0dXJuIG9mZiArIGRpbSAqIChzY2FsZS5kaXIgPT0gLTEgPyAoMSAtIHBjdCkgOiBwY3QpO1xuXHR9XG5cblx0ZnVuY3Rpb24gZ2V0VlBvcyh2YWwsIHNjYWxlLCBkaW0sIG9mZikge1xuXHRcdGxldCBwY3QgPSBnZXRWYWxQY3QodmFsLCBzY2FsZSk7XG5cdFx0cmV0dXJuIG9mZiArIGRpbSAqIChzY2FsZS5kaXIgPT0gLTEgPyBwY3QgOiAoMSAtIHBjdCkpO1xuXHR9XG5cblx0ZnVuY3Rpb24gZ2V0UG9zKHZhbCwgc2NhbGUsIGRpbSwgb2ZmKSB7XG5cdFx0cmV0dXJuIHNjYWxlLm9yaSA9PSAwID8gZ2V0SFBvcyh2YWwsIHNjYWxlLCBkaW0sIG9mZikgOiBnZXRWUG9zKHZhbCwgc2NhbGUsIGRpbSwgb2ZmKTtcblx0fVxuXG5cdHNlbGYudmFsVG9Qb3NIID0gZ2V0SFBvcztcblx0c2VsZi52YWxUb1Bvc1YgPSBnZXRWUG9zO1xuXG5cdGxldCByZWFkeSA9IGZhbHNlO1xuXHRzZWxmLnN0YXR1cyA9IDA7XG5cblx0Y29uc3Qgcm9vdCA9IHNlbGYucm9vdCA9IHBsYWNlRGl2KFVQTE9UKTtcblxuXHRpZiAob3B0cy5pZCAhPSBudWxsKVxuXHRcdHJvb3QuaWQgPSBvcHRzLmlkO1xuXG5cdGFkZENsYXNzKHJvb3QsIG9wdHMuY2xhc3MpO1xuXG5cdGlmIChvcHRzLnRpdGxlKSB7XG5cdFx0bGV0IHRpdGxlID0gcGxhY2VEaXYoVElUTEUsIHJvb3QpO1xuXHRcdHRpdGxlLnRleHRDb250ZW50ID0gb3B0cy50aXRsZTtcblx0fVxuXG5cdGNvbnN0IGNhbiA9IHBsYWNlVGFnKFwiY2FudmFzXCIpO1xuXHRjb25zdCBjdHggPSBzZWxmLmN0eCA9IGNhbi5nZXRDb250ZXh0KFwiMmRcIik7XG5cblx0Y29uc3Qgd3JhcCA9IHBsYWNlRGl2KFdSQVAsIHJvb3QpO1xuXHRjb25zdCB1bmRlciA9IHNlbGYudW5kZXIgPSBwbGFjZURpdihVTkRFUiwgd3JhcCk7XG5cdHdyYXAuYXBwZW5kQ2hpbGQoY2FuKTtcblx0Y29uc3Qgb3ZlciA9IHNlbGYub3ZlciA9IHBsYWNlRGl2KE9WRVIsIHdyYXApO1xuXG5cdG9wdHMgPSBjb3B5KG9wdHMpO1xuXG5cdGNvbnN0IHB4QWxpZ24gPSAraWZOdWxsKG9wdHMucHhBbGlnbiwgMSk7XG5cblx0Y29uc3QgcHhSb3VuZCA9IHB4Um91bmRHZW4ocHhBbGlnbik7XG5cblx0KG9wdHMucGx1Z2lucyB8fCBbXSkuZm9yRWFjaChwID0+IHtcblx0XHRpZiAocC5vcHRzKVxuXHRcdFx0b3B0cyA9IHAub3B0cyhzZWxmLCBvcHRzKSB8fCBvcHRzO1xuXHR9KTtcblxuXHRjb25zdCBtcyA9IG9wdHMubXMgfHwgMWUtMztcblxuXHRjb25zdCBzZXJpZXMgID0gc2VsZi5zZXJpZXMgPSBtb2RlID09IDEgP1xuXHRcdHNldERlZmF1bHRzKG9wdHMuc2VyaWVzIHx8IFtdLCB4U2VyaWVzT3B0cywgeVNlcmllc09wdHMsIGZhbHNlKSA6XG5cdFx0c2V0RGVmYXVsdHMyKG9wdHMuc2VyaWVzIHx8IFtudWxsXSwgeHlTZXJpZXNPcHRzKTtcblx0Y29uc3QgYXhlcyAgICA9IHNlbGYuYXhlcyAgID0gc2V0RGVmYXVsdHMob3B0cy5heGVzICAgfHwgW10sIHhBeGlzT3B0cywgICB5QXhpc09wdHMsICAgIHRydWUpO1xuXHRjb25zdCBzY2FsZXMgID0gc2VsZi5zY2FsZXMgPSB7fTtcblx0Y29uc3QgYmFuZHMgICA9IHNlbGYuYmFuZHMgID0gb3B0cy5iYW5kcyB8fCBbXTtcblxuXHRiYW5kcy5mb3JFYWNoKGIgPT4ge1xuXHRcdGIuZmlsbCA9IGZuT3JTZWxmKGIuZmlsbCB8fCBudWxsKTtcblx0XHRiLmRpciA9IGlmTnVsbChiLmRpciwgLTEpO1xuXHR9KTtcblxuXHRjb25zdCB4U2NhbGVLZXkgPSBtb2RlID09IDIgPyBzZXJpZXNbMV0uZmFjZXRzWzBdLnNjYWxlIDogc2VyaWVzWzBdLnNjYWxlO1xuXG5cdGNvbnN0IGRyYXdPcmRlck1hcCA9IHtcblx0XHRheGVzOiBkcmF3QXhlc0dyaWQsXG5cdFx0c2VyaWVzOiBkcmF3U2VyaWVzLFxuXHR9O1xuXG5cdGNvbnN0IGRyYXdPcmRlciA9IChvcHRzLmRyYXdPcmRlciB8fCBbXCJheGVzXCIsIFwic2VyaWVzXCJdKS5tYXAoa2V5ID0+IGRyYXdPcmRlck1hcFtrZXldKTtcblxuXHRmdW5jdGlvbiBpbml0U2NhbGUoc2NhbGVLZXkpIHtcblx0XHRsZXQgc2MgPSBzY2FsZXNbc2NhbGVLZXldO1xuXG5cdFx0aWYgKHNjID09IG51bGwpIHtcblx0XHRcdGxldCBzY2FsZU9wdHMgPSAob3B0cy5zY2FsZXMgfHwgRU1QVFlfT0JKKVtzY2FsZUtleV0gfHwgRU1QVFlfT0JKO1xuXG5cdFx0XHRpZiAoc2NhbGVPcHRzLmZyb20gIT0gbnVsbCkge1xuXHRcdFx0XHQvLyBlbnN1cmUgcGFyZW50IGlzIGluaXRpYWxpemVkXG5cdFx0XHRcdGluaXRTY2FsZShzY2FsZU9wdHMuZnJvbSk7XG5cdFx0XHRcdC8vIGRlcGVuZGVudCBzY2FsZXMgaW5oZXJpdFxuXHRcdFx0XHRzY2FsZXNbc2NhbGVLZXldID0gYXNzaWduKHt9LCBzY2FsZXNbc2NhbGVPcHRzLmZyb21dLCBzY2FsZU9wdHMsIHtrZXk6IHNjYWxlS2V5fSk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0c2MgPSBzY2FsZXNbc2NhbGVLZXldID0gYXNzaWduKHt9LCAoc2NhbGVLZXkgPT0geFNjYWxlS2V5ID8geFNjYWxlT3B0cyA6IHlTY2FsZU9wdHMpLCBzY2FsZU9wdHMpO1xuXG5cdFx0XHRcdHNjLmtleSA9IHNjYWxlS2V5O1xuXG5cdFx0XHRcdGxldCBpc1RpbWUgPSBzYy50aW1lO1xuXG5cdFx0XHRcdGxldCBybiA9IHNjLnJhbmdlO1xuXG5cdFx0XHRcdGxldCByYW5nZUlzQXJyID0gaXNBcnIocm4pO1xuXG5cdFx0XHRcdGlmIChzY2FsZUtleSAhPSB4U2NhbGVLZXkgfHwgKG1vZGUgPT0gMiAmJiAhaXNUaW1lKSkge1xuXHRcdFx0XHRcdC8vIGlmIHJhbmdlIGFycmF5IGhhcyBudWxsIGxpbWl0cywgaXQgc2hvdWxkIGJlIGF1dG9cblx0XHRcdFx0XHRpZiAocmFuZ2VJc0FyciAmJiAocm5bMF0gPT0gbnVsbCB8fCByblsxXSA9PSBudWxsKSkge1xuXHRcdFx0XHRcdFx0cm4gPSB7XG5cdFx0XHRcdFx0XHRcdG1pbjogcm5bMF0gPT0gbnVsbCA/IGF1dG9SYW5nZVBhcnQgOiB7XG5cdFx0XHRcdFx0XHRcdFx0bW9kZTogMSxcblx0XHRcdFx0XHRcdFx0XHRoYXJkOiByblswXSxcblx0XHRcdFx0XHRcdFx0XHRzb2Z0OiByblswXSxcblx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdFx0bWF4OiByblsxXSA9PSBudWxsID8gYXV0b1JhbmdlUGFydCA6IHtcblx0XHRcdFx0XHRcdFx0XHRtb2RlOiAxLFxuXHRcdFx0XHRcdFx0XHRcdGhhcmQ6IHJuWzFdLFxuXHRcdFx0XHRcdFx0XHRcdHNvZnQ6IHJuWzFdLFxuXHRcdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0fTtcblx0XHRcdFx0XHRcdHJhbmdlSXNBcnIgPSBmYWxzZTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoIXJhbmdlSXNBcnIgJiYgaXNPYmoocm4pKSB7XG5cdFx0XHRcdFx0XHRsZXQgY2ZnID0gcm47XG5cdFx0XHRcdFx0XHQvLyB0aGlzIGlzIHNpbWlsYXIgdG8gc25hcE51bVlcblx0XHRcdFx0XHRcdHJuID0gKHNlbGYsIGRhdGFNaW4sIGRhdGFNYXgpID0+IGRhdGFNaW4gPT0gbnVsbCA/IG51bGxOdWxsVHVwbGUgOiByYW5nZU51bShkYXRhTWluLCBkYXRhTWF4LCBjZmcpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdHNjLnJhbmdlID0gZm5PclNlbGYocm4gfHwgKGlzVGltZSA/IHNuYXBUaW1lWCA6IHNjYWxlS2V5ID09IHhTY2FsZUtleSA/XG5cdFx0XHRcdFx0KHNjLmRpc3RyID09IDMgPyBzbmFwTG9nWCA6IHNjLmRpc3RyID09IDQgPyBzbmFwQXNpbmhYIDogc25hcE51bVgpIDpcblx0XHRcdFx0XHQoc2MuZGlzdHIgPT0gMyA/IHNuYXBMb2dZIDogc2MuZGlzdHIgPT0gNCA/IHNuYXBBc2luaFkgOiBzbmFwTnVtWSlcblx0XHRcdFx0KSk7XG5cblx0XHRcdFx0c2MuYXV0byA9IGZuT3JTZWxmKHJhbmdlSXNBcnIgPyBmYWxzZSA6IHNjLmF1dG8pO1xuXG5cdFx0XHRcdHNjLmNsYW1wID0gZm5PclNlbGYoc2MuY2xhbXAgfHwgY2xhbXBTY2FsZSk7XG5cblx0XHRcdFx0Ly8gY2FjaGVzIGZvciBleHBlbnNpdmUgb3BzIGxpa2UgYXNpbmgoKSAmIGxvZygpXG5cdFx0XHRcdHNjLl9taW4gPSBzYy5fbWF4ID0gbnVsbDtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRpbml0U2NhbGUoXCJ4XCIpO1xuXHRpbml0U2NhbGUoXCJ5XCIpO1xuXG5cdC8vIFRPRE86IGluaXQgc2NhbGVzIGZyb20gZmFjZXRzIGluIG1vZGU6IDJcblx0aWYgKG1vZGUgPT0gMSkge1xuXHRcdHNlcmllcy5mb3JFYWNoKHMgPT4ge1xuXHRcdFx0aW5pdFNjYWxlKHMuc2NhbGUpO1xuXHRcdH0pO1xuXHR9XG5cblx0YXhlcy5mb3JFYWNoKGEgPT4ge1xuXHRcdGluaXRTY2FsZShhLnNjYWxlKTtcblx0fSk7XG5cblx0Zm9yIChsZXQgayBpbiBvcHRzLnNjYWxlcylcblx0XHRpbml0U2NhbGUoayk7XG5cblx0Y29uc3Qgc2NhbGVYID0gc2NhbGVzW3hTY2FsZUtleV07XG5cblx0Y29uc3QgeFNjYWxlRGlzdHIgPSBzY2FsZVguZGlzdHI7XG5cblx0bGV0IHZhbFRvUG9zWCwgdmFsVG9Qb3NZO1xuXG5cdGlmIChzY2FsZVgub3JpID09IDApIHtcblx0XHRhZGRDbGFzcyhyb290LCBPUklfSFopO1xuXHRcdHZhbFRvUG9zWCA9IGdldEhQb3M7XG5cdFx0dmFsVG9Qb3NZID0gZ2V0VlBvcztcblx0XHQvKlxuXHRcdHVwZE9yaURpbXMgPSAoKSA9PiB7XG5cdFx0XHR4RGltQ2FuID0gcGxvdFdpZDtcblx0XHRcdHhPZmZDYW4gPSBwbG90TGZ0O1xuXHRcdFx0eURpbUNhbiA9IHBsb3RIZ3Q7XG5cdFx0XHR5T2ZmQ2FuID0gcGxvdFRvcDtcblxuXHRcdFx0eERpbUNzcyA9IHBsb3RXaWRDc3M7XG5cdFx0XHR4T2ZmQ3NzID0gcGxvdExmdENzcztcblx0XHRcdHlEaW1Dc3MgPSBwbG90SGd0Q3NzO1xuXHRcdFx0eU9mZkNzcyA9IHBsb3RUb3BDc3M7XG5cdFx0fTtcblx0XHQqL1xuXHR9XG5cdGVsc2Uge1xuXHRcdGFkZENsYXNzKHJvb3QsIE9SSV9WVCk7XG5cdFx0dmFsVG9Qb3NYID0gZ2V0VlBvcztcblx0XHR2YWxUb1Bvc1kgPSBnZXRIUG9zO1xuXHRcdC8qXG5cdFx0dXBkT3JpRGltcyA9ICgpID0+IHtcblx0XHRcdHhEaW1DYW4gPSBwbG90SGd0O1xuXHRcdFx0eE9mZkNhbiA9IHBsb3RUb3A7XG5cdFx0XHR5RGltQ2FuID0gcGxvdFdpZDtcblx0XHRcdHlPZmZDYW4gPSBwbG90TGZ0O1xuXG5cdFx0XHR4RGltQ3NzID0gcGxvdEhndENzcztcblx0XHRcdHhPZmZDc3MgPSBwbG90VG9wQ3NzO1xuXHRcdFx0eURpbUNzcyA9IHBsb3RXaWRDc3M7XG5cdFx0XHR5T2ZmQ3NzID0gcGxvdExmdENzcztcblx0XHR9O1xuXHRcdCovXG5cdH1cblxuXHRjb25zdCBwZW5kU2NhbGVzID0ge307XG5cblx0Ly8gZXhwbGljaXRseS1zZXQgaW5pdGlhbCBzY2FsZXNcblx0Zm9yIChsZXQgayBpbiBzY2FsZXMpIHtcblx0XHRsZXQgc2MgPSBzY2FsZXNba107XG5cblx0XHRpZiAoc2MubWluICE9IG51bGwgfHwgc2MubWF4ICE9IG51bGwpIHtcblx0XHRcdHBlbmRTY2FsZXNba10gPSB7bWluOiBzYy5taW4sIG1heDogc2MubWF4fTtcblx0XHRcdHNjLm1pbiA9IHNjLm1heCA9IG51bGw7XG5cdFx0fVxuXHR9XG5cbi8vXHRzZWxmLnR6ID0gb3B0cy50eiB8fCBJbnRsLkRhdGVUaW1lRm9ybWF0KCkucmVzb2x2ZWRPcHRpb25zKCkudGltZVpvbmU7XG5cdGNvbnN0IF90ekRhdGUgID0gKG9wdHMudHpEYXRlIHx8ICh0cyA9PiBuZXcgRGF0ZShyb3VuZCh0cyAvIG1zKSkpKTtcblx0Y29uc3QgX2ZtdERhdGUgPSAob3B0cy5mbXREYXRlIHx8IGZtdERhdGUpO1xuXG5cdGNvbnN0IF90aW1lQXhpc1NwbGl0cyA9IChtcyA9PSAxID8gdGltZUF4aXNTcGxpdHNNcyhfdHpEYXRlKSA6IHRpbWVBeGlzU3BsaXRzUyhfdHpEYXRlKSk7XG5cdGNvbnN0IF90aW1lQXhpc1ZhbHMgICA9IHRpbWVBeGlzVmFscyhfdHpEYXRlLCB0aW1lQXhpc1N0YW1wcygobXMgPT0gMSA/IF90aW1lQXhpc1N0YW1wc01zIDogX3RpbWVBeGlzU3RhbXBzUyksIF9mbXREYXRlKSk7XG5cdGNvbnN0IF90aW1lU2VyaWVzVmFsICA9IHRpbWVTZXJpZXNWYWwoX3R6RGF0ZSwgdGltZVNlcmllc1N0YW1wKF90aW1lU2VyaWVzU3RhbXAsIF9mbXREYXRlKSk7XG5cblx0Y29uc3QgYWN0aXZlSWR4cyA9IFtdO1xuXG5cdGNvbnN0IGxlZ2VuZCAgICAgPSAoc2VsZi5sZWdlbmQgPSBhc3NpZ24oe30sIGxlZ2VuZE9wdHMsIG9wdHMubGVnZW5kKSk7XG5cdGNvbnN0IHNob3dMZWdlbmQgPSBsZWdlbmQuc2hvdztcblx0Y29uc3QgbWFya2VycyAgICA9IGxlZ2VuZC5tYXJrZXJzO1xuXG5cdHtcblx0XHRsZWdlbmQuaWR4cyA9IGFjdGl2ZUlkeHM7XG5cblx0XHRtYXJrZXJzLndpZHRoICA9IGZuT3JTZWxmKG1hcmtlcnMud2lkdGgpO1xuXHRcdG1hcmtlcnMuZGFzaCAgID0gZm5PclNlbGYobWFya2Vycy5kYXNoKTtcblx0XHRtYXJrZXJzLnN0cm9rZSA9IGZuT3JTZWxmKG1hcmtlcnMuc3Ryb2tlKTtcblx0XHRtYXJrZXJzLmZpbGwgICA9IGZuT3JTZWxmKG1hcmtlcnMuZmlsbCk7XG5cdH1cblxuXHRsZXQgbGVnZW5kRWw7XG5cdGxldCBsZWdlbmRSb3dzID0gW107XG5cdGxldCBsZWdlbmRDZWxscyA9IFtdO1xuXHRsZXQgbGVnZW5kQ29scztcblx0bGV0IG11bHRpVmFsTGVnZW5kID0gZmFsc2U7XG5cdGxldCBOVUxMX0xFR0VORF9WQUxVRVMgPSB7fTtcblxuXHRpZiAobGVnZW5kLmxpdmUpIHtcblx0XHRjb25zdCBnZXRNdWx0aVZhbHMgPSBzZXJpZXNbMV0gPyBzZXJpZXNbMV0udmFsdWVzIDogbnVsbDtcblx0XHRtdWx0aVZhbExlZ2VuZCA9IGdldE11bHRpVmFscyAhPSBudWxsO1xuXHRcdGxlZ2VuZENvbHMgPSBtdWx0aVZhbExlZ2VuZCA/IGdldE11bHRpVmFscyhzZWxmLCAxLCAwKSA6IHtfOiAwfTtcblxuXHRcdGZvciAobGV0IGsgaW4gbGVnZW5kQ29scylcblx0XHRcdE5VTExfTEVHRU5EX1ZBTFVFU1trXSA9IFwiLS1cIjtcblx0fVxuXG5cdGlmIChzaG93TGVnZW5kKSB7XG5cdFx0bGVnZW5kRWwgPSBwbGFjZVRhZyhcInRhYmxlXCIsIExFR0VORCwgcm9vdCk7XG5cblx0XHRpZiAobXVsdGlWYWxMZWdlbmQpIHtcblx0XHRcdGxldCBoZWFkID0gcGxhY2VUYWcoXCJ0clwiLCBMRUdFTkRfVEhFQUQsIGxlZ2VuZEVsKTtcblx0XHRcdHBsYWNlVGFnKFwidGhcIiwgbnVsbCwgaGVhZCk7XG5cblx0XHRcdGZvciAodmFyIGtleSBpbiBsZWdlbmRDb2xzKVxuXHRcdFx0XHRwbGFjZVRhZyhcInRoXCIsIExFR0VORF9MQUJFTCwgaGVhZCkudGV4dENvbnRlbnQgPSBrZXk7XG5cdFx0fVxuXHRcdGVsc2Uge1xuXHRcdFx0YWRkQ2xhc3MobGVnZW5kRWwsIExFR0VORF9JTkxJTkUpO1xuXHRcdFx0bGVnZW5kLmxpdmUgJiYgYWRkQ2xhc3MobGVnZW5kRWwsIExFR0VORF9MSVZFKTtcblx0XHR9XG5cdH1cblxuXHRjb25zdCBzb24gID0ge3Nob3c6IHRydWV9O1xuXHRjb25zdCBzb2ZmID0ge3Nob3c6IGZhbHNlfTtcblxuXHRmdW5jdGlvbiBpbml0TGVnZW5kUm93KHMsIGkpIHtcblx0XHRpZiAoaSA9PSAwICYmIChtdWx0aVZhbExlZ2VuZCB8fCAhbGVnZW5kLmxpdmUgfHwgbW9kZSA9PSAyKSlcblx0XHRcdHJldHVybiBudWxsTnVsbFR1cGxlO1xuXG5cdFx0bGV0IGNlbGxzID0gW107XG5cblx0XHRsZXQgcm93ID0gcGxhY2VUYWcoXCJ0clwiLCBMRUdFTkRfU0VSSUVTLCBsZWdlbmRFbCwgbGVnZW5kRWwuY2hpbGROb2Rlc1tpXSk7XG5cblx0XHRhZGRDbGFzcyhyb3csIHMuY2xhc3MpO1xuXG5cdFx0aWYgKCFzLnNob3cpXG5cdFx0XHRhZGRDbGFzcyhyb3csIE9GRik7XG5cblx0XHRsZXQgbGFiZWwgPSBwbGFjZVRhZyhcInRoXCIsIG51bGwsIHJvdyk7XG5cblx0XHRpZiAobWFya2Vycy5zaG93KSB7XG5cdFx0XHRsZXQgaW5kaWMgPSBwbGFjZURpdihMRUdFTkRfTUFSS0VSLCBsYWJlbCk7XG5cblx0XHRcdGlmIChpID4gMCkge1xuXHRcdFx0XHRsZXQgd2lkdGggID0gbWFya2Vycy53aWR0aChzZWxmLCBpKTtcblxuXHRcdFx0XHRpZiAod2lkdGgpXG5cdFx0XHRcdFx0aW5kaWMuc3R5bGUuYm9yZGVyID0gd2lkdGggKyBcInB4IFwiICsgbWFya2Vycy5kYXNoKHNlbGYsIGkpICsgXCIgXCIgKyBtYXJrZXJzLnN0cm9rZShzZWxmLCBpKTtcblxuXHRcdFx0XHRpbmRpYy5zdHlsZS5iYWNrZ3JvdW5kID0gbWFya2Vycy5maWxsKHNlbGYsIGkpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGxldCB0ZXh0ID0gcGxhY2VEaXYoTEVHRU5EX0xBQkVMLCBsYWJlbCk7XG5cdFx0dGV4dC50ZXh0Q29udGVudCA9IHMubGFiZWw7XG5cblx0XHRpZiAoaSA+IDApIHtcblx0XHRcdGlmICghbWFya2Vycy5zaG93KVxuXHRcdFx0XHR0ZXh0LnN0eWxlLmNvbG9yID0gcy53aWR0aCA+IDAgPyBtYXJrZXJzLnN0cm9rZShzZWxmLCBpKSA6IG1hcmtlcnMuZmlsbChzZWxmLCBpKTtcblxuXHRcdFx0b25Nb3VzZShcImNsaWNrXCIsIGxhYmVsLCBlID0+IHtcblx0XHRcdFx0aWYgKGN1cnNvci5fbG9jaylcblx0XHRcdFx0XHRyZXR1cm47XG5cblx0XHRcdFx0bGV0IHNlcmllc0lkeCA9IHNlcmllcy5pbmRleE9mKHMpO1xuXG5cdFx0XHRcdGlmICgoZS5jdHJsS2V5IHx8IGUubWV0YUtleSkgIT0gbGVnZW5kLmlzb2xhdGUpIHtcblx0XHRcdFx0XHQvLyBpZiBhbnkgb3RoZXIgc2VyaWVzIGlzIHNob3duLCBpc29sYXRlIHRoaXMgb25lLiBlbHNlIHNob3cgYWxsXG5cdFx0XHRcdFx0bGV0IGlzb2xhdGUgPSBzZXJpZXMuc29tZSgocywgaSkgPT4gaSA+IDAgJiYgaSAhPSBzZXJpZXNJZHggJiYgcy5zaG93KTtcblxuXHRcdFx0XHRcdHNlcmllcy5mb3JFYWNoKChzLCBpKSA9PiB7XG5cdFx0XHRcdFx0XHRpID4gMCAmJiBzZXRTZXJpZXMoaSwgaXNvbGF0ZSA/IChpID09IHNlcmllc0lkeCA/IHNvbiA6IHNvZmYpIDogc29uLCB0cnVlLCBzeW5jT3B0cy5zZXRTZXJpZXMpO1xuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHRzZXRTZXJpZXMoc2VyaWVzSWR4LCB7c2hvdzogIXMuc2hvd30sIHRydWUsIHN5bmNPcHRzLnNldFNlcmllcyk7XG5cdFx0XHR9KTtcblxuXHRcdFx0aWYgKGN1cnNvckZvY3VzKSB7XG5cdFx0XHRcdG9uTW91c2UobW91c2VlbnRlciwgbGFiZWwsIGUgPT4ge1xuXHRcdFx0XHRcdGlmIChjdXJzb3IuX2xvY2spXG5cdFx0XHRcdFx0XHRyZXR1cm47XG5cblx0XHRcdFx0XHRzZXRTZXJpZXMoc2VyaWVzLmluZGV4T2YocyksIEZPQ1VTX1RSVUUsIHRydWUsIHN5bmNPcHRzLnNldFNlcmllcyk7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGZvciAodmFyIGtleSBpbiBsZWdlbmRDb2xzKSB7XG5cdFx0XHRsZXQgdiA9IHBsYWNlVGFnKFwidGRcIiwgTEVHRU5EX1ZBTFVFLCByb3cpO1xuXHRcdFx0di50ZXh0Q29udGVudCA9IFwiLS1cIjtcblx0XHRcdGNlbGxzLnB1c2godik7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIFtyb3csIGNlbGxzXTtcblx0fVxuXG5cdGNvbnN0IG1vdXNlTGlzdGVuZXJzID0gbmV3IE1hcCgpO1xuXG5cdGZ1bmN0aW9uIG9uTW91c2UoZXYsIHRhcmcsIGZuKSB7XG5cdFx0Y29uc3QgdGFyZ0xpc3RlbmVycyA9IG1vdXNlTGlzdGVuZXJzLmdldCh0YXJnKSB8fCB7fTtcblx0XHRjb25zdCBsaXN0ZW5lciA9IGN1cnNvci5iaW5kW2V2XShzZWxmLCB0YXJnLCBmbik7XG5cblx0XHRpZiAobGlzdGVuZXIpIHtcblx0XHRcdG9uKGV2LCB0YXJnLCB0YXJnTGlzdGVuZXJzW2V2XSA9IGxpc3RlbmVyKTtcblx0XHRcdG1vdXNlTGlzdGVuZXJzLnNldCh0YXJnLCB0YXJnTGlzdGVuZXJzKTtcblx0XHR9XG5cdH1cblxuXHRmdW5jdGlvbiBvZmZNb3VzZShldiwgdGFyZywgZm4pIHtcblx0XHRjb25zdCB0YXJnTGlzdGVuZXJzID0gbW91c2VMaXN0ZW5lcnMuZ2V0KHRhcmcpIHx8IHt9O1xuXG5cdFx0Zm9yIChsZXQgayBpbiB0YXJnTGlzdGVuZXJzKSB7XG5cdFx0XHRpZiAoZXYgPT0gbnVsbCB8fCBrID09IGV2KSB7XG5cdFx0XHRcdG9mZihrLCB0YXJnLCB0YXJnTGlzdGVuZXJzW2tdKTtcblx0XHRcdFx0ZGVsZXRlIHRhcmdMaXN0ZW5lcnNba107XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKGV2ID09IG51bGwpXG5cdFx0XHRtb3VzZUxpc3RlbmVycy5kZWxldGUodGFyZyk7XG5cdH1cblxuXHRsZXQgZnVsbFdpZENzcyA9IDA7XG5cdGxldCBmdWxsSGd0Q3NzID0gMDtcblxuXHRsZXQgcGxvdFdpZENzcyA9IDA7XG5cdGxldCBwbG90SGd0Q3NzID0gMDtcblxuXHQvLyBwbG90IG1hcmdpbnMgdG8gYWNjb3VudCBmb3IgYXhlc1xuXHRsZXQgcGxvdExmdENzcyA9IDA7XG5cdGxldCBwbG90VG9wQ3NzID0gMDtcblxuXHRsZXQgcGxvdExmdCA9IDA7XG5cdGxldCBwbG90VG9wID0gMDtcblx0bGV0IHBsb3RXaWQgPSAwO1xuXHRsZXQgcGxvdEhndCA9IDA7XG5cblx0c2VsZi5iYm94ID0ge307XG5cblx0bGV0IHNob3VsZFNldFNjYWxlcyA9IGZhbHNlO1xuXHRsZXQgc2hvdWxkU2V0U2l6ZSA9IGZhbHNlO1xuXHRsZXQgc2hvdWxkQ29udmVyZ2VTaXplID0gZmFsc2U7XG5cdGxldCBzaG91bGRTZXRDdXJzb3IgPSBmYWxzZTtcblx0bGV0IHNob3VsZFNldExlZ2VuZCA9IGZhbHNlO1xuXG5cdGZ1bmN0aW9uIF9zZXRTaXplKHdpZHRoLCBoZWlnaHQsIGZvcmNlKSB7XG5cdFx0aWYgKGZvcmNlIHx8ICh3aWR0aCAhPSBzZWxmLndpZHRoIHx8IGhlaWdodCAhPSBzZWxmLmhlaWdodCkpXG5cdFx0XHRjYWxjU2l6ZSh3aWR0aCwgaGVpZ2h0KTtcblxuXHRcdHJlc2V0WVNlcmllcyhmYWxzZSk7XG5cblx0XHRzaG91bGRDb252ZXJnZVNpemUgPSB0cnVlO1xuXHRcdHNob3VsZFNldFNpemUgPSB0cnVlO1xuXHRcdHNob3VsZFNldEN1cnNvciA9IHNob3VsZFNldExlZ2VuZCA9IGN1cnNvci5sZWZ0ID49IDA7XG5cdFx0Y29tbWl0KCk7XG5cdH1cblxuXHRmdW5jdGlvbiBjYWxjU2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XG5cdC8vXHRsb2coXCJjYWxjU2l6ZSgpXCIsIGFyZ3VtZW50cyk7XG5cblx0XHRzZWxmLndpZHRoICA9IGZ1bGxXaWRDc3MgPSBwbG90V2lkQ3NzID0gd2lkdGg7XG5cdFx0c2VsZi5oZWlnaHQgPSBmdWxsSGd0Q3NzID0gcGxvdEhndENzcyA9IGhlaWdodDtcblx0XHRwbG90TGZ0Q3NzICA9IHBsb3RUb3BDc3MgPSAwO1xuXG5cdFx0Y2FsY1Bsb3RSZWN0KCk7XG5cdFx0Y2FsY0F4ZXNSZWN0cygpO1xuXG5cdFx0bGV0IGJiID0gc2VsZi5iYm94O1xuXG5cdFx0cGxvdExmdCA9IGJiLmxlZnQgICA9IGluY3JSb3VuZChwbG90TGZ0Q3NzICogcHhSYXRpbywgMC41KTtcblx0XHRwbG90VG9wID0gYmIudG9wICAgID0gaW5jclJvdW5kKHBsb3RUb3BDc3MgKiBweFJhdGlvLCAwLjUpO1xuXHRcdHBsb3RXaWQgPSBiYi53aWR0aCAgPSBpbmNyUm91bmQocGxvdFdpZENzcyAqIHB4UmF0aW8sIDAuNSk7XG5cdFx0cGxvdEhndCA9IGJiLmhlaWdodCA9IGluY3JSb3VuZChwbG90SGd0Q3NzICogcHhSYXRpbywgMC41KTtcblxuXHQvL1x0dXBkT3JpRGltcygpO1xuXHR9XG5cblx0Ly8gZW5zdXJlcyBzaXplIGNhbGMgY29udmVyZ2VuY2Vcblx0Y29uc3QgQ1lDTEVfTElNSVQgPSAzO1xuXG5cdGZ1bmN0aW9uIGNvbnZlcmdlU2l6ZSgpIHtcblx0XHRsZXQgY29udmVyZ2VkID0gZmFsc2U7XG5cblx0XHRsZXQgY3ljbGVOdW0gPSAwO1xuXG5cdFx0d2hpbGUgKCFjb252ZXJnZWQpIHtcblx0XHRcdGN5Y2xlTnVtKys7XG5cblx0XHRcdGxldCBheGVzQ29udmVyZ2VkID0gYXhlc0NhbGMoY3ljbGVOdW0pO1xuXHRcdFx0bGV0IHBhZGRpbmdDb252ZXJnZWQgPSBwYWRkaW5nQ2FsYyhjeWNsZU51bSk7XG5cblx0XHRcdGNvbnZlcmdlZCA9IGN5Y2xlTnVtID09IENZQ0xFX0xJTUlUIHx8IChheGVzQ29udmVyZ2VkICYmIHBhZGRpbmdDb252ZXJnZWQpO1xuXG5cdFx0XHRpZiAoIWNvbnZlcmdlZCkge1xuXHRcdFx0XHRjYWxjU2l6ZShzZWxmLndpZHRoLCBzZWxmLmhlaWdodCk7XG5cdFx0XHRcdHNob3VsZFNldFNpemUgPSB0cnVlO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdGZ1bmN0aW9uIHNldFNpemUoe3dpZHRoLCBoZWlnaHR9KSB7XG5cdFx0X3NldFNpemUod2lkdGgsIGhlaWdodCk7XG5cdH1cblxuXHRzZWxmLnNldFNpemUgPSBzZXRTaXplO1xuXG5cdC8vIGFjY3VtdWxhdGUgYXhpcyBvZmZzZXRzLCByZWR1Y2UgY2FudmFzIHdpZHRoXG5cdGZ1bmN0aW9uIGNhbGNQbG90UmVjdCgpIHtcblx0XHQvLyBlYXNlbWVudHMgZm9yIGVkZ2UgbGFiZWxzXG5cdFx0bGV0IGhhc1RvcEF4aXMgPSBmYWxzZTtcblx0XHRsZXQgaGFzQnRtQXhpcyA9IGZhbHNlO1xuXHRcdGxldCBoYXNSZ3RBeGlzID0gZmFsc2U7XG5cdFx0bGV0IGhhc0xmdEF4aXMgPSBmYWxzZTtcblxuXHRcdGF4ZXMuZm9yRWFjaCgoYXhpcywgaSkgPT4ge1xuXHRcdFx0aWYgKGF4aXMuc2hvdyAmJiBheGlzLl9zaG93KSB7XG5cdFx0XHRcdGxldCB7c2lkZSwgX3NpemV9ID0gYXhpcztcblx0XHRcdFx0bGV0IGlzVnQgPSBzaWRlICUgMjtcblx0XHRcdFx0bGV0IGxhYmVsU2l6ZSA9IGF4aXMubGFiZWwgIT0gbnVsbCA/IGF4aXMubGFiZWxTaXplIDogMDtcblxuXHRcdFx0XHRsZXQgZnVsbFNpemUgPSBfc2l6ZSArIGxhYmVsU2l6ZTtcblxuXHRcdFx0XHRpZiAoZnVsbFNpemUgPiAwKSB7XG5cdFx0XHRcdFx0aWYgKGlzVnQpIHtcblx0XHRcdFx0XHRcdHBsb3RXaWRDc3MgLT0gZnVsbFNpemU7XG5cblx0XHRcdFx0XHRcdGlmIChzaWRlID09IDMpIHtcblx0XHRcdFx0XHRcdFx0cGxvdExmdENzcyArPSBmdWxsU2l6ZTtcblx0XHRcdFx0XHRcdFx0aGFzTGZ0QXhpcyA9IHRydWU7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0XHRcdGhhc1JndEF4aXMgPSB0cnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHRcdHBsb3RIZ3RDc3MgLT0gZnVsbFNpemU7XG5cblx0XHRcdFx0XHRcdGlmIChzaWRlID09IDApIHtcblx0XHRcdFx0XHRcdFx0cGxvdFRvcENzcyArPSBmdWxsU2l6ZTtcblx0XHRcdFx0XHRcdFx0aGFzVG9wQXhpcyA9IHRydWU7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0XHRcdGhhc0J0bUF4aXMgPSB0cnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0c2lkZXNXaXRoQXhlc1swXSA9IGhhc1RvcEF4aXM7XG5cdFx0c2lkZXNXaXRoQXhlc1sxXSA9IGhhc1JndEF4aXM7XG5cdFx0c2lkZXNXaXRoQXhlc1syXSA9IGhhc0J0bUF4aXM7XG5cdFx0c2lkZXNXaXRoQXhlc1szXSA9IGhhc0xmdEF4aXM7XG5cblx0XHQvLyBoeiBwYWRkaW5nXG5cdFx0cGxvdFdpZENzcyAtPSBfcGFkZGluZ1sxXSArIF9wYWRkaW5nWzNdO1xuXHRcdHBsb3RMZnRDc3MgKz0gX3BhZGRpbmdbM107XG5cblx0XHQvLyB2dCBwYWRkaW5nXG5cdFx0cGxvdEhndENzcyAtPSBfcGFkZGluZ1syXSArIF9wYWRkaW5nWzBdO1xuXHRcdHBsb3RUb3BDc3MgKz0gX3BhZGRpbmdbMF07XG5cdH1cblxuXHRmdW5jdGlvbiBjYWxjQXhlc1JlY3RzKCkge1xuXHRcdC8vIHdpbGwgYWNjdW0gK1xuXHRcdGxldCBvZmYxID0gcGxvdExmdENzcyArIHBsb3RXaWRDc3M7XG5cdFx0bGV0IG9mZjIgPSBwbG90VG9wQ3NzICsgcGxvdEhndENzcztcblx0XHQvLyB3aWxsIGFjY3VtIC1cblx0XHRsZXQgb2ZmMyA9IHBsb3RMZnRDc3M7XG5cdFx0bGV0IG9mZjAgPSBwbG90VG9wQ3NzO1xuXG5cdFx0ZnVuY3Rpb24gaW5jck9mZnNldChzaWRlLCBzaXplKSB7XG5cdFx0XHRzd2l0Y2ggKHNpZGUpIHtcblx0XHRcdFx0Y2FzZSAxOiBvZmYxICs9IHNpemU7IHJldHVybiBvZmYxIC0gc2l6ZTtcblx0XHRcdFx0Y2FzZSAyOiBvZmYyICs9IHNpemU7IHJldHVybiBvZmYyIC0gc2l6ZTtcblx0XHRcdFx0Y2FzZSAzOiBvZmYzIC09IHNpemU7IHJldHVybiBvZmYzICsgc2l6ZTtcblx0XHRcdFx0Y2FzZSAwOiBvZmYwIC09IHNpemU7IHJldHVybiBvZmYwICsgc2l6ZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRheGVzLmZvckVhY2goKGF4aXMsIGkpID0+IHtcblx0XHRcdGlmIChheGlzLnNob3cgJiYgYXhpcy5fc2hvdykge1xuXHRcdFx0XHRsZXQgc2lkZSA9IGF4aXMuc2lkZTtcblxuXHRcdFx0XHRheGlzLl9wb3MgPSBpbmNyT2Zmc2V0KHNpZGUsIGF4aXMuX3NpemUpO1xuXG5cdFx0XHRcdGlmIChheGlzLmxhYmVsICE9IG51bGwpXG5cdFx0XHRcdFx0YXhpcy5fbHBvcyA9IGluY3JPZmZzZXQoc2lkZSwgYXhpcy5sYWJlbFNpemUpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0Y29uc3QgY3Vyc29yID0gKHNlbGYuY3Vyc29yID0gYXNzaWduKHt9LCBjdXJzb3JPcHRzLCB7ZHJhZzoge3k6IG1vZGUgPT0gMn19LCBvcHRzLmN1cnNvcikpO1xuXG5cdHtcblx0XHRjdXJzb3IuaWR4cyA9IGFjdGl2ZUlkeHM7XG5cblx0XHRjdXJzb3IuX2xvY2sgPSBmYWxzZTtcblxuXHRcdGxldCBwb2ludHMgPSBjdXJzb3IucG9pbnRzO1xuXG5cdFx0cG9pbnRzLnNob3cgICA9IGZuT3JTZWxmKHBvaW50cy5zaG93KTtcblx0XHRwb2ludHMuc2l6ZSAgID0gZm5PclNlbGYocG9pbnRzLnNpemUpO1xuXHRcdHBvaW50cy5zdHJva2UgPSBmbk9yU2VsZihwb2ludHMuc3Ryb2tlKTtcblx0XHRwb2ludHMud2lkdGggID0gZm5PclNlbGYocG9pbnRzLndpZHRoKTtcblx0XHRwb2ludHMuZmlsbCAgID0gZm5PclNlbGYocG9pbnRzLmZpbGwpO1xuXHR9XG5cblx0Y29uc3QgZm9jdXMgPSBzZWxmLmZvY3VzID0gYXNzaWduKHt9LCBvcHRzLmZvY3VzIHx8IHthbHBoYTogMC4zfSwgY3Vyc29yLmZvY3VzKTtcblx0Y29uc3QgY3Vyc29yRm9jdXMgPSBmb2N1cy5wcm94ID49IDA7XG5cblx0Ly8gc2VyaWVzLWludGVyc2VjdGlvbiBtYXJrZXJzXG5cdGxldCBjdXJzb3JQdHMgPSBbbnVsbF07XG5cblx0ZnVuY3Rpb24gaW5pdEN1cnNvclB0KHMsIHNpKSB7XG5cdFx0aWYgKHNpID4gMCkge1xuXHRcdFx0bGV0IHB0ID0gY3Vyc29yLnBvaW50cy5zaG93KHNlbGYsIHNpKTtcblxuXHRcdFx0aWYgKHB0KSB7XG5cdFx0XHRcdGFkZENsYXNzKHB0LCBDVVJTT1JfUFQpO1xuXHRcdFx0XHRhZGRDbGFzcyhwdCwgcy5jbGFzcyk7XG5cdFx0XHRcdGVsVHJhbnMocHQsIC0xMCwgLTEwLCBwbG90V2lkQ3NzLCBwbG90SGd0Q3NzKTtcblx0XHRcdFx0b3Zlci5pbnNlcnRCZWZvcmUocHQsIGN1cnNvclB0c1tzaV0pO1xuXG5cdFx0XHRcdHJldHVybiBwdDtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRmdW5jdGlvbiBpbml0U2VyaWVzKHMsIGkpIHtcblx0XHRpZiAobW9kZSA9PSAxIHx8IGkgPiAwKSB7XG5cdFx0XHRsZXQgaXNUaW1lID0gbW9kZSA9PSAxICYmIHNjYWxlc1tzLnNjYWxlXS50aW1lO1xuXG5cdFx0XHRsZXQgc3YgPSBzLnZhbHVlO1xuXHRcdFx0cy52YWx1ZSA9IGlzVGltZSA/IChpc1N0cihzdikgPyB0aW1lU2VyaWVzVmFsKF90ekRhdGUsIHRpbWVTZXJpZXNTdGFtcChzdiwgX2ZtdERhdGUpKSA6IHN2IHx8IF90aW1lU2VyaWVzVmFsKSA6IHN2IHx8IG51bVNlcmllc1ZhbDtcblx0XHRcdHMubGFiZWwgPSBzLmxhYmVsIHx8IChpc1RpbWUgPyB0aW1lU2VyaWVzTGFiZWwgOiBudW1TZXJpZXNMYWJlbCk7XG5cdFx0fVxuXG5cdFx0aWYgKGkgPiAwKSB7XG5cdFx0XHRzLndpZHRoICA9IHMud2lkdGggPT0gbnVsbCA/IDEgOiBzLndpZHRoO1xuXHRcdFx0cy5wYXRocyAgPSBzLnBhdGhzIHx8IGxpbmVhclBhdGggfHwgcmV0TnVsbDtcblx0XHRcdHMuZmlsbFRvID0gZm5PclNlbGYocy5maWxsVG8gfHwgc2VyaWVzRmlsbFRvKTtcblx0XHRcdHMucHhBbGlnbiA9ICtpZk51bGwocy5weEFsaWduLCBweEFsaWduKTtcblx0XHRcdHMucHhSb3VuZCA9IHB4Um91bmRHZW4ocy5weEFsaWduKTtcblxuXHRcdFx0cy5zdHJva2UgPSBmbk9yU2VsZihzLnN0cm9rZSB8fCBudWxsKTtcblx0XHRcdHMuZmlsbCAgID0gZm5PclNlbGYocy5maWxsIHx8IG51bGwpO1xuXHRcdFx0cy5fc3Ryb2tlID0gcy5fZmlsbCA9IHMuX3BhdGhzID0gcy5fZm9jdXMgPSBudWxsO1xuXG5cdFx0XHRsZXQgX3B0RGlhID0gcHREaWEocy53aWR0aCwgMSk7XG5cdFx0XHRsZXQgcG9pbnRzID0gcy5wb2ludHMgPSBhc3NpZ24oe30sIHtcblx0XHRcdFx0c2l6ZTogX3B0RGlhLFxuXHRcdFx0XHR3aWR0aDogbWF4KDEsIF9wdERpYSAqIC4yKSxcblx0XHRcdFx0c3Ryb2tlOiBzLnN0cm9rZSxcblx0XHRcdFx0c3BhY2U6IF9wdERpYSAqIDIsXG5cdFx0XHRcdHBhdGhzOiBwb2ludHNQYXRoLFxuXHRcdFx0XHRfc3Ryb2tlOiBudWxsLFxuXHRcdFx0XHRfZmlsbDogbnVsbCxcblx0XHRcdH0sIHMucG9pbnRzKTtcblx0XHRcdHBvaW50cy5zaG93ICAgPSBmbk9yU2VsZihwb2ludHMuc2hvdyk7XG5cdFx0XHRwb2ludHMuZmlsdGVyID0gZm5PclNlbGYocG9pbnRzLmZpbHRlcik7XG5cdFx0XHRwb2ludHMuZmlsbCAgID0gZm5PclNlbGYocG9pbnRzLmZpbGwpO1xuXHRcdFx0cG9pbnRzLnN0cm9rZSA9IGZuT3JTZWxmKHBvaW50cy5zdHJva2UpO1xuXHRcdFx0cG9pbnRzLnBhdGhzICA9IGZuT3JTZWxmKHBvaW50cy5wYXRocyk7XG5cdFx0XHRwb2ludHMucHhBbGlnbiA9IHMucHhBbGlnbjtcblx0XHR9XG5cblx0XHRpZiAoc2hvd0xlZ2VuZCkge1xuXHRcdFx0bGV0IHJvd0NlbGxzID0gaW5pdExlZ2VuZFJvdyhzLCBpKTtcblx0XHRcdGxlZ2VuZFJvd3Muc3BsaWNlKGksIDAsIHJvd0NlbGxzWzBdKTtcblx0XHRcdGxlZ2VuZENlbGxzLnNwbGljZShpLCAwLCByb3dDZWxsc1sxXSk7XG5cdFx0XHRsZWdlbmQudmFsdWVzLnB1c2gobnVsbCk7XHQvLyBOVUxMX0xFR0VORF9WQUxTIG5vdCB5ZXQgYXZpbCBoZXJlIDooXG5cdFx0fVxuXG5cdFx0aWYgKGN1cnNvci5zaG93KSB7XG5cdFx0XHRhY3RpdmVJZHhzLnNwbGljZShpLCAwLCBudWxsKTtcblxuXHRcdFx0bGV0IHB0ID0gaW5pdEN1cnNvclB0KHMsIGkpO1xuXHRcdFx0cHQgJiYgY3Vyc29yUHRzLnNwbGljZShpLCAwLCBwdCk7XG5cdFx0fVxuXG5cdFx0ZmlyZShcImFkZFNlcmllc1wiLCBpKTtcblx0fVxuXG5cdGZ1bmN0aW9uIGFkZFNlcmllcyhvcHRzLCBzaSkge1xuXHRcdHNpID0gc2kgPT0gbnVsbCA/IHNlcmllcy5sZW5ndGggOiBzaTtcblxuXHRcdG9wdHMgPSBzZXREZWZhdWx0KG9wdHMsIHNpLCB4U2VyaWVzT3B0cywgeVNlcmllc09wdHMpO1xuXHRcdHNlcmllcy5zcGxpY2Uoc2ksIDAsIG9wdHMpO1xuXHRcdGluaXRTZXJpZXMoc2VyaWVzW3NpXSwgc2kpO1xuXHR9XG5cblx0c2VsZi5hZGRTZXJpZXMgPSBhZGRTZXJpZXM7XG5cblx0ZnVuY3Rpb24gZGVsU2VyaWVzKGkpIHtcblx0XHRzZXJpZXMuc3BsaWNlKGksIDEpO1xuXG5cdFx0aWYgKHNob3dMZWdlbmQpIHtcblx0XHRcdGxlZ2VuZC52YWx1ZXMuc3BsaWNlKGksIDEpO1xuXG5cdFx0XHRsZWdlbmRDZWxscy5zcGxpY2UoaSwgMSk7XG5cdFx0XHRsZXQgdHIgPSBsZWdlbmRSb3dzLnNwbGljZShpLCAxKVswXTtcblx0XHRcdG9mZk1vdXNlKG51bGwsIHRyLmZpcnN0Q2hpbGQpO1xuXHRcdFx0dHIucmVtb3ZlKCk7XG5cdFx0fVxuXG5cdFx0aWYgKGN1cnNvci5zaG93KSB7XG5cdFx0XHRhY3RpdmVJZHhzLnNwbGljZShpLCAxKTtcblxuXHRcdFx0Y3Vyc29yUHRzLmxlbmd0aCA+IDEgJiYgY3Vyc29yUHRzLnNwbGljZShpLCAxKVswXS5yZW1vdmUoKTtcblx0XHR9XG5cblx0XHQvLyBUT0RPOiBkZS1pbml0IG5vLWxvbmdlci1uZWVkZWQgc2NhbGVzP1xuXG5cdFx0ZmlyZShcImRlbFNlcmllc1wiLCBpKTtcblx0fVxuXG5cdHNlbGYuZGVsU2VyaWVzID0gZGVsU2VyaWVzO1xuXG5cdGNvbnN0IHNpZGVzV2l0aEF4ZXMgPSBbZmFsc2UsIGZhbHNlLCBmYWxzZSwgZmFsc2VdO1xuXG5cdGZ1bmN0aW9uIGluaXRBeGlzKGF4aXMsIGkpIHtcblx0XHRheGlzLl9zaG93ID0gYXhpcy5zaG93O1xuXG5cdFx0aWYgKGF4aXMuc2hvdykge1xuXHRcdFx0bGV0IGlzVnQgPSBheGlzLnNpZGUgJSAyO1xuXG5cdFx0XHRsZXQgc2MgPSBzY2FsZXNbYXhpcy5zY2FsZV07XG5cblx0XHRcdC8vIHRoaXMgY2FuIG9jY3VyIGlmIGFsbCBzZXJpZXMgc3BlY2lmeSBub24tZGVmYXVsdCBzY2FsZXNcblx0XHRcdGlmIChzYyA9PSBudWxsKSB7XG5cdFx0XHRcdGF4aXMuc2NhbGUgPSBpc1Z0ID8gc2VyaWVzWzFdLnNjYWxlIDogeFNjYWxlS2V5O1xuXHRcdFx0XHRzYyA9IHNjYWxlc1theGlzLnNjYWxlXTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gYWxzbyBzZXQgZGVmYXVsdHMgZm9yIGluY3JzICYgdmFsdWVzIGJhc2VkIG9uIGF4aXMgZGlzdHJcblx0XHRcdGxldCBpc1RpbWUgPSBzYy50aW1lO1xuXG5cdFx0XHRheGlzLnNpemUgICA9IGZuT3JTZWxmKGF4aXMuc2l6ZSk7XG5cdFx0XHRheGlzLnNwYWNlICA9IGZuT3JTZWxmKGF4aXMuc3BhY2UpO1xuXHRcdFx0YXhpcy5yb3RhdGUgPSBmbk9yU2VsZihheGlzLnJvdGF0ZSk7XG5cdFx0XHRheGlzLmluY3JzICA9IGZuT3JTZWxmKGF4aXMuaW5jcnMgIHx8ICggICAgICAgICAgc2MuZGlzdHIgPT0gMiA/IHdob2xlSW5jcnMgOiAoaXNUaW1lID8gKG1zID09IDEgPyB0aW1lSW5jcnNNcyA6IHRpbWVJbmNyc1MpIDogbnVtSW5jcnMpKSk7XG5cdFx0XHRheGlzLnNwbGl0cyA9IGZuT3JTZWxmKGF4aXMuc3BsaXRzIHx8IChpc1RpbWUgJiYgc2MuZGlzdHIgPT0gMSA/IF90aW1lQXhpc1NwbGl0cyA6IHNjLmRpc3RyID09IDMgPyBsb2dBeGlzU3BsaXRzIDogc2MuZGlzdHIgPT0gNCA/IGFzaW5oQXhpc1NwbGl0cyA6IG51bUF4aXNTcGxpdHMpKTtcblxuXHRcdFx0YXhpcy5zdHJva2UgICAgICAgID0gZm5PclNlbGYoYXhpcy5zdHJva2UpO1xuXHRcdFx0YXhpcy5ncmlkLnN0cm9rZSAgID0gZm5PclNlbGYoYXhpcy5ncmlkLnN0cm9rZSk7XG5cdFx0XHRheGlzLnRpY2tzLnN0cm9rZSAgPSBmbk9yU2VsZihheGlzLnRpY2tzLnN0cm9rZSk7XG5cdFx0XHRheGlzLmJvcmRlci5zdHJva2UgPSBmbk9yU2VsZihheGlzLmJvcmRlci5zdHJva2UpO1xuXG5cdFx0XHRsZXQgYXYgPSBheGlzLnZhbHVlcztcblxuXHRcdFx0YXhpcy52YWx1ZXMgPSAoXG5cdFx0XHRcdC8vIHN0YXRpYyBhcnJheSBvZiB0aWNrIHZhbHVlc1xuXHRcdFx0XHRpc0FycihhdikgJiYgIWlzQXJyKGF2WzBdKSA/IGZuT3JTZWxmKGF2KSA6XG5cdFx0XHRcdC8vIHRlbXBvcmFsXG5cdFx0XHRcdGlzVGltZSA/IChcblx0XHRcdFx0XHQvLyBjb25maWcgYXJyYXkgb2YgZm10RGF0ZSBzdHJpbmcgdHBsc1xuXHRcdFx0XHRcdGlzQXJyKGF2KSA/XG5cdFx0XHRcdFx0XHR0aW1lQXhpc1ZhbHMoX3R6RGF0ZSwgdGltZUF4aXNTdGFtcHMoYXYsIF9mbXREYXRlKSkgOlxuXHRcdFx0XHRcdC8vIGZtdERhdGUgc3RyaW5nIHRwbFxuXHRcdFx0XHRcdGlzU3RyKGF2KSA/XG5cdFx0XHRcdFx0XHR0aW1lQXhpc1ZhbChfdHpEYXRlLCBhdikgOlxuXHRcdFx0XHRcdGF2IHx8IF90aW1lQXhpc1ZhbHNcblx0XHRcdFx0KSA6IGF2IHx8IG51bUF4aXNWYWxzXG5cdFx0XHQpO1xuXG5cdFx0XHRheGlzLmZpbHRlciA9IGZuT3JTZWxmKGF4aXMuZmlsdGVyIHx8ICggICAgICAgICAgc2MuZGlzdHIgPj0gMyA/IGxvZ0F4aXNWYWxzRmlsdCA6IHJldEFyZzEpKTtcblxuXHRcdFx0YXhpcy5mb250ICAgICAgPSBweFJhdGlvRm9udChheGlzLmZvbnQpO1xuXHRcdFx0YXhpcy5sYWJlbEZvbnQgPSBweFJhdGlvRm9udChheGlzLmxhYmVsRm9udCk7XG5cblx0XHRcdGF4aXMuX3NpemUgICA9IGF4aXMuc2l6ZShzZWxmLCBudWxsLCBpLCAwKTtcblxuXHRcdFx0YXhpcy5fc3BhY2UgID1cblx0XHRcdGF4aXMuX3JvdGF0ZSA9XG5cdFx0XHRheGlzLl9pbmNycyAgPVxuXHRcdFx0YXhpcy5fZm91bmQgID1cdC8vIGZvdW5kSW5jclNwYWNlXG5cdFx0XHRheGlzLl9zcGxpdHMgPVxuXHRcdFx0YXhpcy5fdmFsdWVzID0gbnVsbDtcblxuXHRcdFx0aWYgKGF4aXMuX3NpemUgPiAwKSB7XG5cdFx0XHRcdHNpZGVzV2l0aEF4ZXNbaV0gPSB0cnVlO1xuXHRcdFx0XHRheGlzLl9lbCA9IHBsYWNlRGl2KEFYSVMsIHdyYXApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBkZWJ1Z1xuXHRcdC8vXHRheGlzLl9lbC5zdHlsZS5iYWNrZ3JvdW5kID0gXCIjXCIgICsgTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpKjE2Nzc3MjE1KS50b1N0cmluZygxNikgKyAnODAnO1xuXHRcdH1cblx0fVxuXG5cdGZ1bmN0aW9uIGF1dG9QYWRTaWRlKHNlbGYsIHNpZGUsIHNpZGVzV2l0aEF4ZXMsIGN5Y2xlTnVtKSB7XG5cdFx0bGV0IFtoYXNUb3BBeGlzLCBoYXNSZ3RBeGlzLCBoYXNCdG1BeGlzLCBoYXNMZnRBeGlzXSA9IHNpZGVzV2l0aEF4ZXM7XG5cblx0XHRsZXQgb3JpID0gc2lkZSAlIDI7XG5cdFx0bGV0IHNpemUgPSAwO1xuXG5cdFx0aWYgKG9yaSA9PSAwICYmIChoYXNMZnRBeGlzIHx8IGhhc1JndEF4aXMpKVxuXHRcdFx0c2l6ZSA9IChzaWRlID09IDAgJiYgIWhhc1RvcEF4aXMgfHwgc2lkZSA9PSAyICYmICFoYXNCdG1BeGlzID8gcm91bmQoeEF4aXNPcHRzLnNpemUgLyAzKSA6IDApO1xuXHRcdGlmIChvcmkgPT0gMSAmJiAoaGFzVG9wQXhpcyB8fCBoYXNCdG1BeGlzKSlcblx0XHRcdHNpemUgPSAoc2lkZSA9PSAxICYmICFoYXNSZ3RBeGlzIHx8IHNpZGUgPT0gMyAmJiAhaGFzTGZ0QXhpcyA/IHJvdW5kKHlBeGlzT3B0cy5zaXplIC8gMikgOiAwKTtcblxuXHRcdHJldHVybiBzaXplO1xuXHR9XG5cblx0Y29uc3QgcGFkZGluZyA9IHNlbGYucGFkZGluZyA9IChvcHRzLnBhZGRpbmcgfHwgW2F1dG9QYWRTaWRlLGF1dG9QYWRTaWRlLGF1dG9QYWRTaWRlLGF1dG9QYWRTaWRlXSkubWFwKHAgPT4gZm5PclNlbGYoaWZOdWxsKHAsIGF1dG9QYWRTaWRlKSkpO1xuXHRjb25zdCBfcGFkZGluZyA9IHNlbGYuX3BhZGRpbmcgPSBwYWRkaW5nLm1hcCgocCwgaSkgPT4gcChzZWxmLCBpLCBzaWRlc1dpdGhBeGVzLCAwKSk7XG5cblx0bGV0IGRhdGFMZW47XG5cblx0Ly8gcmVuZGVyZWQgZGF0YSB3aW5kb3dcblx0bGV0IGkwID0gbnVsbDtcblx0bGV0IGkxID0gbnVsbDtcblx0Y29uc3QgaWR4cyA9IG1vZGUgPT0gMSA/IHNlcmllc1swXS5pZHhzIDogbnVsbDtcblxuXHRsZXQgZGF0YTAgPSBudWxsO1xuXG5cdGxldCB2aWFBdXRvU2NhbGVYID0gZmFsc2U7XG5cblx0ZnVuY3Rpb24gc2V0RGF0YShfZGF0YSwgX3Jlc2V0U2NhbGVzKSB7XG5cdFx0ZGF0YSA9IF9kYXRhID09IG51bGwgPyBbXSA6IGNvcHkoX2RhdGEsIGZhc3RJc09iaik7XG5cblx0XHRpZiAobW9kZSA9PSAyKSB7XG5cdFx0XHRkYXRhTGVuID0gMDtcblx0XHRcdGZvciAobGV0IGkgPSAxOyBpIDwgc2VyaWVzLmxlbmd0aDsgaSsrKVxuXHRcdFx0XHRkYXRhTGVuICs9IGRhdGFbaV1bMF0ubGVuZ3RoO1xuXHRcdFx0c2VsZi5kYXRhID0gZGF0YSA9IF9kYXRhO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGlmIChkYXRhWzBdID09IG51bGwpXG5cdFx0XHRcdGRhdGFbMF0gPSBbXTtcblxuXHRcdFx0c2VsZi5kYXRhID0gZGF0YS5zbGljZSgpO1xuXG5cdFx0XHRkYXRhMCA9IGRhdGFbMF07XG5cdFx0XHRkYXRhTGVuID0gZGF0YTAubGVuZ3RoO1xuXG5cdFx0XHRpZiAoeFNjYWxlRGlzdHIgPT0gMikge1xuXHRcdFx0XHRkYXRhWzBdID0gQXJyYXkoZGF0YUxlbik7XG5cdFx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgZGF0YUxlbjsgaSsrKVxuXHRcdFx0XHRcdGRhdGFbMF1baV0gPSBpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHNlbGYuX2RhdGEgPSBkYXRhO1xuXG5cdFx0cmVzZXRZU2VyaWVzKHRydWUpO1xuXG5cdFx0ZmlyZShcInNldERhdGFcIik7XG5cblx0XHQvLyBmb3JjZXMgeCBheGlzIHRpY2sgdmFsdWVzIHRvIHJlLWdlbmVyYXRlIHdoZW4gbmVpdGhlciB4IHNjYWxlIG5vciB5IHNjYWxlIGNoYW5nZXNcblx0XHQvLyBpbiBvcmRpbmFsIG1vZGUsIHNjYWxlIHJhbmdlIGlzIGJ5IGluZGV4LCBzbyB3aWxsIG5vdCBjaGFuZ2UgaWYgbmV3IGRhdGEgaGFzIHNhbWUgbGVuZ3RoLCBidXQgdGljayB2YWx1ZXMgYXJlIGZyb20gZGF0YVxuXHRcdGlmICh4U2NhbGVEaXN0ciA9PSAyKSB7XG5cdFx0XHRzaG91bGRDb252ZXJnZVNpemUgPSB0cnVlO1xuXG5cdFx0XHQvKiBvciBzb21ld2hhdCBjaGVhcGVyLCBhbmQgdWdsaWVyOlxuXHRcdFx0aWYgKHJlYWR5KSB7XG5cdFx0XHRcdC8vIGxvZ2ljIGV4dHJhY3RlZCBmcm9tIGF4ZXNDYWxjKClcblx0XHRcdFx0bGV0IGkgPSAwO1xuXHRcdFx0XHRsZXQgYXhpcyA9IGF4ZXNbaV07XG5cdFx0XHRcdGxldCBfc3BsaXRzID0gYXhpcy5fc3BsaXRzLm1hcChpID0+IGRhdGEwW2ldKTtcblx0XHRcdFx0bGV0IFtfaW5jciwgX3NwYWNlXSA9IGF4aXMuX2ZvdW5kO1xuXHRcdFx0XHRsZXQgaW5jciA9IGRhdGEwW19zcGxpdHNbMV1dIC0gZGF0YTBbX3NwbGl0c1swXV07XG5cdFx0XHRcdGF4aXMuX3ZhbHVlcyA9IGF4aXMudmFsdWVzKHNlbGYsIGF4aXMuZmlsdGVyKHNlbGYsIF9zcGxpdHMsIGksIF9zcGFjZSwgaW5jciksIGksIF9zcGFjZSwgaW5jcik7XG5cdFx0XHR9XG5cdFx0XHQqL1xuXHRcdH1cblxuXHRcdGlmIChfcmVzZXRTY2FsZXMgIT09IGZhbHNlKSB7XG5cdFx0XHRsZXQgeHNjID0gc2NhbGVYO1xuXG5cdFx0XHRpZiAoeHNjLmF1dG8oc2VsZiwgdmlhQXV0b1NjYWxlWCkpXG5cdFx0XHRcdGF1dG9TY2FsZVgoKTtcblx0XHRcdGVsc2Vcblx0XHRcdFx0X3NldFNjYWxlKHhTY2FsZUtleSwgeHNjLm1pbiwgeHNjLm1heCk7XG5cblx0XHRcdHNob3VsZFNldEN1cnNvciA9IGN1cnNvci5sZWZ0ID49IDA7XG5cdFx0XHRzaG91bGRTZXRMZWdlbmQgPSB0cnVlO1xuXHRcdFx0Y29tbWl0KCk7XG5cdFx0fVxuXHR9XG5cblx0c2VsZi5zZXREYXRhID0gc2V0RGF0YTtcblxuXHRmdW5jdGlvbiBhdXRvU2NhbGVYKCkge1xuXHRcdHZpYUF1dG9TY2FsZVggPSB0cnVlO1xuXG5cdFx0bGV0IF9taW4sIF9tYXg7XG5cblx0XHRpZiAobW9kZSA9PSAxKSB7XG5cdFx0XHRpZiAoZGF0YUxlbiA+IDApIHtcblx0XHRcdFx0aTAgPSBpZHhzWzBdID0gMDtcblx0XHRcdFx0aTEgPSBpZHhzWzFdID0gZGF0YUxlbiAtIDE7XG5cblx0XHRcdFx0X21pbiA9IGRhdGFbMF1baTBdO1xuXHRcdFx0XHRfbWF4ID0gZGF0YVswXVtpMV07XG5cblx0XHRcdFx0aWYgKHhTY2FsZURpc3RyID09IDIpIHtcblx0XHRcdFx0XHRfbWluID0gaTA7XG5cdFx0XHRcdFx0X21heCA9IGkxO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2UgaWYgKGRhdGFMZW4gPT0gMSkge1xuXHRcdFx0XHRcdGlmICh4U2NhbGVEaXN0ciA9PSAzKVxuXHRcdFx0XHRcdFx0W19taW4sIF9tYXhdID0gcmFuZ2VMb2coX21pbiwgX21pbiwgc2NhbGVYLmxvZywgZmFsc2UpO1xuXHRcdFx0XHRcdGVsc2UgaWYgKHhTY2FsZURpc3RyID09IDQpXG5cdFx0XHRcdFx0XHRbX21pbiwgX21heF0gPSByYW5nZUFzaW5oKF9taW4sIF9taW4sIHNjYWxlWC5sb2csIGZhbHNlKTtcblx0XHRcdFx0XHRlbHNlIGlmIChzY2FsZVgudGltZSlcblx0XHRcdFx0XHRcdF9tYXggPSBfbWluICsgcm91bmQoODY0MDAgLyBtcyk7XG5cdFx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdFx0W19taW4sIF9tYXhdID0gcmFuZ2VOdW0oX21pbiwgX21heCwgcmFuZ2VQYWQsIHRydWUpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0aTAgPSBpZHhzWzBdID0gX21pbiA9IG51bGw7XG5cdFx0XHRcdGkxID0gaWR4c1sxXSA9IF9tYXggPSBudWxsO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdF9zZXRTY2FsZSh4U2NhbGVLZXksIF9taW4sIF9tYXgpO1xuXHR9XG5cblx0bGV0IGN0eFN0cm9rZSwgY3R4RmlsbCwgY3R4V2lkdGgsIGN0eERhc2gsIGN0eEpvaW4sIGN0eENhcCwgY3R4Rm9udCwgY3R4QWxpZ24sIGN0eEJhc2VsaW5lO1xuXHRsZXQgY3R4QWxwaGE7XG5cblx0ZnVuY3Rpb24gc2V0Q3R4U3R5bGUoc3Ryb2tlID0gdHJhbnNwYXJlbnQsIHdpZHRoLCBkYXNoID0gRU1QVFlfQVJSLCBjYXAgPSBcImJ1dHRcIiwgZmlsbCA9IHRyYW5zcGFyZW50LCBqb2luID0gXCJyb3VuZFwiKSB7XG5cdFx0aWYgKHN0cm9rZSAhPSBjdHhTdHJva2UpXG5cdFx0XHRjdHguc3Ryb2tlU3R5bGUgPSBjdHhTdHJva2UgPSBzdHJva2U7XG5cdFx0aWYgKGZpbGwgIT0gY3R4RmlsbClcblx0XHRcdGN0eC5maWxsU3R5bGUgPSBjdHhGaWxsID0gZmlsbDtcblx0XHRpZiAod2lkdGggIT0gY3R4V2lkdGgpXG5cdFx0XHRjdHgubGluZVdpZHRoID0gY3R4V2lkdGggPSB3aWR0aDtcblx0XHRpZiAoam9pbiAhPSBjdHhKb2luKVxuXHRcdFx0Y3R4LmxpbmVKb2luID0gY3R4Sm9pbiA9IGpvaW47XG5cdFx0aWYgKGNhcCAhPSBjdHhDYXApXG5cdFx0XHRjdHgubGluZUNhcCA9IGN0eENhcCA9IGNhcDsgLy8gKOKAv3zigL8pXG5cdFx0aWYgKGRhc2ggIT0gY3R4RGFzaClcblx0XHRcdGN0eC5zZXRMaW5lRGFzaChjdHhEYXNoID0gZGFzaCk7XG5cdH1cblxuXHRmdW5jdGlvbiBzZXRGb250U3R5bGUoZm9udCwgZmlsbCwgYWxpZ24sIGJhc2VsaW5lKSB7XG5cdFx0aWYgKGZpbGwgIT0gY3R4RmlsbClcblx0XHRcdGN0eC5maWxsU3R5bGUgPSBjdHhGaWxsID0gZmlsbDtcblx0XHRpZiAoZm9udCAhPSBjdHhGb250KVxuXHRcdFx0Y3R4LmZvbnQgPSBjdHhGb250ID0gZm9udDtcblx0XHRpZiAoYWxpZ24gIT0gY3R4QWxpZ24pXG5cdFx0XHRjdHgudGV4dEFsaWduID0gY3R4QWxpZ24gPSBhbGlnbjtcblx0XHRpZiAoYmFzZWxpbmUgIT0gY3R4QmFzZWxpbmUpXG5cdFx0XHRjdHgudGV4dEJhc2VsaW5lID0gY3R4QmFzZWxpbmUgPSBiYXNlbGluZTtcblx0fVxuXG5cdGZ1bmN0aW9uIGFjY1NjYWxlKHdzYywgcHNjLCBmYWNldCwgZGF0YSwgc29ydGVkID0gMCkge1xuXHRcdGlmIChkYXRhLmxlbmd0aCA+IDAgJiYgd3NjLmF1dG8oc2VsZiwgdmlhQXV0b1NjYWxlWCkgJiYgKHBzYyA9PSBudWxsIHx8IHBzYy5taW4gPT0gbnVsbCkpIHtcblx0XHRcdGxldCBfaTAgPSBpZk51bGwoaTAsIDApO1xuXHRcdFx0bGV0IF9pMSA9IGlmTnVsbChpMSwgZGF0YS5sZW5ndGggLSAxKTtcblxuXHRcdFx0Ly8gb25seSBydW4gZ2V0TWluTWF4KCkgZm9yIGludmFsaWRhdGVkIHNlcmllcyBkYXRhLCBlbHNlIHJldXNlXG5cdFx0XHRsZXQgbWluTWF4ID0gZmFjZXQubWluID09IG51bGwgPyAod3NjLmRpc3RyID09IDMgPyBnZXRNaW5NYXhMb2coZGF0YSwgX2kwLCBfaTEpIDogZ2V0TWluTWF4KGRhdGEsIF9pMCwgX2kxLCBzb3J0ZWQpKSA6IFtmYWNldC5taW4sIGZhY2V0Lm1heF07XG5cblx0XHRcdC8vIGluaXRpYWwgbWluL21heFxuXHRcdFx0d3NjLm1pbiA9IG1pbih3c2MubWluLCBmYWNldC5taW4gPSBtaW5NYXhbMF0pO1xuXHRcdFx0d3NjLm1heCA9IG1heCh3c2MubWF4LCBmYWNldC5tYXggPSBtaW5NYXhbMV0pO1xuXHRcdH1cblx0fVxuXG5cdGZ1bmN0aW9uIHNldFNjYWxlcygpIHtcblx0Ly9cdGxvZyhcInNldFNjYWxlcygpXCIsIGFyZ3VtZW50cyk7XG5cblx0XHQvLyB3aXAgc2NhbGVzXG5cdFx0bGV0IHdpcFNjYWxlcyA9IGNvcHkoc2NhbGVzLCBmYXN0SXNPYmopO1xuXG5cdFx0Zm9yIChsZXQgayBpbiB3aXBTY2FsZXMpIHtcblx0XHRcdGxldCB3c2MgPSB3aXBTY2FsZXNba107XG5cdFx0XHRsZXQgcHNjID0gcGVuZFNjYWxlc1trXTtcblxuXHRcdFx0aWYgKHBzYyAhPSBudWxsICYmIHBzYy5taW4gIT0gbnVsbCkge1xuXHRcdFx0XHRhc3NpZ24od3NjLCBwc2MpO1xuXG5cdFx0XHRcdC8vIGV4cGxpY2l0bHkgc2V0dGluZyB0aGUgeC1zY2FsZSBpbnZhbGlkYXRlcyBldmVyeXRoaW5nIChhY3RzIGFzIHJlZHJhdylcblx0XHRcdFx0aWYgKGsgPT0geFNjYWxlS2V5KVxuXHRcdFx0XHRcdHJlc2V0WVNlcmllcyh0cnVlKTtcblx0XHRcdH1cblx0XHRcdGVsc2UgaWYgKGsgIT0geFNjYWxlS2V5IHx8IG1vZGUgPT0gMikge1xuXHRcdFx0XHRpZiAoZGF0YUxlbiA9PSAwICYmIHdzYy5mcm9tID09IG51bGwpIHtcblx0XHRcdFx0XHRsZXQgbWluTWF4ID0gd3NjLnJhbmdlKHNlbGYsIG51bGwsIG51bGwsIGspO1xuXHRcdFx0XHRcdHdzYy5taW4gPSBtaW5NYXhbMF07XG5cdFx0XHRcdFx0d3NjLm1heCA9IG1pbk1heFsxXTtcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHR3c2MubWluID0gaW5mO1xuXHRcdFx0XHRcdHdzYy5tYXggPSAtaW5mO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKGRhdGFMZW4gPiAwKSB7XG5cdFx0XHQvLyBwcmUtcmFuZ2UgeS1zY2FsZXMgZnJvbSB5IHNlcmllcycgZGF0YSB2YWx1ZXNcblx0XHRcdHNlcmllcy5mb3JFYWNoKChzLCBpKSA9PiB7XG5cdFx0XHRcdGlmIChtb2RlID09IDEpIHtcblx0XHRcdFx0XHRsZXQgayA9IHMuc2NhbGU7XG5cdFx0XHRcdFx0bGV0IHdzYyA9IHdpcFNjYWxlc1trXTtcblx0XHRcdFx0XHRsZXQgcHNjID0gcGVuZFNjYWxlc1trXTtcblxuXHRcdFx0XHRcdGlmIChpID09IDApIHtcblx0XHRcdFx0XHRcdGxldCBtaW5NYXggPSB3c2MucmFuZ2Uoc2VsZiwgd3NjLm1pbiwgd3NjLm1heCwgayk7XG5cblx0XHRcdFx0XHRcdHdzYy5taW4gPSBtaW5NYXhbMF07XG5cdFx0XHRcdFx0XHR3c2MubWF4ID0gbWluTWF4WzFdO1xuXG5cdFx0XHRcdFx0XHRpMCA9IGNsb3Nlc3RJZHgod3NjLm1pbiwgZGF0YVswXSk7XG5cdFx0XHRcdFx0XHRpMSA9IGNsb3Nlc3RJZHgod3NjLm1heCwgZGF0YVswXSk7XG5cblx0XHRcdFx0XHRcdC8vIGNsb3Nlc3QgaW5kaWNlcyBjYW4gYmUgb3V0c2lkZSBvZiB2aWV3XG5cdFx0XHRcdFx0XHRpZiAoZGF0YVswXVtpMF0gPCB3c2MubWluKVxuXHRcdFx0XHRcdFx0XHRpMCsrO1xuXHRcdFx0XHRcdFx0aWYgKGRhdGFbMF1baTFdID4gd3NjLm1heClcblx0XHRcdFx0XHRcdFx0aTEtLTtcblxuXHRcdFx0XHRcdFx0cy5taW4gPSBkYXRhMFtpMF07XG5cdFx0XHRcdFx0XHRzLm1heCA9IGRhdGEwW2kxXTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSBpZiAocy5zaG93ICYmIHMuYXV0bylcblx0XHRcdFx0XHRcdGFjY1NjYWxlKHdzYywgcHNjLCBzLCBkYXRhW2ldLCBzLnNvcnRlZCk7XG5cblx0XHRcdFx0XHRzLmlkeHNbMF0gPSBpMDtcblx0XHRcdFx0XHRzLmlkeHNbMV0gPSBpMTtcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHRpZiAoaSA+IDApIHtcblx0XHRcdFx0XHRcdGlmIChzLnNob3cgJiYgcy5hdXRvKSB7XG5cdFx0XHRcdFx0XHRcdC8vIFRPRE86IG9ubHkgaGFuZGxlcywgYXNzdW1lcyBhbmQgcmVxdWlyZXMgZmFjZXRzWzBdIC8gJ3gnIHNjYWxlLCBhbmQgZmFjZXRzWzFdIC8gJ3knIHNjYWxlXG5cdFx0XHRcdFx0XHRcdGxldCBbIHhGYWNldCwgeUZhY2V0IF0gPSBzLmZhY2V0cztcblx0XHRcdFx0XHRcdFx0bGV0IHhTY2FsZUtleSA9IHhGYWNldC5zY2FsZTtcblx0XHRcdFx0XHRcdFx0bGV0IHlTY2FsZUtleSA9IHlGYWNldC5zY2FsZTtcblx0XHRcdFx0XHRcdFx0bGV0IFsgeERhdGEsIHlEYXRhIF0gPSBkYXRhW2ldO1xuXG5cdFx0XHRcdFx0XHRcdGFjY1NjYWxlKHdpcFNjYWxlc1t4U2NhbGVLZXldLCBwZW5kU2NhbGVzW3hTY2FsZUtleV0sIHhGYWNldCwgeERhdGEsIHhGYWNldC5zb3J0ZWQpO1xuXHRcdFx0XHRcdFx0XHRhY2NTY2FsZSh3aXBTY2FsZXNbeVNjYWxlS2V5XSwgcGVuZFNjYWxlc1t5U2NhbGVLZXldLCB5RmFjZXQsIHlEYXRhLCB5RmFjZXQuc29ydGVkKTtcblxuXHRcdFx0XHRcdFx0XHQvLyB0ZW1wXG5cdFx0XHRcdFx0XHRcdHMubWluID0geUZhY2V0Lm1pbjtcblx0XHRcdFx0XHRcdFx0cy5tYXggPSB5RmFjZXQubWF4O1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cblx0XHRcdC8vIHJhbmdlIGluZGVwZW5kZW50IHNjYWxlc1xuXHRcdFx0Zm9yIChsZXQgayBpbiB3aXBTY2FsZXMpIHtcblx0XHRcdFx0bGV0IHdzYyA9IHdpcFNjYWxlc1trXTtcblx0XHRcdFx0bGV0IHBzYyA9IHBlbmRTY2FsZXNba107XG5cblx0XHRcdFx0aWYgKHdzYy5mcm9tID09IG51bGwgJiYgKHBzYyA9PSBudWxsIHx8IHBzYy5taW4gPT0gbnVsbCkpIHtcblx0XHRcdFx0XHRsZXQgbWluTWF4ID0gd3NjLnJhbmdlKFxuXHRcdFx0XHRcdFx0c2VsZixcblx0XHRcdFx0XHRcdHdzYy5taW4gPT0gIGluZiA/IG51bGwgOiB3c2MubWluLFxuXHRcdFx0XHRcdFx0d3NjLm1heCA9PSAtaW5mID8gbnVsbCA6IHdzYy5tYXgsXG5cdFx0XHRcdFx0XHRrXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0XHR3c2MubWluID0gbWluTWF4WzBdO1xuXHRcdFx0XHRcdHdzYy5tYXggPSBtaW5NYXhbMV07XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyByYW5nZSBkZXBlbmRlbnQgc2NhbGVzXG5cdFx0Zm9yIChsZXQgayBpbiB3aXBTY2FsZXMpIHtcblx0XHRcdGxldCB3c2MgPSB3aXBTY2FsZXNba107XG5cblx0XHRcdGlmICh3c2MuZnJvbSAhPSBudWxsKSB7XG5cdFx0XHRcdGxldCBiYXNlID0gd2lwU2NhbGVzW3dzYy5mcm9tXTtcblxuXHRcdFx0XHRpZiAoYmFzZS5taW4gPT0gbnVsbClcblx0XHRcdFx0XHR3c2MubWluID0gd3NjLm1heCA9IG51bGw7XG5cdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdGxldCBtaW5NYXggPSB3c2MucmFuZ2Uoc2VsZiwgYmFzZS5taW4sIGJhc2UubWF4LCBrKTtcblx0XHRcdFx0XHR3c2MubWluID0gbWluTWF4WzBdO1xuXHRcdFx0XHRcdHdzYy5tYXggPSBtaW5NYXhbMV07XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRsZXQgY2hhbmdlZCA9IHt9O1xuXHRcdGxldCBhbnlDaGFuZ2VkID0gZmFsc2U7XG5cblx0XHRmb3IgKGxldCBrIGluIHdpcFNjYWxlcykge1xuXHRcdFx0bGV0IHdzYyA9IHdpcFNjYWxlc1trXTtcblx0XHRcdGxldCBzYyA9IHNjYWxlc1trXTtcblxuXHRcdFx0aWYgKHNjLm1pbiAhPSB3c2MubWluIHx8IHNjLm1heCAhPSB3c2MubWF4KSB7XG5cdFx0XHRcdHNjLm1pbiA9IHdzYy5taW47XG5cdFx0XHRcdHNjLm1heCA9IHdzYy5tYXg7XG5cblx0XHRcdFx0bGV0IGRpc3RyID0gc2MuZGlzdHI7XG5cblx0XHRcdFx0c2MuX21pbiA9IGRpc3RyID09IDMgPyBsb2cxMChzYy5taW4pIDogZGlzdHIgPT0gNCA/IGFzaW5oKHNjLm1pbiwgc2MuYXNpbmgpIDogc2MubWluO1xuXHRcdFx0XHRzYy5fbWF4ID0gZGlzdHIgPT0gMyA/IGxvZzEwKHNjLm1heCkgOiBkaXN0ciA9PSA0ID8gYXNpbmgoc2MubWF4LCBzYy5hc2luaCkgOiBzYy5tYXg7XG5cblx0XHRcdFx0Y2hhbmdlZFtrXSA9IGFueUNoYW5nZWQgPSB0cnVlO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmIChhbnlDaGFuZ2VkKSB7XG5cdFx0XHQvLyBpbnZhbGlkYXRlIHBhdGhzIG9mIGFsbCBzZXJpZXMgb24gY2hhbmdlZCBzY2FsZXNcblx0XHRcdHNlcmllcy5mb3JFYWNoKChzLCBpKSA9PiB7XG5cdFx0XHRcdGlmIChtb2RlID09IDIpIHtcblx0XHRcdFx0XHRpZiAoaSA+IDAgJiYgY2hhbmdlZC55KVxuXHRcdFx0XHRcdFx0cy5fcGF0aHMgPSBudWxsO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdGlmIChjaGFuZ2VkW3Muc2NhbGVdKVxuXHRcdFx0XHRcdFx0cy5fcGF0aHMgPSBudWxsO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblxuXHRcdFx0Zm9yIChsZXQgayBpbiBjaGFuZ2VkKSB7XG5cdFx0XHRcdHNob3VsZENvbnZlcmdlU2l6ZSA9IHRydWU7XG5cdFx0XHRcdGZpcmUoXCJzZXRTY2FsZVwiLCBrKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGN1cnNvci5zaG93KVxuXHRcdFx0XHRzaG91bGRTZXRDdXJzb3IgPSBzaG91bGRTZXRMZWdlbmQgPSBjdXJzb3IubGVmdCA+PSAwO1xuXHRcdH1cblxuXHRcdGZvciAobGV0IGsgaW4gcGVuZFNjYWxlcylcblx0XHRcdHBlbmRTY2FsZXNba10gPSBudWxsO1xuXHR9XG5cblx0Ly8gZ3JhYnMgdGhlIG5lYXJlc3QgaW5kaWNlcyB3aXRoIHkgZGF0YSBvdXRzaWRlIG9mIHgtc2NhbGUgbGltaXRzXG5cdGZ1bmN0aW9uIGdldE91dGVySWR4cyh5ZGF0YSkge1xuXHRcdGxldCBfaTAgPSBjbGFtcChpMCAtIDEsIDAsIGRhdGFMZW4gLSAxKTtcblx0XHRsZXQgX2kxID0gY2xhbXAoaTEgKyAxLCAwLCBkYXRhTGVuIC0gMSk7XG5cblx0XHR3aGlsZSAoeWRhdGFbX2kwXSA9PSBudWxsICYmIF9pMCA+IDApXG5cdFx0XHRfaTAtLTtcblxuXHRcdHdoaWxlICh5ZGF0YVtfaTFdID09IG51bGwgJiYgX2kxIDwgZGF0YUxlbiAtIDEpXG5cdFx0XHRfaTErKztcblxuXHRcdHJldHVybiBbX2kwLCBfaTFdO1xuXHR9XG5cblx0ZnVuY3Rpb24gZHJhd1NlcmllcygpIHtcblx0XHRpZiAoZGF0YUxlbiA+IDApIHtcblx0XHRcdHNlcmllcy5mb3JFYWNoKChzLCBpKSA9PiB7XG5cdFx0XHRcdGlmIChpID4gMCAmJiBzLnNob3cgJiYgcy5fcGF0aHMgPT0gbnVsbCkge1xuXHRcdFx0XHRcdGxldCBfaWR4cyA9IGdldE91dGVySWR4cyhkYXRhW2ldKTtcblx0XHRcdFx0XHRzLl9wYXRocyA9IHMucGF0aHMoc2VsZiwgaSwgX2lkeHNbMF0sIF9pZHhzWzFdKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cblx0XHRcdHNlcmllcy5mb3JFYWNoKChzLCBpKSA9PiB7XG5cdFx0XHRcdGlmIChpID4gMCAmJiBzLnNob3cpIHtcblx0XHRcdFx0XHRpZiAoY3R4QWxwaGEgIT0gcy5hbHBoYSlcblx0XHRcdFx0XHRcdGN0eC5nbG9iYWxBbHBoYSA9IGN0eEFscGhhID0gcy5hbHBoYTtcblxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGNhY2hlU3Ryb2tlRmlsbChpLCBmYWxzZSk7XG5cdFx0XHRcdFx0XHRzLl9wYXRocyAmJiBkcmF3UGF0aChpLCBmYWxzZSk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0Y2FjaGVTdHJva2VGaWxsKGksIHRydWUpO1xuXG5cdFx0XHRcdFx0XHRsZXQgc2hvdyA9IHMucG9pbnRzLnNob3coc2VsZiwgaSwgaTAsIGkxKTtcblx0XHRcdFx0XHRcdGxldCBpZHhzID0gcy5wb2ludHMuZmlsdGVyKHNlbGYsIGksIHNob3csIHMuX3BhdGhzID8gcy5fcGF0aHMuZ2FwcyA6IG51bGwpO1xuXG5cdFx0XHRcdFx0XHRpZiAoc2hvdyB8fCBpZHhzKSB7XG5cdFx0XHRcdFx0XHRcdHMucG9pbnRzLl9wYXRocyA9IHMucG9pbnRzLnBhdGhzKHNlbGYsIGksIGkwLCBpMSwgaWR4cyk7XG5cdFx0XHRcdFx0XHRcdGRyYXdQYXRoKGksIHRydWUpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmIChjdHhBbHBoYSAhPSAxKVxuXHRcdFx0XHRcdFx0Y3R4Lmdsb2JhbEFscGhhID0gY3R4QWxwaGEgPSAxO1xuXG5cdFx0XHRcdFx0ZmlyZShcImRyYXdTZXJpZXNcIiwgaSk7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH1cblx0fVxuXG5cdGZ1bmN0aW9uIGNhY2hlU3Ryb2tlRmlsbChzaSwgX3BvaW50cykge1xuXHRcdGxldCBzID0gX3BvaW50cyA/IHNlcmllc1tzaV0ucG9pbnRzIDogc2VyaWVzW3NpXTtcblxuXHRcdHMuX3N0cm9rZSA9IHMuc3Ryb2tlKHNlbGYsIHNpKTtcblx0XHRzLl9maWxsICAgPSBzLmZpbGwoc2VsZiwgc2kpO1xuXHR9XG5cblx0ZnVuY3Rpb24gZHJhd1BhdGgoc2ksIF9wb2ludHMpIHtcblx0XHRsZXQgcyA9IF9wb2ludHMgPyBzZXJpZXNbc2ldLnBvaW50cyA6IHNlcmllc1tzaV07XG5cblx0XHRsZXQgc3Ryb2tlU3R5bGUgPSBzLl9zdHJva2U7XG5cdFx0bGV0IGZpbGxTdHlsZSAgID0gcy5fZmlsbDtcblxuXHRcdGxldCB7IHN0cm9rZSwgZmlsbCwgY2xpcDogZ2Fwc0NsaXAsIGZsYWdzIH0gPSBzLl9wYXRocztcblx0XHRsZXQgYm91bmRzQ2xpcCA9IG51bGw7XG5cdFx0bGV0IHdpZHRoID0gcm91bmREZWMocy53aWR0aCAqIHB4UmF0aW8sIDMpO1xuXHRcdGxldCBvZmZzZXQgPSAod2lkdGggJSAyKSAvIDI7XG5cblx0XHRpZiAoX3BvaW50cyAmJiBmaWxsU3R5bGUgPT0gbnVsbClcblx0XHRcdGZpbGxTdHlsZSA9IHdpZHRoID4gMCA/IFwiI2ZmZlwiIDogc3Ryb2tlU3R5bGU7XG5cblx0XHRsZXQgX3B4QWxpZ24gPSBzLnB4QWxpZ24gPT0gMTtcblxuXHRcdF9weEFsaWduICYmIGN0eC50cmFuc2xhdGUob2Zmc2V0LCBvZmZzZXQpO1xuXG5cdFx0aWYgKCFfcG9pbnRzKSB7XG5cdFx0XHRsZXQgbGZ0ID0gcGxvdExmdCxcblx0XHRcdFx0dG9wID0gcGxvdFRvcCxcblx0XHRcdFx0d2lkID0gcGxvdFdpZCxcblx0XHRcdFx0aGd0ID0gcGxvdEhndDtcblxuXHRcdFx0bGV0IGhhbGZXaWQgPSB3aWR0aCAqIHB4UmF0aW8gLyAyO1xuXG5cdFx0XHRpZiAocy5taW4gPT0gMClcblx0XHRcdFx0aGd0ICs9IGhhbGZXaWQ7XG5cblx0XHRcdGlmIChzLm1heCA9PSAwKSB7XG5cdFx0XHRcdHRvcCAtPSBoYWxmV2lkO1xuXHRcdFx0XHRoZ3QgKz0gaGFsZldpZDtcblx0XHRcdH1cblxuXHRcdFx0Ym91bmRzQ2xpcCA9IG5ldyBQYXRoMkQoKTtcblx0XHRcdGJvdW5kc0NsaXAucmVjdChsZnQsIHRvcCwgd2lkLCBoZ3QpO1xuXHRcdH1cblxuXHRcdC8vIHRoZSBwb2ludHMgcGF0aGJ1aWxkZXIncyBnYXBzQ2xpcCBpcyBpdHMgYm91bmRzQ2xpcCwgc2luY2UgcG9pbnRzIGRvbnQgbmVlZCBnYXBzIGNsaXBwaW5nLCBhbmQgYm91bmRzIGRlcGVuZCBvbiBwb2ludCBzaXplXG5cdFx0aWYgKF9wb2ludHMpXG5cdFx0XHRzdHJva2VGaWxsKHN0cm9rZVN0eWxlLCB3aWR0aCwgcy5kYXNoLCBzLmNhcCwgZmlsbFN0eWxlLCBzdHJva2UsIGZpbGwsIGZsYWdzLCBnYXBzQ2xpcCk7XG5cdFx0ZWxzZVxuXHRcdFx0ZmlsbFN0cm9rZShzaSwgc3Ryb2tlU3R5bGUsIHdpZHRoLCBzLmRhc2gsIHMuY2FwLCBmaWxsU3R5bGUsIHN0cm9rZSwgZmlsbCwgZmxhZ3MsIGJvdW5kc0NsaXAsIGdhcHNDbGlwKTtcblxuXHRcdF9weEFsaWduICYmIGN0eC50cmFuc2xhdGUoLW9mZnNldCwgLW9mZnNldCk7XG5cdH1cblxuXHRmdW5jdGlvbiBmaWxsU3Ryb2tlKHNpLCBzdHJva2VTdHlsZSwgbGluZVdpZHRoLCBsaW5lRGFzaCwgbGluZUNhcCwgZmlsbFN0eWxlLCBzdHJva2VQYXRoLCBmaWxsUGF0aCwgZmxhZ3MsIGJvdW5kc0NsaXAsIGdhcHNDbGlwKSB7XG5cdFx0bGV0IGRpZFN0cm9rZUZpbGwgPSBmYWxzZTtcblxuXHRcdC8vIGZvciBhbGwgYmFuZHMgd2hlcmUgdGhpcyBzZXJpZXMgaXMgdGhlIHRvcCBlZGdlLCBjcmVhdGUgdXB3YXJkcyBjbGlwcyB1c2luZyB0aGUgYm90dG9tIGVkZ2VzXG5cdFx0Ly8gYW5kIGFwcGx5IGNsaXBzICsgZmlsbCB3aXRoIGJhbmQgZmlsbCBvciBkZmx0RmlsbFxuXHRcdGJhbmRzLmZvckVhY2goKGIsIGJpKSA9PiB7XG5cdFx0XHQvLyBpc1VwcGVyRWRnZT9cblx0XHRcdGlmIChiLnNlcmllc1swXSA9PSBzaSkge1xuXHRcdFx0XHRsZXQgbG93ZXJFZGdlID0gc2VyaWVzW2Iuc2VyaWVzWzFdXTtcblx0XHRcdFx0bGV0IGxvd2VyRGF0YSA9IGRhdGFbYi5zZXJpZXNbMV1dO1xuXG5cdFx0XHRcdGxldCBiYW5kQ2xpcCA9IChsb3dlckVkZ2UuX3BhdGhzIHx8IEVNUFRZX09CSikuYmFuZDtcblxuXHRcdFx0XHRpZiAoaXNBcnIoYmFuZENsaXApKVxuXHRcdFx0XHRcdGJhbmRDbGlwID0gYi5kaXIgPT0gMSA/IGJhbmRDbGlwWzBdIDogYmFuZENsaXBbMV07XG5cblx0XHRcdFx0bGV0IGdhcHNDbGlwMjtcblxuXHRcdFx0XHRsZXQgX2ZpbGxTdHlsZSA9IG51bGw7XG5cblx0XHRcdFx0Ly8gaGFzTG93ZXJFZGdlP1xuXHRcdFx0XHRpZiAobG93ZXJFZGdlLnNob3cgJiYgYmFuZENsaXAgJiYgaGFzRGF0YShsb3dlckRhdGEsIGkwLCBpMSkpIHtcblx0XHRcdFx0XHRfZmlsbFN0eWxlID0gYi5maWxsKHNlbGYsIGJpKSB8fCBmaWxsU3R5bGU7XG5cdFx0XHRcdFx0Z2Fwc0NsaXAyID0gbG93ZXJFZGdlLl9wYXRocy5jbGlwO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHRiYW5kQ2xpcCA9IG51bGw7XG5cblx0XHRcdFx0c3Ryb2tlRmlsbChzdHJva2VTdHlsZSwgbGluZVdpZHRoLCBsaW5lRGFzaCwgbGluZUNhcCwgX2ZpbGxTdHlsZSwgc3Ryb2tlUGF0aCwgZmlsbFBhdGgsIGZsYWdzLCBib3VuZHNDbGlwLCBnYXBzQ2xpcCwgZ2Fwc0NsaXAyLCBiYW5kQ2xpcCk7XG5cblx0XHRcdFx0ZGlkU3Ryb2tlRmlsbCA9IHRydWU7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHRpZiAoIWRpZFN0cm9rZUZpbGwpXG5cdFx0XHRzdHJva2VGaWxsKHN0cm9rZVN0eWxlLCBsaW5lV2lkdGgsIGxpbmVEYXNoLCBsaW5lQ2FwLCBmaWxsU3R5bGUsIHN0cm9rZVBhdGgsIGZpbGxQYXRoLCBmbGFncywgYm91bmRzQ2xpcCwgZ2Fwc0NsaXApO1xuXHR9XG5cblx0Y29uc3QgQ0xJUF9GSUxMX1NUUk9LRSA9IEJBTkRfQ0xJUF9GSUxMIHwgQkFORF9DTElQX1NUUk9LRTtcblxuXHRmdW5jdGlvbiBzdHJva2VGaWxsKHN0cm9rZVN0eWxlLCBsaW5lV2lkdGgsIGxpbmVEYXNoLCBsaW5lQ2FwLCBmaWxsU3R5bGUsIHN0cm9rZVBhdGgsIGZpbGxQYXRoLCBmbGFncywgYm91bmRzQ2xpcCwgZ2Fwc0NsaXAsIGdhcHNDbGlwMiwgYmFuZENsaXApIHtcblx0XHRzZXRDdHhTdHlsZShzdHJva2VTdHlsZSwgbGluZVdpZHRoLCBsaW5lRGFzaCwgbGluZUNhcCwgZmlsbFN0eWxlKTtcblxuXHRcdGlmIChib3VuZHNDbGlwIHx8IGdhcHNDbGlwIHx8IGJhbmRDbGlwKSB7XG5cdFx0XHRjdHguc2F2ZSgpO1xuXHRcdFx0Ym91bmRzQ2xpcCAmJiBjdHguY2xpcChib3VuZHNDbGlwKTtcblx0XHRcdGdhcHNDbGlwICYmIGN0eC5jbGlwKGdhcHNDbGlwKTtcblx0XHR9XG5cblx0XHRpZiAoYmFuZENsaXApIHtcblx0XHRcdGlmICgoZmxhZ3MgJiBDTElQX0ZJTExfU1RST0tFKSA9PSBDTElQX0ZJTExfU1RST0tFKSB7XG5cdFx0XHRcdGN0eC5jbGlwKGJhbmRDbGlwKTtcblx0XHRcdFx0Z2Fwc0NsaXAyICYmIGN0eC5jbGlwKGdhcHNDbGlwMik7XG5cdFx0XHRcdGRvRmlsbChmaWxsU3R5bGUsIGZpbGxQYXRoKTtcblx0XHRcdFx0ZG9TdHJva2Uoc3Ryb2tlU3R5bGUsIHN0cm9rZVBhdGgsIGxpbmVXaWR0aCk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIGlmIChmbGFncyAmIEJBTkRfQ0xJUF9TVFJPS0UpIHtcblx0XHRcdFx0ZG9GaWxsKGZpbGxTdHlsZSwgZmlsbFBhdGgpO1xuXHRcdFx0XHRjdHguY2xpcChiYW5kQ2xpcCk7XG5cdFx0XHRcdGRvU3Ryb2tlKHN0cm9rZVN0eWxlLCBzdHJva2VQYXRoLCBsaW5lV2lkdGgpO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSBpZiAoZmxhZ3MgJiBCQU5EX0NMSVBfRklMTCkge1xuXHRcdFx0XHRjdHguc2F2ZSgpO1xuXHRcdFx0XHRjdHguY2xpcChiYW5kQ2xpcCk7XG5cdFx0XHRcdGdhcHNDbGlwMiAmJiBjdHguY2xpcChnYXBzQ2xpcDIpO1xuXHRcdFx0XHRkb0ZpbGwoZmlsbFN0eWxlLCBmaWxsUGF0aCk7XG5cdFx0XHRcdGN0eC5yZXN0b3JlKCk7XG5cdFx0XHRcdGRvU3Ryb2tlKHN0cm9rZVN0eWxlLCBzdHJva2VQYXRoLCBsaW5lV2lkdGgpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGRvRmlsbChmaWxsU3R5bGUsIGZpbGxQYXRoKTtcblx0XHRcdGRvU3Ryb2tlKHN0cm9rZVN0eWxlLCBzdHJva2VQYXRoLCBsaW5lV2lkdGgpO1xuXHRcdH1cblxuXHRcdGlmIChib3VuZHNDbGlwIHx8IGdhcHNDbGlwIHx8IGJhbmRDbGlwKVxuXHRcdFx0Y3R4LnJlc3RvcmUoKTtcblx0fVxuXG5cdGZ1bmN0aW9uIGRvU3Ryb2tlKHN0cm9rZVN0eWxlLCBzdHJva2VQYXRoLCBsaW5lV2lkdGgpIHtcblx0XHRpZiAobGluZVdpZHRoID4gMCkge1xuXHRcdFx0aWYgKHN0cm9rZVBhdGggaW5zdGFuY2VvZiBNYXApIHtcblx0XHRcdFx0c3Ryb2tlUGF0aC5mb3JFYWNoKChzdHJva2VQYXRoLCBzdHJva2VTdHlsZSkgPT4ge1xuXHRcdFx0XHRcdGN0eC5zdHJva2VTdHlsZSA9IGN0eFN0cm9rZSA9IHN0cm9rZVN0eWxlO1xuXHRcdFx0XHRcdGN0eC5zdHJva2Uoc3Ryb2tlUGF0aCk7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZVxuXHRcdFx0XHRzdHJva2VQYXRoICE9IG51bGwgJiYgc3Ryb2tlU3R5bGUgJiYgY3R4LnN0cm9rZShzdHJva2VQYXRoKTtcblx0XHR9XG5cdH1cblxuXHRmdW5jdGlvbiBkb0ZpbGwoZmlsbFN0eWxlLCBmaWxsUGF0aCkge1xuXHRcdGlmIChmaWxsUGF0aCBpbnN0YW5jZW9mIE1hcCkge1xuXHRcdFx0ZmlsbFBhdGguZm9yRWFjaCgoZmlsbFBhdGgsIGZpbGxTdHlsZSkgPT4ge1xuXHRcdFx0XHRjdHguZmlsbFN0eWxlID0gY3R4RmlsbCA9IGZpbGxTdHlsZTtcblx0XHRcdFx0Y3R4LmZpbGwoZmlsbFBhdGgpO1xuXHRcdFx0fSk7XG5cdFx0fVxuXHRcdGVsc2Vcblx0XHRcdGZpbGxQYXRoICE9IG51bGwgJiYgZmlsbFN0eWxlICYmIGN0eC5maWxsKGZpbGxQYXRoKTtcblx0fVxuXG5cdGZ1bmN0aW9uIGdldEluY3JTcGFjZShheGlzSWR4LCBtaW4sIG1heCwgZnVsbERpbSkge1xuXHRcdGxldCBheGlzID0gYXhlc1theGlzSWR4XTtcblxuXHRcdGxldCBpbmNyU3BhY2U7XG5cblx0XHRpZiAoZnVsbERpbSA8PSAwKVxuXHRcdFx0aW5jclNwYWNlID0gWzAsIDBdO1xuXHRcdGVsc2Uge1xuXHRcdFx0bGV0IG1pblNwYWNlID0gYXhpcy5fc3BhY2UgPSBheGlzLnNwYWNlKHNlbGYsIGF4aXNJZHgsIG1pbiwgbWF4LCBmdWxsRGltKTtcblx0XHRcdGxldCBpbmNycyAgICA9IGF4aXMuX2luY3JzID0gYXhpcy5pbmNycyhzZWxmLCBheGlzSWR4LCBtaW4sIG1heCwgZnVsbERpbSwgbWluU3BhY2UpO1xuXHRcdFx0aW5jclNwYWNlICAgID0gZmluZEluY3IobWluLCBtYXgsIGluY3JzLCBmdWxsRGltLCBtaW5TcGFjZSk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIChheGlzLl9mb3VuZCA9IGluY3JTcGFjZSk7XG5cdH1cblxuXHRmdW5jdGlvbiBkcmF3T3J0aG9MaW5lcyhvZmZzLCBmaWx0cywgb3JpLCBzaWRlLCBwb3MwLCBsZW4sIHdpZHRoLCBzdHJva2UsIGRhc2gsIGNhcCkge1xuXHRcdGxldCBvZmZzZXQgPSAod2lkdGggJSAyKSAvIDI7XG5cblx0XHRweEFsaWduID09IDEgJiYgY3R4LnRyYW5zbGF0ZShvZmZzZXQsIG9mZnNldCk7XG5cblx0XHRzZXRDdHhTdHlsZShzdHJva2UsIHdpZHRoLCBkYXNoLCBjYXAsIHN0cm9rZSk7XG5cblx0XHRjdHguYmVnaW5QYXRoKCk7XG5cblx0XHRsZXQgeDAsIHkwLCB4MSwgeTEsIHBvczEgPSBwb3MwICsgKHNpZGUgPT0gMCB8fCBzaWRlID09IDMgPyAtbGVuIDogbGVuKTtcblxuXHRcdGlmIChvcmkgPT0gMCkge1xuXHRcdFx0eTAgPSBwb3MwO1xuXHRcdFx0eTEgPSBwb3MxO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdHgwID0gcG9zMDtcblx0XHRcdHgxID0gcG9zMTtcblx0XHR9XG5cblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IG9mZnMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGlmIChmaWx0c1tpXSAhPSBudWxsKSB7XG5cdFx0XHRcdGlmIChvcmkgPT0gMClcblx0XHRcdFx0XHR4MCA9IHgxID0gb2Zmc1tpXTtcblx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdHkwID0geTEgPSBvZmZzW2ldO1xuXG5cdFx0XHRcdGN0eC5tb3ZlVG8oeDAsIHkwKTtcblx0XHRcdFx0Y3R4LmxpbmVUbyh4MSwgeTEpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGN0eC5zdHJva2UoKTtcblxuXHRcdHB4QWxpZ24gPT0gMSAmJiBjdHgudHJhbnNsYXRlKC1vZmZzZXQsIC1vZmZzZXQpO1xuXHR9XG5cblx0ZnVuY3Rpb24gYXhlc0NhbGMoY3ljbGVOdW0pIHtcblx0Ly9cdGxvZyhcImF4ZXNDYWxjKClcIiwgYXJndW1lbnRzKTtcblxuXHRcdGxldCBjb252ZXJnZWQgPSB0cnVlO1xuXG5cdFx0YXhlcy5mb3JFYWNoKChheGlzLCBpKSA9PiB7XG5cdFx0XHRpZiAoIWF4aXMuc2hvdylcblx0XHRcdFx0cmV0dXJuO1xuXG5cdFx0XHRsZXQgc2NhbGUgPSBzY2FsZXNbYXhpcy5zY2FsZV07XG5cblx0XHRcdGlmIChzY2FsZS5taW4gPT0gbnVsbCkge1xuXHRcdFx0XHRpZiAoYXhpcy5fc2hvdykge1xuXHRcdFx0XHRcdGNvbnZlcmdlZCA9IGZhbHNlO1xuXHRcdFx0XHRcdGF4aXMuX3Nob3cgPSBmYWxzZTtcblx0XHRcdFx0XHRyZXNldFlTZXJpZXMoZmFsc2UpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHRpZiAoIWF4aXMuX3Nob3cpIHtcblx0XHRcdFx0XHRjb252ZXJnZWQgPSBmYWxzZTtcblx0XHRcdFx0XHRheGlzLl9zaG93ID0gdHJ1ZTtcblx0XHRcdFx0XHRyZXNldFlTZXJpZXMoZmFsc2UpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGxldCBzaWRlID0gYXhpcy5zaWRlO1xuXHRcdFx0bGV0IG9yaSA9IHNpZGUgJSAyO1xuXG5cdFx0XHRsZXQge21pbiwgbWF4fSA9IHNjYWxlO1x0XHQvLyBcdFx0Ly8gc2hvdWxkIHRoaXMgdG9nZ2xlIHRoZW0gLl9zaG93ID0gZmFsc2VcblxuXHRcdFx0bGV0IFtfaW5jciwgX3NwYWNlXSA9IGdldEluY3JTcGFjZShpLCBtaW4sIG1heCwgb3JpID09IDAgPyBwbG90V2lkQ3NzIDogcGxvdEhndENzcyk7XG5cblx0XHRcdGlmIChfc3BhY2UgPT0gMClcblx0XHRcdFx0cmV0dXJuO1xuXG5cdFx0XHQvLyBpZiB3ZSdyZSB1c2luZyBpbmRleCBwb3NpdGlvbnMsIGZvcmNlIGZpcnN0IHRpY2sgdG8gbWF0Y2ggcGFzc2VkIGluZGV4XG5cdFx0XHRsZXQgZm9yY2VNaW4gPSBzY2FsZS5kaXN0ciA9PSAyO1xuXG5cdFx0XHRsZXQgX3NwbGl0cyA9IGF4aXMuX3NwbGl0cyA9IGF4aXMuc3BsaXRzKHNlbGYsIGksIG1pbiwgbWF4LCBfaW5jciwgX3NwYWNlLCBmb3JjZU1pbik7XG5cblx0XHRcdC8vIHRpY2sgbGFiZWxzXG5cdFx0XHQvLyBCT08gdGhpcyBhc3N1bWVzIGEgc3BlY2lmaWMgZGF0YS9zZXJpZXNcblx0XHRcdGxldCBzcGxpdHMgPSBzY2FsZS5kaXN0ciA9PSAyID8gX3NwbGl0cy5tYXAoaSA9PiBkYXRhMFtpXSkgOiBfc3BsaXRzO1xuXHRcdFx0bGV0IGluY3IgICA9IHNjYWxlLmRpc3RyID09IDIgPyBkYXRhMFtfc3BsaXRzWzFdXSAtIGRhdGEwW19zcGxpdHNbMF1dIDogX2luY3I7XG5cblx0XHRcdGxldCB2YWx1ZXMgPSBheGlzLl92YWx1ZXMgPSBheGlzLnZhbHVlcyhzZWxmLCBheGlzLmZpbHRlcihzZWxmLCBzcGxpdHMsIGksIF9zcGFjZSwgaW5jciksIGksIF9zcGFjZSwgaW5jcik7XG5cblx0XHRcdC8vIHJvdGF0aW5nIG9mIGxhYmVscyBvbmx5IHN1cHBvcnRlZCBvbiBib3R0b20geCBheGlzXG5cdFx0XHRheGlzLl9yb3RhdGUgPSBzaWRlID09IDIgPyBheGlzLnJvdGF0ZShzZWxmLCB2YWx1ZXMsIGksIF9zcGFjZSkgOiAwO1xuXG5cdFx0XHRsZXQgb2xkU2l6ZSA9IGF4aXMuX3NpemU7XG5cblx0XHRcdGF4aXMuX3NpemUgPSBjZWlsKGF4aXMuc2l6ZShzZWxmLCB2YWx1ZXMsIGksIGN5Y2xlTnVtKSk7XG5cblx0XHRcdGlmIChvbGRTaXplICE9IG51bGwgJiYgYXhpcy5fc2l6ZSAhPSBvbGRTaXplKVx0XHRcdC8vIHJlYWR5ICYmID9cblx0XHRcdFx0Y29udmVyZ2VkID0gZmFsc2U7XG5cdFx0fSk7XG5cblx0XHRyZXR1cm4gY29udmVyZ2VkO1xuXHR9XG5cblx0ZnVuY3Rpb24gcGFkZGluZ0NhbGMoY3ljbGVOdW0pIHtcblx0XHRsZXQgY29udmVyZ2VkID0gdHJ1ZTtcblxuXHRcdHBhZGRpbmcuZm9yRWFjaCgocCwgaSkgPT4ge1xuXHRcdFx0bGV0IF9wID0gcChzZWxmLCBpLCBzaWRlc1dpdGhBeGVzLCBjeWNsZU51bSk7XG5cblx0XHRcdGlmIChfcCAhPSBfcGFkZGluZ1tpXSlcblx0XHRcdFx0Y29udmVyZ2VkID0gZmFsc2U7XG5cblx0XHRcdF9wYWRkaW5nW2ldID0gX3A7XG5cdFx0fSk7XG5cblx0XHRyZXR1cm4gY29udmVyZ2VkO1xuXHR9XG5cblx0ZnVuY3Rpb24gZHJhd0F4ZXNHcmlkKCkge1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgYXhlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0bGV0IGF4aXMgPSBheGVzW2ldO1xuXG5cdFx0XHRpZiAoIWF4aXMuc2hvdyB8fCAhYXhpcy5fc2hvdylcblx0XHRcdFx0Y29udGludWU7XG5cblx0XHRcdGxldCBzaWRlID0gYXhpcy5zaWRlO1xuXHRcdFx0bGV0IG9yaSA9IHNpZGUgJSAyO1xuXG5cdFx0XHRsZXQgeCwgeTtcblxuXHRcdFx0bGV0IGZpbGxTdHlsZSA9IGF4aXMuc3Ryb2tlKHNlbGYsIGkpO1xuXG5cdFx0XHRsZXQgc2hpZnREaXIgPSBzaWRlID09IDAgfHwgc2lkZSA9PSAzID8gLTEgOiAxO1xuXG5cdFx0XHQvLyBheGlzIGxhYmVsXG5cdFx0XHRpZiAoYXhpcy5sYWJlbCkge1xuXHRcdFx0XHRsZXQgc2hpZnRBbXQgPSBheGlzLmxhYmVsR2FwICogc2hpZnREaXI7XG5cdFx0XHRcdGxldCBiYXNlTHBvcyA9IHJvdW5kKChheGlzLl9scG9zICsgc2hpZnRBbXQpICogcHhSYXRpbyk7XG5cblx0XHRcdFx0c2V0Rm9udFN0eWxlKGF4aXMubGFiZWxGb250WzBdLCBmaWxsU3R5bGUsIFwiY2VudGVyXCIsIHNpZGUgPT0gMiA/IFRPUCA6IEJPVFRPTSk7XG5cblx0XHRcdFx0Y3R4LnNhdmUoKTtcblxuXHRcdFx0XHRpZiAob3JpID09IDEpIHtcblx0XHRcdFx0XHR4ID0geSA9IDA7XG5cblx0XHRcdFx0XHRjdHgudHJhbnNsYXRlKFxuXHRcdFx0XHRcdFx0YmFzZUxwb3MsXG5cdFx0XHRcdFx0XHRyb3VuZChwbG90VG9wICsgcGxvdEhndCAvIDIpLFxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0Y3R4LnJvdGF0ZSgoc2lkZSA9PSAzID8gLVBJIDogUEkpIC8gMik7XG5cblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHR4ID0gcm91bmQocGxvdExmdCArIHBsb3RXaWQgLyAyKTtcblx0XHRcdFx0XHR5ID0gYmFzZUxwb3M7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRjdHguZmlsbFRleHQoYXhpcy5sYWJlbCwgeCwgeSk7XG5cblx0XHRcdFx0Y3R4LnJlc3RvcmUoKTtcblx0XHRcdH1cblxuXHRcdFx0bGV0IFtfaW5jciwgX3NwYWNlXSA9IGF4aXMuX2ZvdW5kO1xuXG5cdFx0XHRpZiAoX3NwYWNlID09IDApXG5cdFx0XHRcdGNvbnRpbnVlO1xuXG5cdFx0XHRsZXQgc2NhbGUgPSBzY2FsZXNbYXhpcy5zY2FsZV07XG5cblx0XHRcdGxldCBwbG90RGltID0gb3JpID09IDAgPyBwbG90V2lkIDogcGxvdEhndDtcblx0XHRcdGxldCBwbG90T2ZmID0gb3JpID09IDAgPyBwbG90TGZ0IDogcGxvdFRvcDtcblxuXHRcdFx0bGV0IGF4aXNHYXAgPSByb3VuZChheGlzLmdhcCAqIHB4UmF0aW8pO1xuXG5cdFx0XHRsZXQgX3NwbGl0cyA9IGF4aXMuX3NwbGl0cztcblxuXHRcdFx0Ly8gdGljayBsYWJlbHNcblx0XHRcdC8vIEJPTyB0aGlzIGFzc3VtZXMgYSBzcGVjaWZpYyBkYXRhL3Nlcmllc1xuXHRcdFx0bGV0IHNwbGl0cyA9IHNjYWxlLmRpc3RyID09IDIgPyBfc3BsaXRzLm1hcChpID0+IGRhdGEwW2ldKSA6IF9zcGxpdHM7XG5cdFx0XHRsZXQgaW5jciAgID0gc2NhbGUuZGlzdHIgPT0gMiA/IGRhdGEwW19zcGxpdHNbMV1dIC0gZGF0YTBbX3NwbGl0c1swXV0gOiBfaW5jcjtcblxuXHRcdFx0bGV0IHRpY2tzID0gYXhpcy50aWNrcztcblx0XHRcdGxldCBib3JkZXIgPSBheGlzLmJvcmRlcjtcblx0XHRcdGxldCB0aWNrU2l6ZSA9IHRpY2tzLnNob3cgPyByb3VuZCh0aWNrcy5zaXplICogcHhSYXRpbykgOiAwO1xuXG5cdFx0XHQvLyByb3RhdGluZyBvZiBsYWJlbHMgb25seSBzdXBwb3J0ZWQgb24gYm90dG9tIHggYXhpc1xuXHRcdFx0bGV0IGFuZ2xlID0gYXhpcy5fcm90YXRlICogLVBJLzE4MDtcblxuXHRcdFx0bGV0IGJhc2VQb3MgID0gcHhSb3VuZChheGlzLl9wb3MgKiBweFJhdGlvKTtcblx0XHRcdGxldCBzaGlmdEFtdCA9ICh0aWNrU2l6ZSArIGF4aXNHYXApICogc2hpZnREaXI7XG5cdFx0XHRsZXQgZmluYWxQb3MgPSBiYXNlUG9zICsgc2hpZnRBbXQ7XG5cdFx0XHQgICAgeSAgICAgICAgPSBvcmkgPT0gMCA/IGZpbmFsUG9zIDogMDtcblx0XHRcdCAgICB4ICAgICAgICA9IG9yaSA9PSAxID8gZmluYWxQb3MgOiAwO1xuXG5cdFx0XHRsZXQgZm9udCAgICAgICAgID0gYXhpcy5mb250WzBdO1xuXHRcdFx0bGV0IHRleHRBbGlnbiAgICA9IGF4aXMuYWxpZ24gPT0gMSA/IExFRlQgOlxuXHRcdFx0ICAgICAgICAgICAgICAgICAgIGF4aXMuYWxpZ24gPT0gMiA/IFJJR0hUIDpcblx0XHRcdCAgICAgICAgICAgICAgICAgICBhbmdsZSA+IDAgPyBMRUZUIDpcblx0XHRcdCAgICAgICAgICAgICAgICAgICBhbmdsZSA8IDAgPyBSSUdIVCA6XG5cdFx0XHQgICAgICAgICAgICAgICAgICAgb3JpID09IDAgPyBcImNlbnRlclwiIDogc2lkZSA9PSAzID8gUklHSFQgOiBMRUZUO1xuXHRcdFx0bGV0IHRleHRCYXNlbGluZSA9IGFuZ2xlIHx8XG5cdFx0XHQgICAgICAgICAgICAgICAgICAgb3JpID09IDEgPyBcIm1pZGRsZVwiIDogc2lkZSA9PSAyID8gVE9QICAgOiBCT1RUT007XG5cblx0XHRcdHNldEZvbnRTdHlsZShmb250LCBmaWxsU3R5bGUsIHRleHRBbGlnbiwgdGV4dEJhc2VsaW5lKTtcblxuXHRcdFx0bGV0IGxpbmVIZWlnaHQgPSBheGlzLmZvbnRbMV0gKiBsaW5lTXVsdDtcblxuXHRcdFx0bGV0IGNhbk9mZnMgPSBfc3BsaXRzLm1hcCh2YWwgPT4gcHhSb3VuZChnZXRQb3ModmFsLCBzY2FsZSwgcGxvdERpbSwgcGxvdE9mZikpKTtcblxuXHRcdFx0bGV0IF92YWx1ZXMgPSBheGlzLl92YWx1ZXM7XG5cblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgX3ZhbHVlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHRsZXQgdmFsID0gX3ZhbHVlc1tpXTtcblxuXHRcdFx0XHRpZiAodmFsICE9IG51bGwpIHtcblx0XHRcdFx0XHRpZiAob3JpID09IDApXG5cdFx0XHRcdFx0XHR4ID0gY2FuT2Zmc1tpXTtcblx0XHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0XHR5ID0gY2FuT2Zmc1tpXTtcblxuXHRcdFx0XHRcdHZhbCA9IFwiXCIgKyB2YWw7XG5cblx0XHRcdFx0XHRsZXQgX3BhcnRzID0gdmFsLmluZGV4T2YoXCJcXG5cIikgPT0gLTEgPyBbdmFsXSA6IHZhbC5zcGxpdCgvXFxuL2dtKTtcblxuXHRcdFx0XHRcdGZvciAobGV0IGogPSAwOyBqIDwgX3BhcnRzLmxlbmd0aDsgaisrKSB7XG5cdFx0XHRcdFx0XHRsZXQgdGV4dCA9IF9wYXJ0c1tqXTtcblxuXHRcdFx0XHRcdFx0aWYgKGFuZ2xlKSB7XG5cdFx0XHRcdFx0XHRcdGN0eC5zYXZlKCk7XG5cdFx0XHRcdFx0XHRcdGN0eC50cmFuc2xhdGUoeCwgeSArIGogKiBsaW5lSGVpZ2h0KTsgLy8gY2FuIHRoaXMgYmUgcmVwbGFjZWQgd2l0aCBwb3NpdGlvbiBtYXRoP1xuXHRcdFx0XHRcdFx0XHRjdHgucm90YXRlKGFuZ2xlKTsgLy8gY2FuIHRoaXMgYmUgZG9uZSBvbmNlP1xuXHRcdFx0XHRcdFx0XHRjdHguZmlsbFRleHQodGV4dCwgMCwgMCk7XG5cdFx0XHRcdFx0XHRcdGN0eC5yZXN0b3JlKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0XHRcdGN0eC5maWxsVGV4dCh0ZXh0LCB4LCB5ICsgaiAqIGxpbmVIZWlnaHQpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyB0aWNrc1xuXHRcdFx0aWYgKHRpY2tzLnNob3cpIHtcblx0XHRcdFx0ZHJhd09ydGhvTGluZXMoXG5cdFx0XHRcdFx0Y2FuT2Zmcyxcblx0XHRcdFx0XHR0aWNrcy5maWx0ZXIoc2VsZiwgc3BsaXRzLCBpLCBfc3BhY2UsIGluY3IpLFxuXHRcdFx0XHRcdG9yaSxcblx0XHRcdFx0XHRzaWRlLFxuXHRcdFx0XHRcdGJhc2VQb3MsXG5cdFx0XHRcdFx0dGlja1NpemUsXG5cdFx0XHRcdFx0cm91bmREZWModGlja3Mud2lkdGggKiBweFJhdGlvLCAzKSxcblx0XHRcdFx0XHR0aWNrcy5zdHJva2Uoc2VsZiwgaSksXG5cdFx0XHRcdFx0dGlja3MuZGFzaCxcblx0XHRcdFx0XHR0aWNrcy5jYXAsXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIGdyaWRcblx0XHRcdGxldCBncmlkID0gYXhpcy5ncmlkO1xuXG5cdFx0XHRpZiAoZ3JpZC5zaG93KSB7XG5cdFx0XHRcdGRyYXdPcnRob0xpbmVzKFxuXHRcdFx0XHRcdGNhbk9mZnMsXG5cdFx0XHRcdFx0Z3JpZC5maWx0ZXIoc2VsZiwgc3BsaXRzLCBpLCBfc3BhY2UsIGluY3IpLFxuXHRcdFx0XHRcdG9yaSxcblx0XHRcdFx0XHRvcmkgPT0gMCA/IDIgOiAxLFxuXHRcdFx0XHRcdG9yaSA9PSAwID8gcGxvdFRvcCA6IHBsb3RMZnQsXG5cdFx0XHRcdFx0b3JpID09IDAgPyBwbG90SGd0IDogcGxvdFdpZCxcblx0XHRcdFx0XHRyb3VuZERlYyhncmlkLndpZHRoICogcHhSYXRpbywgMyksXG5cdFx0XHRcdFx0Z3JpZC5zdHJva2Uoc2VsZiwgaSksXG5cdFx0XHRcdFx0Z3JpZC5kYXNoLFxuXHRcdFx0XHRcdGdyaWQuY2FwLFxuXHRcdFx0XHQpO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoYm9yZGVyLnNob3cpIHtcblx0XHRcdFx0ZHJhd09ydGhvTGluZXMoXG5cdFx0XHRcdFx0W2Jhc2VQb3NdLFxuXHRcdFx0XHRcdFsxXSxcblx0XHRcdFx0XHRvcmkgPT0gMCA/IDEgOiAwLFxuXHRcdFx0XHRcdG9yaSA9PSAwID8gMSA6IDIsXG5cdFx0XHRcdFx0b3JpID09IDEgPyBwbG90VG9wIDogcGxvdExmdCxcblx0XHRcdFx0XHRvcmkgPT0gMSA/IHBsb3RIZ3QgOiBwbG90V2lkLFxuXHRcdFx0XHRcdHJvdW5kRGVjKGJvcmRlci53aWR0aCAqIHB4UmF0aW8sIDMpLFxuXHRcdFx0XHRcdGJvcmRlci5zdHJva2Uoc2VsZiwgaSksXG5cdFx0XHRcdFx0Ym9yZGVyLmRhc2gsXG5cdFx0XHRcdFx0Ym9yZGVyLmNhcCxcblx0XHRcdFx0KTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRmaXJlKFwiZHJhd0F4ZXNcIik7XG5cdH1cblxuXHRmdW5jdGlvbiByZXNldFlTZXJpZXMobWluTWF4KSB7XG5cdC8vXHRsb2coXCJyZXNldFlTZXJpZXMoKVwiLCBhcmd1bWVudHMpO1xuXG5cdFx0c2VyaWVzLmZvckVhY2goKHMsIGkpID0+IHtcblx0XHRcdGlmIChpID4gMCkge1xuXHRcdFx0XHRzLl9wYXRocyA9IG51bGw7XG5cblx0XHRcdFx0aWYgKG1pbk1heCkge1xuXHRcdFx0XHRcdGlmIChtb2RlID09IDEpIHtcblx0XHRcdFx0XHRcdHMubWluID0gbnVsbDtcblx0XHRcdFx0XHRcdHMubWF4ID0gbnVsbDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0XHRzLmZhY2V0cy5mb3JFYWNoKGYgPT4ge1xuXHRcdFx0XHRcdFx0XHRmLm1pbiA9IG51bGw7XG5cdFx0XHRcdFx0XHRcdGYubWF4ID0gbnVsbDtcblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0bGV0IHF1ZXVlZENvbW1pdCA9IGZhbHNlO1xuXG5cdGZ1bmN0aW9uIGNvbW1pdCgpIHtcblx0XHRpZiAoIXF1ZXVlZENvbW1pdCkge1xuXHRcdFx0bWljcm9UYXNrKF9jb21taXQpO1xuXHRcdFx0cXVldWVkQ29tbWl0ID0gdHJ1ZTtcblx0XHR9XG5cdH1cblxuXHRmdW5jdGlvbiBfY29tbWl0KCkge1xuXHQvL1x0bG9nKFwiX2NvbW1pdCgpXCIsIGFyZ3VtZW50cyk7XG5cblx0XHRpZiAoc2hvdWxkU2V0U2NhbGVzKSB7XG5cdFx0XHRzZXRTY2FsZXMoKTtcblx0XHRcdHNob3VsZFNldFNjYWxlcyA9IGZhbHNlO1xuXHRcdH1cblxuXHRcdGlmIChzaG91bGRDb252ZXJnZVNpemUpIHtcblx0XHRcdGNvbnZlcmdlU2l6ZSgpO1xuXHRcdFx0c2hvdWxkQ29udmVyZ2VTaXplID0gZmFsc2U7XG5cdFx0fVxuXG5cdFx0aWYgKHNob3VsZFNldFNpemUpIHtcblx0XHRcdHNldFN0eWxlUHgodW5kZXIsIExFRlQsICAgcGxvdExmdENzcyk7XG5cdFx0XHRzZXRTdHlsZVB4KHVuZGVyLCBUT1AsICAgIHBsb3RUb3BDc3MpO1xuXHRcdFx0c2V0U3R5bGVQeCh1bmRlciwgV0lEVEgsICBwbG90V2lkQ3NzKTtcblx0XHRcdHNldFN0eWxlUHgodW5kZXIsIEhFSUdIVCwgcGxvdEhndENzcyk7XG5cblx0XHRcdHNldFN0eWxlUHgob3ZlciwgTEVGVCwgICAgcGxvdExmdENzcyk7XG5cdFx0XHRzZXRTdHlsZVB4KG92ZXIsIFRPUCwgICAgIHBsb3RUb3BDc3MpO1xuXHRcdFx0c2V0U3R5bGVQeChvdmVyLCBXSURUSCwgICBwbG90V2lkQ3NzKTtcblx0XHRcdHNldFN0eWxlUHgob3ZlciwgSEVJR0hULCAgcGxvdEhndENzcyk7XG5cblx0XHRcdHNldFN0eWxlUHgod3JhcCwgV0lEVEgsICAgZnVsbFdpZENzcyk7XG5cdFx0XHRzZXRTdHlsZVB4KHdyYXAsIEhFSUdIVCwgIGZ1bGxIZ3RDc3MpO1xuXG5cdFx0XHQvLyBOT1RFOiBtdXRhdGluZyB0aGlzIGR1cmluZyBwcmludCBwcmV2aWV3IGluIENocm9tZSBmb3JjZXMgdHJhbnNwYXJlbnRcblx0XHRcdC8vIGNhbnZhcyBwaXhlbHMgdG8gd2hpdGUsIGV2ZW4gd2hlbiBmb2xsb3dlZCB1cCB3aXRoIGNsZWFyUmVjdCgpIGJlbG93XG5cdFx0XHRjYW4ud2lkdGggID0gcm91bmQoZnVsbFdpZENzcyAqIHB4UmF0aW8pO1xuXHRcdFx0Y2FuLmhlaWdodCA9IHJvdW5kKGZ1bGxIZ3RDc3MgKiBweFJhdGlvKTtcblxuXHRcdFx0YXhlcy5mb3JFYWNoKCh7IF9lbCwgX3Nob3csIF9zaXplLCBfcG9zLCBzaWRlIH0pID0+IHtcblx0XHRcdFx0aWYgKF9lbCAhPSBudWxsKSB7XG5cdFx0XHRcdFx0aWYgKF9zaG93KSB7XG5cdFx0XHRcdFx0XHRsZXQgcG9zT2Zmc2V0ID0gKHNpZGUgPT09IDMgfHwgc2lkZSA9PT0gMCA/IF9zaXplIDogMCk7XG5cdFx0XHRcdFx0XHRsZXQgaXNWdCA9IHNpZGUgJSAyID09IDE7XG5cblx0XHRcdFx0XHRcdHNldFN0eWxlUHgoX2VsLCBpc1Z0ID8gXCJsZWZ0XCIgICA6IFwidG9wXCIsICAgIF9wb3MgLSBwb3NPZmZzZXQpO1xuXHRcdFx0XHRcdFx0c2V0U3R5bGVQeChfZWwsIGlzVnQgPyBcIndpZHRoXCIgIDogXCJoZWlnaHRcIiwgX3NpemUpO1xuXHRcdFx0XHRcdFx0c2V0U3R5bGVQeChfZWwsIGlzVnQgPyBcInRvcFwiICAgIDogXCJsZWZ0XCIsICAgaXNWdCA/IHBsb3RUb3BDc3MgOiBwbG90TGZ0Q3NzKTtcblx0XHRcdFx0XHRcdHNldFN0eWxlUHgoX2VsLCBpc1Z0ID8gXCJoZWlnaHRcIiA6IFwid2lkdGhcIiwgIGlzVnQgPyBwbG90SGd0Q3NzIDogcGxvdFdpZENzcyk7XG5cblx0XHRcdFx0XHRcdHJlbUNsYXNzKF9lbCwgT0ZGKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdFx0YWRkQ2xhc3MoX2VsLCBPRkYpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblxuXHRcdFx0Ly8gaW52YWxpZGF0ZSBjdHggc3R5bGUgY2FjaGVcblx0XHRcdGN0eFN0cm9rZSA9IGN0eEZpbGwgPSBjdHhXaWR0aCA9IGN0eEpvaW4gPSBjdHhDYXAgPSBjdHhGb250ID0gY3R4QWxpZ24gPSBjdHhCYXNlbGluZSA9IGN0eERhc2ggPSBudWxsO1xuXHRcdFx0Y3R4QWxwaGEgPSAxO1xuXG5cdFx0XHRzeW5jUmVjdCh0cnVlKTtcblxuXHRcdFx0ZmlyZShcInNldFNpemVcIik7XG5cblx0XHRcdHNob3VsZFNldFNpemUgPSBmYWxzZTtcblx0XHR9XG5cblx0XHRpZiAoZnVsbFdpZENzcyA+IDAgJiYgZnVsbEhndENzcyA+IDApIHtcblx0XHRcdGN0eC5jbGVhclJlY3QoMCwgMCwgY2FuLndpZHRoLCBjYW4uaGVpZ2h0KTtcblx0XHRcdGZpcmUoXCJkcmF3Q2xlYXJcIik7XG5cdFx0XHRkcmF3T3JkZXIuZm9yRWFjaChmbiA9PiBmbigpKTtcblx0XHRcdGZpcmUoXCJkcmF3XCIpO1xuXHRcdH1cblxuXHQvL1x0aWYgKHNob3VsZFNldFNlbGVjdCkge1xuXHRcdC8vIFRPRE86IHVwZGF0ZSAudS1zZWxlY3QgbWV0cmljcyAoaWYgdmlzaWJsZSlcblx0XHQvL1x0c2V0U3R5bGVQeChzZWxlY3REaXYsIFRPUCwgc2VsZWN0LnRvcCA9IDApO1xuXHRcdC8vXHRzZXRTdHlsZVB4KHNlbGVjdERpdiwgTEVGVCwgc2VsZWN0LmxlZnQgPSAwKTtcblx0XHQvL1x0c2V0U3R5bGVQeChzZWxlY3REaXYsIFdJRFRILCBzZWxlY3Qud2lkdGggPSAwKTtcblx0XHQvL1x0c2V0U3R5bGVQeChzZWxlY3REaXYsIEhFSUdIVCwgc2VsZWN0LmhlaWdodCA9IDApO1xuXHRcdC8vXHRzaG91bGRTZXRTZWxlY3QgPSBmYWxzZTtcblx0Ly9cdH1cblxuXHRcdGlmIChjdXJzb3Iuc2hvdyAmJiBzaG91bGRTZXRDdXJzb3IpIHtcblx0XHRcdHVwZGF0ZUN1cnNvcihudWxsLCB0cnVlLCBmYWxzZSk7XG5cdFx0XHRzaG91bGRTZXRDdXJzb3IgPSBmYWxzZTtcblx0XHR9XG5cblx0Ly9cdGlmIChGRUFUX0xFR0VORCAmJiBsZWdlbmQuc2hvdyAmJiBsZWdlbmQubGl2ZSAmJiBzaG91bGRTZXRMZWdlbmQpIHt9XG5cblx0XHRpZiAoIXJlYWR5KSB7XG5cdFx0XHRyZWFkeSA9IHRydWU7XG5cdFx0XHRzZWxmLnN0YXR1cyA9IDE7XG5cblx0XHRcdGZpcmUoXCJyZWFkeVwiKTtcblx0XHR9XG5cblx0XHR2aWFBdXRvU2NhbGVYID0gZmFsc2U7XG5cblx0XHRxdWV1ZWRDb21taXQgPSBmYWxzZTtcblx0fVxuXG5cdHNlbGYucmVkcmF3ID0gKHJlYnVpbGRQYXRocywgcmVjYWxjQXhlcykgPT4ge1xuXHRcdHNob3VsZENvbnZlcmdlU2l6ZSA9IHJlY2FsY0F4ZXMgfHwgZmFsc2U7XG5cblx0XHRpZiAocmVidWlsZFBhdGhzICE9PSBmYWxzZSlcblx0XHRcdF9zZXRTY2FsZSh4U2NhbGVLZXksIHNjYWxlWC5taW4sIHNjYWxlWC5tYXgpO1xuXHRcdGVsc2Vcblx0XHRcdGNvbW1pdCgpO1xuXHR9O1xuXG5cdC8vIHJlZHJhdygpID0+IHNldFNjYWxlKCd4Jywgc2NhbGVzLngubWluLCBzY2FsZXMueC5tYXgpO1xuXG5cdC8vIGV4cGxpY2l0LCBuZXZlciByZS1yYW5nZWQgKGlzIHRoaXMgYWN0dWFsbHkgdHJ1ZT8gZm9yIHggYW5kIHkpXG5cdGZ1bmN0aW9uIHNldFNjYWxlKGtleSwgb3B0cykge1xuXHRcdGxldCBzYyA9IHNjYWxlc1trZXldO1xuXG5cdFx0aWYgKHNjLmZyb20gPT0gbnVsbCkge1xuXHRcdFx0aWYgKGRhdGFMZW4gPT0gMCkge1xuXHRcdFx0XHRsZXQgbWluTWF4ID0gc2MucmFuZ2Uoc2VsZiwgb3B0cy5taW4sIG9wdHMubWF4LCBrZXkpO1xuXHRcdFx0XHRvcHRzLm1pbiA9IG1pbk1heFswXTtcblx0XHRcdFx0b3B0cy5tYXggPSBtaW5NYXhbMV07XG5cdFx0XHR9XG5cblx0XHRcdGlmIChvcHRzLm1pbiA+IG9wdHMubWF4KSB7XG5cdFx0XHRcdGxldCBfbWluID0gb3B0cy5taW47XG5cdFx0XHRcdG9wdHMubWluID0gb3B0cy5tYXg7XG5cdFx0XHRcdG9wdHMubWF4ID0gX21pbjtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGRhdGFMZW4gPiAxICYmIG9wdHMubWluICE9IG51bGwgJiYgb3B0cy5tYXggIT0gbnVsbCAmJiBvcHRzLm1heCAtIG9wdHMubWluIDwgMWUtMTYpXG5cdFx0XHRcdHJldHVybjtcblxuXHRcdFx0aWYgKGtleSA9PSB4U2NhbGVLZXkpIHtcblx0XHRcdFx0aWYgKHNjLmRpc3RyID09IDIgJiYgZGF0YUxlbiA+IDApIHtcblx0XHRcdFx0XHRvcHRzLm1pbiA9IGNsb3Nlc3RJZHgob3B0cy5taW4sIGRhdGFbMF0pO1xuXHRcdFx0XHRcdG9wdHMubWF4ID0gY2xvc2VzdElkeChvcHRzLm1heCwgZGF0YVswXSk7XG5cblx0XHRcdFx0XHRpZiAob3B0cy5taW4gPT0gb3B0cy5tYXgpXG5cdFx0XHRcdFx0XHRvcHRzLm1heCsrO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHQvL1x0bG9nKFwic2V0U2NhbGUoKVwiLCBhcmd1bWVudHMpO1xuXG5cdFx0XHRwZW5kU2NhbGVzW2tleV0gPSBvcHRzO1xuXG5cdFx0XHRzaG91bGRTZXRTY2FsZXMgPSB0cnVlO1xuXHRcdFx0Y29tbWl0KCk7XG5cdFx0fVxuXHR9XG5cblx0c2VsZi5zZXRTY2FsZSA9IHNldFNjYWxlO1xuXG4vL1x0SU5URVJBQ1RJT05cblxuXHRsZXQgeEN1cnNvcjtcblx0bGV0IHlDdXJzb3I7XG5cdGxldCB2Q3Vyc29yO1xuXHRsZXQgaEN1cnNvcjtcblxuXHQvLyBzdGFydGluZyBwb3NpdGlvbiBiZWZvcmUgY3Vyc29yLm1vdmVcblx0bGV0IHJhd01vdXNlTGVmdDA7XG5cdGxldCByYXdNb3VzZVRvcDA7XG5cblx0Ly8gc3RhcnRpbmcgcG9zaXRpb25cblx0bGV0IG1vdXNlTGVmdDA7XG5cdGxldCBtb3VzZVRvcDA7XG5cblx0Ly8gY3VycmVudCBwb3NpdGlvbiBiZWZvcmUgY3Vyc29yLm1vdmVcblx0bGV0IHJhd01vdXNlTGVmdDE7XG5cdGxldCByYXdNb3VzZVRvcDE7XG5cblx0Ly8gY3VycmVudCBwb3NpdGlvblxuXHRsZXQgbW91c2VMZWZ0MTtcblx0bGV0IG1vdXNlVG9wMTtcblxuXHRsZXQgZHJhZ2dpbmcgPSBmYWxzZTtcblxuXHRjb25zdCBkcmFnID0gY3Vyc29yLmRyYWc7XG5cblx0bGV0IGRyYWdYID0gZHJhZy54O1xuXHRsZXQgZHJhZ1kgPSBkcmFnLnk7XG5cblx0aWYgKGN1cnNvci5zaG93KSB7XG5cdFx0aWYgKGN1cnNvci54KVxuXHRcdFx0eEN1cnNvciA9IHBsYWNlRGl2KENVUlNPUl9YLCBvdmVyKTtcblx0XHRpZiAoY3Vyc29yLnkpXG5cdFx0XHR5Q3Vyc29yID0gcGxhY2VEaXYoQ1VSU09SX1ksIG92ZXIpO1xuXG5cdFx0aWYgKHNjYWxlWC5vcmkgPT0gMCkge1xuXHRcdFx0dkN1cnNvciA9IHhDdXJzb3I7XG5cdFx0XHRoQ3Vyc29yID0geUN1cnNvcjtcblx0XHR9XG5cdFx0ZWxzZSB7XG5cdFx0XHR2Q3Vyc29yID0geUN1cnNvcjtcblx0XHRcdGhDdXJzb3IgPSB4Q3Vyc29yO1xuXHRcdH1cblxuXHRcdG1vdXNlTGVmdDEgPSBjdXJzb3IubGVmdDtcblx0XHRtb3VzZVRvcDEgPSBjdXJzb3IudG9wO1xuXHR9XG5cblx0Y29uc3Qgc2VsZWN0ID0gc2VsZi5zZWxlY3QgPSBhc3NpZ24oe1xuXHRcdHNob3c6ICAgdHJ1ZSxcblx0XHRvdmVyOiAgIHRydWUsXG5cdFx0bGVmdDogICAwLFxuXHRcdHdpZHRoOiAgMCxcblx0XHR0b3A6ICAgIDAsXG5cdFx0aGVpZ2h0OiAwLFxuXHR9LCBvcHRzLnNlbGVjdCk7XG5cblx0Y29uc3Qgc2VsZWN0RGl2ID0gc2VsZWN0LnNob3cgPyBwbGFjZURpdihTRUxFQ1QsIHNlbGVjdC5vdmVyID8gb3ZlciA6IHVuZGVyKSA6IG51bGw7XG5cblx0ZnVuY3Rpb24gc2V0U2VsZWN0KG9wdHMsIF9maXJlKSB7XG5cdFx0aWYgKHNlbGVjdC5zaG93KSB7XG5cdFx0XHRmb3IgKGxldCBwcm9wIGluIG9wdHMpXG5cdFx0XHRcdHNldFN0eWxlUHgoc2VsZWN0RGl2LCBwcm9wLCBzZWxlY3RbcHJvcF0gPSBvcHRzW3Byb3BdKTtcblxuXHRcdFx0X2ZpcmUgIT09IGZhbHNlICYmIGZpcmUoXCJzZXRTZWxlY3RcIik7XG5cdFx0fVxuXHR9XG5cblx0c2VsZi5zZXRTZWxlY3QgPSBzZXRTZWxlY3Q7XG5cblx0ZnVuY3Rpb24gdG9nZ2xlRE9NKGksIG9uT2ZmKSB7XG5cdFx0bGV0IHMgPSBzZXJpZXNbaV07XG5cdFx0bGV0IGxhYmVsID0gc2hvd0xlZ2VuZCA/IGxlZ2VuZFJvd3NbaV0gOiBudWxsO1xuXG5cdFx0aWYgKHMuc2hvdylcblx0XHRcdGxhYmVsICYmIHJlbUNsYXNzKGxhYmVsLCBPRkYpO1xuXHRcdGVsc2Uge1xuXHRcdFx0bGFiZWwgJiYgYWRkQ2xhc3MobGFiZWwsIE9GRik7XG5cdFx0XHRjdXJzb3JQdHMubGVuZ3RoID4gMSAmJiBlbFRyYW5zKGN1cnNvclB0c1tpXSwgLTEwLCAtMTAsIHBsb3RXaWRDc3MsIHBsb3RIZ3RDc3MpO1xuXHRcdH1cblx0fVxuXG5cdGZ1bmN0aW9uIF9zZXRTY2FsZShrZXksIG1pbiwgbWF4KSB7XG5cdFx0c2V0U2NhbGUoa2V5LCB7bWluLCBtYXh9KTtcblx0fVxuXG5cdGZ1bmN0aW9uIHNldFNlcmllcyhpLCBvcHRzLCBfZmlyZSwgX3B1Yikge1xuXHQvL1x0bG9nKFwic2V0U2VyaWVzKClcIiwgYXJndW1lbnRzKTtcblxuXHRcdGlmIChvcHRzLmZvY3VzICE9IG51bGwpXG5cdFx0XHRzZXRGb2N1cyhpKTtcblxuXHRcdGlmIChvcHRzLnNob3cgIT0gbnVsbCkge1xuXHRcdFx0c2VyaWVzLmZvckVhY2goKHMsIHNpKSA9PiB7XG5cdFx0XHRcdGlmIChzaSA+IDAgJiYgKGkgPT0gc2kgfHwgaSA9PSBudWxsKSkge1xuXHRcdFx0XHRcdHMuc2hvdyA9IG9wdHMuc2hvdztcblx0XHRcdFx0XHR0b2dnbGVET00oc2ksIG9wdHMuc2hvdyk7XG5cblx0XHRcdFx0XHRfc2V0U2NhbGUobW9kZSA9PSAyID8gcy5mYWNldHNbMV0uc2NhbGUgOiBzLnNjYWxlLCBudWxsLCBudWxsKTtcblx0XHRcdFx0XHRjb21taXQoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXG5cdFx0X2ZpcmUgIT09IGZhbHNlICYmIGZpcmUoXCJzZXRTZXJpZXNcIiwgaSwgb3B0cyk7XG5cblx0XHRfcHViICYmIHB1YlN5bmMoXCJzZXRTZXJpZXNcIiwgc2VsZiwgaSwgb3B0cyk7XG5cdH1cblxuXHRzZWxmLnNldFNlcmllcyA9IHNldFNlcmllcztcblxuXHRmdW5jdGlvbiBzZXRCYW5kKGJpLCBvcHRzKSB7XG5cdFx0YXNzaWduKGJhbmRzW2JpXSwgb3B0cyk7XG5cdH1cblxuXHRmdW5jdGlvbiBhZGRCYW5kKG9wdHMsIGJpKSB7XG5cdFx0b3B0cy5maWxsID0gZm5PclNlbGYob3B0cy5maWxsIHx8IG51bGwpO1xuXHRcdG9wdHMuZGlyID0gaWZOdWxsKG9wdHMuZGlyLCAtMSk7XG5cdFx0YmkgPSBiaSA9PSBudWxsID8gYmFuZHMubGVuZ3RoIDogYmk7XG5cdFx0YmFuZHMuc3BsaWNlKGJpLCAwLCBvcHRzKTtcblx0fVxuXG5cdGZ1bmN0aW9uIGRlbEJhbmQoYmkpIHtcblx0XHRpZiAoYmkgPT0gbnVsbClcblx0XHRcdGJhbmRzLmxlbmd0aCA9IDA7XG5cdFx0ZWxzZVxuXHRcdFx0YmFuZHMuc3BsaWNlKGJpLCAxKTtcblx0fVxuXG5cdHNlbGYuYWRkQmFuZCA9IGFkZEJhbmQ7XG5cdHNlbGYuc2V0QmFuZCA9IHNldEJhbmQ7XG5cdHNlbGYuZGVsQmFuZCA9IGRlbEJhbmQ7XG5cblx0ZnVuY3Rpb24gc2V0QWxwaGEoaSwgdmFsdWUpIHtcblx0XHRzZXJpZXNbaV0uYWxwaGEgPSB2YWx1ZTtcblxuXHRcdGlmIChjdXJzb3Iuc2hvdyAmJiBjdXJzb3JQdHNbaV0pXG5cdFx0XHRjdXJzb3JQdHNbaV0uc3R5bGUub3BhY2l0eSA9IHZhbHVlO1xuXG5cdFx0aWYgKHNob3dMZWdlbmQgJiYgbGVnZW5kUm93c1tpXSlcblx0XHRcdGxlZ2VuZFJvd3NbaV0uc3R5bGUub3BhY2l0eSA9IHZhbHVlO1xuXHR9XG5cblx0Ly8geS1kaXN0YW5jZVxuXHRsZXQgY2xvc2VzdERpc3Q7XG5cdGxldCBjbG9zZXN0U2VyaWVzO1xuXHRsZXQgZm9jdXNlZFNlcmllcztcblx0Y29uc3QgRk9DVVNfVFJVRSAgPSB7Zm9jdXM6IHRydWV9O1xuXG5cdGZ1bmN0aW9uIHNldEZvY3VzKGkpIHtcblx0XHRpZiAoaSAhPSBmb2N1c2VkU2VyaWVzKSB7XG5cdFx0Ly9cdGxvZyhcInNldEZvY3VzKClcIiwgYXJndW1lbnRzKTtcblxuXHRcdFx0bGV0IGFsbEZvY3VzZWQgPSBpID09IG51bGw7XG5cblx0XHRcdGxldCBfc2V0QWxwaGEgPSBmb2N1cy5hbHBoYSAhPSAxO1xuXG5cdFx0XHRzZXJpZXMuZm9yRWFjaCgocywgaTIpID0+IHtcblx0XHRcdFx0bGV0IGlzRm9jdXNlZCA9IGFsbEZvY3VzZWQgfHwgaTIgPT0gMCB8fCBpMiA9PSBpO1xuXHRcdFx0XHRzLl9mb2N1cyA9IGFsbEZvY3VzZWQgPyBudWxsIDogaXNGb2N1c2VkO1xuXHRcdFx0XHRfc2V0QWxwaGEgJiYgc2V0QWxwaGEoaTIsIGlzRm9jdXNlZCA/IDEgOiBmb2N1cy5hbHBoYSk7XG5cdFx0XHR9KTtcblxuXHRcdFx0Zm9jdXNlZFNlcmllcyA9IGk7XG5cdFx0XHRfc2V0QWxwaGEgJiYgY29tbWl0KCk7XG5cdFx0fVxuXHR9XG5cblx0aWYgKHNob3dMZWdlbmQgJiYgY3Vyc29yRm9jdXMpIHtcblx0XHRvbihtb3VzZWxlYXZlLCBsZWdlbmRFbCwgZSA9PiB7XG5cdFx0XHRpZiAoY3Vyc29yLl9sb2NrKVxuXHRcdFx0XHRyZXR1cm47XG5cblx0XHRcdGlmIChmb2N1c2VkU2VyaWVzICE9IG51bGwpXG5cdFx0XHRcdHNldFNlcmllcyhudWxsLCBGT0NVU19UUlVFLCB0cnVlLCBzeW5jT3B0cy5zZXRTZXJpZXMpO1xuXHRcdH0pO1xuXHR9XG5cblx0ZnVuY3Rpb24gcG9zVG9WYWwocG9zLCBzY2FsZSwgY2FuKSB7XG5cdFx0bGV0IHNjID0gc2NhbGVzW3NjYWxlXTtcblxuXHRcdGlmIChjYW4pXG5cdFx0XHRwb3MgPSBwb3MgLyBweFJhdGlvIC0gKHNjLm9yaSA9PSAxID8gcGxvdFRvcENzcyA6IHBsb3RMZnRDc3MpO1xuXG5cdFx0bGV0IGRpbSA9IHBsb3RXaWRDc3M7XG5cblx0XHRpZiAoc2Mub3JpID09IDEpIHtcblx0XHRcdGRpbSA9IHBsb3RIZ3RDc3M7XG5cdFx0XHRwb3MgPSBkaW0gLSBwb3M7XG5cdFx0fVxuXG5cdFx0aWYgKHNjLmRpciA9PSAtMSlcblx0XHRcdHBvcyA9IGRpbSAtIHBvcztcblxuXHRcdGxldCBfbWluID0gc2MuX21pbixcblx0XHRcdF9tYXggPSBzYy5fbWF4LFxuXHRcdFx0cGN0ID0gcG9zIC8gZGltO1xuXG5cdFx0bGV0IHN2ID0gX21pbiArIChfbWF4IC0gX21pbikgKiBwY3Q7XG5cblx0XHRsZXQgZGlzdHIgPSBzYy5kaXN0cjtcblxuXHRcdHJldHVybiAoXG5cdFx0XHRkaXN0ciA9PSAzID8gcG93KDEwLCBzdikgOlxuXHRcdFx0ZGlzdHIgPT0gNCA/IHNpbmgoc3YsIHNjLmFzaW5oKSA6XG5cdFx0XHRzdlxuXHRcdCk7XG5cdH1cblxuXHRmdW5jdGlvbiBjbG9zZXN0SWR4RnJvbVhwb3MocG9zLCBjYW4pIHtcblx0XHRsZXQgdiA9IHBvc1RvVmFsKHBvcywgeFNjYWxlS2V5LCBjYW4pO1xuXHRcdHJldHVybiBjbG9zZXN0SWR4KHYsIGRhdGFbMF0sIGkwLCBpMSk7XG5cdH1cblxuXHRzZWxmLnZhbFRvSWR4ID0gdmFsID0+IGNsb3Nlc3RJZHgodmFsLCBkYXRhWzBdKTtcblx0c2VsZi5wb3NUb0lkeCA9IGNsb3Nlc3RJZHhGcm9tWHBvcztcblx0c2VsZi5wb3NUb1ZhbCA9IHBvc1RvVmFsO1xuXHRzZWxmLnZhbFRvUG9zID0gKHZhbCwgc2NhbGUsIGNhbikgPT4gKFxuXHRcdHNjYWxlc1tzY2FsZV0ub3JpID09IDAgP1xuXHRcdGdldEhQb3ModmFsLCBzY2FsZXNbc2NhbGVdLFxuXHRcdFx0Y2FuID8gcGxvdFdpZCA6IHBsb3RXaWRDc3MsXG5cdFx0XHRjYW4gPyBwbG90TGZ0IDogMCxcblx0XHQpIDpcblx0XHRnZXRWUG9zKHZhbCwgc2NhbGVzW3NjYWxlXSxcblx0XHRcdGNhbiA/IHBsb3RIZ3QgOiBwbG90SGd0Q3NzLFxuXHRcdFx0Y2FuID8gcGxvdFRvcCA6IDAsXG5cdFx0KVxuXHQpO1xuXG5cdC8vIGRlZmVycyBjYWxsaW5nIGV4cGVuc2l2ZSBmdW5jdGlvbnNcblx0ZnVuY3Rpb24gYmF0Y2goZm4pIHtcblx0XHRmbihzZWxmKTtcblx0XHRjb21taXQoKTtcblx0fVxuXG5cdHNlbGYuYmF0Y2ggPSBiYXRjaDtcblxuXHQoc2VsZi5zZXRDdXJzb3IgPSAob3B0cywgX2ZpcmUsIF9wdWIpID0+IHtcblx0XHRtb3VzZUxlZnQxID0gb3B0cy5sZWZ0O1xuXHRcdG1vdXNlVG9wMSA9IG9wdHMudG9wO1xuXHQvL1x0YXNzaWduKGN1cnNvciwgb3B0cyk7XG5cdFx0dXBkYXRlQ3Vyc29yKG51bGwsIF9maXJlLCBfcHViKTtcblx0fSk7XG5cblx0ZnVuY3Rpb24gc2V0U2VsSChvZmYsIGRpbSkge1xuXHRcdHNldFN0eWxlUHgoc2VsZWN0RGl2LCBMRUZULCAgc2VsZWN0LmxlZnQgPSBvZmYpO1xuXHRcdHNldFN0eWxlUHgoc2VsZWN0RGl2LCBXSURUSCwgc2VsZWN0LndpZHRoID0gZGltKTtcblx0fVxuXG5cdGZ1bmN0aW9uIHNldFNlbFYob2ZmLCBkaW0pIHtcblx0XHRzZXRTdHlsZVB4KHNlbGVjdERpdiwgVE9QLCAgICBzZWxlY3QudG9wID0gb2ZmKTtcblx0XHRzZXRTdHlsZVB4KHNlbGVjdERpdiwgSEVJR0hULCBzZWxlY3QuaGVpZ2h0ID0gZGltKTtcblx0fVxuXG5cdGxldCBzZXRTZWxYID0gc2NhbGVYLm9yaSA9PSAwID8gc2V0U2VsSCA6IHNldFNlbFY7XG5cdGxldCBzZXRTZWxZID0gc2NhbGVYLm9yaSA9PSAxID8gc2V0U2VsSCA6IHNldFNlbFY7XG5cblx0ZnVuY3Rpb24gc3luY0xlZ2VuZCgpIHtcblx0XHRpZiAoc2hvd0xlZ2VuZCAmJiBsZWdlbmQubGl2ZSkge1xuXHRcdFx0Zm9yIChsZXQgaSA9IG1vZGUgPT0gMiA/IDEgOiAwOyBpIDwgc2VyaWVzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdGlmIChpID09IDAgJiYgbXVsdGlWYWxMZWdlbmQpXG5cdFx0XHRcdFx0Y29udGludWU7XG5cblx0XHRcdFx0bGV0IHZhbHMgPSBsZWdlbmQudmFsdWVzW2ldO1xuXG5cdFx0XHRcdGxldCBqID0gMDtcblxuXHRcdFx0XHRmb3IgKGxldCBrIGluIHZhbHMpXG5cdFx0XHRcdFx0bGVnZW5kQ2VsbHNbaV1baisrXS5maXJzdENoaWxkLm5vZGVWYWx1ZSA9IHZhbHNba107XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0ZnVuY3Rpb24gc2V0TGVnZW5kKG9wdHMsIF9maXJlKSB7XG5cdFx0aWYgKG9wdHMgIT0gbnVsbCkge1xuXHRcdFx0bGV0IGlkeCA9IG9wdHMuaWR4O1xuXG5cdFx0XHRsZWdlbmQuaWR4ID0gaWR4O1xuXHRcdFx0c2VyaWVzLmZvckVhY2goKHMsIHNpZHgpID0+IHtcblx0XHRcdFx0KHNpZHggPiAwIHx8ICFtdWx0aVZhbExlZ2VuZCkgJiYgc2V0TGVnZW5kVmFsdWVzKHNpZHgsIGlkeCk7XG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHRpZiAoc2hvd0xlZ2VuZCAmJiBsZWdlbmQubGl2ZSlcblx0XHRcdHN5bmNMZWdlbmQoKTtcblxuXHRcdHNob3VsZFNldExlZ2VuZCA9IGZhbHNlO1xuXG5cdFx0X2ZpcmUgIT09IGZhbHNlICYmIGZpcmUoXCJzZXRMZWdlbmRcIik7XG5cdH1cblxuXHRzZWxmLnNldExlZ2VuZCA9IHNldExlZ2VuZDtcblxuXHRmdW5jdGlvbiBzZXRMZWdlbmRWYWx1ZXMoc2lkeCwgaWR4KSB7XG5cdFx0bGV0IHZhbDtcblxuXHRcdGlmIChpZHggPT0gbnVsbClcblx0XHRcdHZhbCA9IE5VTExfTEVHRU5EX1ZBTFVFUztcblx0XHRlbHNlIHtcblx0XHRcdGxldCBzID0gc2VyaWVzW3NpZHhdO1xuXHRcdFx0bGV0IHNyYyA9IHNpZHggPT0gMCAmJiB4U2NhbGVEaXN0ciA9PSAyID8gZGF0YTAgOiBkYXRhW3NpZHhdO1xuXHRcdFx0dmFsID0gbXVsdGlWYWxMZWdlbmQgPyBzLnZhbHVlcyhzZWxmLCBzaWR4LCBpZHgpIDoge186IHMudmFsdWUoc2VsZiwgc3JjW2lkeF0sIHNpZHgsIGlkeCl9O1xuXHRcdH1cblxuXHRcdGxlZ2VuZC52YWx1ZXNbc2lkeF0gPSB2YWw7XG5cdH1cblxuXHRmdW5jdGlvbiB1cGRhdGVDdXJzb3Ioc3JjLCBfZmlyZSwgX3B1Yikge1xuXHQvL1x0dHMgPT0gbnVsbCAmJiBsb2coXCJ1cGRhdGVDdXJzb3IoKVwiLCBhcmd1bWVudHMpO1xuXG5cdFx0cmF3TW91c2VMZWZ0MSA9IG1vdXNlTGVmdDE7XG5cdFx0cmF3TW91c2VUb3AxID0gbW91c2VUb3AxO1xuXG5cdFx0W21vdXNlTGVmdDEsIG1vdXNlVG9wMV0gPSBjdXJzb3IubW92ZShzZWxmLCBtb3VzZUxlZnQxLCBtb3VzZVRvcDEpO1xuXG5cdFx0aWYgKGN1cnNvci5zaG93KSB7XG5cdFx0XHR2Q3Vyc29yICYmIGVsVHJhbnModkN1cnNvciwgcm91bmQobW91c2VMZWZ0MSksIDAsIHBsb3RXaWRDc3MsIHBsb3RIZ3RDc3MpO1xuXHRcdFx0aEN1cnNvciAmJiBlbFRyYW5zKGhDdXJzb3IsIDAsIHJvdW5kKG1vdXNlVG9wMSksIHBsb3RXaWRDc3MsIHBsb3RIZ3RDc3MpO1xuXHRcdH1cblxuXHRcdGxldCBpZHg7XG5cblx0XHQvLyB3aGVuIHpvb21pbmcgdG8gYW4geCBzY2FsZSByYW5nZSBiZXR3ZWVuIGRhdGFwb2ludHMgdGhlIGJpbmFyeSBzZWFyY2hcblx0XHQvLyBmb3IgbmVhcmVzdCBtaW4vbWF4IGluZGljZXMgcmVzdWx0cyBpbiB0aGlzIGNvbmRpdGlvbi4gY2hlYXAgaGFjayA6RFxuXHRcdGxldCBub0RhdGFJblJhbmdlID0gaTAgPiBpMTsgLy8gd29ya3MgZm9yIG1vZGUgMSBvbmx5XG5cblx0XHRjbG9zZXN0RGlzdCA9IGluZjtcblxuXHRcdC8vIFRPRE86IGV4dHJhY3Rcblx0XHRsZXQgeERpbSA9IHNjYWxlWC5vcmkgPT0gMCA/IHBsb3RXaWRDc3MgOiBwbG90SGd0Q3NzO1xuXHRcdGxldCB5RGltID0gc2NhbGVYLm9yaSA9PSAxID8gcGxvdFdpZENzcyA6IHBsb3RIZ3RDc3M7XG5cblx0XHQvLyBpZiBjdXJzb3IgaGlkZGVuLCBoaWRlIHBvaW50cyAmIGNsZWFyIGxlZ2VuZCB2YWxzXG5cdFx0aWYgKG1vdXNlTGVmdDEgPCAwIHx8IGRhdGFMZW4gPT0gMCB8fCBub0RhdGFJblJhbmdlKSB7XG5cdFx0XHRpZHggPSBudWxsO1xuXG5cdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHNlcmllcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHRpZiAoaSA+IDApIHtcblx0XHRcdFx0XHRjdXJzb3JQdHMubGVuZ3RoID4gMSAmJiBlbFRyYW5zKGN1cnNvclB0c1tpXSwgLTEwLCAtMTAsIHBsb3RXaWRDc3MsIHBsb3RIZ3RDc3MpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGlmIChjdXJzb3JGb2N1cylcblx0XHRcdFx0c2V0U2VyaWVzKG51bGwsIEZPQ1VTX1RSVUUsIHRydWUsIHNyYyA9PSBudWxsICYmIHN5bmNPcHRzLnNldFNlcmllcyk7XG5cblx0XHRcdGlmIChsZWdlbmQubGl2ZSkge1xuXHRcdFx0XHRhY3RpdmVJZHhzLmZpbGwobnVsbCk7XG5cdFx0XHRcdHNob3VsZFNldExlZ2VuZCA9IHRydWU7XG5cblx0XHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBzZXJpZXMubGVuZ3RoOyBpKyspXG5cdFx0XHRcdFx0bGVnZW5kLnZhbHVlc1tpXSA9IE5VTExfTEVHRU5EX1ZBTFVFUztcblx0XHRcdH1cblx0XHR9XG5cdFx0ZWxzZSB7XG5cdFx0Ly9cdGxldCBwY3RZID0gMSAtICh5IC8gcmVjdC5oZWlnaHQpO1xuXG5cdFx0XHRsZXQgbW91c2VYUG9zLCB2YWxBdFBvc1gsIHhQb3M7XG5cblx0XHRcdGlmIChtb2RlID09IDEpIHtcblx0XHRcdFx0bW91c2VYUG9zID0gc2NhbGVYLm9yaSA9PSAwID8gbW91c2VMZWZ0MSA6IG1vdXNlVG9wMTtcblx0XHRcdFx0dmFsQXRQb3NYID0gcG9zVG9WYWwobW91c2VYUG9zLCB4U2NhbGVLZXkpO1xuXHRcdFx0XHRpZHggPSBjbG9zZXN0SWR4KHZhbEF0UG9zWCwgZGF0YVswXSwgaTAsIGkxKTtcblx0XHRcdFx0eFBvcyA9IGluY3JSb3VuZFVwKHZhbFRvUG9zWChkYXRhWzBdW2lkeF0sIHNjYWxlWCwgeERpbSwgMCksIDAuNSk7XG5cdFx0XHR9XG5cblx0XHRcdGZvciAobGV0IGkgPSBtb2RlID09IDIgPyAxIDogMDsgaSA8IHNlcmllcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHRsZXQgcyA9IHNlcmllc1tpXTtcblxuXHRcdFx0XHRsZXQgaWR4MSAgPSBhY3RpdmVJZHhzW2ldO1xuXHRcdFx0XHRsZXQgeVZhbDEgPSBtb2RlID09IDEgPyBkYXRhW2ldW2lkeDFdIDogZGF0YVtpXVsxXVtpZHgxXTtcblxuXHRcdFx0XHRsZXQgaWR4MiAgPSBjdXJzb3IuZGF0YUlkeChzZWxmLCBpLCBpZHgsIHZhbEF0UG9zWCk7XG5cdFx0XHRcdGxldCB5VmFsMiA9IG1vZGUgPT0gMSA/IGRhdGFbaV1baWR4Ml0gOiBkYXRhW2ldWzFdW2lkeDJdO1xuXG5cdFx0XHRcdHNob3VsZFNldExlZ2VuZCA9IHNob3VsZFNldExlZ2VuZCB8fCB5VmFsMiAhPSB5VmFsMSB8fCBpZHgyICE9IGlkeDE7XG5cblx0XHRcdFx0YWN0aXZlSWR4c1tpXSA9IGlkeDI7XG5cblx0XHRcdFx0bGV0IHhQb3MyID0gaWR4MiA9PSBpZHggPyB4UG9zIDogaW5jclJvdW5kVXAodmFsVG9Qb3NYKG1vZGUgPT0gMSA/IGRhdGFbMF1baWR4Ml0gOiBkYXRhW2ldWzBdW2lkeDJdLCBzY2FsZVgsIHhEaW0sIDApLCAwLjUpO1xuXG5cdFx0XHRcdGlmIChpID4gMCAmJiBzLnNob3cpIHtcblx0XHRcdFx0XHRsZXQgeVBvcyA9IHlWYWwyID09IG51bGwgPyAtMTAgOiBpbmNyUm91bmRVcCh2YWxUb1Bvc1koeVZhbDIsIG1vZGUgPT0gMSA/IHNjYWxlc1tzLnNjYWxlXSA6IHNjYWxlc1tzLmZhY2V0c1sxXS5zY2FsZV0sIHlEaW0sIDApLCAwLjUpO1xuXG5cdFx0XHRcdFx0aWYgKHlQb3MgPiAwICYmIG1vZGUgPT0gMSkge1xuXHRcdFx0XHRcdFx0bGV0IGRpc3QgPSBhYnMoeVBvcyAtIG1vdXNlVG9wMSk7XG5cblx0XHRcdFx0XHRcdGlmIChkaXN0IDw9IGNsb3Nlc3REaXN0KSB7XG5cdFx0XHRcdFx0XHRcdGNsb3Nlc3REaXN0ID0gZGlzdDtcblx0XHRcdFx0XHRcdFx0Y2xvc2VzdFNlcmllcyA9IGk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0bGV0IGhQb3MsIHZQb3M7XG5cblx0XHRcdFx0XHRpZiAoc2NhbGVYLm9yaSA9PSAwKSB7XG5cdFx0XHRcdFx0XHRoUG9zID0geFBvczI7XG5cdFx0XHRcdFx0XHR2UG9zID0geVBvcztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0XHRoUG9zID0geVBvcztcblx0XHRcdFx0XHRcdHZQb3MgPSB4UG9zMjtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoc2hvdWxkU2V0TGVnZW5kICYmIGN1cnNvclB0cy5sZW5ndGggPiAxKSB7XG5cdFx0XHRcdFx0XHRlbENvbG9yKGN1cnNvclB0c1tpXSwgY3Vyc29yLnBvaW50cy5maWxsKHNlbGYsIGkpLCBjdXJzb3IucG9pbnRzLnN0cm9rZShzZWxmLCBpKSk7XG5cblx0XHRcdFx0XHRcdGxldCBwdFdpZCwgcHRIZ3QsIHB0TGZ0LCBwdFRvcCxcblx0XHRcdFx0XHRcdFx0Y2VudGVyZWQgPSB0cnVlLFxuXHRcdFx0XHRcdFx0XHRnZXRCQm94ID0gY3Vyc29yLnBvaW50cy5iYm94O1xuXG5cdFx0XHRcdFx0XHRpZiAoZ2V0QkJveCAhPSBudWxsKSB7XG5cdFx0XHRcdFx0XHRcdGNlbnRlcmVkID0gZmFsc2U7XG5cblx0XHRcdFx0XHRcdFx0bGV0IGJib3ggPSBnZXRCQm94KHNlbGYsIGkpO1xuXG5cdFx0XHRcdFx0XHRcdHB0TGZ0ID0gYmJveC5sZWZ0O1xuXHRcdFx0XHRcdFx0XHRwdFRvcCA9IGJib3gudG9wO1xuXHRcdFx0XHRcdFx0XHRwdFdpZCA9IGJib3gud2lkdGg7XG5cdFx0XHRcdFx0XHRcdHB0SGd0ID0gYmJveC5oZWlnaHQ7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHRcdFx0cHRMZnQgPSBoUG9zO1xuXHRcdFx0XHRcdFx0XHRwdFRvcCA9IHZQb3M7XG5cdFx0XHRcdFx0XHRcdHB0V2lkID0gcHRIZ3QgPSBjdXJzb3IucG9pbnRzLnNpemUoc2VsZiwgaSk7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdGVsU2l6ZShjdXJzb3JQdHNbaV0sIHB0V2lkLCBwdEhndCwgY2VudGVyZWQpO1xuXHRcdFx0XHRcdFx0ZWxUcmFucyhjdXJzb3JQdHNbaV0sIHB0TGZ0LCBwdFRvcCwgcGxvdFdpZENzcywgcGxvdEhndENzcyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKGxlZ2VuZC5saXZlKSB7XG5cdFx0XHRcdFx0aWYgKCFzaG91bGRTZXRMZWdlbmQgfHwgaSA9PSAwICYmIG11bHRpVmFsTGVnZW5kKVxuXHRcdFx0XHRcdFx0Y29udGludWU7XG5cblx0XHRcdFx0XHRzZXRMZWdlbmRWYWx1ZXMoaSwgaWR4Mik7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRjdXJzb3IuaWR4ID0gaWR4O1xuXHRcdGN1cnNvci5sZWZ0ID0gbW91c2VMZWZ0MTtcblx0XHRjdXJzb3IudG9wID0gbW91c2VUb3AxO1xuXG5cdFx0aWYgKHNob3VsZFNldExlZ2VuZCkge1xuXHRcdFx0bGVnZW5kLmlkeCA9IGlkeDtcblx0XHRcdHNldExlZ2VuZCgpO1xuXHRcdH1cblxuXHRcdC8vIG5pdDogY3Vyc29yLmRyYWcuc2V0U2VsZWN0IGlzIGFzc3VtZWQgYWx3YXlzIHRydWVcblx0XHRpZiAoc2VsZWN0LnNob3cgJiYgZHJhZ2dpbmcpIHtcblx0XHRcdGlmIChzcmMgIT0gbnVsbCkge1xuXHRcdFx0XHRsZXQgW3hLZXksIHlLZXldID0gc3luY09wdHMuc2NhbGVzO1xuXHRcdFx0XHRsZXQgW21hdGNoWEtleXMsIG1hdGNoWUtleXNdID0gc3luY09wdHMubWF0Y2g7XG5cdFx0XHRcdGxldCBbeEtleVNyYywgeUtleVNyY10gPSBzcmMuY3Vyc29yLnN5bmMuc2NhbGVzO1xuXG5cdFx0XHRcdC8vIG1hdGNoIHRoZSBkcmFnWC9kcmFnWSBpbXBsaWNpdG5lc3MvZXhwbGljaXRuZXNzIG9mIHNyY1xuXHRcdFx0XHRsZXQgc2RyYWcgPSBzcmMuY3Vyc29yLmRyYWc7XG5cdFx0XHRcdGRyYWdYID0gc2RyYWcuX3g7XG5cdFx0XHRcdGRyYWdZID0gc2RyYWcuX3k7XG5cblx0XHRcdFx0aWYgKGRyYWdYIHx8IGRyYWdZKSB7XG5cdFx0XHRcdFx0bGV0IHsgbGVmdCwgdG9wLCB3aWR0aCwgaGVpZ2h0IH0gPSBzcmMuc2VsZWN0O1xuXG5cdFx0XHRcdFx0bGV0IHNvcmkgPSBzcmMuc2NhbGVzW3hLZXldLm9yaTtcblx0XHRcdFx0XHRsZXQgc1Bvc1RvVmFsID0gc3JjLnBvc1RvVmFsO1xuXG5cdFx0XHRcdFx0bGV0IHNPZmYsIHNEaW0sIHNjLCBhLCBiO1xuXG5cdFx0XHRcdFx0bGV0IG1hdGNoaW5nWCA9IHhLZXkgIT0gbnVsbCAmJiBtYXRjaFhLZXlzKHhLZXksIHhLZXlTcmMpO1xuXHRcdFx0XHRcdGxldCBtYXRjaGluZ1kgPSB5S2V5ICE9IG51bGwgJiYgbWF0Y2hZS2V5cyh5S2V5LCB5S2V5U3JjKTtcblxuXHRcdFx0XHRcdGlmIChtYXRjaGluZ1ggJiYgZHJhZ1gpIHtcblx0XHRcdFx0XHRcdGlmIChzb3JpID09IDApIHtcblx0XHRcdFx0XHRcdFx0c09mZiA9IGxlZnQ7XG5cdFx0XHRcdFx0XHRcdHNEaW0gPSB3aWR0aDtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRzT2ZmID0gdG9wO1xuXHRcdFx0XHRcdFx0XHRzRGltID0gaGVpZ2h0O1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRzYyA9IHNjYWxlc1t4S2V5XTtcblxuXHRcdFx0XHRcdFx0YSA9IHZhbFRvUG9zWChzUG9zVG9WYWwoc09mZiwgeEtleVNyYyksICAgICAgICBzYywgeERpbSwgMCk7XG5cdFx0XHRcdFx0XHRiID0gdmFsVG9Qb3NYKHNQb3NUb1ZhbChzT2ZmICsgc0RpbSwgeEtleVNyYyksIHNjLCB4RGltLCAwKTtcblxuXHRcdFx0XHRcdFx0c2V0U2VsWChtaW4oYSxiKSwgYWJzKGItYSkpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0XHRzZXRTZWxYKDAsIHhEaW0pO1xuXG5cdFx0XHRcdFx0aWYgKG1hdGNoaW5nWSAmJiBkcmFnWSkge1xuXHRcdFx0XHRcdFx0aWYgKHNvcmkgPT0gMSkge1xuXHRcdFx0XHRcdFx0XHRzT2ZmID0gbGVmdDtcblx0XHRcdFx0XHRcdFx0c0RpbSA9IHdpZHRoO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHNPZmYgPSB0b3A7XG5cdFx0XHRcdFx0XHRcdHNEaW0gPSBoZWlnaHQ7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdHNjID0gc2NhbGVzW3lLZXldO1xuXG5cdFx0XHRcdFx0XHRhID0gdmFsVG9Qb3NZKHNQb3NUb1ZhbChzT2ZmLCB5S2V5U3JjKSwgICAgICAgIHNjLCB5RGltLCAwKTtcblx0XHRcdFx0XHRcdGIgPSB2YWxUb1Bvc1koc1Bvc1RvVmFsKHNPZmYgKyBzRGltLCB5S2V5U3JjKSwgc2MsIHlEaW0sIDApO1xuXG5cdFx0XHRcdFx0XHRzZXRTZWxZKG1pbihhLGIpLCBhYnMoYi1hKSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHRcdHNldFNlbFkoMCwgeURpbSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdGhpZGVTZWxlY3QoKTtcblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHRsZXQgcmF3RFggPSBhYnMocmF3TW91c2VMZWZ0MSAtIHJhd01vdXNlTGVmdDApO1xuXHRcdFx0XHRsZXQgcmF3RFkgPSBhYnMocmF3TW91c2VUb3AxIC0gcmF3TW91c2VUb3AwKTtcblxuXHRcdFx0XHRpZiAoc2NhbGVYLm9yaSA9PSAxKSB7XG5cdFx0XHRcdFx0bGV0IF9yYXdEWCA9IHJhd0RYO1xuXHRcdFx0XHRcdHJhd0RYID0gcmF3RFk7XG5cdFx0XHRcdFx0cmF3RFkgPSBfcmF3RFg7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRkcmFnWCA9IGRyYWcueCAmJiByYXdEWCA+PSBkcmFnLmRpc3Q7XG5cdFx0XHRcdGRyYWdZID0gZHJhZy55ICYmIHJhd0RZID49IGRyYWcuZGlzdDtcblxuXHRcdFx0XHRsZXQgdW5pID0gZHJhZy51bmk7XG5cblx0XHRcdFx0aWYgKHVuaSAhPSBudWxsKSB7XG5cdFx0XHRcdFx0Ly8gb25seSBjYWxjIGRyYWcgc3RhdHVzIGlmIHRoZXkgcGFzcyB0aGUgZGlzdCB0aHJlc2hcblx0XHRcdFx0XHRpZiAoZHJhZ1ggJiYgZHJhZ1kpIHtcblx0XHRcdFx0XHRcdGRyYWdYID0gcmF3RFggPj0gdW5pO1xuXHRcdFx0XHRcdFx0ZHJhZ1kgPSByYXdEWSA+PSB1bmk7XG5cblx0XHRcdFx0XHRcdC8vIGZvcmNlIHVuaWRpcmVjdGlvbmFsaXR5IHdoZW4gYm90aCBhcmUgdW5kZXIgdW5pIGxpbWl0XG5cdFx0XHRcdFx0XHRpZiAoIWRyYWdYICYmICFkcmFnWSkge1xuXHRcdFx0XHRcdFx0XHRpZiAocmF3RFkgPiByYXdEWClcblx0XHRcdFx0XHRcdFx0XHRkcmFnWSA9IHRydWU7XG5cdFx0XHRcdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHRcdFx0XHRkcmFnWCA9IHRydWU7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2UgaWYgKGRyYWcueCAmJiBkcmFnLnkgJiYgKGRyYWdYIHx8IGRyYWdZKSlcblx0XHRcdFx0XHQvLyBpZiBvbW5pIHdpdGggbm8gdW5pIHRoZW4gYm90aCBkcmFnWCAvIGRyYWdZIHNob3VsZCBiZSB0cnVlIGlmIGVpdGhlciBpcyB0cnVlXG5cdFx0XHRcdFx0ZHJhZ1ggPSBkcmFnWSA9IHRydWU7XG5cblx0XHRcdFx0bGV0IHAwLCBwMTtcblxuXHRcdFx0XHRpZiAoZHJhZ1gpIHtcblx0XHRcdFx0XHRpZiAoc2NhbGVYLm9yaSA9PSAwKSB7XG5cdFx0XHRcdFx0XHRwMCA9IG1vdXNlTGVmdDA7XG5cdFx0XHRcdFx0XHRwMSA9IG1vdXNlTGVmdDE7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdFx0cDAgPSBtb3VzZVRvcDA7XG5cdFx0XHRcdFx0XHRwMSA9IG1vdXNlVG9wMTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRzZXRTZWxYKG1pbihwMCwgcDEpLCBhYnMocDEgLSBwMCkpO1xuXG5cdFx0XHRcdFx0aWYgKCFkcmFnWSlcblx0XHRcdFx0XHRcdHNldFNlbFkoMCwgeURpbSk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoZHJhZ1kpIHtcblx0XHRcdFx0XHRpZiAoc2NhbGVYLm9yaSA9PSAxKSB7XG5cdFx0XHRcdFx0XHRwMCA9IG1vdXNlTGVmdDA7XG5cdFx0XHRcdFx0XHRwMSA9IG1vdXNlTGVmdDE7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdFx0cDAgPSBtb3VzZVRvcDA7XG5cdFx0XHRcdFx0XHRwMSA9IG1vdXNlVG9wMTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRzZXRTZWxZKG1pbihwMCwgcDEpLCBhYnMocDEgLSBwMCkpO1xuXG5cdFx0XHRcdFx0aWYgKCFkcmFnWClcblx0XHRcdFx0XHRcdHNldFNlbFgoMCwgeERpbSk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyB0aGUgZHJhZyBkaWRuJ3QgcGFzcyB0aGUgZGlzdCByZXF1aXJlbWVudFxuXHRcdFx0XHRpZiAoIWRyYWdYICYmICFkcmFnWSkge1xuXHRcdFx0XHRcdHNldFNlbFgoMCwgMCk7XG5cdFx0XHRcdFx0c2V0U2VsWSgwLCAwKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGRyYWcuX3ggPSBkcmFnWDtcblx0XHRkcmFnLl95ID0gZHJhZ1k7XG5cblx0XHRpZiAoc3JjID09IG51bGwpIHtcblx0XHRcdGlmIChfcHViKSB7XG5cdFx0XHRcdGlmIChzeW5jS2V5ICE9IG51bGwpIHtcblx0XHRcdFx0XHRsZXQgW3hTeW5jS2V5LCB5U3luY0tleV0gPSBzeW5jT3B0cy5zY2FsZXM7XG5cblx0XHRcdFx0XHRzeW5jT3B0cy52YWx1ZXNbMF0gPSB4U3luY0tleSAhPSBudWxsID8gcG9zVG9WYWwoc2NhbGVYLm9yaSA9PSAwID8gbW91c2VMZWZ0MSA6IG1vdXNlVG9wMSwgeFN5bmNLZXkpIDogbnVsbDtcblx0XHRcdFx0XHRzeW5jT3B0cy52YWx1ZXNbMV0gPSB5U3luY0tleSAhPSBudWxsID8gcG9zVG9WYWwoc2NhbGVYLm9yaSA9PSAxID8gbW91c2VMZWZ0MSA6IG1vdXNlVG9wMSwgeVN5bmNLZXkpIDogbnVsbDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHB1YlN5bmMobW91c2Vtb3ZlLCBzZWxmLCBtb3VzZUxlZnQxLCBtb3VzZVRvcDEsIHBsb3RXaWRDc3MsIHBsb3RIZ3RDc3MsIGlkeCk7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChjdXJzb3JGb2N1cykge1xuXHRcdFx0XHRsZXQgc2hvdWxkUHViID0gX3B1YiAmJiBzeW5jT3B0cy5zZXRTZXJpZXM7XG5cdFx0XHRcdGxldCBwID0gZm9jdXMucHJveDtcblxuXHRcdFx0XHRpZiAoZm9jdXNlZFNlcmllcyA9PSBudWxsKSB7XG5cdFx0XHRcdFx0aWYgKGNsb3Nlc3REaXN0IDw9IHApXG5cdFx0XHRcdFx0XHRzZXRTZXJpZXMoY2xvc2VzdFNlcmllcywgRk9DVVNfVFJVRSwgdHJ1ZSwgc2hvdWxkUHViKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHRpZiAoY2xvc2VzdERpc3QgPiBwKVxuXHRcdFx0XHRcdFx0c2V0U2VyaWVzKG51bGwsIEZPQ1VTX1RSVUUsIHRydWUsIHNob3VsZFB1Yik7XG5cdFx0XHRcdFx0ZWxzZSBpZiAoY2xvc2VzdFNlcmllcyAhPSBmb2N1c2VkU2VyaWVzKVxuXHRcdFx0XHRcdFx0c2V0U2VyaWVzKGNsb3Nlc3RTZXJpZXMsIEZPQ1VTX1RSVUUsIHRydWUsIHNob3VsZFB1Yik7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZWFkeSAmJiBfZmlyZSAhPT0gZmFsc2UgJiYgZmlyZShcInNldEN1cnNvclwiKTtcblx0fVxuXG5cdGxldCByZWN0ID0gbnVsbDtcblxuXHRmdW5jdGlvbiBzeW5jUmVjdChkZWZlcikge1xuXHRcdGlmIChkZWZlciA9PT0gdHJ1ZSlcblx0XHRcdHJlY3QgPSBudWxsO1xuXHRcdGVsc2Uge1xuXHRcdFx0cmVjdCA9IG92ZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cdFx0XHRmaXJlKFwic3luY1JlY3RcIiwgcmVjdCk7XG5cdFx0fVxuXHR9XG5cblx0ZnVuY3Rpb24gbW91c2VNb3ZlKGUsIHNyYywgX2wsIF90LCBfdywgX2gsIF9pKSB7XG5cdFx0aWYgKGN1cnNvci5fbG9jaylcblx0XHRcdHJldHVybjtcblxuXHRcdGNhY2hlTW91c2UoZSwgc3JjLCBfbCwgX3QsIF93LCBfaCwgX2ksIGZhbHNlLCBlICE9IG51bGwpO1xuXG5cdFx0aWYgKGUgIT0gbnVsbClcblx0XHRcdHVwZGF0ZUN1cnNvcihudWxsLCB0cnVlLCB0cnVlKTtcblx0XHRlbHNlXG5cdFx0XHR1cGRhdGVDdXJzb3Ioc3JjLCB0cnVlLCBmYWxzZSk7XG5cdH1cblxuXHRmdW5jdGlvbiBjYWNoZU1vdXNlKGUsIHNyYywgX2wsIF90LCBfdywgX2gsIF9pLCBpbml0aWFsLCBzbmFwKSB7XG5cdFx0aWYgKHJlY3QgPT0gbnVsbClcblx0XHRcdHN5bmNSZWN0KGZhbHNlKTtcblxuXHRcdGlmIChlICE9IG51bGwpIHtcblx0XHRcdF9sID0gZS5jbGllbnRYIC0gcmVjdC5sZWZ0O1xuXHRcdFx0X3QgPSBlLmNsaWVudFkgLSByZWN0LnRvcDtcblx0XHR9XG5cdFx0ZWxzZSB7XG5cdFx0XHRpZiAoX2wgPCAwIHx8IF90IDwgMCkge1xuXHRcdFx0XHRtb3VzZUxlZnQxID0gLTEwO1xuXHRcdFx0XHRtb3VzZVRvcDEgPSAtMTA7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0bGV0IFt4S2V5LCB5S2V5XSA9IHN5bmNPcHRzLnNjYWxlcztcblxuXHRcdFx0bGV0IHN5bmNPcHRzU3JjID0gc3JjLmN1cnNvci5zeW5jO1xuXHRcdFx0bGV0IFt4VmFsU3JjLCB5VmFsU3JjXSA9IHN5bmNPcHRzU3JjLnZhbHVlcztcblx0XHRcdGxldCBbeEtleVNyYywgeUtleVNyY10gPSBzeW5jT3B0c1NyYy5zY2FsZXM7XG5cdFx0XHRsZXQgW21hdGNoWEtleXMsIG1hdGNoWUtleXNdID0gc3luY09wdHMubWF0Y2g7XG5cblx0XHRcdGxldCByb3RTcmMgPSBzcmMuYXhlc1swXS5zaWRlICUgMiA9PSAxO1xuXG5cdFx0XHRsZXQgeERpbSA9IHNjYWxlWC5vcmkgPT0gMCA/IHBsb3RXaWRDc3MgOiBwbG90SGd0Q3NzLFxuXHRcdFx0XHR5RGltID0gc2NhbGVYLm9yaSA9PSAxID8gcGxvdFdpZENzcyA6IHBsb3RIZ3RDc3MsXG5cdFx0XHRcdF94RGltID0gcm90U3JjID8gX2ggOiBfdyxcblx0XHRcdFx0X3lEaW0gPSByb3RTcmMgPyBfdyA6IF9oLFxuXHRcdFx0XHRfeFBvcyA9IHJvdFNyYyA/IF90IDogX2wsXG5cdFx0XHRcdF95UG9zID0gcm90U3JjID8gX2wgOiBfdDtcblxuXHRcdFx0aWYgKHhLZXlTcmMgIT0gbnVsbClcblx0XHRcdFx0X2wgPSBtYXRjaFhLZXlzKHhLZXksIHhLZXlTcmMpID8gZ2V0UG9zKHhWYWxTcmMsIHNjYWxlc1t4S2V5XSwgeERpbSwgMCkgOiAtMTA7XG5cdFx0XHRlbHNlXG5cdFx0XHRcdF9sID0geERpbSAqIChfeFBvcy9feERpbSk7XG5cblx0XHRcdGlmICh5S2V5U3JjICE9IG51bGwpXG5cdFx0XHRcdF90ID0gbWF0Y2hZS2V5cyh5S2V5LCB5S2V5U3JjKSA/IGdldFBvcyh5VmFsU3JjLCBzY2FsZXNbeUtleV0sIHlEaW0sIDApIDogLTEwO1xuXHRcdFx0ZWxzZVxuXHRcdFx0XHRfdCA9IHlEaW0gKiAoX3lQb3MvX3lEaW0pO1xuXG5cdFx0XHRpZiAoc2NhbGVYLm9yaSA9PSAxKSB7XG5cdFx0XHRcdGxldCBfX2wgPSBfbDtcblx0XHRcdFx0X2wgPSBfdDtcblx0XHRcdFx0X3QgPSBfX2w7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKHNuYXApIHtcblx0XHRcdGlmIChfbCA8PSAxIHx8IF9sID49IHBsb3RXaWRDc3MgLSAxKVxuXHRcdFx0XHRfbCA9IGluY3JSb3VuZChfbCwgcGxvdFdpZENzcyk7XG5cblx0XHRcdGlmIChfdCA8PSAxIHx8IF90ID49IHBsb3RIZ3RDc3MgLSAxKVxuXHRcdFx0XHRfdCA9IGluY3JSb3VuZChfdCwgcGxvdEhndENzcyk7XG5cdFx0fVxuXG5cdFx0aWYgKGluaXRpYWwpIHtcblx0XHRcdHJhd01vdXNlTGVmdDAgPSBfbDtcblx0XHRcdHJhd01vdXNlVG9wMCA9IF90O1xuXG5cdFx0XHRbbW91c2VMZWZ0MCwgbW91c2VUb3AwXSA9IGN1cnNvci5tb3ZlKHNlbGYsIF9sLCBfdCk7XG5cdFx0fVxuXHRcdGVsc2Uge1xuXHRcdFx0bW91c2VMZWZ0MSA9IF9sO1xuXHRcdFx0bW91c2VUb3AxID0gX3Q7XG5cdFx0fVxuXHR9XG5cblx0Y29uc3QgX2hpZGVQcm9wcyA9IHtcblx0XHR3aWR0aDogMCxcblx0XHRoZWlnaHQ6IDAsXG5cdH07XG5cblx0ZnVuY3Rpb24gaGlkZVNlbGVjdCgpIHtcblx0XHRzZXRTZWxlY3QoX2hpZGVQcm9wcywgZmFsc2UpO1xuXHR9XG5cblx0ZnVuY3Rpb24gbW91c2VEb3duKGUsIHNyYywgX2wsIF90LCBfdywgX2gsIF9pKSB7XG5cdFx0ZHJhZ2dpbmcgPSB0cnVlO1xuXHRcdGRyYWdYID0gZHJhZ1kgPSBkcmFnLl94ID0gZHJhZy5feSA9IGZhbHNlO1xuXG5cdFx0Y2FjaGVNb3VzZShlLCBzcmMsIF9sLCBfdCwgX3csIF9oLCBfaSwgdHJ1ZSwgZmFsc2UpO1xuXG5cdFx0aWYgKGUgIT0gbnVsbCkge1xuXHRcdFx0b25Nb3VzZShtb3VzZXVwLCBkb2MsIG1vdXNlVXApO1xuXHRcdFx0cHViU3luYyhtb3VzZWRvd24sIHNlbGYsIG1vdXNlTGVmdDAsIG1vdXNlVG9wMCwgcGxvdFdpZENzcywgcGxvdEhndENzcywgbnVsbCk7XG5cdFx0fVxuXHR9XG5cblx0ZnVuY3Rpb24gbW91c2VVcChlLCBzcmMsIF9sLCBfdCwgX3csIF9oLCBfaSkge1xuXHRcdGRyYWdnaW5nID0gZHJhZy5feCA9IGRyYWcuX3kgPSBmYWxzZTtcblxuXHRcdGNhY2hlTW91c2UoZSwgc3JjLCBfbCwgX3QsIF93LCBfaCwgX2ksIGZhbHNlLCB0cnVlKTtcblxuXHRcdGxldCB7IGxlZnQsIHRvcCwgd2lkdGgsIGhlaWdodCB9ID0gc2VsZWN0O1xuXG5cdFx0bGV0IGhhc1NlbGVjdCA9IHdpZHRoID4gMCB8fCBoZWlnaHQgPiAwO1xuXG5cdFx0aGFzU2VsZWN0ICYmIHNldFNlbGVjdChzZWxlY3QpO1xuXG5cdFx0aWYgKGRyYWcuc2V0U2NhbGUgJiYgaGFzU2VsZWN0KSB7XG5cdFx0Ly9cdGlmIChzeW5jS2V5ICE9IG51bGwpIHtcblx0XHQvL1x0XHRkcmFnWCA9IGRyYWcueDtcblx0XHQvL1x0XHRkcmFnWSA9IGRyYWcueTtcblx0XHQvL1x0fVxuXG5cdFx0XHRsZXQgeE9mZiA9IGxlZnQsXG5cdFx0XHRcdHhEaW0gPSB3aWR0aCxcblx0XHRcdFx0eU9mZiA9IHRvcCxcblx0XHRcdFx0eURpbSA9IGhlaWdodDtcblxuXHRcdFx0aWYgKHNjYWxlWC5vcmkgPT0gMSkge1xuXHRcdFx0XHR4T2ZmID0gdG9wLFxuXHRcdFx0XHR4RGltID0gaGVpZ2h0LFxuXHRcdFx0XHR5T2ZmID0gbGVmdCxcblx0XHRcdFx0eURpbSA9IHdpZHRoO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoZHJhZ1gpIHtcblx0XHRcdFx0X3NldFNjYWxlKHhTY2FsZUtleSxcblx0XHRcdFx0XHRwb3NUb1ZhbCh4T2ZmLCB4U2NhbGVLZXkpLFxuXHRcdFx0XHRcdHBvc1RvVmFsKHhPZmYgKyB4RGltLCB4U2NhbGVLZXkpXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChkcmFnWSkge1xuXHRcdFx0XHRmb3IgKGxldCBrIGluIHNjYWxlcykge1xuXHRcdFx0XHRcdGxldCBzYyA9IHNjYWxlc1trXTtcblxuXHRcdFx0XHRcdGlmIChrICE9IHhTY2FsZUtleSAmJiBzYy5mcm9tID09IG51bGwgJiYgc2MubWluICE9IGluZikge1xuXHRcdFx0XHRcdFx0X3NldFNjYWxlKGssXG5cdFx0XHRcdFx0XHRcdHBvc1RvVmFsKHlPZmYgKyB5RGltLCBrKSxcblx0XHRcdFx0XHRcdFx0cG9zVG9WYWwoeU9mZiwgaylcblx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGhpZGVTZWxlY3QoKTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoY3Vyc29yLmxvY2spIHtcblx0XHRcdGN1cnNvci5fbG9jayA9ICFjdXJzb3IuX2xvY2s7XG5cblx0XHRcdGlmICghY3Vyc29yLl9sb2NrKVxuXHRcdFx0XHR1cGRhdGVDdXJzb3IobnVsbCwgdHJ1ZSwgZmFsc2UpO1xuXHRcdH1cblxuXHRcdGlmIChlICE9IG51bGwpIHtcblx0XHRcdG9mZk1vdXNlKG1vdXNldXAsIGRvYyk7XG5cdFx0XHRwdWJTeW5jKG1vdXNldXAsIHNlbGYsIG1vdXNlTGVmdDEsIG1vdXNlVG9wMSwgcGxvdFdpZENzcywgcGxvdEhndENzcywgbnVsbCk7XG5cdFx0fVxuXHR9XG5cblx0ZnVuY3Rpb24gbW91c2VMZWF2ZShlLCBzcmMsIF9sLCBfdCwgX3csIF9oLCBfaSkge1xuXHRcdGlmICghY3Vyc29yLl9sb2NrKSB7XG5cdFx0XHRsZXQgX2RyYWdnaW5nID0gZHJhZ2dpbmc7XG5cblx0XHRcdGlmIChkcmFnZ2luZykge1xuXHRcdFx0XHQvLyBoYW5kbGUgY2FzZSB3aGVuIG1vdXNlbW92ZSBhcmVuJ3QgZmlyZWQgYWxsIHRoZSB3YXkgdG8gZWRnZXMgYnkgYnJvd3NlclxuXHRcdFx0XHRsZXQgc25hcEggPSB0cnVlO1xuXHRcdFx0XHRsZXQgc25hcFYgPSB0cnVlO1xuXHRcdFx0XHRsZXQgc25hcFByb3ggPSAxMDtcblxuXHRcdFx0XHRsZXQgZHJhZ0gsIGRyYWdWO1xuXG5cdFx0XHRcdGlmIChzY2FsZVgub3JpID09IDApIHtcblx0XHRcdFx0XHRkcmFnSCA9IGRyYWdYO1xuXHRcdFx0XHRcdGRyYWdWID0gZHJhZ1k7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0ZHJhZ0ggPSBkcmFnWTtcblx0XHRcdFx0XHRkcmFnViA9IGRyYWdYO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKGRyYWdIICYmIGRyYWdWKSB7XG5cdFx0XHRcdFx0Ly8gbWF5YmUgb21uaSBjb3JuZXIgc25hcFxuXHRcdFx0XHRcdHNuYXBIID0gbW91c2VMZWZ0MSA8PSBzbmFwUHJveCB8fCBtb3VzZUxlZnQxID49IHBsb3RXaWRDc3MgLSBzbmFwUHJveDtcblx0XHRcdFx0XHRzbmFwViA9IG1vdXNlVG9wMSAgPD0gc25hcFByb3ggfHwgbW91c2VUb3AxICA+PSBwbG90SGd0Q3NzIC0gc25hcFByb3g7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoZHJhZ0ggJiYgc25hcEgpXG5cdFx0XHRcdFx0bW91c2VMZWZ0MSA9IG1vdXNlTGVmdDEgPCBtb3VzZUxlZnQwID8gMCA6IHBsb3RXaWRDc3M7XG5cblx0XHRcdFx0aWYgKGRyYWdWICYmIHNuYXBWKVxuXHRcdFx0XHRcdG1vdXNlVG9wMSA9IG1vdXNlVG9wMSA8IG1vdXNlVG9wMCA/IDAgOiBwbG90SGd0Q3NzO1xuXG5cdFx0XHRcdHVwZGF0ZUN1cnNvcihudWxsLCB0cnVlLCB0cnVlKTtcblxuXHRcdFx0XHRkcmFnZ2luZyA9IGZhbHNlO1xuXHRcdFx0fVxuXG5cdFx0XHRtb3VzZUxlZnQxID0gLTEwO1xuXHRcdFx0bW91c2VUb3AxID0gLTEwO1xuXG5cdFx0XHQvLyBwYXNzaW5nIGEgbm9uLW51bGwgdGltZXN0YW1wIHRvIGZvcmNlIHN5bmMvbW91c2Vtb3ZlIGV2ZW50XG5cdFx0XHR1cGRhdGVDdXJzb3IobnVsbCwgdHJ1ZSwgdHJ1ZSk7XG5cblx0XHRcdGlmIChfZHJhZ2dpbmcpXG5cdFx0XHRcdGRyYWdnaW5nID0gX2RyYWdnaW5nO1xuXHRcdH1cblx0fVxuXG5cdGZ1bmN0aW9uIGRibENsaWNrKGUsIHNyYywgX2wsIF90LCBfdywgX2gsIF9pKSB7XG5cdFx0YXV0b1NjYWxlWCgpO1xuXG5cdFx0aGlkZVNlbGVjdCgpO1xuXG5cdFx0aWYgKGUgIT0gbnVsbClcblx0XHRcdHB1YlN5bmMoZGJsY2xpY2ssIHNlbGYsIG1vdXNlTGVmdDEsIG1vdXNlVG9wMSwgcGxvdFdpZENzcywgcGxvdEhndENzcywgbnVsbCk7XG5cdH1cblxuXHRmdW5jdGlvbiBzeW5jUHhSYXRpbygpIHtcblx0XHRheGVzLmZvckVhY2goc3luY0ZvbnRTaXplKTtcblx0XHRfc2V0U2l6ZShzZWxmLndpZHRoLCBzZWxmLmhlaWdodCwgdHJ1ZSk7XG5cdH1cblxuXHRvbihkcHB4Y2hhbmdlLCB3aW4sIHN5bmNQeFJhdGlvKTtcblxuXHQvLyBpbnRlcm5hbCBwdWIvc3ViXG5cdGNvbnN0IGV2ZW50cyA9IHt9O1xuXG5cdGV2ZW50cy5tb3VzZWRvd24gPSBtb3VzZURvd247XG5cdGV2ZW50cy5tb3VzZW1vdmUgPSBtb3VzZU1vdmU7XG5cdGV2ZW50cy5tb3VzZXVwID0gbW91c2VVcDtcblx0ZXZlbnRzLmRibGNsaWNrID0gZGJsQ2xpY2s7XG5cdGV2ZW50c1tcInNldFNlcmllc1wiXSA9IChlLCBzcmMsIGlkeCwgb3B0cykgPT4ge1xuXHRcdHNldFNlcmllcyhpZHgsIG9wdHMsIHRydWUsIGZhbHNlKTtcblx0fTtcblxuXHRpZiAoY3Vyc29yLnNob3cpIHtcblx0XHRvbk1vdXNlKG1vdXNlZG93biwgIG92ZXIsIG1vdXNlRG93bik7XG5cdFx0b25Nb3VzZShtb3VzZW1vdmUsICBvdmVyLCBtb3VzZU1vdmUpO1xuXHRcdG9uTW91c2UobW91c2VlbnRlciwgb3Zlciwgc3luY1JlY3QpO1xuXHRcdG9uTW91c2UobW91c2VsZWF2ZSwgb3ZlciwgbW91c2VMZWF2ZSk7XG5cblx0XHRvbk1vdXNlKGRibGNsaWNrLCBvdmVyLCBkYmxDbGljayk7XG5cblx0XHRjdXJzb3JQbG90cy5hZGQoc2VsZik7XG5cblx0XHRzZWxmLnN5bmNSZWN0ID0gc3luY1JlY3Q7XG5cdH1cblxuXHQvLyBleHRlcm5hbCBvbi9vZmZcblx0Y29uc3QgaG9va3MgPSBzZWxmLmhvb2tzID0gb3B0cy5ob29rcyB8fCB7fTtcblxuXHRmdW5jdGlvbiBmaXJlKGV2TmFtZSwgYTEsIGEyKSB7XG5cdFx0aWYgKGV2TmFtZSBpbiBob29rcykge1xuXHRcdFx0aG9va3NbZXZOYW1lXS5mb3JFYWNoKGZuID0+IHtcblx0XHRcdFx0Zm4uY2FsbChudWxsLCBzZWxmLCBhMSwgYTIpO1xuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG5cblx0KG9wdHMucGx1Z2lucyB8fCBbXSkuZm9yRWFjaChwID0+IHtcblx0XHRmb3IgKGxldCBldk5hbWUgaW4gcC5ob29rcylcblx0XHRcdGhvb2tzW2V2TmFtZV0gPSAoaG9va3NbZXZOYW1lXSB8fCBbXSkuY29uY2F0KHAuaG9va3NbZXZOYW1lXSk7XG5cdH0pO1xuXG5cdGNvbnN0IHN5bmNPcHRzID0gYXNzaWduKHtcblx0XHRrZXk6IG51bGwsXG5cdFx0c2V0U2VyaWVzOiBmYWxzZSxcblx0XHRmaWx0ZXJzOiB7XG5cdFx0XHRwdWI6IHJldFRydWUsXG5cdFx0XHRzdWI6IHJldFRydWUsXG5cdFx0fSxcblx0XHRzY2FsZXM6IFt4U2NhbGVLZXksIHNlcmllc1sxXSA/IHNlcmllc1sxXS5zY2FsZSA6IG51bGxdLFxuXHRcdG1hdGNoOiBbcmV0RXEsIHJldEVxXSxcblx0XHR2YWx1ZXM6IFtudWxsLCBudWxsXSxcblx0fSwgY3Vyc29yLnN5bmMpO1xuXG5cdChjdXJzb3Iuc3luYyA9IHN5bmNPcHRzKTtcblxuXHRjb25zdCBzeW5jS2V5ID0gc3luY09wdHMua2V5O1xuXG5cdGNvbnN0IHN5bmMgPSBfc3luYyhzeW5jS2V5KTtcblxuXHRmdW5jdGlvbiBwdWJTeW5jKHR5cGUsIHNyYywgeCwgeSwgdywgaCwgaSkge1xuXHRcdGlmIChzeW5jT3B0cy5maWx0ZXJzLnB1Yih0eXBlLCBzcmMsIHgsIHksIHcsIGgsIGkpKVxuXHRcdFx0c3luYy5wdWIodHlwZSwgc3JjLCB4LCB5LCB3LCBoLCBpKTtcblx0fVxuXG5cdHN5bmMuc3ViKHNlbGYpO1xuXG5cdGZ1bmN0aW9uIHB1Yih0eXBlLCBzcmMsIHgsIHksIHcsIGgsIGkpIHtcblx0XHRpZiAoc3luY09wdHMuZmlsdGVycy5zdWIodHlwZSwgc3JjLCB4LCB5LCB3LCBoLCBpKSlcblx0XHRcdGV2ZW50c1t0eXBlXShudWxsLCBzcmMsIHgsIHksIHcsIGgsIGkpO1xuXHR9XG5cblx0KHNlbGYucHViID0gcHViKTtcblxuXHRmdW5jdGlvbiBkZXN0cm95KCkge1xuXHRcdHN5bmMudW5zdWIoc2VsZik7XG5cdFx0Y3Vyc29yUGxvdHMuZGVsZXRlKHNlbGYpO1xuXHRcdG1vdXNlTGlzdGVuZXJzLmNsZWFyKCk7XG5cdFx0b2ZmKGRwcHhjaGFuZ2UsIHdpbiwgc3luY1B4UmF0aW8pO1xuXHRcdHJvb3QucmVtb3ZlKCk7XG5cdFx0ZmlyZShcImRlc3Ryb3lcIik7XG5cdH1cblxuXHRzZWxmLmRlc3Ryb3kgPSBkZXN0cm95O1xuXG5cdGZ1bmN0aW9uIF9pbml0KCkge1xuXHRcdGZpcmUoXCJpbml0XCIsIG9wdHMsIGRhdGEpO1xuXG5cdFx0c2V0RGF0YShkYXRhIHx8IG9wdHMuZGF0YSwgZmFsc2UpO1xuXG5cdFx0aWYgKHBlbmRTY2FsZXNbeFNjYWxlS2V5XSlcblx0XHRcdHNldFNjYWxlKHhTY2FsZUtleSwgcGVuZFNjYWxlc1t4U2NhbGVLZXldKTtcblx0XHRlbHNlXG5cdFx0XHRhdXRvU2NhbGVYKCk7XG5cblx0XHRfc2V0U2l6ZShvcHRzLndpZHRoLCBvcHRzLmhlaWdodCk7XG5cblx0XHR1cGRhdGVDdXJzb3IobnVsbCwgdHJ1ZSwgZmFsc2UpO1xuXG5cdFx0c2V0U2VsZWN0KHNlbGVjdCwgZmFsc2UpO1xuXHR9XG5cblx0c2VyaWVzLmZvckVhY2goaW5pdFNlcmllcyk7XG5cblx0YXhlcy5mb3JFYWNoKGluaXRBeGlzKTtcblxuXHRpZiAodGhlbikge1xuXHRcdGlmICh0aGVuIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcblx0XHRcdHRoZW4uYXBwZW5kQ2hpbGQocm9vdCk7XG5cdFx0XHRfaW5pdCgpO1xuXHRcdH1cblx0XHRlbHNlXG5cdFx0XHR0aGVuKHNlbGYsIF9pbml0KTtcblx0fVxuXHRlbHNlXG5cdFx0X2luaXQoKTtcblxuXHRyZXR1cm4gc2VsZjtcbn1cblxudVBsb3QuYXNzaWduID0gYXNzaWduO1xudVBsb3QuZm10TnVtID0gZm10TnVtO1xudVBsb3QucmFuZ2VOdW0gPSByYW5nZU51bTtcbnVQbG90LnJhbmdlTG9nID0gcmFuZ2VMb2c7XG51UGxvdC5yYW5nZUFzaW5oID0gcmFuZ2VBc2luaDtcbnVQbG90Lm9yaWVudCAgID0gb3JpZW50O1xudVBsb3QucHhSYXRpbyA9IHB4UmF0aW87XG5cbntcblx0dVBsb3Quam9pbiA9IGpvaW47XG59XG5cbntcblx0dVBsb3QuZm10RGF0ZSA9IGZtdERhdGU7XG5cdHVQbG90LnR6RGF0ZSAgPSB0ekRhdGU7XG59XG5cbntcblx0dVBsb3Quc3luYyA9IF9zeW5jO1xufVxuXG57XG5cdHVQbG90LmFkZEdhcCA9IGFkZEdhcDtcblx0dVBsb3QuY2xpcEdhcHMgPSBjbGlwR2FwcztcblxuXHRsZXQgcGF0aHMgPSB1UGxvdC5wYXRocyA9IHtcblx0XHRwb2ludHMsXG5cdH07XG5cblx0KHBhdGhzLmxpbmVhciAgPSBsaW5lYXIpO1xuXHQocGF0aHMuc3RlcHBlZCA9IHN0ZXBwZWQpO1xuXHQocGF0aHMuYmFycyAgICA9IGJhcnMpO1xuXHQocGF0aHMuc3BsaW5lICA9IG1vbm90b25lQ3ViaWMpO1xufVxuXG5leHBvcnQgeyB1UGxvdCBhcyBkZWZhdWx0IH07XG4iLCJmdW5jdGlvbiBzdGFjayhkYXRhLCBvbWl0KSB7XG4gIGxldCBkYXRhMiA9IFtdO1xuICBsZXQgYmFuZHMgPSBbXTtcbiAgbGV0IGQwTGVuID0gZGF0YVswXS5sZW5ndGg7XG4gIGxldCBhY2N1bSA9IEFycmF5KGQwTGVuKTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGQwTGVuOyBpKyspIGFjY3VtW2ldID0gMDtcblxuICBmb3IgKGxldCBpID0gMTsgaSA8IGRhdGEubGVuZ3RoOyBpKyspXG4gICAgZGF0YTIucHVzaChvbWl0KGkpID8gZGF0YVtpXSA6IGRhdGFbaV0ubWFwKCh2LCBpKSA9PiAoYWNjdW1baV0gKz0gK3YpKSk7XG5cbiAgZm9yIChsZXQgaSA9IDE7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKVxuICAgICFvbWl0KGkpICYmXG4gICAgICBiYW5kcy5wdXNoKHtcbiAgICAgICAgc2VyaWVzOiBbZGF0YS5maW5kSW5kZXgoKHMsIGopID0+IGogPiBpICYmICFvbWl0KGopKSwgaV1cbiAgICAgIH0pO1xuXG4gIGJhbmRzID0gYmFuZHMuZmlsdGVyKGIgPT4gYi5zZXJpZXNbMV0gPiAtMSk7XG5cbiAgcmV0dXJuIHtcbiAgICBkYXRhOiBbZGF0YVswXV0uY29uY2F0KGRhdGEyKSxcbiAgICBiYW5kc1xuICB9O1xufVxuXG5mdW5jdGlvbiBnZXRPcHRzKHRpdGxlLCBzZXJpZXMpIHtcbiAgcmV0dXJuIHtcbiAgICBzY2FsZXM6IHtcbiAgICAgIHg6IHtcbiAgICAgICAgdGltZTogdHJ1ZVxuICAgICAgfVxuICAgIH0sXG4gICAgc2VyaWVzXG4gIH07XG59XG5cbmZ1bmN0aW9uIGdldFN0YWNrZWRPcHRzKHRpdGxlLCBzZXJpZXMsIGRhdGEsIGludGVycCkge1xuICBsZXQgb3B0cyA9IGdldE9wdHModGl0bGUsIHNlcmllcyk7XG5cbiAgbGV0IGludGVycGVkID0gaW50ZXJwID8gaW50ZXJwKGRhdGEpIDogZGF0YTtcblxuICBsZXQgc3RhY2tlZCA9IHN0YWNrKGludGVycGVkLCBpID0+IGZhbHNlKTtcbiAgb3B0cy5iYW5kcyA9IHN0YWNrZWQuYmFuZHM7XG5cbiAgb3B0cy5jdXJzb3IgPSBvcHRzLmN1cnNvciB8fCB7fTtcbiAgb3B0cy5jdXJzb3IuZGF0YUlkeCA9ICh1LCBzZXJpZXNJZHgsIGNsb3Nlc3RJZHgsIHhWYWx1ZSkgPT4ge1xuICAgIHJldHVybiBkYXRhW3Nlcmllc0lkeF1bY2xvc2VzdElkeF0gPT09IG51bGwgPyBudWxsIDogY2xvc2VzdElkeDtcbiAgfTtcblxuICBvcHRzLnNlcmllcy5mb3JFYWNoKHMgPT4ge1xuICAgIHMudmFsdWUgPSAodSwgdiwgc2ksIGkpID0+IGRhdGFbc2ldW2ldO1xuXG4gICAgcy5wb2ludHMgPSBzLnBvaW50cyB8fCB7fTtcblxuICAgIC8vIHNjYW4gcmF3IHVuc3RhY2tlZCBkYXRhIHRvIHJldHVybiBvbmx5IHJlYWwgcG9pbnRzXG4gICAgcy5wb2ludHMuZmlsdGVyID0gKHUsIHNlcmllc0lkeCwgc2hvdywgZ2FwcykgPT4ge1xuICAgICAgaWYgKHNob3cpIHtcbiAgICAgICAgbGV0IHB0cyA9IFtdO1xuICAgICAgICBkYXRhW3Nlcmllc0lkeF0uZm9yRWFjaCgodiwgaSkgPT4ge1xuICAgICAgICAgIHYgIT09IG51bGwgJiYgcHRzLnB1c2goaSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcHRzO1xuICAgICAgfVxuICAgIH07XG4gIH0pO1xuXG4gIC8vIGZvcmNlIDAgdG8gYmUgdGhlIHN1bSBtaW5pbXVtIHRoaXMgaW5zdGVhZCBvZiB0aGUgYm90dG9tIHNlcmllc1xuICBvcHRzLnNjYWxlcy55ID0ge1xuICAgIHJhbmdlOiAodSwgbWluLCBtYXgpID0+IHtcbiAgICAgIGxldCBtaW5NYXggPSB1UGxvdC5yYW5nZU51bShtaW4sIG1heCwgMC4xLCB0cnVlKTtcbiAgICAgIHJldHVybiBbbWluTWF4WzBdLCBtaW5NYXhbMV1dO1xuICAgIH1cbiAgfTtcblxuICAvLyByZXN0YWNrIG9uIHRvZ2dsZVxuICBvcHRzLmhvb2tzID0ge1xuICAgIHNldFNlcmllczogW1xuICAgICAgKHUsIGkpID0+IHtcbiAgICAgICAgbGV0IHN0YWNrZWQgPSBzdGFjayhkYXRhLCBpID0+ICF1LnNlcmllc1tpXS5zaG93KTtcbiAgICAgICAgdS5kZWxCYW5kKG51bGwpO1xuICAgICAgICBzdGFja2VkLmJhbmRzLmZvckVhY2goYiA9PiB1LmFkZEJhbmQoYikpO1xuICAgICAgICB1LnNldERhdGEoc3RhY2tlZC5kYXRhKTtcbiAgICAgIH1cbiAgICBdXG4gIH07XG5cbiAgcmV0dXJuIHsgb3B0cywgZGF0YTogc3RhY2tlZC5kYXRhIH07XG59XG5cbmZ1bmN0aW9uIHN0YWNrMihzZXJpZXMpIHtcbiAgLy8gZm9yIHVwbG90IGRhdGFcbiAgbGV0IGRhdGEgPSBBcnJheShzZXJpZXMubGVuZ3RoKTtcbiAgbGV0IGJhbmRzID0gW107XG5cbiAgbGV0IGRhdGFMZW4gPSBzZXJpZXNbMF0udmFsdWVzLmxlbmd0aDtcblxuICBsZXQgemVyb0FyciA9IEFycmF5KGRhdGFMZW4pLmZpbGwoMCk7XG5cbiAgbGV0IHN0YWNrR3JvdXBzID0gbmV3IE1hcCgpO1xuICBsZXQgc2VyaWVzU3RhY2tLZXlzID0gQXJyYXkoc2VyaWVzLmxlbmd0aCk7XG5cbiAgc2VyaWVzLmZvckVhY2goKHMsIHNpKSA9PiB7XG4gICAgbGV0IHZhbHMgPSBzLnZhbHVlcy5zbGljZSgpO1xuXG4gICAgLy8gYXBwbHkgbmVnWVxuICAgIGlmIChzLm5lZ1kpIHtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdmFscy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAodmFsc1tpXSAhPT0gbnVsbCkgdmFsc1tpXSAqPSAtMTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAocy5zdGFja2luZy5tb2RlICE9IFwibm9uZVwiKSB7XG4gICAgICBsZXQgaGFzUG9zID0gdmFscy5zb21lKHYgPT4gdiA+IDApO1xuICAgICAgLy8gZGVyaXZlIHN0YWNraW5nIGtleVxuICAgICAgbGV0IHN0YWNrS2V5ID0gKHNlcmllc1N0YWNrS2V5c1tzaV0gPVxuICAgICAgICBzLnN0YWNraW5nLm1vZGUgKyBzLnNjYWxlS2V5ICsgcy5zdGFja2luZy5ncm91cCArIChoYXNQb3MgPyBcIitcIiA6IFwiLVwiKSk7XG4gICAgICBsZXQgZ3JvdXAgPSBzdGFja0dyb3Vwcy5nZXQoc3RhY2tLZXkpO1xuXG4gICAgICAvLyBpbml0aWFsaXplIHN0YWNraW5nIGdyb3VwXG4gICAgICBpZiAoZ3JvdXAgPT09IG51bGwpIHtcbiAgICAgICAgZ3JvdXAgPSB7XG4gICAgICAgICAgc2VyaWVzOiBbXSxcbiAgICAgICAgICBhY2M6IHplcm9BcnIuc2xpY2UoKSxcbiAgICAgICAgICBkaXI6IGhhc1BvcyA/IC0xIDogMVxuICAgICAgICB9O1xuICAgICAgICBzdGFja0dyb3Vwcy5zZXQoc3RhY2tLZXksIGdyb3VwKTtcbiAgICAgIH1cblxuICAgICAgLy8gcHVzaCBmb3IgYmFuZHMgZ2VuXG4gICAgICBncm91cC5zZXJpZXMudW5zaGlmdChzaSk7XG5cbiAgICAgIGxldCBzdGFja2VkID0gKGRhdGFbc2ldID0gQXJyYXkoZGF0YUxlbikpO1xuICAgICAgbGV0IHsgYWNjIH0gPSBncm91cDtcblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhTGVuOyBpKyspIHtcbiAgICAgICAgbGV0IHYgPSB2YWxzW2ldO1xuXG4gICAgICAgIGlmICh2ICE9PSBudWxsKSBzdGFja2VkW2ldID0gYWNjW2ldICs9IHY7XG4gICAgICAgIGVsc2Ugc3RhY2tlZFtpXSA9IHY7IC8vIHdlIG1heSB3YW50IHRvIGNvZXJjZSB0byAwIGhlcmVcbiAgICAgIH1cbiAgICB9IGVsc2UgZGF0YVtzaV0gPSB2YWxzO1xuICB9KTtcblxuICAvLyByZS1jb21wdXRlIGJ5IHBlcmNlbnRcbiAgc2VyaWVzLmZvckVhY2goKHMsIHNpKSA9PiB7XG4gICAgaWYgKHMuc3RhY2tpbmcubW9kZSA9PSBcInBlcmNlbnRcIikge1xuICAgICAgbGV0IGdyb3VwID0gc3RhY2tHcm91cHMuZ2V0KHNlcmllc1N0YWNrS2V5c1tzaV0pO1xuICAgICAgbGV0IHsgYWNjIH0gPSBncm91cDtcblxuICAgICAgLy8gcmUtbmVnYXRpZnkgcGVyY2VudFxuICAgICAgbGV0IHNpZ24gPSBncm91cC5kaXIgKiAtMTtcblxuICAgICAgbGV0IHN0YWNrZWQgPSBkYXRhW3NpXTtcblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhTGVuOyBpKyspIHtcbiAgICAgICAgbGV0IHYgPSBzdGFja2VkW2ldO1xuXG4gICAgICAgIGlmICh2ICE9PSBudWxsKSBzdGFja2VkW2ldID0gc2lnbiAqICh2IC8gYWNjW2ldKTtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIC8vIGdlbmVyYXRlIGJhbmRzIGJldHdlZW4gYWRqYWNlbnQgZ3JvdXAgc2VyaWVzXG4gIHN0YWNrR3JvdXBzLmZvckVhY2goZ3JvdXAgPT4ge1xuICAgIGxldCB7IHNlcmllcywgZGlyIH0gPSBncm91cDtcbiAgICBsZXQgbGFzdElkeCA9IHNlcmllcy5sZW5ndGggLSAxO1xuXG4gICAgc2VyaWVzLmZvckVhY2goKHNpLCBpKSA9PiB7XG4gICAgICBpZiAoaSAhPSBsYXN0SWR4KSB7XG4gICAgICAgIGxldCBuZXh0SWR4ID0gc2VyaWVzW2kgKyAxXTtcbiAgICAgICAgYmFuZHMucHVzaCh7XG4gICAgICAgICAgLy8gc2luY2Ugd2UncmUgbm90IHBhc3NpbmcgeCBzZXJpZXNbMF0gZm9yIHN0YWNraW5nLCByZWFsIGlkeHMgYXJlIGFjdHVhbGx5ICsxXG4gICAgICAgICAgc2VyaWVzOiBbc2kgKyAxLCBuZXh0SWR4ICsgMV0sXG4gICAgICAgICAgZGlyXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICByZXR1cm4ge1xuICAgIGRhdGEsXG4gICAgYmFuZHNcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN0YWNrZWRDaGFydCh0aXRsZSwgc2VyaWVzLCBfZGF0YSwgaW50ZXJwLCB3aWR0aCwgaGVpZ2h0LCBob29rcywgZWwpIHtcbiAgbGV0IHsgb3B0cywgZGF0YSB9ID0gZ2V0U3RhY2tlZE9wdHModGl0bGUsIHNlcmllcywgX2RhdGEsIGludGVycCk7XG4gIG9wdHMudGl0bGUgPSB0aXRsZTtcbiAgb3B0cy53aWR0aCA9IHdpZHRoO1xuICBvcHRzLmhlaWdodCA9IGhlaWdodDtcbiAgb3B0cy5ob29rcyA9IE9iamVjdC5hc3NpZ24ob3B0cy5ob29rcywgaG9va3MpO1xuICBjb25zb2xlLmxvZyhvcHRzKTtcbiAgcmV0dXJuIG5ldyB1UGxvdChvcHRzLCBkYXRhLCBlbCk7XG59XG5cbiIsIi8vIEZyb20gRnJpc3MgdHV0byAoaHR0cHM6Ly9naXRodWIuY29tL0ZyaXNzQW5hbHl0aWNzL3NoaW55SnNUdXRvcmlhbHMvYmxvYi9tYXN0ZXIvdHV0b3JpYWxzL3R1dG9yaWFsXzAzLlJtZClcbmV4cG9ydCBmdW5jdGlvbiBnZXRXaWRnZXQoaWQpIHtcbiAgdmFyIGh0bWxXaWRnZXRzT2JqID0gSFRNTFdpZGdldHMuZmluZChcIiNcIiArIGlkKTtcbiAgdmFyIHdpZGdldE9iajtcbiAgaWYgKHR5cGVvZiBodG1sV2lkZ2V0c09iaiAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgIHdpZGdldE9iaiA9IGh0bWxXaWRnZXRzT2JqLmdldFdpZGdldCgpO1xuICB9XG4gIHJldHVybiB3aWRnZXRPYmo7XG59XG4iLCJtb2R1bGUuZXhwb3J0cyA9IHdpbmRvd1tcIkhUTUxXaWRnZXRzXCJdOyIsIi8vIFRoZSBtb2R1bGUgY2FjaGVcbnZhciBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX18gPSB7fTtcblxuLy8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbmZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG5cdHZhciBjYWNoZWRNb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdO1xuXHRpZiAoY2FjaGVkTW9kdWxlICE9PSB1bmRlZmluZWQpIHtcblx0XHRyZXR1cm4gY2FjaGVkTW9kdWxlLmV4cG9ydHM7XG5cdH1cblx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcblx0dmFyIG1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF0gPSB7XG5cdFx0aWQ6IG1vZHVsZUlkLFxuXHRcdC8vIG5vIG1vZHVsZS5sb2FkZWQgbmVlZGVkXG5cdFx0ZXhwb3J0czoge31cblx0fTtcblxuXHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cblx0X193ZWJwYWNrX21vZHVsZXNfX1ttb2R1bGVJZF0obW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cblx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcblx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xufVxuXG4iLCIvLyBnZXREZWZhdWx0RXhwb3J0IGZ1bmN0aW9uIGZvciBjb21wYXRpYmlsaXR5IHdpdGggbm9uLWhhcm1vbnkgbW9kdWxlc1xuX193ZWJwYWNrX3JlcXVpcmVfXy5uID0gKG1vZHVsZSkgPT4ge1xuXHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cblx0XHQoKSA9PiAobW9kdWxlWydkZWZhdWx0J10pIDpcblx0XHQoKSA9PiAobW9kdWxlKTtcblx0X193ZWJwYWNrX3JlcXVpcmVfXy5kKGdldHRlciwgeyBhOiBnZXR0ZXIgfSk7XG5cdHJldHVybiBnZXR0ZXI7XG59OyIsIi8vIGRlZmluZSBnZXR0ZXIgZnVuY3Rpb25zIGZvciBoYXJtb255IGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uZCA9IChleHBvcnRzLCBkZWZpbml0aW9uKSA9PiB7XG5cdGZvcih2YXIga2V5IGluIGRlZmluaXRpb24pIHtcblx0XHRpZihfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZGVmaW5pdGlvbiwga2V5KSAmJiAhX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIGtleSkpIHtcblx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBrZXksIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBkZWZpbml0aW9uW2tleV0gfSk7XG5cdFx0fVxuXHR9XG59OyIsIl9fd2VicGFja19yZXF1aXJlX18ubyA9IChvYmosIHByb3ApID0+IChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKSkiLCIvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSAoZXhwb3J0cykgPT4ge1xuXHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcblx0fVxuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xufTsiLCJfX3dlYnBhY2tfcmVxdWlyZV9fLm5jID0gdW5kZWZpbmVkOyIsImltcG9ydCBcIndpZGdldHNcIjtcbmltcG9ydCB1UGxvdCBmcm9tIFwidXBsb3RcIjtcbmltcG9ydCBcInVwbG90L2Rpc3QvdVBsb3QubWluLmNzc1wiO1xuaW1wb3J0ICogYXMgdXRpbHMgZnJvbSBcIi4uL21vZHVsZXMvdXRpbHNcIjtcbmltcG9ydCB7IHN0YWNrZWRDaGFydCB9IGZyb20gXCIuLi9tb2R1bGVzL3N0YWNrXCI7XG5cbmNvbnN0IHJlc2l6ZXIgPSBlbCA9PiB7XG4gIGNvbnN0IGZ1bmMgPSAodSwgaW5pdCkgPT4ge1xuICAgIGNvbnN0IHJlc2l6ZU9ic2VydmVyID0gbmV3IFJlc2l6ZU9ic2VydmVyKGVudHJpZXMgPT4ge1xuICAgICAgZm9yIChsZXQgZW50cnkgb2YgZW50cmllcykge1xuICAgICAgICBsZXQgYWRqSGVpZ2h0ID0gZW50cnkuY29udGVudFJlY3QuaGVpZ2h0O1xuICAgICAgICBsZXQgYWRqV2lkdGggPSBlbnRyeS5jb250ZW50UmVjdC53aWR0aDtcbiAgICAgICAgY29uc3QgZXh0cmFzID0gdS5yb290LnF1ZXJ5U2VsZWN0b3JBbGwoXCIudS1sZWdlbmQsIC51LXRpdGxlXCIpO1xuICAgICAgICBmb3IgKGxldCBleHRyYSBvZiBleHRyYXMpIHtcbiAgICAgICAgICBhZGpIZWlnaHQgLT0gTWF0aC5mbG9vcihleHRyYS5vZmZzZXRIZWlnaHQpO1xuICAgICAgICB9XG4gICAgICAgIHUuc2V0U2l6ZSh7IHdpZHRoOiBhZGpXaWR0aCwgaGVpZ2h0OiBhZGpIZWlnaHQgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmVzaXplT2JzZXJ2ZXIub2JzZXJ2ZShlbCk7XG4gICAgZWwuYXBwZW5kQ2hpbGQodS5yb290KTtcbiAgICBpbml0KCk7XG4gIH07XG4gIHJldHVybiBmdW5jO1xufTtcblxuY29uc3QgZHJhd1BvaW50cyA9ICh1LCBzZXJpZXNJZHgsIGlkeDAsIGlkeDEpID0+IHtcbiAgY29uc3Qgc2l6ZSA9IDUgKiBkZXZpY2VQaXhlbFJhdGlvO1xuXG4gIHVQbG90Lm9yaWVudChcbiAgICB1LFxuICAgIHNlcmllc0lkeCxcbiAgICAoXG4gICAgICBzZXJpZXMsXG4gICAgICBkYXRhWCxcbiAgICAgIGRhdGFZLFxuICAgICAgc2NhbGVYLFxuICAgICAgc2NhbGVZLFxuICAgICAgdmFsVG9Qb3NYLFxuICAgICAgdmFsVG9Qb3NZLFxuICAgICAgeE9mZixcbiAgICAgIHlPZmYsXG4gICAgICB4RGltLFxuICAgICAgeURpbSxcbiAgICAgIG1vdmVUbyxcbiAgICAgIGxpbmVUbyxcbiAgICAgIHJlY3QsXG4gICAgICBhcmNcbiAgICApID0+IHtcbiAgICAgIGxldCBkID0gdS5kYXRhW3Nlcmllc0lkeF07XG5cbiAgICAgIHUuY3R4LmZpbGxTdHlsZSA9IHNlcmllcy5zdHJva2UoKTtcblxuICAgICAgbGV0IGRlZzM2MCA9IDIgKiBNYXRoLlBJO1xuXG4gICAgICBjb25zb2xlLnRpbWUoXCJwb2ludHNcIik7XG5cbiAgICAgIC8vXHRsZXQgY2lyID0gbmV3IFBhdGgyRCgpO1xuICAgICAgLy9cdGNpci5tb3ZlVG8oMCwgMCk7XG4gICAgICAvL1x0YXJjKGNpciwgMCwgMCwgMywgMCwgZGVnMzYwKTtcblxuICAgICAgLy8gQ3JlYXRlIHRyYW5zZm9ybWF0aW9uIG1hdHJpeCB0aGF0IG1vdmVzIDIwMCBwb2ludHMgdG8gdGhlIHJpZ2h0XG4gICAgICAvL1x0bGV0IG0gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoJ2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJywgJ3N2ZycpLmNyZWF0ZVNWR01hdHJpeCgpO1xuICAgICAgLy9cdG0uYSA9IDE7ICAgbS5iID0gMDtcbiAgICAgIC8vXHRtLmMgPSAwOyAgIG0uZCA9IDE7XG4gICAgICAvL1x0bS5lID0gMjAwOyBtLmYgPSAwO1xuXG4gICAgICBsZXQgcCA9IG5ldyBQYXRoMkQoKTtcblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkWzBdLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGxldCB4VmFsID0gZFswXVtpXTtcbiAgICAgICAgbGV0IHlWYWwgPSBkWzFdW2ldO1xuXG4gICAgICAgIGlmIChcbiAgICAgICAgICB4VmFsID49IHNjYWxlWC5taW4gJiZcbiAgICAgICAgICB4VmFsIDw9IHNjYWxlWC5tYXggJiZcbiAgICAgICAgICB5VmFsID49IHNjYWxlWS5taW4gJiZcbiAgICAgICAgICB5VmFsIDw9IHNjYWxlWS5tYXhcbiAgICAgICAgKSB7XG4gICAgICAgICAgbGV0IGN4ID0gdmFsVG9Qb3NYKHhWYWwsIHNjYWxlWCwgeERpbSwgeE9mZik7XG4gICAgICAgICAgbGV0IGN5ID0gdmFsVG9Qb3NZKHlWYWwsIHNjYWxlWSwgeURpbSwgeU9mZik7XG5cbiAgICAgICAgICBwLm1vdmVUbyhjeCArIHNpemUgLyAyLCBjeSk7XG4gICAgICAgICAgLy9cdGFyYyhwLCBjeCwgY3ksIDMsIDAsIGRlZzM2MCk7XG4gICAgICAgICAgYXJjKHAsIGN4LCBjeSwgc2l6ZSAvIDIsIDAsIGRlZzM2MCk7XG5cbiAgICAgICAgICAvL1x0bS5lID0gY3g7XG4gICAgICAgICAgLy9cdG0uZiA9IGN5O1xuICAgICAgICAgIC8vXHRwLmFkZFBhdGgoY2lyLCBtKTtcblxuICAgICAgICAgIC8vXHRxdC5hZGQoe3g6IGN4IC0gMS41LCB5OiBjeSAtIDEuNSwgdzogMywgaDogMywgc2lkeDogc2VyaWVzSWR4LCBkaWR4OiBpfSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc29sZS50aW1lRW5kKFwicG9pbnRzXCIpO1xuXG4gICAgICB1LmN0eC5maWxsKHApO1xuICAgIH1cbiAgKTtcblxuICByZXR1cm4gbnVsbDtcbn07XG5cbkhUTUxXaWRnZXRzLndpZGdldCh7XG4gIG5hbWU6IFwidVBsb3RcIixcblxuICB0eXBlOiBcIm91dHB1dFwiLFxuXG4gIGZhY3Rvcnk6IGZ1bmN0aW9uKGVsLCB3aWR0aCwgaGVpZ2h0KSB7XG4gICAgdmFyIHBsb3QsIG9wdGlvbnMsIGRhdGE7XG5cbiAgICByZXR1cm4ge1xuICAgICAgcmVuZGVyVmFsdWU6IGZ1bmN0aW9uKHgpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBwbG90ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgcGxvdC5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICAgICAgb3B0aW9ucyA9IHgub3B0aW9ucztcbiAgICAgICAgb3B0aW9ucy53aWR0aCA9IHdpZHRoO1xuICAgICAgICBvcHRpb25zLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgZGF0YSA9IHguZGF0YTtcbiAgICAgICAgaWYgKHguc3RhY2tlZCkge1xuICAgICAgICAgIGlmICghb3B0aW9ucy5ob29rcylcbiAgICAgICAgICAgIG9wdGlvbnMuaG9va3MgPSB7fTtcbiAgICAgICAgICBvcHRpb25zLmhvb2tzLmluaXQgPSBbXG4gICAgICAgICAgICB1ID0+IHtcbiAgICAgICAgICAgICAgWy4uLnUucm9vdC5xdWVyeVNlbGVjdG9yQWxsKFwiLnUtbGVnZW5kIC51LXNlcmllc1wiKV0uZm9yRWFjaChcbiAgICAgICAgICAgICAgICAoZWwsIGkpID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICh1LnNlcmllc1tpXS5faGlkZSkge1xuICAgICAgICAgICAgICAgICAgICBlbC5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIF07XG4gICAgICAgICAgcGxvdCA9IHN0YWNrZWRDaGFydChcbiAgICAgICAgICAgIG9wdGlvbnMudGl0bGUsXG4gICAgICAgICAgICBvcHRpb25zLnNlcmllcyxcbiAgICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgd2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQsXG4gICAgICAgICAgICBvcHRpb25zLmhvb2tzLFxuICAgICAgICAgICAgcmVzaXplcihlbClcbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBsb3QgPSBuZXcgdVBsb3Qob3B0aW9ucywgZGF0YSwgcmVzaXplcihlbCkpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgZ2V0V2lkZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHBsb3Q7XG4gICAgICB9LFxuICAgICAgcmVzaXplOiBmdW5jdGlvbih3aWR0aCwgaGVpZ2h0KSB7fVxuICAgIH07XG4gIH1cbn0pO1xuXG5pZiAoSFRNTFdpZGdldHMuc2hpbnlNb2RlKSB7XG4gIFNoaW55LmFkZEN1c3RvbU1lc3NhZ2VIYW5kbGVyKFwidXBsb3QtYXBpXCIsIGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciBwbG90ID0gdXRpbHMuZ2V0V2lkZ2V0KG9iai5pZCk7XG4gICAgaWYgKHR5cGVvZiBwbG90ICE9IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgIHBsb3Rbb2JqLm5hbWVdLmFwcGx5KG51bGwsIG9iai5hcmdzKTtcbiAgICB9XG4gIH0pO1xuICBTaGlueS5hZGRDdXN0b21NZXNzYWdlSGFuZGxlcihcInVwbG90LXNldERhdGFcIiwgZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIHBsb3QgPSB1dGlscy5nZXRXaWRnZXQob2JqLmlkKTtcbiAgICBpZiAodHlwZW9mIHBsb3QgIT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgcGxvdC5zZXREYXRhKG9iai5kYXRhKTtcbiAgICB9XG4gIH0pO1xufVxuXG5leHBvcnQgeyB1UGxvdCwgZHJhd1BvaW50cyB9O1xuXG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file +(()=>{"use strict";var e={350:(e,t,l)=>{l.d(t,{Z:()=>s});var n=l(81),o=l.n(n),i=l(645),r=l.n(i)()(o());r.push([e.id,'.uplot, .uplot *, .uplot *::before, .uplot *::after {box-sizing: border-box;}.uplot {font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";line-height: 1.5;width: min-content;}.u-title {text-align: center;font-size: 18px;font-weight: bold;}.u-wrap {position: relative;user-select: none;}.u-over, .u-under {position: absolute;}.u-under {overflow: hidden;}.uplot canvas {display: block;position: relative;width: 100%;height: 100%;}.u-axis {position: absolute;}.u-legend {font-size: 14px;margin: auto;text-align: center;}.u-inline {display: block;}.u-inline * {display: inline-block;}.u-inline tr {margin-right: 16px;}.u-legend th {font-weight: 600;}.u-legend th > * {vertical-align: middle;display: inline-block;}.u-legend .u-marker {width: 1em;height: 1em;margin-right: 4px;background-clip: padding-box !important;}.u-inline.u-live th::after {content: ":";vertical-align: middle;}.u-inline:not(.u-live) .u-value {display: none;}.u-series > * {padding: 4px;}.u-series th {cursor: pointer;}.u-legend .u-off > * {opacity: 0.3;}.u-select {background: rgba(0,0,0,0.07);position: absolute;pointer-events: none;}.u-cursor-x, .u-cursor-y {position: absolute;left: 0;top: 0;pointer-events: none;will-change: transform;}.u-hz .u-cursor-x, .u-vt .u-cursor-y {height: 100%;border-right: 1px dashed #607D8B;}.u-hz .u-cursor-y, .u-vt .u-cursor-x {width: 100%;border-bottom: 1px dashed #607D8B;}.u-cursor-pt {position: absolute;top: 0;left: 0;border-radius: 50%;border: 0 solid;pointer-events: none;will-change: transform;/*this has to be !important since we set inline "background" shorthand */background-clip: padding-box !important;}.u-axis.u-off, .u-select.u-off, .u-cursor-x.u-off, .u-cursor-y.u-off, .u-cursor-pt.u-off {display: none;}',""]);const s=r},645:e=>{e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var l="",n=void 0!==t[5];return t[4]&&(l+="@supports (".concat(t[4],") {")),t[2]&&(l+="@media ".concat(t[2]," {")),n&&(l+="@layer".concat(t[5].length>0?" ".concat(t[5]):""," {")),l+=e(t),n&&(l+="}"),t[2]&&(l+="}"),t[4]&&(l+="}"),l})).join("")},t.i=function(e,l,n,o,i){"string"==typeof e&&(e=[[null,e,void 0]]);var r={};if(n)for(var s=0;s0?" ".concat(c[5]):""," {").concat(c[1],"}")),c[5]=i),l&&(c[2]?(c[1]="@media ".concat(c[2]," {").concat(c[1],"}"),c[2]=l):c[2]=l),o&&(c[4]?(c[1]="@supports (".concat(c[4],") {").concat(c[1],"}"),c[4]=o):c[4]="".concat(o)),t.push(c))}},t}},81:e=>{e.exports=function(e){return e[1]}},379:e=>{var t=[];function l(e){for(var l=-1,n=0;n{var t={};e.exports=function(e,l){var n=function(e){if(void 0===t[e]){var l=document.querySelector(e);if(window.HTMLIFrameElement&&l instanceof window.HTMLIFrameElement)try{l=l.contentDocument.head}catch(e){l=null}t[e]=l}return t[e]}(e);if(!n)throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");n.appendChild(l)}},216:e=>{e.exports=function(e){var t=document.createElement("style");return e.setAttributes(t,e.attributes),e.insert(t,e.options),t}},565:(e,t,l)=>{e.exports=function(e){var t=l.nc;t&&e.setAttribute("nonce",t)}},795:e=>{e.exports=function(e){var t=e.insertStyleElement(e);return{update:function(l){!function(e,t,l){var n="";l.supports&&(n+="@supports (".concat(l.supports,") {")),l.media&&(n+="@media ".concat(l.media," {"));var o=void 0!==l.layer;o&&(n+="@layer".concat(l.layer.length>0?" ".concat(l.layer):""," {")),n+=l.css,o&&(n+="}"),l.media&&(n+="}"),l.supports&&(n+="}");var i=l.sourceMap;i&&"undefined"!=typeof btoa&&(n+="\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(i))))," */")),t.styleTagTransform(n,e,t.options)}(t,e,l)},remove:function(){!function(e){if(null===e.parentNode)return!1;e.parentNode.removeChild(e)}(t)}}}},589:e=>{e.exports=function(e,t){if(t.styleSheet)t.styleSheet.cssText=e;else{for(;t.firstChild;)t.removeChild(t.firstChild);t.appendChild(document.createTextNode(e))}}}},t={};function l(n){var o=t[n];if(void 0!==o)return o.exports;var i=t[n]={id:n,exports:{}};return e[n](i,i.exports,l),i.exports}l.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return l.d(t,{a:t}),t},l.d=(e,t)=>{for(var n in t)l.o(t,n)&&!l.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},l.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),l.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.nc=void 0;var n={};(()=>{l.r(n),l.d(n,{drawPoints:()=>hn,uPlot:()=>ql}),window.HTMLWidgets;const e="u-off",t="u-label",o="width",i="height",r="top",s="bottom",u="left",a="right",c="#000",f="#0000",d="mousemove",h="mousedown",p="mouseup",m="mouseenter",g="mouseleave",x="dblclick",w="change",v="dppxchange",b="--",y="undefined"!=typeof window,k=y?document:null,_=y?window:null,M=y?navigator:null;let S,E;function T(e,t){if(null!=t){let l=e.classList;!l.contains(t)&&l.add(t)}}function z(e,t){let l=e.classList;l.contains(t)&&l.remove(t)}function P(e,t,l){e.style[t]=l+"px"}function D(e,t,l,n){let o=k.createElement(e);return null!=t&&T(o,t),null!=l&&l.insertBefore(o,n),o}function A(e,t){return D("div",e,t)}const C=new WeakMap;function W(t,l,n,o,i){let r="translate("+l+"px,"+n+"px)";r!=C.get(t)&&(t.style.transform=r,C.set(t,r),l<0||n<0||l>o||n>i?T(t,e):z(t,e))}const H=new WeakMap;function I(e,t,l){let n=t+l;n!=H.get(e)&&(H.set(e,n),e.style.background=t,e.style.borderColor=l)}const Y=new WeakMap;function R(e,t,l,n){let o=t+""+l;o!=Y.get(e)&&(Y.set(e,o),e.style.height=l+"px",e.style.width=t+"px",e.style.marginLeft=n?-t/2+"px":0,e.style.marginTop=n?-l/2+"px":0)}const O={passive:!0},j={...O,capture:!0};function L(e,t,l,n){t.addEventListener(e,l,n?j:O)}function F(e,t,l,n){t.removeEventListener(e,l,n?j:O)}function N(e,t,l,n){let o;l=l||0;let i=(n=n||t.length-1)<=2147483647;for(;n-l>1;)o=i?l+n>>1:ne((l+n)/2),t[o]=t&&o<=l;o+=n)if(null!=e[o])return o;return-1}function U(e,t,l,n){let o=ae(e),i=ae(t),r=10==l?ce:fe;e==t&&(-1==o?(e*=l,t/=l):(e/=l,t*=l));let s=1==i?ie:ne,u=(1==o?ne:ie)(r(le(e))),a=s(r(le(t))),c=ue(l,u),f=ue(l,a);return 10==l&&(u<0&&(c=Ee(c,-u)),a<0&&(f=Ee(f,-a))),n||2==l?(e=c*o,t=f*i):(e=Se(e,c),t=Me(t,f)),[e,t]}function B(e,t,l,n){let o=U(e,t,l,n);return 0==e&&(o[0]=0),0==t&&(o[1]=0),o}y&&function e(){let t=devicePixelRatio;S!=t&&(S=t,E&&F(w,E,e),E=matchMedia(`(min-resolution: ${S-.001}dppx) and (max-resolution: ${S+.001}dppx)`),L(w,E,e),_.dispatchEvent(new CustomEvent(v)))}();const V={mode:3,pad:.1},Z={pad:0,soft:null,mode:0},q={min:Z,max:Z};function J(e,t,l,n){return Ye(l)?X(e,t,l):(Z.pad=l,Z.soft=n?0:null,Z.mode=n?3:0,X(e,t,q))}function K(e,t){return null==e?t:e}function X(e,t,l){let n=l.min,o=l.max,i=K(n.pad,0),r=K(o.pad,0),s=K(n.hard,-he),u=K(o.hard,he),a=K(n.soft,he),c=K(o.soft,-he),f=K(n.mode,0),d=K(o.mode,0),h=t-e,p=ce(h),m=se(le(e),le(t)),g=ce(m),x=le(g-p);(h<1e-9||x>10)&&(h=0,0!=e&&0!=t||(h=1e-9,2==f&&a!=he&&(i=0),2==d&&c!=-he&&(r=0)));let w=h||m||1e3,v=ce(w),b=ue(10,ne(v)),y=Ee(Se(e-w*(0==h?0==e?.1:1:i),b/10),9),k=e>=a&&(1==f||3==f&&y<=a||2==f&&y>=a)?a:he,_=se(s,y=k?k:re(k,y)),M=Ee(Me(t+w*(0==h?0==t?.1:1:r),b/10),9),S=t<=c&&(1==d||3==d&&M>=c||2==d&&M<=c)?c:-he,E=re(u,M>S&&t<=S?S:se(S,M));return _==E&&0==_&&(E=100),[_,E]}const $=new Intl.NumberFormat(y?M.language:"en-US"),Q=e=>$.format(e),ee=Math,te=ee.PI,le=ee.abs,ne=ee.floor,oe=ee.round,ie=ee.ceil,re=ee.min,se=ee.max,ue=ee.pow,ae=ee.sign,ce=ee.log10,fe=ee.log2,de=(e,t=1)=>ee.asinh(e/t),he=1/0;function pe(e){return 1+(0|ce((e^e>>31)-(e>>31)))}function me(e,t,l){return re(se(e,t),l)}function ge(e){return"function"==typeof e?e:()=>e}const xe=e=>e,we=(e,t)=>t,ve=e=>null,be=e=>!0,ye=(e,t)=>e==t,ke=e=>Ee(e,14);function _e(e,t){return ke(Ee(ke(e/t))*t)}function Me(e,t){return ke(ie(ke(e/t))*t)}function Se(e,t){return ke(ne(ke(e/t))*t)}function Ee(e,t=0){if(He(e))return e;let l=10**t,n=e*l*(1+Number.EPSILON);return oe(n)/l}const Te=new Map;function ze(e){return((""+e).split(".")[1]||"").length}function Pe(e,t,l,n){let o=[],i=n.map(ze);for(let r=t;r=0&&r>=0?0:t)+(r>=i[e]?0:i[e]),a=Ee(s,u);o.push(a),Te.set(a,u)}}return o}const De={},Ae=[],Ce=[null,null],We=Array.isArray,He=Number.isInteger;function Ie(e){return"string"==typeof e}function Ye(e){let t=!1;if(null!=e){let l=e.constructor;t=null==l||l==Object}return t}function Re(e){return null!=e&&"object"==typeof e}const Oe=Object.getPrototypeOf(Uint8Array);function je(e,t=Ye){let l;if(We(e)){let n=e.find((e=>null!=e));if(We(n)||t(n)){l=Array(e.length);for(let n=0;ni){for(n=r-1;n>=0&&null==e[n];)e[n--]=null;for(n=r+1;nPromise.resolve().then(e):queueMicrotask,Ge=["January","February","March","April","May","June","July","August","September","October","November","December"],Ue=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];function Be(e){return e.slice(0,3)}const Ve=Ue.map(Be),Ze=Ge.map(Be),qe={MMMM:Ge,MMM:Ze,WWWW:Ue,WWW:Ve};function Je(e){return(e<10?"0":"")+e}const Ke={YYYY:e=>e.getFullYear(),YY:e=>(e.getFullYear()+"").slice(2),MMMM:(e,t)=>t.MMMM[e.getMonth()],MMM:(e,t)=>t.MMM[e.getMonth()],MM:e=>Je(e.getMonth()+1),M:e=>e.getMonth()+1,DD:e=>Je(e.getDate()),D:e=>e.getDate(),WWWW:(e,t)=>t.WWWW[e.getDay()],WWW:(e,t)=>t.WWW[e.getDay()],HH:e=>Je(e.getHours()),H:e=>e.getHours(),h:e=>{let t=e.getHours();return 0==t?12:t>12?t-12:t},AA:e=>e.getHours()>=12?"PM":"AM",aa:e=>e.getHours()>=12?"pm":"am",a:e=>e.getHours()>=12?"p":"a",mm:e=>Je(e.getMinutes()),m:e=>e.getMinutes(),ss:e=>Je(e.getSeconds()),s:e=>e.getSeconds(),fff:e=>{return((t=e.getMilliseconds())<10?"00":t<100?"0":"")+t;var t}};function Xe(e,t){t=t||qe;let l,n=[],o=/\{([a-z]+)\}|[^{]+/gi;for(;l=o.exec(e);)n.push("{"==l[0][0]?Ke[l[1]]:l[0]);return e=>{let l="";for(let o=0;oe%1==0,et=[1,2,2.5,5],tt=Pe(10,-16,0,et),lt=Pe(10,0,16,et),nt=lt.filter(Qe),ot=tt.concat(lt),it="{YYYY}",rt="\n"+it,st="{M}/{D}",ut="\n"+st,at=ut+"/{YY}",ct="{aa}",ft="{h}:{mm}"+ct,dt="\n"+ft,ht=":{ss}",pt=null;function mt(e){let t=1e3*e,l=60*t,n=60*l,o=24*n,i=30*o,r=365*o;return[(1==e?Pe(10,0,3,et).filter(Qe):Pe(10,-3,0,et)).concat([t,5*t,10*t,15*t,30*t,l,5*l,10*l,15*l,30*l,n,2*n,3*n,4*n,6*n,8*n,12*n,o,2*o,3*o,4*o,5*o,6*o,7*o,8*o,9*o,10*o,15*o,i,2*i,3*i,4*i,6*i,r,2*r,5*r,10*r,25*r,50*r,100*r]),[[r,it,pt,pt,pt,pt,pt,pt,1],[28*o,"{MMM}",rt,pt,pt,pt,pt,pt,1],[o,st,rt,pt,pt,pt,pt,pt,1],[n,"{h}"+ct,at,pt,ut,pt,pt,pt,1],[l,ft,at,pt,ut,pt,pt,pt,1],[t,ht,at+" "+ft,pt,ut+" "+ft,pt,dt,pt,1],[e,ht+".{fff}",at+" "+ft,pt,ut+" "+ft,pt,dt,pt,1]],function(t){return(s,u,a,c,f,d)=>{let h=[],p=f>=r,m=f>=i&&f=o?o:f,r=v+(ne(a)-ne(x))+Me(x-v,i);h.push(r);let p=t(r),m=p.getHours()+p.getMinutes()/l+p.getSeconds()/n,g=f/n,w=d/s.axes[u]._space;for(;r=Ee(r+f,1==e?0:3),!(r>c);)if(g>1){let e=ne(Ee(m+g,6))%24,l=t(r).getHours()-e;l>1&&(l=-1),r-=l*n,m=(m+g)%24,Ee((r-h[h.length-1])/f,3)*w>=.7&&h.push(r)}else h.push(r)}return h}}]}const[gt,xt,wt]=mt(1),[vt,bt,yt]=mt(.001);function kt(e,t){return e.map((e=>e.map(((l,n)=>0==n||8==n||null==l?l:t(1==n||0==e[8]?l:e[1]+l)))))}function _t(e,t){return(l,n,o,i,r)=>{let s,u,a,c,f,d,h=t.find((e=>r>=e[0]))||t[t.length-1];return n.map((t=>{let l=e(t),n=l.getFullYear(),o=l.getMonth(),i=l.getDate(),r=l.getHours(),p=l.getMinutes(),m=l.getSeconds(),g=n!=s&&h[2]||o!=u&&h[3]||i!=a&&h[4]||r!=c&&h[5]||p!=f&&h[6]||m!=d&&h[7]||h[1];return s=n,u=o,a=i,c=r,f=p,d=m,g(l)}))}}function Mt(e,t,l){return new Date(e,t,l)}function St(e,t){return t(e)}function Et(e,t){return(l,n,o,i)=>null==i?b:t(e(n))}Pe(2,-53,53,[1]);const Tt={show:!0,live:!0,isolate:!1,mount:()=>{},markers:{show:!0,width:2,stroke:function(e,t){let l=e.series[t];return l.width?l.stroke(e,t):l.points.width?l.points.stroke(e,t):null},fill:function(e,t){return e.series[t].fill(e,t)},dash:"solid"},idx:null,idxs:null,values:[]},zt=[0,0];function Pt(e,t,l,n=!0){return e=>{0==e.button&&(!n||e.target==t)&&l(e)}}function Dt(e,t,l,n=!0){return e=>{(!n||e.target==t)&&l(e)}}const At={show:!0,x:!0,y:!0,lock:!1,move:function(e,t,l){return zt[0]=t,zt[1]=l,zt},points:{show:function(e,t){let l=e.cursor.points,n=A(),r=l.size(e,t);P(n,o,r),P(n,i,r);let s=r/-2;P(n,"marginLeft",s),P(n,"marginTop",s);let u=l.width(e,t,r);return u&&P(n,"borderWidth",u),n},size:function(e,t){return e.series[t].points.size},width:0,stroke:function(e,t){let l=e.series[t].points;return l._stroke||l._fill},fill:function(e,t){let l=e.series[t].points;return l._fill||l._stroke}},bind:{mousedown:Pt,mouseup:Pt,click:Pt,dblclick:Pt,mousemove:Dt,mouseleave:Dt,mouseenter:Dt},drag:{setScale:!0,x:!0,y:!1,dist:0,uni:null,click:(e,t)=>{t.stopPropagation(),t.stopImmediatePropagation()},_x:!1,_y:!1},focus:{prox:-1,bias:0},left:-10,top:-10,idx:null,dataIdx:function(e,t,l){return l},idxs:null,event:null},Ct={show:!0,stroke:"rgba(0,0,0,0.07)",width:2},Wt=Le({},Ct,{filter:we}),Ht=Le({},Wt,{size:10}),It=Le({},Ct,{show:!1}),Yt='12px system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"',Rt="bold "+Yt,Ot={show:!0,scale:"x",stroke:c,space:50,gap:5,size:50,labelGap:0,labelSize:30,labelFont:Rt,side:2,grid:Wt,ticks:Ht,border:It,font:Yt,lineGap:1.5,rotate:0},jt={show:!0,scale:"x",auto:!1,sorted:1,min:he,max:-he,idxs:[]};function Lt(e,t,l,n,o){return t.map((e=>null==e?"":Q(e)))}function Ft(e,t,l,n,o,i,r){let s=[],u=Te.get(o)||0;for(let e=l=r?l:Ee(Me(l,o),u);e<=n;e=Ee(e+o,u))s.push(Object.is(e,-0)?0:e);return s}function Nt(e,t,l,n,o,i,r){const s=[],u=e.scales[e.axes[t].scale].log,a=ne((10==u?ce:fe)(l));o=ue(u,a),10==u&&a<0&&(o=Ee(o,-a));let c=l;do{s.push(c),c+=o,10==u&&(c=Ee(c,Te.get(o))),c>=o*u&&(o=c)}while(c<=n);return s}function Gt(e,t,l,n,o,i,r){let s=e.scales[e.axes[t].scale].asinh,u=n>s?Nt(e,t,se(s,l),n,o):[s],a=n>=0&&l<=0?[0]:[];return(l<-s?Nt(e,t,se(s,-n),-l,o):[s]).reverse().map((e=>-e)).concat(a,u)}const Ut=/./,Bt=/[12357]/,Vt=/[125]/,Zt=/1/,qt=(e,t,l,n)=>e.map(((e,o)=>4==t&&0==e||o%n==0&&l.test(e.toExponential()[e<0?1:0])?e:null));function Jt(e,t,l,n,o){let i=e.axes[l],r=i.scale,s=e.scales[r],u=e.valToPos,a=i._space,c=u(10,r),f=u(9,r)-c>=a?Ut:u(7,r)-c>=a?Bt:u(5,r)-c>=a?Vt:Zt;if(f==Zt){let e=le(u(1,r)-c);if(eo,tl={show:!0,auto:!0,sorted:0,gaps:el,alpha:1,facets:[Le({},Qt,{scale:"x"}),Le({},Qt,{scale:"y"})]},ll={scale:"y",auto:!0,sorted:0,show:!0,spanGaps:!1,gaps:el,alpha:1,points:{show:function(e,t){let{scale:l,idxs:n}=e.series[0],o=e._data[0],i=e.valToPos(o[n[0]],l,!0),r=e.valToPos(o[n[1]],l,!0),s=le(r-i)/(e.series[t].points.space*S);return n[1]-n[0]<=s},filter:null},values:null,min:he,max:-he,idxs:[],path:null,clip:null};function nl(e,t,l,n,o){return l/10}const ol={time:!0,auto:!0,distr:1,log:10,asinh:1,min:null,max:null,dir:1,ori:0},il=Le({},ol,{time:!1,ori:1}),rl={};function sl(e,t){let l=rl[e];return l||(l={key:e,plots:[],sub(e){l.plots.push(e)},unsub(e){l.plots=l.plots.filter((t=>t!=e))},pub(e,t,n,o,i,r,s){for(let u=0;u{let m=e.pxRound;const g=s.dir*(0==s.ori?1:-1),x=0==s.ori?wl:vl;let w,v;1==g?(w=l,v=n):(w=n,v=l);let b=m(a(t[w],s,h,f)),y=m(c(r[w],u,p,d)),k=m(a(t[v],s,h,f)),_=m(c(1==i?u.max:u.min,u,p,d)),M=new Path2D(o);return x(M,k,_),x(M,b,_),x(M,b,y),M}))}function dl(e,t,l,n,o,i){let r=null;if(e.length>0){r=new Path2D;const s=0==t?bl:yl;let u=l;for(let t=0;tl[0]){let e=l[0]-u;e>0&&s(r,u,n,e,n+i),u=l[1]}}let a=l+o-u,c=10;a>0&&s(r,u,n-c/2,a,n+i+c)}return r}function hl(e,t,l,n,o,i,r){let s=[],u=e.length;for(let a=1==o?l:n;a>=l&&a<=n;a+=o)if(null===t[a]){let c=a,f=a;if(1==o)for(;++a<=n&&null===t[a];)f=a;else for(;--a>=l&&null===t[a];)f=a;let d=i(e[c]),h=f==c?d:i(e[f]),p=c-o;d=r<=0&&p>=0&&p=0&&m>=0&&m=d&&s.push([d,h])}return s}function pl(e){return 0==e?xe:1==e?oe:t=>_e(t,e)}function ml(e){let t=0==e?gl:xl,l=0==e?(e,t,l,n,o,i)=>{e.arcTo(t,l,n,o,i)}:(e,t,l,n,o,i)=>{e.arcTo(l,t,o,n,i)},n=0==e?(e,t,l,n,o)=>{e.rect(t,l,n,o)}:(e,t,l,n,o)=>{e.rect(l,t,o,n)};return(e,o,i,r,s,u=0,a=0)=>{0==u&&0==a?n(e,o,i,r,s):(u=re(u,r/2,s/2),a=re(a,r/2,s/2),t(e,o+u,i),l(e,o+r,i,o+r,i+s,u),l(e,o+r,i+s,o,i+s,a),l(e,o,i+s,o,i,a),l(e,o,i,o+r,i,u),e.closePath())}}const gl=(e,t,l)=>{e.moveTo(t,l)},xl=(e,t,l)=>{e.moveTo(l,t)},wl=(e,t,l)=>{e.lineTo(t,l)},vl=(e,t,l)=>{e.lineTo(l,t)},bl=ml(0),yl=ml(1),kl=(e,t,l,n,o,i)=>{e.arc(t,l,n,o,i)},_l=(e,t,l,n,o,i)=>{e.arc(l,t,n,o,i)},Ml=(e,t,l,n,o,i,r)=>{e.bezierCurveTo(t,l,n,o,i,r)},Sl=(e,t,l,n,o,i,r)=>{e.bezierCurveTo(l,t,o,n,r,i)};function El(e){return(e,t,l,n,o)=>ul(e,t,((t,i,r,s,u,a,c,f,d,h,p)=>{let m,g,{pxRound:x,points:w}=t;0==s.ori?(m=gl,g=kl):(m=xl,g=_l);const v=Ee(w.width*S,3);let b=(w.size-w.width)/2*S,y=Ee(2*b,3),k=new Path2D,_=new Path2D,{left:M,top:E,width:T,height:z}=e.bbox;bl(_,M-y,E-y,T+2*y,z+2*y);const P=e=>{if(null!=r[e]){let t=x(a(i[e],s,h,f)),l=x(c(r[e],u,p,d));m(k,t+b,l),g(k,t,l,b,0,2*te)}};if(o)o.forEach(P);else for(let e=l;e<=n;e++)P(e);return{stroke:v>0?k:null,fill:k,clip:_,flags:3}}))}function Tl(e){return(t,l,n,o,i,r)=>{n!=o&&(i!=n&&r!=n&&e(t,l,n),i!=o&&r!=o&&e(t,l,o),e(t,l,r))}}const zl=Tl(wl),Pl=Tl(vl);function Dl(e){const t=K(e?.alignGaps,0);return(e,l,n,o)=>ul(e,l,((i,r,s,u,a,c,f,d,h,p,m)=>{let g,x,w=i.pxRound,v=e=>w(c(e,u,p,d)),b=e=>w(f(e,a,m,h));0==u.ori?(g=wl,x=zl):(g=vl,x=Pl);const y=u.dir*(0==u.ori?1:-1),k={stroke:new Path2D,fill:null,clip:null,band:null,gaps:null,flags:1},_=k.stroke;let M,S,E,T=he,z=-he,P=v(r[1==y?n:o]),D=G(s,n,o,1*y),A=G(s,n,o,-1*y),C=v(r[D]),W=v(r[A]),H=!1;for(let e=1==y?n:o;e>=n&&e<=o;e+=y){let t=v(r[e]),l=s[e];t==P?null!=l?(S=b(l),T==he&&(g(_,t,S),M=S),T=re(S,T),z=se(S,z)):null===l&&(H=!0):(T!=he&&(x(_,P,T,z,M,S),E=P),null!=l?(S=b(l),g(_,t,S),T=z=M=S):(T=he,z=-he,null===l&&(H=!0)),P=t)}T!=he&&T!=z&&E!=P&&x(_,P,T,z,M,S);let[I,Y]=al(e,l);if(null!=i.fill||0!=I){let t=k.fill=new Path2D(_),n=b(i.fillTo(e,l,i.min,i.max,I));g(t,W,n),g(t,C,n)}if(!i.spanGaps){let a=[];H&&a.push(...hl(r,s,n,o,y,v,t)),k.gaps=a=i.gaps(e,l,n,o,a),k.clip=dl(a,u.ori,d,h,p,m)}return 0!=Y&&(k.band=2==Y?[fl(e,l,n,o,_,-1),fl(e,l,n,o,_,1)]:fl(e,l,n,o,_,Y)),k}))}function Al(e,t,l,n,o,i){const r=e.length;if(r<2)return null;const s=new Path2D;if(l(s,e[0],t[0]),2==r)n(s,e[1],t[1]);else{let l=Array(r),n=Array(r-1),i=Array(r-1),u=Array(r-1);for(let l=0;l0!=n[e]>0?l[e]=0:(l[e]=3*(u[e-1]+u[e])/((2*u[e]+u[e-1])/n[e-1]+(u[e]+2*u[e-1])/n[e]),isFinite(l[e])||(l[e]=0));l[r-1]=n[r-2];for(let n=0;n{ql.pxRatio=S})));const Hl=Dl(),Il=El();function Yl(e,t,l,n){return(n?[e[0],e[1]].concat(e.slice(2)):[e[0]].concat(e.slice(1))).map(((e,n)=>Rl(e,n,t,l)))}function Rl(e,t,l,n){return Le({},0==t?l:n,e)}function Ol(e,t,l){return null==t?Ce:[t,l]}const jl=Ol;function Ll(e,t,l){return null==t?Ce:J(t,l,.1,!0)}function Fl(e,t,l,n){return null==t?Ce:U(t,l,e.scales[n].log,!1)}const Nl=Fl;function Gl(e,t,l,n){return null==t?Ce:B(t,l,e.scales[n].log,!1)}const Ul=Gl;function Bl(e,t,l,n,o){let i=se(pe(e),pe(t)),r=t-e,s=N(o/n*r,l);do{let e=l[s],t=n*e/r;if(t>=o&&i+(e<5?Te.get(e):0)<=17)return[e,t]}while(++s(t=oe((l=+n)*S))+"px")),t,l]}function Zl(e){e.show&&[e.font,e.labelFont].forEach((e=>{let t=Ee(e[2]*S,1);e[0]=e[0].replace(/[0-9.]+px/,t+"px"),e[1]=t}))}function ql(l,n,c){const w={mode:K(l.mode,1)},y=w.mode;function M(e,t){return((3==t.distr?ce(e>0?e:t.clamp(w,e,t.min,t.max,t.key)):4==t.distr?de(e,t.asinh):e)-t._min)/(t._max-t._min)}function E(e,t,l,n){let o=M(e,t);return n+l*(-1==t.dir?1-o:o)}function C(e,t,l,n){let o=M(e,t);return n+l*(-1==t.dir?o:1-o)}function H(e,t,l,n){return 0==t.ori?E(e,t,l,n):C(e,t,l,n)}w.valToPosH=E,w.valToPosV=C;let Y=!1;w.status=0;const O=w.root=A("uplot");null!=l.id&&(O.id=l.id),T(O,l.class),l.title&&(A("u-title",O).textContent=l.title);const j=D("canvas"),G=w.ctx=j.getContext("2d"),Z=A("u-wrap",O);L("click",Z,(e=>{e.target===X&&(Tn!=_n||zn!=Mn)&&Hn.click(w,e)}),!0);const q=w.under=A("u-under",Z);Z.appendChild(j);const X=w.over=A("u-over",Z),$=+K((l=je(l)).pxAlign,1),Q=pl($);(l.plugins||[]).forEach((e=>{e.opts&&(l=e.opts(w,l)||l)}));const ne=l.ms||.001,ae=w.series=1==y?Yl(l.series||[],jt,ll,!1):(fe=l.series||[null],pe=tl,fe.map(((e,t)=>0==t?null:Le({},pe,e))));var fe,pe;const xe=w.axes=Yl(l.axes||[],Ot,$t,!0),ke=w.scales={},Se=w.bands=l.bands||[];Se.forEach((e=>{e.fill=ge(e.fill||null),e.dir=K(e.dir,-1)}));const Pe=2==y?ae[1].facets[0].scale:ae[0].scale,He={axes:function(){for(let e=0;een[e])):v,y=2==p.distr?en[v[1]]-en[v[0]]:d,k=t.ticks,_=t.border,M=k.show?oe(k.size*S):0,E=t._rotate*-te/180,T=Q(t._pos*S),z=T+(M+x)*f;n=0==i?z:0,l=1==i?z:0,rn(t.font[0],c,1==t.align?u:2==t.align?a:E>0?u:E<0?a:0==i?"center":3==o?a:u,E||1==i?"middle":2==o?r:s);let P=t.font[1]*t.lineGap,D=v.map((e=>Q(H(e,p,m,g)))),A=t._values;for(let e=0;e0&&(ae.forEach(((e,t)=>{if(t>0&&e.show&&null==e._paths){let l=2==y?[0,n[t][0].length-1]:function(e){let t=me(El-1,0,Sl-1),l=me(Tl+1,0,Sl-1);for(;null==e[t]&&t>0;)t--;for(;null==e[l]&&l{if(t>0&&e.show){Ql!=e.alpha&&(G.globalAlpha=Ql=e.alpha),un(t,!1),e._paths&&an(t,!1);{un(t,!0);let l=e._paths?e._paths.gaps:null,n=e.points.show(w,t,El,Tl,l),o=e.points.filter(w,t,n,l);(n||o)&&(e.points._paths=e.points.paths(w,t,El,Tl,o),an(t,!0))}1!=Ql&&(G.globalAlpha=Ql=1),xo("drawSeries",t)}})))}},Oe=(l.drawOrder||["axes","series"]).map((e=>He[e]));function Fe(e){let t=ke[e];if(null==t){let n=(l.scales||De)[e]||De;if(null!=n.from)Fe(n.from),ke[e]=Le({},ke[n.from],n,{key:e});else{t=ke[e]=Le({},e==Pe?ol:il,n),t.key=e;let l=t.time,o=t.range,i=We(o);if((e!=Pe||2==y&&!l)&&(!i||null!=o[0]&&null!=o[1]||(o={min:null==o[0]?V:{mode:1,hard:o[0],soft:o[0]},max:null==o[1]?V:{mode:1,hard:o[1],soft:o[1]}},i=!1),!i&&Ye(o))){let e=o;o=(t,l,n)=>null==l?Ce:J(l,n,e)}t.range=ge(o||(l?jl:e==Pe?3==t.distr?Nl:4==t.distr?Ul:Ol:3==t.distr?Fl:4==t.distr?Gl:Ll)),t.auto=ge(!i&&t.auto),t.clamp=ge(t.clamp||nl),t._min=t._max=null}}}Fe("x"),Fe("y"),1==y&&ae.forEach((e=>{Fe(e.scale)})),xe.forEach((e=>{Fe(e.scale)}));for(let e in l.scales)Fe(e);const Ge=ke[Pe],Ue=Ge.distr;let Be,Ve;0==Ge.ori?(T(O,"u-hz"),Be=E,Ve=C):(T(O,"u-vt"),Be=C,Ve=E);const Ze={};for(let e in ke){let t=ke[e];null==t.min&&null==t.max||(Ze[e]={min:t.min,max:t.max},t.min=t.max=null)}const qe=l.tzDate||(e=>new Date(oe(e/ne))),Je=l.fmtDate||Xe,Ke=1==ne?wt(qe):yt(qe),$e=_t(qe,kt(1==ne?xt:bt,Je)),Qe=Et(qe,St("{YYYY}-{MM}-{DD} {h}:{mm}{aa}",Je)),et=[],tt=w.legend=Le({},Tt,l.legend),lt=tt.show,it=tt.markers;let rt,st,ut;tt.idxs=et,it.width=ge(it.width),it.dash=ge(it.dash),it.stroke=ge(it.stroke),it.fill=ge(it.fill);let at,ct=[],ft=[],dt=!1,ht={};if(tt.live){const e=ae[1]?ae[1].values:null;dt=null!=e,at=dt?e(w,1,0):{_:0};for(let e in at)ht[e]=b}if(lt)if(rt=D("table","u-legend",O),ut=D("tbody",null,rt),tt.mount(w,rt),dt){st=D("thead",null,rt,ut);let e=D("tr",null,st);for(var pt in D("th",null,e),at)D("th",t,e).textContent=pt}else T(rt,"u-inline"),tt.live&&T(rt,"u-live");const mt={show:!0},Mt={show:!1},zt=new Map;function Pt(e,t,l,n=!0){const o=zt.get(t)||{},i=hl.bind[e](w,t,l,n);i&&(L(e,t,o[e]=i),zt.set(t,o))}function Dt(e,t,l){const n=zt.get(t)||{};for(let l in n)null!=e&&l!=e||(F(l,t,n[l]),delete n[l]);null==e&&zt.delete(t)}let Ct=0,Wt=0,Ht=0,It=0,Yt=0,Rt=0,Ut=0,Bt=0,Vt=0,Zt=0;w.bbox={};let qt=!1,Qt=!1,el=!1,rl=!1,ul=!1,al=!1;function fl(e,t,l){(l||e!=w.width||t!=w.height)&&dl(e,t),gn(!1),el=!0,Qt=!0,hl.left>=0&&(rl=al=!0),Dn()}function dl(e,t){w.width=Ct=Ht=e,w.height=Wt=It=t,Yt=Rt=0,function(){let e=!1,t=!1,l=!1,n=!1;xe.forEach(((o,i)=>{if(o.show&&o._show){let{side:i,_size:r}=o,s=i%2,u=r+(null!=o.label?o.labelSize:0);u>0&&(s?(Ht-=u,3==i?(Yt+=u,n=!0):l=!0):(It-=u,0==i?(Rt+=u,e=!0):t=!0))}})),yl[0]=e,yl[1]=l,yl[2]=t,yl[3]=n,Ht-=Ml[1]+Ml[3],Yt+=Ml[3],It-=Ml[2]+Ml[0],Rt+=Ml[0]}(),function(){let e=Yt+Ht,t=Rt+It,l=Yt,n=Rt;function o(o,i){switch(o){case 1:return e+=i,e-i;case 2:return t+=i,t-i;case 3:return l-=i,l+i;case 0:return n-=i,n+i}}xe.forEach(((e,t)=>{if(e.show&&e._show){let t=e.side;e._pos=o(t,e._size),null!=e.label&&(e._lpos=o(t,e.labelSize))}}))}();let l=w.bbox;Ut=l.left=_e(Yt*S,.5),Bt=l.top=_e(Rt*S,.5),Vt=l.width=_e(Ht*S,.5),Zt=l.height=_e(It*S,.5)}w.setSize=function({width:e,height:t}){fl(e,t)};const hl=w.cursor=Le({},At,{drag:{y:2==y}},l.cursor),ml=e=>{hl.event=e};hl.idxs=et,hl._lock=!1;let gl=hl.points;gl.show=ge(gl.show),gl.size=ge(gl.size),gl.stroke=ge(gl.stroke),gl.width=ge(gl.width),gl.fill=ge(gl.fill);const xl=w.focus=Le({},l.focus||{alpha:.3},hl.focus),wl=xl.prox>=0;let vl=[null];function bl(l,n){if(1==y||n>0){let e=1==y&&ke[l.scale].time,t=l.value;l.value=e?Ie(t)?Et(qe,St(t,Je)):t||Qe:t||Xt,l.label=l.label||(e?"Time":"Value")}if(n>0){l.width=null==l.width?1:l.width,l.paths=l.paths||Hl||ve,l.fillTo=ge(l.fillTo||cl),l.pxAlign=+K(l.pxAlign,$),l.pxRound=pl(l.pxAlign),l.stroke=ge(l.stroke||null),l.fill=ge(l.fill||null),l._stroke=l._fill=l._paths=l._focus=null;let e=Ee(1*(3+2*(se(1,l.width)||1)),3),t=l.points=Le({},{size:e,width:se(1,.2*e),stroke:l.stroke,space:2*e,paths:Il,_stroke:null,_fill:null},l.points);t.show=ge(t.show),t.filter=ge(t.filter),t.fill=ge(t.fill),t.stroke=ge(t.stroke),t.paths=ge(t.paths),t.pxAlign=l.pxAlign}if(lt){let o=function(l,n){if(0==n&&(dt||!tt.live||2==y))return Ce;let o=[],i=D("tr","u-series",ut,ut.childNodes[n]);T(i,l.class),l.show||T(i,e);let r=D("th",null,i);if(it.show){let e=A("u-marker",r);if(n>0){let t=it.width(w,n);t&&(e.style.border=t+"px "+it.dash(w,n)+" "+it.stroke(w,n)),e.style.background=it.fill(w,n)}}let s=A(t,r);for(var u in s.textContent=l.label,n>0&&(it.show||(s.style.color=l.width>0?it.stroke(w,n):it.fill(w,n)),Pt("click",r,(e=>{if(hl._lock)return;ml(e);let t=ae.indexOf(l);if((e.ctrlKey||e.metaKey)!=tt.isolate){let e=ae.some(((e,l)=>l>0&&l!=t&&e.show));ae.forEach(((l,n)=>{n>0&&Fn(n,e?n==t?mt:Mt:mt,!0,vo.setSeries)}))}else Fn(t,{show:!l.show},!0,vo.setSeries)}),!1),wl&&Pt(m,r,(e=>{hl._lock||(ml(e),Fn(ae.indexOf(l),Bn,!0,vo.setSeries))}),!1)),at){let e=D("td","u-value",i);e.textContent="--",o.push(e)}return[i,o]}(l,n);ct.splice(n,0,o[0]),ft.splice(n,0,o[1]),tt.values.push(null)}if(hl.show){et.splice(n,0,null);let e=function(e,t){if(t>0){let l=hl.points.show(w,t);if(l)return T(l,"u-cursor-pt"),T(l,e.class),W(l,-10,-10,Ht,It),X.insertBefore(l,vl[t]),l}}(l,n);e&&vl.splice(n,0,e)}xo("addSeries",n)}w.addSeries=function(e,t){t=null==t?ae.length:t,e=1==y?Rl(e,t,jt,ll):Rl(e,t,null,tl),ae.splice(t,0,e),bl(ae[t],t)},w.delSeries=function(e){if(ae.splice(e,1),lt){tt.values.splice(e,1),ft.splice(e,1);let t=ct.splice(e,1)[0];Dt(null,t.firstChild),t.remove()}hl.show&&(et.splice(e,1),vl.length>1&&vl.splice(e,1)[0].remove()),xo("delSeries",e)};const yl=[!1,!1,!1,!1];function kl(e,t,l,n){let[o,i,r,s]=l,u=t%2,a=0;return 0==u&&(s||i)&&(a=0==t&&!o||2==t&&!r?oe(Ot.size/3):0),1==u&&(o||r)&&(a=1==t&&!i||3==t&&!s?oe($t.size/2):0),a}const _l=w.padding=(l.padding||[kl,kl,kl,kl]).map((e=>ge(K(e,kl)))),Ml=w._padding=_l.map(((e,t)=>e(w,t,yl,0)));let Sl,El=null,Tl=null;const zl=1==y?ae[0].idxs:null;let Pl,Dl,Al,Wl,ql,Jl,Kl,Xl,$l,Ql,en=null,tn=!1;function ln(e,t){if(n=null==e?[]:je(e,Re),2==y){Sl=0;for(let e=1;e=0,al=!0,Dn()}}function nn(){let e,t;tn=!0,1==y&&(Sl>0?(El=zl[0]=0,Tl=zl[1]=Sl-1,e=n[0][El],t=n[0][Tl],2==Ue?(e=El,t=Tl):e==t&&(3==Ue?[e,t]=U(e,e,Ge.log,!1):4==Ue?[e,t]=B(e,e,Ge.log,!1):Ge.time?t=e+oe(86400/ne):[e,t]=J(e,t,.1,!0))):(El=zl[0]=e=null,Tl=zl[1]=t=null)),Ln(Pe,e,t)}function on(e,t,l,n,o,i){e??=f,l??=Ae,n??="butt",o??=f,i??="round",e!=Pl&&(G.strokeStyle=Pl=e),o!=Dl&&(G.fillStyle=Dl=o),t!=Al&&(G.lineWidth=Al=t),i!=ql&&(G.lineJoin=ql=i),n!=Jl&&(G.lineCap=Jl=n),l!=Wl&&G.setLineDash(Wl=l)}function rn(e,t,l,n){t!=Dl&&(G.fillStyle=Dl=t),e!=Kl&&(G.font=Kl=e),l!=Xl&&(G.textAlign=Xl=l),n!=$l&&(G.textBaseline=$l=n)}function sn(e,t,l,n,o=0){if(n.length>0&&e.auto(w,tn)&&(null==t||null==t.min)){let t=K(El,0),i=K(Tl,n.length-1),r=null==l.min?3==e.distr?function(e,t,l){let n=he,o=-he;for(let i=t;i<=l;i++){let t=e[i];null!=t&&t>0&&(to&&(o=t))}return[n==he?1:n,o==-he?10:o]}(n,t,i):function(e,t,l,n){let o=he,i=-he;if(1==n)o=e[t],i=e[l];else if(-1==n)o=e[l],i=e[t];else for(let n=t;n<=l;n++){let t=e[n];null!=t&&(ti&&(i=t))}return[o,i]}(n,t,i,o):[l.min,l.max];e.min=re(e.min,l.min=r[0]),e.max=se(e.max,l.max=r[1])}}function un(e,t){let l=t?ae[e].points:ae[e];l._stroke=l.stroke(w,e),l._fill=l.fill(w,e)}function an(e,t){let l=t?ae[e].points:ae[e],o=l._stroke,i=l._fill,{stroke:r,fill:s,clip:u,flags:a}=l._paths,c=null,f=Ee(l.width*S,3),d=f%2/2;t&&null==i&&(i=f>0?"#fff":o);let h=1==l.pxAlign&&d>0;if(h&&G.translate(d,d),!t){let e=Ut-f/2,t=Bt-f/2,l=Vt+f,n=Zt+f;c=new Path2D,c.rect(e,t,l,n)}t?cn(o,f,l.dash,l.cap,i,r,s,a,u):function(e,t,l,o,i,r,s,u,a,c,f){let d=!1;Se.forEach(((h,p)=>{if(h.series[0]==e){let e,m=ae[h.series[1]],g=n[h.series[1]],x=(m._paths||De).band;We(x)&&(x=1==h.dir?x[0]:x[1]);let v=null;m.show&&x&&function(e,t,l){for(t=K(t,0),l=K(l,e.length-1);t<=l;){if(null!=e[t])return!0;t++}return!1}(g,El,Tl)?(v=h.fill(w,p)||r,e=m._paths.clip):x=null,cn(t,l,o,i,v,s,u,a,c,f,e,x),d=!0}})),d||cn(t,l,o,i,r,s,u,a,c,f)}(e,o,f,l.dash,l.cap,i,r,s,a,c,u),h&&G.translate(-d,-d)}function cn(e,t,l,n,o,i,r,s,u,a,c,f){on(e,t,l,n,o),(u||a||f)&&(G.save(),u&&G.clip(u),a&&G.clip(a)),f?3==(3&s)?(G.clip(f),c&&G.clip(c),dn(o,r),fn(e,i,t)):2&s?(dn(o,r),G.clip(f),fn(e,i,t)):1&s&&(G.save(),G.clip(f),c&&G.clip(c),dn(o,r),G.restore(),fn(e,i,t)):(dn(o,r),fn(e,i,t)),(u||a||f)&&G.restore()}function fn(e,t,l){l>0&&(t instanceof Map?t.forEach(((e,t)=>{G.strokeStyle=Pl=t,G.stroke(e)})):null!=t&&e&&G.stroke(t))}function dn(e,t){t instanceof Map?t.forEach(((e,t)=>{G.fillStyle=Dl=t,G.fill(e)})):null!=t&&e&&G.fill(t)}function hn(e,t,l,n,o,i,r,s,u,a){let c=r%2/2;1==$&&G.translate(c,c),on(s,r,u,a,s),G.beginPath();let f,d,h,p,m=o+(0==n||3==n?-i:i);0==l?(d=o,p=m):(f=o,h=m);for(let n=0;n{if(!l.show)return;let o=ke[l.scale];if(null==o.min)return void(l._show&&(t=!1,l._show=!1,gn(!1)));l._show||(t=!1,l._show=!0,gn(!1));let i=l.side,r=i%2,{min:s,max:u}=o,[a,c]=function(e,t,l,n){let o,i=xe[e];if(n<=0)o=[0,0];else{let r=i._space=i.space(w,e,t,l,n);o=Bl(t,l,i._incrs=i.incrs(w,e,t,l,n,r),n,r)}return i._found=o}(n,s,u,0==r?Ht:It);if(0==c)return;let f=2==o.distr,d=l._splits=l.splits(w,n,s,u,a,c,f),h=2==o.distr?d.map((e=>en[e])):d,p=2==o.distr?en[d[1]]-en[d[0]]:a,m=l._values=l.values(w,l.filter(w,h,n,c,p),n,c,p);l._rotate=2==i?l.rotate(w,m,n,c):0;let g=l._size;l._size=ie(l.size(w,m,n,e)),null!=g&&l._size!=g&&(t=!1)})),t}function mn(e){let t=!0;return _l.forEach(((l,n)=>{let o=l(w,n,yl,e);o!=Ml[n]&&(t=!1),Ml[n]=o})),t}function gn(e){ae.forEach(((t,l)=>{l>0&&(t._paths=null,e&&(1==y?(t.min=null,t.max=null):t.facets.forEach((e=>{e.min=null,e.max=null}))))}))}w.setData=ln;let xn,wn,vn,bn,yn,kn,_n,Mn,Sn,En,Tn,zn,Pn=!1;function Dn(){Pn||(Ne(An),Pn=!0)}function An(){qt&&(function(){let e=je(ke,Re);for(let t in e){let l=e[t],n=Ze[t];if(null!=n&&null!=n.min)Le(l,n),t==Pe&&gn(!0);else if(t!=Pe||2==y)if(0==Sl&&null==l.from){let e=l.range(w,null,null,t);l.min=e[0],l.max=e[1]}else l.min=he,l.max=-he}if(Sl>0){ae.forEach(((t,l)=>{if(1==y){let o=t.scale,i=e[o],r=Ze[o];if(0==l){let e=i.range(w,i.min,i.max,o);i.min=e[0],i.max=e[1],El=N(i.min,n[0]),Tl=N(i.max,n[0]),Tl-El>1&&(n[0][El]i.max&&Tl--),t.min=en[El],t.max=en[Tl]}else t.show&&t.auto&&sn(i,r,t,n[l],t.sorted);t.idxs[0]=El,t.idxs[1]=Tl}else if(l>0&&t.show&&t.auto){let[o,i]=t.facets,r=o.scale,s=i.scale,[u,a]=n[l];sn(e[r],Ze[r],o,u,o.sorted),sn(e[s],Ze[s],i,a,i.sorted),t.min=i.min,t.max=i.max}}));for(let t in e){let l=e[t],n=Ze[t];if(null==l.from&&(null==n||null==n.min)){let e=l.range(w,l.min==he?null:l.min,l.max==-he?null:l.max,t);l.min=e[0],l.max=e[1]}}}for(let t in e){let l=e[t];if(null!=l.from){let n=e[l.from];if(null==n.min)l.min=l.max=null;else{let e=l.range(w,n.min,n.max,t);l.min=e[0],l.max=e[1]}}}let t={},l=!1;for(let n in e){let o=e[n],i=ke[n];if(i.min!=o.min||i.max!=o.max){i.min=o.min,i.max=o.max;let e=i.distr;i._min=3==e?ce(i.min):4==e?de(i.min,i.asinh):i.min,i._max=3==e?ce(i.max):4==e?de(i.max,i.asinh):i.max,t[n]=l=!0}}if(l){ae.forEach(((e,l)=>{2==y?l>0&&t.y&&(e._paths=null):t[e.scale]&&(e._paths=null)}));for(let e in t)el=!0,xo("setScale",e);hl.show&&hl.left>=0&&(rl=al=!0)}for(let e in Ze)Ze[e]=null}(),qt=!1),el&&(function(){let e=!1,t=0;for(;!e;){t++;let l=pn(t),n=mn(t);e=3==t||l&&n,e||(dl(w.width,w.height),Qt=!0)}}(),el=!1),Qt&&(P(q,u,Yt),P(q,r,Rt),P(q,o,Ht),P(q,i,It),P(X,u,Yt),P(X,r,Rt),P(X,o,Ht),P(X,i,It),P(Z,o,Ct),P(Z,i,Wt),j.width=oe(Ct*S),j.height=oe(Wt*S),xe.forEach((({_el:t,_show:l,_size:n,_pos:o,side:i})=>{if(null!=t)if(l){let l=i%2==1;P(t,l?"left":"top",o-(3===i||0===i?n:0)),P(t,l?"width":"height",n),P(t,l?"top":"left",l?Rt:Yt),P(t,l?"height":"width",l?It:Ht),z(t,e)}else T(t,e)})),Pl=Dl=Al=ql=Jl=Kl=Xl=$l=Wl=null,Ql=1,to(!0),xo("setSize"),Qt=!1),Ct>0&&Wt>0&&(G.clearRect(0,0,j.width,j.height),xo("drawClear"),Oe.forEach((e=>e())),xo("draw")),Rn.show&&ul&&(jn(Rn),ul=!1),hl.show&&rl&&(Qn(null,!0,!1),rl=!1),tt.show&&tt.live&&al&&(Xn(),al=!1),Y||(Y=!0,w.status=1,xo("ready")),tn=!1,Pn=!1}function Cn(e,t){let l=ke[e];if(null==l.from){if(0==Sl){let n=l.range(w,t.min,t.max,e);t.min=n[0],t.max=n[1]}if(t.min>t.max){let e=t.min;t.min=t.max,t.max=e}if(Sl>1&&null!=t.min&&null!=t.max&&t.max-t.min<1e-16)return;e==Pe&&2==l.distr&&Sl>0&&(t.min=N(t.min,n[0]),t.max=N(t.max,n[0]),t.min==t.max&&t.max++),Ze[e]=t,qt=!0,Dn()}}w.redraw=(e,t)=>{el=t||!1,!1!==e?Ln(Pe,Ge.min,Ge.max):Dn()},w.setScale=Cn;let Wn=!1;const Hn=hl.drag;let In=Hn.x,Yn=Hn.y;hl.show&&(hl.x&&(xn=A("u-cursor-x",X)),hl.y&&(wn=A("u-cursor-y",X)),0==Ge.ori?(vn=xn,bn=wn):(vn=wn,bn=xn),Tn=hl.left,zn=hl.top);const Rn=w.select=Le({show:!0,over:!0,left:0,width:0,top:0,height:0},l.select),On=Rn.show?A("u-select",Rn.over?X:q):null;function jn(e,t){if(Rn.show){for(let t in e)Rn[t]=e[t],t in oo&&P(On,t,e[t]);!1!==t&&xo("setSelect")}}function Ln(e,t,l){Cn(e,{min:t,max:l})}function Fn(t,l,n,o){null!=l.focus&&function(e){if(e!=Un){let t=null==e,l=1!=xl.alpha;ae.forEach(((n,o)=>{let i=t||0==o||o==e;n._focus=t?null:i,l&&function(e,t){ae[e].alpha=t,hl.show&&vl[e]&&(vl[e].style.opacity=t),lt&&ct[e]&&(ct[e].style.opacity=t)}(o,i?1:xl.alpha)})),Un=e,l&&Dn()}}(t),null!=l.show&&ae.forEach(((n,o)=>{o>0&&(t==o||null==t)&&(n.show=l.show,function(t,l){let n=ae[t],o=lt?ct[t]:null;n.show?o&&z(o,e):(o&&T(o,e),vl.length>1&&W(vl[t],-10,-10,Ht,It))}(o,l.show),Ln(2==y?n.facets[1].scale:n.scale,null,null),Dn())})),!1!==n&&xo("setSeries",t,l),o&&ko("setSeries",w,t,l)}let Nn,Gn,Un;w.setSelect=jn,w.setSeries=Fn,w.addBand=function(e,t){e.fill=ge(e.fill||null),e.dir=K(e.dir,-1),t=null==t?Se.length:t,Se.splice(t,0,e)},w.setBand=function(e,t){Le(Se[e],t)},w.delBand=function(e){null==e?Se.length=0:Se.splice(e,1)};const Bn={focus:!0};function Vn(e,t,l){let n=ke[t];l&&(e=e/S-(1==n.ori?Rt:Yt));let o=Ht;1==n.ori&&(o=It,e=o-e),-1==n.dir&&(e=o-e);let i=n._min,r=i+(n._max-i)*(e/o),s=n.distr;return 3==s?ue(10,r):4==s?((e,t=1)=>ee.sinh(e)*t)(r,n.asinh):r}function Zn(e,t){P(On,u,Rn.left=e),P(On,o,Rn.width=t)}function qn(e,t){P(On,r,Rn.top=e),P(On,i,Rn.height=t)}lt&&wl&&Pt(g,rt,(e=>{hl._lock||(ml(e),null!=Un&&Fn(null,Bn,!0,vo.setSeries))})),w.valToIdx=e=>N(e,n[0]),w.posToIdx=function(e,t){return N(Vn(e,Pe,t),n[0],El,Tl)},w.posToVal=Vn,w.valToPos=(e,t,l)=>0==ke[t].ori?E(e,ke[t],l?Vt:Ht,l?Ut:0):C(e,ke[t],l?Zt:It,l?Bt:0),w.batch=function(e){e(w),Dn()},w.setCursor=(e,t,l)=>{Tn=e.left,zn=e.top,Qn(null,t,l)};let Jn=0==Ge.ori?Zn:qn,Kn=1==Ge.ori?Zn:qn;function Xn(e,t){null!=e&&(e.idxs?e.idxs.forEach(((e,t)=>{et[t]=e})):void 0!==e.idx&&et.fill(e.idx),tt.idx=et[0]);for(let e=0;e0||1==y&&!dt)&&$n(e,et[e]);lt&&tt.live&&function(){if(lt&&tt.live)for(let e=2==y?1:0;eTl;Nn=he;let r=0==Ge.ori?Ht:It,s=1==Ge.ori?Ht:It;if(Tn<0||0==Sl||i){o=null;for(let e=0;e0&&vl.length>1&&W(vl[e],-10,-10,Ht,It);wl&&Fn(null,Bn,!0,null==e&&vo.setSeries),tt.live&&(et.fill(o),al=!0)}else{let e,t,l;1==y&&(e=0==Ge.ori?Tn:zn,t=Vn(e,Pe),o=N(t,n[0],El,Tl),l=Be(n[0][o],Ge,r,0));for(let e=2==y?1:0;e0&&i.show){let t,l,n=null==f?-10:Me(Ve(f,1==y?ke[i.scale]:ke[i.facets[1].scale],s,0),1);if(wl&&n>=0&&1==y){let t=le(n-zn);if(t=0?1:-1;o==(f>=0?1:-1)&&(1==o?1==l?f>=n:f<=n:1==l?f<=n:f>=n)&&(Nn=t,Gn=e)}else Nn=t,Gn=e}}if(0==Ge.ori?(t=d,l=n):(t=n,l=d),al&&vl.length>1){I(vl[e],hl.points.fill(w,e),hl.points.stroke(w,e));let n,o,i,r,s=!0,u=hl.points.bbox;if(null!=u){s=!1;let t=u(w,e);i=t.left,r=t.top,n=t.width,o=t.height}else i=t,r=l,n=o=hl.points.size(w,e);R(vl[e],n,o,s),W(vl[e],i,r,Ht,It)}}}}if(hl.idx=o,hl.left=Tn,hl.top=zn,al&&(tt.idx=o,Xn()),Rn.show&&Wn)if(null!=e){let[t,l]=vo.scales,[n,o]=vo.match,[i,u]=e.cursor.sync.scales,a=e.cursor.drag;if(In=a._x,Yn=a._y,In||Yn){let a,c,f,d,h,{left:p,top:m,width:g,height:x}=e.select,w=e.scales[t].ori,v=e.posToVal,b=null!=t&&n(t,i),y=null!=l&&o(l,u);b&&In?(0==w?(a=p,c=g):(a=m,c=x),f=ke[t],d=Be(v(a,i),f,r,0),h=Be(v(a+c,i),f,r,0),Jn(re(d,h),le(h-d))):Jn(0,r),y&&Yn?(1==w?(a=p,c=g):(a=m,c=x),f=ke[l],d=Ve(v(a,u),f,s,0),h=Ve(v(a+c,u),f,s,0),Kn(re(d,h),le(h-d))):Kn(0,s)}else io()}else{let e=le(Sn-yn),t=le(En-kn);if(1==Ge.ori){let l=e;e=t,t=l}In=Hn.x&&e>=Hn.dist,Yn=Hn.y&&t>=Hn.dist;let l,n,o=Hn.uni;null!=o?In&&Yn&&(In=e>=o,Yn=t>=o,In||Yn||(t>e?Yn=!0:In=!0)):Hn.x&&Hn.y&&(In||Yn)&&(In=Yn=!0),In&&(0==Ge.ori?(l=_n,n=Tn):(l=Mn,n=zn),Jn(re(l,n),le(n-l)),Yn||Kn(0,s)),Yn&&(1==Ge.ori?(l=_n,n=Tn):(l=Mn,n=zn),Kn(re(l,n),le(n-l)),In||Jn(0,r)),In||Yn||(Jn(0,0),Kn(0,0))}if(Hn._x=In,Hn._y=Yn,null==e){if(l){if(null!=bo){let[e,t]=vo.scales;vo.values[0]=null!=e?Vn(0==Ge.ori?Tn:zn,e):null,vo.values[1]=null!=t?Vn(1==Ge.ori?Tn:zn,t):null}ko(d,w,Tn,zn,Ht,It,o)}if(wl){let e=l&&vo.setSeries,t=xl.prox;null==Un?Nn<=t&&Fn(Gn,Bn,!0,e):Nn>t?Fn(null,Bn,!0,e):Gn!=Un&&Fn(Gn,Bn,!0,e)}}!1!==t&&xo("setCursor")}w.setLegend=Xn;let eo=null;function to(e=!1){e?eo=null:(eo=X.getBoundingClientRect(),xo("syncRect",eo))}function lo(e,t,l,n,o,i,r){hl._lock||Wn&&null!=e&&0==e.movementX&&0==e.movementY||(no(e,t,l,n,o,i,0,!1,null!=e),null!=e?Qn(null,!0,!0):Qn(t,!0,!1))}function no(e,t,l,n,o,i,r,s,u){if(null==eo&&to(!1),ml(e),null!=e)l=e.clientX-eo.left,n=e.clientY-eo.top;else{if(l<0||n<0)return Tn=-10,void(zn=-10);let[e,r]=vo.scales,s=t.cursor.sync,[u,a]=s.values,[c,f]=s.scales,[d,h]=vo.match,p=t.axes[0].side%2==1,m=0==Ge.ori?Ht:It,g=1==Ge.ori?Ht:It,x=p?i:o,w=p?o:i,v=p?n:l,b=p?l:n;if(l=null!=c?d(e,c)?H(u,ke[e],m,0):-10:m*(v/x),n=null!=f?h(r,f)?H(a,ke[r],g,0):-10:g*(b/w),1==Ge.ori){let e=l;l=n,n=e}}u&&((l<=1||l>=Ht-1)&&(l=_e(l,Ht)),(n<=1||n>=It-1)&&(n=_e(n,It))),s?(yn=l,kn=n,[_n,Mn]=hl.move(w,l,n)):(Tn=l,zn=n)}Object.defineProperty(w,"rect",{get:()=>(null==eo&&to(!1),eo)});const oo={width:0,height:0,left:0,top:0};function io(){jn(oo,!1)}let ro,so,uo,ao;function co(e,t,l,n,o,i,r){Wn=!0,In=Yn=Hn._x=Hn._y=!1,no(e,t,l,n,o,i,0,!0,!1),null!=e&&(Pt(p,k,fo,!1),ko(h,w,_n,Mn,Ht,It,null));let{left:s,top:u,width:a,height:c}=Rn;ro=s,so=u,uo=a,ao=c,io()}function fo(e,t,l,n,o,i,r){Wn=Hn._x=Hn._y=!1,no(e,t,l,n,o,i,0,!1,!0);let{left:s,top:u,width:a,height:c}=Rn,f=a>0||c>0,d=ro!=s||so!=u||uo!=a||ao!=c;if(f&&d&&jn(Rn),Hn.setScale&&f&&d){let e=s,t=a,l=u,n=c;if(1==Ge.ori&&(e=u,t=c,l=s,n=a),In&&Ln(Pe,Vn(e,Pe),Vn(e+t,Pe)),Yn)for(let e in ke){let t=ke[e];e!=Pe&&null==t.from&&t.min!=he&&Ln(e,Vn(l+n,e),Vn(l,e))}io()}else hl.lock&&(hl._lock=!hl._lock,hl._lock||Qn(null,!0,!1));null!=e&&(Dt(p,k),ko(p,w,Tn,zn,Ht,It,null))}function ho(e,t,l,n,o,i,r){hl._lock||(ml(e),nn(),io(),null!=e&&ko(x,w,Tn,zn,Ht,It,null))}function po(){xe.forEach(Zl),fl(w.width,w.height,!0)}L(v,_,po);const mo={};mo.mousedown=co,mo.mousemove=lo,mo.mouseup=fo,mo.dblclick=ho,mo.setSeries=(e,t,l,n)=>{-1!=(l=(0,vo.match[2])(w,t,l))&&Fn(l,n,!0,!1)},hl.show&&(Pt(h,X,co),Pt(d,X,lo),Pt(m,X,(e=>{ml(e),to(!1)})),Pt(g,X,(function(e,t,l,n,o,i,r){if(hl._lock)return;ml(e);let s=Wn;if(Wn){let e,t,l=!0,n=!0,o=10;0==Ge.ori?(e=In,t=Yn):(e=Yn,t=In),e&&t&&(l=Tn<=o||Tn>=Ht-o,n=zn<=o||zn>=It-o),e&&l&&(Tn=Tn<_n?0:Ht),t&&n&&(zn=zn{e.call(null,w,t,l)}))}(l.plugins||[]).forEach((e=>{for(let t in e.hooks)go[t]=(go[t]||[]).concat(e.hooks[t])}));const wo=(e,t,l)=>l,vo=Le({key:null,setSeries:!1,filters:{pub:be,sub:be},scales:[Pe,ae[1]?ae[1].scale:null],match:[ye,ye,wo],values:[null,null]},hl.sync);2==vo.match.length&&vo.match.push(wo),hl.sync=vo;const bo=vo.key,yo=sl(bo);function ko(e,t,l,n,o,i,r){vo.filters.pub(e,t,l,n,o,i,r)&&yo.pub(e,t,l,n,o,i,r)}function _o(){xo("init",l,n),ln(n||l.data,!1),Ze[Pe]?Cn(Pe,Ze[Pe]):nn(),ul=Rn.show,rl=al=!0,fl(l.width,l.height)}return yo.sub(w),w.pub=function(e,t,l,n,o,i,r){vo.filters.sub(e,t,l,n,o,i,r)&&mo[e](null,t,l,n,o,i,r)},w.destroy=function(){yo.unsub(w),Cl.delete(w),zt.clear(),F(v,_,po),O.remove(),rt?.remove(),xo("destroy")},ae.forEach(bl),xe.forEach((function(e,t){if(e._show=e.show,e.show){let l=e.side%2,n=ke[e.scale];null==n&&(e.scale=l?ae[1].scale:Pe,n=ke[e.scale]);let o=n.time;e.size=ge(e.size),e.space=ge(e.space),e.rotate=ge(e.rotate),We(e.incrs)&&e.incrs.forEach((e=>{!Te.has(e)&&Te.set(e,ze(e))})),e.incrs=ge(e.incrs||(2==n.distr?nt:o?1==ne?gt:vt:ot)),e.splits=ge(e.splits||(o&&1==n.distr?Ke:3==n.distr?Nt:4==n.distr?Gt:Ft)),e.stroke=ge(e.stroke),e.grid.stroke=ge(e.grid.stroke),e.ticks.stroke=ge(e.ticks.stroke),e.border.stroke=ge(e.border.stroke);let i=e.values;e.values=We(i)&&!We(i[0])?ge(i):o?We(i)?_t(qe,kt(i,Je)):Ie(i)?function(e,t){let l=Xe(t);return(t,n,o,i,r)=>n.map((t=>l(e(t))))}(qe,i):i||$e:i||Lt,e.filter=ge(e.filter||(n.distr>=3&&10==n.log?Jt:3==n.distr&&2==n.log?Kt:we)),e.font=Vl(e.font),e.labelFont=Vl(e.labelFont),e._size=e.size(w,null,t,0),e._space=e._rotate=e._incrs=e._found=e._splits=e._values=null,e._size>0&&(yl[t]=!0,e._el=A("u-axis",Z))}})),c?c instanceof HTMLElement?(c.appendChild(O),_o()):c(w,_o):_o(),w}ql.assign=Le,ql.fmtNum=Q,ql.rangeNum=J,ql.rangeLog=U,ql.rangeAsinh=B,ql.orient=ul,ql.pxRatio=S,ql.join=function(e,t){if(function(e){let t=e[0][0],l=t.length;for(let n=1;n=n&&null==e[o];)o--;if(o<=n)return!0;const i=se(1,ne((o-n+1)/t));for(let t=e[n],l=n+i;l<=o;l+=i){const n=e[l];if(null!=n){if(n<=t)return!1;t=n}}return!0}(t[0])||(t=function(e){let t=e[0],l=t.length,n=Array(l);for(let e=0;et[e]-t[l]));let o=[];for(let t=0;te-t))],o=n[0].length,i=new Map;for(let e=0;eul(e,i,((u,a,c,f,d,h,p,m,g,x,w)=>{let v=u.pxRound,{left:b,width:y}=e.bbox,k=e=>v(h(e,f,x,m)),_=e=>v(p(e,d,w,g)),M=0==f.ori?wl:vl;const E={stroke:new Path2D,fill:null,clip:null,band:null,gaps:null,flags:1},T=E.stroke,z=f.dir*(0==f.ori?1:-1);r=G(c,r,s,1),s=G(c,r,s,-1);let P=_(c[1==z?r:s]),D=k(a[1==z?r:s]),A=D,C=D;o&&-1==t&&(C=b,M(T,C,P)),M(T,D,P);for(let e=1==z?r:s;e>=r&&e<=s;e+=z){let l=c[e];if(null==l)continue;let n=k(a[e]),o=_(l);1==t?M(T,n,P):M(T,A,o),M(T,n,o),P=o,A=n}let W=A;o&&1==t&&(W=b+y,M(T,W,P));let[H,I]=al(e,i);if(null!=u.fill||0!=H){let t=E.fill=new Path2D(T),l=_(u.fillTo(e,i,u.min,u.max,H));M(t,W,l),M(t,C,l)}if(!u.spanGaps){let o=[];o.push(...hl(a,c,r,s,z,k,n));let d=u.width*S/2,h=l||1==t?d:-d,p=l||-1==t?-d:d;o.forEach((e=>{e[0]+=h,e[1]+=p})),E.gaps=o=u.gaps(e,i,r,s,o),E.clip=dl(o,f.ori,m,g,x,w)}return 0!=I&&(E.band=2==I?[fl(e,i,r,s,T,-1),fl(e,i,r,s,T,1)]:fl(e,i,r,s,T,I)),E}))},e.bars=function(e){const t=K((e=e||De).size,[.6,he,1]),l=e.align||0,n=(e.gap||0)*S;let o=e.radius;o=null==o?[0,0]:"number"==typeof o?[o,0]:o;const i=ge(o),r=1-t[0],s=K(t[1],he)*S,u=K(t[2],1)*S,a=K(e.disp,De),c=K(e.each,(e=>{})),{fill:f,stroke:d}=a;return(e,t,o,h)=>ul(e,t,((p,m,g,x,w,v,b,y,k,_,M)=>{let E,T,z=p.pxRound;0==x.ori?[E,T]=i(e,t):[T,E]=i(e,t);const P=x.dir*(0==x.ori?1:-1),D=w.dir*(1==w.ori?1:-1);let A,C,W=0==x.ori?bl:yl,H=0==x.ori?c:(e,t,l,n,o,i,r)=>{c(e,t,l,o,n,r,i)},[I,Y]=al(e,t),R=3==w.distr?1==I?w.max:w.min:0,O=b(R,w,M,k),j=z(p.width*S),L=!1,F=null,N=null,G=null,U=null;null==f||0!=j&&null==d||(L=!0,F=f.values(e,t,o,h),N=new Map,new Set(F).forEach((e=>{null!=e&&N.set(e,new Path2D)})),j>0&&(G=d.values(e,t,o,h),U=new Map,new Set(G).forEach((e=>{null!=e&&U.set(e,new Path2D)}))));let{x0:B,size:V}=a,Z=!0;if(null!=B&&null!=V){m=B.values(e,t,o,h),2==B.unit&&(m=m.map((t=>e.posToVal(y+t*_,x.key,!0))));let l=V.values(e,t,o,h);C=2==V.unit?l[0]*_:v(l[0],x,_,y)-v(0,x,_,y),j>=C&&(j=0),C=z(me(C-j,u,s)),A=1==P?-j/2:C+j/2}else{let e=_;if(m.length>1){let t=null;for(let l=0,n=1/0;l=C&&(j=0),t+n<5&&(z=xe),C=z(me(e-t,u,s)-j-n),A=(0==l?C/2:l==P?0:C)-l*P*n/2,C+j>e&&(Z=!1)}const q={stroke:null,fill:null,clip:null,band:null,gaps:null,flags:3};let J;0!=Y&&(q.band=new Path2D,J=z(b(1==Y?w.max:w.min,w,M,k)));const X=L?null:new Path2D,$=q.band;let{y0:Q,y1:ee}=a,te=null;null!=Q&&null!=ee&&(g=ee.values(e,t,o,h),te=Q.values(e,t,o,h));let oe=E*C,ie=T*C;for(let l=1==P?o:h;l>=o&&l<=h;l+=P){let n=g[l];if(void 0===n)continue;let o=v(2!=x.distr||null!=a?m[l]:l,x,_,y),i=b(K(n,R),w,M,k);null!=te&&null!=n&&(O=b(te[l],w,M,k));let r=z(o-A),s=z(se(i,O)),u=z(re(i,O)),c=s-u;if(null!=n){let o=n<0?ie:oe,i=n<0?oe:ie;L?(j>0&&null!=G[l]&&W(U.get(G[l]),r,u+ne(j/2),C,se(0,c-j),o,i),null!=F[l]&&W(N.get(F[l]),r,u+ne(j/2),C,se(0,c-j),o,i)):W(X,r,u+ne(j/2),C,se(0,c-j),o,i),H(e,t,l,r-j/2,u,C+j,c)}0==Y||null==n&&!Z||(D*Y==1?(s=u,u=J):(u=s,s=J),c=s-u,W($,r-j/2,u,C+j,se(0,c),0,0))}return j>0&&(q.stroke=L?U:X),q.fill=L?N:X,q}))},e.spline=function(e){return function(e,t){const l=K(t?.alignGaps,0);return(t,n,o,i)=>ul(t,n,((r,s,u,a,c,f,d,h,p,m,g)=>{let x,w,v,b=r.pxRound,y=e=>b(f(e,a,m,h)),k=e=>b(d(e,c,g,p));0==a.ori?(x=gl,v=wl,w=Ml):(x=xl,v=vl,w=Sl);const _=a.dir*(0==a.ori?1:-1);o=G(u,o,i,1),i=G(u,o,i,-1);let M=y(s[1==_?o:i]),S=M,E=[],T=[];for(let e=1==_?o:i;e>=o&&e<=i;e+=_)if(null!=u[e]){let t=y(s[e]);E.push(S=t),T.push(k(u[e]))}const z={stroke:e(E,T,x,v,w,b),fill:null,clip:null,band:null,gaps:null,flags:1},P=z.stroke;let[D,A]=al(t,n);if(null!=r.fill||0!=D){let e=z.fill=new Path2D(P),l=k(r.fillTo(t,n,r.min,r.max,D));v(e,S,l),v(e,M,l)}if(!r.spanGaps){let e=[];e.push(...hl(s,u,o,i,_,y,l)),z.gaps=e=r.gaps(t,n,o,i,e),z.clip=dl(e,a.ori,h,p,m,g)}return 0!=A&&(z.band=2==A?[fl(t,n,o,i,P,-1),fl(t,n,o,i,P,1)]:fl(t,n,o,i,P,A)),z}))}(Al,e)}}var Jl=l(379),Kl=l.n(Jl),Xl=l(795),$l=l.n(Xl),Ql=l(569),en=l.n(Ql),tn=l(565),ln=l.n(tn),nn=l(216),on=l.n(nn),rn=l(589),sn=l.n(rn),un=l(350),an={};function cn(e){var t,l=HTMLWidgets.find("#"+e);return void 0!==l&&(t=l.getWidget()),t}function fn(e,t){let l=[],n=[],o=e[0].length,i=Array(o);for(let e=0;ei[t]+=+e)));for(let l=1;ln>l&&!t(n))),l]});return n=n.filter((e=>e.series[1]>-1)),{data:[e[0]].concat(l),bands:n}}an.styleTagTransform=sn(),an.setAttributes=ln(),an.insert=en().bind(null,"head"),an.domAPI=$l(),an.insertStyleElement=on(),Kl()(un.Z,an),un.Z&&un.Z.locals&&un.Z.locals;const dn=e=>(t,l)=>{new ResizeObserver((e=>{for(let l of e){let e=l.contentRect.height,n=l.contentRect.width;const o=t.root.querySelectorAll(".u-legend, .u-title");for(let t of o)e-=Math.floor(t.offsetHeight);t.setSize({width:n,height:e})}})).observe(e),e.appendChild(t.root),l()},hn=(e,t,l,n)=>{const o=5*devicePixelRatio;return ql.orient(e,t,((l,n,i,r,s,u,a,c,f,d,h,p,m,g,x)=>{let w=e.data[t];e.ctx.fillStyle=l.stroke();let v=2*Math.PI;console.time("points");let b=new Path2D;for(let e=0;e=r.min&&t<=r.max&&l>=s.min&&l<=s.max){let e=u(t,r,d,c),n=a(l,s,h,f);b.moveTo(e+o/2,n),x(b,e,n,o/2,0,v)}}console.timeEnd("points"),e.ctx.fill(b)})),null};HTMLWidgets.widget({name:"uPlot",type:"output",factory:function(e,t,l){var n,o,i;return{renderValue:function(r){void 0!==n&&n.destroy(),(o=r.options).width=t,o.height=l,i=r.data,r.stacked?(o.hooks||(o.hooks={}),o.hooks.init=[e=>{[...e.root.querySelectorAll(".u-legend .u-series")].forEach(((t,l)=>{e.series[l]._hide&&(t.style.display="none")}))}],n=function(e,t,l,n,o,i,r,s){let{opts:u,data:a}=function(e,t,l,n){let o=function(e,t){return{scales:{x:{time:!0}},series:t}}(0,t),i=fn(n?n(l):l,(e=>!1));return o.bands=i.bands,o.cursor=o.cursor||{},o.cursor.dataIdx=(e,t,n,o)=>null===l[t][n]?null:n,o.series.forEach((e=>{e.value=(e,t,n,o)=>l[n][o],e.points=e.points||{},e.points.filter=(e,t,n,o)=>{if(n){let e=[];return l[t].forEach(((t,l)=>{null!==t&&e.push(l)})),e}}})),o.scales.y={range:(e,t,l)=>{let n=uPlot.rangeNum(t,l,.1,!0);return[n[0],n[1]]}},o.hooks={setSeries:[(e,t)=>{let n=fn(l,(t=>!e.series[t].show));e.delBand(null),n.bands.forEach((t=>e.addBand(t))),e.setData(n.data)}]},{opts:o,data:i.data}}(0,t,l,n);return u.title=e,u.width=o,u.height=i,u.hooks=Object.assign(u.hooks,r),console.log(u),new uPlot(u,a,s)}(o.title,o.series,i,null,t,l,o.hooks,dn(e))):n=new ql(o,i,dn(e))},getWidget:function(){return n},resize:function(e,t){}}}}),HTMLWidgets.shinyMode&&(Shiny.addCustomMessageHandler("uplot-api",(function(e){var t=cn(e.id);void 0!==t&&t[e.name].apply(null,e.args)})),Shiny.addCustomMessageHandler("uplot-setData",(function(e){var t=cn(e.id);void 0!==t&&t.setData(e.data)})))})();var o=window;for(var i in n)o[i]=n[i];n.__esModule&&Object.defineProperty(o,"__esModule",{value:!0})})(); \ No newline at end of file diff --git a/man/uPlot.Rd b/man/uPlot.Rd index 0cda700..e307e60 100644 --- a/man/uPlot.Rd +++ b/man/uPlot.Rd @@ -4,7 +4,14 @@ \alias{uPlot} \title{uPlot} \usage{ -uPlot(data, options, ..., width = NULL, height = NULL, elementId = NULL) +uPlot( + data, + options = list(), + ..., + width = NULL, + height = NULL, + elementId = NULL +) } \arguments{ \item{data}{Data to plot as a \code{list} (must match \code{µPlot.js} expectations) or diff --git a/package-lock.json b/package-lock.json index d07e0b5..79e9465 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "css-loader": "^6.7.1", "style-loader": "^3.3.1", - "uplot": "^1.6.22", + "uplot": "^1.6.26", "webpack": "^5.73.0", "webpack-cli": "^4.10.0", "webpack-merge": "^5.8.0" @@ -1370,9 +1370,9 @@ } }, "node_modules/uplot": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/uplot/-/uplot-1.6.22.tgz", - "integrity": "sha512-2jtSb/YHUgtmIUn0+QJjf7ggcJicb5PKe7ijBiRDTPsG/f8F/MFayZ+g6/0kATNkDyF/qQsHJDmCp6cxncg1EQ==", + "version": "1.6.26", + "resolved": "https://registry.npmjs.org/uplot/-/uplot-1.6.26.tgz", + "integrity": "sha512-qN0mveL6UsP40TnHzHAJkUQvpfA3y8zSLXtXKVlJo/sLfj2+vjan/Z3g81MCZjy/hEDUFNtnLftPmETDA4s7Rg==", "dev": true }, "node_modules/uri-js": { @@ -2543,9 +2543,9 @@ } }, "uplot": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/uplot/-/uplot-1.6.22.tgz", - "integrity": "sha512-2jtSb/YHUgtmIUn0+QJjf7ggcJicb5PKe7ijBiRDTPsG/f8F/MFayZ+g6/0kATNkDyF/qQsHJDmCp6cxncg1EQ==", + "version": "1.6.26", + "resolved": "https://registry.npmjs.org/uplot/-/uplot-1.6.26.tgz", + "integrity": "sha512-qN0mveL6UsP40TnHzHAJkUQvpfA3y8zSLXtXKVlJo/sLfj2+vjan/Z3g81MCZjy/hEDUFNtnLftPmETDA4s7Rg==", "dev": true }, "uri-js": { diff --git a/package.json b/package.json index c81627a..7b594ed 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "devDependencies": { "css-loader": "^6.7.1", "style-loader": "^3.3.1", - "uplot": "^1.6.22", + "uplot": "^1.6.26", "webpack": "^5.73.0", "webpack-cli": "^4.10.0", "webpack-merge": "^5.8.0"